]> Git Repo - linux.git/commitdiff
fpga: bridge: Use standard dev_release for class driver
authorRuss Weight <[email protected]>
Fri, 19 Nov 2021 01:55:52 +0000 (17:55 -0800)
committerMoritz Fischer <[email protected]>
Sun, 28 Nov 2021 22:02:13 +0000 (14:02 -0800)
The FPGA bridge 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() function.

Signed-off-by: Russ Weight <[email protected]>
Reviewed-by: Xu Yilun <[email protected]>
Acked-by: Xu Yilun <[email protected]>
Signed-off-by: Moritz Fischer <[email protected]>
Documentation/driver-api/fpga/fpga-bridge.rst
drivers/fpga/altera-fpga2sdram.c
drivers/fpga/altera-freeze-bridge.c
drivers/fpga/altera-hps2fpga.c
drivers/fpga/dfl-fme-br.c
drivers/fpga/fpga-bridge.c
drivers/fpga/xilinx-pr-decoupler.c
include/linux/fpga/fpga-bridge.h

index 8d650b4e2ce6da5bef514e6ebc3de1a34932c573..604208534095339537ba261972bf0ef1c03635b5 100644 (file)
@@ -6,8 +6,7 @@ API to implement a new FPGA bridge
 
 * struct fpga_bridge - The FPGA Bridge structure
 * struct fpga_bridge_ops - Low level Bridge driver ops
-* devm_fpga_bridge_create() - Allocate and init a bridge struct
-* fpga_bridge_register() - Register a bridge
+* fpga_bridge_register() - Create and register a bridge
 * fpga_bridge_unregister() - Unregister a bridge
 
 .. kernel-doc:: include/linux/fpga/fpga-bridge.h
@@ -16,9 +15,6 @@ API to implement a new FPGA bridge
 .. kernel-doc:: include/linux/fpga/fpga-bridge.h
    :functions: fpga_bridge_ops
 
-.. kernel-doc:: drivers/fpga/fpga-bridge.c
-   :functions: devm_fpga_bridge_create
-
 .. kernel-doc:: drivers/fpga/fpga-bridge.c
    :functions: fpga_bridge_register
 
index a78e49c63c640d3fb8313d6015bd6af9f0607e80..ff3a646fd9e32fab30acef6a4a4e373c85a7c697 100644 (file)
@@ -121,17 +121,13 @@ static int alt_fpga_bridge_probe(struct platform_device *pdev)
        /* Get f2s bridge configuration saved in handoff register */
        regmap_read(sysmgr, SYSMGR_ISWGRP_HANDOFF3, &priv->mask);
 
-       br = devm_fpga_bridge_create(dev, F2S_BRIDGE_NAME,
-                                    &altera_fpga2sdram_br_ops, priv);
-       if (!br)
-               return -ENOMEM;
+       br = fpga_bridge_register(dev, F2S_BRIDGE_NAME,
+                                 &altera_fpga2sdram_br_ops, priv);
+       if (IS_ERR(br))
+               return PTR_ERR(br);
 
        platform_set_drvdata(pdev, br);
 
-       ret = fpga_bridge_register(br);
-       if (ret)
-               return ret;
-
        dev_info(dev, "driver initialized with handoff %08x\n", priv->mask);
 
        if (!of_property_read_u32(dev->of_node, "bridge-enable", &enable)) {
index 7d22a44d652e29870d58f3ef7c435a7f30b87f70..445f4b011167fa978f7ab6edb5af6e0c63d0403e 100644 (file)
@@ -246,14 +246,14 @@ static int altera_freeze_br_probe(struct platform_device *pdev)
 
        priv->base_addr = base_addr;
 
-       br = devm_fpga_bridge_create(dev, FREEZE_BRIDGE_NAME,
-                                    &altera_freeze_br_br_ops, priv);
-       if (!br)
-               return -ENOMEM;
+       br = fpga_bridge_register(dev, FREEZE_BRIDGE_NAME,
+                                 &altera_freeze_br_br_ops, priv);
+       if (IS_ERR(br))
+               return PTR_ERR(br);
 
        platform_set_drvdata(pdev, br);
 
-       return fpga_bridge_register(br);
+       return 0;
 }
 
 static int altera_freeze_br_remove(struct platform_device *pdev)
index 77b95f2518216863bdba6c80c38e329c51912cc5..aa758426c22bcd5fec39dc9c31c8b2991a043dee 100644 (file)
@@ -180,19 +180,15 @@ static int alt_fpga_bridge_probe(struct platform_device *pdev)
                }
        }
 
-       br = devm_fpga_bridge_create(dev, priv->name,
-                                    &altera_hps2fpga_br_ops, priv);
-       if (!br) {
-               ret = -ENOMEM;
+       br = fpga_bridge_register(dev, priv->name,
+                                 &altera_hps2fpga_br_ops, priv);
+       if (IS_ERR(br)) {
+               ret = PTR_ERR(br);
                goto err;
        }
 
        platform_set_drvdata(pdev, br);
 
-       ret = fpga_bridge_register(br);
-       if (ret)
-               goto err;
-
        return 0;
 
 err:
index 3ff9f3a687ce52b3399b5c06ce4a1b91eec52621..808d1f4d76df8f3f69569f598cc6ad1c9b73c47d 100644 (file)
@@ -68,14 +68,14 @@ static int fme_br_probe(struct platform_device *pdev)
 
        priv->pdata = dev_get_platdata(dev);
 
-       br = devm_fpga_bridge_create(dev, "DFL FPGA FME Bridge",
-                                    &fme_bridge_ops, priv);
-       if (!br)
-               return -ENOMEM;
+       br = fpga_bridge_register(dev, "DFL FPGA FME Bridge",
+                                 &fme_bridge_ops, priv);
+       if (IS_ERR(br))
+               return PTR_ERR(br);
 
        platform_set_drvdata(pdev, br);
 
-       return fpga_bridge_register(br);
+       return 0;
 }
 
 static int fme_br_remove(struct platform_device *pdev)
index 798f55670646ceaae3f013d399ab60190105d369..16f2b164a178a5185f72f8834e98d615bf01a16f 100644 (file)
@@ -312,36 +312,41 @@ static struct attribute *fpga_bridge_attrs[] = {
 ATTRIBUTE_GROUPS(fpga_bridge);
 
 /**
- * fpga_bridge_create - create and initialize a struct fpga_bridge
+ * fpga_bridge_register - create and register an FPGA Bridge device
  * @parent:    FPGA bridge device from pdev
  * @name:      FPGA bridge name
  * @br_ops:    pointer to structure of fpga bridge ops
  * @priv:      FPGA bridge private data
  *
- * The caller of this function is responsible for freeing the bridge with
- * fpga_bridge_free().  Using devm_fpga_bridge_create() instead is recommended.
- *
- * Return: struct fpga_bridge or NULL
+ * Return: struct fpga_bridge pointer or ERR_PTR()
  */
-struct fpga_bridge *fpga_bridge_create(struct device *parent, const char *name,
-                                      const struct fpga_bridge_ops *br_ops,
-                                      void *priv)
+struct fpga_bridge *
+fpga_bridge_register(struct device *parent, const char *name,
+                    const struct fpga_bridge_ops *br_ops,
+                    void *priv)
 {
        struct fpga_bridge *bridge;
        int id, ret;
 
+       if (!br_ops) {
+               dev_err(parent, "Attempt to register without fpga_bridge_ops\n");
+               return ERR_PTR(-EINVAL);
+       }
+
        if (!name || !strlen(name)) {
                dev_err(parent, "Attempt to register with no name!\n");
-               return NULL;
+               return ERR_PTR(-EINVAL);
        }
 
        bridge = kzalloc(sizeof(*bridge), GFP_KERNEL);
        if (!bridge)
-               return NULL;
+               return ERR_PTR(-ENOMEM);
 
        id = ida_simple_get(&fpga_bridge_ida, 0, 0, GFP_KERNEL);
-       if (id < 0)
+       if (id < 0) {
+               ret = id;
                goto error_kfree;
+       }
 
        mutex_init(&bridge->mutex);
        INIT_LIST_HEAD(&bridge->node);
@@ -350,17 +355,23 @@ struct fpga_bridge *fpga_bridge_create(struct device *parent, const char *name,
        bridge->br_ops = br_ops;
        bridge->priv = priv;
 
-       device_initialize(&bridge->dev);
        bridge->dev.groups = br_ops->groups;
        bridge->dev.class = fpga_bridge_class;
        bridge->dev.parent = parent;
        bridge->dev.of_node = parent->of_node;
        bridge->dev.id = id;
+       of_platform_populate(bridge->dev.of_node, NULL, NULL, &bridge->dev);
 
        ret = dev_set_name(&bridge->dev, "br%d", id);
        if (ret)
                goto error_device;
 
+       ret = device_register(&bridge->dev);
+       if (ret) {
+               put_device(&bridge->dev);
+               return ERR_PTR(ret);
+       }
+
        return bridge;
 
 error_device:
@@ -368,88 +379,7 @@ error_device:
 error_kfree:
        kfree(bridge);
 
-       return NULL;
-}
-EXPORT_SYMBOL_GPL(fpga_bridge_create);
-
-/**
- * fpga_bridge_free - free an fpga bridge created by fpga_bridge_create()
- * @bridge:    FPGA bridge struct
- */
-void fpga_bridge_free(struct fpga_bridge *bridge)
-{
-       ida_simple_remove(&fpga_bridge_ida, bridge->dev.id);
-       kfree(bridge);
-}
-EXPORT_SYMBOL_GPL(fpga_bridge_free);
-
-static void devm_fpga_bridge_release(struct device *dev, void *res)
-{
-       struct fpga_bridge *bridge = *(struct fpga_bridge **)res;
-
-       fpga_bridge_free(bridge);
-}
-
-/**
- * devm_fpga_bridge_create - create and init a managed struct fpga_bridge
- * @parent:    FPGA bridge device from pdev
- * @name:      FPGA bridge name
- * @br_ops:    pointer to structure of fpga bridge ops
- * @priv:      FPGA bridge private data
- *
- * This function is intended for use in an FPGA bridge driver's probe function.
- * After the bridge driver creates the struct with devm_fpga_bridge_create(), it
- * should register the bridge with fpga_bridge_register().  The bridge driver's
- * remove function should call fpga_bridge_unregister().  The bridge 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_bridge_register(), the struct will still get cleaned up.
- *
- *  Return: struct fpga_bridge or NULL
- */
-struct fpga_bridge
-*devm_fpga_bridge_create(struct device *parent, const char *name,
-                        const struct fpga_bridge_ops *br_ops, void *priv)
-{
-       struct fpga_bridge **ptr, *bridge;
-
-       ptr = devres_alloc(devm_fpga_bridge_release, sizeof(*ptr), GFP_KERNEL);
-       if (!ptr)
-               return NULL;
-
-       bridge = fpga_bridge_create(parent, name, br_ops, priv);
-       if (!bridge) {
-               devres_free(ptr);
-       } else {
-               *ptr = bridge;
-               devres_add(parent, ptr);
-       }
-
-       return bridge;
-}
-EXPORT_SYMBOL_GPL(devm_fpga_bridge_create);
-
-/**
- * fpga_bridge_register - register an FPGA bridge
- *
- * @bridge: FPGA bridge struct
- *
- * Return: 0 for success, error code otherwise.
- */
-int fpga_bridge_register(struct fpga_bridge *bridge)
-{
-       struct device *dev = &bridge->dev;
-       int ret;
-
-       ret = device_add(dev);
-       if (ret)
-               return ret;
-
-       of_platform_populate(dev->of_node, NULL, NULL, dev);
-
-       dev_info(dev->parent, "fpga bridge [%s] registered\n", bridge->name);
-
-       return 0;
+       return ERR_PTR(ret);
 }
 EXPORT_SYMBOL_GPL(fpga_bridge_register);
 
@@ -475,6 +405,10 @@ EXPORT_SYMBOL_GPL(fpga_bridge_unregister);
 
 static void fpga_bridge_dev_release(struct device *dev)
 {
+       struct fpga_bridge *bridge = to_fpga_bridge(dev);
+
+       ida_simple_remove(&fpga_bridge_ida, bridge->dev.id);
+       kfree(bridge);
 }
 
 static int __init fpga_bridge_dev_init(void)
index e986ed47c4ed702866796eab197a3ed5b4776831..2d9c491f7be9477be2bf187c1d28941395bb968f 100644 (file)
@@ -140,22 +140,17 @@ static int xlnx_pr_decoupler_probe(struct platform_device *pdev)
 
        clk_disable(priv->clk);
 
-       br = devm_fpga_bridge_create(&pdev->dev, priv->ipconfig->name,
-                                    &xlnx_pr_decoupler_br_ops, priv);
-       if (!br) {
-               err = -ENOMEM;
-               goto err_clk;
-       }
-
-       platform_set_drvdata(pdev, br);
-
-       err = fpga_bridge_register(br);
-       if (err) {
+       br = fpga_bridge_register(&pdev->dev, priv->ipconfig->name,
+                                 &xlnx_pr_decoupler_br_ops, priv);
+       if (IS_ERR(br)) {
+               err = PTR_ERR(br);
                dev_err(&pdev->dev, "unable to register %s",
                        priv->ipconfig->name);
                goto err_clk;
        }
 
+       platform_set_drvdata(pdev, br);
+
        return 0;
 
 err_clk:
index 6c3c28806ff13f9bcde899fc40509f4690ba9a05..223da48a6d18b519457f817c1cbe0b9ba1becf56 100644 (file)
@@ -22,6 +22,23 @@ struct fpga_bridge_ops {
        const struct attribute_group **groups;
 };
 
+/**
+ * struct fpga_bridge_info - collection of parameters an FPGA Bridge
+ * @name: fpga bridge name
+ * @br_ops: pointer to structure of fpga bridge ops
+ * @priv: fpga bridge private data
+ *
+ * fpga_bridge_info contains parameters for the register function. These
+ * are separated into an info structure because they some are optional
+ * others could be added to in the future. The info structure facilitates
+ * maintaining a stable API.
+ */
+struct fpga_bridge_info {
+       const char *name;
+       const struct fpga_bridge_ops *br_ops;
+       void *priv;
+};
+
 /**
  * struct fpga_bridge - FPGA bridge structure
  * @name: name of low level FPGA bridge
@@ -62,15 +79,10 @@ int of_fpga_bridge_get_to_list(struct device_node *np,
                               struct fpga_image_info *info,
                               struct list_head *bridge_list);
 
-struct fpga_bridge *fpga_bridge_create(struct device *dev, const char *name,
-                                      const struct fpga_bridge_ops *br_ops,
-                                      void *priv);
-void fpga_bridge_free(struct fpga_bridge *br);
-int fpga_bridge_register(struct fpga_bridge *br);
+struct fpga_bridge *
+fpga_bridge_register(struct device *parent, const char *name,
+                    const struct fpga_bridge_ops *br_ops,
+                    void *priv);
 void fpga_bridge_unregister(struct fpga_bridge *br);
 
-struct fpga_bridge
-*devm_fpga_bridge_create(struct device *dev, const char *name,
-                        const struct fpga_bridge_ops *br_ops, void *priv);
-
 #endif /* _LINUX_FPGA_BRIDGE_H */
This page took 0.126453 seconds and 4 git commands to generate.