Skip to content

Commit

Permalink
mfd: mfd-core: Remove usage counting for .{en,dis}able() call-backs
Browse files Browse the repository at this point in the history
The MFD implementation for reference counting was complex and unnecessary.
There was only one bona fide user which has now been converted to handle
the process in a different way. Any future resource protection, shared
enablement functions should be handed by the parent device, rather than
through the MFD subsystem API.

Signed-off-by: Lee Jones <lee.jones@linaro.org>
Reviewed-by: Daniel Thompson <daniel.thompson@linaro.org>
Reviewed-by: Mark Brown <broonie@kernel.org>
  • Loading branch information
Lee Jones committed Nov 11, 2019
1 parent 504c3fa commit 5a47c0f
Show file tree
Hide file tree
Showing 2 changed files with 9 additions and 50 deletions.
57 changes: 9 additions & 48 deletions drivers/mfd/mfd-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,53 +26,31 @@ static struct device_type mfd_dev_type = {
int mfd_cell_enable(struct platform_device *pdev)
{
const struct mfd_cell *cell = mfd_get_cell(pdev);
int err = 0;

if (!cell->enable) {
dev_dbg(&pdev->dev, "No .enable() call-back registered\n");
return 0;
}

/* only call enable hook if the cell wasn't previously enabled */
if (atomic_inc_return(cell->usage_count) == 1)
err = cell->enable(pdev);

/* if the enable hook failed, decrement counter to allow retries */
if (err)
atomic_dec(cell->usage_count);

return err;
return cell->enable(pdev);
}
EXPORT_SYMBOL(mfd_cell_enable);

int mfd_cell_disable(struct platform_device *pdev)
{
const struct mfd_cell *cell = mfd_get_cell(pdev);
int err = 0;

if (!cell->disable) {
dev_dbg(&pdev->dev, "No .disable() call-back registered\n");
return 0;
}

/* only disable if no other clients are using it */
if (atomic_dec_return(cell->usage_count) == 0)
err = cell->disable(pdev);

/* if the disable hook failed, increment to allow retries */
if (err)
atomic_inc(cell->usage_count);

/* sanity check; did someone call disable too many times? */
WARN_ON(atomic_read(cell->usage_count) < 0);

return err;
return cell->disable(pdev);
}
EXPORT_SYMBOL(mfd_cell_disable);

static int mfd_platform_add_cell(struct platform_device *pdev,
const struct mfd_cell *cell,
atomic_t *usage_count)
const struct mfd_cell *cell)
{
if (!cell)
return 0;
Expand All @@ -81,7 +59,6 @@ static int mfd_platform_add_cell(struct platform_device *pdev,
if (!pdev->mfd_cell)
return -ENOMEM;

pdev->mfd_cell->usage_count = usage_count;
return 0;
}

Expand Down Expand Up @@ -144,7 +121,7 @@ static inline void mfd_acpi_add_device(const struct mfd_cell *cell,
#endif

static int mfd_add_device(struct device *parent, int id,
const struct mfd_cell *cell, atomic_t *usage_count,
const struct mfd_cell *cell,
struct resource *mem_base,
int irq_base, struct irq_domain *domain)
{
Expand Down Expand Up @@ -206,7 +183,7 @@ static int mfd_add_device(struct device *parent, int id,
goto fail_alias;
}

ret = mfd_platform_add_cell(pdev, cell, usage_count);
ret = mfd_platform_add_cell(pdev, cell);
if (ret)
goto fail_alias;

Expand Down Expand Up @@ -296,16 +273,9 @@ int mfd_add_devices(struct device *parent, int id,
{
int i;
int ret;
atomic_t *cnts;

/* initialize reference counting for all cells */
cnts = kcalloc(n_devs, sizeof(*cnts), GFP_KERNEL);
if (!cnts)
return -ENOMEM;

for (i = 0; i < n_devs; i++) {
atomic_set(&cnts[i], 0);
ret = mfd_add_device(parent, id, cells + i, cnts + i, mem_base,
ret = mfd_add_device(parent, id, cells + i, mem_base,
irq_base, domain);
if (ret)
goto fail;
Expand All @@ -316,17 +286,15 @@ int mfd_add_devices(struct device *parent, int id,
fail:
if (i)
mfd_remove_devices(parent);
else
kfree(cnts);

return ret;
}
EXPORT_SYMBOL(mfd_add_devices);

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

if (dev->type != &mfd_dev_type)
return 0;
Expand All @@ -337,20 +305,13 @@ static int mfd_remove_devices_fn(struct device *dev, void *c)
regulator_bulk_unregister_supply_alias(dev, cell->parent_supplies,
cell->num_parent_supplies);

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

platform_device_unregister(pdev);
return 0;
}

void mfd_remove_devices(struct device *parent)
{
atomic_t *cnts = NULL;

device_for_each_child_reverse(parent, &cnts, mfd_remove_devices_fn);
kfree(cnts);
device_for_each_child_reverse(parent, NULL, mfd_remove_devices_fn);
}
EXPORT_SYMBOL(mfd_remove_devices);

Expand Down
2 changes: 0 additions & 2 deletions include/linux/mfd/core.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,6 @@ struct mfd_cell {
const char *name;
int id;

/* refcounting for multiple drivers to use a single cell */
atomic_t *usage_count;
int (*enable)(struct platform_device *dev);
int (*disable)(struct platform_device *dev);

Expand Down

0 comments on commit 5a47c0f

Please sign in to comment.