patch-2.3.40 linux/drivers/net/3c527.c

Next file: linux/drivers/net/Config.in
Previous file: linux/drivers/net/3c509.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.3.39/linux/drivers/net/3c527.c linux/drivers/net/3c527.c
@@ -16,7 +16,7 @@
  */
 
 static const char *version =
-	"3c527.c:v0.05 1999/09/06 Alan Cox (alan@redhat.com)\n";
+	"3c527.c:v0.07 2000/01/18 Alan Cox (alan@redhat.com)\n";
 
 /*
  *	Things you need
@@ -447,10 +447,22 @@
 
 
 /*
- *	Send exec commands
+ *	Send exec commands. This requires a bit of explaining.
+ *
+ *	You feed the card a command, you wait, it interrupts you get a 
+ *	reply. All well and good. The complication arises because you use
+ *	commands for filter list changes which come in at bh level from things
+ *	like IPV6 group stuff.
+ *
+ *	We have a simple state machine
+ *
+ *	0	- nothing issued
+ *	1	- command issued, wait reply
+ *	2	- reply waiting - reader then goes to state 0
+ *	3	- command issued, trash reply. In which case the irq
+ *		  takes it back to state 0
  */
 
-
 /*
  *	Send command from interrupt state
  */
@@ -463,7 +475,7 @@
 	if(lp->exec_pending)
 		return -1;
 		
-	lp->exec_pending=1;
+	lp->exec_pending=3;
 	lp->exec_box->mbox=0;
 	lp->exec_box->mbox=cmd;
 	memcpy((void *)lp->exec_box->data, data, len);
@@ -492,6 +504,9 @@
 	 *	Wait for a command
 	 */
 	 
+	save_flags(flags);
+	cli();
+	 
 	while(lp->exec_pending)
 		sleep_on(&lp->event);
 		
@@ -500,6 +515,9 @@
 	 */
 
 	lp->exec_pending=1;
+	
+	restore_flags(flags);
+	
 	lp->exec_box->mbox=0;
 	lp->exec_box->mbox=cmd;
 	memcpy((void *)lp->exec_box->data, data, len);
@@ -826,6 +844,10 @@
 		wmb();
 		
 		np->length	= skb->len;
+		
+		if(np->length < 60)
+			np->length = 60;
+			
 		np->data	= virt_to_bus(skb->data);
 		np->status	= 0;
 		np->control	= (1<<7)|(1<<6);	/* EOP EOL */
@@ -1015,8 +1037,11 @@
 		status>>=3;
 		if(status&1)
 		{
-			/* 0=no 1=yes 2=reply clearing */
-			lp->exec_pending=2;
+			/* 0=no 1=yes 2=replied, get cmd, 3 = wait reply & dump it */
+			if(lp->exec_pending!=3)
+				lp->exec_pending=2;
+			else
+				lp->exec_pending=0;
 			wake_up(&lp->event);
 		}
 		if(status&2)

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)