Arch/led_fixes.patch
changeset 6 35c0804c8ca2
equal deleted inserted replaced
5:bca986acd412 6:35c0804c8ca2
       
     1 diff -purN linux-3.11.orig/drivers/leds/trigger/Kconfig linux-3.11/drivers/leds/trigger/Kconfig
       
     2 --- linux-3.11.orig/drivers/leds/trigger/Kconfig	2013-09-02 22:46:10.000000000 +0200
       
     3 +++ linux-3.11/drivers/leds/trigger/Kconfig	2013-09-12 23:10:19.343331257 +0200
       
     4 @@ -38,6 +38,14 @@ config LEDS_TRIGGER_IDE_DISK
       
     5  	depends on IDE_GD_ATA
       
     6  	depends on LEDS_TRIGGERS
       
     7  	help
       
     8 +	  This allows LEDs to be controlled by SATA disk activity.
       
     9 +	  If unsure, say Y.
       
    10 +
       
    11 +config LEDS_TRIGGER_SATA_DISK
       
    12 +	bool "LED SATA Disk Trigger"
       
    13 +	depends on ATA
       
    14 +	depends on LEDS_TRIGGERS
       
    15 +	help
       
    16  	  This allows LEDs to be controlled by IDE disk activity.
       
    17  	  If unsure, say Y.
       
    18  
       
    19 @@ -89,6 +97,13 @@ config LEDS_TRIGGER_DEFAULT_ON
       
    20  	  This allows LEDs to be initialised in the ON state.
       
    21  	  If unsure, say Y.
       
    22  
       
    23 +config LEDS_TRIGGER_NETDEV 
       
    24 +       tristate "LED Netdev Trigger" 
       
    25 +       depends on LEDS_TRIGGERS 
       
    26 +       help 
       
    27 +        This allows LEDs to be controlled by network device activity. 
       
    28 +        If unsure, say Y. 
       
    29 +
       
    30  comment "iptables trigger is under Netfilter config (LED target)"
       
    31  	depends on LEDS_TRIGGERS
       
    32  
       
    33 diff -purN linux-3.11.orig/drivers/leds/trigger/ledtrig-netdev.c linux-3.11/drivers/leds/trigger/ledtrig-netdev.c
       
    34 --- linux-3.11.orig/drivers/leds/trigger/ledtrig-netdev.c	1970-01-01 01:00:00.000000000 +0100
       
    35 +++ linux-3.11/drivers/leds/trigger/ledtrig-netdev.c	2013-09-12 23:17:47.227775980 +0200
       
    36 @@ -0,0 +1,460 @@
       
    37 +/*
       
    38 + * LED Kernel Netdev Trigger
       
    39 + *
       
    40 + * Toggles the LED to reflect the link and traffic state of a named net device
       
    41 + *
       
    42 + * Copyright 2007 Oliver Jowett <oliver@opencloud.com>
       
    43 + *
       
    44 + * Derived from ledtrig-timer.c which is:
       
    45 + *  Copyright 2005-2006 Openedhand Ltd.
       
    46 + *  Author: Richard Purdie <rpurdie@openedhand.com>
       
    47 + *
       
    48 + * This program is free software; you can redistribute it and/or modify
       
    49 + * it under the terms of the GNU General Public License version 2 as
       
    50 + * published by the Free Software Foundation.
       
    51 + *
       
    52 + */
       
    53 +
       
    54 +#include <linux/module.h>
       
    55 +#include <linux/jiffies.h>
       
    56 +#include <linux/kernel.h>
       
    57 +#include <linux/init.h>
       
    58 +#include <linux/list.h>
       
    59 +#include <linux/spinlock.h>
       
    60 +#include <linux/device.h>
       
    61 +#include <linux/netdevice.h>
       
    62 +#include <linux/timer.h>
       
    63 +#include <linux/ctype.h>
       
    64 +#include <linux/leds.h>
       
    65 +#include <linux/version.h>
       
    66 +#include <net/net_namespace.h>
       
    67 +
       
    68 +/*
       
    69 + * Configurable sysfs attributes:
       
    70 + *
       
    71 + * device_name - network device name to monitor
       
    72 + *
       
    73 + * interval - duration of LED blink, in milliseconds
       
    74 + *
       
    75 + * mode - either "none" (LED is off) or a space separated list
       
    76 + * of one or more of:
       
    77 + *   link: LED's normal state reflects whether the link is up (has carrier)
       
    78 + *         or not
       
    79 + *   tx:   LED blinks on transmitted data
       
    80 + *   rx:   LED blinks on receive data
       
    81 + *
       
    82 + * Some suggestions:
       
    83 + *
       
    84 + *  Simple link status LED:
       
    85 + *  $ echo netdev >someled/trigger
       
    86 + *  $ echo eth0 >someled/device_name
       
    87 + *  $ echo link >someled/mode
       
    88 + *
       
    89 + *  Ethernet-style link/activity LED:
       
    90 + *  $ echo netdev >someled/trigger
       
    91 + *  $ echo eth0 >someled/device_name
       
    92 + *  $ echo "link tx rx" >someled/mode
       
    93 + *
       
    94 + *  Modem-style tx/rx LEDs:
       
    95 + *  $ echo netdev >led1/trigger
       
    96 + *  $ echo ppp0 >led1/device_name
       
    97 + *  $ echo tx >led1/mode
       
    98 + *  $ echo netdev >led2/trigger
       
    99 + *  $ echo ppp0 >led2/device_name
       
   100 + *  $ echo rx >led2/mode
       
   101 + *
       
   102 + */
       
   103 +
       
   104 +#define MODE_LINK 1
       
   105 +#define MODE_TX	  2
       
   106 +#define MODE_RX	  4
       
   107 +
       
   108 +struct led_netdev_data {
       
   109 +	rwlock_t lock;
       
   110 +
       
   111 +	struct timer_list timer;
       
   112 +	struct notifier_block notifier;
       
   113 +
       
   114 +	struct led_classdev *led_cdev;
       
   115 +	struct net_device *net_dev;
       
   116 +
       
   117 +	char device_name[IFNAMSIZ];
       
   118 +	unsigned interval;
       
   119 +	unsigned mode;
       
   120 +	unsigned link_up;
       
   121 +	unsigned last_activity;
       
   122 +};
       
   123 +
       
   124 +static void set_baseline_state(struct led_netdev_data *trigger_data)
       
   125 +{
       
   126 +	if ((trigger_data->mode & MODE_LINK) != 0 && trigger_data->link_up)
       
   127 +		led_set_brightness(trigger_data->led_cdev, LED_FULL);
       
   128 +	else
       
   129 +		led_set_brightness(trigger_data->led_cdev, LED_OFF);
       
   130 +
       
   131 +	if ((trigger_data->mode & (MODE_TX | MODE_RX)) != 0 &&
       
   132 +	    trigger_data->link_up)
       
   133 +		mod_timer(&trigger_data->timer,
       
   134 +			  jiffies + trigger_data->interval);
       
   135 +	else
       
   136 +		del_timer(&trigger_data->timer);
       
   137 +}
       
   138 +
       
   139 +static ssize_t led_device_name_show(struct device *dev,
       
   140 +				    struct device_attribute *attr, char *buf)
       
   141 +{
       
   142 +	struct led_classdev *led_cdev = dev_get_drvdata(dev);
       
   143 +	struct led_netdev_data *trigger_data = led_cdev->trigger_data;
       
   144 +
       
   145 +	read_lock(&trigger_data->lock);
       
   146 +	sprintf(buf, "%s\n", trigger_data->device_name);
       
   147 +	read_unlock(&trigger_data->lock);
       
   148 +
       
   149 +	return strlen(buf) + 1;
       
   150 +}
       
   151 +
       
   152 +static ssize_t led_device_name_store(struct device *dev,
       
   153 +				     struct device_attribute *attr,
       
   154 +				     const char *buf, size_t size)
       
   155 +{
       
   156 +	struct led_classdev *led_cdev = dev_get_drvdata(dev);
       
   157 +	struct led_netdev_data *trigger_data = led_cdev->trigger_data;
       
   158 +
       
   159 +	if (size < 0 || size >= IFNAMSIZ)
       
   160 +		return -EINVAL;
       
   161 +
       
   162 +	write_lock(&trigger_data->lock);
       
   163 +
       
   164 +	strcpy(trigger_data->device_name, buf);
       
   165 +	if (size > 0 && trigger_data->device_name[size-1] == '\n')
       
   166 +		trigger_data->device_name[size-1] = 0;
       
   167 +
       
   168 +	if (trigger_data->device_name[0] != 0) {
       
   169 +		/* check for existing device to update from */
       
   170 +		struct net_device *dev =
       
   171 +			dev_get_by_name(&init_net, trigger_data->device_name);
       
   172 +		if (dev != NULL) {
       
   173 +			unsigned int flags = dev_get_flags(dev);
       
   174 +			trigger_data->net_dev = dev;
       
   175 +			trigger_data->link_up = (flags & IFF_LOWER_UP) != 0;
       
   176 +		}
       
   177 +		/* updates LEDs, may start timers */
       
   178 +		set_baseline_state(trigger_data);
       
   179 +	}
       
   180 +
       
   181 +	write_unlock(&trigger_data->lock);
       
   182 +	return size;
       
   183 +}
       
   184 +
       
   185 +static DEVICE_ATTR(device_name, 0644,
       
   186 +		   led_device_name_show, led_device_name_store);
       
   187 +
       
   188 +static ssize_t led_mode_show(struct device *dev,
       
   189 +			     struct device_attribute *attr, char *buf)
       
   190 +{
       
   191 +	struct led_classdev *led_cdev = dev_get_drvdata(dev);
       
   192 +	struct led_netdev_data *trigger_data = led_cdev->trigger_data;
       
   193 +
       
   194 +	read_lock(&trigger_data->lock);
       
   195 +
       
   196 +	if (trigger_data->mode == 0) {
       
   197 +		strcpy(buf, "none\n");
       
   198 +	} else {
       
   199 +		if (trigger_data->mode & MODE_LINK)
       
   200 +			strcat(buf, "link ");
       
   201 +		if (trigger_data->mode & MODE_TX)
       
   202 +			strcat(buf, "tx ");
       
   203 +		if (trigger_data->mode & MODE_RX)
       
   204 +			strcat(buf, "rx ");
       
   205 +		strcat(buf, "\n");
       
   206 +	}
       
   207 +
       
   208 +	read_unlock(&trigger_data->lock);
       
   209 +
       
   210 +	return strlen(buf)+1;
       
   211 +}
       
   212 +
       
   213 +static ssize_t led_mode_store(struct device *dev,
       
   214 +			      struct device_attribute *attr,
       
   215 +			      const char *buf, size_t size)
       
   216 +{
       
   217 +	struct led_classdev *led_cdev = dev_get_drvdata(dev);
       
   218 +	struct led_netdev_data *trigger_data = led_cdev->trigger_data;
       
   219 +	char copybuf[32];
       
   220 +	int new_mode = -1;
       
   221 +	char *p, *token;
       
   222 +
       
   223 +	/* take a copy since we don't want to trash the inbound buffer
       
   224 +	   when using strsep */
       
   225 +	strncpy(copybuf, buf, sizeof(copybuf));
       
   226 +	copybuf[sizeof(copybuf) - 1] = '\0';
       
   227 +	p = copybuf;
       
   228 +
       
   229 +	while ((token = strsep(&p, " \t\n")) != NULL) {
       
   230 +		if (!*token)
       
   231 +			continue;
       
   232 +
       
   233 +		if (new_mode == -1)
       
   234 +			new_mode = 0;
       
   235 +
       
   236 +		if (!strcmp(token, "none"))
       
   237 +			new_mode = 0;
       
   238 +		else if (!strcmp(token, "tx"))
       
   239 +			new_mode |= MODE_TX;
       
   240 +		else if (!strcmp(token, "rx"))
       
   241 +			new_mode |= MODE_RX;
       
   242 +		else if (!strcmp(token, "link"))
       
   243 +			new_mode |= MODE_LINK;
       
   244 +		else
       
   245 +			return -EINVAL;
       
   246 +	}
       
   247 +
       
   248 +	if (new_mode == -1)
       
   249 +		return -EINVAL;
       
   250 +
       
   251 +	write_lock(&trigger_data->lock);
       
   252 +	trigger_data->mode = new_mode;
       
   253 +	set_baseline_state(trigger_data);
       
   254 +	write_unlock(&trigger_data->lock);
       
   255 +
       
   256 +	return size;
       
   257 +}
       
   258 +
       
   259 +static DEVICE_ATTR(mode, 0644, led_mode_show, led_mode_store);
       
   260 +
       
   261 +static ssize_t led_interval_show(struct device *dev,
       
   262 +				 struct device_attribute *attr,
       
   263 +				 char *buf)
       
   264 +{
       
   265 +	struct led_classdev *led_cdev = dev_get_drvdata(dev);
       
   266 +	struct led_netdev_data *trigger_data = led_cdev->trigger_data;
       
   267 +
       
   268 +	read_lock(&trigger_data->lock);
       
   269 +	sprintf(buf, "%u\n", jiffies_to_msecs(trigger_data->interval));
       
   270 +	read_unlock(&trigger_data->lock);
       
   271 +
       
   272 +	return strlen(buf) + 1;
       
   273 +}
       
   274 +
       
   275 +static ssize_t led_interval_store(struct device *dev,
       
   276 +				  struct device_attribute *attr,
       
   277 +				  const char *buf, size_t size)
       
   278 +{
       
   279 +	struct led_classdev *led_cdev = dev_get_drvdata(dev);
       
   280 +	struct led_netdev_data *trigger_data = led_cdev->trigger_data;
       
   281 +	int ret = -EINVAL;
       
   282 +	char *after;
       
   283 +	unsigned long value = simple_strtoul(buf, &after, 10);
       
   284 +	size_t count = after - buf;
       
   285 +
       
   286 +	if (*after && isspace(*after))
       
   287 +		count++;
       
   288 +
       
   289 +	/* impose some basic bounds on the timer interval */
       
   290 +	if (count == size && value >= 5 && value <= 10000) {
       
   291 +		write_lock(&trigger_data->lock);
       
   292 +		trigger_data->interval = msecs_to_jiffies(value);
       
   293 +		set_baseline_state(trigger_data);	/* resets timer */
       
   294 +		write_unlock(&trigger_data->lock);
       
   295 +		ret = count;
       
   296 +	}
       
   297 +
       
   298 +	return ret;
       
   299 +}
       
   300 +
       
   301 +static DEVICE_ATTR(interval, 0644, led_interval_show, led_interval_store);
       
   302 +
       
   303 +static int netdev_trig_notify(struct notifier_block *nb,
       
   304 +			      unsigned long evt,
       
   305 +			      void *dv)
       
   306 +{
       
   307 +	struct net_device *dev = dv;
       
   308 +	struct led_netdev_data *trigger_data =
       
   309 +		container_of(nb, struct led_netdev_data, notifier);
       
   310 +
       
   311 +	if (evt != NETDEV_UP && evt != NETDEV_DOWN && evt != NETDEV_CHANGE &&
       
   312 +	    evt != NETDEV_REGISTER && evt != NETDEV_UNREGISTER)
       
   313 +		return NOTIFY_DONE;
       
   314 +
       
   315 +	write_lock(&trigger_data->lock);
       
   316 +
       
   317 +	if (strcmp(dev->name, trigger_data->device_name))
       
   318 +		goto done;
       
   319 +
       
   320 +	if (evt == NETDEV_REGISTER) {
       
   321 +		if (trigger_data->net_dev != NULL)
       
   322 +			dev_put(trigger_data->net_dev);
       
   323 +		dev_hold(dev);
       
   324 +		trigger_data->net_dev = dev;
       
   325 +		trigger_data->link_up = 0;
       
   326 +		goto done;
       
   327 +	}
       
   328 +
       
   329 +	if (evt == NETDEV_UNREGISTER && trigger_data->net_dev != NULL) {
       
   330 +		dev_put(trigger_data->net_dev);
       
   331 +		trigger_data->net_dev = NULL;
       
   332 +		goto done;
       
   333 +	}
       
   334 +
       
   335 +	/* UP / DOWN / CHANGE */
       
   336 +
       
   337 +	trigger_data->link_up = (evt != NETDEV_DOWN && netif_carrier_ok(dev));
       
   338 +	set_baseline_state(trigger_data);
       
   339 +
       
   340 +done:
       
   341 +	write_unlock(&trigger_data->lock);
       
   342 +	return NOTIFY_DONE;
       
   343 +}
       
   344 +
       
   345 +/* here's the real work! */
       
   346 +static void netdev_trig_timer(unsigned long arg)
       
   347 +{
       
   348 +	struct led_netdev_data *trigger_data = (struct led_netdev_data *)arg;
       
   349 +	struct rtnl_link_stats64 temp;
       
   350 +	const struct rtnl_link_stats64 *dev_stats;
       
   351 +	unsigned new_activity;
       
   352 +
       
   353 +	write_lock(&trigger_data->lock);
       
   354 +
       
   355 +	if (!trigger_data->link_up || !trigger_data->net_dev ||
       
   356 +	    (trigger_data->mode & (MODE_TX | MODE_RX)) == 0) {
       
   357 +		/* we don't need to do timer work, just reflect link state. */
       
   358 +		int on = (trigger_data->mode & MODE_LINK) != 0 &&
       
   359 +			trigger_data->link_up;
       
   360 +		led_set_brightness(trigger_data->led_cdev,
       
   361 +				   on ? LED_FULL : LED_OFF);
       
   362 +		goto no_restart;
       
   363 +	}
       
   364 +
       
   365 +	dev_stats = dev_get_stats(trigger_data->net_dev, &temp);
       
   366 +
       
   367 +	new_activity =
       
   368 +		((trigger_data->mode & MODE_TX) ? dev_stats->tx_packets : 0) +
       
   369 +		((trigger_data->mode & MODE_RX) ? dev_stats->rx_packets : 0);
       
   370 +
       
   371 +	if (trigger_data->mode & MODE_LINK) {
       
   372 +		/* base state is ON (link present) */
       
   373 +		/* if there's no link, we don't get this far
       
   374 +		   and the LED is off */
       
   375 +
       
   376 +		/* OFF -> ON always */
       
   377 +		/* ON -> OFF on activity */
       
   378 +		if (trigger_data->led_cdev->brightness == LED_OFF)
       
   379 +			led_set_brightness(trigger_data->led_cdev, LED_FULL);
       
   380 +		else if (trigger_data->last_activity != new_activity)
       
   381 +			led_set_brightness(trigger_data->led_cdev, LED_OFF);
       
   382 +	} else {
       
   383 +		/* base state is OFF */
       
   384 +		/* ON -> OFF always */
       
   385 +		/* OFF -> ON on activity */
       
   386 +		if (trigger_data->led_cdev->brightness == LED_FULL)
       
   387 +			led_set_brightness(trigger_data->led_cdev, LED_OFF);
       
   388 +		else if (trigger_data->last_activity != new_activity)
       
   389 +			led_set_brightness(trigger_data->led_cdev, LED_FULL);
       
   390 +	}
       
   391 +
       
   392 +	trigger_data->last_activity = new_activity;
       
   393 +	mod_timer(&trigger_data->timer, jiffies + trigger_data->interval);
       
   394 +
       
   395 +no_restart:
       
   396 +	write_unlock(&trigger_data->lock);
       
   397 +}
       
   398 +
       
   399 +static void netdev_trig_activate(struct led_classdev *led_cdev)
       
   400 +{
       
   401 +	struct led_netdev_data *trigger_data;
       
   402 +	int rc;
       
   403 +
       
   404 +	trigger_data = kzalloc(sizeof(struct led_netdev_data), GFP_KERNEL);
       
   405 +	if (!trigger_data)
       
   406 +		return;
       
   407 +
       
   408 +	rwlock_init(&trigger_data->lock);
       
   409 +
       
   410 +	trigger_data->notifier.notifier_call = netdev_trig_notify;
       
   411 +	trigger_data->notifier.priority = 10;
       
   412 +
       
   413 +	setup_timer(&trigger_data->timer, netdev_trig_timer,
       
   414 +		    (unsigned long) trigger_data);
       
   415 +
       
   416 +	trigger_data->led_cdev = led_cdev;
       
   417 +	trigger_data->net_dev = NULL;
       
   418 +	trigger_data->device_name[0] = 0;
       
   419 +
       
   420 +	trigger_data->mode = 0;
       
   421 +	trigger_data->interval = msecs_to_jiffies(50);
       
   422 +	trigger_data->link_up = 0;
       
   423 +	trigger_data->last_activity = 0;
       
   424 +
       
   425 +	led_cdev->trigger_data = trigger_data;
       
   426 +
       
   427 +	rc = device_create_file(led_cdev->dev, &dev_attr_device_name);
       
   428 +	if (rc)
       
   429 +		goto err_out;
       
   430 +	rc = device_create_file(led_cdev->dev, &dev_attr_mode);
       
   431 +	if (rc)
       
   432 +		goto err_out_device_name;
       
   433 +	rc = device_create_file(led_cdev->dev, &dev_attr_interval);
       
   434 +	if (rc)
       
   435 +		goto err_out_mode;
       
   436 +
       
   437 +	register_netdevice_notifier(&trigger_data->notifier);
       
   438 +	return;
       
   439 +
       
   440 +err_out_mode:
       
   441 +	device_remove_file(led_cdev->dev, &dev_attr_mode);
       
   442 +err_out_device_name:
       
   443 +	device_remove_file(led_cdev->dev, &dev_attr_device_name);
       
   444 +err_out:
       
   445 +	led_cdev->trigger_data = NULL;
       
   446 +	kfree(trigger_data);
       
   447 +}
       
   448 +
       
   449 +static void netdev_trig_deactivate(struct led_classdev *led_cdev)
       
   450 +{
       
   451 +	struct led_netdev_data *trigger_data = led_cdev->trigger_data;
       
   452 +
       
   453 +	if (trigger_data) {
       
   454 +		unregister_netdevice_notifier(&trigger_data->notifier);
       
   455 +
       
   456 +		device_remove_file(led_cdev->dev, &dev_attr_device_name);
       
   457 +		device_remove_file(led_cdev->dev, &dev_attr_mode);
       
   458 +		device_remove_file(led_cdev->dev, &dev_attr_interval);
       
   459 +
       
   460 +		write_lock(&trigger_data->lock);
       
   461 +
       
   462 +		if (trigger_data->net_dev) {
       
   463 +			dev_put(trigger_data->net_dev);
       
   464 +			trigger_data->net_dev = NULL;
       
   465 +		}
       
   466 +
       
   467 +		write_unlock(&trigger_data->lock);
       
   468 +
       
   469 +		del_timer_sync(&trigger_data->timer);
       
   470 +
       
   471 +		kfree(trigger_data);
       
   472 +	}
       
   473 +}
       
   474 +
       
   475 +static struct led_trigger netdev_led_trigger = {
       
   476 +	.name	  = "netdev",
       
   477 +	.activate = netdev_trig_activate,
       
   478 +	.deactivate = netdev_trig_deactivate,
       
   479 +};
       
   480 +
       
   481 +static int __init netdev_trig_init(void)
       
   482 +{
       
   483 +	return led_trigger_register(&netdev_led_trigger);
       
   484 +}
       
   485 +
       
   486 +static void __exit netdev_trig_exit(void)
       
   487 +{
       
   488 +	led_trigger_unregister(&netdev_led_trigger);
       
   489 +}
       
   490 +
       
   491 +module_init(netdev_trig_init);
       
   492 +module_exit(netdev_trig_exit);
       
   493 +
       
   494 +MODULE_AUTHOR("Oliver Jowett <oliver@opencloud.com>");
       
   495 +MODULE_DESCRIPTION("Netdev LED trigger");
       
   496 +MODULE_LICENSE("GPL");
       
   497 diff -purN linux-3.11.orig/drivers/leds/trigger/ledtrig-sata-disk.c linux-3.11/drivers/leds/trigger/ledtrig-sata-disk.c
       
   498 --- linux-3.11.orig/drivers/leds/trigger/ledtrig-sata-disk.c	1970-01-01 01:00:00.000000000 +0100
       
   499 +++ linux-3.11/drivers/leds/trigger/ledtrig-sata-disk.c	2013-09-12 23:10:19.343331257 +0200
       
   500 @@ -0,0 +1,64 @@
       
   501 +/*
       
   502 + * LED SATA-Disk Activity Trigger
       
   503 + *
       
   504 + * Copyright 2006 Openedhand Ltd.
       
   505 + *
       
   506 + * Author: Richard Purdie <rpurdie@openedhand.com>
       
   507 + *
       
   508 + * This program is free software; you can redistribute it and/or modify
       
   509 + * it under the terms of the GNU General Public License version 2 as
       
   510 + * published by the Free Software Foundation.
       
   511 + *
       
   512 + */
       
   513 +
       
   514 +#include <linux/module.h>
       
   515 +#include <linux/jiffies.h>
       
   516 +#include <linux/kernel.h>
       
   517 +#include <linux/init.h>
       
   518 +#include <linux/timer.h>
       
   519 +#include <linux/leds.h>
       
   520 +
       
   521 +static void ledtrig_sata_timerfunc(unsigned long data);
       
   522 +
       
   523 +DEFINE_LED_TRIGGER(ledtrig_sata);
       
   524 +static DEFINE_TIMER(ledtrig_sata_timer, ledtrig_sata_timerfunc, 0, 0);
       
   525 +static int sata_activity;
       
   526 +static int sata_lastactivity;
       
   527 +
       
   528 +void ledtrig_sata_activity(void)
       
   529 +{
       
   530 +	sata_activity++;
       
   531 +	if (!timer_pending(&ledtrig_sata_timer))
       
   532 +		mod_timer(&ledtrig_sata_timer, jiffies + msecs_to_jiffies(10));
       
   533 +}
       
   534 +EXPORT_SYMBOL(ledtrig_sata_activity);
       
   535 +
       
   536 +static void ledtrig_sata_timerfunc(unsigned long data)
       
   537 +{
       
   538 +	if (sata_lastactivity != sata_activity) {
       
   539 +		sata_lastactivity = sata_activity;
       
   540 +		/* INT_MAX will set each LED to its maximum brightness */
       
   541 +		led_trigger_event(ledtrig_sata, INT_MAX);
       
   542 +		mod_timer(&ledtrig_sata_timer, jiffies + msecs_to_jiffies(10));
       
   543 +	} else {
       
   544 +		led_trigger_event(ledtrig_sata, LED_OFF);
       
   545 +	}
       
   546 +}
       
   547 +
       
   548 +static int __init ledtrig_sata_init(void)
       
   549 +{
       
   550 +	led_trigger_register_simple("sata-disk", &ledtrig_sata);
       
   551 +	return 0;
       
   552 +}
       
   553 +
       
   554 +static void __exit ledtrig_sata_exit(void)
       
   555 +{
       
   556 +	led_trigger_unregister_simple(ledtrig_sata);
       
   557 +}
       
   558 +
       
   559 +module_init(ledtrig_sata_init);
       
   560 +module_exit(ledtrig_sata_exit);
       
   561 +
       
   562 +MODULE_AUTHOR("Richard Purdie <rpurdie@openedhand.com>");
       
   563 +MODULE_DESCRIPTION("LED IDE Disk Activity Trigger");
       
   564 +MODULE_LICENSE("GPL");
       
   565 diff -purN linux-3.11.orig/drivers/leds/trigger/Makefile linux-3.11/drivers/leds/trigger/Makefile
       
   566 --- linux-3.11.orig/drivers/leds/trigger/Makefile	2013-09-02 22:46:10.000000000 +0200
       
   567 +++ linux-3.11/drivers/leds/trigger/Makefile	2013-09-12 23:10:19.343331257 +0200
       
   568 @@ -1,6 +1,8 @@
       
   569  obj-$(CONFIG_LEDS_TRIGGER_TIMER)	+= ledtrig-timer.o
       
   570  obj-$(CONFIG_LEDS_TRIGGER_ONESHOT)	+= ledtrig-oneshot.o
       
   571  obj-$(CONFIG_LEDS_TRIGGER_IDE_DISK)	+= ledtrig-ide-disk.o
       
   572 +obj-$(CONFIG_LEDS_TRIGGER_SATA_DISK)	+= ledtrig-sata-disk.o
       
   573 +obj-$(CONFIG_LEDS_TRIGGER_NETDEV)      += ledtrig-netdev.o 
       
   574  obj-$(CONFIG_LEDS_TRIGGER_HEARTBEAT)	+= ledtrig-heartbeat.o
       
   575  obj-$(CONFIG_LEDS_TRIGGER_BACKLIGHT)	+= ledtrig-backlight.o
       
   576  obj-$(CONFIG_LEDS_TRIGGER_GPIO)		+= ledtrig-gpio.o
       
   577 diff -purN linux-3.11.orig/include/linux/leds.h linux-3.11/include/linux/leds.h
       
   578 --- linux-3.11.orig/include/linux/leds.h	2013-09-02 22:46:10.000000000 +0200
       
   579 +++ linux-3.11/include/linux/leds.h	2013-09-12 23:10:19.346664574 +0200
       
   580 @@ -226,6 +226,12 @@ static inline void ledtrig_flash_ctrl(bo
       
   581  static inline void ledtrig_torch_ctrl(bool on) {}
       
   582  #endif
       
   583  
       
   584 +#ifdef CONFIG_LEDS_TRIGGER_SATA_DISK
       
   585 +extern void ledtrig_sata_activity(void);
       
   586 +#else
       
   587 +#define ledtrig_sata_activity() do {} while(0)
       
   588 +#endif
       
   589 +
       
   590  /*
       
   591   * Generic LED platform data for describing LED names and default triggers.
       
   592   */
       
   593 diff -purN linux-3.11.orig/drivers/ata/sata_mv.c linux-3.11/drivers/ata/sata_mv.c
       
   594 --- linux-3.11.orig/drivers/ata/sata_mv.c	2013-09-02 22:46:10.000000000 +0200
       
   595 +++ linux-3.11/drivers/ata/sata_mv.c	2013-09-12 23:10:19.343331257 +0200
       
   596 @@ -71,6 +71,7 @@
       
   597  #include <scsi/scsi_cmnd.h>
       
   598  #include <scsi/scsi_device.h>
       
   599  #include <linux/libata.h>
       
   600 +#include <linux/leds.h>
       
   601  
       
   602  #define DRV_NAME	"sata_mv"
       
   603  #define DRV_VERSION	"1.28"
       
   604 @@ -1156,6 +1157,8 @@ static void mv_start_edma(struct ata_por
       
   605  {
       
   606  	int want_ncq = (protocol == ATA_PROT_NCQ);
       
   607  
       
   608 +	ledtrig_sata_activity();
       
   609 +
       
   610  	if (pp->pp_flags & MV_PP_FLAG_EDMA_EN) {
       
   611  		int using_ncq = ((pp->pp_flags & MV_PP_FLAG_NCQ_EN) != 0);
       
   612  		if (want_ncq != using_ncq)
       
   613 --- linux-3.11/arch/arm/mach-kirkwood/dns320l-setup.c.orig	2013-10-15 18:55:07.894007006 +0200
       
   614 +++ linux-3.11/arch/arm/mach-kirkwood/dns320l-setup.c	2013-10-15 18:55:33.193954386 +0200
       
   615 @@ -155,12 +155,12 @@ static struct gpio_led dns320l_led_pins[
       
   616  	{
       
   617  	    .name   = "dns320l:blue:sata0",
       
   618  	    .gpio   = DNS320L_GPIO_LED_SATA0_BLUE,
       
   619 -	    .default_trigger = "ide-disk"
       
   620 +	    .default_trigger = "sata-disk"
       
   621  	},
       
   622  	{
       
   623  	    .name   = "dns320l:blue:sata1",
       
   624  	    .gpio   = DNS320L_GPIO_LED_SATA1_BLUE,
       
   625 -	    .default_trigger = "ide-disk"
       
   626 +	    .default_trigger = "sata-disk"
       
   627  	},
       
   628  	{
       
   629  	    .name   = "dns320l:red:sata0",