Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 860d7ef6 authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'hv_netvsc-races'



Vitaly Kuznetsov says:

====================
hv_netvsc: avoid races on mtu change/set channels

Changes since v1:
- Rebased to net-next [Haiyang Zhang]

Original description:

MTU change and set channels operations are implemented as netvsc device
re-creation destroying internal structures (struct net_device stays). This
is really unfortunate but there is no support from Hyper-V host to do it
in a different way. Such re-creation is unsurprisingly racy, Haiyang
reported a crash when netvsc_change_mtu() is racing with
netvsc_link_change() but I was able to identify additional races upon
investigation. Both netvsc_set_channels() and netvsc_change_mtu() race
against:
1) netvsc_link_change()
2) netvsc_remove()
3) netvsc_send()

To solve these issues without introducing new locks some refactoring is
required. We need to get rid of very complex link graph in all the
internal structures and avoid traveling through structures which are being
removed.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents da47b457 88098834
Loading
Loading
Loading
Loading
+7 −10
Original line number Diff line number Diff line
@@ -158,7 +158,7 @@ enum rndis_device_state {
};

struct rndis_device {
	struct netvsc_device *net_dev;
	struct net_device *ndev;

	enum rndis_device_state state;
	bool link_state;
@@ -202,7 +202,7 @@ int rndis_filter_receive(struct hv_device *dev,
int rndis_filter_set_packet_filter(struct rndis_device *dev, u32 new_filter);
int rndis_filter_set_device_mac(struct hv_device *hdev, char *mac);

void netvsc_switch_datapath(struct netvsc_device *nv_dev, bool vf);
void netvsc_switch_datapath(struct net_device *nv_dev, bool vf);

#define NVSP_INVALID_PROTOCOL_VERSION	((u32)0xFFFFFFFF)

@@ -653,6 +653,8 @@ struct garp_wrk {
struct net_device_context {
	/* point back to our device context */
	struct hv_device *device_ctx;
	/* netvsc_device */
	struct netvsc_device *nvdev;
	/* reconfigure work */
	struct delayed_work dwork;
	/* last reconfig time */
@@ -672,17 +674,17 @@ struct net_device_context {
	/* Ethtool settings */
	u8 duplex;
	u32 speed;

	/* the device is going away */
	bool start_remove;
};

/* Per netvsc device */
struct netvsc_device {
	struct hv_device *dev;

	u32 nvsp_version;

	atomic_t num_outstanding_sends;
	wait_queue_head_t wait_drain;
	bool start_remove;
	bool destroy;

	/* Receive buffer allocated by us but manages by NetVSP */
@@ -708,8 +710,6 @@ struct netvsc_device {
	struct nvsp_message revoke_packet;
	/* unsigned char HwMacAddr[HW_MACADDR_LEN]; */

	struct net_device *ndev;

	struct vmbus_channel *chn_table[VRSS_CHANNEL_MAX];
	u32 send_table[VRSS_SEND_TAB_SIZE];
	u32 max_chn;
@@ -732,9 +732,6 @@ struct netvsc_device {
	u32 max_pkt; /* max number of pkt in one send, e.g. 8 */
	u32 pkt_align; /* alignment bytes, e.g. 8 */

	/* The net device context */
	struct net_device_context *nd_ctx;

	/* 1: allocated, serial number is valid. 0: not allocated */
	u32 vf_alloc;
	/* Serial number of the VF to team with */
+60 −76
Original line number Diff line number Diff line
@@ -37,10 +37,12 @@
 * Switch the data path from the synthetic interface to the VF
 * interface.
 */
void netvsc_switch_datapath(struct netvsc_device *nv_dev, bool vf)
void netvsc_switch_datapath(struct net_device *ndev, bool vf)
{
	struct net_device_context *net_device_ctx = netdev_priv(ndev);
	struct hv_device *dev = net_device_ctx->device_ctx;
	struct netvsc_device *nv_dev = net_device_ctx->nvdev;
	struct nvsp_message *init_pkt = &nv_dev->channel_init_pkt;
	struct hv_device *dev = nv_dev->dev;

	memset(init_pkt, 0, sizeof(struct nvsp_message));
	init_pkt->hdr.msg_type = NVSP_MSG4_TYPE_SWITCH_DATA_PATH;
@@ -58,10 +60,9 @@ void netvsc_switch_datapath(struct netvsc_device *nv_dev, bool vf)
}


static struct netvsc_device *alloc_net_device(struct hv_device *device)
static struct netvsc_device *alloc_net_device(void)
{
	struct netvsc_device *net_device;
	struct net_device *ndev = hv_get_drvdata(device);

	net_device = kzalloc(sizeof(struct netvsc_device), GFP_KERNEL);
	if (!net_device)
@@ -74,19 +75,15 @@ static struct netvsc_device *alloc_net_device(struct hv_device *device)
	}

	init_waitqueue_head(&net_device->wait_drain);
	net_device->start_remove = false;
	net_device->destroy = false;
	atomic_set(&net_device->open_cnt, 0);
	atomic_set(&net_device->vf_use_cnt, 0);
	net_device->dev = device;
	net_device->ndev = ndev;
	net_device->max_pkt = RNDIS_MAX_PKT_DEFAULT;
	net_device->pkt_align = RNDIS_PKT_ALIGN_DEFAULT;

	net_device->vf_netdev = NULL;
	net_device->vf_inject = false;

	hv_set_drvdata(device, net_device);
	return net_device;
}

@@ -98,9 +95,10 @@ static void free_netvsc_device(struct netvsc_device *nvdev)

static struct netvsc_device *get_outbound_net_device(struct hv_device *device)
{
	struct netvsc_device *net_device;
	struct net_device *ndev = hv_get_drvdata(device);
	struct net_device_context *net_device_ctx = netdev_priv(ndev);
	struct netvsc_device *net_device = net_device_ctx->nvdev;

	net_device = hv_get_drvdata(device);
	if (net_device && net_device->destroy)
		net_device = NULL;

@@ -109,9 +107,9 @@ static struct netvsc_device *get_outbound_net_device(struct hv_device *device)

static struct netvsc_device *get_inbound_net_device(struct hv_device *device)
{
	struct netvsc_device *net_device;

	net_device = hv_get_drvdata(device);
	struct net_device *ndev = hv_get_drvdata(device);
	struct net_device_context *net_device_ctx = netdev_priv(ndev);
	struct netvsc_device *net_device = net_device_ctx->nvdev;

	if (!net_device)
		goto get_in_err;
@@ -125,11 +123,13 @@ static struct netvsc_device *get_inbound_net_device(struct hv_device *device)
}


static int netvsc_destroy_buf(struct netvsc_device *net_device)
static int netvsc_destroy_buf(struct hv_device *device)
{
	struct nvsp_message *revoke_packet;
	int ret = 0;
	struct net_device *ndev = net_device->ndev;
	struct net_device *ndev = hv_get_drvdata(device);
	struct net_device_context *net_device_ctx = netdev_priv(ndev);
	struct netvsc_device *net_device = net_device_ctx->nvdev;

	/*
	 * If we got a section count, it means we received a
@@ -147,7 +147,7 @@ static int netvsc_destroy_buf(struct netvsc_device *net_device)
		revoke_packet->msg.v1_msg.
		revoke_recv_buf.id = NETVSC_RECEIVE_BUFFER_ID;

		ret = vmbus_sendpacket(net_device->dev->channel,
		ret = vmbus_sendpacket(device->channel,
				       revoke_packet,
				       sizeof(struct nvsp_message),
				       (unsigned long)revoke_packet,
@@ -165,7 +165,7 @@ static int netvsc_destroy_buf(struct netvsc_device *net_device)

	/* Teardown the gpadl on the vsp end */
	if (net_device->recv_buf_gpadl_handle) {
		ret = vmbus_teardown_gpadl(net_device->dev->channel,
		ret = vmbus_teardown_gpadl(device->channel,
					   net_device->recv_buf_gpadl_handle);

		/* If we failed here, we might as well return and have a leak
@@ -207,7 +207,7 @@ static int netvsc_destroy_buf(struct netvsc_device *net_device)
		revoke_packet->msg.v1_msg.revoke_send_buf.id =
			NETVSC_SEND_BUFFER_ID;

		ret = vmbus_sendpacket(net_device->dev->channel,
		ret = vmbus_sendpacket(device->channel,
				       revoke_packet,
				       sizeof(struct nvsp_message),
				       (unsigned long)revoke_packet,
@@ -223,7 +223,7 @@ static int netvsc_destroy_buf(struct netvsc_device *net_device)
	}
	/* Teardown the gpadl on the vsp end */
	if (net_device->send_buf_gpadl_handle) {
		ret = vmbus_teardown_gpadl(net_device->dev->channel,
		ret = vmbus_teardown_gpadl(device->channel,
					   net_device->send_buf_gpadl_handle);

		/* If we failed here, we might as well return and have a leak
@@ -258,7 +258,7 @@ static int netvsc_init_buf(struct hv_device *device)
	net_device = get_outbound_net_device(device);
	if (!net_device)
		return -ENODEV;
	ndev = net_device->ndev;
	ndev = hv_get_drvdata(device);

	node = cpu_to_node(device->channel->target_cpu);
	net_device->recv_buf = vzalloc_node(net_device->recv_buf_size, node);
@@ -435,7 +435,7 @@ static int netvsc_init_buf(struct hv_device *device)
	goto exit;

cleanup:
	netvsc_destroy_buf(net_device);
	netvsc_destroy_buf(device);

exit:
	return ret;
@@ -448,6 +448,7 @@ static int negotiate_nvsp_ver(struct hv_device *device,
			      struct nvsp_message *init_packet,
			      u32 nvsp_ver)
{
	struct net_device *ndev = hv_get_drvdata(device);
	int ret;
	unsigned long t;

@@ -481,8 +482,7 @@ static int negotiate_nvsp_ver(struct hv_device *device,
	/* NVSPv2 or later: Send NDIS config */
	memset(init_packet, 0, sizeof(struct nvsp_message));
	init_packet->hdr.msg_type = NVSP_MSG2_TYPE_SEND_NDIS_CONFIG;
	init_packet->msg.v2_msg.send_ndis_config.mtu = net_device->ndev->mtu +
						       ETH_HLEN;
	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)
@@ -502,7 +502,6 @@ static int netvsc_connect_vsp(struct hv_device *device)
	struct netvsc_device *net_device;
	struct nvsp_message *init_packet;
	int ndis_version;
	struct net_device *ndev;
	u32 ver_list[] = { NVSP_PROTOCOL_VERSION_1, NVSP_PROTOCOL_VERSION_2,
		NVSP_PROTOCOL_VERSION_4, NVSP_PROTOCOL_VERSION_5 };
	int i, num_ver = 4; /* number of different NVSP versions */
@@ -510,7 +509,6 @@ static int netvsc_connect_vsp(struct hv_device *device)
	net_device = get_outbound_net_device(device);
	if (!net_device)
		return -ENODEV;
	ndev = net_device->ndev;

	init_packet = &net_device->channel_init_pkt;

@@ -566,9 +564,9 @@ static int netvsc_connect_vsp(struct hv_device *device)
	return ret;
}

static void netvsc_disconnect_vsp(struct netvsc_device *net_device)
static void netvsc_disconnect_vsp(struct hv_device *device)
{
	netvsc_destroy_buf(net_device);
	netvsc_destroy_buf(device);
}

/*
@@ -576,24 +574,13 @@ static void netvsc_disconnect_vsp(struct netvsc_device *net_device)
 */
int netvsc_device_remove(struct hv_device *device)
{
	struct netvsc_device *net_device;
	unsigned long flags;

	net_device = hv_get_drvdata(device);

	netvsc_disconnect_vsp(net_device);
	struct net_device *ndev = hv_get_drvdata(device);
	struct net_device_context *net_device_ctx = netdev_priv(ndev);
	struct netvsc_device *net_device = net_device_ctx->nvdev;

	/*
	 * Since we have already drained, we don't need to busy wait
	 * as was done in final_release_stor_device()
	 * Note that we cannot set the ext pointer to NULL until
	 * we have drained - to drain the outgoing packets, we need to
	 * allow incoming packets.
	 */
	netvsc_disconnect_vsp(device);

	spin_lock_irqsave(&device->channel->inbound_lock, flags);
	hv_set_drvdata(device, NULL);
	spin_unlock_irqrestore(&device->channel->inbound_lock, flags);
	net_device_ctx->nvdev = NULL;

	/*
	 * At this point, no one should be accessing net_device
@@ -641,12 +628,11 @@ static void netvsc_send_completion(struct netvsc_device *net_device,
{
	struct nvsp_message *nvsp_packet;
	struct hv_netvsc_packet *nvsc_packet;
	struct net_device *ndev;
	struct net_device *ndev = hv_get_drvdata(device);
	struct net_device_context *net_device_ctx = netdev_priv(ndev);
	u32 send_index;
	struct sk_buff *skb;

	ndev = net_device->ndev;

	nvsp_packet = (struct nvsp_message *)((unsigned long)packet +
			(packet->offset8 << 3));

@@ -691,7 +677,7 @@ static void netvsc_send_completion(struct netvsc_device *net_device,
			wake_up(&net_device->wait_drain);

		if (netif_tx_queue_stopped(netdev_get_tx_queue(ndev, q_idx)) &&
		    !net_device->start_remove &&
		    !net_device_ctx->start_remove &&
		    (hv_ringbuf_avail_percent(&channel->outbound) >
		     RING_AVAIL_PERCENT_HIWATER || queue_sends < 1))
				netif_tx_wake_queue(netdev_get_tx_queue(
@@ -775,6 +761,7 @@ static u32 netvsc_copy_to_send_buf(struct netvsc_device *net_device,
}

static inline int netvsc_send_pkt(
	struct hv_device *device,
	struct hv_netvsc_packet *packet,
	struct netvsc_device *net_device,
	struct hv_page_buffer **pb,
@@ -783,7 +770,7 @@ static inline int netvsc_send_pkt(
	struct nvsp_message nvmsg;
	u16 q_idx = packet->q_idx;
	struct vmbus_channel *out_channel = net_device->chn_table[q_idx];
	struct net_device *ndev = net_device->ndev;
	struct net_device *ndev = hv_get_drvdata(device);
	u64 req_id;
	int ret;
	struct hv_page_buffer *pgbuf;
@@ -978,7 +965,8 @@ int netvsc_send(struct hv_device *device,
	}

	if (msd_send) {
		m_ret = netvsc_send_pkt(msd_send, net_device, NULL, msd_skb);
		m_ret = netvsc_send_pkt(device, msd_send, net_device,
					NULL, msd_skb);

		if (m_ret != 0) {
			netvsc_free_send_slot(net_device,
@@ -989,7 +977,7 @@ int netvsc_send(struct hv_device *device,

send_now:
	if (cur_send)
		ret = netvsc_send_pkt(cur_send, net_device, pb, skb);
		ret = netvsc_send_pkt(device, cur_send, net_device, pb, skb);

	if (ret != 0 && section_index != NETVSC_INVALID_INDEX)
		netvsc_free_send_slot(net_device, section_index);
@@ -1005,9 +993,7 @@ static void netvsc_send_recv_completion(struct hv_device *device,
	struct nvsp_message recvcompMessage;
	int retries = 0;
	int ret;
	struct net_device *ndev;

	ndev = net_device->ndev;
	struct net_device *ndev = hv_get_drvdata(device);

	recvcompMessage.hdr.msg_type =
				NVSP_MSG1_TYPE_SEND_RNDIS_PKT_COMPLETE;
@@ -1054,11 +1040,9 @@ static void netvsc_receive(struct netvsc_device *net_device,
	u32 status = NVSP_STAT_SUCCESS;
	int i;
	int count = 0;
	struct net_device *ndev;
	struct net_device *ndev = hv_get_drvdata(device);
	void *data;

	ndev = net_device->ndev;

	/*
	 * All inbound packets other than send completion should be xfer page
	 * packet
@@ -1114,14 +1098,13 @@ static void netvsc_send_table(struct hv_device *hdev,
			      struct nvsp_message *nvmsg)
{
	struct netvsc_device *nvscdev;
	struct net_device *ndev;
	struct net_device *ndev = hv_get_drvdata(hdev);
	int i;
	u32 count, *tab;

	nvscdev = get_outbound_net_device(hdev);
	if (!nvscdev)
		return;
	ndev = nvscdev->ndev;

	count = nvmsg->msg.v5_msg.send_table.count;
	if (count != VRSS_SEND_TAB_SIZE) {
@@ -1180,7 +1163,7 @@ void netvsc_channel_cb(void *context)
	net_device = get_inbound_net_device(device);
	if (!net_device)
		return;
	ndev = net_device->ndev;
	ndev = hv_get_drvdata(device);
	buffer = get_per_channel_state(channel);

	do {
@@ -1253,30 +1236,19 @@ void netvsc_channel_cb(void *context)
 */
int netvsc_device_add(struct hv_device *device, void *additional_info)
{
	int ret = 0;
	int i, ret = 0;
	int ring_size =
	((struct netvsc_device_info *)additional_info)->ring_size;
	struct netvsc_device *net_device;
	struct net_device *ndev;
	struct net_device *ndev = hv_get_drvdata(device);
	struct net_device_context *net_device_ctx = netdev_priv(ndev);

	net_device = alloc_net_device(device);
	net_device = alloc_net_device();
	if (!net_device)
		return -ENOMEM;

	net_device->ring_size = ring_size;

	/*
	 * Coming into this function, struct net_device * is
	 * registered as the driver private data.
	 * In alloc_net_device(), we register struct netvsc_device *
	 * as the driver private data and stash away struct net_device *
	 * in struct netvsc_device *.
	 */
	ndev = net_device->ndev;

	/* Add netvsc_device context to netvsc_device */
	net_device->nd_ctx = netdev_priv(ndev);

	/* Initialize the NetVSC channel extension */
	init_completion(&net_device->channel_init_wait);

@@ -1295,7 +1267,19 @@ int netvsc_device_add(struct hv_device *device, void *additional_info)
	/* Channel is opened */
	pr_info("hv_netvsc channel opened successfully\n");

	net_device->chn_table[0] = device->channel;
	/* If we're reopening the device we may have multiple queues, fill the
	 * chn_table with the default channel to use it before subchannels are
	 * opened.
	 */
	for (i = 0; i < VRSS_CHANNEL_MAX; i++)
		net_device->chn_table[i] = device->channel;

	/* Writing nvdev pointer unlocks netvsc_send(), make sure chn_table is
	 * populated.
	 */
	wmb();

	net_device_ctx->nvdev = net_device;

	/* Connect with the NetVsp */
	ret = netvsc_connect_vsp(device);
+105 −73

File changed.

Preview size limit exceeded, changes collapsed.

+43 −39
Original line number Diff line number Diff line
@@ -126,11 +126,7 @@ static void put_rndis_request(struct rndis_device *dev,
static void dump_rndis_message(struct hv_device *hv_dev,
			struct rndis_message *rndis_msg)
{
	struct net_device *netdev;
	struct netvsc_device *net_device;

	net_device = hv_get_drvdata(hv_dev);
	netdev = net_device->ndev;
	struct net_device *netdev = hv_get_drvdata(hv_dev);

	switch (rndis_msg->ndis_msg_type) {
	case RNDIS_MSG_PACKET:
@@ -211,6 +207,7 @@ static int rndis_filter_send_request(struct rndis_device *dev,
	struct hv_netvsc_packet *packet;
	struct hv_page_buffer page_buf[2];
	struct hv_page_buffer *pb = page_buf;
	struct net_device_context *net_device_ctx = netdev_priv(dev->ndev);

	/* Setup the packet to send it */
	packet = &req->pkt;
@@ -236,7 +233,7 @@ static int rndis_filter_send_request(struct rndis_device *dev,
			pb[0].len;
	}

	ret = netvsc_send(dev->net_dev->dev, packet, NULL, &pb, NULL);
	ret = netvsc_send(net_device_ctx->device_ctx, packet, NULL, &pb, NULL);
	return ret;
}

@@ -262,9 +259,7 @@ static void rndis_filter_receive_response(struct rndis_device *dev,
	struct rndis_request *request = NULL;
	bool found = false;
	unsigned long flags;
	struct net_device *ndev;

	ndev = dev->net_dev->ndev;
	struct net_device *ndev = dev->ndev;

	spin_lock_irqsave(&dev->request_lock, flags);
	list_for_each_entry(request, &dev->req_list, list_ent) {
@@ -355,6 +350,7 @@ static int rndis_filter_receive_data(struct rndis_device *dev,
	struct ndis_pkt_8021q_info *vlan;
	struct ndis_tcp_ip_checksum_info *csum_info;
	u16 vlan_tci = 0;
	struct net_device_context *net_device_ctx = netdev_priv(dev->ndev);

	rndis_pkt = &msg->msg.pkt;

@@ -368,7 +364,7 @@ static int rndis_filter_receive_data(struct rndis_device *dev,
	 * should be the data packet size plus the trailer padding size
	 */
	if (pkt->total_data_buflen < rndis_pkt->data_len) {
		netdev_err(dev->net_dev->ndev, "rndis message buffer "
		netdev_err(dev->ndev, "rndis message buffer "
			   "overflow detected (got %u, min %u)"
			   "...dropping this message!\n",
			   pkt->total_data_buflen, rndis_pkt->data_len);
@@ -390,7 +386,7 @@ static int rndis_filter_receive_data(struct rndis_device *dev,
	}

	csum_info = rndis_get_ppi(rndis_pkt, TCPIP_CHKSUM_PKTINFO);
	return netvsc_recv_callback(dev->net_dev->dev, pkt, data,
	return netvsc_recv_callback(net_device_ctx->device_ctx, pkt, data,
				    csum_info, channel, vlan_tci);
}

@@ -399,10 +395,11 @@ int rndis_filter_receive(struct hv_device *dev,
				void **data,
				struct vmbus_channel *channel)
{
	struct netvsc_device *net_dev = hv_get_drvdata(dev);
	struct net_device *ndev = hv_get_drvdata(dev);
	struct net_device_context *net_device_ctx = netdev_priv(ndev);
	struct netvsc_device *net_dev = net_device_ctx->nvdev;
	struct rndis_device *rndis_dev;
	struct rndis_message *rndis_msg;
	struct net_device *ndev;
	int ret = 0;

	if (!net_dev) {
@@ -410,8 +407,6 @@ int rndis_filter_receive(struct hv_device *dev,
		goto exit;
	}

	ndev = net_dev->ndev;

	/* Make sure the rndis device state is initialized */
	if (!net_dev->extension) {
		netdev_err(ndev, "got rndis message but no rndis device - "
@@ -430,7 +425,7 @@ int rndis_filter_receive(struct hv_device *dev,

	rndis_msg = *data;

	if (netif_msg_rx_err(net_dev->nd_ctx))
	if (netif_msg_rx_err(net_device_ctx))
		dump_rndis_message(dev, rndis_msg);

	switch (rndis_msg->ndis_msg_type) {
@@ -550,9 +545,10 @@ static int rndis_filter_query_device_mac(struct rndis_device *dev)

int rndis_filter_set_device_mac(struct hv_device *hdev, char *mac)
{
	struct netvsc_device *nvdev = hv_get_drvdata(hdev);
	struct net_device *ndev = hv_get_drvdata(hdev);
	struct net_device_context *net_device_ctx = netdev_priv(ndev);
	struct netvsc_device *nvdev = net_device_ctx->nvdev;
	struct rndis_device *rdev = nvdev->extension;
	struct net_device *ndev = nvdev->ndev;
	struct rndis_request *request;
	struct rndis_set_request *set;
	struct rndis_config_parameter_info *cpi;
@@ -629,9 +625,10 @@ static int
rndis_filter_set_offload_params(struct hv_device *hdev,
				struct ndis_offload_params *req_offloads)
{
	struct netvsc_device *nvdev = hv_get_drvdata(hdev);
	struct net_device *ndev = hv_get_drvdata(hdev);
	struct net_device_context *net_device_ctx = netdev_priv(ndev);
	struct netvsc_device *nvdev = net_device_ctx->nvdev;
	struct rndis_device *rdev = nvdev->extension;
	struct net_device *ndev = nvdev->ndev;
	struct rndis_request *request;
	struct rndis_set_request *set;
	struct ndis_offload_params *offload_params;
@@ -703,7 +700,7 @@ u8 netvsc_hash_key[HASH_KEYLEN] = {

static int rndis_filter_set_rss_param(struct rndis_device *rdev, int num_queue)
{
	struct net_device *ndev = rdev->net_dev->ndev;
	struct net_device *ndev = rdev->ndev;
	struct rndis_request *request;
	struct rndis_set_request *set;
	struct rndis_set_complete *set_complete;
@@ -799,9 +796,7 @@ int rndis_filter_set_packet_filter(struct rndis_device *dev, u32 new_filter)
	u32 status;
	int ret;
	unsigned long t;
	struct net_device *ndev;

	ndev = dev->net_dev->ndev;
	struct net_device *ndev = dev->ndev;

	request = get_rndis_request(dev, RNDIS_MSG_SET,
			RNDIS_MESSAGE_SIZE(struct rndis_set_request) +
@@ -856,7 +851,8 @@ static int rndis_filter_init_device(struct rndis_device *dev)
	u32 status;
	int ret;
	unsigned long t;
	struct netvsc_device *nvdev = dev->net_dev;
	struct net_device_context *net_device_ctx = netdev_priv(dev->ndev);
	struct netvsc_device *nvdev = net_device_ctx->nvdev;

	request = get_rndis_request(dev, RNDIS_MSG_INIT,
			RNDIS_MESSAGE_SIZE(struct rndis_initialize_request));
@@ -879,7 +875,6 @@ static int rndis_filter_init_device(struct rndis_device *dev)
		goto cleanup;
	}


	t = wait_for_completion_timeout(&request->wait_event, 5*HZ);

	if (t == 0) {
@@ -910,8 +905,9 @@ static void rndis_filter_halt_device(struct rndis_device *dev)
{
	struct rndis_request *request;
	struct rndis_halt_request *halt;
	struct netvsc_device *nvdev = dev->net_dev;
	struct hv_device *hdev = nvdev->dev;
	struct net_device_context *net_device_ctx = netdev_priv(dev->ndev);
	struct netvsc_device *nvdev = net_device_ctx->nvdev;
	struct hv_device *hdev = net_device_ctx->device_ctx;
	ulong flags;

	/* Attempt to do a rndis device halt */
@@ -979,13 +975,14 @@ static int rndis_filter_close_device(struct rndis_device *dev)

static void netvsc_sc_open(struct vmbus_channel *new_sc)
{
	struct netvsc_device *nvscdev;
	struct net_device *ndev =
		hv_get_drvdata(new_sc->primary_channel->device_obj);
	struct net_device_context *net_device_ctx = netdev_priv(ndev);
	struct netvsc_device *nvscdev = net_device_ctx->nvdev;
	u16 chn_index = new_sc->offermsg.offer.sub_channel_index;
	int ret;
	unsigned long flags;

	nvscdev = hv_get_drvdata(new_sc->primary_channel->device_obj);

	if (chn_index >= nvscdev->num_chn)
		return;

@@ -1010,6 +1007,8 @@ int rndis_filter_device_add(struct hv_device *dev,
				  void *additional_info)
{
	int ret;
	struct net_device *net = hv_get_drvdata(dev);
	struct net_device_context *net_device_ctx = netdev_priv(net);
	struct netvsc_device *net_device;
	struct rndis_device *rndis_device;
	struct netvsc_device_info *device_info = additional_info;
@@ -1040,16 +1039,15 @@ int rndis_filter_device_add(struct hv_device *dev,
		return ret;
	}


	/* Initialize the rndis device */
	net_device = hv_get_drvdata(dev);
	net_device = net_device_ctx->nvdev;
	net_device->max_chn = 1;
	net_device->num_chn = 1;

	spin_lock_init(&net_device->sc_lock);

	net_device->extension = rndis_device;
	rndis_device->net_dev = net_device;
	rndis_device->ndev = net;

	/* Send the rndis initialization message */
	ret = rndis_filter_init_device(rndis_device);
@@ -1063,8 +1061,8 @@ int rndis_filter_device_add(struct hv_device *dev,
	ret = rndis_filter_query_device(rndis_device,
					RNDIS_OID_GEN_MAXIMUM_FRAME_SIZE,
					&mtu, &size);
	if (ret == 0 && size == sizeof(u32) && mtu < net_device->ndev->mtu)
		net_device->ndev->mtu = mtu;
	if (ret == 0 && size == sizeof(u32) && mtu < net->mtu)
		net->mtu = mtu;

	/* Get the mac address */
	ret = rndis_filter_query_device_mac(rndis_device);
@@ -1198,7 +1196,9 @@ int rndis_filter_device_add(struct hv_device *dev,

void rndis_filter_device_remove(struct hv_device *dev)
{
	struct netvsc_device *net_dev = hv_get_drvdata(dev);
	struct net_device *ndev = hv_get_drvdata(dev);
	struct net_device_context *net_device_ctx = netdev_priv(ndev);
	struct netvsc_device *net_dev = net_device_ctx->nvdev;
	struct rndis_device *rndis_dev = net_dev->extension;
	unsigned long t;

@@ -1224,7 +1224,9 @@ void rndis_filter_device_remove(struct hv_device *dev)

int rndis_filter_open(struct hv_device *dev)
{
	struct netvsc_device *net_device = hv_get_drvdata(dev);
	struct net_device *ndev = hv_get_drvdata(dev);
	struct net_device_context *net_device_ctx = netdev_priv(ndev);
	struct netvsc_device *net_device = net_device_ctx->nvdev;

	if (!net_device)
		return -EINVAL;
@@ -1237,7 +1239,9 @@ int rndis_filter_open(struct hv_device *dev)

int rndis_filter_close(struct hv_device *dev)
{
	struct netvsc_device *nvdev = hv_get_drvdata(dev);
	struct net_device *ndev = hv_get_drvdata(dev);
	struct net_device_context *net_device_ctx = netdev_priv(ndev);
	struct netvsc_device *nvdev = net_device_ctx->nvdev;

	if (!nvdev)
		return -EINVAL;