Merge branch 'dev' of 106.109.8.71:/srv/git/dbi into dev
[kernel/swap-modules.git] / driver / device_driver.c
1 ////////////////////////////////////////////////////////////////////////////////////
2 //
3 //      FILE:           device_driver.c
4 //
5 //      DESCRIPTION:
6 //      This file is C source for SWAP driver.
7 //
8 //      SEE ALSO:       device_driver.h
9 //      AUTHOR:         L.Komkov, S.Dianov, S.Grekhov, A.Gerenkov
10 //      COMPANY NAME:   Samsung Research Center in Moscow
11 //      DEPT NAME:      Advanced Software Group 
12 //      CREATED:        2008.02.15
13 //      VERSION:        1.0
14 //      REVISION DATE:  2008.12.03
15 //
16 ////////////////////////////////////////////////////////////////////////////////////
17
18 #include "module.h"
19 #include "device_driver.h"      // device driver
20 #include "handlers_core.h"
21 #include <linux/notifier.h>
22
23 #ifdef OVERHEAD_DEBUG
24 extern unsigned long swap_sum_time;
25 extern unsigned long swap_sum_hit;
26 #endif
27
28 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 17)
29 static BLOCKING_NOTIFIER_HEAD(swap_notifier_list);
30 #endif
31 pid_t gl_nNotifyTgid;
32 EXPORT_SYMBOL_GPL(gl_nNotifyTgid);
33
34 DECLARE_WAIT_QUEUE_HEAD (notification_waiters_queue);
35 volatile unsigned notification_count;
36
37 static int device_mmap (struct file *filp, struct vm_area_struct *vma);
38 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36)
39 static int device_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg);
40 #else
41 static long device_ioctl (struct file *file, unsigned int cmd, unsigned long arg);
42 #endif
43 static int device_open(struct inode *, struct file *);
44 static int device_release(struct inode *, struct file *);
45 static ssize_t device_read(struct file *, char *, size_t, loff_t *);
46 static ssize_t device_write(struct file *, const char *, size_t, loff_t *);
47
48 static int gl_nDeviceOpened = 0;
49 static struct file_operations device_fops = {
50         .owner = THIS_MODULE,
51         .mmap = device_mmap,
52 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36)
53         .ioctl = device_ioctl,
54 #else
55         .unlocked_ioctl = device_ioctl,
56 #endif
57         .read = device_read,
58         .write = device_write,
59         .open = device_open,
60         .release = device_release
61 };
62
63 typedef void (* dbi_module_callback)();
64
65 int device_init (void)
66 {
67         int nReserved = 0;
68         nReserved = register_chrdev(0, device_name, &device_fops);
69         if(nReserved < 0)
70         {
71                 unregister_chrdev(nReserved, device_name);
72                 EPRINTF("Cannot register character device!");
73                 return -1;
74         }
75         EPRINTF("New device node with major number [%d], was created\n", nReserved);
76         device_major = nReserved;
77         return 0;
78 }
79
80 void device_down (void)
81 {
82         unregister_chrdev(device_major, device_name);
83 }
84
85 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 17)
86 void swap_register_notify (struct notifier_block *nb)
87 {
88         blocking_notifier_chain_register(&swap_notifier_list, nb);
89 }
90 EXPORT_SYMBOL_GPL(swap_register_notify);
91
92 void swap_unregister_notify (struct notifier_block *nb)
93 {
94         blocking_notifier_chain_unregister(&swap_notifier_list, nb);
95 }
96 EXPORT_SYMBOL_GPL(swap_unregister_notify);
97 #endif
98
99 void notify_user (event_id_t event_id)
100 {
101         ec_info.events_counters[event_id] += 1;
102
103         if (EVENT_EC_PROBE_RECORD == event_id)
104         {
105                 // EC_PROBE_RECORD events happen to often. To reduce overhead user
106                 // space will be notified only once per each EVENTS_AGGREGATION_USEC
107                 static uint64_t timestamp_usec = 0;
108
109                 uint64_t current_usec;
110                 uint64_t delta_usec;
111
112                 struct timeval tv;
113
114                 do_gettimeofday (&tv);
115                 current_usec = 1000000ULL * (unsigned) tv.tv_sec + (unsigned) tv.tv_usec;
116
117                 if (current_usec < timestamp_usec)
118                 {
119                         // Note: time from do_gettimeofday() may go backward
120                         EPRINTF ("current_usec=%llu timestamp_usec=%llu", current_usec, timestamp_usec);
121                 }
122                 else
123                 {
124                         delta_usec = current_usec - timestamp_usec;
125                         if (EVENTS_AGGREGATION_USEC > delta_usec)
126                         {
127                                 // wait the time left
128 #if defined(__DEBUG)
129                                 unsigned UNUSED left_usec = EVENTS_AGGREGATION_USEC - delta_usec;
130 #endif /* defined(__DEBUG) */
131                                 return; // supress notification
132                         }
133                 }
134                 timestamp_usec = current_usec;  // remember new time for the future use
135         } else if (EVENT_EC_START_CONDITION_SEEN == event_id) {
136                 return;         // supress notification
137         } else if (EVENT_EC_STOP_CONDITION_SEEN == event_id) {
138                 return;         // supress notification
139         }
140
141         ++notification_count;
142         wake_up_interruptible (&notification_waiters_queue);
143 }
144
145 static int device_mmap (struct file *filp UNUSED, struct vm_area_struct *vma)
146 {
147         if(!p_buffer) {
148                 EPRINTF("Null pointer to buffer!");
149                 return -1;
150         }
151         return remap_vmalloc_range (vma, p_buffer, 0);
152 }
153
154 static int device_open(struct inode *inode, struct file *file)
155 {
156         /*if (gl_nDeviceOpened)
157                 return -EBUSY;*/
158         gl_nDeviceOpened++;
159         // TODO
160         try_module_get(THIS_MODULE);
161         return 0;
162 }
163  
164 static int device_release(struct inode *inode, struct file *file)
165 {
166         gl_nDeviceOpened--;
167         module_put(THIS_MODULE);
168         return 0;
169 }
170  
171 static ssize_t device_read(struct file *filp, char *buffer, size_t length, loff_t * offset)
172 {
173         EPRINTF("Operation <<read>> not supported!");
174         return -1;
175 }
176  
177 static ssize_t device_write(struct file *filp, const char *buff, size_t len, loff_t * off)
178 {
179         EPRINTF("Operation <<write>> not supported!");
180         return -1;
181 }
182
183 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36)
184 static int device_ioctl (struct inode *inode UNUSED, struct file *file UNUSED, unsigned int cmd, unsigned long arg)
185 #else
186 static long device_ioctl (struct file *file UNUSED, unsigned int cmd, unsigned long arg)
187 #endif
188 {
189         unsigned long spinlock_flags = 0L;
190         int result = -1;
191 //      DPRINTF("Command=%d", cmd);
192         switch (cmd)
193         {
194         case EC_IOCTL_SET_EC_MODE:
195                 {
196                         ioctl_general_t param;
197                         unsigned long nIgnoredBytes = 0;
198                         memset(&param, '0', sizeof(ioctl_general_t));
199                         nIgnoredBytes = copy_from_user (&param, (void*)arg, sizeof(ioctl_general_t));
200                         if (nIgnoredBytes > 0) {
201                                 result = -1;
202                                 break;
203                         }
204                         if(SetECMode(param.m_unsignedLong) == -1) {
205                                 result = -1;
206                                 break;
207                         }
208                         result = 0;
209                         DPRINTF("Set EC Mode = %lu", param.m_unsignedLong);
210                         break;
211                 }
212         case EC_IOCTL_GET_EC_MODE:
213                 {
214                         ioctl_general_t param;
215                         unsigned long nIgnoredBytes = 0;
216                         memset(&param, '0', sizeof(ioctl_general_t));
217                         param.m_unsignedLong = GetECMode();
218                         nIgnoredBytes = copy_to_user ((void*)arg, &param, sizeof (ioctl_general_t));
219                         if (nIgnoredBytes > 0) {
220                                 result = -1;
221                                 break;
222                         }
223                         result = 0;
224 //                      DPRINTF("Get EC Mode = %lu", param.m_unsignedLong);  // Frequent call
225                         break;
226                 }
227         case EC_IOCTL_SET_BUFFER_SIZE:
228                 {
229                         ioctl_general_t param;
230                         unsigned long nIgnoredBytes = 0;
231                         memset(&param, '0', sizeof(ioctl_general_t));
232                         nIgnoredBytes = copy_from_user (&param, (void*)arg, sizeof(ioctl_general_t));
233                         if (nIgnoredBytes > 0) {
234                                 result = -1;
235                                 break;
236                         }
237                         if (SetBufferSize(param.m_unsignedLong) == -1) {
238                                 result = -1;
239                                 break;
240                         }
241                         result = 0;
242                         DPRINTF("Set Buffer Size = %lu", param.m_unsignedLong);
243                         break;
244                 }
245         case EC_IOCTL_GET_BUFFER_SIZE:
246                 {
247                         ioctl_general_t param;
248                         unsigned long nIgnoredBytes = 0;
249                         memset(&param, '0', sizeof(ioctl_general_t));
250                         param.m_unsignedLong = GetBufferSize();
251                         nIgnoredBytes = copy_to_user ((void*)arg, &param, sizeof (ioctl_general_t));
252                         if (nIgnoredBytes > 0) {
253                                 result = -1;
254                                 break;
255                         }
256                         result = 0;
257                         DPRINTF("Get Buffer Size = %lu", param.m_unsignedLong);
258                         break;
259                 }
260         case EC_IOCTL_RESET_BUFFER:
261                 {
262                         if (ResetBuffer() == -1) {
263                                 result = -1;
264                                 break;
265                         }
266                         result = 0;
267                         DPRINTF("Reset Buffer");
268                         break;
269                 }
270         case EC_IOCTL_GET_EC_INFO:
271                 {
272                         if (copy_ec_info_to_user_space ((ec_info_t *) arg) != 0) {
273                                 result = -1;
274                                 break;
275                         }
276                         result = 0;
277 //                      DPRINTF("Get Buffer Status"); // Frequent call
278                         break;
279                 }
280         case EC_IOCTL_CONSUME_BUFFER:
281                 {
282                         static ec_info_t ec_info_copy;
283                         int nIgnoredBytes = 0;
284
285                         nIgnoredBytes = copy_from_user (&ec_info_copy, (ec_info_t *) arg, sizeof (ec_info_t));
286                         if(nIgnoredBytes > 0)
287                         {
288                                 EPRINTF ("copy_from_user(%08X,%08X)=%d", (unsigned) arg, (unsigned) &ec_info_copy, nIgnoredBytes);
289                                 result = -1;
290                                 break;
291                         }
292
293                         spin_lock_irqsave (&ec_spinlock, spinlock_flags);
294
295                         // Original buffer
296                         if(ec_info.after_last > ec_info.first) {
297                                 ec_info.buffer_effect = ec_info.buffer_size;
298                         }
299                         if (ec_info.after_last == ec_info.buffer_effect) {
300                                  ec_info.first = 0;
301                         } else {
302                                  ec_info.first = ec_info_copy.after_last;
303                         }
304                         ec_info.trace_size = ec_info.trace_size - ec_info_copy.trace_size;
305
306                         spin_unlock_irqrestore (&ec_spinlock, spinlock_flags);
307                         result = 0;
308 //                      DPRINTF("Consume Buffer"); // Frequent call
309                         break;
310                 }
311         case EC_IOCTL_ADD_PROBE:
312                 {
313                         unsigned long addr = arg;
314                         result = add_probe(addr);
315
316                         break;
317                 }
318         //@AGv: remove_probe expects probe address instead of name
319         /*case EC_IOCTL_REMOVE_PROBE:
320                 {
321                         char *probe_name = (char *) arg;
322                         result = remove_probe (probe_name);
323
324                         break;
325                 }*/
326         case EC_IOCTL_SET_APPDEPS:
327         {
328                 size_t size;
329                 result = copy_from_user(&size, (void *)arg, sizeof(size_t));
330                 if (result) {
331                         EPRINTF("Cannot copy deps size!");
332                         result = -1;
333                         break;
334                 }
335                 DPRINTF("Deps size has been copied (%d)", size);
336
337                 if (size == 0) {
338                         DPRINTF("Deps are size of 0");
339                         break;
340                 }
341
342                 deps = vmalloc(size);
343                 if (deps == NULL) {
344                         EPRINTF("Cannot alloc mem for deps!");
345                         result = -1;
346                         break;
347                 }
348                 DPRINTF("Mem for deps has been allocated");
349
350                 result = copy_from_user(deps, (void *)arg, size);
351                 if (result) {
352                         EPRINTF("Cannot copy deps!");
353                         result = -1;
354                         break;
355                 }
356                 DPRINTF("Deps has been copied successfully");
357
358                 break;
359         }
360         case EC_IOCTL_SET_PID:
361         {
362                 unsigned int _pid;
363
364                 result = copy_from_user(&_pid, (void *)arg, sizeof(unsigned int));
365                 if (result) {
366                         EPRINTF("Cannot copy pid!");
367                         result = -1;
368                         break;
369                 }
370
371                 inst_pid = _pid;
372
373                 DPRINTF("EC_IOCTL_SET_PID pid:%d", inst_pid);
374
375                 break;
376         }
377         case EC_IOCTL_SET_PROFILEBUNDLE:
378         {
379                 size_t size;
380
381                 result = copy_from_user(&size, (void *)arg, sizeof(size_t));
382                 if (result) {
383                         EPRINTF("Cannot copy bundle size!");
384                         result = -1;
385                         break;
386                 }
387                 DPRINTF("Bundle size has been copied");
388
389                 bundle = vmalloc(size);
390                 if (bundle == NULL) {
391                         EPRINTF("Cannot alloc mem for bundle!");
392                         result = -1;
393                         break;
394                 }
395                 DPRINTF("Mem for bundle has been alloced");
396
397                 result = copy_from_user(bundle, (void *)arg, size);
398                 if (result) {
399                         EPRINTF("Cannot copy bundle!");
400                         result = -1;
401                         break;
402                 }
403                 DPRINTF("Bundle has been copied successfully");
404
405                 if (link_bundle() == -1) {
406                         EPRINTF("Cannot link profile bundle!");
407                         result = -1;
408                         break;
409                 }
410
411                 break;
412         }
413         case EC_IOCTL_RESET_PROBES:
414                 {
415                         result = reset_probes();
416
417                         break;
418                 }
419         case EC_IOCTL_UPDATE_CONDS:
420                 {
421                         int args_cnt, i;
422                         struct cond *c, *c_tmp, *p_cond;
423                         unsigned char *p_data;
424                         int err;
425                         result = 0;
426                         err = copy_from_user(&args_cnt, (void *)arg, sizeof(int));
427                         if (err) {
428                                 result = -1;
429                                 break;
430                         }
431                         /* first, delete all the conds */
432                         list_for_each_entry_safe(c, c_tmp, &cond_list.list, list) {
433                                 list_del(&c->list);
434                                 kfree(c);
435                         }
436                         /* second, add new conds */
437                         p_data = (unsigned char *)(arg + sizeof(int));
438                         for (i = 0; i < args_cnt; i++) {
439                                 p_cond = kmalloc(sizeof(struct cond), GFP_KERNEL);
440                                 if (!p_cond) {
441                                         DPRINTF("Cannot alloc cond!");
442                                         result = -1;
443                                         break;
444                                 }
445                                 err = copy_from_user(&p_cond->tmpl, p_data, sizeof(struct event_tmpl));
446                                 if (err) {
447                                         DPRINTF("Cannot copy cond from user!");
448                                         result = -1;
449                                         break;
450                                 }
451                                 p_cond->applied = 0;
452                                 list_add(&(p_cond->list), &(cond_list.list));
453                                 p_data += sizeof(struct event_tmpl);
454                         }
455                         break;
456                 }
457         case EC_IOCTL_ATTACH:
458                 {
459                         unsigned long dbi_flags;
460                         struct dbi_modules_handlers *local_mh;
461                         struct dbi_modules_handlers_info *local_mhi;
462                         int j;
463                         dbi_module_callback dmc_start;
464
465                         // call "start"-callback for all modules according module priority
466                         local_mh = get_dbi_modules_handlers();
467                         spin_lock_irqsave(&local_mh->lock, dbi_flags);
468                         for (j = 0; j <= MAX_PRIORITY; j++) {
469                                 list_for_each_entry_rcu(local_mhi, &local_mh->modules_handlers, dbi_list_head) {
470                                         if (local_mhi->dbi_module_priority_start == j) {
471                                                 if (local_mhi->dbi_module_callback_start != NULL) {
472                                                         printk("Started module callback (start) %s\n", local_mhi->dbi_module->name);
473                                                         dmc_start = (dbi_module_callback )local_mhi->dbi_module_callback_start;
474                                                         dmc_start();
475                                                 }
476                                         }
477                                 }
478                         }
479                         spin_unlock_irqrestore(&local_mh->lock, dbi_flags);
480
481                         result = ec_user_attach ();
482 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 17)
483                         DPRINTF("EC_IOCTL_ATTACH calling notification chain");
484                         blocking_notifier_call_chain(&swap_notifier_list, EC_IOCTL_ATTACH, (void*)NULL);
485 #endif
486                         DPRINTF("Attach Probes");
487                         break;
488                 }
489         case EC_IOCTL_ACTIVATE:
490                 result = ec_user_activate ();
491                 DPRINTF("Activate Probes");
492                 break;
493         case EC_IOCTL_STOP_AND_DETACH:
494         {
495                 unsigned long nIgnoredBytes = 0;
496                 unsigned long dbi_flags;
497                 struct dbi_modules_handlers *local_mh;
498                 struct dbi_modules_handlers_info *local_mhi;
499                 unsigned int local_module_refcount = 0;
500                 int j;
501                 dbi_module_callback dmc_stop;
502
503 #ifdef OVERHEAD_DEBUG
504                 printk("\nswap_sum_time = %ld in kprobe_handler()\n", swap_sum_time);
505                 printk("swap_sum_hit = %ld in kprobe_handler()\n", swap_sum_hit);
506                 swap_sum_time = 0;
507                 swap_sum_hit = 0;
508 #endif
509                 local_mh = get_dbi_modules_handlers();
510                 if(ec_user_stop() != 0) {
511                         result = -1;
512                         goto sad_cleanup;
513                 }
514                 nIgnoredBytes = copy_ec_info_to_user_space ((ec_info_t*)arg);
515                 if(nIgnoredBytes > 0) {
516                         result = -1;
517                         goto sad_cleanup;
518                 }
519                 vfree(bundle);
520                 result = 0;
521                 DPRINTF("Stop and Detach Probes");
522 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 17)
523                 DPRINTF("EC_IOCTL_STOP_AND_DETACH calling notification chain");
524                 blocking_notifier_call_chain(&swap_notifier_list, EC_IOCTL_STOP_AND_DETACH, (void*)&gl_nNotifyTgid);
525 #endif
526                 // call "stop"-callback for all modules according module priority
527                 spin_lock_irqsave(&local_mh->lock, dbi_flags);
528                 for (j = 0; j <= MAX_PRIORITY; j++) {
529                         list_for_each_entry_rcu(local_mhi, &local_mh->modules_handlers, dbi_list_head) {
530                                 if (local_mhi->dbi_module_priority_stop == j) {
531                                         if (local_mhi->dbi_module_callback_stop != NULL) {
532                                                 printk("Started module callback (stop) %s\n", local_mhi->dbi_module->name);
533                                                 dmc_stop = (dbi_module_callback )local_mhi->dbi_module_callback_stop;
534                                                 dmc_stop();
535                                         }
536                                 }
537                         }
538                 }
539                 spin_unlock_irqrestore(&local_mh->lock, dbi_flags);
540 sad_cleanup:
541                 spin_lock_irqsave(&local_mh->lock, dbi_flags);
542                 list_for_each_entry_rcu(local_mhi, &local_mh->modules_handlers, dbi_list_head) {
543                         local_module_refcount = module_refcount(local_mhi->dbi_module);
544                         if (local_module_refcount == 1) {
545                                 module_put(local_mhi->dbi_module);
546                         }
547                         else if (local_module_refcount > 1) {
548                                 printk("local_module_refcount too much - force set refcount to zero\n");
549                                 while (local_module_refcount--)
550                                         module_put(local_mhi->dbi_module);
551                         }
552                 }
553                 spin_unlock_irqrestore(&local_mh->lock, dbi_flags);
554                 break;
555         }
556         case EC_IOCTL_WAIT_NOTIFICATION:
557                 {
558                         static ec_info_t ec_info_copy;
559
560                         ioctl_wait_notification_t ioctl_args;
561
562                         result = copy_from_user (&ioctl_args, (void *) arg, sizeof (ioctl_args));
563                         if (result)
564                         {
565                                 result = -1;
566                                 break;
567                         }
568
569                         result = wait_event_interruptible (notification_waiters_queue, ioctl_args.notification_count != notification_count);
570                         if (result)
571                         {
572                                 result = -EINTR;        // woken by signal (ERESTARTSYS 512)
573                                 break;
574                         }
575
576                         ioctl_args.notification_count = notification_count;
577
578                         result = copy_to_user ((void *) arg, &ioctl_args, sizeof (ioctl_args));
579                         if (result)
580                         {
581                                 result = -1;
582                                 break;
583                         }
584
585                         // FIXME: synchronization is necessary here (ec_info must be locked).
586                         // ENTER_CRITICAL_SECTION
587                         memcpy (&ec_info_copy, &ec_info, sizeof (ec_info_copy));
588                         // LEAVE_CRITICAL_SECTION
589
590                         result = copy_to_user ((void *) ioctl_args.p_ec_info, &ec_info_copy, sizeof (ec_info_t));
591                         if (result)
592                         {
593                                 EPRINTF ("copy_to_user(%08X,%08X)=%d", (unsigned) ioctl_args.p_ec_info, (unsigned) &ec_info_copy, result);
594                                 result = -1;
595                                 break;
596                         }
597                         DPRINTF("Wake up");
598                         break;
599                 }
600         case EC_IOCTL_US_EVENT:
601                 {
602                         ioctl_us_event_t ioctl_args;
603                         result = copy_from_user (&ioctl_args, (void *) arg, sizeof (ioctl_args));
604                         if (result)
605                         {
606                                 result = -1;
607                                 EPRINTF ("copy_from_user() failure");
608                         }
609                         else
610                         {
611                                 if(ioctl_args.len == 0){
612                                         result = -EINVAL;
613                                         EPRINTF ("invalid event length!");                                      
614                                 }
615                                 else {
616                                         char *buf = kmalloc(ioctl_args.len, GFP_KERNEL);
617                                         if(!buf){
618                                                 result = -ENOMEM;
619                                                 EPRINTF ("failed to alloc mem for event!");                                     
620                                         }
621                                         else {
622                                                 result = copy_from_user (buf, (void *) ioctl_args.data, ioctl_args.len);
623                                                 if (result){
624                                                         result = -1;
625                                                         EPRINTF ("failed to copy event from user space!");
626                                                 }
627                                                 else
628                                                         result = put_us_event(buf, ioctl_args.len);
629                                                 kfree(buf);
630                                         }
631                                 }
632                         }
633 //                      DPRINTF("User Space Event"); // Frequent call
634                         break;
635                 }
636                 
637         case EC_IOCTL_SET_EVENT_MASK:
638                 {
639                         int mask;
640                         result = copy_from_user (&mask, (void *) arg, sizeof (mask));
641                         if (result)
642                         {
643                                 result = -EFAULT;
644                                 break;
645                         }
646
647                         result = set_event_mask (mask);
648                         if (result)
649                         {
650                                 break;
651                         }
652                         DPRINTF("Set Event Mask = %d", mask);
653                         break;
654                 }
655
656         case EC_IOCTL_GET_EVENT_MASK:
657                 {
658                         int mask = 0;
659                         result = get_event_mask(&mask);
660                         if (result)
661                         {
662                                 result = -EFAULT;
663                         }
664                         result = copy_to_user ((void *) arg, &mask, sizeof (mask));
665                         if (result)
666                         {
667                                 result = -EFAULT;
668                         }
669                         DPRINTF("Get Event Mask = %d", mask);
670                         break;
671                 }
672
673         case EC_IOCTL_SET_PREDEF_UPROBES:
674                 {
675                         ioctl_predef_uprobes_info_t data;
676                         result = copy_from_user (&data, (void *) arg, sizeof (data));
677                         if (result)
678                         {
679                                 result = -EFAULT;
680                                 break;
681                         }
682
683                         result = set_predef_uprobes (&data);
684                         if (result)
685                         {
686                                 break;
687                         }
688                         DPRINTF("Set Predefined User Space Probes");
689                         break;
690                 }
691                 
692         case EC_IOCTL_GET_PREDEF_UPROBES:
693                 {
694                         result = get_predef_uprobes((ioctl_predef_uprobes_info_t *)arg);
695                         if (result)
696                         {
697                                 result = -EFAULT;
698                         }
699                         DPRINTF("Get Predefined User Space Probes");
700                         break;
701                 }
702                 
703         case EC_IOCTL_GET_PREDEF_UPROBES_SIZE:
704                 {
705                         int size = 0;
706                         result = get_predef_uprobes_size(&size);
707                         if (result)
708                         {
709                                 result = -EFAULT;
710                         }
711                         result = copy_to_user ((void *) arg, &size, sizeof (size));
712                         if (result)
713                         {
714                                 result = -EFAULT;
715                         }
716                         DPRINTF("Get Size of Predefined User Space Probes");
717                         break;
718                 }
719         
720         default:
721                 EPRINTF ("Unknown driver command = %u", cmd);
722                 result = -EINVAL;
723                 break;
724         }
725
726         return result;
727 }