Skip to content

Commit ce58c7c

Browse files
vcgomesanguy11
authored andcommitted
igc: Check if hardware TX timestamping is enabled earlier
Before requesting a packet transmission to be hardware timestamped, check if the user has TX timestamping enabled. Fixes an issue that if a packet was internally forwarded to the NIC, and it had the SKBTX_HW_TSTAMP flag set, the driver would mark that timestamp as skipped. In reality, that timestamp was "not for us", as TX timestamp could never be enabled in the NIC. Checking if the TX timestamping is enabled earlier has a secondary effect that when TX timestamping is disabled, there's no need to check for timestamp timeouts. We should only take care to free any pending timestamp when TX timestamping is disabled, as that skb would never be released otherwise. Fixes: 2c344ae ("igc: Add support for TX timestamping") Suggested-by: Vladimir Oltean <vladimir.oltean@nxp.com> Signed-off-by: Vinicius Costa Gomes <vinicius.gomes@intel.com> Tested-by: Naama Meir <naamax.meir@linux.intel.com> Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
1 parent 9c50e2b commit ce58c7c

3 files changed

Lines changed: 43 additions & 5 deletions

File tree

drivers/net/ethernet/intel/igc/igc.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -581,6 +581,7 @@ enum igc_ring_flags_t {
581581
IGC_RING_FLAG_TX_CTX_IDX,
582582
IGC_RING_FLAG_TX_DETECT_HANG,
583583
IGC_RING_FLAG_AF_XDP_ZC,
584+
IGC_RING_FLAG_TX_HWTSTAMP,
584585
};
585586

586587
#define ring_uses_large_buffer(ring) \

drivers/net/ethernet/intel/igc/igc_main.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1585,15 +1585,16 @@ static netdev_tx_t igc_xmit_frame_ring(struct sk_buff *skb,
15851585
}
15861586
}
15871587

1588-
if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)) {
1588+
if (unlikely(test_bit(IGC_RING_FLAG_TX_HWTSTAMP, &tx_ring->flags) &&
1589+
skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)) {
15891590
/* FIXME: add support for retrieving timestamps from
15901591
* the other timer registers before skipping the
15911592
* timestamping request.
15921593
*/
15931594
unsigned long flags;
15941595

15951596
spin_lock_irqsave(&adapter->ptp_tx_lock, flags);
1596-
if (adapter->tstamp_config.tx_type == HWTSTAMP_TX_ON && !adapter->ptp_tx_skb) {
1597+
if (!adapter->ptp_tx_skb) {
15971598
skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
15981599
tx_flags |= IGC_TX_FLAGS_TSTAMP;
15991600

drivers/net/ethernet/intel/igc/igc_ptp.c

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -536,22 +536,60 @@ static void igc_ptp_enable_rx_timestamp(struct igc_adapter *adapter)
536536
wr32(IGC_TSYNCRXCTL, val);
537537
}
538538

539+
static void igc_ptp_clear_tx_tstamp(struct igc_adapter *adapter)
540+
{
541+
unsigned long flags;
542+
543+
cancel_work_sync(&adapter->ptp_tx_work);
544+
545+
spin_lock_irqsave(&adapter->ptp_tx_lock, flags);
546+
547+
dev_kfree_skb_any(adapter->ptp_tx_skb);
548+
adapter->ptp_tx_skb = NULL;
549+
550+
spin_unlock_irqrestore(&adapter->ptp_tx_lock, flags);
551+
}
552+
539553
static void igc_ptp_disable_tx_timestamp(struct igc_adapter *adapter)
540554
{
541555
struct igc_hw *hw = &adapter->hw;
556+
int i;
557+
558+
/* Clear the flags first to avoid new packets to be enqueued
559+
* for TX timestamping.
560+
*/
561+
for (i = 0; i < adapter->num_tx_queues; i++) {
562+
struct igc_ring *tx_ring = adapter->tx_ring[i];
563+
564+
clear_bit(IGC_RING_FLAG_TX_HWTSTAMP, &tx_ring->flags);
565+
}
566+
567+
/* Now we can clean the pending TX timestamp requests. */
568+
igc_ptp_clear_tx_tstamp(adapter);
542569

543570
wr32(IGC_TSYNCTXCTL, 0);
544571
}
545572

546573
static void igc_ptp_enable_tx_timestamp(struct igc_adapter *adapter)
547574
{
548575
struct igc_hw *hw = &adapter->hw;
576+
int i;
549577

550578
wr32(IGC_TSYNCTXCTL, IGC_TSYNCTXCTL_ENABLED | IGC_TSYNCTXCTL_TXSYNSIG);
551579

552580
/* Read TXSTMP registers to discard any timestamp previously stored. */
553581
rd32(IGC_TXSTMPL);
554582
rd32(IGC_TXSTMPH);
583+
584+
/* The hardware is ready to accept TX timestamp requests,
585+
* notify the transmit path.
586+
*/
587+
for (i = 0; i < adapter->num_tx_queues; i++) {
588+
struct igc_ring *tx_ring = adapter->tx_ring[i];
589+
590+
set_bit(IGC_RING_FLAG_TX_HWTSTAMP, &tx_ring->flags);
591+
}
592+
555593
}
556594

557595
/**
@@ -1026,9 +1064,7 @@ void igc_ptp_suspend(struct igc_adapter *adapter)
10261064
if (!(adapter->ptp_flags & IGC_PTP_ENABLED))
10271065
return;
10281066

1029-
cancel_work_sync(&adapter->ptp_tx_work);
1030-
dev_kfree_skb_any(adapter->ptp_tx_skb);
1031-
adapter->ptp_tx_skb = NULL;
1067+
igc_ptp_clear_tx_tstamp(adapter);
10321068

10331069
if (pci_device_is_present(adapter->pdev)) {
10341070
igc_ptp_time_save(adapter);

0 commit comments

Comments
 (0)