aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBruce Allan <bruce.w.allan@intel.com>2009-12-01 10:47:22 -0500
committerDavid S. Miller <davem@davemloft.net>2009-12-02 03:35:52 -0500
commit17f208deb9bf88315aa72c08c866a235c399fb9a (patch)
tree9cc8bc9ce40587590fcea9d80e134adaf54567b2
parenteb656d4552a6c9de5fdcee4a376b171f57b8a4a2 (diff)
e1000e: provide family-specific PHY power up/down operations
The different families (80003es2lan, 8257x, ICHx/PCH) supported by the driver each have their own conditions when the PHY can be powered down. This patch rewrites the PHY power up/down code to fit with the family- specific style used in the driver. All pre-existing calls to power up or down the PHY remain untouched. A new call to power down the PHY when removing the driver when the interface is down replaces the current call to reset the PHY in order to reduce power consumption. Signed-off-by: Bruce Allan <bruce.w.allan@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/e1000e/82571.c26
-rw-r--r--drivers/net/e1000e/e1000.h2
-rw-r--r--drivers/net/e1000e/es2lan.c21
-rw-r--r--drivers/net/e1000e/hw.h2
-rw-r--r--drivers/net/e1000e/ich8lan.c23
-rw-r--r--drivers/net/e1000e/netdev.c50
-rw-r--r--drivers/net/e1000e/phy.c37
7 files changed, 122 insertions, 39 deletions
diff --git a/drivers/net/e1000e/82571.c b/drivers/net/e1000e/82571.c
index 8ea3ed7e5364..26ea5d57a354 100644
--- a/drivers/net/e1000e/82571.c
+++ b/drivers/net/e1000e/82571.c
@@ -69,6 +69,7 @@ static void e1000_clear_vfta_82571(struct e1000_hw *hw);
69static bool e1000_check_mng_mode_82574(struct e1000_hw *hw); 69static bool e1000_check_mng_mode_82574(struct e1000_hw *hw);
70static s32 e1000_led_on_82574(struct e1000_hw *hw); 70static s32 e1000_led_on_82574(struct e1000_hw *hw);
71static void e1000_put_hw_semaphore_82571(struct e1000_hw *hw); 71static void e1000_put_hw_semaphore_82571(struct e1000_hw *hw);
72static void e1000_power_down_phy_copper_82571(struct e1000_hw *hw);
72 73
73/** 74/**
74 * e1000_init_phy_params_82571 - Init PHY func ptrs. 75 * e1000_init_phy_params_82571 - Init PHY func ptrs.
@@ -88,6 +89,9 @@ static s32 e1000_init_phy_params_82571(struct e1000_hw *hw)
88 phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT; 89 phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT;
89 phy->reset_delay_us = 100; 90 phy->reset_delay_us = 100;
90 91
92 phy->ops.power_up = e1000_power_up_phy_copper;
93 phy->ops.power_down = e1000_power_down_phy_copper_82571;
94
91 switch (hw->mac.type) { 95 switch (hw->mac.type) {
92 case e1000_82571: 96 case e1000_82571:
93 case e1000_82572: 97 case e1000_82572:
@@ -1601,6 +1605,28 @@ static s32 e1000_fix_nvm_checksum_82571(struct e1000_hw *hw)
1601} 1605}
1602 1606
1603/** 1607/**
1608 * e1000_power_down_phy_copper_82571 - Remove link during PHY power down
1609 * @hw: pointer to the HW structure
1610 *
1611 * In the case of a PHY power down to save power, or to turn off link during a
1612 * driver unload, or wake on lan is not enabled, remove the link.
1613 **/
1614static void e1000_power_down_phy_copper_82571(struct e1000_hw *hw)
1615{
1616 struct e1000_phy_info *phy = &hw->phy;
1617 struct e1000_mac_info *mac = &hw->mac;
1618
1619 if (!(phy->ops.check_reset_block))
1620 return;
1621
1622 /* If the management interface is not enabled, then power down */
1623 if (!(mac->ops.check_mng_mode(hw) || phy->ops.check_reset_block(hw)))
1624 e1000_power_down_phy_copper(hw);
1625
1626 return;
1627}
1628
1629/**
1604 * e1000_clear_hw_cntrs_82571 - Clear device specific hardware counters 1630 * e1000_clear_hw_cntrs_82571 - Clear device specific hardware counters
1605 * @hw: pointer to the HW structure 1631 * @hw: pointer to the HW structure
1606 * 1632 *
diff --git a/drivers/net/e1000e/e1000.h b/drivers/net/e1000e/e1000.h
index 4c08752b824d..c4e861fb3862 100644
--- a/drivers/net/e1000e/e1000.h
+++ b/drivers/net/e1000e/e1000.h
@@ -568,6 +568,8 @@ extern s32 e1000e_read_kmrn_reg_locked(struct e1000_hw *hw, u32 offset,
568extern s32 e1000e_phy_has_link_generic(struct e1000_hw *hw, u32 iterations, 568extern s32 e1000e_phy_has_link_generic(struct e1000_hw *hw, u32 iterations,
569 u32 usec_interval, bool *success); 569 u32 usec_interval, bool *success);
570extern s32 e1000e_phy_reset_dsp(struct e1000_hw *hw); 570extern s32 e1000e_phy_reset_dsp(struct e1000_hw *hw);
571extern void e1000_power_up_phy_copper(struct e1000_hw *hw);
572extern void e1000_power_down_phy_copper(struct e1000_hw *hw);
571extern s32 e1000e_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data); 573extern s32 e1000e_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data);
572extern s32 e1000e_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data); 574extern s32 e1000e_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data);
573extern s32 e1000e_check_downshift(struct e1000_hw *hw); 575extern s32 e1000e_check_downshift(struct e1000_hw *hw);
diff --git a/drivers/net/e1000e/es2lan.c b/drivers/net/e1000e/es2lan.c
index 3f435c16608d..c7bc657b5da2 100644
--- a/drivers/net/e1000e/es2lan.c
+++ b/drivers/net/e1000e/es2lan.c
@@ -114,6 +114,7 @@ static s32 e1000_read_kmrn_reg_80003es2lan(struct e1000_hw *hw, u32 offset,
114 u16 *data); 114 u16 *data);
115static s32 e1000_write_kmrn_reg_80003es2lan(struct e1000_hw *hw, u32 offset, 115static s32 e1000_write_kmrn_reg_80003es2lan(struct e1000_hw *hw, u32 offset,
116 u16 data); 116 u16 data);
117static void e1000_power_down_phy_copper_80003es2lan(struct e1000_hw *hw);
117 118
118/** 119/**
119 * e1000_init_phy_params_80003es2lan - Init ESB2 PHY func ptrs. 120 * e1000_init_phy_params_80003es2lan - Init ESB2 PHY func ptrs.
@@ -127,6 +128,9 @@ static s32 e1000_init_phy_params_80003es2lan(struct e1000_hw *hw)
127 if (hw->phy.media_type != e1000_media_type_copper) { 128 if (hw->phy.media_type != e1000_media_type_copper) {
128 phy->type = e1000_phy_none; 129 phy->type = e1000_phy_none;
129 return 0; 130 return 0;
131 } else {
132 phy->ops.power_up = e1000_power_up_phy_copper;
133 phy->ops.power_down = e1000_power_down_phy_copper_80003es2lan;
130 } 134 }
131 135
132 phy->addr = 1; 136 phy->addr = 1;
@@ -1303,6 +1307,23 @@ static s32 e1000_write_kmrn_reg_80003es2lan(struct e1000_hw *hw, u32 offset,
1303} 1307}
1304 1308
1305/** 1309/**
1310 * e1000_power_down_phy_copper_80003es2lan - Remove link during PHY power down
1311 * @hw: pointer to the HW structure
1312 *
1313 * In the case of a PHY power down to save power, or to turn off link during a
1314 * driver unload, or wake on lan is not enabled, remove the link.
1315 **/
1316static void e1000_power_down_phy_copper_80003es2lan(struct e1000_hw *hw)
1317{
1318 /* If the management interface is not enabled, then power down */
1319 if (!(hw->mac.ops.check_mng_mode(hw) ||
1320 hw->phy.ops.check_reset_block(hw)))
1321 e1000_power_down_phy_copper(hw);
1322
1323 return;
1324}
1325
1326/**
1306 * e1000_clear_hw_cntrs_80003es2lan - Clear device specific hardware counters 1327 * e1000_clear_hw_cntrs_80003es2lan - Clear device specific hardware counters
1307 * @hw: pointer to the HW structure 1328 * @hw: pointer to the HW structure
1308 * 1329 *
diff --git a/drivers/net/e1000e/hw.h b/drivers/net/e1000e/hw.h
index 6c3d55fc7753..e0addf3eea8a 100644
--- a/drivers/net/e1000e/hw.h
+++ b/drivers/net/e1000e/hw.h
@@ -774,6 +774,8 @@ struct e1000_phy_operations {
774 s32 (*set_d3_lplu_state)(struct e1000_hw *, bool); 774 s32 (*set_d3_lplu_state)(struct e1000_hw *, bool);
775 s32 (*write_reg)(struct e1000_hw *, u32, u16); 775 s32 (*write_reg)(struct e1000_hw *, u32, u16);
776 s32 (*write_reg_locked)(struct e1000_hw *, u32, u16); 776 s32 (*write_reg_locked)(struct e1000_hw *, u32, u16);
777 void (*power_up)(struct e1000_hw *);
778 void (*power_down)(struct e1000_hw *);
777}; 779};
778 780
779/* Function pointers for the NVM. */ 781/* Function pointers for the NVM. */
diff --git a/drivers/net/e1000e/ich8lan.c b/drivers/net/e1000e/ich8lan.c
index 7530fc5d81c3..9c3895598923 100644
--- a/drivers/net/e1000e/ich8lan.c
+++ b/drivers/net/e1000e/ich8lan.c
@@ -217,6 +217,7 @@ static s32 e1000_cleanup_led_pchlan(struct e1000_hw *hw);
217static s32 e1000_led_on_pchlan(struct e1000_hw *hw); 217static s32 e1000_led_on_pchlan(struct e1000_hw *hw);
218static s32 e1000_led_off_pchlan(struct e1000_hw *hw); 218static s32 e1000_led_off_pchlan(struct e1000_hw *hw);
219static s32 e1000_set_lplu_state_pchlan(struct e1000_hw *hw, bool active); 219static s32 e1000_set_lplu_state_pchlan(struct e1000_hw *hw, bool active);
220static void e1000_power_down_phy_copper_ich8lan(struct e1000_hw *hw);
220static void e1000_lan_init_done_ich8lan(struct e1000_hw *hw); 221static void e1000_lan_init_done_ich8lan(struct e1000_hw *hw);
221static s32 e1000_k1_gig_workaround_hv(struct e1000_hw *hw, bool link); 222static s32 e1000_k1_gig_workaround_hv(struct e1000_hw *hw, bool link);
222 223
@@ -266,6 +267,8 @@ static s32 e1000_init_phy_params_pchlan(struct e1000_hw *hw)
266 phy->ops.set_d3_lplu_state = e1000_set_lplu_state_pchlan; 267 phy->ops.set_d3_lplu_state = e1000_set_lplu_state_pchlan;
267 phy->ops.write_reg = e1000_write_phy_reg_hv; 268 phy->ops.write_reg = e1000_write_phy_reg_hv;
268 phy->ops.write_reg_locked = e1000_write_phy_reg_hv_locked; 269 phy->ops.write_reg_locked = e1000_write_phy_reg_hv_locked;
270 phy->ops.power_up = e1000_power_up_phy_copper;
271 phy->ops.power_down = e1000_power_down_phy_copper_ich8lan;
269 phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT; 272 phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT;
270 273
271 phy->id = e1000_phy_unknown; 274 phy->id = e1000_phy_unknown;
@@ -299,6 +302,9 @@ static s32 e1000_init_phy_params_ich8lan(struct e1000_hw *hw)
299 phy->addr = 1; 302 phy->addr = 1;
300 phy->reset_delay_us = 100; 303 phy->reset_delay_us = 100;
301 304
305 phy->ops.power_up = e1000_power_up_phy_copper;
306 phy->ops.power_down = e1000_power_down_phy_copper_ich8lan;
307
302 /* 308 /*
303 * We may need to do this twice - once for IGP and if that fails, 309 * We may need to do this twice - once for IGP and if that fails,
304 * we'll set BM func pointers and try again 310 * we'll set BM func pointers and try again
@@ -3392,6 +3398,23 @@ static s32 e1000_get_cfg_done_ich8lan(struct e1000_hw *hw)
3392} 3398}
3393 3399
3394/** 3400/**
3401 * e1000_power_down_phy_copper_ich8lan - Remove link during PHY power down
3402 * @hw: pointer to the HW structure
3403 *
3404 * In the case of a PHY power down to save power, or to turn off link during a
3405 * driver unload, or wake on lan is not enabled, remove the link.
3406 **/
3407static void e1000_power_down_phy_copper_ich8lan(struct e1000_hw *hw)
3408{
3409 /* If the management interface is not enabled, then power down */
3410 if (!(hw->mac.ops.check_mng_mode(hw) ||
3411 hw->phy.ops.check_reset_block(hw)))
3412 e1000_power_down_phy_copper(hw);
3413
3414 return;
3415}
3416
3417/**
3395 * e1000_clear_hw_cntrs_ich8lan - Clear statistical counters 3418 * e1000_clear_hw_cntrs_ich8lan - Clear statistical counters
3396 * @hw: pointer to the HW structure 3419 * @hw: pointer to the HW structure
3397 * 3420 *
diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c
index 2381cb76f17c..ab4db5266f14 100644
--- a/drivers/net/e1000e/netdev.c
+++ b/drivers/net/e1000e/netdev.c
@@ -2641,18 +2641,8 @@ static void e1000_configure(struct e1000_adapter *adapter)
2641 **/ 2641 **/
2642void e1000e_power_up_phy(struct e1000_adapter *adapter) 2642void e1000e_power_up_phy(struct e1000_adapter *adapter)
2643{ 2643{
2644 u16 mii_reg = 0; 2644 if (adapter->hw.phy.ops.power_up)
2645 2645 adapter->hw.phy.ops.power_up(&adapter->hw);
2646 /* Just clear the power down bit to wake the phy back up */
2647 if (adapter->hw.phy.media_type == e1000_media_type_copper) {
2648 /*
2649 * According to the manual, the phy will retain its
2650 * settings across a power-down/up cycle
2651 */
2652 e1e_rphy(&adapter->hw, PHY_CONTROL, &mii_reg);
2653 mii_reg &= ~MII_CR_POWER_DOWN;
2654 e1e_wphy(&adapter->hw, PHY_CONTROL, mii_reg);
2655 }
2656 2646
2657 adapter->hw.mac.ops.setup_link(&adapter->hw); 2647 adapter->hw.mac.ops.setup_link(&adapter->hw);
2658} 2648}
@@ -2660,35 +2650,17 @@ void e1000e_power_up_phy(struct e1000_adapter *adapter)
2660/** 2650/**
2661 * e1000_power_down_phy - Power down the PHY 2651 * e1000_power_down_phy - Power down the PHY
2662 * 2652 *
2663 * Power down the PHY so no link is implied when interface is down 2653 * Power down the PHY so no link is implied when interface is down.
2664 * The PHY cannot be powered down is management or WoL is active 2654 * The PHY cannot be powered down if management or WoL is active.
2665 */ 2655 */
2666static void e1000_power_down_phy(struct e1000_adapter *adapter) 2656static void e1000_power_down_phy(struct e1000_adapter *adapter)
2667{ 2657{
2668 struct e1000_hw *hw = &adapter->hw;
2669 u16 mii_reg;
2670
2671 /* WoL is enabled */ 2658 /* WoL is enabled */
2672 if (adapter->wol) 2659 if (adapter->wol)
2673 return; 2660 return;
2674 2661
2675 /* non-copper PHY? */ 2662 if (adapter->hw.phy.ops.power_down)
2676 if (adapter->hw.phy.media_type != e1000_media_type_copper) 2663 adapter->hw.phy.ops.power_down(&adapter->hw);
2677 return;
2678
2679 /* reset is blocked because of a SoL/IDER session */
2680 if (e1000e_check_mng_mode(hw) || e1000_check_reset_block(hw))
2681 return;
2682
2683 /* manageability (AMT) is enabled */
2684 if (er32(MANC) & E1000_MANC_SMBUS_EN)
2685 return;
2686
2687 /* power down the PHY */
2688 e1e_rphy(hw, PHY_CONTROL, &mii_reg);
2689 mii_reg |= MII_CR_POWER_DOWN;
2690 e1e_wphy(hw, PHY_CONTROL, mii_reg);
2691 mdelay(1);
2692} 2664}
2693 2665
2694/** 2666/**
@@ -5294,17 +5266,17 @@ static void __devexit e1000_remove(struct pci_dev *pdev)
5294 cancel_work_sync(&adapter->print_hang_task); 5266 cancel_work_sync(&adapter->print_hang_task);
5295 flush_scheduled_work(); 5267 flush_scheduled_work();
5296 5268
5269 if (!(netdev->flags & IFF_UP))
5270 e1000_power_down_phy(adapter);
5271
5272 unregister_netdev(netdev);
5273
5297 /* 5274 /*
5298 * Release control of h/w to f/w. If f/w is AMT enabled, this 5275 * Release control of h/w to f/w. If f/w is AMT enabled, this
5299 * would have already happened in close and is redundant. 5276 * would have already happened in close and is redundant.
5300 */ 5277 */
5301 e1000_release_hw_control(adapter); 5278 e1000_release_hw_control(adapter);
5302 5279
5303 unregister_netdev(netdev);
5304
5305 if (!e1000_check_reset_block(&adapter->hw))
5306 e1000_phy_hw_reset(&adapter->hw);
5307
5308 e1000e_reset_interrupt_capability(adapter); 5280 e1000e_reset_interrupt_capability(adapter);
5309 kfree(adapter->tx_ring); 5281 kfree(adapter->tx_ring);
5310 kfree(adapter->rx_ring); 5282 kfree(adapter->rx_ring);
diff --git a/drivers/net/e1000e/phy.c b/drivers/net/e1000e/phy.c
index 9ce499734dca..140b23b320fd 100644
--- a/drivers/net/e1000e/phy.c
+++ b/drivers/net/e1000e/phy.c
@@ -2534,6 +2534,43 @@ out:
2534} 2534}
2535 2535
2536/** 2536/**
2537 * e1000_power_up_phy_copper - Restore copper link in case of PHY power down
2538 * @hw: pointer to the HW structure
2539 *
2540 * In the case of a PHY power down to save power, or to turn off link during a
2541 * driver unload, or wake on lan is not enabled, restore the link to previous
2542 * settings.
2543 **/
2544void e1000_power_up_phy_copper(struct e1000_hw *hw)
2545{
2546 u16 mii_reg = 0;
2547
2548 /* The PHY will retain its settings across a power down/up cycle */
2549 e1e_rphy(hw, PHY_CONTROL, &mii_reg);
2550 mii_reg &= ~MII_CR_POWER_DOWN;
2551 e1e_wphy(hw, PHY_CONTROL, mii_reg);
2552}
2553
2554/**
2555 * e1000_power_down_phy_copper - Restore copper link in case of PHY power down
2556 * @hw: pointer to the HW structure
2557 *
2558 * In the case of a PHY power down to save power, or to turn off link during a
2559 * driver unload, or wake on lan is not enabled, restore the link to previous
2560 * settings.
2561 **/
2562void e1000_power_down_phy_copper(struct e1000_hw *hw)
2563{
2564 u16 mii_reg = 0;
2565
2566 /* The PHY will retain its settings across a power down/up cycle */
2567 e1e_rphy(hw, PHY_CONTROL, &mii_reg);
2568 mii_reg |= MII_CR_POWER_DOWN;
2569 e1e_wphy(hw, PHY_CONTROL, mii_reg);
2570 msleep(1);
2571}
2572
2573/**
2537 * e1000e_commit_phy - Soft PHY reset 2574 * e1000e_commit_phy - Soft PHY reset
2538 * @hw: pointer to the HW structure 2575 * @hw: pointer to the HW structure
2539 * 2576 *