Commit ab507c9a authored by Denys Vlasenko's avatar Denys Vlasenko Committed by Jeff Kirsher

e1000e: e1000e_cyclecounter_read(): do overflow check only if needed

SYSTIMH:SYSTIML registers are incremented by 24-bit value TIMINCA[23..0]

er32(SYSTIML) are probably moderately expensive (they are pci bus reads).
Can we avoid one of them? Yes, we can.

If the SYSTIML value we see is smaller than 0xff000000, the overflow
into SYSTIMH would require at least two increments.

We do two reads, er32(SYSTIML) and er32(SYSTIMH), in this order.

Even if one increment happens between them, the overflow into SYSTIMH
is impossible, and we can avoid doing another er32(SYSTIML) read
and overflow check.
Signed-off-by: default avatarDenys Vlasenko <dvlasenk@redhat.com>
Tested-by: default avatarAaron Brown <aaron.f.brown@intel.com>
Signed-off-by: default avatarJeff Kirsher <jeffrey.t.kirsher@intel.com>
parent a07fd74d
...@@ -4275,7 +4275,7 @@ static cycle_t e1000e_cyclecounter_read(const struct cyclecounter *cc) ...@@ -4275,7 +4275,7 @@ static cycle_t e1000e_cyclecounter_read(const struct cyclecounter *cc)
struct e1000_adapter *adapter = container_of(cc, struct e1000_adapter, struct e1000_adapter *adapter = container_of(cc, struct e1000_adapter,
cc); cc);
struct e1000_hw *hw = &adapter->hw; struct e1000_hw *hw = &adapter->hw;
u32 systimel_1, systimel_2, systimeh; u32 systimel, systimeh;
cycle_t systim, systim_next; cycle_t systim, systim_next;
/* SYSTIMH latching upon SYSTIML read does not work well. /* SYSTIMH latching upon SYSTIML read does not work well.
* This means that if SYSTIML overflows after we read it but before * This means that if SYSTIML overflows after we read it but before
...@@ -4283,21 +4283,21 @@ static cycle_t e1000e_cyclecounter_read(const struct cyclecounter *cc) ...@@ -4283,21 +4283,21 @@ static cycle_t e1000e_cyclecounter_read(const struct cyclecounter *cc)
* will experience a huge non linear increment in the systime value * will experience a huge non linear increment in the systime value
* to fix that we test for overflow and if true, we re-read systime. * to fix that we test for overflow and if true, we re-read systime.
*/ */
systimel_1 = er32(SYSTIML); systimel = er32(SYSTIML);
systimeh = er32(SYSTIMH); systimeh = er32(SYSTIMH);
systimel_2 = er32(SYSTIML); /* Is systimel is so large that overflow is possible? */
/* Check for overflow. If there was no overflow, use the values */ if (systimel >= (u32)0xffffffff - E1000_TIMINCA_INCVALUE_MASK) {
if (systimel_1 <= systimel_2) { u32 systimel_2 = er32(SYSTIML);
systim = (cycle_t)systimel_1; if (systimel > systimel_2) {
systim |= (cycle_t)systimeh << 32; /* There was an overflow, read again SYSTIMH, and use
} else { * systimel_2
/* There was an overflow, read again SYSTIMH, and use */
* systimel_2 systimeh = er32(SYSTIMH);
*/ systimel = systimel_2;
systimeh = er32(SYSTIMH); }
systim = (cycle_t)systimel_2;
systim |= (cycle_t)systimeh << 32;
} }
systim = (cycle_t)systimel;
systim |= (cycle_t)systimeh << 32;
if ((hw->mac.type == e1000_82574) || (hw->mac.type == e1000_82583)) { if ((hw->mac.type == e1000_82574) || (hw->mac.type == e1000_82583)) {
u64 time_delta, rem, temp; u64 time_delta, rem, temp;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment