hv_netvsc: Add handler for physical link speed change
authorHaiyang Zhang <haiyangz@microsoft.com>
Thu, 4 Aug 2016 17:42:15 +0000 (10:42 -0700)
committerDavid S. Miller <davem@davemloft.net>
Mon, 8 Aug 2016 23:14:07 +0000 (16:14 -0700)
On Hyper-V host 2016 and later, VMs gets an event message of the physical
link speed when vSwitch is changed. This patch handles this message, so
the updated link speed can be reported by ethtool.

Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Reviewed-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/hyperv/hyperv_net.h
drivers/net/hyperv/netvsc.c
drivers/net/hyperv/netvsc_drv.c

index 467fb8b4d08389b00fbca446bae9261e2145b909..c1403fda874c87da1f73845bfe143db654c10e54 100644 (file)
@@ -490,6 +490,7 @@ struct nvsp_2_vsc_capability {
                        u64 sriov:1;
                        u64 ieee8021q:1;
                        u64 correlation_id:1;
+                       u64 teaming:1;
                };
        };
 } __packed;
index 20e09174ff6240bb5b1ba2eb4f13f0a4fd0d5bf3..36a7994f2811174b9ec829d250dbab4a57443547 100644 (file)
@@ -472,9 +472,13 @@ static int negotiate_nvsp_ver(struct hv_device *device,
        init_packet->msg.v2_msg.send_ndis_config.mtu = ndev->mtu + ETH_HLEN;
        init_packet->msg.v2_msg.send_ndis_config.capability.ieee8021q = 1;
 
-       if (nvsp_ver >= NVSP_PROTOCOL_VERSION_5)
+       if (nvsp_ver >= NVSP_PROTOCOL_VERSION_5) {
                init_packet->msg.v2_msg.send_ndis_config.capability.sriov = 1;
 
+               /* Teaming bit is needed to receive link speed updates */
+               init_packet->msg.v2_msg.send_ndis_config.capability.teaming = 1;
+       }
+
        ret = vmbus_sendpacket(device->channel, init_packet,
                                sizeof(struct nvsp_message),
                                (unsigned long)init_packet,
index 3e5356b6f825968b50719697b1b3efdecb081c05..82c8f6d47283fe5c56d86e0a2cc6173db670a942 100644 (file)
@@ -579,19 +579,32 @@ void netvsc_linkstatus_callback(struct hv_device *device_obj,
        struct netvsc_reconfig *event;
        unsigned long flags;
 
-       /* Handle link change statuses only */
+       net = hv_get_drvdata(device_obj);
+
+       if (!net)
+               return;
+
+       ndev_ctx = netdev_priv(net);
+
+       /* Update the physical link speed when changing to another vSwitch */
+       if (indicate->status == RNDIS_STATUS_LINK_SPEED_CHANGE) {
+               u32 speed;
+
+               speed = *(u32 *)((void *)indicate + indicate->
+                                status_buf_offset) / 10000;
+               ndev_ctx->speed = speed;
+               return;
+       }
+
+       /* Handle these link change statuses below */
        if (indicate->status != RNDIS_STATUS_NETWORK_CHANGE &&
            indicate->status != RNDIS_STATUS_MEDIA_CONNECT &&
            indicate->status != RNDIS_STATUS_MEDIA_DISCONNECT)
                return;
 
-       net = hv_get_drvdata(device_obj);
-
-       if (!net || net->reg_state != NETREG_REGISTERED)
+       if (net->reg_state != NETREG_REGISTERED)
                return;
 
-       ndev_ctx = netdev_priv(net);
-
        event = kzalloc(sizeof(*event), GFP_ATOMIC);
        if (!event)
                return;