PCI: construct one fakephp slot per PCI slot
Register one slot per slot, rather than one slot per function. Change the name of the slot to fake%d instead of the pci address. Signed-off-by: Alex Chiang <achiang@hp.com> Signed-off-by: Matthew Wilcox <matthew@wil.cx> Cc: Greg KH <greg@kroah.com> Cc: Kristen Carlson Accardi <kristen.c.accardi@intel.com> Cc: Len Brown <lenb@kernel.org> Cc: Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
This commit is contained in:
parent
64dab20450
commit
fe99740cac
@ -66,6 +66,7 @@ struct dummy_slot {
|
|||||||
struct pci_dev *dev;
|
struct pci_dev *dev;
|
||||||
struct work_struct remove_work;
|
struct work_struct remove_work;
|
||||||
unsigned long removed;
|
unsigned long removed;
|
||||||
|
char name[8];
|
||||||
};
|
};
|
||||||
|
|
||||||
static int debug;
|
static int debug;
|
||||||
@ -100,6 +101,7 @@ static int add_slot(struct pci_dev *dev)
|
|||||||
struct dummy_slot *dslot;
|
struct dummy_slot *dslot;
|
||||||
struct hotplug_slot *slot;
|
struct hotplug_slot *slot;
|
||||||
int retval = -ENOMEM;
|
int retval = -ENOMEM;
|
||||||
|
static int count = 1;
|
||||||
|
|
||||||
slot = kzalloc(sizeof(struct hotplug_slot), GFP_KERNEL);
|
slot = kzalloc(sizeof(struct hotplug_slot), GFP_KERNEL);
|
||||||
if (!slot)
|
if (!slot)
|
||||||
@ -113,13 +115,13 @@ static int add_slot(struct pci_dev *dev)
|
|||||||
slot->info->max_bus_speed = PCI_SPEED_UNKNOWN;
|
slot->info->max_bus_speed = PCI_SPEED_UNKNOWN;
|
||||||
slot->info->cur_bus_speed = PCI_SPEED_UNKNOWN;
|
slot->info->cur_bus_speed = PCI_SPEED_UNKNOWN;
|
||||||
|
|
||||||
slot->name = &dev->dev.bus_id[0];
|
|
||||||
dbg("slot->name = %s\n", slot->name);
|
|
||||||
|
|
||||||
dslot = kzalloc(sizeof(struct dummy_slot), GFP_KERNEL);
|
dslot = kzalloc(sizeof(struct dummy_slot), GFP_KERNEL);
|
||||||
if (!dslot)
|
if (!dslot)
|
||||||
goto error_info;
|
goto error_info;
|
||||||
|
|
||||||
|
slot->name = dslot->name;
|
||||||
|
snprintf(slot->name, sizeof(dslot->name), "fake%d", count++);
|
||||||
|
dbg("slot->name = %s\n", slot->name);
|
||||||
slot->ops = &dummy_hotplug_slot_ops;
|
slot->ops = &dummy_hotplug_slot_ops;
|
||||||
slot->release = &dummy_release;
|
slot->release = &dummy_release;
|
||||||
slot->private = dslot;
|
slot->private = dslot;
|
||||||
@ -148,17 +150,17 @@ error:
|
|||||||
static int __init pci_scan_buses(void)
|
static int __init pci_scan_buses(void)
|
||||||
{
|
{
|
||||||
struct pci_dev *dev = NULL;
|
struct pci_dev *dev = NULL;
|
||||||
int retval = 0;
|
int lastslot = 0;
|
||||||
|
|
||||||
while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
|
while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
|
||||||
retval = add_slot(dev);
|
if (PCI_FUNC(dev->devfn) > 0 &&
|
||||||
if (retval) {
|
lastslot == PCI_SLOT(dev->devfn))
|
||||||
pci_dev_put(dev);
|
continue;
|
||||||
break;
|
lastslot = PCI_SLOT(dev->devfn);
|
||||||
}
|
add_slot(dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
return retval;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void remove_slot(struct dummy_slot *dslot)
|
static void remove_slot(struct dummy_slot *dslot)
|
||||||
@ -296,23 +298,9 @@ static int enable_slot(struct hotplug_slot *hotplug_slot)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* find the hotplug_slot for the pci_dev */
|
|
||||||
static struct hotplug_slot *get_slot_from_dev(struct pci_dev *dev)
|
|
||||||
{
|
|
||||||
struct dummy_slot *dslot;
|
|
||||||
|
|
||||||
list_for_each_entry(dslot, &slot_list, node) {
|
|
||||||
if (dslot->dev == dev)
|
|
||||||
return dslot->slot;
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int disable_slot(struct hotplug_slot *slot)
|
static int disable_slot(struct hotplug_slot *slot)
|
||||||
{
|
{
|
||||||
struct dummy_slot *dslot;
|
struct dummy_slot *dslot;
|
||||||
struct hotplug_slot *hslot;
|
|
||||||
struct pci_dev *dev;
|
struct pci_dev *dev;
|
||||||
int func;
|
int func;
|
||||||
|
|
||||||
@ -322,41 +310,27 @@ static int disable_slot(struct hotplug_slot *slot)
|
|||||||
|
|
||||||
dbg("%s - physical_slot = %s\n", __func__, slot->name);
|
dbg("%s - physical_slot = %s\n", __func__, slot->name);
|
||||||
|
|
||||||
/* don't disable bridged devices just yet, we can't handle them easily... */
|
for (func = 7; func >= 0; func--) {
|
||||||
if (dslot->dev->subordinate) {
|
dev = pci_get_slot(dslot->dev->bus, dslot->dev->devfn + func);
|
||||||
err("Can't remove PCI devices with other PCI devices behind it yet.\n");
|
if (!dev)
|
||||||
return -ENODEV;
|
continue;
|
||||||
}
|
|
||||||
if (test_and_set_bit(0, &dslot->removed)) {
|
if (test_and_set_bit(0, &dslot->removed)) {
|
||||||
dbg("Slot already scheduled for removal\n");
|
dbg("Slot already scheduled for removal\n");
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
|
||||||
/* search for subfunctions and disable them first */
|
|
||||||
if (!(dslot->dev->devfn & 7)) {
|
|
||||||
for (func = 1; func < 8; func++) {
|
|
||||||
dev = pci_get_slot(dslot->dev->bus,
|
|
||||||
dslot->dev->devfn + func);
|
|
||||||
if (dev) {
|
|
||||||
hslot = get_slot_from_dev(dev);
|
|
||||||
if (hslot)
|
|
||||||
disable_slot(hslot);
|
|
||||||
else {
|
|
||||||
err("Hotplug slot not found for subfunction of PCI device\n");
|
|
||||||
return -ENODEV;
|
|
||||||
}
|
|
||||||
pci_dev_put(dev);
|
|
||||||
} else
|
|
||||||
dbg("No device in slot found\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* queue work item to blow away this sysfs entry and other
|
||||||
|
* parts.
|
||||||
|
*/
|
||||||
|
INIT_WORK(&dslot->remove_work, remove_slot_worker);
|
||||||
|
queue_work(dummyphp_wq, &dslot->remove_work);
|
||||||
|
|
||||||
|
/* blow away this sysfs entry and other parts. */
|
||||||
|
remove_slot(dslot);
|
||||||
|
|
||||||
|
pci_dev_put(dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* remove the device from the pci core */
|
|
||||||
pci_remove_bus_device(dslot->dev);
|
|
||||||
|
|
||||||
/* queue work item to blow away this sysfs entry and other parts. */
|
|
||||||
INIT_WORK(&dslot->remove_work, remove_slot_worker);
|
|
||||||
queue_work(dummyphp_wq, &dslot->remove_work);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user