patch-2.2.3 linux/drivers/net/shaper.c
Next file: linux/drivers/net/sk_g16.c
Previous file: linux/drivers/net/plip.c
Back to the patch index
Back to the overall index
- Lines: 160
- Date:
Wed Feb 24 16:27:53 1999
- Orig file:
v2.2.2/linux/drivers/net/shaper.c
- Orig date:
Thu Nov 19 09:56:28 1998
diff -u --recursive --new-file v2.2.2/linux/drivers/net/shaper.c linux/drivers/net/shaper.c
@@ -53,6 +53,13 @@
* This will be fixed in BETA4
*/
+/*
+ * bh_atomic() SMP races fixes and rewritten the locking code to be SMP safe
+ * and irq-mask friendly. NOTE: we can't use start_bh_atomic() in kick_shaper()
+ * because it's going to be recalled from an irq handler, and synchronize_bh()
+ * is a nono if called from irq context.
+ * 1999 Andrea Arcangeli
+ */
#include <linux/module.h>
#include <linux/kernel.h>
@@ -83,21 +90,17 @@
static int shaper_lock(struct shaper *sh)
{
- unsigned long flags;
- save_flags(flags);
- cli();
/*
- * Lock in an interrupt may fail
+ * Lock in an interrupt must fail
*/
- if(sh->locked && in_interrupt())
+ while (test_and_set_bit(0, &sh->locked))
{
- restore_flags(flags);
- return 0;
+ if (!in_interrupt())
+ sleep_on(&sh->wait_queue);
+ else
+ return 0;
+
}
- while(sh->locked)
- sleep_on(&sh->wait_queue);
- sh->locked=1;
- restore_flags(flags);
return 1;
}
@@ -105,7 +108,7 @@
static void shaper_unlock(struct shaper *sh)
{
- sh->locked=0;
+ clear_bit(0, &sh->locked);
wake_up(&sh->wait_queue);
shaper_kick(sh);
}
@@ -240,7 +243,6 @@
dev_kfree_skb(ptr);
}
shaper_unlock(shaper);
- shaper_kick(shaper);
return 0;
}
@@ -285,24 +287,16 @@
static void shaper_kick(struct shaper *shaper)
{
struct sk_buff *skb;
- unsigned long flags;
- save_flags(flags);
- cli();
-
- del_timer(&shaper->timer);
-
/*
* Shaper unlock will kick
*/
- if(shaper->locked)
- {
+ if (test_and_set_bit(0, &shaper->locked))
+ {
if(sh_debug)
printk("Shaper locked.\n");
- shaper->timer.expires=jiffies+1;
- add_timer(&shaper->timer);
- restore_flags(flags);
+ mod_timer(&shaper->timer, jiffies);
return;
}
@@ -320,7 +314,7 @@
if(sh_debug)
printk("Clock = %d, jiffies = %ld\n", skb->shapeclock, jiffies);
- if(skb->shapeclock - jiffies <= SHAPER_BURST)
+ if(time_before_eq(skb->shapeclock - jiffies, SHAPER_BURST))
{
/*
* Pull the frame and get interrupts back on.
@@ -329,8 +323,6 @@
skb_unlink(skb);
if (shaper->recovery < skb->shapeclock + skb->shapelen)
shaper->recovery = skb->shapeclock + skb->shapelen;
- restore_flags(flags);
-
/*
* Pass on to the physical target device via
* our low level packet thrower.
@@ -338,7 +330,6 @@
skb->shapepend=0;
shaper_queue_xmit(shaper, skb); /* Fire */
- cli();
}
else
break;
@@ -349,17 +340,9 @@
*/
if(skb!=NULL)
- {
- del_timer(&shaper->timer);
- shaper->timer.expires=skb->shapeclock;
- add_timer(&shaper->timer);
- }
-
- /*
- * Interrupts on, mission complete
- */
-
- restore_flags(flags);
+ mod_timer(&shaper->timer, skb->shapeclock);
+
+ clear_bit(0, &shaper->locked);
}
@@ -370,8 +353,14 @@
static void shaper_flush(struct shaper *shaper)
{
struct sk_buff *skb;
+ if(!shaper_lock(shaper))
+ {
+ printk(KERN_ERR "shaper: shaper_flush() called by an irq!\n");
+ return;
+ }
while((skb=skb_dequeue(&shaper->sendq))!=NULL)
dev_kfree_skb(skb);
+ shaper_unlock(shaper);
}
/*
@@ -405,7 +394,9 @@
{
struct shaper *shaper=dev->priv;
shaper_flush(shaper);
+ start_bh_atomic();
del_timer(&shaper->timer);
+ end_bh_atomic();
MOD_DEC_USE_COUNT;
return 0;
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)