[PATCH] acpiphp: configure _PRT - V3

Current acpiphp does not free acpi_device structs when the
PCI devices are removed. When the PCI device is added,
acpi_bus_add() fails because acpi_device struct has already
exists. So, _PRT method does not evaluate.

This patch fixes this issue.

Signed-off-by: MUNEDA Takahiro <muneda.takahiro@jp.fujitsu.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
This commit is contained in:
MUNEDA Takahiro 2006-03-22 14:49:09 +09:00 committed by Greg Kroah-Hartman
parent e55dea58c5
commit 92c9be9554
1 changed files with 33 additions and 38 deletions

View File

@ -797,36 +797,6 @@ static unsigned char acpiphp_max_busnr(struct pci_bus *bus)
}
/**
* get_func - get a pointer to acpiphp_func given a slot, device
* @slot: slot to search
* @dev: pci_dev struct to match.
*
* This function will increase the reference count of pci_dev,
* so callers should call pci_dev_put when complete.
*
*/
static struct acpiphp_func *
get_func(struct acpiphp_slot *slot, struct pci_dev *dev)
{
struct acpiphp_func *func = NULL;
struct pci_bus *bus = slot->bridge->pci_bus;
struct pci_dev *pdev;
list_for_each_entry(func, &slot->funcs, sibling) {
pdev = pci_get_slot(bus, PCI_DEVFN(slot->device,
func->function));
if (pdev) {
if (pdev == dev)
break;
pci_dev_put(pdev);
}
}
return func;
}
/**
* acpiphp_bus_add - add a new bus to acpi subsystem
* @func: acpiphp_func of the bridge
@ -872,6 +842,28 @@ acpiphp_bus_add_out:
}
/**
* acpiphp_bus_trim - trim a bus from acpi subsystem
* @handle: handle to acpi namespace
*
*/
int acpiphp_bus_trim(acpi_handle handle)
{
struct acpi_device *device;
int retval;
retval = acpi_bus_get_device(handle, &device);
if (retval) {
dbg("acpi_device not found\n");
return retval;
}
retval = acpi_bus_trim(device, 1);
if (retval)
err("cannot remove from acpi list\n");
return retval;
}
/**
* enable_device - enable, configure a slot
@ -918,19 +910,17 @@ static int enable_device(struct acpiphp_slot *slot)
if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE ||
dev->hdr_type == PCI_HEADER_TYPE_CARDBUS) {
max = pci_scan_bridge(bus, dev, max, pass);
if (pass && dev->subordinate) {
if (pass && dev->subordinate)
pci_bus_size_bridges(dev->subordinate);
func = get_func(slot, dev);
if (func) {
acpiphp_bus_add(func);
/* side effect of get_func */
pci_dev_put(dev);
}
}
}
}
}
list_for_each (l, &slot->funcs) {
func = list_entry(l, struct acpiphp_func, sibling);
acpiphp_bus_add(func);
}
pci_bus_assign_resources(bus);
acpiphp_sanitize_bus(bus);
pci_enable_bridges(bus);
@ -967,6 +957,11 @@ static int disable_device(struct acpiphp_slot *slot)
list_for_each (l, &slot->funcs) {
func = list_entry(l, struct acpiphp_func, sibling);
acpiphp_bus_trim(func->handle);
/* try to remove anyway.
* acpiphp_bus_add might have been failed */
if (!func->pci_dev)
continue;