Subject: Re: kern/32643: re(4) has problems with HW VLAN tagging
To: None <gnats-bugs@netbsd.org>
From: Izumi Tsutsui <tsutsui@ceres.dti.ne.jp>
List: netbsd-bugs
Date: 11/19/2006 12:46:04
> Maybe it is a hardware bug?

This looks a software bug.
(re_vlanctl in the DMA descriptors are not cleared)

Could you try the attached patch?
VLAN seems working on both i386 and macppc with this patch.
---
Izumi Tsutsui


Index: rtl8169.c
===================================================================
RCS file: /cvsroot/src/sys/dev/ic/rtl8169.c,v
retrieving revision 1.68
diff -u -r1.68 rtl8169.c
--- rtl8169.c	18 Nov 2006 17:39:44 -0000	1.68
+++ rtl8169.c	19 Nov 2006 03:33:11 -0000
@@ -759,16 +759,8 @@
 	ifp->if_mtu = ETHERMTU;
 	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
 	ifp->if_ioctl = re_ioctl;
-	sc->ethercom.ec_capabilities |= ETHERCAP_VLAN_MTU;
-
-	/*
-	 * This is a way to disable hw VLAN tagging by default
-	 * (RE_VLAN is undefined), as it is problematic. PR 32643
-	 */
-
-#ifdef RE_VLAN
-	sc->ethercom.ec_capabilities |= ETHERCAP_VLAN_HWTAGGING;
-#endif
+	sc->ethercom.ec_capabilities |=
+	    ETHERCAP_VLAN_MTU | ETHERCAP_VLAN_HWTAGGING;
 	ifp->if_start = re_start;
 	ifp->if_stop = re_stop;
 
@@ -1083,6 +1075,7 @@
 
 	rxs->rxs_mbuf = m;
 
+	d->re_vlanctl = 0;
 	cmdstat = map->dm_segs[0].ds_len;
 	if (idx == (RE_RX_DESC_CNT - 1))
 		cmdstat |= RE_RDESC_CMD_EOR;
@@ -1287,13 +1280,11 @@
 				m->m_pkthdr.csum_flags |= M_CSUM_TCP_UDP_BAD;
 		}
 
-#ifdef RE_VLAN
 		if (rxvlan & RE_RDESC_VLANCTL_TAG) {
 			VLAN_INPUT_TAG(ifp, m,
-			     be16toh(rxvlan & RE_RDESC_VLANCTL_DATA),
+			     bswap16(rxvlan & RE_RDESC_VLANCTL_DATA),
 			     continue);
 		}
-#endif
 #if NBPFILTER > 0
 		if (ifp->if_bpf)
 			bpf_mtap(ifp->if_bpf, m);
@@ -1517,9 +1508,7 @@
 	bus_dmamap_t		map;
 	struct re_txq		*txq;
 	struct re_desc		*d;
-#ifdef RE_VLAN
 	struct m_tag		*mtag;
-#endif
 	uint32_t		cmdstat, re_flags;
 	int			ofree, idx, error, nsegs, seg;
 	int			startdesc, curdesc, lastdesc;
@@ -1645,6 +1634,7 @@
 			}
 #endif
 
+			d->re_vlanctl = 0;
 			re_set_bufaddr(d, map->dm_segs[seg].ds_addr);
 			cmdstat = re_flags | map->dm_segs[seg].ds_len;
 			if (seg == 0)
@@ -1665,6 +1655,7 @@
 			bus_addr_t paddaddr;
 
 			d = &sc->re_ldata.re_tx_list[curdesc];
+			d->re_vlanctl = 0;
 			paddaddr = RE_TXPADDADDR(sc);
 			re_set_bufaddr(d, paddaddr);
 			cmdstat = re_flags |
@@ -1685,14 +1676,11 @@
 		 * appear in the first descriptor of a multi-descriptor
 		 * transmission attempt.
 		 */
-
-#ifdef RE_VLAN
 		if ((mtag = VLAN_OUTPUT_TAG(&sc->ethercom, m)) != NULL) {
 			sc->re_ldata.re_tx_list[startdesc].re_vlanctl =
-			    htole32(htons(VLAN_TAG_VALUE(mtag)) |
+			    htole32(bswap16(VLAN_TAG_VALUE(mtag)) |
 			    RE_TDESC_VLANCTL_TAG);
 		}
-#endif
 
 		/* Transfer ownership of packet to the chip. */
 
@@ -1795,9 +1783,7 @@
 
 	if (1)  {/* not for 8169S ? */
 		reg |=
-#ifdef RE_VLAN
 		    RTK_CPLUSCMD_VLANSTRIP |
-#endif
 		    (ifp->if_capenable &
 		    (IFCAP_CSUM_IPv4_Rx | IFCAP_CSUM_TCPv4_Rx |
 		     IFCAP_CSUM_UDPv4_Rx) ?