The following diff adds HW VLAN tagging/stripping and checksum offload
support.

Tested with a SiS 190 adapter.

OK?


Index: if_se.c
===================================================================
RCS file: /home/cvs/src/sys/dev/pci/if_se.c,v
retrieving revision 1.7
diff -u -p -r1.7 if_se.c
--- if_se.c     26 Sep 2012 19:18:00 -0000      1.7
+++ if_se.c     11 Nov 2012 05:54:47 -0000
@@ -179,6 +179,7 @@ uint16_t
        se_read_eeprom(struct se_softc *, int);
 
 void   se_iff(struct se_softc *);
+void   se_setvlan(struct se_softc *);
 void   se_reset(struct se_softc *);
 int    se_list_rx_init(struct se_softc *);
 int    se_list_rx_free(struct se_softc *);
@@ -487,6 +488,18 @@ se_iff(struct se_softc *sc)
 }
 
 void
+se_setvlan(struct se_softc *sc)
+{
+       struct ifnet *ifp = &sc->sc_ac.ac_if;
+       uint16_t rxfilt;
+
+       rxfilt = CSR_READ_2(sc, RxMacControl);
+       if (ifp->if_capabilities & IFCAP_VLAN_HWTAGGING)
+               rxfilt |= RXMAC_STRIP_VLAN;
+       CSR_WRITE_2(sc, RxMacControl, rxfilt);
+}
+
+void
 se_reset(struct se_softc *sc)
 {
        CSR_WRITE_4(sc, IntrMask, 0);
@@ -699,6 +712,15 @@ se_attach(struct device *parent, struct 
 
        ifp->if_capabilities = IFCAP_VLAN_MTU;
 
+#ifdef SE_CKSUM
+       ifp->if_capabilities |= IFCAP_CSUM_IPv4 | IFCAP_CSUM_TCPv4 |
+           IFCAP_CSUM_UDPv4;
+#endif
+
+#if NVLAN > 0
+       ifp->if_capabilities |= IFCAP_VLAN_HWTAGGING;
+#endif
+
        /*
         * Do MII setup.
         */
@@ -950,6 +972,27 @@ se_rxeof(struct se_softc *sc)
                        ifp->if_iqdrops++;
                        continue;
                }
+
+               if ((rxinfo & RDC_IP_CSUM) != 0 &&
+                   (rxinfo & RDC_IP_CSUM_OK) != 0)
+                       m->m_pkthdr.csum_flags |=
+                           M_IPV4_CSUM_IN_OK;
+               if (((rxinfo & RDC_TCP_CSUM) != 0 &&
+                   (rxinfo & RDC_TCP_CSUM_OK) != 0) ||
+                   ((rxinfo & RDC_UDP_CSUM) != 0 &&
+                   (rxinfo & RDC_UDP_CSUM_OK) != 0)) {
+                       m->m_pkthdr.csum_flags |=
+                           M_TCP_CSUM_IN_OK | M_UDP_CSUM_IN_OK;
+               }
+
+#if NVLAN > 0
+               /* Check for VLAN tagged frame. */
+               if ((rxstat & RDS_VLAN) != 0) {
+                       m->m_pkthdr.ether_vtag = rxinfo & RDC_VLAN_MASK;
+                       m->m_flags |= M_VLANTAG;
+               }
+#endif
+
                /*
                 * Account for 10 bytes auto padding which is used
                 * to align IP header on a 32bit boundary.  Also note,
@@ -964,7 +1007,7 @@ se_rxeof(struct se_softc *sc)
 
 #if NBPFILTER > 0
                if (ifp->if_bpf)
-                       bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_IN);
+                       bpf_mtap_ether(ifp->if_bpf, m, BPF_DIRECTION_IN);
 #endif
                ether_input_mbuf(ifp, m);
        }
@@ -1116,6 +1159,7 @@ se_encap(struct se_softc *sc, struct mbu
        struct se_list_data *ld = &sc->se_ldata;
        struct se_chain_data *cd = &sc->se_cdata;
        struct se_desc *desc;
+       uint32_t cflags = 0;
        uint i, cnt = 0;
        int rc;
 
@@ -1139,6 +1183,13 @@ se_encap(struct se_softc *sc, struct mbu
                return ENOBUFS; /* XXX should not be fatal */
        }
 
+       if (m->m_pkthdr.csum_flags & M_IPV4_CSUM_OUT)
+               cflags |= TDC_IP_CSUM;
+       if (m->m_pkthdr.csum_flags & M_TCP_CSUM_OUT)
+               cflags |= TDC_TCP_CSUM;
+       if (m->m_pkthdr.csum_flags & M_UDP_CSUM_OUT)
+               cflags |= TDC_UDP_CSUM;
+
        /*
         * Start packing the mbufs in this chain into
         * the fragment pointers. Stop when we run out
@@ -1168,13 +1219,19 @@ se_encap(struct se_softc *sc, struct mbu
 
                desc = &ld->se_tx_ring[i];
                desc->se_sts_size = htole32(cd->se_tx_map[i]->dm_segs->ds_len);
+#if NVLAN > 0
+               if (m_head->m_flags & M_VLANTAG) {
+                       cflags |= m->m_pkthdr.ether_vtag;
+                       desc->se_sts_size |= htole32(TDS_INS_VLAN);
+               }
+#endif
                desc->se_ptr =
                    htole32((uint32_t)cd->se_tx_map[i]->dm_segs->ds_addr);
                desc->se_flags = htole32(cd->se_tx_map[i]->dm_segs->ds_len);
                if (i == SE_TX_RING_CNT - 1)
                        desc->se_flags |= htole32(RING_END);
                desc->se_cmdsts = htole32(TDC_OWN | TDC_INTR | TDC_DEF |
-                   TDC_CRC | TDC_PAD | TDC_BST);
+                   TDC_CRC | TDC_PAD | TDC_BST | cflags);
                bus_dmamap_sync(sc->sc_dmat, ld->se_tx_dmamap,
                    i * sizeof(*desc), sizeof(*desc),
                    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
@@ -1239,7 +1296,7 @@ se_start(struct ifnet *ifp)
                 */
 #if NBPFILTER > 0
                if (ifp->if_bpf)
-                       bpf_mtap(ifp->if_bpf, m_head, BPF_DIRECTION_OUT);
+                       bpf_mtap_ether(ifp->if_bpf, m_head, BPF_DIRECTION_OUT);
 #endif
        }
 
@@ -1297,6 +1354,8 @@ se_init(struct ifnet *ifp)
 
        /* Program promiscuous mode and multicast filters. */
        se_iff(sc);
+
+       se_setvlan(sc);
 
        /*
         * Clear and enable interrupts.

-- 
This message has been scanned for viruses and
dangerous content by MailScanner, and is
believed to be clean.

Reply via email to