Skip to content

Commit

Permalink
e1000e: 82574/82583 TimeSync errata for SYSTIM read
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Todd Fujinaka authored and Jeff Kirsher committed May 27, 2014
1 parent b3e5bf1 commit 5e7ff97
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 1 deletion.
2 changes: 2 additions & 0 deletions drivers/net/ethernet/intel/e1000e/e1000.h
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,8 @@ s32 e1000e_get_base_timinca(struct e1000_adapter *adapter, u32 *timinca);
* 25MHz 46-bit 2^46 / 10^9 / 3600 = 19.55 hours
*/
#define E1000_SYSTIM_OVERFLOW_PERIOD (HZ * 60 * 60 * 4)
#define E1000_MAX_82574_SYSTIM_REREADS 50
#define E1000_82574_SYSTIM_EPSILON (1ULL << 35ULL)

/* hardware capability, feature, and workaround flags */
#define FLAG_HAS_AMT (1 << 0)
Expand Down
27 changes: 26 additions & 1 deletion drivers/net/ethernet/intel/e1000e/netdev.c
Original file line number Diff line number Diff line change
Expand Up @@ -4099,12 +4099,37 @@ static cycle_t e1000e_cyclecounter_read(const struct cyclecounter *cc)
struct e1000_adapter *adapter = container_of(cc, struct e1000_adapter,
cc);
struct e1000_hw *hw = &adapter->hw;
cycle_t systim;
cycle_t systim, systim_next;

/* latch SYSTIMH on read of SYSTIML */
systim = (cycle_t)er32(SYSTIML);
systim |= (cycle_t)er32(SYSTIMH) << 32;

if ((hw->mac.type == e1000_82574) || (hw->mac.type == e1000_82583)) {
u64 incvalue, time_delta, rem, temp;
int i;

/* errata for 82574/82583 possible bad bits read from SYSTIMH/L
* check to see that the time is incrementing at a reasonable
* rate and is a multiple of incvalue
*/
incvalue = er32(TIMINCA) & E1000_TIMINCA_INCVALUE_MASK;
for (i = 0; i < E1000_MAX_82574_SYSTIM_REREADS; i++) {
/* latch SYSTIMH on read of SYSTIML */
systim_next = (cycle_t)er32(SYSTIML);
systim_next |= (cycle_t)er32(SYSTIMH) << 32;

time_delta = systim_next - systim;
temp = time_delta;
rem = do_div(temp, incvalue);

systim = systim_next;

if ((time_delta < E1000_82574_SYSTIM_EPSILON) &&
(rem == 0))
break;
}
}
return systim;
}

Expand Down

0 comments on commit 5e7ff97

Please sign in to comment.