ath9k: do a chip reset if noise floor calibration fails, should improve stability
[openwrt/svn-archive/archive.git] / package / kernel / mac80211 / patches / 565-ath9k_restart_after_nfcal_failure.patch
1 --- a/drivers/net/wireless/ath/ath9k/calib.c
2 +++ b/drivers/net/wireless/ath/ath9k/calib.c
3 @@ -234,7 +234,7 @@ void ath9k_hw_start_nfcal(struct ath_hw
4 REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF);
5 }
6
7 -void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan)
8 +int ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan)
9 {
10 struct ath9k_nfcal_hist *h = NULL;
11 unsigned i, j;
12 @@ -301,7 +301,7 @@ void ath9k_hw_loadnf(struct ath_hw *ah,
13 ath_dbg(common, ANY,
14 "Timeout while waiting for nf to load: AR_PHY_AGC_CONTROL=0x%x\n",
15 REG_READ(ah, AR_PHY_AGC_CONTROL));
16 - return;
17 + return -ETIMEDOUT;
18 }
19
20 /*
21 @@ -322,6 +322,8 @@ void ath9k_hw_loadnf(struct ath_hw *ah,
22 }
23 }
24 REGWRITE_BUFFER_FLUSH(ah);
25 +
26 + return 0;
27 }
28
29
30 --- a/drivers/net/wireless/ath/ath9k/calib.h
31 +++ b/drivers/net/wireless/ath/ath9k/calib.h
32 @@ -109,7 +109,7 @@ struct ath9k_pacal_info{
33
34 bool ath9k_hw_reset_calvalid(struct ath_hw *ah);
35 void ath9k_hw_start_nfcal(struct ath_hw *ah, bool update);
36 -void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan);
37 +int ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan);
38 bool ath9k_hw_getnf(struct ath_hw *ah, struct ath9k_channel *chan);
39 void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah,
40 struct ath9k_channel *chan);
41 --- a/drivers/net/wireless/ath/ath9k/ar9002_calib.c
42 +++ b/drivers/net/wireless/ath/ath9k/ar9002_calib.c
43 @@ -657,14 +657,13 @@ static void ar9002_hw_olc_temp_compensat
44 ar9280_hw_olc_temp_compensation(ah);
45 }
46
47 -static bool ar9002_hw_calibrate(struct ath_hw *ah,
48 - struct ath9k_channel *chan,
49 - u8 rxchainmask,
50 - bool longcal)
51 +static int ar9002_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan,
52 + u8 rxchainmask, bool longcal)
53 {
54 bool iscaldone = true;
55 struct ath9k_cal_list *currCal = ah->cal_list_curr;
56 bool nfcal, nfcal_pending = false;
57 + int ret;
58
59 nfcal = !!(REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF);
60 if (ah->caldata)
61 @@ -698,7 +697,9 @@ static bool ar9002_hw_calibrate(struct a
62 * NF is slow time-variant, so it is OK to use a
63 * historical value.
64 */
65 - ath9k_hw_loadnf(ah, ah->curchan);
66 + ret = ath9k_hw_loadnf(ah, ah->curchan);
67 + if (ret < 0)
68 + return ret;
69 }
70
71 if (longcal) {
72 --- a/drivers/net/wireless/ath/ath9k/hw-ops.h
73 +++ b/drivers/net/wireless/ath/ath9k/hw-ops.h
74 @@ -41,10 +41,9 @@ static inline void ath9k_hw_set_desc_lin
75 ath9k_hw_ops(ah)->set_desc_link(ds, link);
76 }
77
78 -static inline bool ath9k_hw_calibrate(struct ath_hw *ah,
79 - struct ath9k_channel *chan,
80 - u8 rxchainmask,
81 - bool longcal)
82 +static inline int ath9k_hw_calibrate(struct ath_hw *ah,
83 + struct ath9k_channel *chan,
84 + u8 rxchainmask, bool longcal)
85 {
86 return ath9k_hw_ops(ah)->calibrate(ah, chan, rxchainmask, longcal);
87 }
88 --- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c
89 +++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c
90 @@ -121,13 +121,12 @@ static bool ar9003_hw_per_calibration(st
91 return iscaldone;
92 }
93
94 -static bool ar9003_hw_calibrate(struct ath_hw *ah,
95 - struct ath9k_channel *chan,
96 - u8 rxchainmask,
97 - bool longcal)
98 +static int ar9003_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan,
99 + u8 rxchainmask, bool longcal)
100 {
101 bool iscaldone = true;
102 struct ath9k_cal_list *currCal = ah->cal_list_curr;
103 + int ret;
104
105 /*
106 * For given calibration:
107 @@ -163,7 +162,9 @@ static bool ar9003_hw_calibrate(struct a
108 * NF is slow time-variant, so it is OK to use a historical
109 * value.
110 */
111 - ath9k_hw_loadnf(ah, ah->curchan);
112 + ret = ath9k_hw_loadnf(ah, ah->curchan);
113 + if (ret < 0)
114 + return ret;
115
116 /* start NF calibration, without updating BB NF register */
117 ath9k_hw_start_nfcal(ah, false);
118 --- a/drivers/net/wireless/ath/ath9k/hw.h
119 +++ b/drivers/net/wireless/ath/ath9k/hw.h
120 @@ -695,10 +695,8 @@ struct ath_hw_ops {
121 bool power_off);
122 void (*rx_enable)(struct ath_hw *ah);
123 void (*set_desc_link)(void *ds, u32 link);
124 - bool (*calibrate)(struct ath_hw *ah,
125 - struct ath9k_channel *chan,
126 - u8 rxchainmask,
127 - bool longcal);
128 + int (*calibrate)(struct ath_hw *ah, struct ath9k_channel *chan,
129 + u8 rxchainmask, bool longcal);
130 bool (*get_isr)(struct ath_hw *ah, enum ath9k_int *masked,
131 u32 *sync_cause_p);
132 void (*set_txdesc)(struct ath_hw *ah, void *ds,
133 --- a/drivers/net/wireless/ath/ath9k/debug.h
134 +++ b/drivers/net/wireless/ath/ath9k/debug.h
135 @@ -49,6 +49,7 @@ enum ath_reset_type {
136 RESET_TYPE_MAC_HANG,
137 RESET_TYPE_BEACON_STUCK,
138 RESET_TYPE_MCI,
139 + RESET_TYPE_CALIBRATION,
140 __RESET_TYPE_MAX
141 };
142
143 --- a/drivers/net/wireless/ath/ath9k/debug.c
144 +++ b/drivers/net/wireless/ath/ath9k/debug.c
145 @@ -857,6 +857,7 @@ static ssize_t read_file_reset(struct fi
146 [RESET_TYPE_MAC_HANG] = "MAC Hang",
147 [RESET_TYPE_BEACON_STUCK] = "Stuck Beacon",
148 [RESET_TYPE_MCI] = "MCI Reset",
149 + [RESET_TYPE_CALIBRATION] = "Calibration error",
150 };
151 char buf[512];
152 unsigned int len = 0;
153 --- a/drivers/net/wireless/ath/ath9k/link.c
154 +++ b/drivers/net/wireless/ath/ath9k/link.c
155 @@ -376,9 +376,14 @@ void ath_ani_calibrate(unsigned long dat
156
157 /* Perform calibration if necessary */
158 if (longcal || shortcal) {
159 - common->ani.caldone =
160 - ath9k_hw_calibrate(ah, ah->curchan,
161 - ah->rxchainmask, longcal);
162 + int ret = ath9k_hw_calibrate(ah, ah->curchan, ah->rxchainmask,
163 + longcal);
164 + if (ret < 0) {
165 + ath9k_queue_reset(sc, RESET_TYPE_CALIBRATION);
166 + return;
167 + }
168 +
169 + common->ani.caldone = ret;
170 }
171
172 ath_dbg(common, ANI,