Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7f0c5ae1 authored by Andy Shevchenko's avatar Andy Shevchenko Committed by Lee Jones
Browse files

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 c4726abc ("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
c4726abc ("mfd: intel_quark_i2c_gpio: Use clkdev_create()") first.

Cc: stable@vger.kernel.org
Fixes: 60ae5b9f (mfd: intel_quark_i2c_gpio: Add Intel Quark X1000 I2C-GPIO MFD Driver)
Signed-off-by: default avatarAndy Shevchenko <andriy.shevchenko@linux.intel.com>
Acked-by: default avatarStephen Boyd <sboyd@codeaurora.org>
Signed-off-by: default avatarLee Jones <lee.jones@linaro.org>
parent 65433fd5
Loading
Loading
Loading
Loading
+17 −8
Original line number Diff line number Diff line
@@ -139,6 +139,7 @@ static int intel_quark_register_i2c_clk(struct intel_quark_mfd *quark_mfd)
						INTEL_QUARK_I2C_CONTROLLER_CLK);

	if (!quark_mfd->i2c_clk_lookup) {
		clk_unregister(quark_mfd->i2c_clk);
		dev_err(&pdev->dev, "Fixed clk register failed\n");
		return -ENOMEM;
	}
@@ -150,7 +151,7 @@ static void intel_quark_unregister_i2c_clk(struct pci_dev *pdev)
{
	struct intel_quark_mfd *quark_mfd = dev_get_drvdata(&pdev->dev);

	if (!quark_mfd->i2c_clk || !quark_mfd->i2c_clk_lookup)
	if (!quark_mfd->i2c_clk_lookup)
		return;

	clkdev_drop(quark_mfd->i2c_clk_lookup);
@@ -246,25 +247,33 @@ static int intel_quark_mfd_probe(struct pci_dev *pdev,
	quark_mfd = devm_kzalloc(&pdev->dev, sizeof(*quark_mfd), GFP_KERNEL);
	if (!quark_mfd)
		return -ENOMEM;

	quark_mfd->pdev = pdev;
	dev_set_drvdata(&pdev->dev, quark_mfd);

	ret = intel_quark_register_i2c_clk(quark_mfd);
	if (ret)
		return ret;

	dev_set_drvdata(&pdev->dev, quark_mfd);

	ret = intel_quark_i2c_setup(pdev, &intel_quark_mfd_cells[1]);
	if (ret)
		return ret;
		goto err_unregister_i2c_clk;

	ret = intel_quark_gpio_setup(pdev, &intel_quark_mfd_cells[0]);
	if (ret)
		return ret;
		goto err_unregister_i2c_clk;

	return mfd_add_devices(&pdev->dev, 0, intel_quark_mfd_cells,
	ret = mfd_add_devices(&pdev->dev, 0, intel_quark_mfd_cells,
			      ARRAY_SIZE(intel_quark_mfd_cells), NULL, 0,
			      NULL);
	if (ret)
		goto err_unregister_i2c_clk;

	return 0;

err_unregister_i2c_clk:
	intel_quark_unregister_i2c_clk(pdev);
	return ret;
}

static void intel_quark_mfd_remove(struct pci_dev *pdev)