exfield.c 16.4 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5 6 7
/******************************************************************************
 *
 * Module Name: exfield - ACPI AML (p-code) execution - field manipulation
 *
 *****************************************************************************/

/*
8
 * Copyright (C) 2000 - 2016, Intel Corp.
L
Linus Torvalds 已提交
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions, and the following disclaimer,
 *    without modification.
 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
 *    substantially similar to the "NO WARRANTY" disclaimer below
 *    ("Disclaimer") and any redistribution must be conditioned upon
 *    including a substantially similar Disclaimer requirement for further
 *    binary redistribution.
 * 3. Neither the names of the above-listed copyright holders nor the names
 *    of any contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * Alternatively, this software may be distributed under the terms of the
 * GNU General Public License ("GPL") version 2 as published by the Free
 * Software Foundation.
 *
 * NO WARRANTY
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGES.
 */

#include <acpi/acpi.h>
L
Len Brown 已提交
45 46 47
#include "accommon.h"
#include "acdispat.h"
#include "acinterp.h"
48
#include "amlcode.h"
L
Linus Torvalds 已提交
49 50

#define _COMPONENT          ACPI_EXECUTER
L
Len Brown 已提交
51
ACPI_MODULE_NAME("exfield")
L
Linus Torvalds 已提交
52

53 54 55 56 57 58
/* Local prototypes */
static u32
acpi_ex_get_serial_access_length(u32 accessor_type, u32 access_length);

/*******************************************************************************
 *
59
 * FUNCTION:    acpi_ex_get_serial_access_length
60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105
 *
 * PARAMETERS:  accessor_type   - The type of the protocol indicated by region
 *                                field access attributes
 *              access_length   - The access length of the region field
 *
 * RETURN:      Decoded access length
 *
 * DESCRIPTION: This routine returns the length of the generic_serial_bus
 *              protocol bytes
 *
 ******************************************************************************/

static u32
acpi_ex_get_serial_access_length(u32 accessor_type, u32 access_length)
{
	u32 length;

	switch (accessor_type) {
	case AML_FIELD_ATTRIB_QUICK:

		length = 0;
		break;

	case AML_FIELD_ATTRIB_SEND_RCV:
	case AML_FIELD_ATTRIB_BYTE:

		length = 1;
		break;

	case AML_FIELD_ATTRIB_WORD:
	case AML_FIELD_ATTRIB_WORD_CALL:

		length = 2;
		break;

	case AML_FIELD_ATTRIB_MULTIBYTE:
	case AML_FIELD_ATTRIB_RAW_BYTES:
	case AML_FIELD_ATTRIB_RAW_PROCESS:

		length = access_length;
		break;

	case AML_FIELD_ATTRIB_BLOCK:
	case AML_FIELD_ATTRIB_BLOCK_CALL:
	default:

106
		length = ACPI_GSBUS_BUFFER_SIZE - 2;
107 108 109 110 111 112
		break;
	}

	return (length);
}

L
Linus Torvalds 已提交
113 114 115 116 117 118 119 120 121 122
/*******************************************************************************
 *
 * FUNCTION:    acpi_ex_read_data_from_field
 *
 * PARAMETERS:  walk_state          - Current execution state
 *              obj_desc            - The named field
 *              ret_buffer_desc     - Where the return data object is stored
 *
 * RETURN:      Status
 *
123
 * DESCRIPTION: Read from a named field. Returns either an Integer or a
L
Linus Torvalds 已提交
124 125 126
 *              Buffer, depending on the size of the field.
 *
 ******************************************************************************/
127

L
Linus Torvalds 已提交
128
acpi_status
129
acpi_ex_read_data_from_field(struct acpi_walk_state * walk_state,
L
Len Brown 已提交
130 131
			     union acpi_operand_object *obj_desc,
			     union acpi_operand_object **ret_buffer_desc)
L
Linus Torvalds 已提交
132
{
L
Len Brown 已提交
133 134 135 136
	acpi_status status;
	union acpi_operand_object *buffer_desc;
	acpi_size length;
	void *buffer;
137
	u32 function;
138
	u16 accessor_type;
L
Linus Torvalds 已提交
139

B
Bob Moore 已提交
140
	ACPI_FUNCTION_TRACE_PTR(ex_read_data_from_field, obj_desc);
L
Linus Torvalds 已提交
141 142 143 144

	/* Parameter validation */

	if (!obj_desc) {
L
Len Brown 已提交
145
		return_ACPI_STATUS(AE_AML_NO_OPERAND);
L
Linus Torvalds 已提交
146
	}
147
	if (!ret_buffer_desc) {
L
Len Brown 已提交
148
		return_ACPI_STATUS(AE_BAD_PARAMETER);
149
	}
L
Linus Torvalds 已提交
150

151
	if (obj_desc->common.type == ACPI_TYPE_BUFFER_FIELD) {
L
Linus Torvalds 已提交
152 153 154 155 156
		/*
		 * If the buffer_field arguments have not been previously evaluated,
		 * evaluate them now and save the results.
		 */
		if (!(obj_desc->common.flags & AOPOBJ_DATA_VALID)) {
L
Len Brown 已提交
157 158 159
			status = acpi_ds_get_buffer_field_arguments(obj_desc);
			if (ACPI_FAILURE(status)) {
				return_ACPI_STATUS(status);
L
Linus Torvalds 已提交
160 161
			}
		}
162 163
	} else if ((obj_desc->common.type == ACPI_TYPE_LOCAL_REGION_FIELD) &&
		   (obj_desc->field.region_obj->region.space_id ==
164 165
		    ACPI_ADR_SPACE_SMBUS
		    || obj_desc->field.region_obj->region.space_id ==
166 167
		    ACPI_ADR_SPACE_GSBUS
		    || obj_desc->field.region_obj->region.space_id ==
168
		    ACPI_ADR_SPACE_IPMI)) {
L
Linus Torvalds 已提交
169
		/*
170 171
		 * This is an SMBus, GSBus or IPMI read. We must create a buffer to
		 * hold the data and then directly access the region handler.
172
		 *
173 174
		 * Note: SMBus and GSBus protocol value is passed in upper 16-bits
		 * of Function
L
Linus Torvalds 已提交
175
		 */
176 177 178 179 180
		if (obj_desc->field.region_obj->region.space_id ==
		    ACPI_ADR_SPACE_SMBUS) {
			length = ACPI_SMBUS_BUFFER_SIZE;
			function =
			    ACPI_READ | (obj_desc->field.attribute << 16);
181 182
		} else if (obj_desc->field.region_obj->region.space_id ==
			   ACPI_ADR_SPACE_GSBUS) {
183
			accessor_type = obj_desc->field.attribute;
184 185 186 187
			length =
			    acpi_ex_get_serial_access_length(accessor_type,
							     obj_desc->field.
							     access_length);
188 189

			/*
190 191
			 * Add additional 2 bytes for the generic_serial_bus data buffer:
			 *
192 193 194
			 *     Status;    (Byte 0 of the data buffer)
			 *     Length;    (Byte 1 of the data buffer)
			 *     Data[x-1]: (Bytes 2-x of the arbitrary length data buffer)
195 196 197
			 */
			length += 2;
			function = ACPI_READ | (accessor_type << 16);
198 199 200 201 202 203 204
		} else {	/* IPMI */

			length = ACPI_IPMI_BUFFER_SIZE;
			function = ACPI_READ;
		}

		buffer_desc = acpi_ut_create_buffer_object(length);
L
Linus Torvalds 已提交
205
		if (!buffer_desc) {
L
Len Brown 已提交
206
			return_ACPI_STATUS(AE_NO_MEMORY);
L
Linus Torvalds 已提交
207 208 209 210
		}

		/* Lock entire transaction if requested */

211
		acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags);
L
Linus Torvalds 已提交
212

213 214
		/* Call the region handler for the read */

L
Len Brown 已提交
215
		status = acpi_ex_access_region(obj_desc, 0,
216
					       ACPI_CAST_PTR(u64,
L
Len Brown 已提交
217 218
							     buffer_desc->
							     buffer.pointer),
219
					       function);
220

221
		acpi_ex_release_global_lock(obj_desc->common_field.field_flags);
L
Linus Torvalds 已提交
222 223 224 225 226 227
		goto exit;
	}

	/*
	 * Allocate a buffer for the contents of the field.
	 *
228
	 * If the field is larger than the current integer width, create
229
	 * a BUFFER to hold it. Otherwise, use an INTEGER. This allows
L
Linus Torvalds 已提交
230 231 232 233 234
	 * the use of arithmetic operators on the returned value if the
	 * field size is equal or smaller than an Integer.
	 *
	 * Note: Field.length is in bits.
	 */
L
Len Brown 已提交
235 236
	length =
	    (acpi_size) ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->field.bit_length);
237

L
Linus Torvalds 已提交
238
	if (length > acpi_gbl_integer_byte_width) {
B
Bob Moore 已提交
239

L
Linus Torvalds 已提交
240 241
		/* Field is too large for an Integer, create a Buffer instead */

L
Len Brown 已提交
242
		buffer_desc = acpi_ut_create_buffer_object(length);
L
Linus Torvalds 已提交
243
		if (!buffer_desc) {
L
Len Brown 已提交
244
			return_ACPI_STATUS(AE_NO_MEMORY);
L
Linus Torvalds 已提交
245 246
		}
		buffer = buffer_desc->buffer.pointer;
L
Len Brown 已提交
247
	} else {
L
Linus Torvalds 已提交
248 249
		/* Field will fit within an Integer (normal case) */

250
		buffer_desc = acpi_ut_create_integer_object((u64) 0);
L
Linus Torvalds 已提交
251
		if (!buffer_desc) {
L
Len Brown 已提交
252
			return_ACPI_STATUS(AE_NO_MEMORY);
L
Linus Torvalds 已提交
253 254 255 256 257 258
		}

		length = acpi_gbl_integer_byte_width;
		buffer = &buffer_desc->integer.value;
	}

259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278
	if ((obj_desc->common.type == ACPI_TYPE_LOCAL_REGION_FIELD) &&
	    (obj_desc->field.region_obj->region.space_id ==
	     ACPI_ADR_SPACE_GPIO)) {
		/*
		 * For GPIO (general_purpose_io), the Address will be the bit offset
		 * from the previous Connection() operator, making it effectively a
		 * pin number index. The bit_length is the length of the field, which
		 * is thus the number of pins.
		 */
		ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
				  "GPIO FieldRead [FROM]:  Pin %u Bits %u\n",
				  obj_desc->field.pin_number_index,
				  obj_desc->field.bit_length));

		/* Lock entire transaction if requested */

		acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags);

		/* Perform the write */

279 280 281 282
		status =
		    acpi_ex_access_region(obj_desc, 0, (u64 *)buffer,
					  ACPI_READ);

283 284 285 286 287 288 289 290 291
		acpi_ex_release_global_lock(obj_desc->common_field.field_flags);
		if (ACPI_FAILURE(status)) {
			acpi_ut_remove_reference(buffer_desc);
		} else {
			*ret_buffer_desc = buffer_desc;
		}
		return_ACPI_STATUS(status);
	}

L
Len Brown 已提交
292
	ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
B
Bob Moore 已提交
293
			  "FieldRead [TO]:   Obj %p, Type %X, Buf %p, ByteLen %X\n",
294
			  obj_desc, obj_desc->common.type, buffer,
L
Len Brown 已提交
295 296
			  (u32) length));
	ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
B
Bob Moore 已提交
297
			  "FieldRead [FROM]: BitLen %X, BitOff %X, ByteOff %X\n",
L
Len Brown 已提交
298 299 300
			  obj_desc->common_field.bit_length,
			  obj_desc->common_field.start_field_bit_offset,
			  obj_desc->common_field.base_byte_offset));
L
Linus Torvalds 已提交
301 302 303

	/* Lock entire transaction if requested */

304
	acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags);
L
Linus Torvalds 已提交
305 306 307

	/* Read from the field */

L
Len Brown 已提交
308
	status = acpi_ex_extract_from_field(obj_desc, buffer, (u32) length);
309
	acpi_ex_release_global_lock(obj_desc->common_field.field_flags);
L
Linus Torvalds 已提交
310

311
exit:
L
Len Brown 已提交
312 313 314
	if (ACPI_FAILURE(status)) {
		acpi_ut_remove_reference(buffer_desc);
	} else {
L
Linus Torvalds 已提交
315 316 317
		*ret_buffer_desc = buffer_desc;
	}

L
Len Brown 已提交
318
	return_ACPI_STATUS(status);
L
Linus Torvalds 已提交
319 320 321 322 323 324 325 326
}

/*******************************************************************************
 *
 * FUNCTION:    acpi_ex_write_data_to_field
 *
 * PARAMETERS:  source_desc         - Contains data to write
 *              obj_desc            - The named field
R
Robert Moore 已提交
327
 *              result_desc         - Where the return value is returned, if any
L
Linus Torvalds 已提交
328 329 330 331 332 333 334 335
 *
 * RETURN:      Status
 *
 * DESCRIPTION: Write to a named field
 *
 ******************************************************************************/

acpi_status
L
Len Brown 已提交
336 337 338
acpi_ex_write_data_to_field(union acpi_operand_object *source_desc,
			    union acpi_operand_object *obj_desc,
			    union acpi_operand_object **result_desc)
L
Linus Torvalds 已提交
339
{
L
Len Brown 已提交
340 341 342 343
	acpi_status status;
	u32 length;
	void *buffer;
	union acpi_operand_object *buffer_desc;
344
	u32 function;
345
	u16 accessor_type;
L
Linus Torvalds 已提交
346

B
Bob Moore 已提交
347
	ACPI_FUNCTION_TRACE_PTR(ex_write_data_to_field, obj_desc);
L
Linus Torvalds 已提交
348 349 350 351

	/* Parameter validation */

	if (!source_desc || !obj_desc) {
L
Len Brown 已提交
352
		return_ACPI_STATUS(AE_AML_NO_OPERAND);
L
Linus Torvalds 已提交
353 354
	}

355
	if (obj_desc->common.type == ACPI_TYPE_BUFFER_FIELD) {
L
Linus Torvalds 已提交
356 357 358 359 360
		/*
		 * If the buffer_field arguments have not been previously evaluated,
		 * evaluate them now and save the results.
		 */
		if (!(obj_desc->common.flags & AOPOBJ_DATA_VALID)) {
L
Len Brown 已提交
361 362 363
			status = acpi_ds_get_buffer_field_arguments(obj_desc);
			if (ACPI_FAILURE(status)) {
				return_ACPI_STATUS(status);
L
Linus Torvalds 已提交
364 365
			}
		}
366 367
	} else if ((obj_desc->common.type == ACPI_TYPE_LOCAL_REGION_FIELD) &&
		   (obj_desc->field.region_obj->region.space_id ==
368 369
		    ACPI_ADR_SPACE_SMBUS
		    || obj_desc->field.region_obj->region.space_id ==
370 371
		    ACPI_ADR_SPACE_GSBUS
		    || obj_desc->field.region_obj->region.space_id ==
372
		    ACPI_ADR_SPACE_IPMI)) {
L
Linus Torvalds 已提交
373
		/*
374 375 376 377
		 * This is an SMBus, GSBus or IPMI write. We will bypass the entire
		 * field mechanism and handoff the buffer directly to the handler.
		 * For these address spaces, the buffer is bi-directional; on a
		 * write, return data is returned in the same buffer.
378 379
		 *
		 * Source must be a buffer of sufficient size:
380 381
		 * ACPI_SMBUS_BUFFER_SIZE, ACPI_GSBUS_BUFFER_SIZE, or
		 * ACPI_IPMI_BUFFER_SIZE.
L
Linus Torvalds 已提交
382
		 *
383 384
		 * Note: SMBus and GSBus protocol type is passed in upper 16-bits
		 * of Function
L
Linus Torvalds 已提交
385
		 */
386
		if (source_desc->common.type != ACPI_TYPE_BUFFER) {
B
Bob Moore 已提交
387
			ACPI_ERROR((AE_INFO,
388 389
				    "SMBus/IPMI/GenericSerialBus write requires "
				    "Buffer, found type %s",
B
Bob Moore 已提交
390
				    acpi_ut_get_object_type_name(source_desc)));
R
Robert Moore 已提交
391

L
Len Brown 已提交
392
			return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
L
Linus Torvalds 已提交
393 394
		}

395 396 397 398 399
		if (obj_desc->field.region_obj->region.space_id ==
		    ACPI_ADR_SPACE_SMBUS) {
			length = ACPI_SMBUS_BUFFER_SIZE;
			function =
			    ACPI_WRITE | (obj_desc->field.attribute << 16);
400 401
		} else if (obj_desc->field.region_obj->region.space_id ==
			   ACPI_ADR_SPACE_GSBUS) {
402
			accessor_type = obj_desc->field.attribute;
403 404 405 406
			length =
			    acpi_ex_get_serial_access_length(accessor_type,
							     obj_desc->field.
							     access_length);
407 408

			/*
409 410
			 * Add additional 2 bytes for the generic_serial_bus data buffer:
			 *
411 412 413
			 *     Status;    (Byte 0 of the data buffer)
			 *     Length;    (Byte 1 of the data buffer)
			 *     Data[x-1]: (Bytes 2-x of the arbitrary length data buffer)
414 415 416
			 */
			length += 2;
			function = ACPI_WRITE | (accessor_type << 16);
417 418 419 420 421 422 423
		} else {	/* IPMI */

			length = ACPI_IPMI_BUFFER_SIZE;
			function = ACPI_WRITE;
		}

		if (source_desc->buffer.length < length) {
B
Bob Moore 已提交
424
			ACPI_ERROR((AE_INFO,
425 426
				    "SMBus/IPMI/GenericSerialBus write requires "
				    "Buffer of length %u, found length %u",
427
				    length, source_desc->buffer.length));
R
Robert Moore 已提交
428

L
Len Brown 已提交
429
			return_ACPI_STATUS(AE_AML_BUFFER_LIMIT);
L
Linus Torvalds 已提交
430 431
		}

432 433 434
		/* Create the bi-directional buffer */

		buffer_desc = acpi_ut_create_buffer_object(length);
L
Linus Torvalds 已提交
435
		if (!buffer_desc) {
L
Len Brown 已提交
436
			return_ACPI_STATUS(AE_NO_MEMORY);
L
Linus Torvalds 已提交
437 438 439
		}

		buffer = buffer_desc->buffer.pointer;
440
		memcpy(buffer, source_desc->buffer.pointer, length);
L
Linus Torvalds 已提交
441 442 443

		/* Lock entire transaction if requested */

444
		acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags);
L
Linus Torvalds 已提交
445 446

		/*
R
Robert Moore 已提交
447 448
		 * Perform the write (returns status and perhaps data in the
		 * same buffer)
L
Linus Torvalds 已提交
449
		 */
450 451
		status =
		    acpi_ex_access_region(obj_desc, 0, (u64 *)buffer, function);
452
		acpi_ex_release_global_lock(obj_desc->common_field.field_flags);
L
Linus Torvalds 已提交
453 454

		*result_desc = buffer_desc;
L
Len Brown 已提交
455
		return_ACPI_STATUS(status);
456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471
	} else if ((obj_desc->common.type == ACPI_TYPE_LOCAL_REGION_FIELD) &&
		   (obj_desc->field.region_obj->region.space_id ==
		    ACPI_ADR_SPACE_GPIO)) {
		/*
		 * For GPIO (general_purpose_io), we will bypass the entire field
		 * mechanism and handoff the bit address and bit width directly to
		 * the handler. The Address will be the bit offset
		 * from the previous Connection() operator, making it effectively a
		 * pin number index. The bit_length is the length of the field, which
		 * is thus the number of pins.
		 */
		if (source_desc->common.type != ACPI_TYPE_INTEGER) {
			return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
		}

		ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
472
				  "GPIO FieldWrite [FROM]: (%s:%X), Val %.8X  [TO]: Pin %u Bits %u\n",
473 474 475 476 477 478 479 480 481 482 483 484 485 486 487
				  acpi_ut_get_type_name(source_desc->common.
							type),
				  source_desc->common.type,
				  (u32)source_desc->integer.value,
				  obj_desc->field.pin_number_index,
				  obj_desc->field.bit_length));

		buffer = &source_desc->integer.value;

		/* Lock entire transaction if requested */

		acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags);

		/* Perform the write */

488 489 490
		status =
		    acpi_ex_access_region(obj_desc, 0, (u64 *)buffer,
					  ACPI_WRITE);
491 492
		acpi_ex_release_global_lock(obj_desc->common_field.field_flags);
		return_ACPI_STATUS(status);
L
Linus Torvalds 已提交
493 494
	}

R
Robert Moore 已提交
495 496
	/* Get a pointer to the data to be written */

497
	switch (source_desc->common.type) {
L
Linus Torvalds 已提交
498
	case ACPI_TYPE_INTEGER:
499

L
Linus Torvalds 已提交
500
		buffer = &source_desc->integer.value;
L
Len Brown 已提交
501
		length = sizeof(source_desc->integer.value);
L
Linus Torvalds 已提交
502 503 504
		break;

	case ACPI_TYPE_BUFFER:
505

L
Linus Torvalds 已提交
506 507 508 509 510
		buffer = source_desc->buffer.pointer;
		length = source_desc->buffer.length;
		break;

	case ACPI_TYPE_STRING:
511

L
Linus Torvalds 已提交
512 513 514 515 516
		buffer = source_desc->string.pointer;
		length = source_desc->string.length;
		break;

	default:
517

L
Len Brown 已提交
518
		return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
L
Linus Torvalds 已提交
519 520
	}

L
Len Brown 已提交
521
	ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
B
Bob Moore 已提交
522
			  "FieldWrite [FROM]: Obj %p (%s:%X), Buf %p, ByteLen %X\n",
L
Len Brown 已提交
523
			  source_desc,
524 525
			  acpi_ut_get_type_name(source_desc->common.type),
			  source_desc->common.type, buffer, length));
L
Len Brown 已提交
526 527

	ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
B
Bob Moore 已提交
528
			  "FieldWrite [TO]:   Obj %p (%s:%X), BitLen %X, BitOff %X, ByteOff %X\n",
L
Len Brown 已提交
529
			  obj_desc,
530 531
			  acpi_ut_get_type_name(obj_desc->common.type),
			  obj_desc->common.type,
L
Len Brown 已提交
532 533 534
			  obj_desc->common_field.bit_length,
			  obj_desc->common_field.start_field_bit_offset,
			  obj_desc->common_field.base_byte_offset));
L
Linus Torvalds 已提交
535 536 537

	/* Lock entire transaction if requested */

538
	acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags);
L
Linus Torvalds 已提交
539 540 541

	/* Write to the field */

L
Len Brown 已提交
542
	status = acpi_ex_insert_into_field(obj_desc, buffer, length);
543
	acpi_ex_release_global_lock(obj_desc->common_field.field_flags);
L
Linus Torvalds 已提交
544

L
Len Brown 已提交
545
	return_ACPI_STATUS(status);
L
Linus Torvalds 已提交
546
}