diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/leds/Kconfig | 5 | ||||
-rw-r--r-- | drivers/leds/led-triggers.c | 2 | ||||
-rw-r--r-- | drivers/leds/leds-gpio.c | 4 | ||||
-rw-r--r-- | drivers/leds/leds-ss4200.c | 13 | ||||
-rw-r--r-- | drivers/leds/leds-tca6507.c | 2 | ||||
-rw-r--r-- | drivers/leds/leds.h | 1 | ||||
-rw-r--r-- | drivers/leds/trigger/Kconfig | 18 | ||||
-rw-r--r-- | drivers/leds/trigger/Makefile | 2 | ||||
-rw-r--r-- | drivers/leds/trigger/ledtrig-ide-disk.c | 3 | ||||
-rw-r--r-- | drivers/leds/trigger/ledtrig-mtd.c | 45 | ||||
-rw-r--r-- | drivers/leds/trigger/ledtrig-panic.c | 77 | ||||
-rw-r--r-- | drivers/mtd/mtdcore.c | 19 | ||||
-rw-r--r-- | drivers/mtd/nand/nand_base.c | 29 |
13 files changed, 188 insertions, 32 deletions
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig index 225147863e02..5ae28340a98b 100644 --- a/drivers/leds/Kconfig +++ b/drivers/leds/Kconfig @@ -413,10 +413,11 @@ config LEDS_INTEL_SS4200 tristate "LED driver for Intel NAS SS4200 series" depends on LEDS_CLASS depends on PCI && DMI + depends on X86 help This option enables support for the Intel SS4200 series of - Network Attached Storage servers. You may control the hard - drive or power LEDs on the front panel. Using this driver + Network Attached Storage servers. You may control the hard + drive or power LEDs on the front panel. Using this driver can stop the front LED from blinking after startup. config LEDS_LT3593 diff --git a/drivers/leds/led-triggers.c b/drivers/leds/led-triggers.c index 2181581795d3..55fa65e1ae03 100644 --- a/drivers/leds/led-triggers.c +++ b/drivers/leds/led-triggers.c @@ -26,7 +26,7 @@ * Nests outside led_cdev->trigger_lock */ static DECLARE_RWSEM(triggers_list_lock); -static LIST_HEAD(trigger_list); +LIST_HEAD(trigger_list); /* Used by LED Class */ diff --git a/drivers/leds/leds-gpio.c b/drivers/leds/leds-gpio.c index 61143f55597e..8229f063b483 100644 --- a/drivers/leds/leds-gpio.c +++ b/drivers/leds/leds-gpio.c @@ -127,6 +127,8 @@ static int create_gpio_led(const struct gpio_led *template, led_dat->cdev.brightness = state ? LED_FULL : LED_OFF; if (!template->retain_state_suspended) led_dat->cdev.flags |= LED_CORE_SUSPENDRESUME; + if (template->panic_indicator) + led_dat->cdev.flags |= LED_PANIC_INDICATOR; ret = gpiod_direction_output(led_dat->gpiod, state); if (ret < 0) @@ -200,6 +202,8 @@ static struct gpio_leds_priv *gpio_leds_create(struct platform_device *pdev) if (fwnode_property_present(child, "retain-state-suspended")) led.retain_state_suspended = 1; + if (fwnode_property_present(child, "panic-indicator")) + led.panic_indicator = 1; ret = create_gpio_led(&led, &priv->leds[priv->num_leds], dev, NULL); diff --git a/drivers/leds/leds-ss4200.c b/drivers/leds/leds-ss4200.c index 046cb7008745..732eb86bc1a5 100644 --- a/drivers/leds/leds-ss4200.c +++ b/drivers/leds/leds-ss4200.c @@ -101,6 +101,19 @@ static struct dmi_system_id nas_led_whitelist[] __initdata = { DMI_MATCH(DMI_PRODUCT_VERSION, "1.00.00") } }, + { + /* + * FUJITSU SIEMENS SCALEO Home Server/SS4200-E + * BIOS V090L 12/19/2007 + */ + .callback = ss4200_led_dmi_callback, + .ident = "Fujitsu Siemens SCALEO Home Server", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), + DMI_MATCH(DMI_PRODUCT_NAME, "SCALEO Home Server"), + DMI_MATCH(DMI_PRODUCT_VERSION, "1.00.00") + } + }, {} }; diff --git a/drivers/leds/leds-tca6507.c b/drivers/leds/leds-tca6507.c index c548ea10f0f0..45222a7f4f75 100644 --- a/drivers/leds/leds-tca6507.c +++ b/drivers/leds/leds-tca6507.c @@ -327,6 +327,8 @@ static void set_times(struct tca6507_chip *tca, int bank) int result; result = choose_times(tca->bank[bank].ontime, &c1, &c2); + if (result < 0) + return; dev_dbg(&tca->client->dev, "Chose on times %d(%d) %d(%d) for %dms\n", c1, time_codes[c1], diff --git a/drivers/leds/leds.h b/drivers/leds/leds.h index db3f20da7221..7d38e6b9a740 100644 --- a/drivers/leds/leds.h +++ b/drivers/leds/leds.h @@ -30,5 +30,6 @@ void led_set_brightness_nosleep(struct led_classdev *led_cdev, extern struct rw_semaphore leds_list_lock; extern struct list_head leds_list; +extern struct list_head trigger_list; #endif /* __LEDS_H_INCLUDED */ diff --git a/drivers/leds/trigger/Kconfig b/drivers/leds/trigger/Kconfig index 5bda6a9b56bb..9893d911390d 100644 --- a/drivers/leds/trigger/Kconfig +++ b/drivers/leds/trigger/Kconfig @@ -41,6 +41,14 @@ config LEDS_TRIGGER_IDE_DISK This allows LEDs to be controlled by IDE disk activity. If unsure, say Y. +config LEDS_TRIGGER_MTD + bool "LED MTD (NAND/NOR) Trigger" + depends on MTD + depends on LEDS_TRIGGERS + help + This allows LEDs to be controlled by MTD activity. + If unsure, say N. + config LEDS_TRIGGER_HEARTBEAT tristate "LED Heartbeat Trigger" depends on LEDS_TRIGGERS @@ -108,4 +116,14 @@ config LEDS_TRIGGER_CAMERA This enables direct flash/torch on/off by the driver, kernel space. If unsure, say Y. +config LEDS_TRIGGER_PANIC + bool "LED Panic Trigger" + depends on LEDS_TRIGGERS + help + This allows LEDs to be configured to blink on a kernel panic. + Enabling this option will allow to mark certain LEDs as panic indicators, + allowing to blink them on a kernel panic, even if they are set to + a different trigger. + If unsure, say Y. + endif # LEDS_TRIGGERS diff --git a/drivers/leds/trigger/Makefile b/drivers/leds/trigger/Makefile index 1abf48dacf7e..8cc64a4f4e25 100644 --- a/drivers/leds/trigger/Makefile +++ b/drivers/leds/trigger/Makefile @@ -1,6 +1,7 @@ obj-$(CONFIG_LEDS_TRIGGER_TIMER) += ledtrig-timer.o obj-$(CONFIG_LEDS_TRIGGER_ONESHOT) += ledtrig-oneshot.o obj-$(CONFIG_LEDS_TRIGGER_IDE_DISK) += ledtrig-ide-disk.o +obj-$(CONFIG_LEDS_TRIGGER_MTD) += ledtrig-mtd.o obj-$(CONFIG_LEDS_TRIGGER_HEARTBEAT) += ledtrig-heartbeat.o obj-$(CONFIG_LEDS_TRIGGER_BACKLIGHT) += ledtrig-backlight.o obj-$(CONFIG_LEDS_TRIGGER_GPIO) += ledtrig-gpio.o @@ -8,3 +9,4 @@ obj-$(CONFIG_LEDS_TRIGGER_CPU) += ledtrig-cpu.o obj-$(CONFIG_LEDS_TRIGGER_DEFAULT_ON) += ledtrig-default-on.o obj-$(CONFIG_LEDS_TRIGGER_TRANSIENT) += ledtrig-transient.o obj-$(CONFIG_LEDS_TRIGGER_CAMERA) += ledtrig-camera.o +obj-$(CONFIG_LEDS_TRIGGER_PANIC) += ledtrig-panic.o diff --git a/drivers/leds/trigger/ledtrig-ide-disk.c b/drivers/leds/trigger/ledtrig-ide-disk.c index c02a3ac3cd2b..15123d389240 100644 --- a/drivers/leds/trigger/ledtrig-ide-disk.c +++ b/drivers/leds/trigger/ledtrig-ide-disk.c @@ -18,10 +18,11 @@ #define BLINK_DELAY 30 DEFINE_LED_TRIGGER(ledtrig_ide); -static unsigned long ide_blink_delay = BLINK_DELAY; void ledtrig_ide_activity(void) { + unsigned long ide_blink_delay = BLINK_DELAY; + led_trigger_blink_oneshot(ledtrig_ide, &ide_blink_delay, &ide_blink_delay, 0); } diff --git a/drivers/leds/trigger/ledtrig-mtd.c b/drivers/leds/trigger/ledtrig-mtd.c new file mode 100644 index 000000000000..99b5b0a4d826 --- /dev/null +++ b/drivers/leds/trigger/ledtrig-mtd.c @@ -0,0 +1,45 @@ +/* + * LED MTD trigger + * + * Copyright 2016 Ezequiel Garcia <ezequiel@vanguardiasur.com.ar> + * + * Based on LED IDE-Disk Activity Trigger + * + * Copyright 2006 Openedhand Ltd. + * + * Author: Richard Purdie <rpurdie@openedhand.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/leds.h> + +#define BLINK_DELAY 30 + +DEFINE_LED_TRIGGER(ledtrig_mtd); +DEFINE_LED_TRIGGER(ledtrig_nand); + +void ledtrig_mtd_activity(void) +{ + unsigned long blink_delay = BLINK_DELAY; + + led_trigger_blink_oneshot(ledtrig_mtd, + &blink_delay, &blink_delay, 0); + led_trigger_blink_oneshot(ledtrig_nand, + &blink_delay, &blink_delay, 0); +} +EXPORT_SYMBOL(ledtrig_mtd_activity); + +static int __init ledtrig_mtd_init(void) +{ + led_trigger_register_simple("mtd", &ledtrig_mtd); + led_trigger_register_simple("nand-disk", &ledtrig_nand); + + return 0; +} +device_initcall(ledtrig_mtd_init); diff --git a/drivers/leds/trigger/ledtrig-panic.c b/drivers/leds/trigger/ledtrig-panic.c new file mode 100644 index 000000000000..d735526b9db4 --- /dev/null +++ b/drivers/leds/trigger/ledtrig-panic.c @@ -0,0 +1,77 @@ +/* + * Kernel Panic LED Trigger + * + * Copyright 2016 Ezequiel Garcia <ezequiel@vanguardiasur.com.ar> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/notifier.h> +#include <linux/leds.h> +#include "../leds.h" + +static struct led_trigger *trigger; + +/* + * This is called in a special context by the atomic panic + * notifier. This means the trigger can be changed without + * worrying about locking. + */ +static void led_trigger_set_panic(struct led_classdev *led_cdev) +{ + struct led_trigger *trig; + + list_for_each_entry(trig, &trigger_list, next_trig) { + if (strcmp("panic", trig->name)) + continue; + if (led_cdev->trigger) + list_del(&led_cdev->trig_list); + list_add_tail(&led_cdev->trig_list, &trig->led_cdevs); + + /* Avoid the delayed blink path */ + led_cdev->blink_delay_on = 0; + led_cdev->blink_delay_off = 0; + + led_cdev->trigger = trig; + if (trig->activate) + trig->activate(led_cdev); + break; + } +} + +static int led_trigger_panic_notifier(struct notifier_block *nb, + unsigned long code, void *unused) +{ + struct led_classdev *led_cdev; + + list_for_each_entry(led_cdev, &leds_list, node) + if (led_cdev->flags & LED_PANIC_INDICATOR) + led_trigger_set_panic(led_cdev); + return NOTIFY_DONE; +} + +static struct notifier_block led_trigger_panic_nb = { + .notifier_call = led_trigger_panic_notifier, +}; + +static long led_panic_blink(int state) +{ + led_trigger_event(trigger, state ? LED_FULL : LED_OFF); + return 0; +} + +static int __init ledtrig_panic_init(void) +{ + atomic_notifier_chain_register(&panic_notifier_list, + &led_trigger_panic_nb); + + led_trigger_register_simple("panic", &trigger); + panic_blink = led_panic_blink; + return 0; +} +device_initcall(ledtrig_panic_init); diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c index 309625130b21..bee180bd11e7 100644 --- a/drivers/mtd/mtdcore.c +++ b/drivers/mtd/mtdcore.c @@ -40,6 +40,7 @@ #include <linux/slab.h> #include <linux/reboot.h> #include <linux/kconfig.h> +#include <linux/leds.h> #include <linux/mtd/mtd.h> #include <linux/mtd/partitions.h> @@ -862,6 +863,7 @@ int mtd_erase(struct mtd_info *mtd, struct erase_info *instr) mtd_erase_callback(instr); return 0; } + ledtrig_mtd_activity(); return mtd->_erase(mtd, instr); } EXPORT_SYMBOL_GPL(mtd_erase); @@ -925,6 +927,7 @@ int mtd_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, if (!len) return 0; + ledtrig_mtd_activity(); /* * In the absence of an error, drivers return a non-negative integer * representing the maximum number of bitflips that were corrected on @@ -949,6 +952,7 @@ int mtd_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, return -EROFS; if (!len) return 0; + ledtrig_mtd_activity(); return mtd->_write(mtd, to, len, retlen, buf); } EXPORT_SYMBOL_GPL(mtd_write); @@ -982,6 +986,8 @@ int mtd_read_oob(struct mtd_info *mtd, loff_t from, struct mtd_oob_ops *ops) ops->retlen = ops->oobretlen = 0; if (!mtd->_read_oob) return -EOPNOTSUPP; + + ledtrig_mtd_activity(); /* * In cases where ops->datbuf != NULL, mtd->_read_oob() has semantics * similar to mtd->_read(), returning a non-negative integer @@ -997,6 +1003,19 @@ int mtd_read_oob(struct mtd_info *mtd, loff_t from, struct mtd_oob_ops *ops) } EXPORT_SYMBOL_GPL(mtd_read_oob); +int mtd_write_oob(struct mtd_info *mtd, loff_t to, + struct mtd_oob_ops *ops) +{ + ops->retlen = ops->oobretlen = 0; + if (!mtd->_write_oob) + return -EOPNOTSUPP; + if (!(mtd->flags & MTD_WRITEABLE)) + return -EROFS; + ledtrig_mtd_activity(); + return mtd->_write_oob(mtd, to, ops); +} +EXPORT_SYMBOL_GPL(mtd_write_oob); + /* * Method to access the protection register area, present in some flash * devices. The user data is one time programmable but the factory data is read diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index 557b8462f55e..ba4f603e0537 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -43,7 +43,6 @@ #include <linux/mtd/nand_bch.h> #include <linux/interrupt.h> #include <linux/bitops.h> -#include <linux/leds.h> #include <linux/io.h> #include <linux/mtd/partitions.h> #include <linux/of_mtd.h> @@ -97,12 +96,6 @@ static int nand_get_device(struct mtd_info *mtd, int new_state); static int nand_do_write_oob(struct mtd_info *mtd, loff_t to, struct mtd_oob_ops *ops); -/* - * For devices which display every fart in the system on a separate LED. Is - * compiled away when LED support is disabled. - */ -DEFINE_LED_TRIGGER(nand_led_trigger); - static int check_offs_len(struct mtd_info *mtd, loff_t ofs, uint64_t len) { @@ -540,19 +533,16 @@ void nand_wait_ready(struct mtd_info *mtd) if (in_interrupt() || oops_in_progress) return panic_nand_wait_ready(mtd, timeo); - led_trigger_event(nand_led_trigger, LED_FULL); /* Wait until command is processed or timeout occurs */ timeo = jiffies + msecs_to_jiffies(timeo); do { if (chip->dev_ready(mtd)) - goto out; + return; cond_resched(); } while (time_before(jiffies, timeo)); if (!chip->dev_ready(mtd)) pr_warn_ratelimited("timeout while waiting for chip to become ready\n"); -out: - led_trigger_event(nand_led_trigger, LED_OFF); } EXPORT_SYMBOL_GPL(nand_wait_ready); @@ -885,8 +875,6 @@ static int nand_wait(struct mtd_info *mtd, struct nand_chip *chip) int status; unsigned long timeo = 400; - led_trigger_event(nand_led_trigger, LED_FULL); - /* * Apply this short delay always to ensure that we do wait tWB in any * case on any machine. @@ -910,7 +898,6 @@ static int nand_wait(struct mtd_info *mtd, struct nand_chip *chip) cond_resched(); } while (time_before(jiffies, timeo)); } - led_trigger_event(nand_led_trigger, LED_OFF); status = (int)chip->read_byte(mtd); /* This can happen if in case of timeout or buggy dev_ready */ @@ -4466,20 +4453,6 @@ void nand_release(struct mtd_info *mtd) } EXPORT_SYMBOL_GPL(nand_release); -static int __init nand_base_init(void) -{ - led_trigger_register_simple("nand-disk", &nand_led_trigger); - return 0; -} - -static void __exit nand_base_exit(void) -{ - led_trigger_unregister_simple(nand_led_trigger); -} - -module_init(nand_base_init); -module_exit(nand_base_exit); - MODULE_LICENSE("GPL"); MODULE_AUTHOR("Steven J. Hill <sjhill@realitydiluted.com>"); MODULE_AUTHOR("Thomas Gleixner <tglx@linutronix.de>"); |