On Fri, Dec 29, 2006 at 02:27:59PM +0100, Ard -kwaak- van Breemen wrote: > I will clean up the patches found on this list to fix and detect this.
Preliminary patches: - pci fix of Andrews patches - parse-one detection of Yanmin - start_kernel detection and workaround (disable them again) These are the patches that I am about to test in the next 2 hours... :-) Anyway: I think it is possible that other drivers are also potential irq enablers as soon as they are called from parse_one. Usually I compile network drivers as modules, but in diskless setups this might not be the case :-). -- program signature; begin { telegraaf.com } writeln("<[EMAIL PROTECTED]> TEM2"); end .
--- linux-2.6.19.vanilla/drivers/pci/search.c 2006-11-29 21:57:37.000000000 +0000 +++ linux-2.6.19/drivers/pci/search.c 2006-12-29 13:58:51.000000000 +0000 @@ -193,6 +193,17 @@ struct pci_dev *dev; WARN_ON(in_interrupt()); + + /* + * pci_find_subsys() can be called on the ide_setup() path, super-early + * in boot. But the down_read() will enable local interrupts, which + * can cause some machines to crash. So here we detect and flag that + * situation and bail out early. + */ + if(unlikely(list_empty(&pci_devices))) { + printk(KERN_INFO "pci_find_subsys() called while pci_devices is still empty\n"); + return NULL; + } down_read(&pci_bus_sem); n = from ? from->global_list.next : pci_devices.next; @@ -259,6 +270,16 @@ struct pci_dev *dev; WARN_ON(in_interrupt()); + /* + * pci_get_subsys() can potentially be called by drivers super-early + * in boot. But the down_read() will enable local interrupts, which + * can cause some machines to crash. So here we detect and flag that + * situation and bail out early. + */ + if(unlikely(list_empty(&pci_devices))) { + printk(KERN_NOTICE "pci_get_subsys() called while pci_devices is still empty\n"); + return NULL; + } down_read(&pci_bus_sem); n = from ? from->global_list.next : pci_devices.next;
--- linux-2.6.19.vanilla/kernel/params.c 2006-11-29 21:57:37.000000000 +0000 +++ linux-2.6.19/kernel/params.c 2006-12-29 14:02:48.000000000 +0000 @@ -53,13 +53,20 @@ int (*handle_unknown)(char *param, char *val)) { unsigned int i; + int result; + int irq_was_disabled; /* Find parameter */ for (i = 0; i < num_params; i++) { if (parameq(param, params[i].name)) { DEBUGP("They are equal! Calling %p\n", params[i].set); - return params[i].set(val, ¶ms[i]); + irq_was_disabled = irqs_disabled(); + result=params[i].set(val, ¶ms[i]); + if (irq_was_disabled && !irqs_disabled()) { + printk(KERN_WARNING "[BUG] parse_one: kerneloption '%s' enabled irq!\n",param); + } + return result; } }
--- linux-2.6.19.vanilla/init/main.c 2006-11-29 21:57:37.000000000 +0000 +++ linux-2.6.19/init/main.c 2006-12-29 13:58:37.000000000 +0000 @@ -525,6 +525,10 @@ parse_args("Booting kernel", command_line, __start___param, __stop___param - __start___param, &unknown_bootoption); + if (!irqs_disabled()) { + printk(KERN_WARNING "start_kernel(): bug: interrupts were enabled *very* early, fixing it\n"); + local_irq_disable(); + } sort_main_extable(); trap_init(); rcu_init();