Author: sephe
Date: Mon Sep 19 07:17:43 2016
New Revision: 305964
URL: https://svnweb.freebsd.org/changeset/base/305964

Log:
  hyperv/hn: Save capabilities for later use.
  
  And don't allow capability changes during reinitialization, which
  breaks too much static configuration.
  
  MFC after:    1 week
  Sponsored by: Microsoft
  Differential Revision:        https://reviews.freebsd.org/D7922

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

Modified: head/sys/dev/hyperv/netvsc/hv_net_vsc.c
==============================================================================
--- head/sys/dev/hyperv/netvsc/hv_net_vsc.c     Mon Sep 19 07:07:55 2016        
(r305963)
+++ head/sys/dev/hyperv/netvsc/hv_net_vsc.c     Mon Sep 19 07:17:43 2016        
(r305964)
@@ -467,9 +467,15 @@ hn_nvs_conf_ndis(struct hn_softc *sc, in
 
        /* NOTE: No response. */
        error = hn_nvs_req_send(sc, &conf, sizeof(conf));
-       if (error)
+       if (error) {
                if_printf(sc->hn_ifp, "send nvs ndis conf failed: %d\n", error);
-       return (error);
+               return (error);
+       }
+
+       if (bootverbose)
+               if_printf(sc->hn_ifp, "nvs ndis conf done\n");
+       sc->hn_caps |= HN_CAP_MTU | HN_CAP_VLAN;
+       return (0);
 }
 
 static int

Modified: head/sys/dev/hyperv/netvsc/hv_net_vsc.h
==============================================================================
--- head/sys/dev/hyperv/netvsc/hv_net_vsc.h     Mon Sep 19 07:07:55 2016        
(r305963)
+++ head/sys/dev/hyperv/netvsc/hv_net_vsc.h     Mon Sep 19 07:17:43 2016        
(r305964)
@@ -228,7 +228,8 @@ struct hn_softc {
        struct vmbus_xact_ctx *hn_xact;
        uint32_t        hn_nvs_ver;
 
-       uint32_t                hn_flags;
+       uint32_t                hn_caps;        /* HN_CAP_ */
+       uint32_t                hn_flags;       /* HN_FLAG_ */
        void                    *hn_rxbuf;
        uint32_t                hn_rxbuf_gpadl;
        struct hyperv_dma       hn_rxbuf_dma;
@@ -245,6 +246,16 @@ struct hn_softc {
 #define HN_FLAG_RXBUF_CONNECTED                0x0001
 #define HN_FLAG_CHIM_CONNECTED         0x0002
 
+#define HN_CAP_VLAN                    0x0001
+#define HN_CAP_MTU                     0x0002
+#define HN_CAP_IPCS                    0x0004
+#define HN_CAP_TCP4CS                  0x0008
+#define HN_CAP_TCP6CS                  0x0010
+#define HN_CAP_UDP4CS                  0x0020
+#define HN_CAP_UDP6CS                  0x0040
+#define HN_CAP_TSO4                    0x0080
+#define HN_CAP_TSO6                    0x0100
+
 /*
  * Externs
  */

Modified: head/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c
==============================================================================
--- head/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c  Mon Sep 19 07:07:55 
2016        (r305963)
+++ head/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c  Mon Sep 19 07:17:43 
2016        (r305964)
@@ -325,6 +325,7 @@ static int hn_rx_stat_ulong_sysctl(SYSCT
 static int hn_tx_stat_ulong_sysctl(SYSCTL_HANDLER_ARGS);
 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_rss_key_sysctl(SYSCTL_HANDLER_ARGS);
 static int hn_rss_ind_sysctl(SYSCTL_HANDLER_ARGS);
 static int hn_check_iplen(const struct mbuf *, int);
@@ -641,6 +642,9 @@ netvsc_attach(device_t dev)
        SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "ndis_version",
            CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE, sc, 0,
            hn_ndis_version_sysctl, "A", "NDIS version");
+       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, "rss_key",
            CTLTYPE_OPAQUE | CTLFLAG_RW | CTLFLAG_MPSAFE, sc, 0,
            hn_rss_key_sysctl, "IU", "RSS key");
@@ -2095,6 +2099,30 @@ hn_ndis_version_sysctl(SYSCTL_HANDLER_AR
 }
 
 static int
+hn_caps_sysctl(SYSCTL_HANDLER_ARGS)
+{
+       struct hn_softc *sc = arg1;
+       char caps_str[128];
+       uint32_t caps;
+
+       HN_LOCK(sc);
+       caps = sc->hn_caps;
+       HN_UNLOCK(sc);
+       snprintf(caps_str, sizeof(caps_str), "%b", caps,
+           "\020"
+           "\001VLAN"
+           "\002MTU"
+           "\003IPCS"
+           "\004TCP4CS"
+           "\005TCP6CS"
+           "\006UDP4CS"
+           "\007UDP6CS"
+           "\010TSO4"
+           "\011TSO6");
+       return sysctl_handle_string(oidp, caps_str, sizeof(caps_str), req);
+}
+
+static int
 hn_rss_key_sysctl(SYSCTL_HANDLER_ARGS)
 {
        struct hn_softc *sc = arg1;
@@ -3223,6 +3251,11 @@ hn_synth_attach(struct hn_softc *sc, int
 {
        struct ndis_rssprm_toeplitz *rss = &sc->hn_rss;
        int error, nsubch, nchan, i;
+       uint32_t old_caps;
+
+       /* Save capabilities for later verification. */
+       old_caps = sc->hn_caps;
+       sc->hn_caps = 0;
 
        /*
         * Attach the primary channel _before_ attaching NVS and RNDIS.
@@ -3246,6 +3279,17 @@ hn_synth_attach(struct hn_softc *sc, int
                return (error);
 
        /*
+        * Make sure capabilities are not changed.
+        */
+       if (device_is_attached(sc->hn_dev) && old_caps != sc->hn_caps) {
+               if_printf(sc->hn_ifp, "caps mismatch old 0x%08x, new 0x%08x\n",
+                   old_caps, sc->hn_caps);
+               /* Restore old capabilities and abort. */
+               sc->hn_caps = old_caps;
+               return ENXIO;
+       }
+
+       /*
         * Allocate sub-channels for multi-TX/RX rings.
         *
         * NOTE:

Modified: head/sys/dev/hyperv/netvsc/hv_rndis_filter.c
==============================================================================
--- head/sys/dev/hyperv/netvsc/hv_rndis_filter.c        Mon Sep 19 07:07:55 
2016        (r305963)
+++ head/sys/dev/hyperv/netvsc/hv_rndis_filter.c        Mon Sep 19 07:17:43 
2016        (r305964)
@@ -800,6 +800,7 @@ static int
 hn_rndis_conf_offload(struct hn_softc *sc)
 {
        struct ndis_offload_params params;
+       uint32_t caps;
        size_t paramsz;
        int error;
 
@@ -816,24 +817,29 @@ hn_rndis_conf_offload(struct hn_softc *s
        }
        params.ndis_hdr.ndis_size = paramsz;
 
+       caps = HN_CAP_IPCS | HN_CAP_TCP4CS | HN_CAP_TCP6CS;
        params.ndis_ip4csum = NDIS_OFFLOAD_PARAM_TXRX;
        params.ndis_tcp4csum = NDIS_OFFLOAD_PARAM_TXRX;
        params.ndis_tcp6csum = NDIS_OFFLOAD_PARAM_TXRX;
        if (sc->hn_ndis_ver >= HN_NDIS_VERSION_6_30) {
+               caps |= HN_CAP_UDP4CS | HN_CAP_UDP6CS;
                params.ndis_udp4csum = NDIS_OFFLOAD_PARAM_TXRX;
                params.ndis_udp6csum = NDIS_OFFLOAD_PARAM_TXRX;
        }
+       caps |= HN_CAP_TSO4;
        params.ndis_lsov2_ip4 = NDIS_OFFLOAD_LSOV2_ON;
        /* XXX ndis_lsov2_ip6 = NDIS_OFFLOAD_LSOV2_ON */
 
        error = hn_rndis_set(sc, OID_TCP_OFFLOAD_PARAMETERS, &params, paramsz);
        if (error) {
                if_printf(sc->hn_ifp, "offload config failed: %d\n", error);
-       } else {
-               if (bootverbose)
-                       if_printf(sc->hn_ifp, "offload config done\n");
+               return (error);
        }
-       return (error);
+
+       if (bootverbose)
+               if_printf(sc->hn_ifp, "offload config done\n");
+       sc->hn_caps |= caps;
+       return (0);
 }
 
 int
_______________________________________________
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