gianfar.c: Unwanted VLAN tagging on TX frames
Andy Fleming
afleming at gmail.com
Tue Aug 25 09:32:18 EST 2009
On Mon, Aug 24, 2009 at 11:10 AM, Torsten Fleischer <
to-fleischer at t-online.de> wrote:
> Hello everyone,
>
> I have the Freescale's MPC8313erdb eval board and run the latest stable
> linux
> kernel version (linux-2.6.30.5).
>
> After creating a VLAN device (e.g. eth0.2) a VLAN tag is also inserted into
> frames that don't relate to a VLAN device. This is the case for frames that
> are directly sent through a standard ethernet interface (e.g. eth0).
>
> When creating a VLAN device the gianfar driver enables the hardware
> supported
> VLAN tagging on TX frames. This is done by setting the VLINS bit of the
> TCTRL
> register inside the function gianfar_vlan_rx_register().
> The problem is that every outgoing frame will be tagged. For frames from
> an
> interface like eth0 the VLN bit of the FCB isn't set. Therefore the eTSEC
> uses
> the content of the Default VLAN control word register (DFVLAN) to tag the
> frame. As long as this register will not be modified after a reset of the
> controller the outgoing frames will be tagged with VID = 0 (priority tagged
> frames).
>
> The following patch solves this problem.
>
> diff -uprN linux-2.6.30.5_orig//drivers/net/gianfar.c
> linux-2.6.30.5/drivers/net/gianfar.c
> --- linux-2.6.30.5_orig//drivers/net/gianfar.c 2009-08-16
> 23:19:38.000000000 +0200
> +++ linux-2.6.30.5/drivers/net/gianfar.c 2009-08-22
> 10:38:28.000000000 +0200
> @@ -1309,6 +1309,7 @@ static int gfar_start_xmit(struct sk_buf
> u32 bufaddr;
> unsigned long flags;
> unsigned int nr_frags, length;
> + u32 tempval;
>
> base = priv->tx_bd_base;
>
> @@ -1385,13 +1386,30 @@ static int gfar_start_xmit(struct sk_buf
> gfar_tx_checksum(skb, fcb);
> }
>
> - if (priv->vlgrp && vlan_tx_tag_present(skb)) {
> - if (unlikely(NULL == fcb)) {
> - fcb = gfar_add_fcb(skb);
> - lstatus |= BD_LFLAG(TXBD_TOE);
> - }
> + if (priv->vlgrp) {
> + if (vlan_tx_tag_present(skb)) {
> + if (unlikely(NULL == fcb)) {
> + fcb = gfar_add_fcb(skb);
> + lstatus |= BD_LFLAG(TXBD_TOE);
> + }
> +
> + /* Enable VLAN tag insertion for frames from VLAN
> devices */
> + tempval = gfar_read(&priv->regs->tctrl);
> + if ( !(tempval & TCTRL_VLINS) ) {
> + tempval |= TCTRL_VLINS;
> + gfar_write(&priv->regs->tctrl, tempval);
> + }
>
> - gfar_tx_vlan(skb, fcb);
> + gfar_tx_vlan(skb, fcb);
> + }
> + else {
> + /* Disable VLAN tag insertion for frames that are
> not from a VLAN device */
> + tempval = gfar_read(&priv->regs->tctrl);
> + if ( tempval & TCTRL_VLINS ) {
> + tempval &= ~TCTRL_VLINS;
> + gfar_write(&priv->regs->tctrl, tempval);
> + }
> + }
> }
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's a reasonable chance that the second packet's VLAN tags (or lack
thereof) will take precedence.
Without speaking for the company, I suspect that this is just how the eTSEC
works with VLAN -- all, or nothing.
Andy
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.ozlabs.org/pipermail/linuxppc-dev/attachments/20090824/fee8ed60/attachment.htm>
More information about the Linuxppc-dev
mailing list