Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 14 Oct 2016 02:27:19 +0000 (UTC)
From:      Sepherosa Ziehau <sephe@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org
Subject:   svn commit: r307246 - stable/10/sys/dev/hyperv/netvsc
Message-ID:  <201610140227.u9E2RJ10049288@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: sephe
Date: Fri Oct 14 02:27:19 2016
New Revision: 307246
URL: https://svnweb.freebsd.org/changeset/base/307246

Log:
  MFC 306013,306014
  
  306013
      hyperv/hn: Fix ifnet hwassist setup.
  
      Sponsored by:   Microsoft
      Differential Revision:  https://reviews.freebsd.org/D7948
  
  306014
      hyperv/hn: Let the caller of hn_nvs_doinit() do the error logging.
  
      So that NVS version probing failure does not look too scary.
  
      Sponsored by:   Microsoft
      Differential Revision:  https://reviews.freebsd.org/D7950

Modified:
  stable/10/sys/dev/hyperv/netvsc/hv_net_vsc.c
  stable/10/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/sys/dev/hyperv/netvsc/hv_net_vsc.c
==============================================================================
--- stable/10/sys/dev/hyperv/netvsc/hv_net_vsc.c	Fri Oct 14 02:19:47 2016	(r307245)
+++ stable/10/sys/dev/hyperv/netvsc/hv_net_vsc.c	Fri Oct 14 02:27:19 2016	(r307246)
@@ -443,8 +443,15 @@ hn_nvs_doinit(struct hn_softc *sc, uint3
 	vmbus_xact_put(xact);
 
 	if (status != HN_NVS_STATUS_OK) {
-		if_printf(sc->hn_ifp, "nvs init failed for ver 0x%x\n",
-		    nvs_ver);
+		if (bootverbose) {
+			/*
+			 * Caller may try another NVS version, and will log
+			 * error if there are no more NVS versions to try,
+			 * so don't bark out loud here.
+			 */
+			if_printf(sc->hn_ifp, "nvs init failed for ver 0x%x\n",
+			    nvs_ver);
+		}
 		return (EINVAL);
 	}
 	return (0);
@@ -498,7 +505,7 @@ hn_nvs_init_ndis(struct hn_softc *sc)
 static int
 hn_nvs_init(struct hn_softc *sc)
 {
-	int i;
+	int i, error;
 
 	if (device_is_attached(sc->hn_dev)) {
 		/*
@@ -510,15 +517,19 @@ hn_nvs_init(struct hn_softc *sc)
 			    HN_NDIS_VERSION_MAJOR(sc->hn_ndis_ver),
 			    HN_NDIS_VERSION_MINOR(sc->hn_ndis_ver));
 		}
-		return (hn_nvs_doinit(sc, sc->hn_nvs_ver));
+
+		error = hn_nvs_doinit(sc, sc->hn_nvs_ver);
+		if (error) {
+			if_printf(sc->hn_ifp, "reinit NVS version 0x%x "
+			    "failed: %d\n", sc->hn_nvs_ver, error);
+		}
+		return (error);
 	}
 
 	/*
 	 * Find the supported NVS version and set NDIS version accordingly.
 	 */
 	for (i = 0; i < nitems(hn_nvs_version); ++i) {
-		int error;
-
 		error = hn_nvs_doinit(sc, hn_nvs_version[i]);
 		if (!error) {
 			sc->hn_nvs_ver = hn_nvs_version[i];

Modified: stable/10/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c
==============================================================================
--- stable/10/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c	Fri Oct 14 02:19:47 2016	(r307245)
+++ stable/10/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c	Fri Oct 14 02:27:19 2016	(r307246)
@@ -182,14 +182,6 @@ struct hn_txdesc {
 #define HN_TXD_FLAG_ONLIST	0x1
 #define HN_TXD_FLAG_DMAMAP	0x2
 
-/*
- * Only enable UDP checksum offloading when it is on 2012R2 or
- * later.  UDP checksum offloading doesn't work on earlier
- * Windows releases.
- */
-#define HN_CSUM_ASSIST_WIN8	(CSUM_IP | CSUM_TCP)
-#define HN_CSUM_ASSIST		(CSUM_IP | CSUM_UDP | CSUM_TCP)
-
 #define HN_LRO_LENLIM_MULTIRX_DEF	(12 * ETHERMTU)
 #define HN_LRO_LENLIM_DEF		(25 * ETHERMTU)
 /* YYY 2*MTU is a bit rough, but should be good enough. */
@@ -204,6 +196,13 @@ struct hn_txdesc {
 #define HN_LOCK(sc)			sx_xlock(&(sc)->hn_lock)
 #define HN_UNLOCK(sc)			sx_xunlock(&(sc)->hn_lock)
 
+#define HN_CSUM_IP_MASK			(CSUM_IP | CSUM_IP_TCP | CSUM_IP_UDP)
+#define HN_CSUM_IP6_MASK		(CSUM_IP6_TCP | CSUM_IP6_UDP)
+#define HN_CSUM_IP_HWASSIST(sc)		\
+	((sc)->hn_tx_ring[0].hn_csum_assist & HN_CSUM_IP_MASK)
+#define HN_CSUM_IP6_HWASSIST(sc)	\
+	((sc)->hn_tx_ring[0].hn_csum_assist & HN_CSUM_IP6_MASK)
+
 /*
  * Globals
  */
@@ -328,12 +327,14 @@ static int hn_tx_stat_ulong_sysctl(SYSCT
 static int hn_tx_conf_int_sysctl(SYSCTL_HANDLER_ARGS);
 static int hn_ndis_version_sysctl(SYSCTL_HANDLER_ARGS);
 static int hn_caps_sysctl(SYSCTL_HANDLER_ARGS);
+static int hn_hwassist_sysctl(SYSCTL_HANDLER_ARGS);
 static int hn_rss_key_sysctl(SYSCTL_HANDLER_ARGS);
 static int hn_rss_ind_sysctl(SYSCTL_HANDLER_ARGS);
 static int hn_check_iplen(const struct mbuf *, int);
 static int hn_create_tx_ring(struct hn_softc *, int);
 static void hn_destroy_tx_ring(struct hn_tx_ring *);
 static int hn_create_tx_data(struct hn_softc *, int);
+static void hn_fixup_tx_data(struct hn_softc *);
 static void hn_destroy_tx_data(struct hn_softc *);
 static void hn_start_taskfunc(void *, int);
 static void hn_start_txeof_taskfunc(void *, int);
@@ -648,10 +649,10 @@ netvsc_attach(device_t dev)
 	}
 #endif
 
-	hn_set_chim_size(sc, sc->hn_chim_szmax);
-	if (hn_tx_chimney_size > 0 &&
-	    hn_tx_chimney_size < sc->hn_chim_szmax)
-		hn_set_chim_size(sc, hn_tx_chimney_size);
+	/*
+	 * Fixup TX stuffs after synthetic parts are attached.
+	 */
+	hn_fixup_tx_data(sc);
 
 	ctx = device_get_sysctl_ctx(dev);
 	child = SYSCTL_CHILDREN(device_get_sysctl_tree(dev));
@@ -663,6 +664,9 @@ netvsc_attach(device_t dev)
 	SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "caps",
 	    CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE, sc, 0,
 	    hn_caps_sysctl, "A", "capabilities");
+	SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "hwassist",
+	    CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE, sc, 0,
+	    hn_hwassist_sysctl, "A", "hwassist");
 	SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "rss_key",
 	    CTLTYPE_OPAQUE | CTLFLAG_RW | CTLFLAG_MPSAFE, sc, 0,
 	    hn_rss_key_sysctl, "IU", "RSS key");
@@ -697,13 +701,32 @@ netvsc_attach(device_t dev)
 		ifp->if_qflush = hn_xmit_qflush;
 	}
 
-	ifp->if_capabilities |=
-	    IFCAP_VLAN_HWTAGGING | IFCAP_VLAN_MTU | IFCAP_HWCSUM | IFCAP_TSO |
-	    IFCAP_LRO;
-	ifp->if_capenable |=
-	    IFCAP_VLAN_HWTAGGING | IFCAP_VLAN_MTU | IFCAP_HWCSUM | IFCAP_TSO |
-	    IFCAP_LRO;
-	ifp->if_hwassist = sc->hn_tx_ring[0].hn_csum_assist | CSUM_TSO;
+	ifp->if_capabilities |= IFCAP_RXCSUM | IFCAP_LRO;
+#ifdef foo
+	/* We can't diff IPv6 packets from IPv4 packets on RX path. */
+	ifp->if_capabilities |= IFCAP_RXCSUM_IPV6;
+#endif
+	if (sc->hn_caps & HN_CAP_VLAN) {
+		/* XXX not sure about VLAN_MTU. */
+		ifp->if_capabilities |= IFCAP_VLAN_HWTAGGING | IFCAP_VLAN_MTU;
+	}
+
+	ifp->if_hwassist = sc->hn_tx_ring[0].hn_csum_assist;
+	if (ifp->if_hwassist & HN_CSUM_IP_MASK)
+		ifp->if_capabilities |= IFCAP_TXCSUM;
+	if (ifp->if_hwassist & HN_CSUM_IP6_MASK)
+		ifp->if_capabilities |= IFCAP_TXCSUM_IPV6;
+	if (sc->hn_caps & HN_CAP_TSO4) {
+		ifp->if_capabilities |= IFCAP_TSO4;
+		ifp->if_hwassist |= CSUM_IP_TSO;
+	}
+	if (sc->hn_caps & HN_CAP_TSO6) {
+		ifp->if_capabilities |= IFCAP_TSO6;
+		ifp->if_hwassist |= CSUM_IP6_TSO;
+	}
+
+	/* 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)
@@ -1063,14 +1086,19 @@ hn_encap(struct hn_tx_ring *txr, struct 
 	} else if (m_head->m_pkthdr.csum_flags & txr->hn_csum_assist) {
 		pi_data = hn_rndis_pktinfo_append(pkt, HN_RNDIS_PKT_LEN,
 		    NDIS_TXCSUM_INFO_SIZE, NDIS_PKTINFO_TYPE_CSUM);
-		*pi_data = NDIS_TXCSUM_INFO_IPV4;
-
-		if (m_head->m_pkthdr.csum_flags & CSUM_IP)
-			*pi_data |= NDIS_TXCSUM_INFO_IPCS;
+		if (m_head->m_pkthdr.csum_flags &
+		    (CSUM_IP6_TCP | CSUM_IP6_UDP)) {
+			*pi_data = NDIS_TXCSUM_INFO_IPV6;
+		} else {
+			*pi_data = NDIS_TXCSUM_INFO_IPV4;
+			if (m_head->m_pkthdr.csum_flags & CSUM_IP)
+				*pi_data |= NDIS_TXCSUM_INFO_IPCS;
+		}
 
-		if (m_head->m_pkthdr.csum_flags & CSUM_TCP)
+		if (m_head->m_pkthdr.csum_flags & (CSUM_IP_TCP | CSUM_IP6_TCP))
 			*pi_data |= NDIS_TXCSUM_INFO_TCPCS;
-		else if (m_head->m_pkthdr.csum_flags & CSUM_UDP)
+		else if (m_head->m_pkthdr.csum_flags &
+		    (CSUM_IP_UDP | CSUM_IP6_UDP))
 			*pi_data |= NDIS_TXCSUM_INFO_UDPCS;
 	}
 
@@ -1685,21 +1713,31 @@ hn_ioctl(struct ifnet *ifp, u_long cmd, 
 
 	case SIOCSIFCAP:
 		HN_LOCK(sc);
-
 		mask = ifr->ifr_reqcap ^ ifp->if_capenable;
+
 		if (mask & IFCAP_TXCSUM) {
 			ifp->if_capenable ^= IFCAP_TXCSUM;
-			if (ifp->if_capenable & IFCAP_TXCSUM) {
-				ifp->if_hwassist |=
-				    sc->hn_tx_ring[0].hn_csum_assist;
-			} else {
-				ifp->if_hwassist &=
-				    ~sc->hn_tx_ring[0].hn_csum_assist;
-			}
+			if (ifp->if_capenable & IFCAP_TXCSUM)
+				ifp->if_hwassist |= HN_CSUM_IP_HWASSIST(sc);
+			else
+				ifp->if_hwassist &= ~HN_CSUM_IP_HWASSIST(sc);
+		}
+		if (mask & IFCAP_TXCSUM_IPV6) {
+			ifp->if_capenable ^= IFCAP_TXCSUM_IPV6;
+			if (ifp->if_capenable & IFCAP_TXCSUM_IPV6)
+				ifp->if_hwassist |= HN_CSUM_IP6_HWASSIST(sc);
+			else
+				ifp->if_hwassist &= ~HN_CSUM_IP6_HWASSIST(sc);
 		}
 
+		/* TODO: flip RNDIS offload parameters for RXCSUM. */
 		if (mask & IFCAP_RXCSUM)
 			ifp->if_capenable ^= IFCAP_RXCSUM;
+#ifdef foo
+		/* We can't diff IPv6 packets from IPv4 packets on RX path. */
+		if (mask & IFCAP_RXCSUM_IPV6)
+			ifp->if_capenable ^= IFCAP_RXCSUM_IPV6;
+#endif
 
 		if (mask & IFCAP_LRO)
 			ifp->if_capenable ^= IFCAP_LRO;
@@ -1711,7 +1749,6 @@ hn_ioctl(struct ifnet *ifp, u_long cmd, 
 			else
 				ifp->if_hwassist &= ~CSUM_IP_TSO;
 		}
-
 		if (mask & IFCAP_TSO6) {
 			ifp->if_capenable ^= IFCAP_TSO6;
 			if (ifp->if_capenable & IFCAP_TSO6)
@@ -2152,6 +2189,20 @@ hn_caps_sysctl(SYSCTL_HANDLER_ARGS)
 }
 
 static int
+hn_hwassist_sysctl(SYSCTL_HANDLER_ARGS)
+{
+	struct hn_softc *sc = arg1;
+	char assist_str[128];
+	uint32_t hwassist;
+
+	HN_LOCK(sc);
+	hwassist = sc->hn_ifp->if_hwassist;
+	HN_UNLOCK(sc);
+	snprintf(assist_str, sizeof(assist_str), "%b", hwassist, CSUM_BITS);
+	return sysctl_handle_string(oidp, assist_str, sizeof(assist_str), req);
+}
+
+static int
 hn_rss_key_sysctl(SYSCTL_HANDLER_ARGS)
 {
 	struct hn_softc *sc = arg1;
@@ -2508,7 +2559,6 @@ hn_create_tx_ring(struct hn_softc *sc, i
 	device_t dev = sc->hn_dev;
 	bus_dma_tag_t parent_dtag;
 	int error, i;
-	uint32_t version;
 
 	txr->hn_sc = sc;
 	txr->hn_tx_idx = id;
@@ -2547,18 +2597,6 @@ hn_create_tx_ring(struct hn_softc *sc, i
 	}
 
 	txr->hn_direct_tx_size = hn_direct_tx_size;
-	version = VMBUS_GET_VERSION(device_get_parent(dev), dev);
-	if (version >= VMBUS_VERSION_WIN8_1) {
-		txr->hn_csum_assist = HN_CSUM_ASSIST;
-	} else {
-		txr->hn_csum_assist = HN_CSUM_ASSIST_WIN8;
-		if (id == 0) {
-			device_printf(dev, "bus version %u.%u, "
-			    "no UDP checksum offloading\n",
-			    VMBUS_VERSION_MAJOR(version),
-			    VMBUS_VERSION_MINOR(version));
-		}
-	}
 
 	/*
 	 * Always schedule transmission instead of trying to do direct
@@ -2854,6 +2892,35 @@ hn_set_chim_size(struct hn_softc *sc, in
 }
 
 static void
+hn_fixup_tx_data(struct hn_softc *sc)
+{
+	uint64_t csum_assist;
+	int i;
+
+	hn_set_chim_size(sc, sc->hn_chim_szmax);
+	if (hn_tx_chimney_size > 0 &&
+	    hn_tx_chimney_size < sc->hn_chim_szmax)
+		hn_set_chim_size(sc, hn_tx_chimney_size);
+
+	csum_assist = 0;
+	if (sc->hn_caps & HN_CAP_IPCS)
+		csum_assist |= CSUM_IP;
+	if (sc->hn_caps & HN_CAP_TCP4CS)
+		csum_assist |= CSUM_IP_TCP;
+	if (sc->hn_caps & HN_CAP_UDP4CS)
+		csum_assist |= CSUM_IP_UDP;
+#ifdef notyet
+	if (sc->hn_caps & HN_CAP_TCP6CS)
+		csum_assist |= CSUM_IP6_TCP;
+	if (sc->hn_caps & HN_CAP_UDP6CS)
+		csum_assist |= CSUM_IP6_UDP;
+#endif
+
+	for (i = 0; i < sc->hn_tx_ring_cnt; ++i)
+		sc->hn_tx_ring[i].hn_csum_assist = csum_assist;
+}
+
+static void
 hn_destroy_tx_data(struct hn_softc *sc)
 {
 	int i;



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201610140227.u9E2RJ10049288>