diff options
author | Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com> | 2008-10-20 19:40:57 -0400 |
---|---|---|
committer | Jesse Barnes <jbarnes@virtuousgeek.org> | 2008-10-22 19:42:38 -0400 |
commit | 95cb9093960b6249fdbe7417bf513a1358aaa51a (patch) | |
tree | 8cfe1c98235ff947685940b328e73c39809751fe /drivers | |
parent | 828f37683e6d3ab5912989df0d04201db7ad798e (diff) |
PCI Hotplug: serialize pci_hp_register and pci_hp_deregister
Convert the pci_hotplug_slot_list_lock, which only protected the
list of hotplug slots, to a pci_hp_mutex which now protects both
interfaces.
Signed-off-by: Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com>
Signed-off-by: Alex Chiang <achiang@hp.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Diffstat (limited to 'drivers')
-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 | } |