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 (*suspend)(struct dsa_switch *ds);
|
||||||
int (*resume)(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);
|
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 dsa_slave_priv *p = netdev_priv(dev);
|
||||||
struct net_device *master = p->parent->dst->master_netdev;
|
struct net_device *master = p->parent->dst->master_netdev;
|
||||||
|
struct dsa_switch *ds = p->parent;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
if (!(master->flags & IFF_UP))
|
if (!(master->flags & IFF_UP))
|
||||||
@ -84,11 +85,20 @@ static int dsa_slave_open(struct net_device *dev)
|
|||||||
goto clear_allmulti;
|
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)
|
if (p->phy)
|
||||||
phy_start(p->phy);
|
phy_start(p->phy);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
clear_promisc:
|
||||||
|
if (dev->flags & IFF_PROMISC)
|
||||||
|
dev_set_promiscuity(master, 0);
|
||||||
clear_allmulti:
|
clear_allmulti:
|
||||||
if (dev->flags & IFF_ALLMULTI)
|
if (dev->flags & IFF_ALLMULTI)
|
||||||
dev_set_allmulti(master, -1);
|
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 dsa_slave_priv *p = netdev_priv(dev);
|
||||||
struct net_device *master = p->parent->dst->master_netdev;
|
struct net_device *master = p->parent->dst->master_netdev;
|
||||||
|
struct dsa_switch *ds = p->parent;
|
||||||
|
|
||||||
if (p->phy)
|
if (p->phy)
|
||||||
phy_stop(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))
|
if (!ether_addr_equal(dev->dev_addr, master->dev_addr))
|
||||||
dev_uc_del(master, dev->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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user