diff options
Diffstat (limited to 'drivers/acpi/acpica/evxfevnt.c')
-rw-r--r-- | drivers/acpi/acpica/evxfevnt.c | 249 |
1 files changed, 104 insertions, 145 deletions
diff --git a/drivers/acpi/acpica/evxfevnt.c b/drivers/acpi/acpica/evxfevnt.c index 18b3f1468b7d..0ec900da5794 100644 --- a/drivers/acpi/acpica/evxfevnt.c +++ b/drivers/acpi/acpica/evxfevnt.c | |||
@@ -213,101 +213,71 @@ ACPI_EXPORT_SYMBOL(acpi_enable_event) | |||
213 | 213 | ||
214 | /******************************************************************************* | 214 | /******************************************************************************* |
215 | * | 215 | * |
216 | * FUNCTION: acpi_clear_and_enable_gpe | 216 | * FUNCTION: acpi_gpe_wakeup |
217 | * | ||
218 | * PARAMETERS: gpe_event_info - GPE to enable | ||
219 | * | ||
220 | * RETURN: Status | ||
221 | * | ||
222 | * DESCRIPTION: Clear the given GPE from stale events and enable it. | ||
223 | * | ||
224 | ******************************************************************************/ | ||
225 | static acpi_status | ||
226 | acpi_clear_and_enable_gpe(struct acpi_gpe_event_info *gpe_event_info) | ||
227 | { | ||
228 | acpi_status status; | ||
229 | |||
230 | /* | ||
231 | * We will only allow a GPE to be enabled if it has either an | ||
232 | * associated method (_Lxx/_Exx) or a handler. Otherwise, the | ||
233 | * GPE will be immediately disabled by acpi_ev_gpe_dispatch the | ||
234 | * first time it fires. | ||
235 | */ | ||
236 | if (!(gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK)) { | ||
237 | return_ACPI_STATUS(AE_NO_HANDLER); | ||
238 | } | ||
239 | |||
240 | /* Clear the GPE (of stale events) */ | ||
241 | status = acpi_hw_clear_gpe(gpe_event_info); | ||
242 | if (ACPI_FAILURE(status)) { | ||
243 | return_ACPI_STATUS(status); | ||
244 | } | ||
245 | |||
246 | /* Enable the requested GPE */ | ||
247 | status = acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_ENABLE); | ||
248 | |||
249 | return_ACPI_STATUS(status); | ||
250 | } | ||
251 | |||
252 | /******************************************************************************* | ||
253 | * | ||
254 | * FUNCTION: acpi_set_gpe | ||
255 | * | 217 | * |
256 | * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1 | 218 | * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1 |
257 | * gpe_number - GPE level within the GPE block | 219 | * gpe_number - GPE level within the GPE block |
258 | * action - ACPI_GPE_ENABLE or ACPI_GPE_DISABLE | 220 | * Action - Enable or Disable |
259 | * | 221 | * |
260 | * RETURN: Status | 222 | * RETURN: Status |
261 | * | 223 | * |
262 | * DESCRIPTION: Enable or disable an individual GPE. This function bypasses | 224 | * DESCRIPTION: Set or clear the GPE's wakeup enable mask bit. |
263 | * the reference count mechanism used in the acpi_enable_gpe and | ||
264 | * acpi_disable_gpe interfaces -- and should be used with care. | ||
265 | * | ||
266 | * Note: Typically used to disable a runtime GPE for short period of time, | ||
267 | * then re-enable it, without disturbing the existing reference counts. This | ||
268 | * is useful, for example, in the Embedded Controller (EC) driver. | ||
269 | * | 225 | * |
270 | ******************************************************************************/ | 226 | ******************************************************************************/ |
271 | acpi_status acpi_set_gpe(acpi_handle gpe_device, u32 gpe_number, u8 action) | 227 | acpi_status acpi_gpe_wakeup(acpi_handle gpe_device, u32 gpe_number, u8 action) |
272 | { | 228 | { |
229 | acpi_status status = AE_OK; | ||
273 | struct acpi_gpe_event_info *gpe_event_info; | 230 | struct acpi_gpe_event_info *gpe_event_info; |
274 | acpi_status status; | 231 | struct acpi_gpe_register_info *gpe_register_info; |
275 | acpi_cpu_flags flags; | 232 | acpi_cpu_flags flags; |
233 | u32 register_bit; | ||
276 | 234 | ||
277 | ACPI_FUNCTION_TRACE(acpi_set_gpe); | 235 | ACPI_FUNCTION_TRACE(acpi_gpe_wakeup); |
278 | 236 | ||
279 | flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); | 237 | flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); |
280 | 238 | ||
281 | /* Ensure that we have a valid GPE number */ | 239 | /* Ensure that we have a valid GPE number */ |
282 | 240 | ||
283 | gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number); | 241 | gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number); |
284 | if (!gpe_event_info) { | 242 | if (!gpe_event_info || !(gpe_event_info->flags & ACPI_GPE_CAN_WAKE)) { |
285 | status = AE_BAD_PARAMETER; | 243 | status = AE_BAD_PARAMETER; |
286 | goto unlock_and_exit; | 244 | goto unlock_and_exit; |
287 | } | 245 | } |
288 | 246 | ||
247 | gpe_register_info = gpe_event_info->register_info; | ||
248 | if (!gpe_register_info) { | ||
249 | status = AE_NOT_EXIST; | ||
250 | goto unlock_and_exit; | ||
251 | } | ||
252 | |||
253 | register_bit = | ||
254 | acpi_hw_get_gpe_register_bit(gpe_event_info, gpe_register_info); | ||
255 | |||
289 | /* Perform the action */ | 256 | /* Perform the action */ |
290 | 257 | ||
291 | switch (action) { | 258 | switch (action) { |
292 | case ACPI_GPE_ENABLE: | 259 | case ACPI_GPE_ENABLE: |
293 | status = acpi_clear_and_enable_gpe(gpe_event_info); | 260 | ACPI_SET_BIT(gpe_register_info->enable_for_wake, |
261 | (u8)register_bit); | ||
294 | break; | 262 | break; |
295 | 263 | ||
296 | case ACPI_GPE_DISABLE: | 264 | case ACPI_GPE_DISABLE: |
297 | status = acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_DISABLE); | 265 | ACPI_CLEAR_BIT(gpe_register_info->enable_for_wake, |
266 | (u8)register_bit); | ||
298 | break; | 267 | break; |
299 | 268 | ||
300 | default: | 269 | default: |
270 | ACPI_ERROR((AE_INFO, "%u, Invalid action", action)); | ||
301 | status = AE_BAD_PARAMETER; | 271 | status = AE_BAD_PARAMETER; |
302 | break; | 272 | break; |
303 | } | 273 | } |
304 | 274 | ||
305 | unlock_and_exit: | 275 | unlock_and_exit: |
306 | acpi_os_release_lock(acpi_gbl_gpe_lock, flags); | 276 | acpi_os_release_lock(acpi_gbl_gpe_lock, flags); |
307 | return_ACPI_STATUS(status); | 277 | return_ACPI_STATUS(status); |
308 | } | 278 | } |
309 | 279 | ||
310 | ACPI_EXPORT_SYMBOL(acpi_set_gpe) | 280 | ACPI_EXPORT_SYMBOL(acpi_gpe_wakeup) |
311 | 281 | ||
312 | /******************************************************************************* | 282 | /******************************************************************************* |
313 | * | 283 | * |
@@ -315,17 +285,14 @@ ACPI_EXPORT_SYMBOL(acpi_set_gpe) | |||
315 | * | 285 | * |
316 | * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1 | 286 | * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1 |
317 | * gpe_number - GPE level within the GPE block | 287 | * gpe_number - GPE level within the GPE block |
318 | * gpe_type - ACPI_GPE_TYPE_RUNTIME or ACPI_GPE_TYPE_WAKE | ||
319 | * or both | ||
320 | * | 288 | * |
321 | * RETURN: Status | 289 | * RETURN: Status |
322 | * | 290 | * |
323 | * DESCRIPTION: Add a reference to a GPE. On the first reference, the GPE is | 291 | * DESCRIPTION: Add a reference to a GPE. On the first reference, the GPE is |
324 | * hardware-enabled (for runtime GPEs), or the GPE register mask | 292 | * hardware-enabled. |
325 | * is updated (for wake GPEs). | ||
326 | * | 293 | * |
327 | ******************************************************************************/ | 294 | ******************************************************************************/ |
328 | acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number, u8 gpe_type) | 295 | acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number) |
329 | { | 296 | { |
330 | acpi_status status = AE_OK; | 297 | acpi_status status = AE_OK; |
331 | struct acpi_gpe_event_info *gpe_event_info; | 298 | struct acpi_gpe_event_info *gpe_event_info; |
@@ -333,12 +300,6 @@ acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number, u8 gpe_type) | |||
333 | 300 | ||
334 | ACPI_FUNCTION_TRACE(acpi_enable_gpe); | 301 | ACPI_FUNCTION_TRACE(acpi_enable_gpe); |
335 | 302 | ||
336 | /* Parameter validation */ | ||
337 | |||
338 | if (!gpe_type || (gpe_type & ~ACPI_GPE_TYPE_WAKE_RUN)) { | ||
339 | return_ACPI_STATUS(AE_BAD_PARAMETER); | ||
340 | } | ||
341 | |||
342 | flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); | 303 | flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); |
343 | 304 | ||
344 | /* Ensure that we have a valid GPE number */ | 305 | /* Ensure that we have a valid GPE number */ |
@@ -349,46 +310,19 @@ acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number, u8 gpe_type) | |||
349 | goto unlock_and_exit; | 310 | goto unlock_and_exit; |
350 | } | 311 | } |
351 | 312 | ||
352 | if (gpe_type & ACPI_GPE_TYPE_RUNTIME) { | 313 | if (gpe_event_info->runtime_count == ACPI_UINT8_MAX) { |
353 | if (gpe_event_info->runtime_count == ACPI_UINT8_MAX) { | 314 | status = AE_LIMIT; /* Too many references */ |
354 | status = AE_LIMIT; /* Too many references */ | 315 | goto unlock_and_exit; |
355 | goto unlock_and_exit; | ||
356 | } | ||
357 | |||
358 | gpe_event_info->runtime_count++; | ||
359 | if (gpe_event_info->runtime_count == 1) { | ||
360 | status = acpi_ev_update_gpe_enable_masks(gpe_event_info); | ||
361 | if (ACPI_SUCCESS(status)) { | ||
362 | status = acpi_clear_and_enable_gpe(gpe_event_info); | ||
363 | } | ||
364 | |||
365 | if (ACPI_FAILURE(status)) { | ||
366 | gpe_event_info->runtime_count--; | ||
367 | goto unlock_and_exit; | ||
368 | } | ||
369 | } | ||
370 | } | 316 | } |
371 | 317 | ||
372 | if (gpe_type & ACPI_GPE_TYPE_WAKE) { | 318 | gpe_event_info->runtime_count++; |
373 | /* The GPE must have the ability to wake the system */ | 319 | if (gpe_event_info->runtime_count == 1) { |
374 | 320 | status = acpi_ev_update_gpe_enable_mask(gpe_event_info); | |
375 | if (!(gpe_event_info->flags & ACPI_GPE_CAN_WAKE)) { | 321 | if (ACPI_SUCCESS(status)) { |
376 | status = AE_TYPE; | 322 | status = acpi_ev_enable_gpe(gpe_event_info); |
377 | goto unlock_and_exit; | ||
378 | } | 323 | } |
379 | 324 | if (ACPI_FAILURE(status)) { | |
380 | if (gpe_event_info->wakeup_count == ACPI_UINT8_MAX) { | 325 | gpe_event_info->runtime_count--; |
381 | status = AE_LIMIT; /* Too many references */ | ||
382 | goto unlock_and_exit; | ||
383 | } | ||
384 | |||
385 | /* | ||
386 | * Update the enable mask on the first wakeup reference. Wake GPEs | ||
387 | * are only hardware-enabled just before sleeping. | ||
388 | */ | ||
389 | gpe_event_info->wakeup_count++; | ||
390 | if (gpe_event_info->wakeup_count == 1) { | ||
391 | status = acpi_ev_update_gpe_enable_masks(gpe_event_info); | ||
392 | } | 326 | } |
393 | } | 327 | } |
394 | 328 | ||
@@ -404,8 +338,6 @@ ACPI_EXPORT_SYMBOL(acpi_enable_gpe) | |||
404 | * | 338 | * |
405 | * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1 | 339 | * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1 |
406 | * gpe_number - GPE level within the GPE block | 340 | * gpe_number - GPE level within the GPE block |
407 | * gpe_type - ACPI_GPE_TYPE_RUNTIME or ACPI_GPE_TYPE_WAKE | ||
408 | * or both | ||
409 | * | 341 | * |
410 | * RETURN: Status | 342 | * RETURN: Status |
411 | * | 343 | * |
@@ -414,7 +346,7 @@ ACPI_EXPORT_SYMBOL(acpi_enable_gpe) | |||
414 | * the GPE mask bit disabled (for wake GPEs) | 346 | * the GPE mask bit disabled (for wake GPEs) |
415 | * | 347 | * |
416 | ******************************************************************************/ | 348 | ******************************************************************************/ |
417 | acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number, u8 gpe_type) | 349 | acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number) |
418 | { | 350 | { |
419 | acpi_status status = AE_OK; | 351 | acpi_status status = AE_OK; |
420 | struct acpi_gpe_event_info *gpe_event_info; | 352 | struct acpi_gpe_event_info *gpe_event_info; |
@@ -422,12 +354,6 @@ acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number, u8 gpe_type | |||
422 | 354 | ||
423 | ACPI_FUNCTION_TRACE(acpi_disable_gpe); | 355 | ACPI_FUNCTION_TRACE(acpi_disable_gpe); |
424 | 356 | ||
425 | /* Parameter validation */ | ||
426 | |||
427 | if (!gpe_type || (gpe_type & ~ACPI_GPE_TYPE_WAKE_RUN)) { | ||
428 | return_ACPI_STATUS(AE_BAD_PARAMETER); | ||
429 | } | ||
430 | |||
431 | flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); | 357 | flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); |
432 | 358 | ||
433 | /* Ensure that we have a valid GPE number */ | 359 | /* Ensure that we have a valid GPE number */ |
@@ -440,41 +366,21 @@ acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number, u8 gpe_type | |||
440 | 366 | ||
441 | /* Hardware-disable a runtime GPE on removal of the last reference */ | 367 | /* Hardware-disable a runtime GPE on removal of the last reference */ |
442 | 368 | ||
443 | if (gpe_type & ACPI_GPE_TYPE_RUNTIME) { | 369 | if (!gpe_event_info->runtime_count) { |
444 | if (!gpe_event_info->runtime_count) { | 370 | status = AE_LIMIT; /* There are no references to remove */ |
445 | status = AE_LIMIT; /* There are no references to remove */ | 371 | goto unlock_and_exit; |
446 | goto unlock_and_exit; | ||
447 | } | ||
448 | |||
449 | gpe_event_info->runtime_count--; | ||
450 | if (!gpe_event_info->runtime_count) { | ||
451 | status = acpi_ev_update_gpe_enable_masks(gpe_event_info); | ||
452 | if (ACPI_SUCCESS(status)) { | ||
453 | status = acpi_hw_low_set_gpe(gpe_event_info, | ||
454 | ACPI_GPE_DISABLE); | ||
455 | } | ||
456 | |||
457 | if (ACPI_FAILURE(status)) { | ||
458 | gpe_event_info->runtime_count++; | ||
459 | goto unlock_and_exit; | ||
460 | } | ||
461 | } | ||
462 | } | 372 | } |
463 | 373 | ||
464 | /* | 374 | gpe_event_info->runtime_count--; |
465 | * Update masks for wake GPE on removal of the last reference. | 375 | if (!gpe_event_info->runtime_count) { |
466 | * No need to hardware-disable wake GPEs here, they are not currently | 376 | status = acpi_ev_update_gpe_enable_mask(gpe_event_info); |
467 | * enabled. | 377 | if (ACPI_SUCCESS(status)) { |
468 | */ | 378 | status = |
469 | if (gpe_type & ACPI_GPE_TYPE_WAKE) { | 379 | acpi_hw_low_set_gpe(gpe_event_info, |
470 | if (!gpe_event_info->wakeup_count) { | 380 | ACPI_GPE_DISABLE); |
471 | status = AE_LIMIT; /* There are no references to remove */ | ||
472 | goto unlock_and_exit; | ||
473 | } | 381 | } |
474 | 382 | if (ACPI_FAILURE(status)) { | |
475 | gpe_event_info->wakeup_count--; | 383 | gpe_event_info->runtime_count++; |
476 | if (!gpe_event_info->wakeup_count) { | ||
477 | status = acpi_ev_update_gpe_enable_masks(gpe_event_info); | ||
478 | } | 384 | } |
479 | } | 385 | } |
480 | 386 | ||
@@ -486,6 +392,59 @@ ACPI_EXPORT_SYMBOL(acpi_disable_gpe) | |||
486 | 392 | ||
487 | /******************************************************************************* | 393 | /******************************************************************************* |
488 | * | 394 | * |
395 | * FUNCTION: acpi_gpe_can_wake | ||
396 | * | ||
397 | * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1 | ||
398 | * gpe_number - GPE level within the GPE block | ||
399 | * | ||
400 | * RETURN: Status | ||
401 | * | ||
402 | * DESCRIPTION: Set the ACPI_GPE_CAN_WAKE flag for the given GPE. If the GPE | ||
403 | * has a corresponding method and is currently enabled, disable it | ||
404 | * (GPEs with corresponding methods are enabled unconditionally | ||
405 | * during initialization, but GPEs that can wake up are expected | ||
406 | * to be initially disabled). | ||
407 | * | ||
408 | ******************************************************************************/ | ||
409 | acpi_status acpi_gpe_can_wake(acpi_handle gpe_device, u32 gpe_number) | ||
410 | { | ||
411 | acpi_status status = AE_OK; | ||
412 | struct acpi_gpe_event_info *gpe_event_info; | ||
413 | acpi_cpu_flags flags; | ||
414 | u8 disable = 0; | ||
415 | |||
416 | ACPI_FUNCTION_TRACE(acpi_gpe_can_wake); | ||
417 | |||
418 | flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); | ||
419 | |||
420 | /* Ensure that we have a valid GPE number */ | ||
421 | |||
422 | gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number); | ||
423 | if (!gpe_event_info) { | ||
424 | status = AE_BAD_PARAMETER; | ||
425 | goto unlock_and_exit; | ||
426 | } | ||
427 | |||
428 | if (gpe_event_info->flags & ACPI_GPE_CAN_WAKE) { | ||
429 | goto unlock_and_exit; | ||
430 | } | ||
431 | |||
432 | gpe_event_info->flags |= ACPI_GPE_CAN_WAKE; | ||
433 | disable = (gpe_event_info->flags & ACPI_GPE_DISPATCH_METHOD) | ||
434 | && gpe_event_info->runtime_count; | ||
435 | |||
436 | unlock_and_exit: | ||
437 | acpi_os_release_lock(acpi_gbl_gpe_lock, flags); | ||
438 | |||
439 | if (disable) | ||
440 | status = acpi_disable_gpe(gpe_device, gpe_number); | ||
441 | |||
442 | return_ACPI_STATUS(status); | ||
443 | } | ||
444 | ACPI_EXPORT_SYMBOL(acpi_gpe_can_wake) | ||
445 | |||
446 | /******************************************************************************* | ||
447 | * | ||
489 | * FUNCTION: acpi_disable_event | 448 | * FUNCTION: acpi_disable_event |
490 | * | 449 | * |
491 | * PARAMETERS: Event - The fixed eventto be enabled | 450 | * PARAMETERS: Event - The fixed eventto be enabled |
@@ -800,7 +759,7 @@ acpi_install_gpe_block(acpi_handle gpe_device, | |||
800 | 759 | ||
801 | obj_desc->device.gpe_block = gpe_block; | 760 | obj_desc->device.gpe_block = gpe_block; |
802 | 761 | ||
803 | /* Run the _PRW methods and enable the runtime GPEs in the new block */ | 762 | /* Enable the runtime GPEs in the new block */ |
804 | 763 | ||
805 | status = acpi_ev_initialize_gpe_block(node, gpe_block); | 764 | status = acpi_ev_initialize_gpe_block(node, gpe_block); |
806 | 765 | ||