Ignore:
Timestamp:
2011-08-29T20:41:18+02:00 (5 years ago)
Author:
nbd
Message:

ath9k: fix a few crash issues on hardware reset

File:
1 moved

Legend:

Unmodified
Added
Removed
  • trunk/package/mac80211/patches/582-ath9k_merge_reset_functions.patch

    r28118 r28122  
    11--- a/drivers/net/wireless/ath/ath9k/main.c 
    22+++ b/drivers/net/wireless/ath/ath9k/main.c 
    3 @@ -212,83 +212,47 @@ static int ath_update_survey_stats(struc 
     3@@ -212,83 +212,57 @@ static int ath_update_survey_stats(struc 
    44        return ret; 
    55 } 
     
    1212-static int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw, 
    1313-                   struct ath9k_channel *hchan) 
    14 +static bool ath_prepare_reset(struct ath_softc *sc, bool retry_tx, bool flush) 
     14+static void __ath_cancel_work(struct ath_softc *sc) 
    1515 { 
    16         struct ath_hw *ah = sc->sc_ah; 
    17         struct ath_common *common = ath9k_hw_common(ah); 
     16-       struct ath_hw *ah = sc->sc_ah; 
     17-       struct ath_common *common = ath9k_hw_common(ah); 
    1818-       struct ieee80211_conf *conf = &common->hw->conf; 
    1919-       bool fastcc = true, stopped; 
     
    2121-       struct ath9k_hw_cal_data *caldata = NULL; 
    2222-       int r; 
    23 +       bool ret; 
    24   
     23- 
    2524-       if (sc->sc_flags & SC_OP_INVALID) 
    2625-               return -EIO; 
    27 +       ieee80211_stop_queues(sc->hw); 
    28   
    29         sc->hw_busy_count = 0; 
    30 - 
    31         del_timer_sync(&common->ani.timer); 
     26- 
     27-       sc->hw_busy_count = 0; 
     28- 
     29-       del_timer_sync(&common->ani.timer); 
    3230        cancel_work_sync(&sc->paprd_work); 
    3331        cancel_work_sync(&sc->hw_check_work); 
    3432        cancel_delayed_work_sync(&sc->tx_complete_work); 
    3533        cancel_delayed_work_sync(&sc->hw_pll_work); 
     34+} 
    3635  
    3736-       ath9k_ps_wakeup(sc); 
    38 - 
     37+static void ath_cancel_work(struct ath_softc *sc) 
     38+{ 
     39+       __ath_cancel_work(sc); 
     40+       cancel_work_sync(&sc->hw_reset_work); 
     41+} 
     42  
    3943-       spin_lock_bh(&sc->sc_pcu_lock); 
    40 - 
     44+static bool ath_prepare_reset(struct ath_softc *sc, bool retry_tx, bool flush) 
     45+{ 
     46+       struct ath_hw *ah = sc->sc_ah; 
     47+       struct ath_common *common = ath9k_hw_common(ah); 
     48+       bool ret; 
     49  
    4150-       /* 
    4251-        * This is only performed if the channel settings have 
     
    4857-        * the relevant bits of the h/w. 
    4958-        */ 
    50         ath9k_hw_disable_interrupts(ah); 
     59-       ath9k_hw_disable_interrupts(ah); 
    5160-       stopped = ath_drain_all_txq(sc, false); 
    52 - 
     61+       ieee80211_stop_queues(sc->hw); 
     62  
    5363-       if (!ath_stoprecv(sc)) 
    5464-               stopped = false; 
     65+       sc->hw_busy_count = 0; 
     66+       del_timer_sync(&common->ani.timer); 
    5567  
    5668-       if (!ath9k_hw_check_alive(ah)) 
    5769-               stopped = false; 
    58 +       ret = ath_drain_all_txq(sc, retry_tx); 
     70+       ath9k_hw_disable_interrupts(ah); 
    5971  
    6072-       /* XXX: do not flush receive queue here. We don't want 
    6173-        * to flush data frames already in queue because of 
    6274-        * changing channel. */ 
    63 - 
     75+       ret = ath_drain_all_txq(sc, retry_tx); 
     76  
    6477-       if (!stopped || !(sc->sc_flags & SC_OP_OFFCHANNEL)) 
    6578-               fastcc = false; 
     
    105118  
    106119        ath9k_cmn_update_txpow(ah, sc->curtxpow, 
    107 @@ -296,21 +260,89 @@ static int ath_set_channel(struct ath_so 
     120@@ -296,21 +270,93 @@ static int ath_set_channel(struct ath_so 
    108121        ath9k_hw_set_interrupts(ah, ah->imask); 
    109122        ath9k_hw_enable_interrupts(ah); 
     
    137150+       int r; 
    138151+ 
     152+       __ath_cancel_work(sc); 
     153+ 
     154+       spin_lock_bh(&sc->sc_pcu_lock); 
     155  
    139156+       if (!(sc->sc_flags & SC_OP_OFFCHANNEL)) { 
    140157+               fastcc = false; 
     
    164181+               ath_err(common, 
    165182+                       "Unable to reset channel, reset status %d\n", r); 
    166 +               return r; 
     183+               goto out; 
    167184+       } 
    168185+ 
    169186+       if (!ath_complete_reset(sc, true)) 
    170 +               return -EIO; 
    171 + 
     187+               r = -EIO; 
     188+ 
     189+out: 
     190        spin_unlock_bh(&sc->sc_pcu_lock); 
    172191+       return 0; 
    173192+} 
     
    183202+{ 
    184203+       int r; 
    185   
     204+ 
    186205+       if (sc->sc_flags & SC_OP_INVALID) 
    187206+               return -EIO; 
     
    189208+       ath9k_ps_wakeup(sc); 
    190209+ 
    191 +       spin_lock_bh(&sc->sc_pcu_lock); 
    192210+       r = ath_reset_internal(sc, hchan, false); 
    193         spin_unlock_bh(&sc->sc_pcu_lock); 
    194211  
    195212        ath9k_ps_restore(sc); 
     
    198215 } 
    199216  
    200 @@ -893,28 +925,13 @@ static void ath_radio_enable(struct ath_ 
     217@@ -823,28 +869,13 @@ static void ath_radio_enable(struct ath_ 
    201218                        channel->center_freq, r); 
    202219        } 
     
    228245  
    229246        ath9k_ps_restore(sc); 
    230 @@ -927,12 +944,8 @@ void ath_radio_disable(struct ath_softc  
     247@@ -857,11 +888,10 @@ void ath_radio_disable(struct ath_softc  
    231248        int r; 
    232249  
    233250        ath9k_ps_wakeup(sc); 
    234251-       cancel_delayed_work_sync(&sc->hw_pll_work); 
    235 - 
    236         spin_lock_bh(&sc->sc_pcu_lock); 
     252  
     253-       spin_lock_bh(&sc->sc_pcu_lock); 
     254+       ath_cancel_work(sc); 
    237255  
    238256-       ieee80211_stop_queues(hw); 
    239 - 
     257+       spin_lock_bh(&sc->sc_pcu_lock); 
     258  
    240259        /* 
    241260         * Keep the LED on when the radio is disabled 
    242          * during idle unassociated state. 
    243 @@ -942,13 +955,7 @@ void ath_radio_disable(struct ath_softc  
     261@@ -872,13 +902,7 @@ void ath_radio_disable(struct ath_softc  
    244262                ath9k_hw_cfg_gpio_input(ah, ah->led_pin); 
    245263        } 
     
    256274        if (!ah->curchan) 
    257275                ah->curchan = ath9k_cmn_get_curchannel(hw, ah); 
    258 @@ -970,48 +977,11 @@ void ath_radio_disable(struct ath_softc  
    259   
    260  int ath_reset(struct ath_softc *sc, bool retry_tx) 
     276@@ -900,48 +924,11 @@ void ath_radio_disable(struct ath_softc  
     277  
     278 static int ath_reset(struct ath_softc *sc, bool retry_tx) 
    261279 { 
    262280-       struct ath_hw *ah = sc->sc_ah; 
     
    306324        if (retry_tx) { 
    307325                int i; 
    308 @@ -1024,12 +994,6 @@ int ath_reset(struct ath_softc *sc, bool 
     326@@ -954,12 +941,6 @@ static int ath_reset(struct ath_softc *s 
    309327                } 
    310328        } 
     
    319337  
    320338        return r; 
    321 @@ -1081,28 +1045,6 @@ static int ath9k_start(struct ieee80211_ 
     339@@ -969,9 +950,7 @@ void ath_reset_work(struct work_struct * 
     340 { 
     341        struct ath_softc *sc = container_of(work, struct ath_softc, hw_check_work); 
     342  
     343-       spin_lock_bh(&sc->sc_pcu_lock); 
     344        ath_reset(sc, true); 
     345-       spin_unlock_bh(&sc->sc_pcu_lock); 
     346 } 
     347  
     348 void ath_hw_check(struct work_struct *work) 
     349@@ -992,11 +971,8 @@ void ath_hw_check(struct work_struct *wo 
     350        ath_dbg(common, ATH_DBG_RESET, "Possible baseband hang, " 
     351                "busy=%d (try %d)\n", busy, sc->hw_busy_count + 1); 
     352        if (busy >= 99) { 
     353-               if (++sc->hw_busy_count >= 3) { 
     354-                       spin_lock_bh(&sc->sc_pcu_lock); 
     355-                       ath_reset(sc, true); 
     356-                       spin_unlock_bh(&sc->sc_pcu_lock); 
     357-               } 
     358+               if (++sc->hw_busy_count >= 3) 
     359+                       ieee80211_queue_work(sc->hw, &sc->hw_reset_work); 
     360  
     361        } else if (busy >= 0) 
     362                sc->hw_busy_count = 0; 
     363@@ -1016,9 +992,7 @@ static void ath_hw_pll_rx_hang_check(str 
     364                        /* Rx is hung for more than 500ms. Reset it */ 
     365                        ath_dbg(common, ATH_DBG_RESET, 
     366                                "Possible RX hang, resetting"); 
     367-                       spin_lock_bh(&sc->sc_pcu_lock); 
     368-                       ath_reset(sc, true); 
     369-                       spin_unlock_bh(&sc->sc_pcu_lock); 
     370+                       ieee80211_queue_work(sc->hw, &sc->hw_reset_work); 
     371                        count = 0; 
     372                } 
     373        } else 
     374@@ -1089,28 +1063,6 @@ static int ath9k_start(struct ieee80211_ 
    322375                goto mutex_unlock; 
    323376        } 
     
    348401        ah->imask = ATH9K_INT_TX | ATH9K_INT_RXEOL | 
    349402                    ATH9K_INT_RXORN | ATH9K_INT_FATAL | 
    350 @@ -1125,12 +1067,14 @@ static int ath9k_start(struct ieee80211_ 
     403@@ -1133,12 +1085,14 @@ static int ath9k_start(struct ieee80211_ 
    351404  
    352405        /* Disable BMISS interrupt when we're not associated */ 
     
    367420        if ((ah->btcoex_hw.scheme != ATH_BTCOEX_CFG_NONE) && 
    368421            !ah->btcoex_hw.enabled) { 
     422@@ -1231,10 +1185,7 @@ static void ath9k_stop(struct ieee80211_ 
     423  
     424        mutex_lock(&sc->mutex); 
     425  
     426-       cancel_delayed_work_sync(&sc->tx_complete_work); 
     427-       cancel_delayed_work_sync(&sc->hw_pll_work); 
     428-       cancel_work_sync(&sc->paprd_work); 
     429-       cancel_work_sync(&sc->hw_check_work); 
     430+       ath_cancel_work(sc); 
     431  
     432        if (sc->sc_flags & SC_OP_INVALID) { 
     433                ath_dbg(common, ATH_DBG_ANY, "Device not present\n"); 
     434@@ -2351,9 +2302,11 @@ static void ath9k_flush(struct ieee80211 
     435        ath9k_ps_wakeup(sc); 
     436        spin_lock_bh(&sc->sc_pcu_lock); 
     437        drain_txq = ath_drain_all_txq(sc, false); 
     438+       spin_unlock_bh(&sc->sc_pcu_lock); 
     439+ 
     440        if (!drain_txq) 
     441                ath_reset(sc, false); 
     442-       spin_unlock_bh(&sc->sc_pcu_lock); 
     443+ 
     444        ath9k_ps_restore(sc); 
     445        ieee80211_wake_queues(hw); 
     446  
Note: See TracChangeset for help on using the changeset viewer.