summaryrefslogtreecommitdiff
path: root/sys/dev/pci/ahci.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/pci/ahci.c')
-rw-r--r--sys/dev/pci/ahci.c22
1 files changed, 15 insertions, 7 deletions
diff --git a/sys/dev/pci/ahci.c b/sys/dev/pci/ahci.c
index 299b387a026..a66c52663fd 100644
--- a/sys/dev/pci/ahci.c
+++ b/sys/dev/pci/ahci.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ahci.c,v 1.174 2011/04/07 15:30:16 miod Exp $ */
+/* $OpenBSD: ahci.c,v 1.175 2011/04/21 02:37:31 dlg Exp $ */
/*
* Copyright (c) 2006 David Gwynne <dlg@openbsd.org>
@@ -373,6 +373,7 @@ struct ahci_port {
TAILQ_HEAD(, ahci_ccb) ap_ccb_free;
TAILQ_HEAD(, ahci_ccb) ap_ccb_pending;
struct mutex ap_ccb_mtx;
+ struct ahci_ccb *ap_ccb_err;
u_int32_t ap_state;
#define AP_S_NORMAL 0
@@ -863,8 +864,7 @@ noccc:
aaa.aaa_methods = &ahci_atascsi_methods;
aaa.aaa_minphys = NULL;
aaa.aaa_nports = AHCI_MAX_PORTS;
- aaa.aaa_ncmds = sc->sc_ncmds;
- aaa.aaa_capability = ASAA_CAP_NEEDS_RESERVED;
+ aaa.aaa_ncmds = sc->sc_ncmds - 1;
if (!(sc->sc_flags & AHCI_F_NO_NCQ) &&
(sc->sc_cap & AHCI_REG_CAP_SNCQ)) {
aaa.aaa_capability |= ASAA_CAP_NCQ | ASAA_CAP_PMP_NCQ;
@@ -1292,6 +1292,10 @@ nomem:
ahci_enable_interrupts(ap);
+ /* grab a ccb for use during error recovery */
+ ap->ap_ccb_err = &ap->ap_ccbs[sc->sc_ncmds - 1];
+ TAILQ_REMOVE(&ap->ap_ccb_free, ap->ap_ccb_err, ccb_entry);
+
freeport:
if (rc != 0)
ahci_port_free(sc, port);
@@ -1313,6 +1317,9 @@ ahci_port_free(struct ahci_softc *sc, u_int port)
ahci_write(sc, AHCI_REG_IS, 1 << port);
}
+ if (ap->ap_ccb_err)
+ ahci_put_ccb(ap->ap_ccb_err);
+
if (ap->ap_ccbs) {
while ((ccb = ahci_get_ccb(ap)) != NULL)
bus_dmamap_destroy(sc->sc_dmat, ccb->ccb_dmamap);
@@ -3012,12 +3019,11 @@ ahci_get_err_ccb(struct ahci_port *ap)
* Grab a CCB to use for error recovery. This should never fail, as
* we ask atascsi to reserve one for us at init time.
*/
- err_ccb = ahci_get_ccb(ap);
- KASSERT(err_ccb != NULL);
+ err_ccb = ap->ap_ccb_err;
err_ccb->ccb_xa.flags = 0;
err_ccb->ccb_done = ahci_empty_done;
- return err_ccb;
+ return (err_ccb);
}
void
@@ -3037,8 +3043,10 @@ ahci_put_err_ccb(struct ahci_ccb *ccb)
printf("ahci_port_err_ccb_restore but SACT %08x != 0?\n", sact);
KASSERT(ahci_pread(ap, AHCI_PREG_CI) == 0);
+#ifdef DIAGNOSTIC
/* Done with the CCB */
- ahci_put_ccb(ccb);
+ KASSERT(ccb == ap->ap_ccb_err);
+#endif
/* Restore outstanding command state */
ap->ap_sactive = ap->ap_err_saved_sactive;