Clean up several code points in which the return code from misc_register is
not handled properly.
Several modules failed to deregister various hooks when misc_register fails,
and this patch cleans them up. Also there are a few modules that legitimately
don't care about the failure status of misc register. These drivers however
unilaterally call misc_deregister on module unload.
Since misc_register doesn't initialize the list_head in the init_routine if it
fails, the deregister operation is at risk for oopsing when list_del is
called. The initial solution was to manually init the list in the miscdev
structure in each of those modules, but the consensus in this thread was to
consolodate and do that universally inside misc_register.
Signed-off-by: Neil Horman <nhorman@tuxdriver.com>
Cc: Bjorn Helgaas <bjorn.helgaas@hp.com>
Cc: Kylene Jo Hall <kjhall@us.ibm.com>
Cc: Dmitry Torokhov <dtor@mail.ru>
Cc: Olaf Hering <olh@suse.de>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
+ INIT_LIST_HEAD(&misc->list);
+
down(&misc_sem);
list_for_each_entry(c, &misc_list, list) {
if (c->minor == misc->minor) {
down(&misc_sem);
list_for_each_entry(c, &misc_list, list) {
if (c->minor == misc->minor) {
if (sn_rtc_cycles_per_second < 100000) {
printk(KERN_ERR "%s: unable to determine clock frequency\n",
MMTIMER_NAME);
if (sn_rtc_cycles_per_second < 100000) {
printk(KERN_ERR "%s: unable to determine clock frequency\n",
MMTIMER_NAME);
}
mmtimer_femtoperiod = ((unsigned long)1E15 + sn_rtc_cycles_per_second /
}
mmtimer_femtoperiod = ((unsigned long)1E15 + sn_rtc_cycles_per_second /
if (request_irq(SGI_MMTIMER_VECTOR, mmtimer_interrupt, IRQF_PERCPU, MMTIMER_NAME, NULL)) {
printk(KERN_WARNING "%s: unable to allocate interrupt.",
MMTIMER_NAME);
if (request_irq(SGI_MMTIMER_VECTOR, mmtimer_interrupt, IRQF_PERCPU, MMTIMER_NAME, NULL)) {
printk(KERN_WARNING "%s: unable to allocate interrupt.",
MMTIMER_NAME);
}
if (misc_register(&mmtimer_miscdev)) {
printk(KERN_ERR "%s: failed to register device\n",
MMTIMER_NAME);
}
if (misc_register(&mmtimer_miscdev)) {
printk(KERN_ERR "%s: failed to register device\n",
MMTIMER_NAME);
}
/* Get max numbered node, calculate slots needed */
}
/* Get max numbered node, calculate slots needed */
if (timers == NULL) {
printk(KERN_ERR "%s: failed to allocate memory for device\n",
MMTIMER_NAME);
if (timers == NULL) {
printk(KERN_ERR "%s: failed to allocate memory for device\n",
MMTIMER_NAME);
+ memset(timers,0,(sizeof(mmtimer_t *)*maxn));
+
/* Allocate mmtimer_t's for each online node */
for_each_online_node(node) {
timers[node] = kmalloc_node(sizeof(mmtimer_t)*NUM_COMPARATORS, GFP_KERNEL, node);
if (timers[node] == NULL) {
printk(KERN_ERR "%s: failed to allocate memory for device\n",
MMTIMER_NAME);
/* Allocate mmtimer_t's for each online node */
for_each_online_node(node) {
timers[node] = kmalloc_node(sizeof(mmtimer_t)*NUM_COMPARATORS, GFP_KERNEL, node);
if (timers[node] == NULL) {
printk(KERN_ERR "%s: failed to allocate memory for device\n",
MMTIMER_NAME);
}
for (i=0; i< NUM_COMPARATORS; i++) {
mmtimer_t * base = timers[node] + i;
}
for (i=0; i< NUM_COMPARATORS; i++) {
mmtimer_t * base = timers[node] + i;
sn_rtc_cycles_per_second/(unsigned long)1E6);
return 0;
sn_rtc_cycles_per_second/(unsigned long)1E6);
return 0;
+
+out4:
+ for_each_online_node(node) {
+ kfree(timers[node]);
+ }
+out3:
+ misc_deregister(&mmtimer_miscdev);
+out2:
+ free_irq(SGI_MMTIMER_VECTOR, NULL);
+out1:
+ return -1;
}
module_init(mmtimer_init);
}
module_init(mmtimer_init);
if (sysfs_create_group(&dev->kobj, chip->vendor.attr_group)) {
list_del(&chip->list);
if (sysfs_create_group(&dev->kobj, chip->vendor.attr_group)) {
list_del(&chip->list);
+ misc_deregister(&chip->vendor.miscdev);
put_device(dev);
clear_bit(chip->dev_num, dev_mask);
kfree(chip);
put_device(dev);
clear_bit(chip->dev_num, dev_mask);
kfree(chip);
if ((ret = hp_sdc_request_timer_irq(&hp_sdc_rtc_isr)))
return ret;
if ((ret = hp_sdc_request_timer_irq(&hp_sdc_rtc_isr)))
return ret;
- misc_register(&hp_sdc_rtc_dev);
+ if (misc_register(&hp_sdc_rtc_dev) != 0)
+ printk(KERN_INFO "Could not register misc. dev for i8042 rtc\n");
+
create_proc_read_entry ("driver/rtc", 0, NULL,
hp_sdc_rtc_read_proc, NULL);
create_proc_read_entry ("driver/rtc", 0, NULL,
hp_sdc_rtc_read_proc, NULL);
if (apm_proc)
apm_proc->owner = THIS_MODULE;
if (apm_proc)
apm_proc->owner = THIS_MODULE;
- misc_register(&apm_device);
+ if (misc_register(&apm_device) != 0)
+ printk(KERN_INFO "Could not create misc. device for apm\n");
pmu_register_sleep_notifier(&apm_sleep_notifier);
pmu_register_sleep_notifier(&apm_sleep_notifier);