blob: e2c833fb923f2221e6907bf78feb779046239763 [file] [log] [blame]
Hank Janssen3e7ee492009-07-13 16:02:34 -07001/*
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
Greg Kroah-Hartman5654e932009-07-14 15:08:20 -070024#include <linux/kernel.h>
Greg Kroah-Hartman09d50ff2009-07-13 17:09:34 -070025#include "include/osd.h"
26#include "include/logging.h"
Hank Janssen3e7ee492009-07-13 16:02:34 -070027
28#include "VmbusPrivate.h"
29
Bill Pemberton454f18a2009-07-27 16:47:24 -040030/* Internal routines */
Hank Janssen3e7ee492009-07-13 16:02:34 -070031static int
32VmbusChannelCreateGpadlHeader(
Bill Pemberton454f18a2009-07-27 16:47:24 -040033 void * Kbuffer, /* must be phys and virt contiguous */
34 u32 Size, /* page-size multiple */
Hank Janssen3e7ee492009-07-13 16:02:34 -070035 VMBUS_CHANNEL_MSGINFO **msgInfo,
Greg Kroah-Hartman4d643112009-07-14 15:09:36 -070036 u32 *MessageCount
Hank Janssen3e7ee492009-07-13 16:02:34 -070037 );
38
39static void
40DumpVmbusChannel(
41 VMBUS_CHANNEL *Channel
42 );
43
44
45static void
46VmbusChannelSetEvent(
47 VMBUS_CHANNEL *Channel
48 );
49
50
51#if 0
52static void
53DumpMonitorPage(
54 HV_MONITOR_PAGE *MonitorPage
55 )
56{
57 int i=0;
58 int j=0;
59
60 DPRINT_DBG(VMBUS, "monitorPage - %p, trigger state - %d", MonitorPage, MonitorPage->TriggerState);
61
62 for (i=0; i<4; i++)
63 {
64 DPRINT_DBG(VMBUS, "trigger group (%d) - %llx", i, MonitorPage->TriggerGroup[i].AsUINT64);
65 }
66
67 for (i=0; i<4; i++)
68 {
69 for (j=0; j<32; j++)
70 {
71 DPRINT_DBG(VMBUS, "latency (%d)(%d) - %llx", i, j, MonitorPage->Latency[i][j]);
72 }
73 }
74 for (i=0; i<4; i++)
75 {
76 for (j=0; j<32; j++)
77 {
Greg Kroah-Hartman4d643112009-07-14 15:09:36 -070078 DPRINT_DBG(VMBUS, "param-conn id (%d)(%d) - %d", i, j, MonitorPage->Parameter[i][j].ConnectionId.Asu32);
Hank Janssen3e7ee492009-07-13 16:02:34 -070079 DPRINT_DBG(VMBUS, "param-flag (%d)(%d) - %d", i, j, MonitorPage->Parameter[i][j].FlagNumber);
80
81 }
82 }
83}
84#endif
85
86/*++
87
88Name:
89 VmbusChannelSetEvent()
90
91Description:
92 Trigger an event notification on the specified channel.
93
94--*/
95static void
96VmbusChannelSetEvent(
97 VMBUS_CHANNEL *Channel
98 )
99{
100 HV_MONITOR_PAGE *monitorPage;
101
102 DPRINT_ENTER(VMBUS);
103
104 if (Channel->OfferMsg.MonitorAllocated)
105 {
Bill Pemberton454f18a2009-07-27 16:47:24 -0400106 /* Each u32 represents 32 channels */
Greg Kroah-Hartman4d643112009-07-14 15:09:36 -0700107 BitSet((u32*)gVmbusConnection.SendInterruptPage + (Channel->OfferMsg.ChildRelId >> 5), Channel->OfferMsg.ChildRelId & 31);
Hank Janssen3e7ee492009-07-13 16:02:34 -0700108
109 monitorPage = (HV_MONITOR_PAGE*)gVmbusConnection.MonitorPages;
Bill Pemberton454f18a2009-07-27 16:47:24 -0400110 monitorPage++; /* Get the child to parent monitor page */
Hank Janssen3e7ee492009-07-13 16:02:34 -0700111
Greg Kroah-Hartman4d643112009-07-14 15:09:36 -0700112 BitSet((u32*) &monitorPage->TriggerGroup[Channel->MonitorGroup].Pending, Channel->MonitorBit);
Hank Janssen3e7ee492009-07-13 16:02:34 -0700113 }
114 else
115 {
116 VmbusSetEvent(Channel->OfferMsg.ChildRelId);
117 }
118
119 DPRINT_EXIT(VMBUS);
120}
121
122#if 0
123static void
124VmbusChannelClearEvent(
125 VMBUS_CHANNEL *Channel
126 )
127{
128 HV_MONITOR_PAGE *monitorPage;
129
130 DPRINT_ENTER(VMBUS);
131
132 if (Channel->OfferMsg.MonitorAllocated)
133 {
Bill Pemberton454f18a2009-07-27 16:47:24 -0400134 /* Each u32 represents 32 channels */
Greg Kroah-Hartman4d643112009-07-14 15:09:36 -0700135 BitClear((u32*)gVmbusConnection.SendInterruptPage + (Channel->OfferMsg.ChildRelId >> 5), Channel->OfferMsg.ChildRelId & 31);
Hank Janssen3e7ee492009-07-13 16:02:34 -0700136
137 monitorPage = (HV_MONITOR_PAGE*)gVmbusConnection.MonitorPages;
Bill Pemberton454f18a2009-07-27 16:47:24 -0400138 monitorPage++; /* Get the child to parent monitor page */
Hank Janssen3e7ee492009-07-13 16:02:34 -0700139
Greg Kroah-Hartman4d643112009-07-14 15:09:36 -0700140 BitClear((u32*) &monitorPage->TriggerGroup[Channel->MonitorGroup].Pending, Channel->MonitorBit);
Hank Janssen3e7ee492009-07-13 16:02:34 -0700141 }
142
143 DPRINT_EXIT(VMBUS);
144}
145
146#endif
147/*++;
148
149Name:
150 VmbusChannelGetDebugInfo()
151
152Description:
153 Retrieve various channel debug info
154
155--*/
156void
157VmbusChannelGetDebugInfo(
158 VMBUS_CHANNEL *Channel,
159 VMBUS_CHANNEL_DEBUG_INFO *DebugInfo
160 )
161{
162 HV_MONITOR_PAGE *monitorPage;
Greg Kroah-Hartman5654e932009-07-14 15:08:20 -0700163 u8 monitorGroup = (u8)Channel->OfferMsg.MonitorId / 32;
164 u8 monitorOffset = (u8)Channel->OfferMsg.MonitorId % 32;
Bill Pemberton454f18a2009-07-27 16:47:24 -0400165 /* u32 monitorBit = 1 << monitorOffset; */
Hank Janssen3e7ee492009-07-13 16:02:34 -0700166
167 DebugInfo->RelId = Channel->OfferMsg.ChildRelId;
168 DebugInfo->State = Channel->State;
169 memcpy(&DebugInfo->InterfaceType, &Channel->OfferMsg.Offer.InterfaceType, sizeof(GUID));
170 memcpy(&DebugInfo->InterfaceInstance, &Channel->OfferMsg.Offer.InterfaceInstance, sizeof(GUID));
171
172 monitorPage = (HV_MONITOR_PAGE*)gVmbusConnection.MonitorPages;
173
174 DebugInfo->MonitorId = Channel->OfferMsg.MonitorId;
175
176 DebugInfo->ServerMonitorPending = monitorPage->TriggerGroup[monitorGroup].Pending;
177 DebugInfo->ServerMonitorLatency = monitorPage->Latency[monitorGroup][ monitorOffset];
178 DebugInfo->ServerMonitorConnectionId = monitorPage->Parameter[monitorGroup][ monitorOffset].ConnectionId.u.Id;
179
180 monitorPage++;
181
182 DebugInfo->ClientMonitorPending = monitorPage->TriggerGroup[monitorGroup].Pending;
183 DebugInfo->ClientMonitorLatency = monitorPage->Latency[monitorGroup][ monitorOffset];
184 DebugInfo->ClientMonitorConnectionId = monitorPage->Parameter[monitorGroup][ monitorOffset].ConnectionId.u.Id;
185
186 RingBufferGetDebugInfo(&Channel->Inbound, &DebugInfo->Inbound);
187 RingBufferGetDebugInfo(&Channel->Outbound, &DebugInfo->Outbound);
188}
189
190
191/*++;
192
193Name:
194 VmbusChannelOpen()
195
196Description:
197 Open the specified channel.
198
199--*/
200int
201VmbusChannelOpen(
202 VMBUS_CHANNEL *NewChannel,
Greg Kroah-Hartman4d643112009-07-14 15:09:36 -0700203 u32 SendRingBufferSize,
204 u32 RecvRingBufferSize,
Greg Kroah-Hartman8282c402009-07-14 15:06:28 -0700205 void * UserData,
Greg Kroah-Hartman4d643112009-07-14 15:09:36 -0700206 u32 UserDataLen,
Hank Janssen3e7ee492009-07-13 16:02:34 -0700207 PFN_CHANNEL_CALLBACK pfnOnChannelCallback,
Greg Kroah-Hartman8282c402009-07-14 15:06:28 -0700208 void * Context
Hank Janssen3e7ee492009-07-13 16:02:34 -0700209 )
210{
211 int ret=0;
212 VMBUS_CHANNEL_OPEN_CHANNEL* openMsg;
213 VMBUS_CHANNEL_MSGINFO* openInfo;
214 void *in, *out;
Greg Kroah-Hartmandd0813b2009-07-15 14:56:45 -0700215 unsigned long flags;
Hank Janssen3e7ee492009-07-13 16:02:34 -0700216
217 DPRINT_ENTER(VMBUS);
218
Bill Pemberton454f18a2009-07-27 16:47:24 -0400219 /* Aligned to page size */
Hank Janssen3e7ee492009-07-13 16:02:34 -0700220 ASSERT(!(SendRingBufferSize & (PAGE_SIZE -1)));
221 ASSERT(!(RecvRingBufferSize & (PAGE_SIZE -1)));
222
223 NewChannel->OnChannelCallback = pfnOnChannelCallback;
224 NewChannel->ChannelCallbackContext = Context;
225
Bill Pemberton454f18a2009-07-27 16:47:24 -0400226 /* Allocate the ring buffer */
Hank Janssen3e7ee492009-07-13 16:02:34 -0700227 out = PageAlloc((SendRingBufferSize + RecvRingBufferSize) >> PAGE_SHIFT);
Bill Pemberton454f18a2009-07-27 16:47:24 -0400228 /* out = kzalloc(sendRingBufferSize + recvRingBufferSize, GFP_KERNEL); */
Hank Janssen3e7ee492009-07-13 16:02:34 -0700229 ASSERT(out);
Greg Kroah-Hartmanc4b0bc92009-07-14 15:12:46 -0700230 ASSERT(((unsigned long)out & (PAGE_SIZE-1)) == 0);
Hank Janssen3e7ee492009-07-13 16:02:34 -0700231
Greg Kroah-Hartmanc4b0bc92009-07-14 15:12:46 -0700232 in = (void*)((unsigned long)out + SendRingBufferSize);
Hank Janssen3e7ee492009-07-13 16:02:34 -0700233
234 NewChannel->RingBufferPages = out;
235 NewChannel->RingBufferPageCount = (SendRingBufferSize + RecvRingBufferSize) >> PAGE_SHIFT;
236
237 RingBufferInit(&NewChannel->Outbound, out, SendRingBufferSize);
238
239 RingBufferInit(&NewChannel->Inbound, in, RecvRingBufferSize);
240
Bill Pemberton454f18a2009-07-27 16:47:24 -0400241 /* Establish the gpadl for the ring buffer */
Hank Janssen3e7ee492009-07-13 16:02:34 -0700242 DPRINT_DBG(VMBUS, "Establishing ring buffer's gpadl for channel %p...", NewChannel);
243
244 NewChannel->RingBufferGpadlHandle = 0;
245
246 ret = VmbusChannelEstablishGpadl(NewChannel,
247 NewChannel->Outbound.RingBuffer,
248 SendRingBufferSize + RecvRingBufferSize,
249 &NewChannel->RingBufferGpadlHandle);
250
251 DPRINT_DBG(VMBUS, "channel %p <relid %d gpadl 0x%x send ring %p size %d recv ring %p size %d, downstreamoffset %d>",
252 NewChannel,
253 NewChannel->OfferMsg.ChildRelId,
254 NewChannel->RingBufferGpadlHandle,
255 NewChannel->Outbound.RingBuffer,
256 NewChannel->Outbound.RingSize,
257 NewChannel->Inbound.RingBuffer,
258 NewChannel->Inbound.RingSize,
259 SendRingBufferSize);
260
Bill Pemberton454f18a2009-07-27 16:47:24 -0400261 /* Create and init the channel open message */
Greg Kroah-Hartmane40d37c2009-07-15 12:47:22 -0700262 openInfo = kmalloc(sizeof(VMBUS_CHANNEL_MSGINFO) + sizeof(VMBUS_CHANNEL_OPEN_CHANNEL), GFP_KERNEL);
Hank Janssen3e7ee492009-07-13 16:02:34 -0700263 ASSERT(openInfo != NULL);
264
265 openInfo->WaitEvent = WaitEventCreate();
266
267 openMsg = (VMBUS_CHANNEL_OPEN_CHANNEL*)openInfo->Msg;
268 openMsg->Header.MessageType = ChannelMessageOpenChannel;
Bill Pemberton454f18a2009-07-27 16:47:24 -0400269 openMsg->OpenId = NewChannel->OfferMsg.ChildRelId; /* FIXME */
Hank Janssen3e7ee492009-07-13 16:02:34 -0700270 openMsg->ChildRelId = NewChannel->OfferMsg.ChildRelId;
271 openMsg->RingBufferGpadlHandle = NewChannel->RingBufferGpadlHandle;
272 ASSERT(openMsg->RingBufferGpadlHandle);
273 openMsg->DownstreamRingBufferPageOffset = SendRingBufferSize >> PAGE_SHIFT;
Bill Pemberton454f18a2009-07-27 16:47:24 -0400274 openMsg->ServerContextAreaGpadlHandle = 0; /* TODO */
Hank Janssen3e7ee492009-07-13 16:02:34 -0700275
276 ASSERT(UserDataLen <= MAX_USER_DEFINED_BYTES);
277 if (UserDataLen)
278 {
279 memcpy(openMsg->UserData, UserData, UserDataLen);
280 }
281
Greg Kroah-Hartmandd0813b2009-07-15 14:56:45 -0700282 spin_lock_irqsave(&gVmbusConnection.channelmsg_lock, flags);
Hank Janssen3e7ee492009-07-13 16:02:34 -0700283 INSERT_TAIL_LIST(&gVmbusConnection.ChannelMsgList, &openInfo->MsgListEntry);
Greg Kroah-Hartmandd0813b2009-07-15 14:56:45 -0700284 spin_unlock_irqrestore(&gVmbusConnection.channelmsg_lock, flags);
Hank Janssen3e7ee492009-07-13 16:02:34 -0700285
286 DPRINT_DBG(VMBUS, "Sending channel open msg...");
287
288 ret = VmbusPostMessage(openMsg, sizeof(VMBUS_CHANNEL_OPEN_CHANNEL));
289 if (ret != 0)
290 {
291 DPRINT_ERR(VMBUS, "unable to open channel - %d", ret);
292 goto Cleanup;
293 }
294
Bill Pemberton454f18a2009-07-27 16:47:24 -0400295 /* FIXME: Need to time-out here */
Hank Janssen3e7ee492009-07-13 16:02:34 -0700296 WaitEventWait(openInfo->WaitEvent);
297
298 if (openInfo->Response.OpenResult.Status == 0)
299 {
300 DPRINT_INFO(VMBUS, "channel <%p> open success!!", NewChannel);
301 }
302 else
303 {
304 DPRINT_INFO(VMBUS, "channel <%p> open failed - %d!!", NewChannel, openInfo->Response.OpenResult.Status);
305 }
306
307Cleanup:
Greg Kroah-Hartmandd0813b2009-07-15 14:56:45 -0700308 spin_lock_irqsave(&gVmbusConnection.channelmsg_lock, flags);
Hank Janssen3e7ee492009-07-13 16:02:34 -0700309 REMOVE_ENTRY_LIST(&openInfo->MsgListEntry);
Greg Kroah-Hartmandd0813b2009-07-15 14:56:45 -0700310 spin_unlock_irqrestore(&gVmbusConnection.channelmsg_lock, flags);
Hank Janssen3e7ee492009-07-13 16:02:34 -0700311
312 WaitEventClose(openInfo->WaitEvent);
Greg Kroah-Hartman8c69f522009-07-15 12:48:29 -0700313 kfree(openInfo);
Hank Janssen3e7ee492009-07-13 16:02:34 -0700314
315 DPRINT_EXIT(VMBUS);
316
317 return 0;
318}
319
320/*++;
321
322Name:
323 DumpGpadlBody()
324
325Description:
326 Dump the gpadl body message to the console for debugging purposes.
327
328--*/
329static void DumpGpadlBody(
330 VMBUS_CHANNEL_GPADL_BODY *Gpadl,
Greg Kroah-Hartman4d643112009-07-14 15:09:36 -0700331 u32 Len)
Hank Janssen3e7ee492009-07-13 16:02:34 -0700332{
333 int i=0;
334 int pfnCount=0;
335
Greg Kroah-Hartman59471432009-07-14 15:10:26 -0700336 pfnCount = (Len - sizeof(VMBUS_CHANNEL_GPADL_BODY))/ sizeof(u64);
Hank Janssen3e7ee492009-07-13 16:02:34 -0700337 DPRINT_DBG(VMBUS, "gpadl body - len %d pfn count %d", Len, pfnCount);
338
339 for (i=0; i< pfnCount; i++)
340 {
341 DPRINT_DBG(VMBUS, "gpadl body - %d) pfn %llu", i, Gpadl->Pfn[i]);
342 }
343}
344
345
346/*++;
347
348Name:
349 DumpGpadlHeader()
350
351Description:
352 Dump the gpadl header message to the console for debugging purposes.
353
354--*/
355static void DumpGpadlHeader(
356 VMBUS_CHANNEL_GPADL_HEADER *Gpadl
357 )
358{
359 int i=0,j=0;
360 int pageCount=0;
361
362
363 DPRINT_DBG(VMBUS, "gpadl header - relid %d, range count %d, range buflen %d",
364 Gpadl->ChildRelId,
365 Gpadl->RangeCount,
366 Gpadl->RangeBufLen);
367 for (i=0; i< Gpadl->RangeCount; i++)
368 {
369 pageCount = Gpadl->Range[i].ByteCount >> PAGE_SHIFT;
370 pageCount = (pageCount > 26)? 26 : pageCount;
371
372 DPRINT_DBG(VMBUS, "gpadl range %d - len %d offset %d page count %d",
373 i, Gpadl->Range[i].ByteCount, Gpadl->Range[i].ByteOffset, pageCount);
374
375 for (j=0; j< pageCount; j++)
376 {
377 DPRINT_DBG(VMBUS, "%d) pfn %llu", j, Gpadl->Range[i].PfnArray[j]);
378 }
379 }
380}
381
382/*++;
383
384Name:
385 VmbusChannelCreateGpadlHeader()
386
387Description:
388 Creates a gpadl for the specified buffer
389
390--*/
391static int
392VmbusChannelCreateGpadlHeader(
Bill Pemberton454f18a2009-07-27 16:47:24 -0400393 void * Kbuffer, /* from kmalloc() */
394 u32 Size, /* page-size multiple */
Hank Janssen3e7ee492009-07-13 16:02:34 -0700395 VMBUS_CHANNEL_MSGINFO **MsgInfo,
Greg Kroah-Hartman4d643112009-07-14 15:09:36 -0700396 u32 *MessageCount)
Hank Janssen3e7ee492009-07-13 16:02:34 -0700397{
398 int i;
399 int pageCount;
400 unsigned long long pfn;
401 VMBUS_CHANNEL_GPADL_HEADER* gpaHeader;
402 VMBUS_CHANNEL_GPADL_BODY* gpadlBody;
403 VMBUS_CHANNEL_MSGINFO* msgHeader;
404 VMBUS_CHANNEL_MSGINFO* msgBody;
Greg Kroah-Hartman4d643112009-07-14 15:09:36 -0700405 u32 msgSize;
Hank Janssen3e7ee492009-07-13 16:02:34 -0700406
407 int pfnSum, pfnCount, pfnLeft, pfnCurr, pfnSize;
408
Bill Pemberton454f18a2009-07-27 16:47:24 -0400409 /* ASSERT( (kbuffer & (PAGE_SIZE-1)) == 0); */
Hank Janssen3e7ee492009-07-13 16:02:34 -0700410 ASSERT( (Size & (PAGE_SIZE-1)) == 0);
411
412 pageCount = Size >> PAGE_SHIFT;
413 pfn = GetPhysicalAddress(Kbuffer) >> PAGE_SHIFT;
414
Bill Pemberton454f18a2009-07-27 16:47:24 -0400415 /* do we need a gpadl body msg */
Hank Janssen3e7ee492009-07-13 16:02:34 -0700416 pfnSize = MAX_SIZE_CHANNEL_MESSAGE - sizeof(VMBUS_CHANNEL_GPADL_HEADER) - sizeof(GPA_RANGE);
Greg Kroah-Hartman59471432009-07-14 15:10:26 -0700417 pfnCount = pfnSize / sizeof(u64);
Hank Janssen3e7ee492009-07-13 16:02:34 -0700418
Bill Pemberton454f18a2009-07-27 16:47:24 -0400419 if (pageCount > pfnCount) /* we need a gpadl body */
Hank Janssen3e7ee492009-07-13 16:02:34 -0700420 {
Bill Pemberton454f18a2009-07-27 16:47:24 -0400421 /* fill in the header */
Greg Kroah-Hartman59471432009-07-14 15:10:26 -0700422 msgSize = sizeof(VMBUS_CHANNEL_MSGINFO) + sizeof(VMBUS_CHANNEL_GPADL_HEADER) + sizeof(GPA_RANGE) + pfnCount*sizeof(u64);
Greg Kroah-Hartmane276a3a2009-07-15 12:47:43 -0700423 msgHeader = kzalloc(msgSize, GFP_KERNEL);
Hank Janssen3e7ee492009-07-13 16:02:34 -0700424
425 INITIALIZE_LIST_HEAD(&msgHeader->SubMsgList);
426 msgHeader->MessageSize=msgSize;
427
428 gpaHeader = (VMBUS_CHANNEL_GPADL_HEADER*)msgHeader->Msg;
429 gpaHeader->RangeCount = 1;
Greg Kroah-Hartman59471432009-07-14 15:10:26 -0700430 gpaHeader->RangeBufLen = sizeof(GPA_RANGE) + pageCount*sizeof(u64);
Hank Janssen3e7ee492009-07-13 16:02:34 -0700431 gpaHeader->Range[0].ByteOffset = 0;
432 gpaHeader->Range[0].ByteCount = Size;
433 for (i=0; i<pfnCount; i++)
434 {
435 gpaHeader->Range[0].PfnArray[i] = pfn+i;
436 }
437 *MsgInfo = msgHeader;
438 *MessageCount = 1;
439
440 pfnSum = pfnCount;
441 pfnLeft = pageCount - pfnCount;
442
Bill Pemberton454f18a2009-07-27 16:47:24 -0400443 /* how many pfns can we fit */
Hank Janssen3e7ee492009-07-13 16:02:34 -0700444 pfnSize = MAX_SIZE_CHANNEL_MESSAGE - sizeof(VMBUS_CHANNEL_GPADL_BODY);
Greg Kroah-Hartman59471432009-07-14 15:10:26 -0700445 pfnCount = pfnSize / sizeof(u64);
Hank Janssen3e7ee492009-07-13 16:02:34 -0700446
Bill Pemberton454f18a2009-07-27 16:47:24 -0400447 /* fill in the body */
Hank Janssen3e7ee492009-07-13 16:02:34 -0700448 while (pfnLeft)
449 {
450 if (pfnLeft > pfnCount)
451 {
452 pfnCurr = pfnCount;
453 }
454 else
455 {
456 pfnCurr = pfnLeft;
457 }
458
Greg Kroah-Hartman59471432009-07-14 15:10:26 -0700459 msgSize = sizeof(VMBUS_CHANNEL_MSGINFO) + sizeof(VMBUS_CHANNEL_GPADL_BODY) + pfnCurr*sizeof(u64);
Greg Kroah-Hartmane276a3a2009-07-15 12:47:43 -0700460 msgBody = kzalloc(msgSize, GFP_KERNEL);
Hank Janssen3e7ee492009-07-13 16:02:34 -0700461 ASSERT(msgBody);
462 msgBody->MessageSize = msgSize;
463 (*MessageCount)++;
464 gpadlBody = (VMBUS_CHANNEL_GPADL_BODY*)msgBody->Msg;
465
Bill Pemberton454f18a2009-07-27 16:47:24 -0400466 /* FIXME: Gpadl is u32 and we are using a pointer which could be 64-bit */
467 /* gpadlBody->Gpadl = kbuffer; */
Hank Janssen3e7ee492009-07-13 16:02:34 -0700468 for (i=0; i<pfnCurr; i++)
469 {
470 gpadlBody->Pfn[i] = pfn + pfnSum + i;
471 }
472
Bill Pemberton454f18a2009-07-27 16:47:24 -0400473 /* add to msg header */
Hank Janssen3e7ee492009-07-13 16:02:34 -0700474 INSERT_TAIL_LIST(&msgHeader->SubMsgList, &msgBody->MsgListEntry);
475 pfnSum += pfnCurr;
476 pfnLeft -= pfnCurr;
477 }
478 }
479 else
480 {
Bill Pemberton454f18a2009-07-27 16:47:24 -0400481 /* everything fits in a header */
Greg Kroah-Hartman59471432009-07-14 15:10:26 -0700482 msgSize = sizeof(VMBUS_CHANNEL_MSGINFO) + sizeof(VMBUS_CHANNEL_GPADL_HEADER) + sizeof(GPA_RANGE) + pageCount*sizeof(u64);
Greg Kroah-Hartmane276a3a2009-07-15 12:47:43 -0700483 msgHeader = kzalloc(msgSize, GFP_KERNEL);
Hank Janssen3e7ee492009-07-13 16:02:34 -0700484 msgHeader->MessageSize=msgSize;
485
486 gpaHeader = (VMBUS_CHANNEL_GPADL_HEADER*)msgHeader->Msg;
487 gpaHeader->RangeCount = 1;
Greg Kroah-Hartman59471432009-07-14 15:10:26 -0700488 gpaHeader->RangeBufLen = sizeof(GPA_RANGE) + pageCount*sizeof(u64);
Hank Janssen3e7ee492009-07-13 16:02:34 -0700489 gpaHeader->Range[0].ByteOffset = 0;
490 gpaHeader->Range[0].ByteCount = Size;
491 for (i=0; i<pageCount; i++)
492 {
493 gpaHeader->Range[0].PfnArray[i] = pfn+i;
494 }
495
496 *MsgInfo = msgHeader;
497 *MessageCount = 1;
498 }
499
500 return 0;
501}
502
503
504/*++;
505
506Name:
507 VmbusChannelEstablishGpadl()
508
509Description:
510 Estabish a GPADL for the specified buffer
511
512--*/
513int
514VmbusChannelEstablishGpadl(
515 VMBUS_CHANNEL *Channel,
Bill Pemberton454f18a2009-07-27 16:47:24 -0400516 void * Kbuffer, /* from kmalloc() */
517 u32 Size, /* page-size multiple */
Greg Kroah-Hartman4d643112009-07-14 15:09:36 -0700518 u32 *GpadlHandle
Hank Janssen3e7ee492009-07-13 16:02:34 -0700519 )
520{
521 int ret=0;
522 VMBUS_CHANNEL_GPADL_HEADER* gpadlMsg;
523 VMBUS_CHANNEL_GPADL_BODY* gpadlBody;
Bill Pemberton454f18a2009-07-27 16:47:24 -0400524 /* VMBUS_CHANNEL_GPADL_CREATED* gpadlCreated; */
Hank Janssen3e7ee492009-07-13 16:02:34 -0700525
526 VMBUS_CHANNEL_MSGINFO *msgInfo;
527 VMBUS_CHANNEL_MSGINFO *subMsgInfo;
528
Greg Kroah-Hartman4d643112009-07-14 15:09:36 -0700529 u32 msgCount;
Hank Janssen3e7ee492009-07-13 16:02:34 -0700530 LIST_ENTRY* anchor;
531 LIST_ENTRY* curr;
Greg Kroah-Hartman4d643112009-07-14 15:09:36 -0700532 u32 nextGpadlHandle;
Greg Kroah-Hartmandd0813b2009-07-15 14:56:45 -0700533 unsigned long flags;
Hank Janssen3e7ee492009-07-13 16:02:34 -0700534
535 DPRINT_ENTER(VMBUS);
536
537 nextGpadlHandle = gVmbusConnection.NextGpadlHandle;
538 InterlockedIncrement((int*)&gVmbusConnection.NextGpadlHandle);
539
540 VmbusChannelCreateGpadlHeader(Kbuffer, Size, &msgInfo, &msgCount);
541 ASSERT(msgInfo != NULL);
542 ASSERT(msgCount >0);
543
544 msgInfo->WaitEvent = WaitEventCreate();
545 gpadlMsg = (VMBUS_CHANNEL_GPADL_HEADER*)msgInfo->Msg;
546 gpadlMsg->Header.MessageType = ChannelMessageGpadlHeader;
547 gpadlMsg->ChildRelId = Channel->OfferMsg.ChildRelId;
548 gpadlMsg->Gpadl = nextGpadlHandle;
549
550 DumpGpadlHeader(gpadlMsg);
551
Greg Kroah-Hartmandd0813b2009-07-15 14:56:45 -0700552 spin_lock_irqsave(&gVmbusConnection.channelmsg_lock, flags);
Hank Janssen3e7ee492009-07-13 16:02:34 -0700553 INSERT_TAIL_LIST(&gVmbusConnection.ChannelMsgList, &msgInfo->MsgListEntry);
Greg Kroah-Hartmandd0813b2009-07-15 14:56:45 -0700554 spin_unlock_irqrestore(&gVmbusConnection.channelmsg_lock, flags);
Hank Janssen3e7ee492009-07-13 16:02:34 -0700555
556 DPRINT_DBG(VMBUS, "buffer %p, size %d msg cnt %d", Kbuffer, Size, msgCount);
557
Bill Pemberton226408a2009-07-27 16:47:23 -0400558 DPRINT_DBG(VMBUS, "Sending GPADL Header - len %ld", msgInfo->MessageSize - sizeof(VMBUS_CHANNEL_MSGINFO));
Hank Janssen3e7ee492009-07-13 16:02:34 -0700559
560 ret = VmbusPostMessage(gpadlMsg, msgInfo->MessageSize - sizeof(VMBUS_CHANNEL_MSGINFO));
561 if (ret != 0)
562 {
563 DPRINT_ERR(VMBUS, "Unable to open channel - %d", ret);
564 goto Cleanup;
565 }
566
567 if (msgCount>1)
568 {
569 ITERATE_LIST_ENTRIES(anchor, curr, &msgInfo->SubMsgList)
570 {
571 subMsgInfo = (VMBUS_CHANNEL_MSGINFO*) curr;
572 gpadlBody = (VMBUS_CHANNEL_GPADL_BODY*)subMsgInfo->Msg;
573
574 gpadlBody->Header.MessageType = ChannelMessageGpadlBody;
575 gpadlBody->Gpadl = nextGpadlHandle;
576
Bill Pemberton226408a2009-07-27 16:47:23 -0400577 DPRINT_DBG(VMBUS, "Sending GPADL Body - len %ld", subMsgInfo->MessageSize - sizeof(VMBUS_CHANNEL_MSGINFO));
Hank Janssen3e7ee492009-07-13 16:02:34 -0700578
579 DumpGpadlBody(gpadlBody, subMsgInfo->MessageSize - sizeof(VMBUS_CHANNEL_MSGINFO));
580 ret = VmbusPostMessage(gpadlBody, subMsgInfo->MessageSize - sizeof(VMBUS_CHANNEL_MSGINFO));
581 ASSERT(ret == 0);
582 }
583 }
584 WaitEventWait(msgInfo->WaitEvent);
585
Bill Pemberton454f18a2009-07-27 16:47:24 -0400586 /* At this point, we received the gpadl created msg */
Hank Janssen3e7ee492009-07-13 16:02:34 -0700587 DPRINT_DBG(VMBUS, "Received GPADL created (relid %d, status %d handle %x)",
588 Channel->OfferMsg.ChildRelId,
589 msgInfo->Response.GpadlCreated.CreationStatus,
590 gpadlMsg->Gpadl);
591
592 *GpadlHandle = gpadlMsg->Gpadl;
593
594Cleanup:
Greg Kroah-Hartmandd0813b2009-07-15 14:56:45 -0700595 spin_lock_irqsave(&gVmbusConnection.channelmsg_lock, flags);
Hank Janssen3e7ee492009-07-13 16:02:34 -0700596 REMOVE_ENTRY_LIST(&msgInfo->MsgListEntry);
Greg Kroah-Hartmandd0813b2009-07-15 14:56:45 -0700597 spin_unlock_irqrestore(&gVmbusConnection.channelmsg_lock, flags);
Hank Janssen3e7ee492009-07-13 16:02:34 -0700598
599 WaitEventClose(msgInfo->WaitEvent);
Greg Kroah-Hartman8c69f522009-07-15 12:48:29 -0700600 kfree(msgInfo);
Hank Janssen3e7ee492009-07-13 16:02:34 -0700601
602 DPRINT_EXIT(VMBUS);
603
604 return ret;
605}
606
607
608
609/*++;
610
611Name:
612 VmbusChannelTeardownGpadl()
613
614Description:
615 Teardown the specified GPADL handle
616
617--*/
618int
619VmbusChannelTeardownGpadl(
620 VMBUS_CHANNEL *Channel,
Greg Kroah-Hartman4d643112009-07-14 15:09:36 -0700621 u32 GpadlHandle
Hank Janssen3e7ee492009-07-13 16:02:34 -0700622 )
623{
624 int ret=0;
625 VMBUS_CHANNEL_GPADL_TEARDOWN *msg;
626 VMBUS_CHANNEL_MSGINFO* info;
Greg Kroah-Hartmandd0813b2009-07-15 14:56:45 -0700627 unsigned long flags;
Hank Janssen3e7ee492009-07-13 16:02:34 -0700628
629 DPRINT_ENTER(VMBUS);
630
631 ASSERT(GpadlHandle != 0);
632
Greg Kroah-Hartmane40d37c2009-07-15 12:47:22 -0700633 info = kmalloc(sizeof(VMBUS_CHANNEL_MSGINFO) + sizeof(VMBUS_CHANNEL_GPADL_TEARDOWN), GFP_KERNEL);
Hank Janssen3e7ee492009-07-13 16:02:34 -0700634 ASSERT(info != NULL);
635
636 info->WaitEvent = WaitEventCreate();
637
638 msg = (VMBUS_CHANNEL_GPADL_TEARDOWN*)info->Msg;
639
640 msg->Header.MessageType = ChannelMessageGpadlTeardown;
641 msg->ChildRelId = Channel->OfferMsg.ChildRelId;
642 msg->Gpadl = GpadlHandle;
643
Greg Kroah-Hartmandd0813b2009-07-15 14:56:45 -0700644 spin_lock_irqsave(&gVmbusConnection.channelmsg_lock, flags);
Hank Janssen3e7ee492009-07-13 16:02:34 -0700645 INSERT_TAIL_LIST(&gVmbusConnection.ChannelMsgList, &info->MsgListEntry);
Greg Kroah-Hartmandd0813b2009-07-15 14:56:45 -0700646 spin_unlock_irqrestore(&gVmbusConnection.channelmsg_lock, flags);
Hank Janssen3e7ee492009-07-13 16:02:34 -0700647
648 ret = VmbusPostMessage(msg, sizeof(VMBUS_CHANNEL_GPADL_TEARDOWN));
649 if (ret != 0)
650 {
Bill Pemberton454f18a2009-07-27 16:47:24 -0400651 /* TODO: */
Hank Janssen3e7ee492009-07-13 16:02:34 -0700652 }
653
654 WaitEventWait(info->WaitEvent);
655
Bill Pemberton454f18a2009-07-27 16:47:24 -0400656 /* Received a torndown response */
Greg Kroah-Hartmandd0813b2009-07-15 14:56:45 -0700657 spin_lock_irqsave(&gVmbusConnection.channelmsg_lock, flags);
Hank Janssen3e7ee492009-07-13 16:02:34 -0700658 REMOVE_ENTRY_LIST(&info->MsgListEntry);
Greg Kroah-Hartmandd0813b2009-07-15 14:56:45 -0700659 spin_unlock_irqrestore(&gVmbusConnection.channelmsg_lock, flags);
Hank Janssen3e7ee492009-07-13 16:02:34 -0700660
661 WaitEventClose(info->WaitEvent);
Greg Kroah-Hartman8c69f522009-07-15 12:48:29 -0700662 kfree(info);
Hank Janssen3e7ee492009-07-13 16:02:34 -0700663
664 DPRINT_EXIT(VMBUS);
665
666 return ret;
667}
668
669
670/*++
671
672Name:
673 VmbusChannelClose()
674
675Description:
676 Close the specified channel
677
678--*/
Greg Kroah-Hartmane20f6832009-07-14 15:07:21 -0700679void
Hank Janssen3e7ee492009-07-13 16:02:34 -0700680VmbusChannelClose(
681 VMBUS_CHANNEL *Channel
682 )
683{
684 int ret=0;
685 VMBUS_CHANNEL_CLOSE_CHANNEL* msg;
686 VMBUS_CHANNEL_MSGINFO* info;
Greg Kroah-Hartman0f5e44c2009-07-15 14:57:16 -0700687 unsigned long flags;
Hank Janssen3e7ee492009-07-13 16:02:34 -0700688
689 DPRINT_ENTER(VMBUS);
690
Bill Pemberton454f18a2009-07-27 16:47:24 -0400691 /* Stop callback and cancel the timer asap */
Hank Janssen3e7ee492009-07-13 16:02:34 -0700692 Channel->OnChannelCallback = NULL;
693 TimerStop(Channel->PollTimer);
694
Bill Pemberton454f18a2009-07-27 16:47:24 -0400695 /* Send a closing message */
Greg Kroah-Hartmane40d37c2009-07-15 12:47:22 -0700696 info = kmalloc(sizeof(VMBUS_CHANNEL_MSGINFO) + sizeof(VMBUS_CHANNEL_CLOSE_CHANNEL), GFP_KERNEL);
Hank Janssen3e7ee492009-07-13 16:02:34 -0700697 ASSERT(info != NULL);
698
Bill Pemberton454f18a2009-07-27 16:47:24 -0400699 /* info->waitEvent = WaitEventCreate(); */
Hank Janssen3e7ee492009-07-13 16:02:34 -0700700
701 msg = (VMBUS_CHANNEL_CLOSE_CHANNEL*)info->Msg;
702 msg->Header.MessageType = ChannelMessageCloseChannel;
703 msg->ChildRelId = Channel->OfferMsg.ChildRelId;
704
705 ret = VmbusPostMessage(msg, sizeof(VMBUS_CHANNEL_CLOSE_CHANNEL));
706 if (ret != 0)
707 {
Bill Pemberton454f18a2009-07-27 16:47:24 -0400708 /* TODO: */
Hank Janssen3e7ee492009-07-13 16:02:34 -0700709 }
710
Bill Pemberton454f18a2009-07-27 16:47:24 -0400711 /* Tear down the gpadl for the channel's ring buffer */
Hank Janssen3e7ee492009-07-13 16:02:34 -0700712 if (Channel->RingBufferGpadlHandle)
713 {
714 VmbusChannelTeardownGpadl(Channel, Channel->RingBufferGpadlHandle);
715 }
716
Bill Pemberton454f18a2009-07-27 16:47:24 -0400717 /* TODO: Send a msg to release the childRelId */
Hank Janssen3e7ee492009-07-13 16:02:34 -0700718
Bill Pemberton454f18a2009-07-27 16:47:24 -0400719 /* Cleanup the ring buffers for this channel */
Hank Janssen3e7ee492009-07-13 16:02:34 -0700720 RingBufferCleanup(&Channel->Outbound);
721 RingBufferCleanup(&Channel->Inbound);
722
723 PageFree(Channel->RingBufferPages, Channel->RingBufferPageCount);
724
Greg Kroah-Hartman8c69f522009-07-15 12:48:29 -0700725 kfree(info);
Hank Janssen3e7ee492009-07-13 16:02:34 -0700726
Bill Pemberton454f18a2009-07-27 16:47:24 -0400727
728 /*
729 * If we are closing the channel during an error path in
730 * opening the channel, don't free the channel since the
731 * caller will free the channel
732 */
733
Hank Janssen3e7ee492009-07-13 16:02:34 -0700734 if (Channel->State == CHANNEL_OPEN_STATE)
735 {
Greg Kroah-Hartman0f5e44c2009-07-15 14:57:16 -0700736 spin_lock_irqsave(&gVmbusConnection.channel_lock, flags);
Hank Janssen3e7ee492009-07-13 16:02:34 -0700737 REMOVE_ENTRY_LIST(&Channel->ListEntry);
Greg Kroah-Hartman0f5e44c2009-07-15 14:57:16 -0700738 spin_unlock_irqrestore(&gVmbusConnection.channel_lock, flags);
Hank Janssen3e7ee492009-07-13 16:02:34 -0700739
740 FreeVmbusChannel(Channel);
741 }
742
743 DPRINT_EXIT(VMBUS);
744}
745
746
747/*++
748
749Name:
750 VmbusChannelSendPacket()
751
752Description:
753 Send the specified buffer on the given channel
754
755--*/
756int
757VmbusChannelSendPacket(
758 VMBUS_CHANNEL *Channel,
Greg Kroah-Hartman8282c402009-07-14 15:06:28 -0700759 const void * Buffer,
Greg Kroah-Hartman4d643112009-07-14 15:09:36 -0700760 u32 BufferLen,
Greg Kroah-Hartman59471432009-07-14 15:10:26 -0700761 u64 RequestId,
Hank Janssen3e7ee492009-07-13 16:02:34 -0700762 VMBUS_PACKET_TYPE Type,
Greg Kroah-Hartman4d643112009-07-14 15:09:36 -0700763 u32 Flags
Hank Janssen3e7ee492009-07-13 16:02:34 -0700764)
765{
766 int ret=0;
767 VMPACKET_DESCRIPTOR desc;
Greg Kroah-Hartman4d643112009-07-14 15:09:36 -0700768 u32 packetLen = sizeof(VMPACKET_DESCRIPTOR) + BufferLen;
Greg Kroah-Hartman59471432009-07-14 15:10:26 -0700769 u32 packetLenAligned = ALIGN_UP(packetLen, sizeof(u64));
Hank Janssen3e7ee492009-07-13 16:02:34 -0700770 SG_BUFFER_LIST bufferList[3];
Greg Kroah-Hartman59471432009-07-14 15:10:26 -0700771 u64 alignedData=0;
Hank Janssen3e7ee492009-07-13 16:02:34 -0700772
773 DPRINT_ENTER(VMBUS);
774 DPRINT_DBG(VMBUS, "channel %p buffer %p len %d", Channel, Buffer, BufferLen);
775
776 DumpVmbusChannel(Channel);
777
Greg Kroah-Hartman59471432009-07-14 15:10:26 -0700778 ASSERT((packetLenAligned - packetLen) < sizeof(u64));
Hank Janssen3e7ee492009-07-13 16:02:34 -0700779
Bill Pemberton454f18a2009-07-27 16:47:24 -0400780 /* Setup the descriptor */
781 desc.Type = Type; /* VmbusPacketTypeDataInBand; */
782 desc.Flags = Flags; /* VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED; */
783 desc.DataOffset8 = sizeof(VMPACKET_DESCRIPTOR) >> 3; /* in 8-bytes granularity */
784 desc.Length8 = (u16)(packetLenAligned >> 3);
785 desc.TransactionId = RequestId;
Hank Janssen3e7ee492009-07-13 16:02:34 -0700786
787 bufferList[0].Data = &desc;
788 bufferList[0].Length = sizeof(VMPACKET_DESCRIPTOR);
789
790 bufferList[1].Data = Buffer;
791 bufferList[1].Length = BufferLen;
792
793 bufferList[2].Data = &alignedData;
794 bufferList[2].Length = packetLenAligned - packetLen;
795
796 ret = RingBufferWrite(
797 &Channel->Outbound,
798 bufferList,
799 3);
800
Bill Pemberton454f18a2009-07-27 16:47:24 -0400801 /* TODO: We should determine if this is optional */
Hank Janssen3e7ee492009-07-13 16:02:34 -0700802 if (ret == 0 && !GetRingBufferInterruptMask(&Channel->Outbound))
803 {
804 VmbusChannelSetEvent(Channel);
805 }
806
807 DPRINT_EXIT(VMBUS);
808
809 return ret;
810}
811
812
813/*++
814
815Name:
816 VmbusChannelSendPacketPageBuffer()
817
818Description:
819 Send a range of single-page buffer packets using a GPADL Direct packet type.
820
821--*/
822int
823VmbusChannelSendPacketPageBuffer(
824 VMBUS_CHANNEL *Channel,
825 PAGE_BUFFER PageBuffers[],
Greg Kroah-Hartman4d643112009-07-14 15:09:36 -0700826 u32 PageCount,
Greg Kroah-Hartman8282c402009-07-14 15:06:28 -0700827 void * Buffer,
Greg Kroah-Hartman4d643112009-07-14 15:09:36 -0700828 u32 BufferLen,
Greg Kroah-Hartman59471432009-07-14 15:10:26 -0700829 u64 RequestId
Hank Janssen3e7ee492009-07-13 16:02:34 -0700830)
831{
832 int ret=0;
833 int i=0;
Bill Pemberton0cf4fa82009-07-27 16:47:39 -0400834 struct VMBUS_CHANNEL_PACKET_PAGE_BUFFER desc;
Greg Kroah-Hartman4d643112009-07-14 15:09:36 -0700835 u32 descSize;
836 u32 packetLen;
837 u32 packetLenAligned;
Hank Janssen3e7ee492009-07-13 16:02:34 -0700838 SG_BUFFER_LIST bufferList[3];
Greg Kroah-Hartman59471432009-07-14 15:10:26 -0700839 u64 alignedData=0;
Hank Janssen3e7ee492009-07-13 16:02:34 -0700840
841 DPRINT_ENTER(VMBUS);
842
843 ASSERT(PageCount <= MAX_PAGE_BUFFER_COUNT);
844
845 DumpVmbusChannel(Channel);
846
Bill Pemberton454f18a2009-07-27 16:47:24 -0400847 /* Adjust the size down since VMBUS_CHANNEL_PACKET_PAGE_BUFFER is the largest size we support */
Bill Pemberton0cf4fa82009-07-27 16:47:39 -0400848 descSize = sizeof(struct VMBUS_CHANNEL_PACKET_PAGE_BUFFER) - ((MAX_PAGE_BUFFER_COUNT - PageCount)*sizeof(PAGE_BUFFER));
Hank Janssen3e7ee492009-07-13 16:02:34 -0700849 packetLen = descSize + BufferLen;
Greg Kroah-Hartman59471432009-07-14 15:10:26 -0700850 packetLenAligned = ALIGN_UP(packetLen, sizeof(u64));
Hank Janssen3e7ee492009-07-13 16:02:34 -0700851
Greg Kroah-Hartman59471432009-07-14 15:10:26 -0700852 ASSERT((packetLenAligned - packetLen) < sizeof(u64));
Hank Janssen3e7ee492009-07-13 16:02:34 -0700853
Bill Pemberton454f18a2009-07-27 16:47:24 -0400854 /* Setup the descriptor */
Hank Janssen3e7ee492009-07-13 16:02:34 -0700855 desc.Type = VmbusPacketTypeDataUsingGpaDirect;
856 desc.Flags = VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED;
Bill Pemberton454f18a2009-07-27 16:47:24 -0400857 desc.DataOffset8 = descSize >> 3; /* in 8-bytes grandularity */
858 desc.Length8 = (u16)(packetLenAligned >> 3);
859 desc.TransactionId = RequestId;
Hank Janssen3e7ee492009-07-13 16:02:34 -0700860 desc.RangeCount = PageCount;
861
862 for (i=0; i<PageCount; i++)
863 {
864 desc.Range[i].Length = PageBuffers[i].Length;
865 desc.Range[i].Offset = PageBuffers[i].Offset;
866 desc.Range[i].Pfn = PageBuffers[i].Pfn;
867 }
868
869 bufferList[0].Data = &desc;
870 bufferList[0].Length = descSize;
871
872 bufferList[1].Data = Buffer;
873 bufferList[1].Length = BufferLen;
874
875 bufferList[2].Data = &alignedData;
876 bufferList[2].Length = packetLenAligned - packetLen;
877
878 ret = RingBufferWrite(
879 &Channel->Outbound,
880 bufferList,
881 3);
882
Bill Pemberton454f18a2009-07-27 16:47:24 -0400883 /* TODO: We should determine if this is optional */
Hank Janssen3e7ee492009-07-13 16:02:34 -0700884 if (ret == 0 && !GetRingBufferInterruptMask(&Channel->Outbound))
885 {
886 VmbusChannelSetEvent(Channel);
887 }
888
889 DPRINT_EXIT(VMBUS);
890
891 return ret;
892}
893
894
895
896/*++
897
898Name:
899 VmbusChannelSendPacketMultiPageBuffer()
900
901Description:
902 Send a multi-page buffer packet using a GPADL Direct packet type.
903
904--*/
905int
906VmbusChannelSendPacketMultiPageBuffer(
907 VMBUS_CHANNEL *Channel,
908 MULTIPAGE_BUFFER *MultiPageBuffer,
Greg Kroah-Hartman8282c402009-07-14 15:06:28 -0700909 void * Buffer,
Greg Kroah-Hartman4d643112009-07-14 15:09:36 -0700910 u32 BufferLen,
Greg Kroah-Hartman59471432009-07-14 15:10:26 -0700911 u64 RequestId
Hank Janssen3e7ee492009-07-13 16:02:34 -0700912)
913{
914 int ret=0;
915 VMBUS_CHANNEL_PACKET_MULITPAGE_BUFFER desc;
Greg Kroah-Hartman4d643112009-07-14 15:09:36 -0700916 u32 descSize;
917 u32 packetLen;
918 u32 packetLenAligned;
Hank Janssen3e7ee492009-07-13 16:02:34 -0700919 SG_BUFFER_LIST bufferList[3];
Greg Kroah-Hartman59471432009-07-14 15:10:26 -0700920 u64 alignedData=0;
Greg Kroah-Hartman4d643112009-07-14 15:09:36 -0700921 u32 PfnCount = NUM_PAGES_SPANNED(MultiPageBuffer->Offset, MultiPageBuffer->Length);
Hank Janssen3e7ee492009-07-13 16:02:34 -0700922
923 DPRINT_ENTER(VMBUS);
924
925 DumpVmbusChannel(Channel);
926
927 DPRINT_DBG(VMBUS, "data buffer - offset %u len %u pfn count %u", MultiPageBuffer->Offset, MultiPageBuffer->Length, PfnCount);
928
929 ASSERT(PfnCount > 0);
930 ASSERT(PfnCount <= MAX_MULTIPAGE_BUFFER_COUNT);
931
Bill Pemberton454f18a2009-07-27 16:47:24 -0400932 /* Adjust the size down since VMBUS_CHANNEL_PACKET_MULITPAGE_BUFFER is the largest size we support */
Greg Kroah-Hartman59471432009-07-14 15:10:26 -0700933 descSize = sizeof(VMBUS_CHANNEL_PACKET_MULITPAGE_BUFFER) - ((MAX_MULTIPAGE_BUFFER_COUNT - PfnCount)*sizeof(u64));
Hank Janssen3e7ee492009-07-13 16:02:34 -0700934 packetLen = descSize + BufferLen;
Greg Kroah-Hartman59471432009-07-14 15:10:26 -0700935 packetLenAligned = ALIGN_UP(packetLen, sizeof(u64));
Hank Janssen3e7ee492009-07-13 16:02:34 -0700936
Greg Kroah-Hartman59471432009-07-14 15:10:26 -0700937 ASSERT((packetLenAligned - packetLen) < sizeof(u64));
Hank Janssen3e7ee492009-07-13 16:02:34 -0700938
Bill Pemberton454f18a2009-07-27 16:47:24 -0400939 /* Setup the descriptor */
Hank Janssen3e7ee492009-07-13 16:02:34 -0700940 desc.Type = VmbusPacketTypeDataUsingGpaDirect;
941 desc.Flags = VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED;
Bill Pemberton454f18a2009-07-27 16:47:24 -0400942 desc.DataOffset8 = descSize >> 3; /* in 8-bytes grandularity */
943 desc.Length8 = (u16)(packetLenAligned >> 3);
944 desc.TransactionId = RequestId;
Hank Janssen3e7ee492009-07-13 16:02:34 -0700945 desc.RangeCount = 1;
946
947 desc.Range.Length = MultiPageBuffer->Length;
948 desc.Range.Offset = MultiPageBuffer->Offset;
949
Greg Kroah-Hartman59471432009-07-14 15:10:26 -0700950 memcpy(desc.Range.PfnArray, MultiPageBuffer->PfnArray, PfnCount*sizeof(u64));
Hank Janssen3e7ee492009-07-13 16:02:34 -0700951
952 bufferList[0].Data = &desc;
953 bufferList[0].Length = descSize;
954
955 bufferList[1].Data = Buffer;
956 bufferList[1].Length = BufferLen;
957
958 bufferList[2].Data = &alignedData;
959 bufferList[2].Length = packetLenAligned - packetLen;
960
961 ret = RingBufferWrite(
962 &Channel->Outbound,
963 bufferList,
964 3);
965
Bill Pemberton454f18a2009-07-27 16:47:24 -0400966 /* TODO: We should determine if this is optional */
Hank Janssen3e7ee492009-07-13 16:02:34 -0700967 if (ret == 0 && !GetRingBufferInterruptMask(&Channel->Outbound))
968 {
969 VmbusChannelSetEvent(Channel);
970 }
971
972 DPRINT_EXIT(VMBUS);
973
974 return ret;
975}
976
977
978/*++
979
980Name:
981 VmbusChannelRecvPacket()
982
983Description:
984 Retrieve the user packet on the specified channel
985
986--*/
Bill Pemberton454f18a2009-07-27 16:47:24 -0400987/* TODO: Do we ever receive a gpa direct packet other than the ones we send ? */
Hank Janssen3e7ee492009-07-13 16:02:34 -0700988int
989VmbusChannelRecvPacket(
990 VMBUS_CHANNEL *Channel,
Greg Kroah-Hartman8282c402009-07-14 15:06:28 -0700991 void * Buffer,
Greg Kroah-Hartman4d643112009-07-14 15:09:36 -0700992 u32 BufferLen,
993 u32* BufferActualLen,
Greg Kroah-Hartman59471432009-07-14 15:10:26 -0700994 u64* RequestId
Hank Janssen3e7ee492009-07-13 16:02:34 -0700995 )
996{
997 VMPACKET_DESCRIPTOR desc;
Greg Kroah-Hartman4d643112009-07-14 15:09:36 -0700998 u32 packetLen;
999 u32 userLen;
Hank Janssen3e7ee492009-07-13 16:02:34 -07001000 int ret;
Greg Kroah-Hartman54411c42009-07-15 14:48:32 -07001001 unsigned long flags;
Hank Janssen3e7ee492009-07-13 16:02:34 -07001002
1003 DPRINT_ENTER(VMBUS);
1004
1005 *BufferActualLen = 0;
1006 *RequestId = 0;
1007
Greg Kroah-Hartman54411c42009-07-15 14:48:32 -07001008 spin_lock_irqsave(&Channel->inbound_lock, flags);
Hank Janssen3e7ee492009-07-13 16:02:34 -07001009
1010 ret = RingBufferPeek(&Channel->Inbound, &desc, sizeof(VMPACKET_DESCRIPTOR));
1011 if (ret != 0)
1012 {
Greg Kroah-Hartman54411c42009-07-15 14:48:32 -07001013 spin_unlock_irqrestore(&Channel->inbound_lock, flags);
Hank Janssen3e7ee492009-07-13 16:02:34 -07001014
Bill Pemberton454f18a2009-07-27 16:47:24 -04001015 /* DPRINT_DBG(VMBUS, "nothing to read!!"); */
Hank Janssen3e7ee492009-07-13 16:02:34 -07001016 DPRINT_EXIT(VMBUS);
1017 return 0;
1018 }
1019
Bill Pemberton454f18a2009-07-27 16:47:24 -04001020 /* VmbusChannelClearEvent(Channel); */
Hank Janssen3e7ee492009-07-13 16:02:34 -07001021
1022 packetLen = desc.Length8 << 3;
1023 userLen = packetLen - (desc.DataOffset8 << 3);
Bill Pemberton454f18a2009-07-27 16:47:24 -04001024 /* ASSERT(userLen > 0); */
Hank Janssen3e7ee492009-07-13 16:02:34 -07001025
1026 DPRINT_DBG(VMBUS, "packet received on channel %p relid %d <type %d flag %d tid %llx pktlen %d datalen %d> ",
1027 Channel,
1028 Channel->OfferMsg.ChildRelId,
1029 desc.Type,
1030 desc.Flags,
1031 desc.TransactionId, packetLen, userLen);
1032
1033 *BufferActualLen = userLen;
1034
1035 if (userLen > BufferLen)
1036 {
Greg Kroah-Hartman54411c42009-07-15 14:48:32 -07001037 spin_unlock_irqrestore(&Channel->inbound_lock, flags);
Hank Janssen3e7ee492009-07-13 16:02:34 -07001038
1039 DPRINT_ERR(VMBUS, "buffer too small - got %d needs %d", BufferLen, userLen);
1040 DPRINT_EXIT(VMBUS);
1041
1042 return -1;
1043 }
1044
1045 *RequestId = desc.TransactionId;
1046
Bill Pemberton454f18a2009-07-27 16:47:24 -04001047 /* Copy over the packet to the user buffer */
Hank Janssen3e7ee492009-07-13 16:02:34 -07001048 ret = RingBufferRead(&Channel->Inbound, Buffer, userLen, (desc.DataOffset8 << 3));
1049
Greg Kroah-Hartman54411c42009-07-15 14:48:32 -07001050 spin_unlock_irqrestore(&Channel->inbound_lock, flags);
Hank Janssen3e7ee492009-07-13 16:02:34 -07001051
1052 DPRINT_EXIT(VMBUS);
1053
1054 return 0;
1055}
1056
1057/*++
1058
1059Name:
1060 VmbusChannelRecvPacketRaw()
1061
1062Description:
1063 Retrieve the raw packet on the specified channel
1064
1065--*/
1066int
1067VmbusChannelRecvPacketRaw(
1068 VMBUS_CHANNEL *Channel,
Greg Kroah-Hartman8282c402009-07-14 15:06:28 -07001069 void * Buffer,
Greg Kroah-Hartman4d643112009-07-14 15:09:36 -07001070 u32 BufferLen,
1071 u32* BufferActualLen,
Greg Kroah-Hartman59471432009-07-14 15:10:26 -07001072 u64* RequestId
Hank Janssen3e7ee492009-07-13 16:02:34 -07001073 )
1074{
1075 VMPACKET_DESCRIPTOR desc;
Greg Kroah-Hartman4d643112009-07-14 15:09:36 -07001076 u32 packetLen;
1077 u32 userLen;
Hank Janssen3e7ee492009-07-13 16:02:34 -07001078 int ret;
Greg Kroah-Hartman54411c42009-07-15 14:48:32 -07001079 unsigned long flags;
Hank Janssen3e7ee492009-07-13 16:02:34 -07001080
1081 DPRINT_ENTER(VMBUS);
1082
1083 *BufferActualLen = 0;
1084 *RequestId = 0;
1085
Greg Kroah-Hartman54411c42009-07-15 14:48:32 -07001086 spin_lock_irqsave(&Channel->inbound_lock, flags);
Hank Janssen3e7ee492009-07-13 16:02:34 -07001087
1088 ret = RingBufferPeek(&Channel->Inbound, &desc, sizeof(VMPACKET_DESCRIPTOR));
1089 if (ret != 0)
1090 {
Greg Kroah-Hartman54411c42009-07-15 14:48:32 -07001091 spin_unlock_irqrestore(&Channel->inbound_lock, flags);
Hank Janssen3e7ee492009-07-13 16:02:34 -07001092
Bill Pemberton454f18a2009-07-27 16:47:24 -04001093 /* DPRINT_DBG(VMBUS, "nothing to read!!"); */
Hank Janssen3e7ee492009-07-13 16:02:34 -07001094 DPRINT_EXIT(VMBUS);
1095 return 0;
1096 }
1097
Bill Pemberton454f18a2009-07-27 16:47:24 -04001098 /* VmbusChannelClearEvent(Channel); */
Hank Janssen3e7ee492009-07-13 16:02:34 -07001099
1100 packetLen = desc.Length8 << 3;
1101 userLen = packetLen - (desc.DataOffset8 << 3);
1102
1103 DPRINT_DBG(VMBUS, "packet received on channel %p relid %d <type %d flag %d tid %llx pktlen %d datalen %d> ",
1104 Channel,
1105 Channel->OfferMsg.ChildRelId,
1106 desc.Type,
1107 desc.Flags,
1108 desc.TransactionId, packetLen, userLen);
1109
1110 *BufferActualLen = packetLen;
1111
1112 if (packetLen > BufferLen)
1113 {
Greg Kroah-Hartman54411c42009-07-15 14:48:32 -07001114 spin_unlock_irqrestore(&Channel->inbound_lock, flags);
Hank Janssen3e7ee492009-07-13 16:02:34 -07001115
1116 DPRINT_ERR(VMBUS, "buffer too small - needed %d bytes but got space for only %d bytes", packetLen, BufferLen);
1117 DPRINT_EXIT(VMBUS);
1118 return -2;
1119 }
1120
1121 *RequestId = desc.TransactionId;
1122
Bill Pemberton454f18a2009-07-27 16:47:24 -04001123 /* Copy over the entire packet to the user buffer */
Hank Janssen3e7ee492009-07-13 16:02:34 -07001124 ret = RingBufferRead(&Channel->Inbound, Buffer, packetLen, 0);
1125
Greg Kroah-Hartman54411c42009-07-15 14:48:32 -07001126 spin_unlock_irqrestore(&Channel->inbound_lock, flags);
Hank Janssen3e7ee492009-07-13 16:02:34 -07001127
1128 DPRINT_EXIT(VMBUS);
1129
1130 return 0;
1131}
1132
1133
1134/*++
1135
1136Name:
1137 VmbusChannelOnChannelEvent()
1138
1139Description:
1140 Channel event callback
1141
1142--*/
1143void
1144VmbusChannelOnChannelEvent(
1145 VMBUS_CHANNEL *Channel
1146 )
1147{
1148 DumpVmbusChannel(Channel);
1149 ASSERT(Channel->OnChannelCallback);
1150#ifdef ENABLE_POLLING
1151 TimerStop(Channel->PollTimer);
1152 Channel->OnChannelCallback(Channel->ChannelCallbackContext);
1153 TimerStart(Channel->PollTimer, 100 /* 100us */);
1154#else
1155 Channel->OnChannelCallback(Channel->ChannelCallbackContext);
1156#endif
1157}
1158
1159/*++
1160
1161Name:
1162 VmbusChannelOnTimer()
1163
1164Description:
1165 Timer event callback
1166
1167--*/
1168void
1169VmbusChannelOnTimer(
1170 void *Context
1171 )
1172{
1173 VMBUS_CHANNEL *channel = (VMBUS_CHANNEL*)Context;
1174
1175 if (channel->OnChannelCallback)
1176 {
1177 channel->OnChannelCallback(channel->ChannelCallbackContext);
1178#ifdef ENABLE_POLLING
1179 TimerStart(channel->PollTimer, 100 /* 100us */);
1180#endif
1181 }
1182}
1183
1184
1185/*++
1186
1187Name:
1188 DumpVmbusChannel()
1189
1190Description:
1191 Dump vmbus channel info to the console
1192
1193--*/
1194static void
1195DumpVmbusChannel(
1196 VMBUS_CHANNEL *Channel
1197 )
1198{
1199 DPRINT_DBG(VMBUS, "Channel (%d)", Channel->OfferMsg.ChildRelId);
1200 DumpRingInfo(&Channel->Outbound, "Outbound ");
1201 DumpRingInfo(&Channel->Inbound, "Inbound ");
1202}
1203
1204
Bill Pemberton454f18a2009-07-27 16:47:24 -04001205/* eof */