Support a way to define a revocable consumer handle on stack. Under some circumstances, the user wouldn't like to use dynamic memory allocation for consumer handles.
This makes the struct revocable no longer opaque. Signed-off-by: Tzung-Bi Shih <[email protected]> --- .../driver-api/driver-model/revocable.rst | 5 +- drivers/base/revocable.c | 60 +++++++++++++------ include/linux/revocable.h | 30 +++++++++- 3 files changed, 74 insertions(+), 21 deletions(-) diff --git a/Documentation/driver-api/driver-model/revocable.rst b/Documentation/driver-api/driver-model/revocable.rst index 22a442cc8d7f..fff081dbd296 100644 --- a/Documentation/driver-api/driver-model/revocable.rst +++ b/Documentation/driver-api/driver-model/revocable.rst @@ -84,7 +84,7 @@ For Resource Providers For Resource Consumers ---------------------- -.. kernel-doc:: drivers/base/revocable.c +.. kernel-doc:: include/linux/revocable.h :identifiers: revocable .. kernel-doc:: drivers/base/revocable.c @@ -93,6 +93,9 @@ For Resource Consumers .. kernel-doc:: drivers/base/revocable.c :identifiers: revocable_free +.. kernel-doc:: include/linux/revocable.h + :identifiers: DEFINE_REVOCABLE + .. kernel-doc:: drivers/base/revocable.c :identifiers: revocable_try_access diff --git a/drivers/base/revocable.c b/drivers/base/revocable.c index f6cece275aac..93c925252665 100644 --- a/drivers/base/revocable.c +++ b/drivers/base/revocable.c @@ -71,16 +71,6 @@ struct revocable_provider { struct kref kref; }; -/** - * struct revocable - A handle for resource consumer. - * @rp: The pointer of resource provider. - * @idx: The index for the RCU critical section. - */ -struct revocable { - struct revocable_provider *rp; - int idx; -}; - /** * revocable_provider_alloc() - Allocate struct revocable_provider. * @res: The pointer of resource. @@ -170,11 +160,47 @@ struct revocable_provider *devm_revocable_provider_alloc(struct device *dev, EXPORT_SYMBOL_GPL(devm_revocable_provider_alloc); /** - * revocable_alloc() - Allocate struct revocable. + * revocable_init() - Initialize struct revocable. + * @rev: The pointer of struct revocable. * @rp: The pointer of resource provider. * * This holds a refcount to the resource provider. * + * Don't call this function directly. Use revocable_alloc() or + * DEFINE_REVOCABLE(). + */ +void revocable_init(struct revocable *rev, struct revocable_provider *rp) +{ + rev->rp = rp; + kref_get(&rp->kref); +} +EXPORT_SYMBOL_GPL(revocable_init); + +/** + * revocable_deinit() - Deinitialize struct revocable. + * @rev: The pointer of struct revocable. + * + * This drops a refcount to the resource provider. If it is the final + * reference, revocable_provider_release() will be called to free the struct. + * + * Don't call this function directly. revocable_free() or DEFINE_REVOCABLE() + * should help to do so. + */ +void revocable_deinit(struct revocable *rev) +{ + struct revocable_provider *rp = rev->rp; + + kref_put(&rp->kref, revocable_provider_release); +} +EXPORT_SYMBOL_GPL(revocable_deinit); + +/** + * revocable_alloc() - Allocate struct revocable. + * @rp: The pointer of resource provider. + * + * Allocate a struct revocable and call revocable_init() to holds a refcount + * to the resource provider. + * * Return: The pointer of struct revocable. NULL on errors. */ struct revocable *revocable_alloc(struct revocable_provider *rp) @@ -185,9 +211,7 @@ struct revocable *revocable_alloc(struct revocable_provider *rp) if (!rev) return NULL; - rev->rp = rp; - kref_get(&rp->kref); - + revocable_init(rev, rp); return rev; } EXPORT_SYMBOL_GPL(revocable_alloc); @@ -196,14 +220,12 @@ EXPORT_SYMBOL_GPL(revocable_alloc); * revocable_free() - Free struct revocable. * @rev: The pointer of struct revocable. * - * This drops a refcount to the resource provider. If it is the final - * reference, revocable_provider_release() will be called to free the struct. + * Call revocable_deinit() to drop a refcount to the resource provider and + * free the struct revocable. */ void revocable_free(struct revocable *rev) { - struct revocable_provider *rp = rev->rp; - - kref_put(&rp->kref, revocable_provider_release); + revocable_deinit(rev); kfree(rev); } EXPORT_SYMBOL_GPL(revocable_free); diff --git a/include/linux/revocable.h b/include/linux/revocable.h index 659ba01c58db..89bb1a5c74e4 100644 --- a/include/linux/revocable.h +++ b/include/linux/revocable.h @@ -10,19 +10,47 @@ #include <linux/cleanup.h> struct device; -struct revocable; struct revocable_provider; +/** + * struct revocable - A handle for resource consumer. + * @rp: The pointer of resource provider. + * @idx: The index for the RCU critical section. + */ +struct revocable { + struct revocable_provider *rp; + int idx; +}; + struct revocable_provider *revocable_provider_alloc(void *res); void revocable_provider_revoke(struct revocable_provider *rp); struct revocable_provider *devm_revocable_provider_alloc(struct device *dev, void *res); +void revocable_init(struct revocable *rev, struct revocable_provider *rp); +void revocable_deinit(struct revocable *rev); struct revocable *revocable_alloc(struct revocable_provider *rp); void revocable_free(struct revocable *rev); void *revocable_try_access(struct revocable *rev) __acquires(&rev->rp->srcu); void revocable_withdraw_access(struct revocable *rev) __releases(&rev->rp->srcu); +DEFINE_FREE(define_rev, struct revocable *, revocable_deinit(_T)) + +#define _DEFINE_REVOCABLE(_rev, _name, _rp) \ + struct revocable _name; \ + struct revocable *_rev __free(define_rev) = &_name; \ + revocable_init(_rev, _rp) + +/** + * DEFINE_REVOCABLE() - A helper for defining a revocable consumer on stack + * @_rev: The variable name to ``struct revocable *``. + * @_rp: The provider's ``struct revocable_provider *`` handle. + * + * The macro declares and defines a revocable consumer handle on stack. + */ +#define DEFINE_REVOCABLE(_rev, _rp) \ + _DEFINE_REVOCABLE(_rev, __UNIQUE_ID(name), _rp) + DEFINE_FREE(access_rev, struct revocable *, if (_T) revocable_withdraw_access(_T)) /** -- 2.52.0.457.g6b5491de43-goog
