aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorIvo van Doorn <ivdoorn@gmail.com>2008-02-03 09:54:11 -0500
committerJohn W. Linville <linville@tuxdriver.com>2008-02-29 15:37:00 -0500
commit3b640f21af4b6b36b546fecbd3fe5109981360da (patch)
tree5fce049b149283f8864d60b5b265a12b08827b3f /drivers
parenta9450b70a755abf093600035ef5361c53343fe9a (diff)
rt2x00: Enable LED class support for rt2500usb/rt73usb
Add kerneldoc for vendor request functions in rt2x00usb. Add asynchroneous vendor request function in rt2x00usb. With the availability of the asynchroneuous vendor request we can now enable LED class support for rt2500usb and rt73usb. Since LED handling is not important, it doesn't really matter if a register call fails (This solution is better then no LED class support at all). 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/Kconfig14
-rw-r--r--drivers/net/wireless/rt2x00/rt2500usb.c20
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00leds.c217
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00leds.h63
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00usb.c52
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00usb.h129
-rw-r--r--drivers/net/wireless/rt2x00/rt73usb.c21
7 files changed, 463 insertions, 53 deletions
diff --git a/drivers/net/wireless/rt2x00/Kconfig b/drivers/net/wireless/rt2x00/Kconfig
index 88a6ef693862..51adb2f37c55 100644
--- a/drivers/net/wireless/rt2x00/Kconfig
+++ b/drivers/net/wireless/rt2x00/Kconfig
@@ -133,6 +133,13 @@ config RT2500USB
133 133
134 When compiled as a module, this driver will be called "rt2500usb.ko". 134 When compiled as a module, this driver will be called "rt2500usb.ko".
135 135
136config RT2500USB_LEDS
137 bool "RT2500 leds support"
138 depends on RT2500USB
139 select RT2X00_LIB_LEDS
140 ---help---
141 This adds support for led triggers provided my mac80211.
142
136config RT73USB 143config RT73USB
137 tristate "Ralink rt73 usb support" 144 tristate "Ralink rt73 usb support"
138 depends on RT2X00 && USB 145 depends on RT2X00 && USB
@@ -143,6 +150,13 @@ config RT73USB
143 150
144 When compiled as a module, this driver will be called "rt73usb.ko". 151 When compiled as a module, this driver will be called "rt73usb.ko".
145 152
153config RT73USB_LEDS
154 bool "RT73 leds support"
155 depends on RT73USB
156 select RT2X00_LIB_LEDS
157 ---help---
158 This adds support for led triggers provided my mac80211.
159
146config RT2X00_LIB_DEBUGFS 160config RT2X00_LIB_DEBUGFS
147 bool "Ralink debugfs support" 161 bool "Ralink debugfs support"
148 depends on RT2X00_LIB && MAC80211_DEBUGFS 162 depends on RT2X00_LIB && MAC80211_DEBUGFS
diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c
index 6352ebe8cb43..a64b62b20051 100644
--- a/drivers/net/wireless/rt2x00/rt2500usb.c
+++ b/drivers/net/wireless/rt2x00/rt2500usb.c
@@ -291,17 +291,16 @@ static void rt2500usb_led_brightness(struct led_classdev *led_cdev,
291 unsigned int enabled = brightness != LED_OFF; 291 unsigned int enabled = brightness != LED_OFF;
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 u16 reg;
295
296 rt2500usb_register_read(led->rt2x00dev, MAC_CSR20, &reg);
297 294
298 if (led->type == LED_TYPE_RADIO || led->type == LED_TYPE_ASSOC) { 295 if (led->type == LED_TYPE_RADIO || led->type == LED_TYPE_ASSOC) {
299 rt2x00_set_field16(&reg, MAC_CSR20_LINK, enabled); 296 rt2x00_set_field16(&led->rt2x00dev->led_mcu_reg,
300 rt2x00_set_field16(&reg, MAC_CSR20_ACTIVITY, 297 MAC_CSR20_LINK, enabled);
301 enabled && activity); 298 rt2x00_set_field16(&led->rt2x00dev->led_mcu_reg,
299 MAC_CSR20_ACTIVITY, enabled && activity);
302 } 300 }
303 301
304 rt2500usb_register_write(led->rt2x00dev, MAC_CSR20, reg); 302 rt2x00usb_vendor_request_async(led->rt2x00dev, USB_SINGLE_WRITE,
303 MAC_CSR20, led->rt2x00dev->led_mcu_reg);
305} 304}
306#else 305#else
307#define rt2500usb_led_brightness NULL 306#define rt2500usb_led_brightness NULL
@@ -1377,6 +1376,13 @@ static int rt2500usb_init_eeprom(struct rt2x00_dev *rt2x00dev)
1377 rt2x00dev->led_flags = LED_SUPPORT_RADIO; 1376 rt2x00dev->led_flags = LED_SUPPORT_RADIO;
1378 break; 1377 break;
1379 } 1378 }
1379
1380 /*
1381 * Store the current led register value, we need it later
1382 * in set_brightness but that is called in irq context which
1383 * means we can't use rt2500usb_register_read() at that time.
1384 */
1385 rt2500usb_register_read(rt2x00dev, MAC_CSR20, &rt2x00dev->led_mcu_reg);
1380#endif /* CONFIG_RT2500USB_LEDS */ 1386#endif /* CONFIG_RT2500USB_LEDS */
1381 1387
1382 /* 1388 /*
diff --git a/drivers/net/wireless/rt2x00/rt2x00leds.c b/drivers/net/wireless/rt2x00/rt2x00leds.c
new file mode 100644
index 000000000000..9c29d17e0cc2
--- /dev/null
+++ b/drivers/net/wireless/rt2x00/rt2x00leds.c
@@ -0,0 +1,217 @@
1/*
2 Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
3 <http://rt2x00.serialmonkey.com>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the
17 Free Software Foundation, Inc.,
18 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 */
20
21/*
22 Module: rt2x00lib
23 Abstract: rt2x00 led specific routines.
24 */
25
26#include <linux/kernel.h>
27#include <linux/module.h>
28
29#include "rt2x00.h"
30#include "rt2x00lib.h"
31
32void rt2x00leds_led_quality(struct rt2x00_dev *rt2x00dev, int rssi)
33{
34 if (!rt2x00dev->trigger_qual.registered)
35 return;
36
37 /*
38 * Led handling requires a positive value for the rssi,
39 * to do that correctly we need to add the correction.
40 */
41 rssi += rt2x00dev->rssi_offset;
42
43 /*
44 * Get the rssi level, this is used to convert the rssi
45 * to a LED value inside the range LED_OFF - LED_FULL.
46 */
47 if (rssi <= 30)
48 rssi = 0;
49 else if (rssi <= 39)
50 rssi = 1;
51 else if (rssi <= 49)
52 rssi = 2;
53 else if (rssi <= 53)
54 rssi = 3;
55 else if (rssi <= 63)
56 rssi = 4;
57 else
58 rssi = 5;
59
60 /*
61 * Note that we must _not_ send LED_OFF since the driver
62 * is going to calculate the value and might use it in a
63 * division.
64 */
65 led_trigger_event(&rt2x00dev->trigger_qual.trigger,
66 ((LED_FULL / 6) * rssi) + 1);
67}
68
69static int rt2x00leds_register_trigger(struct rt2x00_dev *rt2x00dev,
70 struct rt2x00_trigger *trigger,
71 const char *name)
72{
73 int retval;
74
75 trigger->trigger.name = name;
76 retval = led_trigger_register(&trigger->trigger);
77 if (retval) {
78 ERROR(rt2x00dev, "Failed to register led trigger.\n");
79 return retval;
80 }
81
82 trigger->registered = 1;
83
84 return 0;
85}
86
87static int rt2x00leds_register_led(struct rt2x00_dev *rt2x00dev,
88 struct rt2x00_led *led,
89 enum led_type type,
90 const char *name, char *trigger)
91{
92 struct device *device = wiphy_dev(rt2x00dev->hw->wiphy);
93 int retval;
94
95 led->led_dev.name = name;
96 led->led_dev.brightness_set = rt2x00dev->ops->lib->led_brightness;
97 led->led_dev.default_trigger = trigger;
98
99 retval = led_classdev_register(device, &led->led_dev);
100 if (retval) {
101 ERROR(rt2x00dev, "Failed to register led handler.\n");
102 return retval;
103 }
104
105 led->rt2x00dev = rt2x00dev;
106 led->type = type;
107 led->registered = 1;
108
109 return 0;
110}
111
112int rt2x00leds_register(struct rt2x00_dev *rt2x00dev)
113{
114 char *trigger;
115 char dev_name[16];
116 char name[32];
117 int retval;
118
119 if (!rt2x00dev->ops->lib->led_brightness)
120 return 0;
121
122 snprintf(dev_name, sizeof(dev_name), "%s-%s",
123 rt2x00dev->ops->name, wiphy_name(rt2x00dev->hw->wiphy));
124
125 if (rt2x00dev->led_flags & LED_SUPPORT_RADIO) {
126 trigger = ieee80211_get_radio_led_name(rt2x00dev->hw);
127 snprintf(name, sizeof(name), "%s:radio", dev_name);
128
129 retval = rt2x00leds_register_led(rt2x00dev,
130 &rt2x00dev->led_radio,
131 LED_TYPE_RADIO,
132 name, trigger);
133 if (retval)
134 goto exit_fail;
135 }
136
137 if (rt2x00dev->led_flags & LED_SUPPORT_ASSOC) {
138 trigger = ieee80211_get_assoc_led_name(rt2x00dev->hw);
139 snprintf(name, sizeof(name), "%s:assoc", dev_name);
140
141 retval = rt2x00leds_register_led(rt2x00dev,
142 &rt2x00dev->led_assoc,
143 LED_TYPE_ASSOC,
144 name, trigger);
145 if (retval)
146 goto exit_fail;
147 }
148
149 if (rt2x00dev->led_flags & LED_SUPPORT_QUALITY) {
150 snprintf(name, sizeof(name), "%s:quality", dev_name);
151
152 retval = rt2x00leds_register_trigger(rt2x00dev,
153 &rt2x00dev->trigger_qual,
154 name);
155
156 retval = rt2x00leds_register_led(rt2x00dev,
157 &rt2x00dev->led_qual,
158 LED_TYPE_QUALITY,
159 name, name);
160 if (retval)
161 goto exit_fail;
162 }
163
164 return 0;
165
166exit_fail:
167 rt2x00leds_unregister(rt2x00dev);
168 return retval;
169}
170
171static void rt2x00leds_unregister_trigger(struct rt2x00_trigger *trigger)
172{
173 if (!trigger->registered)
174 return;
175
176 led_trigger_unregister(&trigger->trigger);
177 trigger->registered = 0;
178}
179
180static void rt2x00leds_unregister_led(struct rt2x00_led *led)
181{
182 if (!led->registered)
183 return;
184
185 led_classdev_unregister(&led->led_dev);
186
187 led->led_dev.brightness_set(&led->led_dev, LED_OFF);
188 led->registered = 0;
189}
190
191void rt2x00leds_unregister(struct rt2x00_dev *rt2x00dev)
192{
193 rt2x00leds_unregister_trigger(&rt2x00dev->trigger_qual);
194 rt2x00leds_unregister_led(&rt2x00dev->led_qual);
195 rt2x00leds_unregister_led(&rt2x00dev->led_assoc);
196 rt2x00leds_unregister_led(&rt2x00dev->led_radio);
197}
198
199void rt2x00leds_suspend(struct rt2x00_dev *rt2x00dev)
200{
201 if (rt2x00dev->led_qual.registered)
202 led_classdev_suspend(&rt2x00dev->led_qual.led_dev);
203 if (rt2x00dev->led_assoc.registered)
204 led_classdev_suspend(&rt2x00dev->led_assoc.led_dev);
205 if (rt2x00dev->led_radio.registered)
206 led_classdev_suspend(&rt2x00dev->led_radio.led_dev);
207}
208
209void rt2x00leds_resume(struct rt2x00_dev *rt2x00dev)
210{
211 if (rt2x00dev->led_radio.registered)
212 led_classdev_resume(&rt2x00dev->led_radio.led_dev);
213 if (rt2x00dev->led_assoc.registered)
214 led_classdev_resume(&rt2x00dev->led_assoc.led_dev);
215 if (rt2x00dev->led_qual.registered)
216 led_classdev_resume(&rt2x00dev->led_qual.led_dev);
217}
diff --git a/drivers/net/wireless/rt2x00/rt2x00leds.h b/drivers/net/wireless/rt2x00/rt2x00leds.h
new file mode 100644
index 000000000000..11e71e9ce853
--- /dev/null
+++ b/drivers/net/wireless/rt2x00/rt2x00leds.h
@@ -0,0 +1,63 @@
1/*
2 Copyright (C) 2004 - 2008 rt2x00 SourceForge Project
3 <http://rt2x00.serialmonkey.com>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the
17 Free Software Foundation, Inc.,
18 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 */
20
21/*
22 Module: rt2x00lib
23 Abstract: rt2x00 led datastructures and routines
24 */
25
26#ifndef RT2X00LEDS_H
27#define RT2X00LEDS_H
28
29/*
30* Flags used by driver to indicate which
31 * which led types are supported.
32 */
33#define LED_SUPPORT_RADIO 0x000001
34#define LED_SUPPORT_ASSOC 0x000002
35#define LED_SUPPORT_ACTIVITY 0x000004
36#define LED_SUPPORT_QUALITY 0x000008
37
38enum led_type {
39 LED_TYPE_RADIO,
40 LED_TYPE_ASSOC,
41 LED_TYPE_QUALITY,
42};
43
44#ifdef CONFIG_RT2X00_LIB_LEDS
45
46struct rt2x00_led {
47 struct rt2x00_dev *rt2x00dev;
48 struct led_classdev led_dev;
49
50 enum led_type type;
51 unsigned int registered;
52};
53
54struct rt2x00_trigger {
55 struct led_trigger trigger;
56
57 enum led_type type;
58 unsigned int registered;
59};
60
61#endif /* CONFIG_RT2X00_LIB_LEDS */
62
63#endif /* RT2X00LEDS_H */
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c
index fc606448908e..44ab2167c6ee 100644
--- a/drivers/net/wireless/rt2x00/rt2x00usb.c
+++ b/drivers/net/wireless/rt2x00/rt2x00usb.c
@@ -122,6 +122,58 @@ int rt2x00usb_vendor_request_buff(struct rt2x00_dev *rt2x00dev,
122} 122}
123EXPORT_SYMBOL_GPL(rt2x00usb_vendor_request_buff); 123EXPORT_SYMBOL_GPL(rt2x00usb_vendor_request_buff);
124 124
125static 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
134int 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
169exit:
170 usb_put_urb(urb);
171 kfree(ctrl);
172
173 return status;
174}
175EXPORT_SYMBOL_GPL(rt2x00usb_vendor_request_async);
176
125/* 177/*
126 * TX data handlers. 178 * TX data handlers.
127 */ 179 */
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.h b/drivers/net/wireless/rt2x00/rt2x00usb.h
index af606638e227..275b089a2a4d 100644
--- a/drivers/net/wireless/rt2x00/rt2x00usb.h
+++ b/drivers/net/wireless/rt2x00/rt2x00usb.h
@@ -60,34 +60,47 @@
60#define USB_VENDOR_REQUEST_IN ( USB_DIR_IN | USB_VENDOR_REQUEST ) 60#define USB_VENDOR_REQUEST_IN ( USB_DIR_IN | USB_VENDOR_REQUEST )
61#define USB_VENDOR_REQUEST_OUT ( USB_DIR_OUT | USB_VENDOR_REQUEST ) 61#define USB_VENDOR_REQUEST_OUT ( USB_DIR_OUT | USB_VENDOR_REQUEST )
62 62
63/* 63/**
64 * USB vendor commands. 64 * enum rt2x00usb_vendor_request: USB vendor commands.
65 */ 65 */
66#define USB_DEVICE_MODE 0x01 66enum rt2x00usb_vendor_request {
67#define USB_SINGLE_WRITE 0x02 67 USB_DEVICE_MODE = 1,
68#define USB_SINGLE_READ 0x03 68 USB_SINGLE_WRITE = 2,
69#define USB_MULTI_WRITE 0x06 69 USB_SINGLE_READ = 3,
70#define USB_MULTI_READ 0x07 70 USB_MULTI_WRITE = 6,
71#define USB_EEPROM_WRITE 0x08 71 USB_MULTI_READ = 7,
72#define USB_EEPROM_READ 0x09 72 USB_EEPROM_WRITE = 8,
73#define USB_LED_CONTROL 0x0a /* RT73USB */ 73 USB_EEPROM_READ = 9,
74#define USB_RX_CONTROL 0x0c 74 USB_LED_CONTROL = 10, /* RT73USB */
75 USB_RX_CONTROL = 12,
76};
75 77
76/* 78/**
77 * Device modes offset 79 * enum rt2x00usb_mode_offset: Device modes offset.
78 */ 80 */
79#define USB_MODE_RESET 0x01 81enum rt2x00usb_mode_offset {
80#define USB_MODE_UNPLUG 0x02 82 USB_MODE_RESET = 1,
81#define USB_MODE_FUNCTION 0x03 83 USB_MODE_UNPLUG = 2,
82#define USB_MODE_TEST 0x04 84 USB_MODE_FUNCTION = 3,
83#define USB_MODE_SLEEP 0x07 /* RT73USB */ 85 USB_MODE_TEST = 4,
84#define USB_MODE_FIRMWARE 0x08 /* RT73USB */ 86 USB_MODE_SLEEP = 7, /* RT73USB */
85#define USB_MODE_WAKEUP 0x09 /* RT73USB */ 87 USB_MODE_FIRMWARE = 8, /* RT73USB */
88 USB_MODE_WAKEUP = 9, /* RT73USB */
89};
86 90
87/* 91/**
88 * Used to read/write from/to the device. 92 * rt2x00usb_vendor_request - Send register command to device
93 * @rt2x00dev: Pointer to &struct rt2x00_dev
94 * @request: USB vendor command (See &enum rt2x00usb_vendor_request)
95 * @requesttype: Request type &USB_VENDOR_REQUEST_*
96 * @offset: Register offset to perform action on
97 * @value: Value to write to device
98 * @buffer: Buffer where information will be read/written to by device
99 * @buffer_length: Size of &buffer
100 * @timeout: Operation timeout
101 *
89 * This is the main function to communicate with the device, 102 * This is the main function to communicate with the device,
90 * the buffer argument _must_ either be NULL or point to 103 * the &buffer argument _must_ either be NULL or point to
91 * a buffer allocated by kmalloc. Failure to do so can lead 104 * a buffer allocated by kmalloc. Failure to do so can lead
92 * to unexpected behavior depending on the architecture. 105 * to unexpected behavior depending on the architecture.
93 */ 106 */
@@ -97,13 +110,21 @@ int rt2x00usb_vendor_request(struct rt2x00_dev *rt2x00dev,
97 void *buffer, const u16 buffer_length, 110 void *buffer, const u16 buffer_length,
98 const int timeout); 111 const int timeout);
99 112
100/* 113/**
101 * Used to read/write from/to the device. 114 * rt2x00usb_vendor_request_buff - Send register command to device (buffered)
115 * @rt2x00dev: Pointer to &struct rt2x00_dev
116 * @request: USB vendor command (See &enum rt2x00usb_vendor_request)
117 * @requesttype: Request type &USB_VENDOR_REQUEST_*
118 * @offset: Register offset to perform action on
119 * @buffer: Buffer where information will be read/written to by device
120 * @buffer_length: Size of &buffer
121 * @timeout: Operation timeout
122 *
102 * This function will use a previously with kmalloc allocated cache 123 * This function will use a previously with kmalloc allocated cache
103 * to communicate with the device. The contents of the buffer pointer 124 * to communicate with the device. The contents of the buffer pointer
104 * will be copied to this cache when writing, or read from the cache 125 * will be copied to this cache when writing, or read from the cache
105 * when reading. 126 * when reading.
106 * Buffers send to rt2x00usb_vendor_request _must_ be allocated with 127 * Buffers send to &rt2x00usb_vendor_request _must_ be allocated with
107 * kmalloc. Hence the reason for using a previously allocated cache 128 * kmalloc. Hence the reason for using a previously allocated cache
108 * which has been allocated properly. 129 * which has been allocated properly.
109 */ 130 */
@@ -112,15 +133,32 @@ int rt2x00usb_vendor_request_buff(struct rt2x00_dev *rt2x00dev,
112 const u16 offset, void *buffer, 133 const u16 offset, void *buffer,
113 const u16 buffer_length, const int timeout); 134 const u16 buffer_length, const int timeout);
114 135
115/* 136/**
116 * A version of rt2x00usb_vendor_request_buff which must be called 137 * rt2x00usb_vendor_request_buff - Send register command to device (buffered)
117 * if the usb_cache_mutex is already held. */ 138 * @rt2x00dev: Pointer to &struct rt2x00_dev
139 * @request: USB vendor command (See &enum rt2x00usb_vendor_request)
140 * @requesttype: Request type &USB_VENDOR_REQUEST_*
141 * @offset: Register offset to perform action on
142 * @buffer: Buffer where information will be read/written to by device
143 * @buffer_length: Size of &buffer
144 * @timeout: Operation timeout
145 *
146 * A version of &rt2x00usb_vendor_request_buff which must be called
147 * if the usb_cache_mutex is already held.
148 */
118int rt2x00usb_vendor_req_buff_lock(struct rt2x00_dev *rt2x00dev, 149int rt2x00usb_vendor_req_buff_lock(struct rt2x00_dev *rt2x00dev,
119 const u8 request, const u8 requesttype, 150 const u8 request, const u8 requesttype,
120 const u16 offset, void *buffer, 151 const u16 offset, void *buffer,
121 const u16 buffer_length, const int timeout); 152 const u16 buffer_length, const int timeout);
122 153
123/* 154/**
155 * rt2x00usb_vendor_request_sw - Send single register command to device
156 * @rt2x00dev: Pointer to &struct rt2x00_dev
157 * @request: USB vendor command (See &enum rt2x00usb_vendor_request)
158 * @offset: Register offset to perform action on
159 * @value: Value to write to device
160 * @timeout: Operation timeout
161 *
124 * Simple wrapper around rt2x00usb_vendor_request to write a single 162 * Simple wrapper around rt2x00usb_vendor_request to write a single
125 * command to the device. Since we don't use the buffer argument we 163 * command to the device. Since we don't use the buffer argument we
126 * don't have to worry about kmalloc here. 164 * don't have to worry about kmalloc here.
@@ -136,7 +174,12 @@ static inline int rt2x00usb_vendor_request_sw(struct rt2x00_dev *rt2x00dev,
136 value, NULL, 0, timeout); 174 value, NULL, 0, timeout);
137} 175}
138 176
139/* 177/**
178 * rt2x00usb_eeprom_read - Read eeprom from device
179 * @rt2x00dev: Pointer to &struct rt2x00_dev
180 * @eeprom: Pointer to eeprom array to store the information in
181 * @length: Number of bytes to read from the eeprom
182 *
140 * Simple wrapper around rt2x00usb_vendor_request to read the eeprom 183 * Simple wrapper around rt2x00usb_vendor_request to read the eeprom
141 * from the device. Note that the eeprom argument _must_ be allocated using 184 * from the device. Note that the eeprom argument _must_ be allocated using
142 * kmalloc for correct handling inside the kernel USB layer. 185 * kmalloc for correct handling inside the kernel USB layer.
@@ -147,10 +190,28 @@ static inline int rt2x00usb_eeprom_read(struct rt2x00_dev *rt2x00dev,
147 int timeout = REGISTER_TIMEOUT * (lenght / sizeof(u16)); 190 int timeout = REGISTER_TIMEOUT * (lenght / sizeof(u16));
148 191
149 return rt2x00usb_vendor_request(rt2x00dev, USB_EEPROM_READ, 192 return rt2x00usb_vendor_request(rt2x00dev, USB_EEPROM_READ,
150 USB_VENDOR_REQUEST_IN, 0x0000, 193 USB_VENDOR_REQUEST_IN, 0, 0,
151 0x0000, eeprom, lenght, timeout); 194 eeprom, lenght, timeout);
152} 195}
153 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 */
211int rt2x00usb_vendor_request_async(struct rt2x00_dev *rt2x00dev,
212 const u8 request, const u16 offset,
213 const u16 value);
214
154/* 215/*
155 * Radio handlers 216 * Radio handlers
156 */ 217 */
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c
index ca5a9855adbd..92c8f601296f 100644
--- a/drivers/net/wireless/rt2x00/rt73usb.c
+++ b/drivers/net/wireless/rt2x00/rt73usb.c
@@ -294,28 +294,25 @@ static void rt73usb_led_brightness(struct led_classdev *led_cdev,
294 rt2x00_set_field16(&led->rt2x00dev->led_mcu_reg, 294 rt2x00_set_field16(&led->rt2x00dev->led_mcu_reg,
295 MCU_LEDCS_RADIO_STATUS, enabled); 295 MCU_LEDCS_RADIO_STATUS, enabled);
296 296
297 rt2x00usb_vendor_request_sw(led->rt2x00dev, USB_LED_CONTROL, 0, 297 rt2x00usb_vendor_request_async(led->rt2x00dev, USB_LED_CONTROL,
298 led->rt2x00dev->led_mcu_reg, 298 0, led->rt2x00dev->led_mcu_reg);
299 REGISTER_TIMEOUT);
300 } else if (led->type == LED_TYPE_ASSOC) { 299 } else if (led->type == LED_TYPE_ASSOC) {
301 rt2x00_set_field16(&led->rt2x00dev->led_mcu_reg, 300 rt2x00_set_field16(&led->rt2x00dev->led_mcu_reg,
302 MCU_LEDCS_LINK_BG_STATUS, bg_mode); 301 MCU_LEDCS_LINK_BG_STATUS, bg_mode);
303 rt2x00_set_field16(&led->rt2x00dev->led_mcu_reg, 302 rt2x00_set_field16(&led->rt2x00dev->led_mcu_reg,
304 MCU_LEDCS_LINK_A_STATUS, a_mode); 303 MCU_LEDCS_LINK_A_STATUS, a_mode);
305 304
306 rt2x00usb_vendor_request_sw(led->rt2x00dev, USB_LED_CONTROL, 0, 305 rt2x00usb_vendor_request_async(led->rt2x00dev, USB_LED_CONTROL,
307 led->rt2x00dev->led_mcu_reg, 306 0, led->rt2x00dev->led_mcu_reg);
308 REGISTER_TIMEOUT);
309 } else if (led->type == LED_TYPE_QUALITY) { 307 } else if (led->type == LED_TYPE_QUALITY) {
310 /* 308 /*
311 * The brightness is divided into 6 levels (0 - 5), 309 * The brightness is divided into 6 levels (0 - 5),
312 * this means we need to convert the brightness 310 * this means we need to convert the brightness
313 * argument into the matching level within that range. 311 * argument into the matching level within that range.
314 */ 312 */
315 rt2x00usb_vendor_request_sw(led->rt2x00dev, USB_LED_CONTROL, 313 rt2x00usb_vendor_request_async(led->rt2x00dev, USB_LED_CONTROL,
316 brightness / (LED_FULL / 6), 314 brightness / (LED_FULL / 6),
317 led->rt2x00dev->led_mcu_reg, 315 led->rt2x00dev->led_mcu_reg);
318 REGISTER_TIMEOUT);
319 } 316 }
320} 317}
321#else 318#else
@@ -871,7 +868,7 @@ static int rt73usb_load_firmware(struct rt2x00_dev *rt2x00dev, void *data,
871 868
872 rt2x00usb_vendor_request(rt2x00dev, USB_MULTI_WRITE, 869 rt2x00usb_vendor_request(rt2x00dev, USB_MULTI_WRITE,
873 USB_VENDOR_REQUEST_OUT, 870 USB_VENDOR_REQUEST_OUT,
874 FIRMWARE_IMAGE_BASE + i, 0x0000, 871 FIRMWARE_IMAGE_BASE + i, 0,
875 cache, buflen, timeout); 872 cache, buflen, timeout);
876 873
877 ptr += buflen; 874 ptr += buflen;
@@ -884,7 +881,7 @@ static int rt73usb_load_firmware(struct rt2x00_dev *rt2x00dev, void *data,
884 * we need to specify a long timeout time. 881 * we need to specify a long timeout time.
885 */ 882 */
886 status = rt2x00usb_vendor_request_sw(rt2x00dev, USB_DEVICE_MODE, 883 status = rt2x00usb_vendor_request_sw(rt2x00dev, USB_DEVICE_MODE,
887 0x0000, USB_MODE_FIRMWARE, 884 0, USB_MODE_FIRMWARE,
888 REGISTER_TIMEOUT_FIRMWARE); 885 REGISTER_TIMEOUT_FIRMWARE);
889 if (status < 0) { 886 if (status < 0) {
890 ERROR(rt2x00dev, "Failed to write Firmware to device.\n"); 887 ERROR(rt2x00dev, "Failed to write Firmware to device.\n");