[Vivid][PATCH] UBUNTU: SAUCE: Drivers: hv: vmbus: Fix a Host signaling bug
Jay Vosburgh
jay.vosburgh at canonical.com
Thu Nov 19 23:46:47 UTC 2015
From: K. Y. Srinivasan <kys at microsoft.com>
BugLink: https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1508706
Currently we have two policies for deciding when to signal the host:
One based on the ring buffer state and the other based on what the
VMBUS client driver wants to do. Consider the case when the client
wants to explicitly control when to signal the host. In this case,
if the client were to defer signaling, we will not be able to signal
the host subsequently when the client does want to signal since the
ring buffer state will prevent the signaling. Implement logic to
have only one signaling policy in force for a given channel.
Signed-off-by: K. Y. Srinivasan <kys at microsoft.com>
Reviewed-by: Haiyang Zhang <haiyangz at microsoft.com>
Tested-by: Haiyang Zhang <haiyangz at microsoft.com>
Cc: <stable at vger.kernel.org> # v4.2+
Signed-off-by: Jay Vosburgh <jay.vosburgh at canonical.com>
---
drivers/hv/channel.c | 16 ++++++++++++++++
include/linux/hyperv.h | 12 ++++++++++++
2 files changed, 28 insertions(+)
diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c
index 053dd4cae445..e983d0c92c6c 100644
--- a/drivers/hv/channel.c
+++ b/drivers/hv/channel.c
@@ -602,6 +602,14 @@ int vmbus_sendpacket_ctl(struct vmbus_channel *channel, void *buffer,
ret = hv_ringbuffer_write(&channel->outbound, bufferlist, 3, &signal);
+ /* Based on the channel signal state, we will decide
+ * which signaling policy will be applied.
+ */
+ if (channel->signal_state)
+ signal = true;
+ else
+ kick_q = true;
+
if ((ret == 0) && kick_q && signal)
vmbus_setevent(channel);
@@ -693,6 +701,14 @@ int vmbus_sendpacket_pagebuffer_ctl(struct vmbus_channel *channel,
ret = hv_ringbuffer_write(&channel->outbound, bufferlist, 3, &signal);
+ /* Based on the channel signal state, we will decide
+ * which signaling policy will be applied.
+ */
+ if (channel->signal_state)
+ signal = true;
+ else
+ kick_q = true;
+
if ((ret == 0) && kick_q && signal)
vmbus_setevent(channel);
diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h
index 504b9ec36fe6..0f194ac40326 100644
--- a/include/linux/hyperv.h
+++ b/include/linux/hyperv.h
@@ -758,8 +758,20 @@ struct vmbus_channel {
* link up channels based on their CPU affinity.
*/
struct list_head percpu_list;
+ /*
+ * Host signaling policy: The default policy will be
+ * based on the ring buffer state. We will also support
+ * a policy where the client driver can have explicit
+ * signaling control.
+ */
+ bool signal_state;
};
+static inline void set_channel_signal_state(struct vmbus_channel *c, bool state)
+{
+ c->signal_state = state;
+}
+
static inline void set_channel_read_state(struct vmbus_channel *c, bool state)
{
c->batched_reading = state;
--
1.9.1
More information about the kernel-team
mailing list