aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/hotplug/acpiphp_glue.c
diff options
context:
space:
mode:
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>2013-07-13 17:27:24 -0400
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2013-07-22 22:00:21 -0400
commit43e5c091c797616170b11f4a1b32ea8c81ad0100 (patch)
treea6d08e9db5144a78d782ef643e0e35ec1ee03b99 /drivers/pci/hotplug/acpiphp_glue.c
parentc8ebcf1ff91a8f64b09c4df0ee21ae80a953c39c (diff)
ACPI / hotplug / PCI: Merge hotplug event handling functions
There are separate handling event functions for hotplug bridges and for hotplug functions, but they may be combined into one common hotplug event handling function which simplifies the code slightly. That also allows a theoretical bug to be dealt with which in principle may occur if a hotplug bridge is on a dock station, because in that case the bridge-specific notification should be used instead of the function-specific one, but the dock station always uses the latter. Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Tested-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Diffstat (limited to 'drivers/pci/hotplug/acpiphp_glue.c')
-rw-r--r--drivers/pci/hotplug/acpiphp_glue.c152
1 files changed, 65 insertions, 87 deletions
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c
index b5a98f4baa3a..e2f9ea03aece 100644
--- a/drivers/pci/hotplug/acpiphp_glue.c
+++ b/drivers/pci/hotplug/acpiphp_glue.c
@@ -62,7 +62,7 @@ static DEFINE_MUTEX(acpiphp_context_lock);
62static void handle_hotplug_event(acpi_handle handle, u32 type, void *data); 62static void handle_hotplug_event(acpi_handle handle, u32 type, void *data);
63static void acpiphp_sanitize_bus(struct pci_bus *bus); 63static void acpiphp_sanitize_bus(struct pci_bus *bus);
64static void acpiphp_set_hpp_values(struct pci_bus *bus); 64static void acpiphp_set_hpp_values(struct pci_bus *bus);
65static void hotplug_event_func(acpi_handle handle, u32 type, void *context); 65static void hotplug_event(acpi_handle handle, u32 type, void *data);
66static void free_bridge(struct kref *kref); 66static void free_bridge(struct kref *kref);
67 67
68/* callback routine to check for the existence of a pci dock device */ 68/* callback routine to check for the existence of a pci dock device */
@@ -201,8 +201,8 @@ static void free_bridge(struct kref *kref)
201 */ 201 */
202static void post_dock_fixups(acpi_handle not_used, u32 event, void *data) 202static void post_dock_fixups(acpi_handle not_used, u32 event, void *data)
203{ 203{
204 struct acpiphp_func *func = data; 204 struct acpiphp_context *context = data;
205 struct pci_bus *bus = func->slot->bridge->pci_bus; 205 struct pci_bus *bus = context->func->slot->bridge->pci_bus;
206 u32 buses; 206 u32 buses;
207 207
208 if (!bus->self) 208 if (!bus->self)
@@ -227,7 +227,7 @@ static void post_dock_fixups(acpi_handle not_used, u32 event, void *data)
227 227
228static const struct acpi_dock_ops acpiphp_dock_ops = { 228static const struct acpi_dock_ops acpiphp_dock_ops = {
229 .fixup = post_dock_fixups, 229 .fixup = post_dock_fixups,
230 .handler = hotplug_event_func, 230 .handler = hotplug_event,
231}; 231};
232 232
233/* Check whether the PCI device is managed by native PCIe hotplug driver */ 233/* Check whether the PCI device is managed by native PCIe hotplug driver */
@@ -261,16 +261,16 @@ static bool device_is_managed_by_native_pciehp(struct pci_dev *pdev)
261 261
262static void acpiphp_dock_init(void *data) 262static void acpiphp_dock_init(void *data)
263{ 263{
264 struct acpiphp_func *func = data; 264 struct acpiphp_context *context = data;
265 265
266 get_bridge(func->slot->bridge); 266 get_bridge(context->func->slot->bridge);
267} 267}
268 268
269static void acpiphp_dock_release(void *data) 269static void acpiphp_dock_release(void *data)
270{ 270{
271 struct acpiphp_func *func = data; 271 struct acpiphp_context *context = data;
272 272
273 put_bridge(func->slot->bridge); 273 put_bridge(context->func->slot->bridge);
274} 274}
275 275
276/* callback routine to register each ACPI PCI slot object */ 276/* callback routine to register each ACPI PCI slot object */
@@ -406,7 +406,7 @@ static acpi_status register_slot(acpi_handle handle, u32 lvl, void *data,
406 */ 406 */
407 newfunc->flags &= ~FUNC_HAS_EJ0; 407 newfunc->flags &= ~FUNC_HAS_EJ0;
408 if (register_hotplug_dock_device(handle, 408 if (register_hotplug_dock_device(handle,
409 &acpiphp_dock_ops, newfunc, 409 &acpiphp_dock_ops, context,
410 acpiphp_dock_init, acpiphp_dock_release)) 410 acpiphp_dock_init, acpiphp_dock_release))
411 dbg("failed to register dock device\n"); 411 dbg("failed to register dock device\n");
412 } 412 }
@@ -987,24 +987,26 @@ void acpiphp_check_host_bridge(acpi_handle handle)
987 ACPI_UINT32_MAX, check_sub_bridges, NULL, NULL, NULL); 987 ACPI_UINT32_MAX, check_sub_bridges, NULL, NULL, NULL);
988} 988}
989 989
990static void _handle_hotplug_event_bridge(struct work_struct *work) 990static void hotplug_event(acpi_handle handle, u32 type, void *data)
991{ 991{
992 struct acpiphp_context *context; 992 struct acpiphp_context *context = data;
993 struct acpiphp_bridge *bridge; 993 struct acpiphp_bridge *bridge;
994 struct acpiphp_func *func;
994 char objname[64]; 995 char objname[64];
995 struct acpi_buffer buffer = { .length = sizeof(objname), 996 struct acpi_buffer buffer = { .length = sizeof(objname),
996 .pointer = objname }; 997 .pointer = objname };
997 struct acpi_hp_work *hp_work;
998 acpi_handle handle;
999 u32 type;
1000 998
1001 hp_work = container_of(work, struct acpi_hp_work, work); 999 mutex_lock(&acpiphp_context_lock);
1002 handle = hp_work->handle;
1003 type = hp_work->type;
1004 context = hp_work->context;
1005 bridge = context->bridge; 1000 bridge = context->bridge;
1001 if (bridge)
1002 get_bridge(bridge);
1006 1003
1007 acpi_scan_lock_acquire(); 1004 /*
1005 * If context->func is not NULL, we are holding a reference to its
1006 * parent bridge, so it won't go away until we drop that reference.
1007 */
1008 func = context->func;
1009 mutex_unlock(&acpiphp_context_lock);
1008 1010
1009 acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer); 1011 acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
1010 1012
@@ -1013,15 +1015,24 @@ static void _handle_hotplug_event_bridge(struct work_struct *work)
1013 /* bus re-enumerate */ 1015 /* bus re-enumerate */
1014 dbg("%s: Bus check notify on %s\n", __func__, objname); 1016 dbg("%s: Bus check notify on %s\n", __func__, objname);
1015 dbg("%s: re-enumerating slots under %s\n", __func__, objname); 1017 dbg("%s: re-enumerating slots under %s\n", __func__, objname);
1016 acpiphp_check_bridge(bridge); 1018 if (bridge) {
1017 acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, 1019 acpiphp_check_bridge(bridge);
1018 ACPI_UINT32_MAX, check_sub_bridges, NULL, NULL, NULL); 1020 acpi_walk_namespace(ACPI_TYPE_DEVICE, handle,
1021 ACPI_UINT32_MAX, check_sub_bridges,
1022 NULL, NULL, NULL);
1023 } else {
1024 acpiphp_enable_slot(func->slot);
1025 }
1019 break; 1026 break;
1020 1027
1021 case ACPI_NOTIFY_DEVICE_CHECK: 1028 case ACPI_NOTIFY_DEVICE_CHECK:
1022 /* device check */ 1029 /* device check */
1023 dbg("%s: Device check notify on %s\n", __func__, objname); 1030 dbg("%s: Device check notify on %s\n", __func__, objname);
1024 acpiphp_check_bridge(bridge); 1031 if (bridge)
1032 acpiphp_check_bridge(bridge);
1033 else
1034 acpiphp_check_bridge(func->slot->bridge);
1035
1025 break; 1036 break;
1026 1037
1027 case ACPI_NOTIFY_DEVICE_WAKE: 1038 case ACPI_NOTIFY_DEVICE_WAKE:
@@ -1032,12 +1043,15 @@ static void _handle_hotplug_event_bridge(struct work_struct *work)
1032 case ACPI_NOTIFY_EJECT_REQUEST: 1043 case ACPI_NOTIFY_EJECT_REQUEST:
1033 /* request device eject */ 1044 /* request device eject */
1034 dbg("%s: Device eject notify on %s\n", __func__, objname); 1045 dbg("%s: Device eject notify on %s\n", __func__, objname);
1035 if ((bridge->flags & BRIDGE_HAS_EJ0) && bridge->func) { 1046 if (!func)
1036 struct acpiphp_slot *slot; 1047 break;
1037 slot = bridge->func->slot; 1048
1038 if (!acpiphp_disable_slot(slot)) 1049 if (bridge && !(bridge->flags & BRIDGE_HAS_EJ0))
1039 acpiphp_eject_slot(slot); 1050 break;
1040 } 1051
1052 if (!(acpiphp_disable_slot(func->slot)))
1053 acpiphp_eject_slot(func->slot);
1054
1041 break; 1055 break;
1042 1056
1043 case ACPI_NOTIFY_FREQUENCY_MISMATCH: 1057 case ACPI_NOTIFY_FREQUENCY_MISMATCH:
@@ -1056,56 +1070,16 @@ static void _handle_hotplug_event_bridge(struct work_struct *work)
1056 break; 1070 break;
1057 1071
1058 default: 1072 default:
1059 warn("notify_handler: unknown event type 0x%x for %s\n", type, objname); 1073 warn("notify_handler: unknown event type 0x%x for %s\n", type,
1074 objname);
1060 break; 1075 break;
1061 } 1076 }
1062 1077
1063 acpi_scan_lock_release(); 1078 if (bridge)
1064 kfree(hp_work); /* allocated in handle_hotplug_event_bridge */ 1079 put_bridge(bridge);
1065 put_bridge(bridge);
1066}
1067
1068static void hotplug_event_func(acpi_handle handle, u32 type, void *context)
1069{
1070 struct acpiphp_func *func = context;
1071 char objname[64];
1072 struct acpi_buffer buffer = { .length = sizeof(objname),
1073 .pointer = objname };
1074
1075 acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
1076
1077 switch (type) {
1078 case ACPI_NOTIFY_BUS_CHECK:
1079 /* bus re-enumerate */
1080 dbg("%s: Bus check notify on %s\n", __func__, objname);
1081 acpiphp_enable_slot(func->slot);
1082 break;
1083
1084 case ACPI_NOTIFY_DEVICE_CHECK:
1085 /* device check : re-enumerate from parent bus */
1086 dbg("%s: Device check notify on %s\n", __func__, objname);
1087 acpiphp_check_bridge(func->slot->bridge);
1088 break;
1089
1090 case ACPI_NOTIFY_DEVICE_WAKE:
1091 /* wake event */
1092 dbg("%s: Device wake notify on %s\n", __func__, objname);
1093 break;
1094
1095 case ACPI_NOTIFY_EJECT_REQUEST:
1096 /* request device eject */
1097 dbg("%s: Device eject notify on %s\n", __func__, objname);
1098 if (!(acpiphp_disable_slot(func->slot)))
1099 acpiphp_eject_slot(func->slot);
1100 break;
1101
1102 default:
1103 warn("notify_handler: unknown event type 0x%x for %s\n", type, objname);
1104 break;
1105 }
1106} 1080}
1107 1081
1108static void _handle_hotplug_event_func(struct work_struct *work) 1082static void hotplug_event_work(struct work_struct *work)
1109{ 1083{
1110 struct acpiphp_context *context; 1084 struct acpiphp_context *context;
1111 struct acpi_hp_work *hp_work; 1085 struct acpi_hp_work *hp_work;
@@ -1114,11 +1088,18 @@ static void _handle_hotplug_event_func(struct work_struct *work)
1114 context = hp_work->context; 1088 context = hp_work->context;
1115 acpi_scan_lock_acquire(); 1089 acpi_scan_lock_acquire();
1116 1090
1117 hotplug_event_func(hp_work->handle, hp_work->type, context->func); 1091 hotplug_event(hp_work->handle, hp_work->type, context);
1118 1092
1119 acpi_scan_lock_release(); 1093 acpi_scan_lock_release();
1120 kfree(hp_work); /* allocated in handle_hotplug_event_func */ 1094 kfree(hp_work); /* allocated in handle_hotplug_event() */
1121 put_bridge(context->func->slot->bridge); 1095
1096 mutex_lock(&acpiphp_context_lock);
1097 if (context->func)
1098 put_bridge(context->func->slot->bridge);
1099 else
1100 acpiphp_put_context(context);
1101
1102 mutex_unlock(&acpiphp_context_lock);
1122} 1103}
1123 1104
1124/** 1105/**
@@ -1132,22 +1113,19 @@ static void _handle_hotplug_event_func(struct work_struct *work)
1132static void handle_hotplug_event(acpi_handle handle, u32 type, void *data) 1113static void handle_hotplug_event(acpi_handle handle, u32 type, void *data)
1133{ 1114{
1134 struct acpiphp_context *context; 1115 struct acpiphp_context *context;
1135 void (*work_func)(struct work_struct *work) = NULL;
1136 1116
1137 mutex_lock(&acpiphp_context_lock); 1117 mutex_lock(&acpiphp_context_lock);
1138 context = acpiphp_get_context(handle); 1118 context = acpiphp_get_context(handle);
1139 if (context) { 1119 if (context) {
1140 if (context->bridge) { 1120 if (context->func) {
1141 get_bridge(context->bridge);
1142 work_func = _handle_hotplug_event_bridge;
1143 } else if (context->func) {
1144 get_bridge(context->func->slot->bridge); 1121 get_bridge(context->func->slot->bridge);
1145 work_func = _handle_hotplug_event_func; 1122 acpiphp_put_context(context);
1123 } else if (!context->bridge) {
1124 acpiphp_put_context(context);
1125 context = NULL;
1146 } 1126 }
1147 acpiphp_put_context(context);
1148 } 1127 }
1149 mutex_unlock(&acpiphp_context_lock); 1128 mutex_unlock(&acpiphp_context_lock);
1150
1151 /* 1129 /*
1152 * Currently the code adds all hotplug events to the kacpid_wq 1130 * Currently the code adds all hotplug events to the kacpid_wq
1153 * queue when it should add hotplug events to the kacpi_hotplug_wq. 1131 * queue when it should add hotplug events to the kacpi_hotplug_wq.
@@ -1156,8 +1134,8 @@ static void handle_hotplug_event(acpi_handle handle, u32 type, void *data)
1156 * For now just re-add this work to the kacpi_hotplug_wq so we 1134 * For now just re-add this work to the kacpi_hotplug_wq so we
1157 * don't deadlock on hotplug actions. 1135 * don't deadlock on hotplug actions.
1158 */ 1136 */
1159 if (work_func) 1137 if (context)
1160 alloc_acpi_hp_work(handle, type, context, work_func); 1138 alloc_acpi_hp_work(handle, type, context, hotplug_event_work);
1161} 1139}
1162 1140
1163/* 1141/*