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); | |||
| 185 | * @mgr: manager that programs this region | 185 | * @mgr: manager that programs this region |
| 186 | * @get_bridges: optional function to get bridges to a list | 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 | * Return: struct fpga_region or NULL | 192 | * Return: struct fpga_region or NULL |
| 189 | */ | 193 | */ |
| 190 | struct fpga_region | 194 | struct fpga_region |
| @@ -230,8 +234,8 @@ err_free: | |||
| 230 | EXPORT_SYMBOL_GPL(fpga_region_create); | 234 | EXPORT_SYMBOL_GPL(fpga_region_create); |
| 231 | 235 | ||
| 232 | /** | 236 | /** |
| 233 | * fpga_region_free - free a struct fpga_region | 237 | * fpga_region_free - free a FPGA region created by fpga_region_create() |
| 234 | * @region: FPGA region created by fpga_region_create | 238 | * @region: FPGA region |
| 235 | */ | 239 | */ |
| 236 | void fpga_region_free(struct fpga_region *region) | 240 | void fpga_region_free(struct fpga_region *region) |
| 237 | { | 241 | { |
| @@ -240,21 +244,69 @@ void fpga_region_free(struct fpga_region *region) | |||
| 240 | } | 244 | } |
| 241 | EXPORT_SYMBOL_GPL(fpga_region_free); | 245 | EXPORT_SYMBOL_GPL(fpga_region_free); |
| 242 | 246 | ||
| 247 | static void devm_fpga_region_release(struct device *dev, void *res) | ||
| 248 | { | ||
| 249 | struct fpga_region *region = *(struct fpga_region **)res; | ||
| 250 | |||
| 251 | fpga_region_free(region); | ||
| 252 | } | ||
| 253 | |||
| 254 | /** | ||
| 255 | * devm_fpga_region_create - create and initialize a managed FPGA region struct | ||
| 256 | * @dev: device parent | ||
| 257 | * @mgr: manager that programs this region | ||
| 258 | * @get_bridges: optional function to get bridges to a list | ||
| 259 | * | ||
| 260 | * This function is intended for use in a FPGA region driver's probe function. | ||
| 261 | * After the region driver creates the region struct with | ||
| 262 | * devm_fpga_region_create(), it should register it with fpga_region_register(). | ||
| 263 | * The region driver's remove function should call fpga_region_unregister(). | ||
| 264 | * The region struct allocated with this function will be freed automatically on | ||
| 265 | * driver detach. This includes the case of a probe function returning error | ||
| 266 | * before calling fpga_region_register(), the struct will still get cleaned up. | ||
| 267 | * | ||
| 268 | * Return: struct fpga_region or NULL | ||
| 269 | */ | ||
| 270 | struct fpga_region | ||
| 271 | *devm_fpga_region_create(struct device *dev, | ||
| 272 | struct fpga_manager *mgr, | ||
| 273 | int (*get_bridges)(struct fpga_region *)) | ||
| 274 | { | ||
| 275 | struct fpga_region **ptr, *region; | ||
| 276 | |||
| 277 | ptr = devres_alloc(devm_fpga_region_release, sizeof(*ptr), GFP_KERNEL); | ||
| 278 | if (!ptr) | ||
| 279 | return NULL; | ||
| 280 | |||
| 281 | region = fpga_region_create(dev, mgr, get_bridges); | ||
| 282 | if (!region) { | ||
| 283 | devres_free(ptr); | ||
| 284 | } else { | ||
| 285 | *ptr = region; | ||
| 286 | devres_add(dev, ptr); | ||
| 287 | } | ||
| 288 | |||
| 289 | return region; | ||
| 290 | } | ||
| 291 | EXPORT_SYMBOL_GPL(devm_fpga_region_create); | ||
| 292 | |||
| 243 | /** | 293 | /** |
| 244 | * fpga_region_register - register a FPGA region | 294 | * fpga_region_register - register a FPGA region |
| 245 | * @region: FPGA region created by fpga_region_create | 295 | * @region: FPGA region |
| 296 | * | ||
| 246 | * Return: 0 or -errno | 297 | * Return: 0 or -errno |
| 247 | */ | 298 | */ |
| 248 | int fpga_region_register(struct fpga_region *region) | 299 | int fpga_region_register(struct fpga_region *region) |
| 249 | { | 300 | { |
| 250 | return device_add(®ion->dev); | 301 | return device_add(®ion->dev); |
| 251 | |||
| 252 | } | 302 | } |
| 253 | EXPORT_SYMBOL_GPL(fpga_region_register); | 303 | EXPORT_SYMBOL_GPL(fpga_region_register); |
| 254 | 304 | ||
| 255 | /** | 305 | /** |
| 256 | * fpga_region_unregister - unregister and free a FPGA region | 306 | * fpga_region_unregister - unregister a FPGA region |
| 257 | * @region: FPGA region | 307 | * @region: FPGA region |
| 308 | * | ||
| 309 | * This function is intended for use in a FPGA region driver's remove function. | ||
| 258 | */ | 310 | */ |
| 259 | void fpga_region_unregister(struct fpga_region *region) | 311 | void fpga_region_unregister(struct fpga_region *region) |
| 260 | { | 312 | { |
| @@ -264,9 +316,6 @@ EXPORT_SYMBOL_GPL(fpga_region_unregister); | |||
| 264 | 316 | ||
| 265 | static void fpga_region_dev_release(struct device *dev) | 317 | static void fpga_region_dev_release(struct device *dev) |
| 266 | { | 318 | { |
| 267 | struct fpga_region *region = to_fpga_region(dev); | ||
| 268 | |||
| 269 | fpga_region_free(region); | ||
| 270 | } | 319 | } |
| 271 | 320 | ||
| 272 | /** | 321 | /** |
