* [PATCH v2 0/8] fpga: add devm managed create APIs
@ 2018-09-04 21:22 Alan Tull
2018-09-04 21:22 ` [PATCH v2 1/8] fpga: do not access region struct after fpga_region_unregister Alan Tull
` (7 more replies)
0 siblings, 8 replies; 19+ messages in thread
From: Alan Tull @ 2018-09-04 21:22 UTC (permalink / raw)
To: Moritz Fischer, Jonathan Corbet
Cc: Randy Dunlap, linux-kernel, linux-fpga, linux-doc, Alan Tull
Fix one functional FPGA bug.
Implement managed devm_fpga_(mgr|bridge|region)_create() functions.
More documentation cleanup to make the documentation more helpful
and to emphasize the use of FPGA regions for FPGA programming.
Fix a few minor documentation corrections.
v2: Add Suggested-by
Documentation changes from review comments
Alan Tull (8):
fpga: do not access region struct after fpga_region_unregister
fpga: mgr: add devm_fpga_mgr_create
fpga: bridge: add devm_fpga_bridge_create
fpga: add devm_fpga_region_create
dt-bindings: fpga: fix freeze controller compatible in region doc
fpga: bridge: fix obvious function documentation error
docs: fpga: document fpga manager flags
docs: fpga: document programming fpgas using regions
.../devicetree/bindings/fpga/fpga-region.txt | 4 +-
Documentation/driver-api/fpga/fpga-bridge.rst | 37 ++-----
Documentation/driver-api/fpga/fpga-mgr.rst | 121 +++------------------
Documentation/driver-api/fpga/fpga-programming.rst | 107 ++++++++++++++++++
Documentation/driver-api/fpga/fpga-region.rst | 91 ++++++++--------
Documentation/driver-api/fpga/index.rst | 2 +
Documentation/driver-api/fpga/intro.rst | 2 +-
drivers/fpga/altera-cvp.c | 8 +-
drivers/fpga/altera-fpga2sdram.c | 8 +-
drivers/fpga/altera-freeze-bridge.c | 13 +--
drivers/fpga/altera-hps2fpga.c | 7 +-
drivers/fpga/altera-pr-ip-core.c | 9 +-
drivers/fpga/altera-ps-spi.c | 11 +-
drivers/fpga/dfl-fme-br.c | 11 +-
drivers/fpga/dfl-fme-mgr.c | 11 +-
drivers/fpga/dfl-fme-region.c | 10 +-
drivers/fpga/dfl.c | 6 +-
drivers/fpga/fpga-bridge.c | 74 +++++++++++--
drivers/fpga/fpga-mgr.c | 67 ++++++++++--
drivers/fpga/fpga-region.c | 68 ++++++++++--
drivers/fpga/ice40-spi.c | 10 +-
drivers/fpga/machxo2-spi.c | 11 +-
drivers/fpga/of-fpga-region.c | 9 +-
drivers/fpga/socfpga-a10.c | 5 +-
drivers/fpga/socfpga.c | 10 +-
drivers/fpga/ts73xx-fpga.c | 11 +-
drivers/fpga/xilinx-pr-decoupler.c | 4 +-
drivers/fpga/xilinx-spi.c | 12 +-
drivers/fpga/zynq-fpga.c | 5 +-
include/linux/fpga/fpga-bridge.h | 4 +
include/linux/fpga/fpga-mgr.h | 24 +++-
include/linux/fpga/fpga-region.h | 4 +
32 files changed, 444 insertions(+), 332 deletions(-)
create mode 100644 Documentation/driver-api/fpga/fpga-programming.rst
--
2.7.4
^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH v2 1/8] fpga: do not access region struct after fpga_region_unregister
2018-09-04 21:22 [PATCH v2 0/8] fpga: add devm managed create APIs Alan Tull
@ 2018-09-04 21:22 ` Alan Tull
2018-09-04 23:41 ` Moritz Fischer
2018-09-04 21:22 ` [PATCH v2 2/8] fpga: mgr: add devm_fpga_mgr_create Alan Tull
` (6 subsequent siblings)
7 siblings, 1 reply; 19+ messages in thread
From: Alan Tull @ 2018-09-04 21:22 UTC (permalink / raw)
To: Moritz Fischer, Jonathan Corbet
Cc: Randy Dunlap, linux-kernel, linux-fpga, linux-doc, Alan Tull
A couple drivers were accessing the region struct after it had been
freed. Save off the pointer to the mgr before the region struct gets
freed.
Signed-off-by: Alan Tull <atull@kernel.org>
---
v2: no change in v2 of patchset
---
drivers/fpga/dfl-fme-region.c | 4 +++-
drivers/fpga/of-fpga-region.c | 3 ++-
2 files changed, 5 insertions(+), 2 deletions(-)
diff --git a/drivers/fpga/dfl-fme-region.c b/drivers/fpga/dfl-fme-region.c
index 0b7e19c..51a5ac2 100644
--- a/drivers/fpga/dfl-fme-region.c
+++ b/drivers/fpga/dfl-fme-region.c
@@ -14,6 +14,7 @@
*/
#include <linux/module.h>
+#include <linux/fpga/fpga-mgr.h>
#include <linux/fpga/fpga-region.h>
#include "dfl-fme-pr.h"
@@ -66,9 +67,10 @@ static int fme_region_probe(struct platform_device *pdev)
static int fme_region_remove(struct platform_device *pdev)
{
struct fpga_region *region = dev_get_drvdata(&pdev->dev);
+ struct fpga_manager *mgr = region->mgr;
fpga_region_unregister(region);
- fpga_mgr_put(region->mgr);
+ fpga_mgr_put(mgr);
return 0;
}
diff --git a/drivers/fpga/of-fpga-region.c b/drivers/fpga/of-fpga-region.c
index 35fabb8..052a134 100644
--- a/drivers/fpga/of-fpga-region.c
+++ b/drivers/fpga/of-fpga-region.c
@@ -437,9 +437,10 @@ static int of_fpga_region_probe(struct platform_device *pdev)
static int of_fpga_region_remove(struct platform_device *pdev)
{
struct fpga_region *region = platform_get_drvdata(pdev);
+ struct fpga_manager *mgr = region->mgr;
fpga_region_unregister(region);
- fpga_mgr_put(region->mgr);
+ fpga_mgr_put(mgr);
return 0;
}
--
2.7.4
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH v2 2/8] fpga: mgr: add devm_fpga_mgr_create
2018-09-04 21:22 [PATCH v2 0/8] fpga: add devm managed create APIs Alan Tull
2018-09-04 21:22 ` [PATCH v2 1/8] fpga: do not access region struct after fpga_region_unregister Alan Tull
@ 2018-09-04 21:22 ` Alan Tull
2018-09-04 21:22 ` [PATCH v2 3/8] fpga: bridge: add devm_fpga_bridge_create Alan Tull
` (5 subsequent siblings)
7 siblings, 0 replies; 19+ messages in thread
From: Alan Tull @ 2018-09-04 21:22 UTC (permalink / raw)
To: Moritz Fischer, Jonathan Corbet
Cc: Randy Dunlap, linux-kernel, linux-fpga, linux-doc, Alan Tull
Add devm_fpga_mgr_create() which is the managed
version of fpga_mgr_create().
Change current FPGA manager drivers to use
devm_fpga_mgr_create()
Signed-off-by: Alan Tull <atull@kernel.org>
Suggested-by: Federico Vaga <federico.vaga@cern.ch>
---
v2: add suggested-by
---
Documentation/driver-api/fpga/fpga-mgr.rst | 13 +++---
drivers/fpga/altera-cvp.c | 8 ++--
drivers/fpga/altera-pr-ip-core.c | 9 +---
drivers/fpga/altera-ps-spi.c | 11 ++---
drivers/fpga/dfl-fme-mgr.c | 11 ++---
drivers/fpga/fpga-mgr.c | 67 ++++++++++++++++++++++++++----
drivers/fpga/ice40-spi.c | 10 ++---
drivers/fpga/machxo2-spi.c | 11 ++---
drivers/fpga/socfpga-a10.c | 5 +--
drivers/fpga/socfpga.c | 10 ++---
drivers/fpga/ts73xx-fpga.c | 11 ++---
drivers/fpga/xilinx-spi.c | 12 ++----
drivers/fpga/zynq-fpga.c | 5 +--
include/linux/fpga/fpga-mgr.h | 4 ++
14 files changed, 100 insertions(+), 87 deletions(-)
diff --git a/Documentation/driver-api/fpga/fpga-mgr.rst b/Documentation/driver-api/fpga/fpga-mgr.rst
index 4b3825d..431556d 100644
--- a/Documentation/driver-api/fpga/fpga-mgr.rst
+++ b/Documentation/driver-api/fpga/fpga-mgr.rst
@@ -49,18 +49,14 @@ probe function calls fpga_mgr_register(), such as::
* them in priv
*/
- mgr = fpga_mgr_create(dev, "Altera SOCFPGA FPGA Manager",
- &socfpga_fpga_ops, priv);
+ mgr = devm_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;
+ return fpga_mgr_register(mgr);
}
static int socfpga_fpga_remove(struct platform_device *pdev)
@@ -170,6 +166,9 @@ API for implementing a new FPGA Manager driver
:functions: fpga_manager_ops
.. kernel-doc:: drivers/fpga/fpga-mgr.c
+ :functions: devm_fpga_mgr_create
+
+.. kernel-doc:: drivers/fpga/fpga-mgr.c
:functions: fpga_mgr_create
.. kernel-doc:: drivers/fpga/fpga-mgr.c
diff --git a/drivers/fpga/altera-cvp.c b/drivers/fpga/altera-cvp.c
index 7fa7936..610a155 100644
--- a/drivers/fpga/altera-cvp.c
+++ b/drivers/fpga/altera-cvp.c
@@ -453,8 +453,8 @@ 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));
- mgr = fpga_mgr_create(&pdev->dev, conf->mgr_name,
- &altera_cvp_ops, conf);
+ mgr = devm_fpga_mgr_create(&pdev->dev, conf->mgr_name,
+ &altera_cvp_ops, conf);
if (!mgr) {
ret = -ENOMEM;
goto err_unmap;
@@ -463,10 +463,8 @@ static int altera_cvp_probe(struct pci_dev *pdev,
pci_set_drvdata(pdev, mgr);
ret = fpga_mgr_register(mgr);
- if (ret) {
- fpga_mgr_free(mgr);
+ if (ret)
goto err_unmap;
- }
ret = driver_create_file(&altera_cvp_driver.driver,
&driver_attr_chkcfg);
diff --git a/drivers/fpga/altera-pr-ip-core.c b/drivers/fpga/altera-pr-ip-core.c
index 65e0b6a..a7a3bf0 100644
--- a/drivers/fpga/altera-pr-ip-core.c
+++ b/drivers/fpga/altera-pr-ip-core.c
@@ -177,7 +177,6 @@ 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);
@@ -192,17 +191,13 @@ 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));
- mgr = fpga_mgr_create(dev, dev_name(dev), &alt_pr_ops, priv);
+ mgr = devm_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;
+ return fpga_mgr_register(mgr);
}
EXPORT_SYMBOL_GPL(alt_pr_register);
diff --git a/drivers/fpga/altera-ps-spi.c b/drivers/fpga/altera-ps-spi.c
index 24b25c6..33aafda 100644
--- a/drivers/fpga/altera-ps-spi.c
+++ b/drivers/fpga/altera-ps-spi.c
@@ -239,7 +239,6 @@ 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)
@@ -275,18 +274,14 @@ 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));
- mgr = fpga_mgr_create(&spi->dev, conf->mgr_name,
- &altera_ps_ops, conf);
+ mgr = devm_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;
+ return fpga_mgr_register(mgr);
}
static int altera_ps_remove(struct spi_device *spi)
diff --git a/drivers/fpga/dfl-fme-mgr.c b/drivers/fpga/dfl-fme-mgr.c
index b5ef405..617ce0b 100644
--- a/drivers/fpga/dfl-fme-mgr.c
+++ b/drivers/fpga/dfl-fme-mgr.c
@@ -287,7 +287,6 @@ static int fme_mgr_probe(struct platform_device *pdev)
struct fme_mgr_priv *priv;
struct fpga_manager *mgr;
struct resource *res;
- int ret;
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
@@ -309,19 +308,15 @@ static int fme_mgr_probe(struct platform_device *pdev)
fme_mgr_get_compat_id(priv->ioaddr, compat_id);
- mgr = fpga_mgr_create(dev, "DFL FME FPGA Manager",
- &fme_mgr_ops, priv);
+ mgr = devm_fpga_mgr_create(dev, "DFL FME FPGA Manager",
+ &fme_mgr_ops, priv);
if (!mgr)
return -ENOMEM;
mgr->compat_id = compat_id;
platform_set_drvdata(pdev, mgr);
- ret = fpga_mgr_register(mgr);
- if (ret)
- fpga_mgr_free(mgr);
-
- return ret;
+ return fpga_mgr_register(mgr);
}
static int fme_mgr_remove(struct platform_device *pdev)
diff --git a/drivers/fpga/fpga-mgr.c b/drivers/fpga/fpga-mgr.c
index a41b07e..c8684bc 100644
--- a/drivers/fpga/fpga-mgr.c
+++ b/drivers/fpga/fpga-mgr.c
@@ -558,6 +558,9 @@ EXPORT_SYMBOL_GPL(fpga_mgr_unlock);
* @mops: pointer to structure of fpga manager ops
* @priv: fpga manager private data
*
+ * The caller of this function is responsible for freeing the struct with
+ * fpga_mgr_free(). Using devm_fpga_mgr_create() instead is recommended.
+ *
* Return: pointer to struct fpga_manager or NULL
*/
struct fpga_manager *fpga_mgr_create(struct device *dev, const char *name,
@@ -618,8 +621,8 @@ struct fpga_manager *fpga_mgr_create(struct device *dev, const char *name,
EXPORT_SYMBOL_GPL(fpga_mgr_create);
/**
- * fpga_mgr_free - deallocate a FPGA manager
- * @mgr: fpga manager struct created by fpga_mgr_create
+ * fpga_mgr_free - free a FPGA manager created with fpga_mgr_create()
+ * @mgr: fpga manager struct
*/
void fpga_mgr_free(struct fpga_manager *mgr)
{
@@ -628,9 +631,55 @@ void fpga_mgr_free(struct fpga_manager *mgr)
}
EXPORT_SYMBOL_GPL(fpga_mgr_free);
+static void devm_fpga_mgr_release(struct device *dev, void *res)
+{
+ struct fpga_manager *mgr = *(struct fpga_manager **)res;
+
+ fpga_mgr_free(mgr);
+}
+
+/**
+ * devm_fpga_mgr_create - create and initialize a managed 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
+ *
+ * This function is intended for use in a FPGA manager driver's probe function.
+ * After the manager driver creates the manager struct with
+ * devm_fpga_mgr_create(), it should register it with fpga_mgr_register(). The
+ * manager driver's remove function should call fpga_mgr_unregister(). The
+ * manager 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_mgr_register(), the struct will still get cleaned up.
+ *
+ * Return: pointer to struct fpga_manager or NULL
+ */
+struct fpga_manager *devm_fpga_mgr_create(struct device *dev, const char *name,
+ const struct fpga_manager_ops *mops,
+ void *priv)
+{
+ struct fpga_manager **ptr, *mgr;
+
+ ptr = devres_alloc(devm_fpga_mgr_release, sizeof(*ptr), GFP_KERNEL);
+ if (!ptr)
+ return NULL;
+
+ mgr = fpga_mgr_create(dev, name, mops, priv);
+ if (!mgr) {
+ devres_free(ptr);
+ } else {
+ *ptr = mgr;
+ devres_add(dev, ptr);
+ }
+
+ return mgr;
+}
+EXPORT_SYMBOL_GPL(devm_fpga_mgr_create);
+
/**
* fpga_mgr_register - register a FPGA manager
- * @mgr: fpga manager struct created by fpga_mgr_create
+ * @mgr: fpga manager struct
*
* Return: 0 on success, negative error code otherwise.
*/
@@ -661,8 +710,13 @@ int fpga_mgr_register(struct fpga_manager *mgr)
EXPORT_SYMBOL_GPL(fpga_mgr_register);
/**
- * fpga_mgr_unregister - unregister and free a FPGA manager
- * @mgr: fpga manager struct
+ * fpga_mgr_unregister - unregister a FPGA manager
+ * @mgr: fpga manager struct
+ *
+ * This function is intended for use in a FPGA manager driver's remove function.
+ * If the manager was created by devm_fpga_mgr_create(), it will be
+ * automatically freed. If the manager was created by fpga_mgr_create(), the
+ * caller is responsible for freeing it with fpga_mgr_free().
*/
void fpga_mgr_unregister(struct fpga_manager *mgr)
{
@@ -681,9 +735,6 @@ EXPORT_SYMBOL_GPL(fpga_mgr_unregister);
static void fpga_mgr_dev_release(struct device *dev)
{
- struct fpga_manager *mgr = to_fpga_manager(dev);
-
- fpga_mgr_free(mgr);
}
static int __init fpga_mgr_class_init(void)
diff --git a/drivers/fpga/ice40-spi.c b/drivers/fpga/ice40-spi.c
index 5981c7e..6154661 100644
--- a/drivers/fpga/ice40-spi.c
+++ b/drivers/fpga/ice40-spi.c
@@ -175,18 +175,14 @@ static int ice40_fpga_probe(struct spi_device *spi)
return ret;
}
- mgr = fpga_mgr_create(dev, "Lattice iCE40 FPGA Manager",
- &ice40_fpga_ops, priv);
+ mgr = devm_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;
+ return fpga_mgr_register(mgr);
}
static int ice40_fpga_remove(struct spi_device *spi)
diff --git a/drivers/fpga/machxo2-spi.c b/drivers/fpga/machxo2-spi.c
index a582e00..4d8a876 100644
--- a/drivers/fpga/machxo2-spi.c
+++ b/drivers/fpga/machxo2-spi.c
@@ -356,25 +356,20 @@ 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;
}
- mgr = fpga_mgr_create(dev, "Lattice MachXO2 SPI FPGA Manager",
- &machxo2_ops, spi);
+ mgr = devm_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;
+ return fpga_mgr_register(mgr);
}
static int machxo2_spi_remove(struct spi_device *spi)
diff --git a/drivers/fpga/socfpga-a10.c b/drivers/fpga/socfpga-a10.c
index be30c48..573d88b 100644
--- a/drivers/fpga/socfpga-a10.c
+++ b/drivers/fpga/socfpga-a10.c
@@ -508,8 +508,8 @@ static int socfpga_a10_fpga_probe(struct platform_device *pdev)
return -EBUSY;
}
- mgr = fpga_mgr_create(dev, "SoCFPGA Arria10 FPGA Manager",
- &socfpga_a10_fpga_mgr_ops, priv);
+ mgr = devm_fpga_mgr_create(dev, "SoCFPGA Arria10 FPGA Manager",
+ &socfpga_a10_fpga_mgr_ops, priv);
if (!mgr)
return -ENOMEM;
@@ -517,7 +517,6 @@ static int socfpga_a10_fpga_probe(struct platform_device *pdev)
ret = fpga_mgr_register(mgr);
if (ret) {
- fpga_mgr_free(mgr);
clk_disable_unprepare(priv->clk);
return ret;
}
diff --git a/drivers/fpga/socfpga.c b/drivers/fpga/socfpga.c
index 959d71f..4a8a2fc 100644
--- a/drivers/fpga/socfpga.c
+++ b/drivers/fpga/socfpga.c
@@ -571,18 +571,14 @@ static int socfpga_fpga_probe(struct platform_device *pdev)
if (ret)
return ret;
- mgr = fpga_mgr_create(dev, "Altera SOCFPGA FPGA Manager",
- &socfpga_fpga_ops, priv);
+ mgr = devm_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;
+ return fpga_mgr_register(mgr);
}
static int socfpga_fpga_remove(struct platform_device *pdev)
diff --git a/drivers/fpga/ts73xx-fpga.c b/drivers/fpga/ts73xx-fpga.c
index 08efd18..dc22a58 100644
--- a/drivers/fpga/ts73xx-fpga.c
+++ b/drivers/fpga/ts73xx-fpga.c
@@ -118,7 +118,6 @@ static int ts73xx_fpga_probe(struct platform_device *pdev)
struct ts73xx_fpga_priv *priv;
struct fpga_manager *mgr;
struct resource *res;
- int ret;
priv = devm_kzalloc(kdev, sizeof(*priv), GFP_KERNEL);
if (!priv)
@@ -133,18 +132,14 @@ static int ts73xx_fpga_probe(struct platform_device *pdev)
return PTR_ERR(priv->io_base);
}
- mgr = fpga_mgr_create(kdev, "TS-73xx FPGA Manager",
- &ts73xx_fpga_ops, priv);
+ mgr = devm_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;
+ return fpga_mgr_register(mgr);
}
static int ts73xx_fpga_remove(struct platform_device *pdev)
diff --git a/drivers/fpga/xilinx-spi.c b/drivers/fpga/xilinx-spi.c
index 8d19459..469486b 100644
--- a/drivers/fpga/xilinx-spi.c
+++ b/drivers/fpga/xilinx-spi.c
@@ -144,7 +144,6 @@ 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)
@@ -167,18 +166,15 @@ static int xilinx_spi_probe(struct spi_device *spi)
return PTR_ERR(conf->done);
}
- mgr = fpga_mgr_create(&spi->dev, "Xilinx Slave Serial FPGA Manager",
- &xilinx_spi_ops, conf);
+ mgr = devm_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;
+ return fpga_mgr_register(mgr);
}
static int xilinx_spi_remove(struct spi_device *spi)
diff --git a/drivers/fpga/zynq-fpga.c b/drivers/fpga/zynq-fpga.c
index 3110e00..bb82efe 100644
--- a/drivers/fpga/zynq-fpga.c
+++ b/drivers/fpga/zynq-fpga.c
@@ -614,8 +614,8 @@ static int zynq_fpga_probe(struct platform_device *pdev)
clk_disable(priv->clk);
- mgr = fpga_mgr_create(dev, "Xilinx Zynq FPGA Manager",
- &zynq_fpga_ops, priv);
+ mgr = devm_fpga_mgr_create(dev, "Xilinx Zynq FPGA Manager",
+ &zynq_fpga_ops, priv);
if (!mgr)
return -ENOMEM;
@@ -624,7 +624,6 @@ static int zynq_fpga_probe(struct platform_device *pdev)
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;
}
diff --git a/include/linux/fpga/fpga-mgr.h b/include/linux/fpga/fpga-mgr.h
index 8942e61..1ca02ce 100644
--- a/include/linux/fpga/fpga-mgr.h
+++ b/include/linux/fpga/fpga-mgr.h
@@ -190,4 +190,8 @@ void fpga_mgr_free(struct fpga_manager *mgr);
int fpga_mgr_register(struct fpga_manager *mgr);
void fpga_mgr_unregister(struct fpga_manager *mgr);
+struct fpga_manager *devm_fpga_mgr_create(struct device *dev, const char *name,
+ const struct fpga_manager_ops *mops,
+ void *priv);
+
#endif /*_LINUX_FPGA_MGR_H */
--
2.7.4
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH v2 3/8] fpga: bridge: add devm_fpga_bridge_create
2018-09-04 21:22 [PATCH v2 0/8] fpga: add devm managed create APIs Alan Tull
2018-09-04 21:22 ` [PATCH v2 1/8] fpga: do not access region struct after fpga_region_unregister Alan Tull
2018-09-04 21:22 ` [PATCH v2 2/8] fpga: mgr: add devm_fpga_mgr_create Alan Tull
@ 2018-09-04 21:22 ` Alan Tull
2018-09-05 15:22 ` Moritz Fischer
2018-09-04 21:22 ` [PATCH v2 4/8] fpga: add devm_fpga_region_create Alan Tull
` (4 subsequent siblings)
7 siblings, 1 reply; 19+ messages in thread
From: Alan Tull @ 2018-09-04 21:22 UTC (permalink / raw)
To: Moritz Fischer, Jonathan Corbet
Cc: Randy Dunlap, linux-kernel, linux-fpga, linux-doc, Alan Tull
Add devm_fpga_bridge_create() which is the managed
version of fpga_bridge_create().
Change current bridge drivers to use
devm_fpga_bridge_create().
Signed-off-by: Alan Tull <atull@kernel.org>
Suggested-by: Federico Vaga <federico.vaga@cern.ch>
---
v2: add suggested-by
---
Documentation/driver-api/fpga/fpga-bridge.rst | 3 ++
drivers/fpga/altera-fpga2sdram.c | 8 ++-
drivers/fpga/altera-freeze-bridge.c | 13 ++---
drivers/fpga/altera-hps2fpga.c | 7 ++-
drivers/fpga/dfl-fme-br.c | 11 ++--
drivers/fpga/fpga-bridge.c | 72 +++++++++++++++++++++++----
drivers/fpga/xilinx-pr-decoupler.c | 4 +-
include/linux/fpga/fpga-bridge.h | 4 ++
8 files changed, 84 insertions(+), 38 deletions(-)
diff --git a/Documentation/driver-api/fpga/fpga-bridge.rst b/Documentation/driver-api/fpga/fpga-bridge.rst
index 2c2aaca..ebbcbde 100644
--- a/Documentation/driver-api/fpga/fpga-bridge.rst
+++ b/Documentation/driver-api/fpga/fpga-bridge.rst
@@ -11,6 +11,9 @@ API to implement a new FPGA bridge
: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_create
.. kernel-doc:: drivers/fpga/fpga-bridge.c
diff --git a/drivers/fpga/altera-fpga2sdram.c b/drivers/fpga/altera-fpga2sdram.c
index 23660cc..a78e49c 100644
--- a/drivers/fpga/altera-fpga2sdram.c
+++ b/drivers/fpga/altera-fpga2sdram.c
@@ -121,18 +121,16 @@ 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 = fpga_bridge_create(dev, F2S_BRIDGE_NAME,
- &altera_fpga2sdram_br_ops, priv);
+ br = devm_fpga_bridge_create(dev, F2S_BRIDGE_NAME,
+ &altera_fpga2sdram_br_ops, priv);
if (!br)
return -ENOMEM;
platform_set_drvdata(pdev, br);
ret = fpga_bridge_register(br);
- if (ret) {
- fpga_bridge_free(br);
+ if (ret)
return ret;
- }
dev_info(dev, "driver initialized with handoff %08x\n", priv->mask);
diff --git a/drivers/fpga/altera-freeze-bridge.c b/drivers/fpga/altera-freeze-bridge.c
index ffd586c..dd58c4a 100644
--- a/drivers/fpga/altera-freeze-bridge.c
+++ b/drivers/fpga/altera-freeze-bridge.c
@@ -213,7 +213,6 @@ static int altera_freeze_br_probe(struct platform_device *pdev)
struct fpga_bridge *br;
struct resource *res;
u32 status, revision;
- int ret;
if (!np)
return -ENODEV;
@@ -245,20 +244,14 @@ static int altera_freeze_br_probe(struct platform_device *pdev)
priv->base_addr = base_addr;
- br = fpga_bridge_create(dev, FREEZE_BRIDGE_NAME,
- &altera_freeze_br_br_ops, priv);
+ br = devm_fpga_bridge_create(dev, FREEZE_BRIDGE_NAME,
+ &altera_freeze_br_br_ops, priv);
if (!br)
return -ENOMEM;
platform_set_drvdata(pdev, br);
- ret = fpga_bridge_register(br);
- if (ret) {
- fpga_bridge_free(br);
- return ret;
- }
-
- return 0;
+ return fpga_bridge_register(br);
}
static int altera_freeze_br_remove(struct platform_device *pdev)
diff --git a/drivers/fpga/altera-hps2fpga.c b/drivers/fpga/altera-hps2fpga.c
index a974d3f..77b95f2 100644
--- a/drivers/fpga/altera-hps2fpga.c
+++ b/drivers/fpga/altera-hps2fpga.c
@@ -180,7 +180,8 @@ static int alt_fpga_bridge_probe(struct platform_device *pdev)
}
}
- br = fpga_bridge_create(dev, priv->name, &altera_hps2fpga_br_ops, priv);
+ br = devm_fpga_bridge_create(dev, priv->name,
+ &altera_hps2fpga_br_ops, priv);
if (!br) {
ret = -ENOMEM;
goto err;
@@ -190,12 +191,10 @@ static int alt_fpga_bridge_probe(struct platform_device *pdev)
ret = fpga_bridge_register(br);
if (ret)
- goto err_free;
+ goto err;
return 0;
-err_free:
- fpga_bridge_free(br);
err:
clk_disable_unprepare(priv->clk);
diff --git a/drivers/fpga/dfl-fme-br.c b/drivers/fpga/dfl-fme-br.c
index 7cc041d..3ff9f3a 100644
--- a/drivers/fpga/dfl-fme-br.c
+++ b/drivers/fpga/dfl-fme-br.c
@@ -61,7 +61,6 @@ static int fme_br_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
struct fme_br_priv *priv;
struct fpga_bridge *br;
- int ret;
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
@@ -69,18 +68,14 @@ static int fme_br_probe(struct platform_device *pdev)
priv->pdata = dev_get_platdata(dev);
- br = fpga_bridge_create(dev, "DFL FPGA FME Bridge",
- &fme_bridge_ops, priv);
+ br = devm_fpga_bridge_create(dev, "DFL FPGA FME Bridge",
+ &fme_bridge_ops, priv);
if (!br)
return -ENOMEM;
platform_set_drvdata(pdev, br);
- ret = fpga_bridge_register(br);
- if (ret)
- fpga_bridge_free(br);
-
- return ret;
+ return fpga_bridge_register(br);
}
static int fme_br_remove(struct platform_device *pdev)
diff --git a/drivers/fpga/fpga-bridge.c b/drivers/fpga/fpga-bridge.c
index 24b8f98..c39d35f 100644
--- a/drivers/fpga/fpga-bridge.c
+++ b/drivers/fpga/fpga-bridge.c
@@ -324,6 +324,9 @@ ATTRIBUTE_GROUPS(fpga_bridge);
* @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
*/
struct fpga_bridge *fpga_bridge_create(struct device *dev, const char *name,
@@ -378,8 +381,8 @@ struct fpga_bridge *fpga_bridge_create(struct device *dev, const char *name,
EXPORT_SYMBOL_GPL(fpga_bridge_create);
/**
- * fpga_bridge_free - free a fpga bridge and its id
- * @bridge: FPGA bridge struct created by fpga_bridge_create
+ * fpga_bridge_free - free a fpga bridge created by fpga_bridge_create()
+ * @bridge: FPGA bridge struct
*/
void fpga_bridge_free(struct fpga_bridge *bridge)
{
@@ -388,9 +391,56 @@ void fpga_bridge_free(struct fpga_bridge *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);
+}
+
/**
- * fpga_bridge_register - register a fpga bridge
- * @bridge: FPGA bridge struct created by fpga_bridge_create
+ * devm_fpga_bridge_create - create and init a managed struct fpga_bridge
+ * @dev: 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 a 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 *dev, 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(dev, name, br_ops, priv);
+ if (!bridge) {
+ devres_free(ptr);
+ } else {
+ *ptr = bridge;
+ devres_add(dev, ptr);
+ }
+
+ return bridge;
+}
+EXPORT_SYMBOL_GPL(devm_fpga_bridge_create);
+
+/**
+ * fpga_bridge_register - register a FPGA bridge
+ *
+ * @bridge: FPGA bridge struct
*
* Return: 0 for success, error code otherwise.
*/
@@ -412,8 +462,15 @@ int fpga_bridge_register(struct fpga_bridge *bridge)
EXPORT_SYMBOL_GPL(fpga_bridge_register);
/**
- * fpga_bridge_unregister - unregister and free a fpga bridge
- * @bridge: FPGA bridge struct created by fpga_bridge_create
+ * fpga_bridge_unregister - unregister a FPGA bridge
+ *
+ * @bridge: FPGA bridge struct
+ *
+ * This function is intended for use in a FPGA bridge driver's remove function.
+ * If the bridge was created with devm_fpga_bridge_create(), the bridge struct
+ * will be automatically freed. If the bridge was created with
+ * fpga_bridge_create(), the caller is responsible for freeing the bridge with
+ * fpga_bridge_free().
*/
void fpga_bridge_unregister(struct fpga_bridge *bridge)
{
@@ -430,9 +487,6 @@ EXPORT_SYMBOL_GPL(fpga_bridge_unregister);
static void fpga_bridge_dev_release(struct device *dev)
{
- struct fpga_bridge *bridge = to_fpga_bridge(dev);
-
- fpga_bridge_free(bridge);
}
static int __init fpga_bridge_dev_init(void)
diff --git a/drivers/fpga/xilinx-pr-decoupler.c b/drivers/fpga/xilinx-pr-decoupler.c
index 07ba153..6410361 100644
--- a/drivers/fpga/xilinx-pr-decoupler.c
+++ b/drivers/fpga/xilinx-pr-decoupler.c
@@ -121,8 +121,8 @@ static int xlnx_pr_decoupler_probe(struct platform_device *pdev)
clk_disable(priv->clk);
- br = fpga_bridge_create(&pdev->dev, "Xilinx PR Decoupler",
- &xlnx_pr_decoupler_br_ops, priv);
+ br = devm_fpga_bridge_create(&pdev->dev, "Xilinx PR Decoupler",
+ &xlnx_pr_decoupler_br_ops, priv);
if (!br) {
err = -ENOMEM;
goto err_clk;
diff --git a/include/linux/fpga/fpga-bridge.h b/include/linux/fpga/fpga-bridge.h
index ce550fc..817600a 100644
--- a/include/linux/fpga/fpga-bridge.h
+++ b/include/linux/fpga/fpga-bridge.h
@@ -69,4 +69,8 @@ void fpga_bridge_free(struct fpga_bridge *br);
int fpga_bridge_register(struct fpga_bridge *br);
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 */
--
2.7.4
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH v2 4/8] fpga: add devm_fpga_region_create
2018-09-04 21:22 [PATCH v2 0/8] fpga: add devm managed create APIs Alan Tull
` (2 preceding siblings ...)
2018-09-04 21:22 ` [PATCH v2 3/8] fpga: bridge: add devm_fpga_bridge_create Alan Tull
@ 2018-09-04 21:22 ` Alan Tull
2018-09-04 21:22 ` [PATCH v2 5/8] dt-bindings: fpga: fix freeze controller compatible in region doc Alan Tull
` (3 subsequent siblings)
7 siblings, 0 replies; 19+ messages in thread
From: Alan Tull @ 2018-09-04 21:22 UTC (permalink / raw)
To: Moritz Fischer, Jonathan Corbet
Cc: Randy Dunlap, linux-kernel, linux-fpga, linux-doc, Alan Tull
Add devm_fpga_region_create() which is the
managed version of fpga_region_create().
Change current region drivers to use
devm_fpga_region_create().
Signed-off-by: Alan Tull <atull@kernel.org>
Suggested-by: Federico Vaga <federico.vaga@cern.ch>
---
v2: add suggested-by
---
Documentation/driver-api/fpga/fpga-region.rst | 3 ++
drivers/fpga/dfl-fme-region.c | 6 +--
drivers/fpga/dfl.c | 6 +--
drivers/fpga/fpga-region.c | 68 +++++++++++++++++++++++----
drivers/fpga/of-fpga-region.c | 6 +--
include/linux/fpga/fpga-region.h | 4 ++
6 files changed, 73 insertions(+), 20 deletions(-)
diff --git a/Documentation/driver-api/fpga/fpga-region.rst b/Documentation/driver-api/fpga/fpga-region.rst
index f30333c..dc9f75c 100644
--- a/Documentation/driver-api/fpga/fpga-region.rst
+++ b/Documentation/driver-api/fpga/fpga-region.rst
@@ -90,6 +90,9 @@ API to add a new FPGA region
:functions: fpga_region
.. kernel-doc:: drivers/fpga/fpga-region.c
+ :functions: devm_fpga_region_create
+
+.. kernel-doc:: drivers/fpga/fpga-region.c
:functions: fpga_region_create
.. kernel-doc:: drivers/fpga/fpga-region.c
diff --git a/drivers/fpga/dfl-fme-region.c b/drivers/fpga/dfl-fme-region.c
index 51a5ac2..ec134ec 100644
--- a/drivers/fpga/dfl-fme-region.c
+++ b/drivers/fpga/dfl-fme-region.c
@@ -39,7 +39,7 @@ static int fme_region_probe(struct platform_device *pdev)
if (IS_ERR(mgr))
return -EPROBE_DEFER;
- region = fpga_region_create(dev, mgr, fme_region_get_bridges);
+ region = devm_fpga_region_create(dev, mgr, fme_region_get_bridges);
if (!region) {
ret = -ENOMEM;
goto eprobe_mgr_put;
@@ -51,14 +51,12 @@ static int fme_region_probe(struct platform_device *pdev)
ret = fpga_region_register(region);
if (ret)
- goto region_free;
+ goto eprobe_mgr_put;
dev_dbg(dev, "DFL FME FPGA Region probed\n");
return 0;
-region_free:
- fpga_region_free(region);
eprobe_mgr_put:
fpga_mgr_put(mgr);
return ret;
diff --git a/drivers/fpga/dfl.c b/drivers/fpga/dfl.c
index a9b521b..2c09e50 100644
--- a/drivers/fpga/dfl.c
+++ b/drivers/fpga/dfl.c
@@ -899,7 +899,7 @@ dfl_fpga_feature_devs_enumerate(struct dfl_fpga_enum_info *info)
if (!cdev)
return ERR_PTR(-ENOMEM);
- cdev->region = fpga_region_create(info->dev, NULL, NULL);
+ cdev->region = devm_fpga_region_create(info->dev, NULL, NULL);
if (!cdev->region) {
ret = -ENOMEM;
goto free_cdev_exit;
@@ -911,7 +911,7 @@ dfl_fpga_feature_devs_enumerate(struct dfl_fpga_enum_info *info)
ret = fpga_region_register(cdev->region);
if (ret)
- goto free_region_exit;
+ goto free_cdev_exit;
/* create and init build info for enumeration */
binfo = devm_kzalloc(info->dev, sizeof(*binfo), GFP_KERNEL);
@@ -942,8 +942,6 @@ dfl_fpga_feature_devs_enumerate(struct dfl_fpga_enum_info *info)
unregister_region_exit:
fpga_region_unregister(cdev->region);
-free_region_exit:
- fpga_region_free(cdev->region);
free_cdev_exit:
devm_kfree(info->dev, cdev);
return ERR_PTR(ret);
diff --git a/drivers/fpga/fpga-region.c b/drivers/fpga/fpga-region.c
index 0d65220..56f773d 100644
--- a/drivers/fpga/fpga-region.c
+++ b/drivers/fpga/fpga-region.c
@@ -185,6 +185,10 @@ ATTRIBUTE_GROUPS(fpga_region);
* @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.
+ *
* Return: struct fpga_region or NULL
*/
struct fpga_region
@@ -230,8 +234,8 @@ struct fpga_region
EXPORT_SYMBOL_GPL(fpga_region_create);
/**
- * fpga_region_free - free a struct fpga_region
- * @region: FPGA region created by fpga_region_create
+ * fpga_region_free - free a FPGA region created by fpga_region_create()
+ * @region: FPGA region
*/
void fpga_region_free(struct fpga_region *region)
{
@@ -240,21 +244,72 @@ void fpga_region_free(struct fpga_region *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);
+}
+
+/**
+ * devm_fpga_region_create - create and initialize a managed FPGA region struct
+ * @dev: 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 a 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.
+ *
+ * Return: struct fpga_region or NULL
+ */
+struct fpga_region
+*devm_fpga_region_create(struct device *dev,
+ 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;
+
+ region = fpga_region_create(dev, mgr, get_bridges);
+ if (!region) {
+ devres_free(ptr);
+ } else {
+ *ptr = region;
+ devres_add(dev, ptr);
+ }
+
+ return region;
+}
+EXPORT_SYMBOL_GPL(devm_fpga_region_create);
+
/**
* fpga_region_register - register a FPGA region
- * @region: FPGA region created by fpga_region_create
+ * @region: FPGA region
+ *
* Return: 0 or -errno
*/
int fpga_region_register(struct fpga_region *region)
{
return device_add(®ion->dev);
-
}
EXPORT_SYMBOL_GPL(fpga_region_register);
/**
- * fpga_region_unregister - unregister and free a FPGA region
+ * fpga_region_unregister - unregister a FPGA region
* @region: FPGA region
+ *
+ * This function is intended for use in a FPGA region driver's remove function.
+ * If the region was created by devm_fpga_region_create(), it will be
+ * automatically freed. If the region was created by fpga_region_create(), the
+ * caller is responsible for freeing it with fpga_region_free().
*/
void fpga_region_unregister(struct fpga_region *region)
{
@@ -264,9 +319,6 @@ EXPORT_SYMBOL_GPL(fpga_region_unregister);
static void fpga_region_dev_release(struct device *dev)
{
- struct fpga_region *region = to_fpga_region(dev);
-
- fpga_region_free(region);
}
/**
diff --git a/drivers/fpga/of-fpga-region.c b/drivers/fpga/of-fpga-region.c
index 052a134..122286f 100644
--- a/drivers/fpga/of-fpga-region.c
+++ b/drivers/fpga/of-fpga-region.c
@@ -410,7 +410,7 @@ static int of_fpga_region_probe(struct platform_device *pdev)
if (IS_ERR(mgr))
return -EPROBE_DEFER;
- region = fpga_region_create(dev, mgr, of_fpga_region_get_bridges);
+ region = devm_fpga_region_create(dev, mgr, of_fpga_region_get_bridges);
if (!region) {
ret = -ENOMEM;
goto eprobe_mgr_put;
@@ -418,7 +418,7 @@ static int of_fpga_region_probe(struct platform_device *pdev)
ret = fpga_region_register(region);
if (ret)
- goto eprobe_free;
+ goto eprobe_mgr_put;
of_platform_populate(np, fpga_region_of_match, NULL, ®ion->dev);
dev_set_drvdata(dev, region);
@@ -427,8 +427,6 @@ static int of_fpga_region_probe(struct platform_device *pdev)
return 0;
-eprobe_free:
- fpga_region_free(region);
eprobe_mgr_put:
fpga_mgr_put(mgr);
return ret;
diff --git a/include/linux/fpga/fpga-region.h b/include/linux/fpga/fpga-region.h
index 0521b7f..27cb706 100644
--- a/include/linux/fpga/fpga-region.h
+++ b/include/linux/fpga/fpga-region.h
@@ -44,4 +44,8 @@ void fpga_region_free(struct fpga_region *region);
int fpga_region_register(struct fpga_region *region);
void fpga_region_unregister(struct fpga_region *region);
+struct fpga_region
+*devm_fpga_region_create(struct device *dev, struct fpga_manager *mgr,
+ int (*get_bridges)(struct fpga_region *));
+
#endif /* _FPGA_REGION_H */
--
2.7.4
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH v2 5/8] dt-bindings: fpga: fix freeze controller compatible in region doc
2018-09-04 21:22 [PATCH v2 0/8] fpga: add devm managed create APIs Alan Tull
` (3 preceding siblings ...)
2018-09-04 21:22 ` [PATCH v2 4/8] fpga: add devm_fpga_region_create Alan Tull
@ 2018-09-04 21:22 ` Alan Tull
2018-09-06 18:01 ` Alan Tull
2018-09-04 21:22 ` [PATCH v2 6/8] fpga: bridge: fix obvious function documentation error Alan Tull
` (2 subsequent siblings)
7 siblings, 1 reply; 19+ messages in thread
From: Alan Tull @ 2018-09-04 21:22 UTC (permalink / raw)
To: Moritz Fischer, Jonathan Corbet
Cc: Randy Dunlap, linux-kernel, linux-fpga, linux-doc, Alan Tull
Documentation/devicetree/bindings/fpga/fpga-region.txt has an error
regarding the freeze controller bridge, secifically:
compatible = "altr,freeze-bridge";
The compatibility string should be "altr,freeze-bridge-controller"
as set forth in altera-freeze-bridge.txt.
Signed-off-by: Alan Tull <atull@kernel.org>
Reported-by: Dalon Westergreen <dalon.westergreen@intel.com>
---
v2: no change in v2 of patchset
---
Documentation/devicetree/bindings/fpga/fpga-region.txt | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/Documentation/devicetree/bindings/fpga/fpga-region.txt b/Documentation/devicetree/bindings/fpga/fpga-region.txt
index 6db8aed..90c4469 100644
--- a/Documentation/devicetree/bindings/fpga/fpga-region.txt
+++ b/Documentation/devicetree/bindings/fpga/fpga-region.txt
@@ -415,7 +415,7 @@ DT Overlay contains:
firmware-name = "base.rbf";
fpga-bridge@4400 {
- compatible = "altr,freeze-bridge";
+ compatible = "altr,freeze-bridge-controller";
reg = <0x4400 0x10>;
fpga_region1: fpga-region1 {
@@ -427,7 +427,7 @@ DT Overlay contains:
};
fpga-bridge@4420 {
- compatible = "altr,freeze-bridge";
+ compatible = "altr,freeze-bridge-controller";
reg = <0x4420 0x10>;
fpga_region2: fpga-region2 {
--
2.7.4
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH v2 6/8] fpga: bridge: fix obvious function documentation error
2018-09-04 21:22 [PATCH v2 0/8] fpga: add devm managed create APIs Alan Tull
` (4 preceding siblings ...)
2018-09-04 21:22 ` [PATCH v2 5/8] dt-bindings: fpga: fix freeze controller compatible in region doc Alan Tull
@ 2018-09-04 21:22 ` Alan Tull
2018-09-06 18:43 ` Moritz Fischer
2018-09-04 21:22 ` [PATCH v2 7/8] docs: fpga: document fpga manager flags Alan Tull
2018-09-04 21:22 ` [PATCH v2 8/8] docs: fpga: document programming fpgas using regions Alan Tull
7 siblings, 1 reply; 19+ messages in thread
From: Alan Tull @ 2018-09-04 21:22 UTC (permalink / raw)
To: Moritz Fischer, Jonathan Corbet
Cc: Randy Dunlap, linux-kernel, linux-fpga, linux-doc, Alan Tull
fpga_bridge_dev_match() returns a FPGA bridge struct, not a
FPGA manager struct so s/manager/bridge/.
Signed-off-by: Alan Tull <atull@kernel.org>
---
v2: no change in v2 of patchset
---
drivers/fpga/fpga-bridge.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/fpga/fpga-bridge.c b/drivers/fpga/fpga-bridge.c
index c39d35f..7b0071a 100644
--- a/drivers/fpga/fpga-bridge.c
+++ b/drivers/fpga/fpga-bridge.c
@@ -125,7 +125,7 @@ static int fpga_bridge_dev_match(struct device *dev, const void *data)
*
* Given a device, get an exclusive reference to a fpga bridge.
*
- * Return: fpga manager struct or IS_ERR() condition containing error code.
+ * Return: fpga bridge struct or IS_ERR() condition containing error code.
*/
struct fpga_bridge *fpga_bridge_get(struct device *dev,
struct fpga_image_info *info)
--
2.7.4
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH v2 7/8] docs: fpga: document fpga manager flags
2018-09-04 21:22 [PATCH v2 0/8] fpga: add devm managed create APIs Alan Tull
` (5 preceding siblings ...)
2018-09-04 21:22 ` [PATCH v2 6/8] fpga: bridge: fix obvious function documentation error Alan Tull
@ 2018-09-04 21:22 ` Alan Tull
2018-09-06 18:42 ` Moritz Fischer
2018-09-04 21:22 ` [PATCH v2 8/8] docs: fpga: document programming fpgas using regions Alan Tull
7 siblings, 1 reply; 19+ messages in thread
From: Alan Tull @ 2018-09-04 21:22 UTC (permalink / raw)
To: Moritz Fischer, Jonathan Corbet
Cc: Randy Dunlap, linux-kernel, linux-fpga, linux-doc, Alan Tull
Add flags #defines to kerneldoc documentation in a
useful place.
Signed-off-by: Alan Tull <atull@kernel.org>
---
v2: add description for FPGA_MGR_ENCRYPTED_BITSTREAM
---
Documentation/driver-api/fpga/fpga-mgr.rst | 5 +++++
include/linux/fpga/fpga-mgr.h | 20 ++++++++++++++------
2 files changed, 19 insertions(+), 6 deletions(-)
diff --git a/Documentation/driver-api/fpga/fpga-mgr.rst b/Documentation/driver-api/fpga/fpga-mgr.rst
index 431556d..db8885e 100644
--- a/Documentation/driver-api/fpga/fpga-mgr.rst
+++ b/Documentation/driver-api/fpga/fpga-mgr.rst
@@ -183,6 +183,11 @@ API for implementing a new FPGA Manager driver
API for programming an FPGA
---------------------------
+FPGA Manager flags
+
+.. kernel-doc:: include/linux/fpga/fpga-mgr.h
+ :doc: FPGA Manager flags
+
.. kernel-doc:: include/linux/fpga/fpga-mgr.h
:functions: fpga_image_info
diff --git a/include/linux/fpga/fpga-mgr.h b/include/linux/fpga/fpga-mgr.h
index 1ca02ce..e8ca62b 100644
--- a/include/linux/fpga/fpga-mgr.h
+++ b/include/linux/fpga/fpga-mgr.h
@@ -53,12 +53,20 @@ enum fpga_mgr_states {
FPGA_MGR_STATE_OPERATING,
};
-/*
- * FPGA Manager flags
- * FPGA_MGR_PARTIAL_RECONFIG: do partial reconfiguration if supported
- * FPGA_MGR_EXTERNAL_CONFIG: FPGA has been configured prior to Linux booting
- * FPGA_MGR_BITSTREAM_LSB_FIRST: SPI bitstream bit order is LSB first
- * FPGA_MGR_COMPRESSED_BITSTREAM: FPGA bitstream is compressed
+/**
+ * DOC: FPGA Manager flags
+ *
+ * Flags used in the &fpga_image_info->flags field
+ *
+ * %FPGA_MGR_PARTIAL_RECONFIG: do partial reconfiguration if supported
+ *
+ * %FPGA_MGR_EXTERNAL_CONFIG: FPGA has been configured prior to Linux booting
+ *
+ * %FPGA_MGR_ENCRYPTED_BITSTREAM: indicates bitstream is encrypted
+ *
+ * %FPGA_MGR_BITSTREAM_LSB_FIRST: SPI bitstream bit order is LSB first
+ *
+ * %FPGA_MGR_COMPRESSED_BITSTREAM: FPGA bitstream is compressed
*/
#define FPGA_MGR_PARTIAL_RECONFIG BIT(0)
#define FPGA_MGR_EXTERNAL_CONFIG BIT(1)
--
2.7.4
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH v2 8/8] docs: fpga: document programming fpgas using regions
2018-09-04 21:22 [PATCH v2 0/8] fpga: add devm managed create APIs Alan Tull
` (6 preceding siblings ...)
2018-09-04 21:22 ` [PATCH v2 7/8] docs: fpga: document fpga manager flags Alan Tull
@ 2018-09-04 21:22 ` Alan Tull
7 siblings, 0 replies; 19+ messages in thread
From: Alan Tull @ 2018-09-04 21:22 UTC (permalink / raw)
To: Moritz Fischer, Jonathan Corbet
Cc: Randy Dunlap, linux-kernel, linux-fpga, linux-doc, Alan Tull
Clarify the intention that interfaces and upper layers use
regions rather than managers directly.
Rearrange API documentation to better group the API functions
used to create FPGA mgr/bridge/regions and the API used for
programming FPGAs.
Signed-off-by: Alan Tull <atull@kernel.org>
Suggested-by: Federico Vaga <federico.vaga@cern.ch>
---
v2: Add suggested-by
s/a FPGA/an FPGA/
document freeing the fpga_mgr_info on success path
minor formatting fixes and suggested edits
---
Documentation/driver-api/fpga/fpga-bridge.rst | 38 ++-----
Documentation/driver-api/fpga/fpga-mgr.rst | 117 ++-------------------
Documentation/driver-api/fpga/fpga-programming.rst | 107 +++++++++++++++++++
Documentation/driver-api/fpga/fpga-region.rst | 92 ++++++++--------
Documentation/driver-api/fpga/index.rst | 2 +
Documentation/driver-api/fpga/intro.rst | 2 +-
6 files changed, 171 insertions(+), 187 deletions(-)
create mode 100644 Documentation/driver-api/fpga/fpga-programming.rst
diff --git a/Documentation/driver-api/fpga/fpga-bridge.rst b/Documentation/driver-api/fpga/fpga-bridge.rst
index ebbcbde..71c5a40 100644
--- a/Documentation/driver-api/fpga/fpga-bridge.rst
+++ b/Documentation/driver-api/fpga/fpga-bridge.rst
@@ -4,6 +4,12 @@ FPGA Bridge
API to implement a new FPGA bridge
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+* struct :c:type:`fpga_bridge` — The FPGA Bridge structure
+* struct :c:type:`fpga_bridge_ops` — Low level Bridge driver ops
+* :c:func:`devm_fpga_bridge_create()` — Allocate and init a bridge struct
+* :c:func:`fpga_bridge_register()` — Register a bridge
+* :c:func:`fpga_bridge_unregister()` — Unregister a bridge
+
.. kernel-doc:: include/linux/fpga/fpga-bridge.h
:functions: fpga_bridge
@@ -14,39 +20,7 @@ API to implement a new FPGA bridge
:functions: devm_fpga_bridge_create
.. kernel-doc:: drivers/fpga/fpga-bridge.c
- :functions: fpga_bridge_create
-
-.. kernel-doc:: drivers/fpga/fpga-bridge.c
- :functions: fpga_bridge_free
-
-.. kernel-doc:: drivers/fpga/fpga-bridge.c
:functions: fpga_bridge_register
.. kernel-doc:: drivers/fpga/fpga-bridge.c
:functions: fpga_bridge_unregister
-
-API to control an FPGA bridge
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-You probably won't need these directly. FPGA regions should handle this.
-
-.. kernel-doc:: drivers/fpga/fpga-bridge.c
- :functions: of_fpga_bridge_get
-
-.. kernel-doc:: drivers/fpga/fpga-bridge.c
- :functions: fpga_bridge_get
-
-.. kernel-doc:: drivers/fpga/fpga-bridge.c
- :functions: fpga_bridge_put
-
-.. kernel-doc:: drivers/fpga/fpga-bridge.c
- :functions: fpga_bridge_get_to_list
-
-.. kernel-doc:: drivers/fpga/fpga-bridge.c
- :functions: of_fpga_bridge_get_to_list
-
-.. kernel-doc:: drivers/fpga/fpga-bridge.c
- :functions: fpga_bridge_enable
-
-.. kernel-doc:: drivers/fpga/fpga-bridge.c
- :functions: fpga_bridge_disable
diff --git a/Documentation/driver-api/fpga/fpga-mgr.rst b/Documentation/driver-api/fpga/fpga-mgr.rst
index db8885e..576f194 100644
--- a/Documentation/driver-api/fpga/fpga-mgr.rst
+++ b/Documentation/driver-api/fpga/fpga-mgr.rst
@@ -98,67 +98,19 @@ The ops include a .state function which will determine the state the FPGA is in
and return a code of type enum fpga_mgr_states. It doesn't result in a change
in state.
-How to write an image buffer to a supported FPGA
-------------------------------------------------
-
-Some sample code::
-
- #include <linux/fpga/fpga-mgr.h>
-
- struct fpga_manager *mgr;
- struct fpga_image_info *info;
- int ret;
-
- /*
- * Get a reference to FPGA manager. The manager is not locked, so you can
- * hold onto this reference without it preventing programming.
- *
- * This example uses the device node of the manager. Alternatively, use
- * fpga_mgr_get(dev) instead if you have the device.
- */
- mgr = of_fpga_mgr_get(mgr_node);
-
- /* struct with information about the FPGA image to program. */
- info = fpga_image_info_alloc(dev);
-
- /* flags indicates whether to do full or partial reconfiguration */
- info->flags = FPGA_MGR_PARTIAL_RECONFIG;
-
- /*
- * At this point, indicate where the image is. This is pseudo-code; you're
- * going to use one of these three.
- */
- if (image is in a scatter gather table) {
-
- info->sgt = [your scatter gather table]
-
- } else if (image is in a buffer) {
-
- info->buf = [your image buffer]
- info->count = [image buffer size]
-
- } else if (image is in a firmware file) {
-
- info->firmware_name = devm_kstrdup(dev, firmware_name, GFP_KERNEL);
-
- }
-
- /* Get exclusive control of FPGA manager */
- ret = fpga_mgr_lock(mgr);
-
- /* Load the buffer to the FPGA */
- ret = fpga_mgr_buf_load(mgr, &info, buf, count);
-
- /* Release the FPGA manager */
- fpga_mgr_unlock(mgr);
- fpga_mgr_put(mgr);
-
- /* Deallocate the image info if you're done with it */
- fpga_image_info_free(info);
-
API for implementing a new FPGA Manager driver
----------------------------------------------
+* ``fpga_mgr_states`` — Values for :c:member:`fpga_manager->state`.
+* struct :c:type:`fpga_manager` — the FPGA manager struct
+* struct :c:type:`fpga_manager_ops` — Low level FPGA manager driver ops
+* :c:func:`devm_fpga_mgr_create` — Allocate and init a manager struct
+* :c:func:`fpga_mgr_register` — Register an FPGA manager
+* :c:func:`fpga_mgr_unregister` — Unregister an FPGA manager
+
+.. kernel-doc:: include/linux/fpga/fpga-mgr.h
+ :functions: fpga_mgr_states
+
.. kernel-doc:: include/linux/fpga/fpga-mgr.h
:functions: fpga_manager
@@ -169,56 +121,7 @@ API for implementing a new FPGA Manager driver
:functions: devm_fpga_mgr_create
.. kernel-doc:: drivers/fpga/fpga-mgr.c
- :functions: fpga_mgr_create
-
-.. kernel-doc:: drivers/fpga/fpga-mgr.c
- :functions: fpga_mgr_free
-
-.. kernel-doc:: drivers/fpga/fpga-mgr.c
:functions: fpga_mgr_register
.. kernel-doc:: drivers/fpga/fpga-mgr.c
:functions: fpga_mgr_unregister
-
-API for programming an FPGA
----------------------------
-
-FPGA Manager flags
-
-.. kernel-doc:: include/linux/fpga/fpga-mgr.h
- :doc: FPGA Manager flags
-
-.. kernel-doc:: include/linux/fpga/fpga-mgr.h
- :functions: fpga_image_info
-
-.. kernel-doc:: include/linux/fpga/fpga-mgr.h
- :functions: fpga_mgr_states
-
-.. kernel-doc:: drivers/fpga/fpga-mgr.c
- :functions: fpga_image_info_alloc
-
-.. kernel-doc:: drivers/fpga/fpga-mgr.c
- :functions: fpga_image_info_free
-
-.. kernel-doc:: drivers/fpga/fpga-mgr.c
- :functions: of_fpga_mgr_get
-
-.. kernel-doc:: drivers/fpga/fpga-mgr.c
- :functions: fpga_mgr_get
-
-.. kernel-doc:: drivers/fpga/fpga-mgr.c
- :functions: fpga_mgr_put
-
-.. kernel-doc:: drivers/fpga/fpga-mgr.c
- :functions: fpga_mgr_lock
-
-.. kernel-doc:: drivers/fpga/fpga-mgr.c
- :functions: fpga_mgr_unlock
-
-.. kernel-doc:: include/linux/fpga/fpga-mgr.h
- :functions: fpga_mgr_states
-
-Note - use :c:func:`fpga_region_program_fpga()` instead of :c:func:`fpga_mgr_load()`
-
-.. kernel-doc:: drivers/fpga/fpga-mgr.c
- :functions: fpga_mgr_load
diff --git a/Documentation/driver-api/fpga/fpga-programming.rst b/Documentation/driver-api/fpga/fpga-programming.rst
new file mode 100644
index 0000000..b5484df
--- /dev/null
+++ b/Documentation/driver-api/fpga/fpga-programming.rst
@@ -0,0 +1,107 @@
+In-kernel API for FPGA Programming
+==================================
+
+Overview
+--------
+
+The in-kernel API for FPGA programming is a combination of APIs from
+FPGA manager, bridge, and regions. The actual function used to
+trigger FPGA programming is :c:func:`fpga_region_program_fpga()`.
+
+:c:func:`fpga_region_program_fpga()` uses functionality supplied by
+the FPGA manager and bridges. It will:
+
+ * lock the region's mutex
+ * lock the mutex of the region's FPGA manager
+ * build a list of FPGA bridges if a method has been specified to do so
+ * disable the bridges
+ * program the FPGA using info passed in :c:member:`fpga_region->info`.
+ * re-enable the bridges
+ * release the locks
+
+The struct fpga_image_info specifies what FPGA image to program. It is
+allocated/freed by :c:func:`fpga_image_info_alloc()` and freed with
+:c:func:`fpga_image_info_free()`
+
+How to program an FPGA using a region
+-------------------------------------
+
+When the FPGA region driver probed, it was given a pointer to an FPGA manager
+driver so it knows which manager to use. The region also either has a list of
+bridges to control during programming or it has a pointer to a function that
+will generate that list. Here's some sample code of what to do next::
+
+ #include <linux/fpga/fpga-mgr.h>
+ #include <linux/fpga/fpga-region.h>
+
+ struct fpga_image_info *info;
+ int ret;
+
+ /*
+ * First, alloc the struct with information about the FPGA image to
+ * program.
+ */
+ info = fpga_image_info_alloc(dev);
+ if (!info)
+ return -ENOMEM;
+
+ /* Set flags as needed, such as: */
+ info->flags = FPGA_MGR_PARTIAL_RECONFIG;
+
+ /*
+ * Indicate where the FPGA image is. This is pseudo-code; you're
+ * going to use one of these three.
+ */
+ if (image is in a scatter gather table) {
+
+ info->sgt = [your scatter gather table]
+
+ } else if (image is in a buffer) {
+
+ info->buf = [your image buffer]
+ info->count = [image buffer size]
+
+ } else if (image is in a firmware file) {
+
+ info->firmware_name = devm_kstrdup(dev, firmware_name,
+ GFP_KERNEL);
+
+ }
+
+ /* Add info to region and do the programming */
+ region->info = info;
+ ret = fpga_region_program_fpga(region);
+
+ /* Deallocate the image info if you're done with it */
+ region->info = NULL;
+ fpga_image_info_free(info);
+
+ if (ret)
+ return ret;
+
+ /* Now enumerate whatever hardware has appeared in the FPGA. */
+
+API for programming an FPGA
+---------------------------
+
+* :c:func:`fpga_region_program_fpga` — Program an FPGA
+* :c:type:`fpga_image_info` — Specifies what FPGA image to program
+* :c:func:`fpga_image_info_alloc()` — Allocate an FPGA image info struct
+* :c:func:`fpga_image_info_free()` — Free an FPGA image info struct
+
+.. kernel-doc:: drivers/fpga/fpga-region.c
+ :functions: fpga_region_program_fpga
+
+FPGA Manager flags
+
+.. kernel-doc:: include/linux/fpga/fpga-mgr.h
+ :doc: FPGA Manager flags
+
+.. kernel-doc:: include/linux/fpga/fpga-mgr.h
+ :functions: fpga_image_info
+
+.. kernel-doc:: drivers/fpga/fpga-mgr.c
+ :functions: fpga_image_info_alloc
+
+.. kernel-doc:: drivers/fpga/fpga-mgr.c
+ :functions: fpga_image_info_free
diff --git a/Documentation/driver-api/fpga/fpga-region.rst b/Documentation/driver-api/fpga/fpga-region.rst
index dc9f75c..0529b2d 100644
--- a/Documentation/driver-api/fpga/fpga-region.rst
+++ b/Documentation/driver-api/fpga/fpga-region.rst
@@ -34,41 +34,6 @@ fpga_image_info including:
* flags indicating specifics such as whether the image is for partial
reconfiguration.
-How to program an FPGA using a region
--------------------------------------
-
-First, allocate the info struct::
-
- info = fpga_image_info_alloc(dev);
- if (!info)
- return -ENOMEM;
-
-Set flags as needed, i.e.::
-
- info->flags |= FPGA_MGR_PARTIAL_RECONFIG;
-
-Point to your FPGA image, such as::
-
- info->sgt = &sgt;
-
-Add info to region and do the programming::
-
- region->info = info;
- ret = fpga_region_program_fpga(region);
-
-:c:func:`fpga_region_program_fpga()` operates on info passed in the
-fpga_image_info (region->info). This function will attempt to:
-
- * lock the region's mutex
- * lock the region's FPGA manager
- * build a list of FPGA bridges if a method has been specified to do so
- * disable the bridges
- * program the FPGA
- * re-enable the bridges
- * release the locks
-
-Then you will want to enumerate whatever hardware has appeared in the FPGA.
-
How to add a new FPGA region
----------------------------
@@ -77,15 +42,36 @@ An example of usage can be seen in the probe function of [#f2]_.
.. [#f1] ../devicetree/bindings/fpga/fpga-region.txt
.. [#f2] ../../drivers/fpga/of-fpga-region.c
-API to program an FPGA
-----------------------
-
-.. kernel-doc:: drivers/fpga/fpga-region.c
- :functions: fpga_region_program_fpga
-
API to add a new FPGA region
----------------------------
+* struct :c:type:`fpga_region` — The FPGA region struct
+* :c:func:`devm_fpga_region_create` — Allocate and init a region struct
+* :c:func:`fpga_region_register` — Register an FPGA region
+* :c:func:`fpga_region_unregister` — Unregister an FPGA region
+
+The FPGA region's probe function will need to get a reference to the FPGA
+Manager it will be using to do the programming. This usually would happen
+during the region's probe function.
+
+* :c:func:`fpga_mgr_get` — Get a reference to an FPGA manager, raise ref count
+* :c:func:`of_fpga_mgr_get` — Get a reference to an FPGA manager, raise ref count,
+ given a device node.
+* :c:func:`fpga_mgr_put` — Put an FPGA manager
+
+The FPGA region will need to specify which bridges to control while programming
+the FPGA. The region driver can build a list of bridges during probe time
+(:c:member:`fpga_region->bridge_list`) or it can have a function that creates
+the list of bridges to program just before programming
+(:c:member:`fpga_region->get_bridges`). The FPGA bridge framework supplies the
+following APIs to handle building or tearing down that list.
+
+* :c:func:`fpga_bridge_get_to_list` — Get a ref of an FPGA bridge, add it to a
+ list
+* :c:func:`of_fpga_bridge_get_to_list` — Get a ref of an FPGA bridge, add it to a
+ list, given a device node
+* :c:func:`fpga_bridges_put` — Given a list of bridges, put them
+
.. kernel-doc:: include/linux/fpga/fpga-region.h
:functions: fpga_region
@@ -93,13 +79,25 @@ API to add a new FPGA region
:functions: devm_fpga_region_create
.. kernel-doc:: drivers/fpga/fpga-region.c
- :functions: fpga_region_create
-
-.. kernel-doc:: drivers/fpga/fpga-region.c
- :functions: fpga_region_free
-
-.. kernel-doc:: drivers/fpga/fpga-region.c
:functions: fpga_region_register
.. kernel-doc:: drivers/fpga/fpga-region.c
:functions: fpga_region_unregister
+
+.. kernel-doc:: drivers/fpga/fpga-mgr.c
+ :functions: fpga_mgr_get
+
+.. kernel-doc:: drivers/fpga/fpga-mgr.c
+ :functions: of_fpga_mgr_get
+
+.. kernel-doc:: drivers/fpga/fpga-mgr.c
+ :functions: fpga_mgr_put
+
+.. kernel-doc:: drivers/fpga/fpga-bridge.c
+ :functions: fpga_bridge_get_to_list
+
+.. kernel-doc:: drivers/fpga/fpga-bridge.c
+ :functions: of_fpga_bridge_get_to_list
+
+.. kernel-doc:: drivers/fpga/fpga-bridge.c
+ :functions: fpga_bridges_put
diff --git a/Documentation/driver-api/fpga/index.rst b/Documentation/driver-api/fpga/index.rst
index c51e5eb..31a4773 100644
--- a/Documentation/driver-api/fpga/index.rst
+++ b/Documentation/driver-api/fpga/index.rst
@@ -11,3 +11,5 @@ FPGA Subsystem
fpga-mgr
fpga-bridge
fpga-region
+ fpga-programming
+
diff --git a/Documentation/driver-api/fpga/intro.rst b/Documentation/driver-api/fpga/intro.rst
index 50d1cab..f54c7da 100644
--- a/Documentation/driver-api/fpga/intro.rst
+++ b/Documentation/driver-api/fpga/intro.rst
@@ -44,7 +44,7 @@ FPGA Region
-----------
If you are adding a new interface to the FPGA framework, add it on top
-of an FPGA region to allow the most reuse of your interface.
+of an FPGA region.
The FPGA Region framework (fpga-region.c) associates managers and
bridges as reconfigurable regions. A region may refer to the whole
--
2.7.4
^ permalink raw reply related [flat|nested] 19+ messages in thread
* Re: [PATCH v2 1/8] fpga: do not access region struct after fpga_region_unregister
2018-09-04 21:22 ` [PATCH v2 1/8] fpga: do not access region struct after fpga_region_unregister Alan Tull
@ 2018-09-04 23:41 ` Moritz Fischer
2018-09-05 15:07 ` Alan Tull
0 siblings, 1 reply; 19+ messages in thread
From: Moritz Fischer @ 2018-09-04 23:41 UTC (permalink / raw)
To: Alan Tull
Cc: Jonathan Corbet, Randy Dunlap, Linux Kernel Mailing List,
linux-fpga, Linux Doc Mailing List
Hi Alan,
On Tue, Sep 4, 2018 at 2:22 PM, Alan Tull <atull@kernel.org> wrote:
> A couple drivers were accessing the region struct after it had been
> freed. Save off the pointer to the mgr before the region struct gets
> freed.
>
> Signed-off-by: Alan Tull <atull@kernel.org>
Acked-by: Moritz Fischer <mdf@kernel.org>
> ---
> v2: no change in v2 of patchset
> ---
> drivers/fpga/dfl-fme-region.c | 4 +++-
> drivers/fpga/of-fpga-region.c | 3 ++-
> 2 files changed, 5 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/fpga/dfl-fme-region.c b/drivers/fpga/dfl-fme-region.c
> index 0b7e19c..51a5ac2 100644
> --- a/drivers/fpga/dfl-fme-region.c
> +++ b/drivers/fpga/dfl-fme-region.c
> @@ -14,6 +14,7 @@
> */
>
> #include <linux/module.h>
> +#include <linux/fpga/fpga-mgr.h>
> #include <linux/fpga/fpga-region.h>
>
> #include "dfl-fme-pr.h"
> @@ -66,9 +67,10 @@ static int fme_region_probe(struct platform_device *pdev)
> static int fme_region_remove(struct platform_device *pdev)
> {
> struct fpga_region *region = dev_get_drvdata(&pdev->dev);
> + struct fpga_manager *mgr = region->mgr;
>
> fpga_region_unregister(region);
> - fpga_mgr_put(region->mgr);
> + fpga_mgr_put(mgr);
>
> return 0;
> }
> diff --git a/drivers/fpga/of-fpga-region.c b/drivers/fpga/of-fpga-region.c
> index 35fabb8..052a134 100644
> --- a/drivers/fpga/of-fpga-region.c
> +++ b/drivers/fpga/of-fpga-region.c
> @@ -437,9 +437,10 @@ static int of_fpga_region_probe(struct platform_device *pdev)
> static int of_fpga_region_remove(struct platform_device *pdev)
> {
> struct fpga_region *region = platform_get_drvdata(pdev);
> + struct fpga_manager *mgr = region->mgr;
>
> fpga_region_unregister(region);
> - fpga_mgr_put(region->mgr);
> + fpga_mgr_put(mgr);
>
> return 0;
> }
> --
> 2.7.4
>
Thanks,
Moritz
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v2 1/8] fpga: do not access region struct after fpga_region_unregister
2018-09-04 23:41 ` Moritz Fischer
@ 2018-09-05 15:07 ` Alan Tull
0 siblings, 0 replies; 19+ messages in thread
From: Alan Tull @ 2018-09-05 15:07 UTC (permalink / raw)
To: Moritz Fischer
Cc: Jonathan Corbet, Randy Dunlap, linux-kernel, linux-fpga,
Linux Doc Mailing List
On Tue, Sep 4, 2018 at 6:41 PM Moritz Fischer <moritz.fischer@ettus.com> wrote:
Hi Moritz,
>
> Hi Alan,
>
> On Tue, Sep 4, 2018 at 2:22 PM, Alan Tull <atull@kernel.org> wrote:
> > A couple drivers were accessing the region struct after it had been
> > freed. Save off the pointer to the mgr before the region struct gets
> > freed.
> >
> > Signed-off-by: Alan Tull <atull@kernel.org>
> Acked-by: Moritz Fischer <mdf@kernel.org>
Thanks!
Alan
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v2 3/8] fpga: bridge: add devm_fpga_bridge_create
2018-09-04 21:22 ` [PATCH v2 3/8] fpga: bridge: add devm_fpga_bridge_create Alan Tull
@ 2018-09-05 15:22 ` Moritz Fischer
2018-09-05 15:38 ` Alan Tull
0 siblings, 1 reply; 19+ messages in thread
From: Moritz Fischer @ 2018-09-05 15:22 UTC (permalink / raw)
To: Alan Tull
Cc: Jonathan Corbet, Randy Dunlap, Linux Kernel Mailing List,
linux-fpga, Linux Doc Mailing List
Hi Alan,
looks good to me: Small nit inline. Not a showstopper.
On Tue, Sep 4, 2018 at 2:22 PM Alan Tull <atull@kernel.org> wrote:
>
> Add devm_fpga_bridge_create() which is the managed
> version of fpga_bridge_create().
>
> Change current bridge drivers to use
> devm_fpga_bridge_create().
>
> Signed-off-by: Alan Tull <atull@kernel.org>
Acked-by: Moritz Fischer <mdf@kernel.org>
> Suggested-by: Federico Vaga <federico.vaga@cern.ch>
> ---
> v2: add suggested-by
> ---
> Documentation/driver-api/fpga/fpga-bridge.rst | 3 ++
> drivers/fpga/altera-fpga2sdram.c | 8 ++-
> drivers/fpga/altera-freeze-bridge.c | 13 ++---
> drivers/fpga/altera-hps2fpga.c | 7 ++-
> drivers/fpga/dfl-fme-br.c | 11 ++--
> drivers/fpga/fpga-bridge.c | 72 +++++++++++++++++++++++----
> drivers/fpga/xilinx-pr-decoupler.c | 4 +-
> include/linux/fpga/fpga-bridge.h | 4 ++
> 8 files changed, 84 insertions(+), 38 deletions(-)
>
> diff --git a/Documentation/driver-api/fpga/fpga-bridge.rst b/Documentation/driver-api/fpga/fpga-bridge.rst
> index 2c2aaca..ebbcbde 100644
> --- a/Documentation/driver-api/fpga/fpga-bridge.rst
> +++ b/Documentation/driver-api/fpga/fpga-bridge.rst
> @@ -11,6 +11,9 @@ API to implement a new FPGA bridge
> :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_create
>
> .. kernel-doc:: drivers/fpga/fpga-bridge.c
> diff --git a/drivers/fpga/altera-fpga2sdram.c b/drivers/fpga/altera-fpga2sdram.c
> index 23660cc..a78e49c 100644
> --- a/drivers/fpga/altera-fpga2sdram.c
> +++ b/drivers/fpga/altera-fpga2sdram.c
> @@ -121,18 +121,16 @@ 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 = fpga_bridge_create(dev, F2S_BRIDGE_NAME,
> - &altera_fpga2sdram_br_ops, priv);
> + br = devm_fpga_bridge_create(dev, F2S_BRIDGE_NAME,
> + &altera_fpga2sdram_br_ops, priv);
> if (!br)
> return -ENOMEM;
>
> platform_set_drvdata(pdev, br);
>
> ret = fpga_bridge_register(br);
> - if (ret) {
> - fpga_bridge_free(br);
> + if (ret)
> return ret;
> - }
>
> dev_info(dev, "driver initialized with handoff %08x\n", priv->mask);
>
> diff --git a/drivers/fpga/altera-freeze-bridge.c b/drivers/fpga/altera-freeze-bridge.c
> index ffd586c..dd58c4a 100644
> --- a/drivers/fpga/altera-freeze-bridge.c
> +++ b/drivers/fpga/altera-freeze-bridge.c
> @@ -213,7 +213,6 @@ static int altera_freeze_br_probe(struct platform_device *pdev)
> struct fpga_bridge *br;
> struct resource *res;
> u32 status, revision;
> - int ret;
>
> if (!np)
> return -ENODEV;
> @@ -245,20 +244,14 @@ static int altera_freeze_br_probe(struct platform_device *pdev)
>
> priv->base_addr = base_addr;
>
> - br = fpga_bridge_create(dev, FREEZE_BRIDGE_NAME,
> - &altera_freeze_br_br_ops, priv);
> + br = devm_fpga_bridge_create(dev, FREEZE_BRIDGE_NAME,
> + &altera_freeze_br_br_ops, priv);
> if (!br)
> return -ENOMEM;
>
> platform_set_drvdata(pdev, br);
>
> - ret = fpga_bridge_register(br);
> - if (ret) {
> - fpga_bridge_free(br);
> - return ret;
> - }
> -
> - return 0;
> + return fpga_bridge_register(br);
> }
>
> static int altera_freeze_br_remove(struct platform_device *pdev)
> diff --git a/drivers/fpga/altera-hps2fpga.c b/drivers/fpga/altera-hps2fpga.c
> index a974d3f..77b95f2 100644
> --- a/drivers/fpga/altera-hps2fpga.c
> +++ b/drivers/fpga/altera-hps2fpga.c
> @@ -180,7 +180,8 @@ static int alt_fpga_bridge_probe(struct platform_device *pdev)
> }
> }
>
> - br = fpga_bridge_create(dev, priv->name, &altera_hps2fpga_br_ops, priv);
> + br = devm_fpga_bridge_create(dev, priv->name,
> + &altera_hps2fpga_br_ops, priv);
> if (!br) {
> ret = -ENOMEM;
> goto err;
> @@ -190,12 +191,10 @@ static int alt_fpga_bridge_probe(struct platform_device *pdev)
>
> ret = fpga_bridge_register(br);
> if (ret)
> - goto err_free;
> + goto err;
>
> return 0;
>
> -err_free:
> - fpga_bridge_free(br);
> err:
> clk_disable_unprepare(priv->clk);
>
> diff --git a/drivers/fpga/dfl-fme-br.c b/drivers/fpga/dfl-fme-br.c
> index 7cc041d..3ff9f3a 100644
> --- a/drivers/fpga/dfl-fme-br.c
> +++ b/drivers/fpga/dfl-fme-br.c
> @@ -61,7 +61,6 @@ static int fme_br_probe(struct platform_device *pdev)
> struct device *dev = &pdev->dev;
> struct fme_br_priv *priv;
> struct fpga_bridge *br;
> - int ret;
>
> priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
> if (!priv)
> @@ -69,18 +68,14 @@ static int fme_br_probe(struct platform_device *pdev)
>
> priv->pdata = dev_get_platdata(dev);
>
> - br = fpga_bridge_create(dev, "DFL FPGA FME Bridge",
> - &fme_bridge_ops, priv);
> + br = devm_fpga_bridge_create(dev, "DFL FPGA FME Bridge",
> + &fme_bridge_ops, priv);
> if (!br)
> return -ENOMEM;
>
> platform_set_drvdata(pdev, br);
>
> - ret = fpga_bridge_register(br);
> - if (ret)
> - fpga_bridge_free(br);
> -
> - return ret;
> + return fpga_bridge_register(br);
> }
>
> static int fme_br_remove(struct platform_device *pdev)
> diff --git a/drivers/fpga/fpga-bridge.c b/drivers/fpga/fpga-bridge.c
> index 24b8f98..c39d35f 100644
> --- a/drivers/fpga/fpga-bridge.c
> +++ b/drivers/fpga/fpga-bridge.c
> @@ -324,6 +324,9 @@ ATTRIBUTE_GROUPS(fpga_bridge);
> * @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
> */
> struct fpga_bridge *fpga_bridge_create(struct device *dev, const char *name,
> @@ -378,8 +381,8 @@ struct fpga_bridge *fpga_bridge_create(struct device *dev, const char *name,
> EXPORT_SYMBOL_GPL(fpga_bridge_create);
>
> /**
> - * fpga_bridge_free - free a fpga bridge and its id
> - * @bridge: FPGA bridge struct created by fpga_bridge_create
> + * fpga_bridge_free - free a fpga bridge created by fpga_bridge_create()
> + * @bridge: FPGA bridge struct
> */
> void fpga_bridge_free(struct fpga_bridge *bridge)
> {
> @@ -388,9 +391,56 @@ void fpga_bridge_free(struct fpga_bridge *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);
> +}
> +
> /**
> - * fpga_bridge_register - register a fpga bridge
> - * @bridge: FPGA bridge struct created by fpga_bridge_create
> + * devm_fpga_bridge_create - create and init a managed struct fpga_bridge
> + * @dev: 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 a 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 *dev, 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(dev, name, br_ops, priv);
> + if (!bridge) {
> + devres_free(ptr);
> + } else {
> + *ptr = bridge;
> + devres_add(dev, ptr);
> + }
> +
> + return bridge;
> +}
> +EXPORT_SYMBOL_GPL(devm_fpga_bridge_create);
> +
> +/**
> + * fpga_bridge_register - register a FPGA bridge
> + *
> + * @bridge: FPGA bridge struct
> *
> * Return: 0 for success, error code otherwise.
> */
> @@ -412,8 +462,15 @@ int fpga_bridge_register(struct fpga_bridge *bridge)
> EXPORT_SYMBOL_GPL(fpga_bridge_register);
>
> /**
> - * fpga_bridge_unregister - unregister and free a fpga bridge
> - * @bridge: FPGA bridge struct created by fpga_bridge_create
> + * fpga_bridge_unregister - unregister a FPGA bridge
> + *
> + * @bridge: FPGA bridge struct
> + *
> + * This function is intended for use in a FPGA bridge driver's remove function.
> + * If the bridge was created with devm_fpga_bridge_create(), the bridge struct
> + * will be automatically freed. If the bridge was created with
> + * fpga_bridge_create(), the caller is responsible for freeing the bridge with
> + * fpga_bridge_free().
I find the formulation somewhat confusing, since it could be
interpreted as if you
used the devm_() functions you don't have to call unregister().
> */
> void fpga_bridge_unregister(struct fpga_bridge *bridge)
> {
> @@ -430,9 +487,6 @@ EXPORT_SYMBOL_GPL(fpga_bridge_unregister);
>
> static void fpga_bridge_dev_release(struct device *dev)
> {
> - struct fpga_bridge *bridge = to_fpga_bridge(dev);
> -
> - fpga_bridge_free(bridge);
> }
>
> static int __init fpga_bridge_dev_init(void)
> diff --git a/drivers/fpga/xilinx-pr-decoupler.c b/drivers/fpga/xilinx-pr-decoupler.c
> index 07ba153..6410361 100644
> --- a/drivers/fpga/xilinx-pr-decoupler.c
> +++ b/drivers/fpga/xilinx-pr-decoupler.c
> @@ -121,8 +121,8 @@ static int xlnx_pr_decoupler_probe(struct platform_device *pdev)
>
> clk_disable(priv->clk);
>
> - br = fpga_bridge_create(&pdev->dev, "Xilinx PR Decoupler",
> - &xlnx_pr_decoupler_br_ops, priv);
> + br = devm_fpga_bridge_create(&pdev->dev, "Xilinx PR Decoupler",
> + &xlnx_pr_decoupler_br_ops, priv);
> if (!br) {
> err = -ENOMEM;
> goto err_clk;
> diff --git a/include/linux/fpga/fpga-bridge.h b/include/linux/fpga/fpga-bridge.h
> index ce550fc..817600a 100644
> --- a/include/linux/fpga/fpga-bridge.h
> +++ b/include/linux/fpga/fpga-bridge.h
> @@ -69,4 +69,8 @@ void fpga_bridge_free(struct fpga_bridge *br);
> int fpga_bridge_register(struct fpga_bridge *br);
> 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 */
> --
> 2.7.4
>
Thanks,
Moritz
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v2 3/8] fpga: bridge: add devm_fpga_bridge_create
2018-09-05 15:22 ` Moritz Fischer
@ 2018-09-05 15:38 ` Alan Tull
2018-09-06 18:19 ` Moritz Fischer
0 siblings, 1 reply; 19+ messages in thread
From: Alan Tull @ 2018-09-05 15:38 UTC (permalink / raw)
To: Moritz Fischer
Cc: Jonathan Corbet, Randy Dunlap, linux-kernel, linux-fpga,
Linux Doc Mailing List
On Wed, Sep 5, 2018 at 10:22 AM Moritz Fischer
<moritz.fischer.private@gmail.com> wrote:
>
> Hi Alan,
>
> looks good to me: Small nit inline. Not a showstopper.
> On Tue, Sep 4, 2018 at 2:22 PM Alan Tull <atull@kernel.org> wrote:
> >
> > Add devm_fpga_bridge_create() which is the managed
> > version of fpga_bridge_create().
> >
> > Change current bridge drivers to use
> > devm_fpga_bridge_create().
> >
> > Signed-off-by: Alan Tull <atull@kernel.org>
> Acked-by: Moritz Fischer <mdf@kernel.org>
> > Suggested-by: Federico Vaga <federico.vaga@cern.ch>
> > ---
> > v2: add suggested-by
> > ---
> > Documentation/driver-api/fpga/fpga-bridge.rst | 3 ++
> > drivers/fpga/altera-fpga2sdram.c | 8 ++-
> > drivers/fpga/altera-freeze-bridge.c | 13 ++---
> > drivers/fpga/altera-hps2fpga.c | 7 ++-
> > drivers/fpga/dfl-fme-br.c | 11 ++--
> > drivers/fpga/fpga-bridge.c | 72 +++++++++++++++++++++++----
> > drivers/fpga/xilinx-pr-decoupler.c | 4 +-
> > include/linux/fpga/fpga-bridge.h | 4 ++
> > 8 files changed, 84 insertions(+), 38 deletions(-)
> >
> > diff --git a/Documentation/driver-api/fpga/fpga-bridge.rst b/Documentation/driver-api/fpga/fpga-bridge.rst
> > index 2c2aaca..ebbcbde 100644
> > --- a/Documentation/driver-api/fpga/fpga-bridge.rst
> > +++ b/Documentation/driver-api/fpga/fpga-bridge.rst
> > @@ -11,6 +11,9 @@ API to implement a new FPGA bridge
> > :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_create
> >
> > .. kernel-doc:: drivers/fpga/fpga-bridge.c
> > diff --git a/drivers/fpga/altera-fpga2sdram.c b/drivers/fpga/altera-fpga2sdram.c
> > index 23660cc..a78e49c 100644
> > --- a/drivers/fpga/altera-fpga2sdram.c
> > +++ b/drivers/fpga/altera-fpga2sdram.c
> > @@ -121,18 +121,16 @@ 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 = fpga_bridge_create(dev, F2S_BRIDGE_NAME,
> > - &altera_fpga2sdram_br_ops, priv);
> > + br = devm_fpga_bridge_create(dev, F2S_BRIDGE_NAME,
> > + &altera_fpga2sdram_br_ops, priv);
> > if (!br)
> > return -ENOMEM;
> >
> > platform_set_drvdata(pdev, br);
> >
> > ret = fpga_bridge_register(br);
> > - if (ret) {
> > - fpga_bridge_free(br);
> > + if (ret)
> > return ret;
> > - }
> >
> > dev_info(dev, "driver initialized with handoff %08x\n", priv->mask);
> >
> > diff --git a/drivers/fpga/altera-freeze-bridge.c b/drivers/fpga/altera-freeze-bridge.c
> > index ffd586c..dd58c4a 100644
> > --- a/drivers/fpga/altera-freeze-bridge.c
> > +++ b/drivers/fpga/altera-freeze-bridge.c
> > @@ -213,7 +213,6 @@ static int altera_freeze_br_probe(struct platform_device *pdev)
> > struct fpga_bridge *br;
> > struct resource *res;
> > u32 status, revision;
> > - int ret;
> >
> > if (!np)
> > return -ENODEV;
> > @@ -245,20 +244,14 @@ static int altera_freeze_br_probe(struct platform_device *pdev)
> >
> > priv->base_addr = base_addr;
> >
> > - br = fpga_bridge_create(dev, FREEZE_BRIDGE_NAME,
> > - &altera_freeze_br_br_ops, priv);
> > + br = devm_fpga_bridge_create(dev, FREEZE_BRIDGE_NAME,
> > + &altera_freeze_br_br_ops, priv);
> > if (!br)
> > return -ENOMEM;
> >
> > platform_set_drvdata(pdev, br);
> >
> > - ret = fpga_bridge_register(br);
> > - if (ret) {
> > - fpga_bridge_free(br);
> > - return ret;
> > - }
> > -
> > - return 0;
> > + return fpga_bridge_register(br);
> > }
> >
> > static int altera_freeze_br_remove(struct platform_device *pdev)
> > diff --git a/drivers/fpga/altera-hps2fpga.c b/drivers/fpga/altera-hps2fpga.c
> > index a974d3f..77b95f2 100644
> > --- a/drivers/fpga/altera-hps2fpga.c
> > +++ b/drivers/fpga/altera-hps2fpga.c
> > @@ -180,7 +180,8 @@ static int alt_fpga_bridge_probe(struct platform_device *pdev)
> > }
> > }
> >
> > - br = fpga_bridge_create(dev, priv->name, &altera_hps2fpga_br_ops, priv);
> > + br = devm_fpga_bridge_create(dev, priv->name,
> > + &altera_hps2fpga_br_ops, priv);
> > if (!br) {
> > ret = -ENOMEM;
> > goto err;
> > @@ -190,12 +191,10 @@ static int alt_fpga_bridge_probe(struct platform_device *pdev)
> >
> > ret = fpga_bridge_register(br);
> > if (ret)
> > - goto err_free;
> > + goto err;
> >
> > return 0;
> >
> > -err_free:
> > - fpga_bridge_free(br);
> > err:
> > clk_disable_unprepare(priv->clk);
> >
> > diff --git a/drivers/fpga/dfl-fme-br.c b/drivers/fpga/dfl-fme-br.c
> > index 7cc041d..3ff9f3a 100644
> > --- a/drivers/fpga/dfl-fme-br.c
> > +++ b/drivers/fpga/dfl-fme-br.c
> > @@ -61,7 +61,6 @@ static int fme_br_probe(struct platform_device *pdev)
> > struct device *dev = &pdev->dev;
> > struct fme_br_priv *priv;
> > struct fpga_bridge *br;
> > - int ret;
> >
> > priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
> > if (!priv)
> > @@ -69,18 +68,14 @@ static int fme_br_probe(struct platform_device *pdev)
> >
> > priv->pdata = dev_get_platdata(dev);
> >
> > - br = fpga_bridge_create(dev, "DFL FPGA FME Bridge",
> > - &fme_bridge_ops, priv);
> > + br = devm_fpga_bridge_create(dev, "DFL FPGA FME Bridge",
> > + &fme_bridge_ops, priv);
> > if (!br)
> > return -ENOMEM;
> >
> > platform_set_drvdata(pdev, br);
> >
> > - ret = fpga_bridge_register(br);
> > - if (ret)
> > - fpga_bridge_free(br);
> > -
> > - return ret;
> > + return fpga_bridge_register(br);
> > }
> >
> > static int fme_br_remove(struct platform_device *pdev)
> > diff --git a/drivers/fpga/fpga-bridge.c b/drivers/fpga/fpga-bridge.c
> > index 24b8f98..c39d35f 100644
> > --- a/drivers/fpga/fpga-bridge.c
> > +++ b/drivers/fpga/fpga-bridge.c
> > @@ -324,6 +324,9 @@ ATTRIBUTE_GROUPS(fpga_bridge);
> > * @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
> > */
> > struct fpga_bridge *fpga_bridge_create(struct device *dev, const char *name,
> > @@ -378,8 +381,8 @@ struct fpga_bridge *fpga_bridge_create(struct device *dev, const char *name,
> > EXPORT_SYMBOL_GPL(fpga_bridge_create);
> >
> > /**
> > - * fpga_bridge_free - free a fpga bridge and its id
> > - * @bridge: FPGA bridge struct created by fpga_bridge_create
> > + * fpga_bridge_free - free a fpga bridge created by fpga_bridge_create()
> > + * @bridge: FPGA bridge struct
> > */
> > void fpga_bridge_free(struct fpga_bridge *bridge)
> > {
> > @@ -388,9 +391,56 @@ void fpga_bridge_free(struct fpga_bridge *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);
> > +}
> > +
> > /**
> > - * fpga_bridge_register - register a fpga bridge
> > - * @bridge: FPGA bridge struct created by fpga_bridge_create
> > + * devm_fpga_bridge_create - create and init a managed struct fpga_bridge
> > + * @dev: 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 a 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 *dev, 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(dev, name, br_ops, priv);
> > + if (!bridge) {
> > + devres_free(ptr);
> > + } else {
> > + *ptr = bridge;
> > + devres_add(dev, ptr);
> > + }
> > +
> > + return bridge;
> > +}
> > +EXPORT_SYMBOL_GPL(devm_fpga_bridge_create);
> > +
> > +/**
> > + * fpga_bridge_register - register a FPGA bridge
> > + *
> > + * @bridge: FPGA bridge struct
> > *
> > * Return: 0 for success, error code otherwise.
> > */
> > @@ -412,8 +462,15 @@ int fpga_bridge_register(struct fpga_bridge *bridge)
> > EXPORT_SYMBOL_GPL(fpga_bridge_register);
> >
> > /**
> > - * fpga_bridge_unregister - unregister and free a fpga bridge
> > - * @bridge: FPGA bridge struct created by fpga_bridge_create
> > + * fpga_bridge_unregister - unregister a FPGA bridge
> > + *
> > + * @bridge: FPGA bridge struct
> > + *
> > + * This function is intended for use in a FPGA bridge driver's remove function.
> > + * If the bridge was created with devm_fpga_bridge_create(), the bridge struct
> > + * will be automatically freed. If the bridge was created with
> > + * fpga_bridge_create(), the caller is responsible for freeing the bridge with
> > + * fpga_bridge_free().
>
> I find the formulation somewhat confusing, since it could be
> interpreted as if you
> used the devm_() functions you don't have to call unregister().
Yes I'm being too verbose and it's making things muddled. How about
if I take out the part that starts with "If bridge was created..."?
That just leaves "This function is intended for use in a FPGA bridge
driver's remove function."
Alan
> > */
> > void fpga_bridge_unregister(struct fpga_bridge *bridge)
> > {
> > @@ -430,9 +487,6 @@ EXPORT_SYMBOL_GPL(fpga_bridge_unregister);
> >
> > static void fpga_bridge_dev_release(struct device *dev)
> > {
> > - struct fpga_bridge *bridge = to_fpga_bridge(dev);
> > -
> > - fpga_bridge_free(bridge);
> > }
> >
> > static int __init fpga_bridge_dev_init(void)
> > diff --git a/drivers/fpga/xilinx-pr-decoupler.c b/drivers/fpga/xilinx-pr-decoupler.c
> > index 07ba153..6410361 100644
> > --- a/drivers/fpga/xilinx-pr-decoupler.c
> > +++ b/drivers/fpga/xilinx-pr-decoupler.c
> > @@ -121,8 +121,8 @@ static int xlnx_pr_decoupler_probe(struct platform_device *pdev)
> >
> > clk_disable(priv->clk);
> >
> > - br = fpga_bridge_create(&pdev->dev, "Xilinx PR Decoupler",
> > - &xlnx_pr_decoupler_br_ops, priv);
> > + br = devm_fpga_bridge_create(&pdev->dev, "Xilinx PR Decoupler",
> > + &xlnx_pr_decoupler_br_ops, priv);
> > if (!br) {
> > err = -ENOMEM;
> > goto err_clk;
> > diff --git a/include/linux/fpga/fpga-bridge.h b/include/linux/fpga/fpga-bridge.h
> > index ce550fc..817600a 100644
> > --- a/include/linux/fpga/fpga-bridge.h
> > +++ b/include/linux/fpga/fpga-bridge.h
> > @@ -69,4 +69,8 @@ void fpga_bridge_free(struct fpga_bridge *br);
> > int fpga_bridge_register(struct fpga_bridge *br);
> > 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 */
> > --
> > 2.7.4
> >
>
> Thanks,
>
> Moritz
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v2 5/8] dt-bindings: fpga: fix freeze controller compatible in region doc
2018-09-04 21:22 ` [PATCH v2 5/8] dt-bindings: fpga: fix freeze controller compatible in region doc Alan Tull
@ 2018-09-06 18:01 ` Alan Tull
0 siblings, 0 replies; 19+ messages in thread
From: Alan Tull @ 2018-09-06 18:01 UTC (permalink / raw)
To: Moritz Fischer, Jonathan Corbet
Cc: Randy Dunlap, linux-kernel, linux-fpga, Linux Doc Mailing List
On Tue, Sep 4, 2018 at 4:22 PM Alan Tull <atull@kernel.org> wrote:
OK I left off the DT folk. I'll resend this one patch separately.
Alan
>
> Documentation/devicetree/bindings/fpga/fpga-region.txt has an error
> regarding the freeze controller bridge, secifically:
>
> compatible = "altr,freeze-bridge";
>
> The compatibility string should be "altr,freeze-bridge-controller"
> as set forth in altera-freeze-bridge.txt.
>
> Signed-off-by: Alan Tull <atull@kernel.org>
> Reported-by: Dalon Westergreen <dalon.westergreen@intel.com>
> ---
> v2: no change in v2 of patchset
> ---
> Documentation/devicetree/bindings/fpga/fpga-region.txt | 4 ++--
> 1 file changed, 2 insertions(+), 2 deletions(-)
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v2 3/8] fpga: bridge: add devm_fpga_bridge_create
2018-09-05 15:38 ` Alan Tull
@ 2018-09-06 18:19 ` Moritz Fischer
2018-09-06 18:49 ` Alan Tull
0 siblings, 1 reply; 19+ messages in thread
From: Moritz Fischer @ 2018-09-06 18:19 UTC (permalink / raw)
To: Alan Tull
Cc: Moritz Fischer, Jonathan Corbet, Randy Dunlap, linux-kernel,
linux-fpga, Linux Doc Mailing List
Hi Alan,
On Wed, Sep 05, 2018 at 10:38:53AM -0500, Alan Tull wrote:
> > > - * fpga_bridge_unregister - unregister and free a fpga bridge
> > > - * @bridge: FPGA bridge struct created by fpga_bridge_create
> > > + * fpga_bridge_unregister - unregister a FPGA bridge
> > > + *
> > > + * @bridge: FPGA bridge struct
> > > + *
> > > + * This function is intended for use in a FPGA bridge driver's remove function.
> > > + * If the bridge was created with devm_fpga_bridge_create(), the bridge struct
> > > + * will be automatically freed. If the bridge was created with
> > > + * fpga_bridge_create(), the caller is responsible for freeing the bridge with
> > > + * fpga_bridge_free().
> >
> > I find the formulation somewhat confusing, since it could be
> > interpreted as if you
> > used the devm_() functions you don't have to call unregister().
>
> Yes I'm being too verbose and it's making things muddled. How about
> if I take out the part that starts with "If bridge was created..."?
> That just leaves "This function is intended for use in a FPGA bridge
> driver's remove function."
Sounds good.
Moritz
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v2 7/8] docs: fpga: document fpga manager flags
2018-09-04 21:22 ` [PATCH v2 7/8] docs: fpga: document fpga manager flags Alan Tull
@ 2018-09-06 18:42 ` Moritz Fischer
0 siblings, 0 replies; 19+ messages in thread
From: Moritz Fischer @ 2018-09-06 18:42 UTC (permalink / raw)
To: Alan Tull
Cc: Moritz Fischer, Jonathan Corbet, Randy Dunlap, linux-kernel,
linux-fpga, linux-doc
On Tue, Sep 04, 2018 at 04:22:36PM -0500, Alan Tull wrote:
> Add flags #defines to kerneldoc documentation in a
> useful place.
>
> Signed-off-by: Alan Tull <atull@kernel.org>
Acked-by: Moritz Fischer <mdf@kernel.org>
> ---
> v2: add description for FPGA_MGR_ENCRYPTED_BITSTREAM
> ---
> Documentation/driver-api/fpga/fpga-mgr.rst | 5 +++++
> include/linux/fpga/fpga-mgr.h | 20 ++++++++++++++------
> 2 files changed, 19 insertions(+), 6 deletions(-)
>
> diff --git a/Documentation/driver-api/fpga/fpga-mgr.rst b/Documentation/driver-api/fpga/fpga-mgr.rst
> index 431556d..db8885e 100644
> --- a/Documentation/driver-api/fpga/fpga-mgr.rst
> +++ b/Documentation/driver-api/fpga/fpga-mgr.rst
> @@ -183,6 +183,11 @@ API for implementing a new FPGA Manager driver
> API for programming an FPGA
> ---------------------------
>
> +FPGA Manager flags
> +
> +.. kernel-doc:: include/linux/fpga/fpga-mgr.h
> + :doc: FPGA Manager flags
> +
> .. kernel-doc:: include/linux/fpga/fpga-mgr.h
> :functions: fpga_image_info
>
> diff --git a/include/linux/fpga/fpga-mgr.h b/include/linux/fpga/fpga-mgr.h
> index 1ca02ce..e8ca62b 100644
> --- a/include/linux/fpga/fpga-mgr.h
> +++ b/include/linux/fpga/fpga-mgr.h
> @@ -53,12 +53,20 @@ enum fpga_mgr_states {
> FPGA_MGR_STATE_OPERATING,
> };
>
> -/*
> - * FPGA Manager flags
> - * FPGA_MGR_PARTIAL_RECONFIG: do partial reconfiguration if supported
> - * FPGA_MGR_EXTERNAL_CONFIG: FPGA has been configured prior to Linux booting
> - * FPGA_MGR_BITSTREAM_LSB_FIRST: SPI bitstream bit order is LSB first
> - * FPGA_MGR_COMPRESSED_BITSTREAM: FPGA bitstream is compressed
> +/**
> + * DOC: FPGA Manager flags
> + *
> + * Flags used in the &fpga_image_info->flags field
> + *
> + * %FPGA_MGR_PARTIAL_RECONFIG: do partial reconfiguration if supported
> + *
> + * %FPGA_MGR_EXTERNAL_CONFIG: FPGA has been configured prior to Linux booting
> + *
> + * %FPGA_MGR_ENCRYPTED_BITSTREAM: indicates bitstream is encrypted
> + *
> + * %FPGA_MGR_BITSTREAM_LSB_FIRST: SPI bitstream bit order is LSB first
> + *
> + * %FPGA_MGR_COMPRESSED_BITSTREAM: FPGA bitstream is compressed
> */
> #define FPGA_MGR_PARTIAL_RECONFIG BIT(0)
> #define FPGA_MGR_EXTERNAL_CONFIG BIT(1)
> --
> 2.7.4
>
Thanks for doing this,
Moritz
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v2 6/8] fpga: bridge: fix obvious function documentation error
2018-09-04 21:22 ` [PATCH v2 6/8] fpga: bridge: fix obvious function documentation error Alan Tull
@ 2018-09-06 18:43 ` Moritz Fischer
2018-09-06 21:28 ` Alan Tull
0 siblings, 1 reply; 19+ messages in thread
From: Moritz Fischer @ 2018-09-06 18:43 UTC (permalink / raw)
To: Alan Tull
Cc: Moritz Fischer, Jonathan Corbet, Randy Dunlap, linux-kernel,
linux-fpga, linux-doc
On Tue, Sep 04, 2018 at 04:22:35PM -0500, Alan Tull wrote:
> fpga_bridge_dev_match() returns a FPGA bridge struct, not a
> FPGA manager struct so s/manager/bridge/.
>
> Signed-off-by: Alan Tull <atull@kernel.org>
Acked-by: Moritz Fischer <mdf@kernel.org>
> ---
> v2: no change in v2 of patchset
> ---
> drivers/fpga/fpga-bridge.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/fpga/fpga-bridge.c b/drivers/fpga/fpga-bridge.c
> index c39d35f..7b0071a 100644
> --- a/drivers/fpga/fpga-bridge.c
> +++ b/drivers/fpga/fpga-bridge.c
> @@ -125,7 +125,7 @@ static int fpga_bridge_dev_match(struct device *dev, const void *data)
> *
> * Given a device, get an exclusive reference to a fpga bridge.
> *
> - * Return: fpga manager struct or IS_ERR() condition containing error code.
> + * Return: fpga bridge struct or IS_ERR() condition containing error code.
> */
> struct fpga_bridge *fpga_bridge_get(struct device *dev,
> struct fpga_image_info *info)
> --
> 2.7.4
>
Thanks,
Moritz
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v2 3/8] fpga: bridge: add devm_fpga_bridge_create
2018-09-06 18:19 ` Moritz Fischer
@ 2018-09-06 18:49 ` Alan Tull
0 siblings, 0 replies; 19+ messages in thread
From: Alan Tull @ 2018-09-06 18:49 UTC (permalink / raw)
To: Moritz Fischer
Cc: Moritz Fischer, Jonathan Corbet, Randy Dunlap, linux-kernel,
linux-fpga, Linux Doc Mailing List
On Thu, Sep 6, 2018 at 1:19 PM Moritz Fischer <mdf@kernel.org> wrote:
>
> Hi Alan,
>
> On Wed, Sep 05, 2018 at 10:38:53AM -0500, Alan Tull wrote:
> > > > - * fpga_bridge_unregister - unregister and free a fpga bridge
> > > > - * @bridge: FPGA bridge struct created by fpga_bridge_create
> > > > + * fpga_bridge_unregister - unregister a FPGA bridge
> > > > + *
> > > > + * @bridge: FPGA bridge struct
> > > > + *
> > > > + * This function is intended for use in a FPGA bridge driver's remove function.
> > > > + * If the bridge was created with devm_fpga_bridge_create(), the bridge struct
> > > > + * will be automatically freed. If the bridge was created with
> > > > + * fpga_bridge_create(), the caller is responsible for freeing the bridge with
> > > > + * fpga_bridge_free().
> > >
> > > I find the formulation somewhat confusing, since it could be
> > > interpreted as if you
> > > used the devm_() functions you don't have to call unregister().
> >
> > Yes I'm being too verbose and it's making things muddled. How about
> > if I take out the part that starts with "If bridge was created..."?
> > That just leaves "This function is intended for use in a FPGA bridge
> > driver's remove function."
>
> Sounds good.
OK, for v3 I'll make a similar change in patches 2 and 4.
Alan
>
> Moritz
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v2 6/8] fpga: bridge: fix obvious function documentation error
2018-09-06 18:43 ` Moritz Fischer
@ 2018-09-06 21:28 ` Alan Tull
0 siblings, 0 replies; 19+ messages in thread
From: Alan Tull @ 2018-09-06 21:28 UTC (permalink / raw)
To: Moritz Fischer
Cc: Jonathan Corbet, Randy Dunlap, linux-kernel, linux-fpga,
Linux Doc Mailing List
On Thu, Sep 6, 2018 at 1:43 PM Moritz Fischer <mdf@kernel.org> wrote:
Hi Moritz,
>
> On Tue, Sep 04, 2018 at 04:22:35PM -0500, Alan Tull wrote:
> > fpga_bridge_dev_match() returns a FPGA bridge struct, not a
> > FPGA manager struct so s/manager/bridge/.
> >
> > Signed-off-by: Alan Tull <atull@kernel.org>
> Acked-by: Moritz Fischer <mdf@kernel.org>
Thanks!
Alan
^ permalink raw reply [flat|nested] 19+ messages in thread
end of thread, other threads:[~2018-09-06 21:28 UTC | newest]
Thread overview: 19+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-09-04 21:22 [PATCH v2 0/8] fpga: add devm managed create APIs Alan Tull
2018-09-04 21:22 ` [PATCH v2 1/8] fpga: do not access region struct after fpga_region_unregister Alan Tull
2018-09-04 23:41 ` Moritz Fischer
2018-09-05 15:07 ` Alan Tull
2018-09-04 21:22 ` [PATCH v2 2/8] fpga: mgr: add devm_fpga_mgr_create Alan Tull
2018-09-04 21:22 ` [PATCH v2 3/8] fpga: bridge: add devm_fpga_bridge_create Alan Tull
2018-09-05 15:22 ` Moritz Fischer
2018-09-05 15:38 ` Alan Tull
2018-09-06 18:19 ` Moritz Fischer
2018-09-06 18:49 ` Alan Tull
2018-09-04 21:22 ` [PATCH v2 4/8] fpga: add devm_fpga_region_create Alan Tull
2018-09-04 21:22 ` [PATCH v2 5/8] dt-bindings: fpga: fix freeze controller compatible in region doc Alan Tull
2018-09-06 18:01 ` Alan Tull
2018-09-04 21:22 ` [PATCH v2 6/8] fpga: bridge: fix obvious function documentation error Alan Tull
2018-09-06 18:43 ` Moritz Fischer
2018-09-06 21:28 ` Alan Tull
2018-09-04 21:22 ` [PATCH v2 7/8] docs: fpga: document fpga manager flags Alan Tull
2018-09-06 18:42 ` Moritz Fischer
2018-09-04 21:22 ` [PATCH v2 8/8] docs: fpga: document programming fpgas using regions Alan Tull
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).