aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTodd Fujinaka <todd.fujinaka@intel.com>2014-05-03 02:41:37 -0400
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>2014-05-27 05:09:57 -0400
commit5e7ff970041321a26f2dc3aa41ba79e787fcf8f9 (patch)
tree7e72236781a130581d00b17c738926975b79f2a3
parentb3e5bf1ff32cbc58c56675498565020460c683cd (diff)
e1000e: 82574/82583 TimeSync errata for SYSTIM read
Due to a synchronization error, the value read from SYSTIML/SYSTIMH might be incorrect. Signed-off-by: Todd Fujinaka <todd.fujinaka@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/e1000e/e1000.h2
-rw-r--r--drivers/net/ethernet/intel/e1000e/netdev.c27
2 files changed, 28 insertions, 1 deletions
diff --git a/drivers/net/ethernet/intel/e1000e/e1000.h b/drivers/net/ethernet/intel/e1000e/e1000.h
index e27e60910949..63bde99a4ab4 100644
--- a/drivers/net/ethernet/intel/e1000e/e1000.h
+++ b/drivers/net/ethernet/intel/e1000e/e1000.h
@@ -391,6 +391,8 @@ s32 e1000e_get_base_timinca(struct e1000_adapter *adapter, u32 *timinca);
391 * 25MHz 46-bit 2^46 / 10^9 / 3600 = 19.55 hours 391 * 25MHz 46-bit 2^46 / 10^9 / 3600 = 19.55 hours
392 */ 392 */
393#define E1000_SYSTIM_OVERFLOW_PERIOD (HZ * 60 * 60 * 4) 393#define E1000_SYSTIM_OVERFLOW_PERIOD (HZ * 60 * 60 * 4)
394#define E1000_MAX_82574_SYSTIM_REREADS 50
395#define E1000_82574_SYSTIM_EPSILON (1ULL << 35ULL)
394 396
395/* hardware capability, feature, and workaround flags */ 397/* hardware capability, feature, and workaround flags */
396#define FLAG_HAS_AMT (1 << 0) 398#define FLAG_HAS_AMT (1 << 0)
diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c
index 6084e6ba45c2..95cf482cf0af 100644
--- a/drivers/net/ethernet/intel/e1000e/netdev.c
+++ b/drivers/net/ethernet/intel/e1000e/netdev.c
@@ -4099,12 +4099,37 @@ static cycle_t e1000e_cyclecounter_read(const struct cyclecounter *cc)
4099 struct e1000_adapter *adapter = container_of(cc, struct e1000_adapter, 4099 struct e1000_adapter *adapter = container_of(cc, struct e1000_adapter,
4100 cc); 4100 cc);
4101 struct e1000_hw *hw = &adapter->hw; 4101 struct e1000_hw *hw = &adapter->hw;
4102 cycle_t systim; 4102 cycle_t systim, systim_next;
4103 4103
4104 /* latch SYSTIMH on read of SYSTIML */ 4104 /* latch SYSTIMH on read of SYSTIML */
4105 systim = (cycle_t)er32(SYSTIML); 4105 systim = (cycle_t)er32(SYSTIML);
4106 systim |= (cycle_t)er32(SYSTIMH) << 32; 4106 systim |= (cycle_t)er32(SYSTIMH) << 32;
4107 4107
4108 if ((hw->mac.type == e1000_82574) || (hw->mac.type == e1000_82583)) {
4109 u64 incvalue, time_delta, rem, temp;
4110 int i;
4111
4112 /* errata for 82574/82583 possible bad bits read from SYSTIMH/L
4113 * check to see that the time is incrementing at a reasonable
4114 * rate and is a multiple of incvalue
4115 */
4116 incvalue = er32(TIMINCA) & E1000_TIMINCA_INCVALUE_MASK;
4117 for (i = 0; i < E1000_MAX_82574_SYSTIM_REREADS; i++) {
4118 /* latch SYSTIMH on read of SYSTIML */
4119 systim_next = (cycle_t)er32(SYSTIML);
4120 systim_next |= (cycle_t)er32(SYSTIMH) << 32;
4121
4122 time_delta = systim_next - systim;
4123 temp = time_delta;
4124 rem = do_div(temp, incvalue);
4125
4126 systim = systim_next;
4127
4128 if ((time_delta < E1000_82574_SYSTIM_EPSILON) &&
4129 (rem == 0))
4130 break;
4131 }
4132 }
4108 return systim; 4133 return systim;
4109} 4134}
4110 4135