From 4a12b0531a1ce79b6c60cb8ac13f9c762f9fdd4f Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sat, 27 Nov 2010 22:11:13 +0000 Subject: mac80211: add pending patches for throughput based led blinking and replace the broken ath9k blinking code with it git-svn-id: svn://svn.openwrt.org/openwrt/trunk@24159 3c298f89-4303-0410-b956-a3cf2f4a3e73 --- .../mac80211/patches/560-led_blink_backport.patch | 207 +++++++++++++++++++++ 1 file changed, 207 insertions(+) create mode 100644 package/mac80211/patches/560-led_blink_backport.patch (limited to 'package/mac80211/patches/560-led_blink_backport.patch') diff --git a/package/mac80211/patches/560-led_blink_backport.patch b/package/mac80211/patches/560-led_blink_backport.patch new file mode 100644 index 0000000000..d22ec95cc1 --- /dev/null +++ b/package/mac80211/patches/560-led_blink_backport.patch @@ -0,0 +1,207 @@ +--- a/compat/compat-2.6.37.c ++++ b/compat/compat-2.6.37.c +@@ -152,3 +152,175 @@ int compat_genl_unregister_family(struct + } + EXPORT_SYMBOL(compat_genl_unregister_family); + ++#ifdef CONFIG_LEDS_CLASS ++ ++#undef led_brightness_set ++#undef led_classdev_unregister ++ ++spinlock_t led_lock; ++static LIST_HEAD(led_timers); ++ ++struct led_timer { ++ struct list_head list; ++ struct led_classdev *cdev; ++ struct timer_list blink_timer; ++ unsigned long blink_delay_on; ++ unsigned long blink_delay_off; ++ int blink_brightness; ++}; ++ ++static void led_brightness_set(struct led_classdev *led_cdev, ++ enum led_brightness brightness) ++{ ++ led_cdev->brightness = brightness; ++ led_cdev->brightness_set(led_cdev, brightness); ++} ++ ++static struct led_timer *led_get_timer(struct led_classdev *led_cdev) ++{ ++ struct led_timer *p; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&led_lock, flags); ++ list_for_each_entry(p, &led_timers, list) { ++ if (p->cdev == led_cdev) ++ goto found; ++ } ++ p = NULL; ++found: ++ spin_unlock_irqrestore(&led_lock, flags); ++ return p; ++} ++ ++static void led_stop_software_blink(struct led_timer *led) ++{ ++ del_timer_sync(&led->blink_timer); ++ led->blink_delay_on = 0; ++ led->blink_delay_off = 0; ++} ++ ++static void led_timer_function(unsigned long data) ++{ ++ struct led_timer *led = (struct led_timer *)data; ++ unsigned long brightness; ++ unsigned long delay; ++ ++ if (!led->blink_delay_on || !led->blink_delay_off) { ++ led->cdev->brightness_set(led->cdev, LED_OFF); ++ return; ++ } ++ ++ brightness = led->cdev->brightness; ++ if (!brightness) { ++ /* Time to switch the LED on. */ ++ brightness = led->blink_brightness; ++ delay = led->blink_delay_on; ++ } else { ++ /* Store the current brightness value to be able ++ * to restore it when the delay_off period is over. ++ */ ++ led->blink_brightness = brightness; ++ brightness = LED_OFF; ++ delay = led->blink_delay_off; ++ } ++ ++ led_brightness_set(led->cdev, brightness); ++ mod_timer(&led->blink_timer, jiffies + msecs_to_jiffies(delay)); ++} ++ ++static struct led_timer *led_new_timer(struct led_classdev *led_cdev) ++{ ++ struct led_timer *led; ++ unsigned long flags; ++ ++ led = kzalloc(sizeof(struct led_timer), GFP_ATOMIC); ++ if (!led) ++ return NULL; ++ ++ led->cdev = led_cdev; ++ init_timer(&led->blink_timer); ++ led->blink_timer.function = led_timer_function; ++ led->blink_timer.data = (unsigned long) led; ++ ++ spin_lock_irqsave(&led_lock, flags); ++ list_add(&led->list, &led_timers); ++ spin_unlock_irqrestore(&led_lock, flags); ++ ++ return led; ++} ++ ++void led_blink_set(struct led_classdev *led_cdev, ++ unsigned long *delay_on, ++ unsigned long *delay_off) ++{ ++ struct led_timer *led = led_get_timer(led_cdev); ++ int current_brightness; ++ ++ if (!led) { ++ led = led_new_timer(led_cdev); ++ if (!led) ++ return; ++ } ++ ++ /* blink with 1 Hz as default if nothing specified */ ++ if (!*delay_on && !*delay_off) ++ *delay_on = *delay_off = 500; ++ ++ if (led->blink_delay_on == *delay_on && ++ led->blink_delay_off == *delay_off) ++ return; ++ ++ current_brightness = led_cdev->brightness; ++ if (current_brightness) ++ led->blink_brightness = current_brightness; ++ if (!led->blink_brightness) ++ led->blink_brightness = led_cdev->max_brightness; ++ ++ led_stop_software_blink(led); ++ led->blink_delay_on = *delay_on; ++ led->blink_delay_off = *delay_off; ++ ++ /* never on - don't blink */ ++ if (!*delay_on) ++ return; ++ ++ /* never off - just set to brightness */ ++ if (!*delay_off) { ++ led_brightness_set(led_cdev, led->blink_brightness); ++ return; ++ } ++ ++ mod_timer(&led->blink_timer, jiffies + 1); ++} ++EXPORT_SYMBOL(led_blink_set); ++ ++void compat_led_brightness_set(struct led_classdev *led_cdev, ++ enum led_brightness brightness) ++{ ++ struct led_timer *led = led_get_timer(led_cdev); ++ ++ if (led) ++ led_stop_software_blink(led); ++ ++ return led_cdev->brightness_set(led_cdev, brightness); ++} ++EXPORT_SYMBOL(compat_led_brightness_set); ++ ++void compat_led_classdev_unregister(struct led_classdev *led_cdev) ++{ ++ struct led_timer *led = led_get_timer(led_cdev); ++ unsigned long flags; ++ ++ if (led) { ++ del_timer_sync(&led->blink_timer); ++ spin_lock_irqsave(&led_lock, flags); ++ list_del(&led->list); ++ spin_unlock_irqrestore(&led_lock, flags); ++ kfree(led); ++ } ++ ++ led_classdev_unregister(led_cdev); ++} ++EXPORT_SYMBOL(compat_led_classdev_unregister); ++ ++#endif +--- a/include/linux/compat-2.6.37.h ++++ b/include/linux/compat-2.6.37.h +@@ -6,6 +6,7 @@ + #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37)) + + #include ++#include + + #define SDIO_CLASS_BT_AMP 0x09 /* Type-A Bluetooth AMP interface */ + +@@ -93,6 +94,18 @@ int genl_unregister_family(struct genl_f + #define genl_register_mc_group(_fam, _grp) genl_register_mc_group(&(_fam)->family, _grp) + #define genl_unregister_mc_group(_fam, _grp) genl_unregister_mc_group(&(_fam)->family, _grp) + ++ ++extern void led_blink_set(struct led_classdev *led_cdev, ++ unsigned long *delay_on, ++ unsigned long *delay_off); ++ ++#define led_classdev_unregister compat_led_classdev_unregister ++extern void led_classdev_unregister(struct led_classdev *led_cdev); ++ ++#define led_brightness_set compat_led_brightness_set ++extern void led_brightness_set(struct led_classdev *led_cdev, ++ enum led_brightness brightness); ++ + #endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37)) */ + + #endif /* LINUX_26_37_COMPAT_H */ -- cgit v1.2.3