Staging: hv: add the Hyper-V virtual bus
[safe/jmp/linux-2.6] / drivers / staging / hv / vmbus_drv.c
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
24
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>
31
32 #include "logging.h"
33 #include "vmbus.h"
34
35 //
36 // Defines
37 //
38
39 // FIXME! We need to do this dynamically for PIC and APIC system
40 #define VMBUS_IRQ                               0x5
41 #ifdef KERNEL_2_6_27
42 #define VMBUS_IRQ_VECTOR     IRQ5_VECTOR
43 #endif
44 //
45 // Data types
46 //
47
48 // Main vmbus driver data structure
49 struct vmbus_driver_context {
50         // !! These must be the first 2 fields !!
51         // The driver field is not used in here. Instead, the bus field is
52         // used to represent the driver
53         struct driver_context   drv_ctx;
54         VMBUS_DRIVER_OBJECT             drv_obj;
55
56         struct bus_type                 bus;
57         struct tasklet_struct   msg_dpc;
58         struct tasklet_struct   event_dpc;
59
60         // The bus root device
61         struct device_context   device_ctx;
62 };
63
64 //
65 // Static decl
66 //
67 static int vmbus_match(struct device *device, struct device_driver *driver);
68 static int vmbus_probe(struct device *device);
69 static int vmbus_remove(struct device *device);
70 static void vmbus_shutdown(struct device *device);
71 #if defined(KERNEL_2_6_5) || defined(KERNEL_2_6_9)
72 #elif defined(KERNEL_2_6_27)
73 static int vmbus_uevent(struct device *device, struct kobj_uevent_env *env);
74 #else
75 static int vmbus_uevent(struct device *device, char **envp, int num_envp, char *buffer, int buffer_size);
76 #endif
77 static void vmbus_msg_dpc(unsigned long data);
78 static void vmbus_event_dpc(unsigned long data);
79
80 #ifdef KERNEL_2_6_27
81 static irqreturn_t vmbus_isr(int irq, void* dev_id);
82 #else
83 static int vmbus_isr(int irq, void* dev_id, struct pt_regs *regs);
84 #endif
85
86 static void vmbus_device_release(struct device *device);
87 static void vmbus_bus_release(struct device *device);
88
89 static DEVICE_OBJECT* vmbus_child_device_create(GUID type, GUID instance, void* context);
90 static void vmbus_child_device_destroy(DEVICE_OBJECT* device_obj);
91 static int vmbus_child_device_register(DEVICE_OBJECT* root_device_obj, DEVICE_OBJECT* child_device_obj);
92 static void vmbus_child_device_unregister(DEVICE_OBJECT* child_device_obj);
93 static void vmbus_child_device_get_info(DEVICE_OBJECT *device_obj, DEVICE_INFO *device_info);
94
95 //static ssize_t vmbus_show_class_id(struct device *dev, struct device_attribute *attr, char *buf);
96 //static ssize_t vmbus_show_device_id(struct device *dev, struct device_attribute *attr, char *buf);
97
98 static ssize_t vmbus_show_device_attr(struct device *dev, struct device_attribute *dev_attr, char *buf);
99
100 //
101 // Global
102 //
103
104 // Global logging setting
105
106 //unsigned int vmbus_loglevel= (((VMBUS | VMBUS_DRV)<<16) | DEBUG_LVL_ENTEREXIT);
107 //unsigned int vmbus_loglevel= (ALL_MODULES << 16 | DEBUG_LVL_ENTEREXIT);
108 unsigned int vmbus_loglevel= (ALL_MODULES << 16 | INFO_LVL);
109 EXPORT_SYMBOL(vmbus_loglevel);
110
111 static int vmbus_irq = VMBUS_IRQ;
112
113 // Setup /proc/sys/bus/vmbus/vmbus_loglevel
114 // Allow usage of sysctl cmd to set the logging level
115 static struct ctl_table_header *vmbus_ctl_table_hdr;
116
117 static ctl_table vmbus_dev_ctl_table[] = {
118         { .ctl_name     = 8461,
119           .procname     = "vmbus_loglevel",
120           .data         = &vmbus_loglevel,
121           .maxlen       = sizeof(vmbus_loglevel),
122           .mode         = 0644,
123           .proc_handler = &proc_dointvec },
124         { }
125 };
126
127 static ctl_table vmbus_ctl_table[] = {
128         { .ctl_name     = CTL_DEV,
129           .procname     = "vmbus",
130           .mode         = 0555,
131           .child        = vmbus_dev_ctl_table },
132         { }
133 };
134
135 static ctl_table vmus_root_ctl_table[] = {
136         { .ctl_name     = CTL_BUS,
137           .procname     = "bus",
138           .mode         = 0555,
139           .child        = vmbus_ctl_table },
140         { }
141 };
142
143 #if defined(KERNEL_2_6_5) || defined(KERNEL_2_6_9)
144 #else
145 //
146 // Set up per device attributes in /sys/bus/vmbus/devices/<bus device>
147 //
148 static struct device_attribute vmbus_device_attrs[] = {
149         __ATTR(id, S_IRUGO, vmbus_show_device_attr, NULL),
150         __ATTR(state, S_IRUGO, vmbus_show_device_attr, NULL),
151         __ATTR(class_id, S_IRUGO, vmbus_show_device_attr, NULL),
152         __ATTR(device_id, S_IRUGO, vmbus_show_device_attr, NULL),
153         __ATTR(monitor_id, S_IRUGO, vmbus_show_device_attr, NULL),
154
155         __ATTR(server_monitor_pending, S_IRUGO, vmbus_show_device_attr, NULL),
156         __ATTR(server_monitor_latency, S_IRUGO, vmbus_show_device_attr, NULL),
157         __ATTR(server_monitor_conn_id, S_IRUGO, vmbus_show_device_attr, NULL),
158
159         __ATTR(client_monitor_pending, S_IRUGO, vmbus_show_device_attr, NULL),
160         __ATTR(client_monitor_latency, S_IRUGO, vmbus_show_device_attr, NULL),
161         __ATTR(client_monitor_conn_id, S_IRUGO, vmbus_show_device_attr, NULL),
162
163         __ATTR(out_intr_mask, S_IRUGO, vmbus_show_device_attr, NULL),
164         __ATTR(out_read_index, S_IRUGO, vmbus_show_device_attr, NULL),
165         __ATTR(out_write_index, S_IRUGO, vmbus_show_device_attr, NULL),
166         __ATTR(out_read_bytes_avail, S_IRUGO, vmbus_show_device_attr, NULL),
167         __ATTR(out_write_bytes_avail, S_IRUGO, vmbus_show_device_attr, NULL),
168
169         __ATTR(in_intr_mask, S_IRUGO, vmbus_show_device_attr, NULL),
170         __ATTR(in_read_index, S_IRUGO, vmbus_show_device_attr, NULL),
171         __ATTR(in_write_index, S_IRUGO, vmbus_show_device_attr, NULL),
172         __ATTR(in_read_bytes_avail, S_IRUGO, vmbus_show_device_attr, NULL),
173         __ATTR(in_write_bytes_avail, S_IRUGO, vmbus_show_device_attr, NULL),
174         __ATTR_NULL
175 };
176 #endif
177
178 // The one and only one
179 static struct vmbus_driver_context g_vmbus_drv={
180         .bus.name       = "vmbus",
181         .bus.match      = vmbus_match,
182 #if defined(KERNEL_2_6_5) || defined(KERNEL_2_6_9)
183 #else
184         .bus.shutdown = vmbus_shutdown,
185         .bus.remove = vmbus_remove,
186         .bus.probe      = vmbus_probe,
187         .bus.uevent = vmbus_uevent,
188         .bus.dev_attrs = vmbus_device_attrs,
189 #endif
190 };
191
192 //
193 // Routines
194 //
195
196
197 /*++
198
199 Name:   vmbus_show_device_attr()
200
201 Desc:   Show the device attribute in sysfs. This is invoked when user does a "cat /sys/bus/vmbus/devices/<bus device>/<attr name>"
202
203 --*/
204 static ssize_t vmbus_show_device_attr(struct device *dev, struct device_attribute *dev_attr, char *buf)
205 {
206         struct device_context *device_ctx = device_to_device_context(dev);
207         DEVICE_INFO device_info;
208
209         memset(&device_info, 0, sizeof(DEVICE_INFO));
210
211         vmbus_child_device_get_info(&device_ctx->device_obj, &device_info);
212
213         if (!strcmp(dev_attr->attr.name, "class_id"))
214         {
215                 return sprintf(buf, "{%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x%02x%02x}\n",
216                         device_info.ChannelType.Data[3], device_info.ChannelType.Data[2], device_info.ChannelType.Data[1], device_info.ChannelType.Data[0],
217                         device_info.ChannelType.Data[5], device_info.ChannelType.Data[4],
218                         device_info.ChannelType.Data[7], device_info.ChannelType.Data[6],
219                         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]);
220
221         }
222         else if (!strcmp(dev_attr->attr.name, "device_id"))
223         {
224                 return sprintf(buf, "{%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x%02x%02x}\n",
225                         device_info.ChannelInstance.Data[3], device_info.ChannelInstance.Data[2], device_info.ChannelInstance.Data[1], device_info.ChannelInstance.Data[0],
226                         device_info.ChannelInstance.Data[5], device_info.ChannelInstance.Data[4],
227                         device_info.ChannelInstance.Data[7], device_info.ChannelInstance.Data[6],
228                         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]);
229         }
230         else if (!strcmp(dev_attr->attr.name, "state"))
231         {
232                 return sprintf(buf, "%d\n", device_info.ChannelState);
233         }
234         else if (!strcmp(dev_attr->attr.name, "id"))
235         {
236                 return sprintf(buf, "%d\n", device_info.ChannelId);
237         }
238         else if (!strcmp(dev_attr->attr.name, "out_intr_mask"))
239         {
240                 return sprintf(buf, "%d\n", device_info.Outbound.InterruptMask);
241         }
242         else if (!strcmp(dev_attr->attr.name, "out_read_index"))
243         {
244                 return sprintf(buf, "%d\n", device_info.Outbound.ReadIndex);
245         }
246         else if (!strcmp(dev_attr->attr.name, "out_write_index"))
247         {
248                 return sprintf(buf, "%d\n", device_info.Outbound.WriteIndex);
249         }
250         else if (!strcmp(dev_attr->attr.name, "out_read_bytes_avail"))
251         {
252                 return sprintf(buf, "%d\n", device_info.Outbound.BytesAvailToRead);
253         }
254         else if (!strcmp(dev_attr->attr.name, "out_write_bytes_avail"))
255         {
256                 return sprintf(buf, "%d\n", device_info.Outbound.BytesAvailToWrite);
257         }
258         else if (!strcmp(dev_attr->attr.name, "in_intr_mask"))
259         {
260                 return sprintf(buf, "%d\n", device_info.Inbound.InterruptMask);
261         }
262         else if (!strcmp(dev_attr->attr.name, "in_read_index"))
263         {
264                 return sprintf(buf, "%d\n", device_info.Inbound.ReadIndex);
265         }
266         else if (!strcmp(dev_attr->attr.name, "in_write_index"))
267         {
268                 return sprintf(buf, "%d\n", device_info.Inbound.WriteIndex);
269         }
270         else if (!strcmp(dev_attr->attr.name, "in_read_bytes_avail"))
271         {
272                 return sprintf(buf, "%d\n", device_info.Inbound.BytesAvailToRead);
273         }
274         else if (!strcmp(dev_attr->attr.name, "in_write_bytes_avail"))
275         {
276                 return sprintf(buf, "%d\n", device_info.Inbound.BytesAvailToWrite);
277         }
278         else if (!strcmp(dev_attr->attr.name, "monitor_id"))
279         {
280                 return sprintf(buf, "%d\n", device_info.MonitorId);
281         }
282         else if (!strcmp(dev_attr->attr.name, "server_monitor_pending"))
283         {
284                 return sprintf(buf, "%d\n", device_info.ServerMonitorPending);
285         }
286         else if (!strcmp(dev_attr->attr.name, "server_monitor_latency"))
287         {
288                 return sprintf(buf, "%d\n", device_info.ServerMonitorLatency);
289         }
290         else if (!strcmp(dev_attr->attr.name, "server_monitor_conn_id"))
291         {
292                 return sprintf(buf, "%d\n", device_info.ServerMonitorConnectionId);
293         }
294         else if (!strcmp(dev_attr->attr.name, "client_monitor_pending"))
295         {
296                 return sprintf(buf, "%d\n", device_info.ClientMonitorPending);
297         }
298         else if (!strcmp(dev_attr->attr.name, "client_monitor_latency"))
299         {
300                 return sprintf(buf, "%d\n", device_info.ClientMonitorLatency);
301         }
302         else if (!strcmp(dev_attr->attr.name, "client_monitor_conn_id"))
303         {
304                 return sprintf(buf, "%d\n", device_info.ClientMonitorConnectionId);
305         }
306         else
307         {
308                 return 0;
309         }
310 }
311
312 /*++
313
314 Name:   vmbus_show_class_id()
315
316 Desc:   Show the device class id in sysfs
317
318 --*/
319 //static ssize_t vmbus_show_class_id(struct device *dev, struct device_attribute *attr, char *buf)
320 //{
321 //      struct device_context *device_ctx = device_to_device_context(dev);
322 //      return sprintf(buf, "{%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x%02x%02x}\n",
323 //              device_ctx->class_id[3], device_ctx->class_id[2], device_ctx->class_id[1], device_ctx->class_id[0],
324 //              device_ctx->class_id[5], device_ctx->class_id[4],
325 //              device_ctx->class_id[7], device_ctx->class_id[6],
326 //              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]);
327 //}
328
329 /*++
330
331 Name:   vmbus_show_device_id()
332
333 Desc:   Show the device instance id in sysfs
334
335 --*/
336 //static ssize_t vmbus_show_device_id(struct device *dev, struct device_attribute *attr, char *buf)
337 //{
338 //      struct device_context *device_ctx = device_to_device_context(dev);
339 //      return sprintf(buf, "{%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x%02x%02x}\n",
340 //              device_ctx->device_id[3], device_ctx->device_id[2], device_ctx->device_id[1], device_ctx->device_id[0],
341 //              device_ctx->device_id[5], device_ctx->device_id[4],
342 //              device_ctx->device_id[7], device_ctx->device_id[6],
343 //              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]);
344 //}
345
346 /*++
347
348 Name:   vmbus_bus_init()
349
350 Desc:   Main vmbus driver initialization routine. Here, we
351                 - initialize the vmbus driver context
352                 - setup various driver entry points
353                 - invoke the vmbus hv main init routine
354                 - get the irq resource
355                 - invoke the vmbus to add the vmbus root device
356                 - setup the vmbus root device
357                 - retrieve the channel offers
358 --*/
359 int vmbus_bus_init(PFN_DRIVERINITIALIZE pfn_drv_init)
360 {
361         int ret=0;
362         unsigned int vector=0;
363
364         struct vmbus_driver_context *vmbus_drv_ctx=&g_vmbus_drv;
365         VMBUS_DRIVER_OBJECT *vmbus_drv_obj=&g_vmbus_drv.drv_obj;
366
367         struct device_context *dev_ctx=&g_vmbus_drv.device_ctx;
368
369         DPRINT_ENTER(VMBUS_DRV);
370
371         // Set this up to allow lower layer to callback to add/remove child devices on the bus
372         vmbus_drv_obj->OnChildDeviceCreate = vmbus_child_device_create;
373         vmbus_drv_obj->OnChildDeviceDestroy = vmbus_child_device_destroy;
374         vmbus_drv_obj->OnChildDeviceAdd = vmbus_child_device_register;
375         vmbus_drv_obj->OnChildDeviceRemove = vmbus_child_device_unregister;
376
377         // Call to bus driver to initialize
378         ret = pfn_drv_init(&vmbus_drv_obj->Base);
379         if (ret != 0)
380         {
381                 DPRINT_ERR(VMBUS_DRV, "Unable to initialize vmbus (%d)", ret);
382                 goto cleanup;
383         }
384
385         // Sanity checks
386         if (!vmbus_drv_obj->Base.OnDeviceAdd)
387         {
388                 DPRINT_ERR(VMBUS_DRV, "OnDeviceAdd() routine not set");
389                 ret = -1;
390                 goto cleanup;
391         }
392
393         vmbus_drv_ctx->bus.name = vmbus_drv_obj->Base.name;
394
395         // Initialize the bus context
396         tasklet_init(&vmbus_drv_ctx->msg_dpc, vmbus_msg_dpc, (unsigned long)vmbus_drv_obj);
397         tasklet_init(&vmbus_drv_ctx->event_dpc, vmbus_event_dpc, (unsigned long)vmbus_drv_obj);
398
399         // Now, register the bus driver with LDM
400         bus_register(&vmbus_drv_ctx->bus);
401
402         // Get the interrupt resource
403 #ifdef KERNEL_2_6_27
404         ret = request_irq(vmbus_irq,
405                           vmbus_isr,
406                           IRQF_SAMPLE_RANDOM,
407                           vmbus_drv_obj->Base.name,
408                           NULL);
409 #else
410         ret = request_irq(vmbus_irq,
411                           vmbus_isr,
412                           SA_SAMPLE_RANDOM,
413                           vmbus_drv_obj->Base.name,
414                           NULL);
415 #endif
416
417         if (ret != 0)
418         {
419                 DPRINT_ERR(VMBUS_DRV, "ERROR - Unable to request IRQ %d", vmbus_irq);
420
421                 bus_unregister(&vmbus_drv_ctx->bus);
422
423                 ret = -1;
424                 goto cleanup;
425         }
426 #ifdef KERNEL_2_6_27
427         vector = VMBUS_IRQ_VECTOR;
428 #else
429 #if X2V_LINUX
430         vector = vmbus_irq + FIRST_DEVICE_VECTOR - 2;
431 #else
432         vector = vmbus_irq + FIRST_EXTERNAL_VECTOR;
433 #endif
434 #endif
435
436         DPRINT_INFO(VMBUS_DRV, "irq 0x%x vector 0x%x", vmbus_irq, vector);
437
438         // Call to bus driver to add the root device
439         memset(dev_ctx, 0, sizeof(struct device_context));
440
441         ret = vmbus_drv_obj->Base.OnDeviceAdd(&dev_ctx->device_obj, &vector);
442         if (ret != 0)
443         {
444                 DPRINT_ERR(VMBUS_DRV, "ERROR - Unable to add vmbus root device");
445
446                 free_irq(vmbus_irq, NULL);
447
448                 bus_unregister(&vmbus_drv_ctx->bus);
449
450                 ret = -1;
451                 goto cleanup;
452         }
453         //strcpy(dev_ctx->device.bus_id, dev_ctx->device_obj.name);
454         sprintf(dev_ctx->device.bus_id, "vmbus_0_0");
455         memcpy(&dev_ctx->class_id, &dev_ctx->device_obj.deviceType, sizeof(GUID));
456         memcpy(&dev_ctx->device_id, &dev_ctx->device_obj.deviceInstance, sizeof(GUID));
457
458         // No need to bind a driver to the root device.
459         dev_ctx->device.parent = NULL;
460         dev_ctx->device.bus = &vmbus_drv_ctx->bus; //NULL; // vmbus_remove() does not get invoked
461
462         // Setup the device dispatch table
463         dev_ctx->device.release = vmbus_bus_release;
464
465         // Setup the bus as root device
466         device_register(&dev_ctx->device);
467
468         vmbus_drv_obj->GetChannelOffers();
469
470 cleanup:
471         DPRINT_EXIT(VMBUS_DRV);
472
473         return ret;
474 }
475
476
477 /*++
478
479 Name:   vmbus_bus_exit()
480
481 Desc:   Terminate the vmbus driver. This routine is opposite of vmbus_bus_init()
482
483 --*/
484 void vmbus_bus_exit(void)
485 {
486         VMBUS_DRIVER_OBJECT *vmbus_drv_obj=&g_vmbus_drv.drv_obj;
487         struct vmbus_driver_context *vmbus_drv_ctx=&g_vmbus_drv;
488
489         struct device_context *dev_ctx=&g_vmbus_drv.device_ctx;
490
491         DPRINT_ENTER(VMBUS_DRV);
492
493         // Remove the root device
494         if (vmbus_drv_obj->Base.OnDeviceRemove)
495                 vmbus_drv_obj->Base.OnDeviceRemove(&dev_ctx->device_obj);
496
497         if (vmbus_drv_obj->Base.OnCleanup)
498                 vmbus_drv_obj->Base.OnCleanup(&vmbus_drv_obj->Base);
499
500         // Unregister the root bus device
501         device_unregister(&dev_ctx->device);
502
503         bus_unregister(&vmbus_drv_ctx->bus);
504
505         free_irq(vmbus_irq, NULL);
506
507         tasklet_kill(&vmbus_drv_ctx->msg_dpc);
508         tasklet_kill(&vmbus_drv_ctx->event_dpc);
509
510         DPRINT_EXIT(VMBUS_DRV);
511
512         return;
513 }
514
515 /*++
516
517 Name:   vmbus_child_driver_register()
518
519 Desc:   Register a vmbus's child driver
520
521 --*/
522 void vmbus_child_driver_register(struct driver_context* driver_ctx)
523 {
524         VMBUS_DRIVER_OBJECT *vmbus_drv_obj=&g_vmbus_drv.drv_obj;
525
526         DPRINT_ENTER(VMBUS_DRV);
527
528         DPRINT_INFO(VMBUS_DRV, "child driver (%p) registering - name %s", driver_ctx, driver_ctx->driver.name);
529
530         // The child driver on this vmbus
531         driver_ctx->driver.bus = &g_vmbus_drv.bus;
532
533         driver_register(&driver_ctx->driver);
534
535         vmbus_drv_obj->GetChannelOffers();
536
537         DPRINT_EXIT(VMBUS_DRV);
538 }
539
540 EXPORT_SYMBOL(vmbus_child_driver_register);
541
542 /*++
543
544 Name:   vmbus_child_driver_unregister()
545
546 Desc:   Unregister a vmbus's child driver
547
548 --*/
549 void vmbus_child_driver_unregister(struct driver_context* driver_ctx)
550 {
551         DPRINT_ENTER(VMBUS_DRV);
552
553         DPRINT_INFO(VMBUS_DRV, "child driver (%p) unregistering - name %s", driver_ctx, driver_ctx->driver.name);
554
555         driver_unregister(&driver_ctx->driver);
556
557         driver_ctx->driver.bus = NULL;
558
559         DPRINT_EXIT(VMBUS_DRV);
560 }
561
562 EXPORT_SYMBOL(vmbus_child_driver_unregister);
563
564 /*++
565
566 Name:   vmbus_get_interface()
567
568 Desc:   Get the vmbus channel interface. This is invoked by child/client driver that sits
569                 above vmbus
570 --*/
571 void vmbus_get_interface(VMBUS_CHANNEL_INTERFACE *interface)
572 {
573         VMBUS_DRIVER_OBJECT *vmbus_drv_obj=&g_vmbus_drv.drv_obj;
574
575         vmbus_drv_obj->GetChannelInterface(interface);
576 }
577
578 EXPORT_SYMBOL(vmbus_get_interface);
579
580
581 /*++
582
583 Name:   vmbus_child_device_get_info()
584
585 Desc:   Get the vmbus child device info. This is invoked to display various device attributes in sysfs.
586 --*/
587 static void vmbus_child_device_get_info(DEVICE_OBJECT *device_obj, DEVICE_INFO *device_info)
588 {
589         VMBUS_DRIVER_OBJECT *vmbus_drv_obj=&g_vmbus_drv.drv_obj;
590
591         vmbus_drv_obj->GetChannelInfo(device_obj, device_info);
592 }
593
594
595 /*++
596
597 Name:   vmbus_child_device_create()
598
599 Desc:   Creates and registers a new child device on the vmbus.
600
601 --*/
602 static DEVICE_OBJECT* vmbus_child_device_create(GUID type, GUID instance, void* context)
603 {
604         struct device_context *child_device_ctx;
605         DEVICE_OBJECT* child_device_obj;
606
607         DPRINT_ENTER(VMBUS_DRV);
608
609         // Allocate the new child device
610         child_device_ctx = kzalloc(sizeof(struct device_context), GFP_KERNEL);
611         if (!child_device_ctx)
612         {
613                 DPRINT_ERR(VMBUS_DRV, "unable to allocate device_context for child device");
614                 DPRINT_EXIT(VMBUS_DRV);
615
616                 return NULL;
617         }
618
619         DPRINT_DBG(VMBUS_DRV, "child device (%p) allocated - "
620                 "type {%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x%02x%02x},"
621                 "id {%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x%02x%02x}",
622                 &child_device_ctx->device,
623                 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],
624                 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]);
625
626         child_device_obj = &child_device_ctx->device_obj;
627         child_device_obj->context = context;
628         memcpy(&child_device_obj->deviceType, &type, sizeof(GUID));
629         memcpy(&child_device_obj->deviceInstance, &instance, sizeof(GUID));
630
631         memcpy(&child_device_ctx->class_id, &type, sizeof(GUID));
632         memcpy(&child_device_ctx->device_id, &instance, sizeof(GUID));
633
634         DPRINT_EXIT(VMBUS_DRV);
635
636         return child_device_obj;
637 }
638
639 /*++
640
641 Name:   vmbus_child_device_register()
642
643 Desc:   Register the child device on the specified bus
644
645 --*/
646 static int vmbus_child_device_register(DEVICE_OBJECT* root_device_obj, DEVICE_OBJECT* child_device_obj)
647 {
648         int ret=0;
649         struct device_context *root_device_ctx = to_device_context(root_device_obj);
650         struct device_context *child_device_ctx = to_device_context(child_device_obj);
651         static int device_num=0;
652
653         DPRINT_ENTER(VMBUS_DRV);
654
655         DPRINT_DBG(VMBUS_DRV, "child device (%p) registering", child_device_ctx);
656         //
657         // Make sure we are not registered already
658         //
659         if (child_device_ctx->device.bus_id[0] != '\0')
660         {
661                 DPRINT_ERR(VMBUS_DRV, "child device (%p) already registered - busid %s", child_device_ctx, child_device_ctx->device.bus_id);
662
663                 ret = -1;
664                 goto Cleanup;
665         }
666
667         // Set the device bus id. Otherwise, device_register()will fail.
668         sprintf(child_device_ctx->device.bus_id, "vmbus_0_%d", InterlockedIncrement(&device_num));
669
670         // The new device belongs to this bus
671         child_device_ctx->device.bus = &g_vmbus_drv.bus; //device->dev.bus;
672         child_device_ctx->device.parent = &root_device_ctx->device;
673         child_device_ctx->device.release = vmbus_device_release;
674
675         // Register with the LDM. This will kick off the driver/device binding...which will
676         // eventually call vmbus_match() and vmbus_probe()
677         ret = device_register(&child_device_ctx->device);
678
679         // vmbus_probe() error does not get propergate to device_register().
680         ret = child_device_ctx->probe_error;
681
682         if (ret)
683                 DPRINT_ERR(VMBUS_DRV, "unable to register child device (%p) (%d)", &child_device_ctx->device);
684         else
685                 DPRINT_INFO(VMBUS_DRV, "child device (%p) registered", &child_device_ctx->device);
686
687 Cleanup:
688         DPRINT_EXIT(VMBUS_DRV);
689
690         return ret;
691 }
692
693 /*++
694
695 Name:   vmbus_child_device_unregister()
696
697 Desc:   Remove the specified child device from the vmbus.
698
699 --*/
700 static void vmbus_child_device_unregister(DEVICE_OBJECT* device_obj)
701 {
702         struct device_context *device_ctx = to_device_context(device_obj);
703
704         DPRINT_ENTER(VMBUS_DRV);
705
706         DPRINT_INFO(VMBUS_DRV, "unregistering child device (%p)", &device_ctx->device);
707
708         // Kick off the process of unregistering the device.
709         // This will call vmbus_remove() and eventually vmbus_device_release()
710         device_unregister(&device_ctx->device);
711
712         DPRINT_INFO(VMBUS_DRV, "child device (%p) unregistered", &device_ctx->device);
713
714         DPRINT_EXIT(VMBUS_DRV);
715 }
716
717
718 /*++
719
720 Name:   vmbus_child_device_destroy()
721
722 Desc:   Destroy the specified child device on the vmbus.
723
724 --*/
725 static void vmbus_child_device_destroy(DEVICE_OBJECT* device_obj)
726 {
727         DPRINT_ENTER(VMBUS_DRV);
728
729         DPRINT_EXIT(VMBUS_DRV);
730 }
731
732 /*++
733
734 Name:   vmbus_uevent()
735
736 Desc:   This routine is invoked when a device is added or removed on the vmbus to generate a uevent to udev in the
737                 userspace. The udev will then look at its rule and the uevent generated here to load the appropriate driver
738
739 --*/
740 #if defined(KERNEL_2_6_5) || defined(KERNEL_2_6_9)
741 #elif defined(KERNEL_2_6_27)
742 static int vmbus_uevent(struct device *device, struct kobj_uevent_env *env)
743 {
744         struct device_context *device_ctx = device_to_device_context(device);
745         int i=0;
746         int len=0;
747         int ret;
748
749         DPRINT_ENTER(VMBUS_DRV);
750
751         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}",
752                 device_ctx->class_id.Data[3], device_ctx->class_id.Data[2], device_ctx->class_id.Data[1], device_ctx->class_id.Data[0],
753                 device_ctx->class_id.Data[5], device_ctx->class_id.Data[4],
754                 device_ctx->class_id.Data[7], device_ctx->class_id.Data[6],
755                 device_ctx->class_id.Data[8], device_ctx->class_id.Data[9], device_ctx->class_id.Data[10], device_ctx->class_id.Data[11],
756                 device_ctx->class_id.Data[12], device_ctx->class_id.Data[13], device_ctx->class_id.Data[14], device_ctx->class_id.Data[15]);
757
758         env->envp_idx = i;
759         env->buflen = len;
760         ret = add_uevent_var(env,
761                 "VMBUS_DEVICE_CLASS_GUID={%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x%02x%02x}",
762                 device_ctx->class_id.Data[3], device_ctx->class_id.Data[2], device_ctx->class_id.Data[1], device_ctx->class_id.Data[0],
763                 device_ctx->class_id.Data[5], device_ctx->class_id.Data[4],
764                 device_ctx->class_id.Data[7], device_ctx->class_id.Data[6],
765                 device_ctx->class_id.Data[8], device_ctx->class_id.Data[9], device_ctx->class_id.Data[10], device_ctx->class_id.Data[11],
766                 device_ctx->class_id.Data[12], device_ctx->class_id.Data[13], device_ctx->class_id.Data[14], device_ctx->class_id.Data[15]);
767
768         if (ret)
769         {
770                 return ret;
771         }
772
773         ret = add_uevent_var(env,
774                 "VMBUS_DEVICE_DEVICE_GUID={%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x%02x%02x}",
775                 device_ctx->device_id.Data[3], device_ctx->device_id.Data[2], device_ctx->device_id.Data[1], device_ctx->device_id.Data[0],
776                 device_ctx->device_id.Data[5], device_ctx->device_id.Data[4],
777                 device_ctx->device_id.Data[7], device_ctx->device_id.Data[6],
778                 device_ctx->device_id.Data[8], device_ctx->device_id.Data[9], device_ctx->device_id.Data[10], device_ctx->device_id.Data[11],
779                 device_ctx->device_id.Data[12], device_ctx->device_id.Data[13], device_ctx->device_id.Data[14], device_ctx->device_id.Data[15]);
780
781         if (ret)
782         {
783                 return ret;
784         }
785
786         env->envp[env->envp_idx] = NULL;
787
788         DPRINT_EXIT(VMBUS_DRV);
789
790         return 0;
791 }
792
793 #else
794 static int vmbus_uevent(struct device *device, char **envp, int num_envp, char *buffer, int buffer_size)
795 {
796         struct device_context *device_ctx = device_to_device_context(device);
797         int i=0;
798         int len=0;
799         int ret;
800
801         DPRINT_ENTER(VMBUS_DRV);
802
803         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}",
804                 device_ctx->class_id.Data[3], device_ctx->class_id.Data[2], device_ctx->class_id.Data[1], device_ctx->class_id.Data[0],
805                 device_ctx->class_id.Data[5], device_ctx->class_id.Data[4],
806                 device_ctx->class_id.Data[7], device_ctx->class_id.Data[6],
807                 device_ctx->class_id.Data[8], device_ctx->class_id.Data[9], device_ctx->class_id.Data[10], device_ctx->class_id.Data[11],
808                 device_ctx->class_id.Data[12], device_ctx->class_id.Data[13], device_ctx->class_id.Data[14], device_ctx->class_id.Data[15]);
809
810         ret = add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &len,
811                 "VMBUS_DEVICE_CLASS_GUID={%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x%02x%02x}",
812                 device_ctx->class_id.Data[3], device_ctx->class_id.Data[2], device_ctx->class_id.Data[1], device_ctx->class_id.Data[0],
813                 device_ctx->class_id.Data[5], device_ctx->class_id.Data[4],
814                 device_ctx->class_id.Data[7], device_ctx->class_id.Data[6],
815                 device_ctx->class_id.Data[8], device_ctx->class_id.Data[9], device_ctx->class_id.Data[10], device_ctx->class_id.Data[11],
816                 device_ctx->class_id.Data[12], device_ctx->class_id.Data[13], device_ctx->class_id.Data[14], device_ctx->class_id.Data[15]);
817
818         if (ret)
819         {
820                 return ret;
821         }
822
823         ret = add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &len,
824                 "VMBUS_DEVICE_DEVICE_GUID={%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x%02x%02x}",
825                 device_ctx->device_id.Data[3], device_ctx->device_id.Data[2], device_ctx->device_id.Data[1], device_ctx->device_id.Data[0],
826                 device_ctx->device_id.Data[5], device_ctx->device_id.Data[4],
827                 device_ctx->device_id.Data[7], device_ctx->device_id.Data[6],
828                 device_ctx->device_id.Data[8], device_ctx->device_id.Data[9], device_ctx->device_id.Data[10], device_ctx->device_id.Data[11],
829                 device_ctx->device_id.Data[12], device_ctx->device_id.Data[13], device_ctx->device_id.Data[14], device_ctx->device_id.Data[15]);
830
831         if (ret)
832         {
833                 return ret;
834         }
835
836         envp[i] = NULL;
837
838         DPRINT_EXIT(VMBUS_DRV);
839
840         return 0;
841 }
842 #endif
843
844 /*++
845
846 Name:   vmbus_match()
847
848 Desc:   Attempt to match the specified device to the specified driver
849
850 --*/
851 static int vmbus_match(struct device *device, struct device_driver *driver)
852 {
853         int match=0;
854         struct driver_context *driver_ctx = driver_to_driver_context(driver);
855         struct device_context *device_ctx = device_to_device_context(device);
856
857         DPRINT_ENTER(VMBUS_DRV);
858
859         // We found our driver ?
860         if (memcmp(&device_ctx->class_id, &driver_ctx->class_id, sizeof(GUID)) == 0)
861         {
862                 // !! NOTE: The driver_ctx is not a vmbus_drv_ctx. We typecast it here to access the
863                 // DRIVER_OBJECT field
864                 struct vmbus_driver_context *vmbus_drv_ctx = (struct vmbus_driver_context*)driver_ctx;
865                 device_ctx->device_obj.Driver = &vmbus_drv_ctx->drv_obj.Base;
866                 DPRINT_INFO(VMBUS_DRV, "device object (%p) set to driver object (%p)", &device_ctx->device_obj, device_ctx->device_obj.Driver);
867
868                 match = 1;
869         }
870
871         DPRINT_EXIT(VMBUS_DRV);
872
873         return match;
874 }
875
876
877 /*++
878
879 Name:   vmbus_probe_failed_cb()
880
881 Desc:   Callback when a driver probe failed in vmbus_probe(). We need a callback because
882                 we cannot invoked device_unregister() inside vmbus_probe() since vmbus_probe() may be
883                 invoked inside device_register() i.e. we cannot call device_unregister() inside
884                 device_register()
885 --*/
886 #ifdef KERNEL_2_6_27
887 static void vmbus_probe_failed_cb(struct work_struct *context)
888 #else
889 static void vmbus_probe_failed_cb(void* context)
890 #endif
891 {
892         struct device_context *device_ctx = (struct device_context*)context;
893
894
895         DPRINT_ENTER(VMBUS_DRV);
896
897         // Kick off the process of unregistering the device.
898         // This will call vmbus_remove() and eventually vmbus_device_release()
899         device_unregister(&device_ctx->device);
900
901         //put_device(&device_ctx->device);
902         DPRINT_EXIT(VMBUS_DRV);
903 }
904
905
906 /*++
907
908 Name:   vmbus_probe()
909
910 Desc:   Add the new vmbus's child device
911
912 --*/
913 static int vmbus_probe(struct device *child_device)
914 {
915         int ret=0;
916         struct driver_context *driver_ctx = driver_to_driver_context(child_device->driver);
917         struct device_context *device_ctx = device_to_device_context(child_device);
918
919         DPRINT_ENTER(VMBUS_DRV);
920
921         // Let the specific open-source driver handles the probe if it can
922         if (driver_ctx->probe)
923         {
924                 ret = device_ctx->probe_error = driver_ctx->probe(child_device);
925                 if (ret != 0)
926                 {
927                         DPRINT_ERR(VMBUS_DRV, "probe() failed for device %s (%p) on driver %s (%d)...", child_device->bus_id, child_device, child_device->driver->name, ret);
928
929 #ifdef KERNEL_2_6_27
930                         INIT_WORK(&device_ctx->probe_failed_work_item, vmbus_probe_failed_cb);
931 #else
932                         INIT_WORK(&device_ctx->probe_failed_work_item, vmbus_probe_failed_cb, device_ctx);
933 #endif
934                         schedule_work(&device_ctx->probe_failed_work_item);
935                 }
936         }
937         else
938         {
939                 DPRINT_ERR(VMBUS_DRV, "probe() method not set for driver - %s", child_device->driver->name);
940                 ret = -1;
941         }
942
943         DPRINT_EXIT(VMBUS_DRV);
944         return ret;
945 }
946
947
948 /*++
949
950 Name:   vmbus_remove()
951
952 Desc:   Remove a vmbus device
953
954 --*/
955 static int vmbus_remove(struct device *child_device)
956 {
957         int ret=0;
958         struct driver_context *driver_ctx;
959
960         DPRINT_ENTER(VMBUS_DRV);
961
962         // Special case root bus device
963         if (child_device->parent == NULL)
964         {
965                 // No-op since it is statically defined and handle in vmbus_bus_exit()
966                 DPRINT_EXIT(VMBUS_DRV);
967                 return 0;
968         }
969
970         if (child_device->driver)
971         {
972                 driver_ctx = driver_to_driver_context(child_device->driver);
973
974                 // Let the specific open-source driver handles the removal if it can
975                 if (driver_ctx->remove)
976                 {
977                         ret = driver_ctx->remove(child_device);
978                 }
979                 else
980                 {
981                         DPRINT_ERR(VMBUS_DRV, "remove() method not set for driver - %s", child_device->driver->name);
982                         ret = -1;
983                 }
984         }
985         else
986         {
987
988         }
989
990         DPRINT_EXIT(VMBUS_DRV);
991
992         return 0;
993 }
994
995 /*++
996
997 Name:   vmbus_shutdown()
998
999 Desc:   Shutdown a vmbus device
1000
1001 --*/
1002 static void vmbus_shutdown(struct device *child_device)
1003 {
1004         struct driver_context *driver_ctx;
1005
1006         DPRINT_ENTER(VMBUS_DRV);
1007
1008         // Special case root bus device
1009         if (child_device->parent == NULL)
1010         {
1011                 // No-op since it is statically defined and handle in vmbus_bus_exit()
1012                 DPRINT_EXIT(VMBUS_DRV);
1013                 return;
1014         }
1015
1016         // The device may not be attached yet
1017         if (!child_device->driver)
1018         {
1019                 DPRINT_EXIT(VMBUS_DRV);
1020                 return;
1021         }
1022
1023         driver_ctx = driver_to_driver_context(child_device->driver);
1024
1025         // Let the specific open-source driver handles the removal if it can
1026         if (driver_ctx->shutdown)
1027         {
1028                 driver_ctx->shutdown(child_device);
1029         }
1030
1031         DPRINT_EXIT(VMBUS_DRV);
1032
1033         return;
1034 }
1035
1036 /*++
1037
1038 Name:   vmbus_bus_release()
1039
1040 Desc:   Final callback release of the vmbus root device
1041
1042 --*/
1043 static void vmbus_bus_release(struct device *device)
1044 {
1045         DPRINT_ENTER(VMBUS_DRV);
1046         DPRINT_EXIT(VMBUS_DRV);
1047 }
1048
1049 /*++
1050
1051 Name:   vmbus_device_release()
1052
1053 Desc:   Final callback release of the vmbus child device
1054
1055 --*/
1056 static void vmbus_device_release(struct device *device)
1057 {
1058         struct device_context *device_ctx = device_to_device_context(device);
1059
1060         DPRINT_ENTER(VMBUS_DRV);
1061
1062         //vmbus_child_device_destroy(&device_ctx->device_obj);
1063         kfree(device_ctx);
1064
1065         // !!DO NOT REFERENCE device_ctx anymore at this point!!
1066
1067         DPRINT_EXIT(VMBUS_DRV);
1068
1069         return;
1070 }
1071
1072 /*++
1073
1074 Name:   vmbus_msg_dpc()
1075
1076 Desc:   Tasklet routine to handle hypervisor messages
1077
1078 --*/
1079 static void vmbus_msg_dpc(unsigned long data)
1080 {
1081         VMBUS_DRIVER_OBJECT* vmbus_drv_obj = (VMBUS_DRIVER_OBJECT*)data;
1082
1083         DPRINT_ENTER(VMBUS_DRV);
1084
1085         ASSERT(vmbus_drv_obj->OnMsgDpc != NULL);
1086
1087         // Call to bus driver to handle interrupt
1088         vmbus_drv_obj->OnMsgDpc(&vmbus_drv_obj->Base);
1089
1090         DPRINT_EXIT(VMBUS_DRV);
1091 }
1092
1093 /*++
1094
1095 Name:   vmbus_msg_dpc()
1096
1097 Desc:   Tasklet routine to handle hypervisor events
1098
1099 --*/
1100 static void vmbus_event_dpc(unsigned long data)
1101 {
1102         VMBUS_DRIVER_OBJECT* vmbus_drv_obj = (VMBUS_DRIVER_OBJECT*)data;
1103
1104         DPRINT_ENTER(VMBUS_DRV);
1105
1106         ASSERT(vmbus_drv_obj->OnEventDpc != NULL);
1107
1108         // Call to bus driver to handle interrupt
1109         vmbus_drv_obj->OnEventDpc(&vmbus_drv_obj->Base);
1110
1111         DPRINT_EXIT(VMBUS_DRV);
1112 }
1113
1114 /*++
1115
1116 Name:   vmbus_msg_dpc()
1117
1118 Desc:   ISR routine
1119
1120 --*/
1121 #ifdef KERNEL_2_6_27
1122 static irqreturn_t vmbus_isr(int irq, void* dev_id)
1123 #else
1124 static int vmbus_isr(int irq, void* dev_id, struct pt_regs *regs)
1125 #endif
1126 {
1127         int ret=0;
1128         VMBUS_DRIVER_OBJECT* vmbus_driver_obj = &g_vmbus_drv.drv_obj;
1129
1130         DPRINT_ENTER(VMBUS_DRV);
1131
1132         ASSERT(vmbus_driver_obj->OnIsr != NULL);
1133
1134         // Call to bus driver to handle interrupt
1135         ret = vmbus_driver_obj->OnIsr(&vmbus_driver_obj->Base);
1136
1137         // Schedules a dpc if necessary
1138         if (ret > 0)
1139         {
1140                 if (test_bit(0, (unsigned long*)&ret))
1141                 {
1142                         tasklet_schedule(&g_vmbus_drv.msg_dpc);
1143                 }
1144
1145                 if (test_bit(1, (unsigned long*)&ret))
1146                 {
1147                         tasklet_schedule(&g_vmbus_drv.event_dpc);
1148                 }
1149
1150                 DPRINT_EXIT(VMBUS_DRV);
1151                 return IRQ_HANDLED;
1152         }
1153         else
1154         {
1155                 DPRINT_EXIT(VMBUS_DRV);
1156                 return IRQ_NONE;
1157         }
1158 }
1159
1160 MODULE_LICENSE("GPL");
1161
1162
1163 /*++
1164
1165 Name:   vmbus_init()
1166
1167 Desc:   Main vmbus driver entry routine
1168
1169 --*/
1170 static int __init vmbus_init(void)
1171 {
1172         int ret=0;
1173
1174         DPRINT_ENTER(VMBUS_DRV);
1175
1176         DPRINT_INFO(VMBUS_DRV,
1177                 "Vmbus initializing.... current log level 0x%x (%x,%x)",
1178                 vmbus_loglevel, HIWORD(vmbus_loglevel), LOWORD(vmbus_loglevel));
1179 #ifdef KERNEL_2_6_27
1180 //Todo: it is used for loglevel, to be ported to new kernel.
1181 #else
1182         vmbus_ctl_table_hdr = register_sysctl_table(vmus_root_ctl_table, 0);
1183         if (!vmbus_ctl_table_hdr)
1184         {
1185                 DPRINT_EXIT(VMBUS_DRV);
1186                 return -ENOMEM;
1187         }
1188 #endif
1189
1190         ret = vmbus_bus_init(VmbusInitialize);
1191
1192         DPRINT_EXIT(VMBUS_DRV);
1193         return ret;
1194 }
1195
1196
1197
1198 /*++
1199
1200 Name:   vmbus_init()
1201
1202 Desc:   Main vmbus driver exit routine
1203
1204 --*/
1205 static void __exit vmbus_exit(void)
1206 {
1207         DPRINT_ENTER(VMBUS_DRV);
1208
1209         vmbus_bus_exit();
1210 #ifdef KERNEL_2_6_27
1211 //Todo: it is used for loglevel, to be ported to new kernel.
1212 #else
1213         unregister_sysctl_table(vmbus_ctl_table_hdr);
1214 #endif
1215         DPRINT_EXIT(VMBUS_DRV);
1216
1217         return;
1218 }
1219
1220 #if defined(KERNEL_2_6_5)
1221 #else
1222 module_param(vmbus_irq, int, S_IRUGO);
1223 module_param(vmbus_loglevel, int, S_IRUGO);
1224 #endif
1225
1226 module_init(vmbus_init);
1227 module_exit(vmbus_exit);
1228 // eof