Merge branch 'mtd-nand-trigger' of git://git.kernel.org/pub/scm/linux/kernel/git/j.anaszewski/linux-leds into nand/next

Pull leds-trigger changes from Jacek Anaszewski.
Create a generic mtd led-trigger to replace the exisitng nand led-trigger
implementation.

* 'mtd-nand-trigger' of git://git.kernel.org/pub/scm/linux/kernel/git/j.anaszewski/linux-leds:
  mtd: Hook I/O activity to the MTD LED trigger
  mtd: nand: Remove the "nand-disk" LED trigger
  leds: trigger: Introduce a MTD (NAND/NOR) trigger
  mtd: Uninline mtd_write_oob and move it to mtdcore.c
  leds: trigger: Introduce a kernel panic LED trigger
This commit is contained in:
Boris Brezillon 2016-04-19 21:44:11 +02:00
commit 8de53481b4
8 changed files with 119 additions and 39 deletions

View File

@ -41,6 +41,14 @@ config LEDS_TRIGGER_IDE_DISK
This allows LEDs to be controlled by IDE disk activity. This allows LEDs to be controlled by IDE disk activity.
If unsure, say Y. 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 config LEDS_TRIGGER_HEARTBEAT
tristate "LED Heartbeat Trigger" tristate "LED Heartbeat Trigger"
depends on LEDS_TRIGGERS depends on LEDS_TRIGGERS
@ -108,4 +116,11 @@ config LEDS_TRIGGER_CAMERA
This enables direct flash/torch on/off by the driver, kernel space. This enables direct flash/torch on/off by the driver, kernel space.
If unsure, say Y. 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.
If unsure, say Y.
endif # LEDS_TRIGGERS endif # LEDS_TRIGGERS

View File

@ -1,6 +1,7 @@
obj-$(CONFIG_LEDS_TRIGGER_TIMER) += ledtrig-timer.o obj-$(CONFIG_LEDS_TRIGGER_TIMER) += ledtrig-timer.o
obj-$(CONFIG_LEDS_TRIGGER_ONESHOT) += ledtrig-oneshot.o obj-$(CONFIG_LEDS_TRIGGER_ONESHOT) += ledtrig-oneshot.o
obj-$(CONFIG_LEDS_TRIGGER_IDE_DISK) += ledtrig-ide-disk.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_HEARTBEAT) += ledtrig-heartbeat.o
obj-$(CONFIG_LEDS_TRIGGER_BACKLIGHT) += ledtrig-backlight.o obj-$(CONFIG_LEDS_TRIGGER_BACKLIGHT) += ledtrig-backlight.o
obj-$(CONFIG_LEDS_TRIGGER_GPIO) += ledtrig-gpio.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_DEFAULT_ON) += ledtrig-default-on.o
obj-$(CONFIG_LEDS_TRIGGER_TRANSIENT) += ledtrig-transient.o obj-$(CONFIG_LEDS_TRIGGER_TRANSIENT) += ledtrig-transient.o
obj-$(CONFIG_LEDS_TRIGGER_CAMERA) += ledtrig-camera.o obj-$(CONFIG_LEDS_TRIGGER_CAMERA) += ledtrig-camera.o
obj-$(CONFIG_LEDS_TRIGGER_PANIC) += ledtrig-panic.o

View File

@ -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);

View File

@ -0,0 +1,30 @@
/*
* 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/leds.h>
static struct led_trigger *trigger;
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)
{
led_trigger_register_simple("panic", &trigger);
panic_blink = led_panic_blink;
return 0;
}
device_initcall(ledtrig_panic_init);

View File

@ -40,6 +40,7 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/reboot.h> #include <linux/reboot.h>
#include <linux/kconfig.h> #include <linux/kconfig.h>
#include <linux/leds.h>
#include <linux/mtd/mtd.h> #include <linux/mtd/mtd.h>
#include <linux/mtd/partitions.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); mtd_erase_callback(instr);
return 0; return 0;
} }
ledtrig_mtd_activity();
return mtd->_erase(mtd, instr); return mtd->_erase(mtd, instr);
} }
EXPORT_SYMBOL_GPL(mtd_erase); 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) if (!len)
return 0; return 0;
ledtrig_mtd_activity();
/* /*
* In the absence of an error, drivers return a non-negative integer * In the absence of an error, drivers return a non-negative integer
* representing the maximum number of bitflips that were corrected on * 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; return -EROFS;
if (!len) if (!len)
return 0; return 0;
ledtrig_mtd_activity();
return mtd->_write(mtd, to, len, retlen, buf); return mtd->_write(mtd, to, len, retlen, buf);
} }
EXPORT_SYMBOL_GPL(mtd_write); 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; ops->retlen = ops->oobretlen = 0;
if (!mtd->_read_oob) if (!mtd->_read_oob)
return -EOPNOTSUPP; return -EOPNOTSUPP;
ledtrig_mtd_activity();
/* /*
* In cases where ops->datbuf != NULL, mtd->_read_oob() has semantics * In cases where ops->datbuf != NULL, mtd->_read_oob() has semantics
* similar to mtd->_read(), returning a non-negative integer * 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); 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 * 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 * devices. The user data is one time programmable but the factory data is read

View File

@ -43,7 +43,6 @@
#include <linux/mtd/nand_bch.h> #include <linux/mtd/nand_bch.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/bitops.h> #include <linux/bitops.h>
#include <linux/leds.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/mtd/partitions.h> #include <linux/mtd/partitions.h>
#include <linux/of_mtd.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, static int nand_do_write_oob(struct mtd_info *mtd, loff_t to,
struct mtd_oob_ops *ops); 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, static int check_offs_len(struct mtd_info *mtd,
loff_t ofs, uint64_t len) loff_t ofs, uint64_t len)
{ {
@ -540,19 +533,16 @@ void nand_wait_ready(struct mtd_info *mtd)
if (in_interrupt() || oops_in_progress) if (in_interrupt() || oops_in_progress)
return panic_nand_wait_ready(mtd, timeo); return panic_nand_wait_ready(mtd, timeo);
led_trigger_event(nand_led_trigger, LED_FULL);
/* Wait until command is processed or timeout occurs */ /* Wait until command is processed or timeout occurs */
timeo = jiffies + msecs_to_jiffies(timeo); timeo = jiffies + msecs_to_jiffies(timeo);
do { do {
if (chip->dev_ready(mtd)) if (chip->dev_ready(mtd))
goto out; return;
cond_resched(); cond_resched();
} while (time_before(jiffies, timeo)); } while (time_before(jiffies, timeo));
if (!chip->dev_ready(mtd)) if (!chip->dev_ready(mtd))
pr_warn_ratelimited("timeout while waiting for chip to become ready\n"); 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); EXPORT_SYMBOL_GPL(nand_wait_ready);
@ -885,8 +875,6 @@ static int nand_wait(struct mtd_info *mtd, struct nand_chip *chip)
int status; int status;
unsigned long timeo = 400; 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 * Apply this short delay always to ensure that we do wait tWB in any
* case on any machine. * case on any machine.
@ -910,7 +898,6 @@ static int nand_wait(struct mtd_info *mtd, struct nand_chip *chip)
cond_resched(); cond_resched();
} while (time_before(jiffies, timeo)); } while (time_before(jiffies, timeo));
} }
led_trigger_event(nand_led_trigger, LED_OFF);
status = (int)chip->read_byte(mtd); status = (int)chip->read_byte(mtd);
/* This can happen if in case of timeout or buggy dev_ready */ /* This can happen if in case of timeout or buggy dev_ready */
@ -4474,20 +4461,6 @@ void nand_release(struct mtd_info *mtd)
} }
EXPORT_SYMBOL_GPL(nand_release); 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_LICENSE("GPL");
MODULE_AUTHOR("Steven J. Hill <sjhill@realitydiluted.com>"); MODULE_AUTHOR("Steven J. Hill <sjhill@realitydiluted.com>");
MODULE_AUTHOR("Thomas Gleixner <tglx@linutronix.de>"); MODULE_AUTHOR("Thomas Gleixner <tglx@linutronix.de>");

View File

@ -329,6 +329,12 @@ extern void ledtrig_ide_activity(void);
static inline void ledtrig_ide_activity(void) {} static inline void ledtrig_ide_activity(void) {}
#endif #endif
#ifdef CONFIG_LEDS_TRIGGER_MTD
extern void ledtrig_mtd_activity(void);
#else
static inline void ledtrig_mtd_activity(void) {}
#endif
#if defined(CONFIG_LEDS_TRIGGER_CAMERA) || defined(CONFIG_LEDS_TRIGGER_CAMERA_MODULE) #if defined(CONFIG_LEDS_TRIGGER_CAMERA) || defined(CONFIG_LEDS_TRIGGER_CAMERA_MODULE)
extern void ledtrig_flash_ctrl(bool on); extern void ledtrig_flash_ctrl(bool on);
extern void ledtrig_torch_ctrl(bool on); extern void ledtrig_torch_ctrl(bool on);

View File

@ -283,17 +283,7 @@ int mtd_panic_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen,
const u_char *buf); const u_char *buf);
int mtd_read_oob(struct mtd_info *mtd, loff_t from, struct mtd_oob_ops *ops); int mtd_read_oob(struct mtd_info *mtd, loff_t from, struct mtd_oob_ops *ops);
int mtd_write_oob(struct mtd_info *mtd, loff_t to, struct mtd_oob_ops *ops);
static inline 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;
return mtd->_write_oob(mtd, to, ops);
}
int mtd_get_fact_prot_info(struct mtd_info *mtd, size_t len, size_t *retlen, int mtd_get_fact_prot_info(struct mtd_info *mtd, size_t len, size_t *retlen,
struct otp_info *buf); struct otp_info *buf);