Merge branch 'phy_power'
Sebastian Hesselbarth says: ==================== net: phy: Ethernet PHY powerdown optimization This is v2 of the ethernet PHY power optimization patches to reduce power consumption of network PHYs with link that are either unused or the corresponding netdev is down. Compared to the last version, this patch set drops a patch to disable unused PHYs after late initcall, as it is not compatible with a modular mdio bus [1]. I'll investigate different ways to have a modular mdio bus driver get notified when driver loading is done. Again, a branch with v2 applied to v3.13-rc2 can also be found at https://github.com/shesselba/linux-dove.git topic/ethphy-power-v2 [1] http://www.spinics.net/lists/arm-kernel/msg293028.html ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Коммит
b80b376c44
|
@ -2080,6 +2080,7 @@ static void port_start(struct mv643xx_eth_private *mp)
|
|||
mv643xx_eth_get_settings(mp->dev, &cmd);
|
||||
phy_init_hw(mp->phy);
|
||||
mv643xx_eth_set_settings(mp->dev, &cmd);
|
||||
phy_start(mp->phy);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -2275,7 +2276,8 @@ static int mv643xx_eth_stop(struct net_device *dev)
|
|||
del_timer_sync(&mp->rx_oom);
|
||||
|
||||
netif_carrier_off(dev);
|
||||
|
||||
if (mp->phy)
|
||||
phy_stop(mp->phy);
|
||||
free_irq(dev->irq, dev);
|
||||
|
||||
port_reset(mp);
|
||||
|
|
|
@ -894,6 +894,8 @@ static struct phy_driver marvell_drivers[] = {
|
|||
.read_status = &genphy_read_status,
|
||||
.ack_interrupt = &marvell_ack_interrupt,
|
||||
.config_intr = &marvell_config_intr,
|
||||
.resume = &genphy_resume,
|
||||
.suspend = &genphy_suspend,
|
||||
.driver = { .owner = THIS_MODULE },
|
||||
},
|
||||
{
|
||||
|
@ -907,6 +909,8 @@ static struct phy_driver marvell_drivers[] = {
|
|||
.read_status = &genphy_read_status,
|
||||
.ack_interrupt = &marvell_ack_interrupt,
|
||||
.config_intr = &marvell_config_intr,
|
||||
.resume = &genphy_resume,
|
||||
.suspend = &genphy_suspend,
|
||||
.driver = { .owner = THIS_MODULE },
|
||||
},
|
||||
{
|
||||
|
@ -920,6 +924,8 @@ static struct phy_driver marvell_drivers[] = {
|
|||
.read_status = &marvell_read_status,
|
||||
.ack_interrupt = &marvell_ack_interrupt,
|
||||
.config_intr = &marvell_config_intr,
|
||||
.resume = &genphy_resume,
|
||||
.suspend = &genphy_suspend,
|
||||
.driver = { .owner = THIS_MODULE },
|
||||
},
|
||||
{
|
||||
|
@ -933,6 +939,8 @@ static struct phy_driver marvell_drivers[] = {
|
|||
.read_status = &genphy_read_status,
|
||||
.ack_interrupt = &marvell_ack_interrupt,
|
||||
.config_intr = &marvell_config_intr,
|
||||
.resume = &genphy_resume,
|
||||
.suspend = &genphy_suspend,
|
||||
.driver = {.owner = THIS_MODULE,},
|
||||
},
|
||||
{
|
||||
|
@ -946,6 +954,8 @@ static struct phy_driver marvell_drivers[] = {
|
|||
.ack_interrupt = &marvell_ack_interrupt,
|
||||
.config_intr = &marvell_config_intr,
|
||||
.did_interrupt = &m88e1121_did_interrupt,
|
||||
.resume = &genphy_resume,
|
||||
.suspend = &genphy_suspend,
|
||||
.driver = { .owner = THIS_MODULE },
|
||||
},
|
||||
{
|
||||
|
@ -961,6 +971,8 @@ static struct phy_driver marvell_drivers[] = {
|
|||
.did_interrupt = &m88e1121_did_interrupt,
|
||||
.get_wol = &m88e1318_get_wol,
|
||||
.set_wol = &m88e1318_set_wol,
|
||||
.resume = &genphy_resume,
|
||||
.suspend = &genphy_suspend,
|
||||
.driver = { .owner = THIS_MODULE },
|
||||
},
|
||||
{
|
||||
|
@ -974,6 +986,8 @@ static struct phy_driver marvell_drivers[] = {
|
|||
.read_status = &genphy_read_status,
|
||||
.ack_interrupt = &marvell_ack_interrupt,
|
||||
.config_intr = &marvell_config_intr,
|
||||
.resume = &genphy_resume,
|
||||
.suspend = &genphy_suspend,
|
||||
.driver = { .owner = THIS_MODULE },
|
||||
},
|
||||
{
|
||||
|
@ -987,6 +1001,8 @@ static struct phy_driver marvell_drivers[] = {
|
|||
.read_status = &genphy_read_status,
|
||||
.ack_interrupt = &marvell_ack_interrupt,
|
||||
.config_intr = &marvell_config_intr,
|
||||
.resume = &genphy_resume,
|
||||
.suspend = &genphy_suspend,
|
||||
.driver = { .owner = THIS_MODULE },
|
||||
},
|
||||
{
|
||||
|
@ -1000,6 +1016,8 @@ static struct phy_driver marvell_drivers[] = {
|
|||
.read_status = &genphy_read_status,
|
||||
.ack_interrupt = &marvell_ack_interrupt,
|
||||
.config_intr = &marvell_config_intr,
|
||||
.resume = &genphy_resume,
|
||||
.suspend = &genphy_suspend,
|
||||
.driver = { .owner = THIS_MODULE },
|
||||
},
|
||||
{
|
||||
|
@ -1013,6 +1031,8 @@ static struct phy_driver marvell_drivers[] = {
|
|||
.read_status = &genphy_read_status,
|
||||
.ack_interrupt = &marvell_ack_interrupt,
|
||||
.config_intr = &marvell_config_intr,
|
||||
.resume = &genphy_resume,
|
||||
.suspend = &genphy_suspend,
|
||||
.driver = { .owner = THIS_MODULE },
|
||||
},
|
||||
{
|
||||
|
@ -1026,6 +1046,8 @@ static struct phy_driver marvell_drivers[] = {
|
|||
.ack_interrupt = &marvell_ack_interrupt,
|
||||
.config_intr = &marvell_config_intr,
|
||||
.did_interrupt = &m88e1121_did_interrupt,
|
||||
.resume = &genphy_resume,
|
||||
.suspend = &genphy_suspend,
|
||||
.driver = { .owner = THIS_MODULE },
|
||||
},
|
||||
};
|
||||
|
|
|
@ -739,7 +739,7 @@ void phy_state_machine(struct work_struct *work)
|
|||
struct delayed_work *dwork = to_delayed_work(work);
|
||||
struct phy_device *phydev =
|
||||
container_of(dwork, struct phy_device, state_queue);
|
||||
int needs_aneg = 0;
|
||||
int needs_aneg = 0, do_suspend = 0;
|
||||
int err = 0;
|
||||
|
||||
mutex_lock(&phydev->lock);
|
||||
|
@ -854,6 +854,7 @@ void phy_state_machine(struct work_struct *work)
|
|||
phydev->link = 0;
|
||||
netif_carrier_off(phydev->attached_dev);
|
||||
phydev->adjust_link(phydev->attached_dev);
|
||||
do_suspend = 1;
|
||||
}
|
||||
break;
|
||||
case PHY_RESUMING:
|
||||
|
@ -912,6 +913,9 @@ void phy_state_machine(struct work_struct *work)
|
|||
if (needs_aneg)
|
||||
err = phy_start_aneg(phydev);
|
||||
|
||||
if (do_suspend)
|
||||
phy_suspend(phydev);
|
||||
|
||||
if (err < 0)
|
||||
phy_error(phydev);
|
||||
|
||||
|
|
|
@ -624,6 +624,8 @@ static int phy_attach_direct(struct net_device *dev, struct phy_device *phydev,
|
|||
if (err)
|
||||
phy_detach(phydev);
|
||||
|
||||
phy_resume(phydev);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -669,6 +671,7 @@ void phy_detach(struct phy_device *phydev)
|
|||
{
|
||||
phydev->attached_dev->phydev = NULL;
|
||||
phydev->attached_dev = NULL;
|
||||
phy_suspend(phydev);
|
||||
|
||||
/* If the device had no specific driver before (i.e. - it
|
||||
* was using the generic driver), we unbind the device
|
||||
|
@ -679,6 +682,30 @@ void phy_detach(struct phy_device *phydev)
|
|||
}
|
||||
EXPORT_SYMBOL(phy_detach);
|
||||
|
||||
int phy_suspend(struct phy_device *phydev)
|
||||
{
|
||||
struct phy_driver *phydrv = to_phy_driver(phydev->dev.driver);
|
||||
struct ethtool_wolinfo wol;
|
||||
|
||||
/* If the device has WOL enabled, we cannot suspend the PHY */
|
||||
wol.cmd = ETHTOOL_GWOL;
|
||||
phy_ethtool_get_wol(phydev, &wol);
|
||||
if (wol.wolopts)
|
||||
return -EBUSY;
|
||||
|
||||
if (phydrv->suspend)
|
||||
return phydrv->suspend(phydev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int phy_resume(struct phy_device *phydev)
|
||||
{
|
||||
struct phy_driver *phydrv = to_phy_driver(phydev->dev.driver);
|
||||
|
||||
if (phydrv->resume)
|
||||
return phydrv->resume(phydev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Generic PHY support and helper functions */
|
||||
|
||||
|
|
|
@ -548,6 +548,8 @@ struct phy_device *phy_device_create(struct mii_bus *bus, int addr, int phy_id,
|
|||
struct phy_device *get_phy_device(struct mii_bus *bus, int addr, bool is_c45);
|
||||
int phy_device_register(struct phy_device *phy);
|
||||
int phy_init_hw(struct phy_device *phydev);
|
||||
int phy_suspend(struct phy_device *phydev);
|
||||
int phy_resume(struct phy_device *phydev);
|
||||
struct phy_device * phy_attach(struct net_device *dev,
|
||||
const char *bus_id, phy_interface_t interface);
|
||||
struct phy_device *phy_find_first(struct mii_bus *bus);
|
||||
|
|
Загрузка…
Ссылка в новой задаче