Commit 98942d70 authored by Miroslav Lichvar's avatar Miroslav Lichvar Committed by David S. Miller

e1000e: extend PTP gettime function to read system clock

This adds support for the PTP_SYS_OFFSET_EXTENDED ioctl.

Cc: Richard Cochran <richardcochran@gmail.com>
Cc: Jacob Keller <jacob.e.keller@intel.com>
Cc: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Signed-off-by: default avatarMiroslav Lichvar <mlichvar@redhat.com>
Acked-by: default avatarJeff Kirsher <jeffrey.t.kirsher@intel.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 916444df
...@@ -505,6 +505,9 @@ extern const struct e1000_info e1000_es2_info; ...@@ -505,6 +505,9 @@ extern const struct e1000_info e1000_es2_info;
void e1000e_ptp_init(struct e1000_adapter *adapter); void e1000e_ptp_init(struct e1000_adapter *adapter);
void e1000e_ptp_remove(struct e1000_adapter *adapter); void e1000e_ptp_remove(struct e1000_adapter *adapter);
u64 e1000e_read_systim(struct e1000_adapter *adapter,
struct ptp_system_timestamp *sts);
static inline s32 e1000_phy_hw_reset(struct e1000_hw *hw) static inline s32 e1000_phy_hw_reset(struct e1000_hw *hw)
{ {
return hw->phy.ops.reset(hw); return hw->phy.ops.reset(hw);
......
...@@ -4319,13 +4319,16 @@ void e1000e_reinit_locked(struct e1000_adapter *adapter) ...@@ -4319,13 +4319,16 @@ void e1000e_reinit_locked(struct e1000_adapter *adapter)
/** /**
* e1000e_sanitize_systim - sanitize raw cycle counter reads * e1000e_sanitize_systim - sanitize raw cycle counter reads
* @hw: pointer to the HW structure * @hw: pointer to the HW structure
* @systim: time value read, sanitized and returned * @systim: PHC time value read, sanitized and returned
* @sts: structure to hold system time before and after reading SYSTIML,
* may be NULL
* *
* Errata for 82574/82583 possible bad bits read from SYSTIMH/L: * Errata for 82574/82583 possible bad bits read from SYSTIMH/L:
* check to see that the time is incrementing at a reasonable * check to see that the time is incrementing at a reasonable
* rate and is a multiple of incvalue. * rate and is a multiple of incvalue.
**/ **/
static u64 e1000e_sanitize_systim(struct e1000_hw *hw, u64 systim) static u64 e1000e_sanitize_systim(struct e1000_hw *hw, u64 systim,
struct ptp_system_timestamp *sts)
{ {
u64 time_delta, rem, temp; u64 time_delta, rem, temp;
u64 systim_next; u64 systim_next;
...@@ -4335,7 +4338,9 @@ static u64 e1000e_sanitize_systim(struct e1000_hw *hw, u64 systim) ...@@ -4335,7 +4338,9 @@ static u64 e1000e_sanitize_systim(struct e1000_hw *hw, u64 systim)
incvalue = er32(TIMINCA) & E1000_TIMINCA_INCVALUE_MASK; incvalue = er32(TIMINCA) & E1000_TIMINCA_INCVALUE_MASK;
for (i = 0; i < E1000_MAX_82574_SYSTIM_REREADS; i++) { for (i = 0; i < E1000_MAX_82574_SYSTIM_REREADS; i++) {
/* latch SYSTIMH on read of SYSTIML */ /* latch SYSTIMH on read of SYSTIML */
ptp_read_system_prets(sts);
systim_next = (u64)er32(SYSTIML); systim_next = (u64)er32(SYSTIML);
ptp_read_system_postts(sts);
systim_next |= (u64)er32(SYSTIMH) << 32; systim_next |= (u64)er32(SYSTIMH) << 32;
time_delta = systim_next - systim; time_delta = systim_next - systim;
...@@ -4353,15 +4358,16 @@ static u64 e1000e_sanitize_systim(struct e1000_hw *hw, u64 systim) ...@@ -4353,15 +4358,16 @@ static u64 e1000e_sanitize_systim(struct e1000_hw *hw, u64 systim)
} }
/** /**
* e1000e_cyclecounter_read - read raw cycle counter (used by time counter) * e1000e_read_systim - read SYSTIM register
* @cc: cyclecounter structure * @adapter: board private structure
* @sts: structure which will contain system time before and after reading
* SYSTIML, may be NULL
**/ **/
static u64 e1000e_cyclecounter_read(const struct cyclecounter *cc) u64 e1000e_read_systim(struct e1000_adapter *adapter,
struct ptp_system_timestamp *sts)
{ {
struct e1000_adapter *adapter = container_of(cc, struct e1000_adapter,
cc);
struct e1000_hw *hw = &adapter->hw; struct e1000_hw *hw = &adapter->hw;
u32 systimel, systimeh; u32 systimel, systimel_2, systimeh;
u64 systim; u64 systim;
/* 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
...@@ -4369,11 +4375,15 @@ static u64 e1000e_cyclecounter_read(const struct cyclecounter *cc) ...@@ -4369,11 +4375,15 @@ static u64 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.
*/ */
ptp_read_system_prets(sts);
systimel = er32(SYSTIML); systimel = er32(SYSTIML);
ptp_read_system_postts(sts);
systimeh = er32(SYSTIMH); systimeh = er32(SYSTIMH);
/* Is systimel is so large that overflow is possible? */ /* Is systimel is so large that overflow is possible? */
if (systimel >= (u32)0xffffffff - E1000_TIMINCA_INCVALUE_MASK) { if (systimel >= (u32)0xffffffff - E1000_TIMINCA_INCVALUE_MASK) {
u32 systimel_2 = er32(SYSTIML); ptp_read_system_prets(sts);
systimel_2 = er32(SYSTIML);
ptp_read_system_postts(sts);
if (systimel > systimel_2) { if (systimel > systimel_2) {
/* There was an overflow, read again SYSTIMH, and use /* There was an overflow, read again SYSTIMH, and use
* systimel_2 * systimel_2
...@@ -4386,11 +4396,23 @@ static u64 e1000e_cyclecounter_read(const struct cyclecounter *cc) ...@@ -4386,11 +4396,23 @@ static u64 e1000e_cyclecounter_read(const struct cyclecounter *cc)
systim |= (u64)systimeh << 32; systim |= (u64)systimeh << 32;
if (adapter->flags2 & FLAG2_CHECK_SYSTIM_OVERFLOW) if (adapter->flags2 & FLAG2_CHECK_SYSTIM_OVERFLOW)
systim = e1000e_sanitize_systim(hw, systim); systim = e1000e_sanitize_systim(hw, systim, sts);
return systim; return systim;
} }
/**
* e1000e_cyclecounter_read - read raw cycle counter (used by time counter)
* @cc: cyclecounter structure
**/
static u64 e1000e_cyclecounter_read(const struct cyclecounter *cc)
{
struct e1000_adapter *adapter = container_of(cc, struct e1000_adapter,
cc);
return e1000e_read_systim(adapter, NULL);
}
/** /**
* e1000_sw_init - Initialize general software structures (struct e1000_adapter) * e1000_sw_init - Initialize general software structures (struct e1000_adapter)
* @adapter: board private structure to initialize * @adapter: board private structure to initialize
......
...@@ -161,14 +161,18 @@ static int e1000e_phc_getcrosststamp(struct ptp_clock_info *ptp, ...@@ -161,14 +161,18 @@ static int e1000e_phc_getcrosststamp(struct ptp_clock_info *ptp,
#endif/*CONFIG_E1000E_HWTS*/ #endif/*CONFIG_E1000E_HWTS*/
/** /**
* e1000e_phc_gettime - Reads the current time from the hardware clock * e1000e_phc_gettimex - Reads the current time from the hardware clock and
* system clock
* @ptp: ptp clock structure * @ptp: ptp clock structure
* @ts: timespec structure to hold the current time value * @ts: timespec structure to hold the current PHC time
* @sts: structure to hold the current system time
* *
* Read the timecounter and return the correct value in ns after converting * Read the timecounter and return the correct value in ns after converting
* it into a struct timespec. * it into a struct timespec.
**/ **/
static int e1000e_phc_gettime(struct ptp_clock_info *ptp, struct timespec64 *ts) static int e1000e_phc_gettimex(struct ptp_clock_info *ptp,
struct timespec64 *ts,
struct ptp_system_timestamp *sts)
{ {
struct e1000_adapter *adapter = container_of(ptp, struct e1000_adapter, struct e1000_adapter *adapter = container_of(ptp, struct e1000_adapter,
ptp_clock_info); ptp_clock_info);
...@@ -177,8 +181,8 @@ static int e1000e_phc_gettime(struct ptp_clock_info *ptp, struct timespec64 *ts) ...@@ -177,8 +181,8 @@ static int e1000e_phc_gettime(struct ptp_clock_info *ptp, struct timespec64 *ts)
spin_lock_irqsave(&adapter->systim_lock, flags); spin_lock_irqsave(&adapter->systim_lock, flags);
/* Use timecounter_cyc2time() to allow non-monotonic SYSTIM readings */ /* NOTE: Non-monotonic SYSTIM readings may be returned */
cycles = adapter->cc.read(&adapter->cc); cycles = e1000e_read_systim(adapter, sts);
ns = timecounter_cyc2time(&adapter->tc, cycles); ns = timecounter_cyc2time(&adapter->tc, cycles);
spin_unlock_irqrestore(&adapter->systim_lock, flags); spin_unlock_irqrestore(&adapter->systim_lock, flags);
...@@ -258,7 +262,7 @@ static const struct ptp_clock_info e1000e_ptp_clock_info = { ...@@ -258,7 +262,7 @@ static const struct ptp_clock_info e1000e_ptp_clock_info = {
.pps = 0, .pps = 0,
.adjfreq = e1000e_phc_adjfreq, .adjfreq = e1000e_phc_adjfreq,
.adjtime = e1000e_phc_adjtime, .adjtime = e1000e_phc_adjtime,
.gettime64 = e1000e_phc_gettime, .gettimex64 = e1000e_phc_gettimex,
.settime64 = e1000e_phc_settime, .settime64 = e1000e_phc_settime,
.enable = e1000e_phc_enable, .enable = e1000e_phc_enable,
}; };
......
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