aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFinn Thain <fthain@telegraphics.com.au>2016-02-22 18:07:05 -0500
committerMartin K. Petersen <martin.petersen@oracle.com>2016-03-01 09:37:53 -0500
commit1678847ec93040ae8280d19c42ae0ba8a4233e6d (patch)
tree48b66e39bcdaeb772545726a2a63a8175165f0aa
parent1884c2838f31e6bf20f21459ed9921f8c92ed3ef (diff)
ncr5380: Dont release lock for PIO transfer
The calls to NCR5380_transfer_pio() for DATA IN and DATA OUT phases will modify cmd->SCp.this_residual, cmd->SCp.ptr and cmd->SCp.buffer. That works as long as EH does not intervene, which became possible in atari_NCR5380.c when I changed the locking to bring it closer to NCR5380.c. If error recovery aborts the command, the scsi_cmnd in question and its buffer will be returned to the mid-layer. So the transfer has to cease, but it can't be stopped by the initiator because the target controls the bus phase. The problem does not arise if the lock is not released. That was fine for atari_scsi, because it implements DMA. For the other drivers, we have to release the lock and re-enable interrupts for long PIO data transfers. The solution is to split the transfer into small chunks. In between chunks the main loop releases the lock and re-enables interrupts. Thus interrupts can be serviced and eh_bus_reset_handler can intervene if need be. This fixes an oops in NCR5380_transfer_pio() that can happen when the EH abort handler is invoked during DATA IN or DATA OUT phase. Fixes: 11d2f63b9cf5 ("ncr5380: Change instance->host_lock to hostdata->lock") Reported-and-tested-by: Michael Schmitz <schmitzmic@gmail.com> Cc: <stable@vger.kernel.org> # 4.5 Signed-off-by: Finn Thain <fthain@telegraphics.com.au> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
-rw-r--r--drivers/scsi/NCR5380.c16
-rw-r--r--drivers/scsi/atari_NCR5380.c16
2 files changed, 18 insertions, 14 deletions
diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c
index ce577f413328..0e00d487ceb4 100644
--- a/drivers/scsi/NCR5380.c
+++ b/drivers/scsi/NCR5380.c
@@ -1759,9 +1759,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance)
1759 unsigned char msgout = NOP; 1759 unsigned char msgout = NOP;
1760 int sink = 0; 1760 int sink = 0;
1761 int len; 1761 int len;
1762#if defined(PSEUDO_DMA) || defined(REAL_DMA_POLL)
1763 int transfersize; 1762 int transfersize;
1764#endif
1765 unsigned char *data; 1763 unsigned char *data;
1766 unsigned char phase, tmp, extended_msg[10], old_phase = 0xff; 1764 unsigned char phase, tmp, extended_msg[10], old_phase = 0xff;
1767 struct scsi_cmnd *cmd; 1765 struct scsi_cmnd *cmd;
@@ -1854,13 +1852,17 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance)
1854 } else 1852 } else
1855#endif /* defined(PSEUDO_DMA) || defined(REAL_DMA_POLL) */ 1853#endif /* defined(PSEUDO_DMA) || defined(REAL_DMA_POLL) */
1856 { 1854 {
1857 spin_unlock_irq(&hostdata->lock); 1855 /* Break up transfer into 3 ms chunks,
1858 NCR5380_transfer_pio(instance, &phase, 1856 * presuming 6 accesses per handshake.
1859 (int *)&cmd->SCp.this_residual, 1857 */
1858 transfersize = min((unsigned long)cmd->SCp.this_residual,
1859 hostdata->accesses_per_ms / 2);
1860 len = transfersize;
1861 NCR5380_transfer_pio(instance, &phase, &len,
1860 (unsigned char **)&cmd->SCp.ptr); 1862 (unsigned char **)&cmd->SCp.ptr);
1861 spin_lock_irq(&hostdata->lock); 1863 cmd->SCp.this_residual -= transfersize - len;
1862 } 1864 }
1863 break; 1865 return;
1864 case PHASE_MSGIN: 1866 case PHASE_MSGIN:
1865 len = 1; 1867 len = 1;
1866 data = &tmp; 1868 data = &tmp;
diff --git a/drivers/scsi/atari_NCR5380.c b/drivers/scsi/atari_NCR5380.c
index af0421829701..d382e71f4f4e 100644
--- a/drivers/scsi/atari_NCR5380.c
+++ b/drivers/scsi/atari_NCR5380.c
@@ -1838,9 +1838,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance)
1838 unsigned char msgout = NOP; 1838 unsigned char msgout = NOP;
1839 int sink = 0; 1839 int sink = 0;
1840 int len; 1840 int len;
1841#if defined(REAL_DMA)
1842 int transfersize; 1841 int transfersize;
1843#endif
1844 unsigned char *data; 1842 unsigned char *data;
1845 unsigned char phase, tmp, extended_msg[10], old_phase = 0xff; 1843 unsigned char phase, tmp, extended_msg[10], old_phase = 0xff;
1846 struct scsi_cmnd *cmd; 1844 struct scsi_cmnd *cmd;
@@ -1983,18 +1981,22 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance)
1983 } else 1981 } else
1984#endif /* defined(REAL_DMA) */ 1982#endif /* defined(REAL_DMA) */
1985 { 1983 {
1986 spin_unlock_irq(&hostdata->lock); 1984 /* Break up transfer into 3 ms chunks,
1987 NCR5380_transfer_pio(instance, &phase, 1985 * presuming 6 accesses per handshake.
1988 (int *)&cmd->SCp.this_residual, 1986 */
1987 transfersize = min((unsigned long)cmd->SCp.this_residual,
1988 hostdata->accesses_per_ms / 2);
1989 len = transfersize;
1990 NCR5380_transfer_pio(instance, &phase, &len,
1989 (unsigned char **)&cmd->SCp.ptr); 1991 (unsigned char **)&cmd->SCp.ptr);
1990 spin_lock_irq(&hostdata->lock); 1992 cmd->SCp.this_residual -= transfersize - len;
1991 } 1993 }
1992#if defined(CONFIG_SUN3) && defined(REAL_DMA) 1994#if defined(CONFIG_SUN3) && defined(REAL_DMA)
1993 /* if we had intended to dma that command clear it */ 1995 /* if we had intended to dma that command clear it */
1994 if (sun3_dma_setup_done == cmd) 1996 if (sun3_dma_setup_done == cmd)
1995 sun3_dma_setup_done = NULL; 1997 sun3_dma_setup_done = NULL;
1996#endif 1998#endif
1997 break; 1999 return;
1998 case PHASE_MSGIN: 2000 case PHASE_MSGIN:
1999 len = 1; 2001 len = 1;
2000 data = &tmp; 2002 data = &tmp;