aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless
diff options
context:
space:
mode:
authorIdo Yariv <ido@wizery.com>2011-06-06 07:57:05 -0400
committerLuciano Coelho <coelho@ti.com>2011-06-27 08:05:15 -0400
commitbaacb9aed020b890ddf6a57837a169092a25fc9b (patch)
treea961d0ce3773f29b419f97715863fea151f3ecf4 /drivers/net/wireless
parent842f1a6c71551ac10fbdff4a4e65821228df9ea7 (diff)
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: Ido Yariv <ido@wizery.com> Signed-off-by: Arik Nemtsov <arik@wizery.com> Signed-off-by: Luciano Coelho <coelho@ti.com>
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r--drivers/net/wireless/wl12xx/cmd.c4
-rw-r--r--drivers/net/wireless/wl12xx/debugfs.c2
-rw-r--r--drivers/net/wireless/wl12xx/main.c14
-rw-r--r--drivers/net/wireless/wl12xx/ps.c2
-rw-r--r--drivers/net/wireless/wl12xx/scan.c2
-rw-r--r--drivers/net/wireless/wl12xx/testmode.c2
-rw-r--r--drivers/net/wireless/wl12xx/wl12xx.h2
7 files changed, 21 insertions, 7 deletions
diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c
index cdcb324093a5..f3d332d11f81 100644
--- a/drivers/net/wireless/wl12xx/cmd.c
+++ b/drivers/net/wireless/wl12xx/cmd.c
@@ -105,7 +105,7 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len,
105 105
106fail: 106fail:
107 WARN_ON(1); 107 WARN_ON(1);
108 ieee80211_queue_work(wl->hw, &wl->recovery_work); 108 wl12xx_queue_recovery_work(wl);
109 return ret; 109 return ret;
110} 110}
111 111
@@ -356,7 +356,7 @@ static int wl1271_cmd_wait_for_event(struct wl1271 *wl, u32 mask)
356 356
357 ret = wl1271_cmd_wait_for_event_or_timeout(wl, mask); 357 ret = wl1271_cmd_wait_for_event_or_timeout(wl, mask);
358 if (ret != 0) { 358 if (ret != 0) {
359 ieee80211_queue_work(wl->hw, &wl->recovery_work); 359 wl12xx_queue_recovery_work(wl);
360 return ret; 360 return ret;
361 } 361 }
362 362
diff --git a/drivers/net/wireless/wl12xx/debugfs.c b/drivers/net/wireless/wl12xx/debugfs.c
index c3f19463474d..da2127018300 100644
--- a/drivers/net/wireless/wl12xx/debugfs.c
+++ b/drivers/net/wireless/wl12xx/debugfs.c
@@ -306,7 +306,7 @@ static ssize_t start_recovery_write(struct file *file,
306 struct wl1271 *wl = file->private_data; 306 struct wl1271 *wl = file->private_data;
307 307
308 mutex_lock(&wl->mutex); 308 mutex_lock(&wl->mutex);
309 ieee80211_queue_work(wl->hw, &wl->recovery_work); 309 wl12xx_queue_recovery_work(wl);
310 mutex_unlock(&wl->mutex); 310 mutex_unlock(&wl->mutex);
311 311
312 return count; 312 return count;
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index 2c03b4716d3f..6926d0a3e5c6 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -937,7 +937,7 @@ irqreturn_t wl1271_irq(int irq, void *cookie)
937 if (unlikely(intr & WL1271_ACX_INTR_WATCHDOG)) { 937 if (unlikely(intr & WL1271_ACX_INTR_WATCHDOG)) {
938 wl1271_error("watchdog interrupt received! " 938 wl1271_error("watchdog interrupt received! "
939 "starting recovery."); 939 "starting recovery.");
940 ieee80211_queue_work(wl->hw, &wl->recovery_work); 940 wl12xx_queue_recovery_work(wl);
941 941
942 /* restarting the chip. ignore any other interrupt. */ 942 /* restarting the chip. ignore any other interrupt. */
943 goto out; 943 goto out;
@@ -1099,6 +1099,12 @@ out:
1099 return ret; 1099 return ret;
1100} 1100}
1101 1101
1102void wl12xx_queue_recovery_work(struct wl1271 *wl)
1103{
1104 if (!test_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags))
1105 ieee80211_queue_work(wl->hw, &wl->recovery_work);
1106}
1107
1102static void wl1271_recovery_work(struct work_struct *work) 1108static void wl1271_recovery_work(struct work_struct *work)
1103{ 1109{
1104 struct wl1271 *wl = 1110 struct wl1271 *wl =
@@ -1109,6 +1115,9 @@ static void wl1271_recovery_work(struct work_struct *work)
1109 if (wl->state != WL1271_STATE_ON) 1115 if (wl->state != WL1271_STATE_ON)
1110 goto out; 1116 goto out;
1111 1117
1118 /* Avoid a recursive recovery */
1119 set_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags);
1120
1112 wl1271_info("Hardware recovery in progress. FW ver: %s pc: 0x%x", 1121 wl1271_info("Hardware recovery in progress. FW ver: %s pc: 0x%x",
1113 wl->chip.fw_ver_str, wl1271_read32(wl, SCR_PAD4)); 1122 wl->chip.fw_ver_str, wl1271_read32(wl, SCR_PAD4));
1114 1123
@@ -1125,6 +1134,9 @@ static void wl1271_recovery_work(struct work_struct *work)
1125 1134
1126 /* reboot the chipset */ 1135 /* reboot the chipset */
1127 __wl1271_op_remove_interface(wl, false); 1136 __wl1271_op_remove_interface(wl, false);
1137
1138 clear_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags);
1139
1128 ieee80211_restart_hw(wl->hw); 1140 ieee80211_restart_hw(wl->hw);
1129 1141
1130 /* 1142 /*
diff --git a/drivers/net/wireless/wl12xx/ps.c b/drivers/net/wireless/wl12xx/ps.c
index 5116db0826f9..3e68a664c9de 100644
--- a/drivers/net/wireless/wl12xx/ps.c
+++ b/drivers/net/wireless/wl12xx/ps.c
@@ -118,7 +118,7 @@ int wl1271_ps_elp_wakeup(struct wl1271 *wl)
118 &compl, msecs_to_jiffies(WL1271_WAKEUP_TIMEOUT)); 118 &compl, msecs_to_jiffies(WL1271_WAKEUP_TIMEOUT));
119 if (ret == 0) { 119 if (ret == 0) {
120 wl1271_error("ELP wakeup timeout!"); 120 wl1271_error("ELP wakeup timeout!");
121 ieee80211_queue_work(wl->hw, &wl->recovery_work); 121 wl12xx_queue_recovery_work(wl);
122 ret = -ETIMEDOUT; 122 ret = -ETIMEDOUT;
123 goto err; 123 goto err;
124 } else if (ret < 0) { 124 } else if (ret < 0) {
diff --git a/drivers/net/wireless/wl12xx/scan.c b/drivers/net/wireless/wl12xx/scan.c
index cb84dd5edf4d..5e5c66dd06d5 100644
--- a/drivers/net/wireless/wl12xx/scan.c
+++ b/drivers/net/wireless/wl12xx/scan.c
@@ -62,7 +62,7 @@ void wl1271_scan_complete_work(struct work_struct *work)
62 62
63 if (wl->scan.failed) { 63 if (wl->scan.failed) {
64 wl1271_info("Scan completed due to error."); 64 wl1271_info("Scan completed due to error.");
65 ieee80211_queue_work(wl->hw, &wl->recovery_work); 65 wl12xx_queue_recovery_work(wl);
66 } 66 }
67 67
68out: 68out:
diff --git a/drivers/net/wireless/wl12xx/testmode.c b/drivers/net/wireless/wl12xx/testmode.c
index da351d7cd1f2..5d5e1ef87206 100644
--- a/drivers/net/wireless/wl12xx/testmode.c
+++ b/drivers/net/wireless/wl12xx/testmode.c
@@ -260,7 +260,7 @@ static int wl1271_tm_cmd_recover(struct wl1271 *wl, struct nlattr *tb[])
260{ 260{
261 wl1271_debug(DEBUG_TESTMODE, "testmode cmd recover"); 261 wl1271_debug(DEBUG_TESTMODE, "testmode cmd recover");
262 262
263 ieee80211_queue_work(wl->hw, &wl->recovery_work); 263 wl12xx_queue_recovery_work(wl);
264 264
265 return 0; 265 return 0;
266} 266}
diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h
index bbf4ee6d4102..754a16ce5bc0 100644
--- a/drivers/net/wireless/wl12xx/wl12xx.h
+++ b/drivers/net/wireless/wl12xx/wl12xx.h
@@ -361,6 +361,7 @@ enum wl12xx_flags {
361 WL1271_FLAG_PENDING_WORK, 361 WL1271_FLAG_PENDING_WORK,
362 WL1271_FLAG_SOFT_GEMINI, 362 WL1271_FLAG_SOFT_GEMINI,
363 WL1271_FLAG_RX_STREAMING_STARTED, 363 WL1271_FLAG_RX_STREAMING_STARTED,
364 WL1271_FLAG_RECOVERY_IN_PROGRESS,
364}; 365};
365 366
366struct wl1271_link { 367struct wl1271_link {
@@ -612,6 +613,7 @@ struct wl1271_station {
612int wl1271_plt_start(struct wl1271 *wl); 613int wl1271_plt_start(struct wl1271 *wl);
613int wl1271_plt_stop(struct wl1271 *wl); 614int wl1271_plt_stop(struct wl1271 *wl);
614int wl1271_recalc_rx_streaming(struct wl1271 *wl); 615int wl1271_recalc_rx_streaming(struct wl1271 *wl);
616void wl12xx_queue_recovery_work(struct wl1271 *wl);
615 617
616#define JOIN_TIMEOUT 5000 /* 5000 milliseconds to join */ 618#define JOIN_TIMEOUT 5000 /* 5000 milliseconds to join */
617 619