summaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--net/mac80211/ieee80211_i.h7
-rw-r--r--net/mac80211/led.c239
-rw-r--r--net/mac80211/led.h44
-rw-r--r--net/mac80211/main.c4
4 files changed, 194 insertions, 100 deletions
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index ca00127497f8..241b74f3bd81 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -1260,10 +1260,11 @@ struct ieee80211_local {
1260 struct mutex chanctx_mtx; 1260 struct mutex chanctx_mtx;
1261 1261
1262#ifdef CONFIG_MAC80211_LEDS 1262#ifdef CONFIG_MAC80211_LEDS
1263 struct led_trigger *tx_led, *rx_led, *assoc_led, *radio_led; 1263 struct led_trigger tx_led, rx_led, assoc_led, radio_led;
1264 struct led_trigger tpt_led;
1265 atomic_t tx_led_active, rx_led_active, assoc_led_active;
1266 atomic_t radio_led_active, tpt_led_active;
1264 struct tpt_led_trigger *tpt_led_trigger; 1267 struct tpt_led_trigger *tpt_led_trigger;
1265 char tx_led_name[32], rx_led_name[32],
1266 assoc_led_name[32], radio_led_name[32];
1267#endif 1268#endif
1268 1269
1269#ifdef CONFIG_MAC80211_DEBUG_COUNTERS 1270#ifdef CONFIG_MAC80211_DEBUG_COUNTERS
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;
diff --git a/net/mac80211/led.h b/net/mac80211/led.h
index 89f4344f13b9..a7893a1ac98b 100644
--- a/net/mac80211/led.h
+++ b/net/mac80211/led.h
@@ -11,25 +11,42 @@
11#include <linux/leds.h> 11#include <linux/leds.h>
12#include "ieee80211_i.h" 12#include "ieee80211_i.h"
13 13
14#define MAC80211_BLINK_DELAY 50 /* ms */
15
16static inline void ieee80211_led_rx(struct ieee80211_local *local)
17{
18#ifdef CONFIG_MAC80211_LEDS
19 unsigned long led_delay = MAC80211_BLINK_DELAY;
20
21 if (!atomic_read(&local->rx_led_active))
22 return;
23 led_trigger_blink_oneshot(&local->rx_led, &led_delay, &led_delay, 0);
24#endif
25}
26
27static inline void ieee80211_led_tx(struct ieee80211_local *local)
28{
29#ifdef CONFIG_MAC80211_LEDS
30 unsigned long led_delay = MAC80211_BLINK_DELAY;
31
32 if (!atomic_read(&local->tx_led_active))
33 return;
34 led_trigger_blink_oneshot(&local->tx_led, &led_delay, &led_delay, 0);
35#endif
36}
37
14#ifdef CONFIG_MAC80211_LEDS 38#ifdef CONFIG_MAC80211_LEDS
15void ieee80211_led_rx(struct ieee80211_local *local);
16void ieee80211_led_tx(struct ieee80211_local *local);
17void ieee80211_led_assoc(struct ieee80211_local *local, 39void ieee80211_led_assoc(struct ieee80211_local *local,
18 bool associated); 40 bool associated);
19void ieee80211_led_radio(struct ieee80211_local *local, 41void ieee80211_led_radio(struct ieee80211_local *local,
20 bool enabled); 42 bool enabled);
21void ieee80211_led_names(struct ieee80211_local *local); 43void ieee80211_alloc_led_names(struct ieee80211_local *local);
44void ieee80211_free_led_names(struct ieee80211_local *local);
22void ieee80211_led_init(struct ieee80211_local *local); 45void ieee80211_led_init(struct ieee80211_local *local);
23void ieee80211_led_exit(struct ieee80211_local *local); 46void ieee80211_led_exit(struct ieee80211_local *local);
24void ieee80211_mod_tpt_led_trig(struct ieee80211_local *local, 47void ieee80211_mod_tpt_led_trig(struct ieee80211_local *local,
25 unsigned int types_on, unsigned int types_off); 48 unsigned int types_on, unsigned int types_off);
26#else 49#else
27static inline void ieee80211_led_rx(struct ieee80211_local *local)
28{
29}
30static inline void ieee80211_led_tx(struct ieee80211_local *local)
31{
32}
33static inline void ieee80211_led_assoc(struct ieee80211_local *local, 50static inline void ieee80211_led_assoc(struct ieee80211_local *local,
34 bool associated) 51 bool associated)
35{ 52{
@@ -38,7 +55,10 @@ static inline void ieee80211_led_radio(struct ieee80211_local *local,
38 bool enabled) 55 bool enabled)
39{ 56{
40} 57}
41static inline void ieee80211_led_names(struct ieee80211_local *local) 58static inline void ieee80211_alloc_led_names(struct ieee80211_local *local)
59{
60}
61static inline void ieee80211_free_led_names(struct ieee80211_local *local)
42{ 62{
43} 63}
44static inline void ieee80211_led_init(struct ieee80211_local *local) 64static inline void ieee80211_led_init(struct ieee80211_local *local)
@@ -58,7 +78,7 @@ static inline void
58ieee80211_tpt_led_trig_tx(struct ieee80211_local *local, __le16 fc, int bytes) 78ieee80211_tpt_led_trig_tx(struct ieee80211_local *local, __le16 fc, int bytes)
59{ 79{
60#ifdef CONFIG_MAC80211_LEDS 80#ifdef CONFIG_MAC80211_LEDS
61 if (local->tpt_led_trigger && ieee80211_is_data(fc)) 81 if (ieee80211_is_data(fc) && atomic_read(&local->tpt_led_active))
62 local->tpt_led_trigger->tx_bytes += bytes; 82 local->tpt_led_trigger->tx_bytes += bytes;
63#endif 83#endif
64} 84}
@@ -67,7 +87,7 @@ static inline void
67ieee80211_tpt_led_trig_rx(struct ieee80211_local *local, __le16 fc, int bytes) 87ieee80211_tpt_led_trig_rx(struct ieee80211_local *local, __le16 fc, int bytes)
68{ 88{
69#ifdef CONFIG_MAC80211_LEDS 89#ifdef CONFIG_MAC80211_LEDS
70 if (local->tpt_led_trigger && ieee80211_is_data(fc)) 90 if (ieee80211_is_data(fc) && atomic_read(&local->tpt_led_active))
71 local->tpt_led_trigger->rx_bytes += bytes; 91 local->tpt_led_trigger->rx_bytes += bytes;
72#endif 92#endif
73} 93}
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index b144de971366..effe9d39cd7e 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -643,7 +643,7 @@ struct ieee80211_hw *ieee80211_alloc_hw_nm(size_t priv_data_len,
643 skb_queue_head_init(&local->skb_queue); 643 skb_queue_head_init(&local->skb_queue);
644 skb_queue_head_init(&local->skb_queue_unreliable); 644 skb_queue_head_init(&local->skb_queue_unreliable);
645 645
646 ieee80211_led_names(local); 646 ieee80211_alloc_led_names(local);
647 647
648 ieee80211_roc_setup(local); 648 ieee80211_roc_setup(local);
649 649
@@ -1207,6 +1207,8 @@ void ieee80211_free_hw(struct ieee80211_hw *hw)
1207 1207
1208 sta_info_stop(local); 1208 sta_info_stop(local);
1209 1209
1210 ieee80211_free_led_names(local);
1211
1210 wiphy_free(local->hw.wiphy); 1212 wiphy_free(local->hw.wiphy);
1211} 1213}
1212EXPORT_SYMBOL(ieee80211_free_hw); 1214EXPORT_SYMBOL(ieee80211_free_hw);