diff options
Diffstat (limited to 'drivers/pci')
-rw-r--r-- | drivers/pci/hotplug/acpiphp.h | 13 | ||||
-rw-r--r-- | drivers/pci/hotplug/acpiphp_glue.c | 130 | ||||
-rw-r--r-- | drivers/pci/iov.c | 1 |
3 files changed, 17 insertions, 127 deletions
diff --git a/drivers/pci/hotplug/acpiphp.h b/drivers/pci/hotplug/acpiphp.h index b3ead7ad7b31..b70ac00a117e 100644 --- a/drivers/pci/hotplug/acpiphp.h +++ b/drivers/pci/hotplug/acpiphp.h | |||
@@ -79,7 +79,6 @@ struct acpiphp_bridge { | |||
79 | /* Ejectable PCI-to-PCI bridge (PCI bridge and PCI function) */ | 79 | /* Ejectable PCI-to-PCI bridge (PCI bridge and PCI function) */ |
80 | struct acpiphp_func *func; | 80 | struct acpiphp_func *func; |
81 | 81 | ||
82 | int type; | ||
83 | int nr_slots; | 82 | int nr_slots; |
84 | 83 | ||
85 | u32 flags; | 84 | u32 flags; |
@@ -146,10 +145,6 @@ struct acpiphp_attention_info | |||
146 | /* PCI bus bridge HID */ | 145 | /* PCI bus bridge HID */ |
147 | #define ACPI_PCI_HOST_HID "PNP0A03" | 146 | #define ACPI_PCI_HOST_HID "PNP0A03" |
148 | 147 | ||
149 | /* PCI BRIDGE type */ | ||
150 | #define BRIDGE_TYPE_HOST 0 | ||
151 | #define BRIDGE_TYPE_P2P 1 | ||
152 | |||
153 | /* ACPI _STA method value (ignore bit 4; battery present) */ | 148 | /* ACPI _STA method value (ignore bit 4; battery present) */ |
154 | #define ACPI_STA_PRESENT (0x00000001) | 149 | #define ACPI_STA_PRESENT (0x00000001) |
155 | #define ACPI_STA_ENABLED (0x00000002) | 150 | #define ACPI_STA_ENABLED (0x00000002) |
@@ -158,13 +153,7 @@ struct acpiphp_attention_info | |||
158 | #define ACPI_STA_ALL (0x0000000f) | 153 | #define ACPI_STA_ALL (0x0000000f) |
159 | 154 | ||
160 | /* bridge flags */ | 155 | /* bridge flags */ |
161 | #define BRIDGE_HAS_STA (0x00000001) | 156 | #define BRIDGE_HAS_EJ0 (0x00000001) |
162 | #define BRIDGE_HAS_EJ0 (0x00000002) | ||
163 | #define BRIDGE_HAS_HPP (0x00000004) | ||
164 | #define BRIDGE_HAS_PS0 (0x00000010) | ||
165 | #define BRIDGE_HAS_PS1 (0x00000020) | ||
166 | #define BRIDGE_HAS_PS2 (0x00000040) | ||
167 | #define BRIDGE_HAS_PS3 (0x00000080) | ||
168 | 157 | ||
169 | /* slot flags */ | 158 | /* slot flags */ |
170 | 159 | ||
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index bd784ff4a244..4681d2c9b1dd 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c | |||
@@ -325,8 +325,8 @@ static void init_bridge_misc(struct acpiphp_bridge *bridge) | |||
325 | return; | 325 | return; |
326 | } | 326 | } |
327 | 327 | ||
328 | /* install notify handler */ | 328 | /* install notify handler for P2P bridges */ |
329 | if (bridge->type != BRIDGE_TYPE_HOST) { | 329 | if (!pci_is_root_bus(bridge->pci_bus)) { |
330 | if ((bridge->flags & BRIDGE_HAS_EJ0) && bridge->func) { | 330 | if ((bridge->flags & BRIDGE_HAS_EJ0) && bridge->func) { |
331 | status = acpi_remove_notify_handler(bridge->func->handle, | 331 | status = acpi_remove_notify_handler(bridge->func->handle, |
332 | ACPI_SYSTEM_NOTIFY, | 332 | ACPI_SYSTEM_NOTIFY, |
@@ -369,27 +369,12 @@ static struct acpiphp_func *acpiphp_bridge_handle_to_function(acpi_handle handle | |||
369 | static inline void config_p2p_bridge_flags(struct acpiphp_bridge *bridge) | 369 | static inline void config_p2p_bridge_flags(struct acpiphp_bridge *bridge) |
370 | { | 370 | { |
371 | acpi_handle dummy_handle; | 371 | acpi_handle dummy_handle; |
372 | struct acpiphp_func *func; | ||
372 | 373 | ||
373 | if (ACPI_SUCCESS(acpi_get_handle(bridge->handle, | 374 | if (ACPI_SUCCESS(acpi_get_handle(bridge->handle, |
374 | "_STA", &dummy_handle))) | 375 | "_EJ0", &dummy_handle))) { |
375 | bridge->flags |= BRIDGE_HAS_STA; | ||
376 | |||
377 | if (ACPI_SUCCESS(acpi_get_handle(bridge->handle, | ||
378 | "_EJ0", &dummy_handle))) | ||
379 | bridge->flags |= BRIDGE_HAS_EJ0; | 376 | bridge->flags |= BRIDGE_HAS_EJ0; |
380 | 377 | ||
381 | if (ACPI_SUCCESS(acpi_get_handle(bridge->handle, | ||
382 | "_PS0", &dummy_handle))) | ||
383 | bridge->flags |= BRIDGE_HAS_PS0; | ||
384 | |||
385 | if (ACPI_SUCCESS(acpi_get_handle(bridge->handle, | ||
386 | "_PS3", &dummy_handle))) | ||
387 | bridge->flags |= BRIDGE_HAS_PS3; | ||
388 | |||
389 | /* is this ejectable p2p bridge? */ | ||
390 | if (bridge->flags & BRIDGE_HAS_EJ0) { | ||
391 | struct acpiphp_func *func; | ||
392 | |||
393 | dbg("found ejectable p2p bridge\n"); | 378 | dbg("found ejectable p2p bridge\n"); |
394 | 379 | ||
395 | /* make link between PCI bridge and PCI function */ | 380 | /* make link between PCI bridge and PCI function */ |
@@ -412,7 +397,6 @@ static void add_host_bridge(struct acpi_pci_root *root) | |||
412 | if (bridge == NULL) | 397 | if (bridge == NULL) |
413 | return; | 398 | return; |
414 | 399 | ||
415 | bridge->type = BRIDGE_TYPE_HOST; | ||
416 | bridge->handle = handle; | 400 | bridge->handle = handle; |
417 | 401 | ||
418 | bridge->pci_bus = root->bus; | 402 | bridge->pci_bus = root->bus; |
@@ -432,7 +416,6 @@ static void add_p2p_bridge(acpi_handle *handle) | |||
432 | return; | 416 | return; |
433 | } | 417 | } |
434 | 418 | ||
435 | bridge->type = BRIDGE_TYPE_P2P; | ||
436 | bridge->handle = handle; | 419 | bridge->handle = handle; |
437 | config_p2p_bridge_flags(bridge); | 420 | config_p2p_bridge_flags(bridge); |
438 | 421 | ||
@@ -543,7 +526,7 @@ static void cleanup_bridge(struct acpiphp_bridge *bridge) | |||
543 | acpi_status status; | 526 | acpi_status status; |
544 | acpi_handle handle = bridge->handle; | 527 | acpi_handle handle = bridge->handle; |
545 | 528 | ||
546 | if (bridge->type != BRIDGE_TYPE_HOST) { | 529 | if (!pci_is_root_bus(bridge->pci_bus)) { |
547 | status = acpi_remove_notify_handler(handle, | 530 | status = acpi_remove_notify_handler(handle, |
548 | ACPI_SYSTEM_NOTIFY, | 531 | ACPI_SYSTEM_NOTIFY, |
549 | handle_hotplug_event_bridge); | 532 | handle_hotplug_event_bridge); |
@@ -551,8 +534,7 @@ static void cleanup_bridge(struct acpiphp_bridge *bridge) | |||
551 | err("failed to remove notify handler\n"); | 534 | err("failed to remove notify handler\n"); |
552 | } | 535 | } |
553 | 536 | ||
554 | if ((bridge->type != BRIDGE_TYPE_HOST) && | 537 | if ((bridge->flags & BRIDGE_HAS_EJ0) && bridge->func) { |
555 | ((bridge->flags & BRIDGE_HAS_EJ0) && bridge->func)) { | ||
556 | status = acpi_install_notify_handler(bridge->func->handle, | 538 | status = acpi_install_notify_handler(bridge->func->handle, |
557 | ACPI_SYSTEM_NOTIFY, | 539 | ACPI_SYSTEM_NOTIFY, |
558 | handle_hotplug_event_func, | 540 | handle_hotplug_event_func, |
@@ -839,6 +821,9 @@ static int __ref enable_device(struct acpiphp_slot *slot) | |||
839 | if (slot->flags & SLOT_ENABLED) | 821 | if (slot->flags & SLOT_ENABLED) |
840 | goto err_exit; | 822 | goto err_exit; |
841 | 823 | ||
824 | list_for_each_entry(func, &slot->funcs, sibling) | ||
825 | acpiphp_bus_add(func); | ||
826 | |||
842 | num = pci_scan_slot(bus, PCI_DEVFN(slot->device, 0)); | 827 | num = pci_scan_slot(bus, PCI_DEVFN(slot->device, 0)); |
843 | if (num == 0) { | 828 | if (num == 0) { |
844 | /* Maybe only part of funcs are added. */ | 829 | /* Maybe only part of funcs are added. */ |
@@ -862,9 +847,6 @@ static int __ref enable_device(struct acpiphp_slot *slot) | |||
862 | } | 847 | } |
863 | } | 848 | } |
864 | 849 | ||
865 | list_for_each_entry(func, &slot->funcs, sibling) | ||
866 | acpiphp_bus_add(func); | ||
867 | |||
868 | pci_bus_assign_resources(bus); | 850 | pci_bus_assign_resources(bus); |
869 | acpiphp_sanitize_bus(bus); | 851 | acpiphp_sanitize_bus(bus); |
870 | acpiphp_set_hpp_values(bus); | 852 | acpiphp_set_hpp_values(bus); |
@@ -1122,64 +1104,11 @@ static void acpiphp_sanitize_bus(struct pci_bus *bus) | |||
1122 | } | 1104 | } |
1123 | } | 1105 | } |
1124 | 1106 | ||
1125 | /* Program resources in newly inserted bridge */ | ||
1126 | static int acpiphp_configure_p2p_bridge(acpi_handle handle) | ||
1127 | { | ||
1128 | struct pci_dev *pdev = acpi_get_pci_dev(handle); | ||
1129 | struct pci_bus *bus = pdev->subordinate; | ||
1130 | |||
1131 | pci_dev_put(pdev); | ||
1132 | |||
1133 | pci_bus_size_bridges(bus); | ||
1134 | pci_bus_assign_resources(bus); | ||
1135 | acpiphp_sanitize_bus(bus); | ||
1136 | acpiphp_set_hpp_values(bus); | ||
1137 | pci_enable_bridges(bus); | ||
1138 | return 0; | ||
1139 | } | ||
1140 | |||
1141 | static void handle_p2p_bridge_insertion(acpi_handle handle, u32 type) | ||
1142 | { | ||
1143 | struct acpi_device *device; | ||
1144 | |||
1145 | if ((type != ACPI_NOTIFY_BUS_CHECK) && | ||
1146 | (type != ACPI_NOTIFY_DEVICE_CHECK)) { | ||
1147 | err("unexpected notification type %d\n", type); | ||
1148 | return; | ||
1149 | } | ||
1150 | |||
1151 | if (acpi_bus_scan(handle)) { | ||
1152 | err("cannot add bridge to acpi list\n"); | ||
1153 | return; | ||
1154 | } | ||
1155 | if (acpi_bus_get_device(handle, &device)) { | ||
1156 | err("ACPI device object missing\n"); | ||
1157 | return; | ||
1158 | } | ||
1159 | if (!acpiphp_configure_p2p_bridge(handle)) | ||
1160 | add_p2p_bridge(handle); | ||
1161 | else | ||
1162 | err("cannot configure and start bridge\n"); | ||
1163 | |||
1164 | } | ||
1165 | |||
1166 | /* | 1107 | /* |
1167 | * ACPI event handlers | 1108 | * ACPI event handlers |
1168 | */ | 1109 | */ |
1169 | 1110 | ||
1170 | static acpi_status | 1111 | static acpi_status |
1171 | count_sub_bridges(acpi_handle handle, u32 lvl, void *context, void **rv) | ||
1172 | { | ||
1173 | int *count = (int *)context; | ||
1174 | struct acpiphp_bridge *bridge; | ||
1175 | |||
1176 | bridge = acpiphp_handle_to_bridge(handle); | ||
1177 | if (bridge) | ||
1178 | (*count)++; | ||
1179 | return AE_OK ; | ||
1180 | } | ||
1181 | |||
1182 | static acpi_status | ||
1183 | check_sub_bridges(acpi_handle handle, u32 lvl, void *context, void **rv) | 1112 | check_sub_bridges(acpi_handle handle, u32 lvl, void *context, void **rv) |
1184 | { | 1113 | { |
1185 | struct acpiphp_bridge *bridge; | 1114 | struct acpiphp_bridge *bridge; |
@@ -1203,8 +1132,6 @@ static void _handle_hotplug_event_bridge(struct work_struct *work) | |||
1203 | char objname[64]; | 1132 | char objname[64]; |
1204 | struct acpi_buffer buffer = { .length = sizeof(objname), | 1133 | struct acpi_buffer buffer = { .length = sizeof(objname), |
1205 | .pointer = objname }; | 1134 | .pointer = objname }; |
1206 | struct acpi_device *device; | ||
1207 | int num_sub_bridges = 0; | ||
1208 | struct acpi_hp_work *hp_work; | 1135 | struct acpi_hp_work *hp_work; |
1209 | acpi_handle handle; | 1136 | acpi_handle handle; |
1210 | u32 type; | 1137 | u32 type; |
@@ -1212,23 +1139,7 @@ static void _handle_hotplug_event_bridge(struct work_struct *work) | |||
1212 | hp_work = container_of(work, struct acpi_hp_work, work); | 1139 | hp_work = container_of(work, struct acpi_hp_work, work); |
1213 | handle = hp_work->handle; | 1140 | handle = hp_work->handle; |
1214 | type = hp_work->type; | 1141 | type = hp_work->type; |
1215 | 1142 | bridge = (struct acpiphp_bridge *)hp_work->context; | |
1216 | if (acpi_bus_get_device(handle, &device)) { | ||
1217 | /* This bridge must have just been physically inserted */ | ||
1218 | handle_p2p_bridge_insertion(handle, type); | ||
1219 | goto out; | ||
1220 | } | ||
1221 | |||
1222 | bridge = acpiphp_handle_to_bridge(handle); | ||
1223 | if (type == ACPI_NOTIFY_BUS_CHECK) { | ||
1224 | acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, ACPI_UINT32_MAX, | ||
1225 | count_sub_bridges, NULL, &num_sub_bridges, NULL); | ||
1226 | } | ||
1227 | |||
1228 | if (!bridge && !num_sub_bridges) { | ||
1229 | err("cannot get bridge info\n"); | ||
1230 | goto out; | ||
1231 | } | ||
1232 | 1143 | ||
1233 | acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer); | 1144 | acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer); |
1234 | 1145 | ||
@@ -1236,14 +1147,10 @@ static void _handle_hotplug_event_bridge(struct work_struct *work) | |||
1236 | case ACPI_NOTIFY_BUS_CHECK: | 1147 | case ACPI_NOTIFY_BUS_CHECK: |
1237 | /* bus re-enumerate */ | 1148 | /* bus re-enumerate */ |
1238 | dbg("%s: Bus check notify on %s\n", __func__, objname); | 1149 | dbg("%s: Bus check notify on %s\n", __func__, objname); |
1239 | if (bridge) { | 1150 | dbg("%s: re-enumerating slots under %s\n", __func__, objname); |
1240 | dbg("%s: re-enumerating slots under %s\n", | 1151 | acpiphp_check_bridge(bridge); |
1241 | __func__, objname); | 1152 | acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, |
1242 | acpiphp_check_bridge(bridge); | 1153 | ACPI_UINT32_MAX, check_sub_bridges, NULL, NULL, NULL); |
1243 | } | ||
1244 | if (num_sub_bridges) | ||
1245 | acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, | ||
1246 | ACPI_UINT32_MAX, check_sub_bridges, NULL, NULL, NULL); | ||
1247 | break; | 1154 | break; |
1248 | 1155 | ||
1249 | case ACPI_NOTIFY_DEVICE_CHECK: | 1156 | case ACPI_NOTIFY_DEVICE_CHECK: |
@@ -1260,8 +1167,7 @@ static void _handle_hotplug_event_bridge(struct work_struct *work) | |||
1260 | case ACPI_NOTIFY_EJECT_REQUEST: | 1167 | case ACPI_NOTIFY_EJECT_REQUEST: |
1261 | /* request device eject */ | 1168 | /* request device eject */ |
1262 | dbg("%s: Device eject notify on %s\n", __func__, objname); | 1169 | dbg("%s: Device eject notify on %s\n", __func__, objname); |
1263 | if ((bridge->type != BRIDGE_TYPE_HOST) && | 1170 | if ((bridge->flags & BRIDGE_HAS_EJ0) && bridge->func) { |
1264 | (bridge->flags & BRIDGE_HAS_EJ0)) { | ||
1265 | struct acpiphp_slot *slot; | 1171 | struct acpiphp_slot *slot; |
1266 | slot = bridge->func->slot; | 1172 | slot = bridge->func->slot; |
1267 | if (!acpiphp_disable_slot(slot)) | 1173 | if (!acpiphp_disable_slot(slot)) |
@@ -1289,7 +1195,6 @@ static void _handle_hotplug_event_bridge(struct work_struct *work) | |||
1289 | break; | 1195 | break; |
1290 | } | 1196 | } |
1291 | 1197 | ||
1292 | out: | ||
1293 | kfree(hp_work); /* allocated in handle_hotplug_event_bridge */ | 1198 | kfree(hp_work); /* allocated in handle_hotplug_event_bridge */ |
1294 | } | 1199 | } |
1295 | 1200 | ||
@@ -1324,17 +1229,14 @@ static void _handle_hotplug_event_func(struct work_struct *work) | |||
1324 | struct acpi_hp_work *hp_work; | 1229 | struct acpi_hp_work *hp_work; |
1325 | acpi_handle handle; | 1230 | acpi_handle handle; |
1326 | u32 type; | 1231 | u32 type; |
1327 | void *context; | ||
1328 | 1232 | ||
1329 | hp_work = container_of(work, struct acpi_hp_work, work); | 1233 | hp_work = container_of(work, struct acpi_hp_work, work); |
1330 | handle = hp_work->handle; | 1234 | handle = hp_work->handle; |
1331 | type = hp_work->type; | 1235 | type = hp_work->type; |
1332 | context = hp_work->context; | 1236 | func = (struct acpiphp_func *)hp_work->context; |
1333 | 1237 | ||
1334 | acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer); | 1238 | acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer); |
1335 | 1239 | ||
1336 | func = (struct acpiphp_func *)context; | ||
1337 | |||
1338 | switch (type) { | 1240 | switch (type) { |
1339 | case ACPI_NOTIFY_BUS_CHECK: | 1241 | case ACPI_NOTIFY_BUS_CHECK: |
1340 | /* bus re-enumerate */ | 1242 | /* bus re-enumerate */ |
diff --git a/drivers/pci/iov.c b/drivers/pci/iov.c index f8720afe0537..4ea7139db1be 100644 --- a/drivers/pci/iov.c +++ b/drivers/pci/iov.c | |||
@@ -33,7 +33,6 @@ static inline u8 virtfn_devfn(struct pci_dev *dev, int id) | |||
33 | 33 | ||
34 | static struct pci_bus *virtfn_add_bus(struct pci_bus *bus, int busnr) | 34 | static struct pci_bus *virtfn_add_bus(struct pci_bus *bus, int busnr) |
35 | { | 35 | { |
36 | int rc; | ||
37 | struct pci_bus *child; | 36 | struct pci_bus *child; |
38 | 37 | ||
39 | if (bus->number == busnr) | 38 | if (bus->number == busnr) |