netvsc.c revision 4d447c9a6ebc0142d320f075c5bac6d202a79fd4
1fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen/*
2fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen * Copyright (c) 2009, Microsoft Corporation.
3fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen *
4fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen * This program is free software; you can redistribute it and/or modify it
5fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen * under the terms and conditions of the GNU General Public License,
6fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen * version 2, as published by the Free Software Foundation.
7fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen *
8fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen * This program is distributed in the hope it will be useful, but WITHOUT
9fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
11fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen * more details.
12fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen *
13fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen * You should have received a copy of the GNU General Public License along with
14fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
15fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen * Place - Suite 330, Boston, MA 02111-1307 USA.
16fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen *
17fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen * Authors:
18d0e94d17ed8590d53252212414a627125825b379Haiyang Zhang *   Haiyang Zhang <haiyangz@microsoft.com>
19fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen *   Hank Janssen  <hjanssen@microsoft.com>
20fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen */
21eb335bc42781ddc19da98a3c74add1013ba08da2Hank Janssen#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
22eb335bc42781ddc19da98a3c74add1013ba08da2Hank Janssen
235654e932262840f853233317689fc59536226d76Greg Kroah-Hartman#include <linux/kernel.h>
240c3b7b2f75158f9420ceeb87d5924bdbd8d0304aK. Y. Srinivasan#include <linux/sched.h>
250c3b7b2f75158f9420ceeb87d5924bdbd8d0304aK. Y. Srinivasan#include <linux/wait.h>
260ffa63b09bf99ce3ee879c7de1c687267a90d20bGreg Kroah-Hartman#include <linux/mm.h>
27b4362c9c1fe8bec487e275f92fdf57c585ac236aGreg Kroah-Hartman#include <linux/delay.h>
2821a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman#include <linux/io.h>
295a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h>
30d9871158718778ff060f08cbee0c61eb23041671Haiyang Zhang#include <linux/netdevice.h>
31f157e78de5923dfb209355f3005ce1b5d64f7998Haiyang Zhang#include <linux/if_ether.h>
323f335ea2131b14bca2333b4316c8d4dd737e30dbK. Y. Srinivasan
335ca7252a7e2be5e05772f202d94e173b7224e7a9K. Y. Srinivasan#include "hyperv_net.h"
34fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
35fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
365a71ae303c0f82968d93d86724c1d94d753b34d7Haiyang Zhangstatic struct netvsc_device *alloc_net_device(struct hv_device *device)
37fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen{
3885799a37553f89b23797ec4f69e45f6c5e9109dfHaiyang Zhang	struct netvsc_device *net_device;
392ddd5e5fb342b9f014d61941a4f73c0bd9b50a60K. Y. Srinivasan	struct net_device *ndev = hv_get_drvdata(device);
40fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
4185799a37553f89b23797ec4f69e45f6c5e9109dfHaiyang Zhang	net_device = kzalloc(sizeof(struct netvsc_device), GFP_KERNEL);
4285799a37553f89b23797ec4f69e45f6c5e9109dfHaiyang Zhang	if (!net_device)
43fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen		return NULL;
44fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
454d447c9a6ebc0142d320f075c5bac6d202a79fd4Haiyang Zhang	net_device->start_remove = false;
46c38b9c7118b95aa48bfa38d3bcd241dba3d23c10K. Y. Srinivasan	net_device->destroy = false;
4753d21fdbf4d38dcfe27173d746acf74ea1a19958Haiyang Zhang	net_device->dev = device;
482ddd5e5fb342b9f014d61941a4f73c0bd9b50a60K. Y. Srinivasan	net_device->ndev = ndev;
49fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
502ddd5e5fb342b9f014d61941a4f73c0bd9b50a60K. Y. Srinivasan	hv_set_drvdata(device, net_device);
5185799a37553f89b23797ec4f69e45f6c5e9109dfHaiyang Zhang	return net_device;
52fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen}
53fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
545a71ae303c0f82968d93d86724c1d94d753b34d7Haiyang Zhangstatic struct netvsc_device *get_outbound_net_device(struct hv_device *device)
55fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen{
5685799a37553f89b23797ec4f69e45f6c5e9109dfHaiyang Zhang	struct netvsc_device *net_device;
57fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
582ddd5e5fb342b9f014d61941a4f73c0bd9b50a60K. Y. Srinivasan	net_device = hv_get_drvdata(device);
599d88f33a1530f4241227226e7479d36ac959e9ceK. Y. Srinivasan	if (net_device && net_device->destroy)
6085799a37553f89b23797ec4f69e45f6c5e9109dfHaiyang Zhang		net_device = NULL;
61fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
6285799a37553f89b23797ec4f69e45f6c5e9109dfHaiyang Zhang	return net_device;
63fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen}
64fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
655a71ae303c0f82968d93d86724c1d94d753b34d7Haiyang Zhangstatic struct netvsc_device *get_inbound_net_device(struct hv_device *device)
66fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen{
6785799a37553f89b23797ec4f69e45f6c5e9109dfHaiyang Zhang	struct netvsc_device *net_device;
68fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
692ddd5e5fb342b9f014d61941a4f73c0bd9b50a60K. Y. Srinivasan	net_device = hv_get_drvdata(device);
709d88f33a1530f4241227226e7479d36ac959e9ceK. Y. Srinivasan
719d88f33a1530f4241227226e7479d36ac959e9ceK. Y. Srinivasan	if (!net_device)
729d88f33a1530f4241227226e7479d36ac959e9ceK. Y. Srinivasan		goto get_in_err;
739d88f33a1530f4241227226e7479d36ac959e9ceK. Y. Srinivasan
749d88f33a1530f4241227226e7479d36ac959e9ceK. Y. Srinivasan	if (net_device->destroy &&
759d88f33a1530f4241227226e7479d36ac959e9ceK. Y. Srinivasan		atomic_read(&net_device->num_outstanding_sends) == 0)
7685799a37553f89b23797ec4f69e45f6c5e9109dfHaiyang Zhang		net_device = NULL;
77fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
789d88f33a1530f4241227226e7479d36ac959e9ceK. Y. Srinivasanget_in_err:
7985799a37553f89b23797ec4f69e45f6c5e9109dfHaiyang Zhang	return net_device;
80fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen}
81fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
82fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
83ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhangstatic int netvsc_destroy_recv_buf(struct netvsc_device *net_device)
84ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang{
85ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang	struct nvsp_message *revoke_packet;
86ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang	int ret = 0;
872ddd5e5fb342b9f014d61941a4f73c0bd9b50a60K. Y. Srinivasan	struct net_device *ndev = net_device->ndev;
88ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang
89ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang	/*
90ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang	 * If we got a section count, it means we received a
91ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang	 * SendReceiveBufferComplete msg (ie sent
92ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang	 * NvspMessage1TypeSendReceiveBuffer msg) therefore, we need
93ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang	 * to send a revoke msg here
94ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang	 */
95ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang	if (net_device->recv_section_cnt) {
96ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang		/* Send the revoke receive buffer */
97ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang		revoke_packet = &net_device->revoke_packet;
98ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang		memset(revoke_packet, 0, sizeof(struct nvsp_message));
99ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang
100ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang		revoke_packet->hdr.msg_type =
101ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang			NVSP_MSG1_TYPE_REVOKE_RECV_BUF;
102ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang		revoke_packet->msg.v1_msg.
103ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang		revoke_recv_buf.id = NETVSC_RECEIVE_BUFFER_ID;
104ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang
105ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang		ret = vmbus_sendpacket(net_device->dev->channel,
106ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang				       revoke_packet,
107ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang				       sizeof(struct nvsp_message),
108ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang				       (unsigned long)revoke_packet,
109ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang				       VM_PKT_DATA_INBAND, 0);
110ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang		/*
111ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang		 * If we failed here, we might as well return and
112ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang		 * have a leak rather than continue and a bugchk
113ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang		 */
114ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang		if (ret != 0) {
115d9871158718778ff060f08cbee0c61eb23041671Haiyang Zhang			netdev_err(ndev, "unable to send "
116c909ebbd0dcf19c617408c2cfde56c4bbd4f6cb4Haiyang Zhang				"revoke receive buffer to netvsp\n");
117a3e00530469baa39ccc08b1731a4e120bd63012fK. Y. Srinivasan			return ret;
118ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang		}
119ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang	}
120ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang
121ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang	/* Teardown the gpadl on the vsp end */
122ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang	if (net_device->recv_buf_gpadl_handle) {
123ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang		ret = vmbus_teardown_gpadl(net_device->dev->channel,
124ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang			   net_device->recv_buf_gpadl_handle);
125ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang
126ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang		/* If we failed here, we might as well return and have a leak
127ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang		 * rather than continue and a bugchk
128ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang		 */
129ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang		if (ret != 0) {
130d9871158718778ff060f08cbee0c61eb23041671Haiyang Zhang			netdev_err(ndev,
131c909ebbd0dcf19c617408c2cfde56c4bbd4f6cb4Haiyang Zhang				   "unable to teardown receive buffer's gpadl\n");
1327f9615e6f6c703c68f84460fe22b858be6c258d1Dan Carpenter			return ret;
133ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang		}
134ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang		net_device->recv_buf_gpadl_handle = 0;
135ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang	}
136ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang
137ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang	if (net_device->recv_buf) {
138ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang		/* Free up the receive buffer */
139ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang		free_pages((unsigned long)net_device->recv_buf,
140ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang			get_order(net_device->recv_buf_size));
141ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang		net_device->recv_buf = NULL;
142ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang	}
143ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang
144ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang	if (net_device->recv_section) {
145ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang		net_device->recv_section_cnt = 0;
146ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang		kfree(net_device->recv_section);
147ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang		net_device->recv_section = NULL;
148ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang	}
149ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang
150ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang	return ret;
151ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang}
152ec91cd09b153d896d14bb2882d6128a97f00ff41Haiyang Zhang
1535a71ae303c0f82968d93d86724c1d94d753b34d7Haiyang Zhangstatic int netvsc_init_recv_buf(struct hv_device *device)
154fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen{
15521a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman	int ret = 0;
15635abb21ace3413de6ea8d5c7750cedfd46111f0cK. Y. Srinivasan	int t;
15785799a37553f89b23797ec4f69e45f6c5e9109dfHaiyang Zhang	struct netvsc_device *net_device;
15885799a37553f89b23797ec4f69e45f6c5e9109dfHaiyang Zhang	struct nvsp_message *init_packet;
1592ddd5e5fb342b9f014d61941a4f73c0bd9b50a60K. Y. Srinivasan	struct net_device *ndev;
160fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
1615a71ae303c0f82968d93d86724c1d94d753b34d7Haiyang Zhang	net_device = get_outbound_net_device(device);
1622ddd5e5fb342b9f014d61941a4f73c0bd9b50a60K. Y. Srinivasan	if (!net_device)
163927bc33c0a239b706635b23c5cc1f3df2a3c8b86K. Y. Srinivasan		return -ENODEV;
1642ddd5e5fb342b9f014d61941a4f73c0bd9b50a60K. Y. Srinivasan	ndev = net_device->ndev;
165fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
16653d21fdbf4d38dcfe27173d746acf74ea1a19958Haiyang Zhang	net_device->recv_buf =
167df3493e0b3ba72f9b6192a91b24197cac41ce557K. Y. Srinivasan		(void *)__get_free_pages(GFP_KERNEL|__GFP_ZERO,
168df3493e0b3ba72f9b6192a91b24197cac41ce557K. Y. Srinivasan				get_order(net_device->recv_buf_size));
16953d21fdbf4d38dcfe27173d746acf74ea1a19958Haiyang Zhang	if (!net_device->recv_buf) {
170d9871158718778ff060f08cbee0c61eb23041671Haiyang Zhang		netdev_err(ndev, "unable to allocate receive "
171c909ebbd0dcf19c617408c2cfde56c4bbd4f6cb4Haiyang Zhang			"buffer of size %d\n", net_device->recv_buf_size);
172927bc33c0a239b706635b23c5cc1f3df2a3c8b86K. Y. Srinivasan		ret = -ENOMEM;
1730c3b7b2f75158f9420ceeb87d5924bdbd8d0304aK. Y. Srinivasan		goto cleanup;
174fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen	}
175fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
176454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton	/*
177454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton	 * Establish the gpadl handle for this buffer on this
178454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton	 * channel.  Note: This call uses the vmbus connection rather
179454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton	 * than the channel to establish the gpadl handle.
180454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton	 */
18153d21fdbf4d38dcfe27173d746acf74ea1a19958Haiyang Zhang	ret = vmbus_establish_gpadl(device->channel, net_device->recv_buf,
18253d21fdbf4d38dcfe27173d746acf74ea1a19958Haiyang Zhang				    net_device->recv_buf_size,
18353d21fdbf4d38dcfe27173d746acf74ea1a19958Haiyang Zhang				    &net_device->recv_buf_gpadl_handle);
18421a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman	if (ret != 0) {
185d9871158718778ff060f08cbee0c61eb23041671Haiyang Zhang		netdev_err(ndev,
186c909ebbd0dcf19c617408c2cfde56c4bbd4f6cb4Haiyang Zhang			"unable to establish receive buffer's gpadl\n");
1870c3b7b2f75158f9420ceeb87d5924bdbd8d0304aK. Y. Srinivasan		goto cleanup;
188fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen	}
189fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
190fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
191454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton	/* Notify the NetVsp of the gpadl handle */
19253d21fdbf4d38dcfe27173d746acf74ea1a19958Haiyang Zhang	init_packet = &net_device->channel_init_pkt;
193fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
19485799a37553f89b23797ec4f69e45f6c5e9109dfHaiyang Zhang	memset(init_packet, 0, sizeof(struct nvsp_message));
195fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
19653d21fdbf4d38dcfe27173d746acf74ea1a19958Haiyang Zhang	init_packet->hdr.msg_type = NVSP_MSG1_TYPE_SEND_RECV_BUF;
19753d21fdbf4d38dcfe27173d746acf74ea1a19958Haiyang Zhang	init_packet->msg.v1_msg.send_recv_buf.
19853d21fdbf4d38dcfe27173d746acf74ea1a19958Haiyang Zhang		gpadl_handle = net_device->recv_buf_gpadl_handle;
19953d21fdbf4d38dcfe27173d746acf74ea1a19958Haiyang Zhang	init_packet->msg.v1_msg.
20053d21fdbf4d38dcfe27173d746acf74ea1a19958Haiyang Zhang		send_recv_buf.id = NETVSC_RECEIVE_BUFFER_ID;
201fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
202454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton	/* Send the gpadl notification request */
20385799a37553f89b23797ec4f69e45f6c5e9109dfHaiyang Zhang	ret = vmbus_sendpacket(device->channel, init_packet,
2045a4df29058625ce59f549730817961b293f58d49Greg Kroah-Hartman			       sizeof(struct nvsp_message),
20585799a37553f89b23797ec4f69e45f6c5e9109dfHaiyang Zhang			       (unsigned long)init_packet,
206415f228712d86dd5598f809e8e379ff5ad729652Haiyang Zhang			       VM_PKT_DATA_INBAND,
2075a4df29058625ce59f549730817961b293f58d49Greg Kroah-Hartman			       VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
20821a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman	if (ret != 0) {
209d9871158718778ff060f08cbee0c61eb23041671Haiyang Zhang		netdev_err(ndev,
210c909ebbd0dcf19c617408c2cfde56c4bbd4f6cb4Haiyang Zhang			"unable to send receive buffer's gpadl to netvsp\n");
2110c3b7b2f75158f9420ceeb87d5924bdbd8d0304aK. Y. Srinivasan		goto cleanup;
212fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen	}
213fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
2145c5781b3f88567211ecaaada13431af15c8c6003K. Y. Srinivasan	t = wait_for_completion_timeout(&net_device->channel_init_wait, 5*HZ);
21535abb21ace3413de6ea8d5c7750cedfd46111f0cK. Y. Srinivasan	BUG_ON(t == 0);
2160c3b7b2f75158f9420ceeb87d5924bdbd8d0304aK. Y. Srinivasan
217fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
218454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton	/* Check the response */
21953d21fdbf4d38dcfe27173d746acf74ea1a19958Haiyang Zhang	if (init_packet->msg.v1_msg.
22053d21fdbf4d38dcfe27173d746acf74ea1a19958Haiyang Zhang	    send_recv_buf_complete.status != NVSP_STAT_SUCCESS) {
221d9871158718778ff060f08cbee0c61eb23041671Haiyang Zhang		netdev_err(ndev, "Unable to complete receive buffer "
2228bff33ab417f246dac4ab9835be6894eaddfb546Haiyang Zhang			   "initialization with NetVsp - status %d\n",
22353d21fdbf4d38dcfe27173d746acf74ea1a19958Haiyang Zhang			   init_packet->msg.v1_msg.
22453d21fdbf4d38dcfe27173d746acf74ea1a19958Haiyang Zhang			   send_recv_buf_complete.status);
225927bc33c0a239b706635b23c5cc1f3df2a3c8b86K. Y. Srinivasan		ret = -EINVAL;
2260c3b7b2f75158f9420ceeb87d5924bdbd8d0304aK. Y. Srinivasan		goto cleanup;
227fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen	}
228fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
229454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton	/* Parse the response */
230fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
23153d21fdbf4d38dcfe27173d746acf74ea1a19958Haiyang Zhang	net_device->recv_section_cnt = init_packet->msg.
23253d21fdbf4d38dcfe27173d746acf74ea1a19958Haiyang Zhang		v1_msg.send_recv_buf_complete.num_sections;
233fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
234c18132005e711c07523d8c6602e5b2266ab9a0f2Haiyang Zhang	net_device->recv_section = kmemdup(
235c18132005e711c07523d8c6602e5b2266ab9a0f2Haiyang Zhang		init_packet->msg.v1_msg.send_recv_buf_complete.sections,
236c18132005e711c07523d8c6602e5b2266ab9a0f2Haiyang Zhang		net_device->recv_section_cnt *
237c18132005e711c07523d8c6602e5b2266ab9a0f2Haiyang Zhang		sizeof(struct nvsp_1_receive_buffer_section),
238c18132005e711c07523d8c6602e5b2266ab9a0f2Haiyang Zhang		GFP_KERNEL);
23953d21fdbf4d38dcfe27173d746acf74ea1a19958Haiyang Zhang	if (net_device->recv_section == NULL) {
240927bc33c0a239b706635b23c5cc1f3df2a3c8b86K. Y. Srinivasan		ret = -EINVAL;
2410c3b7b2f75158f9420ceeb87d5924bdbd8d0304aK. Y. Srinivasan		goto cleanup;
242fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen	}
243fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
24421a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman	/*
24521a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman	 * For 1st release, there should only be 1 section that represents the
24621a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman	 * entire receive buffer
24721a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman	 */
24853d21fdbf4d38dcfe27173d746acf74ea1a19958Haiyang Zhang	if (net_device->recv_section_cnt != 1 ||
24953d21fdbf4d38dcfe27173d746acf74ea1a19958Haiyang Zhang	    net_device->recv_section->offset != 0) {
250927bc33c0a239b706635b23c5cc1f3df2a3c8b86K. Y. Srinivasan		ret = -EINVAL;
2510c3b7b2f75158f9420ceeb87d5924bdbd8d0304aK. Y. Srinivasan		goto cleanup;
252fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen	}
253fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
2540c3b7b2f75158f9420ceeb87d5924bdbd8d0304aK. Y. Srinivasan	goto exit;
255fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
2560c3b7b2f75158f9420ceeb87d5924bdbd8d0304aK. Y. Srinivasancleanup:
2575a71ae303c0f82968d93d86724c1d94d753b34d7Haiyang Zhang	netvsc_destroy_recv_buf(net_device);
258fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
2590c3b7b2f75158f9420ceeb87d5924bdbd8d0304aK. Y. Srinivasanexit:
260fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen	return ret;
261fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen}
262fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
263fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
264f157e78de5923dfb209355f3005ce1b5d64f7998Haiyang Zhang/* Negotiate NVSP protocol version */
265f157e78de5923dfb209355f3005ce1b5d64f7998Haiyang Zhangstatic int negotiate_nvsp_ver(struct hv_device *device,
266f157e78de5923dfb209355f3005ce1b5d64f7998Haiyang Zhang			      struct netvsc_device *net_device,
267f157e78de5923dfb209355f3005ce1b5d64f7998Haiyang Zhang			      struct nvsp_message *init_packet,
268f157e78de5923dfb209355f3005ce1b5d64f7998Haiyang Zhang			      u32 nvsp_ver)
269fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen{
27035abb21ace3413de6ea8d5c7750cedfd46111f0cK. Y. Srinivasan	int ret, t;
271fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
27285799a37553f89b23797ec4f69e45f6c5e9109dfHaiyang Zhang	memset(init_packet, 0, sizeof(struct nvsp_message));
27353d21fdbf4d38dcfe27173d746acf74ea1a19958Haiyang Zhang	init_packet->hdr.msg_type = NVSP_MSG_TYPE_INIT;
274f157e78de5923dfb209355f3005ce1b5d64f7998Haiyang Zhang	init_packet->msg.init_msg.init.min_protocol_ver = nvsp_ver;
275f157e78de5923dfb209355f3005ce1b5d64f7998Haiyang Zhang	init_packet->msg.init_msg.init.max_protocol_ver = nvsp_ver;
276fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
277454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton	/* Send the init request */
27885799a37553f89b23797ec4f69e45f6c5e9109dfHaiyang Zhang	ret = vmbus_sendpacket(device->channel, init_packet,
2795a4df29058625ce59f549730817961b293f58d49Greg Kroah-Hartman			       sizeof(struct nvsp_message),
28085799a37553f89b23797ec4f69e45f6c5e9109dfHaiyang Zhang			       (unsigned long)init_packet,
281415f228712d86dd5598f809e8e379ff5ad729652Haiyang Zhang			       VM_PKT_DATA_INBAND,
2825a4df29058625ce59f549730817961b293f58d49Greg Kroah-Hartman			       VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
28321a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman
284b8a3d52b2f7db637edcb62f9a332e1b35eefad13Hank Janssen	if (ret != 0)
285f157e78de5923dfb209355f3005ce1b5d64f7998Haiyang Zhang		return ret;
286fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
2875c5781b3f88567211ecaaada13431af15c8c6003K. Y. Srinivasan	t = wait_for_completion_timeout(&net_device->channel_init_wait, 5*HZ);
28835abb21ace3413de6ea8d5c7750cedfd46111f0cK. Y. Srinivasan
289f157e78de5923dfb209355f3005ce1b5d64f7998Haiyang Zhang	if (t == 0)
290f157e78de5923dfb209355f3005ce1b5d64f7998Haiyang Zhang		return -ETIMEDOUT;
291fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
29253d21fdbf4d38dcfe27173d746acf74ea1a19958Haiyang Zhang	if (init_packet->msg.init_msg.init_complete.status !=
293f157e78de5923dfb209355f3005ce1b5d64f7998Haiyang Zhang	    NVSP_STAT_SUCCESS)
294f157e78de5923dfb209355f3005ce1b5d64f7998Haiyang Zhang		return -EINVAL;
295fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
296f157e78de5923dfb209355f3005ce1b5d64f7998Haiyang Zhang	if (nvsp_ver != NVSP_PROTOCOL_VERSION_2)
297f157e78de5923dfb209355f3005ce1b5d64f7998Haiyang Zhang		return 0;
298f157e78de5923dfb209355f3005ce1b5d64f7998Haiyang Zhang
299f157e78de5923dfb209355f3005ce1b5d64f7998Haiyang Zhang	/* NVSPv2 only: Send NDIS config */
300f157e78de5923dfb209355f3005ce1b5d64f7998Haiyang Zhang	memset(init_packet, 0, sizeof(struct nvsp_message));
301f157e78de5923dfb209355f3005ce1b5d64f7998Haiyang Zhang	init_packet->hdr.msg_type = NVSP_MSG2_TYPE_SEND_NDIS_CONFIG;
3024d447c9a6ebc0142d320f075c5bac6d202a79fd4Haiyang Zhang	init_packet->msg.v2_msg.send_ndis_config.mtu = net_device->ndev->mtu;
303f157e78de5923dfb209355f3005ce1b5d64f7998Haiyang Zhang
304f157e78de5923dfb209355f3005ce1b5d64f7998Haiyang Zhang	ret = vmbus_sendpacket(device->channel, init_packet,
305f157e78de5923dfb209355f3005ce1b5d64f7998Haiyang Zhang				sizeof(struct nvsp_message),
306f157e78de5923dfb209355f3005ce1b5d64f7998Haiyang Zhang				(unsigned long)init_packet,
307f157e78de5923dfb209355f3005ce1b5d64f7998Haiyang Zhang				VM_PKT_DATA_INBAND, 0);
308f157e78de5923dfb209355f3005ce1b5d64f7998Haiyang Zhang
309f157e78de5923dfb209355f3005ce1b5d64f7998Haiyang Zhang	return ret;
310f157e78de5923dfb209355f3005ce1b5d64f7998Haiyang Zhang}
311f157e78de5923dfb209355f3005ce1b5d64f7998Haiyang Zhang
312f157e78de5923dfb209355f3005ce1b5d64f7998Haiyang Zhangstatic int netvsc_connect_vsp(struct hv_device *device)
313f157e78de5923dfb209355f3005ce1b5d64f7998Haiyang Zhang{
314f157e78de5923dfb209355f3005ce1b5d64f7998Haiyang Zhang	int ret;
315f157e78de5923dfb209355f3005ce1b5d64f7998Haiyang Zhang	struct netvsc_device *net_device;
316f157e78de5923dfb209355f3005ce1b5d64f7998Haiyang Zhang	struct nvsp_message *init_packet;
317f157e78de5923dfb209355f3005ce1b5d64f7998Haiyang Zhang	int ndis_version;
318f157e78de5923dfb209355f3005ce1b5d64f7998Haiyang Zhang	struct net_device *ndev;
319f157e78de5923dfb209355f3005ce1b5d64f7998Haiyang Zhang
320f157e78de5923dfb209355f3005ce1b5d64f7998Haiyang Zhang	net_device = get_outbound_net_device(device);
321f157e78de5923dfb209355f3005ce1b5d64f7998Haiyang Zhang	if (!net_device)
322f157e78de5923dfb209355f3005ce1b5d64f7998Haiyang Zhang		return -ENODEV;
323f157e78de5923dfb209355f3005ce1b5d64f7998Haiyang Zhang	ndev = net_device->ndev;
324f157e78de5923dfb209355f3005ce1b5d64f7998Haiyang Zhang
325f157e78de5923dfb209355f3005ce1b5d64f7998Haiyang Zhang	init_packet = &net_device->channel_init_pkt;
326f157e78de5923dfb209355f3005ce1b5d64f7998Haiyang Zhang
327f157e78de5923dfb209355f3005ce1b5d64f7998Haiyang Zhang	/* Negotiate the latest NVSP protocol supported */
328f157e78de5923dfb209355f3005ce1b5d64f7998Haiyang Zhang	if (negotiate_nvsp_ver(device, net_device, init_packet,
329f157e78de5923dfb209355f3005ce1b5d64f7998Haiyang Zhang			       NVSP_PROTOCOL_VERSION_2) == 0) {
330f157e78de5923dfb209355f3005ce1b5d64f7998Haiyang Zhang		net_device->nvsp_version = NVSP_PROTOCOL_VERSION_2;
331f157e78de5923dfb209355f3005ce1b5d64f7998Haiyang Zhang	} else if (negotiate_nvsp_ver(device, net_device, init_packet,
332f157e78de5923dfb209355f3005ce1b5d64f7998Haiyang Zhang				    NVSP_PROTOCOL_VERSION_1) == 0) {
333f157e78de5923dfb209355f3005ce1b5d64f7998Haiyang Zhang		net_device->nvsp_version = NVSP_PROTOCOL_VERSION_1;
334f157e78de5923dfb209355f3005ce1b5d64f7998Haiyang Zhang	} else {
3350f48c72ca63a6e1da7f226163c36fecd7a923fedK. Y. Srinivasan		ret = -EPROTO;
3360c3b7b2f75158f9420ceeb87d5924bdbd8d0304aK. Y. Srinivasan		goto cleanup;
337fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen	}
338f157e78de5923dfb209355f3005ce1b5d64f7998Haiyang Zhang
339f157e78de5923dfb209355f3005ce1b5d64f7998Haiyang Zhang	pr_debug("Negotiated NVSP version:%x\n", net_device->nvsp_version);
340f157e78de5923dfb209355f3005ce1b5d64f7998Haiyang Zhang
341454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton	/* Send the ndis version */
34285799a37553f89b23797ec4f69e45f6c5e9109dfHaiyang Zhang	memset(init_packet, 0, sizeof(struct nvsp_message));
343fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
34485799a37553f89b23797ec4f69e45f6c5e9109dfHaiyang Zhang	ndis_version = 0x00050000;
345fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
34653d21fdbf4d38dcfe27173d746acf74ea1a19958Haiyang Zhang	init_packet->hdr.msg_type = NVSP_MSG1_TYPE_SEND_NDIS_VER;
34753d21fdbf4d38dcfe27173d746acf74ea1a19958Haiyang Zhang	init_packet->msg.v1_msg.
34853d21fdbf4d38dcfe27173d746acf74ea1a19958Haiyang Zhang		send_ndis_ver.ndis_major_ver =
34985799a37553f89b23797ec4f69e45f6c5e9109dfHaiyang Zhang				(ndis_version & 0xFFFF0000) >> 16;
35053d21fdbf4d38dcfe27173d746acf74ea1a19958Haiyang Zhang	init_packet->msg.v1_msg.
35153d21fdbf4d38dcfe27173d746acf74ea1a19958Haiyang Zhang		send_ndis_ver.ndis_minor_ver =
35285799a37553f89b23797ec4f69e45f6c5e9109dfHaiyang Zhang				ndis_version & 0xFFFF;
353fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
354454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton	/* Send the init request */
35585799a37553f89b23797ec4f69e45f6c5e9109dfHaiyang Zhang	ret = vmbus_sendpacket(device->channel, init_packet,
3560c3b7b2f75158f9420ceeb87d5924bdbd8d0304aK. Y. Srinivasan				sizeof(struct nvsp_message),
3570c3b7b2f75158f9420ceeb87d5924bdbd8d0304aK. Y. Srinivasan				(unsigned long)init_packet,
3580c3b7b2f75158f9420ceeb87d5924bdbd8d0304aK. Y. Srinivasan				VM_PKT_DATA_INBAND, 0);
3590f48c72ca63a6e1da7f226163c36fecd7a923fedK. Y. Srinivasan	if (ret != 0)
3600c3b7b2f75158f9420ceeb87d5924bdbd8d0304aK. Y. Srinivasan		goto cleanup;
361454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton
362454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton	/* Post the big receive buffer to NetVSP */
3635a71ae303c0f82968d93d86724c1d94d753b34d7Haiyang Zhang	ret = netvsc_init_recv_buf(device);
364fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
3650c3b7b2f75158f9420ceeb87d5924bdbd8d0304aK. Y. Srinivasancleanup:
366fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen	return ret;
367fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen}
368fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
369648dc59899073d4d23ba346c0281dc96792725b3Haiyang Zhangstatic void netvsc_disconnect_vsp(struct netvsc_device *net_device)
370fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen{
3715a71ae303c0f82968d93d86724c1d94d753b34d7Haiyang Zhang	netvsc_destroy_recv_buf(net_device);
372fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen}
373fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
3743e18951955797872558dad615851a4ca63b2770eHank Janssen/*
3755a71ae303c0f82968d93d86724c1d94d753b34d7Haiyang Zhang * netvsc_device_remove - Callback when the root bus device is removed
37621a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman */
377905620d16f5c9e7c8ff850e15f47f5700824f6fbK. Y. Srinivasanint netvsc_device_remove(struct hv_device *device)
378fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen{
37985799a37553f89b23797ec4f69e45f6c5e9109dfHaiyang Zhang	struct netvsc_device *net_device;
38085799a37553f89b23797ec4f69e45f6c5e9109dfHaiyang Zhang	struct hv_netvsc_packet *netvsc_packet, *pos;
381c38b9c7118b95aa48bfa38d3bcd241dba3d23c10K. Y. Srinivasan	unsigned long flags;
382fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
3832ddd5e5fb342b9f014d61941a4f73c0bd9b50a60K. Y. Srinivasan	net_device = hv_get_drvdata(device);
384c38b9c7118b95aa48bfa38d3bcd241dba3d23c10K. Y. Srinivasan	spin_lock_irqsave(&device->channel->inbound_lock, flags);
385c38b9c7118b95aa48bfa38d3bcd241dba3d23c10K. Y. Srinivasan	net_device->destroy = true;
386c38b9c7118b95aa48bfa38d3bcd241dba3d23c10K. Y. Srinivasan	spin_unlock_irqrestore(&device->channel->inbound_lock, flags);
387c38b9c7118b95aa48bfa38d3bcd241dba3d23c10K. Y. Srinivasan
388454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton	/* Wait for all send completions */
38953d21fdbf4d38dcfe27173d746acf74ea1a19958Haiyang Zhang	while (atomic_read(&net_device->num_outstanding_sends)) {
390d9871158718778ff060f08cbee0c61eb23041671Haiyang Zhang		dev_info(&device->device,
391c909ebbd0dcf19c617408c2cfde56c4bbd4f6cb4Haiyang Zhang			"waiting for %d requests to complete...\n",
392eb335bc42781ddc19da98a3c74add1013ba08da2Hank Janssen			atomic_read(&net_device->num_outstanding_sends));
393b4362c9c1fe8bec487e275f92fdf57c585ac236aGreg Kroah-Hartman		udelay(100);
394fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen	}
395fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
396648dc59899073d4d23ba346c0281dc96792725b3Haiyang Zhang	netvsc_disconnect_vsp(net_device);
397fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
3983852409b88e8ec2a8abb28db5be25a7503297208K. Y. Srinivasan	/*
3999d88f33a1530f4241227226e7479d36ac959e9ceK. Y. Srinivasan	 * Since we have already drained, we don't need to busy wait
4009d88f33a1530f4241227226e7479d36ac959e9ceK. Y. Srinivasan	 * as was done in final_release_stor_device()
4019d88f33a1530f4241227226e7479d36ac959e9ceK. Y. Srinivasan	 * Note that we cannot set the ext pointer to NULL until
4029d88f33a1530f4241227226e7479d36ac959e9ceK. Y. Srinivasan	 * we have drained - to drain the outgoing packets, we need to
4039d88f33a1530f4241227226e7479d36ac959e9ceK. Y. Srinivasan	 * allow incoming packets.
4043852409b88e8ec2a8abb28db5be25a7503297208K. Y. Srinivasan	 */
4059d88f33a1530f4241227226e7479d36ac959e9ceK. Y. Srinivasan
4069d88f33a1530f4241227226e7479d36ac959e9ceK. Y. Srinivasan	spin_lock_irqsave(&device->channel->inbound_lock, flags);
4072ddd5e5fb342b9f014d61941a4f73c0bd9b50a60K. Y. Srinivasan	hv_set_drvdata(device, NULL);
4089d88f33a1530f4241227226e7479d36ac959e9ceK. Y. Srinivasan	spin_unlock_irqrestore(&device->channel->inbound_lock, flags);
4093852409b88e8ec2a8abb28db5be25a7503297208K. Y. Srinivasan
41086c921af41f0d40ff9105a73fb20378440f0299fK. Y. Srinivasan	/*
41186c921af41f0d40ff9105a73fb20378440f0299fK. Y. Srinivasan	 * At this point, no one should be accessing net_device
41286c921af41f0d40ff9105a73fb20378440f0299fK. Y. Srinivasan	 * except in here
41386c921af41f0d40ff9105a73fb20378440f0299fK. Y. Srinivasan	 */
414c909ebbd0dcf19c617408c2cfde56c4bbd4f6cb4Haiyang Zhang	dev_notice(&device->device, "net device safe to remove\n");
415fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
416454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton	/* Now, we can close the channel safely */
41785799a37553f89b23797ec4f69e45f6c5e9109dfHaiyang Zhang	vmbus_close(device->channel);
418fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
419454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton	/* Release all resources */
42085799a37553f89b23797ec4f69e45f6c5e9109dfHaiyang Zhang	list_for_each_entry_safe(netvsc_packet, pos,
42153d21fdbf4d38dcfe27173d746acf74ea1a19958Haiyang Zhang				 &net_device->recv_pkt_list, list_ent) {
42272a2f5bd53bf83302f4dcfe8500d4ec440545d27Haiyang Zhang		list_del(&netvsc_packet->list_ent);
42385799a37553f89b23797ec4f69e45f6c5e9109dfHaiyang Zhang		kfree(netvsc_packet);
424fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen	}
425fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
426356c4657193c8a5b3aff84fe8cdf5ddc64742801K. Y. Srinivasan	kfree(net_device);
42721a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman	return 0;
428fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen}
429fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
4305a71ae303c0f82968d93d86724c1d94d753b34d7Haiyang Zhangstatic void netvsc_send_completion(struct hv_device *device,
43185799a37553f89b23797ec4f69e45f6c5e9109dfHaiyang Zhang				   struct vmpacket_descriptor *packet)
432fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen{
43385799a37553f89b23797ec4f69e45f6c5e9109dfHaiyang Zhang	struct netvsc_device *net_device;
43485799a37553f89b23797ec4f69e45f6c5e9109dfHaiyang Zhang	struct nvsp_message *nvsp_packet;
43585799a37553f89b23797ec4f69e45f6c5e9109dfHaiyang Zhang	struct hv_netvsc_packet *nvsc_packet;
4362ddd5e5fb342b9f014d61941a4f73c0bd9b50a60K. Y. Srinivasan	struct net_device *ndev;
437fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
4385a71ae303c0f82968d93d86724c1d94d753b34d7Haiyang Zhang	net_device = get_inbound_net_device(device);
4392ddd5e5fb342b9f014d61941a4f73c0bd9b50a60K. Y. Srinivasan	if (!net_device)
440fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen		return;
4412ddd5e5fb342b9f014d61941a4f73c0bd9b50a60K. Y. Srinivasan	ndev = net_device->ndev;
442fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
44385799a37553f89b23797ec4f69e45f6c5e9109dfHaiyang Zhang	nvsp_packet = (struct nvsp_message *)((unsigned long)packet +
444415f228712d86dd5598f809e8e379ff5ad729652Haiyang Zhang			(packet->offset8 << 3));
445fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
44653d21fdbf4d38dcfe27173d746acf74ea1a19958Haiyang Zhang	if ((nvsp_packet->hdr.msg_type == NVSP_MSG_TYPE_INIT_COMPLETE) ||
44753d21fdbf4d38dcfe27173d746acf74ea1a19958Haiyang Zhang	    (nvsp_packet->hdr.msg_type ==
44853d21fdbf4d38dcfe27173d746acf74ea1a19958Haiyang Zhang	     NVSP_MSG1_TYPE_SEND_RECV_BUF_COMPLETE) ||
44953d21fdbf4d38dcfe27173d746acf74ea1a19958Haiyang Zhang	    (nvsp_packet->hdr.msg_type ==
45053d21fdbf4d38dcfe27173d746acf74ea1a19958Haiyang Zhang	     NVSP_MSG1_TYPE_SEND_SEND_BUF_COMPLETE)) {
451454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton		/* Copy the response back */
45253d21fdbf4d38dcfe27173d746acf74ea1a19958Haiyang Zhang		memcpy(&net_device->channel_init_pkt, nvsp_packet,
45321a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman		       sizeof(struct nvsp_message));
45435abb21ace3413de6ea8d5c7750cedfd46111f0cK. Y. Srinivasan		complete(&net_device->channel_init_wait);
45553d21fdbf4d38dcfe27173d746acf74ea1a19958Haiyang Zhang	} else if (nvsp_packet->hdr.msg_type ==
45653d21fdbf4d38dcfe27173d746acf74ea1a19958Haiyang Zhang		   NVSP_MSG1_TYPE_SEND_RNDIS_PKT_COMPLETE) {
457454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton		/* Get the send context */
45885799a37553f89b23797ec4f69e45f6c5e9109dfHaiyang Zhang		nvsc_packet = (struct hv_netvsc_packet *)(unsigned long)
459415f228712d86dd5598f809e8e379ff5ad729652Haiyang Zhang			packet->trans_id;
460fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
461454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton		/* Notify the layer above us */
46272a2f5bd53bf83302f4dcfe8500d4ec440545d27Haiyang Zhang		nvsc_packet->completion.send.send_completion(
46372a2f5bd53bf83302f4dcfe8500d4ec440545d27Haiyang Zhang			nvsc_packet->completion.send.send_completion_ctx);
464fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
46553d21fdbf4d38dcfe27173d746acf74ea1a19958Haiyang Zhang		atomic_dec(&net_device->num_outstanding_sends);
4661d06825b0ede541f63b5577435abd2fc649a9b5eHaiyang Zhang
4674d447c9a6ebc0142d320f075c5bac6d202a79fd4Haiyang Zhang		if (netif_queue_stopped(ndev) && !net_device->start_remove)
4681d06825b0ede541f63b5577435abd2fc649a9b5eHaiyang Zhang			netif_wake_queue(ndev);
46921a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman	} else {
470d9871158718778ff060f08cbee0c61eb23041671Haiyang Zhang		netdev_err(ndev, "Unknown send completion packet type- "
471c909ebbd0dcf19c617408c2cfde56c4bbd4f6cb4Haiyang Zhang			   "%d received!!\n", nvsp_packet->hdr.msg_type);
472fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen	}
473fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
474fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen}
475fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
476f9819f05f2c5a3fb61853c5fc8d20d61dfbfe89bK. Y. Srinivasanint netvsc_send(struct hv_device *device,
47785799a37553f89b23797ec4f69e45f6c5e9109dfHaiyang Zhang			struct hv_netvsc_packet *packet)
478fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen{
47985799a37553f89b23797ec4f69e45f6c5e9109dfHaiyang Zhang	struct netvsc_device *net_device;
48021a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman	int ret = 0;
481223c1aa632dbad672ad9b907e5d5e8f385417945Greg Kroah-Hartman	struct nvsp_message sendMessage;
4822ddd5e5fb342b9f014d61941a4f73c0bd9b50a60K. Y. Srinivasan	struct net_device *ndev;
483fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
4845a71ae303c0f82968d93d86724c1d94d753b34d7Haiyang Zhang	net_device = get_outbound_net_device(device);
4852ddd5e5fb342b9f014d61941a4f73c0bd9b50a60K. Y. Srinivasan	if (!net_device)
486ff2bd69ae3ec164b606114fcbd9b9e4d5f2bcdc7K. Y. Srinivasan		return -ENODEV;
4872ddd5e5fb342b9f014d61941a4f73c0bd9b50a60K. Y. Srinivasan	ndev = net_device->ndev;
488fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
48953d21fdbf4d38dcfe27173d746acf74ea1a19958Haiyang Zhang	sendMessage.hdr.msg_type = NVSP_MSG1_TYPE_SEND_RNDIS_PKT;
49072a2f5bd53bf83302f4dcfe8500d4ec440545d27Haiyang Zhang	if (packet->is_data_pkt) {
49121a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman		/* 0 is RMC_DATA; */
49253d21fdbf4d38dcfe27173d746acf74ea1a19958Haiyang Zhang		sendMessage.msg.v1_msg.send_rndis_pkt.channel_type = 0;
49321a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman	} else {
49421a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman		/* 1 is RMC_CONTROL; */
49553d21fdbf4d38dcfe27173d746acf74ea1a19958Haiyang Zhang		sendMessage.msg.v1_msg.send_rndis_pkt.channel_type = 1;
49621a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman	}
497fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
498454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton	/* Not using send buffer section */
49953d21fdbf4d38dcfe27173d746acf74ea1a19958Haiyang Zhang	sendMessage.msg.v1_msg.send_rndis_pkt.send_buf_section_index =
50053d21fdbf4d38dcfe27173d746acf74ea1a19958Haiyang Zhang		0xFFFFFFFF;
50153d21fdbf4d38dcfe27173d746acf74ea1a19958Haiyang Zhang	sendMessage.msg.v1_msg.send_rndis_pkt.send_buf_section_size = 0;
50221a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman
50372a2f5bd53bf83302f4dcfe8500d4ec440545d27Haiyang Zhang	if (packet->page_buf_cnt) {
50485799a37553f89b23797ec4f69e45f6c5e9109dfHaiyang Zhang		ret = vmbus_sendpacket_pagebuffer(device->channel,
50572a2f5bd53bf83302f4dcfe8500d4ec440545d27Haiyang Zhang						  packet->page_buf,
50672a2f5bd53bf83302f4dcfe8500d4ec440545d27Haiyang Zhang						  packet->page_buf_cnt,
507ff3f8eece20bb45f8b515641b3797b6047a657fdGreg Kroah-Hartman						  &sendMessage,
508ff3f8eece20bb45f8b515641b3797b6047a657fdGreg Kroah-Hartman						  sizeof(struct nvsp_message),
50985799a37553f89b23797ec4f69e45f6c5e9109dfHaiyang Zhang						  (unsigned long)packet);
51021a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman	} else {
51185799a37553f89b23797ec4f69e45f6c5e9109dfHaiyang Zhang		ret = vmbus_sendpacket(device->channel, &sendMessage,
512e4d59ac5c6bbb671b61108dad0c7cd33c753ce22Haiyang Zhang				sizeof(struct nvsp_message),
513e4d59ac5c6bbb671b61108dad0c7cd33c753ce22Haiyang Zhang				(unsigned long)packet,
514e4d59ac5c6bbb671b61108dad0c7cd33c753ce22Haiyang Zhang				VM_PKT_DATA_INBAND,
515e4d59ac5c6bbb671b61108dad0c7cd33c753ce22Haiyang Zhang				VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
516fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
517fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen	}
518fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
5191d06825b0ede541f63b5577435abd2fc649a9b5eHaiyang Zhang	if (ret == 0) {
5201d06825b0ede541f63b5577435abd2fc649a9b5eHaiyang Zhang		atomic_inc(&net_device->num_outstanding_sends);
5211d06825b0ede541f63b5577435abd2fc649a9b5eHaiyang Zhang	} else if (ret == -EAGAIN) {
5221d06825b0ede541f63b5577435abd2fc649a9b5eHaiyang Zhang		netif_stop_queue(ndev);
5231d06825b0ede541f63b5577435abd2fc649a9b5eHaiyang Zhang		if (atomic_read(&net_device->num_outstanding_sends) < 1)
5241d06825b0ede541f63b5577435abd2fc649a9b5eHaiyang Zhang			netif_wake_queue(ndev);
5251d06825b0ede541f63b5577435abd2fc649a9b5eHaiyang Zhang	} else {
526d9871158718778ff060f08cbee0c61eb23041671Haiyang Zhang		netdev_err(ndev, "Unable to send packet %p ret %d\n",
52785799a37553f89b23797ec4f69e45f6c5e9109dfHaiyang Zhang			   packet, ret);
5281d06825b0ede541f63b5577435abd2fc649a9b5eHaiyang Zhang	}
529fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
530fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen	return ret;
531fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen}
532fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
5335fa9d3c51d15a3b573c76e385dd9149cc77e7598Haiyang Zhangstatic void netvsc_send_recv_completion(struct hv_device *device,
5345fa9d3c51d15a3b573c76e385dd9149cc77e7598Haiyang Zhang					u64 transaction_id)
5355fa9d3c51d15a3b573c76e385dd9149cc77e7598Haiyang Zhang{
5365fa9d3c51d15a3b573c76e385dd9149cc77e7598Haiyang Zhang	struct nvsp_message recvcompMessage;
5375fa9d3c51d15a3b573c76e385dd9149cc77e7598Haiyang Zhang	int retries = 0;
5385fa9d3c51d15a3b573c76e385dd9149cc77e7598Haiyang Zhang	int ret;
5392ddd5e5fb342b9f014d61941a4f73c0bd9b50a60K. Y. Srinivasan	struct net_device *ndev;
5402ddd5e5fb342b9f014d61941a4f73c0bd9b50a60K. Y. Srinivasan	struct netvsc_device *net_device = hv_get_drvdata(device);
5412ddd5e5fb342b9f014d61941a4f73c0bd9b50a60K. Y. Srinivasan
5422ddd5e5fb342b9f014d61941a4f73c0bd9b50a60K. Y. Srinivasan	ndev = net_device->ndev;
5435fa9d3c51d15a3b573c76e385dd9149cc77e7598Haiyang Zhang
5445fa9d3c51d15a3b573c76e385dd9149cc77e7598Haiyang Zhang	recvcompMessage.hdr.msg_type =
5455fa9d3c51d15a3b573c76e385dd9149cc77e7598Haiyang Zhang				NVSP_MSG1_TYPE_SEND_RNDIS_PKT_COMPLETE;
5465fa9d3c51d15a3b573c76e385dd9149cc77e7598Haiyang Zhang
5475fa9d3c51d15a3b573c76e385dd9149cc77e7598Haiyang Zhang	/* FIXME: Pass in the status */
5485fa9d3c51d15a3b573c76e385dd9149cc77e7598Haiyang Zhang	recvcompMessage.msg.v1_msg.send_rndis_pkt_complete.status =
5495fa9d3c51d15a3b573c76e385dd9149cc77e7598Haiyang Zhang		NVSP_STAT_SUCCESS;
5505fa9d3c51d15a3b573c76e385dd9149cc77e7598Haiyang Zhang
5515fa9d3c51d15a3b573c76e385dd9149cc77e7598Haiyang Zhangretry_send_cmplt:
5525fa9d3c51d15a3b573c76e385dd9149cc77e7598Haiyang Zhang	/* Send the completion */
5535fa9d3c51d15a3b573c76e385dd9149cc77e7598Haiyang Zhang	ret = vmbus_sendpacket(device->channel, &recvcompMessage,
5545fa9d3c51d15a3b573c76e385dd9149cc77e7598Haiyang Zhang			       sizeof(struct nvsp_message), transaction_id,
5555fa9d3c51d15a3b573c76e385dd9149cc77e7598Haiyang Zhang			       VM_PKT_COMP, 0);
5565fa9d3c51d15a3b573c76e385dd9149cc77e7598Haiyang Zhang	if (ret == 0) {
5575fa9d3c51d15a3b573c76e385dd9149cc77e7598Haiyang Zhang		/* success */
5585fa9d3c51d15a3b573c76e385dd9149cc77e7598Haiyang Zhang		/* no-op */
559d2598f017f02bbc3623503c6e08f22f7ea473cddK. Y. Srinivasan	} else if (ret == -EAGAIN) {
5605fa9d3c51d15a3b573c76e385dd9149cc77e7598Haiyang Zhang		/* no more room...wait a bit and attempt to retry 3 times */
5615fa9d3c51d15a3b573c76e385dd9149cc77e7598Haiyang Zhang		retries++;
562d9871158718778ff060f08cbee0c61eb23041671Haiyang Zhang		netdev_err(ndev, "unable to send receive completion pkt"
563c909ebbd0dcf19c617408c2cfde56c4bbd4f6cb4Haiyang Zhang			" (tid %llx)...retrying %d\n", transaction_id, retries);
5645fa9d3c51d15a3b573c76e385dd9149cc77e7598Haiyang Zhang
5655fa9d3c51d15a3b573c76e385dd9149cc77e7598Haiyang Zhang		if (retries < 4) {
5665fa9d3c51d15a3b573c76e385dd9149cc77e7598Haiyang Zhang			udelay(100);
5675fa9d3c51d15a3b573c76e385dd9149cc77e7598Haiyang Zhang			goto retry_send_cmplt;
5685fa9d3c51d15a3b573c76e385dd9149cc77e7598Haiyang Zhang		} else {
569d9871158718778ff060f08cbee0c61eb23041671Haiyang Zhang			netdev_err(ndev, "unable to send receive "
570c909ebbd0dcf19c617408c2cfde56c4bbd4f6cb4Haiyang Zhang				"completion pkt (tid %llx)...give up retrying\n",
5715fa9d3c51d15a3b573c76e385dd9149cc77e7598Haiyang Zhang				transaction_id);
5725fa9d3c51d15a3b573c76e385dd9149cc77e7598Haiyang Zhang		}
5735fa9d3c51d15a3b573c76e385dd9149cc77e7598Haiyang Zhang	} else {
574d9871158718778ff060f08cbee0c61eb23041671Haiyang Zhang		netdev_err(ndev, "unable to send receive "
575c909ebbd0dcf19c617408c2cfde56c4bbd4f6cb4Haiyang Zhang			"completion pkt - %llx\n", transaction_id);
5765fa9d3c51d15a3b573c76e385dd9149cc77e7598Haiyang Zhang	}
5775fa9d3c51d15a3b573c76e385dd9149cc77e7598Haiyang Zhang}
5785fa9d3c51d15a3b573c76e385dd9149cc77e7598Haiyang Zhang
57957991156b949cca02737e67d8fa3fa75f80720d9Haiyang Zhang/* Send a receive completion packet to RNDIS device (ie NetVsp) */
58057991156b949cca02737e67d8fa3fa75f80720d9Haiyang Zhangstatic void netvsc_receive_completion(void *context)
58157991156b949cca02737e67d8fa3fa75f80720d9Haiyang Zhang{
58257991156b949cca02737e67d8fa3fa75f80720d9Haiyang Zhang	struct hv_netvsc_packet *packet = context;
58357991156b949cca02737e67d8fa3fa75f80720d9Haiyang Zhang	struct hv_device *device = (struct hv_device *)packet->device;
58457991156b949cca02737e67d8fa3fa75f80720d9Haiyang Zhang	struct netvsc_device *net_device;
58557991156b949cca02737e67d8fa3fa75f80720d9Haiyang Zhang	u64 transaction_id = 0;
58657991156b949cca02737e67d8fa3fa75f80720d9Haiyang Zhang	bool fsend_receive_comp = false;
58757991156b949cca02737e67d8fa3fa75f80720d9Haiyang Zhang	unsigned long flags;
5882ddd5e5fb342b9f014d61941a4f73c0bd9b50a60K. Y. Srinivasan	struct net_device *ndev;
58957991156b949cca02737e67d8fa3fa75f80720d9Haiyang Zhang
59057991156b949cca02737e67d8fa3fa75f80720d9Haiyang Zhang	/*
59157991156b949cca02737e67d8fa3fa75f80720d9Haiyang Zhang	 * Even though it seems logical to do a GetOutboundNetDevice() here to
59257991156b949cca02737e67d8fa3fa75f80720d9Haiyang Zhang	 * send out receive completion, we are using GetInboundNetDevice()
59357991156b949cca02737e67d8fa3fa75f80720d9Haiyang Zhang	 * since we may have disable outbound traffic already.
59457991156b949cca02737e67d8fa3fa75f80720d9Haiyang Zhang	 */
59557991156b949cca02737e67d8fa3fa75f80720d9Haiyang Zhang	net_device = get_inbound_net_device(device);
5962ddd5e5fb342b9f014d61941a4f73c0bd9b50a60K. Y. Srinivasan	if (!net_device)
59757991156b949cca02737e67d8fa3fa75f80720d9Haiyang Zhang		return;
5982ddd5e5fb342b9f014d61941a4f73c0bd9b50a60K. Y. Srinivasan	ndev = net_device->ndev;
59957991156b949cca02737e67d8fa3fa75f80720d9Haiyang Zhang
60057991156b949cca02737e67d8fa3fa75f80720d9Haiyang Zhang	/* Overloading use of the lock. */
60157991156b949cca02737e67d8fa3fa75f80720d9Haiyang Zhang	spin_lock_irqsave(&net_device->recv_pkt_list_lock, flags);
60257991156b949cca02737e67d8fa3fa75f80720d9Haiyang Zhang
60357991156b949cca02737e67d8fa3fa75f80720d9Haiyang Zhang	packet->xfer_page_pkt->count--;
60457991156b949cca02737e67d8fa3fa75f80720d9Haiyang Zhang
60557991156b949cca02737e67d8fa3fa75f80720d9Haiyang Zhang	/*
60657991156b949cca02737e67d8fa3fa75f80720d9Haiyang Zhang	 * Last one in the line that represent 1 xfer page packet.
60757991156b949cca02737e67d8fa3fa75f80720d9Haiyang Zhang	 * Return the xfer page packet itself to the freelist
60857991156b949cca02737e67d8fa3fa75f80720d9Haiyang Zhang	 */
60957991156b949cca02737e67d8fa3fa75f80720d9Haiyang Zhang	if (packet->xfer_page_pkt->count == 0) {
61057991156b949cca02737e67d8fa3fa75f80720d9Haiyang Zhang		fsend_receive_comp = true;
61157991156b949cca02737e67d8fa3fa75f80720d9Haiyang Zhang		transaction_id = packet->completion.recv.recv_completion_tid;
61257991156b949cca02737e67d8fa3fa75f80720d9Haiyang Zhang		list_add_tail(&packet->xfer_page_pkt->list_ent,
61357991156b949cca02737e67d8fa3fa75f80720d9Haiyang Zhang			      &net_device->recv_pkt_list);
61457991156b949cca02737e67d8fa3fa75f80720d9Haiyang Zhang
61557991156b949cca02737e67d8fa3fa75f80720d9Haiyang Zhang	}
61657991156b949cca02737e67d8fa3fa75f80720d9Haiyang Zhang
61757991156b949cca02737e67d8fa3fa75f80720d9Haiyang Zhang	/* Put the packet back */
61857991156b949cca02737e67d8fa3fa75f80720d9Haiyang Zhang	list_add_tail(&packet->list_ent, &net_device->recv_pkt_list);
61957991156b949cca02737e67d8fa3fa75f80720d9Haiyang Zhang	spin_unlock_irqrestore(&net_device->recv_pkt_list_lock, flags);
62057991156b949cca02737e67d8fa3fa75f80720d9Haiyang Zhang
62157991156b949cca02737e67d8fa3fa75f80720d9Haiyang Zhang	/* Send a receive completion for the xfer page packet */
62257991156b949cca02737e67d8fa3fa75f80720d9Haiyang Zhang	if (fsend_receive_comp)
62357991156b949cca02737e67d8fa3fa75f80720d9Haiyang Zhang		netvsc_send_recv_completion(device, transaction_id);
62457991156b949cca02737e67d8fa3fa75f80720d9Haiyang Zhang
62557991156b949cca02737e67d8fa3fa75f80720d9Haiyang Zhang}
62657991156b949cca02737e67d8fa3fa75f80720d9Haiyang Zhang
6275a71ae303c0f82968d93d86724c1d94d753b34d7Haiyang Zhangstatic void netvsc_receive(struct hv_device *device,
62885799a37553f89b23797ec4f69e45f6c5e9109dfHaiyang Zhang			    struct vmpacket_descriptor *packet)
629fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen{
63085799a37553f89b23797ec4f69e45f6c5e9109dfHaiyang Zhang	struct netvsc_device *net_device;
63185799a37553f89b23797ec4f69e45f6c5e9109dfHaiyang Zhang	struct vmtransfer_page_packet_header *vmxferpage_packet;
63285799a37553f89b23797ec4f69e45f6c5e9109dfHaiyang Zhang	struct nvsp_message *nvsp_packet;
63385799a37553f89b23797ec4f69e45f6c5e9109dfHaiyang Zhang	struct hv_netvsc_packet *netvsc_packet = NULL;
6347e23a6e9626bf93242712f146a9657d38dda497bGreg Kroah-Hartman	/* struct netvsc_driver *netvscDriver; */
63585799a37553f89b23797ec4f69e45f6c5e9109dfHaiyang Zhang	struct xferpage_packet *xferpage_packet = NULL;
636453263421f88b4a7e508c2e7b639c97e99c5b118Haiyang Zhang	int i;
637453263421f88b4a7e508c2e7b639c97e99c5b118Haiyang Zhang	int count = 0;
6386436873afce6f20fecc0c5099db899b25e1e6c2bGreg Kroah-Hartman	unsigned long flags;
6392ddd5e5fb342b9f014d61941a4f73c0bd9b50a60K. Y. Srinivasan	struct net_device *ndev;
640779b4d17c177de592141ab01d2a66d025ff4d238K. Y. Srinivasan
641d29274efb73735c6a94f20214b1e4ea994da8848Bill Pemberton	LIST_HEAD(listHead);
642fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
6435a71ae303c0f82968d93d86724c1d94d753b34d7Haiyang Zhang	net_device = get_inbound_net_device(device);
6442ddd5e5fb342b9f014d61941a4f73c0bd9b50a60K. Y. Srinivasan	if (!net_device)
645fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen		return;
6462ddd5e5fb342b9f014d61941a4f73c0bd9b50a60K. Y. Srinivasan	ndev = net_device->ndev;
647fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
64821a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman	/*
64921a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman	 * All inbound packets other than send completion should be xfer page
65021a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman	 * packet
65121a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman	 */
652415f228712d86dd5598f809e8e379ff5ad729652Haiyang Zhang	if (packet->type != VM_PKT_DATA_USING_XFER_PAGES) {
653d9871158718778ff060f08cbee0c61eb23041671Haiyang Zhang		netdev_err(ndev, "Unknown packet type received - %d\n",
654415f228712d86dd5598f809e8e379ff5ad729652Haiyang Zhang			   packet->type);
655fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen		return;
656fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen	}
657fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
65885799a37553f89b23797ec4f69e45f6c5e9109dfHaiyang Zhang	nvsp_packet = (struct nvsp_message *)((unsigned long)packet +
659415f228712d86dd5598f809e8e379ff5ad729652Haiyang Zhang			(packet->offset8 << 3));
660fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
661454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton	/* Make sure this is a valid nvsp packet */
66253d21fdbf4d38dcfe27173d746acf74ea1a19958Haiyang Zhang	if (nvsp_packet->hdr.msg_type !=
66353d21fdbf4d38dcfe27173d746acf74ea1a19958Haiyang Zhang	    NVSP_MSG1_TYPE_SEND_RNDIS_PKT) {
664d9871158718778ff060f08cbee0c61eb23041671Haiyang Zhang		netdev_err(ndev, "Unknown nvsp packet type received-"
665c909ebbd0dcf19c617408c2cfde56c4bbd4f6cb4Haiyang Zhang			" %d\n", nvsp_packet->hdr.msg_type);
666fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen		return;
667fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen	}
668fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
66985799a37553f89b23797ec4f69e45f6c5e9109dfHaiyang Zhang	vmxferpage_packet = (struct vmtransfer_page_packet_header *)packet;
670fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
671415f228712d86dd5598f809e8e379ff5ad729652Haiyang Zhang	if (vmxferpage_packet->xfer_pageset_id != NETVSC_RECEIVE_BUFFER_ID) {
672d9871158718778ff060f08cbee0c61eb23041671Haiyang Zhang		netdev_err(ndev, "Invalid xfer page set id - "
673c909ebbd0dcf19c617408c2cfde56c4bbd4f6cb4Haiyang Zhang			   "expecting %x got %x\n", NETVSC_RECEIVE_BUFFER_ID,
674415f228712d86dd5598f809e8e379ff5ad729652Haiyang Zhang			   vmxferpage_packet->xfer_pageset_id);
675fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen		return;
676fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen	}
677fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
678454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton	/*
679454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton	 * Grab free packets (range count + 1) to represent this xfer
680454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton	 * page packet. +1 to represent the xfer page packet itself.
681454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton	 * We grab it here so that we know exactly how many we can
682454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton	 * fulfil
683454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton	 */
68453d21fdbf4d38dcfe27173d746acf74ea1a19958Haiyang Zhang	spin_lock_irqsave(&net_device->recv_pkt_list_lock, flags);
68553d21fdbf4d38dcfe27173d746acf74ea1a19958Haiyang Zhang	while (!list_empty(&net_device->recv_pkt_list)) {
68653d21fdbf4d38dcfe27173d746acf74ea1a19958Haiyang Zhang		list_move_tail(net_device->recv_pkt_list.next, &listHead);
687415f228712d86dd5598f809e8e379ff5ad729652Haiyang Zhang		if (++count == vmxferpage_packet->range_cnt + 1)
688fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen			break;
689fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen	}
69053d21fdbf4d38dcfe27173d746acf74ea1a19958Haiyang Zhang	spin_unlock_irqrestore(&net_device->recv_pkt_list_lock, flags);
691fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
692454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton	/*
693454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton	 * We need at least 2 netvsc pkts (1 to represent the xfer
694454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton	 * page and at least 1 for the range) i.e. we can handled
695454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton	 * some of the xfer page packet ranges...
696454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton	 */
69721a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman	if (count < 2) {
698d9871158718778ff060f08cbee0c61eb23041671Haiyang Zhang		netdev_err(ndev, "Got only %d netvsc pkt...needed "
699c909ebbd0dcf19c617408c2cfde56c4bbd4f6cb4Haiyang Zhang			"%d pkts. Dropping this xfer page packet completely!\n",
700eb335bc42781ddc19da98a3c74add1013ba08da2Hank Janssen			count, vmxferpage_packet->range_cnt + 1);
701fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
702454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton		/* Return it to the freelist */
70353d21fdbf4d38dcfe27173d746acf74ea1a19958Haiyang Zhang		spin_lock_irqsave(&net_device->recv_pkt_list_lock, flags);
70421a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman		for (i = count; i != 0; i--) {
70592ec0893ad0996a534a5b605659d3ca31cf5dfd9Milan Dadok			list_move_tail(listHead.next,
70653d21fdbf4d38dcfe27173d746acf74ea1a19958Haiyang Zhang				       &net_device->recv_pkt_list);
707fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen		}
70853d21fdbf4d38dcfe27173d746acf74ea1a19958Haiyang Zhang		spin_unlock_irqrestore(&net_device->recv_pkt_list_lock,
70921a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman				       flags);
710fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
7115a71ae303c0f82968d93d86724c1d94d753b34d7Haiyang Zhang		netvsc_send_recv_completion(device,
712415f228712d86dd5598f809e8e379ff5ad729652Haiyang Zhang					    vmxferpage_packet->d.trans_id);
713fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
714fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen		return;
715fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen	}
716fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
717454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton	/* Remove the 1st packet to represent the xfer page packet itself */
71885799a37553f89b23797ec4f69e45f6c5e9109dfHaiyang Zhang	xferpage_packet = (struct xferpage_packet *)listHead.next;
71972a2f5bd53bf83302f4dcfe8500d4ec440545d27Haiyang Zhang	list_del(&xferpage_packet->list_ent);
720d29274efb73735c6a94f20214b1e4ea994da8848Bill Pemberton
72121a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman	/* This is how much we can satisfy */
72272a2f5bd53bf83302f4dcfe8500d4ec440545d27Haiyang Zhang	xferpage_packet->count = count - 1;
72321a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman
724415f228712d86dd5598f809e8e379ff5ad729652Haiyang Zhang	if (xferpage_packet->count != vmxferpage_packet->range_cnt) {
7258bff33ab417f246dac4ab9835be6894eaddfb546Haiyang Zhang		netdev_err(ndev, "Needed %d netvsc pkts to satisfy "
726c909ebbd0dcf19c617408c2cfde56c4bbd4f6cb4Haiyang Zhang			"this xfer page...got %d\n",
727eb335bc42781ddc19da98a3c74add1013ba08da2Hank Janssen			vmxferpage_packet->range_cnt, xferpage_packet->count);
728fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen	}
729fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
730454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton	/* Each range represents 1 RNDIS pkt that contains 1 ethernet frame */
73121a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman	for (i = 0; i < (count - 1); i++) {
73285799a37553f89b23797ec4f69e45f6c5e9109dfHaiyang Zhang		netvsc_packet = (struct hv_netvsc_packet *)listHead.next;
73372a2f5bd53bf83302f4dcfe8500d4ec440545d27Haiyang Zhang		list_del(&netvsc_packet->list_ent);
734fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
735454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton		/* Initialize the netvsc packet */
73672a2f5bd53bf83302f4dcfe8500d4ec440545d27Haiyang Zhang		netvsc_packet->xfer_page_pkt = xferpage_packet;
73772a2f5bd53bf83302f4dcfe8500d4ec440545d27Haiyang Zhang		netvsc_packet->completion.recv.recv_completion =
7385a71ae303c0f82968d93d86724c1d94d753b34d7Haiyang Zhang					netvsc_receive_completion;
73972a2f5bd53bf83302f4dcfe8500d4ec440545d27Haiyang Zhang		netvsc_packet->completion.recv.recv_completion_ctx =
74085799a37553f89b23797ec4f69e45f6c5e9109dfHaiyang Zhang					netvsc_packet;
74172a2f5bd53bf83302f4dcfe8500d4ec440545d27Haiyang Zhang		netvsc_packet->device = device;
74221a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman		/* Save this so that we can send it back */
74372a2f5bd53bf83302f4dcfe8500d4ec440545d27Haiyang Zhang		netvsc_packet->completion.recv.recv_completion_tid =
744415f228712d86dd5598f809e8e379ff5ad729652Haiyang Zhang					vmxferpage_packet->d.trans_id;
745fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
746453263421f88b4a7e508c2e7b639c97e99c5b118Haiyang Zhang		netvsc_packet->data = (void *)((unsigned long)net_device->
747453263421f88b4a7e508c2e7b639c97e99c5b118Haiyang Zhang			recv_buf + vmxferpage_packet->ranges[i].byte_offset);
74872a2f5bd53bf83302f4dcfe8500d4ec440545d27Haiyang Zhang		netvsc_packet->total_data_buflen =
749415f228712d86dd5598f809e8e379ff5ad729652Haiyang Zhang					vmxferpage_packet->ranges[i].byte_count;
750fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
751454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton		/* Pass it to the upper layer */
752ac6f78590104f01036ae7f1ecc062411a251f756K. Y. Srinivasan		rndis_filter_receive(device, netvsc_packet);
753fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
7545a71ae303c0f82968d93d86724c1d94d753b34d7Haiyang Zhang		netvsc_receive_completion(netvsc_packet->
75572a2f5bd53bf83302f4dcfe8500d4ec440545d27Haiyang Zhang				completion.recv.recv_completion_ctx);
756fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen	}
757fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
758fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen}
759fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
7605a71ae303c0f82968d93d86724c1d94d753b34d7Haiyang Zhangstatic void netvsc_channel_cb(void *context)
761fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen{
76221a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman	int ret;
76385799a37553f89b23797ec4f69e45f6c5e9109dfHaiyang Zhang	struct hv_device *device = context;
76485799a37553f89b23797ec4f69e45f6c5e9109dfHaiyang Zhang	struct netvsc_device *net_device;
76585799a37553f89b23797ec4f69e45f6c5e9109dfHaiyang Zhang	u32 bytes_recvd;
76685799a37553f89b23797ec4f69e45f6c5e9109dfHaiyang Zhang	u64 request_id;
767c6fcf0baa6367fecd3e025253700b64ccff8c1ebBill Pemberton	unsigned char *packet;
7688dc0a06ad1f192ea0c8dbe4d2090206c7d880281Greg Kroah-Hartman	struct vmpacket_descriptor *desc;
769c6fcf0baa6367fecd3e025253700b64ccff8c1ebBill Pemberton	unsigned char *buffer;
770c6fcf0baa6367fecd3e025253700b64ccff8c1ebBill Pemberton	int bufferlen = NETVSC_PACKET_SIZE;
7712ddd5e5fb342b9f014d61941a4f73c0bd9b50a60K. Y. Srinivasan	struct net_device *ndev;
772fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
773c6fcf0baa6367fecd3e025253700b64ccff8c1ebBill Pemberton	packet = kzalloc(NETVSC_PACKET_SIZE * sizeof(unsigned char),
774d70c673153d42e8aefd5ac296c8159ef222d076bTimo Teräs			 GFP_ATOMIC);
775c6fcf0baa6367fecd3e025253700b64ccff8c1ebBill Pemberton	if (!packet)
776c6fcf0baa6367fecd3e025253700b64ccff8c1ebBill Pemberton		return;
777c6fcf0baa6367fecd3e025253700b64ccff8c1ebBill Pemberton	buffer = packet;
778c6fcf0baa6367fecd3e025253700b64ccff8c1ebBill Pemberton
7795a71ae303c0f82968d93d86724c1d94d753b34d7Haiyang Zhang	net_device = get_inbound_net_device(device);
7802ddd5e5fb342b9f014d61941a4f73c0bd9b50a60K. Y. Srinivasan	if (!net_device)
781c6fcf0baa6367fecd3e025253700b64ccff8c1ebBill Pemberton		goto out;
7822ddd5e5fb342b9f014d61941a4f73c0bd9b50a60K. Y. Srinivasan	ndev = net_device->ndev;
783fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
78421a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman	do {
7859f630068e8ccba24d728f196cb3ddc120ebee38eGreg Kroah-Hartman		ret = vmbus_recvpacket_raw(device->channel, buffer, bufferlen,
78685799a37553f89b23797ec4f69e45f6c5e9109dfHaiyang Zhang					   &bytes_recvd, &request_id);
78721a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman		if (ret == 0) {
78885799a37553f89b23797ec4f69e45f6c5e9109dfHaiyang Zhang			if (bytes_recvd > 0) {
78921a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman				desc = (struct vmpacket_descriptor *)buffer;
790415f228712d86dd5598f809e8e379ff5ad729652Haiyang Zhang				switch (desc->type) {
791415f228712d86dd5598f809e8e379ff5ad729652Haiyang Zhang				case VM_PKT_COMP:
7925a71ae303c0f82968d93d86724c1d94d753b34d7Haiyang Zhang					netvsc_send_completion(device, desc);
79321a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman					break;
79421a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman
795415f228712d86dd5598f809e8e379ff5ad729652Haiyang Zhang				case VM_PKT_DATA_USING_XFER_PAGES:
7965a71ae303c0f82968d93d86724c1d94d753b34d7Haiyang Zhang					netvsc_receive(device, desc);
79721a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman					break;
79821a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman
79921a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman				default:
800d9871158718778ff060f08cbee0c61eb23041671Haiyang Zhang					netdev_err(ndev,
80121a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman						   "unhandled packet type %d, "
80221a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman						   "tid %llx len %d\n",
803415f228712d86dd5598f809e8e379ff5ad729652Haiyang Zhang						   desc->type, request_id,
80485799a37553f89b23797ec4f69e45f6c5e9109dfHaiyang Zhang						   bytes_recvd);
80521a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman					break;
806fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen				}
807fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
808454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton				/* reset */
809c6fcf0baa6367fecd3e025253700b64ccff8c1ebBill Pemberton				if (bufferlen > NETVSC_PACKET_SIZE) {
8108c69f52ab3d918be9d91c8202e5321421876ea50Greg Kroah-Hartman					kfree(buffer);
811fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen					buffer = packet;
812c6fcf0baa6367fecd3e025253700b64ccff8c1ebBill Pemberton					bufferlen = NETVSC_PACKET_SIZE;
813fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen				}
81421a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman			} else {
815454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton				/* reset */
816c6fcf0baa6367fecd3e025253700b64ccff8c1ebBill Pemberton				if (bufferlen > NETVSC_PACKET_SIZE) {
8178c69f52ab3d918be9d91c8202e5321421876ea50Greg Kroah-Hartman					kfree(buffer);
818fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen					buffer = packet;
819c6fcf0baa6367fecd3e025253700b64ccff8c1ebBill Pemberton					bufferlen = NETVSC_PACKET_SIZE;
820fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen				}
821fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
822fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen				break;
823fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen			}
8243d5cad97c4be2bfc5cb4e52a0972c6e3bf8c278dK. Y. Srinivasan		} else if (ret == -ENOBUFS) {
82521a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman			/* Handle large packet */
82685799a37553f89b23797ec4f69e45f6c5e9109dfHaiyang Zhang			buffer = kmalloc(bytes_recvd, GFP_ATOMIC);
82721a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman			if (buffer == NULL) {
828454f18a963cf6519bf317e74e6b9781ffef8d253Bill Pemberton				/* Try again next time around */
829d9871158718778ff060f08cbee0c61eb23041671Haiyang Zhang				netdev_err(ndev,
83021a8082043aa474107f4ed62fb62651ffad8e2f6Greg Kroah-Hartman					   "unable to allocate buffer of size "
831c909ebbd0dcf19c617408c2cfde56c4bbd4f6cb4Haiyang Zhang					   "(%d)!!\n", bytes_recvd);
832fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen				break;
833fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen			}
834fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
83585799a37553f89b23797ec4f69e45f6c5e9109dfHaiyang Zhang			bufferlen = bytes_recvd;
836fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen		}
837fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen	} while (1);
838fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen
839c6fcf0baa6367fecd3e025253700b64ccff8c1ebBill Pembertonout:
840c6fcf0baa6367fecd3e025253700b64ccff8c1ebBill Pemberton	kfree(buffer);
841fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen	return;
842fceaf24a943d8d50391f409ac7fb888cd1f36f32Hank Janssen}
843af24ce42c51fad4fdc2eb3576b8c0388fd19ed4aHaiyang Zhang
844af24ce42c51fad4fdc2eb3576b8c0388fd19ed4aHaiyang Zhang/*
845b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang * netvsc_device_add - Callback when the device belonging to this
846b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang * driver is added
847b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang */
8487bd23a4d8737777f41cbbe099a027b582b762581K. Y. Srinivasanint netvsc_device_add(struct hv_device *device, void *additional_info)
849b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang{
850b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang	int ret = 0;
851b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang	int i;
852aae23986fd5baaf48c7112612fbff7fb1094ad03K. Y. Srinivasan	int ring_size =
853aae23986fd5baaf48c7112612fbff7fb1094ad03K. Y. Srinivasan	((struct netvsc_device_info *)additional_info)->ring_size;
854b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang	struct netvsc_device *net_device;
855b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang	struct hv_netvsc_packet *packet, *pos;
8562ddd5e5fb342b9f014d61941a4f73c0bd9b50a60K. Y. Srinivasan	struct net_device *ndev;
857b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang
858b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang	net_device = alloc_net_device(device);
859b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang	if (!net_device) {
860ace163a85a9a98e7f91db3a23db3f63689038f1eK. Y. Srinivasan		ret = -ENOMEM;
861b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang		goto cleanup;
862b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang	}
863b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang
8642ddd5e5fb342b9f014d61941a4f73c0bd9b50a60K. Y. Srinivasan	/*
8652ddd5e5fb342b9f014d61941a4f73c0bd9b50a60K. Y. Srinivasan	 * Coming into this function, struct net_device * is
8662ddd5e5fb342b9f014d61941a4f73c0bd9b50a60K. Y. Srinivasan	 * registered as the driver private data.
8672ddd5e5fb342b9f014d61941a4f73c0bd9b50a60K. Y. Srinivasan	 * In alloc_net_device(), we register struct netvsc_device *
8682ddd5e5fb342b9f014d61941a4f73c0bd9b50a60K. Y. Srinivasan	 * as the driver private data and stash away struct net_device *
8692ddd5e5fb342b9f014d61941a4f73c0bd9b50a60K. Y. Srinivasan	 * in struct netvsc_device *.
8702ddd5e5fb342b9f014d61941a4f73c0bd9b50a60K. Y. Srinivasan	 */
8712ddd5e5fb342b9f014d61941a4f73c0bd9b50a60K. Y. Srinivasan	ndev = net_device->ndev;
8722ddd5e5fb342b9f014d61941a4f73c0bd9b50a60K. Y. Srinivasan
873b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang	/* Initialize the NetVSC channel extension */
874b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang	net_device->recv_buf_size = NETVSC_RECEIVE_BUFFER_SIZE;
875b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang	spin_lock_init(&net_device->recv_pkt_list_lock);
876b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang
877b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang	INIT_LIST_HEAD(&net_device->recv_pkt_list);
878b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang
879b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang	for (i = 0; i < NETVSC_RECEIVE_PACKETLIST_COUNT; i++) {
880b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang		packet = kzalloc(sizeof(struct hv_netvsc_packet) +
881b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang				 (NETVSC_RECEIVE_SG_COUNT *
882b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang				  sizeof(struct hv_page_buffer)), GFP_KERNEL);
883b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang		if (!packet)
884b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang			break;
885b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang
886b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang		list_add_tail(&packet->list_ent,
887b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang			      &net_device->recv_pkt_list);
888b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang	}
88935abb21ace3413de6ea8d5c7750cedfd46111f0cK. Y. Srinivasan	init_completion(&net_device->channel_init_wait);
890b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang
891b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang	/* Open the channel */
892aae23986fd5baaf48c7112612fbff7fb1094ad03K. Y. Srinivasan	ret = vmbus_open(device->channel, ring_size * PAGE_SIZE,
893aae23986fd5baaf48c7112612fbff7fb1094ad03K. Y. Srinivasan			 ring_size * PAGE_SIZE, NULL, 0,
894b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang			 netvsc_channel_cb, device);
895b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang
896b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang	if (ret != 0) {
897d9871158718778ff060f08cbee0c61eb23041671Haiyang Zhang		netdev_err(ndev, "unable to open channel: %d\n", ret);
898b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang		goto cleanup;
899b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang	}
900b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang
901b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang	/* Channel is opened */
902c909ebbd0dcf19c617408c2cfde56c4bbd4f6cb4Haiyang Zhang	pr_info("hv_netvsc channel opened successfully\n");
903b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang
904b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang	/* Connect with the NetVsp */
905b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang	ret = netvsc_connect_vsp(device);
906b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang	if (ret != 0) {
907d9871158718778ff060f08cbee0c61eb23041671Haiyang Zhang		netdev_err(ndev,
908c909ebbd0dcf19c617408c2cfde56c4bbd4f6cb4Haiyang Zhang			"unable to connect to NetVSP - %d\n", ret);
909b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang		goto close;
910b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang	}
911b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang
912b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang	return ret;
913b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang
914b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhangclose:
915b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang	/* Now, we can close the channel safely */
916b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang	vmbus_close(device->channel);
917b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang
918b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhangcleanup:
919b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang
920b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang	if (net_device) {
921b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang		list_for_each_entry_safe(packet, pos,
922b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang					 &net_device->recv_pkt_list,
923b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang					 list_ent) {
924b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang			list_del(&packet->list_ent);
925b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang			kfree(packet);
926b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang		}
927b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang
928356c4657193c8a5b3aff84fe8cdf5ddc64742801K. Y. Srinivasan		kfree(net_device);
929b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang	}
930b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang
931b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang	return ret;
932b637e023484d420e8df326b561195f8ba74c1a73Haiyang Zhang}
933