aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorRobert Hancock <hancockr@shaw.ca>2007-11-25 17:59:36 -0500
committerJeff Garzik <jeff@garzik.org>2007-12-04 14:01:18 -0500
commit3f3debdbfb7713aa06c4370bab6bef277dfd7a37 (patch)
tree0f69f5b993db5e7ec188383f082079396975cd18 /drivers
parent2254c2e0184c603f92fc9b81016ff4bb53da622d (diff)
sata_nv: don't use legacy DMA in ADMA mode (v3)
We need to run any DMA command with result taskfile requested in ADMA mode when the port is in ADMA mode, otherwise it may try to use the legacy DMA engine in ADMA mode which is not allowed. Enforce this with BUG_ON() since data corruption could potentially result if this happened. Also, fail any attempt to try and issue NCQ commands with result taskfile requested, since the hardware doesn't allow this. Signed-off-by: Robert Hancock <hancockr@shaw.ca> Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/ata/sata_nv.c32
1 files changed, 23 insertions, 9 deletions
diff --git a/drivers/ata/sata_nv.c b/drivers/ata/sata_nv.c
index 44f9e5d9e362..ed5dc7cb50cd 100644
--- a/drivers/ata/sata_nv.c
+++ b/drivers/ata/sata_nv.c
@@ -791,11 +791,13 @@ static int nv_adma_check_atapi_dma(struct ata_queued_cmd *qc)
791 791
792static void nv_adma_tf_read(struct ata_port *ap, struct ata_taskfile *tf) 792static void nv_adma_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
793{ 793{
794 /* Since commands where a result TF is requested are not 794 /* Other than when internal or pass-through commands are executed,
795 executed in ADMA mode, the only time this function will be called 795 the only time this function will be called in ADMA mode will be
796 in ADMA mode will be if a command fails. In this case we 796 if a command fails. In the failure case we don't care about going
797 don't care about going into register mode with ADMA commands 797 into register mode with ADMA commands pending, as the commands will
798 pending, as the commands will all shortly be aborted anyway. */ 798 all shortly be aborted anyway. We assume that NCQ commands are not
799 issued via passthrough, which is the only way that switching into
800 ADMA mode could abort outstanding commands. */
799 nv_adma_register_mode(ap); 801 nv_adma_register_mode(ap);
800 802
801 ata_tf_read(ap, tf); 803 ata_tf_read(ap, tf);
@@ -1359,11 +1361,9 @@ static int nv_adma_use_reg_mode(struct ata_queued_cmd *qc)
1359 struct nv_adma_port_priv *pp = qc->ap->private_data; 1361 struct nv_adma_port_priv *pp = qc->ap->private_data;
1360 1362
1361 /* ADMA engine can only be used for non-ATAPI DMA commands, 1363 /* ADMA engine can only be used for non-ATAPI DMA commands,
1362 or interrupt-driven no-data commands, where a result taskfile 1364 or interrupt-driven no-data commands. */
1363 is not required. */
1364 if ((pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE) || 1365 if ((pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE) ||
1365 (qc->tf.flags & ATA_TFLAG_POLLING) || 1366 (qc->tf.flags & ATA_TFLAG_POLLING))
1366 (qc->flags & ATA_QCFLAG_RESULT_TF))
1367 return 1; 1367 return 1;
1368 1368
1369 if ((qc->flags & ATA_QCFLAG_DMAMAP) || 1369 if ((qc->flags & ATA_QCFLAG_DMAMAP) ||
@@ -1381,6 +1381,8 @@ static void nv_adma_qc_prep(struct ata_queued_cmd *qc)
1381 NV_CPB_CTL_IEN; 1381 NV_CPB_CTL_IEN;
1382 1382
1383 if (nv_adma_use_reg_mode(qc)) { 1383 if (nv_adma_use_reg_mode(qc)) {
1384 BUG_ON(!(pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE) &&
1385 (qc->flags & ATA_QCFLAG_DMAMAP));
1384 nv_adma_register_mode(qc->ap); 1386 nv_adma_register_mode(qc->ap);
1385 ata_qc_prep(qc); 1387 ata_qc_prep(qc);
1386 return; 1388 return;
@@ -1425,9 +1427,21 @@ static unsigned int nv_adma_qc_issue(struct ata_queued_cmd *qc)
1425 1427
1426 VPRINTK("ENTER\n"); 1428 VPRINTK("ENTER\n");
1427 1429
1430 /* We can't handle result taskfile with NCQ commands, since
1431 retrieving the taskfile switches us out of ADMA mode and would abort
1432 existing commands. */
1433 if (unlikely(qc->tf.protocol == ATA_PROT_NCQ &&
1434 (qc->flags & ATA_QCFLAG_RESULT_TF))) {
1435 ata_dev_printk(qc->dev, KERN_ERR,
1436 "NCQ w/ RESULT_TF not allowed\n");
1437 return AC_ERR_SYSTEM;
1438 }
1439
1428 if (nv_adma_use_reg_mode(qc)) { 1440 if (nv_adma_use_reg_mode(qc)) {
1429 /* use ATA register mode */ 1441 /* use ATA register mode */
1430 VPRINTK("using ATA register mode: 0x%lx\n", qc->flags); 1442 VPRINTK("using ATA register mode: 0x%lx\n", qc->flags);
1443 BUG_ON(!(pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE) &&
1444 (qc->flags & ATA_QCFLAG_DMAMAP));
1431 nv_adma_register_mode(qc->ap); 1445 nv_adma_register_mode(qc->ap);
1432 return ata_qc_issue_prot(qc); 1446 return ata_qc_issue_prot(qc);
1433 } else 1447 } else