igb: Improve cable length function for I210, etc.
authorJoe Schultz <jschultz@xes-inc.com>
Tue, 3 Nov 2015 18:37:24 +0000 (12:37 -0600)
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>
Tue, 15 Dec 2015 00:04:05 +0000 (16:04 -0800)
Previously, the PHY-specific code to get the cable length for the
I210 internal and related PHYs was reporting the cable length of a
single pair and reporting it as the min, max, and total cable length.
Update it so that all four pairs are checked so the true min, max,
and average cable lengths are reported.

Signed-off-by: Joe Schultz <jschultz@xes-inc.com>
Signed-off-by: Aaron Sierra <asierra@xes-inc.com>
Tested-by: Aaron Brown <aaron.f.brown@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
drivers/net/ethernet/intel/igb/e1000_defines.h
drivers/net/ethernet/intel/igb/e1000_hw.h
drivers/net/ethernet/intel/igb/e1000_phy.c

index a61ee9462dd48583129d839c79a9628d8480d780..c3c598c347a951455d9e2626e023159b81f68136 100644 (file)
 
 /* Intel i347-AT4 Registers */
 
-#define I347AT4_PCDL                   0x10 /* PHY Cable Diagnostics Length */
+#define I347AT4_PCDL0                  0x10 /* Pair 0 PHY Cable Diagnostics Length */
+#define I347AT4_PCDL1                  0x11 /* Pair 1 PHY Cable Diagnostics Length */
+#define I347AT4_PCDL2                  0x12 /* Pair 2 PHY Cable Diagnostics Length */
+#define I347AT4_PCDL3                  0x13 /* Pair 3 PHY Cable Diagnostics Length */
 #define I347AT4_PCDC                   0x15 /* PHY Cable Diagnostics Control */
 #define I347AT4_PAGE_SELECT            0x16
 
index 2003b3756ba2d7321f8735b302f467852ed85fdc..4034207eb5ccb434a9ae4af124b10223f9c71395 100644 (file)
@@ -441,6 +441,7 @@ struct e1000_phy_info {
        u16 cable_length;
        u16 max_cable_length;
        u16 min_cable_length;
+       u16 pair_length[4];
 
        u8 mdix;
 
index 8015f3b8e579319f3a86e1189890f88ab4564088..5b54254aed4f35e4529b7c33df8442ef32d8b0dc 100644 (file)
@@ -1717,6 +1717,9 @@ s32 igb_get_cable_length_m88_gen2(struct e1000_hw *hw)
        struct e1000_phy_info *phy = &hw->phy;
        s32 ret_val;
        u16 phy_data, phy_data2, index, default_page, is_cm;
+       int len_tot = 0;
+       u16 len_min;
+       u16 len_max;
 
        switch (hw->phy.id) {
        case M88E1543_E_PHY_ID:
@@ -1733,11 +1736,6 @@ s32 igb_get_cable_length_m88_gen2(struct e1000_hw *hw)
                if (ret_val)
                        goto out;
 
-               /* Get cable length from PHY Cable Diagnostics Control Reg */
-               ret_val = phy->ops.read_reg(hw, I347AT4_PCDL, &phy_data);
-               if (ret_val)
-                       goto out;
-
                /* Check if the unit of cable length is meters or cm */
                ret_val = phy->ops.read_reg(hw, I347AT4_PCDC, &phy_data2);
                if (ret_val)
@@ -1745,10 +1743,50 @@ s32 igb_get_cable_length_m88_gen2(struct e1000_hw *hw)
 
                is_cm = !(phy_data2 & I347AT4_PCDC_CABLE_LENGTH_UNIT);
 
+               /* Get cable length from Pair 0 length Regs */
+               ret_val = phy->ops.read_reg(hw, I347AT4_PCDL0, &phy_data);
+               if (ret_val)
+                       goto out;
+
+               phy->pair_length[0] = phy_data / (is_cm ? 100 : 1);
+               len_tot = phy->pair_length[0];
+               len_min = phy->pair_length[0];
+               len_max = phy->pair_length[0];
+
+               /* Get cable length from Pair 1 length Regs */
+               ret_val = phy->ops.read_reg(hw, I347AT4_PCDL1, &phy_data);
+               if (ret_val)
+                       goto out;
+
+               phy->pair_length[1] = phy_data / (is_cm ? 100 : 1);
+               len_tot += phy->pair_length[1];
+               len_min = min(len_min, phy->pair_length[1]);
+               len_max = max(len_max, phy->pair_length[1]);
+
+               /* Get cable length from Pair 2 length Regs */
+               ret_val = phy->ops.read_reg(hw, I347AT4_PCDL2, &phy_data);
+               if (ret_val)
+                       goto out;
+
+               phy->pair_length[2] = phy_data / (is_cm ? 100 : 1);
+               len_tot += phy->pair_length[2];
+               len_min = min(len_min, phy->pair_length[2]);
+               len_max = max(len_max, phy->pair_length[2]);
+
+               /* Get cable length from Pair 3 length Regs */
+               ret_val = phy->ops.read_reg(hw, I347AT4_PCDL3, &phy_data);
+               if (ret_val)
+                       goto out;
+
+               phy->pair_length[3] = phy_data / (is_cm ? 100 : 1);
+               len_tot += phy->pair_length[3];
+               len_min = min(len_min, phy->pair_length[3]);
+               len_max = max(len_max, phy->pair_length[3]);
+
                /* Populate the phy structure with cable length in meters */
-               phy->min_cable_length = phy_data / (is_cm ? 100 : 1);
-               phy->max_cable_length = phy_data / (is_cm ? 100 : 1);
-               phy->cable_length = phy_data / (is_cm ? 100 : 1);
+               phy->min_cable_length = len_min;
+               phy->max_cable_length = len_max;
+               phy->cable_length = len_tot / 4;
 
                /* Reset the page selec to its original value */
                ret_val = phy->ops.write_reg(hw, I347AT4_PAGE_SELECT,