From: Philip A. Prindeville <[email protected]> Use RCU protection around a hook to allow ledtrig-ide-disk to instrument itself into ide-disk without requiring static linkage.
Signed-off-by: Philip A. Prindeville <[email protected]> --- drivers/ide/ide-disk.c | 15 ++++++++++++++- drivers/leds/Kconfig | 3 ++- drivers/leds/ledtrig-ide-disk.c | 8 ++++++-- include/linux/leds.h | 10 +++++----- 4 files changed, 27 insertions(+), 9 deletions(-) diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c index 2747980..de472ed 100644 --- a/drivers/ide/ide-disk.c +++ b/drivers/ide/ide-disk.c @@ -178,6 +178,10 @@ static ide_startstop_t __ide_do_rw_disk(ide_drive_t *drive, struct request *rq, * 1073741822 == 549756 MB or 48bit addressing fake drive */ +void __rcu (*ide_activity_hook)(void) __read_mostly = NULL; + +EXPORT_SYMBOL(ide_activity_hook); + static ide_startstop_t ide_do_rw_disk(ide_drive_t *drive, struct request *rq, sector_t block) { @@ -186,7 +190,16 @@ static ide_startstop_t ide_do_rw_disk(ide_drive_t *drive, struct request *rq, BUG_ON(drive->dev_flags & IDE_DFLAG_BLOCKED); BUG_ON(rq->cmd_type != REQ_TYPE_FS); - ledtrig_ide_activity(); + { + void (*ide_activity)(void); + + rcu_read_lock(); + ide_activity = rcu_dereference(ide_activity_hook); + + if (ide_activity) + ide_activity(); + rcu_read_unlock(); + } pr_debug("%s: %sing: block=%llu, sectors=%u, buffer=0x%08lx\n", drive->name, rq_data_dir(rq) == READ ? "read" : "writ", diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig index 4a40561..26e5f03 100644 --- a/drivers/leds/Kconfig +++ b/drivers/leds/Kconfig @@ -411,7 +411,8 @@ config LEDS_TRIGGER_TIMER If unsure, say Y. config LEDS_TRIGGER_IDE_DISK - bool "LED IDE Disk Trigger" + tristate "LED IDE Disk Trigger" + depends on (TREE_RCU || TREE_PREEMPT_RCU || TINY_RCU || TINY_PREEMPT_TCU) depends on IDE_GD_ATA depends on LEDS_TRIGGERS help diff --git a/drivers/leds/ledtrig-ide-disk.c b/drivers/leds/ledtrig-ide-disk.c index ec099fc..77a1f74 100644 --- a/drivers/leds/ledtrig-ide-disk.c +++ b/drivers/leds/ledtrig-ide-disk.c @@ -25,13 +25,12 @@ static DEFINE_TIMER(ledtrig_ide_timer, ledtrig_ide_timerfunc, 0, 0); static int ide_activity; static int ide_lastactivity; -void ledtrig_ide_activity(void) +static void ledtrig_ide_activity(void) { ide_activity++; if (!timer_pending(&ledtrig_ide_timer)) mod_timer(&ledtrig_ide_timer, jiffies + msecs_to_jiffies(10)); } -EXPORT_SYMBOL(ledtrig_ide_activity); static void ledtrig_ide_timerfunc(unsigned long data) { @@ -48,11 +47,16 @@ static void ledtrig_ide_timerfunc(unsigned long data) static int __init ledtrig_ide_init(void) { led_trigger_register_simple("ide-disk", &ledtrig_ide); + + rcu_assign_pointer(ide_activity_hook, ledtrig_ide_activity); return 0; } static void __exit ledtrig_ide_exit(void) { + rcu_assign_pointer(ide_activity_hook, NULL); + synchronize_rcu(); + led_trigger_unregister_simple(ledtrig_ide); } diff --git a/include/linux/leds.h b/include/linux/leds.h index 61e0340..28571f2 100644 --- a/include/linux/leds.h +++ b/include/linux/leds.h @@ -160,11 +160,11 @@ extern void led_trigger_blink(struct led_trigger *trigger, #endif -/* Trigger specific functions */ -#ifdef CONFIG_LEDS_TRIGGER_IDE_DISK -extern void ledtrig_ide_activity(void); -#else -#define ledtrig_ide_activity() do {} while(0) +#if defined(CONFIG_TINY_RCU) || defined(CONFIG_TINY_PREEMPT_RCU) \ + || defined(CONFIG_TREE_RCU) || defined(CONFIG_TREE_PREEMPT_RCU) +#include <linux/rcupdate.h> + +extern void __rcu (*ide_activity_hook)(void) __read_mostly; #endif /* -- 1.7.4.4 _______________________________________________ stable mailing list [email protected] http://linux.kernel.org/mailman/listinfo/stable
