Re: [PATCH v8 10/30] PCI: Introduce pci_host_bridge_list to manage host bridges

2015-03-26 Thread Yijing Wang
On 2015/3/27 0:31, Yinghai Lu wrote:
> On Mon, Mar 23, 2015 at 8:34 PM, Yijing Wang  wrote:
>> Introduce pci_host_bridge_list to manage pci host
>> bridges in system, this make us have the ability
>> to check whether the new host would conflict with
>> existing one. Then we could remove bus alreay exist
>> check in __pci_create_root_bus().
> 
> Can we use bus_type instead?
> Then we can use bus_find_device for the host_bridge enumeration.
> 
> Please refer the patches that I sent out couple years ago.

HI Yinghai,
   I think your changes is good, but in this series, we only iterate the 
pci_host_bridge
in drivers/pci/host-bridge.c. The simple list is enough, of course, if we want 
to export
this list and support to host bridge hotplug, we must need a new iteration for 
host bridge,
and your series looks good to me, I read your series history, found Bjorn 
comment a lot.

So I think Bjorn may have some comments for this.

Thanks!
Yijing.




-- 
Thanks!
Yijing

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v8 10/30] PCI: Introduce pci_host_bridge_list to manage host bridges

2015-03-26 Thread Yinghai Lu
On Mon, Mar 23, 2015 at 8:34 PM, Yijing Wang  wrote:
> Introduce pci_host_bridge_list to manage pci host
> bridges in system, this make us have the ability
> to check whether the new host would conflict with
> existing one. Then we could remove bus alreay exist
> check in __pci_create_root_bus().

Can we use bus_type instead?
Then we can use bus_find_device for the host_bridge enumeration.

Please refer the patches that I sent out couple years ago.

Thanks

Yinghai
Subject: [PATCH] PCI: Add dummy bus_type for pci_host_bridge

Need to use it for looping registered host_bridges, and kill
pci_root_buses list later.

Signed-off-by: Yinghai Lu 

---
 drivers/pci/pci-driver.c |   10 ++
 drivers/pci/probe.c  |1 +
 include/linux/pci.h  |2 ++
 3 files changed, 13 insertions(+)

Index: linux-2.6/include/linux/pci.h
===
--- linux-2.6.orig/include/linux/pci.h
+++ linux-2.6/include/linux/pci.h
@@ -735,6 +735,7 @@ enum pcie_bus_config_types {
 
 extern enum pcie_bus_config_types pcie_bus_config;
 
+extern struct bus_type pci_host_bridge_bus_type;
 extern struct bus_type pci_bus_type;
 
 /* Do NOT directly access these two variables, unless you are arch-specific PCI
@@ -808,6 +809,7 @@ void pci_stop_root_bus(struct pci_bus *b
 void pci_remove_root_bus(struct pci_bus *bus);
 void pci_setup_cardbus(struct pci_bus *bus);
 void pci_sort_breadthfirst(void);
+#define dev_is_pci_host_bridge(d) ((d)->bus == _host_bridge_bus_type)
 #define dev_is_pci(d) ((d)->bus == _bus_type)
 #define dev_is_pf(d) ((dev_is_pci(d) ? to_pci_dev(d)->is_physfn : false))
 #define dev_num_vf(d) ((dev_is_pci(d) ? pci_num_vf(to_pci_dev(d)) : 0))
Index: linux-2.6/drivers/pci/pci-driver.c
===
--- linux-2.6.orig/drivers/pci/pci-driver.c
+++ linux-2.6/drivers/pci/pci-driver.c
@@ -1408,6 +1408,16 @@ struct bus_type pci_bus_type = {
 };
 EXPORT_SYMBOL(pci_bus_type);
 
+struct bus_type pci_host_bridge_bus_type = {
+	.name   = "pci_host_bridge",
+};
+
+static int __init pci_host_bridge_driver_init(void)
+{
+	return bus_register(_host_bridge_bus_type);
+}
+postcore_initcall(pci_host_bridge_driver_init);
+
 static int __init pci_driver_init(void)
 {
 	return bus_register(_bus_type);
Index: linux-2.6/drivers/pci/probe.c
===
--- linux-2.6.orig/drivers/pci/probe.c
+++ linux-2.6/drivers/pci/probe.c
@@ -1949,6 +1949,7 @@ struct pci_bus *pci_create_root_bus(stru
 		goto err_out;
 
 	bridge->dev.parent = parent;
+	bridge->dev.bus = _host_bridge_bus_type;
 	bridge->dev.release = pci_release_host_bridge_dev;
 	dev_set_name(>dev, "pci%04x:%02x", pci_domain_nr(b), bus);
 	error = pcibios_root_bridge_prepare(bridge);
Subject: [PATCH] PCI: Add for_each_pci_host_bridge() and pci_get_next_host_bridge

Now we have pci_root_buses list, and there is lots of iteration with
list_of_each of it, that is not safe after we add pci root bus hotplug
support after booting stage.

Also pci_find_next_bus is pretty misleading name, and it is only finding
next root bus instead of regular pci bus.

Add pci_get_next_host_bridge and use bus_find_device in driver core to
iterate host bridge and the same time get root bus.

In folllowing patches will replace searching root bus with searching host_bridge.
after using with that host-bridge, will need to call put device to release
reference if break early from the loop.

After those replacing, we even could kill pci_root_buses list.

-v2: fixes compiling error when CONFIG_PCI is not defined that Fengguang found.

Signed-off-by: Yinghai Lu 

---
 drivers/pci/search.c |   24 
 include/linux/pci.h  |9 +
 2 files changed, 33 insertions(+)

Index: linux-2.6/include/linux/pci.h
===
--- linux-2.6.orig/include/linux/pci.h
+++ linux-2.6/include/linux/pci.h
@@ -409,6 +409,8 @@ struct pci_host_bridge {
 };
 
 #define	to_pci_host_bridge(n) container_of(n, struct pci_host_bridge, dev)
+#define for_each_pci_host_bridge(d) while ((d = pci_get_next_host_bridge(d)) != NULL)
+
 void pci_set_host_bridge_release(struct pci_host_bridge *bridge,
 		 void (*release_fn)(struct pci_host_bridge *),
 		 void *release_data);
@@ -831,6 +833,7 @@ int pci_find_ht_capability(struct pci_de
 int pci_find_next_ht_capability(struct pci_dev *dev, int pos, int ht_cap);
 struct pci_bus *pci_find_next_bus(const struct pci_bus *from);
 
+struct pci_host_bridge *pci_get_next_host_bridge(struct pci_host_bridge *from);
 struct pci_dev *pci_get_device(unsigned int vendor, unsigned int device,
 struct pci_dev *from);
 struct pci_dev *pci_get_subsys(unsigned int vendor, unsigned int device,
@@ -1447,6 +1450,12 @@ static inline int pci_domain_nr(struct p
 static inline struct pci_dev *pci_dev_get(struct pci_dev *dev) { return NULL; }
 static inline int 

Re: [PATCH v8 10/30] PCI: Introduce pci_host_bridge_list to manage host bridges

2015-03-26 Thread Yijing Wang
On 2015/3/27 0:31, Yinghai Lu wrote:
 On Mon, Mar 23, 2015 at 8:34 PM, Yijing Wang wangyij...@huawei.com wrote:
 Introduce pci_host_bridge_list to manage pci host
 bridges in system, this make us have the ability
 to check whether the new host would conflict with
 existing one. Then we could remove bus alreay exist
 check in __pci_create_root_bus().
 
 Can we use bus_type instead?
 Then we can use bus_find_device for the host_bridge enumeration.
 
 Please refer the patches that I sent out couple years ago.

HI Yinghai,
   I think your changes is good, but in this series, we only iterate the 
pci_host_bridge
in drivers/pci/host-bridge.c. The simple list is enough, of course, if we want 
to export
this list and support to host bridge hotplug, we must need a new iteration for 
host bridge,
and your series looks good to me, I read your series history, found Bjorn 
comment a lot.

So I think Bjorn may have some comments for this.

Thanks!
Yijing.




-- 
Thanks!
Yijing

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v8 10/30] PCI: Introduce pci_host_bridge_list to manage host bridges

2015-03-26 Thread Yinghai Lu
On Mon, Mar 23, 2015 at 8:34 PM, Yijing Wang wangyij...@huawei.com wrote:
 Introduce pci_host_bridge_list to manage pci host
 bridges in system, this make us have the ability
 to check whether the new host would conflict with
 existing one. Then we could remove bus alreay exist
 check in __pci_create_root_bus().

Can we use bus_type instead?
Then we can use bus_find_device for the host_bridge enumeration.

Please refer the patches that I sent out couple years ago.

Thanks

Yinghai
Subject: [PATCH] PCI: Add dummy bus_type for pci_host_bridge

Need to use it for looping registered host_bridges, and kill
pci_root_buses list later.

Signed-off-by: Yinghai Lu ying...@kernel.org

---
 drivers/pci/pci-driver.c |   10 ++
 drivers/pci/probe.c  |1 +
 include/linux/pci.h  |2 ++
 3 files changed, 13 insertions(+)

Index: linux-2.6/include/linux/pci.h
===
--- linux-2.6.orig/include/linux/pci.h
+++ linux-2.6/include/linux/pci.h
@@ -735,6 +735,7 @@ enum pcie_bus_config_types {
 
 extern enum pcie_bus_config_types pcie_bus_config;
 
+extern struct bus_type pci_host_bridge_bus_type;
 extern struct bus_type pci_bus_type;
 
 /* Do NOT directly access these two variables, unless you are arch-specific PCI
@@ -808,6 +809,7 @@ void pci_stop_root_bus(struct pci_bus *b
 void pci_remove_root_bus(struct pci_bus *bus);
 void pci_setup_cardbus(struct pci_bus *bus);
 void pci_sort_breadthfirst(void);
+#define dev_is_pci_host_bridge(d) ((d)-bus == pci_host_bridge_bus_type)
 #define dev_is_pci(d) ((d)-bus == pci_bus_type)
 #define dev_is_pf(d) ((dev_is_pci(d) ? to_pci_dev(d)-is_physfn : false))
 #define dev_num_vf(d) ((dev_is_pci(d) ? pci_num_vf(to_pci_dev(d)) : 0))
Index: linux-2.6/drivers/pci/pci-driver.c
===
--- linux-2.6.orig/drivers/pci/pci-driver.c
+++ linux-2.6/drivers/pci/pci-driver.c
@@ -1408,6 +1408,16 @@ struct bus_type pci_bus_type = {
 };
 EXPORT_SYMBOL(pci_bus_type);
 
+struct bus_type pci_host_bridge_bus_type = {
+	.name   = pci_host_bridge,
+};
+
+static int __init pci_host_bridge_driver_init(void)
+{
+	return bus_register(pci_host_bridge_bus_type);
+}
+postcore_initcall(pci_host_bridge_driver_init);
+
 static int __init pci_driver_init(void)
 {
 	return bus_register(pci_bus_type);
Index: linux-2.6/drivers/pci/probe.c
===
--- linux-2.6.orig/drivers/pci/probe.c
+++ linux-2.6/drivers/pci/probe.c
@@ -1949,6 +1949,7 @@ struct pci_bus *pci_create_root_bus(stru
 		goto err_out;
 
 	bridge-dev.parent = parent;
+	bridge-dev.bus = pci_host_bridge_bus_type;
 	bridge-dev.release = pci_release_host_bridge_dev;
 	dev_set_name(bridge-dev, pci%04x:%02x, pci_domain_nr(b), bus);
 	error = pcibios_root_bridge_prepare(bridge);
Subject: [PATCH] PCI: Add for_each_pci_host_bridge() and pci_get_next_host_bridge

Now we have pci_root_buses list, and there is lots of iteration with
list_of_each of it, that is not safe after we add pci root bus hotplug
support after booting stage.

Also pci_find_next_bus is pretty misleading name, and it is only finding
next root bus instead of regular pci bus.

Add pci_get_next_host_bridge and use bus_find_device in driver core to
iterate host bridge and the same time get root bus.

In folllowing patches will replace searching root bus with searching host_bridge.
after using with that host-bridge, will need to call put device to release
reference if break early from the loop.

After those replacing, we even could kill pci_root_buses list.

-v2: fixes compiling error when CONFIG_PCI is not defined that Fengguang found.

Signed-off-by: Yinghai Lu ying...@kernel.org

---
 drivers/pci/search.c |   24 
 include/linux/pci.h  |9 +
 2 files changed, 33 insertions(+)

Index: linux-2.6/include/linux/pci.h
===
--- linux-2.6.orig/include/linux/pci.h
+++ linux-2.6/include/linux/pci.h
@@ -409,6 +409,8 @@ struct pci_host_bridge {
 };
 
 #define	to_pci_host_bridge(n) container_of(n, struct pci_host_bridge, dev)
+#define for_each_pci_host_bridge(d) while ((d = pci_get_next_host_bridge(d)) != NULL)
+
 void pci_set_host_bridge_release(struct pci_host_bridge *bridge,
 		 void (*release_fn)(struct pci_host_bridge *),
 		 void *release_data);
@@ -831,6 +833,7 @@ int pci_find_ht_capability(struct pci_de
 int pci_find_next_ht_capability(struct pci_dev *dev, int pos, int ht_cap);
 struct pci_bus *pci_find_next_bus(const struct pci_bus *from);
 
+struct pci_host_bridge *pci_get_next_host_bridge(struct pci_host_bridge *from);
 struct pci_dev *pci_get_device(unsigned int vendor, unsigned int device,
 struct pci_dev *from);
 struct pci_dev *pci_get_subsys(unsigned int vendor, unsigned int device,
@@ -1447,6 +1450,12 @@ static inline int pci_domain_nr(struct p
 static inline struct pci_dev *pci_dev_get(struct 

Re: [PATCH v8 10/30] PCI: Introduce pci_host_bridge_list to manage host bridges

2015-03-25 Thread Yijing Wang
On 2015/3/26 0:42, Tomasz Nowicki wrote:
> On 24.03.2015 04:34, Yijing Wang wrote:
>> Introduce pci_host_bridge_list to manage pci host
>> bridges in system, this make us have the ability
>> to check whether the new host would conflict with
>> existing one. Then we could remove bus alreay exist
>> check in __pci_create_root_bus().
>>
>> Signed-off-by: Yijing Wang 
>> ---
>>   drivers/pci/host-bridge.c |   41 -
>>   drivers/pci/probe.c   |9 +
>>   include/linux/pci.h   |1 +
>>   3 files changed, 42 insertions(+), 9 deletions(-)
>>
>> diff --git a/drivers/pci/host-bridge.c b/drivers/pci/host-bridge.c
>> index 1a9834b..8af6d51 100644
>> --- a/drivers/pci/host-bridge.c
>> +++ b/drivers/pci/host-bridge.c
>> @@ -8,6 +8,9 @@
>>
>>   #include "pci.h"
>>
>> +static LIST_HEAD(pci_host_bridge_list);
>> +static DEFINE_MUTEX(pci_host_mutex);
>> +
>>   static void pci_release_host_bridge_dev(struct device *dev)
>>   {
>>   struct pci_host_bridge *bridge = to_pci_host_bridge(dev);
>> @@ -41,12 +44,29 @@ static void pci_host_update_busn_res(
>>   pci_add_resource(resources, >busn_res);
>>   }
>>
>> +static bool pci_host_busn_res_overlap(
>> +struct pci_host_bridge *new, struct pci_host_bridge *old)
>> +{
>> +struct resource_entry *entry;
>> +struct resource *res1 = NULL, *res2 = NULL;
>> +
>> +resource_list_for_each_entry(entry, >windows)
>> +if (entry->res->flags & IORESOURCE_BUS)
>> +res1 = entry->res;
>> +
>> +resource_list_for_each_entry(entry, >windows)
>> +if (entry->res->flags & IORESOURCE_BUS)
>> +res2 = entry->res;
>> +
>> +return resource_overlaps(res1, res2);
>> +}
>> +
>>   struct pci_host_bridge *pci_create_host_bridge(
>>   struct device *parent, int domain, int bus,
>>   struct list_head *resources)
>>   {
>>   int error;
>> -struct pci_host_bridge *host;
>> +struct pci_host_bridge *host, *tmp;
>>   struct resource_entry *window, *n;
>>
>>   host = kzalloc(sizeof(*host), GFP_KERNEL);
>> @@ -65,6 +85,21 @@ struct pci_host_bridge *pci_create_host_bridge(
>>*/
>>   host->domain = domain;
>>   pci_host_assign_domain_nr(host);
>> +mutex_lock(_host_mutex);
>> +list_for_each_entry(tmp, _host_bridge_list, list) {
>> +if (tmp->domain != host->domain
>> +  || pci_host_busn_res_overlap(host, tmp)) {
> 
> I think you should construct condition this way:
> +if (tmp->domain == host->domain
> +  && pci_host_busn_res_overlap(host, tmp)) {

Good catch! I mistook this in the v8. Tomasz, thanks for your review!


> 
> Regards,
> Tomasz
> 
>> +pr_warn("pci host bridge pci%04x:%02x exist\n",
>> +host->domain, bus);
>> +mutex_unlock(_host_mutex);
>> +pci_free_resource_list(>windows);
>> +kfree(host);
>> +return NULL;
>> +}
>> +}
>> +list_add_tail(>list, _host_bridge_list);
>> +mutex_unlock(_host_mutex);
>> +
>>   host->dev.release = pci_release_host_bridge_dev;
>>   dev_set_name(>dev, "pci%04x:%02x",
>>   host->domain, bus);
>> @@ -80,6 +115,10 @@ struct pci_host_bridge *pci_create_host_bridge(
>>
>>   void pci_free_host_bridge(struct pci_host_bridge *host)
>>   {
>> +mutex_lock(_host_mutex);
>> +list_del(>list);
>> +mutex_unlock(_host_mutex);
>> +
>>   device_unregister(>dev);
>>   }
>>
>> diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
>> index 25ac741..8517d1b 100644
>> --- a/drivers/pci/probe.c
>> +++ b/drivers/pci/probe.c
>> @@ -1869,7 +1869,7 @@ static struct pci_bus *__pci_create_root_bus(
>>   void *sysdata)
>>   {
>>   int error;
>> -struct pci_bus *b, *b2;
>> +struct pci_bus *b;
>>   struct resource_entry *window;
>>   struct device *parent;
>>   struct resource *res;
>> @@ -1887,12 +1887,6 @@ static struct pci_bus *__pci_create_root_bus(
>>   b->number = b->busn_res.start =
>>   pci_host_first_busnr(bridge);
>>   pci_bus_assign_domain_nr(b, parent);
>> -b2 = pci_find_bus(pci_domain_nr(b), b->number);
>> -if (b2) {
>> -/* If we already got to this bus through a different bridge, ignore 
>> it */
>> -dev_dbg(>dev, "bus already known\n");
>> -goto err_out;
>> -}
>>
>>   bridge->bus = b;
>>   b->bridge = get_device(>dev);
>> @@ -1952,7 +1946,6 @@ static struct pci_bus *__pci_create_root_bus(
>>
>>   put_dev:
>>   put_device(>dev);
>> -err_out:
>>   kfree(b);
>>   return NULL;
>>   }
>> diff --git a/include/linux/pci.h b/include/linux/pci.h
>> index f189dfb..91cba01 100644
>> --- a/include/linux/pci.h
>> +++ b/include/linux/pci.h
>> @@ -407,6 +407,7 @@ struct pci_host_bridge {
>>   /* we use default bus resource if no bus resource provided */
>>   struct resource busn_res;
>>   struct list_head windows;/* resource_entry */
>> +  

Re: [PATCH v8 10/30] PCI: Introduce pci_host_bridge_list to manage host bridges

2015-03-25 Thread Tomasz Nowicki

On 24.03.2015 04:34, Yijing Wang wrote:

Introduce pci_host_bridge_list to manage pci host
bridges in system, this make us have the ability
to check whether the new host would conflict with
existing one. Then we could remove bus alreay exist
check in __pci_create_root_bus().

Signed-off-by: Yijing Wang 
---
  drivers/pci/host-bridge.c |   41 -
  drivers/pci/probe.c   |9 +
  include/linux/pci.h   |1 +
  3 files changed, 42 insertions(+), 9 deletions(-)

diff --git a/drivers/pci/host-bridge.c b/drivers/pci/host-bridge.c
index 1a9834b..8af6d51 100644
--- a/drivers/pci/host-bridge.c
+++ b/drivers/pci/host-bridge.c
@@ -8,6 +8,9 @@

  #include "pci.h"

+static LIST_HEAD(pci_host_bridge_list);
+static DEFINE_MUTEX(pci_host_mutex);
+
  static void pci_release_host_bridge_dev(struct device *dev)
  {
struct pci_host_bridge *bridge = to_pci_host_bridge(dev);
@@ -41,12 +44,29 @@ static void pci_host_update_busn_res(
pci_add_resource(resources, >busn_res);
  }

+static bool pci_host_busn_res_overlap(
+   struct pci_host_bridge *new, struct pci_host_bridge *old)
+{
+   struct resource_entry *entry;
+   struct resource *res1 = NULL, *res2 = NULL;
+
+   resource_list_for_each_entry(entry, >windows)
+   if (entry->res->flags & IORESOURCE_BUS)
+   res1 = entry->res;
+
+   resource_list_for_each_entry(entry, >windows)
+   if (entry->res->flags & IORESOURCE_BUS)
+   res2 = entry->res;
+
+   return resource_overlaps(res1, res2);
+}
+
  struct pci_host_bridge *pci_create_host_bridge(
struct device *parent, int domain, int bus,
struct list_head *resources)
  {
int error;
-   struct pci_host_bridge *host;
+   struct pci_host_bridge *host, *tmp;
struct resource_entry *window, *n;

host = kzalloc(sizeof(*host), GFP_KERNEL);
@@ -65,6 +85,21 @@ struct pci_host_bridge *pci_create_host_bridge(
 */
host->domain = domain;
pci_host_assign_domain_nr(host);
+   mutex_lock(_host_mutex);
+   list_for_each_entry(tmp, _host_bridge_list, list) {
+   if (tmp->domain != host->domain
+ || pci_host_busn_res_overlap(host, tmp)) {


I think you should construct condition this way:
+   if (tmp->domain == host->domain
+ && pci_host_busn_res_overlap(host, tmp)) {

Regards,
Tomasz


+   pr_warn("pci host bridge pci%04x:%02x exist\n",
+   host->domain, bus);
+   mutex_unlock(_host_mutex);
+   pci_free_resource_list(>windows);
+   kfree(host);
+   return NULL;
+   }
+   }
+   list_add_tail(>list, _host_bridge_list);
+   mutex_unlock(_host_mutex);
+
host->dev.release = pci_release_host_bridge_dev;
dev_set_name(>dev, "pci%04x:%02x",
host->domain, bus);
@@ -80,6 +115,10 @@ struct pci_host_bridge *pci_create_host_bridge(

  void pci_free_host_bridge(struct pci_host_bridge *host)
  {
+   mutex_lock(_host_mutex);
+   list_del(>list);
+   mutex_unlock(_host_mutex);
+
device_unregister(>dev);
  }

diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 25ac741..8517d1b 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -1869,7 +1869,7 @@ static struct pci_bus *__pci_create_root_bus(
void *sysdata)
  {
int error;
-   struct pci_bus *b, *b2;
+   struct pci_bus *b;
struct resource_entry *window;
struct device *parent;
struct resource *res;
@@ -1887,12 +1887,6 @@ static struct pci_bus *__pci_create_root_bus(
b->number = b->busn_res.start =
pci_host_first_busnr(bridge);
pci_bus_assign_domain_nr(b, parent);
-   b2 = pci_find_bus(pci_domain_nr(b), b->number);
-   if (b2) {
-   /* If we already got to this bus through a different bridge, 
ignore it */
-   dev_dbg(>dev, "bus already known\n");
-   goto err_out;
-   }

bridge->bus = b;
b->bridge = get_device(>dev);
@@ -1952,7 +1946,6 @@ static struct pci_bus *__pci_create_root_bus(

  put_dev:
put_device(>dev);
-err_out:
kfree(b);
return NULL;
  }
diff --git a/include/linux/pci.h b/include/linux/pci.h
index f189dfb..91cba01 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -407,6 +407,7 @@ struct pci_host_bridge {
/* we use default bus resource if no bus resource provided */
struct resource busn_res;
struct list_head windows;   /* resource_entry */
+   struct list_head list;
void (*release_fn)(struct pci_host_bridge *);
void *release_data;
  };


--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in

Re: [PATCH v8 10/30] PCI: Introduce pci_host_bridge_list to manage host bridges

2015-03-25 Thread Tomasz Nowicki

On 24.03.2015 04:34, Yijing Wang wrote:

Introduce pci_host_bridge_list to manage pci host
bridges in system, this make us have the ability
to check whether the new host would conflict with
existing one. Then we could remove bus alreay exist
check in __pci_create_root_bus().

Signed-off-by: Yijing Wang wangyij...@huawei.com
---
  drivers/pci/host-bridge.c |   41 -
  drivers/pci/probe.c   |9 +
  include/linux/pci.h   |1 +
  3 files changed, 42 insertions(+), 9 deletions(-)

diff --git a/drivers/pci/host-bridge.c b/drivers/pci/host-bridge.c
index 1a9834b..8af6d51 100644
--- a/drivers/pci/host-bridge.c
+++ b/drivers/pci/host-bridge.c
@@ -8,6 +8,9 @@

  #include pci.h

+static LIST_HEAD(pci_host_bridge_list);
+static DEFINE_MUTEX(pci_host_mutex);
+
  static void pci_release_host_bridge_dev(struct device *dev)
  {
struct pci_host_bridge *bridge = to_pci_host_bridge(dev);
@@ -41,12 +44,29 @@ static void pci_host_update_busn_res(
pci_add_resource(resources, host-busn_res);
  }

+static bool pci_host_busn_res_overlap(
+   struct pci_host_bridge *new, struct pci_host_bridge *old)
+{
+   struct resource_entry *entry;
+   struct resource *res1 = NULL, *res2 = NULL;
+
+   resource_list_for_each_entry(entry, old-windows)
+   if (entry-res-flags  IORESOURCE_BUS)
+   res1 = entry-res;
+
+   resource_list_for_each_entry(entry, new-windows)
+   if (entry-res-flags  IORESOURCE_BUS)
+   res2 = entry-res;
+
+   return resource_overlaps(res1, res2);
+}
+
  struct pci_host_bridge *pci_create_host_bridge(
struct device *parent, int domain, int bus,
struct list_head *resources)
  {
int error;
-   struct pci_host_bridge *host;
+   struct pci_host_bridge *host, *tmp;
struct resource_entry *window, *n;

host = kzalloc(sizeof(*host), GFP_KERNEL);
@@ -65,6 +85,21 @@ struct pci_host_bridge *pci_create_host_bridge(
 */
host-domain = domain;
pci_host_assign_domain_nr(host);
+   mutex_lock(pci_host_mutex);
+   list_for_each_entry(tmp, pci_host_bridge_list, list) {
+   if (tmp-domain != host-domain
+ || pci_host_busn_res_overlap(host, tmp)) {


I think you should construct condition this way:
+   if (tmp-domain == host-domain
+  pci_host_busn_res_overlap(host, tmp)) {

Regards,
Tomasz


+   pr_warn(pci host bridge pci%04x:%02x exist\n,
+   host-domain, bus);
+   mutex_unlock(pci_host_mutex);
+   pci_free_resource_list(host-windows);
+   kfree(host);
+   return NULL;
+   }
+   }
+   list_add_tail(host-list, pci_host_bridge_list);
+   mutex_unlock(pci_host_mutex);
+
host-dev.release = pci_release_host_bridge_dev;
dev_set_name(host-dev, pci%04x:%02x,
host-domain, bus);
@@ -80,6 +115,10 @@ struct pci_host_bridge *pci_create_host_bridge(

  void pci_free_host_bridge(struct pci_host_bridge *host)
  {
+   mutex_lock(pci_host_mutex);
+   list_del(host-list);
+   mutex_unlock(pci_host_mutex);
+
device_unregister(host-dev);
  }

diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 25ac741..8517d1b 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -1869,7 +1869,7 @@ static struct pci_bus *__pci_create_root_bus(
void *sysdata)
  {
int error;
-   struct pci_bus *b, *b2;
+   struct pci_bus *b;
struct resource_entry *window;
struct device *parent;
struct resource *res;
@@ -1887,12 +1887,6 @@ static struct pci_bus *__pci_create_root_bus(
b-number = b-busn_res.start =
pci_host_first_busnr(bridge);
pci_bus_assign_domain_nr(b, parent);
-   b2 = pci_find_bus(pci_domain_nr(b), b-number);
-   if (b2) {
-   /* If we already got to this bus through a different bridge, 
ignore it */
-   dev_dbg(b2-dev, bus already known\n);
-   goto err_out;
-   }

bridge-bus = b;
b-bridge = get_device(bridge-dev);
@@ -1952,7 +1946,6 @@ static struct pci_bus *__pci_create_root_bus(

  put_dev:
put_device(bridge-dev);
-err_out:
kfree(b);
return NULL;
  }
diff --git a/include/linux/pci.h b/include/linux/pci.h
index f189dfb..91cba01 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -407,6 +407,7 @@ struct pci_host_bridge {
/* we use default bus resource if no bus resource provided */
struct resource busn_res;
struct list_head windows;   /* resource_entry */
+   struct list_head list;
void (*release_fn)(struct pci_host_bridge *);
void *release_data;
  };


--
To unsubscribe from 

Re: [PATCH v8 10/30] PCI: Introduce pci_host_bridge_list to manage host bridges

2015-03-25 Thread Yijing Wang
On 2015/3/26 0:42, Tomasz Nowicki wrote:
 On 24.03.2015 04:34, Yijing Wang wrote:
 Introduce pci_host_bridge_list to manage pci host
 bridges in system, this make us have the ability
 to check whether the new host would conflict with
 existing one. Then we could remove bus alreay exist
 check in __pci_create_root_bus().

 Signed-off-by: Yijing Wang wangyij...@huawei.com
 ---
   drivers/pci/host-bridge.c |   41 -
   drivers/pci/probe.c   |9 +
   include/linux/pci.h   |1 +
   3 files changed, 42 insertions(+), 9 deletions(-)

 diff --git a/drivers/pci/host-bridge.c b/drivers/pci/host-bridge.c
 index 1a9834b..8af6d51 100644
 --- a/drivers/pci/host-bridge.c
 +++ b/drivers/pci/host-bridge.c
 @@ -8,6 +8,9 @@

   #include pci.h

 +static LIST_HEAD(pci_host_bridge_list);
 +static DEFINE_MUTEX(pci_host_mutex);
 +
   static void pci_release_host_bridge_dev(struct device *dev)
   {
   struct pci_host_bridge *bridge = to_pci_host_bridge(dev);
 @@ -41,12 +44,29 @@ static void pci_host_update_busn_res(
   pci_add_resource(resources, host-busn_res);
   }

 +static bool pci_host_busn_res_overlap(
 +struct pci_host_bridge *new, struct pci_host_bridge *old)
 +{
 +struct resource_entry *entry;
 +struct resource *res1 = NULL, *res2 = NULL;
 +
 +resource_list_for_each_entry(entry, old-windows)
 +if (entry-res-flags  IORESOURCE_BUS)
 +res1 = entry-res;
 +
 +resource_list_for_each_entry(entry, new-windows)
 +if (entry-res-flags  IORESOURCE_BUS)
 +res2 = entry-res;
 +
 +return resource_overlaps(res1, res2);
 +}
 +
   struct pci_host_bridge *pci_create_host_bridge(
   struct device *parent, int domain, int bus,
   struct list_head *resources)
   {
   int error;
 -struct pci_host_bridge *host;
 +struct pci_host_bridge *host, *tmp;
   struct resource_entry *window, *n;

   host = kzalloc(sizeof(*host), GFP_KERNEL);
 @@ -65,6 +85,21 @@ struct pci_host_bridge *pci_create_host_bridge(
*/
   host-domain = domain;
   pci_host_assign_domain_nr(host);
 +mutex_lock(pci_host_mutex);
 +list_for_each_entry(tmp, pci_host_bridge_list, list) {
 +if (tmp-domain != host-domain
 +  || pci_host_busn_res_overlap(host, tmp)) {
 
 I think you should construct condition this way:
 +if (tmp-domain == host-domain
 +   pci_host_busn_res_overlap(host, tmp)) {

Good catch! I mistook this in the v8. Tomasz, thanks for your review!


 
 Regards,
 Tomasz
 
 +pr_warn(pci host bridge pci%04x:%02x exist\n,
 +host-domain, bus);
 +mutex_unlock(pci_host_mutex);
 +pci_free_resource_list(host-windows);
 +kfree(host);
 +return NULL;
 +}
 +}
 +list_add_tail(host-list, pci_host_bridge_list);
 +mutex_unlock(pci_host_mutex);
 +
   host-dev.release = pci_release_host_bridge_dev;
   dev_set_name(host-dev, pci%04x:%02x,
   host-domain, bus);
 @@ -80,6 +115,10 @@ struct pci_host_bridge *pci_create_host_bridge(

   void pci_free_host_bridge(struct pci_host_bridge *host)
   {
 +mutex_lock(pci_host_mutex);
 +list_del(host-list);
 +mutex_unlock(pci_host_mutex);
 +
   device_unregister(host-dev);
   }

 diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
 index 25ac741..8517d1b 100644
 --- a/drivers/pci/probe.c
 +++ b/drivers/pci/probe.c
 @@ -1869,7 +1869,7 @@ static struct pci_bus *__pci_create_root_bus(
   void *sysdata)
   {
   int error;
 -struct pci_bus *b, *b2;
 +struct pci_bus *b;
   struct resource_entry *window;
   struct device *parent;
   struct resource *res;
 @@ -1887,12 +1887,6 @@ static struct pci_bus *__pci_create_root_bus(
   b-number = b-busn_res.start =
   pci_host_first_busnr(bridge);
   pci_bus_assign_domain_nr(b, parent);
 -b2 = pci_find_bus(pci_domain_nr(b), b-number);
 -if (b2) {
 -/* If we already got to this bus through a different bridge, ignore 
 it */
 -dev_dbg(b2-dev, bus already known\n);
 -goto err_out;
 -}

   bridge-bus = b;
   b-bridge = get_device(bridge-dev);
 @@ -1952,7 +1946,6 @@ static struct pci_bus *__pci_create_root_bus(

   put_dev:
   put_device(bridge-dev);
 -err_out:
   kfree(b);
   return NULL;
   }
 diff --git a/include/linux/pci.h b/include/linux/pci.h
 index f189dfb..91cba01 100644
 --- a/include/linux/pci.h
 +++ b/include/linux/pci.h
 @@ -407,6 +407,7 @@ struct pci_host_bridge {
   /* we use default bus resource if no bus resource provided */
   struct resource busn_res;
   struct list_head windows;/* resource_entry */
 +struct list_head list;
   void (*release_fn)(struct pci_host_bridge *);
   void *release_data;
   };

 
 .
 


-- 
Thanks!
Yijing

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the 

[PATCH v8 10/30] PCI: Introduce pci_host_bridge_list to manage host bridges

2015-03-23 Thread Yijing Wang
Introduce pci_host_bridge_list to manage pci host
bridges in system, this make us have the ability
to check whether the new host would conflict with
existing one. Then we could remove bus alreay exist
check in __pci_create_root_bus().

Signed-off-by: Yijing Wang 
---
 drivers/pci/host-bridge.c |   41 -
 drivers/pci/probe.c   |9 +
 include/linux/pci.h   |1 +
 3 files changed, 42 insertions(+), 9 deletions(-)

diff --git a/drivers/pci/host-bridge.c b/drivers/pci/host-bridge.c
index 1a9834b..8af6d51 100644
--- a/drivers/pci/host-bridge.c
+++ b/drivers/pci/host-bridge.c
@@ -8,6 +8,9 @@
 
 #include "pci.h"
 
+static LIST_HEAD(pci_host_bridge_list);
+static DEFINE_MUTEX(pci_host_mutex);
+
 static void pci_release_host_bridge_dev(struct device *dev)
 {
struct pci_host_bridge *bridge = to_pci_host_bridge(dev);
@@ -41,12 +44,29 @@ static void pci_host_update_busn_res(
pci_add_resource(resources, >busn_res);
 }
 
+static bool pci_host_busn_res_overlap(
+   struct pci_host_bridge *new, struct pci_host_bridge *old)
+{
+   struct resource_entry *entry;
+   struct resource *res1 = NULL, *res2 = NULL;
+
+   resource_list_for_each_entry(entry, >windows)
+   if (entry->res->flags & IORESOURCE_BUS)
+   res1 = entry->res;
+
+   resource_list_for_each_entry(entry, >windows)
+   if (entry->res->flags & IORESOURCE_BUS)
+   res2 = entry->res;
+
+   return resource_overlaps(res1, res2);
+}
+
 struct pci_host_bridge *pci_create_host_bridge(
struct device *parent, int domain, int bus,
struct list_head *resources)
 {
int error;
-   struct pci_host_bridge *host;
+   struct pci_host_bridge *host, *tmp;
struct resource_entry *window, *n;
 
host = kzalloc(sizeof(*host), GFP_KERNEL);
@@ -65,6 +85,21 @@ struct pci_host_bridge *pci_create_host_bridge(
 */
host->domain = domain;
pci_host_assign_domain_nr(host);
+   mutex_lock(_host_mutex);
+   list_for_each_entry(tmp, _host_bridge_list, list) {
+   if (tmp->domain != host->domain
+ || pci_host_busn_res_overlap(host, tmp)) {
+   pr_warn("pci host bridge pci%04x:%02x exist\n",
+   host->domain, bus);
+   mutex_unlock(_host_mutex);
+   pci_free_resource_list(>windows);
+   kfree(host);
+   return NULL;
+   }
+   }
+   list_add_tail(>list, _host_bridge_list);
+   mutex_unlock(_host_mutex);
+
host->dev.release = pci_release_host_bridge_dev;
dev_set_name(>dev, "pci%04x:%02x",
host->domain, bus);
@@ -80,6 +115,10 @@ struct pci_host_bridge *pci_create_host_bridge(
 
 void pci_free_host_bridge(struct pci_host_bridge *host)
 {
+   mutex_lock(_host_mutex);
+   list_del(>list);
+   mutex_unlock(_host_mutex);
+
device_unregister(>dev);
 }
 
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 25ac741..8517d1b 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -1869,7 +1869,7 @@ static struct pci_bus *__pci_create_root_bus(
void *sysdata)
 {
int error;
-   struct pci_bus *b, *b2;
+   struct pci_bus *b;
struct resource_entry *window;
struct device *parent;
struct resource *res;
@@ -1887,12 +1887,6 @@ static struct pci_bus *__pci_create_root_bus(
b->number = b->busn_res.start =
pci_host_first_busnr(bridge);
pci_bus_assign_domain_nr(b, parent);
-   b2 = pci_find_bus(pci_domain_nr(b), b->number);
-   if (b2) {
-   /* If we already got to this bus through a different bridge, 
ignore it */
-   dev_dbg(>dev, "bus already known\n");
-   goto err_out;
-   }
 
bridge->bus = b;
b->bridge = get_device(>dev);
@@ -1952,7 +1946,6 @@ static struct pci_bus *__pci_create_root_bus(
 
 put_dev:
put_device(>dev);
-err_out:
kfree(b);
return NULL;
 }
diff --git a/include/linux/pci.h b/include/linux/pci.h
index f189dfb..91cba01 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -407,6 +407,7 @@ struct pci_host_bridge {
/* we use default bus resource if no bus resource provided */
struct resource busn_res;
struct list_head windows;   /* resource_entry */
+   struct list_head list;
void (*release_fn)(struct pci_host_bridge *);
void *release_data;
 };
-- 
1.7.1

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v8 10/30] PCI: Introduce pci_host_bridge_list to manage host bridges

2015-03-23 Thread Yijing Wang
Introduce pci_host_bridge_list to manage pci host
bridges in system, this make us have the ability
to check whether the new host would conflict with
existing one. Then we could remove bus alreay exist
check in __pci_create_root_bus().

Signed-off-by: Yijing Wang wangyij...@huawei.com
---
 drivers/pci/host-bridge.c |   41 -
 drivers/pci/probe.c   |9 +
 include/linux/pci.h   |1 +
 3 files changed, 42 insertions(+), 9 deletions(-)

diff --git a/drivers/pci/host-bridge.c b/drivers/pci/host-bridge.c
index 1a9834b..8af6d51 100644
--- a/drivers/pci/host-bridge.c
+++ b/drivers/pci/host-bridge.c
@@ -8,6 +8,9 @@
 
 #include pci.h
 
+static LIST_HEAD(pci_host_bridge_list);
+static DEFINE_MUTEX(pci_host_mutex);
+
 static void pci_release_host_bridge_dev(struct device *dev)
 {
struct pci_host_bridge *bridge = to_pci_host_bridge(dev);
@@ -41,12 +44,29 @@ static void pci_host_update_busn_res(
pci_add_resource(resources, host-busn_res);
 }
 
+static bool pci_host_busn_res_overlap(
+   struct pci_host_bridge *new, struct pci_host_bridge *old)
+{
+   struct resource_entry *entry;
+   struct resource *res1 = NULL, *res2 = NULL;
+
+   resource_list_for_each_entry(entry, old-windows)
+   if (entry-res-flags  IORESOURCE_BUS)
+   res1 = entry-res;
+
+   resource_list_for_each_entry(entry, new-windows)
+   if (entry-res-flags  IORESOURCE_BUS)
+   res2 = entry-res;
+
+   return resource_overlaps(res1, res2);
+}
+
 struct pci_host_bridge *pci_create_host_bridge(
struct device *parent, int domain, int bus,
struct list_head *resources)
 {
int error;
-   struct pci_host_bridge *host;
+   struct pci_host_bridge *host, *tmp;
struct resource_entry *window, *n;
 
host = kzalloc(sizeof(*host), GFP_KERNEL);
@@ -65,6 +85,21 @@ struct pci_host_bridge *pci_create_host_bridge(
 */
host-domain = domain;
pci_host_assign_domain_nr(host);
+   mutex_lock(pci_host_mutex);
+   list_for_each_entry(tmp, pci_host_bridge_list, list) {
+   if (tmp-domain != host-domain
+ || pci_host_busn_res_overlap(host, tmp)) {
+   pr_warn(pci host bridge pci%04x:%02x exist\n,
+   host-domain, bus);
+   mutex_unlock(pci_host_mutex);
+   pci_free_resource_list(host-windows);
+   kfree(host);
+   return NULL;
+   }
+   }
+   list_add_tail(host-list, pci_host_bridge_list);
+   mutex_unlock(pci_host_mutex);
+
host-dev.release = pci_release_host_bridge_dev;
dev_set_name(host-dev, pci%04x:%02x,
host-domain, bus);
@@ -80,6 +115,10 @@ struct pci_host_bridge *pci_create_host_bridge(
 
 void pci_free_host_bridge(struct pci_host_bridge *host)
 {
+   mutex_lock(pci_host_mutex);
+   list_del(host-list);
+   mutex_unlock(pci_host_mutex);
+
device_unregister(host-dev);
 }
 
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 25ac741..8517d1b 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -1869,7 +1869,7 @@ static struct pci_bus *__pci_create_root_bus(
void *sysdata)
 {
int error;
-   struct pci_bus *b, *b2;
+   struct pci_bus *b;
struct resource_entry *window;
struct device *parent;
struct resource *res;
@@ -1887,12 +1887,6 @@ static struct pci_bus *__pci_create_root_bus(
b-number = b-busn_res.start =
pci_host_first_busnr(bridge);
pci_bus_assign_domain_nr(b, parent);
-   b2 = pci_find_bus(pci_domain_nr(b), b-number);
-   if (b2) {
-   /* If we already got to this bus through a different bridge, 
ignore it */
-   dev_dbg(b2-dev, bus already known\n);
-   goto err_out;
-   }
 
bridge-bus = b;
b-bridge = get_device(bridge-dev);
@@ -1952,7 +1946,6 @@ static struct pci_bus *__pci_create_root_bus(
 
 put_dev:
put_device(bridge-dev);
-err_out:
kfree(b);
return NULL;
 }
diff --git a/include/linux/pci.h b/include/linux/pci.h
index f189dfb..91cba01 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -407,6 +407,7 @@ struct pci_host_bridge {
/* we use default bus resource if no bus resource provided */
struct resource busn_res;
struct list_head windows;   /* resource_entry */
+   struct list_head list;
void (*release_fn)(struct pci_host_bridge *);
void *release_data;
 };
-- 
1.7.1

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/