devres: provide and use devm_krealloc()
Subsystems (5)
v9 cover devres: provide and use devm_krealloc()
From: Bartosz Golaszewski <[email protected]>
Regular krealloc() obviously can't work with managed memory. This series implements devm_krealloc() and adds two first users with hope that this helper will be adopted by other drivers currently using non-managed krealloc().
v1 -> v2:
- remove leftover call to hwmon_device_unregister() from pmbus_core.c
- add a patch extending devm_kmalloc() to handle zero size case
- use WARN_ON() instead of WARN_ONCE() in devm_krealloc() when passed a pointer to non-managed memory
- correctly handle the case when devm_krealloc() is passed a pointer to memory in .rodata (potentially returned by devm_kstrdup_const())
- correctly handle ZERO_SIZE_PTR passed as the ptr argument in devm_krealloc()
v2 -> v3:
- drop already applied patches
- collect Acks
- add an additional user in iio
v3 -> v4:
- add the kerneldoc for devm_krealloc()
- WARN() outside of spinlock
- rename local variable
v4 -> v5:
- tweak the kerneldoc
v5 -> v6:
- tweak the devres_lock handling in devm_krealloc()
v6 -> v7:
- rework devm_krealloc() to avoid calling krealloc() with spinlock taken
v7 -> v8:
- drop unnecessary explicit pointer casting in to_devres()
- check the return value of ksize() to make sure the pointer actually points to a dynamically allocated chunk
- add more comments to explain the locking strategy and resource handling
v8 -> v9:
- use container_of() and offsetoff() instead of manual offset calculations
- use kfree() instead of devres_free() in error path as the latter expects the pointer to devres data, not devres node
Bartosz Golaszewski (3):
devres: provide devm_krealloc()
hwmon: pmbus: use more devres helpers
iio: adc: xilinx-xadc: use devm_krealloc()
.../driver-api/driver-model/devres.rst | 1 + drivers/base/devres.c | 105 ++++++++++++++++++ drivers/hwmon/pmbus/pmbus_core.c | 28 ++--- drivers/iio/adc/xilinx-xadc-core.c | 16 +-- include/linux/device.h | 2 + 5 files changed, 125 insertions(+), 27 deletions(-)
Signature · 1 line
2.26.1
PATCH v9 1/3 devres: provide devm_krealloc()
From: Bartosz Golaszewski <[email protected]>
Implement the managed variant of krealloc(). This function works with all memory allocated by devm_kmalloc() (or devres functions using it implicitly like devm_kmemdup(), devm_kstrdup() etc.).
Managed realloc'ed chunks can be manually released with devm_kfree().
--- .../driver-api/driver-model/devres.rst | 1 + drivers/base/devres.c | 105 ++++++++++++++++++ include/linux/device.h | 2 + 3 files changed, 108 insertions(+)
Documentation/driver-api/driver-model/devres.rst +1 -0
@@ -354,6 +354,7 @@ MEM devm_kmalloc() devm_kmalloc_array() devm_kmemdup() + devm_krealloc() devm_kstrdup() devm_kvasprintf() devm_kzalloc()
drivers/base/devres.c +105 -0
117 lines not on this page · raw message
include/linux/device.h +2 -0
@@ -206,6 +206,8 @@ int devres_release_group(struct device *dev, void *id);/* managed devm_k.alloc/kfree for device drivers */ void *devm_kmalloc (struct device *dev,size_t size,gfp_t gfp) __malloc; +void *devm_krealloc (struct device *dev,void *ptr,size_t size, +gfp_t gfp)__must_check ; __printf(3, 0) char *devm_kvasprintf(struct device *dev, gfp_t gfp,const char *fmt,va_list ap) __malloc; __printf(3, 4) char *devm_kasprintf(struct device *dev, gfp_t gfp,
Signature · 1 line
2.26.1
PATCH v9 2/3 hwmon: pmbus: use more devres helpers
In reply to Bartosz GolaszewskiFrom: Bartosz Golaszewski <[email protected]>
Shrink pmbus code by using devm_hwmon_device_register_with_groups() and devm_krealloc() instead of their non-managed variants.
--- drivers/hwmon/pmbus/pmbus_core.c | 28 +++++++++------------------- 1 file changed, 9 insertions(+), 19 deletions(-)
drivers/hwmon/pmbus/pmbus_core.c +9 -19
@@ -1018,9 +1018,9 @@ static int pmbus_add_attribute(struct pmbus_data *data, struct attribute *attr) {if (data->num_attributes >= data->max_attributes -1 ) {int new_max_attrs = data->max_attributes +PMBUS_ATTR_ALLOC_SIZE ; -void *new_attrs =krealloc (data->group.attrs, - new_max_attrs *sizeof (void *), -GFP_KERNEL ); +void *new_attrs =devm_krealloc (data->dev, data->group.attrs, + new_max_attrs *sizeof (void *), +GFP_KERNEL );if (!new_attrs)return -ENOMEM ; data->group.attrs = new_attrs;
@@ -2534,7 +2534,7 @@ int pmbus_do_probe(struct i2c_client *client, const struct i2c_device_id *id, ret =pmbus_find_attributes (client, data);if (ret) - goto out_kfree; +return ret;/* * If there are no attributes, something is wrong.
@@ -2542,35 +2542,27 @@ int pmbus_do_probe(struct i2c_client *client, const struct i2c_device_id *id,*/ if (!data->num_attributes) {dev_err (dev,"No attributes found\n" ); - ret = -ENODEV ; - goto out_kfree; +return -ENODEV ; } data->groups[0 ] = &data->group;memcpy (data->groups +1 , info->groups,sizeof (void *) * groups_num); - data->hwmon_dev =hwmon_device_register_with_groups (dev, client->name, - data, data->groups); + data->hwmon_dev =devm_hwmon_device_register_with_groups (dev, + client->name, data, data->groups);if (IS_ERR (data->hwmon_dev)) { - ret =PTR_ERR (data->hwmon_dev);dev_err (dev,"Failed to register hwmon device\n" ); - goto out_kfree; +return PTR_ERR (data->hwmon_dev); } ret =pmbus_regulator_register (data);if (ret) - goto out_unregister; +return ret; ret =pmbus_init_debugfs (client, data);if (ret)dev_warn (dev,"Failed to register debugfs\n" );return 0 ; - -out_unregister: -hwmon_device_unregister (data->hwmon_dev); -out_kfree: -kfree (data->group.attrs); -return ret; }EXPORT_SYMBOL_GPL (pmbus_do_probe);
@@ -2580,8 +2572,6 @@ int pmbus_do_remove(struct i2c_client *client)debugfs_remove_recursive (data->debugfs); -hwmon_device_unregister (data->hwmon_dev); -kfree (data->group.attrs);return 0 ; }EXPORT_SYMBOL_GPL (pmbus_do_remove);
Signature · 1 line
2.26.1
PATCH v9 3/3 iio: adc: xilinx-xadc: use devm_krealloc()
In reply to Bartosz GolaszewskiFrom: Bartosz Golaszewski <[email protected]>
Use the managed variant of krealloc() and shrink the code a bit.
--- drivers/iio/adc/xilinx-xadc-core.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-)
drivers/iio/adc/xilinx-xadc-core.c +8 -8
@@ -1092,6 +1092,7 @@ MODULE_DEVICE_TABLE(of, xadc_of_match_table);static int xadc_parse_dt (struct iio_dev *indio_dev,struct device_node *np,unsigned int *conf) { +struct device *dev = indio_dev->dev.parent;struct xadc *xadc =iio_priv (indio_dev);struct iio_chan_spec *channels, *chan;struct device_node *chan_node, *child;
@@ -1136,7 +1137,8 @@ static int xadc_parse_dt(struct iio_dev *indio_dev, struct device_node *np, *conf |=XADC_CONF0_MUX |XADC_CONF0_CHAN (ext_mux_chan); } - channels =kmemdup (xadc_channels,sizeof (xadc_channels),GFP_KERNEL ); + channels =devm_kmemdup (dev, xadc_channels, +sizeof (xadc_channels),GFP_KERNEL );if (!channels)return -ENOMEM ;
@@ -1172,8 +1174,9 @@ static int xadc_parse_dt(struct iio_dev *indio_dev, struct device_node *np,of_node_put (chan_node); indio_dev->num_channels = num_channels; - indio_dev->channels =krealloc (channels,sizeof (*channels) * - num_channels,GFP_KERNEL ); + indio_dev->channels =devm_krealloc (dev, channels, +sizeof (*channels) * num_channels, +GFP_KERNEL );/* If we can't resize the channels array, just use the original */ if (!indio_dev->channels) indio_dev->channels = channels;
@@ -1225,14 +1228,14 @@ static int xadc_probe(struct platform_device *pdev) ret =xadc_parse_dt (indio_dev, pdev->dev.of_node, &conf0);if (ret) - goto err_device_free; +return ret;if (xadc->ops->flags &XADC_FLAGS_BUFFERED ) { ret =iio_triggered_buffer_setup (indio_dev, &iio_pollfunc_store_time, &xadc_trigger_handler, &xadc_buffer_ops);if (ret) - goto err_device_free; +return ret; xadc->convst_trigger =xadc_alloc_trigger (indio_dev,"convst" );if (IS_ERR (xadc->convst_trigger)) {
@@ -1350,8 +1353,6 @@ static int xadc_probe(struct platform_device *pdev) err_triggered_buffer_cleanup:if (xadc->ops->flags &XADC_FLAGS_BUFFERED )iio_triggered_buffer_cleanup (indio_dev); -err_device_free: -kfree (indio_dev->channels);return ret; }
@@ -1371,7 +1372,6 @@ static int xadc_remove(struct platform_device *pdev)cancel_delayed_work_sync (&xadc->zynq_unmask_work);clk_disable_unprepare (xadc->clk);kfree (xadc->data); -kfree (indio_dev->channels);return 0 ; }
Signature · 1 line
2.26.1