Staging: hv: osd: remove Sleep wrapper
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / drivers / staging / hv / NetVsc.c
blob3039812a17cbfdd976f8001640f83b0b715ed1f4
1 /*
3 * Copyright (c) 2009, Microsoft Corporation.
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.
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.
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.
18 * Authors:
19 * Hank Janssen <hjanssen@microsoft.com>
23 #define KERNEL_2_6_27
25 #include <linux/kernel.h>
26 #include <linux/mm.h>
27 #include <linux/delay.h>
28 #include "include/logging.h"
29 #include "NetVsc.h"
30 #include "RndisFilter.h"
34 // Globals
36 static const char* gDriverName="netvsc";
38 // {F8615163-DF3E-46c5-913F-F2D2F965ED0E}
39 static const GUID gNetVscDeviceType={
40 .Data = {0x63, 0x51, 0x61, 0xF8, 0x3E, 0xDF, 0xc5, 0x46, 0x91, 0x3F, 0xF2, 0xD2, 0xF9, 0x65, 0xED, 0x0E}
45 // Internal routines
47 static int
48 NetVscOnDeviceAdd(
49 DEVICE_OBJECT *Device,
50 void *AdditionalInfo
53 static int
54 NetVscOnDeviceRemove(
55 DEVICE_OBJECT *Device
58 static void
59 NetVscOnCleanup(
60 DRIVER_OBJECT *Driver
63 static void
64 NetVscOnChannelCallback(
65 void * context
68 static int
69 NetVscInitializeSendBufferWithNetVsp(
70 DEVICE_OBJECT *Device
73 static int
74 NetVscInitializeReceiveBufferWithNetVsp(
75 DEVICE_OBJECT *Device
78 static int
79 NetVscDestroySendBuffer(
80 NETVSC_DEVICE *NetDevice
83 static int
84 NetVscDestroyReceiveBuffer(
85 NETVSC_DEVICE *NetDevice
88 static int
89 NetVscConnectToVsp(
90 DEVICE_OBJECT *Device
93 static void
94 NetVscOnSendCompletion(
95 DEVICE_OBJECT *Device,
96 VMPACKET_DESCRIPTOR *Packet
99 static int
100 NetVscOnSend(
101 DEVICE_OBJECT *Device,
102 NETVSC_PACKET *Packet
105 static void
106 NetVscOnReceive(
107 DEVICE_OBJECT *Device,
108 VMPACKET_DESCRIPTOR *Packet
111 static void
112 NetVscOnReceiveCompletion(
113 void * Context
116 static void
117 NetVscSendReceiveCompletion(
118 DEVICE_OBJECT *Device,
119 u64 TransactionId
122 static inline NETVSC_DEVICE* AllocNetDevice(DEVICE_OBJECT *Device)
124 NETVSC_DEVICE *netDevice;
126 netDevice = kzalloc(sizeof(NETVSC_DEVICE), GFP_KERNEL);
127 if (!netDevice)
128 return NULL;
130 // Set to 2 to allow both inbound and outbound traffic
131 InterlockedCompareExchange(&netDevice->RefCount, 2, 0);
133 netDevice->Device = Device;
134 Device->Extension = netDevice;
136 return netDevice;
139 static inline void FreeNetDevice(NETVSC_DEVICE *Device)
141 ASSERT(Device->RefCount == 0);
142 Device->Device->Extension = NULL;
143 kfree(Device);
147 // Get the net device object iff exists and its refcount > 1
148 static inline NETVSC_DEVICE* GetOutboundNetDevice(DEVICE_OBJECT *Device)
150 NETVSC_DEVICE *netDevice;
152 netDevice = (NETVSC_DEVICE*)Device->Extension;
153 if (netDevice && netDevice->RefCount > 1)
155 InterlockedIncrement(&netDevice->RefCount);
157 else
159 netDevice = NULL;
162 return netDevice;
165 // Get the net device object iff exists and its refcount > 0
166 static inline NETVSC_DEVICE* GetInboundNetDevice(DEVICE_OBJECT *Device)
168 NETVSC_DEVICE *netDevice;
170 netDevice = (NETVSC_DEVICE*)Device->Extension;
171 if (netDevice && netDevice->RefCount)
173 InterlockedIncrement(&netDevice->RefCount);
175 else
177 netDevice = NULL;
180 return netDevice;
183 static inline void PutNetDevice(DEVICE_OBJECT *Device)
185 NETVSC_DEVICE *netDevice;
187 netDevice = (NETVSC_DEVICE*)Device->Extension;
188 ASSERT(netDevice);
190 InterlockedDecrement(&netDevice->RefCount);
193 static inline NETVSC_DEVICE* ReleaseOutboundNetDevice(DEVICE_OBJECT *Device)
195 NETVSC_DEVICE *netDevice;
197 netDevice = (NETVSC_DEVICE*)Device->Extension;
198 if (netDevice == NULL)
199 return NULL;
201 // Busy wait until the ref drop to 2, then set it to 1
202 while (InterlockedCompareExchange(&netDevice->RefCount, 1, 2) != 2)
204 udelay(100);
207 return netDevice;
210 static inline NETVSC_DEVICE* ReleaseInboundNetDevice(DEVICE_OBJECT *Device)
212 NETVSC_DEVICE *netDevice;
214 netDevice = (NETVSC_DEVICE*)Device->Extension;
215 if (netDevice == NULL)
216 return NULL;
218 // Busy wait until the ref drop to 1, then set it to 0
219 while (InterlockedCompareExchange(&netDevice->RefCount, 0, 1) != 1)
221 udelay(100);
224 Device->Extension = NULL;
225 return netDevice;
228 /*++;
231 Name:
232 NetVscInitialize()
234 Description:
235 Main entry point
237 --*/
239 NetVscInitialize(
240 DRIVER_OBJECT *drv
243 NETVSC_DRIVER_OBJECT* driver = (NETVSC_DRIVER_OBJECT*)drv;
244 int ret=0;
246 DPRINT_ENTER(NETVSC);
248 DPRINT_DBG(NETVSC, "sizeof(NETVSC_PACKET)=%d, sizeof(NVSP_MESSAGE)=%d, sizeof(VMTRANSFER_PAGE_PACKET_HEADER)=%d",
249 sizeof(NETVSC_PACKET), sizeof(NVSP_MESSAGE), sizeof(VMTRANSFER_PAGE_PACKET_HEADER));
251 // Make sure we are at least 2 pages since 1 page is used for control
252 ASSERT(driver->RingBufferSize >= (PAGE_SIZE << 1));
254 drv->name = gDriverName;
255 memcpy(&drv->deviceType, &gNetVscDeviceType, sizeof(GUID));
257 // Make sure it is set by the caller
258 ASSERT(driver->OnReceiveCallback);
259 ASSERT(driver->OnLinkStatusChanged);
261 // Setup the dispatch table
262 driver->Base.OnDeviceAdd = NetVscOnDeviceAdd;
263 driver->Base.OnDeviceRemove = NetVscOnDeviceRemove;
264 driver->Base.OnCleanup = NetVscOnCleanup;
266 driver->OnSend = NetVscOnSend;
268 RndisFilterInit(driver);
270 DPRINT_EXIT(NETVSC);
272 return ret;
275 static int
276 NetVscInitializeReceiveBufferWithNetVsp(
277 DEVICE_OBJECT *Device
280 int ret=0;
281 NETVSC_DEVICE *netDevice;
282 NVSP_MESSAGE *initPacket;
284 DPRINT_ENTER(NETVSC);
286 netDevice = GetOutboundNetDevice(Device);
287 if (!netDevice)
289 DPRINT_ERR(NETVSC, "unable to get net device...device being destroyed?");
290 DPRINT_EXIT(NETVSC);
291 return -1;
293 ASSERT(netDevice->ReceiveBufferSize > 0);
294 ASSERT((netDevice->ReceiveBufferSize & (PAGE_SIZE-1)) == 0); // page-size grandularity
296 netDevice->ReceiveBuffer = PageAlloc(netDevice->ReceiveBufferSize >> PAGE_SHIFT);
297 if (!netDevice->ReceiveBuffer)
299 DPRINT_ERR(NETVSC, "unable to allocate receive buffer of size %d", netDevice->ReceiveBufferSize);
300 ret = -1;
301 goto Cleanup;
303 ASSERT(((unsigned long)netDevice->ReceiveBuffer & (PAGE_SIZE-1)) == 0); // page-aligned buffer
305 DPRINT_INFO(NETVSC, "Establishing receive buffer's GPADL...");
307 // Establish the gpadl handle for this buffer on this channel.
308 // Note: This call uses the vmbus connection rather than the channel to establish
309 // the gpadl handle.
310 ret = Device->Driver->VmbusChannelInterface.EstablishGpadl(Device,
311 netDevice->ReceiveBuffer,
312 netDevice->ReceiveBufferSize,
313 &netDevice->ReceiveBufferGpadlHandle);
315 if (ret != 0)
317 DPRINT_ERR(NETVSC, "unable to establish receive buffer's gpadl");
318 goto Cleanup;
321 //WaitEventWait(ext->ChannelInitEvent);
323 // Notify the NetVsp of the gpadl handle
324 DPRINT_INFO(NETVSC, "Sending NvspMessage1TypeSendReceiveBuffer...");
326 initPacket = &netDevice->ChannelInitPacket;
328 memset(initPacket, 0, sizeof(NVSP_MESSAGE));
330 initPacket->Header.MessageType = NvspMessage1TypeSendReceiveBuffer;
331 initPacket->Messages.Version1Messages.SendReceiveBuffer.GpadlHandle = netDevice->ReceiveBufferGpadlHandle;
332 initPacket->Messages.Version1Messages.SendReceiveBuffer.Id = NETVSC_RECEIVE_BUFFER_ID;
334 // Send the gpadl notification request
335 ret = Device->Driver->VmbusChannelInterface.SendPacket(Device,
336 initPacket,
337 sizeof(NVSP_MESSAGE),
338 (unsigned long)initPacket,
339 VmbusPacketTypeDataInBand,
340 VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
341 if (ret != 0)
343 DPRINT_ERR(NETVSC, "unable to send receive buffer's gpadl to netvsp");
344 goto Cleanup;
347 WaitEventWait(netDevice->ChannelInitEvent);
349 // Check the response
350 if (initPacket->Messages.Version1Messages.SendReceiveBufferComplete.Status != NvspStatusSuccess)
352 DPRINT_ERR(NETVSC,
353 "Unable to complete receive buffer initialzation with NetVsp - status %d",
354 initPacket->Messages.Version1Messages.SendReceiveBufferComplete.Status);
355 ret = -1;
356 goto Cleanup;
359 // Parse the response
360 ASSERT(netDevice->ReceiveSectionCount == 0);
361 ASSERT(netDevice->ReceiveSections == NULL);
363 netDevice->ReceiveSectionCount = initPacket->Messages.Version1Messages.SendReceiveBufferComplete.NumSections;
365 netDevice->ReceiveSections = kmalloc(netDevice->ReceiveSectionCount * sizeof(NVSP_1_RECEIVE_BUFFER_SECTION), GFP_KERNEL);
366 if (netDevice->ReceiveSections == NULL)
368 ret = -1;
369 goto Cleanup;
372 memcpy(netDevice->ReceiveSections,
373 initPacket->Messages.Version1Messages.SendReceiveBufferComplete.Sections,
374 netDevice->ReceiveSectionCount * sizeof(NVSP_1_RECEIVE_BUFFER_SECTION));
376 DPRINT_INFO(NETVSC,
377 "Receive sections info (count %d, offset %d, endoffset %d, suballoc size %d, num suballocs %d)",
378 netDevice->ReceiveSectionCount, netDevice->ReceiveSections[0].Offset, netDevice->ReceiveSections[0].EndOffset,
379 netDevice->ReceiveSections[0].SubAllocationSize, netDevice->ReceiveSections[0].NumSubAllocations);
382 //For 1st release, there should only be 1 section that represents the entire receive buffer
383 if (netDevice->ReceiveSectionCount != 1 ||
384 netDevice->ReceiveSections->Offset != 0 )
386 ret = -1;
387 goto Cleanup;
390 goto Exit;
392 Cleanup:
393 NetVscDestroyReceiveBuffer(netDevice);
395 Exit:
396 PutNetDevice(Device);
397 DPRINT_EXIT(NETVSC);
398 return ret;
402 static int
403 NetVscInitializeSendBufferWithNetVsp(
404 DEVICE_OBJECT *Device
407 int ret=0;
408 NETVSC_DEVICE *netDevice;
409 NVSP_MESSAGE *initPacket;
411 DPRINT_ENTER(NETVSC);
413 netDevice = GetOutboundNetDevice(Device);
414 if (!netDevice)
416 DPRINT_ERR(NETVSC, "unable to get net device...device being destroyed?");
417 DPRINT_EXIT(NETVSC);
418 return -1;
420 ASSERT(netDevice->SendBufferSize > 0);
421 ASSERT((netDevice->SendBufferSize & (PAGE_SIZE-1)) == 0); // page-size grandularity
423 netDevice->SendBuffer = PageAlloc(netDevice->SendBufferSize >> PAGE_SHIFT);
424 if (!netDevice->SendBuffer)
426 DPRINT_ERR(NETVSC, "unable to allocate send buffer of size %d", netDevice->SendBufferSize);
427 ret = -1;
428 goto Cleanup;
430 ASSERT(((unsigned long)netDevice->SendBuffer & (PAGE_SIZE-1)) == 0); // page-aligned buffer
432 DPRINT_INFO(NETVSC, "Establishing send buffer's GPADL...");
434 // Establish the gpadl handle for this buffer on this channel.
435 // Note: This call uses the vmbus connection rather than the channel to establish
436 // the gpadl handle.
437 ret = Device->Driver->VmbusChannelInterface.EstablishGpadl(Device,
438 netDevice->SendBuffer,
439 netDevice->SendBufferSize,
440 &netDevice->SendBufferGpadlHandle);
442 if (ret != 0)
444 DPRINT_ERR(NETVSC, "unable to establish send buffer's gpadl");
445 goto Cleanup;
448 //WaitEventWait(ext->ChannelInitEvent);
450 // Notify the NetVsp of the gpadl handle
451 DPRINT_INFO(NETVSC, "Sending NvspMessage1TypeSendSendBuffer...");
453 initPacket = &netDevice->ChannelInitPacket;
455 memset(initPacket, 0, sizeof(NVSP_MESSAGE));
457 initPacket->Header.MessageType = NvspMessage1TypeSendSendBuffer;
458 initPacket->Messages.Version1Messages.SendReceiveBuffer.GpadlHandle = netDevice->SendBufferGpadlHandle;
459 initPacket->Messages.Version1Messages.SendReceiveBuffer.Id = NETVSC_SEND_BUFFER_ID;
461 // Send the gpadl notification request
462 ret = Device->Driver->VmbusChannelInterface.SendPacket(Device,
463 initPacket,
464 sizeof(NVSP_MESSAGE),
465 (unsigned long)initPacket,
466 VmbusPacketTypeDataInBand,
467 VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
468 if (ret != 0)
470 DPRINT_ERR(NETVSC, "unable to send receive buffer's gpadl to netvsp");
471 goto Cleanup;
474 WaitEventWait(netDevice->ChannelInitEvent);
476 // Check the response
477 if (initPacket->Messages.Version1Messages.SendSendBufferComplete.Status != NvspStatusSuccess)
479 DPRINT_ERR(NETVSC,
480 "Unable to complete send buffer initialzation with NetVsp - status %d",
481 initPacket->Messages.Version1Messages.SendSendBufferComplete.Status);
482 ret = -1;
483 goto Cleanup;
486 netDevice->SendSectionSize = initPacket->Messages.Version1Messages.SendSendBufferComplete.SectionSize;
488 goto Exit;
490 Cleanup:
491 NetVscDestroySendBuffer(netDevice);
493 Exit:
494 PutNetDevice(Device);
495 DPRINT_EXIT(NETVSC);
496 return ret;
499 static int
500 NetVscDestroyReceiveBuffer(
501 NETVSC_DEVICE *NetDevice
504 NVSP_MESSAGE *revokePacket;
505 int ret=0;
508 DPRINT_ENTER(NETVSC);
510 // If we got a section count, it means we received a SendReceiveBufferComplete msg
511 // (ie sent NvspMessage1TypeSendReceiveBuffer msg) therefore, we need to send a revoke msg here
512 if (NetDevice->ReceiveSectionCount)
514 DPRINT_INFO(NETVSC, "Sending NvspMessage1TypeRevokeReceiveBuffer...");
516 // Send the revoke receive buffer
517 revokePacket = &NetDevice->RevokePacket;
518 memset(revokePacket, 0, sizeof(NVSP_MESSAGE));
520 revokePacket->Header.MessageType = NvspMessage1TypeRevokeReceiveBuffer;
521 revokePacket->Messages.Version1Messages.RevokeReceiveBuffer.Id = NETVSC_RECEIVE_BUFFER_ID;
523 ret = NetDevice->Device->Driver->VmbusChannelInterface.SendPacket(NetDevice->Device,
524 revokePacket,
525 sizeof(NVSP_MESSAGE),
526 (unsigned long)revokePacket,
527 VmbusPacketTypeDataInBand,
529 // If we failed here, we might as well return and have a leak rather than continue and a bugchk
530 if (ret != 0)
532 DPRINT_ERR(NETVSC, "unable to send revoke receive buffer to netvsp");
533 DPRINT_EXIT(NETVSC);
534 return -1;
538 // Teardown the gpadl on the vsp end
539 if (NetDevice->ReceiveBufferGpadlHandle)
541 DPRINT_INFO(NETVSC, "Tearing down receive buffer's GPADL...");
543 ret = NetDevice->Device->Driver->VmbusChannelInterface.TeardownGpadl(NetDevice->Device,
544 NetDevice->ReceiveBufferGpadlHandle);
546 // If we failed here, we might as well return and have a leak rather than continue and a bugchk
547 if (ret != 0)
549 DPRINT_ERR(NETVSC, "unable to teardown receive buffer's gpadl");
550 DPRINT_EXIT(NETVSC);
551 return -1;
553 NetDevice->ReceiveBufferGpadlHandle = 0;
556 if (NetDevice->ReceiveBuffer)
558 DPRINT_INFO(NETVSC, "Freeing up receive buffer...");
560 // Free up the receive buffer
561 PageFree(NetDevice->ReceiveBuffer, NetDevice->ReceiveBufferSize >> PAGE_SHIFT);
562 NetDevice->ReceiveBuffer = NULL;
565 if (NetDevice->ReceiveSections)
567 kfree(NetDevice->ReceiveSections);
568 NetDevice->ReceiveSections = NULL;
569 NetDevice->ReceiveSectionCount = 0;
572 DPRINT_EXIT(NETVSC);
574 return ret;
580 static int
581 NetVscDestroySendBuffer(
582 NETVSC_DEVICE *NetDevice
585 NVSP_MESSAGE *revokePacket;
586 int ret=0;
589 DPRINT_ENTER(NETVSC);
591 // If we got a section count, it means we received a SendReceiveBufferComplete msg
592 // (ie sent NvspMessage1TypeSendReceiveBuffer msg) therefore, we need to send a revoke msg here
593 if (NetDevice->SendSectionSize)
595 DPRINT_INFO(NETVSC, "Sending NvspMessage1TypeRevokeSendBuffer...");
597 // Send the revoke send buffer
598 revokePacket = &NetDevice->RevokePacket;
599 memset(revokePacket, 0, sizeof(NVSP_MESSAGE));
601 revokePacket->Header.MessageType = NvspMessage1TypeRevokeSendBuffer;
602 revokePacket->Messages.Version1Messages.RevokeSendBuffer.Id = NETVSC_SEND_BUFFER_ID;
604 ret = NetDevice->Device->Driver->VmbusChannelInterface.SendPacket(NetDevice->Device,
605 revokePacket,
606 sizeof(NVSP_MESSAGE),
607 (unsigned long)revokePacket,
608 VmbusPacketTypeDataInBand,
610 // If we failed here, we might as well return and have a leak rather than continue and a bugchk
611 if (ret != 0)
613 DPRINT_ERR(NETVSC, "unable to send revoke send buffer to netvsp");
614 DPRINT_EXIT(NETVSC);
615 return -1;
619 // Teardown the gpadl on the vsp end
620 if (NetDevice->SendBufferGpadlHandle)
622 DPRINT_INFO(NETVSC, "Tearing down send buffer's GPADL...");
624 ret = NetDevice->Device->Driver->VmbusChannelInterface.TeardownGpadl(NetDevice->Device,
625 NetDevice->SendBufferGpadlHandle);
627 // If we failed here, we might as well return and have a leak rather than continue and a bugchk
628 if (ret != 0)
630 DPRINT_ERR(NETVSC, "unable to teardown send buffer's gpadl");
631 DPRINT_EXIT(NETVSC);
632 return -1;
634 NetDevice->SendBufferGpadlHandle = 0;
637 if (NetDevice->SendBuffer)
639 DPRINT_INFO(NETVSC, "Freeing up send buffer...");
641 // Free up the receive buffer
642 PageFree(NetDevice->SendBuffer, NetDevice->SendBufferSize >> PAGE_SHIFT);
643 NetDevice->SendBuffer = NULL;
646 DPRINT_EXIT(NETVSC);
648 return ret;
653 static int
654 NetVscConnectToVsp(
655 DEVICE_OBJECT *Device
658 int ret=0;
659 NETVSC_DEVICE *netDevice;
660 NVSP_MESSAGE *initPacket;
661 int ndisVersion;
663 DPRINT_ENTER(NETVSC);
665 netDevice = GetOutboundNetDevice(Device);
666 if (!netDevice)
668 DPRINT_ERR(NETVSC, "unable to get net device...device being destroyed?");
669 DPRINT_EXIT(NETVSC);
670 return -1;
673 initPacket = &netDevice->ChannelInitPacket;
675 memset(initPacket, 0, sizeof(NVSP_MESSAGE));
676 initPacket->Header.MessageType = NvspMessageTypeInit;
677 initPacket->Messages.InitMessages.Init.MinProtocolVersion = NVSP_MIN_PROTOCOL_VERSION;
678 initPacket->Messages.InitMessages.Init.MaxProtocolVersion = NVSP_MAX_PROTOCOL_VERSION;
680 DPRINT_INFO(NETVSC, "Sending NvspMessageTypeInit...");
682 // Send the init request
683 ret = Device->Driver->VmbusChannelInterface.SendPacket(Device,
684 initPacket,
685 sizeof(NVSP_MESSAGE),
686 (unsigned long)initPacket,
687 VmbusPacketTypeDataInBand,
688 VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
690 if( ret != 0)
692 DPRINT_ERR(NETVSC, "unable to send NvspMessageTypeInit");
693 goto Cleanup;
696 WaitEventWait(netDevice->ChannelInitEvent);
698 // Now, check the response
699 //ASSERT(initPacket->Messages.InitMessages.InitComplete.MaximumMdlChainLength <= MAX_MULTIPAGE_BUFFER_COUNT);
700 DPRINT_INFO(NETVSC, "NvspMessageTypeInit status(%d) max mdl chain (%d)",
701 initPacket->Messages.InitMessages.InitComplete.Status,
702 initPacket->Messages.InitMessages.InitComplete.MaximumMdlChainLength);
704 if (initPacket->Messages.InitMessages.InitComplete.Status != NvspStatusSuccess)
706 DPRINT_ERR(NETVSC, "unable to initialize with netvsp (status 0x%x)", initPacket->Messages.InitMessages.InitComplete.Status);
707 ret = -1;
708 goto Cleanup;
711 if (initPacket->Messages.InitMessages.InitComplete.NegotiatedProtocolVersion != NVSP_PROTOCOL_VERSION_1)
713 DPRINT_ERR(NETVSC, "unable to initialize with netvsp (version expected 1 got %d)",
714 initPacket->Messages.InitMessages.InitComplete.NegotiatedProtocolVersion);
715 ret = -1;
716 goto Cleanup;
718 DPRINT_INFO(NETVSC, "Sending NvspMessage1TypeSendNdisVersion...");
720 // Send the ndis version
721 memset(initPacket, 0, sizeof(NVSP_MESSAGE));
723 ndisVersion = 0x00050000;
725 initPacket->Header.MessageType = NvspMessage1TypeSendNdisVersion;
726 initPacket->Messages.Version1Messages.SendNdisVersion.NdisMajorVersion = (ndisVersion & 0xFFFF0000) >> 16;
727 initPacket->Messages.Version1Messages.SendNdisVersion.NdisMinorVersion = ndisVersion & 0xFFFF;
729 // Send the init request
730 ret = Device->Driver->VmbusChannelInterface.SendPacket(Device,
731 initPacket,
732 sizeof(NVSP_MESSAGE),
733 (unsigned long)initPacket,
734 VmbusPacketTypeDataInBand,
736 if (ret != 0)
738 DPRINT_ERR(NETVSC, "unable to send NvspMessage1TypeSendNdisVersion");
739 ret = -1;
740 goto Cleanup;
743 // BUGBUG - We have to wait for the above msg since the netvsp uses KMCL which acknowledges packet (completion packet)
744 // since our Vmbus always set the VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED flag
745 //WaitEventWait(NetVscChannel->ChannelInitEvent);
747 // Post the big receive buffer to NetVSP
748 ret = NetVscInitializeReceiveBufferWithNetVsp(Device);
749 if (ret == 0)
751 ret = NetVscInitializeSendBufferWithNetVsp(Device);
754 Cleanup:
755 PutNetDevice(Device);
756 DPRINT_EXIT(NETVSC);
757 return ret;
760 static void
761 NetVscDisconnectFromVsp(
762 NETVSC_DEVICE *NetDevice
765 DPRINT_ENTER(NETVSC);
767 NetVscDestroyReceiveBuffer(NetDevice);
768 NetVscDestroySendBuffer(NetDevice);
770 DPRINT_EXIT(NETVSC);
774 /*++
776 Name:
777 NetVscOnDeviceAdd()
779 Description:
780 Callback when the device belonging to this driver is added
782 --*/
784 NetVscOnDeviceAdd(
785 DEVICE_OBJECT *Device,
786 void *AdditionalInfo
789 int ret=0;
790 int i;
792 NETVSC_DEVICE* netDevice;
793 NETVSC_PACKET* packet;
794 LIST_ENTRY *entry;
796 NETVSC_DRIVER_OBJECT *netDriver = (NETVSC_DRIVER_OBJECT*) Device->Driver;;
798 DPRINT_ENTER(NETVSC);
800 netDevice = AllocNetDevice(Device);
801 if (!netDevice)
803 ret = -1;
804 goto Cleanup;
807 DPRINT_DBG(NETVSC, "netvsc channel object allocated - %p", netDevice);
809 // Initialize the NetVSC channel extension
810 netDevice->ReceiveBufferSize = NETVSC_RECEIVE_BUFFER_SIZE;
811 spin_lock_init(&netDevice->receive_packet_list_lock);
813 netDevice->SendBufferSize = NETVSC_SEND_BUFFER_SIZE;
815 INITIALIZE_LIST_HEAD(&netDevice->ReceivePacketList);
817 for (i=0; i < NETVSC_RECEIVE_PACKETLIST_COUNT; i++)
819 packet = kzalloc(sizeof(NETVSC_PACKET) + (NETVSC_RECEIVE_SG_COUNT* sizeof(PAGE_BUFFER)), GFP_KERNEL);
820 if (!packet)
822 DPRINT_DBG(NETVSC, "unable to allocate netvsc pkts for receive pool (wanted %d got %d)", NETVSC_RECEIVE_PACKETLIST_COUNT, i);
823 break;
826 INSERT_TAIL_LIST(&netDevice->ReceivePacketList, &packet->ListEntry);
828 netDevice->ChannelInitEvent = WaitEventCreate();
830 // Open the channel
831 ret = Device->Driver->VmbusChannelInterface.Open(Device,
832 netDriver->RingBufferSize,
833 netDriver->RingBufferSize,
834 NULL, 0,
835 NetVscOnChannelCallback,
836 Device
839 if (ret != 0)
841 DPRINT_ERR(NETVSC, "unable to open channel: %d", ret);
842 ret = -1;
843 goto Cleanup;
846 // Channel is opened
847 DPRINT_INFO(NETVSC, "*** NetVSC channel opened successfully! ***");
849 // Connect with the NetVsp
850 ret = NetVscConnectToVsp(Device);
851 if (ret != 0)
853 DPRINT_ERR(NETVSC, "unable to connect to NetVSP - %d", ret);
854 ret = -1;
855 goto Close;
858 DPRINT_INFO(NETVSC, "*** NetVSC channel handshake result - %d ***", ret);
860 DPRINT_EXIT(NETVSC);
861 return ret;
863 Close:
864 // Now, we can close the channel safely
865 Device->Driver->VmbusChannelInterface.Close(Device);
867 Cleanup:
869 if (netDevice)
871 WaitEventClose(netDevice->ChannelInitEvent);
873 while (!IsListEmpty(&netDevice->ReceivePacketList))
875 entry = REMOVE_HEAD_LIST(&netDevice->ReceivePacketList);
876 packet = CONTAINING_RECORD(entry, NETVSC_PACKET, ListEntry);
877 kfree(packet);
880 ReleaseOutboundNetDevice(Device);
881 ReleaseInboundNetDevice(Device);
883 FreeNetDevice(netDevice);
886 DPRINT_EXIT(NETVSC);
887 return ret;
891 /*++
893 Name:
894 NetVscOnDeviceRemove()
896 Description:
897 Callback when the root bus device is removed
899 --*/
901 NetVscOnDeviceRemove(
902 DEVICE_OBJECT *Device
905 NETVSC_DEVICE *netDevice;
906 NETVSC_PACKET *netvscPacket;
907 int ret=0;
908 LIST_ENTRY *entry;
910 DPRINT_ENTER(NETVSC);
912 DPRINT_INFO(NETVSC, "Disabling outbound traffic on net device (%p)...", Device->Extension);
914 // Stop outbound traffic ie sends and receives completions
915 netDevice = ReleaseOutboundNetDevice(Device);
916 if (!netDevice)
918 DPRINT_ERR(NETVSC, "No net device present!!");
919 return -1;
922 // Wait for all send completions
923 while (netDevice->NumOutstandingSends)
925 DPRINT_INFO(NETVSC, "waiting for %d requests to complete...", netDevice->NumOutstandingSends);
927 udelay(100);
930 DPRINT_INFO(NETVSC, "Disconnecting from netvsp...");
932 NetVscDisconnectFromVsp(netDevice);
934 DPRINT_INFO(NETVSC, "Disabling inbound traffic on net device (%p)...", Device->Extension);
936 // Stop inbound traffic ie receives and sends completions
937 netDevice = ReleaseInboundNetDevice(Device);
939 // At this point, no one should be accessing netDevice except in here
940 DPRINT_INFO(NETVSC, "net device (%p) safe to remove", netDevice);
942 // Now, we can close the channel safely
943 Device->Driver->VmbusChannelInterface.Close(Device);
945 // Release all resources
946 while (!IsListEmpty(&netDevice->ReceivePacketList))
948 entry = REMOVE_HEAD_LIST(&netDevice->ReceivePacketList);
949 netvscPacket = CONTAINING_RECORD(entry, NETVSC_PACKET, ListEntry);
951 kfree(netvscPacket);
954 WaitEventClose(netDevice->ChannelInitEvent);
955 FreeNetDevice(netDevice);
957 DPRINT_EXIT(NETVSC);
958 return ret;
963 /*++
965 Name:
966 NetVscOnCleanup()
968 Description:
969 Perform any cleanup when the driver is removed
971 --*/
972 void
973 NetVscOnCleanup(
974 DRIVER_OBJECT *drv
977 DPRINT_ENTER(NETVSC);
979 DPRINT_EXIT(NETVSC);
982 static void
983 NetVscOnSendCompletion(
984 DEVICE_OBJECT *Device,
985 VMPACKET_DESCRIPTOR *Packet
988 NETVSC_DEVICE* netDevice;
989 NVSP_MESSAGE *nvspPacket;
990 NETVSC_PACKET *nvscPacket;
992 DPRINT_ENTER(NETVSC);
994 netDevice = GetInboundNetDevice(Device);
995 if (!netDevice)
997 DPRINT_ERR(NETVSC, "unable to get net device...device being destroyed?");
998 DPRINT_EXIT(NETVSC);
999 return;
1002 nvspPacket = (NVSP_MESSAGE*)((unsigned long)Packet + (Packet->DataOffset8 << 3));
1004 DPRINT_DBG(NETVSC, "send completion packet - type %d", nvspPacket->Header.MessageType);
1006 if (nvspPacket->Header.MessageType == NvspMessageTypeInitComplete ||
1007 nvspPacket->Header.MessageType == NvspMessage1TypeSendReceiveBufferComplete ||
1008 nvspPacket->Header.MessageType == NvspMessage1TypeSendSendBufferComplete)
1010 // Copy the response back
1011 memcpy(&netDevice->ChannelInitPacket, nvspPacket, sizeof(NVSP_MESSAGE));
1012 WaitEventSet(netDevice->ChannelInitEvent);
1014 else if (nvspPacket->Header.MessageType == NvspMessage1TypeSendRNDISPacketComplete)
1016 // Get the send context
1017 nvscPacket = (NETVSC_PACKET *)(unsigned long)Packet->TransactionId;
1018 ASSERT(nvscPacket);
1020 // Notify the layer above us
1021 nvscPacket->Completion.Send.OnSendCompletion(nvscPacket->Completion.Send.SendCompletionContext);
1023 InterlockedDecrement(&netDevice->NumOutstandingSends);
1025 else
1027 DPRINT_ERR(NETVSC, "Unknown send completion packet type - %d received!!", nvspPacket->Header.MessageType);
1030 PutNetDevice(Device);
1031 DPRINT_EXIT(NETVSC);
1036 static int
1037 NetVscOnSend(
1038 DEVICE_OBJECT *Device,
1039 NETVSC_PACKET *Packet
1042 NETVSC_DEVICE* netDevice;
1043 int ret=0;
1045 NVSP_MESSAGE sendMessage;
1047 DPRINT_ENTER(NETVSC);
1049 netDevice = GetOutboundNetDevice(Device);
1050 if (!netDevice)
1052 DPRINT_ERR(NETVSC, "net device (%p) shutting down...ignoring outbound packets", netDevice);
1053 DPRINT_EXIT(NETVSC);
1054 return -2;
1057 sendMessage.Header.MessageType = NvspMessage1TypeSendRNDISPacket;
1058 if (Packet->IsDataPacket)
1059 sendMessage.Messages.Version1Messages.SendRNDISPacket.ChannelType = 0;// 0 is RMC_DATA;
1060 else
1061 sendMessage.Messages.Version1Messages.SendRNDISPacket.ChannelType = 1;// 1 is RMC_CONTROL;
1063 // Not using send buffer section
1064 sendMessage.Messages.Version1Messages.SendRNDISPacket.SendBufferSectionIndex = 0xFFFFFFFF;
1065 sendMessage.Messages.Version1Messages.SendRNDISPacket.SendBufferSectionSize = 0;
1067 if (Packet->PageBufferCount)
1069 ret = Device->Driver->VmbusChannelInterface.SendPacketPageBuffer(Device,
1070 Packet->PageBuffers,
1071 Packet->PageBufferCount,
1072 &sendMessage,
1073 sizeof(NVSP_MESSAGE),
1074 (unsigned long)Packet);
1076 else
1078 ret = Device->Driver->VmbusChannelInterface.SendPacket(Device,
1079 &sendMessage,
1080 sizeof(NVSP_MESSAGE),
1081 (unsigned long)Packet,
1082 VmbusPacketTypeDataInBand,
1083 VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
1087 if (ret != 0)
1089 DPRINT_ERR(NETVSC, "Unable to send packet %p ret %d", Packet, ret);
1092 InterlockedIncrement(&netDevice->NumOutstandingSends);
1093 PutNetDevice(Device);
1095 DPRINT_EXIT(NETVSC);
1096 return ret;
1100 static void
1101 NetVscOnReceive(
1102 DEVICE_OBJECT *Device,
1103 VMPACKET_DESCRIPTOR *Packet
1106 NETVSC_DEVICE* netDevice;
1107 VMTRANSFER_PAGE_PACKET_HEADER *vmxferpagePacket;
1108 NVSP_MESSAGE *nvspPacket;
1109 NETVSC_PACKET *netvscPacket=NULL;
1110 LIST_ENTRY* entry;
1111 unsigned long start;
1112 unsigned long end, endVirtual;
1113 //NETVSC_DRIVER_OBJECT *netvscDriver;
1114 XFERPAGE_PACKET *xferpagePacket=NULL;
1115 LIST_ENTRY listHead;
1117 int i=0, j=0;
1118 int count=0, bytesRemain=0;
1119 unsigned long flags;
1121 DPRINT_ENTER(NETVSC);
1123 netDevice = GetInboundNetDevice(Device);
1124 if (!netDevice)
1126 DPRINT_ERR(NETVSC, "unable to get net device...device being destroyed?");
1127 DPRINT_EXIT(NETVSC);
1128 return;
1131 // All inbound packets other than send completion should be xfer page packet
1132 if (Packet->Type != VmbusPacketTypeDataUsingTransferPages)
1134 DPRINT_ERR(NETVSC, "Unknown packet type received - %d", Packet->Type);
1135 PutNetDevice(Device);
1136 return;
1139 nvspPacket = (NVSP_MESSAGE*)((unsigned long)Packet + (Packet->DataOffset8 << 3));
1141 // Make sure this is a valid nvsp packet
1142 if (nvspPacket->Header.MessageType != NvspMessage1TypeSendRNDISPacket )
1144 DPRINT_ERR(NETVSC, "Unknown nvsp packet type received - %d", nvspPacket->Header.MessageType);
1145 PutNetDevice(Device);
1146 return;
1149 DPRINT_DBG(NETVSC, "NVSP packet received - type %d", nvspPacket->Header.MessageType);
1151 vmxferpagePacket = (VMTRANSFER_PAGE_PACKET_HEADER*)Packet;
1153 if (vmxferpagePacket->TransferPageSetId != NETVSC_RECEIVE_BUFFER_ID)
1155 DPRINT_ERR(NETVSC, "Invalid xfer page set id - expecting %x got %x", NETVSC_RECEIVE_BUFFER_ID, vmxferpagePacket->TransferPageSetId);
1156 PutNetDevice(Device);
1157 return;
1160 DPRINT_DBG(NETVSC, "xfer page - range count %d", vmxferpagePacket->RangeCount);
1162 INITIALIZE_LIST_HEAD(&listHead);
1164 // Grab free packets (range count + 1) to represent this xfer page packet. +1 to represent
1165 // the xfer page packet itself. We grab it here so that we know exactly how many we can fulfil
1166 spin_lock_irqsave(&netDevice->receive_packet_list_lock, flags);
1167 while (!IsListEmpty(&netDevice->ReceivePacketList))
1169 entry = REMOVE_HEAD_LIST(&netDevice->ReceivePacketList);
1170 netvscPacket = CONTAINING_RECORD(entry, NETVSC_PACKET, ListEntry);
1172 INSERT_TAIL_LIST(&listHead, &netvscPacket->ListEntry);
1174 if (++count == vmxferpagePacket->RangeCount + 1)
1175 break;
1177 spin_unlock_irqrestore(&netDevice->receive_packet_list_lock, flags);
1179 // We need at least 2 netvsc pkts (1 to represent the xfer page and at least 1 for the range)
1180 // i.e. we can handled some of the xfer page packet ranges...
1181 if (count < 2)
1183 DPRINT_ERR(NETVSC, "Got only %d netvsc pkt...needed %d pkts. Dropping this xfer page packet completely!", count, vmxferpagePacket->RangeCount+1);
1185 // Return it to the freelist
1186 spin_lock_irqsave(&netDevice->receive_packet_list_lock, flags);
1187 for (i=count; i != 0; i--)
1189 entry = REMOVE_HEAD_LIST(&listHead);
1190 netvscPacket = CONTAINING_RECORD(entry, NETVSC_PACKET, ListEntry);
1192 INSERT_TAIL_LIST(&netDevice->ReceivePacketList, &netvscPacket->ListEntry);
1194 spin_unlock_irqrestore(&netDevice->receive_packet_list_lock, flags);
1196 NetVscSendReceiveCompletion(Device, vmxferpagePacket->d.TransactionId);
1198 PutNetDevice(Device);
1199 return;
1202 // Remove the 1st packet to represent the xfer page packet itself
1203 entry = REMOVE_HEAD_LIST(&listHead);
1204 xferpagePacket = CONTAINING_RECORD(entry, XFERPAGE_PACKET, ListEntry);
1205 xferpagePacket->Count = count - 1; // This is how much we can satisfy
1206 ASSERT(xferpagePacket->Count > 0 && xferpagePacket->Count <= vmxferpagePacket->RangeCount);
1208 if (xferpagePacket->Count != vmxferpagePacket->RangeCount)
1210 DPRINT_INFO(NETVSC, "Needed %d netvsc pkts to satisy this xfer page...got %d", vmxferpagePacket->RangeCount, xferpagePacket->Count);
1213 // Each range represents 1 RNDIS pkt that contains 1 ethernet frame
1214 for (i=0; i < (count - 1); i++)
1216 entry = REMOVE_HEAD_LIST(&listHead);
1217 netvscPacket = CONTAINING_RECORD(entry, NETVSC_PACKET, ListEntry);
1219 // Initialize the netvsc packet
1220 netvscPacket->XferPagePacket = xferpagePacket;
1221 netvscPacket->Completion.Recv.OnReceiveCompletion = NetVscOnReceiveCompletion;
1222 netvscPacket->Completion.Recv.ReceiveCompletionContext = netvscPacket;
1223 netvscPacket->Device = Device;
1224 netvscPacket->Completion.Recv.ReceiveCompletionTid = vmxferpagePacket->d.TransactionId; // Save this so that we can send it back
1226 netvscPacket->TotalDataBufferLength = vmxferpagePacket->Ranges[i].ByteCount;
1227 netvscPacket->PageBufferCount = 1;
1229 ASSERT(vmxferpagePacket->Ranges[i].ByteOffset + vmxferpagePacket->Ranges[i].ByteCount < netDevice->ReceiveBufferSize);
1231 netvscPacket->PageBuffers[0].Length = vmxferpagePacket->Ranges[i].ByteCount;
1233 start = GetPhysicalAddress((void*)((unsigned long)netDevice->ReceiveBuffer + vmxferpagePacket->Ranges[i].ByteOffset));
1235 netvscPacket->PageBuffers[0].Pfn = start >> PAGE_SHIFT;
1236 endVirtual = (unsigned long)netDevice->ReceiveBuffer
1237 + vmxferpagePacket->Ranges[i].ByteOffset
1238 + vmxferpagePacket->Ranges[i].ByteCount -1;
1239 end = GetPhysicalAddress((void*)endVirtual);
1241 // Calculate the page relative offset
1242 netvscPacket->PageBuffers[0].Offset = vmxferpagePacket->Ranges[i].ByteOffset & (PAGE_SIZE -1);
1243 if ((end >> PAGE_SHIFT) != (start>>PAGE_SHIFT)) {
1244 //Handle frame across multiple pages:
1245 netvscPacket->PageBuffers[0].Length =
1246 (netvscPacket->PageBuffers[0].Pfn <<PAGE_SHIFT) + PAGE_SIZE - start;
1247 bytesRemain = netvscPacket->TotalDataBufferLength - netvscPacket->PageBuffers[0].Length;
1248 for (j=1; j<NETVSC_PACKET_MAXPAGE; j++) {
1249 netvscPacket->PageBuffers[j].Offset = 0;
1250 if (bytesRemain <= PAGE_SIZE) {
1251 netvscPacket->PageBuffers[j].Length = bytesRemain;
1252 bytesRemain = 0;
1253 } else {
1254 netvscPacket->PageBuffers[j].Length = PAGE_SIZE;
1255 bytesRemain -= PAGE_SIZE;
1257 netvscPacket->PageBuffers[j].Pfn =
1258 GetPhysicalAddress((void*)(endVirtual - bytesRemain)) >> PAGE_SHIFT;
1259 netvscPacket->PageBufferCount++;
1260 if (bytesRemain == 0)
1261 break;
1263 ASSERT(bytesRemain == 0);
1265 DPRINT_DBG(NETVSC, "[%d] - (abs offset %u len %u) => (pfn %llx, offset %u, len %u)",
1267 vmxferpagePacket->Ranges[i].ByteOffset,
1268 vmxferpagePacket->Ranges[i].ByteCount,
1269 netvscPacket->PageBuffers[0].Pfn,
1270 netvscPacket->PageBuffers[0].Offset,
1271 netvscPacket->PageBuffers[0].Length);
1273 // Pass it to the upper layer
1274 ((NETVSC_DRIVER_OBJECT*)Device->Driver)->OnReceiveCallback(Device, netvscPacket);
1276 NetVscOnReceiveCompletion(netvscPacket->Completion.Recv.ReceiveCompletionContext);
1279 ASSERT(IsListEmpty(&listHead));
1281 PutNetDevice(Device);
1282 DPRINT_EXIT(NETVSC);
1286 static void
1287 NetVscSendReceiveCompletion(
1288 DEVICE_OBJECT *Device,
1289 u64 TransactionId
1292 NVSP_MESSAGE recvcompMessage;
1293 int retries=0;
1294 int ret=0;
1296 DPRINT_DBG(NETVSC, "Sending receive completion pkt - %llx", TransactionId);
1298 recvcompMessage.Header.MessageType = NvspMessage1TypeSendRNDISPacketComplete;
1300 // FIXME: Pass in the status
1301 recvcompMessage.Messages.Version1Messages.SendRNDISPacketComplete.Status = NvspStatusSuccess;
1303 retry_send_cmplt:
1304 // Send the completion
1305 ret = Device->Driver->VmbusChannelInterface.SendPacket(Device,
1306 &recvcompMessage,
1307 sizeof(NVSP_MESSAGE),
1308 TransactionId,
1309 VmbusPacketTypeCompletion,
1311 if (ret == 0) // success
1313 // no-op
1315 else if (ret == -1) // no more room...wait a bit and attempt to retry 3 times
1317 retries++;
1318 DPRINT_ERR(NETVSC, "unable to send receive completion pkt (tid %llx)...retrying %d", TransactionId, retries);
1320 if (retries < 4)
1322 udelay(100);
1323 goto retry_send_cmplt;
1325 else
1327 DPRINT_ERR(NETVSC, "unable to send receive completion pkt (tid %llx)...give up retrying", TransactionId);
1330 else
1332 DPRINT_ERR(NETVSC, "unable to send receive completion pkt - %llx", TransactionId);
1337 // Send a receive completion packet to RNDIS device (ie NetVsp)
1339 static void
1340 NetVscOnReceiveCompletion(
1341 void * Context)
1343 NETVSC_PACKET *packet = (NETVSC_PACKET*)Context;
1344 DEVICE_OBJECT *device = (DEVICE_OBJECT*)packet->Device;
1345 NETVSC_DEVICE* netDevice;
1346 u64 transactionId=0;
1347 bool fSendReceiveComp = false;
1348 unsigned long flags;
1350 DPRINT_ENTER(NETVSC);
1352 ASSERT(packet->XferPagePacket);
1354 // Even though it seems logical to do a GetOutboundNetDevice() here to send out receive completion,
1355 // we are using GetInboundNetDevice() since we may have disable outbound traffic already.
1356 netDevice = GetInboundNetDevice(device);
1357 if (!netDevice)
1359 DPRINT_ERR(NETVSC, "unable to get net device...device being destroyed?");
1360 DPRINT_EXIT(NETVSC);
1361 return;
1364 // Overloading use of the lock.
1365 spin_lock_irqsave(&netDevice->receive_packet_list_lock, flags);
1367 ASSERT(packet->XferPagePacket->Count > 0);
1368 packet->XferPagePacket->Count--;
1370 // Last one in the line that represent 1 xfer page packet.
1371 // Return the xfer page packet itself to the freelist
1372 if (packet->XferPagePacket->Count == 0)
1374 fSendReceiveComp = true;
1375 transactionId = packet->Completion.Recv.ReceiveCompletionTid;
1377 INSERT_TAIL_LIST(&netDevice->ReceivePacketList, &packet->XferPagePacket->ListEntry);
1380 // Put the packet back
1381 INSERT_TAIL_LIST(&netDevice->ReceivePacketList, &packet->ListEntry);
1382 spin_unlock_irqrestore(&netDevice->receive_packet_list_lock, flags);
1384 // Send a receive completion for the xfer page packet
1385 if (fSendReceiveComp)
1387 NetVscSendReceiveCompletion(device, transactionId);
1390 PutNetDevice(device);
1391 DPRINT_EXIT(NETVSC);
1396 void
1397 NetVscOnChannelCallback(
1398 void * Context
1401 const int netPacketSize=2048;
1402 int ret=0;
1403 DEVICE_OBJECT *device=(DEVICE_OBJECT*)Context;
1404 NETVSC_DEVICE *netDevice;
1406 u32 bytesRecvd;
1407 u64 requestId;
1408 unsigned char packet[netPacketSize];
1409 VMPACKET_DESCRIPTOR *desc;
1410 unsigned char *buffer=packet;
1411 int bufferlen=netPacketSize;
1414 DPRINT_ENTER(NETVSC);
1416 ASSERT(device);
1418 netDevice = GetInboundNetDevice(device);
1419 if (!netDevice)
1421 DPRINT_ERR(NETVSC, "net device (%p) shutting down...ignoring inbound packets", netDevice);
1422 DPRINT_EXIT(NETVSC);
1423 return;
1428 ret = device->Driver->VmbusChannelInterface.RecvPacketRaw(device,
1429 buffer,
1430 bufferlen,
1431 &bytesRecvd,
1432 &requestId);
1434 if (ret == 0)
1436 if (bytesRecvd > 0)
1438 DPRINT_DBG(NETVSC, "receive %d bytes, tid %llx", bytesRecvd, requestId);
1440 desc = (VMPACKET_DESCRIPTOR*)buffer;
1441 switch (desc->Type)
1443 case VmbusPacketTypeCompletion:
1444 NetVscOnSendCompletion(device, desc);
1445 break;
1447 case VmbusPacketTypeDataUsingTransferPages:
1448 NetVscOnReceive(device, desc);
1449 break;
1451 default:
1452 DPRINT_ERR(NETVSC, "unhandled packet type %d, tid %llx len %d\n", desc->Type, requestId, bytesRecvd);
1453 break;
1456 // reset
1457 if (bufferlen > netPacketSize)
1459 kfree(buffer);
1461 buffer = packet;
1462 bufferlen = netPacketSize;
1465 else
1467 //DPRINT_DBG(NETVSC, "nothing else to read...");
1469 // reset
1470 if (bufferlen > netPacketSize)
1472 kfree(buffer);
1474 buffer = packet;
1475 bufferlen = netPacketSize;
1478 break;
1481 else if (ret == -2) // Handle large packet
1483 buffer = kmalloc(bytesRecvd, GFP_ATOMIC);
1484 if (buffer == NULL)
1486 // Try again next time around
1487 DPRINT_ERR(NETVSC, "unable to allocate buffer of size (%d)!!", bytesRecvd);
1488 break;
1491 bufferlen = bytesRecvd;
1493 else
1495 ASSERT(0);
1497 } while (1);
1499 PutNetDevice(device);
1500 DPRINT_EXIT(NETVSC);
1501 return;