Index: sys/arch/evbarm/rpi/rpi_machdep.c =================================================================== RCS file: /cvsroot/src/sys/arch/evbarm/rpi/rpi_machdep.c,v retrieving revision 1.66 diff -u -p -r1.66 rpi_machdep.c --- sys/arch/evbarm/rpi/rpi_machdep.c 31 May 2015 08:13:18 -0000 1.66 +++ sys/arch/evbarm/rpi/rpi_machdep.c 28 Jul 2015 12:41:01 -0000 @@ -534,11 +534,6 @@ rpi_bootstrap(void) __func__, i); } } - - /* - * XXXNH: Disable non-boot CPUs for now - */ - arm_cpu_hatched = 0; #endif } Index: sys/dev/ccdvar.h =================================================================== RCS file: /cvsroot/src/sys/dev/ccdvar.h,v retrieving revision 1.34 diff -u -p -r1.34 ccdvar.h --- sys/dev/ccdvar.h 16 Aug 2014 19:27:27 -0000 1.34 +++ sys/dev/ccdvar.h 28 Jul 2015 12:41:06 -0000 @@ -168,11 +168,15 @@ struct ccd_softc { struct ccdcinfo *sc_cinfo; /* component info */ struct ccdiinfo *sc_itable; /* interleave table */ struct ccdgeom sc_geom; /* pseudo geometry info */ - char sc_xname[8]; /* XXX external name */ - struct disk sc_dkdev; /* generic disk device info */ + kmutex_t sc_dvlock; /* lock on device node */ - struct bufq_state *sc_bufq; /* buffer queue */ - kmutex_t *sc_iolock; /* lock on I/O start/stop */ + + struct bufq_state *sc_bufq; /* dk */ /* buffer queue */ + char sc_xname[8]; /* dk */ /* XXX external name */ + struct disk sc_dkdev; /* dk */ /* generic disk device info */ + + kmutex_t *sc_iolock; /* dk? */ /* lock on I/O start/stop */ + kcondvar_t sc_stop; /* when inflight goes zero */ struct lwp *sc_thread; /* for deferred I/O */ kcondvar_t sc_push; /* for deferred I/O */ Index: sys/dev/dksubr.c =================================================================== RCS file: /cvsroot/src/sys/dev/dksubr.c,v retrieving revision 1.67 diff -u -p -r1.67 dksubr.c --- sys/dev/dksubr.c 22 Jul 2015 10:32:16 -0000 1.67 +++ sys/dev/dksubr.c 28 Jul 2015 12:41:06 -0000 @@ -74,6 +74,28 @@ static int dk_subr_modcmd(modcmd_t, void static void dk_makedisklabel(struct dk_softc *); +static inline void +dk_lock(struct dk_softc *dksc) +{ + if (dksc->sc_iolock) + mutex_enter(dksc->sc_iolock); +} + +static inline void +dk_unlock(struct dk_softc *dksc) +{ + if (dksc->sc_iolock) + mutex_exit(dksc->sc_iolock); +} + +static inline void +dk_assertlock(struct dk_softc *dksc) +{ + if (dksc->sc_iolock) { + KASSERT(mutex_owned(dksc->sc_iolock)); + } +} + void dk_init(struct dk_softc *dksc, device_t dev, int dtype) { @@ -89,16 +111,20 @@ dk_init(struct dk_softc *dksc, device_t void dk_attach(struct dk_softc *dksc) { + dk_lock(dksc); dksc->sc_flags |= DKF_INITED; #ifdef DIAGNOSTIC dksc->sc_flags |= DKF_WARNLABEL | DKF_LABELSANITY; #endif + dk_unlock(dksc); } void dk_detach(struct dk_softc *dksc) { + dk_lock(dksc); dksc->sc_flags &= ~DKF_INITED; + dk_unlock(dksc); } /* ARGSUSED */ @@ -203,7 +229,7 @@ void dk_strategy(struct dk_softc *dksc, struct buf *bp) { const struct dkdriver *dkd = dksc->sc_dkdev.dk_driver; - int s, part; + int part; int wlabel; daddr_t blkno; struct disklabel *lp; @@ -214,9 +240,13 @@ dk_strategy(struct dk_softc *dksc, struc DPRINTF_FOLLOW(("dk_strategy(%s, %p, %p)\n", dksc->sc_xname, dksc, bp)); + dk_lock(dksc); + + /* Synchronize with init/uninit. */ if (!(dksc->sc_flags & DKF_INITED)) { + dk_unlock(dksc); DPRINTF_FOLLOW(("dk_strategy: not inited\n")); - bp->b_error = ENXIO; + bp->b_error = ENXIO; biodone(bp); return; } @@ -235,6 +265,8 @@ dk_strategy(struct dk_softc *dksc, struc * not be negative. */ if ((bp->b_bcount % secsize) != 0 || bp->b_blkno < 0) { + dk_unlock(dksc); + bp->b_error = EINVAL; biodone(bp); return; @@ -242,6 +274,8 @@ dk_strategy(struct dk_softc *dksc, struc /* If there is nothing to do, then we are done */ if (bp->b_bcount == 0) { + dk_unlock(dksc); + biodone(bp); return; } @@ -249,11 +283,13 @@ dk_strategy(struct dk_softc *dksc, struc wlabel = dksc->sc_flags & (DKF_WLABEL|DKF_LABELLING); if (part == RAW_PART) { if (bounds_check_with_mediasize(bp, DEV_BSIZE, numsecs) <= 0) { + dk_unlock(dksc); biodone(bp); return; } } else { if (bounds_check_with_label(&dksc->sc_dkdev, bp, wlabel) <= 0) { + dk_unlock(dksc); biodone(bp); return; } @@ -276,10 +312,10 @@ dk_strategy(struct dk_softc *dksc, struc * Start the unit by calling the start routine * provided by the individual driver. */ - s = splbio(); + dk_assertlock(dksc); bufq_put(dksc->sc_bufq, bp); dkd->d_diskstart(dksc->sc_dev); - splx(s); + return; } @@ -288,17 +324,24 @@ dk_done(struct dk_softc *dksc, struct bu { struct disk *dk = &dksc->sc_dkdev; + dk_assertlock(dksc); + if (bp->b_error != 0) { - diskerr(bp, dksc->sc_xname, "error", LOG_PRINTF, 0, + char msg[128]; + snprintf(msg, sizeof(msg), "error %d", bp->b_error); + diskerr(bp, dksc->sc_xname, msg, LOG_PRINTF, 0, dk->dk_label); printf("\n"); + Debugger(); } disk_unbusy(dk, bp->b_bcount - bp->b_resid, (bp->b_flags & B_READ)); #ifdef notyet rnd_add_uint(&dksc->sc_rnd_source, bp->b_rawblkno); #endif + dk_unlock(dksc); biodone(bp); + dk_lock(dksc); } int @@ -356,12 +399,15 @@ dk_ioctl(struct dk_softc *dksc, dev_t de case ODIOCWDINFO: #endif case DIOCWLABEL: + case DIOCKLABEL: case DIOCAWEDGE: case DIOCDWEDGE: + case DIOCSSTRATEGY: if ((flag & FWRITE) == 0) return EBADF; } + dk_lock(dksc); /* ensure that the pseudo-disk is initialized for these */ switch (cmd) { case DIOCGDINFO: @@ -382,15 +428,17 @@ dk_ioctl(struct dk_softc *dksc, dev_t de case ODIOCWDINFO: case ODIOCGDEFLABEL: #endif - if ((dksc->sc_flags & DKF_INITED) == 0) + if ((dksc->sc_flags & DKF_INITED) == 0) { + dk_unlock(dksc); return ENXIO; + } } error = disk_ioctl(dk, dev, cmd, data, flag, l); if (error != EPASSTHROUGH) - return error; - else - error = 0; + goto done; + + error = 0; switch (cmd) { case DIOCWDINFO: @@ -429,8 +477,6 @@ dk_ioctl(struct dk_softc *dksc, dev_t de break; case DIOCKLABEL: - if ((flag & FWRITE) == 0) - return (EBADF); if (*(int *)data != 0) dksc->sc_flags |= DKF_KLABEL; else @@ -460,12 +506,11 @@ dk_ioctl(struct dk_softc *dksc, dev_t de case DIOCGSTRATEGY: { struct disk_strategy *dks = (void *)data; - int s; - s = splbio(); + dk_lock(dksc); strlcpy(dks->dks_name, bufq_getstrategyname(dksc->sc_bufq), sizeof(dks->dks_name)); - splx(s); + dk_unlock(dksc); dks->dks_paramlen = 0; return 0; @@ -476,11 +521,7 @@ dk_ioctl(struct dk_softc *dksc, dev_t de struct disk_strategy *dks = (void *)data; struct bufq_state *new; struct bufq_state *old; - int s; - if ((flag & FWRITE) == 0) { - return EBADF; - } if (dks->dks_param != NULL) { return EINVAL; } @@ -490,11 +531,12 @@ dk_ioctl(struct dk_softc *dksc, dev_t de if (error) { return error; } - s = splbio(); + dk_lock(dksc); old = dksc->sc_bufq; bufq_move(new, old); dksc->sc_bufq = new; - splx(s); + dk_unlock(dksc); + bufq_free(old); return 0; @@ -503,7 +545,8 @@ dk_ioctl(struct dk_softc *dksc, dev_t de default: error = ENOTTY; } - +done: + dk_unlock(dksc); return error; } Index: sys/dev/dkvar.h =================================================================== RCS file: /cvsroot/src/sys/dev/dkvar.h,v retrieving revision 1.20 diff -u -p -r1.20 dkvar.h --- sys/dev/dkvar.h 2 May 2015 08:00:08 -0000 1.20 +++ sys/dev/dkvar.h 28 Jul 2015 12:41:06 -0000 @@ -31,7 +31,8 @@ struct pathbuf; /* from namei.h */ -/* literally this is not a softc, but is intended to be included in +/* + * literally this is not a softc, but is intended to be included in * the pseudo-disk's softc and passed to calls in dksubr.c. It * should include the common elements of the pseudo-disk's softc. * All elements that are included here should describe the external @@ -44,6 +45,7 @@ struct dk_softc { #define DK_XNAME_SIZE 8 char sc_xname[DK_XNAME_SIZE]; /* external name */ struct disk sc_dkdev; /* generic disk info */ + kmutex_t *sc_iolock; /* protects buffer queue */ struct bufq_state *sc_bufq; /* buffer queue */ int sc_dtype; /* disk type */ }; Index: sys/dev/ld.c =================================================================== RCS file: /cvsroot/src/sys/dev/ld.c,v retrieving revision 1.84 diff -u -p -r1.84 ld.c --- sys/dev/ld.c 22 Jul 2015 10:32:16 -0000 1.84 +++ sys/dev/ld.c 28 Jul 2015 12:41:06 -0000 @@ -30,7 +30,7 @@ */ /* - * Disk driver for use by RAID controllers. + * Disk driver for use by RAID controllers and SD/MMC devices. */ #include @@ -60,6 +60,16 @@ __KERNEL_RCSID(0, "$NetBSD: ld.c,v 1.84 #include +/* + * Logical Disk driver. + * + * Notes on concurrency: + * + * => sc_mutex serializes access to ld_softc members, and to sc_bufq and disk + * stats of dk_softc if non-NULL. This is a temporary measure while + * all users of ld(4) are updated. + */ + static void ldminphys(struct buf *bp); static bool ld_suspend(device_t, const pmf_qual_t *); static bool ld_shutdown(device_t, int); @@ -90,7 +100,7 @@ const struct bdevsw ld_bdevsw = { .d_dump = lddump, .d_psize = ldsize, .d_discard = nodiscard, - .d_flag = D_DISK + .d_flag = D_DISK | D_MPSAFE }; const struct cdevsw ld_cdevsw = { @@ -105,7 +115,7 @@ const struct cdevsw ld_cdevsw = { .d_mmap = nommap, .d_kqfilter = nokqfilter, .d_discard = nodiscard, - .d_flag = D_DISK + .d_flag = D_DISK | D_MPSAFE }; static struct dkdriver lddkdriver = { @@ -125,14 +135,17 @@ ldattach(struct ld_softc *sc) device_t self = sc->sc_dv; struct dk_softc *dksc = &sc->sc_dksc; - mutex_init(&sc->sc_mutex, MUTEX_DEFAULT, IPL_VM); - if ((sc->sc_flags & LDF_ENABLED) == 0) { return; } +// cv_init(&sc->sc_stop, "lddstop"); +// cv_init(&sc->sc_work, "ldwork"); /* Initialise dk and disk structure. */ dk_init(dksc, self, DKTYPE_LD); + /* Could be NULL until all backends are converted */ + dksc->sc_iolock = sc->sc_mutex; + disk_init(&dksc->sc_dkdev, dksc->sc_xname, &lddkdriver); /* Attach the device into the rnd source list. */ @@ -168,11 +181,10 @@ ldattach(struct ld_softc *sc) int ldadjqparam(struct ld_softc *sc, int xmax) { - int s; - s = splbio(); + mutex_enter(sc->sc_mutex); sc->sc_maxqueuecnt = xmax; - splx(s); + mutex_exit(sc->sc_mutex); return (0); } @@ -181,57 +193,60 @@ int ldbegindetach(struct ld_softc *sc, int flags) { struct dk_softc *dksc = &sc->sc_dksc; - int s, rv = 0; + int rv = 0; if ((sc->sc_flags & LDF_ENABLED) == 0) - return (0); + return 0; rv = disk_begindetach(&dksc->sc_dkdev, ld_lastclose, dksc->sc_dev, flags); if (rv != 0) return rv; - s = splbio(); + mutex_enter(sc->sc_mutex); sc->sc_maxqueuecnt = 0; dk_detach(dksc); while (sc->sc_queuecnt > 0) { sc->sc_flags |= LDF_DRAIN; - rv = tsleep(&sc->sc_queuecnt, PRIBIO, "lddrn", 0); + rv = cv_timedwait(&sc->sc_stop, dksc->sc_iolock, hz); if (rv) break; } - splx(s); + mutex_exit(sc->sc_mutex); return (rv); } + void ldenddetach(struct ld_softc *sc) { struct dk_softc *dksc = &sc->sc_dksc; - int s, bmaj, cmaj, i, mn; + int bmaj, cmaj, i, mn; if ((sc->sc_flags & LDF_ENABLED) == 0) return; + mutex_enter(sc->sc_mutex); /* Wait for commands queued with the hardware to complete. */ - if (sc->sc_queuecnt != 0) - if (tsleep(&sc->sc_queuecnt, PRIBIO, "lddtch", 30 * hz)) + while (sc->sc_queuecnt != 0) { + cv_timedwait(&sc->sc_stop, dksc->sc_iolock, hz); + if (false) printf("%s: not drained\n", dksc->sc_xname); - - /* Locate the major numbers. */ - bmaj = bdevsw_lookup_major(&ld_bdevsw); - cmaj = cdevsw_lookup_major(&ld_cdevsw); + } /* Kill off any queued buffers. */ - s = splbio(); bufq_drain(dksc->sc_bufq); - splx(s); + mutex_exit(sc->sc_mutex); bufq_free(dksc->sc_bufq); + /* Locate the major numbers. */ + bmaj = bdevsw_lookup_major(&ld_bdevsw); + cmaj = cdevsw_lookup_major(&ld_cdevsw); + /* Nuke the vnodes for any open instances. */ for (i = 0; i < MAXPARTITIONS; i++) { mn = DISKMINOR(device_unit(dksc->sc_dev), i); @@ -263,7 +278,6 @@ ldenddetach(struct ld_softc *sc) if ((*sc->sc_flush)(sc, 0) != 0) aprint_error_dev(dksc->sc_dev, "unable to flush cache\n"); #endif - mutex_destroy(&sc->sc_mutex); } /* ARGSUSED */ @@ -298,7 +312,8 @@ ldopen(dev_t dev, int flags, int fmt, st unit = DISKUNIT(dev); if ((sc = device_lookup_private(&ld_cd, unit)) == NULL) - return (ENXIO); + return ENXIO; + dksc = &sc->sc_dksc; return dk_open(dksc, dev, flags, fmt, l); @@ -358,13 +373,15 @@ ldioctl(dev_t dev, u_long cmd, void *add sc = device_lookup_private(&ld_cd, unit); dksc = &sc->sc_dksc; +// mutex_enter(xxx); + error = disk_ioctl(&dksc->sc_dkdev, dev, cmd, addr, flag, l); if (error != EPASSTHROUGH) - return (error); + return error; error = dk_ioctl(dksc, dev, cmd, addr, flag, l); if (error != EPASSTHROUGH) - return (error); + return error; error = 0; @@ -386,7 +403,7 @@ ldioctl(dev_t dev, u_long cmd, void *add break; } - return (error); + return error; } static void @@ -411,7 +428,7 @@ ld_start(device_t dev) struct buf *bp; int error; - mutex_enter(&sc->sc_mutex); + KASSERT(mutex_owned(dksc->sc_iolock)); while (sc->sc_queuecnt < sc->sc_maxqueuecnt) { /* See if there is work to do. */ @@ -423,8 +440,8 @@ ld_start(device_t dev) if (__predict_true((error = (*sc->sc_start)(sc, bp)) == 0)) { /* - * The back-end is running the job; remove it from - * the queue. + * The back-end is running/will run the job; remove it + * from the queue. */ (void) bufq_get(dksc->sc_bufq); } else { @@ -444,14 +461,14 @@ ld_start(device_t dev) (void) bufq_get(dksc->sc_bufq); bp->b_error = error; bp->b_resid = bp->b_bcount; - mutex_exit(&sc->sc_mutex); + mutex_exit(sc->sc_mutex); biodone(bp); - mutex_enter(&sc->sc_mutex); + return; } } } - mutex_exit(&sc->sc_mutex); + mutex_exit(sc->sc_mutex); } void @@ -459,18 +476,19 @@ lddone(struct ld_softc *sc, struct buf * { struct dk_softc *dksc = &sc->sc_dksc; + KASSERT(mutex_owned(dksc->sc_iolock)); dk_done(dksc, bp); - mutex_enter(&sc->sc_mutex); if (--sc->sc_queuecnt <= sc->sc_maxqueuecnt) { if ((sc->sc_flags & LDF_DRAIN) != 0) { sc->sc_flags &= ~LDF_DRAIN; - wakeup(&sc->sc_queuecnt); + cv_broadcast(&sc->sc_stop); } - mutex_exit(&sc->sc_mutex); + /* releases lock */ ld_start(dksc->sc_dev); - } else - mutex_exit(&sc->sc_mutex); + return; + } + mutex_exit(sc->sc_mutex); } static int Index: sys/dev/ldvar.h =================================================================== RCS file: /cvsroot/src/sys/dev/ldvar.h,v retrieving revision 1.24 diff -u -p -r1.24 ldvar.h --- sys/dev/ldvar.h 26 Jul 2015 07:23:10 -0000 1.24 +++ sys/dev/ldvar.h 28 Jul 2015 12:41:06 -0000 @@ -39,9 +39,10 @@ struct ld_softc { struct dk_softc sc_dksc; - kmutex_t sc_mutex; + kmutex_t *sc_mutex; /* Protects some members of dk_softc */ krndsource_t sc_rnd_source; + kcondvar_t sc_stop; int sc_queuecnt; /* current h/w queue depth */ int sc_ncylinders; /* # cylinders */ int sc_nheads; /* # heads */ Index: sys/dev/sdmmc/ld_sdmmc.c =================================================================== RCS file: /cvsroot/src/sys/dev/sdmmc/ld_sdmmc.c,v retrieving revision 1.17 diff -u -p -r1.17 ld_sdmmc.c --- sys/dev/sdmmc/ld_sdmmc.c 27 Jul 2015 07:53:46 -0000 1.17 +++ sys/dev/sdmmc/ld_sdmmc.c 28 Jul 2015 12:41:07 -0000 @@ -62,12 +62,13 @@ struct ld_sdmmc_softc; struct ld_sdmmc_task { struct sdmmc_task task; - struct ld_sdmmc_softc *task_sc; + struct ld_softc *task_ld; struct buf *task_bp; }; struct ld_sdmmc_softc { struct ld_softc sc_ld; +// kmutex_t *sc_mutex; int sc_hwunit; struct sdmmc_function *sc_sf; @@ -118,6 +119,12 @@ ld_sdmmc_attach(device_t parent, device_ sc->sc_hwunit = 0; /* always 0? */ sc->sc_sf = sa->sf; + /* + * We're synchronizing against other threads and not interrupt + * handlers? XXXNH IPL_VM for now - not sure that's correct. + */ + + ld->sc_mutex = mutex_obj_alloc(MUTEX_DEFAULT, IPL_VM); ld->sc_flags = LDF_ENABLED; ld->sc_secperunit = sc->sc_sf->csd.capacity; ld->sc_secsize = SDMMC_SECTOR_SIZE; @@ -173,10 +180,22 @@ ld_sdmmc_detach(device_t dev, int flags) static int ld_sdmmc_start(struct ld_softc *ld, struct buf *bp) { + struct dk_softc *dksc __diagused = &ld->sc_dksc; struct ld_sdmmc_softc *sc = device_private(ld->sc_dv); struct ld_sdmmc_task *task = &sc->sc_task; - task->task_sc = sc; + KASSERT(mutex_owned(dksc->sc_iolock)); + + /* is everything done in terms of blocks? */ + if (bp->b_rawblkno >= sc->sc_sf->csd.capacity) { + /* trying to read or write past end of device */ + aprint_error_dev(sc->sc_ld.sc_dv, + "blkno 0x%" PRIu64 " exceeds capacity %d\n", + bp->b_rawblkno, sc->sc_sf->csd.capacity); + return EINVAL; + } + + task->task_ld = ld; task->task_bp = bp; sdmmc_init_task(&task->task, ld_sdmmc_dobio, task); @@ -188,10 +207,15 @@ ld_sdmmc_start(struct ld_softc *ld, stru static void ld_sdmmc_dobio(void *arg) { - struct ld_sdmmc_task *task = (struct ld_sdmmc_task *)arg; - struct ld_sdmmc_softc *sc = task->task_sc; + struct ld_sdmmc_task *task = arg; + struct ld_softc *ld = task->task_ld; struct buf *bp = task->task_bp; - int error, s; + struct dk_softc *dksc = &ld->sc_dksc; + struct ld_sdmmc_softc *sc = device_private(ld->sc_dv); + int error; + + /* buf won't be off the queue until we have acquired the lock */ + mutex_enter(dksc->sc_iolock); /* * I/O operation @@ -208,19 +232,19 @@ ld_sdmmc_dobio(void *arg) bp->b_rawblkno, sc->sc_sf->csd.capacity); bp->b_error = EINVAL; bp->b_resid = bp->b_bcount; - s = splbio(); + /* releases lock */ lddone(&sc->sc_ld, bp); - splx(s); return; } - s = splbio(); + mutex_exit(dksc->sc_iolock); if (bp->b_flags & B_READ) error = sdmmc_mem_read_block(sc->sc_sf, bp->b_rawblkno, bp->b_data, bp->b_bcount); else error = sdmmc_mem_write_block(sc->sc_sf, bp->b_rawblkno, bp->b_data, bp->b_bcount); + if (error) { DPRINTF(("%s: error %d\n", device_xname(sc->sc_ld.sc_dv), error)); @@ -230,8 +254,10 @@ ld_sdmmc_dobio(void *arg) bp->b_resid = 0; } + mutex_enter(dksc->sc_iolock); + + /* releases lock */ lddone(&sc->sc_ld, bp); - splx(s); } static int Index: sys/dev/sdmmc/sdmmc.c =================================================================== RCS file: /cvsroot/src/sys/dev/sdmmc/sdmmc.c,v retrieving revision 1.27 diff -u -p -r1.27 sdmmc.c --- sys/dev/sdmmc/sdmmc.c 28 Jul 2015 06:19:47 -0000 1.27 +++ sys/dev/sdmmc/sdmmc.c 28 Jul 2015 12:41:07 -0000 @@ -150,8 +150,8 @@ sdmmc_attach(device_t parent, device_t s mutex_init(&sc->sc_mtx, MUTEX_DEFAULT, IPL_SDMMC); mutex_init(&sc->sc_tskq_mtx, MUTEX_DEFAULT, IPL_SDMMC); - mutex_init(&sc->sc_discover_task_mtx, MUTEX_DEFAULT, IPL_SDMMC); - mutex_init(&sc->sc_intr_task_mtx, MUTEX_DEFAULT, IPL_SDMMC); +// mutex_init(&sc->sc_discover_task_mtx, MUTEX_DEFAULT, IPL_SDMMC); +// mutex_init(&sc->sc_intr_task_mtx, MUTEX_DEFAULT, IPL_SDMMC); cv_init(&sc->sc_tskq_cv, "mmctaskq"); if (ISSET(sc->sc_caps, SMC_CAPS_POLL_CARD_DET)) { @@ -207,7 +207,7 @@ sdmmc_detach(device_t self, int flags) mutex_destroy(&sc->sc_intr_task_mtx); mutex_destroy(&sc->sc_discover_task_mtx); mutex_destroy(&sc->sc_tskq_mtx); - mutex_destroy(&sc->sc_mtx); + //mutex_destroy(&sc->sc_mtx); return 0; } @@ -217,7 +217,7 @@ sdmmc_doattach(device_t dev) { struct sdmmc_softc *sc = device_private(dev); - if (kthread_create(PRI_BIO, 0, NULL, + if (kthread_create(PRI_BIO, 0 /*KTHREAD_MPSAFE*/, curcpu()/*NULL*/, sdmmc_task_thread, sc, &sc->sc_tskq_lwp, "%s", device_xname(dev))) { aprint_error_dev(dev, "couldn't create task thread\n"); } @@ -228,10 +228,12 @@ sdmmc_add_task(struct sdmmc_softc *sc, s { mutex_enter(&sc->sc_tskq_mtx); - task->onqueue = 1; - task->sc = sc; - TAILQ_INSERT_TAIL(&sc->sc_tskq, task, next); - cv_broadcast(&sc->sc_tskq_cv); + if (!task->onqueue) { + task->onqueue = 1; + task->sc = sc; + TAILQ_INSERT_TAIL(&sc->sc_tskq, task, next); + cv_broadcast(&sc->sc_tskq_cv); + } mutex_exit(&sc->sc_tskq_mtx); } @@ -239,6 +241,7 @@ static inline void sdmmc_del_task1(struct sdmmc_softc *sc, struct sdmmc_task *task) { + KASSERT(mutex_owned(&sc->sc_tskq_mtx)); TAILQ_REMOVE(&sc->sc_tskq, task, next); task->sc = NULL; task->onqueue = 0; @@ -306,8 +309,7 @@ sdmmc_needs_discover(device_t dev) return; mutex_enter(&sc->sc_discover_task_mtx); - if (!sdmmc_task_pending(&sc->sc_discover_task)) - sdmmc_add_task(sc, &sc->sc_discover_task); + sdmmc_add_task(sc, &sc->sc_discover_task); mutex_exit(&sc->sc_discover_task_mtx); } @@ -336,9 +338,8 @@ sdmmc_polling_card(void *arg) { struct sdmmc_softc *sc = (struct sdmmc_softc *)arg; int card_detect; - int s; - s = splsdmmc(); + mutex_enter(&sc->sc_mtx); card_detect = sdmmc_chip_card_detect(sc->sc_sct, sc->sc_sch); if (card_detect) { if (!ISSET(sc->sc_flags, SMF_CARD_PRESENT)) { @@ -349,7 +350,7 @@ sdmmc_polling_card(void *arg) sdmmc_needs_discover(sc->sc_dev); } } - splx(s); + mutex_exit(&sc->sc_mtx); callout_schedule(&sc->sc_card_detect_ch, hz); }