From patchwork Mon Jan 21 21:20:51 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: [v10,10/11] PCI: Skip attaching driver in device_add() Date: Mon, 21 Jan 2013 11:20:51 -0000 From: Yinghai Lu X-Patchwork-Id: 214258 Message-Id: <1358803252-20639-11-git-send-email-yinghai@kernel.org> To: Bjorn Helgaas , "Rafael J. Wysocki" , Len Brown , Taku Izumi , Jiang Liu Cc: linux-pci@vger.kernel.org, linux-kernel@vger.kernel.org, linux-acpi@vger.kernel.org, Yinghai Lu We want to add pci device to device tree as early as possible but delay attach driver in next following path. To make that patch smaller, in this patch: We add match_driver field in pci_dev and default vaule is false, it will make pci_bus_match fail, so device_add will skip attaching driver, then pci_bus_attach_device() will set match_driver to true so pci_bus_match will return true and device_attach will attach driver to pci device. Signed-off-by: Yinghai Lu Acked-by: Rafael J. Wysocki --- drivers/pci/bus.c | 10 ++++++++++ drivers/pci/pci-driver.c | 6 +++++- include/linux/pci.h | 1 + 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c index 847f3ca..18c1c6d 100644 --- a/drivers/pci/bus.c +++ b/drivers/pci/bus.c @@ -160,6 +160,15 @@ pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res, void __weak pcibios_resource_survey_bus(struct pci_bus *bus) { } +static void pci_bus_attach_device(struct pci_dev *dev) +{ + int ret; + + dev->match_driver = true; + ret = device_attach(&dev->dev); + WARN_ON(ret < 0); +} + /** * pci_bus_add_device - add a single device * @dev: device to add @@ -181,6 +190,7 @@ int pci_bus_add_device(struct pci_dev *dev) if (retval) return retval; + pci_bus_attach_device(dev); dev->is_added = 1; pci_proc_attach_device(dev); pci_create_sysfs_dev_files(dev); diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index f79cbcd..acdcc3c 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c @@ -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; diff --git a/include/linux/pci.h b/include/linux/pci.h index 6860f4d..e2aed11 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -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; /* These fields are used by common fixups */ unsigned int transparent:1; /* Transparent PCI bridge */ unsigned int multifunction:1;/* Part of multi-function device */