Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+16 −5
Original line number Diff line number Diff line
@@ -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,
	br = fpga_bridge_create(dev, F2S_BRIDGE_NAME,
				&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;
	}

	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;
}
+19 −3
Original line number Diff line number Diff line
@@ -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,
	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;
}
+19 −5
Original line number Diff line number Diff line
@@ -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,10 +191,23 @@ 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)
		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);

+46 −24
Original line number Diff line number Diff line
@@ -328,28 +328,29 @@ static struct attribute *fpga_bridge_attrs[] = {
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
 * @name:	FPGA bridge name
 * @br_ops:	pointer to structure of fpga bridge ops
 * @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,
			 const struct fpga_bridge_ops *br_ops, void *priv)
struct fpga_bridge *fpga_bridge_create(struct device *dev, const char *name,
				       const struct fpga_bridge_ops *br_ops,
				       void *priv)
{
	struct fpga_bridge *bridge;
	int id, ret = 0;

	if (!name || !strlen(name)) {
		dev_err(dev, "Attempt to register with no name!\n");
		return -EINVAL;
		return NULL;
	}

	bridge = kzalloc(sizeof(*bridge), GFP_KERNEL);
	if (!bridge)
		return -ENOMEM;
		return NULL;

	id = ida_simple_get(&fpga_bridge_ida, 0, 0, GFP_KERNEL);
	if (id < 0) {
@@ -370,40 +371,62 @@ int fpga_bridge_register(struct device *dev, const char *name,
	bridge->dev.parent = dev;
	bridge->dev.of_node = dev->of_node;
	bridge->dev.id = id;
	dev_set_drvdata(dev, bridge);

	ret = dev_set_name(&bridge->dev, "br%d", id);
	if (ret)
		goto error_device;

	ret = device_add(&bridge->dev);
	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;
	return bridge;

error_device:
	ida_simple_remove(&fpga_bridge_ida, id);
error_kfree:
	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;

	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);

/**
 * 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
	 * a desired state upon unregister, do it.
@@ -419,8 +442,7 @@ 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);
	fpga_bridge_free(bridge);
}

static int __init fpga_bridge_dev_init(void)
+17 −5
Original line number Diff line number Diff line
@@ -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",
	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);

Loading