aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/sched/sch_cbq.c70
1 files changed, 41 insertions, 29 deletions
diff --git a/net/sched/sch_cbq.c b/net/sched/sch_cbq.c
index 32f6a308bad6..0491fad97c0a 100644
--- a/net/sched/sch_cbq.c
+++ b/net/sched/sch_cbq.c
@@ -112,7 +112,7 @@ struct cbq_class
112 112
113 /* Overlimit strategy parameters */ 113 /* Overlimit strategy parameters */
114 void (*overlimit)(struct cbq_class *cl); 114 void (*overlimit)(struct cbq_class *cl);
115 long penalty; 115 psched_tdiff_t penalty;
116 116
117 /* General scheduler (WRR) parameters */ 117 /* General scheduler (WRR) parameters */
118 long allot; 118 long allot;
@@ -143,7 +143,7 @@ struct cbq_class
143 psched_time_t undertime; 143 psched_time_t undertime;
144 long avgidle; 144 long avgidle;
145 long deficit; /* Saved deficit for WRR */ 145 long deficit; /* Saved deficit for WRR */
146 unsigned long penalized; 146 psched_time_t penalized;
147 struct gnet_stats_basic bstats; 147 struct gnet_stats_basic bstats;
148 struct gnet_stats_queue qstats; 148 struct gnet_stats_queue qstats;
149 struct gnet_stats_rate_est rate_est; 149 struct gnet_stats_rate_est rate_est;
@@ -180,7 +180,7 @@ struct cbq_sched_data
180 psched_time_t now_rt; /* Cached real time */ 180 psched_time_t now_rt; /* Cached real time */
181 unsigned pmask; 181 unsigned pmask;
182 182
183 struct timer_list delay_timer; 183 struct hrtimer delay_timer;
184 struct qdisc_watchdog watchdog; /* Watchdog timer, 184 struct qdisc_watchdog watchdog; /* Watchdog timer,
185 started when CBQ has 185 started when CBQ has
186 backlog, but cannot 186 backlog, but cannot
@@ -549,7 +549,8 @@ static void cbq_ovl_delay(struct cbq_class *cl)
549 psched_tdiff_t delay = PSCHED_TDIFF(cl->undertime, q->now); 549 psched_tdiff_t delay = PSCHED_TDIFF(cl->undertime, q->now);
550 550
551 if (!cl->delayed) { 551 if (!cl->delayed) {
552 unsigned long sched = jiffies; 552 psched_time_t sched = q->now;
553 ktime_t expires;
553 554
554 delay += cl->offtime; 555 delay += cl->offtime;
555 if (cl->avgidle < 0) 556 if (cl->avgidle < 0)
@@ -559,14 +560,18 @@ static void cbq_ovl_delay(struct cbq_class *cl)
559 PSCHED_TADD2(q->now, delay, cl->undertime); 560 PSCHED_TADD2(q->now, delay, cl->undertime);
560 561
561 if (delay > 0) { 562 if (delay > 0) {
562 sched += PSCHED_US2JIFFIE(delay) + cl->penalty; 563 sched += delay + cl->penalty;
563 cl->penalized = sched; 564 cl->penalized = sched;
564 cl->cpriority = TC_CBQ_MAXPRIO; 565 cl->cpriority = TC_CBQ_MAXPRIO;
565 q->pmask |= (1<<TC_CBQ_MAXPRIO); 566 q->pmask |= (1<<TC_CBQ_MAXPRIO);
566 if (del_timer(&q->delay_timer) && 567
567 (long)(q->delay_timer.expires - sched) > 0) 568 expires = ktime_set(0, 0);
568 q->delay_timer.expires = sched; 569 expires = ktime_add_ns(expires, PSCHED_US2NS(sched));
569 add_timer(&q->delay_timer); 570 if (hrtimer_try_to_cancel(&q->delay_timer) &&
571 ktime_to_ns(ktime_sub(q->delay_timer.expires,
572 expires)) > 0)
573 q->delay_timer.expires = expires;
574 hrtimer_restart(&q->delay_timer);
570 cl->delayed = 1; 575 cl->delayed = 1;
571 cl->xstats.overactions++; 576 cl->xstats.overactions++;
572 return; 577 return;
@@ -583,7 +588,7 @@ static void cbq_ovl_lowprio(struct cbq_class *cl)
583{ 588{
584 struct cbq_sched_data *q = qdisc_priv(cl->qdisc); 589 struct cbq_sched_data *q = qdisc_priv(cl->qdisc);
585 590
586 cl->penalized = jiffies + cl->penalty; 591 cl->penalized = q->now + cl->penalty;
587 592
588 if (cl->cpriority != cl->priority2) { 593 if (cl->cpriority != cl->priority2) {
589 cl->cpriority = cl->priority2; 594 cl->cpriority = cl->priority2;
@@ -604,19 +609,19 @@ static void cbq_ovl_drop(struct cbq_class *cl)
604 cbq_ovl_classic(cl); 609 cbq_ovl_classic(cl);
605} 610}
606 611
607static unsigned long cbq_undelay_prio(struct cbq_sched_data *q, int prio) 612static psched_tdiff_t cbq_undelay_prio(struct cbq_sched_data *q, int prio,
613 psched_time_t now)
608{ 614{
609 struct cbq_class *cl; 615 struct cbq_class *cl;
610 struct cbq_class *cl_prev = q->active[prio]; 616 struct cbq_class *cl_prev = q->active[prio];
611 unsigned long now = jiffies; 617 psched_time_t sched = now;
612 unsigned long sched = now;
613 618
614 if (cl_prev == NULL) 619 if (cl_prev == NULL)
615 return 0; 620 return 0;
616 621
617 do { 622 do {
618 cl = cl_prev->next_alive; 623 cl = cl_prev->next_alive;
619 if ((long)(now - cl->penalized) > 0) { 624 if (now - cl->penalized > 0) {
620 cl_prev->next_alive = cl->next_alive; 625 cl_prev->next_alive = cl->next_alive;
621 cl->next_alive = NULL; 626 cl->next_alive = NULL;
622 cl->cpriority = cl->priority; 627 cl->cpriority = cl->priority;
@@ -632,30 +637,34 @@ static unsigned long cbq_undelay_prio(struct cbq_sched_data *q, int prio)
632 } 637 }
633 638
634 cl = cl_prev->next_alive; 639 cl = cl_prev->next_alive;
635 } else if ((long)(sched - cl->penalized) > 0) 640 } else if (sched - cl->penalized > 0)
636 sched = cl->penalized; 641 sched = cl->penalized;
637 } while ((cl_prev = cl) != q->active[prio]); 642 } while ((cl_prev = cl) != q->active[prio]);
638 643
639 return (long)(sched - now); 644 return sched - now;
640} 645}
641 646
642static void cbq_undelay(unsigned long arg) 647static enum hrtimer_restart cbq_undelay(struct hrtimer *timer)
643{ 648{
644 struct Qdisc *sch = (struct Qdisc*)arg; 649 struct cbq_sched_data *q = container_of(timer, struct cbq_sched_data,
645 struct cbq_sched_data *q = qdisc_priv(sch); 650 delay_timer);
646 long delay = 0; 651 struct Qdisc *sch = q->watchdog.qdisc;
652 psched_time_t now;
653 psched_tdiff_t delay = 0;
647 unsigned pmask; 654 unsigned pmask;
648 655
656 PSCHED_GET_TIME(now);
657
649 pmask = q->pmask; 658 pmask = q->pmask;
650 q->pmask = 0; 659 q->pmask = 0;
651 660
652 while (pmask) { 661 while (pmask) {
653 int prio = ffz(~pmask); 662 int prio = ffz(~pmask);
654 long tmp; 663 psched_tdiff_t tmp;
655 664
656 pmask &= ~(1<<prio); 665 pmask &= ~(1<<prio);
657 666
658 tmp = cbq_undelay_prio(q, prio); 667 tmp = cbq_undelay_prio(q, prio, now);
659 if (tmp > 0) { 668 if (tmp > 0) {
660 q->pmask |= 1<<prio; 669 q->pmask |= 1<<prio;
661 if (tmp < delay || delay == 0) 670 if (tmp < delay || delay == 0)
@@ -664,12 +673,16 @@ static void cbq_undelay(unsigned long arg)
664 } 673 }
665 674
666 if (delay) { 675 if (delay) {
667 q->delay_timer.expires = jiffies + delay; 676 ktime_t time;
668 add_timer(&q->delay_timer); 677
678 time = ktime_set(0, 0);
679 time = ktime_add_ns(time, PSCHED_US2NS(now + delay));
680 hrtimer_start(&q->delay_timer, time, HRTIMER_MODE_ABS);
669 } 681 }
670 682
671 sch->flags &= ~TCQ_F_THROTTLED; 683 sch->flags &= ~TCQ_F_THROTTLED;
672 netif_schedule(sch->dev); 684 netif_schedule(sch->dev);
685 return HRTIMER_NORESTART;
673} 686}
674 687
675 688
@@ -1265,7 +1278,7 @@ cbq_reset(struct Qdisc* sch)
1265 q->tx_class = NULL; 1278 q->tx_class = NULL;
1266 q->tx_borrowed = NULL; 1279 q->tx_borrowed = NULL;
1267 qdisc_watchdog_cancel(&q->watchdog); 1280 qdisc_watchdog_cancel(&q->watchdog);
1268 del_timer(&q->delay_timer); 1281 hrtimer_cancel(&q->delay_timer);
1269 q->toplevel = TC_CBQ_MAXLEVEL; 1282 q->toplevel = TC_CBQ_MAXLEVEL;
1270 PSCHED_GET_TIME(q->now); 1283 PSCHED_GET_TIME(q->now);
1271 q->now_rt = q->now; 1284 q->now_rt = q->now;
@@ -1367,7 +1380,7 @@ static int cbq_set_overlimit(struct cbq_class *cl, struct tc_cbq_ovl *ovl)
1367 default: 1380 default:
1368 return -EINVAL; 1381 return -EINVAL;
1369 } 1382 }
1370 cl->penalty = (ovl->penalty*HZ)/1000; 1383 cl->penalty = ovl->penalty;
1371 return 0; 1384 return 0;
1372} 1385}
1373 1386
@@ -1435,8 +1448,7 @@ static int cbq_init(struct Qdisc *sch, struct rtattr *opt)
1435 q->link.stats_lock = &sch->dev->queue_lock; 1448 q->link.stats_lock = &sch->dev->queue_lock;
1436 1449
1437 qdisc_watchdog_init(&q->watchdog, sch); 1450 qdisc_watchdog_init(&q->watchdog, sch);
1438 init_timer(&q->delay_timer); 1451 hrtimer_init(&q->delay_timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
1439 q->delay_timer.data = (unsigned long)sch;
1440 q->delay_timer.function = cbq_undelay; 1452 q->delay_timer.function = cbq_undelay;
1441 q->toplevel = TC_CBQ_MAXLEVEL; 1453 q->toplevel = TC_CBQ_MAXLEVEL;
1442 PSCHED_GET_TIME(q->now); 1454 PSCHED_GET_TIME(q->now);
@@ -1514,7 +1526,7 @@ static __inline__ int cbq_dump_ovl(struct sk_buff *skb, struct cbq_class *cl)
1514 opt.strategy = cl->ovl_strategy; 1526 opt.strategy = cl->ovl_strategy;
1515 opt.priority2 = cl->priority2+1; 1527 opt.priority2 = cl->priority2+1;
1516 opt.pad = 0; 1528 opt.pad = 0;
1517 opt.penalty = (cl->penalty*1000)/HZ; 1529 opt.penalty = cl->penalty;
1518 RTA_PUT(skb, TCA_CBQ_OVL_STRATEGY, sizeof(opt), &opt); 1530 RTA_PUT(skb, TCA_CBQ_OVL_STRATEGY, sizeof(opt), &opt);
1519 return skb->len; 1531 return skb->len;
1520 1532