Commit 89dcb1da authored by Bryan O'Donoghue's avatar Bryan O'Donoghue Committed by Kalle Valo

wcn36xx: Fix DMA channel enable/disable cycle

Right now we have a broken sequence where we enable DMA channel interrupts
which can be left enabled and never disabled if we hit an error path.

Worse still when we unload the driver, the DMA channel interrupt bits are
left intact. About the only saving grace here is that we do remember to
disable the wcnss interrupt when unload the driver.

Fixes: 8e84c258 ("wcn36xx: mac80211 driver for Qualcomm WCN3660/WCN3680 hardware")
Signed-off-by: default avatarBryan O'Donoghue <bryan.odonoghue@linaro.org>
Signed-off-by: default avatarKalle Valo <kvalo@codeaurora.org>
Link: https://lore.kernel.org/r/20211105122152.1580542-2-bryan.odonoghue@linaro.org
parent 22f9ba7f
...@@ -272,6 +272,21 @@ static int wcn36xx_dxe_enable_ch_int(struct wcn36xx *wcn, u16 wcn_ch) ...@@ -272,6 +272,21 @@ static int wcn36xx_dxe_enable_ch_int(struct wcn36xx *wcn, u16 wcn_ch)
return 0; 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,
&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, static int wcn36xx_dxe_fill_skb(struct device *dev,
struct wcn36xx_dxe_ctl *ctl, struct wcn36xx_dxe_ctl *ctl,
gfp_t gfp) gfp_t gfp)
...@@ -916,7 +931,6 @@ int wcn36xx_dxe_init(struct wcn36xx *wcn) ...@@ -916,7 +931,6 @@ int wcn36xx_dxe_init(struct wcn36xx *wcn)
WCN36XX_DXE_WQ_TX_L); WCN36XX_DXE_WQ_TX_L);
wcn36xx_dxe_read_register(wcn, WCN36XX_DXE_REG_CH_EN, &reg_data); wcn36xx_dxe_read_register(wcn, WCN36XX_DXE_REG_CH_EN, &reg_data);
wcn36xx_dxe_enable_ch_int(wcn, WCN36XX_INT_MASK_CHAN_TX_L);
/***************************************/ /***************************************/
/* Init descriptors for TX HIGH channel */ /* Init descriptors for TX HIGH channel */
...@@ -940,9 +954,6 @@ int wcn36xx_dxe_init(struct wcn36xx *wcn) ...@@ -940,9 +954,6 @@ int wcn36xx_dxe_init(struct wcn36xx *wcn)
wcn36xx_dxe_read_register(wcn, WCN36XX_DXE_REG_CH_EN, &reg_data); wcn36xx_dxe_read_register(wcn, WCN36XX_DXE_REG_CH_EN, &reg_data);
/* Enable channel interrupts */
wcn36xx_dxe_enable_ch_int(wcn, WCN36XX_INT_MASK_CHAN_TX_H);
/***************************************/ /***************************************/
/* Init descriptors for RX LOW channel */ /* Init descriptors for RX LOW channel */
/***************************************/ /***************************************/
...@@ -952,7 +963,6 @@ int wcn36xx_dxe_init(struct wcn36xx *wcn) ...@@ -952,7 +963,6 @@ int wcn36xx_dxe_init(struct wcn36xx *wcn)
goto out_err_rxl_ch; goto out_err_rxl_ch;
} }
/* For RX we need to preallocated buffers */ /* For RX we need to preallocated buffers */
wcn36xx_dxe_ch_alloc_skb(wcn, &wcn->dxe_rx_l_ch); wcn36xx_dxe_ch_alloc_skb(wcn, &wcn->dxe_rx_l_ch);
...@@ -975,9 +985,6 @@ int wcn36xx_dxe_init(struct wcn36xx *wcn) ...@@ -975,9 +985,6 @@ int wcn36xx_dxe_init(struct wcn36xx *wcn)
WCN36XX_DXE_REG_CTL_RX_L, WCN36XX_DXE_REG_CTL_RX_L,
WCN36XX_DXE_CH_DEFAULT_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 */ /* Init descriptors for RX HIGH channel */
/***************************************/ /***************************************/
...@@ -1009,15 +1016,18 @@ int wcn36xx_dxe_init(struct wcn36xx *wcn) ...@@ -1009,15 +1016,18 @@ int wcn36xx_dxe_init(struct wcn36xx *wcn)
WCN36XX_DXE_REG_CTL_RX_H, WCN36XX_DXE_REG_CTL_RX_H,
WCN36XX_DXE_CH_DEFAULT_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); ret = wcn36xx_dxe_request_irqs(wcn);
if (ret < 0) if (ret < 0)
goto out_err_irq; goto out_err_irq;
timer_setup(&wcn->tx_ack_timer, wcn36xx_dxe_tx_timer, 0); 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; return 0;
out_err_irq: out_err_irq:
...@@ -1034,6 +1044,12 @@ int wcn36xx_dxe_init(struct wcn36xx *wcn) ...@@ -1034,6 +1044,12 @@ int wcn36xx_dxe_init(struct wcn36xx *wcn)
void wcn36xx_dxe_deinit(struct wcn36xx *wcn) void wcn36xx_dxe_deinit(struct wcn36xx *wcn)
{ {
/* 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->tx_irq, wcn);
free_irq(wcn->rx_irq, wcn); free_irq(wcn->rx_irq, wcn);
del_timer(&wcn->tx_ack_timer); del_timer(&wcn->tx_ack_timer);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment