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

Commit b9fbb62e authored by Charles Keepax's avatar Charles Keepax Committed by Samuel Ortiz
Browse files

mfd: Only unregister platform devices allocated by the mfd core



mfd_remove_devices would iterate over all devices sharing a parent with
an mfd device regardless of whether they were allocated by the mfd core
or not. This especially caused problems when the device structure was
not contained within a platform_device, because to_platform_device is
used on each device pointer.

This patch defines a device_type for mfd devices and checks this is
present from mfd_remove_devices_fn before processing the device.

Cc: stable@vger.kernel.org
Signed-off-by: default avatarCharles Keepax <ckeepax@opensource.wolfsonmicro.com>
Tested-by: default avatarPeter Tyser <ptyser@xes-inc.com>
Reviewed-by: default avatarMark Brown <broonie@opensource.wolfsonmicro.com>
Signed-off-by: default avatarSamuel Ortiz <sameo@linux.intel.com>
parent d511b9c3
Loading
Loading
Loading
Loading
+13 −2
Original line number Diff line number Diff line
@@ -21,6 +21,10 @@
#include <linux/irqdomain.h>
#include <linux/of.h>

static struct device_type mfd_dev_type = {
	.name	= "mfd_device",
};

int mfd_cell_enable(struct platform_device *pdev)
{
	const struct mfd_cell *cell = mfd_get_cell(pdev);
@@ -91,6 +95,7 @@ static int mfd_add_device(struct device *parent, int id,
		goto fail_device;

	pdev->dev.parent = parent;
	pdev->dev.type = &mfd_dev_type;

	if (parent->of_node && cell->of_compatible) {
		for_each_child_of_node(parent->of_node, np) {
@@ -204,10 +209,16 @@ EXPORT_SYMBOL(mfd_add_devices);

static int mfd_remove_devices_fn(struct device *dev, void *c)
{
	struct platform_device *pdev = to_platform_device(dev);
	const struct mfd_cell *cell = mfd_get_cell(pdev);
	struct platform_device *pdev;
	const struct mfd_cell *cell;
	atomic_t **usage_count = c;

	if (dev->type != &mfd_dev_type)
		return 0;

	pdev = to_platform_device(dev);
	cell = mfd_get_cell(pdev);

	/* find the base address of usage_count pointers (for freeing) */
	if (!*usage_count || (cell->usage_count < *usage_count))
		*usage_count = cell->usage_count;