aboutsummaryrefslogtreecommitdiffstats
path: root/net/sched/sch_sfq.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/sched/sch_sfq.c')
-rw-r--r--net/sched/sch_sfq.c52
1 files changed, 33 insertions, 19 deletions
diff --git a/net/sched/sch_sfq.c b/net/sched/sch_sfq.c
index e9d5c911576d..16feb88503af 100644
--- a/net/sched/sch_sfq.c
+++ b/net/sched/sch_sfq.c
@@ -544,10 +544,38 @@ static int sfq_change(struct Qdisc *sch, struct nlattr *opt)
544 return 0; 544 return 0;
545} 545}
546 546
547static void *sfq_alloc(size_t sz)
548{
549 void *ptr = kmalloc(sz, GFP_KERNEL | __GFP_NOWARN);
550
551 if (!ptr)
552 ptr = vmalloc(sz);
553 return ptr;
554}
555
556static void sfq_free(void *addr)
557{
558 if (addr) {
559 if (is_vmalloc_addr(addr))
560 vfree(addr);
561 else
562 kfree(addr);
563 }
564}
565
566static void sfq_destroy(struct Qdisc *sch)
567{
568 struct sfq_sched_data *q = qdisc_priv(sch);
569
570 tcf_destroy_chain(&q->filter_list);
571 q->perturb_period = 0;
572 del_timer_sync(&q->perturb_timer);
573 sfq_free(q->ht);
574}
575
547static int sfq_init(struct Qdisc *sch, struct nlattr *opt) 576static int sfq_init(struct Qdisc *sch, struct nlattr *opt)
548{ 577{
549 struct sfq_sched_data *q = qdisc_priv(sch); 578 struct sfq_sched_data *q = qdisc_priv(sch);
550 size_t sz;
551 int i; 579 int i;
552 580
553 q->perturb_timer.function = sfq_perturbation; 581 q->perturb_timer.function = sfq_perturbation;
@@ -574,12 +602,11 @@ static int sfq_init(struct Qdisc *sch, struct nlattr *opt)
574 return err; 602 return err;
575 } 603 }
576 604
577 sz = sizeof(q->ht[0]) * q->divisor; 605 q->ht = sfq_alloc(sizeof(q->ht[0]) * q->divisor);
578 q->ht = kmalloc(sz, GFP_KERNEL); 606 if (!q->ht) {
579 if (!q->ht && sz > PAGE_SIZE) 607 sfq_destroy(sch);
580 q->ht = vmalloc(sz);
581 if (!q->ht)
582 return -ENOMEM; 608 return -ENOMEM;
609 }
583 for (i = 0; i < q->divisor; i++) 610 for (i = 0; i < q->divisor; i++)
584 q->ht[i] = SFQ_EMPTY_SLOT; 611 q->ht[i] = SFQ_EMPTY_SLOT;
585 612
@@ -594,19 +621,6 @@ static int sfq_init(struct Qdisc *sch, struct nlattr *opt)
594 return 0; 621 return 0;
595} 622}
596 623
597static void sfq_destroy(struct Qdisc *sch)
598{
599 struct sfq_sched_data *q = qdisc_priv(sch);
600
601 tcf_destroy_chain(&q->filter_list);
602 q->perturb_period = 0;
603 del_timer_sync(&q->perturb_timer);
604 if (is_vmalloc_addr(q->ht))
605 vfree(q->ht);
606 else
607 kfree(q->ht);
608}
609
610static int sfq_dump(struct Qdisc *sch, struct sk_buff *skb) 624static int sfq_dump(struct Qdisc *sch, struct sk_buff *skb)
611{ 625{
612 struct sfq_sched_data *q = qdisc_priv(sch); 626 struct sfq_sched_data *q = qdisc_priv(sch);