aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@lst.de>2005-06-02 19:36:00 -0400
committerDavid S. Miller <davem@davemloft.net>2005-06-02 19:36:00 -0400
commitb597ef4712c05c962640a655386a7f06cc1a1fbc (patch)
treeaf2a1822d63cf447dd6e9b58808ea22341c85955 /drivers/net
parent4fef0304eeaa4156db5625e3578f92ed94645a43 (diff)
[NET]: Fix locking in shaper driver.
o use a semaphore instead of an opencoded and racy lock o move locking out of shaper_kick and into the callers - most just released the lock before calling shaper_kick o remove in_interrupt() tests. from ->close we can always block, from ->hard_start_xmit and timer context never Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/shaper.c86
1 files changed, 19 insertions, 67 deletions
diff --git a/drivers/net/shaper.c b/drivers/net/shaper.c
index e68cf5fb4920..20edeb345792 100644
--- a/drivers/net/shaper.c
+++ b/drivers/net/shaper.c
@@ -100,35 +100,8 @@ static int sh_debug; /* Debug flag */
100 100
101#define SHAPER_BANNER "CymruNet Traffic Shaper BETA 0.04 for Linux 2.1\n" 101#define SHAPER_BANNER "CymruNet Traffic Shaper BETA 0.04 for Linux 2.1\n"
102 102
103/*
104 * Locking
105 */
106
107static int shaper_lock(struct shaper *sh)
108{
109 /*
110 * Lock in an interrupt must fail
111 */
112 while (test_and_set_bit(0, &sh->locked))
113 {
114 if (!in_interrupt())
115 sleep_on(&sh->wait_queue);
116 else
117 return 0;
118
119 }
120 return 1;
121}
122
123static void shaper_kick(struct shaper *sh); 103static void shaper_kick(struct shaper *sh);
124 104
125static void shaper_unlock(struct shaper *sh)
126{
127 clear_bit(0, &sh->locked);
128 wake_up(&sh->wait_queue);
129 shaper_kick(sh);
130}
131
132/* 105/*
133 * Compute clocks on a buffer 106 * Compute clocks on a buffer
134 */ 107 */
@@ -157,17 +130,15 @@ static void shaper_setspeed(struct shaper *shaper, int bitspersec)
157 * Throw a frame at a shaper. 130 * Throw a frame at a shaper.
158 */ 131 */
159 132
160static int shaper_qframe(struct shaper *shaper, struct sk_buff *skb) 133
134static int shaper_start_xmit(struct sk_buff *skb, struct net_device *dev)
161{ 135{
136 struct shaper *shaper = dev->priv;
162 struct sk_buff *ptr; 137 struct sk_buff *ptr;
163 138
164 /* 139 if (down_trylock(&shaper->sem))
165 * Get ready to work on this shaper. Lock may fail if its 140 return -1;
166 * an interrupt and locked. 141
167 */
168
169 if(!shaper_lock(shaper))
170 return -1;
171 ptr=shaper->sendq.prev; 142 ptr=shaper->sendq.prev;
172 143
173 /* 144 /*
@@ -260,7 +231,8 @@ static int shaper_qframe(struct shaper *shaper, struct sk_buff *skb)
260 dev_kfree_skb(ptr); 231 dev_kfree_skb(ptr);
261 shaper->stats.collisions++; 232 shaper->stats.collisions++;
262 } 233 }
263 shaper_unlock(shaper); 234 shaper_kick(shaper);
235 up(&shaper->sem);
264 return 0; 236 return 0;
265} 237}
266 238
@@ -297,8 +269,13 @@ static void shaper_queue_xmit(struct shaper *shaper, struct sk_buff *skb)
297 269
298static void shaper_timer(unsigned long data) 270static void shaper_timer(unsigned long data)
299{ 271{
300 struct shaper *sh=(struct shaper *)data; 272 struct shaper *shaper = (struct shaper *)data;
301 shaper_kick(sh); 273
274 if (!down_trylock(&shaper->sem)) {
275 shaper_kick(shaper);
276 up(&shaper->sem);
277 } else
278 mod_timer(&shaper->timer, jiffies);
302} 279}
303 280
304/* 281/*
@@ -311,19 +288,6 @@ static void shaper_kick(struct shaper *shaper)
311 struct sk_buff *skb; 288 struct sk_buff *skb;
312 289
313 /* 290 /*
314 * Shaper unlock will kick
315 */
316
317 if (test_and_set_bit(0, &shaper->locked))
318 {
319 if(sh_debug)
320 printk("Shaper locked.\n");
321 mod_timer(&shaper->timer, jiffies);
322 return;
323 }
324
325
326 /*
327 * Walk the list (may be empty) 291 * Walk the list (may be empty)
328 */ 292 */
329 293
@@ -364,8 +328,6 @@ static void shaper_kick(struct shaper *shaper)
364 328
365 if(skb!=NULL) 329 if(skb!=NULL)
366 mod_timer(&shaper->timer, SHAPERCB(skb)->shapeclock); 330 mod_timer(&shaper->timer, SHAPERCB(skb)->shapeclock);
367
368 clear_bit(0, &shaper->locked);
369} 331}
370 332
371 333
@@ -376,14 +338,12 @@ static void shaper_kick(struct shaper *shaper)
376static void shaper_flush(struct shaper *shaper) 338static void shaper_flush(struct shaper *shaper)
377{ 339{
378 struct sk_buff *skb; 340 struct sk_buff *skb;
379 if(!shaper_lock(shaper)) 341
380 { 342 down(&shaper->sem);
381 printk(KERN_ERR "shaper: shaper_flush() called by an irq!\n");
382 return;
383 }
384 while((skb=skb_dequeue(&shaper->sendq))!=NULL) 343 while((skb=skb_dequeue(&shaper->sendq))!=NULL)
385 dev_kfree_skb(skb); 344 dev_kfree_skb(skb);
386 shaper_unlock(shaper); 345 shaper_kick(shaper);
346 up(&shaper->sem);
387} 347}
388 348
389/* 349/*
@@ -426,13 +386,6 @@ static int shaper_close(struct net_device *dev)
426 * ARP and other resolutions and not before. 386 * ARP and other resolutions and not before.
427 */ 387 */
428 388
429
430static int shaper_start_xmit(struct sk_buff *skb, struct net_device *dev)
431{
432 struct shaper *sh=dev->priv;
433 return shaper_qframe(sh, skb);
434}
435
436static struct net_device_stats *shaper_get_stats(struct net_device *dev) 389static struct net_device_stats *shaper_get_stats(struct net_device *dev)
437{ 390{
438 struct shaper *sh=dev->priv; 391 struct shaper *sh=dev->priv;
@@ -623,7 +576,6 @@ static void shaper_init_priv(struct net_device *dev)
623 init_timer(&sh->timer); 576 init_timer(&sh->timer);
624 sh->timer.function=shaper_timer; 577 sh->timer.function=shaper_timer;
625 sh->timer.data=(unsigned long)sh; 578 sh->timer.data=(unsigned long)sh;
626 init_waitqueue_head(&sh->wait_queue);
627} 579}
628 580
629/* 581/*