<br><br><div class="gmail_quote">On Mon, Aug 24, 2009 at 11:10 AM, Torsten Fleischer <span dir="ltr">&lt;<a href="mailto:to-fleischer@t-online.de">to-fleischer@t-online.de</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
Hello everyone,<br>
<br>
I have the Freescale&#39;s MPC8313erdb eval board and run the latest stable linux<br>
kernel version (linux-2.6.30.5).<br>
<br>
After creating a VLAN device (e.g. eth0.2) a VLAN tag is also inserted into<br>
frames that don&#39;t relate to a VLAN device. This is the case for frames that<br>
are directly sent through a standard ethernet interface (e.g. eth0).<br>
<br>
When creating a VLAN device the gianfar driver enables the  hardware supported<br>
VLAN tagging on TX frames. This is done by setting the VLINS bit of the TCTRL<br>
register inside the function gianfar_vlan_rx_register().<br>
The problem is that every outgoing frame will be tagged.  For frames from an<br>
interface like eth0 the VLN bit of the FCB isn&#39;t set. Therefore the eTSEC uses<br>
the content of the Default VLAN control word register (DFVLAN) to tag the<br>
frame. As long as this register will not be modified after a reset of the<br>
controller the outgoing frames will be tagged with VID = 0 (priority tagged<br>
frames).<br>
<br>
The following patch solves this problem.<br>
<br>
diff -uprN linux-2.6.30.5_orig//drivers/net/gianfar.c linux-2.6.30.5/drivers/net/gianfar.c<br>
--- linux-2.6.30.5_orig//drivers/net/gianfar.c  2009-08-16 23:19:38.000000000 +0200<br>
+++ linux-2.6.30.5/drivers/net/gianfar.c        2009-08-22 10:38:28.000000000 +0200<br>
@@ -1309,6 +1309,7 @@ static int gfar_start_xmit(struct sk_buf<br>
        u32 bufaddr;<br>
        unsigned long flags;<br>
        unsigned int nr_frags, length;<br>
+       u32 tempval;<br>
<br>
        base = priv-&gt;tx_bd_base;<br>
<br>
@@ -1385,13 +1386,30 @@ static int gfar_start_xmit(struct sk_buf<br>
                gfar_tx_checksum(skb, fcb);<br>
        }<br>
<br>
-       if (priv-&gt;vlgrp &amp;&amp; vlan_tx_tag_present(skb)) {<br>
-               if (unlikely(NULL == fcb)) {<br>
-                       fcb = gfar_add_fcb(skb);<br>
-                       lstatus |= BD_LFLAG(TXBD_TOE);<br>
-               }<br>
+       if (priv-&gt;vlgrp) {<br>
+               if (vlan_tx_tag_present(skb)) {<br>
+                       if (unlikely(NULL == fcb)) {<br>
+                               fcb = gfar_add_fcb(skb);<br>
+                               lstatus |= BD_LFLAG(TXBD_TOE);<br>
+                       }<br>
+<br>
+                       /* Enable VLAN tag insertion for frames from VLAN devices */<br>
+                       tempval = gfar_read(&amp;priv-&gt;regs-&gt;tctrl);<br>
+                       if ( !(tempval &amp; TCTRL_VLINS) ) {<br>
+                               tempval |= TCTRL_VLINS;<br>
+                               gfar_write(&amp;priv-&gt;regs-&gt;tctrl, tempval);<br>
+                       }<br>
<br>
-               gfar_tx_vlan(skb, fcb);<br>
+                       gfar_tx_vlan(skb, fcb);<br>
+               }<br>
+               else {<br>
+                       /* Disable VLAN tag insertion for frames that are not from a VLAN device */<br>
+                       tempval = gfar_read(&amp;priv-&gt;regs-&gt;tctrl);<br>
+                       if ( tempval &amp; TCTRL_VLINS ) {<br>
+                               tempval &amp;= ~TCTRL_VLINS;<br>
+                               gfar_write(&amp;priv-&gt;regs-&gt;tctrl, tempval);<br>
+                       }<br>
+               }<br>
        }</blockquote><div><br></div><div><br></div><div>Hmmm....how have you tested this?  This looks like it has a bad race condition.  The TCTRL register applies to all packets, which means if you send a packet with VLAN tags, followed by one without, or visa versa, there&#39;s a reasonable chance that the second packet&#39;s VLAN tags (or lack thereof) will take precedence.</div>
<div><br></div><div>Without speaking for the company, I suspect that this is just how the eTSEC works with VLAN -- all, or nothing.</div><div><br></div><div>Andy </div></div><br>