]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blame - drivers/staging/hv/netvsc.c
staging: hv: Convert camel cased variables in netvsc.c to lower cases
[mirror_ubuntu-artful-kernel.git] / drivers / staging / hv / netvsc.c
CommitLineData
fceaf24a 1/*
fceaf24a
HJ
2 * Copyright (c) 2009, Microsoft Corporation.
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms and conditions of the GNU General Public License,
6 * version 2, as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 * more details.
12 *
13 * You should have received a copy of the GNU General Public License along with
14 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
15 * Place - Suite 330, Boston, MA 02111-1307 USA.
16 *
17 * Authors:
d0e94d17 18 * Haiyang Zhang <haiyangz@microsoft.com>
fceaf24a 19 * Hank Janssen <hjanssen@microsoft.com>
fceaf24a 20 */
5654e932 21#include <linux/kernel.h>
0ffa63b0 22#include <linux/mm.h>
b4362c9c 23#include <linux/delay.h>
21a80820 24#include <linux/io.h>
5a0e3ad6 25#include <linux/slab.h>
4983b39a 26#include "osd.h"
645954c5 27#include "logging.h"
af167ae9 28#include "netvsc.h"
043efcc3 29#include "rndis_filter.h"
314bf1d1 30#include "channel.h"
fceaf24a
HJ
31
32
454f18a9 33/* Globals */
85799a37 34static const char *driver_name = "netvsc";
fceaf24a 35
454f18a9 36/* {F8615163-DF3E-46c5-913F-F2D2F965ED0E} */
85799a37 37static const struct hv_guid netvsc_device_type = {
caf26a31
GKH
38 .data = {
39 0x63, 0x51, 0x61, 0xF8, 0x3E, 0xDF, 0xc5, 0x46,
40 0x91, 0x3F, 0xF2, 0xD2, 0xF9, 0x65, 0xED, 0x0E
41 }
fceaf24a
HJ
42};
43
85799a37 44static int NetVscOnDeviceAdd(struct hv_device *device, void *additional_info);
21a80820 45
85799a37 46static int NetVscOnDeviceRemove(struct hv_device *device);
21a80820 47
85799a37 48static void NetVscOnCleanup(struct hv_driver *driver);
21a80820
GKH
49
50static void NetVscOnChannelCallback(void *context);
51
85799a37 52static int NetVscInitializeSendBufferWithNetVsp(struct hv_device *device);
21a80820 53
85799a37 54static int NetVscInitializeReceiveBufferWithNetVsp(struct hv_device *device);
21a80820 55
85799a37 56static int NetVscDestroySendBuffer(struct netvsc_device *net_device);
21a80820 57
85799a37 58static int NetVscDestroyReceiveBuffer(struct netvsc_device *net_device);
21a80820 59
85799a37 60static int NetVscConnectToVsp(struct hv_device *device);
21a80820 61
85799a37
HZ
62static void NetVscOnSendCompletion(struct hv_device *device,
63 struct vmpacket_descriptor *packet);
21a80820 64
85799a37
HZ
65static int NetVscOnSend(struct hv_device *device,
66 struct hv_netvsc_packet *packet);
21a80820 67
85799a37
HZ
68static void NetVscOnReceive(struct hv_device *device,
69 struct vmpacket_descriptor *packet);
21a80820 70
85799a37 71static void NetVscOnReceiveCompletion(void *context);
21a80820 72
85799a37
HZ
73static void NetVscSendReceiveCompletion(struct hv_device *device,
74 u64 transaction_id);
21a80820 75
fceaf24a 76
85799a37 77static struct netvsc_device *AllocNetDevice(struct hv_device *device)
fceaf24a 78{
85799a37 79 struct netvsc_device *net_device;
fceaf24a 80
85799a37
HZ
81 net_device = kzalloc(sizeof(struct netvsc_device), GFP_KERNEL);
82 if (!net_device)
fceaf24a
HJ
83 return NULL;
84
454f18a9 85 /* Set to 2 to allow both inbound and outbound traffic */
85799a37 86 atomic_cmpxchg(&net_device->RefCount, 0, 2);
fceaf24a 87
85799a37
HZ
88 net_device->Device = device;
89 device->Extension = net_device;
fceaf24a 90
85799a37 91 return net_device;
fceaf24a
HJ
92}
93
85799a37 94static void FreeNetDevice(struct netvsc_device *device)
fceaf24a 95{
85799a37
HZ
96 WARN_ON(atomic_read(&device->RefCount) == 0);
97 device->Device->Extension = NULL;
98 kfree(device);
fceaf24a
HJ
99}
100
101
454f18a9 102/* Get the net device object iff exists and its refcount > 1 */
85799a37 103static struct netvsc_device *GetOutboundNetDevice(struct hv_device *device)
fceaf24a 104{
85799a37 105 struct netvsc_device *net_device;
fceaf24a 106
85799a37
HZ
107 net_device = device->Extension;
108 if (net_device && atomic_read(&net_device->RefCount) > 1)
109 atomic_inc(&net_device->RefCount);
fceaf24a 110 else
85799a37 111 net_device = NULL;
fceaf24a 112
85799a37 113 return net_device;
fceaf24a
HJ
114}
115
454f18a9 116/* Get the net device object iff exists and its refcount > 0 */
85799a37 117static struct netvsc_device *GetInboundNetDevice(struct hv_device *device)
fceaf24a 118{
85799a37 119 struct netvsc_device *net_device;
fceaf24a 120
85799a37
HZ
121 net_device = device->Extension;
122 if (net_device && atomic_read(&net_device->RefCount))
123 atomic_inc(&net_device->RefCount);
fceaf24a 124 else
85799a37 125 net_device = NULL;
fceaf24a 126
85799a37 127 return net_device;
fceaf24a
HJ
128}
129
85799a37 130static void PutNetDevice(struct hv_device *device)
fceaf24a 131{
85799a37 132 struct netvsc_device *net_device;
fceaf24a 133
85799a37 134 net_device = device->Extension;
972b9529 135 /* ASSERT(netDevice); */
fceaf24a 136
85799a37 137 atomic_dec(&net_device->RefCount);
fceaf24a
HJ
138}
139
85799a37 140static struct netvsc_device *ReleaseOutboundNetDevice(struct hv_device *device)
fceaf24a 141{
85799a37 142 struct netvsc_device *net_device;
fceaf24a 143
85799a37
HZ
144 net_device = device->Extension;
145 if (net_device == NULL)
fceaf24a
HJ
146 return NULL;
147
454f18a9 148 /* Busy wait until the ref drop to 2, then set it to 1 */
85799a37 149 while (atomic_cmpxchg(&net_device->RefCount, 2, 1) != 2)
b4362c9c 150 udelay(100);
fceaf24a 151
85799a37 152 return net_device;
fceaf24a
HJ
153}
154
85799a37 155static struct netvsc_device *ReleaseInboundNetDevice(struct hv_device *device)
fceaf24a 156{
85799a37 157 struct netvsc_device *net_device;
fceaf24a 158
85799a37
HZ
159 net_device = device->Extension;
160 if (net_device == NULL)
fceaf24a
HJ
161 return NULL;
162
454f18a9 163 /* Busy wait until the ref drop to 1, then set it to 0 */
85799a37 164 while (atomic_cmpxchg(&net_device->RefCount, 1, 0) != 1)
b4362c9c 165 udelay(100);
fceaf24a 166
85799a37
HZ
167 device->Extension = NULL;
168 return net_device;
fceaf24a
HJ
169}
170
3e189519 171/*
21a80820
GKH
172 * NetVscInitialize - Main entry point
173 */
174int NetVscInitialize(struct hv_driver *drv)
fceaf24a 175{
7e23a6e9 176 struct netvsc_driver *driver = (struct netvsc_driver *)drv;
fceaf24a 177
21a80820
GKH
178 DPRINT_DBG(NETVSC, "sizeof(struct hv_netvsc_packet)=%zd, "
179 "sizeof(struct nvsp_message)=%zd, "
180 "sizeof(struct vmtransfer_page_packet_header)=%zd",
181 sizeof(struct hv_netvsc_packet),
182 sizeof(struct nvsp_message),
183 sizeof(struct vmtransfer_page_packet_header));
fceaf24a 184
454f18a9 185 /* Make sure we are at least 2 pages since 1 page is used for control */
972b9529 186 /* ASSERT(driver->RingBufferSize >= (PAGE_SIZE << 1)); */
fceaf24a 187
85799a37
HZ
188 drv->name = driver_name;
189 memcpy(&drv->deviceType, &netvsc_device_type, sizeof(struct hv_guid));
fceaf24a 190
454f18a9 191 /* Make sure it is set by the caller */
972b9529
BP
192 /* FIXME: These probably should still be tested in some way */
193 /* ASSERT(driver->OnReceiveCallback); */
194 /* ASSERT(driver->OnLinkStatusChanged); */
fceaf24a 195
454f18a9 196 /* Setup the dispatch table */
21a80820
GKH
197 driver->Base.OnDeviceAdd = NetVscOnDeviceAdd;
198 driver->Base.OnDeviceRemove = NetVscOnDeviceRemove;
199 driver->Base.OnCleanup = NetVscOnCleanup;
fceaf24a 200
21a80820 201 driver->OnSend = NetVscOnSend;
fceaf24a
HJ
202
203 RndisFilterInit(driver);
21a80820 204 return 0;
fceaf24a
HJ
205}
206
85799a37 207static int NetVscInitializeReceiveBufferWithNetVsp(struct hv_device *device)
fceaf24a 208{
21a80820 209 int ret = 0;
85799a37
HZ
210 struct netvsc_device *net_device;
211 struct nvsp_message *init_packet;
fceaf24a 212
85799a37
HZ
213 net_device = GetOutboundNetDevice(device);
214 if (!net_device) {
21a80820
GKH
215 DPRINT_ERR(NETVSC, "unable to get net device..."
216 "device being destroyed?");
fceaf24a
HJ
217 return -1;
218 }
972b9529 219 /* ASSERT(netDevice->ReceiveBufferSize > 0); */
21a80820 220 /* page-size grandularity */
972b9529 221 /* ASSERT((netDevice->ReceiveBufferSize & (PAGE_SIZE - 1)) == 0); */
fceaf24a 222
85799a37
HZ
223 net_device->ReceiveBuffer =
224 osd_page_alloc(net_device->ReceiveBufferSize >> PAGE_SHIFT);
225 if (!net_device->ReceiveBuffer) {
21a80820
GKH
226 DPRINT_ERR(NETVSC,
227 "unable to allocate receive buffer of size %d",
85799a37 228 net_device->ReceiveBufferSize);
fceaf24a
HJ
229 ret = -1;
230 goto Cleanup;
231 }
21a80820 232 /* page-aligned buffer */
972b9529
BP
233 /* ASSERT(((unsigned long)netDevice->ReceiveBuffer & (PAGE_SIZE - 1)) == */
234 /* 0); */
fceaf24a
HJ
235
236 DPRINT_INFO(NETVSC, "Establishing receive buffer's GPADL...");
237
454f18a9
BP
238 /*
239 * Establish the gpadl handle for this buffer on this
240 * channel. Note: This call uses the vmbus connection rather
241 * than the channel to establish the gpadl handle.
242 */
85799a37
HZ
243 ret = vmbus_establish_gpadl(device->channel, net_device->ReceiveBuffer,
244 net_device->ReceiveBufferSize,
245 &net_device->ReceiveBufferGpadlHandle);
21a80820
GKH
246 if (ret != 0) {
247 DPRINT_ERR(NETVSC,
248 "unable to establish receive buffer's gpadl");
fceaf24a
HJ
249 goto Cleanup;
250 }
251
203df82d 252 /* osd_waitevent_wait(ext->ChannelInitEvent); */
fceaf24a 253
454f18a9 254 /* Notify the NetVsp of the gpadl handle */
fceaf24a
HJ
255 DPRINT_INFO(NETVSC, "Sending NvspMessage1TypeSendReceiveBuffer...");
256
85799a37 257 init_packet = &net_device->ChannelInitPacket;
fceaf24a 258
85799a37 259 memset(init_packet, 0, sizeof(struct nvsp_message));
fceaf24a 260
85799a37
HZ
261 init_packet->Header.MessageType = NvspMessage1TypeSendReceiveBuffer;
262 init_packet->Messages.Version1Messages.SendReceiveBuffer.
263 GpadlHandle = net_device->ReceiveBufferGpadlHandle;
264 init_packet->Messages.Version1Messages.
265 SendReceiveBuffer.Id = NETVSC_RECEIVE_BUFFER_ID;
fceaf24a 266
454f18a9 267 /* Send the gpadl notification request */
85799a37 268 ret = vmbus_sendpacket(device->channel, init_packet,
5a4df290 269 sizeof(struct nvsp_message),
85799a37 270 (unsigned long)init_packet,
5a4df290
GKH
271 VmbusPacketTypeDataInBand,
272 VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
21a80820
GKH
273 if (ret != 0) {
274 DPRINT_ERR(NETVSC,
275 "unable to send receive buffer's gpadl to netvsp");
fceaf24a
HJ
276 goto Cleanup;
277 }
278
85799a37 279 osd_waitevent_wait(net_device->ChannelInitEvent);
fceaf24a 280
454f18a9 281 /* Check the response */
85799a37
HZ
282 if (init_packet->Messages.Version1Messages.
283 SendReceiveBufferComplete.Status != NvspStatusSuccess) {
21a80820
GKH
284 DPRINT_ERR(NETVSC, "Unable to complete receive buffer "
285 "initialzation with NetVsp - status %d",
85799a37
HZ
286 init_packet->Messages.Version1Messages.
287 SendReceiveBufferComplete.Status);
fceaf24a
HJ
288 ret = -1;
289 goto Cleanup;
290 }
291
454f18a9 292 /* Parse the response */
972b9529
BP
293 /* ASSERT(netDevice->ReceiveSectionCount == 0); */
294 /* ASSERT(netDevice->ReceiveSections == NULL); */
fceaf24a 295
85799a37
HZ
296 net_device->ReceiveSectionCount = init_packet->Messages.
297 Version1Messages.SendReceiveBufferComplete.NumSections;
fceaf24a 298
85799a37
HZ
299 net_device->ReceiveSections = kmalloc(net_device->ReceiveSectionCount
300 * sizeof(struct nvsp_1_receive_buffer_section), GFP_KERNEL);
301 if (net_device->ReceiveSections == NULL) {
fceaf24a
HJ
302 ret = -1;
303 goto Cleanup;
304 }
305
85799a37
HZ
306 memcpy(net_device->ReceiveSections,
307 init_packet->Messages.Version1Messages.
308 SendReceiveBufferComplete.Sections,
309 net_device->ReceiveSectionCount *
310 sizeof(struct nvsp_1_receive_buffer_section));
fceaf24a 311
21a80820
GKH
312 DPRINT_INFO(NETVSC, "Receive sections info (count %d, offset %d, "
313 "endoffset %d, suballoc size %d, num suballocs %d)",
85799a37
HZ
314 net_device->ReceiveSectionCount,
315 net_device->ReceiveSections[0].Offset,
316 net_device->ReceiveSections[0].EndOffset,
317 net_device->ReceiveSections[0].SubAllocationSize,
318 net_device->ReceiveSections[0].NumSubAllocations);
fceaf24a 319
21a80820
GKH
320 /*
321 * For 1st release, there should only be 1 section that represents the
322 * entire receive buffer
323 */
85799a37
HZ
324 if (net_device->ReceiveSectionCount != 1 ||
325 net_device->ReceiveSections->Offset != 0) {
fceaf24a
HJ
326 ret = -1;
327 goto Cleanup;
328 }
329
330 goto Exit;
331
332Cleanup:
85799a37 333 NetVscDestroyReceiveBuffer(net_device);
fceaf24a
HJ
334
335Exit:
85799a37 336 PutNetDevice(device);
fceaf24a
HJ
337 return ret;
338}
339
85799a37 340static int NetVscInitializeSendBufferWithNetVsp(struct hv_device *device)
fceaf24a 341{
21a80820 342 int ret = 0;
85799a37
HZ
343 struct netvsc_device *net_device;
344 struct nvsp_message *init_packet;
fceaf24a 345
85799a37
HZ
346 net_device = GetOutboundNetDevice(device);
347 if (!net_device) {
21a80820
GKH
348 DPRINT_ERR(NETVSC, "unable to get net device..."
349 "device being destroyed?");
fceaf24a
HJ
350 return -1;
351 }
85799a37 352 if (net_device->SendBufferSize <= 0) {
79069684
BP
353 ret = -EINVAL;
354 goto Cleanup;
355 }
356
21a80820 357 /* page-size grandularity */
972b9529 358 /* ASSERT((netDevice->SendBufferSize & (PAGE_SIZE - 1)) == 0); */
21a80820 359
85799a37
HZ
360 net_device->SendBuffer =
361 osd_page_alloc(net_device->SendBufferSize >> PAGE_SHIFT);
362 if (!net_device->SendBuffer) {
21a80820 363 DPRINT_ERR(NETVSC, "unable to allocate send buffer of size %d",
85799a37 364 net_device->SendBufferSize);
fceaf24a
HJ
365 ret = -1;
366 goto Cleanup;
367 }
21a80820 368 /* page-aligned buffer */
972b9529 369 /* ASSERT(((unsigned long)netDevice->SendBuffer & (PAGE_SIZE - 1)) == 0); */
fceaf24a
HJ
370
371 DPRINT_INFO(NETVSC, "Establishing send buffer's GPADL...");
372
454f18a9
BP
373 /*
374 * Establish the gpadl handle for this buffer on this
375 * channel. Note: This call uses the vmbus connection rather
376 * than the channel to establish the gpadl handle.
377 */
85799a37
HZ
378 ret = vmbus_establish_gpadl(device->channel, net_device->SendBuffer,
379 net_device->SendBufferSize,
380 &net_device->SendBufferGpadlHandle);
21a80820 381 if (ret != 0) {
fceaf24a
HJ
382 DPRINT_ERR(NETVSC, "unable to establish send buffer's gpadl");
383 goto Cleanup;
384 }
385
203df82d 386 /* osd_waitevent_wait(ext->ChannelInitEvent); */
fceaf24a 387
454f18a9 388 /* Notify the NetVsp of the gpadl handle */
fceaf24a
HJ
389 DPRINT_INFO(NETVSC, "Sending NvspMessage1TypeSendSendBuffer...");
390
85799a37 391 init_packet = &net_device->ChannelInitPacket;
fceaf24a 392
85799a37 393 memset(init_packet, 0, sizeof(struct nvsp_message));
fceaf24a 394
85799a37
HZ
395 init_packet->Header.MessageType = NvspMessage1TypeSendSendBuffer;
396 init_packet->Messages.Version1Messages.SendReceiveBuffer.
397 GpadlHandle = net_device->SendBufferGpadlHandle;
398 init_packet->Messages.Version1Messages.SendReceiveBuffer.Id =
399 NETVSC_SEND_BUFFER_ID;
fceaf24a 400
454f18a9 401 /* Send the gpadl notification request */
85799a37 402 ret = vmbus_sendpacket(device->channel, init_packet,
5a4df290 403 sizeof(struct nvsp_message),
85799a37 404 (unsigned long)init_packet,
5a4df290
GKH
405 VmbusPacketTypeDataInBand,
406 VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
21a80820
GKH
407 if (ret != 0) {
408 DPRINT_ERR(NETVSC,
409 "unable to send receive buffer's gpadl to netvsp");
fceaf24a
HJ
410 goto Cleanup;
411 }
412
85799a37 413 osd_waitevent_wait(net_device->ChannelInitEvent);
fceaf24a 414
454f18a9 415 /* Check the response */
85799a37
HZ
416 if (init_packet->Messages.Version1Messages.
417 SendSendBufferComplete.Status != NvspStatusSuccess) {
21a80820
GKH
418 DPRINT_ERR(NETVSC, "Unable to complete send buffer "
419 "initialzation with NetVsp - status %d",
85799a37
HZ
420 init_packet->Messages.Version1Messages.
421 SendSendBufferComplete.Status);
fceaf24a
HJ
422 ret = -1;
423 goto Cleanup;
424 }
425
85799a37
HZ
426 net_device->SendSectionSize = init_packet->
427 Messages.Version1Messages.SendSendBufferComplete.SectionSize;
fceaf24a
HJ
428
429 goto Exit;
430
431Cleanup:
85799a37 432 NetVscDestroySendBuffer(net_device);
fceaf24a
HJ
433
434Exit:
85799a37 435 PutNetDevice(device);
fceaf24a
HJ
436 return ret;
437}
438
85799a37 439static int NetVscDestroyReceiveBuffer(struct netvsc_device *net_device)
fceaf24a 440{
85799a37 441 struct nvsp_message *revoke_packet;
21a80820 442 int ret = 0;
fceaf24a 443
454f18a9
BP
444 /*
445 * If we got a section count, it means we received a
446 * SendReceiveBufferComplete msg (ie sent
447 * NvspMessage1TypeSendReceiveBuffer msg) therefore, we need
448 * to send a revoke msg here
449 */
85799a37 450 if (net_device->ReceiveSectionCount) {
21a80820
GKH
451 DPRINT_INFO(NETVSC,
452 "Sending NvspMessage1TypeRevokeReceiveBuffer...");
fceaf24a 453
454f18a9 454 /* Send the revoke receive buffer */
85799a37
HZ
455 revoke_packet = &net_device->RevokePacket;
456 memset(revoke_packet, 0, sizeof(struct nvsp_message));
fceaf24a 457
85799a37
HZ
458 revoke_packet->Header.MessageType =
459 NvspMessage1TypeRevokeReceiveBuffer;
460 revoke_packet->Messages.Version1Messages.
461 RevokeReceiveBuffer.Id = NETVSC_RECEIVE_BUFFER_ID;
fceaf24a 462
85799a37
HZ
463 ret = vmbus_sendpacket(net_device->Device->channel,
464 revoke_packet,
5a4df290 465 sizeof(struct nvsp_message),
85799a37 466 (unsigned long)revoke_packet,
5a4df290 467 VmbusPacketTypeDataInBand, 0);
454f18a9
BP
468 /*
469 * If we failed here, we might as well return and
470 * have a leak rather than continue and a bugchk
471 */
21a80820
GKH
472 if (ret != 0) {
473 DPRINT_ERR(NETVSC, "unable to send revoke receive "
474 "buffer to netvsp");
fceaf24a
HJ
475 return -1;
476 }
477 }
478
454f18a9 479 /* Teardown the gpadl on the vsp end */
85799a37 480 if (net_device->ReceiveBufferGpadlHandle) {
fceaf24a
HJ
481 DPRINT_INFO(NETVSC, "Tearing down receive buffer's GPADL...");
482
85799a37
HZ
483 ret = vmbus_teardown_gpadl(net_device->Device->channel,
484 net_device->ReceiveBufferGpadlHandle);
fceaf24a 485
454f18a9 486 /* If we failed here, we might as well return and have a leak rather than continue and a bugchk */
21a80820
GKH
487 if (ret != 0) {
488 DPRINT_ERR(NETVSC,
489 "unable to teardown receive buffer's gpadl");
fceaf24a
HJ
490 return -1;
491 }
85799a37 492 net_device->ReceiveBufferGpadlHandle = 0;
fceaf24a
HJ
493 }
494
85799a37 495 if (net_device->ReceiveBuffer) {
fceaf24a
HJ
496 DPRINT_INFO(NETVSC, "Freeing up receive buffer...");
497
454f18a9 498 /* Free up the receive buffer */
85799a37
HZ
499 osd_page_free(net_device->ReceiveBuffer,
500 net_device->ReceiveBufferSize >> PAGE_SHIFT);
501 net_device->ReceiveBuffer = NULL;
fceaf24a
HJ
502 }
503
85799a37
HZ
504 if (net_device->ReceiveSections) {
505 net_device->ReceiveSectionCount = 0;
506 kfree(net_device->ReceiveSections);
507 net_device->ReceiveSections = NULL;
fceaf24a
HJ
508 }
509
fceaf24a
HJ
510 return ret;
511}
512
85799a37 513static int NetVscDestroySendBuffer(struct netvsc_device *net_device)
fceaf24a 514{
85799a37 515 struct nvsp_message *revoke_packet;
21a80820 516 int ret = 0;
fceaf24a 517
454f18a9
BP
518 /*
519 * If we got a section count, it means we received a
520 * SendReceiveBufferComplete msg (ie sent
521 * NvspMessage1TypeSendReceiveBuffer msg) therefore, we need
522 * to send a revoke msg here
523 */
85799a37 524 if (net_device->SendSectionSize) {
21a80820
GKH
525 DPRINT_INFO(NETVSC,
526 "Sending NvspMessage1TypeRevokeSendBuffer...");
fceaf24a 527
454f18a9 528 /* Send the revoke send buffer */
85799a37
HZ
529 revoke_packet = &net_device->RevokePacket;
530 memset(revoke_packet, 0, sizeof(struct nvsp_message));
fceaf24a 531
85799a37
HZ
532 revoke_packet->Header.MessageType =
533 NvspMessage1TypeRevokeSendBuffer;
534 revoke_packet->Messages.Version1Messages.
535 RevokeSendBuffer.Id = NETVSC_SEND_BUFFER_ID;
fceaf24a 536
85799a37
HZ
537 ret = vmbus_sendpacket(net_device->Device->channel,
538 revoke_packet,
5a4df290 539 sizeof(struct nvsp_message),
85799a37 540 (unsigned long)revoke_packet,
5a4df290 541 VmbusPacketTypeDataInBand, 0);
21a80820
GKH
542 /*
543 * If we failed here, we might as well return and have a leak
544 * rather than continue and a bugchk
545 */
546 if (ret != 0) {
547 DPRINT_ERR(NETVSC, "unable to send revoke send buffer "
548 "to netvsp");
fceaf24a
HJ
549 return -1;
550 }
551 }
552
454f18a9 553 /* Teardown the gpadl on the vsp end */
85799a37 554 if (net_device->SendBufferGpadlHandle) {
fceaf24a 555 DPRINT_INFO(NETVSC, "Tearing down send buffer's GPADL...");
85799a37
HZ
556 ret = vmbus_teardown_gpadl(net_device->Device->channel,
557 net_device->SendBufferGpadlHandle);
fceaf24a 558
21a80820
GKH
559 /*
560 * If we failed here, we might as well return and have a leak
561 * rather than continue and a bugchk
562 */
563 if (ret != 0) {
564 DPRINT_ERR(NETVSC, "unable to teardown send buffer's "
565 "gpadl");
fceaf24a
HJ
566 return -1;
567 }
85799a37 568 net_device->SendBufferGpadlHandle = 0;
fceaf24a
HJ
569 }
570
85799a37 571 if (net_device->SendBuffer) {
fceaf24a
HJ
572 DPRINT_INFO(NETVSC, "Freeing up send buffer...");
573
454f18a9 574 /* Free up the receive buffer */
85799a37
HZ
575 osd_page_free(net_device->SendBuffer,
576 net_device->SendBufferSize >> PAGE_SHIFT);
577 net_device->SendBuffer = NULL;
fceaf24a
HJ
578 }
579
fceaf24a
HJ
580 return ret;
581}
582
583
85799a37 584static int NetVscConnectToVsp(struct hv_device *device)
fceaf24a 585{
21a80820 586 int ret;
85799a37
HZ
587 struct netvsc_device *net_device;
588 struct nvsp_message *init_packet;
589 int ndis_version;
fceaf24a 590
85799a37
HZ
591 net_device = GetOutboundNetDevice(device);
592 if (!net_device) {
21a80820
GKH
593 DPRINT_ERR(NETVSC, "unable to get net device..."
594 "device being destroyed?");
fceaf24a
HJ
595 return -1;
596 }
597
85799a37 598 init_packet = &net_device->ChannelInitPacket;
fceaf24a 599
85799a37
HZ
600 memset(init_packet, 0, sizeof(struct nvsp_message));
601 init_packet->Header.MessageType = NvspMessageTypeInit;
602 init_packet->Messages.InitMessages.Init.MinProtocolVersion =
603 NVSP_MIN_PROTOCOL_VERSION;
604 init_packet->Messages.InitMessages.Init.MaxProtocolVersion =
605 NVSP_MAX_PROTOCOL_VERSION;
fceaf24a
HJ
606
607 DPRINT_INFO(NETVSC, "Sending NvspMessageTypeInit...");
608
454f18a9 609 /* Send the init request */
85799a37 610 ret = vmbus_sendpacket(device->channel, init_packet,
5a4df290 611 sizeof(struct nvsp_message),
85799a37 612 (unsigned long)init_packet,
5a4df290
GKH
613 VmbusPacketTypeDataInBand,
614 VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
21a80820
GKH
615
616 if (ret != 0) {
fceaf24a
HJ
617 DPRINT_ERR(NETVSC, "unable to send NvspMessageTypeInit");
618 goto Cleanup;
619 }
620
85799a37 621 osd_waitevent_wait(net_device->ChannelInitEvent);
fceaf24a 622
454f18a9
BP
623 /* Now, check the response */
624 /* ASSERT(initPacket->Messages.InitMessages.InitComplete.MaximumMdlChainLength <= MAX_MULTIPAGE_BUFFER_COUNT); */
fceaf24a 625 DPRINT_INFO(NETVSC, "NvspMessageTypeInit status(%d) max mdl chain (%d)",
85799a37
HZ
626 init_packet->Messages.InitMessages.InitComplete.Status,
627 init_packet->Messages.InitMessages.
628 InitComplete.MaximumMdlChainLength);
fceaf24a 629
85799a37 630 if (init_packet->Messages.InitMessages.InitComplete.Status !=
21a80820
GKH
631 NvspStatusSuccess) {
632 DPRINT_ERR(NETVSC,
633 "unable to initialize with netvsp (status 0x%x)",
85799a37 634 init_packet->Messages.InitMessages.InitComplete.Status);
fceaf24a
HJ
635 ret = -1;
636 goto Cleanup;
637 }
638
85799a37
HZ
639 if (init_packet->Messages.InitMessages.InitComplete.
640 NegotiatedProtocolVersion != NVSP_PROTOCOL_VERSION_1) {
21a80820
GKH
641 DPRINT_ERR(NETVSC, "unable to initialize with netvsp "
642 "(version expected 1 got %d)",
85799a37
HZ
643 init_packet->Messages.InitMessages.
644 InitComplete.NegotiatedProtocolVersion);
fceaf24a
HJ
645 ret = -1;
646 goto Cleanup;
647 }
648 DPRINT_INFO(NETVSC, "Sending NvspMessage1TypeSendNdisVersion...");
649
454f18a9 650 /* Send the ndis version */
85799a37 651 memset(init_packet, 0, sizeof(struct nvsp_message));
fceaf24a 652
85799a37 653 ndis_version = 0x00050000;
fceaf24a 654
85799a37
HZ
655 init_packet->Header.MessageType = NvspMessage1TypeSendNdisVersion;
656 init_packet->Messages.Version1Messages.
657 SendNdisVersion.NdisMajorVersion =
658 (ndis_version & 0xFFFF0000) >> 16;
659 init_packet->Messages.Version1Messages.
660 SendNdisVersion.NdisMinorVersion =
661 ndis_version & 0xFFFF;
fceaf24a 662
454f18a9 663 /* Send the init request */
85799a37 664 ret = vmbus_sendpacket(device->channel, init_packet,
5a4df290 665 sizeof(struct nvsp_message),
85799a37 666 (unsigned long)init_packet,
5a4df290 667 VmbusPacketTypeDataInBand, 0);
21a80820
GKH
668 if (ret != 0) {
669 DPRINT_ERR(NETVSC,
670 "unable to send NvspMessage1TypeSendNdisVersion");
fceaf24a
HJ
671 ret = -1;
672 goto Cleanup;
673 }
454f18a9
BP
674 /*
675 * BUGBUG - We have to wait for the above msg since the
676 * netvsp uses KMCL which acknowledges packet (completion
677 * packet) since our Vmbus always set the
678 * VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED flag
679 */
203df82d 680 /* osd_waitevent_wait(NetVscChannel->ChannelInitEvent); */
454f18a9
BP
681
682 /* Post the big receive buffer to NetVSP */
85799a37 683 ret = NetVscInitializeReceiveBufferWithNetVsp(device);
fceaf24a 684 if (ret == 0)
85799a37 685 ret = NetVscInitializeSendBufferWithNetVsp(device);
fceaf24a
HJ
686
687Cleanup:
85799a37 688 PutNetDevice(device);
fceaf24a
HJ
689 return ret;
690}
691
85799a37 692static void NetVscDisconnectFromVsp(struct netvsc_device *net_device)
fceaf24a 693{
85799a37
HZ
694 NetVscDestroyReceiveBuffer(net_device);
695 NetVscDestroySendBuffer(net_device);
fceaf24a
HJ
696}
697
3e189519 698/*
21a80820
GKH
699 * NetVscOnDeviceAdd - Callback when the device belonging to this driver is added
700 */
85799a37 701static int NetVscOnDeviceAdd(struct hv_device *device, void *additional_info)
fceaf24a 702{
21a80820 703 int ret = 0;
fceaf24a 704 int i;
85799a37 705 struct netvsc_device *net_device;
d29274ef 706 struct hv_netvsc_packet *packet, *pos;
85799a37
HZ
707 struct netvsc_driver *net_driver =
708 (struct netvsc_driver *)device->Driver;
fceaf24a 709
85799a37
HZ
710 net_device = AllocNetDevice(device);
711 if (!net_device) {
fceaf24a
HJ
712 ret = -1;
713 goto Cleanup;
714 }
715
85799a37 716 DPRINT_DBG(NETVSC, "netvsc channel object allocated - %p", net_device);
fceaf24a 717
454f18a9 718 /* Initialize the NetVSC channel extension */
85799a37
HZ
719 net_device->ReceiveBufferSize = NETVSC_RECEIVE_BUFFER_SIZE;
720 spin_lock_init(&net_device->receive_packet_list_lock);
fceaf24a 721
85799a37 722 net_device->SendBufferSize = NETVSC_SEND_BUFFER_SIZE;
fceaf24a 723
85799a37 724 INIT_LIST_HEAD(&net_device->ReceivePacketList);
fceaf24a 725
21a80820
GKH
726 for (i = 0; i < NETVSC_RECEIVE_PACKETLIST_COUNT; i++) {
727 packet = kzalloc(sizeof(struct hv_netvsc_packet) +
728 (NETVSC_RECEIVE_SG_COUNT *
729 sizeof(struct hv_page_buffer)), GFP_KERNEL);
730 if (!packet) {
731 DPRINT_DBG(NETVSC, "unable to allocate netvsc pkts "
732 "for receive pool (wanted %d got %d)",
733 NETVSC_RECEIVE_PACKETLIST_COUNT, i);
fceaf24a
HJ
734 break;
735 }
d29274ef 736 list_add_tail(&packet->ListEntry,
85799a37 737 &net_device->ReceivePacketList);
fceaf24a 738 }
85799a37
HZ
739 net_device->ChannelInitEvent = osd_waitevent_create();
740 if (!net_device->ChannelInitEvent) {
80d11b2a
BP
741 ret = -ENOMEM;
742 goto Cleanup;
743 }
fceaf24a 744
454f18a9 745 /* Open the channel */
85799a37
HZ
746 ret = vmbus_open(device->channel, net_driver->RingBufferSize,
747 net_driver->RingBufferSize, NULL, 0,
748 NetVscOnChannelCallback, device);
fceaf24a 749
21a80820 750 if (ret != 0) {
fceaf24a
HJ
751 DPRINT_ERR(NETVSC, "unable to open channel: %d", ret);
752 ret = -1;
753 goto Cleanup;
754 }
755
454f18a9 756 /* Channel is opened */
fceaf24a
HJ
757 DPRINT_INFO(NETVSC, "*** NetVSC channel opened successfully! ***");
758
454f18a9 759 /* Connect with the NetVsp */
85799a37 760 ret = NetVscConnectToVsp(device);
21a80820 761 if (ret != 0) {
fceaf24a
HJ
762 DPRINT_ERR(NETVSC, "unable to connect to NetVSP - %d", ret);
763 ret = -1;
1fb9dff0 764 goto close;
fceaf24a
HJ
765 }
766
21a80820
GKH
767 DPRINT_INFO(NETVSC, "*** NetVSC channel handshake result - %d ***",
768 ret);
fceaf24a 769
fceaf24a
HJ
770 return ret;
771
1fb9dff0 772close:
454f18a9 773 /* Now, we can close the channel safely */
85799a37 774 vmbus_close(device->channel);
fceaf24a
HJ
775
776Cleanup:
777
85799a37
HZ
778 if (net_device) {
779 kfree(net_device->ChannelInitEvent);
fceaf24a 780
d29274ef 781 list_for_each_entry_safe(packet, pos,
85799a37 782 &net_device->ReceivePacketList,
d29274ef
BP
783 ListEntry) {
784 list_del(&packet->ListEntry);
8c69f52a 785 kfree(packet);
fceaf24a
HJ
786 }
787
85799a37
HZ
788 ReleaseOutboundNetDevice(device);
789 ReleaseInboundNetDevice(device);
fceaf24a 790
85799a37 791 FreeNetDevice(net_device);
fceaf24a
HJ
792 }
793
fceaf24a
HJ
794 return ret;
795}
796
3e189519 797/*
21a80820
GKH
798 * NetVscOnDeviceRemove - Callback when the root bus device is removed
799 */
85799a37 800static int NetVscOnDeviceRemove(struct hv_device *device)
fceaf24a 801{
85799a37
HZ
802 struct netvsc_device *net_device;
803 struct hv_netvsc_packet *netvsc_packet, *pos;
fceaf24a 804
21a80820 805 DPRINT_INFO(NETVSC, "Disabling outbound traffic on net device (%p)...",
85799a37 806 device->Extension);
fceaf24a 807
454f18a9 808 /* Stop outbound traffic ie sends and receives completions */
85799a37
HZ
809 net_device = ReleaseOutboundNetDevice(device);
810 if (!net_device) {
fceaf24a
HJ
811 DPRINT_ERR(NETVSC, "No net device present!!");
812 return -1;
813 }
814
454f18a9 815 /* Wait for all send completions */
85799a37 816 while (atomic_read(&net_device->NumOutstandingSends)) {
21a80820 817 DPRINT_INFO(NETVSC, "waiting for %d requests to complete...",
85799a37 818 atomic_read(&net_device->NumOutstandingSends));
b4362c9c 819 udelay(100);
fceaf24a
HJ
820 }
821
822 DPRINT_INFO(NETVSC, "Disconnecting from netvsp...");
823
85799a37 824 NetVscDisconnectFromVsp(net_device);
fceaf24a 825
21a80820 826 DPRINT_INFO(NETVSC, "Disabling inbound traffic on net device (%p)...",
85799a37 827 device->Extension);
fceaf24a 828
454f18a9 829 /* Stop inbound traffic ie receives and sends completions */
85799a37 830 net_device = ReleaseInboundNetDevice(device);
fceaf24a 831
454f18a9 832 /* At this point, no one should be accessing netDevice except in here */
85799a37 833 DPRINT_INFO(NETVSC, "net device (%p) safe to remove", net_device);
fceaf24a 834
454f18a9 835 /* Now, we can close the channel safely */
85799a37 836 vmbus_close(device->channel);
fceaf24a 837
454f18a9 838 /* Release all resources */
85799a37
HZ
839 list_for_each_entry_safe(netvsc_packet, pos,
840 &net_device->ReceivePacketList, ListEntry) {
841 list_del(&netvsc_packet->ListEntry);
842 kfree(netvsc_packet);
fceaf24a
HJ
843 }
844
85799a37
HZ
845 kfree(net_device->ChannelInitEvent);
846 FreeNetDevice(net_device);
21a80820 847 return 0;
fceaf24a
HJ
848}
849
3e189519 850/*
21a80820
GKH
851 * NetVscOnCleanup - Perform any cleanup when the driver is removed
852 */
853static void NetVscOnCleanup(struct hv_driver *drv)
fceaf24a 854{
fceaf24a
HJ
855}
856
85799a37
HZ
857static void NetVscOnSendCompletion(struct hv_device *device,
858 struct vmpacket_descriptor *packet)
fceaf24a 859{
85799a37
HZ
860 struct netvsc_device *net_device;
861 struct nvsp_message *nvsp_packet;
862 struct hv_netvsc_packet *nvsc_packet;
fceaf24a 863
85799a37
HZ
864 net_device = GetInboundNetDevice(device);
865 if (!net_device) {
21a80820
GKH
866 DPRINT_ERR(NETVSC, "unable to get net device..."
867 "device being destroyed?");
fceaf24a
HJ
868 return;
869 }
870
85799a37
HZ
871 nvsp_packet = (struct nvsp_message *)((unsigned long)packet +
872 (packet->DataOffset8 << 3));
fceaf24a 873
21a80820 874 DPRINT_DBG(NETVSC, "send completion packet - type %d",
85799a37 875 nvsp_packet->Header.MessageType);
fceaf24a 876
85799a37
HZ
877 if ((nvsp_packet->Header.MessageType == NvspMessageTypeInitComplete) ||
878 (nvsp_packet->Header.MessageType ==
21a80820 879 NvspMessage1TypeSendReceiveBufferComplete) ||
85799a37 880 (nvsp_packet->Header.MessageType ==
21a80820 881 NvspMessage1TypeSendSendBufferComplete)) {
454f18a9 882 /* Copy the response back */
85799a37 883 memcpy(&net_device->ChannelInitPacket, nvsp_packet,
21a80820 884 sizeof(struct nvsp_message));
85799a37
HZ
885 osd_waitevent_set(net_device->ChannelInitEvent);
886 } else if (nvsp_packet->Header.MessageType ==
21a80820 887 NvspMessage1TypeSendRNDISPacketComplete) {
454f18a9 888 /* Get the send context */
85799a37
HZ
889 nvsc_packet = (struct hv_netvsc_packet *)(unsigned long)
890 packet->TransactionId;
972b9529 891 /* ASSERT(nvscPacket); */
fceaf24a 892
454f18a9 893 /* Notify the layer above us */
85799a37
HZ
894 nvsc_packet->Completion.Send.OnSendCompletion(
895 nvsc_packet->Completion.Send.SendCompletionContext);
fceaf24a 896
85799a37 897 atomic_dec(&net_device->NumOutstandingSends);
21a80820
GKH
898 } else {
899 DPRINT_ERR(NETVSC, "Unknown send completion packet type - "
85799a37 900 "%d received!!", nvsp_packet->Header.MessageType);
fceaf24a
HJ
901 }
902
85799a37 903 PutNetDevice(device);
fceaf24a
HJ
904}
905
85799a37
HZ
906static int NetVscOnSend(struct hv_device *device,
907 struct hv_netvsc_packet *packet)
fceaf24a 908{
85799a37 909 struct netvsc_device *net_device;
21a80820 910 int ret = 0;
fceaf24a 911
223c1aa6 912 struct nvsp_message sendMessage;
fceaf24a 913
85799a37
HZ
914 net_device = GetOutboundNetDevice(device);
915 if (!net_device) {
21a80820 916 DPRINT_ERR(NETVSC, "net device (%p) shutting down..."
85799a37 917 "ignoring outbound packets", net_device);
fceaf24a
HJ
918 return -2;
919 }
920
921 sendMessage.Header.MessageType = NvspMessage1TypeSendRNDISPacket;
85799a37 922 if (packet->IsDataPacket) {
21a80820
GKH
923 /* 0 is RMC_DATA; */
924 sendMessage.Messages.Version1Messages.SendRNDISPacket.ChannelType = 0;
925 } else {
926 /* 1 is RMC_CONTROL; */
927 sendMessage.Messages.Version1Messages.SendRNDISPacket.ChannelType = 1;
928 }
fceaf24a 929
454f18a9 930 /* Not using send buffer section */
21a80820
GKH
931 sendMessage.Messages.Version1Messages.SendRNDISPacket.SendBufferSectionIndex = 0xFFFFFFFF;
932 sendMessage.Messages.Version1Messages.SendRNDISPacket.SendBufferSectionSize = 0;
933
85799a37
HZ
934 if (packet->PageBufferCount) {
935 ret = vmbus_sendpacket_pagebuffer(device->channel,
936 packet->PageBuffers,
937 packet->PageBufferCount,
ff3f8eec
GKH
938 &sendMessage,
939 sizeof(struct nvsp_message),
85799a37 940 (unsigned long)packet);
21a80820 941 } else {
85799a37 942 ret = vmbus_sendpacket(device->channel, &sendMessage,
5a4df290 943 sizeof(struct nvsp_message),
85799a37 944 (unsigned long)packet,
5a4df290
GKH
945 VmbusPacketTypeDataInBand,
946 VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
fceaf24a
HJ
947
948 }
949
950 if (ret != 0)
21a80820 951 DPRINT_ERR(NETVSC, "Unable to send packet %p ret %d",
85799a37 952 packet, ret);
fceaf24a 953
85799a37
HZ
954 atomic_inc(&net_device->NumOutstandingSends);
955 PutNetDevice(device);
fceaf24a
HJ
956 return ret;
957}
958
85799a37
HZ
959static void NetVscOnReceive(struct hv_device *device,
960 struct vmpacket_descriptor *packet)
fceaf24a 961{
85799a37
HZ
962 struct netvsc_device *net_device;
963 struct vmtransfer_page_packet_header *vmxferpage_packet;
964 struct nvsp_message *nvsp_packet;
965 struct hv_netvsc_packet *netvsc_packet = NULL;
c4b0bc94 966 unsigned long start;
85799a37 967 unsigned long end, end_virtual;
7e23a6e9 968 /* struct netvsc_driver *netvscDriver; */
85799a37 969 struct xferpage_packet *xferpage_packet = NULL;
21a80820 970 int i, j;
85799a37 971 int count = 0, bytes_remain = 0;
6436873a 972 unsigned long flags;
d29274ef 973 LIST_HEAD(listHead);
fceaf24a 974
85799a37
HZ
975 net_device = GetInboundNetDevice(device);
976 if (!net_device) {
21a80820
GKH
977 DPRINT_ERR(NETVSC, "unable to get net device..."
978 "device being destroyed?");
fceaf24a
HJ
979 return;
980 }
981
21a80820
GKH
982 /*
983 * All inbound packets other than send completion should be xfer page
984 * packet
985 */
85799a37 986 if (packet->Type != VmbusPacketTypeDataUsingTransferPages) {
21a80820 987 DPRINT_ERR(NETVSC, "Unknown packet type received - %d",
85799a37
HZ
988 packet->Type);
989 PutNetDevice(device);
fceaf24a
HJ
990 return;
991 }
992
85799a37
HZ
993 nvsp_packet = (struct nvsp_message *)((unsigned long)packet +
994 (packet->DataOffset8 << 3));
fceaf24a 995
454f18a9 996 /* Make sure this is a valid nvsp packet */
85799a37
HZ
997 if (nvsp_packet->Header.MessageType !=
998 NvspMessage1TypeSendRNDISPacket) {
21a80820 999 DPRINT_ERR(NETVSC, "Unknown nvsp packet type received - %d",
85799a37
HZ
1000 nvsp_packet->Header.MessageType);
1001 PutNetDevice(device);
fceaf24a
HJ
1002 return;
1003 }
1004
21a80820 1005 DPRINT_DBG(NETVSC, "NVSP packet received - type %d",
85799a37 1006 nvsp_packet->Header.MessageType);
fceaf24a 1007
85799a37 1008 vmxferpage_packet = (struct vmtransfer_page_packet_header *)packet;
fceaf24a 1009
85799a37 1010 if (vmxferpage_packet->TransferPageSetId != NETVSC_RECEIVE_BUFFER_ID) {
21a80820
GKH
1011 DPRINT_ERR(NETVSC, "Invalid xfer page set id - "
1012 "expecting %x got %x", NETVSC_RECEIVE_BUFFER_ID,
85799a37
HZ
1013 vmxferpage_packet->TransferPageSetId);
1014 PutNetDevice(device);
fceaf24a
HJ
1015 return;
1016 }
1017
21a80820 1018 DPRINT_DBG(NETVSC, "xfer page - range count %d",
85799a37 1019 vmxferpage_packet->RangeCount);
fceaf24a 1020
454f18a9
BP
1021 /*
1022 * Grab free packets (range count + 1) to represent this xfer
1023 * page packet. +1 to represent the xfer page packet itself.
1024 * We grab it here so that we know exactly how many we can
1025 * fulfil
1026 */
85799a37
HZ
1027 spin_lock_irqsave(&net_device->receive_packet_list_lock, flags);
1028 while (!list_empty(&net_device->ReceivePacketList)) {
1029 list_move_tail(net_device->ReceivePacketList.next, &listHead);
1030 if (++count == vmxferpage_packet->RangeCount + 1)
fceaf24a
HJ
1031 break;
1032 }
85799a37 1033 spin_unlock_irqrestore(&net_device->receive_packet_list_lock, flags);
fceaf24a 1034
454f18a9
BP
1035 /*
1036 * We need at least 2 netvsc pkts (1 to represent the xfer
1037 * page and at least 1 for the range) i.e. we can handled
1038 * some of the xfer page packet ranges...
1039 */
21a80820
GKH
1040 if (count < 2) {
1041 DPRINT_ERR(NETVSC, "Got only %d netvsc pkt...needed %d pkts. "
1042 "Dropping this xfer page packet completely!",
85799a37 1043 count, vmxferpage_packet->RangeCount + 1);
fceaf24a 1044
454f18a9 1045 /* Return it to the freelist */
85799a37 1046 spin_lock_irqsave(&net_device->receive_packet_list_lock, flags);
21a80820 1047 for (i = count; i != 0; i--) {
92ec0893 1048 list_move_tail(listHead.next,
85799a37 1049 &net_device->ReceivePacketList);
fceaf24a 1050 }
85799a37 1051 spin_unlock_irqrestore(&net_device->receive_packet_list_lock,
21a80820 1052 flags);
fceaf24a 1053
85799a37
HZ
1054 NetVscSendReceiveCompletion(device,
1055 vmxferpage_packet->d.TransactionId);
fceaf24a 1056
85799a37 1057 PutNetDevice(device);
fceaf24a
HJ
1058 return;
1059 }
1060
454f18a9 1061 /* Remove the 1st packet to represent the xfer page packet itself */
85799a37
HZ
1062 xferpage_packet = (struct xferpage_packet *)listHead.next;
1063 list_del(&xferpage_packet->ListEntry);
d29274ef 1064
21a80820 1065 /* This is how much we can satisfy */
85799a37 1066 xferpage_packet->Count = count - 1;
972b9529
BP
1067 /* ASSERT(xferpagePacket->Count > 0 && xferpagePacket->Count <= */
1068 /* vmxferpagePacket->RangeCount); */
21a80820 1069
85799a37 1070 if (xferpage_packet->Count != vmxferpage_packet->RangeCount) {
21a80820 1071 DPRINT_INFO(NETVSC, "Needed %d netvsc pkts to satisy this xfer "
85799a37
HZ
1072 "page...got %d", vmxferpage_packet->RangeCount,
1073 xferpage_packet->Count);
fceaf24a
HJ
1074 }
1075
454f18a9 1076 /* Each range represents 1 RNDIS pkt that contains 1 ethernet frame */
21a80820 1077 for (i = 0; i < (count - 1); i++) {
85799a37
HZ
1078 netvsc_packet = (struct hv_netvsc_packet *)listHead.next;
1079 list_del(&netvsc_packet->ListEntry);
fceaf24a 1080
454f18a9 1081 /* Initialize the netvsc packet */
85799a37
HZ
1082 netvsc_packet->XferPagePacket = xferpage_packet;
1083 netvsc_packet->Completion.Recv.OnReceiveCompletion =
21a80820 1084 NetVscOnReceiveCompletion;
85799a37
HZ
1085 netvsc_packet->Completion.Recv.ReceiveCompletionContext =
1086 netvsc_packet;
1087 netvsc_packet->Device = device;
21a80820 1088 /* Save this so that we can send it back */
85799a37
HZ
1089 netvsc_packet->Completion.Recv.ReceiveCompletionTid =
1090 vmxferpage_packet->d.TransactionId;
fceaf24a 1091
85799a37
HZ
1092 netvsc_packet->TotalDataBufferLength =
1093 vmxferpage_packet->Ranges[i].ByteCount;
1094 netvsc_packet->PageBufferCount = 1;
fceaf24a 1095
972b9529
BP
1096 /* ASSERT(vmxferpagePacket->Ranges[i].ByteOffset + */
1097 /* vmxferpagePacket->Ranges[i].ByteCount < */
1098 /* netDevice->ReceiveBufferSize); */
fceaf24a 1099
85799a37
HZ
1100 netvsc_packet->PageBuffers[0].Length =
1101 vmxferpage_packet->Ranges[i].ByteCount;
fceaf24a 1102
85799a37
HZ
1103 start = virt_to_phys((void *)((unsigned long)net_device->
1104 ReceiveBuffer + vmxferpage_packet->Ranges[i].ByteOffset));
fceaf24a 1105
85799a37
HZ
1106 netvsc_packet->PageBuffers[0].Pfn = start >> PAGE_SHIFT;
1107 end_virtual = (unsigned long)net_device->ReceiveBuffer
1108 + vmxferpage_packet->Ranges[i].ByteOffset
1109 + vmxferpage_packet->Ranges[i].ByteCount - 1;
1110 end = virt_to_phys((void *)end_virtual);
fceaf24a 1111
454f18a9 1112 /* Calculate the page relative offset */
85799a37
HZ
1113 netvsc_packet->PageBuffers[0].Offset =
1114 vmxferpage_packet->Ranges[i].ByteOffset &
1115 (PAGE_SIZE - 1);
21a80820
GKH
1116 if ((end >> PAGE_SHIFT) != (start >> PAGE_SHIFT)) {
1117 /* Handle frame across multiple pages: */
85799a37
HZ
1118 netvsc_packet->PageBuffers[0].Length =
1119 (netvsc_packet->PageBuffers[0].Pfn <<
1120 PAGE_SHIFT)
21a80820 1121 + PAGE_SIZE - start;
85799a37
HZ
1122 bytes_remain = netvsc_packet->TotalDataBufferLength -
1123 netvsc_packet->PageBuffers[0].Length;
21a80820 1124 for (j = 1; j < NETVSC_PACKET_MAXPAGE; j++) {
85799a37
HZ
1125 netvsc_packet->PageBuffers[j].Offset = 0;
1126 if (bytes_remain <= PAGE_SIZE) {
1127 netvsc_packet->PageBuffers[j].Length =
1128 bytes_remain;
1129 bytes_remain = 0;
21a80820 1130 } else {
85799a37
HZ
1131 netvsc_packet->PageBuffers[j].Length =
1132 PAGE_SIZE;
1133 bytes_remain -= PAGE_SIZE;
21a80820 1134 }
85799a37
HZ
1135 netvsc_packet->PageBuffers[j].Pfn =
1136 virt_to_phys((void *)(end_virtual -
1137 bytes_remain)) >> PAGE_SHIFT;
1138 netvsc_packet->PageBufferCount++;
1139 if (bytes_remain == 0)
21a80820 1140 break;
fceaf24a 1141 }
972b9529 1142 /* ASSERT(bytesRemain == 0); */
fceaf24a 1143 }
21a80820
GKH
1144 DPRINT_DBG(NETVSC, "[%d] - (abs offset %u len %u) => "
1145 "(pfn %llx, offset %u, len %u)", i,
85799a37
HZ
1146 vmxferpage_packet->Ranges[i].ByteOffset,
1147 vmxferpage_packet->Ranges[i].ByteCount,
1148 netvsc_packet->PageBuffers[0].Pfn,
1149 netvsc_packet->PageBuffers[0].Offset,
1150 netvsc_packet->PageBuffers[0].Length);
fceaf24a 1151
454f18a9 1152 /* Pass it to the upper layer */
85799a37
HZ
1153 ((struct netvsc_driver *)device->Driver)->
1154 OnReceiveCallback(device, netvsc_packet);
fceaf24a 1155
85799a37
HZ
1156 NetVscOnReceiveCompletion(netvsc_packet->
1157 Completion.Recv.ReceiveCompletionContext);
fceaf24a
HJ
1158 }
1159
972b9529 1160 /* ASSERT(list_empty(&listHead)); */
fceaf24a 1161
85799a37 1162 PutNetDevice(device);
fceaf24a
HJ
1163}
1164
85799a37
HZ
1165static void NetVscSendReceiveCompletion(struct hv_device *device,
1166 u64 transaction_id)
fceaf24a 1167{
223c1aa6 1168 struct nvsp_message recvcompMessage;
21a80820
GKH
1169 int retries = 0;
1170 int ret;
fceaf24a 1171
21a80820 1172 DPRINT_DBG(NETVSC, "Sending receive completion pkt - %llx",
85799a37 1173 transaction_id);
fceaf24a 1174
21a80820
GKH
1175 recvcompMessage.Header.MessageType =
1176 NvspMessage1TypeSendRNDISPacketComplete;
fceaf24a 1177
454f18a9 1178 /* FIXME: Pass in the status */
fceaf24a
HJ
1179 recvcompMessage.Messages.Version1Messages.SendRNDISPacketComplete.Status = NvspStatusSuccess;
1180
1181retry_send_cmplt:
454f18a9 1182 /* Send the completion */
85799a37
HZ
1183 ret = vmbus_sendpacket(device->channel, &recvcompMessage,
1184 sizeof(struct nvsp_message), transaction_id,
5a4df290 1185 VmbusPacketTypeCompletion, 0);
21a80820
GKH
1186 if (ret == 0) {
1187 /* success */
454f18a9 1188 /* no-op */
21a80820
GKH
1189 } else if (ret == -1) {
1190 /* no more room...wait a bit and attempt to retry 3 times */
fceaf24a 1191 retries++;
21a80820 1192 DPRINT_ERR(NETVSC, "unable to send receive completion pkt "
85799a37 1193 "(tid %llx)...retrying %d", transaction_id, retries);
fceaf24a 1194
21a80820 1195 if (retries < 4) {
b4362c9c 1196 udelay(100);
fceaf24a 1197 goto retry_send_cmplt;
21a80820
GKH
1198 } else {
1199 DPRINT_ERR(NETVSC, "unable to send receive completion "
1200 "pkt (tid %llx)...give up retrying",
85799a37 1201 transaction_id);
fceaf24a 1202 }
21a80820
GKH
1203 } else {
1204 DPRINT_ERR(NETVSC, "unable to send receive completion pkt - "
85799a37 1205 "%llx", transaction_id);
fceaf24a
HJ
1206 }
1207}
1208
454f18a9 1209/* Send a receive completion packet to RNDIS device (ie NetVsp) */
85799a37 1210static void NetVscOnReceiveCompletion(void *context)
fceaf24a 1211{
85799a37 1212 struct hv_netvsc_packet *packet = context;
21a80820 1213 struct hv_device *device = (struct hv_device *)packet->Device;
85799a37
HZ
1214 struct netvsc_device *net_device;
1215 u64 transaction_id = 0;
1216 bool fsend_receive_comp = false;
6436873a 1217 unsigned long flags;
fceaf24a 1218
972b9529 1219 /* ASSERT(packet->XferPagePacket); */
fceaf24a 1220
21a80820
GKH
1221 /*
1222 * Even though it seems logical to do a GetOutboundNetDevice() here to
1223 * send out receive completion, we are using GetInboundNetDevice()
1224 * since we may have disable outbound traffic already.
1225 */
85799a37
HZ
1226 net_device = GetInboundNetDevice(device);
1227 if (!net_device) {
21a80820
GKH
1228 DPRINT_ERR(NETVSC, "unable to get net device..."
1229 "device being destroyed?");
fceaf24a
HJ
1230 return;
1231 }
1232
454f18a9 1233 /* Overloading use of the lock. */
85799a37 1234 spin_lock_irqsave(&net_device->receive_packet_list_lock, flags);
fceaf24a 1235
972b9529 1236 /* ASSERT(packet->XferPagePacket->Count > 0); */
fceaf24a
HJ
1237 packet->XferPagePacket->Count--;
1238
21a80820
GKH
1239 /*
1240 * Last one in the line that represent 1 xfer page packet.
1241 * Return the xfer page packet itself to the freelist
1242 */
1243 if (packet->XferPagePacket->Count == 0) {
85799a37
HZ
1244 fsend_receive_comp = true;
1245 transaction_id = packet->Completion.Recv.ReceiveCompletionTid;
d29274ef 1246 list_add_tail(&packet->XferPagePacket->ListEntry,
85799a37 1247 &net_device->ReceivePacketList);
fceaf24a 1248
fceaf24a
HJ
1249 }
1250
454f18a9 1251 /* Put the packet back */
85799a37
HZ
1252 list_add_tail(&packet->ListEntry, &net_device->ReceivePacketList);
1253 spin_unlock_irqrestore(&net_device->receive_packet_list_lock, flags);
fceaf24a 1254
454f18a9 1255 /* Send a receive completion for the xfer page packet */
85799a37
HZ
1256 if (fsend_receive_comp)
1257 NetVscSendReceiveCompletion(device, transaction_id);
fceaf24a
HJ
1258
1259 PutNetDevice(device);
fceaf24a
HJ
1260}
1261
85799a37 1262static void NetVscOnChannelCallback(void *context)
fceaf24a 1263{
21a80820 1264 int ret;
85799a37
HZ
1265 struct hv_device *device = context;
1266 struct netvsc_device *net_device;
1267 u32 bytes_recvd;
1268 u64 request_id;
c6fcf0ba 1269 unsigned char *packet;
8dc0a06a 1270 struct vmpacket_descriptor *desc;
c6fcf0ba
BP
1271 unsigned char *buffer;
1272 int bufferlen = NETVSC_PACKET_SIZE;
fceaf24a 1273
972b9529 1274 /* ASSERT(device); */
fceaf24a 1275
c6fcf0ba
BP
1276 packet = kzalloc(NETVSC_PACKET_SIZE * sizeof(unsigned char),
1277 GFP_KERNEL);
1278 if (!packet)
1279 return;
1280 buffer = packet;
1281
85799a37
HZ
1282 net_device = GetInboundNetDevice(device);
1283 if (!net_device) {
21a80820 1284 DPRINT_ERR(NETVSC, "net device (%p) shutting down..."
85799a37 1285 "ignoring inbound packets", net_device);
c6fcf0ba 1286 goto out;
fceaf24a
HJ
1287 }
1288
21a80820 1289 do {
9f630068 1290 ret = vmbus_recvpacket_raw(device->channel, buffer, bufferlen,
85799a37 1291 &bytes_recvd, &request_id);
21a80820 1292 if (ret == 0) {
85799a37 1293 if (bytes_recvd > 0) {
21a80820 1294 DPRINT_DBG(NETVSC, "receive %d bytes, tid %llx",
85799a37 1295 bytes_recvd, request_id);
21a80820
GKH
1296
1297 desc = (struct vmpacket_descriptor *)buffer;
1298 switch (desc->Type) {
1299 case VmbusPacketTypeCompletion:
1300 NetVscOnSendCompletion(device, desc);
1301 break;
1302
1303 case VmbusPacketTypeDataUsingTransferPages:
1304 NetVscOnReceive(device, desc);
1305 break;
1306
1307 default:
1308 DPRINT_ERR(NETVSC,
1309 "unhandled packet type %d, "
1310 "tid %llx len %d\n",
85799a37
HZ
1311 desc->Type, request_id,
1312 bytes_recvd);
21a80820 1313 break;
fceaf24a
HJ
1314 }
1315
454f18a9 1316 /* reset */
c6fcf0ba 1317 if (bufferlen > NETVSC_PACKET_SIZE) {
8c69f52a 1318 kfree(buffer);
fceaf24a 1319 buffer = packet;
c6fcf0ba 1320 bufferlen = NETVSC_PACKET_SIZE;
fceaf24a 1321 }
21a80820 1322 } else {
454f18a9 1323 /* reset */
c6fcf0ba 1324 if (bufferlen > NETVSC_PACKET_SIZE) {
8c69f52a 1325 kfree(buffer);
fceaf24a 1326 buffer = packet;
c6fcf0ba 1327 bufferlen = NETVSC_PACKET_SIZE;
fceaf24a
HJ
1328 }
1329
1330 break;
1331 }
21a80820
GKH
1332 } else if (ret == -2) {
1333 /* Handle large packet */
85799a37 1334 buffer = kmalloc(bytes_recvd, GFP_ATOMIC);
21a80820 1335 if (buffer == NULL) {
454f18a9 1336 /* Try again next time around */
21a80820
GKH
1337 DPRINT_ERR(NETVSC,
1338 "unable to allocate buffer of size "
85799a37 1339 "(%d)!!", bytes_recvd);
fceaf24a
HJ
1340 break;
1341 }
1342
85799a37 1343 bufferlen = bytes_recvd;
fceaf24a
HJ
1344 }
1345 } while (1);
1346
1347 PutNetDevice(device);
c6fcf0ba
BP
1348out:
1349 kfree(buffer);
fceaf24a
HJ
1350 return;
1351}