aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEmmanuel Vadot <manu@FreeBSD.org>2020-11-20 11:31:25 +0000
committerEmmanuel Vadot <manu@FreeBSD.org>2020-11-20 11:31:25 +0000
commit98ea5a7b9a182dd31f0b3bc58ddcbc4cb058f75c (patch)
tree4a82e6e059425c0c38eea1d6ee3fd72618de1416
parent2b4a66ed171eb0ecd78a9e7f0c7988bdf409e8cf (diff)
downloadsrc-98ea5a7b9a1.tar.gz
src-98ea5a7b9a1.zip
if_dwc: Add checksum offloading support
Notes
Notes: svn path=/head/; revision=367888
-rw-r--r--sys/dev/dwc/if_dwc.c52
1 files changed, 44 insertions, 8 deletions
diff --git a/sys/dev/dwc/if_dwc.c b/sys/dev/dwc/if_dwc.c
index 2a2b285bf31e..cd0e48b3f689 100644
--- a/sys/dev/dwc/if_dwc.c
+++ b/sys/dev/dwc/if_dwc.c
@@ -155,7 +155,6 @@ __FBSDID("$FreeBSD$");
#define RDESC0_FS (1U << 9) /* First Descriptor */
#define RDESC0_LS (1U << 8) /* Last Descriptor */
#define RDESC0_ICE (1U << 7) /* IPC Checksum Error */
-#define RDESC0_GF (1U << 7) /* Giant Frame */
#define RDESC0_LC (1U << 6) /* Late Collision */
#define RDESC0_FT (1U << 5) /* Frame Type */
#define RDESC0_RWT (1U << 4) /* Receive Watchdog Timeout */
@@ -628,7 +627,7 @@ dwc_get1paddr(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
inline static void
dwc_setup_txdesc(struct dwc_softc *sc, int idx, bus_addr_t paddr,
- uint32_t len)
+ uint32_t len, uint32_t flags)
{
uint32_t desc0, desc1;
@@ -641,10 +640,10 @@ dwc_setup_txdesc(struct dwc_softc *sc, int idx, bus_addr_t paddr,
if (sc->mactype != DWC_GMAC_EXT_DESC) {
desc0 = 0;
desc1 = NTDESC1_TCH | NTDESC1_FS | NTDESC1_LS |
- NTDESC1_IC | len;
+ NTDESC1_IC | len | flags;
} else {
desc0 = ETDESC0_TCH | ETDESC0_FS | ETDESC0_LS |
- ETDESC0_IC;
+ ETDESC0_IC | flags;
desc1 = len;
}
++sc->txcount;
@@ -667,6 +666,7 @@ dwc_setup_txbuf(struct dwc_softc *sc, int idx, struct mbuf **mp)
struct bus_dma_segment seg;
int error, nsegs;
struct mbuf * m;
+ uint32_t flags = 0;
if ((m = m_defrag(*mp, M_NOWAIT)) == NULL)
return (ENOMEM);
@@ -685,7 +685,21 @@ dwc_setup_txbuf(struct dwc_softc *sc, int idx, struct mbuf **mp)
sc->txbuf_map[idx].mbuf = m;
- dwc_setup_txdesc(sc, idx, seg.ds_addr, seg.ds_len);
+ if ((m->m_pkthdr.csum_flags & CSUM_IP) != 0) {
+ if ((m->m_pkthdr.csum_flags & (CSUM_TCP|CSUM_UDP)) != 0) {
+ if (sc->mactype != DWC_GMAC_EXT_DESC)
+ flags = NTDESC1_CIC_FULL;
+ else
+ flags = ETDESC0_CIC_FULL;
+ } else {
+ if (sc->mactype != DWC_GMAC_EXT_DESC)
+ flags = NTDESC1_CIC_HDR;
+ else
+ flags = ETDESC0_CIC_HDR;
+ }
+ }
+
+ dwc_setup_txdesc(sc, idx, seg.ds_addr, seg.ds_len, flags);
return (0);
}
@@ -807,6 +821,18 @@ dwc_rxfinish_one(struct dwc_softc *sc, struct dwc_hwdesc *desc,
m->m_len = len;
if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1);
+ if ((if_getcapenable(ifp) & IFCAP_RXCSUM) != 0 &&
+ (rdesc0 & RDESC0_FT) != 0) {
+ m->m_pkthdr.csum_flags = CSUM_IP_CHECKED;
+ if ((rdesc0 & RDESC0_ICE) == 0)
+ m->m_pkthdr.csum_flags |= CSUM_IP_VALID;
+ if ((rdesc0 & RDESC0_PCE) == 0) {
+ m->m_pkthdr.csum_flags |=
+ CSUM_DATA_VALID | CSUM_PSEUDO_HDR;
+ m->m_pkthdr.csum_data = 0xffff;
+ }
+ }
+
/* Remove trailing FCS */
m_adj(m, -ETHER_CRC_LEN);
@@ -893,7 +919,7 @@ setup_dma(struct dwc_softc *sc)
"could not create TX buffer DMA map.\n");
goto out;
}
- dwc_setup_txdesc(sc, idx, 0, 0);
+ dwc_setup_txdesc(sc, idx, 0, 0, 0);
}
/*
@@ -1139,6 +1165,14 @@ dwc_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
/* No work to do except acknowledge the change took */
if_togglecapenable(ifp, IFCAP_VLAN_MTU);
}
+ if (mask & IFCAP_RXCSUM)
+ if_togglecapenable(ifp, IFCAP_RXCSUM);
+ if (mask & IFCAP_TXCSUM)
+ if_togglecapenable(ifp, IFCAP_TXCSUM);
+ if ((if_getcapenable(ifp) & IFCAP_TXCSUM) != 0)
+ if_sethwassistbits(ifp, CSUM_IP | CSUM_UDP | CSUM_TCP, 0);
+ else
+ if_sethwassistbits(ifp, 0, CSUM_IP | CSUM_UDP | CSUM_TCP);
break;
default:
@@ -1173,7 +1207,7 @@ dwc_txfinish_locked(struct dwc_softc *sc)
bus_dmamap_unload(sc->txbuf_tag, bmap->map);
m_freem(bmap->mbuf);
bmap->mbuf = NULL;
- dwc_setup_txdesc(sc, sc->tx_idx_tail, 0, 0);
+ dwc_setup_txdesc(sc, sc->tx_idx_tail, 0, 0, 0);
sc->tx_idx_tail = next_txidx(sc, sc->tx_idx_tail);
if_setdrvflagbits(ifp, 0, IFF_DRV_OACTIVE);
if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
@@ -1212,6 +1246,7 @@ dwc_rxfinish_locked(struct dwc_softc *sc)
if (error != 0)
panic("dwc_setup_rxbuf failed: error %d\n",
error);
+
}
sc->rx_idx = next_rxidx(sc, sc->rx_idx);
}
@@ -1561,7 +1596,8 @@ dwc_attach(device_t dev)
if_setinitfn(ifp, dwc_init);
if_setsendqlen(ifp, TX_DESC_COUNT - 1);
if_setsendqready(sc->ifp);
- if_setcapabilities(sc->ifp, IFCAP_VLAN_MTU);
+ if_sethwassist(sc->ifp, CSUM_IP | CSUM_UDP | CSUM_TCP);
+ if_setcapabilities(sc->ifp, IFCAP_VLAN_MTU | IFCAP_HWCSUM);
if_setcapenable(sc->ifp, if_getcapabilities(sc->ifp));
/* Attach the mii driver. */