Module Name:    src
Committed By:   nisimura
Date:           Tue Mar 31 23:26:32 UTC 2020

Modified Files:
        src/sys/dev/usb: if_mos.c

Log Message:
iron out multicast filter logic and pick better name for its work


To generate a diff of this commit:
cvs rdiff -u -r1.5 -r1.6 src/sys/dev/usb/if_mos.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/dev/usb/if_mos.c
diff -u src/sys/dev/usb/if_mos.c:1.5 src/sys/dev/usb/if_mos.c:1.6
--- src/sys/dev/usb/if_mos.c:1.5	Sun Mar 15 23:04:50 2020
+++ src/sys/dev/usb/if_mos.c	Tue Mar 31 23:26:32 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: if_mos.c,v 1.5 2020/03/15 23:04:50 thorpej Exp $	*/
+/*	$NetBSD: if_mos.c,v 1.6 2020/03/31 23:26:32 nisimura Exp $	*/
 /*	$OpenBSD: if_mos.c,v 1.40 2019/07/07 06:40:10 kevlo Exp $	*/
 
 /*
@@ -72,7 +72,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_mos.c,v 1.5 2020/03/15 23:04:50 thorpej Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_mos.c,v 1.6 2020/03/31 23:26:32 nisimura Exp $");
 
 #include <sys/param.h>
 
@@ -454,14 +454,14 @@ mos_uno_mii_statchg(struct ifnet *ifp)
 }
 
 static void
-mos_setiff_locked(struct usbnet *un)
+mos_rcvfilt_locked(struct usbnet *un)
 {
 	struct ifnet		*ifp = usbnet_ifp(un);
 	struct ethercom		*ec = usbnet_ec(un);
 	struct ether_multi	*enm;
 	struct ether_multistep	step;
-	u_int32_t		h = 0;
-	u_int8_t		rxmode, hashtbl[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
+	u_int32_t h = 0;
+	u_int8_t rxmode, mchash[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
 
 	if (usbnet_isdying(un))
 		return;
@@ -471,40 +471,39 @@ mos_setiff_locked(struct usbnet *un)
 
 	ETHER_LOCK(ec);
 	if (ifp->if_flags & IFF_PROMISC) {
-allmulti:
 		ec->ec_flags |= ETHER_F_ALLMULTI;
-		rxmode |= MOS_CTL_ALLMULTI;
-		if (ifp->if_flags & IFF_PROMISC)
-			rxmode |= MOS_CTL_RX_PROMISC;
-	} else {
-		/* now program new ones */
-		ec->ec_flags &= ~ETHER_F_ALLMULTI;
-
-		ETHER_FIRST_MULTI(step, ec, enm);
-		while (enm != NULL) {
-			if (memcmp(enm->enm_addrlo, enm->enm_addrhi,
-			    ETHER_ADDR_LEN)) {
-				memset(hashtbl, 0, sizeof(hashtbl));
-				goto allmulti;
-			}
-			h = ether_crc32_be(enm->enm_addrlo,
-			    ETHER_ADDR_LEN) >> 26;
-			hashtbl[h / 8] |= 1 << (h % 8);
-
-			ETHER_NEXT_MULTI(step, enm);
+		ETHER_UNLOCK(ec);
+		/* run promisc. mode */
+		rxmode |= MOS_CTL_ALLMULTI; /* ??? */
+		rxmode |= MOS_CTL_RX_PROMISC;
+		goto update;
+	}
+	ec->ec_flags &= ~ETHER_F_ALLMULTI;
+	ETHER_FIRST_MULTI(step, ec, enm);
+	while (enm != NULL) {
+		if (memcmp(enm->enm_addrlo, enm->enm_addrhi, ETHER_ADDR_LEN)) {
+			ec->ec_flags |= ETHER_F_ALLMULTI;
+			ETHER_UNLOCK(ec);
+			memset(mchash, 0, sizeof(mchash)); /* correct ??? */
+			/* accept all mulicast frame */
+			rxmode |= MOS_CTL_ALLMULTI;
+			goto update;
 		}
+		h = ether_crc32_be(enm->enm_addrlo, ETHER_ADDR_LEN);
+		/* 3(31:29) and 3(28:26) sampling to have uint8_t[8] */
+		mchash[h >> 29] |= 1 << ((h >> 26) % 8);
+		ETHER_NEXT_MULTI(step, enm);
 	}
 	ETHER_UNLOCK(ec);
-
+	/* MOS receive filter is always on */
+ update:
 	/* 
 	 * The datasheet claims broadcast frames were always accepted
 	 * regardless of filter settings. But the hardware seems to
 	 * filter broadcast frames, so pass them explicitly.
 	 */
-	h = ether_crc32_be(etherbroadcastaddr, ETHER_ADDR_LEN) >> 26;
-	hashtbl[h / 8] |= 1 << (h % 8);
-
-	mos_write_mcast(un, hashtbl);
+	mchash[7] |= 0x80;
+	mos_write_mcast(un, mchash);
 	mos_reg_write_1(un, MOS_CTL, rxmode);
 }
 
@@ -745,7 +744,7 @@ mos_init_locked(struct ifnet *ifp)
 	mos_reg_write_1(un, MOS_IPG1, ipgs[1]);
 
 	/* Program promiscuous mode and multicast filters. */
-	mos_setiff_locked(un);
+	mos_rcvfilt_locked(un);
 
 	/* Enable receiver and transmitter, bridge controls speed/duplex mode */
 	rxmode = mos_reg_read_1(un, MOS_CTL);
@@ -781,7 +780,7 @@ mos_uno_ioctl(struct ifnet *ifp, u_long 
 	switch (cmd) {
 	case SIOCADDMULTI:
 	case SIOCDELMULTI:
-		mos_setiff_locked(un);
+		mos_rcvfilt_locked(un);
 		break;
 	default:
 		break;

Reply via email to