diff options
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r-- | drivers/net/wireless/rt2x00/Kconfig | 14 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2500usb.c | 20 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00leds.c | 217 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00leds.h | 63 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00usb.c | 52 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00usb.h | 129 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt73usb.c | 21 |
7 files changed, 463 insertions, 53 deletions
diff --git a/drivers/net/wireless/rt2x00/Kconfig b/drivers/net/wireless/rt2x00/Kconfig index 88a6ef69386..51adb2f37c5 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 | ||
136 | config 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 | |||
136 | config RT73USB | 143 | config 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 | ||
153 | config 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 | |||
146 | config RT2X00_LIB_DEBUGFS | 160 | config 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 6352ebe8cb4..a64b62b2005 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, ®); | ||
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(®, MAC_CSR20_LINK, enabled); | 296 | rt2x00_set_field16(&led->rt2x00dev->led_mcu_reg, |
300 | rt2x00_set_field16(®, 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 00000000000..9c29d17e0cc --- /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 | |||
32 | void 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 | |||
69 | static 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 | |||
87 | static 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 | |||
112 | int 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 | |||
166 | exit_fail: | ||
167 | rt2x00leds_unregister(rt2x00dev); | ||
168 | return retval; | ||
169 | } | ||
170 | |||
171 | static 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 | |||
180 | static 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 | |||
191 | void 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 | |||
199 | void 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 | |||
209 | void 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 00000000000..11e71e9ce85 --- /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 | |||
38 | enum led_type { | ||
39 | LED_TYPE_RADIO, | ||
40 | LED_TYPE_ASSOC, | ||
41 | LED_TYPE_QUALITY, | ||
42 | }; | ||
43 | |||
44 | #ifdef CONFIG_RT2X00_LIB_LEDS | ||
45 | |||
46 | struct 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 | |||
54 | struct 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 fc606448908..44ab2167c6e 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 | } |
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 | |||
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 af606638e22..275b089a2a4 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 | 66 | enum 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 | 81 | enum 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 | */ | ||
118 | int rt2x00usb_vendor_req_buff_lock(struct rt2x00_dev *rt2x00dev, | 149 | int 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 | */ | ||
211 | int 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 ca5a9855adb..92c8f601296 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"); |