hyperv/hn: Fix if_hw_tsomax setup.
MFC after: 1 week Sponsored by: Microsoft Differential Revision: https://reviews.freebsd.org/D8089
This commit is contained in:
parent
65ca331080
commit
c21d553cfa
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=306937
@ -244,6 +244,8 @@ struct hn_softc {
|
||||
|
||||
uint32_t hn_rndis_rid;
|
||||
uint32_t hn_ndis_ver;
|
||||
int hn_ndis_tso_szmax;
|
||||
int hn_ndis_tso_sgmin;
|
||||
|
||||
struct ndis_rssprm_toeplitz hn_rss;
|
||||
};
|
||||
|
@ -230,7 +230,7 @@ SYSCTL_INT(_hw_hn, OID_AUTO, trust_hostip, CTLFLAG_RDTUN,
|
||||
"when csum info is missing (global setting)");
|
||||
|
||||
/* Limit TSO burst size */
|
||||
static int hn_tso_maxlen = 0;
|
||||
static int hn_tso_maxlen = IP_MAXPACKET;
|
||||
SYSCTL_INT(_hw_hn, OID_AUTO, tso_maxlen, CTLFLAG_RDTUN,
|
||||
&hn_tso_maxlen, 0, "TSO burst limit");
|
||||
|
||||
@ -338,6 +338,7 @@ static int hn_encap(struct hn_tx_ring *, struct hn_txdesc *, struct mbuf **);
|
||||
static int hn_create_rx_data(struct hn_softc *sc, int);
|
||||
static void hn_destroy_rx_data(struct hn_softc *sc);
|
||||
static void hn_set_chim_size(struct hn_softc *, int);
|
||||
static void hn_set_tso_maxsize(struct hn_softc *, int, int);
|
||||
static int hn_chan_attach(struct hn_softc *, struct vmbus_channel *);
|
||||
static void hn_chan_detach(struct hn_softc *, struct vmbus_channel *);
|
||||
static int hn_attach_subchans(struct hn_softc *);
|
||||
@ -520,7 +521,6 @@ netvsc_attach(device_t dev)
|
||||
uint32_t link_status;
|
||||
struct ifnet *ifp = NULL;
|
||||
int error, ring_cnt, tx_ring_cnt;
|
||||
int tso_maxlen;
|
||||
|
||||
sc->hn_dev = dev;
|
||||
sc->hn_prichan = vmbus_get_channel(dev);
|
||||
@ -720,18 +720,16 @@ netvsc_attach(device_t dev)
|
||||
/* Enable all available capabilities by default. */
|
||||
ifp->if_capenable = ifp->if_capabilities;
|
||||
|
||||
tso_maxlen = hn_tso_maxlen;
|
||||
if (tso_maxlen <= 0 || tso_maxlen > IP_MAXPACKET)
|
||||
tso_maxlen = IP_MAXPACKET;
|
||||
ifp->if_hw_tsomaxsegcount = HN_TX_DATA_SEGCNT_MAX;
|
||||
ifp->if_hw_tsomaxsegsize = PAGE_SIZE;
|
||||
ifp->if_hw_tsomax = tso_maxlen -
|
||||
(ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN);
|
||||
if (ifp->if_capabilities & (IFCAP_TSO6 | IFCAP_TSO4)) {
|
||||
hn_set_tso_maxsize(sc, hn_tso_maxlen, ETHERMTU);
|
||||
ifp->if_hw_tsomaxsegcount = HN_TX_DATA_SEGCNT_MAX;
|
||||
ifp->if_hw_tsomaxsegsize = PAGE_SIZE;
|
||||
}
|
||||
|
||||
ether_ifattach(ifp, eaddr);
|
||||
|
||||
if (bootverbose) {
|
||||
if_printf(ifp, "TSO: %u/%u/%u\n", ifp->if_hw_tsomax,
|
||||
if ((ifp->if_capabilities & (IFCAP_TSO6 | IFCAP_TSO4)) && bootverbose) {
|
||||
if_printf(ifp, "TSO segcnt %u segsz %u\n",
|
||||
ifp->if_hw_tsomaxsegcount, ifp->if_hw_tsomaxsegsize);
|
||||
}
|
||||
|
||||
@ -1672,6 +1670,7 @@ hn_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
|
||||
|
||||
if (sc->hn_tx_ring[0].hn_chim_size > sc->hn_chim_szmax)
|
||||
hn_set_chim_size(sc, sc->hn_chim_szmax);
|
||||
hn_set_tso_maxsize(sc, hn_tso_maxlen, ifr->ifr_mtu);
|
||||
|
||||
/* All done! Resume now. */
|
||||
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
|
||||
@ -2918,6 +2917,34 @@ hn_set_chim_size(struct hn_softc *sc, int chim_size)
|
||||
sc->hn_tx_ring[i].hn_chim_size = chim_size;
|
||||
}
|
||||
|
||||
static void
|
||||
hn_set_tso_maxsize(struct hn_softc *sc, int tso_maxlen, int mtu)
|
||||
{
|
||||
struct ifnet *ifp = sc->hn_ifp;
|
||||
int tso_minlen;
|
||||
|
||||
if ((ifp->if_capabilities & (IFCAP_TSO4 | IFCAP_TSO6)) == 0)
|
||||
return;
|
||||
|
||||
KASSERT(sc->hn_ndis_tso_sgmin >= 2,
|
||||
("invalid NDIS tso sgmin %d", sc->hn_ndis_tso_sgmin));
|
||||
tso_minlen = sc->hn_ndis_tso_sgmin * mtu;
|
||||
|
||||
KASSERT(sc->hn_ndis_tso_szmax >= tso_minlen &&
|
||||
sc->hn_ndis_tso_szmax <= IP_MAXPACKET,
|
||||
("invalid NDIS tso szmax %d", sc->hn_ndis_tso_szmax));
|
||||
|
||||
if (tso_maxlen < tso_minlen)
|
||||
tso_maxlen = tso_minlen;
|
||||
else if (tso_maxlen > IP_MAXPACKET)
|
||||
tso_maxlen = IP_MAXPACKET;
|
||||
if (tso_maxlen > sc->hn_ndis_tso_szmax)
|
||||
tso_maxlen = sc->hn_ndis_tso_szmax;
|
||||
ifp->if_hw_tsomax = tso_maxlen - (ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN);
|
||||
if (bootverbose)
|
||||
if_printf(ifp, "TSO size max %u\n", ifp->if_hw_tsomax);
|
||||
}
|
||||
|
||||
static void
|
||||
hn_fixup_tx_data(struct hn_softc *sc)
|
||||
{
|
||||
@ -3424,7 +3451,7 @@ hn_synth_attach(struct hn_softc *sc, int mtu)
|
||||
/*
|
||||
* Attach RNDIS _after_ NVS is attached.
|
||||
*/
|
||||
error = hn_rndis_attach(sc);
|
||||
error = hn_rndis_attach(sc, mtu);
|
||||
if (error)
|
||||
return (error);
|
||||
|
||||
|
@ -39,6 +39,8 @@ __FBSDID("$FreeBSD$");
|
||||
#include <net/if_var.h>
|
||||
#include <net/ethernet.h>
|
||||
#include <net/rndis.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <sys/types.h>
|
||||
#include <machine/atomic.h>
|
||||
#include <sys/sema.h>
|
||||
@ -77,6 +79,8 @@ __FBSDID("$FreeBSD$");
|
||||
NDIS_TXCSUM_CAP_IP6EXT)
|
||||
#define HN_NDIS_TXCSUM_CAP_UDP6 \
|
||||
(NDIS_TXCSUM_CAP_UDP6 | NDIS_TXCSUM_CAP_IP6EXT)
|
||||
#define HN_NDIS_LSOV2_CAP_IP6 \
|
||||
(NDIS_LSOV2_CAP_IP6EXT | NDIS_LSOV2_CAP_TCP6OPT)
|
||||
|
||||
/*
|
||||
* Forward declarations
|
||||
@ -93,7 +97,7 @@ static int hn_rndis_query2(struct hn_softc *sc, uint32_t oid,
|
||||
size_t min_odlen);
|
||||
static int hn_rndis_set(struct hn_softc *sc, uint32_t oid, const void *data,
|
||||
size_t dlen);
|
||||
static int hn_rndis_conf_offload(struct hn_softc *sc);
|
||||
static int hn_rndis_conf_offload(struct hn_softc *sc, int mtu);
|
||||
static int hn_rndis_query_hwcaps(struct hn_softc *sc,
|
||||
struct ndis_offload *caps);
|
||||
|
||||
@ -830,13 +834,13 @@ hn_rndis_set(struct hn_softc *sc, uint32_t oid, const void *data, size_t dlen)
|
||||
}
|
||||
|
||||
static int
|
||||
hn_rndis_conf_offload(struct hn_softc *sc)
|
||||
hn_rndis_conf_offload(struct hn_softc *sc, int mtu)
|
||||
{
|
||||
struct ndis_offload hwcaps;
|
||||
struct ndis_offload_params params;
|
||||
uint32_t caps = 0;
|
||||
size_t paramsz;
|
||||
int error;
|
||||
int error, tso_maxsz, tso_minsg;
|
||||
|
||||
error = hn_rndis_query_hwcaps(sc, &hwcaps);
|
||||
if (error) {
|
||||
@ -857,18 +861,58 @@ hn_rndis_conf_offload(struct hn_softc *sc)
|
||||
}
|
||||
params.ndis_hdr.ndis_size = paramsz;
|
||||
|
||||
/* TSO */
|
||||
/*
|
||||
* TSO4/TSO6 setup.
|
||||
*/
|
||||
tso_maxsz = IP_MAXPACKET;
|
||||
tso_minsg = 2;
|
||||
if (hwcaps.ndis_lsov2.ndis_ip4_encap & NDIS_OFFLOAD_ENCAP_8023) {
|
||||
caps |= HN_CAP_TSO4;
|
||||
params.ndis_lsov2_ip4 = NDIS_OFFLOAD_LSOV2_ON;
|
||||
/* TODO: tso_max */
|
||||
|
||||
if (hwcaps.ndis_lsov2.ndis_ip4_maxsz < tso_maxsz)
|
||||
tso_maxsz = hwcaps.ndis_lsov2.ndis_ip4_maxsz;
|
||||
if (hwcaps.ndis_lsov2.ndis_ip4_minsg > tso_minsg)
|
||||
tso_minsg = hwcaps.ndis_lsov2.ndis_ip4_minsg;
|
||||
}
|
||||
if (hwcaps.ndis_lsov2.ndis_ip6_encap & NDIS_OFFLOAD_ENCAP_8023) {
|
||||
if ((hwcaps.ndis_lsov2.ndis_ip6_encap & NDIS_OFFLOAD_ENCAP_8023) &&
|
||||
(hwcaps.ndis_lsov2.ndis_ip6_opts & HN_NDIS_LSOV2_CAP_IP6) ==
|
||||
HN_NDIS_LSOV2_CAP_IP6) {
|
||||
#ifdef notyet
|
||||
caps |= HN_CAP_TSO6;
|
||||
params.ndis_lsov2_ip6 = NDIS_OFFLOAD_LSOV2_ON;
|
||||
|
||||
if (hwcaps.ndis_lsov2.ndis_ip6_maxsz < tso_maxsz)
|
||||
tso_maxsz = hwcaps.ndis_lsov2.ndis_ip6_maxsz;
|
||||
if (hwcaps.ndis_lsov2.ndis_ip6_minsg > tso_minsg)
|
||||
tso_minsg = hwcaps.ndis_lsov2.ndis_ip6_minsg;
|
||||
#endif
|
||||
/* TODO: tso_max */
|
||||
}
|
||||
sc->hn_ndis_tso_szmax = 0;
|
||||
sc->hn_ndis_tso_sgmin = 0;
|
||||
if (caps & (HN_CAP_TSO4 | HN_CAP_TSO6)) {
|
||||
KASSERT(tso_maxsz <= IP_MAXPACKET,
|
||||
("invalid NDIS TSO maxsz %d", tso_maxsz));
|
||||
KASSERT(tso_minsg >= 2,
|
||||
("invalid NDIS TSO minsg %d", tso_minsg));
|
||||
if (tso_maxsz < tso_minsg * mtu) {
|
||||
if_printf(sc->hn_ifp, "invalid NDIS TSO config: "
|
||||
"maxsz %d, minsg %d, mtu %d; "
|
||||
"disable TSO4 and TSO6\n",
|
||||
tso_maxsz, tso_minsg, mtu);
|
||||
caps &= ~(HN_CAP_TSO4 | HN_CAP_TSO6);
|
||||
params.ndis_lsov2_ip4 = NDIS_OFFLOAD_LSOV2_OFF;
|
||||
params.ndis_lsov2_ip6 = NDIS_OFFLOAD_LSOV2_OFF;
|
||||
} else {
|
||||
sc->hn_ndis_tso_szmax = tso_maxsz;
|
||||
sc->hn_ndis_tso_sgmin = tso_minsg;
|
||||
if (bootverbose) {
|
||||
if_printf(sc->hn_ifp, "NDIS TSO "
|
||||
"szmax %d sgmin %d\n",
|
||||
sc->hn_ndis_tso_szmax,
|
||||
sc->hn_ndis_tso_sgmin);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* IPv4 checksum */
|
||||
@ -1186,7 +1230,7 @@ hn_rndis_query_hwcaps(struct hn_softc *sc, struct ndis_offload *caps)
|
||||
}
|
||||
|
||||
int
|
||||
hn_rndis_attach(struct hn_softc *sc)
|
||||
hn_rndis_attach(struct hn_softc *sc, int mtu)
|
||||
{
|
||||
int error;
|
||||
|
||||
@ -1201,7 +1245,7 @@ hn_rndis_attach(struct hn_softc *sc)
|
||||
* Configure NDIS offload settings.
|
||||
* XXX no offloading, if error happened?
|
||||
*/
|
||||
hn_rndis_conf_offload(sc);
|
||||
hn_rndis_conf_offload(sc, mtu);
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
@ -117,7 +117,7 @@ struct rndis_packet_msg;
|
||||
uint32_t hn_chim_alloc(struct hn_softc *sc);
|
||||
void hn_chim_free(struct hn_softc *sc, uint32_t chim_idx);
|
||||
|
||||
int hn_rndis_attach(struct hn_softc *sc);
|
||||
int hn_rndis_attach(struct hn_softc *sc, int mtu);
|
||||
void hn_rndis_detach(struct hn_softc *sc);
|
||||
int hn_rndis_conf_rss(struct hn_softc *sc, uint16_t flags);
|
||||
void *hn_rndis_pktinfo_append(struct rndis_packet_msg *,
|
||||
|
Loading…
Reference in New Issue
Block a user