Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 8 Dec 2004 10:30:36 +0000 (GMT)
From:      Robert Watson <rwatson@freebsd.org>
To:        Iasen Kostov <tbyte@OTEL.net>
Cc:        freebsd-net@freebsd.org
Subject:   Re: em(4) VLAN + PROMISC still doesn't work with latest CVS version
Message-ID:  <Pine.NEB.3.96L.1041208102811.24305F-100000@fledge.watson.org>
In-Reply-To: <41B5BC98.2080408@OTEL.net>

next in thread | previous in thread | raw e-mail | index | archive | help

On Tue, 7 Dec 2004, Iasen Kostov wrote:

>     Is there an update on this case or I should find a way to disable
> all hw "things" in the driver ?:) (because things are getting hot here
> :). 

Try the attached patch?  The vlan header in promisc mode was getting
inserted after the mbuf was mapped for dma, so under some circumstances
the remainder of the packet but not the header would be sent.  Given that
the previous change tested fine before, I'm wondering if the recent busdma
changes have triggered this bug. 

I'm beginning to think the right fix here is actually to always leave the
hardware turned on and to re-insert the vlan header on receive, not insert
on transmit, in order to avoid races for queued packets during state
transitions.  I'll have a chance to investigate that before going on
travel Friday, I hope.

Robert N M Watson             FreeBSD Core Team, TrustedBSD Projects
robert@fledge.watson.org      Principal Research Scientist, McAfee Research


Index: if_em.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/em/if_em.c,v
retrieving revision 1.54
diff -u -r1.54 if_em.c
--- if_em.c	14 Nov 2004 20:20:28 -0000	1.54
+++ if_em.c	8 Dec 2004 10:30:03 -0000
@@ -1203,36 +1203,6 @@
                 }
         }
 
-        /*
-         * Map the packet for DMA.
-         */
-        if (bus_dmamap_create(adapter->txtag, BUS_DMA_NOWAIT, &q.map)) {
-                adapter->no_tx_map_avail++;
-                return (ENOMEM);
-        }
-        error = bus_dmamap_load_mbuf(adapter->txtag, q.map,
-                                     m_head, em_tx_cb, &q, BUS_DMA_NOWAIT);
-        if (error != 0) {
-                adapter->no_tx_dma_setup++;
-                bus_dmamap_destroy(adapter->txtag, q.map);
-                return (error);
-        }
-        KASSERT(q.nsegs != 0, ("em_encap: empty packet"));
-
-        if (q.nsegs > adapter->num_tx_desc_avail) {
-                adapter->no_tx_desc_avail2++;
-                bus_dmamap_destroy(adapter->txtag, q.map);
-                return (ENOBUFS);
-        }
-
-
-        if (ifp->if_hwassist > 0) {
-                em_transmit_checksum_setup(adapter,  m_head,
-                                           &txd_upper, &txd_lower);
-        } else
-                txd_upper = txd_lower = 0;
-
-
         /* Find out if we are in vlan mode */
 #if __FreeBSD_version < 500000
         if ((m_head->m_flags & (M_PROTO1|M_PKTHDR)) == (M_PROTO1|M_PKTHDR) &&
@@ -1256,20 +1226,17 @@
 		m_head = m_pullup(m_head, sizeof(eh));
 		if (m_head == NULL) {
 			*m_headp = NULL;
-                	bus_dmamap_destroy(adapter->txtag, q.map);
 			return (ENOBUFS);
 		}
 		eh = *mtod(m_head, struct ether_header *);
 		M_PREPEND(m_head, sizeof(*evl), M_DONTWAIT);
 		if (m_head == NULL) {
 			*m_headp = NULL;
-                	bus_dmamap_destroy(adapter->txtag, q.map);
 			return (ENOBUFS);
 		}
 		m_head = m_pullup(m_head, sizeof(*evl));
 		if (m_head == NULL) {
 			*m_headp = NULL;
-                	bus_dmamap_destroy(adapter->txtag, q.map);
 			return (ENOBUFS);
 		}
 		evl = mtod(m_head, struct ether_vlan_header *);
@@ -1282,6 +1249,36 @@
 		*m_headp = m_head;
 	}
 
+        /*
+         * Map the packet for DMA.
+         */
+        if (bus_dmamap_create(adapter->txtag, BUS_DMA_NOWAIT, &q.map)) {
+                adapter->no_tx_map_avail++;
+                return (ENOMEM);
+        }
+        error = bus_dmamap_load_mbuf(adapter->txtag, q.map,
+                                     m_head, em_tx_cb, &q, BUS_DMA_NOWAIT);
+        if (error != 0) {
+                adapter->no_tx_dma_setup++;
+                bus_dmamap_destroy(adapter->txtag, q.map);
+                return (error);
+        }
+        KASSERT(q.nsegs != 0, ("em_encap: empty packet"));
+
+        if (q.nsegs > adapter->num_tx_desc_avail) {
+                adapter->no_tx_desc_avail2++;
+                bus_dmamap_destroy(adapter->txtag, q.map);
+                return (ENOBUFS);
+        }
+
+
+        if (ifp->if_hwassist > 0) {
+                em_transmit_checksum_setup(adapter,  m_head,
+                                           &txd_upper, &txd_lower);
+        } else
+                txd_upper = txd_lower = 0;
+
+
         i = adapter->next_avail_tx_desc;
 	if (adapter->pcix_82544) {
 		txd_saved = i;




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?Pine.NEB.3.96L.1041208102811.24305F-100000>