Staging: hv: make netDevice->ReceivePacketListLock a real spinlock
[safe/jmp/linux-2.6] / drivers / staging / hv / NetVsc.c
1 /*
2  *
3  * Copyright (c) 2009, Microsoft Corporation.
4  *
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.
8  *
9  * This program is distributed in the hope it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
12  * more details.
13  *
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.
17  *
18  * Authors:
19  *   Hank Janssen  <hjanssen@microsoft.com>
20  *
21  */
22
23 #define KERNEL_2_6_27
24
25 #include <linux/kernel.h>
26 #include <linux/mm.h>
27 #include "include/logging.h"
28 #include "NetVsc.h"
29 #include "RndisFilter.h"
30
31
32 //
33 // Globals
34 //
35 static const char* gDriverName="netvsc";
36
37 // {F8615163-DF3E-46c5-913F-F2D2F965ED0E}
38 static const GUID gNetVscDeviceType={
39         .Data = {0x63, 0x51, 0x61, 0xF8, 0x3E, 0xDF, 0xc5, 0x46, 0x91, 0x3F, 0xF2, 0xD2, 0xF9, 0x65, 0xED, 0x0E}
40 };
41
42
43 //
44 // Internal routines
45 //
46 static int
47 NetVscOnDeviceAdd(
48         DEVICE_OBJECT   *Device,
49         void                    *AdditionalInfo
50         );
51
52 static int
53 NetVscOnDeviceRemove(
54         DEVICE_OBJECT *Device
55         );
56
57 static void
58 NetVscOnCleanup(
59         DRIVER_OBJECT *Driver
60         );
61
62 static void
63 NetVscOnChannelCallback(
64         void * context
65         );
66
67 static int
68 NetVscInitializeSendBufferWithNetVsp(
69         DEVICE_OBJECT                   *Device
70         );
71
72 static int
73 NetVscInitializeReceiveBufferWithNetVsp(
74         DEVICE_OBJECT                   *Device
75         );
76
77 static int
78 NetVscDestroySendBuffer(
79         NETVSC_DEVICE   *NetDevice
80         );
81
82 static int
83 NetVscDestroyReceiveBuffer(
84         NETVSC_DEVICE   *NetDevice
85         );
86
87 static int
88 NetVscConnectToVsp(
89         DEVICE_OBJECT           *Device
90         );
91
92 static void
93 NetVscOnSendCompletion(
94         DEVICE_OBJECT           *Device,
95         VMPACKET_DESCRIPTOR *Packet
96         );
97
98 static int
99 NetVscOnSend(
100         DEVICE_OBJECT   *Device,
101         NETVSC_PACKET   *Packet
102         );
103
104 static void
105 NetVscOnReceive(
106         DEVICE_OBJECT           *Device,
107         VMPACKET_DESCRIPTOR *Packet
108         );
109
110 static void
111 NetVscOnReceiveCompletion(
112         void * Context
113         );
114
115 static void
116 NetVscSendReceiveCompletion(
117         DEVICE_OBJECT   *Device,
118         u64                     TransactionId
119         );
120
121 static inline NETVSC_DEVICE* AllocNetDevice(DEVICE_OBJECT *Device)
122 {
123         NETVSC_DEVICE *netDevice;
124
125         netDevice = kzalloc(sizeof(NETVSC_DEVICE), GFP_KERNEL);
126         if (!netDevice)
127                 return NULL;
128
129         // Set to 2 to allow both inbound and outbound traffic
130         InterlockedCompareExchange(&netDevice->RefCount, 2, 0);
131
132         netDevice->Device = Device;
133         Device->Extension = netDevice;
134
135         return netDevice;
136 }
137
138 static inline void FreeNetDevice(NETVSC_DEVICE *Device)
139 {
140         ASSERT(Device->RefCount == 0);
141         Device->Device->Extension = NULL;
142         kfree(Device);
143 }
144
145
146 // Get the net device object iff exists and its refcount > 1
147 static inline NETVSC_DEVICE* GetOutboundNetDevice(DEVICE_OBJECT *Device)
148 {
149         NETVSC_DEVICE *netDevice;
150
151         netDevice = (NETVSC_DEVICE*)Device->Extension;
152         if (netDevice && netDevice->RefCount > 1)
153         {
154                 InterlockedIncrement(&netDevice->RefCount);
155         }
156         else
157         {
158                 netDevice = NULL;
159         }
160
161         return netDevice;
162 }
163
164 // Get the net device object iff exists and its refcount > 0
165 static inline NETVSC_DEVICE* GetInboundNetDevice(DEVICE_OBJECT  *Device)
166 {
167         NETVSC_DEVICE *netDevice;
168
169         netDevice = (NETVSC_DEVICE*)Device->Extension;
170         if (netDevice && netDevice->RefCount)
171         {
172                 InterlockedIncrement(&netDevice->RefCount);
173         }
174         else
175         {
176                 netDevice = NULL;
177         }
178
179         return netDevice;
180 }
181
182 static inline void PutNetDevice(DEVICE_OBJECT *Device)
183 {
184         NETVSC_DEVICE *netDevice;
185
186         netDevice = (NETVSC_DEVICE*)Device->Extension;
187         ASSERT(netDevice);
188
189         InterlockedDecrement(&netDevice->RefCount);
190 }
191
192 static inline NETVSC_DEVICE* ReleaseOutboundNetDevice(DEVICE_OBJECT *Device)
193 {
194         NETVSC_DEVICE *netDevice;
195
196         netDevice = (NETVSC_DEVICE*)Device->Extension;
197         if (netDevice == NULL)
198                 return NULL;
199
200         // Busy wait until the ref drop to 2, then set it to 1
201         while (InterlockedCompareExchange(&netDevice->RefCount, 1, 2) != 2)
202         {
203                 Sleep(100);
204         }
205
206         return netDevice;
207 }
208
209 static inline NETVSC_DEVICE* ReleaseInboundNetDevice(DEVICE_OBJECT *Device)
210 {
211         NETVSC_DEVICE *netDevice;
212
213         netDevice = (NETVSC_DEVICE*)Device->Extension;
214         if (netDevice == NULL)
215                 return NULL;
216
217         // Busy wait until the ref drop to 1, then set it to 0
218         while (InterlockedCompareExchange(&netDevice->RefCount, 0, 1) != 1)
219         {
220                 Sleep(100);
221         }
222
223         Device->Extension = NULL;
224         return netDevice;
225 }
226
227 /*++;
228
229
230 Name:
231         NetVscInitialize()
232
233 Description:
234         Main entry point
235
236 --*/
237 int
238 NetVscInitialize(
239         DRIVER_OBJECT *drv
240         )
241 {
242         NETVSC_DRIVER_OBJECT* driver = (NETVSC_DRIVER_OBJECT*)drv;
243         int ret=0;
244
245         DPRINT_ENTER(NETVSC);
246
247         DPRINT_DBG(NETVSC, "sizeof(NETVSC_PACKET)=%d, sizeof(NVSP_MESSAGE)=%d, sizeof(VMTRANSFER_PAGE_PACKET_HEADER)=%d",
248                 sizeof(NETVSC_PACKET), sizeof(NVSP_MESSAGE), sizeof(VMTRANSFER_PAGE_PACKET_HEADER));
249
250         // Make sure we are at least 2 pages since 1 page is used for control
251         ASSERT(driver->RingBufferSize >= (PAGE_SIZE << 1));
252
253         drv->name = gDriverName;
254         memcpy(&drv->deviceType, &gNetVscDeviceType, sizeof(GUID));
255
256         // Make sure it is set by the caller
257         ASSERT(driver->OnReceiveCallback);
258         ASSERT(driver->OnLinkStatusChanged);
259
260         // Setup the dispatch table
261         driver->Base.OnDeviceAdd                = NetVscOnDeviceAdd;
262         driver->Base.OnDeviceRemove             = NetVscOnDeviceRemove;
263         driver->Base.OnCleanup                  = NetVscOnCleanup;
264
265         driver->OnSend                                  = NetVscOnSend;
266
267         RndisFilterInit(driver);
268
269         DPRINT_EXIT(NETVSC);
270
271         return ret;
272 }
273
274 static int
275 NetVscInitializeReceiveBufferWithNetVsp(
276         DEVICE_OBJECT   *Device
277         )
278 {
279         int ret=0;
280         NETVSC_DEVICE *netDevice;
281         NVSP_MESSAGE *initPacket;
282
283         DPRINT_ENTER(NETVSC);
284
285         netDevice = GetOutboundNetDevice(Device);
286         if (!netDevice)
287         {
288                 DPRINT_ERR(NETVSC, "unable to get net device...device being destroyed?");
289                 DPRINT_EXIT(NETVSC);
290                 return -1;
291         }
292         ASSERT(netDevice->ReceiveBufferSize > 0);
293         ASSERT((netDevice->ReceiveBufferSize & (PAGE_SIZE-1)) == 0); // page-size grandularity
294
295         netDevice->ReceiveBuffer = PageAlloc(netDevice->ReceiveBufferSize >> PAGE_SHIFT);
296         if (!netDevice->ReceiveBuffer)
297         {
298                 DPRINT_ERR(NETVSC, "unable to allocate receive buffer of size %d", netDevice->ReceiveBufferSize);
299                 ret = -1;
300                 goto Cleanup;
301         }
302         ASSERT(((unsigned long)netDevice->ReceiveBuffer & (PAGE_SIZE-1)) == 0); // page-aligned buffer
303
304         DPRINT_INFO(NETVSC, "Establishing receive buffer's GPADL...");
305
306         // Establish the gpadl handle for this buffer on this channel.
307         // Note: This call uses the vmbus connection rather than the channel to establish
308         // the gpadl handle.
309         ret = Device->Driver->VmbusChannelInterface.EstablishGpadl(Device,
310                                                                                                                                 netDevice->ReceiveBuffer,
311                                                                                                                                 netDevice->ReceiveBufferSize,
312                                                                                                                                 &netDevice->ReceiveBufferGpadlHandle);
313
314         if (ret != 0)
315         {
316                 DPRINT_ERR(NETVSC, "unable to establish receive buffer's gpadl");
317                 goto Cleanup;
318         }
319
320         //WaitEventWait(ext->ChannelInitEvent);
321
322         // Notify the NetVsp of the gpadl handle
323         DPRINT_INFO(NETVSC, "Sending NvspMessage1TypeSendReceiveBuffer...");
324
325         initPacket = &netDevice->ChannelInitPacket;
326
327         memset(initPacket, 0, sizeof(NVSP_MESSAGE));
328
329     initPacket->Header.MessageType = NvspMessage1TypeSendReceiveBuffer;
330     initPacket->Messages.Version1Messages.SendReceiveBuffer.GpadlHandle = netDevice->ReceiveBufferGpadlHandle;
331     initPacket->Messages.Version1Messages.SendReceiveBuffer.Id = NETVSC_RECEIVE_BUFFER_ID;
332
333         // Send the gpadl notification request
334         ret = Device->Driver->VmbusChannelInterface.SendPacket(Device,
335                                                                                                                         initPacket,
336                                                                                                                         sizeof(NVSP_MESSAGE),
337                                                                                                                         (unsigned long)initPacket,
338                                                                                                                         VmbusPacketTypeDataInBand,
339                                                                                                                         VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
340         if (ret != 0)
341         {
342                 DPRINT_ERR(NETVSC, "unable to send receive buffer's gpadl to netvsp");
343                 goto Cleanup;
344         }
345
346         WaitEventWait(netDevice->ChannelInitEvent);
347
348         // Check the response
349         if (initPacket->Messages.Version1Messages.SendReceiveBufferComplete.Status != NvspStatusSuccess)
350         {
351                 DPRINT_ERR(NETVSC,
352                         "Unable to complete receive buffer initialzation with NetVsp - status %d",
353                         initPacket->Messages.Version1Messages.SendReceiveBufferComplete.Status);
354                 ret = -1;
355                 goto Cleanup;
356         }
357
358         // Parse the response
359         ASSERT(netDevice->ReceiveSectionCount == 0);
360         ASSERT(netDevice->ReceiveSections == NULL);
361
362         netDevice->ReceiveSectionCount = initPacket->Messages.Version1Messages.SendReceiveBufferComplete.NumSections;
363
364         netDevice->ReceiveSections = kmalloc(netDevice->ReceiveSectionCount * sizeof(NVSP_1_RECEIVE_BUFFER_SECTION), GFP_KERNEL);
365         if (netDevice->ReceiveSections == NULL)
366         {
367                 ret = -1;
368                 goto Cleanup;
369         }
370
371         memcpy(netDevice->ReceiveSections,
372                 initPacket->Messages.Version1Messages.SendReceiveBufferComplete.Sections,
373                 netDevice->ReceiveSectionCount * sizeof(NVSP_1_RECEIVE_BUFFER_SECTION));
374
375         DPRINT_INFO(NETVSC,
376                 "Receive sections info (count %d, offset %d, endoffset %d, suballoc size %d, num suballocs %d)",
377                 netDevice->ReceiveSectionCount, netDevice->ReceiveSections[0].Offset, netDevice->ReceiveSections[0].EndOffset,
378                 netDevice->ReceiveSections[0].SubAllocationSize, netDevice->ReceiveSections[0].NumSubAllocations);
379
380
381         //For 1st release, there should only be 1 section that represents the entire receive buffer
382         if (netDevice->ReceiveSectionCount != 1 ||
383                 netDevice->ReceiveSections->Offset != 0 )
384         {
385                 ret = -1;
386                 goto Cleanup;
387         }
388
389         goto Exit;
390
391 Cleanup:
392         NetVscDestroyReceiveBuffer(netDevice);
393
394 Exit:
395         PutNetDevice(Device);
396         DPRINT_EXIT(NETVSC);
397         return ret;
398 }
399
400
401 static int
402 NetVscInitializeSendBufferWithNetVsp(
403         DEVICE_OBJECT   *Device
404         )
405 {
406         int ret=0;
407         NETVSC_DEVICE *netDevice;
408         NVSP_MESSAGE *initPacket;
409
410         DPRINT_ENTER(NETVSC);
411
412         netDevice = GetOutboundNetDevice(Device);
413         if (!netDevice)
414         {
415                 DPRINT_ERR(NETVSC, "unable to get net device...device being destroyed?");
416                 DPRINT_EXIT(NETVSC);
417                 return -1;
418         }
419         ASSERT(netDevice->SendBufferSize > 0);
420         ASSERT((netDevice->SendBufferSize & (PAGE_SIZE-1)) == 0); // page-size grandularity
421
422         netDevice->SendBuffer = PageAlloc(netDevice->SendBufferSize >> PAGE_SHIFT);
423         if (!netDevice->SendBuffer)
424         {
425                 DPRINT_ERR(NETVSC, "unable to allocate send buffer of size %d", netDevice->SendBufferSize);
426                 ret = -1;
427                 goto Cleanup;
428         }
429         ASSERT(((unsigned long)netDevice->SendBuffer & (PAGE_SIZE-1)) == 0); // page-aligned buffer
430
431         DPRINT_INFO(NETVSC, "Establishing send buffer's GPADL...");
432
433         // Establish the gpadl handle for this buffer on this channel.
434         // Note: This call uses the vmbus connection rather than the channel to establish
435         // the gpadl handle.
436         ret = Device->Driver->VmbusChannelInterface.EstablishGpadl(Device,
437                                                                                                                                 netDevice->SendBuffer,
438                                                                                                                                 netDevice->SendBufferSize,
439                                                                                                                                 &netDevice->SendBufferGpadlHandle);
440
441         if (ret != 0)
442         {
443                 DPRINT_ERR(NETVSC, "unable to establish send buffer's gpadl");
444                 goto Cleanup;
445         }
446
447         //WaitEventWait(ext->ChannelInitEvent);
448
449         // Notify the NetVsp of the gpadl handle
450         DPRINT_INFO(NETVSC, "Sending NvspMessage1TypeSendSendBuffer...");
451
452         initPacket = &netDevice->ChannelInitPacket;
453
454         memset(initPacket, 0, sizeof(NVSP_MESSAGE));
455
456     initPacket->Header.MessageType = NvspMessage1TypeSendSendBuffer;
457     initPacket->Messages.Version1Messages.SendReceiveBuffer.GpadlHandle = netDevice->SendBufferGpadlHandle;
458     initPacket->Messages.Version1Messages.SendReceiveBuffer.Id = NETVSC_SEND_BUFFER_ID;
459
460         // Send the gpadl notification request
461         ret = Device->Driver->VmbusChannelInterface.SendPacket(Device,
462                                                                                                                         initPacket,
463                                                                                                                         sizeof(NVSP_MESSAGE),
464                                                                                                                         (unsigned long)initPacket,
465                                                                                                                         VmbusPacketTypeDataInBand,
466                                                                                                                         VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
467         if (ret != 0)
468         {
469                 DPRINT_ERR(NETVSC, "unable to send receive buffer's gpadl to netvsp");
470                 goto Cleanup;
471         }
472
473         WaitEventWait(netDevice->ChannelInitEvent);
474
475         // Check the response
476         if (initPacket->Messages.Version1Messages.SendSendBufferComplete.Status != NvspStatusSuccess)
477         {
478                 DPRINT_ERR(NETVSC,
479                         "Unable to complete send buffer initialzation with NetVsp - status %d",
480                         initPacket->Messages.Version1Messages.SendSendBufferComplete.Status);
481                 ret = -1;
482                 goto Cleanup;
483         }
484
485         netDevice->SendSectionSize = initPacket->Messages.Version1Messages.SendSendBufferComplete.SectionSize;
486
487         goto Exit;
488
489 Cleanup:
490         NetVscDestroySendBuffer(netDevice);
491
492 Exit:
493         PutNetDevice(Device);
494         DPRINT_EXIT(NETVSC);
495         return ret;
496 }
497
498 static int
499 NetVscDestroyReceiveBuffer(
500         NETVSC_DEVICE   *NetDevice
501         )
502 {
503         NVSP_MESSAGE *revokePacket;
504         int ret=0;
505
506
507         DPRINT_ENTER(NETVSC);
508
509         // If we got a section count, it means we received a SendReceiveBufferComplete msg
510         // (ie sent NvspMessage1TypeSendReceiveBuffer msg) therefore, we need to send a revoke msg here
511         if (NetDevice->ReceiveSectionCount)
512         {
513                 DPRINT_INFO(NETVSC, "Sending NvspMessage1TypeRevokeReceiveBuffer...");
514
515                 // Send the revoke receive buffer
516                 revokePacket = &NetDevice->RevokePacket;
517                 memset(revokePacket, 0, sizeof(NVSP_MESSAGE));
518
519                 revokePacket->Header.MessageType = NvspMessage1TypeRevokeReceiveBuffer;
520                 revokePacket->Messages.Version1Messages.RevokeReceiveBuffer.Id = NETVSC_RECEIVE_BUFFER_ID;
521
522                 ret = NetDevice->Device->Driver->VmbusChannelInterface.SendPacket(NetDevice->Device,
523                                                                                                                                                         revokePacket,
524                                                                                                                                                         sizeof(NVSP_MESSAGE),
525                                                                                                                                                         (unsigned long)revokePacket,
526                                                                                                                                                         VmbusPacketTypeDataInBand,
527                                                                                                                                                         0);
528                 // If we failed here, we might as well return and have a leak rather than continue and a bugchk
529                 if (ret != 0)
530                 {
531                         DPRINT_ERR(NETVSC, "unable to send revoke receive buffer to netvsp");
532                         DPRINT_EXIT(NETVSC);
533                         return -1;
534                 }
535         }
536
537         // Teardown the gpadl on the vsp end
538         if (NetDevice->ReceiveBufferGpadlHandle)
539         {
540                 DPRINT_INFO(NETVSC, "Tearing down receive buffer's GPADL...");
541
542                 ret = NetDevice->Device->Driver->VmbusChannelInterface.TeardownGpadl(NetDevice->Device,
543                                                                                                                                                                 NetDevice->ReceiveBufferGpadlHandle);
544
545                 // If we failed here, we might as well return and have a leak rather than continue and a bugchk
546                 if (ret != 0)
547                 {
548                         DPRINT_ERR(NETVSC, "unable to teardown receive buffer's gpadl");
549                         DPRINT_EXIT(NETVSC);
550                         return -1;
551                 }
552                 NetDevice->ReceiveBufferGpadlHandle = 0;
553         }
554
555         if (NetDevice->ReceiveBuffer)
556         {
557                 DPRINT_INFO(NETVSC, "Freeing up receive buffer...");
558
559                 // Free up the receive buffer
560                 PageFree(NetDevice->ReceiveBuffer, NetDevice->ReceiveBufferSize >> PAGE_SHIFT);
561                 NetDevice->ReceiveBuffer = NULL;
562         }
563
564         if (NetDevice->ReceiveSections)
565         {
566                 kfree(NetDevice->ReceiveSections);
567                 NetDevice->ReceiveSections = NULL;
568                 NetDevice->ReceiveSectionCount = 0;
569         }
570
571         DPRINT_EXIT(NETVSC);
572
573         return ret;
574 }
575
576
577
578
579 static int
580 NetVscDestroySendBuffer(
581         NETVSC_DEVICE   *NetDevice
582         )
583 {
584         NVSP_MESSAGE *revokePacket;
585         int ret=0;
586
587
588         DPRINT_ENTER(NETVSC);
589
590         // If we got a section count, it means we received a SendReceiveBufferComplete msg
591         // (ie sent NvspMessage1TypeSendReceiveBuffer msg) therefore, we need to send a revoke msg here
592         if (NetDevice->SendSectionSize)
593         {
594                 DPRINT_INFO(NETVSC, "Sending NvspMessage1TypeRevokeSendBuffer...");
595
596                 // Send the revoke send buffer
597                 revokePacket = &NetDevice->RevokePacket;
598                 memset(revokePacket, 0, sizeof(NVSP_MESSAGE));
599
600                 revokePacket->Header.MessageType = NvspMessage1TypeRevokeSendBuffer;
601                 revokePacket->Messages.Version1Messages.RevokeSendBuffer.Id = NETVSC_SEND_BUFFER_ID;
602
603                 ret = NetDevice->Device->Driver->VmbusChannelInterface.SendPacket(NetDevice->Device,
604                                                                                                                                                         revokePacket,
605                                                                                                                                                         sizeof(NVSP_MESSAGE),
606                                                                                                                                                         (unsigned long)revokePacket,
607                                                                                                                                                         VmbusPacketTypeDataInBand,
608                                                                                                                                                         0);
609                 // If we failed here, we might as well return and have a leak rather than continue and a bugchk
610                 if (ret != 0)
611                 {
612                         DPRINT_ERR(NETVSC, "unable to send revoke send buffer to netvsp");
613                         DPRINT_EXIT(NETVSC);
614                         return -1;
615                 }
616         }
617
618         // Teardown the gpadl on the vsp end
619         if (NetDevice->SendBufferGpadlHandle)
620         {
621                 DPRINT_INFO(NETVSC, "Tearing down send buffer's GPADL...");
622
623                 ret = NetDevice->Device->Driver->VmbusChannelInterface.TeardownGpadl(NetDevice->Device,
624                                                                                                                                                                 NetDevice->SendBufferGpadlHandle);
625
626                 // If we failed here, we might as well return and have a leak rather than continue and a bugchk
627                 if (ret != 0)
628                 {
629                         DPRINT_ERR(NETVSC, "unable to teardown send buffer's gpadl");
630                         DPRINT_EXIT(NETVSC);
631                         return -1;
632                 }
633                 NetDevice->SendBufferGpadlHandle = 0;
634         }
635
636         if (NetDevice->SendBuffer)
637         {
638                 DPRINT_INFO(NETVSC, "Freeing up send buffer...");
639
640                 // Free up the receive buffer
641                 PageFree(NetDevice->SendBuffer, NetDevice->SendBufferSize >> PAGE_SHIFT);
642                 NetDevice->SendBuffer = NULL;
643         }
644
645         DPRINT_EXIT(NETVSC);
646
647         return ret;
648 }
649
650
651
652 static int
653 NetVscConnectToVsp(
654         DEVICE_OBJECT   *Device
655         )
656 {
657         int ret=0;
658         NETVSC_DEVICE *netDevice;
659         NVSP_MESSAGE *initPacket;
660         int ndisVersion;
661
662         DPRINT_ENTER(NETVSC);
663
664         netDevice = GetOutboundNetDevice(Device);
665         if (!netDevice)
666         {
667                 DPRINT_ERR(NETVSC, "unable to get net device...device being destroyed?");
668                 DPRINT_EXIT(NETVSC);
669                 return -1;
670         }
671
672         initPacket = &netDevice->ChannelInitPacket;
673
674         memset(initPacket, 0, sizeof(NVSP_MESSAGE));
675         initPacket->Header.MessageType = NvspMessageTypeInit;
676     initPacket->Messages.InitMessages.Init.MinProtocolVersion = NVSP_MIN_PROTOCOL_VERSION;
677     initPacket->Messages.InitMessages.Init.MaxProtocolVersion = NVSP_MAX_PROTOCOL_VERSION;
678
679         DPRINT_INFO(NETVSC, "Sending NvspMessageTypeInit...");
680
681         // Send the init request
682         ret = Device->Driver->VmbusChannelInterface.SendPacket(Device,
683                                                                                                                         initPacket,
684                                                                                                                         sizeof(NVSP_MESSAGE),
685                                                                                                                         (unsigned long)initPacket,
686                                                                                                                         VmbusPacketTypeDataInBand,
687                                                                                                                         VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
688
689         if( ret != 0)
690         {
691                 DPRINT_ERR(NETVSC, "unable to send NvspMessageTypeInit");
692                 goto Cleanup;
693         }
694
695         WaitEventWait(netDevice->ChannelInitEvent);
696
697         // Now, check the response
698         //ASSERT(initPacket->Messages.InitMessages.InitComplete.MaximumMdlChainLength <= MAX_MULTIPAGE_BUFFER_COUNT);
699         DPRINT_INFO(NETVSC, "NvspMessageTypeInit status(%d) max mdl chain (%d)",
700                 initPacket->Messages.InitMessages.InitComplete.Status,
701                 initPacket->Messages.InitMessages.InitComplete.MaximumMdlChainLength);
702
703         if (initPacket->Messages.InitMessages.InitComplete.Status != NvspStatusSuccess)
704         {
705                 DPRINT_ERR(NETVSC, "unable to initialize with netvsp (status 0x%x)", initPacket->Messages.InitMessages.InitComplete.Status);
706                 ret = -1;
707                 goto Cleanup;
708         }
709
710         if (initPacket->Messages.InitMessages.InitComplete.NegotiatedProtocolVersion != NVSP_PROTOCOL_VERSION_1)
711         {
712                 DPRINT_ERR(NETVSC, "unable to initialize with netvsp (version expected 1 got %d)",
713                         initPacket->Messages.InitMessages.InitComplete.NegotiatedProtocolVersion);
714                 ret = -1;
715                 goto Cleanup;
716         }
717         DPRINT_INFO(NETVSC, "Sending NvspMessage1TypeSendNdisVersion...");
718
719         // Send the ndis version
720         memset(initPacket, 0, sizeof(NVSP_MESSAGE));
721
722     ndisVersion = 0x00050000;
723
724     initPacket->Header.MessageType = NvspMessage1TypeSendNdisVersion;
725     initPacket->Messages.Version1Messages.SendNdisVersion.NdisMajorVersion = (ndisVersion & 0xFFFF0000) >> 16;
726     initPacket->Messages.Version1Messages.SendNdisVersion.NdisMinorVersion = ndisVersion & 0xFFFF;
727
728         // Send the init request
729         ret = Device->Driver->VmbusChannelInterface.SendPacket(Device,
730                                                                                                                         initPacket,
731                                                                                                                         sizeof(NVSP_MESSAGE),
732                                                                                                                         (unsigned long)initPacket,
733                                                                                                                         VmbusPacketTypeDataInBand,
734                                                                                                                         0);
735         if (ret != 0)
736         {
737                 DPRINT_ERR(NETVSC, "unable to send NvspMessage1TypeSendNdisVersion");
738                 ret = -1;
739                 goto Cleanup;
740         }
741         //
742         // BUGBUG - We have to wait for the above msg since the netvsp uses KMCL which acknowledges packet (completion packet)
743         // since our Vmbus always set the VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED flag
744         //WaitEventWait(NetVscChannel->ChannelInitEvent);
745
746         // Post the big receive buffer to NetVSP
747         ret = NetVscInitializeReceiveBufferWithNetVsp(Device);
748         if (ret == 0)
749         {
750                 ret = NetVscInitializeSendBufferWithNetVsp(Device);
751         }
752
753 Cleanup:
754         PutNetDevice(Device);
755         DPRINT_EXIT(NETVSC);
756         return ret;
757 }
758
759 static void
760 NetVscDisconnectFromVsp(
761         NETVSC_DEVICE   *NetDevice
762         )
763 {
764         DPRINT_ENTER(NETVSC);
765
766         NetVscDestroyReceiveBuffer(NetDevice);
767         NetVscDestroySendBuffer(NetDevice);
768
769         DPRINT_EXIT(NETVSC);
770 }
771
772
773 /*++
774
775 Name:
776         NetVscOnDeviceAdd()
777
778 Description:
779         Callback when the device belonging to this driver is added
780
781 --*/
782 int
783 NetVscOnDeviceAdd(
784         DEVICE_OBJECT   *Device,
785         void                    *AdditionalInfo
786         )
787 {
788         int ret=0;
789         int i;
790
791         NETVSC_DEVICE* netDevice;
792         NETVSC_PACKET* packet;
793         LIST_ENTRY *entry;
794
795         NETVSC_DRIVER_OBJECT *netDriver = (NETVSC_DRIVER_OBJECT*) Device->Driver;;
796
797         DPRINT_ENTER(NETVSC);
798
799         netDevice = AllocNetDevice(Device);
800         if (!netDevice)
801         {
802                 ret = -1;
803                 goto Cleanup;
804         }
805
806         DPRINT_DBG(NETVSC, "netvsc channel object allocated - %p", netDevice);
807
808         // Initialize the NetVSC channel extension
809         netDevice->ReceiveBufferSize = NETVSC_RECEIVE_BUFFER_SIZE;
810         spin_lock_init(&netDevice->receive_packet_list_lock);
811
812         netDevice->SendBufferSize = NETVSC_SEND_BUFFER_SIZE;
813
814         INITIALIZE_LIST_HEAD(&netDevice->ReceivePacketList);
815
816         for (i=0; i < NETVSC_RECEIVE_PACKETLIST_COUNT; i++)
817         {
818                 packet = kzalloc(sizeof(NETVSC_PACKET) + (NETVSC_RECEIVE_SG_COUNT* sizeof(PAGE_BUFFER)), GFP_KERNEL);
819                 if (!packet)
820                 {
821                         DPRINT_DBG(NETVSC, "unable to allocate netvsc pkts for receive pool (wanted %d got %d)", NETVSC_RECEIVE_PACKETLIST_COUNT, i);
822                         break;
823                 }
824
825                 INSERT_TAIL_LIST(&netDevice->ReceivePacketList, &packet->ListEntry);
826         }
827         netDevice->ChannelInitEvent = WaitEventCreate();
828
829         // Open the channel
830         ret = Device->Driver->VmbusChannelInterface.Open(Device,
831                                                                                                                 netDriver->RingBufferSize,
832                                                                                                                 netDriver->RingBufferSize,
833                                                                                                                 NULL, 0,
834                                                                                                                 NetVscOnChannelCallback,
835                                                                                                                 Device
836                                                                                                                 );
837
838         if (ret != 0)
839         {
840                 DPRINT_ERR(NETVSC, "unable to open channel: %d", ret);
841                 ret = -1;
842                 goto Cleanup;
843         }
844
845         // Channel is opened
846         DPRINT_INFO(NETVSC, "*** NetVSC channel opened successfully! ***");
847
848         // Connect with the NetVsp
849         ret = NetVscConnectToVsp(Device);
850         if (ret != 0)
851         {
852                 DPRINT_ERR(NETVSC, "unable to connect to NetVSP - %d", ret);
853                 ret = -1;
854                 goto Close;
855         }
856
857         DPRINT_INFO(NETVSC, "*** NetVSC channel handshake result - %d ***", ret);
858
859         DPRINT_EXIT(NETVSC);
860         return ret;
861
862 Close:
863         // Now, we can close the channel safely
864         Device->Driver->VmbusChannelInterface.Close(Device);
865
866 Cleanup:
867
868         if (netDevice)
869         {
870                 WaitEventClose(netDevice->ChannelInitEvent);
871
872                 while (!IsListEmpty(&netDevice->ReceivePacketList))
873                 {
874                         entry = REMOVE_HEAD_LIST(&netDevice->ReceivePacketList);
875                         packet = CONTAINING_RECORD(entry, NETVSC_PACKET, ListEntry);
876                         kfree(packet);
877                 }
878
879                 ReleaseOutboundNetDevice(Device);
880                 ReleaseInboundNetDevice(Device);
881
882                 FreeNetDevice(netDevice);
883         }
884
885         DPRINT_EXIT(NETVSC);
886         return ret;
887 }
888
889
890 /*++
891
892 Name:
893         NetVscOnDeviceRemove()
894
895 Description:
896         Callback when the root bus device is removed
897
898 --*/
899 int
900 NetVscOnDeviceRemove(
901         DEVICE_OBJECT *Device
902         )
903 {
904         NETVSC_DEVICE *netDevice;
905         NETVSC_PACKET *netvscPacket;
906         int ret=0;
907         LIST_ENTRY *entry;
908
909         DPRINT_ENTER(NETVSC);
910
911         DPRINT_INFO(NETVSC, "Disabling outbound traffic on net device (%p)...", Device->Extension);
912
913         // Stop outbound traffic ie sends and receives completions
914         netDevice = ReleaseOutboundNetDevice(Device);
915         if (!netDevice)
916         {
917                 DPRINT_ERR(NETVSC, "No net device present!!");
918                 return -1;
919         }
920
921         // Wait for all send completions
922         while (netDevice->NumOutstandingSends)
923         {
924                 DPRINT_INFO(NETVSC, "waiting for %d requests to complete...", netDevice->NumOutstandingSends);
925
926                 Sleep(100);
927         }
928
929         DPRINT_INFO(NETVSC, "Disconnecting from netvsp...");
930
931         NetVscDisconnectFromVsp(netDevice);
932
933         DPRINT_INFO(NETVSC, "Disabling inbound traffic on net device (%p)...", Device->Extension);
934
935         // Stop inbound traffic ie receives and sends completions
936         netDevice = ReleaseInboundNetDevice(Device);
937
938         // At this point, no one should be accessing netDevice except in here
939         DPRINT_INFO(NETVSC, "net device (%p) safe to remove", netDevice);
940
941         // Now, we can close the channel safely
942         Device->Driver->VmbusChannelInterface.Close(Device);
943
944         // Release all resources
945         while (!IsListEmpty(&netDevice->ReceivePacketList))
946         {
947                 entry = REMOVE_HEAD_LIST(&netDevice->ReceivePacketList);
948                 netvscPacket = CONTAINING_RECORD(entry, NETVSC_PACKET, ListEntry);
949
950                 kfree(netvscPacket);
951         }
952
953         WaitEventClose(netDevice->ChannelInitEvent);
954         FreeNetDevice(netDevice);
955
956         DPRINT_EXIT(NETVSC);
957         return ret;
958 }
959
960
961
962 /*++
963
964 Name:
965         NetVscOnCleanup()
966
967 Description:
968         Perform any cleanup when the driver is removed
969
970 --*/
971 void
972 NetVscOnCleanup(
973         DRIVER_OBJECT *drv
974         )
975 {
976         DPRINT_ENTER(NETVSC);
977
978         DPRINT_EXIT(NETVSC);
979 }
980
981 static void
982 NetVscOnSendCompletion(
983         DEVICE_OBJECT           *Device,
984         VMPACKET_DESCRIPTOR *Packet
985         )
986 {
987         NETVSC_DEVICE* netDevice;
988         NVSP_MESSAGE *nvspPacket;
989         NETVSC_PACKET *nvscPacket;
990
991         DPRINT_ENTER(NETVSC);
992
993         netDevice = GetInboundNetDevice(Device);
994         if (!netDevice)
995         {
996                 DPRINT_ERR(NETVSC, "unable to get net device...device being destroyed?");
997                 DPRINT_EXIT(NETVSC);
998                 return;
999         }
1000
1001         nvspPacket = (NVSP_MESSAGE*)((unsigned long)Packet + (Packet->DataOffset8 << 3));
1002
1003         DPRINT_DBG(NETVSC, "send completion packet - type %d", nvspPacket->Header.MessageType);
1004
1005         if (nvspPacket->Header.MessageType == NvspMessageTypeInitComplete ||
1006                 nvspPacket->Header.MessageType == NvspMessage1TypeSendReceiveBufferComplete ||
1007                 nvspPacket->Header.MessageType == NvspMessage1TypeSendSendBufferComplete)
1008         {
1009                 // Copy the response back
1010                 memcpy(&netDevice->ChannelInitPacket, nvspPacket, sizeof(NVSP_MESSAGE));
1011                 WaitEventSet(netDevice->ChannelInitEvent);
1012         }
1013         else if (nvspPacket->Header.MessageType == NvspMessage1TypeSendRNDISPacketComplete)
1014         {
1015                 // Get the send context
1016                 nvscPacket = (NETVSC_PACKET *)(unsigned long)Packet->TransactionId;
1017                 ASSERT(nvscPacket);
1018
1019                 // Notify the layer above us
1020                 nvscPacket->Completion.Send.OnSendCompletion(nvscPacket->Completion.Send.SendCompletionContext);
1021
1022                 InterlockedDecrement(&netDevice->NumOutstandingSends);
1023         }
1024         else
1025         {
1026                 DPRINT_ERR(NETVSC, "Unknown send completion packet type - %d received!!", nvspPacket->Header.MessageType);
1027         }
1028
1029         PutNetDevice(Device);
1030         DPRINT_EXIT(NETVSC);
1031 }
1032
1033
1034
1035 static int
1036 NetVscOnSend(
1037         DEVICE_OBJECT *Device,
1038         NETVSC_PACKET *Packet
1039         )
1040 {
1041         NETVSC_DEVICE* netDevice;
1042         int ret=0;
1043
1044         NVSP_MESSAGE sendMessage;
1045
1046         DPRINT_ENTER(NETVSC);
1047
1048         netDevice = GetOutboundNetDevice(Device);
1049         if (!netDevice)
1050         {
1051                 DPRINT_ERR(NETVSC, "net device (%p) shutting down...ignoring outbound packets", netDevice);
1052                 DPRINT_EXIT(NETVSC);
1053                 return -2;
1054         }
1055
1056         sendMessage.Header.MessageType = NvspMessage1TypeSendRNDISPacket;
1057         if (Packet->IsDataPacket)
1058             sendMessage.Messages.Version1Messages.SendRNDISPacket.ChannelType = 0;// 0 is RMC_DATA;
1059         else
1060                 sendMessage.Messages.Version1Messages.SendRNDISPacket.ChannelType = 1;// 1 is RMC_CONTROL;
1061
1062         // Not using send buffer section
1063     sendMessage.Messages.Version1Messages.SendRNDISPacket.SendBufferSectionIndex = 0xFFFFFFFF;
1064     sendMessage.Messages.Version1Messages.SendRNDISPacket.SendBufferSectionSize = 0;
1065
1066         if (Packet->PageBufferCount)
1067         {
1068                 ret = Device->Driver->VmbusChannelInterface.SendPacketPageBuffer(Device,
1069                                                                                                                                                         Packet->PageBuffers,
1070                                                                                                                                                         Packet->PageBufferCount,
1071                                                                                                                                                         &sendMessage,
1072                                                                                                                                                         sizeof(NVSP_MESSAGE),
1073                                                                                                                                                         (unsigned long)Packet);
1074         }
1075         else
1076         {
1077                 ret = Device->Driver->VmbusChannelInterface.SendPacket(Device,
1078                                                                                                                                 &sendMessage,
1079                                                                                                                                 sizeof(NVSP_MESSAGE),
1080                                                                                                                                 (unsigned long)Packet,
1081                                                                                                                                 VmbusPacketTypeDataInBand,
1082                                                                                                                                 VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
1083
1084         }
1085
1086         if (ret != 0)
1087         {
1088                 DPRINT_ERR(NETVSC, "Unable to send packet %p ret %d", Packet, ret);
1089         }
1090
1091         InterlockedIncrement(&netDevice->NumOutstandingSends);
1092         PutNetDevice(Device);
1093
1094         DPRINT_EXIT(NETVSC);
1095         return ret;
1096 }
1097
1098
1099 static void
1100 NetVscOnReceive(
1101         DEVICE_OBJECT           *Device,
1102         VMPACKET_DESCRIPTOR *Packet
1103         )
1104 {
1105         NETVSC_DEVICE* netDevice;
1106         VMTRANSFER_PAGE_PACKET_HEADER *vmxferpagePacket;
1107         NVSP_MESSAGE *nvspPacket;
1108         NETVSC_PACKET *netvscPacket=NULL;
1109         LIST_ENTRY* entry;
1110         unsigned long start;
1111         unsigned long end, endVirtual;
1112         //NETVSC_DRIVER_OBJECT *netvscDriver;
1113         XFERPAGE_PACKET *xferpagePacket=NULL;
1114         LIST_ENTRY listHead;
1115
1116         int i=0, j=0;
1117         int count=0, bytesRemain=0;
1118         unsigned long flags;
1119
1120         DPRINT_ENTER(NETVSC);
1121
1122         netDevice = GetInboundNetDevice(Device);
1123         if (!netDevice)
1124         {
1125                 DPRINT_ERR(NETVSC, "unable to get net device...device being destroyed?");
1126                 DPRINT_EXIT(NETVSC);
1127                 return;
1128         }
1129
1130         // All inbound packets other than send completion should be xfer page packet
1131         if (Packet->Type != VmbusPacketTypeDataUsingTransferPages)
1132         {
1133                 DPRINT_ERR(NETVSC, "Unknown packet type received - %d", Packet->Type);
1134                 PutNetDevice(Device);
1135                 return;
1136         }
1137
1138         nvspPacket = (NVSP_MESSAGE*)((unsigned long)Packet + (Packet->DataOffset8 << 3));
1139
1140         // Make sure this is a valid nvsp packet
1141         if (nvspPacket->Header.MessageType != NvspMessage1TypeSendRNDISPacket )
1142         {
1143                 DPRINT_ERR(NETVSC, "Unknown nvsp packet type received - %d", nvspPacket->Header.MessageType);
1144                 PutNetDevice(Device);
1145                 return;
1146         }
1147
1148         DPRINT_DBG(NETVSC, "NVSP packet received - type %d", nvspPacket->Header.MessageType);
1149
1150         vmxferpagePacket = (VMTRANSFER_PAGE_PACKET_HEADER*)Packet;
1151
1152         if (vmxferpagePacket->TransferPageSetId != NETVSC_RECEIVE_BUFFER_ID)
1153         {
1154                 DPRINT_ERR(NETVSC, "Invalid xfer page set id - expecting %x got %x", NETVSC_RECEIVE_BUFFER_ID, vmxferpagePacket->TransferPageSetId);
1155                 PutNetDevice(Device);
1156                 return;
1157         }
1158
1159         DPRINT_DBG(NETVSC, "xfer page - range count %d", vmxferpagePacket->RangeCount);
1160
1161         INITIALIZE_LIST_HEAD(&listHead);
1162
1163         // Grab free packets (range count + 1) to represent this xfer page packet. +1 to represent
1164         // the xfer page packet itself. We grab it here so that we know exactly how many we can fulfil
1165         spin_lock_irqsave(&netDevice->receive_packet_list_lock, flags);
1166         while (!IsListEmpty(&netDevice->ReceivePacketList))
1167         {
1168                 entry = REMOVE_HEAD_LIST(&netDevice->ReceivePacketList);
1169                 netvscPacket = CONTAINING_RECORD(entry, NETVSC_PACKET, ListEntry);
1170
1171                 INSERT_TAIL_LIST(&listHead, &netvscPacket->ListEntry);
1172
1173                 if (++count == vmxferpagePacket->RangeCount + 1)
1174                         break;
1175         }
1176         spin_unlock_irqrestore(&netDevice->receive_packet_list_lock, flags);
1177
1178         // We need at least 2 netvsc pkts (1 to represent the xfer page and at least 1 for the range)
1179         // i.e. we can handled some of the xfer page packet ranges...
1180         if (count < 2)
1181         {
1182                 DPRINT_ERR(NETVSC, "Got only %d netvsc pkt...needed %d pkts. Dropping this xfer page packet completely!", count, vmxferpagePacket->RangeCount+1);
1183
1184                 // Return it to the freelist
1185                 spin_lock_irqsave(&netDevice->receive_packet_list_lock, flags);
1186                 for (i=count; i != 0; i--)
1187                 {
1188                         entry = REMOVE_HEAD_LIST(&listHead);
1189                         netvscPacket = CONTAINING_RECORD(entry, NETVSC_PACKET, ListEntry);
1190
1191                         INSERT_TAIL_LIST(&netDevice->ReceivePacketList, &netvscPacket->ListEntry);
1192                 }
1193                 spin_unlock_irqrestore(&netDevice->receive_packet_list_lock, flags);
1194
1195                 NetVscSendReceiveCompletion(Device, vmxferpagePacket->d.TransactionId);
1196
1197                 PutNetDevice(Device);
1198                 return;
1199         }
1200
1201         // Remove the 1st packet to represent the xfer page packet itself
1202         entry = REMOVE_HEAD_LIST(&listHead);
1203         xferpagePacket = CONTAINING_RECORD(entry, XFERPAGE_PACKET, ListEntry);
1204         xferpagePacket->Count = count - 1; // This is how much we can satisfy
1205         ASSERT(xferpagePacket->Count > 0 && xferpagePacket->Count <= vmxferpagePacket->RangeCount);
1206
1207         if (xferpagePacket->Count != vmxferpagePacket->RangeCount)
1208         {
1209                 DPRINT_INFO(NETVSC, "Needed %d netvsc pkts to satisy this xfer page...got %d", vmxferpagePacket->RangeCount, xferpagePacket->Count);
1210         }
1211
1212         // Each range represents 1 RNDIS pkt that contains 1 ethernet frame
1213         for (i=0; i < (count - 1); i++)
1214         {
1215                 entry = REMOVE_HEAD_LIST(&listHead);
1216                 netvscPacket = CONTAINING_RECORD(entry, NETVSC_PACKET, ListEntry);
1217
1218                 // Initialize the netvsc packet
1219                 netvscPacket->XferPagePacket = xferpagePacket;
1220                 netvscPacket->Completion.Recv.OnReceiveCompletion = NetVscOnReceiveCompletion;
1221                 netvscPacket->Completion.Recv.ReceiveCompletionContext = netvscPacket;
1222                 netvscPacket->Device = Device;
1223                 netvscPacket->Completion.Recv.ReceiveCompletionTid = vmxferpagePacket->d.TransactionId; // Save this so that we can send it back
1224
1225                 netvscPacket->TotalDataBufferLength = vmxferpagePacket->Ranges[i].ByteCount;
1226                 netvscPacket->PageBufferCount = 1;
1227
1228                 ASSERT(vmxferpagePacket->Ranges[i].ByteOffset + vmxferpagePacket->Ranges[i].ByteCount < netDevice->ReceiveBufferSize);
1229
1230                 netvscPacket->PageBuffers[0].Length = vmxferpagePacket->Ranges[i].ByteCount;
1231
1232                 start = GetPhysicalAddress((void*)((unsigned long)netDevice->ReceiveBuffer + vmxferpagePacket->Ranges[i].ByteOffset));
1233
1234                 netvscPacket->PageBuffers[0].Pfn = start >> PAGE_SHIFT;
1235                 endVirtual = (unsigned long)netDevice->ReceiveBuffer
1236                     + vmxferpagePacket->Ranges[i].ByteOffset
1237                     + vmxferpagePacket->Ranges[i].ByteCount -1;
1238                 end = GetPhysicalAddress((void*)endVirtual);
1239
1240                 // Calculate the page relative offset
1241                 netvscPacket->PageBuffers[0].Offset = vmxferpagePacket->Ranges[i].ByteOffset & (PAGE_SIZE -1);
1242                 if ((end >> PAGE_SHIFT) != (start>>PAGE_SHIFT)) {
1243                     //Handle frame across multiple pages:
1244                     netvscPacket->PageBuffers[0].Length =
1245                         (netvscPacket->PageBuffers[0].Pfn <<PAGE_SHIFT) + PAGE_SIZE - start;
1246                     bytesRemain = netvscPacket->TotalDataBufferLength - netvscPacket->PageBuffers[0].Length;
1247                     for (j=1; j<NETVSC_PACKET_MAXPAGE; j++) {
1248                         netvscPacket->PageBuffers[j].Offset = 0;
1249                         if (bytesRemain <= PAGE_SIZE) {
1250                             netvscPacket->PageBuffers[j].Length = bytesRemain;
1251                             bytesRemain = 0;
1252                         } else {
1253                             netvscPacket->PageBuffers[j].Length = PAGE_SIZE;
1254                             bytesRemain -= PAGE_SIZE;
1255                         }
1256                         netvscPacket->PageBuffers[j].Pfn =
1257                             GetPhysicalAddress((void*)(endVirtual - bytesRemain)) >> PAGE_SHIFT;
1258                         netvscPacket->PageBufferCount++;
1259                         if (bytesRemain == 0)
1260                             break;
1261                     }
1262                     ASSERT(bytesRemain == 0);
1263                 }
1264                 DPRINT_DBG(NETVSC, "[%d] - (abs offset %u len %u) => (pfn %llx, offset %u, len %u)",
1265                         i,
1266                         vmxferpagePacket->Ranges[i].ByteOffset,
1267                         vmxferpagePacket->Ranges[i].ByteCount,
1268                         netvscPacket->PageBuffers[0].Pfn,
1269                         netvscPacket->PageBuffers[0].Offset,
1270                         netvscPacket->PageBuffers[0].Length);
1271
1272                 // Pass it to the upper layer
1273                 ((NETVSC_DRIVER_OBJECT*)Device->Driver)->OnReceiveCallback(Device, netvscPacket);
1274
1275                 NetVscOnReceiveCompletion(netvscPacket->Completion.Recv.ReceiveCompletionContext);
1276         }
1277
1278         ASSERT(IsListEmpty(&listHead));
1279
1280         PutNetDevice(Device);
1281         DPRINT_EXIT(NETVSC);
1282 }
1283
1284
1285 static void
1286 NetVscSendReceiveCompletion(
1287         DEVICE_OBJECT   *Device,
1288         u64                     TransactionId
1289         )
1290 {
1291         NVSP_MESSAGE recvcompMessage;
1292         int retries=0;
1293         int ret=0;
1294
1295         DPRINT_DBG(NETVSC, "Sending receive completion pkt - %llx", TransactionId);
1296
1297         recvcompMessage.Header.MessageType = NvspMessage1TypeSendRNDISPacketComplete;
1298
1299         // FIXME: Pass in the status
1300         recvcompMessage.Messages.Version1Messages.SendRNDISPacketComplete.Status = NvspStatusSuccess;
1301
1302 retry_send_cmplt:
1303         // Send the completion
1304         ret = Device->Driver->VmbusChannelInterface.SendPacket(Device,
1305                                                                                                                         &recvcompMessage,
1306                                                                                                                         sizeof(NVSP_MESSAGE),
1307                                                                                                                         TransactionId,
1308                                                                                                                         VmbusPacketTypeCompletion,
1309                                                                                                                         0);
1310         if (ret == 0) // success
1311         {
1312                 // no-op
1313         }
1314         else if (ret == -1) // no more room...wait a bit and attempt to retry 3 times
1315         {
1316                 retries++;
1317                 DPRINT_ERR(NETVSC, "unable to send receive completion pkt (tid %llx)...retrying %d", TransactionId, retries);
1318
1319                 if (retries < 4)
1320                 {
1321                         Sleep(100);
1322                         goto retry_send_cmplt;
1323                 }
1324                 else
1325                 {
1326                         DPRINT_ERR(NETVSC, "unable to send receive completion pkt (tid %llx)...give up retrying", TransactionId);
1327                 }
1328         }
1329         else
1330         {
1331                 DPRINT_ERR(NETVSC, "unable to send receive completion pkt - %llx", TransactionId);
1332         }
1333 }
1334
1335 //
1336 // Send a receive completion packet to RNDIS device (ie NetVsp)
1337 //
1338 static void
1339 NetVscOnReceiveCompletion(
1340         void * Context)
1341 {
1342         NETVSC_PACKET *packet = (NETVSC_PACKET*)Context;
1343         DEVICE_OBJECT *device = (DEVICE_OBJECT*)packet->Device;
1344         NETVSC_DEVICE* netDevice;
1345         u64     transactionId=0;
1346         bool fSendReceiveComp = false;
1347         unsigned long flags;
1348
1349         DPRINT_ENTER(NETVSC);
1350
1351         ASSERT(packet->XferPagePacket);
1352
1353         // Even though it seems logical to do a GetOutboundNetDevice() here to send out receive completion,
1354         // we are using GetInboundNetDevice() since we may have disable outbound traffic already.
1355         netDevice = GetInboundNetDevice(device);
1356         if (!netDevice)
1357         {
1358                 DPRINT_ERR(NETVSC, "unable to get net device...device being destroyed?");
1359                 DPRINT_EXIT(NETVSC);
1360                 return;
1361         }
1362
1363         // Overloading use of the lock.
1364         spin_lock_irqsave(&netDevice->receive_packet_list_lock, flags);
1365
1366         ASSERT(packet->XferPagePacket->Count > 0);
1367         packet->XferPagePacket->Count--;
1368
1369         // Last one in the line that represent 1 xfer page packet.
1370         // Return the xfer page packet itself to the freelist
1371         if (packet->XferPagePacket->Count == 0)
1372         {
1373                 fSendReceiveComp = true;
1374                 transactionId = packet->Completion.Recv.ReceiveCompletionTid;
1375
1376                 INSERT_TAIL_LIST(&netDevice->ReceivePacketList, &packet->XferPagePacket->ListEntry);
1377         }
1378
1379         // Put the packet back
1380         INSERT_TAIL_LIST(&netDevice->ReceivePacketList, &packet->ListEntry);
1381         spin_unlock_irqrestore(&netDevice->receive_packet_list_lock, flags);
1382
1383         // Send a receive completion for the xfer page packet
1384         if (fSendReceiveComp)
1385         {
1386                 NetVscSendReceiveCompletion(device, transactionId);
1387         }
1388
1389         PutNetDevice(device);
1390         DPRINT_EXIT(NETVSC);
1391 }
1392
1393
1394
1395 void
1396 NetVscOnChannelCallback(
1397         void * Context
1398         )
1399 {
1400         const int netPacketSize=2048;
1401         int ret=0;
1402         DEVICE_OBJECT *device=(DEVICE_OBJECT*)Context;
1403         NETVSC_DEVICE *netDevice;
1404
1405         u32 bytesRecvd;
1406         u64 requestId;
1407         unsigned char packet[netPacketSize];
1408         VMPACKET_DESCRIPTOR *desc;
1409         unsigned char   *buffer=packet;
1410         int             bufferlen=netPacketSize;
1411
1412
1413         DPRINT_ENTER(NETVSC);
1414
1415         ASSERT(device);
1416
1417         netDevice = GetInboundNetDevice(device);
1418         if (!netDevice)
1419         {
1420                 DPRINT_ERR(NETVSC, "net device (%p) shutting down...ignoring inbound packets", netDevice);
1421                 DPRINT_EXIT(NETVSC);
1422                 return;
1423         }
1424
1425         do
1426         {
1427                 ret = device->Driver->VmbusChannelInterface.RecvPacketRaw(device,
1428                                                                                                                                         buffer,
1429                                                                                                                                         bufferlen,
1430                                                                                                                                         &bytesRecvd,
1431                                                                                                                                         &requestId);
1432
1433                 if (ret == 0)
1434                 {
1435                         if (bytesRecvd > 0)
1436                         {
1437                                 DPRINT_DBG(NETVSC, "receive %d bytes, tid %llx", bytesRecvd, requestId);
1438
1439                                 desc = (VMPACKET_DESCRIPTOR*)buffer;
1440                                 switch (desc->Type)
1441                                 {
1442                                         case VmbusPacketTypeCompletion:
1443                                                 NetVscOnSendCompletion(device, desc);
1444                                                 break;
1445
1446                                         case VmbusPacketTypeDataUsingTransferPages:
1447                                                 NetVscOnReceive(device, desc);
1448                                                 break;
1449
1450                                         default:
1451                                                 DPRINT_ERR(NETVSC, "unhandled packet type %d, tid %llx len %d\n", desc->Type, requestId, bytesRecvd);
1452                                                 break;
1453                                 }
1454
1455                                 // reset
1456                                 if (bufferlen > netPacketSize)
1457                                 {
1458                                         kfree(buffer);
1459
1460                                         buffer = packet;
1461                                         bufferlen = netPacketSize;
1462                                 }
1463                         }
1464                         else
1465                         {
1466                                 //DPRINT_DBG(NETVSC, "nothing else to read...");
1467
1468                                 // reset
1469                                 if (bufferlen > netPacketSize)
1470                                 {
1471                                         kfree(buffer);
1472
1473                                         buffer = packet;
1474                                         bufferlen = netPacketSize;
1475                                 }
1476
1477                                 break;
1478                         }
1479                 }
1480                 else if (ret == -2) // Handle large packet
1481                 {
1482                         buffer = kmalloc(bytesRecvd, GFP_ATOMIC);
1483                         if (buffer == NULL)
1484                         {
1485                                 // Try again next time around
1486                                 DPRINT_ERR(NETVSC, "unable to allocate buffer of size (%d)!!", bytesRecvd);
1487                                 break;
1488                         }
1489
1490                         bufferlen = bytesRecvd;
1491                 }
1492                 else
1493                 {
1494                         ASSERT(0);
1495                 }
1496         } while (1);
1497
1498         PutNetDevice(device);
1499         DPRINT_EXIT(NETVSC);
1500         return;
1501 }