]> Git Repo - J-linux.git/blobdiff - drivers/fpga/fpga-region.c
Merge tag 'lkdtm-next' of https://git.kernel.org/pub/scm/linux/kernel/git/kees/linux...
[J-linux.git] / drivers / fpga / fpga-region.c
index a4838715221ff209792d2829be7864c305336e92..485948e3c0db18049a2fed07e1218ef861063179 100644 (file)
@@ -18,9 +18,9 @@
 static DEFINE_IDA(fpga_region_ida);
 static struct class *fpga_region_class;
 
-struct fpga_region *fpga_region_class_find(
-       struct device *start, const void *data,
-       int (*match)(struct device *, const void *))
+struct fpga_region *
+fpga_region_class_find(struct device *start, const void *data,
+                      int (*match)(struct device *, const void *))
 {
        struct device *dev;
 
@@ -180,39 +180,42 @@ static struct attribute *fpga_region_attrs[] = {
 ATTRIBUTE_GROUPS(fpga_region);
 
 /**
- * fpga_region_create - alloc and init a struct fpga_region
+ * fpga_region_register_full - create and register an FPGA Region device
  * @parent: device parent
- * @mgr: manager that programs this region
- * @get_bridges: optional function to get bridges to a list
- *
- * The caller of this function is responsible for freeing the resulting region
- * struct with fpga_region_free().  Using devm_fpga_region_create() instead is
- * recommended.
+ * @info: parameters for FPGA Region
  *
- * Return: struct fpga_region or NULL
+ * Return: struct fpga_region or ERR_PTR()
  */
-struct fpga_region
-*fpga_region_create(struct device *parent,
-                   struct fpga_manager *mgr,
-                   int (*get_bridges)(struct fpga_region *))
+struct fpga_region *
+fpga_region_register_full(struct device *parent, const struct fpga_region_info *info)
 {
        struct fpga_region *region;
        int id, ret = 0;
 
+       if (!info) {
+               dev_err(parent,
+                       "Attempt to register without required info structure\n");
+               return ERR_PTR(-EINVAL);
+       }
+
        region = kzalloc(sizeof(*region), GFP_KERNEL);
        if (!region)
-               return NULL;
+               return ERR_PTR(-ENOMEM);
 
        id = ida_simple_get(&fpga_region_ida, 0, 0, GFP_KERNEL);
-       if (id < 0)
+       if (id < 0) {
+               ret = id;
                goto err_free;
+       }
+
+       region->mgr = info->mgr;
+       region->compat_id = info->compat_id;
+       region->priv = info->priv;
+       region->get_bridges = info->get_bridges;
 
-       region->mgr = mgr;
-       region->get_bridges = get_bridges;
        mutex_init(&region->mutex);
        INIT_LIST_HEAD(&region->bridge_list);
 
-       device_initialize(&region->dev);
        region->dev.class = fpga_region_class;
        region->dev.parent = parent;
        region->dev.of_node = parent->of_node;
@@ -222,6 +225,12 @@ struct fpga_region
        if (ret)
                goto err_remove;
 
+       ret = device_register(&region->dev);
+       if (ret) {
+               put_device(&region->dev);
+               return ERR_PTR(ret);
+       }
+
        return region;
 
 err_remove:
@@ -229,76 +238,32 @@ err_remove:
 err_free:
        kfree(region);
 
-       return NULL;
-}
-EXPORT_SYMBOL_GPL(fpga_region_create);
-
-/**
- * fpga_region_free - free an FPGA region created by fpga_region_create()
- * @region: FPGA region
- */
-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);
-
-static void devm_fpga_region_release(struct device *dev, void *res)
-{
-       struct fpga_region *region = *(struct fpga_region **)res;
-
-       fpga_region_free(region);
+       return ERR_PTR(ret);
 }
+EXPORT_SYMBOL_GPL(fpga_region_register_full);
 
 /**
- * devm_fpga_region_create - create and initialize a managed FPGA region struct
+ * fpga_region_register - create and register an FPGA Region device
  * @parent: device parent
  * @mgr: manager that programs this region
  * @get_bridges: optional function to get bridges to a list
  *
- * This function is intended for use in an FPGA region driver's probe function.
- * After the region driver creates the region struct with
- * devm_fpga_region_create(), it should register it with fpga_region_register().
- * The region driver's remove function should call fpga_region_unregister().
- * The region struct allocated with this function will be freed automatically on
- * driver detach.  This includes the case of a probe function returning error
- * before calling fpga_region_register(), the struct will still get cleaned up.
+ * This simple version of the register function should be sufficient for most users.
+ * The fpga_region_register_full() function is available for users that need to
+ * pass additional, optional parameters.
  *
- * Return: struct fpga_region or NULL
+ * Return: struct fpga_region or ERR_PTR()
  */
-struct fpga_region
-*devm_fpga_region_create(struct device *parent,
-                        struct fpga_manager *mgr,
-                        int (*get_bridges)(struct fpga_region *))
+struct fpga_region *
+fpga_region_register(struct device *parent, struct fpga_manager *mgr,
+                    int (*get_bridges)(struct fpga_region *))
 {
-       struct fpga_region **ptr, *region;
-
-       ptr = devres_alloc(devm_fpga_region_release, sizeof(*ptr), GFP_KERNEL);
-       if (!ptr)
-               return NULL;
+       struct fpga_region_info info = { 0 };
 
-       region = fpga_region_create(parent, mgr, get_bridges);
-       if (!region) {
-               devres_free(ptr);
-       } else {
-               *ptr = region;
-               devres_add(parent, ptr);
-       }
+       info.mgr = mgr;
+       info.get_bridges = get_bridges;
 
-       return region;
-}
-EXPORT_SYMBOL_GPL(devm_fpga_region_create);
-
-/**
- * fpga_region_register - register an FPGA region
- * @region: FPGA region
- *
- * Return: 0 or -errno
- */
-int fpga_region_register(struct fpga_region *region)
-{
-       return device_add(&region->dev);
+       return fpga_region_register_full(parent, &info);
 }
 EXPORT_SYMBOL_GPL(fpga_region_register);
 
@@ -316,6 +281,10 @@ EXPORT_SYMBOL_GPL(fpga_region_unregister);
 
 static void fpga_region_dev_release(struct device *dev)
 {
+       struct fpga_region *region = to_fpga_region(dev);
+
+       ida_simple_remove(&fpga_region_ida, region->dev.id);
+       kfree(region);
 }
 
 /**
This page took 0.032807 seconds and 4 git commands to generate.