diff options
author | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2009-06-11 04:58:01 -0400 |
---|---|---|
committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2009-06-11 04:58:01 -0400 |
commit | 4894e4aca82aca927d0404ce61f021f790de4b1e (patch) | |
tree | bbe0d083829f5858295298f188d885367cf4b1f6 /drivers/pci/hotplug | |
parent | 05e882f890038c702a4f15d385135d03cf74ad48 (diff) | |
parent | 07a2039b8eb0af4ff464efd3dfd95de5c02648c6 (diff) |
Merge commit 'v2.6.30' into next
Diffstat (limited to 'drivers/pci/hotplug')
-rw-r--r-- | drivers/pci/hotplug/acpiphp.h | 1 | ||||
-rw-r--r-- | drivers/pci/hotplug/acpiphp_glue.c | 63 |
2 files changed, 26 insertions, 38 deletions
diff --git a/drivers/pci/hotplug/acpiphp.h b/drivers/pci/hotplug/acpiphp.h index 4fc168b7009..e68d5f20ffb 100644 --- a/drivers/pci/hotplug/acpiphp.h +++ b/drivers/pci/hotplug/acpiphp.h | |||
@@ -129,7 +129,6 @@ struct acpiphp_func { | |||
129 | struct acpiphp_bridge *bridge; /* Ejectable PCI-to-PCI bridge */ | 129 | struct acpiphp_bridge *bridge; /* Ejectable PCI-to-PCI bridge */ |
130 | 130 | ||
131 | struct list_head sibling; | 131 | struct list_head sibling; |
132 | struct pci_dev *pci_dev; | ||
133 | struct notifier_block nb; | 132 | struct notifier_block nb; |
134 | acpi_handle handle; | 133 | acpi_handle handle; |
135 | 134 | ||
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index a33794d9e0d..3a6064bce56 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c | |||
@@ -32,9 +32,6 @@ | |||
32 | 32 | ||
33 | /* | 33 | /* |
34 | * Lifetime rules for pci_dev: | 34 | * Lifetime rules for pci_dev: |
35 | * - The one in acpiphp_func has its refcount elevated by pci_get_slot() | ||
36 | * when the driver is loaded or when an insertion event occurs. It loses | ||
37 | * a refcount when its ejected or the driver unloads. | ||
38 | * - The one in acpiphp_bridge has its refcount elevated by pci_get_slot() | 35 | * - The one in acpiphp_bridge has its refcount elevated by pci_get_slot() |
39 | * when the bridge is scanned and it loses a refcount when the bridge | 36 | * when the bridge is scanned and it loses a refcount when the bridge |
40 | * is removed. | 37 | * is removed. |
@@ -130,6 +127,7 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) | |||
130 | unsigned long long adr, sun; | 127 | unsigned long long adr, sun; |
131 | int device, function, retval; | 128 | int device, function, retval; |
132 | struct pci_bus *pbus = bridge->pci_bus; | 129 | struct pci_bus *pbus = bridge->pci_bus; |
130 | struct pci_dev *pdev; | ||
133 | 131 | ||
134 | if (!acpi_pci_check_ejectable(pbus, handle) && !is_dock_device(handle)) | 132 | if (!acpi_pci_check_ejectable(pbus, handle) && !is_dock_device(handle)) |
135 | return AE_OK; | 133 | return AE_OK; |
@@ -213,10 +211,10 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) | |||
213 | newfunc->slot = slot; | 211 | newfunc->slot = slot; |
214 | list_add_tail(&newfunc->sibling, &slot->funcs); | 212 | list_add_tail(&newfunc->sibling, &slot->funcs); |
215 | 213 | ||
216 | /* associate corresponding pci_dev */ | 214 | pdev = pci_get_slot(pbus, PCI_DEVFN(device, function)); |
217 | newfunc->pci_dev = pci_get_slot(pbus, PCI_DEVFN(device, function)); | 215 | if (pdev) { |
218 | if (newfunc->pci_dev) { | ||
219 | slot->flags |= (SLOT_ENABLED | SLOT_POWEREDON); | 216 | slot->flags |= (SLOT_ENABLED | SLOT_POWEREDON); |
217 | pci_dev_put(pdev); | ||
220 | } | 218 | } |
221 | 219 | ||
222 | if (is_dock_device(handle)) { | 220 | if (is_dock_device(handle)) { |
@@ -617,7 +615,6 @@ static void cleanup_bridge(struct acpiphp_bridge *bridge) | |||
617 | if (ACPI_FAILURE(status)) | 615 | if (ACPI_FAILURE(status)) |
618 | err("failed to remove notify handler\n"); | 616 | err("failed to remove notify handler\n"); |
619 | } | 617 | } |
620 | pci_dev_put(func->pci_dev); | ||
621 | list_del(list); | 618 | list_del(list); |
622 | kfree(func); | 619 | kfree(func); |
623 | } | 620 | } |
@@ -1101,22 +1098,24 @@ static int __ref enable_device(struct acpiphp_slot *slot) | |||
1101 | pci_enable_bridges(bus); | 1098 | pci_enable_bridges(bus); |
1102 | pci_bus_add_devices(bus); | 1099 | pci_bus_add_devices(bus); |
1103 | 1100 | ||
1104 | /* associate pci_dev to our representation */ | ||
1105 | list_for_each (l, &slot->funcs) { | 1101 | list_for_each (l, &slot->funcs) { |
1106 | func = list_entry(l, struct acpiphp_func, sibling); | 1102 | func = list_entry(l, struct acpiphp_func, sibling); |
1107 | func->pci_dev = pci_get_slot(bus, PCI_DEVFN(slot->device, | 1103 | dev = pci_get_slot(bus, PCI_DEVFN(slot->device, |
1108 | func->function)); | 1104 | func->function)); |
1109 | if (!func->pci_dev) | 1105 | if (!dev) |
1110 | continue; | 1106 | continue; |
1111 | 1107 | ||
1112 | if (func->pci_dev->hdr_type != PCI_HEADER_TYPE_BRIDGE && | 1108 | if (dev->hdr_type != PCI_HEADER_TYPE_BRIDGE && |
1113 | func->pci_dev->hdr_type != PCI_HEADER_TYPE_CARDBUS) | 1109 | dev->hdr_type != PCI_HEADER_TYPE_CARDBUS) { |
1110 | pci_dev_put(dev); | ||
1114 | continue; | 1111 | continue; |
1112 | } | ||
1115 | 1113 | ||
1116 | status = find_p2p_bridge(func->handle, (u32)1, bus, NULL); | 1114 | status = find_p2p_bridge(func->handle, (u32)1, bus, NULL); |
1117 | if (ACPI_FAILURE(status)) | 1115 | if (ACPI_FAILURE(status)) |
1118 | warn("find_p2p_bridge failed (error code = 0x%x)\n", | 1116 | warn("find_p2p_bridge failed (error code = 0x%x)\n", |
1119 | status); | 1117 | status); |
1118 | pci_dev_put(dev); | ||
1120 | } | 1119 | } |
1121 | 1120 | ||
1122 | slot->flags |= SLOT_ENABLED; | 1121 | slot->flags |= SLOT_ENABLED; |
@@ -1142,17 +1141,14 @@ static void disable_bridges(struct pci_bus *bus) | |||
1142 | */ | 1141 | */ |
1143 | static int disable_device(struct acpiphp_slot *slot) | 1142 | static int disable_device(struct acpiphp_slot *slot) |
1144 | { | 1143 | { |
1145 | int retval = 0; | ||
1146 | struct acpiphp_func *func; | 1144 | struct acpiphp_func *func; |
1147 | struct list_head *l; | 1145 | struct pci_dev *pdev; |
1148 | 1146 | ||
1149 | /* is this slot already disabled? */ | 1147 | /* is this slot already disabled? */ |
1150 | if (!(slot->flags & SLOT_ENABLED)) | 1148 | if (!(slot->flags & SLOT_ENABLED)) |
1151 | goto err_exit; | 1149 | goto err_exit; |
1152 | 1150 | ||
1153 | list_for_each (l, &slot->funcs) { | 1151 | list_for_each_entry(func, &slot->funcs, sibling) { |
1154 | func = list_entry(l, struct acpiphp_func, sibling); | ||
1155 | |||
1156 | if (func->bridge) { | 1152 | if (func->bridge) { |
1157 | /* cleanup p2p bridges under this P2P bridge */ | 1153 | /* cleanup p2p bridges under this P2P bridge */ |
1158 | cleanup_p2p_bridge(func->bridge->handle, | 1154 | cleanup_p2p_bridge(func->bridge->handle, |
@@ -1160,35 +1156,28 @@ static int disable_device(struct acpiphp_slot *slot) | |||
1160 | func->bridge = NULL; | 1156 | func->bridge = NULL; |
1161 | } | 1157 | } |
1162 | 1158 | ||
1163 | if (func->pci_dev) { | 1159 | pdev = pci_get_slot(slot->bridge->pci_bus, |
1164 | pci_stop_bus_device(func->pci_dev); | 1160 | PCI_DEVFN(slot->device, func->function)); |
1165 | if (func->pci_dev->subordinate) { | 1161 | if (pdev) { |
1166 | disable_bridges(func->pci_dev->subordinate); | 1162 | pci_stop_bus_device(pdev); |
1167 | pci_disable_device(func->pci_dev); | 1163 | if (pdev->subordinate) { |
1164 | disable_bridges(pdev->subordinate); | ||
1165 | pci_disable_device(pdev); | ||
1168 | } | 1166 | } |
1167 | pci_remove_bus_device(pdev); | ||
1168 | pci_dev_put(pdev); | ||
1169 | } | 1169 | } |
1170 | } | 1170 | } |
1171 | 1171 | ||
1172 | list_for_each (l, &slot->funcs) { | 1172 | list_for_each_entry(func, &slot->funcs, sibling) { |
1173 | func = list_entry(l, struct acpiphp_func, sibling); | ||
1174 | |||
1175 | acpiphp_unconfigure_ioapics(func->handle); | 1173 | acpiphp_unconfigure_ioapics(func->handle); |
1176 | acpiphp_bus_trim(func->handle); | 1174 | acpiphp_bus_trim(func->handle); |
1177 | /* try to remove anyway. | ||
1178 | * acpiphp_bus_add might have been failed */ | ||
1179 | |||
1180 | if (!func->pci_dev) | ||
1181 | continue; | ||
1182 | |||
1183 | pci_remove_bus_device(func->pci_dev); | ||
1184 | pci_dev_put(func->pci_dev); | ||
1185 | func->pci_dev = NULL; | ||
1186 | } | 1175 | } |
1187 | 1176 | ||
1188 | slot->flags &= (~SLOT_ENABLED); | 1177 | slot->flags &= (~SLOT_ENABLED); |
1189 | 1178 | ||
1190 | err_exit: | 1179 | err_exit: |
1191 | return retval; | 1180 | return 0; |
1192 | } | 1181 | } |
1193 | 1182 | ||
1194 | 1183 | ||