Skip to content

Commit

Permalink
tsnep: Fix rotten packets
Browse files Browse the repository at this point in the history
If PTP synchronisation is done every second, then sporadic the interval
is higher than one second:

ptp4l[696.582]: master offset        -17 s2 freq   -1891 path delay 573
ptp4l[697.582]: master offset        -22 s2 freq   -1901 path delay 573
ptp4l[699.368]: master offset         -1 s2 freq   -1887 path delay 573
      ^^^^^^^ Should be 698.582!

This problem is caused by rotten packets, which are received after
polling but before interrupts are enabled again. This can be fixed by
checking for pending work and rescheduling if necessary after interrupts
has been enabled again.

Fixes: 403f69b ("tsnep: Add TSN endpoint Ethernet MAC driver")
Signed-off-by: Gerhard Engleder <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Paolo Abeni <[email protected]>
  • Loading branch information
Gerhard Engleder authored and Paolo Abeni committed Nov 22, 2022
1 parent bb3cfba commit 2dc4ac9
Showing 1 changed file with 56 additions and 1 deletion.
57 changes: 56 additions & 1 deletion drivers/net/ethernet/engleder/tsnep_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -542,6 +542,27 @@ static bool tsnep_tx_poll(struct tsnep_tx *tx, int napi_budget)
return (budget != 0);
}

static bool tsnep_tx_pending(struct tsnep_tx *tx)
{
unsigned long flags;
struct tsnep_tx_entry *entry;
bool pending = false;

spin_lock_irqsave(&tx->lock, flags);

if (tx->read != tx->write) {
entry = &tx->entry[tx->read];
if ((__le32_to_cpu(entry->desc_wb->properties) &
TSNEP_TX_DESC_OWNER_MASK) ==
(entry->properties & TSNEP_TX_DESC_OWNER_MASK))
pending = true;
}

spin_unlock_irqrestore(&tx->lock, flags);

return pending;
}

static int tsnep_tx_open(struct tsnep_adapter *adapter, void __iomem *addr,
int queue_index, struct tsnep_tx *tx)
{
Expand Down Expand Up @@ -821,6 +842,19 @@ static int tsnep_rx_poll(struct tsnep_rx *rx, struct napi_struct *napi,
return done;
}

static bool tsnep_rx_pending(struct tsnep_rx *rx)
{
struct tsnep_rx_entry *entry;

entry = &rx->entry[rx->read];
if ((__le32_to_cpu(entry->desc_wb->properties) &
TSNEP_DESC_OWNER_COUNTER_MASK) ==
(entry->properties & TSNEP_DESC_OWNER_COUNTER_MASK))
return true;

return false;
}

static int tsnep_rx_open(struct tsnep_adapter *adapter, void __iomem *addr,
int queue_index, struct tsnep_rx *rx)
{
Expand Down Expand Up @@ -866,6 +900,17 @@ static void tsnep_rx_close(struct tsnep_rx *rx)
tsnep_rx_ring_cleanup(rx);
}

static bool tsnep_pending(struct tsnep_queue *queue)
{
if (queue->tx && tsnep_tx_pending(queue->tx))
return true;

if (queue->rx && tsnep_rx_pending(queue->rx))
return true;

return false;
}

static int tsnep_poll(struct napi_struct *napi, int budget)
{
struct tsnep_queue *queue = container_of(napi, struct tsnep_queue,
Expand All @@ -886,9 +931,19 @@ static int tsnep_poll(struct napi_struct *napi, int budget)
if (!complete)
return budget;

if (likely(napi_complete_done(napi, done)))
if (likely(napi_complete_done(napi, done))) {
tsnep_enable_irq(queue->adapter, queue->irq_mask);

/* reschedule if work is already pending, prevent rotten packets
* which are transmitted or received after polling but before
* interrupt enable
*/
if (tsnep_pending(queue)) {
tsnep_disable_irq(queue->adapter, queue->irq_mask);
napi_schedule(napi);
}
}

return min(done, budget - 1);
}

Expand Down

0 comments on commit 2dc4ac9

Please sign in to comment.