diff options
author | Finn Thain <fthain@telegraphics.com.au> | 2016-01-03 16:05:35 +1100 |
---|---|---|
committer | Martin K. Petersen <martin.petersen@oracle.com> | 2016-01-06 21:42:58 -0500 |
commit | 55500d9b08295e3b6016b53879dea1cb7787f1b0 (patch) | |
tree | 9866566badb1a99bc4a2e44f729e4546684c19be /drivers/scsi/NCR5380.c | |
parent | 80d3eb6df46603e0b7e9a7361fe5b98383182c7f (diff) | |
download | lwn-55500d9b08295e3b6016b53879dea1cb7787f1b0.tar.gz lwn-55500d9b08295e3b6016b53879dea1cb7787f1b0.zip |
atari_NCR5380: Use arbitration timeout
Allow target selection to fail with a timeout instead of waiting in
infinite loops. This gets rid of the unused NCR_TIMEOUT macro, it is more
defensive and has proved helpful in debugging.
Signed-off-by: Finn Thain <fthain@telegraphics.com.au>
Reviewed-by: Hannes Reinecke <hare@suse.com>
Tested-by: Ondrej Zary <linux@rainbow-software.org>
Tested-by: Michael Schmitz <schmitzmic@gmail.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Diffstat (limited to 'drivers/scsi/NCR5380.c')
-rw-r--r-- | drivers/scsi/NCR5380.c | 44 |
1 files changed, 24 insertions, 20 deletions
diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index 973ea5189dd4..97975cb27337 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -1083,6 +1083,7 @@ static int NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd) unsigned char *data; int len; int err; + unsigned long timeout; NCR5380_dprint(NDEBUG_ARBITRATION, instance); dprintk(NDEBUG_ARBITRATION, "scsi%d : starting arbitration, id = %d\n", instance->host_no, instance->this_id); @@ -1101,28 +1102,31 @@ static int NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd) NCR5380_write(OUTPUT_DATA_REG, hostdata->id_mask); NCR5380_write(MODE_REG, MR_ARBITRATE); + /* The chip now waits for BUS FREE phase. Then after the 800 ns + * Bus Free Delay, arbitration will begin. + */ - /* We can be relaxed here, interrupts are on, we are - in workqueue context, the birds are singing in the trees */ spin_unlock_irq(instance->host_lock); - err = NCR5380_poll_politely(instance, INITIATOR_COMMAND_REG, ICR_ARBITRATION_PROGRESS, ICR_ARBITRATION_PROGRESS, 5*HZ); - spin_lock_irq(instance->host_lock); - if (err < 0) { - printk(KERN_DEBUG "scsi: arbitration timeout at %d\n", __LINE__); - NCR5380_write(MODE_REG, MR_BASE); - NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); - return -1; + timeout = jiffies + HZ; + while (1) { + if (time_is_before_jiffies(timeout)) { + NCR5380_write(MODE_REG, MR_BASE); + shost_printk(KERN_ERR, instance, + "select: arbitration timeout\n"); + spin_lock_irq(instance->host_lock); + return -1; + } + spin_lock_irq(instance->host_lock); + if (!(NCR5380_read(MODE_REG) & MR_ARBITRATE)) { + /* Reselection interrupt */ + return -1; + } + if (NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_PROGRESS) + break; + spin_unlock_irq(instance->host_lock); } - dprintk(NDEBUG_ARBITRATION, "scsi%d : arbitration complete\n", instance->host_no); - - /* - * The arbitration delay is 2.2us, but this is a minimum and there is - * no maximum so we can safely sleep for ceil(2.2) usecs to accommodate - * the integral nature of udelay(). - * - */ - + /* The SCSI-2 arbitration delay is 2.4 us */ udelay(3); /* Check for lost arbitration */ @@ -1270,9 +1274,9 @@ static int NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd) spin_unlock_irq(instance->host_lock); err = NCR5380_poll_politely(instance, STATUS_REG, SR_REQ, SR_REQ, HZ); spin_lock_irq(instance->host_lock); - if (err < 0) { - printk(KERN_ERR "scsi%d: timeout at NCR5380.c:%d\n", instance->host_no, __LINE__); + shost_printk(KERN_ERR, instance, "select: REQ timeout\n"); + NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); return -1; } |