On Fri, 4 Dec 2020, Ahmed S. Darwish wrote:

> NCR5380_poll_politely2() uses in_interrupt() and irqs_disabled() to
> check if it is safe to sleep.
> 
> Such usage in drivers is phased out and Linus clearly requested that
> code which changes behaviour depending on context should either be
> separated, or the context be explicitly conveyed in an argument passed
> by the caller.
> 
> Below is a context analysis of NCR5380_poll_politely2() uppermost
> callers:
> 
>   - NCR5380_maybe_reset_bus(), task, invoked during device probe.
>     -> NCR5380_poll_politely()
>     -> do_abort()
> 
>   - NCR5380_select(), task, but can only sleep in the "release, then
>     re-acquire" regions of the spinlock held by its caller.
>     Sleeping invocations (lock released):
>     -> NCR5380_poll_politely2()
> 
>     Atomic invocations (lock acquired):
>     -> NCR5380_reselect()
>        -> NCR5380_poll_politely()
>        -> do_abort()
>        -> NCR5380_transfer_pio()
> 
>   - NCR5380_intr(), interrupt handler
>     -> NCR5380_dma_complete()
>        -> NCR5380_transfer_pio()
>         -> NCR5380_poll_politely()
>     -> NCR5380_reselect() (see above)
> 
>   - NCR5380_information_transfer(), task, but can only sleep in the
>     "release, then re-acquire" regions of the caller-held spinlock.
>     Sleeping invocations (lock released):
>       - NCR5380_transfer_pio() -> NCR5380_poll_politely()
>       - NCR5380_poll_politely()
> 
>     Atomic invocations (lock acquired):
>       - NCR5380_transfer_dma()
>       -> NCR5380_dma_recv_setup()
>            => generic_NCR5380_precv() -> NCR5380_poll_politely()
>          => macscsi_pread() -> NCR5380_poll_politely()
> 
>       -> NCR5380_dma_send_setup()
>          => generic_NCR5380_psend -> NCR5380_poll_politely2()
>          => macscsi_pwrite() -> NCR5380_poll_politely()
> 
>       -> NCR5380_poll_politely2()
>         -> NCR5380_dma_complete()
>            -> NCR5380_transfer_pio()
>             -> NCR5380_poll_politely()
>       - NCR5380_transfer_pio() -> NCR5380_poll_politely
> 
>   - NCR5380_reselect(), atomic, always called with hostdata spinlock
>     held.
> 
> Since NCR5380_poll_politely2() already takes a "wait" argument in
> jiffies, use it to determine if the function can sleep. Modify atomic
> callers, which passed an unused wait value in terms of HZ, to pass zero.
> 
> Suggested-by: Finn Thain <fth...@telegraphics.com.au>
> Co-developed-by: Sebastian Andrzej Siewior <bige...@linutronix.de>
> Signed-off-by: Ahmed S. Darwish <a.darw...@linutronix.de>
> Cc: Michael Schmitz <schmitz...@gmail.com>
> Cc: <linux-m...@lists.linux-m68k.org>
> ---
>  drivers/scsi/NCR5380.c   | 77 ++++++++++++++++++++++------------------
>  drivers/scsi/NCR5380.h   |  3 +-
>  drivers/scsi/g_NCR5380.c | 12 +++----
>  drivers/scsi/mac_scsi.c  | 10 +++---
>  4 files changed, 55 insertions(+), 47 deletions(-)
> 
> diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c
> index d654a6cc4162..60200f61592e 100644
> --- a/drivers/scsi/NCR5380.c
> +++ b/drivers/scsi/NCR5380.c
> @@ -132,7 +132,7 @@
>  static unsigned int disconnect_mask = ~0;
>  module_param(disconnect_mask, int, 0444);
>  
> -static int do_abort(struct Scsi_Host *);
> +static int do_abort(struct Scsi_Host *, unsigned int);
>  static void do_reset(struct Scsi_Host *);
>  static void bus_reset_cleanup(struct Scsi_Host *);
>  
> @@ -197,7 +197,7 @@ static inline void set_resid_from_SCp(struct scsi_cmnd 
> *cmd)
>   * @reg2: Second 5380 register to poll
>   * @bit2: Second bitmask to check
>   * @val2: Second expected value
> - * @wait: Time-out in jiffies
> + * @wait: Time-out in jiffies, 0 if sleeping is not allowed
>   *
>   * Polls the chip in a reasonably efficient manner waiting for an
>   * event to occur. After a short quick poll we begin to yield the CPU
> @@ -213,7 +213,7 @@ static int NCR5380_poll_politely2(struct NCR5380_hostdata 
> *hostdata,
>                                    unsigned long wait)
>  {
>       unsigned long n = hostdata->poll_loops;
> -     unsigned long deadline = jiffies + wait;
> +     unsigned long deadline;
>  
>       do {
>               if ((NCR5380_read(reg1) & bit1) == val1)
> @@ -223,10 +223,11 @@ static int NCR5380_poll_politely2(struct 
> NCR5380_hostdata *hostdata,
>               cpu_relax();
>       } while (n--);
>  
> -     if (irqs_disabled() || in_interrupt())
> +     if (!wait)
>               return -ETIMEDOUT;
>  
>       /* Repeatedly sleep for 1 ms until deadline */
> +     deadline = jiffies + wait;
>       while (time_is_after_jiffies(deadline)) {
>               schedule_timeout_uninterruptible(1);
>               if ((NCR5380_read(reg1) & bit1) == val1)

The deadline assignment shouldn't be moved. That's a behavioural change 
and doesn't fit under the stated aim of this patch. Also, it isn't 
actually a desirable change: the argument to this function is the overall 
wait time, not just the sleep limit.

The rest looks ok.

Reply via email to