3f8ce7be4c188120b399be0283a7589bd81ff76e
[profile/ivi/kernel-x86-ivi.git] / drivers / hv / connection.c
1 /*
2  *
3  * Copyright (c) 2009, Microsoft Corporation.
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms and conditions of the GNU General Public License,
7  * version 2, as published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
12  * more details.
13  *
14  * You should have received a copy of the GNU General Public License along with
15  * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
16  * Place - Suite 330, Boston, MA 02111-1307 USA.
17  *
18  * Authors:
19  *   Haiyang Zhang <haiyangz@microsoft.com>
20  *   Hank Janssen  <hjanssen@microsoft.com>
21  *
22  */
23 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
24
25 #include <linux/kernel.h>
26 #include <linux/sched.h>
27 #include <linux/wait.h>
28 #include <linux/delay.h>
29 #include <linux/mm.h>
30 #include <linux/slab.h>
31 #include <linux/vmalloc.h>
32 #include <linux/hyperv.h>
33 #include <linux/export.h>
34 #include <asm/hyperv.h>
35 #include "hyperv_vmbus.h"
36
37
38 struct vmbus_connection vmbus_connection = {
39         .conn_state             = DISCONNECTED,
40         .next_gpadl_handle      = ATOMIC_INIT(0xE1E10),
41 };
42
43 /*
44  * VMBUS version is 32 bit entity broken up into
45  * two 16 bit quantities: major_number. minor_number.
46  *
47  * 0 . 13 (Windows Server 2008)
48  * 1 . 1  (Windows 7)
49  * 2 . 4  (Windows 8)
50  */
51
52 #define VERSION_WS2008  ((0 << 16) | (13))
53 #define VERSION_WIN7    ((1 << 16) | (1))
54 #define VERSION_WIN8    ((2 << 16) | (4))
55
56 #define VERSION_INVAL -1
57
58 /*
59  * Negotiated protocol version with the host.
60  */
61 __u32 vmbus_proto_version;
62 EXPORT_SYMBOL_GPL(vmbus_proto_version);
63
64 static __u32 vmbus_get_next_version(__u32 current_version)
65 {
66         switch (current_version) {
67         case (VERSION_WIN7):
68                 return VERSION_WS2008;
69
70         case (VERSION_WIN8):
71                 return VERSION_WIN7;
72
73         case (VERSION_WS2008):
74         default:
75                 return VERSION_INVAL;
76         }
77 }
78
79 static int vmbus_negotiate_version(struct vmbus_channel_msginfo *msginfo,
80                                         __u32 version)
81 {
82         int ret = 0;
83         struct vmbus_channel_initiate_contact *msg;
84         unsigned long flags;
85         int t;
86
87         init_completion(&msginfo->waitevent);
88
89         msg = (struct vmbus_channel_initiate_contact *)msginfo->msg;
90
91         msg->header.msgtype = CHANNELMSG_INITIATE_CONTACT;
92         msg->vmbus_version_requested = version;
93         msg->interrupt_page = virt_to_phys(vmbus_connection.int_page);
94         msg->monitor_page1 = virt_to_phys(vmbus_connection.monitor_pages);
95         msg->monitor_page2 = virt_to_phys(
96                         (void *)((unsigned long)vmbus_connection.monitor_pages +
97                                  PAGE_SIZE));
98
99         /*
100          * Add to list before we send the request since we may
101          * receive the response before returning from this routine
102          */
103         spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
104         list_add_tail(&msginfo->msglistentry,
105                       &vmbus_connection.chn_msg_list);
106
107         spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
108
109         ret = vmbus_post_msg(msg,
110                                sizeof(struct vmbus_channel_initiate_contact));
111         if (ret != 0) {
112                 spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
113                 list_del(&msginfo->msglistentry);
114                 spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock,
115                                         flags);
116                 return ret;
117         }
118
119         /* Wait for the connection response */
120         t =  wait_for_completion_timeout(&msginfo->waitevent, 5*HZ);
121         if (t == 0) {
122                 spin_lock_irqsave(&vmbus_connection.channelmsg_lock,
123                                 flags);
124                 list_del(&msginfo->msglistentry);
125                 spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock,
126                                         flags);
127                 return -ETIMEDOUT;
128         }
129
130         spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
131         list_del(&msginfo->msglistentry);
132         spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
133
134         /* Check if successful */
135         if (msginfo->response.version_response.version_supported) {
136                 vmbus_connection.conn_state = CONNECTED;
137         } else {
138                 pr_err("Unable to connect, "
139                         "Version %d not supported by Hyper-V\n",
140                         version);
141                 return -ECONNREFUSED;
142         }
143
144         return ret;
145 }
146
147 /*
148  * vmbus_connect - Sends a connect request on the partition service connection
149  */
150 int vmbus_connect(void)
151 {
152         int ret = 0;
153         struct vmbus_channel_msginfo *msginfo = NULL;
154         __u32 version;
155
156         /* Initialize the vmbus connection */
157         vmbus_connection.conn_state = CONNECTING;
158         vmbus_connection.work_queue = create_workqueue("hv_vmbus_con");
159         if (!vmbus_connection.work_queue) {
160                 ret = -ENOMEM;
161                 goto cleanup;
162         }
163
164         INIT_LIST_HEAD(&vmbus_connection.chn_msg_list);
165         spin_lock_init(&vmbus_connection.channelmsg_lock);
166
167         INIT_LIST_HEAD(&vmbus_connection.chn_list);
168         spin_lock_init(&vmbus_connection.channel_lock);
169
170         /*
171          * Setup the vmbus event connection for channel interrupt
172          * abstraction stuff
173          */
174         vmbus_connection.int_page =
175         (void *)__get_free_pages(GFP_KERNEL|__GFP_ZERO, 0);
176         if (vmbus_connection.int_page == NULL) {
177                 ret = -ENOMEM;
178                 goto cleanup;
179         }
180
181         vmbus_connection.recv_int_page = vmbus_connection.int_page;
182         vmbus_connection.send_int_page =
183                 (void *)((unsigned long)vmbus_connection.int_page +
184                         (PAGE_SIZE >> 1));
185
186         /*
187          * Setup the monitor notification facility. The 1st page for
188          * parent->child and the 2nd page for child->parent
189          */
190         vmbus_connection.monitor_pages =
191         (void *)__get_free_pages((GFP_KERNEL|__GFP_ZERO), 1);
192         if (vmbus_connection.monitor_pages == NULL) {
193                 ret = -ENOMEM;
194                 goto cleanup;
195         }
196
197         msginfo = kzalloc(sizeof(*msginfo) +
198                           sizeof(struct vmbus_channel_initiate_contact),
199                           GFP_KERNEL);
200         if (msginfo == NULL) {
201                 ret = -ENOMEM;
202                 goto cleanup;
203         }
204
205         /*
206          * Negotiate a compatible VMBUS version number with the
207          * host. We start with the highest number we can support
208          * and work our way down until we negotiate a compatible
209          * version.
210          */
211
212         version = VERSION_WS2008;
213
214         do {
215                 ret = vmbus_negotiate_version(msginfo, version);
216                 if (ret == 0)
217                         break;
218
219                 version = vmbus_get_next_version(version);
220         } while (version != VERSION_INVAL);
221
222         if (version == VERSION_INVAL)
223                 goto cleanup;
224
225         vmbus_proto_version = version;
226         pr_info("Negotiated host information %d\n", version);
227         kfree(msginfo);
228         return 0;
229
230 cleanup:
231         vmbus_connection.conn_state = DISCONNECTED;
232
233         if (vmbus_connection.work_queue)
234                 destroy_workqueue(vmbus_connection.work_queue);
235
236         if (vmbus_connection.int_page) {
237                 free_pages((unsigned long)vmbus_connection.int_page, 0);
238                 vmbus_connection.int_page = NULL;
239         }
240
241         if (vmbus_connection.monitor_pages) {
242                 free_pages((unsigned long)vmbus_connection.monitor_pages, 1);
243                 vmbus_connection.monitor_pages = NULL;
244         }
245
246         kfree(msginfo);
247
248         return ret;
249 }
250
251
252 /*
253  * relid2channel - Get the channel object given its
254  * child relative id (ie channel id)
255  */
256 struct vmbus_channel *relid2channel(u32 relid)
257 {
258         struct vmbus_channel *channel;
259         struct vmbus_channel *found_channel  = NULL;
260         unsigned long flags;
261
262         spin_lock_irqsave(&vmbus_connection.channel_lock, flags);
263         list_for_each_entry(channel, &vmbus_connection.chn_list, listentry) {
264                 if (channel->offermsg.child_relid == relid) {
265                         found_channel = channel;
266                         break;
267                 }
268         }
269         spin_unlock_irqrestore(&vmbus_connection.channel_lock, flags);
270
271         return found_channel;
272 }
273
274 /*
275  * process_chn_event - Process a channel event notification
276  */
277 static void process_chn_event(u32 relid)
278 {
279         struct vmbus_channel *channel;
280         unsigned long flags;
281         void *arg;
282         bool read_state;
283         u32 bytes_to_read;
284
285         /*
286          * Find the channel based on this relid and invokes the
287          * channel callback to process the event
288          */
289         channel = relid2channel(relid);
290
291         if (!channel) {
292                 pr_err("channel not found for relid - %u\n", relid);
293                 return;
294         }
295
296         /*
297          * A channel once created is persistent even when there
298          * is no driver handling the device. An unloading driver
299          * sets the onchannel_callback to NULL under the
300          * protection of the channel inbound_lock. Thus, checking
301          * and invoking the driver specific callback takes care of
302          * orderly unloading of the driver.
303          */
304
305         spin_lock_irqsave(&channel->inbound_lock, flags);
306         if (channel->onchannel_callback != NULL) {
307                 arg = channel->channel_callback_context;
308                 read_state = channel->batched_reading;
309                 /*
310                  * This callback reads the messages sent by the host.
311                  * We can optimize host to guest signaling by ensuring:
312                  * 1. While reading the channel, we disable interrupts from
313                  *    host.
314                  * 2. Ensure that we process all posted messages from the host
315                  *    before returning from this callback.
316                  * 3. Once we return, enable signaling from the host. Once this
317                  *    state is set we check to see if additional packets are
318                  *    available to read. In this case we repeat the process.
319                  */
320
321                 do {
322                         hv_begin_read(&channel->inbound);
323                         channel->onchannel_callback(arg);
324                         bytes_to_read = hv_end_read(&channel->inbound);
325                 } while (read_state && (bytes_to_read != 0));
326         } else {
327                 pr_err("no channel callback for relid - %u\n", relid);
328         }
329
330         spin_unlock_irqrestore(&channel->inbound_lock, flags);
331 }
332
333 /*
334  * vmbus_on_event - Handler for events
335  */
336 void vmbus_on_event(unsigned long data)
337 {
338         u32 dword;
339         u32 maxdword = MAX_NUM_CHANNELS_SUPPORTED >> 5;
340         int bit;
341         u32 relid;
342         u32 *recv_int_page = vmbus_connection.recv_int_page;
343
344         /* Check events */
345         if (!recv_int_page)
346                 return;
347         for (dword = 0; dword < maxdword; dword++) {
348                 if (!recv_int_page[dword])
349                         continue;
350                 for (bit = 0; bit < 32; bit++) {
351                         if (sync_test_and_clear_bit(bit,
352                                 (unsigned long *)&recv_int_page[dword])) {
353                                 relid = (dword << 5) + bit;
354
355                                 if (relid == 0)
356                                         /*
357                                          * Special case - vmbus
358                                          * channel protocol msg
359                                          */
360                                         continue;
361
362                                 process_chn_event(relid);
363                         }
364                 }
365         }
366 }
367
368 /*
369  * vmbus_post_msg - Send a msg on the vmbus's message connection
370  */
371 int vmbus_post_msg(void *buffer, size_t buflen)
372 {
373         union hv_connection_id conn_id;
374         int ret = 0;
375         int retries = 0;
376
377         conn_id.asu32 = 0;
378         conn_id.u.id = VMBUS_MESSAGE_CONNECTION_ID;
379
380         /*
381          * hv_post_message() can have transient failures because of
382          * insufficient resources. Retry the operation a couple of
383          * times before giving up.
384          */
385         while (retries < 3) {
386                 ret =  hv_post_message(conn_id, 1, buffer, buflen);
387                 if (ret != HV_STATUS_INSUFFICIENT_BUFFERS)
388                         return ret;
389                 retries++;
390                 msleep(100);
391         }
392         return ret;
393 }
394
395 /*
396  * vmbus_set_event - Send an event notification to the parent
397  */
398 int vmbus_set_event(u32 child_relid)
399 {
400         /* Each u32 represents 32 channels */
401         sync_set_bit(child_relid & 31,
402                 (unsigned long *)vmbus_connection.send_int_page +
403                 (child_relid >> 5));
404
405         return hv_signal_event(hv_context.signal_event_param);
406 }