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