diff options
author | mav <mav@FreeBSD.org> | 2013-03-25 08:50:51 +0000 |
---|---|---|
committer | mav <mav@FreeBSD.org> | 2013-03-25 08:50:51 +0000 |
commit | a090de11fd9003922fb3a903397d2af1d45038f2 (patch) | |
tree | 47d40738cca91a93e261f93452a557bd494ea8aa | |
parent | 3d1df10de4fa0ec87eaef915c81375c95c7a174f (diff) | |
download | FreeBSD-src-a090de11fd9003922fb3a903397d2af1d45038f2.zip FreeBSD-src-a090de11fd9003922fb3a903397d2af1d45038f2.tar.gz |
Depending on combination of running commands (NCQ/non-NCQ) try to avoid
extra read from PxCI/PxSACT registers. If only NCQ commands are running, we
don't really need PxCI. If only non-NCQ commands are running we don't need
PxSACT. Mixed set may happen only on controllers with FIS-based switching
when port multiplier is attached, and then we have to read both registers.
MFC after: 1 month
-rw-r--r-- | sys/dev/ahci/ahci.c | 15 |
1 files changed, 10 insertions, 5 deletions
diff --git a/sys/dev/ahci/ahci.c b/sys/dev/ahci/ahci.c index 899712d..c39f974 100644 --- a/sys/dev/ahci/ahci.c +++ b/sys/dev/ahci/ahci.c @@ -1449,7 +1449,7 @@ ahci_ch_intr(void *data) { device_t dev = (device_t)data; struct ahci_channel *ch = device_get_softc(dev); - uint32_t istatus, sstatus, cstatus, serr = 0, sntf = 0, ok, err; + uint32_t istatus, cstatus, serr = 0, sntf = 0, ok, err; enum ahci_err_type et; int i, ccs, port, reset = 0; @@ -1459,8 +1459,13 @@ ahci_ch_intr(void *data) return; ATA_OUTL(ch->r_mem, AHCI_P_IS, istatus); /* Read command statuses. */ - sstatus = ATA_INL(ch->r_mem, AHCI_P_SACT); - cstatus = ATA_INL(ch->r_mem, AHCI_P_CI); + if (ch->numtslots != 0) + cstatus = ATA_INL(ch->r_mem, AHCI_P_SACT); + else + cstatus = 0; + if (ch->numrslots != ch->numtslots) + cstatus |= ATA_INL(ch->r_mem, AHCI_P_CI); + /* Read SNTF in one of possible ways. */ if (istatus & AHCI_P_IX_SDB) { if (ch->caps & AHCI_CAP_SSNTF) sntf = ATA_INL(ch->r_mem, AHCI_P_SNTF); @@ -1520,14 +1525,14 @@ ahci_ch_intr(void *data) } } } - err = ch->rslots & (cstatus | sstatus); + err = ch->rslots & cstatus; } else { ccs = 0; err = 0; port = -1; } /* Complete all successfull commands. */ - ok = ch->rslots & ~(cstatus | sstatus); + ok = ch->rslots & ~cstatus; for (i = 0; i < ch->numslots; i++) { if ((ok >> i) & 1) ahci_end_transaction(&ch->slot[i], AHCI_ERR_NONE); |