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