From: Hardik Garg <[email protected]> Sent: Thursday, July 16, 2026 5:19 PM > > VMBus sends CHANNELMSG_INITIATE_CONTACT through a Hyper-V message > connection ID. Older protocol versions use VMBUS_MESSAGE_CONNECTION_ID, > while protocol version 5.0 and newer normally use > VMBUS_MESSAGE_CONNECTION_ID_4. > > For a VTL2 kernel using VMBus protocol 5.0 or newer, the host > may expect INITIATE_CONTACT on either the redirect connection ID or > VMBUS_MESSAGE_CONNECTION_ID_4. There is no capability indication that > identifies which ID is active, so the driver must determine it at runtime. > > During VMBus negotiation, the redirect ID is tried first because it is > used by VTL2 configurations with VMBus redirection enabled. If the > redirect ID is unavailable, the host rejects it synchronously with > HV_STATUS_INVALID_CONNECTION_ID, allowing fallback to the standard ID. > > Return a distinct error for an invalid Initiate Contact connection ID so > this fallback does not mask other post-message failures or > protocol-version rejections. Preserve the existing connection ID > selection for older protocol versions or when running below VTL2. > > Signed-off-by: Hardik Garg <[email protected]>
Reviewed-by: Michael Kelley <[email protected]> > --- > > Notes (v2-changelog): > Changes in v2: > - Replace the connection ID array and loop with a single redirect > attempt, falling back to VMBUS_MESSAGE_CONNECTION_ID_4 only on > -ENXIO. > - Remove redundant connection-state and timeout checks and the > unreachable return after the loop. > - Simplify the commit message to describe runtime connection ID > selection without relay and message-port implementation details. > - Clarify the protocol 5.0 helper and VTL2 redirect comments, remove > redundant comments, and use an exact VTL2 check. > > Link to v1: https://lore.kernel.org/r/20260714213838.3367103-1- > [email protected] > > drivers/hv/connection.c | 47 +++++++++++++++++++++++---------------- > drivers/hv/hyperv_vmbus.h | 2 ++ > 2 files changed, 30 insertions(+), 19 deletions(-) > > diff --git a/drivers/hv/connection.c b/drivers/hv/connection.c > index b5b322ce16df4..0fd50d4cb5739 100644 > --- a/drivers/hv/connection.c > +++ b/drivers/hv/connection.c > @@ -72,7 +72,8 @@ module_param(max_version, uint, S_IRUGO); > MODULE_PARM_DESC(max_version, > "Maximal VMBus protocol version which can be negotiated"); > > -int vmbus_negotiate_version(struct vmbus_channel_msginfo *msginfo, u32 > version) > +static int vmbus_try_connection_id(struct vmbus_channel_msginfo *msginfo, > + u32 version, u32 connection_id) > { > int ret = 0; > struct vmbus_channel_initiate_contact *msg; > @@ -87,20 +88,20 @@ int vmbus_negotiate_version(struct vmbus_channel_msginfo > *msginfo, u32 version) > msg->vmbus_version_requested = version; > > /* > - * VMBus protocol 5.0 (VERSION_WIN10_V5) and higher require 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 and higher, we don't use msg->interrupt_page, but we > - * tell the host explicitly that we still use VMBUS_MESSAGE_SINT(2) for > - * compatibility. > + * For VMBus protocol 5.0 (VERSION_WIN10_V5) and higher, use the > + * caller-supplied connection_id for the Initiate Contact message so > + * the caller can implement the required retry scheme. For subsequent > + * messages, use the Message Connection ID field in the host-returned > + * Version Response message. With VERSION_WIN10_V5 and higher, we don't > + * use msg->interrupt_page, but 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; > msg->msg_vtl = ms_hyperv.vtl; > - vmbus_connection.msg_conn_id = VMBUS_MESSAGE_CONNECTION_ID_4; > + vmbus_connection.msg_conn_id = connection_id; > } else { > msg->interrupt_page = virt_to_phys(vmbus_connection.int_page); > vmbus_connection.msg_conn_id = VMBUS_MESSAGE_CONNECTION_ID; > @@ -165,6 +166,22 @@ int vmbus_negotiate_version(struct vmbus_channel_msginfo > *msginfo, u32 version) > return ret; > } > > +int vmbus_negotiate_version(struct vmbus_channel_msginfo *msginfo, u32 > version) > +{ > + int ret; > + > + /* Try the redirect ID first for VTL2 with VMBus protocol 5.0+. */ > + if (version >= VERSION_WIN10_V5 && ms_hyperv.vtl == 2) { > + ret = vmbus_try_connection_id(msginfo, version, > + VMBUS_MESSAGE_CONNECTION_ID_REDIRECT); > + if (ret != -ENXIO) > + return ret; > + } > + > + return vmbus_try_connection_id(msginfo, version, > + VMBUS_MESSAGE_CONNECTION_ID_4); > +} > + > /* > * vmbus_connect - Sends a connect request on the partition service > connection > */ > @@ -457,18 +474,10 @@ int vmbus_post_msg(void *buffer, size_t buflen, bool > can_sleep) > > switch (ret) { > case HV_STATUS_INVALID_CONNECTION_ID: > - /* > - * See vmbus_negotiate_version(): VMBus protocol 5.0 > - * and higher require 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. > - */ > + /* Allow INITIATE_CONTACT to try another connection ID. > */ > hdr = buffer; > if (hdr->msgtype == CHANNELMSG_INITIATE_CONTACT) > - return -EINVAL; > + return -ENXIO; > /* > * We could get this if we send messages too > * frequently. > diff --git a/drivers/hv/hyperv_vmbus.h b/drivers/hv/hyperv_vmbus.h > index 05a36854389af..87f8aca1a9fb5 100644 > --- a/drivers/hv/hyperv_vmbus.h > +++ b/drivers/hv/hyperv_vmbus.h > @@ -110,6 +110,8 @@ struct hv_input_post_message { > enum { > VMBUS_MESSAGE_CONNECTION_ID = 1, > VMBUS_MESSAGE_CONNECTION_ID_4 = 4, > + /* VTL2 redirect connection ID for INITIATE_CONTACT. */ > + VMBUS_MESSAGE_CONNECTION_ID_REDIRECT = 0x800074, > VMBUS_MESSAGE_PORT_ID = 1, > VMBUS_EVENT_CONNECTION_ID = 2, > VMBUS_EVENT_PORT_ID = 2, > -- > 2.34.1 >

