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