Commit f0c1a117 authored by Eric Snowberg's avatar Eric Snowberg Committed by David S. Miller

sparc64: pci slots information is not populated in sysfs

Add PCI slot numbers within sysfs for PCIe hardware.  Larger
PCIe systems with nested PCI bridges and slots further
down on these bridges were not being populated within sysfs.
This will add ACPI style PCI slot numbers for these systems
since the OF 'slot-names' information is not available on
all PCIe platforms.
Signed-off-by: default avatarEric Snowberg <eric.snowberg@oracle.com>
Reviewed-by: default avatarBob Picco <bob.picco@oracle.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 8642ad1c
...@@ -1002,6 +1002,38 @@ static int __init pcibios_init(void) ...@@ -1002,6 +1002,38 @@ static int __init pcibios_init(void)
subsys_initcall(pcibios_init); subsys_initcall(pcibios_init);
#ifdef CONFIG_SYSFS #ifdef CONFIG_SYSFS
#define SLOT_NAME_SIZE 11 /* Max decimal digits + null in u32 */
static void pcie_bus_slot_names(struct pci_bus *pbus)
{
struct pci_dev *pdev;
struct pci_bus *bus;
list_for_each_entry(pdev, &pbus->devices, bus_list) {
char name[SLOT_NAME_SIZE];
struct pci_slot *pci_slot;
const u32 *slot_num;
int len;
slot_num = of_get_property(pdev->dev.of_node,
"physical-slot#", &len);
if (slot_num == NULL || len != 4)
continue;
snprintf(name, sizeof(name), "%u", slot_num[0]);
pci_slot = pci_create_slot(pbus, slot_num[0], name, NULL);
if (IS_ERR(pci_slot))
pr_err("PCI: pci_create_slot returned %ld.\n",
PTR_ERR(pci_slot));
}
list_for_each_entry(bus, &pbus->children, node)
pcie_bus_slot_names(bus);
}
static void pci_bus_slot_names(struct device_node *node, struct pci_bus *bus) static void pci_bus_slot_names(struct device_node *node, struct pci_bus *bus)
{ {
const struct pci_slot_names { const struct pci_slot_names {
...@@ -1053,18 +1085,29 @@ static int __init of_pci_slot_init(void) ...@@ -1053,18 +1085,29 @@ static int __init of_pci_slot_init(void)
while ((pbus = pci_find_next_bus(pbus)) != NULL) { while ((pbus = pci_find_next_bus(pbus)) != NULL) {
struct device_node *node; struct device_node *node;
struct pci_dev *pdev;
pdev = list_first_entry(&pbus->devices, struct pci_dev,
bus_list);
if (pbus->self) { if (pdev && pci_is_pcie(pdev)) {
/* PCI->PCI bridge */ pcie_bus_slot_names(pbus);
node = pbus->self->dev.of_node;
} else { } else {
struct pci_pbm_info *pbm = pbus->sysdata;
/* Host PCI controller */ if (pbus->self) {
node = pbm->op->dev.of_node;
} /* PCI->PCI bridge */
node = pbus->self->dev.of_node;
} else {
struct pci_pbm_info *pbm = pbus->sysdata;
pci_bus_slot_names(node, pbus); /* Host PCI controller */
node = pbm->op->dev.of_node;
}
pci_bus_slot_names(node, pbus);
}
} }
return 0; return 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment