diff options
author | David S. Miller <davem@davemloft.net> | 2008-07-16 05:15:04 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-07-17 22:21:20 -0400 |
commit | 37437bb2e1ae8af470dfcd5b4ff454110894ccaf (patch) | |
tree | 1795e78a7648252b0c92c972df12b776a28437d7 /net/sched | |
parent | 7698b4fcabcd790efc4f226bada1e7b5870653af (diff) |
pkt_sched: Schedule qdiscs instead of netdev_queue.
When we have shared qdiscs, packets come out of the qdiscs
for multiple transmit queues.
Therefore it doesn't make any sense to schedule the transmit
queue when logically we cannot know ahead of time the TX
queue of the SKB that the qdisc->dequeue() will give us.
Just for sanity I added a BUG check to make sure we never
get into a state where the noop_qdisc is scheduled.
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/sched')
-rw-r--r-- | net/sched/sch_api.c | 3 | ||||
-rw-r--r-- | net/sched/sch_cbq.c | 2 | ||||
-rw-r--r-- | net/sched/sch_generic.c | 30 |
3 files changed, 16 insertions, 19 deletions
diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c index 19c244a00839..8e8c5becc348 100644 --- a/net/sched/sch_api.c +++ b/net/sched/sch_api.c | |||
@@ -294,11 +294,10 @@ static enum hrtimer_restart qdisc_watchdog(struct hrtimer *timer) | |||
294 | { | 294 | { |
295 | struct qdisc_watchdog *wd = container_of(timer, struct qdisc_watchdog, | 295 | struct qdisc_watchdog *wd = container_of(timer, struct qdisc_watchdog, |
296 | timer); | 296 | timer); |
297 | struct netdev_queue *txq = wd->qdisc->dev_queue; | ||
298 | 297 | ||
299 | wd->qdisc->flags &= ~TCQ_F_THROTTLED; | 298 | wd->qdisc->flags &= ~TCQ_F_THROTTLED; |
300 | smp_wmb(); | 299 | smp_wmb(); |
301 | netif_schedule_queue(txq); | 300 | __netif_schedule(wd->qdisc); |
302 | 301 | ||
303 | return HRTIMER_NORESTART; | 302 | return HRTIMER_NORESTART; |
304 | } | 303 | } |
diff --git a/net/sched/sch_cbq.c b/net/sched/sch_cbq.c index 37ae653db683..a3953bbe2d79 100644 --- a/net/sched/sch_cbq.c +++ b/net/sched/sch_cbq.c | |||
@@ -650,7 +650,7 @@ static enum hrtimer_restart cbq_undelay(struct hrtimer *timer) | |||
650 | } | 650 | } |
651 | 651 | ||
652 | sch->flags &= ~TCQ_F_THROTTLED; | 652 | sch->flags &= ~TCQ_F_THROTTLED; |
653 | netif_schedule_queue(sch->dev_queue); | 653 | __netif_schedule(sch); |
654 | return HRTIMER_NORESTART; | 654 | return HRTIMER_NORESTART; |
655 | } | 655 | } |
656 | 656 | ||
diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c index 739a8711ab30..dd5c4e70abe4 100644 --- a/net/sched/sch_generic.c +++ b/net/sched/sch_generic.c | |||
@@ -72,16 +72,14 @@ static inline int qdisc_qlen(struct Qdisc *q) | |||
72 | return q->q.qlen; | 72 | return q->q.qlen; |
73 | } | 73 | } |
74 | 74 | ||
75 | static inline int dev_requeue_skb(struct sk_buff *skb, | 75 | static inline int dev_requeue_skb(struct sk_buff *skb, struct Qdisc *q) |
76 | struct netdev_queue *dev_queue, | ||
77 | struct Qdisc *q) | ||
78 | { | 76 | { |
79 | if (unlikely(skb->next)) | 77 | if (unlikely(skb->next)) |
80 | q->gso_skb = skb; | 78 | q->gso_skb = skb; |
81 | else | 79 | else |
82 | q->ops->requeue(skb, q); | 80 | q->ops->requeue(skb, q); |
83 | 81 | ||
84 | netif_schedule_queue(dev_queue); | 82 | __netif_schedule(q); |
85 | return 0; | 83 | return 0; |
86 | } | 84 | } |
87 | 85 | ||
@@ -121,7 +119,7 @@ static inline int handle_dev_cpu_collision(struct sk_buff *skb, | |||
121 | * some time. | 119 | * some time. |
122 | */ | 120 | */ |
123 | __get_cpu_var(netdev_rx_stat).cpu_collision++; | 121 | __get_cpu_var(netdev_rx_stat).cpu_collision++; |
124 | ret = dev_requeue_skb(skb, dev_queue, q); | 122 | ret = dev_requeue_skb(skb, q); |
125 | } | 123 | } |
126 | 124 | ||
127 | return ret; | 125 | return ret; |
@@ -146,9 +144,9 @@ static inline int handle_dev_cpu_collision(struct sk_buff *skb, | |||
146 | * >0 - queue is not empty. | 144 | * >0 - queue is not empty. |
147 | * | 145 | * |
148 | */ | 146 | */ |
149 | static inline int qdisc_restart(struct netdev_queue *txq, | 147 | static inline int qdisc_restart(struct Qdisc *q) |
150 | struct Qdisc *q) | ||
151 | { | 148 | { |
149 | struct netdev_queue *txq; | ||
152 | int ret = NETDEV_TX_BUSY; | 150 | int ret = NETDEV_TX_BUSY; |
153 | struct net_device *dev; | 151 | struct net_device *dev; |
154 | spinlock_t *root_lock; | 152 | spinlock_t *root_lock; |
@@ -163,7 +161,8 @@ static inline int qdisc_restart(struct netdev_queue *txq, | |||
163 | /* And release qdisc */ | 161 | /* And release qdisc */ |
164 | spin_unlock(root_lock); | 162 | spin_unlock(root_lock); |
165 | 163 | ||
166 | dev = txq->dev; | 164 | dev = qdisc_dev(q); |
165 | txq = netdev_get_tx_queue(dev, skb_get_queue_mapping(skb)); | ||
167 | 166 | ||
168 | HARD_TX_LOCK(dev, txq, smp_processor_id()); | 167 | HARD_TX_LOCK(dev, txq, smp_processor_id()); |
169 | if (!netif_subqueue_stopped(dev, skb)) | 168 | if (!netif_subqueue_stopped(dev, skb)) |
@@ -189,29 +188,28 @@ static inline int qdisc_restart(struct netdev_queue *txq, | |||
189 | printk(KERN_WARNING "BUG %s code %d qlen %d\n", | 188 | printk(KERN_WARNING "BUG %s code %d qlen %d\n", |
190 | dev->name, ret, q->q.qlen); | 189 | dev->name, ret, q->q.qlen); |
191 | 190 | ||
192 | ret = dev_requeue_skb(skb, txq, q); | 191 | ret = dev_requeue_skb(skb, q); |
193 | break; | 192 | break; |
194 | } | 193 | } |
195 | 194 | ||
195 | if (ret && netif_tx_queue_stopped(txq)) | ||
196 | ret = 0; | ||
197 | |||
196 | return ret; | 198 | return ret; |
197 | } | 199 | } |
198 | 200 | ||
199 | void __qdisc_run(struct netdev_queue *txq) | 201 | void __qdisc_run(struct Qdisc *q) |
200 | { | 202 | { |
201 | unsigned long start_time = jiffies; | 203 | unsigned long start_time = jiffies; |
202 | struct Qdisc *q = txq->qdisc; | ||
203 | |||
204 | while (qdisc_restart(txq, q)) { | ||
205 | if (netif_tx_queue_stopped(txq)) | ||
206 | break; | ||
207 | 204 | ||
205 | while (qdisc_restart(q)) { | ||
208 | /* | 206 | /* |
209 | * Postpone processing if | 207 | * Postpone processing if |
210 | * 1. another process needs the CPU; | 208 | * 1. another process needs the CPU; |
211 | * 2. we've been doing it for too long. | 209 | * 2. we've been doing it for too long. |
212 | */ | 210 | */ |
213 | if (need_resched() || jiffies != start_time) { | 211 | if (need_resched() || jiffies != start_time) { |
214 | netif_schedule_queue(txq); | 212 | __netif_schedule(q); |
215 | break; | 213 | break; |
216 | } | 214 | } |
217 | } | 215 | } |