sata_nv: use ADMA for NODATA commands
[powerpc.git] / drivers / ata / sata_nv.c
index 3dd5ca1..19817b3 100644 (file)
@@ -1159,16 +1159,31 @@ static void nv_adma_fill_sg(struct ata_queued_cmd *qc, struct nv_adma_cpb *cpb)
                cpb->next_aprd = cpu_to_le64(((u64)(pp->aprd_dma + NV_ADMA_SGTBL_SZ * qc->tag)));
 }
 
+static int nv_adma_use_reg_mode(struct ata_queued_cmd *qc)
+{
+       struct nv_adma_port_priv *pp = qc->ap->private_data;
+
+       /* ADMA engine can only be used for non-ATAPI DMA commands,
+          or interrupt-driven no-data commands. */
+       if((pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE) ||
+          (qc->tf.flags & ATA_TFLAG_POLLING))
+               return 1;
+
+       if((qc->flags & ATA_QCFLAG_DMAMAP) ||
+          (qc->tf.protocol == ATA_PROT_NODATA))
+               return 0;
+
+       return 1;
+}
+
 static void nv_adma_qc_prep(struct ata_queued_cmd *qc)
 {
        struct nv_adma_port_priv *pp = qc->ap->private_data;
        struct nv_adma_cpb *cpb = &pp->cpb[qc->tag];
        u8 ctl_flags = NV_CPB_CTL_CPB_VALID |
-                      NV_CPB_CTL_APRD_VALID |
                       NV_CPB_CTL_IEN;
 
-       if (!(qc->flags & ATA_QCFLAG_DMAMAP) ||
-            (pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE)) {
+       if (nv_adma_use_reg_mode(qc)) {
                nv_adma_register_mode(qc->ap);
                ata_qc_prep(qc);
                return;
@@ -1188,7 +1203,11 @@ static void nv_adma_qc_prep(struct ata_queued_cmd *qc)
 
        nv_adma_tf_to_cpb(&qc->tf, cpb->tf);
 
-       nv_adma_fill_sg(qc, cpb);
+       if(qc->flags & ATA_QCFLAG_DMAMAP) {
+               nv_adma_fill_sg(qc, cpb);
+               ctl_flags |= NV_CPB_CTL_APRD_VALID;
+       } else
+               memset(&cpb->aprd[0], 0, sizeof(struct nv_adma_prd) * 5);
 
        /* Be paranoid and don't let the device see NV_CPB_CTL_CPB_VALID until we are
           finished filling in all of the contents */
@@ -1203,10 +1222,9 @@ static unsigned int nv_adma_qc_issue(struct ata_queued_cmd *qc)
 
        VPRINTK("ENTER\n");
 
-       if (!(qc->flags & ATA_QCFLAG_DMAMAP) ||
-            (pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE)) {
+       if (nv_adma_use_reg_mode(qc)) {
                /* use ATA register mode */
-               VPRINTK("no dmamap or ATAPI, using ATA register mode: 0x%lx\n", qc->flags);
+               VPRINTK("using ATA register mode: 0x%lx\n", qc->flags);
                nv_adma_register_mode(qc->ap);
                return ata_qc_issue_prot(qc);
        } else