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