net: dsa: allow enabling and disable switch ports
Whenever a per-port network device is used/unused, invoke the switch driver port_enable/port_disable callbacks to allow saving as much power as possible by disabling unused parts of the switch (RX/TX logic, memory arrays, PHYs...). We supply a PHY device argument to make sure the switch driver can act on the PHY device if needed (like putting/taking the PHY out of deep low power mode). Signed-off-by: Florian Fainelli <f.fainelli@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
f7f1de51ed
commit
b2f2af21e3
@ -224,6 +224,14 @@ struct dsa_switch_driver {
|
||||
*/
|
||||
int (*suspend)(struct dsa_switch *ds);
|
||||
int (*resume)(struct dsa_switch *ds);
|
||||
|
||||
/*
|
||||
* Port enable/disable
|
||||
*/
|
||||
int (*port_enable)(struct dsa_switch *ds, int port,
|
||||
struct phy_device *phy);
|
||||
void (*port_disable)(struct dsa_switch *ds, int port,
|
||||
struct phy_device *phy);
|
||||
};
|
||||
|
||||
void register_switch_driver(struct dsa_switch_driver *type);
|
||||
|
@ -62,6 +62,7 @@ static int dsa_slave_open(struct net_device *dev)
|
||||
{
|
||||
struct dsa_slave_priv *p = netdev_priv(dev);
|
||||
struct net_device *master = p->parent->dst->master_netdev;
|
||||
struct dsa_switch *ds = p->parent;
|
||||
int err;
|
||||
|
||||
if (!(master->flags & IFF_UP))
|
||||
@ -84,11 +85,20 @@ static int dsa_slave_open(struct net_device *dev)
|
||||
goto clear_allmulti;
|
||||
}
|
||||
|
||||
if (ds->drv->port_enable) {
|
||||
err = ds->drv->port_enable(ds, p->port, p->phy);
|
||||
if (err)
|
||||
goto clear_promisc;
|
||||
}
|
||||
|
||||
if (p->phy)
|
||||
phy_start(p->phy);
|
||||
|
||||
return 0;
|
||||
|
||||
clear_promisc:
|
||||
if (dev->flags & IFF_PROMISC)
|
||||
dev_set_promiscuity(master, 0);
|
||||
clear_allmulti:
|
||||
if (dev->flags & IFF_ALLMULTI)
|
||||
dev_set_allmulti(master, -1);
|
||||
@ -103,6 +113,7 @@ static int dsa_slave_close(struct net_device *dev)
|
||||
{
|
||||
struct dsa_slave_priv *p = netdev_priv(dev);
|
||||
struct net_device *master = p->parent->dst->master_netdev;
|
||||
struct dsa_switch *ds = p->parent;
|
||||
|
||||
if (p->phy)
|
||||
phy_stop(p->phy);
|
||||
@ -117,6 +128,9 @@ static int dsa_slave_close(struct net_device *dev)
|
||||
if (!ether_addr_equal(dev->dev_addr, master->dev_addr))
|
||||
dev_uc_del(master, dev->dev_addr);
|
||||
|
||||
if (ds->drv->port_disable)
|
||||
ds->drv->port_disable(ds, p->port, p->phy);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user