1d2912cb1SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
22c8dccc7SJohannes Berg /*
32c8dccc7SJohannes Berg * Copyright 2006, Johannes Berg <johannes@sipsolutions.net>
42c8dccc7SJohannes Berg */
52c8dccc7SJohannes Berg
62c8dccc7SJohannes Berg /* just for IFNAMSIZ */
72c8dccc7SJohannes Berg #include <linux/if.h>
85a0e3ad6STejun Heo #include <linux/slab.h>
9bc3b2d7fSPaul Gortmaker #include <linux/export.h>
102c8dccc7SJohannes Berg #include "led.h"
112c8dccc7SJohannes Berg
ieee80211_led_assoc(struct ieee80211_local * local,bool associated)122c8dccc7SJohannes Berg void ieee80211_led_assoc(struct ieee80211_local *local, bool associated)
132c8dccc7SJohannes Berg {
148d5c2585SJohannes Berg if (!atomic_read(&local->assoc_led_active))
152c8dccc7SJohannes Berg return;
162c8dccc7SJohannes Berg if (associated)
178d5c2585SJohannes Berg led_trigger_event(&local->assoc_led, LED_FULL);
182c8dccc7SJohannes Berg else
198d5c2585SJohannes Berg led_trigger_event(&local->assoc_led, LED_OFF);
202c8dccc7SJohannes Berg }
212c8dccc7SJohannes Berg
ieee80211_led_radio(struct ieee80211_local * local,bool enabled)222c8dccc7SJohannes Berg void ieee80211_led_radio(struct ieee80211_local *local, bool enabled)
232c8dccc7SJohannes Berg {
248d5c2585SJohannes Berg if (!atomic_read(&local->radio_led_active))
252c8dccc7SJohannes Berg return;
262c8dccc7SJohannes Berg if (enabled)
278d5c2585SJohannes Berg led_trigger_event(&local->radio_led, LED_FULL);
282c8dccc7SJohannes Berg else
298d5c2585SJohannes Berg led_trigger_event(&local->radio_led, LED_OFF);
302c8dccc7SJohannes Berg }
312c8dccc7SJohannes Berg
ieee80211_alloc_led_names(struct ieee80211_local * local)328d5c2585SJohannes Berg void ieee80211_alloc_led_names(struct ieee80211_local *local)
33fe67c913SJohannes Berg {
348d5c2585SJohannes Berg local->rx_led.name = kasprintf(GFP_KERNEL, "%srx",
358d5c2585SJohannes Berg wiphy_name(local->hw.wiphy));
368d5c2585SJohannes Berg local->tx_led.name = kasprintf(GFP_KERNEL, "%stx",
378d5c2585SJohannes Berg wiphy_name(local->hw.wiphy));
388d5c2585SJohannes Berg local->assoc_led.name = kasprintf(GFP_KERNEL, "%sassoc",
398d5c2585SJohannes Berg wiphy_name(local->hw.wiphy));
408d5c2585SJohannes Berg local->radio_led.name = kasprintf(GFP_KERNEL, "%sradio",
418d5c2585SJohannes Berg wiphy_name(local->hw.wiphy));
428d5c2585SJohannes Berg }
438d5c2585SJohannes Berg
ieee80211_free_led_names(struct ieee80211_local * local)448d5c2585SJohannes Berg void ieee80211_free_led_names(struct ieee80211_local *local)
458d5c2585SJohannes Berg {
468d5c2585SJohannes Berg kfree(local->rx_led.name);
478d5c2585SJohannes Berg kfree(local->tx_led.name);
488d5c2585SJohannes Berg kfree(local->assoc_led.name);
498d5c2585SJohannes Berg kfree(local->radio_led.name);
508d5c2585SJohannes Berg }
518d5c2585SJohannes Berg
ieee80211_tx_led_activate(struct led_classdev * led_cdev)522282e125SUwe Kleine-König static int ieee80211_tx_led_activate(struct led_classdev *led_cdev)
538d5c2585SJohannes Berg {
548d5c2585SJohannes Berg struct ieee80211_local *local = container_of(led_cdev->trigger,
558d5c2585SJohannes Berg struct ieee80211_local,
568d5c2585SJohannes Berg tx_led);
578d5c2585SJohannes Berg
588d5c2585SJohannes Berg atomic_inc(&local->tx_led_active);
592282e125SUwe Kleine-König
602282e125SUwe Kleine-König return 0;
618d5c2585SJohannes Berg }
628d5c2585SJohannes Berg
ieee80211_tx_led_deactivate(struct led_classdev * led_cdev)638d5c2585SJohannes Berg static void ieee80211_tx_led_deactivate(struct led_classdev *led_cdev)
648d5c2585SJohannes Berg {
658d5c2585SJohannes Berg struct ieee80211_local *local = container_of(led_cdev->trigger,
668d5c2585SJohannes Berg struct ieee80211_local,
678d5c2585SJohannes Berg tx_led);
688d5c2585SJohannes Berg
698d5c2585SJohannes Berg atomic_dec(&local->tx_led_active);
708d5c2585SJohannes Berg }
718d5c2585SJohannes Berg
ieee80211_rx_led_activate(struct led_classdev * led_cdev)722282e125SUwe Kleine-König static int ieee80211_rx_led_activate(struct led_classdev *led_cdev)
738d5c2585SJohannes Berg {
748d5c2585SJohannes Berg struct ieee80211_local *local = container_of(led_cdev->trigger,
758d5c2585SJohannes Berg struct ieee80211_local,
768d5c2585SJohannes Berg rx_led);
778d5c2585SJohannes Berg
788d5c2585SJohannes Berg atomic_inc(&local->rx_led_active);
792282e125SUwe Kleine-König
802282e125SUwe Kleine-König return 0;
818d5c2585SJohannes Berg }
828d5c2585SJohannes Berg
ieee80211_rx_led_deactivate(struct led_classdev * led_cdev)838d5c2585SJohannes Berg static void ieee80211_rx_led_deactivate(struct led_classdev *led_cdev)
848d5c2585SJohannes Berg {
858d5c2585SJohannes Berg struct ieee80211_local *local = container_of(led_cdev->trigger,
868d5c2585SJohannes Berg struct ieee80211_local,
878d5c2585SJohannes Berg rx_led);
888d5c2585SJohannes Berg
898d5c2585SJohannes Berg atomic_dec(&local->rx_led_active);
908d5c2585SJohannes Berg }
918d5c2585SJohannes Berg
ieee80211_assoc_led_activate(struct led_classdev * led_cdev)922282e125SUwe Kleine-König static int ieee80211_assoc_led_activate(struct led_classdev *led_cdev)
938d5c2585SJohannes Berg {
948d5c2585SJohannes Berg struct ieee80211_local *local = container_of(led_cdev->trigger,
958d5c2585SJohannes Berg struct ieee80211_local,
968d5c2585SJohannes Berg assoc_led);
978d5c2585SJohannes Berg
988d5c2585SJohannes Berg atomic_inc(&local->assoc_led_active);
992282e125SUwe Kleine-König
1002282e125SUwe Kleine-König return 0;
1018d5c2585SJohannes Berg }
1028d5c2585SJohannes Berg
ieee80211_assoc_led_deactivate(struct led_classdev * led_cdev)1038d5c2585SJohannes Berg static void ieee80211_assoc_led_deactivate(struct led_classdev *led_cdev)
1048d5c2585SJohannes Berg {
1058d5c2585SJohannes Berg struct ieee80211_local *local = container_of(led_cdev->trigger,
1068d5c2585SJohannes Berg struct ieee80211_local,
1078d5c2585SJohannes Berg assoc_led);
1088d5c2585SJohannes Berg
1098d5c2585SJohannes Berg atomic_dec(&local->assoc_led_active);
1108d5c2585SJohannes Berg }
1118d5c2585SJohannes Berg
ieee80211_radio_led_activate(struct led_classdev * led_cdev)1122282e125SUwe Kleine-König static int ieee80211_radio_led_activate(struct led_classdev *led_cdev)
1138d5c2585SJohannes Berg {
1148d5c2585SJohannes Berg struct ieee80211_local *local = container_of(led_cdev->trigger,
1158d5c2585SJohannes Berg struct ieee80211_local,
1168d5c2585SJohannes Berg radio_led);
1178d5c2585SJohannes Berg
1188d5c2585SJohannes Berg atomic_inc(&local->radio_led_active);
1192282e125SUwe Kleine-König
1202282e125SUwe Kleine-König return 0;
1218d5c2585SJohannes Berg }
1228d5c2585SJohannes Berg
ieee80211_radio_led_deactivate(struct led_classdev * led_cdev)1238d5c2585SJohannes Berg static void ieee80211_radio_led_deactivate(struct led_classdev *led_cdev)
1248d5c2585SJohannes Berg {
1258d5c2585SJohannes Berg struct ieee80211_local *local = container_of(led_cdev->trigger,
1268d5c2585SJohannes Berg struct ieee80211_local,
1278d5c2585SJohannes Berg radio_led);
1288d5c2585SJohannes Berg
1298d5c2585SJohannes Berg atomic_dec(&local->radio_led_active);
1308d5c2585SJohannes Berg }
1318d5c2585SJohannes Berg
ieee80211_tpt_led_activate(struct led_classdev * led_cdev)1322282e125SUwe Kleine-König static int ieee80211_tpt_led_activate(struct led_classdev *led_cdev)
1338d5c2585SJohannes Berg {
1348d5c2585SJohannes Berg struct ieee80211_local *local = container_of(led_cdev->trigger,
1358d5c2585SJohannes Berg struct ieee80211_local,
1368d5c2585SJohannes Berg tpt_led);
1378d5c2585SJohannes Berg
1388d5c2585SJohannes Berg atomic_inc(&local->tpt_led_active);
1392282e125SUwe Kleine-König
1402282e125SUwe Kleine-König return 0;
1418d5c2585SJohannes Berg }
1428d5c2585SJohannes Berg
ieee80211_tpt_led_deactivate(struct led_classdev * led_cdev)1438d5c2585SJohannes Berg static void ieee80211_tpt_led_deactivate(struct led_classdev *led_cdev)
1448d5c2585SJohannes Berg {
1458d5c2585SJohannes Berg struct ieee80211_local *local = container_of(led_cdev->trigger,
1468d5c2585SJohannes Berg struct ieee80211_local,
1478d5c2585SJohannes Berg tpt_led);
1488d5c2585SJohannes Berg
1498d5c2585SJohannes Berg atomic_dec(&local->tpt_led_active);
150fe67c913SJohannes Berg }
151fe67c913SJohannes Berg
ieee80211_led_init(struct ieee80211_local * local)1522c8dccc7SJohannes Berg void ieee80211_led_init(struct ieee80211_local *local)
1532c8dccc7SJohannes Berg {
1548d5c2585SJohannes Berg atomic_set(&local->rx_led_active, 0);
1558d5c2585SJohannes Berg local->rx_led.activate = ieee80211_rx_led_activate;
1568d5c2585SJohannes Berg local->rx_led.deactivate = ieee80211_rx_led_deactivate;
1578d5c2585SJohannes Berg if (local->rx_led.name && led_trigger_register(&local->rx_led)) {
1588d5c2585SJohannes Berg kfree(local->rx_led.name);
1598d5c2585SJohannes Berg local->rx_led.name = NULL;
1602c8dccc7SJohannes Berg }
1612c8dccc7SJohannes Berg
1628d5c2585SJohannes Berg atomic_set(&local->tx_led_active, 0);
1638d5c2585SJohannes Berg local->tx_led.activate = ieee80211_tx_led_activate;
1648d5c2585SJohannes Berg local->tx_led.deactivate = ieee80211_tx_led_deactivate;
1658d5c2585SJohannes Berg if (local->tx_led.name && led_trigger_register(&local->tx_led)) {
1668d5c2585SJohannes Berg kfree(local->tx_led.name);
1678d5c2585SJohannes Berg local->tx_led.name = NULL;
1682c8dccc7SJohannes Berg }
1692c8dccc7SJohannes Berg
1708d5c2585SJohannes Berg atomic_set(&local->assoc_led_active, 0);
1718d5c2585SJohannes Berg local->assoc_led.activate = ieee80211_assoc_led_activate;
1728d5c2585SJohannes Berg local->assoc_led.deactivate = ieee80211_assoc_led_deactivate;
1738d5c2585SJohannes Berg if (local->assoc_led.name && led_trigger_register(&local->assoc_led)) {
1748d5c2585SJohannes Berg kfree(local->assoc_led.name);
1758d5c2585SJohannes Berg local->assoc_led.name = NULL;
1762c8dccc7SJohannes Berg }
1772c8dccc7SJohannes Berg
1788d5c2585SJohannes Berg atomic_set(&local->radio_led_active, 0);
1798d5c2585SJohannes Berg local->radio_led.activate = ieee80211_radio_led_activate;
1808d5c2585SJohannes Berg local->radio_led.deactivate = ieee80211_radio_led_deactivate;
1818d5c2585SJohannes Berg if (local->radio_led.name && led_trigger_register(&local->radio_led)) {
1828d5c2585SJohannes Berg kfree(local->radio_led.name);
1838d5c2585SJohannes Berg local->radio_led.name = NULL;
1842c8dccc7SJohannes Berg }
185e1e54068SJohannes Berg
1868d5c2585SJohannes Berg atomic_set(&local->tpt_led_active, 0);
187e1e54068SJohannes Berg if (local->tpt_led_trigger) {
1888d5c2585SJohannes Berg local->tpt_led.activate = ieee80211_tpt_led_activate;
1898d5c2585SJohannes Berg local->tpt_led.deactivate = ieee80211_tpt_led_deactivate;
1908d5c2585SJohannes Berg if (led_trigger_register(&local->tpt_led)) {
191e1e54068SJohannes Berg kfree(local->tpt_led_trigger);
192e1e54068SJohannes Berg local->tpt_led_trigger = NULL;
193e1e54068SJohannes Berg }
194e1e54068SJohannes Berg }
1952c8dccc7SJohannes Berg }
1962c8dccc7SJohannes Berg
ieee80211_led_exit(struct ieee80211_local * local)1972c8dccc7SJohannes Berg void ieee80211_led_exit(struct ieee80211_local *local)
1982c8dccc7SJohannes Berg {
1998d5c2585SJohannes Berg if (local->radio_led.name)
2008d5c2585SJohannes Berg led_trigger_unregister(&local->radio_led);
2018d5c2585SJohannes Berg if (local->assoc_led.name)
2028d5c2585SJohannes Berg led_trigger_unregister(&local->assoc_led);
2038d5c2585SJohannes Berg if (local->tx_led.name)
2048d5c2585SJohannes Berg led_trigger_unregister(&local->tx_led);
2058d5c2585SJohannes Berg if (local->rx_led.name)
2068d5c2585SJohannes Berg led_trigger_unregister(&local->rx_led);
207e1e54068SJohannes Berg
208e1e54068SJohannes Berg if (local->tpt_led_trigger) {
2098d5c2585SJohannes Berg led_trigger_unregister(&local->tpt_led);
210e1e54068SJohannes Berg kfree(local->tpt_led_trigger);
211e1e54068SJohannes Berg }
2122c8dccc7SJohannes Berg }
2132c8dccc7SJohannes Berg
__ieee80211_get_radio_led_name(struct ieee80211_hw * hw)214f5c4ae07SJohannes Berg const char *__ieee80211_get_radio_led_name(struct ieee80211_hw *hw)
2152c8dccc7SJohannes Berg {
2162c8dccc7SJohannes Berg struct ieee80211_local *local = hw_to_local(hw);
2172c8dccc7SJohannes Berg
2188d5c2585SJohannes Berg return local->radio_led.name;
2192c8dccc7SJohannes Berg }
2202c8dccc7SJohannes Berg EXPORT_SYMBOL(__ieee80211_get_radio_led_name);
2212c8dccc7SJohannes Berg
__ieee80211_get_assoc_led_name(struct ieee80211_hw * hw)222f5c4ae07SJohannes Berg const char *__ieee80211_get_assoc_led_name(struct ieee80211_hw *hw)
2232c8dccc7SJohannes Berg {
2242c8dccc7SJohannes Berg struct ieee80211_local *local = hw_to_local(hw);
2252c8dccc7SJohannes Berg
2268d5c2585SJohannes Berg return local->assoc_led.name;
2272c8dccc7SJohannes Berg }
2282c8dccc7SJohannes Berg EXPORT_SYMBOL(__ieee80211_get_assoc_led_name);
2292c8dccc7SJohannes Berg
__ieee80211_get_tx_led_name(struct ieee80211_hw * hw)230f5c4ae07SJohannes Berg const char *__ieee80211_get_tx_led_name(struct ieee80211_hw *hw)
2312c8dccc7SJohannes Berg {
2322c8dccc7SJohannes Berg struct ieee80211_local *local = hw_to_local(hw);
2332c8dccc7SJohannes Berg
2348d5c2585SJohannes Berg return local->tx_led.name;
2352c8dccc7SJohannes Berg }
2362c8dccc7SJohannes Berg EXPORT_SYMBOL(__ieee80211_get_tx_led_name);
2372c8dccc7SJohannes Berg
__ieee80211_get_rx_led_name(struct ieee80211_hw * hw)238f5c4ae07SJohannes Berg const char *__ieee80211_get_rx_led_name(struct ieee80211_hw *hw)
2392c8dccc7SJohannes Berg {
2402c8dccc7SJohannes Berg struct ieee80211_local *local = hw_to_local(hw);
2412c8dccc7SJohannes Berg
2428d5c2585SJohannes Berg return local->rx_led.name;
2432c8dccc7SJohannes Berg }
2442c8dccc7SJohannes Berg EXPORT_SYMBOL(__ieee80211_get_rx_led_name);
245e1e54068SJohannes Berg
tpt_trig_traffic(struct ieee80211_local * local,struct tpt_led_trigger * tpt_trig)246e1e54068SJohannes Berg static unsigned long tpt_trig_traffic(struct ieee80211_local *local,
247e1e54068SJohannes Berg struct tpt_led_trigger *tpt_trig)
248e1e54068SJohannes Berg {
249e1e54068SJohannes Berg unsigned long traffic, delta;
250e1e54068SJohannes Berg
251e1e54068SJohannes Berg traffic = tpt_trig->tx_bytes + tpt_trig->rx_bytes;
252e1e54068SJohannes Berg
253e1e54068SJohannes Berg delta = traffic - tpt_trig->prev_traffic;
254e1e54068SJohannes Berg tpt_trig->prev_traffic = traffic;
255e1e54068SJohannes Berg return DIV_ROUND_UP(delta, 1024 / 8);
256e1e54068SJohannes Berg }
257e1e54068SJohannes Berg
tpt_trig_timer(struct timer_list * t)25834f11cd3SKees Cook static void tpt_trig_timer(struct timer_list *t)
259e1e54068SJohannes Berg {
26034f11cd3SKees Cook struct tpt_led_trigger *tpt_trig = from_timer(tpt_trig, t, timer);
26134f11cd3SKees Cook struct ieee80211_local *local = tpt_trig->local;
262e1e54068SJohannes Berg unsigned long on, off, tpt;
263e1e54068SJohannes Berg int i;
264e1e54068SJohannes Berg
265e1e54068SJohannes Berg if (!tpt_trig->running)
266e1e54068SJohannes Berg return;
267e1e54068SJohannes Berg
268e1e54068SJohannes Berg mod_timer(&tpt_trig->timer, round_jiffies(jiffies + HZ));
269e1e54068SJohannes Berg
270e1e54068SJohannes Berg tpt = tpt_trig_traffic(local, tpt_trig);
271e1e54068SJohannes Berg
272e1e54068SJohannes Berg /* default to just solid on */
273e1e54068SJohannes Berg on = 1;
274e1e54068SJohannes Berg off = 0;
275e1e54068SJohannes Berg
276e1e54068SJohannes Berg for (i = tpt_trig->blink_table_len - 1; i >= 0; i--) {
277e1e54068SJohannes Berg if (tpt_trig->blink_table[i].throughput < 0 ||
278e1e54068SJohannes Berg tpt > tpt_trig->blink_table[i].throughput) {
279e1e54068SJohannes Berg off = tpt_trig->blink_table[i].blink_time / 2;
280e1e54068SJohannes Berg on = tpt_trig->blink_table[i].blink_time - off;
281e1e54068SJohannes Berg break;
282e1e54068SJohannes Berg }
283e1e54068SJohannes Berg }
284e1e54068SJohannes Berg
285*e298d8a3SHans de Goede led_trigger_blink(&local->tpt_led, on, off);
286e1e54068SJohannes Berg }
287e1e54068SJohannes Berg
288f5c4ae07SJohannes Berg const char *
__ieee80211_create_tpt_led_trigger(struct ieee80211_hw * hw,unsigned int flags,const struct ieee80211_tpt_blink * blink_table,unsigned int blink_table_len)289f5c4ae07SJohannes Berg __ieee80211_create_tpt_led_trigger(struct ieee80211_hw *hw,
29006778b1cSJohannes Berg unsigned int flags,
291e1e54068SJohannes Berg const struct ieee80211_tpt_blink *blink_table,
292e1e54068SJohannes Berg unsigned int blink_table_len)
293e1e54068SJohannes Berg {
294e1e54068SJohannes Berg struct ieee80211_local *local = hw_to_local(hw);
295e1e54068SJohannes Berg struct tpt_led_trigger *tpt_trig;
296e1e54068SJohannes Berg
297e1e54068SJohannes Berg if (WARN_ON(local->tpt_led_trigger))
298e1e54068SJohannes Berg return NULL;
299e1e54068SJohannes Berg
300e1e54068SJohannes Berg tpt_trig = kzalloc(sizeof(struct tpt_led_trigger), GFP_KERNEL);
301e1e54068SJohannes Berg if (!tpt_trig)
302e1e54068SJohannes Berg return NULL;
303e1e54068SJohannes Berg
304e1e54068SJohannes Berg snprintf(tpt_trig->name, sizeof(tpt_trig->name),
305e1e54068SJohannes Berg "%stpt", wiphy_name(local->hw.wiphy));
306e1e54068SJohannes Berg
3078d5c2585SJohannes Berg local->tpt_led.name = tpt_trig->name;
308e1e54068SJohannes Berg
309e1e54068SJohannes Berg tpt_trig->blink_table = blink_table;
310e1e54068SJohannes Berg tpt_trig->blink_table_len = blink_table_len;
31167408c8cSJohannes Berg tpt_trig->want = flags;
31234f11cd3SKees Cook tpt_trig->local = local;
313e1e54068SJohannes Berg
31434f11cd3SKees Cook timer_setup(&tpt_trig->timer, tpt_trig_timer, 0);
315e1e54068SJohannes Berg
316e1e54068SJohannes Berg local->tpt_led_trigger = tpt_trig;
317e1e54068SJohannes Berg
318e1e54068SJohannes Berg return tpt_trig->name;
319e1e54068SJohannes Berg }
320e1e54068SJohannes Berg EXPORT_SYMBOL(__ieee80211_create_tpt_led_trigger);
321e1e54068SJohannes Berg
ieee80211_start_tpt_led_trig(struct ieee80211_local * local)32267408c8cSJohannes Berg static void ieee80211_start_tpt_led_trig(struct ieee80211_local *local)
323e1e54068SJohannes Berg {
324e1e54068SJohannes Berg struct tpt_led_trigger *tpt_trig = local->tpt_led_trigger;
325e1e54068SJohannes Berg
32667408c8cSJohannes Berg if (tpt_trig->running)
327e1e54068SJohannes Berg return;
328e1e54068SJohannes Berg
329e1e54068SJohannes Berg /* reset traffic */
330e1e54068SJohannes Berg tpt_trig_traffic(local, tpt_trig);
331e1e54068SJohannes Berg tpt_trig->running = true;
332e1e54068SJohannes Berg
33334f11cd3SKees Cook tpt_trig_timer(&tpt_trig->timer);
334e1e54068SJohannes Berg mod_timer(&tpt_trig->timer, round_jiffies(jiffies + HZ));
335e1e54068SJohannes Berg }
336e1e54068SJohannes Berg
ieee80211_stop_tpt_led_trig(struct ieee80211_local * local)33767408c8cSJohannes Berg static void ieee80211_stop_tpt_led_trig(struct ieee80211_local *local)
338e1e54068SJohannes Berg {
339e1e54068SJohannes Berg struct tpt_led_trigger *tpt_trig = local->tpt_led_trigger;
340e1e54068SJohannes Berg
34167408c8cSJohannes Berg if (!tpt_trig->running)
342e1e54068SJohannes Berg return;
343e1e54068SJohannes Berg
344e1e54068SJohannes Berg tpt_trig->running = false;
345e1e54068SJohannes Berg del_timer_sync(&tpt_trig->timer);
346e1e54068SJohannes Berg
3473f9d9725SJohannes Berg led_trigger_event(&local->tpt_led, LED_OFF);
348e1e54068SJohannes Berg }
34967408c8cSJohannes Berg
ieee80211_mod_tpt_led_trig(struct ieee80211_local * local,unsigned int types_on,unsigned int types_off)35067408c8cSJohannes Berg void ieee80211_mod_tpt_led_trig(struct ieee80211_local *local,
35167408c8cSJohannes Berg unsigned int types_on, unsigned int types_off)
35267408c8cSJohannes Berg {
35367408c8cSJohannes Berg struct tpt_led_trigger *tpt_trig = local->tpt_led_trigger;
35467408c8cSJohannes Berg bool allowed;
35567408c8cSJohannes Berg
35667408c8cSJohannes Berg WARN_ON(types_on & types_off);
35767408c8cSJohannes Berg
35867408c8cSJohannes Berg if (!tpt_trig)
35967408c8cSJohannes Berg return;
36067408c8cSJohannes Berg
36167408c8cSJohannes Berg tpt_trig->active &= ~types_off;
36267408c8cSJohannes Berg tpt_trig->active |= types_on;
36367408c8cSJohannes Berg
36467408c8cSJohannes Berg /*
36567408c8cSJohannes Berg * Regardless of wanted state, we shouldn't blink when
36667408c8cSJohannes Berg * the radio is disabled -- this can happen due to some
36767408c8cSJohannes Berg * code ordering issues with __ieee80211_recalc_idle()
36867408c8cSJohannes Berg * being called before the radio is started.
36967408c8cSJohannes Berg */
37067408c8cSJohannes Berg allowed = tpt_trig->active & IEEE80211_TPT_LEDTRIG_FL_RADIO;
37167408c8cSJohannes Berg
37267408c8cSJohannes Berg if (!allowed || !(tpt_trig->active & tpt_trig->want))
37367408c8cSJohannes Berg ieee80211_stop_tpt_led_trig(local);
37467408c8cSJohannes Berg else
37567408c8cSJohannes Berg ieee80211_start_tpt_led_trig(local);
37667408c8cSJohannes Berg }
377