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

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
...@@ -127,6 +127,11 @@ struct dsa_switch { ...@@ -127,6 +127,11 @@ struct dsa_switch {
struct dsa_switch_tree *dst; struct dsa_switch_tree *dst;
int index; int index;
/*
* Tagging protocol understood by this switch
*/
enum dsa_tag_protocol tag_protocol;
/* /*
* Configuration data for this switch. * Configuration data for this switch.
*/ */
......
...@@ -175,43 +175,14 @@ __ATTRIBUTE_GROUPS(dsa_hwmon); ...@@ -175,43 +175,14 @@ __ATTRIBUTE_GROUPS(dsa_hwmon);
#endif /* CONFIG_NET_DSA_HWMON */ #endif /* CONFIG_NET_DSA_HWMON */
/* basic switch operations **************************************************/ /* basic switch operations **************************************************/
static struct dsa_switch * static int dsa_switch_setup_one(struct dsa_switch *ds, struct device *parent)
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 = ds->drv;
struct dsa_switch_driver *drv; struct dsa_switch_tree *dst = ds->dst;
struct dsa_switch *ds; struct dsa_chip_data *pd = ds->pd;
int ret;
char *name;
int i;
bool valid_name_found = false; bool valid_name_found = false;
int index = ds->index;
/* int i, ret;
* 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;
/* /*
* Validate supplied switch configuration. * Validate supplied switch configuration.
...@@ -256,7 +227,7 @@ dsa_switch_setup(struct dsa_switch_tree *dst, int index, ...@@ -256,7 +227,7 @@ dsa_switch_setup(struct dsa_switch_tree *dst, int index,
* switch. * switch.
*/ */
if (dst->cpu_switch == index) { if (dst->cpu_switch == index) {
switch (drv->tag_protocol) { switch (ds->tag_protocol) {
#ifdef CONFIG_NET_DSA_TAG_DSA #ifdef CONFIG_NET_DSA_TAG_DSA
case DSA_TAG_PROTO_DSA: case DSA_TAG_PROTO_DSA:
dst->rcv = dsa_netdev_ops.rcv; dst->rcv = dsa_netdev_ops.rcv;
...@@ -284,7 +255,7 @@ dsa_switch_setup(struct dsa_switch_tree *dst, int index, ...@@ -284,7 +255,7 @@ dsa_switch_setup(struct dsa_switch_tree *dst, int index,
goto out; 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, ...@@ -350,13 +321,57 @@ dsa_switch_setup(struct dsa_switch_tree *dst, int index,
} }
#endif /* CONFIG_NET_DSA_HWMON */ #endif /* CONFIG_NET_DSA_HWMON */
return ds; return ret;
out_free: out_free:
mdiobus_free(ds->slave_mii_bus); mdiobus_free(ds->slave_mii_bus);
out: out:
kfree(ds); 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) 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) ...@@ -563,9 +578,9 @@ static void dsa_of_free_platform_data(struct dsa_platform_data *pd)
kfree(pd->chip); 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 device_node *child, *mdio, *ethernet, *port, *link;
struct mii_bus *mdio_bus; struct mii_bus *mdio_bus;
struct platform_device *ethernet_dev; struct platform_device *ethernet_dev;
...@@ -583,7 +598,7 @@ static int dsa_of_probe(struct platform_device *pdev) ...@@ -583,7 +598,7 @@ static int dsa_of_probe(struct platform_device *pdev)
mdio_bus = of_mdio_find_bus(mdio); mdio_bus = of_mdio_find_bus(mdio);
if (!mdio_bus) if (!mdio_bus)
return -EINVAL; return -EPROBE_DEFER;
ethernet = of_parse_phandle(np, "dsa,ethernet", 0); ethernet = of_parse_phandle(np, "dsa,ethernet", 0);
if (!ethernet) if (!ethernet)
...@@ -591,13 +606,13 @@ static int dsa_of_probe(struct platform_device *pdev) ...@@ -591,13 +606,13 @@ static int dsa_of_probe(struct platform_device *pdev)
ethernet_dev = of_find_device_by_node(ethernet); ethernet_dev = of_find_device_by_node(ethernet);
if (!ethernet_dev) if (!ethernet_dev)
return -ENODEV; return -EPROBE_DEFER;
pd = kzalloc(sizeof(*pd), GFP_KERNEL); pd = kzalloc(sizeof(*pd), GFP_KERNEL);
if (!pd) if (!pd)
return -ENOMEM; return -ENOMEM;
pdev->dev.platform_data = pd; dev->platform_data = pd;
pd->netdev = &ethernet_dev->dev; pd->netdev = &ethernet_dev->dev;
pd->nr_chips = of_get_available_child_count(np); pd->nr_chips = of_get_available_child_count(np);
if (pd->nr_chips > DSA_MAX_SWITCHES) if (pd->nr_chips > DSA_MAX_SWITCHES)
...@@ -670,43 +685,86 @@ static int dsa_of_probe(struct platform_device *pdev) ...@@ -670,43 +685,86 @@ static int dsa_of_probe(struct platform_device *pdev)
dsa_of_free_platform_data(pd); dsa_of_free_platform_data(pd);
out_free: out_free:
kfree(pd); kfree(pd);
pdev->dev.platform_data = NULL; dev->platform_data = NULL;
return ret; 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; return;
dsa_of_free_platform_data(pd); dsa_of_free_platform_data(pd);
kfree(pd); kfree(pd);
} }
#else #else
static inline int dsa_of_probe(struct platform_device *pdev) static inline int dsa_of_probe(struct device *dev)
{ {
return 0; return 0;
} }
static inline void dsa_of_remove(struct platform_device *pdev) static inline void dsa_of_remove(struct device *dev)
{ {
} }
#endif #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) static int dsa_probe(struct platform_device *pdev)
{ {
struct dsa_platform_data *pd = pdev->dev.platform_data; struct dsa_platform_data *pd = pdev->dev.platform_data;
struct net_device *dev; struct net_device *dev;
struct dsa_switch_tree *dst; struct dsa_switch_tree *dst;
int i, ret; int ret;
pr_notice_once("Distributed Switch Architecture driver version %s\n", pr_notice_once("Distributed Switch Architecture driver version %s\n",
dsa_driver_version); dsa_driver_version);
if (pdev->dev.of_node) { if (pdev->dev.of_node) {
ret = dsa_of_probe(pdev); ret = dsa_of_probe(&pdev->dev);
if (ret) if (ret)
return ret; return ret;
...@@ -718,7 +776,7 @@ static int dsa_probe(struct platform_device *pdev) ...@@ -718,7 +776,7 @@ static int dsa_probe(struct platform_device *pdev)
dev = dev_to_net_device(pd->netdev); dev = dev_to_net_device(pd->netdev);
if (dev == NULL) { if (dev == NULL) {
ret = -EINVAL; ret = -EPROBE_DEFER;
goto out; goto out;
} }
...@@ -737,54 +795,18 @@ static int dsa_probe(struct platform_device *pdev) ...@@ -737,54 +795,18 @@ static int dsa_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, dst); platform_set_drvdata(pdev, dst);
dst->pd = pd; dsa_setup_dst(dst, dev, &pdev->dev, 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);
}
return 0; return 0;
out: out:
dsa_of_remove(pdev); dsa_of_remove(&pdev->dev);
return ret; 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; int i;
if (dst->link_poll_needed) if (dst->link_poll_needed)
...@@ -798,8 +820,14 @@ static int dsa_remove(struct platform_device *pdev) ...@@ -798,8 +820,14 @@ static int dsa_remove(struct platform_device *pdev)
if (ds != NULL) if (ds != NULL)
dsa_switch_destroy(ds); 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; return 0;
} }
......
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