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