Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5e7ff970 authored by Todd Fujinaka's avatar Todd Fujinaka Committed by Jeff Kirsher
Browse files

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: default avatarTodd Fujinaka <todd.fujinaka@intel.com>
Tested-by: default avatarAaron Brown <aaron.f.brown@intel.com>
Signed-off-by: default avatarJeff Kirsher <jeffrey.t.kirsher@intel.com>
parent b3e5bf1f
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -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)
+26 −1
Original line number Diff line number Diff line
@@ -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;
}