diff options
Diffstat (limited to 'drivers/net/wireless/ath/ath9k/gpio.c')
-rw-r--r-- | drivers/net/wireless/ath/ath9k/gpio.c | 164 |
1 files changed, 23 insertions, 141 deletions
diff --git a/drivers/net/wireless/ath/ath9k/gpio.c b/drivers/net/wireless/ath/ath9k/gpio.c index fb4f17a5183d..e369bf7e575f 100644 --- a/drivers/net/wireless/ath/ath9k/gpio.c +++ b/drivers/net/wireless/ath/ath9k/gpio.c | |||
@@ -20,117 +20,25 @@ | |||
20 | /* LED functions */ | 20 | /* LED functions */ |
21 | /********************************/ | 21 | /********************************/ |
22 | 22 | ||
23 | static void ath_led_blink_work(struct work_struct *work) | 23 | #ifdef CONFIG_MAC80211_LEDS |
24 | { | ||
25 | struct ath_softc *sc = container_of(work, struct ath_softc, | ||
26 | ath_led_blink_work.work); | ||
27 | |||
28 | if (!(sc->sc_flags & SC_OP_LED_ASSOCIATED)) | ||
29 | return; | ||
30 | |||
31 | if ((sc->led_on_duration == ATH_LED_ON_DURATION_IDLE) || | ||
32 | (sc->led_off_duration == ATH_LED_OFF_DURATION_IDLE)) | ||
33 | ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 0); | ||
34 | else | ||
35 | ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, | ||
36 | (sc->sc_flags & SC_OP_LED_ON) ? 1 : 0); | ||
37 | |||
38 | ieee80211_queue_delayed_work(sc->hw, | ||
39 | &sc->ath_led_blink_work, | ||
40 | (sc->sc_flags & SC_OP_LED_ON) ? | ||
41 | msecs_to_jiffies(sc->led_off_duration) : | ||
42 | msecs_to_jiffies(sc->led_on_duration)); | ||
43 | |||
44 | sc->led_on_duration = sc->led_on_cnt ? | ||
45 | max((ATH_LED_ON_DURATION_IDLE - sc->led_on_cnt), 25) : | ||
46 | ATH_LED_ON_DURATION_IDLE; | ||
47 | sc->led_off_duration = sc->led_off_cnt ? | ||
48 | max((ATH_LED_OFF_DURATION_IDLE - sc->led_off_cnt), 10) : | ||
49 | ATH_LED_OFF_DURATION_IDLE; | ||
50 | sc->led_on_cnt = sc->led_off_cnt = 0; | ||
51 | if (sc->sc_flags & SC_OP_LED_ON) | ||
52 | sc->sc_flags &= ~SC_OP_LED_ON; | ||
53 | else | ||
54 | sc->sc_flags |= SC_OP_LED_ON; | ||
55 | } | ||
56 | |||
57 | static void ath_led_brightness(struct led_classdev *led_cdev, | 24 | static void ath_led_brightness(struct led_classdev *led_cdev, |
58 | enum led_brightness brightness) | 25 | enum led_brightness brightness) |
59 | { | 26 | { |
60 | struct ath_led *led = container_of(led_cdev, struct ath_led, led_cdev); | 27 | struct ath_softc *sc = container_of(led_cdev, struct ath_softc, led_cdev); |
61 | struct ath_softc *sc = led->sc; | 28 | ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, (brightness == LED_OFF)); |
62 | |||
63 | switch (brightness) { | ||
64 | case LED_OFF: | ||
65 | if (led->led_type == ATH_LED_ASSOC || | ||
66 | led->led_type == ATH_LED_RADIO) { | ||
67 | ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, | ||
68 | (led->led_type == ATH_LED_RADIO)); | ||
69 | sc->sc_flags &= ~SC_OP_LED_ASSOCIATED; | ||
70 | if (led->led_type == ATH_LED_RADIO) | ||
71 | sc->sc_flags &= ~SC_OP_LED_ON; | ||
72 | } else { | ||
73 | sc->led_off_cnt++; | ||
74 | } | ||
75 | break; | ||
76 | case LED_FULL: | ||
77 | if (led->led_type == ATH_LED_ASSOC) { | ||
78 | sc->sc_flags |= SC_OP_LED_ASSOCIATED; | ||
79 | if (led_blink) | ||
80 | ieee80211_queue_delayed_work(sc->hw, | ||
81 | &sc->ath_led_blink_work, 0); | ||
82 | } else if (led->led_type == ATH_LED_RADIO) { | ||
83 | ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 0); | ||
84 | sc->sc_flags |= SC_OP_LED_ON; | ||
85 | } else { | ||
86 | sc->led_on_cnt++; | ||
87 | } | ||
88 | break; | ||
89 | default: | ||
90 | break; | ||
91 | } | ||
92 | } | ||
93 | |||
94 | static int ath_register_led(struct ath_softc *sc, struct ath_led *led, | ||
95 | char *trigger) | ||
96 | { | ||
97 | int ret; | ||
98 | |||
99 | led->sc = sc; | ||
100 | led->led_cdev.name = led->name; | ||
101 | led->led_cdev.default_trigger = trigger; | ||
102 | led->led_cdev.brightness_set = ath_led_brightness; | ||
103 | |||
104 | ret = led_classdev_register(wiphy_dev(sc->hw->wiphy), &led->led_cdev); | ||
105 | if (ret) | ||
106 | ath_err(ath9k_hw_common(sc->sc_ah), | ||
107 | "Failed to register led:%s", led->name); | ||
108 | else | ||
109 | led->registered = 1; | ||
110 | return ret; | ||
111 | } | ||
112 | |||
113 | static void ath_unregister_led(struct ath_led *led) | ||
114 | { | ||
115 | if (led->registered) { | ||
116 | led_classdev_unregister(&led->led_cdev); | ||
117 | led->registered = 0; | ||
118 | } | ||
119 | } | 29 | } |
120 | 30 | ||
121 | void ath_deinit_leds(struct ath_softc *sc) | 31 | void ath_deinit_leds(struct ath_softc *sc) |
122 | { | 32 | { |
123 | ath_unregister_led(&sc->assoc_led); | 33 | if (!sc->led_registered) |
124 | sc->sc_flags &= ~SC_OP_LED_ASSOCIATED; | 34 | return; |
125 | ath_unregister_led(&sc->tx_led); | 35 | |
126 | ath_unregister_led(&sc->rx_led); | 36 | ath_led_brightness(&sc->led_cdev, LED_OFF); |
127 | ath_unregister_led(&sc->radio_led); | 37 | led_classdev_unregister(&sc->led_cdev); |
128 | ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 1); | ||
129 | } | 38 | } |
130 | 39 | ||
131 | void ath_init_leds(struct ath_softc *sc) | 40 | void ath_init_leds(struct ath_softc *sc) |
132 | { | 41 | { |
133 | char *trigger; | ||
134 | int ret; | 42 | int ret; |
135 | 43 | ||
136 | if (AR_SREV_9287(sc->sc_ah)) | 44 | if (AR_SREV_9287(sc->sc_ah)) |
@@ -144,48 +52,22 @@ void ath_init_leds(struct ath_softc *sc) | |||
144 | /* LED off, active low */ | 52 | /* LED off, active low */ |
145 | ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 1); | 53 | ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 1); |
146 | 54 | ||
147 | if (led_blink) | 55 | if (!led_blink) |
148 | INIT_DELAYED_WORK(&sc->ath_led_blink_work, ath_led_blink_work); | 56 | sc->led_cdev.default_trigger = |
149 | 57 | ieee80211_get_radio_led_name(sc->hw); | |
150 | trigger = ieee80211_get_radio_led_name(sc->hw); | 58 | |
151 | snprintf(sc->radio_led.name, sizeof(sc->radio_led.name), | 59 | snprintf(sc->led_name, sizeof(sc->led_name), |
152 | "ath9k-%s::radio", wiphy_name(sc->hw->wiphy)); | 60 | "ath9k-%s", wiphy_name(sc->hw->wiphy)); |
153 | ret = ath_register_led(sc, &sc->radio_led, trigger); | 61 | sc->led_cdev.name = sc->led_name; |
154 | sc->radio_led.led_type = ATH_LED_RADIO; | 62 | sc->led_cdev.brightness_set = ath_led_brightness; |
155 | if (ret) | 63 | |
156 | goto fail; | 64 | ret = led_classdev_register(wiphy_dev(sc->hw->wiphy), &sc->led_cdev); |
157 | 65 | if (ret < 0) | |
158 | trigger = ieee80211_get_assoc_led_name(sc->hw); | 66 | return; |
159 | snprintf(sc->assoc_led.name, sizeof(sc->assoc_led.name), | 67 | |
160 | "ath9k-%s::assoc", wiphy_name(sc->hw->wiphy)); | 68 | sc->led_registered = true; |
161 | ret = ath_register_led(sc, &sc->assoc_led, trigger); | ||
162 | sc->assoc_led.led_type = ATH_LED_ASSOC; | ||
163 | if (ret) | ||
164 | goto fail; | ||
165 | |||
166 | trigger = ieee80211_get_tx_led_name(sc->hw); | ||
167 | snprintf(sc->tx_led.name, sizeof(sc->tx_led.name), | ||
168 | "ath9k-%s::tx", wiphy_name(sc->hw->wiphy)); | ||
169 | ret = ath_register_led(sc, &sc->tx_led, trigger); | ||
170 | sc->tx_led.led_type = ATH_LED_TX; | ||
171 | if (ret) | ||
172 | goto fail; | ||
173 | |||
174 | trigger = ieee80211_get_rx_led_name(sc->hw); | ||
175 | snprintf(sc->rx_led.name, sizeof(sc->rx_led.name), | ||
176 | "ath9k-%s::rx", wiphy_name(sc->hw->wiphy)); | ||
177 | ret = ath_register_led(sc, &sc->rx_led, trigger); | ||
178 | sc->rx_led.led_type = ATH_LED_RX; | ||
179 | if (ret) | ||
180 | goto fail; | ||
181 | |||
182 | return; | ||
183 | |||
184 | fail: | ||
185 | if (led_blink) | ||
186 | cancel_delayed_work_sync(&sc->ath_led_blink_work); | ||
187 | ath_deinit_leds(sc); | ||
188 | } | 69 | } |
70 | #endif | ||
189 | 71 | ||
190 | /*******************/ | 72 | /*******************/ |
191 | /* Rfkill */ | 73 | /* Rfkill */ |