Skip to content

Commit b3ca9ee

Browse files
Gerhard Englederkuba-moo
Gerhard Engleder
authored andcommitted
tsnep: fix timestamping with a stacked DSA driver
This driver is susceptible to a form of the bug explained in commit c26a2c2 ("gianfar: Fix TX timestamping with a stacked DSA driver") and in Documentation/networking/timestamping.rst section "Other caveats for MAC drivers", specifically it timestamps any skb which has SKBTX_HW_TSTAMP, and does not consider if timestamping has been enabled in adapter->hwtstamp_config.tx_type. Evaluate the proper TX timestamping condition only once on the TX path (in tsnep_xmit_frame_ring()) and store the result in an additional TX entry flag. Evaluate the new TX entry flag in the TX confirmation path (in tsnep_tx_poll()). This way SKBTX_IN_PROGRESS is set by the driver as required, but never evaluated. SKBTX_IN_PROGRESS shall not be evaluated as it can be set by a stacked DSA driver and evaluating it would lead to unwanted timestamps. Fixes: 403f69b ("tsnep: Add TSN endpoint Ethernet MAC driver") Suggested-by: Vladimir Oltean <[email protected]> Signed-off-by: Gerhard Engleder <[email protected]> Reviewed-by: Vladimir Oltean <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
1 parent 491deb9 commit b3ca9ee

File tree

1 file changed

+19
-11
lines changed

1 file changed

+19
-11
lines changed

drivers/net/ethernet/engleder/tsnep_main.c

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,8 @@
6767
#define TSNEP_TX_TYPE_XDP_NDO_MAP_PAGE (TSNEP_TX_TYPE_XDP_NDO | TSNEP_TX_TYPE_MAP_PAGE)
6868
#define TSNEP_TX_TYPE_XDP (TSNEP_TX_TYPE_XDP_TX | TSNEP_TX_TYPE_XDP_NDO)
6969
#define TSNEP_TX_TYPE_XSK BIT(12)
70+
#define TSNEP_TX_TYPE_TSTAMP BIT(13)
71+
#define TSNEP_TX_TYPE_SKB_TSTAMP (TSNEP_TX_TYPE_SKB | TSNEP_TX_TYPE_TSTAMP)
7072

7173
#define TSNEP_XDP_TX BIT(0)
7274
#define TSNEP_XDP_REDIRECT BIT(1)
@@ -386,8 +388,7 @@ static void tsnep_tx_activate(struct tsnep_tx *tx, int index, int length,
386388
if (entry->skb) {
387389
entry->properties = length & TSNEP_DESC_LENGTH_MASK;
388390
entry->properties |= TSNEP_DESC_INTERRUPT_FLAG;
389-
if ((entry->type & TSNEP_TX_TYPE_SKB) &&
390-
(skb_shinfo(entry->skb)->tx_flags & SKBTX_IN_PROGRESS))
391+
if ((entry->type & TSNEP_TX_TYPE_SKB_TSTAMP) == TSNEP_TX_TYPE_SKB_TSTAMP)
391392
entry->properties |= TSNEP_DESC_EXTENDED_WRITEBACK_FLAG;
392393

393394
/* toggle user flag to prevent false acknowledge
@@ -479,7 +480,8 @@ static int tsnep_tx_map_frag(skb_frag_t *frag, struct tsnep_tx_entry *entry,
479480
return mapped;
480481
}
481482

482-
static int tsnep_tx_map(struct sk_buff *skb, struct tsnep_tx *tx, int count)
483+
static int tsnep_tx_map(struct sk_buff *skb, struct tsnep_tx *tx, int count,
484+
bool do_tstamp)
483485
{
484486
struct device *dmadev = tx->adapter->dmadev;
485487
struct tsnep_tx_entry *entry;
@@ -505,6 +507,9 @@ static int tsnep_tx_map(struct sk_buff *skb, struct tsnep_tx *tx, int count)
505507
entry->type = TSNEP_TX_TYPE_SKB_INLINE;
506508
mapped = 0;
507509
}
510+
511+
if (do_tstamp)
512+
entry->type |= TSNEP_TX_TYPE_TSTAMP;
508513
} else {
509514
skb_frag_t *frag = &skb_shinfo(skb)->frags[i - 1];
510515

@@ -558,11 +563,12 @@ static int tsnep_tx_unmap(struct tsnep_tx *tx, int index, int count)
558563
static netdev_tx_t tsnep_xmit_frame_ring(struct sk_buff *skb,
559564
struct tsnep_tx *tx)
560565
{
561-
int count = 1;
562566
struct tsnep_tx_entry *entry;
567+
bool do_tstamp = false;
568+
int count = 1;
563569
int length;
564-
int i;
565570
int retval;
571+
int i;
566572

567573
if (skb_shinfo(skb)->nr_frags > 0)
568574
count += skb_shinfo(skb)->nr_frags;
@@ -579,7 +585,13 @@ static netdev_tx_t tsnep_xmit_frame_ring(struct sk_buff *skb,
579585
entry = &tx->entry[tx->write];
580586
entry->skb = skb;
581587

582-
retval = tsnep_tx_map(skb, tx, count);
588+
if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) &&
589+
tx->adapter->hwtstamp_config.tx_type == HWTSTAMP_TX_ON) {
590+
skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
591+
do_tstamp = true;
592+
}
593+
594+
retval = tsnep_tx_map(skb, tx, count, do_tstamp);
583595
if (retval < 0) {
584596
tsnep_tx_unmap(tx, tx->write, count);
585597
dev_kfree_skb_any(entry->skb);
@@ -591,9 +603,6 @@ static netdev_tx_t tsnep_xmit_frame_ring(struct sk_buff *skb,
591603
}
592604
length = retval;
593605

594-
if (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)
595-
skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
596-
597606
for (i = 0; i < count; i++)
598607
tsnep_tx_activate(tx, (tx->write + i) & TSNEP_RING_MASK, length,
599608
i == count - 1);
@@ -844,8 +853,7 @@ static bool tsnep_tx_poll(struct tsnep_tx *tx, int napi_budget)
844853

845854
length = tsnep_tx_unmap(tx, tx->read, count);
846855

847-
if ((entry->type & TSNEP_TX_TYPE_SKB) &&
848-
(skb_shinfo(entry->skb)->tx_flags & SKBTX_IN_PROGRESS) &&
856+
if (((entry->type & TSNEP_TX_TYPE_SKB_TSTAMP) == TSNEP_TX_TYPE_SKB_TSTAMP) &&
849857
(__le32_to_cpu(entry->desc_wb->properties) &
850858
TSNEP_DESC_EXTENDED_WRITEBACK_FLAG)) {
851859
struct skb_shared_hwtstamps hwtstamps;

0 commit comments

Comments
 (0)