since atascsi screws it up... Index: ahci.c =================================================================== RCS file: /cvs/src/sys/dev/pci/ahci.c,v retrieving revision 1.174 diff -u -p -r1.174 ahci.c --- ahci.c 7 Apr 2011 15:30:16 -0000 1.174 +++ ahci.c 18 Apr 2011 01:39:19 -0000 @@ -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_ 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;