]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
sata_nv: delay on switching between NCQ and non-NCQ commands
authorRobert Hancock <hancockr@shaw.ca>
Thu, 22 Mar 2007 16:39:04 +0000 (12:39 -0400)
committerGreg Kroah-Hartman <gregkh@suse.de>
Fri, 6 Apr 2007 10:43:11 +0000 (03:43 -0700)
sata_nv: delay on switching between NCQ and non-NCQ commands

This patch appears to solve some problems with commands timing out in
cases where an NCQ command is immediately followed by a non-NCQ command
(or possibly vice versa). This is a rather ugly solution, but until we
know more about why this is needed, this is about all we can do.

[backport to 2.6.20 by Chuck Ebbert <cebbert@redhat.com>]

Signed-off-by: Robert Hancock <hancockr@shaw.ca>
Cc: Chuck Ebbert <cebbert@redhat.com>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/ata/sata_nv.c

index f7a963eb1f028ea77a7ce4576d64c3c595faa574..91f24b1a2dc3419db10f9d73842a94a6141d190a 100644 (file)
@@ -214,6 +214,7 @@ struct nv_adma_port_priv {
        struct nv_adma_prd      *aprd;
        dma_addr_t              aprd_dma;
        u8                      flags;
+       int                     last_issue_ncq;
 };
 
 #define NV_ADMA_CHECK_INTR(GCTL, PORT) ((GCTL) & ( 1 << (19 + (12 * (PORT)))))
@@ -1151,6 +1152,7 @@ static unsigned int nv_adma_qc_issue(struct ata_queued_cmd *qc)
 {
        struct nv_adma_port_priv *pp = qc->ap->private_data;
        void __iomem *mmio = nv_adma_ctl_block(qc->ap);
+       int curr_ncq = (qc->tf.protocol == ATA_PROT_NCQ);
 
        VPRINTK("ENTER\n");
 
@@ -1166,6 +1168,14 @@ static unsigned int nv_adma_qc_issue(struct ata_queued_cmd *qc)
        /* write append register, command tag in lower 8 bits
           and (number of cpbs to append -1) in top 8 bits */
        wmb();
+
+       if(curr_ncq != pp->last_issue_ncq) {
+               /* Seems to need some delay before switching between NCQ and non-NCQ
+                  commands, else we get command timeouts and such. */
+               udelay(20);
+               pp->last_issue_ncq = curr_ncq;
+       }
+
        writew(qc->tag, mmio + NV_ADMA_APPEND);
 
        DPRINTK("Issued tag %u\n",qc->tag);