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.