diff options
Diffstat (limited to 'drivers/pci/hotplug/acpiphp_glue.c')
-rw-r--r-- | drivers/pci/hotplug/acpiphp_glue.c | 187 |
1 files changed, 29 insertions, 158 deletions
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index 0cb0f830a993..58d25a163a8b 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c | |||
@@ -59,7 +59,7 @@ static DEFINE_SPINLOCK(ioapic_list_lock); | |||
59 | 59 | ||
60 | static void handle_hotplug_event_bridge (acpi_handle, u32, void *); | 60 | static void handle_hotplug_event_bridge (acpi_handle, u32, void *); |
61 | static void acpiphp_sanitize_bus(struct pci_bus *bus); | 61 | static void acpiphp_sanitize_bus(struct pci_bus *bus); |
62 | static void acpiphp_set_hpp_values(acpi_handle handle, struct pci_bus *bus); | 62 | static void acpiphp_set_hpp_values(struct pci_bus *bus); |
63 | static void handle_hotplug_event_func(acpi_handle handle, u32 type, void *context); | 63 | static void handle_hotplug_event_func(acpi_handle handle, u32 type, void *context); |
64 | 64 | ||
65 | /* callback routine to check for the existence of a pci dock device */ | 65 | /* callback routine to check for the existence of a pci dock device */ |
@@ -261,51 +261,21 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) | |||
261 | 261 | ||
262 | 262 | ||
263 | /* see if it's worth looking at this bridge */ | 263 | /* see if it's worth looking at this bridge */ |
264 | static int detect_ejectable_slots(struct pci_bus *pbus) | 264 | static int detect_ejectable_slots(acpi_handle handle) |
265 | { | 265 | { |
266 | int found = acpi_pci_detect_ejectable(pbus); | 266 | int found = acpi_pci_detect_ejectable(handle); |
267 | if (!found) { | 267 | if (!found) { |
268 | acpi_handle bridge_handle = acpi_pci_get_bridge_handle(pbus); | 268 | acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1, |
269 | if (!bridge_handle) | ||
270 | return 0; | ||
271 | acpi_walk_namespace(ACPI_TYPE_DEVICE, bridge_handle, (u32)1, | ||
272 | is_pci_dock_device, (void *)&found, NULL); | 269 | is_pci_dock_device, (void *)&found, NULL); |
273 | } | 270 | } |
274 | return found; | 271 | return found; |
275 | } | 272 | } |
276 | 273 | ||
277 | |||
278 | /* decode ACPI 2.0 _HPP hot plug parameters */ | ||
279 | static void decode_hpp(struct acpiphp_bridge *bridge) | ||
280 | { | ||
281 | acpi_status status; | ||
282 | |||
283 | status = acpi_get_hp_params_from_firmware(bridge->pci_bus, &bridge->hpp); | ||
284 | if (ACPI_FAILURE(status) || | ||
285 | !bridge->hpp.t0 || (bridge->hpp.t0->revision > 1)) { | ||
286 | /* use default numbers */ | ||
287 | printk(KERN_WARNING | ||
288 | "%s: Could not get hotplug parameters. Use defaults\n", | ||
289 | __func__); | ||
290 | bridge->hpp.t0 = &bridge->hpp.type0_data; | ||
291 | bridge->hpp.t0->revision = 0; | ||
292 | bridge->hpp.t0->cache_line_size = 0x10; | ||
293 | bridge->hpp.t0->latency_timer = 0x40; | ||
294 | bridge->hpp.t0->enable_serr = 0; | ||
295 | bridge->hpp.t0->enable_perr = 0; | ||
296 | } | ||
297 | } | ||
298 | |||
299 | |||
300 | |||
301 | /* initialize miscellaneous stuff for both root and PCI-to-PCI bridge */ | 274 | /* initialize miscellaneous stuff for both root and PCI-to-PCI bridge */ |
302 | static void init_bridge_misc(struct acpiphp_bridge *bridge) | 275 | static void init_bridge_misc(struct acpiphp_bridge *bridge) |
303 | { | 276 | { |
304 | acpi_status status; | 277 | acpi_status status; |
305 | 278 | ||
306 | /* decode ACPI 2.0 _HPP (hot plug parameters) */ | ||
307 | decode_hpp(bridge); | ||
308 | |||
309 | /* must be added to the list prior to calling register_slot */ | 279 | /* must be added to the list prior to calling register_slot */ |
310 | list_add(&bridge->list, &bridge_list); | 280 | list_add(&bridge->list, &bridge_list); |
311 | 281 | ||
@@ -399,9 +369,10 @@ static inline void config_p2p_bridge_flags(struct acpiphp_bridge *bridge) | |||
399 | 369 | ||
400 | 370 | ||
401 | /* allocate and initialize host bridge data structure */ | 371 | /* allocate and initialize host bridge data structure */ |
402 | static void add_host_bridge(acpi_handle *handle, struct pci_bus *pci_bus) | 372 | static void add_host_bridge(acpi_handle *handle) |
403 | { | 373 | { |
404 | struct acpiphp_bridge *bridge; | 374 | struct acpiphp_bridge *bridge; |
375 | struct acpi_pci_root *root = acpi_pci_find_root(handle); | ||
405 | 376 | ||
406 | bridge = kzalloc(sizeof(struct acpiphp_bridge), GFP_KERNEL); | 377 | bridge = kzalloc(sizeof(struct acpiphp_bridge), GFP_KERNEL); |
407 | if (bridge == NULL) | 378 | if (bridge == NULL) |
@@ -410,7 +381,7 @@ static void add_host_bridge(acpi_handle *handle, struct pci_bus *pci_bus) | |||
410 | bridge->type = BRIDGE_TYPE_HOST; | 381 | bridge->type = BRIDGE_TYPE_HOST; |
411 | bridge->handle = handle; | 382 | bridge->handle = handle; |
412 | 383 | ||
413 | bridge->pci_bus = pci_bus; | 384 | bridge->pci_bus = root->bus; |
414 | 385 | ||
415 | spin_lock_init(&bridge->res_lock); | 386 | spin_lock_init(&bridge->res_lock); |
416 | 387 | ||
@@ -419,7 +390,7 @@ static void add_host_bridge(acpi_handle *handle, struct pci_bus *pci_bus) | |||
419 | 390 | ||
420 | 391 | ||
421 | /* allocate and initialize PCI-to-PCI bridge data structure */ | 392 | /* allocate and initialize PCI-to-PCI bridge data structure */ |
422 | static void add_p2p_bridge(acpi_handle *handle, struct pci_dev *pci_dev) | 393 | static void add_p2p_bridge(acpi_handle *handle) |
423 | { | 394 | { |
424 | struct acpiphp_bridge *bridge; | 395 | struct acpiphp_bridge *bridge; |
425 | 396 | ||
@@ -433,8 +404,8 @@ static void add_p2p_bridge(acpi_handle *handle, struct pci_dev *pci_dev) | |||
433 | bridge->handle = handle; | 404 | bridge->handle = handle; |
434 | config_p2p_bridge_flags(bridge); | 405 | config_p2p_bridge_flags(bridge); |
435 | 406 | ||
436 | bridge->pci_dev = pci_dev_get(pci_dev); | 407 | bridge->pci_dev = acpi_get_pci_dev(handle); |
437 | bridge->pci_bus = pci_dev->subordinate; | 408 | bridge->pci_bus = bridge->pci_dev->subordinate; |
438 | if (!bridge->pci_bus) { | 409 | if (!bridge->pci_bus) { |
439 | err("This is not a PCI-to-PCI bridge!\n"); | 410 | err("This is not a PCI-to-PCI bridge!\n"); |
440 | goto err; | 411 | goto err; |
@@ -451,7 +422,7 @@ static void add_p2p_bridge(acpi_handle *handle, struct pci_dev *pci_dev) | |||
451 | init_bridge_misc(bridge); | 422 | init_bridge_misc(bridge); |
452 | return; | 423 | return; |
453 | err: | 424 | err: |
454 | pci_dev_put(pci_dev); | 425 | pci_dev_put(bridge->pci_dev); |
455 | kfree(bridge); | 426 | kfree(bridge); |
456 | return; | 427 | return; |
457 | } | 428 | } |
@@ -462,39 +433,21 @@ static acpi_status | |||
462 | find_p2p_bridge(acpi_handle handle, u32 lvl, void *context, void **rv) | 433 | find_p2p_bridge(acpi_handle handle, u32 lvl, void *context, void **rv) |
463 | { | 434 | { |
464 | acpi_status status; | 435 | acpi_status status; |
465 | acpi_handle dummy_handle; | ||
466 | unsigned long long tmp; | ||
467 | int device, function; | ||
468 | struct pci_dev *dev; | 436 | struct pci_dev *dev; |
469 | struct pci_bus *pci_bus = context; | ||
470 | |||
471 | status = acpi_get_handle(handle, "_ADR", &dummy_handle); | ||
472 | if (ACPI_FAILURE(status)) | ||
473 | return AE_OK; /* continue */ | ||
474 | |||
475 | status = acpi_evaluate_integer(handle, "_ADR", NULL, &tmp); | ||
476 | if (ACPI_FAILURE(status)) { | ||
477 | dbg("%s: _ADR evaluation failure\n", __func__); | ||
478 | return AE_OK; | ||
479 | } | ||
480 | |||
481 | device = (tmp >> 16) & 0xffff; | ||
482 | function = tmp & 0xffff; | ||
483 | |||
484 | dev = pci_get_slot(pci_bus, PCI_DEVFN(device, function)); | ||
485 | 437 | ||
438 | dev = acpi_get_pci_dev(handle); | ||
486 | if (!dev || !dev->subordinate) | 439 | if (!dev || !dev->subordinate) |
487 | goto out; | 440 | goto out; |
488 | 441 | ||
489 | /* check if this bridge has ejectable slots */ | 442 | /* check if this bridge has ejectable slots */ |
490 | if ((detect_ejectable_slots(dev->subordinate) > 0)) { | 443 | if ((detect_ejectable_slots(handle) > 0)) { |
491 | dbg("found PCI-to-PCI bridge at PCI %s\n", pci_name(dev)); | 444 | dbg("found PCI-to-PCI bridge at PCI %s\n", pci_name(dev)); |
492 | add_p2p_bridge(handle, dev); | 445 | add_p2p_bridge(handle); |
493 | } | 446 | } |
494 | 447 | ||
495 | /* search P2P bridges under this p2p bridge */ | 448 | /* search P2P bridges under this p2p bridge */ |
496 | status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1, | 449 | status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1, |
497 | find_p2p_bridge, dev->subordinate, NULL); | 450 | find_p2p_bridge, NULL, NULL); |
498 | if (ACPI_FAILURE(status)) | 451 | if (ACPI_FAILURE(status)) |
499 | warn("find_p2p_bridge failed (error code = 0x%x)\n", status); | 452 | warn("find_p2p_bridge failed (error code = 0x%x)\n", status); |
500 | 453 | ||
@@ -509,9 +462,7 @@ static int add_bridge(acpi_handle handle) | |||
509 | { | 462 | { |
510 | acpi_status status; | 463 | acpi_status status; |
511 | unsigned long long tmp; | 464 | unsigned long long tmp; |
512 | int seg, bus; | ||
513 | acpi_handle dummy_handle; | 465 | acpi_handle dummy_handle; |
514 | struct pci_bus *pci_bus; | ||
515 | 466 | ||
516 | /* if the bridge doesn't have _STA, we assume it is always there */ | 467 | /* if the bridge doesn't have _STA, we assume it is always there */ |
517 | status = acpi_get_handle(handle, "_STA", &dummy_handle); | 468 | status = acpi_get_handle(handle, "_STA", &dummy_handle); |
@@ -526,36 +477,15 @@ static int add_bridge(acpi_handle handle) | |||
526 | return 0; | 477 | return 0; |
527 | } | 478 | } |
528 | 479 | ||
529 | /* get PCI segment number */ | ||
530 | status = acpi_evaluate_integer(handle, "_SEG", NULL, &tmp); | ||
531 | |||
532 | seg = ACPI_SUCCESS(status) ? tmp : 0; | ||
533 | |||
534 | /* get PCI bus number */ | ||
535 | status = acpi_evaluate_integer(handle, "_BBN", NULL, &tmp); | ||
536 | |||
537 | if (ACPI_SUCCESS(status)) { | ||
538 | bus = tmp; | ||
539 | } else { | ||
540 | warn("can't get bus number, assuming 0\n"); | ||
541 | bus = 0; | ||
542 | } | ||
543 | |||
544 | pci_bus = pci_find_bus(seg, bus); | ||
545 | if (!pci_bus) { | ||
546 | err("Can't find bus %04x:%02x\n", seg, bus); | ||
547 | return 0; | ||
548 | } | ||
549 | |||
550 | /* check if this bridge has ejectable slots */ | 480 | /* check if this bridge has ejectable slots */ |
551 | if (detect_ejectable_slots(pci_bus) > 0) { | 481 | if (detect_ejectable_slots(handle) > 0) { |
552 | dbg("found PCI host-bus bridge with hot-pluggable slots\n"); | 482 | dbg("found PCI host-bus bridge with hot-pluggable slots\n"); |
553 | add_host_bridge(handle, pci_bus); | 483 | add_host_bridge(handle); |
554 | } | 484 | } |
555 | 485 | ||
556 | /* search P2P bridges under this host bridge */ | 486 | /* search P2P bridges under this host bridge */ |
557 | status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1, | 487 | status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1, |
558 | find_p2p_bridge, pci_bus, NULL); | 488 | find_p2p_bridge, NULL, NULL); |
559 | 489 | ||
560 | if (ACPI_FAILURE(status)) | 490 | if (ACPI_FAILURE(status)) |
561 | warn("find_p2p_bridge failed (error code = 0x%x)\n", status); | 491 | warn("find_p2p_bridge failed (error code = 0x%x)\n", status); |
@@ -1083,7 +1013,7 @@ static int __ref enable_device(struct acpiphp_slot *slot) | |||
1083 | 1013 | ||
1084 | pci_bus_assign_resources(bus); | 1014 | pci_bus_assign_resources(bus); |
1085 | acpiphp_sanitize_bus(bus); | 1015 | acpiphp_sanitize_bus(bus); |
1086 | acpiphp_set_hpp_values(slot->bridge->handle, bus); | 1016 | acpiphp_set_hpp_values(bus); |
1087 | list_for_each_entry(func, &slot->funcs, sibling) | 1017 | list_for_each_entry(func, &slot->funcs, sibling) |
1088 | acpiphp_configure_ioapics(func->handle); | 1018 | acpiphp_configure_ioapics(func->handle); |
1089 | pci_enable_bridges(bus); | 1019 | pci_enable_bridges(bus); |
@@ -1294,70 +1224,12 @@ static int acpiphp_check_bridge(struct acpiphp_bridge *bridge) | |||
1294 | return retval; | 1224 | return retval; |
1295 | } | 1225 | } |
1296 | 1226 | ||
1297 | static void program_hpp(struct pci_dev *dev, struct acpiphp_bridge *bridge) | 1227 | static void acpiphp_set_hpp_values(struct pci_bus *bus) |
1298 | { | 1228 | { |
1299 | u16 pci_cmd, pci_bctl; | ||
1300 | struct pci_dev *cdev; | ||
1301 | |||
1302 | /* Program hpp values for this device */ | ||
1303 | if (!(dev->hdr_type == PCI_HEADER_TYPE_NORMAL || | ||
1304 | (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE && | ||
1305 | (dev->class >> 8) == PCI_CLASS_BRIDGE_PCI))) | ||
1306 | return; | ||
1307 | |||
1308 | if ((dev->class >> 8) == PCI_CLASS_BRIDGE_HOST) | ||
1309 | return; | ||
1310 | |||
1311 | pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, | ||
1312 | bridge->hpp.t0->cache_line_size); | ||
1313 | pci_write_config_byte(dev, PCI_LATENCY_TIMER, | ||
1314 | bridge->hpp.t0->latency_timer); | ||
1315 | pci_read_config_word(dev, PCI_COMMAND, &pci_cmd); | ||
1316 | if (bridge->hpp.t0->enable_serr) | ||
1317 | pci_cmd |= PCI_COMMAND_SERR; | ||
1318 | else | ||
1319 | pci_cmd &= ~PCI_COMMAND_SERR; | ||
1320 | if (bridge->hpp.t0->enable_perr) | ||
1321 | pci_cmd |= PCI_COMMAND_PARITY; | ||
1322 | else | ||
1323 | pci_cmd &= ~PCI_COMMAND_PARITY; | ||
1324 | pci_write_config_word(dev, PCI_COMMAND, pci_cmd); | ||
1325 | |||
1326 | /* Program bridge control value and child devices */ | ||
1327 | if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) { | ||
1328 | pci_write_config_byte(dev, PCI_SEC_LATENCY_TIMER, | ||
1329 | bridge->hpp.t0->latency_timer); | ||
1330 | pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &pci_bctl); | ||
1331 | if (bridge->hpp.t0->enable_serr) | ||
1332 | pci_bctl |= PCI_BRIDGE_CTL_SERR; | ||
1333 | else | ||
1334 | pci_bctl &= ~PCI_BRIDGE_CTL_SERR; | ||
1335 | if (bridge->hpp.t0->enable_perr) | ||
1336 | pci_bctl |= PCI_BRIDGE_CTL_PARITY; | ||
1337 | else | ||
1338 | pci_bctl &= ~PCI_BRIDGE_CTL_PARITY; | ||
1339 | pci_write_config_word(dev, PCI_BRIDGE_CONTROL, pci_bctl); | ||
1340 | if (dev->subordinate) { | ||
1341 | list_for_each_entry(cdev, &dev->subordinate->devices, | ||
1342 | bus_list) | ||
1343 | program_hpp(cdev, bridge); | ||
1344 | } | ||
1345 | } | ||
1346 | } | ||
1347 | |||
1348 | static void acpiphp_set_hpp_values(acpi_handle handle, struct pci_bus *bus) | ||
1349 | { | ||
1350 | struct acpiphp_bridge bridge; | ||
1351 | struct pci_dev *dev; | 1229 | struct pci_dev *dev; |
1352 | 1230 | ||
1353 | memset(&bridge, 0, sizeof(bridge)); | ||
1354 | bridge.handle = handle; | ||
1355 | bridge.pci_bus = bus; | ||
1356 | bridge.pci_dev = bus->self; | ||
1357 | decode_hpp(&bridge); | ||
1358 | list_for_each_entry(dev, &bus->devices, bus_list) | 1231 | list_for_each_entry(dev, &bus->devices, bus_list) |
1359 | program_hpp(dev, &bridge); | 1232 | pci_configure_slot(dev); |
1360 | |||
1361 | } | 1233 | } |
1362 | 1234 | ||
1363 | /* | 1235 | /* |
@@ -1387,24 +1259,23 @@ static void acpiphp_sanitize_bus(struct pci_bus *bus) | |||
1387 | /* Program resources in newly inserted bridge */ | 1259 | /* Program resources in newly inserted bridge */ |
1388 | static int acpiphp_configure_bridge (acpi_handle handle) | 1260 | static int acpiphp_configure_bridge (acpi_handle handle) |
1389 | { | 1261 | { |
1390 | struct pci_dev *dev; | ||
1391 | struct pci_bus *bus; | 1262 | struct pci_bus *bus; |
1392 | 1263 | ||
1393 | dev = acpi_get_pci_dev(handle); | 1264 | if (acpi_is_root_bridge(handle)) { |
1394 | if (!dev) { | 1265 | struct acpi_pci_root *root = acpi_pci_find_root(handle); |
1395 | err("cannot get PCI domain and bus number for bridge\n"); | 1266 | bus = root->bus; |
1396 | return -EINVAL; | 1267 | } else { |
1268 | struct pci_dev *pdev = acpi_get_pci_dev(handle); | ||
1269 | bus = pdev->subordinate; | ||
1270 | pci_dev_put(pdev); | ||
1397 | } | 1271 | } |
1398 | 1272 | ||
1399 | bus = dev->bus; | ||
1400 | |||
1401 | pci_bus_size_bridges(bus); | 1273 | pci_bus_size_bridges(bus); |
1402 | pci_bus_assign_resources(bus); | 1274 | pci_bus_assign_resources(bus); |
1403 | acpiphp_sanitize_bus(bus); | 1275 | acpiphp_sanitize_bus(bus); |
1404 | acpiphp_set_hpp_values(handle, bus); | 1276 | acpiphp_set_hpp_values(bus); |
1405 | pci_enable_bridges(bus); | 1277 | pci_enable_bridges(bus); |
1406 | acpiphp_configure_ioapics(handle); | 1278 | acpiphp_configure_ioapics(handle); |
1407 | pci_dev_put(dev); | ||
1408 | return 0; | 1279 | return 0; |
1409 | } | 1280 | } |
1410 | 1281 | ||