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