Staging: hv: coding style cleanups for Connection.c
[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"
645954c5 27#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 62
ee3d7ddf 63static void VmbusGetChannelInterface(struct vmbus_channel_interface *Interface);
3e7ee490
HJ
64
65static void
66VmbusGetChannelInfo(
3d3b5518 67 struct hv_device *DeviceObject,
ee3d7ddf 68 struct hv_device_info *DeviceInfo
3e7ee490
HJ
69 );
70
71static void
72VmbusGetChannelOffers(
73 void
74 );
75
76static int
77VmbusOnDeviceAdd(
3d3b5518 78 struct hv_device *Device,
3e7ee490
HJ
79 void *AdditionalInfo
80 );
81
82static int
83VmbusOnDeviceRemove(
3d3b5518 84 struct hv_device *dev
3e7ee490
HJ
85 );
86
87static void
88VmbusOnCleanup(
775ef25e 89 struct hv_driver *drv
3e7ee490
HJ
90 );
91
92static int
93VmbusOnISR(
775ef25e 94 struct hv_driver *drv
3e7ee490
HJ
95 );
96
97static void
98VmbusOnMsgDPC(
775ef25e 99 struct hv_driver *drv
3e7ee490
HJ
100 );
101
102static void
103VmbusOnEventDPC(
775ef25e 104 struct hv_driver *drv
3e7ee490
HJ
105 );
106
107/*++;
108
109Name:
110 VmbusInitialize()
111
112Description:
113 Main entry point
114
115--*/
116int
117VmbusInitialize(
775ef25e 118 struct hv_driver *drv
3e7ee490
HJ
119 )
120{
ee3d7ddf 121 struct vmbus_driver *driver = (struct vmbus_driver *)drv;
3e7ee490
HJ
122 int ret=0;
123
124 DPRINT_ENTER(VMBUS);
125
126 DPRINT_INFO(VMBUS, "+++++++ Build Date=%s %s +++++++", VersionDate, VersionTime);
127 DPRINT_INFO(VMBUS, "+++++++ Build Description=%s +++++++", VersionDesc);
128
129 DPRINT_INFO(VMBUS, "+++++++ Vmbus supported version = %d +++++++", VMBUS_REVISION_NUMBER);
130 DPRINT_INFO(VMBUS, "+++++++ Vmbus using SINT %d +++++++", VMBUS_MESSAGE_SINT);
131
b7d7ae6f 132 DPRINT_DBG(VMBUS, "sizeof(VMBUS_CHANNEL_PACKET_PAGE_BUFFER)=%zd, sizeof(VMBUS_CHANNEL_PACKET_MULITPAGE_BUFFER)=%zd",
3fcc523a 133 sizeof(struct VMBUS_CHANNEL_PACKET_PAGE_BUFFER), sizeof(struct VMBUS_CHANNEL_PACKET_MULITPAGE_BUFFER));
3e7ee490
HJ
134
135 drv->name = gDriverName;
caf26a31 136 memcpy(&drv->deviceType, &gVmbusDeviceType, sizeof(struct hv_guid));
3e7ee490 137
454f18a9 138 /* Setup dispatch table */
3e7ee490
HJ
139 driver->Base.OnDeviceAdd = VmbusOnDeviceAdd;
140 driver->Base.OnDeviceRemove = VmbusOnDeviceRemove;
141 driver->Base.OnCleanup = VmbusOnCleanup;
142 driver->OnIsr = VmbusOnISR;
143 driver->OnMsgDpc = VmbusOnMsgDPC;
144 driver->OnEventDpc = VmbusOnEventDPC;
145 driver->GetChannelOffers = VmbusGetChannelOffers;
146 driver->GetChannelInterface = VmbusGetChannelInterface;
147 driver->GetChannelInfo = VmbusGetChannelInfo;
148
454f18a9 149 /* Hypervisor initialization...setup hypercall page..etc */
3e7ee490
HJ
150 ret = HvInit();
151 if (ret != 0)
152 {
153 DPRINT_ERR(VMBUS, "Unable to initialize the hypervisor - 0x%x", ret);
154 }
155
156 gDriver = drv;
157
158 DPRINT_EXIT(VMBUS);
159
160 return ret;
161}
162
163
164/*++;
165
166Name:
167 VmbusGetChannelOffers()
168
169Description:
170 Retrieve the channel offers from the parent partition
171
172--*/
173
174static void
175VmbusGetChannelOffers(void)
176{
177 DPRINT_ENTER(VMBUS);
178 VmbusChannelRequestOffers();
179 DPRINT_EXIT(VMBUS);
180}
181
182
183/*++;
184
185Name:
186 VmbusGetChannelInterface()
187
188Description:
189 Get the channel interface
190
191--*/
ee3d7ddf 192static void VmbusGetChannelInterface(struct vmbus_channel_interface *Interface)
3e7ee490
HJ
193{
194 GetChannelInterface(Interface);
195}
196
197
198/*++;
199
200Name:
ee3d7ddf 201 VmbusGetChannelInfo()
3e7ee490
HJ
202
203Description:
204 Get the device info for the specified device object
205
206--*/
207static void
208VmbusGetChannelInfo(
3d3b5518 209 struct hv_device *DeviceObject,
ee3d7ddf 210 struct hv_device_info *DeviceInfo
3e7ee490
HJ
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
daaa8cc3
GKH
228struct hv_device *VmbusChildDeviceCreate(struct hv_guid *DeviceType,
229 struct hv_guid *DeviceInstance,
f346fdc2 230 void *Context)
3e7ee490 231{
ee3d7ddf 232 struct vmbus_driver *vmbusDriver = (struct vmbus_driver *)gDriver;
3e7ee490
HJ
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 251{
ee3d7ddf 252 struct vmbus_driver *vmbusDriver = (struct vmbus_driver *)gDriver;
3e7ee490
HJ
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 268{
ee3d7ddf 269 struct vmbus_driver *vmbusDriver = (struct vmbus_driver *)gDriver;
3e7ee490
HJ
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{
ee3d7ddf 290 struct vmbus_driver *vmbusDriver = (struct vmbus_driver *)gDriver;
454f18a9 291
ee3d7ddf 292 vmbusDriver->OnChildDeviceDestroy(ChildDevice);
454f18a9
BP
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
caf26a31
GKH
318 memcpy(&gDevice->deviceType, &gVmbusDeviceType, sizeof(struct hv_guid));
319 memcpy(&gDevice->deviceInstance, &gVmbusDeviceId, sizeof(struct hv_guid));
3e7ee490 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{
ee3d7ddf 378 /* struct vmbus_driver *driver = (struct vmbus_driver *)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
eacb1b4d
GKH
404 struct hv_message *msg = (struct hv_message *)page_addr + VMBUS_MESSAGE_SINT;
405 struct hv_message *copied;
3e7ee490
HJ
406 while (1)
407 {
454f18a9 408 if (msg->Header.MessageType == HvMessageTypeNone) /* no msg */
3e7ee490
HJ
409 {
410 break;
411 }
412 else
413 {
eacb1b4d 414 copied = kmalloc(sizeof(*copied), GFP_ATOMIC);
3e7ee490
HJ
415 if (copied == NULL)
416 {
417 continue;
418 }
419
eacb1b4d 420 memcpy(copied, msg, sizeof(*copied));
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{
ee3d7ddf 482 /* struct vmbus_driver *driver = (struct vmbus_driver *)drv; */
3e7ee490
HJ
483
484 int ret=0;
454f18a9 485 /* struct page* page; */
3e7ee490 486 void *page_addr;
eacb1b4d
GKH
487 struct hv_message *msg;
488 union hv_synic_event_flags *event;
3e7ee490 489
454f18a9
BP
490 /* page = SynICMessagePage[0]; */
491 /* page_addr = page_address(page); */
3e7ee490 492 page_addr = gHvContext.synICMessagePage[0];
eacb1b4d 493 msg = (struct hv_message *)page_addr + VMBUS_MESSAGE_SINT;
3e7ee490
HJ
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 505 page_addr = gHvContext.synICEventPage[0];
eacb1b4d 506 event = (union hv_synic_event_flags *)page_addr + VMBUS_MESSAGE_SINT;
3e7ee490 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.056947 seconds and 5 git commands to generate.