Commit 3d54b82f authored by Thomas Graf's avatar Thomas Graf Committed by David S. Miller

[PKT_SCHED]: Cleanup qdisc creation and alignment macros

Adds qdisc_alloc() to share code between qdisc_create()
and qdisc_create_dflt(). Hides the qdisc alignment behind
macros and makes use of them.
Signed-off-by: default avatarThomas Graf <tgraf@suug.ch>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent e41a33e6
...@@ -13,13 +13,12 @@ struct qdisc_walker ...@@ -13,13 +13,12 @@ struct qdisc_walker
extern rwlock_t qdisc_tree_lock; extern rwlock_t qdisc_tree_lock;
#define QDISC_ALIGN 32 #define QDISC_ALIGNTO 32
#define QDISC_ALIGN_CONST (QDISC_ALIGN - 1) #define QDISC_ALIGN(len) (((len) + QDISC_ALIGNTO-1) & ~(QDISC_ALIGNTO-1))
static inline void *qdisc_priv(struct Qdisc *q) static inline void *qdisc_priv(struct Qdisc *q)
{ {
return (char *)q + ((sizeof(struct Qdisc) + QDISC_ALIGN_CONST) return (char *) q + QDISC_ALIGN(sizeof(struct Qdisc));
& ~QDISC_ALIGN_CONST);
} }
/* /*
......
...@@ -173,6 +173,7 @@ extern void dev_activate(struct net_device *dev); ...@@ -173,6 +173,7 @@ extern void dev_activate(struct net_device *dev);
extern void dev_deactivate(struct net_device *dev); extern void dev_deactivate(struct net_device *dev);
extern void qdisc_reset(struct Qdisc *qdisc); extern void qdisc_reset(struct Qdisc *qdisc);
extern void qdisc_destroy(struct Qdisc *qdisc); extern void qdisc_destroy(struct Qdisc *qdisc);
extern struct Qdisc *qdisc_alloc(struct net_device *dev, struct Qdisc_ops *ops);
extern struct Qdisc *qdisc_create_dflt(struct net_device *dev, extern struct Qdisc *qdisc_create_dflt(struct net_device *dev,
struct Qdisc_ops *ops); struct Qdisc_ops *ops);
......
...@@ -399,10 +399,8 @@ qdisc_create(struct net_device *dev, u32 handle, struct rtattr **tca, int *errp) ...@@ -399,10 +399,8 @@ qdisc_create(struct net_device *dev, u32 handle, struct rtattr **tca, int *errp)
{ {
int err; int err;
struct rtattr *kind = tca[TCA_KIND-1]; struct rtattr *kind = tca[TCA_KIND-1];
void *p = NULL;
struct Qdisc *sch; struct Qdisc *sch;
struct Qdisc_ops *ops; struct Qdisc_ops *ops;
int size;
ops = qdisc_lookup_ops(kind); ops = qdisc_lookup_ops(kind);
#ifdef CONFIG_KMOD #ifdef CONFIG_KMOD
...@@ -437,43 +435,23 @@ qdisc_create(struct net_device *dev, u32 handle, struct rtattr **tca, int *errp) ...@@ -437,43 +435,23 @@ qdisc_create(struct net_device *dev, u32 handle, struct rtattr **tca, int *errp)
if (ops == NULL) if (ops == NULL)
goto err_out; goto err_out;
/* ensure that the Qdisc and the private data are 32-byte aligned */ sch = qdisc_alloc(dev, ops);
size = ((sizeof(*sch) + QDISC_ALIGN_CONST) & ~QDISC_ALIGN_CONST); if (IS_ERR(sch)) {
size += ops->priv_size + QDISC_ALIGN_CONST; err = PTR_ERR(sch);
p = kmalloc(size, GFP_KERNEL);
err = -ENOBUFS;
if (!p)
goto err_out2; goto err_out2;
memset(p, 0, size); }
sch = (struct Qdisc *)(((unsigned long)p + QDISC_ALIGN_CONST)
& ~QDISC_ALIGN_CONST);
sch->padded = (char *)sch - (char *)p;
INIT_LIST_HEAD(&sch->list);
skb_queue_head_init(&sch->q);
if (handle == TC_H_INGRESS) if (handle == TC_H_INGRESS) {
sch->flags |= TCQ_F_INGRESS; sch->flags |= TCQ_F_INGRESS;
handle = TC_H_MAKE(TC_H_INGRESS, 0);
sch->ops = ops; } else if (handle == 0) {
sch->enqueue = ops->enqueue;
sch->dequeue = ops->dequeue;
sch->dev = dev;
dev_hold(dev);
atomic_set(&sch->refcnt, 1);
sch->stats_lock = &dev->queue_lock;
if (handle == 0) {
handle = qdisc_alloc_handle(dev); handle = qdisc_alloc_handle(dev);
err = -ENOMEM; err = -ENOMEM;
if (handle == 0) if (handle == 0)
goto err_out3; goto err_out3;
} }
if (handle == TC_H_INGRESS) sch->handle = handle;
sch->handle =TC_H_MAKE(TC_H_INGRESS, 0);
else
sch->handle = handle;
if (!ops->init || (err = ops->init(sch, tca[TCA_OPTIONS-1])) == 0) { if (!ops->init || (err = ops->init(sch, tca[TCA_OPTIONS-1])) == 0) {
qdisc_lock_tree(dev); qdisc_lock_tree(dev);
...@@ -489,12 +467,11 @@ qdisc_create(struct net_device *dev, u32 handle, struct rtattr **tca, int *errp) ...@@ -489,12 +467,11 @@ qdisc_create(struct net_device *dev, u32 handle, struct rtattr **tca, int *errp)
} }
err_out3: err_out3:
dev_put(dev); dev_put(dev);
kfree((char *) sch - sch->padded);
err_out2: err_out2:
module_put(ops->owner); module_put(ops->owner);
err_out: err_out:
*errp = err; *errp = err;
if (p)
kfree(p);
return NULL; return NULL;
} }
......
...@@ -395,24 +395,23 @@ static struct Qdisc_ops pfifo_fast_ops = { ...@@ -395,24 +395,23 @@ static struct Qdisc_ops pfifo_fast_ops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
}; };
struct Qdisc * qdisc_create_dflt(struct net_device *dev, struct Qdisc_ops *ops) struct Qdisc *qdisc_alloc(struct net_device *dev, struct Qdisc_ops *ops)
{ {
void *p; void *p;
struct Qdisc *sch; struct Qdisc *sch;
int size; unsigned int size;
int err = -ENOBUFS;
/* ensure that the Qdisc and the private data are 32-byte aligned */ /* ensure that the Qdisc and the private data are 32-byte aligned */
size = ((sizeof(*sch) + QDISC_ALIGN_CONST) & ~QDISC_ALIGN_CONST); size = QDISC_ALIGN(sizeof(*sch));
size += ops->priv_size + QDISC_ALIGN_CONST; size += ops->priv_size + (QDISC_ALIGNTO - 1);
p = kmalloc(size, GFP_KERNEL); p = kmalloc(size, GFP_KERNEL);
if (!p) if (!p)
return NULL; goto errout;
memset(p, 0, size); memset(p, 0, size);
sch = (struct Qdisc *) QDISC_ALIGN((unsigned long) p);
sch = (struct Qdisc *)(((unsigned long)p + QDISC_ALIGN_CONST) sch->padded = (char *) sch - (char *) p;
& ~QDISC_ALIGN_CONST);
sch->padded = (char *)sch - (char *)p;
INIT_LIST_HEAD(&sch->list); INIT_LIST_HEAD(&sch->list);
skb_queue_head_init(&sch->q); skb_queue_head_init(&sch->q);
...@@ -423,11 +422,24 @@ struct Qdisc * qdisc_create_dflt(struct net_device *dev, struct Qdisc_ops *ops) ...@@ -423,11 +422,24 @@ struct Qdisc * qdisc_create_dflt(struct net_device *dev, struct Qdisc_ops *ops)
dev_hold(dev); dev_hold(dev);
sch->stats_lock = &dev->queue_lock; sch->stats_lock = &dev->queue_lock;
atomic_set(&sch->refcnt, 1); atomic_set(&sch->refcnt, 1);
return sch;
errout:
return ERR_PTR(-err);
}
struct Qdisc * qdisc_create_dflt(struct net_device *dev, struct Qdisc_ops *ops)
{
struct Qdisc *sch;
sch = qdisc_alloc(dev, ops);
if (IS_ERR(sch))
goto errout;
if (!ops->init || ops->init(sch, NULL) == 0) if (!ops->init || ops->init(sch, NULL) == 0)
return sch; return sch;
dev_put(dev); errout:
kfree(p);
return NULL; return NULL;
} }
...@@ -591,6 +603,7 @@ EXPORT_SYMBOL(__netdev_watchdog_up); ...@@ -591,6 +603,7 @@ EXPORT_SYMBOL(__netdev_watchdog_up);
EXPORT_SYMBOL(noop_qdisc); EXPORT_SYMBOL(noop_qdisc);
EXPORT_SYMBOL(noop_qdisc_ops); EXPORT_SYMBOL(noop_qdisc_ops);
EXPORT_SYMBOL(qdisc_create_dflt); EXPORT_SYMBOL(qdisc_create_dflt);
EXPORT_SYMBOL(qdisc_alloc);
EXPORT_SYMBOL(qdisc_destroy); EXPORT_SYMBOL(qdisc_destroy);
EXPORT_SYMBOL(qdisc_reset); EXPORT_SYMBOL(qdisc_reset);
EXPORT_SYMBOL(qdisc_restart); EXPORT_SYMBOL(qdisc_restart);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment