Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'acpi-5.12-rc1-2' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm

Pull more ACPI updates from Rafael Wysocki:
"Fix race condition in generic_serial_bus (I2C) and GPIO Operation
Region handling in ACPICA and reduce some related code duplication
(Hans de Goede)"

* tag 'acpi-5.12-rc1-2' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm:
ACPICA: Remove some code duplication from acpi_ev_address_space_dispatch
ACPICA: Fix race in generic_serial_bus (I2C) and GPIO op_region parameter handling

+62 -35
+1
drivers/acpi/acpica/acobject.h
··· 284 284 acpi_adr_space_handler handler; 285 285 struct acpi_namespace_node *node; /* Parent device */ 286 286 void *context; 287 + acpi_mutex context_mutex; 287 288 acpi_adr_space_setup setup; 288 289 union acpi_operand_object *region_list; /* Regions using this handler */ 289 290 union acpi_operand_object *next;
+7
drivers/acpi/acpica/evhandler.c
··· 489 489 490 490 /* Init handler obj */ 491 491 492 + status = 493 + acpi_os_create_mutex(&handler_obj->address_space.context_mutex); 494 + if (ACPI_FAILURE(status)) { 495 + acpi_ut_remove_reference(handler_obj); 496 + goto unlock_and_exit; 497 + } 498 + 492 499 handler_obj->address_space.space_id = (u8)space_id; 493 500 handler_obj->address_space.handler_flags = flags; 494 501 handler_obj->address_space.region_list = NULL;
+52 -35
drivers/acpi/acpica/evregion.c
··· 112 112 union acpi_operand_object *region_obj2; 113 113 void *region_context = NULL; 114 114 struct acpi_connection_info *context; 115 + acpi_mutex context_mutex; 116 + u8 context_locked; 115 117 acpi_physical_address address; 116 118 117 119 ACPI_FUNCTION_TRACE(ev_address_space_dispatch); ··· 138 136 } 139 137 140 138 context = handler_desc->address_space.context; 139 + context_mutex = handler_desc->address_space.context_mutex; 140 + context_locked = FALSE; 141 141 142 142 /* 143 143 * It may be the case that the region has never been initialized. ··· 208 204 handler = handler_desc->address_space.handler; 209 205 address = (region_obj->region.address + region_offset); 210 206 211 - /* 212 - * Special handling for generic_serial_bus and general_purpose_io: 213 - * There are three extra parameters that must be passed to the 214 - * handler via the context: 215 - * 1) Connection buffer, a resource template from Connection() op 216 - * 2) Length of the above buffer 217 - * 3) Actual access length from the access_as() op 218 - * 219 - * In addition, for general_purpose_io, the Address and bit_width fields 220 - * are defined as follows: 221 - * 1) Address is the pin number index of the field (bit offset from 222 - * the previous Connection) 223 - * 2) bit_width is the actual bit length of the field (number of pins) 224 - */ 225 - if ((region_obj->region.space_id == ACPI_ADR_SPACE_GSBUS) && 226 - context && field_obj) { 227 - 228 - /* Get the Connection (resource_template) buffer */ 229 - 230 - context->connection = field_obj->field.resource_buffer; 231 - context->length = field_obj->field.resource_length; 232 - context->access_length = field_obj->field.access_length; 233 - } 234 - if ((region_obj->region.space_id == ACPI_ADR_SPACE_GPIO) && 235 - context && field_obj) { 236 - 237 - /* Get the Connection (resource_template) buffer */ 238 - 239 - context->connection = field_obj->field.resource_buffer; 240 - context->length = field_obj->field.resource_length; 241 - context->access_length = field_obj->field.access_length; 242 - address = field_obj->field.pin_number_index; 243 - bit_width = field_obj->field.bit_length; 244 - } 245 - 246 207 ACPI_DEBUG_PRINT((ACPI_DB_OPREGION, 247 208 "Handler %p (@%p) Address %8.8X%8.8X [%s]\n", 248 209 &region_obj->region.handler->address_space, handler, ··· 225 256 acpi_ex_exit_interpreter(); 226 257 } 227 258 259 + /* 260 + * Special handling for generic_serial_bus and general_purpose_io: 261 + * There are three extra parameters that must be passed to the 262 + * handler via the context: 263 + * 1) Connection buffer, a resource template from Connection() op 264 + * 2) Length of the above buffer 265 + * 3) Actual access length from the access_as() op 266 + * 267 + * Since we pass these extra parameters via the context, which is 268 + * shared between threads, we must lock the context to avoid these 269 + * parameters being changed from another thread before the handler 270 + * has completed running. 271 + * 272 + * In addition, for general_purpose_io, the Address and bit_width fields 273 + * are defined as follows: 274 + * 1) Address is the pin number index of the field (bit offset from 275 + * the previous Connection) 276 + * 2) bit_width is the actual bit length of the field (number of pins) 277 + */ 278 + if ((region_obj->region.space_id == ACPI_ADR_SPACE_GSBUS || 279 + region_obj->region.space_id == ACPI_ADR_SPACE_GPIO) && 280 + context && field_obj) { 281 + 282 + status = 283 + acpi_os_acquire_mutex(context_mutex, ACPI_WAIT_FOREVER); 284 + if (ACPI_FAILURE(status)) { 285 + goto re_enter_interpreter; 286 + } 287 + 288 + context_locked = TRUE; 289 + 290 + /* Get the Connection (resource_template) buffer */ 291 + 292 + context->connection = field_obj->field.resource_buffer; 293 + context->length = field_obj->field.resource_length; 294 + context->access_length = field_obj->field.access_length; 295 + 296 + if (region_obj->region.space_id == ACPI_ADR_SPACE_GPIO) { 297 + address = field_obj->field.pin_number_index; 298 + bit_width = field_obj->field.bit_length; 299 + } 300 + } 301 + 228 302 /* Call the handler */ 229 303 230 304 status = handler(function, address, bit_width, value, context, 231 305 region_obj2->extra.region_context); 306 + 307 + if (context_locked) { 308 + acpi_os_release_mutex(context_mutex); 309 + } 232 310 233 311 if (ACPI_FAILURE(status)) { 234 312 ACPI_EXCEPTION((AE_INFO, status, "Returned by Handler for [%s]", ··· 293 277 } 294 278 } 295 279 280 + re_enter_interpreter: 296 281 if (!(handler_desc->address_space.handler_flags & 297 282 ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) { 298 283 /*
+2
drivers/acpi/acpica/evxfregn.c
··· 201 201 202 202 /* Now we can delete the handler object */ 203 203 204 + acpi_os_release_mutex(handler_obj->address_space. 205 + context_mutex); 204 206 acpi_ut_remove_reference(handler_obj); 205 207 goto unlock_and_exit; 206 208 }