Author: adrian
Date: Sun Mar 15 21:25:06 2015
New Revision: 280112
URL: https://svnweb.freebsd.org/changeset/base/280112

Log:
  Add an extra mutex for qfullmsk / ring->queued variables.
  
  PR:           kern/197143
  Submitted by: Andriy Voskoboinyk <s3er...@gmail.com>

Modified:
  head/sys/dev/wpi/if_wpi.c
  head/sys/dev/wpi/if_wpivar.h

Modified: head/sys/dev/wpi/if_wpi.c
==============================================================================
--- head/sys/dev/wpi/if_wpi.c   Sun Mar 15 21:24:11 2015        (r280111)
+++ head/sys/dev/wpi/if_wpi.c   Sun Mar 15 21:25:06 2015        (r280112)
@@ -399,6 +399,7 @@ wpi_attach(device_t dev)
        WPI_RXON_LOCK_INIT(sc);
        WPI_NT_LOCK_INIT(sc);
        WPI_TXQ_LOCK_INIT(sc);
+       WPI_TXQ_STATE_LOCK_INIT(sc);
 
        /* Allocate DMA memory for firmware transfers. */
        if ((error = wpi_alloc_fwmem(sc)) != 0) {
@@ -523,7 +524,7 @@ wpi_attach(device_t dev)
 
        callout_init_mtx(&sc->calib_to, &sc->rxon_mtx, 0);
        callout_init_mtx(&sc->scan_timeout, &sc->rxon_mtx, 0);
-       callout_init_mtx(&sc->tx_timeout, &sc->sc_mtx, 0);
+       callout_init_mtx(&sc->tx_timeout, &sc->txq_state_mtx, 0);
        callout_init_mtx(&sc->watchdog_rfkill, &sc->sc_mtx, 0);
        TASK_INIT(&sc->sc_reinittask, 0, wpi_hw_reset, sc);
        TASK_INIT(&sc->sc_radiooff_task, 0, wpi_radio_off, sc);
@@ -721,6 +722,7 @@ wpi_detach(device_t dev)
                if_free(ifp);
 
        DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_END, __func__);
+       WPI_TXQ_STATE_LOCK_DESTROY(sc);
        WPI_TXQ_LOCK_DESTROY(sc);
        WPI_NT_LOCK_DESTROY(sc);
        WPI_RXON_LOCK_DESTROY(sc);
@@ -1970,6 +1972,7 @@ wpi_tx_done(struct wpi_softc *sc, struct
        ieee80211_tx_complete(ni, m, (status & 0xff) != 1);
        WPI_LOCK(sc);
 
+       WPI_TXQ_STATE_LOCK(sc);
        ring->queued -= 1;
        if (ring->queued > 0) {
                callout_reset(&sc->tx_timeout, 5*hz, wpi_tx_timeout, sc);
@@ -1988,6 +1991,7 @@ wpi_tx_done(struct wpi_softc *sc, struct
                }
        } else
                callout_stop(&sc->tx_timeout);
+       WPI_TXQ_STATE_UNLOCK(sc);
 
        DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_END, __func__);
 }
@@ -2524,6 +2528,7 @@ wpi_cmd2(struct wpi_softc *sc, struct wp
 
        if (ring->qid < WPI_CMD_QUEUE_NUM) {
                /* Mark TX ring as full if we reach a certain threshold. */
+               WPI_TXQ_STATE_LOCK(sc);
                if (++ring->queued > WPI_TX_RING_HIMARK) {
                        sc->qfullmsk |= 1 << ring->qid;
 
@@ -2533,6 +2538,7 @@ wpi_cmd2(struct wpi_softc *sc, struct wp
                }
 
                callout_reset(&sc->tx_timeout, 5*hz, wpi_tx_timeout, sc);
+               WPI_TXQ_STATE_UNLOCK(sc);
        }
 
        DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_END, __func__);
@@ -5277,7 +5283,9 @@ wpi_stop_locked(struct wpi_softc *sc)
        sc->txq_active = 0;
        WPI_TXQ_UNLOCK(sc);
 
+       WPI_TXQ_STATE_LOCK(sc);
        callout_stop(&sc->tx_timeout);
+       WPI_TXQ_STATE_UNLOCK(sc);
 
        WPI_RXON_LOCK(sc);
        callout_stop(&sc->scan_timeout);

Modified: head/sys/dev/wpi/if_wpivar.h
==============================================================================
--- head/sys/dev/wpi/if_wpivar.h        Sun Mar 15 21:24:11 2015        
(r280111)
+++ head/sys/dev/wpi/if_wpivar.h        Sun Mar 15 21:25:06 2015        
(r280112)
@@ -172,6 +172,7 @@ struct wpi_softc {
 
        struct wpi_tx_ring      txq[WPI_NTXQUEUES];
        struct mtx              txq_mtx;
+       struct mtx              txq_state_mtx;
        uint32_t                txq_active;
 
        struct wpi_rx_ring      rxq;
@@ -237,7 +238,14 @@ struct wpi_softc {
        char                    domain[4];      /* Regulatory domain. */
 };
 
-/* WPI_LOCK > WPI_RXON_LOCK > WPI_NT_LOCK / WPI_VAP_LOCK > WPI_TXQ_LOCK */
+/*
+ * Locking order:
+ * 1. WPI_LOCK;
+ * 2. WPI_RXON_LOCK;
+ * 3. WPI_NT_LOCK / WPI_VAP_LOCK;
+ * 4. WPI_TXQ_LOCK;
+ * 5. WPI_TXQ_STATE_LOCK;
+ */
 
 #define WPI_LOCK_INIT(_sc) \
        mtx_init(&(_sc)->sc_mtx, device_get_nameunit((_sc)->sc_dev), \
@@ -265,3 +273,9 @@ struct wpi_softc {
 #define WPI_TXQ_LOCK(_sc)              mtx_lock(&(_sc)->txq_mtx)
 #define WPI_TXQ_UNLOCK(_sc)            mtx_unlock(&(_sc)->txq_mtx)
 #define WPI_TXQ_LOCK_DESTROY(_sc)      mtx_destroy(&(_sc)->txq_mtx)
+
+#define WPI_TXQ_STATE_LOCK_INIT(_sc) \
+       mtx_init(&(_sc)->txq_state_mtx, "txq state lock", NULL, MTX_DEF)
+#define WPI_TXQ_STATE_LOCK(_sc)                mtx_lock(&(_sc)->txq_state_mtx)
+#define WPI_TXQ_STATE_UNLOCK(_sc)      mtx_unlock(&(_sc)->txq_state_mtx)
+#define WPI_TXQ_STATE_LOCK_DESTROY(_sc)        
mtx_destroy(&(_sc)->txq_state_mtx)
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to