From: Alan Stern Notifier chain re-implementation (as636b): Two notifier chain callout routines try to unregister themselves. The new blocking-notifier API does not support this, so this patch fixes the problem by adding a new flag. Signed-off-by: Alan Stern Signed-off-by: Chandra Seetharaman Signed-off-by: Andrew Morton --- drivers/parisc/led.c | 14 ++++++++++++-- drivers/scsi/gdth.c | 10 ++++++---- 2 files changed, 18 insertions(+), 6 deletions(-) diff -puN drivers/parisc/led.c~notifier-chain-update-dont-unregister-yourself drivers/parisc/led.c --- 25/drivers/parisc/led.c~notifier-chain-update-dont-unregister-yourself Thu Feb 16 15:47:41 2006 +++ 25-akpm/drivers/parisc/led.c Thu Feb 16 15:47:41 2006 @@ -499,11 +499,16 @@ static int led_halt(struct notifier_bloc static struct notifier_block led_notifier = { .notifier_call = led_halt, }; +static int notifier_disabled = 0; static int led_halt(struct notifier_block *nb, unsigned long event, void *buf) { char *txt; - + + if (notifier_disabled) + return NOTIFY_OK; + + notifier_disabled = 1; switch (event) { case SYS_RESTART: txt = "SYSTEM RESTART"; break; @@ -527,7 +532,6 @@ static int led_halt(struct notifier_bloc if (led_func_ptr) led_func_ptr(0xff); /* turn all LEDs ON */ - unregister_reboot_notifier(&led_notifier); return NOTIFY_OK; } @@ -758,6 +762,12 @@ not_found: return 1; } +static void __exit led_exit(void) +{ + unregister_reboot_notifier(&led_notifier); + return; +} + #ifdef CONFIG_PROC_FS module_init(led_create_procfs) #endif diff -puN drivers/scsi/gdth.c~notifier-chain-update-dont-unregister-yourself drivers/scsi/gdth.c --- 25/drivers/scsi/gdth.c~notifier-chain-update-dont-unregister-yourself Thu Feb 16 15:47:41 2006 +++ 25-akpm/drivers/scsi/gdth.c Thu Feb 16 15:47:41 2006 @@ -671,7 +671,7 @@ static struct file_operations gdth_fops static struct notifier_block gdth_notifier = { gdth_halt, NULL, 0 }; - +static int notifier_disabled = 0; static void gdth_delay(int milliseconds) { @@ -4675,13 +4675,13 @@ static int __init gdth_detect(struct scs add_timer(&gdth_timer); #endif major = register_chrdev(0,"gdth",&gdth_fops); + notifier_disabled = 0; register_reboot_notifier(&gdth_notifier); } gdth_polling = FALSE; return gdth_ctr_vcount; } - static int gdth_release(struct Scsi_Host *shp) { int hanum; @@ -4728,7 +4728,6 @@ static int gdth_release(struct Scsi_Host del_timer(&gdth_timer); #endif unregister_chrdev(major,"gdth"); - unregister_reboot_notifier(&gdth_notifier); } } @@ -5545,10 +5544,14 @@ static int gdth_halt(struct notifier_blo char cmnd[MAX_COMMAND_SIZE]; #endif + if (notifier_disabled) + return NOTIFY_OK; + TRACE2(("gdth_halt() event %d\n",(int)event)); if (event != SYS_RESTART && event != SYS_HALT && event != SYS_POWER_OFF) return NOTIFY_DONE; + notifier_disabled = 1; printk("GDT-HA: Flushing all host drives .. "); for (hanum = 0; hanum < gdth_ctr_count; ++hanum) { gdth_flush(hanum); @@ -5568,7 +5571,6 @@ static int gdth_halt(struct notifier_blo #ifdef GDTH_STATISTICS del_timer(&gdth_timer); #endif - unregister_reboot_notifier(&gdth_notifier); return NOTIFY_OK; } _