Commit 68b308e8 authored by Matthew Dobson's avatar Matthew Dobson Committed by Linus Torvalds

[PATCH] PCI: add pci_bus sysfs class

This is needed to show pci bus topology to userspace properly.
parent 78d65a24
...@@ -116,6 +116,8 @@ void __devinit pci_bus_add_devices(struct pci_bus *bus) ...@@ -116,6 +116,8 @@ void __devinit pci_bus_add_devices(struct pci_bus *bus)
list_add_tail(&dev->subordinate->node, &dev->bus->children); list_add_tail(&dev->subordinate->node, &dev->bus->children);
spin_unlock(&pci_bus_lock); spin_unlock(&pci_bus_lock);
pci_bus_add_devices(dev->subordinate); pci_bus_add_devices(dev->subordinate);
sysfs_create_link(&dev->subordinate->class_dev.kobj, &dev->dev.kobj, "bridge");
} }
} }
} }
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/cpumask.h>
#undef DEBUG #undef DEBUG
...@@ -24,6 +25,39 @@ EXPORT_SYMBOL(pci_root_buses); ...@@ -24,6 +25,39 @@ EXPORT_SYMBOL(pci_root_buses);
LIST_HEAD(pci_devices); LIST_HEAD(pci_devices);
/*
* PCI Bus Class
*/
static void release_pcibus_dev(struct class_device *class_dev)
{
struct pci_bus *pci_bus = to_pci_bus(class_dev);
if (pci_bus->bridge)
put_device(pci_bus->bridge);
kfree(pci_bus);
}
static struct class pcibus_class = {
.name = "pci_bus",
.release = &release_pcibus_dev,
};
static int __init pcibus_class_init(void)
{
return class_register(&pcibus_class);
}
postcore_initcall(pcibus_class_init);
/*
* PCI Bus Class Devices
*/
static ssize_t pci_bus_show_cpuaffinity(struct class_device *class_dev, char *buf)
{
cpumask_t cpumask = pcibus_to_cpumask((to_pci_bus(class_dev))->number);
return sprintf(buf, "%lx\n", (unsigned long)cpumask);
}
static CLASS_DEVICE_ATTR(cpuaffinity, S_IRUGO, pci_bus_show_cpuaffinity, NULL);
/* /*
* Translate the low bits of the PCI base * Translate the low bits of the PCI base
* to the resource type * to the resource type
...@@ -238,20 +272,25 @@ static struct pci_bus * __devinit ...@@ -238,20 +272,25 @@ static struct pci_bus * __devinit
pci_alloc_child_bus(struct pci_bus *parent, struct pci_dev *bridge, int busnr) pci_alloc_child_bus(struct pci_bus *parent, struct pci_dev *bridge, int busnr)
{ {
struct pci_bus *child; struct pci_bus *child;
int i;
/* /*
* Allocate a new bus, and inherit stuff from the parent.. * Allocate a new bus, and inherit stuff from the parent..
*/ */
child = pci_alloc_bus(); child = pci_alloc_bus();
if (!child)
if (child) { return NULL;
int i;
child->self = bridge; child->self = bridge;
child->parent = parent; child->parent = parent;
child->ops = parent->ops; child->ops = parent->ops;
child->sysdata = parent->sysdata; child->sysdata = parent->sysdata;
child->dev = &bridge->dev; child->bridge = get_device(&bridge->dev);
child->class_dev.class = &pcibus_class;
sprintf(child->class_dev.class_id, "%04x:%02x", pci_domain_nr(child), busnr);
class_device_register(&child->class_dev);
class_device_create_file(&child->class_dev, &class_device_attr_cpuaffinity);
/* /*
* Set up the primary, secondary and subordinate * Set up the primary, secondary and subordinate
...@@ -266,9 +305,7 @@ pci_alloc_child_bus(struct pci_bus *parent, struct pci_dev *bridge, int busnr) ...@@ -266,9 +305,7 @@ pci_alloc_child_bus(struct pci_bus *parent, struct pci_dev *bridge, int busnr)
child->resource[i] = &bridge->resource[PCI_BRIDGE_RESOURCES+i]; child->resource[i] = &bridge->resource[PCI_BRIDGE_RESOURCES+i];
child->resource[i]->name = child->name; child->resource[i]->name = child->name;
} }
bridge->subordinate = child; bridge->subordinate = child;
}
return child; return child;
} }
...@@ -307,18 +344,17 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max ...@@ -307,18 +344,17 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max
pci_name(dev), buses & 0xffffff, pass); pci_name(dev), buses & 0xffffff, pass);
if ((buses & 0xffff00) && !pcibios_assign_all_busses() && !is_cardbus) { if ((buses & 0xffff00) && !pcibios_assign_all_busses() && !is_cardbus) {
unsigned int cmax; unsigned int cmax, busnr;
/* /*
* Bus already configured by firmware, process it in the first * Bus already configured by firmware, process it in the first
* pass and just note the configuration. * pass and just note the configuration.
*/ */
if (pass) if (pass)
return max; return max;
child = pci_alloc_child_bus(bus, dev, 0); busnr = (buses >> 8) & 0xFF;
child = pci_alloc_child_bus(bus, dev, busnr);
child->primary = buses & 0xFF; child->primary = buses & 0xFF;
child->secondary = (buses >> 8) & 0xFF;
child->subordinate = (buses >> 16) & 0xFF; child->subordinate = (buses >> 16) & 0xFF;
child->number = child->secondary;
cmax = pci_scan_child_bus(child); cmax = pci_scan_child_bus(child);
if (cmax > max) max = cmax; if (cmax > max) max = cmax;
} else { } else {
...@@ -508,7 +544,7 @@ pci_scan_device(struct pci_bus *bus, int devfn) ...@@ -508,7 +544,7 @@ pci_scan_device(struct pci_bus *bus, int devfn)
memset(dev, 0, sizeof(struct pci_dev)); memset(dev, 0, sizeof(struct pci_dev));
dev->bus = bus; dev->bus = bus;
dev->sysdata = bus->sysdata; dev->sysdata = bus->sysdata;
dev->dev.parent = bus->dev; dev->dev.parent = bus->bridge;
dev->dev.bus = &pci_bus_type; dev->dev.bus = &pci_bus_type;
dev->devfn = devfn; dev->devfn = devfn;
dev->hdr_type = hdr_type & 0x7f; dev->hdr_type = hdr_type & 0x7f;
...@@ -635,13 +671,14 @@ unsigned int __devinit pci_do_scan_bus(struct pci_bus *bus) ...@@ -635,13 +671,14 @@ unsigned int __devinit pci_do_scan_bus(struct pci_bus *bus)
struct pci_bus * __devinit pci_scan_bus_parented(struct device *parent, int bus, struct pci_ops *ops, void *sysdata) struct pci_bus * __devinit pci_scan_bus_parented(struct device *parent, int bus, struct pci_ops *ops, void *sysdata)
{ {
struct pci_bus *b; struct pci_bus *b;
struct device *dev;
b = pci_alloc_bus(); b = pci_alloc_bus();
if (!b) if (!b)
return NULL; return NULL;
b->dev = kmalloc(sizeof(*(b->dev)),GFP_KERNEL); dev = kmalloc(sizeof(*dev), GFP_KERNEL);
if (!b->dev){ if (!dev){
kfree(b); kfree(b);
return NULL; return NULL;
} }
...@@ -652,17 +689,24 @@ struct pci_bus * __devinit pci_scan_bus_parented(struct device *parent, int bus, ...@@ -652,17 +689,24 @@ struct pci_bus * __devinit pci_scan_bus_parented(struct device *parent, int bus,
if (pci_find_bus(pci_domain_nr(b), bus)) { if (pci_find_bus(pci_domain_nr(b), bus)) {
/* If we already got to this bus through a different bridge, ignore it */ /* If we already got to this bus through a different bridge, ignore it */
DBG("PCI: Bus %02x already known\n", bus); DBG("PCI: Bus %02x already known\n", bus);
kfree(b->dev); kfree(dev);
kfree(b); kfree(b);
return NULL; return NULL;
} }
list_add_tail(&b->node, &pci_root_buses); list_add_tail(&b->node, &pci_root_buses);
memset(b->dev,0,sizeof(*(b->dev))); memset(dev, 0, sizeof(*dev));
b->dev->parent = parent; dev->parent = parent;
sprintf(b->dev->bus_id,"pci%04x:%02x", pci_domain_nr(b), bus); sprintf(dev->bus_id, "pci%04x:%02x", pci_domain_nr(b), bus);
device_register(b->dev); device_register(dev);
b->bridge = get_device(dev);
b->class_dev.class = &pcibus_class;
sprintf(b->class_dev.class_id, "%04x:%02x", pci_domain_nr(b), bus);
class_device_register(&b->class_dev);
class_device_create_file(&b->class_dev, &class_device_attr_cpuaffinity);
sysfs_create_link(&b->class_dev.kobj, &b->bridge->kobj, "bridge");
b->number = b->secondary = bus; b->number = b->secondary = bus;
b->resource[0] = &ioport_resource; b->resource[0] = &ioport_resource;
......
...@@ -473,10 +473,12 @@ struct pci_bus { ...@@ -473,10 +473,12 @@ struct pci_bus {
char name[48]; char name[48];
struct device * dev; struct device *bridge;
struct class_device class_dev;
}; };
#define pci_bus_b(n) list_entry(n, struct pci_bus, node) #define pci_bus_b(n) list_entry(n, struct pci_bus, node)
#define to_pci_bus(n) container_of(n, struct pci_bus, class_dev)
/* /*
* Error values that may be returned by PCI functions. * Error values that may be returned by PCI functions.
......
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