Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 29 Aug 2016 05:35:35 +0000 (UTC)
From:      Sepherosa Ziehau <sephe@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r304979 - head/sys/dev/hyperv/netvsc
Message-ID:  <201608290535.u7T5ZZ6g054159@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: sephe
Date: Mon Aug 29 05:35:35 2016
New Revision: 304979
URL: https://svnweb.freebsd.org/changeset/base/304979

Log:
  hyperv/hn: Switch to new RNDIS set for RSS parameters.
  
  MFC after:	1 week
  Sponsored by:	Microsoft
  Differential Revision:	https://reviews.freebsd.org/D7658

Modified:
  head/sys/dev/hyperv/netvsc/hv_net_vsc.h
  head/sys/dev/hyperv/netvsc/hv_rndis.h
  head/sys/dev/hyperv/netvsc/hv_rndis_filter.c
  head/sys/dev/hyperv/netvsc/ndis.h

Modified: head/sys/dev/hyperv/netvsc/hv_net_vsc.h
==============================================================================
--- head/sys/dev/hyperv/netvsc/hv_net_vsc.h	Mon Aug 29 05:17:44 2016	(r304978)
+++ head/sys/dev/hyperv/netvsc/hv_net_vsc.h	Mon Aug 29 05:35:35 2016	(r304979)
@@ -62,6 +62,8 @@
 #include <dev/hyperv/include/hyperv_busdma.h>
 #include <dev/hyperv/include/vmbus.h>
 
+#include <dev/hyperv/netvsc/ndis.h>
+
 #define HN_USE_TXDESC_BUFRING
 
 MALLOC_DECLARE(M_NETVSC);
@@ -383,6 +385,8 @@ typedef struct hn_softc {
 
 	uint32_t		hn_rndis_rid;
 	uint32_t		hn_ndis_ver;
+
+	struct ndis_rssprm_toeplitz hn_rss;
 } hn_softc_t;
 
 #define HN_FLAG_RXBUF_CONNECTED		0x0001

Modified: head/sys/dev/hyperv/netvsc/hv_rndis.h
==============================================================================
--- head/sys/dev/hyperv/netvsc/hv_rndis.h	Mon Aug 29 05:17:44 2016	(r304978)
+++ head/sys/dev/hyperv/netvsc/hv_rndis.h	Mon Aug 29 05:35:35 2016	(r304979)
@@ -536,20 +536,6 @@ struct rndis_hash_info {
 	uint32_t	hash_info;
 } __packed;
 
-#define NDIS_HASH_FUNCTION_MASK		0x000000FF	/* see hash function */
-#define NDIS_HASH_TYPE_MASK		0x00FFFF00	/* see hash type */
-
-/* hash function */
-#define NDIS_HASH_FUNCTION_TOEPLITZ	0x00000001
-
-/* hash type */
-#define NDIS_HASH_IPV4			0x00000100
-#define NDIS_HASH_TCP_IPV4		0x00000200
-#define NDIS_HASH_IPV6			0x00000400
-#define NDIS_HASH_IPV6_EX		0x00000800
-#define NDIS_HASH_TCP_IPV6		0x00001000
-#define NDIS_HASH_TCP_IPV6_EX		0x00002000
-
 typedef struct rndis_tcp_tso_info_ {
 	union {
 		struct {

Modified: head/sys/dev/hyperv/netvsc/hv_rndis_filter.c
==============================================================================
--- head/sys/dev/hyperv/netvsc/hv_rndis_filter.c	Mon Aug 29 05:17:44 2016	(r304978)
+++ head/sys/dev/hyperv/netvsc/hv_rndis_filter.c	Mon Aug 29 05:35:35 2016	(r304979)
@@ -101,6 +101,7 @@ static int hn_rndis_set(struct hn_softc 
     size_t dlen);
 static int hn_rndis_conf_offload(struct hn_softc *sc);
 static int hn_rndis_get_rsscaps(struct hn_softc *sc, int *rxr_cnt);
+static int hn_rndis_conf_rss(struct hn_softc *sc, int nchan);
 
 static __inline uint32_t
 hn_rndis_rid(struct hn_softc *sc)
@@ -670,7 +671,7 @@ hv_rf_query_device_link_status(rndis_dev
 	return (0);
 }
 
-static uint8_t netvsc_hash_key[HASH_KEYLEN] = {
+static uint8_t netvsc_hash_key[NDIS_HASH_KEYSIZE_TOEPLITZ] = {
 	0x6d, 0x5a, 0x56, 0xda, 0x25, 0x5b, 0x0e, 0xc2,
 	0x41, 0x67, 0x25, 0x3d, 0x43, 0xa3, 0x8f, 0xb0,
 	0xd0, 0xca, 0x2b, 0xcb, 0xae, 0x7b, 0x30, 0xb4,
@@ -679,106 +680,6 @@ static uint8_t netvsc_hash_key[HASH_KEYL
 };
 
 /*
- * RNDIS set vRSS parameters
- */
-static int
-hv_rf_set_rss_param(rndis_device *device, int num_queue)
-{
-	rndis_request *request;
-	rndis_set_request *set;
-	rndis_set_complete *set_complete;
-	rndis_recv_scale_param *rssp;
-	uint32_t extlen = sizeof(rndis_recv_scale_param) +
-	    (4 * ITAB_NUM) + HASH_KEYLEN;
-	uint32_t *itab, status;
-	uint8_t *keyp;
-	int i, ret;
-
-
-	request = hv_rndis_request(device, REMOTE_NDIS_SET_MSG,
-	    RNDIS_MESSAGE_SIZE(rndis_set_request) + extlen);
-	if (request == NULL) {
-		if (bootverbose)
-			printf("Netvsc: No memory to set vRSS parameters.\n");
-		ret = -1;
-		goto cleanup;
-	}
-
-	set = &request->request_msg.msg.set_request;
-	set->oid = RNDIS_OID_GEN_RSS_PARAMETERS;
-	set->info_buffer_length = extlen;
-	set->info_buffer_offset = sizeof(rndis_set_request);
-	set->device_vc_handle = 0;
-
-	/* Fill out the rssp parameter structure */
-	rssp = (rndis_recv_scale_param *)(set + 1);
-	rssp->hdr.type = RNDIS_OBJECT_TYPE_RSS_PARAMETERS;
-	rssp->hdr.rev = RNDIS_RECEIVE_SCALE_PARAMETERS_REVISION_2;
-	rssp->hdr.size = sizeof(rndis_recv_scale_param);
-	rssp->flag = 0;
-	rssp->hashinfo = RNDIS_HASH_FUNC_TOEPLITZ | RNDIS_HASH_IPV4 |
-	    RNDIS_HASH_TCP_IPV4 | RNDIS_HASH_IPV6 | RNDIS_HASH_TCP_IPV6;
-	rssp->indirect_tabsize = 4 * ITAB_NUM;
-	rssp->indirect_taboffset = sizeof(rndis_recv_scale_param);
-	rssp->hashkey_size = HASH_KEYLEN;
-	rssp->hashkey_offset = rssp->indirect_taboffset +
-	    rssp->indirect_tabsize;
-
-	/* Set indirection table entries */
-	itab = (uint32_t *)(rssp + 1);
-	for (i = 0; i < ITAB_NUM; i++)
-		itab[i] = i % num_queue;
-
-	/* Set hash key values */
-	keyp = (uint8_t *)((unsigned long)rssp + rssp->hashkey_offset);
-	for (i = 0; i < HASH_KEYLEN; i++)
-		keyp[i] = netvsc_hash_key[i];
-
-	ret = hv_rf_send_request(device, request, REMOTE_NDIS_SET_MSG);
-	if (ret != 0) {
-		goto cleanup;
-	}
-
-	/*
-	 * Wait for the response from the host.  Another thread will signal
-	 * us when the response has arrived.  In the failure case,
-	 * sema_timedwait() returns a non-zero status after waiting 5 seconds.
-	 */
-	ret = sema_timedwait(&request->wait_sema, 5 * hz);
-	if (ret == 0) {
-		/* Response received, check status */
-		set_complete = &request->response_msg.msg.set_complete;
-		status = set_complete->status;
-		if (status != RNDIS_STATUS_SUCCESS) {
-			/* Bad response status, return error */
-			if (bootverbose)
-				printf("Netvsc: Failed to set vRSS "
-				    "parameters.\n");
-			ret = -2;
-		} else {
-			if (bootverbose)
-				printf("Netvsc: Successfully set vRSS "
-				    "parameters.\n");
-		}
-	} else {
-		/*
-		 * We cannot deallocate the request since we may still
-		 * receive a send completion for it.
-		 */
-		printf("Netvsc: vRSS set timeout, id = %u, ret = %d\n",
-		    request->request_msg.msg.init_request.request_id, ret);
-		goto exit;
-	}
-
-cleanup:
-	if (request != NULL) {
-		hv_put_rndis_request(device, request);
-	}
-exit:
-	return (ret);
-}
-
-/*
  * RNDIS filter set packet filter
  * Sends an rndis request with the new filter, then waits for a response
  * from the host.
@@ -1155,6 +1056,52 @@ hn_rndis_conf_offload(struct hn_softc *s
 	return (error);
 }
 
+static int
+hn_rndis_conf_rss(struct hn_softc *sc, int nchan)
+{
+	struct ndis_rssprm_toeplitz *rss = &sc->hn_rss;
+	struct ndis_rss_params *prm = &rss->rss_params;
+	int i, error;
+
+	/*
+	 * Only NDIS 6.30+ is supported.
+	 */
+	KASSERT(sc->hn_ndis_ver >= NDIS_VERSION_6_30,
+	    ("NDIS 6.30+ is required, NDIS version 0x%08x", sc->hn_ndis_ver));
+
+	memset(rss, 0, sizeof(*rss));
+	prm->ndis_hdr.ndis_type = NDIS_OBJTYPE_RSS_PARAMS;
+	prm->ndis_hdr.ndis_rev = NDIS_RSS_PARAMS_REV_2;
+	prm->ndis_hdr.ndis_size = sizeof(*rss);
+	prm->ndis_hash = NDIS_HASH_FUNCTION_TOEPLITZ |
+	    NDIS_HASH_IPV4 | NDIS_HASH_TCP_IPV4 |
+	    NDIS_HASH_IPV6 | NDIS_HASH_TCP_IPV6;
+	/* TODO: Take ndis_rss_caps.ndis_nind into account */
+	prm->ndis_indsize = sizeof(rss->rss_ind);
+	prm->ndis_indoffset =
+	    __offsetof(struct ndis_rssprm_toeplitz, rss_ind[0]);
+	prm->ndis_keysize = sizeof(rss->rss_key);
+	prm->ndis_keyoffset =
+	    __offsetof(struct ndis_rssprm_toeplitz, rss_key[0]);
+
+	/* Setup RSS key */
+	memcpy(rss->rss_key, netvsc_hash_key, sizeof(rss->rss_key));
+
+	/* Setup RSS indirect table */
+	/* TODO: Take ndis_rss_caps.ndis_nind into account */
+	for (i = 0; i < NDIS_HASH_INDCNT; ++i)
+		rss->rss_ind[i] = i % nchan;
+
+	error = hn_rndis_set(sc, OID_GEN_RSS_PARAMETERS, rss, sizeof(*rss));
+	if (error) {
+		if_printf(sc->hn_ifp, "RSS config failed: %d\n", error);
+	} else {
+		if (bootverbose)
+			if_printf(sc->hn_ifp, "RSS config done\n");
+	}
+	return (error);
+}
+
 /*
  * RNDIS filter init device
  */
@@ -1456,8 +1403,11 @@ hv_rf_on_device_add(struct hn_softc *sc,
 	}
 	nchan = nsubch + 1;
 
-	ret = hv_rf_set_rss_param(rndis_dev, nchan);
-	*nchan0 = nchan;
+	ret = hn_rndis_conf_rss(sc, nchan);
+	if (ret != 0)
+		*nchan0 = 1;
+	else
+		*nchan0 = nchan;
 out:
 	if (xact != NULL)
 		vmbus_xact_put(xact);

Modified: head/sys/dev/hyperv/netvsc/ndis.h
==============================================================================
--- head/sys/dev/hyperv/netvsc/ndis.h	Mon Aug 29 05:17:44 2016	(r304978)
+++ head/sys/dev/hyperv/netvsc/ndis.h	Mon Aug 29 05:35:35 2016	(r304979)
@@ -33,10 +33,12 @@
 #define NDIS_MEDIA_STATE_DISCONNECTED	1
 
 #define OID_GEN_RSS_CAPABILITIES	0x00010203
+#define OID_GEN_RSS_PARAMETERS		0x00010204
 #define OID_TCP_OFFLOAD_PARAMETERS	0xFC01020C
 
 #define NDIS_OBJTYPE_DEFAULT		0x80
 #define NDIS_OBJTYPE_RSS_CAPS		0x88
+#define NDIS_OBJTYPE_RSS_PARAMS		0x89
 
 /* common_set */
 #define NDIS_OFFLOAD_SET_NOCHG		0
@@ -46,6 +48,23 @@
 /* a.k.a GRE MAC */
 #define NDIS_ENCAP_TYPE_NVGRE		0x00000001
 
+#define NDIS_HASH_FUNCTION_MASK		0x000000FF	/* see hash function */
+#define NDIS_HASH_TYPE_MASK		0x00FFFF00	/* see hash type */
+
+/* hash function */
+#define NDIS_HASH_FUNCTION_TOEPLITZ	0x00000001
+
+/* hash type */
+#define NDIS_HASH_IPV4			0x00000100
+#define NDIS_HASH_TCP_IPV4		0x00000200
+#define NDIS_HASH_IPV6			0x00000400
+#define NDIS_HASH_IPV6_EX		0x00000800
+#define NDIS_HASH_TCP_IPV6		0x00001000
+#define NDIS_HASH_TCP_IPV6_EX		0x00002000
+
+#define NDIS_HASH_KEYSIZE_TOEPLITZ	40
+#define NDIS_HASH_INDCNT		128
+
 struct ndis_object_hdr {
 	uint8_t			ndis_type;		/* NDIS_OBJTYPE_ */
 	uint8_t			ndis_rev;		/* type specific */
@@ -154,4 +173,45 @@ struct ndis_rss_caps {
 #define NDIS_RSS_CAP_IPV6_EX		0x00000400
 #define NDIS_RSS_CAP_HASH_TOEPLITZ	0x00000001
 
+/*
+ * OID_GEN_RSS_PARAMETERS
+ * ndis_type: NDIS_OBJTYPE_RSS_PARAMS
+ */
+struct ndis_rss_params {
+	struct ndis_object_hdr		ndis_hdr;
+	uint16_t			ndis_flags;	/* NDIS_RSS_FLAG_ */
+	uint16_t			ndis_bcpu;	/* base cpu 0 */
+	uint32_t			ndis_hash;	/* NDIS_HASH_ */
+	uint16_t			ndis_indsize;	/* indirect table */
+	uint32_t			ndis_indoffset;
+	uint16_t			ndis_keysize;	/* hash key */
+	uint32_t			ndis_keyoffset;
+	/* NDIS >= 6.20 */
+	uint32_t			ndis_cpumaskoffset;
+	uint32_t			ndis_cpumaskcnt;
+	uint32_t			ndis_cpumaskentsz;
+};
+
+#define NDIS_RSS_PARAMS_SIZE		sizeof(struct ndis_rss_params)
+#define NDIS_RSS_PARAMS_SIZE_6_0	\
+	__offsetof(struct ndis_rss_params, ndis_cpumaskoffset)
+
+#define NDIS_RSS_PARAMS_REV_1		1	/* NDIS 6.0 */
+#define NDIS_RSS_PARAMS_REV_2		2	/* NDIS 6.20 */
+
+#define NDIS_RSS_FLAG_BCPU_UNCHG	0x0001
+#define NDIS_RSS_FLAG_HASH_UNCHG	0x0002
+#define NDIS_RSS_FLAG_IND_UNCHG		0x0004
+#define NDIS_RSS_FLAG_KEY_UNCHG		0x0008
+#define NDIS_RSS_FLAG_DISABLE		0x0010
+
+/* non-standard convenient struct */
+struct ndis_rssprm_toeplitz {
+	struct ndis_rss_params		rss_params;
+	/* Toeplitz hash key */
+	uint8_t				rss_key[NDIS_HASH_KEYSIZE_TOEPLITZ];
+	/* Indirect table */
+	uint32_t			rss_ind[NDIS_HASH_INDCNT];
+};
+
 #endif	/* !_NET_NDIS_H_ */



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