diff options
author | Ivo van Doorn <ivdoorn@gmail.com> | 2008-02-17 11:35:28 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2008-02-29 15:37:24 -0500 |
commit | 47b10cd1375855dbc6675a176c71a512ac4b7317 (patch) | |
tree | a86ed1c88ea00371935f1ac3cd684d49b561bba2 /drivers | |
parent | 31562e802a72caf0757f351fff563d558d48d087 (diff) |
rt2x00: Remove async vendor request calls from rt2x00usb
The async vendor requests are a ugly hack which is not working correctly.
The proper fix for the scheduling while atomic issue is finding out why
we can't use led classes for USB drivers and fix that.
Just replace all async calls with the regular ones and print an
error for the disallowed LED configuration attempts. That will
help in determining which led class is causing the problem.
Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2500usb.c | 10 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00usb.c | 52 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00usb.h | 18 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt73usb.c | 23 |
4 files changed, 24 insertions, 79 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index 826ed692878c..9f59db91cfc2 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c | |||
@@ -292,6 +292,12 @@ static void rt2500usb_led_brightness(struct led_classdev *led_cdev, | |||
292 | unsigned int activity = | 292 | unsigned int activity = |
293 | led->rt2x00dev->led_flags & LED_SUPPORT_ACTIVITY; | 293 | led->rt2x00dev->led_flags & LED_SUPPORT_ACTIVITY; |
294 | 294 | ||
295 | if (in_atomic()) { | ||
296 | NOTICE(led->rt2x00dev, | ||
297 | "Ignoring LED brightness command for led %d", led->type); | ||
298 | return; | ||
299 | } | ||
300 | |||
295 | if (led->type == LED_TYPE_RADIO || led->type == LED_TYPE_ASSOC) { | 301 | if (led->type == LED_TYPE_RADIO || led->type == LED_TYPE_ASSOC) { |
296 | rt2x00_set_field16(&led->rt2x00dev->led_mcu_reg, | 302 | rt2x00_set_field16(&led->rt2x00dev->led_mcu_reg, |
297 | MAC_CSR20_LINK, enabled); | 303 | MAC_CSR20_LINK, enabled); |
@@ -299,8 +305,8 @@ static void rt2500usb_led_brightness(struct led_classdev *led_cdev, | |||
299 | MAC_CSR20_ACTIVITY, enabled && activity); | 305 | MAC_CSR20_ACTIVITY, enabled && activity); |
300 | } | 306 | } |
301 | 307 | ||
302 | rt2x00usb_vendor_request_async(led->rt2x00dev, USB_SINGLE_WRITE, | 308 | rt2500usb_register_write(led->rt2x00dev, MAC_CSR20, |
303 | MAC_CSR20, led->rt2x00dev->led_mcu_reg); | 309 | led->rt2x00dev->led_mcu_reg); |
304 | } | 310 | } |
305 | #else | 311 | #else |
306 | #define rt2500usb_led_brightness NULL | 312 | #define rt2500usb_led_brightness NULL |
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c index 89471b24a443..063b167da31e 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.c +++ b/drivers/net/wireless/rt2x00/rt2x00usb.c | |||
@@ -122,58 +122,6 @@ int rt2x00usb_vendor_request_buff(struct rt2x00_dev *rt2x00dev, | |||
122 | } | 122 | } |
123 | EXPORT_SYMBOL_GPL(rt2x00usb_vendor_request_buff); | 123 | EXPORT_SYMBOL_GPL(rt2x00usb_vendor_request_buff); |
124 | 124 | ||
125 | static void rt2x00usb_vendor_request_async_complete(struct urb *urb) | ||
126 | { | ||
127 | /* | ||
128 | * We're done with it, descrease usage count and let the | ||
129 | * usb layer delete it as soon as it is done with it. | ||
130 | */ | ||
131 | usb_put_urb(urb); | ||
132 | } | ||
133 | |||
134 | int rt2x00usb_vendor_request_async(struct rt2x00_dev *rt2x00dev, | ||
135 | const u8 request, const u16 offset, | ||
136 | const u16 value) | ||
137 | { | ||
138 | struct usb_device *usb_dev = rt2x00dev_usb_dev(rt2x00dev); | ||
139 | struct usb_ctrlrequest *ctrl; | ||
140 | struct urb *urb; | ||
141 | int status; | ||
142 | |||
143 | urb = usb_alloc_urb(0, GFP_NOIO); | ||
144 | if (!urb) | ||
145 | return -ENOMEM; | ||
146 | |||
147 | ctrl = kmalloc(sizeof(struct usb_ctrlrequest), GFP_NOIO); | ||
148 | if (!ctrl) { | ||
149 | status = -ENOMEM; | ||
150 | goto exit; | ||
151 | } | ||
152 | |||
153 | ctrl->bRequestType= USB_VENDOR_REQUEST_OUT; | ||
154 | ctrl->bRequest = request; | ||
155 | ctrl->wValue = cpu_to_le16p(&value); | ||
156 | ctrl->wIndex = cpu_to_le16p(&offset); | ||
157 | ctrl->wLength = 0; | ||
158 | |||
159 | usb_fill_control_urb(urb, usb_dev, usb_sndctrlpipe(usb_dev, 0), | ||
160 | (unsigned char *)ctrl, NULL, 0, | ||
161 | rt2x00usb_vendor_request_async_complete, NULL); | ||
162 | |||
163 | status = usb_submit_urb(urb, GFP_ATOMIC); | ||
164 | if (!status) | ||
165 | goto exit; | ||
166 | |||
167 | return 0; | ||
168 | |||
169 | exit: | ||
170 | usb_put_urb(urb); | ||
171 | kfree(ctrl); | ||
172 | |||
173 | return status; | ||
174 | } | ||
175 | EXPORT_SYMBOL_GPL(rt2x00usb_vendor_request_async); | ||
176 | |||
177 | /* | 125 | /* |
178 | * TX data handlers. | 126 | * TX data handlers. |
179 | */ | 127 | */ |
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.h b/drivers/net/wireless/rt2x00/rt2x00usb.h index 275b089a2a4d..11e55180cbaf 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.h +++ b/drivers/net/wireless/rt2x00/rt2x00usb.h | |||
@@ -194,24 +194,6 @@ static inline int rt2x00usb_eeprom_read(struct rt2x00_dev *rt2x00dev, | |||
194 | eeprom, lenght, timeout); | 194 | eeprom, lenght, timeout); |
195 | } | 195 | } |
196 | 196 | ||
197 | /** | ||
198 | * rt2x00usb_vendor_request_async - Send register command to device (async) | ||
199 | * @rt2x00dev: Pointer to &struct rt2x00_dev | ||
200 | * @request: USB vendor command (See &enum rt2x00usb_vendor_request) | ||
201 | * @offset: Register offset to perform action on | ||
202 | * @value: Value to write to device | ||
203 | * | ||
204 | * Asynchroneous version of &rt2x00usb_vendor_request this is required | ||
205 | * for some routines where the driver cannot sleep because it is in | ||
206 | * irq context. Note that with this function the driver will not be | ||
207 | * notified on failure or timeout of the command. It will only be notified | ||
208 | * if the start of the command succeeded or not. This means it should not be | ||
209 | * used when the command must succeed. | ||
210 | */ | ||
211 | int rt2x00usb_vendor_request_async(struct rt2x00_dev *rt2x00dev, | ||
212 | const u8 request, const u16 offset, | ||
213 | const u16 value); | ||
214 | |||
215 | /* | 197 | /* |
216 | * Radio handlers | 198 | * Radio handlers |
217 | */ | 199 | */ |
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index bf2391b89571..6546b0d607b9 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c | |||
@@ -290,29 +290,38 @@ static void rt73usb_led_brightness(struct led_classdev *led_cdev, | |||
290 | unsigned int bg_mode = | 290 | unsigned int bg_mode = |
291 | (enabled && led->rt2x00dev->curr_band == IEEE80211_BAND_2GHZ); | 291 | (enabled && led->rt2x00dev->curr_band == IEEE80211_BAND_2GHZ); |
292 | 292 | ||
293 | if (in_atomic()) { | ||
294 | NOTICE(led->rt2x00dev, | ||
295 | "Ignoring LED brightness command for led %d", led->type); | ||
296 | return; | ||
297 | } | ||
298 | |||
293 | if (led->type == LED_TYPE_RADIO) { | 299 | if (led->type == LED_TYPE_RADIO) { |
294 | rt2x00_set_field16(&led->rt2x00dev->led_mcu_reg, | 300 | rt2x00_set_field16(&led->rt2x00dev->led_mcu_reg, |
295 | MCU_LEDCS_RADIO_STATUS, enabled); | 301 | MCU_LEDCS_RADIO_STATUS, enabled); |
296 | 302 | ||
297 | rt2x00usb_vendor_request_async(led->rt2x00dev, USB_LED_CONTROL, | 303 | rt2x00usb_vendor_request_sw(led->rt2x00dev, USB_LED_CONTROL, |
298 | 0, led->rt2x00dev->led_mcu_reg); | 304 | 0, led->rt2x00dev->led_mcu_reg, |
305 | REGISTER_TIMEOUT); | ||
299 | } else if (led->type == LED_TYPE_ASSOC) { | 306 | } else if (led->type == LED_TYPE_ASSOC) { |
300 | rt2x00_set_field16(&led->rt2x00dev->led_mcu_reg, | 307 | rt2x00_set_field16(&led->rt2x00dev->led_mcu_reg, |
301 | MCU_LEDCS_LINK_BG_STATUS, bg_mode); | 308 | MCU_LEDCS_LINK_BG_STATUS, bg_mode); |
302 | rt2x00_set_field16(&led->rt2x00dev->led_mcu_reg, | 309 | rt2x00_set_field16(&led->rt2x00dev->led_mcu_reg, |
303 | MCU_LEDCS_LINK_A_STATUS, a_mode); | 310 | MCU_LEDCS_LINK_A_STATUS, a_mode); |
304 | 311 | ||
305 | rt2x00usb_vendor_request_async(led->rt2x00dev, USB_LED_CONTROL, | 312 | rt2x00usb_vendor_request_sw(led->rt2x00dev, USB_LED_CONTROL, |
306 | 0, led->rt2x00dev->led_mcu_reg); | 313 | 0, led->rt2x00dev->led_mcu_reg, |
314 | REGISTER_TIMEOUT); | ||
307 | } else if (led->type == LED_TYPE_QUALITY) { | 315 | } else if (led->type == LED_TYPE_QUALITY) { |
308 | /* | 316 | /* |
309 | * The brightness is divided into 6 levels (0 - 5), | 317 | * The brightness is divided into 6 levels (0 - 5), |
310 | * this means we need to convert the brightness | 318 | * this means we need to convert the brightness |
311 | * argument into the matching level within that range. | 319 | * argument into the matching level within that range. |
312 | */ | 320 | */ |
313 | rt2x00usb_vendor_request_async(led->rt2x00dev, USB_LED_CONTROL, | 321 | rt2x00usb_vendor_request_sw(led->rt2x00dev, USB_LED_CONTROL, |
314 | brightness / (LED_FULL / 6), | 322 | brightness / (LED_FULL / 6), |
315 | led->rt2x00dev->led_mcu_reg); | 323 | led->rt2x00dev->led_mcu_reg, |
324 | REGISTER_TIMEOUT); | ||
316 | } | 325 | } |
317 | } | 326 | } |
318 | #else | 327 | #else |