aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/rt2x00
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/rt2x00')
-rw-r--r--drivers/net/wireless/rt2x00/rt2500usb.c36
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00.h1
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00dev.c38
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00mac.c4
-rw-r--r--drivers/net/wireless/rt2x00/rt73usb.c36
5 files changed, 70 insertions, 45 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c
index fdbd0ef2be4b..61e59c17a60a 100644
--- a/drivers/net/wireless/rt2x00/rt2500usb.c
+++ b/drivers/net/wireless/rt2x00/rt2500usb.c
@@ -138,11 +138,8 @@ static void rt2500usb_bbp_write(struct rt2x00_dev *rt2x00dev,
138 * Wait until the BBP becomes ready. 138 * Wait until the BBP becomes ready.
139 */ 139 */
140 reg = rt2500usb_bbp_check(rt2x00dev); 140 reg = rt2500usb_bbp_check(rt2x00dev);
141 if (rt2x00_get_field16(reg, PHY_CSR8_BUSY)) { 141 if (rt2x00_get_field16(reg, PHY_CSR8_BUSY))
142 ERROR(rt2x00dev, "PHY_CSR8 register busy. Write failed.\n"); 142 goto exit_fail;
143 mutex_unlock(&rt2x00dev->usb_cache_mutex);
144 return;
145 }
146 143
147 /* 144 /*
148 * Write the data into the BBP. 145 * Write the data into the BBP.
@@ -155,6 +152,13 @@ static void rt2500usb_bbp_write(struct rt2x00_dev *rt2x00dev,
155 rt2500usb_register_write_lock(rt2x00dev, PHY_CSR7, reg); 152 rt2500usb_register_write_lock(rt2x00dev, PHY_CSR7, reg);
156 153
157 mutex_unlock(&rt2x00dev->usb_cache_mutex); 154 mutex_unlock(&rt2x00dev->usb_cache_mutex);
155
156 return;
157
158exit_fail:
159 mutex_unlock(&rt2x00dev->usb_cache_mutex);
160
161 ERROR(rt2x00dev, "PHY_CSR8 register busy. Write failed.\n");
158} 162}
159 163
160static void rt2500usb_bbp_read(struct rt2x00_dev *rt2x00dev, 164static void rt2500usb_bbp_read(struct rt2x00_dev *rt2x00dev,
@@ -168,10 +172,8 @@ static void rt2500usb_bbp_read(struct rt2x00_dev *rt2x00dev,
168 * Wait until the BBP becomes ready. 172 * Wait until the BBP becomes ready.
169 */ 173 */
170 reg = rt2500usb_bbp_check(rt2x00dev); 174 reg = rt2500usb_bbp_check(rt2x00dev);
171 if (rt2x00_get_field16(reg, PHY_CSR8_BUSY)) { 175 if (rt2x00_get_field16(reg, PHY_CSR8_BUSY))
172 ERROR(rt2x00dev, "PHY_CSR8 register busy. Read failed.\n"); 176 goto exit_fail;
173 return;
174 }
175 177
176 /* 178 /*
177 * Write the request into the BBP. 179 * Write the request into the BBP.
@@ -186,17 +188,21 @@ static void rt2500usb_bbp_read(struct rt2x00_dev *rt2x00dev,
186 * Wait until the BBP becomes ready. 188 * Wait until the BBP becomes ready.
187 */ 189 */
188 reg = rt2500usb_bbp_check(rt2x00dev); 190 reg = rt2500usb_bbp_check(rt2x00dev);
189 if (rt2x00_get_field16(reg, PHY_CSR8_BUSY)) { 191 if (rt2x00_get_field16(reg, PHY_CSR8_BUSY))
190 ERROR(rt2x00dev, "PHY_CSR8 register busy. Read failed.\n"); 192 goto exit_fail;
191 *value = 0xff;
192 mutex_unlock(&rt2x00dev->usb_cache_mutex);
193 return;
194 }
195 193
196 rt2500usb_register_read_lock(rt2x00dev, PHY_CSR7, &reg); 194 rt2500usb_register_read_lock(rt2x00dev, PHY_CSR7, &reg);
197 *value = rt2x00_get_field16(reg, PHY_CSR7_DATA); 195 *value = rt2x00_get_field16(reg, PHY_CSR7_DATA);
198 196
199 mutex_unlock(&rt2x00dev->usb_cache_mutex); 197 mutex_unlock(&rt2x00dev->usb_cache_mutex);
198
199 return;
200
201exit_fail:
202 mutex_unlock(&rt2x00dev->usb_cache_mutex);
203
204 ERROR(rt2x00dev, "PHY_CSR8 register busy. Read failed.\n");
205 *value = 0xff;
200} 206}
201 207
202static void rt2500usb_rf_write(struct rt2x00_dev *rt2x00dev, 208static void rt2500usb_rf_write(struct rt2x00_dev *rt2x00dev,
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h
index 611d98320593..b4bf1e09cf9a 100644
--- a/drivers/net/wireless/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/rt2x00/rt2x00.h
@@ -821,6 +821,7 @@ struct rt2x00_dev {
821 /* 821 /*
822 * Scheduled work. 822 * Scheduled work.
823 */ 823 */
824 struct workqueue_struct *workqueue;
824 struct work_struct intf_work; 825 struct work_struct intf_work;
825 struct work_struct filter_work; 826 struct work_struct filter_work;
826 827
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c
index 2673d568bcac..c997d4f28ab3 100644
--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
@@ -75,7 +75,7 @@ static void rt2x00lib_start_link_tuner(struct rt2x00_dev *rt2x00dev)
75 75
76 rt2x00lib_reset_link_tuner(rt2x00dev); 76 rt2x00lib_reset_link_tuner(rt2x00dev);
77 77
78 queue_delayed_work(rt2x00dev->hw->workqueue, 78 queue_delayed_work(rt2x00dev->workqueue,
79 &rt2x00dev->link.work, LINK_TUNE_INTERVAL); 79 &rt2x00dev->link.work, LINK_TUNE_INTERVAL);
80} 80}
81 81
@@ -137,14 +137,6 @@ void rt2x00lib_disable_radio(struct rt2x00_dev *rt2x00dev)
137 return; 137 return;
138 138
139 /* 139 /*
140 * Stop all scheduled work.
141 */
142 if (work_pending(&rt2x00dev->intf_work))
143 cancel_work_sync(&rt2x00dev->intf_work);
144 if (work_pending(&rt2x00dev->filter_work))
145 cancel_work_sync(&rt2x00dev->filter_work);
146
147 /*
148 * Stop the TX queues. 140 * Stop the TX queues.
149 */ 141 */
150 ieee80211_stop_queues(rt2x00dev->hw); 142 ieee80211_stop_queues(rt2x00dev->hw);
@@ -398,8 +390,8 @@ static void rt2x00lib_link_tuner(struct work_struct *work)
398 * Increase tuner counter, and reschedule the next link tuner run. 390 * Increase tuner counter, and reschedule the next link tuner run.
399 */ 391 */
400 rt2x00dev->link.count++; 392 rt2x00dev->link.count++;
401 queue_delayed_work(rt2x00dev->hw->workqueue, &rt2x00dev->link.work, 393 queue_delayed_work(rt2x00dev->workqueue,
402 LINK_TUNE_INTERVAL); 394 &rt2x00dev->link.work, LINK_TUNE_INTERVAL);
403} 395}
404 396
405static void rt2x00lib_packetfilter_scheduled(struct work_struct *work) 397static void rt2x00lib_packetfilter_scheduled(struct work_struct *work)
@@ -433,6 +425,15 @@ static void rt2x00lib_intf_scheduled_iter(void *data, u8 *mac,
433 425
434 spin_unlock(&intf->lock); 426 spin_unlock(&intf->lock);
435 427
428 /*
429 * It is possible the radio was disabled while the work had been
430 * scheduled. If that happens we should return here immediately,
431 * note that in the spinlock protected area above the delayed_flags
432 * have been cleared correctly.
433 */
434 if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags))
435 return;
436
436 if (delayed_flags & DELAYED_UPDATE_BEACON) { 437 if (delayed_flags & DELAYED_UPDATE_BEACON) {
437 skb = ieee80211_beacon_get(rt2x00dev->hw, vif, &control); 438 skb = ieee80211_beacon_get(rt2x00dev->hw, vif, &control);
438 if (skb && rt2x00dev->ops->hw->beacon_update(rt2x00dev->hw, 439 if (skb && rt2x00dev->ops->hw->beacon_update(rt2x00dev->hw,
@@ -441,7 +442,7 @@ static void rt2x00lib_intf_scheduled_iter(void *data, u8 *mac,
441 } 442 }
442 443
443 if (delayed_flags & DELAYED_CONFIG_ERP) 444 if (delayed_flags & DELAYED_CONFIG_ERP)
444 rt2x00lib_config_erp(rt2x00dev, intf, &intf->conf); 445 rt2x00lib_config_erp(rt2x00dev, intf, &conf);
445 446
446 if (delayed_flags & DELAYED_LED_ASSOC) 447 if (delayed_flags & DELAYED_LED_ASSOC)
447 rt2x00leds_led_assoc(rt2x00dev, !!rt2x00dev->intf_associated); 448 rt2x00leds_led_assoc(rt2x00dev, !!rt2x00dev->intf_associated);
@@ -487,7 +488,7 @@ void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev)
487 rt2x00lib_beacondone_iter, 488 rt2x00lib_beacondone_iter,
488 rt2x00dev); 489 rt2x00dev);
489 490
490 queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->intf_work); 491 queue_work(rt2x00dev->workqueue, &rt2x00dev->intf_work);
491} 492}
492EXPORT_SYMBOL_GPL(rt2x00lib_beacondone); 493EXPORT_SYMBOL_GPL(rt2x00lib_beacondone);
493 494
@@ -1130,6 +1131,10 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev)
1130 /* 1131 /*
1131 * Initialize configuration work. 1132 * Initialize configuration work.
1132 */ 1133 */
1134 rt2x00dev->workqueue = create_singlethread_workqueue("rt2x00lib");
1135 if (!rt2x00dev->workqueue)
1136 goto exit;
1137
1133 INIT_WORK(&rt2x00dev->intf_work, rt2x00lib_intf_scheduled); 1138 INIT_WORK(&rt2x00dev->intf_work, rt2x00lib_intf_scheduled);
1134 INIT_WORK(&rt2x00dev->filter_work, rt2x00lib_packetfilter_scheduled); 1139 INIT_WORK(&rt2x00dev->filter_work, rt2x00lib_packetfilter_scheduled);
1135 INIT_DELAYED_WORK(&rt2x00dev->link.work, rt2x00lib_link_tuner); 1140 INIT_DELAYED_WORK(&rt2x00dev->link.work, rt2x00lib_link_tuner);
@@ -1190,6 +1195,13 @@ void rt2x00lib_remove_dev(struct rt2x00_dev *rt2x00dev)
1190 rt2x00leds_unregister(rt2x00dev); 1195 rt2x00leds_unregister(rt2x00dev);
1191 1196
1192 /* 1197 /*
1198 * Stop all queued work. Note that most tasks will already be halted
1199 * during rt2x00lib_disable_radio() and rt2x00lib_uninitialize().
1200 */
1201 flush_workqueue(rt2x00dev->workqueue);
1202 destroy_workqueue(rt2x00dev->workqueue);
1203
1204 /*
1193 * Free ieee80211_hw memory. 1205 * Free ieee80211_hw memory.
1194 */ 1206 */
1195 rt2x00lib_remove_hw(rt2x00dev); 1207 rt2x00lib_remove_hw(rt2x00dev);
diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c
index 87e280a21971..9cb023edd2e9 100644
--- a/drivers/net/wireless/rt2x00/rt2x00mac.c
+++ b/drivers/net/wireless/rt2x00/rt2x00mac.c
@@ -428,7 +428,7 @@ void rt2x00mac_configure_filter(struct ieee80211_hw *hw,
428 if (!test_bit(DRIVER_REQUIRE_SCHEDULED, &rt2x00dev->flags)) 428 if (!test_bit(DRIVER_REQUIRE_SCHEDULED, &rt2x00dev->flags))
429 rt2x00dev->ops->lib->config_filter(rt2x00dev, *total_flags); 429 rt2x00dev->ops->lib->config_filter(rt2x00dev, *total_flags);
430 else 430 else
431 queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->filter_work); 431 queue_work(rt2x00dev->workqueue, &rt2x00dev->filter_work);
432} 432}
433EXPORT_SYMBOL_GPL(rt2x00mac_configure_filter); 433EXPORT_SYMBOL_GPL(rt2x00mac_configure_filter);
434 434
@@ -509,7 +509,7 @@ void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw,
509 memcpy(&intf->conf, bss_conf, sizeof(*bss_conf)); 509 memcpy(&intf->conf, bss_conf, sizeof(*bss_conf));
510 if (delayed) { 510 if (delayed) {
511 intf->delayed_flags |= delayed; 511 intf->delayed_flags |= delayed;
512 queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->intf_work); 512 queue_work(rt2x00dev->workqueue, &rt2x00dev->intf_work);
513 } 513 }
514 spin_unlock(&intf->lock); 514 spin_unlock(&intf->lock);
515} 515}
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c
index fff8386e816b..83cc0147f698 100644
--- a/drivers/net/wireless/rt2x00/rt73usb.c
+++ b/drivers/net/wireless/rt2x00/rt73usb.c
@@ -134,11 +134,8 @@ static void rt73usb_bbp_write(struct rt2x00_dev *rt2x00dev,
134 * Wait until the BBP becomes ready. 134 * Wait until the BBP becomes ready.
135 */ 135 */
136 reg = rt73usb_bbp_check(rt2x00dev); 136 reg = rt73usb_bbp_check(rt2x00dev);
137 if (rt2x00_get_field32(reg, PHY_CSR3_BUSY)) { 137 if (rt2x00_get_field32(reg, PHY_CSR3_BUSY))
138 ERROR(rt2x00dev, "PHY_CSR3 register busy. Write failed.\n"); 138 goto exit_fail;
139 mutex_unlock(&rt2x00dev->usb_cache_mutex);
140 return;
141 }
142 139
143 /* 140 /*
144 * Write the data into the BBP. 141 * Write the data into the BBP.
@@ -151,6 +148,13 @@ static void rt73usb_bbp_write(struct rt2x00_dev *rt2x00dev,
151 148
152 rt73usb_register_write_lock(rt2x00dev, PHY_CSR3, reg); 149 rt73usb_register_write_lock(rt2x00dev, PHY_CSR3, reg);
153 mutex_unlock(&rt2x00dev->usb_cache_mutex); 150 mutex_unlock(&rt2x00dev->usb_cache_mutex);
151
152 return;
153
154exit_fail:
155 mutex_unlock(&rt2x00dev->usb_cache_mutex);
156
157 ERROR(rt2x00dev, "PHY_CSR3 register busy. Write failed.\n");
154} 158}
155 159
156static void rt73usb_bbp_read(struct rt2x00_dev *rt2x00dev, 160static void rt73usb_bbp_read(struct rt2x00_dev *rt2x00dev,
@@ -164,11 +168,8 @@ static void rt73usb_bbp_read(struct rt2x00_dev *rt2x00dev,
164 * Wait until the BBP becomes ready. 168 * Wait until the BBP becomes ready.
165 */ 169 */
166 reg = rt73usb_bbp_check(rt2x00dev); 170 reg = rt73usb_bbp_check(rt2x00dev);
167 if (rt2x00_get_field32(reg, PHY_CSR3_BUSY)) { 171 if (rt2x00_get_field32(reg, PHY_CSR3_BUSY))
168 ERROR(rt2x00dev, "PHY_CSR3 register busy. Read failed.\n"); 172 goto exit_fail;
169 mutex_unlock(&rt2x00dev->usb_cache_mutex);
170 return;
171 }
172 173
173 /* 174 /*
174 * Write the request into the BBP. 175 * Write the request into the BBP.
@@ -184,14 +185,19 @@ static void rt73usb_bbp_read(struct rt2x00_dev *rt2x00dev,
184 * Wait until the BBP becomes ready. 185 * Wait until the BBP becomes ready.
185 */ 186 */
186 reg = rt73usb_bbp_check(rt2x00dev); 187 reg = rt73usb_bbp_check(rt2x00dev);
187 if (rt2x00_get_field32(reg, PHY_CSR3_BUSY)) { 188 if (rt2x00_get_field32(reg, PHY_CSR3_BUSY))
188 ERROR(rt2x00dev, "PHY_CSR3 register busy. Read failed.\n"); 189 goto exit_fail;
189 *value = 0xff;
190 return;
191 }
192 190
193 *value = rt2x00_get_field32(reg, PHY_CSR3_VALUE); 191 *value = rt2x00_get_field32(reg, PHY_CSR3_VALUE);
194 mutex_unlock(&rt2x00dev->usb_cache_mutex); 192 mutex_unlock(&rt2x00dev->usb_cache_mutex);
193
194 return;
195
196exit_fail:
197 mutex_unlock(&rt2x00dev->usb_cache_mutex);
198
199 ERROR(rt2x00dev, "PHY_CSR3 register busy. Read failed.\n");
200 *value = 0xff;
195} 201}
196 202
197static void rt73usb_rf_write(struct rt2x00_dev *rt2x00dev, 203static void rt73usb_rf_write(struct rt2x00_dev *rt2x00dev,