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