aboutsummaryrefslogtreecommitdiffstats
path: root/net/sched
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2008-07-16 05:15:04 -0400
committerDavid S. Miller <davem@davemloft.net>2008-07-17 22:21:20 -0400
commit37437bb2e1ae8af470dfcd5b4ff454110894ccaf (patch)
tree1795e78a7648252b0c92c972df12b776a28437d7 /net/sched
parent7698b4fcabcd790efc4f226bada1e7b5870653af (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.c3
-rw-r--r--net/sched/sch_cbq.c2
-rw-r--r--net/sched/sch_generic.c30
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
75static inline int dev_requeue_skb(struct sk_buff *skb, 75static 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 */
149static inline int qdisc_restart(struct netdev_queue *txq, 147static 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
199void __qdisc_run(struct netdev_queue *txq) 201void __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 }