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