1
2
3
4
5
6
7
8
9#include <linux/types.h>
10#include <linux/slab.h>
11#include <linux/kernel.h>
12#include <linux/string.h>
13#include <linux/list.h>
14#include <linux/errno.h>
15#include <linux/skbuff.h>
16#include <linux/math64.h>
17#include <linux/module.h>
18#include <linux/spinlock.h>
19#include <linux/rcupdate.h>
20#include <net/netlink.h>
21#include <net/pkt_sched.h>
22#include <net/pkt_cls.h>
23#include <net/sch_generic.h>
24#include <net/sock.h>
25#include <net/tcp.h>
26
27static LIST_HEAD(taprio_list);
28static DEFINE_SPINLOCK(taprio_list_lock);
29
30#define TAPRIO_ALL_GATES_OPEN -1
31
32#define FLAGS_VALID(flags) (!((flags) & ~TCA_TAPRIO_ATTR_FLAG_TXTIME_ASSIST))
33#define TXTIME_ASSIST_IS_ENABLED(flags) ((flags) & TCA_TAPRIO_ATTR_FLAG_TXTIME_ASSIST)
34
35struct sched_entry {
36 struct list_head list;
37
38
39
40
41
42 ktime_t close_time;
43 ktime_t next_txtime;
44 atomic_t budget;
45 int index;
46 u32 gate_mask;
47 u32 interval;
48 u8 command;
49};
50
51struct sched_gate_list {
52 struct rcu_head rcu;
53 struct list_head entries;
54 size_t num_entries;
55 ktime_t cycle_close_time;
56 s64 cycle_time;
57 s64 cycle_time_extension;
58 s64 base_time;
59};
60
61struct taprio_sched {
62 struct Qdisc **qdiscs;
63 struct Qdisc *root;
64 u32 flags;
65 enum tk_offsets tk_offset;
66 int clockid;
67 atomic64_t picos_per_byte;
68
69
70
71
72 spinlock_t current_entry_lock;
73 struct sched_entry __rcu *current_entry;
74 struct sched_gate_list __rcu *oper_sched;
75 struct sched_gate_list __rcu *admin_sched;
76 struct hrtimer advance_timer;
77 struct list_head taprio_list;
78 u32 txtime_delay;
79};
80
81static ktime_t sched_base_time(const struct sched_gate_list *sched)
82{
83 if (!sched)
84 return KTIME_MAX;
85
86 return ns_to_ktime(sched->base_time);
87}
88
89static ktime_t taprio_get_time(struct taprio_sched *q)
90{
91 ktime_t mono = ktime_get();
92
93 switch (q->tk_offset) {
94 case TK_OFFS_MAX:
95 return mono;
96 default:
97 return ktime_mono_to_any(mono, q->tk_offset);
98 }
99
100 return KTIME_MAX;
101}
102
103static void taprio_free_sched_cb(struct rcu_head *head)
104{
105 struct sched_gate_list *sched = container_of(head, struct sched_gate_list, rcu);
106 struct sched_entry *entry, *n;
107
108 if (!sched)
109 return;
110
111 list_for_each_entry_safe(entry, n, &sched->entries, list) {
112 list_del(&entry->list);
113 kfree(entry);
114 }
115
116 kfree(sched);
117}
118
119static void switch_schedules(struct taprio_sched *q,
120 struct sched_gate_list **admin,
121 struct sched_gate_list **oper)
122{
123 rcu_assign_pointer(q->oper_sched, *admin);
124 rcu_assign_pointer(q->admin_sched, NULL);
125
126 if (*oper)
127 call_rcu(&(*oper)->rcu, taprio_free_sched_cb);
128
129 *oper = *admin;
130 *admin = NULL;
131}
132
133
134static s32 get_cycle_time_elapsed(struct sched_gate_list *sched, ktime_t time)
135{
136 ktime_t time_since_sched_start;
137 s32 time_elapsed;
138
139 time_since_sched_start = ktime_sub(time, sched->base_time);
140 div_s64_rem(time_since_sched_start, sched->cycle_time, &time_elapsed);
141
142 return time_elapsed;
143}
144
145static ktime_t get_interval_end_time(struct sched_gate_list *sched,
146 struct sched_gate_list *admin,
147 struct sched_entry *entry,
148 ktime_t intv_start)
149{
150 s32 cycle_elapsed = get_cycle_time_elapsed(sched, intv_start);
151 ktime_t intv_end, cycle_ext_end, cycle_end;
152
153 cycle_end = ktime_add_ns(intv_start, sched->cycle_time - cycle_elapsed);
154 intv_end = ktime_add_ns(intv_start, entry->interval);
155 cycle_ext_end = ktime_add(cycle_end, sched->cycle_time_extension);
156
157 if (ktime_before(intv_end, cycle_end))
158 return intv_end;
159 else if (admin && admin != sched &&
160 ktime_after(admin->base_time, cycle_end) &&
161 ktime_before(admin->base_time, cycle_ext_end))
162 return admin->base_time;
163 else
164 return cycle_end;
165}
166
167static int length_to_duration(struct taprio_sched *q, int len)
168{
169 return div_u64(len * atomic64_read(&q->picos_per_byte), 1000);
170}
171
172
173
174
175
176static struct sched_entry *find_entry_to_transmit(struct sk_buff *skb,
177 struct Qdisc *sch,
178 struct sched_gate_list *sched,
179 struct sched_gate_list *admin,
180 ktime_t time,
181 ktime_t *interval_start,
182 ktime_t *interval_end,
183 bool validate_interval)
184{
185 ktime_t curr_intv_start, curr_intv_end, cycle_end, packet_transmit_time;
186 ktime_t earliest_txtime = KTIME_MAX, txtime, cycle, transmit_end_time;
187 struct sched_entry *entry = NULL, *entry_found = NULL;
188 struct taprio_sched *q = qdisc_priv(sch);
189 struct net_device *dev = qdisc_dev(sch);
190 bool entry_available = false;
191 s32 cycle_elapsed;
192 int tc, n;
193
194 tc = netdev_get_prio_tc_map(dev, skb->priority);
195 packet_transmit_time = length_to_duration(q, qdisc_pkt_len(skb));
196
197 *interval_start = 0;
198 *interval_end = 0;
199
200 if (!sched)
201 return NULL;
202
203 cycle = sched->cycle_time;
204 cycle_elapsed = get_cycle_time_elapsed(sched, time);
205 curr_intv_end = ktime_sub_ns(time, cycle_elapsed);
206 cycle_end = ktime_add_ns(curr_intv_end, cycle);
207
208 list_for_each_entry(entry, &sched->entries, list) {
209 curr_intv_start = curr_intv_end;
210 curr_intv_end = get_interval_end_time(sched, admin, entry,
211 curr_intv_start);
212
213 if (ktime_after(curr_intv_start, cycle_end))
214 break;
215
216 if (!(entry->gate_mask & BIT(tc)) ||
217 packet_transmit_time > entry->interval)
218 continue;
219
220 txtime = entry->next_txtime;
221
222 if (ktime_before(txtime, time) || validate_interval) {
223 transmit_end_time = ktime_add_ns(time, packet_transmit_time);
224 if ((ktime_before(curr_intv_start, time) &&
225 ktime_before(transmit_end_time, curr_intv_end)) ||
226 (ktime_after(curr_intv_start, time) && !validate_interval)) {
227 entry_found = entry;
228 *interval_start = curr_intv_start;
229 *interval_end = curr_intv_end;
230 break;
231 } else if (!entry_available && !validate_interval) {
232
233
234
235 entry_available = 1;
236 entry_found = entry;
237 *interval_start = ktime_add_ns(curr_intv_start, cycle);
238 *interval_end = ktime_add_ns(curr_intv_end, cycle);
239 }
240 } else if (ktime_before(txtime, earliest_txtime) &&
241 !entry_available) {
242 earliest_txtime = txtime;
243 entry_found = entry;
244 n = div_s64(ktime_sub(txtime, curr_intv_start), cycle);
245 *interval_start = ktime_add(curr_intv_start, n * cycle);
246 *interval_end = ktime_add(curr_intv_end, n * cycle);
247 }
248 }
249
250 return entry_found;
251}
252
253static bool is_valid_interval(struct sk_buff *skb, struct Qdisc *sch)
254{
255 struct taprio_sched *q = qdisc_priv(sch);
256 struct sched_gate_list *sched, *admin;
257 ktime_t interval_start, interval_end;
258 struct sched_entry *entry;
259
260 rcu_read_lock();
261 sched = rcu_dereference(q->oper_sched);
262 admin = rcu_dereference(q->admin_sched);
263
264 entry = find_entry_to_transmit(skb, sch, sched, admin, skb->tstamp,
265 &interval_start, &interval_end, true);
266 rcu_read_unlock();
267
268 return entry;
269}
270
271
272static ktime_t get_tcp_tstamp(struct taprio_sched *q, struct sk_buff *skb)
273{
274 unsigned int offset = skb_network_offset(skb);
275 const struct ipv6hdr *ipv6h;
276 const struct iphdr *iph;
277 struct ipv6hdr _ipv6h;
278
279 ipv6h = skb_header_pointer(skb, offset, sizeof(_ipv6h), &_ipv6h);
280 if (!ipv6h)
281 return 0;
282
283 if (ipv6h->version == 4) {
284 iph = (struct iphdr *)ipv6h;
285 offset += iph->ihl * 4;
286
287
288
289
290 if (iph->protocol == IPPROTO_IPV6) {
291 ipv6h = skb_header_pointer(skb, offset,
292 sizeof(_ipv6h), &_ipv6h);
293
294 if (!ipv6h || ipv6h->nexthdr != IPPROTO_TCP)
295 return 0;
296 } else if (iph->protocol != IPPROTO_TCP) {
297 return 0;
298 }
299 } else if (ipv6h->version == 6 && ipv6h->nexthdr != IPPROTO_TCP) {
300 return 0;
301 }
302
303 return ktime_mono_to_any(skb->skb_mstamp_ns, q->tk_offset);
304}
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321static long get_packet_txtime(struct sk_buff *skb, struct Qdisc *sch)
322{
323 ktime_t transmit_end_time, interval_end, interval_start, tcp_tstamp;
324 struct taprio_sched *q = qdisc_priv(sch);
325 struct sched_gate_list *sched, *admin;
326 ktime_t minimum_time, now, txtime;
327 int len, packet_transmit_time;
328 struct sched_entry *entry;
329 bool sched_changed;
330
331 now = taprio_get_time(q);
332 minimum_time = ktime_add_ns(now, q->txtime_delay);
333
334 tcp_tstamp = get_tcp_tstamp(q, skb);
335 minimum_time = max_t(ktime_t, minimum_time, tcp_tstamp);
336
337 rcu_read_lock();
338 admin = rcu_dereference(q->admin_sched);
339 sched = rcu_dereference(q->oper_sched);
340 if (admin && ktime_after(minimum_time, admin->base_time))
341 switch_schedules(q, &admin, &sched);
342
343
344 if (!sched || ktime_before(minimum_time, sched->base_time)) {
345 txtime = minimum_time;
346 goto done;
347 }
348
349 len = qdisc_pkt_len(skb);
350 packet_transmit_time = length_to_duration(q, len);
351
352 do {
353 sched_changed = 0;
354
355 entry = find_entry_to_transmit(skb, sch, sched, admin,
356 minimum_time,
357 &interval_start, &interval_end,
358 false);
359 if (!entry) {
360 txtime = 0;
361 goto done;
362 }
363
364 txtime = entry->next_txtime;
365 txtime = max_t(ktime_t, txtime, minimum_time);
366 txtime = max_t(ktime_t, txtime, interval_start);
367
368 if (admin && admin != sched &&
369 ktime_after(txtime, admin->base_time)) {
370 sched = admin;
371 sched_changed = 1;
372 continue;
373 }
374
375 transmit_end_time = ktime_add(txtime, packet_transmit_time);
376 minimum_time = transmit_end_time;
377
378
379
380
381 if (ktime_after(transmit_end_time, interval_end))
382 entry->next_txtime = ktime_add(interval_start, sched->cycle_time);
383 } while (sched_changed || ktime_after(transmit_end_time, interval_end));
384
385 entry->next_txtime = transmit_end_time;
386
387done:
388 rcu_read_unlock();
389 return txtime;
390}
391
392static int taprio_enqueue(struct sk_buff *skb, struct Qdisc *sch,
393 struct sk_buff **to_free)
394{
395 struct taprio_sched *q = qdisc_priv(sch);
396 struct Qdisc *child;
397 int queue;
398
399 queue = skb_get_queue_mapping(skb);
400
401 child = q->qdiscs[queue];
402 if (unlikely(!child))
403 return qdisc_drop(skb, sch, to_free);
404
405 if (skb->sk && sock_flag(skb->sk, SOCK_TXTIME)) {
406 if (!is_valid_interval(skb, sch))
407 return qdisc_drop(skb, sch, to_free);
408 } else if (TXTIME_ASSIST_IS_ENABLED(q->flags)) {
409 skb->tstamp = get_packet_txtime(skb, sch);
410 if (!skb->tstamp)
411 return qdisc_drop(skb, sch, to_free);
412 }
413
414 qdisc_qstats_backlog_inc(sch, skb);
415 sch->q.qlen++;
416
417 return qdisc_enqueue(skb, child, to_free);
418}
419
420static struct sk_buff *taprio_peek(struct Qdisc *sch)
421{
422 struct taprio_sched *q = qdisc_priv(sch);
423 struct net_device *dev = qdisc_dev(sch);
424 struct sched_entry *entry;
425 struct sk_buff *skb;
426 u32 gate_mask;
427 int i;
428
429 rcu_read_lock();
430 entry = rcu_dereference(q->current_entry);
431 gate_mask = entry ? entry->gate_mask : TAPRIO_ALL_GATES_OPEN;
432 rcu_read_unlock();
433
434 if (!gate_mask)
435 return NULL;
436
437 for (i = 0; i < dev->num_tx_queues; i++) {
438 struct Qdisc *child = q->qdiscs[i];
439 int prio;
440 u8 tc;
441
442 if (unlikely(!child))
443 continue;
444
445 skb = child->ops->peek(child);
446 if (!skb)
447 continue;
448
449 if (TXTIME_ASSIST_IS_ENABLED(q->flags))
450 return skb;
451
452 prio = skb->priority;
453 tc = netdev_get_prio_tc_map(dev, prio);
454
455 if (!(gate_mask & BIT(tc)))
456 continue;
457
458 return skb;
459 }
460
461 return NULL;
462}
463
464static void taprio_set_budget(struct taprio_sched *q, struct sched_entry *entry)
465{
466 atomic_set(&entry->budget,
467 div64_u64((u64)entry->interval * 1000,
468 atomic64_read(&q->picos_per_byte)));
469}
470
471static struct sk_buff *taprio_dequeue(struct Qdisc *sch)
472{
473 struct taprio_sched *q = qdisc_priv(sch);
474 struct net_device *dev = qdisc_dev(sch);
475 struct sk_buff *skb = NULL;
476 struct sched_entry *entry;
477 u32 gate_mask;
478 int i;
479
480 rcu_read_lock();
481 entry = rcu_dereference(q->current_entry);
482
483
484
485
486
487 gate_mask = entry ? entry->gate_mask : TAPRIO_ALL_GATES_OPEN;
488
489 if (!gate_mask)
490 goto done;
491
492 for (i = 0; i < dev->num_tx_queues; i++) {
493 struct Qdisc *child = q->qdiscs[i];
494 ktime_t guard;
495 int prio;
496 int len;
497 u8 tc;
498
499 if (unlikely(!child))
500 continue;
501
502 if (TXTIME_ASSIST_IS_ENABLED(q->flags)) {
503 skb = child->ops->dequeue(child);
504 if (!skb)
505 continue;
506 goto skb_found;
507 }
508
509 skb = child->ops->peek(child);
510 if (!skb)
511 continue;
512
513 prio = skb->priority;
514 tc = netdev_get_prio_tc_map(dev, prio);
515
516 if (!(gate_mask & BIT(tc)))
517 continue;
518
519 len = qdisc_pkt_len(skb);
520 guard = ktime_add_ns(taprio_get_time(q),
521 length_to_duration(q, len));
522
523
524
525
526 if (gate_mask != TAPRIO_ALL_GATES_OPEN &&
527 ktime_after(guard, entry->close_time))
528 continue;
529
530
531 if (gate_mask != TAPRIO_ALL_GATES_OPEN &&
532 atomic_sub_return(len, &entry->budget) < 0)
533 continue;
534
535 skb = child->ops->dequeue(child);
536 if (unlikely(!skb))
537 goto done;
538
539skb_found:
540 qdisc_bstats_update(sch, skb);
541 qdisc_qstats_backlog_dec(sch, skb);
542 sch->q.qlen--;
543
544 goto done;
545 }
546
547done:
548 rcu_read_unlock();
549
550 return skb;
551}
552
553static bool should_restart_cycle(const struct sched_gate_list *oper,
554 const struct sched_entry *entry)
555{
556 if (list_is_last(&entry->list, &oper->entries))
557 return true;
558
559 if (ktime_compare(entry->close_time, oper->cycle_close_time) == 0)
560 return true;
561
562 return false;
563}
564
565static bool should_change_schedules(const struct sched_gate_list *admin,
566 const struct sched_gate_list *oper,
567 ktime_t close_time)
568{
569 ktime_t next_base_time, extension_time;
570
571 if (!admin)
572 return false;
573
574 next_base_time = sched_base_time(admin);
575
576
577
578
579 if (ktime_compare(next_base_time, close_time) <= 0)
580 return true;
581
582
583
584
585
586
587 extension_time = ktime_add_ns(close_time, oper->cycle_time_extension);
588
589
590
591
592
593 if (ktime_compare(next_base_time, extension_time) <= 0)
594 return true;
595
596 return false;
597}
598
599static enum hrtimer_restart advance_sched(struct hrtimer *timer)
600{
601 struct taprio_sched *q = container_of(timer, struct taprio_sched,
602 advance_timer);
603 struct sched_gate_list *oper, *admin;
604 struct sched_entry *entry, *next;
605 struct Qdisc *sch = q->root;
606 ktime_t close_time;
607
608 spin_lock(&q->current_entry_lock);
609 entry = rcu_dereference_protected(q->current_entry,
610 lockdep_is_held(&q->current_entry_lock));
611 oper = rcu_dereference_protected(q->oper_sched,
612 lockdep_is_held(&q->current_entry_lock));
613 admin = rcu_dereference_protected(q->admin_sched,
614 lockdep_is_held(&q->current_entry_lock));
615
616 if (!oper)
617 switch_schedules(q, &admin, &oper);
618
619
620
621
622
623
624
625 if (unlikely(!entry || entry->close_time == oper->base_time)) {
626 next = list_first_entry(&oper->entries, struct sched_entry,
627 list);
628 close_time = next->close_time;
629 goto first_run;
630 }
631
632 if (should_restart_cycle(oper, entry)) {
633 next = list_first_entry(&oper->entries, struct sched_entry,
634 list);
635 oper->cycle_close_time = ktime_add_ns(oper->cycle_close_time,
636 oper->cycle_time);
637 } else {
638 next = list_next_entry(entry, list);
639 }
640
641 close_time = ktime_add_ns(entry->close_time, next->interval);
642 close_time = min_t(ktime_t, close_time, oper->cycle_close_time);
643
644 if (should_change_schedules(admin, oper, close_time)) {
645
646
647
648 close_time = sched_base_time(admin);
649 switch_schedules(q, &admin, &oper);
650 }
651
652 next->close_time = close_time;
653 taprio_set_budget(q, next);
654
655first_run:
656 rcu_assign_pointer(q->current_entry, next);
657 spin_unlock(&q->current_entry_lock);
658
659 hrtimer_set_expires(&q->advance_timer, close_time);
660
661 rcu_read_lock();
662 __netif_schedule(sch);
663 rcu_read_unlock();
664
665 return HRTIMER_RESTART;
666}
667
668static const struct nla_policy entry_policy[TCA_TAPRIO_SCHED_ENTRY_MAX + 1] = {
669 [TCA_TAPRIO_SCHED_ENTRY_INDEX] = { .type = NLA_U32 },
670 [TCA_TAPRIO_SCHED_ENTRY_CMD] = { .type = NLA_U8 },
671 [TCA_TAPRIO_SCHED_ENTRY_GATE_MASK] = { .type = NLA_U32 },
672 [TCA_TAPRIO_SCHED_ENTRY_INTERVAL] = { .type = NLA_U32 },
673};
674
675static const struct nla_policy entry_list_policy[TCA_TAPRIO_SCHED_MAX + 1] = {
676 [TCA_TAPRIO_SCHED_ENTRY] = { .type = NLA_NESTED },
677};
678
679static const struct nla_policy taprio_policy[TCA_TAPRIO_ATTR_MAX + 1] = {
680 [TCA_TAPRIO_ATTR_PRIOMAP] = {
681 .len = sizeof(struct tc_mqprio_qopt)
682 },
683 [TCA_TAPRIO_ATTR_SCHED_ENTRY_LIST] = { .type = NLA_NESTED },
684 [TCA_TAPRIO_ATTR_SCHED_BASE_TIME] = { .type = NLA_S64 },
685 [TCA_TAPRIO_ATTR_SCHED_SINGLE_ENTRY] = { .type = NLA_NESTED },
686 [TCA_TAPRIO_ATTR_SCHED_CLOCKID] = { .type = NLA_S32 },
687 [TCA_TAPRIO_ATTR_SCHED_CYCLE_TIME] = { .type = NLA_S64 },
688 [TCA_TAPRIO_ATTR_SCHED_CYCLE_TIME_EXTENSION] = { .type = NLA_S64 },
689};
690
691static int fill_sched_entry(struct nlattr **tb, struct sched_entry *entry,
692 struct netlink_ext_ack *extack)
693{
694 u32 interval = 0;
695
696 if (tb[TCA_TAPRIO_SCHED_ENTRY_CMD])
697 entry->command = nla_get_u8(
698 tb[TCA_TAPRIO_SCHED_ENTRY_CMD]);
699
700 if (tb[TCA_TAPRIO_SCHED_ENTRY_GATE_MASK])
701 entry->gate_mask = nla_get_u32(
702 tb[TCA_TAPRIO_SCHED_ENTRY_GATE_MASK]);
703
704 if (tb[TCA_TAPRIO_SCHED_ENTRY_INTERVAL])
705 interval = nla_get_u32(
706 tb[TCA_TAPRIO_SCHED_ENTRY_INTERVAL]);
707
708 if (interval == 0) {
709 NL_SET_ERR_MSG(extack, "Invalid interval for schedule entry");
710 return -EINVAL;
711 }
712
713 entry->interval = interval;
714
715 return 0;
716}
717
718static int parse_sched_entry(struct nlattr *n, struct sched_entry *entry,
719 int index, struct netlink_ext_ack *extack)
720{
721 struct nlattr *tb[TCA_TAPRIO_SCHED_ENTRY_MAX + 1] = { };
722 int err;
723
724 err = nla_parse_nested_deprecated(tb, TCA_TAPRIO_SCHED_ENTRY_MAX, n,
725 entry_policy, NULL);
726 if (err < 0) {
727 NL_SET_ERR_MSG(extack, "Could not parse nested entry");
728 return -EINVAL;
729 }
730
731 entry->index = index;
732
733 return fill_sched_entry(tb, entry, extack);
734}
735
736static int parse_sched_list(struct nlattr *list,
737 struct sched_gate_list *sched,
738 struct netlink_ext_ack *extack)
739{
740 struct nlattr *n;
741 int err, rem;
742 int i = 0;
743
744 if (!list)
745 return -EINVAL;
746
747 nla_for_each_nested(n, list, rem) {
748 struct sched_entry *entry;
749
750 if (nla_type(n) != TCA_TAPRIO_SCHED_ENTRY) {
751 NL_SET_ERR_MSG(extack, "Attribute is not of type 'entry'");
752 continue;
753 }
754
755 entry = kzalloc(sizeof(*entry), GFP_KERNEL);
756 if (!entry) {
757 NL_SET_ERR_MSG(extack, "Not enough memory for entry");
758 return -ENOMEM;
759 }
760
761 err = parse_sched_entry(n, entry, i, extack);
762 if (err < 0) {
763 kfree(entry);
764 return err;
765 }
766
767 list_add_tail(&entry->list, &sched->entries);
768 i++;
769 }
770
771 sched->num_entries = i;
772
773 return i;
774}
775
776static int parse_taprio_schedule(struct nlattr **tb,
777 struct sched_gate_list *new,
778 struct netlink_ext_ack *extack)
779{
780 int err = 0;
781
782 if (tb[TCA_TAPRIO_ATTR_SCHED_SINGLE_ENTRY]) {
783 NL_SET_ERR_MSG(extack, "Adding a single entry is not supported");
784 return -ENOTSUPP;
785 }
786
787 if (tb[TCA_TAPRIO_ATTR_SCHED_BASE_TIME])
788 new->base_time = nla_get_s64(tb[TCA_TAPRIO_ATTR_SCHED_BASE_TIME]);
789
790 if (tb[TCA_TAPRIO_ATTR_SCHED_CYCLE_TIME_EXTENSION])
791 new->cycle_time_extension = nla_get_s64(tb[TCA_TAPRIO_ATTR_SCHED_CYCLE_TIME_EXTENSION]);
792
793 if (tb[TCA_TAPRIO_ATTR_SCHED_CYCLE_TIME])
794 new->cycle_time = nla_get_s64(tb[TCA_TAPRIO_ATTR_SCHED_CYCLE_TIME]);
795
796 if (tb[TCA_TAPRIO_ATTR_SCHED_ENTRY_LIST])
797 err = parse_sched_list(
798 tb[TCA_TAPRIO_ATTR_SCHED_ENTRY_LIST], new, extack);
799 if (err < 0)
800 return err;
801
802 if (!new->cycle_time) {
803 struct sched_entry *entry;
804 ktime_t cycle = 0;
805
806 list_for_each_entry(entry, &new->entries, list)
807 cycle = ktime_add_ns(cycle, entry->interval);
808 new->cycle_time = cycle;
809 }
810
811 return 0;
812}
813
814static int taprio_parse_mqprio_opt(struct net_device *dev,
815 struct tc_mqprio_qopt *qopt,
816 struct netlink_ext_ack *extack,
817 u32 taprio_flags)
818{
819 int i, j;
820
821 if (!qopt && !dev->num_tc) {
822 NL_SET_ERR_MSG(extack, "'mqprio' configuration is necessary");
823 return -EINVAL;
824 }
825
826
827
828
829 if (dev->num_tc)
830 return 0;
831
832
833 if (qopt->num_tc > TC_MAX_QUEUE) {
834 NL_SET_ERR_MSG(extack, "Number of traffic classes is outside valid range");
835 return -EINVAL;
836 }
837
838
839 if (qopt->num_tc > dev->num_tx_queues) {
840 NL_SET_ERR_MSG(extack, "Number of traffic classes is greater than number of HW queues");
841 return -EINVAL;
842 }
843
844
845 for (i = 0; i < TC_BITMASK + 1; i++) {
846 if (qopt->prio_tc_map[i] >= qopt->num_tc) {
847 NL_SET_ERR_MSG(extack, "Invalid traffic class in priority to traffic class mapping");
848 return -EINVAL;
849 }
850 }
851
852 for (i = 0; i < qopt->num_tc; i++) {
853 unsigned int last = qopt->offset[i] + qopt->count[i];
854
855
856
857
858 if (qopt->offset[i] >= dev->num_tx_queues ||
859 !qopt->count[i] ||
860 last > dev->real_num_tx_queues) {
861 NL_SET_ERR_MSG(extack, "Invalid queue in traffic class to queue mapping");
862 return -EINVAL;
863 }
864
865 if (TXTIME_ASSIST_IS_ENABLED(taprio_flags))
866 continue;
867
868
869 for (j = i + 1; j < qopt->num_tc; j++) {
870 if (last > qopt->offset[j]) {
871 NL_SET_ERR_MSG(extack, "Detected overlap in the traffic class to queue mapping");
872 return -EINVAL;
873 }
874 }
875 }
876
877 return 0;
878}
879
880static int taprio_get_start_time(struct Qdisc *sch,
881 struct sched_gate_list *sched,
882 ktime_t *start)
883{
884 struct taprio_sched *q = qdisc_priv(sch);
885 ktime_t now, base, cycle;
886 s64 n;
887
888 base = sched_base_time(sched);
889 now = taprio_get_time(q);
890
891 if (ktime_after(base, now)) {
892 *start = base;
893 return 0;
894 }
895
896 cycle = sched->cycle_time;
897
898
899
900
901
902
903 if (WARN_ON(!cycle))
904 return -EFAULT;
905
906
907
908
909 n = div64_s64(ktime_sub_ns(now, base), cycle);
910 *start = ktime_add_ns(base, (n + 1) * cycle);
911 return 0;
912}
913
914static void setup_first_close_time(struct taprio_sched *q,
915 struct sched_gate_list *sched, ktime_t base)
916{
917 struct sched_entry *first;
918 ktime_t cycle;
919
920 first = list_first_entry(&sched->entries,
921 struct sched_entry, list);
922
923 cycle = sched->cycle_time;
924
925
926 sched->cycle_close_time = ktime_add_ns(base, cycle);
927
928 first->close_time = ktime_add_ns(base, first->interval);
929 taprio_set_budget(q, first);
930 rcu_assign_pointer(q->current_entry, NULL);
931}
932
933static void taprio_start_sched(struct Qdisc *sch,
934 ktime_t start, struct sched_gate_list *new)
935{
936 struct taprio_sched *q = qdisc_priv(sch);
937 ktime_t expires;
938
939 expires = hrtimer_get_expires(&q->advance_timer);
940 if (expires == 0)
941 expires = KTIME_MAX;
942
943
944
945
946
947 start = min_t(ktime_t, start, expires);
948
949 hrtimer_start(&q->advance_timer, start, HRTIMER_MODE_ABS);
950}
951
952static void taprio_set_picos_per_byte(struct net_device *dev,
953 struct taprio_sched *q)
954{
955 struct ethtool_link_ksettings ecmd;
956 int speed = SPEED_10;
957 int picos_per_byte;
958 int err;
959
960 err = __ethtool_get_link_ksettings(dev, &ecmd);
961 if (err < 0)
962 goto skip;
963
964 if (ecmd.base.speed != SPEED_UNKNOWN)
965 speed = ecmd.base.speed;
966
967skip:
968 picos_per_byte = div64_s64(NSEC_PER_SEC * 1000LL * 8,
969 speed * 1000 * 1000);
970
971 atomic64_set(&q->picos_per_byte, picos_per_byte);
972 netdev_dbg(dev, "taprio: set %s's picos_per_byte to: %lld, linkspeed: %d\n",
973 dev->name, (long long)atomic64_read(&q->picos_per_byte),
974 ecmd.base.speed);
975}
976
977static int taprio_dev_notifier(struct notifier_block *nb, unsigned long event,
978 void *ptr)
979{
980 struct net_device *dev = netdev_notifier_info_to_dev(ptr);
981 struct net_device *qdev;
982 struct taprio_sched *q;
983 bool found = false;
984
985 ASSERT_RTNL();
986
987 if (event != NETDEV_UP && event != NETDEV_CHANGE)
988 return NOTIFY_DONE;
989
990 spin_lock(&taprio_list_lock);
991 list_for_each_entry(q, &taprio_list, taprio_list) {
992 qdev = qdisc_dev(q->root);
993 if (qdev == dev) {
994 found = true;
995 break;
996 }
997 }
998 spin_unlock(&taprio_list_lock);
999
1000 if (found)
1001 taprio_set_picos_per_byte(dev, q);
1002
1003 return NOTIFY_DONE;
1004}
1005
1006static void setup_txtime(struct taprio_sched *q,
1007 struct sched_gate_list *sched, ktime_t base)
1008{
1009 struct sched_entry *entry;
1010 u32 interval = 0;
1011
1012 list_for_each_entry(entry, &sched->entries, list) {
1013 entry->next_txtime = ktime_add_ns(base, interval);
1014 interval += entry->interval;
1015 }
1016}
1017
1018static int taprio_change(struct Qdisc *sch, struct nlattr *opt,
1019 struct netlink_ext_ack *extack)
1020{
1021 struct nlattr *tb[TCA_TAPRIO_ATTR_MAX + 1] = { };
1022 struct sched_gate_list *oper, *admin, *new_admin;
1023 struct taprio_sched *q = qdisc_priv(sch);
1024 struct net_device *dev = qdisc_dev(sch);
1025 struct tc_mqprio_qopt *mqprio = NULL;
1026 u32 taprio_flags = 0;
1027 int i, err, clockid;
1028 unsigned long flags;
1029 ktime_t start;
1030
1031 err = nla_parse_nested_deprecated(tb, TCA_TAPRIO_ATTR_MAX, opt,
1032 taprio_policy, extack);
1033 if (err < 0)
1034 return err;
1035
1036 if (tb[TCA_TAPRIO_ATTR_PRIOMAP])
1037 mqprio = nla_data(tb[TCA_TAPRIO_ATTR_PRIOMAP]);
1038
1039 if (tb[TCA_TAPRIO_ATTR_FLAGS]) {
1040 taprio_flags = nla_get_u32(tb[TCA_TAPRIO_ATTR_FLAGS]);
1041
1042 if (q->flags != 0 && q->flags != taprio_flags) {
1043 NL_SET_ERR_MSG_MOD(extack, "Changing 'flags' of a running schedule is not supported");
1044 return -EOPNOTSUPP;
1045 } else if (!FLAGS_VALID(taprio_flags)) {
1046 NL_SET_ERR_MSG_MOD(extack, "Specified 'flags' are not valid");
1047 return -EINVAL;
1048 }
1049
1050 q->flags = taprio_flags;
1051 }
1052
1053 err = taprio_parse_mqprio_opt(dev, mqprio, extack, taprio_flags);
1054 if (err < 0)
1055 return err;
1056
1057 new_admin = kzalloc(sizeof(*new_admin), GFP_KERNEL);
1058 if (!new_admin) {
1059 NL_SET_ERR_MSG(extack, "Not enough memory for a new schedule");
1060 return -ENOMEM;
1061 }
1062 INIT_LIST_HEAD(&new_admin->entries);
1063
1064 rcu_read_lock();
1065 oper = rcu_dereference(q->oper_sched);
1066 admin = rcu_dereference(q->admin_sched);
1067 rcu_read_unlock();
1068
1069 if (mqprio && (oper || admin)) {
1070 NL_SET_ERR_MSG(extack, "Changing the traffic mapping of a running schedule is not supported");
1071 err = -ENOTSUPP;
1072 goto free_sched;
1073 }
1074
1075 err = parse_taprio_schedule(tb, new_admin, extack);
1076 if (err < 0)
1077 goto free_sched;
1078
1079 if (new_admin->num_entries == 0) {
1080 NL_SET_ERR_MSG(extack, "There should be at least one entry in the schedule");
1081 err = -EINVAL;
1082 goto free_sched;
1083 }
1084
1085 if (tb[TCA_TAPRIO_ATTR_SCHED_CLOCKID]) {
1086 clockid = nla_get_s32(tb[TCA_TAPRIO_ATTR_SCHED_CLOCKID]);
1087
1088
1089
1090
1091 if (clockid < 0 ||
1092 (q->clockid != -1 && q->clockid != clockid)) {
1093 NL_SET_ERR_MSG(extack, "Changing the 'clockid' of a running schedule is not supported");
1094 err = -ENOTSUPP;
1095 goto free_sched;
1096 }
1097
1098 q->clockid = clockid;
1099 }
1100
1101 if (q->clockid == -1 && !tb[TCA_TAPRIO_ATTR_SCHED_CLOCKID]) {
1102 NL_SET_ERR_MSG(extack, "Specifying a 'clockid' is mandatory");
1103 err = -EINVAL;
1104 goto free_sched;
1105 }
1106
1107 taprio_set_picos_per_byte(dev, q);
1108
1109
1110 spin_lock_bh(qdisc_lock(sch));
1111
1112 if (tb[TCA_TAPRIO_ATTR_TXTIME_DELAY]) {
1113 if (!TXTIME_ASSIST_IS_ENABLED(q->flags)) {
1114 NL_SET_ERR_MSG_MOD(extack, "txtime-delay can only be set when txtime-assist mode is enabled");
1115 err = -EINVAL;
1116 goto unlock;
1117 }
1118
1119 q->txtime_delay = nla_get_u32(tb[TCA_TAPRIO_ATTR_TXTIME_DELAY]);
1120 }
1121
1122 if (!TXTIME_ASSIST_IS_ENABLED(taprio_flags) &&
1123 !hrtimer_active(&q->advance_timer)) {
1124 hrtimer_init(&q->advance_timer, q->clockid, HRTIMER_MODE_ABS);
1125 q->advance_timer.function = advance_sched;
1126 }
1127
1128 if (mqprio) {
1129 netdev_set_num_tc(dev, mqprio->num_tc);
1130 for (i = 0; i < mqprio->num_tc; i++)
1131 netdev_set_tc_queue(dev, i,
1132 mqprio->count[i],
1133 mqprio->offset[i]);
1134
1135
1136 for (i = 0; i < TC_BITMASK + 1; i++)
1137 netdev_set_prio_tc_map(dev, i,
1138 mqprio->prio_tc_map[i]);
1139 }
1140
1141 switch (q->clockid) {
1142 case CLOCK_REALTIME:
1143 q->tk_offset = TK_OFFS_REAL;
1144 break;
1145 case CLOCK_MONOTONIC:
1146 q->tk_offset = TK_OFFS_MAX;
1147 break;
1148 case CLOCK_BOOTTIME:
1149 q->tk_offset = TK_OFFS_BOOT;
1150 break;
1151 case CLOCK_TAI:
1152 q->tk_offset = TK_OFFS_TAI;
1153 break;
1154 default:
1155 NL_SET_ERR_MSG(extack, "Invalid 'clockid'");
1156 err = -EINVAL;
1157 goto unlock;
1158 }
1159
1160 err = taprio_get_start_time(sch, new_admin, &start);
1161 if (err < 0) {
1162 NL_SET_ERR_MSG(extack, "Internal error: failed get start time");
1163 goto unlock;
1164 }
1165
1166 if (TXTIME_ASSIST_IS_ENABLED(taprio_flags)) {
1167 setup_txtime(q, new_admin, start);
1168
1169 if (!oper) {
1170 rcu_assign_pointer(q->oper_sched, new_admin);
1171 err = 0;
1172 new_admin = NULL;
1173 goto unlock;
1174 }
1175
1176 rcu_assign_pointer(q->admin_sched, new_admin);
1177 if (admin)
1178 call_rcu(&admin->rcu, taprio_free_sched_cb);
1179 } else {
1180 setup_first_close_time(q, new_admin, start);
1181
1182
1183 spin_lock_irqsave(&q->current_entry_lock, flags);
1184
1185 taprio_start_sched(sch, start, new_admin);
1186
1187 rcu_assign_pointer(q->admin_sched, new_admin);
1188 if (admin)
1189 call_rcu(&admin->rcu, taprio_free_sched_cb);
1190
1191 spin_unlock_irqrestore(&q->current_entry_lock, flags);
1192 }
1193
1194 new_admin = NULL;
1195 err = 0;
1196
1197unlock:
1198 spin_unlock_bh(qdisc_lock(sch));
1199
1200free_sched:
1201 if (new_admin)
1202 call_rcu(&new_admin->rcu, taprio_free_sched_cb);
1203
1204 return err;
1205}
1206
1207static void taprio_destroy(struct Qdisc *sch)
1208{
1209 struct taprio_sched *q = qdisc_priv(sch);
1210 struct net_device *dev = qdisc_dev(sch);
1211 unsigned int i;
1212
1213 spin_lock(&taprio_list_lock);
1214 list_del(&q->taprio_list);
1215 spin_unlock(&taprio_list_lock);
1216
1217 hrtimer_cancel(&q->advance_timer);
1218
1219 if (q->qdiscs) {
1220 for (i = 0; i < dev->num_tx_queues && q->qdiscs[i]; i++)
1221 qdisc_put(q->qdiscs[i]);
1222
1223 kfree(q->qdiscs);
1224 }
1225 q->qdiscs = NULL;
1226
1227 netdev_set_num_tc(dev, 0);
1228
1229 if (q->oper_sched)
1230 call_rcu(&q->oper_sched->rcu, taprio_free_sched_cb);
1231
1232 if (q->admin_sched)
1233 call_rcu(&q->admin_sched->rcu, taprio_free_sched_cb);
1234}
1235
1236static int taprio_init(struct Qdisc *sch, struct nlattr *opt,
1237 struct netlink_ext_ack *extack)
1238{
1239 struct taprio_sched *q = qdisc_priv(sch);
1240 struct net_device *dev = qdisc_dev(sch);
1241 int i;
1242
1243 spin_lock_init(&q->current_entry_lock);
1244
1245 hrtimer_init(&q->advance_timer, CLOCK_TAI, HRTIMER_MODE_ABS);
1246 q->advance_timer.function = advance_sched;
1247
1248 q->root = sch;
1249
1250
1251
1252
1253 q->clockid = -1;
1254
1255 spin_lock(&taprio_list_lock);
1256 list_add(&q->taprio_list, &taprio_list);
1257 spin_unlock(&taprio_list_lock);
1258
1259 if (sch->parent != TC_H_ROOT)
1260 return -EOPNOTSUPP;
1261
1262 if (!netif_is_multiqueue(dev))
1263 return -EOPNOTSUPP;
1264
1265
1266 q->qdiscs = kcalloc(dev->num_tx_queues,
1267 sizeof(q->qdiscs[0]),
1268 GFP_KERNEL);
1269
1270 if (!q->qdiscs)
1271 return -ENOMEM;
1272
1273 if (!opt)
1274 return -EINVAL;
1275
1276 for (i = 0; i < dev->num_tx_queues; i++) {
1277 struct netdev_queue *dev_queue;
1278 struct Qdisc *qdisc;
1279
1280 dev_queue = netdev_get_tx_queue(dev, i);
1281 qdisc = qdisc_create_dflt(dev_queue,
1282 &pfifo_qdisc_ops,
1283 TC_H_MAKE(TC_H_MAJ(sch->handle),
1284 TC_H_MIN(i + 1)),
1285 extack);
1286 if (!qdisc)
1287 return -ENOMEM;
1288
1289 if (i < dev->real_num_tx_queues)
1290 qdisc_hash_add(qdisc, false);
1291
1292 q->qdiscs[i] = qdisc;
1293 }
1294
1295 return taprio_change(sch, opt, extack);
1296}
1297
1298static struct netdev_queue *taprio_queue_get(struct Qdisc *sch,
1299 unsigned long cl)
1300{
1301 struct net_device *dev = qdisc_dev(sch);
1302 unsigned long ntx = cl - 1;
1303
1304 if (ntx >= dev->num_tx_queues)
1305 return NULL;
1306
1307 return netdev_get_tx_queue(dev, ntx);
1308}
1309
1310static int taprio_graft(struct Qdisc *sch, unsigned long cl,
1311 struct Qdisc *new, struct Qdisc **old,
1312 struct netlink_ext_ack *extack)
1313{
1314 struct taprio_sched *q = qdisc_priv(sch);
1315 struct net_device *dev = qdisc_dev(sch);
1316 struct netdev_queue *dev_queue = taprio_queue_get(sch, cl);
1317
1318 if (!dev_queue)
1319 return -EINVAL;
1320
1321 if (dev->flags & IFF_UP)
1322 dev_deactivate(dev);
1323
1324 *old = q->qdiscs[cl - 1];
1325 q->qdiscs[cl - 1] = new;
1326
1327 if (new)
1328 new->flags |= TCQ_F_ONETXQUEUE | TCQ_F_NOPARENT;
1329
1330 if (dev->flags & IFF_UP)
1331 dev_activate(dev);
1332
1333 return 0;
1334}
1335
1336static int dump_entry(struct sk_buff *msg,
1337 const struct sched_entry *entry)
1338{
1339 struct nlattr *item;
1340
1341 item = nla_nest_start_noflag(msg, TCA_TAPRIO_SCHED_ENTRY);
1342 if (!item)
1343 return -ENOSPC;
1344
1345 if (nla_put_u32(msg, TCA_TAPRIO_SCHED_ENTRY_INDEX, entry->index))
1346 goto nla_put_failure;
1347
1348 if (nla_put_u8(msg, TCA_TAPRIO_SCHED_ENTRY_CMD, entry->command))
1349 goto nla_put_failure;
1350
1351 if (nla_put_u32(msg, TCA_TAPRIO_SCHED_ENTRY_GATE_MASK,
1352 entry->gate_mask))
1353 goto nla_put_failure;
1354
1355 if (nla_put_u32(msg, TCA_TAPRIO_SCHED_ENTRY_INTERVAL,
1356 entry->interval))
1357 goto nla_put_failure;
1358
1359 return nla_nest_end(msg, item);
1360
1361nla_put_failure:
1362 nla_nest_cancel(msg, item);
1363 return -1;
1364}
1365
1366static int dump_schedule(struct sk_buff *msg,
1367 const struct sched_gate_list *root)
1368{
1369 struct nlattr *entry_list;
1370 struct sched_entry *entry;
1371
1372 if (nla_put_s64(msg, TCA_TAPRIO_ATTR_SCHED_BASE_TIME,
1373 root->base_time, TCA_TAPRIO_PAD))
1374 return -1;
1375
1376 if (nla_put_s64(msg, TCA_TAPRIO_ATTR_SCHED_CYCLE_TIME,
1377 root->cycle_time, TCA_TAPRIO_PAD))
1378 return -1;
1379
1380 if (nla_put_s64(msg, TCA_TAPRIO_ATTR_SCHED_CYCLE_TIME_EXTENSION,
1381 root->cycle_time_extension, TCA_TAPRIO_PAD))
1382 return -1;
1383
1384 entry_list = nla_nest_start_noflag(msg,
1385 TCA_TAPRIO_ATTR_SCHED_ENTRY_LIST);
1386 if (!entry_list)
1387 goto error_nest;
1388
1389 list_for_each_entry(entry, &root->entries, list) {
1390 if (dump_entry(msg, entry) < 0)
1391 goto error_nest;
1392 }
1393
1394 nla_nest_end(msg, entry_list);
1395 return 0;
1396
1397error_nest:
1398 nla_nest_cancel(msg, entry_list);
1399 return -1;
1400}
1401
1402static int taprio_dump(struct Qdisc *sch, struct sk_buff *skb)
1403{
1404 struct taprio_sched *q = qdisc_priv(sch);
1405 struct net_device *dev = qdisc_dev(sch);
1406 struct sched_gate_list *oper, *admin;
1407 struct tc_mqprio_qopt opt = { 0 };
1408 struct nlattr *nest, *sched_nest;
1409 unsigned int i;
1410
1411 rcu_read_lock();
1412 oper = rcu_dereference(q->oper_sched);
1413 admin = rcu_dereference(q->admin_sched);
1414
1415 opt.num_tc = netdev_get_num_tc(dev);
1416 memcpy(opt.prio_tc_map, dev->prio_tc_map, sizeof(opt.prio_tc_map));
1417
1418 for (i = 0; i < netdev_get_num_tc(dev); i++) {
1419 opt.count[i] = dev->tc_to_txq[i].count;
1420 opt.offset[i] = dev->tc_to_txq[i].offset;
1421 }
1422
1423 nest = nla_nest_start_noflag(skb, TCA_OPTIONS);
1424 if (!nest)
1425 goto start_error;
1426
1427 if (nla_put(skb, TCA_TAPRIO_ATTR_PRIOMAP, sizeof(opt), &opt))
1428 goto options_error;
1429
1430 if (nla_put_s32(skb, TCA_TAPRIO_ATTR_SCHED_CLOCKID, q->clockid))
1431 goto options_error;
1432
1433 if (q->flags && nla_put_u32(skb, TCA_TAPRIO_ATTR_FLAGS, q->flags))
1434 goto options_error;
1435
1436 if (q->txtime_delay &&
1437 nla_put_u32(skb, TCA_TAPRIO_ATTR_TXTIME_DELAY, q->txtime_delay))
1438 goto options_error;
1439
1440 if (oper && dump_schedule(skb, oper))
1441 goto options_error;
1442
1443 if (!admin)
1444 goto done;
1445
1446 sched_nest = nla_nest_start_noflag(skb, TCA_TAPRIO_ATTR_ADMIN_SCHED);
1447 if (!sched_nest)
1448 goto options_error;
1449
1450 if (dump_schedule(skb, admin))
1451 goto admin_error;
1452
1453 nla_nest_end(skb, sched_nest);
1454
1455done:
1456 rcu_read_unlock();
1457
1458 return nla_nest_end(skb, nest);
1459
1460admin_error:
1461 nla_nest_cancel(skb, sched_nest);
1462
1463options_error:
1464 nla_nest_cancel(skb, nest);
1465
1466start_error:
1467 rcu_read_unlock();
1468 return -ENOSPC;
1469}
1470
1471static struct Qdisc *taprio_leaf(struct Qdisc *sch, unsigned long cl)
1472{
1473 struct netdev_queue *dev_queue = taprio_queue_get(sch, cl);
1474
1475 if (!dev_queue)
1476 return NULL;
1477
1478 return dev_queue->qdisc_sleeping;
1479}
1480
1481static unsigned long taprio_find(struct Qdisc *sch, u32 classid)
1482{
1483 unsigned int ntx = TC_H_MIN(classid);
1484
1485 if (!taprio_queue_get(sch, ntx))
1486 return 0;
1487 return ntx;
1488}
1489
1490static int taprio_dump_class(struct Qdisc *sch, unsigned long cl,
1491 struct sk_buff *skb, struct tcmsg *tcm)
1492{
1493 struct netdev_queue *dev_queue = taprio_queue_get(sch, cl);
1494
1495 tcm->tcm_parent = TC_H_ROOT;
1496 tcm->tcm_handle |= TC_H_MIN(cl);
1497 tcm->tcm_info = dev_queue->qdisc_sleeping->handle;
1498
1499 return 0;
1500}
1501
1502static int taprio_dump_class_stats(struct Qdisc *sch, unsigned long cl,
1503 struct gnet_dump *d)
1504 __releases(d->lock)
1505 __acquires(d->lock)
1506{
1507 struct netdev_queue *dev_queue = taprio_queue_get(sch, cl);
1508
1509 sch = dev_queue->qdisc_sleeping;
1510 if (gnet_stats_copy_basic(&sch->running, d, NULL, &sch->bstats) < 0 ||
1511 qdisc_qstats_copy(d, sch) < 0)
1512 return -1;
1513 return 0;
1514}
1515
1516static void taprio_walk(struct Qdisc *sch, struct qdisc_walker *arg)
1517{
1518 struct net_device *dev = qdisc_dev(sch);
1519 unsigned long ntx;
1520
1521 if (arg->stop)
1522 return;
1523
1524 arg->count = arg->skip;
1525 for (ntx = arg->skip; ntx < dev->num_tx_queues; ntx++) {
1526 if (arg->fn(sch, ntx + 1, arg) < 0) {
1527 arg->stop = 1;
1528 break;
1529 }
1530 arg->count++;
1531 }
1532}
1533
1534static struct netdev_queue *taprio_select_queue(struct Qdisc *sch,
1535 struct tcmsg *tcm)
1536{
1537 return taprio_queue_get(sch, TC_H_MIN(tcm->tcm_parent));
1538}
1539
1540static const struct Qdisc_class_ops taprio_class_ops = {
1541 .graft = taprio_graft,
1542 .leaf = taprio_leaf,
1543 .find = taprio_find,
1544 .walk = taprio_walk,
1545 .dump = taprio_dump_class,
1546 .dump_stats = taprio_dump_class_stats,
1547 .select_queue = taprio_select_queue,
1548};
1549
1550static struct Qdisc_ops taprio_qdisc_ops __read_mostly = {
1551 .cl_ops = &taprio_class_ops,
1552 .id = "taprio",
1553 .priv_size = sizeof(struct taprio_sched),
1554 .init = taprio_init,
1555 .change = taprio_change,
1556 .destroy = taprio_destroy,
1557 .peek = taprio_peek,
1558 .dequeue = taprio_dequeue,
1559 .enqueue = taprio_enqueue,
1560 .dump = taprio_dump,
1561 .owner = THIS_MODULE,
1562};
1563
1564static struct notifier_block taprio_device_notifier = {
1565 .notifier_call = taprio_dev_notifier,
1566};
1567
1568static int __init taprio_module_init(void)
1569{
1570 int err = register_netdevice_notifier(&taprio_device_notifier);
1571
1572 if (err)
1573 return err;
1574
1575 return register_qdisc(&taprio_qdisc_ops);
1576}
1577
1578static void __exit taprio_module_exit(void)
1579{
1580 unregister_qdisc(&taprio_qdisc_ops);
1581 unregister_netdevice_notifier(&taprio_device_notifier);
1582}
1583
1584module_init(taprio_module_init);
1585module_exit(taprio_module_exit);
1586MODULE_LICENSE("GPL");
1587