diff options
Diffstat (limited to 'sys/dev/pci/ahci.c')
-rw-r--r-- | sys/dev/pci/ahci.c | 22 |
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; |