Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

pinctrl: ti: ti-iodelay: Fix some error handling paths

In the probe, if an error occurs after the ti_iodelay_pinconf_init_dev()
call, it is likely that ti_iodelay_pinconf_deinit_dev() should be called,
as already done in the remove function.

Also in ti_iodelay_pinconf_init_dev(), if an error occurs after the first
regmap_update_bits() call, it is also likely that the deinit() function
should be called.

The easier way to fix it is to add a devm_add_action_or_reset() at the
rigtht place to have ti_iodelay_pinconf_deinit_dev() called when needed.

Doing so, the .remove() function can be removed, and the associated
platform_set_drvdata() call in the probe as well.

Fixes: 003910ebc83b ("pinctrl: Introduce TI IOdelay configuration driver")
Signed-off-by: Christophe JAILLET <christophe.jaillet@wanadoo.fr>
Link: https://lore.kernel.org/0220fa5b925bd08e361be8206a5438f6229deaac.1720556038.git.christophe.jaillet@wanadoo.fr
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>

authored by

Christophe JAILLET and committed by
Linus Walleij
a9f2b249 bebf833d

+21 -31
+21 -31
drivers/pinctrl/ti/pinctrl-ti-iodelay.c
··· 274 274 } 275 275 276 276 /** 277 + * ti_iodelay_pinconf_deinit_dev() - deinit the iodelay device 278 + * @data: IODelay device 279 + * 280 + * Deinitialize the IODelay device (basically just lock the region back up. 281 + */ 282 + static void ti_iodelay_pinconf_deinit_dev(void *data) 283 + { 284 + struct ti_iodelay_device *iod = data; 285 + const struct ti_iodelay_reg_data *reg = iod->reg_data; 286 + 287 + /* lock the iodelay region back again */ 288 + regmap_update_bits(iod->regmap, reg->reg_global_lock_offset, 289 + reg->global_lock_mask, reg->global_lock_val); 290 + } 291 + 292 + /** 277 293 * ti_iodelay_pinconf_init_dev() - Initialize IODelay device 278 294 * @iod: iodelay device 279 295 * ··· 308 292 /* unlock the iodelay region */ 309 293 r = regmap_update_bits(iod->regmap, reg->reg_global_lock_offset, 310 294 reg->global_lock_mask, reg->global_unlock_val); 295 + if (r) 296 + return r; 297 + 298 + r = devm_add_action_or_reset(iod->dev, ti_iodelay_pinconf_deinit_dev, 299 + iod); 311 300 if (r) 312 301 return r; 313 302 ··· 372 351 ival->fine_ref_count, ival->fine_delay_count, ival->fdpe); 373 352 374 353 return 0; 375 - } 376 - 377 - /** 378 - * ti_iodelay_pinconf_deinit_dev() - deinit the iodelay device 379 - * @iod: IODelay device 380 - * 381 - * Deinitialize the IODelay device (basically just lock the region back up. 382 - */ 383 - static void ti_iodelay_pinconf_deinit_dev(struct ti_iodelay_device *iod) 384 - { 385 - const struct ti_iodelay_reg_data *reg = iod->reg_data; 386 - 387 - /* lock the iodelay region back again */ 388 - regmap_update_bits(iod->regmap, reg->reg_global_lock_offset, 389 - reg->global_lock_mask, reg->global_lock_val); 390 354 } 391 355 392 356 /** ··· 883 877 return ret; 884 878 } 885 879 886 - platform_set_drvdata(pdev, iod); 887 - 888 880 return pinctrl_enable(iod->pctl); 889 - } 890 - 891 - /** 892 - * ti_iodelay_remove() - standard remove 893 - * @pdev: platform device 894 - */ 895 - static void ti_iodelay_remove(struct platform_device *pdev) 896 - { 897 - struct ti_iodelay_device *iod = platform_get_drvdata(pdev); 898 - 899 - ti_iodelay_pinconf_deinit_dev(iod); 900 - 901 - /* Expect other allocations to be freed by devm */ 902 881 } 903 882 904 883 static struct platform_driver ti_iodelay_driver = { 905 884 .probe = ti_iodelay_probe, 906 - .remove_new = ti_iodelay_remove, 907 885 .driver = { 908 886 .name = DRIVER_NAME, 909 887 .of_match_table = ti_iodelay_of_match,