diff options
Diffstat (limited to 'drivers/net/wireless/rt2x00')
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2500usb.c | 36 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00.h | 1 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00dev.c | 38 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00mac.c | 4 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt73usb.c | 36 |
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 | |||
158 | exit_fail: | ||
159 | mutex_unlock(&rt2x00dev->usb_cache_mutex); | ||
160 | |||
161 | ERROR(rt2x00dev, "PHY_CSR8 register busy. Write failed.\n"); | ||
158 | } | 162 | } |
159 | 163 | ||
160 | static void rt2500usb_bbp_read(struct rt2x00_dev *rt2x00dev, | 164 | static 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, ®); | 194 | rt2500usb_register_read_lock(rt2x00dev, PHY_CSR7, ®); |
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 | |||
201 | exit_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 | ||
202 | static void rt2500usb_rf_write(struct rt2x00_dev *rt2x00dev, | 208 | static 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 | ||
405 | static void rt2x00lib_packetfilter_scheduled(struct work_struct *work) | 397 | static 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 | } |
492 | EXPORT_SYMBOL_GPL(rt2x00lib_beacondone); | 493 | EXPORT_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 | } |
433 | EXPORT_SYMBOL_GPL(rt2x00mac_configure_filter); | 433 | EXPORT_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 | |||
154 | exit_fail: | ||
155 | mutex_unlock(&rt2x00dev->usb_cache_mutex); | ||
156 | |||
157 | ERROR(rt2x00dev, "PHY_CSR3 register busy. Write failed.\n"); | ||
154 | } | 158 | } |
155 | 159 | ||
156 | static void rt73usb_bbp_read(struct rt2x00_dev *rt2x00dev, | 160 | static 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 | |||
196 | exit_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 | ||
197 | static void rt73usb_rf_write(struct rt2x00_dev *rt2x00dev, | 203 | static void rt73usb_rf_write(struct rt2x00_dev *rt2x00dev, |