Skip to content

Commit

Permalink
Merge branch 'more-dsa-unbinding-fixes'
Browse files Browse the repository at this point in the history
Neil Armstrong says:

====================
Further fix for dsa unbinding

This series fixes further issues for DSA dynamic unbinding.
The first patch completely removes the PHY link state polling.
The two following cleans up the dsa state upon removal.
The last patch moves slave destroy code as slave function and
adds missing netdev and phy cleanup calls.

v1: http://lkml.kernel.org/r/562F8ECB.6050709@baylibre.com
v2: http://lkml.kernel.org/r/56321D9A.8010109@baylibre.com
remove phy fix and add missing calls in dsa_switch_destroy
then add dedicated dsa_slave_destroy

v3: remove polling instead of fixing it, make single patch for
dsa slave destroy
====================

Acked-by: Andrew Lunn <andrew@lunn.ch>
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Dec 7, 2015
2 parents ad9360b + cda5c15 commit 611d7df
Show file tree
Hide file tree
Showing 4 changed files with 26 additions and 58 deletions.
12 changes: 0 additions & 12 deletions include/net/dsa.h
Original file line number Diff line number Diff line change
Expand Up @@ -116,13 +116,6 @@ struct dsa_switch_tree {
s8 cpu_switch;
s8 cpu_port;

/*
* Link state polling.
*/
int link_poll_needed;
struct work_struct link_poll_work;
struct timer_list link_poll_timer;

/*
* Data for the individual switch chips.
*/
Expand Down Expand Up @@ -231,11 +224,6 @@ struct dsa_switch_driver {
int (*phy_write)(struct dsa_switch *ds, int port,
int regnum, u16 val);

/*
* Link state polling and IRQ handling.
*/
void (*poll_link)(struct dsa_switch *ds);

/*
* Link state adjustment (called from libphy)
*/
Expand Down
60 changes: 14 additions & 46 deletions net/dsa/dsa.c
Original file line number Diff line number Diff line change
Expand Up @@ -456,8 +456,7 @@ static void dsa_switch_destroy(struct dsa_switch *ds)
if (!ds->ports[port])
continue;

unregister_netdev(ds->ports[port]);
free_netdev(ds->ports[port]);
dsa_slave_destroy(ds->ports[port]);
}

mdiobus_unregister(ds->slave_mii_bus);
Expand Down Expand Up @@ -508,33 +507,6 @@ static int dsa_switch_resume(struct dsa_switch *ds)
}
#endif


/* link polling *************************************************************/
static void dsa_link_poll_work(struct work_struct *ugly)
{
struct dsa_switch_tree *dst;
int i;

dst = container_of(ugly, struct dsa_switch_tree, link_poll_work);

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

if (ds != NULL && ds->drv->poll_link != NULL)
ds->drv->poll_link(ds);
}

mod_timer(&dst->link_poll_timer, round_jiffies(jiffies + HZ));
}

static void dsa_link_poll_timer(unsigned long _dst)
{
struct dsa_switch_tree *dst = (void *)_dst;

schedule_work(&dst->link_poll_work);
}


/* platform driver init and cleanup *****************************************/
static int dev_is_class(struct device *dev, void *class)
{
Expand Down Expand Up @@ -877,8 +849,6 @@ static int dsa_setup_dst(struct dsa_switch_tree *dst, struct net_device *dev,
}

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

++configured;
}
Expand All @@ -897,15 +867,6 @@ static int dsa_setup_dst(struct dsa_switch_tree *dst, struct net_device *dev,
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;
}

Expand Down Expand Up @@ -957,8 +918,10 @@ static int dsa_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, dst);

ret = dsa_setup_dst(dst, dev, &pdev->dev, pd);
if (ret)
if (ret) {
dev_put(dev);
goto out;
}

return 0;

Expand All @@ -972,17 +935,14 @@ static void dsa_remove_dst(struct dsa_switch_tree *dst)
{
int i;

if (dst->link_poll_needed)
del_timer_sync(&dst->link_poll_timer);

flush_work(&dst->link_poll_work);

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

if (ds)
dsa_switch_destroy(ds);
}

dev_put(dst->master_netdev);
}

static int dsa_remove(struct platform_device *pdev)
Expand Down Expand Up @@ -1028,6 +988,14 @@ static int dsa_suspend(struct device *d)
struct dsa_switch_tree *dst = platform_get_drvdata(pdev);
int i, ret = 0;

dst->master_netdev->dsa_ptr = NULL;

/* If we used a tagging format that doesn't have an ethertype
* field, make sure that all packets from this point get sent
* without the tag and go through the regular receive path.
*/
wmb();

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

Expand Down
1 change: 1 addition & 0 deletions net/dsa/dsa_priv.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ extern const struct dsa_device_ops notag_netdev_ops;
void dsa_slave_mii_bus_init(struct dsa_switch *ds);
int dsa_slave_create(struct dsa_switch *ds, struct device *parent,
int port, char *name);
void dsa_slave_destroy(struct net_device *slave_dev);
int dsa_slave_suspend(struct net_device *slave_dev);
int dsa_slave_resume(struct net_device *slave_dev);
int dsa_slave_netdevice_event(struct notifier_block *unused,
Expand Down
11 changes: 11 additions & 0 deletions net/dsa/slave.c
Original file line number Diff line number Diff line change
Expand Up @@ -1212,6 +1212,17 @@ int dsa_slave_create(struct dsa_switch *ds, struct device *parent,
return 0;
}

void dsa_slave_destroy(struct net_device *slave_dev)
{
struct dsa_slave_priv *p = netdev_priv(slave_dev);

netif_carrier_off(slave_dev);
if (p->phy)
phy_disconnect(p->phy);
unregister_netdev(slave_dev);
free_netdev(slave_dev);
}

static bool dsa_slave_dev_check(struct net_device *dev)
{
return dev->netdev_ops == &dsa_slave_netdev_ops;
Expand Down

0 comments on commit 611d7df

Please sign in to comment.