aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/networking/multiqueue.txt14
-rw-r--r--net/sched/sch_multiq.c13
2 files changed, 16 insertions, 11 deletions
diff --git a/Documentation/networking/multiqueue.txt b/Documentation/networking/multiqueue.txt
index 8c2b06b77f61..4caa0e314cc2 100644
--- a/Documentation/networking/multiqueue.txt
+++ b/Documentation/networking/multiqueue.txt
@@ -29,15 +29,15 @@ Section 2: Qdisc support for multiqueue devices
29 29
30----------------------------------------------- 30-----------------------------------------------
31 31
32Currently two qdiscs support multiqueue devices. The first is the default 32Currently two qdiscs are optimized for multiqueue devices. The first is the
33pfifo_fast qdisc. This qdisc supports one qdisc per hardware queue. A new 33default pfifo_fast qdisc. This qdisc supports one qdisc per hardware queue.
34round-robin qdisc, sch_multiq also supports multiple hardware queues. The 34A new round-robin qdisc, sch_multiq also supports multiple hardware queues. The
35qdisc is responsible for classifying the skb's and then directing the skb's to 35qdisc is responsible for classifying the skb's and then directing the skb's to
36bands and queues based on the value in skb->queue_mapping. Use this field in 36bands and queues based on the value in skb->queue_mapping. Use this field in
37the base driver to determine which queue to send the skb to. 37the base driver to determine which queue to send the skb to.
38 38
39sch_multiq has been added for hardware that wishes to avoid unnecessary 39sch_multiq has been added for hardware that wishes to avoid head-of-line
40requeuing. It will cycle though the bands and verify that the hardware queue 40blocking. It will cycle though the bands and verify that the hardware queue
41associated with the band is not stopped prior to dequeuing a packet. 41associated with the band is not stopped prior to dequeuing a packet.
42 42
43On qdisc load, the number of bands is based on the number of queues on the 43On qdisc load, the number of bands is based on the number of queues on the
@@ -63,8 +63,8 @@ band 1 => queue 1
63band 2 => queue 2 63band 2 => queue 2
64band 3 => queue 3 64band 3 => queue 3
65 65
66Traffic will begin flowing through each queue if your base device has either 66Traffic will begin flowing through each queue based on either the simple_tx_hash
67the default simple_tx_hash or a custom netdev->select_queue() defined. 67function or based on netdev->select_queue() if you have it defined.
68 68
69The behavior of tc filters remains the same. However a new tc action, 69The behavior of tc filters remains the same. However a new tc action,
70skbedit, has been added. Assuming you wanted to route all traffic to a 70skbedit, has been added. Assuming you wanted to route all traffic to a
diff --git a/net/sched/sch_multiq.c b/net/sched/sch_multiq.c
index 49a8b67ed3b8..5d9cd68e91d1 100644
--- a/net/sched/sch_multiq.c
+++ b/net/sched/sch_multiq.c
@@ -214,8 +214,8 @@ static int multiq_tune(struct Qdisc *sch, struct nlattr *opt)
214 sch_tree_lock(sch); 214 sch_tree_lock(sch);
215 q->bands = qopt->bands; 215 q->bands = qopt->bands;
216 for (i = q->bands; i < q->max_bands; i++) { 216 for (i = q->bands; i < q->max_bands; i++) {
217 struct Qdisc *child = xchg(&q->queues[i], &noop_qdisc); 217 if (q->queues[i] != &noop_qdisc) {
218 if (child != &noop_qdisc) { 218 struct Qdisc *child = xchg(&q->queues[i], &noop_qdisc);
219 qdisc_tree_decrease_qlen(child, child->q.qlen); 219 qdisc_tree_decrease_qlen(child, child->q.qlen);
220 qdisc_destroy(child); 220 qdisc_destroy(child);
221 } 221 }
@@ -250,7 +250,7 @@ static int multiq_tune(struct Qdisc *sch, struct nlattr *opt)
250static int multiq_init(struct Qdisc *sch, struct nlattr *opt) 250static int multiq_init(struct Qdisc *sch, struct nlattr *opt)
251{ 251{
252 struct multiq_sched_data *q = qdisc_priv(sch); 252 struct multiq_sched_data *q = qdisc_priv(sch);
253 int i; 253 int i, err;
254 254
255 q->queues = NULL; 255 q->queues = NULL;
256 256
@@ -265,7 +265,12 @@ static int multiq_init(struct Qdisc *sch, struct nlattr *opt)
265 for (i = 0; i < q->max_bands; i++) 265 for (i = 0; i < q->max_bands; i++)
266 q->queues[i] = &noop_qdisc; 266 q->queues[i] = &noop_qdisc;
267 267
268 return multiq_tune(sch, opt); 268 err = multiq_tune(sch,opt);
269
270 if (err)
271 kfree(q->queues);
272
273 return err;
269} 274}
270 275
271static int multiq_dump(struct Qdisc *sch, struct sk_buff *skb) 276static int multiq_dump(struct Qdisc *sch, struct sk_buff *skb)