Merge tag 'char-misc-6.10-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregk...
[linux-block.git] / drivers / fpga / fpga-bridge.c
index 79c473b3c7c3d5aa4ff1a824dbc7737a49528305..8ef395b49bf8a513abf3b95b4fc79b03f2e348c2 100644 (file)
@@ -55,33 +55,26 @@ int fpga_bridge_disable(struct fpga_bridge *bridge)
 }
 EXPORT_SYMBOL_GPL(fpga_bridge_disable);
 
-static struct fpga_bridge *__fpga_bridge_get(struct device *dev,
+static struct fpga_bridge *__fpga_bridge_get(struct device *bridge_dev,
                                             struct fpga_image_info *info)
 {
        struct fpga_bridge *bridge;
-       int ret = -ENODEV;
 
-       bridge = to_fpga_bridge(dev);
+       bridge = to_fpga_bridge(bridge_dev);
 
        bridge->info = info;
 
-       if (!mutex_trylock(&bridge->mutex)) {
-               ret = -EBUSY;
-               goto err_dev;
-       }
+       if (!mutex_trylock(&bridge->mutex))
+               return ERR_PTR(-EBUSY);
 
-       if (!try_module_get(dev->parent->driver->owner))
-               goto err_ll_mod;
+       if (!try_module_get(bridge->br_ops_owner)) {
+               mutex_unlock(&bridge->mutex);
+               return ERR_PTR(-ENODEV);
+       }
 
        dev_dbg(&bridge->dev, "get\n");
 
        return bridge;
-
-err_ll_mod:
-       mutex_unlock(&bridge->mutex);
-err_dev:
-       put_device(dev);
-       return ERR_PTR(ret);
 }
 
 /**
@@ -98,13 +91,18 @@ err_dev:
 struct fpga_bridge *of_fpga_bridge_get(struct device_node *np,
                                       struct fpga_image_info *info)
 {
-       struct device *dev;
+       struct fpga_bridge *bridge;
+       struct device *bridge_dev;
 
-       dev = class_find_device_by_of_node(&fpga_bridge_class, np);
-       if (!dev)
+       bridge_dev = class_find_device_by_of_node(&fpga_bridge_class, np);
+       if (!bridge_dev)
                return ERR_PTR(-ENODEV);
 
-       return __fpga_bridge_get(dev, info);
+       bridge = __fpga_bridge_get(bridge_dev, info);
+       if (IS_ERR(bridge))
+               put_device(bridge_dev);
+
+       return bridge;
 }
 EXPORT_SYMBOL_GPL(of_fpga_bridge_get);
 
@@ -125,6 +123,7 @@ static int fpga_bridge_dev_match(struct device *dev, const void *data)
 struct fpga_bridge *fpga_bridge_get(struct device *dev,
                                    struct fpga_image_info *info)
 {
+       struct fpga_bridge *bridge;
        struct device *bridge_dev;
 
        bridge_dev = class_find_device(&fpga_bridge_class, NULL, dev,
@@ -132,7 +131,11 @@ struct fpga_bridge *fpga_bridge_get(struct device *dev,
        if (!bridge_dev)
                return ERR_PTR(-ENODEV);
 
-       return __fpga_bridge_get(bridge_dev, info);
+       bridge = __fpga_bridge_get(bridge_dev, info);
+       if (IS_ERR(bridge))
+               put_device(bridge_dev);
+
+       return bridge;
 }
 EXPORT_SYMBOL_GPL(fpga_bridge_get);
 
@@ -146,7 +149,7 @@ void fpga_bridge_put(struct fpga_bridge *bridge)
        dev_dbg(&bridge->dev, "put\n");
 
        bridge->info = NULL;
-       module_put(bridge->dev.parent->driver->owner);
+       module_put(bridge->br_ops_owner);
        mutex_unlock(&bridge->mutex);
        put_device(&bridge->dev);
 }
@@ -316,18 +319,19 @@ static struct attribute *fpga_bridge_attrs[] = {
 ATTRIBUTE_GROUPS(fpga_bridge);
 
 /**
- * fpga_bridge_register - create and register an FPGA Bridge device
+ * __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
+ * @owner:     owner module containing the br_ops
  *
  * Return: struct fpga_bridge pointer or ERR_PTR()
  */
 struct fpga_bridge *
-fpga_bridge_register(struct device *parent, const char *name,
-                    const struct fpga_bridge_ops *br_ops,
-                    void *priv)
+__fpga_bridge_register(struct device *parent, const char *name,
+                      const struct fpga_bridge_ops *br_ops,
+                      void *priv, struct module *owner)
 {
        struct fpga_bridge *bridge;
        int id, ret;
@@ -357,6 +361,7 @@ fpga_bridge_register(struct device *parent, const char *name,
 
        bridge->name = name;
        bridge->br_ops = br_ops;
+       bridge->br_ops_owner = owner;
        bridge->priv = priv;
 
        bridge->dev.groups = br_ops->groups;
@@ -386,7 +391,7 @@ error_kfree:
 
        return ERR_PTR(ret);
 }
-EXPORT_SYMBOL_GPL(fpga_bridge_register);
+EXPORT_SYMBOL_GPL(__fpga_bridge_register);
 
 /**
  * fpga_bridge_unregister - unregister an FPGA bridge