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, &params[i]);
+                       irq_was_disabled = irqs_disabled();
+                       result=params[i].set(val, &params[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();

Reply via email to