Module Name:    src
Committed By:   martin
Date:           Sun Dec  8 14:29:37 UTC 2019

Modified Files:
        src/sys/arch/arm/imx [netbsd-9]: if_enet.c

Log Message:
Pull up following revision(s) (requested by ryo in ticket #509):

        sys/arch/arm/imx/if_enet.c: revision 1.29

set the multicast filter properly.

don't always IFF_ALLMULTI if multicast is configured.
fix the handling of GAUR and GALR.


To generate a diff of this commit:
cvs rdiff -u -r1.25 -r1.25.2.1 src/sys/arch/arm/imx/if_enet.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/arch/arm/imx/if_enet.c
diff -u src/sys/arch/arm/imx/if_enet.c:1.25 src/sys/arch/arm/imx/if_enet.c:1.25.2.1
--- src/sys/arch/arm/imx/if_enet.c:1.25	Tue Jul 30 06:26:31 2019
+++ src/sys/arch/arm/imx/if_enet.c	Sun Dec  8 14:29:36 2019
@@ -1,4 +1,4 @@
-/*	$NetBSD: if_enet.c,v 1.25 2019/07/30 06:26:31 hkenken Exp $	*/
+/*	$NetBSD: if_enet.c,v 1.25.2.1 2019/12/08 14:29:36 martin Exp $	*/
 
 /*
  * Copyright (c) 2014 Ryo Shimizu <r...@nerv.org>
@@ -31,7 +31,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_enet.c,v 1.25 2019/07/30 06:26:31 hkenken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_enet.c,v 1.25.2.1 2019/12/08 14:29:36 martin Exp $");
 
 #include "vlan.h"
 
@@ -714,15 +714,14 @@ enet_setmulti(struct enet_softc *sc)
 	struct ifnet *ifp = &ec->ec_if;
 	struct ether_multi *enm;
 	struct ether_multistep step;
-	int promisc;
-	uint32_t crc;
+	uint32_t crc, hashidx;
 	uint32_t gaddr[2];
 
-	promisc = 0;
-	if ((ifp->if_flags & IFF_PROMISC) || ec->ec_multicnt > 0) {
-		ifp->if_flags |= IFF_ALLMULTI;
-		if (ifp->if_flags & IFF_PROMISC)
-			promisc = 1;
+	if (ifp->if_flags & IFF_PROMISC) {
+		/* receive all unicast packet */
+		ENET_REG_WRITE(sc, ENET_IAUR, 0xffffffff);
+		ENET_REG_WRITE(sc, ENET_IALR, 0xffffffff);
+		/* receive all multicast packet */
 		gaddr[0] = gaddr[1] = 0xffffffff;
 	} else {
 		gaddr[0] = gaddr[1] = 0;
@@ -730,25 +729,38 @@ enet_setmulti(struct enet_softc *sc)
 		ETHER_LOCK(ec);
 		ETHER_FIRST_MULTI(step, ec, enm);
 		while (enm != NULL) {
+			if (memcmp(enm->enm_addrlo, enm->enm_addrhi,
+			    ETHER_ADDR_LEN)) {
+				/*
+				 * if specified by range, give up setting hash,
+				 * and fallback to allmulti.
+				 */
+				gaddr[0] = gaddr[1] = 0xffffffff;
+				break;
+			}
+
 			crc = ether_crc32_le(enm->enm_addrlo, ETHER_ADDR_LEN);
-			gaddr[crc >> 31] |= 1 << ((crc >> 26) & 0x1f);
+			hashidx = __SHIFTOUT(crc, __BITS(30,26));
+			gaddr[__SHIFTOUT(crc, __BIT(31))] |= __BIT(hashidx);
+
 			ETHER_NEXT_MULTI(step, enm);
 		}
 		ETHER_UNLOCK(ec);
-	}
-
-	ENET_REG_WRITE(sc, ENET_GAUR, gaddr[0]);
-	ENET_REG_WRITE(sc, ENET_GALR, gaddr[1]);
 
-	if (promisc) {
-		/* match all packet */
-		ENET_REG_WRITE(sc, ENET_IAUR, 0xffffffff);
-		ENET_REG_WRITE(sc, ENET_IALR, 0xffffffff);
-	} else {
-		/* don't match any packet */
+		/* dont't receive any unicast packet (except own address) */
 		ENET_REG_WRITE(sc, ENET_IAUR, 0);
 		ENET_REG_WRITE(sc, ENET_IALR, 0);
 	}
+
+	if (gaddr[0] == 0xffffffff && gaddr[1] == 0xffffffff)
+		ifp->if_flags |= IFF_ALLMULTI;
+	else
+		ifp->if_flags &= ~IFF_ALLMULTI;
+
+	/* receive multicast packets according to multicast filter */
+	ENET_REG_WRITE(sc, ENET_GAUR, gaddr[1]);
+	ENET_REG_WRITE(sc, ENET_GALR, gaddr[0]);
+
 }
 
 static void

Reply via email to