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