Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 15 Mar 2015 20:40:12 +0000 (UTC)
From:      Adrian Chadd <adrian@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r280071 - head/sys/dev/wpi
Message-ID:  <201503152040.t2FKeC30064917@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: adrian
Date: Sun Mar 15 20:40:11 2015
New Revision: 280071
URL: https://svnweb.freebsd.org/changeset/base/280071

Log:
  Add separate lock for TX queues.
  
  PR:		kern/197143
  Submitted by:	Andriy Voskoboinyk <s3erios@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 20:35:25 2015	(r280070)
+++ head/sys/dev/wpi/if_wpi.c	Sun Mar 15 20:40:11 2015	(r280071)
@@ -384,6 +384,7 @@ wpi_attach(device_t dev)
 	}
 
 	WPI_LOCK_INIT(sc);
+	WPI_TXQ_LOCK_INIT(sc);
 
 	/* Allocate DMA memory for firmware transfers. */
 	if ((error = wpi_alloc_fwmem(sc)) != 0) {
@@ -679,6 +680,7 @@ wpi_detach(device_t dev)
 		if_free(ifp);
 
 	DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_END, __func__);
+	WPI_TXQ_LOCK_DESTROY(sc);
 	WPI_LOCK_DESTROY(sc);
 	return 0;
 }
@@ -2151,6 +2153,7 @@ wpi_wakeup_intr(struct wpi_softc *sc)
 		sc->rxq.update = 0;
 		wpi_update_rx_ring(sc);
 	}
+	WPI_TXQ_LOCK(sc);
 	for (qid = 0; qid < WPI_DRV_NTXQUEUES; qid++) {
 		struct wpi_tx_ring *ring = &sc->txq[qid];
 
@@ -2159,6 +2162,7 @@ wpi_wakeup_intr(struct wpi_softc *sc)
 			wpi_update_tx_ring(sc, ring);
 		}
 	}
+	WPI_TXQ_UNLOCK(sc);
 
 	WPI_CLRBITS(sc, WPI_GP_CNTRL, WPI_GP_CNTRL_MAC_ACCESS_REQ);
 }
@@ -2220,11 +2224,13 @@ wpi_fatal_intr(struct wpi_softc *sc)
 	wpi_nic_unlock(sc);
 	/* Dump driver status (TX and RX rings) while we're here. */
 	printf("driver status:\n");
+	WPI_TXQ_LOCK(sc);
 	for (i = 0; i < WPI_DRV_NTXQUEUES; i++) {
 		struct wpi_tx_ring *ring = &sc->txq[i];
 		printf("  tx ring %2d: qid=%-2d cur=%-3d queued=%-3d\n",
 		    i, ring->qid, ring->cur, ring->queued);
 	}
+	WPI_TXQ_UNLOCK(sc);
 	printf("  rx ring: cur=%d\n", sc->rxq.cur);
 }
 
@@ -2302,8 +2308,16 @@ wpi_cmd2(struct wpi_softc *sc, struct wp
 
 	WPI_LOCK_ASSERT(sc);
 
+	WPI_TXQ_LOCK(sc);
+
 	DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_BEGIN, __func__);
 
+	if (sc->txq_active == 0) {
+		/* wpi_stop() was called */
+		error = ENETDOWN;
+		goto fail;
+	}
+
 	wh = mtod(buf->m, struct ieee80211_frame *);
 	hdrlen = ieee80211_anyhdrsize(wh);
 	totlen = buf->m->m_pkthdr.len;
@@ -2336,8 +2350,7 @@ wpi_cmd2(struct wpi_softc *sc, struct wp
 	if (error != 0 && error != EFBIG) {
 		device_printf(sc->sc_dev,
 		    "%s: can't map mbuf (error %d)\n", __func__, error);
-		m_freem(buf->m);
-		return error;
+		goto fail;
 	}
 	if (error != 0) {
 		/* Too many DMA segments, linearize mbuf. */
@@ -2345,8 +2358,8 @@ wpi_cmd2(struct wpi_softc *sc, struct wp
 		if (m1 == NULL) {
 			device_printf(sc->sc_dev,
 			    "%s: could not defrag mbuf\n", __func__);
-			m_freem(buf->m);
-			return ENOBUFS;
+			error = ENOBUFS;
+			goto fail;
 		}
 		buf->m = m1;
 
@@ -2356,8 +2369,7 @@ wpi_cmd2(struct wpi_softc *sc, struct wp
 			device_printf(sc->sc_dev,
 			    "%s: can't map mbuf (error %d)\n", __func__,
 			    error);
-			m_freem(buf->m);
-			return error;
+			goto fail;
 		}
 	}
 
@@ -2400,7 +2412,17 @@ wpi_cmd2(struct wpi_softc *sc, struct wp
 
 	DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_END, __func__);
 
+	WPI_TXQ_UNLOCK(sc);
+
 	return 0;
+
+fail:	m_freem(buf->m);
+
+	DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_END_ERR, __func__);
+
+	WPI_TXQ_UNLOCK(sc);
+
+	return error;
 }
 
 /*
@@ -2867,8 +2889,16 @@ wpi_cmd(struct wpi_softc *sc, int code, 
 	bus_addr_t paddr;
 	int totlen, error;
 
+	WPI_TXQ_LOCK(sc);
+
 	DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_BEGIN, __func__);
 
+	if (sc->txq_active == 0) {
+		/* wpi_stop() was called */
+		error = 0;
+		goto fail;
+	}
+
 	if (async == 0)
 		WPI_LOCK_ASSERT(sc);
 
@@ -2888,17 +2918,21 @@ wpi_cmd(struct wpi_softc *sc, int code, 
 
 	if (size > sizeof cmd->data) {
 		/* Command is too large to fit in a descriptor. */
-		if (totlen > MCLBYTES)
-			return EINVAL;
+		if (totlen > MCLBYTES) {
+			error = EINVAL;
+			goto fail;
+		}
 		m = m_getjcl(M_NOWAIT, MT_DATA, M_PKTHDR, MJUMPAGESIZE);
-		if (m == NULL)
-			return ENOMEM;
+		if (m == NULL) {
+			error = ENOMEM;
+			goto fail;
+		}
 		cmd = mtod(m, struct wpi_tx_cmd *);
 		error = bus_dmamap_load(ring->data_dmat, data->map, cmd,
 		    totlen, wpi_dma_map_addr, &paddr, BUS_DMA_NOWAIT);
 		if (error != 0) {
 			m_freem(m);
-			return error;
+			goto fail;
 		}
 		data->m = m;
 	} else {
@@ -2932,12 +2966,20 @@ wpi_cmd(struct wpi_softc *sc, int code, 
 
 	DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_END, __func__);
 
+	WPI_TXQ_UNLOCK(sc);
+
 	if (async) {
 		sc->flags &= ~WPI_FLAG_BUSY;
 		return 0;
 	}
 
 	return mtx_sleep(cmd, &sc->sc_mtx, PCATCH, "wpicmd", hz);
+
+fail:	DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_END_ERR, __func__);
+
+	WPI_TXQ_UNLOCK(sc);
+
+	return error;
 }
 
 /*
@@ -4817,6 +4859,7 @@ wpi_init_locked(struct wpi_softc *sc)
 	}
 
 	/* Configure adapter now that it is ready. */
+	sc->txq_active = 1;
 	if ((error = wpi_config(sc)) != 0) {
 		device_printf(sc->sc_dev,
 		    "%s: could not configure device, error %d\n", __func__,
@@ -4859,6 +4902,10 @@ wpi_stop_locked(struct wpi_softc *sc)
 
 	WPI_LOCK_ASSERT(sc);
 
+	WPI_TXQ_LOCK(sc);
+	sc->txq_active = 0;
+	WPI_TXQ_UNLOCK(sc);
+
 	sc->sc_scan_timer = 0;
 	sc->sc_tx_timer = 0;
 	callout_stop(&sc->watchdog_to);

Modified: head/sys/dev/wpi/if_wpivar.h
==============================================================================
--- head/sys/dev/wpi/if_wpivar.h	Sun Mar 15 20:35:25 2015	(r280070)
+++ head/sys/dev/wpi/if_wpivar.h	Sun Mar 15 20:40:11 2015	(r280071)
@@ -163,6 +163,9 @@ struct wpi_softc {
 	struct wpi_shared	*shared;
 
 	struct wpi_tx_ring	txq[WPI_NTXQUEUES];
+	struct mtx		txq_mtx;
+	uint32_t		txq_active;
+
 	struct wpi_rx_ring	rxq;
 
 	/* TX Thermal Callibration. */
@@ -222,6 +225,8 @@ struct wpi_softc {
 	char			domain[4];	/* Regulatory domain. */
 };
 
+/* WPI_LOCK > WPI_TXQ_LOCK */
+
 #define WPI_LOCK_INIT(_sc) \
 	mtx_init(&(_sc)->sc_mtx, device_get_nameunit((_sc)->sc_dev), \
 	    MTX_NETWORK_LOCK, MTX_DEF)
@@ -229,3 +234,9 @@ struct wpi_softc {
 #define WPI_UNLOCK(_sc)		mtx_unlock(&(_sc)->sc_mtx)
 #define WPI_LOCK_ASSERT(sc)	mtx_assert(&(sc)->sc_mtx, MA_OWNED)
 #define WPI_LOCK_DESTROY(_sc)	mtx_destroy(&(_sc)->sc_mtx)
+
+#define WPI_TXQ_LOCK_INIT(_sc) \
+	mtx_init(&(_sc)->txq_mtx, "txq/cmdq lock", NULL, MTX_DEF)
+#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)



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