diff options
author | Moritz Fischer <mdf@kernel.org> | 2020-11-15 11:51:18 -0800 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2020-12-01 18:49:32 +0100 |
commit | 57d9352b6c651b090179f8b223b6681275c64a4f (patch) | |
tree | 41fdd92dba396c0b718c4b849eb1d8bc28f06395 /drivers/fpga | |
parent | cd5f82dbbad04418afca092e8c7c6250e6815554 (diff) |
fpga: fpga-mgr: Add devm_fpga_mgr_register() API
Add a devm_fpga_mgr_register() API that can be used to register a FPGA
Manager that was created using devm_fpga_mgr_create().
Introduce a struct fpga_mgr_devres that makes the devres
allocation a little bit more readable and gets reused for
devm_fpga_mgr_create() devm_fpga_mgr_register().
Reviewed-by: Tom Rix <trix@redhat.com>
Signed-off-by: Moritz Fischer <mdf@kernel.org>
Link: https://lore.kernel.org/r/20201115195127.284487-2-mdf@kernel.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/fpga')
-rw-r--r-- | drivers/fpga/fpga-mgr.c | 81 |
1 files changed, 69 insertions, 12 deletions
diff --git a/drivers/fpga/fpga-mgr.c b/drivers/fpga/fpga-mgr.c index f38bab01432e..b85bc47c91a9 100644 --- a/drivers/fpga/fpga-mgr.c +++ b/drivers/fpga/fpga-mgr.c @@ -21,6 +21,10 @@ static DEFINE_IDA(fpga_mgr_ida); static struct class *fpga_mgr_class; +struct fpga_mgr_devres { + struct fpga_manager *mgr; +}; + /** * fpga_image_info_alloc - Allocate a FPGA image info struct * @dev: owning device @@ -625,9 +629,9 @@ EXPORT_SYMBOL_GPL(fpga_mgr_free); static void devm_fpga_mgr_release(struct device *dev, void *res) { - struct fpga_manager *mgr = *(struct fpga_manager **)res; + struct fpga_mgr_devres *dr = res; - fpga_mgr_free(mgr); + fpga_mgr_free(dr->mgr); } /** @@ -651,21 +655,21 @@ struct fpga_manager *devm_fpga_mgr_create(struct device *dev, const char *name, const struct fpga_manager_ops *mops, void *priv) { - struct fpga_manager **ptr, *mgr; + struct fpga_mgr_devres *dr; - ptr = devres_alloc(devm_fpga_mgr_release, sizeof(*ptr), GFP_KERNEL); - if (!ptr) + dr = devres_alloc(devm_fpga_mgr_release, sizeof(*dr), GFP_KERNEL); + if (!dr) return NULL; - mgr = fpga_mgr_create(dev, name, mops, priv); - if (!mgr) { - devres_free(ptr); - } else { - *ptr = mgr; - devres_add(dev, ptr); + dr->mgr = fpga_mgr_create(dev, name, mops, priv); + if (!dr->mgr) { + devres_free(dr); + return NULL; } - return mgr; + devres_add(dev, dr); + + return dr->mgr; } EXPORT_SYMBOL_GPL(devm_fpga_mgr_create); @@ -722,6 +726,59 @@ void fpga_mgr_unregister(struct fpga_manager *mgr) } EXPORT_SYMBOL_GPL(fpga_mgr_unregister); +static int fpga_mgr_devres_match(struct device *dev, void *res, + void *match_data) +{ + struct fpga_mgr_devres *dr = res; + + return match_data == dr->mgr; +} + +static void devm_fpga_mgr_unregister(struct device *dev, void *res) +{ + struct fpga_mgr_devres *dr = res; + + fpga_mgr_unregister(dr->mgr); +} + +/** + * devm_fpga_mgr_register - resource managed variant of fpga_mgr_register() + * @dev: managing device for this FPGA manager + * @mgr: fpga manager struct + * + * This is the devres variant of fpga_mgr_register() for which the unregister + * function will be called automatically when the managing device is detached. + */ +int devm_fpga_mgr_register(struct device *dev, struct fpga_manager *mgr) +{ + struct fpga_mgr_devres *dr; + int ret; + + /* + * Make sure that the struct fpga_manager * that is passed in is + * managed itself. + */ + if (WARN_ON(!devres_find(dev, devm_fpga_mgr_release, + fpga_mgr_devres_match, mgr))) + return -EINVAL; + + dr = devres_alloc(devm_fpga_mgr_unregister, sizeof(*dr), GFP_KERNEL); + if (!dr) + return -ENOMEM; + + ret = fpga_mgr_register(mgr); + if (ret) { + devres_free(dr); + return ret; + } + + dr->mgr = mgr; + devres_add(dev, dr); + + return 0; +} +EXPORT_SYMBOL_GPL(devm_fpga_mgr_register); + static void fpga_mgr_dev_release(struct device *dev) { } |