Skip to content

Commit 1f6e817

Browse files
MatthewVickIntelJeff Kirsher
authored andcommitted
igb: Prevent dropped Tx timestamps via work items and interrupts.
In rare circumstances, it's possible a descriptor writeback will occur before a timestamped Tx packet will go out on the wire, leading to the driver believing the hardware failed to timestamp the packet. Schedule a work item for 82576 and use the available time sync interrupt registers on 82580 and above to account for this. Cc: Richard Cochran <richardcochran@gmail.com> Signed-off-by: Matthew Vick <matthew.vick@intel.com> Tested-by: Jeff Pieper <jeffrey.e.pieper@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
1 parent 201987e commit 1f6e817

File tree

5 files changed

+153
-25
lines changed

5 files changed

+153
-25
lines changed

drivers/net/ethernet/intel/igb/e1000_defines.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -360,6 +360,7 @@
360360
#define E1000_ICR_RXDMT0 0x00000010 /* rx desc min. threshold (0) */
361361
#define E1000_ICR_RXT0 0x00000080 /* rx timer intr (ring 0) */
362362
#define E1000_ICR_VMMB 0x00000100 /* VM MB event */
363+
#define E1000_ICR_TS 0x00080000 /* Time Sync Interrupt */
363364
#define E1000_ICR_DRSTA 0x40000000 /* Device Reset Asserted */
364365
/* If this bit asserted, the driver should claim the interrupt */
365366
#define E1000_ICR_INT_ASSERTED 0x80000000
@@ -399,6 +400,7 @@
399400
#define E1000_IMS_TXDW E1000_ICR_TXDW /* Transmit desc written back */
400401
#define E1000_IMS_LSC E1000_ICR_LSC /* Link Status Change */
401402
#define E1000_IMS_VMMB E1000_ICR_VMMB /* Mail box activity */
403+
#define E1000_IMS_TS E1000_ICR_TS /* Time Sync Interrupt */
402404
#define E1000_IMS_RXSEQ E1000_ICR_RXSEQ /* rx sequence error */
403405
#define E1000_IMS_RXDMT0 E1000_ICR_RXDMT0 /* rx desc min. threshold */
404406
#define E1000_IMS_RXT0 E1000_ICR_RXT0 /* rx timer intr */
@@ -510,6 +512,9 @@
510512

511513
#define E1000_TIMINCA_16NS_SHIFT 24
512514

515+
#define E1000_TSICR_TXTS 0x00000002
516+
#define E1000_TSIM_TXTS 0x00000002
517+
513518
#define E1000_MDICNFG_EXT_MDIO 0x80000000 /* MDI ext/int destination */
514519
#define E1000_MDICNFG_COM_MDIO 0x40000000 /* MDI shared w/ lan 0 */
515520
#define E1000_MDICNFG_PHY_MASK 0x03E00000

drivers/net/ethernet/intel/igb/e1000_regs.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,8 @@
9191
#define E1000_TIMINCA 0x0B608 /* Increment attributes register - RW */
9292
#define E1000_TSAUXC 0x0B640 /* Timesync Auxiliary Control register */
9393
#define E1000_SYSTIMR 0x0B6F8 /* System time register Residue */
94+
#define E1000_TSICR 0x0B66C /* Interrupt Cause Register */
95+
#define E1000_TSIM 0x0B674 /* Interrupt Mask Register */
9496

9597
/* Filtering Registers */
9698
#define E1000_SAQF(_n) (0x5980 + 4 * (_n))

drivers/net/ethernet/intel/igb/igb.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -381,6 +381,8 @@ struct igb_adapter {
381381
struct ptp_clock *ptp_clock;
382382
struct ptp_clock_info ptp_caps;
383383
struct delayed_work ptp_overflow_work;
384+
struct work_struct ptp_tx_work;
385+
struct sk_buff *ptp_tx_skb;
384386
spinlock_t tmreg_lock;
385387
struct cyclecounter cc;
386388
struct timecounter tc;
@@ -394,6 +396,7 @@ struct igb_adapter {
394396
#define IGB_FLAG_QUAD_PORT_A (1 << 2)
395397
#define IGB_FLAG_QUEUE_PAIRS (1 << 3)
396398
#define IGB_FLAG_DMAC (1 << 4)
399+
#define IGB_FLAG_PTP (1 << 5)
397400

398401
/* DMA Coalescing defines */
399402
#define IGB_MIN_TXPBSIZE 20408
@@ -440,8 +443,9 @@ extern void igb_set_fw_version(struct igb_adapter *);
440443
#ifdef CONFIG_IGB_PTP
441444
extern void igb_ptp_init(struct igb_adapter *adapter);
442445
extern void igb_ptp_stop(struct igb_adapter *adapter);
443-
extern void igb_ptp_tx_hwtstamp(struct igb_q_vector *q_vector,
444-
struct igb_tx_buffer *buffer_info);
446+
extern void igb_ptp_reset(struct igb_adapter *adapter);
447+
extern void igb_ptp_tx_work(struct work_struct *work);
448+
extern void igb_ptp_tx_hwtstamp(struct igb_adapter *adapter);
445449
extern void igb_ptp_rx_hwtstamp(struct igb_q_vector *q_vector,
446450
union e1000_adv_rx_desc *rx_desc,
447451
struct sk_buff *skb);

drivers/net/ethernet/intel/igb/igb_main.c

Lines changed: 54 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1751,6 +1751,11 @@ void igb_reset(struct igb_adapter *adapter)
17511751
/* Enable h/w to recognize an 802.1Q VLAN Ethernet packet */
17521752
wr32(E1000_VET, ETHERNET_IEEE_VLAN_TYPE);
17531753

1754+
#ifdef CONFIG_IGB_PTP
1755+
/* Re-enable PTP, where applicable. */
1756+
igb_ptp_reset(adapter);
1757+
#endif /* CONFIG_IGB_PTP */
1758+
17541759
igb_get_phy_info(hw);
17551760
}
17561761

@@ -4234,7 +4239,7 @@ static __le32 igb_tx_cmd_type(u32 tx_flags)
42344239

42354240
#ifdef CONFIG_IGB_PTP
42364241
/* set timestamp bit if present */
4237-
if (tx_flags & IGB_TX_FLAGS_TSTAMP)
4242+
if (unlikely(tx_flags & IGB_TX_FLAGS_TSTAMP))
42384243
cmd_type |= cpu_to_le32(E1000_ADVTXD_MAC_TSTAMP);
42394244
#endif /* CONFIG_IGB_PTP */
42404245

@@ -4445,6 +4450,9 @@ static inline int igb_maybe_stop_tx(struct igb_ring *tx_ring, const u16 size)
44454450
netdev_tx_t igb_xmit_frame_ring(struct sk_buff *skb,
44464451
struct igb_ring *tx_ring)
44474452
{
4453+
#ifdef CONFIG_IGB_PTP
4454+
struct igb_adapter *adapter = netdev_priv(tx_ring->netdev);
4455+
#endif /* CONFIG_IGB_PTP */
44484456
struct igb_tx_buffer *first;
44494457
int tso;
44504458
u32 tx_flags = 0;
@@ -4468,9 +4476,14 @@ netdev_tx_t igb_xmit_frame_ring(struct sk_buff *skb,
44684476
first->gso_segs = 1;
44694477

44704478
#ifdef CONFIG_IGB_PTP
4471-
if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)) {
4479+
if (unlikely((skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) &&
4480+
!(adapter->ptp_tx_skb))) {
44724481
skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
44734482
tx_flags |= IGB_TX_FLAGS_TSTAMP;
4483+
4484+
adapter->ptp_tx_skb = skb_get(skb);
4485+
if (adapter->hw.mac.type == e1000_82576)
4486+
schedule_work(&adapter->ptp_tx_work);
44744487
}
44754488
#endif /* CONFIG_IGB_PTP */
44764489

@@ -4859,6 +4872,19 @@ static irqreturn_t igb_msix_other(int irq, void *data)
48594872
mod_timer(&adapter->watchdog_timer, jiffies + 1);
48604873
}
48614874

4875+
#ifdef CONFIG_IGB_PTP
4876+
if (icr & E1000_ICR_TS) {
4877+
u32 tsicr = rd32(E1000_TSICR);
4878+
4879+
if (tsicr & E1000_TSICR_TXTS) {
4880+
/* acknowledge the interrupt */
4881+
wr32(E1000_TSICR, E1000_TSICR_TXTS);
4882+
/* retrieve hardware timestamp */
4883+
schedule_work(&adapter->ptp_tx_work);
4884+
}
4885+
}
4886+
#endif /* CONFIG_IGB_PTP */
4887+
48624888
wr32(E1000_EIMS, adapter->eims_other);
48634889

48644890
return IRQ_HANDLED;
@@ -5650,6 +5676,19 @@ static irqreturn_t igb_intr_msi(int irq, void *data)
56505676
mod_timer(&adapter->watchdog_timer, jiffies + 1);
56515677
}
56525678

5679+
#ifdef CONFIG_IGB_PTP
5680+
if (icr & E1000_ICR_TS) {
5681+
u32 tsicr = rd32(E1000_TSICR);
5682+
5683+
if (tsicr & E1000_TSICR_TXTS) {
5684+
/* acknowledge the interrupt */
5685+
wr32(E1000_TSICR, E1000_TSICR_TXTS);
5686+
/* retrieve hardware timestamp */
5687+
schedule_work(&adapter->ptp_tx_work);
5688+
}
5689+
}
5690+
#endif /* CONFIG_IGB_PTP */
5691+
56535692
napi_schedule(&q_vector->napi);
56545693

56555694
return IRQ_HANDLED;
@@ -5691,6 +5730,19 @@ static irqreturn_t igb_intr(int irq, void *data)
56915730
mod_timer(&adapter->watchdog_timer, jiffies + 1);
56925731
}
56935732

5733+
#ifdef CONFIG_IGB_PTP
5734+
if (icr & E1000_ICR_TS) {
5735+
u32 tsicr = rd32(E1000_TSICR);
5736+
5737+
if (tsicr & E1000_TSICR_TXTS) {
5738+
/* acknowledge the interrupt */
5739+
wr32(E1000_TSICR, E1000_TSICR_TXTS);
5740+
/* retrieve hardware timestamp */
5741+
schedule_work(&adapter->ptp_tx_work);
5742+
}
5743+
}
5744+
#endif /* CONFIG_IGB_PTP */
5745+
56945746
napi_schedule(&q_vector->napi);
56955747

56965748
return IRQ_HANDLED;
@@ -5794,11 +5846,6 @@ static bool igb_clean_tx_irq(struct igb_q_vector *q_vector)
57945846
total_bytes += tx_buffer->bytecount;
57955847
total_packets += tx_buffer->gso_segs;
57965848

5797-
#ifdef CONFIG_IGB_PTP
5798-
/* retrieve hardware timestamp */
5799-
igb_ptp_tx_hwtstamp(q_vector, tx_buffer);
5800-
#endif /* CONFIG_IGB_PTP */
5801-
58025849
/* free the skb */
58035850
dev_kfree_skb_any(tx_buffer->skb);
58045851
tx_buffer->skb = NULL;

drivers/net/ethernet/intel/igb/igb_ptp.c

Lines changed: 86 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,31 @@ static int igb_ptp_enable(struct ptp_clock_info *ptp,
289289
return -EOPNOTSUPP;
290290
}
291291

292+
/**
293+
* igb_ptp_tx_work
294+
* @work: pointer to work struct
295+
*
296+
* This work function polls the TSYNCTXCTL valid bit to determine when a
297+
* timestamp has been taken for the current stored skb.
298+
*/
299+
void igb_ptp_tx_work(struct work_struct *work)
300+
{
301+
struct igb_adapter *adapter = container_of(work, struct igb_adapter,
302+
ptp_tx_work);
303+
struct e1000_hw *hw = &adapter->hw;
304+
u32 tsynctxctl;
305+
306+
if (!adapter->ptp_tx_skb)
307+
return;
308+
309+
tsynctxctl = rd32(E1000_TSYNCTXCTL);
310+
if (tsynctxctl & E1000_TSYNCTXCTL_VALID)
311+
igb_ptp_tx_hwtstamp(adapter);
312+
else
313+
/* reschedule to check later */
314+
schedule_work(&adapter->ptp_tx_work);
315+
}
316+
292317
static void igb_ptp_overflow_check(struct work_struct *work)
293318
{
294319
struct igb_adapter *igb =
@@ -305,31 +330,25 @@ static void igb_ptp_overflow_check(struct work_struct *work)
305330

306331
/**
307332
* igb_ptp_tx_hwtstamp - utility function which checks for TX time stamp
308-
* @q_vector: pointer to q_vector containing needed info
309-
* @buffer: pointer to igb_tx_buffer structure
333+
* @adapter: Board private structure.
310334
*
311335
* If we were asked to do hardware stamping and such a time stamp is
312336
* available, then it must have been for this skb here because we only
313337
* allow only one such packet into the queue.
314338
*/
315-
void igb_ptp_tx_hwtstamp(struct igb_q_vector *q_vector,
316-
struct igb_tx_buffer *buffer_info)
339+
void igb_ptp_tx_hwtstamp(struct igb_adapter *adapter)
317340
{
318-
struct igb_adapter *adapter = q_vector->adapter;
319341
struct e1000_hw *hw = &adapter->hw;
320342
struct skb_shared_hwtstamps shhwtstamps;
321343
u64 regval;
322344

323-
/* if skb does not support hw timestamp or TX stamp not valid exit */
324-
if (likely(!(buffer_info->tx_flags & IGB_TX_FLAGS_TSTAMP)) ||
325-
!(rd32(E1000_TSYNCTXCTL) & E1000_TSYNCTXCTL_VALID))
326-
return;
327-
328345
regval = rd32(E1000_TXSTMPL);
329346
regval |= (u64)rd32(E1000_TXSTMPH) << 32;
330347

331348
igb_ptp_systim_to_hwtstamp(adapter, &shhwtstamps, regval);
332-
skb_tstamp_tx(buffer_info->skb, &shhwtstamps);
349+
skb_tstamp_tx(adapter->ptp_tx_skb, &shhwtstamps);
350+
dev_kfree_skb_any(adapter->ptp_tx_skb);
351+
adapter->ptp_tx_skb = NULL;
333352
}
334353

335354
void igb_ptp_rx_hwtstamp(struct igb_q_vector *q_vector,
@@ -603,16 +622,26 @@ void igb_ptp_init(struct igb_adapter *adapter)
603622

604623
spin_lock_init(&adapter->tmreg_lock);
605624

625+
INIT_WORK(&adapter->ptp_tx_work, igb_ptp_tx_work);
626+
606627
schedule_delayed_work(&adapter->ptp_overflow_work,
607628
IGB_SYSTIM_OVERFLOW_PERIOD);
608629

630+
/* Initialize the time sync interrupts for devices that support it. */
631+
if (hw->mac.type >= e1000_82580) {
632+
wr32(E1000_TSIM, E1000_TSIM_TXTS);
633+
wr32(E1000_IMS, E1000_IMS_TS);
634+
}
635+
609636
adapter->ptp_clock = ptp_clock_register(&adapter->ptp_caps);
610637
if (IS_ERR(adapter->ptp_clock)) {
611638
adapter->ptp_clock = NULL;
612639
dev_err(&adapter->pdev->dev, "ptp_clock_register failed\n");
613-
} else
640+
} else {
614641
dev_info(&adapter->pdev->dev, "added PHC on %s\n",
615642
adapter->netdev->name);
643+
adapter->flags |= IGB_FLAG_PTP;
644+
}
616645
}
617646

618647
/**
@@ -624,20 +653,61 @@ void igb_ptp_init(struct igb_adapter *adapter)
624653
void igb_ptp_stop(struct igb_adapter *adapter)
625654
{
626655
switch (adapter->hw.mac.type) {
627-
case e1000_i211:
628-
case e1000_i210:
629-
case e1000_i350:
630-
case e1000_82580:
631656
case e1000_82576:
657+
case e1000_82580:
658+
case e1000_i350:
632659
cancel_delayed_work_sync(&adapter->ptp_overflow_work);
633660
break;
661+
case e1000_i210:
662+
case e1000_i211:
663+
/* No delayed work to cancel. */
664+
break;
634665
default:
635666
return;
636667
}
637668

669+
cancel_work_sync(&adapter->ptp_tx_work);
670+
638671
if (adapter->ptp_clock) {
639672
ptp_clock_unregister(adapter->ptp_clock);
640673
dev_info(&adapter->pdev->dev, "removed PHC on %s\n",
641674
adapter->netdev->name);
675+
adapter->flags &= ~IGB_FLAG_PTP;
642676
}
643677
}
678+
679+
/**
680+
* igb_ptp_reset - Re-enable the adapter for PTP following a reset.
681+
* @adapter: Board private structure.
682+
*
683+
* This function handles the reset work required to re-enable the PTP device.
684+
**/
685+
void igb_ptp_reset(struct igb_adapter *adapter)
686+
{
687+
struct e1000_hw *hw = &adapter->hw;
688+
689+
if (!(adapter->flags & IGB_FLAG_PTP))
690+
return;
691+
692+
switch (adapter->hw.mac.type) {
693+
case e1000_82576:
694+
/* Dial the nominal frequency. */
695+
wr32(E1000_TIMINCA, INCPERIOD_82576 | INCVALUE_82576);
696+
break;
697+
case e1000_82580:
698+
case e1000_i350:
699+
case e1000_i210:
700+
case e1000_i211:
701+
/* Enable the timer functions and interrupts. */
702+
wr32(E1000_TSAUXC, 0x0);
703+
wr32(E1000_TSIM, E1000_TSIM_TXTS);
704+
wr32(E1000_IMS, E1000_IMS_TS);
705+
break;
706+
default:
707+
/* No work to do. */
708+
return;
709+
}
710+
711+
timecounter_init(&adapter->tc, &adapter->cc,
712+
ktime_to_ns(ktime_get_real()));
713+
}

0 commit comments

Comments
 (0)