diff options
author | MUNEDA Takahiro <muneda.takahiro@jp.fujitsu.com> | 2006-03-22 00:49:09 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2006-06-19 17:13:21 -0400 |
commit | 92c9be95549632da09088320f202fa5c05b21ddf (patch) | |
tree | 744691b15a41c90f9eb6747aff01396c55222834 /drivers/pci | |
parent | e55dea58c5609aece6156a6cd2306b820a7794ef (diff) |
[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>
Diffstat (limited to 'drivers/pci')
-rw-r--r-- | drivers/pci/hotplug/acpiphp_glue.c | 71 |
1 files changed, 33 insertions, 38 deletions
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index 053ee843863c..fadd264b64c3 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c | |||
@@ -797,36 +797,6 @@ static unsigned char acpiphp_max_busnr(struct pci_bus *bus) | |||
797 | } | 797 | } |
798 | 798 | ||
799 | 799 | ||
800 | |||
801 | /** | ||
802 | * get_func - get a pointer to acpiphp_func given a slot, device | ||
803 | * @slot: slot to search | ||
804 | * @dev: pci_dev struct to match. | ||
805 | * | ||
806 | * This function will increase the reference count of pci_dev, | ||
807 | * so callers should call pci_dev_put when complete. | ||
808 | * | ||
809 | */ | ||
810 | static struct acpiphp_func * | ||
811 | get_func(struct acpiphp_slot *slot, struct pci_dev *dev) | ||
812 | { | ||
813 | struct acpiphp_func *func = NULL; | ||
814 | struct pci_bus *bus = slot->bridge->pci_bus; | ||
815 | struct pci_dev *pdev; | ||
816 | |||
817 | list_for_each_entry(func, &slot->funcs, sibling) { | ||
818 | pdev = pci_get_slot(bus, PCI_DEVFN(slot->device, | ||
819 | func->function)); | ||
820 | if (pdev) { | ||
821 | if (pdev == dev) | ||
822 | break; | ||
823 | pci_dev_put(pdev); | ||
824 | } | ||
825 | } | ||
826 | return func; | ||
827 | } | ||
828 | |||
829 | |||
830 | /** | 800 | /** |
831 | * acpiphp_bus_add - add a new bus to acpi subsystem | 801 | * acpiphp_bus_add - add a new bus to acpi subsystem |
832 | * @func: acpiphp_func of the bridge | 802 | * @func: acpiphp_func of the bridge |
@@ -872,6 +842,28 @@ acpiphp_bus_add_out: | |||
872 | } | 842 | } |
873 | 843 | ||
874 | 844 | ||
845 | /** | ||
846 | * acpiphp_bus_trim - trim a bus from acpi subsystem | ||
847 | * @handle: handle to acpi namespace | ||
848 | * | ||
849 | */ | ||
850 | int acpiphp_bus_trim(acpi_handle handle) | ||
851 | { | ||
852 | struct acpi_device *device; | ||
853 | int retval; | ||
854 | |||
855 | retval = acpi_bus_get_device(handle, &device); | ||
856 | if (retval) { | ||
857 | dbg("acpi_device not found\n"); | ||
858 | return retval; | ||
859 | } | ||
860 | |||
861 | retval = acpi_bus_trim(device, 1); | ||
862 | if (retval) | ||
863 | err("cannot remove from acpi list\n"); | ||
864 | |||
865 | return retval; | ||
866 | } | ||
875 | 867 | ||
876 | /** | 868 | /** |
877 | * enable_device - enable, configure a slot | 869 | * enable_device - enable, configure a slot |
@@ -918,19 +910,17 @@ static int enable_device(struct acpiphp_slot *slot) | |||
918 | if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE || | 910 | if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE || |
919 | dev->hdr_type == PCI_HEADER_TYPE_CARDBUS) { | 911 | dev->hdr_type == PCI_HEADER_TYPE_CARDBUS) { |
920 | max = pci_scan_bridge(bus, dev, max, pass); | 912 | max = pci_scan_bridge(bus, dev, max, pass); |
921 | if (pass && dev->subordinate) { | 913 | if (pass && dev->subordinate) |
922 | pci_bus_size_bridges(dev->subordinate); | 914 | pci_bus_size_bridges(dev->subordinate); |
923 | func = get_func(slot, dev); | ||
924 | if (func) { | ||
925 | acpiphp_bus_add(func); | ||
926 | /* side effect of get_func */ | ||
927 | pci_dev_put(dev); | ||
928 | } | ||
929 | } | ||
930 | } | 915 | } |
931 | } | 916 | } |
932 | } | 917 | } |
933 | 918 | ||
919 | list_for_each (l, &slot->funcs) { | ||
920 | func = list_entry(l, struct acpiphp_func, sibling); | ||
921 | acpiphp_bus_add(func); | ||
922 | } | ||
923 | |||
934 | pci_bus_assign_resources(bus); | 924 | pci_bus_assign_resources(bus); |
935 | acpiphp_sanitize_bus(bus); | 925 | acpiphp_sanitize_bus(bus); |
936 | pci_enable_bridges(bus); | 926 | pci_enable_bridges(bus); |
@@ -967,6 +957,11 @@ static int disable_device(struct acpiphp_slot *slot) | |||
967 | 957 | ||
968 | list_for_each (l, &slot->funcs) { | 958 | list_for_each (l, &slot->funcs) { |
969 | func = list_entry(l, struct acpiphp_func, sibling); | 959 | func = list_entry(l, struct acpiphp_func, sibling); |
960 | |||
961 | acpiphp_bus_trim(func->handle); | ||
962 | /* try to remove anyway. | ||
963 | * acpiphp_bus_add might have been failed */ | ||
964 | |||
970 | if (!func->pci_dev) | 965 | if (!func->pci_dev) |
971 | continue; | 966 | continue; |
972 | 967 | ||