summaryrefslogtreecommitdiffstats
path: root/net/mac80211
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2010-11-30 08:59:23 +0100
committerJohn W. Linville <linville@tuxdriver.com>2010-12-22 20:33:37 +0100
commit67408c8c7b9daf28b50e33be3541334c07d15789 (patch)
treeac11ea966add7f7187274fcf9e647c5227099108 /net/mac80211
parentmac80211: add throughput based LED blink trigger (diff)
downloadlinux-67408c8c7b9daf28b50e33be3541334c07d15789.tar.xz
linux-67408c8c7b9daf28b50e33be3541334c07d15789.zip
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>
Diffstat (limited to 'net/mac80211')
-rw-r--r--net/mac80211/ieee80211_i.h3
-rw-r--r--net/mac80211/iface.c16
-rw-r--r--net/mac80211/led.c39
-rw-r--r--net/mac80211/led.h11
-rw-r--r--net/mac80211/util.c5
5 files changed, 59 insertions, 15 deletions
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 523b90be8dc5..3810c72ac062 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -637,9 +637,10 @@ struct tpt_led_trigger {
const struct ieee80211_tpt_blink *blink_table;
unsigned int blink_table_len;
struct timer_list timer;
- bool running;
unsigned long prev_traffic;
unsigned long tx_bytes, rx_bytes;
+ unsigned int active, want;
+ bool running;
};
/**
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 989df7065c21..b6db237672ff 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -220,7 +220,8 @@ static int ieee80211_do_open(struct net_device *dev, bool coming_up)
/* we're brought up, everything changes */
hw_reconf_flags = ~0;
ieee80211_led_radio(local, true);
- ieee80211_start_tpt_led_trig(local);
+ ieee80211_mod_tpt_led_trig(local,
+ IEEE80211_TPT_LEDTRIG_FL_RADIO, 0);
}
/*
@@ -1265,6 +1266,7 @@ u32 __ieee80211_recalc_idle(struct ieee80211_local *local)
int count = 0;
bool working = false, scanning = false;
struct ieee80211_work *wk;
+ unsigned int led_trig_start = 0, led_trig_stop = 0;
#ifdef CONFIG_PROVE_LOCKING
WARN_ON(debug_locks && !lockdep_rtnl_is_held() &&
@@ -1314,6 +1316,18 @@ u32 __ieee80211_recalc_idle(struct ieee80211_local *local)
ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_IDLE);
}
+ if (working || scanning)
+ led_trig_start |= IEEE80211_TPT_LEDTRIG_FL_WORK;
+ else
+ led_trig_stop |= IEEE80211_TPT_LEDTRIG_FL_WORK;
+
+ if (count)
+ led_trig_start |= IEEE80211_TPT_LEDTRIG_FL_CONNECTED;
+ else
+ led_trig_stop |= IEEE80211_TPT_LEDTRIG_FL_CONNECTED;
+
+ ieee80211_mod_tpt_led_trig(local, led_trig_start, led_trig_stop);
+
if (working)
return ieee80211_idle_off(local, "working");
if (scanning)
diff --git a/net/mac80211/led.c b/net/mac80211/led.c
index 79b13090aed7..4905eb8af572 100644
--- a/net/mac80211/led.c
+++ b/net/mac80211/led.c
@@ -216,7 +216,7 @@ static void tpt_trig_timer(unsigned long data)
}
extern char *__ieee80211_create_tpt_led_trigger(
- struct ieee80211_hw *hw,
+ struct ieee80211_hw *hw, unsigned int flags,
const struct ieee80211_tpt_blink *blink_table,
unsigned int blink_table_len)
{
@@ -237,6 +237,7 @@ extern char *__ieee80211_create_tpt_led_trigger(
tpt_trig->blink_table = blink_table;
tpt_trig->blink_table_len = blink_table_len;
+ tpt_trig->want = flags;
setup_timer(&tpt_trig->timer, tpt_trig_timer, (unsigned long)local);
@@ -246,11 +247,11 @@ extern char *__ieee80211_create_tpt_led_trigger(
}
EXPORT_SYMBOL(__ieee80211_create_tpt_led_trigger);
-void ieee80211_start_tpt_led_trig(struct ieee80211_local *local)
+static void ieee80211_start_tpt_led_trig(struct ieee80211_local *local)
{
struct tpt_led_trigger *tpt_trig = local->tpt_led_trigger;
- if (!tpt_trig)
+ if (tpt_trig->running)
return;
/* reset traffic */
@@ -261,12 +262,12 @@ void ieee80211_start_tpt_led_trig(struct ieee80211_local *local)
mod_timer(&tpt_trig->timer, round_jiffies(jiffies + HZ));
}
-void ieee80211_stop_tpt_led_trig(struct ieee80211_local *local)
+static void ieee80211_stop_tpt_led_trig(struct ieee80211_local *local)
{
struct tpt_led_trigger *tpt_trig = local->tpt_led_trigger;
struct led_classdev *led_cdev;
- if (!tpt_trig)
+ if (!tpt_trig->running)
return;
tpt_trig->running = false;
@@ -277,3 +278,31 @@ void ieee80211_stop_tpt_led_trig(struct ieee80211_local *local)
led_brightness_set(led_cdev, LED_OFF);
read_unlock(&tpt_trig->trig.leddev_list_lock);
}
+
+void ieee80211_mod_tpt_led_trig(struct ieee80211_local *local,
+ unsigned int types_on, unsigned int types_off)
+{
+ struct tpt_led_trigger *tpt_trig = local->tpt_led_trigger;
+ bool allowed;
+
+ WARN_ON(types_on & types_off);
+
+ if (!tpt_trig)
+ return;
+
+ tpt_trig->active &= ~types_off;
+ tpt_trig->active |= types_on;
+
+ /*
+ * Regardless of wanted state, we shouldn't blink when
+ * the radio is disabled -- this can happen due to some
+ * code ordering issues with __ieee80211_recalc_idle()
+ * being called before the radio is started.
+ */
+ allowed = tpt_trig->active & IEEE80211_TPT_LEDTRIG_FL_RADIO;
+
+ if (!allowed || !(tpt_trig->active & tpt_trig->want))
+ ieee80211_stop_tpt_led_trig(local);
+ else
+ ieee80211_start_tpt_led_trig(local);
+}
diff --git a/net/mac80211/led.h b/net/mac80211/led.h
index 6c215dc0fc96..e0275d9befa8 100644
--- a/net/mac80211/led.h
+++ b/net/mac80211/led.h
@@ -21,8 +21,8 @@ void ieee80211_led_radio(struct ieee80211_local *local,
void ieee80211_led_names(struct ieee80211_local *local);
void ieee80211_led_init(struct ieee80211_local *local);
void ieee80211_led_exit(struct ieee80211_local *local);
-void ieee80211_start_tpt_led_trig(struct ieee80211_local *local);
-void ieee80211_stop_tpt_led_trig(struct ieee80211_local *local);
+void ieee80211_mod_tpt_led_trig(struct ieee80211_local *local,
+ unsigned int types_on, unsigned int types_off);
#else
static inline void ieee80211_led_rx(struct ieee80211_local *local)
{
@@ -47,10 +47,9 @@ static inline void ieee80211_led_init(struct ieee80211_local *local)
static inline void ieee80211_led_exit(struct ieee80211_local *local)
{
}
-static inline void ieee80211_start_tpt_led_trig(struct ieee80211_local *local)
-{
-}
-static inline void ieee80211_stop_tpt_led_trig(struct ieee80211_local *local)
+static inline void ieee80211_mod_tpt_led_trig(struct ieee80211_local *local,
+ unsigned int types_on,
+ unsigned int types_off)
{
}
#endif
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 48306415a1cb..cf68700abffa 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -1116,7 +1116,7 @@ u32 ieee80211_sta_get_rates(struct ieee80211_local *local,
void ieee80211_stop_device(struct ieee80211_local *local)
{
ieee80211_led_radio(local, false);
- ieee80211_stop_tpt_led_trig(local);
+ ieee80211_mod_tpt_led_trig(local, 0, IEEE80211_TPT_LEDTRIG_FL_RADIO);
cancel_work_sync(&local->reconfig_filter);
@@ -1151,7 +1151,8 @@ int ieee80211_reconfig(struct ieee80211_local *local)
}
ieee80211_led_radio(local, true);
- ieee80211_start_tpt_led_trig(local);
+ ieee80211_mod_tpt_led_trig(local,
+ IEEE80211_TPT_LEDTRIG_FL_RADIO, 0);
}
/* add interfaces */