aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>2014-06-12 07:36:27 -0400
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2014-06-12 07:36:27 -0400
commit9d674f2107b7dc801db9780f5f6b645f4905372f (patch)
tree624465152808cdfff5a8c6ffae9fdee63056b1af
parent9b758d4e293deb282dd4870503e4d2778cf69df0 (diff)
parent882d18a702c66404fcb62b84748f719f9b47441c (diff)
Merge branch 'acpi-hotplug'
* acpi-hotplug: ACPI / hotplug / PCI: Add hotplug contexts to PCI host bridges
-rw-r--r--drivers/pci/hotplug/acpiphp.h10
-rw-r--r--drivers/pci/hotplug/acpiphp_glue.c60
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
145struct acpiphp_root_context {
146 struct acpi_hotplug_context hp;
147 struct acpiphp_bridge *root_bridge;
148};
149
150static 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
374static struct acpiphp_bridge *acpiphp_dev_to_bridge(struct acpi_device *adev) 374static 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
932void 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