Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 7 Jun 2010 16:32:12 +0000 (UTC)
From:      Matt Jacob <mjacob@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-8@freebsd.org
Subject:   svn commit: r208894 - stable/8/sys/dev/mpt
Message-ID:  <201006071632.o57GWCXZ031934@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: mjacob
Date: Mon Jun  7 16:32:12 2010
New Revision: 208894
URL: http://svn.freebsd.org/changeset/base/208894

Log:
  MFC of 198262
  
  Use callout_init_mtx on FreeBSD versions recent enough. This closes
  the race where interrupt thread can complete the request for which
  timeout has fired and while mpt_timeout has blocked on mpt_lock.
  
  Approved by:	re (kib)

Modified:
  stable/8/sys/dev/mpt/mpt.c
  stable/8/sys/dev/mpt/mpt.h
  stable/8/sys/dev/mpt/mpt_cam.c
  stable/8/sys/dev/mpt/mpt_raid.c

Modified: stable/8/sys/dev/mpt/mpt.c
==============================================================================
--- stable/8/sys/dev/mpt/mpt.c	Mon Jun  7 13:44:04 2010	(r208893)
+++ stable/8/sys/dev/mpt/mpt.c	Mon Jun  7 16:32:12 2010	(r208894)
@@ -1238,7 +1238,6 @@ retry:
 		req->state = REQ_STATE_ALLOCATED;
 		req->chain = NULL;
 		mpt_assign_serno(mpt, req);
-		mpt_callout_init(&req->callout);
 	} else if (sleep_ok != 0) {
 		mpt->getreqwaiter = 1;
 		mpt_sleep(mpt, &mpt->request_free_list, PUSER, "mptgreq", 0);
@@ -2251,6 +2250,7 @@ mpt_core_attach(struct mpt_softc *mpt)
 	for (val = 0; val < MPT_MAX_REQUESTS(mpt); val++) {
 		request_t *req = &mpt->request_pool[val];
 		req->state = REQ_STATE_ALLOCATED;
+		mpt_callout_init(mpt, &req->callout);
 		mpt_free_request(mpt, req);
 	}
 	MPT_UNLOCK(mpt);
@@ -2334,10 +2334,18 @@ mpt_core_shutdown(struct mpt_softc *mpt)
 void
 mpt_core_detach(struct mpt_softc *mpt)
 {
+	int val;
+
 	/*
 	 * XXX: FREE MEMORY 
 	 */
 	mpt_disable_ints(mpt);
+
+	/* Make sure no request has pending timeouts. */
+	for (val = 0; val < MPT_MAX_REQUESTS(mpt); val++) {
+		request_t *req = &mpt->request_pool[val];
+		mpt_callout_drain(mpt, &req->callout);
+	}
 }
 
 int

Modified: stable/8/sys/dev/mpt/mpt.h
==============================================================================
--- stable/8/sys/dev/mpt/mpt.h	Mon Jun  7 13:44:04 2010	(r208893)
+++ stable/8/sys/dev/mpt/mpt.h	Mon Jun  7 16:32:12 2010	(r208894)
@@ -303,13 +303,6 @@ void mpt_map_rquest(void *, bus_dma_segm
 	kthread_exit(status)
 #endif
 
-/****************************** Timer Facilities ******************************/
-#if __FreeBSD_version > 500000
-#define mpt_callout_init(c)	callout_init(c, /*mpsafe*/1);
-#else
-#define mpt_callout_init(c)	callout_init(c);
-#endif
-
 /********************************** Endianess *********************************/
 #define	MPT_2_HOST64(ptr, tag)	ptr->tag = le64toh(ptr->tag)
 #define	MPT_2_HOST32(ptr, tag)	ptr->tag = le32toh(ptr->tag)
@@ -897,6 +890,10 @@ mpt_sleep(struct mpt_softc *mpt, void *i
 	callout_reset(&(req)->callout, (ticks), (func), (arg));
 #define mpt_req_untimeout(req, func, arg) \
 	callout_stop(&(req)->callout)
+#define mpt_callout_init(mpt, c) \
+	callout_init(c)
+#define mpt_callout_drain(mpt, c) \
+	callout_stop(c)
 
 #else
 #if 1
@@ -919,9 +916,13 @@ mpt_sleep(struct mpt_softc *mpt, void *i
 #define mpt_sleep(mpt, ident, priority, wmesg, timo) \
 	msleep(ident, &(mpt)->mpt_lock, priority, wmesg, timo)
 #define mpt_req_timeout(req, ticks, func, arg) \
-	callout_reset(&(req)->callout, (ticks), (func), (arg));
+	callout_reset(&(req)->callout, (ticks), (func), (arg))
 #define mpt_req_untimeout(req, func, arg) \
 	callout_stop(&(req)->callout)
+#define mpt_callout_init(mpt, c) \
+	callout_init_mtx(c, &(mpt)->mpt_lock, 0)
+#define mpt_callout_drain(mpt, c) \
+	callout_drain(c)
 
 #else
 
@@ -934,18 +935,18 @@ mpt_sleep(struct mpt_softc *mpt, void *i
 #define	MPTLOCK_2_CAMLOCK(mpt)
 #define	CAMLOCK_2_MPTLOCK(mpt)
 
+#define mpt_req_timeout(req, ticks, func, arg) \
+	callout_reset(&(req)->callout, (ticks), (func), (arg))
+#define mpt_req_untimeout(req, func, arg) \
+	callout_stop(&(req)->callout)
+#define mpt_callout_init(mpt, c) \
+	callout_init(c, 0)
+#define mpt_callout_drain(mpt, c) \
+	callout_drain(c)
+
 static __inline int
 mpt_sleep(struct mpt_softc *, void *, int, const char *, int);
 
-#define mpt_ccb_timeout(ccb, ticks, func, arg) \
-	do {	\
-		(ccb)->ccb_h.timeout_ch = timeout((func), (arg), (ticks)); \
-	} while (0)
-#define mpt_ccb_untimeout(ccb, func, arg) \
-	untimeout((func), (arg), (ccb)->ccb_h.timeout_ch)
-#define mpt_ccb_timeout_init(ccb) \
-	callout_handle_init(&(ccb)->ccb_h.timeout_ch)
-
 static __inline int
 mpt_sleep(struct mpt_softc *mpt, void *i, int p, const char *w, int t)
 {

Modified: stable/8/sys/dev/mpt/mpt_cam.c
==============================================================================
--- stable/8/sys/dev/mpt/mpt_cam.c	Mon Jun  7 13:44:04 2010	(r208893)
+++ stable/8/sys/dev/mpt/mpt_cam.c	Mon Jun  7 16:32:12 2010	(r208894)
@@ -1250,7 +1250,10 @@ mpt_timeout(void *arg)
 	ccb = (union ccb *)arg;
 	mpt = ccb->ccb_h.ccb_mpt_ptr;
 
+#if __FreeBSD_version < 500000
 	MPT_LOCK(mpt);
+#endif
+	MPT_LOCK_ASSERT(mpt);
 	req = ccb->ccb_h.ccb_req_ptr;
 	mpt_prt(mpt, "request %p:%u timed out for ccb %p (req->ccb %p)\n", req,
 	    req->serno, ccb, req->ccb);
@@ -1261,7 +1264,9 @@ mpt_timeout(void *arg)
 		req->state |= REQ_STATE_TIMEDOUT;
 		mpt_wakeup_recovery_thread(mpt);
 	}
+#if __FreeBSD_version < 500000
 	MPT_UNLOCK(mpt);
+#endif
 }
 
 /*

Modified: stable/8/sys/dev/mpt/mpt_raid.c
==============================================================================
--- stable/8/sys/dev/mpt/mpt_raid.c	Mon Jun  7 13:44:04 2010	(r208893)
+++ stable/8/sys/dev/mpt/mpt_raid.c	Mon Jun  7 16:32:12 2010	(r208894)
@@ -270,7 +270,7 @@ mpt_raid_attach(struct mpt_softc *mpt)
 	mpt_handler_t	 handler;
 	int		 error;
 
-	mpt_callout_init(&mpt->raid_timer);
+	mpt_callout_init(mpt, &mpt->raid_timer);
 
 	error = mpt_spawn_raid_thread(mpt);
 	if (error != 0) {
@@ -319,10 +319,10 @@ mpt_raid_detach(struct mpt_softc *mpt)
 	struct ccb_setasync csa;
 	mpt_handler_t handler;
 
-	callout_stop(&mpt->raid_timer);
+	mpt_callout_drain(mpt, &mpt->raid_timer);
+
 	MPT_LOCK(mpt);
 	mpt_terminate_raid_thread(mpt); 
-
 	handler.reply_handler = mpt_raid_reply_handler;
 	mpt_deregister_handler(mpt, MPT_HANDLER_REPLY, handler,
 			       raid_handler_id);
@@ -1555,9 +1555,14 @@ mpt_raid_timer(void *arg)
 	struct mpt_softc *mpt;
 
 	mpt = (struct mpt_softc *)arg;
+#if __FreeBSD_version < 500000
 	MPT_LOCK(mpt);
+#endif
+	MPT_LOCK_ASSERT(mpt);
 	mpt_raid_wakeup(mpt);
+#if __FreeBSD_version < 500000
 	MPT_UNLOCK(mpt);
+#endif
 }
 
 void



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201006071632.o57GWCXZ031934>