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