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

fpga: region: Use standard dev_release for class driver

The FPGA region class driver data structure is being treated as a
managed resource instead of using the standard dev_release call-back
function to release the class data structure. This change removes the
managed resource code and combines the create() and register()
functions into a single register() or register_full() function.

The register_full() function accepts an info data structure to provide
flexibility in passing optional parameters. The register() function
supports the current parameter list for users that don't require the
use of optional parameters.

Signed-off-by: Russ Weight <russell.h.weight@intel.com>
Reviewed-by: Xu Yilun <yilun.xu@intel.com>
Acked-by: Xu Yilun <yilun.xu@intel.com>
Signed-off-by: Moritz Fischer <mdf@kernel.org>

authored by

Russ Weight and committed by
Moritz Fischer
8886a579 0d70af3c

+95 -111
+9 -3
Documentation/driver-api/fpga/fpga-region.rst
··· 46 46 ---------------------------- 47 47 48 48 * struct fpga_region - The FPGA region struct 49 - * devm_fpga_region_create() - Allocate and init a region struct 50 - * fpga_region_register() - Register an FPGA region 49 + * struct fpga_region_info - Parameter structure for fpga_region_register_full() 50 + * fpga_region_register_full() - Create and register an FPGA region using the 51 + fpga_region_info structure to provide the full flexibility of options 52 + * fpga_region_register() - Create and register an FPGA region using standard 53 + arguments 51 54 * fpga_region_unregister() - Unregister an FPGA region 52 55 53 56 The FPGA region's probe function will need to get a reference to the FPGA ··· 78 75 .. kernel-doc:: include/linux/fpga/fpga-region.h 79 76 :functions: fpga_region 80 77 78 + .. kernel-doc:: include/linux/fpga/fpga-region.h 79 + :functions: fpga_region_info 80 + 81 81 .. kernel-doc:: drivers/fpga/fpga-region.c 82 - :functions: devm_fpga_region_create 82 + :functions: fpga_region_register_full 83 83 84 84 .. kernel-doc:: drivers/fpga/fpga-region.c 85 85 :functions: fpga_region_register
+8 -9
drivers/fpga/dfl-fme-region.c
··· 30 30 static int fme_region_probe(struct platform_device *pdev) 31 31 { 32 32 struct dfl_fme_region_pdata *pdata = dev_get_platdata(&pdev->dev); 33 + struct fpga_region_info info = { 0 }; 33 34 struct device *dev = &pdev->dev; 34 35 struct fpga_region *region; 35 36 struct fpga_manager *mgr; ··· 40 39 if (IS_ERR(mgr)) 41 40 return -EPROBE_DEFER; 42 41 43 - region = devm_fpga_region_create(dev, mgr, fme_region_get_bridges); 44 - if (!region) { 45 - ret = -ENOMEM; 42 + info.mgr = mgr; 43 + info.compat_id = mgr->compat_id; 44 + info.get_bridges = fme_region_get_bridges; 45 + info.priv = pdata; 46 + region = fpga_region_register_full(dev, &info); 47 + if (IS_ERR(region)) { 48 + ret = PTR_ERR(region); 46 49 goto eprobe_mgr_put; 47 50 } 48 51 49 - region->priv = pdata; 50 - region->compat_id = mgr->compat_id; 51 52 platform_set_drvdata(pdev, region); 52 - 53 - ret = fpga_region_register(region); 54 - if (ret) 55 - goto eprobe_mgr_put; 56 53 57 54 dev_dbg(dev, "DFL FME FPGA Region probed\n"); 58 55
+4 -8
drivers/fpga/dfl.c
··· 1407 1407 if (!cdev) 1408 1408 return ERR_PTR(-ENOMEM); 1409 1409 1410 - cdev->region = devm_fpga_region_create(info->dev, NULL, NULL); 1411 - if (!cdev->region) { 1412 - ret = -ENOMEM; 1413 - goto free_cdev_exit; 1414 - } 1415 - 1416 1410 cdev->parent = info->dev; 1417 1411 mutex_init(&cdev->lock); 1418 1412 INIT_LIST_HEAD(&cdev->port_dev_list); 1419 1413 1420 - ret = fpga_region_register(cdev->region); 1421 - if (ret) 1414 + cdev->region = fpga_region_register(info->dev, NULL, NULL); 1415 + if (IS_ERR(cdev->region)) { 1416 + ret = PTR_ERR(cdev->region); 1422 1417 goto free_cdev_exit; 1418 + } 1423 1419 1424 1420 /* create and init build info for enumeration */ 1425 1421 binfo = devm_kzalloc(info->dev, sizeof(*binfo), GFP_KERNEL);
+44 -75
drivers/fpga/fpga-region.c
··· 180 180 ATTRIBUTE_GROUPS(fpga_region); 181 181 182 182 /** 183 - * fpga_region_create - alloc and init a struct fpga_region 183 + * fpga_region_register_full - create and register an FPGA Region device 184 184 * @parent: device parent 185 - * @mgr: manager that programs this region 186 - * @get_bridges: optional function to get bridges to a list 185 + * @info: parameters for FPGA Region 187 186 * 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 - * 192 - * Return: struct fpga_region or NULL 187 + * Return: struct fpga_region or ERR_PTR() 193 188 */ 194 - struct fpga_region 195 - *fpga_region_create(struct device *parent, 196 - struct fpga_manager *mgr, 197 - int (*get_bridges)(struct fpga_region *)) 189 + struct fpga_region * 190 + fpga_region_register_full(struct device *parent, const struct fpga_region_info *info) 198 191 { 199 192 struct fpga_region *region; 200 193 int id, ret = 0; 201 194 195 + if (!info) { 196 + dev_err(parent, 197 + "Attempt to register without required info structure\n"); 198 + return ERR_PTR(-EINVAL); 199 + } 200 + 202 201 region = kzalloc(sizeof(*region), GFP_KERNEL); 203 202 if (!region) 204 - return NULL; 203 + return ERR_PTR(-ENOMEM); 205 204 206 205 id = ida_simple_get(&fpga_region_ida, 0, 0, GFP_KERNEL); 207 - if (id < 0) 206 + if (id < 0) { 207 + ret = id; 208 208 goto err_free; 209 + } 209 210 210 - region->mgr = mgr; 211 - region->get_bridges = get_bridges; 211 + region->mgr = info->mgr; 212 + region->compat_id = info->compat_id; 213 + region->priv = info->priv; 214 + region->get_bridges = info->get_bridges; 215 + 212 216 mutex_init(&region->mutex); 213 217 INIT_LIST_HEAD(&region->bridge_list); 214 218 215 - device_initialize(&region->dev); 216 219 region->dev.class = fpga_region_class; 217 220 region->dev.parent = parent; 218 221 region->dev.of_node = parent->of_node; ··· 225 222 if (ret) 226 223 goto err_remove; 227 224 225 + ret = device_register(&region->dev); 226 + if (ret) { 227 + put_device(&region->dev); 228 + return ERR_PTR(ret); 229 + } 230 + 228 231 return region; 229 232 230 233 err_remove: ··· 238 229 err_free: 239 230 kfree(region); 240 231 241 - return NULL; 232 + return ERR_PTR(ret); 242 233 } 243 - EXPORT_SYMBOL_GPL(fpga_region_create); 234 + EXPORT_SYMBOL_GPL(fpga_region_register_full); 244 235 245 236 /** 246 - * fpga_region_free - free an FPGA region created by fpga_region_create() 247 - * @region: FPGA region 248 - */ 249 - void fpga_region_free(struct fpga_region *region) 250 - { 251 - ida_simple_remove(&fpga_region_ida, region->dev.id); 252 - kfree(region); 253 - } 254 - EXPORT_SYMBOL_GPL(fpga_region_free); 255 - 256 - static void devm_fpga_region_release(struct device *dev, void *res) 257 - { 258 - struct fpga_region *region = *(struct fpga_region **)res; 259 - 260 - fpga_region_free(region); 261 - } 262 - 263 - /** 264 - * devm_fpga_region_create - create and initialize a managed FPGA region struct 237 + * fpga_region_register - create and register an FPGA Region device 265 238 * @parent: device parent 266 239 * @mgr: manager that programs this region 267 240 * @get_bridges: optional function to get bridges to a list 268 241 * 269 - * This function is intended for use in an FPGA region driver's probe function. 270 - * After the region driver creates the region struct with 271 - * devm_fpga_region_create(), it should register it with fpga_region_register(). 272 - * The region driver's remove function should call fpga_region_unregister(). 273 - * The region struct allocated with this function will be freed automatically on 274 - * driver detach. This includes the case of a probe function returning error 275 - * before calling fpga_region_register(), the struct will still get cleaned up. 242 + * This simple version of the register function should be sufficient for most users. 243 + * The fpga_region_register_full() function is available for users that need to 244 + * pass additional, optional parameters. 276 245 * 277 - * Return: struct fpga_region or NULL 246 + * Return: struct fpga_region or ERR_PTR() 278 247 */ 279 - struct fpga_region 280 - *devm_fpga_region_create(struct device *parent, 281 - struct fpga_manager *mgr, 282 - int (*get_bridges)(struct fpga_region *)) 248 + struct fpga_region * 249 + fpga_region_register(struct device *parent, struct fpga_manager *mgr, 250 + int (*get_bridges)(struct fpga_region *)) 283 251 { 284 - struct fpga_region **ptr, *region; 252 + struct fpga_region_info info = { 0 }; 285 253 286 - ptr = devres_alloc(devm_fpga_region_release, sizeof(*ptr), GFP_KERNEL); 287 - if (!ptr) 288 - return NULL; 254 + info.mgr = mgr; 255 + info.get_bridges = get_bridges; 289 256 290 - region = fpga_region_create(parent, mgr, get_bridges); 291 - if (!region) { 292 - devres_free(ptr); 293 - } else { 294 - *ptr = region; 295 - devres_add(parent, ptr); 296 - } 297 - 298 - return region; 299 - } 300 - EXPORT_SYMBOL_GPL(devm_fpga_region_create); 301 - 302 - /** 303 - * fpga_region_register - register an FPGA region 304 - * @region: FPGA region 305 - * 306 - * Return: 0 or -errno 307 - */ 308 - int fpga_region_register(struct fpga_region *region) 309 - { 310 - return device_add(&region->dev); 257 + return fpga_region_register_full(parent, &info); 311 258 } 312 259 EXPORT_SYMBOL_GPL(fpga_region_register); 313 260 ··· 281 316 282 317 static void fpga_region_dev_release(struct device *dev) 283 318 { 319 + struct fpga_region *region = to_fpga_region(dev); 320 + 321 + ida_simple_remove(&fpga_region_ida, region->dev.id); 322 + kfree(region); 284 323 } 285 324 286 325 /**
+3 -7
drivers/fpga/of-fpga-region.c
··· 405 405 if (IS_ERR(mgr)) 406 406 return -EPROBE_DEFER; 407 407 408 - region = devm_fpga_region_create(dev, mgr, of_fpga_region_get_bridges); 409 - if (!region) { 410 - ret = -ENOMEM; 408 + region = fpga_region_register(dev, mgr, of_fpga_region_get_bridges); 409 + if (IS_ERR(region)) { 410 + ret = PTR_ERR(region); 411 411 goto eprobe_mgr_put; 412 412 } 413 - 414 - ret = fpga_region_register(region); 415 - if (ret) 416 - goto eprobe_mgr_put; 417 413 418 414 of_platform_populate(np, fpga_region_of_match, NULL, &region->dev); 419 415 platform_set_drvdata(pdev, region);
+27 -9
include/linux/fpga/fpga-region.h
··· 7 7 #include <linux/fpga/fpga-mgr.h> 8 8 #include <linux/fpga/fpga-bridge.h> 9 9 10 + struct fpga_region; 11 + 12 + /** 13 + * struct fpga_region_info - collection of parameters an FPGA Region 14 + * @mgr: fpga region manager 15 + * @compat_id: FPGA region id for compatibility check. 16 + * @priv: fpga region private data 17 + * @get_bridges: optional function to get bridges to a list 18 + * 19 + * fpga_region_info contains parameters for the register_full function. 20 + * These are separated into an info structure because they some are optional 21 + * others could be added to in the future. The info structure facilitates 22 + * maintaining a stable API. 23 + */ 24 + struct fpga_region_info { 25 + struct fpga_manager *mgr; 26 + struct fpga_compat_id *compat_id; 27 + void *priv; 28 + int (*get_bridges)(struct fpga_region *region); 29 + }; 30 + 10 31 /** 11 32 * struct fpga_region - FPGA Region structure 12 33 * @dev: FPGA Region device ··· 58 37 59 38 int fpga_region_program_fpga(struct fpga_region *region); 60 39 61 - struct fpga_region 62 - *fpga_region_create(struct device *dev, struct fpga_manager *mgr, 63 - int (*get_bridges)(struct fpga_region *)); 64 - void fpga_region_free(struct fpga_region *region); 65 - int fpga_region_register(struct fpga_region *region); 66 - void fpga_region_unregister(struct fpga_region *region); 40 + struct fpga_region * 41 + fpga_region_register_full(struct device *parent, const struct fpga_region_info *info); 67 42 68 - struct fpga_region 69 - *devm_fpga_region_create(struct device *dev, struct fpga_manager *mgr, 70 - int (*get_bridges)(struct fpga_region *)); 43 + struct fpga_region * 44 + fpga_region_register(struct device *parent, struct fpga_manager *mgr, 45 + int (*get_bridges)(struct fpga_region *)); 46 + void fpga_region_unregister(struct fpga_region *region); 71 47 72 48 #endif /* _FPGA_REGION_H */