channel.c 25.6 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/*
 * Copyright (c) 2009, Microsoft Corporation.
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms and conditions of the GNU General Public License,
 * version 2, as published by the Free Software Foundation.
 *
 * This program is distributed in the hope it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
 * Place - Suite 330, Boston, MA 02111-1307 USA.
 *
 * Authors:
 *   Haiyang Zhang <haiyangz@microsoft.com>
 *   Hank Janssen  <hjanssen@microsoft.com>
 */
21
22
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt

23
#include <linux/kernel.h>
24
25
#include <linux/sched.h>
#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
#include <linux/uio.h>
31
#include <linux/interrupt.h>
32

33
#include "hyperv_vmbus.h"
34

35
36
37
#define NUM_PAGES_SPANNED(addr, len) \
((PAGE_ALIGN(addr + len) >> PAGE_SHIFT) - (addr >> PAGE_SHIFT))

38
/*
39
 * vmbus_setevent- Trigger an event notification on the specified
40
 * channel.
41
 */
42
void vmbus_setevent(struct vmbus_channel *channel)
43
{
44
	struct hv_monitor_page *monitorpage;
45

46
47
48
49
	/*
	 * For channels marked as in "low latency" mode
	 * bypass the monitor page mechanism.
	 */
50
51
	if (channel->offermsg.monitor_allocated && !channel->low_latency) {
		vmbus_send_interrupt(channel->offermsg.child_relid);
52

53
54
		/* Get the child to parent monitor page */
		monitorpage = vmbus_connection.monitor_pages[1];
55

56
		sync_set_bit(channel->monitor_bit,
57
58
			(unsigned long *)&monitorpage->trigger_group
					[channel->monitor_grp].pending);
59

60
	} else {
61
		vmbus_set_event(channel);
62
63
	}
}
64
EXPORT_SYMBOL_GPL(vmbus_setevent);
65

66
/*
67
 * vmbus_open - Open the specified channel.
68
 */
69
int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size,
70
71
		     u32 recv_ringbuffer_size, void *userdata, u32 userdatalen,
		     void (*onchannelcallback)(void *context), void *context)
72
{
73
	struct vmbus_channel_open_channel *open_msg;
74
	struct vmbus_channel_msginfo *open_info = NULL;
75
	unsigned long flags;
76
	int ret, err = 0;
77
	struct page *page;
78

79
80
81
82
	if (send_ringbuffer_size % PAGE_SIZE ||
	    recv_ringbuffer_size % PAGE_SIZE)
		return -EINVAL;

83
	spin_lock_irqsave(&newchannel->lock, flags);
84
85
86
	if (newchannel->state == CHANNEL_OPEN_STATE) {
		newchannel->state = CHANNEL_OPENING_STATE;
	} else {
87
		spin_unlock_irqrestore(&newchannel->lock, flags);
88
89
		return -EINVAL;
	}
90
	spin_unlock_irqrestore(&newchannel->lock, flags);
91

92
93
	newchannel->onchannel_callback = onchannelcallback;
	newchannel->channel_callback_context = context;
94

95
	/* Allocate the ring buffer */
96
97
98
99
100
101
	page = alloc_pages_node(cpu_to_node(newchannel->target_cpu),
				GFP_KERNEL|__GFP_ZERO,
				get_order(send_ringbuffer_size +
				recv_ringbuffer_size));

	if (!page)
102
103
104
		page = alloc_pages(GFP_KERNEL|__GFP_ZERO,
				   get_order(send_ringbuffer_size +
					     recv_ringbuffer_size));
105

106
	if (!page) {
107
		err = -ENOMEM;
108
		goto error_set_chnstate;
109
	}
110

111
	newchannel->ringbuffer_pages = page_address(page);
112
	newchannel->ringbuffer_pagecount = (send_ringbuffer_size +
113
					   recv_ringbuffer_size) >> PAGE_SHIFT;
114

115
116
	ret = hv_ringbuffer_init(&newchannel->outbound, page,
				 send_ringbuffer_size >> PAGE_SHIFT);
117

118
	if (ret != 0) {
119
		err = ret;
120
		goto error_free_pages;
121
122
	}

123
124
125
	ret = hv_ringbuffer_init(&newchannel->inbound,
				 &page[send_ringbuffer_size >> PAGE_SHIFT],
				 recv_ringbuffer_size >> PAGE_SHIFT);
126
	if (ret != 0) {
127
		err = ret;
128
		goto error_free_pages;
129
	}
130
131


132
	/* Establish the gpadl for the ring buffer */
133
	newchannel->ringbuffer_gpadlhandle = 0;
134

135
	ret = vmbus_establish_gpadl(newchannel,
136
137
138
139
				    page_address(page),
				    send_ringbuffer_size +
				    recv_ringbuffer_size,
				    &newchannel->ringbuffer_gpadlhandle);
140

141
	if (ret != 0) {
142
		err = ret;
143
		goto error_free_pages;
144
	}
145

146
	/* Create and init the channel open message */
147
	open_info = kmalloc(sizeof(*open_info) +
148
149
			   sizeof(struct vmbus_channel_open_channel),
			   GFP_KERNEL);
150
	if (!open_info) {
151
		err = -ENOMEM;
152
		goto error_free_gpadl;
153
	}
154

155
	init_completion(&open_info->waitevent);
156
	open_info->waiting_channel = newchannel;
157

158
	open_msg = (struct vmbus_channel_open_channel *)open_info->msg;
159
160
161
162
163
	open_msg->header.msgtype = CHANNELMSG_OPENCHANNEL;
	open_msg->openid = newchannel->offermsg.child_relid;
	open_msg->child_relid = newchannel->offermsg.child_relid;
	open_msg->ringbuffer_gpadlhandle = newchannel->ringbuffer_gpadlhandle;
	open_msg->downstream_ringbuffer_pageoffset = send_ringbuffer_size >>
164
						  PAGE_SHIFT;
165
	open_msg->target_vp = newchannel->target_vp;
166

167
	if (userdatalen > MAX_USER_DEFINED_BYTES) {
168
		err = -EINVAL;
169
		goto error_free_gpadl;
170
171
	}

172
	if (userdatalen)
173
		memcpy(open_msg->userdata, userdata, userdatalen);
174

175
	spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
176
	list_add_tail(&open_info->msglistentry,
177
		      &vmbus_connection.chn_msg_list);
178
	spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
179

180
	ret = vmbus_post_msg(open_msg,
181
			     sizeof(struct vmbus_channel_open_channel), true);
182

183
184
	if (ret != 0) {
		err = ret;
185
		goto error_clean_msglist;
186
	}
187

188
	wait_for_completion(&open_info->waitevent);
189

190
	spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
191
	list_del(&open_info->msglistentry);
192
	spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
193

194
195
196
197
198
	if (newchannel->rescind) {
		err = -ENODEV;
		goto error_free_gpadl;
	}

199
200
	if (open_info->response.open_result.status) {
		err = -EAGAIN;
201
		goto error_free_gpadl;
202
	}
203

204
	newchannel->state = CHANNEL_OPENED_STATE;
205
	kfree(open_info);
206
	return 0;
207

208
error_clean_msglist:
209
210
211
212
	spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
	list_del(&open_info->msglistentry);
	spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);

213
error_free_gpadl:
214
	vmbus_teardown_gpadl(newchannel, newchannel->ringbuffer_gpadlhandle);
215
216
	kfree(open_info);
error_free_pages:
217
218
219
220
	hv_ringbuffer_cleanup(&newchannel->outbound);
	hv_ringbuffer_cleanup(&newchannel->inbound);
	__free_pages(page,
		     get_order(send_ringbuffer_size + recv_ringbuffer_size));
221
error_set_chnstate:
222
	newchannel->state = CHANNEL_OPEN_STATE;
223
	return err;
224
}
225
EXPORT_SYMBOL_GPL(vmbus_open);
226

227
228
229
230
231
232
233
234
235
236
237
/* Used for Hyper-V Socket: a guest client's connect() to the host */
int vmbus_send_tl_connect_request(const uuid_le *shv_guest_servie_id,
				  const uuid_le *shv_host_servie_id)
{
	struct vmbus_channel_tl_connect_request conn_msg;

	memset(&conn_msg, 0, sizeof(conn_msg));
	conn_msg.header.msgtype = CHANNELMSG_TL_CONNECT_REQUEST;
	conn_msg.guest_endpoint_id = *shv_guest_servie_id;
	conn_msg.host_service_id = *shv_host_servie_id;

238
	return vmbus_post_msg(&conn_msg, sizeof(conn_msg), true);
239
240
241
}
EXPORT_SYMBOL_GPL(vmbus_send_tl_connect_request);

242
/*
243
 * create_gpadl_header - Creates a gpadl for the specified buffer
244
 */
245
static int create_gpadl_header(void *kbuffer, u32 size,
246
			       struct vmbus_channel_msginfo **msginfo)
247
248
{
	int i;
249
250
251
252
253
254
	int pagecount;
	struct vmbus_channel_gpadl_header *gpadl_header;
	struct vmbus_channel_gpadl_body *gpadl_body;
	struct vmbus_channel_msginfo *msgheader;
	struct vmbus_channel_msginfo *msgbody = NULL;
	u32 msgsize;
255

256
	int pfnsum, pfncount, pfnleft, pfncurr, pfnsize;
257

258
	pagecount = size >> PAGE_SHIFT;
259

260
	/* do we need a gpadl body msg */
261
	pfnsize = MAX_SIZE_CHANNEL_MESSAGE -
262
263
		  sizeof(struct vmbus_channel_gpadl_header) -
		  sizeof(struct gpa_range);
264
	pfncount = pfnsize / sizeof(u64);
265

266
	if (pagecount > pfncount) {
267
		/* we need a gpadl body */
268
		/* fill in the header */
269
		msgsize = sizeof(struct vmbus_channel_msginfo) +
270
			  sizeof(struct vmbus_channel_gpadl_header) +
271
272
273
			  sizeof(struct gpa_range) + pfncount * sizeof(u64);
		msgheader =  kzalloc(msgsize, GFP_KERNEL);
		if (!msgheader)
274
			goto nomem;
275

276
277
		INIT_LIST_HEAD(&msgheader->submsglist);
		msgheader->msgsize = msgsize;
278

279
		gpadl_header = (struct vmbus_channel_gpadl_header *)
280
281
282
			msgheader->msg;
		gpadl_header->rangecount = 1;
		gpadl_header->range_buflen = sizeof(struct gpa_range) +
283
					 pagecount * sizeof(u64);
284
285
		gpadl_header->range[0].byte_offset = 0;
		gpadl_header->range[0].byte_count = size;
286
		for (i = 0; i < pfncount; i++)
287
288
			gpadl_header->range[0].pfn_array[i] = slow_virt_to_phys(
				kbuffer + PAGE_SIZE * i) >> PAGE_SHIFT;
289
		*msginfo = msgheader;
290

291
292
		pfnsum = pfncount;
		pfnleft = pagecount - pfncount;
293

294
		/* how many pfns can we fit */
295
		pfnsize = MAX_SIZE_CHANNEL_MESSAGE -
296
			  sizeof(struct vmbus_channel_gpadl_body);
297
		pfncount = pfnsize / sizeof(u64);
298

299
		/* fill in the body */
300
301
302
		while (pfnleft) {
			if (pfnleft > pfncount)
				pfncurr = pfncount;
303
			else
304
				pfncurr = pfnleft;
305

306
			msgsize = sizeof(struct vmbus_channel_msginfo) +
307
				  sizeof(struct vmbus_channel_gpadl_body) +
308
309
				  pfncurr * sizeof(u64);
			msgbody = kzalloc(msgsize, GFP_KERNEL);
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324

			if (!msgbody) {
				struct vmbus_channel_msginfo *pos = NULL;
				struct vmbus_channel_msginfo *tmp = NULL;
				/*
				 * Free up all the allocated messages.
				 */
				list_for_each_entry_safe(pos, tmp,
					&msgheader->submsglist,
					msglistentry) {

					list_del(&pos->msglistentry);
					kfree(pos);
				}

325
				goto nomem;
326
327
			}

328
			msgbody->msgsize = msgsize;
329
			gpadl_body =
330
				(struct vmbus_channel_gpadl_body *)msgbody->msg;
331
332
333
334

			/*
			 * Gpadl is u32 and we are using a pointer which could
			 * be 64-bit
335
336
			 * This is governed by the guest/host protocol and
			 * so the hypervisor gurantees that this is ok.
337
			 */
338
			for (i = 0; i < pfncurr; i++)
339
340
341
				gpadl_body->pfn[i] = slow_virt_to_phys(
					kbuffer + PAGE_SIZE * (pfnsum + i)) >>
					PAGE_SHIFT;
342

343
			/* add to msg header */
344
345
			list_add_tail(&msgbody->msglistentry,
				      &msgheader->submsglist);
346
347
			pfnsum += pfncurr;
			pfnleft -= pfncurr;
348
		}
349
	} else {
350
		/* everything fits in a header */
351
		msgsize = sizeof(struct vmbus_channel_msginfo) +
352
			  sizeof(struct vmbus_channel_gpadl_header) +
353
354
355
			  sizeof(struct gpa_range) + pagecount * sizeof(u64);
		msgheader = kzalloc(msgsize, GFP_KERNEL);
		if (msgheader == NULL)
356
			goto nomem;
357
358

		INIT_LIST_HEAD(&msgheader->submsglist);
359
		msgheader->msgsize = msgsize;
360
361

		gpadl_header = (struct vmbus_channel_gpadl_header *)
362
363
364
			msgheader->msg;
		gpadl_header->rangecount = 1;
		gpadl_header->range_buflen = sizeof(struct gpa_range) +
365
					 pagecount * sizeof(u64);
366
367
		gpadl_header->range[0].byte_offset = 0;
		gpadl_header->range[0].byte_count = size;
368
		for (i = 0; i < pagecount; i++)
369
370
			gpadl_header->range[0].pfn_array[i] = slow_virt_to_phys(
				kbuffer + PAGE_SIZE * i) >> PAGE_SHIFT;
371
372

		*msginfo = msgheader;
373
374
375
	}

	return 0;
376
nomem:
377
378
	kfree(msgheader);
	kfree(msgbody);
379
	return -ENOMEM;
380
381
}

382
/*
383
 * vmbus_establish_gpadl - Estabish a GPADL for the specified buffer
384
 *
385
 * @channel: a channel
386
 * @kbuffer: from kmalloc or vmalloc
387
388
 * @size: page-size multiple
 * @gpadl_handle: some funky thing
389
 */
390
int vmbus_establish_gpadl(struct vmbus_channel *channel, void *kbuffer,
391
			       u32 size, u32 *gpadl_handle)
392
{
393
394
395
	struct vmbus_channel_gpadl_header *gpadlmsg;
	struct vmbus_channel_gpadl_body *gpadl_body;
	struct vmbus_channel_msginfo *msginfo = NULL;
396
	struct vmbus_channel_msginfo *submsginfo, *tmp;
397
	struct list_head *curr;
398
	u32 next_gpadl_handle;
399
	unsigned long flags;
400
	int ret = 0;
401

402
403
	next_gpadl_handle =
		(atomic_inc_return(&vmbus_connection.next_gpadl_handle) - 1);
404

405
	ret = create_gpadl_header(kbuffer, size, &msginfo);
406
407
	if (ret)
		return ret;
408

409
	init_completion(&msginfo->waitevent);
410
	msginfo->waiting_channel = channel;
411

412
413
414
415
	gpadlmsg = (struct vmbus_channel_gpadl_header *)msginfo->msg;
	gpadlmsg->header.msgtype = CHANNELMSG_GPADL_HEADER;
	gpadlmsg->child_relid = channel->offermsg.child_relid;
	gpadlmsg->gpadl = next_gpadl_handle;
416
417


418
	spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
419
	list_add_tail(&msginfo->msglistentry,
420
		      &vmbus_connection.chn_msg_list);
421

422
	spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
423

424
	ret = vmbus_post_msg(gpadlmsg, msginfo->msgsize -
425
			     sizeof(*msginfo), true);
426
	if (ret != 0)
427
		goto cleanup;
428

429
430
431
432
	list_for_each(curr, &msginfo->submsglist) {
		submsginfo = (struct vmbus_channel_msginfo *)curr;
		gpadl_body =
			(struct vmbus_channel_gpadl_body *)submsginfo->msg;
433

434
435
436
		gpadl_body->header.msgtype =
			CHANNELMSG_GPADL_BODY;
		gpadl_body->gpadl = next_gpadl_handle;
437

438
		ret = vmbus_post_msg(gpadl_body,
439
440
				     submsginfo->msgsize - sizeof(*submsginfo),
				     true);
441
442
		if (ret != 0)
			goto cleanup;
443
444

	}
445
	wait_for_completion(&msginfo->waitevent);
446

447
448
449
450
451
	if (channel->rescind) {
		ret = -ENODEV;
		goto cleanup;
	}

452
	/* At this point, we received the gpadl created msg */
453
	*gpadl_handle = gpadlmsg->gpadl;
454

455
cleanup:
456
	spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
457
	list_del(&msginfo->msglistentry);
458
	spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
459
460
461
462
	list_for_each_entry_safe(submsginfo, tmp, &msginfo->submsglist,
				 msglistentry) {
		kfree(submsginfo);
	}
463

464
	kfree(msginfo);
465
466
	return ret;
}
467
EXPORT_SYMBOL_GPL(vmbus_establish_gpadl);
468

469
/*
470
 * vmbus_teardown_gpadl -Teardown the specified GPADL handle
471
 */
472
int vmbus_teardown_gpadl(struct vmbus_channel *channel, u32 gpadl_handle)
473
{
474
	struct vmbus_channel_gpadl_teardown *msg;
475
	struct vmbus_channel_msginfo *info;
476
	unsigned long flags;
477
	int ret;
478

479
480
	info = kmalloc(sizeof(*info) +
		       sizeof(struct vmbus_channel_gpadl_teardown), GFP_KERNEL);
481
482
	if (!info)
		return -ENOMEM;
483

484
	init_completion(&info->waitevent);
485
	info->waiting_channel = channel;
486

487
	msg = (struct vmbus_channel_gpadl_teardown *)info->msg;
488

489
490
491
	msg->header.msgtype = CHANNELMSG_GPADL_TEARDOWN;
	msg->child_relid = channel->offermsg.child_relid;
	msg->gpadl = gpadl_handle;
492

493
	spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
494
	list_add_tail(&info->msglistentry,
495
		      &vmbus_connection.chn_msg_list);
496
	spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
497
498
	ret = vmbus_post_msg(msg, sizeof(struct vmbus_channel_gpadl_teardown),
			     true);
499

500
501
502
503
	if (ret)
		goto post_msg_err;

	wait_for_completion(&info->waitevent);
504

505
post_msg_err:
506
507
508
509
510
511
512
513
	/*
	 * If the channel has been rescinded;
	 * we will be awakened by the rescind
	 * handler; set the error code to zero so we don't leak memory.
	 */
	if (channel->rescind)
		ret = 0;

514
	spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
515
	list_del(&info->msglistentry);
516
	spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
517

518
	kfree(info);
519
520
	return ret;
}
521
EXPORT_SYMBOL_GPL(vmbus_teardown_gpadl);
522

523
524
525
526
527
528
529
static void reset_channel_cb(void *arg)
{
	struct vmbus_channel *channel = arg;

	channel->onchannel_callback = NULL;
}

530
static int vmbus_close_internal(struct vmbus_channel *channel)
531
{
532
	struct vmbus_channel_close_channel *msg;
533
	int ret;
534

535
	/*
536
	 * vmbus_on_event(), running in the per-channel tasklet, can race
537
538
	 * with vmbus_close_internal() in the case of SMP guest, e.g., when
	 * the former is accessing channel->inbound.ring_buffer, the latter
539
540
	 * could be freeing the ring_buffer pages, so here we must stop it
	 * first.
541
	 */
542
	tasklet_disable(&channel->callback_event);
543

544
545
546
	/*
	 * In case a device driver's probe() fails (e.g.,
	 * util_probe() -> vmbus_open() returns -ENOMEM) and the device is
547
	 * rescinded later (e.g., we dynamically disable an Integrated Service
548
549
550
551
552
553
554
555
	 * in Hyper-V Manager), the driver's remove() invokes vmbus_close():
	 * here we should skip most of the below cleanup work.
	 */
	if (channel->state != CHANNEL_OPENED_STATE) {
		ret = -EINVAL;
		goto out;
	}

556
557
	channel->state = CHANNEL_OPEN_STATE;
	channel->sc_creation_callback = NULL;
558
	/* Stop callback and cancel the timer asap */
559
560
	if (channel->target_cpu != get_cpu()) {
		put_cpu();
561
562
		smp_call_function_single(channel->target_cpu, reset_channel_cb,
					 channel, true);
563
	} else {
564
		reset_channel_cb(channel);
565
566
		put_cpu();
	}
567

568
	/* Send a closing message */
569

570
	msg = &channel->close_msg.msg;
571

572
573
	msg->header.msgtype = CHANNELMSG_CLOSECHANNEL;
	msg->child_relid = channel->offermsg.child_relid;
574

575
576
	ret = vmbus_post_msg(msg, sizeof(struct vmbus_channel_close_channel),
			     true);
577

578
579
580
581
582
583
	if (ret) {
		pr_err("Close failed: close post msg return is %d\n", ret);
		/*
		 * If we failed to post the close msg,
		 * it is perhaps better to leak memory.
		 */
584
		goto out;
585
586
	}

587
	/* Tear down the gpadl for the channel's ring buffer */
588
589
590
591
592
593
594
595
596
	if (channel->ringbuffer_gpadlhandle) {
		ret = vmbus_teardown_gpadl(channel,
					   channel->ringbuffer_gpadlhandle);
		if (ret) {
			pr_err("Close failed: teardown gpadl return %d\n", ret);
			/*
			 * If we failed to teardown gpadl,
			 * it is perhaps better to leak memory.
			 */
597
			goto out;
598
599
		}
	}
600

601
	/* Cleanup the ring buffers for this channel */
602
603
	hv_ringbuffer_cleanup(&channel->outbound);
	hv_ringbuffer_cleanup(&channel->inbound);
604

605
606
	free_pages((unsigned long)channel->ringbuffer_pages,
		get_order(channel->ringbuffer_pagecount * PAGE_SIZE));
607

608
out:
609
	return ret;
610
}
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641

/*
 * vmbus_close - Close the specified channel
 */
void vmbus_close(struct vmbus_channel *channel)
{
	struct list_head *cur, *tmp;
	struct vmbus_channel *cur_channel;

	if (channel->primary_channel != NULL) {
		/*
		 * We will only close sub-channels when
		 * the primary is closed.
		 */
		return;
	}
	/*
	 * Close all the sub-channels first and then close the
	 * primary channel.
	 */
	list_for_each_safe(cur, tmp, &channel->sc_list) {
		cur_channel = list_entry(cur, struct vmbus_channel, sc_list);
		if (cur_channel->state != CHANNEL_OPENED_STATE)
			continue;
		vmbus_close_internal(cur_channel);
	}
	/*
	 * Now close the primary.
	 */
	vmbus_close_internal(channel);
}
642
EXPORT_SYMBOL_GPL(vmbus_close);
643

644
int vmbus_sendpacket_ctl(struct vmbus_channel *channel, void *buffer,
645
646
			 u32 bufferlen, u64 requestid,
			 enum vmbus_packet_type type, u32 flags)
647
{
648
	struct vmpacket_descriptor desc;
649
	u32 packetlen = sizeof(struct vmpacket_descriptor) + bufferlen;
650
	u32 packetlen_aligned = ALIGN(packetlen, sizeof(u64));
651
	struct kvec bufferlist[3];
652
	u64 aligned_data = 0;
653
	int num_vecs = ((bufferlen != 0) ? 3 : 1);
654
655


656
	/* Setup the descriptor */
657
658
	desc.type = type; /* VmbusPacketTypeDataInBand; */
	desc.flags = flags; /* VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED; */
659
	/* in 8-bytes granularity */
660
661
662
	desc.offset8 = sizeof(struct vmpacket_descriptor) >> 3;
	desc.len8 = (u16)(packetlen_aligned >> 3);
	desc.trans_id = requestid;
663

664
665
666
667
668
669
	bufferlist[0].iov_base = &desc;
	bufferlist[0].iov_len = sizeof(struct vmpacket_descriptor);
	bufferlist[1].iov_base = buffer;
	bufferlist[1].iov_len = bufferlen;
	bufferlist[2].iov_base = &aligned_data;
	bufferlist[2].iov_len = (packetlen_aligned - packetlen);
670

671
	return hv_ringbuffer_write(channel, bufferlist, num_vecs);
672
}
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
EXPORT_SYMBOL(vmbus_sendpacket_ctl);

/**
 * vmbus_sendpacket() - Send the specified buffer on the given channel
 * @channel: Pointer to vmbus_channel structure.
 * @buffer: Pointer to the buffer you want to receive the data into.
 * @bufferlen: Maximum size of what the the buffer will hold
 * @requestid: Identifier of the request
 * @type: Type of packet that is being send e.g. negotiate, time
 * packet etc.
 *
 * Sends data in @buffer directly to hyper-v via the vmbus
 * This will send the data unparsed to hyper-v.
 *
 * Mainly used by Hyper-V drivers.
 */
int vmbus_sendpacket(struct vmbus_channel *channel, void *buffer,
			   u32 bufferlen, u64 requestid,
			   enum vmbus_packet_type type, u32 flags)
{
	return vmbus_sendpacket_ctl(channel, buffer, bufferlen, requestid,
694
				    type, flags);
695
}
696
EXPORT_SYMBOL(vmbus_sendpacket);
697

698
/*
699
700
701
702
703
 * vmbus_sendpacket_pagebuffer_ctl - Send a range of single-page buffer
 * packets using a GPADL Direct packet type. This interface allows you
 * to control notifying the host. This will be useful for sending
 * batched data. Also the sender can control the send flags
 * explicitly.
704
 */
705
int vmbus_sendpacket_pagebuffer_ctl(struct vmbus_channel *channel,
706
707
708
				    struct hv_page_buffer pagebuffers[],
				    u32 pagecount, void *buffer, u32 bufferlen,
				    u64 requestid, u32 flags)
709
{
710
	int i;
711
	struct vmbus_channel_packet_page_buffer desc;
712
713
714
	u32 descsize;
	u32 packetlen;
	u32 packetlen_aligned;
715
	struct kvec bufferlist[3];
716
	u64 aligned_data = 0;
717

718
	if (pagecount > MAX_PAGE_BUFFER_COUNT)
719
		return -EINVAL;
720

721
	/*
722
	 * Adjust the size down since vmbus_channel_packet_page_buffer is the
723
724
	 * largest size we support
	 */
725
726
	descsize = sizeof(struct vmbus_channel_packet_page_buffer) -
			  ((MAX_PAGE_BUFFER_COUNT - pagecount) *
727
			  sizeof(struct hv_page_buffer));
728
	packetlen = descsize + bufferlen;
729
	packetlen_aligned = ALIGN(packetlen, sizeof(u64));
730

731
	/* Setup the descriptor */
732
	desc.type = VM_PKT_DATA_USING_GPA_DIRECT;
733
	desc.flags = flags;
734
735
736
737
738
739
	desc.dataoffset8 = descsize >> 3; /* in 8-bytes grandularity */
	desc.length8 = (u16)(packetlen_aligned >> 3);
	desc.transactionid = requestid;
	desc.rangecount = pagecount;

	for (i = 0; i < pagecount; i++) {
740
741
742
		desc.range[i].len = pagebuffers[i].len;
		desc.range[i].offset = pagebuffers[i].offset;
		desc.range[i].pfn	 = pagebuffers[i].pfn;
743
744
	}

745
746
747
748
749
750
	bufferlist[0].iov_base = &desc;
	bufferlist[0].iov_len = descsize;
	bufferlist[1].iov_base = buffer;
	bufferlist[1].iov_len = bufferlen;
	bufferlist[2].iov_base = &aligned_data;
	bufferlist[2].iov_len = (packetlen_aligned - packetlen);
751

752
	return hv_ringbuffer_write(channel, bufferlist, 3);
753
}
754
EXPORT_SYMBOL_GPL(vmbus_sendpacket_pagebuffer_ctl);
755
756
757
758
759
760
761
762
763
764
765

/*
 * vmbus_sendpacket_pagebuffer - Send a range of single-page buffer
 * packets using a GPADL Direct packet type.
 */
int vmbus_sendpacket_pagebuffer(struct vmbus_channel *channel,
				     struct hv_page_buffer pagebuffers[],
				     u32 pagecount, void *buffer, u32 bufferlen,
				     u64 requestid)
{
	u32 flags = VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED;
766

767
	return vmbus_sendpacket_pagebuffer_ctl(channel, pagebuffers, pagecount,
768
769
					       buffer, bufferlen,
					       requestid, flags);
770
771

}
772
EXPORT_SYMBOL_GPL(vmbus_sendpacket_pagebuffer);
773

774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
/*
 * vmbus_sendpacket_multipagebuffer - Send a multi-page buffer packet
 * using a GPADL Direct packet type.
 * The buffer includes the vmbus descriptor.
 */
int vmbus_sendpacket_mpb_desc(struct vmbus_channel *channel,
			      struct vmbus_packet_mpb_array *desc,
			      u32 desc_size,
			      void *buffer, u32 bufferlen, u64 requestid)
{
	u32 packetlen;
	u32 packetlen_aligned;
	struct kvec bufferlist[3];
	u64 aligned_data = 0;

	packetlen = desc_size + bufferlen;
	packetlen_aligned = ALIGN(packetlen, sizeof(u64));

	/* Setup the descriptor */
	desc->type = VM_PKT_DATA_USING_GPA_DIRECT;
	desc->flags = VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED;
	desc->dataoffset8 = desc_size >> 3; /* in 8-bytes grandularity */
	desc->length8 = (u16)(packetlen_aligned >> 3);
	desc->transactionid = requestid;
	desc->rangecount = 1;

	bufferlist[0].iov_base = desc;
	bufferlist[0].iov_len = desc_size;
	bufferlist[1].iov_base = buffer;
	bufferlist[1].iov_len = bufferlen;
	bufferlist[2].iov_base = &aligned_data;
	bufferlist[2].iov_len = (packetlen_aligned - packetlen);

807
	return hv_ringbuffer_write(channel, bufferlist, 3);
808
809
810
}
EXPORT_SYMBOL_GPL(vmbus_sendpacket_mpb_desc);

811
/*
812
 * vmbus_sendpacket_multipagebuffer - Send a multi-page buffer packet
813
 * using a GPADL Direct packet type.
814
 */
815
int vmbus_sendpacket_multipagebuffer(struct vmbus_channel *channel,
816
817
				struct hv_multipage_buffer *multi_pagebuffer,
				void *buffer, u32 bufferlen, u64 requestid)
818
{
819
	struct vmbus_channel_packet_multipage_buffer desc;
820
821
822
	u32 descsize;
	u32 packetlen;
	u32 packetlen_aligned;
823
	struct kvec bufferlist[3];
824
	u64 aligned_data = 0;
825
826
	u32 pfncount = NUM_PAGES_SPANNED(multi_pagebuffer->offset,
					 multi_pagebuffer->len);
827

828
	if (pfncount > MAX_MULTIPAGE_BUFFER_COUNT)
829
		return -EINVAL;
830