It looks vlan tag info must appear not only in the first descriptor

but in all descriptors of a multi-descriptor transmission attempt on re(4).

Problem was reported and fix was confirmed by Chris Brookes on tech-net.
Should also close PR kern/37959.
This commit is contained in:
tsutsui 2008-03-18 14:06:56 +00:00
parent d5bb355fe9
commit 0e8643dfc7
1 changed files with 15 additions and 16 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: rtl8169.c,v 1.97 2008/03/14 13:42:01 tsutsui Exp $ */
/* $NetBSD: rtl8169.c,v 1.98 2008/03/18 14:06:56 tsutsui Exp $ */
/*
* Copyright (c) 1997, 1998-2003
@ -33,7 +33,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: rtl8169.c,v 1.97 2008/03/14 13:42:01 tsutsui Exp $");
__KERNEL_RCSID(0, "$NetBSD: rtl8169.c,v 1.98 2008/03/18 14:06:56 tsutsui Exp $");
/* $FreeBSD: /repoman/r/ncvs/src/sys/dev/re/if_re.c,v 1.20 2004/04/11 20:34:08 ru Exp $ */
/*
@ -1458,7 +1458,7 @@ re_start(struct ifnet *ifp)
struct re_txq *txq;
struct re_desc *d;
struct m_tag *mtag;
uint32_t cmdstat, re_flags;
uint32_t cmdstat, re_flags, vlanctl;
int ofree, idx, error, nsegs, seg;
int startdesc, curdesc, lastdesc;
bool pad;
@ -1553,6 +1553,16 @@ re_start(struct ifnet *ifp)
bus_dmamap_sync(sc->sc_dmat, map, 0, map->dm_mapsize,
BUS_DMASYNC_PREWRITE);
/*
* Set up hardware VLAN tagging. Note: vlan tag info must
* appear in all descriptors of a multi-descriptor
* transmission attempt.
*/
vlanctl = 0;
if ((mtag = VLAN_OUTPUT_TAG(&sc->ethercom, m)) != NULL)
vlanctl = bswap16(VLAN_TAG_VALUE(mtag)) |
RE_TDESC_VLANCTL_TAG;
/*
* Map the segment array into descriptors.
* Note that we set the start-of-frame and
@ -1583,7 +1593,7 @@ re_start(struct ifnet *ifp)
}
#endif
d->re_vlanctl = 0;
d->re_vlanctl = htole32(vlanctl);
re_set_bufaddr(d, map->dm_segs[seg].ds_addr);
cmdstat = re_flags | map->dm_segs[seg].ds_len;
if (seg == 0)
@ -1604,7 +1614,7 @@ re_start(struct ifnet *ifp)
bus_addr_t paddaddr;
d = &sc->re_ldata.re_tx_list[curdesc];
d->re_vlanctl = 0;
d->re_vlanctl = htole32(vlanctl);
paddaddr = RE_TXPADDADDR(sc);
re_set_bufaddr(d, paddaddr);
cmdstat = re_flags |
@ -1620,17 +1630,6 @@ re_start(struct ifnet *ifp)
}
KASSERT(lastdesc != -1);
/*
* Set up hardware VLAN tagging. Note: vlan tag info must
* appear in the first descriptor of a multi-descriptor
* transmission attempt.
*/
if ((mtag = VLAN_OUTPUT_TAG(&sc->ethercom, m)) != NULL) {
sc->re_ldata.re_tx_list[startdesc].re_vlanctl =
htole32(bswap16(VLAN_TAG_VALUE(mtag)) |
RE_TDESC_VLANCTL_TAG);
}
/* Transfer ownership of packet to the chip. */
sc->re_ldata.re_tx_list[startdesc].re_cmdstat |=