Author: sephe
Date: Mon Aug 29 04:54:13 2016
New Revision: 304975
URL: https://svnweb.freebsd.org/changeset/base/304975

Log:
  hyperv/hn: Switch to new RNDIS query for RSS capabilities extraction.
  
  MFC after:    1 week
  Sponsored by: Microsoft
  Differential Revision:        https://reviews.freebsd.org/D7656

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

Modified: head/sys/dev/hyperv/netvsc/hv_rndis_filter.c
==============================================================================
--- head/sys/dev/hyperv/netvsc/hv_rndis_filter.c        Mon Aug 29 04:45:58 
2016        (r304974)
+++ head/sys/dev/hyperv/netvsc/hv_rndis_filter.c        Mon Aug 29 04:54:13 
2016        (r304975)
@@ -79,8 +79,6 @@ static void hv_rf_receive_indicate_statu
     const rndis_msg *response);
 static void hv_rf_receive_data(struct hn_rx_ring *rxr,
     const void *data, int dlen);
-static int  hv_rf_query_device(rndis_device *device, uint32_t oid,
-                              void *result, uint32_t *result_size);
 static inline int hv_rf_query_device_mac(rndis_device *device);
 static inline int hv_rf_query_device_link_status(rndis_device *device);
 static int  hv_rf_set_packet_filter(rndis_device *device, uint32_t new_filter);
@@ -102,6 +100,7 @@ static int hn_rndis_query(struct hn_soft
 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_get_rsscaps(struct hn_softc *sc, int *rxr_cnt);
 
 static __inline uint32_t
 hn_rndis_rid(struct hn_softc *sc)
@@ -628,77 +627,6 @@ hv_rf_on_receive(struct hn_softc *sc, st
 }
 
 /*
- * RNDIS filter query device
- */
-static int
-hv_rf_query_device(rndis_device *device, uint32_t oid, void *result,
-                  uint32_t *result_size)
-{
-       rndis_request *request;
-       uint32_t in_result_size = *result_size;
-       rndis_query_request *query;
-       rndis_query_complete *query_complete;
-       int ret = 0;
-
-       *result_size = 0;
-       request = hv_rndis_request(device, REMOTE_NDIS_QUERY_MSG,
-           RNDIS_MESSAGE_SIZE(rndis_query_request));
-       if (request == NULL) {
-               ret = -1;
-               goto cleanup;
-       }
-
-       /* Set up the rndis query */
-       query = &request->request_msg.msg.query_request;
-       query->oid = oid;
-       query->info_buffer_offset = sizeof(rndis_query_request); 
-       query->info_buffer_length = 0;
-       query->device_vc_handle = 0;
-
-       if (oid == RNDIS_OID_GEN_RSS_CAPABILITIES) {
-               struct rndis_recv_scale_cap *cap;
-
-               request->request_msg.msg_len += 
-                       sizeof(struct rndis_recv_scale_cap);
-               query->info_buffer_length = sizeof(struct rndis_recv_scale_cap);
-               cap = (struct rndis_recv_scale_cap *)((unsigned long)query + 
-                                               query->info_buffer_offset);
-               cap->hdr.type = RNDIS_OBJECT_TYPE_RSS_CAPABILITIES;
-               cap->hdr.rev = RNDIS_RECEIVE_SCALE_CAPABILITIES_REVISION_2;
-               cap->hdr.size = sizeof(struct rndis_recv_scale_cap);
-       }
-
-       ret = hv_rf_send_request(device, request, REMOTE_NDIS_QUERY_MSG);
-       if (ret != 0) {
-               /* Fixme:  printf added */
-               printf("RNDISFILTER request failed to Send!\n");
-               goto cleanup;
-       }
-
-       sema_wait(&request->wait_sema);
-
-       /* Copy the response back */
-       query_complete = &request->response_msg.msg.query_complete;
-       
-       if (query_complete->info_buffer_length > in_result_size) {
-               ret = EINVAL;
-               goto cleanup;
-       }
-
-       memcpy(result, (void *)((unsigned long)query_complete +
-           query_complete->info_buffer_offset),
-           query_complete->info_buffer_length);
-
-       *result_size = query_complete->info_buffer_length;
-
-cleanup:
-       if (request != NULL)
-               hv_put_rndis_request(device, request);
-
-       return (ret);
-}
-
-/*
  * RNDIS filter query device MAC address
  */
 static int
@@ -1093,6 +1021,51 @@ done:
 }
 
 static int
+hn_rndis_get_rsscaps(struct hn_softc *sc, int *rxr_cnt)
+{
+       struct ndis_rss_caps in, caps;
+       size_t caps_len;
+       int 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));
+       *rxr_cnt = 0;
+
+       memset(&in, 0, sizeof(in));
+       in.ndis_hdr.ndis_type = NDIS_OBJTYPE_RSS_CAPS;
+       in.ndis_hdr.ndis_rev = NDIS_RSS_CAPS_REV_2;
+       in.ndis_hdr.ndis_size = NDIS_RSS_CAPS_SIZE;
+
+       caps_len = NDIS_RSS_CAPS_SIZE;
+       error = hn_rndis_query(sc, OID_GEN_RSS_CAPABILITIES,
+           &in, NDIS_RSS_CAPS_SIZE, &caps, &caps_len);
+       if (error)
+               return (error);
+       if (caps_len < NDIS_RSS_CAPS_SIZE_6_0) {
+               if_printf(sc->hn_ifp, "invalid NDIS RSS caps len %zu",
+                   caps_len);
+               return (EINVAL);
+       }
+
+       if (caps.ndis_nrxr == 0) {
+               if_printf(sc->hn_ifp, "0 RX rings!?\n");
+               return (EINVAL);
+       }
+       *rxr_cnt = caps.ndis_nrxr;
+
+       if (caps_len == NDIS_RSS_CAPS_SIZE) {
+               if (bootverbose) {
+                       if_printf(sc->hn_ifp, "RSS indirect table size %u\n",
+                           caps.ndis_nind);
+               }
+       }
+       return (0);
+}
+
+static int
 hn_rndis_set(struct hn_softc *sc, uint32_t oid, const void *data, size_t dlen)
 {
        struct rndis_set_req *req;
@@ -1347,8 +1320,6 @@ hv_rf_on_device_add(struct hn_softc *sc,
 {
        int ret;
        rndis_device *rndis_dev;
-       struct rndis_recv_scale_cap rsscaps;
-       uint32_t rsscaps_size = sizeof(struct rndis_recv_scale_cap);
        netvsc_device_info *dev_info = (netvsc_device_info *)additl_info;
        device_t dev = sc->hn_dev;
        struct hn_nvs_subch_req *req;
@@ -1357,6 +1328,7 @@ hv_rf_on_device_add(struct hn_softc *sc,
        struct vmbus_xact *xact = NULL;
        uint32_t status, nsubch;
        int nchan = *nchan0;
+       int rxr_cnt;
 
        rndis_dev = hv_get_rndis_device();
        if (rndis_dev == NULL) {
@@ -1405,22 +1377,23 @@ hv_rf_on_device_add(struct hn_softc *sc,
        
        dev_info->link_state = rndis_dev->link_status;
 
-       if (sc->hn_nvs_ver < NVSP_PROTOCOL_VERSION_5 || nchan == 1)
+       if (sc->hn_ndis_ver < NDIS_VERSION_6_30 || nchan == 1)
                return (0);
 
-       memset(&rsscaps, 0, rsscaps_size);
-       ret = hv_rf_query_device(rndis_dev,
-                       RNDIS_OID_GEN_RSS_CAPABILITIES,
-                       &rsscaps, &rsscaps_size);
-       if ((ret != 0) || (rsscaps.num_recv_que < 2)) {
-               device_printf(dev, "hv_rf_query_device failed or "
-                       "rsscaps.num_recv_que < 2 \n");
+       /*
+        * Get RSS capabilities, e.g. # of RX rings, and # of indirect
+        * table entries.
+        */
+       ret = hn_rndis_get_rsscaps(sc, &rxr_cnt);
+       if (ret) {
+               /* This is benign. */
+               ret = 0;
                goto out;
        }
-       device_printf(dev, "channel, offered %u, requested %d\n",
-           rsscaps.num_recv_que, nchan);
-       if (nchan > rsscaps.num_recv_que)
-               nchan = rsscaps.num_recv_que;
+       if (nchan > rxr_cnt)
+               nchan = rxr_cnt;
+       if_printf(sc->hn_ifp, "RX rings offered %u, requested %d\n",
+           rxr_cnt, nchan);
 
        if (nchan == 1) {
                device_printf(dev, "only 1 channel is supported, no vRSS\n");

Modified: head/sys/dev/hyperv/netvsc/ndis.h
==============================================================================
--- head/sys/dev/hyperv/netvsc/ndis.h   Mon Aug 29 04:45:58 2016        
(r304974)
+++ head/sys/dev/hyperv/netvsc/ndis.h   Mon Aug 29 04:54:13 2016        
(r304975)
@@ -32,9 +32,11 @@
 #define NDIS_MEDIA_STATE_CONNECTED     0
 #define NDIS_MEDIA_STATE_DISCONNECTED  1
 
+#define OID_GEN_RSS_CAPABILITIES       0x00010203
 #define OID_TCP_OFFLOAD_PARAMETERS     0xFC01020C
 
 #define NDIS_OBJTYPE_DEFAULT           0x80
+#define NDIS_OBJTYPE_RSS_CAPS          0x88
 
 /* common_set */
 #define NDIS_OFFLOAD_SET_NOCHG         0
@@ -50,7 +52,10 @@ struct ndis_object_hdr {
        uint16_t                ndis_size;              /* incl. this hdr */
 };
 
-/* OID_TCP_OFFLOAD_PARAMETERS */
+/*
+ * OID_TCP_OFFLOAD_PARAMETERS
+ * ndis_type: NDIS_OBJTYPE_DEFAULT
+ */
 struct ndis_offload_params {
        struct ndis_object_hdr  ndis_hdr;
        uint8_t                 ndis_ip4csum;           /* param_set */
@@ -118,4 +123,35 @@ struct ndis_offload_params {
 #define NDIS_OFFLOAD_RSC_OFF           1
 #define NDIS_OFFLOAD_RSC_ON            2
 
+/*
+ * OID_GEN_RSS_CAPABILITIES
+ * ndis_type: NDIS_OBJTYPE_RSS_CAPS
+ */
+struct ndis_rss_caps {
+       struct ndis_object_hdr          ndis_hdr;
+       uint32_t                        ndis_flags;     /* NDIS_RSS_CAP_ */
+       uint32_t                        ndis_nmsi;      /* # of MSIs */
+       uint32_t                        ndis_nrxr;      /* # of RX rings */
+       /* NDIS >= 6.30 */
+       uint16_t                        ndis_nind;      /* # of indtbl ent. */
+       uint16_t                        ndis_pad;
+};
+
+#define NDIS_RSS_CAPS_SIZE             \
+       __offsetof(struct ndis_rss_caps, ndis_pad)
+#define NDIS_RSS_CAPS_SIZE_6_0         \
+       __offsetof(struct ndis_rss_caps, ndis_nind)
+
+#define NDIS_RSS_CAPS_REV_1            1       /* NDIS 6.{0,1,20} */
+#define NDIS_RSS_CAPS_REV_2            2       /* NDIS 6.30 */
+
+#define NDIS_RSS_CAP_MSI               0x01000000
+#define NDIS_RSS_CAP_CLASSIFY_ISR      0x02000000
+#define NDIS_RSS_CAP_CLASSIFY_DPC      0x04000000
+#define NDIS_RSS_CAP_MSIX              0x08000000
+#define NDIS_RSS_CAP_IPV4              0x00000100
+#define NDIS_RSS_CAP_IPV6              0x00000200
+#define NDIS_RSS_CAP_IPV6_EX           0x00000400
+#define NDIS_RSS_CAP_HASH_TOEPLITZ     0x00000001
+
 #endif /* !_NET_NDIS_H_ */
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to