Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

fpga: add devm_fpga_region_create

Add devm_fpga_region_create() which is the
managed version of fpga_region_create().

Change current region drivers to use
devm_fpga_region_create().

Signed-off-by: Alan Tull <atull@kernel.org>
Suggested-by: Federico Vaga <federico.vaga@cern.ch>
Acked-by: Moritz Fischer <mdf@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Alan Tull and committed by
Greg Kroah-Hartman
fea82b7f 213befe0

+70 -20
+3
Documentation/driver-api/fpga/fpga-region.rst
··· 90 90 :functions: fpga_region 91 91 92 92 .. kernel-doc:: drivers/fpga/fpga-region.c 93 + :functions: devm_fpga_region_create 94 + 95 + .. kernel-doc:: drivers/fpga/fpga-region.c 93 96 :functions: fpga_region_create 94 97 95 98 .. kernel-doc:: drivers/fpga/fpga-region.c
+2 -4
drivers/fpga/dfl-fme-region.c
··· 39 39 if (IS_ERR(mgr)) 40 40 return -EPROBE_DEFER; 41 41 42 - region = fpga_region_create(dev, mgr, fme_region_get_bridges); 42 + region = devm_fpga_region_create(dev, mgr, fme_region_get_bridges); 43 43 if (!region) { 44 44 ret = -ENOMEM; 45 45 goto eprobe_mgr_put; ··· 51 51 52 52 ret = fpga_region_register(region); 53 53 if (ret) 54 - goto region_free; 54 + goto eprobe_mgr_put; 55 55 56 56 dev_dbg(dev, "DFL FME FPGA Region probed\n"); 57 57 58 58 return 0; 59 59 60 - region_free: 61 - fpga_region_free(region); 62 60 eprobe_mgr_put: 63 61 fpga_mgr_put(mgr); 64 62 return ret;
+2 -4
drivers/fpga/dfl.c
··· 899 899 if (!cdev) 900 900 return ERR_PTR(-ENOMEM); 901 901 902 - cdev->region = fpga_region_create(info->dev, NULL, NULL); 902 + cdev->region = devm_fpga_region_create(info->dev, NULL, NULL); 903 903 if (!cdev->region) { 904 904 ret = -ENOMEM; 905 905 goto free_cdev_exit; ··· 911 911 912 912 ret = fpga_region_register(cdev->region); 913 913 if (ret) 914 - goto free_region_exit; 914 + goto free_cdev_exit; 915 915 916 916 /* create and init build info for enumeration */ 917 917 binfo = devm_kzalloc(info->dev, sizeof(*binfo), GFP_KERNEL); ··· 942 942 943 943 unregister_region_exit: 944 944 fpga_region_unregister(cdev->region); 945 - free_region_exit: 946 - fpga_region_free(cdev->region); 947 945 free_cdev_exit: 948 946 devm_kfree(info->dev, cdev); 949 947 return ERR_PTR(ret);
+57 -8
drivers/fpga/fpga-region.c
··· 185 185 * @mgr: manager that programs this region 186 186 * @get_bridges: optional function to get bridges to a list 187 187 * 188 + * The caller of this function is responsible for freeing the resulting region 189 + * struct with fpga_region_free(). Using devm_fpga_region_create() instead is 190 + * recommended. 191 + * 188 192 * Return: struct fpga_region or NULL 189 193 */ 190 194 struct fpga_region ··· 234 230 EXPORT_SYMBOL_GPL(fpga_region_create); 235 231 236 232 /** 237 - * fpga_region_free - free a struct fpga_region 238 - * @region: FPGA region created by fpga_region_create 233 + * fpga_region_free - free a FPGA region created by fpga_region_create() 234 + * @region: FPGA region 239 235 */ 240 236 void fpga_region_free(struct fpga_region *region) 241 237 { ··· 244 240 } 245 241 EXPORT_SYMBOL_GPL(fpga_region_free); 246 242 243 + static void devm_fpga_region_release(struct device *dev, void *res) 244 + { 245 + struct fpga_region *region = *(struct fpga_region **)res; 246 + 247 + fpga_region_free(region); 248 + } 249 + 250 + /** 251 + * devm_fpga_region_create - create and initialize a managed FPGA region struct 252 + * @dev: device parent 253 + * @mgr: manager that programs this region 254 + * @get_bridges: optional function to get bridges to a list 255 + * 256 + * This function is intended for use in a FPGA region driver's probe function. 257 + * After the region driver creates the region struct with 258 + * devm_fpga_region_create(), it should register it with fpga_region_register(). 259 + * The region driver's remove function should call fpga_region_unregister(). 260 + * The region struct allocated with this function will be freed automatically on 261 + * driver detach. This includes the case of a probe function returning error 262 + * before calling fpga_region_register(), the struct will still get cleaned up. 263 + * 264 + * Return: struct fpga_region or NULL 265 + */ 266 + struct fpga_region 267 + *devm_fpga_region_create(struct device *dev, 268 + struct fpga_manager *mgr, 269 + int (*get_bridges)(struct fpga_region *)) 270 + { 271 + struct fpga_region **ptr, *region; 272 + 273 + ptr = devres_alloc(devm_fpga_region_release, sizeof(*ptr), GFP_KERNEL); 274 + if (!ptr) 275 + return NULL; 276 + 277 + region = fpga_region_create(dev, mgr, get_bridges); 278 + if (!region) { 279 + devres_free(ptr); 280 + } else { 281 + *ptr = region; 282 + devres_add(dev, ptr); 283 + } 284 + 285 + return region; 286 + } 287 + EXPORT_SYMBOL_GPL(devm_fpga_region_create); 288 + 247 289 /** 248 290 * fpga_region_register - register a FPGA region 249 - * @region: FPGA region created by fpga_region_create 291 + * @region: FPGA region 292 + * 250 293 * Return: 0 or -errno 251 294 */ 252 295 int fpga_region_register(struct fpga_region *region) 253 296 { 254 297 return device_add(&region->dev); 255 - 256 298 } 257 299 EXPORT_SYMBOL_GPL(fpga_region_register); 258 300 259 301 /** 260 - * fpga_region_unregister - unregister and free a FPGA region 302 + * fpga_region_unregister - unregister a FPGA region 261 303 * @region: FPGA region 304 + * 305 + * This function is intended for use in a FPGA region driver's remove function. 262 306 */ 263 307 void fpga_region_unregister(struct fpga_region *region) 264 308 { ··· 316 264 317 265 static void fpga_region_dev_release(struct device *dev) 318 266 { 319 - struct fpga_region *region = to_fpga_region(dev); 320 - 321 - fpga_region_free(region); 322 267 } 323 268 324 269 /**
+2 -4
drivers/fpga/of-fpga-region.c
··· 410 410 if (IS_ERR(mgr)) 411 411 return -EPROBE_DEFER; 412 412 413 - region = fpga_region_create(dev, mgr, of_fpga_region_get_bridges); 413 + region = devm_fpga_region_create(dev, mgr, of_fpga_region_get_bridges); 414 414 if (!region) { 415 415 ret = -ENOMEM; 416 416 goto eprobe_mgr_put; ··· 418 418 419 419 ret = fpga_region_register(region); 420 420 if (ret) 421 - goto eprobe_free; 421 + goto eprobe_mgr_put; 422 422 423 423 of_platform_populate(np, fpga_region_of_match, NULL, &region->dev); 424 424 dev_set_drvdata(dev, region); ··· 427 427 428 428 return 0; 429 429 430 - eprobe_free: 431 - fpga_region_free(region); 432 430 eprobe_mgr_put: 433 431 fpga_mgr_put(mgr); 434 432 return ret;
+4
include/linux/fpga/fpga-region.h
··· 44 44 int fpga_region_register(struct fpga_region *region); 45 45 void fpga_region_unregister(struct fpga_region *region); 46 46 47 + struct fpga_region 48 + *devm_fpga_region_create(struct device *dev, struct fpga_manager *mgr, 49 + int (*get_bridges)(struct fpga_region *)); 50 + 47 51 #endif /* _FPGA_REGION_H */