lkml.org 
[lkml]   [2022]   [Jan]   [24]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 5.10 057/563] wcn36xx: Fix DMA channel enable/disable cycle
    Date
    From: Bryan O'Donoghue <bryan.odonoghue@linaro.org>

    [ Upstream commit 89dcb1da611d9b3ff0728502d58372fdaae9ebff ]

    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: 8e84c2582169 ("wcn36xx: mac80211 driver for Qualcomm WCN3660/WCN3680 hardware")
    Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
    Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
    Link: https://lore.kernel.org/r/20211105122152.1580542-2-bryan.odonoghue@linaro.org
    Signed-off-by: Sasha Levin <sashal@kernel.org>
    ---
    drivers/net/wireless/ath/wcn36xx/dxe.c | 38 ++++++++++++++++++--------
    1 file changed, 27 insertions(+), 11 deletions(-)

    diff --git a/drivers/net/wireless/ath/wcn36xx/dxe.c b/drivers/net/wireless/ath/wcn36xx/dxe.c
    index cf4eb0fb28151..0909d0c423cbb 100644
    --- a/drivers/net/wireless/ath/wcn36xx/dxe.c
    +++ b/drivers/net/wireless/ath/wcn36xx/dxe.c
    @@ -272,6 +272,21 @@ static int wcn36xx_dxe_enable_ch_int(struct wcn36xx *wcn, u16 wcn_ch)
    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,
    struct wcn36xx_dxe_ctl *ctl,
    gfp_t gfp)
    @@ -869,7 +884,6 @@ int wcn36xx_dxe_init(struct wcn36xx *wcn)
    WCN36XX_DXE_WQ_TX_L);

    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 */
    @@ -893,9 +907,6 @@ int wcn36xx_dxe_init(struct wcn36xx *wcn)

    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 */
    /***************************************/
    @@ -905,7 +916,6 @@ int wcn36xx_dxe_init(struct wcn36xx *wcn)
    goto out_err_rxl_ch;
    }

    -
    /* For RX we need to preallocated buffers */
    wcn36xx_dxe_ch_alloc_skb(wcn, &wcn->dxe_rx_l_ch);

    @@ -928,9 +938,6 @@ int wcn36xx_dxe_init(struct wcn36xx *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 */
    /***************************************/
    @@ -962,15 +969,18 @@ int wcn36xx_dxe_init(struct wcn36xx *wcn)
    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;

    out_err_irq:
    @@ -987,6 +997,12 @@ out_err_txh_ch:

    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->rx_irq, wcn);
    del_timer(&wcn->tx_ack_timer);
    --
    2.34.1


    \
     
     \ /
      Last update: 2022-01-25 04:10    [W:4.027 / U:0.448 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site