mirror of
https://github.com/nxp-imx/linux-imx.git
synced 2025-07-07 09:55:19 +02:00
scsi: NCR5380: Check for phase match during PDMA fixup
[ Upstream commit5768718da9
] 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 <userm57@yahoo.com> Fixes:55181be8ce
("ncr5380: Replace redundant flags with FLAG_NO_DMA_FIXUP") Signed-off-by: Finn Thain <fthain@linux-m68k.org> Link: https://lore.kernel.org/r/99dc7d1f4c825621b5b120963a69f6cd3e9ca659.1723001788.git.fthain@linux-m68k.org Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com> Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
parent
464fd60a16
commit
53c18f7baf
|
@ -1485,6 +1485,7 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance,
|
||||||
unsigned char **data)
|
unsigned char **data)
|
||||||
{
|
{
|
||||||
struct NCR5380_hostdata *hostdata = shost_priv(instance);
|
struct NCR5380_hostdata *hostdata = shost_priv(instance);
|
||||||
|
struct NCR5380_cmd *ncmd = NCR5380_to_ncmd(hostdata->connected);
|
||||||
int c = *count;
|
int c = *count;
|
||||||
unsigned char p = *phase;
|
unsigned char p = *phase;
|
||||||
unsigned char *d = *data;
|
unsigned char *d = *data;
|
||||||
|
@ -1496,7 +1497,7 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance,
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
NCR5380_to_ncmd(hostdata->connected)->phase = p;
|
ncmd->phase = p;
|
||||||
|
|
||||||
if (p & SR_IO) {
|
if (p & SR_IO) {
|
||||||
if (hostdata->read_overruns)
|
if (hostdata->read_overruns)
|
||||||
|
@ -1608,13 +1609,13 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance,
|
||||||
* request.
|
* request.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (hostdata->flags & FLAG_DMA_FIXUP) {
|
if ((hostdata->flags & FLAG_DMA_FIXUP) &&
|
||||||
if (p & SR_IO) {
|
(NCR5380_read(BUS_AND_STATUS_REG) & BASR_PHASE_MATCH)) {
|
||||||
/*
|
/*
|
||||||
* The workaround was to transfer fewer bytes than we
|
* The workaround was to transfer fewer bytes than we
|
||||||
* intended to with the pseudo-DMA read function, wait for
|
* intended to with the pseudo-DMA receive function, wait for
|
||||||
* the chip to latch the last byte, read it, and then disable
|
* the chip to latch the last byte, read it, and then disable
|
||||||
* pseudo-DMA mode.
|
* DMA mode.
|
||||||
*
|
*
|
||||||
* After REQ is asserted, the NCR5380 asserts DRQ and ACK.
|
* After REQ is asserted, the NCR5380 asserts DRQ and ACK.
|
||||||
* REQ is deasserted when ACK is asserted, and not reasserted
|
* REQ is deasserted when ACK is asserted, and not reasserted
|
||||||
|
@ -1623,31 +1624,30 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance,
|
||||||
* the DMA port or we take the NCR5380 out of DMA mode, we
|
* the DMA port or we take the NCR5380 out of DMA mode, we
|
||||||
* can guarantee that we won't handshake another extra
|
* can guarantee that we won't handshake another extra
|
||||||
* byte.
|
* byte.
|
||||||
|
*
|
||||||
|
* If sending, wait for the last byte to be sent. If REQ is
|
||||||
|
* being asserted for the byte we're interested, we'll ACK it
|
||||||
|
* and it will go false.
|
||||||
*/
|
*/
|
||||||
|
if (!NCR5380_poll_politely(hostdata, BUS_AND_STATUS_REG,
|
||||||
if (NCR5380_poll_politely(hostdata, BUS_AND_STATUS_REG,
|
BASR_DRQ, BASR_DRQ, 0)) {
|
||||||
BASR_DRQ, BASR_DRQ, 0) < 0) {
|
if ((p & SR_IO) &&
|
||||||
result = -1;
|
(NCR5380_read(BUS_AND_STATUS_REG) & BASR_PHASE_MATCH)) {
|
||||||
shost_printk(KERN_ERR, instance, "PDMA read: DRQ timeout\n");
|
if (!NCR5380_poll_politely(hostdata, STATUS_REG,
|
||||||
}
|
SR_REQ, 0, 0)) {
|
||||||
if (NCR5380_poll_politely(hostdata, STATUS_REG,
|
d[c] = NCR5380_read(INPUT_DATA_REG);
|
||||||
SR_REQ, 0, 0) < 0) {
|
--ncmd->this_residual;
|
||||||
result = -1;
|
|
||||||
shost_printk(KERN_ERR, instance, "PDMA read: !REQ timeout\n");
|
|
||||||
}
|
|
||||||
d[*count - 1] = NCR5380_read(INPUT_DATA_REG);
|
|
||||||
} else {
|
} else {
|
||||||
/*
|
|
||||||
* Wait for the last byte to be sent. If REQ is being asserted for
|
|
||||||
* the byte we're interested, we'll ACK it and it will go false.
|
|
||||||
*/
|
|
||||||
if (NCR5380_poll_politely2(hostdata,
|
|
||||||
BUS_AND_STATUS_REG, BASR_DRQ, BASR_DRQ,
|
|
||||||
BUS_AND_STATUS_REG, BASR_PHASE_MATCH, 0, 0) < 0) {
|
|
||||||
result = -1;
|
result = -1;
|
||||||
shost_printk(KERN_ERR, instance, "PDMA write: DRQ and phase timeout\n");
|
scmd_printk(KERN_ERR, hostdata->connected,
|
||||||
|
"PDMA fixup: !REQ timeout\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if (NCR5380_read(BUS_AND_STATUS_REG) & BASR_PHASE_MATCH) {
|
||||||
|
result = -1;
|
||||||
|
scmd_printk(KERN_ERR, hostdata->connected,
|
||||||
|
"PDMA fixup: DRQ timeout\n");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
NCR5380_dma_complete(instance);
|
NCR5380_dma_complete(instance);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user