summaryrefslogtreecommitdiffstats
path: root/sys/dev/ahci/ahci.c
diff options
context:
space:
mode:
authormav <mav@FreeBSD.org>2017-02-08 16:07:59 +0000
committermav <mav@FreeBSD.org>2017-02-08 16:07:59 +0000
commitfebf34e08cb22a28a9caf6ae59e2c433a9640e60 (patch)
tree41ccfb3029b8c84d3afa5bed12167c45141e73f1 /sys/dev/ahci/ahci.c
parentd24939b123c155083b8d3035f7bc752b09f0ff67 (diff)
downloadFreeBSD-src-febf34e08cb22a28a9caf6ae59e2c433a9640e60.zip
FreeBSD-src-febf34e08cb22a28a9caf6ae59e2c433a9640e60.tar.gz
MFC r312767: Partially workaround ASMedia HBA error recovery.
Taking closer look on my ASM1062 I found that it has bunch of issues around error recovery: reported wrong CCS, failed commands reported as completed, READ LOG EXT times out after NCQ error. This patch workarounds first two problems, that were making ATAPI devices close to unusable on these HBAs.
Diffstat (limited to 'sys/dev/ahci/ahci.c')
-rw-r--r--sys/dev/ahci/ahci.c17
1 files changed, 14 insertions, 3 deletions
diff --git a/sys/dev/ahci/ahci.c b/sys/dev/ahci/ahci.c
index f8807e7..a9061bc 100644
--- a/sys/dev/ahci/ahci.c
+++ b/sys/dev/ahci/ahci.c
@@ -711,7 +711,7 @@ ahci_ch_attach(device_t dev)
/* Construct SIM entry */
ch->sim = cam_sim_alloc(ahciaction, ahcipoll, "ahcich", ch,
device_get_unit(dev), (struct mtx *)&ch->mtx,
- min(2, ch->numslots),
+ (ch->quirks & AHCI_Q_NOCCS) ? 1 : min(2, ch->numslots),
(ch->caps & AHCI_CAP_SNCQ) ? ch->numslots : 0,
devq);
if (ch->sim == NULL) {
@@ -1224,8 +1224,19 @@ ahci_ch_intr_main(struct ahci_channel *ch, uint32_t istatus)
/* Process command errors */
if (istatus & (AHCI_P_IX_OF | AHCI_P_IX_IF |
AHCI_P_IX_HBD | AHCI_P_IX_HBF | AHCI_P_IX_TFE)) {
- ccs = (ATA_INL(ch->r_mem, AHCI_P_CMD) & AHCI_P_CMD_CCS_MASK)
- >> AHCI_P_CMD_CCS_SHIFT;
+ if (ch->quirks & AHCI_Q_NOCCS) {
+ /*
+ * ASMedia chips sometimes report failed commands as
+ * completed. Count all running commands as failed.
+ */
+ cstatus |= ch->rslots;
+
+ /* They also report wrong CCS, so try to guess one. */
+ ccs = powerof2(cstatus) ? ffs(cstatus) - 1 : -1;
+ } else {
+ ccs = (ATA_INL(ch->r_mem, AHCI_P_CMD) &
+ AHCI_P_CMD_CCS_MASK) >> AHCI_P_CMD_CCS_SHIFT;
+ }
//device_printf(dev, "%s ERROR is %08x cs %08x ss %08x rs %08x tfd %02x serr %08x fbs %08x ccs %d\n",
// __func__, istatus, cstatus, sstatus, ch->rslots, ATA_INL(ch->r_mem, AHCI_P_TFD),
// serr, ATA_INL(ch->r_mem, AHCI_P_FBS), ccs);
OpenPOWER on IntegriCloud