]> bbs.cooldavid.org Git - net-next-2.6.git/blame - drivers/staging/hv/ChannelMgmt.c
Staging: hv: osd: add osd_ prefix to global functions
[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 143
bfc30aae 144 channel->PollTimer = osd_TimerCreate(VmbusChannelOnTimer, channel);
3e7ee490
HJ
145 if (!channel->PollTimer)
146 {
8c69f52a 147 kfree(channel);
3e7ee490
HJ
148 return NULL;
149 }
150
454f18a9 151 /* channel->dataWorkQueue = WorkQueueCreate("data"); */
de65a384 152 channel->ControlWQ = create_workqueue("hv_vmbus_ctl");
3e7ee490
HJ
153 if (!channel->ControlWQ)
154 {
bfc30aae 155 osd_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);
de65a384 179 destroy_workqueue(channel->ControlWQ);
3e7ee490
HJ
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{
bfc30aae 198 osd_TimerClose(Channel->PollTimer);
3e7ee490 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. */
de65a384
BP
202 osd_schedule_callback(gVmbusConnection.WorkQueue, ReleaseVmbusChannel,
203 (void *)Channel);
3e7ee490
HJ
204}
205
206
207/*++
208
209Name:
210 VmbusChannelProcessOffer()
211
212Description:
213 Process the offer by creating a channel/device associated with this offer
214
215--*/
216static void
217VmbusChannelProcessOffer(
8282c400 218 void * context
3e7ee490
HJ
219 )
220{
221 int ret=0;
222 VMBUS_CHANNEL* newChannel=(VMBUS_CHANNEL*)context;
223 LIST_ENTRY* anchor;
224 LIST_ENTRY* curr;
0e727613 225 bool fNew = true;
3e7ee490 226 VMBUS_CHANNEL* channel;
0f5e44ca 227 unsigned long flags;
3e7ee490
HJ
228
229 DPRINT_ENTER(VMBUS);
230
454f18a9 231 /* Make sure this is a new offer */
0f5e44ca 232 spin_lock_irqsave(&gVmbusConnection.channel_lock, flags);
3e7ee490
HJ
233
234 ITERATE_LIST_ENTRIES(anchor, curr, &gVmbusConnection.ChannelList)
235 {
236 channel = CONTAINING_RECORD(curr, VMBUS_CHANNEL, ListEntry);
237
238 if (!memcmp(&channel->OfferMsg.Offer.InterfaceType, &newChannel->OfferMsg.Offer.InterfaceType,sizeof(GUID)) &&
239 !memcmp(&channel->OfferMsg.Offer.InterfaceInstance, &newChannel->OfferMsg.Offer.InterfaceInstance, sizeof(GUID)))
240 {
0e727613 241 fNew = false;
3e7ee490
HJ
242 break;
243 }
244 }
245
246 if (fNew)
247 {
248 INSERT_TAIL_LIST(&gVmbusConnection.ChannelList, &newChannel->ListEntry);
249 }
0f5e44ca 250 spin_unlock_irqrestore(&gVmbusConnection.channel_lock, flags);
3e7ee490
HJ
251
252 if (!fNew)
253 {
254 DPRINT_DBG(VMBUS, "Ignoring duplicate offer for relid (%d)", newChannel->OfferMsg.ChildRelId);
255 FreeVmbusChannel(newChannel);
256 DPRINT_EXIT(VMBUS);
257 return;
258 }
259
454f18a9
BP
260 /* Start the process of binding this offer to the driver */
261 /* We need to set the DeviceObject field before calling VmbusChildDeviceAdd() */
3e7ee490
HJ
262 newChannel->DeviceObject = VmbusChildDeviceCreate(
263 newChannel->OfferMsg.Offer.InterfaceType,
264 newChannel->OfferMsg.Offer.InterfaceInstance,
265 newChannel);
266
267 DPRINT_DBG(VMBUS, "child device object allocated - %p", newChannel->DeviceObject);
268
454f18a9
BP
269 /*
270 * Add the new device to the bus. This will kick off device-driver
271 * binding which eventually invokes the device driver's AddDevice()
272 * method.
273 */
274
3e7ee490
HJ
275 ret = VmbusChildDeviceAdd(newChannel->DeviceObject);
276 if (ret != 0)
277 {
278 DPRINT_ERR(VMBUS, "unable to add child device object (relid %d)",
279 newChannel->OfferMsg.ChildRelId);
280
0f5e44ca 281 spin_lock_irqsave(&gVmbusConnection.channel_lock, flags);
3e7ee490 282 REMOVE_ENTRY_LIST(&newChannel->ListEntry);
0f5e44ca 283 spin_unlock_irqrestore(&gVmbusConnection.channel_lock, flags);
3e7ee490
HJ
284
285 FreeVmbusChannel(newChannel);
286 }
287 else
288 {
454f18a9
BP
289 /*
290 * This state is used to indicate a successful open
291 * so that when we do close the channel normally, we
292 * can cleanup properly
293 */
3e7ee490
HJ
294 newChannel->State = CHANNEL_OPEN_STATE;
295 }
296 DPRINT_EXIT(VMBUS);
297}
298
299/*++
300
301Name:
302 VmbusChannelProcessRescindOffer()
303
304Description:
305 Rescind the offer by initiating a device removal
306
307--*/
308static void
309VmbusChannelProcessRescindOffer(
8282c400 310 void * context
3e7ee490
HJ
311 )
312{
313 VMBUS_CHANNEL* channel=(VMBUS_CHANNEL*)context;
314
315 DPRINT_ENTER(VMBUS);
316
317 VmbusChildDeviceRemove(channel->DeviceObject);
318
319 DPRINT_EXIT(VMBUS);
320}
321
322
323/*++
324
325Name:
326 VmbusChannelOnOffer()
327
328Description:
329 Handler for channel offers from vmbus in parent partition. We ignore all offers except
330 network and storage offers. For each network and storage offers, we create a channel object
331 and queue a work item to the channel object to process the offer synchronously
332
333--*/
334static void
335VmbusChannelOnOffer(
336 PVMBUS_CHANNEL_MESSAGE_HEADER hdr
337 )
338{
339 VMBUS_CHANNEL_OFFER_CHANNEL* offer = (VMBUS_CHANNEL_OFFER_CHANNEL*)hdr;
340 VMBUS_CHANNEL* newChannel;
341
342 GUID *guidType;
343 GUID *guidInstance;
344 int i;
345 int fSupported=0;
346
347 DPRINT_ENTER(VMBUS);
348
349 for (i=0; i<MAX_NUM_DEVICE_CLASSES_SUPPORTED; i++)
350 {
351 if (memcmp(&offer->Offer.InterfaceType, &gSupportedDeviceClasses[i], sizeof(GUID)) == 0)
352 {
353 fSupported = 1;
354 break;
355 }
356 }
357
358 if (!fSupported)
359 {
360 DPRINT_DBG(VMBUS, "Ignoring channel offer notification for child relid %d", offer->ChildRelId);
361 DPRINT_EXIT(VMBUS);
362
363 return;
364 }
365
366 guidType = &offer->Offer.InterfaceType;
367 guidInstance = &offer->Offer.InterfaceInstance;
368
369 DPRINT_INFO(VMBUS, "Channel offer notification - child relid %d monitor id %d allocated %d, "
370 "type {%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x%02x%02x} "
371 "instance {%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x%02x%02x}",
372 offer->ChildRelId,
373 offer->MonitorId,
374 offer->MonitorAllocated,
375 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],
376 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]);
377
454f18a9 378 /* Allocate the channel object and save this offer. */
3e7ee490
HJ
379 newChannel = AllocVmbusChannel();
380 if (!newChannel)
381 {
382 DPRINT_ERR(VMBUS, "unable to allocate channel object");
383 return;
384 }
385
386 DPRINT_DBG(VMBUS, "channel object allocated - %p", newChannel);
387
388 memcpy(&newChannel->OfferMsg, offer, sizeof(VMBUS_CHANNEL_OFFER_CHANNEL));
5654e932
GKH
389 newChannel->MonitorGroup = (u8)offer->MonitorId / 32;
390 newChannel->MonitorBit = (u8)offer->MonitorId % 32;
3e7ee490 391
454f18a9 392 /* TODO: Make sure the offer comes from our parent partition */
de65a384
BP
393 osd_schedule_callback(newChannel->ControlWQ, VmbusChannelProcessOffer,
394 newChannel);
3e7ee490
HJ
395
396 DPRINT_EXIT(VMBUS);
397}
398
399
400/*++
401
402Name:
403 VmbusChannelOnOfferRescind()
404
405Description:
406 Rescind offer handler. We queue a work item to process this offer
407 synchronously
408
409--*/
410static void
411VmbusChannelOnOfferRescind(
412 PVMBUS_CHANNEL_MESSAGE_HEADER hdr
413 )
414{
415 VMBUS_CHANNEL_RESCIND_OFFER* rescind = (VMBUS_CHANNEL_RESCIND_OFFER*)hdr;
416 VMBUS_CHANNEL* channel;
417
418 DPRINT_ENTER(VMBUS);
419
420 channel = GetChannelFromRelId(rescind->ChildRelId);
421 if (channel == NULL)
422 {
423 DPRINT_DBG(VMBUS, "channel not found for relId %d", rescind->ChildRelId);
424 return;
425 }
426
de65a384
BP
427 osd_schedule_callback(channel->ControlWQ,
428 VmbusChannelProcessRescindOffer,
429 channel);
3e7ee490
HJ
430
431 DPRINT_EXIT(VMBUS);
432}
433
434
435/*++
436
437Name:
438 VmbusChannelOnOffersDelivered()
439
440Description:
441 This is invoked when all offers have been delivered.
442 Nothing to do here.
443
444--*/
445static void
446VmbusChannelOnOffersDelivered(
447 PVMBUS_CHANNEL_MESSAGE_HEADER hdr
448 )
449{
450 DPRINT_ENTER(VMBUS);
451 DPRINT_EXIT(VMBUS);
452}
453
454
455/*++
456
457Name:
458 VmbusChannelOnOpenResult()
459
460Description:
461 Open result handler. This is invoked when we received a response
462 to our channel open request. Find the matching request, copy the
463 response and signal the requesting thread.
464
465--*/
466static void
467VmbusChannelOnOpenResult(
468 PVMBUS_CHANNEL_MESSAGE_HEADER hdr
469 )
470{
471 VMBUS_CHANNEL_OPEN_RESULT* result = (VMBUS_CHANNEL_OPEN_RESULT*)hdr;
472 LIST_ENTRY* anchor;
473 LIST_ENTRY* curr;
474 VMBUS_CHANNEL_MSGINFO* msgInfo;
475 VMBUS_CHANNEL_MESSAGE_HEADER* requestHeader;
476 VMBUS_CHANNEL_OPEN_CHANNEL* openMsg;
dd0813b6 477 unsigned long flags;
3e7ee490
HJ
478
479 DPRINT_ENTER(VMBUS);
480
481 DPRINT_DBG(VMBUS, "vmbus open result - %d", result->Status);
482
454f18a9 483 /* Find the open msg, copy the result and signal/unblock the wait event */
dd0813b6 484 spin_lock_irqsave(&gVmbusConnection.channelmsg_lock, flags);
3e7ee490
HJ
485
486 ITERATE_LIST_ENTRIES(anchor, curr, &gVmbusConnection.ChannelMsgList)
487 {
488 msgInfo = (VMBUS_CHANNEL_MSGINFO*) curr;
489 requestHeader = (VMBUS_CHANNEL_MESSAGE_HEADER*)msgInfo->Msg;
490
491 if (requestHeader->MessageType == ChannelMessageOpenChannel)
492 {
493 openMsg = (VMBUS_CHANNEL_OPEN_CHANNEL*)msgInfo->Msg;
494 if (openMsg->ChildRelId == result->ChildRelId &&
495 openMsg->OpenId == result->OpenId)
496 {
497 memcpy(&msgInfo->Response.OpenResult, result, sizeof(VMBUS_CHANNEL_OPEN_RESULT));
bfc30aae 498 osd_WaitEventSet(msgInfo->WaitEvent);
3e7ee490
HJ
499 break;
500 }
501 }
502 }
dd0813b6 503 spin_unlock_irqrestore(&gVmbusConnection.channelmsg_lock, flags);
3e7ee490
HJ
504
505 DPRINT_EXIT(VMBUS);
506}
507
508
509/*++
510
511Name:
512 VmbusChannelOnGpadlCreated()
513
514Description:
515 GPADL created handler. This is invoked when we received a response
516 to our gpadl create request. Find the matching request, copy the
517 response and signal the requesting thread.
518
519--*/
520static void
521VmbusChannelOnGpadlCreated(
522 PVMBUS_CHANNEL_MESSAGE_HEADER hdr
523 )
524{
525 VMBUS_CHANNEL_GPADL_CREATED *gpadlCreated = (VMBUS_CHANNEL_GPADL_CREATED*)hdr;
526 LIST_ENTRY *anchor;
527 LIST_ENTRY *curr;
528 VMBUS_CHANNEL_MSGINFO *msgInfo;
529 VMBUS_CHANNEL_MESSAGE_HEADER *requestHeader;
530 VMBUS_CHANNEL_GPADL_HEADER *gpadlHeader;
dd0813b6 531 unsigned long flags;
3e7ee490
HJ
532
533 DPRINT_ENTER(VMBUS);
534
535 DPRINT_DBG(VMBUS, "vmbus gpadl created result - %d", gpadlCreated->CreationStatus);
536
454f18a9 537 /* Find the establish msg, copy the result and signal/unblock the wait event */
dd0813b6 538 spin_lock_irqsave(&gVmbusConnection.channelmsg_lock, flags);
3e7ee490
HJ
539
540 ITERATE_LIST_ENTRIES(anchor, curr, &gVmbusConnection.ChannelMsgList)
541 {
542 msgInfo = (VMBUS_CHANNEL_MSGINFO*) curr;
543 requestHeader = (VMBUS_CHANNEL_MESSAGE_HEADER*)msgInfo->Msg;
544
545 if (requestHeader->MessageType == ChannelMessageGpadlHeader)
546 {
547 gpadlHeader = (VMBUS_CHANNEL_GPADL_HEADER*)requestHeader;
548
549 if ((gpadlCreated->ChildRelId == gpadlHeader->ChildRelId) &&
550 (gpadlCreated->Gpadl == gpadlHeader->Gpadl))
551 {
552 memcpy(&msgInfo->Response.GpadlCreated, gpadlCreated, sizeof(VMBUS_CHANNEL_GPADL_CREATED));
bfc30aae 553 osd_WaitEventSet(msgInfo->WaitEvent);
3e7ee490
HJ
554 break;
555 }
556 }
557 }
dd0813b6 558 spin_unlock_irqrestore(&gVmbusConnection.channelmsg_lock, flags);
3e7ee490
HJ
559
560 DPRINT_EXIT(VMBUS);
561}
562
563
564/*++
565
566Name:
567 VmbusChannelOnGpadlTorndown()
568
569Description:
570 GPADL torndown handler. This is invoked when we received a response
571 to our gpadl teardown request. Find the matching request, copy the
572 response and signal the requesting thread.
573
574--*/
575static void
576VmbusChannelOnGpadlTorndown(
577 PVMBUS_CHANNEL_MESSAGE_HEADER hdr
578 )
579{
580 VMBUS_CHANNEL_GPADL_TORNDOWN* gpadlTorndown = (VMBUS_CHANNEL_GPADL_TORNDOWN*)hdr;
581 LIST_ENTRY* anchor;
582 LIST_ENTRY* curr;
583 VMBUS_CHANNEL_MSGINFO* msgInfo;
584 VMBUS_CHANNEL_MESSAGE_HEADER *requestHeader;
585 VMBUS_CHANNEL_GPADL_TEARDOWN *gpadlTeardown;
dd0813b6 586 unsigned long flags;
3e7ee490
HJ
587
588 DPRINT_ENTER(VMBUS);
589
454f18a9 590 /* Find the open msg, copy the result and signal/unblock the wait event */
dd0813b6 591 spin_lock_irqsave(&gVmbusConnection.channelmsg_lock, flags);
3e7ee490
HJ
592
593 ITERATE_LIST_ENTRIES(anchor, curr, &gVmbusConnection.ChannelMsgList)
594 {
595 msgInfo = (VMBUS_CHANNEL_MSGINFO*) curr;
596 requestHeader = (VMBUS_CHANNEL_MESSAGE_HEADER*)msgInfo->Msg;
597
598 if (requestHeader->MessageType == ChannelMessageGpadlTeardown)
599 {
600 gpadlTeardown = (VMBUS_CHANNEL_GPADL_TEARDOWN*)requestHeader;
601
602 if (gpadlTorndown->Gpadl == gpadlTeardown->Gpadl)
603 {
604 memcpy(&msgInfo->Response.GpadlTorndown, gpadlTorndown, sizeof(VMBUS_CHANNEL_GPADL_TORNDOWN));
bfc30aae 605 osd_WaitEventSet(msgInfo->WaitEvent);
3e7ee490
HJ
606 break;
607 }
608 }
609 }
dd0813b6 610 spin_unlock_irqrestore(&gVmbusConnection.channelmsg_lock, flags);
3e7ee490
HJ
611
612 DPRINT_EXIT(VMBUS);
613}
614
615
616/*++
617
618Name:
619 VmbusChannelOnVersionResponse()
620
621Description:
622 Version response handler. This is invoked when we received a response
623 to our initiate contact request. Find the matching request, copy the
624 response and signal the requesting thread.
625
626--*/
627static void
628VmbusChannelOnVersionResponse(
629 PVMBUS_CHANNEL_MESSAGE_HEADER hdr
630 )
631{
632 LIST_ENTRY* anchor;
633 LIST_ENTRY* curr;
634 VMBUS_CHANNEL_MSGINFO *msgInfo;
635 VMBUS_CHANNEL_MESSAGE_HEADER *requestHeader;
636 VMBUS_CHANNEL_INITIATE_CONTACT *initiate;
637 VMBUS_CHANNEL_VERSION_RESPONSE *versionResponse = (VMBUS_CHANNEL_VERSION_RESPONSE*)hdr;
dd0813b6 638 unsigned long flags;
3e7ee490
HJ
639
640 DPRINT_ENTER(VMBUS);
641
dd0813b6 642 spin_lock_irqsave(&gVmbusConnection.channelmsg_lock, flags);
3e7ee490
HJ
643
644 ITERATE_LIST_ENTRIES(anchor, curr, &gVmbusConnection.ChannelMsgList)
645 {
646 msgInfo = (VMBUS_CHANNEL_MSGINFO*) curr;
647 requestHeader = (VMBUS_CHANNEL_MESSAGE_HEADER*)msgInfo->Msg;
648
649 if (requestHeader->MessageType == ChannelMessageInitiateContact)
650 {
651 initiate = (VMBUS_CHANNEL_INITIATE_CONTACT*)requestHeader;
652 memcpy(&msgInfo->Response.VersionResponse, versionResponse, sizeof(VMBUS_CHANNEL_VERSION_RESPONSE));
bfc30aae 653 osd_WaitEventSet(msgInfo->WaitEvent);
3e7ee490
HJ
654 }
655 }
dd0813b6 656 spin_unlock_irqrestore(&gVmbusConnection.channelmsg_lock, flags);
3e7ee490
HJ
657
658 DPRINT_EXIT(VMBUS);
659}
660
661
662/*++
663
664Name:
665 VmbusOnChannelMessage()
666
667Description:
668 Handler for channel protocol messages.
669 This is invoked in the vmbus worker thread context.
670
671--*/
bd1de709 672static void
3e7ee490
HJ
673VmbusOnChannelMessage(
674 void *Context
675 )
676{
677 HV_MESSAGE *msg=(HV_MESSAGE*)Context;
678 VMBUS_CHANNEL_MESSAGE_HEADER* hdr;
679 int size;
680
681 DPRINT_ENTER(VMBUS);
682
683 hdr = (VMBUS_CHANNEL_MESSAGE_HEADER*)msg->u.Payload;
684 size=msg->Header.PayloadSize;
685
686 DPRINT_DBG(VMBUS, "message type %d size %d", hdr->MessageType, size);
687
688 if (hdr->MessageType >= ChannelMessageCount)
689 {
690 DPRINT_ERR(VMBUS, "Received invalid channel message type %d size %d", hdr->MessageType, size);
04f50c4d
GKH
691 print_hex_dump_bytes("", DUMP_PREFIX_NONE,
692 (unsigned char *)msg->u.Payload, size);
8c69f52a 693 kfree(msg);
3e7ee490
HJ
694 return;
695 }
696
697 if (gChannelMessageTable[hdr->MessageType].messageHandler)
698 {
699 gChannelMessageTable[hdr->MessageType].messageHandler(hdr);
700 }
701 else
702 {
703 DPRINT_ERR(VMBUS, "Unhandled channel message type %d", hdr->MessageType);
704 }
705
454f18a9 706 /* Free the msg that was allocated in VmbusOnMsgDPC() */
8c69f52a 707 kfree(msg);
3e7ee490
HJ
708 DPRINT_EXIT(VMBUS);
709}
710
711
712/*++
713
714Name:
715 VmbusChannelRequestOffers()
716
717Description:
718 Send a request to get all our pending offers.
719
720--*/
bd1de709 721static int
3e7ee490 722VmbusChannelRequestOffers(
e20f683b 723 void
3e7ee490
HJ
724 )
725{
726 int ret=0;
727 VMBUS_CHANNEL_MESSAGE_HEADER* msg;
728 VMBUS_CHANNEL_MSGINFO* msgInfo;
729
730 DPRINT_ENTER(VMBUS);
731
e40d37cc 732 msgInfo = kmalloc(sizeof(VMBUS_CHANNEL_MSGINFO) + sizeof(VMBUS_CHANNEL_MESSAGE_HEADER), GFP_KERNEL);
3e7ee490
HJ
733 ASSERT(msgInfo != NULL);
734
bfc30aae 735 msgInfo->WaitEvent = osd_WaitEventCreate();
3e7ee490
HJ
736 msg = (VMBUS_CHANNEL_MESSAGE_HEADER*)msgInfo->Msg;
737
738 msg->MessageType = ChannelMessageRequestOffers;
739
740 /*SpinlockAcquire(gVmbusConnection.channelMsgLock);
741 INSERT_TAIL_LIST(&gVmbusConnection.channelMsgList, &msgInfo->msgListEntry);
742 SpinlockRelease(gVmbusConnection.channelMsgLock);*/
743
744 ret = VmbusPostMessage(msg, sizeof(VMBUS_CHANNEL_MESSAGE_HEADER));
745 if (ret != 0)
746 {
747 DPRINT_ERR(VMBUS, "Unable to request offers - %d", ret);
748
749 /*SpinlockAcquire(gVmbusConnection.channelMsgLock);
750 REMOVE_ENTRY_LIST(&msgInfo->msgListEntry);
751 SpinlockRelease(gVmbusConnection.channelMsgLock);*/
752
753 goto Cleanup;
754 }
bfc30aae 755 /* osd_WaitEventWait(msgInfo->waitEvent); */
3e7ee490
HJ
756
757 /*SpinlockAcquire(gVmbusConnection.channelMsgLock);
758 REMOVE_ENTRY_LIST(&msgInfo->msgListEntry);
759 SpinlockRelease(gVmbusConnection.channelMsgLock);*/
760
761
762Cleanup:
763 if (msgInfo)
764 {
420beac4 765 kfree(msgInfo->WaitEvent);
8c69f52a 766 kfree(msgInfo);
3e7ee490
HJ
767 }
768
769 DPRINT_EXIT(VMBUS);
770
771 return ret;
772}
773
774/*++
775
776Name:
777 VmbusChannelReleaseUnattachedChannels()
778
779Description:
780 Release channels that are unattached/unconnected ie (no drivers associated)
781
782--*/
bd1de709 783static void
3e7ee490 784VmbusChannelReleaseUnattachedChannels(
e20f683b 785 void
3e7ee490
HJ
786 )
787{
788 LIST_ENTRY *entry;
789 VMBUS_CHANNEL *channel;
790 VMBUS_CHANNEL *start=NULL;
0f5e44ca 791 unsigned long flags;
3e7ee490 792
0f5e44ca 793 spin_lock_irqsave(&gVmbusConnection.channel_lock, flags);
3e7ee490
HJ
794
795 while (!IsListEmpty(&gVmbusConnection.ChannelList))
796 {
797 entry = TOP_LIST_ENTRY(&gVmbusConnection.ChannelList);
798 channel = CONTAINING_RECORD(entry, VMBUS_CHANNEL, ListEntry);
799
800 if (channel == start)
801 break;
802
803 if (!channel->DeviceObject->Driver)
804 {
805 REMOVE_ENTRY_LIST(&channel->ListEntry);
806 DPRINT_INFO(VMBUS, "Releasing unattached device object %p", channel->DeviceObject);
807
808 VmbusChildDeviceRemove(channel->DeviceObject);
809 FreeVmbusChannel(channel);
810 }
811 else
812 {
813 if (!start)
814 {
815 start = channel;
816 }
817 }
818 }
819
0f5e44ca 820 spin_unlock_irqrestore(&gVmbusConnection.channel_lock, flags);
3e7ee490
HJ
821}
822
454f18a9 823/* eof */