diff --git a/net/sched/sch_taprio.c b/net/sched/sch_taprio.c index a0d54b422186..41add4a1d407 100644 --- a/net/sched/sch_taprio.c +++ b/net/sched/sch_taprio.c @@ -44,6 +44,8 @@ static struct static_key_false taprio_have_working_mqprio; (TCA_TAPRIO_ATTR_FLAG_TXTIME_ASSIST | TCA_TAPRIO_ATTR_FLAG_FULL_OFFLOAD) #define TAPRIO_FLAGS_INVALID U32_MAX +#define TAPRIO_MAX_NUM_SCHEDULES_BEFORE_NOW 10 + struct sched_entry { /* Durations between this GCL entry and the GCL entry where the * respective traffic class gate closes @@ -62,6 +64,8 @@ struct sched_entry { u32 gate_mask; u32 interval; u8 command; + /* Used to skip some cycles to prevent other tasks from starving */ + u8 num_schedules_before_now; }; struct sched_gate_list { @@ -111,6 +115,9 @@ struct __tc_taprio_qopt_offload { struct tc_taprio_qopt_offload offload; }; +static void setup_txtime(struct taprio_sched *q, + struct sched_gate_list *sched, ktime_t base); + static void taprio_calculate_gate_durations(struct taprio_sched *q, struct sched_gate_list *sched) { @@ -919,6 +926,7 @@ static enum hrtimer_restart advance_sched(struct hrtimer *timer) struct sched_entry *entry, *next; struct Qdisc *sch = q->root; ktime_t end_time; + ktime_t basenow; int tc; spin_lock(&q->current_entry_lock); @@ -977,6 +985,23 @@ static enum hrtimer_restart advance_sched(struct hrtimer *timer) taprio_set_budgets(q, oper, next); first_run: + basenow = ktime_get(); + if (ktime_before(end_time, basenow)) + { + next->num_schedules_before_now++; + if (next->num_schedules_before_now >= TAPRIO_MAX_NUM_SCHEDULES_BEFORE_NOW) + { + end_time = ktime_add_ns(basenow, oper->cycle_time); + next->end_time = end_time; + next->num_schedules_before_now = 0; + setup_txtime(q, oper, basenow); + } + } + else + { + next->num_schedules_before_now = 0; + } + rcu_assign_pointer(q->current_entry, next); spin_unlock(&q->current_entry_lock); @@ -1074,6 +1099,7 @@ static int parse_sched_entry(struct taprio_sched *q, struct nlattr *n, } entry->index = index; + entry->num_schedules_before_now = 0; return fill_sched_entry(q, tb, entry, extack); }