Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[PATCH] acpiphp - slot management fix - V4

o This patch removes IDs (for slots management).
o This patch removes the slot register/unregister processes
from the init/exit phases. Instead, adds these processes
in the bridge add/cleanup phases.
o Currently, this change doesn't have any meanings. But
these changes are needed to support p2p bridge(with
hotplug slot)

Signed-off-by: MUNEDA Takahiro <muneda.takahiro@jp.fujitsu.com>
Signed-off-by: Kristen Carlson Accardi <kristen.c.accardi@intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

authored by

MUNEDA Takahiro and committed by
Greg Kroah-Hartman
e27da381 63e5f248

+78 -89
+3 -5
drivers/pci/hotplug/acpiphp.h
··· 60 60 * struct slot - slot information for each *physical* slot 61 61 */ 62 62 struct slot { 63 - u8 number; 64 63 struct hotplug_slot *hotplug_slot; 65 - struct list_head slot_list; 66 - 67 64 struct acpiphp_slot *acpi_slot; 68 65 }; 69 66 ··· 116 119 struct acpiphp_bridge *bridge; /* parent */ 117 120 struct list_head funcs; /* one slot may have different 118 121 objects (i.e. for each function) */ 122 + struct slot *slot; 119 123 struct mutex crit_sect; 120 124 121 - u32 id; /* slot id (serial #) for hotplug core */ 122 125 u8 device; /* pci device# */ 123 126 124 127 u32 sun; /* ACPI _SUN (slot unique number) */ ··· 226 229 /* acpiphp_core.c */ 227 230 extern int acpiphp_register_attention(struct acpiphp_attention_info*info); 228 231 extern int acpiphp_unregister_attention(struct acpiphp_attention_info *info); 232 + extern int acpiphp_register_hotplug_slot(struct acpiphp_slot *slot); 233 + extern void acpiphp_unregister_hotplug_slot(struct acpiphp_slot *slot); 229 234 230 235 /* acpiphp_glue.c */ 231 236 extern int acpiphp_glue_init (void); 232 237 extern void acpiphp_glue_exit (void); 233 238 extern int acpiphp_get_num_slots (void); 234 - extern struct acpiphp_slot *get_slot_from_id (int id); 235 239 typedef int (*acpiphp_callback)(struct acpiphp_slot *slot, void *data); 236 240 void handle_hotplug_event_func(acpi_handle, u32, void*); 237 241
+52 -59
drivers/pci/hotplug/acpiphp_core.c
··· 44 44 #include "pci_hotplug.h" 45 45 #include "acpiphp.h" 46 46 47 - static LIST_HEAD(slot_list); 48 - 49 47 #define MY_NAME "acpiphp" 50 48 51 49 static int debug; ··· 339 341 kfree(slot); 340 342 } 341 343 342 - /** 343 - * init_slots - initialize 'struct slot' structures for each slot 344 - * 345 - */ 346 - static int __init init_slots(void) 344 + /* callback routine to initialize 'struct slot' for each slot */ 345 + int acpiphp_register_hotplug_slot(struct acpiphp_slot *acpiphp_slot) 347 346 { 348 347 struct slot *slot; 348 + struct hotplug_slot *hotplug_slot; 349 + struct hotplug_slot_info *hotplug_slot_info; 349 350 int retval = -ENOMEM; 350 - int i; 351 351 352 - for (i = 0; i < num_slots; ++i) { 353 - slot = kmalloc(sizeof(struct slot), GFP_KERNEL); 354 - if (!slot) 355 - goto error; 356 - memset(slot, 0, sizeof(struct slot)); 352 + slot = kzalloc(sizeof(*slot), GFP_KERNEL); 353 + if (!slot) 354 + goto error; 357 355 358 - slot->hotplug_slot = kmalloc(sizeof(struct hotplug_slot), GFP_KERNEL); 359 - if (!slot->hotplug_slot) 360 - goto error_slot; 361 - memset(slot->hotplug_slot, 0, sizeof(struct hotplug_slot)); 356 + slot->hotplug_slot = kzalloc(sizeof(*hotplug_slot), GFP_KERNEL); 357 + if (!slot->hotplug_slot) 358 + goto error_slot; 362 359 363 - slot->hotplug_slot->info = kmalloc(sizeof(struct hotplug_slot_info), GFP_KERNEL); 364 - if (!slot->hotplug_slot->info) 365 - goto error_hpslot; 366 - memset(slot->hotplug_slot->info, 0, sizeof(struct hotplug_slot_info)); 360 + slot->hotplug_slot->info = kzalloc(sizeof(*hotplug_slot_info), 361 + GFP_KERNEL); 362 + if (!slot->hotplug_slot->info) 363 + goto error_hpslot; 367 364 368 - slot->hotplug_slot->name = kmalloc(SLOT_NAME_SIZE, GFP_KERNEL); 369 - if (!slot->hotplug_slot->name) 370 - goto error_info; 365 + slot->hotplug_slot->name = kzalloc(SLOT_NAME_SIZE, GFP_KERNEL); 366 + if (!slot->hotplug_slot->name) 367 + goto error_info; 371 368 372 - slot->number = i; 369 + slot->hotplug_slot->private = slot; 370 + slot->hotplug_slot->release = &release_slot; 371 + slot->hotplug_slot->ops = &acpi_hotplug_slot_ops; 373 372 374 - slot->hotplug_slot->private = slot; 375 - slot->hotplug_slot->release = &release_slot; 376 - slot->hotplug_slot->ops = &acpi_hotplug_slot_ops; 373 + slot->acpi_slot = acpiphp_slot; 374 + slot->hotplug_slot->info->power_status = acpiphp_get_power_status(slot->acpi_slot); 375 + slot->hotplug_slot->info->attention_status = 0; 376 + slot->hotplug_slot->info->latch_status = acpiphp_get_latch_status(slot->acpi_slot); 377 + slot->hotplug_slot->info->adapter_status = acpiphp_get_adapter_status(slot->acpi_slot); 378 + slot->hotplug_slot->info->max_bus_speed = PCI_SPEED_UNKNOWN; 379 + slot->hotplug_slot->info->cur_bus_speed = PCI_SPEED_UNKNOWN; 377 380 378 - slot->acpi_slot = get_slot_from_id(i); 379 - slot->hotplug_slot->info->power_status = acpiphp_get_power_status(slot->acpi_slot); 380 - slot->hotplug_slot->info->attention_status = 0; 381 - slot->hotplug_slot->info->latch_status = acpiphp_get_latch_status(slot->acpi_slot); 382 - slot->hotplug_slot->info->adapter_status = acpiphp_get_adapter_status(slot->acpi_slot); 383 - slot->hotplug_slot->info->max_bus_speed = PCI_SPEED_UNKNOWN; 384 - slot->hotplug_slot->info->cur_bus_speed = PCI_SPEED_UNKNOWN; 381 + acpiphp_slot->slot = slot; 382 + make_slot_name(slot); 385 383 386 - make_slot_name(slot); 384 + retval = pci_hp_register(slot->hotplug_slot); 385 + if (retval) { 386 + err("pci_hp_register failed with error %d\n", retval); 387 + goto error_name; 388 + } 387 389 388 - retval = pci_hp_register(slot->hotplug_slot); 389 - if (retval) { 390 - err("pci_hp_register failed with error %d\n", retval); 391 - goto error_name; 392 - } 393 - 394 - /* add slot to our internal list */ 395 - list_add(&slot->slot_list, &slot_list); 396 - info("Slot [%s] registered\n", slot->hotplug_slot->name); 397 - } 390 + info("Slot [%s] registered\n", slot->hotplug_slot->name); 398 391 399 392 return 0; 400 393 error_name: ··· 401 412 } 402 413 403 414 404 - static void __exit cleanup_slots (void) 415 + void acpiphp_unregister_hotplug_slot(struct acpiphp_slot *acpiphp_slot) 405 416 { 406 - struct list_head *tmp, *n; 407 - struct slot *slot; 417 + struct slot *slot = acpiphp_slot->slot; 418 + int retval = 0; 408 419 409 - list_for_each_safe (tmp, n, &slot_list) { 410 - /* memory will be freed in release_slot callback */ 411 - slot = list_entry(tmp, struct slot, slot_list); 412 - list_del(&slot->slot_list); 413 - pci_hp_deregister(slot->hotplug_slot); 414 - } 420 + info ("Slot [%s] unregistered\n", slot->hotplug_slot->name); 421 + 422 + retval = pci_hp_deregister(slot->hotplug_slot); 423 + if (retval) 424 + err("pci_hp_deregister failed with error %d\n", retval); 415 425 } 416 426 417 427 ··· 427 439 428 440 /* read all the ACPI info from the system */ 429 441 retval = init_acpi(); 430 - if (retval && !(docking_station)) 431 - return retval; 432 442 433 - return init_slots(); 443 + /* if we have found a docking station, we should 444 + * go ahead and load even if init_acpi has found 445 + * no slots. This handles the case when the _DCK 446 + * method not defined under the actual dock bridge 447 + */ 448 + if (docking_station) 449 + return 0; 450 + else 451 + return retval; 434 452 } 435 453 436 454 437 455 static void __exit acpiphp_exit(void) 438 456 { 439 - cleanup_slots(); 440 457 /* deallocate internal data structures etc. */ 441 458 acpiphp_glue_exit(); 442 459
+23 -25
drivers/pci/hotplug/acpiphp_glue.c
··· 128 128 acpi_handle tmp; 129 129 acpi_status status = AE_OK; 130 130 unsigned long adr, sun; 131 - int device, function; 132 - static int num_slots = 0; /* XXX if we support I/O node hotplug... */ 131 + int device, function, retval; 133 132 134 133 status = acpi_evaluate_integer(handle, "_ADR", NULL, &adr); 135 134 ··· 197 198 198 199 memset(slot, 0, sizeof(struct acpiphp_slot)); 199 200 slot->bridge = bridge; 200 - slot->id = num_slots++; 201 201 slot->device = device; 202 202 slot->sun = sun; 203 203 INIT_LIST_HEAD(&slot->funcs); ··· 210 212 dbg("found ACPI PCI Hotplug slot %d at PCI %04x:%02x:%02x\n", 211 213 slot->sun, pci_domain_nr(bridge->pci_bus), 212 214 bridge->pci_bus->number, slot->device); 215 + retval = acpiphp_register_hotplug_slot(slot); 216 + if (retval) { 217 + warn("acpiphp_register_hotplug_slot failed(err code = 0x%x)\n", retval); 218 + goto err_exit; 219 + } 213 220 } 214 221 215 222 newfunc->slot = slot; ··· 256 253 status = AE_OK; 257 254 258 255 return status; 256 + 257 + err_exit: 258 + bridge->nr_slots--; 259 + bridge->slots = slot->next; 260 + kfree(slot); 261 + kfree(newfunc); 262 + 263 + return AE_OK; 259 264 } 260 265 261 266 ··· 346 335 /* decode ACPI 2.0 _HPP (hot plug parameters) */ 347 336 decode_hpp(bridge); 348 337 338 + /* must be added to the list prior to calling register_slot */ 339 + list_add(&bridge->list, &bridge_list); 340 + 349 341 /* register all slot objects under this bridge */ 350 342 status = acpi_walk_namespace(ACPI_TYPE_DEVICE, bridge->handle, (u32)1, 351 343 register_slot, bridge, NULL); 344 + if (ACPI_FAILURE(status)) { 345 + list_del(&bridge->list); 346 + return; 347 + } 352 348 353 349 /* install notify handler */ 354 350 if (bridge->type != BRIDGE_TYPE_HOST) { ··· 368 350 err("failed to register interrupt notify handler\n"); 369 351 } 370 352 } 371 - 372 - list_add(&bridge->list, &bridge_list); 373 353 } 374 354 375 355 ··· 571 555 list_del(list); 572 556 kfree(func); 573 557 } 558 + acpiphp_unregister_hotplug_slot(slot); 559 + list_del(&slot->funcs); 574 560 kfree(slot); 575 561 slot = next; 576 562 } ··· 1538 1520 return retval; 1539 1521 } 1540 1522 #endif 1541 - 1542 - /* search matching slot from id */ 1543 - struct acpiphp_slot *get_slot_from_id(int id) 1544 - { 1545 - struct list_head *node; 1546 - struct acpiphp_bridge *bridge; 1547 - struct acpiphp_slot *slot; 1548 - 1549 - list_for_each (node, &bridge_list) { 1550 - bridge = (struct acpiphp_bridge *)node; 1551 - for (slot = bridge->slots; slot; slot = slot->next) 1552 - if (slot->id == id) 1553 - return slot; 1554 - } 1555 - 1556 - /* should never happen! */ 1557 - err("%s: no object for id %d\n", __FUNCTION__, id); 1558 - WARN_ON(1); 1559 - return NULL; 1560 - } 1561 1523 1562 1524 1563 1525 /**