mac80211: add initial support for AR9330
[openwrt.git] / package / mac80211 / patches / 570-ath9k-add-external_reset-callback-to-ath9k_platfom_d.patch
1 diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c
2 index 323b6ab..5d373fc 100644
3 --- a/drivers/net/wireless/ath/ath9k/hw.c
4 +++ b/drivers/net/wireless/ath/ath9k/hw.c
5 @@ -1161,6 +1161,41 @@ static bool ath9k_hw_set_reset(struct ath_hw *ah, int type)
6                         rst_flags |= AR_RTC_RC_MAC_COLD;
7         }
8  
9 +       if (AR_SREV_9330(ah)) {
10 +               int npend = 0;
11 +               int i;
12 +
13 +               /* AR9330 WAR:
14 +                * call external reset function to reset WMAC if:
15 +                * - doing a cold reset
16 +                * - we have pending frames in the TX queues
17 +                */
18 +
19 +               for (i = 0; i < AR_NUM_QCU; i++) {
20 +                       npend = ath9k_hw_numtxpending(ah, i);
21 +                       if (npend)
22 +                               break;
23 +               }
24 +
25 +               if (ah->external_reset &&
26 +                   (npend || type == ATH9K_RESET_COLD)) {
27 +                       int reset_err = 0;
28 +
29 +                       ath_dbg(ath9k_hw_common(ah), ATH_DBG_RESET,
30 +                               "reset MAC via external reset\n");
31 +
32 +                       reset_err = ah->external_reset();
33 +                       if (reset_err) {
34 +                               ath_err(ath9k_hw_common(ah),
35 +                                       "External reset failed, err=%d\n",
36 +                                       reset_err);
37 +                               return false;
38 +                       }
39 +
40 +                       REG_WRITE(ah, AR_RTC_RESET, 1);
41 +               }
42 +       }
43 +
44         REG_WRITE(ah, AR_RTC_RC, rst_flags);
45  
46         REGWRITE_BUFFER_FLUSH(ah);
47 diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h
48 index 8d9ac49..f29a806 100644
49 --- a/drivers/net/wireless/ath/ath9k/hw.h
50 +++ b/drivers/net/wireless/ath/ath9k/hw.h
51 @@ -864,6 +864,7 @@ struct ath_hw {
52  
53         bool is_clk_25mhz;
54         int (*get_mac_revision)(void);
55 +       int (*external_reset)(void);
56  };
57  
58  struct ath_bus_ops {
59 diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c
60 index 5ffabb9..f517649 100644
61 --- a/drivers/net/wireless/ath/ath9k/init.c
62 +++ b/drivers/net/wireless/ath/ath9k/init.c
63 @@ -576,6 +576,7 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid,
64                 sc->sc_ah->led_pin = pdata->led_pin;
65                 ah->is_clk_25mhz = pdata->is_clk_25mhz;
66                 ah->get_mac_revision = pdata->get_mac_revision;
67 +               ah->external_reset = pdata->external_reset;
68         }
69  
70         common = ath9k_hw_common(ah);
71 diff --git a/include/linux/ath9k_platform.h b/include/linux/ath9k_platform.h
72 index c207607..6e3f54f 100644
73 --- a/include/linux/ath9k_platform.h
74 +++ b/include/linux/ath9k_platform.h
75 @@ -31,6 +31,7 @@ struct ath9k_platform_data {
76  
77         bool is_clk_25mhz;
78         int (*get_mac_revision)(void);
79 +       int (*external_reset)(void);
80  };
81  
82  #endif /* _LINUX_ATH9K_PLATFORM_H */