[PATCH 4/4] staging: brcm80211: invalidate all AMPDU packets on IEEE80211_AMPDU_TX_STOP

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



The previous patch flushed the AMPDU packets associated to a certain STA/AP
in the driver queues, but left the AMPDU packets in the DMA queue untouched.
This patch invalidates AMPDU packets in the DMA queue, so they can be
processed accordingly when hardware releases the packets to the driver.

Signed-off-by: Roland Vossen <rvossen@xxxxxxxxxxxx>
Reviewed-by: Arend van Spriel <arend@xxxxxxxxxxxx>

---
 drivers/staging/brcm80211/brcmsmac/wlc_ampdu.c |   14 ++++++++++++++
 drivers/staging/brcm80211/brcmsmac/wlc_main.c  |   18 ++++++++++++++++++
 drivers/staging/brcm80211/brcmsmac/wlc_main.h  |    3 +++
 drivers/staging/brcm80211/include/hnddma.h     |    3 ++-
 drivers/staging/brcm80211/util/hnddma.c        |   24 ++++++++++++++++++++++++
 5 files changed, 61 insertions(+), 1 deletions(-)

diff --git a/drivers/staging/brcm80211/brcmsmac/wlc_ampdu.c b/drivers/staging/brcm80211/brcmsmac/wlc_ampdu.c
index 3d00180..0a0ff30 100644
--- a/drivers/staging/brcm80211/brcmsmac/wlc_ampdu.c
+++ b/drivers/staging/brcm80211/brcmsmac/wlc_ampdu.c
@@ -1388,6 +1388,19 @@ static bool cb_del_ampdu_pkt(void *p, int arg_a)
 }
 
 /*
+ * callback function that helps invalidating ampdu packets in a DMA queue
+ */
+static void dma_cb_fn_ampdu(void *txi, void *arg_a)
+{
+	struct ieee80211_sta *sta = arg_a;
+	struct ieee80211_tx_info *tx_info = (struct ieee80211_tx_info *)txi;
+
+	if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) &&
+	    (tx_info->control.sta == sta || sta == NULL))
+		tx_info->control.sta = NULL;
+}
+
+/*
  * When a remote party is no longer available for ampdu communication, any
  * pending tx ampdu packets in the driver have to be flushed.
  */
@@ -1405,4 +1418,5 @@ void wlc_ampdu_flush(struct wlc_info *wlc,
 		pktq_pflush(pq, prec, true, cb_del_ampdu_pkt,
 			    (int)&ampdu_pars);
 	}
+	wlc_inval_dma_pkts(wlc->hw, sta, dma_cb_fn_ampdu);
 }
diff --git a/drivers/staging/brcm80211/brcmsmac/wlc_main.c b/drivers/staging/brcm80211/brcmsmac/wlc_main.c
index cc16504..4f7fc0b 100644
--- a/drivers/staging/brcm80211/brcmsmac/wlc_main.c
+++ b/drivers/staging/brcm80211/brcmsmac/wlc_main.c
@@ -8476,3 +8476,21 @@ void wlc_associate_upd(struct wlc_info *wlc, bool state)
 	wlc->pub->associated = state;
 	wlc->cfg->associated = state;
 }
+
+/*
+ * When a remote STA/AP is removed by Mac80211, or when it can no longer accept
+ * AMPDU traffic, packets pending in hardware have to be invalidated so that
+ * when later on hardware releases them, they can be handled appropriately.
+ */
+void wlc_inval_dma_pkts(struct wlc_hw_info *hw,
+			       struct ieee80211_sta *sta,
+			       void (*dma_callback_fn))
+{
+	struct hnddma_pub *dmah;
+	int i;
+	for (i = 0; i < NFIFO; i++) {
+		dmah = hw->di[i];
+		if (dmah != NULL)
+			dma_walk_packets(dmah, dma_callback_fn, sta);
+	}
+}
diff --git a/drivers/staging/brcm80211/brcmsmac/wlc_main.h b/drivers/staging/brcm80211/brcmsmac/wlc_main.h
index 7c5d7e1..0eaef07 100644
--- a/drivers/staging/brcm80211/brcmsmac/wlc_main.h
+++ b/drivers/staging/brcm80211/brcmsmac/wlc_main.h
@@ -873,6 +873,9 @@ extern u16 wlc_compute_rtscts_dur(struct wlc_info *wlc, bool cts_only,
 				     bool ba);
 
 extern void wlc_tbtt(struct wlc_info *wlc, d11regs_t *regs);
+extern void wlc_inval_dma_pkts(struct wlc_hw_info *hw,
+			       struct ieee80211_sta *sta,
+			       void (*dma_callback_fn));
 
 #if defined(BCMDBG)
 extern void wlc_dump_ie(struct wlc_info *wlc, bcm_tlv_t *ie,
diff --git a/drivers/staging/brcm80211/include/hnddma.h b/drivers/staging/brcm80211/include/hnddma.h
index 121768e..5d079e7 100644
--- a/drivers/staging/brcm80211/include/hnddma.h
+++ b/drivers/staging/brcm80211/include/hnddma.h
@@ -202,5 +202,6 @@ extern const di_fcn_t dma64proc;
  * This info is needed by DMA_ALLOC_CONSISTENT in dma attach
  */
 extern uint dma_addrwidth(si_t *sih, void *dmaregs);
-
+void dma_walk_packets(struct hnddma_pub *dmah, void (*callback_fnc)
+		      (void *pkt, void *arg_a), void *arg_a);
 #endif				/* _hnddma_h_ */
diff --git a/drivers/staging/brcm80211/util/hnddma.c b/drivers/staging/brcm80211/util/hnddma.c
index 6273314..9362f56 100644
--- a/drivers/staging/brcm80211/util/hnddma.c
+++ b/drivers/staging/brcm80211/util/hnddma.c
@@ -1801,3 +1801,27 @@ uint dma_addrwidth(si_t *sih, void *dmaregs)
 	return DMADDRWIDTH_64;
 }
 
+/*
+ * Mac80211 initiated actions sometimes require packets in the DMA queue to be
+ * modified. The modified portion of the packet is not under control of the DMA
+ * engine. This function calls a caller-supplied function for each packet in
+ * the caller specified dma chain.
+ */
+void dma_walk_packets(struct hnddma_pub *dmah, void (*callback_fnc)
+		      (void *pkt, void *arg_a), void *arg_a)
+{
+	dma_info_t *di = (dma_info_t *) dmah;
+	uint i =   di->txin;
+	uint end = di->txout;
+	struct sk_buff *skb;
+	struct ieee80211_tx_info *tx_info;
+
+	while (i != end) {
+		skb = (struct sk_buff *)di->txp[i];
+		if (skb != NULL) {
+			tx_info = (struct ieee80211_tx_info *)skb->cb;
+			(callback_fnc)(tx_info, arg_a);
+		}
+		i = NEXTTXD(i);
+	}
+}
-- 
1.7.1


_______________________________________________
devel mailing list
devel@xxxxxxxxxxxxxxxxxxxxxx
http://driverdev.linuxdriverproject.org/mailman/listinfo/devel


[Index of Archives]     [Linux Driver Backports]     [DMA Engine]     [Linux GPIO]     [Linux SPI]     [Video for Linux]     [Linux USB Devel]     [Linux Coverity]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]
  Powered by Linux