Skip to content

Commit bf3624c

Browse files
leitaokuba-moo
authored andcommitted
netdevsim: call napi_schedule from a timer context
The netdevsim driver was experiencing NOHZ tick-stop errors during packet transmission due to pending softirq work when calling napi_schedule(). This issue was observed when running the netconsole selftest, which triggered the following error message: NOHZ tick-stop error: local softirq work is pending, handler #8!!! To fix this issue, introduce a timer that schedules napi_schedule() from a timer context instead of calling it directly from the TX path. Create an hrtimer for each queue and kick it from the TX path, which then schedules napi_schedule() from the timer context. Suggested-by: Jakub Kicinski <[email protected]> Signed-off-by: Breno Leitao <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
1 parent 372ab5a commit bf3624c

File tree

2 files changed

+21
-1
lines changed

2 files changed

+21
-1
lines changed

drivers/net/netdevsim/netdev.c

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,8 @@ static netdev_tx_t nsim_start_xmit(struct sk_buff *skb, struct net_device *dev)
8787
if (unlikely(nsim_forward_skb(peer_dev, skb, rq) == NET_RX_DROP))
8888
goto out_drop_cnt;
8989

90-
napi_schedule(&rq->napi);
90+
if (!hrtimer_active(&rq->napi_timer))
91+
hrtimer_start(&rq->napi_timer, us_to_ktime(5), HRTIMER_MODE_REL);
9192

9293
rcu_read_unlock();
9394
u64_stats_update_begin(&ns->syncp);
@@ -426,6 +427,22 @@ static int nsim_init_napi(struct netdevsim *ns)
426427
return err;
427428
}
428429

430+
static enum hrtimer_restart nsim_napi_schedule(struct hrtimer *timer)
431+
{
432+
struct nsim_rq *rq;
433+
434+
rq = container_of(timer, struct nsim_rq, napi_timer);
435+
napi_schedule(&rq->napi);
436+
437+
return HRTIMER_NORESTART;
438+
}
439+
440+
static void nsim_rq_timer_init(struct nsim_rq *rq)
441+
{
442+
hrtimer_init(&rq->napi_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
443+
rq->napi_timer.function = nsim_napi_schedule;
444+
}
445+
429446
static void nsim_enable_napi(struct netdevsim *ns)
430447
{
431448
struct net_device *dev = ns->netdev;
@@ -615,11 +632,13 @@ static struct nsim_rq *nsim_queue_alloc(void)
615632
return NULL;
616633

617634
skb_queue_head_init(&rq->skb_queue);
635+
nsim_rq_timer_init(rq);
618636
return rq;
619637
}
620638

621639
static void nsim_queue_free(struct nsim_rq *rq)
622640
{
641+
hrtimer_cancel(&rq->napi_timer);
623642
skb_queue_purge_reason(&rq->skb_queue, SKB_DROP_REASON_QUEUE_PURGE);
624643
kfree(rq);
625644
}

drivers/net/netdevsim/netdevsim.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ struct nsim_rq {
9797
struct napi_struct napi;
9898
struct sk_buff_head skb_queue;
9999
struct page_pool *page_pool;
100+
struct hrtimer napi_timer;
100101
};
101102

102103
struct netdevsim {

0 commit comments

Comments
 (0)