GUI: Fix Tomato RAF theme for all builds. Compilation typo.
[tomato.git] / release / src-rt-6.x.4708 / linux / linux-2.6.36 / drivers / staging / hv / channel.c
blob4df8afbb0c20e6834c32c3715c3f5b0ceaa2fc6e
1 /*
2 * Copyright (c) 2009, Microsoft Corporation.
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.
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.
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.
17 * Authors:
18 * Haiyang Zhang <haiyangz@microsoft.com>
19 * Hank Janssen <hjanssen@microsoft.com>
21 #include <linux/kernel.h>
22 #include <linux/mm.h>
23 #include <linux/slab.h>
24 #include <linux/module.h>
25 #include "osd.h"
26 #include "logging.h"
27 #include "vmbus_private.h"
29 /* Internal routines */
30 static int VmbusChannelCreateGpadlHeader(
31 void *Kbuffer, /* must be phys and virt contiguous */
32 u32 Size, /* page-size multiple */
33 struct vmbus_channel_msginfo **msgInfo,
34 u32 *MessageCount);
35 static void DumpVmbusChannel(struct vmbus_channel *channel);
36 static void VmbusChannelSetEvent(struct vmbus_channel *channel);
41 * VmbusChannelSetEvent - Trigger an event notification on the specified
42 * channel.
44 static void VmbusChannelSetEvent(struct vmbus_channel *Channel)
46 struct hv_monitor_page *monitorPage;
48 if (Channel->OfferMsg.MonitorAllocated) {
49 /* Each u32 represents 32 channels */
50 set_bit(Channel->OfferMsg.ChildRelId & 31,
51 (unsigned long *) gVmbusConnection.SendInterruptPage +
52 (Channel->OfferMsg.ChildRelId >> 5));
54 monitorPage = gVmbusConnection.MonitorPages;
55 monitorPage++; /* Get the child to parent monitor page */
57 set_bit(Channel->MonitorBit,
58 (unsigned long *)&monitorPage->TriggerGroup
59 [Channel->MonitorGroup].Pending);
61 } else {
62 VmbusSetEvent(Channel->OfferMsg.ChildRelId);
67 * VmbusChannelGetDebugInfo -Retrieve various channel debug info
69 void VmbusChannelGetDebugInfo(struct vmbus_channel *Channel,
70 struct vmbus_channel_debug_info *DebugInfo)
72 struct hv_monitor_page *monitorPage;
73 u8 monitorGroup = (u8)Channel->OfferMsg.MonitorId / 32;
74 u8 monitorOffset = (u8)Channel->OfferMsg.MonitorId % 32;
75 /* u32 monitorBit = 1 << monitorOffset; */
77 DebugInfo->RelId = Channel->OfferMsg.ChildRelId;
78 DebugInfo->State = Channel->State;
79 memcpy(&DebugInfo->InterfaceType,
80 &Channel->OfferMsg.Offer.InterfaceType, sizeof(struct hv_guid));
81 memcpy(&DebugInfo->InterfaceInstance,
82 &Channel->OfferMsg.Offer.InterfaceInstance,
83 sizeof(struct hv_guid));
85 monitorPage = (struct hv_monitor_page *)gVmbusConnection.MonitorPages;
87 DebugInfo->MonitorId = Channel->OfferMsg.MonitorId;
89 DebugInfo->ServerMonitorPending =
90 monitorPage->TriggerGroup[monitorGroup].Pending;
91 DebugInfo->ServerMonitorLatency =
92 monitorPage->Latency[monitorGroup][monitorOffset];
93 DebugInfo->ServerMonitorConnectionId =
94 monitorPage->Parameter[monitorGroup]
95 [monitorOffset].ConnectionId.u.Id;
97 monitorPage++;
99 DebugInfo->ClientMonitorPending =
100 monitorPage->TriggerGroup[monitorGroup].Pending;
101 DebugInfo->ClientMonitorLatency =
102 monitorPage->Latency[monitorGroup][monitorOffset];
103 DebugInfo->ClientMonitorConnectionId =
104 monitorPage->Parameter[monitorGroup]
105 [monitorOffset].ConnectionId.u.Id;
107 RingBufferGetDebugInfo(&Channel->Inbound, &DebugInfo->Inbound);
108 RingBufferGetDebugInfo(&Channel->Outbound, &DebugInfo->Outbound);
112 * VmbusChannelOpen - Open the specified channel.
114 int VmbusChannelOpen(struct vmbus_channel *NewChannel, u32 SendRingBufferSize,
115 u32 RecvRingBufferSize, void *UserData, u32 UserDataLen,
116 void (*OnChannelCallback)(void *context), void *Context)
118 struct vmbus_channel_open_channel *openMsg;
119 struct vmbus_channel_msginfo *openInfo = NULL;
120 void *in, *out;
121 unsigned long flags;
122 int ret, err = 0;
124 /* Aligned to page size */
125 /* ASSERT(!(SendRingBufferSize & (PAGE_SIZE - 1))); */
126 /* ASSERT(!(RecvRingBufferSize & (PAGE_SIZE - 1))); */
128 NewChannel->OnChannelCallback = OnChannelCallback;
129 NewChannel->ChannelCallbackContext = Context;
131 /* Allocate the ring buffer */
132 out = osd_PageAlloc((SendRingBufferSize + RecvRingBufferSize)
133 >> PAGE_SHIFT);
134 if (!out)
135 return -ENOMEM;
137 /* ASSERT(((unsigned long)out & (PAGE_SIZE-1)) == 0); */
139 in = (void *)((unsigned long)out + SendRingBufferSize);
141 NewChannel->RingBufferPages = out;
142 NewChannel->RingBufferPageCount = (SendRingBufferSize +
143 RecvRingBufferSize) >> PAGE_SHIFT;
145 ret = RingBufferInit(&NewChannel->Outbound, out, SendRingBufferSize);
146 if (ret != 0) {
147 err = ret;
148 goto errorout;
151 ret = RingBufferInit(&NewChannel->Inbound, in, RecvRingBufferSize);
152 if (ret != 0) {
153 err = ret;
154 goto errorout;
158 /* Establish the gpadl for the ring buffer */
159 DPRINT_DBG(VMBUS, "Establishing ring buffer's gpadl for channel %p...",
160 NewChannel);
162 NewChannel->RingBufferGpadlHandle = 0;
164 ret = VmbusChannelEstablishGpadl(NewChannel,
165 NewChannel->Outbound.RingBuffer,
166 SendRingBufferSize +
167 RecvRingBufferSize,
168 &NewChannel->RingBufferGpadlHandle);
170 if (ret != 0) {
171 err = ret;
172 goto errorout;
175 DPRINT_DBG(VMBUS, "channel %p <relid %d gpadl 0x%x send ring %p "
176 "size %d recv ring %p size %d, downstreamoffset %d>",
177 NewChannel, NewChannel->OfferMsg.ChildRelId,
178 NewChannel->RingBufferGpadlHandle,
179 NewChannel->Outbound.RingBuffer,
180 NewChannel->Outbound.RingSize,
181 NewChannel->Inbound.RingBuffer,
182 NewChannel->Inbound.RingSize,
183 SendRingBufferSize);
185 /* Create and init the channel open message */
186 openInfo = kmalloc(sizeof(*openInfo) +
187 sizeof(struct vmbus_channel_open_channel),
188 GFP_KERNEL);
189 if (!openInfo) {
190 err = -ENOMEM;
191 goto errorout;
194 openInfo->WaitEvent = osd_WaitEventCreate();
195 if (!openInfo->WaitEvent) {
196 err = -ENOMEM;
197 goto errorout;
200 openMsg = (struct vmbus_channel_open_channel *)openInfo->Msg;
201 openMsg->Header.MessageType = ChannelMessageOpenChannel;
202 openMsg->OpenId = NewChannel->OfferMsg.ChildRelId;
203 openMsg->ChildRelId = NewChannel->OfferMsg.ChildRelId;
204 openMsg->RingBufferGpadlHandle = NewChannel->RingBufferGpadlHandle;
205 openMsg->DownstreamRingBufferPageOffset = SendRingBufferSize >>
206 PAGE_SHIFT;
207 openMsg->ServerContextAreaGpadlHandle = 0; /* TODO */
209 if (UserDataLen > MAX_USER_DEFINED_BYTES) {
210 err = -EINVAL;
211 goto errorout;
214 if (UserDataLen)
215 memcpy(openMsg->UserData, UserData, UserDataLen);
217 spin_lock_irqsave(&gVmbusConnection.channelmsg_lock, flags);
218 list_add_tail(&openInfo->MsgListEntry,
219 &gVmbusConnection.ChannelMsgList);
220 spin_unlock_irqrestore(&gVmbusConnection.channelmsg_lock, flags);
222 DPRINT_DBG(VMBUS, "Sending channel open msg...");
224 ret = VmbusPostMessage(openMsg,
225 sizeof(struct vmbus_channel_open_channel));
226 if (ret != 0) {
227 DPRINT_ERR(VMBUS, "unable to open channel - %d", ret);
228 goto Cleanup;
231 osd_WaitEventWait(openInfo->WaitEvent);
233 if (openInfo->Response.OpenResult.Status == 0)
234 DPRINT_INFO(VMBUS, "channel <%p> open success!!", NewChannel);
235 else
236 DPRINT_INFO(VMBUS, "channel <%p> open failed - %d!!",
237 NewChannel, openInfo->Response.OpenResult.Status);
239 Cleanup:
240 spin_lock_irqsave(&gVmbusConnection.channelmsg_lock, flags);
241 list_del(&openInfo->MsgListEntry);
242 spin_unlock_irqrestore(&gVmbusConnection.channelmsg_lock, flags);
244 kfree(openInfo->WaitEvent);
245 kfree(openInfo);
246 return 0;
248 errorout:
249 RingBufferCleanup(&NewChannel->Outbound);
250 RingBufferCleanup(&NewChannel->Inbound);
251 osd_PageFree(out, (SendRingBufferSize + RecvRingBufferSize)
252 >> PAGE_SHIFT);
253 kfree(openInfo);
254 return err;
258 * DumpGpadlBody - Dump the gpadl body message to the console for
259 * debugging purposes.
261 static void DumpGpadlBody(struct vmbus_channel_gpadl_body *Gpadl, u32 Len)
263 int i;
264 int pfnCount;
266 pfnCount = (Len - sizeof(struct vmbus_channel_gpadl_body)) /
267 sizeof(u64);
268 DPRINT_DBG(VMBUS, "gpadl body - len %d pfn count %d", Len, pfnCount);
270 for (i = 0; i < pfnCount; i++)
271 DPRINT_DBG(VMBUS, "gpadl body - %d) pfn %llu",
272 i, Gpadl->Pfn[i]);
276 * DumpGpadlHeader - Dump the gpadl header message to the console for
277 * debugging purposes.
279 static void DumpGpadlHeader(struct vmbus_channel_gpadl_header *Gpadl)
281 int i, j;
282 int pageCount;
284 DPRINT_DBG(VMBUS,
285 "gpadl header - relid %d, range count %d, range buflen %d",
286 Gpadl->ChildRelId, Gpadl->RangeCount, Gpadl->RangeBufLen);
287 for (i = 0; i < Gpadl->RangeCount; i++) {
288 pageCount = Gpadl->Range[i].ByteCount >> PAGE_SHIFT;
289 pageCount = (pageCount > 26) ? 26 : pageCount;
291 DPRINT_DBG(VMBUS, "gpadl range %d - len %d offset %d "
292 "page count %d", i, Gpadl->Range[i].ByteCount,
293 Gpadl->Range[i].ByteOffset, pageCount);
295 for (j = 0; j < pageCount; j++)
296 DPRINT_DBG(VMBUS, "%d) pfn %llu", j,
297 Gpadl->Range[i].PfnArray[j]);
302 * VmbusChannelCreateGpadlHeader - Creates a gpadl for the specified buffer
304 static int VmbusChannelCreateGpadlHeader(void *Kbuffer, u32 Size,
305 struct vmbus_channel_msginfo **MsgInfo,
306 u32 *MessageCount)
308 int i;
309 int pageCount;
310 unsigned long long pfn;
311 struct vmbus_channel_gpadl_header *gpaHeader;
312 struct vmbus_channel_gpadl_body *gpadlBody;
313 struct vmbus_channel_msginfo *msgHeader;
314 struct vmbus_channel_msginfo *msgBody = NULL;
315 u32 msgSize;
317 int pfnSum, pfnCount, pfnLeft, pfnCurr, pfnSize;
319 /* ASSERT((kbuffer & (PAGE_SIZE-1)) == 0); */
320 /* ASSERT((Size & (PAGE_SIZE-1)) == 0); */
322 pageCount = Size >> PAGE_SHIFT;
323 pfn = virt_to_phys(Kbuffer) >> PAGE_SHIFT;
325 /* do we need a gpadl body msg */
326 pfnSize = MAX_SIZE_CHANNEL_MESSAGE -
327 sizeof(struct vmbus_channel_gpadl_header) -
328 sizeof(struct gpa_range);
329 pfnCount = pfnSize / sizeof(u64);
331 if (pageCount > pfnCount) {
332 /* we need a gpadl body */
333 /* fill in the header */
334 msgSize = sizeof(struct vmbus_channel_msginfo) +
335 sizeof(struct vmbus_channel_gpadl_header) +
336 sizeof(struct gpa_range) + pfnCount * sizeof(u64);
337 msgHeader = kzalloc(msgSize, GFP_KERNEL);
338 if (!msgHeader)
339 goto nomem;
341 INIT_LIST_HEAD(&msgHeader->SubMsgList);
342 msgHeader->MessageSize = msgSize;
344 gpaHeader = (struct vmbus_channel_gpadl_header *)msgHeader->Msg;
345 gpaHeader->RangeCount = 1;
346 gpaHeader->RangeBufLen = sizeof(struct gpa_range) +
347 pageCount * sizeof(u64);
348 gpaHeader->Range[0].ByteOffset = 0;
349 gpaHeader->Range[0].ByteCount = Size;
350 for (i = 0; i < pfnCount; i++)
351 gpaHeader->Range[0].PfnArray[i] = pfn+i;
352 *MsgInfo = msgHeader;
353 *MessageCount = 1;
355 pfnSum = pfnCount;
356 pfnLeft = pageCount - pfnCount;
358 /* how many pfns can we fit */
359 pfnSize = MAX_SIZE_CHANNEL_MESSAGE -
360 sizeof(struct vmbus_channel_gpadl_body);
361 pfnCount = pfnSize / sizeof(u64);
363 /* fill in the body */
364 while (pfnLeft) {
365 if (pfnLeft > pfnCount)
366 pfnCurr = pfnCount;
367 else
368 pfnCurr = pfnLeft;
370 msgSize = sizeof(struct vmbus_channel_msginfo) +
371 sizeof(struct vmbus_channel_gpadl_body) +
372 pfnCurr * sizeof(u64);
373 msgBody = kzalloc(msgSize, GFP_KERNEL);
374 if (!msgBody)
375 goto nomem;
376 msgBody->MessageSize = msgSize;
377 (*MessageCount)++;
378 gpadlBody =
379 (struct vmbus_channel_gpadl_body *)msgBody->Msg;
381 /* gpadlBody->Gpadl = kbuffer; */
382 for (i = 0; i < pfnCurr; i++)
383 gpadlBody->Pfn[i] = pfn + pfnSum + i;
385 /* add to msg header */
386 list_add_tail(&msgBody->MsgListEntry,
387 &msgHeader->SubMsgList);
388 pfnSum += pfnCurr;
389 pfnLeft -= pfnCurr;
391 } else {
392 /* everything fits in a header */
393 msgSize = sizeof(struct vmbus_channel_msginfo) +
394 sizeof(struct vmbus_channel_gpadl_header) +
395 sizeof(struct gpa_range) + pageCount * sizeof(u64);
396 msgHeader = kzalloc(msgSize, GFP_KERNEL);
397 if (msgHeader == NULL)
398 goto nomem;
399 msgHeader->MessageSize = msgSize;
401 gpaHeader = (struct vmbus_channel_gpadl_header *)msgHeader->Msg;
402 gpaHeader->RangeCount = 1;
403 gpaHeader->RangeBufLen = sizeof(struct gpa_range) +
404 pageCount * sizeof(u64);
405 gpaHeader->Range[0].ByteOffset = 0;
406 gpaHeader->Range[0].ByteCount = Size;
407 for (i = 0; i < pageCount; i++)
408 gpaHeader->Range[0].PfnArray[i] = pfn+i;
410 *MsgInfo = msgHeader;
411 *MessageCount = 1;
414 return 0;
415 nomem:
416 kfree(msgHeader);
417 kfree(msgBody);
418 return -ENOMEM;
422 * VmbusChannelEstablishGpadl - Estabish a GPADL for the specified buffer
424 * @Channel: a channel
425 * @Kbuffer: from kmalloc
426 * @Size: page-size multiple
427 * @GpadlHandle: some funky thing
429 int VmbusChannelEstablishGpadl(struct vmbus_channel *Channel, void *Kbuffer,
430 u32 Size, u32 *GpadlHandle)
432 struct vmbus_channel_gpadl_header *gpadlMsg;
433 struct vmbus_channel_gpadl_body *gpadlBody;
434 /* struct vmbus_channel_gpadl_created *gpadlCreated; */
435 struct vmbus_channel_msginfo *msgInfo = NULL;
436 struct vmbus_channel_msginfo *subMsgInfo;
437 u32 msgCount;
438 struct list_head *curr;
439 u32 nextGpadlHandle;
440 unsigned long flags;
441 int ret = 0;
443 nextGpadlHandle = atomic_read(&gVmbusConnection.NextGpadlHandle);
444 atomic_inc(&gVmbusConnection.NextGpadlHandle);
446 ret = VmbusChannelCreateGpadlHeader(Kbuffer, Size, &msgInfo, &msgCount);
447 if (ret)
448 return ret;
450 msgInfo->WaitEvent = osd_WaitEventCreate();
451 if (!msgInfo->WaitEvent) {
452 ret = -ENOMEM;
453 goto Cleanup;
456 gpadlMsg = (struct vmbus_channel_gpadl_header *)msgInfo->Msg;
457 gpadlMsg->Header.MessageType = ChannelMessageGpadlHeader;
458 gpadlMsg->ChildRelId = Channel->OfferMsg.ChildRelId;
459 gpadlMsg->Gpadl = nextGpadlHandle;
461 DumpGpadlHeader(gpadlMsg);
463 spin_lock_irqsave(&gVmbusConnection.channelmsg_lock, flags);
464 list_add_tail(&msgInfo->MsgListEntry,
465 &gVmbusConnection.ChannelMsgList);
467 spin_unlock_irqrestore(&gVmbusConnection.channelmsg_lock, flags);
468 DPRINT_DBG(VMBUS, "buffer %p, size %d msg cnt %d",
469 Kbuffer, Size, msgCount);
471 DPRINT_DBG(VMBUS, "Sending GPADL Header - len %zd",
472 msgInfo->MessageSize - sizeof(*msgInfo));
474 ret = VmbusPostMessage(gpadlMsg, msgInfo->MessageSize -
475 sizeof(*msgInfo));
476 if (ret != 0) {
477 DPRINT_ERR(VMBUS, "Unable to open channel - %d", ret);
478 goto Cleanup;
481 if (msgCount > 1) {
482 list_for_each(curr, &msgInfo->SubMsgList) {
484 subMsgInfo = (struct vmbus_channel_msginfo *)curr;
485 gpadlBody =
486 (struct vmbus_channel_gpadl_body *)subMsgInfo->Msg;
488 gpadlBody->Header.MessageType = ChannelMessageGpadlBody;
489 gpadlBody->Gpadl = nextGpadlHandle;
491 DPRINT_DBG(VMBUS, "Sending GPADL Body - len %zd",
492 subMsgInfo->MessageSize -
493 sizeof(*subMsgInfo));
495 DumpGpadlBody(gpadlBody, subMsgInfo->MessageSize -
496 sizeof(*subMsgInfo));
497 ret = VmbusPostMessage(gpadlBody,
498 subMsgInfo->MessageSize -
499 sizeof(*subMsgInfo));
500 if (ret != 0)
501 goto Cleanup;
505 osd_WaitEventWait(msgInfo->WaitEvent);
507 /* At this point, we received the gpadl created msg */
508 DPRINT_DBG(VMBUS, "Received GPADL created "
509 "(relid %d, status %d handle %x)",
510 Channel->OfferMsg.ChildRelId,
511 msgInfo->Response.GpadlCreated.CreationStatus,
512 gpadlMsg->Gpadl);
514 *GpadlHandle = gpadlMsg->Gpadl;
516 Cleanup:
517 spin_lock_irqsave(&gVmbusConnection.channelmsg_lock, flags);
518 list_del(&msgInfo->MsgListEntry);
519 spin_unlock_irqrestore(&gVmbusConnection.channelmsg_lock, flags);
521 kfree(msgInfo->WaitEvent);
522 kfree(msgInfo);
523 return ret;
527 * VmbusChannelTeardownGpadl -Teardown the specified GPADL handle
529 int VmbusChannelTeardownGpadl(struct vmbus_channel *Channel, u32 GpadlHandle)
531 struct vmbus_channel_gpadl_teardown *msg;
532 struct vmbus_channel_msginfo *info;
533 unsigned long flags;
534 int ret;
536 /* ASSERT(GpadlHandle != 0); */
538 info = kmalloc(sizeof(*info) +
539 sizeof(struct vmbus_channel_gpadl_teardown), GFP_KERNEL);
540 if (!info)
541 return -ENOMEM;
543 info->WaitEvent = osd_WaitEventCreate();
544 if (!info->WaitEvent) {
545 kfree(info);
546 return -ENOMEM;
549 msg = (struct vmbus_channel_gpadl_teardown *)info->Msg;
551 msg->Header.MessageType = ChannelMessageGpadlTeardown;
552 msg->ChildRelId = Channel->OfferMsg.ChildRelId;
553 msg->Gpadl = GpadlHandle;
555 spin_lock_irqsave(&gVmbusConnection.channelmsg_lock, flags);
556 list_add_tail(&info->MsgListEntry,
557 &gVmbusConnection.ChannelMsgList);
558 spin_unlock_irqrestore(&gVmbusConnection.channelmsg_lock, flags);
560 ret = VmbusPostMessage(msg,
561 sizeof(struct vmbus_channel_gpadl_teardown));
562 if (ret != 0) {
563 /* TODO: */
564 /* something... */
567 osd_WaitEventWait(info->WaitEvent);
569 /* Received a torndown response */
570 spin_lock_irqsave(&gVmbusConnection.channelmsg_lock, flags);
571 list_del(&info->MsgListEntry);
572 spin_unlock_irqrestore(&gVmbusConnection.channelmsg_lock, flags);
574 kfree(info->WaitEvent);
575 kfree(info);
576 return ret;
580 * VmbusChannelClose - Close the specified channel
582 void VmbusChannelClose(struct vmbus_channel *Channel)
584 struct vmbus_channel_close_channel *msg;
585 struct vmbus_channel_msginfo *info;
586 unsigned long flags;
587 int ret;
589 /* Stop callback and cancel the timer asap */
590 Channel->OnChannelCallback = NULL;
591 del_timer_sync(&Channel->poll_timer);
593 /* Send a closing message */
594 info = kmalloc(sizeof(*info) +
595 sizeof(struct vmbus_channel_close_channel), GFP_KERNEL);
596 if (!info)
597 return;
599 /* info->waitEvent = osd_WaitEventCreate(); */
601 msg = (struct vmbus_channel_close_channel *)info->Msg;
602 msg->Header.MessageType = ChannelMessageCloseChannel;
603 msg->ChildRelId = Channel->OfferMsg.ChildRelId;
605 ret = VmbusPostMessage(msg, sizeof(struct vmbus_channel_close_channel));
606 if (ret != 0) {
607 /* TODO: */
608 /* something... */
611 /* Tear down the gpadl for the channel's ring buffer */
612 if (Channel->RingBufferGpadlHandle)
613 VmbusChannelTeardownGpadl(Channel,
614 Channel->RingBufferGpadlHandle);
616 /* TODO: Send a msg to release the childRelId */
618 /* Cleanup the ring buffers for this channel */
619 RingBufferCleanup(&Channel->Outbound);
620 RingBufferCleanup(&Channel->Inbound);
622 osd_PageFree(Channel->RingBufferPages, Channel->RingBufferPageCount);
624 kfree(info);
627 * If we are closing the channel during an error path in
628 * opening the channel, don't free the channel since the
629 * caller will free the channel
632 if (Channel->State == CHANNEL_OPEN_STATE) {
633 spin_lock_irqsave(&gVmbusConnection.channel_lock, flags);
634 list_del(&Channel->ListEntry);
635 spin_unlock_irqrestore(&gVmbusConnection.channel_lock, flags);
637 FreeVmbusChannel(Channel);
642 * VmbusChannelSendPacket() - Send the specified buffer on the given channel
643 * @Channel: Pointer to vmbus_channel structure.
644 * @Buffer: Pointer to the buffer you want to receive the data into.
645 * @BufferLen: Maximum size of what the the buffer will hold
646 * @RequestId: Identifier of the request
647 * @vmbus_packet_type: Type of packet that is being send e.g. negotiate, time
648 * packet etc.
650 * Sends data in @Buffer directly to hyper-v via the vmbus
651 * This will send the data unparsed to hyper-v.
653 * Mainly used by Hyper-V drivers.
655 int VmbusChannelSendPacket(struct vmbus_channel *Channel, const void *Buffer,
656 u32 BufferLen, u64 RequestId,
657 enum vmbus_packet_type Type, u32 Flags)
659 struct vmpacket_descriptor desc;
660 u32 packetLen = sizeof(struct vmpacket_descriptor) + BufferLen;
661 u32 packetLenAligned = ALIGN_UP(packetLen, sizeof(u64));
662 struct scatterlist bufferList[3];
663 u64 alignedData = 0;
664 int ret;
666 DPRINT_DBG(VMBUS, "channel %p buffer %p len %d",
667 Channel, Buffer, BufferLen);
669 DumpVmbusChannel(Channel);
671 /* ASSERT((packetLenAligned - packetLen) < sizeof(u64)); */
673 /* Setup the descriptor */
674 desc.Type = Type; /* VmbusPacketTypeDataInBand; */
675 desc.Flags = Flags; /* VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED; */
676 /* in 8-bytes granularity */
677 desc.DataOffset8 = sizeof(struct vmpacket_descriptor) >> 3;
678 desc.Length8 = (u16)(packetLenAligned >> 3);
679 desc.TransactionId = RequestId;
681 sg_init_table(bufferList, 3);
682 sg_set_buf(&bufferList[0], &desc, sizeof(struct vmpacket_descriptor));
683 sg_set_buf(&bufferList[1], Buffer, BufferLen);
684 sg_set_buf(&bufferList[2], &alignedData, packetLenAligned - packetLen);
686 ret = RingBufferWrite(&Channel->Outbound, bufferList, 3);
688 /* TODO: We should determine if this is optional */
689 if (ret == 0 && !GetRingBufferInterruptMask(&Channel->Outbound))
690 VmbusChannelSetEvent(Channel);
692 return ret;
694 EXPORT_SYMBOL(VmbusChannelSendPacket);
697 * VmbusChannelSendPacketPageBuffer - Send a range of single-page buffer
698 * packets using a GPADL Direct packet type.
700 int VmbusChannelSendPacketPageBuffer(struct vmbus_channel *Channel,
701 struct hv_page_buffer PageBuffers[],
702 u32 PageCount, void *Buffer, u32 BufferLen,
703 u64 RequestId)
705 int ret;
706 int i;
707 struct VMBUS_CHANNEL_PACKET_PAGE_BUFFER desc;
708 u32 descSize;
709 u32 packetLen;
710 u32 packetLenAligned;
711 struct scatterlist bufferList[3];
712 u64 alignedData = 0;
714 if (PageCount > MAX_PAGE_BUFFER_COUNT)
715 return -EINVAL;
717 DumpVmbusChannel(Channel);
720 * Adjust the size down since VMBUS_CHANNEL_PACKET_PAGE_BUFFER is the
721 * largest size we support
723 descSize = sizeof(struct VMBUS_CHANNEL_PACKET_PAGE_BUFFER) -
724 ((MAX_PAGE_BUFFER_COUNT - PageCount) *
725 sizeof(struct hv_page_buffer));
726 packetLen = descSize + BufferLen;
727 packetLenAligned = ALIGN_UP(packetLen, sizeof(u64));
729 /* ASSERT((packetLenAligned - packetLen) < sizeof(u64)); */
731 /* Setup the descriptor */
732 desc.Type = VmbusPacketTypeDataUsingGpaDirect;
733 desc.Flags = VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED;
734 desc.DataOffset8 = descSize >> 3; /* in 8-bytes grandularity */
735 desc.Length8 = (u16)(packetLenAligned >> 3);
736 desc.TransactionId = RequestId;
737 desc.RangeCount = PageCount;
739 for (i = 0; i < PageCount; i++) {
740 desc.Range[i].Length = PageBuffers[i].Length;
741 desc.Range[i].Offset = PageBuffers[i].Offset;
742 desc.Range[i].Pfn = PageBuffers[i].Pfn;
745 sg_init_table(bufferList, 3);
746 sg_set_buf(&bufferList[0], &desc, descSize);
747 sg_set_buf(&bufferList[1], Buffer, BufferLen);
748 sg_set_buf(&bufferList[2], &alignedData, packetLenAligned - packetLen);
750 ret = RingBufferWrite(&Channel->Outbound, bufferList, 3);
752 /* TODO: We should determine if this is optional */
753 if (ret == 0 && !GetRingBufferInterruptMask(&Channel->Outbound))
754 VmbusChannelSetEvent(Channel);
756 return ret;
760 * VmbusChannelSendPacketMultiPageBuffer - Send a multi-page buffer packet
761 * using a GPADL Direct packet type.
763 int VmbusChannelSendPacketMultiPageBuffer(struct vmbus_channel *Channel,
764 struct hv_multipage_buffer *MultiPageBuffer,
765 void *Buffer, u32 BufferLen, u64 RequestId)
767 int ret;
768 struct VMBUS_CHANNEL_PACKET_MULITPAGE_BUFFER desc;
769 u32 descSize;
770 u32 packetLen;
771 u32 packetLenAligned;
772 struct scatterlist bufferList[3];
773 u64 alignedData = 0;
774 u32 PfnCount = NUM_PAGES_SPANNED(MultiPageBuffer->Offset,
775 MultiPageBuffer->Length);
777 DumpVmbusChannel(Channel);
779 DPRINT_DBG(VMBUS, "data buffer - offset %u len %u pfn count %u",
780 MultiPageBuffer->Offset, MultiPageBuffer->Length, PfnCount);
782 if ((PfnCount < 0) || (PfnCount > MAX_MULTIPAGE_BUFFER_COUNT))
783 return -EINVAL;
786 * Adjust the size down since VMBUS_CHANNEL_PACKET_MULITPAGE_BUFFER is
787 * the largest size we support
789 descSize = sizeof(struct VMBUS_CHANNEL_PACKET_MULITPAGE_BUFFER) -
790 ((MAX_MULTIPAGE_BUFFER_COUNT - PfnCount) *
791 sizeof(u64));
792 packetLen = descSize + BufferLen;
793 packetLenAligned = ALIGN_UP(packetLen, sizeof(u64));
795 /* ASSERT((packetLenAligned - packetLen) < sizeof(u64)); */
797 /* Setup the descriptor */
798 desc.Type = VmbusPacketTypeDataUsingGpaDirect;
799 desc.Flags = VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED;
800 desc.DataOffset8 = descSize >> 3; /* in 8-bytes grandularity */
801 desc.Length8 = (u16)(packetLenAligned >> 3);
802 desc.TransactionId = RequestId;
803 desc.RangeCount = 1;
805 desc.Range.Length = MultiPageBuffer->Length;
806 desc.Range.Offset = MultiPageBuffer->Offset;
808 memcpy(desc.Range.PfnArray, MultiPageBuffer->PfnArray,
809 PfnCount * sizeof(u64));
811 sg_init_table(bufferList, 3);
812 sg_set_buf(&bufferList[0], &desc, descSize);
813 sg_set_buf(&bufferList[1], Buffer, BufferLen);
814 sg_set_buf(&bufferList[2], &alignedData, packetLenAligned - packetLen);
816 ret = RingBufferWrite(&Channel->Outbound, bufferList, 3);
818 /* TODO: We should determine if this is optional */
819 if (ret == 0 && !GetRingBufferInterruptMask(&Channel->Outbound))
820 VmbusChannelSetEvent(Channel);
822 return ret;
827 * VmbusChannelRecvPacket() - Retrieve the user packet on the specified channel
828 * @Channel: Pointer to vmbus_channel structure.
829 * @Buffer: Pointer to the buffer you want to receive the data into.
830 * @BufferLen: Maximum size of what the the buffer will hold
831 * @BufferActualLen: The actual size of the data after it was received
832 * @RequestId: Identifier of the request
834 * Receives directly from the hyper-v vmbus and puts the data it received
835 * into Buffer. This will receive the data unparsed from hyper-v.
837 * Mainly used by Hyper-V drivers.
839 int VmbusChannelRecvPacket(struct vmbus_channel *Channel, void *Buffer,
840 u32 BufferLen, u32 *BufferActualLen, u64 *RequestId)
842 struct vmpacket_descriptor desc;
843 u32 packetLen;
844 u32 userLen;
845 int ret;
846 unsigned long flags;
848 *BufferActualLen = 0;
849 *RequestId = 0;
851 spin_lock_irqsave(&Channel->inbound_lock, flags);
853 ret = RingBufferPeek(&Channel->Inbound, &desc,
854 sizeof(struct vmpacket_descriptor));
855 if (ret != 0) {
856 spin_unlock_irqrestore(&Channel->inbound_lock, flags);
858 /* DPRINT_DBG(VMBUS, "nothing to read!!"); */
859 return 0;
862 /* VmbusChannelClearEvent(Channel); */
864 packetLen = desc.Length8 << 3;
865 userLen = packetLen - (desc.DataOffset8 << 3);
866 /* ASSERT(userLen > 0); */
868 DPRINT_DBG(VMBUS, "packet received on channel %p relid %d <type %d "
869 "flag %d tid %llx pktlen %d datalen %d> ",
870 Channel, Channel->OfferMsg.ChildRelId, desc.Type,
871 desc.Flags, desc.TransactionId, packetLen, userLen);
873 *BufferActualLen = userLen;
875 if (userLen > BufferLen) {
876 spin_unlock_irqrestore(&Channel->inbound_lock, flags);
878 DPRINT_ERR(VMBUS, "buffer too small - got %d needs %d",
879 BufferLen, userLen);
880 return -1;
883 *RequestId = desc.TransactionId;
885 /* Copy over the packet to the user buffer */
886 ret = RingBufferRead(&Channel->Inbound, Buffer, userLen,
887 (desc.DataOffset8 << 3));
889 spin_unlock_irqrestore(&Channel->inbound_lock, flags);
891 return 0;
893 EXPORT_SYMBOL(VmbusChannelRecvPacket);
896 * VmbusChannelRecvPacketRaw - Retrieve the raw packet on the specified channel
898 int VmbusChannelRecvPacketRaw(struct vmbus_channel *Channel, void *Buffer,
899 u32 BufferLen, u32 *BufferActualLen,
900 u64 *RequestId)
902 struct vmpacket_descriptor desc;
903 u32 packetLen;
904 u32 userLen;
905 int ret;
906 unsigned long flags;
908 *BufferActualLen = 0;
909 *RequestId = 0;
911 spin_lock_irqsave(&Channel->inbound_lock, flags);
913 ret = RingBufferPeek(&Channel->Inbound, &desc,
914 sizeof(struct vmpacket_descriptor));
915 if (ret != 0) {
916 spin_unlock_irqrestore(&Channel->inbound_lock, flags);
918 /* DPRINT_DBG(VMBUS, "nothing to read!!"); */
919 return 0;
922 /* VmbusChannelClearEvent(Channel); */
924 packetLen = desc.Length8 << 3;
925 userLen = packetLen - (desc.DataOffset8 << 3);
927 DPRINT_DBG(VMBUS, "packet received on channel %p relid %d <type %d "
928 "flag %d tid %llx pktlen %d datalen %d> ",
929 Channel, Channel->OfferMsg.ChildRelId, desc.Type,
930 desc.Flags, desc.TransactionId, packetLen, userLen);
932 *BufferActualLen = packetLen;
934 if (packetLen > BufferLen) {
935 spin_unlock_irqrestore(&Channel->inbound_lock, flags);
937 DPRINT_ERR(VMBUS, "buffer too small - needed %d bytes but "
938 "got space for only %d bytes", packetLen, BufferLen);
939 return -2;
942 *RequestId = desc.TransactionId;
944 /* Copy over the entire packet to the user buffer */
945 ret = RingBufferRead(&Channel->Inbound, Buffer, packetLen, 0);
947 spin_unlock_irqrestore(&Channel->inbound_lock, flags);
948 return 0;
952 * VmbusChannelOnChannelEvent - Channel event callback
954 void VmbusChannelOnChannelEvent(struct vmbus_channel *Channel)
956 DumpVmbusChannel(Channel);
957 /* ASSERT(Channel->OnChannelCallback); */
959 Channel->OnChannelCallback(Channel->ChannelCallbackContext);
961 mod_timer(&Channel->poll_timer, jiffies + usecs_to_jiffies(100));
965 * VmbusChannelOnTimer - Timer event callback
967 void VmbusChannelOnTimer(unsigned long data)
969 struct vmbus_channel *channel = (struct vmbus_channel *)data;
971 if (channel->OnChannelCallback)
972 channel->OnChannelCallback(channel->ChannelCallbackContext);
976 * DumpVmbusChannel - Dump vmbus channel info to the console
978 static void DumpVmbusChannel(struct vmbus_channel *Channel)
980 DPRINT_DBG(VMBUS, "Channel (%d)", Channel->OfferMsg.ChildRelId);
981 DumpRingInfo(&Channel->Outbound, "Outbound ");
982 DumpRingInfo(&Channel->Inbound, "Inbound ");