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