lkml.org 
[lkml]   [2014]   [Jan]   [6]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 3.12 088/144] ath9k: Fix interrupt handling for the AR9002 family
    Date
    3.12-stable review patch.  If anyone has any objections, please let me know.

    ------------------

    From: Sujith Manoharan <c_manoha@qca.qualcomm.com>

    commit 73f0b56a1ff64e7fb6c3a62088804bab93bcedc2 upstream.

    This patch adds a driver workaround for a HW issue.

    A race condition in the HW results in missing interrupts,
    which can be avoided by a read/write with the ISR register.
    All chips in the AR9002 series are affected by this bug - AR9003
    and above do not have this problem.

    Cc: Felix Fietkau <nbd@openwrt.org>
    Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
    Signed-off-by: John W. Linville <linville@tuxdriver.com>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

    ---
    drivers/net/wireless/ath/ath9k/ar9002_mac.c | 52 +++++++++++++++++++++++-----
    1 file changed, 43 insertions(+), 9 deletions(-)

    --- a/drivers/net/wireless/ath/ath9k/ar9002_mac.c
    +++ b/drivers/net/wireless/ath/ath9k/ar9002_mac.c
    @@ -76,9 +76,16 @@ static bool ar9002_hw_get_isr(struct ath
    mask2 |= ATH9K_INT_CST;
    if (isr2 & AR_ISR_S2_TSFOOR)
    mask2 |= ATH9K_INT_TSFOOR;
    +
    + if (!(pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED)) {
    + REG_WRITE(ah, AR_ISR_S2, isr2);
    + isr &= ~AR_ISR_BCNMISC;
    + }
    }

    - isr = REG_READ(ah, AR_ISR_RAC);
    + if (pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED)
    + isr = REG_READ(ah, AR_ISR_RAC);
    +
    if (isr == 0xffffffff) {
    *masked = 0;
    return false;
    @@ -97,11 +104,23 @@ static bool ar9002_hw_get_isr(struct ath

    *masked |= ATH9K_INT_TX;

    - s0_s = REG_READ(ah, AR_ISR_S0_S);
    + if (pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED) {
    + s0_s = REG_READ(ah, AR_ISR_S0_S);
    + s1_s = REG_READ(ah, AR_ISR_S1_S);
    + } else {
    + s0_s = REG_READ(ah, AR_ISR_S0);
    + REG_WRITE(ah, AR_ISR_S0, s0_s);
    + s1_s = REG_READ(ah, AR_ISR_S1);
    + REG_WRITE(ah, AR_ISR_S1, s1_s);
    +
    + isr &= ~(AR_ISR_TXOK |
    + AR_ISR_TXDESC |
    + AR_ISR_TXERR |
    + AR_ISR_TXEOL);
    + }
    +
    ah->intr_txqs |= MS(s0_s, AR_ISR_S0_QCU_TXOK);
    ah->intr_txqs |= MS(s0_s, AR_ISR_S0_QCU_TXDESC);
    -
    - s1_s = REG_READ(ah, AR_ISR_S1_S);
    ah->intr_txqs |= MS(s1_s, AR_ISR_S1_QCU_TXERR);
    ah->intr_txqs |= MS(s1_s, AR_ISR_S1_QCU_TXEOL);
    }
    @@ -114,13 +133,15 @@ static bool ar9002_hw_get_isr(struct ath
    *masked |= mask2;
    }

    - if (AR_SREV_9100(ah))
    - return true;
    -
    - if (isr & AR_ISR_GENTMR) {
    + if (!AR_SREV_9100(ah) && (isr & AR_ISR_GENTMR)) {
    u32 s5_s;

    - s5_s = REG_READ(ah, AR_ISR_S5_S);
    + if (pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED) {
    + s5_s = REG_READ(ah, AR_ISR_S5_S);
    + } else {
    + s5_s = REG_READ(ah, AR_ISR_S5);
    + }
    +
    ah->intr_gen_timer_trigger =
    MS(s5_s, AR_ISR_S5_GENTIMER_TRIG);

    @@ -133,8 +154,21 @@ static bool ar9002_hw_get_isr(struct ath
    if ((s5_s & AR_ISR_S5_TIM_TIMER) &&
    !(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP))
    *masked |= ATH9K_INT_TIM_TIMER;
    +
    + if (!(pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED)) {
    + REG_WRITE(ah, AR_ISR_S5, s5_s);
    + isr &= ~AR_ISR_GENTMR;
    + }
    + }
    +
    + if (!(pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED)) {
    + REG_WRITE(ah, AR_ISR, isr);
    + REG_READ(ah, AR_ISR);
    }

    + if (AR_SREV_9100(ah))
    + return true;
    +
    if (sync_cause) {
    ath9k_debug_sync_cause(common, sync_cause);
    fatal_int =



    \
     
     \ /
      Last update: 2014-01-07 03:41    [W:4.060 / U:0.040 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site