summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Hancock <hancockr@shaw.ca>2007-02-19 18:42:30 -0600
committerJeff Garzik <jeff@garzik.org>2007-02-21 04:58:18 -0500
commit5e5c74a5e11d1e2a99d03132cc6c4455016db6c2 (patch)
tree7de25ad9b898e9fea72cecd8cdf9916de2c5a090
parentcc0759103ff00c3dfc459059af4a1cfb0e865841 (diff)
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. Signed-off-by: Robert Hancock <hancockr@shaw.ca> Signed-off-by: Jeff Garzik <jeff@garzik.org>
-rw-r--r--drivers/ata/sata_nv.c10
1 files changed, 10 insertions, 0 deletions
diff --git a/drivers/ata/sata_nv.c b/drivers/ata/sata_nv.c
index f1fea96e90bd..b93e64d3fcf1 100644
--- a/drivers/ata/sata_nv.c
+++ b/drivers/ata/sata_nv.c
@@ -219,6 +219,7 @@ struct nv_adma_port_priv {
void __iomem * gen_block;
void __iomem * notifier_clear_block;
u8 flags;
+ int last_issue_ncq;
};
struct nv_host_priv {
@@ -1260,6 +1261,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 = pp->ctl_block;
+ int curr_ncq = (qc->tf.protocol == ATA_PROT_NCQ);
VPRINTK("ENTER\n");
@@ -1274,6 +1276,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);