0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <acpi/acpi.h>
0011 #include "accommon.h"
0012 #include "acevents.h"
0013 #include "acnamesp.h"
0014
0015 #define _COMPONENT ACPI_EVENTS
0016 ACPI_MODULE_NAME("evgpeinit")
0017 #if (!ACPI_REDUCED_HARDWARE)
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035 #ifdef ACPI_GPE_USE_LOGICAL_ADDRESSES
0036 #define ACPI_FADT_GPE_BLOCK_ADDRESS(N) \
0037 acpi_gbl_FADT.xgpe##N##_block.space_id == \
0038 ACPI_ADR_SPACE_SYSTEM_MEMORY ? \
0039 (u64)acpi_gbl_xgpe##N##_block_logical_address : \
0040 acpi_gbl_FADT.xgpe##N##_block.address
0041 #else
0042 #define ACPI_FADT_GPE_BLOCK_ADDRESS(N) acpi_gbl_FADT.xgpe##N##_block.address
0043 #endif
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056 acpi_status acpi_ev_gpe_initialize(void)
0057 {
0058 u32 register_count0 = 0;
0059 u32 register_count1 = 0;
0060 u32 gpe_number_max = 0;
0061 acpi_status status;
0062 u64 address;
0063
0064 ACPI_FUNCTION_TRACE(ev_gpe_initialize);
0065
0066 ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT,
0067 "Initializing General Purpose Events (GPEs):\n"));
0068
0069 status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
0070 if (ACPI_FAILURE(status)) {
0071 return_ACPI_STATUS(status);
0072 }
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094
0095
0096
0097
0098
0099 address = ACPI_FADT_GPE_BLOCK_ADDRESS(0);
0100
0101 if (acpi_gbl_FADT.gpe0_block_length && address) {
0102
0103
0104
0105 register_count0 = (u16)(acpi_gbl_FADT.gpe0_block_length / 2);
0106 gpe_number_max =
0107 (register_count0 * ACPI_GPE_REGISTER_WIDTH) - 1;
0108
0109
0110
0111 status = acpi_ev_create_gpe_block(acpi_gbl_fadt_gpe_device,
0112 address,
0113 acpi_gbl_FADT.xgpe0_block.
0114 space_id, register_count0, 0,
0115 acpi_gbl_FADT.sci_interrupt,
0116 &acpi_gbl_gpe_fadt_blocks[0]);
0117
0118 if (ACPI_FAILURE(status)) {
0119 ACPI_EXCEPTION((AE_INFO, status,
0120 "Could not create GPE Block 0"));
0121 }
0122 }
0123
0124 address = ACPI_FADT_GPE_BLOCK_ADDRESS(1);
0125
0126 if (acpi_gbl_FADT.gpe1_block_length && address) {
0127
0128
0129
0130 register_count1 = (u16)(acpi_gbl_FADT.gpe1_block_length / 2);
0131
0132
0133
0134 if ((register_count0) &&
0135 (gpe_number_max >= acpi_gbl_FADT.gpe1_base)) {
0136 ACPI_ERROR((AE_INFO,
0137 "GPE0 block (GPE 0 to %u) overlaps the GPE1 block "
0138 "(GPE %u to %u) - Ignoring GPE1",
0139 gpe_number_max, acpi_gbl_FADT.gpe1_base,
0140 acpi_gbl_FADT.gpe1_base +
0141 ((register_count1 *
0142 ACPI_GPE_REGISTER_WIDTH) - 1)));
0143
0144
0145
0146 register_count1 = 0;
0147 } else {
0148
0149
0150 status =
0151 acpi_ev_create_gpe_block(acpi_gbl_fadt_gpe_device,
0152 address,
0153 acpi_gbl_FADT.xgpe1_block.
0154 space_id, register_count1,
0155 acpi_gbl_FADT.gpe1_base,
0156 acpi_gbl_FADT.
0157 sci_interrupt,
0158 &acpi_gbl_gpe_fadt_blocks
0159 [1]);
0160
0161 if (ACPI_FAILURE(status)) {
0162 ACPI_EXCEPTION((AE_INFO, status,
0163 "Could not create GPE Block 1"));
0164 }
0165
0166
0167
0168
0169
0170 }
0171 }
0172
0173
0174
0175 if ((register_count0 + register_count1) == 0) {
0176
0177
0178
0179 ACPI_DEBUG_PRINT((ACPI_DB_INIT,
0180 "There are no GPE blocks defined in the FADT\n"));
0181 goto cleanup;
0182 }
0183
0184 cleanup:
0185 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
0186 return_ACPI_STATUS(AE_OK);
0187 }
0188
0189
0190
0191
0192
0193
0194
0195
0196
0197
0198
0199
0200
0201
0202
0203 void acpi_ev_update_gpes(acpi_owner_id table_owner_id)
0204 {
0205 struct acpi_gpe_xrupt_info *gpe_xrupt_info;
0206 struct acpi_gpe_block_info *gpe_block;
0207 struct acpi_gpe_walk_info walk_info;
0208 acpi_status status = AE_OK;
0209
0210
0211
0212
0213
0214
0215
0216
0217
0218
0219 status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
0220 if (ACPI_FAILURE(status)) {
0221 return;
0222 }
0223
0224 walk_info.count = 0;
0225 walk_info.owner_id = table_owner_id;
0226 walk_info.execute_by_owner_id = TRUE;
0227
0228
0229
0230 gpe_xrupt_info = acpi_gbl_gpe_xrupt_list_head;
0231 while (gpe_xrupt_info) {
0232
0233
0234
0235 gpe_block = gpe_xrupt_info->gpe_block_list_head;
0236 while (gpe_block) {
0237 walk_info.gpe_block = gpe_block;
0238 walk_info.gpe_device = gpe_block->node;
0239
0240 status = acpi_ns_walk_namespace(ACPI_TYPE_METHOD,
0241 walk_info.gpe_device,
0242 ACPI_UINT32_MAX,
0243 ACPI_NS_WALK_NO_UNLOCK,
0244 acpi_ev_match_gpe_method,
0245 NULL, &walk_info, NULL);
0246 if (ACPI_FAILURE(status)) {
0247 ACPI_EXCEPTION((AE_INFO, status,
0248 "While decoding _Lxx/_Exx methods"));
0249 }
0250
0251 gpe_block = gpe_block->next;
0252 }
0253
0254 gpe_xrupt_info = gpe_xrupt_info->next;
0255 }
0256
0257 if (walk_info.count) {
0258 ACPI_INFO(("Enabled %u new GPEs", walk_info.count));
0259 }
0260
0261 (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
0262 return;
0263 }
0264
0265
0266
0267
0268
0269
0270
0271
0272
0273
0274
0275
0276
0277
0278
0279
0280
0281
0282
0283
0284
0285
0286
0287
0288
0289
0290
0291 acpi_status
0292 acpi_ev_match_gpe_method(acpi_handle obj_handle,
0293 u32 level, void *context, void **return_value)
0294 {
0295 struct acpi_namespace_node *method_node =
0296 ACPI_CAST_PTR(struct acpi_namespace_node, obj_handle);
0297 struct acpi_gpe_walk_info *walk_info =
0298 ACPI_CAST_PTR(struct acpi_gpe_walk_info, context);
0299 struct acpi_gpe_event_info *gpe_event_info;
0300 acpi_status status;
0301 u32 gpe_number;
0302 u8 temp_gpe_number;
0303 char name[ACPI_NAMESEG_SIZE + 1];
0304 u8 type;
0305
0306 ACPI_FUNCTION_TRACE(ev_match_gpe_method);
0307
0308
0309
0310 if ((walk_info->execute_by_owner_id) &&
0311 (method_node->owner_id != walk_info->owner_id)) {
0312 return_ACPI_STATUS(AE_OK);
0313 }
0314
0315
0316
0317
0318
0319
0320 ACPI_MOVE_32_TO_32(name, &method_node->name.integer);
0321 name[ACPI_NAMESEG_SIZE] = 0;
0322
0323
0324
0325 if (name[0] != '_') {
0326 return_ACPI_STATUS(AE_OK);
0327 }
0328
0329
0330
0331
0332
0333 switch (name[1]) {
0334 case 'L':
0335
0336 type = ACPI_GPE_LEVEL_TRIGGERED;
0337 break;
0338
0339 case 'E':
0340
0341 type = ACPI_GPE_EDGE_TRIGGERED;
0342 break;
0343
0344 default:
0345
0346
0347
0348 ACPI_DEBUG_PRINT((ACPI_DB_LOAD,
0349 "Ignoring unknown GPE method type: %s "
0350 "(name not of form _Lxx or _Exx)", name));
0351 return_ACPI_STATUS(AE_OK);
0352 }
0353
0354
0355
0356 status = acpi_ut_ascii_to_hex_byte(&name[2], &temp_gpe_number);
0357 if (ACPI_FAILURE(status)) {
0358
0359
0360
0361 ACPI_DEBUG_PRINT((ACPI_DB_LOAD,
0362 "Could not extract GPE number from name: %s "
0363 "(name is not of form _Lxx or _Exx)", name));
0364 return_ACPI_STATUS(AE_OK);
0365 }
0366
0367
0368
0369 gpe_number = (u32)temp_gpe_number;
0370 gpe_event_info =
0371 acpi_ev_low_get_gpe_info(gpe_number, walk_info->gpe_block);
0372 if (!gpe_event_info) {
0373
0374
0375
0376
0377
0378 return_ACPI_STATUS(AE_OK);
0379 }
0380
0381 if ((ACPI_GPE_DISPATCH_TYPE(gpe_event_info->flags) ==
0382 ACPI_GPE_DISPATCH_HANDLER) ||
0383 (ACPI_GPE_DISPATCH_TYPE(gpe_event_info->flags) ==
0384 ACPI_GPE_DISPATCH_RAW_HANDLER)) {
0385
0386
0387
0388 return_ACPI_STATUS(AE_OK);
0389 }
0390
0391 if (ACPI_GPE_DISPATCH_TYPE(gpe_event_info->flags) ==
0392 ACPI_GPE_DISPATCH_METHOD) {
0393
0394
0395
0396
0397 if (type != (gpe_event_info->flags & ACPI_GPE_XRUPT_TYPE_MASK)) {
0398 ACPI_ERROR((AE_INFO,
0399 "For GPE 0x%.2X, found both _L%2.2X and _E%2.2X methods",
0400 gpe_number, gpe_number, gpe_number));
0401 }
0402 return_ACPI_STATUS(AE_OK);
0403 }
0404
0405
0406
0407 (void)acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_DISABLE);
0408
0409
0410
0411
0412
0413 gpe_event_info->flags &= ~(ACPI_GPE_DISPATCH_MASK);
0414 gpe_event_info->flags |= (u8)(type | ACPI_GPE_DISPATCH_METHOD);
0415 gpe_event_info->dispatch.method_node = method_node;
0416
0417 ACPI_DEBUG_PRINT((ACPI_DB_LOAD,
0418 "Registered GPE method %s as GPE number 0x%.2X\n",
0419 name, gpe_number));
0420 return_ACPI_STATUS(AE_OK);
0421 }
0422
0423 #endif