--- /dev/null
+---
+ drivers/base/dd.c | 82 ++++++++++++++++++++++++++++++++---------------
+ drivers/pci/pci-driver.c | 1
+ drivers/scsi/ata_piix.c | 3 +
+ include/linux/device.h | 2 +
+ 4 files changed, 63 insertions(+), 25 deletions(-)
+
+--- gregkh-2.6.orig/drivers/base/dd.c
++++ gregkh-2.6/drivers/base/dd.c
+@@ -17,6 +17,7 @@
+
+ #include <linux/device.h>
+ #include <linux/module.h>
++#include <linux/kthread.h>
+
+ #include "base.h"
+ #include "power/power.h"
+@@ -51,32 +52,18 @@ void device_bind_driver(struct device *
+ sysfs_create_link(&dev->kobj, &dev->driver->kobj, "driver");
+ }
+
+-/**
+- * driver_probe_device - attempt to bind device & driver.
+- * @drv: driver.
+- * @dev: device.
+- *
+- * First, we call the bus's match function, if one present, which
+- * should compare the device IDs the driver supports with the
+- * device IDs of the device. Note we don't do this ourselves
+- * because we don't know the format of the ID structures, nor what
+- * is to be considered a match and what is not.
+- *
+- * This function returns 1 if a match is found, an error if one
+- * occurs (that is not -ENODEV or -ENXIO), and 0 otherwise.
+- *
+- * This function must be called with @dev->sem held. When called
+- * for a USB interface, @dev->parent->sem must be held as well.
+- */
+-int driver_probe_device(struct device_driver * drv, struct device * dev)
++struct stupid_thread_structure {
++ struct device_driver *drv;
++ struct device *dev;
++};
++
++static int really_probe(void *void_data)
+ {
++ struct stupid_thread_structure *data = void_data;
++ struct device_driver *drv = data->drv;
++ struct device *dev = data->dev;
+ int ret = 0;
+
+- if (drv->bus->match && !drv->bus->match(dev, drv))
+- goto Done;
+-
+- pr_debug("%s: Matched Device %s with Driver %s\n",
+- drv->bus->name, dev->bus_id, drv->name);
+ dev->driver = drv;
+ if (dev->bus->probe) {
+ ret = dev->bus->probe(dev);
+@@ -97,7 +84,7 @@ int driver_probe_device(struct device_dr
+ drv->bus->name, dev->bus_id, drv->name);
+ goto Done;
+
+- ProbeFailed:
++ProbeFailed:
+ if (ret == -ENODEV || ret == -ENXIO) {
+ /* Driver matched, but didn't support device
+ * or device not found.
+@@ -110,7 +97,52 @@ int driver_probe_device(struct device_dr
+ "%s: probe of %s failed with error %d\n",
+ drv->name, dev->bus_id, ret);
+ }
+- Done:
++Done:
++ kfree(data);
++ return ret;
++}
++
++/**
++ * driver_probe_device - attempt to bind device & driver.
++ * @drv: driver.
++ * @dev: device.
++ *
++ * First, we call the bus's match function, if one present, which
++ * should compare the device IDs the driver supports with the
++ * device IDs of the device. Note we don't do this ourselves
++ * because we don't know the format of the ID structures, nor what
++ * is to be considered a match and what is not.
++ *
++ * This function returns 1 if a match is found, an error if one
++ * occurs (that is not -ENODEV or -ENXIO), and 0 otherwise.
++ *
++ * This function must be called with @dev->sem held. When called
++ * for a USB interface, @dev->parent->sem must be held as well.
++ */
++int driver_probe_device(struct device_driver * drv, struct device * dev)
++{
++ struct stupid_thread_structure *data;
++ struct task_struct *probe_task;
++ int ret = 0;
++
++ if (drv->bus->match && !drv->bus->match(dev, drv))
++ goto Done;
++
++ pr_debug("%s: Matched Device %s with Driver %s\n",
++ drv->bus->name, dev->bus_id, drv->name);
++
++ data = kmalloc(sizeof(*data), GFP_KERNEL);
++ data->drv = drv;
++ data->dev = dev;
++
++ if (drv->multithread_probe) {
++ probe_task = kthread_run(really_probe, data, "probe");
++ if (IS_ERR(probe_task))
++ ret = PTR_ERR(probe_task);
++ } else
++ ret = really_probe(data);
++
++Done:
+ return ret;
+ }
+
+--- gregkh-2.6.orig/drivers/pci/pci-driver.c
++++ gregkh-2.6/drivers/pci/pci-driver.c
+@@ -422,6 +422,7 @@ int __pci_register_driver(struct pci_dri
+ drv->driver.bus = &pci_bus_type;
+ drv->driver.owner = owner;
+ drv->driver.kobj.ktype = &pci_driver_kobj_type;
++ drv->driver.multithread_probe = 1;
+
+ spin_lock_init(&drv->dynids.lock);
+ INIT_LIST_HEAD(&drv->dynids.list);
+--- gregkh-2.6.orig/drivers/scsi/ata_piix.c
++++ gregkh-2.6/drivers/scsi/ata_piix.c
+@@ -202,6 +202,9 @@ static struct pci_driver piix_pci_driver
+ .remove = ata_pci_remove_one,
+ .suspend = ata_pci_device_suspend,
+ .resume = ata_pci_device_resume,
++ .driver = {
++ .multithread_probe = 1,
++ },
+ };
+
+ static struct scsi_host_template piix_sht = {
+--- gregkh-2.6.orig/include/linux/device.h
++++ gregkh-2.6/include/linux/device.h
+@@ -105,6 +105,8 @@ struct device_driver {
+ void (*shutdown) (struct device * dev);
+ int (*suspend) (struct device * dev, pm_message_t state);
+ int (*resume) (struct device * dev);
++
++ unsigned int multithread_probe:1;
+ };
+
+