| From aad394d83ce64151470caa64d1c9c33c028ac5fa Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Thu, 27 Sep 2018 11:17:11 +1000 |
| Subject: scsi: NCR5380: Don't clear busy flag when abort fails |
| |
| From: Finn Thain <fthain@telegraphics.com.au> |
| |
| [ Upstream commit 45ddc1b24806cc8f1a09f23dd4e7b6e4a8ae36e1 ] |
| |
| When NCR5380_abort() returns FAILED, the driver forgets that the target is |
| still busy. Hence, further commands may be sent to the target, which may fail |
| during selection and produce the error message, "reselection after won |
| arbitration?". Prevent this by leaving the busy flag set when NCR5380_abort() |
| fails. |
| |
| Tested-by: Michael Schmitz <schmitzmic@gmail.com> |
| Signed-off-by: Finn Thain <fthain@telegraphics.com.au> |
| Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| drivers/scsi/NCR5380.c | 14 ++++++++++---- |
| 1 file changed, 10 insertions(+), 4 deletions(-) |
| |
| diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c |
| index c67f476447372..227ceb5197555 100644 |
| --- a/drivers/scsi/NCR5380.c |
| +++ b/drivers/scsi/NCR5380.c |
| @@ -522,8 +522,6 @@ static void complete_cmd(struct Scsi_Host *instance, |
| hostdata->sensing = NULL; |
| } |
| |
| - hostdata->busy[scmd_id(cmd)] &= ~(1 << cmd->device->lun); |
| - |
| cmd->scsi_done(cmd); |
| } |
| |
| @@ -1711,6 +1709,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) |
| cmd->result = DID_ERROR << 16; |
| complete_cmd(instance, cmd); |
| hostdata->connected = NULL; |
| + hostdata->busy[scmd_id(cmd)] &= ~(1 << cmd->device->lun); |
| return; |
| #endif |
| case PHASE_DATAIN: |
| @@ -1793,6 +1792,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) |
| cmd, scmd_id(cmd), cmd->device->lun); |
| |
| hostdata->connected = NULL; |
| + hostdata->busy[scmd_id(cmd)] &= ~(1 << cmd->device->lun); |
| |
| cmd->result &= ~0xffff; |
| cmd->result |= cmd->SCp.Status; |
| @@ -1946,6 +1946,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) |
| NCR5380_transfer_pio(instance, &phase, &len, &data); |
| if (msgout == ABORT) { |
| hostdata->connected = NULL; |
| + hostdata->busy[scmd_id(cmd)] &= ~(1 << cmd->device->lun); |
| cmd->result = DID_ERROR << 16; |
| complete_cmd(instance, cmd); |
| maybe_release_dma_irq(instance); |
| @@ -2100,13 +2101,16 @@ static void NCR5380_reselect(struct Scsi_Host *instance) |
| dsprintk(NDEBUG_RESELECTION | NDEBUG_QUEUES, instance, |
| "reselect: removed %p from disconnected queue\n", tmp); |
| } else { |
| + int target = ffs(target_mask) - 1; |
| + |
| shost_printk(KERN_ERR, instance, "target bitmask 0x%02x lun %d not in disconnected queue.\n", |
| target_mask, lun); |
| /* |
| * Since we have an established nexus that we can't do anything |
| * with, we must abort it. |
| */ |
| - do_abort(instance); |
| + if (do_abort(instance) == 0) |
| + hostdata->busy[target] &= ~(1 << lun); |
| return; |
| } |
| |
| @@ -2277,8 +2281,10 @@ static int NCR5380_abort(struct scsi_cmnd *cmd) |
| out: |
| if (result == FAILED) |
| dsprintk(NDEBUG_ABORT, instance, "abort: failed to abort %p\n", cmd); |
| - else |
| + else { |
| + hostdata->busy[scmd_id(cmd)] &= ~(1 << cmd->device->lun); |
| dsprintk(NDEBUG_ABORT, instance, "abort: successfully aborted %p\n", cmd); |
| + } |
| |
| queue_work(hostdata->work_q, &hostdata->main_task); |
| maybe_release_dma_irq(instance); |
| -- |
| 2.20.1 |
| |