bc0393a41d29bf8e230cebc073b72db6d2e7172e
[linux-flexiantxendom0-3.2.10.git] / drivers / staging / hv / channel_mgmt.c
1 /*
2  * Copyright (c) 2009, Microsoft Corporation.
3  *
4  * This program is free software; you can redistribute it and/or modify it
5  * under the terms and conditions of the GNU General Public License,
6  * version 2, as published by the Free Software Foundation.
7  *
8  * This program is distributed in the hope it will be useful, but WITHOUT
9  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
11  * more details.
12  *
13  * You should have received a copy of the GNU General Public License along with
14  * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
15  * Place - Suite 330, Boston, MA 02111-1307 USA.
16  *
17  * Authors:
18  *   Haiyang Zhang <haiyangz@microsoft.com>
19  *   Hank Janssen  <hjanssen@microsoft.com>
20  */
21 #include <linux/kernel.h>
22 #include <linux/sched.h>
23 #include <linux/wait.h>
24 #include <linux/mm.h>
25 #include <linux/slab.h>
26 #include <linux/list.h>
27 #include <linux/module.h>
28 #include <linux/completion.h>
29 #include "hv_api.h"
30 #include "logging.h"
31 #include "vmbus_private.h"
32 #include "utils.h"
33
34 struct vmbus_channel_message_table_entry {
35         enum vmbus_channel_message_type messageType;
36         void (*messageHandler)(struct vmbus_channel_message_header *msg);
37 };
38
39 #define MAX_MSG_TYPES                    4
40 #define MAX_NUM_DEVICE_CLASSES_SUPPORTED 8
41
42 static const struct hv_guid
43         gSupportedDeviceClasses[MAX_NUM_DEVICE_CLASSES_SUPPORTED] = {
44         /* {ba6163d9-04a1-4d29-b605-72e2ffb1dc7f} */
45         /* Storage - SCSI */
46         {
47                 .data  = {
48                         0xd9, 0x63, 0x61, 0xba, 0xa1, 0x04, 0x29, 0x4d,
49                         0xb6, 0x05, 0x72, 0xe2, 0xff, 0xb1, 0xdc, 0x7f
50                 }
51         },
52
53         /* {F8615163-DF3E-46c5-913F-F2D2F965ED0E} */
54         /* Network */
55         {
56                 .data = {
57                         0x63, 0x51, 0x61, 0xF8, 0x3E, 0xDF, 0xc5, 0x46,
58                         0x91, 0x3F, 0xF2, 0xD2, 0xF9, 0x65, 0xED, 0x0E
59                 }
60         },
61
62         /* {CFA8B69E-5B4A-4cc0-B98B-8BA1A1F3F95A} */
63         /* Input */
64         {
65                 .data = {
66                         0x9E, 0xB6, 0xA8, 0xCF, 0x4A, 0x5B, 0xc0, 0x4c,
67                         0xB9, 0x8B, 0x8B, 0xA1, 0xA1, 0xF3, 0xF9, 0x5A
68                 }
69         },
70
71         /* {32412632-86cb-44a2-9b5c-50d1417354f5} */
72         /* IDE */
73         {
74                 .data = {
75                         0x32, 0x26, 0x41, 0x32, 0xcb, 0x86, 0xa2, 0x44,
76                         0x9b, 0x5c, 0x50, 0xd1, 0x41, 0x73, 0x54, 0xf5
77                 }
78         },
79         /* 0E0B6031-5213-4934-818B-38D90CED39DB */
80         /* Shutdown */
81         {
82                 .data = {
83                         0x31, 0x60, 0x0B, 0X0E, 0x13, 0x52, 0x34, 0x49,
84                         0x81, 0x8B, 0x38, 0XD9, 0x0C, 0xED, 0x39, 0xDB
85                 }
86         },
87         /* {9527E630-D0AE-497b-ADCE-E80AB0175CAF} */
88         /* TimeSync */
89         {
90                 .data = {
91                         0x30, 0xe6, 0x27, 0x95, 0xae, 0xd0, 0x7b, 0x49,
92                         0xad, 0xce, 0xe8, 0x0a, 0xb0, 0x17, 0x5c, 0xaf
93                 }
94         },
95         /* {57164f39-9115-4e78-ab55-382f3bd5422d} */
96         /* Heartbeat */
97         {
98                 .data = {
99                         0x39, 0x4f, 0x16, 0x57, 0x15, 0x91, 0x78, 0x4e,
100                         0xab, 0x55, 0x38, 0x2f, 0x3b, 0xd5, 0x42, 0x2d
101                 }
102         },
103         /* {A9A0F4E7-5A45-4d96-B827-8A841E8C03E6} */
104         /* KVP */
105         {
106                 .data = {
107                         0xe7, 0xf4, 0xa0, 0xa9, 0x45, 0x5a, 0x96, 0x4d,
108                         0xb8, 0x27, 0x8a, 0x84, 0x1e, 0x8c, 0x3,  0xe6
109         }
110         },
111
112 };
113
114
115 /**
116  * prep_negotiate_resp() - Create default response for Hyper-V Negotiate message
117  * @icmsghdrp: Pointer to msg header structure
118  * @icmsg_negotiate: Pointer to negotiate message structure
119  * @buf: Raw buffer channel data
120  *
121  * @icmsghdrp is of type &struct icmsg_hdr.
122  * @negop is of type &struct icmsg_negotiate.
123  * Set up and fill in default negotiate response message. This response can
124  * come from both the vmbus driver and the hv_utils driver. The current api
125  * will respond properly to both Windows 2008 and Windows 2008-R2 operating
126  * systems.
127  *
128  * Mainly used by Hyper-V drivers.
129  */
130 void prep_negotiate_resp(struct icmsg_hdr *icmsghdrp,
131                              struct icmsg_negotiate *negop,
132                              u8 *buf)
133 {
134         if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) {
135                 icmsghdrp->icmsgsize = 0x10;
136
137                 negop = (struct icmsg_negotiate *)&buf[
138                         sizeof(struct vmbuspipe_hdr) +
139                         sizeof(struct icmsg_hdr)];
140
141                 if (negop->icframe_vercnt == 2 &&
142                    negop->icversion_data[1].major == 3) {
143                         negop->icversion_data[0].major = 3;
144                         negop->icversion_data[0].minor = 0;
145                         negop->icversion_data[1].major = 3;
146                         negop->icversion_data[1].minor = 0;
147                 } else {
148                         negop->icversion_data[0].major = 1;
149                         negop->icversion_data[0].minor = 0;
150                         negop->icversion_data[1].major = 1;
151                         negop->icversion_data[1].minor = 0;
152                 }
153
154                 negop->icframe_vercnt = 1;
155                 negop->icmsg_vercnt = 1;
156         }
157 }
158 EXPORT_SYMBOL(prep_negotiate_resp);
159
160 /**
161  * chn_cb_negotiate() - Default handler for non IDE/SCSI/NETWORK
162  * Hyper-V requests
163  * @context: Pointer to argument structure.
164  *
165  * Set up the default handler for non device driver specific requests
166  * from Hyper-V. This stub responds to the default negotiate messages
167  * that come in for every non IDE/SCSI/Network request.
168  * This behavior is normally overwritten in the hv_utils driver. That
169  * driver handles requests like gracefull shutdown, heartbeats etc.
170  *
171  * Mainly used by Hyper-V drivers.
172  */
173 void chn_cb_negotiate(void *context)
174 {
175         struct vmbus_channel *channel = context;
176         u8 *buf;
177         u32 buflen, recvlen;
178         u64 requestid;
179
180         struct icmsg_hdr *icmsghdrp;
181         struct icmsg_negotiate *negop = NULL;
182
183         buflen = PAGE_SIZE;
184         buf = kmalloc(buflen, GFP_ATOMIC);
185
186         vmbus_recvpacket(channel, buf, buflen, &recvlen, &requestid);
187
188         if (recvlen > 0) {
189                 icmsghdrp = (struct icmsg_hdr *)&buf[
190                         sizeof(struct vmbuspipe_hdr)];
191
192                 prep_negotiate_resp(icmsghdrp, negop, buf);
193
194                 icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION
195                         | ICMSGHDRFLAG_RESPONSE;
196
197                 vmbus_sendpacket(channel, buf,
198                                        recvlen, requestid,
199                                        VM_PKT_DATA_INBAND, 0);
200         }
201
202         kfree(buf);
203 }
204 EXPORT_SYMBOL(chn_cb_negotiate);
205
206 /*
207  * Function table used for message responses for non IDE/SCSI/Network type
208  * messages. (Such as KVP/Shutdown etc)
209  */
210 struct hyperv_service_callback hv_cb_utils[MAX_MSG_TYPES] = {
211         /* 0E0B6031-5213-4934-818B-38D90CED39DB */
212         /* Shutdown */
213         {
214                 .msg_type = HV_SHUTDOWN_MSG,
215                 .data = {
216                         0x31, 0x60, 0x0B, 0X0E, 0x13, 0x52, 0x34, 0x49,
217                         0x81, 0x8B, 0x38, 0XD9, 0x0C, 0xED, 0x39, 0xDB
218                 },
219                 .callback = chn_cb_negotiate,
220                 .log_msg = "Shutdown channel functionality initialized"
221         },
222
223         /* {9527E630-D0AE-497b-ADCE-E80AB0175CAF} */
224         /* TimeSync */
225         {
226                 .msg_type = HV_TIMESYNC_MSG,
227                 .data = {
228                         0x30, 0xe6, 0x27, 0x95, 0xae, 0xd0, 0x7b, 0x49,
229                         0xad, 0xce, 0xe8, 0x0a, 0xb0, 0x17, 0x5c, 0xaf
230                 },
231                 .callback = chn_cb_negotiate,
232                 .log_msg = "Timesync channel functionality initialized"
233         },
234         /* {57164f39-9115-4e78-ab55-382f3bd5422d} */
235         /* Heartbeat */
236         {
237                 .msg_type = HV_HEARTBEAT_MSG,
238                 .data = {
239                         0x39, 0x4f, 0x16, 0x57, 0x15, 0x91, 0x78, 0x4e,
240                         0xab, 0x55, 0x38, 0x2f, 0x3b, 0xd5, 0x42, 0x2d
241                 },
242                 .callback = chn_cb_negotiate,
243                 .log_msg = "Heartbeat channel functionality initialized"
244         },
245         /* {A9A0F4E7-5A45-4d96-B827-8A841E8C03E6} */
246         /* KVP */
247         {
248                 .data = {
249                         0xe7, 0xf4, 0xa0, 0xa9, 0x45, 0x5a, 0x96, 0x4d,
250                         0xb8, 0x27, 0x8a, 0x84, 0x1e, 0x8c, 0x3,  0xe6
251                 },
252                 .callback = chn_cb_negotiate,
253                 .log_msg = "KVP channel functionality initialized"
254         },
255 };
256 EXPORT_SYMBOL(hv_cb_utils);
257
258 /*
259  * alloc_channel - Allocate and initialize a vmbus channel object
260  */
261 static struct vmbus_channel *alloc_channel(void)
262 {
263         struct vmbus_channel *channel;
264
265         channel = kzalloc(sizeof(*channel), GFP_ATOMIC);
266         if (!channel)
267                 return NULL;
268
269         spin_lock_init(&channel->inbound_lock);
270
271         init_timer(&channel->poll_timer);
272         channel->poll_timer.data = (unsigned long)channel;
273         channel->poll_timer.function = vmbus_ontimer;
274
275         channel->controlwq = create_workqueue("hv_vmbus_ctl");
276         if (!channel->controlwq) {
277                 kfree(channel);
278                 return NULL;
279         }
280
281         return channel;
282 }
283
284 /*
285  * release_hannel - Release the vmbus channel object itself
286  */
287 static void release_channel(struct work_struct *work)
288 {
289         struct vmbus_channel *channel = container_of(work,
290                                                      struct vmbus_channel,
291                                                      work);
292
293         DPRINT_DBG(VMBUS, "releasing channel (%p)", channel);
294         destroy_workqueue(channel->controlwq);
295         DPRINT_DBG(VMBUS, "channel released (%p)", channel);
296
297         kfree(channel);
298 }
299
300 /*
301  * free_channel - Release the resources used by the vmbus channel object
302  */
303 void free_channel(struct vmbus_channel *channel)
304 {
305         del_timer_sync(&channel->poll_timer);
306
307         /*
308          * We have to release the channel's workqueue/thread in the vmbus's
309          * workqueue/thread context
310          * ie we can't destroy ourselves.
311          */
312         INIT_WORK(&channel->work, release_channel);
313         queue_work(vmbus_connection.work_queue, &channel->work);
314 }
315
316
317 DECLARE_COMPLETION(hv_channel_ready);
318
319 /*
320  * Count initialized channels, and ensure all channels are ready when hv_vmbus
321  * module loading completes.
322  */
323 static void count_hv_channel(void)
324 {
325         static int counter;
326         unsigned long flags;
327
328         spin_lock_irqsave(&vmbus_connection.channel_lock, flags);
329         if (++counter == MAX_MSG_TYPES)
330                 complete(&hv_channel_ready);
331         spin_unlock_irqrestore(&vmbus_connection.channel_lock, flags);
332 }
333
334 /*
335  * vmbus_process_rescind_offer -
336  * Rescind the offer by initiating a device removal
337  */
338 static void vmbus_process_rescind_offer(struct work_struct *work)
339 {
340         struct vmbus_channel *channel = container_of(work,
341                                                      struct vmbus_channel,
342                                                      work);
343
344         vmbus_child_device_unregister(channel->device_obj);
345 }
346
347 /*
348  * vmbus_process_offer - Process the offer by creating a channel/device
349  * associated with this offer
350  */
351 static void vmbus_process_offer(struct work_struct *work)
352 {
353         struct vmbus_channel *newchannel = container_of(work,
354                                                         struct vmbus_channel,
355                                                         work);
356         struct vmbus_channel *channel;
357         bool fnew = true;
358         int ret;
359         int cnt;
360         unsigned long flags;
361
362         /* The next possible work is rescind handling */
363         INIT_WORK(&newchannel->work, vmbus_process_rescind_offer);
364
365         /* Make sure this is a new offer */
366         spin_lock_irqsave(&vmbus_connection.channel_lock, flags);
367
368         list_for_each_entry(channel, &vmbus_connection.chn_list, listentry) {
369                 if (!memcmp(&channel->offermsg.offer.if_type,
370                             &newchannel->offermsg.offer.if_type,
371                             sizeof(struct hv_guid)) &&
372                     !memcmp(&channel->offermsg.offer.if_instance,
373                             &newchannel->offermsg.offer.if_instance,
374                             sizeof(struct hv_guid))) {
375                         fnew = false;
376                         break;
377                 }
378         }
379
380         if (fnew)
381                 list_add_tail(&newchannel->listentry,
382                               &vmbus_connection.chn_list);
383
384         spin_unlock_irqrestore(&vmbus_connection.channel_lock, flags);
385
386         if (!fnew) {
387                 DPRINT_DBG(VMBUS, "Ignoring duplicate offer for relid (%d)",
388                            newchannel->offermsg.child_relid);
389                 free_channel(newchannel);
390                 return;
391         }
392
393         /*
394          * Start the process of binding this offer to the driver
395          * We need to set the DeviceObject field before calling
396          * vmbus_child_dev_add()
397          */
398         newchannel->device_obj = vmbus_child_device_create(
399                 &newchannel->offermsg.offer.if_type,
400                 &newchannel->offermsg.offer.if_instance,
401                 newchannel);
402
403         DPRINT_DBG(VMBUS, "child device object allocated - %p",
404                    newchannel->device_obj);
405
406         /*
407          * Add the new device to the bus. This will kick off device-driver
408          * binding which eventually invokes the device driver's AddDevice()
409          * method.
410          */
411         ret = vmbus_child_device_register(newchannel->device_obj);
412         if (ret != 0) {
413                 DPRINT_ERR(VMBUS,
414                            "unable to add child device object (relid %d)",
415                            newchannel->offermsg.child_relid);
416
417                 spin_lock_irqsave(&vmbus_connection.channel_lock, flags);
418                 list_del(&newchannel->listentry);
419                 spin_unlock_irqrestore(&vmbus_connection.channel_lock, flags);
420
421                 free_channel(newchannel);
422         } else {
423                 /*
424                  * This state is used to indicate a successful open
425                  * so that when we do close the channel normally, we
426                  * can cleanup properly
427                  */
428                 newchannel->state = CHANNEL_OPEN_STATE;
429
430                 /* Open IC channels */
431                 for (cnt = 0; cnt < MAX_MSG_TYPES; cnt++) {
432                         if (memcmp(&newchannel->offermsg.offer.if_type,
433                                    &hv_cb_utils[cnt].data,
434                                    sizeof(struct hv_guid)) == 0 &&
435                                 vmbus_open(newchannel, 2 * PAGE_SIZE,
436                                                  2 * PAGE_SIZE, NULL, 0,
437                                                  hv_cb_utils[cnt].callback,
438                                                  newchannel) == 0) {
439                                 hv_cb_utils[cnt].channel = newchannel;
440                                 DPRINT_INFO(VMBUS, "%s",
441                                                 hv_cb_utils[cnt].log_msg);
442                                 count_hv_channel();
443                         }
444                 }
445         }
446 }
447
448 /*
449  * vmbus_onoffer - Handler for channel offers from vmbus in parent partition.
450  *
451  * We ignore all offers except network and storage offers. For each network and
452  * storage offers, we create a channel object and queue a work item to the
453  * channel object to process the offer synchronously
454  */
455 static void vmbus_onoffer(struct vmbus_channel_message_header *hdr)
456 {
457         struct vmbus_channel_offer_channel *offer;
458         struct vmbus_channel *newchannel;
459         struct hv_guid *guidtype;
460         struct hv_guid *guidinstance;
461         int i;
462         int fsupported = 0;
463
464         offer = (struct vmbus_channel_offer_channel *)hdr;
465         for (i = 0; i < MAX_NUM_DEVICE_CLASSES_SUPPORTED; i++) {
466                 if (memcmp(&offer->offer.if_type,
467                     &gSupportedDeviceClasses[i], sizeof(struct hv_guid)) == 0) {
468                         fsupported = 1;
469                         break;
470                 }
471         }
472
473         if (!fsupported) {
474                 DPRINT_DBG(VMBUS, "Ignoring channel offer notification for "
475                            "child relid %d", offer->child_relid);
476                 return;
477         }
478
479         guidtype = &offer->offer.if_type;
480         guidinstance = &offer->offer.if_instance;
481
482         DPRINT_INFO(VMBUS, "Channel offer notification - "
483                     "child relid %d monitor id %d allocated %d, "
484                     "type {%02x%02x%02x%02x-%02x%02x-%02x%02x-"
485                     "%02x%02x%02x%02x%02x%02x%02x%02x} "
486                     "instance {%02x%02x%02x%02x-%02x%02x-%02x%02x-"
487                     "%02x%02x%02x%02x%02x%02x%02x%02x}",
488                     offer->child_relid, offer->monitorid,
489                     offer->monitor_allocated,
490                     guidtype->data[3], guidtype->data[2],
491                     guidtype->data[1], guidtype->data[0],
492                     guidtype->data[5], guidtype->data[4],
493                     guidtype->data[7], guidtype->data[6],
494                     guidtype->data[8], guidtype->data[9],
495                     guidtype->data[10], guidtype->data[11],
496                     guidtype->data[12], guidtype->data[13],
497                     guidtype->data[14], guidtype->data[15],
498                     guidinstance->data[3], guidinstance->data[2],
499                     guidinstance->data[1], guidinstance->data[0],
500                     guidinstance->data[5], guidinstance->data[4],
501                     guidinstance->data[7], guidinstance->data[6],
502                     guidinstance->data[8], guidinstance->data[9],
503                     guidinstance->data[10], guidinstance->data[11],
504                     guidinstance->data[12], guidinstance->data[13],
505                     guidinstance->data[14], guidinstance->data[15]);
506
507         /* Allocate the channel object and save this offer. */
508         newchannel = alloc_channel();
509         if (!newchannel) {
510                 DPRINT_ERR(VMBUS, "unable to allocate channel object");
511                 return;
512         }
513
514         DPRINT_DBG(VMBUS, "channel object allocated - %p", newchannel);
515
516         memcpy(&newchannel->offermsg, offer,
517                sizeof(struct vmbus_channel_offer_channel));
518         newchannel->monitor_grp = (u8)offer->monitorid / 32;
519         newchannel->monitor_bit = (u8)offer->monitorid % 32;
520
521         /* TODO: Make sure the offer comes from our parent partition */
522         INIT_WORK(&newchannel->work, vmbus_process_offer);
523         queue_work(newchannel->controlwq, &newchannel->work);
524 }
525
526 /*
527  * vmbus_onoffer_rescind - Rescind offer handler.
528  *
529  * We queue a work item to process this offer synchronously
530  */
531 static void vmbus_onoffer_rescind(struct vmbus_channel_message_header *hdr)
532 {
533         struct vmbus_channel_rescind_offer *rescind;
534         struct vmbus_channel *channel;
535
536         rescind = (struct vmbus_channel_rescind_offer *)hdr;
537         channel = relid2channel(rescind->child_relid);
538         if (channel == NULL) {
539                 DPRINT_DBG(VMBUS, "channel not found for relId %d",
540                            rescind->child_relid);
541                 return;
542         }
543
544         /* work is initialized for vmbus_process_rescind_offer() from
545          * vmbus_process_offer() where the channel got created */
546         queue_work(channel->controlwq, &channel->work);
547 }
548
549 /*
550  * vmbus_onoffers_delivered -
551  * This is invoked when all offers have been delivered.
552  *
553  * Nothing to do here.
554  */
555 static void vmbus_onoffers_delivered(
556                         struct vmbus_channel_message_header *hdr)
557 {
558 }
559
560 /*
561  * vmbus_onopen_result - Open result handler.
562  *
563  * This is invoked when we received a response to our channel open request.
564  * Find the matching request, copy the response and signal the requesting
565  * thread.
566  */
567 static void vmbus_onopen_result(struct vmbus_channel_message_header *hdr)
568 {
569         struct vmbus_channel_open_result *result;
570         struct vmbus_channel_msginfo *msginfo;
571         struct vmbus_channel_message_header *requestheader;
572         struct vmbus_channel_open_channel *openmsg;
573         unsigned long flags;
574
575         result = (struct vmbus_channel_open_result *)hdr;
576         DPRINT_DBG(VMBUS, "vmbus open result - %d", result->status);
577
578         /*
579          * Find the open msg, copy the result and signal/unblock the wait event
580          */
581         spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
582
583         list_for_each_entry(msginfo, &vmbus_connection.chn_msg_list,
584                                 msglistentry) {
585                 requestheader =
586                         (struct vmbus_channel_message_header *)msginfo->msg;
587
588                 if (requestheader->msgtype == CHANNELMSG_OPENCHANNEL) {
589                         openmsg =
590                         (struct vmbus_channel_open_channel *)msginfo->msg;
591                         if (openmsg->child_relid == result->child_relid &&
592                             openmsg->openid == result->openid) {
593                                 memcpy(&msginfo->response.open_result,
594                                        result,
595                                        sizeof(struct vmbus_channel_open_result));
596                                 msginfo->wait_condition = 1;
597                                 wake_up(&msginfo->waitevent);
598                                 break;
599                         }
600                 }
601         }
602         spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
603 }
604
605 /*
606  * vmbus_ongpadl_created - GPADL created handler.
607  *
608  * This is invoked when we received a response to our gpadl create request.
609  * Find the matching request, copy the response and signal the requesting
610  * thread.
611  */
612 static void vmbus_ongpadl_created(struct vmbus_channel_message_header *hdr)
613 {
614         struct vmbus_channel_gpadl_created *gpadlcreated;
615         struct vmbus_channel_msginfo *msginfo;
616         struct vmbus_channel_message_header *requestheader;
617         struct vmbus_channel_gpadl_header *gpadlheader;
618         unsigned long flags;
619
620         gpadlcreated = (struct vmbus_channel_gpadl_created *)hdr;
621         DPRINT_DBG(VMBUS, "vmbus gpadl created result - %d",
622                    gpadlcreated->creation_status);
623
624         /*
625          * Find the establish msg, copy the result and signal/unblock the wait
626          * event
627          */
628         spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
629
630         list_for_each_entry(msginfo, &vmbus_connection.chn_msg_list,
631                                 msglistentry) {
632                 requestheader =
633                         (struct vmbus_channel_message_header *)msginfo->msg;
634
635                 if (requestheader->msgtype == CHANNELMSG_GPADL_HEADER) {
636                         gpadlheader =
637                         (struct vmbus_channel_gpadl_header *)requestheader;
638
639                         if ((gpadlcreated->child_relid ==
640                              gpadlheader->child_relid) &&
641                             (gpadlcreated->gpadl == gpadlheader->gpadl)) {
642                                 memcpy(&msginfo->response.gpadl_created,
643                                        gpadlcreated,
644                                        sizeof(struct vmbus_channel_gpadl_created));
645                                 msginfo->wait_condition = 1;
646                                 wake_up(&msginfo->waitevent);
647                                 break;
648                         }
649                 }
650         }
651         spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
652 }
653
654 /*
655  * vmbus_ongpadl_torndown - GPADL torndown handler.
656  *
657  * This is invoked when we received a response to our gpadl teardown request.
658  * Find the matching request, copy the response and signal the requesting
659  * thread.
660  */
661 static void vmbus_ongpadl_torndown(
662                         struct vmbus_channel_message_header *hdr)
663 {
664         struct vmbus_channel_gpadl_torndown *gpadl_torndown;
665         struct vmbus_channel_msginfo *msginfo;
666         struct vmbus_channel_message_header *requestheader;
667         struct vmbus_channel_gpadl_teardown *gpadl_teardown;
668         unsigned long flags;
669
670         gpadl_torndown = (struct vmbus_channel_gpadl_torndown *)hdr;
671
672         /*
673          * Find the open msg, copy the result and signal/unblock the wait event
674          */
675         spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
676
677         list_for_each_entry(msginfo, &vmbus_connection.chn_msg_list,
678                                 msglistentry) {
679                 requestheader =
680                         (struct vmbus_channel_message_header *)msginfo->msg;
681
682                 if (requestheader->msgtype == CHANNELMSG_GPADL_TEARDOWN) {
683                         gpadl_teardown =
684                         (struct vmbus_channel_gpadl_teardown *)requestheader;
685
686                         if (gpadl_torndown->gpadl == gpadl_teardown->gpadl) {
687                                 memcpy(&msginfo->response.gpadl_torndown,
688                                        gpadl_torndown,
689                                        sizeof(struct vmbus_channel_gpadl_torndown));
690                                 msginfo->wait_condition = 1;
691                                 wake_up(&msginfo->waitevent);
692                                 break;
693                         }
694                 }
695         }
696         spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
697 }
698
699 /*
700  * vmbus_onversion_response - Version response handler
701  *
702  * This is invoked when we received a response to our initiate contact request.
703  * Find the matching request, copy the response and signal the requesting
704  * thread.
705  */
706 static void vmbus_onversion_response(
707                 struct vmbus_channel_message_header *hdr)
708 {
709         struct vmbus_channel_msginfo *msginfo;
710         struct vmbus_channel_message_header *requestheader;
711         struct vmbus_channel_initiate_contact *initiate;
712         struct vmbus_channel_version_response *version_response;
713         unsigned long flags;
714
715         version_response = (struct vmbus_channel_version_response *)hdr;
716         spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
717
718         list_for_each_entry(msginfo, &vmbus_connection.chn_msg_list,
719                                 msglistentry) {
720                 requestheader =
721                         (struct vmbus_channel_message_header *)msginfo->msg;
722
723                 if (requestheader->msgtype ==
724                     CHANNELMSG_INITIATE_CONTACT) {
725                         initiate =
726                         (struct vmbus_channel_initiate_contact *)requestheader;
727                         memcpy(&msginfo->response.version_response,
728                               version_response,
729                               sizeof(struct vmbus_channel_version_response));
730                         msginfo->wait_condition = 1;
731                         wake_up(&msginfo->waitevent);
732                 }
733         }
734         spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
735 }
736
737 /* Channel message dispatch table */
738 static struct vmbus_channel_message_table_entry
739         gChannelMessageTable[CHANNELMSG_COUNT] = {
740         {CHANNELMSG_INVALID,                    NULL},
741         {CHANNELMSG_OFFERCHANNEL,               vmbus_onoffer},
742         {CHANNELMSG_RESCIND_CHANNELOFFER,       vmbus_onoffer_rescind},
743         {CHANNELMSG_REQUESTOFFERS,              NULL},
744         {CHANNELMSG_ALLOFFERS_DELIVERED,        vmbus_onoffers_delivered},
745         {CHANNELMSG_OPENCHANNEL,                NULL},
746         {CHANNELMSG_OPENCHANNEL_RESULT, vmbus_onopen_result},
747         {CHANNELMSG_CLOSECHANNEL,               NULL},
748         {CHANNELMSG_GPADL_HEADER,               NULL},
749         {CHANNELMSG_GPADL_BODY,         NULL},
750         {CHANNELMSG_GPADL_CREATED,              vmbus_ongpadl_created},
751         {CHANNELMSG_GPADL_TEARDOWN,             NULL},
752         {CHANNELMSG_GPADL_TORNDOWN,             vmbus_ongpadl_torndown},
753         {CHANNELMSG_RELID_RELEASED,             NULL},
754         {CHANNELMSG_INITIATE_CONTACT,           NULL},
755         {CHANNELMSG_VERSION_RESPONSE,           vmbus_onversion_response},
756         {CHANNELMSG_UNLOAD,                     NULL},
757 };
758
759 /*
760  * vmbus_onmessage - Handler for channel protocol messages.
761  *
762  * This is invoked in the vmbus worker thread context.
763  */
764 void vmbus_onmessage(void *context)
765 {
766         struct hv_message *msg = context;
767         struct vmbus_channel_message_header *hdr;
768         int size;
769
770         hdr = (struct vmbus_channel_message_header *)msg->u.payload;
771         size = msg->header.payload_size;
772
773         DPRINT_DBG(VMBUS, "message type %d size %d", hdr->msgtype, size);
774
775         if (hdr->msgtype >= CHANNELMSG_COUNT) {
776                 DPRINT_ERR(VMBUS,
777                            "Received invalid channel message type %d size %d",
778                            hdr->msgtype, size);
779                 print_hex_dump_bytes("", DUMP_PREFIX_NONE,
780                                      (unsigned char *)msg->u.payload, size);
781                 return;
782         }
783
784         if (gChannelMessageTable[hdr->msgtype].messageHandler)
785                 gChannelMessageTable[hdr->msgtype].messageHandler(hdr);
786         else
787                 DPRINT_ERR(VMBUS, "Unhandled channel message type %d",
788                            hdr->msgtype);
789 }
790
791 /*
792  * vmbus_request_offers - Send a request to get all our pending offers.
793  */
794 int vmbus_request_offers(void)
795 {
796         struct vmbus_channel_message_header *msg;
797         struct vmbus_channel_msginfo *msginfo;
798         int ret;
799
800         msginfo = kmalloc(sizeof(*msginfo) +
801                           sizeof(struct vmbus_channel_message_header),
802                           GFP_KERNEL);
803         if (!msginfo)
804                 return -ENOMEM;
805
806         init_waitqueue_head(&msginfo->waitevent);
807
808         msg = (struct vmbus_channel_message_header *)msginfo->msg;
809
810         msg->msgtype = CHANNELMSG_REQUESTOFFERS;
811
812
813         ret = vmbus_post_msg(msg,
814                                sizeof(struct vmbus_channel_message_header));
815         if (ret != 0) {
816                 DPRINT_ERR(VMBUS, "Unable to request offers - %d", ret);
817
818                 goto cleanup;
819         }
820
821         msginfo->wait_condition = 0;
822         wait_event_timeout(msginfo->waitevent, msginfo->wait_condition,
823                         msecs_to_jiffies(1000));
824         if (msginfo->wait_condition == 0) {
825                 ret = -ETIMEDOUT;
826                 goto cleanup;
827         }
828
829
830
831 cleanup:
832         kfree(msginfo);
833
834         return ret;
835 }
836
837 /*
838  * vmbus_release_unattached_channels - Release channels that are
839  * unattached/unconnected ie (no drivers associated)
840  */
841 void vmbus_release_unattached_channels(void)
842 {
843         struct vmbus_channel *channel, *pos;
844         struct vmbus_channel *start = NULL;
845         unsigned long flags;
846
847         spin_lock_irqsave(&vmbus_connection.channel_lock, flags);
848
849         list_for_each_entry_safe(channel, pos, &vmbus_connection.chn_list,
850                                  listentry) {
851                 if (channel == start)
852                         break;
853
854                 if (!channel->device_obj->drv) {
855                         list_del(&channel->listentry);
856                         DPRINT_INFO(VMBUS,
857                                     "Releasing unattached device object %p",
858                                     channel->device_obj);
859
860                         vmbus_child_device_unregister(channel->device_obj);
861                         free_channel(channel);
862                 } else {
863                         if (!start)
864                                 start = channel;
865                 }
866         }
867
868         spin_unlock_irqrestore(&vmbus_connection.channel_lock, flags);
869 }
870
871 /* eof */