FPGA Manager Patches for 4.18
Subsystems (3)
Moritz Fischer
maintainercover FPGA Manager Patches for 4.18
Hi Greg,
Here's Alan's reworked patchset changing the API for creating and registering FPGA Managers, Bridges and Regions following your suggestions on the API.
These go on top of Paolo and Alan's patches that you queued up the other day.
Thanks,
Moritz
Alan Tull (4):
fpga: region: don't use drvdata in common fpga code
fpga: manager: change api, don't use drvdata
fpga: bridge: change api, don't use drvdata
fpga: region: change api, add fpga_region_create/free
Documentation/fpga/fpga-mgr.txt | 35 ++++++++++--- Documentation/fpga/fpga-region.txt | 3 +- drivers/fpga/altera-cvp.c | 19 +++++-- drivers/fpga/altera-fpga2sdram.c | 21 ++++++-- drivers/fpga/altera-freeze-bridge.c | 22 ++++++-- drivers/fpga/altera-hps2fpga.c | 24 +++++++-- drivers/fpga/altera-pr-ip-core.c | 18 ++++++- drivers/fpga/altera-ps-spi.c | 20 ++++++-- drivers/fpga/fpga-bridge.c | 70 +++++++++++++++++--------- drivers/fpga/fpga-mgr.c | 78 +++++++++++++++++++---------- drivers/fpga/fpga-region.c | 69 +++++++++++++++++++------ drivers/fpga/ice40-spi.c | 21 ++++++-- drivers/fpga/machxo2-spi.c | 20 ++++++-- drivers/fpga/of-fpga-region.c | 14 +++--- drivers/fpga/socfpga-a10.c | 14 ++++-- drivers/fpga/socfpga.c | 19 +++++-- drivers/fpga/ts73xx-fpga.c | 20 ++++++-- drivers/fpga/xilinx-pr-decoupler.c | 22 ++++++-- drivers/fpga/xilinx-spi.c | 20 ++++++-- drivers/fpga/zynq-fpga.c | 14 ++++-- include/linux/fpga/fpga-bridge.h | 9 ++-- include/linux/fpga/fpga-mgr.h | 10 ++-- include/linux/fpga/fpga-region.h | 11 ++-- 23 files changed, 429 insertions(+), 144 deletions(-)
Signature · 1 line
2.17.0
Moritz Fischer
maintainerPATCH 1/4 fpga: region: don't use drvdata in common fpga code
From: Alan Tull <[email protected]>
Changes to fpga_region_register function to not set drvdata.
Setting drvdata is fine for DT based devices that will have one region per platform device. However PCIe based devices may have multiple FPGA regions under one PCIe device. Without these changes, the PCIe solution has to create an extra device for each child region to hold drvdata.
--- drivers/fpga/fpga-region.c | 1 - drivers/fpga/of-fpga-region.c | 1 + 2 files changed, 1 insertion(+), 1 deletion(-)
drivers/fpga/fpga-region.c +0 -1
@@ -183,7 +183,6 @@ int fpga_region_register(struct device *dev, struct fpga_region *region) region->dev.parent = dev; region->dev.of_node = dev->of_node; region->dev.id = id; -dev_set_drvdata (dev, region); ret =dev_set_name (®ion->dev,"region%d" , id);if (ret)
drivers/fpga/of-fpga-region.c +1 -0
@@ -438,6 +438,7 @@ static int of_fpga_region_probe(struct platform_device *pdev) goto eprobe_mgr_put;of_platform_populate (np, fpga_region_of_match,NULL , ®ion->dev); +dev_set_drvdata (dev, region);dev_info (dev,"FPGA Region probed\n" );
Signature · 1 line
2.17.0
Moritz Fischer
maintainerPATCH 2/4 fpga: manager: change api, don't use drvdata
In reply to Moritz FischerFrom: Alan Tull <[email protected]>
Change fpga_mgr_register to not set or use drvdata. This supports the case where a PCIe device has more than one manager.
Add fpga_mgr_create/free functions. Change fpga_mgr_register and fpga_mgr_unregister functions to take the mgr struct as their only parameter.
struct fpga_manager *fpga_mgr_create(struct device *dev,
const char *name,
const struct fpga_manager_ops *mops,
void *priv);
void fpga_mgr_free(struct fpga_manager *mgr);
int fpga_mgr_register(struct fpga_manager *mgr);
void fpga_mgr_unregister(struct fpga_manager *mgr);Update the drivers that call fpga_mgr_register with the new API.
--- Documentation/fpga/fpga-mgr.txt | 35 ++++++++++---- drivers/fpga/altera-cvp.c | 19 ++++++-- drivers/fpga/altera-pr-ip-core.c | 18 +++++++- drivers/fpga/altera-ps-spi.c | 20 ++++++-- drivers/fpga/fpga-mgr.c | 78 +++++++++++++++++++++----------- drivers/fpga/ice40-spi.c | 21 +++++++-- drivers/fpga/machxo2-spi.c | 20 ++++++-- drivers/fpga/socfpga-a10.c | 14 ++++-- drivers/fpga/socfpga.c | 19 ++++++-- drivers/fpga/ts73xx-fpga.c | 20 ++++++-- drivers/fpga/xilinx-spi.c | 20 ++++++-- drivers/fpga/zynq-fpga.c | 14 ++++-- include/linux/fpga/fpga-mgr.h | 10 ++-- 13 files changed, 237 insertions(+), 71 deletions(-)
Documentation/fpga/fpga-mgr.txt +27 -8
@@ -63,17 +63,23 @@ The user should call fpga_mgr_lock and verify that it returns 0 before attempting to program the FPGA. Likewise, the user should call fpga_mgr_unlock when done programming the FPGA. +To alloc/free a FPGA manager struct: +------------------------------------ + + struct fpga_manager *fpga_mgr_create(struct device *dev, + const char *name, + const struct fpga_manager_ops *mops, + void *priv); + void fpga_mgr_free(struct fpga_manager *mgr); To register or unregister the low level FPGA-specific driver: ------------------------------------------------------------- - int fpga_mgr_register(struct device *dev, const char *name, - const struct fpga_manager_ops *mops, - void *priv); + int fpga_mgr_register(struct fpga_manager *mgr); - void fpga_mgr_unregister(struct device *dev); + void fpga_mgr_unregister(struct fpga_manager *mgr); -Use of these two functions is described below in "How To Support a new FPGA +Use of these functions is described below in "How To Support a new FPGA device."
@@ -148,6 +154,7 @@ static int socfpga_fpga_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct socfpga_fpga_priv *priv; + struct fpga_manager *mgr; int ret; priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
@@ -157,13 +164,25 @@ static int socfpga_fpga_probe(struct platform_device *pdev) /* ... do ioremaps, get interrupts, etc. and save them in priv... */ - return fpga_mgr_register(dev, "Altera SOCFPGA FPGA Manager", - &socfpga_fpga_ops, priv); + mgr = fpga_mgr_create(dev, "Altera SOCFPGA FPGA Manager", + &socfpga_fpga_ops, priv); + if (!mgr) + return -ENOMEM; + + platform_set_drvdata(pdev, mgr); + + ret = fpga_mgr_register(mgr); + if (ret) + fpga_mgr_free(mgr); + + return ret; } static int socfpga_fpga_remove(struct platform_device *pdev) { - fpga_mgr_unregister(&pdev->dev); + struct fpga_manager *mgr = platform_get_drvdata(pdev); + + fpga_mgr_unregister(mgr); return 0; }
drivers/fpga/altera-cvp.c +14 -5
@@ -401,6 +401,7 @@ static int altera_cvp_probe(struct pci_dev *pdev, const struct pci_device_id *dev_id) {struct altera_cvp_conf *conf; +struct fpga_manager *mgr;u16 cmd, val;int ret;
@@ -452,16 +453,24 @@ static int altera_cvp_probe(struct pci_dev *pdev,snprintf (conf->mgr_name,sizeof (conf->mgr_name),"%s @%s" ,ALTERA_CVP_MGR_NAME ,pci_name (pdev)); - ret =fpga_mgr_register (&pdev->dev, conf->mgr_name, - &altera_cvp_ops, conf); -if (ret) + mgr =fpga_mgr_create (&pdev->dev, conf->mgr_name, + &altera_cvp_ops, conf); +if (!mgr) +return -ENOMEM ; + +pci_set_drvdata (pdev, mgr); + + ret =fpga_mgr_register (mgr); +if (ret) { +fpga_mgr_free (mgr); goto err_unmap; + } ret =driver_create_file (&altera_cvp_driver.driver, &driver_attr_chkcfg);if (ret) {dev_err (&pdev->dev,"Can't create sysfs chkcfg file\n" ); -fpga_mgr_unregister (&pdev->dev); +fpga_mgr_unregister (mgr); goto err_unmap; }
@@ -483,7 +492,7 @@ static void altera_cvp_remove(struct pci_dev *pdev)u16 cmd;driver_remove_file (&altera_cvp_driver.driver, &driver_attr_chkcfg); -fpga_mgr_unregister (&pdev->dev); +fpga_mgr_unregister (mgr);pci_iounmap (pdev, conf->map);pci_release_region (pdev,CVP_BAR );pci_read_config_word (pdev,PCI_COMMAND , &cmd);
drivers/fpga/altera-pr-ip-core.c +16 -2
@@ -187,6 +187,8 @@ static const struct fpga_manager_ops alt_pr_ops = {int alt_pr_register (struct device *dev,void __iomem *reg_base) {struct alt_pr_priv *priv; +struct fpga_manager *mgr; +int ret;u32 val; priv =devm_kzalloc (dev,sizeof (*priv),GFP_KERNEL );
@@ -201,15 +203,27 @@ int alt_pr_register(struct device *dev, void __iomem *reg_base) (val &ALT_PR_CSR_STATUS_MSK ) >>ALT_PR_CSR_STATUS_SFT , (int)(val & ALT_PR_CSR_PR_START)); -return fpga_mgr_register (dev,dev_name (dev), &alt_pr_ops, priv); + mgr =fpga_mgr_create (dev,dev_name (dev), &alt_pr_ops, priv); +if (!mgr) +return -ENOMEM ; + +dev_set_drvdata (dev, mgr); + + ret =fpga_mgr_register (mgr); +if (ret) +fpga_mgr_free (mgr); + +return ret; }EXPORT_SYMBOL_GPL (alt_pr_register);int alt_pr_unregister (struct device *dev) { +struct fpga_manager *mgr =dev_get_drvdata (dev); +dev_dbg (dev,"%s\n" , __func__); -fpga_mgr_unregister (dev); +fpga_mgr_unregister (mgr);return 0 ; }
drivers/fpga/altera-ps-spi.c +17 -3
@@ -238,6 +238,8 @@ static int altera_ps_probe(struct spi_device *spi) {struct altera_ps_conf *conf;const struct of_device_id *of_id; +struct fpga_manager *mgr; +int ret; conf =devm_kzalloc (&spi->dev,sizeof (*conf),GFP_KERNEL );if (!conf)
@@ -273,13 +275,25 @@ static int altera_ps_probe(struct spi_device *spi)snprintf (conf->mgr_name,sizeof (conf->mgr_name),"%s %s" ,dev_driver_string (&spi->dev),dev_name (&spi->dev)); -return fpga_mgr_register (&spi->dev, conf->mgr_name, - &altera_ps_ops, conf); + mgr =fpga_mgr_create (&spi->dev, conf->mgr_name, + &altera_ps_ops, conf); +if (!mgr) +return -ENOMEM ; + +spi_set_drvdata (spi, mgr); + + ret =fpga_mgr_register (mgr); +if (ret) +fpga_mgr_free (mgr); + +return ret; }static int altera_ps_remove (struct spi_device *spi) { -fpga_mgr_unregister (&spi->dev); +struct fpga_manager *mgr =spi_get_drvdata (spi); + +fpga_mgr_unregister (mgr);return 0 ; }
drivers/fpga/fpga-mgr.c +52 -26
141 lines not on this page · raw message
drivers/fpga/ice40-spi.c +17 -4
@@ -133,6 +133,7 @@ static int ice40_fpga_probe(struct spi_device *spi) {struct device *dev = &spi->dev;struct ice40_fpga_priv *priv; +struct fpga_manager *mgr;int ret; priv =devm_kzalloc (&spi->dev,sizeof (*priv),GFP_KERNEL );
@@ -174,14 +175,26 @@ static int ice40_fpga_probe(struct spi_device *spi)return ret; } -/* Register with the FPGA manager */ -return fpga_mgr_register (dev,"Lattice iCE40 FPGA Manager" , - &ice40_fpga_ops, priv); + mgr =fpga_mgr_create (dev,"Lattice iCE40 FPGA Manager" , + &ice40_fpga_ops, priv); +if (!mgr) +return -ENOMEM ; + +spi_set_drvdata (spi, mgr); + + ret =fpga_mgr_register (mgr); +if (ret) +fpga_mgr_free (mgr); + +return ret; }static int ice40_fpga_remove (struct spi_device *spi) { -fpga_mgr_unregister (&spi->dev); +struct fpga_manager *mgr =spi_get_drvdata (spi); + +fpga_mgr_unregister (mgr); +return 0 ; }
drivers/fpga/machxo2-spi.c +16 -4
@@ -355,21 +355,33 @@ static const struct fpga_manager_ops machxo2_ops = {static int machxo2_spi_probe (struct spi_device *spi) {struct device *dev = &spi->dev; +struct fpga_manager *mgr; +int ret;if (spi->max_speed_hz >MACHXO2_MAX_SPEED ) {dev_err (dev,"Speed is too high\n" );return -EINVAL ; } -return fpga_mgr_register (dev,"Lattice MachXO2 SPI FPGA Manager" , - &machxo2_ops, spi); + mgr =fpga_mgr_create (dev,"Lattice MachXO2 SPI FPGA Manager" , + &machxo2_ops, spi); +if (!mgr) +return -ENOMEM ; + +spi_set_drvdata (spi, mgr); + + ret =fpga_mgr_register (mgr); +if (ret) +fpga_mgr_free (mgr); + +return ret; }static int machxo2_spi_remove (struct spi_device *spi) { -struct device *dev = &spi->dev; +struct fpga_manager *mgr =spi_get_drvdata (spi); -fpga_mgr_unregister (dev); +fpga_mgr_unregister (mgr);return 0 ; }
drivers/fpga/socfpga-a10.c +11 -3
@@ -482,6 +482,7 @@ static int socfpga_a10_fpga_probe(struct platform_device *pdev)struct device *dev = &pdev->dev;struct a10_fpga_priv *priv;void __iomem *reg_base; +struct fpga_manager *mgr;struct resource *res;int ret;
@@ -519,9 +520,16 @@ static int socfpga_a10_fpga_probe(struct platform_device *pdev)return -EBUSY ; } - ret =fpga_mgr_register (dev,"SoCFPGA Arria10 FPGA Manager" , - &socfpga_a10_fpga_mgr_ops, priv); + mgr =fpga_mgr_create (dev,"SoCFPGA Arria10 FPGA Manager" , + &socfpga_a10_fpga_mgr_ops, priv); +if (!mgr) +return -ENOMEM ; + +platform_set_drvdata (pdev, mgr); + + ret =fpga_mgr_register (mgr);if (ret) { +fpga_mgr_free (mgr);clk_disable_unprepare (priv->clk);return ret; }
@@ -534,7 +542,7 @@ static int socfpga_a10_fpga_remove(struct platform_device *pdev)struct fpga_manager *mgr =platform_get_drvdata (pdev);struct a10_fpga_priv *priv = mgr->priv; -fpga_mgr_unregister (&pdev->dev); +fpga_mgr_unregister (mgr);clk_disable_unprepare (priv->clk);return 0 ;
drivers/fpga/socfpga.c +16 -3
@@ -555,6 +555,7 @@ static int socfpga_fpga_probe(struct platform_device *pdev) {struct device *dev = &pdev->dev;struct socfpga_fpga_priv *priv; +struct fpga_manager *mgr;struct resource *res;int ret;
@@ -581,13 +582,25 @@ static int socfpga_fpga_probe(struct platform_device *pdev)if (ret)return ret; -return fpga_mgr_register (dev,"Altera SOCFPGA FPGA Manager" , - &socfpga_fpga_ops, priv); + mgr =fpga_mgr_create (dev,"Altera SOCFPGA FPGA Manager" , + &socfpga_fpga_ops, priv); +if (!mgr) +return -ENOMEM ; + +platform_set_drvdata (pdev, mgr); + + ret =fpga_mgr_register (mgr); +if (ret) +fpga_mgr_free (mgr); + +return ret; }static int socfpga_fpga_remove (struct platform_device *pdev) { -fpga_mgr_unregister (&pdev->dev); +struct fpga_manager *mgr =platform_get_drvdata (pdev); + +fpga_mgr_unregister (mgr);return 0 ; }
drivers/fpga/ts73xx-fpga.c +17 -3
@@ -116,7 +116,9 @@ static int ts73xx_fpga_probe(struct platform_device *pdev) {struct device *kdev = &pdev->dev;struct ts73xx_fpga_priv *priv; +struct fpga_manager *mgr;struct resource *res; +int ret; priv =devm_kzalloc (kdev,sizeof (*priv),GFP_KERNEL );if (!priv)
@@ -131,13 +133,25 @@ static int ts73xx_fpga_probe(struct platform_device *pdev)return PTR_ERR (priv->io_base); } -return fpga_mgr_register (kdev,"TS-73xx FPGA Manager" , - &ts73xx_fpga_ops, priv); + mgr =fpga_mgr_create (kdev,"TS-73xx FPGA Manager" , + &ts73xx_fpga_ops, priv); +if (!mgr) +return -ENOMEM ; + +platform_set_drvdata (pdev, mgr); + + ret =fpga_mgr_register (mgr); +if (ret) +fpga_mgr_free (mgr); + +return ret; }static int ts73xx_fpga_remove (struct platform_device *pdev) { -fpga_mgr_unregister (&pdev->dev); +struct fpga_manager *mgr =platform_get_drvdata (pdev); + +fpga_mgr_unregister (mgr);return 0 ; }
drivers/fpga/xilinx-spi.c +17 -3
@@ -143,6 +143,8 @@ static const struct fpga_manager_ops xilinx_spi_ops = {static int xilinx_spi_probe (struct spi_device *spi) {struct xilinx_spi_conf *conf; +struct fpga_manager *mgr; +int ret; conf =devm_kzalloc (&spi->dev,sizeof (*conf),GFP_KERNEL );if (!conf)
@@ -165,13 +167,25 @@ static int xilinx_spi_probe(struct spi_device *spi)return PTR_ERR (conf->done); } -return fpga_mgr_register (&spi->dev,"Xilinx Slave Serial FPGA Manager" , - &xilinx_spi_ops, conf); + mgr =fpga_mgr_create (&spi->dev,"Xilinx Slave Serial FPGA Manager" , + &xilinx_spi_ops, conf); +if (!mgr) +return -ENOMEM ; + +spi_set_drvdata (spi, mgr); + + ret =fpga_mgr_register (mgr); +if (ret) +fpga_mgr_free (mgr); + +return ret; }static int xilinx_spi_remove (struct spi_device *spi) { -fpga_mgr_unregister (&spi->dev); +struct fpga_manager *mgr =spi_get_drvdata (spi); + +fpga_mgr_unregister (mgr);return 0 ; }
drivers/fpga/zynq-fpga.c +11 -3
@@ -558,6 +558,7 @@ static int zynq_fpga_probe(struct platform_device *pdev) {struct device *dev = &pdev->dev;struct zynq_fpga_priv *priv; +struct fpga_manager *mgr;struct resource *res;int err;
@@ -613,10 +614,17 @@ static int zynq_fpga_probe(struct platform_device *pdev)clk_disable (priv->clk); - err =fpga_mgr_register (dev,"Xilinx Zynq FPGA Manager" , - &zynq_fpga_ops, priv); + mgr =fpga_mgr_create (dev,"Xilinx Zynq FPGA Manager" , + &zynq_fpga_ops, priv); +if (!mgr) +return -ENOMEM ; + +platform_set_drvdata (pdev, mgr); + + err =fpga_mgr_register (mgr);if (err) {dev_err (dev,"unable to register FPGA manager\n" ); +fpga_mgr_free (mgr);clk_unprepare (priv->clk);return err; }
@@ -632,7 +640,7 @@ static int zynq_fpga_remove(struct platform_device *pdev) mgr =platform_get_drvdata (pdev); priv = mgr->priv; -fpga_mgr_unregister (&pdev->dev); +fpga_mgr_unregister (mgr);clk_unprepare (priv->clk);
include/linux/fpga/fpga-mgr.h +6 -4
@@ -170,9 +170,11 @@ struct fpga_manager *fpga_mgr_get(struct device *dev);void fpga_mgr_put (struct fpga_manager *mgr); -int fpga_mgr_register (struct device *dev,const char *name, -const struct fpga_manager_ops *mops,void *priv); - -void fpga_mgr_unregister (struct device *dev); +struct fpga_manager *fpga_mgr_create (struct device *dev,const char *name, +const struct fpga_manager_ops *mops, +void *priv); +void fpga_mgr_free (struct fpga_manager *mgr); +int fpga_mgr_register (struct fpga_manager *mgr); +void fpga_mgr_unregister (struct fpga_manager *mgr);#endif /*_LINUX_FPGA_MGR_H */
Signature · 1 line
2.17.0
Re: [PATCH 2/4] fpga: manager: change api, don't use drvdata
Quoted 17 lines · Moritz Fischer
From: Alan Tull <[email protected]>
Change
fpga_mgr_registerto not set or use drvdata. This supports the case where a PCIe device has more than one manager.Add fpga_mgr_create/free functions. Change
fpga_mgr_registerandfpga_mgr_unregisterfunctions to take the mgr struct as their only parameter.struct fpga_manager *fpga_mgr_create(struct device *dev, const char *name, const struct fpga_manager_ops *mops, void *priv); void fpga_mgr_free(struct fpga_manager *mgr); int fpga_mgr_register(struct fpga_manager *mgr); void fpga_mgr_unregister(struct fpga_manager *mgr);
Quoted 1 line
Update the drivers that call
fpga_mgr_registerwith the new API.
Apologies for chiming in so late, this commit does not make it clear that fpga_mgr_unregister() now also free the 'mgr' argument by calling fpga_mgr_free(), this is kind of detail, but an API should make that clear IMHO.
Thanks
Signature · 1 line
Florian
Re: [PATCH 2/4] fpga: manager: change api, don't use drvdata
Quoted 18 lines · Florian Fainelli
Quoted 17 lines · Moritz Fischer
From: Alan Tull <[email protected]>
Change
fpga_mgr_registerto not set or use drvdata. This supports the case where a PCIe device has more than one manager.Add fpga_mgr_create/free functions. Change
fpga_mgr_registerandfpga_mgr_unregisterfunctions to take the mgr struct as their only parameter.struct fpga_manager *fpga_mgr_create(struct device *dev, const char *name, const struct fpga_manager_ops *mops, void *priv); void fpga_mgr_free(struct fpga_manager *mgr); int fpga_mgr_register(struct fpga_manager *mgr); void fpga_mgr_unregister(struct fpga_manager *mgr);
Quoted 6 lines
Quoted 1 line
Update the drivers that call
fpga_mgr_registerwith the new API.Apologies for chiming in so late, this commit does not make it clear that
fpga_mgr_unregister()now also free the 'mgr' argument by callingfpga_mgr_free(), this is kind of detail, but an API should make that clear IMHO.
If people follow the usage information, in Documentation/fpga/fpga-mgr.txt, they'll do the right thing. But I can add a patch that clarifies the description of fpga_mgr_unregister in fpga-mgr.c that it "unregisters and frees" the manager.
Quoted 4 lines
Thanks
--
Florian
Re: [PATCH 2/4] fpga: manager: change api, don't use drvdata
Quoted 26 lines · Alan Tull
Quoted 18 lines · Florian Fainelli
Quoted 17 lines · Moritz Fischer
From: Alan Tull <[email protected]>
Change
fpga_mgr_registerto not set or use drvdata. This supports the case where a PCIe device has more than one manager.Add fpga_mgr_create/free functions. Change
fpga_mgr_registerandfpga_mgr_unregisterfunctions to take the mgr struct as their only parameter.struct fpga_manager *fpga_mgr_create(struct device *dev, const char *name, const struct fpga_manager_ops *mops, void *priv); void fpga_mgr_free(struct fpga_manager *mgr); int fpga_mgr_register(struct fpga_manager *mgr); void fpga_mgr_unregister(struct fpga_manager *mgr);Quoted 6 lines
Quoted 1 line
Update the drivers that call
fpga_mgr_registerwith the new API.Apologies for chiming in so late, this commit does not make it clear that
fpga_mgr_unregister()now also free the 'mgr' argument by callingfpga_mgr_free(), this is kind of detail, but an API should make that clear IMHO.
Quoted 4 lines
If people follow the usage information, in
Documentation/fpga/fpga-mgr.txt, they'll do the right thing. But I can add a patch that clarifies the description offpga_mgr_unregisterinfpga-mgr.cthat it "unregisters and frees" the manager.
Just mentioning that because not all APIs do this, take the network
devices: there is an unregister_netdev() and a free_netdev(). Either way is fine with me as long as it is documented as such, I had to look at the API implementation to figure out that, no, all the drivers were not leaking their fpga_manager instance in their .remove() function :)
Signature · 1 line
Florian
Moritz Fischer
maintainerPATCH 3/4 fpga: bridge: change api, don't use drvdata
In reply to Moritz FischerFrom: Alan Tull <[email protected]>
Change fpga_bridge_register to not set drvdata. This is to support the case where a PCIe device can have more than one bridge.
Add API functions to create/free the fpga bridge struct. Change fpga_bridge_register/unregister to take FPGA bridge struct as the only parameter.
struct fpga_bridge
*fpga_bridge_create(struct device *dev, const char *name,
const struct fpga_bridge_ops *br_ops,
void *priv);
void fpga_bridge_free(struct fpga_bridge *br);
int fpga_bridge_register(struct fpga_bridge *br);
void fpga_bridge_unregister(struct fpga_bridge *br);Update the drivers that call fpga_bridge_register with the new API.
--- drivers/fpga/altera-fpga2sdram.c | 21 ++++++--- drivers/fpga/altera-freeze-bridge.c | 22 +++++++-- drivers/fpga/altera-hps2fpga.c | 24 +++++++--- drivers/fpga/fpga-bridge.c | 70 +++++++++++++++++++---------- drivers/fpga/xilinx-pr-decoupler.c | 22 ++++++--- include/linux/fpga/fpga-bridge.h | 9 ++-- 6 files changed, 123 insertions(+), 45 deletions(-)
drivers/fpga/altera-fpga2sdram.c +16 -5
@@ -106,6 +106,7 @@ static int alt_fpga_bridge_probe(struct platform_device *pdev) {struct device *dev = &pdev->dev;struct alt_fpga2sdram_data *priv; +struct fpga_bridge *br;u32 enable;struct regmap *sysmgr;int ret =0 ;
@@ -131,10 +132,18 @@ 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); - ret =fpga_bridge_register (dev,F2S_BRIDGE_NAME , - &altera_fpga2sdram_br_ops, priv); -if (ret) + br =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);return ret; + }dev_info (dev,"driver initialized with handoff %08x\n" , priv->mask);
@@ -146,7 +155,7 @@ static int alt_fpga_bridge_probe(struct platform_device *pdev) (enable ? "enabling" : "disabling")); ret =_alt_fpga2sdram_enable_set (priv, enable);if (ret) { -fpga_bridge_unregister (&pdev->dev); +fpga_bridge_unregister (br);return ret; } }
@@ -157,7 +166,9 @@ static int alt_fpga_bridge_probe(struct platform_device *pdev)static int alt_fpga_bridge_remove (struct platform_device *pdev) { -fpga_bridge_unregister (&pdev->dev); +struct fpga_bridge *br =platform_get_drvdata (pdev); + +fpga_bridge_unregister (br);return 0 ; }
drivers/fpga/altera-freeze-bridge.c +19 -3
@@ -221,8 +221,10 @@ static int altera_freeze_br_probe(struct platform_device *pdev)struct device_node *np = pdev->dev.of_node;void __iomem *base_addr;struct altera_freeze_br_data *priv; +struct fpga_bridge *br;struct resource *res;u32 status, revision; +int ret;if (!np)return -ENODEV ;
@@ -254,13 +256,27 @@ static int altera_freeze_br_probe(struct platform_device *pdev) priv->base_addr = base_addr; -return fpga_bridge_register (dev,FREEZE_BRIDGE_NAME , - &altera_freeze_br_br_ops, priv); + br =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 ; }static int altera_freeze_br_remove (struct platform_device *pdev) { -fpga_bridge_unregister (&pdev->dev); +struct fpga_bridge *br =platform_get_drvdata (pdev); + +fpga_bridge_unregister (br);return 0 ; }
drivers/fpga/altera-hps2fpga.c +19 -5
@@ -139,6 +139,7 @@ static int alt_fpga_bridge_probe(struct platform_device *pdev)struct device *dev = &pdev->dev;struct altera_hps2fpga_data *priv;const struct of_device_id *of_id; +struct fpga_bridge *br;u32 enable;int ret;
@@ -190,11 +191,24 @@ static int alt_fpga_bridge_probe(struct platform_device *pdev) } } - ret =fpga_bridge_register (dev, priv->name, &altera_hps2fpga_br_ops, - priv); -err: + br =fpga_bridge_create (dev, priv->name, &altera_hps2fpga_br_ops, priv); +if (!br) { + ret = -ENOMEM ; + goto err; + } + +platform_set_drvdata (pdev, br); + + ret =fpga_bridge_register (br);if (ret) -clk_disable_unprepare (priv->clk); + goto err_free; + +return 0 ; + +err_free: +fpga_bridge_free (br); +err: +clk_disable_unprepare (priv->clk);return ret; }
@@ -204,7 +218,7 @@ static int alt_fpga_bridge_remove(struct platform_device *pdev)struct fpga_bridge *bridge =platform_get_drvdata (pdev);struct altera_hps2fpga_data *priv = bridge->priv; -fpga_bridge_unregister (&pdev->dev); +fpga_bridge_unregister (bridge);clk_disable_unprepare (priv->clk);
drivers/fpga/fpga-bridge.c +46 -24
122 lines not on this page · raw message
drivers/fpga/xilinx-pr-decoupler.c +17 -5
@@ -94,6 +94,7 @@ MODULE_DEVICE_TABLE(of, xlnx_pr_decoupler_of_match);static int xlnx_pr_decoupler_probe (struct platform_device *pdev) {struct xlnx_pr_decoupler_data *priv; +struct fpga_bridge *br;int err;struct resource *res;
@@ -120,16 +121,27 @@ static int xlnx_pr_decoupler_probe(struct platform_device *pdev)clk_disable (priv->clk); - err =fpga_bridge_register (&pdev->dev,"Xilinx PR Decoupler" , - &xlnx_pr_decoupler_br_ops, priv); + br =fpga_bridge_create (&pdev->dev,"Xilinx PR Decoupler" , + &xlnx_pr_decoupler_br_ops, priv); +if (!br) { + err = -ENOMEM ; + goto err_clk; + } + +platform_set_drvdata (pdev, br); + err =fpga_bridge_register (br);if (err) {dev_err (&pdev->dev,"unable to register Xilinx PR Decoupler" ); -clk_unprepare (priv->clk); -return err; + goto err_clk; }return 0 ; + +err_clk: +clk_unprepare (priv->clk); + +return err; }static int xlnx_pr_decoupler_remove (struct platform_device *pdev)
@@ -137,7 +149,7 @@ static int xlnx_pr_decoupler_remove(struct platform_device *pdev)struct fpga_bridge *bridge =platform_get_drvdata (pdev);struct xlnx_pr_decoupler_data *p = bridge->priv; -fpga_bridge_unregister (&pdev->dev); +fpga_bridge_unregister (bridge);clk_unprepare (p->clk);
include/linux/fpga/fpga-bridge.h +6 -3
@@ -62,8 +62,11 @@ int of_fpga_bridge_get_to_list(struct device_node *np,struct fpga_image_info *info, struct list_head *bridge_list); -int fpga_bridge_register (struct device *dev,const char *name, -const struct fpga_bridge_ops *br_ops,void *priv); -void fpga_bridge_unregister (struct device *dev); +struct fpga_bridge *fpga_bridge_create (struct device *dev,const char *name, +const struct fpga_bridge_ops *br_ops, +void *priv); +void fpga_bridge_free (struct fpga_bridge *br); +int fpga_bridge_register (struct fpga_bridge *br); +void fpga_bridge_unregister (struct fpga_bridge *br);#endif /* _LINUX_FPGA_BRIDGE_H */
Signature · 1 line
2.17.0
Moritz Fischer
maintainerPATCH 4/4 fpga: region: change api, add fpga_region_create/free
In reply to Moritz FischerFrom: Alan Tull <[email protected]>
Add fpga_region_create/free API functions.
Change fpga_region_register to take FPGA region struct as the only parameter. Change fpga_region_unregister to return void.
struct fpga_region *fpga_region_create(struct device *dev,
struct fpga_manager *mgr,
int (*get_bridges)(struct fpga_region *));
void fpga_region_free(struct fpga_region *region);
int fpga_region_register(struct fpga_region *region);
void fpga_region_unregister(struct fpga_region *region);Remove groups storage from struct fpga_region, it's not needed. Callers can just "region->dev.groups = groups;" after calling fpga_region_create.
Update the drivers that call fpga_region_register with the new API.
--- Documentation/fpga/fpga-region.txt | 3 +- drivers/fpga/fpga-region.c | 68 ++++++++++++++++++++++++------ drivers/fpga/of-fpga-region.c | 13 +++--- include/linux/fpga/fpga-region.h | 11 +++-- 4 files changed, 68 insertions(+), 27 deletions(-)
Documentation/fpga/fpga-region.txt +1 -2
@@ -42,8 +42,7 @@ The FPGA region API To register or unregister a region: ----------------------------------- - int fpga_region_register(struct device *dev, - struct fpga_region *region); + int fpga_region_register(struct fpga_region *region); int fpga_region_unregister(struct fpga_region *region); An example of usage can be seen in the probe function of [3]
drivers/fpga/fpga-region.c +55 -13
103 lines not on this page · raw message
drivers/fpga/of-fpga-region.c +5 -8
@@ -422,20 +422,15 @@ static int of_fpga_region_probe(struct platform_device *pdev)if (IS_ERR (mgr))return -EPROBE_DEFER ; - region =devm_kzalloc (dev,sizeof (*region),GFP_KERNEL ); + region =fpga_region_create (dev, mgr, of_fpga_region_get_bridges);if (!region) { ret = -ENOMEM ; goto eprobe_mgr_put; } - region->mgr = mgr; - -/* Specify how to get bridges for this type of region. */ - region->get_bridges = of_fpga_region_get_bridges; - - ret =fpga_region_register (dev, region); + ret =fpga_region_register (region);if (ret) - goto eprobe_mgr_put; + goto eprobe_free;of_platform_populate (np, fpga_region_of_match,NULL , ®ion->dev);dev_set_drvdata (dev, region);
@@ -444,6 +439,8 @@ 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;
include/linux/fpga/fpga-region.h +7 -4
@@ -14,7 +14,6 @@* @info: FPGA image info * @priv: private data * @get_bridges: optional function to get bridges to a list -* @groups: optional attribute groups. */ struct fpga_region {struct device dev;
@@ -24,7 +23,6 @@ struct fpga_region {struct fpga_image_info *info;void *priv;int (*get_bridges)(struct fpga_region *region); -const struct attribute_group **groups; };#define to_fpga_region (d) container_of(d, struct fpga_region, dev)
@@ -34,7 +32,12 @@ struct fpga_region *fpga_region_class_find( int (*match)(struct device *, const void *));int fpga_region_program_fpga (struct fpga_region *region); -int fpga_region_register (struct device *dev,struct fpga_region *region); -int fpga_region_unregister (struct fpga_region *region); + +struct fpga_region +*fpga_region_create (struct device *dev,struct fpga_manager *mgr, +int (*get_bridges)(struct fpga_region *)); +void fpga_region_free (struct fpga_region *region); +int fpga_region_register (struct fpga_region *region); +void fpga_region_unregister (struct fpga_region *region);#endif /* _FPGA_REGION_H */
Signature · 1 line
2.17.0