Commit 306ba240 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'gpio-fixes-for-v6.1' of git://git.kernel.org/pub/scm/linux/kernel/git/brgl/linux

Pull gpio fixes from Bartosz Golaszewski:

 - fix a memory leak in gpiolib core

 - fix reference leaks in gpio-amd8111 and gpio-rockchip

* tag 'gpio-fixes-for-v6.1' of git://git.kernel.org/pub/scm/linux/kernel/git/brgl/linux:
  gpio/rockchip: fix refcount leak in rockchip_gpiolib_register()
  gpio: amd8111: Fix PCI device reference count leak
  gpiolib: fix memory leak in gpiochip_setup_dev()
parents 57fb3f66 63ff545a
...@@ -226,7 +226,10 @@ static int __init amd_gpio_init(void) ...@@ -226,7 +226,10 @@ static int __init amd_gpio_init(void)
ioport_unmap(gp.pm); ioport_unmap(gp.pm);
goto out; goto out;
} }
return 0;
out: out:
pci_dev_put(pdev);
return err; return err;
} }
...@@ -234,6 +237,7 @@ static void __exit amd_gpio_exit(void) ...@@ -234,6 +237,7 @@ static void __exit amd_gpio_exit(void)
{ {
gpiochip_remove(&gp.chip); gpiochip_remove(&gp.chip);
ioport_unmap(gp.pm); ioport_unmap(gp.pm);
pci_dev_put(gp.pdev);
} }
module_init(amd_gpio_init); module_init(amd_gpio_init);
......
...@@ -610,6 +610,7 @@ static int rockchip_gpiolib_register(struct rockchip_pin_bank *bank) ...@@ -610,6 +610,7 @@ static int rockchip_gpiolib_register(struct rockchip_pin_bank *bank)
return -ENODATA; return -ENODATA;
pctldev = of_pinctrl_get(pctlnp); pctldev = of_pinctrl_get(pctlnp);
of_node_put(pctlnp);
if (!pctldev) if (!pctldev)
return -ENODEV; return -ENODEV;
......
...@@ -526,12 +526,13 @@ static int gpiochip_setup_dev(struct gpio_device *gdev) ...@@ -526,12 +526,13 @@ static int gpiochip_setup_dev(struct gpio_device *gdev)
if (ret) if (ret)
return ret; return ret;
/* From this point, the .release() function cleans up gpio_device */
gdev->dev.release = gpiodevice_release;
ret = gpiochip_sysfs_register(gdev); ret = gpiochip_sysfs_register(gdev);
if (ret) if (ret)
goto err_remove_device; goto err_remove_device;
/* From this point, the .release() function cleans up gpio_device */
gdev->dev.release = gpiodevice_release;
dev_dbg(&gdev->dev, "registered GPIOs %d to %d on %s\n", gdev->base, dev_dbg(&gdev->dev, "registered GPIOs %d to %d on %s\n", gdev->base,
gdev->base + gdev->ngpio - 1, gdev->chip->label ? : "generic"); gdev->base + gdev->ngpio - 1, gdev->chip->label ? : "generic");
...@@ -597,10 +598,10 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data, ...@@ -597,10 +598,10 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data,
struct fwnode_handle *fwnode = NULL; struct fwnode_handle *fwnode = NULL;
struct gpio_device *gdev; struct gpio_device *gdev;
unsigned long flags; unsigned long flags;
int base = gc->base;
unsigned int i; unsigned int i;
u32 ngpios = 0;
int base = 0;
int ret = 0; int ret = 0;
u32 ngpios;
if (gc->fwnode) if (gc->fwnode)
fwnode = gc->fwnode; fwnode = gc->fwnode;
...@@ -647,17 +648,12 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data, ...@@ -647,17 +648,12 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data,
else else
gdev->owner = THIS_MODULE; gdev->owner = THIS_MODULE;
gdev->descs = kcalloc(gc->ngpio, sizeof(gdev->descs[0]), GFP_KERNEL);
if (!gdev->descs) {
ret = -ENOMEM;
goto err_free_dev_name;
}
/* /*
* Try the device properties if the driver didn't supply the number * Try the device properties if the driver didn't supply the number
* of GPIO lines. * of GPIO lines.
*/ */
if (gc->ngpio == 0) { ngpios = gc->ngpio;
if (ngpios == 0) {
ret = device_property_read_u32(&gdev->dev, "ngpios", &ngpios); ret = device_property_read_u32(&gdev->dev, "ngpios", &ngpios);
if (ret == -ENODATA) if (ret == -ENODATA)
/* /*
...@@ -668,7 +664,7 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data, ...@@ -668,7 +664,7 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data,
*/ */
ngpios = 0; ngpios = 0;
else if (ret) else if (ret)
goto err_free_descs; goto err_free_dev_name;
gc->ngpio = ngpios; gc->ngpio = ngpios;
} }
...@@ -676,13 +672,19 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data, ...@@ -676,13 +672,19 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data,
if (gc->ngpio == 0) { if (gc->ngpio == 0) {
chip_err(gc, "tried to insert a GPIO chip with zero lines\n"); chip_err(gc, "tried to insert a GPIO chip with zero lines\n");
ret = -EINVAL; ret = -EINVAL;
goto err_free_descs; goto err_free_dev_name;
} }
if (gc->ngpio > FASTPATH_NGPIO) if (gc->ngpio > FASTPATH_NGPIO)
chip_warn(gc, "line cnt %u is greater than fast path cnt %u\n", chip_warn(gc, "line cnt %u is greater than fast path cnt %u\n",
gc->ngpio, FASTPATH_NGPIO); gc->ngpio, FASTPATH_NGPIO);
gdev->descs = kcalloc(gc->ngpio, sizeof(*gdev->descs), GFP_KERNEL);
if (!gdev->descs) {
ret = -ENOMEM;
goto err_free_dev_name;
}
gdev->label = kstrdup_const(gc->label ?: "unknown", GFP_KERNEL); gdev->label = kstrdup_const(gc->label ?: "unknown", GFP_KERNEL);
if (!gdev->label) { if (!gdev->label) {
ret = -ENOMEM; ret = -ENOMEM;
...@@ -701,11 +703,13 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data, ...@@ -701,11 +703,13 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data,
* it may be a pipe dream. It will not happen before we get rid * it may be a pipe dream. It will not happen before we get rid
* of the sysfs interface anyways. * of the sysfs interface anyways.
*/ */
base = gc->base;
if (base < 0) { if (base < 0) {
base = gpiochip_find_base(gc->ngpio); base = gpiochip_find_base(gc->ngpio);
if (base < 0) { if (base < 0) {
ret = base;
spin_unlock_irqrestore(&gpio_lock, flags); spin_unlock_irqrestore(&gpio_lock, flags);
ret = base;
base = 0;
goto err_free_label; goto err_free_label;
} }
/* /*
...@@ -816,6 +820,11 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data, ...@@ -816,6 +820,11 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data,
err_free_gpiochip_mask: err_free_gpiochip_mask:
gpiochip_remove_pin_ranges(gc); gpiochip_remove_pin_ranges(gc);
gpiochip_free_valid_mask(gc); gpiochip_free_valid_mask(gc);
if (gdev->dev.release) {
/* release() has been registered by gpiochip_setup_dev() */
put_device(&gdev->dev);
goto err_print_message;
}
err_remove_from_list: err_remove_from_list:
spin_lock_irqsave(&gpio_lock, flags); spin_lock_irqsave(&gpio_lock, flags);
list_del(&gdev->list); list_del(&gdev->list);
...@@ -829,13 +838,14 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data, ...@@ -829,13 +838,14 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data,
err_free_ida: err_free_ida:
ida_free(&gpio_ida, gdev->id); ida_free(&gpio_ida, gdev->id);
err_free_gdev: err_free_gdev:
kfree(gdev);
err_print_message:
/* failures here can mean systems won't boot... */ /* failures here can mean systems won't boot... */
if (ret != -EPROBE_DEFER) { if (ret != -EPROBE_DEFER) {
pr_err("%s: GPIOs %d..%d (%s) failed to register, %d\n", __func__, pr_err("%s: GPIOs %d..%d (%s) failed to register, %d\n", __func__,
gdev->base, gdev->base + gdev->ngpio - 1, base, base + (int)ngpios - 1,
gc->label ? : "generic", ret); gc->label ? : "generic", ret);
} }
kfree(gdev);
return ret; return ret;
} }
EXPORT_SYMBOL_GPL(gpiochip_add_data_with_key); EXPORT_SYMBOL_GPL(gpiochip_add_data_with_key);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment