Commit 83b72f1c authored by Robert Hancock's avatar Robert Hancock Committed by Greg Kroah-Hartman

sata_nv: delay on switching between NCQ and non-NCQ commands

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: default avatarRobert Hancock <hancockr@shaw.ca>
Cc: Chuck Ebbert <cebbert@redhat.com>
Signed-off-by: default avatarJeff Garzik <jeff@garzik.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent 9f6a92b4
...@@ -214,6 +214,7 @@ struct nv_adma_port_priv { ...@@ -214,6 +214,7 @@ struct nv_adma_port_priv {
struct nv_adma_prd *aprd; struct nv_adma_prd *aprd;
dma_addr_t aprd_dma; dma_addr_t aprd_dma;
u8 flags; u8 flags;
int last_issue_ncq;
}; };
#define NV_ADMA_CHECK_INTR(GCTL, PORT) ((GCTL) & ( 1 << (19 + (12 * (PORT))))) #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) ...@@ -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; struct nv_adma_port_priv *pp = qc->ap->private_data;
void __iomem *mmio = nv_adma_ctl_block(qc->ap); void __iomem *mmio = nv_adma_ctl_block(qc->ap);
int curr_ncq = (qc->tf.protocol == ATA_PROT_NCQ);
VPRINTK("ENTER\n"); VPRINTK("ENTER\n");
...@@ -1166,6 +1168,14 @@ static unsigned int nv_adma_qc_issue(struct ata_queued_cmd *qc) ...@@ -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 /* write append register, command tag in lower 8 bits
and (number of cpbs to append -1) in top 8 bits */ and (number of cpbs to append -1) in top 8 bits */
wmb(); 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); writew(qc->tag, mmio + NV_ADMA_APPEND);
DPRINTK("Issued tag %u\n",qc->tag); DPRINTK("Issued tag %u\n",qc->tag);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment