1bb1a801a90d7a523daba3ceb6150fa267dd51b0
[linux-3.10.git] / drivers / 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 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
22
23 #include <linux/kernel.h>
24 #include <linux/sched.h>
25 #include <linux/wait.h>
26 #include <linux/mm.h>
27 #include <linux/slab.h>
28 #include <linux/module.h>
29 #include <linux/hyperv.h>
30
31 #include "hyperv_vmbus.h"
32
33 #define NUM_PAGES_SPANNED(addr, len) \
34 ((PAGE_ALIGN(addr + len) >> PAGE_SHIFT) - (addr >> PAGE_SHIFT))
35
36 /*
37  * vmbus_setevent- Trigger an event notification on the specified
38  * channel.
39  */
40 static void vmbus_setevent(struct vmbus_channel *channel)
41 {
42         struct hv_monitor_page *monitorpage;
43
44         if (channel->offermsg.monitor_allocated) {
45                 /* Each u32 represents 32 channels */
46                 sync_set_bit(channel->offermsg.child_relid & 31,
47                         (unsigned long *) vmbus_connection.send_int_page +
48                         (channel->offermsg.child_relid >> 5));
49
50                 monitorpage = vmbus_connection.monitor_pages;
51                 monitorpage++; /* Get the child to parent monitor page */
52
53                 sync_set_bit(channel->monitor_bit,
54                         (unsigned long *)&monitorpage->trigger_group
55                                         [channel->monitor_grp].pending);
56
57         } else {
58                 vmbus_set_event(channel->offermsg.child_relid);
59         }
60 }
61
62 /*
63  * vmbus_get_debug_info -Retrieve various channel debug info
64  */
65 void vmbus_get_debug_info(struct vmbus_channel *channel,
66                               struct vmbus_channel_debug_info *debuginfo)
67 {
68         struct hv_monitor_page *monitorpage;
69         u8 monitor_group = (u8)channel->offermsg.monitorid / 32;
70         u8 monitor_offset = (u8)channel->offermsg.monitorid % 32;
71
72         debuginfo->relid = channel->offermsg.child_relid;
73         debuginfo->state = channel->state;
74         memcpy(&debuginfo->interfacetype,
75                &channel->offermsg.offer.if_type, sizeof(uuid_le));
76         memcpy(&debuginfo->interface_instance,
77                &channel->offermsg.offer.if_instance,
78                sizeof(uuid_le));
79
80         monitorpage = (struct hv_monitor_page *)vmbus_connection.monitor_pages;
81
82         debuginfo->monitorid = channel->offermsg.monitorid;
83
84         debuginfo->servermonitor_pending =
85                         monitorpage->trigger_group[monitor_group].pending;
86         debuginfo->servermonitor_latency =
87                         monitorpage->latency[monitor_group][monitor_offset];
88         debuginfo->servermonitor_connectionid =
89                         monitorpage->parameter[monitor_group]
90                                         [monitor_offset].connectionid.u.id;
91
92         monitorpage++;
93
94         debuginfo->clientmonitor_pending =
95                         monitorpage->trigger_group[monitor_group].pending;
96         debuginfo->clientmonitor_latency =
97                         monitorpage->latency[monitor_group][monitor_offset];
98         debuginfo->clientmonitor_connectionid =
99                         monitorpage->parameter[monitor_group]
100                                         [monitor_offset].connectionid.u.id;
101
102         hv_ringbuffer_get_debuginfo(&channel->inbound, &debuginfo->inbound);
103         hv_ringbuffer_get_debuginfo(&channel->outbound, &debuginfo->outbound);
104 }
105
106 /*
107  * vmbus_open - Open the specified channel.
108  */
109 int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size,
110                      u32 recv_ringbuffer_size, void *userdata, u32 userdatalen,
111                      void (*onchannelcallback)(void *context), void *context)
112 {
113         struct vmbus_channel_open_channel *open_msg;
114         struct vmbus_channel_msginfo *open_info = NULL;
115         void *in, *out;
116         unsigned long flags;
117         int ret, t, err = 0;
118
119         newchannel->onchannel_callback = onchannelcallback;
120         newchannel->channel_callback_context = context;
121
122         /* Allocate the ring buffer */
123         out = (void *)__get_free_pages(GFP_KERNEL|__GFP_ZERO,
124                 get_order(send_ringbuffer_size + recv_ringbuffer_size));
125
126         if (!out)
127                 return -ENOMEM;
128
129
130         in = (void *)((unsigned long)out + send_ringbuffer_size);
131
132         newchannel->ringbuffer_pages = out;
133         newchannel->ringbuffer_pagecount = (send_ringbuffer_size +
134                                            recv_ringbuffer_size) >> PAGE_SHIFT;
135
136         ret = hv_ringbuffer_init(
137                 &newchannel->outbound, out, send_ringbuffer_size);
138
139         if (ret != 0) {
140                 err = ret;
141                 goto errorout;
142         }
143
144         ret = hv_ringbuffer_init(
145                 &newchannel->inbound, in, recv_ringbuffer_size);
146         if (ret != 0) {
147                 err = ret;
148                 goto errorout;
149         }
150
151
152         /* Establish the gpadl for the ring buffer */
153         newchannel->ringbuffer_gpadlhandle = 0;
154
155         ret = vmbus_establish_gpadl(newchannel,
156                                          newchannel->outbound.ring_buffer,
157                                          send_ringbuffer_size +
158                                          recv_ringbuffer_size,
159                                          &newchannel->ringbuffer_gpadlhandle);
160
161         if (ret != 0) {
162                 err = ret;
163                 goto errorout;
164         }
165
166         /* Create and init the channel open message */
167         open_info = kmalloc(sizeof(*open_info) +
168                            sizeof(struct vmbus_channel_open_channel),
169                            GFP_KERNEL);
170         if (!open_info) {
171                 err = -ENOMEM;
172                 goto errorout;
173         }
174
175         init_completion(&open_info->waitevent);
176
177         open_msg = (struct vmbus_channel_open_channel *)open_info->msg;
178         open_msg->header.msgtype = CHANNELMSG_OPENCHANNEL;
179         open_msg->openid = newchannel->offermsg.child_relid;
180         open_msg->child_relid = newchannel->offermsg.child_relid;
181         open_msg->ringbuffer_gpadlhandle = newchannel->ringbuffer_gpadlhandle;
182         open_msg->downstream_ringbuffer_pageoffset = send_ringbuffer_size >>
183                                                   PAGE_SHIFT;
184         open_msg->server_contextarea_gpadlhandle = 0;
185
186         if (userdatalen > MAX_USER_DEFINED_BYTES) {
187                 err = -EINVAL;
188                 goto errorout;
189         }
190
191         if (userdatalen)
192                 memcpy(open_msg->userdata, userdata, userdatalen);
193
194         spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
195         list_add_tail(&open_info->msglistentry,
196                       &vmbus_connection.chn_msg_list);
197         spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
198
199         ret = vmbus_post_msg(open_msg,
200                                sizeof(struct vmbus_channel_open_channel));
201
202         if (ret != 0)
203                 goto cleanup;
204
205         t = wait_for_completion_timeout(&open_info->waitevent, 5*HZ);
206         if (t == 0) {
207                 err = -ETIMEDOUT;
208                 goto errorout;
209         }
210
211
212         if (open_info->response.open_result.status)
213                 err = open_info->response.open_result.status;
214
215 cleanup:
216         spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
217         list_del(&open_info->msglistentry);
218         spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
219
220         kfree(open_info);
221         return err;
222
223 errorout:
224         hv_ringbuffer_cleanup(&newchannel->outbound);
225         hv_ringbuffer_cleanup(&newchannel->inbound);
226         free_pages((unsigned long)out,
227                 get_order(send_ringbuffer_size + recv_ringbuffer_size));
228         kfree(open_info);
229         return err;
230 }
231 EXPORT_SYMBOL_GPL(vmbus_open);
232
233 /*
234  * create_gpadl_header - Creates a gpadl for the specified buffer
235  */
236 static int create_gpadl_header(void *kbuffer, u32 size,
237                                          struct vmbus_channel_msginfo **msginfo,
238                                          u32 *messagecount)
239 {
240         int i;
241         int pagecount;
242         unsigned long long pfn;
243         struct vmbus_channel_gpadl_header *gpadl_header;
244         struct vmbus_channel_gpadl_body *gpadl_body;
245         struct vmbus_channel_msginfo *msgheader;
246         struct vmbus_channel_msginfo *msgbody = NULL;
247         u32 msgsize;
248
249         int pfnsum, pfncount, pfnleft, pfncurr, pfnsize;
250
251         pagecount = size >> PAGE_SHIFT;
252         pfn = virt_to_phys(kbuffer) >> PAGE_SHIFT;
253
254         /* do we need a gpadl body msg */
255         pfnsize = MAX_SIZE_CHANNEL_MESSAGE -
256                   sizeof(struct vmbus_channel_gpadl_header) -
257                   sizeof(struct gpa_range);
258         pfncount = pfnsize / sizeof(u64);
259
260         if (pagecount > pfncount) {
261                 /* we need a gpadl body */
262                 /* fill in the header */
263                 msgsize = sizeof(struct vmbus_channel_msginfo) +
264                           sizeof(struct vmbus_channel_gpadl_header) +
265                           sizeof(struct gpa_range) + pfncount * sizeof(u64);
266                 msgheader =  kzalloc(msgsize, GFP_KERNEL);
267                 if (!msgheader)
268                         goto nomem;
269
270                 INIT_LIST_HEAD(&msgheader->submsglist);
271                 msgheader->msgsize = msgsize;
272
273                 gpadl_header = (struct vmbus_channel_gpadl_header *)
274                         msgheader->msg;
275                 gpadl_header->rangecount = 1;
276                 gpadl_header->range_buflen = sizeof(struct gpa_range) +
277                                          pagecount * sizeof(u64);
278                 gpadl_header->range[0].byte_offset = 0;
279                 gpadl_header->range[0].byte_count = size;
280                 for (i = 0; i < pfncount; i++)
281                         gpadl_header->range[0].pfn_array[i] = pfn+i;
282                 *msginfo = msgheader;
283                 *messagecount = 1;
284
285                 pfnsum = pfncount;
286                 pfnleft = pagecount - pfncount;
287
288                 /* how many pfns can we fit */
289                 pfnsize = MAX_SIZE_CHANNEL_MESSAGE -
290                           sizeof(struct vmbus_channel_gpadl_body);
291                 pfncount = pfnsize / sizeof(u64);
292
293                 /* fill in the body */
294                 while (pfnleft) {
295                         if (pfnleft > pfncount)
296                                 pfncurr = pfncount;
297                         else
298                                 pfncurr = pfnleft;
299
300                         msgsize = sizeof(struct vmbus_channel_msginfo) +
301                                   sizeof(struct vmbus_channel_gpadl_body) +
302                                   pfncurr * sizeof(u64);
303                         msgbody = kzalloc(msgsize, GFP_KERNEL);
304
305                         if (!msgbody) {
306                                 struct vmbus_channel_msginfo *pos = NULL;
307                                 struct vmbus_channel_msginfo *tmp = NULL;
308                                 /*
309                                  * Free up all the allocated messages.
310                                  */
311                                 list_for_each_entry_safe(pos, tmp,
312                                         &msgheader->submsglist,
313                                         msglistentry) {
314
315                                         list_del(&pos->msglistentry);
316                                         kfree(pos);
317                                 }
318
319                                 goto nomem;
320                         }
321
322                         msgbody->msgsize = msgsize;
323                         (*messagecount)++;
324                         gpadl_body =
325                                 (struct vmbus_channel_gpadl_body *)msgbody->msg;
326
327                         /*
328                          * Gpadl is u32 and we are using a pointer which could
329                          * be 64-bit
330                          * This is governed by the guest/host protocol and
331                          * so the hypervisor gurantees that this is ok.
332                          */
333                         for (i = 0; i < pfncurr; i++)
334                                 gpadl_body->pfn[i] = pfn + pfnsum + i;
335
336                         /* add to msg header */
337                         list_add_tail(&msgbody->msglistentry,
338                                       &msgheader->submsglist);
339                         pfnsum += pfncurr;
340                         pfnleft -= pfncurr;
341                 }
342         } else {
343                 /* everything fits in a header */
344                 msgsize = sizeof(struct vmbus_channel_msginfo) +
345                           sizeof(struct vmbus_channel_gpadl_header) +
346                           sizeof(struct gpa_range) + pagecount * sizeof(u64);
347                 msgheader = kzalloc(msgsize, GFP_KERNEL);
348                 if (msgheader == NULL)
349                         goto nomem;
350                 msgheader->msgsize = msgsize;
351
352                 gpadl_header = (struct vmbus_channel_gpadl_header *)
353                         msgheader->msg;
354                 gpadl_header->rangecount = 1;
355                 gpadl_header->range_buflen = sizeof(struct gpa_range) +
356                                          pagecount * sizeof(u64);
357                 gpadl_header->range[0].byte_offset = 0;
358                 gpadl_header->range[0].byte_count = size;
359                 for (i = 0; i < pagecount; i++)
360                         gpadl_header->range[0].pfn_array[i] = pfn+i;
361
362                 *msginfo = msgheader;
363                 *messagecount = 1;
364         }
365
366         return 0;
367 nomem:
368         kfree(msgheader);
369         kfree(msgbody);
370         return -ENOMEM;
371 }
372
373 /*
374  * vmbus_establish_gpadl - Estabish a GPADL for the specified buffer
375  *
376  * @channel: a channel
377  * @kbuffer: from kmalloc
378  * @size: page-size multiple
379  * @gpadl_handle: some funky thing
380  */
381 int vmbus_establish_gpadl(struct vmbus_channel *channel, void *kbuffer,
382                                u32 size, u32 *gpadl_handle)
383 {
384         struct vmbus_channel_gpadl_header *gpadlmsg;
385         struct vmbus_channel_gpadl_body *gpadl_body;
386         struct vmbus_channel_msginfo *msginfo = NULL;
387         struct vmbus_channel_msginfo *submsginfo;
388         u32 msgcount;
389         struct list_head *curr;
390         u32 next_gpadl_handle;
391         unsigned long flags;
392         int ret = 0;
393         int t;
394
395         next_gpadl_handle = atomic_read(&vmbus_connection.next_gpadl_handle);
396         atomic_inc(&vmbus_connection.next_gpadl_handle);
397
398         ret = create_gpadl_header(kbuffer, size, &msginfo, &msgcount);
399         if (ret)
400                 return ret;
401
402         init_completion(&msginfo->waitevent);
403
404         gpadlmsg = (struct vmbus_channel_gpadl_header *)msginfo->msg;
405         gpadlmsg->header.msgtype = CHANNELMSG_GPADL_HEADER;
406         gpadlmsg->child_relid = channel->offermsg.child_relid;
407         gpadlmsg->gpadl = next_gpadl_handle;
408
409
410         spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
411         list_add_tail(&msginfo->msglistentry,
412                       &vmbus_connection.chn_msg_list);
413
414         spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
415
416         ret = vmbus_post_msg(gpadlmsg, msginfo->msgsize -
417                                sizeof(*msginfo));
418         if (ret != 0)
419                 goto cleanup;
420
421         if (msgcount > 1) {
422                 list_for_each(curr, &msginfo->submsglist) {
423
424                         submsginfo = (struct vmbus_channel_msginfo *)curr;
425                         gpadl_body =
426                              (struct vmbus_channel_gpadl_body *)submsginfo->msg;
427
428                         gpadl_body->header.msgtype =
429                                 CHANNELMSG_GPADL_BODY;
430                         gpadl_body->gpadl = next_gpadl_handle;
431
432                         ret = vmbus_post_msg(gpadl_body,
433                                                submsginfo->msgsize -
434                                                sizeof(*submsginfo));
435                         if (ret != 0)
436                                 goto cleanup;
437
438                 }
439         }
440         t = wait_for_completion_timeout(&msginfo->waitevent, 5*HZ);
441         BUG_ON(t == 0);
442
443
444         /* At this point, we received the gpadl created msg */
445         *gpadl_handle = gpadlmsg->gpadl;
446
447 cleanup:
448         spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
449         list_del(&msginfo->msglistentry);
450         spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
451
452         kfree(msginfo);
453         return ret;
454 }
455 EXPORT_SYMBOL_GPL(vmbus_establish_gpadl);
456
457 /*
458  * vmbus_teardown_gpadl -Teardown the specified GPADL handle
459  */
460 int vmbus_teardown_gpadl(struct vmbus_channel *channel, u32 gpadl_handle)
461 {
462         struct vmbus_channel_gpadl_teardown *msg;
463         struct vmbus_channel_msginfo *info;
464         unsigned long flags;
465         int ret, t;
466
467         info = kmalloc(sizeof(*info) +
468                        sizeof(struct vmbus_channel_gpadl_teardown), GFP_KERNEL);
469         if (!info)
470                 return -ENOMEM;
471
472         init_completion(&info->waitevent);
473
474         msg = (struct vmbus_channel_gpadl_teardown *)info->msg;
475
476         msg->header.msgtype = CHANNELMSG_GPADL_TEARDOWN;
477         msg->child_relid = channel->offermsg.child_relid;
478         msg->gpadl = gpadl_handle;
479
480         spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
481         list_add_tail(&info->msglistentry,
482                       &vmbus_connection.chn_msg_list);
483         spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
484         ret = vmbus_post_msg(msg,
485                                sizeof(struct vmbus_channel_gpadl_teardown));
486
487         BUG_ON(ret != 0);
488         t = wait_for_completion_timeout(&info->waitevent, 5*HZ);
489         BUG_ON(t == 0);
490
491         /* Received a torndown response */
492         spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
493         list_del(&info->msglistentry);
494         spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
495
496         kfree(info);
497         return ret;
498 }
499 EXPORT_SYMBOL_GPL(vmbus_teardown_gpadl);
500
501 /*
502  * vmbus_close - Close the specified channel
503  */
504 void vmbus_close(struct vmbus_channel *channel)
505 {
506         struct vmbus_channel_close_channel *msg;
507         int ret;
508         unsigned long flags;
509
510         /* Stop callback and cancel the timer asap */
511         spin_lock_irqsave(&channel->inbound_lock, flags);
512         channel->onchannel_callback = NULL;
513         spin_unlock_irqrestore(&channel->inbound_lock, flags);
514
515         /* Send a closing message */
516
517         msg = &channel->close_msg.msg;
518
519         msg->header.msgtype = CHANNELMSG_CLOSECHANNEL;
520         msg->child_relid = channel->offermsg.child_relid;
521
522         ret = vmbus_post_msg(msg, sizeof(struct vmbus_channel_close_channel));
523
524         BUG_ON(ret != 0);
525         /* Tear down the gpadl for the channel's ring buffer */
526         if (channel->ringbuffer_gpadlhandle)
527                 vmbus_teardown_gpadl(channel,
528                                           channel->ringbuffer_gpadlhandle);
529
530         /* Cleanup the ring buffers for this channel */
531         hv_ringbuffer_cleanup(&channel->outbound);
532         hv_ringbuffer_cleanup(&channel->inbound);
533
534         free_pages((unsigned long)channel->ringbuffer_pages,
535                 get_order(channel->ringbuffer_pagecount * PAGE_SIZE));
536
537
538 }
539 EXPORT_SYMBOL_GPL(vmbus_close);
540
541 /**
542  * vmbus_sendpacket() - Send the specified buffer on the given channel
543  * @channel: Pointer to vmbus_channel structure.
544  * @buffer: Pointer to the buffer you want to receive the data into.
545  * @bufferlen: Maximum size of what the the buffer will hold
546  * @requestid: Identifier of the request
547  * @type: Type of packet that is being send e.g. negotiate, time
548  * packet etc.
549  *
550  * Sends data in @buffer directly to hyper-v via the vmbus
551  * This will send the data unparsed to hyper-v.
552  *
553  * Mainly used by Hyper-V drivers.
554  */
555 int vmbus_sendpacket(struct vmbus_channel *channel, const void *buffer,
556                            u32 bufferlen, u64 requestid,
557                            enum vmbus_packet_type type, u32 flags)
558 {
559         struct vmpacket_descriptor desc;
560         u32 packetlen = sizeof(struct vmpacket_descriptor) + bufferlen;
561         u32 packetlen_aligned = ALIGN(packetlen, sizeof(u64));
562         struct scatterlist bufferlist[3];
563         u64 aligned_data = 0;
564         int ret;
565
566
567         /* Setup the descriptor */
568         desc.type = type; /* VmbusPacketTypeDataInBand; */
569         desc.flags = flags; /* VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED; */
570         /* in 8-bytes granularity */
571         desc.offset8 = sizeof(struct vmpacket_descriptor) >> 3;
572         desc.len8 = (u16)(packetlen_aligned >> 3);
573         desc.trans_id = requestid;
574
575         sg_init_table(bufferlist, 3);
576         sg_set_buf(&bufferlist[0], &desc, sizeof(struct vmpacket_descriptor));
577         sg_set_buf(&bufferlist[1], buffer, bufferlen);
578         sg_set_buf(&bufferlist[2], &aligned_data,
579                    packetlen_aligned - packetlen);
580
581         ret = hv_ringbuffer_write(&channel->outbound, bufferlist, 3);
582
583         if (ret == 0 && !hv_get_ringbuffer_interrupt_mask(&channel->outbound))
584                 vmbus_setevent(channel);
585
586         return ret;
587 }
588 EXPORT_SYMBOL(vmbus_sendpacket);
589
590 /*
591  * vmbus_sendpacket_pagebuffer - Send a range of single-page buffer
592  * packets using a GPADL Direct packet type.
593  */
594 int vmbus_sendpacket_pagebuffer(struct vmbus_channel *channel,
595                                      struct hv_page_buffer pagebuffers[],
596                                      u32 pagecount, void *buffer, u32 bufferlen,
597                                      u64 requestid)
598 {
599         int ret;
600         int i;
601         struct vmbus_channel_packet_page_buffer desc;
602         u32 descsize;
603         u32 packetlen;
604         u32 packetlen_aligned;
605         struct scatterlist bufferlist[3];
606         u64 aligned_data = 0;
607
608         if (pagecount > MAX_PAGE_BUFFER_COUNT)
609                 return -EINVAL;
610
611
612         /*
613          * Adjust the size down since vmbus_channel_packet_page_buffer is the
614          * largest size we support
615          */
616         descsize = sizeof(struct vmbus_channel_packet_page_buffer) -
617                           ((MAX_PAGE_BUFFER_COUNT - pagecount) *
618                           sizeof(struct hv_page_buffer));
619         packetlen = descsize + bufferlen;
620         packetlen_aligned = ALIGN(packetlen, sizeof(u64));
621
622         /* Setup the descriptor */
623         desc.type = VM_PKT_DATA_USING_GPA_DIRECT;
624         desc.flags = VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED;
625         desc.dataoffset8 = descsize >> 3; /* in 8-bytes grandularity */
626         desc.length8 = (u16)(packetlen_aligned >> 3);
627         desc.transactionid = requestid;
628         desc.rangecount = pagecount;
629
630         for (i = 0; i < pagecount; i++) {
631                 desc.range[i].len = pagebuffers[i].len;
632                 desc.range[i].offset = pagebuffers[i].offset;
633                 desc.range[i].pfn        = pagebuffers[i].pfn;
634         }
635
636         sg_init_table(bufferlist, 3);
637         sg_set_buf(&bufferlist[0], &desc, descsize);
638         sg_set_buf(&bufferlist[1], buffer, bufferlen);
639         sg_set_buf(&bufferlist[2], &aligned_data,
640                 packetlen_aligned - packetlen);
641
642         ret = hv_ringbuffer_write(&channel->outbound, bufferlist, 3);
643
644         if (ret == 0 && !hv_get_ringbuffer_interrupt_mask(&channel->outbound))
645                 vmbus_setevent(channel);
646
647         return ret;
648 }
649 EXPORT_SYMBOL_GPL(vmbus_sendpacket_pagebuffer);
650
651 /*
652  * vmbus_sendpacket_multipagebuffer - Send a multi-page buffer packet
653  * using a GPADL Direct packet type.
654  */
655 int vmbus_sendpacket_multipagebuffer(struct vmbus_channel *channel,
656                                 struct hv_multipage_buffer *multi_pagebuffer,
657                                 void *buffer, u32 bufferlen, u64 requestid)
658 {
659         int ret;
660         struct vmbus_channel_packet_multipage_buffer desc;
661         u32 descsize;
662         u32 packetlen;
663         u32 packetlen_aligned;
664         struct scatterlist bufferlist[3];
665         u64 aligned_data = 0;
666         u32 pfncount = NUM_PAGES_SPANNED(multi_pagebuffer->offset,
667                                          multi_pagebuffer->len);
668
669
670         if ((pfncount < 0) || (pfncount > MAX_MULTIPAGE_BUFFER_COUNT))
671                 return -EINVAL;
672
673         /*
674          * Adjust the size down since vmbus_channel_packet_multipage_buffer is
675          * the largest size we support
676          */
677         descsize = sizeof(struct vmbus_channel_packet_multipage_buffer) -
678                           ((MAX_MULTIPAGE_BUFFER_COUNT - pfncount) *
679                           sizeof(u64));
680         packetlen = descsize + bufferlen;
681         packetlen_aligned = ALIGN(packetlen, sizeof(u64));
682
683
684         /* Setup the descriptor */
685         desc.type = VM_PKT_DATA_USING_GPA_DIRECT;
686         desc.flags = VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED;
687         desc.dataoffset8 = descsize >> 3; /* in 8-bytes grandularity */
688         desc.length8 = (u16)(packetlen_aligned >> 3);
689         desc.transactionid = requestid;
690         desc.rangecount = 1;
691
692         desc.range.len = multi_pagebuffer->len;
693         desc.range.offset = multi_pagebuffer->offset;
694
695         memcpy(desc.range.pfn_array, multi_pagebuffer->pfn_array,
696                pfncount * sizeof(u64));
697
698         sg_init_table(bufferlist, 3);
699         sg_set_buf(&bufferlist[0], &desc, descsize);
700         sg_set_buf(&bufferlist[1], buffer, bufferlen);
701         sg_set_buf(&bufferlist[2], &aligned_data,
702                 packetlen_aligned - packetlen);
703
704         ret = hv_ringbuffer_write(&channel->outbound, bufferlist, 3);
705
706         if (ret == 0 && !hv_get_ringbuffer_interrupt_mask(&channel->outbound))
707                 vmbus_setevent(channel);
708
709         return ret;
710 }
711 EXPORT_SYMBOL_GPL(vmbus_sendpacket_multipagebuffer);
712
713 /**
714  * vmbus_recvpacket() - Retrieve the user packet on the specified channel
715  * @channel: Pointer to vmbus_channel structure.
716  * @buffer: Pointer to the buffer you want to receive the data into.
717  * @bufferlen: Maximum size of what the the buffer will hold
718  * @buffer_actual_len: The actual size of the data after it was received
719  * @requestid: Identifier of the request
720  *
721  * Receives directly from the hyper-v vmbus and puts the data it received
722  * into Buffer. This will receive the data unparsed from hyper-v.
723  *
724  * Mainly used by Hyper-V drivers.
725  */
726 int vmbus_recvpacket(struct vmbus_channel *channel, void *buffer,
727                         u32 bufferlen, u32 *buffer_actual_len, u64 *requestid)
728 {
729         struct vmpacket_descriptor desc;
730         u32 packetlen;
731         u32 userlen;
732         int ret;
733
734         *buffer_actual_len = 0;
735         *requestid = 0;
736
737
738         ret = hv_ringbuffer_peek(&channel->inbound, &desc,
739                              sizeof(struct vmpacket_descriptor));
740         if (ret != 0)
741                 return 0;
742
743         packetlen = desc.len8 << 3;
744         userlen = packetlen - (desc.offset8 << 3);
745
746         *buffer_actual_len = userlen;
747
748         if (userlen > bufferlen) {
749
750                 pr_err("Buffer too small - got %d needs %d\n",
751                            bufferlen, userlen);
752                 return -ETOOSMALL;
753         }
754
755         *requestid = desc.trans_id;
756
757         /* Copy over the packet to the user buffer */
758         ret = hv_ringbuffer_read(&channel->inbound, buffer, userlen,
759                              (desc.offset8 << 3));
760
761
762         return 0;
763 }
764 EXPORT_SYMBOL(vmbus_recvpacket);
765
766 /*
767  * vmbus_recvpacket_raw - Retrieve the raw packet on the specified channel
768  */
769 int vmbus_recvpacket_raw(struct vmbus_channel *channel, void *buffer,
770                               u32 bufferlen, u32 *buffer_actual_len,
771                               u64 *requestid)
772 {
773         struct vmpacket_descriptor desc;
774         u32 packetlen;
775         u32 userlen;
776         int ret;
777
778         *buffer_actual_len = 0;
779         *requestid = 0;
780
781
782         ret = hv_ringbuffer_peek(&channel->inbound, &desc,
783                              sizeof(struct vmpacket_descriptor));
784         if (ret != 0)
785                 return 0;
786
787
788         packetlen = desc.len8 << 3;
789         userlen = packetlen - (desc.offset8 << 3);
790
791         *buffer_actual_len = packetlen;
792
793         if (packetlen > bufferlen) {
794                 pr_err("Buffer too small - needed %d bytes but "
795                         "got space for only %d bytes\n",
796                         packetlen, bufferlen);
797                 return -ENOBUFS;
798         }
799
800         *requestid = desc.trans_id;
801
802         /* Copy over the entire packet to the user buffer */
803         ret = hv_ringbuffer_read(&channel->inbound, buffer, packetlen, 0);
804
805         return 0;
806 }
807 EXPORT_SYMBOL_GPL(vmbus_recvpacket_raw);