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>
This commit is contained in:
Lorenzo Pieralisi 2014-12-27 18:19:12 -07:00 committed by Bjorn Helgaas
parent 97bf6af1f9
commit 7c67470009
2 changed files with 49 additions and 22 deletions

View File

@ -46,25 +46,3 @@ int pcibios_add_device(struct pci_dev *dev)
return 0;
}
#ifdef CONFIG_PCI_DOMAINS_GENERIC
static bool dt_domain_found = false;
void pci_bus_assign_domain_nr(struct pci_bus *bus, struct device *parent)
{
int domain = of_get_pci_domain_nr(parent->of_node);
if (domain >= 0) {
dt_domain_found = true;
} else if (dt_domain_found == true) {
dev_err(parent, "Node %s is missing \"linux,pci-domain\" property in DT\n",
parent->of_node->full_name);
return;
} else {
domain = pci_get_new_domain_nr();
}
bus->domain_nr = domain;
}
#endif

View File

@ -10,6 +10,8 @@
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/of.h>
#include <linux/of_pci.h>
#include <linux/pci.h>
#include <linux/pm.h>
#include <linux/slab.h>
@ -4439,6 +4441,53 @@ int pci_get_new_domain_nr(void)
{
return atomic_inc_return(&__domain_nr);
}
#ifdef CONFIG_PCI_DOMAINS_GENERIC
void pci_bus_assign_domain_nr(struct pci_bus *bus, struct device *parent)
{
static int use_dt_domains = -1;
int domain = of_get_pci_domain_nr(parent->of_node);
/*
* Check DT domain and use_dt_domains values.
*
* If DT domain property is valid (domain >= 0) and
* use_dt_domains != 0, the DT assignment is valid since this means
* we have not previously allocated a domain number by using
* pci_get_new_domain_nr(); we should also update use_dt_domains to
* 1, to indicate that we have just assigned a domain number from
* DT.
*
* If DT domain property value is not valid (ie domain < 0), and we
* have not previously assigned a domain number from DT
* (use_dt_domains != 1) we should assign a domain number by
* using the:
*
* pci_get_new_domain_nr()
*
* API and update the use_dt_domains value to keep track of method we
* are using to assign domain numbers (use_dt_domains = 0).
*
* All other combinations imply we have a platform that is trying
* to mix domain numbers obtained from DT and pci_get_new_domain_nr(),
* which is a recipe for domain mishandling and it is prevented by
* invalidating the domain value (domain = -1) and printing a
* corresponding error.
*/
if (domain >= 0 && use_dt_domains) {
use_dt_domains = 1;
} else if (domain < 0 && use_dt_domains != 1) {
use_dt_domains = 0;
domain = pci_get_new_domain_nr();
} else {
dev_err(parent, "Node %s has inconsistent \"linux,pci-domain\" property in DT\n",
parent->of_node->full_name);
domain = -1;
}
bus->domain_nr = domain;
}
#endif
#endif
/**