| .. | .. |
|---|
| 3 | 3 | * |
|---|
| 4 | 4 | * Module Name: evregion - Operation Region support |
|---|
| 5 | 5 | * |
|---|
| 6 | | - * Copyright (C) 2000 - 2018, Intel Corp. |
|---|
| 6 | + * Copyright (C) 2000 - 2020, Intel Corp. |
|---|
| 7 | 7 | * |
|---|
| 8 | 8 | *****************************************************************************/ |
|---|
| 9 | 9 | |
|---|
| .. | .. |
|---|
| 111 | 111 | union acpi_operand_object *region_obj2; |
|---|
| 112 | 112 | void *region_context = NULL; |
|---|
| 113 | 113 | struct acpi_connection_info *context; |
|---|
| 114 | + acpi_mutex context_mutex; |
|---|
| 115 | + u8 context_locked; |
|---|
| 114 | 116 | acpi_physical_address address; |
|---|
| 115 | 117 | |
|---|
| 116 | 118 | ACPI_FUNCTION_TRACE(ev_address_space_dispatch); |
|---|
| .. | .. |
|---|
| 135 | 137 | } |
|---|
| 136 | 138 | |
|---|
| 137 | 139 | context = handler_desc->address_space.context; |
|---|
| 140 | + context_mutex = handler_desc->address_space.context_mutex; |
|---|
| 141 | + context_locked = FALSE; |
|---|
| 138 | 142 | |
|---|
| 139 | 143 | /* |
|---|
| 140 | 144 | * It may be the case that the region has never been initialized. |
|---|
| .. | .. |
|---|
| 203 | 207 | handler = handler_desc->address_space.handler; |
|---|
| 204 | 208 | address = (region_obj->region.address + region_offset); |
|---|
| 205 | 209 | |
|---|
| 206 | | - /* |
|---|
| 207 | | - * Special handling for generic_serial_bus and general_purpose_io: |
|---|
| 208 | | - * There are three extra parameters that must be passed to the |
|---|
| 209 | | - * handler via the context: |
|---|
| 210 | | - * 1) Connection buffer, a resource template from Connection() op |
|---|
| 211 | | - * 2) Length of the above buffer |
|---|
| 212 | | - * 3) Actual access length from the access_as() op |
|---|
| 213 | | - * |
|---|
| 214 | | - * In addition, for general_purpose_io, the Address and bit_width fields |
|---|
| 215 | | - * are defined as follows: |
|---|
| 216 | | - * 1) Address is the pin number index of the field (bit offset from |
|---|
| 217 | | - * the previous Connection) |
|---|
| 218 | | - * 2) bit_width is the actual bit length of the field (number of pins) |
|---|
| 219 | | - */ |
|---|
| 220 | | - if ((region_obj->region.space_id == ACPI_ADR_SPACE_GSBUS) && |
|---|
| 221 | | - context && field_obj) { |
|---|
| 222 | | - |
|---|
| 223 | | - /* Get the Connection (resource_template) buffer */ |
|---|
| 224 | | - |
|---|
| 225 | | - context->connection = field_obj->field.resource_buffer; |
|---|
| 226 | | - context->length = field_obj->field.resource_length; |
|---|
| 227 | | - context->access_length = field_obj->field.access_length; |
|---|
| 228 | | - } |
|---|
| 229 | | - if ((region_obj->region.space_id == ACPI_ADR_SPACE_GPIO) && |
|---|
| 230 | | - context && field_obj) { |
|---|
| 231 | | - |
|---|
| 232 | | - /* Get the Connection (resource_template) buffer */ |
|---|
| 233 | | - |
|---|
| 234 | | - context->connection = field_obj->field.resource_buffer; |
|---|
| 235 | | - context->length = field_obj->field.resource_length; |
|---|
| 236 | | - context->access_length = field_obj->field.access_length; |
|---|
| 237 | | - address = field_obj->field.pin_number_index; |
|---|
| 238 | | - bit_width = field_obj->field.bit_length; |
|---|
| 239 | | - } |
|---|
| 240 | | - |
|---|
| 241 | 210 | ACPI_DEBUG_PRINT((ACPI_DB_OPREGION, |
|---|
| 242 | 211 | "Handler %p (@%p) Address %8.8X%8.8X [%s]\n", |
|---|
| 243 | 212 | ®ion_obj->region.handler->address_space, handler, |
|---|
| .. | .. |
|---|
| 250 | 219 | /* |
|---|
| 251 | 220 | * For handlers other than the default (supplied) handlers, we must |
|---|
| 252 | 221 | * exit the interpreter because the handler *might* block -- we don't |
|---|
| 253 | | - * know what it will do, so we can't hold the lock on the intepreter. |
|---|
| 222 | + * know what it will do, so we can't hold the lock on the interpreter. |
|---|
| 254 | 223 | */ |
|---|
| 255 | 224 | acpi_ex_exit_interpreter(); |
|---|
| 225 | + } |
|---|
| 226 | + |
|---|
| 227 | + /* |
|---|
| 228 | + * Special handling for generic_serial_bus and general_purpose_io: |
|---|
| 229 | + * There are three extra parameters that must be passed to the |
|---|
| 230 | + * handler via the context: |
|---|
| 231 | + * 1) Connection buffer, a resource template from Connection() op |
|---|
| 232 | + * 2) Length of the above buffer |
|---|
| 233 | + * 3) Actual access length from the access_as() op |
|---|
| 234 | + * |
|---|
| 235 | + * Since we pass these extra parameters via the context, which is |
|---|
| 236 | + * shared between threads, we must lock the context to avoid these |
|---|
| 237 | + * parameters being changed from another thread before the handler |
|---|
| 238 | + * has completed running. |
|---|
| 239 | + * |
|---|
| 240 | + * In addition, for general_purpose_io, the Address and bit_width fields |
|---|
| 241 | + * are defined as follows: |
|---|
| 242 | + * 1) Address is the pin number index of the field (bit offset from |
|---|
| 243 | + * the previous Connection) |
|---|
| 244 | + * 2) bit_width is the actual bit length of the field (number of pins) |
|---|
| 245 | + */ |
|---|
| 246 | + if ((region_obj->region.space_id == ACPI_ADR_SPACE_GSBUS) && |
|---|
| 247 | + context && field_obj) { |
|---|
| 248 | + |
|---|
| 249 | + status = |
|---|
| 250 | + acpi_os_acquire_mutex(context_mutex, ACPI_WAIT_FOREVER); |
|---|
| 251 | + if (ACPI_FAILURE(status)) { |
|---|
| 252 | + goto re_enter_interpreter; |
|---|
| 253 | + } |
|---|
| 254 | + |
|---|
| 255 | + context_locked = TRUE; |
|---|
| 256 | + |
|---|
| 257 | + /* Get the Connection (resource_template) buffer */ |
|---|
| 258 | + |
|---|
| 259 | + context->connection = field_obj->field.resource_buffer; |
|---|
| 260 | + context->length = field_obj->field.resource_length; |
|---|
| 261 | + context->access_length = field_obj->field.access_length; |
|---|
| 262 | + } |
|---|
| 263 | + if ((region_obj->region.space_id == ACPI_ADR_SPACE_GPIO) && |
|---|
| 264 | + context && field_obj) { |
|---|
| 265 | + |
|---|
| 266 | + status = |
|---|
| 267 | + acpi_os_acquire_mutex(context_mutex, ACPI_WAIT_FOREVER); |
|---|
| 268 | + if (ACPI_FAILURE(status)) { |
|---|
| 269 | + goto re_enter_interpreter; |
|---|
| 270 | + } |
|---|
| 271 | + |
|---|
| 272 | + context_locked = TRUE; |
|---|
| 273 | + |
|---|
| 274 | + /* Get the Connection (resource_template) buffer */ |
|---|
| 275 | + |
|---|
| 276 | + context->connection = field_obj->field.resource_buffer; |
|---|
| 277 | + context->length = field_obj->field.resource_length; |
|---|
| 278 | + context->access_length = field_obj->field.access_length; |
|---|
| 279 | + address = field_obj->field.pin_number_index; |
|---|
| 280 | + bit_width = field_obj->field.bit_length; |
|---|
| 256 | 281 | } |
|---|
| 257 | 282 | |
|---|
| 258 | 283 | /* Call the handler */ |
|---|
| 259 | 284 | |
|---|
| 260 | 285 | status = handler(function, address, bit_width, value, context, |
|---|
| 261 | 286 | region_obj2->extra.region_context); |
|---|
| 287 | + |
|---|
| 288 | + if (context_locked) { |
|---|
| 289 | + acpi_os_release_mutex(context_mutex); |
|---|
| 290 | + } |
|---|
| 262 | 291 | |
|---|
| 263 | 292 | if (ACPI_FAILURE(status)) { |
|---|
| 264 | 293 | ACPI_EXCEPTION((AE_INFO, status, "Returned by Handler for [%s]", |
|---|
| .. | .. |
|---|
| 276 | 305 | } |
|---|
| 277 | 306 | } |
|---|
| 278 | 307 | |
|---|
| 308 | +re_enter_interpreter: |
|---|
| 279 | 309 | if (!(handler_desc->address_space.handler_flags & |
|---|
| 280 | 310 | ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) { |
|---|
| 281 | 311 | /* |
|---|
| .. | .. |
|---|
| 836 | 866 | objects[1].type = ACPI_TYPE_INTEGER; |
|---|
| 837 | 867 | objects[1].integer.value = ACPI_REG_CONNECT; |
|---|
| 838 | 868 | |
|---|
| 839 | | - status = acpi_evaluate_object(reg_method, NULL, &args, NULL); |
|---|
| 869 | + (void)acpi_evaluate_object(reg_method, NULL, &args, NULL); |
|---|
| 840 | 870 | |
|---|
| 841 | 871 | exit: |
|---|
| 842 | 872 | /* We ignore all errors from above, don't care */ |
|---|
| 843 | 873 | |
|---|
| 844 | | - status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); |
|---|
| 874 | + (void)acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); |
|---|
| 845 | 875 | return_VOID; |
|---|
| 846 | 876 | } |
|---|