2 * Copyright (c) 2009, Microsoft Corporation.
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.
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
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.
18 * Haiyang Zhang <haiyangz@microsoft.com>
19 * Hank Janssen <hjanssen@microsoft.com>
21 #include <linux/kernel.h>
23 #include <linux/slab.h>
24 #include <linux/module.h>
27 #include "vmbus_private.h"
29 /* Internal routines */
30 static int create_gpadl_header(
31 void *kbuffer
, /* must be phys and virt contiguous */
32 u32 size
, /* page-size multiple */
33 struct vmbus_channel_msginfo
**msginfo
,
35 static void dump_vmbus_channel(struct vmbus_channel
*channel
);
36 static void vmbus_setevent(struct vmbus_channel
*channel
);
40 static void DumpMonitorPage(struct hv_monitor_page
*MonitorPage
)
45 DPRINT_DBG(VMBUS
, "monitorPage - %p, trigger state - %d",
46 MonitorPage
, MonitorPage
->trigger_state
);
48 for (i
= 0; i
< 4; i
++)
49 DPRINT_DBG(VMBUS
, "trigger group (%d) - %llx", i
,
50 MonitorPage
->trigger_group
[i
].as_uint64
);
52 for (i
= 0; i
< 4; i
++) {
53 for (j
= 0; j
< 32; j
++) {
54 DPRINT_DBG(VMBUS
, "latency (%d)(%d) - %llx", i
, j
,
55 MonitorPage
->latency
[i
][j
]);
58 for (i
= 0; i
< 4; i
++) {
59 for (j
= 0; j
< 32; j
++) {
60 DPRINT_DBG(VMBUS
, "param-conn id (%d)(%d) - %d", i
, j
,
61 MonitorPage
->parameter
[i
][j
].connectionid
.asu32
);
62 DPRINT_DBG(VMBUS
, "param-flag (%d)(%d) - %d", i
, j
,
63 MonitorPage
->parameter
[i
][j
].flag_number
);
70 * vmbus_setevent- Trigger an event notification on the specified
73 static void vmbus_setevent(struct vmbus_channel
*channel
)
75 struct hv_monitor_page
*monitorpage
;
77 if (channel
->offermsg
.monitor_allocated
) {
78 /* Each u32 represents 32 channels */
79 set_bit(channel
->offermsg
.child_relid
& 31,
80 (unsigned long *) gVmbusConnection
.SendInterruptPage
+
81 (channel
->offermsg
.child_relid
>> 5));
83 monitorpage
= gVmbusConnection
.MonitorPages
;
84 monitorpage
++; /* Get the child to parent monitor page */
86 set_bit(channel
->monitor_bit
,
87 (unsigned long *)&monitorpage
->trigger_group
88 [channel
->monitor_grp
].pending
);
91 VmbusSetEvent(channel
->offermsg
.child_relid
);
96 static void VmbusChannelClearEvent(struct vmbus_channel
*channel
)
98 struct hv_monitor_page
*monitorPage
;
100 if (Channel
->offermsg
.monitor_allocated
) {
101 /* Each u32 represents 32 channels */
102 clear_bit(Channel
->offermsg
.child_relid
& 31,
103 (unsigned long *)gVmbusConnection
.SendInterruptPage
+
104 (Channel
->offermsg
.child_relid
>> 5));
107 (struct hv_monitor_page
*)gVmbusConnection
.MonitorPages
;
108 monitorPage
++; /* Get the child to parent monitor page */
110 clear_bit(Channel
->monitor_bit
,
111 (unsigned long *)&monitorPage
->trigger_group
112 [Channel
->monitor_grp
].Pending
);
118 * vmbus_get_debug_info -Retrieve various channel debug info
120 void vmbus_get_debug_info(struct vmbus_channel
*channel
,
121 struct vmbus_channel_debug_info
*debuginfo
)
123 struct hv_monitor_page
*monitorpage
;
124 u8 monitor_group
= (u8
)channel
->offermsg
.monitorid
/ 32;
125 u8 monitor_offset
= (u8
)channel
->offermsg
.monitorid
% 32;
126 /* u32 monitorBit = 1 << monitorOffset; */
128 debuginfo
->relid
= channel
->offermsg
.child_relid
;
129 debuginfo
->state
= channel
->state
;
130 memcpy(&debuginfo
->interfacetype
,
131 &channel
->offermsg
.offer
.InterfaceType
, sizeof(struct hv_guid
));
132 memcpy(&debuginfo
->interface_instance
,
133 &channel
->offermsg
.offer
.InterfaceInstance
,
134 sizeof(struct hv_guid
));
136 monitorpage
= (struct hv_monitor_page
*)gVmbusConnection
.MonitorPages
;
138 debuginfo
->monitorid
= channel
->offermsg
.monitorid
;
140 debuginfo
->servermonitor_pending
=
141 monitorpage
->trigger_group
[monitor_group
].pending
;
142 debuginfo
->servermonitor_latency
=
143 monitorpage
->latency
[monitor_group
][monitor_offset
];
144 debuginfo
->servermonitor_connectionid
=
145 monitorpage
->parameter
[monitor_group
]
146 [monitor_offset
].connectionid
.u
.id
;
150 debuginfo
->clientmonitor_pending
=
151 monitorpage
->trigger_group
[monitor_group
].pending
;
152 debuginfo
->clientmonitor_latency
=
153 monitorpage
->latency
[monitor_group
][monitor_offset
];
154 debuginfo
->clientmonitor_connectionid
=
155 monitorpage
->parameter
[monitor_group
]
156 [monitor_offset
].connectionid
.u
.id
;
158 ringbuffer_get_debuginfo(&channel
->inbound
, &debuginfo
->inbound
);
159 ringbuffer_get_debuginfo(&channel
->outbound
, &debuginfo
->outbound
);
163 * vmbus_open - Open the specified channel.
165 int vmbus_open(struct vmbus_channel
*newchannel
, u32 send_ringbuffer_size
,
166 u32 recv_ringbuffer_size
, void *userdata
, u32 userdatalen
,
167 void (*onchannelcallback
)(void *context
), void *context
)
169 struct vmbus_channel_open_channel
*openMsg
;
170 struct vmbus_channel_msginfo
*openInfo
= NULL
;
175 /* Aligned to page size */
176 /* ASSERT(!(SendRingBufferSize & (PAGE_SIZE - 1))); */
177 /* ASSERT(!(RecvRingBufferSize & (PAGE_SIZE - 1))); */
179 newchannel
->onchannel_callback
= onchannelcallback
;
180 newchannel
->channel_callback_context
= context
;
182 /* Allocate the ring buffer */
183 out
= osd_page_alloc((send_ringbuffer_size
+ recv_ringbuffer_size
)
188 /* ASSERT(((unsigned long)out & (PAGE_SIZE-1)) == 0); */
190 in
= (void *)((unsigned long)out
+ send_ringbuffer_size
);
192 newchannel
->ringbuffer_pages
= out
;
193 newchannel
->ringbuffer_pagecount
= (send_ringbuffer_size
+
194 recv_ringbuffer_size
) >> PAGE_SHIFT
;
196 ret
= ringbuffer_init(&newchannel
->outbound
, out
, send_ringbuffer_size
);
202 ret
= ringbuffer_init(&newchannel
->inbound
, in
, recv_ringbuffer_size
);
209 /* Establish the gpadl for the ring buffer */
210 DPRINT_DBG(VMBUS
, "Establishing ring buffer's gpadl for channel %p...",
213 newchannel
->ringbuffer_gpadlhandle
= 0;
215 ret
= vmbus_establish_gpadl(newchannel
,
216 newchannel
->outbound
.ring_buffer
,
217 send_ringbuffer_size
+
218 recv_ringbuffer_size
,
219 &newchannel
->ringbuffer_gpadlhandle
);
226 DPRINT_DBG(VMBUS
, "channel %p <relid %d gpadl 0x%x send ring %p "
227 "size %d recv ring %p size %d, downstreamoffset %d>",
228 newchannel
, newchannel
->offermsg
.child_relid
,
229 newchannel
->ringbuffer_gpadlhandle
,
230 newchannel
->outbound
.ring_buffer
,
231 newchannel
->outbound
.ring_size
,
232 newchannel
->inbound
.ring_buffer
,
233 newchannel
->inbound
.ring_size
,
234 send_ringbuffer_size
);
236 /* Create and init the channel open message */
237 openInfo
= kmalloc(sizeof(*openInfo
) +
238 sizeof(struct vmbus_channel_open_channel
),
245 openInfo
->waitevent
= osd_waitevent_create();
246 if (!openInfo
->waitevent
) {
251 openMsg
= (struct vmbus_channel_open_channel
*)openInfo
->msg
;
252 openMsg
->header
.msgtype
= CHANNELMSG_OPENCHANNEL
;
253 openMsg
->openid
= newchannel
->offermsg
.child_relid
; /* FIXME */
254 openMsg
->child_relid
= newchannel
->offermsg
.child_relid
;
255 openMsg
->ringbuffer_gpadlhandle
= newchannel
->ringbuffer_gpadlhandle
;
256 openMsg
->downstream_ringbuffer_pageoffset
= send_ringbuffer_size
>>
258 openMsg
->server_contextarea_gpadlhandle
= 0; /* TODO */
260 if (userdatalen
> MAX_USER_DEFINED_BYTES
) {
266 memcpy(openMsg
->userdata
, userdata
, userdatalen
);
268 spin_lock_irqsave(&gVmbusConnection
.channelmsg_lock
, flags
);
269 list_add_tail(&openInfo
->msglistentry
,
270 &gVmbusConnection
.ChannelMsgList
);
271 spin_unlock_irqrestore(&gVmbusConnection
.channelmsg_lock
, flags
);
273 DPRINT_DBG(VMBUS
, "Sending channel open msg...");
275 ret
= VmbusPostMessage(openMsg
,
276 sizeof(struct vmbus_channel_open_channel
));
278 DPRINT_ERR(VMBUS
, "unable to open channel - %d", ret
);
282 /* FIXME: Need to time-out here */
283 osd_waitevent_wait(openInfo
->waitevent
);
285 if (openInfo
->response
.open_result
.status
== 0)
286 DPRINT_INFO(VMBUS
, "channel <%p> open success!!", newchannel
);
288 DPRINT_INFO(VMBUS
, "channel <%p> open failed - %d!!",
289 newchannel
, openInfo
->response
.open_result
.status
);
292 spin_lock_irqsave(&gVmbusConnection
.channelmsg_lock
, flags
);
293 list_del(&openInfo
->msglistentry
);
294 spin_unlock_irqrestore(&gVmbusConnection
.channelmsg_lock
, flags
);
296 kfree(openInfo
->waitevent
);
301 ringbuffer_cleanup(&newchannel
->outbound
);
302 ringbuffer_cleanup(&newchannel
->inbound
);
303 osd_page_free(out
, (send_ringbuffer_size
+ recv_ringbuffer_size
)
308 EXPORT_SYMBOL_GPL(vmbus_open
);
311 * dump_gpadl_body - Dump the gpadl body message to the console for
312 * debugging purposes.
314 static void dump_gpadl_body(struct vmbus_channel_gpadl_body
*gpadl
, u32 len
)
319 pfncount
= (len
- sizeof(struct vmbus_channel_gpadl_body
)) /
321 DPRINT_DBG(VMBUS
, "gpadl body - len %d pfn count %d", len
, pfncount
);
323 for (i
= 0; i
< pfncount
; i
++)
324 DPRINT_DBG(VMBUS
, "gpadl body - %d) pfn %llu",
329 * dump_gpadl_header - Dump the gpadl header message to the console for
330 * debugging purposes.
332 static void dump_gpadl_header(struct vmbus_channel_gpadl_header
*gpadl
)
338 "gpadl header - relid %d, range count %d, range buflen %d",
339 gpadl
->child_relid
, gpadl
->rangecount
, gpadl
->range_buflen
);
340 for (i
= 0; i
< gpadl
->rangecount
; i
++) {
341 pagecount
= gpadl
->range
[i
].ByteCount
>> PAGE_SHIFT
;
342 pagecount
= (pagecount
> 26) ? 26 : pagecount
;
344 DPRINT_DBG(VMBUS
, "gpadl range %d - len %d offset %d "
345 "page count %d", i
, gpadl
->range
[i
].ByteCount
,
346 gpadl
->range
[i
].ByteOffset
, pagecount
);
348 for (j
= 0; j
< pagecount
; j
++)
349 DPRINT_DBG(VMBUS
, "%d) pfn %llu", j
,
350 gpadl
->range
[i
].PfnArray
[j
]);
355 * create_gpadl_header - Creates a gpadl for the specified buffer
357 static int create_gpadl_header(void *kbuffer
, u32 size
,
358 struct vmbus_channel_msginfo
**msginfo
,
363 unsigned long long pfn
;
364 struct vmbus_channel_gpadl_header
*gpadl_header
;
365 struct vmbus_channel_gpadl_body
*gpadl_body
;
366 struct vmbus_channel_msginfo
*msgheader
;
367 struct vmbus_channel_msginfo
*msgbody
= NULL
;
370 int pfnsum
, pfncount
, pfnleft
, pfncurr
, pfnsize
;
372 /* ASSERT((kbuffer & (PAGE_SIZE-1)) == 0); */
373 /* ASSERT((Size & (PAGE_SIZE-1)) == 0); */
375 pagecount
= size
>> PAGE_SHIFT
;
376 pfn
= virt_to_phys(kbuffer
) >> PAGE_SHIFT
;
378 /* do we need a gpadl body msg */
379 pfnsize
= MAX_SIZE_CHANNEL_MESSAGE
-
380 sizeof(struct vmbus_channel_gpadl_header
) -
381 sizeof(struct gpa_range
);
382 pfncount
= pfnsize
/ sizeof(u64
);
384 if (pagecount
> pfncount
) {
385 /* we need a gpadl body */
386 /* fill in the header */
387 msgsize
= sizeof(struct vmbus_channel_msginfo
) +
388 sizeof(struct vmbus_channel_gpadl_header
) +
389 sizeof(struct gpa_range
) + pfncount
* sizeof(u64
);
390 msgheader
= kzalloc(msgsize
, GFP_KERNEL
);
394 INIT_LIST_HEAD(&msgheader
->submsglist
);
395 msgheader
->msgsize
= msgsize
;
397 gpadl_header
= (struct vmbus_channel_gpadl_header
*)
399 gpadl_header
->rangecount
= 1;
400 gpadl_header
->range_buflen
= sizeof(struct gpa_range
) +
401 pagecount
* sizeof(u64
);
402 gpadl_header
->range
[0].ByteOffset
= 0;
403 gpadl_header
->range
[0].ByteCount
= size
;
404 for (i
= 0; i
< pfncount
; i
++)
405 gpadl_header
->range
[0].PfnArray
[i
] = pfn
+i
;
406 *msginfo
= msgheader
;
410 pfnleft
= pagecount
- pfncount
;
412 /* how many pfns can we fit */
413 pfnsize
= MAX_SIZE_CHANNEL_MESSAGE
-
414 sizeof(struct vmbus_channel_gpadl_body
);
415 pfncount
= pfnsize
/ sizeof(u64
);
417 /* fill in the body */
419 if (pfnleft
> pfncount
)
424 msgsize
= sizeof(struct vmbus_channel_msginfo
) +
425 sizeof(struct vmbus_channel_gpadl_body
) +
426 pfncurr
* sizeof(u64
);
427 msgbody
= kzalloc(msgsize
, GFP_KERNEL
);
428 /* FIXME: we probably need to more if this fails */
431 msgbody
->msgsize
= msgsize
;
434 (struct vmbus_channel_gpadl_body
*)msgbody
->msg
;
438 * Gpadl is u32 and we are using a pointer which could
441 /* gpadl_body->Gpadl = kbuffer; */
442 for (i
= 0; i
< pfncurr
; i
++)
443 gpadl_body
->pfn
[i
] = pfn
+ pfnsum
+ i
;
445 /* add to msg header */
446 list_add_tail(&msgbody
->msglistentry
,
447 &msgheader
->submsglist
);
452 /* everything fits in a header */
453 msgsize
= sizeof(struct vmbus_channel_msginfo
) +
454 sizeof(struct vmbus_channel_gpadl_header
) +
455 sizeof(struct gpa_range
) + pagecount
* sizeof(u64
);
456 msgheader
= kzalloc(msgsize
, GFP_KERNEL
);
457 if (msgheader
== NULL
)
459 msgheader
->msgsize
= msgsize
;
461 gpadl_header
= (struct vmbus_channel_gpadl_header
*)
463 gpadl_header
->rangecount
= 1;
464 gpadl_header
->range_buflen
= sizeof(struct gpa_range
) +
465 pagecount
* sizeof(u64
);
466 gpadl_header
->range
[0].ByteOffset
= 0;
467 gpadl_header
->range
[0].ByteCount
= size
;
468 for (i
= 0; i
< pagecount
; i
++)
469 gpadl_header
->range
[0].PfnArray
[i
] = pfn
+i
;
471 *msginfo
= msgheader
;
483 * vmbus_establish_gpadl - Estabish a GPADL for the specified buffer
485 * @channel: a channel
486 * @kbuffer: from kmalloc
487 * @size: page-size multiple
488 * @gpadl_handle: some funky thing
490 int vmbus_establish_gpadl(struct vmbus_channel
*channel
, void *kbuffer
,
491 u32 size
, u32
*gpadl_handle
)
493 struct vmbus_channel_gpadl_header
*gpadlmsg
;
494 struct vmbus_channel_gpadl_body
*gpadl_body
;
495 /* struct vmbus_channel_gpadl_created *gpadlCreated; */
496 struct vmbus_channel_msginfo
*msginfo
= NULL
;
497 struct vmbus_channel_msginfo
*submsginfo
;
499 struct list_head
*curr
;
500 u32 next_gpadl_handle
;
504 next_gpadl_handle
= atomic_read(&gVmbusConnection
.NextGpadlHandle
);
505 atomic_inc(&gVmbusConnection
.NextGpadlHandle
);
507 ret
= create_gpadl_header(kbuffer
, size
, &msginfo
, &msgcount
);
511 msginfo
->waitevent
= osd_waitevent_create();
512 if (!msginfo
->waitevent
) {
517 gpadlmsg
= (struct vmbus_channel_gpadl_header
*)msginfo
->msg
;
518 gpadlmsg
->header
.msgtype
= CHANNELMSG_GPADL_HEADER
;
519 gpadlmsg
->child_relid
= channel
->offermsg
.child_relid
;
520 gpadlmsg
->gpadl
= next_gpadl_handle
;
522 dump_gpadl_header(gpadlmsg
);
524 spin_lock_irqsave(&gVmbusConnection
.channelmsg_lock
, flags
);
525 list_add_tail(&msginfo
->msglistentry
,
526 &gVmbusConnection
.ChannelMsgList
);
528 spin_unlock_irqrestore(&gVmbusConnection
.channelmsg_lock
, flags
);
529 DPRINT_DBG(VMBUS
, "buffer %p, size %d msg cnt %d",
530 kbuffer
, size
, msgcount
);
532 DPRINT_DBG(VMBUS
, "Sending GPADL Header - len %zd",
533 msginfo
->msgsize
- sizeof(*msginfo
));
535 ret
= VmbusPostMessage(gpadlmsg
, msginfo
->msgsize
-
538 DPRINT_ERR(VMBUS
, "Unable to open channel - %d", ret
);
543 list_for_each(curr
, &msginfo
->submsglist
) {
545 /* FIXME: should this use list_entry() instead ? */
546 submsginfo
= (struct vmbus_channel_msginfo
*)curr
;
548 (struct vmbus_channel_gpadl_body
*)submsginfo
->msg
;
550 gpadl_body
->header
.msgtype
=
551 CHANNELMSG_GPADL_BODY
;
552 gpadl_body
->gpadl
= next_gpadl_handle
;
554 DPRINT_DBG(VMBUS
, "Sending GPADL Body - len %zd",
555 submsginfo
->msgsize
-
556 sizeof(*submsginfo
));
558 dump_gpadl_body(gpadl_body
, submsginfo
->msgsize
-
559 sizeof(*submsginfo
));
560 ret
= VmbusPostMessage(gpadl_body
,
561 submsginfo
->msgsize
-
562 sizeof(*submsginfo
));
568 osd_waitevent_wait(msginfo
->waitevent
);
570 /* At this point, we received the gpadl created msg */
571 DPRINT_DBG(VMBUS
, "Received GPADL created "
572 "(relid %d, status %d handle %x)",
573 channel
->offermsg
.child_relid
,
574 msginfo
->response
.gpadl_created
.creation_status
,
577 *gpadl_handle
= gpadlmsg
->gpadl
;
580 spin_lock_irqsave(&gVmbusConnection
.channelmsg_lock
, flags
);
581 list_del(&msginfo
->msglistentry
);
582 spin_unlock_irqrestore(&gVmbusConnection
.channelmsg_lock
, flags
);
584 kfree(msginfo
->waitevent
);
588 EXPORT_SYMBOL_GPL(vmbus_establish_gpadl
);
591 * vmbus_teardown_gpadl -Teardown the specified GPADL handle
593 int vmbus_teardown_gpadl(struct vmbus_channel
*channel
, u32 gpadl_handle
)
595 struct vmbus_channel_gpadl_teardown
*msg
;
596 struct vmbus_channel_msginfo
*info
;
600 /* ASSERT(gpadl_handle != 0); */
602 info
= kmalloc(sizeof(*info
) +
603 sizeof(struct vmbus_channel_gpadl_teardown
), GFP_KERNEL
);
607 info
->waitevent
= osd_waitevent_create();
608 if (!info
->waitevent
) {
613 msg
= (struct vmbus_channel_gpadl_teardown
*)info
->msg
;
615 msg
->header
.msgtype
= CHANNELMSG_GPADL_TEARDOWN
;
616 msg
->child_relid
= channel
->offermsg
.child_relid
;
617 msg
->gpadl
= gpadl_handle
;
619 spin_lock_irqsave(&gVmbusConnection
.channelmsg_lock
, flags
);
620 list_add_tail(&info
->msglistentry
,
621 &gVmbusConnection
.ChannelMsgList
);
622 spin_unlock_irqrestore(&gVmbusConnection
.channelmsg_lock
, flags
);
624 ret
= VmbusPostMessage(msg
,
625 sizeof(struct vmbus_channel_gpadl_teardown
));
631 osd_waitevent_wait(info
->waitevent
);
633 /* Received a torndown response */
634 spin_lock_irqsave(&gVmbusConnection
.channelmsg_lock
, flags
);
635 list_del(&info
->msglistentry
);
636 spin_unlock_irqrestore(&gVmbusConnection
.channelmsg_lock
, flags
);
638 kfree(info
->waitevent
);
642 EXPORT_SYMBOL_GPL(vmbus_teardown_gpadl
);
645 * vmbus_close - Close the specified channel
647 void vmbus_close(struct vmbus_channel
*channel
)
649 struct vmbus_channel_close_channel
*msg
;
650 struct vmbus_channel_msginfo
*info
;
654 /* Stop callback and cancel the timer asap */
655 channel
->onchannel_callback
= NULL
;
656 del_timer_sync(&channel
->poll_timer
);
658 /* Send a closing message */
659 info
= kmalloc(sizeof(*info
) +
660 sizeof(struct vmbus_channel_close_channel
), GFP_KERNEL
);
661 /* FIXME: can't do anything other than return here because the
662 * function is void */
666 /* info->waitEvent = osd_waitevent_create(); */
668 msg
= (struct vmbus_channel_close_channel
*)info
->msg
;
669 msg
->header
.msgtype
= CHANNELMSG_CLOSECHANNEL
;
670 msg
->child_relid
= channel
->offermsg
.child_relid
;
672 ret
= VmbusPostMessage(msg
, sizeof(struct vmbus_channel_close_channel
));
678 /* Tear down the gpadl for the channel's ring buffer */
679 if (channel
->ringbuffer_gpadlhandle
)
680 vmbus_teardown_gpadl(channel
,
681 channel
->ringbuffer_gpadlhandle
);
683 /* TODO: Send a msg to release the childRelId */
685 /* Cleanup the ring buffers for this channel */
686 ringbuffer_cleanup(&channel
->outbound
);
687 ringbuffer_cleanup(&channel
->inbound
);
689 osd_page_free(channel
->ringbuffer_pages
, channel
->ringbuffer_pagecount
);
694 * If we are closing the channel during an error path in
695 * opening the channel, don't free the channel since the
696 * caller will free the channel
699 if (channel
->state
== CHANNEL_OPEN_STATE
) {
700 spin_lock_irqsave(&gVmbusConnection
.channel_lock
, flags
);
701 list_del(&channel
->listentry
);
702 spin_unlock_irqrestore(&gVmbusConnection
.channel_lock
, flags
);
704 free_channel(channel
);
707 EXPORT_SYMBOL_GPL(vmbus_close
);
710 * vmbus_sendpacket() - Send the specified buffer on the given channel
711 * @channel: Pointer to vmbus_channel structure.
712 * @buffer: Pointer to the buffer you want to receive the data into.
713 * @bufferlen: Maximum size of what the the buffer will hold
714 * @requestid: Identifier of the request
715 * @type: Type of packet that is being send e.g. negotiate, time
718 * Sends data in @buffer directly to hyper-v via the vmbus
719 * This will send the data unparsed to hyper-v.
721 * Mainly used by Hyper-V drivers.
723 int vmbus_sendpacket(struct vmbus_channel
*channel
, const void *buffer
,
724 u32 bufferlen
, u64 requestid
,
725 enum vmbus_packet_type type
, u32 flags
)
727 struct vmpacket_descriptor desc
;
728 u32 packetlen
= sizeof(struct vmpacket_descriptor
) + bufferlen
;
729 u32 packetlen_aligned
= ALIGN_UP(packetlen
, sizeof(u64
));
730 struct scatterlist bufferlist
[3];
731 u64 aligned_data
= 0;
734 DPRINT_DBG(VMBUS
, "channel %p buffer %p len %d",
735 channel
, buffer
, bufferlen
);
737 dump_vmbus_channel(channel
);
739 /* ASSERT((packetLenAligned - packetLen) < sizeof(u64)); */
741 /* Setup the descriptor */
742 desc
.Type
= type
; /* VmbusPacketTypeDataInBand; */
743 desc
.Flags
= flags
; /* VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED; */
744 /* in 8-bytes granularity */
745 desc
.DataOffset8
= sizeof(struct vmpacket_descriptor
) >> 3;
746 desc
.Length8
= (u16
)(packetlen_aligned
>> 3);
747 desc
.TransactionId
= requestid
;
749 sg_init_table(bufferlist
, 3);
750 sg_set_buf(&bufferlist
[0], &desc
, sizeof(struct vmpacket_descriptor
));
751 sg_set_buf(&bufferlist
[1], buffer
, bufferlen
);
752 sg_set_buf(&bufferlist
[2], &aligned_data
,
753 packetlen_aligned
- packetlen
);
755 ret
= ringbuffer_write(&channel
->outbound
, bufferlist
, 3);
757 /* TODO: We should determine if this is optional */
758 if (ret
== 0 && !get_ringbuffer_interrupt_mask(&channel
->outbound
))
759 vmbus_setevent(channel
);
763 EXPORT_SYMBOL(vmbus_sendpacket
);
766 * vmbus_sendpacket_pagebuffer - Send a range of single-page buffer
767 * packets using a GPADL Direct packet type.
769 int vmbus_sendpacket_pagebuffer(struct vmbus_channel
*channel
,
770 struct hv_page_buffer pagebuffers
[],
771 u32 pagecount
, void *buffer
, u32 bufferlen
,
776 struct vmbus_channel_packet_page_buffer desc
;
779 u32 packetlen_aligned
;
780 struct scatterlist bufferlist
[3];
781 u64 aligned_data
= 0;
783 if (pagecount
> MAX_PAGE_BUFFER_COUNT
)
786 dump_vmbus_channel(channel
);
789 * Adjust the size down since vmbus_channel_packet_page_buffer is the
790 * largest size we support
792 descsize
= sizeof(struct vmbus_channel_packet_page_buffer
) -
793 ((MAX_PAGE_BUFFER_COUNT
- pagecount
) *
794 sizeof(struct hv_page_buffer
));
795 packetlen
= descsize
+ bufferlen
;
796 packetlen_aligned
= ALIGN_UP(packetlen
, sizeof(u64
));
798 /* ASSERT((packetLenAligned - packetLen) < sizeof(u64)); */
800 /* Setup the descriptor */
801 desc
.type
= VmbusPacketTypeDataUsingGpaDirect
;
802 desc
.flags
= VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED
;
803 desc
.dataoffset8
= descsize
>> 3; /* in 8-bytes grandularity */
804 desc
.length8
= (u16
)(packetlen_aligned
>> 3);
805 desc
.transactionid
= requestid
;
806 desc
.rangecount
= pagecount
;
808 for (i
= 0; i
< pagecount
; i
++) {
809 desc
.range
[i
].Length
= pagebuffers
[i
].Length
;
810 desc
.range
[i
].Offset
= pagebuffers
[i
].Offset
;
811 desc
.range
[i
].Pfn
= pagebuffers
[i
].Pfn
;
814 sg_init_table(bufferlist
, 3);
815 sg_set_buf(&bufferlist
[0], &desc
, descsize
);
816 sg_set_buf(&bufferlist
[1], buffer
, bufferlen
);
817 sg_set_buf(&bufferlist
[2], &aligned_data
,
818 packetlen_aligned
- packetlen
);
820 ret
= ringbuffer_write(&channel
->outbound
, bufferlist
, 3);
822 /* TODO: We should determine if this is optional */
823 if (ret
== 0 && !get_ringbuffer_interrupt_mask(&channel
->outbound
))
824 vmbus_setevent(channel
);
828 EXPORT_SYMBOL_GPL(vmbus_sendpacket_pagebuffer
);
831 * vmbus_sendpacket_multipagebuffer - Send a multi-page buffer packet
832 * using a GPADL Direct packet type.
834 int vmbus_sendpacket_multipagebuffer(struct vmbus_channel
*channel
,
835 struct hv_multipage_buffer
*multi_pagebuffer
,
836 void *buffer
, u32 bufferlen
, u64 requestid
)
839 struct vmbus_channel_packet_multipage_buffer desc
;
842 u32 packetlen_aligned
;
843 struct scatterlist bufferlist
[3];
844 u64 aligned_data
= 0;
845 u32 pfncount
= NUM_PAGES_SPANNED(multi_pagebuffer
->Offset
,
846 multi_pagebuffer
->Length
);
848 dump_vmbus_channel(channel
);
850 DPRINT_DBG(VMBUS
, "data buffer - offset %u len %u pfn count %u",
851 multi_pagebuffer
->Offset
,
852 multi_pagebuffer
->Length
, pfncount
);
854 if ((pfncount
< 0) || (pfncount
> MAX_MULTIPAGE_BUFFER_COUNT
))
858 * Adjust the size down since vmbus_channel_packet_multipage_buffer is
859 * the largest size we support
861 descsize
= sizeof(struct vmbus_channel_packet_multipage_buffer
) -
862 ((MAX_MULTIPAGE_BUFFER_COUNT
- pfncount
) *
864 packetlen
= descsize
+ bufferlen
;
865 packetlen_aligned
= ALIGN_UP(packetlen
, sizeof(u64
));
867 /* ASSERT((packetLenAligned - packetLen) < sizeof(u64)); */
869 /* Setup the descriptor */
870 desc
.type
= VmbusPacketTypeDataUsingGpaDirect
;
871 desc
.flags
= VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED
;
872 desc
.dataoffset8
= descsize
>> 3; /* in 8-bytes grandularity */
873 desc
.length8
= (u16
)(packetlen_aligned
>> 3);
874 desc
.transactionid
= requestid
;
877 desc
.range
.Length
= multi_pagebuffer
->Length
;
878 desc
.range
.Offset
= multi_pagebuffer
->Offset
;
880 memcpy(desc
.range
.PfnArray
, multi_pagebuffer
->PfnArray
,
881 pfncount
* sizeof(u64
));
883 sg_init_table(bufferlist
, 3);
884 sg_set_buf(&bufferlist
[0], &desc
, descsize
);
885 sg_set_buf(&bufferlist
[1], buffer
, bufferlen
);
886 sg_set_buf(&bufferlist
[2], &aligned_data
,
887 packetlen_aligned
- packetlen
);
889 ret
= ringbuffer_write(&channel
->outbound
, bufferlist
, 3);
891 /* TODO: We should determine if this is optional */
892 if (ret
== 0 && !get_ringbuffer_interrupt_mask(&channel
->outbound
))
893 vmbus_setevent(channel
);
897 EXPORT_SYMBOL_GPL(vmbus_sendpacket_multipagebuffer
);
900 * vmbus_recvpacket() - Retrieve the user packet on the specified channel
901 * @channel: Pointer to vmbus_channel structure.
902 * @buffer: Pointer to the buffer you want to receive the data into.
903 * @bufferlen: Maximum size of what the the buffer will hold
904 * @buffer_actual_len: The actual size of the data after it was received
905 * @requestid: Identifier of the request
907 * Receives directly from the hyper-v vmbus and puts the data it received
908 * into Buffer. This will receive the data unparsed from hyper-v.
910 * Mainly used by Hyper-V drivers.
912 int vmbus_recvpacket(struct vmbus_channel
*channel
, void *buffer
,
913 u32 bufferlen
, u32
*buffer_actual_len
, u64
*requestid
)
915 struct vmpacket_descriptor desc
;
921 *buffer_actual_len
= 0;
924 spin_lock_irqsave(&channel
->inbound_lock
, flags
);
926 ret
= ringbuffer_peek(&channel
->inbound
, &desc
,
927 sizeof(struct vmpacket_descriptor
));
929 spin_unlock_irqrestore(&channel
->inbound_lock
, flags
);
931 /* DPRINT_DBG(VMBUS, "nothing to read!!"); */
935 /* VmbusChannelClearEvent(Channel); */
937 packetlen
= desc
.Length8
<< 3;
938 userlen
= packetlen
- (desc
.DataOffset8
<< 3);
939 /* ASSERT(userLen > 0); */
941 DPRINT_DBG(VMBUS
, "packet received on channel %p relid %d <type %d "
942 "flag %d tid %llx pktlen %d datalen %d> ",
943 channel
, channel
->offermsg
.child_relid
, desc
.Type
,
944 desc
.Flags
, desc
.TransactionId
, packetlen
, userlen
);
946 *buffer_actual_len
= userlen
;
948 if (userlen
> bufferlen
) {
949 spin_unlock_irqrestore(&channel
->inbound_lock
, flags
);
951 DPRINT_ERR(VMBUS
, "buffer too small - got %d needs %d",
956 *requestid
= desc
.TransactionId
;
958 /* Copy over the packet to the user buffer */
959 ret
= ringbuffer_read(&channel
->inbound
, buffer
, userlen
,
960 (desc
.DataOffset8
<< 3));
962 spin_unlock_irqrestore(&channel
->inbound_lock
, flags
);
966 EXPORT_SYMBOL(vmbus_recvpacket
);
969 * vmbus_recvpacket_raw - Retrieve the raw packet on the specified channel
971 int vmbus_recvpacket_raw(struct vmbus_channel
*channel
, void *buffer
,
972 u32 bufferlen
, u32
*buffer_actual_len
,
975 struct vmpacket_descriptor desc
;
981 *buffer_actual_len
= 0;
984 spin_lock_irqsave(&channel
->inbound_lock
, flags
);
986 ret
= ringbuffer_peek(&channel
->inbound
, &desc
,
987 sizeof(struct vmpacket_descriptor
));
989 spin_unlock_irqrestore(&channel
->inbound_lock
, flags
);
991 /* DPRINT_DBG(VMBUS, "nothing to read!!"); */
995 /* VmbusChannelClearEvent(Channel); */
997 packetlen
= desc
.Length8
<< 3;
998 userlen
= packetlen
- (desc
.DataOffset8
<< 3);
1000 DPRINT_DBG(VMBUS
, "packet received on channel %p relid %d <type %d "
1001 "flag %d tid %llx pktlen %d datalen %d> ",
1002 channel
, channel
->offermsg
.child_relid
, desc
.Type
,
1003 desc
.Flags
, desc
.TransactionId
, packetlen
, userlen
);
1005 *buffer_actual_len
= packetlen
;
1007 if (packetlen
> bufferlen
) {
1008 spin_unlock_irqrestore(&channel
->inbound_lock
, flags
);
1010 DPRINT_ERR(VMBUS
, "buffer too small - needed %d bytes but "
1011 "got space for only %d bytes", packetlen
, bufferlen
);
1015 *requestid
= desc
.TransactionId
;
1017 /* Copy over the entire packet to the user buffer */
1018 ret
= ringbuffer_read(&channel
->inbound
, buffer
, packetlen
, 0);
1020 spin_unlock_irqrestore(&channel
->inbound_lock
, flags
);
1023 EXPORT_SYMBOL_GPL(vmbus_recvpacket_raw
);
1026 * vmbus_onchannel_event - Channel event callback
1028 void vmbus_onchannel_event(struct vmbus_channel
*channel
)
1030 dump_vmbus_channel(channel
);
1031 /* ASSERT(Channel->OnChannelCallback); */
1033 channel
->onchannel_callback(channel
->channel_callback_context
);
1035 mod_timer(&channel
->poll_timer
, jiffies
+ usecs_to_jiffies(100));
1039 * vmbus_ontimer - Timer event callback
1041 void vmbus_ontimer(unsigned long data
)
1043 struct vmbus_channel
*channel
= (struct vmbus_channel
*)data
;
1045 if (channel
->onchannel_callback
)
1046 channel
->onchannel_callback(channel
->channel_callback_context
);
1050 * dump_vmbus_channel- Dump vmbus channel info to the console
1052 static void dump_vmbus_channel(struct vmbus_channel
*channel
)
1054 DPRINT_DBG(VMBUS
, "Channel (%d)", channel
->offermsg
.child_relid
);
1055 dump_ring_info(&channel
->outbound
, "Outbound ");
1056 dump_ring_info(&channel
->inbound
, "Inbound ");