aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorIvo van Doorn <ivdoorn@gmail.com>2008-11-01 19:37:09 -0400
committerJohn W. Linville <linville@tuxdriver.com>2008-11-21 11:06:05 -0500
commit9a95dba32735534bda59def40c747bf606fedf05 (patch)
treebf64ebc24d6a6d812853af5904c8200a0813c984 /drivers/net
parent3d8606a680529d41ad8985f36ecf83a7b393ecaf (diff)
rt2x00: Fix LED state handling
For every global LED state change (register/unregister, suspend/resume) we should force the LEDS to turn off. This makes sure that the LEDS will always be in a sane state after the state switch. Note that when unregister is called but the LED class wasn't resumed yet, we shouldn't change the LED state since we might not have access to the device (device was unplugged while suspended). Also remove the checks in the activity, assoc and radio LEDS which blocked calls to brightness_set() when the state hasn't changed. Some of those LEDS could be enabled by themselves when something happens in the hardware (e.g. firmware is loaded). We already did called rt2x00leds to switch the LED off, but those calls were blocked. Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00leds.c94
1 files changed, 56 insertions, 38 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2x00leds.c b/drivers/net/wireless/rt2x00/rt2x00leds.c
index b362a1cf3f8..66c61b1eca5 100644
--- a/drivers/net/wireless/rt2x00/rt2x00leds.c
+++ b/drivers/net/wireless/rt2x00/rt2x00leds.c
@@ -72,49 +72,33 @@ void rt2x00leds_led_quality(struct rt2x00_dev *rt2x00dev, int rssi)
72 } 72 }
73} 73}
74 74
75void rt2x00led_led_activity(struct rt2x00_dev *rt2x00dev, bool enabled) 75static void rt2x00led_led_simple(struct rt2x00_led *led, bool enabled)
76{ 76{
77 struct rt2x00_led *led = &rt2x00dev->led_qual; 77 unsigned int brightness = enabled ? LED_FULL : LED_OFF;
78 unsigned int brightness;
79 78
80 if ((led->type != LED_TYPE_ACTIVITY) || !(led->flags & LED_REGISTERED)) 79 if (!(led->flags & LED_REGISTERED))
81 return; 80 return;
82 81
83 brightness = enabled ? LED_FULL : LED_OFF; 82 led->led_dev.brightness_set(&led->led_dev, brightness);
84 if (brightness != led->led_dev.brightness) { 83 led->led_dev.brightness = brightness;
85 led->led_dev.brightness_set(&led->led_dev, brightness);
86 led->led_dev.brightness = brightness;
87 }
88} 84}
89 85
90void rt2x00leds_led_assoc(struct rt2x00_dev *rt2x00dev, bool enabled) 86void rt2x00led_led_activity(struct rt2x00_dev *rt2x00dev, bool enabled)
91{ 87{
92 struct rt2x00_led *led = &rt2x00dev->led_assoc; 88 if (rt2x00dev->led_qual.type == LED_TYPE_ACTIVITY)
93 unsigned int brightness; 89 rt2x00led_led_simple(&rt2x00dev->led_qual, enabled);
94 90}
95 if ((led->type != LED_TYPE_ASSOC) || !(led->flags & LED_REGISTERED))
96 return;
97 91
98 brightness = enabled ? LED_FULL : LED_OFF; 92void rt2x00leds_led_assoc(struct rt2x00_dev *rt2x00dev, bool enabled)
99 if (brightness != led->led_dev.brightness) { 93{
100 led->led_dev.brightness_set(&led->led_dev, brightness); 94 if (rt2x00dev->led_assoc.type == LED_TYPE_ASSOC)
101 led->led_dev.brightness = brightness; 95 rt2x00led_led_simple(&rt2x00dev->led_assoc, enabled);
102 }
103} 96}
104 97
105void rt2x00leds_led_radio(struct rt2x00_dev *rt2x00dev, bool enabled) 98void rt2x00leds_led_radio(struct rt2x00_dev *rt2x00dev, bool enabled)
106{ 99{
107 struct rt2x00_led *led = &rt2x00dev->led_radio; 100 if (rt2x00dev->led_radio.type == LED_TYPE_ASSOC)
108 unsigned int brightness; 101 rt2x00led_led_simple(&rt2x00dev->led_radio, enabled);
109
110 if ((led->type != LED_TYPE_RADIO) || !(led->flags & LED_REGISTERED))
111 return;
112
113 brightness = enabled ? LED_FULL : LED_OFF;
114 if (brightness != led->led_dev.brightness) {
115 led->led_dev.brightness_set(&led->led_dev, brightness);
116 led->led_dev.brightness = brightness;
117 }
118} 102}
119 103
120static int rt2x00leds_register_led(struct rt2x00_dev *rt2x00dev, 104static int rt2x00leds_register_led(struct rt2x00_dev *rt2x00dev,
@@ -125,6 +109,13 @@ static int rt2x00leds_register_led(struct rt2x00_dev *rt2x00dev,
125 int retval; 109 int retval;
126 110
127 led->led_dev.name = name; 111 led->led_dev.name = name;
112 led->led_dev.brightness = LED_OFF;
113
114 /*
115 * Ensure the LED is off, it might have been enabled
116 * by the hardware when the device was powered on.
117 */
118 led->led_dev.brightness_set(&led->led_dev, LED_OFF);
128 119
129 retval = led_classdev_register(device, &led->led_dev); 120 retval = led_classdev_register(device, &led->led_dev);
130 if (retval) { 121 if (retval) {
@@ -199,7 +190,16 @@ exit_fail:
199static void rt2x00leds_unregister_led(struct rt2x00_led *led) 190static void rt2x00leds_unregister_led(struct rt2x00_led *led)
200{ 191{
201 led_classdev_unregister(&led->led_dev); 192 led_classdev_unregister(&led->led_dev);
202 led->led_dev.brightness_set(&led->led_dev, LED_OFF); 193
194 /*
195 * This might look weird, but when we are unregistering while
196 * suspended the led is already off, and since we haven't
197 * fully resumed yet, access to the device might not be
198 * possible yet.
199 */
200 if (!(led->led_dev.flags & LED_SUSPENDED))
201 led->led_dev.brightness_set(&led->led_dev, LED_OFF);
202
203 led->flags &= ~LED_REGISTERED; 203 led->flags &= ~LED_REGISTERED;
204} 204}
205 205
@@ -213,22 +213,40 @@ void rt2x00leds_unregister(struct rt2x00_dev *rt2x00dev)
213 rt2x00leds_unregister_led(&rt2x00dev->led_radio); 213 rt2x00leds_unregister_led(&rt2x00dev->led_radio);
214} 214}
215 215
216static inline void rt2x00leds_suspend_led(struct rt2x00_led *led)
217{
218 led_classdev_suspend(&led->led_dev);
219
220 /* This shouldn't be needed, but just to be safe */
221 led->led_dev.brightness_set(&led->led_dev, LED_OFF);
222 led->led_dev.brightness = LED_OFF;
223}
224
216void rt2x00leds_suspend(struct rt2x00_dev *rt2x00dev) 225void rt2x00leds_suspend(struct rt2x00_dev *rt2x00dev)
217{ 226{
218 if (rt2x00dev->led_qual.flags & LED_REGISTERED) 227 if (rt2x00dev->led_qual.flags & LED_REGISTERED)
219 led_classdev_suspend(&rt2x00dev->led_qual.led_dev); 228 rt2x00leds_suspend_led(&rt2x00dev->led_qual);
220 if (rt2x00dev->led_assoc.flags & LED_REGISTERED) 229 if (rt2x00dev->led_assoc.flags & LED_REGISTERED)
221 led_classdev_suspend(&rt2x00dev->led_assoc.led_dev); 230 rt2x00leds_suspend_led(&rt2x00dev->led_assoc);
222 if (rt2x00dev->led_radio.flags & LED_REGISTERED) 231 if (rt2x00dev->led_radio.flags & LED_REGISTERED)
223 led_classdev_suspend(&rt2x00dev->led_radio.led_dev); 232 rt2x00leds_suspend_led(&rt2x00dev->led_radio);
233}
234
235static inline void rt2x00leds_resume_led(struct rt2x00_led *led)
236{
237 led_classdev_resume(&led->led_dev);
238
239 /* Device might have enabled the LEDS during resume */
240 led->led_dev.brightness_set(&led->led_dev, LED_OFF);
241 led->led_dev.brightness = LED_OFF;
224} 242}
225 243
226void rt2x00leds_resume(struct rt2x00_dev *rt2x00dev) 244void rt2x00leds_resume(struct rt2x00_dev *rt2x00dev)
227{ 245{
228 if (rt2x00dev->led_radio.flags & LED_REGISTERED) 246 if (rt2x00dev->led_radio.flags & LED_REGISTERED)
229 led_classdev_resume(&rt2x00dev->led_radio.led_dev); 247 rt2x00leds_resume_led(&rt2x00dev->led_radio);
230 if (rt2x00dev->led_assoc.flags & LED_REGISTERED) 248 if (rt2x00dev->led_assoc.flags & LED_REGISTERED)
231 led_classdev_resume(&rt2x00dev->led_assoc.led_dev); 249 rt2x00leds_resume_led(&rt2x00dev->led_assoc);
232 if (rt2x00dev->led_qual.flags & LED_REGISTERED) 250 if (rt2x00dev->led_qual.flags & LED_REGISTERED)
233 led_classdev_resume(&rt2x00dev->led_qual.led_dev); 251 rt2x00leds_resume_led(&rt2x00dev->led_qual);
234} 252}