diff options
Diffstat (limited to 'drivers/pci/hotplug')
| -rw-r--r-- | drivers/pci/hotplug/Makefile | 2 | ||||
| -rw-r--r-- | drivers/pci/hotplug/acpi_pcihp.c | 117 | ||||
| -rw-r--r-- | drivers/pci/hotplug/acpiphp.h | 3 | ||||
| -rw-r--r-- | drivers/pci/hotplug/acpiphp_glue.c | 187 | ||||
| -rw-r--r-- | drivers/pci/hotplug/pci_hotplug_core.c | 3 | ||||
| -rw-r--r-- | drivers/pci/hotplug/pciehp.h | 9 | ||||
| -rw-r--r-- | drivers/pci/hotplug/pciehp_acpi.c | 7 | ||||
| -rw-r--r-- | drivers/pci/hotplug/pciehp_ctrl.c | 5 | ||||
| -rw-r--r-- | drivers/pci/hotplug/pciehp_hpc.c | 10 | ||||
| -rw-r--r-- | drivers/pci/hotplug/pciehp_pci.c | 137 | ||||
| -rw-r--r-- | drivers/pci/hotplug/pcihp_slot.c | 187 | ||||
| -rw-r--r-- | drivers/pci/hotplug/shpchp.h | 9 | ||||
| -rw-r--r-- | drivers/pci/hotplug/shpchp_pci.c | 62 |
13 files changed, 271 insertions, 467 deletions
diff --git a/drivers/pci/hotplug/Makefile b/drivers/pci/hotplug/Makefile index 2aa117c8cd87..3625b094bf7e 100644 --- a/drivers/pci/hotplug/Makefile +++ b/drivers/pci/hotplug/Makefile | |||
| @@ -22,7 +22,7 @@ obj-$(CONFIG_HOTPLUG_PCI_SGI) += sgi_hotplug.o | |||
| 22 | # Link this last so it doesn't claim devices that have a real hotplug driver | 22 | # Link this last so it doesn't claim devices that have a real hotplug driver |
| 23 | obj-$(CONFIG_HOTPLUG_PCI_FAKE) += fakephp.o | 23 | obj-$(CONFIG_HOTPLUG_PCI_FAKE) += fakephp.o |
| 24 | 24 | ||
| 25 | pci_hotplug-objs := pci_hotplug_core.o | 25 | pci_hotplug-objs := pci_hotplug_core.o pcihp_slot.o |
| 26 | 26 | ||
| 27 | ifdef CONFIG_HOTPLUG_PCI_CPCI | 27 | ifdef CONFIG_HOTPLUG_PCI_CPCI |
| 28 | pci_hotplug-objs += cpci_hotplug_core.o \ | 28 | pci_hotplug-objs += cpci_hotplug_core.o \ |
diff --git a/drivers/pci/hotplug/acpi_pcihp.c b/drivers/pci/hotplug/acpi_pcihp.c index eb159587d0bf..a73028ec52e5 100644 --- a/drivers/pci/hotplug/acpi_pcihp.c +++ b/drivers/pci/hotplug/acpi_pcihp.c | |||
| @@ -41,7 +41,6 @@ | |||
| 41 | #define warn(format, arg...) printk(KERN_WARNING "%s: " format , MY_NAME , ## arg) | 41 | #define warn(format, arg...) printk(KERN_WARNING "%s: " format , MY_NAME , ## arg) |
| 42 | 42 | ||
| 43 | #define METHOD_NAME__SUN "_SUN" | 43 | #define METHOD_NAME__SUN "_SUN" |
| 44 | #define METHOD_NAME__HPP "_HPP" | ||
| 45 | #define METHOD_NAME_OSHP "OSHP" | 44 | #define METHOD_NAME_OSHP "OSHP" |
| 46 | 45 | ||
| 47 | static int debug_acpi; | 46 | static int debug_acpi; |
| @@ -215,80 +214,41 @@ acpi_run_hpx(acpi_handle handle, struct hotplug_params *hpx) | |||
| 215 | static acpi_status | 214 | static acpi_status |
| 216 | acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp) | 215 | acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp) |
| 217 | { | 216 | { |
| 218 | acpi_status status; | 217 | acpi_status status; |
| 219 | u8 nui[4]; | 218 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; |
| 220 | struct acpi_buffer ret_buf = { 0, NULL}; | 219 | union acpi_object *package, *fields; |
| 221 | struct acpi_buffer string = { ACPI_ALLOCATE_BUFFER, NULL }; | 220 | int i; |
| 222 | union acpi_object *ext_obj, *package; | ||
| 223 | int i, len = 0; | ||
| 224 | |||
| 225 | acpi_get_name(handle, ACPI_FULL_PATHNAME, &string); | ||
| 226 | 221 | ||
| 227 | /* Clear the return buffer with zeros */ | ||
| 228 | memset(hpp, 0, sizeof(struct hotplug_params)); | 222 | memset(hpp, 0, sizeof(struct hotplug_params)); |
| 229 | 223 | ||
| 230 | /* get _hpp */ | 224 | status = acpi_evaluate_object(handle, "_HPP", NULL, &buffer); |
| 231 | status = acpi_evaluate_object(handle, METHOD_NAME__HPP, NULL, &ret_buf); | 225 | if (ACPI_FAILURE(status)) |
| 232 | switch (status) { | 226 | return status; |
| 233 | case AE_BUFFER_OVERFLOW: | ||
| 234 | ret_buf.pointer = kmalloc (ret_buf.length, GFP_KERNEL); | ||
| 235 | if (!ret_buf.pointer) { | ||
| 236 | printk(KERN_ERR "%s:%s alloc for _HPP fail\n", | ||
| 237 | __func__, (char *)string.pointer); | ||
| 238 | kfree(string.pointer); | ||
| 239 | return AE_NO_MEMORY; | ||
| 240 | } | ||
| 241 | status = acpi_evaluate_object(handle, METHOD_NAME__HPP, | ||
| 242 | NULL, &ret_buf); | ||
| 243 | if (ACPI_SUCCESS(status)) | ||
| 244 | break; | ||
| 245 | default: | ||
| 246 | if (ACPI_FAILURE(status)) { | ||
| 247 | pr_debug("%s:%s _HPP fail=0x%x\n", __func__, | ||
| 248 | (char *)string.pointer, status); | ||
| 249 | kfree(string.pointer); | ||
| 250 | return status; | ||
| 251 | } | ||
| 252 | } | ||
| 253 | 227 | ||
| 254 | ext_obj = (union acpi_object *) ret_buf.pointer; | 228 | package = (union acpi_object *) buffer.pointer; |
| 255 | if (ext_obj->type != ACPI_TYPE_PACKAGE) { | 229 | if (package->type != ACPI_TYPE_PACKAGE || |
| 256 | printk(KERN_ERR "%s:%s _HPP obj not a package\n", __func__, | 230 | package->package.count != 4) { |
| 257 | (char *)string.pointer); | ||
| 258 | status = AE_ERROR; | 231 | status = AE_ERROR; |
| 259 | goto free_and_return; | 232 | goto exit; |
| 260 | } | 233 | } |
| 261 | 234 | ||
| 262 | len = ext_obj->package.count; | 235 | fields = package->package.elements; |
| 263 | package = (union acpi_object *) ret_buf.pointer; | 236 | for (i = 0; i < 4; i++) { |
| 264 | for ( i = 0; (i < len) || (i < 4); i++) { | 237 | if (fields[i].type != ACPI_TYPE_INTEGER) { |
| 265 | ext_obj = (union acpi_object *) &package->package.elements[i]; | ||
| 266 | switch (ext_obj->type) { | ||
| 267 | case ACPI_TYPE_INTEGER: | ||
| 268 | nui[i] = (u8)ext_obj->integer.value; | ||
| 269 | break; | ||
| 270 | default: | ||
| 271 | printk(KERN_ERR "%s:%s _HPP obj type incorrect\n", | ||
| 272 | __func__, (char *)string.pointer); | ||
| 273 | status = AE_ERROR; | 238 | status = AE_ERROR; |
| 274 | goto free_and_return; | 239 | goto exit; |
| 275 | } | 240 | } |
| 276 | } | 241 | } |
| 277 | 242 | ||
| 278 | hpp->t0 = &hpp->type0_data; | 243 | hpp->t0 = &hpp->type0_data; |
| 279 | hpp->t0->cache_line_size = nui[0]; | 244 | hpp->t0->revision = 1; |
| 280 | hpp->t0->latency_timer = nui[1]; | 245 | hpp->t0->cache_line_size = fields[0].integer.value; |
| 281 | hpp->t0->enable_serr = nui[2]; | 246 | hpp->t0->latency_timer = fields[1].integer.value; |
| 282 | hpp->t0->enable_perr = nui[3]; | 247 | hpp->t0->enable_serr = fields[2].integer.value; |
| 283 | 248 | hpp->t0->enable_perr = fields[3].integer.value; | |
| 284 | pr_debug(" _HPP: cache_line_size=0x%x\n", hpp->t0->cache_line_size); | ||
| 285 | pr_debug(" _HPP: latency timer =0x%x\n", hpp->t0->latency_timer); | ||
| 286 | pr_debug(" _HPP: enable SERR =0x%x\n", hpp->t0->enable_serr); | ||
| 287 | pr_debug(" _HPP: enable PERR =0x%x\n", hpp->t0->enable_perr); | ||
| 288 | 249 | ||
| 289 | free_and_return: | 250 | exit: |
| 290 | kfree(string.pointer); | 251 | kfree(buffer.pointer); |
| 291 | kfree(ret_buf.pointer); | ||
| 292 | return status; | 252 | return status; |
| 293 | } | 253 | } |
| 294 | 254 | ||
| @@ -322,20 +282,19 @@ static acpi_status acpi_run_oshp(acpi_handle handle) | |||
| 322 | return status; | 282 | return status; |
| 323 | } | 283 | } |
| 324 | 284 | ||
| 325 | /* acpi_get_hp_params_from_firmware | 285 | /* pci_get_hp_params |
| 326 | * | 286 | * |
| 327 | * @bus - the pci_bus of the bus on which the device is newly added | 287 | * @dev - the pci_dev for which we want parameters |
| 328 | * @hpp - allocated by the caller | 288 | * @hpp - allocated by the caller |
| 329 | */ | 289 | */ |
| 330 | acpi_status acpi_get_hp_params_from_firmware(struct pci_bus *bus, | 290 | int pci_get_hp_params(struct pci_dev *dev, struct hotplug_params *hpp) |
| 331 | struct hotplug_params *hpp) | ||
| 332 | { | 291 | { |
| 333 | acpi_status status = AE_NOT_FOUND; | 292 | acpi_status status; |
| 334 | acpi_handle handle, phandle; | 293 | acpi_handle handle, phandle; |
| 335 | struct pci_bus *pbus; | 294 | struct pci_bus *pbus; |
| 336 | 295 | ||
| 337 | handle = NULL; | 296 | handle = NULL; |
| 338 | for (pbus = bus; pbus; pbus = pbus->parent) { | 297 | for (pbus = dev->bus; pbus; pbus = pbus->parent) { |
| 339 | handle = acpi_pci_get_bridge_handle(pbus); | 298 | handle = acpi_pci_get_bridge_handle(pbus); |
| 340 | if (handle) | 299 | if (handle) |
| 341 | break; | 300 | break; |
| @@ -345,15 +304,15 @@ acpi_status acpi_get_hp_params_from_firmware(struct pci_bus *bus, | |||
| 345 | * _HPP settings apply to all child buses, until another _HPP is | 304 | * _HPP settings apply to all child buses, until another _HPP is |
| 346 | * encountered. If we don't find an _HPP for the input pci dev, | 305 | * encountered. If we don't find an _HPP for the input pci dev, |
| 347 | * look for it in the parent device scope since that would apply to | 306 | * look for it in the parent device scope since that would apply to |
| 348 | * this pci dev. If we don't find any _HPP, use hardcoded defaults | 307 | * this pci dev. |
| 349 | */ | 308 | */ |
| 350 | while (handle) { | 309 | while (handle) { |
| 351 | status = acpi_run_hpx(handle, hpp); | 310 | status = acpi_run_hpx(handle, hpp); |
| 352 | if (ACPI_SUCCESS(status)) | 311 | if (ACPI_SUCCESS(status)) |
| 353 | break; | 312 | return 0; |
| 354 | status = acpi_run_hpp(handle, hpp); | 313 | status = acpi_run_hpp(handle, hpp); |
| 355 | if (ACPI_SUCCESS(status)) | 314 | if (ACPI_SUCCESS(status)) |
| 356 | break; | 315 | return 0; |
| 357 | if (acpi_is_root_bridge(handle)) | 316 | if (acpi_is_root_bridge(handle)) |
| 358 | break; | 317 | break; |
| 359 | status = acpi_get_parent(handle, &phandle); | 318 | status = acpi_get_parent(handle, &phandle); |
| @@ -361,9 +320,9 @@ acpi_status acpi_get_hp_params_from_firmware(struct pci_bus *bus, | |||
| 361 | break; | 320 | break; |
| 362 | handle = phandle; | 321 | handle = phandle; |
| 363 | } | 322 | } |
| 364 | return status; | 323 | return -ENODEV; |
| 365 | } | 324 | } |
| 366 | EXPORT_SYMBOL_GPL(acpi_get_hp_params_from_firmware); | 325 | EXPORT_SYMBOL_GPL(pci_get_hp_params); |
| 367 | 326 | ||
| 368 | /** | 327 | /** |
| 369 | * acpi_get_hp_hw_control_from_firmware | 328 | * acpi_get_hp_hw_control_from_firmware |
| @@ -500,18 +459,18 @@ check_hotplug(acpi_handle handle, u32 lvl, void *context, void **rv) | |||
| 500 | 459 | ||
| 501 | /** | 460 | /** |
| 502 | * acpi_pci_detect_ejectable - check if the PCI bus has ejectable slots | 461 | * acpi_pci_detect_ejectable - check if the PCI bus has ejectable slots |
| 503 | * @pbus - PCI bus to scan | 462 | * @handle - handle of the PCI bus to scan |
| 504 | * | 463 | * |
| 505 | * Returns 1 if the PCI bus has ACPI based ejectable slots, 0 otherwise. | 464 | * Returns 1 if the PCI bus has ACPI based ejectable slots, 0 otherwise. |
| 506 | */ | 465 | */ |
| 507 | int acpi_pci_detect_ejectable(struct pci_bus *pbus) | 466 | int acpi_pci_detect_ejectable(acpi_handle handle) |
| 508 | { | 467 | { |
| 509 | acpi_handle handle; | ||
| 510 | int found = 0; | 468 | int found = 0; |
| 511 | 469 | ||
| 512 | if (!(handle = acpi_pci_get_bridge_handle(pbus))) | 470 | if (!handle) |
| 513 | return 0; | 471 | return found; |
| 514 | acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1, | 472 | |
| 473 | acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, 1, | ||
| 515 | check_hotplug, (void *)&found, NULL); | 474 | check_hotplug, (void *)&found, NULL); |
| 516 | return found; | 475 | return found; |
| 517 | } | 476 | } |
diff --git a/drivers/pci/hotplug/acpiphp.h b/drivers/pci/hotplug/acpiphp.h index e68d5f20ffb3..7d938df79206 100644 --- a/drivers/pci/hotplug/acpiphp.h +++ b/drivers/pci/hotplug/acpiphp.h | |||
| @@ -91,9 +91,6 @@ struct acpiphp_bridge { | |||
| 91 | /* PCI-to-PCI bridge device */ | 91 | /* PCI-to-PCI bridge device */ |
| 92 | struct pci_dev *pci_dev; | 92 | struct pci_dev *pci_dev; |
| 93 | 93 | ||
| 94 | /* ACPI 2.0 _HPP parameters */ | ||
| 95 | struct hotplug_params hpp; | ||
| 96 | |||
| 97 | spinlock_t res_lock; | 94 | spinlock_t res_lock; |
| 98 | }; | 95 | }; |
| 99 | 96 | ||
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 | ||
diff --git a/drivers/pci/hotplug/pci_hotplug_core.c b/drivers/pci/hotplug/pci_hotplug_core.c index 5c5043f239cf..0325d989bb46 100644 --- a/drivers/pci/hotplug/pci_hotplug_core.c +++ b/drivers/pci/hotplug/pci_hotplug_core.c | |||
| @@ -86,7 +86,8 @@ static char *pci_bus_speed_strings[] = { | |||
| 86 | "66 MHz PCIX 533", /* 0x11 */ | 86 | "66 MHz PCIX 533", /* 0x11 */ |
| 87 | "100 MHz PCIX 533", /* 0x12 */ | 87 | "100 MHz PCIX 533", /* 0x12 */ |
| 88 | "133 MHz PCIX 533", /* 0x13 */ | 88 | "133 MHz PCIX 533", /* 0x13 */ |
| 89 | "25 GBps PCI-E", /* 0x14 */ | 89 | "2.5 GT/s PCI-E", /* 0x14 */ |
| 90 | "5.0 GT/s PCI-E", /* 0x15 */ | ||
| 90 | }; | 91 | }; |
| 91 | 92 | ||
| 92 | #ifdef CONFIG_HOTPLUG_PCI_CPCI | 93 | #ifdef CONFIG_HOTPLUG_PCI_CPCI |
diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h index e6cf096498be..36faa9a8e18f 100644 --- a/drivers/pci/hotplug/pciehp.h +++ b/drivers/pci/hotplug/pciehp.h | |||
| @@ -237,17 +237,8 @@ static inline int pciehp_get_hp_hw_control_from_firmware(struct pci_dev *dev) | |||
| 237 | return retval; | 237 | return retval; |
| 238 | return pciehp_acpi_slot_detection_check(dev); | 238 | return pciehp_acpi_slot_detection_check(dev); |
| 239 | } | 239 | } |
| 240 | |||
| 241 | static inline int pciehp_get_hp_params_from_firmware(struct pci_dev *dev, | ||
| 242 | struct hotplug_params *hpp) | ||
| 243 | { | ||
| 244 | if (ACPI_FAILURE(acpi_get_hp_params_from_firmware(dev->bus, hpp))) | ||
| 245 | return -ENODEV; | ||
| 246 | return 0; | ||
| 247 | } | ||
| 248 | #else | 240 | #else |
| 249 | #define pciehp_firmware_init() do {} while (0) | 241 | #define pciehp_firmware_init() do {} while (0) |
| 250 | #define pciehp_get_hp_hw_control_from_firmware(dev) 0 | 242 | #define pciehp_get_hp_hw_control_from_firmware(dev) 0 |
| 251 | #define pciehp_get_hp_params_from_firmware(dev, hpp) (-ENODEV) | ||
| 252 | #endif /* CONFIG_ACPI */ | 243 | #endif /* CONFIG_ACPI */ |
| 253 | #endif /* _PCIEHP_H */ | 244 | #endif /* _PCIEHP_H */ |
diff --git a/drivers/pci/hotplug/pciehp_acpi.c b/drivers/pci/hotplug/pciehp_acpi.c index 96048010e7d9..7163e6a6cfae 100644 --- a/drivers/pci/hotplug/pciehp_acpi.c +++ b/drivers/pci/hotplug/pciehp_acpi.c | |||
| @@ -47,7 +47,7 @@ int pciehp_acpi_slot_detection_check(struct pci_dev *dev) | |||
| 47 | { | 47 | { |
| 48 | if (slot_detection_mode != PCIEHP_DETECT_ACPI) | 48 | if (slot_detection_mode != PCIEHP_DETECT_ACPI) |
| 49 | return 0; | 49 | return 0; |
| 50 | if (acpi_pci_detect_ejectable(dev->subordinate)) | 50 | if (acpi_pci_detect_ejectable(DEVICE_ACPI_HANDLE(&dev->dev))) |
| 51 | return 0; | 51 | return 0; |
| 52 | return -ENODEV; | 52 | return -ENODEV; |
| 53 | } | 53 | } |
| @@ -76,9 +76,9 @@ static int __init dummy_probe(struct pcie_device *dev) | |||
| 76 | { | 76 | { |
| 77 | int pos; | 77 | int pos; |
| 78 | u32 slot_cap; | 78 | u32 slot_cap; |
| 79 | acpi_handle handle; | ||
| 79 | struct slot *slot, *tmp; | 80 | struct slot *slot, *tmp; |
| 80 | struct pci_dev *pdev = dev->port; | 81 | struct pci_dev *pdev = dev->port; |
| 81 | struct pci_bus *pbus = pdev->subordinate; | ||
| 82 | /* Note: pciehp_detect_mode != PCIEHP_DETECT_ACPI here */ | 82 | /* Note: pciehp_detect_mode != PCIEHP_DETECT_ACPI here */ |
| 83 | if (pciehp_get_hp_hw_control_from_firmware(pdev)) | 83 | if (pciehp_get_hp_hw_control_from_firmware(pdev)) |
| 84 | return -ENODEV; | 84 | return -ENODEV; |
| @@ -94,7 +94,8 @@ static int __init dummy_probe(struct pcie_device *dev) | |||
| 94 | dup_slot_id++; | 94 | dup_slot_id++; |
| 95 | } | 95 | } |
| 96 | list_add_tail(&slot->slot_list, &dummy_slots); | 96 | list_add_tail(&slot->slot_list, &dummy_slots); |
| 97 | if (!acpi_slot_detected && acpi_pci_detect_ejectable(pbus)) | 97 | handle = DEVICE_ACPI_HANDLE(&pdev->dev); |
| 98 | if (!acpi_slot_detected && acpi_pci_detect_ejectable(handle)) | ||
| 98 | acpi_slot_detected = 1; | 99 | acpi_slot_detected = 1; |
| 99 | return -ENODEV; /* dummy driver always returns error */ | 100 | return -ENODEV; /* dummy driver always returns error */ |
| 100 | } | 101 | } |
diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c index 8aab8edf123e..b97cb4c3e0fe 100644 --- a/drivers/pci/hotplug/pciehp_ctrl.c +++ b/drivers/pci/hotplug/pciehp_ctrl.c | |||
| @@ -246,11 +246,6 @@ static int board_added(struct slot *p_slot) | |||
| 246 | goto err_exit; | 246 | goto err_exit; |
| 247 | } | 247 | } |
| 248 | 248 | ||
| 249 | /* | ||
| 250 | * Some PCI Express root ports require fixup after hot-plug operation. | ||
| 251 | */ | ||
| 252 | if (pcie_mch_quirk) | ||
| 253 | pci_fixup_device(pci_fixup_final, ctrl->pci_dev); | ||
| 254 | if (PWR_LED(ctrl)) | 249 | if (PWR_LED(ctrl)) |
| 255 | p_slot->hpc_ops->green_led_on(p_slot); | 250 | p_slot->hpc_ops->green_led_on(p_slot); |
| 256 | 251 | ||
diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index 52813257e5bf..271f917b6f2c 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c | |||
| @@ -693,7 +693,10 @@ static int hpc_get_max_lnk_speed(struct slot *slot, enum pci_bus_speed *value) | |||
| 693 | 693 | ||
| 694 | switch (lnk_cap & 0x000F) { | 694 | switch (lnk_cap & 0x000F) { |
| 695 | case 1: | 695 | case 1: |
| 696 | lnk_speed = PCIE_2PT5GB; | 696 | lnk_speed = PCIE_2_5GB; |
| 697 | break; | ||
| 698 | case 2: | ||
| 699 | lnk_speed = PCIE_5_0GB; | ||
| 697 | break; | 700 | break; |
| 698 | default: | 701 | default: |
| 699 | lnk_speed = PCIE_LNK_SPEED_UNKNOWN; | 702 | lnk_speed = PCIE_LNK_SPEED_UNKNOWN; |
| @@ -772,7 +775,10 @@ static int hpc_get_cur_lnk_speed(struct slot *slot, enum pci_bus_speed *value) | |||
| 772 | 775 | ||
| 773 | switch (lnk_status & PCI_EXP_LNKSTA_CLS) { | 776 | switch (lnk_status & PCI_EXP_LNKSTA_CLS) { |
| 774 | case 1: | 777 | case 1: |
| 775 | lnk_speed = PCIE_2PT5GB; | 778 | lnk_speed = PCIE_2_5GB; |
| 779 | break; | ||
| 780 | case 2: | ||
| 781 | lnk_speed = PCIE_5_0GB; | ||
| 776 | break; | 782 | break; |
| 777 | default: | 783 | default: |
| 778 | lnk_speed = PCIE_LNK_SPEED_UNKNOWN; | 784 | lnk_speed = PCIE_LNK_SPEED_UNKNOWN; |
diff --git a/drivers/pci/hotplug/pciehp_pci.c b/drivers/pci/hotplug/pciehp_pci.c index 10f9566cceeb..02e24d63b3ee 100644 --- a/drivers/pci/hotplug/pciehp_pci.c +++ b/drivers/pci/hotplug/pciehp_pci.c | |||
| @@ -34,136 +34,6 @@ | |||
| 34 | #include "../pci.h" | 34 | #include "../pci.h" |
| 35 | #include "pciehp.h" | 35 | #include "pciehp.h" |
| 36 | 36 | ||
| 37 | static void program_hpp_type0(struct pci_dev *dev, struct hpp_type0 *hpp) | ||
| 38 | { | ||
| 39 | u16 pci_cmd, pci_bctl; | ||
| 40 | |||
| 41 | if (hpp->revision > 1) { | ||
| 42 | warn("Rev.%d type0 record not supported\n", hpp->revision); | ||
| 43 | return; | ||
| 44 | } | ||
| 45 | |||
| 46 | pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, hpp->cache_line_size); | ||
| 47 | pci_write_config_byte(dev, PCI_LATENCY_TIMER, hpp->latency_timer); | ||
| 48 | pci_read_config_word(dev, PCI_COMMAND, &pci_cmd); | ||
| 49 | if (hpp->enable_serr) | ||
| 50 | pci_cmd |= PCI_COMMAND_SERR; | ||
| 51 | else | ||
| 52 | pci_cmd &= ~PCI_COMMAND_SERR; | ||
| 53 | if (hpp->enable_perr) | ||
| 54 | pci_cmd |= PCI_COMMAND_PARITY; | ||
| 55 | else | ||
| 56 | pci_cmd &= ~PCI_COMMAND_PARITY; | ||
| 57 | pci_write_config_word(dev, PCI_COMMAND, pci_cmd); | ||
| 58 | |||
| 59 | /* Program bridge control value */ | ||
| 60 | if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) { | ||
| 61 | pci_write_config_byte(dev, PCI_SEC_LATENCY_TIMER, | ||
| 62 | hpp->latency_timer); | ||
| 63 | pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &pci_bctl); | ||
| 64 | if (hpp->enable_serr) | ||
| 65 | pci_bctl |= PCI_BRIDGE_CTL_SERR; | ||
| 66 | else | ||
| 67 | pci_bctl &= ~PCI_BRIDGE_CTL_SERR; | ||
| 68 | if (hpp->enable_perr) | ||
| 69 | pci_bctl |= PCI_BRIDGE_CTL_PARITY; | ||
| 70 | else | ||
| 71 | pci_bctl &= ~PCI_BRIDGE_CTL_PARITY; | ||
| 72 | pci_write_config_word(dev, PCI_BRIDGE_CONTROL, pci_bctl); | ||
| 73 | } | ||
| 74 | } | ||
| 75 | |||
| 76 | static void program_hpp_type2(struct pci_dev *dev, struct hpp_type2 *hpp) | ||
| 77 | { | ||
| 78 | int pos; | ||
| 79 | u16 reg16; | ||
| 80 | u32 reg32; | ||
| 81 | |||
| 82 | if (hpp->revision > 1) { | ||
| 83 | warn("Rev.%d type2 record not supported\n", hpp->revision); | ||
| 84 | return; | ||
| 85 | } | ||
| 86 | |||
| 87 | /* Find PCI Express capability */ | ||
| 88 | pos = pci_find_capability(dev, PCI_CAP_ID_EXP); | ||
| 89 | if (!pos) | ||
| 90 | return; | ||
| 91 | |||
| 92 | /* Initialize Device Control Register */ | ||
| 93 | pci_read_config_word(dev, pos + PCI_EXP_DEVCTL, ®16); | ||
| 94 | reg16 = (reg16 & hpp->pci_exp_devctl_and) | hpp->pci_exp_devctl_or; | ||
| 95 | pci_write_config_word(dev, pos + PCI_EXP_DEVCTL, reg16); | ||
| 96 | |||
| 97 | /* Initialize Link Control Register */ | ||
| 98 | if (dev->subordinate) { | ||
| 99 | pci_read_config_word(dev, pos + PCI_EXP_LNKCTL, ®16); | ||
| 100 | reg16 = (reg16 & hpp->pci_exp_lnkctl_and) | ||
| 101 | | hpp->pci_exp_lnkctl_or; | ||
| 102 | pci_write_config_word(dev, pos + PCI_EXP_LNKCTL, reg16); | ||
| 103 | } | ||
| 104 | |||
| 105 | /* Find Advanced Error Reporting Enhanced Capability */ | ||
| 106 | pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR); | ||
| 107 | if (!pos) | ||
| 108 | return; | ||
| 109 | |||
| 110 | /* Initialize Uncorrectable Error Mask Register */ | ||
| 111 | pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_MASK, ®32); | ||
| 112 | reg32 = (reg32 & hpp->unc_err_mask_and) | hpp->unc_err_mask_or; | ||
| 113 | pci_write_config_dword(dev, pos + PCI_ERR_UNCOR_MASK, reg32); | ||
| 114 | |||
| 115 | /* Initialize Uncorrectable Error Severity Register */ | ||
| 116 | pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_SEVER, ®32); | ||
| 117 | reg32 = (reg32 & hpp->unc_err_sever_and) | hpp->unc_err_sever_or; | ||
| 118 | pci_write_config_dword(dev, pos + PCI_ERR_UNCOR_SEVER, reg32); | ||
| 119 | |||
| 120 | /* Initialize Correctable Error Mask Register */ | ||
| 121 | pci_read_config_dword(dev, pos + PCI_ERR_COR_MASK, ®32); | ||
| 122 | reg32 = (reg32 & hpp->cor_err_mask_and) | hpp->cor_err_mask_or; | ||
| 123 | pci_write_config_dword(dev, pos + PCI_ERR_COR_MASK, reg32); | ||
| 124 | |||
| 125 | /* Initialize Advanced Error Capabilities and Control Register */ | ||
| 126 | pci_read_config_dword(dev, pos + PCI_ERR_CAP, ®32); | ||
| 127 | reg32 = (reg32 & hpp->adv_err_cap_and) | hpp->adv_err_cap_or; | ||
| 128 | pci_write_config_dword(dev, pos + PCI_ERR_CAP, reg32); | ||
| 129 | |||
| 130 | /* | ||
| 131 | * FIXME: The following two registers are not supported yet. | ||
| 132 | * | ||
| 133 | * o Secondary Uncorrectable Error Severity Register | ||
| 134 | * o Secondary Uncorrectable Error Mask Register | ||
| 135 | */ | ||
| 136 | } | ||
| 137 | |||
| 138 | static void program_fw_provided_values(struct pci_dev *dev) | ||
| 139 | { | ||
| 140 | struct pci_dev *cdev; | ||
| 141 | struct hotplug_params hpp; | ||
| 142 | |||
| 143 | /* Program hpp values for this device */ | ||
| 144 | if (!(dev->hdr_type == PCI_HEADER_TYPE_NORMAL || | ||
| 145 | (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE && | ||
| 146 | (dev->class >> 8) == PCI_CLASS_BRIDGE_PCI))) | ||
| 147 | return; | ||
| 148 | |||
| 149 | if (pciehp_get_hp_params_from_firmware(dev, &hpp)) { | ||
| 150 | warn("Could not get hotplug parameters\n"); | ||
| 151 | return; | ||
| 152 | } | ||
| 153 | |||
| 154 | if (hpp.t2) | ||
| 155 | program_hpp_type2(dev, hpp.t2); | ||
| 156 | if (hpp.t0) | ||
| 157 | program_hpp_type0(dev, hpp.t0); | ||
| 158 | |||
| 159 | /* Program child devices */ | ||
| 160 | if (dev->subordinate) { | ||
| 161 | list_for_each_entry(cdev, &dev->subordinate->devices, | ||
| 162 | bus_list) | ||
| 163 | program_fw_provided_values(cdev); | ||
| 164 | } | ||
| 165 | } | ||
| 166 | |||
| 167 | static int __ref pciehp_add_bridge(struct pci_dev *dev) | 37 | static int __ref pciehp_add_bridge(struct pci_dev *dev) |
| 168 | { | 38 | { |
| 169 | struct pci_bus *parent = dev->bus; | 39 | struct pci_bus *parent = dev->bus; |
| @@ -226,7 +96,7 @@ int pciehp_configure_device(struct slot *p_slot) | |||
| 226 | (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)) { | 96 | (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)) { |
| 227 | pciehp_add_bridge(dev); | 97 | pciehp_add_bridge(dev); |
| 228 | } | 98 | } |
| 229 | program_fw_provided_values(dev); | 99 | pci_configure_slot(dev); |
| 230 | pci_dev_put(dev); | 100 | pci_dev_put(dev); |
| 231 | } | 101 | } |
| 232 | 102 | ||
| @@ -285,11 +155,6 @@ int pciehp_unconfigure_device(struct slot *p_slot) | |||
| 285 | } | 155 | } |
| 286 | pci_dev_put(temp); | 156 | pci_dev_put(temp); |
| 287 | } | 157 | } |
| 288 | /* | ||
| 289 | * Some PCI Express root ports require fixup after hot-plug operation. | ||
| 290 | */ | ||
| 291 | if (pcie_mch_quirk) | ||
| 292 | pci_fixup_device(pci_fixup_final, p_slot->ctrl->pci_dev); | ||
| 293 | 158 | ||
| 294 | return rc; | 159 | return rc; |
| 295 | } | 160 | } |
diff --git a/drivers/pci/hotplug/pcihp_slot.c b/drivers/pci/hotplug/pcihp_slot.c new file mode 100644 index 000000000000..cc8ec3aa41a7 --- /dev/null +++ b/drivers/pci/hotplug/pcihp_slot.c | |||
| @@ -0,0 +1,187 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 1995,2001 Compaq Computer Corporation | ||
| 3 | * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com) | ||
| 4 | * Copyright (C) 2001 IBM Corp. | ||
| 5 | * Copyright (C) 2003-2004 Intel Corporation | ||
| 6 | * (c) Copyright 2009 Hewlett-Packard Development Company, L.P. | ||
| 7 | * | ||
| 8 | * All rights reserved. | ||
| 9 | * | ||
| 10 | * This program is free software; you can redistribute it and/or modify | ||
| 11 | * it under the terms of the GNU General Public License as published by | ||
| 12 | * the Free Software Foundation; either version 2 of the License, or (at | ||
| 13 | * your option) any later version. | ||
| 14 | * | ||
| 15 | * This program is distributed in the hope that it will be useful, but | ||
| 16 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 17 | * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or | ||
| 18 | * NON INFRINGEMENT. See the GNU General Public License for more | ||
| 19 | * details. | ||
| 20 | * | ||
| 21 | * You should have received a copy of the GNU General Public License | ||
| 22 | * along with this program; if not, write to the Free Software | ||
| 23 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
| 24 | */ | ||
| 25 | |||
| 26 | #include <linux/pci.h> | ||
| 27 | #include <linux/pci_hotplug.h> | ||
| 28 | |||
| 29 | static struct hpp_type0 pci_default_type0 = { | ||
| 30 | .revision = 1, | ||
| 31 | .cache_line_size = 8, | ||
| 32 | .latency_timer = 0x40, | ||
| 33 | .enable_serr = 0, | ||
| 34 | .enable_perr = 0, | ||
| 35 | }; | ||
| 36 | |||
| 37 | static void program_hpp_type0(struct pci_dev *dev, struct hpp_type0 *hpp) | ||
| 38 | { | ||
| 39 | u16 pci_cmd, pci_bctl; | ||
| 40 | |||
| 41 | if (!hpp) { | ||
| 42 | /* | ||
| 43 | * Perhaps we *should* use default settings for PCIe, but | ||
| 44 | * pciehp didn't, so we won't either. | ||
| 45 | */ | ||
| 46 | if (dev->is_pcie) | ||
| 47 | return; | ||
| 48 | dev_info(&dev->dev, "using default PCI settings\n"); | ||
| 49 | hpp = &pci_default_type0; | ||
| 50 | } | ||
| 51 | |||
| 52 | if (hpp->revision > 1) { | ||
| 53 | dev_warn(&dev->dev, | ||
| 54 | "PCI settings rev %d not supported; using defaults\n", | ||
| 55 | hpp->revision); | ||
| 56 | hpp = &pci_default_type0; | ||
| 57 | } | ||
| 58 | |||
| 59 | pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, hpp->cache_line_size); | ||
| 60 | pci_write_config_byte(dev, PCI_LATENCY_TIMER, hpp->latency_timer); | ||
| 61 | pci_read_config_word(dev, PCI_COMMAND, &pci_cmd); | ||
| 62 | if (hpp->enable_serr) | ||
| 63 | pci_cmd |= PCI_COMMAND_SERR; | ||
| 64 | else | ||
| 65 | pci_cmd &= ~PCI_COMMAND_SERR; | ||
| 66 | if (hpp->enable_perr) | ||
| 67 | pci_cmd |= PCI_COMMAND_PARITY; | ||
| 68 | else | ||
| 69 | pci_cmd &= ~PCI_COMMAND_PARITY; | ||
| 70 | pci_write_config_word(dev, PCI_COMMAND, pci_cmd); | ||
| 71 | |||
| 72 | /* Program bridge control value */ | ||
| 73 | if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) { | ||
| 74 | pci_write_config_byte(dev, PCI_SEC_LATENCY_TIMER, | ||
| 75 | hpp->latency_timer); | ||
| 76 | pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &pci_bctl); | ||
| 77 | if (hpp->enable_serr) | ||
| 78 | pci_bctl |= PCI_BRIDGE_CTL_SERR; | ||
| 79 | else | ||
| 80 | pci_bctl &= ~PCI_BRIDGE_CTL_SERR; | ||
| 81 | if (hpp->enable_perr) | ||
| 82 | pci_bctl |= PCI_BRIDGE_CTL_PARITY; | ||
| 83 | else | ||
| 84 | pci_bctl &= ~PCI_BRIDGE_CTL_PARITY; | ||
| 85 | pci_write_config_word(dev, PCI_BRIDGE_CONTROL, pci_bctl); | ||
| 86 | } | ||
| 87 | } | ||
| 88 | |||
| 89 | static void program_hpp_type1(struct pci_dev *dev, struct hpp_type1 *hpp) | ||
| 90 | { | ||
| 91 | if (hpp) | ||
| 92 | dev_warn(&dev->dev, "PCI-X settings not supported\n"); | ||
| 93 | } | ||
| 94 | |||
| 95 | static void program_hpp_type2(struct pci_dev *dev, struct hpp_type2 *hpp) | ||
| 96 | { | ||
| 97 | int pos; | ||
| 98 | u16 reg16; | ||
| 99 | u32 reg32; | ||
| 100 | |||
| 101 | if (!hpp) | ||
| 102 | return; | ||
| 103 | |||
| 104 | /* Find PCI Express capability */ | ||
| 105 | pos = pci_find_capability(dev, PCI_CAP_ID_EXP); | ||
| 106 | if (!pos) | ||
| 107 | return; | ||
| 108 | |||
| 109 | if (hpp->revision > 1) { | ||
| 110 | dev_warn(&dev->dev, "PCIe settings rev %d not supported\n", | ||
| 111 | hpp->revision); | ||
| 112 | return; | ||
| 113 | } | ||
| 114 | |||
| 115 | /* Initialize Device Control Register */ | ||
| 116 | pci_read_config_word(dev, pos + PCI_EXP_DEVCTL, ®16); | ||
| 117 | reg16 = (reg16 & hpp->pci_exp_devctl_and) | hpp->pci_exp_devctl_or; | ||
| 118 | pci_write_config_word(dev, pos + PCI_EXP_DEVCTL, reg16); | ||
| 119 | |||
| 120 | /* Initialize Link Control Register */ | ||
| 121 | if (dev->subordinate) { | ||
| 122 | pci_read_config_word(dev, pos + PCI_EXP_LNKCTL, ®16); | ||
| 123 | reg16 = (reg16 & hpp->pci_exp_lnkctl_and) | ||
| 124 | | hpp->pci_exp_lnkctl_or; | ||
| 125 | pci_write_config_word(dev, pos + PCI_EXP_LNKCTL, reg16); | ||
| 126 | } | ||
| 127 | |||
| 128 | /* Find Advanced Error Reporting Enhanced Capability */ | ||
| 129 | pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR); | ||
| 130 | if (!pos) | ||
| 131 | return; | ||
| 132 | |||
| 133 | /* Initialize Uncorrectable Error Mask Register */ | ||
| 134 | pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_MASK, ®32); | ||
| 135 | reg32 = (reg32 & hpp->unc_err_mask_and) | hpp->unc_err_mask_or; | ||
| 136 | pci_write_config_dword(dev, pos + PCI_ERR_UNCOR_MASK, reg32); | ||
| 137 | |||
| 138 | /* Initialize Uncorrectable Error Severity Register */ | ||
| 139 | pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_SEVER, ®32); | ||
| 140 | reg32 = (reg32 & hpp->unc_err_sever_and) | hpp->unc_err_sever_or; | ||
| 141 | pci_write_config_dword(dev, pos + PCI_ERR_UNCOR_SEVER, reg32); | ||
| 142 | |||
| 143 | /* Initialize Correctable Error Mask Register */ | ||
| 144 | pci_read_config_dword(dev, pos + PCI_ERR_COR_MASK, ®32); | ||
| 145 | reg32 = (reg32 & hpp->cor_err_mask_and) | hpp->cor_err_mask_or; | ||
| 146 | pci_write_config_dword(dev, pos + PCI_ERR_COR_MASK, reg32); | ||
| 147 | |||
| 148 | /* Initialize Advanced Error Capabilities and Control Register */ | ||
| 149 | pci_read_config_dword(dev, pos + PCI_ERR_CAP, ®32); | ||
| 150 | reg32 = (reg32 & hpp->adv_err_cap_and) | hpp->adv_err_cap_or; | ||
| 151 | pci_write_config_dword(dev, pos + PCI_ERR_CAP, reg32); | ||
| 152 | |||
| 153 | /* | ||
| 154 | * FIXME: The following two registers are not supported yet. | ||
| 155 | * | ||
| 156 | * o Secondary Uncorrectable Error Severity Register | ||
| 157 | * o Secondary Uncorrectable Error Mask Register | ||
| 158 | */ | ||
| 159 | } | ||
| 160 | |||
| 161 | void pci_configure_slot(struct pci_dev *dev) | ||
| 162 | { | ||
| 163 | struct pci_dev *cdev; | ||
| 164 | struct hotplug_params hpp; | ||
| 165 | int ret; | ||
| 166 | |||
| 167 | if (!(dev->hdr_type == PCI_HEADER_TYPE_NORMAL || | ||
| 168 | (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE && | ||
| 169 | (dev->class >> 8) == PCI_CLASS_BRIDGE_PCI))) | ||
| 170 | return; | ||
| 171 | |||
| 172 | memset(&hpp, 0, sizeof(hpp)); | ||
| 173 | ret = pci_get_hp_params(dev, &hpp); | ||
| 174 | if (ret) | ||
| 175 | dev_warn(&dev->dev, "no hotplug settings from platform\n"); | ||
| 176 | |||
| 177 | program_hpp_type2(dev, hpp.t2); | ||
| 178 | program_hpp_type1(dev, hpp.t1); | ||
| 179 | program_hpp_type0(dev, hpp.t0); | ||
| 180 | |||
| 181 | if (dev->subordinate) { | ||
| 182 | list_for_each_entry(cdev, &dev->subordinate->devices, | ||
| 183 | bus_list) | ||
| 184 | pci_configure_slot(cdev); | ||
| 185 | } | ||
| 186 | } | ||
| 187 | EXPORT_SYMBOL_GPL(pci_configure_slot); | ||
diff --git a/drivers/pci/hotplug/shpchp.h b/drivers/pci/hotplug/shpchp.h index 974e924ca96d..bd588eb8e922 100644 --- a/drivers/pci/hotplug/shpchp.h +++ b/drivers/pci/hotplug/shpchp.h | |||
| @@ -188,21 +188,12 @@ static inline const char *slot_name(struct slot *slot) | |||
| 188 | 188 | ||
| 189 | #ifdef CONFIG_ACPI | 189 | #ifdef CONFIG_ACPI |
| 190 | #include <linux/pci-acpi.h> | 190 | #include <linux/pci-acpi.h> |
| 191 | static inline int get_hp_params_from_firmware(struct pci_dev *dev, | ||
| 192 | struct hotplug_params *hpp) | ||
| 193 | { | ||
| 194 | if (ACPI_FAILURE(acpi_get_hp_params_from_firmware(dev->bus, hpp))) | ||
| 195 | return -ENODEV; | ||
| 196 | return 0; | ||
| 197 | } | ||
| 198 | |||
| 199 | static inline int get_hp_hw_control_from_firmware(struct pci_dev *dev) | 191 | static inline int get_hp_hw_control_from_firmware(struct pci_dev *dev) |
| 200 | { | 192 | { |
| 201 | u32 flags = OSC_SHPC_NATIVE_HP_CONTROL; | 193 | u32 flags = OSC_SHPC_NATIVE_HP_CONTROL; |
| 202 | return acpi_get_hp_hw_control_from_firmware(dev, flags); | 194 | return acpi_get_hp_hw_control_from_firmware(dev, flags); |
| 203 | } | 195 | } |
| 204 | #else | 196 | #else |
| 205 | #define get_hp_params_from_firmware(dev, hpp) (-ENODEV) | ||
| 206 | #define get_hp_hw_control_from_firmware(dev) (0) | 197 | #define get_hp_hw_control_from_firmware(dev) (0) |
| 207 | #endif | 198 | #endif |
| 208 | 199 | ||
diff --git a/drivers/pci/hotplug/shpchp_pci.c b/drivers/pci/hotplug/shpchp_pci.c index aa315e52529b..8c3d3219f227 100644 --- a/drivers/pci/hotplug/shpchp_pci.c +++ b/drivers/pci/hotplug/shpchp_pci.c | |||
| @@ -34,66 +34,6 @@ | |||
| 34 | #include "../pci.h" | 34 | #include "../pci.h" |
| 35 | #include "shpchp.h" | 35 | #include "shpchp.h" |
| 36 | 36 | ||
| 37 | static void program_fw_provided_values(struct pci_dev *dev) | ||
| 38 | { | ||
| 39 | u16 pci_cmd, pci_bctl; | ||
| 40 | struct pci_dev *cdev; | ||
| 41 | struct hotplug_params hpp; | ||
| 42 | |||
| 43 | /* Program hpp values for this device */ | ||
| 44 | if (!(dev->hdr_type == PCI_HEADER_TYPE_NORMAL || | ||
| 45 | (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE && | ||
| 46 | (dev->class >> 8) == PCI_CLASS_BRIDGE_PCI))) | ||
| 47 | return; | ||
| 48 | |||
| 49 | /* use default values if we can't get them from firmware */ | ||
| 50 | if (get_hp_params_from_firmware(dev, &hpp) || | ||
| 51 | !hpp.t0 || (hpp.t0->revision > 1)) { | ||
| 52 | warn("Could not get hotplug parameters. Use defaults\n"); | ||
| 53 | hpp.t0 = &hpp.type0_data; | ||
| 54 | hpp.t0->revision = 0; | ||
| 55 | hpp.t0->cache_line_size = 8; | ||
| 56 | hpp.t0->latency_timer = 0x40; | ||
| 57 | hpp.t0->enable_serr = 0; | ||
| 58 | hpp.t0->enable_perr = 0; | ||
| 59 | } | ||
| 60 | |||
| 61 | pci_write_config_byte(dev, | ||
| 62 | PCI_CACHE_LINE_SIZE, hpp.t0->cache_line_size); | ||
| 63 | pci_write_config_byte(dev, PCI_LATENCY_TIMER, hpp.t0->latency_timer); | ||
| 64 | pci_read_config_word(dev, PCI_COMMAND, &pci_cmd); | ||
| 65 | if (hpp.t0->enable_serr) | ||
| 66 | pci_cmd |= PCI_COMMAND_SERR; | ||
| 67 | else | ||
| 68 | pci_cmd &= ~PCI_COMMAND_SERR; | ||
| 69 | if (hpp.t0->enable_perr) | ||
| 70 | pci_cmd |= PCI_COMMAND_PARITY; | ||
| 71 | else | ||
| 72 | pci_cmd &= ~PCI_COMMAND_PARITY; | ||
| 73 | pci_write_config_word(dev, PCI_COMMAND, pci_cmd); | ||
| 74 | |||
| 75 | /* Program bridge control value and child devices */ | ||
| 76 | if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) { | ||
| 77 | pci_write_config_byte(dev, PCI_SEC_LATENCY_TIMER, | ||
| 78 | hpp.t0->latency_timer); | ||
| 79 | pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &pci_bctl); | ||
| 80 | if (hpp.t0->enable_serr) | ||
| 81 | pci_bctl |= PCI_BRIDGE_CTL_SERR; | ||
| 82 | else | ||
| 83 | pci_bctl &= ~PCI_BRIDGE_CTL_SERR; | ||
| 84 | if (hpp.t0->enable_perr) | ||
| 85 | pci_bctl |= PCI_BRIDGE_CTL_PARITY; | ||
| 86 | else | ||
| 87 | pci_bctl &= ~PCI_BRIDGE_CTL_PARITY; | ||
| 88 | pci_write_config_word(dev, PCI_BRIDGE_CONTROL, pci_bctl); | ||
| 89 | if (dev->subordinate) { | ||
| 90 | list_for_each_entry(cdev, &dev->subordinate->devices, | ||
| 91 | bus_list) | ||
| 92 | program_fw_provided_values(cdev); | ||
| 93 | } | ||
| 94 | } | ||
| 95 | } | ||
| 96 | |||
| 97 | int __ref shpchp_configure_device(struct slot *p_slot) | 37 | int __ref shpchp_configure_device(struct slot *p_slot) |
| 98 | { | 38 | { |
| 99 | struct pci_dev *dev; | 39 | struct pci_dev *dev; |
| @@ -153,7 +93,7 @@ int __ref shpchp_configure_device(struct slot *p_slot) | |||
| 153 | child->subordinate = pci_do_scan_bus(child); | 93 | child->subordinate = pci_do_scan_bus(child); |
| 154 | pci_bus_size_bridges(child); | 94 | pci_bus_size_bridges(child); |
| 155 | } | 95 | } |
| 156 | program_fw_provided_values(dev); | 96 | pci_configure_slot(dev); |
| 157 | pci_dev_put(dev); | 97 | pci_dev_put(dev); |
| 158 | } | 98 | } |
| 159 | 99 | ||
