summaryrefslogtreecommitdiffstats
path: root/net/mac80211/led.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2015-04-23 06:19:22 -0400
committerJohannes Berg <johannes.berg@intel.com>2015-05-05 08:21:56 -0400
commit8d5c25856859bd826aca4b88103552a80b344cef (patch)
treeef166e18c83c91618e208e9726084ab77acd388c /net/mac80211/led.c
parentf5c4ae07992ca64d8628a11439c184baf5595e4b (diff)
mac80211: make LED triggering depend on activation
When LED triggers are compiled in, but not used, mac80211 will still call them to update the status. This isn't really a problem for the assoc and radio ones, but the TX/RX (and to a certain extend TPT) ones can be called very frequently (for every packet.) In order to avoid that when they're not used, track their activation and call the corresponding trigger (and in the TPT case, account for throughput) only when the trigger is actually used by an LED. Additionally, make those trigger functions inlines since theyre only used once in the remaining code. Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/mac80211/led.c')
-rw-r--r--net/mac80211/led.c239
1 files changed, 155 insertions, 84 deletions
diff --git a/net/mac80211/led.c b/net/mac80211/led.c
index 3e13eb86f85d..38f05565eaac 100644
--- a/net/mac80211/led.c
+++ b/net/mac80211/led.c
@@ -12,96 +12,175 @@
12#include <linux/export.h> 12#include <linux/export.h>
13#include "led.h" 13#include "led.h"
14 14
15#define MAC80211_BLINK_DELAY 50 /* ms */
16
17void ieee80211_led_rx(struct ieee80211_local *local)
18{
19 unsigned long led_delay = MAC80211_BLINK_DELAY;
20 if (unlikely(!local->rx_led))
21 return;
22 led_trigger_blink_oneshot(local->rx_led, &led_delay, &led_delay, 0);
23}
24
25void ieee80211_led_tx(struct ieee80211_local *local)
26{
27 unsigned long led_delay = MAC80211_BLINK_DELAY;
28 if (unlikely(!local->tx_led))
29 return;
30 led_trigger_blink_oneshot(local->tx_led, &led_delay, &led_delay, 0);
31}
32
33void ieee80211_led_assoc(struct ieee80211_local *local, bool associated) 15void ieee80211_led_assoc(struct ieee80211_local *local, bool associated)
34{ 16{
35 if (unlikely(!local->assoc_led)) 17 if (!atomic_read(&local->assoc_led_active))
36 return; 18 return;
37 if (associated) 19 if (associated)
38 led_trigger_event(local->assoc_led, LED_FULL); 20 led_trigger_event(&local->assoc_led, LED_FULL);
39 else 21 else
40 led_trigger_event(local->assoc_led, LED_OFF); 22 led_trigger_event(&local->assoc_led, LED_OFF);
41} 23}
42 24
43void ieee80211_led_radio(struct ieee80211_local *local, bool enabled) 25void ieee80211_led_radio(struct ieee80211_local *local, bool enabled)
44{ 26{
45 if (unlikely(!local->radio_led)) 27 if (!atomic_read(&local->radio_led_active))
46 return; 28 return;
47 if (enabled) 29 if (enabled)
48 led_trigger_event(local->radio_led, LED_FULL); 30 led_trigger_event(&local->radio_led, LED_FULL);
49 else 31 else
50 led_trigger_event(local->radio_led, LED_OFF); 32 led_trigger_event(&local->radio_led, LED_OFF);
33}
34
35void ieee80211_alloc_led_names(struct ieee80211_local *local)
36{
37 local->rx_led.name = kasprintf(GFP_KERNEL, "%srx",
38 wiphy_name(local->hw.wiphy));
39 local->tx_led.name = kasprintf(GFP_KERNEL, "%stx",
40 wiphy_name(local->hw.wiphy));
41 local->assoc_led.name = kasprintf(GFP_KERNEL, "%sassoc",
42 wiphy_name(local->hw.wiphy));
43 local->radio_led.name = kasprintf(GFP_KERNEL, "%sradio",
44 wiphy_name(local->hw.wiphy));
45}
46
47void ieee80211_free_led_names(struct ieee80211_local *local)
48{
49 kfree(local->rx_led.name);
50 kfree(local->tx_led.name);
51 kfree(local->assoc_led.name);
52 kfree(local->radio_led.name);
53}
54
55static void ieee80211_tx_led_activate(struct led_classdev *led_cdev)
56{
57 struct ieee80211_local *local = container_of(led_cdev->trigger,
58 struct ieee80211_local,
59 tx_led);
60
61 atomic_inc(&local->tx_led_active);
62}
63
64static void ieee80211_tx_led_deactivate(struct led_classdev *led_cdev)
65{
66 struct ieee80211_local *local = container_of(led_cdev->trigger,
67 struct ieee80211_local,
68 tx_led);
69
70 atomic_dec(&local->tx_led_active);
71}
72
73static void ieee80211_rx_led_activate(struct led_classdev *led_cdev)
74{
75 struct ieee80211_local *local = container_of(led_cdev->trigger,
76 struct ieee80211_local,
77 rx_led);
78
79 atomic_inc(&local->rx_led_active);
80}
81
82static void ieee80211_rx_led_deactivate(struct led_classdev *led_cdev)
83{
84 struct ieee80211_local *local = container_of(led_cdev->trigger,
85 struct ieee80211_local,
86 rx_led);
87
88 atomic_dec(&local->rx_led_active);
89}
90
91static void ieee80211_assoc_led_activate(struct led_classdev *led_cdev)
92{
93 struct ieee80211_local *local = container_of(led_cdev->trigger,
94 struct ieee80211_local,
95 assoc_led);
96
97 atomic_inc(&local->assoc_led_active);
98}
99
100static void ieee80211_assoc_led_deactivate(struct led_classdev *led_cdev)
101{
102 struct ieee80211_local *local = container_of(led_cdev->trigger,
103 struct ieee80211_local,
104 assoc_led);
105
106 atomic_dec(&local->assoc_led_active);
107}
108
109static void ieee80211_radio_led_activate(struct led_classdev *led_cdev)
110{
111 struct ieee80211_local *local = container_of(led_cdev->trigger,
112 struct ieee80211_local,
113 radio_led);
114
115 atomic_inc(&local->radio_led_active);
116}
117
118static void ieee80211_radio_led_deactivate(struct led_classdev *led_cdev)
119{
120 struct ieee80211_local *local = container_of(led_cdev->trigger,
121 struct ieee80211_local,
122 radio_led);
123
124 atomic_dec(&local->radio_led_active);
125}
126
127static void ieee80211_tpt_led_activate(struct led_classdev *led_cdev)
128{
129 struct ieee80211_local *local = container_of(led_cdev->trigger,
130 struct ieee80211_local,
131 tpt_led);
132
133 atomic_inc(&local->tpt_led_active);
51} 134}
52 135
53void ieee80211_led_names(struct ieee80211_local *local) 136static void ieee80211_tpt_led_deactivate(struct led_classdev *led_cdev)
54{ 137{
55 snprintf(local->rx_led_name, sizeof(local->rx_led_name), 138 struct ieee80211_local *local = container_of(led_cdev->trigger,
56 "%srx", wiphy_name(local->hw.wiphy)); 139 struct ieee80211_local,
57 snprintf(local->tx_led_name, sizeof(local->tx_led_name), 140 tpt_led);
58 "%stx", wiphy_name(local->hw.wiphy)); 141
59 snprintf(local->assoc_led_name, sizeof(local->assoc_led_name), 142 atomic_dec(&local->tpt_led_active);
60 "%sassoc", wiphy_name(local->hw.wiphy));
61 snprintf(local->radio_led_name, sizeof(local->radio_led_name),
62 "%sradio", wiphy_name(local->hw.wiphy));
63} 143}
64 144
65void ieee80211_led_init(struct ieee80211_local *local) 145void ieee80211_led_init(struct ieee80211_local *local)
66{ 146{
67 local->rx_led = kzalloc(sizeof(struct led_trigger), GFP_KERNEL); 147 atomic_set(&local->rx_led_active, 0);
68 if (local->rx_led) { 148 local->rx_led.activate = ieee80211_rx_led_activate;
69 local->rx_led->name = local->rx_led_name; 149 local->rx_led.deactivate = ieee80211_rx_led_deactivate;
70 if (led_trigger_register(local->rx_led)) { 150 if (local->rx_led.name && led_trigger_register(&local->rx_led)) {
71 kfree(local->rx_led); 151 kfree(local->rx_led.name);
72 local->rx_led = NULL; 152 local->rx_led.name = NULL;
73 }
74 } 153 }
75 154
76 local->tx_led = kzalloc(sizeof(struct led_trigger), GFP_KERNEL); 155 atomic_set(&local->tx_led_active, 0);
77 if (local->tx_led) { 156 local->tx_led.activate = ieee80211_tx_led_activate;
78 local->tx_led->name = local->tx_led_name; 157 local->tx_led.deactivate = ieee80211_tx_led_deactivate;
79 if (led_trigger_register(local->tx_led)) { 158 if (local->tx_led.name && led_trigger_register(&local->tx_led)) {
80 kfree(local->tx_led); 159 kfree(local->tx_led.name);
81 local->tx_led = NULL; 160 local->tx_led.name = NULL;
82 }
83 } 161 }
84 162
85 local->assoc_led = kzalloc(sizeof(struct led_trigger), GFP_KERNEL); 163 atomic_set(&local->assoc_led_active, 0);
86 if (local->assoc_led) { 164 local->assoc_led.activate = ieee80211_assoc_led_activate;
87 local->assoc_led->name = local->assoc_led_name; 165 local->assoc_led.deactivate = ieee80211_assoc_led_deactivate;
88 if (led_trigger_register(local->assoc_led)) { 166 if (local->assoc_led.name && led_trigger_register(&local->assoc_led)) {
89 kfree(local->assoc_led); 167 kfree(local->assoc_led.name);
90 local->assoc_led = NULL; 168 local->assoc_led.name = NULL;
91 }
92 } 169 }
93 170
94 local->radio_led = kzalloc(sizeof(struct led_trigger), GFP_KERNEL); 171 atomic_set(&local->radio_led_active, 0);
95 if (local->radio_led) { 172 local->radio_led.activate = ieee80211_radio_led_activate;
96 local->radio_led->name = local->radio_led_name; 173 local->radio_led.deactivate = ieee80211_radio_led_deactivate;
97 if (led_trigger_register(local->radio_led)) { 174 if (local->radio_led.name && led_trigger_register(&local->radio_led)) {
98 kfree(local->radio_led); 175 kfree(local->radio_led.name);
99 local->radio_led = NULL; 176 local->radio_led.name = NULL;
100 }
101 } 177 }
102 178
179 atomic_set(&local->tpt_led_active, 0);
103 if (local->tpt_led_trigger) { 180 if (local->tpt_led_trigger) {
104 if (led_trigger_register(&local->tpt_led_trigger->trig)) { 181 local->tpt_led.activate = ieee80211_tpt_led_activate;
182 local->tpt_led.deactivate = ieee80211_tpt_led_deactivate;
183 if (led_trigger_register(&local->tpt_led)) {
105 kfree(local->tpt_led_trigger); 184 kfree(local->tpt_led_trigger);
106 local->tpt_led_trigger = NULL; 185 local->tpt_led_trigger = NULL;
107 } 186 }
@@ -110,25 +189,17 @@ void ieee80211_led_init(struct ieee80211_local *local)
110 189
111void ieee80211_led_exit(struct ieee80211_local *local) 190void ieee80211_led_exit(struct ieee80211_local *local)
112{ 191{
113 if (local->radio_led) { 192 if (local->radio_led.name)
114 led_trigger_unregister(local->radio_led); 193 led_trigger_unregister(&local->radio_led);
115 kfree(local->radio_led); 194 if (local->assoc_led.name)
116 } 195 led_trigger_unregister(&local->assoc_led);
117 if (local->assoc_led) { 196 if (local->tx_led.name)
118 led_trigger_unregister(local->assoc_led); 197 led_trigger_unregister(&local->tx_led);
119 kfree(local->assoc_led); 198 if (local->rx_led.name)
120 } 199 led_trigger_unregister(&local->rx_led);
121 if (local->tx_led) {
122 led_trigger_unregister(local->tx_led);
123 kfree(local->tx_led);
124 }
125 if (local->rx_led) {
126 led_trigger_unregister(local->rx_led);
127 kfree(local->rx_led);
128 }
129 200
130 if (local->tpt_led_trigger) { 201 if (local->tpt_led_trigger) {
131 led_trigger_unregister(&local->tpt_led_trigger->trig); 202 led_trigger_unregister(&local->tpt_led);
132 kfree(local->tpt_led_trigger); 203 kfree(local->tpt_led_trigger);
133 } 204 }
134} 205}
@@ -137,7 +208,7 @@ const char *__ieee80211_get_radio_led_name(struct ieee80211_hw *hw)
137{ 208{
138 struct ieee80211_local *local = hw_to_local(hw); 209 struct ieee80211_local *local = hw_to_local(hw);
139 210
140 return local->radio_led_name; 211 return local->radio_led.name;
141} 212}
142EXPORT_SYMBOL(__ieee80211_get_radio_led_name); 213EXPORT_SYMBOL(__ieee80211_get_radio_led_name);
143 214
@@ -145,7 +216,7 @@ const char *__ieee80211_get_assoc_led_name(struct ieee80211_hw *hw)
145{ 216{
146 struct ieee80211_local *local = hw_to_local(hw); 217 struct ieee80211_local *local = hw_to_local(hw);
147 218
148 return local->assoc_led_name; 219 return local->assoc_led.name;
149} 220}
150EXPORT_SYMBOL(__ieee80211_get_assoc_led_name); 221EXPORT_SYMBOL(__ieee80211_get_assoc_led_name);
151 222
@@ -153,7 +224,7 @@ const char *__ieee80211_get_tx_led_name(struct ieee80211_hw *hw)
153{ 224{
154 struct ieee80211_local *local = hw_to_local(hw); 225 struct ieee80211_local *local = hw_to_local(hw);
155 226
156 return local->tx_led_name; 227 return local->tx_led.name;
157} 228}
158EXPORT_SYMBOL(__ieee80211_get_tx_led_name); 229EXPORT_SYMBOL(__ieee80211_get_tx_led_name);
159 230
@@ -161,7 +232,7 @@ const char *__ieee80211_get_rx_led_name(struct ieee80211_hw *hw)
161{ 232{
162 struct ieee80211_local *local = hw_to_local(hw); 233 struct ieee80211_local *local = hw_to_local(hw);
163 234
164 return local->rx_led_name; 235 return local->rx_led.name;
165} 236}
166EXPORT_SYMBOL(__ieee80211_get_rx_led_name); 237EXPORT_SYMBOL(__ieee80211_get_rx_led_name);
167 238
@@ -230,7 +301,7 @@ __ieee80211_create_tpt_led_trigger(struct ieee80211_hw *hw,
230 snprintf(tpt_trig->name, sizeof(tpt_trig->name), 301 snprintf(tpt_trig->name, sizeof(tpt_trig->name),
231 "%stpt", wiphy_name(local->hw.wiphy)); 302 "%stpt", wiphy_name(local->hw.wiphy));
232 303
233 tpt_trig->trig.name = tpt_trig->name; 304 local->tpt_led.name = tpt_trig->name;
234 305
235 tpt_trig->blink_table = blink_table; 306 tpt_trig->blink_table = blink_table;
236 tpt_trig->blink_table_len = blink_table_len; 307 tpt_trig->blink_table_len = blink_table_len;