lists.openwall.net | lists / announce owl-users owl-dev john-users john-dev passwdqc-users yescrypt popa3d-users / oss-security kernel-hardening musl sabotage tlsify passwords / crypt-dev xvendor / Bugtraq Full-Disclosure linux-kernel linux-netdev linux-ext4 linux-hardening linux-cve-announce PHC | |
Open Source and information security mailing list archives
| ||
|
Date: Mon, 2 Jun 2014 10:01:43 +0100 From: Charles Keepax <ckeepax@...nsource.wolfsonmicro.com> To: lee.jones@...aro.org Cc: sameo@...ux.intel.com, patches@...nsource.wolfsonmicro.com, linux-kernel@...r.kernel.org Subject: [PATCH 1/2] mfd: core: Add the option to order destruction of MFD cells Sometimes MFD children will have interdependancies. For example an MFD device might contain a regulator cell and another cell which requires that regulator to function. Probe deferral will ensure that these devices probe in the correct order, however currently nothing ensures they are destroyed in the correct order. As such it is possible for a cell to be destroyed whilst another cell still expects it to exist. For example the cell mentioned earlier would attempt to do a regulator_put as part of its own tear-down but the regulator may have already been destroyed. This patch add a field remove_level to the mfd_cell data structure which allows users to group the destruction of the MFD cells. Cells with a lower remove_level will be destroyed first. This approach also doesn't alter the destruction order for existing devices, so should be no-op for devices not explicitly using it. Signed-off-by: Charles Keepax <ckeepax@...nsource.wolfsonmicro.com> --- drivers/mfd/mfd-core.c | 33 +++++++++++++++++++++++++++++---- include/linux/mfd/core.h | 3 +++ 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/drivers/mfd/mfd-core.c b/drivers/mfd/mfd-core.c index 2676492..0c12787 100644 --- a/drivers/mfd/mfd-core.c +++ b/drivers/mfd/mfd-core.c @@ -226,11 +226,19 @@ fail: } EXPORT_SYMBOL(mfd_add_devices); +struct mfd_remove_data { + atomic_t *cnts; + + int level; + int next_level; +}; + static int mfd_remove_devices_fn(struct device *dev, void *c) { struct platform_device *pdev; const struct mfd_cell *cell; - atomic_t **usage_count = c; + struct mfd_remove_data *rd = c; + atomic_t **usage_count = &rd->cnts; if (dev->type != &mfd_dev_type) return 0; @@ -238,6 +246,15 @@ static int mfd_remove_devices_fn(struct device *dev, void *c) pdev = to_platform_device(dev); cell = mfd_get_cell(pdev); + if (rd->level < cell->remove_level) { + if (!rd->next_level || rd->next_level > cell->remove_level) + rd->next_level = cell->remove_level; + + return 0; + } + + dev_dbg(dev, "Removing from MFD\n"); + /* find the base address of usage_count pointers (for freeing) */ if (!*usage_count || (cell->usage_count < *usage_count)) *usage_count = cell->usage_count; @@ -248,10 +265,18 @@ static int mfd_remove_devices_fn(struct device *dev, void *c) void mfd_remove_devices(struct device *parent) { - atomic_t *cnts = NULL; + struct mfd_remove_data rd = {}; + + do { + rd.level = rd.next_level; + rd.next_level = 0; + + dev_dbg(parent, "Running remove for level: %d\n", rd.level); + + device_for_each_child(parent, &rd, mfd_remove_devices_fn); + } while (rd.next_level); - device_for_each_child(parent, &cnts, mfd_remove_devices_fn); - kfree(cnts); + kfree(rd.cnts); } EXPORT_SYMBOL(mfd_remove_devices); diff --git a/include/linux/mfd/core.h b/include/linux/mfd/core.h index bdba8c6..40586a6 100644 --- a/include/linux/mfd/core.h +++ b/include/linux/mfd/core.h @@ -65,6 +65,9 @@ struct mfd_cell { */ const char **parent_supplies; int num_parent_supplies; + + /* Cells with a lower remove level will be destroyed first */ + int remove_level; }; /* -- 1.7.2.5 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@...r.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Powered by blists - more mailing lists