hyperv: Add support for vNIC hot removal
authorHaiyang Zhang <haiyangz@microsoft.com>
Mon, 1 Dec 2014 21:28:39 +0000 (13:28 -0800)
committerDavid S. Miller <davem@davemloft.net>
Tue, 9 Dec 2014 01:24:11 +0000 (20:24 -0500)
This patch adds proper handling of the vNIC hot removal event, which includes
a rescind-channel-offer message from the host side that triggers vNIC close and
removal. In this case, the notices to the host during close and removal is not
necessary because the channel is rescinded. This patch blocks these unnecessary
messages, and lets vNIC removal process complete normally.

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/hv/channel_mgmt.c
drivers/net/hyperv/netvsc.c
drivers/net/hyperv/rndis_filter.c
include/linux/hyperv.h

index a2d1a9612c86c4730c6aa2f0ce038ca06da4f9c5..191a6a3ae6ca704195a41e8caf62b23b510f5bf4 100644 (file)
@@ -517,6 +517,8 @@ static void vmbus_onoffer_rescind(struct vmbus_channel_message_header *hdr)
                /* Just return here, no channel found */
                return;
 
+       channel->rescind = true;
+
        /* work is initialized for vmbus_process_rescind_offer() from
         * vmbus_process_offer() where the channel got created */
        queue_work(channel->controlwq, &channel->work);
index 6fc834e4306d4b76ff4c42b42337e32008a683f0..dd867e6cabd6167342b7a3875c427b94321650bf 100644 (file)
@@ -764,6 +764,9 @@ int netvsc_send(struct hv_device *device,
                out_channel = device->channel;
        packet->channel = out_channel;
 
+       if (out_channel->rescind)
+               return -ENODEV;
+
        if (packet->page_buf_cnt) {
                ret = vmbus_sendpacket_pagebuffer(out_channel,
                                                  packet->page_buf,
index 7b2c5d1e9bad1b21747d4310324d8d51e7a3000f..ec0c40a8f653cb80e7c8a591db8975b79e4d6066 100644 (file)
@@ -958,6 +958,9 @@ static int rndis_filter_close_device(struct rndis_device *dev)
                return 0;
 
        ret = rndis_filter_set_packet_filter(dev, 0);
+       if (ret == -ENODEV)
+               ret = 0;
+
        if (ret == 0)
                dev->state = RNDIS_DEV_INITIALIZED;
 
index 08cfaff8a072313e5e3ed634162cf67c948c4ad5..476c685ca6f9c5c6447944aee2fa98a85cdd14e4 100644 (file)
@@ -650,6 +650,8 @@ struct vmbus_channel {
        u8 monitor_grp;
        u8 monitor_bit;
 
+       bool rescind; /* got rescind msg */
+
        u32 ringbuffer_gpadlhandle;
 
        /* Allocated memory for ring buffer */