diff options
| author | James Morris <james.morris@microsoft.com> | 2018-11-12 09:07:41 -0800 | 
|---|---|---|
| committer | James Morris <james.morris@microsoft.com> | 2018-11-12 09:07:41 -0800 | 
| commit | 26b76320a8a550472bbb8f42257df83fcb8d8df6 (patch) | |
| tree | 8a5b569f4f070bf4971e24e7fccfe3004b8fc4ba /drivers/fpga/fpga-region.c | |
| parent | f09c296ebf407f98f4ca70892e612b54484bf663 (diff) | |
| parent | ccda4af0f4b92f7b4c308d3acc262f4a7e3affad (diff) | |
Merge tag 'v4.20-rc2' into next-general
Sync to Linux 4.20-rc2 for downstream developers.
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);  }  /** | 
