152 lines
		
	
	
		
			4.1 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			152 lines
		
	
	
		
			4.1 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
--- a/drivers/net/r6040.c
 | 
						|
+++ b/drivers/net/r6040.c
 | 
						|
@@ -70,6 +70,8 @@
 | 
						|
 
 | 
						|
 /* MAC registers */
 | 
						|
 #define MCR0		0x00	/* Control register 0 */
 | 
						|
+#define  PROMISC	0x0020	/* Promiscuous mode */
 | 
						|
+#define  HASH_EN	0x0100	/* Enable multicast hash table function */
 | 
						|
 #define MCR1		0x04	/* Control register 1 */
 | 
						|
 #define  MAC_RST	0x0001	/* Reset the MAC */
 | 
						|
 #define MBCR		0x08	/* Bus control */
 | 
						|
@@ -837,76 +839,96 @@
 | 
						|
 {
 | 
						|
 	struct r6040_private *lp = netdev_priv(dev);
 | 
						|
 	void __iomem *ioaddr = lp->base;
 | 
						|
-	u16 *adrp;
 | 
						|
-	u16 reg;
 | 
						|
 	unsigned long flags;
 | 
						|
 	struct dev_mc_list *dmi = dev->mc_list;
 | 
						|
 	int i;
 | 
						|
+	u16 *adrp;
 | 
						|
+	u16 hash_table[4] = { 0 };
 | 
						|
+
 | 
						|
+	spin_lock_irqsave(&lp->lock, flags);
 | 
						|
 
 | 
						|
-	/* MAC Address */
 | 
						|
+	/* Keep our MAC Address */
 | 
						|
 	adrp = (u16 *)dev->dev_addr;
 | 
						|
 	iowrite16(adrp[0], ioaddr + MID_0L);
 | 
						|
 	iowrite16(adrp[1], ioaddr + MID_0M);
 | 
						|
 	iowrite16(adrp[2], ioaddr + MID_0H);
 | 
						|
 
 | 
						|
-	/* Promiscous Mode */
 | 
						|
-	spin_lock_irqsave(&lp->lock, flags);
 | 
						|
-
 | 
						|
 	/* Clear AMCP & PROM bits */
 | 
						|
-	reg = ioread16(ioaddr) & ~0x0120;
 | 
						|
+	lp->mcr0 = ioread16(ioaddr + MCR0) & ~(PROMISC | HASH_EN);
 | 
						|
+
 | 
						|
+	/* Promiscuous mode */
 | 
						|
 	if (dev->flags & IFF_PROMISC) {
 | 
						|
-		reg |= 0x0020;
 | 
						|
-		lp->mcr0 |= 0x0020;
 | 
						|
+		lp->mcr0 |= PROMISC;
 | 
						|
 	}
 | 
						|
-	/* Too many multicast addresses
 | 
						|
-	 * accept all traffic */
 | 
						|
-	else if ((dev->mc_count > MCAST_MAX)
 | 
						|
-		|| (dev->flags & IFF_ALLMULTI))
 | 
						|
-		reg |= 0x0020;
 | 
						|
 
 | 
						|
-	iowrite16(reg, ioaddr);
 | 
						|
-	spin_unlock_irqrestore(&lp->lock, flags);
 | 
						|
-
 | 
						|
-	/* Build the hash table */
 | 
						|
-	if (dev->mc_count > MCAST_MAX) {
 | 
						|
-		u16 hash_table[4];
 | 
						|
-		u32 crc;
 | 
						|
+	/* Enable multicast hash table function to
 | 
						|
+	 * receive all multicast packets. */
 | 
						|
+	else if (dev->flags & IFF_ALLMULTI) {
 | 
						|
+		lp->mcr0 |= HASH_EN;
 | 
						|
+
 | 
						|
+		for (i = 0; i < MCAST_MAX ; i++) {
 | 
						|
+			iowrite16(0, ioaddr + MID_1L + 8 * i);
 | 
						|
+			iowrite16(0, ioaddr + MID_1M + 8 * i);
 | 
						|
+			iowrite16(0, ioaddr + MID_1H + 8 * i);
 | 
						|
+		}
 | 
						|
 
 | 
						|
 		for (i = 0; i < 4; i++)
 | 
						|
-			hash_table[i] = 0;
 | 
						|
+			hash_table[i] = 0xffff;
 | 
						|
+	}
 | 
						|
 
 | 
						|
-		for (i = 0; i < dev->mc_count; i++) {
 | 
						|
-			char *addrs = dmi->dmi_addr;
 | 
						|
+	/* Use internal multicast address registers if the number of
 | 
						|
+	 * multicast addresses is not greater than MCAST_MAX. */
 | 
						|
+	else if (dev->mc_count <= MCAST_MAX) {
 | 
						|
+		i = 0;
 | 
						|
+		while (i < dev->mc_count) {
 | 
						|
+			u16 *adrp = (u16 *)dmi->dmi_addr;
 | 
						|
 
 | 
						|
 			dmi = dmi->next;
 | 
						|
+			iowrite16(adrp[0], ioaddr + MID_1L + 8 * i);
 | 
						|
+			iowrite16(adrp[1], ioaddr + MID_1M + 8 * i);
 | 
						|
+			iowrite16(adrp[2], ioaddr + MID_1H + 8 * i);
 | 
						|
+			i++;
 | 
						|
+		}
 | 
						|
+		while (i < MCAST_MAX) {
 | 
						|
+			iowrite16(0, ioaddr + MID_1L + 8 * i);
 | 
						|
+			iowrite16(0, ioaddr + MID_1M + 8 * i);
 | 
						|
+			iowrite16(0, ioaddr + MID_1H + 8 * i);
 | 
						|
+			i++;
 | 
						|
+		}
 | 
						|
+	}
 | 
						|
+	/* Otherwise, Enable multicast hash table function. */
 | 
						|
+	else {
 | 
						|
+		u32 crc;
 | 
						|
+
 | 
						|
+		lp->mcr0 |= HASH_EN;
 | 
						|
 
 | 
						|
-			if (!(*addrs & 1))
 | 
						|
-				continue;
 | 
						|
+		for (i = 0; i < MCAST_MAX ; i++) {
 | 
						|
+			iowrite16(0, ioaddr + MID_1L + 8 * i);
 | 
						|
+			iowrite16(0, ioaddr + MID_1M + 8 * i);
 | 
						|
+			iowrite16(0, ioaddr + MID_1H + 8 * i);
 | 
						|
+		}
 | 
						|
+
 | 
						|
+		/* Build multicast hash table */
 | 
						|
+		for (i = 0; i < dev->mc_count; i++) {
 | 
						|
+			u8 *addrs = dmi->dmi_addr;
 | 
						|
+			dmi = dmi->next;
 | 
						|
 
 | 
						|
-			crc = ether_crc_le(6, addrs);
 | 
						|
+			crc = ether_crc(ETH_ALEN, addrs);
 | 
						|
 			crc >>= 26;
 | 
						|
-			hash_table[crc >> 4] |= 1 << (15 - (crc & 0xf));
 | 
						|
+			hash_table[crc >> 4] |= 1 << (crc & 0xf);
 | 
						|
 		}
 | 
						|
-		/* Fill the MAC hash tables with their values */
 | 
						|
+	}
 | 
						|
+	iowrite16(lp->mcr0, ioaddr + MCR0);
 | 
						|
+
 | 
						|
+	/* Fill the MAC hash tables with their values */
 | 
						|
+	if (lp->mcr0 && HASH_EN) {
 | 
						|
 		iowrite16(hash_table[0], ioaddr + MAR0);
 | 
						|
 		iowrite16(hash_table[1], ioaddr + MAR1);
 | 
						|
 		iowrite16(hash_table[2], ioaddr + MAR2);
 | 
						|
 		iowrite16(hash_table[3], ioaddr + MAR3);
 | 
						|
 	}
 | 
						|
-	/* Multicast Address 1~4 case */
 | 
						|
-	dmi = dev->mc_list;
 | 
						|
-	for (i = 0, dmi; (i < dev->mc_count) && (i < MCAST_MAX); i++) {
 | 
						|
-		adrp = (u16 *)dmi->dmi_addr;
 | 
						|
-		iowrite16(adrp[0], ioaddr + MID_1L + 8*i);
 | 
						|
-		iowrite16(adrp[1], ioaddr + MID_1M + 8*i);
 | 
						|
-		iowrite16(adrp[2], ioaddr + MID_1H + 8*i);
 | 
						|
-		dmi = dmi->next;
 | 
						|
-	}
 | 
						|
-	for (i = dev->mc_count; i < MCAST_MAX; i++) {
 | 
						|
-		iowrite16(0xffff, ioaddr + MID_1L + 8*i);
 | 
						|
-		iowrite16(0xffff, ioaddr + MID_1M + 8*i);
 | 
						|
-		iowrite16(0xffff, ioaddr + MID_1H + 8*i);
 | 
						|
-	}
 | 
						|
+
 | 
						|
+	spin_unlock_irqrestore(&lp->lock, flags);
 | 
						|
 }
 | 
						|
 
 | 
						|
 static void netdev_get_drvinfo(struct net_device *dev,
 |