From 1543e317f1da31b75942316931e8f491a8920811 Mon Sep 17 00:00:00 2001
From: hc <hc@nodka.com>
Date: Thu, 04 Jan 2024 10:08:02 +0000
Subject: [PATCH] disable FB
---
kernel/drivers/net/wireless/ath/wcn36xx/dxe.c | 110 ++++++++++++++++++++++++++++++++++++++++++++-----------
1 files changed, 88 insertions(+), 22 deletions(-)
diff --git a/kernel/drivers/net/wireless/ath/wcn36xx/dxe.c b/kernel/drivers/net/wireless/ath/wcn36xx/dxe.c
index 38eef15..6c62ffc 100644
--- a/kernel/drivers/net/wireless/ath/wcn36xx/dxe.c
+++ b/kernel/drivers/net/wireless/ath/wcn36xx/dxe.c
@@ -179,8 +179,6 @@
if (!wcn_ch->cpu_addr)
return -ENOMEM;
- memset(wcn_ch->cpu_addr, 0, size);
-
cur_dxe = (struct wcn36xx_dxe_desc *)wcn_ch->cpu_addr;
cur_ctl = wcn_ch->head_blk_ctl;
@@ -274,6 +272,21 @@
return 0;
}
+static void wcn36xx_dxe_disable_ch_int(struct wcn36xx *wcn, u16 wcn_ch)
+{
+ int reg_data = 0;
+
+ wcn36xx_dxe_read_register(wcn,
+ WCN36XX_DXE_INT_MASK_REG,
+ ®_data);
+
+ reg_data &= ~wcn_ch;
+
+ wcn36xx_dxe_write_register(wcn,
+ WCN36XX_DXE_INT_MASK_REG,
+ (int)reg_data);
+}
+
static int wcn36xx_dxe_fill_skb(struct device *dev,
struct wcn36xx_dxe_ctl *ctl,
gfp_t gfp)
@@ -336,6 +349,7 @@
spin_lock_irqsave(&wcn->dxe_lock, flags);
skb = wcn->tx_ack_skb;
wcn->tx_ack_skb = NULL;
+ del_timer(&wcn->tx_ack_timer);
spin_unlock_irqrestore(&wcn->dxe_lock, flags);
if (!skb) {
@@ -347,8 +361,36 @@
if (status == 1)
info->flags |= IEEE80211_TX_STAT_ACK;
+ else
+ info->flags &= ~IEEE80211_TX_STAT_ACK;
wcn36xx_dbg(WCN36XX_DBG_DXE, "dxe tx ack status: %d\n", status);
+
+ ieee80211_tx_status_irqsafe(wcn->hw, skb);
+ ieee80211_wake_queues(wcn->hw);
+}
+
+static void wcn36xx_dxe_tx_timer(struct timer_list *t)
+{
+ struct wcn36xx *wcn = from_timer(wcn, t, tx_ack_timer);
+ struct ieee80211_tx_info *info;
+ unsigned long flags;
+ struct sk_buff *skb;
+
+ /* TX Timeout */
+ wcn36xx_dbg(WCN36XX_DBG_DXE, "TX timeout\n");
+
+ spin_lock_irqsave(&wcn->dxe_lock, flags);
+ skb = wcn->tx_ack_skb;
+ wcn->tx_ack_skb = NULL;
+ spin_unlock_irqrestore(&wcn->dxe_lock, flags);
+
+ if (!skb)
+ return;
+
+ info = IEEE80211_SKB_CB(skb);
+ info->flags &= ~IEEE80211_TX_STAT_ACK;
+ info->flags &= ~IEEE80211_TX_STAT_NOACK_TRANSMITTED;
ieee80211_tx_status_irqsafe(wcn->hw, skb);
ieee80211_wake_queues(wcn->hw);
@@ -376,8 +418,21 @@
dma_unmap_single(wcn->dev, ctl->desc->src_addr_l,
ctl->skb->len, DMA_TO_DEVICE);
info = IEEE80211_SKB_CB(ctl->skb);
- if (!(info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS)) {
- /* Keep frame until TX status comes */
+ if (info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS) {
+ if (info->flags & IEEE80211_TX_CTL_NO_ACK) {
+ info->flags |= IEEE80211_TX_STAT_NOACK_TRANSMITTED;
+ ieee80211_tx_status_irqsafe(wcn->hw, ctl->skb);
+ } else {
+ /* Wait for the TX ack indication or timeout... */
+ spin_lock(&wcn->dxe_lock);
+ if (WARN_ON(wcn->tx_ack_skb))
+ ieee80211_free_txskb(wcn->hw, wcn->tx_ack_skb);
+ wcn->tx_ack_skb = ctl->skb; /* Tracking ref */
+ mod_timer(&wcn->tx_ack_timer, jiffies + HZ / 10);
+ spin_unlock(&wcn->dxe_lock);
+ }
+ /* do not free, ownership transferred to mac80211 status cb */
+ } else {
ieee80211_free_txskb(wcn->hw, ctl->skb);
}
@@ -436,8 +491,9 @@
int_reason);
if (int_reason & (WCN36XX_CH_STAT_INT_DONE_MASK |
- WCN36XX_CH_STAT_INT_ED_MASK))
+ WCN36XX_CH_STAT_INT_ED_MASK)) {
reap_tx_dxes(wcn, &wcn->dxe_tx_h_ch);
+ }
}
if (int_src & WCN36XX_INT_MASK_CHAN_TX_L) {
@@ -448,7 +504,6 @@
wcn36xx_dxe_write_register(wcn,
WCN36XX_DXE_0_INT_CLR,
WCN36XX_INT_MASK_CHAN_TX_L);
-
if (int_reason & WCN36XX_CH_STAT_INT_ERR_MASK ) {
wcn36xx_dxe_write_register(wcn,
@@ -475,8 +530,9 @@
int_reason);
if (int_reason & (WCN36XX_CH_STAT_INT_DONE_MASK |
- WCN36XX_CH_STAT_INT_ED_MASK))
+ WCN36XX_CH_STAT_INT_ED_MASK)) {
reap_tx_dxes(wcn, &wcn->dxe_tx_l_ch);
+ }
}
return IRQ_HANDLED;
@@ -638,13 +694,13 @@
16 - (WCN36XX_BD_CHUNK_SIZE % 8);
s = wcn->mgmt_mem_pool.chunk_size * WCN36XX_DXE_CH_DESC_NUMB_TX_H;
- cpu_addr = dma_alloc_coherent(wcn->dev, s, &wcn->mgmt_mem_pool.phy_addr,
+ cpu_addr = dma_alloc_coherent(wcn->dev, s,
+ &wcn->mgmt_mem_pool.phy_addr,
GFP_KERNEL);
if (!cpu_addr)
goto out_err;
wcn->mgmt_mem_pool.virt_addr = cpu_addr;
- memset(cpu_addr, 0, s);
/* Allocate BD headers for DATA frames */
@@ -653,13 +709,13 @@
16 - (WCN36XX_BD_CHUNK_SIZE % 8);
s = wcn->data_mem_pool.chunk_size * WCN36XX_DXE_CH_DESC_NUMB_TX_L;
- cpu_addr = dma_alloc_coherent(wcn->dev, s, &wcn->data_mem_pool.phy_addr,
+ cpu_addr = dma_alloc_coherent(wcn->dev, s,
+ &wcn->data_mem_pool.phy_addr,
GFP_KERNEL);
if (!cpu_addr)
goto out_err;
wcn->data_mem_pool.virt_addr = cpu_addr;
- memset(cpu_addr, 0, s);
return 0;
@@ -828,7 +884,6 @@
WCN36XX_DXE_WQ_TX_L);
wcn36xx_dxe_read_register(wcn, WCN36XX_DXE_REG_CH_EN, ®_data);
- wcn36xx_dxe_enable_ch_int(wcn, WCN36XX_INT_MASK_CHAN_TX_L);
/***************************************/
/* Init descriptors for TX HIGH channel */
@@ -852,9 +907,6 @@
wcn36xx_dxe_read_register(wcn, WCN36XX_DXE_REG_CH_EN, ®_data);
- /* Enable channel interrupts */
- wcn36xx_dxe_enable_ch_int(wcn, WCN36XX_INT_MASK_CHAN_TX_H);
-
/***************************************/
/* Init descriptors for RX LOW channel */
/***************************************/
@@ -863,7 +915,6 @@
dev_err(wcn->dev, "Error allocating descriptor\n");
goto out_err_rxl_ch;
}
-
/* For RX we need to preallocated buffers */
wcn36xx_dxe_ch_alloc_skb(wcn, &wcn->dxe_rx_l_ch);
@@ -886,9 +937,6 @@
wcn36xx_dxe_write_register(wcn,
WCN36XX_DXE_REG_CTL_RX_L,
WCN36XX_DXE_CH_DEFAULT_CTL_RX_L);
-
- /* Enable channel interrupts */
- wcn36xx_dxe_enable_ch_int(wcn, WCN36XX_INT_MASK_CHAN_RX_L);
/***************************************/
/* Init descriptors for RX HIGH channel */
@@ -921,12 +969,17 @@
WCN36XX_DXE_REG_CTL_RX_H,
WCN36XX_DXE_CH_DEFAULT_CTL_RX_H);
- /* Enable channel interrupts */
- wcn36xx_dxe_enable_ch_int(wcn, WCN36XX_INT_MASK_CHAN_RX_H);
-
ret = wcn36xx_dxe_request_irqs(wcn);
if (ret < 0)
goto out_err_irq;
+
+ timer_setup(&wcn->tx_ack_timer, wcn36xx_dxe_tx_timer, 0);
+
+ /* Enable channel interrupts */
+ wcn36xx_dxe_enable_ch_int(wcn, WCN36XX_INT_MASK_CHAN_TX_L);
+ wcn36xx_dxe_enable_ch_int(wcn, WCN36XX_INT_MASK_CHAN_TX_H);
+ wcn36xx_dxe_enable_ch_int(wcn, WCN36XX_INT_MASK_CHAN_RX_L);
+ wcn36xx_dxe_enable_ch_int(wcn, WCN36XX_INT_MASK_CHAN_RX_H);
return 0;
@@ -944,14 +997,27 @@
void wcn36xx_dxe_deinit(struct wcn36xx *wcn)
{
+ int reg_data = 0;
+
+ /* Disable channel interrupts */
+ wcn36xx_dxe_disable_ch_int(wcn, WCN36XX_INT_MASK_CHAN_RX_H);
+ wcn36xx_dxe_disable_ch_int(wcn, WCN36XX_INT_MASK_CHAN_RX_L);
+ wcn36xx_dxe_disable_ch_int(wcn, WCN36XX_INT_MASK_CHAN_TX_H);
+ wcn36xx_dxe_disable_ch_int(wcn, WCN36XX_INT_MASK_CHAN_TX_L);
+
free_irq(wcn->tx_irq, wcn);
free_irq(wcn->rx_irq, wcn);
+ del_timer(&wcn->tx_ack_timer);
if (wcn->tx_ack_skb) {
ieee80211_tx_status_irqsafe(wcn->hw, wcn->tx_ack_skb);
wcn->tx_ack_skb = NULL;
}
+ /* Put the DXE block into reset before freeing memory */
+ reg_data = WCN36XX_DXE_REG_RESET;
+ wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_REG_CSR_RESET, reg_data);
+
wcn36xx_dxe_ch_free_skbs(wcn, &wcn->dxe_rx_l_ch);
wcn36xx_dxe_ch_free_skbs(wcn, &wcn->dxe_rx_h_ch);
--
Gitblit v1.6.2