hc
2024-01-03 2f7c68cb55ecb7331f2381deb497c27155f32faf
kernel/drivers/hv/channel.c
....@@ -1,18 +1,6 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * 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.
164 *
175 * Authors:
186 * Haiyang Zhang <haiyangz@microsoft.com>
....@@ -30,23 +18,101 @@
3018 #include <linux/uio.h>
3119 #include <linux/interrupt.h>
3220 #include <asm/page.h>
21
+#include <asm/mshyperv.h>
3322
3423 #include "hyperv_vmbus.h"
3524
36
-#define NUM_PAGES_SPANNED(addr, len) \
37
-((PAGE_ALIGN(addr + len) >> PAGE_SHIFT) - (addr >> PAGE_SHIFT))
38
-
39
-static unsigned long virt_to_hvpfn(void *addr)
25
+/*
26
+ * hv_gpadl_size - Return the real size of a gpadl, the size that Hyper-V uses
27
+ *
28
+ * For BUFFER gpadl, Hyper-V uses the exact same size as the guest does.
29
+ *
30
+ * For RING gpadl, in each ring, the guest uses one PAGE_SIZE as the header
31
+ * (because of the alignment requirement), however, the hypervisor only
32
+ * uses the first HV_HYP_PAGE_SIZE as the header, therefore leaving a
33
+ * (PAGE_SIZE - HV_HYP_PAGE_SIZE) gap. And since there are two rings in a
34
+ * ringbuffer, the total size for a RING gpadl that Hyper-V uses is the
35
+ * total size that the guest uses minus twice of the gap size.
36
+ */
37
+static inline u32 hv_gpadl_size(enum hv_gpadl_type type, u32 size)
4038 {
41
- phys_addr_t paddr;
39
+ switch (type) {
40
+ case HV_GPADL_BUFFER:
41
+ return size;
42
+ case HV_GPADL_RING:
43
+ /* The size of a ringbuffer must be page-aligned */
44
+ BUG_ON(size % PAGE_SIZE);
45
+ /*
46
+ * Two things to notice here:
47
+ * 1) We're processing two ring buffers as a unit
48
+ * 2) We're skipping any space larger than HV_HYP_PAGE_SIZE in
49
+ * the first guest-size page of each of the two ring buffers.
50
+ * So we effectively subtract out two guest-size pages, and add
51
+ * back two Hyper-V size pages.
52
+ */
53
+ return size - 2 * (PAGE_SIZE - HV_HYP_PAGE_SIZE);
54
+ }
55
+ BUG();
56
+ return 0;
57
+}
4258
43
- if (is_vmalloc_addr(addr))
44
- paddr = page_to_phys(vmalloc_to_page(addr)) +
45
- offset_in_page(addr);
46
- else
47
- paddr = __pa(addr);
59
+/*
60
+ * hv_ring_gpadl_send_hvpgoffset - Calculate the send offset (in unit of
61
+ * HV_HYP_PAGE) in a ring gpadl based on the
62
+ * offset in the guest
63
+ *
64
+ * @offset: the offset (in bytes) where the send ringbuffer starts in the
65
+ * virtual address space of the guest
66
+ */
67
+static inline u32 hv_ring_gpadl_send_hvpgoffset(u32 offset)
68
+{
4869
49
- return paddr >> PAGE_SHIFT;
70
+ /*
71
+ * For RING gpadl, in each ring, the guest uses one PAGE_SIZE as the
72
+ * header (because of the alignment requirement), however, the
73
+ * hypervisor only uses the first HV_HYP_PAGE_SIZE as the header,
74
+ * therefore leaving a (PAGE_SIZE - HV_HYP_PAGE_SIZE) gap.
75
+ *
76
+ * And to calculate the effective send offset in gpadl, we need to
77
+ * substract this gap.
78
+ */
79
+ return (offset - (PAGE_SIZE - HV_HYP_PAGE_SIZE)) >> HV_HYP_PAGE_SHIFT;
80
+}
81
+
82
+/*
83
+ * hv_gpadl_hvpfn - Return the Hyper-V page PFN of the @i th Hyper-V page in
84
+ * the gpadl
85
+ *
86
+ * @type: the type of the gpadl
87
+ * @kbuffer: the pointer to the gpadl in the guest
88
+ * @size: the total size (in bytes) of the gpadl
89
+ * @send_offset: the offset (in bytes) where the send ringbuffer starts in the
90
+ * virtual address space of the guest
91
+ * @i: the index
92
+ */
93
+static inline u64 hv_gpadl_hvpfn(enum hv_gpadl_type type, void *kbuffer,
94
+ u32 size, u32 send_offset, int i)
95
+{
96
+ int send_idx = hv_ring_gpadl_send_hvpgoffset(send_offset);
97
+ unsigned long delta = 0UL;
98
+
99
+ switch (type) {
100
+ case HV_GPADL_BUFFER:
101
+ break;
102
+ case HV_GPADL_RING:
103
+ if (i == 0)
104
+ delta = 0;
105
+ else if (i <= send_idx)
106
+ delta = PAGE_SIZE - HV_HYP_PAGE_SIZE;
107
+ else
108
+ delta = 2 * (PAGE_SIZE - HV_HYP_PAGE_SIZE);
109
+ break;
110
+ default:
111
+ BUG();
112
+ break;
113
+ }
114
+
115
+ return virt_to_hvpfn(kbuffer + delta + (HV_HYP_PAGE_SIZE * i));
50116 }
51117
52118 /*
....@@ -79,175 +145,53 @@
79145 }
80146 EXPORT_SYMBOL_GPL(vmbus_setevent);
81147
82
-/*
83
- * vmbus_open - Open the specified channel.
84
- */
85
-int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size,
86
- u32 recv_ringbuffer_size, void *userdata, u32 userdatalen,
87
- void (*onchannelcallback)(void *context), void *context)
148
+/* vmbus_free_ring - drop mapping of ring buffer */
149
+void vmbus_free_ring(struct vmbus_channel *channel)
88150 {
89
- struct vmbus_channel_open_channel *open_msg;
90
- struct vmbus_channel_msginfo *open_info = NULL;
91
- unsigned long flags;
92
- int ret, err = 0;
93
- struct page *page;
94
- unsigned int order;
151
+ hv_ringbuffer_cleanup(&channel->outbound);
152
+ hv_ringbuffer_cleanup(&channel->inbound);
95153
96
- if (send_ringbuffer_size % PAGE_SIZE ||
97
- recv_ringbuffer_size % PAGE_SIZE)
98
- return -EINVAL;
99
-
100
- order = get_order(send_ringbuffer_size + recv_ringbuffer_size);
101
-
102
- spin_lock_irqsave(&newchannel->lock, flags);
103
- if (newchannel->state == CHANNEL_OPEN_STATE) {
104
- newchannel->state = CHANNEL_OPENING_STATE;
105
- } else {
106
- spin_unlock_irqrestore(&newchannel->lock, flags);
107
- return -EINVAL;
154
+ if (channel->ringbuffer_page) {
155
+ __free_pages(channel->ringbuffer_page,
156
+ get_order(channel->ringbuffer_pagecount
157
+ << PAGE_SHIFT));
158
+ channel->ringbuffer_page = NULL;
108159 }
109
- spin_unlock_irqrestore(&newchannel->lock, flags);
160
+}
161
+EXPORT_SYMBOL_GPL(vmbus_free_ring);
110162
111
- newchannel->onchannel_callback = onchannelcallback;
112
- newchannel->channel_callback_context = context;
163
+/* vmbus_alloc_ring - allocate and map pages for ring buffer */
164
+int vmbus_alloc_ring(struct vmbus_channel *newchannel,
165
+ u32 send_size, u32 recv_size)
166
+{
167
+ struct page *page;
168
+ int order;
169
+
170
+ if (send_size % PAGE_SIZE || recv_size % PAGE_SIZE)
171
+ return -EINVAL;
113172
114173 /* Allocate the ring buffer */
174
+ order = get_order(send_size + recv_size);
115175 page = alloc_pages_node(cpu_to_node(newchannel->target_cpu),
116176 GFP_KERNEL|__GFP_ZERO, order);
117177
118178 if (!page)
119179 page = alloc_pages(GFP_KERNEL|__GFP_ZERO, order);
120180
121
- if (!page) {
122
- err = -ENOMEM;
123
- goto error_set_chnstate;
124
- }
181
+ if (!page)
182
+ return -ENOMEM;
125183
126184 newchannel->ringbuffer_page = page;
127
- newchannel->ringbuffer_pagecount = (send_ringbuffer_size +
128
- recv_ringbuffer_size) >> PAGE_SHIFT;
185
+ newchannel->ringbuffer_pagecount = (send_size + recv_size) >> PAGE_SHIFT;
186
+ newchannel->ringbuffer_send_offset = send_size >> PAGE_SHIFT;
129187
130
- ret = hv_ringbuffer_init(&newchannel->outbound, page,
131
- send_ringbuffer_size >> PAGE_SHIFT);
132
-
133
- if (ret != 0) {
134
- err = ret;
135
- goto error_free_pages;
136
- }
137
-
138
- ret = hv_ringbuffer_init(&newchannel->inbound,
139
- &page[send_ringbuffer_size >> PAGE_SHIFT],
140
- recv_ringbuffer_size >> PAGE_SHIFT);
141
- if (ret != 0) {
142
- err = ret;
143
- goto error_free_pages;
144
- }
145
-
146
-
147
- /* Establish the gpadl for the ring buffer */
148
- newchannel->ringbuffer_gpadlhandle = 0;
149
-
150
- ret = vmbus_establish_gpadl(newchannel,
151
- page_address(page),
152
- send_ringbuffer_size +
153
- recv_ringbuffer_size,
154
- &newchannel->ringbuffer_gpadlhandle);
155
-
156
- if (ret != 0) {
157
- err = ret;
158
- goto error_free_pages;
159
- }
160
-
161
- /* Create and init the channel open message */
162
- open_info = kmalloc(sizeof(*open_info) +
163
- sizeof(struct vmbus_channel_open_channel),
164
- GFP_KERNEL);
165
- if (!open_info) {
166
- err = -ENOMEM;
167
- goto error_free_gpadl;
168
- }
169
-
170
- init_completion(&open_info->waitevent);
171
- open_info->waiting_channel = newchannel;
172
-
173
- open_msg = (struct vmbus_channel_open_channel *)open_info->msg;
174
- open_msg->header.msgtype = CHANNELMSG_OPENCHANNEL;
175
- open_msg->openid = newchannel->offermsg.child_relid;
176
- open_msg->child_relid = newchannel->offermsg.child_relid;
177
- open_msg->ringbuffer_gpadlhandle = newchannel->ringbuffer_gpadlhandle;
178
- open_msg->downstream_ringbuffer_pageoffset = send_ringbuffer_size >>
179
- PAGE_SHIFT;
180
- open_msg->target_vp = newchannel->target_vp;
181
-
182
- if (userdatalen > MAX_USER_DEFINED_BYTES) {
183
- err = -EINVAL;
184
- goto error_free_gpadl;
185
- }
186
-
187
- if (userdatalen)
188
- memcpy(open_msg->userdata, userdata, userdatalen);
189
-
190
- spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
191
- list_add_tail(&open_info->msglistentry,
192
- &vmbus_connection.chn_msg_list);
193
- spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
194
-
195
- if (newchannel->rescind) {
196
- err = -ENODEV;
197
- goto error_free_gpadl;
198
- }
199
-
200
- ret = vmbus_post_msg(open_msg,
201
- sizeof(struct vmbus_channel_open_channel), true);
202
-
203
- trace_vmbus_open(open_msg, ret);
204
-
205
- if (ret != 0) {
206
- err = ret;
207
- goto error_clean_msglist;
208
- }
209
-
210
- wait_for_completion(&open_info->waitevent);
211
-
212
- spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
213
- list_del(&open_info->msglistentry);
214
- spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
215
-
216
- if (newchannel->rescind) {
217
- err = -ENODEV;
218
- goto error_free_gpadl;
219
- }
220
-
221
- if (open_info->response.open_result.status) {
222
- err = -EAGAIN;
223
- goto error_free_gpadl;
224
- }
225
-
226
- newchannel->state = CHANNEL_OPENED_STATE;
227
- kfree(open_info);
228188 return 0;
229
-
230
-error_clean_msglist:
231
- spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
232
- list_del(&open_info->msglistentry);
233
- spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
234
-
235
-error_free_gpadl:
236
- vmbus_teardown_gpadl(newchannel, newchannel->ringbuffer_gpadlhandle);
237
- kfree(open_info);
238
-error_free_pages:
239
- hv_ringbuffer_cleanup(&newchannel->outbound);
240
- hv_ringbuffer_cleanup(&newchannel->inbound);
241
- __free_pages(page, order);
242
-error_set_chnstate:
243
- newchannel->state = CHANNEL_OPEN_STATE;
244
- return err;
245189 }
246
-EXPORT_SYMBOL_GPL(vmbus_open);
190
+EXPORT_SYMBOL_GPL(vmbus_alloc_ring);
247191
248192 /* Used for Hyper-V Socket: a guest client's connect() to the host */
249
-int vmbus_send_tl_connect_request(const uuid_le *shv_guest_servie_id,
250
- const uuid_le *shv_host_servie_id)
193
+int vmbus_send_tl_connect_request(const guid_t *shv_guest_servie_id,
194
+ const guid_t *shv_host_servie_id)
251195 {
252196 struct vmbus_channel_tl_connect_request conn_msg;
253197 int ret;
....@@ -266,9 +210,38 @@
266210 EXPORT_SYMBOL_GPL(vmbus_send_tl_connect_request);
267211
268212 /*
213
+ * Set/change the vCPU (@target_vp) the channel (@child_relid) will interrupt.
214
+ *
215
+ * CHANNELMSG_MODIFYCHANNEL messages are aynchronous. Also, Hyper-V does not
216
+ * ACK such messages. IOW we can't know when the host will stop interrupting
217
+ * the "old" vCPU and start interrupting the "new" vCPU for the given channel.
218
+ *
219
+ * The CHANNELMSG_MODIFYCHANNEL message type is supported since VMBus version
220
+ * VERSION_WIN10_V4_1.
221
+ */
222
+int vmbus_send_modifychannel(u32 child_relid, u32 target_vp)
223
+{
224
+ struct vmbus_channel_modifychannel conn_msg;
225
+ int ret;
226
+
227
+ memset(&conn_msg, 0, sizeof(conn_msg));
228
+ conn_msg.header.msgtype = CHANNELMSG_MODIFYCHANNEL;
229
+ conn_msg.child_relid = child_relid;
230
+ conn_msg.target_vp = target_vp;
231
+
232
+ ret = vmbus_post_msg(&conn_msg, sizeof(conn_msg), true);
233
+
234
+ trace_vmbus_send_modifychannel(&conn_msg, ret);
235
+
236
+ return ret;
237
+}
238
+EXPORT_SYMBOL_GPL(vmbus_send_modifychannel);
239
+
240
+/*
269241 * create_gpadl_header - Creates a gpadl for the specified buffer
270242 */
271
-static int create_gpadl_header(void *kbuffer, u32 size,
243
+static int create_gpadl_header(enum hv_gpadl_type type, void *kbuffer,
244
+ u32 size, u32 send_offset,
272245 struct vmbus_channel_msginfo **msginfo)
273246 {
274247 int i;
....@@ -281,7 +254,7 @@
281254
282255 int pfnsum, pfncount, pfnleft, pfncurr, pfnsize;
283256
284
- pagecount = size >> PAGE_SHIFT;
257
+ pagecount = hv_gpadl_size(type, size) >> HV_HYP_PAGE_SHIFT;
285258
286259 /* do we need a gpadl body msg */
287260 pfnsize = MAX_SIZE_CHANNEL_MESSAGE -
....@@ -308,10 +281,10 @@
308281 gpadl_header->range_buflen = sizeof(struct gpa_range) +
309282 pagecount * sizeof(u64);
310283 gpadl_header->range[0].byte_offset = 0;
311
- gpadl_header->range[0].byte_count = size;
284
+ gpadl_header->range[0].byte_count = hv_gpadl_size(type, size);
312285 for (i = 0; i < pfncount; i++)
313
- gpadl_header->range[0].pfn_array[i] = virt_to_hvpfn(
314
- kbuffer + PAGE_SIZE * i);
286
+ gpadl_header->range[0].pfn_array[i] = hv_gpadl_hvpfn(
287
+ type, kbuffer, size, send_offset, i);
315288 *msginfo = msgheader;
316289
317290 pfnsum = pfncount;
....@@ -362,8 +335,8 @@
362335 * so the hypervisor guarantees that this is ok.
363336 */
364337 for (i = 0; i < pfncurr; i++)
365
- gpadl_body->pfn[i] = virt_to_hvpfn(
366
- kbuffer + PAGE_SIZE * (pfnsum + i));
338
+ gpadl_body->pfn[i] = hv_gpadl_hvpfn(type,
339
+ kbuffer, size, send_offset, pfnsum + i);
367340
368341 /* add to msg header */
369342 list_add_tail(&msgbody->msglistentry,
....@@ -389,10 +362,10 @@
389362 gpadl_header->range_buflen = sizeof(struct gpa_range) +
390363 pagecount * sizeof(u64);
391364 gpadl_header->range[0].byte_offset = 0;
392
- gpadl_header->range[0].byte_count = size;
365
+ gpadl_header->range[0].byte_count = hv_gpadl_size(type, size);
393366 for (i = 0; i < pagecount; i++)
394
- gpadl_header->range[0].pfn_array[i] = virt_to_hvpfn(
395
- kbuffer + PAGE_SIZE * i);
367
+ gpadl_header->range[0].pfn_array[i] = hv_gpadl_hvpfn(
368
+ type, kbuffer, size, send_offset, i);
396369
397370 *msginfo = msgheader;
398371 }
....@@ -405,15 +378,20 @@
405378 }
406379
407380 /*
408
- * vmbus_establish_gpadl - Establish a GPADL for the specified buffer
381
+ * __vmbus_establish_gpadl - Establish a GPADL for a buffer or ringbuffer
409382 *
410383 * @channel: a channel
384
+ * @type: the type of the corresponding GPADL, only meaningful for the guest.
411385 * @kbuffer: from kmalloc or vmalloc
412386 * @size: page-size multiple
387
+ * @send_offset: the offset (in bytes) where the send ring buffer starts,
388
+ * should be 0 for BUFFER type gpadl
413389 * @gpadl_handle: some funky thing
414390 */
415
-int vmbus_establish_gpadl(struct vmbus_channel *channel, void *kbuffer,
416
- u32 size, u32 *gpadl_handle)
391
+static int __vmbus_establish_gpadl(struct vmbus_channel *channel,
392
+ enum hv_gpadl_type type, void *kbuffer,
393
+ u32 size, u32 send_offset,
394
+ u32 *gpadl_handle)
417395 {
418396 struct vmbus_channel_gpadl_header *gpadlmsg;
419397 struct vmbus_channel_gpadl_body *gpadl_body;
....@@ -427,7 +405,7 @@
427405 next_gpadl_handle =
428406 (atomic_inc_return(&vmbus_connection.next_gpadl_handle) - 1);
429407
430
- ret = create_gpadl_header(kbuffer, size, &msginfo);
408
+ ret = create_gpadl_header(type, kbuffer, size, send_offset, &msginfo);
431409 if (ret)
432410 return ret;
433411
....@@ -508,7 +486,183 @@
508486 kfree(msginfo);
509487 return ret;
510488 }
489
+
490
+/*
491
+ * vmbus_establish_gpadl - Establish a GPADL for the specified buffer
492
+ *
493
+ * @channel: a channel
494
+ * @kbuffer: from kmalloc or vmalloc
495
+ * @size: page-size multiple
496
+ * @gpadl_handle: some funky thing
497
+ */
498
+int vmbus_establish_gpadl(struct vmbus_channel *channel, void *kbuffer,
499
+ u32 size, u32 *gpadl_handle)
500
+{
501
+ return __vmbus_establish_gpadl(channel, HV_GPADL_BUFFER, kbuffer, size,
502
+ 0U, gpadl_handle);
503
+}
511504 EXPORT_SYMBOL_GPL(vmbus_establish_gpadl);
505
+
506
+static int __vmbus_open(struct vmbus_channel *newchannel,
507
+ void *userdata, u32 userdatalen,
508
+ void (*onchannelcallback)(void *context), void *context)
509
+{
510
+ struct vmbus_channel_open_channel *open_msg;
511
+ struct vmbus_channel_msginfo *open_info = NULL;
512
+ struct page *page = newchannel->ringbuffer_page;
513
+ u32 send_pages, recv_pages;
514
+ unsigned long flags;
515
+ int err;
516
+
517
+ if (userdatalen > MAX_USER_DEFINED_BYTES)
518
+ return -EINVAL;
519
+
520
+ send_pages = newchannel->ringbuffer_send_offset;
521
+ recv_pages = newchannel->ringbuffer_pagecount - send_pages;
522
+
523
+ if (newchannel->state != CHANNEL_OPEN_STATE)
524
+ return -EINVAL;
525
+
526
+ newchannel->state = CHANNEL_OPENING_STATE;
527
+ newchannel->onchannel_callback = onchannelcallback;
528
+ newchannel->channel_callback_context = context;
529
+
530
+ err = hv_ringbuffer_init(&newchannel->outbound, page, send_pages);
531
+ if (err)
532
+ goto error_clean_ring;
533
+
534
+ err = hv_ringbuffer_init(&newchannel->inbound,
535
+ &page[send_pages], recv_pages);
536
+ if (err)
537
+ goto error_clean_ring;
538
+
539
+ /* Establish the gpadl for the ring buffer */
540
+ newchannel->ringbuffer_gpadlhandle = 0;
541
+
542
+ err = __vmbus_establish_gpadl(newchannel, HV_GPADL_RING,
543
+ page_address(newchannel->ringbuffer_page),
544
+ (send_pages + recv_pages) << PAGE_SHIFT,
545
+ newchannel->ringbuffer_send_offset << PAGE_SHIFT,
546
+ &newchannel->ringbuffer_gpadlhandle);
547
+ if (err)
548
+ goto error_clean_ring;
549
+
550
+ /* Create and init the channel open message */
551
+ open_info = kmalloc(sizeof(*open_info) +
552
+ sizeof(struct vmbus_channel_open_channel),
553
+ GFP_KERNEL);
554
+ if (!open_info) {
555
+ err = -ENOMEM;
556
+ goto error_free_gpadl;
557
+ }
558
+
559
+ init_completion(&open_info->waitevent);
560
+ open_info->waiting_channel = newchannel;
561
+
562
+ open_msg = (struct vmbus_channel_open_channel *)open_info->msg;
563
+ open_msg->header.msgtype = CHANNELMSG_OPENCHANNEL;
564
+ open_msg->openid = newchannel->offermsg.child_relid;
565
+ open_msg->child_relid = newchannel->offermsg.child_relid;
566
+ open_msg->ringbuffer_gpadlhandle = newchannel->ringbuffer_gpadlhandle;
567
+ /*
568
+ * The unit of ->downstream_ringbuffer_pageoffset is HV_HYP_PAGE and
569
+ * the unit of ->ringbuffer_send_offset (i.e. send_pages) is PAGE, so
570
+ * here we calculate it into HV_HYP_PAGE.
571
+ */
572
+ open_msg->downstream_ringbuffer_pageoffset =
573
+ hv_ring_gpadl_send_hvpgoffset(send_pages << PAGE_SHIFT);
574
+ open_msg->target_vp = hv_cpu_number_to_vp_number(newchannel->target_cpu);
575
+
576
+ if (userdatalen)
577
+ memcpy(open_msg->userdata, userdata, userdatalen);
578
+
579
+ spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
580
+ list_add_tail(&open_info->msglistentry,
581
+ &vmbus_connection.chn_msg_list);
582
+ spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
583
+
584
+ if (newchannel->rescind) {
585
+ err = -ENODEV;
586
+ goto error_clean_msglist;
587
+ }
588
+
589
+ err = vmbus_post_msg(open_msg,
590
+ sizeof(struct vmbus_channel_open_channel), true);
591
+
592
+ trace_vmbus_open(open_msg, err);
593
+
594
+ if (err != 0)
595
+ goto error_clean_msglist;
596
+
597
+ wait_for_completion(&open_info->waitevent);
598
+
599
+ spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
600
+ list_del(&open_info->msglistentry);
601
+ spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
602
+
603
+ if (newchannel->rescind) {
604
+ err = -ENODEV;
605
+ goto error_free_info;
606
+ }
607
+
608
+ if (open_info->response.open_result.status) {
609
+ err = -EAGAIN;
610
+ goto error_free_info;
611
+ }
612
+
613
+ newchannel->state = CHANNEL_OPENED_STATE;
614
+ kfree(open_info);
615
+ return 0;
616
+
617
+error_clean_msglist:
618
+ spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
619
+ list_del(&open_info->msglistentry);
620
+ spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
621
+error_free_info:
622
+ kfree(open_info);
623
+error_free_gpadl:
624
+ vmbus_teardown_gpadl(newchannel, newchannel->ringbuffer_gpadlhandle);
625
+ newchannel->ringbuffer_gpadlhandle = 0;
626
+error_clean_ring:
627
+ hv_ringbuffer_cleanup(&newchannel->outbound);
628
+ hv_ringbuffer_cleanup(&newchannel->inbound);
629
+ newchannel->state = CHANNEL_OPEN_STATE;
630
+ return err;
631
+}
632
+
633
+/*
634
+ * vmbus_connect_ring - Open the channel but reuse ring buffer
635
+ */
636
+int vmbus_connect_ring(struct vmbus_channel *newchannel,
637
+ void (*onchannelcallback)(void *context), void *context)
638
+{
639
+ return __vmbus_open(newchannel, NULL, 0, onchannelcallback, context);
640
+}
641
+EXPORT_SYMBOL_GPL(vmbus_connect_ring);
642
+
643
+/*
644
+ * vmbus_open - Open the specified channel.
645
+ */
646
+int vmbus_open(struct vmbus_channel *newchannel,
647
+ u32 send_ringbuffer_size, u32 recv_ringbuffer_size,
648
+ void *userdata, u32 userdatalen,
649
+ void (*onchannelcallback)(void *context), void *context)
650
+{
651
+ int err;
652
+
653
+ err = vmbus_alloc_ring(newchannel, send_ringbuffer_size,
654
+ recv_ringbuffer_size);
655
+ if (err)
656
+ return err;
657
+
658
+ err = __vmbus_open(newchannel, userdata, userdatalen,
659
+ onchannelcallback, context);
660
+ if (err)
661
+ vmbus_free_ring(newchannel);
662
+
663
+ return err;
664
+}
665
+EXPORT_SYMBOL_GPL(vmbus_open);
512666
513667 /*
514668 * vmbus_teardown_gpadl -Teardown the specified GPADL handle
....@@ -570,35 +724,31 @@
570724 }
571725 EXPORT_SYMBOL_GPL(vmbus_teardown_gpadl);
572726
573
-static void reset_channel_cb(void *arg)
574
-{
575
- struct vmbus_channel *channel = arg;
576
-
577
- channel->onchannel_callback = NULL;
578
-}
579
-
580727 void vmbus_reset_channel_cb(struct vmbus_channel *channel)
581728 {
729
+ unsigned long flags;
730
+
582731 /*
583732 * vmbus_on_event(), running in the per-channel tasklet, can race
584733 * with vmbus_close_internal() in the case of SMP guest, e.g., when
585734 * the former is accessing channel->inbound.ring_buffer, the latter
586735 * could be freeing the ring_buffer pages, so here we must stop it
587736 * first.
737
+ *
738
+ * vmbus_chan_sched() might call the netvsc driver callback function
739
+ * that ends up scheduling NAPI work that accesses the ring buffer.
740
+ * At this point, we have to ensure that any such work is completed
741
+ * and that the channel ring buffer is no longer being accessed, cf.
742
+ * the calls to napi_disable() in netvsc_device_remove().
588743 */
589744 tasklet_disable(&channel->callback_event);
590745
591
- channel->sc_creation_callback = NULL;
746
+ /* See the inline comments in vmbus_chan_sched(). */
747
+ spin_lock_irqsave(&channel->sched_lock, flags);
748
+ channel->onchannel_callback = NULL;
749
+ spin_unlock_irqrestore(&channel->sched_lock, flags);
592750
593
- /* Stop the callback asap */
594
- if (channel->target_cpu != get_cpu()) {
595
- put_cpu();
596
- smp_call_function_single(channel->target_cpu, reset_channel_cb,
597
- channel, true);
598
- } else {
599
- reset_channel_cb(channel);
600
- put_cpu();
601
- }
751
+ channel->sc_creation_callback = NULL;
602752
603753 /* Re-enable tasklet for use on re-open */
604754 tasklet_enable(&channel->callback_event);
....@@ -618,10 +768,8 @@
618768 * in Hyper-V Manager), the driver's remove() invokes vmbus_close():
619769 * here we should skip most of the below cleanup work.
620770 */
621
- if (channel->state != CHANNEL_OPENED_STATE) {
622
- ret = -EINVAL;
623
- goto out;
624
- }
771
+ if (channel->state != CHANNEL_OPENED_STATE)
772
+ return -EINVAL;
625773
626774 channel->state = CHANNEL_OPEN_STATE;
627775
....@@ -643,11 +791,10 @@
643791 * If we failed to post the close msg,
644792 * it is perhaps better to leak memory.
645793 */
646
- goto out;
647794 }
648795
649796 /* Tear down the gpadl for the channel's ring buffer */
650
- if (channel->ringbuffer_gpadlhandle) {
797
+ else if (channel->ringbuffer_gpadlhandle) {
651798 ret = vmbus_teardown_gpadl(channel,
652799 channel->ringbuffer_gpadlhandle);
653800 if (ret) {
....@@ -656,74 +803,70 @@
656803 * If we failed to teardown gpadl,
657804 * it is perhaps better to leak memory.
658805 */
659
- goto out;
660806 }
807
+
808
+ channel->ringbuffer_gpadlhandle = 0;
661809 }
662810
663
- /* Cleanup the ring buffers for this channel */
664
- hv_ringbuffer_cleanup(&channel->outbound);
665
- hv_ringbuffer_cleanup(&channel->inbound);
666
-
667
- __free_pages(channel->ringbuffer_page,
668
- get_order(channel->ringbuffer_pagecount << PAGE_SHIFT));
669
-
670
-out:
671811 return ret;
672812 }
813
+
814
+/* disconnect ring - close all channels */
815
+int vmbus_disconnect_ring(struct vmbus_channel *channel)
816
+{
817
+ struct vmbus_channel *cur_channel, *tmp;
818
+ int ret;
819
+
820
+ if (channel->primary_channel != NULL)
821
+ return -EINVAL;
822
+
823
+ list_for_each_entry_safe(cur_channel, tmp, &channel->sc_list, sc_list) {
824
+ if (cur_channel->rescind)
825
+ wait_for_completion(&cur_channel->rescind_event);
826
+
827
+ mutex_lock(&vmbus_connection.channel_mutex);
828
+ if (vmbus_close_internal(cur_channel) == 0) {
829
+ vmbus_free_ring(cur_channel);
830
+
831
+ if (cur_channel->rescind)
832
+ hv_process_channel_removal(cur_channel);
833
+ }
834
+ mutex_unlock(&vmbus_connection.channel_mutex);
835
+ }
836
+
837
+ /*
838
+ * Now close the primary.
839
+ */
840
+ mutex_lock(&vmbus_connection.channel_mutex);
841
+ ret = vmbus_close_internal(channel);
842
+ mutex_unlock(&vmbus_connection.channel_mutex);
843
+
844
+ return ret;
845
+}
846
+EXPORT_SYMBOL_GPL(vmbus_disconnect_ring);
673847
674848 /*
675849 * vmbus_close - Close the specified channel
676850 */
677851 void vmbus_close(struct vmbus_channel *channel)
678852 {
679
- struct list_head *cur, *tmp;
680
- struct vmbus_channel *cur_channel;
681
-
682
- if (channel->primary_channel != NULL) {
683
- /*
684
- * We will only close sub-channels when
685
- * the primary is closed.
686
- */
687
- return;
688
- }
689
- /*
690
- * Close all the sub-channels first and then close the
691
- * primary channel.
692
- */
693
- list_for_each_safe(cur, tmp, &channel->sc_list) {
694
- cur_channel = list_entry(cur, struct vmbus_channel, sc_list);
695
- if (cur_channel->rescind) {
696
- wait_for_completion(&cur_channel->rescind_event);
697
- mutex_lock(&vmbus_connection.channel_mutex);
698
- vmbus_close_internal(cur_channel);
699
- hv_process_channel_removal(
700
- cur_channel->offermsg.child_relid);
701
- } else {
702
- mutex_lock(&vmbus_connection.channel_mutex);
703
- vmbus_close_internal(cur_channel);
704
- }
705
- mutex_unlock(&vmbus_connection.channel_mutex);
706
- }
707
- /*
708
- * Now close the primary.
709
- */
710
- mutex_lock(&vmbus_connection.channel_mutex);
711
- vmbus_close_internal(channel);
712
- mutex_unlock(&vmbus_connection.channel_mutex);
853
+ if (vmbus_disconnect_ring(channel) == 0)
854
+ vmbus_free_ring(channel);
713855 }
714856 EXPORT_SYMBOL_GPL(vmbus_close);
715857
716858 /**
717859 * vmbus_sendpacket() - Send the specified buffer on the given channel
718
- * @channel: Pointer to vmbus_channel structure.
719
- * @buffer: Pointer to the buffer you want to receive the data into.
720
- * @bufferlen: Maximum size of what the the buffer will hold
860
+ * @channel: Pointer to vmbus_channel structure
861
+ * @buffer: Pointer to the buffer you want to send the data from.
862
+ * @bufferlen: Maximum size of what the buffer holds.
721863 * @requestid: Identifier of the request
722
- * @type: Type of packet that is being send e.g. negotiate, time
723
- * packet etc.
864
+ * @type: Type of packet that is being sent e.g. negotiate, time
865
+ * packet etc.
866
+ * @flags: 0 or VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED
724867 *
725
- * Sends data in @buffer directly to hyper-v via the vmbus
726
- * This will send the data unparsed to hyper-v.
868
+ * Sends data in @buffer directly to Hyper-V via the vmbus.
869
+ * This will send the data unparsed to Hyper-V.
727870 *
728871 * Mainly used by Hyper-V drivers.
729872 */
....@@ -856,12 +999,13 @@
856999 EXPORT_SYMBOL_GPL(vmbus_sendpacket_mpb_desc);
8571000
8581001 /**
859
- * vmbus_recvpacket() - Retrieve the user packet on the specified channel
860
- * @channel: Pointer to vmbus_channel structure.
1002
+ * __vmbus_recvpacket() - Retrieve the user packet on the specified channel
1003
+ * @channel: Pointer to vmbus_channel structure
8611004 * @buffer: Pointer to the buffer you want to receive the data into.
862
- * @bufferlen: Maximum size of what the the buffer will hold
863
- * @buffer_actual_len: The actual size of the data after it was received
1005
+ * @bufferlen: Maximum size of what the buffer can hold.
1006
+ * @buffer_actual_len: The actual size of the data after it was received.
8641007 * @requestid: Identifier of the request
1008
+ * @raw: true means keep the vmpacket_descriptor header in the received data.
8651009 *
8661010 * Receives directly from the hyper-v vmbus and puts the data it received
8671011 * into Buffer. This will receive the data unparsed from hyper-v.