Resurrecting this, I've now fixed the problem I introduced when I merged
in your changes and have tested it.

The performance on my ALIX routing from a VLAN to another non-VLAN
interface, iperf TCP went up a little (the CPU is saturated at this
point):

baseline: RX 80.0 Mbits/sec TX 65.2 Mbits/sec
hwtagging: RX 80.4 Mbits/sec TX 73.2 Mbits/sec

ok?

Index: dev/pci/if_vr.c
===================================================================
RCS file: /cvs/src/sys/dev/pci/if_vr.c,v
retrieving revision 1.121
diff -u -p -r1.121 if_vr.c
--- dev/pci/if_vr.c     1 Dec 2012 09:55:03 -0000       1.121
+++ dev/pci/if_vr.c     14 Jan 2013 03:30:55 -0000
@@ -62,6 +62,7 @@
  */
 
 #include "bpfilter.h"
+#include "vlan.h"
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -83,6 +84,11 @@
 #include <net/if_dl.h>
 #include <net/if_media.h>
 
+#if NVLAN > 0
+#include <net/if_types.h>
+#include <net/if_vlan_var.h>
+#endif
+
 #if NBPFILTER > 0
 #include <net/bpf.h>
 #endif
@@ -632,6 +638,12 @@ vr_attach(struct device *parent, struct 
                ifp->if_capabilities |= IFCAP_CSUM_IPv4 | IFCAP_CSUM_TCPv4 |
                                        IFCAP_CSUM_UDPv4;
 
+#if NVLAN > 0
+       /* if the hardware can do VLAN tagging, say so. */
+       if (sc->vr_quirks & VR_Q_HWTAG)
+               ifp->if_capabilities |= IFCAP_VLAN_HWTAGGING;
+#endif
+
 #ifndef SMALL_KERNEL
        if (sc->vr_revid >= REV_ID_VT3065_A) {
                ifp->if_capabilities |= IFCAP_WOL;
@@ -874,6 +886,21 @@ vr_rxeof(struct vr_softc *sc)
                    cur_rx->vr_map->dm_mapsize, BUS_DMASYNC_POSTREAD);
                bus_dmamap_unload(sc->sc_dmat, cur_rx->vr_map);
 
+#if NVLAN > 0
+               /*
+                * If there's a tagged packet, the 802.1q header will be at the
+                * 4-byte boundary following the CRC.  There will be 2 bytes
+                * TPID (0x8100) and 2 bytes TCI (including VLAN ID).
+                * This isn't in the data sheet.
+                */
+               if (rxctl & VR_RXCTL_TAG) {
+                       int offset = ((total_len + 3) & ~3) + 2;
+                       m->m_pkthdr.ether_vtag = htons(*(u_int16_t *)
+                           ((u_int8_t *)m->m_data + offset));
+                       m->m_flags |= M_VLANTAG;
+               }
+#endif
+
                /*
                 * The VIA Rhine chip includes the CRC with every
                 * received frame, and there's no way to turn this
@@ -1223,12 +1250,20 @@ vr_encap(struct vr_softc *sc, struct vr_
 
        if (m_new != NULL) {
                m_freem(m_head);
-
                c->vr_mbuf = m_new;
        } else
                c->vr_mbuf = m_head;
        txmap = c->vr_map;
        for (i = 0; i < txmap->dm_nsegs; i++) {
+#if NVLAN > 0
+               /* Tell chip to insert VLAN tag if needed. */
+               if (m_head->m_flags & M_VLANTAG) {
+                       u_int32_t vtag = m_head->m_pkthdr.ether_vtag;
+                       vtag = (vtag << VR_TXSTAT_PQSHIFT) & VR_TXSTAT_PQMASK;
+                       vr_status |= vtag;
+                       vr_ctl |= htole32(VR_TXCTL_INSERTTAG);
+               }
+#endif
                if (i != 0)
                        *cp = c = c->vr_nextdesc;
                f = c->vr_ptr;
@@ -1254,7 +1289,7 @@ vr_encap(struct vr_softc *sc, struct vr_
                sc->vr_cdata.vr_tx_cnt++;
        }
 
-       /* Set EOP on the last desciptor */
+       /* Set EOP on the last descriptor */
        f->vr_ctl |= htole32(VR_TXCTL_LASTFRAG | VR_TXCTL_FINT);
 
        return (0);
@@ -1395,6 +1430,11 @@ vr_init(void *xsc)
 
        VR_CLRBIT(sc, VR_TXCFG, VR_TXCFG_TX_THRESH);
        VR_SETBIT(sc, VR_TXCFG, VR_TXTHRESH_STORENFWD);
+
+#if NVLAN > 0
+       if (ifp->if_capabilities & IFCAP_VLAN_HWTAGGING)
+               VR_SETBIT(sc, VR_TXCFG, VR_TXCFG_TXTAGEN);
+#endif
 
        /* Init circular RX list. */
        if (vr_list_rx_init(sc) == ENOBUFS) {
Index: dev/pci/if_vrreg.h
===================================================================
RCS file: /cvs/src/sys/dev/pci/if_vrreg.h,v
retrieving revision 1.32
diff -u -p -r1.32 if_vrreg.h
--- dev/pci/if_vrreg.h  20 Oct 2012 16:12:22 -0000      1.32
+++ dev/pci/if_vrreg.h  14 Jan 2013 03:30:55 -0000
@@ -83,6 +83,9 @@
 #define VR_MPA_CNT             0x7C
 #define VR_CRC_CNT             0x7E
 #define VR_STICKHW             0x83
+#define VR_CAMMASK             0x88 /* length 4 bytes */
+#define VR_CAMCTRL             0x92
+#define VR_CAMADDR             0x93
 
 /* Misc Registers */
 #define VR_MISC_CR1            0x81
@@ -342,6 +345,14 @@
 #define VR_BCR1_VLANFILT_ENB   0x80            /* 6105M */
 
 /*
+ * CAM Control registers (VT6105M)
+ */
+#define VR_CAMCTRL_WREN                0x01
+#define VR_CAMCTRL_VCAMSEL     0x02
+#define VR_CAMCTRL_WRITE       0x04
+#define VR_CAMCTRL_READ                0x08
+
+/*
  * Rhine TX/RX list structure.
  */
 
@@ -404,6 +415,7 @@ struct vr_desc {
 #define VR_TXSTAT_ERRSUM       0x00008000
 #define VR_TXSTAT_PQMASK       0x7FFF0000
 #define VR_TXSTAT_OWN          0x80000000
+#define VR_TXSTAT_PQSHIFT      16
 
 #define VR_TXCTL_BUFLEN                0x000007FF
 #define VR_TXCTL_BUFLEN_EXT    0x00007800

-- 
Darren Tucker (dtucker at zip.com.au)
GPG key 8FF4FA69 / D9A3 86E9 7EEE AF4B B2D4  37C9 C982 80C7 8FF4 FA69
    Good judgement comes with experience. Unfortunately, the experience
usually comes from bad judgement.

Reply via email to