diff options
author | Sujith Manoharan <Sujith.Manoharan@atheros.com> | 2011-04-28 06:44:05 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2011-04-29 15:36:15 -0400 |
commit | d244f21e79162b829c9af09845421d9b4fac4253 (patch) | |
tree | 5220722b8938e258f4f3eab67f7eaedd3e88800e /drivers/net/wireless/ath | |
parent | 22450902e4a13479acf6f4e93475af7ca1829d92 (diff) |
ath9k_htc: Revamp LED management
Remove all the convoluted hacks in the driver and simplify things
by making use of mac80211's LED triggers.
Signed-off-by: Sujith Manoharan <Sujith.Manoharan@atheros.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/ath')
-rw-r--r-- | drivers/net/wireless/ath/ath9k/htc.h | 65 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/htc_drv_gpio.c | 188 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/htc_drv_init.c | 22 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/htc_drv_main.c | 6 |
4 files changed, 85 insertions, 196 deletions
diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h index 6bb71e311a4b..dfc7a982fc7e 100644 --- a/drivers/net/wireless/ath/ath9k/htc.h +++ b/drivers/net/wireless/ath/ath9k/htc.h | |||
@@ -385,25 +385,6 @@ static inline void ath9k_htc_err_stat_rx(struct ath9k_htc_priv *priv, | |||
385 | #define ATH_LED_PIN_9287 10 | 385 | #define ATH_LED_PIN_9287 10 |
386 | #define ATH_LED_PIN_9271 15 | 386 | #define ATH_LED_PIN_9271 15 |
387 | #define ATH_LED_PIN_7010 12 | 387 | #define ATH_LED_PIN_7010 12 |
388 | #define ATH_LED_ON_DURATION_IDLE 350 /* in msecs */ | ||
389 | #define ATH_LED_OFF_DURATION_IDLE 250 /* in msecs */ | ||
390 | |||
391 | enum ath_led_type { | ||
392 | ATH_LED_RADIO, | ||
393 | ATH_LED_ASSOC, | ||
394 | ATH_LED_TX, | ||
395 | ATH_LED_RX | ||
396 | }; | ||
397 | |||
398 | struct ath_led { | ||
399 | struct ath9k_htc_priv *priv; | ||
400 | struct led_classdev led_cdev; | ||
401 | enum ath_led_type led_type; | ||
402 | struct delayed_work brightness_work; | ||
403 | char name[32]; | ||
404 | bool registered; | ||
405 | int brightness; | ||
406 | }; | ||
407 | 388 | ||
408 | #define BSTUCK_THRESHOLD 10 | 389 | #define BSTUCK_THRESHOLD 10 |
409 | 390 | ||
@@ -437,14 +418,11 @@ void ath_htc_cancel_btcoex_work(struct ath9k_htc_priv *priv); | |||
437 | 418 | ||
438 | #define OP_INVALID BIT(0) | 419 | #define OP_INVALID BIT(0) |
439 | #define OP_SCANNING BIT(1) | 420 | #define OP_SCANNING BIT(1) |
440 | #define OP_LED_ASSOCIATED BIT(2) | 421 | #define OP_ENABLE_BEACON BIT(2) |
441 | #define OP_LED_ON BIT(3) | 422 | #define OP_BT_PRIORITY_DETECTED BIT(3) |
442 | #define OP_ENABLE_BEACON BIT(4) | 423 | #define OP_BT_SCAN BIT(4) |
443 | #define OP_LED_DEINIT BIT(5) | 424 | #define OP_ANI_RUNNING BIT(5) |
444 | #define OP_BT_PRIORITY_DETECTED BIT(6) | 425 | #define OP_TSF_RESET BIT(6) |
445 | #define OP_BT_SCAN BIT(7) | ||
446 | #define OP_ANI_RUNNING BIT(8) | ||
447 | #define OP_TSF_RESET BIT(9) | ||
448 | 426 | ||
449 | struct ath9k_htc_priv { | 427 | struct ath9k_htc_priv { |
450 | struct device *dev; | 428 | struct device *dev; |
@@ -504,15 +482,13 @@ struct ath9k_htc_priv { | |||
504 | bool ps_enabled; | 482 | bool ps_enabled; |
505 | bool ps_idle; | 483 | bool ps_idle; |
506 | 484 | ||
507 | struct ath_led radio_led; | 485 | #ifdef CONFIG_MAC80211_LEDS |
508 | struct ath_led assoc_led; | 486 | enum led_brightness brightness; |
509 | struct ath_led tx_led; | 487 | bool led_registered; |
510 | struct ath_led rx_led; | 488 | char led_name[32]; |
511 | struct delayed_work ath9k_led_blink_work; | 489 | struct led_classdev led_cdev; |
512 | int led_on_duration; | 490 | struct work_struct led_work; |
513 | int led_off_duration; | 491 | #endif |
514 | int led_on_cnt; | ||
515 | int led_off_cnt; | ||
516 | 492 | ||
517 | int beaconq; | 493 | int beaconq; |
518 | int cabq; | 494 | int cabq; |
@@ -597,9 +573,24 @@ void ath9k_start_rfkill_poll(struct ath9k_htc_priv *priv); | |||
597 | void ath9k_htc_rfkill_poll_state(struct ieee80211_hw *hw); | 573 | void ath9k_htc_rfkill_poll_state(struct ieee80211_hw *hw); |
598 | void ath9k_htc_radio_enable(struct ieee80211_hw *hw); | 574 | void ath9k_htc_radio_enable(struct ieee80211_hw *hw); |
599 | void ath9k_htc_radio_disable(struct ieee80211_hw *hw); | 575 | void ath9k_htc_radio_disable(struct ieee80211_hw *hw); |
600 | void ath9k_led_stop_brightness(struct ath9k_htc_priv *priv); | 576 | |
577 | #ifdef CONFIG_MAC80211_LEDS | ||
601 | void ath9k_init_leds(struct ath9k_htc_priv *priv); | 578 | void ath9k_init_leds(struct ath9k_htc_priv *priv); |
602 | void ath9k_deinit_leds(struct ath9k_htc_priv *priv); | 579 | void ath9k_deinit_leds(struct ath9k_htc_priv *priv); |
580 | void ath9k_led_work(struct work_struct *work); | ||
581 | #else | ||
582 | static inline void ath9k_init_leds(struct ath9k_htc_priv *priv) | ||
583 | { | ||
584 | } | ||
585 | |||
586 | static inline void ath9k_deinit_leds(struct ath9k_htc_priv *priv) | ||
587 | { | ||
588 | } | ||
589 | |||
590 | static inline void ath9k_led_work(struct work_struct *work) | ||
591 | { | ||
592 | } | ||
593 | #endif | ||
603 | 594 | ||
604 | int ath9k_htc_probe_device(struct htc_target *htc_handle, struct device *dev, | 595 | int ath9k_htc_probe_device(struct htc_target *htc_handle, struct device *dev, |
605 | u16 devid, char *product, u32 drv_info); | 596 | u16 devid, char *product, u32 drv_info); |
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c b/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c index 26ede1daa304..af57fe5aab98 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c | |||
@@ -154,140 +154,41 @@ void ath_htc_cancel_btcoex_work(struct ath9k_htc_priv *priv) | |||
154 | /* LED */ | 154 | /* LED */ |
155 | /*******/ | 155 | /*******/ |
156 | 156 | ||
157 | static void ath9k_led_blink_work(struct work_struct *work) | 157 | #ifdef CONFIG_MAC80211_LEDS |
158 | void ath9k_led_work(struct work_struct *work) | ||
158 | { | 159 | { |
159 | struct ath9k_htc_priv *priv = container_of(work, struct ath9k_htc_priv, | 160 | struct ath9k_htc_priv *priv = container_of(work, |
160 | ath9k_led_blink_work.work); | 161 | struct ath9k_htc_priv, |
161 | 162 | led_work); | |
162 | if (!(priv->op_flags & OP_LED_ASSOCIATED)) | ||
163 | return; | ||
164 | 163 | ||
165 | if ((priv->led_on_duration == ATH_LED_ON_DURATION_IDLE) || | 164 | ath9k_hw_set_gpio(priv->ah, priv->ah->led_pin, |
166 | (priv->led_off_duration == ATH_LED_OFF_DURATION_IDLE)) | 165 | (priv->brightness == LED_OFF)); |
167 | ath9k_hw_set_gpio(priv->ah, priv->ah->led_pin, 0); | ||
168 | else | ||
169 | ath9k_hw_set_gpio(priv->ah, priv->ah->led_pin, | ||
170 | (priv->op_flags & OP_LED_ON) ? 1 : 0); | ||
171 | |||
172 | ieee80211_queue_delayed_work(priv->hw, | ||
173 | &priv->ath9k_led_blink_work, | ||
174 | (priv->op_flags & OP_LED_ON) ? | ||
175 | msecs_to_jiffies(priv->led_off_duration) : | ||
176 | msecs_to_jiffies(priv->led_on_duration)); | ||
177 | |||
178 | priv->led_on_duration = priv->led_on_cnt ? | ||
179 | max((ATH_LED_ON_DURATION_IDLE - priv->led_on_cnt), 25) : | ||
180 | ATH_LED_ON_DURATION_IDLE; | ||
181 | priv->led_off_duration = priv->led_off_cnt ? | ||
182 | max((ATH_LED_OFF_DURATION_IDLE - priv->led_off_cnt), 10) : | ||
183 | ATH_LED_OFF_DURATION_IDLE; | ||
184 | priv->led_on_cnt = priv->led_off_cnt = 0; | ||
185 | |||
186 | if (priv->op_flags & OP_LED_ON) | ||
187 | priv->op_flags &= ~OP_LED_ON; | ||
188 | else | ||
189 | priv->op_flags |= OP_LED_ON; | ||
190 | } | ||
191 | |||
192 | static void ath9k_led_brightness_work(struct work_struct *work) | ||
193 | { | ||
194 | struct ath_led *led = container_of(work, struct ath_led, | ||
195 | brightness_work.work); | ||
196 | struct ath9k_htc_priv *priv = led->priv; | ||
197 | |||
198 | switch (led->brightness) { | ||
199 | case LED_OFF: | ||
200 | if (led->led_type == ATH_LED_ASSOC || | ||
201 | led->led_type == ATH_LED_RADIO) { | ||
202 | ath9k_hw_set_gpio(priv->ah, priv->ah->led_pin, | ||
203 | (led->led_type == ATH_LED_RADIO)); | ||
204 | priv->op_flags &= ~OP_LED_ASSOCIATED; | ||
205 | if (led->led_type == ATH_LED_RADIO) | ||
206 | priv->op_flags &= ~OP_LED_ON; | ||
207 | } else { | ||
208 | priv->led_off_cnt++; | ||
209 | } | ||
210 | break; | ||
211 | case LED_FULL: | ||
212 | if (led->led_type == ATH_LED_ASSOC) { | ||
213 | priv->op_flags |= OP_LED_ASSOCIATED; | ||
214 | ieee80211_queue_delayed_work(priv->hw, | ||
215 | &priv->ath9k_led_blink_work, 0); | ||
216 | } else if (led->led_type == ATH_LED_RADIO) { | ||
217 | ath9k_hw_set_gpio(priv->ah, priv->ah->led_pin, 0); | ||
218 | priv->op_flags |= OP_LED_ON; | ||
219 | } else { | ||
220 | priv->led_on_cnt++; | ||
221 | } | ||
222 | break; | ||
223 | default: | ||
224 | break; | ||
225 | } | ||
226 | } | 166 | } |
227 | 167 | ||
228 | static void ath9k_led_brightness(struct led_classdev *led_cdev, | 168 | static void ath9k_led_brightness(struct led_classdev *led_cdev, |
229 | enum led_brightness brightness) | 169 | enum led_brightness brightness) |
230 | { | 170 | { |
231 | struct ath_led *led = container_of(led_cdev, struct ath_led, led_cdev); | 171 | struct ath9k_htc_priv *priv = container_of(led_cdev, |
232 | struct ath9k_htc_priv *priv = led->priv; | 172 | struct ath9k_htc_priv, |
233 | 173 | led_cdev); | |
234 | led->brightness = brightness; | ||
235 | if (!(priv->op_flags & OP_LED_DEINIT)) | ||
236 | ieee80211_queue_delayed_work(priv->hw, | ||
237 | &led->brightness_work, 0); | ||
238 | } | ||
239 | 174 | ||
240 | void ath9k_led_stop_brightness(struct ath9k_htc_priv *priv) | 175 | /* Not locked, but it's just a tiny green light..*/ |
241 | { | 176 | priv->brightness = brightness; |
242 | cancel_delayed_work_sync(&priv->radio_led.brightness_work); | 177 | ieee80211_queue_work(priv->hw, &priv->led_work); |
243 | cancel_delayed_work_sync(&priv->assoc_led.brightness_work); | ||
244 | cancel_delayed_work_sync(&priv->tx_led.brightness_work); | ||
245 | cancel_delayed_work_sync(&priv->rx_led.brightness_work); | ||
246 | } | ||
247 | |||
248 | static int ath9k_register_led(struct ath9k_htc_priv *priv, struct ath_led *led, | ||
249 | char *trigger) | ||
250 | { | ||
251 | int ret; | ||
252 | |||
253 | led->priv = priv; | ||
254 | led->led_cdev.name = led->name; | ||
255 | led->led_cdev.default_trigger = trigger; | ||
256 | led->led_cdev.brightness_set = ath9k_led_brightness; | ||
257 | |||
258 | ret = led_classdev_register(wiphy_dev(priv->hw->wiphy), &led->led_cdev); | ||
259 | if (ret) | ||
260 | ath_err(ath9k_hw_common(priv->ah), | ||
261 | "Failed to register led:%s", led->name); | ||
262 | else | ||
263 | led->registered = 1; | ||
264 | |||
265 | INIT_DELAYED_WORK(&led->brightness_work, ath9k_led_brightness_work); | ||
266 | |||
267 | return ret; | ||
268 | } | ||
269 | |||
270 | static void ath9k_unregister_led(struct ath_led *led) | ||
271 | { | ||
272 | if (led->registered) { | ||
273 | led_classdev_unregister(&led->led_cdev); | ||
274 | led->registered = 0; | ||
275 | } | ||
276 | } | 178 | } |
277 | 179 | ||
278 | void ath9k_deinit_leds(struct ath9k_htc_priv *priv) | 180 | void ath9k_deinit_leds(struct ath9k_htc_priv *priv) |
279 | { | 181 | { |
280 | priv->op_flags |= OP_LED_DEINIT; | 182 | if (!priv->led_registered) |
281 | ath9k_unregister_led(&priv->assoc_led); | 183 | return; |
282 | priv->op_flags &= ~OP_LED_ASSOCIATED; | 184 | |
283 | ath9k_unregister_led(&priv->tx_led); | 185 | ath9k_led_brightness(&priv->led_cdev, LED_OFF); |
284 | ath9k_unregister_led(&priv->rx_led); | 186 | led_classdev_unregister(&priv->led_cdev); |
285 | ath9k_unregister_led(&priv->radio_led); | 187 | cancel_work_sync(&priv->led_work); |
286 | } | 188 | } |
287 | 189 | ||
288 | void ath9k_init_leds(struct ath9k_htc_priv *priv) | 190 | void ath9k_init_leds(struct ath9k_htc_priv *priv) |
289 | { | 191 | { |
290 | char *trigger; | ||
291 | int ret; | 192 | int ret; |
292 | 193 | ||
293 | if (AR_SREV_9287(priv->ah)) | 194 | if (AR_SREV_9287(priv->ah)) |
@@ -305,48 +206,21 @@ void ath9k_init_leds(struct ath9k_htc_priv *priv) | |||
305 | /* LED off, active low */ | 206 | /* LED off, active low */ |
306 | ath9k_hw_set_gpio(priv->ah, priv->ah->led_pin, 1); | 207 | ath9k_hw_set_gpio(priv->ah, priv->ah->led_pin, 1); |
307 | 208 | ||
308 | INIT_DELAYED_WORK(&priv->ath9k_led_blink_work, ath9k_led_blink_work); | 209 | snprintf(priv->led_name, sizeof(priv->led_name), |
309 | 210 | "ath9k_htc-%s", wiphy_name(priv->hw->wiphy)); | |
310 | trigger = ieee80211_get_radio_led_name(priv->hw); | 211 | priv->led_cdev.name = priv->led_name; |
311 | snprintf(priv->radio_led.name, sizeof(priv->radio_led.name), | 212 | priv->led_cdev.brightness_set = ath9k_led_brightness; |
312 | "ath9k-%s::radio", wiphy_name(priv->hw->wiphy)); | ||
313 | ret = ath9k_register_led(priv, &priv->radio_led, trigger); | ||
314 | priv->radio_led.led_type = ATH_LED_RADIO; | ||
315 | if (ret) | ||
316 | goto fail; | ||
317 | |||
318 | trigger = ieee80211_get_assoc_led_name(priv->hw); | ||
319 | snprintf(priv->assoc_led.name, sizeof(priv->assoc_led.name), | ||
320 | "ath9k-%s::assoc", wiphy_name(priv->hw->wiphy)); | ||
321 | ret = ath9k_register_led(priv, &priv->assoc_led, trigger); | ||
322 | priv->assoc_led.led_type = ATH_LED_ASSOC; | ||
323 | if (ret) | ||
324 | goto fail; | ||
325 | |||
326 | trigger = ieee80211_get_tx_led_name(priv->hw); | ||
327 | snprintf(priv->tx_led.name, sizeof(priv->tx_led.name), | ||
328 | "ath9k-%s::tx", wiphy_name(priv->hw->wiphy)); | ||
329 | ret = ath9k_register_led(priv, &priv->tx_led, trigger); | ||
330 | priv->tx_led.led_type = ATH_LED_TX; | ||
331 | if (ret) | ||
332 | goto fail; | ||
333 | |||
334 | trigger = ieee80211_get_rx_led_name(priv->hw); | ||
335 | snprintf(priv->rx_led.name, sizeof(priv->rx_led.name), | ||
336 | "ath9k-%s::rx", wiphy_name(priv->hw->wiphy)); | ||
337 | ret = ath9k_register_led(priv, &priv->rx_led, trigger); | ||
338 | priv->rx_led.led_type = ATH_LED_RX; | ||
339 | if (ret) | ||
340 | goto fail; | ||
341 | |||
342 | priv->op_flags &= ~OP_LED_DEINIT; | ||
343 | 213 | ||
344 | return; | 214 | ret = led_classdev_register(wiphy_dev(priv->hw->wiphy), &priv->led_cdev); |
215 | if (ret < 0) | ||
216 | return; | ||
345 | 217 | ||
346 | fail: | 218 | INIT_WORK(&priv->led_work, ath9k_led_work); |
347 | cancel_delayed_work_sync(&priv->ath9k_led_blink_work); | 219 | priv->led_registered = true; |
348 | ath9k_deinit_leds(priv); | 220 | |
221 | return; | ||
349 | } | 222 | } |
223 | #endif | ||
350 | 224 | ||
351 | /*******************/ | 225 | /*******************/ |
352 | /* Rfkill */ | 226 | /* Rfkill */ |
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c index d2dd5a63e10a..bfdc8a887183 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c | |||
@@ -117,6 +117,21 @@ static struct ieee80211_rate ath9k_legacy_rates[] = { | |||
117 | RATE(540, 0x0c, 0), | 117 | RATE(540, 0x0c, 0), |
118 | }; | 118 | }; |
119 | 119 | ||
120 | #ifdef CONFIG_MAC80211_LEDS | ||
121 | static const struct ieee80211_tpt_blink ath9k_htc_tpt_blink[] = { | ||
122 | { .throughput = 0 * 1024, .blink_time = 334 }, | ||
123 | { .throughput = 1 * 1024, .blink_time = 260 }, | ||
124 | { .throughput = 5 * 1024, .blink_time = 220 }, | ||
125 | { .throughput = 10 * 1024, .blink_time = 190 }, | ||
126 | { .throughput = 20 * 1024, .blink_time = 170 }, | ||
127 | { .throughput = 50 * 1024, .blink_time = 150 }, | ||
128 | { .throughput = 70 * 1024, .blink_time = 130 }, | ||
129 | { .throughput = 100 * 1024, .blink_time = 110 }, | ||
130 | { .throughput = 200 * 1024, .blink_time = 80 }, | ||
131 | { .throughput = 300 * 1024, .blink_time = 50 }, | ||
132 | }; | ||
133 | #endif | ||
134 | |||
120 | static int ath9k_htc_wait_for_target(struct ath9k_htc_priv *priv) | 135 | static int ath9k_htc_wait_for_target(struct ath9k_htc_priv *priv) |
121 | { | 136 | { |
122 | int time_left; | 137 | int time_left; |
@@ -863,6 +878,13 @@ static int ath9k_init_device(struct ath9k_htc_priv *priv, | |||
863 | if (error != 0) | 878 | if (error != 0) |
864 | goto err_rx; | 879 | goto err_rx; |
865 | 880 | ||
881 | #ifdef CONFIG_MAC80211_LEDS | ||
882 | /* must be initialized before ieee80211_register_hw */ | ||
883 | priv->led_cdev.default_trigger = ieee80211_create_tpt_led_trigger(priv->hw, | ||
884 | IEEE80211_TPT_LEDTRIG_FL_RADIO, ath9k_htc_tpt_blink, | ||
885 | ARRAY_SIZE(ath9k_htc_tpt_blink)); | ||
886 | #endif | ||
887 | |||
866 | /* Register with mac80211 */ | 888 | /* Register with mac80211 */ |
867 | error = ieee80211_register_hw(hw); | 889 | error = ieee80211_register_hw(hw); |
868 | if (error) | 890 | if (error) |
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index e9746e8ff8dd..5aa104fe7eeb 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c | |||
@@ -1003,9 +1003,11 @@ static void ath9k_htc_stop(struct ieee80211_hw *hw) | |||
1003 | /* Cancel all the running timers/work .. */ | 1003 | /* Cancel all the running timers/work .. */ |
1004 | cancel_work_sync(&priv->fatal_work); | 1004 | cancel_work_sync(&priv->fatal_work); |
1005 | cancel_work_sync(&priv->ps_work); | 1005 | cancel_work_sync(&priv->ps_work); |
1006 | cancel_delayed_work_sync(&priv->ath9k_led_blink_work); | 1006 | |
1007 | #ifdef CONFIG_MAC80211_LEDS | ||
1008 | cancel_work_sync(&priv->led_work); | ||
1009 | #endif | ||
1007 | ath9k_htc_stop_ani(priv); | 1010 | ath9k_htc_stop_ani(priv); |
1008 | ath9k_led_stop_brightness(priv); | ||
1009 | 1011 | ||
1010 | mutex_lock(&priv->mutex); | 1012 | mutex_lock(&priv->mutex); |
1011 | 1013 | ||