Skip to content

Commit 5768718

Browse files
fthainmartinkpetersen
authored andcommitted
scsi: NCR5380: Check for phase match during PDMA fixup
It's not an error for a target to change the bus phase during a transfer. Unfortunately, the FLAG_DMA_FIXUP workaround does not allow for that -- a phase change produces a DRQ timeout error and the device borken flag will be set. Check the phase match bit during FLAG_DMA_FIXUP processing. Don't forget to decrement the command residual. While we are here, change shost_printk() into scmd_printk() for better consistency with other DMA error messages. Tested-by: Stan Johnson <[email protected]> Fixes: 55181be ("ncr5380: Replace redundant flags with FLAG_NO_DMA_FIXUP") Signed-off-by: Finn Thain <[email protected]> Link: https://lore.kernel.org/r/99dc7d1f4c825621b5b120963a69f6cd3e9ca659.1723001788.git.fthain@linux-m68k.org Signed-off-by: Martin K. Petersen <[email protected]>
1 parent 5551bc3 commit 5768718

File tree

1 file changed

+39
-39
lines changed

1 file changed

+39
-39
lines changed

drivers/scsi/NCR5380.c

Lines changed: 39 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1485,6 +1485,7 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance,
14851485
unsigned char **data)
14861486
{
14871487
struct NCR5380_hostdata *hostdata = shost_priv(instance);
1488+
struct NCR5380_cmd *ncmd = NCR5380_to_ncmd(hostdata->connected);
14881489
int c = *count;
14891490
unsigned char p = *phase;
14901491
unsigned char *d = *data;
@@ -1496,7 +1497,7 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance,
14961497
return -1;
14971498
}
14981499

1499-
NCR5380_to_ncmd(hostdata->connected)->phase = p;
1500+
ncmd->phase = p;
15001501

15011502
if (p & SR_IO) {
15021503
if (hostdata->read_overruns)
@@ -1608,45 +1609,44 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance,
16081609
* request.
16091610
*/
16101611

1611-
if (hostdata->flags & FLAG_DMA_FIXUP) {
1612-
if (p & SR_IO) {
1613-
/*
1614-
* The workaround was to transfer fewer bytes than we
1615-
* intended to with the pseudo-DMA read function, wait for
1616-
* the chip to latch the last byte, read it, and then disable
1617-
* pseudo-DMA mode.
1618-
*
1619-
* After REQ is asserted, the NCR5380 asserts DRQ and ACK.
1620-
* REQ is deasserted when ACK is asserted, and not reasserted
1621-
* until ACK goes false. Since the NCR5380 won't lower ACK
1622-
* until DACK is asserted, which won't happen unless we twiddle
1623-
* the DMA port or we take the NCR5380 out of DMA mode, we
1624-
* can guarantee that we won't handshake another extra
1625-
* byte.
1626-
*/
1627-
1628-
if (NCR5380_poll_politely(hostdata, BUS_AND_STATUS_REG,
1629-
BASR_DRQ, BASR_DRQ, 0) < 0) {
1630-
result = -1;
1631-
shost_printk(KERN_ERR, instance, "PDMA read: DRQ timeout\n");
1632-
}
1633-
if (NCR5380_poll_politely(hostdata, STATUS_REG,
1634-
SR_REQ, 0, 0) < 0) {
1635-
result = -1;
1636-
shost_printk(KERN_ERR, instance, "PDMA read: !REQ timeout\n");
1637-
}
1638-
d[*count - 1] = NCR5380_read(INPUT_DATA_REG);
1639-
} else {
1640-
/*
1641-
* Wait for the last byte to be sent. If REQ is being asserted for
1642-
* the byte we're interested, we'll ACK it and it will go false.
1643-
*/
1644-
if (NCR5380_poll_politely2(hostdata,
1645-
BUS_AND_STATUS_REG, BASR_DRQ, BASR_DRQ,
1646-
BUS_AND_STATUS_REG, BASR_PHASE_MATCH, 0, 0) < 0) {
1647-
result = -1;
1648-
shost_printk(KERN_ERR, instance, "PDMA write: DRQ and phase timeout\n");
1612+
if ((hostdata->flags & FLAG_DMA_FIXUP) &&
1613+
(NCR5380_read(BUS_AND_STATUS_REG) & BASR_PHASE_MATCH)) {
1614+
/*
1615+
* The workaround was to transfer fewer bytes than we
1616+
* intended to with the pseudo-DMA receive function, wait for
1617+
* the chip to latch the last byte, read it, and then disable
1618+
* DMA mode.
1619+
*
1620+
* After REQ is asserted, the NCR5380 asserts DRQ and ACK.
1621+
* REQ is deasserted when ACK is asserted, and not reasserted
1622+
* until ACK goes false. Since the NCR5380 won't lower ACK
1623+
* until DACK is asserted, which won't happen unless we twiddle
1624+
* the DMA port or we take the NCR5380 out of DMA mode, we
1625+
* can guarantee that we won't handshake another extra
1626+
* byte.
1627+
*
1628+
* If sending, wait for the last byte to be sent. If REQ is
1629+
* being asserted for the byte we're interested, we'll ACK it
1630+
* and it will go false.
1631+
*/
1632+
if (!NCR5380_poll_politely(hostdata, BUS_AND_STATUS_REG,
1633+
BASR_DRQ, BASR_DRQ, 0)) {
1634+
if ((p & SR_IO) &&
1635+
(NCR5380_read(BUS_AND_STATUS_REG) & BASR_PHASE_MATCH)) {
1636+
if (!NCR5380_poll_politely(hostdata, STATUS_REG,
1637+
SR_REQ, 0, 0)) {
1638+
d[c] = NCR5380_read(INPUT_DATA_REG);
1639+
--ncmd->this_residual;
1640+
} else {
1641+
result = -1;
1642+
scmd_printk(KERN_ERR, hostdata->connected,
1643+
"PDMA fixup: !REQ timeout\n");
1644+
}
16491645
}
1646+
} else if (NCR5380_read(BUS_AND_STATUS_REG) & BASR_PHASE_MATCH) {
1647+
result = -1;
1648+
scmd_printk(KERN_ERR, hostdata->connected,
1649+
"PDMA fixup: DRQ timeout\n");
16501650
}
16511651
}
16521652

0 commit comments

Comments
 (0)