|
@@ -411,7 +411,7 @@ void ixgbe_ptp_overflow_check(struct ixgbe_adapter *adapter)
|
|
|
unsigned long elapsed_jiffies = adapter->last_overflow_check - jiffies;
|
|
|
struct timespec ts;
|
|
|
|
|
|
- if ((adapter->flags2 & IXGBE_FLAG2_OVERFLOW_CHECK_ENABLED) &&
|
|
|
+ if ((adapter->flags2 & IXGBE_FLAG2_PTP_ENABLED) &&
|
|
|
(elapsed_jiffies >= IXGBE_OVERFLOW_PERIOD)) {
|
|
|
ixgbe_ptp_gettime(&adapter->ptp_caps, &ts);
|
|
|
adapter->last_overflow_check = jiffies;
|
|
@@ -759,57 +759,19 @@ int ixgbe_ptp_hwtstamp_ioctl(struct ixgbe_adapter *adapter,
|
|
|
* ixgbe_ptp_start_cyclecounter - create the cycle counter from hw
|
|
|
* @adapter: pointer to the adapter structure
|
|
|
*
|
|
|
- * this function initializes the timecounter and cyclecounter
|
|
|
- * structures for use in generated a ns counter from the arbitrary
|
|
|
- * fixed point cycles registers in the hardware.
|
|
|
- *
|
|
|
- * A change in link speed impacts the frequency of the DMA clock on
|
|
|
- * the device, which is used to generate the cycle counter
|
|
|
- * registers. Therefor this function is called whenever the link speed
|
|
|
- * changes.
|
|
|
- *
|
|
|
- * This function also turns on the SDP pin for clock out feature (X540
|
|
|
- * only), because this is where the shift is first calculated.
|
|
|
+ * This function should be called to set the proper values for the TIMINCA
|
|
|
+ * register and tell the cyclecounter structure what the tick rate of SYSTIME
|
|
|
+ * is. It does not directly modify SYSTIME registers or the timecounter
|
|
|
+ * structure. It should be called whenever a new TIMINCA value is necessary,
|
|
|
+ * such as during initialization or when the link speed changes.
|
|
|
*/
|
|
|
void ixgbe_ptp_start_cyclecounter(struct ixgbe_adapter *adapter)
|
|
|
{
|
|
|
struct ixgbe_hw *hw = &adapter->hw;
|
|
|
u32 incval = 0;
|
|
|
- u32 timinca = 0;
|
|
|
u32 shift = 0;
|
|
|
- u32 cycle_speed;
|
|
|
unsigned long flags;
|
|
|
|
|
|
- /**
|
|
|
- * Determine what speed we need to set the cyclecounter
|
|
|
- * for. It should be different for 100Mb, 1Gb, and 10Gb. Treat
|
|
|
- * unknown speeds as 10Gb. (Hence why we can't just copy the
|
|
|
- * link_speed.
|
|
|
- */
|
|
|
- switch (adapter->link_speed) {
|
|
|
- case IXGBE_LINK_SPEED_100_FULL:
|
|
|
- case IXGBE_LINK_SPEED_1GB_FULL:
|
|
|
- case IXGBE_LINK_SPEED_10GB_FULL:
|
|
|
- cycle_speed = adapter->link_speed;
|
|
|
- break;
|
|
|
- default:
|
|
|
- /* cycle speed should be 10Gb when there is no link */
|
|
|
- cycle_speed = IXGBE_LINK_SPEED_10GB_FULL;
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
- /*
|
|
|
- * grab the current TIMINCA value from the register so that it can be
|
|
|
- * double checked. If the register value has been cleared, it must be
|
|
|
- * reset to the correct value for generating a cyclecounter. If
|
|
|
- * TIMINCA is zero, the SYSTIME registers do not increment at all.
|
|
|
- */
|
|
|
- timinca = IXGBE_READ_REG(hw, IXGBE_TIMINCA);
|
|
|
-
|
|
|
- /* Bail if the cycle speed didn't change and TIMINCA is non-zero */
|
|
|
- if (adapter->cycle_speed == cycle_speed && timinca)
|
|
|
- return;
|
|
|
-
|
|
|
/**
|
|
|
* Scale the NIC cycle counter by a large factor so that
|
|
|
* relatively small corrections to the frequency can be added
|
|
@@ -819,8 +781,12 @@ void ixgbe_ptp_start_cyclecounter(struct ixgbe_adapter *adapter)
|
|
|
* to nanoseconds using only a multiplier and a right-shift,
|
|
|
* and (c) the value must fit within the timinca register space
|
|
|
* => math based on internal DMA clock rate and available bits
|
|
|
+ *
|
|
|
+ * Note that when there is no link, internal DMA clock is same as when
|
|
|
+ * link speed is 10Gb. Set the registers correctly even when link is
|
|
|
+ * down to preserve the clock setting
|
|
|
*/
|
|
|
- switch (cycle_speed) {
|
|
|
+ switch (adapter->link_speed) {
|
|
|
case IXGBE_LINK_SPEED_100_FULL:
|
|
|
incval = IXGBE_INCVAL_100;
|
|
|
shift = IXGBE_INCVAL_SHIFT_100;
|
|
@@ -830,6 +796,7 @@ void ixgbe_ptp_start_cyclecounter(struct ixgbe_adapter *adapter)
|
|
|
shift = IXGBE_INCVAL_SHIFT_1GB;
|
|
|
break;
|
|
|
case IXGBE_LINK_SPEED_10GB_FULL:
|
|
|
+ default:
|
|
|
incval = IXGBE_INCVAL_10GB;
|
|
|
shift = IXGBE_INCVAL_SHIFT_10GB;
|
|
|
break;
|
|
@@ -857,18 +824,11 @@ void ixgbe_ptp_start_cyclecounter(struct ixgbe_adapter *adapter)
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- /* reset the system time registers */
|
|
|
- IXGBE_WRITE_REG(hw, IXGBE_SYSTIML, 0x00000000);
|
|
|
- IXGBE_WRITE_REG(hw, IXGBE_SYSTIMH, 0x00000000);
|
|
|
- IXGBE_WRITE_FLUSH(hw);
|
|
|
-
|
|
|
- /* store the new cycle speed */
|
|
|
- adapter->cycle_speed = cycle_speed;
|
|
|
-
|
|
|
+ /* update the base incval used to calculate frequency adjustment */
|
|
|
ACCESS_ONCE(adapter->base_incval) = incval;
|
|
|
smp_mb();
|
|
|
|
|
|
- /* grab the ptp lock */
|
|
|
+ /* need lock to prevent incorrect read while modifying cyclecounter */
|
|
|
spin_lock_irqsave(&adapter->tmreg_lock, flags);
|
|
|
|
|
|
memset(&adapter->cc, 0, sizeof(adapter->cc));
|
|
@@ -877,6 +837,31 @@ void ixgbe_ptp_start_cyclecounter(struct ixgbe_adapter *adapter)
|
|
|
adapter->cc.shift = shift;
|
|
|
adapter->cc.mult = 1;
|
|
|
|
|
|
+ spin_unlock_irqrestore(&adapter->tmreg_lock, flags);
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * ixgbe_ptp_reset
|
|
|
+ * @adapter: the ixgbe private board structure
|
|
|
+ *
|
|
|
+ * When the MAC resets, all timesync features are reset. This function should be
|
|
|
+ * called to re-enable the PTP clock structure. It will re-init the timecounter
|
|
|
+ * structure based on the kernel time as well as setup the cycle counter data.
|
|
|
+ */
|
|
|
+void ixgbe_ptp_reset(struct ixgbe_adapter *adapter)
|
|
|
+{
|
|
|
+ struct ixgbe_hw *hw = &adapter->hw;
|
|
|
+ unsigned long flags;
|
|
|
+
|
|
|
+ /* set SYSTIME registers to 0 just in case */
|
|
|
+ IXGBE_WRITE_REG(hw, IXGBE_SYSTIML, 0x00000000);
|
|
|
+ IXGBE_WRITE_REG(hw, IXGBE_SYSTIMH, 0x00000000);
|
|
|
+ IXGBE_WRITE_FLUSH(hw);
|
|
|
+
|
|
|
+ ixgbe_ptp_start_cyclecounter(adapter);
|
|
|
+
|
|
|
+ spin_lock_irqsave(&adapter->tmreg_lock, flags);
|
|
|
+
|
|
|
/* reset the ns time counter */
|
|
|
timecounter_init(&adapter->tc, &adapter->cc,
|
|
|
ktime_to_ns(ktime_get_real()));
|
|
@@ -904,7 +889,7 @@ void ixgbe_ptp_init(struct ixgbe_adapter *adapter)
|
|
|
|
|
|
switch (adapter->hw.mac.type) {
|
|
|
case ixgbe_mac_X540:
|
|
|
- snprintf(adapter->ptp_caps.name, 16, "%pm", netdev->dev_addr);
|
|
|
+ snprintf(adapter->ptp_caps.name, 16, "%s", netdev->name);
|
|
|
adapter->ptp_caps.owner = THIS_MODULE;
|
|
|
adapter->ptp_caps.max_adj = 250000000;
|
|
|
adapter->ptp_caps.n_alarm = 0;
|
|
@@ -918,7 +903,7 @@ void ixgbe_ptp_init(struct ixgbe_adapter *adapter)
|
|
|
adapter->ptp_caps.enable = ixgbe_ptp_enable;
|
|
|
break;
|
|
|
case ixgbe_mac_82599EB:
|
|
|
- snprintf(adapter->ptp_caps.name, 16, "%pm", netdev->dev_addr);
|
|
|
+ snprintf(adapter->ptp_caps.name, 16, "%s", netdev->name);
|
|
|
adapter->ptp_caps.owner = THIS_MODULE;
|
|
|
adapter->ptp_caps.max_adj = 250000000;
|
|
|
adapter->ptp_caps.n_alarm = 0;
|
|
@@ -942,11 +927,6 @@ void ixgbe_ptp_init(struct ixgbe_adapter *adapter)
|
|
|
|
|
|
spin_lock_init(&adapter->tmreg_lock);
|
|
|
|
|
|
- ixgbe_ptp_start_cyclecounter(adapter);
|
|
|
-
|
|
|
- /* (Re)start the overflow check */
|
|
|
- adapter->flags2 |= IXGBE_FLAG2_OVERFLOW_CHECK_ENABLED;
|
|
|
-
|
|
|
adapter->ptp_clock = ptp_clock_register(&adapter->ptp_caps,
|
|
|
&adapter->pdev->dev);
|
|
|
if (IS_ERR(adapter->ptp_clock)) {
|
|
@@ -955,6 +935,11 @@ void ixgbe_ptp_init(struct ixgbe_adapter *adapter)
|
|
|
} else
|
|
|
e_dev_info("registered PHC device on %s\n", netdev->name);
|
|
|
|
|
|
+ ixgbe_ptp_reset(adapter);
|
|
|
+
|
|
|
+ /* set the flag that PTP has been enabled */
|
|
|
+ adapter->flags2 |= IXGBE_FLAG2_PTP_ENABLED;
|
|
|
+
|
|
|
return;
|
|
|
}
|
|
|
|
|
@@ -967,7 +952,7 @@ void ixgbe_ptp_init(struct ixgbe_adapter *adapter)
|
|
|
void ixgbe_ptp_stop(struct ixgbe_adapter *adapter)
|
|
|
{
|
|
|
/* stop the overflow check task */
|
|
|
- adapter->flags2 &= ~(IXGBE_FLAG2_OVERFLOW_CHECK_ENABLED |
|
|
|
+ adapter->flags2 &= ~(IXGBE_FLAG2_PTP_ENABLED |
|
|
|
IXGBE_FLAG2_PTP_PPS_ENABLED);
|
|
|
|
|
|
ixgbe_ptp_setup_sdp(adapter);
|