summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordlg <dlg@openbsd.org>2011-04-21 02:37:31 +0000
committerdlg <dlg@openbsd.org>2011-04-21 02:37:31 +0000
commit4c9a7c095b8b4805e34205df74795b0412eb60d0 (patch)
tree29096461918354041a4c536684a4100e539458b0
parentfind: return exit code 1 if any path could not be traversed (diff)
downloadwireguard-openbsd-4c9a7c095b8b4805e34205df74795b0412eb60d0.tar.xz
wireguard-openbsd-4c9a7c095b8b4805e34205df74795b0412eb60d0.zip
ahci asks atascsi to reserve a ccb to use for error handling, but then
atascsi goes and throws away all the ccbs that the disk wont use, including the reserved one. this makes ahci reserve its own ccb. light testing by krw@ without regression.
-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;