Patchwork [v8,21/22] PCI: add match_driver in struct pci_dev

login
register
mail settings
Submitter Yinghai Lu
Date Jan. 11, 2013, 10:40 p.m.
Message ID <1357944049-29620-22-git-send-email-yinghai@kernel.org>
Download mbox | patch
Permalink /patch/211427/
State Superseded
Headers show

Comments

Yinghai Lu - Jan. 11, 2013, 10:40 p.m.
with that we could move out attaching driver for pci device,
out of device_add for pci hot add path.

pci_bus_attach_device() will attach driver to pci device.

Signed-off-by: Yinghai Lu <yinghai@kernel.org>
---
 drivers/pci/bus.c        |   10 ++++++++++
 drivers/pci/pci-driver.c |    6 +++++-
 include/linux/pci.h      |    1 +
 3 files changed, 16 insertions(+), 1 deletion(-)
Rafael J. Wysocki - Jan. 12, 2013, 11:49 p.m.
On Friday, January 11, 2013 02:40:48 PM Yinghai Lu wrote:
> with that we could move out attaching driver for pci device,
> out of device_add for pci hot add path.
> 
> pci_bus_attach_device() will attach driver to pci device.

Clever, but I wonder why exactly we need to do that?

Rafael


> Signed-off-by: Yinghai Lu <yinghai@kernel.org>
> ---
>  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 5f9c728..1f5916a 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 907b455..d73af08 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 */
>
Jiang Liu - Jan. 13, 2013, 3:40 p.m.
On 01/13/2013 07:49 AM, Rafael J. Wysocki wrote:
> On Friday, January 11, 2013 02:40:48 PM Yinghai Lu wrote:
>> with that we could move out attaching driver for pci device,
>> out of device_add for pci hot add path.
>>
>> pci_bus_attach_device() will attach driver to pci device.
> 
> Clever, but I wonder why exactly we need to do that?
Hi Rafael,
	To make following sequence possible,
1) Create PCI device objects for hot-added PCI host bridge
2) Create IOMMU devices for DMAR units belong to the hot-added PCI host bridge
3) Bind and start all PCI devices connected to the PCI host bridge.

Regards!
Gerry

> 
> Rafael
> 
> 
>> Signed-off-by: Yinghai Lu <yinghai@kernel.org>
>> ---
>>  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 5f9c728..1f5916a 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 907b455..d73af08 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 */
>>

--
To unsubscribe from this list: send the line "unsubscribe linux-pci" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Rafael J. Wysocki - Jan. 13, 2013, 8:01 p.m.
On Sunday, January 13, 2013 11:40:12 PM Jiang Liu wrote:
> On 01/13/2013 07:49 AM, Rafael J. Wysocki wrote:
> > On Friday, January 11, 2013 02:40:48 PM Yinghai Lu wrote:
> >> with that we could move out attaching driver for pci device,
> >> out of device_add for pci hot add path.
> >>
> >> pci_bus_attach_device() will attach driver to pci device.
> > 
> > Clever, but I wonder why exactly we need to do that?
> Hi Rafael,
> 	To make following sequence possible,
> 1) Create PCI device objects for hot-added PCI host bridge
> 2) Create IOMMU devices for DMAR units belong to the hot-added PCI host bridge
> 3) Bind and start all PCI devices connected to the PCI host bridge.

OK, but why exactly isn't it possible without that change?

Rafael


> >> Signed-off-by: Yinghai Lu <yinghai@kernel.org>
> >> ---
> >>  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 5f9c728..1f5916a 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 907b455..d73af08 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 */
> >>
>

Patch

diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c
index 5f9c728..1f5916a 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 907b455..d73af08 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 */