diff options
author | Finn Thain <fthain@telegraphics.com.au> | 2019-06-08 21:19:11 -0400 |
---|---|---|
committer | Martin K. Petersen <martin.petersen@oracle.com> | 2019-06-20 15:37:03 -0400 |
commit | 57f31326518e98ee4cabf9a04efe00ed57c54147 (patch) | |
tree | d4eb1cf67ed98ed81e95fe602ba9d3e5b80b789b | |
parent | 25fcf94a2fa89dd3e73e965ebb0b38a2a4f72aa4 (diff) |
scsi: NCR5380: Always re-enable reselection interrupt
The reselection interrupt gets disabled during selection and must be
re-enabled when hostdata->connected becomes NULL. If it isn't re-enabled a
disconnected command may time-out or the target may wedge the bus while
trying to reselect the host. This can happen after a command is aborted.
Fix this by enabling the reselection interrupt in NCR5380_main() after
calls to NCR5380_select() and NCR5380_information_transfer() return.
Cc: Michael Schmitz <schmitzmic@gmail.com>
Cc: stable@vger.kernel.org # v4.9+
Fixes: 8b00c3d5d40d ("ncr5380: Implement new eh_abort_handler")
Signed-off-by: Finn Thain <fthain@telegraphics.com.au>
Tested-by: Stan Johnson <userm57@yahoo.com>
Tested-by: Michael Schmitz <schmitzmic@gmail.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
-rw-r--r-- | drivers/scsi/NCR5380.c | 12 |
1 files changed, 2 insertions, 10 deletions
diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index fe0535affc14..08e3ea8159b3 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c | |||
@@ -709,6 +709,8 @@ static void NCR5380_main(struct work_struct *work) | |||
709 | NCR5380_information_transfer(instance); | 709 | NCR5380_information_transfer(instance); |
710 | done = 0; | 710 | done = 0; |
711 | } | 711 | } |
712 | if (!hostdata->connected) | ||
713 | NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); | ||
712 | spin_unlock_irq(&hostdata->lock); | 714 | spin_unlock_irq(&hostdata->lock); |
713 | if (!done) | 715 | if (!done) |
714 | cond_resched(); | 716 | cond_resched(); |
@@ -1110,8 +1112,6 @@ static bool NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd) | |||
1110 | spin_lock_irq(&hostdata->lock); | 1112 | spin_lock_irq(&hostdata->lock); |
1111 | NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); | 1113 | NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); |
1112 | NCR5380_reselect(instance); | 1114 | NCR5380_reselect(instance); |
1113 | if (!hostdata->connected) | ||
1114 | NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); | ||
1115 | shost_printk(KERN_ERR, instance, "reselection after won arbitration?\n"); | 1115 | shost_printk(KERN_ERR, instance, "reselection after won arbitration?\n"); |
1116 | goto out; | 1116 | goto out; |
1117 | } | 1117 | } |
@@ -1119,7 +1119,6 @@ static bool NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd) | |||
1119 | if (err < 0) { | 1119 | if (err < 0) { |
1120 | spin_lock_irq(&hostdata->lock); | 1120 | spin_lock_irq(&hostdata->lock); |
1121 | NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); | 1121 | NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); |
1122 | NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); | ||
1123 | 1122 | ||
1124 | /* Can't touch cmd if it has been reclaimed by the scsi ML */ | 1123 | /* Can't touch cmd if it has been reclaimed by the scsi ML */ |
1125 | if (!hostdata->selecting) | 1124 | if (!hostdata->selecting) |
@@ -1157,7 +1156,6 @@ static bool NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd) | |||
1157 | if (err < 0) { | 1156 | if (err < 0) { |
1158 | shost_printk(KERN_ERR, instance, "select: REQ timeout\n"); | 1157 | shost_printk(KERN_ERR, instance, "select: REQ timeout\n"); |
1159 | NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); | 1158 | NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); |
1160 | NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); | ||
1161 | goto out; | 1159 | goto out; |
1162 | } | 1160 | } |
1163 | if (!hostdata->selecting) { | 1161 | if (!hostdata->selecting) { |
@@ -1826,9 +1824,6 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) | |||
1826 | */ | 1824 | */ |
1827 | NCR5380_write(TARGET_COMMAND_REG, 0); | 1825 | NCR5380_write(TARGET_COMMAND_REG, 0); |
1828 | 1826 | ||
1829 | /* Enable reselect interrupts */ | ||
1830 | NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); | ||
1831 | |||
1832 | maybe_release_dma_irq(instance); | 1827 | maybe_release_dma_irq(instance); |
1833 | return; | 1828 | return; |
1834 | case MESSAGE_REJECT: | 1829 | case MESSAGE_REJECT: |
@@ -1860,8 +1855,6 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) | |||
1860 | */ | 1855 | */ |
1861 | NCR5380_write(TARGET_COMMAND_REG, 0); | 1856 | NCR5380_write(TARGET_COMMAND_REG, 0); |
1862 | 1857 | ||
1863 | /* Enable reselect interrupts */ | ||
1864 | NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); | ||
1865 | #ifdef SUN3_SCSI_VME | 1858 | #ifdef SUN3_SCSI_VME |
1866 | dregs->csr |= CSR_DMA_ENABLE; | 1859 | dregs->csr |= CSR_DMA_ENABLE; |
1867 | #endif | 1860 | #endif |
@@ -1964,7 +1957,6 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) | |||
1964 | cmd->result = DID_ERROR << 16; | 1957 | cmd->result = DID_ERROR << 16; |
1965 | complete_cmd(instance, cmd); | 1958 | complete_cmd(instance, cmd); |
1966 | maybe_release_dma_irq(instance); | 1959 | maybe_release_dma_irq(instance); |
1967 | NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); | ||
1968 | return; | 1960 | return; |
1969 | } | 1961 | } |
1970 | msgout = NOP; | 1962 | msgout = NOP; |