diff options
Diffstat (limited to 'drivers/fpga/fpga-mgr.c')
| -rw-r--r-- | drivers/fpga/fpga-mgr.c | 64 | 
1 files changed, 56 insertions, 8 deletions
| diff --git a/drivers/fpga/fpga-mgr.c b/drivers/fpga/fpga-mgr.c index a41b07e37884..c3866816456a 100644 --- a/drivers/fpga/fpga-mgr.c +++ b/drivers/fpga/fpga-mgr.c @@ -558,6 +558,9 @@ EXPORT_SYMBOL_GPL(fpga_mgr_unlock);   * @mops:	pointer to structure of fpga manager ops   * @priv:	fpga manager private data   * + * The caller of this function is responsible for freeing the struct with + * fpga_mgr_free().  Using devm_fpga_mgr_create() instead is recommended. + *   * Return: pointer to struct fpga_manager or NULL   */  struct fpga_manager *fpga_mgr_create(struct device *dev, const char *name, @@ -618,8 +621,8 @@ error_kfree:  EXPORT_SYMBOL_GPL(fpga_mgr_create);  /** - * fpga_mgr_free - deallocate a FPGA manager - * @mgr:	fpga manager struct created by fpga_mgr_create + * fpga_mgr_free - free a FPGA manager created with fpga_mgr_create() + * @mgr:	fpga manager struct   */  void fpga_mgr_free(struct fpga_manager *mgr)  { @@ -628,9 +631,55 @@ void fpga_mgr_free(struct fpga_manager *mgr)  }  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; + +	fpga_mgr_free(mgr); +} + +/** + * devm_fpga_mgr_create - create and initialize a managed FPGA manager struct + * @dev:	fpga manager device from pdev + * @name:	fpga manager name + * @mops:	pointer to structure of fpga manager ops + * @priv:	fpga manager private data + * + * This function is intended for use in a FPGA manager driver's probe function. + * After the manager driver creates the manager struct with + * devm_fpga_mgr_create(), it should register it with fpga_mgr_register().  The + * manager driver's remove function should call fpga_mgr_unregister().  The + * manager struct allocated with this function will be freed automatically on + * driver detach.  This includes the case of a probe function returning error + * before calling fpga_mgr_register(), the struct will still get cleaned up. + * + * Return: pointer to struct fpga_manager or NULL + */ +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; + +	ptr = devres_alloc(devm_fpga_mgr_release, sizeof(*ptr), GFP_KERNEL); +	if (!ptr) +		return NULL; + +	mgr = fpga_mgr_create(dev, name, mops, priv); +	if (!mgr) { +		devres_free(ptr); +	} else { +		*ptr = mgr; +		devres_add(dev, ptr); +	} + +	return mgr; +} +EXPORT_SYMBOL_GPL(devm_fpga_mgr_create); +  /**   * fpga_mgr_register - register a FPGA manager - * @mgr:	fpga manager struct created by fpga_mgr_create + * @mgr: fpga manager struct   *   * Return: 0 on success, negative error code otherwise.   */ @@ -661,8 +710,10 @@ error_device:  EXPORT_SYMBOL_GPL(fpga_mgr_register);  /** - * fpga_mgr_unregister - unregister and free a FPGA manager - * @mgr:	fpga manager struct + * fpga_mgr_unregister - unregister a FPGA manager + * @mgr: fpga manager struct + * + * This function is intended for use in a FPGA manager driver's remove function.   */  void fpga_mgr_unregister(struct fpga_manager *mgr)  { @@ -681,9 +732,6 @@ EXPORT_SYMBOL_GPL(fpga_mgr_unregister);  static void fpga_mgr_dev_release(struct device *dev)  { -	struct fpga_manager *mgr = to_fpga_manager(dev); - -	fpga_mgr_free(mgr);  }  static int __init fpga_mgr_class_init(void) | 
