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