diff options
author | Andy Shevchenko <andriy.shevchenko@linux.intel.com> | 2016-02-19 03:42:10 -0500 |
---|---|---|
committer | Lee Jones <lee.jones@linaro.org> | 2016-04-11 08:31:39 -0400 |
commit | 7f0c5ae18d649ed2f4978cbf07c02a0ff732f23e (patch) | |
tree | d2ab98dbce17b3209fc465c919ba8b6658985245 /drivers/mfd | |
parent | 65433fd561f089f232758efc2c6566b6b6febb47 (diff) |
mfd: intel_quark_i2c_gpio: Remove clock tree on error path
There is a potential resource leak in case when ->probe() fails. We have to
unregister and remove clock tree which is done here.
This is a follow up to previously pushed commit c4726abce63b ("mfd:
intel_quark_i2c_gpio: Use clkdev_create()") that prevents double free() when
clkdev_drop() followed by kfree() in devm_kcalloc() release stage.
I leave Fixes tag here, but the backporting will require to backport the commit
c4726abce63b ("mfd: intel_quark_i2c_gpio: Use clkdev_create()") first.
Cc: stable@vger.kernel.org
Fixes: 60ae5b9f5cdd (mfd: intel_quark_i2c_gpio: Add Intel Quark X1000 I2C-GPIO MFD Driver)
Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Acked-by: Stephen Boyd <sboyd@codeaurora.org>
Signed-off-by: Lee Jones <lee.jones@linaro.org>
Diffstat (limited to 'drivers/mfd')
-rw-r--r-- | drivers/mfd/intel_quark_i2c_gpio.c | 25 |
1 files changed, 17 insertions, 8 deletions
diff --git a/drivers/mfd/intel_quark_i2c_gpio.c b/drivers/mfd/intel_quark_i2c_gpio.c index bdc5e27222c0..7450f5d8770c 100644 --- a/drivers/mfd/intel_quark_i2c_gpio.c +++ b/drivers/mfd/intel_quark_i2c_gpio.c | |||
@@ -139,6 +139,7 @@ static int intel_quark_register_i2c_clk(struct intel_quark_mfd *quark_mfd) | |||
139 | INTEL_QUARK_I2C_CONTROLLER_CLK); | 139 | INTEL_QUARK_I2C_CONTROLLER_CLK); |
140 | 140 | ||
141 | if (!quark_mfd->i2c_clk_lookup) { | 141 | if (!quark_mfd->i2c_clk_lookup) { |
142 | clk_unregister(quark_mfd->i2c_clk); | ||
142 | dev_err(&pdev->dev, "Fixed clk register failed\n"); | 143 | dev_err(&pdev->dev, "Fixed clk register failed\n"); |
143 | return -ENOMEM; | 144 | return -ENOMEM; |
144 | } | 145 | } |
@@ -150,7 +151,7 @@ static void intel_quark_unregister_i2c_clk(struct pci_dev *pdev) | |||
150 | { | 151 | { |
151 | struct intel_quark_mfd *quark_mfd = dev_get_drvdata(&pdev->dev); | 152 | struct intel_quark_mfd *quark_mfd = dev_get_drvdata(&pdev->dev); |
152 | 153 | ||
153 | if (!quark_mfd->i2c_clk || !quark_mfd->i2c_clk_lookup) | 154 | if (!quark_mfd->i2c_clk_lookup) |
154 | return; | 155 | return; |
155 | 156 | ||
156 | clkdev_drop(quark_mfd->i2c_clk_lookup); | 157 | clkdev_drop(quark_mfd->i2c_clk_lookup); |
@@ -246,25 +247,33 @@ static int intel_quark_mfd_probe(struct pci_dev *pdev, | |||
246 | quark_mfd = devm_kzalloc(&pdev->dev, sizeof(*quark_mfd), GFP_KERNEL); | 247 | quark_mfd = devm_kzalloc(&pdev->dev, sizeof(*quark_mfd), GFP_KERNEL); |
247 | if (!quark_mfd) | 248 | if (!quark_mfd) |
248 | return -ENOMEM; | 249 | return -ENOMEM; |
250 | |||
249 | quark_mfd->pdev = pdev; | 251 | quark_mfd->pdev = pdev; |
252 | dev_set_drvdata(&pdev->dev, quark_mfd); | ||
250 | 253 | ||
251 | ret = intel_quark_register_i2c_clk(quark_mfd); | 254 | ret = intel_quark_register_i2c_clk(quark_mfd); |
252 | if (ret) | 255 | if (ret) |
253 | return ret; | 256 | return ret; |
254 | 257 | ||
255 | dev_set_drvdata(&pdev->dev, quark_mfd); | ||
256 | |||
257 | ret = intel_quark_i2c_setup(pdev, &intel_quark_mfd_cells[1]); | 258 | ret = intel_quark_i2c_setup(pdev, &intel_quark_mfd_cells[1]); |
258 | if (ret) | 259 | if (ret) |
259 | return ret; | 260 | goto err_unregister_i2c_clk; |
260 | 261 | ||
261 | ret = intel_quark_gpio_setup(pdev, &intel_quark_mfd_cells[0]); | 262 | ret = intel_quark_gpio_setup(pdev, &intel_quark_mfd_cells[0]); |
262 | if (ret) | 263 | if (ret) |
263 | return ret; | 264 | goto err_unregister_i2c_clk; |
264 | 265 | ||
265 | return mfd_add_devices(&pdev->dev, 0, intel_quark_mfd_cells, | 266 | ret = mfd_add_devices(&pdev->dev, 0, intel_quark_mfd_cells, |
266 | ARRAY_SIZE(intel_quark_mfd_cells), NULL, 0, | 267 | ARRAY_SIZE(intel_quark_mfd_cells), NULL, 0, |
267 | NULL); | 268 | NULL); |
269 | if (ret) | ||
270 | goto err_unregister_i2c_clk; | ||
271 | |||
272 | return 0; | ||
273 | |||
274 | err_unregister_i2c_clk: | ||
275 | intel_quark_unregister_i2c_clk(pdev); | ||
276 | return ret; | ||
268 | } | 277 | } |
269 | 278 | ||
270 | static void intel_quark_mfd_remove(struct pci_dev *pdev) | 279 | static void intel_quark_mfd_remove(struct pci_dev *pdev) |