Skip to content

Commit

Permalink
PCI: Skip attaching driver in device_add()
Browse files Browse the repository at this point in the history
We want to add PCI devices to the device tree as early as possible but
delay attaching drivers.

device_add() adds a device to the device hierarchy and (via
device_attach()) attaches a matching driver and calls its .probe() method.
We want to separate adding the device to the hierarchy from attaching the
driver.

This patch does that by adding "match_driver" in struct pci_dev.  When
false, we return failure from pci_bus_match(), which makes device_attach()
believe there's no matching driver.

Later, we set "match_driver = true" and call device_attach() again, which
now attaches the driver and calls its .probe() method.

[bhelgaas: changelog, explicitly init dev->match_driver,
fold device_attach() call into pci_bus_add_device()]
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
  • Loading branch information
Yinghai Lu authored and Bjorn Helgaas committed Jan 25, 2013
1 parent d59f53b commit 58d9a38
Show file tree
Hide file tree
Showing 3 changed files with 11 additions and 1 deletion.
5 changes: 5 additions & 0 deletions drivers/pci/bus.c
Original file line number Diff line number Diff line change
Expand Up @@ -177,10 +177,15 @@ int pci_bus_add_device(struct pci_dev *dev)
if (retval)
return retval;

dev->match_driver = false;
retval = device_add(&dev->dev);
if (retval)
return retval;

dev->match_driver = true;
retval = device_attach(&dev->dev);
WARN_ON(retval < 0);

dev->is_added = 1;
pci_proc_attach_device(dev);
pci_create_sysfs_dev_files(dev);
Expand Down
6 changes: 5 additions & 1 deletion drivers/pci/pci-driver.c
Original file line number Diff line number Diff line change
Expand Up @@ -1186,9 +1186,13 @@ pci_dev_driver(const struct pci_dev *dev)
static int pci_bus_match(struct device *dev, struct device_driver *drv)
{
struct pci_dev *pci_dev = to_pci_dev(dev);
struct pci_driver *pci_drv = to_pci_driver(drv);
struct pci_driver *pci_drv;
const struct pci_device_id *found_id;

if (!pci_dev->match_driver)
return 0;

pci_drv = to_pci_driver(drv);
found_id = pci_match_device(pci_drv, pci_dev);
if (found_id)
return 1;
Expand Down
1 change: 1 addition & 0 deletions include/linux/pci.h
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,7 @@ struct pci_dev {
unsigned int irq;
struct resource resource[DEVICE_COUNT_RESOURCE]; /* I/O and memory regions + expansion ROMs */

bool match_driver; /* Skip attaching driver */
/* These fields are used by common fixups */
unsigned int transparent:1; /* Transparent PCI bridge */
unsigned int multifunction:1;/* Part of multi-function device */
Expand Down

0 comments on commit 58d9a38

Please sign in to comment.