diff options
| -rw-r--r-- | drivers/pci/hotplug/pci_hotplug_core.c | 51 |
1 files changed, 28 insertions, 23 deletions
diff --git a/drivers/pci/hotplug/pci_hotplug_core.c b/drivers/pci/hotplug/pci_hotplug_core.c index 1cdeb642fdcf..e71524825180 100644 --- a/drivers/pci/hotplug/pci_hotplug_core.c +++ b/drivers/pci/hotplug/pci_hotplug_core.c | |||
| @@ -37,6 +37,7 @@ | |||
| 37 | #include <linux/init.h> | 37 | #include <linux/init.h> |
| 38 | #include <linux/mount.h> | 38 | #include <linux/mount.h> |
| 39 | #include <linux/namei.h> | 39 | #include <linux/namei.h> |
| 40 | #include <linux/mutex.h> | ||
| 40 | #include <linux/pci.h> | 41 | #include <linux/pci.h> |
| 41 | #include <linux/pci_hotplug.h> | 42 | #include <linux/pci_hotplug.h> |
| 42 | #include <asm/uaccess.h> | 43 | #include <asm/uaccess.h> |
| @@ -61,7 +62,7 @@ static int debug; | |||
| 61 | ////////////////////////////////////////////////////////////////// | 62 | ////////////////////////////////////////////////////////////////// |
| 62 | 63 | ||
| 63 | static LIST_HEAD(pci_hotplug_slot_list); | 64 | static LIST_HEAD(pci_hotplug_slot_list); |
| 64 | static DEFINE_SPINLOCK(pci_hotplug_slot_list_lock); | 65 | static DEFINE_MUTEX(pci_hp_mutex); |
| 65 | 66 | ||
| 66 | /* these strings match up with the values in pci_bus_speed */ | 67 | /* these strings match up with the values in pci_bus_speed */ |
| 67 | static char *pci_bus_speed_strings[] = { | 68 | static char *pci_bus_speed_strings[] = { |
| @@ -530,16 +531,12 @@ static struct hotplug_slot *get_slot_from_name (const char *name) | |||
| 530 | struct hotplug_slot *slot; | 531 | struct hotplug_slot *slot; |
| 531 | struct list_head *tmp; | 532 | struct list_head *tmp; |
| 532 | 533 | ||
| 533 | spin_lock(&pci_hotplug_slot_list_lock); | ||
| 534 | list_for_each (tmp, &pci_hotplug_slot_list) { | 534 | list_for_each (tmp, &pci_hotplug_slot_list) { |
| 535 | slot = list_entry (tmp, struct hotplug_slot, slot_list); | 535 | slot = list_entry (tmp, struct hotplug_slot, slot_list); |
| 536 | if (strcmp(slot->name, name) == 0) | 536 | if (strcmp(slot->name, name) == 0) |
| 537 | goto out; | 537 | return slot; |
| 538 | } | 538 | } |
| 539 | slot = NULL; | 539 | return NULL; |
| 540 | out: | ||
| 541 | spin_unlock(&pci_hotplug_slot_list_lock); | ||
| 542 | return slot; | ||
| 543 | } | 540 | } |
| 544 | 541 | ||
| 545 | /** | 542 | /** |
| @@ -570,9 +567,13 @@ int pci_hp_register(struct hotplug_slot *slot, struct pci_bus *bus, int slot_nr, | |||
| 570 | return -EINVAL; | 567 | return -EINVAL; |
| 571 | } | 568 | } |
| 572 | 569 | ||
| 570 | mutex_lock(&pci_hp_mutex); | ||
| 571 | |||
| 573 | /* Check if we have already registered a slot with the same name. */ | 572 | /* Check if we have already registered a slot with the same name. */ |
| 574 | if (get_slot_from_name(name)) | 573 | if (get_slot_from_name(name)) { |
| 575 | return -EEXIST; | 574 | result = -EEXIST; |
| 575 | goto out; | ||
| 576 | } | ||
| 576 | 577 | ||
| 577 | /* | 578 | /* |
| 578 | * No problems if we call this interface from both ACPI_PCI_SLOT | 579 | * No problems if we call this interface from both ACPI_PCI_SLOT |
| @@ -580,13 +581,15 @@ int pci_hp_register(struct hotplug_slot *slot, struct pci_bus *bus, int slot_nr, | |||
| 580 | * pci_slot, the interface will simply bump the refcount. | 581 | * pci_slot, the interface will simply bump the refcount. |
| 581 | */ | 582 | */ |
| 582 | pci_slot = pci_create_slot(bus, slot_nr, name, slot); | 583 | pci_slot = pci_create_slot(bus, slot_nr, name, slot); |
| 583 | if (IS_ERR(pci_slot)) | 584 | if (IS_ERR(pci_slot)) { |
| 584 | return PTR_ERR(pci_slot); | 585 | result = PTR_ERR(pci_slot); |
| 586 | goto cleanup; | ||
| 587 | } | ||
| 585 | 588 | ||
| 586 | if (pci_slot->hotplug) { | 589 | if (pci_slot->hotplug) { |
| 587 | dbg("%s: already claimed\n", __func__); | 590 | dbg("%s: already claimed\n", __func__); |
| 588 | pci_destroy_slot(pci_slot); | 591 | result = -EBUSY; |
| 589 | return -EBUSY; | 592 | goto cleanup; |
| 590 | } | 593 | } |
| 591 | 594 | ||
| 592 | slot->pci_slot = pci_slot; | 595 | slot->pci_slot = pci_slot; |
| @@ -597,21 +600,21 @@ int pci_hp_register(struct hotplug_slot *slot, struct pci_bus *bus, int slot_nr, | |||
| 597 | */ | 600 | */ |
| 598 | if (strcmp(kobject_name(&pci_slot->kobj), name)) { | 601 | if (strcmp(kobject_name(&pci_slot->kobj), name)) { |
| 599 | result = kobject_rename(&pci_slot->kobj, name); | 602 | result = kobject_rename(&pci_slot->kobj, name); |
| 600 | if (result) { | 603 | if (result) |
| 601 | pci_destroy_slot(pci_slot); | 604 | goto cleanup; |
| 602 | return result; | ||
| 603 | } | ||
| 604 | } | 605 | } |
| 605 | 606 | ||
| 606 | spin_lock(&pci_hotplug_slot_list_lock); | ||
| 607 | list_add(&slot->slot_list, &pci_hotplug_slot_list); | 607 | list_add(&slot->slot_list, &pci_hotplug_slot_list); |
| 608 | spin_unlock(&pci_hotplug_slot_list_lock); | ||
| 609 | 608 | ||
| 610 | result = fs_add_slot(pci_slot); | 609 | result = fs_add_slot(pci_slot); |
| 611 | kobject_uevent(&pci_slot->kobj, KOBJ_ADD); | 610 | kobject_uevent(&pci_slot->kobj, KOBJ_ADD); |
| 612 | dbg("Added slot %s to the list\n", name); | 611 | dbg("Added slot %s to the list\n", name); |
| 613 | 612 | out: | |
| 613 | mutex_unlock(&pci_hp_mutex); | ||
| 614 | return result; | 614 | return result; |
| 615 | cleanup: | ||
| 616 | pci_destroy_slot(pci_slot); | ||
| 617 | goto out; | ||
| 615 | } | 618 | } |
| 616 | 619 | ||
| 617 | /** | 620 | /** |
| @@ -631,13 +634,14 @@ int pci_hp_deregister(struct hotplug_slot *hotplug) | |||
| 631 | if (!hotplug) | 634 | if (!hotplug) |
| 632 | return -ENODEV; | 635 | return -ENODEV; |
| 633 | 636 | ||
| 637 | mutex_lock(&pci_hp_mutex); | ||
| 634 | temp = get_slot_from_name(hotplug->name); | 638 | temp = get_slot_from_name(hotplug->name); |
| 635 | if (temp != hotplug) | 639 | if (temp != hotplug) { |
| 640 | mutex_unlock(&pci_hp_mutex); | ||
| 636 | return -ENODEV; | 641 | return -ENODEV; |
| 642 | } | ||
| 637 | 643 | ||
| 638 | spin_lock(&pci_hotplug_slot_list_lock); | ||
| 639 | list_del(&hotplug->slot_list); | 644 | list_del(&hotplug->slot_list); |
| 640 | spin_unlock(&pci_hotplug_slot_list_lock); | ||
| 641 | 645 | ||
| 642 | slot = hotplug->pci_slot; | 646 | slot = hotplug->pci_slot; |
| 643 | fs_remove_slot(slot); | 647 | fs_remove_slot(slot); |
| @@ -646,6 +650,7 @@ int pci_hp_deregister(struct hotplug_slot *hotplug) | |||
| 646 | hotplug->release(hotplug); | 650 | hotplug->release(hotplug); |
| 647 | slot->hotplug = NULL; | 651 | slot->hotplug = NULL; |
| 648 | pci_destroy_slot(slot); | 652 | pci_destroy_slot(slot); |
| 653 | mutex_unlock(&pci_hp_mutex); | ||
| 649 | 654 | ||
| 650 | return 0; | 655 | return 0; |
| 651 | } | 656 | } |
