FPGA Manager changes for 5.17-rc1

Russ' patches rework the way we register FPGA managers, regions and
 bridges by simplifying the functions into a single register call.
 
 Nathan's patch addresses an unused variable warning that was introduced
 by Russ' patches.
 
 Yang's patch addresses a kernel doc warning.
 
 All patches have been reviewed on the mailing list, and have been in the
 last few linux-next releases (as part of our for-next branch) without issues.
 
 Signed-off-by: Moritz Fischer <mdf@kernel.org>
 -----BEGIN PGP SIGNATURE-----
 
 iIUEABYIAC0WIQSdhnt2PwibB65UG0C3mJX/Vsn7uQUCYbz4vQ8cbWRmQGtlcm5l
 bC5vcmcACgkQt5iV/1bJ+7mdsAEA1wiVjcmpJZGb+3HoMxdLIJGQ+BV341eXpDp3
 AYS9Hx4A/i8jZ4YqrFe+v9IgXe6Arq2ePzIW/FpacwijobMBiHQE
 =S1TU
 -----END PGP SIGNATURE-----

Merge tag 'fpga-for-5.17-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/mdf/linux-fpga into char-misc-next

Moritz writes:

FPGA Manager changes for 5.17-rc1

Russ' patches rework the way we register FPGA managers, regions and
bridges by simplifying the functions into a single register call.

Nathan's patch addresses an unused variable warning that was introduced
by Russ' patches.

Yang's patch addresses a kernel doc warning.

All patches have been reviewed on the mailing list, and have been in the
last few linux-next releases (as part of our for-next branch) without issues.

Signed-off-by: Moritz Fischer <mdf@kernel.org>

* tag 'fpga-for-5.17-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/mdf/linux-fpga:
  fpga: region: fix kernel-doc
  fpga: stratix10-soc: Do not use ret uninitialized in s10_probe()
  fpga: region: Use standard dev_release for class driver
  fpga: bridge: Use standard dev_release for class driver
  fpga: mgr: Use standard dev_release for class driver
This commit is contained in:
Greg Kroah-Hartman 2021-12-21 10:05:01 +01:00
Родитель 1b18af40c1 98ceca2f29
Коммит a4c1aaf97b
31 изменённых файлов: 397 добавлений и 528 удалений

Просмотреть файл

@ -6,8 +6,7 @@ API to implement a new FPGA bridge
* struct fpga_bridge - The FPGA Bridge structure
* struct fpga_bridge_ops - Low level Bridge driver ops
* devm_fpga_bridge_create() - Allocate and init a bridge struct
* fpga_bridge_register() - Register a bridge
* fpga_bridge_register() - Create and register a bridge
* fpga_bridge_unregister() - Unregister a bridge
.. kernel-doc:: include/linux/fpga/fpga-bridge.h
@ -16,9 +15,6 @@ API to implement a new FPGA bridge
.. kernel-doc:: include/linux/fpga/fpga-bridge.h
:functions: fpga_bridge_ops
.. kernel-doc:: drivers/fpga/fpga-bridge.c
:functions: devm_fpga_bridge_create
.. kernel-doc:: drivers/fpga/fpga-bridge.c
:functions: fpga_bridge_register

Просмотреть файл

@ -24,7 +24,7 @@ How to support a new FPGA device
--------------------------------
To add another FPGA manager, write a driver that implements a set of ops. The
probe function calls fpga_mgr_register(), such as::
probe function calls fpga_mgr_register() or fpga_mgr_register_full(), such as::
static const struct fpga_manager_ops socfpga_fpga_ops = {
.write_init = socfpga_fpga_ops_configure_init,
@ -49,14 +49,14 @@ probe function calls fpga_mgr_register(), such as::
* them in priv
*/
mgr = devm_fpga_mgr_create(dev, "Altera SOCFPGA FPGA Manager",
&socfpga_fpga_ops, priv);
if (!mgr)
return -ENOMEM;
mgr = fpga_mgr_register(dev, "Altera SOCFPGA FPGA Manager",
&socfpga_fpga_ops, priv);
if (IS_ERR(mgr))
return PTR_ERR(mgr);
platform_set_drvdata(pdev, mgr);
return fpga_mgr_register(mgr);
return 0;
}
static int socfpga_fpga_remove(struct platform_device *pdev)
@ -68,6 +68,11 @@ probe function calls fpga_mgr_register(), such as::
return 0;
}
Alternatively, the probe function could call one of the resource managed
register functions, devm_fpga_mgr_register() or devm_fpga_mgr_register_full().
When these functions are used, the parameter syntax is the same, but the call
to fpga_mgr_unregister() should be removed. In the above example, the
socfpga_fpga_remove() function would not be required.
The ops will implement whatever device specific register writes are needed to
do the programming sequence for this particular FPGA. These ops return 0 for
@ -104,8 +109,14 @@ API for implementing a new FPGA Manager driver
* ``fpga_mgr_states`` - Values for :c:expr:`fpga_manager->state`.
* struct fpga_manager - the FPGA manager struct
* struct fpga_manager_ops - Low level FPGA manager driver ops
* devm_fpga_mgr_create() - Allocate and init a manager struct
* fpga_mgr_register() - Register an FPGA manager
* struct fpga_manager_info - Parameter structure for fpga_mgr_register_full()
* fpga_mgr_register_full() - Create and register an FPGA manager using the
fpga_mgr_info structure to provide the full flexibility of options
* fpga_mgr_register() - Create and register an FPGA manager using standard
arguments
* devm_fpga_mgr_register_full() - Resource managed version of
fpga_mgr_register_full()
* devm_fpga_mgr_register() - Resource managed version of fpga_mgr_register()
* fpga_mgr_unregister() - Unregister an FPGA manager
.. kernel-doc:: include/linux/fpga/fpga-mgr.h
@ -117,11 +128,20 @@ API for implementing a new FPGA Manager driver
.. kernel-doc:: include/linux/fpga/fpga-mgr.h
:functions: fpga_manager_ops
.. kernel-doc:: include/linux/fpga/fpga-mgr.h
:functions: fpga_manager_info
.. kernel-doc:: drivers/fpga/fpga-mgr.c
:functions: devm_fpga_mgr_create
:functions: fpga_mgr_register_full
.. kernel-doc:: drivers/fpga/fpga-mgr.c
:functions: fpga_mgr_register
.. kernel-doc:: drivers/fpga/fpga-mgr.c
:functions: devm_fpga_mgr_register_full
.. kernel-doc:: drivers/fpga/fpga-mgr.c
:functions: devm_fpga_mgr_register
.. kernel-doc:: drivers/fpga/fpga-mgr.c
:functions: fpga_mgr_unregister

Просмотреть файл

@ -46,8 +46,11 @@ API to add a new FPGA region
----------------------------
* struct fpga_region - The FPGA region struct
* devm_fpga_region_create() - Allocate and init a region struct
* fpga_region_register() - Register an FPGA region
* struct fpga_region_info - Parameter structure for fpga_region_register_full()
* fpga_region_register_full() - Create and register an FPGA region using the
fpga_region_info structure to provide the full flexibility of options
* fpga_region_register() - Create and register an FPGA region using standard
arguments
* fpga_region_unregister() - Unregister an FPGA region
The FPGA region's probe function will need to get a reference to the FPGA
@ -75,8 +78,11 @@ following APIs to handle building or tearing down that list.
.. kernel-doc:: include/linux/fpga/fpga-region.h
:functions: fpga_region
.. kernel-doc:: include/linux/fpga/fpga-region.h
:functions: fpga_region_info
.. kernel-doc:: drivers/fpga/fpga-region.c
:functions: devm_fpga_region_create
:functions: fpga_region_register_full
.. kernel-doc:: drivers/fpga/fpga-region.c
:functions: fpga_region_register

Просмотреть файл

@ -652,19 +652,15 @@ 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 = devm_fpga_mgr_create(&pdev->dev, conf->mgr_name,
&altera_cvp_ops, conf);
if (!mgr) {
ret = -ENOMEM;
mgr = fpga_mgr_register(&pdev->dev, conf->mgr_name,
&altera_cvp_ops, conf);
if (IS_ERR(mgr)) {
ret = PTR_ERR(mgr);
goto err_unmap;
}
pci_set_drvdata(pdev, mgr);
ret = fpga_mgr_register(mgr);
if (ret)
goto err_unmap;
return 0;
err_unmap:

Просмотреть файл

@ -121,17 +121,13 @@ static int alt_fpga_bridge_probe(struct platform_device *pdev)
/* Get f2s bridge configuration saved in handoff register */
regmap_read(sysmgr, SYSMGR_ISWGRP_HANDOFF3, &priv->mask);
br = devm_fpga_bridge_create(dev, F2S_BRIDGE_NAME,
&altera_fpga2sdram_br_ops, priv);
if (!br)
return -ENOMEM;
br = fpga_bridge_register(dev, F2S_BRIDGE_NAME,
&altera_fpga2sdram_br_ops, priv);
if (IS_ERR(br))
return PTR_ERR(br);
platform_set_drvdata(pdev, br);
ret = fpga_bridge_register(br);
if (ret)
return ret;
dev_info(dev, "driver initialized with handoff %08x\n", priv->mask);
if (!of_property_read_u32(dev->of_node, "bridge-enable", &enable)) {

Просмотреть файл

@ -246,14 +246,14 @@ static int altera_freeze_br_probe(struct platform_device *pdev)
priv->base_addr = base_addr;
br = devm_fpga_bridge_create(dev, FREEZE_BRIDGE_NAME,
&altera_freeze_br_br_ops, priv);
if (!br)
return -ENOMEM;
br = fpga_bridge_register(dev, FREEZE_BRIDGE_NAME,
&altera_freeze_br_br_ops, priv);
if (IS_ERR(br))
return PTR_ERR(br);
platform_set_drvdata(pdev, br);
return fpga_bridge_register(br);
return 0;
}
static int altera_freeze_br_remove(struct platform_device *pdev)

Просмотреть файл

@ -180,19 +180,15 @@ static int alt_fpga_bridge_probe(struct platform_device *pdev)
}
}
br = devm_fpga_bridge_create(dev, priv->name,
&altera_hps2fpga_br_ops, priv);
if (!br) {
ret = -ENOMEM;
br = fpga_bridge_register(dev, priv->name,
&altera_hps2fpga_br_ops, priv);
if (IS_ERR(br)) {
ret = PTR_ERR(br);
goto err;
}
platform_set_drvdata(pdev, br);
ret = fpga_bridge_register(br);
if (ret)
goto err;
return 0;
err:

Просмотреть файл

@ -191,11 +191,8 @@ 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 = devm_fpga_mgr_create(dev, dev_name(dev), &alt_pr_ops, priv);
if (!mgr)
return -ENOMEM;
return devm_fpga_mgr_register(dev, mgr);
mgr = devm_fpga_mgr_register(dev, dev_name(dev), &alt_pr_ops, priv);
return PTR_ERR_OR_ZERO(mgr);
}
EXPORT_SYMBOL_GPL(alt_pr_register);

Просмотреть файл

@ -302,12 +302,9 @@ 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 = devm_fpga_mgr_create(&spi->dev, conf->mgr_name,
&altera_ps_ops, conf);
if (!mgr)
return -ENOMEM;
return devm_fpga_mgr_register(&spi->dev, mgr);
mgr = devm_fpga_mgr_register(&spi->dev, conf->mgr_name,
&altera_ps_ops, conf);
return PTR_ERR_OR_ZERO(mgr);
}
static const struct spi_device_id altera_ps_spi_ids[] = {

Просмотреть файл

@ -68,14 +68,14 @@ static int fme_br_probe(struct platform_device *pdev)
priv->pdata = dev_get_platdata(dev);
br = devm_fpga_bridge_create(dev, "DFL FPGA FME Bridge",
&fme_bridge_ops, priv);
if (!br)
return -ENOMEM;
br = fpga_bridge_register(dev, "DFL FPGA FME Bridge",
&fme_bridge_ops, priv);
if (IS_ERR(br))
return PTR_ERR(br);
platform_set_drvdata(pdev, br);
return fpga_bridge_register(br);
return 0;
}
static int fme_br_remove(struct platform_device *pdev)

Просмотреть файл

@ -276,7 +276,7 @@ static void fme_mgr_get_compat_id(void __iomem *fme_pr,
static int fme_mgr_probe(struct platform_device *pdev)
{
struct dfl_fme_mgr_pdata *pdata = dev_get_platdata(&pdev->dev);
struct fpga_compat_id *compat_id;
struct fpga_manager_info info = { 0 };
struct device *dev = &pdev->dev;
struct fme_mgr_priv *priv;
struct fpga_manager *mgr;
@ -296,20 +296,16 @@ static int fme_mgr_probe(struct platform_device *pdev)
return PTR_ERR(priv->ioaddr);
}
compat_id = devm_kzalloc(dev, sizeof(*compat_id), GFP_KERNEL);
if (!compat_id)
info.name = "DFL FME FPGA Manager";
info.mops = &fme_mgr_ops;
info.priv = priv;
info.compat_id = devm_kzalloc(dev, sizeof(*info.compat_id), GFP_KERNEL);
if (!info.compat_id)
return -ENOMEM;
fme_mgr_get_compat_id(priv->ioaddr, compat_id);
mgr = devm_fpga_mgr_create(dev, "DFL FME FPGA Manager",
&fme_mgr_ops, priv);
if (!mgr)
return -ENOMEM;
mgr->compat_id = compat_id;
return devm_fpga_mgr_register(dev, mgr);
fme_mgr_get_compat_id(priv->ioaddr, info.compat_id);
mgr = devm_fpga_mgr_register_full(dev, &info);
return PTR_ERR_OR_ZERO(mgr);
}
static struct platform_driver fme_mgr_driver = {

Просмотреть файл

@ -30,6 +30,7 @@ static int fme_region_get_bridges(struct fpga_region *region)
static int fme_region_probe(struct platform_device *pdev)
{
struct dfl_fme_region_pdata *pdata = dev_get_platdata(&pdev->dev);
struct fpga_region_info info = { 0 };
struct device *dev = &pdev->dev;
struct fpga_region *region;
struct fpga_manager *mgr;
@ -39,20 +40,18 @@ static int fme_region_probe(struct platform_device *pdev)
if (IS_ERR(mgr))
return -EPROBE_DEFER;
region = devm_fpga_region_create(dev, mgr, fme_region_get_bridges);
if (!region) {
ret = -ENOMEM;
info.mgr = mgr;
info.compat_id = mgr->compat_id;
info.get_bridges = fme_region_get_bridges;
info.priv = pdata;
region = fpga_region_register_full(dev, &info);
if (IS_ERR(region)) {
ret = PTR_ERR(region);
goto eprobe_mgr_put;
}
region->priv = pdata;
region->compat_id = mgr->compat_id;
platform_set_drvdata(pdev, region);
ret = fpga_region_register(region);
if (ret)
goto eprobe_mgr_put;
dev_dbg(dev, "DFL FME FPGA Region probed\n");
return 0;

Просмотреть файл

@ -1407,19 +1407,15 @@ dfl_fpga_feature_devs_enumerate(struct dfl_fpga_enum_info *info)
if (!cdev)
return ERR_PTR(-ENOMEM);
cdev->region = devm_fpga_region_create(info->dev, NULL, NULL);
if (!cdev->region) {
ret = -ENOMEM;
goto free_cdev_exit;
}
cdev->parent = info->dev;
mutex_init(&cdev->lock);
INIT_LIST_HEAD(&cdev->port_dev_list);
ret = fpga_region_register(cdev->region);
if (ret)
cdev->region = fpga_region_register(info->dev, NULL, NULL);
if (IS_ERR(cdev->region)) {
ret = PTR_ERR(cdev->region);
goto free_cdev_exit;
}
/* create and init build info for enumeration */
binfo = devm_kzalloc(info->dev, sizeof(*binfo), GFP_KERNEL);

Просмотреть файл

@ -312,36 +312,41 @@ static struct attribute *fpga_bridge_attrs[] = {
ATTRIBUTE_GROUPS(fpga_bridge);
/**
* fpga_bridge_create - create and initialize a struct fpga_bridge
* fpga_bridge_register - create and register an FPGA Bridge device
* @parent: FPGA bridge device from pdev
* @name: FPGA bridge name
* @br_ops: pointer to structure of fpga bridge ops
* @priv: FPGA bridge private data
*
* The caller of this function is responsible for freeing the bridge with
* fpga_bridge_free(). Using devm_fpga_bridge_create() instead is recommended.
*
* Return: struct fpga_bridge or NULL
* Return: struct fpga_bridge pointer or ERR_PTR()
*/
struct fpga_bridge *fpga_bridge_create(struct device *parent, const char *name,
const struct fpga_bridge_ops *br_ops,
void *priv)
struct fpga_bridge *
fpga_bridge_register(struct device *parent, const char *name,
const struct fpga_bridge_ops *br_ops,
void *priv)
{
struct fpga_bridge *bridge;
int id, ret;
if (!br_ops) {
dev_err(parent, "Attempt to register without fpga_bridge_ops\n");
return ERR_PTR(-EINVAL);
}
if (!name || !strlen(name)) {
dev_err(parent, "Attempt to register with no name!\n");
return NULL;
return ERR_PTR(-EINVAL);
}
bridge = kzalloc(sizeof(*bridge), GFP_KERNEL);
if (!bridge)
return NULL;
return ERR_PTR(-ENOMEM);
id = ida_simple_get(&fpga_bridge_ida, 0, 0, GFP_KERNEL);
if (id < 0)
if (id < 0) {
ret = id;
goto error_kfree;
}
mutex_init(&bridge->mutex);
INIT_LIST_HEAD(&bridge->node);
@ -350,17 +355,23 @@ struct fpga_bridge *fpga_bridge_create(struct device *parent, const char *name,
bridge->br_ops = br_ops;
bridge->priv = priv;
device_initialize(&bridge->dev);
bridge->dev.groups = br_ops->groups;
bridge->dev.class = fpga_bridge_class;
bridge->dev.parent = parent;
bridge->dev.of_node = parent->of_node;
bridge->dev.id = id;
of_platform_populate(bridge->dev.of_node, NULL, NULL, &bridge->dev);
ret = dev_set_name(&bridge->dev, "br%d", id);
if (ret)
goto error_device;
ret = device_register(&bridge->dev);
if (ret) {
put_device(&bridge->dev);
return ERR_PTR(ret);
}
return bridge;
error_device:
@ -368,88 +379,7 @@ error_device:
error_kfree:
kfree(bridge);
return NULL;
}
EXPORT_SYMBOL_GPL(fpga_bridge_create);
/**
* fpga_bridge_free - free an fpga bridge created by fpga_bridge_create()
* @bridge: FPGA bridge struct
*/
void fpga_bridge_free(struct fpga_bridge *bridge)
{
ida_simple_remove(&fpga_bridge_ida, bridge->dev.id);
kfree(bridge);
}
EXPORT_SYMBOL_GPL(fpga_bridge_free);
static void devm_fpga_bridge_release(struct device *dev, void *res)
{
struct fpga_bridge *bridge = *(struct fpga_bridge **)res;
fpga_bridge_free(bridge);
}
/**
* devm_fpga_bridge_create - create and init a managed struct fpga_bridge
* @parent: FPGA bridge device from pdev
* @name: FPGA bridge name
* @br_ops: pointer to structure of fpga bridge ops
* @priv: FPGA bridge private data
*
* This function is intended for use in an FPGA bridge driver's probe function.
* After the bridge driver creates the struct with devm_fpga_bridge_create(), it
* should register the bridge with fpga_bridge_register(). The bridge driver's
* remove function should call fpga_bridge_unregister(). The bridge struct
* allocated with this function will be freed automatically on driver detach.
* This includes the case of a probe function returning error before calling
* fpga_bridge_register(), the struct will still get cleaned up.
*
* Return: struct fpga_bridge or NULL
*/
struct fpga_bridge
*devm_fpga_bridge_create(struct device *parent, const char *name,
const struct fpga_bridge_ops *br_ops, void *priv)
{
struct fpga_bridge **ptr, *bridge;
ptr = devres_alloc(devm_fpga_bridge_release, sizeof(*ptr), GFP_KERNEL);
if (!ptr)
return NULL;
bridge = fpga_bridge_create(parent, name, br_ops, priv);
if (!bridge) {
devres_free(ptr);
} else {
*ptr = bridge;
devres_add(parent, ptr);
}
return bridge;
}
EXPORT_SYMBOL_GPL(devm_fpga_bridge_create);
/**
* fpga_bridge_register - register an FPGA bridge
*
* @bridge: FPGA bridge struct
*
* Return: 0 for success, error code otherwise.
*/
int fpga_bridge_register(struct fpga_bridge *bridge)
{
struct device *dev = &bridge->dev;
int ret;
ret = device_add(dev);
if (ret)
return ret;
of_platform_populate(dev->of_node, NULL, NULL, dev);
dev_info(dev->parent, "fpga bridge [%s] registered\n", bridge->name);
return 0;
return ERR_PTR(ret);
}
EXPORT_SYMBOL_GPL(fpga_bridge_register);
@ -475,6 +405,10 @@ EXPORT_SYMBOL_GPL(fpga_bridge_unregister);
static void fpga_bridge_dev_release(struct device *dev)
{
struct fpga_bridge *bridge = to_fpga_bridge(dev);
ida_simple_remove(&fpga_bridge_ida, bridge->dev.id);
kfree(bridge);
}
static int __init fpga_bridge_dev_init(void)

Просмотреть файл

@ -592,49 +592,49 @@ void fpga_mgr_unlock(struct fpga_manager *mgr)
EXPORT_SYMBOL_GPL(fpga_mgr_unlock);
/**
* fpga_mgr_create - create and initialize an FPGA manager struct
* fpga_mgr_register_full - create and register an FPGA Manager device
* @parent: fpga manager device from pdev
* @name: fpga manager name
* @mops: pointer to structure of fpga manager ops
* @priv: fpga manager private data
* @info: parameters for fpga manager
*
* The caller of this function is responsible for freeing the struct with
* fpga_mgr_free(). Using devm_fpga_mgr_create() instead is recommended.
* The caller of this function is responsible for calling fpga_mgr_unregister().
* Using devm_fpga_mgr_register_full() instead is recommended.
*
* Return: pointer to struct fpga_manager or NULL
* Return: pointer to struct fpga_manager pointer or ERR_PTR()
*/
struct fpga_manager *fpga_mgr_create(struct device *parent, const char *name,
const struct fpga_manager_ops *mops,
void *priv)
struct fpga_manager *
fpga_mgr_register_full(struct device *parent, const struct fpga_manager_info *info)
{
const struct fpga_manager_ops *mops = info->mops;
struct fpga_manager *mgr;
int id, ret;
if (!mops) {
dev_err(parent, "Attempt to register without fpga_manager_ops\n");
return NULL;
return ERR_PTR(-EINVAL);
}
if (!name || !strlen(name)) {
if (!info->name || !strlen(info->name)) {
dev_err(parent, "Attempt to register with no name!\n");
return NULL;
return ERR_PTR(-EINVAL);
}
mgr = kzalloc(sizeof(*mgr), GFP_KERNEL);
if (!mgr)
return NULL;
return ERR_PTR(-ENOMEM);
id = ida_simple_get(&fpga_mgr_ida, 0, 0, GFP_KERNEL);
if (id < 0)
if (id < 0) {
ret = id;
goto error_kfree;
}
mutex_init(&mgr->ref_mutex);
mgr->name = name;
mgr->mops = mops;
mgr->priv = priv;
mgr->name = info->name;
mgr->mops = info->mops;
mgr->priv = info->priv;
mgr->compat_id = info->compat_id;
device_initialize(&mgr->dev);
mgr->dev.class = fpga_mgr_class;
mgr->dev.groups = mops->groups;
mgr->dev.parent = parent;
@ -645,84 +645,6 @@ struct fpga_manager *fpga_mgr_create(struct device *parent, const char *name,
if (ret)
goto error_device;
return mgr;
error_device:
ida_simple_remove(&fpga_mgr_ida, id);
error_kfree:
kfree(mgr);
return NULL;
}
EXPORT_SYMBOL_GPL(fpga_mgr_create);
/**
* fpga_mgr_free - free an FPGA manager created with fpga_mgr_create()
* @mgr: fpga manager struct
*/
void fpga_mgr_free(struct fpga_manager *mgr)
{
ida_simple_remove(&fpga_mgr_ida, mgr->dev.id);
kfree(mgr);
}
EXPORT_SYMBOL_GPL(fpga_mgr_free);
static void devm_fpga_mgr_release(struct device *dev, void *res)
{
struct fpga_mgr_devres *dr = res;
fpga_mgr_free(dr->mgr);
}
/**
* devm_fpga_mgr_create - create and initialize a managed FPGA manager struct
* @parent: 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 an 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 *parent, const char *name,
const struct fpga_manager_ops *mops,
void *priv)
{
struct fpga_mgr_devres *dr;
dr = devres_alloc(devm_fpga_mgr_release, sizeof(*dr), GFP_KERNEL);
if (!dr)
return NULL;
dr->mgr = fpga_mgr_create(parent, name, mops, priv);
if (!dr->mgr) {
devres_free(dr);
return NULL;
}
devres_add(parent, dr);
return dr->mgr;
}
EXPORT_SYMBOL_GPL(devm_fpga_mgr_create);
/**
* fpga_mgr_register - register an FPGA manager
* @mgr: fpga manager struct
*
* Return: 0 on success, negative error code otherwise.
*/
int fpga_mgr_register(struct fpga_manager *mgr)
{
int ret;
/*
* Initialize framework state by requesting low level driver read state
* from device. FPGA may be in reset mode or may have been programmed
@ -730,18 +652,49 @@ int fpga_mgr_register(struct fpga_manager *mgr)
*/
mgr->state = fpga_mgr_state(mgr);
ret = device_add(&mgr->dev);
if (ret)
goto error_device;
ret = device_register(&mgr->dev);
if (ret) {
put_device(&mgr->dev);
return ERR_PTR(ret);
}
dev_info(&mgr->dev, "%s registered\n", mgr->name);
return 0;
return mgr;
error_device:
ida_simple_remove(&fpga_mgr_ida, mgr->dev.id);
ida_simple_remove(&fpga_mgr_ida, id);
error_kfree:
kfree(mgr);
return ret;
return ERR_PTR(ret);
}
EXPORT_SYMBOL_GPL(fpga_mgr_register_full);
/**
* fpga_mgr_register - create and register an FPGA Manager device
* @parent: fpga manager device from pdev
* @name: fpga manager name
* @mops: pointer to structure of fpga manager ops
* @priv: fpga manager private data
*
* The caller of this function is responsible for calling fpga_mgr_unregister().
* Using devm_fpga_mgr_register() instead is recommended. This simple
* version of the register function should be sufficient for most users. The
* fpga_mgr_register_full() function is available for users that need to pass
* additional, optional parameters.
*
* Return: pointer to struct fpga_manager pointer or ERR_PTR()
*/
struct fpga_manager *
fpga_mgr_register(struct device *parent, const char *name,
const struct fpga_manager_ops *mops, void *priv)
{
struct fpga_manager_info info = { 0 };
info.name = name;
info.mops = mops;
info.priv = priv;
return fpga_mgr_register_full(parent, &info);
}
EXPORT_SYMBOL_GPL(fpga_mgr_register);
@ -765,14 +718,6 @@ void fpga_mgr_unregister(struct fpga_manager *mgr)
}
EXPORT_SYMBOL_GPL(fpga_mgr_unregister);
static int fpga_mgr_devres_match(struct device *dev, void *res,
void *match_data)
{
struct fpga_mgr_devres *dr = res;
return match_data == dr->mgr;
}
static void devm_fpga_mgr_unregister(struct device *dev, void *res)
{
struct fpga_mgr_devres *dr = res;
@ -781,45 +726,67 @@ static void devm_fpga_mgr_unregister(struct device *dev, void *res)
}
/**
* devm_fpga_mgr_register - resource managed variant of fpga_mgr_register()
* @dev: managing device for this FPGA manager
* @mgr: fpga manager struct
* devm_fpga_mgr_register_full - resource managed variant of fpga_mgr_register()
* @parent: fpga manager device from pdev
* @info: parameters for fpga manager
*
* This is the devres variant of fpga_mgr_register() for which the unregister
* This is the devres variant of fpga_mgr_register_full() for which the unregister
* function will be called automatically when the managing device is detached.
*/
int devm_fpga_mgr_register(struct device *dev, struct fpga_manager *mgr)
struct fpga_manager *
devm_fpga_mgr_register_full(struct device *parent, const struct fpga_manager_info *info)
{
struct fpga_mgr_devres *dr;
int ret;
/*
* Make sure that the struct fpga_manager * that is passed in is
* managed itself.
*/
if (WARN_ON(!devres_find(dev, devm_fpga_mgr_release,
fpga_mgr_devres_match, mgr)))
return -EINVAL;
struct fpga_manager *mgr;
dr = devres_alloc(devm_fpga_mgr_unregister, sizeof(*dr), GFP_KERNEL);
if (!dr)
return -ENOMEM;
return ERR_PTR(-ENOMEM);
ret = fpga_mgr_register(mgr);
if (ret) {
mgr = fpga_mgr_register_full(parent, info);
if (IS_ERR(mgr)) {
devres_free(dr);
return ret;
return mgr;
}
dr->mgr = mgr;
devres_add(dev, dr);
devres_add(parent, dr);
return 0;
return mgr;
}
EXPORT_SYMBOL_GPL(devm_fpga_mgr_register_full);
/**
* devm_fpga_mgr_register - resource managed variant of fpga_mgr_register()
* @parent: fpga manager device from pdev
* @name: fpga manager name
* @mops: pointer to structure of fpga manager ops
* @priv: fpga manager private data
*
* This is the devres variant of fpga_mgr_register() for which the
* unregister function will be called automatically when the managing
* device is detached.
*/
struct fpga_manager *
devm_fpga_mgr_register(struct device *parent, const char *name,
const struct fpga_manager_ops *mops, void *priv)
{
struct fpga_manager_info info = { 0 };
info.name = name;
info.mops = mops;
info.priv = priv;
return devm_fpga_mgr_register_full(parent, &info);
}
EXPORT_SYMBOL_GPL(devm_fpga_mgr_register);
static void fpga_mgr_dev_release(struct device *dev)
{
struct fpga_manager *mgr = to_fpga_manager(dev);
ida_simple_remove(&fpga_mgr_ida, mgr->dev.id);
kfree(mgr);
}
static int __init fpga_mgr_class_init(void)

Просмотреть файл

@ -180,39 +180,42 @@ static struct attribute *fpga_region_attrs[] = {
ATTRIBUTE_GROUPS(fpga_region);
/**
* fpga_region_create - alloc and init a struct fpga_region
* fpga_region_register_full - create and register an FPGA Region device
* @parent: device parent
* @mgr: manager that programs this region
* @get_bridges: optional function to get bridges to a list
* @info: parameters for FPGA Region
*
* 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
* Return: struct fpga_region or ERR_PTR()
*/
struct fpga_region
*fpga_region_create(struct device *parent,
struct fpga_manager *mgr,
int (*get_bridges)(struct fpga_region *))
struct fpga_region *
fpga_region_register_full(struct device *parent, const struct fpga_region_info *info)
{
struct fpga_region *region;
int id, ret = 0;
if (!info) {
dev_err(parent,
"Attempt to register without required info structure\n");
return ERR_PTR(-EINVAL);
}
region = kzalloc(sizeof(*region), GFP_KERNEL);
if (!region)
return NULL;
return ERR_PTR(-ENOMEM);
id = ida_simple_get(&fpga_region_ida, 0, 0, GFP_KERNEL);
if (id < 0)
if (id < 0) {
ret = id;
goto err_free;
}
region->mgr = info->mgr;
region->compat_id = info->compat_id;
region->priv = info->priv;
region->get_bridges = info->get_bridges;
region->mgr = mgr;
region->get_bridges = get_bridges;
mutex_init(&region->mutex);
INIT_LIST_HEAD(&region->bridge_list);
device_initialize(&region->dev);
region->dev.class = fpga_region_class;
region->dev.parent = parent;
region->dev.of_node = parent->of_node;
@ -222,6 +225,12 @@ struct fpga_region
if (ret)
goto err_remove;
ret = device_register(&region->dev);
if (ret) {
put_device(&region->dev);
return ERR_PTR(ret);
}
return region;
err_remove:
@ -229,76 +238,32 @@ err_remove:
err_free:
kfree(region);
return NULL;
return ERR_PTR(ret);
}
EXPORT_SYMBOL_GPL(fpga_region_create);
EXPORT_SYMBOL_GPL(fpga_region_register_full);
/**
* fpga_region_free - free an FPGA region created by fpga_region_create()
* @region: FPGA region
*/
void fpga_region_free(struct fpga_region *region)
{
ida_simple_remove(&fpga_region_ida, region->dev.id);
kfree(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
* fpga_region_register - create and register an FPGA Region device
* @parent: 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 an 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.
* This simple version of the register function should be sufficient for most users.
* The fpga_region_register_full() function is available for users that need to
* pass additional, optional parameters.
*
* Return: struct fpga_region or NULL
* Return: struct fpga_region or ERR_PTR()
*/
struct fpga_region
*devm_fpga_region_create(struct device *parent,
struct fpga_manager *mgr,
int (*get_bridges)(struct fpga_region *))
struct fpga_region *
fpga_region_register(struct device *parent, struct fpga_manager *mgr,
int (*get_bridges)(struct fpga_region *))
{
struct fpga_region **ptr, *region;
struct fpga_region_info info = { 0 };
ptr = devres_alloc(devm_fpga_region_release, sizeof(*ptr), GFP_KERNEL);
if (!ptr)
return NULL;
info.mgr = mgr;
info.get_bridges = get_bridges;
region = fpga_region_create(parent, mgr, get_bridges);
if (!region) {
devres_free(ptr);
} else {
*ptr = region;
devres_add(parent, ptr);
}
return region;
}
EXPORT_SYMBOL_GPL(devm_fpga_region_create);
/**
* fpga_region_register - register an FPGA region
* @region: FPGA region
*
* Return: 0 or -errno
*/
int fpga_region_register(struct fpga_region *region)
{
return device_add(&region->dev);
return fpga_region_register_full(parent, &info);
}
EXPORT_SYMBOL_GPL(fpga_region_register);
@ -316,6 +281,10 @@ EXPORT_SYMBOL_GPL(fpga_region_unregister);
static void fpga_region_dev_release(struct device *dev)
{
struct fpga_region *region = to_fpga_region(dev);
ida_simple_remove(&fpga_region_ida, region->dev.id);
kfree(region);
}
/**

Просмотреть файл

@ -178,12 +178,9 @@ static int ice40_fpga_probe(struct spi_device *spi)
return ret;
}
mgr = devm_fpga_mgr_create(dev, "Lattice iCE40 FPGA Manager",
&ice40_fpga_ops, priv);
if (!mgr)
return -ENOMEM;
return devm_fpga_mgr_register(dev, mgr);
mgr = devm_fpga_mgr_register(dev, "Lattice iCE40 FPGA Manager",
&ice40_fpga_ops, priv);
return PTR_ERR_OR_ZERO(mgr);
}
static const struct of_device_id ice40_fpga_of_match[] = {

Просмотреть файл

@ -370,12 +370,9 @@ static int machxo2_spi_probe(struct spi_device *spi)
return -EINVAL;
}
mgr = devm_fpga_mgr_create(dev, "Lattice MachXO2 SPI FPGA Manager",
&machxo2_ops, spi);
if (!mgr)
return -ENOMEM;
return devm_fpga_mgr_register(dev, mgr);
mgr = devm_fpga_mgr_register(dev, "Lattice MachXO2 SPI FPGA Manager",
&machxo2_ops, spi);
return PTR_ERR_OR_ZERO(mgr);
}
#ifdef CONFIG_OF

Просмотреть файл

@ -405,16 +405,12 @@ static int of_fpga_region_probe(struct platform_device *pdev)
if (IS_ERR(mgr))
return -EPROBE_DEFER;
region = devm_fpga_region_create(dev, mgr, of_fpga_region_get_bridges);
if (!region) {
ret = -ENOMEM;
region = fpga_region_register(dev, mgr, of_fpga_region_get_bridges);
if (IS_ERR(region)) {
ret = PTR_ERR(region);
goto eprobe_mgr_put;
}
ret = fpga_region_register(region);
if (ret)
goto eprobe_mgr_put;
of_platform_populate(np, fpga_region_of_match, NULL, &region->dev);
platform_set_drvdata(pdev, region);
@ -448,7 +444,7 @@ static struct platform_driver of_fpga_region_driver = {
};
/**
* fpga_region_init - init function for fpga_region class
* of_fpga_region_init - init function for fpga_region class
* Creates the fpga_region class and registers a reconfig notifier.
*/
static int __init of_fpga_region_init(void)

Просмотреть файл

@ -508,19 +508,15 @@ static int socfpga_a10_fpga_probe(struct platform_device *pdev)
return -EBUSY;
}
mgr = devm_fpga_mgr_create(dev, "SoCFPGA Arria10 FPGA Manager",
&socfpga_a10_fpga_mgr_ops, priv);
if (!mgr)
return -ENOMEM;
mgr = fpga_mgr_register(dev, "SoCFPGA Arria10 FPGA Manager",
&socfpga_a10_fpga_mgr_ops, priv);
if (IS_ERR(mgr)) {
clk_disable_unprepare(priv->clk);
return PTR_ERR(mgr);
}
platform_set_drvdata(pdev, mgr);
ret = fpga_mgr_register(mgr);
if (ret) {
clk_disable_unprepare(priv->clk);
return ret;
}
return 0;
}

Просмотреть файл

@ -571,12 +571,9 @@ static int socfpga_fpga_probe(struct platform_device *pdev)
if (ret)
return ret;
mgr = devm_fpga_mgr_create(dev, "Altera SOCFPGA FPGA Manager",
&socfpga_fpga_ops, priv);
if (!mgr)
return -ENOMEM;
return devm_fpga_mgr_register(dev, mgr);
mgr = devm_fpga_mgr_register(dev, "Altera SOCFPGA FPGA Manager",
&socfpga_fpga_ops, priv);
return PTR_ERR_OR_ZERO(mgr);
}
#ifdef CONFIG_OF

Просмотреть файл

@ -419,23 +419,16 @@ static int s10_probe(struct platform_device *pdev)
init_completion(&priv->status_return_completion);
mgr = fpga_mgr_create(dev, "Stratix10 SOC FPGA Manager",
&s10_ops, priv);
if (!mgr) {
dev_err(dev, "unable to create FPGA manager\n");
ret = -ENOMEM;
goto probe_err;
}
ret = fpga_mgr_register(mgr);
if (ret) {
mgr = fpga_mgr_register(dev, "Stratix10 SOC FPGA Manager",
&s10_ops, priv);
if (IS_ERR(mgr)) {
dev_err(dev, "unable to register FPGA manager\n");
fpga_mgr_free(mgr);
ret = PTR_ERR(mgr);
goto probe_err;
}
platform_set_drvdata(pdev, mgr);
return ret;
return 0;
probe_err:
stratix10_svc_free_channel(priv->chan);
@ -448,7 +441,6 @@ static int s10_remove(struct platform_device *pdev)
struct s10_priv *priv = mgr->priv;
fpga_mgr_unregister(mgr);
fpga_mgr_free(mgr);
stratix10_svc_free_channel(priv->chan);
return 0;

Просмотреть файл

@ -116,12 +116,9 @@ static int ts73xx_fpga_probe(struct platform_device *pdev)
if (IS_ERR(priv->io_base))
return PTR_ERR(priv->io_base);
mgr = devm_fpga_mgr_create(kdev, "TS-73xx FPGA Manager",
&ts73xx_fpga_ops, priv);
if (!mgr)
return -ENOMEM;
return devm_fpga_mgr_register(kdev, mgr);
mgr = devm_fpga_mgr_register(kdev, "TS-73xx FPGA Manager",
&ts73xx_fpga_ops, priv);
return PTR_ERR_OR_ZERO(mgr);
}
static struct platform_driver ts73xx_fpga_driver = {

Просмотреть файл

@ -54,12 +54,9 @@ static int versal_fpga_probe(struct platform_device *pdev)
return ret;
}
mgr = devm_fpga_mgr_create(dev, "Xilinx Versal FPGA Manager",
&versal_fpga_ops, NULL);
if (!mgr)
return -ENOMEM;
return devm_fpga_mgr_register(dev, mgr);
mgr = devm_fpga_mgr_register(dev, "Xilinx Versal FPGA Manager",
&versal_fpga_ops, NULL);
return PTR_ERR_OR_ZERO(mgr);
}
static const struct of_device_id versal_fpga_of_match[] = {

Просмотреть файл

@ -140,22 +140,17 @@ static int xlnx_pr_decoupler_probe(struct platform_device *pdev)
clk_disable(priv->clk);
br = devm_fpga_bridge_create(&pdev->dev, priv->ipconfig->name,
&xlnx_pr_decoupler_br_ops, priv);
if (!br) {
err = -ENOMEM;
goto err_clk;
}
platform_set_drvdata(pdev, br);
err = fpga_bridge_register(br);
if (err) {
br = fpga_bridge_register(&pdev->dev, priv->ipconfig->name,
&xlnx_pr_decoupler_br_ops, priv);
if (IS_ERR(br)) {
err = PTR_ERR(br);
dev_err(&pdev->dev, "unable to register %s",
priv->ipconfig->name);
goto err_clk;
}
platform_set_drvdata(pdev, br);
return 0;
err_clk:

Просмотреть файл

@ -247,13 +247,10 @@ static int xilinx_spi_probe(struct spi_device *spi)
return dev_err_probe(&spi->dev, PTR_ERR(conf->done),
"Failed to get DONE gpio\n");
mgr = devm_fpga_mgr_create(&spi->dev,
"Xilinx Slave Serial FPGA Manager",
&xilinx_spi_ops, conf);
if (!mgr)
return -ENOMEM;
return devm_fpga_mgr_register(&spi->dev, mgr);
mgr = devm_fpga_mgr_register(&spi->dev,
"Xilinx Slave Serial FPGA Manager",
&xilinx_spi_ops, conf);
return PTR_ERR_OR_ZERO(mgr);
}
#ifdef CONFIG_OF

Просмотреть файл

@ -609,20 +609,16 @@ static int zynq_fpga_probe(struct platform_device *pdev)
clk_disable(priv->clk);
mgr = devm_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) {
mgr = fpga_mgr_register(dev, "Xilinx Zynq FPGA Manager",
&zynq_fpga_ops, priv);
if (IS_ERR(mgr)) {
dev_err(dev, "unable to register FPGA manager\n");
clk_unprepare(priv->clk);
return err;
return PTR_ERR(mgr);
}
platform_set_drvdata(pdev, mgr);
return 0;
}

Просмотреть файл

@ -95,12 +95,9 @@ static int zynqmp_fpga_probe(struct platform_device *pdev)
priv->dev = dev;
mgr = devm_fpga_mgr_create(dev, "Xilinx ZynqMP FPGA Manager",
&zynqmp_fpga_ops, priv);
if (!mgr)
return -ENOMEM;
return devm_fpga_mgr_register(dev, mgr);
mgr = devm_fpga_mgr_register(dev, "Xilinx ZynqMP FPGA Manager",
&zynqmp_fpga_ops, priv);
return PTR_ERR_OR_ZERO(mgr);
}
#ifdef CONFIG_OF

Просмотреть файл

@ -22,6 +22,23 @@ struct fpga_bridge_ops {
const struct attribute_group **groups;
};
/**
* struct fpga_bridge_info - collection of parameters an FPGA Bridge
* @name: fpga bridge name
* @br_ops: pointer to structure of fpga bridge ops
* @priv: fpga bridge private data
*
* fpga_bridge_info contains parameters for the register function. These
* are separated into an info structure because they some are optional
* others could be added to in the future. The info structure facilitates
* maintaining a stable API.
*/
struct fpga_bridge_info {
const char *name;
const struct fpga_bridge_ops *br_ops;
void *priv;
};
/**
* struct fpga_bridge - FPGA bridge structure
* @name: name of low level FPGA bridge
@ -62,15 +79,10 @@ int of_fpga_bridge_get_to_list(struct device_node *np,
struct fpga_image_info *info,
struct list_head *bridge_list);
struct fpga_bridge *fpga_bridge_create(struct device *dev, const char *name,
const struct fpga_bridge_ops *br_ops,
void *priv);
void fpga_bridge_free(struct fpga_bridge *br);
int fpga_bridge_register(struct fpga_bridge *br);
struct fpga_bridge *
fpga_bridge_register(struct device *parent, const char *name,
const struct fpga_bridge_ops *br_ops,
void *priv);
void fpga_bridge_unregister(struct fpga_bridge *br);
struct fpga_bridge
*devm_fpga_bridge_create(struct device *dev, const char *name,
const struct fpga_bridge_ops *br_ops, void *priv);
#endif /* _LINUX_FPGA_BRIDGE_H */

Просмотреть файл

@ -105,6 +105,36 @@ struct fpga_image_info {
#endif
};
/**
* struct fpga_compat_id - id for compatibility check
*
* @id_h: high 64bit of the compat_id
* @id_l: low 64bit of the compat_id
*/
struct fpga_compat_id {
u64 id_h;
u64 id_l;
};
/**
* struct fpga_manager_info - collection of parameters for an FPGA Manager
* @name: fpga manager name
* @compat_id: FPGA manager id for compatibility check.
* @mops: pointer to structure of fpga manager ops
* @priv: fpga manager private data
*
* fpga_manager_info contains parameters for the register_full function.
* These are separated into an info structure because they some are optional
* others could be added to in the future. The info structure facilitates
* maintaining a stable API.
*/
struct fpga_manager_info {
const char *name;
struct fpga_compat_id *compat_id;
const struct fpga_manager_ops *mops;
void *priv;
};
/**
* struct fpga_manager_ops - ops for low level fpga manager drivers
* @initial_header_size: Maximum number of bytes that should be passed into write_init
@ -143,17 +173,6 @@ struct fpga_manager_ops {
#define FPGA_MGR_STATUS_IP_PROTOCOL_ERR BIT(3)
#define FPGA_MGR_STATUS_FIFO_OVERFLOW_ERR BIT(4)
/**
* struct fpga_compat_id - id for compatibility check
*
* @id_h: high 64bit of the compat_id
* @id_l: low 64bit of the compat_id
*/
struct fpga_compat_id {
u64 id_h;
u64 id_l;
};
/**
* struct fpga_manager - fpga manager structure
* @name: name of low level fpga manager
@ -191,17 +210,18 @@ struct fpga_manager *fpga_mgr_get(struct device *dev);
void fpga_mgr_put(struct fpga_manager *mgr);
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);
struct fpga_manager *
fpga_mgr_register_full(struct device *parent, const struct fpga_manager_info *info);
struct fpga_manager *
fpga_mgr_register(struct device *parent, const char *name,
const struct fpga_manager_ops *mops, void *priv);
void fpga_mgr_unregister(struct fpga_manager *mgr);
int devm_fpga_mgr_register(struct device *dev, 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);
struct fpga_manager *
devm_fpga_mgr_register_full(struct device *parent, const struct fpga_manager_info *info);
struct fpga_manager *
devm_fpga_mgr_register(struct device *parent, const char *name,
const struct fpga_manager_ops *mops, void *priv);
#endif /*_LINUX_FPGA_MGR_H */

Просмотреть файл

@ -7,6 +7,27 @@
#include <linux/fpga/fpga-mgr.h>
#include <linux/fpga/fpga-bridge.h>
struct fpga_region;
/**
* struct fpga_region_info - collection of parameters an FPGA Region
* @mgr: fpga region manager
* @compat_id: FPGA region id for compatibility check.
* @priv: fpga region private data
* @get_bridges: optional function to get bridges to a list
*
* fpga_region_info contains parameters for the register_full function.
* These are separated into an info structure because they some are optional
* others could be added to in the future. The info structure facilitates
* maintaining a stable API.
*/
struct fpga_region_info {
struct fpga_manager *mgr;
struct fpga_compat_id *compat_id;
void *priv;
int (*get_bridges)(struct fpga_region *region);
};
/**
* struct fpga_region - FPGA Region structure
* @dev: FPGA Region device
@ -37,15 +58,12 @@ struct fpga_region *fpga_region_class_find(
int fpga_region_program_fpga(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);
struct fpga_region *
fpga_region_register_full(struct device *parent, const struct fpga_region_info *info);
struct fpga_region *
fpga_region_register(struct device *parent, struct fpga_manager *mgr,
int (*get_bridges)(struct fpga_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 */