diff options
Diffstat (limited to 'net/sched/sch_generic.c')
-rw-r--r-- | net/sched/sch_generic.c | 18 |
1 files changed, 11 insertions, 7 deletions
diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c index 0da09d50873..a854cab03f1 100644 --- a/net/sched/sch_generic.c +++ b/net/sched/sch_generic.c | |||
@@ -550,21 +550,25 @@ struct Qdisc *qdisc_alloc(struct netdev_queue *dev_queue, | |||
550 | { | 550 | { |
551 | void *p; | 551 | void *p; |
552 | struct Qdisc *sch; | 552 | struct Qdisc *sch; |
553 | unsigned int size; | 553 | unsigned int size = QDISC_ALIGN(sizeof(*sch)) + ops->priv_size; |
554 | int err = -ENOBUFS; | 554 | int err = -ENOBUFS; |
555 | 555 | ||
556 | /* ensure that the Qdisc and the private data are 64-byte aligned */ | ||
557 | size = QDISC_ALIGN(sizeof(*sch)); | ||
558 | size += ops->priv_size + (QDISC_ALIGNTO - 1); | ||
559 | |||
560 | p = kzalloc_node(size, GFP_KERNEL, | 556 | p = kzalloc_node(size, GFP_KERNEL, |
561 | netdev_queue_numa_node_read(dev_queue)); | 557 | netdev_queue_numa_node_read(dev_queue)); |
562 | 558 | ||
563 | if (!p) | 559 | if (!p) |
564 | goto errout; | 560 | goto errout; |
565 | sch = (struct Qdisc *) QDISC_ALIGN((unsigned long) p); | 561 | sch = (struct Qdisc *) QDISC_ALIGN((unsigned long) p); |
566 | sch->padded = (char *) sch - (char *) p; | 562 | /* if we got non aligned memory, ask more and do alignment ourself */ |
567 | 563 | if (sch != p) { | |
564 | kfree(p); | ||
565 | p = kzalloc_node(size + QDISC_ALIGNTO - 1, GFP_KERNEL, | ||
566 | netdev_queue_numa_node_read(dev_queue)); | ||
567 | if (!p) | ||
568 | goto errout; | ||
569 | sch = (struct Qdisc *) QDISC_ALIGN((unsigned long) p); | ||
570 | sch->padded = (char *) sch - (char *) p; | ||
571 | } | ||
568 | INIT_LIST_HEAD(&sch->list); | 572 | INIT_LIST_HEAD(&sch->list); |
569 | skb_queue_head_init(&sch->q); | 573 | skb_queue_head_init(&sch->q); |
570 | spin_lock_init(&sch->busylock); | 574 | spin_lock_init(&sch->busylock); |