Module Name: src Committed By: jdolecek Date: Mon Apr 10 22:57:03 UTC 2017
Modified Files: src/sys/dev/ata [jdolecek-ncq]: ata.c ata_wdc.c atavar.h src/sys/dev/ic [jdolecek-ncq]: ahcisata_core.c mvsata.c siisata.c wdc.c src/sys/dev/pci [jdolecek-ncq]: artsata.c cmdide.c cypide.c pciide_common.c pdcsata.c satalink.c viaide.c src/sys/dev/scsipi [jdolecek-ncq]: atapi_wdc.c Log Message: ATA infrastructure improvements to eventually support more outstanding commands patch by Matt Thomas To generate a diff of this commit: cvs rdiff -u -r1.132 -r1.132.8.1 src/sys/dev/ata/ata.c cvs rdiff -u -r1.105 -r1.105.6.1 src/sys/dev/ata/ata_wdc.c cvs rdiff -u -r1.92 -r1.92.8.1 src/sys/dev/ata/atavar.h cvs rdiff -u -r1.57 -r1.57.6.1 src/sys/dev/ic/ahcisata_core.c cvs rdiff -u -r1.35 -r1.35.6.1 src/sys/dev/ic/mvsata.c cvs rdiff -u -r1.30 -r1.30.4.1 src/sys/dev/ic/siisata.c cvs rdiff -u -r1.283 -r1.283.2.1 src/sys/dev/ic/wdc.c cvs rdiff -u -r1.26 -r1.26.18.1 src/sys/dev/pci/artsata.c cvs rdiff -u -r1.38 -r1.38.28.1 src/sys/dev/pci/cmdide.c cvs rdiff -u -r1.30 -r1.30.18.1 src/sys/dev/pci/cypide.c cvs rdiff -u -r1.62 -r1.62.4.1 src/sys/dev/pci/pciide_common.c cvs rdiff -u -r1.27 -r1.27.18.1 src/sys/dev/pci/pdcsata.c cvs rdiff -u -r1.53 -r1.53.4.1 src/sys/dev/pci/satalink.c cvs rdiff -u -r1.84 -r1.84.18.1 src/sys/dev/pci/viaide.c cvs rdiff -u -r1.123 -r1.123.4.1 src/sys/dev/scsipi/atapi_wdc.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/dev/ata/ata.c diff -u src/sys/dev/ata/ata.c:1.132 src/sys/dev/ata/ata.c:1.132.8.1 --- src/sys/dev/ata/ata.c:1.132 Wed Sep 10 07:04:48 2014 +++ src/sys/dev/ata/ata.c Mon Apr 10 22:57:02 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: ata.c,v 1.132 2014/09/10 07:04:48 matt Exp $ */ +/* $NetBSD: ata.c,v 1.132.8.1 2017/04/10 22:57:02 jdolecek Exp $ */ /* * Copyright (c) 1998, 2001 Manuel Bouyer. All rights reserved. @@ -25,7 +25,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ata.c,v 1.132 2014/09/10 07:04:48 matt Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ata.c,v 1.132.8.1 2017/04/10 22:57:02 jdolecek Exp $"); #include "opt_ata.h" @@ -180,6 +180,56 @@ ataprint(void *aux, const char *pnp) return (UNCONF); } +static void +ata_queue_reset(struct ata_queue *chq) +{ + /* make sure that we can use polled commands */ + TAILQ_INIT(&chq->queue_xfer); + chq->queue_freeze = 0; + chq->queue_active = 0; + for (u_int i = 0; i < chq->queue_openings; i++) { + chq->active_xfers[0] = NULL; + } +} + +struct ata_xfer * +ata_queue_hwslot_to_xfer(struct ata_queue *chq, int hwslot) +{ + KASSERT(hwslot < chq->queue_openings); + if (chq->queue_openings == 1) { + struct ata_xfer *xfer = chq->active_xfers[0]; + KASSERT(xfer == NULL || xfer->c_hwslot == hwslot); + return xfer; + } + for (u_int i = 0; i < chq->queue_openings; i++) { + struct ata_xfer *xfer = chq->active_xfers[i]; + if (xfer != NULL && xfer->c_hwslot == hwslot) { + return xfer; + } + } + return NULL; +} + +struct ata_queue * +ata_queue_alloc(int openings) +{ + if (openings == 0) + openings = 1; + struct ata_queue *chq = malloc(offsetof(struct ata_queue, active_xfers[openings]), + M_DEVBUF, M_WAITOK); + if (chq != NULL) { + chq->queue_openings = openings; + ata_queue_reset(chq); + } + return chq; +} + +void +ata_queue_free(struct ata_queue *chq) +{ + free(chq, M_DEVBUF); +} + /* * ata_channel_attach: * @@ -188,6 +238,7 @@ ataprint(void *aux, const char *pnp) void ata_channel_attach(struct ata_channel *chp) { + struct ata_queue * const chq = chp->ch_queue; if (chp->ch_flags & ATACH_DISABLED) return; @@ -195,10 +246,9 @@ ata_channel_attach(struct ata_channel *c /* XXX callout_destroy */ callout_init(&chp->ch_callout, 0); - TAILQ_INIT(&chp->ch_queue->queue_xfer); - chp->ch_queue->queue_freeze = 0; - chp->ch_queue->queue_flags = 0; - chp->ch_queue->active_xfer = NULL; + chq->queue_openings = 1; /* XXX */ + + ata_queue_reset(chq); chp->atabus = config_found_ia(chp->ch_atac->atac_dev, "ata", chp, atabusprint); @@ -350,7 +400,7 @@ atabusconfig_thread(void *arg) memset(&adev, 0, sizeof(struct ata_device)); adev.adev_bustype = atac->atac_bustype_ata; adev.adev_channel = chp->ch_channel; - adev.adev_openings = 1; + adev.adev_openings = chp->ch_queue->queue_openings; adev.adev_drv_data = &chp->ch_drive[i]; chp->ch_drive[i].drv_softc = config_found_ia(atabus_sc->sc_dev, "ata_hl", &adev, ataprint); @@ -418,6 +468,7 @@ atabus_thread(void *arg) { struct atabus_softc *sc = arg; struct ata_channel *chp = sc->sc_chan; + struct ata_queue *chq = chp->ch_queue; struct ata_xfer *xfer; int i, s; @@ -442,8 +493,7 @@ atabus_thread(void *arg) s = splbio(); for (;;) { if ((chp->ch_flags & (ATACH_TH_RESET | ATACH_SHUTDOWN)) == 0 && - (chp->ch_queue->active_xfer == NULL || - chp->ch_queue->queue_freeze == 0)) { + (chq->queue_active == 0 || chq->queue_freeze == 0)) { chp->ch_flags &= ~ATACH_TH_RUN; (void) tsleep(&chp->ch_thread, PRIBIO, "atath", 0); chp->ch_flags |= ATACH_TH_RUN; @@ -460,18 +510,22 @@ atabus_thread(void *arg) * ata_reset_channel() will freeze 2 times, so * unfreeze one time. Not a problem as we're at splbio */ - chp->ch_queue->queue_freeze--; + chq->queue_freeze--; ata_reset_channel(chp, AT_WAIT | chp->ch_reset_flags); - } else if (chp->ch_queue->active_xfer != NULL && - chp->ch_queue->queue_freeze == 1) { + } else if (chq->queue_active > 0 && chq->queue_freeze == 1) { /* * Caller has bumped queue_freeze, decrease it. */ - chp->ch_queue->queue_freeze--; - xfer = chp->ch_queue->active_xfer; - KASSERT(xfer != NULL); - (*xfer->c_start)(xfer->c_chp, xfer); - } else if (chp->ch_queue->queue_freeze > 1) + chq->queue_freeze--; + u_int active __diagused = 0; + for (i = 0; i < chq->queue_openings; i++) { + if ((xfer = chq->active_xfers[i]) != NULL) { + (*xfer->c_start)(xfer->c_chp, xfer); + active++; + } + } + KASSERT(active == chq->queue_active); + } else if (chq->queue_freeze > 1) panic("ata_thread: queue_freeze"); } splx(s); @@ -884,7 +938,7 @@ ata_queue_idle(struct ata_queue *queue) { int s = splbio(); queue->queue_freeze++; - while (queue->active_xfer != NULL) { + while (queue->queue_active > 0) { queue->queue_flags |= QF_IDLE_WAIT; tsleep(&queue->queue_flags, PRIBIO, "qidl", 0); } @@ -905,16 +959,18 @@ ata_exec_xfer(struct ata_channel *chp, s /* complete xfer setup */ xfer->c_chp = chp; + xfer->c_slot = 0; /* insert at the end of command list */ TAILQ_INSERT_TAIL(&chp->ch_queue->queue_xfer, xfer, c_xferchain); ATADEBUG_PRINT(("atastart from ata_exec_xfer, flags 0x%x\n", chp->ch_flags), DEBUG_XFERS); + /* * if polling and can sleep, wait for the xfer to be at head of queue */ if ((xfer->c_flags & (C_POLL | C_WAIT)) == (C_POLL | C_WAIT)) { - while (chp->ch_queue->active_xfer != NULL || + while (chp->ch_queue->queue_active > 0 || TAILQ_FIRST(&chp->ch_queue->queue_xfer) != xfer) { xfer->c_flags |= C_WAITACT; tsleep(xfer, PRIBIO, "ataact", 0); @@ -939,6 +995,7 @@ void atastart(struct ata_channel *chp) { struct atac_softc *atac = chp->ch_atac; + struct ata_queue *chq = chp->ch_queue; struct ata_xfer *xfer; #ifdef ATA_DEBUG @@ -954,23 +1011,31 @@ atastart(struct ata_channel *chp) splx(spl1); #endif /* ATA_DEBUG */ + if (chq->queue_active == chq->queue_openings) { + return; /* channel completely busy */ + } + + /* is the queue frozen? */ + if (__predict_false(chq->queue_freeze > 0)) { + if (chq->queue_flags & QF_IDLE_WAIT) { + chq->queue_flags &= ~QF_IDLE_WAIT; + wakeup(&chq->queue_flags); + } + return; /* queue frozen */ + } + /* is there a xfer ? */ if ((xfer = TAILQ_FIRST(&chp->ch_queue->queue_xfer)) == NULL) return; + KASSERT(chp->ch_ndrives == 1 || chq->queue_openings == 1); + /* adjust chp, in case we have a shared queue */ chp = xfer->c_chp; + KASSERT(chp->ch_queue == chq); + + struct ata_drive_datas * const drvp = &chp->ch_drive[xfer->c_drive]; - if (chp->ch_queue->active_xfer != NULL) { - return; /* channel aleady active */ - } - if (__predict_false(chp->ch_queue->queue_freeze > 0)) { - if (chp->ch_queue->queue_flags & QF_IDLE_WAIT) { - chp->ch_queue->queue_flags &= ~QF_IDLE_WAIT; - wakeup(&chp->ch_queue->queue_flags); - } - return; /* queue frozen */ - } /* * if someone is waiting for the command to be active, wake it up * and let it process the command @@ -986,18 +1051,31 @@ atastart(struct ata_channel *chp) if ((chp->ch_flags & ATACH_IRQ_WAIT) != 0) panic("atastart: channel waiting for irq"); #endif - if (atac->atac_claim_hw) + if (atac->atac_claim_hw) { if (!(*atac->atac_claim_hw)(chp, 0)) return; + } ATADEBUG_PRINT(("atastart: xfer %p channel %d drive %d\n", xfer, chp->ch_channel, xfer->c_drive), DEBUG_XFERS); - if (chp->ch_drive[xfer->c_drive].drive_flags & ATA_DRIVE_RESET) { - chp->ch_drive[xfer->c_drive].drive_flags &= ~ATA_DRIVE_RESET; - chp->ch_drive[xfer->c_drive].state = 0; + if (drvp->drive_flags & ATA_DRIVE_RESET) { + drvp->drive_flags &= ~ATA_DRIVE_RESET; + drvp->state = 0; + } + + if (chq->queue_openings == 1) { + xfer->c_slot = 0; + xfer->c_hwslot = 0; + } else { + for (u_int slot = 0; slot < chq->queue_openings; slot++) { + if (chq->active_xfers[slot] == NULL) { + xfer->c_slot = slot; + xfer->c_hwslot = slot; + break; + } + } } - chp->ch_queue->active_xfer = xfer; - TAILQ_REMOVE(&chp->ch_queue->queue_xfer, xfer, c_xferchain); + ata_activate_xfer(chp, xfer); if (atac->atac_cap & ATAC_CAP_NOIRQ) KASSERT(xfer->c_flags & C_POLL); @@ -1018,6 +1096,7 @@ ata_get_xfer(int flags) if (xfer != NULL) { memset(xfer, 0, sizeof(struct ata_xfer)); } + xfer->c_slot = -1; return xfer; } @@ -1052,6 +1131,82 @@ ata_free_xfer(struct ata_channel *chp, s splx(s); } +void +ata_activate_xfer(struct ata_channel *chp, struct ata_xfer *xfer) +{ + struct ata_queue * const chq = chp->ch_queue; + + KASSERT(xfer->c_slot >= 0); + KASSERT(chq->queue_active < chq->queue_openings); + KASSERT(chq->active_xfers[xfer->c_slot] == NULL); + + TAILQ_REMOVE(&chq->queue_xfer, xfer, c_xferchain); + + chq->active_xfers[xfer->c_slot] = xfer; + chq->queue_active++; +} + +void +ata_deactivate_xfer(struct ata_channel *chp, struct ata_xfer *xfer) +{ + struct ata_queue * const chq = chp->ch_queue; + + KASSERT(xfer->c_slot >= 0); + KASSERT(chq->queue_active > 0); + KASSERT(chq->active_xfers[xfer->c_slot] == xfer); + + //if ((xfer->c_flags & C_TIMEOU) == 0) + callout_stop(&chp->ch_callout); + + chq->active_xfers[xfer->c_slot] = NULL; + chq->queue_active--; + + xfer->c_slot = -1; +} + + +bool +ata_waitdrain_check(struct ata_channel *chp, int drive) +{ + if (chp->ch_drive[drive].drive_flags & ATA_DRIVE_WAITDRAIN) { + chp->ch_drive[drive].drive_flags &= ~ATA_DRIVE_WAITDRAIN; + wakeup(chp->ch_queue->active_xfers); + return true; + } + return false; +} + +bool +ata_waitdrain_xfer_check(struct ata_channel *chp, struct ata_xfer *xfer) +{ + int drive = xfer->c_drive; + if (chp->ch_drive[drive].drive_flags & ATA_DRIVE_WAITDRAIN) { + (*xfer->c_kill_xfer)(chp, xfer, KILL_GONE); + chp->ch_drive[drive].drive_flags &= ~ATA_DRIVE_WAITDRAIN; + wakeup(chp->ch_queue->active_xfers); + return true; + } + return false; +} + +/* + * Kill off all active xfers for a ata_channel. + * + * Must be called at splbio(). + */ +void +ata_kill_active(struct ata_channel *chp, int reason) +{ + struct ata_queue * const chq = chp->ch_queue; + for (u_int i = 0; + chq->queue_active > 0 && i < chq->queue_openings; i++) { + struct ata_xfer *xfer = chq->active_xfers[i]; + if (xfer != NULL) { + (*xfer->c_kill_xfer)(xfer->c_chp, xfer, reason); + } + } +} + /* * Kill off all pending xfers for a ata_channel. * @@ -1060,28 +1215,28 @@ ata_free_xfer(struct ata_channel *chp, s void ata_kill_pending(struct ata_drive_datas *drvp) { - struct ata_channel *chp = drvp->chnl_softc; + struct ata_channel * const chp = drvp->chnl_softc; + struct ata_queue * const chq = chp->ch_queue; struct ata_xfer *xfer, *next_xfer; int s = splbio(); - for (xfer = TAILQ_FIRST(&chp->ch_queue->queue_xfer); + for (xfer = TAILQ_FIRST(&chq->queue_xfer); xfer != NULL; xfer = next_xfer) { next_xfer = TAILQ_NEXT(xfer, c_xferchain); if (xfer->c_chp != chp || xfer->c_drive != drvp->drive) continue; - TAILQ_REMOVE(&chp->ch_queue->queue_xfer, xfer, c_xferchain); + TAILQ_REMOVE(&chq->queue_xfer, xfer, c_xferchain); (*xfer->c_kill_xfer)(chp, xfer, KILL_GONE); } - while ((xfer = chp->ch_queue->active_xfer) != NULL) { - if (xfer->c_chp == chp && xfer->c_drive == drvp->drive) { - drvp->drive_flags |= ATA_DRIVE_WAITDRAIN; - (void) tsleep(&chp->ch_queue->active_xfer, - PRIBIO, "atdrn", 0); - } else { - /* no more xfer for us */ - break; + while (chq->queue_active > 0) { + if (chq->queue_openings == 1 && chp->ch_ndrives > 1) { + xfer = chq->active_xfers[0]; + if (xfer->c_chp != chp || xfer->c_drive != drvp->drive) + break; } + drvp->drive_flags |= ATA_DRIVE_WAITDRAIN; + (void) tsleep(&chq->active_xfers[0], PRIBIO, "atdrn", 0); } splx(s); } @@ -1144,9 +1299,7 @@ ata_reset_channel(struct ata_channel *ch atastart(chp); } else { /* make sure that we can use polled commands */ - TAILQ_INIT(&chp->ch_queue->queue_xfer); - chp->ch_queue->queue_freeze = 0; - chp->ch_queue->active_xfer = NULL; + ata_queue_reset(chp->ch_queue); } } Index: src/sys/dev/ata/ata_wdc.c diff -u src/sys/dev/ata/ata_wdc.c:1.105 src/sys/dev/ata/ata_wdc.c:1.105.6.1 --- src/sys/dev/ata/ata_wdc.c:1.105 Fri Jan 2 19:42:06 2015 +++ src/sys/dev/ata/ata_wdc.c Mon Apr 10 22:57:02 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: ata_wdc.c,v 1.105 2015/01/02 19:42:06 christos Exp $ */ +/* $NetBSD: ata_wdc.c,v 1.105.6.1 2017/04/10 22:57:02 jdolecek Exp $ */ /* * Copyright (c) 1998, 2001, 2003 Manuel Bouyer. @@ -54,7 +54,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ata_wdc.c,v 1.105 2015/01/02 19:42:06 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ata_wdc.c,v 1.105.6.1 2017/04/10 22:57:02 jdolecek Exp $"); #include "opt_ata.h" #include "opt_wdc.h" @@ -808,13 +808,11 @@ wdc_ata_bio_done(struct ata_channel *chp ata_bio->bcount = xfer->c_bcount; /* mark controller inactive and free xfer */ - chp->ch_queue->active_xfer = NULL; + ata_deactivate_xfer(chp, xfer); ata_free_xfer(chp, xfer); - if (chp->ch_drive[drive].drive_flags & ATA_DRIVE_WAITDRAIN) { + if (ata_waitdrain_check(chp, drive)) { ata_bio->error = ERR_NODEV; - chp->ch_drive[drive].drive_flags &= ~ATA_DRIVE_WAITDRAIN; - wakeup(&chp->ch_queue->active_xfer); } ata_bio->flags |= ATA_ITSDONE; ATADEBUG_PRINT(("wdc_ata_done: drv_done\n"), DEBUG_XFERS); Index: src/sys/dev/ata/atavar.h diff -u src/sys/dev/ata/atavar.h:1.92 src/sys/dev/ata/atavar.h:1.92.8.1 --- src/sys/dev/ata/atavar.h:1.92 Wed Sep 10 07:04:48 2014 +++ src/sys/dev/ata/atavar.h Mon Apr 10 22:57:02 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: atavar.h,v 1.92 2014/09/10 07:04:48 matt Exp $ */ +/* $NetBSD: atavar.h,v 1.92.8.1 2017/04/10 22:57:02 jdolecek Exp $ */ /* * Copyright (c) 1998, 2001 Manuel Bouyer. @@ -45,7 +45,9 @@ struct ata_xfer { /* Channel and drive that are to process the request. */ struct ata_channel *c_chp; - int c_drive; + uint16_t c_drive; + int8_t c_slot; /* queue slot # */ + uint8_t c_hwslot; /* hardware slot # */ void *c_cmd; /* private request structure pointer */ void *c_databuf; /* pointer to data buffer */ @@ -81,9 +83,12 @@ struct ata_xfer { struct ata_queue { TAILQ_HEAD(, ata_xfer) queue_xfer; /* queue of pending commands */ int queue_freeze; /* freeze count for the queue */ - struct ata_xfer *active_xfer; /* active command */ int queue_flags; /* flags for this queue */ -#define QF_IDLE_WAIT 0x01 /* someone is wants the controller idle */ +#define QF_IDLE_WAIT 0x01 /* someone is wants the controller idle */ +#define QF_SHARED 0x02 /* this queue is shared */ + int queue_active; /* number of active transfers */ + int queue_openings; /* max number of active transfers */ + struct ata_xfer *active_xfers[1]; /* active command */ }; /* ATA bus instance state information. */ @@ -447,8 +452,12 @@ void ata_free_xfer(struct ata_channel *, #define ATAXF_CANSLEEP 0x00 #define ATAXF_NOSLEEP 0x01 +void ata_activate_xfer(struct ata_channel *, struct ata_xfer *); +void ata_deactivate_xfer(struct ata_channel *, struct ata_xfer *); + void ata_exec_xfer(struct ata_channel *, struct ata_xfer *); void ata_kill_pending(struct ata_drive_datas *); +void ata_kill_active(struct ata_channel *, int); void ata_reset_channel(struct ata_channel *, int); int ata_addref(struct ata_channel *); @@ -464,7 +473,16 @@ void ata_probe_caps(struct ata_drive_dat void ata_dmaerr(struct ata_drive_datas *, int); #endif void ata_queue_idle(struct ata_queue *); +struct ata_queue * + ata_queue_alloc(int openings); +void ata_queue_free(struct ata_queue *); +struct ata_xfer * + ata_queue_hwslot_to_xfer(struct ata_queue *, int); + void ata_delay(int, const char *, int); + +bool ata_waitdrain_check(struct ata_channel *, int); +bool ata_waitdrain_xfer_check(struct ata_channel *, struct ata_xfer *); #endif /* _KERNEL */ #endif /* _DEV_ATA_ATAVAR_H_ */ Index: src/sys/dev/ic/ahcisata_core.c diff -u src/sys/dev/ic/ahcisata_core.c:1.57 src/sys/dev/ic/ahcisata_core.c:1.57.6.1 --- src/sys/dev/ic/ahcisata_core.c:1.57 Fri Jun 3 10:34:03 2016 +++ src/sys/dev/ic/ahcisata_core.c Mon Apr 10 22:57:02 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: ahcisata_core.c,v 1.57 2016/06/03 10:34:03 jmcneill Exp $ */ +/* $NetBSD: ahcisata_core.c,v 1.57.6.1 2017/04/10 22:57:02 jdolecek Exp $ */ /* * Copyright (c) 2006 Manuel Bouyer. @@ -26,7 +26,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ahcisata_core.c,v 1.57 2016/06/03 10:34:03 jmcneill Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ahcisata_core.c,v 1.57.6.1 2017/04/10 22:57:02 jdolecek Exp $"); #include <sys/types.h> #include <sys/malloc.h> @@ -365,8 +365,7 @@ ahci_attach(struct ahci_softc *sc) sc->sc_chanarray[i] = chp; chp->ch_channel = i; chp->ch_atac = &sc->sc_atac; - chp->ch_queue = malloc(sizeof(struct ata_queue), - M_DEVBUF, M_NOWAIT|M_ZERO); + chp->ch_queue = ata_queue_alloc(1); // XXX if (chp->ch_queue == NULL) { aprint_error("%s port %d: can't allocate memory for " "command queue", AHCINAME(sc), i); @@ -508,7 +507,8 @@ ahci_detach(struct ahci_softc *sc, int f bus_dmamem_free(sc->sc_dmat, &achp->ahcic_cmd_tbl_seg, achp->ahcic_cmd_tbl_nseg); - free(chp->ch_queue, M_DEVBUF); + ata_queue_free(chp->ch_queue); + chp->ch_queue = NULL; chp->atabus = NULL; } @@ -557,7 +557,7 @@ ahci_intr_port(struct ahci_softc *sc, st { uint32_t is, tfd; struct ata_channel *chp = &achp->ata_channel; - struct ata_xfer *xfer = chp->ch_queue->active_xfer; + struct ata_xfer *xfer; int slot; is = AHCI_READ(sc, AHCI_P_IS(chp->ch_channel)); @@ -578,6 +578,7 @@ ahci_intr_port(struct ahci_softc *sc, st printf("ahci_intr_port: slot %d\n", slot); panic("ahci_intr_port"); } + xfer = ata_queue_hwslot_to_xfer(chp->ch_queue, slot); if (is & AHCI_P_IX_TFES) { tfd = AHCI_READ(sc, AHCI_P_TFD(chp->ch_channel)); chp->ch_error = @@ -600,6 +601,7 @@ ahci_intr_port(struct ahci_softc *sc, st ahci_channel_start(sc, chp, 0, 0); } else { slot = 0; /* XXX */ + xfer = ata_queue_hwslot_to_xfer(chp->ch_queue, slot); is = AHCI_READ(sc, AHCI_P_IS(chp->ch_channel)); AHCIDEBUG_PRINT(("ahci_intr_port port %d is 0x%x act 0x%x CI 0x%x\n", chp->ch_channel, is, achp->ahcic_cmds_active, @@ -820,10 +822,7 @@ ahci_reset_channel(struct ata_channel *c printf("%s: port %d reset failed\n", AHCINAME(sc), chp->ch_channel); /* XXX and then ? */ } - if (chp->ch_queue->active_xfer) { - chp->ch_queue->active_xfer->c_kill_xfer(chp, - chp->ch_queue->active_xfer, KILL_RESET); - } + ata_kill_active(chp, KILL_RESET); ata_delay(500, "ahcirst", flags); /* clear port interrupt register */ AHCI_WRITE(sc, AHCI_P_IS(chp->ch_channel), 0xffffffff); @@ -976,16 +975,18 @@ ahci_cmd_start(struct ata_channel *chp, struct ahci_softc *sc = (struct ahci_softc *)chp->ch_atac; struct ahci_channel *achp = (struct ahci_channel *)chp; struct ata_command *ata_c = xfer->c_cmd; - int slot = 0 /* XXX slot */; + int slot = xfer->c_slot; struct ahci_cmd_tbl *cmd_tbl; struct ahci_cmd_header *cmd_h; int i; int channel = chp->ch_channel; - AHCIDEBUG_PRINT(("ahci_cmd_start CI 0x%x timo %d\n", - AHCI_READ(sc, AHCI_P_CI(chp->ch_channel)), ata_c->timeout), + AHCIDEBUG_PRINT(("ahci_cmd_start CI 0x%x timo %d\n slot %d", + AHCI_READ(sc, AHCI_P_CI(chp->ch_channel)), ata_c->timeout, slot), DEBUG_XFERS); + KASSERT((achp->ahcic_cmds_active & (1 << slot)) == 0); + cmd_tbl = achp->ahcic_cmd_tbl[slot]; AHCIDEBUG_PRINT(("%s port %d tbl %p\n", AHCINAME(sc), chp->ch_channel, cmd_tbl), DEBUG_XFERS); @@ -1092,15 +1093,11 @@ ahci_cmd_complete(struct ata_channel *ch chp->ch_flags &= ~ATACH_IRQ_WAIT; if (xfer->c_flags & C_TIMEOU) { ata_c->flags |= AT_TIMEOU; - } else - callout_stop(&chp->ch_callout); + } - chp->ch_queue->active_xfer = NULL; + ata_deactivate_xfer(chp, xfer); - if (chp->ch_drive[xfer->c_drive].drive_flags & ATA_DRIVE_WAITDRAIN) { - ahci_cmd_kill_xfer(chp, xfer, KILL_GONE); - chp->ch_drive[xfer->c_drive].drive_flags &= ~ATA_DRIVE_WAITDRAIN; - wakeup(&chp->ch_queue->active_xfer); + if (ata_waitdrain_xfer_check(chp, xfer)) { return 0; } @@ -1318,21 +1315,18 @@ ahci_bio_complete(struct ata_channel *ch if (xfer->c_flags & C_TIMEOU) { ata_bio->error = TIMEOUT; } else { - callout_stop(&chp->ch_callout); ata_bio->error = NOERROR; } - chp->ch_queue->active_xfer = NULL; + ata_deactivate_xfer(chp, xfer); + bus_dmamap_sync(sc->sc_dmat, achp->ahcic_datad[slot], 0, achp->ahcic_datad[slot]->dm_mapsize, (ata_bio->flags & ATA_READ) ? BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE); bus_dmamap_unload(sc->sc_dmat, achp->ahcic_datad[slot]); - if (chp->ch_drive[xfer->c_drive].drive_flags & ATA_DRIVE_WAITDRAIN) { - ahci_bio_kill_xfer(chp, xfer, KILL_GONE); - chp->ch_drive[xfer->c_drive].drive_flags &= ~ATA_DRIVE_WAITDRAIN; - wakeup(&chp->ch_queue->active_xfer); + if (ata_waitdrain_xfer_check(chp, xfer)) { return 0; } ata_free_xfer(chp, xfer); @@ -1439,7 +1433,7 @@ static void ahci_timeout(void *v) { struct ata_channel *chp = (struct ata_channel *)v; - struct ata_xfer *xfer = chp->ch_queue->active_xfer; + struct ata_xfer *xfer = chp->ch_queue->active_xfers[0]; #ifdef AHCI_DEBUG struct ahci_softc *sc = (struct ahci_softc *)chp->ch_atac; #endif @@ -1696,9 +1690,8 @@ ahci_atapi_start(struct ata_channel *chp static int ahci_atapi_complete(struct ata_channel *chp, struct ata_xfer *xfer, int irq) { - int slot = 0; /* XXX slot */ + int slot = xfer->c_slot; /* XXX slot */ struct scsipi_xfer *sc_xfer = xfer->c_cmd; - int drive = xfer->c_drive; struct ahci_channel *achp = (struct ahci_channel *)chp; struct ahci_softc *sc = (struct ahci_softc *)chp->ch_atac; @@ -1710,11 +1703,11 @@ ahci_atapi_complete(struct ata_channel * if (xfer->c_flags & C_TIMEOU) { sc_xfer->error = XS_TIMEOUT; } else { - callout_stop(&chp->ch_callout); sc_xfer->error = 0; } - chp->ch_queue->active_xfer = NULL; + ata_deactivate_xfer(chp, xfer); + if (xfer->c_bcount > 0) { bus_dmamap_sync(sc->sc_dmat, achp->ahcic_datad[slot], 0, achp->ahcic_datad[slot]->dm_mapsize, @@ -1723,10 +1716,8 @@ ahci_atapi_complete(struct ata_channel * bus_dmamap_unload(sc->sc_dmat, achp->ahcic_datad[slot]); } - if (chp->ch_drive[drive].drive_flags & ATA_DRIVE_WAITDRAIN) { - ahci_atapi_kill_xfer(chp, xfer, KILL_GONE); - chp->ch_drive[drive].drive_flags &= ~ATA_DRIVE_WAITDRAIN; - wakeup(&chp->ch_queue->active_xfer); + if (ata_waitdrain_xfer_check(chp, xfer)) { + sc_xfer->error = XS_DRIVER_STUFFUP; return 0; } ata_free_xfer(chp, xfer); Index: src/sys/dev/ic/mvsata.c diff -u src/sys/dev/ic/mvsata.c:1.35 src/sys/dev/ic/mvsata.c:1.35.6.1 --- src/sys/dev/ic/mvsata.c:1.35 Mon May 2 19:18:29 2016 +++ src/sys/dev/ic/mvsata.c Mon Apr 10 22:57:02 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: mvsata.c,v 1.35 2016/05/02 19:18:29 christos Exp $ */ +/* $NetBSD: mvsata.c,v 1.35.6.1 2017/04/10 22:57:02 jdolecek Exp $ */ /* * Copyright (c) 2008 KIYOHARA Takashi * All rights reserved. @@ -26,7 +26,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: mvsata.c,v 1.35 2016/05/02 19:18:29 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: mvsata.c,v 1.35.6.1 2017/04/10 22:57:02 jdolecek Exp $"); #include "opt_mvsata.h" @@ -630,7 +630,7 @@ mvsata_reset_channel(struct ata_channel xfer = mvport->port_reqtbl[i].xfer; if (xfer == NULL) continue; - chp->ch_queue->active_xfer = xfer; + chp->ch_queue->active_xfers[0] = xfer; xfer->c_kill_xfer(chp, xfer, KILL_RESET); } @@ -1447,14 +1447,14 @@ mvsata_bio_done(struct ata_channel *chp, ata_bio->bcount = xfer->c_bcount; /* mark controller inactive and free xfer */ - KASSERT(chp->ch_queue->active_xfer != NULL); - chp->ch_queue->active_xfer = NULL; + KASSERT(chp->ch_queue->active_xfers[0] != NULL); + ata_deactivate_xfer(chp, xfer); ata_free_xfer(chp, xfer); if (chp->ch_drive[drive].drive_flags & ATA_DRIVE_WAITDRAIN) { ata_bio->error = ERR_NODEV; chp->ch_drive[drive].drive_flags &= ~ATA_DRIVE_WAITDRAIN; - wakeup(&chp->ch_queue->active_xfer); + wakeup(chp->ch_queue->active_xfers); } ata_bio->flags |= ATA_ITSDONE; (*chp->ch_drive[drive].drv_done)(chp->ch_drive[drive].drv_softc); @@ -1812,8 +1812,9 @@ mvsata_wdc_cmd_done(struct ata_channel * (uint64_t)(ata_c->r_device & 0x0f) << 24; } } - callout_stop(&chp->ch_callout); - chp->ch_queue->active_xfer = NULL; + + ata_deactivate_xfer(chp, xfer); + if (ata_c->flags & AT_POLL) { /* enable interrupts */ MVSATA_WDC_WRITE_1(mvport, SRB_CAS, WDCTL_4BIT); @@ -1822,7 +1823,7 @@ mvsata_wdc_cmd_done(struct ata_channel * if (chp->ch_drive[xfer->c_drive].drive_flags & ATA_DRIVE_WAITDRAIN) { mvsata_wdc_cmd_kill_xfer(chp, xfer, KILL_GONE); chp->ch_drive[xfer->c_drive].drive_flags &= ~ATA_DRIVE_WAITDRAIN; - wakeup(&chp->ch_queue->active_xfer); + wakeup(chp->ch_queue->active_xfers); } else mvsata_wdc_cmd_done_end(chp, xfer); } @@ -2390,15 +2391,16 @@ mvsata_atapi_done(struct ata_channel *ch DPRINTFN(1, ("%s:%d:%d: mvsata_atapi_done: flags 0x%x\n", device_xname(atac->atac_dev), chp->ch_channel, xfer->c_drive, (u_int)xfer->c_flags)); - callout_stop(&chp->ch_callout); + /* mark controller inactive and free the command */ - chp->ch_queue->active_xfer = NULL; + + ata_deactivate_xfer(chp, xfer); ata_free_xfer(chp, xfer); if (chp->ch_drive[drive].drive_flags & ATA_DRIVE_WAITDRAIN) { sc_xfer->error = XS_DRIVER_STUFFUP; chp->ch_drive[drive].drive_flags &= ~ATA_DRIVE_WAITDRAIN; - wakeup(&chp->ch_queue->active_xfer); + wakeup(chp->ch_queue->active_xfers); } DPRINTFN(1, ("%s:%d: mvsata_atapi_done: scsipi_done\n", @@ -2460,8 +2462,8 @@ mvsata_edma_enqueue(struct mvsata_port * return rv; KASSERT(mvport->port_reqtbl[quetag].xfer == NULL); - KASSERT(chp->ch_queue->active_xfer != NULL); - mvport->port_reqtbl[quetag].xfer = chp->ch_queue->active_xfer; + KASSERT(chp->ch_queue->active_xfers[0] != NULL); + mvport->port_reqtbl[quetag].xfer = chp->ch_queue->active_xfers[0]; /* setup EDMA Physical Region Descriptors (ePRD) Table Data */ data_dmamap = mvport->port_reqtbl[quetag].data_dmamap; @@ -2574,8 +2576,8 @@ mvsata_edma_handle(struct mvsata_port *m #endif crpb = mvport->port_crpb + erpqop; quetag = CRPB_CHOSTQUETAG(le16toh(crpb->id)); - KASSERT(chp->ch_queue->active_xfer != NULL); - xfer = chp->ch_queue->active_xfer; + KASSERT(chp->ch_queue->active_xfers[0] != NULL); + xfer = chp->ch_queue->active_xfers[0]; KASSERT(xfer == mvport->port_reqtbl[quetag].xfer); #ifdef DIAGNOSTIC if (xfer == NULL) @@ -2763,9 +2765,9 @@ mvsata_bdma_init(struct mvsata_port *mvp if (rv != 0) return rv; - KASSERT(chp->ch_queue->active_xfer != NULL); + KASSERT(chp->ch_queue->active_xfers[0] != NULL); KASSERT(mvport->port_reqtbl[quetag].xfer == NULL); - mvport->port_reqtbl[quetag].xfer = chp->ch_queue->active_xfer; + mvport->port_reqtbl[quetag].xfer = chp->ch_queue->active_xfers[0]; /* setup EDMA Physical Region Descriptors (ePRD) Table Data */ data_dmamap = mvport->port_reqtbl[quetag].data_dmamap; @@ -2886,6 +2888,7 @@ mvsata_port_init(struct mvsata_hc *mvhc, chp->ch_channel = channel; chp->ch_atac = &sc->sc_wdcdev.sc_atac; chp->ch_queue = &mvport->port_ata_queue; + chp->ch_queue->queue_openings = 1; // XXX sc->sc_ata_channels[channel] = chp; rv = mvsata_wdc_reg_init(mvport, sc->sc_wdcdev.regs + channel); @@ -3449,7 +3452,7 @@ mvsata_edma_setup_crqb(struct mvsata_por uint8_t cmd, head; int i; const int drive = - mvport->port_ata_channel.ch_queue->active_xfer->c_drive; + mvport->port_ata_channel.ch_queue->active_xfers[0]->c_drive; eprd_addr = mvport->port_eprd_dmamap->dm_segs[0].ds_addr + mvport->port_reqtbl[quetag].eprd_offset; @@ -3697,7 +3700,7 @@ mvsata_edma_setup_crqb_gen2e(struct mvsa uint32_t ctrlflg, rw; uint8_t cmd, head; const int drive = - mvport->port_ata_channel.ch_queue->active_xfer->c_drive; + mvport->port_ata_channel.ch_queue->active_xfers[0]->c_drive; eprd_addr = mvport->port_eprd_dmamap->dm_segs[0].ds_addr + mvport->port_reqtbl[quetag].eprd_offset; Index: src/sys/dev/ic/siisata.c diff -u src/sys/dev/ic/siisata.c:1.30 src/sys/dev/ic/siisata.c:1.30.4.1 --- src/sys/dev/ic/siisata.c:1.30 Tue Jan 3 01:30:15 2017 +++ src/sys/dev/ic/siisata.c Mon Apr 10 22:57:02 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: siisata.c,v 1.30 2017/01/03 01:30:15 jakllsch Exp $ */ +/* $NetBSD: siisata.c,v 1.30.4.1 2017/04/10 22:57:02 jdolecek Exp $ */ /* from ahcisata_core.c */ @@ -79,12 +79,12 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: siisata.c,v 1.30 2017/01/03 01:30:15 jakllsch Exp $"); +__KERNEL_RCSID(0, "$NetBSD: siisata.c,v 1.30.4.1 2017/04/10 22:57:02 jdolecek Exp $"); #include <sys/types.h> -#include <sys/malloc.h> #include <sys/param.h> #include <sys/kernel.h> +#include <sys/malloc.h> #include <sys/systm.h> #include <sys/syslog.h> #include <sys/disklabel.h> @@ -290,8 +290,7 @@ siisata_attach_port(struct siisata_softc sc->sc_chanarray[port] = chp; chp->ch_channel = port; chp->ch_atac = &sc->sc_atac; - chp->ch_queue = malloc(sizeof(struct ata_queue), - M_DEVBUF, M_NOWAIT|M_ZERO); + chp->ch_queue = ata_queue_alloc(1); // XXX if (chp->ch_queue == NULL) { aprint_error_dev(sc->sc_atac.atac_dev, "port %d: can't allocate memory " @@ -481,7 +480,7 @@ siisata_intr_port(struct siisata_channel sc = (struct siisata_softc *)schp->ata_channel.ch_atac; chp = &schp->ata_channel; - xfer = chp->ch_queue->active_xfer; + xfer = chp->ch_queue->active_xfers[0]; slot = SIISATA_NON_NCQ_SLOT; pis = PRREAD(sc, PRX(chp->ch_channel, PRO_PIS)); @@ -625,6 +624,7 @@ siisata_reset_channel(struct ata_channel { struct siisata_softc *sc = (struct siisata_softc *)chp->ch_atac; struct siisata_channel *schp = (struct siisata_channel *)chp; + struct ata_xfer *xfer; SIISATA_DEBUG_PRINT(("%s: %s\n", SIISATANAME(sc), __func__), DEBUG_FUNCS); @@ -640,9 +640,8 @@ siisata_reset_channel(struct ata_channel DELAY(10); PRWRITE(sc, PRX(chp->ch_channel, PRO_SERROR), PRREAD(sc, PRX(chp->ch_channel, PRO_SERROR))); - if (chp->ch_queue->active_xfer) { - chp->ch_queue->active_xfer->c_kill_xfer(chp, - chp->ch_queue->active_xfer, KILL_RESET); + if ((xfer = chp->ch_queue->active_xfers[0]) != NULL) { + (*xfer->c_kill_xfer)(chp, xfer, KILL_RESET); } return; @@ -943,13 +942,11 @@ siisata_cmd_complete(struct ata_channel ata_c->flags |= AT_ERROR; } - if (chp->ch_drive[xfer->c_drive].drive_flags & ATA_DRIVE_WAITDRAIN) { - siisata_cmd_kill_xfer(chp, xfer, KILL_GONE); - chp->ch_drive[xfer->c_drive].drive_flags &= ~ATA_DRIVE_WAITDRAIN; - wakeup(&chp->ch_queue->active_xfer); - return 0; - } else + ata_deactivate_xfer(chp, xfer); + + if (!ata_waitdrain_xfer_check(chp, xfer)) { siisata_cmd_done(chp, xfer, slot); + } return 0; } @@ -998,8 +995,8 @@ siisata_cmd_done(struct ata_channel *chp if (PRREAD(sc, PRSX(chp->ch_channel, slot, PRSO_RTC))) ata_c->flags |= AT_XFDONE; - chp->ch_queue->active_xfer = NULL; ata_free_xfer(chp, xfer); + if (ata_c->flags & AT_WAIT) wakeup(ata_c); else if (ata_c->callback) @@ -1156,15 +1153,14 @@ siisata_bio_complete(struct ata_channel BUS_DMASYNC_POSTWRITE); bus_dmamap_unload(sc->sc_dmat, schp->sch_datad[slot]); - if (chp->ch_drive[xfer->c_drive].drive_flags & ATA_DRIVE_WAITDRAIN) { - siisata_bio_kill_xfer(chp, xfer, KILL_GONE); - chp->ch_drive[xfer->c_drive].drive_flags &= ~ATA_DRIVE_WAITDRAIN; - wakeup(&chp->ch_queue->active_xfer); + ata_deactivate_xfer(chp, xfer); + + if (ata_waitdrain_xfer_check(chp, xfer)) { return 0; } - chp->ch_queue->active_xfer = NULL; ata_free_xfer(chp, xfer); + ata_bio->flags |= ATA_ITSDONE; if (chp->ch_status & WDCS_DWF) { ata_bio->error = ERR_DF; @@ -1195,7 +1191,7 @@ void siisata_timeout(void *v) { struct ata_channel *chp = (struct ata_channel *)v; - struct ata_xfer *xfer = chp->ch_queue->active_xfer; + struct ata_xfer *xfer = chp->ch_queue->active_xfers[0]; int slot = SIISATA_NON_NCQ_SLOT; int s = splbio(); SIISATA_DEBUG_PRINT(("%s: %p\n", __func__, xfer), DEBUG_INTR); @@ -1680,14 +1676,13 @@ siisata_atapi_complete(struct ata_channe BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE); bus_dmamap_unload(sc->sc_dmat, schp->sch_datad[slot]); - if (chp->ch_drive[xfer->c_drive].drive_flags & ATA_DRIVE_WAITDRAIN) { - siisata_atapi_kill_xfer(chp, xfer, KILL_GONE); - chp->ch_drive[xfer->c_drive].drive_flags &= ~ATA_DRIVE_WAITDRAIN; - wakeup(&chp->ch_queue->active_xfer); + ata_deactivate_xfer(chp, xfer); + + if (!ata_waitdrain_xfer_check(chp, xfer)) { + sc_xfer->error = XS_DRIVER_STUFFUP; return 0; /* XXX verify */ } - chp->ch_queue->active_xfer = NULL; ata_free_xfer(chp, xfer); sc_xfer->resid = sc_xfer->datalen; sc_xfer->resid -= PRREAD(sc, PRSX(chp->ch_channel, slot, PRSO_RTC)); Index: src/sys/dev/ic/wdc.c diff -u src/sys/dev/ic/wdc.c:1.283 src/sys/dev/ic/wdc.c:1.283.2.1 --- src/sys/dev/ic/wdc.c:1.283 Wed Mar 29 09:04:35 2017 +++ src/sys/dev/ic/wdc.c Mon Apr 10 22:57:02 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: wdc.c,v 1.283 2017/03/29 09:04:35 msaitoh Exp $ */ +/* $NetBSD: wdc.c,v 1.283.2.1 2017/04/10 22:57:02 jdolecek Exp $ */ /* * Copyright (c) 1998, 2001, 2003 Manuel Bouyer. All rights reserved. @@ -58,7 +58,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: wdc.c,v 1.283 2017/03/29 09:04:35 msaitoh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: wdc.c,v 1.283.2.1 2017/04/10 22:57:02 jdolecek Exp $"); #include "opt_ata.h" #include "opt_wdc.h" @@ -872,7 +872,8 @@ wdcintr(void *arg) } ATADEBUG_PRINT(("wdcintr\n"), DEBUG_INTR); - xfer = chp->ch_queue->active_xfer; + KASSERT(chp->ch_queue->queue_openings == 1); + xfer = ata_queue_hwslot_to_xfer(chp->ch_queue, 0); #ifdef DIAGNOSTIC if (xfer == NULL) panic("wdcintr: no xfer"); @@ -933,7 +934,8 @@ wdc_reset_channel(struct ata_channel *ch * if the current command if on an ATAPI device, issue a * ATAPI_SOFT_RESET */ - xfer = chp->ch_queue->active_xfer; + KASSERT(chp->ch_queue->queue_openings == 1); + xfer = ata_queue_hwslot_to_xfer(chp->ch_queue, 0); if (xfer && xfer->c_chp == chp && (xfer->c_flags & C_ATAPI)) { wdccommandshort(chp, xfer->c_drive, ATAPI_SOFT_RESET); if (flags & AT_WAIT) @@ -977,12 +979,11 @@ wdc_reset_channel(struct ata_channel *ch xfer, c_xferchain); TAILQ_INSERT_TAIL(&reset_xfer, xfer, c_xferchain); } - xfer = chp->ch_queue->active_xfer; + xfer = ata_queue_hwslot_to_xfer(chp->ch_queue, 0); if (xfer) { if (xfer->c_chp != chp) ata_reset_channel(xfer->c_chp, flags); else { - callout_stop(&chp->ch_callout); #if NATA_DMA || NATA_PIOBM /* * If we're waiting for DMA, stop the @@ -995,7 +996,7 @@ wdc_reset_channel(struct ata_channel *ch chp->ch_flags &= ~ATACH_DMA_WAIT; } #endif - chp->ch_queue->active_xfer = NULL; + ata_deactivate_xfer(chp, xfer); if ((flags & AT_RST_EMERG) == 0) xfer->c_kill_xfer( chp, xfer, KILL_RESET); @@ -1231,7 +1232,7 @@ __wdcwait(struct ata_channel *chp, int m #ifdef WDCNDELAY_DEBUG /* After autoconfig, there should be no long delays. */ if (!cold && xtime > WDCNDELAY_DEBUG) { - struct ata_xfer *xfer = chp->ch_queue->active_xfer; + struct ata_xfer *xfer = ata_queue_hwslot_to_xfer(chp->ch_queue, 0); if (xfer == NULL) printf("%s channel %d: warning: busy-wait took %dus\n", device_xname(chp->ch_atac->atac_dev), @@ -1326,12 +1327,13 @@ wdctimeout(void *arg) #if NATA_DMA || NATA_PIOBM struct wdc_softc *wdc = CHAN_TO_WDC(chp); #endif - struct ata_xfer *xfer = chp->ch_queue->active_xfer; int s; ATADEBUG_PRINT(("wdctimeout\n"), DEBUG_FUNCS); s = splbio(); + struct ata_xfer *xfer = ata_queue_hwslot_to_xfer(chp->ch_queue, 0); + KASSERT(xfer != NULL); if ((chp->ch_flags & ATACH_IRQ_WAIT) != 0) { __wdcerror(chp, "lost interrupt"); printf("\ttype: %s tc_bcount: %d tc_skip: %d\n", @@ -1663,8 +1665,9 @@ __wdccommand_done(struct ata_channel *ch } ata_c->r_device &= 0xf0; } - callout_stop(&chp->ch_callout); - chp->ch_queue->active_xfer = NULL; + + ata_deactivate_xfer(chp, xfer); + if (ata_c->flags & AT_POLL) { /* enable interrupts */ if (! (wdc->cap & WDC_CAPABILITY_NO_AUXCTL)) @@ -1672,12 +1675,10 @@ __wdccommand_done(struct ata_channel *ch wd_aux_ctlr, WDCTL_4BIT); delay(10); /* some drives need a little delay here */ } - if (chp->ch_drive[xfer->c_drive].drive_flags & ATA_DRIVE_WAITDRAIN) { - __wdccommand_kill_xfer(chp, xfer, KILL_GONE); - chp->ch_drive[xfer->c_drive].drive_flags &= ~ATA_DRIVE_WAITDRAIN; - wakeup(&chp->ch_queue->active_xfer); - } else + + if (!ata_waitdrain_xfer_check(chp, xfer)) { __wdccommand_done_end(chp, xfer); + } } static void @@ -1849,7 +1850,7 @@ static void __wdcerror(struct ata_channel *chp, const char *msg) { struct atac_softc *atac = chp->ch_atac; - struct ata_xfer *xfer = chp->ch_queue->active_xfer; + struct ata_xfer *xfer = ata_queue_hwslot_to_xfer(chp->ch_queue, 0); if (xfer == NULL) aprint_error("%s:%d: %s\n", device_xname(atac->atac_dev), Index: src/sys/dev/pci/artsata.c diff -u src/sys/dev/pci/artsata.c:1.26 src/sys/dev/pci/artsata.c:1.26.18.1 --- src/sys/dev/pci/artsata.c:1.26 Sat Mar 29 19:28:24 2014 +++ src/sys/dev/pci/artsata.c Mon Apr 10 22:57:02 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: artsata.c,v 1.26 2014/03/29 19:28:24 christos Exp $ */ +/* $NetBSD: artsata.c,v 1.26.18.1 2017/04/10 22:57:02 jdolecek Exp $ */ /*- * Copyright (c) 2003 The NetBSD Foundation, Inc. @@ -30,13 +30,12 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: artsata.c,v 1.26 2014/03/29 19:28:24 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: artsata.c,v 1.26.18.1 2017/04/10 22:57:02 jdolecek Exp $"); #include "opt_pciide.h" #include <sys/param.h> #include <sys/systm.h> -#include <sys/malloc.h> #include <dev/pci/pcivar.h> #include <dev/pci/pcidevs.h> @@ -232,8 +231,7 @@ artisea_chansetup(struct pciide_softc *s cp->name = PCIIDE_CHANNEL_NAME(channel); cp->ata_channel.ch_channel = channel; cp->ata_channel.ch_atac = &sc->sc_wdcdev.sc_atac; - cp->ata_channel.ch_queue = - malloc(sizeof(struct ata_queue), M_DEVBUF, M_NOWAIT); + cp->ata_channel.ch_queue = ata_queue_alloc(1); if (cp->ata_channel.ch_queue == NULL) { aprint_error("%s %s channel: " "can't allocate memory for command queue", Index: src/sys/dev/pci/cmdide.c diff -u src/sys/dev/pci/cmdide.c:1.38 src/sys/dev/pci/cmdide.c:1.38.28.1 --- src/sys/dev/pci/cmdide.c:1.38 Mon Sep 3 15:38:17 2012 +++ src/sys/dev/pci/cmdide.c Mon Apr 10 22:57:02 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: cmdide.c,v 1.38 2012/09/03 15:38:17 kiyohara Exp $ */ +/* $NetBSD: cmdide.c,v 1.38.28.1 2017/04/10 22:57:02 jdolecek Exp $ */ /* * Copyright (c) 1999, 2000, 2001 Manuel Bouyer. @@ -25,11 +25,10 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: cmdide.c,v 1.38 2012/09/03 15:38:17 kiyohara Exp $"); +__KERNEL_RCSID(0, "$NetBSD: cmdide.c,v 1.38.28.1 2017/04/10 22:57:02 jdolecek Exp $"); #include <sys/param.h> #include <sys/systm.h> -#include <sys/malloc.h> #include <dev/pci/pcivar.h> #include <dev/pci/pcidevs.h> @@ -165,8 +164,7 @@ cmd_channel_map(const struct pci_attach_ cp->ata_channel.ch_queue = sc->pciide_channels[0].ata_channel.ch_queue; } else { - cp->ata_channel.ch_queue = - malloc(sizeof(struct ata_queue), M_DEVBUF, M_NOWAIT); + cp->ata_channel.ch_queue = ata_queue_alloc(1); } if (cp->ata_channel.ch_queue == NULL) { aprint_error("%s %s channel: " @@ -521,8 +519,7 @@ cmd680_channel_map(const struct pci_atta cp->ata_channel.ch_channel = channel; cp->ata_channel.ch_atac = &sc->sc_wdcdev.sc_atac; - cp->ata_channel.ch_queue = - malloc(sizeof(struct ata_queue), M_DEVBUF, M_NOWAIT); + cp->ata_channel.ch_queue = ata_queue_alloc(1); if (cp->ata_channel.ch_queue == NULL) { aprint_error("%s %s channel: " "can't allocate memory for command queue", Index: src/sys/dev/pci/cypide.c diff -u src/sys/dev/pci/cypide.c:1.30 src/sys/dev/pci/cypide.c:1.30.18.1 --- src/sys/dev/pci/cypide.c:1.30 Mon Oct 7 19:51:55 2013 +++ src/sys/dev/pci/cypide.c Mon Apr 10 22:57:03 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: cypide.c,v 1.30 2013/10/07 19:51:55 jakllsch Exp $ */ +/* $NetBSD: cypide.c,v 1.30.18.1 2017/04/10 22:57:03 jdolecek Exp $ */ /* * Copyright (c) 1999, 2000, 2001 Manuel Bouyer. @@ -26,11 +26,10 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: cypide.c,v 1.30 2013/10/07 19:51:55 jakllsch Exp $"); +__KERNEL_RCSID(0, "$NetBSD: cypide.c,v 1.30.18.1 2017/04/10 22:57:03 jdolecek Exp $"); #include <sys/param.h> #include <sys/systm.h> -#include <sys/malloc.h> #include <dev/pci/pcivar.h> #include <dev/pci/pcidevs.h> @@ -149,8 +148,7 @@ cy693_chip_map(struct pciide_softc *sc, cp->name = PCIIDE_CHANNEL_NAME(0); cp->ata_channel.ch_channel = 0; cp->ata_channel.ch_atac = &sc->sc_wdcdev.sc_atac; - cp->ata_channel.ch_queue = - malloc(sizeof(struct ata_queue), M_DEVBUF, M_NOWAIT); + cp->ata_channel.ch_queue = ata_queue_alloc(1); if (cp->ata_channel.ch_queue == NULL) { aprint_error("%s primary channel: " "can't allocate memory for command queue", Index: src/sys/dev/pci/pciide_common.c diff -u src/sys/dev/pci/pciide_common.c:1.62 src/sys/dev/pci/pciide_common.c:1.62.4.1 --- src/sys/dev/pci/pciide_common.c:1.62 Thu Oct 13 17:11:09 2016 +++ src/sys/dev/pci/pciide_common.c Mon Apr 10 22:57:03 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: pciide_common.c,v 1.62 2016/10/13 17:11:09 jdolecek Exp $ */ +/* $NetBSD: pciide_common.c,v 1.62.4.1 2017/04/10 22:57:03 jdolecek Exp $ */ /* @@ -70,10 +70,9 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: pciide_common.c,v 1.62 2016/10/13 17:11:09 jdolecek Exp $"); +__KERNEL_RCSID(0, "$NetBSD: pciide_common.c,v 1.62.4.1 2017/04/10 22:57:03 jdolecek Exp $"); #include <sys/param.h> -#include <sys/malloc.h> #include <dev/pci/pcireg.h> #include <dev/pci/pcivar.h> @@ -210,7 +209,7 @@ pciide_common_detach(struct pciide_softc #endif } - free(cp->ata_channel.ch_queue, M_DEVBUF); + ata_queue_free(cp->ata_channel.ch_queue); cp->ata_channel.atabus = NULL; } @@ -877,8 +876,7 @@ pciide_chansetup(struct pciide_softc *sc cp->name = PCIIDE_CHANNEL_NAME(channel); cp->ata_channel.ch_channel = channel; cp->ata_channel.ch_atac = &sc->sc_wdcdev.sc_atac; - cp->ata_channel.ch_queue = - malloc(sizeof(struct ata_queue), M_DEVBUF, M_NOWAIT|M_ZERO); + cp->ata_channel.ch_queue = ata_queue_alloc(1); if (cp->ata_channel.ch_queue == NULL) { aprint_error("%s %s channel: " "can't allocate memory for command queue", Index: src/sys/dev/pci/pdcsata.c diff -u src/sys/dev/pci/pdcsata.c:1.27 src/sys/dev/pci/pdcsata.c:1.27.18.1 --- src/sys/dev/pci/pdcsata.c:1.27 Sat Mar 29 19:28:25 2014 +++ src/sys/dev/pci/pdcsata.c Mon Apr 10 22:57:03 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: pdcsata.c,v 1.27 2014/03/29 19:28:25 christos Exp $ */ +/* $NetBSD: pdcsata.c,v 1.27.18.1 2017/04/10 22:57:03 jdolecek Exp $ */ /* * Copyright (c) 2004, Manuel Bouyer. @@ -25,10 +25,9 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: pdcsata.c,v 1.27 2014/03/29 19:28:25 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: pdcsata.c,v 1.27.18.1 2017/04/10 22:57:03 jdolecek Exp $"); #include <sys/types.h> -#include <sys/malloc.h> #include <sys/param.h> #include <sys/systm.h> @@ -375,8 +374,7 @@ pdcsata_chip_map(struct pciide_softc *sc cp->name = NULL; cp->ata_channel.ch_channel = channel; cp->ata_channel.ch_atac = &sc->sc_wdcdev.sc_atac; - cp->ata_channel.ch_queue = - malloc(sizeof(struct ata_queue), M_DEVBUF, M_NOWAIT); + cp->ata_channel.ch_queue = ata_queue_alloc(1); if (cp->ata_channel.ch_queue == NULL) { aprint_error("%s channel %d: " "can't allocate memory for command queue\n", Index: src/sys/dev/pci/satalink.c diff -u src/sys/dev/pci/satalink.c:1.53 src/sys/dev/pci/satalink.c:1.53.4.1 --- src/sys/dev/pci/satalink.c:1.53 Tue Aug 23 09:46:45 2016 +++ src/sys/dev/pci/satalink.c Mon Apr 10 22:57:03 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: satalink.c,v 1.53 2016/08/23 09:46:45 msaitoh Exp $ */ +/* $NetBSD: satalink.c,v 1.53.4.1 2017/04/10 22:57:03 jdolecek Exp $ */ /*- * Copyright (c) 2003 The NetBSD Foundation, Inc. @@ -30,7 +30,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: satalink.c,v 1.53 2016/08/23 09:46:45 msaitoh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: satalink.c,v 1.53.4.1 2017/04/10 22:57:03 jdolecek Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -600,8 +600,7 @@ sii3114_chansetup(struct pciide_softc *s cp->name = channel_names[channel]; cp->ata_channel.ch_channel = channel; cp->ata_channel.ch_atac = &sc->sc_wdcdev.sc_atac; - cp->ata_channel.ch_queue = - malloc(sizeof(struct ata_queue), M_DEVBUF, M_NOWAIT); + cp->ata_channel.ch_queue = ata_queue_alloc(1); if (cp->ata_channel.ch_queue == NULL) { aprint_error("%s %s channel: " "can't allocate memory for command queue", Index: src/sys/dev/pci/viaide.c diff -u src/sys/dev/pci/viaide.c:1.84 src/sys/dev/pci/viaide.c:1.84.18.1 --- src/sys/dev/pci/viaide.c:1.84 Sat Mar 29 19:28:25 2014 +++ src/sys/dev/pci/viaide.c Mon Apr 10 22:57:03 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: viaide.c,v 1.84 2014/03/29 19:28:25 christos Exp $ */ +/* $NetBSD: viaide.c,v 1.84.18.1 2017/04/10 22:57:03 jdolecek Exp $ */ /* * Copyright (c) 1999, 2000, 2001 Manuel Bouyer. @@ -26,11 +26,10 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: viaide.c,v 1.84 2014/03/29 19:28:25 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: viaide.c,v 1.84.18.1 2017/04/10 22:57:03 jdolecek Exp $"); #include <sys/param.h> #include <sys/systm.h> -#include <sys/malloc.h> #include <dev/pci/pcivar.h> #include <dev/pci/pcidevs.h> @@ -1071,8 +1070,7 @@ via_vt6421_chansetup(struct pciide_softc cp->ata_channel.ch_channel = channel; cp->ata_channel.ch_atac = &sc->sc_wdcdev.sc_atac; - cp->ata_channel.ch_queue = - malloc(sizeof(struct ata_queue), M_DEVBUF, M_NOWAIT); + cp->ata_channel.ch_queue = ata_queue_alloc(1); if (cp->ata_channel.ch_queue == NULL) { aprint_error("%s channel %d: " "can't allocate memory for command queue", Index: src/sys/dev/scsipi/atapi_wdc.c diff -u src/sys/dev/scsipi/atapi_wdc.c:1.123 src/sys/dev/scsipi/atapi_wdc.c:1.123.4.1 --- src/sys/dev/scsipi/atapi_wdc.c:1.123 Sun Nov 20 15:37:19 2016 +++ src/sys/dev/scsipi/atapi_wdc.c Mon Apr 10 22:57:03 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: atapi_wdc.c,v 1.123 2016/11/20 15:37:19 mlelstv Exp $ */ +/* $NetBSD: atapi_wdc.c,v 1.123.4.1 2017/04/10 22:57:03 jdolecek Exp $ */ /* * Copyright (c) 1998, 2001 Manuel Bouyer. @@ -25,7 +25,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: atapi_wdc.c,v 1.123 2016/11/20 15:37:19 mlelstv Exp $"); +__KERNEL_RCSID(0, "$NetBSD: atapi_wdc.c,v 1.123.4.1 2017/04/10 22:57:03 jdolecek Exp $"); #ifndef ATADEBUG #define ATADEBUG @@ -1083,16 +1083,12 @@ wdc_atapi_done(struct ata_channel *chp, ATADEBUG_PRINT(("wdc_atapi_done %s:%d:%d: flags 0x%x\n", device_xname(atac->atac_dev), chp->ch_channel, xfer->c_drive, (u_int)xfer->c_flags), DEBUG_XFERS); - callout_stop(&chp->ch_callout); - /* mark controller inactive and free the command */ - chp->ch_queue->active_xfer = NULL; + + ata_deactivate_xfer(chp, xfer); ata_free_xfer(chp, xfer); - if (chp->ch_drive[drive].drive_flags & ATA_DRIVE_WAITDRAIN) { + if (ata_waitdrain_check(chp, drive)) sc_xfer->error = XS_DRIVER_STUFFUP; - chp->ch_drive[drive].drive_flags &= ~ATA_DRIVE_WAITDRAIN; - wakeup(&chp->ch_queue->active_xfer); - } ATADEBUG_PRINT(("wdc_atapi_done: scsipi_done\n"), DEBUG_XFERS); scsipi_done(sc_xfer);