Date: Mon, 16 Apr 2007 08:48:24 +0900 From: Pyun YongHyeon <pyunyh@gmail.com> To: Peter Grehan <grehan@freebsd.org> Cc: freebsd-ppc@freebsd.org Subject: Re: CFT: gem(4) checksum offload support Message-ID: <20070415234823.GA21416@cdnetworks.co.kr> In-Reply-To: <46229F3F.40903@freebsd.org> References: <20070414060841.GB12777@cdnetworks.co.kr> <46229F3F.40903@freebsd.org>
next in thread | previous in thread | raw e-mail | index | archive | help
--d6Gm4EdcadzBjdND Content-Type: text/plain; charset=us-ascii Content-Disposition: inline On Sun, Apr 15, 2007 at 02:55:11PM -0700, Peter Grehan wrote: > Hi, > > I get a compile error for this on ppc: > > /usr/home/grehan/freebsd/dev_head/src/sys/dev/gem/if_gem.c: In function > `gem_txdma_callback': > /usr/home/grehan/freebsd/dev_head/src/sys/dev/gem/if_gem.c:92: warning: > inlining failed in call to 'gem_txcksum': function body not available > /usr/home/grehan/freebsd/dev_head/src/sys/dev/gem/if_gem.c:505: warning: > called from here > *** Error code 1 > > Removing the __inline's fixed it, as I guess would re-ordering. > Thank you for testing. I guess you've tested it on RELENG_6. Here is updated patch. -- Regards, Pyun YongHyeon --d6Gm4EdcadzBjdND Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="gem.chksum.patch2" Index: if_gem.c =================================================================== RCS file: /home/ncvs/src/sys/dev/gem/if_gem.c,v retrieving revision 1.40 diff -u -r1.40 if_gem.c --- if_gem.c 6 Dec 2006 02:04:25 -0000 1.40 +++ if_gem.c 15 Apr 2007 23:45:59 -0000 @@ -65,6 +65,12 @@ #include <net/if_types.h> #include <net/if_vlan_var.h> +#include <netinet/in.h> +#include <netinet/in_systm.h> +#include <netinet/ip.h> +#include <netinet/tcp.h> +#include <netinet/udp.h> + #include <machine/bus.h> #include <dev/mii/mii.h> @@ -74,6 +80,7 @@ #include <dev/gem/if_gemvar.h> #define TRIES 10000 +#define GEM_CSUM_FEATURES (CSUM_TCP) static void gem_start(struct ifnet *); static void gem_start_locked(struct ifnet *); @@ -82,6 +89,8 @@ static void gem_cddma_callback(void *, bus_dma_segment_t *, int, int); static void gem_txdma_callback(void *, bus_dma_segment_t *, int, bus_size_t, int); +static __inline void gem_txcksum(struct gem_softc *, struct mbuf *, uint64_t *); +static __inline void gem_rxcksum(struct mbuf *, uint64_t); static void gem_tick(void *); static int gem_watchdog(struct gem_softc *); static void gem_init(void *); @@ -264,6 +273,7 @@ device_printf(sc->sc_dev, "%ukB RX FIFO, %ukB TX FIFO\n", sc->sc_rxfifosize / 1024, v / 16); + sc->sc_csum_features = GEM_CSUM_FEATURES; /* Initialize ifnet structure. */ ifp->if_softc = sc; if_initname(ifp, device_get_name(sc->sc_dev), @@ -332,11 +342,12 @@ #endif /* - * Tell the upper layer(s) we support long frames. + * Tell the upper layer(s) we support long frames/checksum offloads. */ ifp->if_data.ifi_hdrlen = sizeof(struct ether_vlan_header); - ifp->if_capabilities |= IFCAP_VLAN_MTU; - ifp->if_capenable |= IFCAP_VLAN_MTU; + ifp->if_capabilities |= IFCAP_VLAN_MTU | IFCAP_HWCSUM; + ifp->if_hwassist |= sc->sc_csum_features; + ifp->if_capenable |= IFCAP_VLAN_MTU | IFCAP_HWCSUM; return (0); @@ -440,6 +451,112 @@ GEM_UNLOCK(sc); } +static __inline void +gem_txcksum(struct gem_softc *sc, struct mbuf *m, uint64_t *cflags) +{ + struct ip *ip; + uint64_t offset, offset2; + char *p; + + offset = sizeof(struct ip) + ETHER_HDR_LEN; + for(; m && m->m_len == 0; m = m->m_next) + ; + if (m == NULL || m->m_len < ETHER_HDR_LEN) { + device_printf(sc->sc_dev, "%s: m_len < ETHER_HDR_LEN\n", + __func__); + /* checksum will be corrupted */ + goto sendit; + } + if (m->m_len < ETHER_HDR_LEN + sizeof(uint32_t)) { + if (m->m_len != ETHER_HDR_LEN) { + device_printf(sc->sc_dev, + "%s: m_len != ETHER_HDR_LEN\n", __func__); + /* checksum will be corrupted */ + goto sendit; + } + for(m = m->m_next; m && m->m_len == 0; m = m->m_next) + ; + if (m == NULL) { + /* checksum will be corrupted */ + goto sendit; + } + ip = mtod(m, struct ip *); + } else { + p = mtod(m, uint8_t *); + p += ETHER_HDR_LEN; + ip = (struct ip *)p; + } + offset = (ip->ip_hl << 2) + ETHER_HDR_LEN; + +sendit: + offset2 = m->m_pkthdr.csum_data; + *cflags = offset << GEM_TD_CXSUM_SSHIFT; + *cflags |= ((offset + offset2) << GEM_TD_CXSUM_OSHIFT); + *cflags |= GEM_TD_CXSUM_ENABLE; +} + +static __inline void +gem_rxcksum(struct mbuf *m, uint64_t flags) +{ + struct ether_header *eh; + struct ip *ip; + struct udphdr *uh; + int32_t hlen, len, pktlen; + uint16_t cksum, *opts; + uint32_t temp32; + + pktlen = m->m_pkthdr.len; + if (pktlen < sizeof(struct ether_header) + sizeof(struct ip)) + return; + eh = mtod(m, struct ether_header *); + if (eh->ether_type != htons(ETHERTYPE_IP)) + return; + ip = (struct ip *)(eh + 1); + if (ip->ip_v != IPVERSION) + return; + + hlen = ip->ip_hl << 2; + pktlen -= sizeof(struct ether_header); + if (hlen < sizeof(struct ip)) + return; + if (ntohs(ip->ip_len) < hlen) + return; + if (ntohs(ip->ip_len) != pktlen) + return; + if (ip->ip_off & htons(IP_MF | IP_OFFMASK)) + return; /* can't handle fragmented packet */ + + switch (ip->ip_p) { + case IPPROTO_TCP: + if (pktlen < (hlen + sizeof(struct tcphdr))) + return; + break; + case IPPROTO_UDP: + if (pktlen < (hlen + sizeof(struct udphdr))) + return; + uh = (struct udphdr *)((uint8_t *)ip + hlen); + if (uh->uh_sum == 0) + return; /* no checksum */ + break; + default: + return; + } + + cksum = ~(flags & GEM_RD_CHECKSUM); + /* checksum fixup for IP options */ + len = hlen - sizeof(struct ip); + if (len > 0) { + opts = (uint16_t *)(ip + 1); + for (; len > 0; len -= sizeof(uint16_t), opts++) { + temp32 = cksum - *opts; + temp32 = (temp32 >> 16) + (temp32 & 65535); + cksum = temp32 & 65535; + } + } + m->m_pkthdr.csum_flags |= CSUM_DATA_VALID; + m->m_pkthdr.csum_data = cksum; +} + static void gem_cddma_callback(xsc, segs, nsegs, error) void *xsc; @@ -470,7 +587,7 @@ struct gem_softc *sc = txd->txd_sc; struct gem_txsoft *txs = txd->txd_txs; bus_size_t len = 0; - uint64_t flags = 0; + uint64_t cflags, flags; int seg, nexttx; if (error != 0) @@ -488,6 +605,10 @@ txs->txs_ndescs = nsegs; nexttx = txs->txs_firstdesc; + + flags = cflags = 0; + if ((txd->m->m_pkthdr.csum_flags & sc->sc_csum_features) != 0) + gem_txcksum(sc, txd->m, &cflags); /* * Initialize the transmit descriptors. */ @@ -507,6 +628,7 @@ KASSERT(segs[seg].ds_len < GEM_TD_BUFSIZE, ("gem_txdma_callback: segment size too large!")); flags = segs[seg].ds_len & GEM_TD_BUFSIZE; + flags |= cflags; if (len == 0) { #ifdef GEM_DEBUG CTR2(KTR_GEM, "txdma_cb: start of packet at seg %d, " @@ -954,12 +1076,14 @@ /* Encode Receive Descriptor ring size: four possible values */ v = gem_ringsize(GEM_NRXDESC /*XXX*/); + /* Rx TCP/UDP checksum offset */ + v |= ((ETHER_HDR_LEN + sizeof(struct ip)) << + GEM_RX_CONFIG_CXM_START_SHFT); /* Enable DMA */ bus_space_write_4(t, h, GEM_RX_CONFIG, v|(GEM_THRSH_1024<<GEM_RX_CONFIG_FIFO_THRS_SHIFT)| - (2<<GEM_RX_CONFIG_FBOFF_SHFT)|GEM_RX_CONFIG_RXDMA_EN| - (0<<GEM_RX_CONFIG_CXM_START_SHFT)); + (2<<GEM_RX_CONFIG_FBOFF_SHFT)|GEM_RX_CONFIG_RXDMA_EN); /* * The following value is for an OFF Threshold of about 3/4 full * and an ON Threshold of 1/4 full. @@ -974,7 +1098,7 @@ /* step 12. RX_MAC Configuration Register */ v = bus_space_read_4(t, h, GEM_MAC_RX_CONFIG); - v |= GEM_MAC_RX_ENABLE; + v |= GEM_MAC_RX_ENABLE | GEM_MAC_RX_STRIP_CRC; bus_space_write_4(t, h, GEM_MAC_RX_CONFIG, v); /* step 14. Issue Transmit Pending command */ @@ -1008,6 +1132,7 @@ txd.txd_sc = sc; txd.txd_txs = txs; txs->txs_firstdesc = sc->sc_txnext; + txd.m = m0; error = bus_dmamap_load_mbuf(sc->sc_tdmatag, txs->txs_dmamap, m0, gem_txdma_callback, &txd, BUS_DMA_NOWAIT); if (error != 0) @@ -1454,8 +1579,7 @@ #endif /* - * No errors; receive the packet. Note the Gem - * includes the CRC with every packet. + * No errors; receive the packet. */ len = GEM_RD_BUFLEN(rxstat); @@ -1473,7 +1597,10 @@ m->m_data += 2; /* We're already off by two */ m->m_pkthdr.rcvif = ifp; - m->m_pkthdr.len = m->m_len = len - ETHER_CRC_LEN; + m->m_pkthdr.len = m->m_len = len; + + if ((ifp->if_capenable & IFCAP_RXCSUM) != 0) + gem_rxcksum(m, rxstat); /* Pass it on. */ GEM_UNLOCK(sc); @@ -1876,6 +2003,12 @@ if (ifp->if_drv_flags & IFF_DRV_RUNNING) gem_stop(ifp, 0); } + if ((ifp->if_flags & IFF_LINK0) != 0) + sc->sc_csum_features |= CSUM_UDP; + else + sc->sc_csum_features &= ~CSUM_UDP; + if ((ifp->if_capenable & IFCAP_TXCSUM) != 0) + ifp->if_hwassist = sc->sc_csum_features; sc->sc_ifflags = ifp->if_flags; GEM_UNLOCK(sc); break; @@ -1889,6 +2022,15 @@ case SIOCSIFMEDIA: error = ifmedia_ioctl(ifp, ifr, &sc->sc_mii->mii_media, cmd); break; + case SIOCSIFCAP: + GEM_LOCK(sc); + ifp->if_capenable = ifr->ifr_reqcap; + if ((ifp->if_capenable & IFCAP_TXCSUM) != 0) + ifp->if_hwassist = sc->sc_csum_features; + else + ifp->if_hwassist = 0; + GEM_UNLOCK(sc); + break; default: error = ether_ioctl(ifp, cmd, data); break; Index: if_gemreg.h =================================================================== RCS file: /home/ncvs/src/sys/dev/gem/if_gemreg.h,v retrieving revision 1.3 diff -u -r1.3 if_gemreg.h --- if_gemreg.h 6 Jan 2005 01:42:42 -0000 1.3 +++ if_gemreg.h 15 Apr 2007 23:45:59 -0000 @@ -516,6 +516,10 @@ #define GEM_TD_START_OF_PACKET 0x0000000080000000LL #define GEM_TD_INTERRUPT_ME 0x0000000100000000LL /* Interrupt me now */ #define GEM_TD_NO_CRC 0x0000000200000000LL /* do not insert crc */ + +#define GEM_TD_CXSUM_SSHIFT 15 +#define GEM_TD_CXSUM_OSHIFT 21 + /* * Only need to set GEM_TD_CXSUM_ENABLE, GEM_TD_CXSUM_STUFF, * GEM_TD_CXSUM_START, and GEM_TD_INTERRUPT_ME in 1st descriptor of a group. Index: if_gemvar.h =================================================================== RCS file: /home/ncvs/src/sys/dev/gem/if_gemvar.h,v retrieving revision 1.12 diff -u -r1.12 if_gemvar.h --- if_gemvar.h 6 Dec 2006 02:04:25 -0000 1.12 +++ if_gemvar.h 15 Apr 2007 23:45:59 -0000 @@ -108,6 +108,7 @@ struct gem_txdma { struct gem_softc *txd_sc; struct gem_txsoft *txd_txs; + struct mbuf *m; }; /* @@ -189,6 +190,7 @@ int sc_inited; int sc_debug; int sc_ifflags; + int sc_csum_features; struct mtx sc_mtx; }; --d6Gm4EdcadzBjdND--
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20070415234823.GA21416>