Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 6 Nov 2016 18:11:19 +0000 (UTC)
From:      Andriy Voskoboinyk <avos@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r308381 - head/sys/dev/rtwn/pci
Message-ID:  <201611061811.uA6IBJO4095149@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: avos
Date: Sun Nov  6 18:11:19 2016
New Revision: 308381
URL: https://svnweb.freebsd.org/changeset/base/308381

Log:
  rtwn: fix Tx ring cleanup.
  
  Do not try to clear stale Tx descriptor entries when there are some
  running vaps; just free node references - rtwn_pci_tx_done() will free
  mbufs without creating holes in the Tx descriptor space.
  Also, reset only 2 first entries in the beacon ring - other will not be
  used anyway.
  
  Tested with RTL8188CE, STA + STA mode.

Modified:
  head/sys/dev/rtwn/pci/rtwn_pci_attach.c

Modified: head/sys/dev/rtwn/pci/rtwn_pci_attach.c
==============================================================================
--- head/sys/dev/rtwn/pci/rtwn_pci_attach.c	Sun Nov  6 17:24:16 2016	(r308380)
+++ head/sys/dev/rtwn/pci/rtwn_pci_attach.c	Sun Nov  6 18:11:19 2016	(r308381)
@@ -49,6 +49,7 @@ __FBSDID("$FreeBSD$");
 
 #include <net80211/ieee80211_var.h>
 
+#include <dev/rtwn/if_rtwnreg.h>
 #include <dev/rtwn/if_rtwnvar.h>
 #include <dev/rtwn/if_rtwn_nop.h>
 #include <dev/rtwn/if_rtwn_debug.h>
@@ -75,6 +76,8 @@ static int	rtwn_pci_alloc_rx_list(struct
 static void	rtwn_pci_reset_rx_list(struct rtwn_softc *);
 static void	rtwn_pci_free_rx_list(struct rtwn_softc *);
 static int	rtwn_pci_alloc_tx_list(struct rtwn_softc *, int);
+static void	rtwn_pci_reset_tx_ring_stopped(struct rtwn_softc *, int);
+static void	rtwn_pci_reset_beacon_ring(struct rtwn_softc *, int);
 static void	rtwn_pci_reset_tx_list(struct rtwn_softc *,
 		    struct ieee80211vap *, int);
 static void	rtwn_pci_free_tx_list(struct rtwn_softc *, int);
@@ -312,48 +315,109 @@ fail:
 }
 
 static void
-rtwn_pci_reset_tx_list(struct rtwn_softc *sc, struct ieee80211vap *vap,
-    int qid)
+rtwn_pci_reset_tx_ring_stopped(struct rtwn_softc *sc, int qid)
 {
-	struct rtwn_vap *uvp = RTWN_VAP(vap);
 	struct rtwn_pci_softc *pc = RTWN_PCI_SOFTC(sc);
-	struct rtwn_tx_ring *tx_ring = &pc->tx_ring[qid];
-	int i, id;
-
-	id = (uvp != NULL ? uvp->id : RTWN_VAP_ID_INVALID);
+	struct rtwn_tx_ring *ring = &pc->tx_ring[qid];
+	int i;
 
 	for (i = 0; i < RTWN_PCI_TX_LIST_COUNT; i++) {
-		struct rtwn_tx_data *tx_data = &tx_ring->tx_data[i];
+		struct rtwn_tx_data *data = &ring->tx_data[i];
+		void *desc = (uint8_t *)ring->desc + sc->txdesc_len * i;
 
-		if (vap == NULL || (tx_data->ni == NULL &&
-		    (tx_data->id == id || id == RTWN_VAP_ID_INVALID)) ||
-		    (tx_data->ni != NULL && tx_data->ni->ni_vap == vap)) {
-			void *tx_desc =
-			    (uint8_t *)tx_ring->desc + sc->txdesc_len * i;
-
-			rtwn_pci_copy_tx_desc(pc, tx_desc, NULL);
-
-			if (tx_data->m != NULL) {
-				bus_dmamap_sync(tx_ring->data_dmat,
-				    tx_data->map, BUS_DMASYNC_POSTWRITE);
-				bus_dmamap_unload(tx_ring->data_dmat,
-				    tx_data->map);
-				m_freem(tx_data->m);
-				tx_data->m = NULL;
-			}
-			if (tx_data->ni != NULL) {
-				ieee80211_free_node(tx_data->ni);
-				tx_data->ni = NULL;
-			}
+		rtwn_pci_copy_tx_desc(pc, desc, NULL);
+
+		if (data->m != NULL) {
+			bus_dmamap_sync(ring->data_dmat, data->map,
+			    BUS_DMASYNC_POSTWRITE);
+			bus_dmamap_unload(ring->data_dmat, data->map);
+			m_freem(data->m);
+			data->m = NULL;
+		}
+		if (data->ni != NULL) {
+			ieee80211_free_node(data->ni);
+			data->ni = NULL;
 		}
 	}
 
-	bus_dmamap_sync(tx_ring->desc_dmat, tx_ring->desc_map,
+	bus_dmamap_sync(ring->desc_dmat, ring->desc_map,
 	    BUS_DMASYNC_POSTWRITE);
 
 	sc->qfullmsk &= ~(1 << qid);
-	tx_ring->queued = 0;
-	tx_ring->last = tx_ring->cur = 0;
+	ring->queued = 0;
+	ring->last = ring->cur = 0;
+}
+
+/*
+ * Clear entry 0 (or 1) in the beacon queue (other are not used).
+ */
+static void
+rtwn_pci_reset_beacon_ring(struct rtwn_softc *sc, int id)
+{
+	struct rtwn_pci_softc *pc = RTWN_PCI_SOFTC(sc);
+	struct rtwn_tx_ring *ring = &pc->tx_ring[RTWN_PCI_BEACON_QUEUE];
+	struct rtwn_tx_data *data = &ring->tx_data[id];
+	struct rtwn_tx_desc_common *txd = (struct rtwn_tx_desc_common *)
+	    ((uint8_t *)ring->desc + id * sc->txdesc_len);
+
+	bus_dmamap_sync(ring->desc_dmat, ring->desc_map, BUS_DMASYNC_POSTREAD);
+	if (txd->flags0 & RTWN_FLAGS0_OWN) {
+		/* Clear OWN bit. */
+		txd->flags0 &= ~RTWN_FLAGS0_OWN;
+		bus_dmamap_sync(ring->desc_dmat, ring->desc_map,
+		    BUS_DMASYNC_PREWRITE);
+
+		/* Unload mbuf. */
+		bus_dmamap_sync(ring->data_dmat, data->map,
+		    BUS_DMASYNC_POSTWRITE);
+		bus_dmamap_unload(ring->data_dmat, data->map);
+	}
+}
+
+/*
+ * Drop stale entries from Tx ring before the vap will be deleted.
+ * In case if vap is NULL just free everything and reset cur / last pointers.
+ */
+static void
+rtwn_pci_reset_tx_list(struct rtwn_softc *sc, struct ieee80211vap *vap,
+    int qid)
+{
+	int i;
+
+	if (vap == NULL) {
+		if (qid != RTWN_PCI_BEACON_QUEUE) {
+			/*
+			 * Device was stopped; just clear all entries.
+			 */
+			rtwn_pci_reset_tx_ring_stopped(sc, qid);
+		} else {
+			for (i = 0; i < RTWN_PORT_COUNT; i++)
+				rtwn_pci_reset_beacon_ring(sc, i);
+		}
+	} else if (qid == RTWN_PCI_BEACON_QUEUE &&
+		   (vap->iv_opmode == IEEE80211_M_HOSTAP ||
+		    vap->iv_opmode == IEEE80211_M_IBSS)) {
+		struct rtwn_vap *uvp = RTWN_VAP(vap);
+
+		rtwn_pci_reset_beacon_ring(sc, uvp->id);
+	} else {
+		struct rtwn_pci_softc *pc = RTWN_PCI_SOFTC(sc);
+		struct rtwn_tx_ring *ring = &pc->tx_ring[qid];
+
+		for (i = 0; i < RTWN_PCI_TX_LIST_COUNT; i++) {
+			struct rtwn_tx_data *data = &ring->tx_data[i];
+			if (data->ni != NULL && data->ni->ni_vap == vap) {
+				/*
+				 * NB: if some vap is still running
+				 * rtwn_pci_tx_done() will free the mbuf;
+				 * otherwise, rtwn_stop() will reset all rings
+				 * after device shutdown.
+				 */
+				ieee80211_free_node(data->ni);
+				data->ni = NULL;
+			}
+		}
+	}
 }
 
 static void



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