[PATCH v2 9/9] Return TXed frames to mac80211.

Pontus Fuchs pontus.fuchs at gmail.com
Thu May 30 04:12:35 EDT 2013


On TX done IRQ reap all transferred skbs.

Signed-off-by: Pontus Fuchs <pontus.fuchs at gmail.com>
---
 dxe.c | 46 +++++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 41 insertions(+), 5 deletions(-)

diff --git a/dxe.c b/dxe.c
index adcd700..97066d4 100644
--- a/dxe.c
+++ b/dxe.c
@@ -271,6 +271,25 @@ static void wcn36xx_dxe_ch_free_skbs(struct wcn36xx *wcn,
 	}
 }
 
+static void reap_tx_dxes(struct wcn36xx *wcn, struct wcn36xx_dxe_ch *ch)
+{
+	struct wcn36xx_dxe_ctl *ctl = ch->tail_blk_ctl;
+	struct ieee80211_tx_info *info;
+
+	while (ctl != ch->head_blk_ctl &&
+	       !(ctl->desc->ctrl & WCN36XX_DXE_CTRL_VALID_MASK)) {
+		if (ctl->skb) {
+			dma_unmap_single(NULL, ctl->desc->src_addr_l,
+					 ctl->skb->len, DMA_TO_DEVICE);
+			info = IEEE80211_SKB_CB(ctl->skb);
+			ieee80211_tx_info_clear_status(info);
+			ieee80211_tx_status_irqsafe(wcn->hw, ctl->skb);
+			ctl->skb = NULL;
+		}
+		ctl = ctl->next;
+	}
+	ch->tail_blk_ctl = ctl;
+}
 static irqreturn_t wcn36xx_irq_tx_complete(int irq, void *dev)
 {
 	struct wcn36xx *wcn = (struct wcn36xx *)dev;
@@ -290,6 +309,7 @@ static irqreturn_t wcn36xx_irq_tx_complete(int irq, void *dev)
 		wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_0_INT_ED_CLR,
 					   WCN36XX_INT_MASK_CHAN_TX_H);
 		wcn36xx_dbg(WCN36XX_DBG_DXE, "dxe tx ready high");
+		reap_tx_dxes(wcn, &wcn->dxe_tx_h_ch);
 	}
 	if (int_src & WCN36XX_INT_MASK_CHAN_TX_L) {
 		wcn36xx_dxe_read_register(wcn,
@@ -303,6 +323,7 @@ static irqreturn_t wcn36xx_irq_tx_complete(int irq, void *dev)
 		wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_0_INT_ED_CLR,
 					   WCN36XX_INT_MASK_CHAN_TX_L);
 		wcn36xx_dbg(WCN36XX_DBG_DXE, "dxe tx ready low");
+		reap_tx_dxes(wcn, &wcn->dxe_tx_l_ch);
 	}
 
 	return IRQ_HANDLED;
@@ -466,8 +487,18 @@ int wcn36xx_dxe_tx(struct wcn36xx *wcn,
 	ch = is_high ? &wcn->dxe_tx_h_ch : &wcn->dxe_tx_l_ch;
 
 	ctl = ch->head_blk_ctl;
+	ctl->skb = NULL;
 	desc = ctl->desc;
-	BUG_ON(!ctl->bd_cpu_addr);
+	if (!ctl->bd_cpu_addr) {
+		/* TX DXE are used in pairs. One for the BD and one for the
+		   actual frame. The BD DXE's has a preallocated buffer while
+		   the skb ones does not. If this isn't true something is really
+		   wierd. TODO: Recover from this situation
+		 */
+
+		wcn36xx_error("bd_cpu_addr may not be NULL for BD DXE");
+		return -EINVAL;
+	}
 
 	wcn36xx_prepare_tx_bd(ctl->bd_cpu_addr, skb->len, header_len);
 	if (!is_high && WCN36XX_BSS_KEY == wcn->en_state) {
@@ -499,11 +530,16 @@ int wcn36xx_dxe_tx(struct wcn36xx *wcn,
 	ctl = ctl->next;
 	ctl->skb = skb;
 	desc = ctl->desc;
+	if (ctl->bd_cpu_addr) {
+		/* TODO: Recover from this situation */
+		wcn36xx_error("bd_cpu_addr cannot be NULL for skb DXE");
+		return -EINVAL;
+	}
 
-	desc->src_addr_l = (int)dma_map_single(NULL,
-		ctl->skb->data,
-		ctl->skb->len,
-		DMA_TO_DEVICE );
+	desc->src_addr_l = dma_map_single(NULL,
+					  ctl->skb->data,
+					  ctl->skb->len,
+					  DMA_TO_DEVICE);
 
 	desc->dst_addr_l = ch->dxe_wq;
 	desc->fr_len = ctl->skb->len;
-- 
1.8.1.2




More information about the wcn36xx mailing list