xref: /openbmc/linux/net/mac80211/led.c (revision 2612e3bbc0386368a850140a6c9b990cd496a5ec)
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