fpga: manager: change api, don't use drvdata
authorAlan Tull <atull@kernel.org>
Wed, 16 May 2018 23:49:55 +0000 (18:49 -0500)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 25 May 2018 16:23:55 +0000 (18:23 +0200)
Change fpga_mgr_register to not set or use drvdata.  This supports
the case where a PCIe device has more than one manager.

Add fpga_mgr_create/free functions.  Change fpga_mgr_register and
fpga_mgr_unregister functions to take the mgr struct as their only
parameter.

  struct fpga_manager *fpga_mgr_create(struct device *dev,
                const char *name,
                const struct fpga_manager_ops *mops,
                void *priv);
  void fpga_mgr_free(struct fpga_manager *mgr);
  int fpga_mgr_register(struct fpga_manager *mgr);
  void fpga_mgr_unregister(struct fpga_manager *mgr);

Update the drivers that call fpga_mgr_register with the new API.

Signed-off-by: Alan Tull <atull@kernel.org>
[Moritz: Fixup whitespace issue]
Reported-by: Jiuyue Ma <majiuyue@huawei.com>
Signed-off-by: Moritz Fischer <mdf@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
13 files changed:
Documentation/fpga/fpga-mgr.txt
drivers/fpga/altera-cvp.c
drivers/fpga/altera-pr-ip-core.c
drivers/fpga/altera-ps-spi.c
drivers/fpga/fpga-mgr.c
drivers/fpga/ice40-spi.c
drivers/fpga/machxo2-spi.c
drivers/fpga/socfpga-a10.c
drivers/fpga/socfpga.c
drivers/fpga/ts73xx-fpga.c
drivers/fpga/xilinx-spi.c
drivers/fpga/zynq-fpga.c
include/linux/fpga/fpga-mgr.h

index cc6413ed6fc91e201e233d519cc655ffa02fafef..86b6df66a90586056e20e692953053737c66a57e 100644 (file)
@@ -63,17 +63,23 @@ The user should call fpga_mgr_lock and verify that it returns 0 before
 attempting to program the FPGA.  Likewise, the user should call
 fpga_mgr_unlock when done programming the FPGA.
 
+To alloc/free a FPGA manager struct:
+------------------------------------
+
+       struct fpga_manager *fpga_mgr_create(struct device *dev,
+                                            const char *name,
+                                            const struct fpga_manager_ops *mops,
+                                            void *priv);
+       void fpga_mgr_free(struct fpga_manager *mgr);
 
 To register or unregister the low level FPGA-specific driver:
 -------------------------------------------------------------
 
-       int fpga_mgr_register(struct device *dev, const char *name,
-                             const struct fpga_manager_ops *mops,
-                             void *priv);
+       int fpga_mgr_register(struct fpga_manager *mgr);
 
-       void fpga_mgr_unregister(struct device *dev);
+       void fpga_mgr_unregister(struct fpga_manager *mgr);
 
-Use of these two functions is described below in "How To Support a new FPGA
+Use of these functions is described below in "How To Support a new FPGA
 device."
 
 
@@ -148,6 +154,7 @@ static int socfpga_fpga_probe(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
        struct socfpga_fpga_priv *priv;
+       struct fpga_manager *mgr;
        int ret;
 
        priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
@@ -157,13 +164,25 @@ static int socfpga_fpga_probe(struct platform_device *pdev)
        /* ... do ioremaps, get interrupts, etc. and save
           them in priv... */
 
-       return fpga_mgr_register(dev, "Altera SOCFPGA FPGA Manager",
-                                &socfpga_fpga_ops, priv);
+       mgr = fpga_mgr_create(dev, "Altera SOCFPGA FPGA Manager",
+                             &socfpga_fpga_ops, priv);
+       if (!mgr)
+               return -ENOMEM;
+
+       platform_set_drvdata(pdev, mgr);
+
+       ret = fpga_mgr_register(mgr);
+       if (ret)
+               fpga_mgr_free(mgr);
+
+       return ret;
 }
 
 static int socfpga_fpga_remove(struct platform_device *pdev)
 {
-       fpga_mgr_unregister(&pdev->dev);
+       struct fpga_manager *mgr = platform_get_drvdata(pdev);
+
+       fpga_mgr_unregister(mgr);
 
        return 0;
 }
index 77b04e4b32544a3fd7359537c1e0acbe3ccf0f84..dd4edd8f22ceebb67c4f6e1ab486c4ac9e9a1106 100644 (file)
@@ -401,6 +401,7 @@ static int altera_cvp_probe(struct pci_dev *pdev,
                            const struct pci_device_id *dev_id)
 {
        struct altera_cvp_conf *conf;
+       struct fpga_manager *mgr;
        u16 cmd, val;
        int ret;
 
@@ -452,16 +453,24 @@ static int altera_cvp_probe(struct pci_dev *pdev,
        snprintf(conf->mgr_name, sizeof(conf->mgr_name), "%s @%s",
                 ALTERA_CVP_MGR_NAME, pci_name(pdev));
 
-       ret = fpga_mgr_register(&pdev->dev, conf->mgr_name,
-                               &altera_cvp_ops, conf);
-       if (ret)
+       mgr = fpga_mgr_create(&pdev->dev, conf->mgr_name,
+                             &altera_cvp_ops, conf);
+       if (!mgr)
+               return -ENOMEM;
+
+       pci_set_drvdata(pdev, mgr);
+
+       ret = fpga_mgr_register(mgr);
+       if (ret) {
+               fpga_mgr_free(mgr);
                goto err_unmap;
+       }
 
        ret = driver_create_file(&altera_cvp_driver.driver,
                                 &driver_attr_chkcfg);
        if (ret) {
                dev_err(&pdev->dev, "Can't create sysfs chkcfg file\n");
-               fpga_mgr_unregister(&pdev->dev);
+               fpga_mgr_unregister(mgr);
                goto err_unmap;
        }
 
@@ -483,7 +492,7 @@ static void altera_cvp_remove(struct pci_dev *pdev)
        u16 cmd;
 
        driver_remove_file(&altera_cvp_driver.driver, &driver_attr_chkcfg);
-       fpga_mgr_unregister(&pdev->dev);
+       fpga_mgr_unregister(mgr);
        pci_iounmap(pdev, conf->map);
        pci_release_region(pdev, CVP_BAR);
        pci_read_config_word(pdev, PCI_COMMAND, &cmd);
index a7b31f9797ce180daa0e0cf91b69424300556626..eea521774cf6099c270149692c225bab1e98a8fa 100644 (file)
@@ -187,6 +187,8 @@ static const struct fpga_manager_ops alt_pr_ops = {
 int alt_pr_register(struct device *dev, void __iomem *reg_base)
 {
        struct alt_pr_priv *priv;
+       struct fpga_manager *mgr;
+       int ret;
        u32 val;
 
        priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
@@ -201,15 +203,27 @@ int alt_pr_register(struct device *dev, void __iomem *reg_base)
                (val & ALT_PR_CSR_STATUS_MSK) >> ALT_PR_CSR_STATUS_SFT,
                (int)(val & ALT_PR_CSR_PR_START));
 
-       return fpga_mgr_register(dev, dev_name(dev), &alt_pr_ops, priv);
+       mgr = fpga_mgr_create(dev, dev_name(dev), &alt_pr_ops, priv);
+       if (!mgr)
+               return -ENOMEM;
+
+       dev_set_drvdata(dev, mgr);
+
+       ret = fpga_mgr_register(mgr);
+       if (ret)
+               fpga_mgr_free(mgr);
+
+       return ret;
 }
 EXPORT_SYMBOL_GPL(alt_pr_register);
 
 int alt_pr_unregister(struct device *dev)
 {
+       struct fpga_manager *mgr = dev_get_drvdata(dev);
+
        dev_dbg(dev, "%s\n", __func__);
 
-       fpga_mgr_unregister(dev);
+       fpga_mgr_unregister(mgr);
 
        return 0;
 }
index 06d212a3d49dd6ebdba471aa1814759ff828d1aa..24b25c62603665aee105e394121110c59f65ad91 100644 (file)
@@ -238,6 +238,8 @@ static int altera_ps_probe(struct spi_device *spi)
 {
        struct altera_ps_conf *conf;
        const struct of_device_id *of_id;
+       struct fpga_manager *mgr;
+       int ret;
 
        conf = devm_kzalloc(&spi->dev, sizeof(*conf), GFP_KERNEL);
        if (!conf)
@@ -273,13 +275,25 @@ static int altera_ps_probe(struct spi_device *spi)
        snprintf(conf->mgr_name, sizeof(conf->mgr_name), "%s %s",
                 dev_driver_string(&spi->dev), dev_name(&spi->dev));
 
-       return fpga_mgr_register(&spi->dev, conf->mgr_name,
-                                &altera_ps_ops, conf);
+       mgr = fpga_mgr_create(&spi->dev, conf->mgr_name,
+                             &altera_ps_ops, conf);
+       if (!mgr)
+               return -ENOMEM;
+
+       spi_set_drvdata(spi, mgr);
+
+       ret = fpga_mgr_register(mgr);
+       if (ret)
+               fpga_mgr_free(mgr);
+
+       return ret;
 }
 
 static int altera_ps_remove(struct spi_device *spi)
 {
-       fpga_mgr_unregister(&spi->dev);
+       struct fpga_manager *mgr = spi_get_drvdata(spi);
+
+       fpga_mgr_unregister(mgr);
 
        return 0;
 }
index 9939d2cbc9a6cbca56d5f3e59ce0e068146919dc..0a5181db3e2b78e08f980bc376de49f4110bcb97 100644 (file)
@@ -515,17 +515,17 @@ void fpga_mgr_unlock(struct fpga_manager *mgr)
 EXPORT_SYMBOL_GPL(fpga_mgr_unlock);
 
 /**
- * fpga_mgr_register - register a low level fpga manager driver
+ * fpga_mgr_create - create and initialize a FPGA manager struct
  * @dev:       fpga manager device from pdev
  * @name:      fpga manager name
  * @mops:      pointer to structure of fpga manager ops
  * @priv:      fpga manager private data
  *
- * Return: 0 on success, negative error code otherwise.
+ * Return: pointer to struct fpga_manager or NULL
  */
-int fpga_mgr_register(struct device *dev, const char *name,
-                     const struct fpga_manager_ops *mops,
-                     void *priv)
+struct fpga_manager *fpga_mgr_create(struct device *dev, const char *name,
+                                    const struct fpga_manager_ops *mops,
+                                    void *priv)
 {
        struct fpga_manager *mgr;
        int id, ret;
@@ -534,17 +534,17 @@ int fpga_mgr_register(struct device *dev, const char *name,
            !mops->write_init || (!mops->write && !mops->write_sg) ||
            (mops->write && mops->write_sg)) {
                dev_err(dev, "Attempt to register without fpga_manager_ops\n");
-               return -EINVAL;
+               return NULL;
        }
 
        if (!name || !strlen(name)) {
                dev_err(dev, "Attempt to register with no name!\n");
-               return -EINVAL;
+               return NULL;
        }
 
        mgr = kzalloc(sizeof(*mgr), GFP_KERNEL);
        if (!mgr)
-               return -ENOMEM;
+               return NULL;
 
        id = ida_simple_get(&fpga_mgr_ida, 0, 0, GFP_KERNEL);
        if (id < 0) {
@@ -558,25 +558,56 @@ int fpga_mgr_register(struct device *dev, const char *name,
        mgr->mops = mops;
        mgr->priv = priv;
 
-       /*
-        * Initialize framework state by requesting low level driver read state
-        * from device.  FPGA may be in reset mode or may have been programmed
-        * by bootloader or EEPROM.
-        */
-       mgr->state = mgr->mops->state(mgr);
-
        device_initialize(&mgr->dev);
        mgr->dev.class = fpga_mgr_class;
        mgr->dev.groups = mops->groups;
        mgr->dev.parent = dev;
        mgr->dev.of_node = dev->of_node;
        mgr->dev.id = id;
-       dev_set_drvdata(dev, mgr);
 
        ret = dev_set_name(&mgr->dev, "fpga%d", id);
        if (ret)
                goto error_device;
 
+       return mgr;
+
+error_device:
+       ida_simple_remove(&fpga_mgr_ida, id);
+error_kfree:
+       kfree(mgr);
+
+       return NULL;
+}
+EXPORT_SYMBOL_GPL(fpga_mgr_create);
+
+/**
+ * fpga_mgr_free - deallocate a FPGA manager
+ * @mgr:       fpga manager struct created by fpga_mgr_create
+ */
+void fpga_mgr_free(struct fpga_manager *mgr)
+{
+       ida_simple_remove(&fpga_mgr_ida, mgr->dev.id);
+       kfree(mgr);
+}
+EXPORT_SYMBOL_GPL(fpga_mgr_free);
+
+/**
+ * fpga_mgr_register - register a FPGA manager
+ * @mgr:       fpga manager struct created by fpga_mgr_create
+ *
+ * Return: 0 on success, negative error code otherwise.
+ */
+int fpga_mgr_register(struct fpga_manager *mgr)
+{
+       int ret;
+
+       /*
+        * Initialize framework state by requesting low level driver read state
+        * from device.  FPGA may be in reset mode or may have been programmed
+        * by bootloader or EEPROM.
+        */
+       mgr->state = mgr->mops->state(mgr);
+
        ret = device_add(&mgr->dev);
        if (ret)
                goto error_device;
@@ -586,22 +617,18 @@ int fpga_mgr_register(struct device *dev, const char *name,
        return 0;
 
 error_device:
-       ida_simple_remove(&fpga_mgr_ida, id);
-error_kfree:
-       kfree(mgr);
+       ida_simple_remove(&fpga_mgr_ida, mgr->dev.id);
 
        return ret;
 }
 EXPORT_SYMBOL_GPL(fpga_mgr_register);
 
 /**
- * fpga_mgr_unregister - unregister a low level fpga manager driver
- * @dev:       fpga manager device from pdev
+ * fpga_mgr_unregister - unregister a FPGA manager
+ * @mgr:       fpga manager struct
  */
-void fpga_mgr_unregister(struct device *dev)
+void fpga_mgr_unregister(struct fpga_manager *mgr)
 {
-       struct fpga_manager *mgr = dev_get_drvdata(dev);
-
        dev_info(&mgr->dev, "%s %s\n", __func__, mgr->name);
 
        /*
@@ -619,8 +646,7 @@ static void fpga_mgr_dev_release(struct device *dev)
 {
        struct fpga_manager *mgr = to_fpga_manager(dev);
 
-       ida_simple_remove(&fpga_mgr_ida, mgr->dev.id);
-       kfree(mgr);
+       fpga_mgr_free(mgr);
 }
 
 static int __init fpga_mgr_class_init(void)
index 7fca8202306245ae2707c514acc15c0a2307ae9f..5981c7ee7a7d4d1f6c583c74fcbf18288cf8039c 100644 (file)
@@ -133,6 +133,7 @@ static int ice40_fpga_probe(struct spi_device *spi)
 {
        struct device *dev = &spi->dev;
        struct ice40_fpga_priv *priv;
+       struct fpga_manager *mgr;
        int ret;
 
        priv = devm_kzalloc(&spi->dev, sizeof(*priv), GFP_KERNEL);
@@ -174,14 +175,26 @@ static int ice40_fpga_probe(struct spi_device *spi)
                return ret;
        }
 
-       /* Register with the FPGA manager */
-       return fpga_mgr_register(dev, "Lattice iCE40 FPGA Manager",
-                                &ice40_fpga_ops, priv);
+       mgr = fpga_mgr_create(dev, "Lattice iCE40 FPGA Manager",
+                             &ice40_fpga_ops, priv);
+       if (!mgr)
+               return -ENOMEM;
+
+       spi_set_drvdata(spi, mgr);
+
+       ret = fpga_mgr_register(mgr);
+       if (ret)
+               fpga_mgr_free(mgr);
+
+       return ret;
 }
 
 static int ice40_fpga_remove(struct spi_device *spi)
 {
-       fpga_mgr_unregister(&spi->dev);
+       struct fpga_manager *mgr = spi_get_drvdata(spi);
+
+       fpga_mgr_unregister(mgr);
+
        return 0;
 }
 
index 8e95ec9c5c9aa68be2d57118e00994ce3f8f406d..a582e0000c97aa7967e0c22f7b7e8fdbfdf6f309 100644 (file)
@@ -355,21 +355,33 @@ static const struct fpga_manager_ops machxo2_ops = {
 static int machxo2_spi_probe(struct spi_device *spi)
 {
        struct device *dev = &spi->dev;
+       struct fpga_manager *mgr;
+       int ret;
 
        if (spi->max_speed_hz > MACHXO2_MAX_SPEED) {
                dev_err(dev, "Speed is too high\n");
                return -EINVAL;
        }
 
-       return fpga_mgr_register(dev, "Lattice MachXO2 SPI FPGA Manager",
-                                &machxo2_ops, spi);
+       mgr = fpga_mgr_create(dev, "Lattice MachXO2 SPI FPGA Manager",
+                             &machxo2_ops, spi);
+       if (!mgr)
+               return -ENOMEM;
+
+       spi_set_drvdata(spi, mgr);
+
+       ret = fpga_mgr_register(mgr);
+       if (ret)
+               fpga_mgr_free(mgr);
+
+       return ret;
 }
 
 static int machxo2_spi_remove(struct spi_device *spi)
 {
-       struct device *dev = &spi->dev;
+       struct fpga_manager *mgr = spi_get_drvdata(spi);
 
-       fpga_mgr_unregister(dev);
+       fpga_mgr_unregister(mgr);
 
        return 0;
 }
index a46e343a5b723cd828c54d52815c3ece8afa6ad7..dec3db5cdab1d8b12fee2a5c879cf199856caf20 100644 (file)
@@ -482,6 +482,7 @@ static int socfpga_a10_fpga_probe(struct platform_device *pdev)
        struct device *dev = &pdev->dev;
        struct a10_fpga_priv *priv;
        void __iomem *reg_base;
+       struct fpga_manager *mgr;
        struct resource *res;
        int ret;
 
@@ -519,9 +520,16 @@ static int socfpga_a10_fpga_probe(struct platform_device *pdev)
                return -EBUSY;
        }
 
-       ret = fpga_mgr_register(dev, "SoCFPGA Arria10 FPGA Manager",
-                                &socfpga_a10_fpga_mgr_ops, priv);
+       mgr = fpga_mgr_create(dev, "SoCFPGA Arria10 FPGA Manager",
+                             &socfpga_a10_fpga_mgr_ops, priv);
+       if (!mgr)
+               return -ENOMEM;
+
+       platform_set_drvdata(pdev, mgr);
+
+       ret = fpga_mgr_register(mgr);
        if (ret) {
+               fpga_mgr_free(mgr);
                clk_disable_unprepare(priv->clk);
                return ret;
        }
@@ -534,7 +542,7 @@ static int socfpga_a10_fpga_remove(struct platform_device *pdev)
        struct fpga_manager *mgr = platform_get_drvdata(pdev);
        struct a10_fpga_priv *priv = mgr->priv;
 
-       fpga_mgr_unregister(&pdev->dev);
+       fpga_mgr_unregister(mgr);
        clk_disable_unprepare(priv->clk);
 
        return 0;
index b6672e66cda632e9d26975503a3ec254d2f3f4e3..51efaf9e0e03a5da800c7b04621672a54480feaa 100644 (file)
@@ -555,6 +555,7 @@ static int socfpga_fpga_probe(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
        struct socfpga_fpga_priv *priv;
+       struct fpga_manager *mgr;
        struct resource *res;
        int ret;
 
@@ -581,13 +582,25 @@ static int socfpga_fpga_probe(struct platform_device *pdev)
        if (ret)
                return ret;
 
-       return fpga_mgr_register(dev, "Altera SOCFPGA FPGA Manager",
-                                &socfpga_fpga_ops, priv);
+       mgr = fpga_mgr_create(dev, "Altera SOCFPGA FPGA Manager",
+                             &socfpga_fpga_ops, priv);
+       if (!mgr)
+               return -ENOMEM;
+
+       platform_set_drvdata(pdev, mgr);
+
+       ret = fpga_mgr_register(mgr);
+       if (ret)
+               fpga_mgr_free(mgr);
+
+       return ret;
 }
 
 static int socfpga_fpga_remove(struct platform_device *pdev)
 {
-       fpga_mgr_unregister(&pdev->dev);
+       struct fpga_manager *mgr = platform_get_drvdata(pdev);
+
+       fpga_mgr_unregister(mgr);
 
        return 0;
 }
index f6a96b42e2ca00b0a47c68f50cf03cdc1b3ec582..08efd1895b1bd1d85a04cafbe5d036ea66b41d59 100644 (file)
@@ -116,7 +116,9 @@ static int ts73xx_fpga_probe(struct platform_device *pdev)
 {
        struct device *kdev = &pdev->dev;
        struct ts73xx_fpga_priv *priv;
+       struct fpga_manager *mgr;
        struct resource *res;
+       int ret;
 
        priv = devm_kzalloc(kdev, sizeof(*priv), GFP_KERNEL);
        if (!priv)
@@ -131,13 +133,25 @@ static int ts73xx_fpga_probe(struct platform_device *pdev)
                return PTR_ERR(priv->io_base);
        }
 
-       return fpga_mgr_register(kdev, "TS-73xx FPGA Manager",
-                                &ts73xx_fpga_ops, priv);
+       mgr = fpga_mgr_create(kdev, "TS-73xx FPGA Manager",
+                             &ts73xx_fpga_ops, priv);
+       if (!mgr)
+               return -ENOMEM;
+
+       platform_set_drvdata(pdev, mgr);
+
+       ret = fpga_mgr_register(mgr);
+       if (ret)
+               fpga_mgr_free(mgr);
+
+       return ret;
 }
 
 static int ts73xx_fpga_remove(struct platform_device *pdev)
 {
-       fpga_mgr_unregister(&pdev->dev);
+       struct fpga_manager *mgr = platform_get_drvdata(pdev);
+
+       fpga_mgr_unregister(mgr);
 
        return 0;
 }
index 9b62a4c2a3df6a0b9968f50f5a30d4cb39446399..8d19459665337d6234cce981f9bd949e0617a5e4 100644 (file)
@@ -143,6 +143,8 @@ static const struct fpga_manager_ops xilinx_spi_ops = {
 static int xilinx_spi_probe(struct spi_device *spi)
 {
        struct xilinx_spi_conf *conf;
+       struct fpga_manager *mgr;
+       int ret;
 
        conf = devm_kzalloc(&spi->dev, sizeof(*conf), GFP_KERNEL);
        if (!conf)
@@ -165,13 +167,25 @@ static int xilinx_spi_probe(struct spi_device *spi)
                return PTR_ERR(conf->done);
        }
 
-       return fpga_mgr_register(&spi->dev, "Xilinx Slave Serial FPGA Manager",
-                                &xilinx_spi_ops, conf);
+       mgr = fpga_mgr_create(&spi->dev, "Xilinx Slave Serial FPGA Manager",
+                             &xilinx_spi_ops, conf);
+       if (!mgr)
+               return -ENOMEM;
+
+       spi_set_drvdata(spi, mgr);
+
+       ret = fpga_mgr_register(mgr);
+       if (ret)
+               fpga_mgr_free(mgr);
+
+       return ret;
 }
 
 static int xilinx_spi_remove(struct spi_device *spi)
 {
-       fpga_mgr_unregister(&spi->dev);
+       struct fpga_manager *mgr = spi_get_drvdata(spi);
+
+       fpga_mgr_unregister(mgr);
 
        return 0;
 }
index 70b15b3034714c9b059cae0c33a9ede494de99df..3110e00121ca0fa6aa80fc29b6c9e1a1f5290e3d 100644 (file)
@@ -558,6 +558,7 @@ static int zynq_fpga_probe(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
        struct zynq_fpga_priv *priv;
+       struct fpga_manager *mgr;
        struct resource *res;
        int err;
 
@@ -613,10 +614,17 @@ static int zynq_fpga_probe(struct platform_device *pdev)
 
        clk_disable(priv->clk);
 
-       err = fpga_mgr_register(dev, "Xilinx Zynq FPGA Manager",
-                               &zynq_fpga_ops, priv);
+       mgr = fpga_mgr_create(dev, "Xilinx Zynq FPGA Manager",
+                             &zynq_fpga_ops, priv);
+       if (!mgr)
+               return -ENOMEM;
+
+       platform_set_drvdata(pdev, mgr);
+
+       err = fpga_mgr_register(mgr);
        if (err) {
                dev_err(dev, "unable to register FPGA manager\n");
+               fpga_mgr_free(mgr);
                clk_unprepare(priv->clk);
                return err;
        }
@@ -632,7 +640,7 @@ static int zynq_fpga_remove(struct platform_device *pdev)
        mgr = platform_get_drvdata(pdev);
        priv = mgr->priv;
 
-       fpga_mgr_unregister(&pdev->dev);
+       fpga_mgr_unregister(mgr);
 
        clk_unprepare(priv->clk);
 
index 3c6de23aabdfd27e471dbcf4ba679a297152990d..1266c1108e70ace1e4250225b64009fc055ff10e 100644 (file)
@@ -170,9 +170,11 @@ struct fpga_manager *fpga_mgr_get(struct device *dev);
 
 void fpga_mgr_put(struct fpga_manager *mgr);
 
-int fpga_mgr_register(struct device *dev, const char *name,
-                     const struct fpga_manager_ops *mops, void *priv);
-
-void fpga_mgr_unregister(struct device *dev);
+struct fpga_manager *fpga_mgr_create(struct device *dev, const char *name,
+                                    const struct fpga_manager_ops *mops,
+                                    void *priv);
+void fpga_mgr_free(struct fpga_manager *mgr);
+int fpga_mgr_register(struct fpga_manager *mgr);
+void fpga_mgr_unregister(struct fpga_manager *mgr);
 
 #endif /*_LINUX_FPGA_MGR_H */