Date: Tue, 16 Jul 2013 04:39:44 +0000 (UTC) From: Bryan Venteicher <bryanv@FreeBSD.org> To: src-committers@freebsd.org, svn-src-projects@freebsd.org Subject: svn commit: r253377 - projects/vmxnet/sys/dev/vmware/vmxnet3 Message-ID: <201307160439.r6G4didh084138@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: bryanv Date: Tue Jul 16 04:39:44 2013 New Revision: 253377 URL: http://svnweb.freebsd.org/changeset/base/253377 Log: Add TSO support and cleanup checksum offloading Modified: projects/vmxnet/sys/dev/vmware/vmxnet3/if_vmx.c projects/vmxnet/sys/dev/vmware/vmxnet3/if_vmxvar.h Modified: projects/vmxnet/sys/dev/vmware/vmxnet3/if_vmx.c ============================================================================== --- projects/vmxnet/sys/dev/vmware/vmxnet3/if_vmx.c Tue Jul 16 03:12:31 2013 (r253376) +++ projects/vmxnet/sys/dev/vmware/vmxnet3/if_vmx.c Tue Jul 16 04:39:44 2013 (r253377) @@ -112,6 +112,7 @@ static int vmxnet3_alloc_queue_data(stru static void vmxnet3_free_queue_data(struct vmxnet3_softc *); static int vmxnet3_alloc_mcast_table(struct vmxnet3_softc *); static void vmxnet3_init_shared_data(struct vmxnet3_softc *); +static void vmxnet3_reinit_interface(struct vmxnet3_softc *); static void vmxnet3_reinit_shared_data(struct vmxnet3_softc *); static int vmxnet3_alloc_data(struct vmxnet3_softc *); static void vmxnet3_free_data(struct vmxnet3_softc *); @@ -454,10 +455,8 @@ vmxnet3_alloc_msix_interrupts(struct vmx if (nmsix < required) return (1); - int error; - cnt = required; - if ((error = pci_alloc_msix(dev, &cnt)) == 0 && cnt >= required) { + if (pci_alloc_msix(dev, &cnt) == 0 && cnt >= required) { sc->vmx_nintrs = required; return (0); } @@ -502,7 +501,6 @@ vmxnet3_alloc_interrupt(struct vmxnet3_s struct vmxnet3_interrupt *intr) { struct resource *irq; - int old_rid = rid; irq = bus_alloc_resource_any(sc->vmx_dev, SYS_RES_IRQ, &rid, flags); if (irq == NULL) @@ -927,10 +925,6 @@ vmxnet3_alloc_txq_data(struct vmxnet3_so txr = &txq->vxtxq_cmd_ring; txc = &txq->vxtxq_comp_ring; - /* - * XXX BMV Need better way to determine the maximum - * size/segments/segsize arguments. - */ error = bus_dma_tag_create(bus_get_dma_tag(dev), 1, 0, /* alignment, boundary */ BUS_SPACE_MAXADDR, /* lowaddr */ @@ -938,7 +932,7 @@ vmxnet3_alloc_txq_data(struct vmxnet3_so NULL, NULL, /* filter, filterarg */ VMXNET3_TSO_MAXSIZE, /* maxsize */ VMXNET3_TX_MAXSEGS, /* nsegments */ - PAGE_SIZE, /* maxsegsize */ + VMXNET3_TX_MAXSEGSIZE, /* maxsegsize */ 0, /* flags */ NULL, NULL, /* lockfunc, lockarg */ &txr->vxtxr_txtag); @@ -1294,22 +1288,40 @@ vmxnet3_init_shared_data(struct vmxnet3_ } static void -vmxnet3_reinit_shared_data(struct vmxnet3_softc *sc) +vmxnet3_reinit_interface(struct vmxnet3_softc *sc) { struct ifnet *ifp; - struct vmxnet3_driver_shared *ds; ifp = sc->vmx_ifp; - ds = sc->vmx_ds; /* Use the current MAC address. */ bcopy(IF_LLADDR(sc->vmx_ifp), sc->vmx_lladdr, ETHER_ADDR_LEN); vmxnet3_set_lladdr(sc); + ifp->if_hwassist = 0; + if (ifp->if_capenable & IFCAP_TXCSUM) + ifp->if_hwassist |= VMXNET3_CSUM_OFFLOAD; + if (ifp->if_capenable & IFCAP_TXCSUM_IPV6) + ifp->if_hwassist |= VMXNET3_CSUM_OFFLOAD_IPV6; + if (ifp->if_capenable & IFCAP_TSO4) + ifp->if_hwassist |= CSUM_TSO; + if (ifp->if_capenable & IFCAP_TSO6) + ifp->if_hwassist |= CSUM_TSO; /* No CSUM_TSO_IPV6. */ +} + +static void +vmxnet3_reinit_shared_data(struct vmxnet3_softc *sc) +{ + struct ifnet *ifp; + struct vmxnet3_driver_shared *ds; + + ifp = sc->vmx_ifp; + ds = sc->vmx_ds; + ds->upt_features = 0; if (ifp->if_capenable & IFCAP_VLAN_HWTAGGING) ds->upt_features |= UPT1_F_VLAN; - if (ifp->if_capenable & IFCAP_RXCSUM) + if (ifp->if_capenable & (IFCAP_RXCSUM | IFCAP_RXCSUM_IPV6)) ds->upt_features |= UPT1_F_CSUM; ds->mtu = ifp->if_mtu; @@ -1380,9 +1392,11 @@ vmxnet3_setup_interface(struct vmxnet3_s vmxnet3_get_lladdr(sc); ether_ifattach(ifp, sc->vmx_lladdr); - ifp->if_capabilities |= IFCAP_VLAN_MTU | IFCAP_VLAN_HWTAGGING; ifp->if_capabilities |= IFCAP_RXCSUM | IFCAP_TXCSUM; - ifp->if_hwassist |= VMXNET3_CSUM_FEATURES; + ifp->if_capabilities |= IFCAP_RXCSUM_IPV6 | IFCAP_TXCSUM_IPV6; + ifp->if_capabilities |= IFCAP_TSO4 | IFCAP_TSO6; + ifp->if_capabilities |= IFCAP_VLAN_MTU | IFCAP_VLAN_HWTAGGING; + ifp->if_hwassist |= VMXNET3_CSUM_ALL_OFFLOAD; ifp->if_capenable = ifp->if_capabilities; @@ -1644,9 +1658,8 @@ vmxnet3_rxeof(struct vmxnet3_softc *sc, m->m_pkthdr.len = m->m_len = length; m->m_pkthdr.csum_flags = 0; - if (ifp->if_capenable & IFCAP_RXCSUM && !rxcd->no_csum) + if (!rxcd->no_csum) vmxnet3_rx_csum(rxcd, m); - if (rxcd->vlan) { m->m_flags |= M_VLANTAG; m->m_pkthdr.ether_vtag = rxcd->vtag; @@ -1965,6 +1978,8 @@ static int vmxnet3_reinit(struct vmxnet3_softc *sc) { + vmxnet3_reinit_interface(sc); + vmxnet3_reinit_shared_data(sc); if (vmxnet3_reinit_queues(sc) != 0) @@ -2063,6 +2078,28 @@ vmxnet3_encap_offload_ctx(struct mbuf *m return (EINVAL); } + if (m->m_pkthdr.csum_flags & CSUM_TSO) { + struct tcphdr *tcp, tcphdr; + + if (__predict_false(*proto != IPPROTO_TCP)) { + /* Likely failed to correctly parse the mbuf. */ + return (EINVAL); + } + + if (m->m_len < *start + sizeof(struct tcphdr)) { + m_copydata(m, offset, sizeof(struct tcphdr), + (caddr_t) &tcphdr); + tcp = &tcphdr; + } else + tcp = (struct tcphdr *)(m->m_data + *start); + + /* + * For TSO, the size of the protocol header is also + * included in the descriptor header size. + */ + *start += (tcp->th_off << 2); + } + return (0); } @@ -2133,7 +2170,7 @@ vmxnet3_encap(struct vmxnet3_softc *sc, if (VMXNET3_TXRING_AVAIL(txr) < nsegs) { vmxnet3_encap_unload_mbuf(sc, txr, dmap); return (ENOSPC); - } else if (m->m_pkthdr.csum_flags & VMXNET3_CSUM_FEATURES) { + } else if (m->m_pkthdr.csum_flags & VMXNET3_CSUM_ALL_OFFLOAD) { error = vmxnet3_encap_offload_ctx(m, &etype, &proto, &start); if (error) { vmxnet3_encap_unload_mbuf(sc, txr, dmap); @@ -2176,7 +2213,12 @@ vmxnet3_encap(struct vmxnet3_softc *sc, sop->vtag = m->m_pkthdr.ether_vtag; } - if (m->m_pkthdr.csum_flags & VMXNET3_CSUM_FEATURES) { + if (m->m_pkthdr.csum_flags & CSUM_TSO) { + sop->offload_mode = VMXNET3_OM_TSO; + sop->hlen = start; + sop->offload_pos = m->m_pkthdr.tso_segsz; + } else if (m->m_pkthdr.csum_flags & (VMXNET3_CSUM_OFFLOAD | + VMXNET3_CSUM_OFFLOAD_IPV6)) { sop->offload_mode = VMXNET3_OM_CSUM; sop->hlen = start; sop->offload_pos = start + m->m_pkthdr.csum_data; Modified: projects/vmxnet/sys/dev/vmware/vmxnet3/if_vmxvar.h ============================================================================== --- projects/vmxnet/sys/dev/vmware/vmxnet3/if_vmxvar.h Tue Jul 16 03:12:31 2013 (r253376) +++ projects/vmxnet/sys/dev/vmware/vmxnet3/if_vmxvar.h Tue Jul 16 04:39:44 2013 (r253377) @@ -210,10 +210,16 @@ struct vmxnet3_softc { * Max descriptors per Tx packet. We must limit the size of the * any TSO packets based on the number of segments. */ -#define VMXNET3_TX_MAXSEGS 16 +#define VMXNET3_TX_MAXSEGS 32 #define VMXNET3_TSO_MAXSIZE 65550 /* + * Maximum support Tx segments size. The length field in the + * Tx descriptor is 14 bits. + */ +#define VMXNET3_TX_MAXSEGSIZE (1 << 14) + +/* * Predetermined size of the multicast MACs filter table. If the * number of multicast addresses exceeds this size, then the * ALL_MULTI mode is use instead. @@ -228,6 +234,10 @@ struct vmxnet3_softc { /* * IP protocols that we can perform Tx checksum offloading of. */ -#define VMXNET3_CSUM_FEATURES (CSUM_UDP | CSUM_TCP) +#define VMXNET3_CSUM_OFFLOAD (CSUM_TCP | CSUM_UDP) +#define VMXNET3_CSUM_OFFLOAD_IPV6 (CSUM_TCP_IPV6 | CSUM_UDP_IPV6) + +#define VMXNET3_CSUM_ALL_OFFLOAD \ + (VMXNET3_CSUM_OFFLOAD | VMXNET3_CSUM_OFFLOAD_IPV6 | CSUM_TSO) #endif /* _IF_VMXVAR_H */
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201307160439.r6G4didh084138>