diff options
Diffstat (limited to 'drivers/acpi/acpica/evmisc.c')
-rw-r--r-- | drivers/acpi/acpica/evmisc.c | 191 |
1 files changed, 70 insertions, 121 deletions
diff --git a/drivers/acpi/acpica/evmisc.c b/drivers/acpi/acpica/evmisc.c index 51ef9f5e002d..51f537937c1f 100644 --- a/drivers/acpi/acpica/evmisc.c +++ b/drivers/acpi/acpica/evmisc.c | |||
@@ -56,7 +56,7 @@ static void ACPI_SYSTEM_XFACE acpi_ev_notify_dispatch(void *context); | |||
56 | * | 56 | * |
57 | * FUNCTION: acpi_ev_is_notify_object | 57 | * FUNCTION: acpi_ev_is_notify_object |
58 | * | 58 | * |
59 | * PARAMETERS: Node - Node to check | 59 | * PARAMETERS: node - Node to check |
60 | * | 60 | * |
61 | * RETURN: TRUE if notifies allowed on this object | 61 | * RETURN: TRUE if notifies allowed on this object |
62 | * | 62 | * |
@@ -86,7 +86,7 @@ u8 acpi_ev_is_notify_object(struct acpi_namespace_node *node) | |||
86 | * | 86 | * |
87 | * FUNCTION: acpi_ev_queue_notify_request | 87 | * FUNCTION: acpi_ev_queue_notify_request |
88 | * | 88 | * |
89 | * PARAMETERS: Node - NS node for the notified object | 89 | * PARAMETERS: node - NS node for the notified object |
90 | * notify_value - Value from the Notify() request | 90 | * notify_value - Value from the Notify() request |
91 | * | 91 | * |
92 | * RETURN: Status | 92 | * RETURN: Status |
@@ -101,102 +101,77 @@ acpi_ev_queue_notify_request(struct acpi_namespace_node * node, | |||
101 | u32 notify_value) | 101 | u32 notify_value) |
102 | { | 102 | { |
103 | union acpi_operand_object *obj_desc; | 103 | union acpi_operand_object *obj_desc; |
104 | union acpi_operand_object *handler_obj = NULL; | 104 | union acpi_operand_object *handler_list_head = NULL; |
105 | union acpi_generic_state *notify_info; | 105 | union acpi_generic_state *info; |
106 | u8 handler_list_id = 0; | ||
106 | acpi_status status = AE_OK; | 107 | acpi_status status = AE_OK; |
107 | 108 | ||
108 | ACPI_FUNCTION_NAME(ev_queue_notify_request); | 109 | ACPI_FUNCTION_NAME(ev_queue_notify_request); |
109 | 110 | ||
110 | /* | 111 | /* Are Notifies allowed on this object? */ |
111 | * For value 0x03 (Ejection Request), may need to run a device method. | ||
112 | * For value 0x02 (Device Wake), if _PRW exists, may need to run | ||
113 | * the _PS0 method. | ||
114 | * For value 0x80 (Status Change) on the power button or sleep button, | ||
115 | * initiate soft-off or sleep operation. | ||
116 | * | ||
117 | * For all cases, simply dispatch the notify to the handler. | ||
118 | */ | ||
119 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | ||
120 | "Dispatching Notify on [%4.4s] (%s) Value 0x%2.2X (%s) Node %p\n", | ||
121 | acpi_ut_get_node_name(node), | ||
122 | acpi_ut_get_type_name(node->type), notify_value, | ||
123 | acpi_ut_get_notify_name(notify_value), node)); | ||
124 | 112 | ||
125 | /* Get the notify object attached to the NS Node */ | 113 | if (!acpi_ev_is_notify_object(node)) { |
126 | 114 | return (AE_TYPE); | |
127 | obj_desc = acpi_ns_get_attached_object(node); | 115 | } |
128 | if (obj_desc) { | ||
129 | |||
130 | /* We have the notify object, Get the correct handler */ | ||
131 | |||
132 | switch (node->type) { | ||
133 | 116 | ||
134 | /* Notify is allowed only on these types */ | 117 | /* Get the correct notify list type (System or Device) */ |
135 | 118 | ||
136 | case ACPI_TYPE_DEVICE: | 119 | if (notify_value <= ACPI_MAX_SYS_NOTIFY) { |
137 | case ACPI_TYPE_THERMAL: | 120 | handler_list_id = ACPI_SYSTEM_HANDLER_LIST; |
138 | case ACPI_TYPE_PROCESSOR: | 121 | } else { |
122 | handler_list_id = ACPI_DEVICE_HANDLER_LIST; | ||
123 | } | ||
139 | 124 | ||
140 | if (notify_value <= ACPI_MAX_SYS_NOTIFY) { | 125 | /* Get the notify object attached to the namespace Node */ |
141 | handler_obj = | ||
142 | obj_desc->common_notify.system_notify; | ||
143 | } else { | ||
144 | handler_obj = | ||
145 | obj_desc->common_notify.device_notify; | ||
146 | } | ||
147 | break; | ||
148 | 126 | ||
149 | default: | 127 | obj_desc = acpi_ns_get_attached_object(node); |
128 | if (obj_desc) { | ||
150 | 129 | ||
151 | /* All other types are not supported */ | 130 | /* We have an attached object, Get the correct handler list */ |
152 | 131 | ||
153 | return (AE_TYPE); | 132 | handler_list_head = |
154 | } | 133 | obj_desc->common_notify.notify_list[handler_list_id]; |
155 | } | 134 | } |
156 | 135 | ||
157 | /* | 136 | /* |
158 | * If there is a handler to run, schedule the dispatcher. | 137 | * If there is no notify handler (Global or Local) |
159 | * Check for: | 138 | * for this object, just ignore the notify |
160 | * 1) Global system notify handler | ||
161 | * 2) Global device notify handler | ||
162 | * 3) Per-device notify handler | ||
163 | */ | 139 | */ |
164 | if ((acpi_gbl_system_notify.handler && | 140 | if (!acpi_gbl_global_notify[handler_list_id].handler |
165 | (notify_value <= ACPI_MAX_SYS_NOTIFY)) || | 141 | && !handler_list_head) { |
166 | (acpi_gbl_device_notify.handler && | 142 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, |
167 | (notify_value > ACPI_MAX_SYS_NOTIFY)) || handler_obj) { | 143 | "No notify handler for Notify, ignoring (%4.4s, %X) node %p\n", |
168 | notify_info = acpi_ut_create_generic_state(); | 144 | acpi_ut_get_node_name(node), notify_value, |
169 | if (!notify_info) { | 145 | node)); |
170 | return (AE_NO_MEMORY); | ||
171 | } | ||
172 | 146 | ||
173 | if (!handler_obj) { | 147 | return (AE_OK); |
174 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | 148 | } |
175 | "Executing system notify handler for Notify (%4.4s, %X) " | ||
176 | "node %p\n", | ||
177 | acpi_ut_get_node_name(node), | ||
178 | notify_value, node)); | ||
179 | } | ||
180 | 149 | ||
181 | notify_info->common.descriptor_type = | 150 | /* Setup notify info and schedule the notify dispatcher */ |
182 | ACPI_DESC_TYPE_STATE_NOTIFY; | ||
183 | notify_info->notify.node = node; | ||
184 | notify_info->notify.value = (u16) notify_value; | ||
185 | notify_info->notify.handler_obj = handler_obj; | ||
186 | 151 | ||
187 | status = | 152 | info = acpi_ut_create_generic_state(); |
188 | acpi_os_execute(OSL_NOTIFY_HANDLER, acpi_ev_notify_dispatch, | 153 | if (!info) { |
189 | notify_info); | 154 | return (AE_NO_MEMORY); |
190 | if (ACPI_FAILURE(status)) { | 155 | } |
191 | acpi_ut_delete_generic_state(notify_info); | ||
192 | } | ||
193 | } else { | ||
194 | /* There is no notify handler (per-device or system) for this device */ | ||
195 | 156 | ||
196 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | 157 | info->common.descriptor_type = ACPI_DESC_TYPE_STATE_NOTIFY; |
197 | "No notify handler for Notify (%4.4s, %X) node %p\n", | 158 | |
198 | acpi_ut_get_node_name(node), notify_value, | 159 | info->notify.node = node; |
199 | node)); | 160 | info->notify.value = (u16)notify_value; |
161 | info->notify.handler_list_id = handler_list_id; | ||
162 | info->notify.handler_list_head = handler_list_head; | ||
163 | info->notify.global = &acpi_gbl_global_notify[handler_list_id]; | ||
164 | |||
165 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | ||
166 | "Dispatching Notify on [%4.4s] (%s) Value 0x%2.2X (%s) Node %p\n", | ||
167 | acpi_ut_get_node_name(node), | ||
168 | acpi_ut_get_type_name(node->type), notify_value, | ||
169 | acpi_ut_get_notify_name(notify_value), node)); | ||
170 | |||
171 | status = acpi_os_execute(OSL_NOTIFY_HANDLER, acpi_ev_notify_dispatch, | ||
172 | info); | ||
173 | if (ACPI_FAILURE(status)) { | ||
174 | acpi_ut_delete_generic_state(info); | ||
200 | } | 175 | } |
201 | 176 | ||
202 | return (status); | 177 | return (status); |
@@ -206,7 +181,7 @@ acpi_ev_queue_notify_request(struct acpi_namespace_node * node, | |||
206 | * | 181 | * |
207 | * FUNCTION: acpi_ev_notify_dispatch | 182 | * FUNCTION: acpi_ev_notify_dispatch |
208 | * | 183 | * |
209 | * PARAMETERS: Context - To be passed to the notify handler | 184 | * PARAMETERS: context - To be passed to the notify handler |
210 | * | 185 | * |
211 | * RETURN: None. | 186 | * RETURN: None. |
212 | * | 187 | * |
@@ -217,60 +192,34 @@ acpi_ev_queue_notify_request(struct acpi_namespace_node * node, | |||
217 | 192 | ||
218 | static void ACPI_SYSTEM_XFACE acpi_ev_notify_dispatch(void *context) | 193 | static void ACPI_SYSTEM_XFACE acpi_ev_notify_dispatch(void *context) |
219 | { | 194 | { |
220 | union acpi_generic_state *notify_info = | 195 | union acpi_generic_state *info = (union acpi_generic_state *)context; |
221 | (union acpi_generic_state *)context; | ||
222 | acpi_notify_handler global_handler = NULL; | ||
223 | void *global_context = NULL; | ||
224 | union acpi_operand_object *handler_obj; | 196 | union acpi_operand_object *handler_obj; |
225 | 197 | ||
226 | ACPI_FUNCTION_ENTRY(); | 198 | ACPI_FUNCTION_ENTRY(); |
227 | 199 | ||
228 | /* | 200 | /* Invoke a global notify handler if installed */ |
229 | * We will invoke a global notify handler if installed. This is done | ||
230 | * _before_ we invoke the per-device handler attached to the device. | ||
231 | */ | ||
232 | if (notify_info->notify.value <= ACPI_MAX_SYS_NOTIFY) { | ||
233 | |||
234 | /* Global system notification handler */ | ||
235 | |||
236 | if (acpi_gbl_system_notify.handler) { | ||
237 | global_handler = acpi_gbl_system_notify.handler; | ||
238 | global_context = acpi_gbl_system_notify.context; | ||
239 | } | ||
240 | } else { | ||
241 | /* Global driver notification handler */ | ||
242 | |||
243 | if (acpi_gbl_device_notify.handler) { | ||
244 | global_handler = acpi_gbl_device_notify.handler; | ||
245 | global_context = acpi_gbl_device_notify.context; | ||
246 | } | ||
247 | } | ||
248 | |||
249 | /* Invoke the system handler first, if present */ | ||
250 | 201 | ||
251 | if (global_handler) { | 202 | if (info->notify.global->handler) { |
252 | global_handler(notify_info->notify.node, | 203 | info->notify.global->handler(info->notify.node, |
253 | notify_info->notify.value, global_context); | 204 | info->notify.value, |
205 | info->notify.global->context); | ||
254 | } | 206 | } |
255 | 207 | ||
256 | /* Now invoke the per-device handler, if present */ | 208 | /* Now invoke the local notify handler(s) if any are installed */ |
257 | 209 | ||
258 | handler_obj = notify_info->notify.handler_obj; | 210 | handler_obj = info->notify.handler_list_head; |
259 | if (handler_obj) { | 211 | while (handler_obj) { |
260 | struct acpi_object_notify_handler *notifier; | 212 | handler_obj->notify.handler(info->notify.node, |
213 | info->notify.value, | ||
214 | handler_obj->notify.context); | ||
261 | 215 | ||
262 | notifier = &handler_obj->notify; | 216 | handler_obj = |
263 | while (notifier) { | 217 | handler_obj->notify.next[info->notify.handler_list_id]; |
264 | notifier->handler(notify_info->notify.node, | ||
265 | notify_info->notify.value, | ||
266 | notifier->context); | ||
267 | notifier = notifier->next; | ||
268 | } | ||
269 | } | 218 | } |
270 | 219 | ||
271 | /* All done with the info object */ | 220 | /* All done with the info object */ |
272 | 221 | ||
273 | acpi_ut_delete_generic_state(notify_info); | 222 | acpi_ut_delete_generic_state(info); |
274 | } | 223 | } |
275 | 224 | ||
276 | #if (!ACPI_REDUCED_HARDWARE) | 225 | #if (!ACPI_REDUCED_HARDWARE) |