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