libata: use PIO for non-16 byte aligned ATAPI commands
The IDE driver used DMA for ATAPI commands if READ/WRITE command is
multiple of sector size or sg command is multiple of 16 bytes. For
libata, READ/WRITE sector alignment is guaranteed by the high level
driver (sr), so we only have to worry about the 16 byte alignment.
This patch makes ata_check_atapi_dma() always request PIO for all data
transfer commands which are not multiple of 16 bytes.
The following reports are related to this problem.
http://bugzilla.kernel.org/show_bug.cgi?id=8605 (confirmed)
http://thread.gmane.org/gmane.linux.kernel/476620 (confirmed)
https://bugzilla.novell.com/show_bug.cgi?id=229260 (probably)
Albert first pointed out the difference between IDE and libata. Kudos
to him.
Signed-off-by: Tejun Heo <htejun@gmail.com>
Cc: Albert Lee <albertcc@tw.ibm.com>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index 642097a..094b518 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -4109,6 +4109,7 @@
if (idx)
ap->prd[idx - 1].flags_len |= cpu_to_le32(ATA_PRD_EOT);
}
+
/**
* ata_check_atapi_dma - Check whether ATAPI DMA can be supported
* @qc: Metadata associated with taskfile to check
@@ -4126,33 +4127,19 @@
int ata_check_atapi_dma(struct ata_queued_cmd *qc)
{
struct ata_port *ap = qc->ap;
- int rc = 0; /* Assume ATAPI DMA is OK by default */
- /* some drives can only do ATAPI DMA on read/write */
- if (unlikely(qc->dev->horkage & ATA_HORKAGE_DMA_RW_ONLY)) {
- struct scsi_cmnd *cmd = qc->scsicmd;
- u8 *scsicmd = cmd->cmnd;
-
- switch (scsicmd[0]) {
- case READ_10:
- case WRITE_10:
- case READ_12:
- case WRITE_12:
- case READ_6:
- case WRITE_6:
- /* atapi dma maybe ok */
- break;
- default:
- /* turn off atapi dma */
- return 1;
- }
- }
+ /* Don't allow DMA if it isn't multiple of 16 bytes. Quite a
+ * few ATAPI devices choke on such DMA requests.
+ */
+ if (unlikely(qc->nbytes & 15))
+ return 1;
if (ap->ops->check_atapi_dma)
- rc = ap->ops->check_atapi_dma(qc);
+ return ap->ops->check_atapi_dma(qc);
- return rc;
+ return 0;
}
+
/**
* ata_qc_prep - Prepare taskfile for submission
* @qc: Metadata associated with taskfile to be prepared