Staging: hv: Transform PDEVICE_OBJECT and DEVICE_OBJECT typedefs into their correspon...
[linux-2.6/mini2440.git] / drivers / staging / hv / vmbus_drv.c
blob32ae68c98775afa801ace00b42adf42e39ab7f78
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>
25 #include <linux/init.h>
26 #include <linux/module.h>
27 #include <linux/device.h>
28 #include <linux/irq.h>
29 #include <linux/interrupt.h>
30 #include <linux/sysctl.h>
32 #include "include/logging.h"
33 #include "include/vmbus.h"
36 /* Defines */
39 /* FIXME! We need to do this dynamically for PIC and APIC system */
40 #define VMBUS_IRQ 0x5
41 #define VMBUS_IRQ_VECTOR IRQ5_VECTOR
43 /* Data types */
46 /* Main vmbus driver data structure */
47 struct vmbus_driver_context {
48 /* !! These must be the first 2 fields !! */
49 /* The driver field is not used in here. Instead, the bus field is */
50 /* used to represent the driver */
51 struct driver_context drv_ctx;
52 VMBUS_DRIVER_OBJECT drv_obj;
54 struct bus_type bus;
55 struct tasklet_struct msg_dpc;
56 struct tasklet_struct event_dpc;
58 /* The bus root device */
59 struct device_context device_ctx;
63 /* Static decl */
65 static int vmbus_match(struct device *device, struct device_driver *driver);
66 static int vmbus_probe(struct device *device);
67 static int vmbus_remove(struct device *device);
68 static void vmbus_shutdown(struct device *device);
69 static int vmbus_uevent(struct device *device, struct kobj_uevent_env *env);
70 static void vmbus_msg_dpc(unsigned long data);
71 static void vmbus_event_dpc(unsigned long data);
73 static irqreturn_t vmbus_isr(int irq, void* dev_id);
75 static void vmbus_device_release(struct device *device);
76 static void vmbus_bus_release(struct device *device);
78 static struct hv_device *vmbus_child_device_create(GUID type, GUID instance, void* context);
79 static void vmbus_child_device_destroy(struct hv_device *device_obj);
80 static int vmbus_child_device_register(struct hv_device *root_device_obj, struct hv_device *child_device_obj);
81 static void vmbus_child_device_unregister(struct hv_device *child_device_obj);
82 static void vmbus_child_device_get_info(struct hv_device *device_obj, DEVICE_INFO *device_info);
84 /* static ssize_t vmbus_show_class_id(struct device *dev, struct device_attribute *attr, char *buf); */
85 /* static ssize_t vmbus_show_device_id(struct device *dev, struct device_attribute *attr, char *buf); */
87 static ssize_t vmbus_show_device_attr(struct device *dev, struct device_attribute *dev_attr, char *buf);
90 /* Global */
93 /* Global logging setting */
95 /* unsigned int vmbus_loglevel= (((VMBUS | VMBUS_DRV)<<16) | DEBUG_LVL_ENTEREXIT); */
96 /* unsigned int vmbus_loglevel= (ALL_MODULES << 16 | DEBUG_LVL_ENTEREXIT); */
97 unsigned int vmbus_loglevel= (ALL_MODULES << 16 | INFO_LVL);
98 EXPORT_SYMBOL(vmbus_loglevel);
100 static int vmbus_irq = VMBUS_IRQ;
102 /* Setup /proc/sys/bus/vmbus/vmbus_loglevel */
103 /* Allow usage of sysctl cmd to set the logging level */
105 /* Set up per device attributes in /sys/bus/vmbus/devices/<bus device> */
107 static struct device_attribute vmbus_device_attrs[] = {
108 __ATTR(id, S_IRUGO, vmbus_show_device_attr, NULL),
109 __ATTR(state, S_IRUGO, vmbus_show_device_attr, NULL),
110 __ATTR(class_id, S_IRUGO, vmbus_show_device_attr, NULL),
111 __ATTR(device_id, S_IRUGO, vmbus_show_device_attr, NULL),
112 __ATTR(monitor_id, S_IRUGO, vmbus_show_device_attr, NULL),
114 __ATTR(server_monitor_pending, S_IRUGO, vmbus_show_device_attr, NULL),
115 __ATTR(server_monitor_latency, S_IRUGO, vmbus_show_device_attr, NULL),
116 __ATTR(server_monitor_conn_id, S_IRUGO, vmbus_show_device_attr, NULL),
118 __ATTR(client_monitor_pending, S_IRUGO, vmbus_show_device_attr, NULL),
119 __ATTR(client_monitor_latency, S_IRUGO, vmbus_show_device_attr, NULL),
120 __ATTR(client_monitor_conn_id, S_IRUGO, vmbus_show_device_attr, NULL),
122 __ATTR(out_intr_mask, S_IRUGO, vmbus_show_device_attr, NULL),
123 __ATTR(out_read_index, S_IRUGO, vmbus_show_device_attr, NULL),
124 __ATTR(out_write_index, S_IRUGO, vmbus_show_device_attr, NULL),
125 __ATTR(out_read_bytes_avail, S_IRUGO, vmbus_show_device_attr, NULL),
126 __ATTR(out_write_bytes_avail, S_IRUGO, vmbus_show_device_attr, NULL),
128 __ATTR(in_intr_mask, S_IRUGO, vmbus_show_device_attr, NULL),
129 __ATTR(in_read_index, S_IRUGO, vmbus_show_device_attr, NULL),
130 __ATTR(in_write_index, S_IRUGO, vmbus_show_device_attr, NULL),
131 __ATTR(in_read_bytes_avail, S_IRUGO, vmbus_show_device_attr, NULL),
132 __ATTR(in_write_bytes_avail, S_IRUGO, vmbus_show_device_attr, NULL),
133 __ATTR_NULL
136 /* The one and only one */
137 static struct vmbus_driver_context g_vmbus_drv={
138 .bus.name = "vmbus",
139 .bus.match = vmbus_match,
140 .bus.shutdown = vmbus_shutdown,
141 .bus.remove = vmbus_remove,
142 .bus.probe = vmbus_probe,
143 .bus.uevent = vmbus_uevent,
144 .bus.dev_attrs = vmbus_device_attrs,
148 /* Routines */
152 /*++
154 Name: vmbus_show_device_attr()
156 Desc: Show the device attribute in sysfs. This is invoked when user does a "cat /sys/bus/vmbus/devices/<bus device>/<attr name>"
158 --*/
159 static ssize_t vmbus_show_device_attr(struct device *dev, struct device_attribute *dev_attr, char *buf)
161 struct device_context *device_ctx = device_to_device_context(dev);
162 DEVICE_INFO device_info;
164 memset(&device_info, 0, sizeof(DEVICE_INFO));
166 vmbus_child_device_get_info(&device_ctx->device_obj, &device_info);
168 if (!strcmp(dev_attr->attr.name, "class_id"))
170 return sprintf(buf, "{%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x%02x%02x}\n",
171 device_info.ChannelType.Data[3], device_info.ChannelType.Data[2], device_info.ChannelType.Data[1], device_info.ChannelType.Data[0],
172 device_info.ChannelType.Data[5], device_info.ChannelType.Data[4],
173 device_info.ChannelType.Data[7], device_info.ChannelType.Data[6],
174 device_info.ChannelType.Data[8], device_info.ChannelType.Data[9], device_info.ChannelType.Data[10], device_info.ChannelType.Data[11], device_info.ChannelType.Data[12], device_info.ChannelType.Data[13], device_info.ChannelType.Data[14], device_info.ChannelType.Data[15]);
177 else if (!strcmp(dev_attr->attr.name, "device_id"))
179 return sprintf(buf, "{%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x%02x%02x}\n",
180 device_info.ChannelInstance.Data[3], device_info.ChannelInstance.Data[2], device_info.ChannelInstance.Data[1], device_info.ChannelInstance.Data[0],
181 device_info.ChannelInstance.Data[5], device_info.ChannelInstance.Data[4],
182 device_info.ChannelInstance.Data[7], device_info.ChannelInstance.Data[6],
183 device_info.ChannelInstance.Data[8], device_info.ChannelInstance.Data[9], device_info.ChannelInstance.Data[10], device_info.ChannelInstance.Data[11], device_info.ChannelInstance.Data[12], device_info.ChannelInstance.Data[13], device_info.ChannelInstance.Data[14], device_info.ChannelInstance.Data[15]);
185 else if (!strcmp(dev_attr->attr.name, "state"))
187 return sprintf(buf, "%d\n", device_info.ChannelState);
189 else if (!strcmp(dev_attr->attr.name, "id"))
191 return sprintf(buf, "%d\n", device_info.ChannelId);
193 else if (!strcmp(dev_attr->attr.name, "out_intr_mask"))
195 return sprintf(buf, "%d\n", device_info.Outbound.InterruptMask);
197 else if (!strcmp(dev_attr->attr.name, "out_read_index"))
199 return sprintf(buf, "%d\n", device_info.Outbound.ReadIndex);
201 else if (!strcmp(dev_attr->attr.name, "out_write_index"))
203 return sprintf(buf, "%d\n", device_info.Outbound.WriteIndex);
205 else if (!strcmp(dev_attr->attr.name, "out_read_bytes_avail"))
207 return sprintf(buf, "%d\n", device_info.Outbound.BytesAvailToRead);
209 else if (!strcmp(dev_attr->attr.name, "out_write_bytes_avail"))
211 return sprintf(buf, "%d\n", device_info.Outbound.BytesAvailToWrite);
213 else if (!strcmp(dev_attr->attr.name, "in_intr_mask"))
215 return sprintf(buf, "%d\n", device_info.Inbound.InterruptMask);
217 else if (!strcmp(dev_attr->attr.name, "in_read_index"))
219 return sprintf(buf, "%d\n", device_info.Inbound.ReadIndex);
221 else if (!strcmp(dev_attr->attr.name, "in_write_index"))
223 return sprintf(buf, "%d\n", device_info.Inbound.WriteIndex);
225 else if (!strcmp(dev_attr->attr.name, "in_read_bytes_avail"))
227 return sprintf(buf, "%d\n", device_info.Inbound.BytesAvailToRead);
229 else if (!strcmp(dev_attr->attr.name, "in_write_bytes_avail"))
231 return sprintf(buf, "%d\n", device_info.Inbound.BytesAvailToWrite);
233 else if (!strcmp(dev_attr->attr.name, "monitor_id"))
235 return sprintf(buf, "%d\n", device_info.MonitorId);
237 else if (!strcmp(dev_attr->attr.name, "server_monitor_pending"))
239 return sprintf(buf, "%d\n", device_info.ServerMonitorPending);
241 else if (!strcmp(dev_attr->attr.name, "server_monitor_latency"))
243 return sprintf(buf, "%d\n", device_info.ServerMonitorLatency);
245 else if (!strcmp(dev_attr->attr.name, "server_monitor_conn_id"))
247 return sprintf(buf, "%d\n", device_info.ServerMonitorConnectionId);
249 else if (!strcmp(dev_attr->attr.name, "client_monitor_pending"))
251 return sprintf(buf, "%d\n", device_info.ClientMonitorPending);
253 else if (!strcmp(dev_attr->attr.name, "client_monitor_latency"))
255 return sprintf(buf, "%d\n", device_info.ClientMonitorLatency);
257 else if (!strcmp(dev_attr->attr.name, "client_monitor_conn_id"))
259 return sprintf(buf, "%d\n", device_info.ClientMonitorConnectionId);
261 else
263 return 0;
267 /*++
269 Name: vmbus_show_class_id()
271 Desc: Show the device class id in sysfs
273 --*/
274 /* static ssize_t vmbus_show_class_id(struct device *dev, struct device_attribute *attr, char *buf) */
275 /* { */
276 /* struct device_context *device_ctx = device_to_device_context(dev); */
277 /* return sprintf(buf, "{%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x%02x%02x}\n", */
278 /* device_ctx->class_id[3], device_ctx->class_id[2], device_ctx->class_id[1], device_ctx->class_id[0], */
279 /* device_ctx->class_id[5], device_ctx->class_id[4], */
280 /* device_ctx->class_id[7], device_ctx->class_id[6], */
281 /* device_ctx->class_id[8], device_ctx->class_id[9], device_ctx->class_id[10], device_ctx->class_id[11], device_ctx->class_id[12], device_ctx->class_id[13], device_ctx->class_id[14], device_ctx->class_id[15]); */
282 /* } */
284 /*++
286 Name: vmbus_show_device_id()
288 Desc: Show the device instance id in sysfs
290 --*/
291 /* static ssize_t vmbus_show_device_id(struct device *dev, struct device_attribute *attr, char *buf) */
292 /* { */
293 /* struct device_context *device_ctx = device_to_device_context(dev); */
294 /* return sprintf(buf, "{%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x%02x%02x}\n", */
295 /* device_ctx->device_id[3], device_ctx->device_id[2], device_ctx->device_id[1], device_ctx->device_id[0], */
296 /* device_ctx->device_id[5], device_ctx->device_id[4], */
297 /* device_ctx->device_id[7], device_ctx->device_id[6], */
298 /* device_ctx->device_id[8], device_ctx->device_id[9], device_ctx->device_id[10], device_ctx->device_id[11], device_ctx->device_id[12], device_ctx->device_id[13], device_ctx->device_id[14], device_ctx->device_id[15]); */
299 /* } */
301 /*++
303 Name: vmbus_bus_init()
305 Desc: Main vmbus driver initialization routine. Here, we
306 - initialize the vmbus driver context
307 - setup various driver entry points
308 - invoke the vmbus hv main init routine
309 - get the irq resource
310 - invoke the vmbus to add the vmbus root device
311 - setup the vmbus root device
312 - retrieve the channel offers
313 --*/
314 int vmbus_bus_init(PFN_DRIVERINITIALIZE pfn_drv_init)
316 int ret=0;
317 unsigned int vector=0;
319 struct vmbus_driver_context *vmbus_drv_ctx=&g_vmbus_drv;
320 VMBUS_DRIVER_OBJECT *vmbus_drv_obj=&g_vmbus_drv.drv_obj;
322 struct device_context *dev_ctx=&g_vmbus_drv.device_ctx;
324 DPRINT_ENTER(VMBUS_DRV);
326 /* Set this up to allow lower layer to callback to add/remove child devices on the bus */
327 vmbus_drv_obj->OnChildDeviceCreate = vmbus_child_device_create;
328 vmbus_drv_obj->OnChildDeviceDestroy = vmbus_child_device_destroy;
329 vmbus_drv_obj->OnChildDeviceAdd = vmbus_child_device_register;
330 vmbus_drv_obj->OnChildDeviceRemove = vmbus_child_device_unregister;
332 /* Call to bus driver to initialize */
333 ret = pfn_drv_init(&vmbus_drv_obj->Base);
334 if (ret != 0)
336 DPRINT_ERR(VMBUS_DRV, "Unable to initialize vmbus (%d)", ret);
337 goto cleanup;
340 /* Sanity checks */
341 if (!vmbus_drv_obj->Base.OnDeviceAdd)
343 DPRINT_ERR(VMBUS_DRV, "OnDeviceAdd() routine not set");
344 ret = -1;
345 goto cleanup;
348 vmbus_drv_ctx->bus.name = vmbus_drv_obj->Base.name;
350 /* Initialize the bus context */
351 tasklet_init(&vmbus_drv_ctx->msg_dpc, vmbus_msg_dpc, (unsigned long)vmbus_drv_obj);
352 tasklet_init(&vmbus_drv_ctx->event_dpc, vmbus_event_dpc, (unsigned long)vmbus_drv_obj);
354 /* Now, register the bus driver with LDM */
355 ret = bus_register(&vmbus_drv_ctx->bus);
356 if (ret)
358 ret = -1;
359 goto cleanup;
362 /* Get the interrupt resource */
363 ret = request_irq(vmbus_irq,
364 vmbus_isr,
365 IRQF_SAMPLE_RANDOM,
366 vmbus_drv_obj->Base.name,
367 NULL);
369 if (ret != 0)
371 DPRINT_ERR(VMBUS_DRV, "ERROR - Unable to request IRQ %d", vmbus_irq);
373 bus_unregister(&vmbus_drv_ctx->bus);
375 ret = -1;
376 goto cleanup;
378 vector = VMBUS_IRQ_VECTOR;
380 DPRINT_INFO(VMBUS_DRV, "irq 0x%x vector 0x%x", vmbus_irq, vector);
382 /* Call to bus driver to add the root device */
383 memset(dev_ctx, 0, sizeof(struct device_context));
385 ret = vmbus_drv_obj->Base.OnDeviceAdd(&dev_ctx->device_obj, &vector);
386 if (ret != 0)
388 DPRINT_ERR(VMBUS_DRV, "ERROR - Unable to add vmbus root device");
390 free_irq(vmbus_irq, NULL);
392 bus_unregister(&vmbus_drv_ctx->bus);
394 ret = -1;
395 goto cleanup;
397 /* strcpy(dev_ctx->device.bus_id, dev_ctx->device_obj.name); */
398 dev_set_name(&dev_ctx->device, "vmbus_0_0");
399 memcpy(&dev_ctx->class_id, &dev_ctx->device_obj.deviceType, sizeof(GUID));
400 memcpy(&dev_ctx->device_id, &dev_ctx->device_obj.deviceInstance, sizeof(GUID));
402 /* No need to bind a driver to the root device. */
403 dev_ctx->device.parent = NULL;
404 dev_ctx->device.bus = &vmbus_drv_ctx->bus; /* NULL; vmbus_remove() does not get invoked */
406 /* Setup the device dispatch table */
407 dev_ctx->device.release = vmbus_bus_release;
409 /* Setup the bus as root device */
410 ret = device_register(&dev_ctx->device);
411 if (ret)
413 DPRINT_ERR(VMBUS_DRV, "ERROR - Unable to register vmbus root device");
415 free_irq(vmbus_irq, NULL);
416 bus_unregister(&vmbus_drv_ctx->bus);
418 ret = -1;
419 goto cleanup;
423 vmbus_drv_obj->GetChannelOffers();
425 cleanup:
426 DPRINT_EXIT(VMBUS_DRV);
428 return ret;
432 /*++
434 Name: vmbus_bus_exit()
436 Desc: Terminate the vmbus driver. This routine is opposite of vmbus_bus_init()
438 --*/
439 void vmbus_bus_exit(void)
441 VMBUS_DRIVER_OBJECT *vmbus_drv_obj=&g_vmbus_drv.drv_obj;
442 struct vmbus_driver_context *vmbus_drv_ctx=&g_vmbus_drv;
444 struct device_context *dev_ctx=&g_vmbus_drv.device_ctx;
446 DPRINT_ENTER(VMBUS_DRV);
448 /* Remove the root device */
449 if (vmbus_drv_obj->Base.OnDeviceRemove)
450 vmbus_drv_obj->Base.OnDeviceRemove(&dev_ctx->device_obj);
452 if (vmbus_drv_obj->Base.OnCleanup)
453 vmbus_drv_obj->Base.OnCleanup(&vmbus_drv_obj->Base);
455 /* Unregister the root bus device */
456 device_unregister(&dev_ctx->device);
458 bus_unregister(&vmbus_drv_ctx->bus);
460 free_irq(vmbus_irq, NULL);
462 tasklet_kill(&vmbus_drv_ctx->msg_dpc);
463 tasklet_kill(&vmbus_drv_ctx->event_dpc);
465 DPRINT_EXIT(VMBUS_DRV);
467 return;
470 /*++
472 Name: vmbus_child_driver_register()
474 Desc: Register a vmbus's child driver
476 --*/
477 int vmbus_child_driver_register(struct driver_context* driver_ctx)
479 VMBUS_DRIVER_OBJECT *vmbus_drv_obj=&g_vmbus_drv.drv_obj;
480 int ret;
482 DPRINT_ENTER(VMBUS_DRV);
484 DPRINT_INFO(VMBUS_DRV, "child driver (%p) registering - name %s", driver_ctx, driver_ctx->driver.name);
486 /* The child driver on this vmbus */
487 driver_ctx->driver.bus = &g_vmbus_drv.bus;
489 ret = driver_register(&driver_ctx->driver);
491 vmbus_drv_obj->GetChannelOffers();
493 DPRINT_EXIT(VMBUS_DRV);
495 return ret;
498 EXPORT_SYMBOL(vmbus_child_driver_register);
500 /*++
502 Name: vmbus_child_driver_unregister()
504 Desc: Unregister a vmbus's child driver
506 --*/
507 void vmbus_child_driver_unregister(struct driver_context* driver_ctx)
509 DPRINT_ENTER(VMBUS_DRV);
511 DPRINT_INFO(VMBUS_DRV, "child driver (%p) unregistering - name %s", driver_ctx, driver_ctx->driver.name);
513 driver_unregister(&driver_ctx->driver);
515 driver_ctx->driver.bus = NULL;
517 DPRINT_EXIT(VMBUS_DRV);
520 EXPORT_SYMBOL(vmbus_child_driver_unregister);
522 /*++
524 Name: vmbus_get_interface()
526 Desc: Get the vmbus channel interface. This is invoked by child/client driver that sits
527 above vmbus
528 --*/
529 void vmbus_get_interface(VMBUS_CHANNEL_INTERFACE *interface)
531 VMBUS_DRIVER_OBJECT *vmbus_drv_obj=&g_vmbus_drv.drv_obj;
533 vmbus_drv_obj->GetChannelInterface(interface);
536 EXPORT_SYMBOL(vmbus_get_interface);
539 /*++
541 Name: vmbus_child_device_get_info()
543 Desc: Get the vmbus child device info. This is invoked to display various device attributes in sysfs.
544 --*/
545 static void vmbus_child_device_get_info(struct hv_device *device_obj, DEVICE_INFO *device_info)
547 VMBUS_DRIVER_OBJECT *vmbus_drv_obj=&g_vmbus_drv.drv_obj;
549 vmbus_drv_obj->GetChannelInfo(device_obj, device_info);
553 /*++
555 Name: vmbus_child_device_create()
557 Desc: Creates and registers a new child device on the vmbus.
559 --*/
560 static struct hv_device *vmbus_child_device_create(GUID type, GUID instance, void* context)
562 struct device_context *child_device_ctx;
563 struct hv_device *child_device_obj;
565 DPRINT_ENTER(VMBUS_DRV);
567 /* Allocate the new child device */
568 child_device_ctx = kzalloc(sizeof(struct device_context), GFP_KERNEL);
569 if (!child_device_ctx)
571 DPRINT_ERR(VMBUS_DRV, "unable to allocate device_context for child device");
572 DPRINT_EXIT(VMBUS_DRV);
574 return NULL;
577 DPRINT_DBG(VMBUS_DRV, "child device (%p) allocated - "
578 "type {%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x%02x%02x},"
579 "id {%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x%02x%02x}",
580 &child_device_ctx->device,
581 type.Data[3], type.Data[2], type.Data[1], type.Data[0], type.Data[5], type.Data[4], type.Data[7], type.Data[6], type.Data[8], type.Data[9], type.Data[10], type.Data[11], type.Data[12], type.Data[13], type.Data[14], type.Data[15],
582 instance.Data[3], instance.Data[2], instance.Data[1], instance.Data[0], instance.Data[5], instance.Data[4], instance.Data[7], instance.Data[6], instance.Data[8], instance.Data[9], instance.Data[10], instance.Data[11], instance.Data[12], instance.Data[13], instance.Data[14], instance.Data[15]);
584 child_device_obj = &child_device_ctx->device_obj;
585 child_device_obj->context = context;
586 memcpy(&child_device_obj->deviceType, &type, sizeof(GUID));
587 memcpy(&child_device_obj->deviceInstance, &instance, sizeof(GUID));
589 memcpy(&child_device_ctx->class_id, &type, sizeof(GUID));
590 memcpy(&child_device_ctx->device_id, &instance, sizeof(GUID));
592 DPRINT_EXIT(VMBUS_DRV);
594 return child_device_obj;
597 /*++
599 Name: vmbus_child_device_register()
601 Desc: Register the child device on the specified bus
603 --*/
604 static int vmbus_child_device_register(struct hv_device *root_device_obj, struct hv_device *child_device_obj)
606 int ret=0;
607 struct device_context *root_device_ctx = to_device_context(root_device_obj);
608 struct device_context *child_device_ctx = to_device_context(child_device_obj);
609 static int device_num=0;
611 DPRINT_ENTER(VMBUS_DRV);
613 DPRINT_DBG(VMBUS_DRV, "child device (%p) registering", child_device_ctx);
615 /* Make sure we are not registered already */
617 if (strlen(dev_name(&child_device_ctx->device)) != 0)
619 DPRINT_ERR(VMBUS_DRV, "child device (%p) already registered - busid %s", child_device_ctx, dev_name(&child_device_ctx->device));
621 ret = -1;
622 goto Cleanup;
625 /* Set the device bus id. Otherwise, device_register()will fail. */
626 dev_set_name(&child_device_ctx->device, "vmbus_0_%d", InterlockedIncrement(&device_num));
628 /* The new device belongs to this bus */
629 child_device_ctx->device.bus = &g_vmbus_drv.bus; /* device->dev.bus; */
630 child_device_ctx->device.parent = &root_device_ctx->device;
631 child_device_ctx->device.release = vmbus_device_release;
633 /* Register with the LDM. This will kick off the driver/device binding...which will */
634 /* eventually call vmbus_match() and vmbus_probe() */
635 ret = device_register(&child_device_ctx->device);
637 /* vmbus_probe() error does not get propergate to device_register(). */
638 ret = child_device_ctx->probe_error;
640 if (ret)
641 DPRINT_ERR(VMBUS_DRV, "unable to register child device (%p)", &child_device_ctx->device);
642 else
643 DPRINT_INFO(VMBUS_DRV, "child device (%p) registered", &child_device_ctx->device);
645 Cleanup:
646 DPRINT_EXIT(VMBUS_DRV);
648 return ret;
651 /*++
653 Name: vmbus_child_device_unregister()
655 Desc: Remove the specified child device from the vmbus.
657 --*/
658 static void vmbus_child_device_unregister(struct hv_device *device_obj)
660 struct device_context *device_ctx = to_device_context(device_obj);
662 DPRINT_ENTER(VMBUS_DRV);
664 DPRINT_INFO(VMBUS_DRV, "unregistering child device (%p)", &device_ctx->device);
666 /* Kick off the process of unregistering the device. */
667 /* This will call vmbus_remove() and eventually vmbus_device_release() */
668 device_unregister(&device_ctx->device);
670 DPRINT_INFO(VMBUS_DRV, "child device (%p) unregistered", &device_ctx->device);
672 DPRINT_EXIT(VMBUS_DRV);
676 /*++
678 Name: vmbus_child_device_destroy()
680 Desc: Destroy the specified child device on the vmbus.
682 --*/
683 static void vmbus_child_device_destroy(struct hv_device *device_obj)
685 DPRINT_ENTER(VMBUS_DRV);
687 DPRINT_EXIT(VMBUS_DRV);
690 /*++
692 Name: vmbus_uevent()
694 Desc: This routine is invoked when a device is added or removed on the vmbus to generate a uevent to udev in the
695 userspace. The udev will then look at its rule and the uevent generated here to load the appropriate driver
697 --*/
698 static int vmbus_uevent(struct device *device, struct kobj_uevent_env *env)
700 struct device_context *device_ctx = device_to_device_context(device);
701 int i=0;
702 int len=0;
703 int ret;
705 DPRINT_ENTER(VMBUS_DRV);
707 DPRINT_INFO(VMBUS_DRV, "generating uevent - VMBUS_DEVICE_CLASS_GUID={%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x%02x%02x}",
708 device_ctx->class_id.Data[3], device_ctx->class_id.Data[2], device_ctx->class_id.Data[1], device_ctx->class_id.Data[0],
709 device_ctx->class_id.Data[5], device_ctx->class_id.Data[4],
710 device_ctx->class_id.Data[7], device_ctx->class_id.Data[6],
711 device_ctx->class_id.Data[8], device_ctx->class_id.Data[9], device_ctx->class_id.Data[10], device_ctx->class_id.Data[11],
712 device_ctx->class_id.Data[12], device_ctx->class_id.Data[13], device_ctx->class_id.Data[14], device_ctx->class_id.Data[15]);
714 env->envp_idx = i;
715 env->buflen = len;
716 ret = add_uevent_var(env,
717 "VMBUS_DEVICE_CLASS_GUID={%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x%02x%02x}",
718 device_ctx->class_id.Data[3], device_ctx->class_id.Data[2], device_ctx->class_id.Data[1], device_ctx->class_id.Data[0],
719 device_ctx->class_id.Data[5], device_ctx->class_id.Data[4],
720 device_ctx->class_id.Data[7], device_ctx->class_id.Data[6],
721 device_ctx->class_id.Data[8], device_ctx->class_id.Data[9], device_ctx->class_id.Data[10], device_ctx->class_id.Data[11],
722 device_ctx->class_id.Data[12], device_ctx->class_id.Data[13], device_ctx->class_id.Data[14], device_ctx->class_id.Data[15]);
724 if (ret)
726 return ret;
729 ret = add_uevent_var(env,
730 "VMBUS_DEVICE_DEVICE_GUID={%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x%02x%02x}",
731 device_ctx->device_id.Data[3], device_ctx->device_id.Data[2], device_ctx->device_id.Data[1], device_ctx->device_id.Data[0],
732 device_ctx->device_id.Data[5], device_ctx->device_id.Data[4],
733 device_ctx->device_id.Data[7], device_ctx->device_id.Data[6],
734 device_ctx->device_id.Data[8], device_ctx->device_id.Data[9], device_ctx->device_id.Data[10], device_ctx->device_id.Data[11],
735 device_ctx->device_id.Data[12], device_ctx->device_id.Data[13], device_ctx->device_id.Data[14], device_ctx->device_id.Data[15]);
737 if (ret)
739 return ret;
742 env->envp[env->envp_idx] = NULL;
744 DPRINT_EXIT(VMBUS_DRV);
746 return 0;
749 /*++
751 Name: vmbus_match()
753 Desc: Attempt to match the specified device to the specified driver
755 --*/
756 static int vmbus_match(struct device *device, struct device_driver *driver)
758 int match=0;
759 struct driver_context *driver_ctx = driver_to_driver_context(driver);
760 struct device_context *device_ctx = device_to_device_context(device);
762 DPRINT_ENTER(VMBUS_DRV);
764 /* We found our driver ? */
765 if (memcmp(&device_ctx->class_id, &driver_ctx->class_id, sizeof(GUID)) == 0)
767 /* !! NOTE: The driver_ctx is not a vmbus_drv_ctx. We typecast it here to access the */
768 /* DRIVER_OBJECT field */
769 struct vmbus_driver_context *vmbus_drv_ctx = (struct vmbus_driver_context*)driver_ctx;
770 device_ctx->device_obj.Driver = &vmbus_drv_ctx->drv_obj.Base;
771 DPRINT_INFO(VMBUS_DRV, "device object (%p) set to driver object (%p)", &device_ctx->device_obj, device_ctx->device_obj.Driver);
773 match = 1;
776 DPRINT_EXIT(VMBUS_DRV);
778 return match;
782 /*++
784 Name: vmbus_probe_failed_cb()
786 Desc: Callback when a driver probe failed in vmbus_probe(). We need a callback because
787 we cannot invoked device_unregister() inside vmbus_probe() since vmbus_probe() may be
788 invoked inside device_register() i.e. we cannot call device_unregister() inside
789 device_register()
790 --*/
791 static void vmbus_probe_failed_cb(struct work_struct *context)
793 struct device_context *device_ctx = (struct device_context*)context;
796 DPRINT_ENTER(VMBUS_DRV);
798 /* Kick off the process of unregistering the device. */
799 /* This will call vmbus_remove() and eventually vmbus_device_release() */
800 device_unregister(&device_ctx->device);
802 /* put_device(&device_ctx->device); */
803 DPRINT_EXIT(VMBUS_DRV);
807 /*++
809 Name: vmbus_probe()
811 Desc: Add the new vmbus's child device
813 --*/
814 static int vmbus_probe(struct device *child_device)
816 int ret=0;
817 struct driver_context *driver_ctx = driver_to_driver_context(child_device->driver);
818 struct device_context *device_ctx = device_to_device_context(child_device);
820 DPRINT_ENTER(VMBUS_DRV);
822 /* Let the specific open-source driver handles the probe if it can */
823 if (driver_ctx->probe)
825 ret = device_ctx->probe_error = driver_ctx->probe(child_device);
826 if (ret != 0)
828 DPRINT_ERR(VMBUS_DRV, "probe() failed for device %s (%p) on driver %s (%d)...", dev_name(child_device), child_device, child_device->driver->name, ret);
830 INIT_WORK(&device_ctx->probe_failed_work_item, vmbus_probe_failed_cb);
831 schedule_work(&device_ctx->probe_failed_work_item);
834 else
836 DPRINT_ERR(VMBUS_DRV, "probe() method not set for driver - %s", child_device->driver->name);
837 ret = -1;
840 DPRINT_EXIT(VMBUS_DRV);
841 return ret;
845 /*++
847 Name: vmbus_remove()
849 Desc: Remove a vmbus device
851 --*/
852 static int vmbus_remove(struct device *child_device)
854 int ret=0;
855 struct driver_context *driver_ctx;
857 DPRINT_ENTER(VMBUS_DRV);
859 /* Special case root bus device */
860 if (child_device->parent == NULL)
862 /* No-op since it is statically defined and handle in vmbus_bus_exit() */
863 DPRINT_EXIT(VMBUS_DRV);
864 return 0;
867 if (child_device->driver)
869 driver_ctx = driver_to_driver_context(child_device->driver);
871 /* Let the specific open-source driver handles the removal if it can */
872 if (driver_ctx->remove)
874 ret = driver_ctx->remove(child_device);
876 else
878 DPRINT_ERR(VMBUS_DRV, "remove() method not set for driver - %s", child_device->driver->name);
879 ret = -1;
882 else
887 DPRINT_EXIT(VMBUS_DRV);
889 return 0;
892 /*++
894 Name: vmbus_shutdown()
896 Desc: Shutdown a vmbus device
898 --*/
899 static void vmbus_shutdown(struct device *child_device)
901 struct driver_context *driver_ctx;
903 DPRINT_ENTER(VMBUS_DRV);
905 /* Special case root bus device */
906 if (child_device->parent == NULL)
908 /* No-op since it is statically defined and handle in vmbus_bus_exit() */
909 DPRINT_EXIT(VMBUS_DRV);
910 return;
913 /* The device may not be attached yet */
914 if (!child_device->driver)
916 DPRINT_EXIT(VMBUS_DRV);
917 return;
920 driver_ctx = driver_to_driver_context(child_device->driver);
922 /* Let the specific open-source driver handles the removal if it can */
923 if (driver_ctx->shutdown)
925 driver_ctx->shutdown(child_device);
928 DPRINT_EXIT(VMBUS_DRV);
930 return;
933 /*++
935 Name: vmbus_bus_release()
937 Desc: Final callback release of the vmbus root device
939 --*/
940 static void vmbus_bus_release(struct device *device)
942 DPRINT_ENTER(VMBUS_DRV);
943 DPRINT_EXIT(VMBUS_DRV);
946 /*++
948 Name: vmbus_device_release()
950 Desc: Final callback release of the vmbus child device
952 --*/
953 static void vmbus_device_release(struct device *device)
955 struct device_context *device_ctx = device_to_device_context(device);
957 DPRINT_ENTER(VMBUS_DRV);
959 /* vmbus_child_device_destroy(&device_ctx->device_obj); */
960 kfree(device_ctx);
962 /* !!DO NOT REFERENCE device_ctx anymore at this point!! */
964 DPRINT_EXIT(VMBUS_DRV);
966 return;
969 /*++
971 Name: vmbus_msg_dpc()
973 Desc: Tasklet routine to handle hypervisor messages
975 --*/
976 static void vmbus_msg_dpc(unsigned long data)
978 VMBUS_DRIVER_OBJECT* vmbus_drv_obj = (VMBUS_DRIVER_OBJECT*)data;
980 DPRINT_ENTER(VMBUS_DRV);
982 ASSERT(vmbus_drv_obj->OnMsgDpc != NULL);
984 /* Call to bus driver to handle interrupt */
985 vmbus_drv_obj->OnMsgDpc(&vmbus_drv_obj->Base);
987 DPRINT_EXIT(VMBUS_DRV);
990 /*++
992 Name: vmbus_msg_dpc()
994 Desc: Tasklet routine to handle hypervisor events
996 --*/
997 static void vmbus_event_dpc(unsigned long data)
999 VMBUS_DRIVER_OBJECT* vmbus_drv_obj = (VMBUS_DRIVER_OBJECT*)data;
1001 DPRINT_ENTER(VMBUS_DRV);
1003 ASSERT(vmbus_drv_obj->OnEventDpc != NULL);
1005 /* Call to bus driver to handle interrupt */
1006 vmbus_drv_obj->OnEventDpc(&vmbus_drv_obj->Base);
1008 DPRINT_EXIT(VMBUS_DRV);
1011 /*++
1013 Name: vmbus_msg_dpc()
1015 Desc: ISR routine
1017 --*/
1018 static irqreturn_t vmbus_isr(int irq, void* dev_id)
1020 int ret=0;
1021 VMBUS_DRIVER_OBJECT* vmbus_driver_obj = &g_vmbus_drv.drv_obj;
1023 DPRINT_ENTER(VMBUS_DRV);
1025 ASSERT(vmbus_driver_obj->OnIsr != NULL);
1027 /* Call to bus driver to handle interrupt */
1028 ret = vmbus_driver_obj->OnIsr(&vmbus_driver_obj->Base);
1030 /* Schedules a dpc if necessary */
1031 if (ret > 0)
1033 if (test_bit(0, (unsigned long*)&ret))
1035 tasklet_schedule(&g_vmbus_drv.msg_dpc);
1038 if (test_bit(1, (unsigned long*)&ret))
1040 tasklet_schedule(&g_vmbus_drv.event_dpc);
1043 DPRINT_EXIT(VMBUS_DRV);
1044 return IRQ_HANDLED;
1046 else
1048 DPRINT_EXIT(VMBUS_DRV);
1049 return IRQ_NONE;
1053 MODULE_LICENSE("GPL");
1056 /*++
1058 Name: vmbus_init()
1060 Desc: Main vmbus driver entry routine
1062 --*/
1063 static int __init vmbus_init(void)
1065 int ret=0;
1067 DPRINT_ENTER(VMBUS_DRV);
1069 DPRINT_INFO(VMBUS_DRV,
1070 "Vmbus initializing.... current log level 0x%x (%x,%x)",
1071 vmbus_loglevel, HIWORD(vmbus_loglevel), LOWORD(vmbus_loglevel));
1072 /* Todo: it is used for loglevel, to be ported to new kernel. */
1074 ret = vmbus_bus_init(VmbusInitialize);
1076 DPRINT_EXIT(VMBUS_DRV);
1077 return ret;
1082 /*++
1084 Name: vmbus_init()
1086 Desc: Main vmbus driver exit routine
1088 --*/
1089 static void __exit vmbus_exit(void)
1091 DPRINT_ENTER(VMBUS_DRV);
1093 vmbus_bus_exit();
1094 /* Todo: it is used for loglevel, to be ported to new kernel. */
1095 DPRINT_EXIT(VMBUS_DRV);
1097 return;
1100 module_param(vmbus_irq, int, S_IRUGO);
1101 module_param(vmbus_loglevel, int, S_IRUGO);
1103 module_init(vmbus_init);
1104 module_exit(vmbus_exit);
1105 /* eof */