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
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.
19 * Hank Janssen <hjanssen@microsoft.com>
25 #include <linux/kernel.h>
27 #include <linux/delay.h>
28 #include "include/logging.h"
30 #include "RndisFilter.h"
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}
49 DEVICE_OBJECT
*Device
,
64 NetVscOnChannelCallback(
69 NetVscInitializeSendBufferWithNetVsp(
74 NetVscInitializeReceiveBufferWithNetVsp(
79 NetVscDestroySendBuffer(
80 NETVSC_DEVICE
*NetDevice
84 NetVscDestroyReceiveBuffer(
85 NETVSC_DEVICE
*NetDevice
94 NetVscOnSendCompletion(
95 DEVICE_OBJECT
*Device
,
96 VMPACKET_DESCRIPTOR
*Packet
101 DEVICE_OBJECT
*Device
,
102 NETVSC_PACKET
*Packet
107 DEVICE_OBJECT
*Device
,
108 VMPACKET_DESCRIPTOR
*Packet
112 NetVscOnReceiveCompletion(
117 NetVscSendReceiveCompletion(
118 DEVICE_OBJECT
*Device
,
122 static inline NETVSC_DEVICE
* AllocNetDevice(DEVICE_OBJECT
*Device
)
124 NETVSC_DEVICE
*netDevice
;
126 netDevice
= kzalloc(sizeof(NETVSC_DEVICE
), GFP_KERNEL
);
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
;
139 static inline void FreeNetDevice(NETVSC_DEVICE
*Device
)
141 ASSERT(Device
->RefCount
== 0);
142 Device
->Device
->Extension
= NULL
;
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
);
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
);
183 static inline void PutNetDevice(DEVICE_OBJECT
*Device
)
185 NETVSC_DEVICE
*netDevice
;
187 netDevice
= (NETVSC_DEVICE
*)Device
->Extension
;
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
)
201 // Busy wait until the ref drop to 2, then set it to 1
202 while (InterlockedCompareExchange(&netDevice
->RefCount
, 1, 2) != 2)
210 static inline NETVSC_DEVICE
* ReleaseInboundNetDevice(DEVICE_OBJECT
*Device
)
212 NETVSC_DEVICE
*netDevice
;
214 netDevice
= (NETVSC_DEVICE
*)Device
->Extension
;
215 if (netDevice
== NULL
)
218 // Busy wait until the ref drop to 1, then set it to 0
219 while (InterlockedCompareExchange(&netDevice
->RefCount
, 0, 1) != 1)
224 Device
->Extension
= NULL
;
243 NETVSC_DRIVER_OBJECT
* driver
= (NETVSC_DRIVER_OBJECT
*)drv
;
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
);
276 NetVscInitializeReceiveBufferWithNetVsp(
277 DEVICE_OBJECT
*Device
281 NETVSC_DEVICE
*netDevice
;
282 NVSP_MESSAGE
*initPacket
;
284 DPRINT_ENTER(NETVSC
);
286 netDevice
= GetOutboundNetDevice(Device
);
289 DPRINT_ERR(NETVSC
, "unable to get net device...device being destroyed?");
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
);
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
310 ret
= Device
->Driver
->VmbusChannelInterface
.EstablishGpadl(Device
,
311 netDevice
->ReceiveBuffer
,
312 netDevice
->ReceiveBufferSize
,
313 &netDevice
->ReceiveBufferGpadlHandle
);
317 DPRINT_ERR(NETVSC
, "unable to establish receive buffer's gpadl");
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
,
337 sizeof(NVSP_MESSAGE
),
338 (unsigned long)initPacket
,
339 VmbusPacketTypeDataInBand
,
340 VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED
);
343 DPRINT_ERR(NETVSC
, "unable to send receive buffer's gpadl to netvsp");
347 WaitEventWait(netDevice
->ChannelInitEvent
);
349 // Check the response
350 if (initPacket
->Messages
.Version1Messages
.SendReceiveBufferComplete
.Status
!= NvspStatusSuccess
)
353 "Unable to complete receive buffer initialzation with NetVsp - status %d",
354 initPacket
->Messages
.Version1Messages
.SendReceiveBufferComplete
.Status
);
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
)
372 memcpy(netDevice
->ReceiveSections
,
373 initPacket
->Messages
.Version1Messages
.SendReceiveBufferComplete
.Sections
,
374 netDevice
->ReceiveSectionCount
* sizeof(NVSP_1_RECEIVE_BUFFER_SECTION
));
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 )
393 NetVscDestroyReceiveBuffer(netDevice
);
396 PutNetDevice(Device
);
403 NetVscInitializeSendBufferWithNetVsp(
404 DEVICE_OBJECT
*Device
408 NETVSC_DEVICE
*netDevice
;
409 NVSP_MESSAGE
*initPacket
;
411 DPRINT_ENTER(NETVSC
);
413 netDevice
= GetOutboundNetDevice(Device
);
416 DPRINT_ERR(NETVSC
, "unable to get net device...device being destroyed?");
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
);
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
437 ret
= Device
->Driver
->VmbusChannelInterface
.EstablishGpadl(Device
,
438 netDevice
->SendBuffer
,
439 netDevice
->SendBufferSize
,
440 &netDevice
->SendBufferGpadlHandle
);
444 DPRINT_ERR(NETVSC
, "unable to establish send buffer's gpadl");
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
,
464 sizeof(NVSP_MESSAGE
),
465 (unsigned long)initPacket
,
466 VmbusPacketTypeDataInBand
,
467 VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED
);
470 DPRINT_ERR(NETVSC
, "unable to send receive buffer's gpadl to netvsp");
474 WaitEventWait(netDevice
->ChannelInitEvent
);
476 // Check the response
477 if (initPacket
->Messages
.Version1Messages
.SendSendBufferComplete
.Status
!= NvspStatusSuccess
)
480 "Unable to complete send buffer initialzation with NetVsp - status %d",
481 initPacket
->Messages
.Version1Messages
.SendSendBufferComplete
.Status
);
486 netDevice
->SendSectionSize
= initPacket
->Messages
.Version1Messages
.SendSendBufferComplete
.SectionSize
;
491 NetVscDestroySendBuffer(netDevice
);
494 PutNetDevice(Device
);
500 NetVscDestroyReceiveBuffer(
501 NETVSC_DEVICE
*NetDevice
504 NVSP_MESSAGE
*revokePacket
;
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
,
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
532 DPRINT_ERR(NETVSC
, "unable to send revoke receive buffer to netvsp");
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
549 DPRINT_ERR(NETVSC
, "unable to teardown receive buffer's gpadl");
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;
581 NetVscDestroySendBuffer(
582 NETVSC_DEVICE
*NetDevice
585 NVSP_MESSAGE
*revokePacket
;
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
,
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
613 DPRINT_ERR(NETVSC
, "unable to send revoke send buffer to netvsp");
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
630 DPRINT_ERR(NETVSC
, "unable to teardown send buffer's gpadl");
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
;
655 DEVICE_OBJECT
*Device
659 NETVSC_DEVICE
*netDevice
;
660 NVSP_MESSAGE
*initPacket
;
663 DPRINT_ENTER(NETVSC
);
665 netDevice
= GetOutboundNetDevice(Device
);
668 DPRINT_ERR(NETVSC
, "unable to get net device...device being destroyed?");
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
,
685 sizeof(NVSP_MESSAGE
),
686 (unsigned long)initPacket
,
687 VmbusPacketTypeDataInBand
,
688 VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED
);
692 DPRINT_ERR(NETVSC
, "unable to send NvspMessageTypeInit");
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
);
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
);
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
,
732 sizeof(NVSP_MESSAGE
),
733 (unsigned long)initPacket
,
734 VmbusPacketTypeDataInBand
,
738 DPRINT_ERR(NETVSC
, "unable to send NvspMessage1TypeSendNdisVersion");
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
);
751 ret
= NetVscInitializeSendBufferWithNetVsp(Device
);
755 PutNetDevice(Device
);
761 NetVscDisconnectFromVsp(
762 NETVSC_DEVICE
*NetDevice
765 DPRINT_ENTER(NETVSC
);
767 NetVscDestroyReceiveBuffer(NetDevice
);
768 NetVscDestroySendBuffer(NetDevice
);
780 Callback when the device belonging to this driver is added
785 DEVICE_OBJECT
*Device
,
792 NETVSC_DEVICE
* netDevice
;
793 NETVSC_PACKET
* packet
;
796 NETVSC_DRIVER_OBJECT
*netDriver
= (NETVSC_DRIVER_OBJECT
*) Device
->Driver
;;
798 DPRINT_ENTER(NETVSC
);
800 netDevice
= AllocNetDevice(Device
);
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
);
822 DPRINT_DBG(NETVSC
, "unable to allocate netvsc pkts for receive pool (wanted %d got %d)", NETVSC_RECEIVE_PACKETLIST_COUNT
, i
);
826 INSERT_TAIL_LIST(&netDevice
->ReceivePacketList
, &packet
->ListEntry
);
828 netDevice
->ChannelInitEvent
= WaitEventCreate();
831 ret
= Device
->Driver
->VmbusChannelInterface
.Open(Device
,
832 netDriver
->RingBufferSize
,
833 netDriver
->RingBufferSize
,
835 NetVscOnChannelCallback
,
841 DPRINT_ERR(NETVSC
, "unable to open channel: %d", ret
);
847 DPRINT_INFO(NETVSC
, "*** NetVSC channel opened successfully! ***");
849 // Connect with the NetVsp
850 ret
= NetVscConnectToVsp(Device
);
853 DPRINT_ERR(NETVSC
, "unable to connect to NetVSP - %d", ret
);
858 DPRINT_INFO(NETVSC
, "*** NetVSC channel handshake result - %d ***", ret
);
864 // Now, we can close the channel safely
865 Device
->Driver
->VmbusChannelInterface
.Close(Device
);
871 WaitEventClose(netDevice
->ChannelInitEvent
);
873 while (!IsListEmpty(&netDevice
->ReceivePacketList
))
875 entry
= REMOVE_HEAD_LIST(&netDevice
->ReceivePacketList
);
876 packet
= CONTAINING_RECORD(entry
, NETVSC_PACKET
, ListEntry
);
880 ReleaseOutboundNetDevice(Device
);
881 ReleaseInboundNetDevice(Device
);
883 FreeNetDevice(netDevice
);
894 NetVscOnDeviceRemove()
897 Callback when the root bus device is removed
901 NetVscOnDeviceRemove(
902 DEVICE_OBJECT
*Device
905 NETVSC_DEVICE
*netDevice
;
906 NETVSC_PACKET
*netvscPacket
;
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
);
918 DPRINT_ERR(NETVSC
, "No net device present!!");
922 // Wait for all send completions
923 while (netDevice
->NumOutstandingSends
)
925 DPRINT_INFO(NETVSC
, "waiting for %d requests to complete...", netDevice
->NumOutstandingSends
);
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
);
954 WaitEventClose(netDevice
->ChannelInitEvent
);
955 FreeNetDevice(netDevice
);
969 Perform any cleanup when the driver is removed
977 DPRINT_ENTER(NETVSC
);
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
);
997 DPRINT_ERR(NETVSC
, "unable to get net device...device being destroyed?");
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
;
1020 // Notify the layer above us
1021 nvscPacket
->Completion
.Send
.OnSendCompletion(nvscPacket
->Completion
.Send
.SendCompletionContext
);
1023 InterlockedDecrement(&netDevice
->NumOutstandingSends
);
1027 DPRINT_ERR(NETVSC
, "Unknown send completion packet type - %d received!!", nvspPacket
->Header
.MessageType
);
1030 PutNetDevice(Device
);
1031 DPRINT_EXIT(NETVSC
);
1038 DEVICE_OBJECT
*Device
,
1039 NETVSC_PACKET
*Packet
1042 NETVSC_DEVICE
* netDevice
;
1045 NVSP_MESSAGE sendMessage
;
1047 DPRINT_ENTER(NETVSC
);
1049 netDevice
= GetOutboundNetDevice(Device
);
1052 DPRINT_ERR(NETVSC
, "net device (%p) shutting down...ignoring outbound packets", netDevice
);
1053 DPRINT_EXIT(NETVSC
);
1057 sendMessage
.Header
.MessageType
= NvspMessage1TypeSendRNDISPacket
;
1058 if (Packet
->IsDataPacket
)
1059 sendMessage
.Messages
.Version1Messages
.SendRNDISPacket
.ChannelType
= 0;// 0 is RMC_DATA;
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
,
1073 sizeof(NVSP_MESSAGE
),
1074 (unsigned long)Packet
);
1078 ret
= Device
->Driver
->VmbusChannelInterface
.SendPacket(Device
,
1080 sizeof(NVSP_MESSAGE
),
1081 (unsigned long)Packet
,
1082 VmbusPacketTypeDataInBand
,
1083 VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED
);
1089 DPRINT_ERR(NETVSC
, "Unable to send packet %p ret %d", Packet
, ret
);
1092 InterlockedIncrement(&netDevice
->NumOutstandingSends
);
1093 PutNetDevice(Device
);
1095 DPRINT_EXIT(NETVSC
);
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
;
1111 unsigned long start
;
1112 unsigned long end
, endVirtual
;
1113 //NETVSC_DRIVER_OBJECT *netvscDriver;
1114 XFERPAGE_PACKET
*xferpagePacket
=NULL
;
1115 LIST_ENTRY listHead
;
1118 int count
=0, bytesRemain
=0;
1119 unsigned long flags
;
1121 DPRINT_ENTER(NETVSC
);
1123 netDevice
= GetInboundNetDevice(Device
);
1126 DPRINT_ERR(NETVSC
, "unable to get net device...device being destroyed?");
1127 DPRINT_EXIT(NETVSC
);
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
);
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
);
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
);
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)
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...
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
);
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
;
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)
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
);
1287 NetVscSendReceiveCompletion(
1288 DEVICE_OBJECT
*Device
,
1292 NVSP_MESSAGE recvcompMessage
;
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
;
1304 // Send the completion
1305 ret
= Device
->Driver
->VmbusChannelInterface
.SendPacket(Device
,
1307 sizeof(NVSP_MESSAGE
),
1309 VmbusPacketTypeCompletion
,
1311 if (ret
== 0) // success
1315 else if (ret
== -1) // no more room...wait a bit and attempt to retry 3 times
1318 DPRINT_ERR(NETVSC
, "unable to send receive completion pkt (tid %llx)...retrying %d", TransactionId
, retries
);
1323 goto retry_send_cmplt
;
1327 DPRINT_ERR(NETVSC
, "unable to send receive completion pkt (tid %llx)...give up retrying", TransactionId
);
1332 DPRINT_ERR(NETVSC
, "unable to send receive completion pkt - %llx", TransactionId
);
1337 // Send a receive completion packet to RNDIS device (ie NetVsp)
1340 NetVscOnReceiveCompletion(
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
);
1359 DPRINT_ERR(NETVSC
, "unable to get net device...device being destroyed?");
1360 DPRINT_EXIT(NETVSC
);
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
);
1397 NetVscOnChannelCallback(
1401 const int netPacketSize
=2048;
1403 DEVICE_OBJECT
*device
=(DEVICE_OBJECT
*)Context
;
1404 NETVSC_DEVICE
*netDevice
;
1408 unsigned char packet
[netPacketSize
];
1409 VMPACKET_DESCRIPTOR
*desc
;
1410 unsigned char *buffer
=packet
;
1411 int bufferlen
=netPacketSize
;
1414 DPRINT_ENTER(NETVSC
);
1418 netDevice
= GetInboundNetDevice(device
);
1421 DPRINT_ERR(NETVSC
, "net device (%p) shutting down...ignoring inbound packets", netDevice
);
1422 DPRINT_EXIT(NETVSC
);
1428 ret
= device
->Driver
->VmbusChannelInterface
.RecvPacketRaw(device
,
1438 DPRINT_DBG(NETVSC
, "receive %d bytes, tid %llx", bytesRecvd
, requestId
);
1440 desc
= (VMPACKET_DESCRIPTOR
*)buffer
;
1443 case VmbusPacketTypeCompletion
:
1444 NetVscOnSendCompletion(device
, desc
);
1447 case VmbusPacketTypeDataUsingTransferPages
:
1448 NetVscOnReceive(device
, desc
);
1452 DPRINT_ERR(NETVSC
, "unhandled packet type %d, tid %llx len %d\n", desc
->Type
, requestId
, bytesRecvd
);
1457 if (bufferlen
> netPacketSize
)
1462 bufferlen
= netPacketSize
;
1467 //DPRINT_DBG(NETVSC, "nothing else to read...");
1470 if (bufferlen
> netPacketSize
)
1475 bufferlen
= netPacketSize
;
1481 else if (ret
== -2) // Handle large packet
1483 buffer
= kmalloc(bytesRecvd
, GFP_ATOMIC
);
1486 // Try again next time around
1487 DPRINT_ERR(NETVSC
, "unable to allocate buffer of size (%d)!!", bytesRecvd
);
1491 bufferlen
= bytesRecvd
;
1499 PutNetDevice(device
);
1500 DPRINT_EXIT(NETVSC
);