fpga: region: change api, add fpga_region_create/free

Add fpga_region_create/free API functions.

Change fpga_region_register to take FPGA region struct as the only
parameter.  Change fpga_region_unregister to return void.

  struct fpga_region *fpga_region_create(struct device *dev,
                        struct fpga_manager *mgr,
                        int (*get_bridges)(struct fpga_region *));
  void fpga_region_free(struct fpga_region *region);
  int fpga_region_register(struct fpga_region *region);
  void fpga_region_unregister(struct fpga_region *region);

Remove groups storage from struct fpga_region, it's not
needed.  Callers can just "region->dev.groups = groups;"
after calling fpga_region_create.

Update the drivers that call fpga_region_register with the new API.

Signed-off-by: Alan Tull <atull@kernel.org>
Signed-off-by: Moritz Fischer <mdf@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
Alan Tull 2018-05-16 18:49:57 -05:00 committed by Greg Kroah-Hartman
parent 371cd1b1fd
commit 9f368977b4
4 changed files with 68 additions and 27 deletions

View File

@ -42,8 +42,7 @@ The FPGA region API
To register or unregister a region: To register or unregister a region:
----------------------------------- -----------------------------------
int fpga_region_register(struct device *dev, int fpga_region_register(struct fpga_region *region);
struct fpga_region *region);
int fpga_region_unregister(struct fpga_region *region); int fpga_region_unregister(struct fpga_region *region);
An example of usage can be seen in the probe function of [3] An example of usage can be seen in the probe function of [3]

View File

@ -167,18 +167,36 @@ err_put_region:
} }
EXPORT_SYMBOL_GPL(fpga_region_program_fpga); EXPORT_SYMBOL_GPL(fpga_region_program_fpga);
int fpga_region_register(struct device *dev, struct fpga_region *region) /**
* fpga_region_create - alloc and init a struct fpga_region
* @dev: device parent
* @mgr: manager that programs this region
* @get_bridges: optional function to get bridges to a list
*
* Return: struct fpga_region or NULL
*/
struct fpga_region
*fpga_region_create(struct device *dev,
struct fpga_manager *mgr,
int (*get_bridges)(struct fpga_region *))
{ {
struct fpga_region *region;
int id, ret = 0; int id, ret = 0;
region = kzalloc(sizeof(*region), GFP_KERNEL);
if (!region)
return NULL;
id = ida_simple_get(&fpga_region_ida, 0, 0, GFP_KERNEL); id = ida_simple_get(&fpga_region_ida, 0, 0, GFP_KERNEL);
if (id < 0) if (id < 0)
return id; goto err_free;
region->mgr = mgr;
region->get_bridges = get_bridges;
mutex_init(&region->mutex); mutex_init(&region->mutex);
INIT_LIST_HEAD(&region->bridge_list); INIT_LIST_HEAD(&region->bridge_list);
device_initialize(&region->dev); device_initialize(&region->dev);
region->dev.groups = region->groups;
region->dev.class = fpga_region_class; region->dev.class = fpga_region_class;
region->dev.parent = dev; region->dev.parent = dev;
region->dev.of_node = dev->of_node; region->dev.of_node = dev->of_node;
@ -188,23 +206,47 @@ int fpga_region_register(struct device *dev, struct fpga_region *region)
if (ret) if (ret)
goto err_remove; goto err_remove;
ret = device_add(&region->dev); return region;
if (ret)
goto err_remove;
return 0;
err_remove: err_remove:
ida_simple_remove(&fpga_region_ida, id); ida_simple_remove(&fpga_region_ida, id);
return ret; err_free:
kfree(region);
return NULL;
}
EXPORT_SYMBOL_GPL(fpga_region_create);
/**
* fpga_region_free - free a struct fpga_region
* @region: FPGA region created by fpga_region_create
*/
void fpga_region_free(struct fpga_region *region)
{
ida_simple_remove(&fpga_region_ida, region->dev.id);
kfree(region);
}
EXPORT_SYMBOL_GPL(fpga_region_free);
/*
* fpga_region_register - register a FPGA region
* @region: FPGA region created by fpga_region_create
* Return: 0 or -errno
*/
int fpga_region_register(struct fpga_region *region)
{
return device_add(&region->dev);
} }
EXPORT_SYMBOL_GPL(fpga_region_register); EXPORT_SYMBOL_GPL(fpga_region_register);
int fpga_region_unregister(struct fpga_region *region) /*
* fpga_region_unregister - unregister a FPGA region
* @region: FPGA region
*/
void fpga_region_unregister(struct fpga_region *region)
{ {
device_unregister(&region->dev); device_unregister(&region->dev);
return 0;
} }
EXPORT_SYMBOL_GPL(fpga_region_unregister); EXPORT_SYMBOL_GPL(fpga_region_unregister);
@ -212,7 +254,7 @@ static void fpga_region_dev_release(struct device *dev)
{ {
struct fpga_region *region = to_fpga_region(dev); struct fpga_region *region = to_fpga_region(dev);
ida_simple_remove(&fpga_region_ida, region->dev.id); fpga_region_free(region);
} }
/** /**

View File

@ -422,20 +422,15 @@ static int of_fpga_region_probe(struct platform_device *pdev)
if (IS_ERR(mgr)) if (IS_ERR(mgr))
return -EPROBE_DEFER; return -EPROBE_DEFER;
region = devm_kzalloc(dev, sizeof(*region), GFP_KERNEL); region = fpga_region_create(dev, mgr, of_fpga_region_get_bridges);
if (!region) { if (!region) {
ret = -ENOMEM; ret = -ENOMEM;
goto eprobe_mgr_put; goto eprobe_mgr_put;
} }
region->mgr = mgr; ret = fpga_region_register(region);
/* Specify how to get bridges for this type of region. */
region->get_bridges = of_fpga_region_get_bridges;
ret = fpga_region_register(dev, region);
if (ret) if (ret)
goto eprobe_mgr_put; goto eprobe_free;
of_platform_populate(np, fpga_region_of_match, NULL, &region->dev); of_platform_populate(np, fpga_region_of_match, NULL, &region->dev);
dev_set_drvdata(dev, region); dev_set_drvdata(dev, region);
@ -444,6 +439,8 @@ static int of_fpga_region_probe(struct platform_device *pdev)
return 0; return 0;
eprobe_free:
fpga_region_free(region);
eprobe_mgr_put: eprobe_mgr_put:
fpga_mgr_put(mgr); fpga_mgr_put(mgr);
return ret; return ret;

View File

@ -14,7 +14,6 @@
* @info: FPGA image info * @info: FPGA image info
* @priv: private data * @priv: private data
* @get_bridges: optional function to get bridges to a list * @get_bridges: optional function to get bridges to a list
* @groups: optional attribute groups.
*/ */
struct fpga_region { struct fpga_region {
struct device dev; struct device dev;
@ -24,7 +23,6 @@ struct fpga_region {
struct fpga_image_info *info; struct fpga_image_info *info;
void *priv; void *priv;
int (*get_bridges)(struct fpga_region *region); int (*get_bridges)(struct fpga_region *region);
const struct attribute_group **groups;
}; };
#define to_fpga_region(d) container_of(d, struct fpga_region, dev) #define to_fpga_region(d) container_of(d, struct fpga_region, dev)
@ -34,7 +32,12 @@ struct fpga_region *fpga_region_class_find(
int (*match)(struct device *, const void *)); int (*match)(struct device *, const void *));
int fpga_region_program_fpga(struct fpga_region *region); int fpga_region_program_fpga(struct fpga_region *region);
int fpga_region_register(struct device *dev, struct fpga_region *region);
int fpga_region_unregister(struct fpga_region *region); struct fpga_region
*fpga_region_create(struct device *dev, struct fpga_manager *mgr,
int (*get_bridges)(struct fpga_region *));
void fpga_region_free(struct fpga_region *region);
int fpga_region_register(struct fpga_region *region);
void fpga_region_unregister(struct fpga_region *region);
#endif /* _FPGA_REGION_H */ #endif /* _FPGA_REGION_H */