Message ID | 20240731201407.1838385-6-robh@kernel.org |
---|---|
State | Superseded |
Headers | show |
Series | input: tegra: Use of_property_read_variable_u32_array() and of_property_present() | expand |
On Wed, Jul 31, 2024 at 02:14:01PM GMT, Rob Herring (Arm) wrote: > There's no need to get the length of an DT array property before > parsing the array. of_property_read_variable_u32_array() takes a > minimum and maximum length and returns the actual length (or error > code). > > This is part of a larger effort to remove callers of of_get_property() > and similar functions. of_get_property() leaks the DT property data > pointer which is a problem for dynamically allocated nodes which may > be freed. > --- > drivers/input/keyboard/tegra-kbc.c | 72 +++++++++++------------------- > 1 file changed, 27 insertions(+), 45 deletions(-) > > diff --git a/drivers/input/keyboard/tegra-kbc.c b/drivers/input/keyboard/tegra-kbc.c > index a1765ed8c825..53f39fc155ea 100644 > --- a/drivers/input/keyboard/tegra-kbc.c > +++ b/drivers/input/keyboard/tegra-kbc.c > @@ -491,12 +491,10 @@ static int tegra_kbc_parse_dt(struct tegra_kbc *kbc) > struct device_node *np = kbc->dev->of_node; > u32 prop; > int i; > - u32 num_rows = 0; > - u32 num_cols = 0; > + int num_rows; > + int num_cols; > u32 cols_cfg[KBC_MAX_GPIO]; > u32 rows_cfg[KBC_MAX_GPIO]; > - int proplen; > - int ret; > > if (!of_property_read_u32(np, "nvidia,debounce-delay-ms", &prop)) > kbc->debounce_cnt = prop; > @@ -510,56 +508,23 @@ static int tegra_kbc_parse_dt(struct tegra_kbc *kbc) > of_property_read_bool(np, "nvidia,wakeup-source")) /* legacy */ > kbc->wakeup = true; > > - if (!of_get_property(np, "nvidia,kbc-row-pins", &proplen)) { > - dev_err(kbc->dev, "property nvidia,kbc-row-pins not found\n"); > - return -ENOENT; > - } > - num_rows = proplen / sizeof(u32); > - > - if (!of_get_property(np, "nvidia,kbc-col-pins", &proplen)) { > - dev_err(kbc->dev, "property nvidia,kbc-col-pins not found\n"); > - return -ENOENT; > - } > - num_cols = proplen / sizeof(u32); > - > - if (num_rows > kbc->hw_support->max_rows) { > - dev_err(kbc->dev, > - "Number of rows is more than supported by hardware\n"); > - return -EINVAL; > - } > - > - if (num_cols > kbc->hw_support->max_columns) { > - dev_err(kbc->dev, > - "Number of cols is more than supported by hardware\n"); > - return -EINVAL; > - } > - > - if (!of_get_property(np, "linux,keymap", &proplen)) { > + if (!of_property_present(np, "linux,keymap")) { > dev_err(kbc->dev, "property linux,keymap not found\n"); > return -ENOENT; > } > > - if (!num_rows || !num_cols || ((num_rows + num_cols) > KBC_MAX_GPIO)) { > - dev_err(kbc->dev, > - "keypad rows/columns not properly specified\n"); > - return -EINVAL; > - } > - > /* Set all pins as non-configured */ > for (i = 0; i < kbc->num_rows_and_columns; i++) > kbc->pin_cfg[i].type = PIN_CFG_IGNORE; > > - ret = of_property_read_u32_array(np, "nvidia,kbc-row-pins", > - rows_cfg, num_rows); > - if (ret < 0) { > + num_rows = of_property_read_variable_u32_array(np, "nvidia,kbc-row-pins", > + rows_cfg, 1, KBC_MAX_GPIO); > + if (num_rows < 0) { > dev_err(kbc->dev, "Rows configurations are not proper\n"); > - return -EINVAL; > - } > - > - ret = of_property_read_u32_array(np, "nvidia,kbc-col-pins", > - cols_cfg, num_cols); > - if (ret < 0) { > - dev_err(kbc->dev, "Cols configurations are not proper\n"); > + return num_rows; > + } else if (num_rows > kbc->hw_support->max_rows) { > + dev_err(kbc->dev, > + "Number of rows is more than supported by hardware\n"); > return -EINVAL; > } > > @@ -568,11 +533,28 @@ static int tegra_kbc_parse_dt(struct tegra_kbc *kbc) > kbc->pin_cfg[rows_cfg[i]].num = i; > } > > + num_cols = of_property_read_variable_u32_array(np, "nvidia,kbc-col-pins", > + cols_cfg, 1, KBC_MAX_GPIO); > + if (num_cols < 0) { > + dev_err(kbc->dev, "Cols configurations are not proper\n"); > + return num_cols; > + } else if (num_cols > kbc->hw_support->max_columns) { > + dev_err(kbc->dev, > + "Number of cols is more than supported by hardware\n"); > + return -EINVAL; > + } > + > for (i = 0; i < num_cols; i++) { > kbc->pin_cfg[cols_cfg[i]].type = PIN_CFG_COL; > kbc->pin_cfg[cols_cfg[i]].num = i; > } > > + if (!num_rows || !num_cols || ((num_rows + num_cols) > KBC_MAX_GPIO)) { > + dev_err(kbc->dev, > + "keypad rows/columns not properly specified\n"); > + return -EINVAL; > + } Previously we wouldn't try to initialize the columns when the rows/columns were invalid, so this block could move before the last for loop above. But it doesn't really matter given that these are exceptions and really shouldn't happen, so: Acked-by: Thierry Reding <treding@nvidia.com>
On Tue, Aug 27, 2024 at 04:23:48PM +0200, Thierry Reding wrote: > On Wed, Jul 31, 2024 at 02:14:01PM GMT, Rob Herring (Arm) wrote: > > There's no need to get the length of an DT array property before > > parsing the array. of_property_read_variable_u32_array() takes a > > minimum and maximum length and returns the actual length (or error > > code). > > > > This is part of a larger effort to remove callers of of_get_property() > > and similar functions. of_get_property() leaks the DT property data > > pointer which is a problem for dynamically allocated nodes which may > > be freed. > > --- > > drivers/input/keyboard/tegra-kbc.c | 72 +++++++++++------------------- > > 1 file changed, 27 insertions(+), 45 deletions(-) > > > > diff --git a/drivers/input/keyboard/tegra-kbc.c b/drivers/input/keyboard/tegra-kbc.c > > index a1765ed8c825..53f39fc155ea 100644 > > --- a/drivers/input/keyboard/tegra-kbc.c > > +++ b/drivers/input/keyboard/tegra-kbc.c > > @@ -491,12 +491,10 @@ static int tegra_kbc_parse_dt(struct tegra_kbc *kbc) > > struct device_node *np = kbc->dev->of_node; > > u32 prop; > > int i; > > - u32 num_rows = 0; > > - u32 num_cols = 0; > > + int num_rows; > > + int num_cols; > > u32 cols_cfg[KBC_MAX_GPIO]; > > u32 rows_cfg[KBC_MAX_GPIO]; > > - int proplen; > > - int ret; > > > > if (!of_property_read_u32(np, "nvidia,debounce-delay-ms", &prop)) > > kbc->debounce_cnt = prop; > > @@ -510,56 +508,23 @@ static int tegra_kbc_parse_dt(struct tegra_kbc *kbc) > > of_property_read_bool(np, "nvidia,wakeup-source")) /* legacy */ > > kbc->wakeup = true; > > > > - if (!of_get_property(np, "nvidia,kbc-row-pins", &proplen)) { > > - dev_err(kbc->dev, "property nvidia,kbc-row-pins not found\n"); > > - return -ENOENT; > > - } > > - num_rows = proplen / sizeof(u32); > > - > > - if (!of_get_property(np, "nvidia,kbc-col-pins", &proplen)) { > > - dev_err(kbc->dev, "property nvidia,kbc-col-pins not found\n"); > > - return -ENOENT; > > - } > > - num_cols = proplen / sizeof(u32); > > - > > - if (num_rows > kbc->hw_support->max_rows) { > > - dev_err(kbc->dev, > > - "Number of rows is more than supported by hardware\n"); > > - return -EINVAL; > > - } > > - > > - if (num_cols > kbc->hw_support->max_columns) { > > - dev_err(kbc->dev, > > - "Number of cols is more than supported by hardware\n"); > > - return -EINVAL; > > - } > > - > > - if (!of_get_property(np, "linux,keymap", &proplen)) { > > + if (!of_property_present(np, "linux,keymap")) { > > dev_err(kbc->dev, "property linux,keymap not found\n"); > > return -ENOENT; > > } > > > > - if (!num_rows || !num_cols || ((num_rows + num_cols) > KBC_MAX_GPIO)) { > > - dev_err(kbc->dev, > > - "keypad rows/columns not properly specified\n"); > > - return -EINVAL; > > - } > > - > > /* Set all pins as non-configured */ > > for (i = 0; i < kbc->num_rows_and_columns; i++) > > kbc->pin_cfg[i].type = PIN_CFG_IGNORE; > > > > - ret = of_property_read_u32_array(np, "nvidia,kbc-row-pins", > > - rows_cfg, num_rows); > > - if (ret < 0) { > > + num_rows = of_property_read_variable_u32_array(np, "nvidia,kbc-row-pins", > > + rows_cfg, 1, KBC_MAX_GPIO); > > + if (num_rows < 0) { > > dev_err(kbc->dev, "Rows configurations are not proper\n"); > > - return -EINVAL; > > - } > > - > > - ret = of_property_read_u32_array(np, "nvidia,kbc-col-pins", > > - cols_cfg, num_cols); > > - if (ret < 0) { > > - dev_err(kbc->dev, "Cols configurations are not proper\n"); > > + return num_rows; > > + } else if (num_rows > kbc->hw_support->max_rows) { > > + dev_err(kbc->dev, > > + "Number of rows is more than supported by hardware\n"); > > return -EINVAL; > > } > > > > @@ -568,11 +533,28 @@ static int tegra_kbc_parse_dt(struct tegra_kbc *kbc) > > kbc->pin_cfg[rows_cfg[i]].num = i; > > } > > > > + num_cols = of_property_read_variable_u32_array(np, "nvidia,kbc-col-pins", > > + cols_cfg, 1, KBC_MAX_GPIO); > > + if (num_cols < 0) { > > + dev_err(kbc->dev, "Cols configurations are not proper\n"); > > + return num_cols; > > + } else if (num_cols > kbc->hw_support->max_columns) { > > + dev_err(kbc->dev, > > + "Number of cols is more than supported by hardware\n"); > > + return -EINVAL; > > + } > > + > > for (i = 0; i < num_cols; i++) { > > kbc->pin_cfg[cols_cfg[i]].type = PIN_CFG_COL; > > kbc->pin_cfg[cols_cfg[i]].num = i; > > } > > > > + if (!num_rows || !num_cols || ((num_rows + num_cols) > KBC_MAX_GPIO)) { > > + dev_err(kbc->dev, > > + "keypad rows/columns not properly specified\n"); > > + return -EINVAL; > > + } > > Previously we wouldn't try to initialize the columns when the > rows/columns were invalid, so this block could move before the last for > loop above. > > But it doesn't really matter given that these are exceptions and really > shouldn't happen, so: > > Acked-by: Thierry Reding <treding@nvidia.com> I don't quite like of_property_read_variable_u32_array() because it is OF-specific. device_property_count_u32() will return the number of elements in an array. But I guess this driver will only be used on an OF system... Applied, thank you.
On Tue, Aug 27, 2024 at 08:36:29AM GMT, Dmitry Torokhov wrote: > On Tue, Aug 27, 2024 at 04:23:48PM +0200, Thierry Reding wrote: > > On Wed, Jul 31, 2024 at 02:14:01PM GMT, Rob Herring (Arm) wrote: > > > There's no need to get the length of an DT array property before > > > parsing the array. of_property_read_variable_u32_array() takes a > > > minimum and maximum length and returns the actual length (or error > > > code). > > > > > > This is part of a larger effort to remove callers of of_get_property() > > > and similar functions. of_get_property() leaks the DT property data > > > pointer which is a problem for dynamically allocated nodes which may > > > be freed. > > > --- > > > drivers/input/keyboard/tegra-kbc.c | 72 +++++++++++------------------- > > > 1 file changed, 27 insertions(+), 45 deletions(-) > > > > > > diff --git a/drivers/input/keyboard/tegra-kbc.c b/drivers/input/keyboard/tegra-kbc.c > > > index a1765ed8c825..53f39fc155ea 100644 > > > --- a/drivers/input/keyboard/tegra-kbc.c > > > +++ b/drivers/input/keyboard/tegra-kbc.c > > > @@ -491,12 +491,10 @@ static int tegra_kbc_parse_dt(struct tegra_kbc *kbc) > > > struct device_node *np = kbc->dev->of_node; > > > u32 prop; > > > int i; > > > - u32 num_rows = 0; > > > - u32 num_cols = 0; > > > + int num_rows; > > > + int num_cols; > > > u32 cols_cfg[KBC_MAX_GPIO]; > > > u32 rows_cfg[KBC_MAX_GPIO]; > > > - int proplen; > > > - int ret; > > > > > > if (!of_property_read_u32(np, "nvidia,debounce-delay-ms", &prop)) > > > kbc->debounce_cnt = prop; > > > @@ -510,56 +508,23 @@ static int tegra_kbc_parse_dt(struct tegra_kbc *kbc) > > > of_property_read_bool(np, "nvidia,wakeup-source")) /* legacy */ > > > kbc->wakeup = true; > > > > > > - if (!of_get_property(np, "nvidia,kbc-row-pins", &proplen)) { > > > - dev_err(kbc->dev, "property nvidia,kbc-row-pins not found\n"); > > > - return -ENOENT; > > > - } > > > - num_rows = proplen / sizeof(u32); > > > - > > > - if (!of_get_property(np, "nvidia,kbc-col-pins", &proplen)) { > > > - dev_err(kbc->dev, "property nvidia,kbc-col-pins not found\n"); > > > - return -ENOENT; > > > - } > > > - num_cols = proplen / sizeof(u32); > > > - > > > - if (num_rows > kbc->hw_support->max_rows) { > > > - dev_err(kbc->dev, > > > - "Number of rows is more than supported by hardware\n"); > > > - return -EINVAL; > > > - } > > > - > > > - if (num_cols > kbc->hw_support->max_columns) { > > > - dev_err(kbc->dev, > > > - "Number of cols is more than supported by hardware\n"); > > > - return -EINVAL; > > > - } > > > - > > > - if (!of_get_property(np, "linux,keymap", &proplen)) { > > > + if (!of_property_present(np, "linux,keymap")) { > > > dev_err(kbc->dev, "property linux,keymap not found\n"); > > > return -ENOENT; > > > } > > > > > > - if (!num_rows || !num_cols || ((num_rows + num_cols) > KBC_MAX_GPIO)) { > > > - dev_err(kbc->dev, > > > - "keypad rows/columns not properly specified\n"); > > > - return -EINVAL; > > > - } > > > - > > > /* Set all pins as non-configured */ > > > for (i = 0; i < kbc->num_rows_and_columns; i++) > > > kbc->pin_cfg[i].type = PIN_CFG_IGNORE; > > > > > > - ret = of_property_read_u32_array(np, "nvidia,kbc-row-pins", > > > - rows_cfg, num_rows); > > > - if (ret < 0) { > > > + num_rows = of_property_read_variable_u32_array(np, "nvidia,kbc-row-pins", > > > + rows_cfg, 1, KBC_MAX_GPIO); > > > + if (num_rows < 0) { > > > dev_err(kbc->dev, "Rows configurations are not proper\n"); > > > - return -EINVAL; > > > - } > > > - > > > - ret = of_property_read_u32_array(np, "nvidia,kbc-col-pins", > > > - cols_cfg, num_cols); > > > - if (ret < 0) { > > > - dev_err(kbc->dev, "Cols configurations are not proper\n"); > > > + return num_rows; > > > + } else if (num_rows > kbc->hw_support->max_rows) { > > > + dev_err(kbc->dev, > > > + "Number of rows is more than supported by hardware\n"); > > > return -EINVAL; > > > } > > > > > > @@ -568,11 +533,28 @@ static int tegra_kbc_parse_dt(struct tegra_kbc *kbc) > > > kbc->pin_cfg[rows_cfg[i]].num = i; > > > } > > > > > > + num_cols = of_property_read_variable_u32_array(np, "nvidia,kbc-col-pins", > > > + cols_cfg, 1, KBC_MAX_GPIO); > > > + if (num_cols < 0) { > > > + dev_err(kbc->dev, "Cols configurations are not proper\n"); > > > + return num_cols; > > > + } else if (num_cols > kbc->hw_support->max_columns) { > > > + dev_err(kbc->dev, > > > + "Number of cols is more than supported by hardware\n"); > > > + return -EINVAL; > > > + } > > > + > > > for (i = 0; i < num_cols; i++) { > > > kbc->pin_cfg[cols_cfg[i]].type = PIN_CFG_COL; > > > kbc->pin_cfg[cols_cfg[i]].num = i; > > > } > > > > > > + if (!num_rows || !num_cols || ((num_rows + num_cols) > KBC_MAX_GPIO)) { > > > + dev_err(kbc->dev, > > > + "keypad rows/columns not properly specified\n"); > > > + return -EINVAL; > > > + } > > > > Previously we wouldn't try to initialize the columns when the > > rows/columns were invalid, so this block could move before the last for > > loop above. > > > > But it doesn't really matter given that these are exceptions and really > > shouldn't happen, so: > > > > Acked-by: Thierry Reding <treding@nvidia.com> > > I don't quite like of_property_read_variable_u32_array() because it is > OF-specific. device_property_count_u32() will return the number of > elements in an array. But I guess this driver will only be used on an OF > system... Yeah, this hardware only exists on fairly old Tegra devices and I know of no plans to support anything other that DT on those. Thierry
On Fri, Sep 6, 2024 at 12:33 AM Dmitry Torokhov <dmitry.torokhov@gmail.com> wrote: > > On Tue, Aug 27, 2024 at 10:53:38AM -0700, Dmitry Torokhov wrote: > > > > > > Applied, thank you. > > > > Oh, wait, can I get your SOB please? > > Rob, I am still waiting on your SOB please. Oh, missed this. That's weird it is missing. New patch coming. Rob
diff --git a/drivers/input/keyboard/tegra-kbc.c b/drivers/input/keyboard/tegra-kbc.c index a1765ed8c825..53f39fc155ea 100644 --- a/drivers/input/keyboard/tegra-kbc.c +++ b/drivers/input/keyboard/tegra-kbc.c @@ -491,12 +491,10 @@ static int tegra_kbc_parse_dt(struct tegra_kbc *kbc) struct device_node *np = kbc->dev->of_node; u32 prop; int i; - u32 num_rows = 0; - u32 num_cols = 0; + int num_rows; + int num_cols; u32 cols_cfg[KBC_MAX_GPIO]; u32 rows_cfg[KBC_MAX_GPIO]; - int proplen; - int ret; if (!of_property_read_u32(np, "nvidia,debounce-delay-ms", &prop)) kbc->debounce_cnt = prop; @@ -510,56 +508,23 @@ static int tegra_kbc_parse_dt(struct tegra_kbc *kbc) of_property_read_bool(np, "nvidia,wakeup-source")) /* legacy */ kbc->wakeup = true; - if (!of_get_property(np, "nvidia,kbc-row-pins", &proplen)) { - dev_err(kbc->dev, "property nvidia,kbc-row-pins not found\n"); - return -ENOENT; - } - num_rows = proplen / sizeof(u32); - - if (!of_get_property(np, "nvidia,kbc-col-pins", &proplen)) { - dev_err(kbc->dev, "property nvidia,kbc-col-pins not found\n"); - return -ENOENT; - } - num_cols = proplen / sizeof(u32); - - if (num_rows > kbc->hw_support->max_rows) { - dev_err(kbc->dev, - "Number of rows is more than supported by hardware\n"); - return -EINVAL; - } - - if (num_cols > kbc->hw_support->max_columns) { - dev_err(kbc->dev, - "Number of cols is more than supported by hardware\n"); - return -EINVAL; - } - - if (!of_get_property(np, "linux,keymap", &proplen)) { + if (!of_property_present(np, "linux,keymap")) { dev_err(kbc->dev, "property linux,keymap not found\n"); return -ENOENT; } - if (!num_rows || !num_cols || ((num_rows + num_cols) > KBC_MAX_GPIO)) { - dev_err(kbc->dev, - "keypad rows/columns not properly specified\n"); - return -EINVAL; - } - /* Set all pins as non-configured */ for (i = 0; i < kbc->num_rows_and_columns; i++) kbc->pin_cfg[i].type = PIN_CFG_IGNORE; - ret = of_property_read_u32_array(np, "nvidia,kbc-row-pins", - rows_cfg, num_rows); - if (ret < 0) { + num_rows = of_property_read_variable_u32_array(np, "nvidia,kbc-row-pins", + rows_cfg, 1, KBC_MAX_GPIO); + if (num_rows < 0) { dev_err(kbc->dev, "Rows configurations are not proper\n"); - return -EINVAL; - } - - ret = of_property_read_u32_array(np, "nvidia,kbc-col-pins", - cols_cfg, num_cols); - if (ret < 0) { - dev_err(kbc->dev, "Cols configurations are not proper\n"); + return num_rows; + } else if (num_rows > kbc->hw_support->max_rows) { + dev_err(kbc->dev, + "Number of rows is more than supported by hardware\n"); return -EINVAL; } @@ -568,11 +533,28 @@ static int tegra_kbc_parse_dt(struct tegra_kbc *kbc) kbc->pin_cfg[rows_cfg[i]].num = i; } + num_cols = of_property_read_variable_u32_array(np, "nvidia,kbc-col-pins", + cols_cfg, 1, KBC_MAX_GPIO); + if (num_cols < 0) { + dev_err(kbc->dev, "Cols configurations are not proper\n"); + return num_cols; + } else if (num_cols > kbc->hw_support->max_columns) { + dev_err(kbc->dev, + "Number of cols is more than supported by hardware\n"); + return -EINVAL; + } + for (i = 0; i < num_cols; i++) { kbc->pin_cfg[cols_cfg[i]].type = PIN_CFG_COL; kbc->pin_cfg[cols_cfg[i]].num = i; } + if (!num_rows || !num_cols || ((num_rows + num_cols) > KBC_MAX_GPIO)) { + dev_err(kbc->dev, + "keypad rows/columns not properly specified\n"); + return -EINVAL; + } + return 0; }