aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath5k/base.c
diff options
context:
space:
mode:
authorBob Copeland <me@bobcopeland.com>2008-06-25 22:35:28 -0400
committerJohn W. Linville <linville@tuxdriver.com>2008-06-27 09:09:17 -0400
commit3a078876caee9634dbb9b41e6269262e30e8b535 (patch)
treecd7e285d0de6d6172b5e5f0f6377c5c6dbadafef /drivers/net/wireless/ath5k/base.c
parentffd7891dc909b3648e87f7cf8f84a6dc12fc1cc6 (diff)
ath5k: convert LED code to use mac80211 triggers
This change cleans up the ath5k LED code and converts it to use the standard LED device class along with the rx/tx LED triggers provided by mac80211. Signed-off-by: Bob Copeland <me@bobcopeland.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/ath5k/base.c')
-rw-r--r--drivers/net/wireless/ath5k/base.c251
1 files changed, 111 insertions, 140 deletions
diff --git a/drivers/net/wireless/ath5k/base.c b/drivers/net/wireless/ath5k/base.c
index 010c66555950..a80a3a4744ab 100644
--- a/drivers/net/wireless/ath5k/base.c
+++ b/drivers/net/wireless/ath5k/base.c
@@ -58,11 +58,6 @@
58#include "reg.h" 58#include "reg.h"
59#include "debug.h" 59#include "debug.h"
60 60
61enum {
62 ATH_LED_TX,
63 ATH_LED_RX,
64};
65
66static int ath5k_calinterval = 10; /* Calibrate PHY every 10 secs (TODO: Fixme) */ 61static int ath5k_calinterval = 10; /* Calibrate PHY every 10 secs (TODO: Fixme) */
67 62
68 63
@@ -309,13 +304,10 @@ static void ath5k_tasklet_reset(unsigned long data);
309 304
310static void ath5k_calibrate(unsigned long data); 305static void ath5k_calibrate(unsigned long data);
311/* LED functions */ 306/* LED functions */
312static void ath5k_led_off(unsigned long data); 307static int ath5k_init_leds(struct ath5k_softc *sc);
313static void ath5k_led_blink(struct ath5k_softc *sc, 308static void ath5k_led_enable(struct ath5k_softc *sc);
314 unsigned int on, 309static void ath5k_led_off(struct ath5k_softc *sc);
315 unsigned int off); 310static void ath5k_unregister_leds(struct ath5k_softc *sc);
316static void ath5k_led_event(struct ath5k_softc *sc,
317 int event);
318
319 311
320/* 312/*
321 * Module init/exit functions 313 * Module init/exit functions
@@ -596,8 +588,7 @@ ath5k_pci_suspend(struct pci_dev *pdev, pm_message_t state)
596 struct ieee80211_hw *hw = pci_get_drvdata(pdev); 588 struct ieee80211_hw *hw = pci_get_drvdata(pdev);
597 struct ath5k_softc *sc = hw->priv; 589 struct ath5k_softc *sc = hw->priv;
598 590
599 if (test_bit(ATH_STAT_LEDSOFT, sc->status)) 591 ath5k_led_off(sc);
600 ath5k_hw_set_gpio(sc->ah, sc->led_pin, 1);
601 592
602 ath5k_stop_hw(sc); 593 ath5k_stop_hw(sc);
603 pci_save_state(pdev); 594 pci_save_state(pdev);
@@ -632,10 +623,7 @@ ath5k_pci_resume(struct pci_dev *pdev)
632 pci_write_config_byte(pdev, 0x41, 0); 623 pci_write_config_byte(pdev, 0x41, 0);
633 624
634 ath5k_init(sc); 625 ath5k_init(sc);
635 if (test_bit(ATH_STAT_LEDSOFT, sc->status)) { 626 ath5k_led_enable(sc);
636 ath5k_hw_set_gpio_output(ah, sc->led_pin);
637 ath5k_hw_set_gpio(ah, sc->led_pin, 0);
638 }
639 627
640 /* 628 /*
641 * Reset the key cache since some parts do not 629 * Reset the key cache since some parts do not
@@ -742,27 +730,6 @@ ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw)
742 tasklet_init(&sc->txtq, ath5k_tasklet_tx, (unsigned long)sc); 730 tasklet_init(&sc->txtq, ath5k_tasklet_tx, (unsigned long)sc);
743 tasklet_init(&sc->restq, ath5k_tasklet_reset, (unsigned long)sc); 731 tasklet_init(&sc->restq, ath5k_tasklet_reset, (unsigned long)sc);
744 setup_timer(&sc->calib_tim, ath5k_calibrate, (unsigned long)sc); 732 setup_timer(&sc->calib_tim, ath5k_calibrate, (unsigned long)sc);
745 setup_timer(&sc->led_tim, ath5k_led_off, (unsigned long)sc);
746
747 sc->led_on = 0; /* low true */
748 /*
749 * Auto-enable soft led processing for IBM cards and for
750 * 5211 minipci cards.
751 */
752 if (pdev->device == PCI_DEVICE_ID_ATHEROS_AR5212_IBM ||
753 pdev->device == PCI_DEVICE_ID_ATHEROS_AR5211) {
754 __set_bit(ATH_STAT_LEDSOFT, sc->status);
755 sc->led_pin = 0;
756 }
757 /* Enable softled on PIN1 on HP Compaq nc6xx, nc4000 & nx5000 laptops */
758 if (pdev->subsystem_vendor == PCI_VENDOR_ID_COMPAQ) {
759 __set_bit(ATH_STAT_LEDSOFT, sc->status);
760 sc->led_pin = 0;
761 }
762 if (test_bit(ATH_STAT_LEDSOFT, sc->status)) {
763 ath5k_hw_set_gpio_output(ah, sc->led_pin);
764 ath5k_hw_set_gpio(ah, sc->led_pin, !sc->led_on);
765 }
766 733
767 ath5k_hw_get_lladdr(ah, mac); 734 ath5k_hw_get_lladdr(ah, mac);
768 SET_IEEE80211_PERM_ADDR(hw, mac); 735 SET_IEEE80211_PERM_ADDR(hw, mac);
@@ -776,6 +743,8 @@ ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw)
776 goto err_queues; 743 goto err_queues;
777 } 744 }
778 745
746 ath5k_init_leds(sc);
747
779 return 0; 748 return 0;
780err_queues: 749err_queues:
781 ath5k_txq_release(sc); 750 ath5k_txq_release(sc);
@@ -809,6 +778,7 @@ ath5k_detach(struct pci_dev *pdev, struct ieee80211_hw *hw)
809 ath5k_desc_free(sc, pdev); 778 ath5k_desc_free(sc, pdev);
810 ath5k_txq_release(sc); 779 ath5k_txq_release(sc);
811 ath5k_hw_release_tx_queue(sc->ah, sc->bhalq); 780 ath5k_hw_release_tx_queue(sc->ah, sc->bhalq);
781 ath5k_unregister_leds(sc);
812 782
813 /* 783 /*
814 * NB: can't reclaim these until after ieee80211_ifdetach 784 * NB: can't reclaim these until after ieee80211_ifdetach
@@ -1060,65 +1030,9 @@ ath5k_chan_set(struct ath5k_softc *sc, struct ieee80211_channel *chan)
1060 return 0; 1030 return 0;
1061} 1031}
1062 1032
1063/*
1064 * TODO: CLEAN THIS !!!
1065 */
1066static void 1033static void
1067ath5k_setcurmode(struct ath5k_softc *sc, unsigned int mode) 1034ath5k_setcurmode(struct ath5k_softc *sc, unsigned int mode)
1068{ 1035{
1069 if (unlikely(test_bit(ATH_STAT_LEDSOFT, sc->status))) {
1070 /* from Atheros NDIS driver, w/ permission */
1071 static const struct {
1072 u16 rate; /* tx/rx 802.11 rate */
1073 u16 timeOn; /* LED on time (ms) */
1074 u16 timeOff; /* LED off time (ms) */
1075 } blinkrates[] = {
1076 { 108, 40, 10 },
1077 { 96, 44, 11 },
1078 { 72, 50, 13 },
1079 { 48, 57, 14 },
1080 { 36, 67, 16 },
1081 { 24, 80, 20 },
1082 { 22, 100, 25 },
1083 { 18, 133, 34 },
1084 { 12, 160, 40 },
1085 { 10, 200, 50 },
1086 { 6, 240, 58 },
1087 { 4, 267, 66 },
1088 { 2, 400, 100 },
1089 { 0, 500, 130 }
1090 };
1091 const struct ath5k_rate_table *rt =
1092 ath5k_hw_get_rate_table(sc->ah, mode);
1093 unsigned int i, j;
1094
1095 BUG_ON(rt == NULL);
1096
1097 memset(sc->hwmap, 0, sizeof(sc->hwmap));
1098 for (i = 0; i < 32; i++) {
1099 u8 ix = rt->rate_code_to_index[i];
1100 if (ix == 0xff) {
1101 sc->hwmap[i].ledon = msecs_to_jiffies(500);
1102 sc->hwmap[i].ledoff = msecs_to_jiffies(130);
1103 continue;
1104 }
1105 sc->hwmap[i].txflags = IEEE80211_RADIOTAP_F_DATAPAD;
1106 /* receive frames include FCS */
1107 sc->hwmap[i].rxflags = sc->hwmap[i].txflags |
1108 IEEE80211_RADIOTAP_F_FCS;
1109 /* setup blink rate table to avoid per-packet lookup */
1110 for (j = 0; j < ARRAY_SIZE(blinkrates) - 1; j++)
1111 if (blinkrates[j].rate == /* XXX why 7f? */
1112 (rt->rates[ix].dot11_rate&0x7f))
1113 break;
1114
1115 sc->hwmap[i].ledon = msecs_to_jiffies(blinkrates[j].
1116 timeOn);
1117 sc->hwmap[i].ledoff = msecs_to_jiffies(blinkrates[j].
1118 timeOff);
1119 }
1120 }
1121
1122 sc->curmode = mode; 1036 sc->curmode = mode;
1123 1037
1124 if (mode == AR5K_MODE_11A) { 1038 if (mode == AR5K_MODE_11A) {
@@ -1900,8 +1814,6 @@ accept:
1900 ath5k_check_ibss_tsf(sc, skb, &rxs); 1814 ath5k_check_ibss_tsf(sc, skb, &rxs);
1901 1815
1902 __ieee80211_rx(sc->hw, skb, &rxs); 1816 __ieee80211_rx(sc->hw, skb, &rxs);
1903 sc->led_rxrate = rs.rs_rate;
1904 ath5k_led_event(sc, ATH_LED_RX);
1905next: 1817next:
1906 list_move_tail(&bf->list, &sc->rxbuf); 1818 list_move_tail(&bf->list, &sc->rxbuf);
1907 } while (ath5k_rxbuf_setup(sc, bf) == 0); 1819 } while (ath5k_rxbuf_setup(sc, bf) == 0);
@@ -1982,13 +1894,9 @@ ath5k_tasklet_tx(unsigned long data)
1982 struct ath5k_softc *sc = (void *)data; 1894 struct ath5k_softc *sc = (void *)data;
1983 1895
1984 ath5k_tx_processq(sc, sc->txq); 1896 ath5k_tx_processq(sc, sc->txq);
1985
1986 ath5k_led_event(sc, ATH_LED_TX);
1987} 1897}
1988 1898
1989 1899
1990
1991
1992/*****************\ 1900/*****************\
1993* Beacon handling * 1901* Beacon handling *
1994\*****************/ 1902\*****************/
@@ -2363,11 +2271,7 @@ ath5k_stop_locked(struct ath5k_softc *sc)
2363 ieee80211_stop_queues(sc->hw); 2271 ieee80211_stop_queues(sc->hw);
2364 2272
2365 if (!test_bit(ATH_STAT_INVALID, sc->status)) { 2273 if (!test_bit(ATH_STAT_INVALID, sc->status)) {
2366 if (test_bit(ATH_STAT_LEDSOFT, sc->status)) { 2274 ath5k_led_off(sc);
2367 del_timer_sync(&sc->led_tim);
2368 ath5k_hw_set_gpio(ah, sc->led_pin, !sc->led_on);
2369 __clear_bit(ATH_STAT_LEDBLINKING, sc->status);
2370 }
2371 ath5k_hw_set_intr(ah, 0); 2275 ath5k_hw_set_intr(ah, 0);
2372 } 2276 }
2373 ath5k_txq_cleanup(sc); 2277 ath5k_txq_cleanup(sc);
@@ -2563,54 +2467,123 @@ ath5k_calibrate(unsigned long data)
2563\***************/ 2467\***************/
2564 2468
2565static void 2469static void
2566ath5k_led_off(unsigned long data) 2470ath5k_led_enable(struct ath5k_softc *sc)
2567{ 2471{
2568 struct ath5k_softc *sc = (void *)data; 2472 if (test_bit(ATH_STAT_LEDSOFT, sc->status)) {
2569 2473 ath5k_hw_set_gpio_output(sc->ah, sc->led_pin);
2570 if (test_bit(ATH_STAT_LEDENDBLINK, sc->status)) 2474 ath5k_led_off(sc);
2571 __clear_bit(ATH_STAT_LEDBLINKING, sc->status);
2572 else {
2573 __set_bit(ATH_STAT_LEDENDBLINK, sc->status);
2574 ath5k_hw_set_gpio(sc->ah, sc->led_pin, !sc->led_on);
2575 mod_timer(&sc->led_tim, jiffies + sc->led_off);
2576 } 2475 }
2577} 2476}
2578 2477
2579/*
2580 * Blink the LED according to the specified on/off times.
2581 */
2582static void 2478static void
2583ath5k_led_blink(struct ath5k_softc *sc, unsigned int on, 2479ath5k_led_on(struct ath5k_softc *sc)
2584 unsigned int off)
2585{ 2480{
2586 ATH5K_DBG(sc, ATH5K_DEBUG_LED, "on %u off %u\n", on, off); 2481 if (!test_bit(ATH_STAT_LEDSOFT, sc->status))
2482 return;
2587 ath5k_hw_set_gpio(sc->ah, sc->led_pin, sc->led_on); 2483 ath5k_hw_set_gpio(sc->ah, sc->led_pin, sc->led_on);
2588 __set_bit(ATH_STAT_LEDBLINKING, sc->status);
2589 __clear_bit(ATH_STAT_LEDENDBLINK, sc->status);
2590 sc->led_off = off;
2591 mod_timer(&sc->led_tim, jiffies + on);
2592} 2484}
2593 2485
2594static void 2486static void
2595ath5k_led_event(struct ath5k_softc *sc, int event) 2487ath5k_led_off(struct ath5k_softc *sc)
2596{ 2488{
2597 if (likely(!test_bit(ATH_STAT_LEDSOFT, sc->status))) 2489 if (!test_bit(ATH_STAT_LEDSOFT, sc->status))
2598 return; 2490 return;
2599 if (unlikely(test_bit(ATH_STAT_LEDBLINKING, sc->status))) 2491 ath5k_hw_set_gpio(sc->ah, sc->led_pin, !sc->led_on);
2600 return; /* don't interrupt active blink */ 2492}
2601 switch (event) { 2493
2602 case ATH_LED_TX: 2494static void
2603 ath5k_led_blink(sc, sc->hwmap[sc->led_txrate].ledon, 2495ath5k_led_brightness_set(struct led_classdev *led_dev,
2604 sc->hwmap[sc->led_txrate].ledoff); 2496 enum led_brightness brightness)
2605 break; 2497{
2606 case ATH_LED_RX: 2498 struct ath5k_led *led = container_of(led_dev, struct ath5k_led,
2607 ath5k_led_blink(sc, sc->hwmap[sc->led_rxrate].ledon, 2499 led_dev);
2608 sc->hwmap[sc->led_rxrate].ledoff); 2500
2609 break; 2501 if (brightness == LED_OFF)
2502 ath5k_led_off(led->sc);
2503 else
2504 ath5k_led_on(led->sc);
2505}
2506
2507static int
2508ath5k_register_led(struct ath5k_softc *sc, struct ath5k_led *led,
2509 const char *name, char *trigger)
2510{
2511 int err;
2512
2513 led->sc = sc;
2514 strncpy(led->name, name, sizeof(led->name));
2515 led->led_dev.name = led->name;
2516 led->led_dev.default_trigger = trigger;
2517 led->led_dev.brightness_set = ath5k_led_brightness_set;
2518
2519 err = led_classdev_register(&sc->pdev->dev, &led->led_dev);
2520 if (err)
2521 {
2522 ATH5K_WARN(sc, "could not register LED %s\n", name);
2523 led->sc = NULL;
2610 } 2524 }
2525 return err;
2526}
2527
2528static void
2529ath5k_unregister_led(struct ath5k_led *led)
2530{
2531 if (!led->sc)
2532 return;
2533 led_classdev_unregister(&led->led_dev);
2534 ath5k_led_off(led->sc);
2535 led->sc = NULL;
2536}
2537
2538static void
2539ath5k_unregister_leds(struct ath5k_softc *sc)
2540{
2541 ath5k_unregister_led(&sc->rx_led);
2542 ath5k_unregister_led(&sc->tx_led);
2611} 2543}
2612 2544
2613 2545
2546static int
2547ath5k_init_leds(struct ath5k_softc *sc)
2548{
2549 int ret = 0;
2550 struct ieee80211_hw *hw = sc->hw;
2551 struct pci_dev *pdev = sc->pdev;
2552 char name[ATH5K_LED_MAX_NAME_LEN + 1];
2553
2554 sc->led_on = 0; /* active low */
2555
2556 /*
2557 * Auto-enable soft led processing for IBM cards and for
2558 * 5211 minipci cards.
2559 */
2560 if (pdev->device == PCI_DEVICE_ID_ATHEROS_AR5212_IBM ||
2561 pdev->device == PCI_DEVICE_ID_ATHEROS_AR5211) {
2562 __set_bit(ATH_STAT_LEDSOFT, sc->status);
2563 sc->led_pin = 0;
2564 }
2565 /* Enable softled on PIN1 on HP Compaq nc6xx, nc4000 & nx5000 laptops */
2566 if (pdev->subsystem_vendor == PCI_VENDOR_ID_COMPAQ) {
2567 __set_bit(ATH_STAT_LEDSOFT, sc->status);
2568 sc->led_pin = 1;
2569 }
2570 if (!test_bit(ATH_STAT_LEDSOFT, sc->status))
2571 goto out;
2572
2573 ath5k_led_enable(sc);
2574
2575 snprintf(name, sizeof(name), "ath5k-%s::rx", wiphy_name(hw->wiphy));
2576 ret = ath5k_register_led(sc, &sc->rx_led, name,
2577 ieee80211_get_rx_led_name(hw));
2578 if (ret)
2579 goto out;
2580
2581 snprintf(name, sizeof(name), "ath5k-%s::tx", wiphy_name(hw->wiphy));
2582 ret = ath5k_register_led(sc, &sc->tx_led, name,
2583 ieee80211_get_tx_led_name(hw));
2584out:
2585 return ret;
2586}
2614 2587
2615 2588
2616/********************\ 2589/********************\
@@ -2648,8 +2621,6 @@ ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
2648 memmove(skb->data, skb->data+pad, hdrlen); 2621 memmove(skb->data, skb->data+pad, hdrlen);
2649 } 2622 }
2650 2623
2651 sc->led_txrate = ieee80211_get_tx_rate(hw, info)->hw_value;
2652
2653 spin_lock_irqsave(&sc->txbuflock, flags); 2624 spin_lock_irqsave(&sc->txbuflock, flags);
2654 if (list_empty(&sc->txbuf)) { 2625 if (list_empty(&sc->txbuf)) {
2655 ATH5K_ERR(sc, "no further txbuf available, dropping packet\n"); 2626 ATH5K_ERR(sc, "no further txbuf available, dropping packet\n");