aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/acpica
diff options
context:
space:
mode:
authorRafael J. Wysocki <rjw@sisk.pl>2010-02-17 17:41:07 -0500
committerJesse Barnes <jbarnes@virtuousgeek.org>2010-02-22 19:20:45 -0500
commit9630bdd9b15d2f489c646d8bc04b60e53eb5ec78 (patch)
treeed99f729cb9142492e0cdf2f7d19f2f33069a3f4 /drivers/acpi/acpica
parentc39fae1416d59fd565606793f090cebe3720d50d (diff)
ACPI: Use GPE reference counting to support shared GPEs
ACPI GPEs may map to multiple devices. The current GPE interface only provides a mechanism for enabling and disabling GPEs, making it difficult to change the state of GPEs at runtime without extensive cooperation between devices. Add an API to allow devices to indicate whether or not they want their device's GPE to be enabled for both runtime and wakeup events. Remove the old GPE type handling entirely, which gets rid of various quirks, like the implicit disabling with GPE type setting. This requires a small amount of rework in order to ensure that non-wake GPEs are enabled by default to preserve existing behaviour. Based on patches from Matthew Garrett <mjg@redhat.com>. Signed-off-by: Matthew Garrett <mjg@redhat.com> Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Diffstat (limited to 'drivers/acpi/acpica')
-rw-r--r--drivers/acpi/acpica/acevents.h6
-rw-r--r--drivers/acpi/acpica/aclocal.h2
-rw-r--r--drivers/acpi/acpica/evgpe.c153
-rw-r--r--drivers/acpi/acpica/evgpeblk.c87
-rw-r--r--drivers/acpi/acpica/evxface.c14
-rw-r--r--drivers/acpi/acpica/evxfevnt.c90
6 files changed, 117 insertions, 235 deletions
diff --git a/drivers/acpi/acpica/acevents.h b/drivers/acpi/acpica/acevents.h
index 0bba148a2c61..197aa4f39640 100644
--- a/drivers/acpi/acpica/acevents.h
+++ b/drivers/acpi/acpica/acevents.h
@@ -76,8 +76,7 @@ acpi_ev_queue_notify_request(struct acpi_namespace_node *node,
76 * evgpe - GPE handling and dispatch 76 * evgpe - GPE handling and dispatch
77 */ 77 */
78acpi_status 78acpi_status
79acpi_ev_update_gpe_enable_masks(struct acpi_gpe_event_info *gpe_event_info, 79acpi_ev_update_gpe_enable_masks(struct acpi_gpe_event_info *gpe_event_info);
80 u8 type);
81 80
82acpi_status 81acpi_status
83acpi_ev_enable_gpe(struct acpi_gpe_event_info *gpe_event_info, 82acpi_ev_enable_gpe(struct acpi_gpe_event_info *gpe_event_info,
@@ -122,9 +121,6 @@ acpi_ev_gpe_dispatch(struct acpi_gpe_event_info *gpe_event_info,
122u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info *gpe_xrupt_list); 121u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info *gpe_xrupt_list);
123 122
124acpi_status 123acpi_status
125acpi_ev_set_gpe_type(struct acpi_gpe_event_info *gpe_event_info, u8 type);
126
127acpi_status
128acpi_ev_check_for_wake_only_gpe(struct acpi_gpe_event_info *gpe_event_info); 124acpi_ev_check_for_wake_only_gpe(struct acpi_gpe_event_info *gpe_event_info);
129 125
130acpi_status acpi_ev_gpe_initialize(void); 126acpi_status acpi_ev_gpe_initialize(void);
diff --git a/drivers/acpi/acpica/aclocal.h b/drivers/acpi/acpica/aclocal.h
index 81e64f478679..13cb80caacde 100644
--- a/drivers/acpi/acpica/aclocal.h
+++ b/drivers/acpi/acpica/aclocal.h
@@ -426,6 +426,8 @@ struct acpi_gpe_event_info {
426 struct acpi_gpe_register_info *register_info; /* Backpointer to register info */ 426 struct acpi_gpe_register_info *register_info; /* Backpointer to register info */
427 u8 flags; /* Misc info about this GPE */ 427 u8 flags; /* Misc info about this GPE */
428 u8 gpe_number; /* This GPE */ 428 u8 gpe_number; /* This GPE */
429 u8 runtime_count;
430 u8 wakeup_count;
429}; 431};
430 432
431/* Information about a GPE register pair, one per each status/enable pair in an array */ 433/* Information about a GPE register pair, one per each status/enable pair in an array */
diff --git a/drivers/acpi/acpica/evgpe.c b/drivers/acpi/acpica/evgpe.c
index afacf4416c73..30ca3a30ef00 100644
--- a/drivers/acpi/acpica/evgpe.c
+++ b/drivers/acpi/acpica/evgpe.c
@@ -54,54 +54,9 @@ static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context);
54 54
55/******************************************************************************* 55/*******************************************************************************
56 * 56 *
57 * FUNCTION: acpi_ev_set_gpe_type
58 *
59 * PARAMETERS: gpe_event_info - GPE to set
60 * Type - New type
61 *
62 * RETURN: Status
63 *
64 * DESCRIPTION: Sets the new type for the GPE (wake, run, or wake/run)
65 *
66 ******************************************************************************/
67
68acpi_status
69acpi_ev_set_gpe_type(struct acpi_gpe_event_info *gpe_event_info, u8 type)
70{
71 acpi_status status;
72
73 ACPI_FUNCTION_TRACE(ev_set_gpe_type);
74
75 /* Validate type and update register enable masks */
76
77 switch (type) {
78 case ACPI_GPE_TYPE_WAKE:
79 case ACPI_GPE_TYPE_RUNTIME:
80 case ACPI_GPE_TYPE_WAKE_RUN:
81 break;
82
83 default:
84 return_ACPI_STATUS(AE_BAD_PARAMETER);
85 }
86
87 /* Disable the GPE if currently enabled */
88
89 status = acpi_ev_disable_gpe(gpe_event_info);
90
91 /* Clear the type bits and insert the new Type */
92
93 gpe_event_info->flags &= ~ACPI_GPE_TYPE_MASK;
94 gpe_event_info->flags |= type;
95 return_ACPI_STATUS(status);
96}
97
98/*******************************************************************************
99 *
100 * FUNCTION: acpi_ev_update_gpe_enable_masks 57 * FUNCTION: acpi_ev_update_gpe_enable_masks
101 * 58 *
102 * PARAMETERS: gpe_event_info - GPE to update 59 * PARAMETERS: gpe_event_info - GPE to update
103 * Type - What to do: ACPI_GPE_DISABLE or
104 * ACPI_GPE_ENABLE
105 * 60 *
106 * RETURN: Status 61 * RETURN: Status
107 * 62 *
@@ -110,8 +65,7 @@ acpi_ev_set_gpe_type(struct acpi_gpe_event_info *gpe_event_info, u8 type)
110 ******************************************************************************/ 65 ******************************************************************************/
111 66
112acpi_status 67acpi_status
113acpi_ev_update_gpe_enable_masks(struct acpi_gpe_event_info *gpe_event_info, 68acpi_ev_update_gpe_enable_masks(struct acpi_gpe_event_info *gpe_event_info)
114 u8 type)
115{ 69{
116 struct acpi_gpe_register_info *gpe_register_info; 70 struct acpi_gpe_register_info *gpe_register_info;
117 u8 register_bit; 71 u8 register_bit;
@@ -127,37 +81,14 @@ acpi_ev_update_gpe_enable_masks(struct acpi_gpe_event_info *gpe_event_info,
127 (1 << 81 (1 <<
128 (gpe_event_info->gpe_number - gpe_register_info->base_gpe_number)); 82 (gpe_event_info->gpe_number - gpe_register_info->base_gpe_number));
129 83
130 /* 1) Disable case. Simply clear all enable bits */ 84 ACPI_CLEAR_BIT(gpe_register_info->enable_for_wake, register_bit);
131 85 ACPI_CLEAR_BIT(gpe_register_info->enable_for_run, register_bit);
132 if (type == ACPI_GPE_DISABLE) {
133 ACPI_CLEAR_BIT(gpe_register_info->enable_for_wake,
134 register_bit);
135 ACPI_CLEAR_BIT(gpe_register_info->enable_for_run, register_bit);
136 return_ACPI_STATUS(AE_OK);
137 }
138
139 /* 2) Enable case. Set/Clear the appropriate enable bits */
140 86
141 switch (gpe_event_info->flags & ACPI_GPE_TYPE_MASK) { 87 if (gpe_event_info->runtime_count)
142 case ACPI_GPE_TYPE_WAKE:
143 ACPI_SET_BIT(gpe_register_info->enable_for_wake, register_bit);
144 ACPI_CLEAR_BIT(gpe_register_info->enable_for_run, register_bit);
145 break;
146
147 case ACPI_GPE_TYPE_RUNTIME:
148 ACPI_CLEAR_BIT(gpe_register_info->enable_for_wake,
149 register_bit);
150 ACPI_SET_BIT(gpe_register_info->enable_for_run, register_bit); 88 ACPI_SET_BIT(gpe_register_info->enable_for_run, register_bit);
151 break;
152 89
153 case ACPI_GPE_TYPE_WAKE_RUN: 90 if (gpe_event_info->wakeup_count)
154 ACPI_SET_BIT(gpe_register_info->enable_for_wake, register_bit); 91 ACPI_SET_BIT(gpe_register_info->enable_for_wake, register_bit);
155 ACPI_SET_BIT(gpe_register_info->enable_for_run, register_bit);
156 break;
157
158 default:
159 return_ACPI_STATUS(AE_BAD_PARAMETER);
160 }
161 92
162 return_ACPI_STATUS(AE_OK); 93 return_ACPI_STATUS(AE_OK);
163} 94}
@@ -186,47 +117,20 @@ acpi_ev_enable_gpe(struct acpi_gpe_event_info *gpe_event_info,
186 117
187 /* Make sure HW enable masks are updated */ 118 /* Make sure HW enable masks are updated */
188 119
189 status = 120 status = acpi_ev_update_gpe_enable_masks(gpe_event_info);
190 acpi_ev_update_gpe_enable_masks(gpe_event_info, ACPI_GPE_ENABLE); 121 if (ACPI_FAILURE(status))
191 if (ACPI_FAILURE(status)) {
192 return_ACPI_STATUS(status); 122 return_ACPI_STATUS(status);
193 }
194 123
195 /* Mark wake-enabled or HW enable, or both */ 124 /* Mark wake-enabled or HW enable, or both */
196 125
197 switch (gpe_event_info->flags & ACPI_GPE_TYPE_MASK) { 126 if (gpe_event_info->runtime_count && write_to_hardware) {
198 case ACPI_GPE_TYPE_WAKE: 127 /* Clear the GPE (of stale events), then enable it */
199 128 status = acpi_hw_clear_gpe(gpe_event_info);
200 ACPI_SET_BIT(gpe_event_info->flags, ACPI_GPE_WAKE_ENABLED); 129 if (ACPI_FAILURE(status))
201 break; 130 return_ACPI_STATUS(status);
202
203 case ACPI_GPE_TYPE_WAKE_RUN:
204
205 ACPI_SET_BIT(gpe_event_info->flags, ACPI_GPE_WAKE_ENABLED);
206
207 /*lint -fallthrough */
208
209 case ACPI_GPE_TYPE_RUNTIME:
210
211 ACPI_SET_BIT(gpe_event_info->flags, ACPI_GPE_RUN_ENABLED);
212
213 if (write_to_hardware) {
214
215 /* Clear the GPE (of stale events), then enable it */
216
217 status = acpi_hw_clear_gpe(gpe_event_info);
218 if (ACPI_FAILURE(status)) {
219 return_ACPI_STATUS(status);
220 }
221
222 /* Enable the requested runtime GPE */
223
224 status = acpi_hw_write_gpe_enable_reg(gpe_event_info);
225 }
226 break;
227 131
228 default: 132 /* Enable the requested runtime GPE */
229 return_ACPI_STATUS(AE_BAD_PARAMETER); 133 status = acpi_hw_write_gpe_enable_reg(gpe_event_info);
230 } 134 }
231 135
232 return_ACPI_STATUS(AE_OK); 136 return_ACPI_STATUS(AE_OK);
@@ -252,34 +156,9 @@ acpi_status acpi_ev_disable_gpe(struct acpi_gpe_event_info *gpe_event_info)
252 156
253 /* Make sure HW enable masks are updated */ 157 /* Make sure HW enable masks are updated */
254 158
255 status = 159 status = acpi_ev_update_gpe_enable_masks(gpe_event_info);
256 acpi_ev_update_gpe_enable_masks(gpe_event_info, ACPI_GPE_DISABLE); 160 if (ACPI_FAILURE(status))
257 if (ACPI_FAILURE(status)) {
258 return_ACPI_STATUS(status); 161 return_ACPI_STATUS(status);
259 }
260
261 /* Clear the appropriate enabled flags for this GPE */
262
263 switch (gpe_event_info->flags & ACPI_GPE_TYPE_MASK) {
264 case ACPI_GPE_TYPE_WAKE:
265 ACPI_CLEAR_BIT(gpe_event_info->flags, ACPI_GPE_WAKE_ENABLED);
266 break;
267
268 case ACPI_GPE_TYPE_WAKE_RUN:
269 ACPI_CLEAR_BIT(gpe_event_info->flags, ACPI_GPE_WAKE_ENABLED);
270
271 /* fallthrough */
272
273 case ACPI_GPE_TYPE_RUNTIME:
274
275 /* Disable the requested runtime GPE */
276
277 ACPI_CLEAR_BIT(gpe_event_info->flags, ACPI_GPE_RUN_ENABLED);
278 break;
279
280 default:
281 break;
282 }
283 162
284 /* 163 /*
285 * Even if we don't know the GPE type, make sure that we always 164 * Even if we don't know the GPE type, make sure that we always
diff --git a/drivers/acpi/acpica/evgpeblk.c b/drivers/acpi/acpica/evgpeblk.c
index 247920900187..3d4c4aca11cd 100644
--- a/drivers/acpi/acpica/evgpeblk.c
+++ b/drivers/acpi/acpica/evgpeblk.c
@@ -258,7 +258,6 @@ acpi_ev_save_method_info(acpi_handle obj_handle,
258 u32 gpe_number; 258 u32 gpe_number;
259 char name[ACPI_NAME_SIZE + 1]; 259 char name[ACPI_NAME_SIZE + 1];
260 u8 type; 260 u8 type;
261 acpi_status status;
262 261
263 ACPI_FUNCTION_TRACE(ev_save_method_info); 262 ACPI_FUNCTION_TRACE(ev_save_method_info);
264 263
@@ -325,26 +324,20 @@ acpi_ev_save_method_info(acpi_handle obj_handle,
325 324
326 /* 325 /*
327 * Now we can add this information to the gpe_event_info block for use 326 * Now we can add this information to the gpe_event_info block for use
328 * during dispatch of this GPE. Default type is RUNTIME, although this may 327 * during dispatch of this GPE.
329 * change when the _PRW methods are executed later.
330 */ 328 */
331 gpe_event_info = 329 gpe_event_info =
332 &gpe_block->event_info[gpe_number - gpe_block->block_base_number]; 330 &gpe_block->event_info[gpe_number - gpe_block->block_base_number];
333 331
334 gpe_event_info->flags = (u8) 332 gpe_event_info->flags = (u8) (type | ACPI_GPE_DISPATCH_METHOD);
335 (type | ACPI_GPE_DISPATCH_METHOD | ACPI_GPE_TYPE_RUNTIME);
336 333
337 gpe_event_info->dispatch.method_node = 334 gpe_event_info->dispatch.method_node =
338 (struct acpi_namespace_node *)obj_handle; 335 (struct acpi_namespace_node *)obj_handle;
339 336
340 /* Update enable mask, but don't enable the HW GPE as of yet */
341
342 status = acpi_ev_enable_gpe(gpe_event_info, FALSE);
343
344 ACPI_DEBUG_PRINT((ACPI_DB_LOAD, 337 ACPI_DEBUG_PRINT((ACPI_DB_LOAD,
345 "Registered GPE method %s as GPE number 0x%.2X\n", 338 "Registered GPE method %s as GPE number 0x%.2X\n",
346 name, gpe_number)); 339 name, gpe_number));
347 return_ACPI_STATUS(status); 340 return_ACPI_STATUS(AE_OK);
348} 341}
349 342
350/******************************************************************************* 343/*******************************************************************************
@@ -454,20 +447,7 @@ acpi_ev_match_prw_and_gpe(acpi_handle obj_handle,
454 gpe_block-> 447 gpe_block->
455 block_base_number]; 448 block_base_number];
456 449
457 /* Mark GPE for WAKE-ONLY but WAKE_DISABLED */ 450 gpe_event_info->flags |= ACPI_GPE_CAN_WAKE;
458
459 gpe_event_info->flags &=
460 ~(ACPI_GPE_WAKE_ENABLED | ACPI_GPE_RUN_ENABLED);
461
462 status =
463 acpi_ev_set_gpe_type(gpe_event_info, ACPI_GPE_TYPE_WAKE);
464 if (ACPI_FAILURE(status)) {
465 goto cleanup;
466 }
467
468 status =
469 acpi_ev_update_gpe_enable_masks(gpe_event_info,
470 ACPI_GPE_DISABLE);
471 } 451 }
472 452
473 cleanup: 453 cleanup:
@@ -989,7 +969,6 @@ acpi_status
989acpi_ev_initialize_gpe_block(struct acpi_namespace_node *gpe_device, 969acpi_ev_initialize_gpe_block(struct acpi_namespace_node *gpe_device,
990 struct acpi_gpe_block_info *gpe_block) 970 struct acpi_gpe_block_info *gpe_block)
991{ 971{
992 acpi_status status;
993 struct acpi_gpe_event_info *gpe_event_info; 972 struct acpi_gpe_event_info *gpe_event_info;
994 struct acpi_gpe_walk_info gpe_info; 973 struct acpi_gpe_walk_info gpe_info;
995 u32 wake_gpe_count; 974 u32 wake_gpe_count;
@@ -1019,42 +998,50 @@ acpi_ev_initialize_gpe_block(struct acpi_namespace_node *gpe_device,
1019 gpe_info.gpe_block = gpe_block; 998 gpe_info.gpe_block = gpe_block;
1020 gpe_info.gpe_device = gpe_device; 999 gpe_info.gpe_device = gpe_device;
1021 1000
1022 status = 1001 acpi_ns_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
1023 acpi_ns_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
1024 ACPI_UINT32_MAX, ACPI_NS_WALK_UNLOCK, 1002 ACPI_UINT32_MAX, ACPI_NS_WALK_UNLOCK,
1025 acpi_ev_match_prw_and_gpe, NULL, 1003 acpi_ev_match_prw_and_gpe, NULL,
1026 &gpe_info, NULL); 1004 &gpe_info, NULL);
1027 } 1005 }
1028 1006
1029 /* 1007 /*
1030 * Enable all GPEs in this block that have these attributes: 1008 * Enable all GPEs that have a corresponding method and aren't
1031 * 1) are "runtime" or "run/wake" GPEs, and 1009 * capable of generating wakeups. Any other GPEs within this block
1032 * 2) have a corresponding _Lxx or _Exx method 1010 * must be enabled via the acpi_enable_gpe() interface.
1033 *
1034 * Any other GPEs within this block must be enabled via the
1035 * acpi_enable_gpe() external interface.
1036 */ 1011 */
1037 wake_gpe_count = 0; 1012 wake_gpe_count = 0;
1038 gpe_enabled_count = 0; 1013 gpe_enabled_count = 0;
1014 if (gpe_device == acpi_gbl_fadt_gpe_device)
1015 gpe_device = NULL;
1039 1016
1040 for (i = 0; i < gpe_block->register_count; i++) { 1017 for (i = 0; i < gpe_block->register_count; i++) {
1041 for (j = 0; j < 8; j++) { 1018 for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++) {
1019 acpi_status status;
1020 acpi_size gpe_index;
1021 int gpe_number;
1042 1022
1043 /* Get the info block for this particular GPE */ 1023 /* Get the info block for this particular GPE */
1024 gpe_index = (acpi_size)i * ACPI_GPE_REGISTER_WIDTH + j;
1025 gpe_event_info = &gpe_block->event_info[gpe_index];
1044 1026
1045 gpe_event_info = &gpe_block->event_info[((acpi_size) i * 1027 if (gpe_event_info->flags & ACPI_GPE_CAN_WAKE) {
1046 ACPI_GPE_REGISTER_WIDTH)
1047 + j];
1048
1049 if (((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) ==
1050 ACPI_GPE_DISPATCH_METHOD) &&
1051 (gpe_event_info->flags & ACPI_GPE_TYPE_RUNTIME)) {
1052 gpe_enabled_count++;
1053 }
1054
1055 if (gpe_event_info->flags & ACPI_GPE_TYPE_WAKE) {
1056 wake_gpe_count++; 1028 wake_gpe_count++;
1029 if (acpi_gbl_leave_wake_gpes_disabled)
1030 continue;
1057 } 1031 }
1032
1033 if (!(gpe_event_info->flags & ACPI_GPE_DISPATCH_METHOD))
1034 continue;
1035
1036 gpe_number = gpe_index + gpe_block->block_base_number;
1037 status = acpi_enable_gpe(gpe_device, gpe_number,
1038 ACPI_GPE_TYPE_RUNTIME);
1039 if (ACPI_FAILURE(status))
1040 ACPI_ERROR((AE_INFO,
1041 "Failed to enable GPE %02X\n",
1042 gpe_number));
1043 else
1044 gpe_enabled_count++;
1058 } 1045 }
1059 } 1046 }
1060 1047
@@ -1062,15 +1049,7 @@ acpi_ev_initialize_gpe_block(struct acpi_namespace_node *gpe_device,
1062 "Found %u Wake, Enabled %u Runtime GPEs in this block\n", 1049 "Found %u Wake, Enabled %u Runtime GPEs in this block\n",
1063 wake_gpe_count, gpe_enabled_count)); 1050 wake_gpe_count, gpe_enabled_count));
1064 1051
1065 /* Enable all valid runtime GPEs found above */ 1052 return_ACPI_STATUS(AE_OK);
1066
1067 status = acpi_hw_enable_runtime_gpe_block(NULL, gpe_block, NULL);
1068 if (ACPI_FAILURE(status)) {
1069 ACPI_ERROR((AE_INFO, "Could not enable GPEs in GpeBlock %p",
1070 gpe_block));
1071 }
1072
1073 return_ACPI_STATUS(status);
1074} 1053}
1075 1054
1076/******************************************************************************* 1055/*******************************************************************************
diff --git a/drivers/acpi/acpica/evxface.c b/drivers/acpi/acpica/evxface.c
index 2fe0809d4eb2..166cbfe1c706 100644
--- a/drivers/acpi/acpica/evxface.c
+++ b/drivers/acpi/acpica/evxface.c
@@ -617,13 +617,6 @@ acpi_install_gpe_handler(acpi_handle gpe_device,
617 handler->context = context; 617 handler->context = context;
618 handler->method_node = gpe_event_info->dispatch.method_node; 618 handler->method_node = gpe_event_info->dispatch.method_node;
619 619
620 /* Disable the GPE before installing the handler */
621
622 status = acpi_ev_disable_gpe(gpe_event_info);
623 if (ACPI_FAILURE(status)) {
624 goto unlock_and_exit;
625 }
626
627 /* Install the handler */ 620 /* Install the handler */
628 621
629 flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); 622 flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
@@ -707,13 +700,6 @@ acpi_remove_gpe_handler(acpi_handle gpe_device,
707 goto unlock_and_exit; 700 goto unlock_and_exit;
708 } 701 }
709 702
710 /* Disable the GPE before removing the handler */
711
712 status = acpi_ev_disable_gpe(gpe_event_info);
713 if (ACPI_FAILURE(status)) {
714 goto unlock_and_exit;
715 }
716
717 /* Make sure all deferred tasks are completed */ 703 /* Make sure all deferred tasks are completed */
718 704
719 (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); 705 (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
diff --git a/drivers/acpi/acpica/evxfevnt.c b/drivers/acpi/acpica/evxfevnt.c
index eed7a38d25f2..1aea1a734159 100644
--- a/drivers/acpi/acpica/evxfevnt.c
+++ b/drivers/acpi/acpica/evxfevnt.c
@@ -201,23 +201,27 @@ ACPI_EXPORT_SYMBOL(acpi_enable_event)
201 201
202/******************************************************************************* 202/*******************************************************************************
203 * 203 *
204 * FUNCTION: acpi_set_gpe_type 204 * FUNCTION: acpi_set_gpe
205 * 205 *
206 * PARAMETERS: gpe_device - Parent GPE Device 206 * PARAMETERS: gpe_device - Parent GPE Device
207 * gpe_number - GPE level within the GPE block 207 * gpe_number - GPE level within the GPE block
208 * Type - New GPE type 208 * action - Enable or disable
209 * Called from ISR or not
209 * 210 *
210 * RETURN: Status 211 * RETURN: Status
211 * 212 *
212 * DESCRIPTION: Set the type of an individual GPE 213 * DESCRIPTION: Enable or disable an ACPI event (general purpose)
213 * 214 *
214 ******************************************************************************/ 215 ******************************************************************************/
215acpi_status acpi_set_gpe_type(acpi_handle gpe_device, u32 gpe_number, u8 type) 216acpi_status acpi_set_gpe(acpi_handle gpe_device, u32 gpe_number, u8 action)
216{ 217{
217 acpi_status status = AE_OK; 218 acpi_status status = AE_OK;
219 acpi_cpu_flags flags;
218 struct acpi_gpe_event_info *gpe_event_info; 220 struct acpi_gpe_event_info *gpe_event_info;
219 221
220 ACPI_FUNCTION_TRACE(acpi_set_gpe_type); 222 ACPI_FUNCTION_TRACE(acpi_set_gpe);
223
224 flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
221 225
222 /* Ensure that we have a valid GPE number */ 226 /* Ensure that we have a valid GPE number */
223 227
@@ -227,19 +231,29 @@ acpi_status acpi_set_gpe_type(acpi_handle gpe_device, u32 gpe_number, u8 type)
227 goto unlock_and_exit; 231 goto unlock_and_exit;
228 } 232 }
229 233
230 if ((gpe_event_info->flags & ACPI_GPE_TYPE_MASK) == type) { 234 /* Perform the action */
231 return_ACPI_STATUS(AE_OK); 235
232 } 236 switch (action) {
237 case ACPI_GPE_ENABLE:
238 status = acpi_ev_enable_gpe(gpe_event_info, TRUE);
239 break;
233 240
234 /* Set the new type (will disable GPE if currently enabled) */ 241 case ACPI_GPE_DISABLE:
242 status = acpi_ev_disable_gpe(gpe_event_info);
243 break;
235 244
236 status = acpi_ev_set_gpe_type(gpe_event_info, type); 245 default:
246 ACPI_ERROR((AE_INFO, "Invalid action\n"));
247 status = AE_BAD_PARAMETER;
248 break;
249 }
237 250
238 unlock_and_exit: 251 unlock_and_exit:
252 acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
239 return_ACPI_STATUS(status); 253 return_ACPI_STATUS(status);
240} 254}
241 255
242ACPI_EXPORT_SYMBOL(acpi_set_gpe_type) 256ACPI_EXPORT_SYMBOL(acpi_set_gpe)
243 257
244/******************************************************************************* 258/*******************************************************************************
245 * 259 *
@@ -247,15 +261,14 @@ ACPI_EXPORT_SYMBOL(acpi_set_gpe_type)
247 * 261 *
248 * PARAMETERS: gpe_device - Parent GPE Device 262 * PARAMETERS: gpe_device - Parent GPE Device
249 * gpe_number - GPE level within the GPE block 263 * gpe_number - GPE level within the GPE block
250 * Flags - Just enable, or also wake enable? 264 * type - Purpose the GPE will be used for
251 * Called from ISR or not
252 * 265 *
253 * RETURN: Status 266 * RETURN: Status
254 * 267 *
255 * DESCRIPTION: Enable an ACPI event (general purpose) 268 * DESCRIPTION: Take a reference to a GPE and enable it if necessary
256 * 269 *
257 ******************************************************************************/ 270 ******************************************************************************/
258acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number) 271acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number, u8 type)
259{ 272{
260 acpi_status status = AE_OK; 273 acpi_status status = AE_OK;
261 acpi_cpu_flags flags; 274 acpi_cpu_flags flags;
@@ -273,15 +286,32 @@ acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number)
273 goto unlock_and_exit; 286 goto unlock_and_exit;
274 } 287 }
275 288
276 /* Perform the enable */ 289 if (type & ACPI_GPE_TYPE_RUNTIME) {
290 if (++gpe_event_info->runtime_count == 1)
291 status = acpi_ev_enable_gpe(gpe_event_info, TRUE);
277 292
278 status = acpi_ev_enable_gpe(gpe_event_info, TRUE); 293 if (ACPI_FAILURE(status))
294 gpe_event_info->runtime_count--;
295 }
279 296
280 unlock_and_exit: 297 if (type & ACPI_GPE_TYPE_WAKE) {
298 if (!(gpe_event_info->flags & ACPI_GPE_CAN_WAKE)) {
299 status = AE_BAD_PARAMETER;
300 goto unlock_and_exit;
301 }
302
303 /*
304 * Wake-up GPEs are only enabled right prior to putting the
305 * system into a sleep state.
306 */
307 if (++gpe_event_info->wakeup_count == 1)
308 acpi_ev_update_gpe_enable_masks(gpe_event_info);
309 }
310
311unlock_and_exit:
281 acpi_os_release_lock(acpi_gbl_gpe_lock, flags); 312 acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
282 return_ACPI_STATUS(status); 313 return_ACPI_STATUS(status);
283} 314}
284
285ACPI_EXPORT_SYMBOL(acpi_enable_gpe) 315ACPI_EXPORT_SYMBOL(acpi_enable_gpe)
286 316
287/******************************************************************************* 317/*******************************************************************************
@@ -290,15 +320,14 @@ ACPI_EXPORT_SYMBOL(acpi_enable_gpe)
290 * 320 *
291 * PARAMETERS: gpe_device - Parent GPE Device 321 * PARAMETERS: gpe_device - Parent GPE Device
292 * gpe_number - GPE level within the GPE block 322 * gpe_number - GPE level within the GPE block
293 * Flags - Just disable, or also wake disable? 323 * type - Purpose the GPE won't be used for any more
294 * Called from ISR or not
295 * 324 *
296 * RETURN: Status 325 * RETURN: Status
297 * 326 *
298 * DESCRIPTION: Disable an ACPI event (general purpose) 327 * DESCRIPTION: Release a reference to a GPE and disable it if necessary
299 * 328 *
300 ******************************************************************************/ 329 ******************************************************************************/
301acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number) 330acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number, u8 type)
302{ 331{
303 acpi_status status = AE_OK; 332 acpi_status status = AE_OK;
304 acpi_cpu_flags flags; 333 acpi_cpu_flags flags;
@@ -315,13 +344,24 @@ acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number)
315 goto unlock_and_exit; 344 goto unlock_and_exit;
316 } 345 }
317 346
318 status = acpi_ev_disable_gpe(gpe_event_info); 347 if ((type & ACPI_GPE_TYPE_WAKE) && gpe_event_info->runtime_count) {
348 if (--gpe_event_info->runtime_count == 0)
349 acpi_ev_disable_gpe(gpe_event_info);
350 }
351
352 if ((type & ACPI_GPE_TYPE_RUNTIME) && gpe_event_info->wakeup_count) {
353 /*
354 * Wake-up GPEs are not enabled after leaving system sleep
355 * states, so we don't need to disable them here.
356 */
357 if (--gpe_event_info->wakeup_count == 0)
358 acpi_ev_update_gpe_enable_masks(gpe_event_info);
359 }
319 360
320unlock_and_exit: 361unlock_and_exit:
321 acpi_os_release_lock(acpi_gbl_gpe_lock, flags); 362 acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
322 return_ACPI_STATUS(status); 363 return_ACPI_STATUS(status);
323} 364}
324
325ACPI_EXPORT_SYMBOL(acpi_disable_gpe) 365ACPI_EXPORT_SYMBOL(acpi_disable_gpe)
326 366
327/******************************************************************************* 367/*******************************************************************************