]> bbs.cooldavid.org Git - net-next-2.6.git/blame - drivers/staging/hv/ChannelMgmt.c
Staging: hv: fix sparse NULL pointer warnings
[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--*/
bd1de709 132static VMBUS_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
HJ
143
144 channel->PollTimer = TimerCreate(VmbusChannelOnTimer, channel);
145 if (!channel->PollTimer)
146 {
8c69f52a 147 kfree(channel);
3e7ee490
HJ
148 return NULL;
149 }
150
454f18a9 151 /* channel->dataWorkQueue = WorkQueueCreate("data"); */
3e7ee490
HJ
152 channel->ControlWQ = WorkQueueCreate("control");
153 if (!channel->ControlWQ)
154 {
155 TimerClose(channel->PollTimer);
8c69f52a 156 kfree(channel);
3e7ee490
HJ
157 return NULL;
158 }
159
160 return channel;
161}
162
163/*++
164
165Name:
166 ReleaseVmbusChannel()
167
168Description:
169 Release the vmbus channel object itself
170
171--*/
172static inline void ReleaseVmbusChannel(void* Context)
173{
174 VMBUS_CHANNEL* channel = (VMBUS_CHANNEL*)Context;
175
176 DPRINT_ENTER(VMBUS);
177
178 DPRINT_DBG(VMBUS, "releasing channel (%p)", channel);
179 WorkQueueClose(channel->ControlWQ);
180 DPRINT_DBG(VMBUS, "channel released (%p)", channel);
181
8c69f52a 182 kfree(channel);
3e7ee490
HJ
183
184 DPRINT_EXIT(VMBUS);
185}
186
187/*++
188
189Name:
190 FreeVmbusChannel()
191
192Description:
193 Release the resources used by the vmbus channel object
194
195--*/
bd1de709 196static void FreeVmbusChannel(VMBUS_CHANNEL* Channel)
3e7ee490 197{
3e7ee490
HJ
198 TimerClose(Channel->PollTimer);
199
454f18a9
BP
200 /* We have to release the channel's workqueue/thread in the vmbus's workqueue/thread context */
201 /* ie we can't destroy ourselves. */
3e7ee490
HJ
202 WorkQueueQueueWorkItem(gVmbusConnection.WorkQueue, ReleaseVmbusChannel, (void*)Channel);
203}
204
205
206/*++
207
208Name:
209 VmbusChannelProcessOffer()
210
211Description:
212 Process the offer by creating a channel/device associated with this offer
213
214--*/
215static void
216VmbusChannelProcessOffer(
8282c400 217 void * context
3e7ee490
HJ
218 )
219{
220 int ret=0;
221 VMBUS_CHANNEL* newChannel=(VMBUS_CHANNEL*)context;
222 LIST_ENTRY* anchor;
223 LIST_ENTRY* curr;
0e727613 224 bool fNew = true;
3e7ee490 225 VMBUS_CHANNEL* channel;
0f5e44ca 226 unsigned long flags;
3e7ee490
HJ
227
228 DPRINT_ENTER(VMBUS);
229
454f18a9 230 /* Make sure this is a new offer */
0f5e44ca 231 spin_lock_irqsave(&gVmbusConnection.channel_lock, flags);
3e7ee490
HJ
232
233 ITERATE_LIST_ENTRIES(anchor, curr, &gVmbusConnection.ChannelList)
234 {
235 channel = CONTAINING_RECORD(curr, VMBUS_CHANNEL, ListEntry);
236
237 if (!memcmp(&channel->OfferMsg.Offer.InterfaceType, &newChannel->OfferMsg.Offer.InterfaceType,sizeof(GUID)) &&
238 !memcmp(&channel->OfferMsg.Offer.InterfaceInstance, &newChannel->OfferMsg.Offer.InterfaceInstance, sizeof(GUID)))
239 {
0e727613 240 fNew = false;
3e7ee490
HJ
241 break;
242 }
243 }
244
245 if (fNew)
246 {
247 INSERT_TAIL_LIST(&gVmbusConnection.ChannelList, &newChannel->ListEntry);
248 }
0f5e44ca 249 spin_unlock_irqrestore(&gVmbusConnection.channel_lock, flags);
3e7ee490
HJ
250
251 if (!fNew)
252 {
253 DPRINT_DBG(VMBUS, "Ignoring duplicate offer for relid (%d)", newChannel->OfferMsg.ChildRelId);
254 FreeVmbusChannel(newChannel);
255 DPRINT_EXIT(VMBUS);
256 return;
257 }
258
454f18a9
BP
259 /* Start the process of binding this offer to the driver */
260 /* We need to set the DeviceObject field before calling VmbusChildDeviceAdd() */
3e7ee490
HJ
261 newChannel->DeviceObject = VmbusChildDeviceCreate(
262 newChannel->OfferMsg.Offer.InterfaceType,
263 newChannel->OfferMsg.Offer.InterfaceInstance,
264 newChannel);
265
266 DPRINT_DBG(VMBUS, "child device object allocated - %p", newChannel->DeviceObject);
267
454f18a9
BP
268 /*
269 * Add the new device to the bus. This will kick off device-driver
270 * binding which eventually invokes the device driver's AddDevice()
271 * method.
272 */
273
3e7ee490
HJ
274 ret = VmbusChildDeviceAdd(newChannel->DeviceObject);
275 if (ret != 0)
276 {
277 DPRINT_ERR(VMBUS, "unable to add child device object (relid %d)",
278 newChannel->OfferMsg.ChildRelId);
279
0f5e44ca 280 spin_lock_irqsave(&gVmbusConnection.channel_lock, flags);
3e7ee490 281 REMOVE_ENTRY_LIST(&newChannel->ListEntry);
0f5e44ca 282 spin_unlock_irqrestore(&gVmbusConnection.channel_lock, flags);
3e7ee490
HJ
283
284 FreeVmbusChannel(newChannel);
285 }
286 else
287 {
454f18a9
BP
288 /*
289 * This state is used to indicate a successful open
290 * so that when we do close the channel normally, we
291 * can cleanup properly
292 */
3e7ee490
HJ
293 newChannel->State = CHANNEL_OPEN_STATE;
294 }
295 DPRINT_EXIT(VMBUS);
296}
297
298/*++
299
300Name:
301 VmbusChannelProcessRescindOffer()
302
303Description:
304 Rescind the offer by initiating a device removal
305
306--*/
307static void
308VmbusChannelProcessRescindOffer(
8282c400 309 void * context
3e7ee490
HJ
310 )
311{
312 VMBUS_CHANNEL* channel=(VMBUS_CHANNEL*)context;
313
314 DPRINT_ENTER(VMBUS);
315
316 VmbusChildDeviceRemove(channel->DeviceObject);
317
318 DPRINT_EXIT(VMBUS);
319}
320
321
322/*++
323
324Name:
325 VmbusChannelOnOffer()
326
327Description:
328 Handler for channel offers from vmbus in parent partition. We ignore all offers except
329 network and storage offers. For each network and storage offers, we create a channel object
330 and queue a work item to the channel object to process the offer synchronously
331
332--*/
333static void
334VmbusChannelOnOffer(
335 PVMBUS_CHANNEL_MESSAGE_HEADER hdr
336 )
337{
338 VMBUS_CHANNEL_OFFER_CHANNEL* offer = (VMBUS_CHANNEL_OFFER_CHANNEL*)hdr;
339 VMBUS_CHANNEL* newChannel;
340
341 GUID *guidType;
342 GUID *guidInstance;
343 int i;
344 int fSupported=0;
345
346 DPRINT_ENTER(VMBUS);
347
348 for (i=0; i<MAX_NUM_DEVICE_CLASSES_SUPPORTED; i++)
349 {
350 if (memcmp(&offer->Offer.InterfaceType, &gSupportedDeviceClasses[i], sizeof(GUID)) == 0)
351 {
352 fSupported = 1;
353 break;
354 }
355 }
356
357 if (!fSupported)
358 {
359 DPRINT_DBG(VMBUS, "Ignoring channel offer notification for child relid %d", offer->ChildRelId);
360 DPRINT_EXIT(VMBUS);
361
362 return;
363 }
364
365 guidType = &offer->Offer.InterfaceType;
366 guidInstance = &offer->Offer.InterfaceInstance;
367
368 DPRINT_INFO(VMBUS, "Channel offer notification - child relid %d monitor id %d allocated %d, "
369 "type {%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x%02x%02x} "
370 "instance {%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x%02x%02x}",
371 offer->ChildRelId,
372 offer->MonitorId,
373 offer->MonitorAllocated,
374 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],
375 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]);
376
454f18a9 377 /* Allocate the channel object and save this offer. */
3e7ee490
HJ
378 newChannel = AllocVmbusChannel();
379 if (!newChannel)
380 {
381 DPRINT_ERR(VMBUS, "unable to allocate channel object");
382 return;
383 }
384
385 DPRINT_DBG(VMBUS, "channel object allocated - %p", newChannel);
386
387 memcpy(&newChannel->OfferMsg, offer, sizeof(VMBUS_CHANNEL_OFFER_CHANNEL));
5654e932
GKH
388 newChannel->MonitorGroup = (u8)offer->MonitorId / 32;
389 newChannel->MonitorBit = (u8)offer->MonitorId % 32;
3e7ee490 390
454f18a9 391 /* TODO: Make sure the offer comes from our parent partition */
3e7ee490
HJ
392 WorkQueueQueueWorkItem(newChannel->ControlWQ, VmbusChannelProcessOffer, newChannel);
393
394 DPRINT_EXIT(VMBUS);
395}
396
397
398/*++
399
400Name:
401 VmbusChannelOnOfferRescind()
402
403Description:
404 Rescind offer handler. We queue a work item to process this offer
405 synchronously
406
407--*/
408static void
409VmbusChannelOnOfferRescind(
410 PVMBUS_CHANNEL_MESSAGE_HEADER hdr
411 )
412{
413 VMBUS_CHANNEL_RESCIND_OFFER* rescind = (VMBUS_CHANNEL_RESCIND_OFFER*)hdr;
414 VMBUS_CHANNEL* channel;
415
416 DPRINT_ENTER(VMBUS);
417
418 channel = GetChannelFromRelId(rescind->ChildRelId);
419 if (channel == NULL)
420 {
421 DPRINT_DBG(VMBUS, "channel not found for relId %d", rescind->ChildRelId);
422 return;
423 }
424
425 WorkQueueQueueWorkItem(channel->ControlWQ, VmbusChannelProcessRescindOffer, channel);
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));
494 WaitEventSet(msgInfo->WaitEvent);
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));
549 WaitEventSet(msgInfo->WaitEvent);
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));
601 WaitEventSet(msgInfo->WaitEvent);
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));
649 WaitEventSet(msgInfo->WaitEvent);
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--*/
bd1de709 668static void
3e7ee490
HJ
669VmbusOnChannelMessage(
670 void *Context
671 )
672{
673 HV_MESSAGE *msg=(HV_MESSAGE*)Context;
674 VMBUS_CHANNEL_MESSAGE_HEADER* hdr;
675 int size;
676
677 DPRINT_ENTER(VMBUS);
678
679 hdr = (VMBUS_CHANNEL_MESSAGE_HEADER*)msg->u.Payload;
680 size=msg->Header.PayloadSize;
681
682 DPRINT_DBG(VMBUS, "message type %d size %d", hdr->MessageType, size);
683
684 if (hdr->MessageType >= ChannelMessageCount)
685 {
686 DPRINT_ERR(VMBUS, "Received invalid channel message type %d size %d", hdr->MessageType, size);
04f50c4d
GKH
687 print_hex_dump_bytes("", DUMP_PREFIX_NONE,
688 (unsigned char *)msg->u.Payload, size);
8c69f52a 689 kfree(msg);
3e7ee490
HJ
690 return;
691 }
692
693 if (gChannelMessageTable[hdr->MessageType].messageHandler)
694 {
695 gChannelMessageTable[hdr->MessageType].messageHandler(hdr);
696 }
697 else
698 {
699 DPRINT_ERR(VMBUS, "Unhandled channel message type %d", hdr->MessageType);
700 }
701
454f18a9 702 /* Free the msg that was allocated in VmbusOnMsgDPC() */
8c69f52a 703 kfree(msg);
3e7ee490
HJ
704 DPRINT_EXIT(VMBUS);
705}
706
707
708/*++
709
710Name:
711 VmbusChannelRequestOffers()
712
713Description:
714 Send a request to get all our pending offers.
715
716--*/
bd1de709 717static int
3e7ee490 718VmbusChannelRequestOffers(
e20f683b 719 void
3e7ee490
HJ
720 )
721{
722 int ret=0;
723 VMBUS_CHANNEL_MESSAGE_HEADER* msg;
724 VMBUS_CHANNEL_MSGINFO* msgInfo;
725
726 DPRINT_ENTER(VMBUS);
727
e40d37cc 728 msgInfo = kmalloc(sizeof(VMBUS_CHANNEL_MSGINFO) + sizeof(VMBUS_CHANNEL_MESSAGE_HEADER), GFP_KERNEL);
3e7ee490
HJ
729 ASSERT(msgInfo != NULL);
730
731 msgInfo->WaitEvent = WaitEventCreate();
732 msg = (VMBUS_CHANNEL_MESSAGE_HEADER*)msgInfo->Msg;
733
734 msg->MessageType = ChannelMessageRequestOffers;
735
736 /*SpinlockAcquire(gVmbusConnection.channelMsgLock);
737 INSERT_TAIL_LIST(&gVmbusConnection.channelMsgList, &msgInfo->msgListEntry);
738 SpinlockRelease(gVmbusConnection.channelMsgLock);*/
739
740 ret = VmbusPostMessage(msg, sizeof(VMBUS_CHANNEL_MESSAGE_HEADER));
741 if (ret != 0)
742 {
743 DPRINT_ERR(VMBUS, "Unable to request offers - %d", ret);
744
745 /*SpinlockAcquire(gVmbusConnection.channelMsgLock);
746 REMOVE_ENTRY_LIST(&msgInfo->msgListEntry);
747 SpinlockRelease(gVmbusConnection.channelMsgLock);*/
748
749 goto Cleanup;
750 }
454f18a9 751 /* WaitEventWait(msgInfo->waitEvent); */
3e7ee490
HJ
752
753 /*SpinlockAcquire(gVmbusConnection.channelMsgLock);
754 REMOVE_ENTRY_LIST(&msgInfo->msgListEntry);
755 SpinlockRelease(gVmbusConnection.channelMsgLock);*/
756
757
758Cleanup:
759 if (msgInfo)
760 {
761 WaitEventClose(msgInfo->WaitEvent);
8c69f52a 762 kfree(msgInfo);
3e7ee490
HJ
763 }
764
765 DPRINT_EXIT(VMBUS);
766
767 return ret;
768}
769
770/*++
771
772Name:
773 VmbusChannelReleaseUnattachedChannels()
774
775Description:
776 Release channels that are unattached/unconnected ie (no drivers associated)
777
778--*/
bd1de709 779static void
3e7ee490 780VmbusChannelReleaseUnattachedChannels(
e20f683b 781 void
3e7ee490
HJ
782 )
783{
784 LIST_ENTRY *entry;
785 VMBUS_CHANNEL *channel;
786 VMBUS_CHANNEL *start=NULL;
0f5e44ca 787 unsigned long flags;
3e7ee490 788
0f5e44ca 789 spin_lock_irqsave(&gVmbusConnection.channel_lock, flags);
3e7ee490
HJ
790
791 while (!IsListEmpty(&gVmbusConnection.ChannelList))
792 {
793 entry = TOP_LIST_ENTRY(&gVmbusConnection.ChannelList);
794 channel = CONTAINING_RECORD(entry, VMBUS_CHANNEL, ListEntry);
795
796 if (channel == start)
797 break;
798
799 if (!channel->DeviceObject->Driver)
800 {
801 REMOVE_ENTRY_LIST(&channel->ListEntry);
802 DPRINT_INFO(VMBUS, "Releasing unattached device object %p", channel->DeviceObject);
803
804 VmbusChildDeviceRemove(channel->DeviceObject);
805 FreeVmbusChannel(channel);
806 }
807 else
808 {
809 if (!start)
810 {
811 start = channel;
812 }
813 }
814 }
815
0f5e44ca 816 spin_unlock_irqrestore(&gVmbusConnection.channel_lock, flags);
3e7ee490
HJ
817}
818
454f18a9 819/* eof */