Staging: hv: cleanup coding style issues in Channel.h
[safe/jmp/linux-2.6] / drivers / staging / hv / Channel.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  *   Haiyang Zhang <haiyangz@microsoft.com>
20  *   Hank Janssen  <hjanssen@microsoft.com>
21  *
22  */
23
24 #include <linux/kernel.h>
25 #include "include/osd.h"
26 #include "include/logging.h"
27
28 #include "VmbusPrivate.h"
29
30 /* Internal routines */
31 static int
32 VmbusChannelCreateGpadlHeader(
33         void *                                  Kbuffer,        /* must be phys and virt contiguous */
34         u32                                     Size,           /* page-size multiple */
35         VMBUS_CHANNEL_MSGINFO   **msgInfo,
36         u32                                     *MessageCount
37         );
38
39 static void
40 DumpVmbusChannel(
41         VMBUS_CHANNEL                   *Channel
42         );
43
44
45 static void
46 VmbusChannelSetEvent(
47         VMBUS_CHANNEL                   *Channel
48         );
49
50
51 #if 0
52 static void
53 DumpMonitorPage(
54         HV_MONITOR_PAGE *MonitorPage
55         )
56 {
57         int i=0;
58         int j=0;
59
60         DPRINT_DBG(VMBUS, "monitorPage - %p, trigger state - %d", MonitorPage, MonitorPage->TriggerState);
61
62         for (i=0; i<4; i++)
63         {
64                 DPRINT_DBG(VMBUS, "trigger group (%d) - %llx", i, MonitorPage->TriggerGroup[i].AsUINT64);
65         }
66
67         for (i=0; i<4; i++)
68         {
69                 for (j=0; j<32; j++)
70                 {
71                         DPRINT_DBG(VMBUS, "latency (%d)(%d) - %llx", i, j, MonitorPage->Latency[i][j]);
72                 }
73         }
74         for (i=0; i<4; i++)
75         {
76                 for (j=0; j<32; j++)
77                 {
78                         DPRINT_DBG(VMBUS, "param-conn id (%d)(%d) - %d", i, j, MonitorPage->Parameter[i][j].ConnectionId.Asu32);
79                         DPRINT_DBG(VMBUS, "param-flag (%d)(%d) - %d", i, j, MonitorPage->Parameter[i][j].FlagNumber);
80
81                 }
82         }
83 }
84 #endif
85
86 /*++
87
88 Name:
89         VmbusChannelSetEvent()
90
91 Description:
92         Trigger an event notification on the specified channel.
93
94 --*/
95 static void
96 VmbusChannelSetEvent(
97         VMBUS_CHANNEL                   *Channel
98         )
99 {
100         HV_MONITOR_PAGE *monitorPage;
101
102         DPRINT_ENTER(VMBUS);
103
104         if (Channel->OfferMsg.MonitorAllocated)
105         {
106                 /* Each u32 represents 32 channels */
107                 set_bit(Channel->OfferMsg.ChildRelId & 31,
108                         (unsigned long *) gVmbusConnection.SendInterruptPage +
109                         (Channel->OfferMsg.ChildRelId >> 5) );
110
111                 monitorPage = (HV_MONITOR_PAGE*)gVmbusConnection.MonitorPages;
112                 monitorPage++; /* Get the child to parent monitor page */
113
114                 set_bit(Channel->MonitorBit,
115                         (unsigned long *) &monitorPage->TriggerGroup[Channel->MonitorGroup].Pending);
116
117         }
118         else
119         {
120                 VmbusSetEvent(Channel->OfferMsg.ChildRelId);
121         }
122
123         DPRINT_EXIT(VMBUS);
124 }
125
126 #if 0
127 static void
128 VmbusChannelClearEvent(
129         VMBUS_CHANNEL                   *Channel
130         )
131 {
132         HV_MONITOR_PAGE *monitorPage;
133
134         DPRINT_ENTER(VMBUS);
135
136         if (Channel->OfferMsg.MonitorAllocated)
137         {
138                 /* Each u32 represents 32 channels */
139                 clear_bit(Channel->OfferMsg.ChildRelId & 31,
140                           (unsigned long *) gVmbusConnection.SendInterruptPage + (Channel->OfferMsg.ChildRelId >> 5));
141
142                 monitorPage = (HV_MONITOR_PAGE*)gVmbusConnection.MonitorPages;
143                 monitorPage++; /* Get the child to parent monitor page */
144
145                 clear_bit(Channel->MonitorBit,
146                           (unsigned long *) &monitorPage->TriggerGroup[Channel->MonitorGroup].Pending);
147         }
148
149         DPRINT_EXIT(VMBUS);
150 }
151
152 #endif
153 /*++;
154
155 Name:
156         VmbusChannelGetDebugInfo()
157
158 Description:
159         Retrieve various channel debug info
160
161 --*/
162 void
163 VmbusChannelGetDebugInfo(
164         VMBUS_CHANNEL                           *Channel,
165         VMBUS_CHANNEL_DEBUG_INFO        *DebugInfo
166         )
167 {
168         HV_MONITOR_PAGE *monitorPage;
169     u8 monitorGroup    = (u8)Channel->OfferMsg.MonitorId / 32;
170     u8 monitorOffset   = (u8)Channel->OfferMsg.MonitorId % 32;
171         /* u32 monitorBit       = 1 << monitorOffset; */
172
173         DebugInfo->RelId = Channel->OfferMsg.ChildRelId;
174         DebugInfo->State = Channel->State;
175         memcpy(&DebugInfo->InterfaceType, &Channel->OfferMsg.Offer.InterfaceType, sizeof(GUID));
176         memcpy(&DebugInfo->InterfaceInstance, &Channel->OfferMsg.Offer.InterfaceInstance, sizeof(GUID));
177
178         monitorPage = (HV_MONITOR_PAGE*)gVmbusConnection.MonitorPages;
179
180         DebugInfo->MonitorId = Channel->OfferMsg.MonitorId;
181
182         DebugInfo->ServerMonitorPending = monitorPage->TriggerGroup[monitorGroup].Pending;
183         DebugInfo->ServerMonitorLatency = monitorPage->Latency[monitorGroup][ monitorOffset];
184         DebugInfo->ServerMonitorConnectionId = monitorPage->Parameter[monitorGroup][ monitorOffset].ConnectionId.u.Id;
185
186         monitorPage++;
187
188         DebugInfo->ClientMonitorPending = monitorPage->TriggerGroup[monitorGroup].Pending;
189         DebugInfo->ClientMonitorLatency = monitorPage->Latency[monitorGroup][ monitorOffset];
190         DebugInfo->ClientMonitorConnectionId = monitorPage->Parameter[monitorGroup][ monitorOffset].ConnectionId.u.Id;
191
192         RingBufferGetDebugInfo(&Channel->Inbound, &DebugInfo->Inbound);
193         RingBufferGetDebugInfo(&Channel->Outbound, &DebugInfo->Outbound);
194 }
195
196
197 /*++;
198
199 Name:
200         VmbusChannelOpen()
201
202 Description:
203         Open the specified channel.
204
205 --*/
206 int
207 VmbusChannelOpen(
208         VMBUS_CHANNEL                   *NewChannel,
209         u32                                     SendRingBufferSize,
210         u32                                     RecvRingBufferSize,
211         void *                                  UserData,
212         u32                                     UserDataLen,
213         PFN_CHANNEL_CALLBACK    pfnOnChannelCallback,
214         void *                                  Context
215         )
216 {
217         int ret=0;
218         VMBUS_CHANNEL_OPEN_CHANNEL* openMsg;
219         VMBUS_CHANNEL_MSGINFO* openInfo;
220         void *in, *out;
221         unsigned long flags;
222
223         DPRINT_ENTER(VMBUS);
224
225         /* Aligned to page size */
226         ASSERT(!(SendRingBufferSize & (PAGE_SIZE -1)));
227         ASSERT(!(RecvRingBufferSize & (PAGE_SIZE -1)));
228
229         NewChannel->OnChannelCallback = pfnOnChannelCallback;
230         NewChannel->ChannelCallbackContext = Context;
231
232         /* Allocate the ring buffer */
233         out = osd_PageAlloc((SendRingBufferSize + RecvRingBufferSize) >> PAGE_SHIFT);
234         /* out = kzalloc(sendRingBufferSize + recvRingBufferSize, GFP_KERNEL); */
235         ASSERT(out);
236         ASSERT(((unsigned long)out & (PAGE_SIZE-1)) == 0);
237
238         in = (void*)((unsigned long)out + SendRingBufferSize);
239
240         NewChannel->RingBufferPages = out;
241         NewChannel->RingBufferPageCount = (SendRingBufferSize + RecvRingBufferSize) >> PAGE_SHIFT;
242
243         RingBufferInit(&NewChannel->Outbound, out, SendRingBufferSize);
244
245         RingBufferInit(&NewChannel->Inbound, in, RecvRingBufferSize);
246
247         /* Establish the gpadl for the ring buffer */
248         DPRINT_DBG(VMBUS, "Establishing ring buffer's gpadl for channel %p...", NewChannel);
249
250         NewChannel->RingBufferGpadlHandle = 0;
251
252         ret = VmbusChannelEstablishGpadl(NewChannel,
253                 NewChannel->Outbound.RingBuffer,
254                 SendRingBufferSize + RecvRingBufferSize,
255                 &NewChannel->RingBufferGpadlHandle);
256
257         DPRINT_DBG(VMBUS, "channel %p <relid %d gpadl 0x%x send ring %p size %d recv ring %p size %d, downstreamoffset %d>",
258                 NewChannel,
259                 NewChannel->OfferMsg.ChildRelId,
260                 NewChannel->RingBufferGpadlHandle,
261                 NewChannel->Outbound.RingBuffer,
262                 NewChannel->Outbound.RingSize,
263                 NewChannel->Inbound.RingBuffer,
264                 NewChannel->Inbound.RingSize,
265                 SendRingBufferSize);
266
267         /* Create and init the channel open message */
268         openInfo = kmalloc(sizeof(VMBUS_CHANNEL_MSGINFO) + sizeof(VMBUS_CHANNEL_OPEN_CHANNEL), GFP_KERNEL);
269         ASSERT(openInfo != NULL);
270
271         openInfo->WaitEvent = osd_WaitEventCreate();
272
273         openMsg = (VMBUS_CHANNEL_OPEN_CHANNEL*)openInfo->Msg;
274         openMsg->Header.MessageType                             = ChannelMessageOpenChannel;
275         openMsg->OpenId                                                 = NewChannel->OfferMsg.ChildRelId; /* FIXME */
276     openMsg->ChildRelId                                         = NewChannel->OfferMsg.ChildRelId;
277     openMsg->RingBufferGpadlHandle                      = NewChannel->RingBufferGpadlHandle;
278     ASSERT(openMsg->RingBufferGpadlHandle);
279     openMsg->DownstreamRingBufferPageOffset             = SendRingBufferSize >> PAGE_SHIFT;
280     openMsg->ServerContextAreaGpadlHandle       = 0; /* TODO */
281
282         ASSERT(UserDataLen <= MAX_USER_DEFINED_BYTES);
283         if (UserDataLen)
284         {
285                 memcpy(openMsg->UserData, UserData, UserDataLen);
286         }
287
288         spin_lock_irqsave(&gVmbusConnection.channelmsg_lock, flags);
289         INSERT_TAIL_LIST(&gVmbusConnection.ChannelMsgList, &openInfo->MsgListEntry);
290         spin_unlock_irqrestore(&gVmbusConnection.channelmsg_lock, flags);
291
292         DPRINT_DBG(VMBUS, "Sending channel open msg...");
293
294         ret = VmbusPostMessage(openMsg, sizeof(VMBUS_CHANNEL_OPEN_CHANNEL));
295         if (ret != 0)
296         {
297                 DPRINT_ERR(VMBUS, "unable to open channel - %d", ret);
298                 goto Cleanup;
299         }
300
301         /* FIXME: Need to time-out here */
302         osd_WaitEventWait(openInfo->WaitEvent);
303
304         if (openInfo->Response.OpenResult.Status == 0)
305         {
306                 DPRINT_INFO(VMBUS, "channel <%p> open success!!", NewChannel);
307         }
308         else
309         {
310                 DPRINT_INFO(VMBUS, "channel <%p> open failed - %d!!", NewChannel, openInfo->Response.OpenResult.Status);
311         }
312
313 Cleanup:
314         spin_lock_irqsave(&gVmbusConnection.channelmsg_lock, flags);
315         REMOVE_ENTRY_LIST(&openInfo->MsgListEntry);
316         spin_unlock_irqrestore(&gVmbusConnection.channelmsg_lock, flags);
317
318         kfree(openInfo->WaitEvent);
319         kfree(openInfo);
320
321         DPRINT_EXIT(VMBUS);
322
323         return 0;
324 }
325
326 /*++;
327
328 Name:
329         DumpGpadlBody()
330
331 Description:
332         Dump the gpadl body message to the console for debugging purposes.
333
334 --*/
335 static void DumpGpadlBody(
336         VMBUS_CHANNEL_GPADL_BODY        *Gpadl,
337         u32                                             Len)
338 {
339         int i=0;
340         int pfnCount=0;
341
342         pfnCount = (Len - sizeof(VMBUS_CHANNEL_GPADL_BODY))/ sizeof(u64);
343         DPRINT_DBG(VMBUS, "gpadl body - len %d pfn count %d", Len, pfnCount);
344
345         for (i=0; i< pfnCount; i++)
346         {
347                 DPRINT_DBG(VMBUS, "gpadl body  - %d) pfn %llu", i, Gpadl->Pfn[i]);
348         }
349 }
350
351
352 /*++;
353
354 Name:
355         DumpGpadlHeader()
356
357 Description:
358         Dump the gpadl header message to the console for debugging purposes.
359
360 --*/
361 static void DumpGpadlHeader(
362         VMBUS_CHANNEL_GPADL_HEADER      *Gpadl
363         )
364 {
365         int i=0,j=0;
366         int pageCount=0;
367
368
369         DPRINT_DBG(VMBUS, "gpadl header - relid %d, range count %d, range buflen %d",
370                                 Gpadl->ChildRelId,
371                                 Gpadl->RangeCount,
372                                 Gpadl->RangeBufLen);
373         for (i=0; i< Gpadl->RangeCount; i++)
374         {
375                 pageCount = Gpadl->Range[i].ByteCount >> PAGE_SHIFT;
376                 pageCount = (pageCount > 26)? 26 : pageCount;
377
378                 DPRINT_DBG(VMBUS, "gpadl range %d - len %d offset %d page count %d",
379                         i, Gpadl->Range[i].ByteCount, Gpadl->Range[i].ByteOffset, pageCount);
380
381                 for (j=0; j< pageCount; j++)
382                 {
383                         DPRINT_DBG(VMBUS, "%d) pfn %llu", j, Gpadl->Range[i].PfnArray[j]);
384                 }
385         }
386 }
387
388 /*++;
389
390 Name:
391         VmbusChannelCreateGpadlHeader()
392
393 Description:
394         Creates a gpadl for the specified buffer
395
396 --*/
397 static int
398 VmbusChannelCreateGpadlHeader(
399         void *                                  Kbuffer,        /* from kmalloc() */
400         u32                                     Size,           /* page-size multiple */
401         VMBUS_CHANNEL_MSGINFO   **MsgInfo,
402         u32                                     *MessageCount)
403 {
404         int i;
405         int pageCount;
406     unsigned long long pfn;
407         VMBUS_CHANNEL_GPADL_HEADER* gpaHeader;
408         VMBUS_CHANNEL_GPADL_BODY* gpadlBody;
409         VMBUS_CHANNEL_MSGINFO* msgHeader;
410         VMBUS_CHANNEL_MSGINFO* msgBody;
411         u32                             msgSize;
412
413         int pfnSum, pfnCount, pfnLeft, pfnCurr, pfnSize;
414
415         /* ASSERT( (kbuffer & (PAGE_SIZE-1)) == 0); */
416         ASSERT( (Size & (PAGE_SIZE-1)) == 0);
417
418         pageCount = Size >> PAGE_SHIFT;
419         pfn = virt_to_phys(Kbuffer) >> PAGE_SHIFT;
420
421         /* do we need a gpadl body msg */
422         pfnSize = MAX_SIZE_CHANNEL_MESSAGE - sizeof(VMBUS_CHANNEL_GPADL_HEADER) - sizeof(GPA_RANGE);
423         pfnCount = pfnSize / sizeof(u64);
424
425         if (pageCount > pfnCount) /* we need a gpadl body */
426         {
427                 /* fill in the header */
428                 msgSize = sizeof(VMBUS_CHANNEL_MSGINFO) + sizeof(VMBUS_CHANNEL_GPADL_HEADER) + sizeof(GPA_RANGE) + pfnCount*sizeof(u64);
429                 msgHeader =  kzalloc(msgSize, GFP_KERNEL);
430
431                 INITIALIZE_LIST_HEAD(&msgHeader->SubMsgList);
432                 msgHeader->MessageSize=msgSize;
433
434                 gpaHeader = (VMBUS_CHANNEL_GPADL_HEADER*)msgHeader->Msg;
435                 gpaHeader->RangeCount = 1;
436                 gpaHeader->RangeBufLen = sizeof(GPA_RANGE) + pageCount*sizeof(u64);
437                 gpaHeader->Range[0].ByteOffset = 0;
438                 gpaHeader->Range[0].ByteCount = Size;
439                 for (i=0; i<pfnCount; i++)
440                 {
441                         gpaHeader->Range[0].PfnArray[i] = pfn+i;
442                 }
443                 *MsgInfo = msgHeader;
444                 *MessageCount = 1;
445
446                 pfnSum = pfnCount;
447                 pfnLeft = pageCount - pfnCount;
448
449                 /* how many pfns can we fit */
450                 pfnSize = MAX_SIZE_CHANNEL_MESSAGE - sizeof(VMBUS_CHANNEL_GPADL_BODY);
451                 pfnCount = pfnSize / sizeof(u64);
452
453                 /* fill in the body */
454                 while (pfnLeft)
455                 {
456                         if (pfnLeft > pfnCount)
457                         {
458                                 pfnCurr = pfnCount;
459                         }
460                         else
461                         {
462                                 pfnCurr = pfnLeft;
463                         }
464
465                         msgSize = sizeof(VMBUS_CHANNEL_MSGINFO) + sizeof(VMBUS_CHANNEL_GPADL_BODY) + pfnCurr*sizeof(u64);
466                         msgBody = kzalloc(msgSize, GFP_KERNEL);
467                         ASSERT(msgBody);
468                         msgBody->MessageSize = msgSize;
469                         (*MessageCount)++;
470                         gpadlBody = (VMBUS_CHANNEL_GPADL_BODY*)msgBody->Msg;
471
472                         /* FIXME: Gpadl is u32 and we are using a pointer which could be 64-bit */
473                         /* gpadlBody->Gpadl = kbuffer; */
474                         for (i=0; i<pfnCurr; i++)
475                         {
476                                 gpadlBody->Pfn[i] = pfn + pfnSum + i;
477                         }
478
479                         /* add to msg header */
480                         INSERT_TAIL_LIST(&msgHeader->SubMsgList, &msgBody->MsgListEntry);
481                         pfnSum += pfnCurr;
482                         pfnLeft -= pfnCurr;
483                 }
484         }
485         else
486         {
487                 /* everything fits in a header */
488                 msgSize = sizeof(VMBUS_CHANNEL_MSGINFO) + sizeof(VMBUS_CHANNEL_GPADL_HEADER) + sizeof(GPA_RANGE) + pageCount*sizeof(u64);
489                 msgHeader = kzalloc(msgSize, GFP_KERNEL);
490                 msgHeader->MessageSize=msgSize;
491
492                 gpaHeader = (VMBUS_CHANNEL_GPADL_HEADER*)msgHeader->Msg;
493                 gpaHeader->RangeCount = 1;
494                 gpaHeader->RangeBufLen = sizeof(GPA_RANGE) + pageCount*sizeof(u64);
495                 gpaHeader->Range[0].ByteOffset = 0;
496                 gpaHeader->Range[0].ByteCount = Size;
497                 for (i=0; i<pageCount; i++)
498                 {
499                         gpaHeader->Range[0].PfnArray[i] = pfn+i;
500                 }
501
502                 *MsgInfo = msgHeader;
503                 *MessageCount = 1;
504         }
505
506         return 0;
507 }
508
509
510 /*++;
511
512 Name:
513         VmbusChannelEstablishGpadl()
514
515 Description:
516         Estabish a GPADL for the specified buffer
517
518 --*/
519 int
520 VmbusChannelEstablishGpadl(
521         VMBUS_CHANNEL   *Channel,
522         void *                  Kbuffer,        /* from kmalloc() */
523         u32                     Size,           /* page-size multiple */
524         u32                     *GpadlHandle
525         )
526 {
527         int ret=0;
528         VMBUS_CHANNEL_GPADL_HEADER* gpadlMsg;
529         VMBUS_CHANNEL_GPADL_BODY* gpadlBody;
530         /* VMBUS_CHANNEL_GPADL_CREATED* gpadlCreated; */
531
532         VMBUS_CHANNEL_MSGINFO *msgInfo;
533         VMBUS_CHANNEL_MSGINFO *subMsgInfo;
534
535         u32 msgCount;
536         LIST_ENTRY* anchor;
537         LIST_ENTRY* curr;
538         u32 nextGpadlHandle;
539         unsigned long flags;
540
541         DPRINT_ENTER(VMBUS);
542
543         nextGpadlHandle = atomic_read(&gVmbusConnection.NextGpadlHandle);
544         atomic_inc(&gVmbusConnection.NextGpadlHandle);
545
546         VmbusChannelCreateGpadlHeader(Kbuffer, Size, &msgInfo, &msgCount);
547         ASSERT(msgInfo != NULL);
548         ASSERT(msgCount >0);
549
550         msgInfo->WaitEvent = osd_WaitEventCreate();
551         gpadlMsg = (VMBUS_CHANNEL_GPADL_HEADER*)msgInfo->Msg;
552         gpadlMsg->Header.MessageType = ChannelMessageGpadlHeader;
553         gpadlMsg->ChildRelId = Channel->OfferMsg.ChildRelId;
554         gpadlMsg->Gpadl = nextGpadlHandle;
555
556         DumpGpadlHeader(gpadlMsg);
557
558         spin_lock_irqsave(&gVmbusConnection.channelmsg_lock, flags);
559         INSERT_TAIL_LIST(&gVmbusConnection.ChannelMsgList, &msgInfo->MsgListEntry);
560         spin_unlock_irqrestore(&gVmbusConnection.channelmsg_lock, flags);
561
562         DPRINT_DBG(VMBUS, "buffer %p, size %d msg cnt %d", Kbuffer, Size, msgCount);
563
564         DPRINT_DBG(VMBUS, "Sending GPADL Header - len %zd", msgInfo->MessageSize - sizeof(VMBUS_CHANNEL_MSGINFO));
565
566         ret = VmbusPostMessage(gpadlMsg, msgInfo->MessageSize - sizeof(VMBUS_CHANNEL_MSGINFO));
567         if (ret != 0)
568         {
569                 DPRINT_ERR(VMBUS, "Unable to open channel - %d", ret);
570                 goto Cleanup;
571         }
572
573         if (msgCount>1)
574         {
575                 ITERATE_LIST_ENTRIES(anchor, curr, &msgInfo->SubMsgList)
576                 {
577                         subMsgInfo = (VMBUS_CHANNEL_MSGINFO*) curr;
578                         gpadlBody = (VMBUS_CHANNEL_GPADL_BODY*)subMsgInfo->Msg;
579
580                         gpadlBody->Header.MessageType = ChannelMessageGpadlBody;
581                         gpadlBody->Gpadl = nextGpadlHandle;
582
583                         DPRINT_DBG(VMBUS, "Sending GPADL Body - len %zd", subMsgInfo->MessageSize - sizeof(VMBUS_CHANNEL_MSGINFO));
584
585                         DumpGpadlBody(gpadlBody, subMsgInfo->MessageSize - sizeof(VMBUS_CHANNEL_MSGINFO));
586                         ret = VmbusPostMessage(gpadlBody, subMsgInfo->MessageSize - sizeof(VMBUS_CHANNEL_MSGINFO));
587                         ASSERT(ret == 0);
588                 }
589         }
590         osd_WaitEventWait(msgInfo->WaitEvent);
591
592         /* At this point, we received the gpadl created msg */
593         DPRINT_DBG(VMBUS, "Received GPADL created (relid %d, status %d handle %x)",
594                 Channel->OfferMsg.ChildRelId,
595                 msgInfo->Response.GpadlCreated.CreationStatus,
596                 gpadlMsg->Gpadl);
597
598         *GpadlHandle = gpadlMsg->Gpadl;
599
600 Cleanup:
601         spin_lock_irqsave(&gVmbusConnection.channelmsg_lock, flags);
602         REMOVE_ENTRY_LIST(&msgInfo->MsgListEntry);
603         spin_unlock_irqrestore(&gVmbusConnection.channelmsg_lock, flags);
604
605         kfree(msgInfo->WaitEvent);
606         kfree(msgInfo);
607
608         DPRINT_EXIT(VMBUS);
609
610         return ret;
611 }
612
613
614
615 /*++;
616
617 Name:
618         VmbusChannelTeardownGpadl()
619
620 Description:
621         Teardown the specified GPADL handle
622
623 --*/
624 int
625 VmbusChannelTeardownGpadl(
626         VMBUS_CHANNEL   *Channel,
627         u32                     GpadlHandle
628         )
629 {
630         int ret=0;
631         VMBUS_CHANNEL_GPADL_TEARDOWN *msg;
632         VMBUS_CHANNEL_MSGINFO* info;
633         unsigned long flags;
634
635         DPRINT_ENTER(VMBUS);
636
637         ASSERT(GpadlHandle != 0);
638
639         info = kmalloc(sizeof(VMBUS_CHANNEL_MSGINFO) + sizeof(VMBUS_CHANNEL_GPADL_TEARDOWN), GFP_KERNEL);
640         ASSERT(info != NULL);
641
642         info->WaitEvent = osd_WaitEventCreate();
643
644         msg = (VMBUS_CHANNEL_GPADL_TEARDOWN*)info->Msg;
645
646         msg->Header.MessageType = ChannelMessageGpadlTeardown;
647     msg->ChildRelId  = Channel->OfferMsg.ChildRelId;
648     msg->Gpadl       = GpadlHandle;
649
650         spin_lock_irqsave(&gVmbusConnection.channelmsg_lock, flags);
651         INSERT_TAIL_LIST(&gVmbusConnection.ChannelMsgList, &info->MsgListEntry);
652         spin_unlock_irqrestore(&gVmbusConnection.channelmsg_lock, flags);
653
654         ret = VmbusPostMessage(msg, sizeof(VMBUS_CHANNEL_GPADL_TEARDOWN));
655         if (ret != 0)
656         {
657                 /* TODO: */
658         }
659
660         osd_WaitEventWait(info->WaitEvent);
661
662         /* Received a torndown response */
663         spin_lock_irqsave(&gVmbusConnection.channelmsg_lock, flags);
664         REMOVE_ENTRY_LIST(&info->MsgListEntry);
665         spin_unlock_irqrestore(&gVmbusConnection.channelmsg_lock, flags);
666
667         kfree(info->WaitEvent);
668         kfree(info);
669
670         DPRINT_EXIT(VMBUS);
671
672         return ret;
673 }
674
675
676 /*++
677
678 Name:
679         VmbusChannelClose()
680
681 Description:
682         Close the specified channel
683
684 --*/
685 void
686 VmbusChannelClose(
687         VMBUS_CHANNEL   *Channel
688         )
689 {
690         int ret=0;
691         VMBUS_CHANNEL_CLOSE_CHANNEL* msg;
692         VMBUS_CHANNEL_MSGINFO* info;
693         unsigned long flags;
694
695         DPRINT_ENTER(VMBUS);
696
697         /* Stop callback and cancel the timer asap */
698         Channel->OnChannelCallback = NULL;
699         del_timer(&Channel->poll_timer);
700
701         /* Send a closing message */
702         info = kmalloc(sizeof(VMBUS_CHANNEL_MSGINFO) + sizeof(VMBUS_CHANNEL_CLOSE_CHANNEL), GFP_KERNEL);
703         ASSERT(info != NULL);
704
705         /* info->waitEvent = osd_WaitEventCreate(); */
706
707         msg = (VMBUS_CHANNEL_CLOSE_CHANNEL*)info->Msg;
708         msg->Header.MessageType                         = ChannelMessageCloseChannel;
709     msg->ChildRelId                                             = Channel->OfferMsg.ChildRelId;
710
711         ret = VmbusPostMessage(msg, sizeof(VMBUS_CHANNEL_CLOSE_CHANNEL));
712         if (ret != 0)
713         {
714                 /* TODO: */
715         }
716
717         /* Tear down the gpadl for the channel's ring buffer */
718         if (Channel->RingBufferGpadlHandle)
719         {
720                 VmbusChannelTeardownGpadl(Channel, Channel->RingBufferGpadlHandle);
721         }
722
723         /* TODO: Send a msg to release the childRelId */
724
725         /* Cleanup the ring buffers for this channel */
726         RingBufferCleanup(&Channel->Outbound);
727         RingBufferCleanup(&Channel->Inbound);
728
729         osd_PageFree(Channel->RingBufferPages, Channel->RingBufferPageCount);
730
731         kfree(info);
732
733
734         /*
735          * If we are closing the channel during an error path in
736          * opening the channel, don't free the channel since the
737          * caller will free the channel
738          */
739
740         if (Channel->State == CHANNEL_OPEN_STATE)
741         {
742                 spin_lock_irqsave(&gVmbusConnection.channel_lock, flags);
743                 REMOVE_ENTRY_LIST(&Channel->ListEntry);
744                 spin_unlock_irqrestore(&gVmbusConnection.channel_lock, flags);
745
746                 FreeVmbusChannel(Channel);
747         }
748
749         DPRINT_EXIT(VMBUS);
750 }
751
752
753 /*++
754
755 Name:
756         VmbusChannelSendPacket()
757
758 Description:
759         Send the specified buffer on the given channel
760
761 --*/
762 int
763 VmbusChannelSendPacket(
764         VMBUS_CHANNEL           *Channel,
765         const void *                    Buffer,
766         u32                             BufferLen,
767         u64                             RequestId,
768         VMBUS_PACKET_TYPE       Type,
769         u32                             Flags
770 )
771 {
772         int ret=0;
773         VMPACKET_DESCRIPTOR desc;
774         u32 packetLen = sizeof(VMPACKET_DESCRIPTOR) + BufferLen;
775         u32 packetLenAligned = ALIGN_UP(packetLen, sizeof(u64));
776         struct scatterlist bufferList[3];
777         u64 alignedData=0;
778
779         DPRINT_ENTER(VMBUS);
780         DPRINT_DBG(VMBUS, "channel %p buffer %p len %d", Channel, Buffer, BufferLen);
781
782         DumpVmbusChannel(Channel);
783
784         ASSERT((packetLenAligned - packetLen) < sizeof(u64));
785
786         /* Setup the descriptor */
787         desc.Type = Type; /* VmbusPacketTypeDataInBand; */
788         desc.Flags = Flags; /* VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED; */
789         desc.DataOffset8 = sizeof(VMPACKET_DESCRIPTOR) >> 3; /* in 8-bytes granularity */
790         desc.Length8 = (u16)(packetLenAligned >> 3);
791         desc.TransactionId = RequestId;
792
793         sg_init_table(bufferList,3);
794         sg_set_buf(&bufferList[0], &desc, sizeof(VMPACKET_DESCRIPTOR));
795         sg_set_buf(&bufferList[1], Buffer, BufferLen);
796         sg_set_buf(&bufferList[2], &alignedData, packetLenAligned - packetLen);
797
798         ret = RingBufferWrite(
799                 &Channel->Outbound,
800                 bufferList,
801                 3);
802
803         /* TODO: We should determine if this is optional */
804         if (ret == 0 && !GetRingBufferInterruptMask(&Channel->Outbound))
805         {
806                 VmbusChannelSetEvent(Channel);
807         }
808
809         DPRINT_EXIT(VMBUS);
810
811         return ret;
812 }
813
814
815 /*++
816
817 Name:
818         VmbusChannelSendPacketPageBuffer()
819
820 Description:
821         Send a range of single-page buffer packets using a GPADL Direct packet type.
822
823 --*/
824 int
825 VmbusChannelSendPacketPageBuffer(
826         VMBUS_CHANNEL           *Channel,
827         PAGE_BUFFER                     PageBuffers[],
828         u32                             PageCount,
829         void *                          Buffer,
830         u32                             BufferLen,
831         u64                             RequestId
832 )
833 {
834         int ret=0;
835         int i=0;
836         struct VMBUS_CHANNEL_PACKET_PAGE_BUFFER desc;
837         u32 descSize;
838         u32 packetLen;
839         u32 packetLenAligned;
840         struct scatterlist bufferList[3];
841         u64 alignedData=0;
842
843         DPRINT_ENTER(VMBUS);
844
845         ASSERT(PageCount <= MAX_PAGE_BUFFER_COUNT);
846
847         DumpVmbusChannel(Channel);
848
849         /* Adjust the size down since VMBUS_CHANNEL_PACKET_PAGE_BUFFER is the largest size we support */
850         descSize = sizeof(struct VMBUS_CHANNEL_PACKET_PAGE_BUFFER) - ((MAX_PAGE_BUFFER_COUNT - PageCount)*sizeof(PAGE_BUFFER));
851         packetLen = descSize + BufferLen;
852         packetLenAligned = ALIGN_UP(packetLen, sizeof(u64));
853
854         ASSERT((packetLenAligned - packetLen) < sizeof(u64));
855
856         /* Setup the descriptor */
857         desc.Type = VmbusPacketTypeDataUsingGpaDirect;
858         desc.Flags = VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED;
859         desc.DataOffset8 = descSize >> 3; /* in 8-bytes grandularity */
860         desc.Length8 = (u16)(packetLenAligned >> 3);
861         desc.TransactionId = RequestId;
862         desc.RangeCount = PageCount;
863
864         for (i=0; i<PageCount; i++)
865         {
866                 desc.Range[i].Length = PageBuffers[i].Length;
867                 desc.Range[i].Offset = PageBuffers[i].Offset;
868                 desc.Range[i].Pfn        = PageBuffers[i].Pfn;
869         }
870
871         sg_init_table(bufferList,3);
872         sg_set_buf(&bufferList[0], &desc, descSize);
873         sg_set_buf(&bufferList[1], Buffer, BufferLen);
874         sg_set_buf(&bufferList[2], &alignedData, packetLenAligned - packetLen);
875
876         ret = RingBufferWrite(
877                 &Channel->Outbound,
878                 bufferList,
879                 3);
880
881         /* TODO: We should determine if this is optional */
882         if (ret == 0 && !GetRingBufferInterruptMask(&Channel->Outbound))
883         {
884                 VmbusChannelSetEvent(Channel);
885         }
886
887         DPRINT_EXIT(VMBUS);
888
889         return ret;
890 }
891
892
893
894 /*++
895
896 Name:
897         VmbusChannelSendPacketMultiPageBuffer()
898
899 Description:
900         Send a multi-page buffer packet using a GPADL Direct packet type.
901
902 --*/
903 int
904 VmbusChannelSendPacketMultiPageBuffer(
905         VMBUS_CHANNEL           *Channel,
906         MULTIPAGE_BUFFER        *MultiPageBuffer,
907         void *                          Buffer,
908         u32                             BufferLen,
909         u64                             RequestId
910 )
911 {
912         int ret=0;
913         struct VMBUS_CHANNEL_PACKET_MULITPAGE_BUFFER desc;
914         u32 descSize;
915         u32 packetLen;
916         u32 packetLenAligned;
917         struct scatterlist bufferList[3];
918         u64 alignedData=0;
919         u32 PfnCount = NUM_PAGES_SPANNED(MultiPageBuffer->Offset, MultiPageBuffer->Length);
920
921         DPRINT_ENTER(VMBUS);
922
923         DumpVmbusChannel(Channel);
924
925         DPRINT_DBG(VMBUS, "data buffer - offset %u len %u pfn count %u", MultiPageBuffer->Offset, MultiPageBuffer->Length, PfnCount);
926
927         ASSERT(PfnCount > 0);
928         ASSERT(PfnCount <= MAX_MULTIPAGE_BUFFER_COUNT);
929
930         /* Adjust the size down since VMBUS_CHANNEL_PACKET_MULITPAGE_BUFFER is the largest size we support */
931         descSize = sizeof(struct VMBUS_CHANNEL_PACKET_MULITPAGE_BUFFER) - ((MAX_MULTIPAGE_BUFFER_COUNT - PfnCount)*sizeof(u64));
932         packetLen = descSize + BufferLen;
933         packetLenAligned = ALIGN_UP(packetLen, sizeof(u64));
934
935         ASSERT((packetLenAligned - packetLen) < sizeof(u64));
936
937         /* Setup the descriptor */
938         desc.Type = VmbusPacketTypeDataUsingGpaDirect;
939         desc.Flags = VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED;
940         desc.DataOffset8 = descSize >> 3; /* in 8-bytes grandularity */
941         desc.Length8 = (u16)(packetLenAligned >> 3);
942         desc.TransactionId = RequestId;
943         desc.RangeCount = 1;
944
945         desc.Range.Length = MultiPageBuffer->Length;
946         desc.Range.Offset = MultiPageBuffer->Offset;
947
948         memcpy(desc.Range.PfnArray, MultiPageBuffer->PfnArray, PfnCount*sizeof(u64));
949
950         sg_init_table(bufferList,3);
951         sg_set_buf(&bufferList[0], &desc, descSize);
952         sg_set_buf(&bufferList[1], Buffer, BufferLen);
953         sg_set_buf(&bufferList[2], &alignedData, packetLenAligned - packetLen);
954
955         ret = RingBufferWrite(
956                 &Channel->Outbound,
957                 bufferList,
958                 3);
959
960         /* TODO: We should determine if this is optional */
961         if (ret == 0 && !GetRingBufferInterruptMask(&Channel->Outbound))
962         {
963                 VmbusChannelSetEvent(Channel);
964         }
965
966         DPRINT_EXIT(VMBUS);
967
968         return ret;
969 }
970
971
972 /*++
973
974 Name:
975         VmbusChannelRecvPacket()
976
977 Description:
978         Retrieve the user packet on the specified channel
979
980 --*/
981 /* TODO: Do we ever receive a gpa direct packet other than the ones we send ? */
982 int VmbusChannelRecvPacket(VMBUS_CHANNEL *Channel,
983                            void *Buffer,
984                            u32 BufferLen,
985                            u32 *BufferActualLen,
986                            u64 *RequestId)
987 {
988         VMPACKET_DESCRIPTOR desc;
989         u32 packetLen;
990         u32 userLen;
991         int ret;
992         unsigned long flags;
993
994         DPRINT_ENTER(VMBUS);
995
996         *BufferActualLen = 0;
997         *RequestId = 0;
998
999         spin_lock_irqsave(&Channel->inbound_lock, flags);
1000
1001         ret = RingBufferPeek(&Channel->Inbound, &desc, sizeof(VMPACKET_DESCRIPTOR));
1002         if (ret != 0)
1003         {
1004                 spin_unlock_irqrestore(&Channel->inbound_lock, flags);
1005
1006                 /* DPRINT_DBG(VMBUS, "nothing to read!!"); */
1007                 DPRINT_EXIT(VMBUS);
1008                 return 0;
1009         }
1010
1011         /* VmbusChannelClearEvent(Channel); */
1012
1013         packetLen = desc.Length8 << 3;
1014         userLen = packetLen - (desc.DataOffset8 << 3);
1015         /* ASSERT(userLen > 0); */
1016
1017         DPRINT_DBG(VMBUS, "packet received on channel %p relid %d <type %d flag %d tid %llx pktlen %d datalen %d> ",
1018                 Channel,
1019                 Channel->OfferMsg.ChildRelId,
1020                 desc.Type,
1021                 desc.Flags,
1022                 desc.TransactionId, packetLen, userLen);
1023
1024         *BufferActualLen = userLen;
1025
1026         if (userLen > BufferLen)
1027         {
1028                 spin_unlock_irqrestore(&Channel->inbound_lock, flags);
1029
1030                 DPRINT_ERR(VMBUS, "buffer too small - got %d needs %d", BufferLen, userLen);
1031                 DPRINT_EXIT(VMBUS);
1032
1033                 return -1;
1034         }
1035
1036         *RequestId = desc.TransactionId;
1037
1038         /* Copy over the packet to the user buffer */
1039         ret = RingBufferRead(&Channel->Inbound, Buffer, userLen, (desc.DataOffset8 << 3));
1040
1041         spin_unlock_irqrestore(&Channel->inbound_lock, flags);
1042
1043         DPRINT_EXIT(VMBUS);
1044
1045         return 0;
1046 }
1047
1048 /*++
1049
1050 Name:
1051         VmbusChannelRecvPacketRaw()
1052
1053 Description:
1054         Retrieve the raw packet on the specified channel
1055
1056 --*/
1057 int
1058 VmbusChannelRecvPacketRaw(
1059         VMBUS_CHANNEL           *Channel,
1060         void *                          Buffer,
1061         u32                             BufferLen,
1062         u32*                            BufferActualLen,
1063         u64*                            RequestId
1064         )
1065 {
1066         VMPACKET_DESCRIPTOR desc;
1067         u32 packetLen;
1068         u32 userLen;
1069         int ret;
1070         unsigned long flags;
1071
1072         DPRINT_ENTER(VMBUS);
1073
1074         *BufferActualLen = 0;
1075         *RequestId = 0;
1076
1077         spin_lock_irqsave(&Channel->inbound_lock, flags);
1078
1079         ret = RingBufferPeek(&Channel->Inbound, &desc, sizeof(VMPACKET_DESCRIPTOR));
1080         if (ret != 0)
1081         {
1082                 spin_unlock_irqrestore(&Channel->inbound_lock, flags);
1083
1084                 /* DPRINT_DBG(VMBUS, "nothing to read!!"); */
1085                 DPRINT_EXIT(VMBUS);
1086                 return 0;
1087         }
1088
1089         /* VmbusChannelClearEvent(Channel); */
1090
1091         packetLen = desc.Length8 << 3;
1092         userLen = packetLen - (desc.DataOffset8 << 3);
1093
1094         DPRINT_DBG(VMBUS, "packet received on channel %p relid %d <type %d flag %d tid %llx pktlen %d datalen %d> ",
1095                 Channel,
1096                 Channel->OfferMsg.ChildRelId,
1097                 desc.Type,
1098                 desc.Flags,
1099                 desc.TransactionId, packetLen, userLen);
1100
1101         *BufferActualLen = packetLen;
1102
1103         if (packetLen > BufferLen)
1104         {
1105                 spin_unlock_irqrestore(&Channel->inbound_lock, flags);
1106
1107                 DPRINT_ERR(VMBUS, "buffer too small - needed %d bytes but got space for only %d bytes", packetLen, BufferLen);
1108                 DPRINT_EXIT(VMBUS);
1109                 return -2;
1110         }
1111
1112         *RequestId = desc.TransactionId;
1113
1114         /* Copy over the entire packet to the user buffer */
1115         ret = RingBufferRead(&Channel->Inbound, Buffer, packetLen, 0);
1116
1117         spin_unlock_irqrestore(&Channel->inbound_lock, flags);
1118
1119         DPRINT_EXIT(VMBUS);
1120
1121         return 0;
1122 }
1123
1124
1125 /*++
1126
1127 Name:
1128         VmbusChannelOnChannelEvent()
1129
1130 Description:
1131         Channel event callback
1132
1133 --*/
1134 void VmbusChannelOnChannelEvent(VMBUS_CHANNEL *Channel)
1135 {
1136         DumpVmbusChannel(Channel);
1137         ASSERT(Channel->OnChannelCallback);
1138 #ifdef ENABLE_POLLING
1139         del_timer(&Channel->poll_timer);
1140         Channel->OnChannelCallback(Channel->ChannelCallbackContext);
1141         channel->poll_timer.expires(jiffies + usecs_to_jiffies(100);
1142         add_timer(&channel->poll_timer);
1143 #else
1144         Channel->OnChannelCallback(Channel->ChannelCallbackContext);
1145 #endif
1146 }
1147
1148 /*++
1149
1150 Name:
1151         VmbusChannelOnTimer()
1152
1153 Description:
1154         Timer event callback
1155
1156 --*/
1157 void VmbusChannelOnTimer(unsigned long data)
1158 {
1159         VMBUS_CHANNEL *channel = (VMBUS_CHANNEL*)data;
1160
1161         if (channel->OnChannelCallback)
1162         {
1163                 channel->OnChannelCallback(channel->ChannelCallbackContext);
1164 #ifdef ENABLE_POLLING
1165                 channel->poll_timer.expires(jiffies + usecs_to_jiffies(100);
1166                 add_timer(&channel->poll_timer);
1167 #endif
1168         }
1169 }
1170
1171
1172 /*++
1173
1174 Name:
1175         DumpVmbusChannel()
1176
1177 Description:
1178         Dump vmbus channel info to the console
1179
1180 --*/
1181 static void
1182 DumpVmbusChannel(
1183         VMBUS_CHANNEL           *Channel
1184         )
1185 {
1186         DPRINT_DBG(VMBUS, "Channel (%d)", Channel->OfferMsg.ChildRelId);
1187         DumpRingInfo(&Channel->Outbound, "Outbound ");
1188         DumpRingInfo(&Channel->Inbound, "Inbound ");
1189 }
1190
1191
1192 /* eof */