Staging: hv: coding style cleanups for VmbusApi.h
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / staging / hv / Vmbus.c
CommitLineData
3e7ee490
HJ
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
5654e932 24#include <linux/kernel.h>
0ffa63b0 25#include <linux/mm.h>
4983b39a 26#include "osd.h"
09d50ff8 27#include "include/logging.h"
3e7ee490
HJ
28#include "VersionInfo.h"
29#include "VmbusPrivate.h"
30
454f18a9
BP
31
32/* Globals */
33
3e7ee490
HJ
34static const char* gDriverName="vmbus";
35
454f18a9
BP
36/* Windows vmbus does not defined this.
37 * We defined this to be consistent with other devices
38 */
39/* {c5295816-f63a-4d5f-8d1a-4daf999ca185} */
caf26a31
GKH
40static const struct hv_guid gVmbusDeviceType = {
41 .data = {
42 0x16, 0x58, 0x29, 0xc5, 0x3a, 0xf6, 0x5f, 0x4d,
43 0x8d, 0x1a, 0x4d, 0xaf, 0x99, 0x9c, 0xa1, 0x85
44 }
3e7ee490
HJ
45};
46
454f18a9 47/* {ac3760fc-9adf-40aa-9427-a70ed6de95c5} */
caf26a31
GKH
48static const struct hv_guid gVmbusDeviceId = {
49 .data = {
50 0xfc, 0x60, 0x37, 0xac, 0xdf, 0x9a, 0xaa, 0x40,
51 0x94, 0x27, 0xa7, 0x0e, 0xd6, 0xde, 0x95, 0xc5
52 }
3e7ee490
HJ
53};
54
775ef25e 55static struct hv_driver *gDriver; /* vmbus driver object */
3d3b5518 56static struct hv_device* gDevice; /* vmbus root device */
454f18a9
BP
57
58
3e7ee490 59
454f18a9 60/* Internal routines */
3e7ee490 61
3e7ee490
HJ
62
63static void
64VmbusGetChannelInterface(
65 VMBUS_CHANNEL_INTERFACE *Interface
66 );
67
68static void
69VmbusGetChannelInfo(
3d3b5518 70 struct hv_device *DeviceObject,
3e7ee490
HJ
71 DEVICE_INFO *DeviceInfo
72 );
73
74static void
75VmbusGetChannelOffers(
76 void
77 );
78
79static int
80VmbusOnDeviceAdd(
3d3b5518 81 struct hv_device *Device,
3e7ee490
HJ
82 void *AdditionalInfo
83 );
84
85static int
86VmbusOnDeviceRemove(
3d3b5518 87 struct hv_device *dev
3e7ee490
HJ
88 );
89
90static void
91VmbusOnCleanup(
775ef25e 92 struct hv_driver *drv
3e7ee490
HJ
93 );
94
95static int
96VmbusOnISR(
775ef25e 97 struct hv_driver *drv
3e7ee490
HJ
98 );
99
100static void
101VmbusOnMsgDPC(
775ef25e 102 struct hv_driver *drv
3e7ee490
HJ
103 );
104
105static void
106VmbusOnEventDPC(
775ef25e 107 struct hv_driver *drv
3e7ee490
HJ
108 );
109
110/*++;
111
112Name:
113 VmbusInitialize()
114
115Description:
116 Main entry point
117
118--*/
119int
120VmbusInitialize(
775ef25e 121 struct hv_driver *drv
3e7ee490
HJ
122 )
123{
124 VMBUS_DRIVER_OBJECT* driver = (VMBUS_DRIVER_OBJECT*)drv;
125 int ret=0;
126
127 DPRINT_ENTER(VMBUS);
128
129 DPRINT_INFO(VMBUS, "+++++++ Build Date=%s %s +++++++", VersionDate, VersionTime);
130 DPRINT_INFO(VMBUS, "+++++++ Build Description=%s +++++++", VersionDesc);
131
132 DPRINT_INFO(VMBUS, "+++++++ Vmbus supported version = %d +++++++", VMBUS_REVISION_NUMBER);
133 DPRINT_INFO(VMBUS, "+++++++ Vmbus using SINT %d +++++++", VMBUS_MESSAGE_SINT);
134
b7d7ae6f 135 DPRINT_DBG(VMBUS, "sizeof(VMBUS_CHANNEL_PACKET_PAGE_BUFFER)=%zd, sizeof(VMBUS_CHANNEL_PACKET_MULITPAGE_BUFFER)=%zd",
3fcc523a 136 sizeof(struct VMBUS_CHANNEL_PACKET_PAGE_BUFFER), sizeof(struct VMBUS_CHANNEL_PACKET_MULITPAGE_BUFFER));
3e7ee490
HJ
137
138 drv->name = gDriverName;
caf26a31 139 memcpy(&drv->deviceType, &gVmbusDeviceType, sizeof(struct hv_guid));
3e7ee490 140
454f18a9 141 /* Setup dispatch table */
3e7ee490
HJ
142 driver->Base.OnDeviceAdd = VmbusOnDeviceAdd;
143 driver->Base.OnDeviceRemove = VmbusOnDeviceRemove;
144 driver->Base.OnCleanup = VmbusOnCleanup;
145 driver->OnIsr = VmbusOnISR;
146 driver->OnMsgDpc = VmbusOnMsgDPC;
147 driver->OnEventDpc = VmbusOnEventDPC;
148 driver->GetChannelOffers = VmbusGetChannelOffers;
149 driver->GetChannelInterface = VmbusGetChannelInterface;
150 driver->GetChannelInfo = VmbusGetChannelInfo;
151
454f18a9 152 /* Hypervisor initialization...setup hypercall page..etc */
3e7ee490
HJ
153 ret = HvInit();
154 if (ret != 0)
155 {
156 DPRINT_ERR(VMBUS, "Unable to initialize the hypervisor - 0x%x", ret);
157 }
158
159 gDriver = drv;
160
161 DPRINT_EXIT(VMBUS);
162
163 return ret;
164}
165
166
167/*++;
168
169Name:
170 VmbusGetChannelOffers()
171
172Description:
173 Retrieve the channel offers from the parent partition
174
175--*/
176
177static void
178VmbusGetChannelOffers(void)
179{
180 DPRINT_ENTER(VMBUS);
181 VmbusChannelRequestOffers();
182 DPRINT_EXIT(VMBUS);
183}
184
185
186/*++;
187
188Name:
189 VmbusGetChannelInterface()
190
191Description:
192 Get the channel interface
193
194--*/
195static void
196VmbusGetChannelInterface(
197 VMBUS_CHANNEL_INTERFACE *Interface
198 )
199{
200 GetChannelInterface(Interface);
201}
202
203
204/*++;
205
206Name:
207 VmbusGetChannelInterface()
208
209Description:
210 Get the device info for the specified device object
211
212--*/
213static void
214VmbusGetChannelInfo(
3d3b5518 215 struct hv_device *DeviceObject,
3e7ee490
HJ
216 DEVICE_INFO *DeviceInfo
217 )
218{
219 GetChannelInfo(DeviceObject, DeviceInfo);
220}
221
222
223
224/*++
225
226Name:
227 VmbusCreateChildDevice()
228
229Description:
230 Creates the child device on the bus that represents the channel offer
231
232--*/
233
daaa8cc3
GKH
234struct hv_device *VmbusChildDeviceCreate(struct hv_guid *DeviceType,
235 struct hv_guid *DeviceInstance,
f346fdc2 236 void *Context)
3e7ee490
HJ
237{
238 VMBUS_DRIVER_OBJECT* vmbusDriver = (VMBUS_DRIVER_OBJECT*)gDriver;
239
240 return vmbusDriver->OnChildDeviceCreate(
241 DeviceType,
242 DeviceInstance,
243 Context);
244}
245
246
247/*++
248
249Name:
250 VmbusChildDeviceAdd()
251
252Description:
253 Registers the child device with the vmbus
254
255--*/
f346fdc2 256int VmbusChildDeviceAdd(struct hv_device *ChildDevice)
3e7ee490
HJ
257{
258 VMBUS_DRIVER_OBJECT* vmbusDriver = (VMBUS_DRIVER_OBJECT*)gDriver;
259
260 return vmbusDriver->OnChildDeviceAdd(gDevice, ChildDevice);
261}
262
263
264/*++
265
266Name:
267 VmbusChildDeviceRemove()
268
269Description:
270 Unregisters the child device from the vmbus
271
272--*/
f346fdc2 273void VmbusChildDeviceRemove(struct hv_device *ChildDevice)
3e7ee490
HJ
274{
275 VMBUS_DRIVER_OBJECT* vmbusDriver = (VMBUS_DRIVER_OBJECT*)gDriver;
276
277 vmbusDriver->OnChildDeviceRemove(ChildDevice);
278}
279
280/*++
281
282Name:
283 VmbusChildDeviceDestroy()
284
285Description:
286 Release the child device from the vmbus
287
288--*/
454f18a9
BP
289
290/* **************
291void
292VmbusChildDeviceDestroy(
3d3b5518 293struct hv_device *ChildDevice
454f18a9
BP
294)
295{
296VMBUS_DRIVER_OBJECT* vmbusDriver = (VMBUS_DRIVER_OBJECT*)gDriver;
297
298vmbusDriver->OnChildDeviceDestroy(ChildDevice);
299}
300************* */
3e7ee490
HJ
301
302/*++
303
304Name:
305 VmbusOnDeviceAdd()
306
307Description:
308 Callback when the root bus device is added
309
310--*/
311static int
312VmbusOnDeviceAdd(
3d3b5518 313 struct hv_device *dev,
3e7ee490
HJ
314 void *AdditionalInfo
315 )
316{
4d643114 317 u32 *irqvector = (u32*) AdditionalInfo;
3e7ee490
HJ
318 int ret=0;
319
320 DPRINT_ENTER(VMBUS);
321
322 gDevice = dev;
323
caf26a31
GKH
324 memcpy(&gDevice->deviceType, &gVmbusDeviceType, sizeof(struct hv_guid));
325 memcpy(&gDevice->deviceInstance, &gVmbusDeviceId, sizeof(struct hv_guid));
3e7ee490 326
454f18a9
BP
327 /* strcpy(dev->name, "vmbus"); */
328 /* SynIC setup... */
3e7ee490
HJ
329 ret = HvSynicInit(*irqvector);
330
454f18a9 331 /* Connect to VMBus in the root partition */
3e7ee490
HJ
332 ret = VmbusConnect();
333
454f18a9 334 /* VmbusSendEvent(device->localPortId+1); */
3e7ee490
HJ
335 DPRINT_EXIT(VMBUS);
336
337 return ret;
338}
339
340
341/*++
342
343Name:
344 VmbusOnDeviceRemove()
345
346Description:
347 Callback when the root bus device is removed
348
349--*/
bd1de709 350static int VmbusOnDeviceRemove(
3d3b5518 351 struct hv_device *dev
3e7ee490
HJ
352 )
353{
354 int ret=0;
355
356 DPRINT_ENTER(VMBUS);
357
358 VmbusChannelReleaseUnattachedChannels();
359
360 VmbusDisconnect();
361
362 HvSynicCleanup();
363
364 DPRINT_EXIT(VMBUS);
365
366 return ret;
367}
368
369
370/*++
371
372Name:
373 VmbusOnCleanup()
374
375Description:
376 Perform any cleanup when the driver is removed
377
378--*/
bd1de709 379static void
3e7ee490 380VmbusOnCleanup(
775ef25e 381 struct hv_driver *drv
3e7ee490
HJ
382 )
383{
454f18a9 384 /* VMBUS_DRIVER_OBJECT* driver = (VMBUS_DRIVER_OBJECT*)drv; */
3e7ee490
HJ
385
386 DPRINT_ENTER(VMBUS);
387
388 HvCleanup();
389
390 DPRINT_EXIT(VMBUS);
391}
392
393
394/*++
395
396Name:
397 VmbusOnMsgDPC()
398
399Description:
400 DPC routine to handle messages from the hypervisior
401
402--*/
bd1de709 403static void
3e7ee490 404VmbusOnMsgDPC(
775ef25e 405 struct hv_driver *drv
3e7ee490
HJ
406 )
407{
408 void *page_addr = gHvContext.synICMessagePage[0];
409
eacb1b4d
GKH
410 struct hv_message *msg = (struct hv_message *)page_addr + VMBUS_MESSAGE_SINT;
411 struct hv_message *copied;
3e7ee490
HJ
412 while (1)
413 {
454f18a9 414 if (msg->Header.MessageType == HvMessageTypeNone) /* no msg */
3e7ee490
HJ
415 {
416 break;
417 }
418 else
419 {
eacb1b4d 420 copied = kmalloc(sizeof(*copied), GFP_ATOMIC);
3e7ee490
HJ
421 if (copied == NULL)
422 {
423 continue;
424 }
425
eacb1b4d 426 memcpy(copied, msg, sizeof(*copied));
de65a384
BP
427 osd_schedule_callback(gVmbusConnection.WorkQueue,
428 VmbusOnChannelMessage,
429 (void *)copied);
3e7ee490
HJ
430 }
431
432 msg->Header.MessageType = HvMessageTypeNone;
433
454f18a9
BP
434 /*
435 * Make sure the write to MessageType (ie set to
436 * HvMessageTypeNone) happens before we read the
437 * MessagePending and EOMing. Otherwise, the EOMing
438 * will not deliver any more messages since there is
439 * no empty slot
440 */
28b6ca9c 441 mb();
3e7ee490
HJ
442
443 if (msg->Header.MessageFlags.MessagePending)
444 {
454f18a9
BP
445 /*
446 * This will cause message queue rescan to
447 * possibly deliver another msg from the
448 * hypervisor
449 */
a51ed7d6 450 wrmsrl(HV_X64_MSR_EOM, 0);
3e7ee490
HJ
451 }
452 }
453}
454
455/*++
456
457Name:
458 VmbusOnEventDPC()
459
460Description:
461 DPC routine to handle events from the hypervisior
462
463--*/
bd1de709 464static void
3e7ee490 465VmbusOnEventDPC(
775ef25e 466 struct hv_driver* drv
3e7ee490
HJ
467 )
468{
454f18a9 469 /* TODO: Process any events */
3e7ee490
HJ
470 VmbusOnEvents();
471}
472
473
474/*++
475
476Name:
477 VmbusOnISR()
478
479Description:
480 ISR routine
481
482--*/
bd1de709 483static int
3e7ee490 484VmbusOnISR(
775ef25e 485 struct hv_driver *drv
3e7ee490
HJ
486 )
487{
454f18a9 488 /* VMBUS_DRIVER_OBJECT* driver = (VMBUS_DRIVER_OBJECT*)drv; */
3e7ee490
HJ
489
490 int ret=0;
454f18a9 491 /* struct page* page; */
3e7ee490 492 void *page_addr;
eacb1b4d
GKH
493 struct hv_message *msg;
494 union hv_synic_event_flags *event;
3e7ee490 495
454f18a9
BP
496 /* page = SynICMessagePage[0]; */
497 /* page_addr = page_address(page); */
3e7ee490 498 page_addr = gHvContext.synICMessagePage[0];
eacb1b4d 499 msg = (struct hv_message *)page_addr + VMBUS_MESSAGE_SINT;
3e7ee490
HJ
500
501 DPRINT_ENTER(VMBUS);
502
454f18a9 503 /* Check if there are actual msgs to be process */
3e7ee490
HJ
504 if (msg->Header.MessageType != HvMessageTypeNone)
505 {
506 DPRINT_DBG(VMBUS, "received msg type %d size %d", msg->Header.MessageType, msg->Header.PayloadSize);
507 ret |= 0x1;
508 }
509
454f18a9 510 /* TODO: Check if there are events to be process */
3e7ee490 511 page_addr = gHvContext.synICEventPage[0];
eacb1b4d 512 event = (union hv_synic_event_flags *)page_addr + VMBUS_MESSAGE_SINT;
3e7ee490 513
454f18a9 514 /* Since we are a child, we only need to check bit 0 */
7c369f40 515 if (test_and_clear_bit(0, (unsigned long *) &event->Flags32[0]))
3e7ee490
HJ
516 {
517 DPRINT_DBG(VMBUS, "received event %d", event->Flags32[0]);
518 ret |= 0x2;
519 }
520
521 DPRINT_EXIT(VMBUS);
522 return ret;
523}
524
454f18a9 525/* eof */