lkml.org 
[lkml]   [2021]   [Mar]   [1]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.19 179/247] ACPI: property: Fix fwnode string properties matching
    Date
    From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

    commit e1e6bd2995ac0e1ad0c2a2d906a06f59ce2ed293 upstream.

    Property matching does not work for ACPI fwnodes if the value of the
    given property is not represented as a package in the _DSD package
    containing it. For example, the "compatible" property in the _DSD
    below

    Name (_DSD, Package () {
    ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
    Package () {
    Package () {"compatible", "ethernet-phy-ieee802.3-c45"}
    }
    })

    will not be found by fwnode_property_match_string(), because the ACPI
    code handling device properties does not regard the single value as a
    "list" in that case.

    Namely, fwnode_property_match_string() invoked to match a given
    string property value first calls fwnode_property_read_string_array()
    with the last two arguments equal to NULL and 0, respectively, in
    order to count the items in the value of the given property, with the
    assumption that this value may be an array. For ACPI fwnodes, that
    operation is carried out by acpi_node_prop_read() which calls
    acpi_data_prop_read() for this purpose. However, when the return
    (val) pointer is NULL, that function only looks for a property whose
    value is a package without checking the single-value case at all.

    To fix that, make acpi_data_prop_read() check the single-value
    case if its return pointer argument is NULL and modify
    acpi_data_prop_read_single() handling that case to attempt to
    read the value of the property if the return pointer is NULL
    and return 1 if that succeeds.

    Fixes: 3708184afc77 ("device property: Move FW type specific functionality to FW specific files")
    Reported-by: Calvin Johnson <calvin.johnson@oss.nxp.com>
    Cc: 4.13+ <stable@vger.kernel.org> # 4.13+
    Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
    Reviewed-by: Sakari Ailus <sakari.ailus@linux.intel.com>
    Reviewed-by: Mika Westerberg <mika.westerberg@linux.intel.com>
    Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
    ---
    drivers/acpi/property.c | 44 +++++++++++++++++++++++++++++++++-----------
    1 file changed, 33 insertions(+), 11 deletions(-)

    --- a/drivers/acpi/property.c
    +++ b/drivers/acpi/property.c
    @@ -720,9 +720,6 @@ static int acpi_data_prop_read_single(co
    const union acpi_object *obj;
    int ret;

    - if (!val)
    - return -EINVAL;
    -
    if (proptype >= DEV_PROP_U8 && proptype <= DEV_PROP_U64) {
    ret = acpi_data_get_property(data, propname, ACPI_TYPE_INTEGER, &obj);
    if (ret)
    @@ -732,28 +729,43 @@ static int acpi_data_prop_read_single(co
    case DEV_PROP_U8:
    if (obj->integer.value > U8_MAX)
    return -EOVERFLOW;
    - *(u8 *)val = obj->integer.value;
    +
    + if (val)
    + *(u8 *)val = obj->integer.value;
    +
    break;
    case DEV_PROP_U16:
    if (obj->integer.value > U16_MAX)
    return -EOVERFLOW;
    - *(u16 *)val = obj->integer.value;
    +
    + if (val)
    + *(u16 *)val = obj->integer.value;
    +
    break;
    case DEV_PROP_U32:
    if (obj->integer.value > U32_MAX)
    return -EOVERFLOW;
    - *(u32 *)val = obj->integer.value;
    +
    + if (val)
    + *(u32 *)val = obj->integer.value;
    +
    break;
    default:
    - *(u64 *)val = obj->integer.value;
    + if (val)
    + *(u64 *)val = obj->integer.value;
    +
    break;
    }
    +
    + if (!val)
    + return 1;
    } else if (proptype == DEV_PROP_STRING) {
    ret = acpi_data_get_property(data, propname, ACPI_TYPE_STRING, &obj);
    if (ret)
    return ret;

    - *(char **)val = obj->string.pointer;
    + if (val)
    + *(char **)val = obj->string.pointer;

    return 1;
    } else {
    @@ -767,7 +779,7 @@ int acpi_dev_prop_read_single(struct acp
    {
    int ret;

    - if (!adev)
    + if (!adev || !val)
    return -EINVAL;

    ret = acpi_data_prop_read_single(&adev->data, propname, proptype, val);
    @@ -861,10 +873,20 @@ static int acpi_data_prop_read(const str
    const union acpi_object *items;
    int ret;

    - if (val && nval == 1) {
    + if (nval == 1 || !val) {
    ret = acpi_data_prop_read_single(data, propname, proptype, val);
    - if (ret >= 0)
    + /*
    + * The overflow error means that the property is there and it is
    + * single-value, but its type does not match, so return.
    + */
    + if (ret >= 0 || ret == -EOVERFLOW)
    return ret;
    +
    + /*
    + * Reading this property as a single-value one failed, but its
    + * value may still be represented as one-element array, so
    + * continue.
    + */
    }

    ret = acpi_data_get_property_array(data, propname, ACPI_TYPE_ANY, &obj);

    \
     
     \ /
      Last update: 2021-03-01 22:39    [W:2.776 / U:0.744 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site