Commit 371cd1b1 authored by Alan Tull's avatar Alan Tull Committed by Greg Kroah-Hartman

fpga: bridge: change api, don't use drvdata

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.
Signed-off-by: default avatarAlan Tull <atull@kernel.org>
Reported-by: default avatarJiuyue Ma <majiuyue@huawei.com>
Signed-off-by: default avatarMoritz Fischer <mdf@kernel.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 7085e2a9
...@@ -106,6 +106,7 @@ static int alt_fpga_bridge_probe(struct platform_device *pdev) ...@@ -106,6 +106,7 @@ static int alt_fpga_bridge_probe(struct platform_device *pdev)
{ {
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
struct alt_fpga2sdram_data *priv; struct alt_fpga2sdram_data *priv;
struct fpga_bridge *br;
u32 enable; u32 enable;
struct regmap *sysmgr; struct regmap *sysmgr;
int ret = 0; int ret = 0;
...@@ -131,10 +132,18 @@ static int alt_fpga_bridge_probe(struct platform_device *pdev) ...@@ -131,10 +132,18 @@ static int alt_fpga_bridge_probe(struct platform_device *pdev)
/* Get f2s bridge configuration saved in handoff register */ /* Get f2s bridge configuration saved in handoff register */
regmap_read(sysmgr, SYSMGR_ISWGRP_HANDOFF3, &priv->mask); regmap_read(sysmgr, SYSMGR_ISWGRP_HANDOFF3, &priv->mask);
ret = fpga_bridge_register(dev, F2S_BRIDGE_NAME, br = fpga_bridge_create(dev, F2S_BRIDGE_NAME,
&altera_fpga2sdram_br_ops, priv); &altera_fpga2sdram_br_ops, priv);
if (ret) if (!br)
return -ENOMEM;
platform_set_drvdata(pdev, br);
ret = fpga_bridge_register(br);
if (ret) {
fpga_bridge_free(br);
return ret; return ret;
}
dev_info(dev, "driver initialized with handoff %08x\n", priv->mask); 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) ...@@ -146,7 +155,7 @@ static int alt_fpga_bridge_probe(struct platform_device *pdev)
(enable ? "enabling" : "disabling")); (enable ? "enabling" : "disabling"));
ret = _alt_fpga2sdram_enable_set(priv, enable); ret = _alt_fpga2sdram_enable_set(priv, enable);
if (ret) { if (ret) {
fpga_bridge_unregister(&pdev->dev); fpga_bridge_unregister(br);
return ret; return ret;
} }
} }
...@@ -157,7 +166,9 @@ static int alt_fpga_bridge_probe(struct platform_device *pdev) ...@@ -157,7 +166,9 @@ static int alt_fpga_bridge_probe(struct platform_device *pdev)
static int alt_fpga_bridge_remove(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; return 0;
} }
......
...@@ -221,8 +221,10 @@ static int altera_freeze_br_probe(struct platform_device *pdev) ...@@ -221,8 +221,10 @@ static int altera_freeze_br_probe(struct platform_device *pdev)
struct device_node *np = pdev->dev.of_node; struct device_node *np = pdev->dev.of_node;
void __iomem *base_addr; void __iomem *base_addr;
struct altera_freeze_br_data *priv; struct altera_freeze_br_data *priv;
struct fpga_bridge *br;
struct resource *res; struct resource *res;
u32 status, revision; u32 status, revision;
int ret;
if (!np) if (!np)
return -ENODEV; return -ENODEV;
...@@ -254,13 +256,27 @@ static int altera_freeze_br_probe(struct platform_device *pdev) ...@@ -254,13 +256,27 @@ static int altera_freeze_br_probe(struct platform_device *pdev)
priv->base_addr = base_addr; priv->base_addr = base_addr;
return fpga_bridge_register(dev, FREEZE_BRIDGE_NAME, br = fpga_bridge_create(dev, FREEZE_BRIDGE_NAME,
&altera_freeze_br_br_ops, priv); &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) 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; return 0;
} }
......
...@@ -139,6 +139,7 @@ static int alt_fpga_bridge_probe(struct platform_device *pdev) ...@@ -139,6 +139,7 @@ static int alt_fpga_bridge_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
struct altera_hps2fpga_data *priv; struct altera_hps2fpga_data *priv;
const struct of_device_id *of_id; const struct of_device_id *of_id;
struct fpga_bridge *br;
u32 enable; u32 enable;
int ret; int ret;
...@@ -190,10 +191,23 @@ static int alt_fpga_bridge_probe(struct platform_device *pdev) ...@@ -190,10 +191,23 @@ static int alt_fpga_bridge_probe(struct platform_device *pdev)
} }
} }
ret = fpga_bridge_register(dev, priv->name, &altera_hps2fpga_br_ops, br = fpga_bridge_create(dev, priv->name, &altera_hps2fpga_br_ops, priv);
priv); if (!br) {
err: ret = -ENOMEM;
goto err;
}
platform_set_drvdata(pdev, br);
ret = fpga_bridge_register(br);
if (ret) if (ret)
goto err_free;
return 0;
err_free:
fpga_bridge_free(br);
err:
clk_disable_unprepare(priv->clk); clk_disable_unprepare(priv->clk);
return ret; return ret;
...@@ -204,7 +218,7 @@ static int alt_fpga_bridge_remove(struct platform_device *pdev) ...@@ -204,7 +218,7 @@ static int alt_fpga_bridge_remove(struct platform_device *pdev)
struct fpga_bridge *bridge = platform_get_drvdata(pdev); struct fpga_bridge *bridge = platform_get_drvdata(pdev);
struct altera_hps2fpga_data *priv = bridge->priv; struct altera_hps2fpga_data *priv = bridge->priv;
fpga_bridge_unregister(&pdev->dev); fpga_bridge_unregister(bridge);
clk_disable_unprepare(priv->clk); clk_disable_unprepare(priv->clk);
......
...@@ -328,28 +328,29 @@ static struct attribute *fpga_bridge_attrs[] = { ...@@ -328,28 +328,29 @@ static struct attribute *fpga_bridge_attrs[] = {
ATTRIBUTE_GROUPS(fpga_bridge); ATTRIBUTE_GROUPS(fpga_bridge);
/** /**
* fpga_bridge_register - register a fpga bridge driver * fpga_bridge_create - create and initialize a struct fpga_bridge
* @dev: FPGA bridge device from pdev * @dev: FPGA bridge device from pdev
* @name: FPGA bridge name * @name: FPGA bridge name
* @br_ops: pointer to structure of fpga bridge ops * @br_ops: pointer to structure of fpga bridge ops
* @priv: FPGA bridge private data * @priv: FPGA bridge private data
* *
* Return: 0 for success, error code otherwise. * Return: struct fpga_bridge or NULL
*/ */
int fpga_bridge_register(struct device *dev, const char *name, struct fpga_bridge *fpga_bridge_create(struct device *dev, const char *name,
const struct fpga_bridge_ops *br_ops, void *priv) const struct fpga_bridge_ops *br_ops,
void *priv)
{ {
struct fpga_bridge *bridge; struct fpga_bridge *bridge;
int id, ret = 0; int id, ret = 0;
if (!name || !strlen(name)) { if (!name || !strlen(name)) {
dev_err(dev, "Attempt to register with no name!\n"); dev_err(dev, "Attempt to register with no name!\n");
return -EINVAL; return NULL;
} }
bridge = kzalloc(sizeof(*bridge), GFP_KERNEL); bridge = kzalloc(sizeof(*bridge), GFP_KERNEL);
if (!bridge) if (!bridge)
return -ENOMEM; return NULL;
id = ida_simple_get(&fpga_bridge_ida, 0, 0, GFP_KERNEL); id = ida_simple_get(&fpga_bridge_ida, 0, 0, GFP_KERNEL);
if (id < 0) { if (id < 0) {
...@@ -370,40 +371,62 @@ int fpga_bridge_register(struct device *dev, const char *name, ...@@ -370,40 +371,62 @@ int fpga_bridge_register(struct device *dev, const char *name,
bridge->dev.parent = dev; bridge->dev.parent = dev;
bridge->dev.of_node = dev->of_node; bridge->dev.of_node = dev->of_node;
bridge->dev.id = id; bridge->dev.id = id;
dev_set_drvdata(dev, bridge);
ret = dev_set_name(&bridge->dev, "br%d", id); ret = dev_set_name(&bridge->dev, "br%d", id);
if (ret) if (ret)
goto error_device; goto error_device;
ret = device_add(&bridge->dev); return bridge;
if (ret)
goto error_device;
of_platform_populate(dev->of_node, NULL, NULL, dev);
dev_info(bridge->dev.parent, "fpga bridge [%s] registered\n",
bridge->name);
return 0;
error_device: error_device:
ida_simple_remove(&fpga_bridge_ida, id); ida_simple_remove(&fpga_bridge_ida, id);
error_kfree: error_kfree:
kfree(bridge); kfree(bridge);
return NULL;
}
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
*/
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);
/**
* fpga_bridge_register - register a fpga bridge
* @bridge: FPGA bridge struct created by fpga_bridge_create
*
* 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; return ret;
of_platform_populate(dev->of_node, NULL, NULL, dev);
dev_info(dev->parent, "fpga bridge [%s] registered\n", bridge->name);
return 0;
} }
EXPORT_SYMBOL_GPL(fpga_bridge_register); EXPORT_SYMBOL_GPL(fpga_bridge_register);
/** /**
* fpga_bridge_unregister - unregister a fpga bridge driver * fpga_bridge_unregister - unregister a fpga bridge driver
* @dev: FPGA bridge device from pdev * @bridge: FPGA bridge struct created by fpga_bridge_create
*/ */
void fpga_bridge_unregister(struct device *dev) void fpga_bridge_unregister(struct fpga_bridge *bridge)
{ {
struct fpga_bridge *bridge = dev_get_drvdata(dev);
/* /*
* If the low level driver provides a method for putting bridge into * If the low level driver provides a method for putting bridge into
* a desired state upon unregister, do it. * a desired state upon unregister, do it.
...@@ -419,8 +442,7 @@ static void fpga_bridge_dev_release(struct device *dev) ...@@ -419,8 +442,7 @@ static void fpga_bridge_dev_release(struct device *dev)
{ {
struct fpga_bridge *bridge = to_fpga_bridge(dev); struct fpga_bridge *bridge = to_fpga_bridge(dev);
ida_simple_remove(&fpga_bridge_ida, bridge->dev.id); fpga_bridge_free(bridge);
kfree(bridge);
} }
static int __init fpga_bridge_dev_init(void) static int __init fpga_bridge_dev_init(void)
......
...@@ -94,6 +94,7 @@ MODULE_DEVICE_TABLE(of, xlnx_pr_decoupler_of_match); ...@@ -94,6 +94,7 @@ MODULE_DEVICE_TABLE(of, xlnx_pr_decoupler_of_match);
static int xlnx_pr_decoupler_probe(struct platform_device *pdev) static int xlnx_pr_decoupler_probe(struct platform_device *pdev)
{ {
struct xlnx_pr_decoupler_data *priv; struct xlnx_pr_decoupler_data *priv;
struct fpga_bridge *br;
int err; int err;
struct resource *res; struct resource *res;
...@@ -120,16 +121,27 @@ static int xlnx_pr_decoupler_probe(struct platform_device *pdev) ...@@ -120,16 +121,27 @@ static int xlnx_pr_decoupler_probe(struct platform_device *pdev)
clk_disable(priv->clk); clk_disable(priv->clk);
err = fpga_bridge_register(&pdev->dev, "Xilinx PR Decoupler", br = fpga_bridge_create(&pdev->dev, "Xilinx PR Decoupler",
&xlnx_pr_decoupler_br_ops, priv); &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) { if (err) {
dev_err(&pdev->dev, "unable to register Xilinx PR Decoupler"); dev_err(&pdev->dev, "unable to register Xilinx PR Decoupler");
clk_unprepare(priv->clk); goto err_clk;
return err;
} }
return 0; return 0;
err_clk:
clk_unprepare(priv->clk);
return err;
} }
static int xlnx_pr_decoupler_remove(struct platform_device *pdev) static int xlnx_pr_decoupler_remove(struct platform_device *pdev)
...@@ -137,7 +149,7 @@ 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 fpga_bridge *bridge = platform_get_drvdata(pdev);
struct xlnx_pr_decoupler_data *p = bridge->priv; struct xlnx_pr_decoupler_data *p = bridge->priv;
fpga_bridge_unregister(&pdev->dev); fpga_bridge_unregister(bridge);
clk_unprepare(p->clk); clk_unprepare(p->clk);
......
...@@ -62,8 +62,11 @@ int of_fpga_bridge_get_to_list(struct device_node *np, ...@@ -62,8 +62,11 @@ int of_fpga_bridge_get_to_list(struct device_node *np,
struct fpga_image_info *info, struct fpga_image_info *info,
struct list_head *bridge_list); struct list_head *bridge_list);
int fpga_bridge_register(struct device *dev, const char *name, struct fpga_bridge *fpga_bridge_create(struct device *dev, const char *name,
const struct fpga_bridge_ops *br_ops, void *priv); const struct fpga_bridge_ops *br_ops,
void fpga_bridge_unregister(struct device *dev); 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 */ #endif /* _LINUX_FPGA_BRIDGE_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment