From owner-svn-src-head@FreeBSD.ORG Sun Mar 15 20:40:13 2015 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [8.8.178.115]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id 12E8EDD5; Sun, 15 Mar 2015 20:40:13 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id F2F95D1; Sun, 15 Mar 2015 20:40:12 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.9/8.14.9) with ESMTP id t2FKeCL8064921; Sun, 15 Mar 2015 20:40:12 GMT (envelope-from adrian@FreeBSD.org) Received: (from adrian@localhost) by svn.freebsd.org (8.14.9/8.14.9/Submit) id t2FKeC30064917; Sun, 15 Mar 2015 20:40:12 GMT (envelope-from adrian@FreeBSD.org) Message-Id: <201503152040.t2FKeC30064917@svn.freebsd.org> X-Authentication-Warning: svn.freebsd.org: adrian set sender to adrian@FreeBSD.org using -f From: Adrian Chadd Date: Sun, 15 Mar 2015 20:40:12 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r280071 - head/sys/dev/wpi X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 15 Mar 2015 20:40:13 -0000 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 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)