[PATCH 12/14] scsi: NCR5380: Remove in_interrupt().

Sebastian Andrzej Siewior
2020-11-26T13:30:45Z

From: "Ahmed S. Darwish" <a.darwish@linutronix.de>

NCR5380_poll_politely2() uses in_interrupt() to check if it is safe to
sleep.

The usage of in_interrupt() 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.

If direct callers are purely atomic, or purely task context, change
their specifications accordingly and mark them with "Context: " tags.

For the mixed ones, trickle-down context from upper layers.

Signed-off-by: Ahmed S. Darwish <a.darwish@linutronix.de>
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Cc: Finn Thain <fthain@telegraphics.com.au>
Cc: Michael Schmitz <schmitzmic@gmail.com>
Cc: <linux-m68k@lists.linux-m68k.org>
---
drivers/scsi/NCR5380.c | 115 ++++++++++++++++++++++-----------------
drivers/scsi/NCR5380.h | 9 +--
drivers/scsi/g_NCR5380.c | 26 ++++++---
drivers/scsi/mac_scsi.c | 10 ++--
4 files changed, 93 insertions(+), 67 deletions(-)

diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c
index d597d7493a627..51a80f3330faa 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 *, bool);
static void do_reset(struct Scsi_Host *);
static void bus_reset_cleanup(struct Scsi_Host *);

@@ -198,6 +198,7 @@ static inline void set_resid_from_SCp(struct scsi_cmnd *cmd)
* @bit2: Second bitmask to check
* @val2: Second expected value
* @wait: Time-out in jiffies
+ * @can_sleep: True if the function can sleep
*
* 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
@@ -210,7 +211,7 @@ static inline void set_resid_from_SCp(struct scsi_cmnd *cmd)
static int NCR5380_poll_politely2(struct NCR5380_hostdata *hostdata,
unsigned int reg1, u8 bit1, u8 val1,
unsigned int reg2, u8 bit2, u8 val2,
- unsigned long wait)
+ unsigned long wait, bool can_sleep)
{
unsigned long n = hostdata->poll_loops;
unsigned long deadline = jiffies + wait;
@@ -223,7 +224,7 @@ static int NCR5380_poll_politely2(struct NCR5380_hostdata *hostdata,
cpu_relax();
} while (n--);

- if (irqs_disabled() || in_interrupt())
+ if (!can_sleep)
return -ETIMEDOUT;

/* Repeatedly sleep for 1 ms until deadline */
@@ -467,9 +468,10 @@ static int NCR5380_init(struct Scsi_Host *instance, int flags)
*
* Note that a bus reset will cause the chip to assert IRQ.
*
+ * Context: task, can sleep
+ *
* Returns 0 if successful, otherwise -ENXIO.
*/
-
static int NCR5380_maybe_reset_bus(struct Scsi_Host *instance)
{
struct NCR5380_hostdata *hostdata = shost_priv(instance);
@@ -482,11 +484,11 @@ static int NCR5380_maybe_reset_bus(struct Scsi_Host *instance)
case 5:
shost_printk(KERN_ERR, instance, "SCSI bus busy, waiting up to five seconds\n");
NCR5380_poll_politely(hostdata,
- STATUS_REG, SR_BSY, 0, 5 * HZ);
+ STATUS_REG, SR_BSY, 0, 5 * HZ, true);
break;
case 2:
shost_printk(KERN_ERR, instance, "bus busy, attempting abort\n");
- do_abort(instance);
+ do_abort(instance, true);
break;
case 4:
shost_printk(KERN_ERR, instance, "bus busy, attempting reset\n");
@@ -690,7 +692,6 @@ static void requeue_cmd(struct Scsi_Host *instance, struct scsi_cmnd *cmd)
* NCR5380_queue_command() and NCR5380_intr() will try to start it
* in case it is not running.
*/
-
static void NCR5380_main(struct work_struct *work)
{
struct NCR5380_hostdata *hostdata =
@@ -750,10 +751,9 @@ static void NCR5380_main(struct work_struct *work)
* NCR5380_dma_complete - finish DMA transfer
* @instance: the scsi host instance
*
- * Called by the interrupt handler when DMA finishes or a phase
- * mismatch occurs (which would end the DMA transfer).
+ * Context: atomic. Called by the interrupt handler when DMA finishes
+ * or a phase mismatch occurs (which would end the DMA transfer).
*/
-
static void NCR5380_dma_complete(struct Scsi_Host *instance)
{
struct NCR5380_hostdata *hostdata = shost_priv(instance);
@@ -822,7 +822,7 @@ static void NCR5380_dma_complete(struct Scsi_Host *instance)
if (toPIO > 0) {
dsprintk(NDEBUG_DMA, instance,
"Doing %d byte PIO to 0x%p\n", cnt, *data);
- NCR5380_transfer_pio(instance, &p, &cnt, data);
+ NCR5380_transfer_pio(instance, &p, &cnt, data, false);
*count -= toPIO - cnt;
}
}
@@ -962,8 +962,11 @@ static irqreturn_t __maybe_unused NCR5380_intr(int irq, void *dev_id)
*
* If failed (no target) : cmd->scsi_done() will be called, and the
* cmd->result host byte set to DID_BAD_TARGET.
+ *
+ * Context: task context, with @instance hostdata spinlock held by
+ * caller. That is, this function can sleep in the areas between
+ * releasing and re-acquring that spinlock.
*/
-
static bool NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd)
__releases(&hostdata->lock) __acquires(&hostdata->lock)
{
@@ -1010,8 +1013,10 @@ static bool NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd)

spin_unlock_irq(&hostdata->lock);
err = NCR5380_poll_politely2(hostdata, MODE_REG, MR_ARBITRATE, 0,
- INITIATOR_COMMAND_REG, ICR_ARBITRATION_PROGRESS,
- ICR_ARBITRATION_PROGRESS, HZ);
+ INITIATOR_COMMAND_REG,
+ ICR_ARBITRATION_PROGRESS,
+ ICR_ARBITRATION_PROGRESS,
+ HZ, true);
spin_lock_irq(&hostdata->lock);
if (!(NCR5380_read(MODE_REG) & MR_ARBITRATE)) {
/* Reselection interrupt */
@@ -1136,7 +1141,7 @@ static bool NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd)
*/

err = NCR5380_poll_politely(hostdata, STATUS_REG, SR_BSY, SR_BSY,
- msecs_to_jiffies(250));
+ msecs_to_jiffies(250), true);

if ((NCR5380_read(STATUS_REG) & (SR_SEL | SR_IO)) == (SR_SEL | SR_IO)) {
spin_lock_irq(&hostdata->lock);
@@ -1181,7 +1186,7 @@ static bool NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd)

/* Wait for start of REQ/ACK handshake */

- err = NCR5380_poll_politely(hostdata, STATUS_REG, SR_REQ, SR_REQ, HZ);
+ err = NCR5380_poll_politely(hostdata, STATUS_REG, SR_REQ, SR_REQ, HZ, true);
spin_lock_irq(&hostdata->lock);
if (err < 0) {
shost_printk(KERN_ERR, instance, "select: REQ timeout\n");
@@ -1189,7 +1194,7 @@ static bool NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd)
goto out;
}
if (!hostdata->selecting) {
- do_abort(instance);
+ do_abort(instance, false);
return false;
}

@@ -1200,7 +1205,7 @@ static bool NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd)
len = 1;
data = tmp;
phase = PHASE_MSGOUT;
- NCR5380_transfer_pio(instance, &phase, &len, &data);
+ NCR5380_transfer_pio(instance, &phase, &len, &data, false);
if (len) {
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
cmd->result = DID_ERROR << 16;
@@ -1238,7 +1243,8 @@ static bool NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd)
*
* Inputs : instance - instance of driver, *phase - pointer to
* what phase is expected, *count - pointer to number of
- * bytes to transfer, **data - pointer to data pointer.
+ * bytes to transfer, **data - pointer to data pointer,
+ * can_sleep - whether it is safe to sleep.
*
* Returns : -1 when different phase is entered without transferring
* maximum number of bytes, 0 if all bytes are transferred or exit
@@ -1257,7 +1263,7 @@ static bool NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd)

static int NCR5380_transfer_pio(struct Scsi_Host *instance,
unsigned char *phase, int *count,
- unsigned char **data)
+ unsigned char **data, bool can_sleep)
{
struct NCR5380_hostdata *hostdata = shost_priv(instance);
unsigned char p = *phase, tmp;
@@ -1278,7 +1284,8 @@ static int NCR5380_transfer_pio(struct Scsi_Host *instance,
* valid
*/

- if (NCR5380_poll_politely(hostdata, STATUS_REG, SR_REQ, SR_REQ, HZ) < 0)
+ if (NCR5380_poll_politely(hostdata, STATUS_REG, SR_REQ, SR_REQ,
+ HZ, can_sleep) < 0)
break;

dsprintk(NDEBUG_HANDSHAKE, instance, "REQ asserted\n");
@@ -1324,7 +1331,7 @@ static int NCR5380_transfer_pio(struct Scsi_Host *instance,
}

if (NCR5380_poll_politely(hostdata,
- STATUS_REG, SR_REQ, 0, 5 * HZ) < 0)
+ STATUS_REG, SR_REQ, 0, 5 * HZ, can_sleep) < 0)
break;

dsprintk(NDEBUG_HANDSHAKE, instance, "REQ negated, handshake complete\n");
@@ -1399,11 +1406,12 @@ static void do_reset(struct Scsi_Host *instance)
* do_abort - abort the currently established nexus by going to
* MESSAGE OUT phase and sending an ABORT message.
* @instance: relevant scsi host instance
+ * @can_sleep: true if the function can sleep
*
* Returns 0 on success, negative error code on failure.
*/

-static int do_abort(struct Scsi_Host *instance)
+static int do_abort(struct Scsi_Host *instance, bool can_sleep)
{
struct NCR5380_hostdata *hostdata = shost_priv(instance);
unsigned char *msgptr, phase, tmp;
@@ -1423,7 +1431,8 @@ static int do_abort(struct Scsi_Host *instance)
* the target sees, so we just handshake.
*/

- rc = NCR5380_poll_politely(hostdata, STATUS_REG, SR_REQ, SR_REQ, 10 * HZ);
+ rc = NCR5380_poll_politely(hostdata, STATUS_REG, SR_REQ, SR_REQ,
+ 10 * HZ, can_sleep);
if (rc < 0)
goto out;

@@ -1434,7 +1443,8 @@ static int do_abort(struct Scsi_Host *instance)
if (tmp != PHASE_MSGOUT) {
NCR5380_write(INITIATOR_COMMAND_REG,
ICR_BASE | ICR_ASSERT_ATN | ICR_ASSERT_ACK);
- rc = NCR5380_poll_politely(hostdata, STATUS_REG, SR_REQ, 0, 3 * HZ);
+ rc = NCR5380_poll_politely(hostdata, STATUS_REG, SR_REQ, 0,
+ 3 * HZ, can_sleep);
if (rc < 0)
goto out;
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN);
@@ -1444,7 +1454,7 @@ static int do_abort(struct Scsi_Host *instance)
msgptr = &tmp;
len = 1;
phase = PHASE_MSGOUT;
- NCR5380_transfer_pio(instance, &phase, &len, &msgptr);
+ NCR5380_transfer_pio(instance, &phase, &len, &msgptr, can_sleep);
if (len)
rc = -ENXIO;

@@ -1474,9 +1484,9 @@ static int do_abort(struct Scsi_Host *instance)
* is in same phase.
*
* Also, *phase, *count, *data are modified in place.
+ *
+ * Context: atomic, @instance hostdata spinlock held
*/
-
-
static int NCR5380_transfer_dma(struct Scsi_Host *instance,
unsigned char *phase, int *count,
unsigned char **data)
@@ -1623,12 +1633,12 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance,
*/

if (NCR5380_poll_politely(hostdata, BUS_AND_STATUS_REG,
- BASR_DRQ, BASR_DRQ, HZ) < 0) {
+ BASR_DRQ, BASR_DRQ, HZ, false) < 0) {
result = -1;
shost_printk(KERN_ERR, instance, "PDMA read: DRQ timeout\n");
}
if (NCR5380_poll_politely(hostdata, STATUS_REG,
- SR_REQ, 0, HZ) < 0) {
+ SR_REQ, 0, HZ, false) < 0) {
result = -1;
shost_printk(KERN_ERR, instance, "PDMA read: !REQ timeout\n");
}
@@ -1640,7 +1650,7 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance,
*/
if (NCR5380_poll_politely2(hostdata,
BUS_AND_STATUS_REG, BASR_DRQ, BASR_DRQ,
- BUS_AND_STATUS_REG, BASR_PHASE_MATCH, 0, HZ) < 0) {
+ BUS_AND_STATUS_REG, BASR_PHASE_MATCH, 0, HZ, false) < 0) {
result = -1;
shost_printk(KERN_ERR, instance, "PDMA write: DRQ and phase timeout\n");
}
@@ -1666,8 +1676,11 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance,
*
* XXX Note : we need to watch for bus free or a reset condition here
* to recover from an unexpected bus free condition.
+ *
+ * Context: task context, with @instance hostdata spinlock held by
+ * caller. That is, this function can sleep in the areas between
+ * releasing and re-acquring that spinlock.
*/
-
static void NCR5380_information_transfer(struct Scsi_Host *instance)
__releases(&hostdata->lock) __acquires(&hostdata->lock)
{
@@ -1737,7 +1750,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance)
#if (NDEBUG & NDEBUG_NO_DATAOUT)
shost_printk(KERN_DEBUG, instance, "NDEBUG_NO_DATAOUT set, attempted DATAOUT aborted\n");
sink = 1;
- do_abort(instance);
+ do_abort(instance, false);
cmd->result = DID_ERROR << 16;
complete_cmd(instance, cmd);
hostdata->connected = NULL;
@@ -1793,7 +1806,8 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance)
NCR5380_PIO_CHUNK_SIZE);
len = transfersize;
NCR5380_transfer_pio(instance, &phase, &len,
- (unsigned char **)&cmd->SCp.ptr);
+ (unsigned char **)&cmd->SCp.ptr,
+ false);
cmd->SCp.this_residual -= transfersize - len;
}
#ifdef CONFIG_SUN3
@@ -1804,7 +1818,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance)
case PHASE_MSGIN:
len = 1;
data = &tmp;
- NCR5380_transfer_pio(instance, &phase, &len, &data);
+ NCR5380_transfer_pio(instance, &phase, &len, &data, false);
cmd->SCp.Message = tmp;

switch (tmp) {
@@ -1910,7 +1924,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance)
len = 2;
data = extended_msg + 1;
phase = PHASE_MSGIN;
- NCR5380_transfer_pio(instance, &phase, &len, &data);
+ NCR5380_transfer_pio(instance, &phase, &len, &data, true);
dsprintk(NDEBUG_EXTENDED, instance, "length %d, code 0x%02x\n",
(int)extended_msg[1],
(int)extended_msg[2]);
@@ -1923,7 +1937,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance)
data = extended_msg + 3;
phase = PHASE_MSGIN;

- NCR5380_transfer_pio(instance, &phase, &len, &data);
+ NCR5380_transfer_pio(instance, &phase, &len, &data, true);
dsprintk(NDEBUG_EXTENDED, instance, "message received, residual %d\n",
len);

@@ -1970,7 +1984,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance)
len = 1;
data = &msgout;
hostdata->last_message = msgout;
- NCR5380_transfer_pio(instance, &phase, &len, &data);
+ NCR5380_transfer_pio(instance, &phase, &len, &data, false);
if (msgout == ABORT) {
hostdata->connected = NULL;
hostdata->busy[scmd_id(cmd)] &= ~(1 << cmd->device->lun);
@@ -1988,12 +2002,12 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance)
* PSEUDO-DMA architecture we should probably
* use the dma transfer function.
*/
- NCR5380_transfer_pio(instance, &phase, &len, &data);
+ NCR5380_transfer_pio(instance, &phase, &len, &data, false);
break;
case PHASE_STATIN:
len = 1;
data = &tmp;
- NCR5380_transfer_pio(instance, &phase, &len, &data);
+ NCR5380_transfer_pio(instance, &phase, &len, &data, false);
cmd->SCp.Status = tmp;
break;
default:
@@ -2002,7 +2016,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance)
} /* switch(phase) */
} else {
spin_unlock_irq(&hostdata->lock);
- NCR5380_poll_politely(hostdata, STATUS_REG, SR_REQ, SR_REQ, HZ);
+ NCR5380_poll_politely(hostdata, STATUS_REG, SR_REQ, SR_REQ, HZ, true);
spin_lock_irq(&hostdata->lock);
}
}
@@ -2016,8 +2030,9 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance)
* nexus has been reestablished,
*
* Inputs : instance - this instance of the NCR5380.
+ *
+ * Context: atomic, with @instance hostdata spinlock held
*/
-
static void NCR5380_reselect(struct Scsi_Host *instance)
{
struct NCR5380_hostdata *hostdata = shost_priv(instance);
@@ -2052,7 +2067,7 @@ static void NCR5380_reselect(struct Scsi_Host *instance)

NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_BSY);
if (NCR5380_poll_politely(hostdata,
- STATUS_REG, SR_SEL, 0, 2 * HZ) < 0) {
+ STATUS_REG, SR_SEL, 0, 2 * HZ, false) < 0) {
shost_printk(KERN_ERR, instance, "reselect: !SEL timeout\n");
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
return;
@@ -2064,12 +2079,12 @@ static void NCR5380_reselect(struct Scsi_Host *instance)
*/

if (NCR5380_poll_politely(hostdata,
- STATUS_REG, SR_REQ, SR_REQ, 2 * HZ) < 0) {
+ STATUS_REG, SR_REQ, SR_REQ, 2 * HZ, false) < 0) {
if ((NCR5380_read(STATUS_REG) & (SR_BSY | SR_SEL)) == 0)
/* BUS FREE phase */
return;
shost_printk(KERN_ERR, instance, "reselect: REQ timeout\n");
- do_abort(instance);
+ do_abort(instance, false);
return;
}

@@ -2085,10 +2100,10 @@ static void NCR5380_reselect(struct Scsi_Host *instance)
unsigned char *data = msg;
unsigned char phase = PHASE_MSGIN;

- NCR5380_transfer_pio(instance, &phase, &len, &data);
+ NCR5380_transfer_pio(instance, &phase, &len, &data, false);

if (len) {
- do_abort(instance);
+ do_abort(instance, false);
return;
}
}
@@ -2098,7 +2113,7 @@ static void NCR5380_reselect(struct Scsi_Host *instance)
shost_printk(KERN_ERR, instance, "expecting IDENTIFY message, got ");
spi_print_msg(msg);
printk("\n");
- do_abort(instance);
+ do_abort(instance, false);
return;
}
lun = msg[0] & 0x07;
@@ -2138,7 +2153,7 @@ static void NCR5380_reselect(struct Scsi_Host *instance)
* Since we have an established nexus that we can't do anything
* with, we must abort it.
*/
- if (do_abort(instance) == 0)
+ if (do_abort(instance, false) == 0)
hostdata->busy[target] &= ~(1 << lun);
return;
}
@@ -2285,7 +2300,7 @@ static int NCR5380_abort(struct scsi_cmnd *cmd)
dsprintk(NDEBUG_ABORT, instance, "abort: cmd %p is connected\n", cmd);
hostdata->connected = NULL;
hostdata->dma_len = 0;
- if (do_abort(instance) < 0) {
+ if (do_abort(instance, false) < 0) {
set_host_byte(cmd, DID_ERROR);
complete_cmd(instance, cmd);
result = FAILED;
diff --git a/drivers/scsi/NCR5380.h b/drivers/scsi/NCR5380.h
index 5935fd6d1a058..7c569e92ca58e 100644
--- a/drivers/scsi/NCR5380.h
+++ b/drivers/scsi/NCR5380.h
@@ -277,20 +277,21 @@ static const char *NCR5380_info(struct Scsi_Host *instance);
static void NCR5380_reselect(struct Scsi_Host *instance);
static bool NCR5380_select(struct Scsi_Host *, struct scsi_cmnd *);
static int NCR5380_transfer_dma(struct Scsi_Host *instance, unsigned char *phase, int *count, unsigned char **data);
-static int NCR5380_transfer_pio(struct Scsi_Host *instance, unsigned char *phase, int *count, unsigned char **data);
+static int NCR5380_transfer_pio(struct Scsi_Host *instance, unsigned char *phase,
+ int *count, unsigned char **data, bool can_sleep);
static int NCR5380_poll_politely2(struct NCR5380_hostdata *,
unsigned int, u8, u8,
- unsigned int, u8, u8, unsigned long);
+ unsigned int, u8, u8, unsigned long, bool);

static inline int NCR5380_poll_politely(struct NCR5380_hostdata *hostdata,
unsigned int reg, u8 bit, u8 val,
- unsigned long wait)
+ unsigned long wait, bool can_sleep)
{
if ((NCR5380_read(reg) & bit) == val)
return 0;

return NCR5380_poll_politely2(hostdata, reg, bit, val,
- reg, bit, val, wait);
+ reg, bit, val, wait, can_sleep);
}

static int NCR5380_dma_xfer_len(struct NCR5380_hostdata *,
diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c
index 29e4cdcade720..06b1fcfd33cc9 100644
--- a/drivers/scsi/g_NCR5380.c
+++ b/drivers/scsi/g_NCR5380.c
@@ -513,9 +513,11 @@ static void wait_for_53c80_access(struct NCR5380_hostdata *hostdata)
* @dst: buffer to write into
* @len: transfer size
*
+ * Context: atomic. This implements NCR5380.c NCR5380_dma_recv_setup(),
+ * which is always called with @hostdata spinlock held.
+ *
* Perform a pseudo DMA mode receive from a 53C400 or equivalent device.
*/
-
static inline int generic_NCR5380_precv(struct NCR5380_hostdata *hostdata,
unsigned char *dst, int len)
{
@@ -529,14 +531,16 @@ static inline int generic_NCR5380_precv(struct NCR5380_hostdata *hostdata,
if (start == len - 128) {
/* Ignore End of DMA interrupt for the final buffer */
if (NCR5380_poll_politely(hostdata, hostdata->c400_ctl_status,
- CSR_HOST_BUF_NOT_RDY, 0, HZ / 64) < 0)
+ CSR_HOST_BUF_NOT_RDY, 0, HZ / 64,
+ false) < 0)
break;
} else {
if (NCR5380_poll_politely2(hostdata, hostdata->c400_ctl_status,
CSR_HOST_BUF_NOT_RDY, 0,
hostdata->c400_ctl_status,
CSR_GATED_53C80_IRQ,
- CSR_GATED_53C80_IRQ, HZ / 64) < 0 ||
+ CSR_GATED_53C80_IRQ, HZ / 64,
+ false) < 0 ||
NCR5380_read(hostdata->c400_ctl_status) & CSR_HOST_BUF_NOT_RDY)
break;
}
@@ -565,7 +569,8 @@ static inline int generic_NCR5380_precv(struct NCR5380_hostdata *hostdata,
if (residual == 0 && NCR5380_poll_politely(hostdata, BUS_AND_STATUS_REG,
BASR_END_DMA_TRANSFER,
BASR_END_DMA_TRANSFER,
- HZ / 64) < 0)
+ HZ / 64,
+ false) < 0)
scmd_printk(KERN_ERR, hostdata->connected, "%s: End of DMA timeout\n",
__func__);

@@ -580,9 +585,11 @@ static inline int generic_NCR5380_precv(struct NCR5380_hostdata *hostdata,
* @src: buffer to read from
* @len: transfer size
*
+ * Context: atomic. This implements NCR5380.c NCR5380_dma_send_setup(),
+ * which is always called with @hostdata spinlock held.
+ *
* Perform a pseudo DMA mode send to a 53C400 or equivalent device.
*/
-
static inline int generic_NCR5380_psend(struct NCR5380_hostdata *hostdata,
unsigned char *src, int len)
{
@@ -597,7 +604,8 @@ static inline int generic_NCR5380_psend(struct NCR5380_hostdata *hostdata,
CSR_HOST_BUF_NOT_RDY, 0,
hostdata->c400_ctl_status,
CSR_GATED_53C80_IRQ,
- CSR_GATED_53C80_IRQ, HZ / 64) < 0 ||
+ CSR_GATED_53C80_IRQ, HZ / 64,
+ false) < 0 ||
NCR5380_read(hostdata->c400_ctl_status) & CSR_HOST_BUF_NOT_RDY) {
/* Both 128 B buffers are in use */
if (start >= 128)
@@ -644,13 +652,15 @@ static inline int generic_NCR5380_psend(struct NCR5380_hostdata *hostdata,
if (residual == 0) {
if (NCR5380_poll_politely(hostdata, TARGET_COMMAND_REG,
TCR_LAST_BYTE_SENT, TCR_LAST_BYTE_SENT,
- HZ / 64) < 0)
+ HZ / 64,
+ false) < 0)
scmd_printk(KERN_ERR, hostdata->connected,
"%s: Last Byte Sent timeout\n", __func__);

if (NCR5380_poll_politely(hostdata, BUS_AND_STATUS_REG,
BASR_END_DMA_TRANSFER, BASR_END_DMA_TRANSFER,
- HZ / 64) < 0)
+ HZ / 64,
+ false) < 0)
scmd_printk(KERN_ERR, hostdata->connected, "%s: End of DMA timeout\n",
__func__);
}
diff --git a/drivers/scsi/mac_scsi.c b/drivers/scsi/mac_scsi.c
index b5dde9d0d0545..3c39db74fd847 100644
--- a/drivers/scsi/mac_scsi.c
+++ b/drivers/scsi/mac_scsi.c
@@ -285,7 +285,7 @@ static inline int macscsi_pread(struct NCR5380_hostdata *hostdata,

while (!NCR5380_poll_politely(hostdata, BUS_AND_STATUS_REG,
BASR_DRQ | BASR_PHASE_MATCH,
- BASR_DRQ | BASR_PHASE_MATCH, HZ / 64)) {
+ BASR_DRQ | BASR_PHASE_MATCH, HZ / 64, false)) {
int bytes;

if (macintosh_config->ident == MAC_MODEL_IIFX)
@@ -304,7 +304,7 @@ static inline int macscsi_pread(struct NCR5380_hostdata *hostdata,

if (NCR5380_poll_politely2(hostdata, STATUS_REG, SR_REQ, SR_REQ,
BUS_AND_STATUS_REG, BASR_ACK,
- BASR_ACK, HZ / 64) < 0)
+ BASR_ACK, HZ / 64, false) < 0)
scmd_printk(KERN_DEBUG, hostdata->connected,
"%s: !REQ and !ACK\n", __func__);
if (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_PHASE_MATCH))
@@ -344,7 +344,7 @@ static inline int macscsi_pwrite(struct NCR5380_hostdata *hostdata,

while (!NCR5380_poll_politely(hostdata, BUS_AND_STATUS_REG,
BASR_DRQ | BASR_PHASE_MATCH,
- BASR_DRQ | BASR_PHASE_MATCH, HZ / 64)) {
+ BASR_DRQ | BASR_PHASE_MATCH, HZ / 64, false)) {
int bytes;

if (macintosh_config->ident == MAC_MODEL_IIFX)
@@ -362,7 +362,7 @@ static inline int macscsi_pwrite(struct NCR5380_hostdata *hostdata,
if (NCR5380_poll_politely(hostdata, TARGET_COMMAND_REG,
TCR_LAST_BYTE_SENT,
TCR_LAST_BYTE_SENT,
- HZ / 64) < 0) {
+ HZ / 64, false) < 0) {
scmd_printk(KERN_ERR, hostdata->connected,
"%s: Last Byte Sent timeout\n", __func__);
result = -1;
@@ -372,7 +372,7 @@ static inline int macscsi_pwrite(struct NCR5380_hostdata *hostdata,

if (NCR5380_poll_politely2(hostdata, STATUS_REG, SR_REQ, SR_REQ,
BUS_AND_STATUS_REG, BASR_ACK,
- BASR_ACK, HZ / 64) < 0)
+ BASR_ACK, HZ / 64, false) < 0)
scmd_printk(KERN_DEBUG, hostdata->connected,
"%s: !REQ and !ACK\n", __func__);
if (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_PHASE_MATCH))
--
2.29.2