aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthew Vick <matthew.vick@intel.com>2013-02-20 22:32:52 -0500
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>2013-04-18 19:40:28 -0400
commit87371b9de5becc32af2f9be84008b8a8a424c58a (patch)
tree58128b8de909c4fab1d389e70ed81464a4e20822
parentb980ac18c95f3251038da7a3826370aff05a7434 (diff)
igb: Enable EEE LP advertisement
On EEE-capable devices, query the PHY to determine what the link partner is advertising. Signed-off-by: Matthew Vick <matthew.vick@intel.com> Tested-by: Aaron Brown <aaron.f.brown@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
-rw-r--r--drivers/net/ethernet/intel/igb/e1000_82575.c35
-rw-r--r--drivers/net/ethernet/intel/igb/e1000_82575.h1
-rw-r--r--drivers/net/ethernet/intel/igb/e1000_defines.h4
-rw-r--r--drivers/net/ethernet/intel/igb/e1000_i210.c65
-rw-r--r--drivers/net/ethernet/intel/igb/e1000_i210.h4
-rw-r--r--drivers/net/ethernet/intel/igb/e1000_regs.h4
-rw-r--r--drivers/net/ethernet/intel/igb/igb_ethtool.c30
7 files changed, 142 insertions, 1 deletions
diff --git a/drivers/net/ethernet/intel/igb/e1000_82575.c b/drivers/net/ethernet/intel/igb/e1000_82575.c
index 9d83058f2075..8ff938d94912 100644
--- a/drivers/net/ethernet/intel/igb/e1000_82575.c
+++ b/drivers/net/ethernet/intel/igb/e1000_82575.c
@@ -2285,6 +2285,41 @@ out:
2285} 2285}
2286 2286
2287/** 2287/**
2288 * __igb_access_emi_reg - Read/write EMI register
2289 * @hw: pointer to the HW structure
2290 * @addr: EMI address to program
2291 * @data: pointer to value to read/write from/to the EMI address
2292 * @read: boolean flag to indicate read or write
2293 **/
2294static s32 __igb_access_emi_reg(struct e1000_hw *hw, u16 address,
2295 u16 *data, bool read)
2296{
2297 s32 ret_val = E1000_SUCCESS;
2298
2299 ret_val = hw->phy.ops.write_reg(hw, E1000_EMIADD, address);
2300 if (ret_val)
2301 return ret_val;
2302
2303 if (read)
2304 ret_val = hw->phy.ops.read_reg(hw, E1000_EMIDATA, data);
2305 else
2306 ret_val = hw->phy.ops.write_reg(hw, E1000_EMIDATA, *data);
2307
2308 return ret_val;
2309}
2310
2311/**
2312 * igb_read_emi_reg - Read Extended Management Interface register
2313 * @hw: pointer to the HW structure
2314 * @addr: EMI address to program
2315 * @data: value to be read from the EMI address
2316 **/
2317s32 igb_read_emi_reg(struct e1000_hw *hw, u16 addr, u16 *data)
2318{
2319 return __igb_access_emi_reg(hw, addr, data, true);
2320}
2321
2322/**
2288 * igb_set_eee_i350 - Enable/disable EEE support 2323 * igb_set_eee_i350 - Enable/disable EEE support
2289 * @hw: pointer to the HW structure 2324 * @hw: pointer to the HW structure
2290 * 2325 *
diff --git a/drivers/net/ethernet/intel/igb/e1000_82575.h b/drivers/net/ethernet/intel/igb/e1000_82575.h
index 73ab41f0e032..0d318ac14818 100644
--- a/drivers/net/ethernet/intel/igb/e1000_82575.h
+++ b/drivers/net/ethernet/intel/igb/e1000_82575.h
@@ -263,6 +263,7 @@ void igb_vmdq_set_anti_spoofing_pf(struct e1000_hw *, bool, int);
263void igb_vmdq_set_loopback_pf(struct e1000_hw *, bool); 263void igb_vmdq_set_loopback_pf(struct e1000_hw *, bool);
264void igb_vmdq_set_replication_pf(struct e1000_hw *, bool); 264void igb_vmdq_set_replication_pf(struct e1000_hw *, bool);
265u16 igb_rxpbs_adjust_82580(u32 data); 265u16 igb_rxpbs_adjust_82580(u32 data);
266s32 igb_read_emi_reg(struct e1000_hw *, u16 addr, u16 *data);
266s32 igb_set_eee_i350(struct e1000_hw *); 267s32 igb_set_eee_i350(struct e1000_hw *);
267s32 igb_init_thermal_sensor_thresh_generic(struct e1000_hw *); 268s32 igb_init_thermal_sensor_thresh_generic(struct e1000_hw *);
268s32 igb_get_thermal_sensor_data_generic(struct e1000_hw *hw); 269s32 igb_get_thermal_sensor_data_generic(struct e1000_hw *hw);
diff --git a/drivers/net/ethernet/intel/igb/e1000_defines.h b/drivers/net/ethernet/intel/igb/e1000_defines.h
index 66a1df974284..f3d87d7b9fdc 100644
--- a/drivers/net/ethernet/intel/igb/e1000_defines.h
+++ b/drivers/net/ethernet/intel/igb/e1000_defines.h
@@ -885,6 +885,10 @@
885#define E1000_EEER_LPI_FC 0x00040000 /* EEE Enable on FC */ 885#define E1000_EEER_LPI_FC 0x00040000 /* EEE Enable on FC */
886#define E1000_EEE_SU_LPI_CLK_STP 0X00800000 /* EEE LPI Clock Stop */ 886#define E1000_EEE_SU_LPI_CLK_STP 0X00800000 /* EEE LPI Clock Stop */
887#define E1000_EEER_EEE_NEG 0x20000000 /* EEE capability nego */ 887#define E1000_EEER_EEE_NEG 0x20000000 /* EEE capability nego */
888#define E1000_EEE_LP_ADV_ADDR_I350 0x040F /* EEE LP Advertisement */
889#define E1000_EEE_LP_ADV_DEV_I210 7 /* EEE LP Adv Device */
890#define E1000_EEE_LP_ADV_ADDR_I210 61 /* EEE LP Adv Register */
891#define E1000_MMDAC_FUNC_DATA 0x4000 /* Data, no post increment */
888 892
889/* SerDes Control */ 893/* SerDes Control */
890#define E1000_GEN_CTL_READY 0x80000000 894#define E1000_GEN_CTL_READY 0x80000000
diff --git a/drivers/net/ethernet/intel/igb/e1000_i210.c b/drivers/net/ethernet/intel/igb/e1000_i210.c
index 7df442a3cdfd..9764cd3610e5 100644
--- a/drivers/net/ethernet/intel/igb/e1000_i210.c
+++ b/drivers/net/ethernet/intel/igb/e1000_i210.c
@@ -708,3 +708,68 @@ s32 igb_valid_led_default_i210(struct e1000_hw *hw, u16 *data)
708out: 708out:
709 return ret_val; 709 return ret_val;
710} 710}
711
712/**
713 * __igb_access_xmdio_reg - Read/write XMDIO register
714 * @hw: pointer to the HW structure
715 * @address: XMDIO address to program
716 * @dev_addr: device address to program
717 * @data: pointer to value to read/write from/to the XMDIO address
718 * @read: boolean flag to indicate read or write
719 **/
720static s32 __igb_access_xmdio_reg(struct e1000_hw *hw, u16 address,
721 u8 dev_addr, u16 *data, bool read)
722{
723 s32 ret_val = E1000_SUCCESS;
724
725 ret_val = hw->phy.ops.write_reg(hw, E1000_MMDAC, dev_addr);
726 if (ret_val)
727 return ret_val;
728
729 ret_val = hw->phy.ops.write_reg(hw, E1000_MMDAAD, address);
730 if (ret_val)
731 return ret_val;
732
733 ret_val = hw->phy.ops.write_reg(hw, E1000_MMDAC, E1000_MMDAC_FUNC_DATA |
734 dev_addr);
735 if (ret_val)
736 return ret_val;
737
738 if (read)
739 ret_val = hw->phy.ops.read_reg(hw, E1000_MMDAAD, data);
740 else
741 ret_val = hw->phy.ops.write_reg(hw, E1000_MMDAAD, *data);
742 if (ret_val)
743 return ret_val;
744
745 /* Recalibrate the device back to 0 */
746 ret_val = hw->phy.ops.write_reg(hw, E1000_MMDAC, 0);
747 if (ret_val)
748 return ret_val;
749
750 return ret_val;
751}
752
753/**
754 * igb_read_xmdio_reg - Read XMDIO register
755 * @hw: pointer to the HW structure
756 * @addr: XMDIO address to program
757 * @dev_addr: device address to program
758 * @data: value to be read from the EMI address
759 **/
760s32 igb_read_xmdio_reg(struct e1000_hw *hw, u16 addr, u8 dev_addr, u16 *data)
761{
762 return __igb_access_xmdio_reg(hw, addr, dev_addr, data, true);
763}
764
765/**
766 * igb_write_xmdio_reg - Write XMDIO register
767 * @hw: pointer to the HW structure
768 * @addr: XMDIO address to program
769 * @dev_addr: device address to program
770 * @data: value to be written to the XMDIO address
771 **/
772s32 igb_write_xmdio_reg(struct e1000_hw *hw, u16 addr, u8 dev_addr, u16 data)
773{
774 return __igb_access_xmdio_reg(hw, addr, dev_addr, &data, false);
775}
diff --git a/drivers/net/ethernet/intel/igb/e1000_i210.h b/drivers/net/ethernet/intel/igb/e1000_i210.h
index e4e1a73b7c75..bfc08e05c907 100644
--- a/drivers/net/ethernet/intel/igb/e1000_i210.h
+++ b/drivers/net/ethernet/intel/igb/e1000_i210.h
@@ -45,6 +45,10 @@ extern s32 igb_read_nvm_i211(struct e1000_hw *hw, u16 offset, u16 words,
45 u16 *data); 45 u16 *data);
46extern s32 igb_read_invm_version(struct e1000_hw *hw, 46extern s32 igb_read_invm_version(struct e1000_hw *hw,
47 struct e1000_fw_version *invm_ver); 47 struct e1000_fw_version *invm_ver);
48extern s32 igb_read_xmdio_reg(struct e1000_hw *hw, u16 addr, u8 dev_addr,
49 u16 *data);
50extern s32 igb_write_xmdio_reg(struct e1000_hw *hw, u16 addr, u8 dev_addr,
51 u16 data);
48 52
49#define E1000_STM_OPCODE 0xDB00 53#define E1000_STM_OPCODE 0xDB00
50#define E1000_EEPROM_FLASH_SIZE_WORD 0x11 54#define E1000_EEPROM_FLASH_SIZE_WORD 0x11
diff --git a/drivers/net/ethernet/intel/igb/e1000_regs.h b/drivers/net/ethernet/intel/igb/e1000_regs.h
index 971b6389358f..bdfc0403c6fc 100644
--- a/drivers/net/ethernet/intel/igb/e1000_regs.h
+++ b/drivers/net/ethernet/intel/igb/e1000_regs.h
@@ -365,6 +365,10 @@
365#define E1000_IPCNFG 0x0E38 /* Internal PHY Configuration */ 365#define E1000_IPCNFG 0x0E38 /* Internal PHY Configuration */
366#define E1000_EEER 0x0E30 /* Energy Efficient Ethernet */ 366#define E1000_EEER 0x0E30 /* Energy Efficient Ethernet */
367#define E1000_EEE_SU 0X0E34 /* EEE Setup */ 367#define E1000_EEE_SU 0X0E34 /* EEE Setup */
368#define E1000_EMIADD 0x10 /* Extended Memory Indirect Address */
369#define E1000_EMIDATA 0x11 /* Extended Memory Indirect Data */
370#define E1000_MMDAC 13 /* MMD Access Control */
371#define E1000_MMDAAD 14 /* MMD Access Address/Data */
368 372
369/* Thermal Sensor Register */ 373/* Thermal Sensor Register */
370#define E1000_THSTAT 0x08110 /* Thermal Sensor Status */ 374#define E1000_THSTAT 0x08110 /* Thermal Sensor Status */
diff --git a/drivers/net/ethernet/intel/igb/igb_ethtool.c b/drivers/net/ethernet/intel/igb/igb_ethtool.c
index 08195bd0a23a..8412f9746c78 100644
--- a/drivers/net/ethernet/intel/igb/igb_ethtool.c
+++ b/drivers/net/ethernet/intel/igb/igb_ethtool.c
@@ -38,6 +38,7 @@
38#include <linux/slab.h> 38#include <linux/slab.h>
39#include <linux/pm_runtime.h> 39#include <linux/pm_runtime.h>
40#include <linux/highmem.h> 40#include <linux/highmem.h>
41#include <linux/mdio.h>
41 42
42#include "igb.h" 43#include "igb.h"
43 44
@@ -2533,7 +2534,8 @@ static int igb_get_eee(struct net_device *netdev, struct ethtool_eee *edata)
2533{ 2534{
2534 struct igb_adapter *adapter = netdev_priv(netdev); 2535 struct igb_adapter *adapter = netdev_priv(netdev);
2535 struct e1000_hw *hw = &adapter->hw; 2536 struct e1000_hw *hw = &adapter->hw;
2536 u32 ipcnfg, eeer; 2537 u32 ipcnfg, eeer, ret_val;
2538 u16 phy_data;
2537 2539
2538 if ((hw->mac.type < e1000_i350) || 2540 if ((hw->mac.type < e1000_i350) ||
2539 (hw->phy.media_type != e1000_media_type_copper)) 2541 (hw->phy.media_type != e1000_media_type_copper))
@@ -2552,6 +2554,32 @@ static int igb_get_eee(struct net_device *netdev, struct ethtool_eee *edata)
2552 if (ipcnfg & E1000_IPCNFG_EEE_100M_AN) 2554 if (ipcnfg & E1000_IPCNFG_EEE_100M_AN)
2553 edata->advertised |= ADVERTISED_100baseT_Full; 2555 edata->advertised |= ADVERTISED_100baseT_Full;
2554 2556
2557 /* EEE Link Partner Advertised */
2558 switch (hw->mac.type) {
2559 case e1000_i350:
2560 ret_val = igb_read_emi_reg(hw, E1000_EEE_LP_ADV_ADDR_I350,
2561 &phy_data);
2562 if (ret_val)
2563 return -ENODATA;
2564
2565 edata->lp_advertised = mmd_eee_adv_to_ethtool_adv_t(phy_data);
2566
2567 break;
2568 case e1000_i210:
2569 case e1000_i211:
2570 ret_val = igb_read_xmdio_reg(hw, E1000_EEE_LP_ADV_ADDR_I210,
2571 E1000_EEE_LP_ADV_DEV_I210,
2572 &phy_data);
2573 if (ret_val)
2574 return -ENODATA;
2575
2576 edata->lp_advertised = mmd_eee_adv_to_ethtool_adv_t(phy_data);
2577
2578 break;
2579 default:
2580 break;
2581 }
2582
2555 if (eeer & E1000_EEER_EEE_NEG) 2583 if (eeer & E1000_EEER_EEE_NEG)
2556 edata->eee_active = true; 2584 edata->eee_active = true;
2557 2585