]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blame - releases/3.16.7/drivers-hv-vmbus-cleanup-hv_post_message.patch
4.14-stable patches
[thirdparty/kernel/stable-queue.git] / releases / 3.16.7 / drivers-hv-vmbus-cleanup-hv_post_message.patch
CommitLineData
94bcd1f7
GKH
1From b29ef3546aecb253a5552b198cef23750d56e1e4 Mon Sep 17 00:00:00 2001
2From: "K. Y. Srinivasan" <kys@microsoft.com>
3Date: Thu, 28 Aug 2014 18:29:52 -0700
4Subject: Drivers: hv: vmbus: Cleanup hv_post_message()
5
6From: "K. Y. Srinivasan" <kys@microsoft.com>
7
8commit b29ef3546aecb253a5552b198cef23750d56e1e4 upstream.
9
10Minimize failures in this function by pre-allocating the buffer
11for posting messages. The hypercall for posting the message can fail
12for a number of reasons:
13
14 1. Transient resource related issues
15 2. Buffer alignment
16 3. Buffer cannot span a page boundry
17
18We address issues 2 and 3 by preallocating a per-cpu page for the buffer.
19Transient resource related failures are handled by retrying by the callers
20of this function.
21
22This patch is based on the investigation
23done by Dexuan Cui <decui@microsoft.com>.
24
25I would like to thank Sitsofe Wheeler <sitsofe@yahoo.com>
26for reporting the issue and helping in debuggging.
27
28Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
29Reported-by: Sitsofe Wheeler <sitsofe@yahoo.com>
30Tested-by: Sitsofe Wheeler <sitsofe@yahoo.com>
31Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
32
33---
34 drivers/hv/hv.c | 27 +++++++++++++++------------
35 drivers/hv/hyperv_vmbus.h | 4 ++++
36 2 files changed, 19 insertions(+), 12 deletions(-)
37
38--- a/drivers/hv/hv.c
39+++ b/drivers/hv/hv.c
40@@ -138,6 +138,8 @@ int hv_init(void)
41 memset(hv_context.synic_event_page, 0, sizeof(void *) * NR_CPUS);
42 memset(hv_context.synic_message_page, 0,
43 sizeof(void *) * NR_CPUS);
44+ memset(hv_context.post_msg_page, 0,
45+ sizeof(void *) * NR_CPUS);
46 memset(hv_context.vp_index, 0,
47 sizeof(int) * NR_CPUS);
48 memset(hv_context.event_dpc, 0,
49@@ -217,26 +219,18 @@ int hv_post_message(union hv_connection_
50 enum hv_message_type message_type,
51 void *payload, size_t payload_size)
52 {
53- struct aligned_input {
54- u64 alignment8;
55- struct hv_input_post_message msg;
56- };
57
58 struct hv_input_post_message *aligned_msg;
59 u16 status;
60- unsigned long addr;
61
62 if (payload_size > HV_MESSAGE_PAYLOAD_BYTE_COUNT)
63 return -EMSGSIZE;
64
65- addr = (unsigned long)kmalloc(sizeof(struct aligned_input), GFP_ATOMIC);
66- if (!addr)
67- return -ENOMEM;
68-
69 aligned_msg = (struct hv_input_post_message *)
70- (ALIGN(addr, HV_HYPERCALL_PARAM_ALIGN));
71+ hv_context.post_msg_page[get_cpu()];
72
73 aligned_msg->connectionid = connection_id;
74+ aligned_msg->reserved = 0;
75 aligned_msg->message_type = message_type;
76 aligned_msg->payload_size = payload_size;
77 memcpy((void *)aligned_msg->payload, payload, payload_size);
78@@ -244,8 +238,7 @@ int hv_post_message(union hv_connection_
79 status = do_hypercall(HVCALL_POST_MESSAGE, aligned_msg, NULL)
80 & 0xFFFF;
81
82- kfree((void *)addr);
83-
84+ put_cpu();
85 return status;
86 }
87
88@@ -294,6 +287,14 @@ int hv_synic_alloc(void)
89 pr_err("Unable to allocate SYNIC event page\n");
90 goto err;
91 }
92+
93+ hv_context.post_msg_page[cpu] =
94+ (void *)get_zeroed_page(GFP_ATOMIC);
95+
96+ if (hv_context.post_msg_page[cpu] == NULL) {
97+ pr_err("Unable to allocate post msg page\n");
98+ goto err;
99+ }
100 }
101
102 return 0;
103@@ -308,6 +309,8 @@ static void hv_synic_free_cpu(int cpu)
104 free_page((unsigned long)hv_context.synic_event_page[cpu]);
105 if (hv_context.synic_message_page[cpu])
106 free_page((unsigned long)hv_context.synic_message_page[cpu]);
107+ if (hv_context.post_msg_page[cpu])
108+ free_page((unsigned long)hv_context.post_msg_page[cpu]);
109 }
110
111 void hv_synic_free(void)
112--- a/drivers/hv/hyperv_vmbus.h
113+++ b/drivers/hv/hyperv_vmbus.h
114@@ -515,6 +515,10 @@ struct hv_context {
115 * per-cpu list of the channels based on their CPU affinity.
116 */
117 struct list_head percpu_list[NR_CPUS];
118+ /*
119+ * buffer to post messages to the host.
120+ */
121+ void *post_msg_page[NR_CPUS];
122 };
123
124 extern struct hv_context hv_context;