summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLukas Wunner <lukas@wunner.de>2018-07-19 18:27:43 -0400
committerBjorn Helgaas <helgaas@kernel.org>2018-07-23 18:04:13 -0400
commit51bbf9bee34ff5d4006d266f24a54dc9c1669eb5 (patch)
treed1bfff3b0bb97baa9f9969005c6c69d25b763eee
parent55a6b7a6576d6cba77bb2ce2bfb2126df83df58a (diff)
PCI: hotplug: Demidlayer registration with the core
When a hotplug driver calls pci_hp_register(), all steps necessary for registration are carried out in one go, including creation of a kobject and addition to sysfs. That's a problem for pciehp once it's converted to enable/disable the slot exclusively from the IRQ thread: The thread needs to be spawned after creation of the kobject (because it uses the kobject's name), but before addition to sysfs (because it will handle enable/disable requests submitted via sysfs). pci_hp_deregister() does offer a ->release callback that's invoked after deletion from sysfs and before destruction of the kobject. But because pci_hp_register() doesn't offer a counterpart, hotplug drivers' ->probe and ->remove code becomes asymmetric, which is error prone as recently discovered use-after-free bugs in pciehp's ->remove hook have shown. In a sense, this appears to be a case of the midlayer antipattern: "The core thesis of the "midlayer mistake" is that midlayers are bad and should not exist. That common functionality which it is so tempting to put in a midlayer should instead be provided as library routines which can [be] used, augmented, or ignored by each bottom level driver independently. Thus every subsystem that supports multiple implementations (or drivers) should provide a very thin top layer which calls directly into the bottom layer drivers, and a rich library of support code that eases the implementation of those drivers. This library is available to, but not forced upon, those drivers." -- Neil Brown (2009), https://lwn.net/Articles/336262/ The presence of midlayer traits in the PCI hotplug core might be ascribed to its age: When it was introduced in February 2002, the blessings of a library approach might not have been well known: https://git.kernel.org/tglx/history/c/a8a2069f432c For comparison, the driver core does offer split functions for creating a kobject (device_initialize()) and addition to sysfs (device_add()) as an alternative to carrying out everything at once (device_register()). This was introduced in October 2002: https://git.kernel.org/tglx/history/c/8b290eb19962 The odd ->release callback in the PCI hotplug core was added in 2003: https://git.kernel.org/tglx/history/c/69f8d663b595 Clearly, a library approach would not force every hotplug driver to implement a ->release callback, but rather allow the driver to remove the sysfs files, release its data structures and finally destroy the kobject. Alternatively, a driver may choose to remove everything with pci_hp_deregister(), then release its data structures. To this end, offer drivers pci_hp_initialize() and pci_hp_add() as a split-up version of pci_hp_register(). Likewise, offer pci_hp_del() and pci_hp_destroy() as a split-up version of pci_hp_deregister(). Eliminate the ->release callback and move its code into each driver's teardown routine. Declare pci_hp_deregister() void, in keeping with the usual kernel pattern that enablement can fail, but disablement cannot. It only returned an error if the caller passed in a NULL pointer or a slot which has never or is no longer registered or is sharing its name with another slot. Those would be bugs, so WARN about them. Few hotplug drivers actually checked the return value and those that did only printed a useless error message to dmesg. Remove that. For most drivers the conversion was straightforward since it doesn't matter whether the code in the ->release callback is executed before or after destruction of the kobject. But in the case of ibmphp, it was unclear to me whether setting slot_cur->ctrl and slot_cur->bus_on to NULL needs to happen before the kobject is destroyed, so I erred on the side of caution and ensured that the order stays the same. Another nontrivial case is pnv_php, I've found the list and kref logic difficult to understand, however my impression was that it is safe to delete the list element and drop the references until after the kobject is destroyed. Signed-off-by: Lukas Wunner <lukas@wunner.de> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Acked-by: Andy Shevchenko <andy.shevchenko@gmail.com> # drivers/platform/x86 Cc: Rafael J. Wysocki <rjw@rjwysocki.net> Cc: Len Brown <lenb@kernel.org> Cc: Scott Murray <scott@spiteful.org> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org> Cc: Paul Mackerras <paulus@samba.org> Cc: Michael Ellerman <mpe@ellerman.id.au> Cc: Gavin Shan <gwshan@linux.vnet.ibm.com> Cc: Sebastian Ott <sebott@linux.vnet.ibm.com> Cc: Gerald Schaefer <gerald.schaefer@de.ibm.com> Cc: Corentin Chary <corentin.chary@gmail.com> Cc: Darren Hart <dvhart@infradead.org> Cc: Andy Shevchenko <andy@infradead.org>
-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 {