2019-05-30 06:57:35 +07:00
|
|
|
// SPDX-License-Identifier: GPL-2.0-only
|
2009-07-14 06:02:34 +07:00
|
|
|
/*
|
|
|
|
*
|
|
|
|
* Copyright (c) 2009, Microsoft Corporation.
|
|
|
|
*
|
|
|
|
* Authors:
|
|
|
|
* Haiyang Zhang <haiyangz@microsoft.com>
|
|
|
|
* Hank Janssen <hjanssen@microsoft.com>
|
|
|
|
*/
|
2011-03-30 03:58:47 +07:00
|
|
|
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
|
|
|
|
2009-08-18 07:22:08 +07:00
|
|
|
#include <linux/kernel.h>
|
2011-02-12 00:59:43 +07:00
|
|
|
#include <linux/sched.h>
|
|
|
|
#include <linux/wait.h>
|
2011-08-25 23:49:01 +07:00
|
|
|
#include <linux/delay.h>
|
2009-08-18 07:22:08 +07:00
|
|
|
#include <linux/mm.h>
|
include cleanup: Update gfp.h and slab.h includes to prepare for breaking implicit slab.h inclusion from percpu.h
percpu.h is included by sched.h and module.h and thus ends up being
included when building most .c files. percpu.h includes slab.h which
in turn includes gfp.h making everything defined by the two files
universally available and complicating inclusion dependencies.
percpu.h -> slab.h dependency is about to be removed. Prepare for
this change by updating users of gfp and slab facilities include those
headers directly instead of assuming availability. As this conversion
needs to touch large number of source files, the following script is
used as the basis of conversion.
http://userweb.kernel.org/~tj/misc/slabh-sweep.py
The script does the followings.
* Scan files for gfp and slab usages and update includes such that
only the necessary includes are there. ie. if only gfp is used,
gfp.h, if slab is used, slab.h.
* When the script inserts a new include, it looks at the include
blocks and try to put the new include such that its order conforms
to its surrounding. It's put in the include block which contains
core kernel includes, in the same order that the rest are ordered -
alphabetical, Christmas tree, rev-Xmas-tree or at the end if there
doesn't seem to be any matching order.
* If the script can't find a place to put a new include (mostly
because the file doesn't have fitting include block), it prints out
an error message indicating which .h file needs to be added to the
file.
The conversion was done in the following steps.
1. The initial automatic conversion of all .c files updated slightly
over 4000 files, deleting around 700 includes and adding ~480 gfp.h
and ~3000 slab.h inclusions. The script emitted errors for ~400
files.
2. Each error was manually checked. Some didn't need the inclusion,
some needed manual addition while adding it to implementation .h or
embedding .c file was more appropriate for others. This step added
inclusions to around 150 files.
3. The script was run again and the output was compared to the edits
from #2 to make sure no file was left behind.
4. Several build tests were done and a couple of problems were fixed.
e.g. lib/decompress_*.c used malloc/free() wrappers around slab
APIs requiring slab.h to be added manually.
5. The script was run on all .h files but without automatically
editing them as sprinkling gfp.h and slab.h inclusions around .h
files could easily lead to inclusion dependency hell. Most gfp.h
inclusion directives were ignored as stuff from gfp.h was usually
wildly available and often used in preprocessor macros. Each
slab.h inclusion directive was examined and added manually as
necessary.
6. percpu.h was updated not to include slab.h.
7. Build test were done on the following configurations and failures
were fixed. CONFIG_GCOV_KERNEL was turned off for all tests (as my
distributed build env didn't work with gcov compiles) and a few
more options had to be turned off depending on archs to make things
build (like ipr on powerpc/64 which failed due to missing writeq).
* x86 and x86_64 UP and SMP allmodconfig and a custom test config.
* powerpc and powerpc64 SMP allmodconfig
* sparc and sparc64 SMP allmodconfig
* ia64 SMP allmodconfig
* s390 SMP allmodconfig
* alpha SMP allmodconfig
* um on x86_64 SMP allmodconfig
8. percpu.h modifications were reverted so that it could be applied as
a separate patch and serve as bisection point.
Given the fact that I had only a couple of failures from tests on step
6, I'm fairly confident about the coverage of this conversion patch.
If there is a breakage, it's likely to be something in one of the arch
headers which should be easily discoverable easily on most builds of
the specific arch.
Signed-off-by: Tejun Heo <tj@kernel.org>
Guess-its-ok-by: Christoph Lameter <cl@linux-foundation.org>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Lee Schermerhorn <Lee.Schermerhorn@hp.com>
2010-03-24 15:04:11 +07:00
|
|
|
#include <linux/slab.h>
|
2009-08-18 07:22:08 +07:00
|
|
|
#include <linux/vmalloc.h>
|
2011-10-05 02:29:52 +07:00
|
|
|
#include <linux/hyperv.h>
|
2012-12-01 21:46:41 +07:00
|
|
|
#include <linux/export.h>
|
2017-08-02 23:09:14 +07:00
|
|
|
#include <asm/mshyperv.h>
|
|
|
|
|
2011-05-13 09:34:28 +07:00
|
|
|
#include "hyperv_vmbus.h"
|
2009-07-14 06:02:34 +07:00
|
|
|
|
|
|
|
|
2011-01-27 03:12:14 +07:00
|
|
|
struct vmbus_connection vmbus_connection = {
|
|
|
|
.conn_state = DISCONNECTED,
|
|
|
|
.next_gpadl_handle = ATOMIC_INIT(0xE1E10),
|
2019-09-06 06:01:21 +07:00
|
|
|
|
|
|
|
.ready_for_suspend_event= COMPLETION_INITIALIZER(
|
|
|
|
vmbus_connection.ready_for_suspend_event),
|
2019-09-06 06:01:22 +07:00
|
|
|
.ready_for_resume_event = COMPLETION_INITIALIZER(
|
|
|
|
vmbus_connection.ready_for_resume_event),
|
2009-07-14 06:02:34 +07:00
|
|
|
};
|
2016-12-04 03:34:40 +07:00
|
|
|
EXPORT_SYMBOL_GPL(vmbus_connection);
|
2009-07-14 06:02:34 +07:00
|
|
|
|
2012-12-01 21:46:41 +07:00
|
|
|
/*
|
|
|
|
* Negotiated protocol version with the host.
|
|
|
|
*/
|
|
|
|
__u32 vmbus_proto_version;
|
|
|
|
EXPORT_SYMBOL_GPL(vmbus_proto_version);
|
|
|
|
|
2012-12-01 21:46:38 +07:00
|
|
|
static __u32 vmbus_get_next_version(__u32 current_version)
|
|
|
|
{
|
|
|
|
switch (current_version) {
|
|
|
|
case (VERSION_WIN7):
|
|
|
|
return VERSION_WS2008;
|
|
|
|
|
|
|
|
case (VERSION_WIN8):
|
|
|
|
return VERSION_WIN7;
|
|
|
|
|
2014-04-04 08:02:45 +07:00
|
|
|
case (VERSION_WIN8_1):
|
|
|
|
return VERSION_WIN8;
|
|
|
|
|
2015-05-27 04:23:01 +07:00
|
|
|
case (VERSION_WIN10):
|
|
|
|
return VERSION_WIN8_1;
|
|
|
|
|
Drivers: hv: vmbus: enable VMBus protocol version 5.0
With VMBus protocol 5.0, we're able to better support new features, e.g.
running two or more VMBus drivers simultaneously in a single VM -- note:
we can't simply load the current VMBus driver twice, instead, a secondary
VMBus driver must be implemented.
This patch adds the support for the new VMBus protocol, which is available
on new Windows hosts, by:
1) We still use SINT2 for compatibility;
2) We must use Connection ID 4 for the Initiate Contact Message, and for
subsequent messages, we must use the Message Connection ID field in
the host-returned VersionResponse Message.
Notes for developers of the secondary VMBus driver:
1) Must use VMBus protocol 5.0 as well;
2) Must use a different SINT number that is not in use.
3) Must use Connection ID 4 for the Initiate Contact Message, and for
subsequent messages, must use the Message Connection ID field in
the host-returned VersionResponse Message.
4) It's possible that the primary VMBus driver using protocol version 4.0
can work with a secondary VMBus driver using protocol version 5.0, but it's
recommended that both should use 5.0 for new Hyper-V features in the future.
Signed-off-by: Dexuan Cui <decui@microsoft.com>
Cc: Stephen Hemminger <sthemmin@microsoft.com>
Cc: K. Y. Srinivasan <kys@microsoft.com>
Cc: Michael Kelley <mikelley@microsoft.com>
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2018-05-12 16:30:33 +07:00
|
|
|
case (VERSION_WIN10_V5):
|
|
|
|
return VERSION_WIN10;
|
|
|
|
|
2012-12-01 21:46:38 +07:00
|
|
|
case (VERSION_WS2008):
|
|
|
|
default:
|
|
|
|
return VERSION_INVAL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-09-06 06:01:19 +07:00
|
|
|
int vmbus_negotiate_version(struct vmbus_channel_msginfo *msginfo, u32 version)
|
2012-12-01 21:46:38 +07:00
|
|
|
{
|
|
|
|
int ret = 0;
|
2018-09-17 11:14:54 +07:00
|
|
|
unsigned int cur_cpu;
|
2012-12-01 21:46:38 +07:00
|
|
|
struct vmbus_channel_initiate_contact *msg;
|
|
|
|
unsigned long flags;
|
|
|
|
|
|
|
|
init_completion(&msginfo->waitevent);
|
|
|
|
|
|
|
|
msg = (struct vmbus_channel_initiate_contact *)msginfo->msg;
|
|
|
|
|
Drivers: hv: vmbus: enable VMBus protocol version 5.0
With VMBus protocol 5.0, we're able to better support new features, e.g.
running two or more VMBus drivers simultaneously in a single VM -- note:
we can't simply load the current VMBus driver twice, instead, a secondary
VMBus driver must be implemented.
This patch adds the support for the new VMBus protocol, which is available
on new Windows hosts, by:
1) We still use SINT2 for compatibility;
2) We must use Connection ID 4 for the Initiate Contact Message, and for
subsequent messages, we must use the Message Connection ID field in
the host-returned VersionResponse Message.
Notes for developers of the secondary VMBus driver:
1) Must use VMBus protocol 5.0 as well;
2) Must use a different SINT number that is not in use.
3) Must use Connection ID 4 for the Initiate Contact Message, and for
subsequent messages, must use the Message Connection ID field in
the host-returned VersionResponse Message.
4) It's possible that the primary VMBus driver using protocol version 4.0
can work with a secondary VMBus driver using protocol version 5.0, but it's
recommended that both should use 5.0 for new Hyper-V features in the future.
Signed-off-by: Dexuan Cui <decui@microsoft.com>
Cc: Stephen Hemminger <sthemmin@microsoft.com>
Cc: K. Y. Srinivasan <kys@microsoft.com>
Cc: Michael Kelley <mikelley@microsoft.com>
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2018-05-12 16:30:33 +07:00
|
|
|
memset(msg, 0, sizeof(*msg));
|
2012-12-01 21:46:38 +07:00
|
|
|
msg->header.msgtype = CHANNELMSG_INITIATE_CONTACT;
|
|
|
|
msg->vmbus_version_requested = version;
|
Drivers: hv: vmbus: enable VMBus protocol version 5.0
With VMBus protocol 5.0, we're able to better support new features, e.g.
running two or more VMBus drivers simultaneously in a single VM -- note:
we can't simply load the current VMBus driver twice, instead, a secondary
VMBus driver must be implemented.
This patch adds the support for the new VMBus protocol, which is available
on new Windows hosts, by:
1) We still use SINT2 for compatibility;
2) We must use Connection ID 4 for the Initiate Contact Message, and for
subsequent messages, we must use the Message Connection ID field in
the host-returned VersionResponse Message.
Notes for developers of the secondary VMBus driver:
1) Must use VMBus protocol 5.0 as well;
2) Must use a different SINT number that is not in use.
3) Must use Connection ID 4 for the Initiate Contact Message, and for
subsequent messages, must use the Message Connection ID field in
the host-returned VersionResponse Message.
4) It's possible that the primary VMBus driver using protocol version 4.0
can work with a secondary VMBus driver using protocol version 5.0, but it's
recommended that both should use 5.0 for new Hyper-V features in the future.
Signed-off-by: Dexuan Cui <decui@microsoft.com>
Cc: Stephen Hemminger <sthemmin@microsoft.com>
Cc: K. Y. Srinivasan <kys@microsoft.com>
Cc: Michael Kelley <mikelley@microsoft.com>
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2018-05-12 16:30:33 +07:00
|
|
|
|
|
|
|
/*
|
|
|
|
* VMBus protocol 5.0 (VERSION_WIN10_V5) requires that we must use
|
|
|
|
* VMBUS_MESSAGE_CONNECTION_ID_4 for the Initiate Contact Message,
|
|
|
|
* and for subsequent messages, we must use the Message Connection ID
|
|
|
|
* field in the host-returned Version Response Message. And, with
|
|
|
|
* VERSION_WIN10_V5, we don't use msg->interrupt_page, but we tell
|
|
|
|
* the host explicitly that we still use VMBUS_MESSAGE_SINT(2) for
|
|
|
|
* compatibility.
|
|
|
|
*
|
|
|
|
* On old hosts, we should always use VMBUS_MESSAGE_CONNECTION_ID (1).
|
|
|
|
*/
|
|
|
|
if (version >= VERSION_WIN10_V5) {
|
|
|
|
msg->msg_sint = VMBUS_MESSAGE_SINT;
|
|
|
|
vmbus_connection.msg_conn_id = VMBUS_MESSAGE_CONNECTION_ID_4;
|
|
|
|
} else {
|
|
|
|
msg->interrupt_page = virt_to_phys(vmbus_connection.int_page);
|
|
|
|
vmbus_connection.msg_conn_id = VMBUS_MESSAGE_CONNECTION_ID;
|
|
|
|
}
|
|
|
|
|
2013-09-14 01:32:55 +07:00
|
|
|
msg->monitor_page1 = virt_to_phys(vmbus_connection.monitor_pages[0]);
|
|
|
|
msg->monitor_page2 = virt_to_phys(vmbus_connection.monitor_pages[1]);
|
2015-12-15 07:01:56 +07:00
|
|
|
/*
|
|
|
|
* We want all channel messages to be delivered on CPU 0.
|
|
|
|
* This has been the behavior pre-win8. This is not
|
|
|
|
* perf issue and having all channel messages delivered on CPU 0
|
|
|
|
* would be ok.
|
2016-02-27 06:13:22 +07:00
|
|
|
* For post win8 hosts, we support receiving channel messagges on
|
|
|
|
* all the CPUs. This is needed for kexec to work correctly where
|
|
|
|
* the CPU attempting to connect may not be CPU 0.
|
2015-12-15 07:01:56 +07:00
|
|
|
*/
|
2017-05-01 06:21:18 +07:00
|
|
|
if (version >= VERSION_WIN8_1) {
|
2018-09-17 11:14:54 +07:00
|
|
|
cur_cpu = get_cpu();
|
|
|
|
msg->target_vcpu = hv_cpu_number_to_vp_number(cur_cpu);
|
|
|
|
vmbus_connection.connect_cpu = cur_cpu;
|
|
|
|
put_cpu();
|
2017-05-01 06:21:18 +07:00
|
|
|
} else {
|
2016-02-27 06:13:22 +07:00
|
|
|
msg->target_vcpu = 0;
|
2017-05-01 06:21:18 +07:00
|
|
|
vmbus_connection.connect_cpu = 0;
|
|
|
|
}
|
2012-12-01 21:46:38 +07:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Add to list before we send the request since we may
|
|
|
|
* receive the response before returning from this routine
|
|
|
|
*/
|
|
|
|
spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
|
|
|
|
list_add_tail(&msginfo->msglistentry,
|
|
|
|
&vmbus_connection.chn_msg_list);
|
|
|
|
|
|
|
|
spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
|
|
|
|
|
|
|
|
ret = vmbus_post_msg(msg,
|
2016-12-07 16:16:24 +07:00
|
|
|
sizeof(struct vmbus_channel_initiate_contact),
|
|
|
|
true);
|
2017-10-30 02:21:13 +07:00
|
|
|
|
|
|
|
trace_vmbus_negotiate_version(msg, ret);
|
|
|
|
|
2012-12-01 21:46:38 +07:00
|
|
|
if (ret != 0) {
|
|
|
|
spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
|
|
|
|
list_del(&msginfo->msglistentry);
|
|
|
|
spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock,
|
|
|
|
flags);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Wait for the connection response */
|
2014-01-17 02:59:58 +07:00
|
|
|
wait_for_completion(&msginfo->waitevent);
|
2012-12-01 21:46:38 +07:00
|
|
|
|
|
|
|
spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
|
|
|
|
list_del(&msginfo->msglistentry);
|
|
|
|
spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
|
|
|
|
|
|
|
|
/* Check if successful */
|
|
|
|
if (msginfo->response.version_response.version_supported) {
|
|
|
|
vmbus_connection.conn_state = CONNECTED;
|
Drivers: hv: vmbus: enable VMBus protocol version 5.0
With VMBus protocol 5.0, we're able to better support new features, e.g.
running two or more VMBus drivers simultaneously in a single VM -- note:
we can't simply load the current VMBus driver twice, instead, a secondary
VMBus driver must be implemented.
This patch adds the support for the new VMBus protocol, which is available
on new Windows hosts, by:
1) We still use SINT2 for compatibility;
2) We must use Connection ID 4 for the Initiate Contact Message, and for
subsequent messages, we must use the Message Connection ID field in
the host-returned VersionResponse Message.
Notes for developers of the secondary VMBus driver:
1) Must use VMBus protocol 5.0 as well;
2) Must use a different SINT number that is not in use.
3) Must use Connection ID 4 for the Initiate Contact Message, and for
subsequent messages, must use the Message Connection ID field in
the host-returned VersionResponse Message.
4) It's possible that the primary VMBus driver using protocol version 4.0
can work with a secondary VMBus driver using protocol version 5.0, but it's
recommended that both should use 5.0 for new Hyper-V features in the future.
Signed-off-by: Dexuan Cui <decui@microsoft.com>
Cc: Stephen Hemminger <sthemmin@microsoft.com>
Cc: K. Y. Srinivasan <kys@microsoft.com>
Cc: Michael Kelley <mikelley@microsoft.com>
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2018-05-12 16:30:33 +07:00
|
|
|
|
|
|
|
if (version >= VERSION_WIN10_V5)
|
|
|
|
vmbus_connection.msg_conn_id =
|
|
|
|
msginfo->response.version_response.msg_conn_id;
|
2012-12-01 21:46:38 +07:00
|
|
|
} else {
|
|
|
|
return -ECONNREFUSED;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2010-03-05 05:11:00 +07:00
|
|
|
/*
|
2011-01-27 03:12:08 +07:00
|
|
|
* vmbus_connect - Sends a connect request on the partition service connection
|
2009-09-01 01:40:14 +07:00
|
|
|
*/
|
2011-01-27 03:12:08 +07:00
|
|
|
int vmbus_connect(void)
|
2009-07-14 06:02:34 +07:00
|
|
|
{
|
2009-09-01 01:40:14 +07:00
|
|
|
int ret = 0;
|
2011-01-27 03:12:07 +07:00
|
|
|
struct vmbus_channel_msginfo *msginfo = NULL;
|
2012-12-01 21:46:38 +07:00
|
|
|
__u32 version;
|
2009-07-14 06:02:34 +07:00
|
|
|
|
2009-07-28 03:47:24 +07:00
|
|
|
/* Initialize the vmbus connection */
|
2011-01-27 03:12:14 +07:00
|
|
|
vmbus_connection.conn_state = CONNECTING;
|
|
|
|
vmbus_connection.work_queue = create_workqueue("hv_vmbus_con");
|
|
|
|
if (!vmbus_connection.work_queue) {
|
2011-06-07 05:50:10 +07:00
|
|
|
ret = -ENOMEM;
|
2011-05-10 21:55:44 +07:00
|
|
|
goto cleanup;
|
2009-07-30 04:00:09 +07:00
|
|
|
}
|
2009-07-14 06:02:34 +07:00
|
|
|
|
Drivers: hv: vmbus: Offload the handling of channels to two workqueues
vmbus_process_offer() mustn't call channel->sc_creation_callback()
directly for sub-channels, because sc_creation_callback() ->
vmbus_open() may never get the host's response to the
OPEN_CHANNEL message (the host may rescind a channel at any time,
e.g. in the case of hot removing a NIC), and vmbus_onoffer_rescind()
may not wake up the vmbus_open() as it's blocked due to a non-zero
vmbus_connection.offer_in_progress, and finally we have a deadlock.
The above is also true for primary channels, if the related device
drivers use sync probing mode by default.
And, usually the handling of primary channels and sub-channels can
depend on each other, so we should offload them to different
workqueues to avoid possible deadlock, e.g. in sync-probing mode,
NIC1's netvsc_subchan_work() can race with NIC2's netvsc_probe() ->
rtnl_lock(), and causes deadlock: the former gets the rtnl_lock
and waits for all the sub-channels to appear, but the latter
can't get the rtnl_lock and this blocks the handling of sub-channels.
The patch can fix the multiple-NIC deadlock described above for
v3.x kernels (e.g. RHEL 7.x) which don't support async-probing
of devices, and v4.4, v4.9, v4.14 and v4.18 which support async-probing
but don't enable async-probing for Hyper-V drivers (yet).
The patch can also fix the hang issue in sub-channel's handling described
above for all versions of kernels, including v4.19 and v4.20-rc4.
So actually the patch should be applied to all the existing kernels,
not only the kernels that have 8195b1396ec8.
Fixes: 8195b1396ec8 ("hv_netvsc: fix deadlock on hotplug")
Cc: stable@vger.kernel.org
Cc: Stephen Hemminger <sthemmin@microsoft.com>
Cc: K. Y. Srinivasan <kys@microsoft.com>
Cc: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: Dexuan Cui <decui@microsoft.com>
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2018-12-03 07:54:35 +07:00
|
|
|
vmbus_connection.handle_primary_chan_wq =
|
|
|
|
create_workqueue("hv_pri_chan");
|
|
|
|
if (!vmbus_connection.handle_primary_chan_wq) {
|
|
|
|
ret = -ENOMEM;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
vmbus_connection.handle_sub_chan_wq =
|
|
|
|
create_workqueue("hv_sub_chan");
|
|
|
|
if (!vmbus_connection.handle_sub_chan_wq) {
|
|
|
|
ret = -ENOMEM;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2011-01-27 03:12:14 +07:00
|
|
|
INIT_LIST_HEAD(&vmbus_connection.chn_msg_list);
|
2011-01-27 03:12:07 +07:00
|
|
|
spin_lock_init(&vmbus_connection.channelmsg_lock);
|
2009-07-14 06:02:34 +07:00
|
|
|
|
2011-01-27 03:12:14 +07:00
|
|
|
INIT_LIST_HEAD(&vmbus_connection.chn_list);
|
2015-12-15 07:01:51 +07:00
|
|
|
mutex_init(&vmbus_connection.channel_mutex);
|
2009-07-14 06:02:34 +07:00
|
|
|
|
2009-07-28 03:47:24 +07:00
|
|
|
/*
|
|
|
|
* Setup the vmbus event connection for channel interrupt
|
|
|
|
* abstraction stuff
|
|
|
|
*/
|
2011-02-12 00:59:00 +07:00
|
|
|
vmbus_connection.int_page =
|
|
|
|
(void *)__get_free_pages(GFP_KERNEL|__GFP_ZERO, 0);
|
2011-01-27 03:12:14 +07:00
|
|
|
if (vmbus_connection.int_page == NULL) {
|
2011-06-07 05:50:10 +07:00
|
|
|
ret = -ENOMEM;
|
2011-05-10 21:55:44 +07:00
|
|
|
goto cleanup;
|
2009-07-14 06:02:34 +07:00
|
|
|
}
|
|
|
|
|
2011-01-27 03:12:14 +07:00
|
|
|
vmbus_connection.recv_int_page = vmbus_connection.int_page;
|
|
|
|
vmbus_connection.send_int_page =
|
|
|
|
(void *)((unsigned long)vmbus_connection.int_page +
|
2009-09-01 01:40:14 +07:00
|
|
|
(PAGE_SIZE >> 1));
|
2009-07-14 06:02:34 +07:00
|
|
|
|
2009-09-01 01:40:14 +07:00
|
|
|
/*
|
|
|
|
* Setup the monitor notification facility. The 1st page for
|
|
|
|
* parent->child and the 2nd page for child->parent
|
2009-07-28 03:47:24 +07:00
|
|
|
*/
|
2013-09-14 01:32:55 +07:00
|
|
|
vmbus_connection.monitor_pages[0] = (void *)__get_free_pages((GFP_KERNEL|__GFP_ZERO), 0);
|
|
|
|
vmbus_connection.monitor_pages[1] = (void *)__get_free_pages((GFP_KERNEL|__GFP_ZERO), 0);
|
|
|
|
if ((vmbus_connection.monitor_pages[0] == NULL) ||
|
|
|
|
(vmbus_connection.monitor_pages[1] == NULL)) {
|
2011-06-07 05:50:10 +07:00
|
|
|
ret = -ENOMEM;
|
2011-05-10 21:55:44 +07:00
|
|
|
goto cleanup;
|
2009-07-14 06:02:34 +07:00
|
|
|
}
|
|
|
|
|
2011-01-27 03:12:07 +07:00
|
|
|
msginfo = kzalloc(sizeof(*msginfo) +
|
2009-09-01 01:40:14 +07:00
|
|
|
sizeof(struct vmbus_channel_initiate_contact),
|
|
|
|
GFP_KERNEL);
|
2011-01-27 03:12:07 +07:00
|
|
|
if (msginfo == NULL) {
|
2010-05-06 02:27:32 +07:00
|
|
|
ret = -ENOMEM;
|
2011-05-10 21:55:44 +07:00
|
|
|
goto cleanup;
|
2009-07-14 06:02:34 +07:00
|
|
|
}
|
|
|
|
|
2009-07-28 03:47:24 +07:00
|
|
|
/*
|
2012-12-01 21:46:38 +07:00
|
|
|
* Negotiate a compatible VMBUS version number with the
|
|
|
|
* host. We start with the highest number we can support
|
|
|
|
* and work our way down until we negotiate a compatible
|
|
|
|
* version.
|
2009-07-28 03:47:24 +07:00
|
|
|
*/
|
2009-07-14 06:02:34 +07:00
|
|
|
|
2012-12-01 21:46:56 +07:00
|
|
|
version = VERSION_CURRENT;
|
2009-07-14 06:02:34 +07:00
|
|
|
|
2012-12-01 21:46:38 +07:00
|
|
|
do {
|
|
|
|
ret = vmbus_negotiate_version(msginfo, version);
|
2013-09-05 05:41:58 +07:00
|
|
|
if (ret == -ETIMEDOUT)
|
2013-08-29 04:56:54 +07:00
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (vmbus_connection.conn_state == CONNECTED)
|
2012-12-01 21:46:38 +07:00
|
|
|
break;
|
2009-07-14 06:02:34 +07:00
|
|
|
|
2012-12-01 21:46:38 +07:00
|
|
|
version = vmbus_get_next_version(version);
|
|
|
|
} while (version != VERSION_INVAL);
|
2009-07-14 06:02:34 +07:00
|
|
|
|
2012-12-01 21:46:38 +07:00
|
|
|
if (version == VERSION_INVAL)
|
2011-05-10 21:55:44 +07:00
|
|
|
goto cleanup;
|
2009-07-14 06:02:34 +07:00
|
|
|
|
2012-12-01 21:46:41 +07:00
|
|
|
vmbus_proto_version = version;
|
2017-01-20 01:51:47 +07:00
|
|
|
pr_info("Vmbus version:%d.%d\n",
|
|
|
|
version >> 16, version & 0xFFFF);
|
2012-12-01 21:46:59 +07:00
|
|
|
|
2011-01-27 03:12:07 +07:00
|
|
|
kfree(msginfo);
|
2009-07-14 06:02:34 +07:00
|
|
|
return 0;
|
|
|
|
|
2011-05-10 21:55:44 +07:00
|
|
|
cleanup:
|
2012-12-01 21:46:59 +07:00
|
|
|
pr_err("Unable to connect to host\n");
|
2015-02-28 02:25:54 +07:00
|
|
|
|
2011-01-27 03:12:14 +07:00
|
|
|
vmbus_connection.conn_state = DISCONNECTED;
|
2015-02-28 02:25:54 +07:00
|
|
|
vmbus_disconnect();
|
|
|
|
|
|
|
|
kfree(msginfo);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
2009-07-14 06:02:34 +07:00
|
|
|
|
2015-02-28 02:25:54 +07:00
|
|
|
void vmbus_disconnect(void)
|
|
|
|
{
|
2015-04-23 11:31:32 +07:00
|
|
|
/*
|
|
|
|
* First send the unload request to the host.
|
|
|
|
*/
|
2016-02-27 06:13:16 +07:00
|
|
|
vmbus_initiate_unload(false);
|
2015-04-23 11:31:32 +07:00
|
|
|
|
Drivers: hv: vmbus: Offload the handling of channels to two workqueues
vmbus_process_offer() mustn't call channel->sc_creation_callback()
directly for sub-channels, because sc_creation_callback() ->
vmbus_open() may never get the host's response to the
OPEN_CHANNEL message (the host may rescind a channel at any time,
e.g. in the case of hot removing a NIC), and vmbus_onoffer_rescind()
may not wake up the vmbus_open() as it's blocked due to a non-zero
vmbus_connection.offer_in_progress, and finally we have a deadlock.
The above is also true for primary channels, if the related device
drivers use sync probing mode by default.
And, usually the handling of primary channels and sub-channels can
depend on each other, so we should offload them to different
workqueues to avoid possible deadlock, e.g. in sync-probing mode,
NIC1's netvsc_subchan_work() can race with NIC2's netvsc_probe() ->
rtnl_lock(), and causes deadlock: the former gets the rtnl_lock
and waits for all the sub-channels to appear, but the latter
can't get the rtnl_lock and this blocks the handling of sub-channels.
The patch can fix the multiple-NIC deadlock described above for
v3.x kernels (e.g. RHEL 7.x) which don't support async-probing
of devices, and v4.4, v4.9, v4.14 and v4.18 which support async-probing
but don't enable async-probing for Hyper-V drivers (yet).
The patch can also fix the hang issue in sub-channel's handling described
above for all versions of kernels, including v4.19 and v4.20-rc4.
So actually the patch should be applied to all the existing kernels,
not only the kernels that have 8195b1396ec8.
Fixes: 8195b1396ec8 ("hv_netvsc: fix deadlock on hotplug")
Cc: stable@vger.kernel.org
Cc: Stephen Hemminger <sthemmin@microsoft.com>
Cc: K. Y. Srinivasan <kys@microsoft.com>
Cc: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: Dexuan Cui <decui@microsoft.com>
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2018-12-03 07:54:35 +07:00
|
|
|
if (vmbus_connection.handle_sub_chan_wq)
|
|
|
|
destroy_workqueue(vmbus_connection.handle_sub_chan_wq);
|
|
|
|
|
|
|
|
if (vmbus_connection.handle_primary_chan_wq)
|
|
|
|
destroy_workqueue(vmbus_connection.handle_primary_chan_wq);
|
|
|
|
|
|
|
|
if (vmbus_connection.work_queue)
|
2011-01-27 03:12:14 +07:00
|
|
|
destroy_workqueue(vmbus_connection.work_queue);
|
2009-07-14 06:02:34 +07:00
|
|
|
|
2011-01-27 03:12:14 +07:00
|
|
|
if (vmbus_connection.int_page) {
|
2011-02-12 00:59:00 +07:00
|
|
|
free_pages((unsigned long)vmbus_connection.int_page, 0);
|
2011-01-27 03:12:14 +07:00
|
|
|
vmbus_connection.int_page = NULL;
|
2009-07-14 06:02:34 +07:00
|
|
|
}
|
|
|
|
|
2014-05-28 00:16:20 +07:00
|
|
|
free_pages((unsigned long)vmbus_connection.monitor_pages[0], 0);
|
|
|
|
free_pages((unsigned long)vmbus_connection.monitor_pages[1], 0);
|
2013-09-14 01:32:55 +07:00
|
|
|
vmbus_connection.monitor_pages[0] = NULL;
|
|
|
|
vmbus_connection.monitor_pages[1] = NULL;
|
2009-07-14 06:02:34 +07:00
|
|
|
}
|
|
|
|
|
2010-03-05 05:11:00 +07:00
|
|
|
/*
|
2011-01-27 03:12:08 +07:00
|
|
|
* relid2channel - Get the channel object given its
|
|
|
|
* child relative id (ie channel id)
|
2009-09-01 01:40:14 +07:00
|
|
|
*/
|
2015-03-27 23:10:09 +07:00
|
|
|
struct vmbus_channel *relid2channel(u32 relid)
|
2009-07-14 06:02:34 +07:00
|
|
|
{
|
2009-08-19 05:21:19 +07:00
|
|
|
struct vmbus_channel *channel;
|
2011-01-27 03:12:07 +07:00
|
|
|
struct vmbus_channel *found_channel = NULL;
|
2013-05-24 02:02:32 +07:00
|
|
|
struct list_head *cur, *tmp;
|
|
|
|
struct vmbus_channel *cur_sc;
|
2009-07-14 06:02:34 +07:00
|
|
|
|
2016-01-28 13:29:43 +07:00
|
|
|
BUG_ON(!mutex_is_locked(&vmbus_connection.channel_mutex));
|
|
|
|
|
2011-01-27 03:12:14 +07:00
|
|
|
list_for_each_entry(channel, &vmbus_connection.chn_list, listentry) {
|
2011-01-27 03:12:07 +07:00
|
|
|
if (channel->offermsg.child_relid == relid) {
|
|
|
|
found_channel = channel;
|
2009-07-14 06:02:34 +07:00
|
|
|
break;
|
2013-05-24 02:02:32 +07:00
|
|
|
} else if (!list_empty(&channel->sc_list)) {
|
|
|
|
/*
|
|
|
|
* Deal with sub-channels.
|
|
|
|
*/
|
|
|
|
list_for_each_safe(cur, tmp, &channel->sc_list) {
|
|
|
|
cur_sc = list_entry(cur, struct vmbus_channel,
|
|
|
|
sc_list);
|
|
|
|
if (cur_sc->offermsg.child_relid == relid) {
|
|
|
|
found_channel = cur_sc;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2009-07-14 06:02:34 +07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-01-27 03:12:07 +07:00
|
|
|
return found_channel;
|
2009-07-14 06:02:34 +07:00
|
|
|
}
|
|
|
|
|
2010-03-05 05:11:00 +07:00
|
|
|
/*
|
2017-02-12 13:02:20 +07:00
|
|
|
* vmbus_on_event - Process a channel event notification
|
2017-03-05 08:27:10 +07:00
|
|
|
*
|
|
|
|
* For batched channels (default) optimize host to guest signaling
|
|
|
|
* by ensuring:
|
|
|
|
* 1. While reading the channel, we disable interrupts from host.
|
|
|
|
* 2. Ensure that we process all posted messages from the host
|
|
|
|
* before returning from this callback.
|
|
|
|
* 3. Once we return, enable signaling from the host. Once this
|
|
|
|
* state is set we check to see if additional packets are
|
|
|
|
* available to read. In this case we repeat the process.
|
|
|
|
* If this tasklet has been running for a long time
|
|
|
|
* then reschedule ourselves.
|
2009-09-01 01:40:14 +07:00
|
|
|
*/
|
2017-02-12 13:02:20 +07:00
|
|
|
void vmbus_on_event(unsigned long data)
|
2009-07-14 06:02:34 +07:00
|
|
|
{
|
2017-02-12 13:02:20 +07:00
|
|
|
struct vmbus_channel *channel = (void *) data;
|
2017-03-05 08:27:10 +07:00
|
|
|
unsigned long time_limit = jiffies + 2;
|
2009-07-14 06:02:34 +07:00
|
|
|
|
2017-10-30 02:21:16 +07:00
|
|
|
trace_vmbus_on_event(channel);
|
|
|
|
|
2017-03-05 08:27:10 +07:00
|
|
|
do {
|
|
|
|
void (*callback_fn)(void *);
|
|
|
|
|
|
|
|
/* A channel once created is persistent even when
|
|
|
|
* there is no driver handling the device. An
|
|
|
|
* unloading driver sets the onchannel_callback to NULL.
|
2012-12-01 21:46:35 +07:00
|
|
|
*/
|
2017-03-05 08:27:10 +07:00
|
|
|
callback_fn = READ_ONCE(channel->onchannel_callback);
|
|
|
|
if (unlikely(callback_fn == NULL))
|
|
|
|
return;
|
2012-12-01 21:46:35 +07:00
|
|
|
|
2017-03-05 08:27:10 +07:00
|
|
|
(*callback_fn)(channel->channel_callback_context);
|
|
|
|
|
|
|
|
if (channel->callback_mode != HV_CALL_BATCHED)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (likely(hv_end_read(&channel->inbound) == 0))
|
|
|
|
return;
|
|
|
|
|
|
|
|
hv_begin_read(&channel->inbound);
|
|
|
|
} while (likely(time_before(jiffies, time_limit)));
|
|
|
|
|
|
|
|
/* The time limit (2 jiffies) has been reached */
|
|
|
|
tasklet_schedule(&channel->callback_event);
|
2009-07-14 06:02:34 +07:00
|
|
|
}
|
|
|
|
|
2010-03-05 05:11:00 +07:00
|
|
|
/*
|
2011-01-27 03:12:08 +07:00
|
|
|
* vmbus_post_msg - Send a msg on the vmbus's message connection
|
2009-09-01 01:40:14 +07:00
|
|
|
*/
|
2016-12-07 16:16:24 +07:00
|
|
|
int vmbus_post_msg(void *buffer, size_t buflen, bool can_sleep)
|
2009-07-14 06:02:34 +07:00
|
|
|
{
|
Drivers: hv: vmbus: enable VMBus protocol version 5.0
With VMBus protocol 5.0, we're able to better support new features, e.g.
running two or more VMBus drivers simultaneously in a single VM -- note:
we can't simply load the current VMBus driver twice, instead, a secondary
VMBus driver must be implemented.
This patch adds the support for the new VMBus protocol, which is available
on new Windows hosts, by:
1) We still use SINT2 for compatibility;
2) We must use Connection ID 4 for the Initiate Contact Message, and for
subsequent messages, we must use the Message Connection ID field in
the host-returned VersionResponse Message.
Notes for developers of the secondary VMBus driver:
1) Must use VMBus protocol 5.0 as well;
2) Must use a different SINT number that is not in use.
3) Must use Connection ID 4 for the Initiate Contact Message, and for
subsequent messages, must use the Message Connection ID field in
the host-returned VersionResponse Message.
4) It's possible that the primary VMBus driver using protocol version 4.0
can work with a secondary VMBus driver using protocol version 5.0, but it's
recommended that both should use 5.0 for new Hyper-V features in the future.
Signed-off-by: Dexuan Cui <decui@microsoft.com>
Cc: Stephen Hemminger <sthemmin@microsoft.com>
Cc: K. Y. Srinivasan <kys@microsoft.com>
Cc: Michael Kelley <mikelley@microsoft.com>
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2018-05-12 16:30:33 +07:00
|
|
|
struct vmbus_channel_message_header *hdr;
|
2011-01-27 03:12:07 +07:00
|
|
|
union hv_connection_id conn_id;
|
2011-08-25 23:49:01 +07:00
|
|
|
int ret = 0;
|
|
|
|
int retries = 0;
|
2016-07-02 06:26:36 +07:00
|
|
|
u32 usec = 1;
|
2009-07-14 06:02:34 +07:00
|
|
|
|
2011-01-27 03:12:07 +07:00
|
|
|
conn_id.asu32 = 0;
|
Drivers: hv: vmbus: enable VMBus protocol version 5.0
With VMBus protocol 5.0, we're able to better support new features, e.g.
running two or more VMBus drivers simultaneously in a single VM -- note:
we can't simply load the current VMBus driver twice, instead, a secondary
VMBus driver must be implemented.
This patch adds the support for the new VMBus protocol, which is available
on new Windows hosts, by:
1) We still use SINT2 for compatibility;
2) We must use Connection ID 4 for the Initiate Contact Message, and for
subsequent messages, we must use the Message Connection ID field in
the host-returned VersionResponse Message.
Notes for developers of the secondary VMBus driver:
1) Must use VMBus protocol 5.0 as well;
2) Must use a different SINT number that is not in use.
3) Must use Connection ID 4 for the Initiate Contact Message, and for
subsequent messages, must use the Message Connection ID field in
the host-returned VersionResponse Message.
4) It's possible that the primary VMBus driver using protocol version 4.0
can work with a secondary VMBus driver using protocol version 5.0, but it's
recommended that both should use 5.0 for new Hyper-V features in the future.
Signed-off-by: Dexuan Cui <decui@microsoft.com>
Cc: Stephen Hemminger <sthemmin@microsoft.com>
Cc: K. Y. Srinivasan <kys@microsoft.com>
Cc: Michael Kelley <mikelley@microsoft.com>
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2018-05-12 16:30:33 +07:00
|
|
|
conn_id.u.id = vmbus_connection.msg_conn_id;
|
2011-08-25 23:49:01 +07:00
|
|
|
|
|
|
|
/*
|
|
|
|
* hv_post_message() can have transient failures because of
|
|
|
|
* insufficient resources. Retry the operation a couple of
|
|
|
|
* times before giving up.
|
|
|
|
*/
|
2016-12-07 16:16:24 +07:00
|
|
|
while (retries < 100) {
|
2014-08-28 06:25:31 +07:00
|
|
|
ret = hv_post_message(conn_id, 1, buffer, buflen);
|
|
|
|
|
|
|
|
switch (ret) {
|
2015-02-28 02:25:59 +07:00
|
|
|
case HV_STATUS_INVALID_CONNECTION_ID:
|
Drivers: hv: vmbus: enable VMBus protocol version 5.0
With VMBus protocol 5.0, we're able to better support new features, e.g.
running two or more VMBus drivers simultaneously in a single VM -- note:
we can't simply load the current VMBus driver twice, instead, a secondary
VMBus driver must be implemented.
This patch adds the support for the new VMBus protocol, which is available
on new Windows hosts, by:
1) We still use SINT2 for compatibility;
2) We must use Connection ID 4 for the Initiate Contact Message, and for
subsequent messages, we must use the Message Connection ID field in
the host-returned VersionResponse Message.
Notes for developers of the secondary VMBus driver:
1) Must use VMBus protocol 5.0 as well;
2) Must use a different SINT number that is not in use.
3) Must use Connection ID 4 for the Initiate Contact Message, and for
subsequent messages, must use the Message Connection ID field in
the host-returned VersionResponse Message.
4) It's possible that the primary VMBus driver using protocol version 4.0
can work with a secondary VMBus driver using protocol version 5.0, but it's
recommended that both should use 5.0 for new Hyper-V features in the future.
Signed-off-by: Dexuan Cui <decui@microsoft.com>
Cc: Stephen Hemminger <sthemmin@microsoft.com>
Cc: K. Y. Srinivasan <kys@microsoft.com>
Cc: Michael Kelley <mikelley@microsoft.com>
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2018-05-12 16:30:33 +07:00
|
|
|
/*
|
|
|
|
* See vmbus_negotiate_version(): VMBus protocol 5.0
|
|
|
|
* requires that we must use
|
|
|
|
* VMBUS_MESSAGE_CONNECTION_ID_4 for the Initiate
|
|
|
|
* Contact message, but on old hosts that only
|
|
|
|
* support VMBus protocol 4.0 or lower, here we get
|
|
|
|
* HV_STATUS_INVALID_CONNECTION_ID and we should
|
|
|
|
* return an error immediately without retrying.
|
|
|
|
*/
|
2018-05-15 07:25:01 +07:00
|
|
|
hdr = buffer;
|
Drivers: hv: vmbus: enable VMBus protocol version 5.0
With VMBus protocol 5.0, we're able to better support new features, e.g.
running two or more VMBus drivers simultaneously in a single VM -- note:
we can't simply load the current VMBus driver twice, instead, a secondary
VMBus driver must be implemented.
This patch adds the support for the new VMBus protocol, which is available
on new Windows hosts, by:
1) We still use SINT2 for compatibility;
2) We must use Connection ID 4 for the Initiate Contact Message, and for
subsequent messages, we must use the Message Connection ID field in
the host-returned VersionResponse Message.
Notes for developers of the secondary VMBus driver:
1) Must use VMBus protocol 5.0 as well;
2) Must use a different SINT number that is not in use.
3) Must use Connection ID 4 for the Initiate Contact Message, and for
subsequent messages, must use the Message Connection ID field in
the host-returned VersionResponse Message.
4) It's possible that the primary VMBus driver using protocol version 4.0
can work with a secondary VMBus driver using protocol version 5.0, but it's
recommended that both should use 5.0 for new Hyper-V features in the future.
Signed-off-by: Dexuan Cui <decui@microsoft.com>
Cc: Stephen Hemminger <sthemmin@microsoft.com>
Cc: K. Y. Srinivasan <kys@microsoft.com>
Cc: Michael Kelley <mikelley@microsoft.com>
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2018-05-12 16:30:33 +07:00
|
|
|
if (hdr->msgtype == CHANNELMSG_INITIATE_CONTACT)
|
|
|
|
return -EINVAL;
|
2015-02-28 02:25:59 +07:00
|
|
|
/*
|
|
|
|
* We could get this if we send messages too
|
|
|
|
* frequently.
|
|
|
|
*/
|
|
|
|
ret = -EAGAIN;
|
|
|
|
break;
|
|
|
|
case HV_STATUS_INSUFFICIENT_MEMORY:
|
2014-08-28 06:25:31 +07:00
|
|
|
case HV_STATUS_INSUFFICIENT_BUFFERS:
|
2017-05-01 06:21:16 +07:00
|
|
|
ret = -ENOBUFS;
|
2014-08-28 06:25:31 +07:00
|
|
|
break;
|
|
|
|
case HV_STATUS_SUCCESS:
|
2011-08-25 23:49:01 +07:00
|
|
|
return ret;
|
2014-08-28 06:25:31 +07:00
|
|
|
default:
|
|
|
|
pr_err("hv_post_msg() failed; error code:%d\n", ret);
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
2011-08-25 23:49:01 +07:00
|
|
|
retries++;
|
2016-12-07 16:16:24 +07:00
|
|
|
if (can_sleep && usec > 1000)
|
|
|
|
msleep(usec / 1000);
|
|
|
|
else if (usec < MAX_UDELAY_MS * 1000)
|
|
|
|
udelay(usec);
|
|
|
|
else
|
|
|
|
mdelay(usec / 1000);
|
|
|
|
|
2017-05-19 00:46:05 +07:00
|
|
|
if (retries < 22)
|
2016-07-02 06:26:36 +07:00
|
|
|
usec *= 2;
|
2011-08-25 23:49:01 +07:00
|
|
|
}
|
|
|
|
return ret;
|
2009-07-14 06:02:34 +07:00
|
|
|
}
|
|
|
|
|
2010-03-05 05:11:00 +07:00
|
|
|
/*
|
2011-01-27 03:12:08 +07:00
|
|
|
* vmbus_set_event - Send an event notification to the parent
|
2009-09-01 01:40:14 +07:00
|
|
|
*/
|
2015-12-22 06:12:20 +07:00
|
|
|
void vmbus_set_event(struct vmbus_channel *channel)
|
2009-07-14 06:02:34 +07:00
|
|
|
{
|
2012-12-01 21:46:43 +07:00
|
|
|
u32 child_relid = channel->offermsg.child_relid;
|
2009-07-30 04:00:11 +07:00
|
|
|
|
2017-02-06 07:20:31 +07:00
|
|
|
if (!channel->is_dedicated_interrupt)
|
|
|
|
vmbus_send_interrupt(child_relid);
|
2012-12-01 21:46:46 +07:00
|
|
|
|
2017-10-30 01:33:40 +07:00
|
|
|
++channel->sig_events;
|
|
|
|
|
2017-08-02 23:09:16 +07:00
|
|
|
hv_do_fast_hypercall8(HVCALL_SIGNAL_EVENT, channel->sig_event);
|
2009-07-14 06:02:34 +07:00
|
|
|
}
|
2016-04-03 07:59:49 +07:00
|
|
|
EXPORT_SYMBOL_GPL(vmbus_set_event);
|