1f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc/* 2f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc * Copyright 2006, Johannes Berg <johannes@sipsolutions.net> 3f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc * 4f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc * This program is free software; you can redistribute it and/or modify 5f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc * it under the terms of the GNU General Public License version 2 as 6f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc * published by the Free Software Foundation. 7f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc */ 8f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 9f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc/* just for IFNAMSIZ */ 10f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc#include <linux/if.h> 115a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h> 12bc3b2d7fb9b014d75ebb79ba371a763dbab5e8cfPaul Gortmaker#include <linux/export.h> 132c8dccc77420fb7433da5674818959d3499d35beJohannes Berg#include "led.h" 14f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 15e47f2509e5f182f4df144406de6f2bc78179d57eFabio Baltieri#define MAC80211_BLINK_DELAY 50 /* ms */ 16e47f2509e5f182f4df144406de6f2bc78179d57eFabio Baltieri 17f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Bencvoid ieee80211_led_rx(struct ieee80211_local *local) 18f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc{ 19e47f2509e5f182f4df144406de6f2bc78179d57eFabio Baltieri unsigned long led_delay = MAC80211_BLINK_DELAY; 20f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc if (unlikely(!local->rx_led)) 21f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc return; 22e47f2509e5f182f4df144406de6f2bc78179d57eFabio Baltieri led_trigger_blink_oneshot(local->rx_led, &led_delay, &led_delay, 0); 23f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc} 24f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 25e47f2509e5f182f4df144406de6f2bc78179d57eFabio Baltierivoid ieee80211_led_tx(struct ieee80211_local *local) 26f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc{ 27e47f2509e5f182f4df144406de6f2bc78179d57eFabio Baltieri unsigned long led_delay = MAC80211_BLINK_DELAY; 28f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc if (unlikely(!local->tx_led)) 29f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc return; 30e47f2509e5f182f4df144406de6f2bc78179d57eFabio Baltieri led_trigger_blink_oneshot(local->tx_led, &led_delay, &led_delay, 0); 31f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc} 32f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 3347f0c502209056da728e6a306a43d5e19a37f4faMichael Bueschvoid ieee80211_led_assoc(struct ieee80211_local *local, bool associated) 3447f0c502209056da728e6a306a43d5e19a37f4faMichael Buesch{ 3547f0c502209056da728e6a306a43d5e19a37f4faMichael Buesch if (unlikely(!local->assoc_led)) 3647f0c502209056da728e6a306a43d5e19a37f4faMichael Buesch return; 3747f0c502209056da728e6a306a43d5e19a37f4faMichael Buesch if (associated) 3847f0c502209056da728e6a306a43d5e19a37f4faMichael Buesch led_trigger_event(local->assoc_led, LED_FULL); 3947f0c502209056da728e6a306a43d5e19a37f4faMichael Buesch else 4047f0c502209056da728e6a306a43d5e19a37f4faMichael Buesch led_trigger_event(local->assoc_led, LED_OFF); 4147f0c502209056da728e6a306a43d5e19a37f4faMichael Buesch} 4247f0c502209056da728e6a306a43d5e19a37f4faMichael Buesch 43cdcb006fbe7a74b5f7827f5c5c27e11399a2fab7Ivo van Doornvoid ieee80211_led_radio(struct ieee80211_local *local, bool enabled) 44cdcb006fbe7a74b5f7827f5c5c27e11399a2fab7Ivo van Doorn{ 45cdcb006fbe7a74b5f7827f5c5c27e11399a2fab7Ivo van Doorn if (unlikely(!local->radio_led)) 46cdcb006fbe7a74b5f7827f5c5c27e11399a2fab7Ivo van Doorn return; 47cdcb006fbe7a74b5f7827f5c5c27e11399a2fab7Ivo van Doorn if (enabled) 48cdcb006fbe7a74b5f7827f5c5c27e11399a2fab7Ivo van Doorn led_trigger_event(local->radio_led, LED_FULL); 49cdcb006fbe7a74b5f7827f5c5c27e11399a2fab7Ivo van Doorn else 50cdcb006fbe7a74b5f7827f5c5c27e11399a2fab7Ivo van Doorn led_trigger_event(local->radio_led, LED_OFF); 51cdcb006fbe7a74b5f7827f5c5c27e11399a2fab7Ivo van Doorn} 52cdcb006fbe7a74b5f7827f5c5c27e11399a2fab7Ivo van Doorn 53fe67c913f1ec2a01aaa9176c80ef36eaf87d705dJohannes Bergvoid ieee80211_led_names(struct ieee80211_local *local) 54fe67c913f1ec2a01aaa9176c80ef36eaf87d705dJohannes Berg{ 55fe67c913f1ec2a01aaa9176c80ef36eaf87d705dJohannes Berg snprintf(local->rx_led_name, sizeof(local->rx_led_name), 56fe67c913f1ec2a01aaa9176c80ef36eaf87d705dJohannes Berg "%srx", wiphy_name(local->hw.wiphy)); 57fe67c913f1ec2a01aaa9176c80ef36eaf87d705dJohannes Berg snprintf(local->tx_led_name, sizeof(local->tx_led_name), 58fe67c913f1ec2a01aaa9176c80ef36eaf87d705dJohannes Berg "%stx", wiphy_name(local->hw.wiphy)); 59fe67c913f1ec2a01aaa9176c80ef36eaf87d705dJohannes Berg snprintf(local->assoc_led_name, sizeof(local->assoc_led_name), 60fe67c913f1ec2a01aaa9176c80ef36eaf87d705dJohannes Berg "%sassoc", wiphy_name(local->hw.wiphy)); 61fe67c913f1ec2a01aaa9176c80ef36eaf87d705dJohannes Berg snprintf(local->radio_led_name, sizeof(local->radio_led_name), 62fe67c913f1ec2a01aaa9176c80ef36eaf87d705dJohannes Berg "%sradio", wiphy_name(local->hw.wiphy)); 63fe67c913f1ec2a01aaa9176c80ef36eaf87d705dJohannes Berg} 64fe67c913f1ec2a01aaa9176c80ef36eaf87d705dJohannes Berg 65f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Bencvoid ieee80211_led_init(struct ieee80211_local *local) 66f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc{ 67f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc local->rx_led = kzalloc(sizeof(struct led_trigger), GFP_KERNEL); 6847f0c502209056da728e6a306a43d5e19a37f4faMichael Buesch if (local->rx_led) { 6947f0c502209056da728e6a306a43d5e19a37f4faMichael Buesch local->rx_led->name = local->rx_led_name; 7047f0c502209056da728e6a306a43d5e19a37f4faMichael Buesch if (led_trigger_register(local->rx_led)) { 7147f0c502209056da728e6a306a43d5e19a37f4faMichael Buesch kfree(local->rx_led); 7247f0c502209056da728e6a306a43d5e19a37f4faMichael Buesch local->rx_led = NULL; 7347f0c502209056da728e6a306a43d5e19a37f4faMichael Buesch } 74f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc } 75f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 76f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc local->tx_led = kzalloc(sizeof(struct led_trigger), GFP_KERNEL); 7747f0c502209056da728e6a306a43d5e19a37f4faMichael Buesch if (local->tx_led) { 7847f0c502209056da728e6a306a43d5e19a37f4faMichael Buesch local->tx_led->name = local->tx_led_name; 7947f0c502209056da728e6a306a43d5e19a37f4faMichael Buesch if (led_trigger_register(local->tx_led)) { 8047f0c502209056da728e6a306a43d5e19a37f4faMichael Buesch kfree(local->tx_led); 8147f0c502209056da728e6a306a43d5e19a37f4faMichael Buesch local->tx_led = NULL; 8247f0c502209056da728e6a306a43d5e19a37f4faMichael Buesch } 8347f0c502209056da728e6a306a43d5e19a37f4faMichael Buesch } 8447f0c502209056da728e6a306a43d5e19a37f4faMichael Buesch 8547f0c502209056da728e6a306a43d5e19a37f4faMichael Buesch local->assoc_led = kzalloc(sizeof(struct led_trigger), GFP_KERNEL); 8647f0c502209056da728e6a306a43d5e19a37f4faMichael Buesch if (local->assoc_led) { 8747f0c502209056da728e6a306a43d5e19a37f4faMichael Buesch local->assoc_led->name = local->assoc_led_name; 8847f0c502209056da728e6a306a43d5e19a37f4faMichael Buesch if (led_trigger_register(local->assoc_led)) { 8947f0c502209056da728e6a306a43d5e19a37f4faMichael Buesch kfree(local->assoc_led); 9047f0c502209056da728e6a306a43d5e19a37f4faMichael Buesch local->assoc_led = NULL; 9147f0c502209056da728e6a306a43d5e19a37f4faMichael Buesch } 92f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc } 93cdcb006fbe7a74b5f7827f5c5c27e11399a2fab7Ivo van Doorn 94cdcb006fbe7a74b5f7827f5c5c27e11399a2fab7Ivo van Doorn local->radio_led = kzalloc(sizeof(struct led_trigger), GFP_KERNEL); 95cdcb006fbe7a74b5f7827f5c5c27e11399a2fab7Ivo van Doorn if (local->radio_led) { 96cdcb006fbe7a74b5f7827f5c5c27e11399a2fab7Ivo van Doorn local->radio_led->name = local->radio_led_name; 97cdcb006fbe7a74b5f7827f5c5c27e11399a2fab7Ivo van Doorn if (led_trigger_register(local->radio_led)) { 98cdcb006fbe7a74b5f7827f5c5c27e11399a2fab7Ivo van Doorn kfree(local->radio_led); 99cdcb006fbe7a74b5f7827f5c5c27e11399a2fab7Ivo van Doorn local->radio_led = NULL; 100cdcb006fbe7a74b5f7827f5c5c27e11399a2fab7Ivo van Doorn } 101cdcb006fbe7a74b5f7827f5c5c27e11399a2fab7Ivo van Doorn } 102e1e5406854378dfada3f33c7192b012083a5b8e0Johannes Berg 103e1e5406854378dfada3f33c7192b012083a5b8e0Johannes Berg if (local->tpt_led_trigger) { 104e1e5406854378dfada3f33c7192b012083a5b8e0Johannes Berg if (led_trigger_register(&local->tpt_led_trigger->trig)) { 105e1e5406854378dfada3f33c7192b012083a5b8e0Johannes Berg kfree(local->tpt_led_trigger); 106e1e5406854378dfada3f33c7192b012083a5b8e0Johannes Berg local->tpt_led_trigger = NULL; 107e1e5406854378dfada3f33c7192b012083a5b8e0Johannes Berg } 108e1e5406854378dfada3f33c7192b012083a5b8e0Johannes Berg } 109f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc} 110f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 111f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Bencvoid ieee80211_led_exit(struct ieee80211_local *local) 112f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc{ 113cdcb006fbe7a74b5f7827f5c5c27e11399a2fab7Ivo van Doorn if (local->radio_led) { 114cdcb006fbe7a74b5f7827f5c5c27e11399a2fab7Ivo van Doorn led_trigger_unregister(local->radio_led); 115cdcb006fbe7a74b5f7827f5c5c27e11399a2fab7Ivo van Doorn kfree(local->radio_led); 116cdcb006fbe7a74b5f7827f5c5c27e11399a2fab7Ivo van Doorn } 11747f0c502209056da728e6a306a43d5e19a37f4faMichael Buesch if (local->assoc_led) { 11847f0c502209056da728e6a306a43d5e19a37f4faMichael Buesch led_trigger_unregister(local->assoc_led); 11947f0c502209056da728e6a306a43d5e19a37f4faMichael Buesch kfree(local->assoc_led); 12047f0c502209056da728e6a306a43d5e19a37f4faMichael Buesch } 121f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc if (local->tx_led) { 122f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc led_trigger_unregister(local->tx_led); 123f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc kfree(local->tx_led); 124f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc } 125f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc if (local->rx_led) { 126f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc led_trigger_unregister(local->rx_led); 127f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc kfree(local->rx_led); 128f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc } 129e1e5406854378dfada3f33c7192b012083a5b8e0Johannes Berg 130e1e5406854378dfada3f33c7192b012083a5b8e0Johannes Berg if (local->tpt_led_trigger) { 131e1e5406854378dfada3f33c7192b012083a5b8e0Johannes Berg led_trigger_unregister(&local->tpt_led_trigger->trig); 132e1e5406854378dfada3f33c7192b012083a5b8e0Johannes Berg kfree(local->tpt_led_trigger); 133e1e5406854378dfada3f33c7192b012083a5b8e0Johannes Berg } 134f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc} 135f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 136cdcb006fbe7a74b5f7827f5c5c27e11399a2fab7Ivo van Doornchar *__ieee80211_get_radio_led_name(struct ieee80211_hw *hw) 137cdcb006fbe7a74b5f7827f5c5c27e11399a2fab7Ivo van Doorn{ 138cdcb006fbe7a74b5f7827f5c5c27e11399a2fab7Ivo van Doorn struct ieee80211_local *local = hw_to_local(hw); 139cdcb006fbe7a74b5f7827f5c5c27e11399a2fab7Ivo van Doorn 140fe67c913f1ec2a01aaa9176c80ef36eaf87d705dJohannes Berg return local->radio_led_name; 141cdcb006fbe7a74b5f7827f5c5c27e11399a2fab7Ivo van Doorn} 142cdcb006fbe7a74b5f7827f5c5c27e11399a2fab7Ivo van DoornEXPORT_SYMBOL(__ieee80211_get_radio_led_name); 143cdcb006fbe7a74b5f7827f5c5c27e11399a2fab7Ivo van Doorn 14447f0c502209056da728e6a306a43d5e19a37f4faMichael Bueschchar *__ieee80211_get_assoc_led_name(struct ieee80211_hw *hw) 14547f0c502209056da728e6a306a43d5e19a37f4faMichael Buesch{ 14647f0c502209056da728e6a306a43d5e19a37f4faMichael Buesch struct ieee80211_local *local = hw_to_local(hw); 14747f0c502209056da728e6a306a43d5e19a37f4faMichael Buesch 148fe67c913f1ec2a01aaa9176c80ef36eaf87d705dJohannes Berg return local->assoc_led_name; 14947f0c502209056da728e6a306a43d5e19a37f4faMichael Buesch} 15047f0c502209056da728e6a306a43d5e19a37f4faMichael BueschEXPORT_SYMBOL(__ieee80211_get_assoc_led_name); 15147f0c502209056da728e6a306a43d5e19a37f4faMichael Buesch 152f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Bencchar *__ieee80211_get_tx_led_name(struct ieee80211_hw *hw) 153f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc{ 154f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc struct ieee80211_local *local = hw_to_local(hw); 155f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 156fe67c913f1ec2a01aaa9176c80ef36eaf87d705dJohannes Berg return local->tx_led_name; 157f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc} 158f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri BencEXPORT_SYMBOL(__ieee80211_get_tx_led_name); 159f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 160f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Bencchar *__ieee80211_get_rx_led_name(struct ieee80211_hw *hw) 161f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc{ 162f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc struct ieee80211_local *local = hw_to_local(hw); 163f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc 164fe67c913f1ec2a01aaa9176c80ef36eaf87d705dJohannes Berg return local->rx_led_name; 165f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri Benc} 166f0706e828e96d0fa4e80c0d25aa98523f6d589a0Jiri BencEXPORT_SYMBOL(__ieee80211_get_rx_led_name); 167e1e5406854378dfada3f33c7192b012083a5b8e0Johannes Berg 168e1e5406854378dfada3f33c7192b012083a5b8e0Johannes Bergstatic unsigned long tpt_trig_traffic(struct ieee80211_local *local, 169e1e5406854378dfada3f33c7192b012083a5b8e0Johannes Berg struct tpt_led_trigger *tpt_trig) 170e1e5406854378dfada3f33c7192b012083a5b8e0Johannes Berg{ 171e1e5406854378dfada3f33c7192b012083a5b8e0Johannes Berg unsigned long traffic, delta; 172e1e5406854378dfada3f33c7192b012083a5b8e0Johannes Berg 173e1e5406854378dfada3f33c7192b012083a5b8e0Johannes Berg traffic = tpt_trig->tx_bytes + tpt_trig->rx_bytes; 174e1e5406854378dfada3f33c7192b012083a5b8e0Johannes Berg 175e1e5406854378dfada3f33c7192b012083a5b8e0Johannes Berg delta = traffic - tpt_trig->prev_traffic; 176e1e5406854378dfada3f33c7192b012083a5b8e0Johannes Berg tpt_trig->prev_traffic = traffic; 177e1e5406854378dfada3f33c7192b012083a5b8e0Johannes Berg return DIV_ROUND_UP(delta, 1024 / 8); 178e1e5406854378dfada3f33c7192b012083a5b8e0Johannes Berg} 179e1e5406854378dfada3f33c7192b012083a5b8e0Johannes Berg 180e1e5406854378dfada3f33c7192b012083a5b8e0Johannes Bergstatic void tpt_trig_timer(unsigned long data) 181e1e5406854378dfada3f33c7192b012083a5b8e0Johannes Berg{ 182e1e5406854378dfada3f33c7192b012083a5b8e0Johannes Berg struct ieee80211_local *local = (void *)data; 183e1e5406854378dfada3f33c7192b012083a5b8e0Johannes Berg struct tpt_led_trigger *tpt_trig = local->tpt_led_trigger; 184e1e5406854378dfada3f33c7192b012083a5b8e0Johannes Berg struct led_classdev *led_cdev; 185e1e5406854378dfada3f33c7192b012083a5b8e0Johannes Berg unsigned long on, off, tpt; 186e1e5406854378dfada3f33c7192b012083a5b8e0Johannes Berg int i; 187e1e5406854378dfada3f33c7192b012083a5b8e0Johannes Berg 188e1e5406854378dfada3f33c7192b012083a5b8e0Johannes Berg if (!tpt_trig->running) 189e1e5406854378dfada3f33c7192b012083a5b8e0Johannes Berg return; 190e1e5406854378dfada3f33c7192b012083a5b8e0Johannes Berg 191e1e5406854378dfada3f33c7192b012083a5b8e0Johannes Berg mod_timer(&tpt_trig->timer, round_jiffies(jiffies + HZ)); 192e1e5406854378dfada3f33c7192b012083a5b8e0Johannes Berg 193e1e5406854378dfada3f33c7192b012083a5b8e0Johannes Berg tpt = tpt_trig_traffic(local, tpt_trig); 194e1e5406854378dfada3f33c7192b012083a5b8e0Johannes Berg 195e1e5406854378dfada3f33c7192b012083a5b8e0Johannes Berg /* default to just solid on */ 196e1e5406854378dfada3f33c7192b012083a5b8e0Johannes Berg on = 1; 197e1e5406854378dfada3f33c7192b012083a5b8e0Johannes Berg off = 0; 198e1e5406854378dfada3f33c7192b012083a5b8e0Johannes Berg 199e1e5406854378dfada3f33c7192b012083a5b8e0Johannes Berg for (i = tpt_trig->blink_table_len - 1; i >= 0; i--) { 200e1e5406854378dfada3f33c7192b012083a5b8e0Johannes Berg if (tpt_trig->blink_table[i].throughput < 0 || 201e1e5406854378dfada3f33c7192b012083a5b8e0Johannes Berg tpt > tpt_trig->blink_table[i].throughput) { 202e1e5406854378dfada3f33c7192b012083a5b8e0Johannes Berg off = tpt_trig->blink_table[i].blink_time / 2; 203e1e5406854378dfada3f33c7192b012083a5b8e0Johannes Berg on = tpt_trig->blink_table[i].blink_time - off; 204e1e5406854378dfada3f33c7192b012083a5b8e0Johannes Berg break; 205e1e5406854378dfada3f33c7192b012083a5b8e0Johannes Berg } 206e1e5406854378dfada3f33c7192b012083a5b8e0Johannes Berg } 207e1e5406854378dfada3f33c7192b012083a5b8e0Johannes Berg 208e1e5406854378dfada3f33c7192b012083a5b8e0Johannes Berg read_lock(&tpt_trig->trig.leddev_list_lock); 209e1e5406854378dfada3f33c7192b012083a5b8e0Johannes Berg list_for_each_entry(led_cdev, &tpt_trig->trig.led_cdevs, trig_list) 210e1e5406854378dfada3f33c7192b012083a5b8e0Johannes Berg led_blink_set(led_cdev, &on, &off); 211e1e5406854378dfada3f33c7192b012083a5b8e0Johannes Berg read_unlock(&tpt_trig->trig.leddev_list_lock); 212e1e5406854378dfada3f33c7192b012083a5b8e0Johannes Berg} 213e1e5406854378dfada3f33c7192b012083a5b8e0Johannes Berg 21406778b1c383afbdb88ffd837e117bec06a76f450Johannes Bergchar *__ieee80211_create_tpt_led_trigger(struct ieee80211_hw *hw, 21506778b1c383afbdb88ffd837e117bec06a76f450Johannes Berg unsigned int flags, 216e1e5406854378dfada3f33c7192b012083a5b8e0Johannes Berg const struct ieee80211_tpt_blink *blink_table, 217e1e5406854378dfada3f33c7192b012083a5b8e0Johannes Berg unsigned int blink_table_len) 218e1e5406854378dfada3f33c7192b012083a5b8e0Johannes Berg{ 219e1e5406854378dfada3f33c7192b012083a5b8e0Johannes Berg struct ieee80211_local *local = hw_to_local(hw); 220e1e5406854378dfada3f33c7192b012083a5b8e0Johannes Berg struct tpt_led_trigger *tpt_trig; 221e1e5406854378dfada3f33c7192b012083a5b8e0Johannes Berg 222e1e5406854378dfada3f33c7192b012083a5b8e0Johannes Berg if (WARN_ON(local->tpt_led_trigger)) 223e1e5406854378dfada3f33c7192b012083a5b8e0Johannes Berg return NULL; 224e1e5406854378dfada3f33c7192b012083a5b8e0Johannes Berg 225e1e5406854378dfada3f33c7192b012083a5b8e0Johannes Berg tpt_trig = kzalloc(sizeof(struct tpt_led_trigger), GFP_KERNEL); 226e1e5406854378dfada3f33c7192b012083a5b8e0Johannes Berg if (!tpt_trig) 227e1e5406854378dfada3f33c7192b012083a5b8e0Johannes Berg return NULL; 228e1e5406854378dfada3f33c7192b012083a5b8e0Johannes Berg 229e1e5406854378dfada3f33c7192b012083a5b8e0Johannes Berg snprintf(tpt_trig->name, sizeof(tpt_trig->name), 230e1e5406854378dfada3f33c7192b012083a5b8e0Johannes Berg "%stpt", wiphy_name(local->hw.wiphy)); 231e1e5406854378dfada3f33c7192b012083a5b8e0Johannes Berg 232e1e5406854378dfada3f33c7192b012083a5b8e0Johannes Berg tpt_trig->trig.name = tpt_trig->name; 233e1e5406854378dfada3f33c7192b012083a5b8e0Johannes Berg 234e1e5406854378dfada3f33c7192b012083a5b8e0Johannes Berg tpt_trig->blink_table = blink_table; 235e1e5406854378dfada3f33c7192b012083a5b8e0Johannes Berg tpt_trig->blink_table_len = blink_table_len; 23667408c8c7b9daf28b50e33be3541334c07d15789Johannes Berg tpt_trig->want = flags; 237e1e5406854378dfada3f33c7192b012083a5b8e0Johannes Berg 238e1e5406854378dfada3f33c7192b012083a5b8e0Johannes Berg setup_timer(&tpt_trig->timer, tpt_trig_timer, (unsigned long)local); 239e1e5406854378dfada3f33c7192b012083a5b8e0Johannes Berg 240e1e5406854378dfada3f33c7192b012083a5b8e0Johannes Berg local->tpt_led_trigger = tpt_trig; 241e1e5406854378dfada3f33c7192b012083a5b8e0Johannes Berg 242e1e5406854378dfada3f33c7192b012083a5b8e0Johannes Berg return tpt_trig->name; 243e1e5406854378dfada3f33c7192b012083a5b8e0Johannes Berg} 244e1e5406854378dfada3f33c7192b012083a5b8e0Johannes BergEXPORT_SYMBOL(__ieee80211_create_tpt_led_trigger); 245e1e5406854378dfada3f33c7192b012083a5b8e0Johannes Berg 24667408c8c7b9daf28b50e33be3541334c07d15789Johannes Bergstatic void ieee80211_start_tpt_led_trig(struct ieee80211_local *local) 247e1e5406854378dfada3f33c7192b012083a5b8e0Johannes Berg{ 248e1e5406854378dfada3f33c7192b012083a5b8e0Johannes Berg struct tpt_led_trigger *tpt_trig = local->tpt_led_trigger; 249e1e5406854378dfada3f33c7192b012083a5b8e0Johannes Berg 25067408c8c7b9daf28b50e33be3541334c07d15789Johannes Berg if (tpt_trig->running) 251e1e5406854378dfada3f33c7192b012083a5b8e0Johannes Berg return; 252e1e5406854378dfada3f33c7192b012083a5b8e0Johannes Berg 253e1e5406854378dfada3f33c7192b012083a5b8e0Johannes Berg /* reset traffic */ 254e1e5406854378dfada3f33c7192b012083a5b8e0Johannes Berg tpt_trig_traffic(local, tpt_trig); 255e1e5406854378dfada3f33c7192b012083a5b8e0Johannes Berg tpt_trig->running = true; 256e1e5406854378dfada3f33c7192b012083a5b8e0Johannes Berg 257e1e5406854378dfada3f33c7192b012083a5b8e0Johannes Berg tpt_trig_timer((unsigned long)local); 258e1e5406854378dfada3f33c7192b012083a5b8e0Johannes Berg mod_timer(&tpt_trig->timer, round_jiffies(jiffies + HZ)); 259e1e5406854378dfada3f33c7192b012083a5b8e0Johannes Berg} 260e1e5406854378dfada3f33c7192b012083a5b8e0Johannes Berg 26167408c8c7b9daf28b50e33be3541334c07d15789Johannes Bergstatic void ieee80211_stop_tpt_led_trig(struct ieee80211_local *local) 262e1e5406854378dfada3f33c7192b012083a5b8e0Johannes Berg{ 263e1e5406854378dfada3f33c7192b012083a5b8e0Johannes Berg struct tpt_led_trigger *tpt_trig = local->tpt_led_trigger; 264e1e5406854378dfada3f33c7192b012083a5b8e0Johannes Berg struct led_classdev *led_cdev; 265e1e5406854378dfada3f33c7192b012083a5b8e0Johannes Berg 26667408c8c7b9daf28b50e33be3541334c07d15789Johannes Berg if (!tpt_trig->running) 267e1e5406854378dfada3f33c7192b012083a5b8e0Johannes Berg return; 268e1e5406854378dfada3f33c7192b012083a5b8e0Johannes Berg 269e1e5406854378dfada3f33c7192b012083a5b8e0Johannes Berg tpt_trig->running = false; 270e1e5406854378dfada3f33c7192b012083a5b8e0Johannes Berg del_timer_sync(&tpt_trig->timer); 271e1e5406854378dfada3f33c7192b012083a5b8e0Johannes Berg 272e1e5406854378dfada3f33c7192b012083a5b8e0Johannes Berg read_lock(&tpt_trig->trig.leddev_list_lock); 273e1e5406854378dfada3f33c7192b012083a5b8e0Johannes Berg list_for_each_entry(led_cdev, &tpt_trig->trig.led_cdevs, trig_list) 27419cd67e2d51225b164560b54b85f943e07deee8aShuah Khan led_set_brightness(led_cdev, LED_OFF); 275e1e5406854378dfada3f33c7192b012083a5b8e0Johannes Berg read_unlock(&tpt_trig->trig.leddev_list_lock); 276e1e5406854378dfada3f33c7192b012083a5b8e0Johannes Berg} 27767408c8c7b9daf28b50e33be3541334c07d15789Johannes Berg 27867408c8c7b9daf28b50e33be3541334c07d15789Johannes Bergvoid ieee80211_mod_tpt_led_trig(struct ieee80211_local *local, 27967408c8c7b9daf28b50e33be3541334c07d15789Johannes Berg unsigned int types_on, unsigned int types_off) 28067408c8c7b9daf28b50e33be3541334c07d15789Johannes Berg{ 28167408c8c7b9daf28b50e33be3541334c07d15789Johannes Berg struct tpt_led_trigger *tpt_trig = local->tpt_led_trigger; 28267408c8c7b9daf28b50e33be3541334c07d15789Johannes Berg bool allowed; 28367408c8c7b9daf28b50e33be3541334c07d15789Johannes Berg 28467408c8c7b9daf28b50e33be3541334c07d15789Johannes Berg WARN_ON(types_on & types_off); 28567408c8c7b9daf28b50e33be3541334c07d15789Johannes Berg 28667408c8c7b9daf28b50e33be3541334c07d15789Johannes Berg if (!tpt_trig) 28767408c8c7b9daf28b50e33be3541334c07d15789Johannes Berg return; 28867408c8c7b9daf28b50e33be3541334c07d15789Johannes Berg 28967408c8c7b9daf28b50e33be3541334c07d15789Johannes Berg tpt_trig->active &= ~types_off; 29067408c8c7b9daf28b50e33be3541334c07d15789Johannes Berg tpt_trig->active |= types_on; 29167408c8c7b9daf28b50e33be3541334c07d15789Johannes Berg 29267408c8c7b9daf28b50e33be3541334c07d15789Johannes Berg /* 29367408c8c7b9daf28b50e33be3541334c07d15789Johannes Berg * Regardless of wanted state, we shouldn't blink when 29467408c8c7b9daf28b50e33be3541334c07d15789Johannes Berg * the radio is disabled -- this can happen due to some 29567408c8c7b9daf28b50e33be3541334c07d15789Johannes Berg * code ordering issues with __ieee80211_recalc_idle() 29667408c8c7b9daf28b50e33be3541334c07d15789Johannes Berg * being called before the radio is started. 29767408c8c7b9daf28b50e33be3541334c07d15789Johannes Berg */ 29867408c8c7b9daf28b50e33be3541334c07d15789Johannes Berg allowed = tpt_trig->active & IEEE80211_TPT_LEDTRIG_FL_RADIO; 29967408c8c7b9daf28b50e33be3541334c07d15789Johannes Berg 30067408c8c7b9daf28b50e33be3541334c07d15789Johannes Berg if (!allowed || !(tpt_trig->active & tpt_trig->want)) 30167408c8c7b9daf28b50e33be3541334c07d15789Johannes Berg ieee80211_stop_tpt_led_trig(local); 30267408c8c7b9daf28b50e33be3541334c07d15789Johannes Berg else 30367408c8c7b9daf28b50e33be3541334c07d15789Johannes Berg ieee80211_start_tpt_led_trig(local); 30467408c8c7b9daf28b50e33be3541334c07d15789Johannes Berg} 305