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