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>
23 #include <linux/kernel.h>
25 #include <linux/delay.h>
26 #include "include/logging.h"
28 #include "RndisFilter.h"
32 static const char* gDriverName
="netvsc";
34 /* {F8615163-DF3E-46c5-913F-F2D2F965ED0E} */
35 static const GUID gNetVscDeviceType
={
36 .Data
= {0x63, 0x51, 0x61, 0xF8, 0x3E, 0xDF, 0xc5, 0x46, 0x91, 0x3F, 0xF2, 0xD2, 0xF9, 0x65, 0xED, 0x0E}
40 /* Internal routines */
43 struct hv_device
*Device
,
49 struct hv_device
*Device
54 struct hv_driver
*Driver
58 NetVscOnChannelCallback(
63 NetVscInitializeSendBufferWithNetVsp(
64 struct hv_device
*Device
68 NetVscInitializeReceiveBufferWithNetVsp(
69 struct hv_device
*Device
73 NetVscDestroySendBuffer(
74 struct NETVSC_DEVICE
*NetDevice
78 NetVscDestroyReceiveBuffer(
79 struct NETVSC_DEVICE
*NetDevice
84 struct hv_device
*Device
88 NetVscOnSendCompletion(
89 struct hv_device
*Device
,
90 VMPACKET_DESCRIPTOR
*Packet
95 struct hv_device
*Device
,
96 struct hv_netvsc_packet
*Packet
101 struct hv_device
*Device
,
102 VMPACKET_DESCRIPTOR
*Packet
106 NetVscOnReceiveCompletion(
111 NetVscSendReceiveCompletion(
112 struct hv_device
*Device
,
116 static inline struct NETVSC_DEVICE
*AllocNetDevice(struct hv_device
*Device
)
118 struct NETVSC_DEVICE
*netDevice
;
120 netDevice
= kzalloc(sizeof(struct NETVSC_DEVICE
), GFP_KERNEL
);
124 /* Set to 2 to allow both inbound and outbound traffic */
125 InterlockedCompareExchange(&netDevice
->RefCount
, 2, 0);
127 netDevice
->Device
= Device
;
128 Device
->Extension
= netDevice
;
133 static inline void FreeNetDevice(struct NETVSC_DEVICE
*Device
)
135 ASSERT(Device
->RefCount
== 0);
136 Device
->Device
->Extension
= NULL
;
141 /* Get the net device object iff exists and its refcount > 1 */
142 static inline struct NETVSC_DEVICE
*GetOutboundNetDevice(struct hv_device
*Device
)
144 struct NETVSC_DEVICE
*netDevice
;
146 netDevice
= (struct NETVSC_DEVICE
*)Device
->Extension
;
147 if (netDevice
&& netDevice
->RefCount
> 1)
149 InterlockedIncrement(&netDevice
->RefCount
);
159 /* Get the net device object iff exists and its refcount > 0 */
160 static inline struct NETVSC_DEVICE
*GetInboundNetDevice(struct hv_device
*Device
)
162 struct NETVSC_DEVICE
*netDevice
;
164 netDevice
= (struct NETVSC_DEVICE
*)Device
->Extension
;
165 if (netDevice
&& netDevice
->RefCount
)
167 InterlockedIncrement(&netDevice
->RefCount
);
177 static inline void PutNetDevice(struct hv_device
*Device
)
179 struct NETVSC_DEVICE
*netDevice
;
181 netDevice
= (struct NETVSC_DEVICE
*)Device
->Extension
;
184 InterlockedDecrement(&netDevice
->RefCount
);
187 static inline struct NETVSC_DEVICE
*ReleaseOutboundNetDevice(struct hv_device
*Device
)
189 struct NETVSC_DEVICE
*netDevice
;
191 netDevice
= (struct NETVSC_DEVICE
*)Device
->Extension
;
192 if (netDevice
== NULL
)
195 /* Busy wait until the ref drop to 2, then set it to 1 */
196 while (InterlockedCompareExchange(&netDevice
->RefCount
, 1, 2) != 2)
204 static inline struct NETVSC_DEVICE
*ReleaseInboundNetDevice(struct hv_device
*Device
)
206 struct NETVSC_DEVICE
*netDevice
;
208 netDevice
= (struct NETVSC_DEVICE
*)Device
->Extension
;
209 if (netDevice
== NULL
)
212 /* Busy wait until the ref drop to 1, then set it to 0 */
213 while (InterlockedCompareExchange(&netDevice
->RefCount
, 0, 1) != 1)
218 Device
->Extension
= NULL
;
234 struct hv_driver
*drv
237 NETVSC_DRIVER_OBJECT
* driver
= (NETVSC_DRIVER_OBJECT
*)drv
;
240 DPRINT_ENTER(NETVSC
);
242 DPRINT_DBG(NETVSC
, "sizeof(struct hv_netvsc_packet)=%zd, sizeof(NVSP_MESSAGE)=%zd, sizeof(VMTRANSFER_PAGE_PACKET_HEADER)=%zd",
243 sizeof(struct hv_netvsc_packet
), sizeof(NVSP_MESSAGE
), sizeof(VMTRANSFER_PAGE_PACKET_HEADER
));
245 /* Make sure we are at least 2 pages since 1 page is used for control */
246 ASSERT(driver
->RingBufferSize
>= (PAGE_SIZE
<< 1));
248 drv
->name
= gDriverName
;
249 memcpy(&drv
->deviceType
, &gNetVscDeviceType
, sizeof(GUID
));
251 /* Make sure it is set by the caller */
252 ASSERT(driver
->OnReceiveCallback
);
253 ASSERT(driver
->OnLinkStatusChanged
);
255 /* Setup the dispatch table */
256 driver
->Base
.OnDeviceAdd
= NetVscOnDeviceAdd
;
257 driver
->Base
.OnDeviceRemove
= NetVscOnDeviceRemove
;
258 driver
->Base
.OnCleanup
= NetVscOnCleanup
;
260 driver
->OnSend
= NetVscOnSend
;
262 RndisFilterInit(driver
);
270 NetVscInitializeReceiveBufferWithNetVsp(
271 struct hv_device
*Device
275 struct NETVSC_DEVICE
*netDevice
;
276 NVSP_MESSAGE
*initPacket
;
278 DPRINT_ENTER(NETVSC
);
280 netDevice
= GetOutboundNetDevice(Device
);
283 DPRINT_ERR(NETVSC
, "unable to get net device...device being destroyed?");
287 ASSERT(netDevice
->ReceiveBufferSize
> 0);
288 ASSERT((netDevice
->ReceiveBufferSize
& (PAGE_SIZE
-1)) == 0); /* page-size grandularity */
290 netDevice
->ReceiveBuffer
= PageAlloc(netDevice
->ReceiveBufferSize
>> PAGE_SHIFT
);
291 if (!netDevice
->ReceiveBuffer
)
293 DPRINT_ERR(NETVSC
, "unable to allocate receive buffer of size %d", netDevice
->ReceiveBufferSize
);
297 ASSERT(((unsigned long)netDevice
->ReceiveBuffer
& (PAGE_SIZE
-1)) == 0); /* page-aligned buffer */
299 DPRINT_INFO(NETVSC
, "Establishing receive buffer's GPADL...");
302 * Establish the gpadl handle for this buffer on this
303 * channel. Note: This call uses the vmbus connection rather
304 * than the channel to establish the gpadl handle.
306 ret
= Device
->Driver
->VmbusChannelInterface
.EstablishGpadl(Device
,
307 netDevice
->ReceiveBuffer
,
308 netDevice
->ReceiveBufferSize
,
309 &netDevice
->ReceiveBufferGpadlHandle
);
313 DPRINT_ERR(NETVSC
, "unable to establish receive buffer's gpadl");
317 /* WaitEventWait(ext->ChannelInitEvent); */
319 /* Notify the NetVsp of the gpadl handle */
320 DPRINT_INFO(NETVSC
, "Sending NvspMessage1TypeSendReceiveBuffer...");
322 initPacket
= &netDevice
->ChannelInitPacket
;
324 memset(initPacket
, 0, sizeof(NVSP_MESSAGE
));
326 initPacket
->Header
.MessageType
= NvspMessage1TypeSendReceiveBuffer
;
327 initPacket
->Messages
.Version1Messages
.SendReceiveBuffer
.GpadlHandle
= netDevice
->ReceiveBufferGpadlHandle
;
328 initPacket
->Messages
.Version1Messages
.SendReceiveBuffer
.Id
= NETVSC_RECEIVE_BUFFER_ID
;
330 /* Send the gpadl notification request */
331 ret
= Device
->Driver
->VmbusChannelInterface
.SendPacket(Device
,
333 sizeof(NVSP_MESSAGE
),
334 (unsigned long)initPacket
,
335 VmbusPacketTypeDataInBand
,
336 VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED
);
339 DPRINT_ERR(NETVSC
, "unable to send receive buffer's gpadl to netvsp");
343 WaitEventWait(netDevice
->ChannelInitEvent
);
345 /* Check the response */
346 if (initPacket
->Messages
.Version1Messages
.SendReceiveBufferComplete
.Status
!= NvspStatusSuccess
)
349 "Unable to complete receive buffer initialzation with NetVsp - status %d",
350 initPacket
->Messages
.Version1Messages
.SendReceiveBufferComplete
.Status
);
355 /* Parse the response */
356 ASSERT(netDevice
->ReceiveSectionCount
== 0);
357 ASSERT(netDevice
->ReceiveSections
== NULL
);
359 netDevice
->ReceiveSectionCount
= initPacket
->Messages
.Version1Messages
.SendReceiveBufferComplete
.NumSections
;
361 netDevice
->ReceiveSections
= kmalloc(netDevice
->ReceiveSectionCount
* sizeof(NVSP_1_RECEIVE_BUFFER_SECTION
), GFP_KERNEL
);
362 if (netDevice
->ReceiveSections
== NULL
)
368 memcpy(netDevice
->ReceiveSections
,
369 initPacket
->Messages
.Version1Messages
.SendReceiveBufferComplete
.Sections
,
370 netDevice
->ReceiveSectionCount
* sizeof(NVSP_1_RECEIVE_BUFFER_SECTION
));
373 "Receive sections info (count %d, offset %d, endoffset %d, suballoc size %d, num suballocs %d)",
374 netDevice
->ReceiveSectionCount
, netDevice
->ReceiveSections
[0].Offset
, netDevice
->ReceiveSections
[0].EndOffset
,
375 netDevice
->ReceiveSections
[0].SubAllocationSize
, netDevice
->ReceiveSections
[0].NumSubAllocations
);
378 /* For 1st release, there should only be 1 section that represents the entire receive buffer */
379 if (netDevice
->ReceiveSectionCount
!= 1 ||
380 netDevice
->ReceiveSections
->Offset
!= 0 )
389 NetVscDestroyReceiveBuffer(netDevice
);
392 PutNetDevice(Device
);
399 NetVscInitializeSendBufferWithNetVsp(
400 struct hv_device
*Device
404 struct NETVSC_DEVICE
*netDevice
;
405 NVSP_MESSAGE
*initPacket
;
407 DPRINT_ENTER(NETVSC
);
409 netDevice
= GetOutboundNetDevice(Device
);
412 DPRINT_ERR(NETVSC
, "unable to get net device...device being destroyed?");
416 ASSERT(netDevice
->SendBufferSize
> 0);
417 ASSERT((netDevice
->SendBufferSize
& (PAGE_SIZE
-1)) == 0); /* page-size grandularity */
419 netDevice
->SendBuffer
= PageAlloc(netDevice
->SendBufferSize
>> PAGE_SHIFT
);
420 if (!netDevice
->SendBuffer
)
422 DPRINT_ERR(NETVSC
, "unable to allocate send buffer of size %d", netDevice
->SendBufferSize
);
426 ASSERT(((unsigned long)netDevice
->SendBuffer
& (PAGE_SIZE
-1)) == 0); /* page-aligned buffer */
428 DPRINT_INFO(NETVSC
, "Establishing send buffer's GPADL...");
431 * Establish the gpadl handle for this buffer on this
432 * channel. Note: This call uses the vmbus connection rather
433 * than the channel to establish the gpadl handle.
435 ret
= Device
->Driver
->VmbusChannelInterface
.EstablishGpadl(Device
,
436 netDevice
->SendBuffer
,
437 netDevice
->SendBufferSize
,
438 &netDevice
->SendBufferGpadlHandle
);
442 DPRINT_ERR(NETVSC
, "unable to establish send buffer's gpadl");
446 /* WaitEventWait(ext->ChannelInitEvent); */
448 /* Notify the NetVsp of the gpadl handle */
449 DPRINT_INFO(NETVSC
, "Sending NvspMessage1TypeSendSendBuffer...");
451 initPacket
= &netDevice
->ChannelInitPacket
;
453 memset(initPacket
, 0, sizeof(NVSP_MESSAGE
));
455 initPacket
->Header
.MessageType
= NvspMessage1TypeSendSendBuffer
;
456 initPacket
->Messages
.Version1Messages
.SendReceiveBuffer
.GpadlHandle
= netDevice
->SendBufferGpadlHandle
;
457 initPacket
->Messages
.Version1Messages
.SendReceiveBuffer
.Id
= NETVSC_SEND_BUFFER_ID
;
459 /* Send the gpadl notification request */
460 ret
= Device
->Driver
->VmbusChannelInterface
.SendPacket(Device
,
462 sizeof(NVSP_MESSAGE
),
463 (unsigned long)initPacket
,
464 VmbusPacketTypeDataInBand
,
465 VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED
);
468 DPRINT_ERR(NETVSC
, "unable to send receive buffer's gpadl to netvsp");
472 WaitEventWait(netDevice
->ChannelInitEvent
);
474 /* Check the response */
475 if (initPacket
->Messages
.Version1Messages
.SendSendBufferComplete
.Status
!= NvspStatusSuccess
)
478 "Unable to complete send buffer initialzation with NetVsp - status %d",
479 initPacket
->Messages
.Version1Messages
.SendSendBufferComplete
.Status
);
484 netDevice
->SendSectionSize
= initPacket
->Messages
.Version1Messages
.SendSendBufferComplete
.SectionSize
;
489 NetVscDestroySendBuffer(netDevice
);
492 PutNetDevice(Device
);
498 NetVscDestroyReceiveBuffer(
499 struct NETVSC_DEVICE
*NetDevice
502 NVSP_MESSAGE
*revokePacket
;
506 DPRINT_ENTER(NETVSC
);
509 * If we got a section count, it means we received a
510 * SendReceiveBufferComplete msg (ie sent
511 * NvspMessage1TypeSendReceiveBuffer msg) therefore, we need
512 * to send a revoke msg here
514 if (NetDevice
->ReceiveSectionCount
)
516 DPRINT_INFO(NETVSC
, "Sending NvspMessage1TypeRevokeReceiveBuffer...");
518 /* Send the revoke receive buffer */
519 revokePacket
= &NetDevice
->RevokePacket
;
520 memset(revokePacket
, 0, sizeof(NVSP_MESSAGE
));
522 revokePacket
->Header
.MessageType
= NvspMessage1TypeRevokeReceiveBuffer
;
523 revokePacket
->Messages
.Version1Messages
.RevokeReceiveBuffer
.Id
= NETVSC_RECEIVE_BUFFER_ID
;
525 ret
= NetDevice
->Device
->Driver
->VmbusChannelInterface
.SendPacket(NetDevice
->Device
,
527 sizeof(NVSP_MESSAGE
),
528 (unsigned long)revokePacket
,
529 VmbusPacketTypeDataInBand
,
532 * If we failed here, we might as well return and
533 * have a leak rather than continue and a bugchk
537 DPRINT_ERR(NETVSC
, "unable to send revoke receive buffer to netvsp");
543 /* Teardown the gpadl on the vsp end */
544 if (NetDevice
->ReceiveBufferGpadlHandle
)
546 DPRINT_INFO(NETVSC
, "Tearing down receive buffer's GPADL...");
548 ret
= NetDevice
->Device
->Driver
->VmbusChannelInterface
.TeardownGpadl(NetDevice
->Device
,
549 NetDevice
->ReceiveBufferGpadlHandle
);
551 /* If we failed here, we might as well return and have a leak rather than continue and a bugchk */
554 DPRINT_ERR(NETVSC
, "unable to teardown receive buffer's gpadl");
558 NetDevice
->ReceiveBufferGpadlHandle
= 0;
561 if (NetDevice
->ReceiveBuffer
)
563 DPRINT_INFO(NETVSC
, "Freeing up receive buffer...");
565 /* Free up the receive buffer */
566 PageFree(NetDevice
->ReceiveBuffer
, NetDevice
->ReceiveBufferSize
>> PAGE_SHIFT
);
567 NetDevice
->ReceiveBuffer
= NULL
;
570 if (NetDevice
->ReceiveSections
)
572 kfree(NetDevice
->ReceiveSections
);
573 NetDevice
->ReceiveSections
= NULL
;
574 NetDevice
->ReceiveSectionCount
= 0;
586 NetVscDestroySendBuffer(
587 struct NETVSC_DEVICE
*NetDevice
590 NVSP_MESSAGE
*revokePacket
;
594 DPRINT_ENTER(NETVSC
);
597 * If we got a section count, it means we received a
598 * SendReceiveBufferComplete msg (ie sent
599 * NvspMessage1TypeSendReceiveBuffer msg) therefore, we need
600 * to send a revoke msg here
602 if (NetDevice
->SendSectionSize
)
604 DPRINT_INFO(NETVSC
, "Sending NvspMessage1TypeRevokeSendBuffer...");
606 /* Send the revoke send buffer */
607 revokePacket
= &NetDevice
->RevokePacket
;
608 memset(revokePacket
, 0, sizeof(NVSP_MESSAGE
));
610 revokePacket
->Header
.MessageType
= NvspMessage1TypeRevokeSendBuffer
;
611 revokePacket
->Messages
.Version1Messages
.RevokeSendBuffer
.Id
= NETVSC_SEND_BUFFER_ID
;
613 ret
= NetDevice
->Device
->Driver
->VmbusChannelInterface
.SendPacket(NetDevice
->Device
,
615 sizeof(NVSP_MESSAGE
),
616 (unsigned long)revokePacket
,
617 VmbusPacketTypeDataInBand
,
619 /* If we failed here, we might as well return and have a leak rather than continue and a bugchk */
622 DPRINT_ERR(NETVSC
, "unable to send revoke send buffer to netvsp");
628 /* Teardown the gpadl on the vsp end */
629 if (NetDevice
->SendBufferGpadlHandle
)
631 DPRINT_INFO(NETVSC
, "Tearing down send buffer's GPADL...");
633 ret
= NetDevice
->Device
->Driver
->VmbusChannelInterface
.TeardownGpadl(NetDevice
->Device
,
634 NetDevice
->SendBufferGpadlHandle
);
636 /* If we failed here, we might as well return and have a leak rather than continue and a bugchk */
639 DPRINT_ERR(NETVSC
, "unable to teardown send buffer's gpadl");
643 NetDevice
->SendBufferGpadlHandle
= 0;
646 if (NetDevice
->SendBuffer
)
648 DPRINT_INFO(NETVSC
, "Freeing up send buffer...");
650 /* Free up the receive buffer */
651 PageFree(NetDevice
->SendBuffer
, NetDevice
->SendBufferSize
>> PAGE_SHIFT
);
652 NetDevice
->SendBuffer
= NULL
;
664 struct hv_device
*Device
668 struct NETVSC_DEVICE
*netDevice
;
669 NVSP_MESSAGE
*initPacket
;
672 DPRINT_ENTER(NETVSC
);
674 netDevice
= GetOutboundNetDevice(Device
);
677 DPRINT_ERR(NETVSC
, "unable to get net device...device being destroyed?");
682 initPacket
= &netDevice
->ChannelInitPacket
;
684 memset(initPacket
, 0, sizeof(NVSP_MESSAGE
));
685 initPacket
->Header
.MessageType
= NvspMessageTypeInit
;
686 initPacket
->Messages
.InitMessages
.Init
.MinProtocolVersion
= NVSP_MIN_PROTOCOL_VERSION
;
687 initPacket
->Messages
.InitMessages
.Init
.MaxProtocolVersion
= NVSP_MAX_PROTOCOL_VERSION
;
689 DPRINT_INFO(NETVSC
, "Sending NvspMessageTypeInit...");
691 /* Send the init request */
692 ret
= Device
->Driver
->VmbusChannelInterface
.SendPacket(Device
,
694 sizeof(NVSP_MESSAGE
),
695 (unsigned long)initPacket
,
696 VmbusPacketTypeDataInBand
,
697 VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED
);
701 DPRINT_ERR(NETVSC
, "unable to send NvspMessageTypeInit");
705 WaitEventWait(netDevice
->ChannelInitEvent
);
707 /* Now, check the response */
708 /* ASSERT(initPacket->Messages.InitMessages.InitComplete.MaximumMdlChainLength <= MAX_MULTIPAGE_BUFFER_COUNT); */
709 DPRINT_INFO(NETVSC
, "NvspMessageTypeInit status(%d) max mdl chain (%d)",
710 initPacket
->Messages
.InitMessages
.InitComplete
.Status
,
711 initPacket
->Messages
.InitMessages
.InitComplete
.MaximumMdlChainLength
);
713 if (initPacket
->Messages
.InitMessages
.InitComplete
.Status
!= NvspStatusSuccess
)
715 DPRINT_ERR(NETVSC
, "unable to initialize with netvsp (status 0x%x)", initPacket
->Messages
.InitMessages
.InitComplete
.Status
);
720 if (initPacket
->Messages
.InitMessages
.InitComplete
.NegotiatedProtocolVersion
!= NVSP_PROTOCOL_VERSION_1
)
722 DPRINT_ERR(NETVSC
, "unable to initialize with netvsp (version expected 1 got %d)",
723 initPacket
->Messages
.InitMessages
.InitComplete
.NegotiatedProtocolVersion
);
727 DPRINT_INFO(NETVSC
, "Sending NvspMessage1TypeSendNdisVersion...");
729 /* Send the ndis version */
730 memset(initPacket
, 0, sizeof(NVSP_MESSAGE
));
732 ndisVersion
= 0x00050000;
734 initPacket
->Header
.MessageType
= NvspMessage1TypeSendNdisVersion
;
735 initPacket
->Messages
.Version1Messages
.SendNdisVersion
.NdisMajorVersion
= (ndisVersion
& 0xFFFF0000) >> 16;
736 initPacket
->Messages
.Version1Messages
.SendNdisVersion
.NdisMinorVersion
= ndisVersion
& 0xFFFF;
738 /* Send the init request */
739 ret
= Device
->Driver
->VmbusChannelInterface
.SendPacket(Device
,
741 sizeof(NVSP_MESSAGE
),
742 (unsigned long)initPacket
,
743 VmbusPacketTypeDataInBand
,
747 DPRINT_ERR(NETVSC
, "unable to send NvspMessage1TypeSendNdisVersion");
752 * BUGBUG - We have to wait for the above msg since the
753 * netvsp uses KMCL which acknowledges packet (completion
754 * packet) since our Vmbus always set the
755 * VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED flag
757 /* WaitEventWait(NetVscChannel->ChannelInitEvent); */
759 /* Post the big receive buffer to NetVSP */
760 ret
= NetVscInitializeReceiveBufferWithNetVsp(Device
);
763 ret
= NetVscInitializeSendBufferWithNetVsp(Device
);
767 PutNetDevice(Device
);
773 NetVscDisconnectFromVsp(
774 struct NETVSC_DEVICE
*NetDevice
777 DPRINT_ENTER(NETVSC
);
779 NetVscDestroyReceiveBuffer(NetDevice
);
780 NetVscDestroySendBuffer(NetDevice
);
792 Callback when the device belonging to this driver is added
797 struct hv_device
*Device
,
804 struct NETVSC_DEVICE
*netDevice
;
805 struct hv_netvsc_packet
*packet
;
808 NETVSC_DRIVER_OBJECT
*netDriver
= (NETVSC_DRIVER_OBJECT
*) Device
->Driver
;;
810 DPRINT_ENTER(NETVSC
);
812 netDevice
= AllocNetDevice(Device
);
819 DPRINT_DBG(NETVSC
, "netvsc channel object allocated - %p", netDevice
);
821 /* Initialize the NetVSC channel extension */
822 netDevice
->ReceiveBufferSize
= NETVSC_RECEIVE_BUFFER_SIZE
;
823 spin_lock_init(&netDevice
->receive_packet_list_lock
);
825 netDevice
->SendBufferSize
= NETVSC_SEND_BUFFER_SIZE
;
827 INITIALIZE_LIST_HEAD(&netDevice
->ReceivePacketList
);
829 for (i
=0; i
< NETVSC_RECEIVE_PACKETLIST_COUNT
; i
++)
831 packet
= kzalloc(sizeof(struct hv_netvsc_packet
) + (NETVSC_RECEIVE_SG_COUNT
* sizeof(PAGE_BUFFER
)), GFP_KERNEL
);
834 DPRINT_DBG(NETVSC
, "unable to allocate netvsc pkts for receive pool (wanted %d got %d)", NETVSC_RECEIVE_PACKETLIST_COUNT
, i
);
838 INSERT_TAIL_LIST(&netDevice
->ReceivePacketList
, &packet
->ListEntry
);
840 netDevice
->ChannelInitEvent
= WaitEventCreate();
842 /* Open the channel */
843 ret
= Device
->Driver
->VmbusChannelInterface
.Open(Device
,
844 netDriver
->RingBufferSize
,
845 netDriver
->RingBufferSize
,
847 NetVscOnChannelCallback
,
853 DPRINT_ERR(NETVSC
, "unable to open channel: %d", ret
);
858 /* Channel is opened */
859 DPRINT_INFO(NETVSC
, "*** NetVSC channel opened successfully! ***");
861 /* Connect with the NetVsp */
862 ret
= NetVscConnectToVsp(Device
);
865 DPRINT_ERR(NETVSC
, "unable to connect to NetVSP - %d", ret
);
870 DPRINT_INFO(NETVSC
, "*** NetVSC channel handshake result - %d ***", ret
);
876 /* Now, we can close the channel safely */
877 Device
->Driver
->VmbusChannelInterface
.Close(Device
);
883 WaitEventClose(netDevice
->ChannelInitEvent
);
885 while (!IsListEmpty(&netDevice
->ReceivePacketList
))
887 entry
= REMOVE_HEAD_LIST(&netDevice
->ReceivePacketList
);
888 packet
= CONTAINING_RECORD(entry
, struct hv_netvsc_packet
, ListEntry
);
892 ReleaseOutboundNetDevice(Device
);
893 ReleaseInboundNetDevice(Device
);
895 FreeNetDevice(netDevice
);
906 NetVscOnDeviceRemove()
909 Callback when the root bus device is removed
913 NetVscOnDeviceRemove(
914 struct hv_device
*Device
917 struct NETVSC_DEVICE
*netDevice
;
918 struct hv_netvsc_packet
*netvscPacket
;
922 DPRINT_ENTER(NETVSC
);
924 DPRINT_INFO(NETVSC
, "Disabling outbound traffic on net device (%p)...", Device
->Extension
);
926 /* Stop outbound traffic ie sends and receives completions */
927 netDevice
= ReleaseOutboundNetDevice(Device
);
930 DPRINT_ERR(NETVSC
, "No net device present!!");
934 /* Wait for all send completions */
935 while (netDevice
->NumOutstandingSends
)
937 DPRINT_INFO(NETVSC
, "waiting for %d requests to complete...", netDevice
->NumOutstandingSends
);
942 DPRINT_INFO(NETVSC
, "Disconnecting from netvsp...");
944 NetVscDisconnectFromVsp(netDevice
);
946 DPRINT_INFO(NETVSC
, "Disabling inbound traffic on net device (%p)...", Device
->Extension
);
948 /* Stop inbound traffic ie receives and sends completions */
949 netDevice
= ReleaseInboundNetDevice(Device
);
951 /* At this point, no one should be accessing netDevice except in here */
952 DPRINT_INFO(NETVSC
, "net device (%p) safe to remove", netDevice
);
954 /* Now, we can close the channel safely */
955 Device
->Driver
->VmbusChannelInterface
.Close(Device
);
957 /* Release all resources */
958 while (!IsListEmpty(&netDevice
->ReceivePacketList
))
960 entry
= REMOVE_HEAD_LIST(&netDevice
->ReceivePacketList
);
961 netvscPacket
= CONTAINING_RECORD(entry
, struct hv_netvsc_packet
, ListEntry
);
966 WaitEventClose(netDevice
->ChannelInitEvent
);
967 FreeNetDevice(netDevice
);
981 Perform any cleanup when the driver is removed
986 struct hv_driver
*drv
989 DPRINT_ENTER(NETVSC
);
995 NetVscOnSendCompletion(
996 struct hv_device
*Device
,
997 VMPACKET_DESCRIPTOR
*Packet
1000 struct NETVSC_DEVICE
*netDevice
;
1001 NVSP_MESSAGE
*nvspPacket
;
1002 struct hv_netvsc_packet
*nvscPacket
;
1004 DPRINT_ENTER(NETVSC
);
1006 netDevice
= GetInboundNetDevice(Device
);
1009 DPRINT_ERR(NETVSC
, "unable to get net device...device being destroyed?");
1010 DPRINT_EXIT(NETVSC
);
1014 nvspPacket
= (NVSP_MESSAGE
*)((unsigned long)Packet
+ (Packet
->DataOffset8
<< 3));
1016 DPRINT_DBG(NETVSC
, "send completion packet - type %d", nvspPacket
->Header
.MessageType
);
1018 if (nvspPacket
->Header
.MessageType
== NvspMessageTypeInitComplete
||
1019 nvspPacket
->Header
.MessageType
== NvspMessage1TypeSendReceiveBufferComplete
||
1020 nvspPacket
->Header
.MessageType
== NvspMessage1TypeSendSendBufferComplete
)
1022 /* Copy the response back */
1023 memcpy(&netDevice
->ChannelInitPacket
, nvspPacket
, sizeof(NVSP_MESSAGE
));
1024 WaitEventSet(netDevice
->ChannelInitEvent
);
1026 else if (nvspPacket
->Header
.MessageType
== NvspMessage1TypeSendRNDISPacketComplete
)
1028 /* Get the send context */
1029 nvscPacket
= (struct hv_netvsc_packet
*)(unsigned long)Packet
->TransactionId
;
1032 /* Notify the layer above us */
1033 nvscPacket
->Completion
.Send
.OnSendCompletion(nvscPacket
->Completion
.Send
.SendCompletionContext
);
1035 InterlockedDecrement(&netDevice
->NumOutstandingSends
);
1039 DPRINT_ERR(NETVSC
, "Unknown send completion packet type - %d received!!", nvspPacket
->Header
.MessageType
);
1042 PutNetDevice(Device
);
1043 DPRINT_EXIT(NETVSC
);
1050 struct hv_device
*Device
,
1051 struct hv_netvsc_packet
*Packet
1054 struct NETVSC_DEVICE
*netDevice
;
1057 NVSP_MESSAGE sendMessage
;
1059 DPRINT_ENTER(NETVSC
);
1061 netDevice
= GetOutboundNetDevice(Device
);
1064 DPRINT_ERR(NETVSC
, "net device (%p) shutting down...ignoring outbound packets", netDevice
);
1065 DPRINT_EXIT(NETVSC
);
1069 sendMessage
.Header
.MessageType
= NvspMessage1TypeSendRNDISPacket
;
1070 if (Packet
->IsDataPacket
)
1071 sendMessage
.Messages
.Version1Messages
.SendRNDISPacket
.ChannelType
= 0;/* 0 is RMC_DATA; */
1073 sendMessage
.Messages
.Version1Messages
.SendRNDISPacket
.ChannelType
= 1;/* 1 is RMC_CONTROL; */
1075 /* Not using send buffer section */
1076 sendMessage
.Messages
.Version1Messages
.SendRNDISPacket
.SendBufferSectionIndex
= 0xFFFFFFFF;
1077 sendMessage
.Messages
.Version1Messages
.SendRNDISPacket
.SendBufferSectionSize
= 0;
1079 if (Packet
->PageBufferCount
)
1081 ret
= Device
->Driver
->VmbusChannelInterface
.SendPacketPageBuffer(Device
,
1082 Packet
->PageBuffers
,
1083 Packet
->PageBufferCount
,
1085 sizeof(NVSP_MESSAGE
),
1086 (unsigned long)Packet
);
1090 ret
= Device
->Driver
->VmbusChannelInterface
.SendPacket(Device
,
1092 sizeof(NVSP_MESSAGE
),
1093 (unsigned long)Packet
,
1094 VmbusPacketTypeDataInBand
,
1095 VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED
);
1101 DPRINT_ERR(NETVSC
, "Unable to send packet %p ret %d", Packet
, ret
);
1104 InterlockedIncrement(&netDevice
->NumOutstandingSends
);
1105 PutNetDevice(Device
);
1107 DPRINT_EXIT(NETVSC
);
1114 struct hv_device
*Device
,
1115 VMPACKET_DESCRIPTOR
*Packet
1118 struct NETVSC_DEVICE
*netDevice
;
1119 VMTRANSFER_PAGE_PACKET_HEADER
*vmxferpagePacket
;
1120 NVSP_MESSAGE
*nvspPacket
;
1121 struct hv_netvsc_packet
*netvscPacket
=NULL
;
1123 unsigned long start
;
1124 unsigned long end
, endVirtual
;
1125 /* NETVSC_DRIVER_OBJECT *netvscDriver; */
1126 XFERPAGE_PACKET
*xferpagePacket
=NULL
;
1127 LIST_ENTRY listHead
;
1130 int count
=0, bytesRemain
=0;
1131 unsigned long flags
;
1133 DPRINT_ENTER(NETVSC
);
1135 netDevice
= GetInboundNetDevice(Device
);
1138 DPRINT_ERR(NETVSC
, "unable to get net device...device being destroyed?");
1139 DPRINT_EXIT(NETVSC
);
1143 /* All inbound packets other than send completion should be xfer page packet */
1144 if (Packet
->Type
!= VmbusPacketTypeDataUsingTransferPages
)
1146 DPRINT_ERR(NETVSC
, "Unknown packet type received - %d", Packet
->Type
);
1147 PutNetDevice(Device
);
1151 nvspPacket
= (NVSP_MESSAGE
*)((unsigned long)Packet
+ (Packet
->DataOffset8
<< 3));
1153 /* Make sure this is a valid nvsp packet */
1154 if (nvspPacket
->Header
.MessageType
!= NvspMessage1TypeSendRNDISPacket
)
1156 DPRINT_ERR(NETVSC
, "Unknown nvsp packet type received - %d", nvspPacket
->Header
.MessageType
);
1157 PutNetDevice(Device
);
1161 DPRINT_DBG(NETVSC
, "NVSP packet received - type %d", nvspPacket
->Header
.MessageType
);
1163 vmxferpagePacket
= (VMTRANSFER_PAGE_PACKET_HEADER
*)Packet
;
1165 if (vmxferpagePacket
->TransferPageSetId
!= NETVSC_RECEIVE_BUFFER_ID
)
1167 DPRINT_ERR(NETVSC
, "Invalid xfer page set id - expecting %x got %x", NETVSC_RECEIVE_BUFFER_ID
, vmxferpagePacket
->TransferPageSetId
);
1168 PutNetDevice(Device
);
1172 DPRINT_DBG(NETVSC
, "xfer page - range count %d", vmxferpagePacket
->RangeCount
);
1174 INITIALIZE_LIST_HEAD(&listHead
);
1177 * Grab free packets (range count + 1) to represent this xfer
1178 * page packet. +1 to represent the xfer page packet itself.
1179 * We grab it here so that we know exactly how many we can
1182 spin_lock_irqsave(&netDevice
->receive_packet_list_lock
, flags
);
1183 while (!IsListEmpty(&netDevice
->ReceivePacketList
))
1185 entry
= REMOVE_HEAD_LIST(&netDevice
->ReceivePacketList
);
1186 netvscPacket
= CONTAINING_RECORD(entry
, struct hv_netvsc_packet
, ListEntry
);
1188 INSERT_TAIL_LIST(&listHead
, &netvscPacket
->ListEntry
);
1190 if (++count
== vmxferpagePacket
->RangeCount
+ 1)
1193 spin_unlock_irqrestore(&netDevice
->receive_packet_list_lock
, flags
);
1196 * We need at least 2 netvsc pkts (1 to represent the xfer
1197 * page and at least 1 for the range) i.e. we can handled
1198 * some of the xfer page packet ranges...
1202 DPRINT_ERR(NETVSC
, "Got only %d netvsc pkt...needed %d pkts. Dropping this xfer page packet completely!", count
, vmxferpagePacket
->RangeCount
+1);
1204 /* Return it to the freelist */
1205 spin_lock_irqsave(&netDevice
->receive_packet_list_lock
, flags
);
1206 for (i
=count
; i
!= 0; i
--)
1208 entry
= REMOVE_HEAD_LIST(&listHead
);
1209 netvscPacket
= CONTAINING_RECORD(entry
, struct hv_netvsc_packet
, ListEntry
);
1211 INSERT_TAIL_LIST(&netDevice
->ReceivePacketList
, &netvscPacket
->ListEntry
);
1213 spin_unlock_irqrestore(&netDevice
->receive_packet_list_lock
, flags
);
1215 NetVscSendReceiveCompletion(Device
, vmxferpagePacket
->d
.TransactionId
);
1217 PutNetDevice(Device
);
1221 /* Remove the 1st packet to represent the xfer page packet itself */
1222 entry
= REMOVE_HEAD_LIST(&listHead
);
1223 xferpagePacket
= CONTAINING_RECORD(entry
, XFERPAGE_PACKET
, ListEntry
);
1224 xferpagePacket
->Count
= count
- 1; /* This is how much we can satisfy */
1225 ASSERT(xferpagePacket
->Count
> 0 && xferpagePacket
->Count
<= vmxferpagePacket
->RangeCount
);
1227 if (xferpagePacket
->Count
!= vmxferpagePacket
->RangeCount
)
1229 DPRINT_INFO(NETVSC
, "Needed %d netvsc pkts to satisy this xfer page...got %d", vmxferpagePacket
->RangeCount
, xferpagePacket
->Count
);
1232 /* Each range represents 1 RNDIS pkt that contains 1 ethernet frame */
1233 for (i
=0; i
< (count
- 1); i
++)
1235 entry
= REMOVE_HEAD_LIST(&listHead
);
1236 netvscPacket
= CONTAINING_RECORD(entry
, struct hv_netvsc_packet
, ListEntry
);
1238 /* Initialize the netvsc packet */
1239 netvscPacket
->XferPagePacket
= xferpagePacket
;
1240 netvscPacket
->Completion
.Recv
.OnReceiveCompletion
= NetVscOnReceiveCompletion
;
1241 netvscPacket
->Completion
.Recv
.ReceiveCompletionContext
= netvscPacket
;
1242 netvscPacket
->Device
= Device
;
1243 netvscPacket
->Completion
.Recv
.ReceiveCompletionTid
= vmxferpagePacket
->d
.TransactionId
; /* Save this so that we can send it back */
1245 netvscPacket
->TotalDataBufferLength
= vmxferpagePacket
->Ranges
[i
].ByteCount
;
1246 netvscPacket
->PageBufferCount
= 1;
1248 ASSERT(vmxferpagePacket
->Ranges
[i
].ByteOffset
+ vmxferpagePacket
->Ranges
[i
].ByteCount
< netDevice
->ReceiveBufferSize
);
1250 netvscPacket
->PageBuffers
[0].Length
= vmxferpagePacket
->Ranges
[i
].ByteCount
;
1252 start
= GetPhysicalAddress((void*)((unsigned long)netDevice
->ReceiveBuffer
+ vmxferpagePacket
->Ranges
[i
].ByteOffset
));
1254 netvscPacket
->PageBuffers
[0].Pfn
= start
>> PAGE_SHIFT
;
1255 endVirtual
= (unsigned long)netDevice
->ReceiveBuffer
1256 + vmxferpagePacket
->Ranges
[i
].ByteOffset
1257 + vmxferpagePacket
->Ranges
[i
].ByteCount
-1;
1258 end
= GetPhysicalAddress((void*)endVirtual
);
1260 /* Calculate the page relative offset */
1261 netvscPacket
->PageBuffers
[0].Offset
= vmxferpagePacket
->Ranges
[i
].ByteOffset
& (PAGE_SIZE
-1);
1262 if ((end
>> PAGE_SHIFT
) != (start
>>PAGE_SHIFT
)) {
1263 /* Handle frame across multiple pages: */
1264 netvscPacket
->PageBuffers
[0].Length
=
1265 (netvscPacket
->PageBuffers
[0].Pfn
<<PAGE_SHIFT
) + PAGE_SIZE
- start
;
1266 bytesRemain
= netvscPacket
->TotalDataBufferLength
- netvscPacket
->PageBuffers
[0].Length
;
1267 for (j
=1; j
<NETVSC_PACKET_MAXPAGE
; j
++) {
1268 netvscPacket
->PageBuffers
[j
].Offset
= 0;
1269 if (bytesRemain
<= PAGE_SIZE
) {
1270 netvscPacket
->PageBuffers
[j
].Length
= bytesRemain
;
1273 netvscPacket
->PageBuffers
[j
].Length
= PAGE_SIZE
;
1274 bytesRemain
-= PAGE_SIZE
;
1276 netvscPacket
->PageBuffers
[j
].Pfn
=
1277 GetPhysicalAddress((void*)(endVirtual
- bytesRemain
)) >> PAGE_SHIFT
;
1278 netvscPacket
->PageBufferCount
++;
1279 if (bytesRemain
== 0)
1282 ASSERT(bytesRemain
== 0);
1284 DPRINT_DBG(NETVSC
, "[%d] - (abs offset %u len %u) => (pfn %llx, offset %u, len %u)",
1286 vmxferpagePacket
->Ranges
[i
].ByteOffset
,
1287 vmxferpagePacket
->Ranges
[i
].ByteCount
,
1288 netvscPacket
->PageBuffers
[0].Pfn
,
1289 netvscPacket
->PageBuffers
[0].Offset
,
1290 netvscPacket
->PageBuffers
[0].Length
);
1292 /* Pass it to the upper layer */
1293 ((NETVSC_DRIVER_OBJECT
*)Device
->Driver
)->OnReceiveCallback(Device
, netvscPacket
);
1295 NetVscOnReceiveCompletion(netvscPacket
->Completion
.Recv
.ReceiveCompletionContext
);
1298 ASSERT(IsListEmpty(&listHead
));
1300 PutNetDevice(Device
);
1301 DPRINT_EXIT(NETVSC
);
1306 NetVscSendReceiveCompletion(
1307 struct hv_device
*Device
,
1311 NVSP_MESSAGE recvcompMessage
;
1315 DPRINT_DBG(NETVSC
, "Sending receive completion pkt - %llx", TransactionId
);
1317 recvcompMessage
.Header
.MessageType
= NvspMessage1TypeSendRNDISPacketComplete
;
1319 /* FIXME: Pass in the status */
1320 recvcompMessage
.Messages
.Version1Messages
.SendRNDISPacketComplete
.Status
= NvspStatusSuccess
;
1323 /* Send the completion */
1324 ret
= Device
->Driver
->VmbusChannelInterface
.SendPacket(Device
,
1326 sizeof(NVSP_MESSAGE
),
1328 VmbusPacketTypeCompletion
,
1330 if (ret
== 0) /* success */
1334 else if (ret
== -1) /* no more room...wait a bit and attempt to retry 3 times */
1337 DPRINT_ERR(NETVSC
, "unable to send receive completion pkt (tid %llx)...retrying %d", TransactionId
, retries
);
1342 goto retry_send_cmplt
;
1346 DPRINT_ERR(NETVSC
, "unable to send receive completion pkt (tid %llx)...give up retrying", TransactionId
);
1351 DPRINT_ERR(NETVSC
, "unable to send receive completion pkt - %llx", TransactionId
);
1355 /* Send a receive completion packet to RNDIS device (ie NetVsp) */
1357 NetVscOnReceiveCompletion(
1360 struct hv_netvsc_packet
*packet
= (struct hv_netvsc_packet
*)Context
;
1361 struct hv_device
*device
= (struct hv_device
*)packet
->Device
;
1362 struct NETVSC_DEVICE
*netDevice
;
1363 u64 transactionId
=0;
1364 bool fSendReceiveComp
= false;
1365 unsigned long flags
;
1367 DPRINT_ENTER(NETVSC
);
1369 ASSERT(packet
->XferPagePacket
);
1371 /* Even though it seems logical to do a GetOutboundNetDevice() here to send out receive completion, */
1372 /* we are using GetInboundNetDevice() since we may have disable outbound traffic already. */
1373 netDevice
= GetInboundNetDevice(device
);
1376 DPRINT_ERR(NETVSC
, "unable to get net device...device being destroyed?");
1377 DPRINT_EXIT(NETVSC
);
1381 /* Overloading use of the lock. */
1382 spin_lock_irqsave(&netDevice
->receive_packet_list_lock
, flags
);
1384 ASSERT(packet
->XferPagePacket
->Count
> 0);
1385 packet
->XferPagePacket
->Count
--;
1387 /* Last one in the line that represent 1 xfer page packet. */
1388 /* Return the xfer page packet itself to the freelist */
1389 if (packet
->XferPagePacket
->Count
== 0)
1391 fSendReceiveComp
= true;
1392 transactionId
= packet
->Completion
.Recv
.ReceiveCompletionTid
;
1394 INSERT_TAIL_LIST(&netDevice
->ReceivePacketList
, &packet
->XferPagePacket
->ListEntry
);
1397 /* Put the packet back */
1398 INSERT_TAIL_LIST(&netDevice
->ReceivePacketList
, &packet
->ListEntry
);
1399 spin_unlock_irqrestore(&netDevice
->receive_packet_list_lock
, flags
);
1401 /* Send a receive completion for the xfer page packet */
1402 if (fSendReceiveComp
)
1404 NetVscSendReceiveCompletion(device
, transactionId
);
1407 PutNetDevice(device
);
1408 DPRINT_EXIT(NETVSC
);
1414 NetVscOnChannelCallback(
1418 const int netPacketSize
=2048;
1420 struct hv_device
*device
=(struct hv_device
*)Context
;
1421 struct NETVSC_DEVICE
*netDevice
;
1425 unsigned char packet
[netPacketSize
];
1426 VMPACKET_DESCRIPTOR
*desc
;
1427 unsigned char *buffer
=packet
;
1428 int bufferlen
=netPacketSize
;
1431 DPRINT_ENTER(NETVSC
);
1435 netDevice
= GetInboundNetDevice(device
);
1438 DPRINT_ERR(NETVSC
, "net device (%p) shutting down...ignoring inbound packets", netDevice
);
1439 DPRINT_EXIT(NETVSC
);
1445 ret
= device
->Driver
->VmbusChannelInterface
.RecvPacketRaw(device
,
1455 DPRINT_DBG(NETVSC
, "receive %d bytes, tid %llx", bytesRecvd
, requestId
);
1457 desc
= (VMPACKET_DESCRIPTOR
*)buffer
;
1460 case VmbusPacketTypeCompletion
:
1461 NetVscOnSendCompletion(device
, desc
);
1464 case VmbusPacketTypeDataUsingTransferPages
:
1465 NetVscOnReceive(device
, desc
);
1469 DPRINT_ERR(NETVSC
, "unhandled packet type %d, tid %llx len %d\n", desc
->Type
, requestId
, bytesRecvd
);
1474 if (bufferlen
> netPacketSize
)
1479 bufferlen
= netPacketSize
;
1484 /* DPRINT_DBG(NETVSC, "nothing else to read..."); */
1487 if (bufferlen
> netPacketSize
)
1492 bufferlen
= netPacketSize
;
1498 else if (ret
== -2) /* Handle large packet */
1500 buffer
= kmalloc(bytesRecvd
, GFP_ATOMIC
);
1503 /* Try again next time around */
1504 DPRINT_ERR(NETVSC
, "unable to allocate buffer of size (%d)!!", bytesRecvd
);
1508 bufferlen
= bytesRecvd
;
1516 PutNetDevice(device
);
1517 DPRINT_EXIT(NETVSC
);