Re: [PATCH v4 1/2] platform/x86: wmi: Support reading/writing 16 bit EC values

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

 



On Sat, Mar 9, 2024 at 11:17 AM Armin Wolf <W_Armin@xxxxxx> wrote:
>
> Am 09.03.24 um 18:07 schrieb Kuppuswamy Sathyanarayanan:
>
> > On 3/8/24 1:05 PM, Armin Wolf wrote:
> >> The ACPI EC address space handler currently only supports
> >> reading/writing 8 bit values. Some firmware implementations however
> >> want to access for example 16 bit values, which is prefectly legal

/s/prefectly/perfectly

> >> according to the ACPI spec.
> >>
> >> Add support for reading/writing such values.
> >>
> >> Tested on a Dell Inspiron 3505 and a Asus Prime B650-Plus.
> >>
> >> Signed-off-by: Armin Wolf <W_Armin@xxxxxx>
> >> ---
> >> Changes since v3:
> >> - change type of variable i to size_t
> >>
> >> Changes since v2:
> >> - fix address overflow check
> >>
> >> Changes since v1:
> >> - use BITS_PER_BYTE
> >> - validate that number of bytes to read/write does not overflow the
> >>    address
> >> ---
> >>   drivers/platform/x86/wmi.c | 49 ++++++++++++++++++++++++++++++--------
> >>   1 file changed, 39 insertions(+), 10 deletions(-)
> >>
> >> diff --git a/drivers/platform/x86/wmi.c b/drivers/platform/x86/wmi.c
> >> index 1920e115da89..d9bf6d452b3a 100644
> >> --- a/drivers/platform/x86/wmi.c
> >> +++ b/drivers/platform/x86/wmi.c
> >> @@ -1153,6 +1153,34 @@ static int parse_wdg(struct device *wmi_bus_dev, struct platform_device *pdev)
> >>      return 0;
> >>   }
> >>
> >> +static int ec_read_multiple(u8 address, u8 *buffer, size_t bytes)
> >> +{
> >> +    size_t i;
> >> +    int ret;
> >> +
> >> +    for (i = 0; i < bytes; i++) {
> >> +            ret = ec_read(address + i, &buffer[i]);
> >> +            if (ret < 0)
> >> +                    return ret;
> >> +    }
> >> +
> >> +    return 0;
> >> +}
> > Why not use ec_transaction?
>
> Hi,
>
> because ec_transaction() is meant to send raw commands to the EC. And AFAIK read/write transactions can only transfer a
> single byte at once, so using ec_transaction() would yield no benefit here.

>From the implementation, I don't see any length restriction. If it is
a functional restriction, then fine.

int ec_transaction(u8 command,
                   const u8 *wdata, unsigned wdata_len,
                   u8 *rdata, unsigned rdata_len)
{
        struct transaction t = {.command = command,
                                .wdata = wdata, .rdata = rdata,
                                .wlen = wdata_len, .rlen = rdata_len};

        if (!first_ec)
                return -ENODEV;

        return acpi_ec_transaction(first_ec, &t);
}
EXPORT_SYMBOL(ec_transaction);


>
> >
> >> +
> >> +static int ec_write_multiple(u8 address, u8 *buffer, size_t bytes)
> >> +{
> >> +    size_t i;
> >> +    int ret;
> >> +
> >> +    for (i = 0; i < bytes; i++) {
> >> +            ret = ec_write(address + i, buffer[i]);
> >> +            if (ret < 0)
> >> +                    return ret;
> >> +    }
> >> +
> >> +    return 0;
> >> +}
> > Same as above.
> >> +
> >>   /*
> >>    * WMI can have EmbeddedControl access regions. In which case, we just want to
> >>    * hand these off to the EC driver.
> >> @@ -1162,27 +1190,28 @@ acpi_wmi_ec_space_handler(u32 function, acpi_physical_address address,
> >>                        u32 bits, u64 *value,
> >>                        void *handler_context, void *region_context)
> >>   {
> >> -    int result = 0;
> >> -    u8 temp = 0;
> >> +    int bytes = bits / BITS_PER_BYTE;
> >> +    int ret;
> >> +
> >> +    if (!value)
> >> +            return AE_NULL_ENTRY;
> >>
> >> -    if ((address > 0xFF) || !value)
> >> +    if (!bytes || bytes > sizeof(*value))
> >>              return AE_BAD_PARAMETER;
> >>
> >> -    if (function != ACPI_READ && function != ACPI_WRITE)
> >> +    if (address > U8_MAX || address + bytes - 1 > U8_MAX)
> >>              return AE_BAD_PARAMETER;
> >>
> >> -    if (bits != 8)
> > Since you want to support only 16 bit reads/writes, can you check for >16
>
> The 16 bit reads/writes where meant as an example, ACPI code can request much larger values.
> The WMI EC handler should be able to handle those, just like the regular ACPI EC handler.
>

Got it.

> Thanks,
> Armin Wolf
>
> >> +    if (function != ACPI_READ && function != ACPI_WRITE)
> >>              return AE_BAD_PARAMETER;
> >>
> >>      if (function == ACPI_READ) {
> >> -            result = ec_read(address, &temp);
> >> -            *value = temp;
> >> +            ret = ec_read_multiple(address, (u8 *)value, bytes);
> >>      } else {
> >> -            temp = 0xff & *value;
> >> -            result = ec_write(address, temp);
> >> +            ret = ec_write_multiple(address, (u8 *)value, bytes);
> >>      }
> >>
> >> -    switch (result) {
> >> +    switch (ret) {
> >>      case -EINVAL:
> >>              return AE_BAD_PARAMETER;
> >>      case -ENODEV:
> >> --
> >> 2.39.2
> >>
> >>





[Index of Archives]     [Linux Kernel Development]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux