]> bbs.cooldavid.org Git - net-next-2.6.git/blame - drivers/staging/hv/ChannelMgmt.c
Staging: hv: cleanup coding style issues in RingBuffer.h
[net-next-2.6.git] / drivers / staging / hv / ChannelMgmt.c
CommitLineData
3e7ee490
HJ
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
09d50ff8
GKH
25#include "include/osd.h"
26#include "include/logging.h"
3e7ee490
HJ
27
28#include "VmbusPrivate.h"
29
454f18a9 30/* Data types */
3e7ee490
HJ
31
32typedef void (*PFN_CHANNEL_MESSAGE_HANDLER)(VMBUS_CHANNEL_MESSAGE_HEADER* msg);
33
34typedef struct _VMBUS_CHANNEL_MESSAGE_TABLE_ENTRY {
35 VMBUS_CHANNEL_MESSAGE_TYPE messageType;
36 PFN_CHANNEL_MESSAGE_HANDLER messageHandler;
37} VMBUS_CHANNEL_MESSAGE_TABLE_ENTRY;
38
454f18a9 39/* Internal routines */
3e7ee490
HJ
40
41static void
42VmbusChannelOnOffer(
43 PVMBUS_CHANNEL_MESSAGE_HEADER hdr
44 );
45static void
46VmbusChannelOnOpenResult(
47 PVMBUS_CHANNEL_MESSAGE_HEADER hdr
48 );
49
50static void
51VmbusChannelOnOfferRescind(
52 PVMBUS_CHANNEL_MESSAGE_HEADER hdr
53 );
54
55static void
56VmbusChannelOnGpadlCreated(
57 PVMBUS_CHANNEL_MESSAGE_HEADER hdr
58 );
59
60static void
61VmbusChannelOnGpadlTorndown(
62 PVMBUS_CHANNEL_MESSAGE_HEADER hdr
63 );
64
65static void
66VmbusChannelOnOffersDelivered(
67 PVMBUS_CHANNEL_MESSAGE_HEADER hdr
68 );
69
70static void
71VmbusChannelOnVersionResponse(
72 PVMBUS_CHANNEL_MESSAGE_HEADER hdr
73 );
74
75static void
76VmbusChannelProcessOffer(
8282c400 77 void * context
3e7ee490
HJ
78 );
79
80static void
81VmbusChannelProcessRescindOffer(
8282c400 82 void * context
3e7ee490
HJ
83 );
84
85
454f18a9 86/* Globals */
3e7ee490
HJ
87
88#define MAX_NUM_DEVICE_CLASSES_SUPPORTED 4
89
bd1de709 90static const GUID gSupportedDeviceClasses[MAX_NUM_DEVICE_CLASSES_SUPPORTED]= {
454f18a9
BP
91 /* {ba6163d9-04a1-4d29-b605-72e2ffb1dc7f} */
92 {.Data = {0xd9, 0x63, 0x61, 0xba, 0xa1, 0x04, 0x29, 0x4d, 0xb6, 0x05, 0x72, 0xe2, 0xff, 0xb1, 0xdc, 0x7f}},/* Storage - SCSI */
93 /* {F8615163-DF3E-46c5-913F-F2D2F965ED0E} */
94 {.Data = {0x63, 0x51, 0x61, 0xF8, 0x3E, 0xDF, 0xc5, 0x46, 0x91, 0x3F, 0xF2, 0xD2, 0xF9, 0x65, 0xED, 0x0E}}, /* Network */
95 /* {CFA8B69E-5B4A-4cc0-B98B-8BA1A1F3F95A} */
96 {.Data = {0x9E, 0xB6, 0xA8, 0xCF, 0x4A, 0x5B, 0xc0, 0x4c, 0xB9, 0x8B, 0x8B, 0xA1, 0xA1, 0xF3, 0xF9, 0x5A}}, /* Input */
97 /* {32412632-86cb-44a2-9b5c-50d1417354f5} */
98 {.Data = {0x32, 0x26, 0x41, 0x32, 0xcb, 0x86, 0xa2, 0x44, 0x9b, 0x5c, 0x50, 0xd1, 0x41, 0x73, 0x54, 0xf5}}, /* IDE */
3e7ee490
HJ
99
100};
101
454f18a9 102/* Channel message dispatch table */
bd1de709 103static VMBUS_CHANNEL_MESSAGE_TABLE_ENTRY gChannelMessageTable[ChannelMessageCount]= {
3e7ee490
HJ
104 {ChannelMessageInvalid, NULL},
105 {ChannelMessageOfferChannel, VmbusChannelOnOffer},
106 {ChannelMessageRescindChannelOffer, VmbusChannelOnOfferRescind},
107 {ChannelMessageRequestOffers, NULL},
108 {ChannelMessageAllOffersDelivered, VmbusChannelOnOffersDelivered},
109 {ChannelMessageOpenChannel, NULL},
110 {ChannelMessageOpenChannelResult, VmbusChannelOnOpenResult},
111 {ChannelMessageCloseChannel, NULL},
112 {ChannelMessageGpadlHeader, NULL},
113 {ChannelMessageGpadlBody, NULL},
114 {ChannelMessageGpadlCreated, VmbusChannelOnGpadlCreated},
115 {ChannelMessageGpadlTeardown, NULL},
116 {ChannelMessageGpadlTorndown, VmbusChannelOnGpadlTorndown},
117 {ChannelMessageRelIdReleased, NULL},
118 {ChannelMessageInitiateContact, NULL},
119 {ChannelMessageVersionResponse, VmbusChannelOnVersionResponse},
120 {ChannelMessageUnload, NULL},
121};
122
123/*++
124
125Name:
126 AllocVmbusChannel()
127
128Description:
129 Allocate and initialize a vmbus channel object
130
131--*/
b239549c 132VMBUS_CHANNEL* AllocVmbusChannel(void)
3e7ee490
HJ
133{
134 VMBUS_CHANNEL* channel;
135
0a72f3cf 136 channel = kzalloc(sizeof(VMBUS_CHANNEL), GFP_ATOMIC);
3e7ee490
HJ
137 if (!channel)
138 {
139 return NULL;
140 }
141
54411c42 142 spin_lock_init(&channel->inbound_lock);
3e7ee490 143
c8a429a4
GKH
144 init_timer(&channel->poll_timer);
145 channel->poll_timer.data = (unsigned long)channel;
146 channel->poll_timer.function = VmbusChannelOnTimer;
3e7ee490 147
454f18a9 148 /* channel->dataWorkQueue = WorkQueueCreate("data"); */
de65a384 149 channel->ControlWQ = create_workqueue("hv_vmbus_ctl");
3e7ee490
HJ
150 if (!channel->ControlWQ)
151 {
8c69f52a 152 kfree(channel);
3e7ee490
HJ
153 return NULL;
154 }
155
156 return channel;
157}
158
159/*++
160
161Name:
162 ReleaseVmbusChannel()
163
164Description:
165 Release the vmbus channel object itself
166
167--*/
168static inline void ReleaseVmbusChannel(void* Context)
169{
170 VMBUS_CHANNEL* channel = (VMBUS_CHANNEL*)Context;
171
172 DPRINT_ENTER(VMBUS);
173
174 DPRINT_DBG(VMBUS, "releasing channel (%p)", channel);
de65a384 175 destroy_workqueue(channel->ControlWQ);
3e7ee490
HJ
176 DPRINT_DBG(VMBUS, "channel released (%p)", channel);
177
8c69f52a 178 kfree(channel);
3e7ee490
HJ
179
180 DPRINT_EXIT(VMBUS);
181}
182
183/*++
184
185Name:
186 FreeVmbusChannel()
187
188Description:
189 Release the resources used by the vmbus channel object
190
191--*/
b239549c 192void FreeVmbusChannel(VMBUS_CHANNEL* Channel)
3e7ee490 193{
c8a429a4 194 del_timer(&Channel->poll_timer);
3e7ee490 195
454f18a9
BP
196 /* We have to release the channel's workqueue/thread in the vmbus's workqueue/thread context */
197 /* ie we can't destroy ourselves. */
de65a384
BP
198 osd_schedule_callback(gVmbusConnection.WorkQueue, ReleaseVmbusChannel,
199 (void *)Channel);
3e7ee490
HJ
200}
201
202
203/*++
204
205Name:
206 VmbusChannelProcessOffer()
207
208Description:
209 Process the offer by creating a channel/device associated with this offer
210
211--*/
212static void
213VmbusChannelProcessOffer(
8282c400 214 void * context
3e7ee490
HJ
215 )
216{
217 int ret=0;
218 VMBUS_CHANNEL* newChannel=(VMBUS_CHANNEL*)context;
219 LIST_ENTRY* anchor;
220 LIST_ENTRY* curr;
0e727613 221 bool fNew = true;
3e7ee490 222 VMBUS_CHANNEL* channel;
0f5e44ca 223 unsigned long flags;
3e7ee490
HJ
224
225 DPRINT_ENTER(VMBUS);
226
454f18a9 227 /* Make sure this is a new offer */
0f5e44ca 228 spin_lock_irqsave(&gVmbusConnection.channel_lock, flags);
3e7ee490
HJ
229
230 ITERATE_LIST_ENTRIES(anchor, curr, &gVmbusConnection.ChannelList)
231 {
232 channel = CONTAINING_RECORD(curr, VMBUS_CHANNEL, ListEntry);
233
234 if (!memcmp(&channel->OfferMsg.Offer.InterfaceType, &newChannel->OfferMsg.Offer.InterfaceType,sizeof(GUID)) &&
235 !memcmp(&channel->OfferMsg.Offer.InterfaceInstance, &newChannel->OfferMsg.Offer.InterfaceInstance, sizeof(GUID)))
236 {
0e727613 237 fNew = false;
3e7ee490
HJ
238 break;
239 }
240 }
241
242 if (fNew)
243 {
244 INSERT_TAIL_LIST(&gVmbusConnection.ChannelList, &newChannel->ListEntry);
245 }
0f5e44ca 246 spin_unlock_irqrestore(&gVmbusConnection.channel_lock, flags);
3e7ee490
HJ
247
248 if (!fNew)
249 {
250 DPRINT_DBG(VMBUS, "Ignoring duplicate offer for relid (%d)", newChannel->OfferMsg.ChildRelId);
251 FreeVmbusChannel(newChannel);
252 DPRINT_EXIT(VMBUS);
253 return;
254 }
255
454f18a9
BP
256 /* Start the process of binding this offer to the driver */
257 /* We need to set the DeviceObject field before calling VmbusChildDeviceAdd() */
3e7ee490
HJ
258 newChannel->DeviceObject = VmbusChildDeviceCreate(
259 newChannel->OfferMsg.Offer.InterfaceType,
260 newChannel->OfferMsg.Offer.InterfaceInstance,
261 newChannel);
262
263 DPRINT_DBG(VMBUS, "child device object allocated - %p", newChannel->DeviceObject);
264
454f18a9
BP
265 /*
266 * Add the new device to the bus. This will kick off device-driver
267 * binding which eventually invokes the device driver's AddDevice()
268 * method.
269 */
270
3e7ee490
HJ
271 ret = VmbusChildDeviceAdd(newChannel->DeviceObject);
272 if (ret != 0)
273 {
274 DPRINT_ERR(VMBUS, "unable to add child device object (relid %d)",
275 newChannel->OfferMsg.ChildRelId);
276
0f5e44ca 277 spin_lock_irqsave(&gVmbusConnection.channel_lock, flags);
3e7ee490 278 REMOVE_ENTRY_LIST(&newChannel->ListEntry);
0f5e44ca 279 spin_unlock_irqrestore(&gVmbusConnection.channel_lock, flags);
3e7ee490
HJ
280
281 FreeVmbusChannel(newChannel);
282 }
283 else
284 {
454f18a9
BP
285 /*
286 * This state is used to indicate a successful open
287 * so that when we do close the channel normally, we
288 * can cleanup properly
289 */
3e7ee490
HJ
290 newChannel->State = CHANNEL_OPEN_STATE;
291 }
292 DPRINT_EXIT(VMBUS);
293}
294
295/*++
296
297Name:
298 VmbusChannelProcessRescindOffer()
299
300Description:
301 Rescind the offer by initiating a device removal
302
303--*/
304static void
305VmbusChannelProcessRescindOffer(
8282c400 306 void * context
3e7ee490
HJ
307 )
308{
309 VMBUS_CHANNEL* channel=(VMBUS_CHANNEL*)context;
310
311 DPRINT_ENTER(VMBUS);
312
313 VmbusChildDeviceRemove(channel->DeviceObject);
314
315 DPRINT_EXIT(VMBUS);
316}
317
318
319/*++
320
321Name:
322 VmbusChannelOnOffer()
323
324Description:
325 Handler for channel offers from vmbus in parent partition. We ignore all offers except
326 network and storage offers. For each network and storage offers, we create a channel object
327 and queue a work item to the channel object to process the offer synchronously
328
329--*/
330static void
331VmbusChannelOnOffer(
332 PVMBUS_CHANNEL_MESSAGE_HEADER hdr
333 )
334{
335 VMBUS_CHANNEL_OFFER_CHANNEL* offer = (VMBUS_CHANNEL_OFFER_CHANNEL*)hdr;
336 VMBUS_CHANNEL* newChannel;
337
338 GUID *guidType;
339 GUID *guidInstance;
340 int i;
341 int fSupported=0;
342
343 DPRINT_ENTER(VMBUS);
344
345 for (i=0; i<MAX_NUM_DEVICE_CLASSES_SUPPORTED; i++)
346 {
347 if (memcmp(&offer->Offer.InterfaceType, &gSupportedDeviceClasses[i], sizeof(GUID)) == 0)
348 {
349 fSupported = 1;
350 break;
351 }
352 }
353
354 if (!fSupported)
355 {
356 DPRINT_DBG(VMBUS, "Ignoring channel offer notification for child relid %d", offer->ChildRelId);
357 DPRINT_EXIT(VMBUS);
358
359 return;
360 }
361
362 guidType = &offer->Offer.InterfaceType;
363 guidInstance = &offer->Offer.InterfaceInstance;
364
365 DPRINT_INFO(VMBUS, "Channel offer notification - child relid %d monitor id %d allocated %d, "
366 "type {%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x%02x%02x} "
367 "instance {%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x%02x%02x}",
368 offer->ChildRelId,
369 offer->MonitorId,
370 offer->MonitorAllocated,
371 guidType->Data[3], guidType->Data[2], guidType->Data[1], guidType->Data[0], guidType->Data[5], guidType->Data[4], guidType->Data[7], guidType->Data[6], guidType->Data[8], guidType->Data[9], guidType->Data[10], guidType->Data[11], guidType->Data[12], guidType->Data[13], guidType->Data[14], guidType->Data[15],
372 guidInstance->Data[3], guidInstance->Data[2], guidInstance->Data[1], guidInstance->Data[0], guidInstance->Data[5], guidInstance->Data[4], guidInstance->Data[7], guidInstance->Data[6], guidInstance->Data[8], guidInstance->Data[9], guidInstance->Data[10], guidInstance->Data[11], guidInstance->Data[12], guidInstance->Data[13], guidInstance->Data[14], guidInstance->Data[15]);
373
454f18a9 374 /* Allocate the channel object and save this offer. */
3e7ee490
HJ
375 newChannel = AllocVmbusChannel();
376 if (!newChannel)
377 {
378 DPRINT_ERR(VMBUS, "unable to allocate channel object");
379 return;
380 }
381
382 DPRINT_DBG(VMBUS, "channel object allocated - %p", newChannel);
383
384 memcpy(&newChannel->OfferMsg, offer, sizeof(VMBUS_CHANNEL_OFFER_CHANNEL));
5654e932
GKH
385 newChannel->MonitorGroup = (u8)offer->MonitorId / 32;
386 newChannel->MonitorBit = (u8)offer->MonitorId % 32;
3e7ee490 387
454f18a9 388 /* TODO: Make sure the offer comes from our parent partition */
de65a384
BP
389 osd_schedule_callback(newChannel->ControlWQ, VmbusChannelProcessOffer,
390 newChannel);
3e7ee490
HJ
391
392 DPRINT_EXIT(VMBUS);
393}
394
395
396/*++
397
398Name:
399 VmbusChannelOnOfferRescind()
400
401Description:
402 Rescind offer handler. We queue a work item to process this offer
403 synchronously
404
405--*/
406static void
407VmbusChannelOnOfferRescind(
408 PVMBUS_CHANNEL_MESSAGE_HEADER hdr
409 )
410{
411 VMBUS_CHANNEL_RESCIND_OFFER* rescind = (VMBUS_CHANNEL_RESCIND_OFFER*)hdr;
412 VMBUS_CHANNEL* channel;
413
414 DPRINT_ENTER(VMBUS);
415
416 channel = GetChannelFromRelId(rescind->ChildRelId);
417 if (channel == NULL)
418 {
419 DPRINT_DBG(VMBUS, "channel not found for relId %d", rescind->ChildRelId);
420 return;
421 }
422
de65a384
BP
423 osd_schedule_callback(channel->ControlWQ,
424 VmbusChannelProcessRescindOffer,
425 channel);
3e7ee490
HJ
426
427 DPRINT_EXIT(VMBUS);
428}
429
430
431/*++
432
433Name:
434 VmbusChannelOnOffersDelivered()
435
436Description:
437 This is invoked when all offers have been delivered.
438 Nothing to do here.
439
440--*/
441static void
442VmbusChannelOnOffersDelivered(
443 PVMBUS_CHANNEL_MESSAGE_HEADER hdr
444 )
445{
446 DPRINT_ENTER(VMBUS);
447 DPRINT_EXIT(VMBUS);
448}
449
450
451/*++
452
453Name:
454 VmbusChannelOnOpenResult()
455
456Description:
457 Open result handler. This is invoked when we received a response
458 to our channel open request. Find the matching request, copy the
459 response and signal the requesting thread.
460
461--*/
462static void
463VmbusChannelOnOpenResult(
464 PVMBUS_CHANNEL_MESSAGE_HEADER hdr
465 )
466{
467 VMBUS_CHANNEL_OPEN_RESULT* result = (VMBUS_CHANNEL_OPEN_RESULT*)hdr;
468 LIST_ENTRY* anchor;
469 LIST_ENTRY* curr;
470 VMBUS_CHANNEL_MSGINFO* msgInfo;
471 VMBUS_CHANNEL_MESSAGE_HEADER* requestHeader;
472 VMBUS_CHANNEL_OPEN_CHANNEL* openMsg;
dd0813b6 473 unsigned long flags;
3e7ee490
HJ
474
475 DPRINT_ENTER(VMBUS);
476
477 DPRINT_DBG(VMBUS, "vmbus open result - %d", result->Status);
478
454f18a9 479 /* Find the open msg, copy the result and signal/unblock the wait event */
dd0813b6 480 spin_lock_irqsave(&gVmbusConnection.channelmsg_lock, flags);
3e7ee490
HJ
481
482 ITERATE_LIST_ENTRIES(anchor, curr, &gVmbusConnection.ChannelMsgList)
483 {
484 msgInfo = (VMBUS_CHANNEL_MSGINFO*) curr;
485 requestHeader = (VMBUS_CHANNEL_MESSAGE_HEADER*)msgInfo->Msg;
486
487 if (requestHeader->MessageType == ChannelMessageOpenChannel)
488 {
489 openMsg = (VMBUS_CHANNEL_OPEN_CHANNEL*)msgInfo->Msg;
490 if (openMsg->ChildRelId == result->ChildRelId &&
491 openMsg->OpenId == result->OpenId)
492 {
493 memcpy(&msgInfo->Response.OpenResult, result, sizeof(VMBUS_CHANNEL_OPEN_RESULT));
bfc30aae 494 osd_WaitEventSet(msgInfo->WaitEvent);
3e7ee490
HJ
495 break;
496 }
497 }
498 }
dd0813b6 499 spin_unlock_irqrestore(&gVmbusConnection.channelmsg_lock, flags);
3e7ee490
HJ
500
501 DPRINT_EXIT(VMBUS);
502}
503
504
505/*++
506
507Name:
508 VmbusChannelOnGpadlCreated()
509
510Description:
511 GPADL created handler. This is invoked when we received a response
512 to our gpadl create request. Find the matching request, copy the
513 response and signal the requesting thread.
514
515--*/
516static void
517VmbusChannelOnGpadlCreated(
518 PVMBUS_CHANNEL_MESSAGE_HEADER hdr
519 )
520{
521 VMBUS_CHANNEL_GPADL_CREATED *gpadlCreated = (VMBUS_CHANNEL_GPADL_CREATED*)hdr;
522 LIST_ENTRY *anchor;
523 LIST_ENTRY *curr;
524 VMBUS_CHANNEL_MSGINFO *msgInfo;
525 VMBUS_CHANNEL_MESSAGE_HEADER *requestHeader;
526 VMBUS_CHANNEL_GPADL_HEADER *gpadlHeader;
dd0813b6 527 unsigned long flags;
3e7ee490
HJ
528
529 DPRINT_ENTER(VMBUS);
530
531 DPRINT_DBG(VMBUS, "vmbus gpadl created result - %d", gpadlCreated->CreationStatus);
532
454f18a9 533 /* Find the establish msg, copy the result and signal/unblock the wait event */
dd0813b6 534 spin_lock_irqsave(&gVmbusConnection.channelmsg_lock, flags);
3e7ee490
HJ
535
536 ITERATE_LIST_ENTRIES(anchor, curr, &gVmbusConnection.ChannelMsgList)
537 {
538 msgInfo = (VMBUS_CHANNEL_MSGINFO*) curr;
539 requestHeader = (VMBUS_CHANNEL_MESSAGE_HEADER*)msgInfo->Msg;
540
541 if (requestHeader->MessageType == ChannelMessageGpadlHeader)
542 {
543 gpadlHeader = (VMBUS_CHANNEL_GPADL_HEADER*)requestHeader;
544
545 if ((gpadlCreated->ChildRelId == gpadlHeader->ChildRelId) &&
546 (gpadlCreated->Gpadl == gpadlHeader->Gpadl))
547 {
548 memcpy(&msgInfo->Response.GpadlCreated, gpadlCreated, sizeof(VMBUS_CHANNEL_GPADL_CREATED));
bfc30aae 549 osd_WaitEventSet(msgInfo->WaitEvent);
3e7ee490
HJ
550 break;
551 }
552 }
553 }
dd0813b6 554 spin_unlock_irqrestore(&gVmbusConnection.channelmsg_lock, flags);
3e7ee490
HJ
555
556 DPRINT_EXIT(VMBUS);
557}
558
559
560/*++
561
562Name:
563 VmbusChannelOnGpadlTorndown()
564
565Description:
566 GPADL torndown handler. This is invoked when we received a response
567 to our gpadl teardown request. Find the matching request, copy the
568 response and signal the requesting thread.
569
570--*/
571static void
572VmbusChannelOnGpadlTorndown(
573 PVMBUS_CHANNEL_MESSAGE_HEADER hdr
574 )
575{
576 VMBUS_CHANNEL_GPADL_TORNDOWN* gpadlTorndown = (VMBUS_CHANNEL_GPADL_TORNDOWN*)hdr;
577 LIST_ENTRY* anchor;
578 LIST_ENTRY* curr;
579 VMBUS_CHANNEL_MSGINFO* msgInfo;
580 VMBUS_CHANNEL_MESSAGE_HEADER *requestHeader;
581 VMBUS_CHANNEL_GPADL_TEARDOWN *gpadlTeardown;
dd0813b6 582 unsigned long flags;
3e7ee490
HJ
583
584 DPRINT_ENTER(VMBUS);
585
454f18a9 586 /* Find the open msg, copy the result and signal/unblock the wait event */
dd0813b6 587 spin_lock_irqsave(&gVmbusConnection.channelmsg_lock, flags);
3e7ee490
HJ
588
589 ITERATE_LIST_ENTRIES(anchor, curr, &gVmbusConnection.ChannelMsgList)
590 {
591 msgInfo = (VMBUS_CHANNEL_MSGINFO*) curr;
592 requestHeader = (VMBUS_CHANNEL_MESSAGE_HEADER*)msgInfo->Msg;
593
594 if (requestHeader->MessageType == ChannelMessageGpadlTeardown)
595 {
596 gpadlTeardown = (VMBUS_CHANNEL_GPADL_TEARDOWN*)requestHeader;
597
598 if (gpadlTorndown->Gpadl == gpadlTeardown->Gpadl)
599 {
600 memcpy(&msgInfo->Response.GpadlTorndown, gpadlTorndown, sizeof(VMBUS_CHANNEL_GPADL_TORNDOWN));
bfc30aae 601 osd_WaitEventSet(msgInfo->WaitEvent);
3e7ee490
HJ
602 break;
603 }
604 }
605 }
dd0813b6 606 spin_unlock_irqrestore(&gVmbusConnection.channelmsg_lock, flags);
3e7ee490
HJ
607
608 DPRINT_EXIT(VMBUS);
609}
610
611
612/*++
613
614Name:
615 VmbusChannelOnVersionResponse()
616
617Description:
618 Version response handler. This is invoked when we received a response
619 to our initiate contact request. Find the matching request, copy the
620 response and signal the requesting thread.
621
622--*/
623static void
624VmbusChannelOnVersionResponse(
625 PVMBUS_CHANNEL_MESSAGE_HEADER hdr
626 )
627{
628 LIST_ENTRY* anchor;
629 LIST_ENTRY* curr;
630 VMBUS_CHANNEL_MSGINFO *msgInfo;
631 VMBUS_CHANNEL_MESSAGE_HEADER *requestHeader;
632 VMBUS_CHANNEL_INITIATE_CONTACT *initiate;
633 VMBUS_CHANNEL_VERSION_RESPONSE *versionResponse = (VMBUS_CHANNEL_VERSION_RESPONSE*)hdr;
dd0813b6 634 unsigned long flags;
3e7ee490
HJ
635
636 DPRINT_ENTER(VMBUS);
637
dd0813b6 638 spin_lock_irqsave(&gVmbusConnection.channelmsg_lock, flags);
3e7ee490
HJ
639
640 ITERATE_LIST_ENTRIES(anchor, curr, &gVmbusConnection.ChannelMsgList)
641 {
642 msgInfo = (VMBUS_CHANNEL_MSGINFO*) curr;
643 requestHeader = (VMBUS_CHANNEL_MESSAGE_HEADER*)msgInfo->Msg;
644
645 if (requestHeader->MessageType == ChannelMessageInitiateContact)
646 {
647 initiate = (VMBUS_CHANNEL_INITIATE_CONTACT*)requestHeader;
648 memcpy(&msgInfo->Response.VersionResponse, versionResponse, sizeof(VMBUS_CHANNEL_VERSION_RESPONSE));
bfc30aae 649 osd_WaitEventSet(msgInfo->WaitEvent);
3e7ee490
HJ
650 }
651 }
dd0813b6 652 spin_unlock_irqrestore(&gVmbusConnection.channelmsg_lock, flags);
3e7ee490
HJ
653
654 DPRINT_EXIT(VMBUS);
655}
656
657
658/*++
659
660Name:
661 VmbusOnChannelMessage()
662
663Description:
664 Handler for channel protocol messages.
665 This is invoked in the vmbus worker thread context.
666
667--*/
b239549c 668void VmbusOnChannelMessage(void *Context)
3e7ee490
HJ
669{
670 HV_MESSAGE *msg=(HV_MESSAGE*)Context;
671 VMBUS_CHANNEL_MESSAGE_HEADER* hdr;
672 int size;
673
674 DPRINT_ENTER(VMBUS);
675
676 hdr = (VMBUS_CHANNEL_MESSAGE_HEADER*)msg->u.Payload;
677 size=msg->Header.PayloadSize;
678
679 DPRINT_DBG(VMBUS, "message type %d size %d", hdr->MessageType, size);
680
681 if (hdr->MessageType >= ChannelMessageCount)
682 {
683 DPRINT_ERR(VMBUS, "Received invalid channel message type %d size %d", hdr->MessageType, size);
04f50c4d
GKH
684 print_hex_dump_bytes("", DUMP_PREFIX_NONE,
685 (unsigned char *)msg->u.Payload, size);
8c69f52a 686 kfree(msg);
3e7ee490
HJ
687 return;
688 }
689
690 if (gChannelMessageTable[hdr->MessageType].messageHandler)
691 {
692 gChannelMessageTable[hdr->MessageType].messageHandler(hdr);
693 }
694 else
695 {
696 DPRINT_ERR(VMBUS, "Unhandled channel message type %d", hdr->MessageType);
697 }
698
454f18a9 699 /* Free the msg that was allocated in VmbusOnMsgDPC() */
8c69f52a 700 kfree(msg);
3e7ee490
HJ
701 DPRINT_EXIT(VMBUS);
702}
703
704
705/*++
706
707Name:
708 VmbusChannelRequestOffers()
709
710Description:
711 Send a request to get all our pending offers.
712
713--*/
b239549c 714int VmbusChannelRequestOffers(void)
3e7ee490
HJ
715{
716 int ret=0;
717 VMBUS_CHANNEL_MESSAGE_HEADER* msg;
718 VMBUS_CHANNEL_MSGINFO* msgInfo;
719
720 DPRINT_ENTER(VMBUS);
721
e40d37cc 722 msgInfo = kmalloc(sizeof(VMBUS_CHANNEL_MSGINFO) + sizeof(VMBUS_CHANNEL_MESSAGE_HEADER), GFP_KERNEL);
3e7ee490
HJ
723 ASSERT(msgInfo != NULL);
724
bfc30aae 725 msgInfo->WaitEvent = osd_WaitEventCreate();
3e7ee490
HJ
726 msg = (VMBUS_CHANNEL_MESSAGE_HEADER*)msgInfo->Msg;
727
728 msg->MessageType = ChannelMessageRequestOffers;
729
730 /*SpinlockAcquire(gVmbusConnection.channelMsgLock);
731 INSERT_TAIL_LIST(&gVmbusConnection.channelMsgList, &msgInfo->msgListEntry);
732 SpinlockRelease(gVmbusConnection.channelMsgLock);*/
733
734 ret = VmbusPostMessage(msg, sizeof(VMBUS_CHANNEL_MESSAGE_HEADER));
735 if (ret != 0)
736 {
737 DPRINT_ERR(VMBUS, "Unable to request offers - %d", ret);
738
739 /*SpinlockAcquire(gVmbusConnection.channelMsgLock);
740 REMOVE_ENTRY_LIST(&msgInfo->msgListEntry);
741 SpinlockRelease(gVmbusConnection.channelMsgLock);*/
742
743 goto Cleanup;
744 }
bfc30aae 745 /* osd_WaitEventWait(msgInfo->waitEvent); */
3e7ee490
HJ
746
747 /*SpinlockAcquire(gVmbusConnection.channelMsgLock);
748 REMOVE_ENTRY_LIST(&msgInfo->msgListEntry);
749 SpinlockRelease(gVmbusConnection.channelMsgLock);*/
750
751
752Cleanup:
753 if (msgInfo)
754 {
420beac4 755 kfree(msgInfo->WaitEvent);
8c69f52a 756 kfree(msgInfo);
3e7ee490
HJ
757 }
758
759 DPRINT_EXIT(VMBUS);
760
761 return ret;
762}
763
764/*++
765
766Name:
767 VmbusChannelReleaseUnattachedChannels()
768
769Description:
770 Release channels that are unattached/unconnected ie (no drivers associated)
771
772--*/
b239549c 773void VmbusChannelReleaseUnattachedChannels(void)
3e7ee490
HJ
774{
775 LIST_ENTRY *entry;
776 VMBUS_CHANNEL *channel;
777 VMBUS_CHANNEL *start=NULL;
0f5e44ca 778 unsigned long flags;
3e7ee490 779
0f5e44ca 780 spin_lock_irqsave(&gVmbusConnection.channel_lock, flags);
3e7ee490
HJ
781
782 while (!IsListEmpty(&gVmbusConnection.ChannelList))
783 {
784 entry = TOP_LIST_ENTRY(&gVmbusConnection.ChannelList);
785 channel = CONTAINING_RECORD(entry, VMBUS_CHANNEL, ListEntry);
786
787 if (channel == start)
788 break;
789
790 if (!channel->DeviceObject->Driver)
791 {
792 REMOVE_ENTRY_LIST(&channel->ListEntry);
793 DPRINT_INFO(VMBUS, "Releasing unattached device object %p", channel->DeviceObject);
794
795 VmbusChildDeviceRemove(channel->DeviceObject);
796 FreeVmbusChannel(channel);
797 }
798 else
799 {
800 if (!start)
801 {
802 start = channel;
803 }
804 }
805 }
806
0f5e44ca 807 spin_unlock_irqrestore(&gVmbusConnection.channel_lock, flags);
3e7ee490
HJ
808}
809
454f18a9 810/* eof */