OpenWrt – Blame information for rev 4
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
4 | office | 1 | --- a/drivers/net/wireless/ath/ath9k/ath9k.h |
2 | +++ b/drivers/net/wireless/ath/ath9k/ath9k.h |
||
3 | @@ -850,6 +850,9 @@ static inline int ath9k_dump_btcoex(stru |
||
4 | #ifdef CPTCFG_MAC80211_LEDS |
||
5 | void ath_init_leds(struct ath_softc *sc); |
||
6 | void ath_deinit_leds(struct ath_softc *sc); |
||
7 | +int ath_create_gpio_led(struct ath_softc *sc, int gpio, const char *name, |
||
8 | + const char *trigger, bool active_low); |
||
9 | + |
||
10 | #else |
||
11 | static inline void ath_init_leds(struct ath_softc *sc) |
||
12 | { |
||
13 | @@ -991,6 +994,13 @@ void ath_ant_comb_scan(struct ath_softc |
||
14 | #define AIRTIME_USE_NEW_QUEUES BIT(2) |
||
15 | #define AIRTIME_ACTIVE(flags) (!!(flags & (AIRTIME_USE_TX|AIRTIME_USE_RX))) |
||
16 | |||
17 | +struct ath_led { |
||
18 | + struct list_head list; |
||
19 | + struct ath_softc *sc; |
||
20 | + const struct gpio_led *gpio; |
||
21 | + struct led_classdev cdev; |
||
22 | +}; |
||
23 | + |
||
24 | struct ath_softc { |
||
25 | struct ieee80211_hw *hw; |
||
26 | struct device *dev; |
||
27 | @@ -1046,9 +1056,8 @@ struct ath_softc { |
||
28 | spinlock_t chan_lock; |
||
29 | |||
30 | #ifdef CPTCFG_MAC80211_LEDS |
||
31 | - bool led_registered; |
||
32 | - char led_name[32]; |
||
33 | - struct led_classdev led_cdev; |
||
34 | + const char *led_default_trigger; |
||
35 | + struct list_head leds; |
||
36 | #endif |
||
37 | |||
38 | #ifdef CPTCFG_ATH9K_DEBUGFS |
||
39 | --- a/drivers/net/wireless/ath/ath9k/gpio.c |
||
40 | +++ b/drivers/net/wireless/ath/ath9k/gpio.c |
||
41 | @@ -39,61 +39,111 @@ static void ath_fill_led_pin(struct ath_ |
||
42 | else |
||
43 | ah->led_pin = ATH_LED_PIN_DEF; |
||
44 | } |
||
45 | +} |
||
46 | + |
||
47 | +static void ath_led_brightness(struct led_classdev *led_cdev, |
||
48 | + enum led_brightness brightness) |
||
49 | +{ |
||
50 | + struct ath_led *led = container_of(led_cdev, struct ath_led, cdev); |
||
51 | + struct ath_softc *sc = led->sc; |
||
52 | + |
||
53 | + ath9k_ps_wakeup(sc); |
||
54 | + ath9k_hw_set_gpio(sc->sc_ah, led->gpio->gpio, |
||
55 | + (brightness != LED_OFF) ^ led->gpio->active_low); |
||
56 | + ath9k_ps_restore(sc); |
||
57 | +} |
||
58 | + |
||
59 | +static int ath_add_led(struct ath_softc *sc, struct ath_led *led) |
||
60 | +{ |
||
61 | + const struct gpio_led *gpio = led->gpio; |
||
62 | + int ret; |
||
63 | + |
||
64 | + led->cdev.name = gpio->name; |
||
65 | + led->cdev.default_trigger = gpio->default_trigger; |
||
66 | + led->cdev.brightness_set = ath_led_brightness; |
||
67 | + |
||
68 | + ret = led_classdev_register(wiphy_dev(sc->hw->wiphy), &led->cdev); |
||
69 | + if (ret < 0) |
||
70 | + return ret; |
||
71 | + |
||
72 | + led->sc = sc; |
||
73 | + list_add(&led->list, &sc->leds); |
||
74 | |||
75 | /* Configure gpio for output */ |
||
76 | - ath9k_hw_gpio_request_out(ah, ah->led_pin, "ath9k-led", |
||
77 | + ath9k_hw_gpio_request_out(sc->sc_ah, gpio->gpio, gpio->name, |
||
78 | AR_GPIO_OUTPUT_MUX_AS_OUTPUT); |
||
79 | |||
80 | - /* LED off, active low */ |
||
81 | - ath9k_hw_set_gpio(ah, ah->led_pin, ah->config.led_active_high ? 0 : 1); |
||
82 | + /* LED off */ |
||
83 | + ath9k_hw_set_gpio(sc->sc_ah, gpio->gpio, gpio->active_low); |
||
84 | + |
||
85 | + return 0; |
||
86 | } |
||
87 | |||
88 | -static void ath_led_brightness(struct led_classdev *led_cdev, |
||
89 | - enum led_brightness brightness) |
||
90 | +int ath_create_gpio_led(struct ath_softc *sc, int gpio_num, const char *name, |
||
91 | + const char *trigger, bool active_low) |
||
92 | { |
||
93 | - struct ath_softc *sc = container_of(led_cdev, struct ath_softc, led_cdev); |
||
94 | - u32 val = (brightness == LED_OFF); |
||
95 | + struct ath_led *led; |
||
96 | + struct gpio_led *gpio; |
||
97 | + char *_name; |
||
98 | + int ret; |
||
99 | |||
100 | - if (sc->sc_ah->config.led_active_high) |
||
101 | - val = !val; |
||
102 | + led = kzalloc(sizeof(*led) + sizeof(*gpio) + strlen(name) + 1, |
||
103 | + GFP_KERNEL); |
||
104 | + if (!led) |
||
105 | + return -ENOMEM; |
||
106 | + |
||
107 | + led->gpio = gpio = (struct gpio_led *) (led + 1); |
||
108 | + _name = (char *) (led->gpio + 1); |
||
109 | + |
||
110 | + strcpy(_name, name); |
||
111 | + gpio->name = _name; |
||
112 | + gpio->gpio = gpio_num; |
||
113 | + gpio->active_low = active_low; |
||
114 | + gpio->default_trigger = trigger; |
||
115 | + |
||
116 | + ret = ath_add_led(sc, led); |
||
117 | + if (unlikely(ret < 0)) |
||
118 | + kfree(led); |
||
119 | |||
120 | - ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, val); |
||
121 | + return ret; |
||
122 | } |
||
123 | |||
124 | void ath_deinit_leds(struct ath_softc *sc) |
||
125 | { |
||
126 | - if (!sc->led_registered) |
||
127 | - return; |
||
128 | + struct ath_led *led; |
||
129 | |||
130 | - ath_led_brightness(&sc->led_cdev, LED_OFF); |
||
131 | - led_classdev_unregister(&sc->led_cdev); |
||
132 | - |
||
133 | - ath9k_hw_gpio_free(sc->sc_ah, sc->sc_ah->led_pin); |
||
134 | + while (!list_empty(&sc->leds)) { |
||
135 | + led = list_first_entry(&sc->leds, struct ath_led, list); |
||
136 | + list_del(&led->list); |
||
137 | + ath_led_brightness(&led->cdev, LED_OFF); |
||
138 | + led_classdev_unregister(&led->cdev); |
||
139 | + ath9k_hw_gpio_free(sc->sc_ah, led->gpio->gpio); |
||
140 | + kfree(led); |
||
141 | + } |
||
142 | } |
||
143 | |||
144 | void ath_init_leds(struct ath_softc *sc) |
||
145 | { |
||
146 | - int ret; |
||
147 | + char led_name[32]; |
||
148 | + const char *trigger; |
||
149 | + |
||
150 | + INIT_LIST_HEAD(&sc->leds); |
||
151 | |||
152 | if (AR_SREV_9100(sc->sc_ah)) |
||
153 | return; |
||
154 | |||
155 | ath_fill_led_pin(sc); |
||
156 | |||
157 | - if (!ath9k_led_blink) |
||
158 | - sc->led_cdev.default_trigger = |
||
159 | - ieee80211_get_radio_led_name(sc->hw); |
||
160 | - |
||
161 | - snprintf(sc->led_name, sizeof(sc->led_name), |
||
162 | - "ath9k-%s", wiphy_name(sc->hw->wiphy)); |
||
163 | - sc->led_cdev.name = sc->led_name; |
||
164 | - sc->led_cdev.brightness_set = ath_led_brightness; |
||
165 | + snprintf(led_name, sizeof(led_name), "ath9k-%s", |
||
166 | + wiphy_name(sc->hw->wiphy)); |
||
167 | |||
168 | - ret = led_classdev_register(wiphy_dev(sc->hw->wiphy), &sc->led_cdev); |
||
169 | - if (ret < 0) |
||
170 | - return; |
||
171 | + if (ath9k_led_blink) |
||
172 | + trigger = sc->led_default_trigger; |
||
173 | + else |
||
174 | + trigger = ieee80211_get_radio_led_name(sc->hw); |
||
175 | |||
176 | - sc->led_registered = true; |
||
177 | + ath_create_gpio_led(sc, sc->sc_ah->led_pin, led_name, trigger, |
||
178 | + !sc->sc_ah->config.led_active_high); |
||
179 | } |
||
180 | #endif |
||
181 | |||
182 | --- a/drivers/net/wireless/ath/ath9k/init.c |
||
183 | +++ b/drivers/net/wireless/ath/ath9k/init.c |
||
184 | @@ -1000,7 +1000,7 @@ int ath9k_init_device(u16 devid, struct |
||
185 | |||
186 | #ifdef CPTCFG_MAC80211_LEDS |
||
187 | /* must be initialized before ieee80211_register_hw */ |
||
188 | - sc->led_cdev.default_trigger = ieee80211_create_tpt_led_trigger(sc->hw, |
||
189 | + sc->led_default_trigger = ieee80211_create_tpt_led_trigger(sc->hw, |
||
190 | IEEE80211_TPT_LEDTRIG_FL_RADIO, ath9k_tpt_blink, |
||
191 | ARRAY_SIZE(ath9k_tpt_blink)); |
||
192 | #endif |
||
193 | --- a/drivers/net/wireless/ath/ath9k/debug.c |
||
194 | +++ b/drivers/net/wireless/ath/ath9k/debug.c |
||
195 | @@ -1466,6 +1466,61 @@ static const struct file_operations fops |
||
196 | .llseek = default_llseek, |
||
197 | }; |
||
198 | |||
199 | +#ifdef CONFIG_MAC80211_LEDS |
||
200 | + |
||
201 | +static ssize_t write_file_gpio_led(struct file *file, const char __user *ubuf, |
||
202 | + size_t count, loff_t *ppos) |
||
203 | +{ |
||
204 | + struct ath_softc *sc = file->private_data; |
||
205 | + char buf[32], *str, *name, *c; |
||
206 | + ssize_t len; |
||
207 | + unsigned int gpio; |
||
208 | + bool active_low = false; |
||
209 | + |
||
210 | + len = min(count, sizeof(buf) - 1); |
||
211 | + if (copy_from_user(buf, ubuf, len)) |
||
212 | + return -EFAULT; |
||
213 | + |
||
214 | + buf[len] = '\0'; |
||
215 | + name = strchr(buf, ','); |
||
216 | + if (!name) |
||
217 | + return -EINVAL; |
||
218 | + |
||
219 | + *(name++) = 0; |
||
220 | + if (!*name) |
||
221 | + return -EINVAL; |
||
222 | + |
||
223 | + c = strchr(name, '\n'); |
||
224 | + if (c) |
||
225 | + *c = 0; |
||
226 | + |
||
227 | + str = buf; |
||
228 | + if (*str == '!') { |
||
229 | + str++; |
||
230 | + active_low = true; |
||
231 | + } |
||
232 | + |
||
233 | + if (kstrtouint(str, 0, &gpio) < 0) |
||
234 | + return -EINVAL; |
||
235 | + |
||
236 | + if (gpio >= sc->sc_ah->caps.num_gpio_pins) |
||
237 | + return -EINVAL; |
||
238 | + |
||
239 | + if (ath_create_gpio_led(sc, gpio, name, NULL, active_low) < 0) |
||
240 | + return -EINVAL; |
||
241 | + |
||
242 | + return count; |
||
243 | +} |
||
244 | + |
||
245 | +static const struct file_operations fops_gpio_led = { |
||
246 | + .write = write_file_gpio_led, |
||
247 | + .open = simple_open, |
||
248 | + .owner = THIS_MODULE, |
||
249 | + .llseek = default_llseek, |
||
250 | +}; |
||
251 | + |
||
252 | +#endif |
||
253 | + |
||
254 | |||
255 | int ath9k_init_debug(struct ath_hw *ah) |
||
256 | { |
||
257 | @@ -1490,6 +1545,10 @@ int ath9k_init_debug(struct ath_hw *ah) |
||
258 | &fops_eeprom); |
||
259 | debugfs_create_file("chanbw", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, |
||
260 | sc, &fops_chanbw); |
||
261 | +#ifdef CONFIG_MAC80211_LEDS |
||
262 | + debugfs_create_file("gpio_led", S_IWUSR, |
||
263 | + sc->debug.debugfs_phy, sc, &fops_gpio_led); |
||
264 | +#endif |
||
265 | debugfs_create_devm_seqfile(sc->dev, "dma", sc->debug.debugfs_phy, |
||
266 | read_file_dma); |
||
267 | debugfs_create_devm_seqfile(sc->dev, "interrupt", sc->debug.debugfs_phy, |