Commit baacb9ae authored by Ido Yariv's avatar Ido Yariv Committed by Luciano Coelho

wl12xx: Avoid recovery while one is already in progress

During recovery work commands sent to the FW could fail and schedule
additional recovery work. Since the chip is going to be powered off,
avoid recursive recoveries.
Signed-off-by: default avatarIdo Yariv <ido@wizery.com>
Signed-off-by: default avatarArik Nemtsov <arik@wizery.com>
Signed-off-by: default avatarLuciano Coelho <coelho@ti.com>
parent 842f1a6c
...@@ -105,7 +105,7 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len, ...@@ -105,7 +105,7 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len,
fail: fail:
WARN_ON(1); WARN_ON(1);
ieee80211_queue_work(wl->hw, &wl->recovery_work); wl12xx_queue_recovery_work(wl);
return ret; return ret;
} }
...@@ -356,7 +356,7 @@ static int wl1271_cmd_wait_for_event(struct wl1271 *wl, u32 mask) ...@@ -356,7 +356,7 @@ static int wl1271_cmd_wait_for_event(struct wl1271 *wl, u32 mask)
ret = wl1271_cmd_wait_for_event_or_timeout(wl, mask); ret = wl1271_cmd_wait_for_event_or_timeout(wl, mask);
if (ret != 0) { if (ret != 0) {
ieee80211_queue_work(wl->hw, &wl->recovery_work); wl12xx_queue_recovery_work(wl);
return ret; return ret;
} }
......
...@@ -306,7 +306,7 @@ static ssize_t start_recovery_write(struct file *file, ...@@ -306,7 +306,7 @@ static ssize_t start_recovery_write(struct file *file,
struct wl1271 *wl = file->private_data; struct wl1271 *wl = file->private_data;
mutex_lock(&wl->mutex); mutex_lock(&wl->mutex);
ieee80211_queue_work(wl->hw, &wl->recovery_work); wl12xx_queue_recovery_work(wl);
mutex_unlock(&wl->mutex); mutex_unlock(&wl->mutex);
return count; return count;
......
...@@ -937,7 +937,7 @@ irqreturn_t wl1271_irq(int irq, void *cookie) ...@@ -937,7 +937,7 @@ irqreturn_t wl1271_irq(int irq, void *cookie)
if (unlikely(intr & WL1271_ACX_INTR_WATCHDOG)) { if (unlikely(intr & WL1271_ACX_INTR_WATCHDOG)) {
wl1271_error("watchdog interrupt received! " wl1271_error("watchdog interrupt received! "
"starting recovery."); "starting recovery.");
ieee80211_queue_work(wl->hw, &wl->recovery_work); wl12xx_queue_recovery_work(wl);
/* restarting the chip. ignore any other interrupt. */ /* restarting the chip. ignore any other interrupt. */
goto out; goto out;
...@@ -1099,6 +1099,12 @@ static int wl1271_fetch_nvs(struct wl1271 *wl) ...@@ -1099,6 +1099,12 @@ static int wl1271_fetch_nvs(struct wl1271 *wl)
return ret; return ret;
} }
void wl12xx_queue_recovery_work(struct wl1271 *wl)
{
if (!test_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags))
ieee80211_queue_work(wl->hw, &wl->recovery_work);
}
static void wl1271_recovery_work(struct work_struct *work) static void wl1271_recovery_work(struct work_struct *work)
{ {
struct wl1271 *wl = struct wl1271 *wl =
...@@ -1109,6 +1115,9 @@ static void wl1271_recovery_work(struct work_struct *work) ...@@ -1109,6 +1115,9 @@ static void wl1271_recovery_work(struct work_struct *work)
if (wl->state != WL1271_STATE_ON) if (wl->state != WL1271_STATE_ON)
goto out; goto out;
/* Avoid a recursive recovery */
set_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags);
wl1271_info("Hardware recovery in progress. FW ver: %s pc: 0x%x", wl1271_info("Hardware recovery in progress. FW ver: %s pc: 0x%x",
wl->chip.fw_ver_str, wl1271_read32(wl, SCR_PAD4)); wl->chip.fw_ver_str, wl1271_read32(wl, SCR_PAD4));
...@@ -1125,6 +1134,9 @@ static void wl1271_recovery_work(struct work_struct *work) ...@@ -1125,6 +1134,9 @@ static void wl1271_recovery_work(struct work_struct *work)
/* reboot the chipset */ /* reboot the chipset */
__wl1271_op_remove_interface(wl, false); __wl1271_op_remove_interface(wl, false);
clear_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags);
ieee80211_restart_hw(wl->hw); ieee80211_restart_hw(wl->hw);
/* /*
......
...@@ -118,7 +118,7 @@ int wl1271_ps_elp_wakeup(struct wl1271 *wl) ...@@ -118,7 +118,7 @@ int wl1271_ps_elp_wakeup(struct wl1271 *wl)
&compl, msecs_to_jiffies(WL1271_WAKEUP_TIMEOUT)); &compl, msecs_to_jiffies(WL1271_WAKEUP_TIMEOUT));
if (ret == 0) { if (ret == 0) {
wl1271_error("ELP wakeup timeout!"); wl1271_error("ELP wakeup timeout!");
ieee80211_queue_work(wl->hw, &wl->recovery_work); wl12xx_queue_recovery_work(wl);
ret = -ETIMEDOUT; ret = -ETIMEDOUT;
goto err; goto err;
} else if (ret < 0) { } else if (ret < 0) {
......
...@@ -62,7 +62,7 @@ void wl1271_scan_complete_work(struct work_struct *work) ...@@ -62,7 +62,7 @@ void wl1271_scan_complete_work(struct work_struct *work)
if (wl->scan.failed) { if (wl->scan.failed) {
wl1271_info("Scan completed due to error."); wl1271_info("Scan completed due to error.");
ieee80211_queue_work(wl->hw, &wl->recovery_work); wl12xx_queue_recovery_work(wl);
} }
out: out:
......
...@@ -260,7 +260,7 @@ static int wl1271_tm_cmd_recover(struct wl1271 *wl, struct nlattr *tb[]) ...@@ -260,7 +260,7 @@ static int wl1271_tm_cmd_recover(struct wl1271 *wl, struct nlattr *tb[])
{ {
wl1271_debug(DEBUG_TESTMODE, "testmode cmd recover"); wl1271_debug(DEBUG_TESTMODE, "testmode cmd recover");
ieee80211_queue_work(wl->hw, &wl->recovery_work); wl12xx_queue_recovery_work(wl);
return 0; return 0;
} }
......
...@@ -361,6 +361,7 @@ enum wl12xx_flags { ...@@ -361,6 +361,7 @@ enum wl12xx_flags {
WL1271_FLAG_PENDING_WORK, WL1271_FLAG_PENDING_WORK,
WL1271_FLAG_SOFT_GEMINI, WL1271_FLAG_SOFT_GEMINI,
WL1271_FLAG_RX_STREAMING_STARTED, WL1271_FLAG_RX_STREAMING_STARTED,
WL1271_FLAG_RECOVERY_IN_PROGRESS,
}; };
struct wl1271_link { struct wl1271_link {
...@@ -612,6 +613,7 @@ struct wl1271_station { ...@@ -612,6 +613,7 @@ struct wl1271_station {
int wl1271_plt_start(struct wl1271 *wl); int wl1271_plt_start(struct wl1271 *wl);
int wl1271_plt_stop(struct wl1271 *wl); int wl1271_plt_stop(struct wl1271 *wl);
int wl1271_recalc_rx_streaming(struct wl1271 *wl); int wl1271_recalc_rx_streaming(struct wl1271 *wl);
void wl12xx_queue_recovery_work(struct wl1271 *wl);
#define JOIN_TIMEOUT 5000 /* 5000 milliseconds to join */ #define JOIN_TIMEOUT 5000 /* 5000 milliseconds to join */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment