Commit 67408c8c7b9daf28b50e33be3541334c07d15789

Authored by Johannes Berg
Committed by John W. Linville
1 parent e1e5406854

mac80211: selective throughput LED trigger active

The throughput LED trigger was always active when
the radio was enabled. In most cases that's likely
the desired behaviour, but iwlwifi requires it to
be only active when one of the virtual interfaces
is actually "connected" in some way.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>

Showing 6 changed files with 76 additions and 18 deletions Side-by-side Diff

include/net/mac80211.h
... ... @@ -1863,13 +1863,26 @@
1863 1863 int blink_time;
1864 1864 };
1865 1865  
  1866 +/**
  1867 + * enum ieee80211_tpt_led_trigger_flags - throughput trigger flags
  1868 + * @IEEE80211_TPT_LEDTRIG_FL_RADIO: enable blinking with radio
  1869 + * @IEEE80211_TPT_LEDTRIG_FL_WORK: enable blinking when working
  1870 + * @IEEE80211_TPT_LEDTRIG_FL_CONNECTED: enable blinking when at least one
  1871 + * interface is connected in some way, including being an AP
  1872 + */
  1873 +enum ieee80211_tpt_led_trigger_flags {
  1874 + IEEE80211_TPT_LEDTRIG_FL_RADIO = BIT(0),
  1875 + IEEE80211_TPT_LEDTRIG_FL_WORK = BIT(1),
  1876 + IEEE80211_TPT_LEDTRIG_FL_CONNECTED = BIT(2),
  1877 +};
  1878 +
1866 1879 #ifdef CONFIG_MAC80211_LEDS
1867 1880 extern char *__ieee80211_get_tx_led_name(struct ieee80211_hw *hw);
1868 1881 extern char *__ieee80211_get_rx_led_name(struct ieee80211_hw *hw);
1869 1882 extern char *__ieee80211_get_assoc_led_name(struct ieee80211_hw *hw);
1870 1883 extern char *__ieee80211_get_radio_led_name(struct ieee80211_hw *hw);
1871 1884 extern char *__ieee80211_create_tpt_led_trigger(
1872   - struct ieee80211_hw *hw,
  1885 + struct ieee80211_hw *hw, unsigned int flags,
1873 1886 const struct ieee80211_tpt_blink *blink_table,
1874 1887 unsigned int blink_table_len);
1875 1888 #endif
... ... @@ -1952,6 +1965,7 @@
1952 1965 /**
1953 1966 * ieee80211_create_tpt_led_trigger - create throughput LED trigger
1954 1967 * @hw: the hardware to create the trigger for
  1968 + * @flags: trigger flags, see &enum ieee80211_tpt_led_trigger_flags
1955 1969 * @blink_table: the blink table -- needs to be ordered by throughput
1956 1970 * @blink_table_len: size of the blink table
1957 1971 *
1958 1972  
... ... @@ -1960,12 +1974,12 @@
1960 1974 * This function must be called before ieee80211_register_hw().
1961 1975 */
1962 1976 static inline char *
1963   -ieee80211_create_tpt_led_trigger(struct ieee80211_hw *hw,
  1977 +ieee80211_create_tpt_led_trigger(struct ieee80211_hw *hw, unsigned int flags,
1964 1978 const struct ieee80211_tpt_blink *blink_table,
1965 1979 unsigned int blink_table_len)
1966 1980 {
1967 1981 #ifdef CONFIG_MAC80211_LEDS
1968   - return __ieee80211_create_tpt_led_trigger(hw, blink_table,
  1982 + return __ieee80211_create_tpt_led_trigger(hw, flags, blink_table,
1969 1983 blink_table_len);
1970 1984 #else
1971 1985 return NULL;
net/mac80211/ieee80211_i.h
... ... @@ -637,9 +637,10 @@
637 637 const struct ieee80211_tpt_blink *blink_table;
638 638 unsigned int blink_table_len;
639 639 struct timer_list timer;
640   - bool running;
641 640 unsigned long prev_traffic;
642 641 unsigned long tx_bytes, rx_bytes;
  642 + unsigned int active, want;
  643 + bool running;
643 644 };
644 645  
645 646 /**
net/mac80211/iface.c
... ... @@ -220,7 +220,8 @@
220 220 /* we're brought up, everything changes */
221 221 hw_reconf_flags = ~0;
222 222 ieee80211_led_radio(local, true);
223   - ieee80211_start_tpt_led_trig(local);
  223 + ieee80211_mod_tpt_led_trig(local,
  224 + IEEE80211_TPT_LEDTRIG_FL_RADIO, 0);
224 225 }
225 226  
226 227 /*
... ... @@ -1265,6 +1266,7 @@
1265 1266 int count = 0;
1266 1267 bool working = false, scanning = false;
1267 1268 struct ieee80211_work *wk;
  1269 + unsigned int led_trig_start = 0, led_trig_stop = 0;
1268 1270  
1269 1271 #ifdef CONFIG_PROVE_LOCKING
1270 1272 WARN_ON(debug_locks && !lockdep_rtnl_is_held() &&
... ... @@ -1313,6 +1315,18 @@
1313 1315 continue;
1314 1316 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_IDLE);
1315 1317 }
  1318 +
  1319 + if (working || scanning)
  1320 + led_trig_start |= IEEE80211_TPT_LEDTRIG_FL_WORK;
  1321 + else
  1322 + led_trig_stop |= IEEE80211_TPT_LEDTRIG_FL_WORK;
  1323 +
  1324 + if (count)
  1325 + led_trig_start |= IEEE80211_TPT_LEDTRIG_FL_CONNECTED;
  1326 + else
  1327 + led_trig_stop |= IEEE80211_TPT_LEDTRIG_FL_CONNECTED;
  1328 +
  1329 + ieee80211_mod_tpt_led_trig(local, led_trig_start, led_trig_stop);
1316 1330  
1317 1331 if (working)
1318 1332 return ieee80211_idle_off(local, "working");
... ... @@ -216,7 +216,7 @@
216 216 }
217 217  
218 218 extern char *__ieee80211_create_tpt_led_trigger(
219   - struct ieee80211_hw *hw,
  219 + struct ieee80211_hw *hw, unsigned int flags,
220 220 const struct ieee80211_tpt_blink *blink_table,
221 221 unsigned int blink_table_len)
222 222 {
... ... @@ -237,6 +237,7 @@
237 237  
238 238 tpt_trig->blink_table = blink_table;
239 239 tpt_trig->blink_table_len = blink_table_len;
  240 + tpt_trig->want = flags;
240 241  
241 242 setup_timer(&tpt_trig->timer, tpt_trig_timer, (unsigned long)local);
242 243  
243 244  
... ... @@ -246,11 +247,11 @@
246 247 }
247 248 EXPORT_SYMBOL(__ieee80211_create_tpt_led_trigger);
248 249  
249   -void ieee80211_start_tpt_led_trig(struct ieee80211_local *local)
  250 +static void ieee80211_start_tpt_led_trig(struct ieee80211_local *local)
250 251 {
251 252 struct tpt_led_trigger *tpt_trig = local->tpt_led_trigger;
252 253  
253   - if (!tpt_trig)
  254 + if (tpt_trig->running)
254 255 return;
255 256  
256 257 /* reset traffic */
257 258  
... ... @@ -261,12 +262,12 @@
261 262 mod_timer(&tpt_trig->timer, round_jiffies(jiffies + HZ));
262 263 }
263 264  
264   -void ieee80211_stop_tpt_led_trig(struct ieee80211_local *local)
  265 +static void ieee80211_stop_tpt_led_trig(struct ieee80211_local *local)
265 266 {
266 267 struct tpt_led_trigger *tpt_trig = local->tpt_led_trigger;
267 268 struct led_classdev *led_cdev;
268 269  
269   - if (!tpt_trig)
  270 + if (!tpt_trig->running)
270 271 return;
271 272  
272 273 tpt_trig->running = false;
... ... @@ -276,5 +277,33 @@
276 277 list_for_each_entry(led_cdev, &tpt_trig->trig.led_cdevs, trig_list)
277 278 led_brightness_set(led_cdev, LED_OFF);
278 279 read_unlock(&tpt_trig->trig.leddev_list_lock);
  280 +}
  281 +
  282 +void ieee80211_mod_tpt_led_trig(struct ieee80211_local *local,
  283 + unsigned int types_on, unsigned int types_off)
  284 +{
  285 + struct tpt_led_trigger *tpt_trig = local->tpt_led_trigger;
  286 + bool allowed;
  287 +
  288 + WARN_ON(types_on & types_off);
  289 +
  290 + if (!tpt_trig)
  291 + return;
  292 +
  293 + tpt_trig->active &= ~types_off;
  294 + tpt_trig->active |= types_on;
  295 +
  296 + /*
  297 + * Regardless of wanted state, we shouldn't blink when
  298 + * the radio is disabled -- this can happen due to some
  299 + * code ordering issues with __ieee80211_recalc_idle()
  300 + * being called before the radio is started.
  301 + */
  302 + allowed = tpt_trig->active & IEEE80211_TPT_LEDTRIG_FL_RADIO;
  303 +
  304 + if (!allowed || !(tpt_trig->active & tpt_trig->want))
  305 + ieee80211_stop_tpt_led_trig(local);
  306 + else
  307 + ieee80211_start_tpt_led_trig(local);
279 308 }
... ... @@ -21,8 +21,8 @@
21 21 void ieee80211_led_names(struct ieee80211_local *local);
22 22 void ieee80211_led_init(struct ieee80211_local *local);
23 23 void ieee80211_led_exit(struct ieee80211_local *local);
24   -void ieee80211_start_tpt_led_trig(struct ieee80211_local *local);
25   -void ieee80211_stop_tpt_led_trig(struct ieee80211_local *local);
  24 +void ieee80211_mod_tpt_led_trig(struct ieee80211_local *local,
  25 + unsigned int types_on, unsigned int types_off);
26 26 #else
27 27 static inline void ieee80211_led_rx(struct ieee80211_local *local)
28 28 {
... ... @@ -47,10 +47,9 @@
47 47 static inline void ieee80211_led_exit(struct ieee80211_local *local)
48 48 {
49 49 }
50   -static inline void ieee80211_start_tpt_led_trig(struct ieee80211_local *local)
51   -{
52   -}
53   -static inline void ieee80211_stop_tpt_led_trig(struct ieee80211_local *local)
  50 +static inline void ieee80211_mod_tpt_led_trig(struct ieee80211_local *local,
  51 + unsigned int types_on,
  52 + unsigned int types_off)
54 53 {
55 54 }
56 55 #endif
... ... @@ -1116,7 +1116,7 @@
1116 1116 void ieee80211_stop_device(struct ieee80211_local *local)
1117 1117 {
1118 1118 ieee80211_led_radio(local, false);
1119   - ieee80211_stop_tpt_led_trig(local);
  1119 + ieee80211_mod_tpt_led_trig(local, 0, IEEE80211_TPT_LEDTRIG_FL_RADIO);
1120 1120  
1121 1121 cancel_work_sync(&local->reconfig_filter);
1122 1122  
... ... @@ -1151,7 +1151,8 @@
1151 1151 }
1152 1152  
1153 1153 ieee80211_led_radio(local, true);
1154   - ieee80211_start_tpt_led_trig(local);
  1154 + ieee80211_mod_tpt_led_trig(local,
  1155 + IEEE80211_TPT_LEDTRIG_FL_RADIO, 0);
1155 1156 }
1156 1157  
1157 1158 /* add interfaces */