summaryrefslogtreecommitdiffstats
path: root/arch/sparc/kernel/pci.c
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2010-02-20 19:53:55 -0800
committerDavid S. Miller <davem@davemloft.net>2010-02-20 19:53:55 -0800
commit2ef2d7477549c85b84b24b155baa798650cbf90b (patch)
tree49b9f1521ff078eabb328288afb72ad6bb592c37 /arch/sparc/kernel/pci.c
parent198d2f63a6096fe575b696b13ba61b62c620266f (diff)
sparc64: If 'slot-names' property exist, create sysfs PCI slot information.
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'arch/sparc/kernel/pci.c')
-rw-r--r--arch/sparc/kernel/pci.c75
1 files changed, 75 insertions, 0 deletions
diff --git a/arch/sparc/kernel/pci.c b/arch/sparc/kernel/pci.c
index 592b03d8516..d7e1cf01dd2 100644
--- a/arch/sparc/kernel/pci.c
+++ b/arch/sparc/kernel/pci.c
@@ -1094,3 +1094,78 @@ static int __init pcibios_init(void)
return 0;
}
subsys_initcall(pcibios_init);
+
+#ifdef CONFIG_SYSFS
+static void __devinit pci_bus_slot_names(struct device_node *node,
+ struct pci_bus *bus)
+{
+ const struct pci_slot_names {
+ u32 slot_mask;
+ char names[0];
+ } *prop;
+ const char *sp;
+ int len, i;
+ u32 mask;
+
+ prop = of_get_property(node, "slot-names", &len);
+ if (!prop)
+ return;
+
+ mask = prop->slot_mask;
+ sp = prop->names;
+
+ if (ofpci_verbose)
+ printk("PCI: Making slots for [%s] mask[0x%02x]\n",
+ node->full_name, mask);
+
+ i = 0;
+ while (mask) {
+ struct pci_slot *pci_slot;
+ u32 this_bit = 1 << i;
+
+ if (!(mask & this_bit)) {
+ i++;
+ continue;
+ }
+
+ if (ofpci_verbose)
+ printk("PCI: Making slot [%s]\n", sp);
+
+ pci_slot = pci_create_slot(bus, i, sp, NULL);
+ if (IS_ERR(pci_slot))
+ printk(KERN_ERR "PCI: pci_create_slot returned %ld\n",
+ PTR_ERR(pci_slot));
+
+ sp += strlen(sp) + 1;
+ mask &= ~this_bit;
+ i++;
+ }
+}
+
+static int __init of_pci_slot_init(void)
+{
+ struct pci_bus *pbus = NULL;
+
+ while ((pbus = pci_find_next_bus(pbus)) != NULL) {
+ struct device_node *node;
+
+ if (pbus->self) {
+ struct dev_archdata *sd = pbus->self->sysdata;
+
+ /* PCI->PCI bridge */
+ node = sd->prom_node;
+ } else {
+ struct pci_pbm_info *pbm = pbus->sysdata;
+
+ /* Host PCI controller */
+ node = pbm->op->node;
+ }
+
+ pci_bus_slot_names(node, pbus);
+ }
+
+ return 0;
+}
+
+module_init(of_pci_slot_init);
+#endif