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