| From 6f0078ae704d94b1a93e5f3d0a44cf3d8090fa91 Mon Sep 17 00:00:00 2001 |
| From: Gwendal Grignou <gwendal@chromium.org> |
| Date: Fri, 26 Mar 2021 11:46:02 -0700 |
| Subject: iio: sx9310: Fix access to variable DT array |
| |
| From: Gwendal Grignou <gwendal@chromium.org> |
| |
| commit 6f0078ae704d94b1a93e5f3d0a44cf3d8090fa91 upstream. |
| |
| With the current code, we want to read 4 entries from DT array |
| "semtech,combined-sensors". If there are less, we silently fail as |
| of_property_read_u32_array() returns -EOVERFLOW. |
| |
| First count the number of entries and if between 1 and 4, collect the |
| content of the array. |
| |
| Fixes: 5b19ca2c78a0 ("iio: sx9310: Set various settings from DT") |
| Signed-off-by: Gwendal Grignou <gwendal@chromium.org> |
| Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com> |
| Link: https://lore.kernel.org/r/20210326184603.251683-2-gwendal@chromium.org |
| Cc: <stable@vger.kernel.org> |
| Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| drivers/iio/proximity/sx9310.c | 40 ++++++++++++++++++++++++++++------------ |
| 1 file changed, 28 insertions(+), 12 deletions(-) |
| |
| --- a/drivers/iio/proximity/sx9310.c |
| +++ b/drivers/iio/proximity/sx9310.c |
| @@ -1221,17 +1221,17 @@ static int sx9310_init_compensation(stru |
| } |
| |
| static const struct sx9310_reg_default * |
| -sx9310_get_default_reg(struct sx9310_data *data, int i, |
| +sx9310_get_default_reg(struct sx9310_data *data, int idx, |
| struct sx9310_reg_default *reg_def) |
| { |
| - int ret; |
| const struct device_node *np = data->client->dev.of_node; |
| - u32 combined[SX9310_NUM_CHANNELS] = { 4, 4, 4, 4 }; |
| + u32 combined[SX9310_NUM_CHANNELS]; |
| + u32 start = 0, raw = 0, pos = 0; |
| unsigned long comb_mask = 0; |
| + int ret, i, count; |
| const char *res; |
| - u32 start = 0, raw = 0, pos = 0; |
| |
| - memcpy(reg_def, &sx9310_default_regs[i], sizeof(*reg_def)); |
| + memcpy(reg_def, &sx9310_default_regs[idx], sizeof(*reg_def)); |
| if (!np) |
| return reg_def; |
| |
| @@ -1242,15 +1242,31 @@ sx9310_get_default_reg(struct sx9310_dat |
| reg_def->def |= SX9310_REG_PROX_CTRL2_SHIELDEN_GROUND; |
| } |
| |
| - reg_def->def &= ~SX9310_REG_PROX_CTRL2_COMBMODE_MASK; |
| - of_property_read_u32_array(np, "semtech,combined-sensors", |
| - combined, ARRAY_SIZE(combined)); |
| - for (i = 0; i < ARRAY_SIZE(combined); i++) { |
| - if (combined[i] <= SX9310_NUM_CHANNELS) |
| - comb_mask |= BIT(combined[i]); |
| + count = of_property_count_elems_of_size(np, "semtech,combined-sensors", |
| + sizeof(u32)); |
| + if (count > 0 && count <= ARRAY_SIZE(combined)) { |
| + ret = of_property_read_u32_array(np, "semtech,combined-sensors", |
| + combined, count); |
| + if (ret) |
| + break; |
| + } else { |
| + /* |
| + * Either the property does not exist in the DT or the |
| + * number of entries is incorrect. |
| + */ |
| + break; |
| } |
| + for (i = 0; i < count; i++) { |
| + if (combined[i] >= SX9310_NUM_CHANNELS) { |
| + /* Invalid sensor (invalid DT). */ |
| + break; |
| + } |
| + comb_mask |= BIT(combined[i]); |
| + } |
| + if (i < count) |
| + break; |
| |
| - comb_mask &= 0xf; |
| + reg_def->def &= ~SX9310_REG_PROX_CTRL2_COMBMODE_MASK; |
| if (comb_mask == (BIT(3) | BIT(2) | BIT(1) | BIT(0))) |
| reg_def->def |= SX9310_REG_PROX_CTRL2_COMBMODE_CS0_CS1_CS2_CS3; |
| else if (comb_mask == (BIT(1) | BIT(2))) |