diff options
author | Vladimir Kondratiev <qca_vkondrat@qca.qualcomm.com> | 2014-05-27 07:45:45 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2014-05-29 13:10:29 -0400 |
commit | fc219eed079eb0b11d93ed1adf4fa58f2b465215 (patch) | |
tree | 6d68c2202f1a2ec44723e481f50e8d902a0c8502 | |
parent | d87bac1b26e81192d7264a73ea11324be80b493c (diff) |
wil6210: limit fw error recovery attempts
In case there is something fundamentally wrong with the firmware
(example: RF cable disconnected), FW will always crash immediately
after reset. This leads to infinite fw error recovery loop.
Count consecutive unsuccessful error recovery attempts in a short period
of time, and stop doing recovery after some reasonable count.
It is still possible to manually reset fw doing
interface down/up sequence.
Signed-off-by: Vladimir Kondratiev <qca_vkondrat@qca.qualcomm.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r-- | drivers/net/wireless/ath/wil6210/main.c | 22 | ||||
-rw-r--r-- | drivers/net/wireless/ath/wil6210/wil6210.h | 4 |
2 files changed, 25 insertions, 1 deletions
diff --git a/drivers/net/wireless/ath/wil6210/main.c b/drivers/net/wireless/ath/wil6210/main.c index 670cc6de3b4c..f24cb92cc185 100644 --- a/drivers/net/wireless/ath/wil6210/main.c +++ b/drivers/net/wireless/ath/wil6210/main.c | |||
@@ -161,12 +161,30 @@ static void wil_fw_error_worker(struct work_struct *work) | |||
161 | if (no_fw_recovery) | 161 | if (no_fw_recovery) |
162 | return; | 162 | return; |
163 | 163 | ||
164 | /* increment @recovery_count if less then WIL6210_FW_RECOVERY_TO | ||
165 | * passed since last recovery attempt | ||
166 | */ | ||
167 | if (time_is_after_jiffies(wil->last_fw_recovery + | ||
168 | WIL6210_FW_RECOVERY_TO)) | ||
169 | wil->recovery_count++; | ||
170 | else | ||
171 | wil->recovery_count = 1; /* fw was alive for a long time */ | ||
172 | |||
173 | if (wil->recovery_count > WIL6210_FW_RECOVERY_RETRIES) { | ||
174 | wil_err(wil, "too many recovery attempts (%d), giving up\n", | ||
175 | wil->recovery_count); | ||
176 | return; | ||
177 | } | ||
178 | |||
179 | wil->last_fw_recovery = jiffies; | ||
180 | |||
164 | mutex_lock(&wil->mutex); | 181 | mutex_lock(&wil->mutex); |
165 | switch (wdev->iftype) { | 182 | switch (wdev->iftype) { |
166 | case NL80211_IFTYPE_STATION: | 183 | case NL80211_IFTYPE_STATION: |
167 | case NL80211_IFTYPE_P2P_CLIENT: | 184 | case NL80211_IFTYPE_P2P_CLIENT: |
168 | case NL80211_IFTYPE_MONITOR: | 185 | case NL80211_IFTYPE_MONITOR: |
169 | wil_info(wil, "fw error recovery started...\n"); | 186 | wil_info(wil, "fw error recovery started (try %d)...\n", |
187 | wil->recovery_count); | ||
170 | wil_reset(wil); | 188 | wil_reset(wil); |
171 | 189 | ||
172 | /* need to re-allocate Rx ring after reset */ | 190 | /* need to re-allocate Rx ring after reset */ |
@@ -249,6 +267,8 @@ int wil_priv_init(struct wil6210_priv *wil) | |||
249 | return -EAGAIN; | 267 | return -EAGAIN; |
250 | } | 268 | } |
251 | 269 | ||
270 | wil->last_fw_recovery = jiffies; | ||
271 | |||
252 | return 0; | 272 | return 0; |
253 | } | 273 | } |
254 | 274 | ||
diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h index 3427ac4a4fa1..f8c598ebd9ee 100644 --- a/drivers/net/wireless/ath/wil6210/wil6210.h +++ b/drivers/net/wireless/ath/wil6210/wil6210.h | |||
@@ -40,6 +40,8 @@ static inline u32 WIL_GET_BITS(u32 x, int b0, int b1) | |||
40 | #define WIL6210_MAX_CID (8) /* HW limit */ | 40 | #define WIL6210_MAX_CID (8) /* HW limit */ |
41 | #define WIL6210_NAPI_BUDGET (16) /* arbitrary */ | 41 | #define WIL6210_NAPI_BUDGET (16) /* arbitrary */ |
42 | #define WIL6210_ITR_TRSH (10000) /* arbitrary - about 15 IRQs/msec */ | 42 | #define WIL6210_ITR_TRSH (10000) /* arbitrary - about 15 IRQs/msec */ |
43 | #define WIL6210_FW_RECOVERY_RETRIES (5) /* try to recover this many times */ | ||
44 | #define WIL6210_FW_RECOVERY_TO msecs_to_jiffies(5000) | ||
43 | 45 | ||
44 | /* Hardware definitions begin */ | 46 | /* Hardware definitions begin */ |
45 | 47 | ||
@@ -361,6 +363,8 @@ struct wil6210_priv { | |||
361 | u32 fw_version; | 363 | u32 fw_version; |
362 | u32 hw_version; | 364 | u32 hw_version; |
363 | u8 n_mids; /* number of additional MIDs as reported by FW */ | 365 | u8 n_mids; /* number of additional MIDs as reported by FW */ |
366 | int recovery_count; /* num of FW recovery attempts in a short time */ | ||
367 | unsigned long last_fw_recovery; /* jiffies of last fw recovery */ | ||
364 | /* profile */ | 368 | /* profile */ |
365 | u32 monitor_flags; | 369 | u32 monitor_flags; |
366 | u32 secure_pcp; /* create secure PCP? */ | 370 | u32 secure_pcp; /* create secure PCP? */ |