diff options
| -rw-r--r-- | drivers/net/ethernet/intel/ixgbe/ixgbe.h | 21 | ||||
| -rw-r--r-- | drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 3 | ||||
| -rw-r--r-- | drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c | 36 |
3 files changed, 15 insertions, 45 deletions
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe.h b/drivers/net/ethernet/intel/ixgbe/ixgbe.h index 1a12c1dd7a27..c6c4ca7d68e6 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe.h | |||
| @@ -256,7 +256,6 @@ struct ixgbe_ring { | |||
| 256 | struct ixgbe_tx_buffer *tx_buffer_info; | 256 | struct ixgbe_tx_buffer *tx_buffer_info; |
| 257 | struct ixgbe_rx_buffer *rx_buffer_info; | 257 | struct ixgbe_rx_buffer *rx_buffer_info; |
| 258 | }; | 258 | }; |
| 259 | unsigned long last_rx_timestamp; | ||
| 260 | unsigned long state; | 259 | unsigned long state; |
| 261 | u8 __iomem *tail; | 260 | u8 __iomem *tail; |
| 262 | dma_addr_t dma; /* phys. address of descriptor ring */ | 261 | dma_addr_t dma; /* phys. address of descriptor ring */ |
| @@ -770,6 +769,7 @@ struct ixgbe_adapter { | |||
| 770 | unsigned long ptp_tx_start; | 769 | unsigned long ptp_tx_start; |
| 771 | unsigned long last_overflow_check; | 770 | unsigned long last_overflow_check; |
| 772 | unsigned long last_rx_ptp_check; | 771 | unsigned long last_rx_ptp_check; |
| 772 | unsigned long last_rx_timestamp; | ||
| 773 | spinlock_t tmreg_lock; | 773 | spinlock_t tmreg_lock; |
| 774 | struct cyclecounter cc; | 774 | struct cyclecounter cc; |
| 775 | struct timecounter tc; | 775 | struct timecounter tc; |
| @@ -944,24 +944,7 @@ void ixgbe_ptp_init(struct ixgbe_adapter *adapter); | |||
| 944 | void ixgbe_ptp_stop(struct ixgbe_adapter *adapter); | 944 | void ixgbe_ptp_stop(struct ixgbe_adapter *adapter); |
| 945 | void ixgbe_ptp_overflow_check(struct ixgbe_adapter *adapter); | 945 | void ixgbe_ptp_overflow_check(struct ixgbe_adapter *adapter); |
| 946 | void ixgbe_ptp_rx_hang(struct ixgbe_adapter *adapter); | 946 | void ixgbe_ptp_rx_hang(struct ixgbe_adapter *adapter); |
| 947 | void __ixgbe_ptp_rx_hwtstamp(struct ixgbe_q_vector *q_vector, | 947 | void ixgbe_ptp_rx_hwtstamp(struct ixgbe_adapter *adapter, struct sk_buff *skb); |
| 948 | struct sk_buff *skb); | ||
| 949 | static inline void ixgbe_ptp_rx_hwtstamp(struct ixgbe_ring *rx_ring, | ||
| 950 | union ixgbe_adv_rx_desc *rx_desc, | ||
| 951 | struct sk_buff *skb) | ||
| 952 | { | ||
| 953 | if (unlikely(!ixgbe_test_staterr(rx_desc, IXGBE_RXDADV_STAT_TS))) | ||
| 954 | return; | ||
| 955 | |||
| 956 | __ixgbe_ptp_rx_hwtstamp(rx_ring->q_vector, skb); | ||
| 957 | |||
| 958 | /* | ||
| 959 | * Update the last_rx_timestamp timer in order to enable watchdog check | ||
| 960 | * for error case of latched timestamp on a dropped packet. | ||
| 961 | */ | ||
| 962 | rx_ring->last_rx_timestamp = jiffies; | ||
| 963 | } | ||
| 964 | |||
| 965 | int ixgbe_ptp_set_ts_config(struct ixgbe_adapter *adapter, struct ifreq *ifr); | 948 | int ixgbe_ptp_set_ts_config(struct ixgbe_adapter *adapter, struct ifreq *ifr); |
| 966 | int ixgbe_ptp_get_ts_config(struct ixgbe_adapter *adapter, struct ifreq *ifr); | 949 | int ixgbe_ptp_get_ts_config(struct ixgbe_adapter *adapter, struct ifreq *ifr); |
| 967 | void ixgbe_ptp_start_cyclecounter(struct ixgbe_adapter *adapter); | 950 | void ixgbe_ptp_start_cyclecounter(struct ixgbe_adapter *adapter); |
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index c4c526b7f99f..d62e7a25cf97 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | |||
| @@ -1664,7 +1664,8 @@ static void ixgbe_process_skb_fields(struct ixgbe_ring *rx_ring, | |||
| 1664 | 1664 | ||
| 1665 | ixgbe_rx_checksum(rx_ring, rx_desc, skb); | 1665 | ixgbe_rx_checksum(rx_ring, rx_desc, skb); |
| 1666 | 1666 | ||
| 1667 | ixgbe_ptp_rx_hwtstamp(rx_ring, rx_desc, skb); | 1667 | if (unlikely(ixgbe_test_staterr(rx_desc, IXGBE_RXDADV_STAT_TS))) |
| 1668 | ixgbe_ptp_rx_hwtstamp(rx_ring->q_vector->adapter, skb); | ||
| 1668 | 1669 | ||
| 1669 | if ((dev->features & NETIF_F_HW_VLAN_CTAG_RX) && | 1670 | if ((dev->features & NETIF_F_HW_VLAN_CTAG_RX) && |
| 1670 | ixgbe_test_staterr(rx_desc, IXGBE_RXD_STAT_VP)) { | 1671 | ixgbe_test_staterr(rx_desc, IXGBE_RXD_STAT_VP)) { |
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c index 63515a6f67fa..c247a225a3e0 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c | |||
| @@ -435,10 +435,8 @@ void ixgbe_ptp_overflow_check(struct ixgbe_adapter *adapter) | |||
| 435 | void ixgbe_ptp_rx_hang(struct ixgbe_adapter *adapter) | 435 | void ixgbe_ptp_rx_hang(struct ixgbe_adapter *adapter) |
| 436 | { | 436 | { |
| 437 | struct ixgbe_hw *hw = &adapter->hw; | 437 | struct ixgbe_hw *hw = &adapter->hw; |
| 438 | struct ixgbe_ring *rx_ring; | ||
| 439 | u32 tsyncrxctl = IXGBE_READ_REG(hw, IXGBE_TSYNCRXCTL); | 438 | u32 tsyncrxctl = IXGBE_READ_REG(hw, IXGBE_TSYNCRXCTL); |
| 440 | unsigned long rx_event; | 439 | unsigned long rx_event; |
| 441 | int n; | ||
| 442 | 440 | ||
| 443 | /* if we don't have a valid timestamp in the registers, just update the | 441 | /* if we don't have a valid timestamp in the registers, just update the |
| 444 | * timeout counter and exit | 442 | * timeout counter and exit |
| @@ -450,11 +448,8 @@ void ixgbe_ptp_rx_hang(struct ixgbe_adapter *adapter) | |||
| 450 | 448 | ||
| 451 | /* determine the most recent watchdog or rx_timestamp event */ | 449 | /* determine the most recent watchdog or rx_timestamp event */ |
| 452 | rx_event = adapter->last_rx_ptp_check; | 450 | rx_event = adapter->last_rx_ptp_check; |
| 453 | for (n = 0; n < adapter->num_rx_queues; n++) { | 451 | if (time_after(adapter->last_rx_timestamp, rx_event)) |
| 454 | rx_ring = adapter->rx_ring[n]; | 452 | rx_event = adapter->last_rx_timestamp; |
| 455 | if (time_after(rx_ring->last_rx_timestamp, rx_event)) | ||
| 456 | rx_event = rx_ring->last_rx_timestamp; | ||
| 457 | } | ||
| 458 | 453 | ||
| 459 | /* only need to read the high RXSTMP register to clear the lock */ | 454 | /* only need to read the high RXSTMP register to clear the lock */ |
| 460 | if (time_is_before_jiffies(rx_event + 5*HZ)) { | 455 | if (time_is_before_jiffies(rx_event + 5*HZ)) { |
| @@ -530,35 +525,22 @@ static void ixgbe_ptp_tx_hwtstamp_work(struct work_struct *work) | |||
| 530 | } | 525 | } |
| 531 | 526 | ||
| 532 | /** | 527 | /** |
| 533 | * __ixgbe_ptp_rx_hwtstamp - utility function which checks for RX time stamp | 528 | * ixgbe_ptp_rx_hwtstamp - utility function which checks for RX time stamp |
| 534 | * @q_vector: structure containing interrupt and ring information | 529 | * @adapter: pointer to adapter struct |
| 535 | * @skb: particular skb to send timestamp with | 530 | * @skb: particular skb to send timestamp with |
| 536 | * | 531 | * |
| 537 | * if the timestamp is valid, we convert it into the timecounter ns | 532 | * if the timestamp is valid, we convert it into the timecounter ns |
| 538 | * value, then store that result into the shhwtstamps structure which | 533 | * value, then store that result into the shhwtstamps structure which |
| 539 | * is passed up the network stack | 534 | * is passed up the network stack |
| 540 | */ | 535 | */ |
| 541 | void __ixgbe_ptp_rx_hwtstamp(struct ixgbe_q_vector *q_vector, | 536 | void ixgbe_ptp_rx_hwtstamp(struct ixgbe_adapter *adapter, struct sk_buff *skb) |
| 542 | struct sk_buff *skb) | ||
| 543 | { | 537 | { |
| 544 | struct ixgbe_adapter *adapter; | 538 | struct ixgbe_hw *hw = &adapter->hw; |
| 545 | struct ixgbe_hw *hw; | ||
| 546 | struct skb_shared_hwtstamps *shhwtstamps; | 539 | struct skb_shared_hwtstamps *shhwtstamps; |
| 547 | u64 regval = 0, ns; | 540 | u64 regval = 0, ns; |
| 548 | u32 tsyncrxctl; | 541 | u32 tsyncrxctl; |
| 549 | unsigned long flags; | 542 | unsigned long flags; |
| 550 | 543 | ||
| 551 | /* we cannot process timestamps on a ring without a q_vector */ | ||
| 552 | if (!q_vector || !q_vector->adapter) | ||
| 553 | return; | ||
| 554 | |||
| 555 | adapter = q_vector->adapter; | ||
| 556 | hw = &adapter->hw; | ||
| 557 | |||
| 558 | /* | ||
| 559 | * Read the tsyncrxctl register afterwards in order to prevent taking an | ||
| 560 | * I/O hit on every packet. | ||
| 561 | */ | ||
| 562 | tsyncrxctl = IXGBE_READ_REG(hw, IXGBE_TSYNCRXCTL); | 544 | tsyncrxctl = IXGBE_READ_REG(hw, IXGBE_TSYNCRXCTL); |
| 563 | if (!(tsyncrxctl & IXGBE_TSYNCRXCTL_VALID)) | 545 | if (!(tsyncrxctl & IXGBE_TSYNCRXCTL_VALID)) |
| 564 | return; | 546 | return; |
| @@ -566,13 +548,17 @@ void __ixgbe_ptp_rx_hwtstamp(struct ixgbe_q_vector *q_vector, | |||
| 566 | regval |= (u64)IXGBE_READ_REG(hw, IXGBE_RXSTMPL); | 548 | regval |= (u64)IXGBE_READ_REG(hw, IXGBE_RXSTMPL); |
| 567 | regval |= (u64)IXGBE_READ_REG(hw, IXGBE_RXSTMPH) << 32; | 549 | regval |= (u64)IXGBE_READ_REG(hw, IXGBE_RXSTMPH) << 32; |
| 568 | 550 | ||
| 569 | |||
| 570 | spin_lock_irqsave(&adapter->tmreg_lock, flags); | 551 | spin_lock_irqsave(&adapter->tmreg_lock, flags); |
| 571 | ns = timecounter_cyc2time(&adapter->tc, regval); | 552 | ns = timecounter_cyc2time(&adapter->tc, regval); |
| 572 | spin_unlock_irqrestore(&adapter->tmreg_lock, flags); | 553 | spin_unlock_irqrestore(&adapter->tmreg_lock, flags); |
| 573 | 554 | ||
| 574 | shhwtstamps = skb_hwtstamps(skb); | 555 | shhwtstamps = skb_hwtstamps(skb); |
| 575 | shhwtstamps->hwtstamp = ns_to_ktime(ns); | 556 | shhwtstamps->hwtstamp = ns_to_ktime(ns); |
| 557 | |||
| 558 | /* Update the last_rx_timestamp timer in order to enable watchdog check | ||
| 559 | * for error case of latched timestamp on a dropped packet. | ||
| 560 | */ | ||
| 561 | adapter->last_rx_timestamp = jiffies; | ||
| 576 | } | 562 | } |
| 577 | 563 | ||
| 578 | int ixgbe_ptp_get_ts_config(struct ixgbe_adapter *adapter, struct ifreq *ifr) | 564 | int ixgbe_ptp_get_ts_config(struct ixgbe_adapter *adapter, struct ifreq *ifr) |
