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>
27 #include "include/logging.h"
29 #include "RndisFilter.h"
33 static const char* gDriverName
="netvsc";
35 /* {F8615163-DF3E-46c5-913F-F2D2F965ED0E} */
36 static const GUID gNetVscDeviceType
={
37 .Data
= {0x63, 0x51, 0x61, 0xF8, 0x3E, 0xDF, 0xc5, 0x46, 0x91, 0x3F, 0xF2, 0xD2, 0xF9, 0x65, 0xED, 0x0E}
41 /* Internal routines */
44 struct hv_device
*Device
,
50 struct hv_device
*Device
55 struct hv_driver
*Driver
59 NetVscOnChannelCallback(
64 NetVscInitializeSendBufferWithNetVsp(
65 struct hv_device
*Device
69 NetVscInitializeReceiveBufferWithNetVsp(
70 struct hv_device
*Device
74 NetVscDestroySendBuffer(
75 struct NETVSC_DEVICE
*NetDevice
79 NetVscDestroyReceiveBuffer(
80 struct NETVSC_DEVICE
*NetDevice
85 struct hv_device
*Device
89 NetVscOnSendCompletion(
90 struct hv_device
*Device
,
91 VMPACKET_DESCRIPTOR
*Packet
96 struct hv_device
*Device
,
97 struct hv_netvsc_packet
*Packet
102 struct hv_device
*Device
,
103 VMPACKET_DESCRIPTOR
*Packet
107 NetVscOnReceiveCompletion(
112 NetVscSendReceiveCompletion(
113 struct hv_device
*Device
,
117 static inline struct NETVSC_DEVICE
*AllocNetDevice(struct hv_device
*Device
)
119 struct NETVSC_DEVICE
*netDevice
;
121 netDevice
= kzalloc(sizeof(struct NETVSC_DEVICE
), GFP_KERNEL
);
125 /* Set to 2 to allow both inbound and outbound traffic */
126 atomic_cmpxchg(&netDevice
->RefCount
, 0, 2);
128 netDevice
->Device
= Device
;
129 Device
->Extension
= netDevice
;
134 static inline void FreeNetDevice(struct NETVSC_DEVICE
*Device
)
136 ASSERT(atomic_read(&Device
->RefCount
) == 0);
137 Device
->Device
->Extension
= NULL
;
142 /* Get the net device object iff exists and its refcount > 1 */
143 static inline struct NETVSC_DEVICE
*GetOutboundNetDevice(struct hv_device
*Device
)
145 struct NETVSC_DEVICE
*netDevice
;
147 netDevice
= (struct NETVSC_DEVICE
*)Device
->Extension
;
148 if (netDevice
&& atomic_read(&netDevice
->RefCount
) > 1)
149 atomic_inc(&netDevice
->RefCount
);
156 /* Get the net device object iff exists and its refcount > 0 */
157 static inline struct NETVSC_DEVICE
*GetInboundNetDevice(struct hv_device
*Device
)
159 struct NETVSC_DEVICE
*netDevice
;
161 netDevice
= (struct NETVSC_DEVICE
*)Device
->Extension
;
162 if (netDevice
&& atomic_read(&netDevice
->RefCount
))
163 atomic_inc(&netDevice
->RefCount
);
170 static inline void PutNetDevice(struct hv_device
*Device
)
172 struct NETVSC_DEVICE
*netDevice
;
174 netDevice
= (struct NETVSC_DEVICE
*)Device
->Extension
;
177 atomic_dec(&netDevice
->RefCount
);
180 static inline struct NETVSC_DEVICE
*ReleaseOutboundNetDevice(struct hv_device
*Device
)
182 struct NETVSC_DEVICE
*netDevice
;
184 netDevice
= (struct NETVSC_DEVICE
*)Device
->Extension
;
185 if (netDevice
== NULL
)
188 /* Busy wait until the ref drop to 2, then set it to 1 */
189 while (atomic_cmpxchg(&netDevice
->RefCount
, 2, 1) != 2)
197 static inline struct NETVSC_DEVICE
*ReleaseInboundNetDevice(struct hv_device
*Device
)
199 struct NETVSC_DEVICE
*netDevice
;
201 netDevice
= (struct NETVSC_DEVICE
*)Device
->Extension
;
202 if (netDevice
== NULL
)
205 /* Busy wait until the ref drop to 1, then set it to 0 */
206 while (atomic_cmpxchg(&netDevice
->RefCount
, 1, 0) != 1)
211 Device
->Extension
= NULL
;
227 struct hv_driver
*drv
230 NETVSC_DRIVER_OBJECT
* driver
= (NETVSC_DRIVER_OBJECT
*)drv
;
233 DPRINT_ENTER(NETVSC
);
235 DPRINT_DBG(NETVSC
, "sizeof(struct hv_netvsc_packet)=%zd, sizeof(NVSP_MESSAGE)=%zd, sizeof(VMTRANSFER_PAGE_PACKET_HEADER)=%zd",
236 sizeof(struct hv_netvsc_packet
), sizeof(NVSP_MESSAGE
), sizeof(VMTRANSFER_PAGE_PACKET_HEADER
));
238 /* Make sure we are at least 2 pages since 1 page is used for control */
239 ASSERT(driver
->RingBufferSize
>= (PAGE_SIZE
<< 1));
241 drv
->name
= gDriverName
;
242 memcpy(&drv
->deviceType
, &gNetVscDeviceType
, sizeof(GUID
));
244 /* Make sure it is set by the caller */
245 ASSERT(driver
->OnReceiveCallback
);
246 ASSERT(driver
->OnLinkStatusChanged
);
248 /* Setup the dispatch table */
249 driver
->Base
.OnDeviceAdd
= NetVscOnDeviceAdd
;
250 driver
->Base
.OnDeviceRemove
= NetVscOnDeviceRemove
;
251 driver
->Base
.OnCleanup
= NetVscOnCleanup
;
253 driver
->OnSend
= NetVscOnSend
;
255 RndisFilterInit(driver
);
263 NetVscInitializeReceiveBufferWithNetVsp(
264 struct hv_device
*Device
268 struct NETVSC_DEVICE
*netDevice
;
269 NVSP_MESSAGE
*initPacket
;
271 DPRINT_ENTER(NETVSC
);
273 netDevice
= GetOutboundNetDevice(Device
);
276 DPRINT_ERR(NETVSC
, "unable to get net device...device being destroyed?");
280 ASSERT(netDevice
->ReceiveBufferSize
> 0);
281 ASSERT((netDevice
->ReceiveBufferSize
& (PAGE_SIZE
-1)) == 0); /* page-size grandularity */
283 netDevice
->ReceiveBuffer
= PageAlloc(netDevice
->ReceiveBufferSize
>> PAGE_SHIFT
);
284 if (!netDevice
->ReceiveBuffer
)
286 DPRINT_ERR(NETVSC
, "unable to allocate receive buffer of size %d", netDevice
->ReceiveBufferSize
);
290 ASSERT(((unsigned long)netDevice
->ReceiveBuffer
& (PAGE_SIZE
-1)) == 0); /* page-aligned buffer */
292 DPRINT_INFO(NETVSC
, "Establishing receive buffer's GPADL...");
295 * Establish the gpadl handle for this buffer on this
296 * channel. Note: This call uses the vmbus connection rather
297 * than the channel to establish the gpadl handle.
299 ret
= Device
->Driver
->VmbusChannelInterface
.EstablishGpadl(Device
,
300 netDevice
->ReceiveBuffer
,
301 netDevice
->ReceiveBufferSize
,
302 &netDevice
->ReceiveBufferGpadlHandle
);
306 DPRINT_ERR(NETVSC
, "unable to establish receive buffer's gpadl");
310 /* WaitEventWait(ext->ChannelInitEvent); */
312 /* Notify the NetVsp of the gpadl handle */
313 DPRINT_INFO(NETVSC
, "Sending NvspMessage1TypeSendReceiveBuffer...");
315 initPacket
= &netDevice
->ChannelInitPacket
;
317 memset(initPacket
, 0, sizeof(NVSP_MESSAGE
));
319 initPacket
->Header
.MessageType
= NvspMessage1TypeSendReceiveBuffer
;
320 initPacket
->Messages
.Version1Messages
.SendReceiveBuffer
.GpadlHandle
= netDevice
->ReceiveBufferGpadlHandle
;
321 initPacket
->Messages
.Version1Messages
.SendReceiveBuffer
.Id
= NETVSC_RECEIVE_BUFFER_ID
;
323 /* Send the gpadl notification request */
324 ret
= Device
->Driver
->VmbusChannelInterface
.SendPacket(Device
,
326 sizeof(NVSP_MESSAGE
),
327 (unsigned long)initPacket
,
328 VmbusPacketTypeDataInBand
,
329 VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED
);
332 DPRINT_ERR(NETVSC
, "unable to send receive buffer's gpadl to netvsp");
336 WaitEventWait(netDevice
->ChannelInitEvent
);
338 /* Check the response */
339 if (initPacket
->Messages
.Version1Messages
.SendReceiveBufferComplete
.Status
!= NvspStatusSuccess
)
342 "Unable to complete receive buffer initialzation with NetVsp - status %d",
343 initPacket
->Messages
.Version1Messages
.SendReceiveBufferComplete
.Status
);
348 /* Parse the response */
349 ASSERT(netDevice
->ReceiveSectionCount
== 0);
350 ASSERT(netDevice
->ReceiveSections
== NULL
);
352 netDevice
->ReceiveSectionCount
= initPacket
->Messages
.Version1Messages
.SendReceiveBufferComplete
.NumSections
;
354 netDevice
->ReceiveSections
= kmalloc(netDevice
->ReceiveSectionCount
* sizeof(NVSP_1_RECEIVE_BUFFER_SECTION
), GFP_KERNEL
);
355 if (netDevice
->ReceiveSections
== NULL
)
361 memcpy(netDevice
->ReceiveSections
,
362 initPacket
->Messages
.Version1Messages
.SendReceiveBufferComplete
.Sections
,
363 netDevice
->ReceiveSectionCount
* sizeof(NVSP_1_RECEIVE_BUFFER_SECTION
));
366 "Receive sections info (count %d, offset %d, endoffset %d, suballoc size %d, num suballocs %d)",
367 netDevice
->ReceiveSectionCount
, netDevice
->ReceiveSections
[0].Offset
, netDevice
->ReceiveSections
[0].EndOffset
,
368 netDevice
->ReceiveSections
[0].SubAllocationSize
, netDevice
->ReceiveSections
[0].NumSubAllocations
);
371 /* For 1st release, there should only be 1 section that represents the entire receive buffer */
372 if (netDevice
->ReceiveSectionCount
!= 1 ||
373 netDevice
->ReceiveSections
->Offset
!= 0 )
382 NetVscDestroyReceiveBuffer(netDevice
);
385 PutNetDevice(Device
);
392 NetVscInitializeSendBufferWithNetVsp(
393 struct hv_device
*Device
397 struct NETVSC_DEVICE
*netDevice
;
398 NVSP_MESSAGE
*initPacket
;
400 DPRINT_ENTER(NETVSC
);
402 netDevice
= GetOutboundNetDevice(Device
);
405 DPRINT_ERR(NETVSC
, "unable to get net device...device being destroyed?");
409 ASSERT(netDevice
->SendBufferSize
> 0);
410 ASSERT((netDevice
->SendBufferSize
& (PAGE_SIZE
-1)) == 0); /* page-size grandularity */
412 netDevice
->SendBuffer
= PageAlloc(netDevice
->SendBufferSize
>> PAGE_SHIFT
);
413 if (!netDevice
->SendBuffer
)
415 DPRINT_ERR(NETVSC
, "unable to allocate send buffer of size %d", netDevice
->SendBufferSize
);
419 ASSERT(((unsigned long)netDevice
->SendBuffer
& (PAGE_SIZE
-1)) == 0); /* page-aligned buffer */
421 DPRINT_INFO(NETVSC
, "Establishing send buffer's GPADL...");
424 * Establish the gpadl handle for this buffer on this
425 * channel. Note: This call uses the vmbus connection rather
426 * than the channel to establish the gpadl handle.
428 ret
= Device
->Driver
->VmbusChannelInterface
.EstablishGpadl(Device
,
429 netDevice
->SendBuffer
,
430 netDevice
->SendBufferSize
,
431 &netDevice
->SendBufferGpadlHandle
);
435 DPRINT_ERR(NETVSC
, "unable to establish send buffer's gpadl");
439 /* WaitEventWait(ext->ChannelInitEvent); */
441 /* Notify the NetVsp of the gpadl handle */
442 DPRINT_INFO(NETVSC
, "Sending NvspMessage1TypeSendSendBuffer...");
444 initPacket
= &netDevice
->ChannelInitPacket
;
446 memset(initPacket
, 0, sizeof(NVSP_MESSAGE
));
448 initPacket
->Header
.MessageType
= NvspMessage1TypeSendSendBuffer
;
449 initPacket
->Messages
.Version1Messages
.SendReceiveBuffer
.GpadlHandle
= netDevice
->SendBufferGpadlHandle
;
450 initPacket
->Messages
.Version1Messages
.SendReceiveBuffer
.Id
= NETVSC_SEND_BUFFER_ID
;
452 /* Send the gpadl notification request */
453 ret
= Device
->Driver
->VmbusChannelInterface
.SendPacket(Device
,
455 sizeof(NVSP_MESSAGE
),
456 (unsigned long)initPacket
,
457 VmbusPacketTypeDataInBand
,
458 VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED
);
461 DPRINT_ERR(NETVSC
, "unable to send receive buffer's gpadl to netvsp");
465 WaitEventWait(netDevice
->ChannelInitEvent
);
467 /* Check the response */
468 if (initPacket
->Messages
.Version1Messages
.SendSendBufferComplete
.Status
!= NvspStatusSuccess
)
471 "Unable to complete send buffer initialzation with NetVsp - status %d",
472 initPacket
->Messages
.Version1Messages
.SendSendBufferComplete
.Status
);
477 netDevice
->SendSectionSize
= initPacket
->Messages
.Version1Messages
.SendSendBufferComplete
.SectionSize
;
482 NetVscDestroySendBuffer(netDevice
);
485 PutNetDevice(Device
);
491 NetVscDestroyReceiveBuffer(
492 struct NETVSC_DEVICE
*NetDevice
495 NVSP_MESSAGE
*revokePacket
;
499 DPRINT_ENTER(NETVSC
);
502 * If we got a section count, it means we received a
503 * SendReceiveBufferComplete msg (ie sent
504 * NvspMessage1TypeSendReceiveBuffer msg) therefore, we need
505 * to send a revoke msg here
507 if (NetDevice
->ReceiveSectionCount
)
509 DPRINT_INFO(NETVSC
, "Sending NvspMessage1TypeRevokeReceiveBuffer...");
511 /* Send the revoke receive buffer */
512 revokePacket
= &NetDevice
->RevokePacket
;
513 memset(revokePacket
, 0, sizeof(NVSP_MESSAGE
));
515 revokePacket
->Header
.MessageType
= NvspMessage1TypeRevokeReceiveBuffer
;
516 revokePacket
->Messages
.Version1Messages
.RevokeReceiveBuffer
.Id
= NETVSC_RECEIVE_BUFFER_ID
;
518 ret
= NetDevice
->Device
->Driver
->VmbusChannelInterface
.SendPacket(NetDevice
->Device
,
520 sizeof(NVSP_MESSAGE
),
521 (unsigned long)revokePacket
,
522 VmbusPacketTypeDataInBand
,
525 * If we failed here, we might as well return and
526 * have a leak rather than continue and a bugchk
530 DPRINT_ERR(NETVSC
, "unable to send revoke receive buffer to netvsp");
536 /* Teardown the gpadl on the vsp end */
537 if (NetDevice
->ReceiveBufferGpadlHandle
)
539 DPRINT_INFO(NETVSC
, "Tearing down receive buffer's GPADL...");
541 ret
= NetDevice
->Device
->Driver
->VmbusChannelInterface
.TeardownGpadl(NetDevice
->Device
,
542 NetDevice
->ReceiveBufferGpadlHandle
);
544 /* If we failed here, we might as well return and have a leak rather than continue and a bugchk */
547 DPRINT_ERR(NETVSC
, "unable to teardown receive buffer's gpadl");
551 NetDevice
->ReceiveBufferGpadlHandle
= 0;
554 if (NetDevice
->ReceiveBuffer
)
556 DPRINT_INFO(NETVSC
, "Freeing up receive buffer...");
558 /* Free up the receive buffer */
559 PageFree(NetDevice
->ReceiveBuffer
, NetDevice
->ReceiveBufferSize
>> PAGE_SHIFT
);
560 NetDevice
->ReceiveBuffer
= NULL
;
563 if (NetDevice
->ReceiveSections
)
565 kfree(NetDevice
->ReceiveSections
);
566 NetDevice
->ReceiveSections
= NULL
;
567 NetDevice
->ReceiveSectionCount
= 0;
579 NetVscDestroySendBuffer(
580 struct NETVSC_DEVICE
*NetDevice
583 NVSP_MESSAGE
*revokePacket
;
587 DPRINT_ENTER(NETVSC
);
590 * If we got a section count, it means we received a
591 * SendReceiveBufferComplete msg (ie sent
592 * NvspMessage1TypeSendReceiveBuffer msg) therefore, we need
593 * to send a revoke msg here
595 if (NetDevice
->SendSectionSize
)
597 DPRINT_INFO(NETVSC
, "Sending NvspMessage1TypeRevokeSendBuffer...");
599 /* Send the revoke send buffer */
600 revokePacket
= &NetDevice
->RevokePacket
;
601 memset(revokePacket
, 0, sizeof(NVSP_MESSAGE
));
603 revokePacket
->Header
.MessageType
= NvspMessage1TypeRevokeSendBuffer
;
604 revokePacket
->Messages
.Version1Messages
.RevokeSendBuffer
.Id
= NETVSC_SEND_BUFFER_ID
;
606 ret
= NetDevice
->Device
->Driver
->VmbusChannelInterface
.SendPacket(NetDevice
->Device
,
608 sizeof(NVSP_MESSAGE
),
609 (unsigned long)revokePacket
,
610 VmbusPacketTypeDataInBand
,
612 /* If we failed here, we might as well return and have a leak rather than continue and a bugchk */
615 DPRINT_ERR(NETVSC
, "unable to send revoke send buffer to netvsp");
621 /* Teardown the gpadl on the vsp end */
622 if (NetDevice
->SendBufferGpadlHandle
)
624 DPRINT_INFO(NETVSC
, "Tearing down send buffer's GPADL...");
626 ret
= NetDevice
->Device
->Driver
->VmbusChannelInterface
.TeardownGpadl(NetDevice
->Device
,
627 NetDevice
->SendBufferGpadlHandle
);
629 /* If we failed here, we might as well return and have a leak rather than continue and a bugchk */
632 DPRINT_ERR(NETVSC
, "unable to teardown send buffer's gpadl");
636 NetDevice
->SendBufferGpadlHandle
= 0;
639 if (NetDevice
->SendBuffer
)
641 DPRINT_INFO(NETVSC
, "Freeing up send buffer...");
643 /* Free up the receive buffer */
644 PageFree(NetDevice
->SendBuffer
, NetDevice
->SendBufferSize
>> PAGE_SHIFT
);
645 NetDevice
->SendBuffer
= NULL
;
657 struct hv_device
*Device
661 struct NETVSC_DEVICE
*netDevice
;
662 NVSP_MESSAGE
*initPacket
;
665 DPRINT_ENTER(NETVSC
);
667 netDevice
= GetOutboundNetDevice(Device
);
670 DPRINT_ERR(NETVSC
, "unable to get net device...device being destroyed?");
675 initPacket
= &netDevice
->ChannelInitPacket
;
677 memset(initPacket
, 0, sizeof(NVSP_MESSAGE
));
678 initPacket
->Header
.MessageType
= NvspMessageTypeInit
;
679 initPacket
->Messages
.InitMessages
.Init
.MinProtocolVersion
= NVSP_MIN_PROTOCOL_VERSION
;
680 initPacket
->Messages
.InitMessages
.Init
.MaxProtocolVersion
= NVSP_MAX_PROTOCOL_VERSION
;
682 DPRINT_INFO(NETVSC
, "Sending NvspMessageTypeInit...");
684 /* Send the init request */
685 ret
= Device
->Driver
->VmbusChannelInterface
.SendPacket(Device
,
687 sizeof(NVSP_MESSAGE
),
688 (unsigned long)initPacket
,
689 VmbusPacketTypeDataInBand
,
690 VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED
);
694 DPRINT_ERR(NETVSC
, "unable to send NvspMessageTypeInit");
698 WaitEventWait(netDevice
->ChannelInitEvent
);
700 /* Now, check the response */
701 /* ASSERT(initPacket->Messages.InitMessages.InitComplete.MaximumMdlChainLength <= MAX_MULTIPAGE_BUFFER_COUNT); */
702 DPRINT_INFO(NETVSC
, "NvspMessageTypeInit status(%d) max mdl chain (%d)",
703 initPacket
->Messages
.InitMessages
.InitComplete
.Status
,
704 initPacket
->Messages
.InitMessages
.InitComplete
.MaximumMdlChainLength
);
706 if (initPacket
->Messages
.InitMessages
.InitComplete
.Status
!= NvspStatusSuccess
)
708 DPRINT_ERR(NETVSC
, "unable to initialize with netvsp (status 0x%x)", initPacket
->Messages
.InitMessages
.InitComplete
.Status
);
713 if (initPacket
->Messages
.InitMessages
.InitComplete
.NegotiatedProtocolVersion
!= NVSP_PROTOCOL_VERSION_1
)
715 DPRINT_ERR(NETVSC
, "unable to initialize with netvsp (version expected 1 got %d)",
716 initPacket
->Messages
.InitMessages
.InitComplete
.NegotiatedProtocolVersion
);
720 DPRINT_INFO(NETVSC
, "Sending NvspMessage1TypeSendNdisVersion...");
722 /* Send the ndis version */
723 memset(initPacket
, 0, sizeof(NVSP_MESSAGE
));
725 ndisVersion
= 0x00050000;
727 initPacket
->Header
.MessageType
= NvspMessage1TypeSendNdisVersion
;
728 initPacket
->Messages
.Version1Messages
.SendNdisVersion
.NdisMajorVersion
= (ndisVersion
& 0xFFFF0000) >> 16;
729 initPacket
->Messages
.Version1Messages
.SendNdisVersion
.NdisMinorVersion
= ndisVersion
& 0xFFFF;
731 /* Send the init request */
732 ret
= Device
->Driver
->VmbusChannelInterface
.SendPacket(Device
,
734 sizeof(NVSP_MESSAGE
),
735 (unsigned long)initPacket
,
736 VmbusPacketTypeDataInBand
,
740 DPRINT_ERR(NETVSC
, "unable to send NvspMessage1TypeSendNdisVersion");
745 * BUGBUG - We have to wait for the above msg since the
746 * netvsp uses KMCL which acknowledges packet (completion
747 * packet) since our Vmbus always set the
748 * VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED flag
750 /* WaitEventWait(NetVscChannel->ChannelInitEvent); */
752 /* Post the big receive buffer to NetVSP */
753 ret
= NetVscInitializeReceiveBufferWithNetVsp(Device
);
756 ret
= NetVscInitializeSendBufferWithNetVsp(Device
);
760 PutNetDevice(Device
);
766 NetVscDisconnectFromVsp(
767 struct NETVSC_DEVICE
*NetDevice
770 DPRINT_ENTER(NETVSC
);
772 NetVscDestroyReceiveBuffer(NetDevice
);
773 NetVscDestroySendBuffer(NetDevice
);
785 Callback when the device belonging to this driver is added
790 struct hv_device
*Device
,
797 struct NETVSC_DEVICE
*netDevice
;
798 struct hv_netvsc_packet
*packet
;
801 NETVSC_DRIVER_OBJECT
*netDriver
= (NETVSC_DRIVER_OBJECT
*) Device
->Driver
;;
803 DPRINT_ENTER(NETVSC
);
805 netDevice
= AllocNetDevice(Device
);
812 DPRINT_DBG(NETVSC
, "netvsc channel object allocated - %p", netDevice
);
814 /* Initialize the NetVSC channel extension */
815 netDevice
->ReceiveBufferSize
= NETVSC_RECEIVE_BUFFER_SIZE
;
816 spin_lock_init(&netDevice
->receive_packet_list_lock
);
818 netDevice
->SendBufferSize
= NETVSC_SEND_BUFFER_SIZE
;
820 INITIALIZE_LIST_HEAD(&netDevice
->ReceivePacketList
);
822 for (i
=0; i
< NETVSC_RECEIVE_PACKETLIST_COUNT
; i
++)
824 packet
= kzalloc(sizeof(struct hv_netvsc_packet
) + (NETVSC_RECEIVE_SG_COUNT
* sizeof(PAGE_BUFFER
)), GFP_KERNEL
);
827 DPRINT_DBG(NETVSC
, "unable to allocate netvsc pkts for receive pool (wanted %d got %d)", NETVSC_RECEIVE_PACKETLIST_COUNT
, i
);
831 INSERT_TAIL_LIST(&netDevice
->ReceivePacketList
, &packet
->ListEntry
);
833 netDevice
->ChannelInitEvent
= WaitEventCreate();
835 /* Open the channel */
836 ret
= Device
->Driver
->VmbusChannelInterface
.Open(Device
,
837 netDriver
->RingBufferSize
,
838 netDriver
->RingBufferSize
,
840 NetVscOnChannelCallback
,
846 DPRINT_ERR(NETVSC
, "unable to open channel: %d", ret
);
851 /* Channel is opened */
852 DPRINT_INFO(NETVSC
, "*** NetVSC channel opened successfully! ***");
854 /* Connect with the NetVsp */
855 ret
= NetVscConnectToVsp(Device
);
858 DPRINT_ERR(NETVSC
, "unable to connect to NetVSP - %d", ret
);
863 DPRINT_INFO(NETVSC
, "*** NetVSC channel handshake result - %d ***", ret
);
869 /* Now, we can close the channel safely */
870 Device
->Driver
->VmbusChannelInterface
.Close(Device
);
876 kfree(netDevice
->ChannelInitEvent
);
878 while (!IsListEmpty(&netDevice
->ReceivePacketList
))
880 entry
= REMOVE_HEAD_LIST(&netDevice
->ReceivePacketList
);
881 packet
= CONTAINING_RECORD(entry
, struct hv_netvsc_packet
, ListEntry
);
885 ReleaseOutboundNetDevice(Device
);
886 ReleaseInboundNetDevice(Device
);
888 FreeNetDevice(netDevice
);
899 NetVscOnDeviceRemove()
902 Callback when the root bus device is removed
906 NetVscOnDeviceRemove(
907 struct hv_device
*Device
910 struct NETVSC_DEVICE
*netDevice
;
911 struct hv_netvsc_packet
*netvscPacket
;
915 DPRINT_ENTER(NETVSC
);
917 DPRINT_INFO(NETVSC
, "Disabling outbound traffic on net device (%p)...", Device
->Extension
);
919 /* Stop outbound traffic ie sends and receives completions */
920 netDevice
= ReleaseOutboundNetDevice(Device
);
923 DPRINT_ERR(NETVSC
, "No net device present!!");
927 /* Wait for all send completions */
928 while (atomic_read(&netDevice
->NumOutstandingSends
))
930 DPRINT_INFO(NETVSC
, "waiting for %d requests to complete...", atomic_read(&netDevice
->NumOutstandingSends
));
935 DPRINT_INFO(NETVSC
, "Disconnecting from netvsp...");
937 NetVscDisconnectFromVsp(netDevice
);
939 DPRINT_INFO(NETVSC
, "Disabling inbound traffic on net device (%p)...", Device
->Extension
);
941 /* Stop inbound traffic ie receives and sends completions */
942 netDevice
= ReleaseInboundNetDevice(Device
);
944 /* At this point, no one should be accessing netDevice except in here */
945 DPRINT_INFO(NETVSC
, "net device (%p) safe to remove", netDevice
);
947 /* Now, we can close the channel safely */
948 Device
->Driver
->VmbusChannelInterface
.Close(Device
);
950 /* Release all resources */
951 while (!IsListEmpty(&netDevice
->ReceivePacketList
))
953 entry
= REMOVE_HEAD_LIST(&netDevice
->ReceivePacketList
);
954 netvscPacket
= CONTAINING_RECORD(entry
, struct hv_netvsc_packet
, ListEntry
);
959 kfree(netDevice
->ChannelInitEvent
);
960 FreeNetDevice(netDevice
);
974 Perform any cleanup when the driver is removed
979 struct hv_driver
*drv
982 DPRINT_ENTER(NETVSC
);
988 NetVscOnSendCompletion(
989 struct hv_device
*Device
,
990 VMPACKET_DESCRIPTOR
*Packet
993 struct NETVSC_DEVICE
*netDevice
;
994 NVSP_MESSAGE
*nvspPacket
;
995 struct hv_netvsc_packet
*nvscPacket
;
997 DPRINT_ENTER(NETVSC
);
999 netDevice
= GetInboundNetDevice(Device
);
1002 DPRINT_ERR(NETVSC
, "unable to get net device...device being destroyed?");
1003 DPRINT_EXIT(NETVSC
);
1007 nvspPacket
= (NVSP_MESSAGE
*)((unsigned long)Packet
+ (Packet
->DataOffset8
<< 3));
1009 DPRINT_DBG(NETVSC
, "send completion packet - type %d", nvspPacket
->Header
.MessageType
);
1011 if (nvspPacket
->Header
.MessageType
== NvspMessageTypeInitComplete
||
1012 nvspPacket
->Header
.MessageType
== NvspMessage1TypeSendReceiveBufferComplete
||
1013 nvspPacket
->Header
.MessageType
== NvspMessage1TypeSendSendBufferComplete
)
1015 /* Copy the response back */
1016 memcpy(&netDevice
->ChannelInitPacket
, nvspPacket
, sizeof(NVSP_MESSAGE
));
1017 WaitEventSet(netDevice
->ChannelInitEvent
);
1019 else if (nvspPacket
->Header
.MessageType
== NvspMessage1TypeSendRNDISPacketComplete
)
1021 /* Get the send context */
1022 nvscPacket
= (struct hv_netvsc_packet
*)(unsigned long)Packet
->TransactionId
;
1025 /* Notify the layer above us */
1026 nvscPacket
->Completion
.Send
.OnSendCompletion(nvscPacket
->Completion
.Send
.SendCompletionContext
);
1028 atomic_dec(&netDevice
->NumOutstandingSends
);
1032 DPRINT_ERR(NETVSC
, "Unknown send completion packet type - %d received!!", nvspPacket
->Header
.MessageType
);
1035 PutNetDevice(Device
);
1036 DPRINT_EXIT(NETVSC
);
1043 struct hv_device
*Device
,
1044 struct hv_netvsc_packet
*Packet
1047 struct NETVSC_DEVICE
*netDevice
;
1050 NVSP_MESSAGE sendMessage
;
1052 DPRINT_ENTER(NETVSC
);
1054 netDevice
= GetOutboundNetDevice(Device
);
1057 DPRINT_ERR(NETVSC
, "net device (%p) shutting down...ignoring outbound packets", netDevice
);
1058 DPRINT_EXIT(NETVSC
);
1062 sendMessage
.Header
.MessageType
= NvspMessage1TypeSendRNDISPacket
;
1063 if (Packet
->IsDataPacket
)
1064 sendMessage
.Messages
.Version1Messages
.SendRNDISPacket
.ChannelType
= 0;/* 0 is RMC_DATA; */
1066 sendMessage
.Messages
.Version1Messages
.SendRNDISPacket
.ChannelType
= 1;/* 1 is RMC_CONTROL; */
1068 /* Not using send buffer section */
1069 sendMessage
.Messages
.Version1Messages
.SendRNDISPacket
.SendBufferSectionIndex
= 0xFFFFFFFF;
1070 sendMessage
.Messages
.Version1Messages
.SendRNDISPacket
.SendBufferSectionSize
= 0;
1072 if (Packet
->PageBufferCount
)
1074 ret
= Device
->Driver
->VmbusChannelInterface
.SendPacketPageBuffer(Device
,
1075 Packet
->PageBuffers
,
1076 Packet
->PageBufferCount
,
1078 sizeof(NVSP_MESSAGE
),
1079 (unsigned long)Packet
);
1083 ret
= Device
->Driver
->VmbusChannelInterface
.SendPacket(Device
,
1085 sizeof(NVSP_MESSAGE
),
1086 (unsigned long)Packet
,
1087 VmbusPacketTypeDataInBand
,
1088 VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED
);
1094 DPRINT_ERR(NETVSC
, "Unable to send packet %p ret %d", Packet
, ret
);
1097 atomic_inc(&netDevice
->NumOutstandingSends
);
1098 PutNetDevice(Device
);
1100 DPRINT_EXIT(NETVSC
);
1107 struct hv_device
*Device
,
1108 VMPACKET_DESCRIPTOR
*Packet
1111 struct NETVSC_DEVICE
*netDevice
;
1112 VMTRANSFER_PAGE_PACKET_HEADER
*vmxferpagePacket
;
1113 NVSP_MESSAGE
*nvspPacket
;
1114 struct hv_netvsc_packet
*netvscPacket
=NULL
;
1116 unsigned long start
;
1117 unsigned long end
, endVirtual
;
1118 /* NETVSC_DRIVER_OBJECT *netvscDriver; */
1119 XFERPAGE_PACKET
*xferpagePacket
=NULL
;
1120 LIST_ENTRY listHead
;
1123 int count
=0, bytesRemain
=0;
1124 unsigned long flags
;
1126 DPRINT_ENTER(NETVSC
);
1128 netDevice
= GetInboundNetDevice(Device
);
1131 DPRINT_ERR(NETVSC
, "unable to get net device...device being destroyed?");
1132 DPRINT_EXIT(NETVSC
);
1136 /* All inbound packets other than send completion should be xfer page packet */
1137 if (Packet
->Type
!= VmbusPacketTypeDataUsingTransferPages
)
1139 DPRINT_ERR(NETVSC
, "Unknown packet type received - %d", Packet
->Type
);
1140 PutNetDevice(Device
);
1144 nvspPacket
= (NVSP_MESSAGE
*)((unsigned long)Packet
+ (Packet
->DataOffset8
<< 3));
1146 /* Make sure this is a valid nvsp packet */
1147 if (nvspPacket
->Header
.MessageType
!= NvspMessage1TypeSendRNDISPacket
)
1149 DPRINT_ERR(NETVSC
, "Unknown nvsp packet type received - %d", nvspPacket
->Header
.MessageType
);
1150 PutNetDevice(Device
);
1154 DPRINT_DBG(NETVSC
, "NVSP packet received - type %d", nvspPacket
->Header
.MessageType
);
1156 vmxferpagePacket
= (VMTRANSFER_PAGE_PACKET_HEADER
*)Packet
;
1158 if (vmxferpagePacket
->TransferPageSetId
!= NETVSC_RECEIVE_BUFFER_ID
)
1160 DPRINT_ERR(NETVSC
, "Invalid xfer page set id - expecting %x got %x", NETVSC_RECEIVE_BUFFER_ID
, vmxferpagePacket
->TransferPageSetId
);
1161 PutNetDevice(Device
);
1165 DPRINT_DBG(NETVSC
, "xfer page - range count %d", vmxferpagePacket
->RangeCount
);
1167 INITIALIZE_LIST_HEAD(&listHead
);
1170 * Grab free packets (range count + 1) to represent this xfer
1171 * page packet. +1 to represent the xfer page packet itself.
1172 * We grab it here so that we know exactly how many we can
1175 spin_lock_irqsave(&netDevice
->receive_packet_list_lock
, flags
);
1176 while (!IsListEmpty(&netDevice
->ReceivePacketList
))
1178 entry
= REMOVE_HEAD_LIST(&netDevice
->ReceivePacketList
);
1179 netvscPacket
= CONTAINING_RECORD(entry
, struct hv_netvsc_packet
, ListEntry
);
1181 INSERT_TAIL_LIST(&listHead
, &netvscPacket
->ListEntry
);
1183 if (++count
== vmxferpagePacket
->RangeCount
+ 1)
1186 spin_unlock_irqrestore(&netDevice
->receive_packet_list_lock
, flags
);
1189 * We need at least 2 netvsc pkts (1 to represent the xfer
1190 * page and at least 1 for the range) i.e. we can handled
1191 * some of the xfer page packet ranges...
1195 DPRINT_ERR(NETVSC
, "Got only %d netvsc pkt...needed %d pkts. Dropping this xfer page packet completely!", count
, vmxferpagePacket
->RangeCount
+1);
1197 /* Return it to the freelist */
1198 spin_lock_irqsave(&netDevice
->receive_packet_list_lock
, flags
);
1199 for (i
=count
; i
!= 0; i
--)
1201 entry
= REMOVE_HEAD_LIST(&listHead
);
1202 netvscPacket
= CONTAINING_RECORD(entry
, struct hv_netvsc_packet
, ListEntry
);
1204 INSERT_TAIL_LIST(&netDevice
->ReceivePacketList
, &netvscPacket
->ListEntry
);
1206 spin_unlock_irqrestore(&netDevice
->receive_packet_list_lock
, flags
);
1208 NetVscSendReceiveCompletion(Device
, vmxferpagePacket
->d
.TransactionId
);
1210 PutNetDevice(Device
);
1214 /* Remove the 1st packet to represent the xfer page packet itself */
1215 entry
= REMOVE_HEAD_LIST(&listHead
);
1216 xferpagePacket
= CONTAINING_RECORD(entry
, XFERPAGE_PACKET
, ListEntry
);
1217 xferpagePacket
->Count
= count
- 1; /* This is how much we can satisfy */
1218 ASSERT(xferpagePacket
->Count
> 0 && xferpagePacket
->Count
<= vmxferpagePacket
->RangeCount
);
1220 if (xferpagePacket
->Count
!= vmxferpagePacket
->RangeCount
)
1222 DPRINT_INFO(NETVSC
, "Needed %d netvsc pkts to satisy this xfer page...got %d", vmxferpagePacket
->RangeCount
, xferpagePacket
->Count
);
1225 /* Each range represents 1 RNDIS pkt that contains 1 ethernet frame */
1226 for (i
=0; i
< (count
- 1); i
++)
1228 entry
= REMOVE_HEAD_LIST(&listHead
);
1229 netvscPacket
= CONTAINING_RECORD(entry
, struct hv_netvsc_packet
, ListEntry
);
1231 /* Initialize the netvsc packet */
1232 netvscPacket
->XferPagePacket
= xferpagePacket
;
1233 netvscPacket
->Completion
.Recv
.OnReceiveCompletion
= NetVscOnReceiveCompletion
;
1234 netvscPacket
->Completion
.Recv
.ReceiveCompletionContext
= netvscPacket
;
1235 netvscPacket
->Device
= Device
;
1236 netvscPacket
->Completion
.Recv
.ReceiveCompletionTid
= vmxferpagePacket
->d
.TransactionId
; /* Save this so that we can send it back */
1238 netvscPacket
->TotalDataBufferLength
= vmxferpagePacket
->Ranges
[i
].ByteCount
;
1239 netvscPacket
->PageBufferCount
= 1;
1241 ASSERT(vmxferpagePacket
->Ranges
[i
].ByteOffset
+ vmxferpagePacket
->Ranges
[i
].ByteCount
< netDevice
->ReceiveBufferSize
);
1243 netvscPacket
->PageBuffers
[0].Length
= vmxferpagePacket
->Ranges
[i
].ByteCount
;
1245 start
= virt_to_phys((void*)((unsigned long)netDevice
->ReceiveBuffer
+ vmxferpagePacket
->Ranges
[i
].ByteOffset
));
1247 netvscPacket
->PageBuffers
[0].Pfn
= start
>> PAGE_SHIFT
;
1248 endVirtual
= (unsigned long)netDevice
->ReceiveBuffer
1249 + vmxferpagePacket
->Ranges
[i
].ByteOffset
1250 + vmxferpagePacket
->Ranges
[i
].ByteCount
-1;
1251 end
= virt_to_phys((void*)endVirtual
);
1253 /* Calculate the page relative offset */
1254 netvscPacket
->PageBuffers
[0].Offset
= vmxferpagePacket
->Ranges
[i
].ByteOffset
& (PAGE_SIZE
-1);
1255 if ((end
>> PAGE_SHIFT
) != (start
>>PAGE_SHIFT
)) {
1256 /* Handle frame across multiple pages: */
1257 netvscPacket
->PageBuffers
[0].Length
=
1258 (netvscPacket
->PageBuffers
[0].Pfn
<<PAGE_SHIFT
) + PAGE_SIZE
- start
;
1259 bytesRemain
= netvscPacket
->TotalDataBufferLength
- netvscPacket
->PageBuffers
[0].Length
;
1260 for (j
=1; j
<NETVSC_PACKET_MAXPAGE
; j
++) {
1261 netvscPacket
->PageBuffers
[j
].Offset
= 0;
1262 if (bytesRemain
<= PAGE_SIZE
) {
1263 netvscPacket
->PageBuffers
[j
].Length
= bytesRemain
;
1266 netvscPacket
->PageBuffers
[j
].Length
= PAGE_SIZE
;
1267 bytesRemain
-= PAGE_SIZE
;
1269 netvscPacket
->PageBuffers
[j
].Pfn
=
1270 virt_to_phys((void*)(endVirtual
- bytesRemain
)) >> PAGE_SHIFT
;
1271 netvscPacket
->PageBufferCount
++;
1272 if (bytesRemain
== 0)
1275 ASSERT(bytesRemain
== 0);
1277 DPRINT_DBG(NETVSC
, "[%d] - (abs offset %u len %u) => (pfn %llx, offset %u, len %u)",
1279 vmxferpagePacket
->Ranges
[i
].ByteOffset
,
1280 vmxferpagePacket
->Ranges
[i
].ByteCount
,
1281 netvscPacket
->PageBuffers
[0].Pfn
,
1282 netvscPacket
->PageBuffers
[0].Offset
,
1283 netvscPacket
->PageBuffers
[0].Length
);
1285 /* Pass it to the upper layer */
1286 ((NETVSC_DRIVER_OBJECT
*)Device
->Driver
)->OnReceiveCallback(Device
, netvscPacket
);
1288 NetVscOnReceiveCompletion(netvscPacket
->Completion
.Recv
.ReceiveCompletionContext
);
1291 ASSERT(IsListEmpty(&listHead
));
1293 PutNetDevice(Device
);
1294 DPRINT_EXIT(NETVSC
);
1299 NetVscSendReceiveCompletion(
1300 struct hv_device
*Device
,
1304 NVSP_MESSAGE recvcompMessage
;
1308 DPRINT_DBG(NETVSC
, "Sending receive completion pkt - %llx", TransactionId
);
1310 recvcompMessage
.Header
.MessageType
= NvspMessage1TypeSendRNDISPacketComplete
;
1312 /* FIXME: Pass in the status */
1313 recvcompMessage
.Messages
.Version1Messages
.SendRNDISPacketComplete
.Status
= NvspStatusSuccess
;
1316 /* Send the completion */
1317 ret
= Device
->Driver
->VmbusChannelInterface
.SendPacket(Device
,
1319 sizeof(NVSP_MESSAGE
),
1321 VmbusPacketTypeCompletion
,
1323 if (ret
== 0) /* success */
1327 else if (ret
== -1) /* no more room...wait a bit and attempt to retry 3 times */
1330 DPRINT_ERR(NETVSC
, "unable to send receive completion pkt (tid %llx)...retrying %d", TransactionId
, retries
);
1335 goto retry_send_cmplt
;
1339 DPRINT_ERR(NETVSC
, "unable to send receive completion pkt (tid %llx)...give up retrying", TransactionId
);
1344 DPRINT_ERR(NETVSC
, "unable to send receive completion pkt - %llx", TransactionId
);
1348 /* Send a receive completion packet to RNDIS device (ie NetVsp) */
1350 NetVscOnReceiveCompletion(
1353 struct hv_netvsc_packet
*packet
= (struct hv_netvsc_packet
*)Context
;
1354 struct hv_device
*device
= (struct hv_device
*)packet
->Device
;
1355 struct NETVSC_DEVICE
*netDevice
;
1356 u64 transactionId
=0;
1357 bool fSendReceiveComp
= false;
1358 unsigned long flags
;
1360 DPRINT_ENTER(NETVSC
);
1362 ASSERT(packet
->XferPagePacket
);
1364 /* Even though it seems logical to do a GetOutboundNetDevice() here to send out receive completion, */
1365 /* we are using GetInboundNetDevice() since we may have disable outbound traffic already. */
1366 netDevice
= GetInboundNetDevice(device
);
1369 DPRINT_ERR(NETVSC
, "unable to get net device...device being destroyed?");
1370 DPRINT_EXIT(NETVSC
);
1374 /* Overloading use of the lock. */
1375 spin_lock_irqsave(&netDevice
->receive_packet_list_lock
, flags
);
1377 ASSERT(packet
->XferPagePacket
->Count
> 0);
1378 packet
->XferPagePacket
->Count
--;
1380 /* Last one in the line that represent 1 xfer page packet. */
1381 /* Return the xfer page packet itself to the freelist */
1382 if (packet
->XferPagePacket
->Count
== 0)
1384 fSendReceiveComp
= true;
1385 transactionId
= packet
->Completion
.Recv
.ReceiveCompletionTid
;
1387 INSERT_TAIL_LIST(&netDevice
->ReceivePacketList
, &packet
->XferPagePacket
->ListEntry
);
1390 /* Put the packet back */
1391 INSERT_TAIL_LIST(&netDevice
->ReceivePacketList
, &packet
->ListEntry
);
1392 spin_unlock_irqrestore(&netDevice
->receive_packet_list_lock
, flags
);
1394 /* Send a receive completion for the xfer page packet */
1395 if (fSendReceiveComp
)
1397 NetVscSendReceiveCompletion(device
, transactionId
);
1400 PutNetDevice(device
);
1401 DPRINT_EXIT(NETVSC
);
1407 NetVscOnChannelCallback(
1411 const int netPacketSize
=2048;
1413 struct hv_device
*device
=(struct hv_device
*)Context
;
1414 struct NETVSC_DEVICE
*netDevice
;
1418 unsigned char packet
[netPacketSize
];
1419 VMPACKET_DESCRIPTOR
*desc
;
1420 unsigned char *buffer
=packet
;
1421 int bufferlen
=netPacketSize
;
1424 DPRINT_ENTER(NETVSC
);
1428 netDevice
= GetInboundNetDevice(device
);
1431 DPRINT_ERR(NETVSC
, "net device (%p) shutting down...ignoring inbound packets", netDevice
);
1432 DPRINT_EXIT(NETVSC
);
1438 ret
= device
->Driver
->VmbusChannelInterface
.RecvPacketRaw(device
,
1448 DPRINT_DBG(NETVSC
, "receive %d bytes, tid %llx", bytesRecvd
, requestId
);
1450 desc
= (VMPACKET_DESCRIPTOR
*)buffer
;
1453 case VmbusPacketTypeCompletion
:
1454 NetVscOnSendCompletion(device
, desc
);
1457 case VmbusPacketTypeDataUsingTransferPages
:
1458 NetVscOnReceive(device
, desc
);
1462 DPRINT_ERR(NETVSC
, "unhandled packet type %d, tid %llx len %d\n", desc
->Type
, requestId
, bytesRecvd
);
1467 if (bufferlen
> netPacketSize
)
1472 bufferlen
= netPacketSize
;
1477 /* DPRINT_DBG(NETVSC, "nothing else to read..."); */
1480 if (bufferlen
> netPacketSize
)
1485 bufferlen
= netPacketSize
;
1491 else if (ret
== -2) /* Handle large packet */
1493 buffer
= kmalloc(bytesRecvd
, GFP_ATOMIC
);
1496 /* Try again next time around */
1497 DPRINT_ERR(NETVSC
, "unable to allocate buffer of size (%d)!!", bytesRecvd
);
1501 bufferlen
= bytesRecvd
;
1509 PutNetDevice(device
);
1510 DPRINT_EXIT(NETVSC
);