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
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.
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"
39 /* FIXME! We need to do this dynamically for PIC and APIC system */
41 #define VMBUS_IRQ_VECTOR IRQ5_VECTOR
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
;
55 struct tasklet_struct msg_dpc
;
56 struct tasklet_struct event_dpc
;
58 /* The bus root device */
59 struct device_context device_ctx
;
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
);
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
),
136 /* The one and only one */
137 static struct vmbus_driver_context g_vmbus_drv
={
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
,
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>"
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
);
269 Name: vmbus_show_class_id()
271 Desc: Show the device class id in sysfs
274 /* static ssize_t vmbus_show_class_id(struct device *dev, struct device_attribute *attr, char *buf) */
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]); */
286 Name: vmbus_show_device_id()
288 Desc: Show the device instance id in sysfs
291 /* static ssize_t vmbus_show_device_id(struct device *dev, struct device_attribute *attr, char *buf) */
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]); */
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
314 int vmbus_bus_init(PFN_DRIVERINITIALIZE pfn_drv_init
)
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
);
336 DPRINT_ERR(VMBUS_DRV
, "Unable to initialize vmbus (%d)", ret
);
341 if (!vmbus_drv_obj
->Base
.OnDeviceAdd
)
343 DPRINT_ERR(VMBUS_DRV
, "OnDeviceAdd() routine not set");
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
);
362 /* Get the interrupt resource */
363 ret
= request_irq(vmbus_irq
,
366 vmbus_drv_obj
->Base
.name
,
371 DPRINT_ERR(VMBUS_DRV
, "ERROR - Unable to request IRQ %d", vmbus_irq
);
373 bus_unregister(&vmbus_drv_ctx
->bus
);
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
);
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
);
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
);
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
);
423 vmbus_drv_obj
->GetChannelOffers();
426 DPRINT_EXIT(VMBUS_DRV
);
434 Name: vmbus_bus_exit()
436 Desc: Terminate the vmbus driver. This routine is opposite of vmbus_bus_init()
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
);
472 Name: vmbus_child_driver_register()
474 Desc: Register a vmbus's child driver
477 int vmbus_child_driver_register(struct driver_context
* driver_ctx
)
479 VMBUS_DRIVER_OBJECT
*vmbus_drv_obj
=&g_vmbus_drv
.drv_obj
;
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
);
498 EXPORT_SYMBOL(vmbus_child_driver_register
);
502 Name: vmbus_child_driver_unregister()
504 Desc: Unregister a vmbus's child driver
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
);
524 Name: vmbus_get_interface()
526 Desc: Get the vmbus channel interface. This is invoked by child/client driver that sits
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
);
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.
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
);
555 Name: vmbus_child_device_create()
557 Desc: Creates and registers a new child device on the vmbus.
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
);
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
;
599 Name: vmbus_child_device_register()
601 Desc: Register the child device on the specified bus
604 static int vmbus_child_device_register(struct hv_device
*root_device_obj
, struct hv_device
*child_device_obj
)
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
));
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
;
641 DPRINT_ERR(VMBUS_DRV
, "unable to register child device (%p)", &child_device_ctx
->device
);
643 DPRINT_INFO(VMBUS_DRV
, "child device (%p) registered", &child_device_ctx
->device
);
646 DPRINT_EXIT(VMBUS_DRV
);
653 Name: vmbus_child_device_unregister()
655 Desc: Remove the specified child device from the vmbus.
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
);
678 Name: vmbus_child_device_destroy()
680 Desc: Destroy the specified child device on the vmbus.
683 static void vmbus_child_device_destroy(struct hv_device
*device_obj
)
685 DPRINT_ENTER(VMBUS_DRV
);
687 DPRINT_EXIT(VMBUS_DRV
);
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
698 static int vmbus_uevent(struct device
*device
, struct kobj_uevent_env
*env
)
700 struct device_context
*device_ctx
= device_to_device_context(device
);
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]);
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]);
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]);
742 env
->envp
[env
->envp_idx
] = NULL
;
744 DPRINT_EXIT(VMBUS_DRV
);
753 Desc: Attempt to match the specified device to the specified driver
756 static int vmbus_match(struct device
*device
, struct device_driver
*driver
)
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
);
776 DPRINT_EXIT(VMBUS_DRV
);
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
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
);
811 Desc: Add the new vmbus's child device
814 static int vmbus_probe(struct device
*child_device
)
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
);
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
);
836 DPRINT_ERR(VMBUS_DRV
, "probe() method not set for driver - %s", child_device
->driver
->name
);
840 DPRINT_EXIT(VMBUS_DRV
);
849 Desc: Remove a vmbus device
852 static int vmbus_remove(struct device
*child_device
)
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
);
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
);
878 DPRINT_ERR(VMBUS_DRV
, "remove() method not set for driver - %s", child_device
->driver
->name
);
887 DPRINT_EXIT(VMBUS_DRV
);
894 Name: vmbus_shutdown()
896 Desc: Shutdown a vmbus device
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
);
913 /* The device may not be attached yet */
914 if (!child_device
->driver
)
916 DPRINT_EXIT(VMBUS_DRV
);
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
);
935 Name: vmbus_bus_release()
937 Desc: Final callback release of the vmbus root device
940 static void vmbus_bus_release(struct device
*device
)
942 DPRINT_ENTER(VMBUS_DRV
);
943 DPRINT_EXIT(VMBUS_DRV
);
948 Name: vmbus_device_release()
950 Desc: Final callback release of the vmbus child device
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); */
962 /* !!DO NOT REFERENCE device_ctx anymore at this point!! */
964 DPRINT_EXIT(VMBUS_DRV
);
971 Name: vmbus_msg_dpc()
973 Desc: Tasklet routine to handle hypervisor messages
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
);
992 Name: vmbus_msg_dpc()
994 Desc: Tasklet routine to handle hypervisor events
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
);
1013 Name: vmbus_msg_dpc()
1018 static irqreturn_t
vmbus_isr(int irq
, void* dev_id
)
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 */
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
);
1048 DPRINT_EXIT(VMBUS_DRV
);
1053 MODULE_LICENSE("GPL");
1060 Desc: Main vmbus driver entry routine
1063 static int __init
vmbus_init(void)
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
);
1086 Desc: Main vmbus driver exit routine
1089 static void __exit
vmbus_exit(void)
1091 DPRINT_ENTER(VMBUS_DRV
);
1094 /* Todo: it is used for loglevel, to be ported to new kernel. */
1095 DPRINT_EXIT(VMBUS_DRV
);
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
);