gpio: vt8500: memory cleanup missing
PATCH v2 1/1 gpio: vt8500: memory cleanup missing
This driver is missing a .remove callback, and the fail path on probe is incomplete.
If an error occurs in vt8500_add_chips, gpio_base is not unmapped. The driver is also ignoring the return value from this function so if a chip fails to register it completes as successful.
Replaced pr_err with dev_err in vt8500_add_chips since the device is available.
There is also no .remove callback defined. To allow removing the registered chips, I have moved *vtchip to be a static global.
---
Hi Grant,
Let me know what you think of these changes.
v2:
Removed unnecessary whitespace change.
Removed test against pdev->dev.of_node (np). Replaced code with a
devm_request_and_ioremap so np is now unneccessary. This also removes the need for cleanup in the fail path.
Move struct vt8500_gpio_chip within vt8500_data and store the iobase and
num_banks in vt8500_data.
drivers/gpio/gpio-vt8500.c | 61 +++++++++++++++++++++++++++++++++++--------- 1 file changed, 49 insertions(+), 12 deletions(-)
drivers/gpio/gpio-vt8500.c +49 -12
@@ -127,6 +127,12 @@ struct vt8500_gpio_chip {void __iomem *base; }; +struct vt8500_data { +struct vt8500_gpio_chip *chip; +void __iomem *iobase; +int num_banks; +}; +#define to_vt8500 (__chip) container_of(__chip, struct vt8500_gpio_chip, chip)
@@ -224,19 +230,32 @@ static int vt8500_of_xlate(struct gpio_chip *gc,static int vt8500_add_chips (struct platform_device *pdev,void __iomem *base,const struct vt8500_gpio_data *data) { +struct vt8500_data *priv;struct vt8500_gpio_chip *vtchip;struct gpio_chip *chip;int i;int pin_cnt =0 ; - vtchip =devm_kzalloc (&pdev->dev, + priv =devm_kzalloc (&pdev->dev,sizeof (struct vt8500_data ),GFP_KERNEL ); +if (!priv) { +dev_err (&pdev->dev,"failed to allocate memory\n" ); +return -ENOMEM ; + } + + priv->chip =devm_kzalloc (&pdev->dev,sizeof (struct vt8500_gpio_chip ) * data->num_banks,GFP_KERNEL ); -if (!vtchip) { -pr_err ("%s: failed to allocate chip memory\n" , __func__); +if (!priv->chip) { +dev_err (&pdev->dev,"failed to allocate chip memory\n" );return -ENOMEM ; } + priv->iobase = base; + priv->num_banks = data->num_banks; +platform_set_drvdata (pdev, priv); + + vtchip = priv->chip; +for (i =0 ; i < data->num_banks; i++) { vtchip[i].base = base; vtchip[i].regs = &data->banks[i];
@@ -273,36 +292,54 @@ static struct of_device_id vt8500_gpio_dt_ids[] = {static int vt8500_gpio_probe (struct platform_device *pdev) { +int ret;void __iomem *gpio_base; -struct device_node *np; +struct resource *res;const struct of_device_id *of_id =of_match_device (vt8500_gpio_dt_ids, &pdev->dev);if (!of_id) { -dev_err (&pdev->dev,"Failed to find gpio controller\n" ); +dev_err (&pdev->dev,"No matching driver data\n" );return -ENODEV ; } - np = pdev->dev.of_node; -if (!np) { -dev_err (&pdev->dev,"Missing GPIO description in devicetree\n" ); -return -EFAULT ; + res =platform_get_resource (pdev,IORESOURCE_MEM ,0 ); +if (!res) { +dev_err (&pdev->dev,"Unable to get IO resource\n" ); +return -ENODEV ; } - gpio_base =of_iomap (np,0 ); + gpio_base =devm_request_and_ioremap (&pdev->dev, res);if (!gpio_base) {dev_err (&pdev->dev,"Unable to map GPIO registers\n" ); -of_node_put (np);return -ENOMEM ; } -vt8500_add_chips (pdev, gpio_base, of_id->data); + ret =vt8500_add_chips (pdev, gpio_base, of_id->data); + +return ret; +} + +static int vt8500_gpio_remove (struct platform_device *pdev) +{ +int i; +int ret; +struct vt8500_data *priv =platform_get_drvdata (pdev); +struct vt8500_gpio_chip *vtchip = priv->chip; + +for (i =0 ; i < priv->num_banks; i++) { + ret =gpiochip_remove (&vtchip[i].chip); +if (ret) +dev_warn (&pdev->dev,"gpiochip_remove returned %d\n" , + ret); + }return 0 ; }static struct platform_driver vt8500_gpio_driver = { .probe = vt8500_gpio_probe, + .remove = vt8500_gpio_remove, .driver = { .name ="vt8500-gpio" , .owner =THIS_MODULE ,
Signature · 1 line
1.7.9.5
Quoted 19 lines · Tony Prisk
This driver is missing a .remove callback, and the fail path on probe is incomplete.
If an error occurs in
vt8500_add_chips,gpio_baseis not unmapped. The driver is also ignoring the return value from this function so if a chip fails to register it completes as successful.Replaced
pr_errwithdev_errinvt8500_add_chipssince the device is available.There is also no .remove callback defined. To allow removing the registered chips, I have moved *vtchip to be a static global.
Signed-off-by Tony Prisk <[email protected]>---
Hi Grant,Let me know what you think of these changes.
Quoted 8 lines
v2:
Removed unnecessary whitespace change.
Removed test againstpdev->dev.of_node(np). Replaced code with a
devm_request_and_ioremapso np is now unneccessary. This also removes the need for cleanup in the fail path.
Move structvt8500_gpio_chipwithinvt8500_dataand store the iobase and
num_banksinvt8500_data.
Grant,
If there are no further changes for this patch, would you mind correcting the commit message when you merge it?
-There is also no .remove callback defined. To allow removing the -Registered chips, I have moved *vtchip to be a static global.
+ There is also no .remove callback defined.
Otherwise, I will fix it along with whatever other comments come in.
Regards
Tony P