summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/pci/hotplug/acpiphp_core.c22
-rw-r--r--drivers/pci/hotplug/cpci_hotplug_core.c14
-rw-r--r--drivers/pci/hotplug/cpqphp_core.c16
-rw-r--r--drivers/pci/hotplug/ibmphp_core.c15
-rw-r--r--drivers/pci/hotplug/ibmphp_ebda.c20
-rw-r--r--drivers/pci/hotplug/pci_hotplug_core.c139
-rw-r--r--drivers/pci/hotplug/pciehp_core.c19
-rw-r--r--drivers/pci/hotplug/pnv_php.c5
-rw-r--r--drivers/pci/hotplug/rpaphp_core.c2
-rw-r--r--drivers/pci/hotplug/rpaphp_slot.c13
-rw-r--r--drivers/pci/hotplug/s390_pci_hpc.c13
-rw-r--r--drivers/pci/hotplug/sgi_hotplug.c9
-rw-r--r--drivers/pci/hotplug/shpchp_core.c20
-rw-r--r--drivers/platform/x86/asus-wmi.c12
-rw-r--r--drivers/platform/x86/eeepc-laptop.c12
-rw-r--r--include/linux/pci_hotplug.h15
16 files changed, 168 insertions, 178 deletions
diff --git a/drivers/pci/hotplug/acpiphp_core.c b/drivers/pci/hotplug/acpiphp_core.c
index 12b5655fd390..ad32ffbc4b91 100644
--- a/drivers/pci/hotplug/acpiphp_core.c
+++ b/drivers/pci/hotplug/acpiphp_core.c
@@ -254,20 +254,6 @@ static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 *value)
254 return 0; 254 return 0;
255} 255}
256 256
257/**
258 * release_slot - free up the memory used by a slot
259 * @hotplug_slot: slot to free
260 */
261static void release_slot(struct hotplug_slot *hotplug_slot)
262{
263 struct slot *slot = hotplug_slot->private;
264
265 pr_debug("%s - physical_slot = %s\n", __func__, slot_name(slot));
266
267 kfree(slot->hotplug_slot);
268 kfree(slot);
269}
270
271/* callback routine to initialize 'struct slot' for each slot */ 257/* callback routine to initialize 'struct slot' for each slot */
272int acpiphp_register_hotplug_slot(struct acpiphp_slot *acpiphp_slot, 258int acpiphp_register_hotplug_slot(struct acpiphp_slot *acpiphp_slot,
273 unsigned int sun) 259 unsigned int sun)
@@ -287,7 +273,6 @@ int acpiphp_register_hotplug_slot(struct acpiphp_slot *acpiphp_slot,
287 slot->hotplug_slot->info = &slot->info; 273 slot->hotplug_slot->info = &slot->info;
288 274
289 slot->hotplug_slot->private = slot; 275 slot->hotplug_slot->private = slot;
290 slot->hotplug_slot->release = &release_slot;
291 slot->hotplug_slot->ops = &acpi_hotplug_slot_ops; 276 slot->hotplug_slot->ops = &acpi_hotplug_slot_ops;
292 277
293 slot->acpi_slot = acpiphp_slot; 278 slot->acpi_slot = acpiphp_slot;
@@ -324,13 +309,12 @@ error:
324void acpiphp_unregister_hotplug_slot(struct acpiphp_slot *acpiphp_slot) 309void acpiphp_unregister_hotplug_slot(struct acpiphp_slot *acpiphp_slot)
325{ 310{
326 struct slot *slot = acpiphp_slot->slot; 311 struct slot *slot = acpiphp_slot->slot;
327 int retval = 0;
328 312
329 pr_info("Slot [%s] unregistered\n", slot_name(slot)); 313 pr_info("Slot [%s] unregistered\n", slot_name(slot));
330 314
331 retval = pci_hp_deregister(slot->hotplug_slot); 315 pci_hp_deregister(slot->hotplug_slot);
332 if (retval) 316 kfree(slot->hotplug_slot);
333 pr_err("pci_hp_deregister failed with error %d\n", retval); 317 kfree(slot);
334} 318}
335 319
336 320
diff --git a/drivers/pci/hotplug/cpci_hotplug_core.c b/drivers/pci/hotplug/cpci_hotplug_core.c
index 07b533adc9df..52a339baf06c 100644
--- a/drivers/pci/hotplug/cpci_hotplug_core.c
+++ b/drivers/pci/hotplug/cpci_hotplug_core.c
@@ -195,10 +195,8 @@ get_latch_status(struct hotplug_slot *hotplug_slot, u8 *value)
195 return 0; 195 return 0;
196} 196}
197 197
198static void release_slot(struct hotplug_slot *hotplug_slot) 198static void release_slot(struct slot *slot)
199{ 199{
200 struct slot *slot = hotplug_slot->private;
201
202 kfree(slot->hotplug_slot->info); 200 kfree(slot->hotplug_slot->info);
203 kfree(slot->hotplug_slot); 201 kfree(slot->hotplug_slot);
204 pci_dev_put(slot->dev); 202 pci_dev_put(slot->dev);
@@ -253,7 +251,6 @@ cpci_hp_register_bus(struct pci_bus *bus, u8 first, u8 last)
253 snprintf(name, SLOT_NAME_SIZE, "%02x:%02x", bus->number, i); 251 snprintf(name, SLOT_NAME_SIZE, "%02x:%02x", bus->number, i);
254 252
255 hotplug_slot->private = slot; 253 hotplug_slot->private = slot;
256 hotplug_slot->release = &release_slot;
257 hotplug_slot->ops = &cpci_hotplug_slot_ops; 254 hotplug_slot->ops = &cpci_hotplug_slot_ops;
258 255
259 /* 256 /*
@@ -308,12 +305,8 @@ cpci_hp_unregister_bus(struct pci_bus *bus)
308 slots--; 305 slots--;
309 306
310 dbg("deregistering slot %s", slot_name(slot)); 307 dbg("deregistering slot %s", slot_name(slot));
311 status = pci_hp_deregister(slot->hotplug_slot); 308 pci_hp_deregister(slot->hotplug_slot);
312 if (status) { 309 release_slot(slot);
313 err("pci_hp_deregister failed with error %d",
314 status);
315 break;
316 }
317 } 310 }
318 } 311 }
319 up_write(&list_rwsem); 312 up_write(&list_rwsem);
@@ -623,6 +616,7 @@ cleanup_slots(void)
623 list_for_each_entry_safe(slot, tmp, &slot_list, slot_list) { 616 list_for_each_entry_safe(slot, tmp, &slot_list, slot_list) {
624 list_del(&slot->slot_list); 617 list_del(&slot->slot_list);
625 pci_hp_deregister(slot->hotplug_slot); 618 pci_hp_deregister(slot->hotplug_slot);
619 release_slot(slot);
626 } 620 }
627cleanup_null: 621cleanup_null:
628 up_write(&list_rwsem); 622 up_write(&list_rwsem);
diff --git a/drivers/pci/hotplug/cpqphp_core.c b/drivers/pci/hotplug/cpqphp_core.c
index 1797e36ec586..5a06636e910a 100644
--- a/drivers/pci/hotplug/cpqphp_core.c
+++ b/drivers/pci/hotplug/cpqphp_core.c
@@ -266,17 +266,6 @@ static void __iomem *get_SMBIOS_entry(void __iomem *smbios_start,
266 return previous; 266 return previous;
267} 267}
268 268
269static void release_slot(struct hotplug_slot *hotplug_slot)
270{
271 struct slot *slot = hotplug_slot->private;
272
273 dbg("%s - physical_slot = %s\n", __func__, slot_name(slot));
274
275 kfree(slot->hotplug_slot->info);
276 kfree(slot->hotplug_slot);
277 kfree(slot);
278}
279
280static int ctrl_slot_cleanup(struct controller *ctrl) 269static int ctrl_slot_cleanup(struct controller *ctrl)
281{ 270{
282 struct slot *old_slot, *next_slot; 271 struct slot *old_slot, *next_slot;
@@ -285,9 +274,11 @@ static int ctrl_slot_cleanup(struct controller *ctrl)
285 ctrl->slot = NULL; 274 ctrl->slot = NULL;
286 275
287 while (old_slot) { 276 while (old_slot) {
288 /* memory will be freed by the release_slot callback */
289 next_slot = old_slot->next; 277 next_slot = old_slot->next;
290 pci_hp_deregister(old_slot->hotplug_slot); 278 pci_hp_deregister(old_slot->hotplug_slot);
279 kfree(old_slot->hotplug_slot->info);
280 kfree(old_slot->hotplug_slot);
281 kfree(old_slot);
291 old_slot = next_slot; 282 old_slot = next_slot;
292 } 283 }
293 284
@@ -678,7 +669,6 @@ static int ctrl_slot_setup(struct controller *ctrl,
678 ((read_slot_enable(ctrl) << 2) >> ctrl_slot) & 0x04; 669 ((read_slot_enable(ctrl) << 2) >> ctrl_slot) & 0x04;
679 670
680 /* register this slot with the hotplug pci core */ 671 /* register this slot with the hotplug pci core */
681 hotplug_slot->release = &release_slot;
682 hotplug_slot->private = slot; 672 hotplug_slot->private = slot;
683 snprintf(name, SLOT_NAME_SIZE, "%u", slot->number); 673 snprintf(name, SLOT_NAME_SIZE, "%u", slot->number);
684 hotplug_slot->ops = &cpqphp_hotplug_slot_ops; 674 hotplug_slot->ops = &cpqphp_hotplug_slot_ops;
diff --git a/drivers/pci/hotplug/ibmphp_core.c b/drivers/pci/hotplug/ibmphp_core.c
index 1869b0411ce0..4ea57e9019f1 100644
--- a/drivers/pci/hotplug/ibmphp_core.c
+++ b/drivers/pci/hotplug/ibmphp_core.c
@@ -673,7 +673,20 @@ static void free_slots(void)
673 673
674 list_for_each_entry_safe(slot_cur, next, &ibmphp_slot_head, 674 list_for_each_entry_safe(slot_cur, next, &ibmphp_slot_head,
675 ibm_slot_list) { 675 ibm_slot_list) {
676 pci_hp_deregister(slot_cur->hotplug_slot); 676 pci_hp_del(slot_cur->hotplug_slot);
677 slot_cur->ctrl = NULL;
678 slot_cur->bus_on = NULL;
679
680 /*
681 * We don't want to actually remove the resources,
682 * since ibmphp_free_resources() will do just that.
683 */
684 ibmphp_unconfigure_card(&slot_cur, -1);
685
686 pci_hp_destroy(slot_cur->hotplug_slot);
687 kfree(slot_cur->hotplug_slot->info);
688 kfree(slot_cur->hotplug_slot);
689 kfree(slot_cur);
677 } 690 }
678 debug("%s -- exit\n", __func__); 691 debug("%s -- exit\n", __func__);
679} 692}
diff --git a/drivers/pci/hotplug/ibmphp_ebda.c b/drivers/pci/hotplug/ibmphp_ebda.c
index 64549aa24c0f..6f8e90e3ec08 100644
--- a/drivers/pci/hotplug/ibmphp_ebda.c
+++ b/drivers/pci/hotplug/ibmphp_ebda.c
@@ -699,25 +699,6 @@ static int fillslotinfo(struct hotplug_slot *hotplug_slot)
699 return rc; 699 return rc;
700} 700}
701 701
702static void release_slot(struct hotplug_slot *hotplug_slot)
703{
704 struct slot *slot;
705
706 if (!hotplug_slot || !hotplug_slot->private)
707 return;
708
709 slot = hotplug_slot->private;
710 kfree(slot->hotplug_slot->info);
711 kfree(slot->hotplug_slot);
712 slot->ctrl = NULL;
713 slot->bus_on = NULL;
714
715 /* we don't want to actually remove the resources, since free_resources will do just that */
716 ibmphp_unconfigure_card(&slot, -1);
717
718 kfree(slot);
719}
720
721static struct pci_driver ibmphp_driver; 702static struct pci_driver ibmphp_driver;
722 703
723/* 704/*
@@ -941,7 +922,6 @@ static int __init ebda_rsrc_controller(void)
941 tmp_slot->hotplug_slot = hp_slot_ptr; 922 tmp_slot->hotplug_slot = hp_slot_ptr;
942 923
943 hp_slot_ptr->private = tmp_slot; 924 hp_slot_ptr->private = tmp_slot;
944 hp_slot_ptr->release = release_slot;
945 925
946 rc = fillslotinfo(hp_slot_ptr); 926 rc = fillslotinfo(hp_slot_ptr);
947 if (rc) 927 if (rc)
diff --git a/drivers/pci/hotplug/pci_hotplug_core.c b/drivers/pci/hotplug/pci_hotplug_core.c
index fd93783a87b0..90fde5f106d8 100644
--- a/drivers/pci/hotplug/pci_hotplug_core.c
+++ b/drivers/pci/hotplug/pci_hotplug_core.c
@@ -396,8 +396,9 @@ static struct hotplug_slot *get_slot_from_name(const char *name)
396 * @owner: caller module owner 396 * @owner: caller module owner
397 * @mod_name: caller module name 397 * @mod_name: caller module name
398 * 398 *
399 * Registers a hotplug slot with the pci hotplug subsystem, which will allow 399 * Prepares a hotplug slot for in-kernel use and immediately publishes it to
400 * userspace interaction to the slot. 400 * user space in one go. Drivers may alternatively carry out the two steps
401 * separately by invoking pci_hp_initialize() and pci_hp_add().
401 * 402 *
402 * Returns 0 if successful, anything else for an error. 403 * Returns 0 if successful, anything else for an error.
403 */ 404 */
@@ -406,54 +407,91 @@ int __pci_hp_register(struct hotplug_slot *slot, struct pci_bus *bus,
406 struct module *owner, const char *mod_name) 407 struct module *owner, const char *mod_name)
407{ 408{
408 int result; 409 int result;
410
411 result = __pci_hp_initialize(slot, bus, devnr, name, owner, mod_name);
412 if (result)
413 return result;
414
415 result = pci_hp_add(slot);
416 if (result)
417 pci_hp_destroy(slot);
418
419 return result;
420}
421EXPORT_SYMBOL_GPL(__pci_hp_register);
422
423/**
424 * __pci_hp_initialize - prepare hotplug slot for in-kernel use
425 * @slot: pointer to the &struct hotplug_slot to initialize
426 * @bus: bus this slot is on
427 * @devnr: slot number
428 * @name: name registered with kobject core
429 * @owner: caller module owner
430 * @mod_name: caller module name
431 *
432 * Allocate and fill in a PCI slot for use by a hotplug driver. Once this has
433 * been called, the driver may invoke hotplug_slot_name() to get the slot's
434 * unique name. The driver must be prepared to handle a ->reset_slot callback
435 * from this point on.
436 *
437 * Returns 0 on success or a negative int on error.
438 */
439int __pci_hp_initialize(struct hotplug_slot *slot, struct pci_bus *bus,
440 int devnr, const char *name, struct module *owner,
441 const char *mod_name)
442{
409 struct pci_slot *pci_slot; 443 struct pci_slot *pci_slot;
410 444
411 if (slot == NULL) 445 if (slot == NULL)
412 return -ENODEV; 446 return -ENODEV;
413 if ((slot->info == NULL) || (slot->ops == NULL)) 447 if ((slot->info == NULL) || (slot->ops == NULL))
414 return -EINVAL; 448 return -EINVAL;
415 if (slot->release == NULL) {
416 dbg("Why are you trying to register a hotplug slot without a proper release function?\n");
417 return -EINVAL;
418 }
419 449
420 slot->ops->owner = owner; 450 slot->ops->owner = owner;
421 slot->ops->mod_name = mod_name; 451 slot->ops->mod_name = mod_name;
422 452
423 mutex_lock(&pci_hp_mutex);
424 /* 453 /*
425 * No problems if we call this interface from both ACPI_PCI_SLOT 454 * No problems if we call this interface from both ACPI_PCI_SLOT
426 * driver and call it here again. If we've already created the 455 * driver and call it here again. If we've already created the
427 * pci_slot, the interface will simply bump the refcount. 456 * pci_slot, the interface will simply bump the refcount.
428 */ 457 */
429 pci_slot = pci_create_slot(bus, devnr, name, slot); 458 pci_slot = pci_create_slot(bus, devnr, name, slot);
430 if (IS_ERR(pci_slot)) { 459 if (IS_ERR(pci_slot))
431 result = PTR_ERR(pci_slot); 460 return PTR_ERR(pci_slot);
432 goto out;
433 }
434 461
435 slot->pci_slot = pci_slot; 462 slot->pci_slot = pci_slot;
436 pci_slot->hotplug = slot; 463 pci_slot->hotplug = slot;
464 return 0;
465}
466EXPORT_SYMBOL_GPL(__pci_hp_initialize);
437 467
438 list_add(&slot->slot_list, &pci_hotplug_slot_list); 468/**
469 * pci_hp_add - publish hotplug slot to user space
470 * @slot: pointer to the &struct hotplug_slot to publish
471 *
472 * Make a hotplug slot's sysfs interface available and inform user space of its
473 * addition by sending a uevent. The hotplug driver must be prepared to handle
474 * all &struct hotplug_slot_ops callbacks from this point on.
475 *
476 * Returns 0 on success or a negative int on error.
477 */
478int pci_hp_add(struct hotplug_slot *slot)
479{
480 struct pci_slot *pci_slot = slot->pci_slot;
481 int result;
439 482
440 result = fs_add_slot(pci_slot); 483 result = fs_add_slot(pci_slot);
441 if (result) 484 if (result)
442 goto err_list_del; 485 return result;
443 486
444 kobject_uevent(&pci_slot->kobj, KOBJ_ADD); 487 kobject_uevent(&pci_slot->kobj, KOBJ_ADD);
445 dbg("Added slot %s to the list\n", name); 488 mutex_lock(&pci_hp_mutex);
446 goto out; 489 list_add(&slot->slot_list, &pci_hotplug_slot_list);
447
448err_list_del:
449 list_del(&slot->slot_list);
450 pci_slot->hotplug = NULL;
451 pci_destroy_slot(pci_slot);
452out:
453 mutex_unlock(&pci_hp_mutex); 490 mutex_unlock(&pci_hp_mutex);
454 return result; 491 dbg("Added slot %s to the list\n", hotplug_slot_name(slot));
492 return 0;
455} 493}
456EXPORT_SYMBOL_GPL(__pci_hp_register); 494EXPORT_SYMBOL_GPL(pci_hp_add);
457 495
458/** 496/**
459 * pci_hp_deregister - deregister a hotplug_slot with the PCI hotplug subsystem 497 * pci_hp_deregister - deregister a hotplug_slot with the PCI hotplug subsystem
@@ -464,35 +502,62 @@ EXPORT_SYMBOL_GPL(__pci_hp_register);
464 * 502 *
465 * Returns 0 if successful, anything else for an error. 503 * Returns 0 if successful, anything else for an error.
466 */ 504 */
467int pci_hp_deregister(struct hotplug_slot *slot) 505void pci_hp_deregister(struct hotplug_slot *slot)
506{
507 pci_hp_del(slot);
508 pci_hp_destroy(slot);
509}
510EXPORT_SYMBOL_GPL(pci_hp_deregister);
511
512/**
513 * pci_hp_del - unpublish hotplug slot from user space
514 * @slot: pointer to the &struct hotplug_slot to unpublish
515 *
516 * Remove a hotplug slot's sysfs interface.
517 *
518 * Returns 0 on success or a negative int on error.
519 */
520void pci_hp_del(struct hotplug_slot *slot)
468{ 521{
469 struct hotplug_slot *temp; 522 struct hotplug_slot *temp;
470 struct pci_slot *pci_slot;
471 523
472 if (!slot) 524 if (WARN_ON(!slot))
473 return -ENODEV; 525 return;
474 526
475 mutex_lock(&pci_hp_mutex); 527 mutex_lock(&pci_hp_mutex);
476 temp = get_slot_from_name(hotplug_slot_name(slot)); 528 temp = get_slot_from_name(hotplug_slot_name(slot));
477 if (temp != slot) { 529 if (WARN_ON(temp != slot)) {
478 mutex_unlock(&pci_hp_mutex); 530 mutex_unlock(&pci_hp_mutex);
479 return -ENODEV; 531 return;
480 } 532 }
481 533
482 list_del(&slot->slot_list); 534 list_del(&slot->slot_list);
483 535 mutex_unlock(&pci_hp_mutex);
484 pci_slot = slot->pci_slot;
485 fs_remove_slot(pci_slot);
486 dbg("Removed slot %s from the list\n", hotplug_slot_name(slot)); 536 dbg("Removed slot %s from the list\n", hotplug_slot_name(slot));
537 fs_remove_slot(slot->pci_slot);
538}
539EXPORT_SYMBOL_GPL(pci_hp_del);
540
541/**
542 * pci_hp_destroy - remove hotplug slot from in-kernel use
543 * @slot: pointer to the &struct hotplug_slot to destroy
544 *
545 * Destroy a PCI slot used by a hotplug driver. Once this has been called,
546 * the driver may no longer invoke hotplug_slot_name() to get the slot's
547 * unique name. The driver no longer needs to handle a ->reset_slot callback
548 * from this point on.
549 *
550 * Returns 0 on success or a negative int on error.
551 */
552void pci_hp_destroy(struct hotplug_slot *slot)
553{
554 struct pci_slot *pci_slot = slot->pci_slot;
487 555
488 slot->release(slot); 556 slot->pci_slot = NULL;
489 pci_slot->hotplug = NULL; 557 pci_slot->hotplug = NULL;
490 pci_destroy_slot(pci_slot); 558 pci_destroy_slot(pci_slot);
491 mutex_unlock(&pci_hp_mutex);
492
493 return 0;
494} 559}
495EXPORT_SYMBOL_GPL(pci_hp_deregister); 560EXPORT_SYMBOL_GPL(pci_hp_destroy);
496 561
497/** 562/**
498 * pci_hp_change_slot_info - changes the slot's information structure in the core 563 * pci_hp_change_slot_info - changes the slot's information structure in the core
diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c
index b360645377c2..37d8f81e548f 100644
--- a/drivers/pci/hotplug/pciehp_core.c
+++ b/drivers/pci/hotplug/pciehp_core.c
@@ -56,17 +56,6 @@ static int get_latch_status(struct hotplug_slot *slot, u8 *value);
56static int get_adapter_status(struct hotplug_slot *slot, u8 *value); 56static int get_adapter_status(struct hotplug_slot *slot, u8 *value);
57static int reset_slot(struct hotplug_slot *slot, int probe); 57static int reset_slot(struct hotplug_slot *slot, int probe);
58 58
59/**
60 * release_slot - free up the memory used by a slot
61 * @hotplug_slot: slot to free
62 */
63static void release_slot(struct hotplug_slot *hotplug_slot)
64{
65 kfree(hotplug_slot->ops);
66 kfree(hotplug_slot->info);
67 kfree(hotplug_slot);
68}
69
70static int init_slot(struct controller *ctrl) 59static int init_slot(struct controller *ctrl)
71{ 60{
72 struct slot *slot = ctrl->slot; 61 struct slot *slot = ctrl->slot;
@@ -107,7 +96,6 @@ static int init_slot(struct controller *ctrl)
107 /* register this slot with the hotplug pci core */ 96 /* register this slot with the hotplug pci core */
108 hotplug->info = info; 97 hotplug->info = info;
109 hotplug->private = slot; 98 hotplug->private = slot;
110 hotplug->release = &release_slot;
111 hotplug->ops = ops; 99 hotplug->ops = ops;
112 slot->hotplug_slot = hotplug; 100 slot->hotplug_slot = hotplug;
113 snprintf(name, SLOT_NAME_SIZE, "%u", PSN(ctrl)); 101 snprintf(name, SLOT_NAME_SIZE, "%u", PSN(ctrl));
@@ -127,7 +115,12 @@ out:
127 115
128static void cleanup_slot(struct controller *ctrl) 116static void cleanup_slot(struct controller *ctrl)
129{ 117{
130 pci_hp_deregister(ctrl->slot->hotplug_slot); 118 struct hotplug_slot *hotplug_slot = ctrl->slot->hotplug_slot;
119
120 pci_hp_deregister(hotplug_slot);
121 kfree(hotplug_slot->ops);
122 kfree(hotplug_slot->info);
123 kfree(hotplug_slot);
131} 124}
132 125
133/* 126/*
diff --git a/drivers/pci/hotplug/pnv_php.c b/drivers/pci/hotplug/pnv_php.c
index 6c2e8d7307c6..3276a5e4c430 100644
--- a/drivers/pci/hotplug/pnv_php.c
+++ b/drivers/pci/hotplug/pnv_php.c
@@ -538,9 +538,8 @@ static struct hotplug_slot_ops php_slot_ops = {
538 .disable_slot = pnv_php_disable_slot, 538 .disable_slot = pnv_php_disable_slot,
539}; 539};
540 540
541static void pnv_php_release(struct hotplug_slot *slot) 541static void pnv_php_release(struct pnv_php_slot *php_slot)
542{ 542{
543 struct pnv_php_slot *php_slot = slot->private;
544 unsigned long flags; 543 unsigned long flags;
545 544
546 /* Remove from global or child list */ 545 /* Remove from global or child list */
@@ -596,7 +595,6 @@ static struct pnv_php_slot *pnv_php_alloc_slot(struct device_node *dn)
596 php_slot->power_state_check = false; 595 php_slot->power_state_check = false;
597 php_slot->slot.ops = &php_slot_ops; 596 php_slot->slot.ops = &php_slot_ops;
598 php_slot->slot.info = &php_slot->slot_info; 597 php_slot->slot.info = &php_slot->slot_info;
599 php_slot->slot.release = pnv_php_release;
600 php_slot->slot.private = php_slot; 598 php_slot->slot.private = php_slot;
601 599
602 INIT_LIST_HEAD(&php_slot->children); 600 INIT_LIST_HEAD(&php_slot->children);
@@ -924,6 +922,7 @@ static void pnv_php_unregister_one(struct device_node *dn)
924 922
925 php_slot->state = PNV_PHP_STATE_OFFLINE; 923 php_slot->state = PNV_PHP_STATE_OFFLINE;
926 pci_hp_deregister(&php_slot->slot); 924 pci_hp_deregister(&php_slot->slot);
925 pnv_php_release(php_slot);
927 pnv_php_put_slot(php_slot); 926 pnv_php_put_slot(php_slot);
928} 927}
929 928
diff --git a/drivers/pci/hotplug/rpaphp_core.c b/drivers/pci/hotplug/rpaphp_core.c
index fb5e0845429d..857c358b727b 100644
--- a/drivers/pci/hotplug/rpaphp_core.c
+++ b/drivers/pci/hotplug/rpaphp_core.c
@@ -404,13 +404,13 @@ static void __exit cleanup_slots(void)
404 /* 404 /*
405 * Unregister all of our slots with the pci_hotplug subsystem, 405 * Unregister all of our slots with the pci_hotplug subsystem,
406 * and free up all memory that we had allocated. 406 * and free up all memory that we had allocated.
407 * memory will be freed in release_slot callback.
408 */ 407 */
409 408
410 list_for_each_entry_safe(slot, next, &rpaphp_slot_head, 409 list_for_each_entry_safe(slot, next, &rpaphp_slot_head,
411 rpaphp_slot_list) { 410 rpaphp_slot_list) {
412 list_del(&slot->rpaphp_slot_list); 411 list_del(&slot->rpaphp_slot_list);
413 pci_hp_deregister(slot->hotplug_slot); 412 pci_hp_deregister(slot->hotplug_slot);
413 dealloc_slot_struct(slot);
414 } 414 }
415 return; 415 return;
416} 416}
diff --git a/drivers/pci/hotplug/rpaphp_slot.c b/drivers/pci/hotplug/rpaphp_slot.c
index 3840a2075e6a..b916c8e4372d 100644
--- a/drivers/pci/hotplug/rpaphp_slot.c
+++ b/drivers/pci/hotplug/rpaphp_slot.c
@@ -19,12 +19,6 @@
19#include "rpaphp.h" 19#include "rpaphp.h"
20 20
21/* free up the memory used by a slot */ 21/* free up the memory used by a slot */
22static void rpaphp_release_slot(struct hotplug_slot *hotplug_slot)
23{
24 struct slot *slot = (struct slot *) hotplug_slot->private;
25 dealloc_slot_struct(slot);
26}
27
28void dealloc_slot_struct(struct slot *slot) 22void dealloc_slot_struct(struct slot *slot)
29{ 23{
30 kfree(slot->hotplug_slot->info); 24 kfree(slot->hotplug_slot->info);
@@ -56,7 +50,6 @@ struct slot *alloc_slot_struct(struct device_node *dn,
56 slot->power_domain = power_domain; 50 slot->power_domain = power_domain;
57 slot->hotplug_slot->private = slot; 51 slot->hotplug_slot->private = slot;
58 slot->hotplug_slot->ops = &rpaphp_hotplug_slot_ops; 52 slot->hotplug_slot->ops = &rpaphp_hotplug_slot_ops;
59 slot->hotplug_slot->release = &rpaphp_release_slot;
60 53
61 return (slot); 54 return (slot);
62 55
@@ -90,10 +83,8 @@ int rpaphp_deregister_slot(struct slot *slot)
90 __func__, slot->name); 83 __func__, slot->name);
91 84
92 list_del(&slot->rpaphp_slot_list); 85 list_del(&slot->rpaphp_slot_list);
93 86 pci_hp_deregister(php_slot);
94 retval = pci_hp_deregister(php_slot); 87 dealloc_slot_struct(slot);
95 if (retval)
96 err("Problem unregistering a slot %s\n", slot->name);
97 88
98 dbg("%s - Exit: rc[%d]\n", __func__, retval); 89 dbg("%s - Exit: rc[%d]\n", __func__, retval);
99 return retval; 90 return retval;
diff --git a/drivers/pci/hotplug/s390_pci_hpc.c b/drivers/pci/hotplug/s390_pci_hpc.c
index ffdc2977395d..93b5341d282c 100644
--- a/drivers/pci/hotplug/s390_pci_hpc.c
+++ b/drivers/pci/hotplug/s390_pci_hpc.c
@@ -130,15 +130,6 @@ static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 *value)
130 return 0; 130 return 0;
131} 131}
132 132
133static void release_slot(struct hotplug_slot *hotplug_slot)
134{
135 struct slot *slot = hotplug_slot->private;
136
137 kfree(slot->hotplug_slot->info);
138 kfree(slot->hotplug_slot);
139 kfree(slot);
140}
141
142static struct hotplug_slot_ops s390_hotplug_slot_ops = { 133static struct hotplug_slot_ops s390_hotplug_slot_ops = {
143 .enable_slot = enable_slot, 134 .enable_slot = enable_slot,
144 .disable_slot = disable_slot, 135 .disable_slot = disable_slot,
@@ -175,7 +166,6 @@ int zpci_init_slot(struct zpci_dev *zdev)
175 hotplug_slot->info = info; 166 hotplug_slot->info = info;
176 167
177 hotplug_slot->ops = &s390_hotplug_slot_ops; 168 hotplug_slot->ops = &s390_hotplug_slot_ops;
178 hotplug_slot->release = &release_slot;
179 169
180 get_power_status(hotplug_slot, &info->power_status); 170 get_power_status(hotplug_slot, &info->power_status);
181 get_adapter_status(hotplug_slot, &info->adapter_status); 171 get_adapter_status(hotplug_slot, &info->adapter_status);
@@ -209,5 +199,8 @@ void zpci_exit_slot(struct zpci_dev *zdev)
209 continue; 199 continue;
210 list_del(&slot->slot_list); 200 list_del(&slot->slot_list);
211 pci_hp_deregister(slot->hotplug_slot); 201 pci_hp_deregister(slot->hotplug_slot);
202 kfree(slot->hotplug_slot->info);
203 kfree(slot->hotplug_slot);
204 kfree(slot);
212 } 205 }
213} 206}
diff --git a/drivers/pci/hotplug/sgi_hotplug.c b/drivers/pci/hotplug/sgi_hotplug.c
index 78b6bdbb3a39..babd23409f61 100644
--- a/drivers/pci/hotplug/sgi_hotplug.c
+++ b/drivers/pci/hotplug/sgi_hotplug.c
@@ -628,7 +628,6 @@ static int sn_hotplug_slot_register(struct pci_bus *pci_bus)
628 goto alloc_err; 628 goto alloc_err;
629 } 629 }
630 bss_hotplug_slot->ops = &sn_hotplug_slot_ops; 630 bss_hotplug_slot->ops = &sn_hotplug_slot_ops;
631 bss_hotplug_slot->release = &sn_release_slot;
632 631
633 rc = pci_hp_register(bss_hotplug_slot, pci_bus, device, name); 632 rc = pci_hp_register(bss_hotplug_slot, pci_bus, device, name);
634 if (rc) 633 if (rc)
@@ -656,8 +655,10 @@ alloc_err:
656 sn_release_slot(bss_hotplug_slot); 655 sn_release_slot(bss_hotplug_slot);
657 656
658 /* destroy anything else on the list */ 657 /* destroy anything else on the list */
659 while ((bss_hotplug_slot = sn_hp_destroy())) 658 while ((bss_hotplug_slot = sn_hp_destroy())) {
660 pci_hp_deregister(bss_hotplug_slot); 659 pci_hp_deregister(bss_hotplug_slot);
660 sn_release_slot(bss_hotplug_slot);
661 }
661 662
662 return rc; 663 return rc;
663} 664}
@@ -703,8 +704,10 @@ static void __exit sn_pci_hotplug_exit(void)
703{ 704{
704 struct hotplug_slot *bss_hotplug_slot; 705 struct hotplug_slot *bss_hotplug_slot;
705 706
706 while ((bss_hotplug_slot = sn_hp_destroy())) 707 while ((bss_hotplug_slot = sn_hp_destroy())) {
707 pci_hp_deregister(bss_hotplug_slot); 708 pci_hp_deregister(bss_hotplug_slot);
709 sn_release_slot(bss_hotplug_slot);
710 }
708 711
709 if (!list_empty(&sn_hp_list)) 712 if (!list_empty(&sn_hp_list))
710 printk(KERN_ERR "%s: internal list is not empty\n", __FILE__); 713 printk(KERN_ERR "%s: internal list is not empty\n", __FILE__);
diff --git a/drivers/pci/hotplug/shpchp_core.c b/drivers/pci/hotplug/shpchp_core.c
index 8e3c6ce12f31..97cee23f3d51 100644
--- a/drivers/pci/hotplug/shpchp_core.c
+++ b/drivers/pci/hotplug/shpchp_core.c
@@ -61,22 +61,6 @@ static struct hotplug_slot_ops shpchp_hotplug_slot_ops = {
61 .get_adapter_status = get_adapter_status, 61 .get_adapter_status = get_adapter_status,
62}; 62};
63 63
64/**
65 * release_slot - free up the memory used by a slot
66 * @hotplug_slot: slot to free
67 */
68static void release_slot(struct hotplug_slot *hotplug_slot)
69{
70 struct slot *slot = hotplug_slot->private;
71
72 ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n",
73 __func__, slot_name(slot));
74
75 kfree(slot->hotplug_slot->info);
76 kfree(slot->hotplug_slot);
77 kfree(slot);
78}
79
80static int init_slots(struct controller *ctrl) 64static int init_slots(struct controller *ctrl)
81{ 65{
82 struct slot *slot; 66 struct slot *slot;
@@ -125,7 +109,6 @@ static int init_slots(struct controller *ctrl)
125 109
126 /* register this slot with the hotplug pci core */ 110 /* register this slot with the hotplug pci core */
127 hotplug_slot->private = slot; 111 hotplug_slot->private = slot;
128 hotplug_slot->release = &release_slot;
129 snprintf(name, SLOT_NAME_SIZE, "%d", slot->number); 112 snprintf(name, SLOT_NAME_SIZE, "%d", slot->number);
130 hotplug_slot->ops = &shpchp_hotplug_slot_ops; 113 hotplug_slot->ops = &shpchp_hotplug_slot_ops;
131 114
@@ -171,6 +154,9 @@ void cleanup_slots(struct controller *ctrl)
171 cancel_delayed_work(&slot->work); 154 cancel_delayed_work(&slot->work);
172 destroy_workqueue(slot->wq); 155 destroy_workqueue(slot->wq);
173 pci_hp_deregister(slot->hotplug_slot); 156 pci_hp_deregister(slot->hotplug_slot);
157 kfree(slot->hotplug_slot->info);
158 kfree(slot->hotplug_slot);
159 kfree(slot);
174 } 160 }
175} 161}
176 162
diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c
index 3d523ca64694..d67f32a29bb4 100644
--- a/drivers/platform/x86/asus-wmi.c
+++ b/drivers/platform/x86/asus-wmi.c
@@ -858,12 +858,6 @@ static int asus_get_adapter_status(struct hotplug_slot *hotplug_slot,
858 return 0; 858 return 0;
859} 859}
860 860
861static void asus_cleanup_pci_hotplug(struct hotplug_slot *hotplug_slot)
862{
863 kfree(hotplug_slot->info);
864 kfree(hotplug_slot);
865}
866
867static struct hotplug_slot_ops asus_hotplug_slot_ops = { 861static struct hotplug_slot_ops asus_hotplug_slot_ops = {
868 .owner = THIS_MODULE, 862 .owner = THIS_MODULE,
869 .get_adapter_status = asus_get_adapter_status, 863 .get_adapter_status = asus_get_adapter_status,
@@ -905,7 +899,6 @@ static int asus_setup_pci_hotplug(struct asus_wmi *asus)
905 goto error_info; 899 goto error_info;
906 900
907 asus->hotplug_slot->private = asus; 901 asus->hotplug_slot->private = asus;
908 asus->hotplug_slot->release = &asus_cleanup_pci_hotplug;
909 asus->hotplug_slot->ops = &asus_hotplug_slot_ops; 902 asus->hotplug_slot->ops = &asus_hotplug_slot_ops;
910 asus_get_adapter_status(asus->hotplug_slot, 903 asus_get_adapter_status(asus->hotplug_slot,
911 &asus->hotplug_slot->info->adapter_status); 904 &asus->hotplug_slot->info->adapter_status);
@@ -1051,8 +1044,11 @@ static void asus_wmi_rfkill_exit(struct asus_wmi *asus)
1051 * asus_unregister_rfkill_notifier() 1044 * asus_unregister_rfkill_notifier()
1052 */ 1045 */
1053 asus_rfkill_hotplug(asus); 1046 asus_rfkill_hotplug(asus);
1054 if (asus->hotplug_slot) 1047 if (asus->hotplug_slot) {
1055 pci_hp_deregister(asus->hotplug_slot); 1048 pci_hp_deregister(asus->hotplug_slot);
1049 kfree(asus->hotplug_slot->info);
1050 kfree(asus->hotplug_slot);
1051 }
1056 if (asus->hotplug_workqueue) 1052 if (asus->hotplug_workqueue)
1057 destroy_workqueue(asus->hotplug_workqueue); 1053 destroy_workqueue(asus->hotplug_workqueue);
1058 1054
diff --git a/drivers/platform/x86/eeepc-laptop.c b/drivers/platform/x86/eeepc-laptop.c
index 4c38904a8a32..a4bbf6ecd1f0 100644
--- a/drivers/platform/x86/eeepc-laptop.c
+++ b/drivers/platform/x86/eeepc-laptop.c
@@ -726,12 +726,6 @@ static int eeepc_get_adapter_status(struct hotplug_slot *hotplug_slot,
726 return 0; 726 return 0;
727} 727}
728 728
729static void eeepc_cleanup_pci_hotplug(struct hotplug_slot *hotplug_slot)
730{
731 kfree(hotplug_slot->info);
732 kfree(hotplug_slot);
733}
734
735static struct hotplug_slot_ops eeepc_hotplug_slot_ops = { 729static struct hotplug_slot_ops eeepc_hotplug_slot_ops = {
736 .owner = THIS_MODULE, 730 .owner = THIS_MODULE,
737 .get_adapter_status = eeepc_get_adapter_status, 731 .get_adapter_status = eeepc_get_adapter_status,
@@ -758,7 +752,6 @@ static int eeepc_setup_pci_hotplug(struct eeepc_laptop *eeepc)
758 goto error_info; 752 goto error_info;
759 753
760 eeepc->hotplug_slot->private = eeepc; 754 eeepc->hotplug_slot->private = eeepc;
761 eeepc->hotplug_slot->release = &eeepc_cleanup_pci_hotplug;
762 eeepc->hotplug_slot->ops = &eeepc_hotplug_slot_ops; 755 eeepc->hotplug_slot->ops = &eeepc_hotplug_slot_ops;
763 eeepc_get_adapter_status(eeepc->hotplug_slot, 756 eeepc_get_adapter_status(eeepc->hotplug_slot,
764 &eeepc->hotplug_slot->info->adapter_status); 757 &eeepc->hotplug_slot->info->adapter_status);
@@ -837,8 +830,11 @@ static void eeepc_rfkill_exit(struct eeepc_laptop *eeepc)
837 eeepc->wlan_rfkill = NULL; 830 eeepc->wlan_rfkill = NULL;
838 } 831 }
839 832
840 if (eeepc->hotplug_slot) 833 if (eeepc->hotplug_slot) {
841 pci_hp_deregister(eeepc->hotplug_slot); 834 pci_hp_deregister(eeepc->hotplug_slot);
835 kfree(eeepc->hotplug_slot->info);
836 kfree(eeepc->hotplug_slot);
837 }
842 838
843 if (eeepc->bluetooth_rfkill) { 839 if (eeepc->bluetooth_rfkill) {
844 rfkill_unregister(eeepc->bluetooth_rfkill); 840 rfkill_unregister(eeepc->bluetooth_rfkill);
diff --git a/include/linux/pci_hotplug.h b/include/linux/pci_hotplug.h
index cf5e22103f68..a6d6650a0490 100644
--- a/include/linux/pci_hotplug.h
+++ b/include/linux/pci_hotplug.h
@@ -80,15 +80,12 @@ struct hotplug_slot_info {
80 * @ops: pointer to the &struct hotplug_slot_ops to be used for this slot 80 * @ops: pointer to the &struct hotplug_slot_ops to be used for this slot
81 * @info: pointer to the &struct hotplug_slot_info for the initial values for 81 * @info: pointer to the &struct hotplug_slot_info for the initial values for
82 * this slot. 82 * this slot.
83 * @release: called during pci_hp_deregister to free memory allocated in a
84 * hotplug_slot structure.
85 * @private: used by the hotplug pci controller driver to store whatever it 83 * @private: used by the hotplug pci controller driver to store whatever it
86 * needs. 84 * needs.
87 */ 85 */
88struct hotplug_slot { 86struct hotplug_slot {
89 struct hotplug_slot_ops *ops; 87 struct hotplug_slot_ops *ops;
90 struct hotplug_slot_info *info; 88 struct hotplug_slot_info *info;
91 void (*release) (struct hotplug_slot *slot);
92 void *private; 89 void *private;
93 90
94 /* Variables below this are for use only by the hotplug pci core. */ 91 /* Variables below this are for use only by the hotplug pci core. */
@@ -104,13 +101,23 @@ static inline const char *hotplug_slot_name(const struct hotplug_slot *slot)
104int __pci_hp_register(struct hotplug_slot *slot, struct pci_bus *pbus, int nr, 101int __pci_hp_register(struct hotplug_slot *slot, struct pci_bus *pbus, int nr,
105 const char *name, struct module *owner, 102 const char *name, struct module *owner,
106 const char *mod_name); 103 const char *mod_name);
107int pci_hp_deregister(struct hotplug_slot *slot); 104int __pci_hp_initialize(struct hotplug_slot *slot, struct pci_bus *bus, int nr,
105 const char *name, struct module *owner,
106 const char *mod_name);
107int pci_hp_add(struct hotplug_slot *slot);
108
109void pci_hp_del(struct hotplug_slot *slot);
110void pci_hp_destroy(struct hotplug_slot *slot);
111void pci_hp_deregister(struct hotplug_slot *slot);
112
108int __must_check pci_hp_change_slot_info(struct hotplug_slot *slot, 113int __must_check pci_hp_change_slot_info(struct hotplug_slot *slot,
109 struct hotplug_slot_info *info); 114 struct hotplug_slot_info *info);
110 115
111/* use a define to avoid include chaining to get THIS_MODULE & friends */ 116/* use a define to avoid include chaining to get THIS_MODULE & friends */
112#define pci_hp_register(slot, pbus, devnr, name) \ 117#define pci_hp_register(slot, pbus, devnr, name) \
113 __pci_hp_register(slot, pbus, devnr, name, THIS_MODULE, KBUILD_MODNAME) 118 __pci_hp_register(slot, pbus, devnr, name, THIS_MODULE, KBUILD_MODNAME)
119#define pci_hp_initialize(slot, bus, nr, name) \
120 __pci_hp_initialize(slot, bus, nr, name, THIS_MODULE, KBUILD_MODNAME)
114 121
115/* PCI Setting Record (Type 0) */ 122/* PCI Setting Record (Type 0) */
116struct hpp_type0 { 123struct hpp_type0 {