From ac1ecc1f77b1ab05265609df8b6592bd145ab532 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sat, 11 Dec 2010 01:45:12 +0000 Subject: mac80211: update to 2010-12-09 git-svn-id: svn://svn.openwrt.org/openwrt/trunk@24471 3c298f89-4303-0410-b956-a3cf2f4a3e73 --- .../mac80211/patches/310-mac80211_tpt_led.patch | 470 +++++++++++++++++++++ 1 file changed, 470 insertions(+) create mode 100644 package/mac80211/patches/310-mac80211_tpt_led.patch (limited to 'package/mac80211/patches/310-mac80211_tpt_led.patch') diff --git a/package/mac80211/patches/310-mac80211_tpt_led.patch b/package/mac80211/patches/310-mac80211_tpt_led.patch new file mode 100644 index 0000000000..9318f8c46c --- /dev/null +++ b/package/mac80211/patches/310-mac80211_tpt_led.patch @@ -0,0 +1,470 @@ +--- a/net/mac80211/led.c ++++ b/net/mac80211/led.c +@@ -54,12 +54,22 @@ void ieee80211_led_radio(struct ieee8021 + led_trigger_event(local->radio_led, LED_OFF); + } + ++void ieee80211_led_names(struct ieee80211_local *local) ++{ ++ snprintf(local->rx_led_name, sizeof(local->rx_led_name), ++ "%srx", wiphy_name(local->hw.wiphy)); ++ snprintf(local->tx_led_name, sizeof(local->tx_led_name), ++ "%stx", wiphy_name(local->hw.wiphy)); ++ snprintf(local->assoc_led_name, sizeof(local->assoc_led_name), ++ "%sassoc", wiphy_name(local->hw.wiphy)); ++ snprintf(local->radio_led_name, sizeof(local->radio_led_name), ++ "%sradio", wiphy_name(local->hw.wiphy)); ++} ++ + void ieee80211_led_init(struct ieee80211_local *local) + { + local->rx_led = kzalloc(sizeof(struct led_trigger), GFP_KERNEL); + if (local->rx_led) { +- snprintf(local->rx_led_name, sizeof(local->rx_led_name), +- "%srx", wiphy_name(local->hw.wiphy)); + local->rx_led->name = local->rx_led_name; + if (led_trigger_register(local->rx_led)) { + kfree(local->rx_led); +@@ -69,8 +79,6 @@ void ieee80211_led_init(struct ieee80211 + + local->tx_led = kzalloc(sizeof(struct led_trigger), GFP_KERNEL); + if (local->tx_led) { +- snprintf(local->tx_led_name, sizeof(local->tx_led_name), +- "%stx", wiphy_name(local->hw.wiphy)); + local->tx_led->name = local->tx_led_name; + if (led_trigger_register(local->tx_led)) { + kfree(local->tx_led); +@@ -80,8 +88,6 @@ void ieee80211_led_init(struct ieee80211 + + local->assoc_led = kzalloc(sizeof(struct led_trigger), GFP_KERNEL); + if (local->assoc_led) { +- snprintf(local->assoc_led_name, sizeof(local->assoc_led_name), +- "%sassoc", wiphy_name(local->hw.wiphy)); + local->assoc_led->name = local->assoc_led_name; + if (led_trigger_register(local->assoc_led)) { + kfree(local->assoc_led); +@@ -91,14 +97,19 @@ void ieee80211_led_init(struct ieee80211 + + local->radio_led = kzalloc(sizeof(struct led_trigger), GFP_KERNEL); + if (local->radio_led) { +- snprintf(local->radio_led_name, sizeof(local->radio_led_name), +- "%sradio", wiphy_name(local->hw.wiphy)); + local->radio_led->name = local->radio_led_name; + if (led_trigger_register(local->radio_led)) { + kfree(local->radio_led); + local->radio_led = NULL; + } + } ++ ++ if (local->tpt_led_trigger) { ++ if (led_trigger_register(&local->tpt_led_trigger->trig)) { ++ kfree(local->tpt_led_trigger); ++ local->tpt_led_trigger = NULL; ++ } ++ } + } + + void ieee80211_led_exit(struct ieee80211_local *local) +@@ -119,15 +130,18 @@ void ieee80211_led_exit(struct ieee80211 + led_trigger_unregister(local->rx_led); + kfree(local->rx_led); + } ++ ++ if (local->tpt_led_trigger) { ++ led_trigger_unregister(&local->tpt_led_trigger->trig); ++ kfree(local->tpt_led_trigger); ++ } + } + + char *__ieee80211_get_radio_led_name(struct ieee80211_hw *hw) + { + struct ieee80211_local *local = hw_to_local(hw); + +- if (local->radio_led) +- return local->radio_led_name; +- return NULL; ++ return local->radio_led_name; + } + EXPORT_SYMBOL(__ieee80211_get_radio_led_name); + +@@ -135,9 +149,7 @@ char *__ieee80211_get_assoc_led_name(str + { + struct ieee80211_local *local = hw_to_local(hw); + +- if (local->assoc_led) +- return local->assoc_led_name; +- return NULL; ++ return local->assoc_led_name; + } + EXPORT_SYMBOL(__ieee80211_get_assoc_led_name); + +@@ -145,9 +157,7 @@ char *__ieee80211_get_tx_led_name(struct + { + struct ieee80211_local *local = hw_to_local(hw); + +- if (local->tx_led) +- return local->tx_led_name; +- return NULL; ++ return local->tx_led_name; + } + EXPORT_SYMBOL(__ieee80211_get_tx_led_name); + +@@ -155,8 +165,115 @@ char *__ieee80211_get_rx_led_name(struct + { + struct ieee80211_local *local = hw_to_local(hw); + +- if (local->rx_led) +- return local->rx_led_name; +- return NULL; ++ return local->rx_led_name; + } + EXPORT_SYMBOL(__ieee80211_get_rx_led_name); ++ ++static unsigned long tpt_trig_traffic(struct ieee80211_local *local, ++ struct tpt_led_trigger *tpt_trig) ++{ ++ unsigned long traffic, delta; ++ ++ traffic = tpt_trig->tx_bytes + tpt_trig->rx_bytes; ++ ++ delta = traffic - tpt_trig->prev_traffic; ++ tpt_trig->prev_traffic = traffic; ++ return DIV_ROUND_UP(delta, 1024 / 8); ++} ++ ++static void tpt_trig_timer(unsigned long data) ++{ ++ struct ieee80211_local *local = (void *)data; ++ struct tpt_led_trigger *tpt_trig = local->tpt_led_trigger; ++ struct led_classdev *led_cdev; ++ unsigned long on, off, tpt; ++ int i; ++ ++ if (!tpt_trig->running) ++ return; ++ ++ mod_timer(&tpt_trig->timer, round_jiffies(jiffies + HZ)); ++ ++ tpt = tpt_trig_traffic(local, tpt_trig); ++ ++ /* default to just solid on */ ++ on = 1; ++ off = 0; ++ ++ for (i = tpt_trig->blink_table_len - 1; i >= 0; i--) { ++ if (tpt_trig->blink_table[i].throughput < 0 || ++ tpt > tpt_trig->blink_table[i].throughput) { ++ off = tpt_trig->blink_table[i].blink_time / 2; ++ on = tpt_trig->blink_table[i].blink_time - off; ++ break; ++ } ++ } ++ ++ read_lock(&tpt_trig->trig.leddev_list_lock); ++ list_for_each_entry(led_cdev, &tpt_trig->trig.led_cdevs, trig_list) ++ led_blink_set(led_cdev, &on, &off); ++ read_unlock(&tpt_trig->trig.leddev_list_lock); ++} ++ ++extern char *__ieee80211_create_tpt_led_trigger( ++ struct ieee80211_hw *hw, ++ const struct ieee80211_tpt_blink *blink_table, ++ unsigned int blink_table_len) ++{ ++ struct ieee80211_local *local = hw_to_local(hw); ++ struct tpt_led_trigger *tpt_trig; ++ ++ if (WARN_ON(local->tpt_led_trigger)) ++ return NULL; ++ ++ tpt_trig = kzalloc(sizeof(struct tpt_led_trigger), GFP_KERNEL); ++ if (!tpt_trig) ++ return NULL; ++ ++ snprintf(tpt_trig->name, sizeof(tpt_trig->name), ++ "%stpt", wiphy_name(local->hw.wiphy)); ++ ++ tpt_trig->trig.name = tpt_trig->name; ++ ++ tpt_trig->blink_table = blink_table; ++ tpt_trig->blink_table_len = blink_table_len; ++ ++ setup_timer(&tpt_trig->timer, tpt_trig_timer, (unsigned long)local); ++ ++ local->tpt_led_trigger = tpt_trig; ++ ++ return tpt_trig->name; ++} ++EXPORT_SYMBOL(__ieee80211_create_tpt_led_trigger); ++ ++void ieee80211_start_tpt_led_trig(struct ieee80211_local *local) ++{ ++ struct tpt_led_trigger *tpt_trig = local->tpt_led_trigger; ++ ++ if (!tpt_trig) ++ return; ++ ++ /* reset traffic */ ++ tpt_trig_traffic(local, tpt_trig); ++ tpt_trig->running = true; ++ ++ tpt_trig_timer((unsigned long)local); ++ mod_timer(&tpt_trig->timer, round_jiffies(jiffies + HZ)); ++} ++ ++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) ++ return; ++ ++ tpt_trig->running = false; ++ del_timer_sync(&tpt_trig->timer); ++ ++ read_lock(&tpt_trig->trig.leddev_list_lock); ++ list_for_each_entry(led_cdev, &tpt_trig->trig.led_cdevs, trig_list) ++ led_brightness_set(led_cdev, LED_OFF); ++ read_unlock(&tpt_trig->trig.leddev_list_lock); ++} +--- a/net/mac80211/led.h ++++ b/net/mac80211/led.h +@@ -12,14 +12,17 @@ + #include "ieee80211_i.h" + + #ifdef CONFIG_MAC80211_LEDS +-extern void ieee80211_led_rx(struct ieee80211_local *local); +-extern void ieee80211_led_tx(struct ieee80211_local *local, int q); +-extern void ieee80211_led_assoc(struct ieee80211_local *local, +- bool associated); +-extern void ieee80211_led_radio(struct ieee80211_local *local, +- bool enabled); +-extern void ieee80211_led_init(struct ieee80211_local *local); +-extern void ieee80211_led_exit(struct ieee80211_local *local); ++void ieee80211_led_rx(struct ieee80211_local *local); ++void ieee80211_led_tx(struct ieee80211_local *local, int q); ++void ieee80211_led_assoc(struct ieee80211_local *local, ++ bool associated); ++void ieee80211_led_radio(struct ieee80211_local *local, ++ bool enabled); ++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); + #else + static inline void ieee80211_led_rx(struct ieee80211_local *local) + { +@@ -35,10 +38,37 @@ static inline void ieee80211_led_radio(s + bool enabled) + { + } ++static inline void ieee80211_led_names(struct ieee80211_local *local) ++{ ++} + 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) ++{ ++} ++#endif ++ ++static inline void ++ieee80211_tpt_led_trig_tx(struct ieee80211_local *local, __le16 fc, int bytes) ++{ ++#ifdef CONFIG_MAC80211_LEDS ++ if (local->tpt_led_trigger && ieee80211_is_data(fc)) ++ local->tpt_led_trigger->tx_bytes += bytes; ++#endif ++} ++ ++static inline void ++ieee80211_tpt_led_trig_rx(struct ieee80211_local *local, __le16 fc, int bytes) ++{ ++#ifdef CONFIG_MAC80211_LEDS ++ if (local->tpt_led_trigger && ieee80211_is_data(fc)) ++ local->tpt_led_trigger->rx_bytes += bytes; + #endif ++} +--- a/net/mac80211/main.c ++++ b/net/mac80211/main.c +@@ -602,6 +602,8 @@ struct ieee80211_hw *ieee80211_alloc_hw( + /* init dummy netdev for use w/ NAPI */ + init_dummy_netdev(&local->napi_dev); + ++ ieee80211_led_names(local); ++ + return local_to_hw(local); + } + EXPORT_SYMBOL(ieee80211_alloc_hw); +--- a/include/net/mac80211.h ++++ b/include/net/mac80211.h +@@ -1856,11 +1856,26 @@ struct ieee80211_hw *ieee80211_alloc_hw( + */ + int ieee80211_register_hw(struct ieee80211_hw *hw); + ++/** ++ * struct ieee80211_tpt_blink - throughput blink description ++ * @throughput: throughput in Kbit/sec ++ * @blink_time: blink time in milliseconds ++ * (full cycle, ie. one off + one on period) ++ */ ++struct ieee80211_tpt_blink { ++ int throughput; ++ int blink_time; ++}; ++ + #ifdef CONFIG_MAC80211_LEDS + extern char *__ieee80211_get_tx_led_name(struct ieee80211_hw *hw); + extern char *__ieee80211_get_rx_led_name(struct ieee80211_hw *hw); + extern char *__ieee80211_get_assoc_led_name(struct ieee80211_hw *hw); + extern char *__ieee80211_get_radio_led_name(struct ieee80211_hw *hw); ++extern char *__ieee80211_create_tpt_led_trigger( ++ struct ieee80211_hw *hw, ++ const struct ieee80211_tpt_blink *blink_table, ++ unsigned int blink_table_len); + #endif + /** + * ieee80211_get_tx_led_name - get name of TX LED +@@ -1939,6 +1954,29 @@ static inline char *ieee80211_get_radio_ + } + + /** ++ * ieee80211_create_tpt_led_trigger - create throughput LED trigger ++ * @hw: the hardware to create the trigger for ++ * @blink_table: the blink table -- needs to be ordered by throughput ++ * @blink_table_len: size of the blink table ++ * ++ * This function returns %NULL (in case of error, or if no LED ++ * triggers are configured) or the name of the new trigger. ++ * This function must be called before ieee80211_register_hw(). ++ */ ++static inline char * ++ieee80211_create_tpt_led_trigger(struct ieee80211_hw *hw, ++ const struct ieee80211_tpt_blink *blink_table, ++ unsigned int blink_table_len) ++{ ++#ifdef CONFIG_MAC80211_LEDS ++ return __ieee80211_create_tpt_led_trigger(hw, blink_table, ++ blink_table_len); ++#else ++ return NULL; ++#endif ++} ++ ++/** + * ieee80211_unregister_hw - Unregister a hardware device + * + * This function instructs mac80211 to free allocated resources +--- a/net/mac80211/ieee80211_i.h ++++ b/net/mac80211/ieee80211_i.h +@@ -23,6 +23,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -629,6 +630,19 @@ enum queue_stop_reason { + IEEE80211_QUEUE_STOP_REASON_SKB_ADD, + }; + ++#ifdef CONFIG_MAC80211_LEDS ++struct tpt_led_trigger { ++ struct led_trigger trig; ++ char name[32]; ++ 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; ++}; ++#endif ++ + /** + * mac80211 scan flags - currently active scan mode + * +@@ -842,6 +856,7 @@ struct ieee80211_local { + #ifdef CONFIG_MAC80211_LEDS + int tx_led_counter, rx_led_counter; + struct led_trigger *tx_led, *rx_led, *assoc_led, *radio_led; ++ struct tpt_led_trigger *tpt_led_trigger; + char tx_led_name[32], rx_led_name[32], + assoc_led_name[32], radio_led_name[32]; + #endif +--- a/net/mac80211/iface.c ++++ b/net/mac80211/iface.c +@@ -220,6 +220,7 @@ static int ieee80211_do_open(struct net_ + /* we're brought up, everything changes */ + hw_reconf_flags = ~0; + ieee80211_led_radio(local, true); ++ ieee80211_start_tpt_led_trig(local); + } + + /* +--- a/net/mac80211/rx.c ++++ b/net/mac80211/rx.c +@@ -2888,6 +2888,9 @@ void ieee80211_rx(struct ieee80211_hw *h + return; + } + ++ ieee80211_tpt_led_trig_rx(local, ++ ((struct ieee80211_hdr *)skb->data)->frame_control, ++ skb->len); + __ieee80211_rx_handle_packet(hw, skb); + + rcu_read_unlock(); +--- a/net/mac80211/tx.c ++++ b/net/mac80211/tx.c +@@ -1293,6 +1293,7 @@ static int __ieee80211_tx(struct ieee802 + + while (skb) { + int q = skb_get_queue_mapping(skb); ++ __le16 fc; + + spin_lock_irqsave(&local->queue_stop_reason_lock, flags); + ret = IEEE80211_TX_OK; +@@ -1335,6 +1336,7 @@ static int __ieee80211_tx(struct ieee802 + else + info->control.sta = NULL; + ++ fc = ((struct ieee80211_hdr *)skb->data)->frame_control; + ret = drv_tx(local, skb); + if (WARN_ON(ret != NETDEV_TX_OK && skb->len != len)) { + dev_kfree_skb(skb); +@@ -1345,6 +1347,7 @@ static int __ieee80211_tx(struct ieee802 + return IEEE80211_TX_AGAIN; + } + ++ ieee80211_tpt_led_trig_tx(local, fc, len); + *skbp = skb = next; + ieee80211_led_tx(local, 1); + fragm = true; +--- a/net/mac80211/util.c ++++ b/net/mac80211/util.c +@@ -1141,6 +1141,7 @@ u32 ieee80211_sta_get_rates(struct ieee8 + void ieee80211_stop_device(struct ieee80211_local *local) + { + ieee80211_led_radio(local, false); ++ ieee80211_stop_tpt_led_trig(local); + + cancel_work_sync(&local->reconfig_filter); + +@@ -1175,6 +1176,7 @@ int ieee80211_reconfig(struct ieee80211_ + } + + ieee80211_led_radio(local, true); ++ ieee80211_start_tpt_led_trig(local); + } + + /* add interfaces */ -- cgit v1.2.3