diff options
author | Bob Moore <robert.moore@intel.com> | 2012-05-02 23:08:19 -0400 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2012-06-01 11:51:50 -0400 |
commit | 86ed4bc83abf530cf2019044b74f89a39dfd6425 (patch) | |
tree | 7cd21414f6121486079be2ca9cb9ff0a7722e01b /drivers/acpi | |
parent | 5134abfcfb4a8a9ef42c82dabad05762fbf04376 (diff) |
ACPICA: Add support for multiple notify handlers
This change adds support to allow multiple notify handlers on
Device, ThermalZone, and Processor objects. Also re-worked
and restructured the entire notify support code for handler
installation, handler removal, notify event queuing, and notify
dispatch to handler.
Extends and updates original commit 3f0be67("ACPI / ACPICA: Multiple
system notify handlers per device") by Rafael Wysocki.
Signed-off-by: Bob Moore <robert.moore@intel.com>
Signed-off-by: Lin Ming <ming.m.lin@intel.com>
Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/acpi')
-rw-r--r-- | drivers/acpi/acpica/acglobal.h | 3 | ||||
-rw-r--r-- | drivers/acpi/acpica/aclocal.h | 13 | ||||
-rw-r--r-- | drivers/acpi/acpica/acobject.h | 9 | ||||
-rw-r--r-- | drivers/acpi/acpica/evmisc.c | 185 | ||||
-rw-r--r-- | drivers/acpi/acpica/evxface.c | 440 | ||||
-rw-r--r-- | drivers/acpi/acpica/exdump.c | 25 | ||||
-rw-r--r-- | drivers/acpi/acpica/utdelete.c | 24 | ||||
-rw-r--r-- | drivers/acpi/acpica/utglobal.c | 4 |
8 files changed, 262 insertions, 441 deletions
diff --git a/drivers/acpi/acpica/acglobal.h b/drivers/acpi/acpica/acglobal.h index 4f7d3f57d05c..dec7994d405c 100644 --- a/drivers/acpi/acpica/acglobal.h +++ b/drivers/acpi/acpica/acglobal.h | |||
@@ -278,8 +278,7 @@ ACPI_EXTERN acpi_cache_t *acpi_gbl_operand_cache; | |||
278 | 278 | ||
279 | /* Global handlers */ | 279 | /* Global handlers */ |
280 | 280 | ||
281 | ACPI_EXTERN struct acpi_object_notify_handler acpi_gbl_device_notify; | 281 | ACPI_EXTERN struct acpi_global_notify_handler acpi_gbl_global_notify[2]; |
282 | ACPI_EXTERN struct acpi_object_notify_handler acpi_gbl_system_notify; | ||
283 | ACPI_EXTERN acpi_exception_handler acpi_gbl_exception_handler; | 282 | ACPI_EXTERN acpi_exception_handler acpi_gbl_exception_handler; |
284 | ACPI_EXTERN acpi_init_handler acpi_gbl_init_handler; | 283 | ACPI_EXTERN acpi_init_handler acpi_gbl_init_handler; |
285 | ACPI_EXTERN acpi_tbl_handler acpi_gbl_table_handler; | 284 | ACPI_EXTERN acpi_tbl_handler acpi_gbl_table_handler; |
diff --git a/drivers/acpi/acpica/aclocal.h b/drivers/acpi/acpica/aclocal.h index e3922ca20e7f..28f677834bfd 100644 --- a/drivers/acpi/acpica/aclocal.h +++ b/drivers/acpi/acpica/aclocal.h | |||
@@ -600,13 +600,22 @@ acpi_status(*acpi_parse_downwards) (struct acpi_walk_state * walk_state, | |||
600 | 600 | ||
601 | typedef acpi_status(*acpi_parse_upwards) (struct acpi_walk_state * walk_state); | 601 | typedef acpi_status(*acpi_parse_upwards) (struct acpi_walk_state * walk_state); |
602 | 602 | ||
603 | /* Global handlers for AML Notifies */ | ||
604 | |||
605 | struct acpi_global_notify_handler { | ||
606 | acpi_notify_handler handler; | ||
607 | void *context; | ||
608 | }; | ||
609 | |||
603 | /* | 610 | /* |
604 | * Notify info - used to pass info to the deferred notify | 611 | * Notify info - used to pass info to the deferred notify |
605 | * handler/dispatcher. | 612 | * handler/dispatcher. |
606 | */ | 613 | */ |
607 | struct acpi_notify_info { | 614 | struct acpi_notify_info { |
608 | ACPI_STATE_COMMON struct acpi_namespace_node *node; | 615 | ACPI_STATE_COMMON u8 handler_list_id; |
609 | union acpi_operand_object *handler_obj; | 616 | struct acpi_namespace_node *node; |
617 | union acpi_operand_object *handler_list_head; | ||
618 | struct acpi_global_notify_handler *global; | ||
610 | }; | 619 | }; |
611 | 620 | ||
612 | /* Generic state is union of structs above */ | 621 | /* Generic state is union of structs above */ |
diff --git a/drivers/acpi/acpica/acobject.h b/drivers/acpi/acpica/acobject.h index c065078ca83b..39a2b84120be 100644 --- a/drivers/acpi/acpica/acobject.h +++ b/drivers/acpi/acpica/acobject.h | |||
@@ -206,8 +206,7 @@ struct acpi_object_method { | |||
206 | * Common fields for objects that support ASL notifications | 206 | * Common fields for objects that support ASL notifications |
207 | */ | 207 | */ |
208 | #define ACPI_COMMON_NOTIFY_INFO \ | 208 | #define ACPI_COMMON_NOTIFY_INFO \ |
209 | union acpi_operand_object *system_notify; /* Handler for system notifies */\ | 209 | union acpi_operand_object *notify_list[2]; /* Handlers for system/device notifies */\ |
210 | union acpi_operand_object *device_notify; /* Handler for driver notifies */\ | ||
211 | union acpi_operand_object *handler; /* Handler for Address space */ | 210 | union acpi_operand_object *handler; /* Handler for Address space */ |
212 | 211 | ||
213 | struct acpi_object_notify_common { /* COMMON NOTIFY for POWER, PROCESSOR, DEVICE, and THERMAL */ | 212 | struct acpi_object_notify_common { /* COMMON NOTIFY for POWER, PROCESSOR, DEVICE, and THERMAL */ |
@@ -296,10 +295,10 @@ struct acpi_object_buffer_field { | |||
296 | 295 | ||
297 | struct acpi_object_notify_handler { | 296 | struct acpi_object_notify_handler { |
298 | ACPI_OBJECT_COMMON_HEADER struct acpi_namespace_node *node; /* Parent device */ | 297 | ACPI_OBJECT_COMMON_HEADER struct acpi_namespace_node *node; /* Parent device */ |
299 | u32 handler_type; | 298 | u32 handler_type; /* Type: Device/System/Both */ |
300 | acpi_notify_handler handler; | 299 | acpi_notify_handler handler; /* Handler address */ |
301 | void *context; | 300 | void *context; |
302 | struct acpi_object_notify_handler *next; | 301 | union acpi_operand_object *next[2]; /* Device and System handler lists */ |
303 | }; | 302 | }; |
304 | 303 | ||
305 | struct acpi_object_addr_handler { | 304 | struct acpi_object_addr_handler { |
diff --git a/drivers/acpi/acpica/evmisc.c b/drivers/acpi/acpica/evmisc.c index 51ef9f5e002d..381fce93a561 100644 --- a/drivers/acpi/acpica/evmisc.c +++ b/drivers/acpi/acpica/evmisc.c | |||
@@ -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); |
@@ -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) |
diff --git a/drivers/acpi/acpica/evxface.c b/drivers/acpi/acpica/evxface.c index 44bef5744ebb..90ae6d193645 100644 --- a/drivers/acpi/acpica/evxface.c +++ b/drivers/acpi/acpica/evxface.c | |||
@@ -54,86 +54,25 @@ ACPI_MODULE_NAME("evxface") | |||
54 | 54 | ||
55 | /******************************************************************************* | 55 | /******************************************************************************* |
56 | * | 56 | * |
57 | * FUNCTION: acpi_populate_handler_object | ||
58 | * | ||
59 | * PARAMETERS: handler_obj - Handler object to populate | ||
60 | * handler_type - The type of handler: | ||
61 | * ACPI_SYSTEM_NOTIFY: system_handler (00-7f) | ||
62 | * ACPI_DEVICE_NOTIFY: driver_handler (80-ff) | ||
63 | * ACPI_ALL_NOTIFY: both system and device | ||
64 | * handler - Address of the handler | ||
65 | * context - Value passed to the handler on each GPE | ||
66 | * next - Address of a handler object to link to | ||
67 | * | ||
68 | * RETURN: None | ||
69 | * | ||
70 | * DESCRIPTION: Populate a handler object. | ||
71 | * | ||
72 | ******************************************************************************/ | ||
73 | static void | ||
74 | acpi_populate_handler_object(struct acpi_object_notify_handler *handler_obj, | ||
75 | u32 handler_type, | ||
76 | acpi_notify_handler handler, void *context, | ||
77 | struct acpi_object_notify_handler *next) | ||
78 | { | ||
79 | handler_obj->handler_type = handler_type; | ||
80 | handler_obj->handler = handler; | ||
81 | handler_obj->context = context; | ||
82 | handler_obj->next = next; | ||
83 | } | ||
84 | |||
85 | /******************************************************************************* | ||
86 | * | ||
87 | * FUNCTION: acpi_add_handler_object | ||
88 | * | ||
89 | * PARAMETERS: parent_obj - Parent of the new object | ||
90 | * handler - Address of the handler | ||
91 | * context - Value passed to the handler on each GPE | ||
92 | * | ||
93 | * RETURN: Status | ||
94 | * | ||
95 | * DESCRIPTION: Create a new handler object and populate it. | ||
96 | * | ||
97 | ******************************************************************************/ | ||
98 | static acpi_status | ||
99 | acpi_add_handler_object(struct acpi_object_notify_handler *parent_obj, | ||
100 | acpi_notify_handler handler, void *context) | ||
101 | { | ||
102 | struct acpi_object_notify_handler *handler_obj; | ||
103 | |||
104 | /* The parent must not be a defice notify handler object. */ | ||
105 | if (parent_obj->handler_type & ACPI_DEVICE_NOTIFY) | ||
106 | return AE_BAD_PARAMETER; | ||
107 | |||
108 | handler_obj = ACPI_ALLOCATE_ZEROED(sizeof(*handler_obj)); | ||
109 | if (!handler_obj) | ||
110 | return AE_NO_MEMORY; | ||
111 | |||
112 | acpi_populate_handler_object(handler_obj, | ||
113 | ACPI_SYSTEM_NOTIFY, | ||
114 | handler, context, | ||
115 | parent_obj->next); | ||
116 | parent_obj->next = handler_obj; | ||
117 | |||
118 | return AE_OK; | ||
119 | } | ||
120 | |||
121 | |||
122 | /******************************************************************************* | ||
123 | * | ||
124 | * FUNCTION: acpi_install_notify_handler | 57 | * FUNCTION: acpi_install_notify_handler |
125 | * | 58 | * |
126 | * PARAMETERS: Device - The device for which notifies will be handled | 59 | * PARAMETERS: Device - The device for which notifies will be handled |
127 | * handler_type - The type of handler: | 60 | * handler_type - The type of handler: |
128 | * ACPI_SYSTEM_NOTIFY: system_handler (00-7f) | 61 | * ACPI_SYSTEM_NOTIFY: System Handler (00-7F) |
129 | * ACPI_DEVICE_NOTIFY: driver_handler (80-ff) | 62 | * ACPI_DEVICE_NOTIFY: Device Handler (80-FF) |
130 | * ACPI_ALL_NOTIFY: both system and device | 63 | * ACPI_ALL_NOTIFY: Both System and Device |
131 | * Handler - Address of the handler | 64 | * Handler - Address of the handler |
132 | * Context - Value passed to the handler on each GPE | 65 | * Context - Value passed to the handler on each GPE |
133 | * | 66 | * |
134 | * RETURN: Status | 67 | * RETURN: Status |
135 | * | 68 | * |
136 | * DESCRIPTION: Install a handler for notifies on an ACPI device | 69 | * DESCRIPTION: Install a handler for notifications on an ACPI Device, |
70 | * thermal_zone, or Processor object. | ||
71 | * | ||
72 | * NOTES: The Root namespace object may have only one handler for each | ||
73 | * type of notify (System/Device). Device/Thermal/Processor objects | ||
74 | * may have one device notify handler, and multiple system notify | ||
75 | * handlers. | ||
137 | * | 76 | * |
138 | ******************************************************************************/ | 77 | ******************************************************************************/ |
139 | acpi_status | 78 | acpi_status |
@@ -141,17 +80,19 @@ acpi_install_notify_handler(acpi_handle device, | |||
141 | u32 handler_type, | 80 | u32 handler_type, |
142 | acpi_notify_handler handler, void *context) | 81 | acpi_notify_handler handler, void *context) |
143 | { | 82 | { |
83 | struct acpi_namespace_node *node = | ||
84 | ACPI_CAST_PTR(struct acpi_namespace_node, device); | ||
144 | union acpi_operand_object *obj_desc; | 85 | union acpi_operand_object *obj_desc; |
145 | union acpi_operand_object *notify_obj; | 86 | union acpi_operand_object *handler_obj; |
146 | struct acpi_namespace_node *node; | ||
147 | acpi_status status; | 87 | acpi_status status; |
88 | u32 i; | ||
148 | 89 | ||
149 | ACPI_FUNCTION_TRACE(acpi_install_notify_handler); | 90 | ACPI_FUNCTION_TRACE(acpi_install_notify_handler); |
150 | 91 | ||
151 | /* Parameter validation */ | 92 | /* Parameter validation */ |
152 | 93 | ||
153 | if ((!device) || | 94 | if ((!device) || (!handler) || (!handler_type) || |
154 | (!handler) || (handler_type > ACPI_MAX_NOTIFY_HANDLER_TYPE)) { | 95 | (handler_type > ACPI_MAX_NOTIFY_HANDLER_TYPE)) { |
155 | return_ACPI_STATUS(AE_BAD_PARAMETER); | 96 | return_ACPI_STATUS(AE_BAD_PARAMETER); |
156 | } | 97 | } |
157 | 98 | ||
@@ -160,144 +101,112 @@ acpi_install_notify_handler(acpi_handle device, | |||
160 | return_ACPI_STATUS(status); | 101 | return_ACPI_STATUS(status); |
161 | } | 102 | } |
162 | 103 | ||
163 | /* Convert and validate the device handle */ | ||
164 | |||
165 | node = acpi_ns_validate_handle(device); | ||
166 | if (!node) { | ||
167 | status = AE_BAD_PARAMETER; | ||
168 | goto unlock_and_exit; | ||
169 | } | ||
170 | |||
171 | /* | 104 | /* |
172 | * Root Object: | 105 | * Root Object: |
173 | * Registering a notify handler on the root object indicates that the | 106 | * Registering a notify handler on the root object indicates that the |
174 | * caller wishes to receive notifications for all objects. Note that | 107 | * caller wishes to receive notifications for all objects. Note that |
175 | * only one <external> global handler can be regsitered (per notify type). | 108 | * only one global handler can be registered per notify type. |
109 | * Ensure that a handler is not already installed. | ||
176 | */ | 110 | */ |
177 | if (device == ACPI_ROOT_OBJECT) { | 111 | if (device == ACPI_ROOT_OBJECT) { |
112 | for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++) { | ||
113 | if (handler_type & (i + 1)) { | ||
114 | if (acpi_gbl_global_notify[i].handler) { | ||
115 | status = AE_ALREADY_EXISTS; | ||
116 | goto unlock_and_exit; | ||
117 | } | ||
178 | 118 | ||
179 | /* Make sure the handler is not already installed */ | 119 | acpi_gbl_global_notify[i].handler = handler; |
180 | 120 | acpi_gbl_global_notify[i].context = context; | |
181 | if (((handler_type & ACPI_SYSTEM_NOTIFY) && | 121 | } |
182 | acpi_gbl_system_notify.handler) || | ||
183 | ((handler_type & ACPI_DEVICE_NOTIFY) && | ||
184 | acpi_gbl_device_notify.handler)) { | ||
185 | status = AE_ALREADY_EXISTS; | ||
186 | goto unlock_and_exit; | ||
187 | } | ||
188 | |||
189 | if (handler_type & ACPI_SYSTEM_NOTIFY) { | ||
190 | acpi_gbl_system_notify.node = node; | ||
191 | acpi_gbl_system_notify.handler = handler; | ||
192 | acpi_gbl_system_notify.context = context; | ||
193 | } | ||
194 | |||
195 | if (handler_type & ACPI_DEVICE_NOTIFY) { | ||
196 | acpi_gbl_device_notify.node = node; | ||
197 | acpi_gbl_device_notify.handler = handler; | ||
198 | acpi_gbl_device_notify.context = context; | ||
199 | } | 122 | } |
200 | 123 | ||
201 | /* Global notify handler installed */ | 124 | goto unlock_and_exit; /* Global notify handler installed, all done */ |
202 | } | 125 | } |
203 | 126 | ||
204 | /* | 127 | /* |
205 | * All Other Objects: | 128 | * All Other Objects: |
206 | * Caller will only receive notifications specific to the target object. | 129 | * Caller will only receive notifications specific to the target |
207 | * Note that only certain object types can receive notifications. | 130 | * object. Note that only certain object types are allowed to |
131 | * receive notifications. | ||
208 | */ | 132 | */ |
209 | else { | ||
210 | /* Notifies allowed on this object? */ | ||
211 | 133 | ||
212 | if (!acpi_ev_is_notify_object(node)) { | 134 | /* Are Notifies allowed on this object? */ |
213 | status = AE_TYPE; | ||
214 | goto unlock_and_exit; | ||
215 | } | ||
216 | 135 | ||
217 | /* Check for an existing internal object */ | 136 | if (!acpi_ev_is_notify_object(node)) { |
137 | status = AE_TYPE; | ||
138 | goto unlock_and_exit; | ||
139 | } | ||
218 | 140 | ||
219 | obj_desc = acpi_ns_get_attached_object(node); | 141 | /* Check for an existing internal object, might not exist */ |
220 | if (obj_desc) { | ||
221 | 142 | ||
222 | /* Object exists. */ | 143 | obj_desc = acpi_ns_get_attached_object(node); |
144 | if (!obj_desc) { | ||
223 | 145 | ||
224 | /* For a device notify, make sure there's no handler. */ | 146 | /* Create a new object */ |
225 | if ((handler_type & ACPI_DEVICE_NOTIFY) && | ||
226 | obj_desc->common_notify.device_notify) { | ||
227 | status = AE_ALREADY_EXISTS; | ||
228 | goto unlock_and_exit; | ||
229 | } | ||
230 | 147 | ||
231 | /* System notifies may have more handlers installed. */ | 148 | obj_desc = acpi_ut_create_internal_object(node->type); |
232 | notify_obj = obj_desc->common_notify.system_notify; | 149 | if (!obj_desc) { |
150 | status = AE_NO_MEMORY; | ||
151 | goto unlock_and_exit; | ||
152 | } | ||
233 | 153 | ||
234 | if ((handler_type & ACPI_SYSTEM_NOTIFY) && notify_obj) { | 154 | /* Attach new object to the Node, remove local reference */ |
235 | struct acpi_object_notify_handler *parent_obj; | ||
236 | 155 | ||
237 | if (handler_type & ACPI_DEVICE_NOTIFY) { | 156 | status = acpi_ns_attach_object(device, obj_desc, node->type); |
157 | acpi_ut_remove_reference(obj_desc); | ||
158 | if (ACPI_FAILURE(status)) { | ||
159 | goto unlock_and_exit; | ||
160 | } | ||
161 | } | ||
162 | |||
163 | /* Ensure that the handler is not already installed in the lists */ | ||
164 | |||
165 | for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++) { | ||
166 | if (handler_type & (i + 1)) { | ||
167 | handler_obj = obj_desc->common_notify.notify_list[i]; | ||
168 | while (handler_obj) { | ||
169 | if (handler_obj->notify.handler == handler) { | ||
238 | status = AE_ALREADY_EXISTS; | 170 | status = AE_ALREADY_EXISTS; |
239 | goto unlock_and_exit; | 171 | goto unlock_and_exit; |
240 | } | 172 | } |
241 | 173 | ||
242 | parent_obj = ¬ify_obj->notify; | 174 | handler_obj = handler_obj->notify.next[i]; |
243 | status = acpi_add_handler_object(parent_obj, | ||
244 | handler, | ||
245 | context); | ||
246 | goto unlock_and_exit; | ||
247 | } | ||
248 | } else { | ||
249 | /* Create a new object */ | ||
250 | |||
251 | obj_desc = acpi_ut_create_internal_object(node->type); | ||
252 | if (!obj_desc) { | ||
253 | status = AE_NO_MEMORY; | ||
254 | goto unlock_and_exit; | ||
255 | } | ||
256 | |||
257 | /* Attach new object to the Node */ | ||
258 | |||
259 | status = | ||
260 | acpi_ns_attach_object(device, obj_desc, node->type); | ||
261 | |||
262 | /* Remove local reference to the object */ | ||
263 | |||
264 | acpi_ut_remove_reference(obj_desc); | ||
265 | if (ACPI_FAILURE(status)) { | ||
266 | goto unlock_and_exit; | ||
267 | } | 175 | } |
268 | } | 176 | } |
177 | } | ||
269 | 178 | ||
270 | /* Install the handler */ | 179 | /* Create and populate a new notify handler object */ |
271 | 180 | ||
272 | notify_obj = | 181 | handler_obj = acpi_ut_create_internal_object(ACPI_TYPE_LOCAL_NOTIFY); |
273 | acpi_ut_create_internal_object(ACPI_TYPE_LOCAL_NOTIFY); | 182 | if (!handler_obj) { |
274 | if (!notify_obj) { | 183 | status = AE_NO_MEMORY; |
275 | status = AE_NO_MEMORY; | 184 | goto unlock_and_exit; |
276 | goto unlock_and_exit; | 185 | } |
277 | } | ||
278 | 186 | ||
279 | acpi_populate_handler_object(¬ify_obj->notify, | 187 | handler_obj->notify.node = node; |
280 | handler_type, | 188 | handler_obj->notify.handler_type = handler_type; |
281 | handler, context, | 189 | handler_obj->notify.handler = handler; |
282 | NULL); | 190 | handler_obj->notify.context = context; |
283 | 191 | ||
284 | if (handler_type & ACPI_SYSTEM_NOTIFY) { | 192 | /* Install the handler at the list head(s) */ |
285 | obj_desc->common_notify.system_notify = notify_obj; | ||
286 | } | ||
287 | 193 | ||
288 | if (handler_type & ACPI_DEVICE_NOTIFY) { | 194 | for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++) { |
289 | obj_desc->common_notify.device_notify = notify_obj; | 195 | if (handler_type & (i + 1)) { |
290 | } | 196 | handler_obj->notify.next[i] = |
197 | obj_desc->common_notify.notify_list[i]; | ||
291 | 198 | ||
292 | if (handler_type == ACPI_ALL_NOTIFY) { | 199 | obj_desc->common_notify.notify_list[i] = handler_obj; |
200 | } | ||
201 | } | ||
293 | 202 | ||
294 | /* Extra ref if installed in both */ | 203 | /* Add an extra reference if handler was installed in both lists */ |
295 | 204 | ||
296 | acpi_ut_add_reference(notify_obj); | 205 | if (handler_type == ACPI_ALL_NOTIFY) { |
297 | } | 206 | acpi_ut_add_reference(handler_obj); |
298 | } | 207 | } |
299 | 208 | ||
300 | unlock_and_exit: | 209 | unlock_and_exit: |
301 | (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); | 210 | (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); |
302 | return_ACPI_STATUS(status); | 211 | return_ACPI_STATUS(status); |
303 | } | 212 | } |
@@ -308,11 +217,11 @@ ACPI_EXPORT_SYMBOL(acpi_install_notify_handler) | |||
308 | * | 217 | * |
309 | * FUNCTION: acpi_remove_notify_handler | 218 | * FUNCTION: acpi_remove_notify_handler |
310 | * | 219 | * |
311 | * PARAMETERS: Device - The device for which notifies will be handled | 220 | * PARAMETERS: Device - The device for which the handler is installed |
312 | * handler_type - The type of handler: | 221 | * handler_type - The type of handler: |
313 | * ACPI_SYSTEM_NOTIFY: system_handler (00-7f) | 222 | * ACPI_SYSTEM_NOTIFY: System Handler (00-7F) |
314 | * ACPI_DEVICE_NOTIFY: driver_handler (80-ff) | 223 | * ACPI_DEVICE_NOTIFY: Device Handler (80-FF) |
315 | * ACPI_ALL_NOTIFY: both system and device | 224 | * ACPI_ALL_NOTIFY: Both System and Device |
316 | * Handler - Address of the handler | 225 | * Handler - Address of the handler |
317 | * | 226 | * |
318 | * RETURN: Status | 227 | * RETURN: Status |
@@ -324,165 +233,106 @@ acpi_status | |||
324 | acpi_remove_notify_handler(acpi_handle device, | 233 | acpi_remove_notify_handler(acpi_handle device, |
325 | u32 handler_type, acpi_notify_handler handler) | 234 | u32 handler_type, acpi_notify_handler handler) |
326 | { | 235 | { |
327 | union acpi_operand_object *notify_obj; | 236 | struct acpi_namespace_node *node = |
237 | ACPI_CAST_PTR(struct acpi_namespace_node, device); | ||
328 | union acpi_operand_object *obj_desc; | 238 | union acpi_operand_object *obj_desc; |
329 | struct acpi_namespace_node *node; | 239 | union acpi_operand_object *handler_obj; |
240 | union acpi_operand_object *previous_handler_obj; | ||
330 | acpi_status status; | 241 | acpi_status status; |
242 | u32 i; | ||
331 | 243 | ||
332 | ACPI_FUNCTION_TRACE(acpi_remove_notify_handler); | 244 | ACPI_FUNCTION_TRACE(acpi_remove_notify_handler); |
333 | 245 | ||
334 | /* Parameter validation */ | 246 | /* Parameter validation */ |
335 | 247 | ||
336 | if ((!device) || | 248 | if ((!device) || (!handler) || (!handler_type) || |
337 | (!handler) || (handler_type > ACPI_MAX_NOTIFY_HANDLER_TYPE)) { | 249 | (handler_type > ACPI_MAX_NOTIFY_HANDLER_TYPE)) { |
338 | status = AE_BAD_PARAMETER; | 250 | return_ACPI_STATUS(AE_BAD_PARAMETER); |
339 | goto exit; | ||
340 | } | 251 | } |
341 | |||
342 | |||
343 | /* Make sure all deferred tasks are completed */ | 252 | /* Make sure all deferred tasks are completed */ |
253 | |||
344 | acpi_os_wait_events_complete(NULL); | 254 | acpi_os_wait_events_complete(NULL); |
345 | 255 | ||
346 | status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); | 256 | status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); |
347 | if (ACPI_FAILURE(status)) { | 257 | if (ACPI_FAILURE(status)) { |
348 | goto exit; | 258 | return_ACPI_STATUS(status); |
349 | } | ||
350 | |||
351 | /* Convert and validate the device handle */ | ||
352 | |||
353 | node = acpi_ns_validate_handle(device); | ||
354 | if (!node) { | ||
355 | status = AE_BAD_PARAMETER; | ||
356 | goto unlock_and_exit; | ||
357 | } | 259 | } |
358 | 260 | ||
359 | /* Root Object */ | 261 | /* Root Object. Global handlers are removed here */ |
360 | 262 | ||
361 | if (device == ACPI_ROOT_OBJECT) { | 263 | if (device == ACPI_ROOT_OBJECT) { |
362 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | 264 | for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++) { |
363 | "Removing notify handler for namespace root object\n")); | 265 | if (handler_type & (i + 1)) { |
266 | if (!acpi_gbl_global_notify[i].handler || | ||
267 | (acpi_gbl_global_notify[i].handler != | ||
268 | handler)) { | ||
269 | status = AE_NOT_EXIST; | ||
270 | goto unlock_and_exit; | ||
271 | } | ||
364 | 272 | ||
365 | if (((handler_type & ACPI_SYSTEM_NOTIFY) && | 273 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, |
366 | !acpi_gbl_system_notify.handler) || | 274 | "Removing global notify handler\n")); |
367 | ((handler_type & ACPI_DEVICE_NOTIFY) && | ||
368 | !acpi_gbl_device_notify.handler)) { | ||
369 | status = AE_NOT_EXIST; | ||
370 | goto unlock_and_exit; | ||
371 | } | ||
372 | 275 | ||
373 | if (handler_type & ACPI_SYSTEM_NOTIFY) { | 276 | acpi_gbl_global_notify[i].handler = NULL; |
374 | acpi_gbl_system_notify.node = NULL; | 277 | acpi_gbl_global_notify[i].context = NULL; |
375 | acpi_gbl_system_notify.handler = NULL; | 278 | } |
376 | acpi_gbl_system_notify.context = NULL; | ||
377 | } | 279 | } |
378 | 280 | ||
379 | if (handler_type & ACPI_DEVICE_NOTIFY) { | 281 | goto unlock_and_exit; |
380 | acpi_gbl_device_notify.node = NULL; | ||
381 | acpi_gbl_device_notify.handler = NULL; | ||
382 | acpi_gbl_device_notify.context = NULL; | ||
383 | } | ||
384 | } | 282 | } |
385 | 283 | ||
386 | /* All Other Objects */ | 284 | /* All other objects: Are Notifies allowed on this object? */ |
387 | |||
388 | else { | ||
389 | /* Notifies allowed on this object? */ | ||
390 | 285 | ||
391 | if (!acpi_ev_is_notify_object(node)) { | 286 | if (!acpi_ev_is_notify_object(node)) { |
392 | status = AE_TYPE; | 287 | status = AE_TYPE; |
393 | goto unlock_and_exit; | 288 | goto unlock_and_exit; |
394 | } | 289 | } |
395 | 290 | ||
396 | /* Check for an existing internal object */ | 291 | /* Must have an existing internal object */ |
397 | 292 | ||
398 | obj_desc = acpi_ns_get_attached_object(node); | 293 | obj_desc = acpi_ns_get_attached_object(node); |
399 | if (!obj_desc) { | 294 | if (!obj_desc) { |
400 | status = AE_NOT_EXIST; | 295 | status = AE_NOT_EXIST; |
401 | goto unlock_and_exit; | 296 | goto unlock_and_exit; |
402 | } | 297 | } |
403 | 298 | ||
404 | /* Object exists - make sure there's an existing handler */ | 299 | /* Internal object exists. Find the handler and remove it */ |
405 | 300 | ||
406 | if (handler_type & ACPI_SYSTEM_NOTIFY) { | 301 | for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++) { |
407 | struct acpi_object_notify_handler *handler_obj; | 302 | if (handler_type & (i + 1)) { |
408 | struct acpi_object_notify_handler *parent_obj; | 303 | handler_obj = obj_desc->common_notify.notify_list[i]; |
304 | previous_handler_obj = NULL; | ||
409 | 305 | ||
410 | notify_obj = obj_desc->common_notify.system_notify; | 306 | /* Attempt to find the handler in the handler list */ |
411 | if (!notify_obj) { | ||
412 | status = AE_NOT_EXIST; | ||
413 | goto unlock_and_exit; | ||
414 | } | ||
415 | 307 | ||
416 | handler_obj = ¬ify_obj->notify; | 308 | while (handler_obj && |
417 | parent_obj = NULL; | 309 | (handler_obj->notify.handler != handler)) { |
418 | while (handler_obj->handler != handler) { | 310 | previous_handler_obj = handler_obj; |
419 | if (handler_obj->next) { | 311 | handler_obj = handler_obj->notify.next[i]; |
420 | parent_obj = handler_obj; | ||
421 | handler_obj = handler_obj->next; | ||
422 | } else { | ||
423 | break; | ||
424 | } | ||
425 | } | 312 | } |
426 | 313 | ||
427 | if (handler_obj->handler != handler) { | 314 | if (!handler_obj) { |
428 | status = AE_BAD_PARAMETER; | 315 | status = AE_NOT_EXIST; |
429 | goto unlock_and_exit; | 316 | goto unlock_and_exit; |
430 | } | 317 | } |
431 | 318 | ||
432 | /* | 319 | /* Remove the handler object from the list */ |
433 | * Remove the handler. There are three possible cases. | ||
434 | * First, we may need to remove a non-embedded object. | ||
435 | * Second, we may need to remove the embedded object's | ||
436 | * handler data, while non-embedded objects exist. | ||
437 | * Finally, we may need to remove the embedded object | ||
438 | * entirely along with its container. | ||
439 | */ | ||
440 | if (parent_obj) { | ||
441 | /* Non-embedded object is being removed. */ | ||
442 | parent_obj->next = handler_obj->next; | ||
443 | ACPI_FREE(handler_obj); | ||
444 | } else if (notify_obj->notify.next) { | ||
445 | /* | ||
446 | * The handler matches the embedded object, but | ||
447 | * there are more handler objects in the list. | ||
448 | * Replace the embedded object's data with the | ||
449 | * first next object's data and remove that | ||
450 | * object. | ||
451 | */ | ||
452 | parent_obj = ¬ify_obj->notify; | ||
453 | handler_obj = notify_obj->notify.next; | ||
454 | *parent_obj = *handler_obj; | ||
455 | ACPI_FREE(handler_obj); | ||
456 | } else { | ||
457 | /* No more handler objects in the list. */ | ||
458 | obj_desc->common_notify.system_notify = NULL; | ||
459 | acpi_ut_remove_reference(notify_obj); | ||
460 | } | ||
461 | } | ||
462 | 320 | ||
463 | if (handler_type & ACPI_DEVICE_NOTIFY) { | 321 | if (previous_handler_obj) { /* Handler is not at the list head */ |
464 | notify_obj = obj_desc->common_notify.device_notify; | 322 | previous_handler_obj->notify.next[i] = |
465 | if (!notify_obj) { | 323 | handler_obj->notify.next[i]; |
466 | status = AE_NOT_EXIST; | 324 | } else { /* Handler is at the list head */ |
467 | goto unlock_and_exit; | ||
468 | } | ||
469 | 325 | ||
470 | if (notify_obj->notify.handler != handler) { | 326 | obj_desc->common_notify.notify_list[i] = |
471 | status = AE_BAD_PARAMETER; | 327 | handler_obj->notify.next[i]; |
472 | goto unlock_and_exit; | ||
473 | } | 328 | } |
474 | 329 | ||
475 | /* Remove the handler */ | 330 | acpi_ut_remove_reference(handler_obj); |
476 | obj_desc->common_notify.device_notify = NULL; | ||
477 | acpi_ut_remove_reference(notify_obj); | ||
478 | } | 331 | } |
479 | } | 332 | } |
480 | 333 | ||
481 | unlock_and_exit: | 334 | unlock_and_exit: |
482 | (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); | 335 | (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); |
483 | exit: | ||
484 | if (ACPI_FAILURE(status)) | ||
485 | ACPI_EXCEPTION((AE_INFO, status, "Removing notify handler")); | ||
486 | return_ACPI_STATUS(status); | 336 | return_ACPI_STATUS(status); |
487 | } | 337 | } |
488 | 338 | ||
diff --git a/drivers/acpi/acpica/exdump.c b/drivers/acpi/acpica/exdump.c index 836fe76e65d0..26c56545804d 100644 --- a/drivers/acpi/acpica/exdump.c +++ b/drivers/acpi/acpica/exdump.c | |||
@@ -109,9 +109,9 @@ static struct acpi_exdump_info acpi_ex_dump_package[5] = { | |||
109 | static struct acpi_exdump_info acpi_ex_dump_device[4] = { | 109 | static struct acpi_exdump_info acpi_ex_dump_device[4] = { |
110 | {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_device), NULL}, | 110 | {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_device), NULL}, |
111 | {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(device.handler), "Handler"}, | 111 | {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(device.handler), "Handler"}, |
112 | {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(device.system_notify), | 112 | {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(device.notify_list[0]), |
113 | "System Notify"}, | 113 | "System Notify"}, |
114 | {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(device.device_notify), | 114 | {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(device.notify_list[1]), |
115 | "Device Notify"} | 115 | "Device Notify"} |
116 | }; | 116 | }; |
117 | 117 | ||
@@ -158,9 +158,9 @@ static struct acpi_exdump_info acpi_ex_dump_power[5] = { | |||
158 | "System Level"}, | 158 | "System Level"}, |
159 | {ACPI_EXD_UINT32, ACPI_EXD_OFFSET(power_resource.resource_order), | 159 | {ACPI_EXD_UINT32, ACPI_EXD_OFFSET(power_resource.resource_order), |
160 | "Resource Order"}, | 160 | "Resource Order"}, |
161 | {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(power_resource.system_notify), | 161 | {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(power_resource.notify_list[0]), |
162 | "System Notify"}, | 162 | "System Notify"}, |
163 | {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(power_resource.device_notify), | 163 | {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(power_resource.notify_list[1]), |
164 | "Device Notify"} | 164 | "Device Notify"} |
165 | }; | 165 | }; |
166 | 166 | ||
@@ -169,18 +169,18 @@ static struct acpi_exdump_info acpi_ex_dump_processor[7] = { | |||
169 | {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(processor.proc_id), "Processor ID"}, | 169 | {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(processor.proc_id), "Processor ID"}, |
170 | {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(processor.length), "Length"}, | 170 | {ACPI_EXD_UINT8, ACPI_EXD_OFFSET(processor.length), "Length"}, |
171 | {ACPI_EXD_ADDRESS, ACPI_EXD_OFFSET(processor.address), "Address"}, | 171 | {ACPI_EXD_ADDRESS, ACPI_EXD_OFFSET(processor.address), "Address"}, |
172 | {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(processor.system_notify), | 172 | {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(processor.notify_list[0]), |
173 | "System Notify"}, | 173 | "System Notify"}, |
174 | {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(processor.device_notify), | 174 | {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(processor.notify_list[1]), |
175 | "Device Notify"}, | 175 | "Device Notify"}, |
176 | {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(processor.handler), "Handler"} | 176 | {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(processor.handler), "Handler"} |
177 | }; | 177 | }; |
178 | 178 | ||
179 | static struct acpi_exdump_info acpi_ex_dump_thermal[4] = { | 179 | static struct acpi_exdump_info acpi_ex_dump_thermal[4] = { |
180 | {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_thermal), NULL}, | 180 | {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_thermal), NULL}, |
181 | {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(thermal_zone.system_notify), | 181 | {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(thermal_zone.notify_list[0]), |
182 | "System Notify"}, | 182 | "System Notify"}, |
183 | {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(thermal_zone.device_notify), | 183 | {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(thermal_zone.notify_list[1]), |
184 | "Device Notify"}, | 184 | "Device Notify"}, |
185 | {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(thermal_zone.handler), "Handler"} | 185 | {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(thermal_zone.handler), "Handler"} |
186 | }; | 186 | }; |
@@ -241,10 +241,15 @@ static struct acpi_exdump_info acpi_ex_dump_address_handler[6] = { | |||
241 | {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(address_space.context), "Context"} | 241 | {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(address_space.context), "Context"} |
242 | }; | 242 | }; |
243 | 243 | ||
244 | static struct acpi_exdump_info acpi_ex_dump_notify[3] = { | 244 | static struct acpi_exdump_info acpi_ex_dump_notify[7] = { |
245 | {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_notify), NULL}, | 245 | {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_notify), NULL}, |
246 | {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(notify.node), "Node"}, | 246 | {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(notify.node), "Node"}, |
247 | {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(notify.context), "Context"} | 247 | {ACPI_EXD_UINT32, ACPI_EXD_OFFSET(notify.handler_type), "Handler Type"}, |
248 | {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(notify.handler), "Handler"}, | ||
249 | {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(notify.context), "Context"}, | ||
250 | {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(notify.next[0]), | ||
251 | "Next System Notify"}, | ||
252 | {ACPI_EXD_POINTER, ACPI_EXD_OFFSET(notify.next[1]), "Next Device Notify"} | ||
248 | }; | 253 | }; |
249 | 254 | ||
250 | /* Miscellaneous tables */ | 255 | /* Miscellaneous tables */ |
diff --git a/drivers/acpi/acpica/utdelete.c b/drivers/acpi/acpica/utdelete.c index 2a6c3e183697..0d50f2c6bac2 100644 --- a/drivers/acpi/acpica/utdelete.c +++ b/drivers/acpi/acpica/utdelete.c | |||
@@ -152,7 +152,7 @@ static void acpi_ut_delete_internal_obj(union acpi_operand_object *object) | |||
152 | case ACPI_TYPE_PROCESSOR: | 152 | case ACPI_TYPE_PROCESSOR: |
153 | case ACPI_TYPE_THERMAL: | 153 | case ACPI_TYPE_THERMAL: |
154 | 154 | ||
155 | /* Walk the notify handler list for this object */ | 155 | /* Walk the address handler list for this object */ |
156 | 156 | ||
157 | handler_desc = object->common_notify.handler; | 157 | handler_desc = object->common_notify.handler; |
158 | while (handler_desc) { | 158 | while (handler_desc) { |
@@ -480,6 +480,7 @@ acpi_ut_update_object_reference(union acpi_operand_object *object, u16 action) | |||
480 | acpi_status status = AE_OK; | 480 | acpi_status status = AE_OK; |
481 | union acpi_generic_state *state_list = NULL; | 481 | union acpi_generic_state *state_list = NULL; |
482 | union acpi_operand_object *next_object = NULL; | 482 | union acpi_operand_object *next_object = NULL; |
483 | union acpi_operand_object *prev_object; | ||
483 | union acpi_generic_state *state; | 484 | union acpi_generic_state *state; |
484 | u32 i; | 485 | u32 i; |
485 | 486 | ||
@@ -505,12 +506,21 @@ acpi_ut_update_object_reference(union acpi_operand_object *object, u16 action) | |||
505 | case ACPI_TYPE_POWER: | 506 | case ACPI_TYPE_POWER: |
506 | case ACPI_TYPE_THERMAL: | 507 | case ACPI_TYPE_THERMAL: |
507 | 508 | ||
508 | /* Update the notify objects for these types (if present) */ | 509 | /* |
509 | 510 | * Update the notify objects for these types (if present) | |
510 | acpi_ut_update_ref_count(object->common_notify. | 511 | * Two lists, system and device notify handlers. |
511 | system_notify, action); | 512 | */ |
512 | acpi_ut_update_ref_count(object->common_notify. | 513 | for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++) { |
513 | device_notify, action); | 514 | prev_object = |
515 | object->common_notify.notify_list[i]; | ||
516 | while (prev_object) { | ||
517 | next_object = | ||
518 | prev_object->notify.next[i]; | ||
519 | acpi_ut_update_ref_count(prev_object, | ||
520 | action); | ||
521 | prev_object = next_object; | ||
522 | } | ||
523 | } | ||
514 | break; | 524 | break; |
515 | 525 | ||
516 | case ACPI_TYPE_PACKAGE: | 526 | case ACPI_TYPE_PACKAGE: |
diff --git a/drivers/acpi/acpica/utglobal.c b/drivers/acpi/acpica/utglobal.c index 90f53b42eca9..78cf1fe390b3 100644 --- a/drivers/acpi/acpica/utglobal.c +++ b/drivers/acpi/acpica/utglobal.c | |||
@@ -304,8 +304,8 @@ acpi_status acpi_ut_init_globals(void) | |||
304 | 304 | ||
305 | /* Global handlers */ | 305 | /* Global handlers */ |
306 | 306 | ||
307 | acpi_gbl_system_notify.handler = NULL; | 307 | acpi_gbl_global_notify[0].handler = NULL; |
308 | acpi_gbl_device_notify.handler = NULL; | 308 | acpi_gbl_global_notify[1].handler = NULL; |
309 | acpi_gbl_exception_handler = NULL; | 309 | acpi_gbl_exception_handler = NULL; |
310 | acpi_gbl_init_handler = NULL; | 310 | acpi_gbl_init_handler = NULL; |
311 | acpi_gbl_table_handler = NULL; | 311 | acpi_gbl_table_handler = NULL; |