Module Name: src Committed By: jdolecek Date: Wed Oct 3 19:20:48 UTC 2018
Modified Files: src/sys/dev/ata [jdolecek-ncqfixes]: TODO.ncq ata.c atavar.h wd.c src/sys/dev/ic [jdolecek-ncqfixes]: ahcisata_core.c mvsata.c siisata.c wdc.c Log Message: change channel reset and drive reset for all ATA controllers to always run via thread, and with channel lock held the whole time; the queue is frozen while reset is pending for this repurpose ata_reset_channel() into new ata_thread_run() also adjust some device printfs to not leak xfer pointer, and avoid aprint_* for non-autoconf messages To generate a diff of this commit: cvs rdiff -u -r1.4.2.9 -r1.4.2.10 src/sys/dev/ata/TODO.ncq cvs rdiff -u -r1.141.6.10 -r1.141.6.11 src/sys/dev/ata/ata.c cvs rdiff -u -r1.99.2.7 -r1.99.2.8 src/sys/dev/ata/atavar.h cvs rdiff -u -r1.441.2.6 -r1.441.2.7 src/sys/dev/ata/wd.c cvs rdiff -u -r1.62.2.5 -r1.62.2.6 src/sys/dev/ic/ahcisata_core.c cvs rdiff -u -r1.41.2.4 -r1.41.2.5 src/sys/dev/ic/mvsata.c cvs rdiff -u -r1.35.6.5 -r1.35.6.6 src/sys/dev/ic/siisata.c cvs rdiff -u -r1.288.6.2 -r1.288.6.3 src/sys/dev/ic/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/TODO.ncq diff -u src/sys/dev/ata/TODO.ncq:1.4.2.9 src/sys/dev/ata/TODO.ncq:1.4.2.10 --- src/sys/dev/ata/TODO.ncq:1.4.2.9 Mon Sep 24 19:48:02 2018 +++ src/sys/dev/ata/TODO.ncq Wed Oct 3 19:20:48 2018 @@ -2,8 +2,6 @@ jdolecek-ncqfixes goals: - fix ahci(4) error handling under paralles - invalid bio via WD_CHAOS_MONKEY ends up being handled as NOERROR, triggering KASSERT() in wd(4) - remove controller-specific slot bitmaps (ic/siisata.c, ic/ahcisata_core.c) -- revert rev 1.431 of wd.c (AT_POOL removal) - ensure still works - for the reset-via-thread case Bugs ---- Index: src/sys/dev/ata/ata.c diff -u src/sys/dev/ata/ata.c:1.141.6.10 src/sys/dev/ata/ata.c:1.141.6.11 --- src/sys/dev/ata/ata.c:1.141.6.10 Mon Sep 24 19:48:02 2018 +++ src/sys/dev/ata/ata.c Wed Oct 3 19:20:48 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: ata.c,v 1.141.6.10 2018/09/24 19:48:02 jdolecek Exp $ */ +/* $NetBSD: ata.c,v 1.141.6.11 2018/10/03 19:20:48 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.141.6.10 2018/09/24 19:48:02 jdolecek Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ata.c,v 1.141.6.11 2018/10/03 19:20:48 jdolecek Exp $"); #include "opt_ata.h" @@ -440,7 +440,7 @@ atabus_thread(void *arg) struct ata_channel *chp = sc->sc_chan; struct ata_queue *chq = chp->ch_queue; struct ata_xfer *xfer; - int i, rv, s; + int i, rv; ata_channel_lock(chp); chp->ch_flags |= ATACH_TH_RUN; @@ -462,7 +462,8 @@ atabus_thread(void *arg) ata_channel_lock(chp); for (;;) { - if ((chp->ch_flags & (ATACH_TH_RESET | ATACH_SHUTDOWN)) == 0 && + if ((chp->ch_flags & (ATACH_TH_RESET | ATACH_TH_DRIVE_RESET + | ATACH_SHUTDOWN)) == 0 && (chq->queue_active == 0 || chq->queue_freeze == 0)) { chp->ch_flags &= ~ATACH_TH_RUN; cv_wait(&chp->ch_thr_idle, &chp->ch_lock); @@ -478,12 +479,24 @@ atabus_thread(void *arg) ata_channel_lock(chp); } if (chp->ch_flags & ATACH_TH_RESET) { - /* ata_reset_channel() will unfreeze the channel */ - ata_channel_unlock(chp); - s = splbio(); - ata_reset_channel(chp, AT_WAIT | chp->ch_reset_flags); - splx(s); - ata_channel_lock(chp); + /* this will unfreeze the channel */ + ata_thread_run(chp, AT_WAIT | chp->ch_reset_flags, + ATACH_TH_RESET, ATACH_NODRIVE); + } else if (chp->ch_flags & ATACH_TH_DRIVE_RESET) { + for (i = 0; i < chp->ch_ndrives; i++) { + struct ata_drive_datas *drvp; + int drv_reset_flags; + + drvp = &chp->ch_drive[i]; + drv_reset_flags = drvp->drive_reset_flags; + + if (drvp->drive_flags & ATACH_TH_DRIVE_RESET) { + ata_thread_run(chp, + AT_WAIT | drv_reset_flags, + ATACH_TH_DRIVE_RESET, i); + } + } + chp->ch_flags &= ~ATACH_TH_DRIVE_RESET; } else if (chq->queue_active > 0 && chq->queue_freeze == 1) { /* * Caller has bumped queue_freeze, decrease it. This @@ -511,6 +524,11 @@ atabus_thread(void *arg) } } else if (chq->queue_freeze > 1) panic("%s: queue_freeze", __func__); + + /* Try to run down the queue once after each event is handled */ + ata_channel_unlock(chp); + atastart(chp); + ata_channel_lock(chp); } chp->ch_thread = NULL; cv_signal(&chp->ch_thr_idle); @@ -1471,7 +1489,8 @@ ata_timo_xfer_check(struct ata_xfer *xfe ata_channel_unlock(chp); device_printf(drvp->drv_softc, - "xfer %p freed while invoking timeout\n", xfer); + "xfer %"PRIxPTR" freed while invoking timeout\n", + (intptr_t)xfer & PAGE_MASK); ata_free_xfer(chp, xfer); return true; @@ -1481,7 +1500,8 @@ ata_timo_xfer_check(struct ata_xfer *xfe ata_channel_unlock(chp); device_printf(drvp->drv_softc, - "xfer %p deactivated while invoking timeout\n", xfer); + "xfer %"PRIxPTR" deactivated while invoking timeout\n", + (intptr_t)xfer & PAGE_MASK); return true; } @@ -1605,44 +1625,28 @@ ata_channel_thaw(struct ata_channel *chp } /* - * ata_reset_channel: + * ata_thread_run: * - * Reset and ATA channel. - * - * MUST BE CALLED AT splbio()! + * Reset and ATA channel. Channel lock must be held. */ void -ata_reset_channel(struct ata_channel *chp, int flags) +ata_thread_run(struct ata_channel *chp, int flags, int type, int drive) { struct atac_softc *atac = chp->ch_atac; - int drive; bool threset = false; + struct ata_drive_datas *drvp; -#ifdef ATA_DEBUG - int spl1, spl2; - - spl1 = splbio(); - spl2 = splbio(); - if (spl2 != spl1) { - printf("ata_reset_channel: not at splbio()\n"); - panic("ata_reset_channel"); - } - splx(spl2); - splx(spl1); -#endif /* ATA_DEBUG */ - - ata_channel_lock(chp); + ata_channel_lock_owned(chp); /* * If we can poll or wait it's OK, otherwise wake up the * kernel thread to do it for us. */ - ATADEBUG_PRINT(("ata_reset_channel flags 0x%x ch_flags 0x%x\n", - flags, chp->ch_flags), DEBUG_FUNCS | DEBUG_XFERS); + ATADEBUG_PRINT(("%s flags 0x%x ch_flags 0x%x\n", + __func__, flags, chp->ch_flags), DEBUG_FUNCS | DEBUG_XFERS); if ((flags & (AT_POLL | AT_WAIT)) == 0) { - if (chp->ch_flags & ATACH_TH_RESET) { + if (chp->ch_flags & type) { /* No need to schedule a reset more than one time. */ - ata_channel_unlock(chp); return; } @@ -1651,10 +1655,24 @@ ata_reset_channel(struct ata_channel *ch * to a thread. */ ata_channel_freeze_locked(chp); - chp->ch_flags |= ATACH_TH_RESET; - chp->ch_reset_flags = flags & AT_RST_EMERG; + chp->ch_flags |= type; + + + switch (type) { + case ATACH_TH_RESET: + chp->ch_reset_flags = flags & AT_RST_EMERG; + break; + case ATACH_TH_DRIVE_RESET: + drvp = &chp->ch_drive[drive]; + drvp->drive_flags |= ATACH_TH_DRIVE_RESET; + drvp->drive_reset_flags = flags; + break; + default: + panic("%s: unknown type: %x", __func__, type); + /* NOTREACHED */ + } + cv_signal(&chp->ch_thr_idle); - ata_channel_unlock(chp); return; } @@ -1666,19 +1684,31 @@ ata_reset_channel(struct ata_channel *ch * the flag now so that the thread won't try to execute it if * we happen to sleep, and thaw one more time after the reset. */ - if (chp->ch_flags & ATACH_TH_RESET) { - chp->ch_flags &= ~ATACH_TH_RESET; + if (chp->ch_flags & type) { + chp->ch_flags &= ~type; threset = true; } - ata_channel_unlock(chp); + switch (type) { + case ATACH_TH_RESET: + (*atac->atac_bustype_ata->ata_reset_channel)(chp, flags); - (*atac->atac_bustype_ata->ata_reset_channel)(chp, flags); + KASSERT(chp->ch_ndrives == 0 || chp->ch_drive != NULL); + for (drive = 0; drive < chp->ch_ndrives; drive++) + chp->ch_drive[drive].state = 0; + break; - ata_channel_lock(chp); - KASSERT(chp->ch_ndrives == 0 || chp->ch_drive != NULL); - for (drive = 0; drive < chp->ch_ndrives; drive++) - chp->ch_drive[drive].state = 0; + case ATACH_TH_DRIVE_RESET: + KASSERT(drive <= chp->ch_ndrives); + drvp = &chp->ch_drive[drive]; + (*atac->atac_bustype_ata->ata_reset_drive)(drvp, flags, NULL); + drvp->state = 0; + break; + + default: + panic("%s: unknown type: %x", __func__, type); + /* NOTREACHED */ + } /* * Thaw one extra time to clear the freeze done when the reset has @@ -1693,13 +1723,9 @@ ata_reset_channel(struct ata_channel *ch /* Signal the thread in case there is an xfer to run */ cv_signal(&chp->ch_thr_idle); - ata_channel_unlock(chp); - if (flags & AT_RST_EMERG) { /* make sure that we can use polled commands */ ata_queue_reset(chp->ch_queue); - } else { - atastart(chp); } } @@ -1846,7 +1872,7 @@ ata_downgrade_mode(struct ata_drive_data (*atac->atac_set_modes)(chp); ata_print_modes(chp); /* reset the channel, which will schedule all drives for setup */ - ata_reset_channel(chp, flags); + ata_thread_run(chp, flags, ATACH_TH_RESET, ATACH_NODRIVE); return 1; } #endif /* NATA_DMA */ @@ -2186,7 +2212,6 @@ atabusioctl(dev_t dev, u_long cmd, void struct ata_channel *chp = sc->sc_chan; int min_drive, max_drive, drive; int error; - int s; /* * Enforce write permission for ioctls that change the @@ -2203,9 +2228,10 @@ atabusioctl(dev_t dev, u_long cmd, void switch (cmd) { case ATABUSIORESET: - s = splbio(); - ata_reset_channel(sc->sc_chan, AT_WAIT | AT_POLL); - splx(s); + ata_channel_lock(chp); + ata_thread_run(sc->sc_chan, AT_WAIT | AT_POLL, + ATACH_TH_RESET, ATACH_NODRIVE); + ata_channel_unlock(chp); return 0; case ATABUSIOSCAN: { @@ -2283,11 +2309,11 @@ atabus_resume(device_t dv, const pmf_qua /* unfreeze the queue and reset drives */ ata_channel_thaw_locked(chp); - ata_channel_unlock(chp); - /* reset channel only if there are drives attached */ if (chp->ch_ndrives > 0) - ata_reset_channel(chp, AT_WAIT); + ata_thread_run(chp, AT_WAIT, ATACH_TH_RESET, ATACH_NODRIVE); + + ata_channel_unlock(chp); out: return true; @@ -2336,6 +2362,7 @@ atabus_rescan(device_t self, const char void ata_delay(struct ata_channel *chp, int ms, const char *msg, int flags) { + KASSERT(mutex_owned(&chp->ch_lock)); if ((flags & (AT_WAIT | AT_POLL)) == AT_POLL) { /* @@ -2346,7 +2373,6 @@ ata_delay(struct ata_channel *chp, int m } else { int pause = mstohz(ms); - KASSERT(mutex_owned(&chp->ch_lock)); kpause(msg, false, pause > 0 ? pause : 1, &chp->ch_lock); } } Index: src/sys/dev/ata/atavar.h diff -u src/sys/dev/ata/atavar.h:1.99.2.7 src/sys/dev/ata/atavar.h:1.99.2.8 --- src/sys/dev/ata/atavar.h:1.99.2.7 Sat Sep 22 17:50:09 2018 +++ src/sys/dev/ata/atavar.h Wed Oct 3 19:20:48 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: atavar.h,v 1.99.2.7 2018/09/22 17:50:09 jdolecek Exp $ */ +/* $NetBSD: atavar.h,v 1.99.2.8 2018/10/03 19:20:48 jdolecek Exp $ */ /* * Copyright (c) 1998, 2001 Manuel Bouyer. @@ -274,6 +274,8 @@ struct ata_drive_datas { #define ATA_DRIVE_WFUA 0x0100 /* drive supports WRITE DMA FUA EXT */ #define ATA_DRIVE_NCQ 0x0200 /* drive supports NCQ feature set */ #define ATA_DRIVE_NCQ_PRIO 0x0400 /* drive supports NCQ PRIO field */ +#define ATA_DRIVE_TH_RESET 0x0800 /* drive waits for thread drive reset */ + int drive_reset_flags; /* flags for drive reset via thread */ uint8_t drive_type; #define ATA_DRIVET_NONE 0 @@ -415,6 +417,9 @@ struct ata_channel { #define ATACH_TH_RESCAN 0x400 /* rescan requested */ #define ATACH_NCQ 0x800 /* channel executing NCQ commands */ #define ATACH_DMA_BEFORE_CMD 0x1000 /* start DMA first */ +#define ATACH_TH_DRIVE_RESET 0x2000 /* thread asked for drive(s) reset */ + +#define ATACH_NODRIVE 0xff /* no drive selected for reset */ /* for the reset callback */ int ch_reset_flags; @@ -543,7 +548,7 @@ void ata_timeout(void *); bool ata_timo_xfer_check(struct ata_xfer *); void ata_kill_pending(struct ata_drive_datas *); void ata_kill_active(struct ata_channel *, int, int); -void ata_reset_channel(struct ata_channel *, int); +void ata_thread_run(struct ata_channel *, int, int, int); void ata_channel_freeze(struct ata_channel *); void ata_channel_thaw(struct ata_channel *); void ata_channel_lock(struct ata_channel *); Index: src/sys/dev/ata/wd.c diff -u src/sys/dev/ata/wd.c:1.441.2.6 src/sys/dev/ata/wd.c:1.441.2.7 --- src/sys/dev/ata/wd.c:1.441.2.6 Sat Sep 22 17:50:09 2018 +++ src/sys/dev/ata/wd.c Wed Oct 3 19:20:48 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: wd.c,v 1.441.2.6 2018/09/22 17:50:09 jdolecek Exp $ */ +/* $NetBSD: wd.c,v 1.441.2.7 2018/10/03 19:20:48 jdolecek Exp $ */ /* * Copyright (c) 1998, 2001 Manuel Bouyer. All rights reserved. @@ -54,7 +54,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: wd.c,v 1.441.2.6 2018/09/22 17:50:09 jdolecek Exp $"); +__KERNEL_RCSID(0, "$NetBSD: wd.c,v 1.441.2.7 2018/10/03 19:20:48 jdolecek Exp $"); #include "opt_ata.h" #include "opt_wd.h" @@ -661,8 +661,8 @@ wdstart1(struct wd_softc *wd, struct buf */ if (BUF_ISREAD(bp) && xfer->c_retries == 0 && wd->drv_chaos_freq > 0 && (++wd->drv_chaos_cnt % wd->drv_chaos_freq) == 0) { - aprint_normal_dev(dksc->sc_dev, "%s: chaos xfer %p\n", - __func__, xfer); + device_printf(dksc->sc_dev, "%s: chaos xfer %"PRIxPTR"\n", + __func__, (intptr_t)xfer & PAGE_MASK); xfer->c_bio.blkno = 7777777 + wd->sc_capacity; xfer->c_flags |= C_CHAOS; } @@ -840,7 +840,10 @@ wddone(device_t self, struct ata_xfer *x retry: /* Just reset and retry. Can we do more ? */ if ((xfer->c_flags & C_RECOVERED) == 0) { int wflags = (xfer->c_flags & C_POLL) ? AT_POLL : 0; - (*wd->atabus->ata_reset_drive)(wd->drvp, wflags, NULL); + ata_channel_lock(wd->drvp->chnl_softc); + ata_thread_run(wd->drvp->chnl_softc, wflags, + ATACH_TH_DRIVE_RESET, wd->drvp->drive); + ata_channel_unlock(wd->drvp->chnl_softc); } retry2: mutex_enter(&wd->sc_lock); @@ -848,7 +851,8 @@ retry2: diskerr(bp, "wd", errmsg, LOG_PRINTF, xfer->c_bio.blkdone, dksc->sc_dkdev.dk_label); if (xfer->c_retries < WDIORETRIES) - printf(", xfer %p, retry %d", xfer, + printf(", xfer %"PRIxPTR", retry %d", + (intptr_t)xfer & PAGE_MASK, xfer->c_retries + 1); printf("\n"); if (do_perror) @@ -911,8 +915,9 @@ out: break; case NOERROR: noerror: if ((xfer->c_bio.flags & ATA_CORR) || xfer->c_retries > 0) - aprint_error_dev(dksc->sc_dev, - "soft error (corrected) xfer %p\n", xfer); + device_printf(dksc->sc_dev, + "soft error (corrected) xfer %"PRIxPTR"\n", + (intptr_t)xfer & PAGE_MASK); #ifdef WD_CHAOS_MONKEY KASSERT((xfer->c_flags & C_CHAOS) == 0); #endif Index: src/sys/dev/ic/ahcisata_core.c diff -u src/sys/dev/ic/ahcisata_core.c:1.62.2.5 src/sys/dev/ic/ahcisata_core.c:1.62.2.6 --- src/sys/dev/ic/ahcisata_core.c:1.62.2.5 Sat Sep 22 09:22:59 2018 +++ src/sys/dev/ic/ahcisata_core.c Wed Oct 3 19:20:48 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: ahcisata_core.c,v 1.62.2.5 2018/09/22 09:22:59 jdolecek Exp $ */ +/* $NetBSD: ahcisata_core.c,v 1.62.2.6 2018/10/03 19:20:48 jdolecek Exp $ */ /* * Copyright (c) 2006 Manuel Bouyer. @@ -26,7 +26,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ahcisata_core.c,v 1.62.2.5 2018/09/22 09:22:59 jdolecek Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ahcisata_core.c,v 1.62.2.6 2018/10/03 19:20:48 jdolecek Exp $"); #include <sys/types.h> #include <sys/malloc.h> @@ -683,7 +683,7 @@ ahci_reset_drive(struct ata_drive_datas struct ahci_softc *sc = (struct ahci_softc *)chp->ch_atac; uint8_t c_slot; - ata_channel_lock(chp); + ata_channel_lock_owned(chp); /* get a slot for running the command on */ if (!ata_queue_alloc_slot(chp, &c_slot, ATA_MAX_OPENINGS)) { @@ -696,13 +696,10 @@ ahci_reset_drive(struct ata_drive_datas AHCI_WRITE(sc, AHCI_GHC, AHCI_READ(sc, AHCI_GHC) & ~AHCI_GHC_IE); ahci_channel_stop(sc, chp, flags); - if (ahci_do_reset_drive(chp, drvp->drive, flags, sigp, c_slot) != 0) - ata_reset_channel(chp, flags); + ahci_do_reset_drive(chp, drvp->drive, flags, sigp, c_slot); AHCI_WRITE(sc, AHCI_GHC, AHCI_READ(sc, AHCI_GHC) | AHCI_GHC_IE); ata_queue_free_slot(chp, c_slot); - - ata_channel_unlock(chp); } /* return error code from ata_bio */ Index: src/sys/dev/ic/mvsata.c diff -u src/sys/dev/ic/mvsata.c:1.41.2.4 src/sys/dev/ic/mvsata.c:1.41.2.5 --- src/sys/dev/ic/mvsata.c:1.41.2.4 Sat Sep 22 09:22:59 2018 +++ src/sys/dev/ic/mvsata.c Wed Oct 3 19:20:48 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: mvsata.c,v 1.41.2.4 2018/09/22 09:22:59 jdolecek Exp $ */ +/* $NetBSD: mvsata.c,v 1.41.2.5 2018/10/03 19:20:48 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.41.2.4 2018/09/22 09:22:59 jdolecek Exp $"); +__KERNEL_RCSID(0, "$NetBSD: mvsata.c,v 1.41.2.5 2018/10/03 19:20:48 jdolecek Exp $"); #include "opt_mvsata.h" @@ -703,7 +703,7 @@ mvsata_reset_drive(struct ata_drive_data uint32_t edma_c; uint32_t sig; - ata_channel_lock(chp); + ata_channel_lock_owned(chp); edma_c = MVSATA_EDMA_READ_4(mvport, EDMA_CMD); @@ -726,10 +726,6 @@ mvsata_reset_drive(struct ata_drive_data mvsata_edma_reset_qptr(mvport); mvsata_edma_enable(mvport); } - - ata_channel_unlock(chp); - - return; } #endif /* MVSATA_WITHOUTDMA */ @@ -743,7 +739,7 @@ mvsata_reset_channel(struct ata_channel DPRINTF(DEBUG_FUNCS, ("%s: mvsata_reset_channel: channel=%d\n", device_xname(MVSATA_DEV2(mvport)), chp->ch_channel)); - ata_channel_lock(chp); + ata_channel_lock_owned(chp); mvsata_hreset_port(mvport); sstat = sata_reset_interface(chp, mvport->port_iot, @@ -774,10 +770,6 @@ mvsata_reset_channel(struct ata_channel mvsata_edma_reset_qptr(mvport); mvsata_edma_enable(mvport); #endif - - ata_channel_unlock(chp); - - return; } #ifndef MVSATA_WITHOUTDMA @@ -3563,6 +3555,8 @@ mvsata_edma_disable(struct mvsata_port * uint32_t idlestatus = EDMA_S_EDMAIDLE | EDMA_S_ECACHEEMPTY; int t; + ata_channel_lock_owned(chp); + if (MVSATA_EDMA_READ_4(mvport, EDMA_CMD) & EDMA_CMD_EENEDMA) { timeout = mstohz(timeout + hztoms(1) - 1); Index: src/sys/dev/ic/siisata.c diff -u src/sys/dev/ic/siisata.c:1.35.6.5 src/sys/dev/ic/siisata.c:1.35.6.6 --- src/sys/dev/ic/siisata.c:1.35.6.5 Sat Sep 22 09:22:59 2018 +++ src/sys/dev/ic/siisata.c Wed Oct 3 19:20:48 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: siisata.c,v 1.35.6.5 2018/09/22 09:22:59 jdolecek Exp $ */ +/* $NetBSD: siisata.c,v 1.35.6.6 2018/10/03 19:20:48 jdolecek Exp $ */ /* from ahcisata_core.c */ @@ -79,7 +79,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: siisata.c,v 1.35.6.5 2018/09/22 09:22:59 jdolecek Exp $"); +__KERNEL_RCSID(0, "$NetBSD: siisata.c,v 1.35.6.6 2018/10/03 19:20:48 jdolecek Exp $"); #include <sys/types.h> #include <sys/param.h> @@ -732,7 +732,7 @@ siisata_reset_drive(struct ata_drive_dat siisata_reinit_port(chp, drvp->drive); - ata_channel_lock(chp); + ata_channel_lock_owned(chp); /* get a slot for running the command on */ if (!ata_queue_alloc_slot(chp, &c_slot, ATA_MAX_OPENINGS)) { @@ -783,8 +783,6 @@ siisata_reset_drive(struct ata_drive_dat siisata_enable_port_interrupt(chp); - ata_channel_unlock(chp); - if (timed_out) { /* timeout */ siisata_device_reset(chp); /* XXX is this right? */ @@ -801,11 +799,7 @@ siisata_reset_drive(struct ata_drive_dat } } - ata_channel_lock(chp); ata_queue_free_slot(chp, c_slot); - ata_channel_unlock(chp); - - return; } void @@ -817,6 +811,8 @@ siisata_reset_channel(struct ata_channel SIISATA_DEBUG_PRINT(("%s: %s channel %d\n", SIISATANAME(sc), __func__, chp->ch_channel), DEBUG_FUNCS); + ata_channel_lock_owned(chp); + if (sata_reset_interface(chp, sc->sc_prt, schp->sch_scontrol, schp->sch_sstatus, flags) != SStatus_DET_DEV) { aprint_error("%s port %d: reset failed\n", @@ -1573,6 +1569,8 @@ siisata_device_reset(struct ata_channel struct siisata_softc *sc = (struct siisata_softc *)chp->ch_atac; int ps; + ata_channel_lock_owned(chp); + /* * This is always called after siisata_reinit_port(), so don't * need to deal with RESUME and clearing device error state. Index: src/sys/dev/ic/wdc.c diff -u src/sys/dev/ic/wdc.c:1.288.6.2 src/sys/dev/ic/wdc.c:1.288.6.3 --- src/sys/dev/ic/wdc.c:1.288.6.2 Mon Sep 17 18:36:14 2018 +++ src/sys/dev/ic/wdc.c Wed Oct 3 19:20:48 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: wdc.c,v 1.288.6.2 2018/09/17 18:36:14 jdolecek Exp $ */ +/* $NetBSD: wdc.c,v 1.288.6.3 2018/10/03 19:20:48 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.288.6.2 2018/09/17 18:36:14 jdolecek Exp $"); +__KERNEL_RCSID(0, "$NetBSD: wdc.c,v 1.288.6.3 2018/10/03 19:20:48 jdolecek Exp $"); #include "opt_ata.h" #include "opt_wdc.h" @@ -932,19 +932,24 @@ wdc_reset_drive(struct ata_drive_datas * { struct ata_channel *chp = drvp->chnl_softc; + ata_channel_lock_owned(chp); + KASSERT(sigp == NULL); ATADEBUG_PRINT(("wdc_reset_drive %s:%d for drive %d\n", device_xname(chp->ch_atac->atac_dev), chp->ch_channel, drvp->drive), DEBUG_FUNCS); - ata_reset_channel(chp, flags); + ata_thread_run(chp, flags, ATACH_TH_RESET, ATACH_NODRIVE); } void wdc_reset_channel(struct ata_channel *chp, int flags) { struct ata_xfer *xfer; + + ata_channel_lock_owned(chp); + #if NATA_DMA || NATA_PIOBM struct wdc_softc *wdc = CHAN_TO_WDC(chp); #endif @@ -955,9 +960,7 @@ wdc_reset_channel(struct ata_channel *ch * if the current command is on an ATAPI device, issue a * ATAPI_SOFT_RESET */ - xfer = ata_queue_get_active_xfer(chp); - - ata_channel_lock(chp); + xfer = ata_queue_get_active_xfer_locked(chp); if (xfer && xfer->c_chp == chp && (xfer->c_flags & C_ATAPI)) { wdccommandshort(chp, xfer->c_drive, ATAPI_SOFT_RESET); @@ -984,9 +987,8 @@ wdc_reset_channel(struct ata_channel *ch */ if (xfer) { if (xfer->c_chp != chp) { - ata_channel_unlock(chp); - ata_reset_channel(xfer->c_chp, flags); - ata_channel_lock(chp); + ata_thread_run(xfer->c_chp, flags, ATACH_TH_RESET, + ATACH_NODRIVE); } else { #if NATA_DMA || NATA_PIOBM /* @@ -1004,8 +1006,6 @@ wdc_reset_channel(struct ata_channel *ch } ata_kill_active(chp, KILL_RESET, flags); - - ata_channel_unlock(chp); } static int