aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/acpi/acpica/evregion.c121
-rw-r--r--drivers/acpi/acpica/evrgnini.c2
-rw-r--r--drivers/acpi/acpica/evxfregn.c13
-rw-r--r--include/acpi/actypes.h5
4 files changed, 132 insertions, 9 deletions
diff --git a/drivers/acpi/acpica/evregion.c b/drivers/acpi/acpica/evregion.c
index bea7223d7a71..f0edf5c43c03 100644
--- a/drivers/acpi/acpica/evregion.c
+++ b/drivers/acpi/acpica/evregion.c
@@ -55,6 +55,8 @@ static u8
55acpi_ev_has_default_handler(struct acpi_namespace_node *node, 55acpi_ev_has_default_handler(struct acpi_namespace_node *node,
56 acpi_adr_space_type space_id); 56 acpi_adr_space_type space_id);
57 57
58static void acpi_ev_orphan_ec_reg_method(void);
59
58static acpi_status 60static acpi_status
59acpi_ev_reg_run(acpi_handle obj_handle, 61acpi_ev_reg_run(acpi_handle obj_handle,
60 u32 level, void *context, void **return_value); 62 u32 level, void *context, void **return_value);
@@ -561,7 +563,9 @@ acpi_ev_detach_region(union acpi_operand_object *region_obj,
561 563
562 /* Now stop region accesses by executing the _REG method */ 564 /* Now stop region accesses by executing the _REG method */
563 565
564 status = acpi_ev_execute_reg_method(region_obj, 0); 566 status =
567 acpi_ev_execute_reg_method(region_obj,
568 ACPI_REG_DISCONNECT);
565 if (ACPI_FAILURE(status)) { 569 if (ACPI_FAILURE(status)) {
566 ACPI_EXCEPTION((AE_INFO, status, 570 ACPI_EXCEPTION((AE_INFO, status,
567 "from region _REG, [%s]", 571 "from region _REG, [%s]",
@@ -1062,6 +1066,12 @@ acpi_ev_execute_reg_methods(struct acpi_namespace_node *node,
1062 ACPI_NS_WALK_UNLOCK, acpi_ev_reg_run, 1066 ACPI_NS_WALK_UNLOCK, acpi_ev_reg_run,
1063 NULL, &space_id, NULL); 1067 NULL, &space_id, NULL);
1064 1068
1069 /* Special case for EC: handle "orphan" _REG methods with no region */
1070
1071 if (space_id == ACPI_ADR_SPACE_EC) {
1072 acpi_ev_orphan_ec_reg_method();
1073 }
1074
1065 return_ACPI_STATUS(status); 1075 return_ACPI_STATUS(status);
1066} 1076}
1067 1077
@@ -1120,6 +1130,113 @@ acpi_ev_reg_run(acpi_handle obj_handle,
1120 return (AE_OK); 1130 return (AE_OK);
1121 } 1131 }
1122 1132
1123 status = acpi_ev_execute_reg_method(obj_desc, 1); 1133 status = acpi_ev_execute_reg_method(obj_desc, ACPI_REG_CONNECT);
1124 return (status); 1134 return (status);
1125} 1135}
1136
1137/*******************************************************************************
1138 *
1139 * FUNCTION: acpi_ev_orphan_ec_reg_method
1140 *
1141 * PARAMETERS: None
1142 *
1143 * RETURN: None
1144 *
1145 * DESCRIPTION: Execute an "orphan" _REG method that appears under the EC
1146 * device. This is a _REG method that has no corresponding region
1147 * within the EC device scope. The orphan _REG method appears to
1148 * have been enabled by the description of the ECDT in the ACPI
1149 * specification: "The availability of the region space can be
1150 * detected by providing a _REG method object underneath the
1151 * Embedded Controller device."
1152 *
1153 * To quickly access the EC device, we use the EC_ID that appears
1154 * within the ECDT. Otherwise, we would need to perform a time-
1155 * consuming namespace walk, executing _HID methods to find the
1156 * EC device.
1157 *
1158 ******************************************************************************/
1159
1160static void acpi_ev_orphan_ec_reg_method(void)
1161{
1162 struct acpi_table_ecdt *table;
1163 acpi_status status;
1164 struct acpi_object_list args;
1165 union acpi_object objects[2];
1166 struct acpi_namespace_node *ec_device_node;
1167 struct acpi_namespace_node *reg_method;
1168 struct acpi_namespace_node *next_node;
1169
1170 ACPI_FUNCTION_TRACE(ev_orphan_ec_reg_method);
1171
1172 /* Get the ECDT (if present in system) */
1173
1174 status = acpi_get_table(ACPI_SIG_ECDT, 0,
1175 ACPI_CAST_INDIRECT_PTR(struct acpi_table_header,
1176 &table));
1177 if (ACPI_FAILURE(status)) {
1178 return_VOID;
1179 }
1180
1181 /* We need a valid EC_ID string */
1182
1183 if (!(*table->id)) {
1184 return_VOID;
1185 }
1186
1187 /* Namespace is currently locked, must release */
1188
1189 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
1190
1191 /* Get a handle to the EC device referenced in the ECDT */
1192
1193 status = acpi_get_handle(NULL,
1194 ACPI_CAST_PTR(char, table->id),
1195 ACPI_CAST_PTR(acpi_handle, &ec_device_node));
1196 if (ACPI_FAILURE(status)) {
1197 goto exit;
1198 }
1199
1200 /* Get a handle to a _REG method immediately under the EC device */
1201
1202 status = acpi_get_handle(ec_device_node,
1203 METHOD_NAME__REG, ACPI_CAST_PTR(acpi_handle,
1204 &reg_method));
1205 if (ACPI_FAILURE(status)) {
1206 goto exit;
1207 }
1208
1209 /*
1210 * Execute the _REG method only if there is no Operation Region in
1211 * this scope with the Embedded Controller space ID. Otherwise, it
1212 * will already have been executed. Note, this allows for Regions
1213 * with other space IDs to be present; but the code below will then
1214 * execute the _REG method with the EC space ID argument.
1215 */
1216 next_node = acpi_ns_get_next_node(ec_device_node, NULL);
1217 while (next_node) {
1218 if ((next_node->type == ACPI_TYPE_REGION) &&
1219 (next_node->object) &&
1220 (next_node->object->region.space_id == ACPI_ADR_SPACE_EC)) {
1221 goto exit; /* Do not execute _REG */
1222 }
1223 next_node = acpi_ns_get_next_node(ec_device_node, next_node);
1224 }
1225
1226 /* Evaluate the _REG(EC,Connect) method */
1227
1228 args.count = 2;
1229 args.pointer = objects;
1230 objects[0].type = ACPI_TYPE_INTEGER;
1231 objects[0].integer.value = ACPI_ADR_SPACE_EC;
1232 objects[1].type = ACPI_TYPE_INTEGER;
1233 objects[1].integer.value = ACPI_REG_CONNECT;
1234
1235 status = acpi_evaluate_object(reg_method, NULL, &args, NULL);
1236
1237 exit:
1238 /* We ignore all errors from above, don't care */
1239
1240 status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
1241 return_VOID;
1242}
diff --git a/drivers/acpi/acpica/evrgnini.c b/drivers/acpi/acpica/evrgnini.c
index 9659cee6093e..55a5d35ef34a 100644
--- a/drivers/acpi/acpica/evrgnini.c
+++ b/drivers/acpi/acpica/evrgnini.c
@@ -637,7 +637,7 @@ acpi_ev_initialize_region(union acpi_operand_object *region_obj,
637 637
638 status = 638 status =
639 acpi_ev_execute_reg_method 639 acpi_ev_execute_reg_method
640 (region_obj, 1); 640 (region_obj, ACPI_REG_CONNECT);
641 641
642 if (acpi_ns_locked) { 642 if (acpi_ns_locked) {
643 status = 643 status =
diff --git a/drivers/acpi/acpica/evxfregn.c b/drivers/acpi/acpica/evxfregn.c
index c85c8c45599d..00cd95692a91 100644
--- a/drivers/acpi/acpica/evxfregn.c
+++ b/drivers/acpi/acpica/evxfregn.c
@@ -130,20 +130,21 @@ acpi_install_address_space_handler(acpi_handle device,
130 case ACPI_ADR_SPACE_PCI_CONFIG: 130 case ACPI_ADR_SPACE_PCI_CONFIG:
131 case ACPI_ADR_SPACE_DATA_TABLE: 131 case ACPI_ADR_SPACE_DATA_TABLE:
132 132
133 if (acpi_gbl_reg_methods_executed) { 133 if (!acpi_gbl_reg_methods_executed) {
134 134
135 /* Run all _REG methods for this address space */ 135 /* We will defer execution of the _REG methods for this space */
136 136 goto unlock_and_exit;
137 status = acpi_ev_execute_reg_methods(node, space_id);
138 } 137 }
139 break; 138 break;
140 139
141 default: 140 default:
142
143 status = acpi_ev_execute_reg_methods(node, space_id);
144 break; 141 break;
145 } 142 }
146 143
144 /* Run all _REG methods for this address space */
145
146 status = acpi_ev_execute_reg_methods(node, space_id);
147
147 unlock_and_exit: 148 unlock_and_exit:
148 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); 149 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
149 return_ACPI_STATUS(status); 150 return_ACPI_STATUS(status);
diff --git a/include/acpi/actypes.h b/include/acpi/actypes.h
index f3b29fa5654e..a6412b82a572 100644
--- a/include/acpi/actypes.h
+++ b/include/acpi/actypes.h
@@ -726,6 +726,11 @@ typedef u8 acpi_adr_space_type;
726#define ACPI_ADR_SPACE_DATA_TABLE (acpi_adr_space_type) 0x7E /* Internal to ACPICA only */ 726#define ACPI_ADR_SPACE_DATA_TABLE (acpi_adr_space_type) 0x7E /* Internal to ACPICA only */
727#define ACPI_ADR_SPACE_FIXED_HARDWARE (acpi_adr_space_type) 0x7F 727#define ACPI_ADR_SPACE_FIXED_HARDWARE (acpi_adr_space_type) 0x7F
728 728
729/* Values for _REG connection code */
730
731#define ACPI_REG_DISCONNECT 0
732#define ACPI_REG_CONNECT 1
733
729/* 734/*
730 * bit_register IDs 735 * bit_register IDs
731 * 736 *