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