diff options
Diffstat (limited to 'drivers/fpga/fpga-region.c')
| -rw-r--r-- | drivers/fpga/fpga-region.c | 65 | 
1 files changed, 57 insertions, 8 deletions
| diff --git a/drivers/fpga/fpga-region.c b/drivers/fpga/fpga-region.c index 0d65220d5ec5..bde5a9d460c5 100644 --- a/drivers/fpga/fpga-region.c +++ b/drivers/fpga/fpga-region.c @@ -185,6 +185,10 @@ ATTRIBUTE_GROUPS(fpga_region);   * @mgr: manager that programs this region   * @get_bridges: optional function to get bridges to a list   * + * The caller of this function is responsible for freeing the resulting region + * struct with fpga_region_free().  Using devm_fpga_region_create() instead is + * recommended. + *   * Return: struct fpga_region or NULL   */  struct fpga_region @@ -230,8 +234,8 @@ err_free:  EXPORT_SYMBOL_GPL(fpga_region_create);  /** - * fpga_region_free - free a struct fpga_region - * @region: FPGA region created by fpga_region_create + * fpga_region_free - free a FPGA region created by fpga_region_create() + * @region: FPGA region   */  void fpga_region_free(struct fpga_region *region)  { @@ -240,21 +244,69 @@ void fpga_region_free(struct fpga_region *region)  }  EXPORT_SYMBOL_GPL(fpga_region_free); +static void devm_fpga_region_release(struct device *dev, void *res) +{ +	struct fpga_region *region = *(struct fpga_region **)res; + +	fpga_region_free(region); +} + +/** + * devm_fpga_region_create - create and initialize a managed FPGA region struct + * @dev: device parent + * @mgr: manager that programs this region + * @get_bridges: optional function to get bridges to a list + * + * This function is intended for use in a FPGA region driver's probe function. + * After the region driver creates the region struct with + * devm_fpga_region_create(), it should register it with fpga_region_register(). + * The region driver's remove function should call fpga_region_unregister(). + * The region 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_region_register(), the struct will still get cleaned up. + * + * Return: struct fpga_region or NULL + */ +struct fpga_region +*devm_fpga_region_create(struct device *dev, +			 struct fpga_manager *mgr, +			 int (*get_bridges)(struct fpga_region *)) +{ +	struct fpga_region **ptr, *region; + +	ptr = devres_alloc(devm_fpga_region_release, sizeof(*ptr), GFP_KERNEL); +	if (!ptr) +		return NULL; + +	region = fpga_region_create(dev, mgr, get_bridges); +	if (!region) { +		devres_free(ptr); +	} else { +		*ptr = region; +		devres_add(dev, ptr); +	} + +	return region; +} +EXPORT_SYMBOL_GPL(devm_fpga_region_create); +  /**   * fpga_region_register - register a FPGA region - * @region: FPGA region created by fpga_region_create + * @region: FPGA region + *   * Return: 0 or -errno   */  int fpga_region_register(struct fpga_region *region)  {  	return device_add(®ion->dev); -  }  EXPORT_SYMBOL_GPL(fpga_region_register);  /** - * fpga_region_unregister - unregister and free a FPGA region + * fpga_region_unregister - unregister a FPGA region   * @region: FPGA region + * + * This function is intended for use in a FPGA region driver's remove function.   */  void fpga_region_unregister(struct fpga_region *region)  { @@ -264,9 +316,6 @@ EXPORT_SYMBOL_GPL(fpga_region_unregister);  static void fpga_region_dev_release(struct device *dev)  { -	struct fpga_region *region = to_fpga_region(dev); - -	fpga_region_free(region);  }  /** | 
