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