[backfire] ar71xx: backport ethernet regression fix from r22075
[openwrt-10.03/.git] / package / mac80211 / patches / 540-ath9k_hang_check.patch
1 --- a/drivers/net/wireless/ath/ath9k/ath9k.h
2 +++ b/drivers/net/wireless/ath/ath9k/ath9k.h
3 @@ -428,6 +428,7 @@ int ath_beaconq_config(struct ath_softc 
4  
5  #define ATH_PAPRD_TIMEOUT      100 /* msecs */
6  
7 +void ath_hw_check(struct work_struct *work);
8  void ath_paprd_calibrate(struct work_struct *work);
9  void ath_ani_calibrate(unsigned long data);
10  
11 @@ -563,6 +564,7 @@ struct ath_softc {
12         spinlock_t sc_pm_lock;
13         struct mutex mutex;
14         struct work_struct paprd_work;
15 +       struct work_struct hw_check_work;
16         struct completion paprd_complete;
17  
18         u32 intrstatus;
19 --- a/drivers/net/wireless/ath/ath9k/main.c
20 +++ b/drivers/net/wireless/ath/ath9k/main.c
21 @@ -516,6 +516,25 @@ static void ath_node_detach(struct ath_s
22                 ath_tx_node_cleanup(sc, an);
23  }
24  
25 +void ath_hw_check(struct work_struct *work)
26 +{
27 +       struct ath_softc *sc = container_of(work, struct ath_softc, hw_check_work);
28 +       int i;
29 +
30 +       ath9k_ps_wakeup(sc);
31 +
32 +       for (i = 0; i < 3; i++) {
33 +               if (ath9k_hw_check_alive(sc->sc_ah))
34 +                       goto out;
35 +
36 +               msleep(1);
37 +       }
38 +       ath_reset(sc, false);
39 +
40 +out:
41 +       ath9k_ps_restore(sc);
42 +}
43 +
44  void ath9k_tasklet(unsigned long data)
45  {
46         struct ath_softc *sc = (struct ath_softc *)data;
47 @@ -527,13 +546,15 @@ void ath9k_tasklet(unsigned long data)
48  
49         ath9k_ps_wakeup(sc);
50  
51 -       if ((status & ATH9K_INT_FATAL) ||
52 -           !ath9k_hw_check_alive(ah)) {
53 +       if (status & ATH9K_INT_FATAL) {
54                 ath_reset(sc, false);
55                 ath9k_ps_restore(sc);
56                 return;
57         }
58  
59 +       if (!ath9k_hw_check_alive(ah))
60 +               ieee80211_queue_work(sc->hw, &sc->hw_check_work);
61 +
62         if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)
63                 rxmask = (ATH9K_INT_RXHP | ATH9K_INT_RXLP | ATH9K_INT_RXEOL |
64                           ATH9K_INT_RXORN);
65 @@ -1254,6 +1275,7 @@ static void ath9k_stop(struct ieee80211_
66  
67         cancel_delayed_work_sync(&sc->tx_complete_work);
68         cancel_work_sync(&sc->paprd_work);
69 +       cancel_work_sync(&sc->hw_check_work);
70  
71         if (!sc->num_sec_wiphy) {
72                 cancel_delayed_work_sync(&sc->wiphy_work);
73 @@ -1977,6 +1999,7 @@ static void ath9k_sw_scan_start(struct i
74         sc->sc_flags |= SC_OP_SCANNING;
75         del_timer_sync(&common->ani.timer);
76         cancel_work_sync(&sc->paprd_work);
77 +       cancel_work_sync(&sc->hw_check_work);
78         cancel_delayed_work_sync(&sc->tx_complete_work);
79         mutex_unlock(&sc->mutex);
80  }
81 --- a/drivers/net/wireless/ath/ath9k/init.c
82 +++ b/drivers/net/wireless/ath/ath9k/init.c
83 @@ -751,6 +751,7 @@ int ath9k_init_device(u16 devid, struct 
84                         goto error_world;
85         }
86  
87 +       INIT_WORK(&sc->hw_check_work, ath_hw_check);
88         INIT_WORK(&sc->paprd_work, ath_paprd_calibrate);
89         INIT_WORK(&sc->chan_work, ath9k_wiphy_chan_work);
90         INIT_DELAYED_WORK(&sc->wiphy_work, ath9k_wiphy_work);