Staging: hv: osd.h: fix GUID reference problem
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / drivers / staging / hv / Vmbus.c
blob58ed469c18c711f301a9f5b1436f17cd60deab51
1 /*
3 * Copyright (c) 2009, Microsoft Corporation.
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.
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.
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.
18 * Authors:
19 * Haiyang Zhang <haiyangz@microsoft.com>
20 * Hank Janssen <hjanssen@microsoft.com>
24 #include <linux/kernel.h>
25 #include <linux/mm.h>
26 #include "osd.h"
27 #include "include/logging.h"
28 #include "VersionInfo.h"
29 #include "VmbusPrivate.h"
32 /* Globals */
34 static const char* gDriverName="vmbus";
36 /* Windows vmbus does not defined this.
37 * We defined this to be consistent with other devices
39 /* {c5295816-f63a-4d5f-8d1a-4daf999ca185} */
40 static 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
47 /* {ac3760fc-9adf-40aa-9427-a70ed6de95c5} */
48 static 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
55 static struct hv_driver *gDriver; /* vmbus driver object */
56 static struct hv_device* gDevice; /* vmbus root device */
60 /* Internal routines */
63 static void
64 VmbusGetChannelInterface(
65 VMBUS_CHANNEL_INTERFACE *Interface
68 static void
69 VmbusGetChannelInfo(
70 struct hv_device *DeviceObject,
71 DEVICE_INFO *DeviceInfo
74 static void
75 VmbusGetChannelOffers(
76 void
79 static int
80 VmbusOnDeviceAdd(
81 struct hv_device *Device,
82 void *AdditionalInfo
85 static int
86 VmbusOnDeviceRemove(
87 struct hv_device *dev
90 static void
91 VmbusOnCleanup(
92 struct hv_driver *drv
95 static int
96 VmbusOnISR(
97 struct hv_driver *drv
100 static void
101 VmbusOnMsgDPC(
102 struct hv_driver *drv
105 static void
106 VmbusOnEventDPC(
107 struct hv_driver *drv
110 /*++;
112 Name:
113 VmbusInitialize()
115 Description:
116 Main entry point
118 --*/
120 VmbusInitialize(
121 struct hv_driver *drv
124 VMBUS_DRIVER_OBJECT* driver = (VMBUS_DRIVER_OBJECT*)drv;
125 int ret=0;
127 DPRINT_ENTER(VMBUS);
129 DPRINT_INFO(VMBUS, "+++++++ Build Date=%s %s +++++++", VersionDate, VersionTime);
130 DPRINT_INFO(VMBUS, "+++++++ Build Description=%s +++++++", VersionDesc);
132 DPRINT_INFO(VMBUS, "+++++++ Vmbus supported version = %d +++++++", VMBUS_REVISION_NUMBER);
133 DPRINT_INFO(VMBUS, "+++++++ Vmbus using SINT %d +++++++", VMBUS_MESSAGE_SINT);
135 DPRINT_DBG(VMBUS, "sizeof(VMBUS_CHANNEL_PACKET_PAGE_BUFFER)=%zd, sizeof(VMBUS_CHANNEL_PACKET_MULITPAGE_BUFFER)=%zd",
136 sizeof(struct VMBUS_CHANNEL_PACKET_PAGE_BUFFER), sizeof(struct VMBUS_CHANNEL_PACKET_MULITPAGE_BUFFER));
138 drv->name = gDriverName;
139 memcpy(&drv->deviceType, &gVmbusDeviceType, sizeof(struct hv_guid));
141 /* Setup dispatch table */
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;
152 /* Hypervisor initialization...setup hypercall page..etc */
153 ret = HvInit();
154 if (ret != 0)
156 DPRINT_ERR(VMBUS, "Unable to initialize the hypervisor - 0x%x", ret);
159 gDriver = drv;
161 DPRINT_EXIT(VMBUS);
163 return ret;
167 /*++;
169 Name:
170 VmbusGetChannelOffers()
172 Description:
173 Retrieve the channel offers from the parent partition
175 --*/
177 static void
178 VmbusGetChannelOffers(void)
180 DPRINT_ENTER(VMBUS);
181 VmbusChannelRequestOffers();
182 DPRINT_EXIT(VMBUS);
186 /*++;
188 Name:
189 VmbusGetChannelInterface()
191 Description:
192 Get the channel interface
194 --*/
195 static void
196 VmbusGetChannelInterface(
197 VMBUS_CHANNEL_INTERFACE *Interface
200 GetChannelInterface(Interface);
204 /*++;
206 Name:
207 VmbusGetChannelInterface()
209 Description:
210 Get the device info for the specified device object
212 --*/
213 static void
214 VmbusGetChannelInfo(
215 struct hv_device *DeviceObject,
216 DEVICE_INFO *DeviceInfo
219 GetChannelInfo(DeviceObject, DeviceInfo);
224 /*++
226 Name:
227 VmbusCreateChildDevice()
229 Description:
230 Creates the child device on the bus that represents the channel offer
232 --*/
234 struct hv_device *VmbusChildDeviceCreate(struct hv_guid *DeviceType,
235 struct hv_guid *DeviceInstance,
236 void *Context)
238 VMBUS_DRIVER_OBJECT* vmbusDriver = (VMBUS_DRIVER_OBJECT*)gDriver;
240 return vmbusDriver->OnChildDeviceCreate(
241 DeviceType,
242 DeviceInstance,
243 Context);
247 /*++
249 Name:
250 VmbusChildDeviceAdd()
252 Description:
253 Registers the child device with the vmbus
255 --*/
256 int VmbusChildDeviceAdd(struct hv_device *ChildDevice)
258 VMBUS_DRIVER_OBJECT* vmbusDriver = (VMBUS_DRIVER_OBJECT*)gDriver;
260 return vmbusDriver->OnChildDeviceAdd(gDevice, ChildDevice);
264 /*++
266 Name:
267 VmbusChildDeviceRemove()
269 Description:
270 Unregisters the child device from the vmbus
272 --*/
273 void VmbusChildDeviceRemove(struct hv_device *ChildDevice)
275 VMBUS_DRIVER_OBJECT* vmbusDriver = (VMBUS_DRIVER_OBJECT*)gDriver;
277 vmbusDriver->OnChildDeviceRemove(ChildDevice);
280 /*++
282 Name:
283 VmbusChildDeviceDestroy()
285 Description:
286 Release the child device from the vmbus
288 --*/
290 /* **************
291 void
292 VmbusChildDeviceDestroy(
293 struct hv_device *ChildDevice
296 VMBUS_DRIVER_OBJECT* vmbusDriver = (VMBUS_DRIVER_OBJECT*)gDriver;
298 vmbusDriver->OnChildDeviceDestroy(ChildDevice);
300 ************* */
302 /*++
304 Name:
305 VmbusOnDeviceAdd()
307 Description:
308 Callback when the root bus device is added
310 --*/
311 static int
312 VmbusOnDeviceAdd(
313 struct hv_device *dev,
314 void *AdditionalInfo
317 u32 *irqvector = (u32*) AdditionalInfo;
318 int ret=0;
320 DPRINT_ENTER(VMBUS);
322 gDevice = dev;
324 memcpy(&gDevice->deviceType, &gVmbusDeviceType, sizeof(struct hv_guid));
325 memcpy(&gDevice->deviceInstance, &gVmbusDeviceId, sizeof(struct hv_guid));
327 /* strcpy(dev->name, "vmbus"); */
328 /* SynIC setup... */
329 ret = HvSynicInit(*irqvector);
331 /* Connect to VMBus in the root partition */
332 ret = VmbusConnect();
334 /* VmbusSendEvent(device->localPortId+1); */
335 DPRINT_EXIT(VMBUS);
337 return ret;
341 /*++
343 Name:
344 VmbusOnDeviceRemove()
346 Description:
347 Callback when the root bus device is removed
349 --*/
350 static int VmbusOnDeviceRemove(
351 struct hv_device *dev
354 int ret=0;
356 DPRINT_ENTER(VMBUS);
358 VmbusChannelReleaseUnattachedChannels();
360 VmbusDisconnect();
362 HvSynicCleanup();
364 DPRINT_EXIT(VMBUS);
366 return ret;
370 /*++
372 Name:
373 VmbusOnCleanup()
375 Description:
376 Perform any cleanup when the driver is removed
378 --*/
379 static void
380 VmbusOnCleanup(
381 struct hv_driver *drv
384 /* VMBUS_DRIVER_OBJECT* driver = (VMBUS_DRIVER_OBJECT*)drv; */
386 DPRINT_ENTER(VMBUS);
388 HvCleanup();
390 DPRINT_EXIT(VMBUS);
394 /*++
396 Name:
397 VmbusOnMsgDPC()
399 Description:
400 DPC routine to handle messages from the hypervisior
402 --*/
403 static void
404 VmbusOnMsgDPC(
405 struct hv_driver *drv
408 void *page_addr = gHvContext.synICMessagePage[0];
410 HV_MESSAGE* msg = (HV_MESSAGE*)page_addr + VMBUS_MESSAGE_SINT;
411 HV_MESSAGE *copied;
412 while (1)
414 if (msg->Header.MessageType == HvMessageTypeNone) /* no msg */
416 break;
418 else
420 copied = kmalloc(sizeof(HV_MESSAGE), GFP_ATOMIC);
421 if (copied == NULL)
423 continue;
426 memcpy(copied, msg, sizeof(HV_MESSAGE));
427 osd_schedule_callback(gVmbusConnection.WorkQueue,
428 VmbusOnChannelMessage,
429 (void *)copied);
432 msg->Header.MessageType = HvMessageTypeNone;
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
441 mb();
443 if (msg->Header.MessageFlags.MessagePending)
446 * This will cause message queue rescan to
447 * possibly deliver another msg from the
448 * hypervisor
450 wrmsrl(HV_X64_MSR_EOM, 0);
455 /*++
457 Name:
458 VmbusOnEventDPC()
460 Description:
461 DPC routine to handle events from the hypervisior
463 --*/
464 static void
465 VmbusOnEventDPC(
466 struct hv_driver* drv
469 /* TODO: Process any events */
470 VmbusOnEvents();
474 /*++
476 Name:
477 VmbusOnISR()
479 Description:
480 ISR routine
482 --*/
483 static int
484 VmbusOnISR(
485 struct hv_driver *drv
488 /* VMBUS_DRIVER_OBJECT* driver = (VMBUS_DRIVER_OBJECT*)drv; */
490 int ret=0;
491 /* struct page* page; */
492 void *page_addr;
493 HV_MESSAGE* msg;
494 HV_SYNIC_EVENT_FLAGS* event;
496 /* page = SynICMessagePage[0]; */
497 /* page_addr = page_address(page); */
498 page_addr = gHvContext.synICMessagePage[0];
499 msg = (HV_MESSAGE*)page_addr + VMBUS_MESSAGE_SINT;
501 DPRINT_ENTER(VMBUS);
503 /* Check if there are actual msgs to be process */
504 if (msg->Header.MessageType != HvMessageTypeNone)
506 DPRINT_DBG(VMBUS, "received msg type %d size %d", msg->Header.MessageType, msg->Header.PayloadSize);
507 ret |= 0x1;
510 /* TODO: Check if there are events to be process */
511 page_addr = gHvContext.synICEventPage[0];
512 event = (HV_SYNIC_EVENT_FLAGS*)page_addr + VMBUS_MESSAGE_SINT;
514 /* Since we are a child, we only need to check bit 0 */
515 if (test_and_clear_bit(0, (unsigned long *) &event->Flags32[0]))
517 DPRINT_DBG(VMBUS, "received event %d", event->Flags32[0]);
518 ret |= 0x2;
521 DPRINT_EXIT(VMBUS);
522 return ret;
525 /* eof */