Re: [PATCH v3] ACPICA: ACPI 6.3: add PCC operation region support for AML interpreter

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Sat, Feb 23, 2019 at 1:09 AM Erik Schmauss <erik.schmauss@xxxxxxxxx> wrote:
>
> ACPICA commit a4849944e80f97970e99843f4975850753584a4e
>
> This change adds PCC operation region support in the AML interpreter
> and a default handler for acpiexec. According to the specification,
> the PCC operation region performs a transaction when the COMD field
> is written. This allows ASL to write data to other fields before
> sending the data.
>
> In order to accommodate this protocol, a temorary buffer is added
> to the regionfield object to accumulate writes. If any offset that
> spans COMD is written, the temporary buffer is sent to the PCC
> operation region handler to be processed.
>
> This change also renames the PCC keyword to platform_comm_channel.
>
> Link: https://github.com/acpica/acpica/commit/a4849944
> Reviewed-by: Kyle Pelton <kyle.d.pelton@xxxxxxxxx>
> Signed-off-by: Erik Schmauss <erik.schmauss@xxxxxxxxx>
> Signed-off-by: Bob Moore <robert.moore@xxxxxxxxx>

I've applied this patch instead of the previous version, thanks!

> ---
>  drivers/acpi/acpica/acobject.h |  1 +
>  drivers/acpi/acpica/dsfield.c  |  7 ++++
>  drivers/acpi/acpica/exfield.c  | 68 ++++++++++++++++++++++++++++++++++
>  drivers/acpi/acpica/utdelete.c |  4 ++
>  4 files changed, 80 insertions(+)
>
> diff --git a/drivers/acpi/acpica/acobject.h b/drivers/acpi/acpica/acobject.h
> index 0edf8fca7567..b2ef703d7df8 100644
> --- a/drivers/acpi/acpica/acobject.h
> +++ b/drivers/acpi/acpica/acobject.h
> @@ -239,6 +239,7 @@ struct acpi_object_region_field {
>         union acpi_operand_object *region_obj;  /* Containing op_region object */
>         u8 *resource_buffer;    /* resource_template for serial regions/fields */
>         u16 pin_number_index;   /* Index relative to previous Connection/Template */
> +       u8 *internal_pcc_buffer;        /* Internal buffer for fields associated with PCC */
>  };
>
>  struct acpi_object_bank_field {
> diff --git a/drivers/acpi/acpica/dsfield.c b/drivers/acpi/acpica/dsfield.c
> index d51216c9d891..cf4e061bb0f0 100644
> --- a/drivers/acpi/acpica/dsfield.c
> +++ b/drivers/acpi/acpica/dsfield.c
> @@ -518,6 +518,13 @@ acpi_ds_create_field(union acpi_parse_object *op,
>         info.region_node = region_node;
>
>         status = acpi_ds_get_field_names(&info, walk_state, arg->common.next);
> +       if (info.region_node->object->region.space_id ==
> +           ACPI_ADR_SPACE_PLATFORM_COMM
> +           && !(region_node->object->field.internal_pcc_buffer =
> +                ACPI_ALLOCATE_ZEROED(info.region_node->object->region.
> +                                     length))) {
> +               return_ACPI_STATUS(AE_NO_MEMORY);
> +       }
>         return_ACPI_STATUS(status);
>  }
>
> diff --git a/drivers/acpi/acpica/exfield.c b/drivers/acpi/acpica/exfield.c
> index 7dcdde094582..3760f96b19f9 100644
> --- a/drivers/acpi/acpica/exfield.c
> +++ b/drivers/acpi/acpica/exfield.c
> @@ -41,6 +41,17 @@ const u8 acpi_protocol_lengths[] = {
>         0xFF                    /* F - ATTRIB_RAW_PROCESS_BYTES */
>  };
>
> +#define PCC_MASTER_SUBSPACE    3
> +
> +/*
> + * The following macros determine a given offset is a COMD field.
> + * According to the specification, generic subspaces (types 0-2) contains a
> + * 2-byte COMD field at offset 4 and master subspaces (type 3) contains a 4-byte
> + * COMD field starting at offset 12.
> + */
> +#define GENERIC_SUBSPACE_COMMAND(a)    (4 == a || a == 5)
> +#define MASTER_SUBSPACE_COMMAND(a)     (12 <= a && a <= 15)
> +
>  /*******************************************************************************
>   *
>   * FUNCTION:    acpi_ex_get_protocol_buffer_length
> @@ -177,6 +188,25 @@ acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state,
>
>                 status = acpi_ex_read_gpio(obj_desc, buffer);
>                 goto exit;
> +       } else if ((obj_desc->common.type == ACPI_TYPE_LOCAL_REGION_FIELD) &&
> +                  (obj_desc->field.region_obj->region.space_id ==
> +                   ACPI_ADR_SPACE_PLATFORM_COMM)) {
> +               /*
> +                * Reading from a PCC field unit does not require the handler because
> +                * it only requires reading from the internal_pcc_buffer.
> +                */
> +               ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
> +                                 "PCC FieldRead bits %u\n",
> +                                 obj_desc->field.bit_length));
> +
> +               memcpy(buffer,
> +                      obj_desc->field.region_obj->field.internal_pcc_buffer +
> +                      obj_desc->field.base_byte_offset,
> +                      (acpi_size)ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->field.
> +                                                             bit_length));
> +
> +               *ret_buffer_desc = buffer_desc;
> +               return AE_OK;
>         }
>
>         ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
> @@ -229,6 +259,7 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc,
>  {
>         acpi_status status;
>         u32 buffer_length;
> +       u32 data_length;
>         void *buffer;
>
>         ACPI_FUNCTION_TRACE_PTR(ex_write_data_to_field, obj_desc);
> @@ -272,6 +303,43 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc,
>                     acpi_ex_write_serial_bus(source_desc, obj_desc,
>                                              result_desc);
>                 return_ACPI_STATUS(status);
> +       } else if ((obj_desc->common.type == ACPI_TYPE_LOCAL_REGION_FIELD) &&
> +                  (obj_desc->field.region_obj->region.space_id ==
> +                   ACPI_ADR_SPACE_PLATFORM_COMM)) {
> +               /*
> +                * According to the spec a write to the COMD field will invoke the
> +                * region handler. Otherwise, write to the pcc_internal buffer. This
> +                * implementation will use the offsets specified rather than the name
> +                * of the field. This is considered safer because some firmware tools
> +                * are known to obfiscate named objects.
> +                */
> +               data_length =
> +                   (acpi_size)ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->field.
> +                                                          bit_length);
> +               memcpy(obj_desc->field.region_obj->field.internal_pcc_buffer +
> +                      obj_desc->field.base_byte_offset,
> +                      source_desc->buffer.pointer, data_length);
> +               if ((obj_desc->field.region_obj->region.address ==
> +                    PCC_MASTER_SUBSPACE
> +                    && MASTER_SUBSPACE_COMMAND(obj_desc->field.
> +                                               base_byte_offset))
> +                   || GENERIC_SUBSPACE_COMMAND(obj_desc->field.
> +                                               base_byte_offset)) {
> +
> +                       /* Perform the write */
> +
> +                       ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
> +                                         "PCC COMD field has been written. Invoking PCC handler now.\n"));
> +
> +                       status =
> +                           acpi_ex_access_region(obj_desc, 0,
> +                                                 (u64 *)obj_desc->field.
> +                                                 region_obj->field.
> +                                                 internal_pcc_buffer,
> +                                                 ACPI_WRITE);
> +                       return_ACPI_STATUS(status);
> +               }
> +               return (AE_OK);
>         }
>
>         /* Get a pointer to the data to be written */
> diff --git a/drivers/acpi/acpica/utdelete.c b/drivers/acpi/acpica/utdelete.c
> index 8cc4392c61f3..eee263cb7beb 100644
> --- a/drivers/acpi/acpica/utdelete.c
> +++ b/drivers/acpi/acpica/utdelete.c
> @@ -257,6 +257,10 @@ static void acpi_ut_delete_internal_obj(union acpi_operand_object *object)
>
>                         acpi_ut_delete_object_desc(second_desc);
>                 }
> +               if (object->field.internal_pcc_buffer) {
> +                       ACPI_FREE(object->field.internal_pcc_buffer);
> +               }
> +
>                 break;
>
>         case ACPI_TYPE_BUFFER_FIELD:
> --
> 2.17.1
>



[Index of Archives]     [Linux IBM ACPI]     [Linux Power Management]     [Linux Kernel]     [Linux Laptop]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Samba]     [Video 4 Linux]     [Device Mapper]     [Linux Resources]

  Powered by Linux