diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index ffa5248a90e2..5bfdab62dc87 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -3284,24 +3284,41 @@ DECLARE_PER_CPU_ALIGNED(struct softnet_data, softnet_data); static inline int dev_recursion_level(void) { +#ifdef CONFIG_PREEMPT_RT + return atomic_read(¤t->xmit_recursion); +#else return this_cpu_read(softnet_data.xmit.recursion); +#endif } #define XMIT_RECURSION_LIMIT 8 static inline bool dev_xmit_recursion(void) { +#ifdef CONFIG_PREEMPT_RT + return unlikely(atomic_read(¤t->xmit_recursion) > + XMIT_RECURSION_LIMIT); +#else return unlikely(__this_cpu_read(softnet_data.xmit.recursion) > XMIT_RECURSION_LIMIT); +#endif } static inline void dev_xmit_recursion_inc(void) { +#ifdef CONFIG_PREEMPT_RT + atomic_inc(¤t->xmit_recursion); +#else __this_cpu_inc(softnet_data.xmit.recursion); +#endif } static inline void dev_xmit_recursion_dec(void) { +#ifdef CONFIG_PREEMPT_RT + atomic_dec(¤t->xmit_recursion); +#else __this_cpu_dec(softnet_data.xmit.recursion); +#endif } void __netif_schedule(struct Qdisc *q); diff --git a/include/linux/sched.h b/include/linux/sched.h index c02fd12b49dc..978a1d715ccf 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -1539,6 +1539,10 @@ struct task_struct { struct user_event_mm *user_event_mm; #endif +#ifdef CONFIG_PREEMPT_RT + atomic_t xmit_recursion; +#endif + /* * New fields for task_struct should be added above here, so that * they are included in the randomized portion of task_struct. diff --git a/kernel/fork.c b/kernel/fork.c index 177ce7438db6..70d4fa074eac 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -1166,6 +1166,10 @@ static struct task_struct *dup_task_struct(struct task_struct *orig, int node) tsk->wake_q.next = NULL; tsk->worker_private = NULL; +#ifdef CONFIG_PREEMPT_RT + atomic_set(&tsk->xmit_recursion, 0); +#endif + kcov_task_init(tsk); kmsan_task_create(tsk); kmap_local_fork(tsk);