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

Commit 050f7dcd authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'dsa-next'

Florian Fainelli says:

====================
net: dsa: code re-organization

This pull request contains the first part of the patches required to implement
the grand plan detailed here:

http://www.spinics.net/lists/netdev/msg295942.html



These are mostly code re-organization and function bodies re-arrangement to
allow different callers of lower-level initialization functions for 'struct
dsa_switch' and 'struct dsa_switch_tree' to be later introduced.

There is no functional code change at this point.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 49612729 c86e59b9
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -127,6 +127,11 @@ struct dsa_switch {
	struct dsa_switch_tree	*dst;
	int			index;

	/*
	 * Tagging protocol understood by this switch
	 */
	enum dsa_tag_protocol	tag_protocol;

	/*
	 * Configuration data for this switch.
	 */
+121 −93
Original line number Diff line number Diff line
@@ -175,43 +175,14 @@ __ATTRIBUTE_GROUPS(dsa_hwmon);
#endif /* CONFIG_NET_DSA_HWMON */

/* basic switch operations **************************************************/
static struct dsa_switch *
dsa_switch_setup(struct dsa_switch_tree *dst, int index,
		 struct device *parent, struct device *host_dev)
static int dsa_switch_setup_one(struct dsa_switch *ds, struct device *parent)
{
	struct dsa_chip_data *pd = dst->pd->chip + index;
	struct dsa_switch_driver *drv;
	struct dsa_switch *ds;
	int ret;
	char *name;
	int i;
	struct dsa_switch_driver *drv = ds->drv;
	struct dsa_switch_tree *dst = ds->dst;
	struct dsa_chip_data *pd = ds->pd;
	bool valid_name_found = false;

	/*
	 * Probe for switch model.
	 */
	drv = dsa_switch_probe(host_dev, pd->sw_addr, &name);
	if (drv == NULL) {
		netdev_err(dst->master_netdev, "[%d]: could not detect attached switch\n",
			   index);
		return ERR_PTR(-EINVAL);
	}
	netdev_info(dst->master_netdev, "[%d]: detected a %s switch\n",
		    index, name);


	/*
	 * Allocate and initialise switch state.
	 */
	ds = kzalloc(sizeof(*ds) + drv->priv_size, GFP_KERNEL);
	if (ds == NULL)
		return ERR_PTR(-ENOMEM);

	ds->dst = dst;
	ds->index = index;
	ds->pd = dst->pd->chip + index;
	ds->drv = drv;
	ds->master_dev = host_dev;
	int index = ds->index;
	int i, ret;

	/*
	 * Validate supplied switch configuration.
@@ -256,7 +227,7 @@ dsa_switch_setup(struct dsa_switch_tree *dst, int index,
	 * switch.
	 */
	if (dst->cpu_switch == index) {
		switch (drv->tag_protocol) {
		switch (ds->tag_protocol) {
#ifdef CONFIG_NET_DSA_TAG_DSA
		case DSA_TAG_PROTO_DSA:
			dst->rcv = dsa_netdev_ops.rcv;
@@ -284,7 +255,7 @@ dsa_switch_setup(struct dsa_switch_tree *dst, int index,
			goto out;
		}

		dst->tag_protocol = drv->tag_protocol;
		dst->tag_protocol = ds->tag_protocol;
	}

	/*
@@ -350,13 +321,57 @@ dsa_switch_setup(struct dsa_switch_tree *dst, int index,
	}
#endif /* CONFIG_NET_DSA_HWMON */

	return ds;
	return ret;

out_free:
	mdiobus_free(ds->slave_mii_bus);
out:
	kfree(ds);
	return ERR_PTR(ret);
	return ret;
}

static struct dsa_switch *
dsa_switch_setup(struct dsa_switch_tree *dst, int index,
		 struct device *parent, struct device *host_dev)
{
	struct dsa_chip_data *pd = dst->pd->chip + index;
	struct dsa_switch_driver *drv;
	struct dsa_switch *ds;
	int ret;
	char *name;

	/*
	 * Probe for switch model.
	 */
	drv = dsa_switch_probe(host_dev, pd->sw_addr, &name);
	if (drv == NULL) {
		netdev_err(dst->master_netdev, "[%d]: could not detect attached switch\n",
			   index);
		return ERR_PTR(-EINVAL);
	}
	netdev_info(dst->master_netdev, "[%d]: detected a %s switch\n",
		    index, name);


	/*
	 * Allocate and initialise switch state.
	 */
	ds = kzalloc(sizeof(*ds) + drv->priv_size, GFP_KERNEL);
	if (ds == NULL)
		return NULL;

	ds->dst = dst;
	ds->index = index;
	ds->pd = pd;
	ds->drv = drv;
	ds->tag_protocol = drv->tag_protocol;
	ds->master_dev = host_dev;

	ret = dsa_switch_setup_one(ds, parent);
	if (ret)
		return NULL;

	return ds;
}

static void dsa_switch_destroy(struct dsa_switch *ds)
@@ -563,9 +578,9 @@ static void dsa_of_free_platform_data(struct dsa_platform_data *pd)
	kfree(pd->chip);
}

static int dsa_of_probe(struct platform_device *pdev)
static int dsa_of_probe(struct device *dev)
{
	struct device_node *np = pdev->dev.of_node;
	struct device_node *np = dev->of_node;
	struct device_node *child, *mdio, *ethernet, *port, *link;
	struct mii_bus *mdio_bus;
	struct platform_device *ethernet_dev;
@@ -583,7 +598,7 @@ static int dsa_of_probe(struct platform_device *pdev)

	mdio_bus = of_mdio_find_bus(mdio);
	if (!mdio_bus)
		return -EINVAL;
		return -EPROBE_DEFER;

	ethernet = of_parse_phandle(np, "dsa,ethernet", 0);
	if (!ethernet)
@@ -591,13 +606,13 @@ static int dsa_of_probe(struct platform_device *pdev)

	ethernet_dev = of_find_device_by_node(ethernet);
	if (!ethernet_dev)
		return -ENODEV;
		return -EPROBE_DEFER;

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

	pdev->dev.platform_data = pd;
	dev->platform_data = pd;
	pd->netdev = &ethernet_dev->dev;
	pd->nr_chips = of_get_available_child_count(np);
	if (pd->nr_chips > DSA_MAX_SWITCHES)
@@ -670,43 +685,86 @@ static int dsa_of_probe(struct platform_device *pdev)
	dsa_of_free_platform_data(pd);
out_free:
	kfree(pd);
	pdev->dev.platform_data = NULL;
	dev->platform_data = NULL;
	return ret;
}

static void dsa_of_remove(struct platform_device *pdev)
static void dsa_of_remove(struct device *dev)
{
	struct dsa_platform_data *pd = pdev->dev.platform_data;
	struct dsa_platform_data *pd = dev->platform_data;

	if (!pdev->dev.of_node)
	if (!dev->of_node)
		return;

	dsa_of_free_platform_data(pd);
	kfree(pd);
}
#else
static inline int dsa_of_probe(struct platform_device *pdev)
static inline int dsa_of_probe(struct device *dev)
{
	return 0;
}

static inline void dsa_of_remove(struct platform_device *pdev)
static inline void dsa_of_remove(struct device *dev)
{
}
#endif

static void dsa_setup_dst(struct dsa_switch_tree *dst, struct net_device *dev,
			  struct device *parent, struct dsa_platform_data *pd)
{
	int i;

	dst->pd = pd;
	dst->master_netdev = dev;
	dst->cpu_switch = -1;
	dst->cpu_port = -1;

	for (i = 0; i < pd->nr_chips; i++) {
		struct dsa_switch *ds;

		ds = dsa_switch_setup(dst, i, parent, pd->chip[i].host_dev);
		if (IS_ERR(ds)) {
			netdev_err(dev, "[%d]: couldn't create dsa switch instance (error %ld)\n",
				   i, PTR_ERR(ds));
			continue;
		}

		dst->ds[i] = ds;
		if (ds->drv->poll_link != NULL)
			dst->link_poll_needed = 1;
	}

	/*
	 * If we use a tagging format that doesn't have an ethertype
	 * field, make sure that all packets from this point on get
	 * sent to the tag format's receive function.
	 */
	wmb();
	dev->dsa_ptr = (void *)dst;

	if (dst->link_poll_needed) {
		INIT_WORK(&dst->link_poll_work, dsa_link_poll_work);
		init_timer(&dst->link_poll_timer);
		dst->link_poll_timer.data = (unsigned long)dst;
		dst->link_poll_timer.function = dsa_link_poll_timer;
		dst->link_poll_timer.expires = round_jiffies(jiffies + HZ);
		add_timer(&dst->link_poll_timer);
	}
}

static int dsa_probe(struct platform_device *pdev)
{
	struct dsa_platform_data *pd = pdev->dev.platform_data;
	struct net_device *dev;
	struct dsa_switch_tree *dst;
	int i, ret;
	int ret;

	pr_notice_once("Distributed Switch Architecture driver version %s\n",
		       dsa_driver_version);

	if (pdev->dev.of_node) {
		ret = dsa_of_probe(pdev);
		ret = dsa_of_probe(&pdev->dev);
		if (ret)
			return ret;

@@ -718,7 +776,7 @@ static int dsa_probe(struct platform_device *pdev)

	dev = dev_to_net_device(pd->netdev);
	if (dev == NULL) {
		ret = -EINVAL;
		ret = -EPROBE_DEFER;
		goto out;
	}

@@ -737,54 +795,18 @@ static int dsa_probe(struct platform_device *pdev)

	platform_set_drvdata(pdev, dst);

	dst->pd = pd;
	dst->master_netdev = dev;
	dst->cpu_switch = -1;
	dst->cpu_port = -1;

	for (i = 0; i < pd->nr_chips; i++) {
		struct dsa_switch *ds;

		ds = dsa_switch_setup(dst, i, &pdev->dev, pd->chip[i].host_dev);
		if (IS_ERR(ds)) {
			netdev_err(dev, "[%d]: couldn't create dsa switch instance (error %ld)\n",
				   i, PTR_ERR(ds));
			continue;
		}

		dst->ds[i] = ds;
		if (ds->drv->poll_link != NULL)
			dst->link_poll_needed = 1;
	}

	/*
	 * If we use a tagging format that doesn't have an ethertype
	 * field, make sure that all packets from this point on get
	 * sent to the tag format's receive function.
	 */
	wmb();
	dev->dsa_ptr = (void *)dst;

	if (dst->link_poll_needed) {
		INIT_WORK(&dst->link_poll_work, dsa_link_poll_work);
		init_timer(&dst->link_poll_timer);
		dst->link_poll_timer.data = (unsigned long)dst;
		dst->link_poll_timer.function = dsa_link_poll_timer;
		dst->link_poll_timer.expires = round_jiffies(jiffies + HZ);
		add_timer(&dst->link_poll_timer);
	}
	dsa_setup_dst(dst, dev, &pdev->dev, pd);

	return 0;

out:
	dsa_of_remove(pdev);
	dsa_of_remove(&pdev->dev);

	return ret;
}

static int dsa_remove(struct platform_device *pdev)
static void dsa_remove_dst(struct dsa_switch_tree *dst)
{
	struct dsa_switch_tree *dst = platform_get_drvdata(pdev);
	int i;

	if (dst->link_poll_needed)
@@ -798,8 +820,14 @@ static int dsa_remove(struct platform_device *pdev)
		if (ds != NULL)
			dsa_switch_destroy(ds);
	}
}

static int dsa_remove(struct platform_device *pdev)
{
	struct dsa_switch_tree *dst = platform_get_drvdata(pdev);

	dsa_of_remove(pdev);
	dsa_remove_dst(dst);
	dsa_of_remove(&pdev->dev);

	return 0;
}