Module Name:    src
Committed By:   jdolecek
Date:           Wed Apr 12 21:59:14 UTC 2017

Modified Files:
        src/sys/dev/ata [jdolecek-ncq]: wd.c wdvar.h

Log Message:
convert to mutex, mark MPSAFE


To generate a diff of this commit:
cvs rdiff -u -r1.428 -r1.428.2.1 src/sys/dev/ata/wd.c
cvs rdiff -u -r1.43 -r1.43.4.1 src/sys/dev/ata/wdvar.h

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/wd.c
diff -u src/sys/dev/ata/wd.c:1.428 src/sys/dev/ata/wd.c:1.428.2.1
--- src/sys/dev/ata/wd.c:1.428	Sun Mar  5 23:07:12 2017
+++ src/sys/dev/ata/wd.c	Wed Apr 12 21:59:14 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: wd.c,v 1.428 2017/03/05 23:07:12 mlelstv Exp $ */
+/*	$NetBSD: wd.c,v 1.428.2.1 2017/04/12 21:59:14 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.428 2017/03/05 23:07:12 mlelstv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: wd.c,v 1.428.2.1 2017/04/12 21:59:14 jdolecek Exp $");
 
 #include "opt_ata.h"
 
@@ -150,7 +150,7 @@ const struct bdevsw wd_bdevsw = {
 	.d_dump = wddump,
 	.d_psize = wdsize,
 	.d_discard = wddiscard,
-	.d_flag = D_DISK
+	.d_flag = D_DISK | D_MPSAFE
 };
 
 const struct cdevsw wd_cdevsw = {
@@ -165,7 +165,7 @@ const struct cdevsw wd_cdevsw = {
 	.d_mmap = nommap,
 	.d_kqfilter = nokqfilter,
 	.d_discard = wddiscard,
-	.d_flag = D_DISK
+	.d_flag = D_DISK | D_MPSAFE
 };
 
 /*
@@ -181,11 +181,9 @@ struct wd_ioctl {
 	struct wd_softc *wi_softc;
 };
 
-LIST_HEAD(, wd_ioctl) wi_head;
-
 struct	wd_ioctl *wi_find(struct buf *);
 void	wi_free(struct wd_ioctl *);
-struct	wd_ioctl *wi_get(void);
+struct	wd_ioctl *wi_get(struct wd_softc *);
 void	wdioctlstrategy(struct buf *);
 
 void  wdgetdefaultlabel(struct wd_softc *, struct disklabel *);
@@ -297,10 +295,12 @@ wdattach(device_t parent, device_t self,
 
 	ATADEBUG_PRINT(("wdattach\n"), DEBUG_FUNCS | DEBUG_PROBE);
 	callout_init(&wd->sc_restart_ch, 0);
+	mutex_init(&wd->sc_lock, MUTEX_DEFAULT, IPL_BIO);
 	bufq_alloc(&wd->sc_q, BUFQ_DISK_DEFAULT_STRAT, BUFQ_SORT_RAWBLOCK);
 #ifdef WD_SOFTBADSECT
 	SLIST_INIT(&wd->sc_bslist);
 #endif
+	LIST_INIT(&wd->wi_head);
 	wd->atabus = adev->adev_bustype;
 	wd->openings = adev->adev_openings;
 	wd->drvp = adev->adev_drv_data;
@@ -458,7 +458,7 @@ int
 wddetach(device_t self, int flags)
 {
 	struct wd_softc *sc = device_private(self);
-	int bmaj, cmaj, i, mn, rc, s;
+	int bmaj, cmaj, i, mn, rc;
 
 	if ((rc = disk_begindetach(&sc->sc_dk, wdlastclose, self, flags)) != 0)
 		return rc;
@@ -477,7 +477,7 @@ wddetach(device_t self, int flags)
 	/* Delete all of our wedges. */
 	dkwedge_delall(&sc->sc_dk);
 
-	s = splbio();
+	mutex_enter(&sc->sc_lock);
 
 	/* Kill off any queued buffers. */
 	bufq_drain(sc->sc_q);
@@ -486,7 +486,7 @@ wddetach(device_t self, int flags)
 	if (flags & DETACH_POWEROFF)
 		wd_standby(sc, AT_POLL);
 
-	splx(s);
+	mutex_exit(&sc->sc_lock);
 	bufq_free(sc->sc_q);
 
 	/* Detach disk. */
@@ -502,6 +502,7 @@ wddetach(device_t self, int flags)
 	}
 	sc->sc_bscount = 0;
 #endif
+	KASSERT(LIST_EMPTY(&sc->wi_head));
 
 	pmf_device_deregister(self);
 
@@ -527,7 +528,6 @@ wdstrategy(struct buf *bp)
 	    device_lookup_private(&wd_cd, WDUNIT(bp->b_dev));
 	struct disklabel *lp = wd->sc_dk.dk_label;
 	daddr_t blkno;
-	int s;
 
 	ATADEBUG_PRINT(("wdstrategy (%s)\n", device_xname(wd->sc_dev)),
 	    DEBUG_XFERS);
@@ -604,11 +604,11 @@ wdstrategy(struct buf *bp)
 #endif
 
 	/* Queue transfer on drive, activate drive and controller if idle. */
-	s = splbio();
+	mutex_enter(&wd->sc_lock);
 	disk_wait(&wd->sc_dk);
 	bufq_put(wd->sc_q, bp);
 	wdstart(wd);
-	splx(s);
+	mutex_exit(&wd->sc_lock);
 	return;
 done:
 	/* Toss transfer; we're done early. */
@@ -651,9 +651,8 @@ static void
 wd_split_mod15_write(struct buf *bp)
 {
 	struct buf *obp = bp->b_private;
-	struct wd_softc *sc =
+	struct wd_softc *wd =
 	    device_lookup_private(&wd_cd, DISKUNIT(obp->b_dev));
-	int s;
 
 	if (__predict_false(bp->b_error != 0)) {
 		/*
@@ -681,26 +680,28 @@ wd_split_mod15_write(struct buf *bp)
 	bp->b_cflags = obp->b_cflags;
 	bp->b_data = (char *)bp->b_data + bp->b_bcount;
 	bp->b_blkno += (bp->b_bcount / DEV_BSIZE);
-	bp->b_rawblkno += (bp->b_bcount / sc->sc_blksize);
-	s = splbio();
-	wdstart1(sc, bp);
-	splx(s);
+	bp->b_rawblkno += (bp->b_bcount / wd->sc_blksize);
+	mutex_enter(&wd->sc_lock);
+	wdstart1(wd, bp);
+	mutex_exit(&wd->sc_lock);
 	return;
 
  done:
 	obp->b_error = bp->b_error;
 	obp->b_resid = bp->b_resid;
-	s = splbio();
+	mutex_enter(&wd->sc_lock);
 	putiobuf(bp);
 	biodone(obp);
-	sc->openings++;
-	splx(s);
+	wd->openings++;
+	mutex_exit(&wd->sc_lock);
 	/* wddone() will call wdstart() */
 }
 
 void
 wdstart1(struct wd_softc *wd, struct buf *bp)
 {
+	/* already locked */
+	KASSERT(mutex_owned(&wd->sc_lock));
 
 	/*
 	 * Deal with the "split mod15 write" quirk.  We just divide the
@@ -716,7 +717,6 @@ wdstart1(struct wd_softc *wd, struct buf
 			    ((bp->b_bcount / 512) % 15) == 1)) {
 		struct buf *nbp;
 
-		/* already at splbio */
 		nbp = getiobuf(NULL, false);
 		if (__predict_false(nbp == NULL)) {
 			/* No memory -- fail the iop. */
@@ -757,6 +757,7 @@ wdstart1(struct wd_softc *wd, struct buf
 	wd->sc_wdc_bio.blkdone =0;
 	KASSERT(bp == wd->sc_bp || wd->sc_bp == NULL);
 	wd->sc_bp = bp;
+
 	/*
 	 * If we're retrying, retry in single-sector mode. This will give us
 	 * the sector number of the problem, and will eventually allow the
@@ -899,13 +900,12 @@ wdrestart(void *v)
 {
 	struct wd_softc *wd = v;
 	struct buf *bp = wd->sc_bp;
-	int s;
 
 	ATADEBUG_PRINT(("wdrestart %s\n", device_xname(wd->sc_dev)),
 	    DEBUG_XFERS);
-	s = splbio();
+	mutex_enter(&wd->sc_lock);
 	wdstart1(v, bp);
-	splx(s);
+	mutex_exit(&wd->sc_lock);
 }
 
 static void
@@ -1125,7 +1125,6 @@ wdgetdisklabel(struct wd_softc *wd)
 {
 	struct disklabel *lp = wd->sc_dk.dk_label;
 	const char *errstring;
-	int s;
 
 	ATADEBUG_PRINT(("wdgetdisklabel\n"), DEBUG_FUNCS);
 
@@ -1136,9 +1135,9 @@ wdgetdisklabel(struct wd_softc *wd)
 	wd->sc_badsect[0] = -1;
 
 	if (wd->drvp->state > RESET) {
-		s = splbio();
+		mutex_enter(&wd->sc_lock);
 		wd->drvp->drive_flags |= ATA_DRIVE_RESET;
-		splx(s);
+		mutex_exit(&wd->sc_lock);
 	}
 	errstring = readdisklabel(MAKEWDDEV(0, device_unit(wd->sc_dev),
 				  RAW_PART), wdstrategy, lp,
@@ -1151,9 +1150,9 @@ wdgetdisklabel(struct wd_softc *wd)
 		 * again.  XXX This is a kluge.
 		 */
 		if (wd->drvp->state > RESET) {
-			s = splbio();
+			mutex_enter(&wd->sc_lock);
 			wd->drvp->drive_flags |= ATA_DRIVE_RESET;
-			splx(s);
+			mutex_exit(&wd->sc_lock);
 		}
 		errstring = readdisklabel(MAKEWDDEV(0, device_unit(wd->sc_dev),
 		    RAW_PART), wdstrategy, lp, wd->sc_dk.dk_cpulabel);
@@ -1164,9 +1163,9 @@ wdgetdisklabel(struct wd_softc *wd)
 	}
 
 	if (wd->drvp->state > RESET) {
-		s = splbio();
+		mutex_enter(&wd->sc_lock);
 		wd->drvp->drive_flags |= ATA_DRIVE_RESET;
-		splx(s);
+		mutex_exit(&wd->sc_lock);
 	}
 #ifdef HAS_BAD144_HANDLING
 	if ((lp->d_flags & D_BADSECT) != 0)
@@ -1218,7 +1217,7 @@ wdioctl(dev_t dev, u_long xfer, void *ad
 {
 	struct wd_softc *wd =
 	    device_lookup_private(&wd_cd, WDUNIT(dev));
-	int error, s;
+	int error;
 #ifdef __HAVE_OLD_DISKLABEL
 	struct disklabel *newlabel = NULL;
 #endif
@@ -1331,9 +1330,9 @@ wdioctl(dev_t dev, u_long xfer, void *ad
 		    wd->sc_dk.dk_cpulabel);
 		if (error == 0) {
 			if (wd->drvp->state > RESET) {
-				s = splbio();
+				mutex_enter(&wd->sc_lock);
 				wd->drvp->drive_flags |= ATA_DRIVE_RESET;
-				splx(s);
+				mutex_exit(&wd->sc_lock);
 			}
 			if (xfer == DIOCWDINFO
 #ifdef __HAVE_OLD_DISKLABEL
@@ -1434,8 +1433,7 @@ wdioctl(dev_t dev, u_long xfer, void *ad
 		atareq_t *atareq = (atareq_t *) addr;
 		int error1;
 
-		wi = wi_get();
-		wi->wi_softc = wd;
+		wi = wi_get(wd);
 		wi->wi_atareq = *atareq;
 
 		if (atareq->datalen && atareq->flags &
@@ -1487,10 +1485,10 @@ wdioctl(dev_t dev, u_long xfer, void *ad
 	    {
 		struct disk_strategy *dks = (void *)addr;
 
-		s = splbio();
+		mutex_enter(&wd->sc_lock);
 		strlcpy(dks->dks_name, bufq_getstrategyname(wd->sc_q),
 		    sizeof(dks->dks_name));
-		splx(s);
+		mutex_exit(&wd->sc_lock);
 		dks->dks_paramlen = 0;
 
 		return 0;
@@ -1514,11 +1512,11 @@ wdioctl(dev_t dev, u_long xfer, void *ad
 		if (error) {
 			return error;
 		}
-		s = splbio();
+		mutex_enter(&wd->sc_lock);
 		old = wd->sc_q;
 		bufq_move(new, old);
 		wd->sc_q = new;
-		splx(s);
+		mutex_exit(&wd->sc_lock);
 		bufq_free(old);
 
 		return 0;
@@ -2008,16 +2006,18 @@ wd_shutdown(device_t dev, int how)
  * scsipi_ioctl.c
  */
 struct wd_ioctl *
-wi_get(void)
+wi_get(struct wd_softc *wd)
 {
 	struct wd_ioctl *wi;
-	int s;
 
 	wi = malloc(sizeof(struct wd_ioctl), M_TEMP, M_WAITOK|M_ZERO);
+	wi->wi_softc = wd;
 	buf_init(&wi->wi_bp);
-	s = splbio();
-	LIST_INSERT_HEAD(&wi_head, wi, wi_list);
-	splx(s);
+
+	mutex_enter(&wd->sc_lock);
+	LIST_INSERT_HEAD(&wd->wi_head, wi, wi_list);
+	mutex_exit(&wd->sc_lock);
+
 	return (wi);
 }
 
@@ -2028,11 +2028,11 @@ wi_get(void)
 void
 wi_free(struct wd_ioctl *wi)
 {
-	int s;
+	struct wd_softc *wd = wi->wi_softc;
 
-	s = splbio();
+	mutex_enter(&wd->sc_lock);
 	LIST_REMOVE(wi, wi_list);
-	splx(s);
+	mutex_exit(&wd->sc_lock);
 	buf_destroy(&wi->wi_bp);
 	free(wi, M_TEMP);
 }
@@ -2044,14 +2044,16 @@ wi_free(struct wd_ioctl *wi)
 struct wd_ioctl *
 wi_find(struct buf *bp)
 {
+	struct wd_softc *wd =
+	    device_lookup_private(&wd_cd, WDUNIT(bp->b_dev));
 	struct wd_ioctl *wi;
-	int s;
 
-	s = splbio();
-	for (wi = wi_head.lh_first; wi != 0; wi = wi->wi_list.le_next)
+	mutex_enter(&wd->sc_lock);
+	LIST_FOREACH(wi, &wd->wi_head, wi_list) {
 		if (bp == &wi->wi_bp)
 			break;
-	splx(s);
+	}
+	mutex_exit(&wd->sc_lock);
 	return (wi);
 }
 

Index: src/sys/dev/ata/wdvar.h
diff -u src/sys/dev/ata/wdvar.h:1.43 src/sys/dev/ata/wdvar.h:1.43.4.1
--- src/sys/dev/ata/wdvar.h:1.43	Fri Jul 22 04:08:10 2016
+++ src/sys/dev/ata/wdvar.h	Wed Apr 12 21:59:14 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: wdvar.h,v 1.43 2016/07/22 04:08:10 jakllsch Exp $	*/
+/*	$NetBSD: wdvar.h,v 1.43.4.1 2017/04/12 21:59:14 jdolecek Exp $	*/
 
 /*
  * Copyright (c) 1998, 2001 Manuel Bouyer.
@@ -39,7 +39,9 @@ struct wd_softc {
 	struct disk sc_dk;
 	struct bufq_state *sc_q;
 	struct callout sc_restart_ch;
+	kmutex_t sc_lock;
 	int sc_quirks;			/* any quirks drive might have */
+
 	/* IDE disk soft states */
 	struct ata_bio sc_wdc_bio; /* current transfer */
 	struct buf *sc_bp; /* buf being transfered */
@@ -71,6 +73,8 @@ struct wd_softc {
 	u_int sc_bscount;
 #endif
 	krndsource_t	rnd_source;
+
+	LIST_HEAD(, wd_ioctl) wi_head;
 };
 
 #define sc_drive sc_wdc_bio.drive

Reply via email to