aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLorenzo Pieralisi <lorenzo.pieralisi@arm.com>2014-12-27 20:19:12 -0500
committerBjorn Helgaas <bhelgaas@google.com>2014-12-27 20:19:12 -0500
commit7c674700098c87b305b99652e3c694c4ef195866 (patch)
tree25a428aaf73fa599d43b42980e1085c5c3aca181
parent97bf6af1f928216fd6c5a66e8a57bfa95a659672 (diff)
PCI: Move domain assignment from arm64 to generic code
The current logic in arm64 pci_bus_assign_domain_nr() is flawed in that depending on the host controller configuration for a platform and the initialization sequence, core code may end up allocating PCI domain numbers from both DT and the generic domain counter, which would result in PCI domain allocation aliases/errors. Fix the logic behind the PCI domain number assignment and move the resulting code to the PCI core so the same domain allocation logic is used on all platforms that select CONFIG_PCI_DOMAINS_GENERIC. [bhelgaas: tidy changelog] Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Acked-by: Liviu Dudau <Liviu.Dudau@arm.com> Acked-by: Arnd Bergmann <arnd@arndb.de> CC: Rob Herring <robh+dt@kernel.org> CC: Catalin Marinas <catalin.marinas@arm.com>
-rw-r--r--arch/arm64/kernel/pci.c22
-rw-r--r--drivers/pci/pci.c49
2 files changed, 49 insertions, 22 deletions
diff --git a/arch/arm64/kernel/pci.c b/arch/arm64/kernel/pci.c
index ce5836c14ec1..6f93c24ca801 100644
--- a/arch/arm64/kernel/pci.c
+++ b/arch/arm64/kernel/pci.c
@@ -46,25 +46,3 @@ int pcibios_add_device(struct pci_dev *dev)
46 46
47 return 0; 47 return 0;
48} 48}
49
50
51#ifdef CONFIG_PCI_DOMAINS_GENERIC
52static bool dt_domain_found = false;
53
54void pci_bus_assign_domain_nr(struct pci_bus *bus, struct device *parent)
55{
56 int domain = of_get_pci_domain_nr(parent->of_node);
57
58 if (domain >= 0) {
59 dt_domain_found = true;
60 } else if (dt_domain_found == true) {
61 dev_err(parent, "Node %s is missing \"linux,pci-domain\" property in DT\n",
62 parent->of_node->full_name);
63 return;
64 } else {
65 domain = pci_get_new_domain_nr();
66 }
67
68 bus->domain_nr = domain;
69}
70#endif
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index cab05f31223f..c419554d0b4b 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -10,6 +10,8 @@
10#include <linux/kernel.h> 10#include <linux/kernel.h>
11#include <linux/delay.h> 11#include <linux/delay.h>
12#include <linux/init.h> 12#include <linux/init.h>
13#include <linux/of.h>
14#include <linux/of_pci.h>
13#include <linux/pci.h> 15#include <linux/pci.h>
14#include <linux/pm.h> 16#include <linux/pm.h>
15#include <linux/slab.h> 17#include <linux/slab.h>
@@ -4439,6 +4441,53 @@ int pci_get_new_domain_nr(void)
4439{ 4441{
4440 return atomic_inc_return(&__domain_nr); 4442 return atomic_inc_return(&__domain_nr);
4441} 4443}
4444
4445#ifdef CONFIG_PCI_DOMAINS_GENERIC
4446void pci_bus_assign_domain_nr(struct pci_bus *bus, struct device *parent)
4447{
4448 static int use_dt_domains = -1;
4449 int domain = of_get_pci_domain_nr(parent->of_node);
4450
4451 /*
4452 * Check DT domain and use_dt_domains values.
4453 *
4454 * If DT domain property is valid (domain >= 0) and
4455 * use_dt_domains != 0, the DT assignment is valid since this means
4456 * we have not previously allocated a domain number by using
4457 * pci_get_new_domain_nr(); we should also update use_dt_domains to
4458 * 1, to indicate that we have just assigned a domain number from
4459 * DT.
4460 *
4461 * If DT domain property value is not valid (ie domain < 0), and we
4462 * have not previously assigned a domain number from DT
4463 * (use_dt_domains != 1) we should assign a domain number by
4464 * using the:
4465 *
4466 * pci_get_new_domain_nr()
4467 *
4468 * API and update the use_dt_domains value to keep track of method we
4469 * are using to assign domain numbers (use_dt_domains = 0).
4470 *
4471 * All other combinations imply we have a platform that is trying
4472 * to mix domain numbers obtained from DT and pci_get_new_domain_nr(),
4473 * which is a recipe for domain mishandling and it is prevented by
4474 * invalidating the domain value (domain = -1) and printing a
4475 * corresponding error.
4476 */
4477 if (domain >= 0 && use_dt_domains) {
4478 use_dt_domains = 1;
4479 } else if (domain < 0 && use_dt_domains != 1) {
4480 use_dt_domains = 0;
4481 domain = pci_get_new_domain_nr();
4482 } else {
4483 dev_err(parent, "Node %s has inconsistent \"linux,pci-domain\" property in DT\n",
4484 parent->of_node->full_name);
4485 domain = -1;
4486 }
4487
4488 bus->domain_nr = domain;
4489}
4490#endif
4442#endif 4491#endif
4443 4492
4444/** 4493/**