Author: marius
Date: Mon Jul 25 16:11:52 2011
New Revision: 224327
URL: http://svn.freebsd.org/changeset/base/224327

Log:
  MFC: r198262
  
  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.

Modified:
  stable/7/sys/dev/mpt/mpt.c
  stable/7/sys/dev/mpt/mpt.h
  stable/7/sys/dev/mpt/mpt_cam.c
  stable/7/sys/dev/mpt/mpt_raid.c
Directory Properties:
  stable/7/sys/   (props changed)
  stable/7/sys/cddl/contrib/opensolaris/   (props changed)
  stable/7/sys/contrib/dev/acpica/   (props changed)
  stable/7/sys/contrib/pf/   (props changed)

Modified: stable/7/sys/dev/mpt/mpt.c
==============================================================================
--- stable/7/sys/dev/mpt/mpt.c  Mon Jul 25 15:14:03 2011        (r224326)
+++ stable/7/sys/dev/mpt/mpt.c  Mon Jul 25 16:11:52 2011        (r224327)
@@ -1239,7 +1239,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);
@@ -2252,6 +2251,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);
@@ -2335,10 +2335,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/7/sys/dev/mpt/mpt.h
==============================================================================
--- stable/7/sys/dev/mpt/mpt.h  Mon Jul 25 15:14:03 2011        (r224326)
+++ stable/7/sys/dev/mpt/mpt.h  Mon Jul 25 16:11:52 2011        (r224327)
@@ -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/7/sys/dev/mpt/mpt_cam.c
==============================================================================
--- stable/7/sys/dev/mpt/mpt_cam.c      Mon Jul 25 15:14:03 2011        
(r224326)
+++ stable/7/sys/dev/mpt/mpt_cam.c      Mon Jul 25 16:11:52 2011        
(r224327)
@@ -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/7/sys/dev/mpt/mpt_raid.c
==============================================================================
--- stable/7/sys/dev/mpt/mpt_raid.c     Mon Jul 25 15:14:03 2011        
(r224326)
+++ stable/7/sys/dev/mpt/mpt_raid.c     Mon Jul 25 16:11:52 2011        
(r224327)
@@ -271,7 +271,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) {
@@ -320,10 +320,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);
@@ -1570,9 +1570,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
_______________________________________________
[email protected] mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "[email protected]"

Reply via email to