linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/8] Drivers: hv: Miscellaneous fixes
@ 2016-02-26 23:13 K. Y. Srinivasan
  2016-02-26 23:13 ` [PATCH 1/8] Drivers: hv: vmbus: don't loose HVMSG_TIMER_EXPIRED messages K. Y. Srinivasan
  0 siblings, 1 reply; 9+ messages in thread
From: K. Y. Srinivasan @ 2016-02-26 23:13 UTC (permalink / raw)
  To: gregkh, linux-kernel, devel, olaf, apw, vkuznets, jasowang
  Cc: K. Y. Srinivasan

Some miscellaneous fixes and cleanup.

Alex Ng (2):
  Drivers: hv: utils: Remove util transport handler from list if
    registration fails
  Drivers: hv: vmbus: Support kexec on ws2012 r2 and above

K. Y. Srinivasan (2):
  Drivers: hv: util: Pass the channel information during the init call
  Drivers: hv: vmbus: Support handling messages on multiple CPUs

Vitaly Kuznetsov (4):
  Drivers: hv: vmbus: don't loose HVMSG_TIMER_EXPIRED messages
  Drivers: hv: vmbus: avoid wait_for_completion() on crash
  Drivers: hv: vmbus: remove code duplication in message handling
  Drivers: hv: vmbus: avoid unneeded compiler optimizations in
    vmbus_wait_for_unload()

 drivers/hv/channel_mgmt.c       |   16 ++-----
 drivers/hv/connection.c         |   12 ++++-
 drivers/hv/hv.c                 |   10 ++++
 drivers/hv/hv_fcopy.c           |    2 +-
 drivers/hv/hv_kvp.c             |    2 +-
 drivers/hv/hv_snapshot.c        |    2 +-
 drivers/hv/hv_util.c            |    1 +
 drivers/hv/hv_utils_transport.c |    3 +
 drivers/hv/hyperv_vmbus.h       |   30 ++++++++++++-
 drivers/hv/vmbus_drv.c          |   92 +++++++++++----------------------------
 include/linux/hyperv.h          |    1 +
 11 files changed, 86 insertions(+), 85 deletions(-)

-- 
1.7.4.1

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH 1/8] Drivers: hv: vmbus: don't loose HVMSG_TIMER_EXPIRED messages
  2016-02-26 23:13 [PATCH 0/8] Drivers: hv: Miscellaneous fixes K. Y. Srinivasan
@ 2016-02-26 23:13 ` K. Y. Srinivasan
  2016-02-26 23:13   ` [PATCH 2/8] Drivers: hv: vmbus: avoid wait_for_completion() on crash K. Y. Srinivasan
                     ` (6 more replies)
  0 siblings, 7 replies; 9+ messages in thread
From: K. Y. Srinivasan @ 2016-02-26 23:13 UTC (permalink / raw)
  To: gregkh, linux-kernel, devel, olaf, apw, vkuznets, jasowang
  Cc: K. Y. Srinivasan

From: Vitaly Kuznetsov <vkuznets@redhat.com>

We must handle HVMSG_TIMER_EXPIRED messages in the interrupt context
and we offload all the rest to vmbus_on_msg_dpc() tasklet. This functions
loops to see if there are new messages pending. In case we'll ever see
HVMSG_TIMER_EXPIRED message there we're going to lose it as we can't
handle it from there. Avoid looping in vmbus_on_msg_dpc(), we're OK
with handling one message per interrupt.

Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com>
Reviewed-by: Radim Kr.má<rkrcmar@redhat.com>
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
---
 drivers/hv/vmbus_drv.c |   68 +++++++++++++++++++++++------------------------
 1 files changed, 33 insertions(+), 35 deletions(-)

diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c
index 063e5f5..30ea8ad 100644
--- a/drivers/hv/vmbus_drv.c
+++ b/drivers/hv/vmbus_drv.c
@@ -740,51 +740,49 @@ static void vmbus_on_msg_dpc(unsigned long data)
 	struct vmbus_channel_message_table_entry *entry;
 	struct onmessage_work_context *ctx;
 
-	while (1) {
-		if (msg->header.message_type == HVMSG_NONE)
-			/* no msg */
-			break;
+	if (msg->header.message_type == HVMSG_NONE)
+		/* no msg */
+		return;
 
-		hdr = (struct vmbus_channel_message_header *)msg->u.payload;
+	hdr = (struct vmbus_channel_message_header *)msg->u.payload;
 
-		if (hdr->msgtype >= CHANNELMSG_COUNT) {
-			WARN_ONCE(1, "unknown msgtype=%d\n", hdr->msgtype);
-			goto msg_handled;
-		}
+	if (hdr->msgtype >= CHANNELMSG_COUNT) {
+		WARN_ONCE(1, "unknown msgtype=%d\n", hdr->msgtype);
+		goto msg_handled;
+	}
 
-		entry = &channel_message_table[hdr->msgtype];
-		if (entry->handler_type	== VMHT_BLOCKING) {
-			ctx = kmalloc(sizeof(*ctx), GFP_ATOMIC);
-			if (ctx == NULL)
-				continue;
+	entry = &channel_message_table[hdr->msgtype];
+	if (entry->handler_type	== VMHT_BLOCKING) {
+		ctx = kmalloc(sizeof(*ctx), GFP_ATOMIC);
+		if (ctx == NULL)
+			return;
 
-			INIT_WORK(&ctx->work, vmbus_onmessage_work);
-			memcpy(&ctx->msg, msg, sizeof(*msg));
+		INIT_WORK(&ctx->work, vmbus_onmessage_work);
+		memcpy(&ctx->msg, msg, sizeof(*msg));
 
-			queue_work(vmbus_connection.work_queue, &ctx->work);
-		} else
-			entry->message_handler(hdr);
+		queue_work(vmbus_connection.work_queue, &ctx->work);
+	} else
+		entry->message_handler(hdr);
 
 msg_handled:
-		msg->header.message_type = HVMSG_NONE;
+	msg->header.message_type = HVMSG_NONE;
+
+	/*
+	 * Make sure the write to MessageType (ie set to
+	 * HVMSG_NONE) happens before we read the
+	 * MessagePending and EOMing. Otherwise, the EOMing
+	 * will not deliver any more messages since there is
+	 * no empty slot
+	 */
+	mb();
 
+	if (msg->header.message_flags.msg_pending) {
 		/*
-		 * Make sure the write to MessageType (ie set to
-		 * HVMSG_NONE) happens before we read the
-		 * MessagePending and EOMing. Otherwise, the EOMing
-		 * will not deliver any more messages since there is
-		 * no empty slot
+		 * This will cause message queue rescan to
+		 * possibly deliver another msg from the
+		 * hypervisor
 		 */
-		mb();
-
-		if (msg->header.message_flags.msg_pending) {
-			/*
-			 * This will cause message queue rescan to
-			 * possibly deliver another msg from the
-			 * hypervisor
-			 */
-			wrmsrl(HV_X64_MSR_EOM, 0);
-		}
+		wrmsrl(HV_X64_MSR_EOM, 0);
 	}
 }
 
-- 
1.7.4.1

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 2/8] Drivers: hv: vmbus: avoid wait_for_completion() on crash
  2016-02-26 23:13 ` [PATCH 1/8] Drivers: hv: vmbus: don't loose HVMSG_TIMER_EXPIRED messages K. Y. Srinivasan
@ 2016-02-26 23:13   ` K. Y. Srinivasan
  2016-02-26 23:13   ` [PATCH 3/8] Drivers: hv: vmbus: remove code duplication in message handling K. Y. Srinivasan
                     ` (5 subsequent siblings)
  6 siblings, 0 replies; 9+ messages in thread
From: K. Y. Srinivasan @ 2016-02-26 23:13 UTC (permalink / raw)
  To: gregkh, linux-kernel, devel, olaf, apw, vkuznets, jasowang
  Cc: K. Y. Srinivasan

From: Vitaly Kuznetsov <vkuznets@redhat.com>

wait_for_completion() may sleep, it enables interrupts and this
is something we really want to avoid on crashes because interrupt
handlers can cause other crashes. Switch to the recently introduced
vmbus_wait_for_unload() doing busy wait instead.

Reported-by: Radim Krcmar <rkrcmar@redhat.com>
Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com>
Reviewed-by: Radim Kr.má<rkrcmar@redhat.com>
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
---
 drivers/hv/channel_mgmt.c |    4 ++--
 drivers/hv/connection.c   |    2 +-
 drivers/hv/hyperv_vmbus.h |    2 +-
 drivers/hv/vmbus_drv.c    |    4 ++--
 4 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c
index b40f429..f70e352 100644
--- a/drivers/hv/channel_mgmt.c
+++ b/drivers/hv/channel_mgmt.c
@@ -641,7 +641,7 @@ static void vmbus_unload_response(struct vmbus_channel_message_header *hdr)
 	complete(&vmbus_connection.unload_event);
 }
 
-void vmbus_initiate_unload(void)
+void vmbus_initiate_unload(bool crash)
 {
 	struct vmbus_channel_message_header hdr;
 
@@ -658,7 +658,7 @@ void vmbus_initiate_unload(void)
 	 * vmbus_initiate_unload() is also called on crash and the crash can be
 	 * happening in an interrupt context, where scheduling is impossible.
 	 */
-	if (!in_interrupt())
+	if (!crash)
 		wait_for_completion(&vmbus_connection.unload_event);
 	else
 		vmbus_wait_for_unload();
diff --git a/drivers/hv/connection.c b/drivers/hv/connection.c
index fa86b2c..3b6dc00 100644
--- a/drivers/hv/connection.c
+++ b/drivers/hv/connection.c
@@ -236,7 +236,7 @@ void vmbus_disconnect(void)
 	/*
 	 * First send the unload request to the host.
 	 */
-	vmbus_initiate_unload();
+	vmbus_initiate_unload(false);
 
 	if (vmbus_connection.work_queue) {
 		drain_workqueue(vmbus_connection.work_queue);
diff --git a/drivers/hv/hyperv_vmbus.h b/drivers/hv/hyperv_vmbus.h
index b9ea7f5..b0299da 100644
--- a/drivers/hv/hyperv_vmbus.h
+++ b/drivers/hv/hyperv_vmbus.h
@@ -663,7 +663,7 @@ void hv_vss_onchannelcallback(void *);
 int hv_fcopy_init(struct hv_util_service *);
 void hv_fcopy_deinit(void);
 void hv_fcopy_onchannelcallback(void *);
-void vmbus_initiate_unload(void);
+void vmbus_initiate_unload(bool crash);
 
 static inline void hv_poll_channel(struct vmbus_channel *channel,
 				   void (*cb)(void *))
diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c
index 30ea8ad..c8f1671 100644
--- a/drivers/hv/vmbus_drv.c
+++ b/drivers/hv/vmbus_drv.c
@@ -1291,7 +1291,7 @@ static void hv_kexec_handler(void)
 	int cpu;
 
 	hv_synic_clockevents_cleanup();
-	vmbus_initiate_unload();
+	vmbus_initiate_unload(false);
 	for_each_online_cpu(cpu)
 		smp_call_function_single(cpu, hv_synic_cleanup, NULL, 1);
 	hv_cleanup();
@@ -1299,7 +1299,7 @@ static void hv_kexec_handler(void)
 
 static void hv_crash_handler(struct pt_regs *regs)
 {
-	vmbus_initiate_unload();
+	vmbus_initiate_unload(true);
 	/*
 	 * In crash handler we can't schedule synic cleanup for all CPUs,
 	 * doing the cleanup for current CPU only. This should be sufficient
-- 
1.7.4.1

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 3/8] Drivers: hv: vmbus: remove code duplication in message handling
  2016-02-26 23:13 ` [PATCH 1/8] Drivers: hv: vmbus: don't loose HVMSG_TIMER_EXPIRED messages K. Y. Srinivasan
  2016-02-26 23:13   ` [PATCH 2/8] Drivers: hv: vmbus: avoid wait_for_completion() on crash K. Y. Srinivasan
@ 2016-02-26 23:13   ` K. Y. Srinivasan
  2016-02-26 23:13   ` [PATCH 4/8] Drivers: hv: vmbus: avoid unneeded compiler optimizations in vmbus_wait_for_unload() K. Y. Srinivasan
                     ` (4 subsequent siblings)
  6 siblings, 0 replies; 9+ messages in thread
From: K. Y. Srinivasan @ 2016-02-26 23:13 UTC (permalink / raw)
  To: gregkh, linux-kernel, devel, olaf, apw, vkuznets, jasowang
  Cc: K. Y. Srinivasan

From: Vitaly Kuznetsov <vkuznets@redhat.com>

We have 3 functions dealing with messages and they all implement
the same logic to finalize reads, move it to vmbus_signal_eom().

Suggested-by: Radim Krcmar <rkrcmar@redhat.com>
Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com>
Reviewed-by: Radim Kr.má<rkrcmar@redhat.com>
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
---
 drivers/hv/channel_mgmt.c |   10 +---------
 drivers/hv/hyperv_vmbus.h |   24 ++++++++++++++++++++++++
 drivers/hv/vmbus_drv.c    |   40 ++--------------------------------------
 3 files changed, 27 insertions(+), 47 deletions(-)

diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c
index f70e352..73a17be 100644
--- a/drivers/hv/channel_mgmt.c
+++ b/drivers/hv/channel_mgmt.c
@@ -614,15 +614,7 @@ static void vmbus_wait_for_unload(void)
 		if (hdr->msgtype == CHANNELMSG_UNLOAD_RESPONSE)
 			unloaded = true;
 
-		msg->header.message_type = HVMSG_NONE;
-		/*
-		 * header.message_type needs to be written before we do
-		 * wrmsrl() below.
-		 */
-		mb();
-
-		if (msg->header.message_flags.msg_pending)
-			wrmsrl(HV_X64_MSR_EOM, 0);
+		vmbus_signal_eom(msg);
 
 		if (unloaded)
 			break;
diff --git a/drivers/hv/hyperv_vmbus.h b/drivers/hv/hyperv_vmbus.h
index b0299da..cada56a 100644
--- a/drivers/hv/hyperv_vmbus.h
+++ b/drivers/hv/hyperv_vmbus.h
@@ -624,6 +624,30 @@ struct vmbus_channel_message_table_entry {
 extern struct vmbus_channel_message_table_entry
 	channel_message_table[CHANNELMSG_COUNT];
 
+/* Free the message slot and signal end-of-message if required */
+static inline void vmbus_signal_eom(struct hv_message *msg)
+{
+	msg->header.message_type = HVMSG_NONE;
+
+	/*
+	 * Make sure the write to MessageType (ie set to
+	 * HVMSG_NONE) happens before we read the
+	 * MessagePending and EOMing. Otherwise, the EOMing
+	 * will not deliver any more messages since there is
+	 * no empty slot
+	 */
+	mb();
+
+	if (msg->header.message_flags.msg_pending) {
+		/*
+		 * This will cause message queue rescan to
+		 * possibly deliver another msg from the
+		 * hypervisor
+		 */
+		wrmsrl(HV_X64_MSR_EOM, 0);
+	}
+}
+
 /* General vmbus interface */
 
 struct hv_device *vmbus_device_create(const uuid_le *type,
diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c
index c8f1671..6cd12f1 100644
--- a/drivers/hv/vmbus_drv.c
+++ b/drivers/hv/vmbus_drv.c
@@ -709,25 +709,7 @@ static void hv_process_timer_expiration(struct hv_message *msg, int cpu)
 	if (dev->event_handler)
 		dev->event_handler(dev);
 
-	msg->header.message_type = HVMSG_NONE;
-
-	/*
-	 * Make sure the write to MessageType (ie set to
-	 * HVMSG_NONE) happens before we read the
-	 * MessagePending and EOMing. Otherwise, the EOMing
-	 * will not deliver any more messages since there is
-	 * no empty slot
-	 */
-	mb();
-
-	if (msg->header.message_flags.msg_pending) {
-		/*
-		 * This will cause message queue rescan to
-		 * possibly deliver another msg from the
-		 * hypervisor
-		 */
-		wrmsrl(HV_X64_MSR_EOM, 0);
-	}
+	vmbus_signal_eom(msg);
 }
 
 static void vmbus_on_msg_dpc(unsigned long data)
@@ -765,25 +747,7 @@ static void vmbus_on_msg_dpc(unsigned long data)
 		entry->message_handler(hdr);
 
 msg_handled:
-	msg->header.message_type = HVMSG_NONE;
-
-	/*
-	 * Make sure the write to MessageType (ie set to
-	 * HVMSG_NONE) happens before we read the
-	 * MessagePending and EOMing. Otherwise, the EOMing
-	 * will not deliver any more messages since there is
-	 * no empty slot
-	 */
-	mb();
-
-	if (msg->header.message_flags.msg_pending) {
-		/*
-		 * This will cause message queue rescan to
-		 * possibly deliver another msg from the
-		 * hypervisor
-		 */
-		wrmsrl(HV_X64_MSR_EOM, 0);
-	}
+	vmbus_signal_eom(msg);
 }
 
 static void vmbus_isr(void)
-- 
1.7.4.1

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 4/8] Drivers: hv: vmbus: avoid unneeded compiler optimizations in vmbus_wait_for_unload()
  2016-02-26 23:13 ` [PATCH 1/8] Drivers: hv: vmbus: don't loose HVMSG_TIMER_EXPIRED messages K. Y. Srinivasan
  2016-02-26 23:13   ` [PATCH 2/8] Drivers: hv: vmbus: avoid wait_for_completion() on crash K. Y. Srinivasan
  2016-02-26 23:13   ` [PATCH 3/8] Drivers: hv: vmbus: remove code duplication in message handling K. Y. Srinivasan
@ 2016-02-26 23:13   ` K. Y. Srinivasan
  2016-02-26 23:13   ` [PATCH 5/8] Drivers: hv: util: Pass the channel information during the init call K. Y. Srinivasan
                     ` (3 subsequent siblings)
  6 siblings, 0 replies; 9+ messages in thread
From: K. Y. Srinivasan @ 2016-02-26 23:13 UTC (permalink / raw)
  To: gregkh, linux-kernel, devel, olaf, apw, vkuznets, jasowang
  Cc: K. Y. Srinivasan

From: Vitaly Kuznetsov <vkuznets@redhat.com>

Message header is modified by the hypervisor and we read it in a loop,
we need to prevent compilers from optimizing accesses. There are no such
optimizations at this moment, this is just a future proof.

Suggested-by: Radim Krcmar <rkrcmar@redhat.com>
Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com>
Reviewed-by: Radim Kr.má<rkrcmar@redhat.com>
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
---
 drivers/hv/channel_mgmt.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c
index 73a17be..38b682ba 100644
--- a/drivers/hv/channel_mgmt.c
+++ b/drivers/hv/channel_mgmt.c
@@ -605,7 +605,7 @@ static void vmbus_wait_for_unload(void)
 	bool unloaded = false;
 
 	while (1) {
-		if (msg->header.message_type == HVMSG_NONE) {
+		if (READ_ONCE(msg->header.message_type) == HVMSG_NONE) {
 			mdelay(10);
 			continue;
 		}
-- 
1.7.4.1

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 5/8] Drivers: hv: util: Pass the channel information during the init call
  2016-02-26 23:13 ` [PATCH 1/8] Drivers: hv: vmbus: don't loose HVMSG_TIMER_EXPIRED messages K. Y. Srinivasan
                     ` (2 preceding siblings ...)
  2016-02-26 23:13   ` [PATCH 4/8] Drivers: hv: vmbus: avoid unneeded compiler optimizations in vmbus_wait_for_unload() K. Y. Srinivasan
@ 2016-02-26 23:13   ` K. Y. Srinivasan
  2016-02-26 23:13   ` [PATCH 6/8] Drivers: hv: utils: Remove util transport handler from list if registration fails K. Y. Srinivasan
                     ` (2 subsequent siblings)
  6 siblings, 0 replies; 9+ messages in thread
From: K. Y. Srinivasan @ 2016-02-26 23:13 UTC (permalink / raw)
  To: gregkh, linux-kernel, devel, olaf, apw, vkuznets, jasowang
  Cc: K. Y. Srinivasan

Pass the channel information to the util drivers that need to defer
reading the channel while they are processing a request. This would address
the following issue reported by Vitaly:

Commit 3cace4a61610 ("Drivers: hv: utils: run polling callback always in
interrupt context") removed direct *_transaction.state = HVUTIL_READY
assignments from *_handle_handshake() functions introducing the following
race: if a userspace daemon connects before we get first non-negotiation
request from the server hv_poll_channel() won't set transaction state to
HVUTIL_READY as (!channel) condition will fail, we set it to non-NULL on
the first real request from the server.

Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Reported-by: Vitaly Kuznetsov <vkuznets@redhat.com>
---
 drivers/hv/hv_fcopy.c    |    2 +-
 drivers/hv/hv_kvp.c      |    2 +-
 drivers/hv/hv_snapshot.c |    2 +-
 drivers/hv/hv_util.c     |    1 +
 include/linux/hyperv.h   |    1 +
 5 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/drivers/hv/hv_fcopy.c b/drivers/hv/hv_fcopy.c
index c37a71e..23c7079 100644
--- a/drivers/hv/hv_fcopy.c
+++ b/drivers/hv/hv_fcopy.c
@@ -251,7 +251,6 @@ void hv_fcopy_onchannelcallback(void *context)
 		 */
 
 		fcopy_transaction.recv_len = recvlen;
-		fcopy_transaction.recv_channel = channel;
 		fcopy_transaction.recv_req_id = requestid;
 		fcopy_transaction.fcopy_msg = fcopy_msg;
 
@@ -317,6 +316,7 @@ static void fcopy_on_reset(void)
 int hv_fcopy_init(struct hv_util_service *srv)
 {
 	recv_buffer = srv->recv_buffer;
+	fcopy_transaction.recv_channel = srv->channel;
 
 	/*
 	 * When this driver loads, the user level daemon that
diff --git a/drivers/hv/hv_kvp.c b/drivers/hv/hv_kvp.c
index d4ab81b..9b9b370 100644
--- a/drivers/hv/hv_kvp.c
+++ b/drivers/hv/hv_kvp.c
@@ -639,7 +639,6 @@ void hv_kvp_onchannelcallback(void *context)
 			 */
 
 			kvp_transaction.recv_len = recvlen;
-			kvp_transaction.recv_channel = channel;
 			kvp_transaction.recv_req_id = requestid;
 			kvp_transaction.kvp_msg = kvp_msg;
 
@@ -688,6 +687,7 @@ int
 hv_kvp_init(struct hv_util_service *srv)
 {
 	recv_buffer = srv->recv_buffer;
+	kvp_transaction.recv_channel = srv->channel;
 
 	/*
 	 * When this driver loads, the user level daemon that
diff --git a/drivers/hv/hv_snapshot.c b/drivers/hv/hv_snapshot.c
index 67def4a..3fba14e 100644
--- a/drivers/hv/hv_snapshot.c
+++ b/drivers/hv/hv_snapshot.c
@@ -263,7 +263,6 @@ void hv_vss_onchannelcallback(void *context)
 			 */
 
 			vss_transaction.recv_len = recvlen;
-			vss_transaction.recv_channel = channel;
 			vss_transaction.recv_req_id = requestid;
 			vss_transaction.msg = (struct hv_vss_msg *)vss_msg;
 
@@ -337,6 +336,7 @@ hv_vss_init(struct hv_util_service *srv)
 		return -ENOTSUPP;
 	}
 	recv_buffer = srv->recv_buffer;
+	vss_transaction.recv_channel = srv->channel;
 
 	/*
 	 * When this driver loads, the user level daemon that
diff --git a/drivers/hv/hv_util.c b/drivers/hv/hv_util.c
index 7994ec2..d5acaa2 100644
--- a/drivers/hv/hv_util.c
+++ b/drivers/hv/hv_util.c
@@ -322,6 +322,7 @@ static int util_probe(struct hv_device *dev,
 	srv->recv_buffer = kmalloc(PAGE_SIZE * 4, GFP_KERNEL);
 	if (!srv->recv_buffer)
 		return -ENOMEM;
+	srv->channel = dev->channel;
 	if (srv->util_init) {
 		ret = srv->util_init(srv);
 		if (ret) {
diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h
index d23dab0..aa0fadc 100644
--- a/include/linux/hyperv.h
+++ b/include/linux/hyperv.h
@@ -1251,6 +1251,7 @@ u64 hv_do_hypercall(u64 control, void *input, void *output);
 
 struct hv_util_service {
 	u8 *recv_buffer;
+	void *channel;
 	void (*util_cb)(void *);
 	int (*util_init)(struct hv_util_service *);
 	void (*util_deinit)(void);
-- 
1.7.4.1

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 6/8] Drivers: hv: utils: Remove util transport handler from list if registration fails
  2016-02-26 23:13 ` [PATCH 1/8] Drivers: hv: vmbus: don't loose HVMSG_TIMER_EXPIRED messages K. Y. Srinivasan
                     ` (3 preceding siblings ...)
  2016-02-26 23:13   ` [PATCH 5/8] Drivers: hv: util: Pass the channel information during the init call K. Y. Srinivasan
@ 2016-02-26 23:13   ` K. Y. Srinivasan
  2016-02-26 23:13   ` [PATCH 7/8] Drivers: hv: vmbus: Support handling messages on multiple CPUs K. Y. Srinivasan
  2016-02-26 23:13   ` [PATCH 8/8] Drivers: hv: vmbus: Support kexec on ws2012 r2 and above K. Y. Srinivasan
  6 siblings, 0 replies; 9+ messages in thread
From: K. Y. Srinivasan @ 2016-02-26 23:13 UTC (permalink / raw)
  To: gregkh, linux-kernel, devel, olaf, apw, vkuznets, jasowang
  Cc: Alex Ng, K. Y. Srinivasan

From: Alex Ng <alexng@microsoft.com>

If util transport fails to initialize for any reason, the list of transport
handlers may become corrupted due to freeing the transport handler without
removing it from the list. Fix this by cleaning it up from the list.

Signed-off-by: Alex Ng <alexng@microsoft.com>
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
---
 drivers/hv/hv_utils_transport.c |    3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)

diff --git a/drivers/hv/hv_utils_transport.c b/drivers/hv/hv_utils_transport.c
index 4f42c0e..9a9983f 100644
--- a/drivers/hv/hv_utils_transport.c
+++ b/drivers/hv/hv_utils_transport.c
@@ -310,6 +310,9 @@ struct hvutil_transport *hvutil_transport_init(const char *name,
 	return hvt;
 
 err_free_hvt:
+	spin_lock(&hvt_list_lock);
+	list_del(&hvt->list);
+	spin_unlock(&hvt_list_lock);
 	kfree(hvt);
 	return NULL;
 }
-- 
1.7.4.1

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 7/8] Drivers: hv: vmbus: Support handling messages on multiple CPUs
  2016-02-26 23:13 ` [PATCH 1/8] Drivers: hv: vmbus: don't loose HVMSG_TIMER_EXPIRED messages K. Y. Srinivasan
                     ` (4 preceding siblings ...)
  2016-02-26 23:13   ` [PATCH 6/8] Drivers: hv: utils: Remove util transport handler from list if registration fails K. Y. Srinivasan
@ 2016-02-26 23:13   ` K. Y. Srinivasan
  2016-02-26 23:13   ` [PATCH 8/8] Drivers: hv: vmbus: Support kexec on ws2012 r2 and above K. Y. Srinivasan
  6 siblings, 0 replies; 9+ messages in thread
From: K. Y. Srinivasan @ 2016-02-26 23:13 UTC (permalink / raw)
  To: gregkh, linux-kernel, devel, olaf, apw, vkuznets, jasowang
  Cc: K. Y. Srinivasan

Starting with Windows 2012 R2, message inteerupts can be delivered
on any VCPU in the guest. Support this functionality.

Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
---
 drivers/hv/hv.c           |   10 ++++++++++
 drivers/hv/hyperv_vmbus.h |    4 +++-
 drivers/hv/vmbus_drv.c    |   10 ++++------
 3 files changed, 17 insertions(+), 7 deletions(-)

diff --git a/drivers/hv/hv.c b/drivers/hv/hv.c
index ccb335f..a1c086b 100644
--- a/drivers/hv/hv.c
+++ b/drivers/hv/hv.c
@@ -204,6 +204,8 @@ int hv_init(void)
 	       sizeof(int) * NR_CPUS);
 	memset(hv_context.event_dpc, 0,
 	       sizeof(void *) * NR_CPUS);
+	memset(hv_context.msg_dpc, 0,
+	       sizeof(void *) * NR_CPUS);
 	memset(hv_context.clk_evt, 0,
 	       sizeof(void *) * NR_CPUS);
 
@@ -415,6 +417,13 @@ int hv_synic_alloc(void)
 		}
 		tasklet_init(hv_context.event_dpc[cpu], vmbus_on_event, cpu);
 
+		hv_context.msg_dpc[cpu] = kmalloc(size, GFP_ATOMIC);
+		if (hv_context.msg_dpc[cpu] == NULL) {
+			pr_err("Unable to allocate event dpc\n");
+			goto err;
+		}
+		tasklet_init(hv_context.msg_dpc[cpu], vmbus_on_msg_dpc, cpu);
+
 		hv_context.clk_evt[cpu] = kzalloc(ced_size, GFP_ATOMIC);
 		if (hv_context.clk_evt[cpu] == NULL) {
 			pr_err("Unable to allocate clock event device\n");
@@ -456,6 +465,7 @@ err:
 static void hv_synic_free_cpu(int cpu)
 {
 	kfree(hv_context.event_dpc[cpu]);
+	kfree(hv_context.msg_dpc[cpu]);
 	kfree(hv_context.clk_evt[cpu]);
 	if (hv_context.synic_event_page[cpu])
 		free_page((unsigned long)hv_context.synic_event_page[cpu]);
diff --git a/drivers/hv/hyperv_vmbus.h b/drivers/hv/hyperv_vmbus.h
index cada56a..a64b176 100644
--- a/drivers/hv/hyperv_vmbus.h
+++ b/drivers/hv/hyperv_vmbus.h
@@ -449,10 +449,11 @@ struct hv_context {
 	u32 vp_index[NR_CPUS];
 	/*
 	 * Starting with win8, we can take channel interrupts on any CPU;
-	 * we will manage the tasklet that handles events on a per CPU
+	 * we will manage the tasklet that handles events messages on a per CPU
 	 * basis.
 	 */
 	struct tasklet_struct *event_dpc[NR_CPUS];
+	struct tasklet_struct *msg_dpc[NR_CPUS];
 	/*
 	 * To optimize the mapping of relid to channel, maintain
 	 * per-cpu list of the channels based on their CPU affinity.
@@ -675,6 +676,7 @@ int vmbus_post_msg(void *buffer, size_t buflen);
 void vmbus_set_event(struct vmbus_channel *channel);
 
 void vmbus_on_event(unsigned long data);
+void vmbus_on_msg_dpc(unsigned long data);
 
 int hv_kvp_init(struct hv_util_service *);
 void hv_kvp_deinit(void);
diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c
index 6cd12f1..64713ff 100644
--- a/drivers/hv/vmbus_drv.c
+++ b/drivers/hv/vmbus_drv.c
@@ -45,7 +45,6 @@
 
 static struct acpi_device  *hv_acpi_dev;
 
-static struct tasklet_struct msg_dpc;
 static struct completion probe_event;
 
 
@@ -712,7 +711,7 @@ static void hv_process_timer_expiration(struct hv_message *msg, int cpu)
 	vmbus_signal_eom(msg);
 }
 
-static void vmbus_on_msg_dpc(unsigned long data)
+void vmbus_on_msg_dpc(unsigned long data)
 {
 	int cpu = smp_processor_id();
 	void *page_addr = hv_context.synic_message_page[cpu];
@@ -800,7 +799,7 @@ static void vmbus_isr(void)
 		if (msg->header.message_type == HVMSG_TIMER_EXPIRED)
 			hv_process_timer_expiration(msg, cpu);
 		else
-			tasklet_schedule(&msg_dpc);
+			tasklet_schedule(hv_context.msg_dpc[cpu]);
 	}
 }
 
@@ -824,8 +823,6 @@ static int vmbus_bus_init(void)
 		return ret;
 	}
 
-	tasklet_init(&msg_dpc, vmbus_on_msg_dpc, 0);
-
 	ret = bus_register(&hv_bus);
 	if (ret)
 		goto err_cleanup;
@@ -1321,7 +1318,8 @@ static void __exit vmbus_exit(void)
 	hv_synic_clockevents_cleanup();
 	vmbus_disconnect();
 	hv_remove_vmbus_irq();
-	tasklet_kill(&msg_dpc);
+	for_each_online_cpu(cpu)
+		tasklet_kill(hv_context.msg_dpc[cpu]);
 	vmbus_free_channels();
 	if (ms_hyperv.misc_features & HV_FEATURE_GUEST_CRASH_MSR_AVAILABLE) {
 		unregister_die_notifier(&hyperv_die_block);
-- 
1.7.4.1

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 8/8] Drivers: hv: vmbus: Support kexec on ws2012 r2 and above
  2016-02-26 23:13 ` [PATCH 1/8] Drivers: hv: vmbus: don't loose HVMSG_TIMER_EXPIRED messages K. Y. Srinivasan
                     ` (5 preceding siblings ...)
  2016-02-26 23:13   ` [PATCH 7/8] Drivers: hv: vmbus: Support handling messages on multiple CPUs K. Y. Srinivasan
@ 2016-02-26 23:13   ` K. Y. Srinivasan
  6 siblings, 0 replies; 9+ messages in thread
From: K. Y. Srinivasan @ 2016-02-26 23:13 UTC (permalink / raw)
  To: gregkh, linux-kernel, devel, olaf, apw, vkuznets, jasowang
  Cc: Alex Ng, K. Y. Srinivasan

From: Alex Ng <alexng@microsoft.com>

WS2012 R2 and above hosts can support kexec in that thay can support
reconnecting to the host (as would be needed in the kexec path)
on any CPU. Enable this. Pre ws2012 r2 hosts don't have this ability
and consequently cannot support kexec.

Signed-off-by: Alex Ng <alexng@microsoft.com>
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
---
 drivers/hv/connection.c |   10 +++++++++-
 1 files changed, 9 insertions(+), 1 deletions(-)

diff --git a/drivers/hv/connection.c b/drivers/hv/connection.c
index 3b6dc00..d02f137 100644
--- a/drivers/hv/connection.c
+++ b/drivers/hv/connection.c
@@ -88,8 +88,16 @@ static int vmbus_negotiate_version(struct vmbus_channel_msginfo *msginfo,
 	 * This has been the behavior pre-win8. This is not
 	 * perf issue and having all channel messages delivered on CPU 0
 	 * would be ok.
+	 * 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.
 	 */
-	msg->target_vcpu = 0;
+	if (version >= VERSION_WIN8_1) {
+		msg->target_vcpu = hv_context.vp_index[get_cpu()];
+		put_cpu();
+	} else {
+		msg->target_vcpu = 0;
+	}
 
 	/*
 	 * Add to list before we send the request since we may
-- 
1.7.4.1

^ permalink raw reply related	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2016-02-26 21:35 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-02-26 23:13 [PATCH 0/8] Drivers: hv: Miscellaneous fixes K. Y. Srinivasan
2016-02-26 23:13 ` [PATCH 1/8] Drivers: hv: vmbus: don't loose HVMSG_TIMER_EXPIRED messages K. Y. Srinivasan
2016-02-26 23:13   ` [PATCH 2/8] Drivers: hv: vmbus: avoid wait_for_completion() on crash K. Y. Srinivasan
2016-02-26 23:13   ` [PATCH 3/8] Drivers: hv: vmbus: remove code duplication in message handling K. Y. Srinivasan
2016-02-26 23:13   ` [PATCH 4/8] Drivers: hv: vmbus: avoid unneeded compiler optimizations in vmbus_wait_for_unload() K. Y. Srinivasan
2016-02-26 23:13   ` [PATCH 5/8] Drivers: hv: util: Pass the channel information during the init call K. Y. Srinivasan
2016-02-26 23:13   ` [PATCH 6/8] Drivers: hv: utils: Remove util transport handler from list if registration fails K. Y. Srinivasan
2016-02-26 23:13   ` [PATCH 7/8] Drivers: hv: vmbus: Support handling messages on multiple CPUs K. Y. Srinivasan
2016-02-26 23:13   ` [PATCH 8/8] Drivers: hv: vmbus: Support kexec on ws2012 r2 and above K. Y. Srinivasan

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).