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