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 {
struct dsa_switch_tree *dst;
int index;
/*
* Tagging protocol understood by this switch
*/
enum dsa_tag_protocol tag_protocol;
/*
* Configuration data for this switch.
*/
......
......@@ -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;
}
......
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