diff options
author | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2014-06-12 07:36:27 -0400 |
---|---|---|
committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2014-06-12 07:36:27 -0400 |
commit | 9d674f2107b7dc801db9780f5f6b645f4905372f (patch) | |
tree | 624465152808cdfff5a8c6ffae9fdee63056b1af | |
parent | 9b758d4e293deb282dd4870503e4d2778cf69df0 (diff) | |
parent | 882d18a702c66404fcb62b84748f719f9b47441c (diff) |
Merge branch 'acpi-hotplug'
* acpi-hotplug:
ACPI / hotplug / PCI: Add hotplug contexts to PCI host bridges
-rw-r--r-- | drivers/pci/hotplug/acpiphp.h | 10 | ||||
-rw-r--r-- | drivers/pci/hotplug/acpiphp_glue.c | 60 |
2 files changed, 52 insertions, 18 deletions
diff --git a/drivers/pci/hotplug/acpiphp.h b/drivers/pci/hotplug/acpiphp.h index 2b859249303b..b0e61bf261a7 100644 --- a/drivers/pci/hotplug/acpiphp.h +++ b/drivers/pci/hotplug/acpiphp.h | |||
@@ -142,6 +142,16 @@ static inline acpi_handle func_to_handle(struct acpiphp_func *func) | |||
142 | return func_to_acpi_device(func)->handle; | 142 | return func_to_acpi_device(func)->handle; |
143 | } | 143 | } |
144 | 144 | ||
145 | struct acpiphp_root_context { | ||
146 | struct acpi_hotplug_context hp; | ||
147 | struct acpiphp_bridge *root_bridge; | ||
148 | }; | ||
149 | |||
150 | static inline struct acpiphp_root_context *to_acpiphp_root_context(struct acpi_hotplug_context *hp) | ||
151 | { | ||
152 | return container_of(hp, struct acpiphp_root_context, hp); | ||
153 | } | ||
154 | |||
145 | /* | 155 | /* |
146 | * struct acpiphp_attention_info - device specific attention registration | 156 | * struct acpiphp_attention_info - device specific attention registration |
147 | * | 157 | * |
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index 75e178330215..91aa3d780138 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c | |||
@@ -373,17 +373,13 @@ static acpi_status acpiphp_add_context(acpi_handle handle, u32 lvl, void *data, | |||
373 | 373 | ||
374 | static struct acpiphp_bridge *acpiphp_dev_to_bridge(struct acpi_device *adev) | 374 | static struct acpiphp_bridge *acpiphp_dev_to_bridge(struct acpi_device *adev) |
375 | { | 375 | { |
376 | struct acpiphp_context *context; | ||
377 | struct acpiphp_bridge *bridge = NULL; | 376 | struct acpiphp_bridge *bridge = NULL; |
378 | 377 | ||
379 | acpi_lock_hp_context(); | 378 | acpi_lock_hp_context(); |
380 | context = acpiphp_get_context(adev); | 379 | if (adev->hp) { |
381 | if (context) { | 380 | bridge = to_acpiphp_root_context(adev->hp)->root_bridge; |
382 | bridge = context->bridge; | ||
383 | if (bridge) | 381 | if (bridge) |
384 | get_bridge(bridge); | 382 | get_bridge(bridge); |
385 | |||
386 | acpiphp_put_context(context); | ||
387 | } | 383 | } |
388 | acpi_unlock_hp_context(); | 384 | acpi_unlock_hp_context(); |
389 | return bridge; | 385 | return bridge; |
@@ -881,7 +877,17 @@ void acpiphp_enumerate_slots(struct pci_bus *bus) | |||
881 | */ | 877 | */ |
882 | get_device(&bus->dev); | 878 | get_device(&bus->dev); |
883 | 879 | ||
884 | if (!pci_is_root_bus(bridge->pci_bus)) { | 880 | acpi_lock_hp_context(); |
881 | if (pci_is_root_bus(bridge->pci_bus)) { | ||
882 | struct acpiphp_root_context *root_context; | ||
883 | |||
884 | root_context = kzalloc(sizeof(*root_context), GFP_KERNEL); | ||
885 | if (!root_context) | ||
886 | goto err; | ||
887 | |||
888 | root_context->root_bridge = bridge; | ||
889 | acpi_set_hp_context(adev, &root_context->hp, NULL, NULL, NULL); | ||
890 | } else { | ||
885 | struct acpiphp_context *context; | 891 | struct acpiphp_context *context; |
886 | 892 | ||
887 | /* | 893 | /* |
@@ -890,21 +896,16 @@ void acpiphp_enumerate_slots(struct pci_bus *bus) | |||
890 | * parent is going to be handled by pciehp, in which case this | 896 | * parent is going to be handled by pciehp, in which case this |
891 | * bridge is not interesting to us either. | 897 | * bridge is not interesting to us either. |
892 | */ | 898 | */ |
893 | acpi_lock_hp_context(); | ||
894 | context = acpiphp_get_context(adev); | 899 | context = acpiphp_get_context(adev); |
895 | if (!context) { | 900 | if (!context) |
896 | acpi_unlock_hp_context(); | 901 | goto err; |
897 | put_device(&bus->dev); | 902 | |
898 | pci_dev_put(bridge->pci_dev); | ||
899 | kfree(bridge); | ||
900 | return; | ||
901 | } | ||
902 | bridge->context = context; | 903 | bridge->context = context; |
903 | context->bridge = bridge; | 904 | context->bridge = bridge; |
904 | /* Get a reference to the parent bridge. */ | 905 | /* Get a reference to the parent bridge. */ |
905 | get_bridge(context->func.parent); | 906 | get_bridge(context->func.parent); |
906 | acpi_unlock_hp_context(); | ||
907 | } | 907 | } |
908 | acpi_unlock_hp_context(); | ||
908 | 909 | ||
909 | /* Must be added to the list prior to calling acpiphp_add_context(). */ | 910 | /* Must be added to the list prior to calling acpiphp_add_context(). */ |
910 | mutex_lock(&bridge_mutex); | 911 | mutex_lock(&bridge_mutex); |
@@ -919,6 +920,30 @@ void acpiphp_enumerate_slots(struct pci_bus *bus) | |||
919 | cleanup_bridge(bridge); | 920 | cleanup_bridge(bridge); |
920 | put_bridge(bridge); | 921 | put_bridge(bridge); |
921 | } | 922 | } |
923 | return; | ||
924 | |||
925 | err: | ||
926 | acpi_unlock_hp_context(); | ||
927 | put_device(&bus->dev); | ||
928 | pci_dev_put(bridge->pci_dev); | ||
929 | kfree(bridge); | ||
930 | } | ||
931 | |||
932 | void acpiphp_drop_bridge(struct acpiphp_bridge *bridge) | ||
933 | { | ||
934 | if (pci_is_root_bus(bridge->pci_bus)) { | ||
935 | struct acpiphp_root_context *root_context; | ||
936 | struct acpi_device *adev; | ||
937 | |||
938 | acpi_lock_hp_context(); | ||
939 | adev = ACPI_COMPANION(bridge->pci_bus->bridge); | ||
940 | root_context = to_acpiphp_root_context(adev->hp); | ||
941 | adev->hp = NULL; | ||
942 | acpi_unlock_hp_context(); | ||
943 | kfree(root_context); | ||
944 | } | ||
945 | cleanup_bridge(bridge); | ||
946 | put_bridge(bridge); | ||
922 | } | 947 | } |
923 | 948 | ||
924 | /** | 949 | /** |
@@ -936,8 +961,7 @@ void acpiphp_remove_slots(struct pci_bus *bus) | |||
936 | list_for_each_entry(bridge, &bridge_list, list) | 961 | list_for_each_entry(bridge, &bridge_list, list) |
937 | if (bridge->pci_bus == bus) { | 962 | if (bridge->pci_bus == bus) { |
938 | mutex_unlock(&bridge_mutex); | 963 | mutex_unlock(&bridge_mutex); |
939 | cleanup_bridge(bridge); | 964 | acpiphp_drop_bridge(bridge); |
940 | put_bridge(bridge); | ||
941 | return; | 965 | return; |
942 | } | 966 | } |
943 | 967 | ||