diff options
author | Shane Huang <shane.huang@amd.com> | 2010-03-16 06:08:55 -0400 |
---|---|---|
committer | Jeff Garzik <jgarzik@redhat.com> | 2010-03-17 15:54:55 -0400 |
commit | 5db5b0215af94a36d4bf10900ff9707b6d5c1610 (patch) | |
tree | 282907c4f5cc0b9193f2c863351f025f3bc1d1a1 /drivers | |
parent | 9deb343189b3cf45e84dd08480f330575ffe2004 (diff) |
ahci: pp->active_link is not reliable when FBS is enabled
pp->active_link is not reliable when FBS is enabled.
Both PORT_SCR_ACT and PORT_CMD_ISSUE should be checked
because mixed NCQ and non-NCQ commands may be in flight.
Signed-off-by: Shane Huang <shane.huang@amd.com>
Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/ata/ahci.c | 23 |
1 files changed, 17 insertions, 6 deletions
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index e7e2c7a147f1..fdc9bcbe55a2 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c | |||
@@ -2278,7 +2278,7 @@ static void ahci_port_intr(struct ata_port *ap) | |||
2278 | struct ahci_port_priv *pp = ap->private_data; | 2278 | struct ahci_port_priv *pp = ap->private_data; |
2279 | struct ahci_host_priv *hpriv = ap->host->private_data; | 2279 | struct ahci_host_priv *hpriv = ap->host->private_data; |
2280 | int resetting = !!(ap->pflags & ATA_PFLAG_RESETTING); | 2280 | int resetting = !!(ap->pflags & ATA_PFLAG_RESETTING); |
2281 | u32 status, qc_active; | 2281 | u32 status, qc_active = 0; |
2282 | int rc; | 2282 | int rc; |
2283 | 2283 | ||
2284 | status = readl(port_mmio + PORT_IRQ_STAT); | 2284 | status = readl(port_mmio + PORT_IRQ_STAT); |
@@ -2336,11 +2336,22 @@ static void ahci_port_intr(struct ata_port *ap) | |||
2336 | } | 2336 | } |
2337 | } | 2337 | } |
2338 | 2338 | ||
2339 | /* pp->active_link is valid iff any command is in flight */ | 2339 | /* pp->active_link is not reliable once FBS is enabled, both |
2340 | if (ap->qc_active && pp->active_link->sactive) | 2340 | * PORT_SCR_ACT and PORT_CMD_ISSUE should be checked because |
2341 | qc_active = readl(port_mmio + PORT_SCR_ACT); | 2341 | * NCQ and non-NCQ commands may be in flight at the same time. |
2342 | else | 2342 | */ |
2343 | qc_active = readl(port_mmio + PORT_CMD_ISSUE); | 2343 | if (pp->fbs_enabled) { |
2344 | if (ap->qc_active) { | ||
2345 | qc_active = readl(port_mmio + PORT_SCR_ACT); | ||
2346 | qc_active |= readl(port_mmio + PORT_CMD_ISSUE); | ||
2347 | } | ||
2348 | } else { | ||
2349 | /* pp->active_link is valid iff any command is in flight */ | ||
2350 | if (ap->qc_active && pp->active_link->sactive) | ||
2351 | qc_active = readl(port_mmio + PORT_SCR_ACT); | ||
2352 | else | ||
2353 | qc_active = readl(port_mmio + PORT_CMD_ISSUE); | ||
2354 | } | ||
2344 | 2355 | ||
2345 | rc = ata_qc_complete_multiple(ap, qc_active); | 2356 | rc = ata_qc_complete_multiple(ap, qc_active); |
2346 | 2357 | ||