drivers/base/devres: introduce devm_release_action()
Patch series "mm/devm_memremap_pages: Fix page release race", v2. Logan audited the devm_memremap_pages() shutdown path and noticed that it was possible to proceed to arch_remove_memory() before all potential page references have been reaped. Introduce a new ->cleanup() callback to do the work of waiting for any straggling page references and then perform the percpu_ref_exit() in devm_memremap_pages_release() context. For p2pdma this involves some deeper reworks to reference count resources on a per-instance basis rather than a per pci-device basis. A modified genalloc api is introduced to convey a driver-private pointer through gen_pool_{alloc,free}() interfaces. Also, a devm_memunmap_pages() api is introduced since p2pdma does not auto-release resources on a setup failure. The dax and pmem changes pass the nvdimm unit tests, and the p2pdma changes should now pass testing with the pci_p2pdma_release() fix. Jrme, how does this look for HMM? This patch (of 6): The devm_add_action() facility allows a resource allocation routine to add custom devm semantics. One such user is devm_memremap_pages(). There is now a need to manually trigger devm_memremap_pages_release(). Introduce devm_release_action() so the release action can be triggered via a new devm_memunmap_pages() api in a follow-on change. Link: http://lkml.kernel.org/r/155727336530.292046.2926860263201336366.stgit@dwillia2-desk3.amr.corp.intel.com Signed-off-by: Dan Williams <dan.j.williams@intel.com> Reviewed-by: Ira Weiny <ira.weiny@intel.com> Reviewed-by: Logan Gunthorpe <logang@deltatee.com> Cc: Bjorn Helgaas <bhelgaas@google.com> Cc: Christoph Hellwig <hch@lst.de> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Cc: "Rafael J. Wysocki" <rafael@kernel.org> Cc: "Jérôme Glisse" <jglisse@redhat.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
parent
a58f2cef26
commit
2374b68225
|
@ -755,10 +755,32 @@ void devm_remove_action(struct device *dev, void (*action)(void *), void *data)
|
||||||
|
|
||||||
WARN_ON(devres_destroy(dev, devm_action_release, devm_action_match,
|
WARN_ON(devres_destroy(dev, devm_action_release, devm_action_match,
|
||||||
&devres));
|
&devres));
|
||||||
|
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(devm_remove_action);
|
EXPORT_SYMBOL_GPL(devm_remove_action);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* devm_release_action() - release previously added custom action
|
||||||
|
* @dev: Device that owns the action
|
||||||
|
* @action: Function implementing the action
|
||||||
|
* @data: Pointer to data passed to @action implementation
|
||||||
|
*
|
||||||
|
* Releases and removes instance of @action previously added by
|
||||||
|
* devm_add_action(). Both action and data should match one of the
|
||||||
|
* existing entries.
|
||||||
|
*/
|
||||||
|
void devm_release_action(struct device *dev, void (*action)(void *), void *data)
|
||||||
|
{
|
||||||
|
struct action_devres devres = {
|
||||||
|
.data = data,
|
||||||
|
.action = action,
|
||||||
|
};
|
||||||
|
|
||||||
|
WARN_ON(devres_release(dev, devm_action_release, devm_action_match,
|
||||||
|
&devres));
|
||||||
|
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(devm_release_action);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Managed kmalloc/kfree
|
* Managed kmalloc/kfree
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -713,6 +713,7 @@ void __iomem *devm_of_iomap(struct device *dev,
|
||||||
/* allows to add/remove a custom action to devres stack */
|
/* allows to add/remove a custom action to devres stack */
|
||||||
int devm_add_action(struct device *dev, void (*action)(void *), void *data);
|
int devm_add_action(struct device *dev, void (*action)(void *), void *data);
|
||||||
void devm_remove_action(struct device *dev, void (*action)(void *), void *data);
|
void devm_remove_action(struct device *dev, void (*action)(void *), void *data);
|
||||||
|
void devm_release_action(struct device *dev, void (*action)(void *), void *data);
|
||||||
|
|
||||||
static inline int devm_add_action_or_reset(struct device *dev,
|
static inline int devm_add_action_or_reset(struct device *dev,
|
||||||
void (*action)(void *), void *data)
|
void (*action)(void *), void *data)
|
||||||
|
|
Loading…
Reference in a new issue