Merge branches 'stable/balloon.cleanup' and 'stable/general.cleanup' of git://git...
[pandora-kernel.git] / drivers / staging / hv / channel.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/module.h>
27 #include "hv_api.h"
28 #include "logging.h"
29 #include "vmbus_private.h"
30
31 #define NUM_PAGES_SPANNED(addr, len) \
32 ((PAGE_ALIGN(addr + len) >> PAGE_SHIFT) - (addr >> PAGE_SHIFT))
33
34 /* Internal routines */
35 static int create_gpadl_header(
36         void *kbuffer,  /* must be phys and virt contiguous */
37         u32 size,       /* page-size multiple */
38         struct vmbus_channel_msginfo **msginfo,
39         u32 *messagecount);
40 static void dump_vmbus_channel(struct vmbus_channel *channel);
41 static void vmbus_setevent(struct vmbus_channel *channel);
42
43
44 #if 0
45 static void DumpMonitorPage(struct hv_monitor_page *MonitorPage)
46 {
47         int i = 0;
48         int j = 0;
49
50         DPRINT_DBG(VMBUS, "monitorPage - %p, trigger state - %d",
51                    MonitorPage, MonitorPage->trigger_state);
52
53         for (i = 0; i < 4; i++)
54                 DPRINT_DBG(VMBUS, "trigger group (%d) - %llx", i,
55                            MonitorPage->trigger_group[i].as_uint64);
56
57         for (i = 0; i < 4; i++) {
58                 for (j = 0; j < 32; j++) {
59                         DPRINT_DBG(VMBUS, "latency (%d)(%d) - %llx", i, j,
60                                    MonitorPage->latency[i][j]);
61                 }
62         }
63         for (i = 0; i < 4; i++) {
64                 for (j = 0; j < 32; j++) {
65                         DPRINT_DBG(VMBUS, "param-conn id (%d)(%d) - %d", i, j,
66                                MonitorPage->parameter[i][j].connectionid.asu32);
67                         DPRINT_DBG(VMBUS, "param-flag (%d)(%d) - %d", i, j,
68                                 MonitorPage->parameter[i][j].flag_number);
69                 }
70         }
71 }
72 #endif
73
74 /*
75  * vmbus_setevent- Trigger an event notification on the specified
76  * channel.
77  */
78 static void vmbus_setevent(struct vmbus_channel *channel)
79 {
80         struct hv_monitor_page *monitorpage;
81
82         if (channel->offermsg.monitor_allocated) {
83                 /* Each u32 represents 32 channels */
84                 sync_set_bit(channel->offermsg.child_relid & 31,
85                         (unsigned long *) vmbus_connection.send_int_page +
86                         (channel->offermsg.child_relid >> 5));
87
88                 monitorpage = vmbus_connection.monitor_pages;
89                 monitorpage++; /* Get the child to parent monitor page */
90
91                 sync_set_bit(channel->monitor_bit,
92                         (unsigned long *)&monitorpage->trigger_group
93                                         [channel->monitor_grp].pending);
94
95         } else {
96                 vmbus_set_event(channel->offermsg.child_relid);
97         }
98 }
99
100 #if 0
101 static void VmbusChannelClearEvent(struct vmbus_channel *channel)
102 {
103         struct hv_monitor_page *monitorPage;
104
105         if (Channel->offermsg.monitor_allocated) {
106                 /* Each u32 represents 32 channels */
107                 sync_clear_bit(Channel->offermsg.child_relid & 31,
108                           (unsigned long *)vmbus_connection.send_int_page +
109                           (Channel->offermsg.child_relid >> 5));
110
111                 monitorPage = (struct hv_monitor_page *)
112                         vmbus_connection.monitor_pages;
113                 monitorPage++; /* Get the child to parent monitor page */
114
115                 sync_clear_bit(Channel->monitor_bit,
116                           (unsigned long *)&monitorPage->trigger_group
117                                         [Channel->monitor_grp].Pending);
118         }
119 }
120
121 #endif
122 /*
123  * vmbus_get_debug_info -Retrieve various channel debug info
124  */
125 void vmbus_get_debug_info(struct vmbus_channel *channel,
126                               struct vmbus_channel_debug_info *debuginfo)
127 {
128         struct hv_monitor_page *monitorpage;
129         u8 monitor_group = (u8)channel->offermsg.monitorid / 32;
130         u8 monitor_offset = (u8)channel->offermsg.monitorid % 32;
131         /* u32 monitorBit       = 1 << monitorOffset; */
132
133         debuginfo->relid = channel->offermsg.child_relid;
134         debuginfo->state = channel->state;
135         memcpy(&debuginfo->interfacetype,
136                &channel->offermsg.offer.if_type, sizeof(struct hv_guid));
137         memcpy(&debuginfo->interface_instance,
138                &channel->offermsg.offer.if_instance,
139                sizeof(struct hv_guid));
140
141         monitorpage = (struct hv_monitor_page *)vmbus_connection.monitor_pages;
142
143         debuginfo->monitorid = channel->offermsg.monitorid;
144
145         debuginfo->servermonitor_pending =
146                         monitorpage->trigger_group[monitor_group].pending;
147         debuginfo->servermonitor_latency =
148                         monitorpage->latency[monitor_group][monitor_offset];
149         debuginfo->servermonitor_connectionid =
150                         monitorpage->parameter[monitor_group]
151                                         [monitor_offset].connectionid.u.id;
152
153         monitorpage++;
154
155         debuginfo->clientmonitor_pending =
156                         monitorpage->trigger_group[monitor_group].pending;
157         debuginfo->clientmonitor_latency =
158                         monitorpage->latency[monitor_group][monitor_offset];
159         debuginfo->clientmonitor_connectionid =
160                         monitorpage->parameter[monitor_group]
161                                         [monitor_offset].connectionid.u.id;
162
163         ringbuffer_get_debuginfo(&channel->inbound, &debuginfo->inbound);
164         ringbuffer_get_debuginfo(&channel->outbound, &debuginfo->outbound);
165 }
166
167 /*
168  * vmbus_open - Open the specified channel.
169  */
170 int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size,
171                      u32 recv_ringbuffer_size, void *userdata, u32 userdatalen,
172                      void (*onchannelcallback)(void *context), void *context)
173 {
174         struct vmbus_channel_open_channel *openMsg;
175         struct vmbus_channel_msginfo *openInfo = NULL;
176         void *in, *out;
177         unsigned long flags;
178         int ret, err = 0;
179
180         /* Aligned to page size */
181         /* ASSERT(!(SendRingBufferSize & (PAGE_SIZE - 1))); */
182         /* ASSERT(!(RecvRingBufferSize & (PAGE_SIZE - 1))); */
183
184         newchannel->onchannel_callback = onchannelcallback;
185         newchannel->channel_callback_context = context;
186
187         /* Allocate the ring buffer */
188         out = (void *)__get_free_pages(GFP_KERNEL|__GFP_ZERO,
189                 get_order(send_ringbuffer_size + recv_ringbuffer_size));
190
191         if (!out)
192                 return -ENOMEM;
193
194         /* ASSERT(((unsigned long)out & (PAGE_SIZE-1)) == 0); */
195
196         in = (void *)((unsigned long)out + send_ringbuffer_size);
197
198         newchannel->ringbuffer_pages = out;
199         newchannel->ringbuffer_pagecount = (send_ringbuffer_size +
200                                            recv_ringbuffer_size) >> PAGE_SHIFT;
201
202         ret = ringbuffer_init(&newchannel->outbound, out, send_ringbuffer_size);
203         if (ret != 0) {
204                 err = ret;
205                 goto errorout;
206         }
207
208         ret = ringbuffer_init(&newchannel->inbound, in, recv_ringbuffer_size);
209         if (ret != 0) {
210                 err = ret;
211                 goto errorout;
212         }
213
214
215         /* Establish the gpadl for the ring buffer */
216         DPRINT_DBG(VMBUS, "Establishing ring buffer's gpadl for channel %p...",
217                    newchannel);
218
219         newchannel->ringbuffer_gpadlhandle = 0;
220
221         ret = vmbus_establish_gpadl(newchannel,
222                                          newchannel->outbound.ring_buffer,
223                                          send_ringbuffer_size +
224                                          recv_ringbuffer_size,
225                                          &newchannel->ringbuffer_gpadlhandle);
226
227         if (ret != 0) {
228                 err = ret;
229                 goto errorout;
230         }
231
232         DPRINT_DBG(VMBUS, "channel %p <relid %d gpadl 0x%x send ring %p "
233                    "size %d recv ring %p size %d, downstreamoffset %d>",
234                    newchannel, newchannel->offermsg.child_relid,
235                    newchannel->ringbuffer_gpadlhandle,
236                    newchannel->outbound.ring_buffer,
237                    newchannel->outbound.ring_size,
238                    newchannel->inbound.ring_buffer,
239                    newchannel->inbound.ring_size,
240                    send_ringbuffer_size);
241
242         /* Create and init the channel open message */
243         openInfo = kmalloc(sizeof(*openInfo) +
244                            sizeof(struct vmbus_channel_open_channel),
245                            GFP_KERNEL);
246         if (!openInfo) {
247                 err = -ENOMEM;
248                 goto errorout;
249         }
250
251         init_waitqueue_head(&openInfo->waitevent);
252
253         openMsg = (struct vmbus_channel_open_channel *)openInfo->msg;
254         openMsg->header.msgtype = CHANNELMSG_OPENCHANNEL;
255         openMsg->openid = newchannel->offermsg.child_relid; /* FIXME */
256         openMsg->child_relid = newchannel->offermsg.child_relid;
257         openMsg->ringbuffer_gpadlhandle = newchannel->ringbuffer_gpadlhandle;
258         openMsg->downstream_ringbuffer_pageoffset = send_ringbuffer_size >>
259                                                   PAGE_SHIFT;
260         openMsg->server_contextarea_gpadlhandle = 0; /* TODO */
261
262         if (userdatalen > MAX_USER_DEFINED_BYTES) {
263                 err = -EINVAL;
264                 goto errorout;
265         }
266
267         if (userdatalen)
268                 memcpy(openMsg->userdata, userdata, userdatalen);
269
270         spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
271         list_add_tail(&openInfo->msglistentry,
272                       &vmbus_connection.chn_msg_list);
273         spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
274
275         DPRINT_DBG(VMBUS, "Sending channel open msg...");
276
277         ret = vmbus_post_msg(openMsg,
278                                sizeof(struct vmbus_channel_open_channel));
279         if (ret != 0) {
280                 DPRINT_ERR(VMBUS, "unable to open channel - %d", ret);
281                 goto Cleanup;
282         }
283
284         openInfo->wait_condition = 0;
285         wait_event_timeout(openInfo->waitevent,
286                         openInfo->wait_condition,
287                         msecs_to_jiffies(1000));
288         if (openInfo->wait_condition == 0) {
289                 err = -ETIMEDOUT;
290                 goto errorout;
291         }
292
293
294         if (openInfo->response.open_result.status == 0)
295                 DPRINT_INFO(VMBUS, "channel <%p> open success!!", newchannel);
296         else
297                 DPRINT_INFO(VMBUS, "channel <%p> open failed - %d!!",
298                             newchannel, openInfo->response.open_result.status);
299
300 Cleanup:
301         spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
302         list_del(&openInfo->msglistentry);
303         spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
304
305         kfree(openInfo);
306         return 0;
307
308 errorout:
309         ringbuffer_cleanup(&newchannel->outbound);
310         ringbuffer_cleanup(&newchannel->inbound);
311         free_pages((unsigned long)out,
312                 get_order(send_ringbuffer_size + recv_ringbuffer_size));
313         kfree(openInfo);
314         return err;
315 }
316 EXPORT_SYMBOL_GPL(vmbus_open);
317
318 /*
319  * dump_gpadl_body - Dump the gpadl body message to the console for
320  * debugging purposes.
321  */
322 static void dump_gpadl_body(struct vmbus_channel_gpadl_body *gpadl, u32 len)
323 {
324         int i;
325         int pfncount;
326
327         pfncount = (len - sizeof(struct vmbus_channel_gpadl_body)) /
328                    sizeof(u64);
329         DPRINT_DBG(VMBUS, "gpadl body - len %d pfn count %d", len, pfncount);
330
331         for (i = 0; i < pfncount; i++)
332                 DPRINT_DBG(VMBUS, "gpadl body  - %d) pfn %llu",
333                            i, gpadl->pfn[i]);
334 }
335
336 /*
337  * dump_gpadl_header - Dump the gpadl header message to the console for
338  * debugging purposes.
339  */
340 static void dump_gpadl_header(struct vmbus_channel_gpadl_header *gpadl)
341 {
342         int i, j;
343         int pagecount;
344
345         DPRINT_DBG(VMBUS,
346                    "gpadl header - relid %d, range count %d, range buflen %d",
347                    gpadl->child_relid, gpadl->rangecount, gpadl->range_buflen);
348         for (i = 0; i < gpadl->rangecount; i++) {
349                 pagecount = gpadl->range[i].byte_count >> PAGE_SHIFT;
350                 pagecount = (pagecount > 26) ? 26 : pagecount;
351
352                 DPRINT_DBG(VMBUS, "gpadl range %d - len %d offset %d "
353                            "page count %d", i, gpadl->range[i].byte_count,
354                            gpadl->range[i].byte_offset, pagecount);
355
356                 for (j = 0; j < pagecount; j++)
357                         DPRINT_DBG(VMBUS, "%d) pfn %llu", j,
358                                    gpadl->range[i].pfn_array[j]);
359         }
360 }
361
362 /*
363  * create_gpadl_header - Creates a gpadl for the specified buffer
364  */
365 static int create_gpadl_header(void *kbuffer, u32 size,
366                                          struct vmbus_channel_msginfo **msginfo,
367                                          u32 *messagecount)
368 {
369         int i;
370         int pagecount;
371         unsigned long long pfn;
372         struct vmbus_channel_gpadl_header *gpadl_header;
373         struct vmbus_channel_gpadl_body *gpadl_body;
374         struct vmbus_channel_msginfo *msgheader;
375         struct vmbus_channel_msginfo *msgbody = NULL;
376         u32 msgsize;
377
378         int pfnsum, pfncount, pfnleft, pfncurr, pfnsize;
379
380         /* ASSERT((kbuffer & (PAGE_SIZE-1)) == 0); */
381         /* ASSERT((Size & (PAGE_SIZE-1)) == 0); */
382
383         pagecount = size >> PAGE_SHIFT;
384         pfn = virt_to_phys(kbuffer) >> PAGE_SHIFT;
385
386         /* do we need a gpadl body msg */
387         pfnsize = MAX_SIZE_CHANNEL_MESSAGE -
388                   sizeof(struct vmbus_channel_gpadl_header) -
389                   sizeof(struct gpa_range);
390         pfncount = pfnsize / sizeof(u64);
391
392         if (pagecount > pfncount) {
393                 /* we need a gpadl body */
394                 /* fill in the header */
395                 msgsize = sizeof(struct vmbus_channel_msginfo) +
396                           sizeof(struct vmbus_channel_gpadl_header) +
397                           sizeof(struct gpa_range) + pfncount * sizeof(u64);
398                 msgheader =  kzalloc(msgsize, GFP_KERNEL);
399                 if (!msgheader)
400                         goto nomem;
401
402                 INIT_LIST_HEAD(&msgheader->submsglist);
403                 msgheader->msgsize = msgsize;
404
405                 gpadl_header = (struct vmbus_channel_gpadl_header *)
406                         msgheader->msg;
407                 gpadl_header->rangecount = 1;
408                 gpadl_header->range_buflen = sizeof(struct gpa_range) +
409                                          pagecount * sizeof(u64);
410                 gpadl_header->range[0].byte_offset = 0;
411                 gpadl_header->range[0].byte_count = size;
412                 for (i = 0; i < pfncount; i++)
413                         gpadl_header->range[0].pfn_array[i] = pfn+i;
414                 *msginfo = msgheader;
415                 *messagecount = 1;
416
417                 pfnsum = pfncount;
418                 pfnleft = pagecount - pfncount;
419
420                 /* how many pfns can we fit */
421                 pfnsize = MAX_SIZE_CHANNEL_MESSAGE -
422                           sizeof(struct vmbus_channel_gpadl_body);
423                 pfncount = pfnsize / sizeof(u64);
424
425                 /* fill in the body */
426                 while (pfnleft) {
427                         if (pfnleft > pfncount)
428                                 pfncurr = pfncount;
429                         else
430                                 pfncurr = pfnleft;
431
432                         msgsize = sizeof(struct vmbus_channel_msginfo) +
433                                   sizeof(struct vmbus_channel_gpadl_body) +
434                                   pfncurr * sizeof(u64);
435                         msgbody = kzalloc(msgsize, GFP_KERNEL);
436                         /* FIXME: we probably need to more if this fails */
437                         if (!msgbody)
438                                 goto nomem;
439                         msgbody->msgsize = msgsize;
440                         (*messagecount)++;
441                         gpadl_body =
442                                 (struct vmbus_channel_gpadl_body *)msgbody->msg;
443
444                         /*
445                          * FIXME:
446                          * Gpadl is u32 and we are using a pointer which could
447                          * be 64-bit
448                          */
449                         /* gpadl_body->Gpadl = kbuffer; */
450                         for (i = 0; i < pfncurr; i++)
451                                 gpadl_body->pfn[i] = pfn + pfnsum + i;
452
453                         /* add to msg header */
454                         list_add_tail(&msgbody->msglistentry,
455                                       &msgheader->submsglist);
456                         pfnsum += pfncurr;
457                         pfnleft -= pfncurr;
458                 }
459         } else {
460                 /* everything fits in a header */
461                 msgsize = sizeof(struct vmbus_channel_msginfo) +
462                           sizeof(struct vmbus_channel_gpadl_header) +
463                           sizeof(struct gpa_range) + pagecount * sizeof(u64);
464                 msgheader = kzalloc(msgsize, GFP_KERNEL);
465                 if (msgheader == NULL)
466                         goto nomem;
467                 msgheader->msgsize = msgsize;
468
469                 gpadl_header = (struct vmbus_channel_gpadl_header *)
470                         msgheader->msg;
471                 gpadl_header->rangecount = 1;
472                 gpadl_header->range_buflen = sizeof(struct gpa_range) +
473                                          pagecount * sizeof(u64);
474                 gpadl_header->range[0].byte_offset = 0;
475                 gpadl_header->range[0].byte_count = size;
476                 for (i = 0; i < pagecount; i++)
477                         gpadl_header->range[0].pfn_array[i] = pfn+i;
478
479                 *msginfo = msgheader;
480                 *messagecount = 1;
481         }
482
483         return 0;
484 nomem:
485         kfree(msgheader);
486         kfree(msgbody);
487         return -ENOMEM;
488 }
489
490 /*
491  * vmbus_establish_gpadl - Estabish a GPADL for the specified buffer
492  *
493  * @channel: a channel
494  * @kbuffer: from kmalloc
495  * @size: page-size multiple
496  * @gpadl_handle: some funky thing
497  */
498 int vmbus_establish_gpadl(struct vmbus_channel *channel, void *kbuffer,
499                                u32 size, u32 *gpadl_handle)
500 {
501         struct vmbus_channel_gpadl_header *gpadlmsg;
502         struct vmbus_channel_gpadl_body *gpadl_body;
503         /* struct vmbus_channel_gpadl_created *gpadlCreated; */
504         struct vmbus_channel_msginfo *msginfo = NULL;
505         struct vmbus_channel_msginfo *submsginfo;
506         u32 msgcount;
507         struct list_head *curr;
508         u32 next_gpadl_handle;
509         unsigned long flags;
510         int ret = 0;
511
512         next_gpadl_handle = atomic_read(&vmbus_connection.next_gpadl_handle);
513         atomic_inc(&vmbus_connection.next_gpadl_handle);
514
515         ret = create_gpadl_header(kbuffer, size, &msginfo, &msgcount);
516         if (ret)
517                 return ret;
518
519         init_waitqueue_head(&msginfo->waitevent);
520
521         gpadlmsg = (struct vmbus_channel_gpadl_header *)msginfo->msg;
522         gpadlmsg->header.msgtype = CHANNELMSG_GPADL_HEADER;
523         gpadlmsg->child_relid = channel->offermsg.child_relid;
524         gpadlmsg->gpadl = next_gpadl_handle;
525
526         dump_gpadl_header(gpadlmsg);
527
528         spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
529         list_add_tail(&msginfo->msglistentry,
530                       &vmbus_connection.chn_msg_list);
531
532         spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
533         DPRINT_DBG(VMBUS, "buffer %p, size %d msg cnt %d",
534                    kbuffer, size, msgcount);
535
536         DPRINT_DBG(VMBUS, "Sending GPADL Header - len %zd",
537                    msginfo->msgsize - sizeof(*msginfo));
538
539         msginfo->wait_condition = 0;
540         ret = vmbus_post_msg(gpadlmsg, msginfo->msgsize -
541                                sizeof(*msginfo));
542         if (ret != 0) {
543                 DPRINT_ERR(VMBUS, "Unable to open channel - %d", ret);
544                 goto Cleanup;
545         }
546
547         if (msgcount > 1) {
548                 list_for_each(curr, &msginfo->submsglist) {
549
550                         /* FIXME: should this use list_entry() instead ? */
551                         submsginfo = (struct vmbus_channel_msginfo *)curr;
552                         gpadl_body =
553                              (struct vmbus_channel_gpadl_body *)submsginfo->msg;
554
555                         gpadl_body->header.msgtype =
556                                 CHANNELMSG_GPADL_BODY;
557                         gpadl_body->gpadl = next_gpadl_handle;
558
559                         DPRINT_DBG(VMBUS, "Sending GPADL Body - len %zd",
560                                    submsginfo->msgsize -
561                                    sizeof(*submsginfo));
562
563                         dump_gpadl_body(gpadl_body, submsginfo->msgsize -
564                                       sizeof(*submsginfo));
565                         ret = vmbus_post_msg(gpadl_body,
566                                                submsginfo->msgsize -
567                                                sizeof(*submsginfo));
568                         if (ret != 0)
569                                 goto Cleanup;
570
571                 }
572         }
573         wait_event_timeout(msginfo->waitevent,
574                                 msginfo->wait_condition,
575                                 msecs_to_jiffies(1000));
576         BUG_ON(msginfo->wait_condition == 0);
577
578
579         /* At this point, we received the gpadl created msg */
580         DPRINT_DBG(VMBUS, "Received GPADL created "
581                    "(relid %d, status %d handle %x)",
582                    channel->offermsg.child_relid,
583                    msginfo->response.gpadl_created.creation_status,
584                    gpadlmsg->gpadl);
585
586         *gpadl_handle = gpadlmsg->gpadl;
587
588 Cleanup:
589         spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
590         list_del(&msginfo->msglistentry);
591         spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
592
593         kfree(msginfo);
594         return ret;
595 }
596 EXPORT_SYMBOL_GPL(vmbus_establish_gpadl);
597
598 /*
599  * vmbus_teardown_gpadl -Teardown the specified GPADL handle
600  */
601 int vmbus_teardown_gpadl(struct vmbus_channel *channel, u32 gpadl_handle)
602 {
603         struct vmbus_channel_gpadl_teardown *msg;
604         struct vmbus_channel_msginfo *info;
605         unsigned long flags;
606         int ret;
607
608         /* ASSERT(gpadl_handle != 0); */
609
610         info = kmalloc(sizeof(*info) +
611                        sizeof(struct vmbus_channel_gpadl_teardown), GFP_KERNEL);
612         if (!info)
613                 return -ENOMEM;
614
615         init_waitqueue_head(&info->waitevent);
616
617         msg = (struct vmbus_channel_gpadl_teardown *)info->msg;
618
619         msg->header.msgtype = CHANNELMSG_GPADL_TEARDOWN;
620         msg->child_relid = channel->offermsg.child_relid;
621         msg->gpadl = gpadl_handle;
622
623         spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
624         list_add_tail(&info->msglistentry,
625                       &vmbus_connection.chn_msg_list);
626         spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
627         info->wait_condition = 0;
628         ret = vmbus_post_msg(msg,
629                                sizeof(struct vmbus_channel_gpadl_teardown));
630
631         BUG_ON(ret != 0);
632         wait_event_timeout(info->waitevent,
633                         info->wait_condition, msecs_to_jiffies(1000));
634         BUG_ON(info->wait_condition == 0);
635
636         /* Received a torndown response */
637         spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
638         list_del(&info->msglistentry);
639         spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
640
641         kfree(info);
642         return ret;
643 }
644 EXPORT_SYMBOL_GPL(vmbus_teardown_gpadl);
645
646 /*
647  * vmbus_close - Close the specified channel
648  */
649 void vmbus_close(struct vmbus_channel *channel)
650 {
651         struct vmbus_channel_close_channel *msg;
652         struct vmbus_channel_msginfo *info;
653         unsigned long flags;
654         int ret;
655
656         /* Stop callback and cancel the timer asap */
657         channel->onchannel_callback = NULL;
658         del_timer_sync(&channel->poll_timer);
659
660         /* Send a closing message */
661         info = kmalloc(sizeof(*info) +
662                        sizeof(struct vmbus_channel_close_channel), GFP_KERNEL);
663         /* FIXME: can't do anything other than return here because the
664          *        function is void */
665         if (!info)
666                 return;
667
668
669         msg = (struct vmbus_channel_close_channel *)info->msg;
670         msg->header.msgtype = CHANNELMSG_CLOSECHANNEL;
671         msg->child_relid = channel->offermsg.child_relid;
672
673         ret = vmbus_post_msg(msg, sizeof(struct vmbus_channel_close_channel));
674
675         BUG_ON(ret != 0);
676         /* Tear down the gpadl for the channel's ring buffer */
677         if (channel->ringbuffer_gpadlhandle)
678                 vmbus_teardown_gpadl(channel,
679                                           channel->ringbuffer_gpadlhandle);
680
681         /* TODO: Send a msg to release the childRelId */
682
683         /* Cleanup the ring buffers for this channel */
684         ringbuffer_cleanup(&channel->outbound);
685         ringbuffer_cleanup(&channel->inbound);
686
687         free_pages((unsigned long)channel->ringbuffer_pages,
688                 get_order(channel->ringbuffer_pagecount * PAGE_SIZE));
689
690         kfree(info);
691
692         /*
693          * If we are closing the channel during an error path in
694          * opening the channel, don't free the channel since the
695          * caller will free the channel
696          */
697
698         if (channel->state == CHANNEL_OPEN_STATE) {
699                 spin_lock_irqsave(&vmbus_connection.channel_lock, flags);
700                 list_del(&channel->listentry);
701                 spin_unlock_irqrestore(&vmbus_connection.channel_lock, flags);
702
703                 free_channel(channel);
704         }
705 }
706 EXPORT_SYMBOL_GPL(vmbus_close);
707
708 /**
709  * vmbus_sendpacket() - Send the specified buffer on the given channel
710  * @channel: Pointer to vmbus_channel structure.
711  * @buffer: Pointer to the buffer you want to receive the data into.
712  * @bufferlen: Maximum size of what the the buffer will hold
713  * @requestid: Identifier of the request
714  * @type: Type of packet that is being send e.g. negotiate, time
715  * packet etc.
716  *
717  * Sends data in @buffer directly to hyper-v via the vmbus
718  * This will send the data unparsed to hyper-v.
719  *
720  * Mainly used by Hyper-V drivers.
721  */
722 int vmbus_sendpacket(struct vmbus_channel *channel, const void *buffer,
723                            u32 bufferlen, u64 requestid,
724                            enum vmbus_packet_type type, u32 flags)
725 {
726         struct vmpacket_descriptor desc;
727         u32 packetlen = sizeof(struct vmpacket_descriptor) + bufferlen;
728         u32 packetlen_aligned = ALIGN(packetlen, sizeof(u64));
729         struct scatterlist bufferlist[3];
730         u64 aligned_data = 0;
731         int ret;
732
733         DPRINT_DBG(VMBUS, "channel %p buffer %p len %d",
734                    channel, buffer, bufferlen);
735
736         dump_vmbus_channel(channel);
737
738         /* ASSERT((packetLenAligned - packetLen) < sizeof(u64)); */
739
740         /* Setup the descriptor */
741         desc.type = type; /* VmbusPacketTypeDataInBand; */
742         desc.flags = flags; /* VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED; */
743         /* in 8-bytes granularity */
744         desc.offset8 = sizeof(struct vmpacket_descriptor) >> 3;
745         desc.len8 = (u16)(packetlen_aligned >> 3);
746         desc.trans_id = requestid;
747
748         sg_init_table(bufferlist, 3);
749         sg_set_buf(&bufferlist[0], &desc, sizeof(struct vmpacket_descriptor));
750         sg_set_buf(&bufferlist[1], buffer, bufferlen);
751         sg_set_buf(&bufferlist[2], &aligned_data,
752                    packetlen_aligned - packetlen);
753
754         ret = ringbuffer_write(&channel->outbound, bufferlist, 3);
755
756         /* TODO: We should determine if this is optional */
757         if (ret == 0 && !get_ringbuffer_interrupt_mask(&channel->outbound))
758                 vmbus_setevent(channel);
759
760         return ret;
761 }
762 EXPORT_SYMBOL(vmbus_sendpacket);
763
764 /*
765  * vmbus_sendpacket_pagebuffer - Send a range of single-page buffer
766  * packets using a GPADL Direct packet type.
767  */
768 int vmbus_sendpacket_pagebuffer(struct vmbus_channel *channel,
769                                      struct hv_page_buffer pagebuffers[],
770                                      u32 pagecount, void *buffer, u32 bufferlen,
771                                      u64 requestid)
772 {
773         int ret;
774         int i;
775         struct vmbus_channel_packet_page_buffer desc;
776         u32 descsize;
777         u32 packetlen;
778         u32 packetlen_aligned;
779         struct scatterlist bufferlist[3];
780         u64 aligned_data = 0;
781
782         if (pagecount > MAX_PAGE_BUFFER_COUNT)
783                 return -EINVAL;
784
785         dump_vmbus_channel(channel);
786
787         /*
788          * Adjust the size down since vmbus_channel_packet_page_buffer is the
789          * largest size we support
790          */
791         descsize = sizeof(struct vmbus_channel_packet_page_buffer) -
792                           ((MAX_PAGE_BUFFER_COUNT - pagecount) *
793                           sizeof(struct hv_page_buffer));
794         packetlen = descsize + bufferlen;
795         packetlen_aligned = ALIGN(packetlen, sizeof(u64));
796
797         /* ASSERT((packetLenAligned - packetLen) < sizeof(u64)); */
798
799         /* Setup the descriptor */
800         desc.type = VM_PKT_DATA_USING_GPA_DIRECT;
801         desc.flags = VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED;
802         desc.dataoffset8 = descsize >> 3; /* in 8-bytes grandularity */
803         desc.length8 = (u16)(packetlen_aligned >> 3);
804         desc.transactionid = requestid;
805         desc.rangecount = pagecount;
806
807         for (i = 0; i < pagecount; i++) {
808                 desc.range[i].len = pagebuffers[i].len;
809                 desc.range[i].offset = pagebuffers[i].offset;
810                 desc.range[i].pfn        = pagebuffers[i].pfn;
811         }
812
813         sg_init_table(bufferlist, 3);
814         sg_set_buf(&bufferlist[0], &desc, descsize);
815         sg_set_buf(&bufferlist[1], buffer, bufferlen);
816         sg_set_buf(&bufferlist[2], &aligned_data,
817                 packetlen_aligned - packetlen);
818
819         ret = ringbuffer_write(&channel->outbound, bufferlist, 3);
820
821         /* TODO: We should determine if this is optional */
822         if (ret == 0 && !get_ringbuffer_interrupt_mask(&channel->outbound))
823                 vmbus_setevent(channel);
824
825         return ret;
826 }
827 EXPORT_SYMBOL_GPL(vmbus_sendpacket_pagebuffer);
828
829 /*
830  * vmbus_sendpacket_multipagebuffer - Send a multi-page buffer packet
831  * using a GPADL Direct packet type.
832  */
833 int vmbus_sendpacket_multipagebuffer(struct vmbus_channel *channel,
834                                 struct hv_multipage_buffer *multi_pagebuffer,
835                                 void *buffer, u32 bufferlen, u64 requestid)
836 {
837         int ret;
838         struct vmbus_channel_packet_multipage_buffer desc;
839         u32 descsize;
840         u32 packetlen;
841         u32 packetlen_aligned;
842         struct scatterlist bufferlist[3];
843         u64 aligned_data = 0;
844         u32 pfncount = NUM_PAGES_SPANNED(multi_pagebuffer->offset,
845                                          multi_pagebuffer->len);
846
847         dump_vmbus_channel(channel);
848
849         DPRINT_DBG(VMBUS, "data buffer - offset %u len %u pfn count %u",
850                 multi_pagebuffer->offset,
851                 multi_pagebuffer->len, pfncount);
852
853         if ((pfncount < 0) || (pfncount > MAX_MULTIPAGE_BUFFER_COUNT))
854                 return -EINVAL;
855
856         /*
857          * Adjust the size down since vmbus_channel_packet_multipage_buffer is
858          * the largest size we support
859          */
860         descsize = sizeof(struct vmbus_channel_packet_multipage_buffer) -
861                           ((MAX_MULTIPAGE_BUFFER_COUNT - pfncount) *
862                           sizeof(u64));
863         packetlen = descsize + bufferlen;
864         packetlen_aligned = ALIGN(packetlen, sizeof(u64));
865
866         /* ASSERT((packetLenAligned - packetLen) < sizeof(u64)); */
867
868         /* Setup the descriptor */
869         desc.type = VM_PKT_DATA_USING_GPA_DIRECT;
870         desc.flags = VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED;
871         desc.dataoffset8 = descsize >> 3; /* in 8-bytes grandularity */
872         desc.length8 = (u16)(packetlen_aligned >> 3);
873         desc.transactionid = requestid;
874         desc.rangecount = 1;
875
876         desc.range.len = multi_pagebuffer->len;
877         desc.range.offset = multi_pagebuffer->offset;
878
879         memcpy(desc.range.pfn_array, multi_pagebuffer->pfn_array,
880                pfncount * sizeof(u64));
881
882         sg_init_table(bufferlist, 3);
883         sg_set_buf(&bufferlist[0], &desc, descsize);
884         sg_set_buf(&bufferlist[1], buffer, bufferlen);
885         sg_set_buf(&bufferlist[2], &aligned_data,
886                 packetlen_aligned - packetlen);
887
888         ret = ringbuffer_write(&channel->outbound, bufferlist, 3);
889
890         /* TODO: We should determine if this is optional */
891         if (ret == 0 && !get_ringbuffer_interrupt_mask(&channel->outbound))
892                 vmbus_setevent(channel);
893
894         return ret;
895 }
896 EXPORT_SYMBOL_GPL(vmbus_sendpacket_multipagebuffer);
897
898 /**
899  * vmbus_recvpacket() - Retrieve the user packet on the specified channel
900  * @channel: Pointer to vmbus_channel structure.
901  * @buffer: Pointer to the buffer you want to receive the data into.
902  * @bufferlen: Maximum size of what the the buffer will hold
903  * @buffer_actual_len: The actual size of the data after it was received
904  * @requestid: Identifier of the request
905  *
906  * Receives directly from the hyper-v vmbus and puts the data it received
907  * into Buffer. This will receive the data unparsed from hyper-v.
908  *
909  * Mainly used by Hyper-V drivers.
910  */
911 int vmbus_recvpacket(struct vmbus_channel *channel, void *buffer,
912                         u32 bufferlen, u32 *buffer_actual_len, u64 *requestid)
913 {
914         struct vmpacket_descriptor desc;
915         u32 packetlen;
916         u32 userlen;
917         int ret;
918         unsigned long flags;
919
920         *buffer_actual_len = 0;
921         *requestid = 0;
922
923         spin_lock_irqsave(&channel->inbound_lock, flags);
924
925         ret = ringbuffer_peek(&channel->inbound, &desc,
926                              sizeof(struct vmpacket_descriptor));
927         if (ret != 0) {
928                 spin_unlock_irqrestore(&channel->inbound_lock, flags);
929
930                 /* DPRINT_DBG(VMBUS, "nothing to read!!"); */
931                 return 0;
932         }
933
934         /* VmbusChannelClearEvent(Channel); */
935
936         packetlen = desc.len8 << 3;
937         userlen = packetlen - (desc.offset8 << 3);
938         /* ASSERT(userLen > 0); */
939
940         DPRINT_DBG(VMBUS, "packet received on channel %p relid %d <type %d "
941                    "flag %d tid %llx pktlen %d datalen %d> ",
942                    channel, channel->offermsg.child_relid, desc.type,
943                    desc.flags, desc.trans_id, packetlen, userlen);
944
945         *buffer_actual_len = userlen;
946
947         if (userlen > bufferlen) {
948                 spin_unlock_irqrestore(&channel->inbound_lock, flags);
949
950                 DPRINT_ERR(VMBUS, "buffer too small - got %d needs %d",
951                            bufferlen, userlen);
952                 return -1;
953         }
954
955         *requestid = desc.trans_id;
956
957         /* Copy over the packet to the user buffer */
958         ret = ringbuffer_read(&channel->inbound, buffer, userlen,
959                              (desc.offset8 << 3));
960
961         spin_unlock_irqrestore(&channel->inbound_lock, flags);
962
963         return 0;
964 }
965 EXPORT_SYMBOL(vmbus_recvpacket);
966
967 /*
968  * vmbus_recvpacket_raw - Retrieve the raw packet on the specified channel
969  */
970 int vmbus_recvpacket_raw(struct vmbus_channel *channel, void *buffer,
971                               u32 bufferlen, u32 *buffer_actual_len,
972                               u64 *requestid)
973 {
974         struct vmpacket_descriptor desc;
975         u32 packetlen;
976         u32 userlen;
977         int ret;
978         unsigned long flags;
979
980         *buffer_actual_len = 0;
981         *requestid = 0;
982
983         spin_lock_irqsave(&channel->inbound_lock, flags);
984
985         ret = ringbuffer_peek(&channel->inbound, &desc,
986                              sizeof(struct vmpacket_descriptor));
987         if (ret != 0) {
988                 spin_unlock_irqrestore(&channel->inbound_lock, flags);
989
990                 /* DPRINT_DBG(VMBUS, "nothing to read!!"); */
991                 return 0;
992         }
993
994         /* VmbusChannelClearEvent(Channel); */
995
996         packetlen = desc.len8 << 3;
997         userlen = packetlen - (desc.offset8 << 3);
998
999         DPRINT_DBG(VMBUS, "packet received on channel %p relid %d <type %d "
1000                    "flag %d tid %llx pktlen %d datalen %d> ",
1001                    channel, channel->offermsg.child_relid, desc.type,
1002                    desc.flags, desc.trans_id, packetlen, userlen);
1003
1004         *buffer_actual_len = packetlen;
1005
1006         if (packetlen > bufferlen) {
1007                 spin_unlock_irqrestore(&channel->inbound_lock, flags);
1008
1009                 DPRINT_ERR(VMBUS, "buffer too small - needed %d bytes but "
1010                            "got space for only %d bytes", packetlen, bufferlen);
1011                 return -2;
1012         }
1013
1014         *requestid = desc.trans_id;
1015
1016         /* Copy over the entire packet to the user buffer */
1017         ret = ringbuffer_read(&channel->inbound, buffer, packetlen, 0);
1018
1019         spin_unlock_irqrestore(&channel->inbound_lock, flags);
1020         return 0;
1021 }
1022 EXPORT_SYMBOL_GPL(vmbus_recvpacket_raw);
1023
1024 /*
1025  * vmbus_onchannel_event - Channel event callback
1026  */
1027 void vmbus_onchannel_event(struct vmbus_channel *channel)
1028 {
1029         dump_vmbus_channel(channel);
1030         /* ASSERT(Channel->OnChannelCallback); */
1031
1032         channel->onchannel_callback(channel->channel_callback_context);
1033
1034         mod_timer(&channel->poll_timer, jiffies + usecs_to_jiffies(100));
1035 }
1036
1037 /*
1038  * vmbus_ontimer - Timer event callback
1039  */
1040 void vmbus_ontimer(unsigned long data)
1041 {
1042         struct vmbus_channel *channel = (struct vmbus_channel *)data;
1043
1044         if (channel->onchannel_callback)
1045                 channel->onchannel_callback(channel->channel_callback_context);
1046 }
1047
1048 /*
1049  * dump_vmbus_channel- Dump vmbus channel info to the console
1050  */
1051 static void dump_vmbus_channel(struct vmbus_channel *channel)
1052 {
1053         DPRINT_DBG(VMBUS, "Channel (%d)", channel->offermsg.child_relid);
1054         dump_ring_info(&channel->outbound, "Outbound ");
1055         dump_ring_info(&channel->inbound, "Inbound ");
1056 }