Skip to content

Commit 9630bdd

Browse files
rjwysockijbarnes993
authored andcommitted
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>
1 parent c39fae1 commit 9630bdd

File tree

13 files changed

+188
-325
lines changed

13 files changed

+188
-325
lines changed

drivers/acpi/acpica/acevents.h

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -76,8 +76,7 @@ acpi_ev_queue_notify_request(struct acpi_namespace_node *node,
7676
* evgpe - GPE handling and dispatch
7777
*/
7878
acpi_status
79-
acpi_ev_update_gpe_enable_masks(struct acpi_gpe_event_info *gpe_event_info,
80-
u8 type);
79+
acpi_ev_update_gpe_enable_masks(struct acpi_gpe_event_info *gpe_event_info);
8180

8281
acpi_status
8382
acpi_ev_enable_gpe(struct acpi_gpe_event_info *gpe_event_info,
@@ -121,9 +120,6 @@ acpi_ev_gpe_dispatch(struct acpi_gpe_event_info *gpe_event_info,
121120

122121
u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info *gpe_xrupt_list);
123122

124-
acpi_status
125-
acpi_ev_set_gpe_type(struct acpi_gpe_event_info *gpe_event_info, u8 type);
126-
127123
acpi_status
128124
acpi_ev_check_for_wake_only_gpe(struct acpi_gpe_event_info *gpe_event_info);
129125

drivers/acpi/acpica/aclocal.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -426,6 +426,8 @@ struct acpi_gpe_event_info {
426426
struct acpi_gpe_register_info *register_info; /* Backpointer to register info */
427427
u8 flags; /* Misc info about this GPE */
428428
u8 gpe_number; /* This GPE */
429+
u8 runtime_count;
430+
u8 wakeup_count;
429431
};
430432

431433
/* Information about a GPE register pair, one per each status/enable pair in an array */

drivers/acpi/acpica/evgpe.c

Lines changed: 16 additions & 137 deletions
Original file line numberDiff line numberDiff line change
@@ -52,56 +52,11 @@ ACPI_MODULE_NAME("evgpe")
5252
/* Local prototypes */
5353
static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context);
5454

55-
/*******************************************************************************
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-
68-
acpi_status
69-
acpi_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-
9855
/*******************************************************************************
9956
*
10057
* FUNCTION: acpi_ev_update_gpe_enable_masks
10158
*
10259
* PARAMETERS: gpe_event_info - GPE to update
103-
* Type - What to do: ACPI_GPE_DISABLE or
104-
* ACPI_GPE_ENABLE
10560
*
10661
* RETURN: Status
10762
*
@@ -110,8 +65,7 @@ acpi_ev_set_gpe_type(struct acpi_gpe_event_info *gpe_event_info, u8 type)
11065
******************************************************************************/
11166

11267
acpi_status
113-
acpi_ev_update_gpe_enable_masks(struct acpi_gpe_event_info *gpe_event_info,
114-
u8 type)
68+
acpi_ev_update_gpe_enable_masks(struct acpi_gpe_event_info *gpe_event_info)
11569
{
11670
struct acpi_gpe_register_info *gpe_register_info;
11771
u8 register_bit;
@@ -127,37 +81,14 @@ acpi_ev_update_gpe_enable_masks(struct acpi_gpe_event_info *gpe_event_info,
12781
(1 <<
12882
(gpe_event_info->gpe_number - gpe_register_info->base_gpe_number));
12983

130-
/* 1) Disable case. Simply clear all enable bits */
131-
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 */
84+
ACPI_CLEAR_BIT(gpe_register_info->enable_for_wake, register_bit);
85+
ACPI_CLEAR_BIT(gpe_register_info->enable_for_run, register_bit);
14086

141-
switch (gpe_event_info->flags & ACPI_GPE_TYPE_MASK) {
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);
87+
if (gpe_event_info->runtime_count)
15088
ACPI_SET_BIT(gpe_register_info->enable_for_run, register_bit);
151-
break;
15289

153-
case ACPI_GPE_TYPE_WAKE_RUN:
90+
if (gpe_event_info->wakeup_count)
15491
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-
}
16192

16293
return_ACPI_STATUS(AE_OK);
16394
}
@@ -186,47 +117,20 @@ acpi_ev_enable_gpe(struct acpi_gpe_event_info *gpe_event_info,
186117

187118
/* Make sure HW enable masks are updated */
188119

189-
status =
190-
acpi_ev_update_gpe_enable_masks(gpe_event_info, ACPI_GPE_ENABLE);
191-
if (ACPI_FAILURE(status)) {
120+
status = acpi_ev_update_gpe_enable_masks(gpe_event_info);
121+
if (ACPI_FAILURE(status))
192122
return_ACPI_STATUS(status);
193-
}
194123

195124
/* Mark wake-enabled or HW enable, or both */
196125

197-
switch (gpe_event_info->flags & ACPI_GPE_TYPE_MASK) {
198-
case ACPI_GPE_TYPE_WAKE:
199-
200-
ACPI_SET_BIT(gpe_event_info->flags, ACPI_GPE_WAKE_ENABLED);
201-
break;
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;
126+
if (gpe_event_info->runtime_count && write_to_hardware) {
127+
/* Clear the GPE (of stale events), then enable it */
128+
status = acpi_hw_clear_gpe(gpe_event_info);
129+
if (ACPI_FAILURE(status))
130+
return_ACPI_STATUS(status);
227131

228-
default:
229-
return_ACPI_STATUS(AE_BAD_PARAMETER);
132+
/* Enable the requested runtime GPE */
133+
status = acpi_hw_write_gpe_enable_reg(gpe_event_info);
230134
}
231135

232136
return_ACPI_STATUS(AE_OK);
@@ -252,34 +156,9 @@ acpi_status acpi_ev_disable_gpe(struct acpi_gpe_event_info *gpe_event_info)
252156

253157
/* Make sure HW enable masks are updated */
254158

255-
status =
256-
acpi_ev_update_gpe_enable_masks(gpe_event_info, ACPI_GPE_DISABLE);
257-
if (ACPI_FAILURE(status)) {
159+
status = acpi_ev_update_gpe_enable_masks(gpe_event_info);
160+
if (ACPI_FAILURE(status))
258161
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-
}
283162

284163
/*
285164
* Even if we don't know the GPE type, make sure that we always

drivers/acpi/acpica/evgpeblk.c

Lines changed: 33 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,6 @@ acpi_ev_save_method_info(acpi_handle obj_handle,
258258
u32 gpe_number;
259259
char name[ACPI_NAME_SIZE + 1];
260260
u8 type;
261-
acpi_status status;
262261

263262
ACPI_FUNCTION_TRACE(ev_save_method_info);
264263

@@ -325,26 +324,20 @@ acpi_ev_save_method_info(acpi_handle obj_handle,
325324

326325
/*
327326
* 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
329-
* change when the _PRW methods are executed later.
327+
* during dispatch of this GPE.
330328
*/
331329
gpe_event_info =
332330
&gpe_block->event_info[gpe_number - gpe_block->block_base_number];
333331

334-
gpe_event_info->flags = (u8)
335-
(type | ACPI_GPE_DISPATCH_METHOD | ACPI_GPE_TYPE_RUNTIME);
332+
gpe_event_info->flags = (u8) (type | ACPI_GPE_DISPATCH_METHOD);
336333

337334
gpe_event_info->dispatch.method_node =
338335
(struct acpi_namespace_node *)obj_handle;
339336

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-
344337
ACPI_DEBUG_PRINT((ACPI_DB_LOAD,
345338
"Registered GPE method %s as GPE number 0x%.2X\n",
346339
name, gpe_number));
347-
return_ACPI_STATUS(status);
340+
return_ACPI_STATUS(AE_OK);
348341
}
349342

350343
/*******************************************************************************
@@ -454,20 +447,7 @@ acpi_ev_match_prw_and_gpe(acpi_handle obj_handle,
454447
gpe_block->
455448
block_base_number];
456449

457-
/* Mark GPE for WAKE-ONLY but WAKE_DISABLED */
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);
450+
gpe_event_info->flags |= ACPI_GPE_CAN_WAKE;
471451
}
472452

473453
cleanup:
@@ -989,7 +969,6 @@ acpi_status
989969
acpi_ev_initialize_gpe_block(struct acpi_namespace_node *gpe_device,
990970
struct acpi_gpe_block_info *gpe_block)
991971
{
992-
acpi_status status;
993972
struct acpi_gpe_event_info *gpe_event_info;
994973
struct acpi_gpe_walk_info gpe_info;
995974
u32 wake_gpe_count;
@@ -1019,58 +998,58 @@ acpi_ev_initialize_gpe_block(struct acpi_namespace_node *gpe_device,
1019998
gpe_info.gpe_block = gpe_block;
1020999
gpe_info.gpe_device = gpe_device;
10211000

1022-
status =
1023-
acpi_ns_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
1001+
acpi_ns_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
10241002
ACPI_UINT32_MAX, ACPI_NS_WALK_UNLOCK,
10251003
acpi_ev_match_prw_and_gpe, NULL,
10261004
&gpe_info, NULL);
10271005
}
10281006

10291007
/*
1030-
* Enable all GPEs in this block that have these attributes:
1031-
* 1) are "runtime" or "run/wake" GPEs, and
1032-
* 2) have a corresponding _Lxx or _Exx method
1033-
*
1034-
* Any other GPEs within this block must be enabled via the
1035-
* acpi_enable_gpe() external interface.
1008+
* Enable all GPEs that have a corresponding method and aren't
1009+
* capable of generating wakeups. Any other GPEs within this block
1010+
* must be enabled via the acpi_enable_gpe() interface.
10361011
*/
10371012
wake_gpe_count = 0;
10381013
gpe_enabled_count = 0;
1014+
if (gpe_device == acpi_gbl_fadt_gpe_device)
1015+
gpe_device = NULL;
10391016

10401017
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;
10421022

10431023
/* 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];
10441026

1045-
gpe_event_info = &gpe_block->event_info[((acpi_size) i *
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) {
1027+
if (gpe_event_info->flags & ACPI_GPE_CAN_WAKE) {
10561028
wake_gpe_count++;
1029+
if (acpi_gbl_leave_wake_gpes_disabled)
1030+
continue;
10571031
}
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++;
10581045
}
10591046
}
10601047

10611048
ACPI_DEBUG_PRINT((ACPI_DB_INIT,
10621049
"Found %u Wake, Enabled %u Runtime GPEs in this block\n",
10631050
wake_gpe_count, gpe_enabled_count));
10641051

1065-
/* Enable all valid runtime GPEs found above */
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);
1052+
return_ACPI_STATUS(AE_OK);
10741053
}
10751054

10761055
/*******************************************************************************

0 commit comments

Comments
 (0)