patch-2.3.40 linux/drivers/net/tokenring/olympic.c

Next file: linux/drivers/net/tokenring/olympic.h
Previous file: linux/drivers/net/tokenring/ibmtr.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.3.39/linux/drivers/net/tokenring/olympic.c linux/drivers/net/tokenring/olympic.c
@@ -25,10 +25,11 @@
  *  8/18/99 - Updated driver for 2.3.13 kernel to use new pci
  *	      resource. Driver also reports the card name returned by
  *            the pci resource.
+ *  1/11/00 - Added spinlocks for smp
  *  
  *  To Do:
  *
- *  Sanitize for smp
+ *  IPv6 Multicast
  *
  *  If Problems do Occur
  *  Most problems can be rectified by either closing and opening the interface
@@ -69,6 +70,7 @@
 #include <linux/stddef.h>
 #include <linux/init.h>
 #include <linux/pci.h>
+#include <linux/spinlock.h>
 #include <net/checksum.h>
 
 #include <asm/io.h>
@@ -86,7 +88,7 @@
  */
 
 static char *version = 
-"Olympic.c v0.3.0 8/18/99 - Peter De Schrijver & Mike Phillips" ; 
+"Olympic.c v0.3.1 1/11/00 - Peter De Schrijver & Mike Phillips" ; 
 
 static char *open_maj_error[]  = {"No error", "Lobe Media Test", "Physical Insertion",
 				   "Address Verification", "Neighbor Notification (Ring Poll)",
@@ -202,7 +204,6 @@
 
 			olympic_priv->olympic_ring_speed = ringspeed[card_no] ; 
 			olympic_priv->olympic_message_level = message_level[card_no] ; 
-			olympic_priv->olympic_multicast_set  = 0 ; 
 	
 			if(olympic_init(dev)==-1) {
 				unregister_netdevice(dev);
@@ -251,6 +252,8 @@
 		}
 	}
 
+	spin_lock_init(&olympic_priv->olympic_lock) ; 
+
 #if OLYMPIC_DEBUG
 	printk("BCTL: %x\n",readl(olympic_mmio+BCTL));
 	printk("GPR: %x\n",readw(olympic_mmio+GPR));
@@ -757,6 +760,8 @@
 	if (!(sisr & SISR_MI)) /* Interrupt isn't for us */ 
 		return ;
 
+	spin_lock(&olympic_priv->olympic_lock);
+
 	if (dev->interrupt) 
 		printk(KERN_WARNING "%s: Re-entering interrupt \n",dev->name) ; 
 
@@ -835,15 +840,20 @@
 	dev->interrupt = 0 ;  
 
 	writel(SISR_MI,olympic_mmio+SISR_MASK_SUM);
-
+	
+	spin_unlock(&olympic_priv->olympic_lock) ; 
 }	
 
 static int olympic_xmit(struct sk_buff *skb, struct net_device *dev) 
 {
 	struct olympic_private *olympic_priv=(struct olympic_private *)dev->priv;
-    __u8 *olympic_mmio=olympic_priv->olympic_mmio;
+	__u8 *olympic_mmio=olympic_priv->olympic_mmio;
+	unsigned long flags ; 
+
+	spin_lock_irqsave(&olympic_priv->olympic_lock, flags);
 
 	if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) {
+		spin_unlock_irqrestore(&olympic_priv->olympic_lock,flags);
 		return 1;
 	}
 
@@ -860,10 +870,12 @@
 		writew((((readw(olympic_mmio+TXENQ_1)) & 0x8000) ^ 0x8000) | 1,olympic_mmio+TXENQ_1);
 
 		dev->tbusy=0;		
-
+		spin_unlock_irqrestore(&olympic_priv->olympic_lock,flags);
 		return 0;
-	} else 
+	} else {
+		spin_unlock_irqrestore(&olympic_priv->olympic_lock,flags);
 		return 1;
+	} 
 
 }
 	
@@ -936,9 +948,11 @@
 {
 	struct olympic_private *olympic_priv = (struct olympic_private *) dev->priv ; 
    	__u8 *olympic_mmio = olympic_priv->olympic_mmio ; 
-	__u8 options = 0, set_mc_list = 0 ; 
-	__u8 *srb, *ata ;
+	__u8 options = 0; 
+	__u8 *srb;
 	struct dev_mc_list *dmi ; 
+	unsigned char dev_mc_address[4] ; 
+	int i ; 
 
 	writel(olympic_priv->srb,olympic_mmio+LAPA);
 	srb=olympic_priv->olympic_lap + (olympic_priv->srb & (~0xf800));
@@ -949,10 +963,6 @@
 	else
 		options &= ~(3<<5) ; 
 
-	if (dev->mc_count) {  
-		set_mc_list = 1 ; 
-	}
-
 	/* Only issue the srb if there is a change in options */
 
 	if ((options ^ olympic_priv->olympic_copy_all_options)) { 
@@ -975,60 +985,30 @@
 		return ;  
 	} 
 
-	if (set_mc_list ^ olympic_priv->olympic_multicast_set) { /* Multicast options have changed */ 
-
-		dmi = dev->mc_list ; 
+	/* Set the functional addresses we need for multicast */
 
-		if (set_mc_list) { /* Turn multicast on */
-
-			/* RFC 1469 Says we must support using the functional address C0 00 00 04 00 00
-                         * We do this with a set functional address mask.
-			 */
-						
-			ata=olympic_priv->olympic_lap + (olympic_priv->olympic_addr_table_addr) ;
-			if (!(readb(ata+11) & 0x04)) { /* Hmmm, need to set the functional mask */ 
-				writeb(SRB_SET_FUNC_ADDRESS,srb+0);
-				writeb(0,srb+1);
-				writeb(OLYMPIC_CLEAR_RET_CODE,srb+2);
-				writeb(0,srb+3);
-				writeb(0,srb+4);
-				writeb(0,srb+5);
-				writeb(readb(ata+10),srb+6);
-				writeb(readb(ata+11)|4,srb+7);
-				writeb(readb(ata+12),srb+8);
-				writeb(readb(ata+13),srb+9);
-			
-				olympic_priv->srb_queued = 2 ; 
-				writel(LISR_SRB_CMD,olympic_mmio+LISR_SUM);
-
-				olympic_priv->olympic_multicast_set = 1 ;  
-			}    
-
-
-		} else { /* Turn multicast off */
-	
-			ata=olympic_priv->olympic_lap + (olympic_priv->olympic_addr_table_addr) ;
-			if ((readb(ata+11) & 0x04)) { /* Hmmm, need to reset the functional mask */ 
-				writeb(SRB_SET_FUNC_ADDRESS,srb+0);
-				writeb(0,srb+1);
-				writeb(OLYMPIC_CLEAR_RET_CODE,srb+2);
-				writeb(0,srb+3);
-				writeb(0,srb+4);
-				writeb(0,srb+5);
-				writeb(readb(ata+10),srb+6);
-				writeb(readb(ata+11) & ~4,srb+7);
-				writeb(readb(ata+12),srb+8);
-				writeb(readb(ata+13),srb+9);
-			
-				olympic_priv->srb_queued = 2 ; 
-				writel(LISR_SRB_CMD,olympic_mmio+LISR_SUM);	
-
-				olympic_priv->olympic_multicast_set = 0 ; 
-			}
-		} 		
+	dev_mc_address[0] = dev_mc_address[1] = dev_mc_address[2] = dev_mc_address[3] = 0 ; 
 
+	for (i=0,dmi=dev->mc_list;i < dev->mc_count; i++,dmi = dmi->next) { 
+		dev_mc_address[0] |= dmi->dmi_addr[2] ; 
+		dev_mc_address[1] |= dmi->dmi_addr[3] ; 
+		dev_mc_address[2] |= dmi->dmi_addr[4] ; 
+		dev_mc_address[3] |= dmi->dmi_addr[5] ; 
 	}
 
+	writeb(SRB_SET_FUNC_ADDRESS,srb+0);
+	writeb(0,srb+1);
+	writeb(OLYMPIC_CLEAR_RET_CODE,srb+2);
+	writeb(0,srb+3);
+	writeb(0,srb+4);
+	writeb(0,srb+5);
+	writeb(dev_mc_address[0],srb+6);
+	writeb(dev_mc_address[1],srb+7);
+	writeb(dev_mc_address[2],srb+8);
+	writeb(dev_mc_address[3],srb+9);
+
+	olympic_priv->srb_queued = 2 ;
+	writel(LISR_SRB_CMD,olympic_mmio+LISR_SUM);
 
 }
 
@@ -1069,7 +1049,6 @@
 		case SRB_SET_GROUP_ADDRESS:
 			switch (readb(srb+2)) { 
 				case 0x00:
-					olympic_priv->olympic_multicast_set = 1 ; 
 					break ; 
 				case 0x01:
 					printk(KERN_WARNING "%s: Unrecognized srb command \n",dev->name) ; 
@@ -1097,7 +1076,6 @@
 		case SRB_RESET_GROUP_ADDRESS:
 			switch (readb(srb+2)) { 
 				case 0x00:
-					olympic_priv->olympic_multicast_set = 0 ; 
 					break ; 
 				case 0x01:
 					printk(KERN_WARNING "%s: Unrecognized srb command \n",dev->name) ; 

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