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>
28 #include "include/logging.h"
30 #include "RndisFilter.h"
34 static const char* gDriverName
="netvsc";
36 /* {F8615163-DF3E-46c5-913F-F2D2F965ED0E} */
37 static const struct hv_guid gNetVscDeviceType
= {
39 0x63, 0x51, 0x61, 0xF8, 0x3E, 0xDF, 0xc5, 0x46,
40 0x91, 0x3F, 0xF2, 0xD2, 0xF9, 0x65, 0xED, 0x0E
45 /* Internal routines */
48 struct hv_device
*Device
,
54 struct hv_device
*Device
59 struct hv_driver
*Driver
63 NetVscOnChannelCallback(
68 NetVscInitializeSendBufferWithNetVsp(
69 struct hv_device
*Device
73 NetVscInitializeReceiveBufferWithNetVsp(
74 struct hv_device
*Device
78 NetVscDestroySendBuffer(
79 struct NETVSC_DEVICE
*NetDevice
83 NetVscDestroyReceiveBuffer(
84 struct NETVSC_DEVICE
*NetDevice
89 struct hv_device
*Device
93 NetVscOnSendCompletion(
94 struct hv_device
*Device
,
95 struct vmpacket_descriptor
*Packet
100 struct hv_device
*Device
,
101 struct hv_netvsc_packet
*Packet
106 struct hv_device
*Device
,
107 struct vmpacket_descriptor
*Packet
111 NetVscOnReceiveCompletion(
116 NetVscSendReceiveCompletion(
117 struct hv_device
*Device
,
121 static inline struct NETVSC_DEVICE
*AllocNetDevice(struct hv_device
*Device
)
123 struct NETVSC_DEVICE
*netDevice
;
125 netDevice
= kzalloc(sizeof(struct NETVSC_DEVICE
), GFP_KERNEL
);
129 /* Set to 2 to allow both inbound and outbound traffic */
130 atomic_cmpxchg(&netDevice
->RefCount
, 0, 2);
132 netDevice
->Device
= Device
;
133 Device
->Extension
= netDevice
;
138 static inline void FreeNetDevice(struct NETVSC_DEVICE
*Device
)
140 ASSERT(atomic_read(&Device
->RefCount
) == 0);
141 Device
->Device
->Extension
= NULL
;
146 /* Get the net device object iff exists and its refcount > 1 */
147 static inline struct NETVSC_DEVICE
*GetOutboundNetDevice(struct hv_device
*Device
)
149 struct NETVSC_DEVICE
*netDevice
;
151 netDevice
= (struct NETVSC_DEVICE
*)Device
->Extension
;
152 if (netDevice
&& atomic_read(&netDevice
->RefCount
) > 1)
153 atomic_inc(&netDevice
->RefCount
);
160 /* Get the net device object iff exists and its refcount > 0 */
161 static inline struct NETVSC_DEVICE
*GetInboundNetDevice(struct hv_device
*Device
)
163 struct NETVSC_DEVICE
*netDevice
;
165 netDevice
= (struct NETVSC_DEVICE
*)Device
->Extension
;
166 if (netDevice
&& atomic_read(&netDevice
->RefCount
))
167 atomic_inc(&netDevice
->RefCount
);
174 static inline void PutNetDevice(struct hv_device
*Device
)
176 struct NETVSC_DEVICE
*netDevice
;
178 netDevice
= (struct NETVSC_DEVICE
*)Device
->Extension
;
181 atomic_dec(&netDevice
->RefCount
);
184 static inline struct NETVSC_DEVICE
*ReleaseOutboundNetDevice(struct hv_device
*Device
)
186 struct NETVSC_DEVICE
*netDevice
;
188 netDevice
= (struct NETVSC_DEVICE
*)Device
->Extension
;
189 if (netDevice
== NULL
)
192 /* Busy wait until the ref drop to 2, then set it to 1 */
193 while (atomic_cmpxchg(&netDevice
->RefCount
, 2, 1) != 2)
201 static inline struct NETVSC_DEVICE
*ReleaseInboundNetDevice(struct hv_device
*Device
)
203 struct NETVSC_DEVICE
*netDevice
;
205 netDevice
= (struct NETVSC_DEVICE
*)Device
->Extension
;
206 if (netDevice
== NULL
)
209 /* Busy wait until the ref drop to 1, then set it to 0 */
210 while (atomic_cmpxchg(&netDevice
->RefCount
, 1, 0) != 1)
215 Device
->Extension
= NULL
;
231 struct hv_driver
*drv
234 struct netvsc_driver
*driver
= (struct netvsc_driver
*)drv
;
237 DPRINT_ENTER(NETVSC
);
239 DPRINT_DBG(NETVSC
, "sizeof(struct hv_netvsc_packet)=%zd, sizeof(NVSP_MESSAGE)=%zd, sizeof(struct vmtransfer_page_packet_header)=%zd",
240 sizeof(struct hv_netvsc_packet
), sizeof(NVSP_MESSAGE
), sizeof(struct vmtransfer_page_packet_header
));
242 /* Make sure we are at least 2 pages since 1 page is used for control */
243 ASSERT(driver
->RingBufferSize
>= (PAGE_SIZE
<< 1));
245 drv
->name
= gDriverName
;
246 memcpy(&drv
->deviceType
, &gNetVscDeviceType
, sizeof(struct hv_guid
));
248 /* Make sure it is set by the caller */
249 ASSERT(driver
->OnReceiveCallback
);
250 ASSERT(driver
->OnLinkStatusChanged
);
252 /* Setup the dispatch table */
253 driver
->Base
.OnDeviceAdd
= NetVscOnDeviceAdd
;
254 driver
->Base
.OnDeviceRemove
= NetVscOnDeviceRemove
;
255 driver
->Base
.OnCleanup
= NetVscOnCleanup
;
257 driver
->OnSend
= NetVscOnSend
;
259 RndisFilterInit(driver
);
267 NetVscInitializeReceiveBufferWithNetVsp(
268 struct hv_device
*Device
272 struct NETVSC_DEVICE
*netDevice
;
273 NVSP_MESSAGE
*initPacket
;
275 DPRINT_ENTER(NETVSC
);
277 netDevice
= GetOutboundNetDevice(Device
);
280 DPRINT_ERR(NETVSC
, "unable to get net device...device being destroyed?");
284 ASSERT(netDevice
->ReceiveBufferSize
> 0);
285 ASSERT((netDevice
->ReceiveBufferSize
& (PAGE_SIZE
-1)) == 0); /* page-size grandularity */
287 netDevice
->ReceiveBuffer
= osd_PageAlloc(netDevice
->ReceiveBufferSize
>> PAGE_SHIFT
);
288 if (!netDevice
->ReceiveBuffer
)
290 DPRINT_ERR(NETVSC
, "unable to allocate receive buffer of size %d", netDevice
->ReceiveBufferSize
);
294 ASSERT(((unsigned long)netDevice
->ReceiveBuffer
& (PAGE_SIZE
-1)) == 0); /* page-aligned buffer */
296 DPRINT_INFO(NETVSC
, "Establishing receive buffer's GPADL...");
299 * Establish the gpadl handle for this buffer on this
300 * channel. Note: This call uses the vmbus connection rather
301 * than the channel to establish the gpadl handle.
303 ret
= Device
->Driver
->VmbusChannelInterface
.EstablishGpadl(Device
,
304 netDevice
->ReceiveBuffer
,
305 netDevice
->ReceiveBufferSize
,
306 &netDevice
->ReceiveBufferGpadlHandle
);
310 DPRINT_ERR(NETVSC
, "unable to establish receive buffer's gpadl");
314 /* osd_WaitEventWait(ext->ChannelInitEvent); */
316 /* Notify the NetVsp of the gpadl handle */
317 DPRINT_INFO(NETVSC
, "Sending NvspMessage1TypeSendReceiveBuffer...");
319 initPacket
= &netDevice
->ChannelInitPacket
;
321 memset(initPacket
, 0, sizeof(NVSP_MESSAGE
));
323 initPacket
->Header
.MessageType
= NvspMessage1TypeSendReceiveBuffer
;
324 initPacket
->Messages
.Version1Messages
.SendReceiveBuffer
.GpadlHandle
= netDevice
->ReceiveBufferGpadlHandle
;
325 initPacket
->Messages
.Version1Messages
.SendReceiveBuffer
.Id
= NETVSC_RECEIVE_BUFFER_ID
;
327 /* Send the gpadl notification request */
328 ret
= Device
->Driver
->VmbusChannelInterface
.SendPacket(Device
,
330 sizeof(NVSP_MESSAGE
),
331 (unsigned long)initPacket
,
332 VmbusPacketTypeDataInBand
,
333 VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED
);
336 DPRINT_ERR(NETVSC
, "unable to send receive buffer's gpadl to netvsp");
340 osd_WaitEventWait(netDevice
->ChannelInitEvent
);
342 /* Check the response */
343 if (initPacket
->Messages
.Version1Messages
.SendReceiveBufferComplete
.Status
!= NvspStatusSuccess
)
346 "Unable to complete receive buffer initialzation with NetVsp - status %d",
347 initPacket
->Messages
.Version1Messages
.SendReceiveBufferComplete
.Status
);
352 /* Parse the response */
353 ASSERT(netDevice
->ReceiveSectionCount
== 0);
354 ASSERT(netDevice
->ReceiveSections
== NULL
);
356 netDevice
->ReceiveSectionCount
= initPacket
->Messages
.Version1Messages
.SendReceiveBufferComplete
.NumSections
;
358 netDevice
->ReceiveSections
= kmalloc(netDevice
->ReceiveSectionCount
* sizeof(NVSP_1_RECEIVE_BUFFER_SECTION
), GFP_KERNEL
);
359 if (netDevice
->ReceiveSections
== NULL
)
365 memcpy(netDevice
->ReceiveSections
,
366 initPacket
->Messages
.Version1Messages
.SendReceiveBufferComplete
.Sections
,
367 netDevice
->ReceiveSectionCount
* sizeof(NVSP_1_RECEIVE_BUFFER_SECTION
));
370 "Receive sections info (count %d, offset %d, endoffset %d, suballoc size %d, num suballocs %d)",
371 netDevice
->ReceiveSectionCount
, netDevice
->ReceiveSections
[0].Offset
, netDevice
->ReceiveSections
[0].EndOffset
,
372 netDevice
->ReceiveSections
[0].SubAllocationSize
, netDevice
->ReceiveSections
[0].NumSubAllocations
);
375 /* For 1st release, there should only be 1 section that represents the entire receive buffer */
376 if (netDevice
->ReceiveSectionCount
!= 1 ||
377 netDevice
->ReceiveSections
->Offset
!= 0 )
386 NetVscDestroyReceiveBuffer(netDevice
);
389 PutNetDevice(Device
);
396 NetVscInitializeSendBufferWithNetVsp(
397 struct hv_device
*Device
401 struct NETVSC_DEVICE
*netDevice
;
402 NVSP_MESSAGE
*initPacket
;
404 DPRINT_ENTER(NETVSC
);
406 netDevice
= GetOutboundNetDevice(Device
);
409 DPRINT_ERR(NETVSC
, "unable to get net device...device being destroyed?");
413 ASSERT(netDevice
->SendBufferSize
> 0);
414 ASSERT((netDevice
->SendBufferSize
& (PAGE_SIZE
-1)) == 0); /* page-size grandularity */
416 netDevice
->SendBuffer
= osd_PageAlloc(netDevice
->SendBufferSize
>> PAGE_SHIFT
);
417 if (!netDevice
->SendBuffer
)
419 DPRINT_ERR(NETVSC
, "unable to allocate send buffer of size %d", netDevice
->SendBufferSize
);
423 ASSERT(((unsigned long)netDevice
->SendBuffer
& (PAGE_SIZE
-1)) == 0); /* page-aligned buffer */
425 DPRINT_INFO(NETVSC
, "Establishing send buffer's GPADL...");
428 * Establish the gpadl handle for this buffer on this
429 * channel. Note: This call uses the vmbus connection rather
430 * than the channel to establish the gpadl handle.
432 ret
= Device
->Driver
->VmbusChannelInterface
.EstablishGpadl(Device
,
433 netDevice
->SendBuffer
,
434 netDevice
->SendBufferSize
,
435 &netDevice
->SendBufferGpadlHandle
);
439 DPRINT_ERR(NETVSC
, "unable to establish send buffer's gpadl");
443 /* osd_WaitEventWait(ext->ChannelInitEvent); */
445 /* Notify the NetVsp of the gpadl handle */
446 DPRINT_INFO(NETVSC
, "Sending NvspMessage1TypeSendSendBuffer...");
448 initPacket
= &netDevice
->ChannelInitPacket
;
450 memset(initPacket
, 0, sizeof(NVSP_MESSAGE
));
452 initPacket
->Header
.MessageType
= NvspMessage1TypeSendSendBuffer
;
453 initPacket
->Messages
.Version1Messages
.SendReceiveBuffer
.GpadlHandle
= netDevice
->SendBufferGpadlHandle
;
454 initPacket
->Messages
.Version1Messages
.SendReceiveBuffer
.Id
= NETVSC_SEND_BUFFER_ID
;
456 /* Send the gpadl notification request */
457 ret
= Device
->Driver
->VmbusChannelInterface
.SendPacket(Device
,
459 sizeof(NVSP_MESSAGE
),
460 (unsigned long)initPacket
,
461 VmbusPacketTypeDataInBand
,
462 VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED
);
465 DPRINT_ERR(NETVSC
, "unable to send receive buffer's gpadl to netvsp");
469 osd_WaitEventWait(netDevice
->ChannelInitEvent
);
471 /* Check the response */
472 if (initPacket
->Messages
.Version1Messages
.SendSendBufferComplete
.Status
!= NvspStatusSuccess
)
475 "Unable to complete send buffer initialzation with NetVsp - status %d",
476 initPacket
->Messages
.Version1Messages
.SendSendBufferComplete
.Status
);
481 netDevice
->SendSectionSize
= initPacket
->Messages
.Version1Messages
.SendSendBufferComplete
.SectionSize
;
486 NetVscDestroySendBuffer(netDevice
);
489 PutNetDevice(Device
);
495 NetVscDestroyReceiveBuffer(
496 struct NETVSC_DEVICE
*NetDevice
499 NVSP_MESSAGE
*revokePacket
;
503 DPRINT_ENTER(NETVSC
);
506 * If we got a section count, it means we received a
507 * SendReceiveBufferComplete msg (ie sent
508 * NvspMessage1TypeSendReceiveBuffer msg) therefore, we need
509 * to send a revoke msg here
511 if (NetDevice
->ReceiveSectionCount
)
513 DPRINT_INFO(NETVSC
, "Sending NvspMessage1TypeRevokeReceiveBuffer...");
515 /* Send the revoke receive buffer */
516 revokePacket
= &NetDevice
->RevokePacket
;
517 memset(revokePacket
, 0, sizeof(NVSP_MESSAGE
));
519 revokePacket
->Header
.MessageType
= NvspMessage1TypeRevokeReceiveBuffer
;
520 revokePacket
->Messages
.Version1Messages
.RevokeReceiveBuffer
.Id
= NETVSC_RECEIVE_BUFFER_ID
;
522 ret
= NetDevice
->Device
->Driver
->VmbusChannelInterface
.SendPacket(NetDevice
->Device
,
524 sizeof(NVSP_MESSAGE
),
525 (unsigned long)revokePacket
,
526 VmbusPacketTypeDataInBand
,
529 * If we failed here, we might as well return and
530 * have a leak rather than continue and a bugchk
534 DPRINT_ERR(NETVSC
, "unable to send revoke receive buffer to netvsp");
540 /* Teardown the gpadl on the vsp end */
541 if (NetDevice
->ReceiveBufferGpadlHandle
)
543 DPRINT_INFO(NETVSC
, "Tearing down receive buffer's GPADL...");
545 ret
= NetDevice
->Device
->Driver
->VmbusChannelInterface
.TeardownGpadl(NetDevice
->Device
,
546 NetDevice
->ReceiveBufferGpadlHandle
);
548 /* If we failed here, we might as well return and have a leak rather than continue and a bugchk */
551 DPRINT_ERR(NETVSC
, "unable to teardown receive buffer's gpadl");
555 NetDevice
->ReceiveBufferGpadlHandle
= 0;
558 if (NetDevice
->ReceiveBuffer
)
560 DPRINT_INFO(NETVSC
, "Freeing up receive buffer...");
562 /* Free up the receive buffer */
563 osd_PageFree(NetDevice
->ReceiveBuffer
, NetDevice
->ReceiveBufferSize
>> PAGE_SHIFT
);
564 NetDevice
->ReceiveBuffer
= NULL
;
567 if (NetDevice
->ReceiveSections
)
569 kfree(NetDevice
->ReceiveSections
);
570 NetDevice
->ReceiveSections
= NULL
;
571 NetDevice
->ReceiveSectionCount
= 0;
583 NetVscDestroySendBuffer(
584 struct NETVSC_DEVICE
*NetDevice
587 NVSP_MESSAGE
*revokePacket
;
591 DPRINT_ENTER(NETVSC
);
594 * If we got a section count, it means we received a
595 * SendReceiveBufferComplete msg (ie sent
596 * NvspMessage1TypeSendReceiveBuffer msg) therefore, we need
597 * to send a revoke msg here
599 if (NetDevice
->SendSectionSize
)
601 DPRINT_INFO(NETVSC
, "Sending NvspMessage1TypeRevokeSendBuffer...");
603 /* Send the revoke send buffer */
604 revokePacket
= &NetDevice
->RevokePacket
;
605 memset(revokePacket
, 0, sizeof(NVSP_MESSAGE
));
607 revokePacket
->Header
.MessageType
= NvspMessage1TypeRevokeSendBuffer
;
608 revokePacket
->Messages
.Version1Messages
.RevokeSendBuffer
.Id
= NETVSC_SEND_BUFFER_ID
;
610 ret
= NetDevice
->Device
->Driver
->VmbusChannelInterface
.SendPacket(NetDevice
->Device
,
612 sizeof(NVSP_MESSAGE
),
613 (unsigned long)revokePacket
,
614 VmbusPacketTypeDataInBand
,
616 /* If we failed here, we might as well return and have a leak rather than continue and a bugchk */
619 DPRINT_ERR(NETVSC
, "unable to send revoke send buffer to netvsp");
625 /* Teardown the gpadl on the vsp end */
626 if (NetDevice
->SendBufferGpadlHandle
)
628 DPRINT_INFO(NETVSC
, "Tearing down send buffer's GPADL...");
630 ret
= NetDevice
->Device
->Driver
->VmbusChannelInterface
.TeardownGpadl(NetDevice
->Device
,
631 NetDevice
->SendBufferGpadlHandle
);
633 /* If we failed here, we might as well return and have a leak rather than continue and a bugchk */
636 DPRINT_ERR(NETVSC
, "unable to teardown send buffer's gpadl");
640 NetDevice
->SendBufferGpadlHandle
= 0;
643 if (NetDevice
->SendBuffer
)
645 DPRINT_INFO(NETVSC
, "Freeing up send buffer...");
647 /* Free up the receive buffer */
648 osd_PageFree(NetDevice
->SendBuffer
, NetDevice
->SendBufferSize
>> PAGE_SHIFT
);
649 NetDevice
->SendBuffer
= NULL
;
661 struct hv_device
*Device
665 struct NETVSC_DEVICE
*netDevice
;
666 NVSP_MESSAGE
*initPacket
;
669 DPRINT_ENTER(NETVSC
);
671 netDevice
= GetOutboundNetDevice(Device
);
674 DPRINT_ERR(NETVSC
, "unable to get net device...device being destroyed?");
679 initPacket
= &netDevice
->ChannelInitPacket
;
681 memset(initPacket
, 0, sizeof(NVSP_MESSAGE
));
682 initPacket
->Header
.MessageType
= NvspMessageTypeInit
;
683 initPacket
->Messages
.InitMessages
.Init
.MinProtocolVersion
= NVSP_MIN_PROTOCOL_VERSION
;
684 initPacket
->Messages
.InitMessages
.Init
.MaxProtocolVersion
= NVSP_MAX_PROTOCOL_VERSION
;
686 DPRINT_INFO(NETVSC
, "Sending NvspMessageTypeInit...");
688 /* Send the init request */
689 ret
= Device
->Driver
->VmbusChannelInterface
.SendPacket(Device
,
691 sizeof(NVSP_MESSAGE
),
692 (unsigned long)initPacket
,
693 VmbusPacketTypeDataInBand
,
694 VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED
);
698 DPRINT_ERR(NETVSC
, "unable to send NvspMessageTypeInit");
702 osd_WaitEventWait(netDevice
->ChannelInitEvent
);
704 /* Now, check the response */
705 /* ASSERT(initPacket->Messages.InitMessages.InitComplete.MaximumMdlChainLength <= MAX_MULTIPAGE_BUFFER_COUNT); */
706 DPRINT_INFO(NETVSC
, "NvspMessageTypeInit status(%d) max mdl chain (%d)",
707 initPacket
->Messages
.InitMessages
.InitComplete
.Status
,
708 initPacket
->Messages
.InitMessages
.InitComplete
.MaximumMdlChainLength
);
710 if (initPacket
->Messages
.InitMessages
.InitComplete
.Status
!= NvspStatusSuccess
)
712 DPRINT_ERR(NETVSC
, "unable to initialize with netvsp (status 0x%x)", initPacket
->Messages
.InitMessages
.InitComplete
.Status
);
717 if (initPacket
->Messages
.InitMessages
.InitComplete
.NegotiatedProtocolVersion
!= NVSP_PROTOCOL_VERSION_1
)
719 DPRINT_ERR(NETVSC
, "unable to initialize with netvsp (version expected 1 got %d)",
720 initPacket
->Messages
.InitMessages
.InitComplete
.NegotiatedProtocolVersion
);
724 DPRINT_INFO(NETVSC
, "Sending NvspMessage1TypeSendNdisVersion...");
726 /* Send the ndis version */
727 memset(initPacket
, 0, sizeof(NVSP_MESSAGE
));
729 ndisVersion
= 0x00050000;
731 initPacket
->Header
.MessageType
= NvspMessage1TypeSendNdisVersion
;
732 initPacket
->Messages
.Version1Messages
.SendNdisVersion
.NdisMajorVersion
= (ndisVersion
& 0xFFFF0000) >> 16;
733 initPacket
->Messages
.Version1Messages
.SendNdisVersion
.NdisMinorVersion
= ndisVersion
& 0xFFFF;
735 /* Send the init request */
736 ret
= Device
->Driver
->VmbusChannelInterface
.SendPacket(Device
,
738 sizeof(NVSP_MESSAGE
),
739 (unsigned long)initPacket
,
740 VmbusPacketTypeDataInBand
,
744 DPRINT_ERR(NETVSC
, "unable to send NvspMessage1TypeSendNdisVersion");
749 * BUGBUG - We have to wait for the above msg since the
750 * netvsp uses KMCL which acknowledges packet (completion
751 * packet) since our Vmbus always set the
752 * VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED flag
754 /* osd_WaitEventWait(NetVscChannel->ChannelInitEvent); */
756 /* Post the big receive buffer to NetVSP */
757 ret
= NetVscInitializeReceiveBufferWithNetVsp(Device
);
760 ret
= NetVscInitializeSendBufferWithNetVsp(Device
);
764 PutNetDevice(Device
);
770 NetVscDisconnectFromVsp(
771 struct NETVSC_DEVICE
*NetDevice
774 DPRINT_ENTER(NETVSC
);
776 NetVscDestroyReceiveBuffer(NetDevice
);
777 NetVscDestroySendBuffer(NetDevice
);
789 Callback when the device belonging to this driver is added
794 struct hv_device
*Device
,
801 struct NETVSC_DEVICE
*netDevice
;
802 struct hv_netvsc_packet
*packet
;
805 struct netvsc_driver
*netDriver
= (struct netvsc_driver
*)Device
->Driver
;
807 DPRINT_ENTER(NETVSC
);
809 netDevice
= AllocNetDevice(Device
);
816 DPRINT_DBG(NETVSC
, "netvsc channel object allocated - %p", netDevice
);
818 /* Initialize the NetVSC channel extension */
819 netDevice
->ReceiveBufferSize
= NETVSC_RECEIVE_BUFFER_SIZE
;
820 spin_lock_init(&netDevice
->receive_packet_list_lock
);
822 netDevice
->SendBufferSize
= NETVSC_SEND_BUFFER_SIZE
;
824 INITIALIZE_LIST_HEAD(&netDevice
->ReceivePacketList
);
826 for (i
=0; i
< NETVSC_RECEIVE_PACKETLIST_COUNT
; i
++)
828 packet
= kzalloc(sizeof(struct hv_netvsc_packet
) + (NETVSC_RECEIVE_SG_COUNT
* sizeof(struct hv_page_buffer
)), GFP_KERNEL
);
831 DPRINT_DBG(NETVSC
, "unable to allocate netvsc pkts for receive pool (wanted %d got %d)", NETVSC_RECEIVE_PACKETLIST_COUNT
, i
);
835 INSERT_TAIL_LIST(&netDevice
->ReceivePacketList
, &packet
->ListEntry
);
837 netDevice
->ChannelInitEvent
= osd_WaitEventCreate();
839 /* Open the channel */
840 ret
= Device
->Driver
->VmbusChannelInterface
.Open(Device
,
841 netDriver
->RingBufferSize
,
842 netDriver
->RingBufferSize
,
844 NetVscOnChannelCallback
,
850 DPRINT_ERR(NETVSC
, "unable to open channel: %d", ret
);
855 /* Channel is opened */
856 DPRINT_INFO(NETVSC
, "*** NetVSC channel opened successfully! ***");
858 /* Connect with the NetVsp */
859 ret
= NetVscConnectToVsp(Device
);
862 DPRINT_ERR(NETVSC
, "unable to connect to NetVSP - %d", ret
);
867 DPRINT_INFO(NETVSC
, "*** NetVSC channel handshake result - %d ***", ret
);
873 /* Now, we can close the channel safely */
874 Device
->Driver
->VmbusChannelInterface
.Close(Device
);
880 kfree(netDevice
->ChannelInitEvent
);
882 while (!IsListEmpty(&netDevice
->ReceivePacketList
))
884 entry
= REMOVE_HEAD_LIST(&netDevice
->ReceivePacketList
);
885 packet
= CONTAINING_RECORD(entry
, struct hv_netvsc_packet
, ListEntry
);
889 ReleaseOutboundNetDevice(Device
);
890 ReleaseInboundNetDevice(Device
);
892 FreeNetDevice(netDevice
);
903 NetVscOnDeviceRemove()
906 Callback when the root bus device is removed
910 NetVscOnDeviceRemove(
911 struct hv_device
*Device
914 struct NETVSC_DEVICE
*netDevice
;
915 struct hv_netvsc_packet
*netvscPacket
;
919 DPRINT_ENTER(NETVSC
);
921 DPRINT_INFO(NETVSC
, "Disabling outbound traffic on net device (%p)...", Device
->Extension
);
923 /* Stop outbound traffic ie sends and receives completions */
924 netDevice
= ReleaseOutboundNetDevice(Device
);
927 DPRINT_ERR(NETVSC
, "No net device present!!");
931 /* Wait for all send completions */
932 while (atomic_read(&netDevice
->NumOutstandingSends
))
934 DPRINT_INFO(NETVSC
, "waiting for %d requests to complete...", atomic_read(&netDevice
->NumOutstandingSends
));
939 DPRINT_INFO(NETVSC
, "Disconnecting from netvsp...");
941 NetVscDisconnectFromVsp(netDevice
);
943 DPRINT_INFO(NETVSC
, "Disabling inbound traffic on net device (%p)...", Device
->Extension
);
945 /* Stop inbound traffic ie receives and sends completions */
946 netDevice
= ReleaseInboundNetDevice(Device
);
948 /* At this point, no one should be accessing netDevice except in here */
949 DPRINT_INFO(NETVSC
, "net device (%p) safe to remove", netDevice
);
951 /* Now, we can close the channel safely */
952 Device
->Driver
->VmbusChannelInterface
.Close(Device
);
954 /* Release all resources */
955 while (!IsListEmpty(&netDevice
->ReceivePacketList
))
957 entry
= REMOVE_HEAD_LIST(&netDevice
->ReceivePacketList
);
958 netvscPacket
= CONTAINING_RECORD(entry
, struct hv_netvsc_packet
, ListEntry
);
963 kfree(netDevice
->ChannelInitEvent
);
964 FreeNetDevice(netDevice
);
978 Perform any cleanup when the driver is removed
983 struct hv_driver
*drv
986 DPRINT_ENTER(NETVSC
);
992 NetVscOnSendCompletion(
993 struct hv_device
*Device
,
994 struct vmpacket_descriptor
*Packet
997 struct NETVSC_DEVICE
*netDevice
;
998 NVSP_MESSAGE
*nvspPacket
;
999 struct hv_netvsc_packet
*nvscPacket
;
1001 DPRINT_ENTER(NETVSC
);
1003 netDevice
= GetInboundNetDevice(Device
);
1006 DPRINT_ERR(NETVSC
, "unable to get net device...device being destroyed?");
1007 DPRINT_EXIT(NETVSC
);
1011 nvspPacket
= (NVSP_MESSAGE
*)((unsigned long)Packet
+ (Packet
->DataOffset8
<< 3));
1013 DPRINT_DBG(NETVSC
, "send completion packet - type %d", nvspPacket
->Header
.MessageType
);
1015 if (nvspPacket
->Header
.MessageType
== NvspMessageTypeInitComplete
||
1016 nvspPacket
->Header
.MessageType
== NvspMessage1TypeSendReceiveBufferComplete
||
1017 nvspPacket
->Header
.MessageType
== NvspMessage1TypeSendSendBufferComplete
)
1019 /* Copy the response back */
1020 memcpy(&netDevice
->ChannelInitPacket
, nvspPacket
, sizeof(NVSP_MESSAGE
));
1021 osd_WaitEventSet(netDevice
->ChannelInitEvent
);
1023 else if (nvspPacket
->Header
.MessageType
== NvspMessage1TypeSendRNDISPacketComplete
)
1025 /* Get the send context */
1026 nvscPacket
= (struct hv_netvsc_packet
*)(unsigned long)Packet
->TransactionId
;
1029 /* Notify the layer above us */
1030 nvscPacket
->Completion
.Send
.OnSendCompletion(nvscPacket
->Completion
.Send
.SendCompletionContext
);
1032 atomic_dec(&netDevice
->NumOutstandingSends
);
1036 DPRINT_ERR(NETVSC
, "Unknown send completion packet type - %d received!!", nvspPacket
->Header
.MessageType
);
1039 PutNetDevice(Device
);
1040 DPRINT_EXIT(NETVSC
);
1047 struct hv_device
*Device
,
1048 struct hv_netvsc_packet
*Packet
1051 struct NETVSC_DEVICE
*netDevice
;
1054 NVSP_MESSAGE sendMessage
;
1056 DPRINT_ENTER(NETVSC
);
1058 netDevice
= GetOutboundNetDevice(Device
);
1061 DPRINT_ERR(NETVSC
, "net device (%p) shutting down...ignoring outbound packets", netDevice
);
1062 DPRINT_EXIT(NETVSC
);
1066 sendMessage
.Header
.MessageType
= NvspMessage1TypeSendRNDISPacket
;
1067 if (Packet
->IsDataPacket
)
1068 sendMessage
.Messages
.Version1Messages
.SendRNDISPacket
.ChannelType
= 0;/* 0 is RMC_DATA; */
1070 sendMessage
.Messages
.Version1Messages
.SendRNDISPacket
.ChannelType
= 1;/* 1 is RMC_CONTROL; */
1072 /* Not using send buffer section */
1073 sendMessage
.Messages
.Version1Messages
.SendRNDISPacket
.SendBufferSectionIndex
= 0xFFFFFFFF;
1074 sendMessage
.Messages
.Version1Messages
.SendRNDISPacket
.SendBufferSectionSize
= 0;
1076 if (Packet
->PageBufferCount
)
1078 ret
= Device
->Driver
->VmbusChannelInterface
.SendPacketPageBuffer(Device
,
1079 Packet
->PageBuffers
,
1080 Packet
->PageBufferCount
,
1082 sizeof(NVSP_MESSAGE
),
1083 (unsigned long)Packet
);
1087 ret
= Device
->Driver
->VmbusChannelInterface
.SendPacket(Device
,
1089 sizeof(NVSP_MESSAGE
),
1090 (unsigned long)Packet
,
1091 VmbusPacketTypeDataInBand
,
1092 VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED
);
1098 DPRINT_ERR(NETVSC
, "Unable to send packet %p ret %d", Packet
, ret
);
1101 atomic_inc(&netDevice
->NumOutstandingSends
);
1102 PutNetDevice(Device
);
1104 DPRINT_EXIT(NETVSC
);
1111 struct hv_device
*Device
,
1112 struct vmpacket_descriptor
*Packet
1115 struct NETVSC_DEVICE
*netDevice
;
1116 struct vmtransfer_page_packet_header
*vmxferpagePacket
;
1117 NVSP_MESSAGE
*nvspPacket
;
1118 struct hv_netvsc_packet
*netvscPacket
=NULL
;
1120 unsigned long start
;
1121 unsigned long end
, endVirtual
;
1122 /* struct netvsc_driver *netvscDriver; */
1123 struct xferpage_packet
*xferpagePacket
=NULL
;
1124 LIST_ENTRY listHead
;
1127 int count
=0, bytesRemain
=0;
1128 unsigned long flags
;
1130 DPRINT_ENTER(NETVSC
);
1132 netDevice
= GetInboundNetDevice(Device
);
1135 DPRINT_ERR(NETVSC
, "unable to get net device...device being destroyed?");
1136 DPRINT_EXIT(NETVSC
);
1140 /* All inbound packets other than send completion should be xfer page packet */
1141 if (Packet
->Type
!= VmbusPacketTypeDataUsingTransferPages
)
1143 DPRINT_ERR(NETVSC
, "Unknown packet type received - %d", Packet
->Type
);
1144 PutNetDevice(Device
);
1148 nvspPacket
= (NVSP_MESSAGE
*)((unsigned long)Packet
+ (Packet
->DataOffset8
<< 3));
1150 /* Make sure this is a valid nvsp packet */
1151 if (nvspPacket
->Header
.MessageType
!= NvspMessage1TypeSendRNDISPacket
)
1153 DPRINT_ERR(NETVSC
, "Unknown nvsp packet type received - %d", nvspPacket
->Header
.MessageType
);
1154 PutNetDevice(Device
);
1158 DPRINT_DBG(NETVSC
, "NVSP packet received - type %d", nvspPacket
->Header
.MessageType
);
1160 vmxferpagePacket
= (struct vmtransfer_page_packet_header
*)Packet
;
1162 if (vmxferpagePacket
->TransferPageSetId
!= NETVSC_RECEIVE_BUFFER_ID
)
1164 DPRINT_ERR(NETVSC
, "Invalid xfer page set id - expecting %x got %x", NETVSC_RECEIVE_BUFFER_ID
, vmxferpagePacket
->TransferPageSetId
);
1165 PutNetDevice(Device
);
1169 DPRINT_DBG(NETVSC
, "xfer page - range count %d", vmxferpagePacket
->RangeCount
);
1171 INITIALIZE_LIST_HEAD(&listHead
);
1174 * Grab free packets (range count + 1) to represent this xfer
1175 * page packet. +1 to represent the xfer page packet itself.
1176 * We grab it here so that we know exactly how many we can
1179 spin_lock_irqsave(&netDevice
->receive_packet_list_lock
, flags
);
1180 while (!IsListEmpty(&netDevice
->ReceivePacketList
))
1182 entry
= REMOVE_HEAD_LIST(&netDevice
->ReceivePacketList
);
1183 netvscPacket
= CONTAINING_RECORD(entry
, struct hv_netvsc_packet
, ListEntry
);
1185 INSERT_TAIL_LIST(&listHead
, &netvscPacket
->ListEntry
);
1187 if (++count
== vmxferpagePacket
->RangeCount
+ 1)
1190 spin_unlock_irqrestore(&netDevice
->receive_packet_list_lock
, flags
);
1193 * We need at least 2 netvsc pkts (1 to represent the xfer
1194 * page and at least 1 for the range) i.e. we can handled
1195 * some of the xfer page packet ranges...
1199 DPRINT_ERR(NETVSC
, "Got only %d netvsc pkt...needed %d pkts. Dropping this xfer page packet completely!", count
, vmxferpagePacket
->RangeCount
+1);
1201 /* Return it to the freelist */
1202 spin_lock_irqsave(&netDevice
->receive_packet_list_lock
, flags
);
1203 for (i
=count
; i
!= 0; i
--)
1205 entry
= REMOVE_HEAD_LIST(&listHead
);
1206 netvscPacket
= CONTAINING_RECORD(entry
, struct hv_netvsc_packet
, ListEntry
);
1208 INSERT_TAIL_LIST(&netDevice
->ReceivePacketList
, &netvscPacket
->ListEntry
);
1210 spin_unlock_irqrestore(&netDevice
->receive_packet_list_lock
, flags
);
1212 NetVscSendReceiveCompletion(Device
, vmxferpagePacket
->d
.TransactionId
);
1214 PutNetDevice(Device
);
1218 /* Remove the 1st packet to represent the xfer page packet itself */
1219 entry
= REMOVE_HEAD_LIST(&listHead
);
1220 xferpagePacket
= CONTAINING_RECORD(entry
, struct xferpage_packet
, ListEntry
);
1221 xferpagePacket
->Count
= count
- 1; /* This is how much we can satisfy */
1222 ASSERT(xferpagePacket
->Count
> 0 && xferpagePacket
->Count
<= vmxferpagePacket
->RangeCount
);
1224 if (xferpagePacket
->Count
!= vmxferpagePacket
->RangeCount
)
1226 DPRINT_INFO(NETVSC
, "Needed %d netvsc pkts to satisy this xfer page...got %d", vmxferpagePacket
->RangeCount
, xferpagePacket
->Count
);
1229 /* Each range represents 1 RNDIS pkt that contains 1 ethernet frame */
1230 for (i
=0; i
< (count
- 1); i
++)
1232 entry
= REMOVE_HEAD_LIST(&listHead
);
1233 netvscPacket
= CONTAINING_RECORD(entry
, struct hv_netvsc_packet
, ListEntry
);
1235 /* Initialize the netvsc packet */
1236 netvscPacket
->XferPagePacket
= xferpagePacket
;
1237 netvscPacket
->Completion
.Recv
.OnReceiveCompletion
= NetVscOnReceiveCompletion
;
1238 netvscPacket
->Completion
.Recv
.ReceiveCompletionContext
= netvscPacket
;
1239 netvscPacket
->Device
= Device
;
1240 netvscPacket
->Completion
.Recv
.ReceiveCompletionTid
= vmxferpagePacket
->d
.TransactionId
; /* Save this so that we can send it back */
1242 netvscPacket
->TotalDataBufferLength
= vmxferpagePacket
->Ranges
[i
].ByteCount
;
1243 netvscPacket
->PageBufferCount
= 1;
1245 ASSERT(vmxferpagePacket
->Ranges
[i
].ByteOffset
+ vmxferpagePacket
->Ranges
[i
].ByteCount
< netDevice
->ReceiveBufferSize
);
1247 netvscPacket
->PageBuffers
[0].Length
= vmxferpagePacket
->Ranges
[i
].ByteCount
;
1249 start
= virt_to_phys((void*)((unsigned long)netDevice
->ReceiveBuffer
+ vmxferpagePacket
->Ranges
[i
].ByteOffset
));
1251 netvscPacket
->PageBuffers
[0].Pfn
= start
>> PAGE_SHIFT
;
1252 endVirtual
= (unsigned long)netDevice
->ReceiveBuffer
1253 + vmxferpagePacket
->Ranges
[i
].ByteOffset
1254 + vmxferpagePacket
->Ranges
[i
].ByteCount
-1;
1255 end
= virt_to_phys((void*)endVirtual
);
1257 /* Calculate the page relative offset */
1258 netvscPacket
->PageBuffers
[0].Offset
= vmxferpagePacket
->Ranges
[i
].ByteOffset
& (PAGE_SIZE
-1);
1259 if ((end
>> PAGE_SHIFT
) != (start
>>PAGE_SHIFT
)) {
1260 /* Handle frame across multiple pages: */
1261 netvscPacket
->PageBuffers
[0].Length
=
1262 (netvscPacket
->PageBuffers
[0].Pfn
<<PAGE_SHIFT
) + PAGE_SIZE
- start
;
1263 bytesRemain
= netvscPacket
->TotalDataBufferLength
- netvscPacket
->PageBuffers
[0].Length
;
1264 for (j
=1; j
<NETVSC_PACKET_MAXPAGE
; j
++) {
1265 netvscPacket
->PageBuffers
[j
].Offset
= 0;
1266 if (bytesRemain
<= PAGE_SIZE
) {
1267 netvscPacket
->PageBuffers
[j
].Length
= bytesRemain
;
1270 netvscPacket
->PageBuffers
[j
].Length
= PAGE_SIZE
;
1271 bytesRemain
-= PAGE_SIZE
;
1273 netvscPacket
->PageBuffers
[j
].Pfn
=
1274 virt_to_phys((void*)(endVirtual
- bytesRemain
)) >> PAGE_SHIFT
;
1275 netvscPacket
->PageBufferCount
++;
1276 if (bytesRemain
== 0)
1279 ASSERT(bytesRemain
== 0);
1281 DPRINT_DBG(NETVSC
, "[%d] - (abs offset %u len %u) => (pfn %llx, offset %u, len %u)",
1283 vmxferpagePacket
->Ranges
[i
].ByteOffset
,
1284 vmxferpagePacket
->Ranges
[i
].ByteCount
,
1285 netvscPacket
->PageBuffers
[0].Pfn
,
1286 netvscPacket
->PageBuffers
[0].Offset
,
1287 netvscPacket
->PageBuffers
[0].Length
);
1289 /* Pass it to the upper layer */
1290 ((struct netvsc_driver
*)Device
->Driver
)->OnReceiveCallback(Device
, netvscPacket
);
1292 NetVscOnReceiveCompletion(netvscPacket
->Completion
.Recv
.ReceiveCompletionContext
);
1295 ASSERT(IsListEmpty(&listHead
));
1297 PutNetDevice(Device
);
1298 DPRINT_EXIT(NETVSC
);
1303 NetVscSendReceiveCompletion(
1304 struct hv_device
*Device
,
1308 NVSP_MESSAGE recvcompMessage
;
1312 DPRINT_DBG(NETVSC
, "Sending receive completion pkt - %llx", TransactionId
);
1314 recvcompMessage
.Header
.MessageType
= NvspMessage1TypeSendRNDISPacketComplete
;
1316 /* FIXME: Pass in the status */
1317 recvcompMessage
.Messages
.Version1Messages
.SendRNDISPacketComplete
.Status
= NvspStatusSuccess
;
1320 /* Send the completion */
1321 ret
= Device
->Driver
->VmbusChannelInterface
.SendPacket(Device
,
1323 sizeof(NVSP_MESSAGE
),
1325 VmbusPacketTypeCompletion
,
1327 if (ret
== 0) /* success */
1331 else if (ret
== -1) /* no more room...wait a bit and attempt to retry 3 times */
1334 DPRINT_ERR(NETVSC
, "unable to send receive completion pkt (tid %llx)...retrying %d", TransactionId
, retries
);
1339 goto retry_send_cmplt
;
1343 DPRINT_ERR(NETVSC
, "unable to send receive completion pkt (tid %llx)...give up retrying", TransactionId
);
1348 DPRINT_ERR(NETVSC
, "unable to send receive completion pkt - %llx", TransactionId
);
1352 /* Send a receive completion packet to RNDIS device (ie NetVsp) */
1354 NetVscOnReceiveCompletion(
1357 struct hv_netvsc_packet
*packet
= (struct hv_netvsc_packet
*)Context
;
1358 struct hv_device
*device
= (struct hv_device
*)packet
->Device
;
1359 struct NETVSC_DEVICE
*netDevice
;
1360 u64 transactionId
=0;
1361 bool fSendReceiveComp
= false;
1362 unsigned long flags
;
1364 DPRINT_ENTER(NETVSC
);
1366 ASSERT(packet
->XferPagePacket
);
1368 /* Even though it seems logical to do a GetOutboundNetDevice() here to send out receive completion, */
1369 /* we are using GetInboundNetDevice() since we may have disable outbound traffic already. */
1370 netDevice
= GetInboundNetDevice(device
);
1373 DPRINT_ERR(NETVSC
, "unable to get net device...device being destroyed?");
1374 DPRINT_EXIT(NETVSC
);
1378 /* Overloading use of the lock. */
1379 spin_lock_irqsave(&netDevice
->receive_packet_list_lock
, flags
);
1381 ASSERT(packet
->XferPagePacket
->Count
> 0);
1382 packet
->XferPagePacket
->Count
--;
1384 /* Last one in the line that represent 1 xfer page packet. */
1385 /* Return the xfer page packet itself to the freelist */
1386 if (packet
->XferPagePacket
->Count
== 0)
1388 fSendReceiveComp
= true;
1389 transactionId
= packet
->Completion
.Recv
.ReceiveCompletionTid
;
1391 INSERT_TAIL_LIST(&netDevice
->ReceivePacketList
, &packet
->XferPagePacket
->ListEntry
);
1394 /* Put the packet back */
1395 INSERT_TAIL_LIST(&netDevice
->ReceivePacketList
, &packet
->ListEntry
);
1396 spin_unlock_irqrestore(&netDevice
->receive_packet_list_lock
, flags
);
1398 /* Send a receive completion for the xfer page packet */
1399 if (fSendReceiveComp
)
1401 NetVscSendReceiveCompletion(device
, transactionId
);
1404 PutNetDevice(device
);
1405 DPRINT_EXIT(NETVSC
);
1411 NetVscOnChannelCallback(
1415 const int netPacketSize
=2048;
1417 struct hv_device
*device
=(struct hv_device
*)Context
;
1418 struct NETVSC_DEVICE
*netDevice
;
1422 unsigned char packet
[netPacketSize
];
1423 struct vmpacket_descriptor
*desc
;
1424 unsigned char *buffer
=packet
;
1425 int bufferlen
=netPacketSize
;
1428 DPRINT_ENTER(NETVSC
);
1432 netDevice
= GetInboundNetDevice(device
);
1435 DPRINT_ERR(NETVSC
, "net device (%p) shutting down...ignoring inbound packets", netDevice
);
1436 DPRINT_EXIT(NETVSC
);
1442 ret
= device
->Driver
->VmbusChannelInterface
.RecvPacketRaw(device
,
1452 DPRINT_DBG(NETVSC
, "receive %d bytes, tid %llx", bytesRecvd
, requestId
);
1454 desc
= (struct vmpacket_descriptor
*)buffer
;
1457 case VmbusPacketTypeCompletion
:
1458 NetVscOnSendCompletion(device
, desc
);
1461 case VmbusPacketTypeDataUsingTransferPages
:
1462 NetVscOnReceive(device
, desc
);
1466 DPRINT_ERR(NETVSC
, "unhandled packet type %d, tid %llx len %d\n", desc
->Type
, requestId
, bytesRecvd
);
1471 if (bufferlen
> netPacketSize
)
1476 bufferlen
= netPacketSize
;
1481 /* DPRINT_DBG(NETVSC, "nothing else to read..."); */
1484 if (bufferlen
> netPacketSize
)
1489 bufferlen
= netPacketSize
;
1495 else if (ret
== -2) /* Handle large packet */
1497 buffer
= kmalloc(bytesRecvd
, GFP_ATOMIC
);
1500 /* Try again next time around */
1501 DPRINT_ERR(NETVSC
, "unable to allocate buffer of size (%d)!!", bytesRecvd
);
1505 bufferlen
= bytesRecvd
;
1513 PutNetDevice(device
);
1514 DPRINT_EXIT(NETVSC
);