[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 коммит произвёл Greg Kroah-Hartman
Родитель e55dea58c5
Коммит 92c9be9554
1 изменённых файлов: 33 добавлений и 38 удалений

Просмотреть файл

@ -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 * acpiphp_bus_add - add a new bus to acpi subsystem
* @func: acpiphp_func of the bridge * @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 * enable_device - enable, configure a slot
@ -918,17 +910,15 @@ static int enable_device(struct acpiphp_slot *slot)
if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE || if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE ||
dev->hdr_type == PCI_HEADER_TYPE_CARDBUS) { dev->hdr_type == PCI_HEADER_TYPE_CARDBUS) {
max = pci_scan_bridge(bus, dev, max, pass); max = pci_scan_bridge(bus, dev, max, pass);
if (pass && dev->subordinate) { if (pass && dev->subordinate)
pci_bus_size_bridges(dev->subordinate); pci_bus_size_bridges(dev->subordinate);
func = get_func(slot, dev); }
if (func) { }
}
list_for_each (l, &slot->funcs) {
func = list_entry(l, struct acpiphp_func, sibling);
acpiphp_bus_add(func); acpiphp_bus_add(func);
/* side effect of get_func */
pci_dev_put(dev);
}
}
}
}
} }
pci_bus_assign_resources(bus); pci_bus_assign_resources(bus);
@ -967,6 +957,11 @@ static int disable_device(struct acpiphp_slot *slot)
list_for_each (l, &slot->funcs) { list_for_each (l, &slot->funcs) {
func = list_entry(l, struct acpiphp_func, sibling); 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) if (!func->pci_dev)
continue; continue;