diff options
author | Alan Tull <atull@kernel.org> | 2018-10-15 18:20:03 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2018-10-16 05:13:50 -0400 |
commit | fea82b7f6670002ff36bf1bc77d0345b0b2f2d1c (patch) | |
tree | eeed3d9f54d90d5f01ea84e1ebdd2d05b3553667 /drivers/fpga/fpga-region.c | |
parent | 213befe049c70cfcfcbb4f6010bd5276dbc1f7b9 (diff) |
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>
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 | /** |