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