bump version
[buildroot.git] / package / fusion / linux-2.6.22.1-008-fusion.patch
blob81d98afada72eb81b655b0457b95c3e294cfb9bf
1 diff -urN linux-2.6.22.1-0rig/drivers/char/fusion/call.c linux-2.6.22.1/drivers/char/fusion/call.c
2 --- linux-2.6.22.1-0rig/drivers/char/fusion/call.c 1970-01-01 01:00:00.000000000 +0100
3 +++ linux-2.6.22.1/drivers/char/fusion/call.c 2007-01-20 05:03:01.000000000 +0100
4 @@ -0,0 +1,478 @@
5 +/*
6 + * Fusion Kernel Module
7 + *
8 + * (c) Copyright 2002-2003 Convergence GmbH
9 + *
10 + * Written by Denis Oliver Kropp <dok@directfb.org>
11 + *
12 + *
13 + * This program is free software; you can redistribute it and/or
14 + * modify it under the terms of the GNU General Public License
15 + * as published by the Free Software Foundation; either version
16 + * 2 of the License, or (at your option) any later version.
17 + */
19 +#ifdef HAVE_LINUX_CONFIG_H
20 +#include <linux/config.h>
21 +#endif
22 +#include <linux/types.h>
23 +#include <linux/kernel.h>
24 +#include <linux/slab.h>
25 +#include <linux/smp_lock.h>
26 +#include <linux/sched.h>
28 +#include <linux/fusion.h>
30 +#include "fusiondev.h"
31 +#include "fusionee.h"
32 +#include "list.h"
33 +#include "call.h"
35 +typedef struct {
36 + FusionLink link;
38 + Fusionee *caller;
40 + int ret_val;
42 + bool executed;
44 + wait_queue_head_t wait;
45 +} FusionCallExecution;
47 +typedef struct {
48 + FusionLink link;
50 + struct semaphore lock;
52 + int id; /* call id */
54 + int pid; /* owner pid */
55 + int fusion_id; /* owner fusion id */
57 + void *handler;
58 + void *ctx;
60 + FusionLink *executions; /* prepending! */
61 + FusionLink *last; /* points to the last item of executions */
63 + int count; /* number of calls ever made */
64 +} FusionCall;
66 +/******************************************************************************/
68 +static int lookup_call (FusionDev *dev, int id, FusionCall **ret_call);
69 +static int lock_call (FusionDev *dev, int id, FusionCall **ret_call);
70 +static void unlock_call (FusionCall *call);
72 +static FusionCallExecution *add_execution (FusionCall *call,
73 + Fusionee *caller,
74 + FusionCallExecute *execute);
75 +static void remove_execution (FusionCall *call,
76 + FusionCallExecution *execution);
77 +static void free_all_executions (FusionCall *call);
79 +/******************************************************************************/
81 +static int
82 +fusion_call_read_proc (char *buf, char **start, off_t offset,
83 + int len, int *eof, void *private)
85 + FusionLink *l, *e;
86 + FusionDev *dev = private;
87 + int written = 0;
89 + if (down_interruptible (&dev->call.lock))
90 + return -EINTR;
92 + fusion_list_foreach (l, dev->call.list) {
93 + bool idle = true;
94 + FusionCall *call = (FusionCall*) l;
96 + if (call->executions)
97 + idle = ((FusionCallExecution*) call->executions)->executed;
99 + written += sprintf(buf+written,
100 + "(%5d) 0x%08x (%d calls) %s",
101 + call->pid, call->id, call->count,
102 + idle ? "idle" : "executing");
104 + fusion_list_foreach (e, call->executions) {
105 + FusionCallExecution *exec = (FusionCallExecution *) e;
107 + written += sprintf(buf+written, " [0x%08lx]", exec->caller ? fusionee_id( exec->caller ) : 0);
110 + written += sprintf(buf+written, "\n");
112 + if (written < offset) {
113 + offset -= written;
114 + written = 0;
117 + if (written >= len)
118 + break;
121 + up (&dev->call.lock);
123 + *start = buf + offset;
124 + written -= offset;
125 + if (written > len) {
126 + *eof = 0;
127 + return len;
130 + *eof = 1;
131 + return(written<0) ? 0 : written;
134 +int
135 +fusion_call_init (FusionDev *dev)
137 + create_proc_read_entry("calls", 0, dev->proc_dir,
138 + fusion_call_read_proc, dev);
140 + init_MUTEX(&dev->call.lock);
142 + return 0;
145 +void
146 +fusion_call_deinit (FusionDev *dev)
148 + FusionLink *l;
150 + down (&dev->call.lock);
152 + remove_proc_entry ("calls", dev->proc_dir);
154 + l = dev->call.list;
155 + while (l) {
156 + FusionLink *next = l->next;
157 + FusionCall *call = (FusionCall *) l;
159 + free_all_executions (call);
161 + kfree (call);
163 + l = next;
166 + up (&dev->call.lock);
169 +/******************************************************************************/
171 +int
172 +fusion_call_new (FusionDev *dev, int fusion_id, FusionCallNew *call_new)
174 + FusionCall *call;
176 + call = kmalloc (sizeof(FusionCall), GFP_KERNEL);
177 + if (!call)
178 + return -ENOMEM;
180 + memset (call, 0, sizeof(FusionCall));
182 + if (down_interruptible (&dev->call.lock)) {
183 + kfree (call);
184 + return -EINTR;
187 + call->id = dev->call.ids++;
188 + call->pid = current->pid;
189 + call->fusion_id = fusion_id;
190 + call->handler = call_new->handler;
191 + call->ctx = call_new->ctx;
193 + init_MUTEX (&call->lock);
195 + fusion_list_prepend (&dev->call.list, &call->link);
197 + up (&dev->call.lock);
199 + call_new->call_id = call->id;
201 + return 0;
204 +int
205 +fusion_call_execute (FusionDev *dev, Fusionee *fusionee, FusionCallExecute *execute)
207 + int ret;
208 + FusionCall *call;
209 + FusionCallExecution *execution;
210 + FusionCallMessage message;
212 + ret = lock_call (dev, execute->call_id, &call);
213 + if (ret)
214 + return ret;
216 + execution = add_execution (call, fusionee, execute);
217 + if (!execution) {
218 + unlock_call (call);
219 + return -ENOMEM;
222 + /* Send call message. */
223 + message.handler = call->handler;
224 + message.ctx = call->ctx;
226 + message.caller = fusionee ? fusionee_id( fusionee ) : 0;
228 + message.call_arg = execute->call_arg;
229 + message.call_ptr = execute->call_ptr;
231 + ret = fusionee_send_message (dev, fusionee, call->fusion_id, FMT_CALL,
232 + call->id, sizeof(message), &message);
233 + if (ret) {
234 + remove_execution (call, execution);
235 + kfree (execution);
236 + unlock_call (call);
237 + return ret;
240 + call->count++;
242 + if (fusionee && !(execute->flags & FCEF_ONEWAY)) {
243 + /* TODO: implement timeout */
244 + fusion_sleep_on (&execution->wait, &call->lock, 0);
246 + ret = lock_call (dev, execute->call_id, &call);
247 + if (ret)
248 + return ret == -EINVAL ? -EIDRM : ret;
250 + if (signal_pending(current)) {
251 + execution->caller = 0;
252 + unlock_call (call);
253 + return -EINTR;
256 + execute->ret_val = execution->ret_val;
258 + remove_execution (call, execution);
260 + kfree (execution);
263 + unlock_call (call);
265 + return 0;
268 +int
269 +fusion_call_return (FusionDev *dev, int fusion_id, FusionCallReturn *call_ret)
271 + int ret;
272 + FusionLink *l;
273 + FusionCall *call;
275 + ret = lock_call (dev, call_ret->call_id, &call);
276 + if (ret)
277 + return ret;
279 + l = call->last;
280 + while (l) {
281 + FusionCallExecution *execution = (FusionCallExecution*) l;
283 + if (execution->executed) {
284 + l = l->prev;
285 + continue;
288 + if (execution->caller) {
289 + execution->ret_val = call_ret->val;
290 + execution->executed = true;
292 + wake_up_interruptible_all (&execution->wait);
294 + else {
295 + remove_execution (call, execution);
297 + kfree (execution);
300 + unlock_call (call);
302 + return 0;
305 + unlock_call (call);
307 + return -EIO;
310 +int
311 +fusion_call_destroy (FusionDev *dev, int fusion_id, int call_id)
313 + int ret;
314 + FusionCall *call;
316 + ret = lookup_call (dev, call_id, &call);
317 + if (ret)
318 + return ret;
320 + if (call->fusion_id != fusion_id) {
321 + up (&dev->call.lock);
322 + return -EIO;
325 + if (down_interruptible (&call->lock)) {
326 + up (&dev->call.lock);
327 + return -EINTR;
330 + fusion_list_remove (&dev->call.list, &call->link);
332 + free_all_executions (call);
334 + up (&dev->call.lock);
336 + up (&call->lock);
338 + kfree (call);
340 + return 0;
343 +void
344 +fusion_call_destroy_all (FusionDev *dev, int fusion_id)
346 + FusionLink *l;
348 + down (&dev->call.lock);
350 + l = dev->call.list;
352 + while (l) {
353 + FusionLink *next = l->next;
354 + FusionCall *call = (FusionCall *) l;
356 + down (&call->lock);
358 + if (call->fusion_id == fusion_id) {
359 + free_all_executions (call);
361 + fusion_list_remove (&dev->call.list, &call->link);
363 + up (&call->lock);
365 + kfree (call);
367 + else
368 + up (&call->lock);
370 + l = next;
373 + up (&dev->call.lock);
376 +/******************************************************************************/
378 +static int
379 +lookup_call (FusionDev *dev, int id, FusionCall **ret_call)
381 + FusionLink *l;
383 + if (down_interruptible (&dev->call.lock))
384 + return -EINTR;
386 + fusion_list_foreach (l, dev->call.list) {
387 + FusionCall *call = (FusionCall *) l;
389 + if (call->id == id) {
390 + *ret_call = call;
391 + return 0;
395 + up (&dev->call.lock);
397 + return -EINVAL;
400 +static int
401 +lock_call (FusionDev *dev, int id, FusionCall **ret_call)
403 + int ret;
404 + FusionCall *call;
406 + ret = lookup_call (dev, id, &call);
407 + if (ret)
408 + return ret;
410 + if (call) {
411 + fusion_list_move_to_front (&dev->call.list, &call->link);
413 + if (down_interruptible (&call->lock)) {
414 + up (&dev->call.lock);
415 + return -EINTR;
418 + up (&dev->call.lock);
421 + *ret_call = call;
423 + return 0;
426 +static void
427 +unlock_call (FusionCall *call)
429 + up (&call->lock);
432 +static FusionCallExecution *
433 +add_execution (FusionCall *call,
434 + Fusionee *caller,
435 + FusionCallExecute *execute)
437 + FusionCallExecution *execution;
439 + /* Allocate execution. */
440 + execution = kmalloc (sizeof(FusionCallExecution), GFP_KERNEL);
441 + if (!execution)
442 + return NULL;
444 + /* Initialize execution. */
445 + memset (execution, 0, sizeof(FusionCallExecution));
447 + execution->caller = caller;
449 + init_waitqueue_head (&execution->wait);
451 + /* Add execution. */
452 + fusion_list_prepend (&call->executions, &execution->link);
454 + if (!call->last)
455 + call->last = &execution->link;
457 + return execution;
460 +static void
461 +remove_execution (FusionCall *call,
462 + FusionCallExecution *execution)
464 + if (call->last == &execution->link)
465 + call->last = execution->link.prev;
467 + fusion_list_remove (&call->executions, &execution->link);
470 +static void
471 +free_all_executions (FusionCall *call)
473 + while (call->last) {
474 + FusionCallExecution *execution = (FusionCallExecution *) call->last;
476 + remove_execution (call, execution);
478 + wake_up_interruptible_all (&execution->wait);
480 + kfree (execution);
483 diff -urN linux-2.6.22.1-0rig/drivers/char/fusion/call.h linux-2.6.22.1/drivers/char/fusion/call.h
484 --- linux-2.6.22.1-0rig/drivers/char/fusion/call.h 1970-01-01 01:00:00.000000000 +0100
485 +++ linux-2.6.22.1/drivers/char/fusion/call.h 2007-01-20 05:03:01.000000000 +0100
486 @@ -0,0 +1,52 @@
488 + * Fusion Kernel Module
490 + * (c) Copyright 2002-2003 Convergence GmbH
492 + * Written by Denis Oliver Kropp <dok@directfb.org>
495 + * This program is free software; you can redistribute it and/or
496 + * modify it under the terms of the GNU General Public License
497 + * as published by the Free Software Foundation; either version
498 + * 2 of the License, or (at your option) any later version.
499 + */
501 +#ifndef __FUSION__CALL_H__
502 +#define __FUSION__CALL_H__
504 +#include <linux/fusion.h>
506 +#include "fusiondev.h"
508 +/* module init/cleanup */
510 +int fusion_call_init (FusionDev *dev);
511 +void fusion_call_deinit (FusionDev *dev);
514 +/* public API */
516 +int fusion_call_new (FusionDev *dev,
517 + int fusion_id,
518 + FusionCallNew *call);
520 +int fusion_call_execute (FusionDev *dev,
521 + Fusionee *fusionee, /* NULL if call is from kernel */
522 + FusionCallExecute *execute);
524 +int fusion_call_return (FusionDev *dev,
525 + int fusion_id,
526 + FusionCallReturn *call_ret);
528 +int fusion_call_destroy (FusionDev *dev,
529 + int fusion_id,
530 + int call_id);
533 +/* internal functions */
535 +void fusion_call_destroy_all (FusionDev *dev,
536 + int fusion_id);
538 +#endif
539 diff -urN linux-2.6.22.1-0rig/drivers/char/fusion/.cvsignore linux-2.6.22.1/drivers/char/fusion/.cvsignore
540 --- linux-2.6.22.1-0rig/drivers/char/fusion/.cvsignore 1970-01-01 01:00:00.000000000 +0100
541 +++ linux-2.6.22.1/drivers/char/fusion/.cvsignore 2005-10-29 07:11:10.000000000 +0200
542 @@ -0,0 +1,6 @@
543 +*.o.flags
544 +*.cmd
545 +Makefile
546 +fusion.ko
547 +fusion.mod.c
548 +.tmp_versions
549 diff -urN linux-2.6.22.1-0rig/drivers/char/fusion/entries.c linux-2.6.22.1/drivers/char/fusion/entries.c
550 --- linux-2.6.22.1-0rig/drivers/char/fusion/entries.c 1970-01-01 01:00:00.000000000 +0100
551 +++ linux-2.6.22.1/drivers/char/fusion/entries.c 2007-03-08 14:02:04.000000000 +0100
552 @@ -0,0 +1,438 @@
554 + * Fusion Kernel Module
556 + * (c) Copyright 2002-2003 Convergence GmbH
558 + * Written by Denis Oliver Kropp <dok@directfb.org>
561 + * This program is free software; you can redistribute it and/or
562 + * modify it under the terms of the GNU General Public License
563 + * as published by the Free Software Foundation; either version
564 + * 2 of the License, or (at your option) any later version.
565 + */
567 +#ifdef HAVE_LINUX_CONFIG_H
568 +#include <linux/config.h>
569 +#endif
570 +#include <linux/types.h>
571 +#include <linux/kernel.h>
572 +#include <linux/slab.h>
573 +#include <linux/smp_lock.h>
574 +#include <linux/sched.h>
575 +#include <linux/time.h>
576 +#include <linux/version.h>
578 +#include <linux/fusion.h>
580 +#include "fusiondev.h"
581 +#include "entries.h"
584 +void
585 +fusion_entries_init( FusionEntries *entries,
586 + FusionEntryClass *class,
587 + void *ctx )
589 + FUSION_ASSERT( entries != NULL );
590 + FUSION_ASSERT( class != NULL );
591 + FUSION_ASSERT( class->object_size >= sizeof(FusionEntry) );
593 + memset( entries, 0, sizeof(FusionEntries) );
595 + entries->class = class;
596 + entries->ctx = ctx;
598 + init_MUTEX( &entries->lock );
601 +void
602 +fusion_entries_deinit( FusionEntries *entries )
604 + FusionLink *tmp;
605 + FusionEntry *entry;
606 + FusionEntryClass *class;
608 + FUSION_ASSERT( entries != NULL );
609 + FUSION_ASSERT( entries->class != NULL );
611 + class = entries->class;
613 + down( &entries->lock );
615 + fusion_list_foreach_safe (entry, tmp, entries->list) {
616 + if (class->Destroy)
617 + class->Destroy( entry, entries->ctx );
619 + kfree( entry );
622 + up( &entries->lock );
625 +int
626 +fusion_entries_read_proc(char *buf, char **start, off_t offset,
627 + int len, int *eof, void *private)
629 + FusionEntry *entry;
630 + FusionEntryClass *class;
631 + FusionEntries *entries = private;
632 + int written = 0;
633 + struct timeval now;
635 + FUSION_ASSERT( entries != NULL );
636 + FUSION_ASSERT( entries->class != NULL );
638 + class = entries->class;
640 + if (!class->Print)
641 + return -ENOTSUPP;
643 + if (down_interruptible (&entries->lock))
644 + return -EINTR;
646 + do_gettimeofday( &now );
648 + fusion_list_foreach (entry, entries->list) {
649 + if (entry->last_lock.tv_sec) {
650 + int diff = ((now.tv_sec - entry->last_lock.tv_sec) * 1000 +
651 + (now.tv_usec - entry->last_lock.tv_usec) / 1000);
653 + if (diff < 1000) {
654 + written += sprintf( buf + written, "%3d ms ", diff );
656 + else if (diff < 1000000) {
657 + written += sprintf( buf + written, "%3d.%d s ",
658 + diff / 1000, (diff % 1000) / 100 );
660 + else {
661 + diff = ( now.tv_sec - entry->last_lock.tv_sec +
662 + (now.tv_usec - entry->last_lock.tv_usec) / 1000000);
664 + written += sprintf( buf + written, "%3d.%d h ",
665 + diff / 3600, (diff % 3600) / 360 );
668 + else
669 + written += sprintf( buf + written, " -.- " );
672 + written += sprintf( buf + written, "(%5d) 0x%08x ", entry->pid, entry->id );
674 + written += sprintf( buf + written, "%-24s ", entry->name[0] ? entry->name : "" );
676 + written += class->Print( entry, entries->ctx, buf + written );
678 + if (written < offset) {
679 + offset -= written;
680 + written = 0;
683 + if (written >= len)
684 + break;
687 + up (&entries->lock);
689 + *start = buf + offset;
690 + written -= offset;
691 + if (written > len) {
692 + *eof = 0;
693 + return len;
696 + *eof = 1;
698 + return (written<0) ? 0 : written;
701 +int
702 +fusion_entry_create( FusionEntries *entries,
703 + int *ret_id,
704 + void *create_ctx )
706 + int ret;
707 + FusionEntry *entry;
708 + FusionEntryClass *class;
710 + FUSION_ASSERT( entries != NULL );
711 + FUSION_ASSERT( entries->class != NULL );
712 + FUSION_ASSERT( ret_id != NULL );
714 + class = entries->class;
716 + entry = kmalloc( class->object_size, GFP_KERNEL );
717 + if (!entry)
718 + return -ENOMEM;
720 + memset( entry, 0, class->object_size );
722 + if (down_interruptible( &entries->lock )) {
723 + kfree( entry );
724 + return -EINTR;
727 + entry->entries = entries;
728 + entry->id = entries->ids++;
729 + entry->pid = current->pid;
731 + init_MUTEX( &entry->lock );
733 + init_waitqueue_head( &entry->wait );
735 + if (class->Init) {
736 + ret = class->Init( entry, entries->ctx, create_ctx );
737 + if (ret) {
738 + up( &entries->lock );
739 + kfree( entry );
740 + return ret;
744 + fusion_list_prepend( &entries->list, &entry->link );
746 + up( &entries->lock );
748 + *ret_id = entry->id;
750 + return 0;
753 +int
754 +fusion_entry_destroy( FusionEntries *entries,
755 + int id )
757 + FusionEntry *entry;
758 + FusionEntryClass *class;
760 + FUSION_ASSERT( entries != NULL );
761 + FUSION_ASSERT( entries->class != NULL );
763 + class = entries->class;
765 + /* Lock entries. */
766 + if (down_interruptible( &entries->lock ))
767 + return -EINTR;
769 + /* Lookup the entry. */
770 + fusion_list_foreach (entry, entries->list) {
771 + if (entry->id == id)
772 + break;
775 + /* Check if no entry was found. */
776 + if (!entry) {
777 + up( &entries->lock );
778 + return -EINVAL;
781 + /* Lock the entry. */
782 + if (down_interruptible( &entry->lock )) {
783 + up( &entries->lock );
784 + return -EINTR;
787 + /* Destroy it now. */
788 + fusion_entry_destroy_locked( entries, entry );
790 + /* Unlock entries. */
791 + up( &entries->lock );
793 + return 0;
796 +void
797 +fusion_entry_destroy_locked( FusionEntries *entries,
798 + FusionEntry *entry )
800 + FusionEntryClass *class;
802 + FUSION_ASSERT( entries != NULL );
803 + FUSION_ASSERT( entries->class != NULL );
805 + class = entries->class;
807 + /* Remove the entry from the list. */
808 + fusion_list_remove( &entries->list, &entry->link );
810 + /* Wake up any waiting process. */
811 + wake_up_interruptible_all( &entry->wait );
813 + /* Call the destroy function. */
814 + if (class->Destroy)
815 + class->Destroy( entry, entries->ctx );
817 + /* Unlock the entry. */
818 + up( &entry->lock );
820 + /* Deallocate the entry. */
821 + kfree( entry );
824 +int
825 +fusion_entry_set_info( FusionEntries *entries,
826 + const FusionEntryInfo *info )
828 + int ret;
829 + FusionEntry *entry;
831 + FUSION_ASSERT( entries != NULL );
832 + FUSION_ASSERT( info != NULL );
834 + ret = fusion_entry_lock( entries, info->id, false, &entry );
835 + if (ret)
836 + return ret;
838 + snprintf( entry->name, FUSION_ENTRY_INFO_NAME_LENGTH, info->name );
840 + fusion_entry_unlock( entry );
842 + return 0;
845 +int
846 +fusion_entry_get_info( FusionEntries *entries,
847 + FusionEntryInfo *info )
849 + int ret;
850 + FusionEntry *entry;
852 + FUSION_ASSERT( entries != NULL );
853 + FUSION_ASSERT( info != NULL );
855 + ret = fusion_entry_lock( entries, info->id, false, &entry );
856 + if (ret)
857 + return ret;
859 + snprintf( info->name, FUSION_ENTRY_INFO_NAME_LENGTH, entry->name );
861 + fusion_entry_unlock( entry );
863 + return 0;
866 +int
867 +fusion_entry_lock( FusionEntries *entries,
868 + int id,
869 + bool keep_entries_lock,
870 + FusionEntry **ret_entry )
872 + FusionEntry *entry;
874 + FUSION_ASSERT( entries != NULL );
875 + FUSION_ASSERT( ret_entry != NULL );
877 + /* Lock entries. */
878 + if (down_interruptible( &entries->lock ))
879 + return -EINTR;
881 + /* Lookup the entry. */
882 + fusion_list_foreach (entry, entries->list) {
883 + if (entry->id == id)
884 + break;
887 + /* Check if no entry was found. */
888 + if (!entry) {
889 + up( &entries->lock );
890 + return -EINVAL;
893 + FUSION_ASSUME( entry->lock_pid != current->pid );
895 + /* Move the entry to the front of all entries. */
896 + fusion_list_move_to_front( &entries->list, &entry->link );
898 + /* Lock the entry. */
899 + if (down_interruptible( &entry->lock )) {
900 + up( &entries->lock );
901 + return -EINTR;
904 + /* Mark as locked. */
905 + entry->lock_pid = current->pid;
907 + /* Keep timestamp, but use the slightly
908 + inexact version to avoid performance impacts. */
909 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) && defined _STRUCT_TIMESPEC
910 + entry->last_lock.tv_sec = xtime.tv_sec;
911 + entry->last_lock.tv_usec = xtime.tv_nsec / 1000;
912 +#else
913 + entry->last_lock = xtime;
914 +#endif
916 + /* Unlock entries. */
917 + if (!keep_entries_lock)
918 + up( &entries->lock );
920 + /* Return the locked entry. */
921 + *ret_entry = entry;
923 + return 0;
926 +void
927 +fusion_entry_unlock( FusionEntry *entry )
929 + FUSION_ASSERT( entry != NULL );
930 + FUSION_ASSUME( entry->lock_pid == current->pid );
932 + entry->lock_pid = 0;
934 + /* Unlock the entry. */
935 + up( &entry->lock );
938 +int
939 +fusion_entry_wait( FusionEntry *entry, long *timeout )
941 + int ret;
942 + int id;
943 + FusionEntries *entries;
944 + FusionEntry *entry2;
946 + FUSION_ASSERT( entry != NULL );
947 + FUSION_ASSERT( entry->entries != NULL );
948 + FUSION_ASSUME( entry->lock_pid == current->pid );
950 + id = entry->id;
951 + entries = entry->entries;
953 + entry->waiters++;
955 + entry->lock_pid = 0;
956 + fusion_sleep_on( &entry->wait, &entry->lock, timeout );
958 + entry->waiters--;
960 + if (signal_pending(current))
961 + return -EINTR;
963 + if (timeout && !*timeout)
964 + return -ETIMEDOUT;
966 + ret = fusion_entry_lock( entries, id, false, &entry2 );
967 + switch (ret) {
968 + case -EINVAL:
969 + return -EIDRM;
971 + case 0:
972 + if (entry != entry2)
973 + BUG();
976 + return ret;
979 +void
980 +fusion_entry_notify( FusionEntry *entry, bool all )
982 + FUSION_ASSERT( entry != NULL );
983 + FUSION_ASSUME( entry->lock_pid == current->pid );
985 + if (all)
986 + wake_up_interruptible_all( &entry->wait );
987 + else
988 + wake_up_interruptible( &entry->wait );
991 diff -urN linux-2.6.22.1-0rig/drivers/char/fusion/entries.h linux-2.6.22.1/drivers/char/fusion/entries.h
992 --- linux-2.6.22.1-0rig/drivers/char/fusion/entries.h 1970-01-01 01:00:00.000000000 +0100
993 +++ linux-2.6.22.1/drivers/char/fusion/entries.h 2006-09-03 13:50:55.000000000 +0200
994 @@ -0,0 +1,179 @@
996 + * Fusion Kernel Module
998 + * (c) Copyright 2002-2003 Convergence GmbH
1000 + * Written by Denis Oliver Kropp <dok@directfb.org>
1003 + * This program is free software; you can redistribute it and/or
1004 + * modify it under the terms of the GNU General Public License
1005 + * as published by the Free Software Foundation; either version
1006 + * 2 of the License, or (at your option) any later version.
1007 + */
1009 +#ifndef __FUSION__ENTRIES_H__
1010 +#define __FUSION__ENTRIES_H__
1012 +#include "types.h"
1013 +#include "list.h"
1016 +typedef struct __FD_FusionEntry FusionEntry;
1019 +typedef const struct {
1020 + int object_size;
1022 + int (*Init) ( FusionEntry *entry, void *ctx, void *create_ctx );
1023 + void (*Destroy)( FusionEntry *entry, void *ctx );
1024 + int (*Print) ( FusionEntry *entry, void *ctx, char *buf );
1025 +} FusionEntryClass;
1028 +typedef struct {
1029 + FusionEntryClass *class;
1030 + void *ctx;
1032 + FusionLink *list;
1033 + int ids;
1034 + struct semaphore lock;
1035 +} FusionEntries;
1038 +struct __FD_FusionEntry {
1039 + FusionLink link;
1041 + FusionEntries *entries;
1043 + int id;
1044 + pid_t pid;
1046 + pid_t lock_pid;
1048 + struct semaphore lock;
1049 + wait_queue_head_t wait;
1050 + int waiters;
1052 + struct timeval last_lock;
1054 + char name[FUSION_ENTRY_INFO_NAME_LENGTH];
1058 +/* Entries Init & DeInit */
1060 +void fusion_entries_init ( FusionEntries *entries,
1061 + FusionEntryClass *class,
1062 + void *ctx );
1064 +void fusion_entries_deinit( FusionEntries *entries );
1067 +/* '/proc' support */
1069 +int fusion_entries_read_proc( char *buf, char **start, off_t offset,
1070 + int len, int *eof, void *private );
1073 +/* Create & Destroy */
1075 +int fusion_entry_create ( FusionEntries *entries,
1076 + int *ret_id,
1077 + void *create_ctx );
1079 +int fusion_entry_destroy ( FusionEntries *entries,
1080 + int id );
1082 +void fusion_entry_destroy_locked( FusionEntries *entries,
1083 + FusionEntry *entry );
1085 +/* Information */
1087 +int fusion_entry_set_info( FusionEntries *entries,
1088 + const FusionEntryInfo *info );
1090 +int fusion_entry_get_info( FusionEntries *entries,
1091 + FusionEntryInfo *info );
1094 +/* Lock & Unlock */
1096 +int fusion_entry_lock ( FusionEntries *entries,
1097 + int id,
1098 + bool keep_entries_lock,
1099 + FusionEntry **ret_entry );
1101 +void fusion_entry_unlock ( FusionEntry *entry );
1104 +/** Wait & Notify **/
1107 + * Wait for the entry to be notified with an optional timeout.
1109 + * The entry
1110 + * (1) has to be locked prior to calling this function.
1111 + * (2) is temporarily unlocked while being waited for.
1113 + * If this function returns an error, the entry is not locked again!
1115 + * Possible errors are:
1116 + * -EIDRM Entry has been removed while being waited for.
1117 + * -ETIMEDOUT Timeout occured.
1118 + * -EINTR A signal has been received.
1119 + */
1120 +int fusion_entry_wait ( FusionEntry *entry,
1121 + long *timeout );
1124 + * Wake up one or all processes waiting for the entry to be notified.
1126 + * The entry has to be locked prior to calling this function.
1127 + */
1128 +void fusion_entry_notify ( FusionEntry *entry,
1129 + bool all );
1132 +#define FUSION_ENTRY_CLASS( Type, name, init_func, destroy_func, print_func ) \
1134 + static FusionEntryClass name##_class = { \
1135 + .object_size = sizeof(Type), \
1136 + .Init = init_func, \
1137 + .Destroy = destroy_func, \
1138 + .Print = print_func \
1139 + }; \
1141 + static inline int fusion_##name##_lock( FusionEntries *entries, \
1142 + int id, \
1143 + bool keep, \
1144 + Type **ret_##name ) \
1145 + { \
1146 + int ret; \
1147 + FusionEntry *entry; \
1149 + ret = fusion_entry_lock( entries, id, keep, &entry ); \
1151 + if (!ret) \
1152 + *ret_##name = (Type *) entry; \
1154 + return ret; \
1155 + } \
1157 + static inline void fusion_##name##_unlock( Type *name ) \
1158 + { \
1159 + fusion_entry_unlock( (FusionEntry*) name ); \
1160 + } \
1162 + static inline int fusion_##name##_wait( Type *name, long *timeout ) \
1163 + { \
1164 + return fusion_entry_wait( (FusionEntry*) name, timeout ); \
1165 + } \
1167 + static inline void fusion_##name##_notify( Type *name, bool all ) \
1168 + { \
1169 + fusion_entry_notify( (FusionEntry*) name, all ); \
1173 +#endif
1174 diff -urN linux-2.6.22.1-0rig/drivers/char/fusion/fifo.c linux-2.6.22.1/drivers/char/fusion/fifo.c
1175 --- linux-2.6.22.1-0rig/drivers/char/fusion/fifo.c 1970-01-01 01:00:00.000000000 +0100
1176 +++ linux-2.6.22.1/drivers/char/fusion/fifo.c 2003-06-16 19:47:03.000000000 +0200
1177 @@ -0,0 +1,53 @@
1179 + * Fusion Kernel Module
1181 + * (c) Copyright 2002-2003 Convergence GmbH
1183 + * Written by Denis Oliver Kropp <dok@directfb.org>
1186 + * This program is free software; you can redistribute it and/or
1187 + * modify it under the terms of the GNU General Public License
1188 + * as published by the Free Software Foundation; either version
1189 + * 2 of the License, or (at your option) any later version.
1190 + */
1192 +#include <linux/types.h>
1194 +#include "fifo.h"
1196 +void
1197 +fusion_fifo_put (FusionFifo *fifo, FusionLink *link)
1199 + link->prev = fifo->last;
1200 + link->next = NULL;
1202 + if (fifo->last)
1203 + fifo->last->next = link;
1204 + else
1205 + fifo->first = link;
1207 + fifo->last = link;
1209 + fifo->count++;
1212 +FusionLink *
1213 +fusion_fifo_get (FusionFifo *fifo)
1215 + FusionLink *first = fifo->first;
1217 + if (!first)
1218 + return NULL;
1220 + fifo->first = first->next;
1222 + if (fifo->last == first)
1223 + fifo->last = NULL;
1224 + else
1225 + fifo->first->prev = NULL;
1227 + fifo->count--;
1229 + return first;
1231 diff -urN linux-2.6.22.1-0rig/drivers/char/fusion/fifo.h linux-2.6.22.1/drivers/char/fusion/fifo.h
1232 --- linux-2.6.22.1-0rig/drivers/char/fusion/fifo.h 1970-01-01 01:00:00.000000000 +0100
1233 +++ linux-2.6.22.1/drivers/char/fusion/fifo.h 2003-06-16 19:47:03.000000000 +0200
1234 @@ -0,0 +1,36 @@
1236 + * Fusion Kernel Module
1238 + * (c) Copyright 2002-2003 Convergence GmbH
1240 + * Written by Denis Oliver Kropp <dok@directfb.org>
1243 + * This program is free software; you can redistribute it and/or
1244 + * modify it under the terms of the GNU General Public License
1245 + * as published by the Free Software Foundation; either version
1246 + * 2 of the License, or (at your option) any later version.
1247 + */
1249 +#ifndef __FUSION__FIFO_H__
1250 +#define __FUSION__FIFO_H__
1252 +#include "types.h"
1253 +#include "list.h"
1255 +typedef struct {
1256 + FusionLink *first;
1257 + FusionLink *last;
1259 + int count;
1260 +} FusionFifo;
1262 +void fusion_fifo_put (FusionFifo *fifo,
1263 + FusionLink *link);
1265 +FusionLink *fusion_fifo_get (FusionFifo *fifo);
1267 +int fusion_fifo_count (FusionFifo *fifo);
1269 +#endif /* __FUSION__LIST_H__ */
1271 diff -urN linux-2.6.22.1-0rig/drivers/char/fusion/fusiondev.c linux-2.6.22.1/drivers/char/fusion/fusiondev.c
1272 --- linux-2.6.22.1-0rig/drivers/char/fusion/fusiondev.c 1970-01-01 01:00:00.000000000 +0100
1273 +++ linux-2.6.22.1/drivers/char/fusion/fusiondev.c 2007-03-08 14:02:47.000000000 +0100
1274 @@ -0,0 +1,1187 @@
1276 + * Fusion Kernel Module
1278 + * (c) Copyright 2002-2003 Convergence GmbH
1280 + * Written by Denis Oliver Kropp <dok@directfb.org>
1283 + * This program is free software; you can redistribute it and/or
1284 + * modify it under the terms of the GNU General Public License
1285 + * as published by the Free Software Foundation; either version
1286 + * 2 of the License, or (at your option) any later version.
1287 + */
1289 +#include <linux/version.h>
1290 +#include <linux/module.h>
1291 +#ifdef HAVE_LINUX_CONFIG_H
1292 +#include <linux/config.h>
1293 +#endif
1294 +#include <linux/types.h>
1295 +#include <linux/kernel.h>
1296 +#include <linux/fs.h>
1297 +#include <linux/slab.h>
1298 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18)
1299 +#include <linux/devfs_fs_kernel.h>
1300 +#endif
1301 +#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 19)
1302 +#include <linux/page-flags.h>
1303 +#include <linux/mm.h>
1304 +#endif
1306 +#include <linux/proc_fs.h>
1307 +#include <linux/poll.h>
1308 +#include <linux/init.h>
1309 +#include <asm/io.h>
1310 +#include <asm/uaccess.h>
1312 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 2)
1313 +#include <linux/device.h>
1314 +#endif
1316 +#include <linux/fusion.h>
1318 +#include "call.h"
1319 +#include "fusiondev.h"
1320 +#include "fusionee.h"
1321 +#include "property.h"
1322 +#include "reactor.h"
1323 +#include "ref.h"
1324 +#include "skirmish.h"
1325 +#include "shmpool.h"
1327 +#if 0
1328 +#define DEBUG(x...) printk (KERN_DEBUG "Fusion: " x)
1329 +#else
1330 +#define DEBUG(x...) do {} while (0)
1331 +#endif
1333 +#ifndef FUSION_MAJOR
1334 +#define FUSION_MAJOR 252
1335 +#endif
1337 +MODULE_LICENSE("GPL");
1338 +MODULE_AUTHOR("Denis Oliver Kropp <dok@directfb.org>");
1340 +struct proc_dir_entry *proc_fusion_dir;
1342 +#define NUM_MINORS 8
1344 +static FusionDev *fusion_devs[NUM_MINORS] = { 0 };
1345 +static DECLARE_MUTEX(devs_lock);
1347 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)
1348 +static devfs_handle_t devfs_handles[NUM_MINORS];
1349 +static inline unsigned iminor(struct inode *inode)
1351 + return MINOR(inode->i_rdev);
1353 +#endif
1355 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 2)
1356 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 13)
1357 +static struct class *fusion_class;
1358 +#else
1359 +static struct class_simple *fusion_class;
1360 +#endif
1361 +#endif
1363 +/******************************************************************************/
1365 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
1366 +void
1367 +fusion_sleep_on(wait_queue_head_t *q, struct semaphore *lock, signed long *timeout)
1369 + DEFINE_WAIT(wait);
1371 + prepare_to_wait( q, &wait, TASK_INTERRUPTIBLE );
1373 + up( lock );
1375 + if (timeout)
1376 + *timeout = schedule_timeout(*timeout);
1377 + else
1378 + schedule();
1380 + finish_wait( q, &wait );
1382 +#else
1383 +void
1384 +fusion_sleep_on(wait_queue_head_t *q, struct semaphore *lock, signed long *timeout)
1386 + wait_queue_t wait;
1388 + init_waitqueue_entry (&wait, current);
1390 + current->state = TASK_INTERRUPTIBLE;
1392 + write_lock (&q->lock);
1393 + __add_wait_queue (q, &wait);
1394 + write_unlock (&q->lock);
1396 + up (lock);
1398 + if (timeout)
1399 + *timeout = schedule_timeout(*timeout);
1400 + else
1401 + schedule();
1403 + write_lock (&q->lock);
1404 + __remove_wait_queue (q, &wait);
1405 + write_unlock (&q->lock);
1407 +#endif
1409 +/******************************************************************************/
1411 +static int
1412 +fusiondev_stat_read_proc(char *buf, char **start, off_t offset,
1413 + int len, int *eof, void *private)
1415 + FusionDev *dev = private;
1416 + int written = 0;
1418 + written += snprintf( buf, len,
1419 + "lease/purchase cede attach detach "
1420 + "ref up ref down prevail/swoop dismiss\n" );
1421 + if (written < offset) {
1422 + offset -= written;
1423 + written = 0;
1426 + if (written < len) {
1427 + written += snprintf( buf+written, len - written,
1428 + "%10d %10d %10d %10d %10d %10d %10d %10d\n",
1429 + dev->stat.property_lease_purchase,
1430 + dev->stat.property_cede,
1431 + dev->stat.reactor_attach,
1432 + dev->stat.reactor_detach,
1433 + dev->stat.ref_up,
1434 + dev->stat.ref_down,
1435 + dev->stat.skirmish_prevail_swoop,
1436 + dev->stat.skirmish_dismiss );
1437 + if (written < offset) {
1438 + offset -= written;
1439 + written = 0;
1443 + *start = buf + offset;
1444 + written -= offset;
1445 + if (written > len) {
1446 + *eof = 0;
1447 + return len;
1450 + *eof = 1;
1451 + return(written<0) ? 0 : written;
1454 +/******************************************************************************/
1456 +static int
1457 +fusiondev_init (FusionDev *dev)
1459 + int ret;
1461 + init_MUTEX( &dev->enter_lock );
1462 + init_waitqueue_head( &dev->enter_wait );
1464 + ret = fusionee_init (dev);
1465 + if (ret)
1466 + goto error_fusionee;
1468 + ret = fusion_ref_init (dev);
1469 + if (ret)
1470 + goto error_ref;
1472 + ret = fusion_skirmish_init (dev);
1473 + if (ret)
1474 + goto error_skirmish;
1476 + ret = fusion_property_init (dev);
1477 + if (ret)
1478 + goto error_property;
1480 + ret = fusion_reactor_init (dev);
1481 + if (ret)
1482 + goto error_reactor;
1484 + ret = fusion_shmpool_init (dev);
1485 + if (ret)
1486 + goto error_shmpool;
1488 + ret = fusion_call_init (dev);
1489 + if (ret)
1490 + goto error_call;
1492 + create_proc_read_entry( "stat", 0, dev->proc_dir,
1493 + fusiondev_stat_read_proc, dev );
1495 + return 0;
1498 +error_call:
1499 + fusion_shmpool_deinit (dev);
1501 +error_shmpool:
1502 + fusion_reactor_deinit (dev);
1504 +error_reactor:
1505 + fusion_property_deinit (dev);
1507 +error_property:
1508 + fusion_skirmish_deinit (dev);
1510 +error_skirmish:
1511 + fusion_ref_deinit (dev);
1513 +error_ref:
1514 + fusionee_deinit (dev);
1516 +error_fusionee:
1517 + return ret;
1520 +static void
1521 +fusiondev_deinit (FusionDev *dev)
1523 + remove_proc_entry ("stat", dev->proc_dir);
1525 + fusion_call_deinit (dev);
1526 + fusion_shmpool_deinit (dev);
1527 + fusion_reactor_deinit (dev);
1528 + fusion_property_deinit (dev);
1529 + fusion_skirmish_deinit (dev);
1530 + fusion_ref_deinit (dev);
1531 + fusionee_deinit (dev);
1533 + if (dev->shared_area) {
1534 + ClearPageReserved( virt_to_page(dev->shared_area) );
1535 + free_page( dev->shared_area );
1539 +/******************************************************************************/
1541 +static int
1542 +fusion_open (struct inode *inode, struct file *file)
1544 + int ret;
1545 + Fusionee *fusionee;
1546 + int minor = iminor(inode);
1548 + DEBUG( "fusion_open( %p, %d )\n", file, atomic_read(&file->f_count) );
1550 + if (down_interruptible (&devs_lock))
1551 + return -EINTR;
1553 + if (!fusion_devs[minor]) {
1554 + char buf[4];
1556 + fusion_devs[minor] = kmalloc (sizeof(FusionDev), GFP_KERNEL);
1557 + if (!fusion_devs[minor]) {
1558 + up (&devs_lock);
1559 + return -ENOMEM;
1562 + memset (fusion_devs[minor], 0, sizeof(FusionDev));
1564 + snprintf (buf, 4, "%d", minor);
1566 + fusion_devs[minor]->proc_dir = proc_mkdir (buf, proc_fusion_dir);
1567 + fusion_devs[minor]->index = minor;
1569 + ret = fusiondev_init (fusion_devs[minor]);
1570 + if (ret) {
1571 + remove_proc_entry (buf, proc_fusion_dir);
1573 + kfree (fusion_devs[minor]);
1574 + fusion_devs[minor] = NULL;
1576 + up (&devs_lock);
1578 + return ret;
1581 + else if (file->f_flags & O_EXCL) {
1582 + if (fusion_devs[minor]->fusionee.last_id) {
1583 + up (&devs_lock);
1584 + return -EBUSY;
1588 + ret = fusionee_new (fusion_devs[minor], !!(file->f_flags & O_APPEND), &fusionee);
1589 + if (ret) {
1590 + if (!fusion_devs[minor]->refs) {
1591 + fusiondev_deinit (fusion_devs[minor]);
1593 + remove_proc_entry (fusion_devs[minor]->proc_dir->name,
1594 + proc_fusion_dir);
1596 + kfree (fusion_devs[minor]);
1597 + fusion_devs[minor] = NULL;
1600 + up (&devs_lock);
1602 + return ret;
1605 + fusion_devs[minor]->refs++;
1607 + up (&devs_lock);
1610 + file->private_data = fusionee;
1612 + return 0;
1615 +static int
1616 +fusion_release (struct inode *inode, struct file *file)
1618 + int minor = iminor(inode);
1619 + Fusionee *fusionee = file->private_data;
1621 + DEBUG( "fusion_release( %p, %d )\n", file, atomic_read(&file->f_count) );
1623 + fusionee_destroy (fusion_devs[minor], fusionee);
1625 + down (&devs_lock);
1627 + if (! --fusion_devs[minor]->refs) {
1628 + fusiondev_deinit (fusion_devs[minor]);
1630 + remove_proc_entry (fusion_devs[minor]->proc_dir->name,
1631 + proc_fusion_dir);
1633 + kfree (fusion_devs[minor]);
1634 + fusion_devs[minor] = NULL;
1637 + up (&devs_lock);
1639 + return 0;
1642 +static int
1643 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18)
1644 +fusion_flush (struct file *file, fl_owner_t id)
1645 +#else
1646 +fusion_flush (struct file *file)
1647 +#endif
1649 + Fusionee *fusionee = file->private_data;
1650 + FusionDev *dev = fusion_devs[iminor(file->f_dentry->d_inode)];
1652 + (void) fusionee;
1654 + DEBUG( "fusion_flush( %p, %d, 0x%08x %d )\n", file, atomic_read(&file->f_count), fusionee_id(fusionee), current->pid );
1656 + if (current->flags & PF_EXITING)
1657 + fusion_skirmish_dismiss_all_from_pid (dev, current->pid);
1659 + return 0;
1662 +static ssize_t
1663 +fusion_read (struct file *file, char *buf, size_t count, loff_t *ppos)
1665 + Fusionee *fusionee = file->private_data;
1666 + FusionDev *dev = fusion_devs[iminor(file->f_dentry->d_inode)];
1668 + DEBUG( "fusion_read( %p, %d, %d )\n", file, atomic_read(&file->f_count), count );
1670 + return fusionee_get_messages (dev, fusionee, buf, count,
1671 + !(file->f_flags & O_NONBLOCK));
1674 +static unsigned int
1675 +fusion_poll (struct file *file, poll_table * wait)
1677 + Fusionee *fusionee = file->private_data;
1678 + FusionDev *dev = fusion_devs[iminor(file->f_dentry->d_inode)];
1680 + DEBUG( "fusion_poll( %p, %d )\n", file, atomic_read(&file->f_count) );
1682 + return fusionee_poll (dev, fusionee, file, wait);
1685 +static int
1686 +lounge_ioctl (struct file *file, FusionDev *dev, Fusionee *fusionee,
1687 + unsigned int cmd, unsigned long arg)
1689 + int ret;
1690 + FusionEnter enter;
1691 + FusionKill kill;
1692 + FusionEntryInfo info;
1693 + FusionFork fork = {0};
1695 + switch (_IOC_NR(cmd)) {
1696 + case _IOC_NR(FUSION_ENTER):
1697 + if (copy_from_user (&enter, (FusionEnter*) arg, sizeof(enter)))
1698 + return -EFAULT;
1700 + ret = fusionee_enter( dev, &enter, fusionee );
1701 + if (ret)
1702 + return ret;
1704 + if (copy_to_user ((FusionEnter*) arg, &enter, sizeof(enter)))
1705 + return -EFAULT;
1707 + return 0;
1709 + case _IOC_NR(FUSION_UNBLOCK):
1710 + if (fusionee_id( fusionee ) != FUSION_ID_MASTER)
1711 + return -EPERM;
1713 + if (down_interruptible( &dev->enter_lock ))
1714 + return -EINTR;
1716 + dev->enter_ok = 1;
1718 + wake_up_interruptible_all( &dev->enter_wait );
1720 + up( &dev->enter_lock );
1722 + return 0;
1724 + case _IOC_NR(FUSION_KILL):
1725 + if (copy_from_user (&kill, (FusionKill*) arg, sizeof(kill)))
1726 + return -EFAULT;
1728 + return fusionee_kill (dev, fusionee,
1729 + kill.fusion_id, kill.signal, kill.timeout_ms);
1731 + case _IOC_NR(FUSION_ENTRY_SET_INFO):
1732 + if (copy_from_user (&info, (FusionEntryInfo*) arg, sizeof(info)))
1733 + return -EFAULT;
1735 + switch (info.type) {
1736 + case FT_SKIRMISH:
1737 + return fusion_entry_set_info (&dev->skirmish, &info);
1739 + case FT_PROPERTY:
1740 + return fusion_entry_set_info (&dev->properties, &info);
1742 + case FT_REACTOR:
1743 + return fusion_entry_set_info (&dev->reactor, &info);
1745 + case FT_REF:
1746 + return fusion_entry_set_info (&dev->ref, &info);
1748 + case FT_SHMPOOL:
1749 + return fusion_entry_set_info (&dev->shmpool, &info);
1751 + default:
1752 + return -ENOSYS;
1755 + case _IOC_NR(FUSION_ENTRY_GET_INFO):
1756 + if (copy_from_user (&info, (FusionEntryInfo*) arg, sizeof(info)))
1757 + return -EFAULT;
1759 + switch (info.type) {
1760 + case FT_SKIRMISH:
1761 + ret = fusion_entry_get_info (&dev->skirmish, &info);
1762 + break;
1764 + case FT_PROPERTY:
1765 + ret = fusion_entry_get_info (&dev->properties, &info);
1766 + break;
1768 + case FT_REACTOR:
1769 + ret = fusion_entry_get_info (&dev->reactor, &info);
1770 + break;
1772 + case FT_REF:
1773 + ret = fusion_entry_get_info (&dev->ref, &info);
1774 + break;
1776 + case FT_SHMPOOL:
1777 + ret = fusion_entry_get_info (&dev->shmpool, &info);
1778 + break;
1780 + default:
1781 + return -ENOSYS;
1784 + if (ret)
1785 + return ret;
1787 + if (copy_to_user ((FusionEntryInfo*) arg, &info, sizeof(info)))
1788 + return -EFAULT;
1790 + return 0;
1792 + case _IOC_NR(FUSION_FORK):
1793 + if (copy_from_user( &fork, (FusionFork*) arg, sizeof(fork) ))
1794 + return -EFAULT;
1796 + ret = fusionee_fork( dev, &fork, fusionee );
1797 + if (ret)
1798 + return ret;
1800 + if (copy_to_user( (FusionFork*) arg, &fork, sizeof(fork) ))
1801 + return -EFAULT;
1803 + return 0;
1806 + return -ENOSYS;
1809 +static int
1810 +messaging_ioctl (FusionDev *dev, Fusionee *fusionee,
1811 + unsigned int cmd, unsigned long arg)
1813 + FusionSendMessage send;
1815 + switch (_IOC_NR(cmd)) {
1816 + case _IOC_NR(FUSION_SEND_MESSAGE):
1817 + if (copy_from_user (&send, (FusionSendMessage*) arg, sizeof(send)))
1818 + return -EFAULT;
1820 + if (send.msg_size <= 0)
1821 + return -EINVAL;
1823 + /* message data > 64k should be stored in shared memory */
1824 + if (send.msg_size > 0x10000)
1825 + return -EMSGSIZE;
1827 + return fusionee_send_message (dev, fusionee, send.fusion_id, FMT_SEND,
1828 + send.msg_id, send.msg_size, send.msg_data);
1831 + return -ENOSYS;
1834 +static int
1835 +call_ioctl (FusionDev *dev, Fusionee *fusionee,
1836 + unsigned int cmd, unsigned long arg)
1838 + int id;
1839 + int ret;
1840 + FusionCallNew call;
1841 + FusionCallExecute execute;
1842 + FusionCallReturn call_ret;
1843 + FusionID fusion_id = fusionee_id( fusionee );
1845 + switch (_IOC_NR(cmd)) {
1846 + case _IOC_NR(FUSION_CALL_NEW):
1847 + if (copy_from_user (&call, (FusionCallNew*) arg, sizeof(call)))
1848 + return -EFAULT;
1850 + ret = fusion_call_new (dev, fusion_id, &call);
1851 + if (ret)
1852 + return ret;
1854 + if (put_user (call.call_id, (int*) arg)) {
1855 + fusion_call_destroy (dev, fusion_id, call.call_id);
1856 + return -EFAULT;
1858 + return 0;
1860 + case _IOC_NR(FUSION_CALL_EXECUTE):
1861 + if (copy_from_user (&execute, (FusionCallExecute*) arg, sizeof(execute)))
1862 + return -EFAULT;
1864 + ret = fusion_call_execute (dev, fusionee, &execute);
1865 + if (ret)
1866 + return ret;
1868 + if (put_user (execute.ret_val, (int*) arg))
1869 + return -EFAULT;
1870 + return 0;
1872 + case _IOC_NR(FUSION_CALL_RETURN):
1873 + if (copy_from_user (&call_ret, (FusionCallReturn*) arg, sizeof(call_ret)))
1874 + return -EFAULT;
1876 + return fusion_call_return (dev, fusion_id, &call_ret);
1878 + case _IOC_NR(FUSION_CALL_DESTROY):
1879 + if (get_user (id, (int*) arg))
1880 + return -EFAULT;
1882 + return fusion_call_destroy (dev, fusion_id, id);
1885 + return -ENOSYS;
1888 +static int
1889 +ref_ioctl (FusionDev *dev, Fusionee *fusionee,
1890 + unsigned int cmd, unsigned long arg)
1892 + int id;
1893 + int ret;
1894 + int refs;
1895 + FusionRefWatch watch;
1896 + FusionRefInherit inherit;
1897 + FusionID fusion_id = fusionee_id( fusionee );
1899 + switch (_IOC_NR(cmd)) {
1900 + case _IOC_NR(FUSION_REF_NEW):
1901 + ret = fusion_ref_new (dev, &id);
1902 + if (ret)
1903 + return ret;
1905 + if (put_user (id, (int*) arg)) {
1906 + fusion_ref_destroy (dev, id);
1907 + return -EFAULT;
1909 + return 0;
1911 + case _IOC_NR(FUSION_REF_UP):
1912 + if (get_user (id, (int*) arg))
1913 + return -EFAULT;
1915 + return fusion_ref_up (dev, id, fusion_id);
1917 + case _IOC_NR(FUSION_REF_UP_GLOBAL):
1918 + if (get_user (id, (int*) arg))
1919 + return -EFAULT;
1921 + return fusion_ref_up (dev, id, 0);
1923 + case _IOC_NR(FUSION_REF_DOWN):
1924 + if (get_user (id, (int*) arg))
1925 + return -EFAULT;
1927 + return fusion_ref_down (dev, id, fusion_id);
1929 + case _IOC_NR(FUSION_REF_DOWN_GLOBAL):
1930 + if (get_user (id, (int*) arg))
1931 + return -EFAULT;
1933 + return fusion_ref_down (dev, id, 0);
1935 + case _IOC_NR(FUSION_REF_ZERO_LOCK):
1936 + if (get_user (id, (int*) arg))
1937 + return -EFAULT;
1939 + return fusion_ref_zero_lock (dev, id, fusion_id);
1941 + case _IOC_NR(FUSION_REF_ZERO_TRYLOCK):
1942 + if (get_user (id, (int*) arg))
1943 + return -EFAULT;
1945 + return fusion_ref_zero_trylock (dev, id, fusion_id);
1947 + case _IOC_NR(FUSION_REF_UNLOCK):
1948 + if (get_user (id, (int*) arg))
1949 + return -EFAULT;
1951 + return fusion_ref_zero_unlock (dev, id, fusion_id);
1953 + case _IOC_NR(FUSION_REF_STAT):
1954 + if (get_user (id, (int*) arg))
1955 + return -EFAULT;
1957 + ret = fusion_ref_stat (dev, id, &refs);
1958 + if (ret)
1959 + return ret;
1961 + return refs;
1963 + case _IOC_NR(FUSION_REF_WATCH):
1964 + if (copy_from_user (&watch, (FusionRefWatch*) arg, sizeof(watch)))
1965 + return -EFAULT;
1967 + return fusion_ref_watch (dev, watch.id, watch.call_id, watch.call_arg);
1969 + case _IOC_NR(FUSION_REF_INHERIT):
1970 + if (copy_from_user (&inherit, (FusionRefInherit*) arg, sizeof(inherit)))
1971 + return -EFAULT;
1973 + return fusion_ref_inherit (dev, inherit.id, inherit.from);
1975 + case _IOC_NR(FUSION_REF_DESTROY):
1976 + if (get_user (id, (int*) arg))
1977 + return -EFAULT;
1979 + return fusion_ref_destroy (dev, id);
1982 + return -ENOSYS;
1985 +static int
1986 +skirmish_ioctl (FusionDev *dev, Fusionee *fusionee,
1987 + unsigned int cmd, unsigned long arg)
1989 + int id;
1990 + int ret;
1991 + int lock_count;
1992 + FusionID fusion_id = fusionee_id( fusionee );
1994 + switch (_IOC_NR(cmd)) {
1995 + case _IOC_NR(FUSION_SKIRMISH_NEW):
1996 + ret = fusion_skirmish_new (dev, &id);
1997 + if (ret)
1998 + return ret;
2000 + if (put_user (id, (int*) arg)) {
2001 + fusion_skirmish_destroy (dev, id);
2002 + return -EFAULT;
2004 + return 0;
2006 + case _IOC_NR(FUSION_SKIRMISH_PREVAIL):
2007 + if (get_user (id, (int*) arg))
2008 + return -EFAULT;
2010 + return fusion_skirmish_prevail (dev, id, fusion_id);
2012 + case _IOC_NR(FUSION_SKIRMISH_SWOOP):
2013 + if (get_user (id, (int*) arg))
2014 + return -EFAULT;
2016 + return fusion_skirmish_swoop (dev, id, fusion_id);
2018 + case _IOC_NR(FUSION_SKIRMISH_DISMISS):
2019 + if (get_user (id, (int*) arg))
2020 + return -EFAULT;
2022 + return fusion_skirmish_dismiss (dev, id, fusion_id);
2024 + case _IOC_NR(FUSION_SKIRMISH_DESTROY):
2025 + if (get_user (id, (int*) arg))
2026 + return -EFAULT;
2028 + return fusion_skirmish_destroy (dev, id);
2030 + case _IOC_NR(FUSION_SKIRMISH_LOCK_COUNT):
2031 + if (get_user (id, (int*) arg))
2032 + return -EFAULT;
2034 + ret = fusion_skirmish_lock_count (dev, id, fusion_id, &lock_count);
2035 + if (put_user(lock_count, ((int*)arg)+1))
2036 + return -EFAULT;
2038 + return ret;
2041 + return -ENOSYS;
2044 +static int
2045 +property_ioctl (FusionDev *dev, Fusionee *fusionee,
2046 + unsigned int cmd, unsigned long arg)
2048 + int id;
2049 + int ret;
2050 + FusionID fusion_id = fusionee_id( fusionee );
2052 + switch (_IOC_NR(cmd)) {
2053 + case _IOC_NR(FUSION_PROPERTY_NEW):
2054 + ret = fusion_property_new (dev, &id);
2055 + if (ret)
2056 + return ret;
2058 + if (put_user (id, (int*) arg)) {
2059 + fusion_property_destroy (dev, id);
2060 + return -EFAULT;
2062 + return 0;
2064 + case _IOC_NR(FUSION_PROPERTY_LEASE):
2065 + if (get_user (id, (int*) arg))
2066 + return -EFAULT;
2068 + return fusion_property_lease (dev, id, fusion_id);
2070 + case _IOC_NR(FUSION_PROPERTY_PURCHASE):
2071 + if (get_user (id, (int*) arg))
2072 + return -EFAULT;
2074 + return fusion_property_purchase (dev, id, fusion_id);
2076 + case _IOC_NR(FUSION_PROPERTY_CEDE):
2077 + if (get_user (id, (int*) arg))
2078 + return -EFAULT;
2080 + return fusion_property_cede (dev, id, fusion_id);
2082 + case _IOC_NR(FUSION_PROPERTY_HOLDUP):
2083 + if (get_user (id, (int*) arg))
2084 + return -EFAULT;
2086 + return fusion_property_holdup (dev, id, fusionee);
2088 + case _IOC_NR(FUSION_PROPERTY_DESTROY):
2089 + if (get_user (id, (int*) arg))
2090 + return -EFAULT;
2092 + return fusion_property_destroy (dev, id);
2095 + return -ENOSYS;
2098 +static int
2099 +reactor_ioctl (FusionDev *dev, Fusionee *fusionee,
2100 + unsigned int cmd, unsigned long arg)
2102 + int id;
2103 + int ret;
2104 + FusionReactorDispatch dispatch;
2105 + FusionID fusion_id = fusionee_id( fusionee );
2107 + switch (_IOC_NR(cmd)) {
2108 + case _IOC_NR(FUSION_REACTOR_NEW):
2109 + ret = fusion_reactor_new (dev, &id);
2110 + if (ret)
2111 + return ret;
2113 + if (put_user (id, (int*) arg)) {
2114 + fusion_reactor_destroy (dev, id);
2115 + return -EFAULT;
2117 + return 0;
2119 + case _IOC_NR(FUSION_REACTOR_ATTACH):
2120 + if (get_user (id, (int*) arg))
2121 + return -EFAULT;
2123 + return fusion_reactor_attach (dev, id, fusion_id);
2125 + case _IOC_NR(FUSION_REACTOR_DETACH):
2126 + if (get_user (id, (int*) arg))
2127 + return -EFAULT;
2129 + return fusion_reactor_detach (dev, id, fusion_id);
2131 + case _IOC_NR(FUSION_REACTOR_DISPATCH):
2132 + if (copy_from_user (&dispatch,
2133 + (FusionReactorDispatch*) arg, sizeof(dispatch)))
2134 + return -EFAULT;
2136 + if (dispatch.msg_size <= 0)
2137 + return -EINVAL;
2139 + /* message data > 64k should be stored in shared memory */
2140 + if (dispatch.msg_size > 0x10000)
2141 + return -EMSGSIZE;
2143 + return fusion_reactor_dispatch (dev, dispatch.reactor_id,
2144 + dispatch.self ? NULL : fusionee,
2145 + dispatch.msg_size, dispatch.msg_data);
2147 + case _IOC_NR(FUSION_REACTOR_DESTROY):
2148 + if (get_user (id, (int*) arg))
2149 + return -EFAULT;
2151 + return fusion_reactor_destroy (dev, id);
2154 + return -ENOSYS;
2157 +static int
2158 +shmpool_ioctl (FusionDev *dev, Fusionee *fusionee,
2159 + unsigned int cmd, unsigned long arg)
2161 + int id;
2162 + int ret;
2163 + FusionSHMPoolNew pool;
2164 + FusionSHMPoolAttach attach;
2165 + FusionSHMPoolDispatch dispatch;
2166 + FusionID fusion_id = fusionee_id( fusionee );
2168 + switch (_IOC_NR(cmd)) {
2169 + case _IOC_NR(FUSION_SHMPOOL_NEW):
2170 + if (copy_from_user (&pool, (FusionSHMPoolNew*) arg, sizeof(pool)))
2171 + return -EFAULT;
2173 + ret = fusion_shmpool_new (dev, &pool);
2174 + if (ret)
2175 + return ret;
2177 + if (copy_to_user ((FusionSHMPoolNew*) arg, &pool, sizeof(pool))) {
2178 + fusion_shmpool_destroy (dev, pool.pool_id);
2179 + return -EFAULT;
2182 + return 0;
2184 + case _IOC_NR(FUSION_SHMPOOL_ATTACH):
2185 + if (copy_from_user (&attach,
2186 + (FusionSHMPoolAttach*) arg, sizeof(attach)))
2187 + return -EFAULT;
2189 + ret = fusion_shmpool_attach (dev, &attach, fusion_id);
2190 + if (ret)
2191 + return ret;
2193 + if (copy_to_user ((FusionSHMPoolAttach*) arg, &attach, sizeof(attach))) {
2194 + fusion_shmpool_detach (dev, attach.pool_id, fusion_id);
2195 + return -EFAULT;
2198 + return 0;
2200 + case _IOC_NR(FUSION_SHMPOOL_DETACH):
2201 + if (get_user (id, (int*) arg))
2202 + return -EFAULT;
2204 + return fusion_shmpool_detach (dev, id, fusion_id);
2206 + case _IOC_NR(FUSION_SHMPOOL_DISPATCH):
2207 + if (copy_from_user (&dispatch,
2208 + (FusionSHMPoolDispatch*) arg, sizeof(dispatch)))
2209 + return -EFAULT;
2211 + return fusion_shmpool_dispatch (dev, &dispatch, fusionee);
2213 + case _IOC_NR(FUSION_SHMPOOL_DESTROY):
2214 + if (get_user (id, (int*) arg))
2215 + return -EFAULT;
2217 + return fusion_shmpool_destroy (dev, id);
2220 + return -ENOSYS;
2223 +static int
2224 +fusion_ioctl (struct inode *inode, struct file *file,
2225 + unsigned int cmd, unsigned long arg)
2227 + Fusionee *fusionee = file->private_data;
2228 + FusionDev *dev = fusion_devs[iminor(inode)];
2230 + DEBUG( "fusion_ioctl (0x%08x)\n", cmd );
2232 + switch (_IOC_TYPE(cmd)) {
2233 + case FT_LOUNGE:
2234 + return lounge_ioctl( file, dev, fusionee, cmd, arg );
2236 + case FT_MESSAGING:
2237 + return messaging_ioctl( dev, fusionee, cmd, arg );
2239 + case FT_CALL:
2240 + return call_ioctl( dev, fusionee, cmd, arg );
2242 + case FT_REF:
2243 + return ref_ioctl( dev, fusionee, cmd, arg );
2245 + case FT_SKIRMISH:
2246 + return skirmish_ioctl( dev, fusionee, cmd, arg );
2248 + case FT_PROPERTY:
2249 + return property_ioctl( dev, fusionee, cmd, arg );
2251 + case FT_REACTOR:
2252 + return reactor_ioctl( dev, fusionee, cmd, arg );
2254 + case FT_SHMPOOL:
2255 + return shmpool_ioctl( dev, fusionee, cmd, arg );
2258 + return -ENOSYS;
2261 +static int
2262 +fusion_mmap( struct file *file,
2263 + struct vm_area_struct *vma )
2265 + Fusionee *fusionee = file->private_data;
2266 + FusionDev *dev = fusion_devs[iminor(file->f_dentry->d_inode)];
2267 + unsigned int size;
2269 + if (vma->vm_pgoff != 0)
2270 + return -EINVAL;
2272 + size = vma->vm_end - vma->vm_start;
2273 + if (!size || size > PAGE_SIZE)
2274 + return -EINVAL;
2276 + if (!dev->shared_area) {
2277 + if (fusionee_id( fusionee ) != FUSION_ID_MASTER)
2278 + return -EPERM;
2280 + dev->shared_area = get_zeroed_page( GFP_KERNEL );
2281 + if (!dev->shared_area)
2282 + return -ENOMEM;
2284 + SetPageReserved( virt_to_page(dev->shared_area) );
2287 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
2288 + return remap_pfn_range( vma, vma->vm_start,
2289 + virt_to_phys((void*)dev->shared_area) >> PAGE_SHIFT,
2290 + PAGE_SIZE, vma->vm_page_prot );
2291 +#else
2292 + return io_remap_page_range( vma->vm_start,
2293 + virt_to_phys((void*)dev->shared_area),
2294 + PAGE_SIZE, vma->vm_page_prot );
2295 +#endif
2298 +static struct file_operations fusion_fops = {
2299 + .owner = THIS_MODULE,
2300 + .open = fusion_open,
2301 + .flush = fusion_flush,
2302 + .release = fusion_release,
2303 + .read = fusion_read,
2304 + .poll = fusion_poll,
2305 + .ioctl = fusion_ioctl,
2306 + .mmap = fusion_mmap
2309 +/******************************************************************************/
2311 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
2312 +static int __init
2313 +register_devices(void)
2315 + int i;
2317 + if (register_chrdev (FUSION_MAJOR, "fusion", &fusion_fops)) {
2318 + printk (KERN_ERR "fusion: unable to get major %d\n", FUSION_MAJOR);
2319 + return -EIO;
2322 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 2)
2323 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 13)
2324 + fusion_class = class_create (THIS_MODULE, "fusion");
2325 +#else
2326 + fusion_class = class_simple_create (THIS_MODULE, "fusion");
2327 +#endif
2328 + if (IS_ERR(fusion_class)) {
2329 + unregister_chrdev (FUSION_MAJOR, "fusion");
2330 + return PTR_ERR(fusion_class);
2332 +#endif
2334 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18)
2335 + devfs_mk_dir("fusion");
2336 +#endif
2338 + for (i=0; i<NUM_MINORS; i++) {
2339 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 15)
2340 + class_device_create (fusion_class,
2341 + NULL,
2342 + MKDEV(FUSION_MAJOR, i),
2343 + NULL, "fusion%d", i);
2344 +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 13)
2345 + class_device_create (fusion_class,
2346 + MKDEV(FUSION_MAJOR, i),
2347 + NULL, "fusion%d", i);
2348 +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 2)
2349 + class_simple_device_add (fusion_class,
2350 + MKDEV(FUSION_MAJOR, i),
2351 + NULL, "fusion%d", i);
2352 +#endif
2354 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18)
2355 + devfs_mk_cdev (MKDEV(FUSION_MAJOR, i),
2356 + S_IFCHR | S_IRUSR | S_IWUSR,
2357 + "fusion/%d", i);
2358 +#endif
2361 + return 0;
2363 +#else
2364 +static int __init
2365 +register_devices(void)
2367 + int i;
2368 + char buf[16];
2370 + if (devfs_register_chrdev (FUSION_MAJOR, "fusion", &fusion_fops)) {
2371 + printk (KERN_ERR "fusion: unable to get major %d\n", FUSION_MAJOR);
2372 + return -EIO;
2375 + for (i=0; i<NUM_MINORS; i++) {
2376 + snprintf (buf, 16, "fusion/%d", i);
2378 + devfs_handles[i] = devfs_register (NULL, buf, DEVFS_FL_DEFAULT,
2379 + FUSION_MAJOR, i,
2380 + S_IFCHR | S_IRUSR | S_IWUSR,
2381 + &fusion_fops, NULL);
2384 + return 0;
2386 +#endif
2388 +int __init
2389 +fusion_init(void)
2391 + int ret;
2393 + ret = register_devices();
2394 + if (ret)
2395 + return ret;
2397 + proc_fusion_dir = proc_mkdir ("fusion", NULL);
2399 + return 0;
2402 +/******************************************************************************/
2404 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
2405 +static void __exit
2406 +deregister_devices(void)
2408 + int i;
2410 + unregister_chrdev (FUSION_MAJOR, "fusion");
2412 + for (i=0; i<NUM_MINORS; i++) {
2413 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 2)
2414 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 13)
2415 + class_device_destroy (fusion_class, MKDEV(FUSION_MAJOR, i));
2416 +#else
2417 + class_simple_device_remove (MKDEV(FUSION_MAJOR, i));
2418 +#endif
2419 +#endif
2421 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18)
2422 + devfs_remove ("fusion/%d", i);
2423 +#endif
2426 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 2)
2427 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 13)
2428 + class_destroy (fusion_class);
2429 +#else
2430 + class_simple_destroy (fusion_class);
2431 +#endif
2432 +#endif
2434 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18)
2435 + devfs_remove ("fusion");
2436 +#endif
2438 +#else
2439 +static void __exit
2440 +deregister_devices(void)
2442 + int i;
2444 + devfs_unregister_chrdev (FUSION_MAJOR, "fusion");
2446 + for (i=0; i<NUM_MINORS; i++)
2447 + devfs_unregister (devfs_handles[i]);
2449 +#endif
2451 +void __exit
2452 +fusion_exit(void)
2454 + deregister_devices();
2456 + remove_proc_entry ("fusion", NULL);
2459 +module_init(fusion_init);
2460 +module_exit(fusion_exit);
2462 diff -urN linux-2.6.22.1-0rig/drivers/char/fusion/fusiondev.h linux-2.6.22.1/drivers/char/fusion/fusiondev.h
2463 --- linux-2.6.22.1-0rig/drivers/char/fusion/fusiondev.h 1970-01-01 01:00:00.000000000 +0100
2464 +++ linux-2.6.22.1/drivers/char/fusion/fusiondev.h 2006-08-04 18:28:01.000000000 +0200
2465 @@ -0,0 +1,83 @@
2467 + * Fusion Kernel Module
2469 + * (c) Copyright 2002-2003 Convergence GmbH
2471 + * Written by Denis Oliver Kropp <dok@directfb.org>
2474 + * This program is free software; you can redistribute it and/or
2475 + * modify it under the terms of the GNU General Public License
2476 + * as published by the Free Software Foundation; either version
2477 + * 2 of the License, or (at your option) any later version.
2478 + */
2480 +#ifndef __FUSIONDEV_H__
2481 +#define __FUSIONDEV_H__
2483 +#include <linux/proc_fs.h>
2485 +#include "entries.h"
2486 +#include "list.h"
2488 +#define FUSION_ASSERT(exp) if (!(exp)) BUG()
2489 +#define FUSION_ASSUME(exp) if (!(exp)) printk( KERN_ERR "fusiondev: assumption '" #exp "' failed!\n" )
2491 +typedef struct {
2492 + int refs;
2493 + int index;
2495 + struct semaphore enter_lock;
2496 + int enter_ok;
2497 + wait_queue_head_t enter_wait;
2499 + unsigned long shared_area;
2501 + struct proc_dir_entry *proc_dir;
2503 + struct {
2504 + int property_lease_purchase;
2505 + int property_cede;
2507 + int reactor_attach;
2508 + int reactor_detach;
2510 + int ref_up;
2511 + int ref_down;
2513 + int skirmish_prevail_swoop;
2514 + int skirmish_dismiss;
2516 + int shmpool_attach;
2517 + int shmpool_detach;
2518 + } stat;
2520 + struct {
2521 + int ids;
2522 + FusionLink *list;
2523 + struct semaphore lock;
2524 + } call;
2526 + struct {
2527 + int last_id;
2528 + FusionLink *list;
2529 + struct semaphore lock;
2530 + wait_queue_head_t wait;
2531 + } fusionee;
2533 + FusionEntries properties;
2534 + FusionEntries reactor;
2535 + FusionEntries ref;
2536 + FusionEntries shmpool;
2537 + FusionEntries skirmish;
2538 +} FusionDev;
2541 + * Special version of interruptible_sleep_on() that unlocks the mutex
2542 + * after adding the entry to the queue (just before schedule).
2543 + */
2544 +void fusion_sleep_on (wait_queue_head_t *q,
2545 + struct semaphore *lock,
2546 + signed long *timeout_ms);
2548 +#endif
2549 diff -urN linux-2.6.22.1-0rig/drivers/char/fusion/fusionee.c linux-2.6.22.1/drivers/char/fusion/fusionee.c
2550 --- linux-2.6.22.1-0rig/drivers/char/fusion/fusionee.c 1970-01-01 01:00:00.000000000 +0100
2551 +++ linux-2.6.22.1/drivers/char/fusion/fusionee.c 2007-01-29 00:31:00.000000000 +0100
2552 @@ -0,0 +1,584 @@
2554 + * Fusion Kernel Module
2556 + * (c) Copyright 2002-2003 Convergence GmbH
2558 + * Written by Denis Oliver Kropp <dok@directfb.org>
2561 + * This program is free software; you can redistribute it and/or
2562 + * modify it under the terms of the GNU General Public License
2563 + * as published by the Free Software Foundation; either version
2564 + * 2 of the License, or (at your option) any later version.
2565 + */
2567 +#ifdef HAVE_LINUX_CONFIG_H
2568 +#include <linux/config.h>
2569 +#endif
2570 +#include <linux/types.h>
2571 +#include <linux/kernel.h>
2572 +#include <linux/slab.h>
2573 +#include <linux/smp_lock.h>
2574 +#include <asm/uaccess.h>
2576 +#include <linux/fusion.h>
2578 +#include "call.h"
2579 +#include "fifo.h"
2580 +#include "list.h"
2581 +#include "fusiondev.h"
2582 +#include "fusionee.h"
2583 +#include "property.h"
2584 +#include "reactor.h"
2585 +#include "ref.h"
2586 +#include "skirmish.h"
2587 +#include "shmpool.h"
2589 +#if 0
2590 +#define DEBUG(x...) printk (KERN_DEBUG "Fusion: " x)
2591 +#else
2592 +#define DEBUG(x...) do {} while (0)
2593 +#endif
2595 +struct __Fusion_Fusionee {
2596 + FusionLink link;
2598 + struct semaphore lock;
2600 + FusionID id;
2601 + int pid;
2603 + FusionFifo messages;
2605 + int rcv_total; /* Total number of messages received. */
2606 + int snd_total; /* Total number of messages sent. */
2608 + wait_queue_head_t wait;
2610 + bool force_slave;
2613 +typedef struct {
2614 + FusionLink link;
2616 + FusionMessageType type;
2617 + FusionID id;
2618 + int size;
2619 + void *data;
2620 +} Message;
2622 +/******************************************************************************/
2624 +static int lookup_fusionee (FusionDev *dev, FusionID id, Fusionee **ret_fusionee);
2625 +static int lock_fusionee (FusionDev *dev, FusionID id, Fusionee **ret_fusionee);
2626 +static void unlock_fusionee (Fusionee *fusionee);
2628 +/******************************************************************************/
2630 +static int
2631 +fusionees_read_proc(char *buf, char **start, off_t offset,
2632 + int len, int *eof, void *private)
2634 + FusionLink *l;
2635 + FusionDev *dev = private;
2636 + int written = 0;
2638 + if (down_interruptible (&dev->fusionee.lock))
2639 + return -EINTR;
2641 + fusion_list_foreach (l, dev->fusionee.list) {
2642 + Fusionee *fusionee = (Fusionee*) l;
2644 + written += sprintf(buf+written, "(%5d) 0x%08lx (%4d messages waiting, %7d received, %7d sent)\n",
2645 + fusionee->pid, fusionee->id, fusionee->messages.count, fusionee->rcv_total, fusionee->snd_total);
2646 + if (written < offset) {
2647 + offset -= written;
2648 + written = 0;
2651 + if (written >= len)
2652 + break;
2655 + up (&dev->fusionee.lock);
2657 + *start = buf + offset;
2658 + written -= offset;
2659 + if (written > len) {
2660 + *eof = 0;
2661 + return len;
2664 + *eof = 1;
2665 + return(written<0) ? 0 : written;
2668 +int
2669 +fusionee_init (FusionDev *dev)
2671 + init_waitqueue_head (&dev->fusionee.wait);
2673 + init_MUTEX (&dev->fusionee.lock);
2675 + create_proc_read_entry("fusionees", 0, dev->proc_dir,
2676 + fusionees_read_proc, dev);
2678 + return 0;
2681 +void
2682 +fusionee_deinit (FusionDev *dev)
2684 + FusionLink *l;
2686 + down (&dev->fusionee.lock);
2688 + remove_proc_entry ("fusionees", dev->proc_dir);
2690 + l = dev->fusionee.list;
2691 + while (l) {
2692 + FusionLink *next = l->next;
2693 + Fusionee *fusionee = (Fusionee *) l;
2695 + while (fusionee->messages.count) {
2696 + Message *message = (Message*) fusion_fifo_get (&fusionee->messages);
2698 + kfree (message);
2701 + kfree (fusionee);
2703 + l = next;
2706 + up (&dev->fusionee.lock);
2709 +/******************************************************************************/
2711 +int
2712 +fusionee_new( FusionDev *dev,
2713 + bool force_slave,
2714 + Fusionee **ret_fusionee )
2716 + Fusionee *fusionee;
2718 + fusionee = kmalloc (sizeof(Fusionee), GFP_KERNEL);
2719 + if (!fusionee)
2720 + return -ENOMEM;
2722 + memset (fusionee, 0, sizeof(Fusionee));
2724 + if (down_interruptible (&dev->fusionee.lock)) {
2725 + kfree (fusionee);
2726 + return -EINTR;
2729 + fusionee->pid = current->pid;
2730 + fusionee->force_slave = force_slave;
2732 + init_MUTEX (&fusionee->lock);
2734 + init_waitqueue_head (&fusionee->wait);
2736 + fusion_list_prepend (&dev->fusionee.list, &fusionee->link);
2738 + up (&dev->fusionee.lock);
2740 + *ret_fusionee = fusionee;
2742 + return 0;
2745 +int
2746 +fusionee_enter( FusionDev *dev,
2747 + FusionEnter *enter,
2748 + Fusionee *fusionee )
2750 + if (enter->api.major != FUSION_API_MAJOR || enter->api.minor > FUSION_API_MINOR)
2751 + return -ENOPROTOOPT;
2753 + if (down_interruptible( &dev->enter_lock ))
2754 + return -EINTR;
2756 + if (dev->fusionee.last_id || fusionee->force_slave) {
2757 + while (!dev->enter_ok) {
2758 + fusion_sleep_on( &dev->enter_wait, &dev->enter_lock, NULL );
2760 + if (signal_pending(current))
2761 + return -EINTR;
2763 + if (down_interruptible( &dev->enter_lock ))
2764 + return -EINTR;
2767 + FUSION_ASSERT( dev->fusionee.last_id != 0 );
2770 + fusionee->id = ++dev->fusionee.last_id;
2772 + up( &dev->enter_lock );
2774 + enter->fusion_id = fusionee->id;
2776 + return 0;
2779 +int
2780 +fusionee_fork( FusionDev *dev,
2781 + FusionFork *fork,
2782 + Fusionee *fusionee )
2784 + int ret;
2786 + ret = fusion_shmpool_fork_all( dev, fusionee->id, fork->fusion_id );
2787 + if (ret)
2788 + return ret;
2790 + ret = fusion_reactor_fork_all( dev, fusionee->id, fork->fusion_id );
2791 + if (ret)
2792 + return ret;
2794 + ret = fusion_ref_fork_all_local( dev, fusionee->id, fork->fusion_id );
2795 + if (ret)
2796 + return ret;
2798 + fork->fusion_id = fusionee->id;
2800 + return 0;
2803 +int
2804 +fusionee_send_message (FusionDev *dev,
2805 + Fusionee *sender,
2806 + FusionID recipient,
2807 + FusionMessageType msg_type,
2808 + int msg_id,
2809 + int msg_size,
2810 + const void *msg_data)
2812 + int ret;
2813 + Message *message;
2814 + Fusionee *fusionee;
2816 + DEBUG( "fusionee_send_message (%d -> %d, type %d, id %d, size %d)\n",
2817 + fusionee->id, recipient, msg_type, msg_id, msg_size );
2819 + ret = lookup_fusionee (dev, recipient, &fusionee);
2820 + if (ret)
2821 + return ret;
2823 + if (down_interruptible (&fusionee->lock)) {
2824 + up (&dev->fusionee.lock);
2825 + return -EINTR;
2828 + if (sender && sender != fusionee) {
2829 + if (down_interruptible (&sender->lock)) {
2830 + unlock_fusionee (fusionee);
2831 + up (&dev->fusionee.lock);
2832 + return -EINTR;
2836 + up (&dev->fusionee.lock);
2839 + message = kmalloc (sizeof(Message) + msg_size, GFP_KERNEL);
2840 + if (!message) {
2841 + if (sender && sender != fusionee)
2842 + unlock_fusionee (sender);
2843 + unlock_fusionee (fusionee);
2844 + return -ENOMEM;
2847 + message->data = message + 1;
2849 + if (msg_type == FMT_CALL || msg_type == FMT_SHMPOOL)
2850 + memcpy (message->data, msg_data, msg_size);
2851 + else if (copy_from_user (message->data, msg_data, msg_size)) {
2852 + kfree (message);
2853 + if (sender && sender != fusionee)
2854 + unlock_fusionee (sender);
2855 + unlock_fusionee (fusionee);
2856 + return -EFAULT;
2859 + message->type = msg_type;
2860 + message->id = msg_id;
2861 + message->size = msg_size;
2863 + fusion_fifo_put (&fusionee->messages, &message->link);
2865 + fusionee->rcv_total++;
2866 + if (sender)
2867 + sender->snd_total++;
2869 + wake_up_interruptible_all (&fusionee->wait);
2871 + if (sender && sender != fusionee)
2872 + unlock_fusionee (sender);
2874 + unlock_fusionee (fusionee);
2876 + return 0;
2879 +int
2880 +fusionee_get_messages (FusionDev *dev,
2881 + Fusionee *fusionee,
2882 + void *buf,
2883 + int buf_size,
2884 + bool block)
2886 + int written = 0;
2888 + if (down_interruptible (&fusionee->lock))
2889 + return -EINTR;
2891 + while (!fusionee->messages.count) {
2892 + if (!block) {
2893 + unlock_fusionee (fusionee);
2894 + return -EAGAIN;
2897 + fusion_sleep_on (&fusionee->wait, &fusionee->lock, 0);
2899 + if (signal_pending(current))
2900 + return -EINTR;
2902 + if (down_interruptible (&fusionee->lock))
2903 + return -EINTR;
2906 + while (fusionee->messages.count) {
2907 + FusionReadMessage header;
2908 + Message *message = (Message*) fusionee->messages.first;
2909 + int bytes = message->size + sizeof(header);
2911 + if (bytes > buf_size) {
2912 + if (!written) {
2913 + unlock_fusionee (fusionee);
2914 + return -EMSGSIZE;
2917 + break;
2920 + header.msg_type = message->type;
2921 + header.msg_id = message->id;
2922 + header.msg_size = message->size;
2924 + if (copy_to_user (buf, &header, sizeof(header)) ||
2925 + copy_to_user (buf + sizeof(header), message->data, message->size)) {
2926 + unlock_fusionee (fusionee);
2927 + return -EFAULT;
2930 + written += bytes;
2931 + buf += bytes;
2932 + buf_size -= bytes;
2934 + fusion_fifo_get (&fusionee->messages);
2936 + kfree (message);
2939 + unlock_fusionee (fusionee);
2941 + return written;
2944 +unsigned int
2945 +fusionee_poll (FusionDev *dev,
2946 + Fusionee *fusionee,
2947 + struct file *file,
2948 + poll_table *wait)
2950 + int ret;
2951 + FusionID id = fusionee->id;
2953 + poll_wait (file, &fusionee->wait, wait);
2956 + ret = lock_fusionee (dev, id, &fusionee);
2957 + if (ret)
2958 + return POLLERR;
2960 + if (fusionee->messages.count) {
2961 + unlock_fusionee (fusionee);
2963 + return POLLIN | POLLRDNORM;
2966 + unlock_fusionee (fusionee);
2968 + return 0;
2971 +int
2972 +fusionee_kill (FusionDev *dev,
2973 + Fusionee *fusionee,
2974 + FusionID target,
2975 + int signal,
2976 + int timeout_ms)
2978 + long timeout = -1;
2980 + while (true) {
2981 + FusionLink *l;
2982 + int killed = 0;
2984 + if (down_interruptible (&dev->fusionee.lock))
2985 + return -EINTR;
2987 + fusion_list_foreach (l, dev->fusionee.list) {
2988 + Fusionee *f = (Fusionee*) l;
2990 + if (f != fusionee && (!target || target == f->id)) {
2991 + kill_proc (f->pid, signal, 0);
2992 + killed++;
2996 + if (!killed || timeout_ms < 0) {
2997 + up (&dev->fusionee.lock);
2998 + break;
3001 + if (timeout_ms) {
3002 + switch (timeout) {
3003 + case 0: /* timed out */
3004 + up (&dev->fusionee.lock);
3005 + return -ETIMEDOUT;
3007 + case -1: /* setup timeout */
3008 + timeout = (timeout_ms * HZ + 500) / 1000;
3009 + if (!timeout)
3010 + timeout = 1;
3012 + /* fall through */
3014 + default:
3015 + fusion_sleep_on (&dev->fusionee.wait,
3016 + &dev->fusionee.lock, &timeout);
3017 + break;
3020 + else
3021 + fusion_sleep_on (&dev->fusionee.wait, &dev->fusionee.lock, NULL);
3023 + if (signal_pending(current))
3024 + return -EINTR;
3027 + return 0;
3030 +void
3031 +fusionee_destroy (FusionDev *dev,
3032 + Fusionee *fusionee)
3034 + /* Lock list. */
3035 + down (&dev->fusionee.lock);
3037 + /* Lock fusionee. */
3038 + down (&fusionee->lock);
3040 + /* Remove from list. */
3041 + fusion_list_remove (&dev->fusionee.list, &fusionee->link);
3043 + /* Wake up waiting killer. */
3044 + wake_up_interruptible_all (&dev->fusionee.wait);
3046 + /* Unlock list. */
3047 + up (&dev->fusionee.lock);
3050 + /* Release locks, references, ... */
3051 + fusion_call_destroy_all (dev, fusionee->id);
3052 + fusion_skirmish_dismiss_all (dev, fusionee->id);
3053 + fusion_reactor_detach_all (dev, fusionee->id);
3054 + fusion_property_cede_all (dev, fusionee->id);
3055 + fusion_ref_clear_all_local (dev, fusionee->id);
3056 + fusion_shmpool_detach_all (dev, fusionee->id);
3058 + /* Free all pending messages. */
3059 + while (fusionee->messages.count) {
3060 + Message *message = (Message*) fusion_fifo_get (&fusionee->messages);
3062 + kfree (message);
3065 + /* Unlock fusionee. */
3066 + up (&fusionee->lock);
3069 + /* Free fusionee data. */
3070 + kfree (fusionee);
3073 +FusionID
3074 +fusionee_id( const Fusionee *fusionee )
3076 + return fusionee->id;
3079 +/******************************************************************************/
3081 +static int
3082 +lookup_fusionee (FusionDev *dev,
3083 + FusionID id,
3084 + Fusionee **ret_fusionee)
3086 + FusionLink *l;
3088 + if (down_interruptible (&dev->fusionee.lock))
3089 + return -EINTR;
3091 + fusion_list_foreach (l, dev->fusionee.list) {
3092 + Fusionee *fusionee = (Fusionee *) l;
3094 + if (fusionee->id == id) {
3095 + *ret_fusionee = fusionee;
3096 + return 0;
3100 + up (&dev->fusionee.lock);
3102 + return -EINVAL;
3105 +static int
3106 +lock_fusionee (FusionDev *dev,
3107 + FusionID id,
3108 + Fusionee **ret_fusionee)
3110 + int ret;
3111 + Fusionee *fusionee;
3113 + ret = lookup_fusionee (dev, id, &fusionee);
3114 + if (ret)
3115 + return ret;
3117 + fusion_list_move_to_front (&dev->fusionee.list, &fusionee->link);
3119 + if (down_interruptible (&fusionee->lock)) {
3120 + up (&dev->fusionee.lock);
3121 + return -EINTR;
3124 + up (&dev->fusionee.lock);
3126 + *ret_fusionee = fusionee;
3128 + return 0;
3131 +static void
3132 +unlock_fusionee (Fusionee *fusionee)
3134 + up (&fusionee->lock);
3137 diff -urN linux-2.6.22.1-0rig/drivers/char/fusion/fusionee.h linux-2.6.22.1/drivers/char/fusion/fusionee.h
3138 --- linux-2.6.22.1-0rig/drivers/char/fusion/fusionee.h 1970-01-01 01:00:00.000000000 +0100
3139 +++ linux-2.6.22.1/drivers/char/fusion/fusionee.h 2007-01-23 22:19:25.000000000 +0100
3140 @@ -0,0 +1,75 @@
3142 + * Fusion Kernel Module
3144 + * (c) Copyright 2002-2003 Convergence GmbH
3146 + * Written by Denis Oliver Kropp <dok@directfb.org>
3149 + * This program is free software; you can redistribute it and/or
3150 + * modify it under the terms of the GNU General Public License
3151 + * as published by the Free Software Foundation; either version
3152 + * 2 of the License, or (at your option) any later version.
3153 + */
3155 +#ifndef __FUSIONEE_H__
3156 +#define __FUSIONEE_H__
3158 +#include <linux/poll.h>
3159 +#include <linux/fusion.h>
3161 +#include "fusiondev.h"
3162 +#include "types.h"
3164 +/* module init/cleanup */
3166 +int fusionee_init (FusionDev *dev);
3167 +void fusionee_deinit (FusionDev *dev);
3170 +/* internal functions */
3172 +int fusionee_new (FusionDev *dev,
3173 + bool force_slave,
3174 + Fusionee **ret_fusionee);
3176 +int fusionee_enter (FusionDev *dev,
3177 + FusionEnter *enter,
3178 + Fusionee *fusionee);
3180 +int fusionee_fork (FusionDev *dev,
3181 + FusionFork *fork,
3182 + Fusionee *fusionee);
3184 +int fusionee_send_message (FusionDev *dev,
3185 + Fusionee *fusionee,
3186 + FusionID recipient,
3187 + FusionMessageType msg_type,
3188 + int msg_id,
3189 + int msg_size,
3190 + const void *msg_data);
3192 +int fusionee_get_messages (FusionDev *dev,
3193 + Fusionee *fusionee,
3194 + void *buf,
3195 + int buf_size,
3196 + bool block);
3198 +unsigned
3199 +int fusionee_poll (FusionDev *dev,
3200 + Fusionee *fusionee,
3201 + struct file *file,
3202 + poll_table *wait);
3204 +int fusionee_kill (FusionDev *dev,
3205 + Fusionee *fusionee,
3206 + FusionID target,
3207 + int signal,
3208 + int timeout_ms);
3210 +void fusionee_destroy (FusionDev *dev,
3211 + Fusionee *fusionee);
3213 +FusionID fusionee_id( const Fusionee *fusionee );
3215 +#endif
3216 diff -urN linux-2.6.22.1-0rig/drivers/char/fusion/Kconfig linux-2.6.22.1/drivers/char/fusion/Kconfig
3217 --- linux-2.6.22.1-0rig/drivers/char/fusion/Kconfig 1970-01-01 01:00:00.000000000 +0100
3218 +++ linux-2.6.22.1/drivers/char/fusion/Kconfig 2007-08-12 19:33:38.000000000 +0200
3219 @@ -0,0 +1,8 @@
3220 +config FUSION_DEVICE
3221 + tristate "Fusion device for DirectFB"
3222 + default m
3223 + ---help---
3224 + The fusion device is a software device allowing the DirectFB
3225 + (Direct Frame Buffer) to support multiple applications
3226 + It is safe to say N unless you need to run several DirectFB
3227 + applications concurrently.
3228 diff -urN linux-2.6.22.1-0rig/drivers/char/fusion/list.c linux-2.6.22.1/drivers/char/fusion/list.c
3229 --- linux-2.6.22.1-0rig/drivers/char/fusion/list.c 1970-01-01 01:00:00.000000000 +0100
3230 +++ linux-2.6.22.1/drivers/char/fusion/list.c 2003-06-16 19:47:03.000000000 +0200
3231 @@ -0,0 +1,62 @@
3233 + * Fusion Kernel Module
3235 + * (c) Copyright 2002-2003 Convergence GmbH
3237 + * Written by Denis Oliver Kropp <dok@directfb.org>
3240 + * This program is free software; you can redistribute it and/or
3241 + * modify it under the terms of the GNU General Public License
3242 + * as published by the Free Software Foundation; either version
3243 + * 2 of the License, or (at your option) any later version.
3244 + */
3246 +#include <linux/types.h>
3248 +#include "list.h"
3250 +void
3251 +fusion_list_prepend (FusionLink **list, FusionLink *link)
3253 + link->prev = NULL;
3254 + link->next = *list;
3256 + if (*list)
3257 + (*list)->prev = link;
3259 + *list = link;
3262 +void
3263 +fusion_list_remove (FusionLink **list, FusionLink *link)
3265 + if (link->prev)
3266 + link->prev->next = link->next;
3267 + else
3268 + *list = link->next;
3270 + if (link->next)
3271 + link->next->prev = link->prev;
3273 + link->next = link->prev = NULL;
3276 +void
3277 +fusion_list_move_to_front (FusionLink **list, FusionLink *link)
3279 + if (*list == link)
3280 + return;
3282 + link->prev->next = link->next;
3284 + if (link->next)
3285 + link->next->prev = link->prev;
3287 + link->prev = NULL;
3288 + link->next = *list;
3290 + (*list)->prev = link;
3292 + *list = link;
3294 diff -urN linux-2.6.22.1-0rig/drivers/char/fusion/list.h linux-2.6.22.1/drivers/char/fusion/list.h
3295 --- linux-2.6.22.1-0rig/drivers/char/fusion/list.h 1970-01-01 01:00:00.000000000 +0100
3296 +++ linux-2.6.22.1/drivers/char/fusion/list.h 2004-08-17 19:24:36.000000000 +0200
3297 @@ -0,0 +1,39 @@
3299 + * Fusion Kernel Module
3301 + * (c) Copyright 2002-2003 Convergence GmbH
3303 + * Written by Denis Oliver Kropp <dok@directfb.org>
3306 + * This program is free software; you can redistribute it and/or
3307 + * modify it under the terms of the GNU General Public License
3308 + * as published by the Free Software Foundation; either version
3309 + * 2 of the License, or (at your option) any later version.
3310 + */
3312 +#ifndef __FUSION__LIST_H__
3313 +#define __FUSION__LIST_H__
3315 +typedef struct _FusionLink {
3316 + struct _FusionLink *next;
3317 + struct _FusionLink *prev;
3318 +} FusionLink;
3320 +void fusion_list_prepend (FusionLink **list, FusionLink *link);
3321 +void fusion_list_remove (FusionLink **list, FusionLink *link);
3322 +void fusion_list_move_to_front (FusionLink **list, FusionLink *link);
3325 +#define fusion_list_foreach(elem, list) \
3326 + for (elem = (void*)(list); \
3327 + elem; \
3328 + elem = (void*)(((FusionLink*)(elem))->next))
3330 +#define fusion_list_foreach_safe(elem, temp, list) \
3331 + for (elem = (void*)(list), temp = ((elem) ? (void*)(((FusionLink*)(elem))->next) : NULL); \
3332 + elem; \
3333 + elem = (void*)(temp), temp = ((elem) ? (void*)(((FusionLink*)(elem))->next) : NULL))
3335 +#endif /* __FUSION__LIST_H__ */
3337 diff -urN linux-2.6.22.1-0rig/drivers/char/fusion/Makefile linux-2.6.22.1/drivers/char/fusion/Makefile
3338 --- linux-2.6.22.1-0rig/drivers/char/fusion/Makefile 1970-01-01 01:00:00.000000000 +0100
3339 +++ linux-2.6.22.1/drivers/char/fusion/Makefile 2005-10-29 02:38:05.000000000 +0200
3340 @@ -0,0 +1,3 @@
3341 +obj-$(CONFIG_FUSION_DEVICE) += fusion.o
3343 +fusion-y := call.o entries.o fifo.o fusiondev.o fusionee.o list.o property.o reactor.o ref.o skirmish.o shmpool.o
3344 diff -urN linux-2.6.22.1-0rig/drivers/char/fusion/property.c linux-2.6.22.1/drivers/char/fusion/property.c
3345 --- linux-2.6.22.1-0rig/drivers/char/fusion/property.c 1970-01-01 01:00:00.000000000 +0100
3346 +++ linux-2.6.22.1/drivers/char/fusion/property.c 2007-01-20 05:03:01.000000000 +0100
3347 @@ -0,0 +1,340 @@
3349 + * Fusion Kernel Module
3351 + * (c) Copyright 2002-2003 Convergence GmbH
3353 + * Written by Denis Oliver Kropp <dok@directfb.org>
3356 + * This program is free software; you can redistribute it and/or
3357 + * modify it under the terms of the GNU General Public License
3358 + * as published by the Free Software Foundation; either version
3359 + * 2 of the License, or (at your option) any later version.
3360 + */
3362 +#ifdef HAVE_LINUX_CONFIG_H
3363 +#include <linux/config.h>
3364 +#endif
3365 +#include <linux/types.h>
3366 +#include <linux/kernel.h>
3367 +#include <linux/slab.h>
3368 +#include <linux/smp_lock.h>
3369 +#include <linux/sched.h>
3371 +#ifndef yield
3372 +#define yield schedule
3373 +#endif
3375 +#include <linux/fusion.h>
3377 +#include "entries.h"
3378 +#include "fusiondev.h"
3379 +#include "fusionee.h"
3380 +#include "list.h"
3381 +#include "property.h"
3383 +typedef enum {
3384 + FUSION_PROPERTY_AVAILABLE = 0,
3385 + FUSION_PROPERTY_LEASED,
3386 + FUSION_PROPERTY_PURCHASED
3387 +} FusionPropertyState;
3389 +typedef struct {
3390 + FusionEntry entry;
3392 + FusionPropertyState state;
3393 + int fusion_id; /* non-zero if leased/purchased */
3394 + unsigned long purchase_stamp;
3395 + int lock_pid;
3396 + int count; /* lock counter */
3397 +} FusionProperty;
3399 +static int
3400 +fusion_property_print( FusionEntry *entry,
3401 + void *ctx,
3402 + char *buf )
3404 + FusionProperty *property = (FusionProperty*) entry;
3406 + if (property->state != FUSION_PROPERTY_AVAILABLE) {
3407 + return sprintf( buf, "%s by 0x%08x (%d) %dx\n",
3408 + property->state == FUSION_PROPERTY_LEASED ? "leased" : "purchased",
3409 + property->fusion_id, property->lock_pid, property->count );
3412 + return sprintf( buf, "\n" );
3415 +FUSION_ENTRY_CLASS( FusionProperty, property, NULL, NULL, fusion_property_print )
3417 +/******************************************************************************/
3419 +int
3420 +fusion_property_init( FusionDev *dev )
3422 + fusion_entries_init( &dev->properties, &property_class, dev );
3424 + create_proc_read_entry( "properties", 0, dev->proc_dir,
3425 + fusion_entries_read_proc, &dev->properties );
3427 + return 0;
3430 +void
3431 +fusion_property_deinit( FusionDev *dev )
3433 + remove_proc_entry( "properties", dev->proc_dir );
3435 + fusion_entries_deinit( &dev->properties );
3438 +/******************************************************************************/
3440 +int
3441 +fusion_property_new( FusionDev *dev, int *ret_id )
3443 + return fusion_entry_create( &dev->properties, ret_id, NULL );
3446 +int
3447 +fusion_property_lease( FusionDev *dev, int id, int fusion_id )
3449 + int ret;
3450 + FusionProperty *property;
3451 + long timeout = -1;
3453 + dev->stat.property_lease_purchase++;
3455 + ret = fusion_property_lock( &dev->properties, id, false, &property );
3456 + if (ret)
3457 + return ret;
3459 + while (true) {
3460 + switch (property->state) {
3461 + case FUSION_PROPERTY_AVAILABLE:
3462 + property->state = FUSION_PROPERTY_LEASED;
3463 + property->fusion_id = fusion_id;
3464 + property->lock_pid = current->pid;
3465 + property->count = 1;
3467 + fusion_property_unlock( property );
3468 + return 0;
3470 + case FUSION_PROPERTY_LEASED:
3471 + if (property->lock_pid == current->pid) {
3472 + property->count++;
3474 + fusion_property_unlock( property );
3475 + return 0;
3478 + ret = fusion_property_wait( property, NULL );
3479 + if (ret)
3480 + return ret;
3482 + break;
3484 + case FUSION_PROPERTY_PURCHASED:
3485 + if (property->lock_pid == current->pid) {
3486 + fusion_property_unlock( property );
3487 + return -EIO;
3490 + if (timeout == -1) {
3491 + if (jiffies - property->purchase_stamp > HZ / 10) {
3492 + fusion_property_unlock( property );
3493 + return -EAGAIN;
3496 + timeout = HZ / 10;
3499 + ret = fusion_property_wait( property, &timeout );
3500 + if (ret)
3501 + return ret;
3503 + break;
3505 + default:
3506 + BUG();
3510 + BUG();
3512 + /* won't reach this */
3513 + return -1;
3516 +int
3517 +fusion_property_purchase( FusionDev *dev, int id, int fusion_id )
3519 + int ret;
3520 + FusionProperty *property;
3521 + signed long timeout = -1;
3523 + dev->stat.property_lease_purchase++;
3525 + ret = fusion_property_lock( &dev->properties, id, false, &property );
3526 + if (ret)
3527 + return ret;
3529 + while (true) {
3530 + switch (property->state) {
3531 + case FUSION_PROPERTY_AVAILABLE:
3532 + property->state = FUSION_PROPERTY_PURCHASED;
3533 + property->fusion_id = fusion_id;
3534 + property->purchase_stamp = jiffies;
3535 + property->lock_pid = current->pid;
3536 + property->count = 1;
3538 + fusion_property_notify( property, true );
3540 + fusion_property_unlock( property );
3541 + return 0;
3543 + case FUSION_PROPERTY_LEASED:
3544 + if (property->lock_pid == current->pid) {
3545 + fusion_property_unlock( property );
3546 + return -EIO;
3549 + ret = fusion_property_wait( property, NULL );
3550 + if (ret)
3551 + return ret;
3553 + break;
3555 + case FUSION_PROPERTY_PURCHASED:
3556 + if (property->lock_pid == current->pid) {
3557 + property->count++;
3559 + fusion_property_unlock( property );
3560 + return 0;
3563 + if (timeout == -1) {
3564 + if (jiffies - property->purchase_stamp > HZ) {
3565 + fusion_property_unlock( property );
3566 + return -EAGAIN;
3569 + timeout = HZ;
3572 + ret = fusion_property_wait( property, &timeout );
3573 + if (ret)
3574 + return ret;
3576 + break;
3578 + default:
3579 + BUG();
3583 + BUG();
3585 + /* won't reach this */
3586 + return -1;
3589 +int
3590 +fusion_property_cede( FusionDev *dev, int id, int fusion_id )
3592 + int ret;
3593 + FusionProperty *property;
3594 + bool purchased;
3596 + dev->stat.property_cede++;
3598 + ret = fusion_property_lock( &dev->properties, id, false, &property );
3599 + if (ret)
3600 + return ret;
3602 + if (property->lock_pid != current->pid) {
3603 + fusion_property_unlock( property );
3604 + return -EIO;
3607 + if (--property->count) {
3608 + fusion_property_unlock( property );
3609 + return 0;
3612 + purchased = (property->state == FUSION_PROPERTY_PURCHASED);
3614 + property->state = FUSION_PROPERTY_AVAILABLE;
3615 + property->fusion_id = 0;
3616 + property->lock_pid = 0;
3618 + fusion_property_notify( property, true );
3620 + fusion_property_unlock( property );
3622 + if (purchased)
3623 + yield();
3625 + return 0;
3628 +int
3629 +fusion_property_holdup( FusionDev *dev, int id, Fusionee *fusionee )
3631 + int ret;
3632 + FusionProperty *property;
3633 + FusionID fusion_id = fusionee_id( fusionee );
3635 + if (fusion_id > 1)
3636 + return -EPERM;
3638 + ret = fusion_property_lock( &dev->properties, id, false, &property );
3639 + if (ret)
3640 + return ret;
3642 + if (property->state == FUSION_PROPERTY_PURCHASED) {
3643 + if (property->fusion_id == fusion_id) {
3644 + fusion_property_unlock( property );
3645 + return -EIO;
3648 + fusionee_kill( dev, fusionee, property->fusion_id, SIGKILL, -1 );
3651 + fusion_property_unlock( property );
3653 + return 0;
3656 +int
3657 +fusion_property_destroy( FusionDev *dev, int id )
3659 + return fusion_entry_destroy( &dev->properties, id );
3662 +void
3663 +fusion_property_cede_all( FusionDev *dev, int fusion_id )
3665 + FusionLink *l;
3667 + down( &dev->properties.lock );
3669 + fusion_list_foreach (l, dev->properties.list) {
3670 + FusionProperty *property = (FusionProperty *) l;
3672 + down( &property->entry.lock );
3674 + if (property->fusion_id == fusion_id) {
3675 + property->state = FUSION_PROPERTY_AVAILABLE;
3676 + property->fusion_id = 0;
3677 + property->lock_pid = 0;
3679 + wake_up_interruptible_all (&property->entry.wait);
3682 + up( &property->entry.lock );
3685 + up( &dev->properties.lock );
3688 diff -urN linux-2.6.22.1-0rig/drivers/char/fusion/property.h linux-2.6.22.1/drivers/char/fusion/property.h
3689 --- linux-2.6.22.1-0rig/drivers/char/fusion/property.h 1970-01-01 01:00:00.000000000 +0100
3690 +++ linux-2.6.22.1/drivers/char/fusion/property.h 2007-01-20 05:03:01.000000000 +0100
3691 @@ -0,0 +1,58 @@
3693 + * Fusion Kernel Module
3695 + * (c) Copyright 2002-2003 Convergence GmbH
3697 + * Written by Denis Oliver Kropp <dok@directfb.org>
3700 + * This program is free software; you can redistribute it and/or
3701 + * modify it under the terms of the GNU General Public License
3702 + * as published by the Free Software Foundation; either version
3703 + * 2 of the License, or (at your option) any later version.
3704 + */
3706 +#ifndef __FUSION__PROPERTY_H__
3707 +#define __FUSION__PROPERTY_H__
3709 +#include "fusiondev.h"
3710 +#include "types.h"
3713 +/* module init/cleanup */
3715 +int fusion_property_init (FusionDev *dev);
3716 +void fusion_property_deinit (FusionDev *dev);
3719 +/* public API */
3721 +int fusion_property_new (FusionDev *dev,
3722 + int *ret_id);
3724 +int fusion_property_lease (FusionDev *dev,
3725 + int id,
3726 + int fusion_id);
3728 +int fusion_property_purchase (FusionDev *dev,
3729 + int id,
3730 + int fusion_id);
3732 +int fusion_property_cede (FusionDev *dev,
3733 + int id,
3734 + int fusion_id);
3736 +int fusion_property_holdup (FusionDev *dev,
3737 + int id,
3738 + Fusionee *fusionee);
3740 +int fusion_property_destroy (FusionDev *dev,
3741 + int id);
3744 +/* internal functions */
3746 +void fusion_property_cede_all (FusionDev *dev,
3747 + int fusion_id);
3749 +#endif
3750 diff -urN linux-2.6.22.1-0rig/drivers/char/fusion/reactor.c linux-2.6.22.1/drivers/char/fusion/reactor.c
3751 --- linux-2.6.22.1-0rig/drivers/char/fusion/reactor.c 1970-01-01 01:00:00.000000000 +0100
3752 +++ linux-2.6.22.1/drivers/char/fusion/reactor.c 2007-01-20 05:03:01.000000000 +0100
3753 @@ -0,0 +1,367 @@
3755 + * Fusion Kernel Module
3757 + * (c) Copyright 2002-2003 Convergence GmbH
3759 + * Written by Denis Oliver Kropp <dok@directfb.org>
3762 + * This program is free software; you can redistribute it and/or
3763 + * modify it under the terms of the GNU General Public License
3764 + * as published by the Free Software Foundation; either version
3765 + * 2 of the License, or (at your option) any later version.
3766 + */
3768 +#ifdef HAVE_LINUX_CONFIG_H
3769 +#include <linux/config.h>
3770 +#endif
3771 +#include <linux/types.h>
3772 +#include <linux/kernel.h>
3773 +#include <linux/slab.h>
3774 +#include <linux/smp_lock.h>
3775 +#include <linux/sched.h>
3777 +#include <linux/fusion.h>
3779 +#include "fusiondev.h"
3780 +#include "fusionee.h"
3781 +#include "list.h"
3782 +#include "reactor.h"
3784 +typedef struct {
3785 + FusionLink link;
3787 + int fusion_id;
3789 + int count; /* number of attach calls */
3790 +} ReactorNode;
3792 +typedef struct {
3793 + FusionEntry entry;
3795 + FusionLink *nodes;
3797 + int dispatch_count;
3799 + bool destroyed;
3800 +} FusionReactor;
3802 +/******************************************************************************/
3804 +static int fork_node ( FusionReactor *reactor,
3805 + FusionID fusion_id,
3806 + FusionID from_id );
3808 +static void free_all_nodes( FusionReactor *reactor );
3810 +/******************************************************************************/
3812 +static inline ReactorNode *
3813 +get_node (FusionReactor *reactor,
3814 + FusionID fusion_id)
3816 + ReactorNode *node;
3818 + fusion_list_foreach (node, reactor->nodes) {
3819 + if (node->fusion_id == fusion_id)
3820 + return node;
3823 + return NULL;
3826 +/******************************************************************************/
3828 +static void
3829 +fusion_reactor_destruct( FusionEntry *entry,
3830 + void *ctx )
3832 + FusionReactor *reactor = (FusionReactor*) entry;
3834 + free_all_nodes( reactor );
3837 +static int
3838 +fusion_reactor_print( FusionEntry *entry,
3839 + void *ctx,
3840 + char *buf )
3842 + int num = 0;
3843 + FusionReactor *reactor = (FusionReactor*) entry;
3844 + FusionLink *node = reactor->nodes;
3846 + fusion_list_foreach (node, reactor->nodes) {
3847 + num++;
3850 + return sprintf( buf, "%5dx dispatch, %d nodes%s\n", reactor->dispatch_count, num,
3851 + reactor->destroyed ? " DESTROYED" : "" );
3855 +FUSION_ENTRY_CLASS( FusionReactor, reactor, NULL,
3856 + fusion_reactor_destruct, fusion_reactor_print )
3858 +/******************************************************************************/
3860 +int
3861 +fusion_reactor_init (FusionDev *dev)
3863 + fusion_entries_init( &dev->reactor, &reactor_class, dev );
3865 + create_proc_read_entry( "reactors", 0, dev->proc_dir,
3866 + fusion_entries_read_proc, &dev->reactor );
3868 + return 0;
3871 +void
3872 +fusion_reactor_deinit (FusionDev *dev)
3874 + remove_proc_entry ("reactors", dev->proc_dir);
3876 + fusion_entries_deinit( &dev->reactor );
3879 +/******************************************************************************/
3881 +int
3882 +fusion_reactor_new (FusionDev *dev, int *ret_id)
3884 + return fusion_entry_create( &dev->reactor, ret_id, NULL );
3887 +int
3888 +fusion_reactor_attach (FusionDev *dev, int id, FusionID fusion_id)
3890 + int ret;
3891 + ReactorNode *node;
3892 + FusionReactor *reactor;
3894 + ret = fusion_reactor_lock( &dev->reactor, id, false, &reactor );
3895 + if (ret)
3896 + return ret;
3898 + if (reactor->destroyed) {
3899 + fusion_reactor_unlock( reactor );
3900 + return -EIDRM;
3903 + dev->stat.reactor_attach++;
3905 + node = get_node (reactor, fusion_id);
3906 + if (!node) {
3907 + node = kmalloc (sizeof(ReactorNode), GFP_KERNEL);
3908 + if (!node) {
3909 + fusion_reactor_unlock( reactor );
3910 + return -ENOMEM;
3913 + node->fusion_id = fusion_id;
3914 + node->count = 1;
3916 + fusion_list_prepend (&reactor->nodes, &node->link);
3918 + else
3919 + node->count++;
3921 + fusion_reactor_unlock( reactor );
3923 + return 0;
3926 +int
3927 +fusion_reactor_detach (FusionDev *dev, int id, FusionID fusion_id)
3929 + int ret;
3930 + ReactorNode *node;
3931 + FusionReactor *reactor;
3933 + ret = fusion_reactor_lock( &dev->reactor, id, true, &reactor );
3934 + if (ret)
3935 + return ret;
3937 + dev->stat.reactor_detach++;
3939 + node = get_node (reactor, fusion_id);
3940 + if (!node) {
3941 + fusion_reactor_unlock( reactor );
3942 + up( &dev->reactor.lock );
3943 + return -EIO;
3946 + if (! --node->count) {
3947 + fusion_list_remove (&reactor->nodes, &node->link);
3948 + kfree (node);
3951 + if (reactor->destroyed && !reactor->nodes)
3952 + fusion_entry_destroy_locked( &dev->reactor, &reactor->entry );
3953 + else
3954 + fusion_reactor_unlock( reactor );
3956 + up( &dev->reactor.lock );
3958 + return 0;
3961 +int
3962 +fusion_reactor_dispatch (FusionDev *dev, int id, Fusionee *fusionee,
3963 + int msg_size, const void *msg_data)
3965 + int ret;
3966 + FusionLink *l;
3967 + FusionReactor *reactor;
3968 + FusionID fusion_id = fusionee ? fusionee_id( fusionee ) : 0;
3970 + ret = fusion_reactor_lock( &dev->reactor, id, false, &reactor );
3971 + if (ret)
3972 + return ret;
3974 + if (reactor->destroyed) {
3975 + fusion_reactor_unlock( reactor );
3976 + return -EIDRM;
3979 + reactor->dispatch_count++;
3981 + fusion_list_foreach (l, reactor->nodes) {
3982 + ReactorNode *node = (ReactorNode *) l;
3984 + if (node->fusion_id == fusion_id)
3985 + continue;
3987 + fusionee_send_message (dev, fusionee, node->fusion_id, FMT_REACTOR,
3988 + reactor->entry.id, msg_size, msg_data);
3991 + fusion_reactor_unlock( reactor );
3993 + return 0;
3996 +int
3997 +fusion_reactor_destroy (FusionDev *dev, int id)
3999 + int ret;
4000 + FusionReactor *reactor;
4002 + ret = fusion_reactor_lock( &dev->reactor, id, true, &reactor );
4003 + if (ret)
4004 + return ret;
4006 + if (reactor->destroyed) {
4007 + fusion_reactor_unlock( reactor );
4008 + up( &dev->reactor.lock );
4009 + return -EIDRM;
4012 + reactor->destroyed = true;
4014 + if (!reactor->nodes)
4015 + fusion_entry_destroy_locked( &dev->reactor, &reactor->entry );
4016 + else
4017 + fusion_reactor_unlock( reactor );
4019 + up( &dev->reactor.lock );
4021 + return 0;
4024 +void
4025 +fusion_reactor_detach_all (FusionDev *dev, FusionID fusion_id)
4027 + FusionLink *l, *n;
4029 + down (&dev->reactor.lock);
4031 + fusion_list_foreach_safe (l, n, dev->reactor.list) {
4032 + ReactorNode *node;
4033 + FusionReactor *reactor = (FusionReactor *) l;
4035 + down (&reactor->entry.lock);
4037 + fusion_list_foreach (node, reactor->nodes) {
4038 + if (node->fusion_id == fusion_id) {
4039 + fusion_list_remove (&reactor->nodes, &node->link);
4040 + kfree (node);
4041 + break;
4045 + if (reactor->destroyed && !reactor->nodes)
4046 + fusion_entry_destroy_locked( &dev->reactor, &reactor->entry );
4047 + else
4048 + up (&reactor->entry.lock);
4051 + up (&dev->reactor.lock);
4054 +int
4055 +fusion_reactor_fork_all (FusionDev *dev, FusionID fusion_id, FusionID from_id)
4057 + FusionLink *l;
4058 + int ret = 0;
4060 + down (&dev->reactor.lock);
4062 + fusion_list_foreach (l, dev->reactor.list) {
4063 + FusionReactor *reactor = (FusionReactor *) l;
4065 + ret = fork_node (reactor, fusion_id, from_id);
4066 + if (ret)
4067 + break;
4070 + up (&dev->reactor.lock);
4072 + return ret;
4075 +/******************************************************************************/
4077 +static int
4078 +fork_node (FusionReactor *reactor, FusionID fusion_id, FusionID from_id)
4080 + ReactorNode *node;
4082 + down (&reactor->entry.lock);
4084 + fusion_list_foreach (node, reactor->nodes) {
4085 + if (node->fusion_id == from_id) {
4086 + ReactorNode *new_node;
4088 + new_node = kmalloc (sizeof(ReactorNode), GFP_KERNEL);
4089 + if (!new_node) {
4090 + up (&reactor->entry.lock);
4091 + return -ENOMEM;
4094 + new_node->fusion_id = fusion_id;
4095 + new_node->count = node->count;
4097 + fusion_list_prepend (&reactor->nodes, &new_node->link);
4099 + break;
4103 + up (&reactor->entry.lock);
4105 + return 0;
4108 +static void
4109 +free_all_nodes (FusionReactor *reactor)
4112 + FusionLink *n;
4113 + ReactorNode *node;
4115 + fusion_list_foreach_safe (node, n, reactor->nodes) {
4116 + kfree (node);
4119 + reactor->nodes = NULL;
4121 diff -urN linux-2.6.22.1-0rig/drivers/char/fusion/reactor.h linux-2.6.22.1/drivers/char/fusion/reactor.h
4122 --- linux-2.6.22.1-0rig/drivers/char/fusion/reactor.h 1970-01-01 01:00:00.000000000 +0100
4123 +++ linux-2.6.22.1/drivers/char/fusion/reactor.h 2007-01-20 05:03:01.000000000 +0100
4124 @@ -0,0 +1,59 @@
4126 + * Fusion Kernel Module
4128 + * (c) Copyright 2002-2003 Convergence GmbH
4130 + * Written by Denis Oliver Kropp <dok@directfb.org>
4133 + * This program is free software; you can redistribute it and/or
4134 + * modify it under the terms of the GNU General Public License
4135 + * as published by the Free Software Foundation; either version
4136 + * 2 of the License, or (at your option) any later version.
4137 + */
4139 +#ifndef __FUSION__REACTOR_H__
4140 +#define __FUSION__REACTOR_H__
4142 +#include "fusiondev.h"
4143 +#include "types.h"
4146 +/* module init/cleanup */
4148 +int fusion_reactor_init (FusionDev *dev);
4149 +void fusion_reactor_deinit (FusionDev *dev);
4152 +/* public API */
4154 +int fusion_reactor_new (FusionDev *dev,
4155 + int *id);
4157 +int fusion_reactor_attach (FusionDev *dev,
4158 + int id,
4159 + FusionID fusion_id);
4161 +int fusion_reactor_detach (FusionDev *dev,
4162 + int id,
4163 + FusionID fusion_id);
4165 +int fusion_reactor_dispatch (FusionDev *dev,
4166 + int id,
4167 + Fusionee *fusionee,
4168 + int msg_size,
4169 + const void *msg_data);
4171 +int fusion_reactor_destroy (FusionDev *dev,
4172 + int id);
4175 +/* internal functions */
4177 +void fusion_reactor_detach_all (FusionDev *dev,
4178 + FusionID fusion_id);
4180 +int fusion_reactor_fork_all (FusionDev *dev,
4181 + FusionID fusion_id,
4182 + FusionID from_id);
4183 +#endif
4184 diff -urN linux-2.6.22.1-0rig/drivers/char/fusion/ref.c linux-2.6.22.1/drivers/char/fusion/ref.c
4185 --- linux-2.6.22.1-0rig/drivers/char/fusion/ref.c 1970-01-01 01:00:00.000000000 +0100
4186 +++ linux-2.6.22.1/drivers/char/fusion/ref.c 2007-01-06 14:09:45.000000000 +0100
4187 @@ -0,0 +1,680 @@
4189 + * Fusion Kernel Module
4191 + * (c) Copyright 2002-2003 Convergence GmbH
4193 + * Written by Denis Oliver Kropp <dok@directfb.org>
4196 + * This program is free software; you can redistribute it and/or
4197 + * modify it under the terms of the GNU General Public License
4198 + * as published by the Free Software Foundation; either version
4199 + * 2 of the License, or (at your option) any later version.
4200 + */
4202 +#ifdef HAVE_LINUX_CONFIG_H
4203 +#include <linux/config.h>
4204 +#endif
4205 +#include <linux/types.h>
4206 +#include <linux/kernel.h>
4207 +#include <linux/slab.h>
4208 +#include <linux/smp_lock.h>
4209 +#include <linux/sched.h>
4211 +#include <linux/fusion.h>
4213 +#include "fusiondev.h"
4214 +#include "list.h"
4215 +#include "call.h"
4216 +#include "ref.h"
4218 +typedef struct __Fusion_FusionRef FusionRef;
4220 +typedef struct {
4221 + FusionLink link;
4222 + FusionID fusion_id;
4223 + int refs;
4224 +} LocalRef;
4226 +typedef struct {
4227 + FusionLink link;
4228 + FusionRef *ref;
4229 +} Inheritor;
4231 +struct __Fusion_FusionRef {
4232 + FusionEntry entry;
4234 + int global;
4235 + int local;
4237 + int locked; /* non-zero fusion id of lock owner */
4239 + bool watched; /* true if watch has been installed */
4240 + int call_id; /* id of call registered with a watch */
4241 + int call_arg; /* optional call parameter */
4243 + FusionRef *inherited;
4244 + FusionLink *inheritors;
4246 + FusionLink *local_refs;
4249 +/**********************************************************************************************************************/
4251 +static int add_local ( FusionRef *ref, FusionID fusion_id, int add );
4252 +static void clear_local ( FusionDev *dev, FusionRef *ref, FusionID fusion_id );
4253 +static int fork_local ( FusionDev *dev, FusionRef *ref, FusionID fusion_id, FusionID from_id );
4254 +static void free_all_local ( FusionRef *ref );
4256 +static int propagate_local ( FusionDev *dev, FusionRef *ref, int diff );
4258 +static void notify_ref ( FusionDev *dev, FusionRef *ref );
4260 +static int add_inheritor ( FusionRef *ref, FusionRef *from );
4261 +static void remove_inheritor( FusionRef *ref, FusionRef *from );
4262 +static void drop_inheritors ( FusionDev *dev, FusionRef *ref );
4264 +/**********************************************************************************************************************/
4266 +static void
4267 +fusion_ref_destruct( FusionEntry *entry,
4268 + void *ctx )
4270 + FusionRef *ref = (FusionRef*) entry;
4271 + FusionDev *dev = (FusionDev*) ctx;
4273 + drop_inheritors( dev, ref );
4275 + if (ref->inherited)
4276 + remove_inheritor( ref, ref->inherited );
4278 + free_all_local( ref );
4281 +static int
4282 +fusion_ref_print( FusionEntry *entry,
4283 + void *ctx,
4284 + char *buf )
4286 + FusionRef *ref = (FusionRef*) entry;
4288 + if (ref->locked)
4289 + return sprintf( buf, "%2d %2d (locked by %d)\n", ref->global, ref->local, ref->locked );
4291 + return sprintf( buf, "%2d %2d\n", ref->global, ref->local );
4294 +FUSION_ENTRY_CLASS( FusionRef, ref, NULL,
4295 + fusion_ref_destruct, fusion_ref_print );
4297 +/**********************************************************************************************************************/
4299 +int
4300 +fusion_ref_init( FusionDev *dev )
4302 + fusion_entries_init( &dev->ref, &ref_class, dev );
4304 + create_proc_read_entry( "refs", 0, dev->proc_dir, fusion_entries_read_proc, &dev->ref );
4306 + return 0;
4309 +void
4310 +fusion_ref_deinit( FusionDev *dev )
4312 + remove_proc_entry( "refs", dev->proc_dir );
4314 + fusion_entries_deinit( &dev->ref );
4317 +/**********************************************************************************************************************/
4319 +int
4320 +fusion_ref_new( FusionDev *dev, int *ret_id )
4322 + return fusion_entry_create( &dev->ref, ret_id, NULL );
4325 +int
4326 +fusion_ref_up (FusionDev *dev, int id, FusionID fusion_id)
4328 + int ret;
4329 + FusionRef *ref;
4331 + ret = fusion_ref_lock( &dev->ref, id, true, &ref );
4332 + if (ret)
4333 + return ret;
4335 + dev->stat.ref_up++;
4337 + if (ref->locked) {
4338 + ret = -EAGAIN;
4339 + goto out;
4342 + if (fusion_id) {
4343 + ret = add_local (ref, fusion_id, 1);
4344 + if (ret)
4345 + goto out;
4347 + ret = propagate_local( dev, ref, 1 );
4349 + else
4350 + ref->global++;
4353 +out:
4354 + fusion_ref_unlock( ref );
4355 + up( &dev->ref.lock );
4357 + return ret;
4360 +int
4361 +fusion_ref_down (FusionDev *dev, int id, FusionID fusion_id)
4363 + int ret;
4364 + FusionRef *ref;
4366 + ret = fusion_ref_lock( &dev->ref, id, true, &ref );
4367 + if (ret)
4368 + return ret;
4370 + dev->stat.ref_down++;
4372 + if (ref->locked) {
4373 + ret = -EAGAIN;
4374 + goto out;
4377 + if (fusion_id) {
4378 + ret = -EIO;
4379 + if (!ref->local)
4380 + goto out;
4382 + ret = add_local (ref, fusion_id, -1);
4383 + if (ret)
4384 + goto out;
4386 + ret = propagate_local( dev, ref, -1 );
4388 + else {
4389 + if (!ref->global) {
4390 + ret = -EIO;
4391 + goto out;
4394 + ref->global--;
4396 + if (ref->local + ref->global == 0)
4397 + notify_ref (dev, ref);
4401 +out:
4402 + fusion_ref_unlock( ref );
4403 + up( &dev->ref.lock );
4405 + return ret;
4408 +int
4409 +fusion_ref_zero_lock (FusionDev *dev, int id, FusionID fusion_id)
4411 + int ret;
4412 + FusionRef *ref;
4414 + ret = fusion_ref_lock( &dev->ref, id, false, &ref );
4415 + if (ret)
4416 + return ret;
4418 + while (true) {
4419 + if (ref->watched) {
4420 + fusion_ref_unlock( ref );
4421 + return -EACCES;
4424 + if (ref->locked) {
4425 + fusion_ref_unlock( ref );
4426 + return ref->locked == fusion_id ? -EIO : -EAGAIN;
4429 + if (ref->global || ref->local) {
4430 + ret = fusion_ref_wait( ref, NULL );
4431 + if (ret)
4432 + return ret;
4434 + else
4435 + break;
4438 + ref->locked = fusion_id;
4440 + fusion_ref_unlock( ref );
4442 + return 0;
4445 +int
4446 +fusion_ref_zero_trylock (FusionDev *dev, int id, FusionID fusion_id)
4448 + int ret;
4449 + FusionRef *ref;
4451 + ret = fusion_ref_lock( &dev->ref, id, false, &ref );
4452 + if (ret)
4453 + return ret;
4455 + if (ref->locked) {
4456 + fusion_ref_unlock( ref );
4457 + return ref->locked == fusion_id ? -EIO : -EAGAIN;
4460 + if (ref->global || ref->local)
4461 + ret = -ETOOMANYREFS;
4462 + else
4463 + ref->locked = fusion_id;
4465 + fusion_ref_unlock( ref );
4467 + return ret;
4470 +int
4471 +fusion_ref_zero_unlock (FusionDev *dev, int id, FusionID fusion_id)
4473 + int ret;
4474 + FusionRef *ref;
4476 + ret = fusion_ref_lock( &dev->ref, id, false, &ref );
4477 + if (ret)
4478 + return ret;
4480 + if (ref->locked != fusion_id) {
4481 + fusion_ref_unlock( ref );
4482 + return -EIO;
4485 + ref->locked = 0;
4487 + fusion_ref_unlock( ref );
4489 + return 0;
4492 +int
4493 +fusion_ref_stat (FusionDev *dev, int id, int *refs)
4495 + int ret;
4496 + FusionRef *ref;
4498 + ret = fusion_ref_lock( &dev->ref, id, false, &ref );
4499 + if (ret)
4500 + return ret;
4502 + *refs = ref->global + ref->local;
4504 + fusion_ref_unlock( ref );
4506 + return 0;
4509 +int
4510 +fusion_ref_watch (FusionDev *dev,
4511 + int id,
4512 + int call_id,
4513 + int call_arg)
4515 + int ret;
4516 + FusionRef *ref;
4518 + ret = fusion_ref_lock( &dev->ref, id, false, &ref );
4519 + if (ret)
4520 + return ret;
4522 + if (ref->entry.pid != current->pid) {
4523 + fusion_ref_unlock( ref );
4524 + return -EACCES;
4527 + if (ref->global + ref->local == 0) {
4528 + fusion_ref_unlock( ref );
4529 + return -EIO;
4532 + if (ref->watched) {
4533 + fusion_ref_unlock( ref );
4534 + return -EBUSY;
4537 + ref->watched = true;
4538 + ref->call_id = call_id;
4539 + ref->call_arg = call_arg;
4541 + fusion_ref_notify( ref, true );
4543 + fusion_ref_unlock( ref );
4545 + return 0;
4548 +int
4549 +fusion_ref_inherit (FusionDev *dev,
4550 + int id,
4551 + int from_id)
4553 + int ret;
4554 + FusionRef *ref;
4555 + FusionRef *from = NULL;
4557 + ret = fusion_ref_lock( &dev->ref, id, true, &ref );
4558 + if (ret)
4559 + return ret;
4561 + ret = -EBUSY;
4562 + if (ref->inherited)
4563 + goto out;
4565 + ret = -EINVAL;
4566 + fusion_list_foreach (from, dev->ref.list) {
4567 + if (from->entry.id == from_id) {
4568 + if (down_interruptible( &from->entry.lock )) {
4569 + ret = -EINTR;
4570 + from = NULL;
4573 + break;
4576 + if (!from)
4577 + goto out;
4579 + ret = add_inheritor( ref, from );
4580 + if (ret)
4581 + goto out;
4583 + ret = propagate_local( dev, ref, from->local );
4584 + if (ret)
4585 + goto out;
4587 + ref->inherited = from;
4589 +out:
4590 + if (from)
4591 + up( &from->entry.lock );
4593 + fusion_ref_unlock( ref );
4594 + up ( &dev->ref.lock );
4596 + return ret;
4599 +int
4600 +fusion_ref_destroy (FusionDev *dev, int id)
4602 + return fusion_entry_destroy( &dev->ref, id );
4605 +void
4606 +fusion_ref_clear_all_local( FusionDev *dev, FusionID fusion_id )
4608 + FusionRef *ref;
4610 + down( &dev->ref.lock );
4612 + fusion_list_foreach (ref, dev->ref.list)
4613 + clear_local( dev, ref, fusion_id );
4615 + up( &dev->ref.lock );
4618 +int
4619 +fusion_ref_fork_all_local( FusionDev *dev, FusionID fusion_id, FusionID from_id )
4621 + FusionRef *ref;
4622 + int ret = 0;
4624 + down( &dev->ref.lock );
4626 + fusion_list_foreach (ref, dev->ref.list) {
4627 + ret = fork_local( dev, ref, fusion_id, from_id );
4628 + if (ret)
4629 + break;
4632 + up( &dev->ref.lock );
4634 + return ret;
4637 +/**********************************************************************************************************************/
4639 +static int
4640 +add_local (FusionRef *ref, FusionID fusion_id, int add)
4642 + FusionLink *l;
4643 + LocalRef *local;
4645 + fusion_list_foreach (l, ref->local_refs) {
4646 + local = (LocalRef *) l;
4648 + if (local->fusion_id == fusion_id) {
4649 + fusion_list_move_to_front( &ref->local_refs, l );
4651 + if (local->refs + add < 0)
4652 + return -EIO;
4654 + local->refs += add;
4655 + return 0;
4659 + /* Can only create local node if value is positive. */
4660 + if (add <= 0)
4661 + return -EIO;
4663 + local = kmalloc (sizeof(LocalRef), GFP_KERNEL);
4664 + if (!local)
4665 + return -ENOMEM;
4667 + local->fusion_id = fusion_id;
4668 + local->refs = add;
4670 + fusion_list_prepend (&ref->local_refs, &local->link);
4672 + return 0;
4675 +static void
4676 +clear_local (FusionDev *dev, FusionRef *ref, FusionID fusion_id)
4678 + FusionLink *l;
4680 + down (&ref->entry.lock);
4682 + if (ref->locked == fusion_id) {
4683 + ref->locked = 0;
4684 + wake_up_interruptible_all (&ref->entry.wait);
4687 + fusion_list_foreach (l, ref->local_refs) {
4688 + LocalRef *local = (LocalRef *) l;
4690 + if (local->fusion_id == fusion_id) {
4691 + if (local->refs)
4692 + propagate_local( dev, ref, - local->refs );
4694 + fusion_list_remove( &ref->local_refs, l );
4696 + kfree (l);
4697 + break;
4701 + up (&ref->entry.lock);
4704 +static int
4705 +fork_local (FusionDev *dev, FusionRef *ref, FusionID fusion_id, FusionID from_id)
4707 + FusionLink *l;
4708 + int ret = 0;
4710 + down (&ref->entry.lock);
4712 + fusion_list_foreach (l, ref->local_refs) {
4713 + LocalRef *local = (LocalRef *) l;
4715 + if (local->fusion_id == from_id) {
4716 + if (local->refs) {
4717 + LocalRef *new_local;
4719 + new_local = kmalloc (sizeof(LocalRef), GFP_KERNEL);
4720 + if (!new_local) {
4721 + ret = -ENOMEM;
4722 + break;
4725 + new_local->fusion_id = fusion_id;
4726 + new_local->refs = local->refs;
4728 + fusion_list_prepend( &ref->local_refs, &new_local->link );
4730 + propagate_local( dev, ref, local->refs );
4732 + break;
4736 + up (&ref->entry.lock);
4738 + return ret;
4741 +static void
4742 +free_all_local (FusionRef *ref)
4744 + FusionLink *l = ref->local_refs;
4746 + while (l) {
4747 + FusionLink *next = l->next;
4749 + kfree (l);
4751 + l = next;
4754 + ref->local_refs = NULL;
4757 +static void
4758 +notify_ref (FusionDev *dev, FusionRef *ref)
4760 + if (ref->watched) {
4761 + FusionCallExecute execute;
4763 + execute.call_id = ref->call_id;
4764 + execute.call_arg = ref->call_arg;
4765 + execute.call_ptr = NULL;
4767 + fusion_call_execute (dev, 0, &execute);
4769 + else
4770 + wake_up_interruptible_all (&ref->entry.wait);
4773 +static int
4774 +propagate_local( FusionDev *dev, FusionRef *ref, int diff )
4776 + FusionLink *l;
4778 + /* Recurse into inheritors. */
4779 + fusion_list_foreach (l, ref->inheritors) {
4780 + FusionRef *inheritor = ((Inheritor*) l)->ref;
4782 + if (down_interruptible( &inheritor->entry.lock )) {
4783 + printk( KERN_ERR "fusion_ref: propagate_local() interrupted!\n" );
4784 + //return -EINTR;
4787 + propagate_local( dev, inheritor, diff );
4789 + up( &inheritor->entry.lock );
4792 + /* Apply difference. */
4793 + ref->local += diff;
4795 + /* Notify zero count. */
4796 + if (ref->local + ref->global == 0)
4797 + notify_ref( dev, ref );
4799 + return 0;
4802 +static int
4803 +add_inheritor(FusionRef *ref, FusionRef *from)
4805 + Inheritor *inheritor;
4807 + inheritor = kmalloc (sizeof(Inheritor), GFP_KERNEL);
4808 + if (!inheritor)
4809 + return -ENOMEM;
4811 + inheritor->ref = ref;
4813 + fusion_list_prepend( &from->inheritors, &inheritor->link );
4815 + return 0;
4818 +static void
4819 +remove_inheritor(FusionRef *ref, FusionRef *from)
4821 + FusionLink *l;
4823 + down( &from->entry.lock );
4825 + fusion_list_foreach (l, from->inheritors) {
4826 + Inheritor *inheritor = (Inheritor*) l;
4828 + if (inheritor->ref == ref) {
4829 + fusion_list_remove( &from->inheritors, &inheritor->link );
4831 + kfree( l );
4832 + break;
4836 + up( &from->entry.lock );
4839 +static void
4840 +drop_inheritors( FusionDev *dev, FusionRef *ref )
4842 + FusionLink *l = ref->inheritors;
4844 + while (l) {
4845 + FusionLink *next = l->next;
4846 + FusionRef *inheritor = ((Inheritor*) l)->ref;
4848 + if (down_interruptible( &inheritor->entry.lock )) {
4849 + printk( KERN_ERR "fusion_ref: drop_inheritors() interrupted!\n" );
4850 + //return;
4853 + propagate_local( dev, inheritor, - ref->local );
4855 + inheritor->inherited = NULL;
4857 + up( &inheritor->entry.lock );
4860 + kfree (l);
4862 + l = next;
4865 + ref->inheritors = NULL;
4868 diff -urN linux-2.6.22.1-0rig/drivers/char/fusion/ref.h linux-2.6.22.1/drivers/char/fusion/ref.h
4869 --- linux-2.6.22.1-0rig/drivers/char/fusion/ref.h 1970-01-01 01:00:00.000000000 +0100
4870 +++ linux-2.6.22.1/drivers/char/fusion/ref.h 2006-08-14 11:16:54.000000000 +0200
4871 @@ -0,0 +1,79 @@
4873 + * Fusion Kernel Module
4875 + * (c) Copyright 2002-2003 Convergence GmbH
4877 + * Written by Denis Oliver Kropp <dok@directfb.org>
4880 + * This program is free software; you can redistribute it and/or
4881 + * modify it under the terms of the GNU General Public License
4882 + * as published by the Free Software Foundation; either version
4883 + * 2 of the License, or (at your option) any later version.
4884 + */
4886 +#ifndef __FUSION__REF_H__
4887 +#define __FUSION__REF_H__
4889 +#include "fusiondev.h"
4890 +#include "types.h"
4893 +/* module init/cleanup */
4895 +int fusion_ref_init (FusionDev *dev);
4896 +void fusion_ref_deinit (FusionDev *dev);
4899 +/* public API */
4901 +int fusion_ref_new (FusionDev *dev,
4902 + int *id);
4904 +int fusion_ref_up (FusionDev *dev,
4905 + int id,
4906 + FusionID fusion_id);
4908 +int fusion_ref_down (FusionDev *dev,
4909 + int id,
4910 + FusionID fusion_id);
4912 +int fusion_ref_zero_lock (FusionDev *dev,
4913 + int id,
4914 + FusionID fusion_id);
4916 +int fusion_ref_zero_trylock (FusionDev *dev,
4917 + int id,
4918 + FusionID fusion_id);
4920 +int fusion_ref_zero_unlock (FusionDev *dev,
4921 + int id,
4922 + FusionID fusion_id);
4924 +int fusion_ref_stat (FusionDev *dev,
4925 + int id,
4926 + int *refs);
4928 +int fusion_ref_watch (FusionDev *dev,
4929 + int id,
4930 + int call_id,
4931 + int call_arg);
4933 +int fusion_ref_inherit (FusionDev *dev,
4934 + int id,
4935 + int from);
4937 +int fusion_ref_destroy (FusionDev *dev,
4938 + int id);
4941 +/* internal functions */
4943 +void fusion_ref_clear_all_local (FusionDev *dev,
4944 + FusionID fusion_id);
4946 +int fusion_ref_fork_all_local (FusionDev *dev,
4947 + FusionID fusion_id,
4948 + FusionID from_id);
4950 +#endif
4951 diff -urN linux-2.6.22.1-0rig/drivers/char/fusion/shmpool.c linux-2.6.22.1/drivers/char/fusion/shmpool.c
4952 --- linux-2.6.22.1-0rig/drivers/char/fusion/shmpool.c 1970-01-01 01:00:00.000000000 +0100
4953 +++ linux-2.6.22.1/drivers/char/fusion/shmpool.c 2007-01-20 05:03:01.000000000 +0100
4954 @@ -0,0 +1,444 @@
4956 + * Fusion Kernel Module
4958 + * (c) Copyright 2002-2003 Convergence GmbH
4960 + * Written by Denis Oliver Kropp <dok@directfb.org>
4963 + * This program is free software; you can redistribute it and/or
4964 + * modify it under the terms of the GNU General Public License
4965 + * as published by the Free Software Foundation; either version
4966 + * 2 of the License, or (at your option) any later version.
4967 + */
4969 +#ifdef HAVE_LINUX_CONFIG_H
4970 +#include <linux/config.h>
4971 +#endif
4972 +#include <linux/types.h>
4973 +#include <linux/kernel.h>
4974 +#include <linux/slab.h>
4975 +#include <linux/smp_lock.h>
4976 +#include <linux/sched.h>
4978 +#include <linux/fusion.h>
4980 +#include "fusiondev.h"
4981 +#include "fusionee.h"
4982 +#include "list.h"
4983 +#include "shmpool.h"
4986 +#define SHM_BASE 0x20010000 /* virtual base address */
4987 +#define SHM_SIZE 0x1FFEF000 /* size of virtual address space */
4990 +typedef struct {
4991 + FusionLink link;
4992 + unsigned long next_base;
4993 +} AddrEntry;
4996 +typedef struct {
4997 + FusionLink link;
4999 + FusionID fusion_id;
5001 + int count; /* number of attach calls */
5002 +} SHMPoolNode;
5004 +typedef struct {
5005 + FusionEntry entry;
5007 + int max_size;
5009 + void *addr_base;
5010 + int size;
5012 + AddrEntry *addr_entry;
5014 + FusionLink *nodes;
5016 + int dispatch_count;
5017 +} FusionSHMPool;
5019 +/******************************************************************************/
5021 +static SHMPoolNode *get_node ( FusionSHMPool *shmpool,
5022 + FusionID fusion_id );
5024 +static void remove_node ( FusionSHMPool *shmpool,
5025 + FusionID fusion_id );
5027 +static int fork_node ( FusionSHMPool *shmpool,
5028 + FusionID fusion_id,
5029 + FusionID from_id );
5031 +static void free_all_nodes( FusionSHMPool *shmpool );
5033 +/******************************************************************************/
5036 +static DECLARE_MUTEX (addr_lock);
5037 +static FusionLink *addr_entries;
5038 +static unsigned long addr_base = SHM_BASE;
5040 +/******************************************************************************/
5042 +static AddrEntry *
5043 +add_addr_entry( unsigned long next_base )
5045 + AddrEntry *entry = kmalloc( sizeof(AddrEntry), GFP_KERNEL );
5047 + entry->next_base = next_base;
5049 + fusion_list_prepend( &addr_entries, &entry->link );
5051 + return entry;
5054 +/******************************************************************************/
5056 +static int
5057 +fusion_shmpool_construct( FusionEntry *entry,
5058 + void *ctx,
5059 + void *create_ctx )
5061 + FusionSHMPool *shmpool = (FusionSHMPool*) entry;
5062 + FusionSHMPoolNew *poolnew = create_ctx;
5064 + down( &addr_lock );
5066 + if (addr_base + poolnew->max_size >= SHM_BASE + SHM_SIZE) {
5067 + up( &addr_lock );
5068 + printk( KERN_WARNING "%s: virtual address space exhausted! (FIXME)\n", __FUNCTION__ );
5069 + return -ENOSPC;
5072 + shmpool->max_size = poolnew->max_size;
5073 + shmpool->addr_base = poolnew->addr_base = (void*) addr_base;
5075 + addr_base += PAGE_ALIGN(poolnew->max_size) + PAGE_SIZE; /* fence page */
5077 + shmpool->addr_entry = add_addr_entry( addr_base );
5079 + up( &addr_lock );
5081 + return 0;
5084 +static void
5085 +fusion_shmpool_destruct( FusionEntry *entry,
5086 + void *ctx )
5088 + AddrEntry *addr_entry;
5089 + FusionSHMPool *shmpool = (FusionSHMPool*) entry;
5091 + free_all_nodes( shmpool );
5094 + down( &addr_lock );
5096 + fusion_list_remove( &addr_entries, &shmpool->addr_entry->link );
5099 + /*
5100 + * free trailing address space
5101 + */
5103 + addr_base = SHM_BASE;
5105 + fusion_list_foreach (addr_entry, addr_entries) {
5106 + if (addr_entry->next_base > addr_base)
5107 + addr_base = addr_entry->next_base;
5110 + up( &addr_lock );
5113 +static int
5114 +fusion_shmpool_print( FusionEntry *entry,
5115 + void *ctx,
5116 + char *buf )
5118 + int num = 0;
5119 + FusionSHMPool *shmpool = (FusionSHMPool*) entry;
5120 + FusionLink *node = shmpool->nodes;
5122 + fusion_list_foreach (node, shmpool->nodes) {
5123 + num++;
5126 + return sprintf( buf, "0x%p [0x%x] - 0x%x, %dx dispatch, %d nodes\n",
5127 + shmpool->addr_base, shmpool->max_size, shmpool->size,
5128 + shmpool->dispatch_count, num );
5132 +FUSION_ENTRY_CLASS( FusionSHMPool, shmpool, fusion_shmpool_construct,
5133 + fusion_shmpool_destruct, fusion_shmpool_print )
5135 +/******************************************************************************/
5137 +int
5138 +fusion_shmpool_init (FusionDev *dev)
5140 + fusion_entries_init( &dev->shmpool, &shmpool_class, dev );
5142 + create_proc_read_entry( "shmpools", 0, dev->proc_dir,
5143 + fusion_entries_read_proc, &dev->shmpool );
5145 + return 0;
5148 +void
5149 +fusion_shmpool_deinit (FusionDev *dev)
5151 + remove_proc_entry ("shmpools", dev->proc_dir);
5153 + fusion_entries_deinit( &dev->shmpool );
5156 +/******************************************************************************/
5158 +int
5159 +fusion_shmpool_new (FusionDev *dev,
5160 + FusionSHMPoolNew *pool)
5162 + if (pool->max_size <= 0)
5163 + return -EINVAL;
5165 + return fusion_entry_create( &dev->shmpool, &pool->pool_id, pool );
5168 +int
5169 +fusion_shmpool_attach (FusionDev *dev,
5170 + FusionSHMPoolAttach *attach,
5171 + FusionID fusion_id)
5173 + int ret;
5174 + SHMPoolNode *node;
5175 + FusionSHMPool *shmpool;
5177 + ret = fusion_shmpool_lock( &dev->shmpool, attach->pool_id, false, &shmpool );
5178 + if (ret)
5179 + return ret;
5181 + dev->stat.shmpool_attach++;
5183 + node = get_node (shmpool, fusion_id);
5184 + if (!node) {
5185 + node = kmalloc (sizeof(SHMPoolNode), GFP_KERNEL);
5186 + if (!node) {
5187 + fusion_shmpool_unlock( shmpool );
5188 + return -ENOMEM;
5191 + node->fusion_id = fusion_id;
5192 + node->count = 1;
5194 + fusion_list_prepend (&shmpool->nodes, &node->link);
5196 + else
5197 + node->count++;
5199 + attach->addr_base = shmpool->addr_base;
5200 + attach->size = shmpool->size;
5202 + fusion_shmpool_unlock( shmpool );
5204 + return 0;
5207 +int
5208 +fusion_shmpool_detach (FusionDev *dev, int id, FusionID fusion_id)
5210 + int ret;
5211 + SHMPoolNode *node;
5212 + FusionSHMPool *shmpool;
5214 + ret = fusion_shmpool_lock( &dev->shmpool, id, false, &shmpool );
5215 + if (ret)
5216 + return ret;
5218 + dev->stat.shmpool_detach++;
5220 + node = get_node (shmpool, fusion_id);
5221 + if (!node) {
5222 + fusion_shmpool_unlock( shmpool );
5223 + return -EIO;
5226 + if (! --node->count) {
5227 + fusion_list_remove (&shmpool->nodes, &node->link);
5228 + kfree (node);
5231 + fusion_shmpool_unlock( shmpool );
5233 + return 0;
5236 +int
5237 +fusion_shmpool_dispatch( FusionDev *dev,
5238 + FusionSHMPoolDispatch *dispatch,
5239 + Fusionee *fusionee )
5241 + int ret;
5242 + FusionLink *l;
5243 + FusionSHMPool *shmpool;
5244 + FusionSHMPoolMessage message;
5245 + FusionID fusion_id = fusionee_id( fusionee );
5247 + if (dispatch->size <= 0)
5248 + return -EINVAL;
5250 + ret = fusion_shmpool_lock( &dev->shmpool, dispatch->pool_id, false, &shmpool );
5251 + if (ret)
5252 + return ret;
5254 + message.type = FSMT_REMAP;
5255 + message.size = dispatch->size;
5257 + shmpool->dispatch_count++;
5259 + shmpool->size = dispatch->size;
5261 + fusion_list_foreach (l, shmpool->nodes) {
5262 + SHMPoolNode *node = (SHMPoolNode *) l;
5264 + if (node->fusion_id == fusion_id)
5265 + continue;
5267 + fusionee_send_message (dev, fusionee, node->fusion_id, FMT_SHMPOOL,
5268 + shmpool->entry.id, sizeof(message), &message);
5271 + fusion_shmpool_unlock( shmpool );
5273 + return 0;
5276 +int
5277 +fusion_shmpool_destroy (FusionDev *dev, int id)
5279 + return fusion_entry_destroy( &dev->shmpool, id );
5282 +void
5283 +fusion_shmpool_detach_all (FusionDev *dev, FusionID fusion_id)
5285 + FusionLink *l;
5287 + down (&dev->shmpool.lock);
5289 + fusion_list_foreach (l, dev->shmpool.list) {
5290 + FusionSHMPool *shmpool = (FusionSHMPool *) l;
5292 + remove_node (shmpool, fusion_id);
5295 + up (&dev->shmpool.lock);
5298 +int
5299 +fusion_shmpool_fork_all( FusionDev *dev,
5300 + FusionID fusion_id,
5301 + FusionID from_id )
5303 + FusionLink *l;
5304 + int ret = 0;
5306 + down (&dev->shmpool.lock);
5308 + fusion_list_foreach (l, dev->shmpool.list) {
5309 + FusionSHMPool *shmpool = (FusionSHMPool *) l;
5311 + ret = fork_node( shmpool, fusion_id, from_id );
5312 + if (ret)
5313 + break;
5316 + up (&dev->shmpool.lock);
5318 + return ret;
5321 +/******************************************************************************/
5323 +static SHMPoolNode *
5324 +get_node (FusionSHMPool *shmpool,
5325 + FusionID fusion_id)
5327 + SHMPoolNode *node;
5329 + fusion_list_foreach (node, shmpool->nodes) {
5330 + if (node->fusion_id == fusion_id)
5331 + return node;
5334 + return NULL;
5337 +static void
5338 +remove_node (FusionSHMPool *shmpool, FusionID fusion_id)
5340 + SHMPoolNode *node;
5342 + down (&shmpool->entry.lock);
5344 + fusion_list_foreach (node, shmpool->nodes) {
5345 + if (node->fusion_id == fusion_id) {
5346 + fusion_list_remove (&shmpool->nodes, &node->link);
5347 + break;
5351 + up (&shmpool->entry.lock);
5354 +static int
5355 +fork_node (FusionSHMPool *shmpool, FusionID fusion_id, FusionID from_id)
5357 + int ret = 0;
5358 + SHMPoolNode *node;
5360 + down (&shmpool->entry.lock);
5362 + fusion_list_foreach (node, shmpool->nodes) {
5363 + if (node->fusion_id == from_id) {
5364 + SHMPoolNode *new_node;
5366 + new_node = kmalloc (sizeof(SHMPoolNode), GFP_KERNEL);
5367 + if (!new_node) {
5368 + ret = -ENOMEM;
5369 + break;
5372 + new_node->fusion_id = fusion_id;
5373 + new_node->count = node->count;
5375 + fusion_list_prepend (&shmpool->nodes, &new_node->link);
5377 + break;
5381 + up (&shmpool->entry.lock);
5383 + return ret;
5386 +static void
5387 +free_all_nodes (FusionSHMPool *shmpool)
5390 + FusionLink *n;
5391 + SHMPoolNode *node;
5393 + fusion_list_foreach_safe (node, n, shmpool->nodes) {
5394 + kfree (node);
5397 + shmpool->nodes = NULL;
5399 diff -urN linux-2.6.22.1-0rig/drivers/char/fusion/shmpool.h linux-2.6.22.1/drivers/char/fusion/shmpool.h
5400 --- linux-2.6.22.1-0rig/drivers/char/fusion/shmpool.h 1970-01-01 01:00:00.000000000 +0100
5401 +++ linux-2.6.22.1/drivers/char/fusion/shmpool.h 2007-01-20 05:03:01.000000000 +0100
5402 @@ -0,0 +1,59 @@
5404 + * Fusion Kernel Module
5406 + * (c) Copyright 2002-2003 Convergence GmbH
5408 + * Written by Denis Oliver Kropp <dok@directfb.org>
5411 + * This program is free software; you can redistribute it and/or
5412 + * modify it under the terms of the GNU General Public License
5413 + * as published by the Free Software Foundation; either version
5414 + * 2 of the License, or (at your option) any later version.
5415 + */
5417 +#ifndef __FUSION__SHMPOOL_H__
5418 +#define __FUSION__SHMPOOL_H__
5420 +#include "fusiondev.h"
5421 +#include "types.h"
5424 +/* module init/cleanup */
5426 +int fusion_shmpool_init (FusionDev *dev);
5427 +void fusion_shmpool_deinit (FusionDev *dev);
5430 +/* public API */
5432 +int fusion_shmpool_new (FusionDev *dev,
5433 + FusionSHMPoolNew *pool);
5435 +int fusion_shmpool_attach (FusionDev *dev,
5436 + FusionSHMPoolAttach *attach,
5437 + FusionID fusion_id);
5439 +int fusion_shmpool_detach (FusionDev *dev,
5440 + int id,
5441 + FusionID fusion_id);
5443 +int fusion_shmpool_dispatch (FusionDev *dev,
5444 + FusionSHMPoolDispatch *dispatch,
5445 + Fusionee *fusionee );
5447 +int fusion_shmpool_destroy (FusionDev *dev,
5448 + int id);
5451 +/* internal functions */
5453 +void fusion_shmpool_detach_all (FusionDev *dev,
5454 + FusionID fusion_id);
5456 +int fusion_shmpool_fork_all (FusionDev *dev,
5457 + FusionID fusion_id,
5458 + FusionID from_id);
5460 +#endif
5462 diff -urN linux-2.6.22.1-0rig/drivers/char/fusion/skirmish.c linux-2.6.22.1/drivers/char/fusion/skirmish.c
5463 --- linux-2.6.22.1-0rig/drivers/char/fusion/skirmish.c 1970-01-01 01:00:00.000000000 +0100
5464 +++ linux-2.6.22.1/drivers/char/fusion/skirmish.c 2007-01-06 14:09:45.000000000 +0100
5465 @@ -0,0 +1,397 @@
5467 + * Fusion Kernel Module
5469 + * (c) Copyright 2002-2003 Convergence GmbH
5471 + * Written by Denis Oliver Kropp <dok@directfb.org>
5474 + * This program is free software; you can redistribute it and/or
5475 + * modify it under the terms of the GNU General Public License
5476 + * as published by the Free Software Foundation; either version
5477 + * 2 of the License, or (at your option) any later version.
5478 + */
5480 +#ifdef HAVE_LINUX_CONFIG_H
5481 +#include <linux/config.h>
5482 +#endif
5483 +#include <linux/types.h>
5484 +#include <linux/kernel.h>
5485 +#include <linux/slab.h>
5486 +#include <linux/smp_lock.h>
5487 +#include <linux/sched.h>
5489 +#include <linux/fusion.h>
5491 +#include "fusiondev.h"
5492 +#include "fusionee.h"
5493 +#include "list.h"
5494 +#include "skirmish.h"
5497 +#define MAX_PRE_ACQUISITIONS 32
5500 +typedef struct __FUSION_FusionSkirmish FusionSkirmish;
5502 +struct __FUSION_FusionSkirmish {
5503 + FusionEntry entry;
5505 + int lock_fid; /* non-zero if locked */
5506 + int lock_pid;
5507 + int lock_count;
5509 + int lock_total;
5511 +#ifdef FUSION_DEBUG_SKIRMISH_DEADLOCK
5512 + int pre_acquis[MAX_PRE_ACQUISITIONS];
5514 + bool outer;
5515 +#endif
5518 +static int
5519 +fusion_skirmish_print( FusionEntry *entry,
5520 + void *ctx,
5521 + char *buf )
5523 + int written = 0;
5524 + FusionSkirmish *skirmish = (FusionSkirmish*) entry;
5526 +#ifdef FUSION_DEBUG_SKIRMISH_DEADLOCK
5527 + int i, n;
5530 + for (i=0, n=0; i<MAX_PRE_ACQUISITIONS; i++) {
5531 + if (skirmish->pre_acquis[i]) {
5532 + n++;
5536 + written += sprintf( buf + written, "[%2d]%s", n, skirmish->outer ? "." : " " );
5538 + for (i=0, n=0; i<MAX_PRE_ACQUISITIONS; i++) {
5539 + if (skirmish->pre_acquis[i]) {
5540 + written += sprintf( buf + written, "%s%02x", n ? "," : "", skirmish->pre_acquis[i] - 1 );
5542 + n++;
5545 +#endif
5547 + if (skirmish->lock_fid) {
5548 + if (skirmish->entry.waiters)
5549 + return sprintf( buf + written, " - %dx [0x%08x] (%d) %d WAITING\n",
5550 + skirmish->lock_count, skirmish->lock_fid,
5551 + skirmish->lock_pid, skirmish->entry.waiters ) + written;
5552 + else
5553 + return sprintf( buf + written, " - %dx [0x%08x] (%d)\n",
5554 + skirmish->lock_count, skirmish->lock_fid,
5555 + skirmish->lock_pid ) + written;
5558 + return sprintf( buf + written, "\n" ) + written;
5561 +FUSION_ENTRY_CLASS( FusionSkirmish, skirmish, NULL, NULL, fusion_skirmish_print )
5563 +/******************************************************************************/
5565 +int
5566 +fusion_skirmish_init (FusionDev *dev)
5568 + fusion_entries_init( &dev->skirmish, &skirmish_class, dev );
5570 + create_proc_read_entry( "skirmishs", 0, dev->proc_dir,
5571 + fusion_entries_read_proc, &dev->skirmish );
5573 + return 0;
5576 +void
5577 +fusion_skirmish_deinit (FusionDev *dev)
5579 + remove_proc_entry ("skirmishs", dev->proc_dir);
5581 + fusion_entries_deinit( &dev->skirmish );
5584 +/******************************************************************************/
5586 +int
5587 +fusion_skirmish_new (FusionDev *dev, int *ret_id)
5589 + return fusion_entry_create( &dev->skirmish, ret_id, NULL );
5592 +int
5593 +fusion_skirmish_prevail (FusionDev *dev, int id, int fusion_id)
5595 + int ret;
5596 + FusionSkirmish *skirmish;
5597 +#ifdef FUSION_DEBUG_SKIRMISH_DEADLOCK
5598 + FusionSkirmish *s;
5599 + int i;
5600 + bool outer = true;
5601 +#endif
5603 + dev->stat.skirmish_prevail_swoop++;
5605 + ret = fusion_skirmish_lock( &dev->skirmish, id, true, &skirmish );
5606 + if (ret)
5607 + return ret;
5609 + if (skirmish->lock_pid == current->pid) {
5610 + skirmish->lock_count++;
5611 + skirmish->lock_total++;
5612 + fusion_skirmish_unlock( skirmish );
5613 + up( &dev->skirmish.lock );
5614 + return 0;
5617 +#ifdef FUSION_DEBUG_SKIRMISH_DEADLOCK
5618 + /* look in currently acquired skirmishs for this one being
5619 + a pre-acquisition, indicating a potential deadlock */
5620 + fusion_list_foreach (s, dev->skirmish.list) {
5621 + if (s->lock_pid != current->pid)
5622 + continue;
5624 + outer = false;
5626 + for (i=0; i<MAX_PRE_ACQUISITIONS; i++) {
5627 + if (s->pre_acquis[i] == id + 1) {
5628 + printk( KERN_DEBUG "FusionSkirmish: Potential deadlock "
5629 + "between locked 0x%x and to be locked 0x%x in world %d!\n",
5630 + s->entry.id, skirmish->entry.id, dev->index );
5635 + if (outer)
5636 + skirmish->outer = true;
5638 + /* remember all previously acquired skirmishs being pre-acquisitions for
5639 + this one, to detect potential deadlocks due to a lock order twist */
5640 + fusion_list_foreach (s, dev->skirmish.list) {
5641 + int free = -1;
5643 + if (s->lock_pid != current->pid)
5644 + continue;
5646 + for (i=0; i<MAX_PRE_ACQUISITIONS; i++) {
5647 + if (skirmish->pre_acquis[i]) {
5648 + if (skirmish->pre_acquis[i] == s->entry.id + 1) {
5649 + break;
5652 + else
5653 + free = i;
5656 + /* not found? */
5657 + if (i == MAX_PRE_ACQUISITIONS) {
5658 + if (free != -1) {
5659 + skirmish->pre_acquis[free] = s->entry.id + 1;
5661 + else {
5662 + printk( KERN_DEBUG "FusionSkirmish: Too many pre-acquisitions to remember.\n" );
5664 + printk( KERN_DEBUG " [ '%s' ] <- ", skirmish->entry.name );
5666 + for (i=0; i<MAX_PRE_ACQUISITIONS; i++)
5667 + printk( "0x%03x ", skirmish->pre_acquis[i] - 1 );
5669 + printk( "\n" );
5673 +#endif
5675 + up( &dev->skirmish.lock );
5677 + while (skirmish->lock_pid) {
5678 + ret = fusion_skirmish_wait( skirmish, NULL );
5679 + if (ret)
5680 + return ret;
5683 + skirmish->lock_fid = fusion_id;
5684 + skirmish->lock_pid = current->pid;
5685 + skirmish->lock_count = 1;
5687 + skirmish->lock_total++;
5689 + fusion_skirmish_unlock( skirmish );
5691 + return 0;
5694 +int
5695 +fusion_skirmish_swoop (FusionDev *dev, int id, int fusion_id)
5697 + int ret;
5698 + FusionSkirmish *skirmish;
5700 + ret = fusion_skirmish_lock( &dev->skirmish, id, false, &skirmish );
5701 + if (ret)
5702 + return ret;
5704 + dev->stat.skirmish_prevail_swoop++;
5706 + if (skirmish->lock_fid) {
5707 + if (skirmish->lock_pid == current->pid) {
5708 + skirmish->lock_count++;
5709 + skirmish->lock_total++;
5710 + fusion_skirmish_unlock( skirmish );
5711 + return 0;
5714 + fusion_skirmish_unlock( skirmish );
5716 + return -EAGAIN;
5719 + skirmish->lock_fid = fusion_id;
5720 + skirmish->lock_pid = current->pid;
5721 + skirmish->lock_count = 1;
5723 + skirmish->lock_total++;
5725 + fusion_skirmish_unlock( skirmish );
5727 + return 0;
5730 +int
5731 +fusion_skirmish_lock_count (FusionDev *dev, int id, int fusion_id, int *ret_lock_count)
5733 + int ret;
5734 + FusionSkirmish *skirmish;
5736 + ret = fusion_skirmish_lock( &dev->skirmish, id, false, &skirmish );
5737 + if (ret)
5738 + return ret;
5740 + if (skirmish->lock_fid == fusion_id &&
5741 + skirmish->lock_pid == current->pid)
5743 + *ret_lock_count = skirmish->lock_count;
5745 + else
5747 + *ret_lock_count = 0;
5750 + fusion_skirmish_unlock( skirmish );
5752 + return 0;
5755 +int
5756 +fusion_skirmish_dismiss (FusionDev *dev, int id, int fusion_id)
5758 + int ret;
5759 + FusionSkirmish *skirmish;
5761 + ret = fusion_skirmish_lock( &dev->skirmish, id, false, &skirmish );
5762 + if (ret)
5763 + return ret;
5765 + dev->stat.skirmish_dismiss++;
5767 + if (skirmish->lock_pid != current->pid) {
5768 + fusion_skirmish_unlock( skirmish );
5769 + return -EIO;
5772 + if (--skirmish->lock_count == 0) {
5773 + skirmish->lock_fid = 0;
5774 + skirmish->lock_pid = 0;
5776 + fusion_skirmish_notify( skirmish, true );
5779 + fusion_skirmish_unlock( skirmish );
5781 + return 0;
5784 +int
5785 +fusion_skirmish_destroy (FusionDev *dev, int id)
5787 +#ifdef FUSION_DEBUG_SKIRMISH_DEADLOCK
5788 + int i;
5789 + FusionSkirmish *s;
5791 + /* Lock entries. */
5792 + if (down_interruptible( &dev->skirmish.lock ))
5793 + return -EINTR;
5795 + /* remove from all pre-acquisition lists */
5796 + fusion_list_foreach (s, dev->skirmish.list) {
5797 + for (i=0; i<MAX_PRE_ACQUISITIONS; i++) {
5798 + if (s->pre_acquis[i] == id + 1)
5799 + s->pre_acquis[i] = 0;
5803 + up( &dev->skirmish.lock );
5805 + /* FIXME: gap? */
5806 +#endif
5808 + return fusion_entry_destroy( &dev->skirmish, id );
5811 +void
5812 +fusion_skirmish_dismiss_all (FusionDev *dev, int fusion_id)
5814 + FusionLink *l;
5816 + down (&dev->skirmish.lock);
5818 + fusion_list_foreach (l, dev->skirmish.list) {
5819 + FusionSkirmish *skirmish = (FusionSkirmish *) l;
5821 + down (&skirmish->entry.lock);
5823 + if (skirmish->lock_fid == fusion_id) {
5824 + skirmish->lock_fid = 0;
5825 + skirmish->lock_pid = 0;
5826 + skirmish->lock_count = 0;
5828 + wake_up_interruptible_all (&skirmish->entry.wait);
5831 + up (&skirmish->entry.lock);
5834 + up (&dev->skirmish.lock);
5837 +void
5838 +fusion_skirmish_dismiss_all_from_pid (FusionDev *dev, int pid)
5840 + FusionLink *l;
5842 + down (&dev->skirmish.lock);
5844 + fusion_list_foreach (l, dev->skirmish.list) {
5845 + FusionSkirmish *skirmish = (FusionSkirmish *) l;
5847 + down (&skirmish->entry.lock);
5849 + if (skirmish->lock_pid == pid) {
5850 + skirmish->lock_fid = 0;
5851 + skirmish->lock_pid = 0;
5852 + skirmish->lock_count = 0;
5854 + wake_up_interruptible_all (&skirmish->entry.wait);
5857 + up (&skirmish->entry.lock);
5860 + up (&dev->skirmish.lock);
5863 diff -urN linux-2.6.22.1-0rig/drivers/char/fusion/skirmish.h linux-2.6.22.1/drivers/char/fusion/skirmish.h
5864 --- linux-2.6.22.1-0rig/drivers/char/fusion/skirmish.h 1970-01-01 01:00:00.000000000 +0100
5865 +++ linux-2.6.22.1/drivers/char/fusion/skirmish.h 2006-06-30 10:54:55.000000000 +0200
5866 @@ -0,0 +1,62 @@
5868 + * Fusion Kernel Module
5870 + * (c) Copyright 2002-2003 Convergence GmbH
5872 + * Written by Denis Oliver Kropp <dok@directfb.org>
5875 + * This program is free software; you can redistribute it and/or
5876 + * modify it under the terms of the GNU General Public License
5877 + * as published by the Free Software Foundation; either version
5878 + * 2 of the License, or (at your option) any later version.
5879 + */
5881 +#ifndef __FUSION__SKIRMISH_H__
5882 +#define __FUSION__SKIRMISH_H__
5884 +#include "fusiondev.h"
5885 +#include "types.h"
5888 +/* module init/cleanup */
5890 +int fusion_skirmish_init (FusionDev *dev);
5891 +void fusion_skirmish_deinit (FusionDev *dev);
5894 +/* public API */
5896 +int fusion_skirmish_new (FusionDev *dev,
5897 + int *id);
5899 +int fusion_skirmish_prevail (FusionDev *dev,
5900 + int id,
5901 + int fusion_id);
5903 +int fusion_skirmish_swoop (FusionDev *dev,
5904 + int id,
5905 + int fusion_id);
5907 +int fusion_skirmish_lock_count (FusionDev *dev,
5908 + int id,
5909 + int fusion_id,
5910 + int *ret_lock_count);
5912 +int fusion_skirmish_dismiss (FusionDev *dev,
5913 + int id,
5914 + int fusion_id);
5916 +int fusion_skirmish_destroy (FusionDev *dev,
5917 + int id);
5920 +/* internal functions */
5922 +void fusion_skirmish_dismiss_all (FusionDev *dev,
5923 + int fusion_id);
5925 +void fusion_skirmish_dismiss_all_from_pid (FusionDev *dev,
5926 + int pid);
5928 +#endif
5929 diff -urN linux-2.6.22.1-0rig/drivers/char/fusion/types.h linux-2.6.22.1/drivers/char/fusion/types.h
5930 --- linux-2.6.22.1-0rig/drivers/char/fusion/types.h 1970-01-01 01:00:00.000000000 +0100
5931 +++ linux-2.6.22.1/drivers/char/fusion/types.h 2007-01-20 05:03:01.000000000 +0100
5932 @@ -0,0 +1,29 @@
5934 + * Fusion Kernel Module
5936 + * (c) Copyright 2002 Convergence GmbH
5938 + * Written by Denis Oliver Kropp <dok@directfb.org>
5941 + * This program is free software; you can redistribute it and/or
5942 + * modify it under the terms of the GNU General Public License
5943 + * as published by the Free Software Foundation; either version
5944 + * 2 of the License, or (at your option) any later version.
5945 + */
5947 +#ifndef __FUSION__TYPES_H__
5948 +#define __FUSION__TYPES_H__
5950 +#include <linux/version.h>
5952 +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 18)
5953 +typedef enum {
5954 + false = 0,
5955 + true = !false
5956 +} bool;
5957 +#endif
5959 +typedef struct __Fusion_Fusionee Fusionee;
5961 +#endif
5962 diff -urN linux-2.6.22.1-0rig/drivers/char/Kconfig linux-2.6.22.1/drivers/char/Kconfig
5963 --- linux-2.6.22.1-0rig/drivers/char/Kconfig 2007-07-10 20:56:30.000000000 +0200
5964 +++ linux-2.6.22.1/drivers/char/Kconfig 2007-08-12 19:30:42.000000000 +0200
5965 @@ -484,6 +484,8 @@
5966 All modern Linux systems use the Unix98 ptys. Say Y unless
5967 you're on an embedded system and want to conserve memory.
5969 +source "drivers/char/fusion/Kconfig"
5971 config LEGACY_PTYS
5972 bool "Legacy (BSD) PTY support"
5973 default y
5974 diff -urN linux-2.6.22.1-0rig/drivers/char/Makefile linux-2.6.22.1/drivers/char/Makefile
5975 --- linux-2.6.22.1-0rig/drivers/char/Makefile 2007-07-10 20:56:30.000000000 +0200
5976 +++ linux-2.6.22.1/drivers/char/Makefile 2007-08-12 19:45:20.000000000 +0200
5977 @@ -100,6 +100,7 @@
5978 obj-$(CONFIG_DRM) += drm/
5979 obj-$(CONFIG_PCMCIA) += pcmcia/
5980 obj-$(CONFIG_IPMI_HANDLER) += ipmi/
5981 +obj-$(CONFIG_FUSION_DEVICE) += fusion/
5983 obj-$(CONFIG_HANGCHECK_TIMER) += hangcheck-timer.o
5984 obj-$(CONFIG_TCG_TPM) += tpm/
5985 diff -urN linux-2.6.22.1-0rig/include/linux/fusion.h linux-2.6.22.1/include/linux/fusion.h
5986 --- linux-2.6.22.1-0rig/include/linux/fusion.h 1970-01-01 01:00:00.000000000 +0100
5987 +++ linux-2.6.22.1/include/linux/fusion.h 2007-01-29 01:43:50.000000000 +0100
5988 @@ -0,0 +1,277 @@
5989 +#ifndef __LINUX__FUSION_H__
5990 +#define __LINUX__FUSION_H__
5992 +#include <asm/ioctl.h>
5995 + * Fusion Kernel Device API Version
5996 + */
5997 +#define FUSION_API_MAJOR 3 /* Increased if backward compatibility is dropped. */
5998 +#define FUSION_API_MINOR 2 /* Increased if new features are added. */
6001 + * The Fusion ID is a unique identifier for one process consisting of threads.
6002 + */
6003 +typedef unsigned long FusionID;
6005 +#define FUSION_ID_MASTER 1 /* This is the fusion id of the master (first process). */
6008 + * Entering a world
6009 + */
6010 +typedef struct {
6011 + struct {
6012 + int major; /* Must be set to FUSION_API_MAJOR before entering. */
6013 + int minor; /* Must be set to FUSION_API_MINOR before entering. */
6014 + } api;
6016 + FusionID fusion_id; /* Returns the fusion id of the entering process. */
6017 +} FusionEnter;
6020 + * Forking in world
6021 + */
6022 +typedef struct {
6023 + FusionID fusion_id; /* Returns the fusion id of the new (forked) fusionee. */
6024 +} FusionFork;
6027 + * Sending a message
6028 + */
6029 +typedef struct {
6030 + FusionID fusion_id; /* recipient */
6032 + int msg_id; /* optional message identifier */
6033 + int msg_size; /* message size, must be greater than zero */
6034 + const void *msg_data; /* message data, must not be NULL */
6035 +} FusionSendMessage;
6038 + * Receiving a message
6039 + */
6040 +typedef enum {
6041 + FMT_SEND, /* msg_id is an optional custom id */
6042 + FMT_CALL, /* msg_id is the call id */
6043 + FMT_REACTOR, /* msg_id is the reactor id */
6044 + FMT_SHMPOOL /* msg_id is the pool id */
6045 +} FusionMessageType;
6047 +typedef struct {
6048 + FusionMessageType msg_type; /* type (origin) of message */
6050 + int msg_id; /* message id (custom id or call/reactor/pool id) */
6051 + int msg_size; /* size of the following message data */
6053 + /* message data follows */
6054 +} FusionReadMessage;
6057 + * Dispatching a message via a reactor
6058 + */
6059 +typedef struct {
6060 + int reactor_id;
6061 + int self;
6063 + int msg_size; /* message size, must be greater than zero */
6064 + const void *msg_data; /* message data, must not be NULL */
6065 +} FusionReactorDispatch;
6068 + * Calling (synchronous RPC)
6069 + */
6070 +typedef struct {
6071 + int call_id; /* new call id returned */
6073 + void *handler; /* function pointer of handler to install */
6074 + void *ctx; /* optional handler context */
6075 +} FusionCallNew;
6077 +typedef enum {
6078 + FCEF_NONE = 0x00000000,
6079 + FCEF_ONEWAY = 0x00000001,
6080 + FCEF_ALL = 0x00000001
6081 +} FusionCallExecFlags;
6083 +typedef struct {
6084 + int ret_val; /* return value of the call */
6086 + int call_id; /* id of the requested call, each call has a fixed owner */
6088 + int call_arg; /* optional int argument */
6089 + void *call_ptr; /* optional pointer argument (shared memory) */
6091 + FusionCallExecFlags flags; /* execution flags */
6092 +} FusionCallExecute;
6094 +typedef struct {
6095 + int call_id; /* id of currently executing call */
6097 + int val; /* value to return */
6098 +} FusionCallReturn;
6100 +typedef struct {
6101 + void *handler; /* function pointer of handler to call */
6102 + void *ctx; /* optional handler context */
6104 + int caller; /* fusion id of the caller or zero if called from Fusion */
6105 + int call_arg; /* optional call parameter */
6106 + void *call_ptr; /* optional call parameter */
6107 +} FusionCallMessage;
6110 + * Watching a reference
6112 + * This information is needed to have a specific call being executed if the
6113 + * reference count reaches zero. Currently one watch per reference is allowed.
6115 + * The call is made by Fusion and therefor has a caller id of zero.
6117 + */
6118 +typedef struct {
6119 + int id; /* id of the reference to watch */
6121 + int call_id; /* id of the call to execute */
6122 + int call_arg; /* optional call parameter, e.g. the id of a user
6123 + space resource associated with that reference */
6124 +} FusionRefWatch;
6127 + * Inheriting local count from other reference
6128 + */
6129 +typedef struct {
6130 + int id; /* own reference id */
6131 + int from; /* id of the reference to inherit from */
6132 +} FusionRefInherit;
6135 + * Killing other fusionees (experimental)
6136 + */
6137 +typedef struct {
6138 + FusionID fusion_id; /* fusionee to kill, zero means all but ourself */
6139 + int signal; /* signal to be delivered, e.g. SIGTERM */
6140 + int timeout_ms; /* -1 means no timeout, 0 means infinite, otherwise the
6141 + max. time to wait until the fusionee(s) terminated */
6142 +} FusionKill;
6146 + * Shared memory pools
6147 + */
6148 +typedef struct {
6149 + int max_size; /* Maximum size that this pool will be allowed to grow to. */
6151 + int pool_id; /* Returns the new pool id. */
6152 + void *addr_base; /* Returns the base of the reserved virtual memory address space. */
6153 +} FusionSHMPoolNew;
6155 +typedef struct {
6156 + int pool_id; /* The id of the pool to attach to. */
6158 + void *addr_base; /* Returns the base of the reserved virtual memory address space. */
6159 + int size; /* Returns the current size of the pool. */
6160 +} FusionSHMPoolAttach;
6162 +typedef struct {
6163 + int pool_id; /* The id of the pool to notify. */
6165 + int size; /* New size of the pool. */
6166 +} FusionSHMPoolDispatch;
6168 +typedef enum {
6169 + FSMT_REMAP, /* Remap the pool due to a change of its size. */
6170 + FSMT_UNMAP /* Unmap the pool due to its destruction. */
6171 +} FusionSHMPoolMessageType;
6173 +typedef struct {
6174 + FusionSHMPoolMessageType type; /* Type of the message. */
6176 + int size; /* New size of the pool, if type is FSMT_REMAP. */
6177 +} FusionSHMPoolMessage;
6181 + * Fusion types
6182 + */
6183 +typedef enum {
6184 + FT_LOUNGE,
6185 + FT_MESSAGING,
6186 + FT_CALL,
6187 + FT_REF,
6188 + FT_SKIRMISH,
6189 + FT_PROPERTY,
6190 + FT_REACTOR,
6191 + FT_SHMPOOL
6192 +} FusionType;
6196 + * Set attributes like 'name' for an entry of the specified type.
6197 + */
6198 +#define FUSION_ENTRY_INFO_NAME_LENGTH 24
6200 +typedef struct {
6201 + FusionType type;
6202 + int id;
6204 + char name[FUSION_ENTRY_INFO_NAME_LENGTH];
6205 +} FusionEntryInfo;
6209 +#define FUSION_ENTER _IOR(FT_LOUNGE, 0x00, FusionEnter)
6210 +#define FUSION_UNBLOCK _IO (FT_LOUNGE, 0x01)
6211 +#define FUSION_KILL _IOW(FT_LOUNGE, 0x02, FusionKill)
6213 +#define FUSION_ENTRY_SET_INFO _IOW(FT_LOUNGE, 0x03, FusionEntryInfo)
6214 +#define FUSION_ENTRY_GET_INFO _IOW(FT_LOUNGE, 0x04, FusionEntryInfo)
6216 +#define FUSION_FORK _IOW(FT_LOUNGE, 0x05, FusionFork)
6218 +#define FUSION_SEND_MESSAGE _IOW(FT_MESSAGING, 0x00, FusionSendMessage)
6220 +#define FUSION_CALL_NEW _IOW(FT_CALL, 0x00, FusionCallNew)
6221 +#define FUSION_CALL_EXECUTE _IOW(FT_CALL, 0x01, FusionCallExecute)
6222 +#define FUSION_CALL_RETURN _IOW(FT_CALL, 0x02, FusionCallReturn)
6223 +#define FUSION_CALL_DESTROY _IOW(FT_CALL, 0x03, int)
6225 +#define FUSION_REF_NEW _IOW(FT_REF, 0x00, int)
6226 +#define FUSION_REF_UP _IOW(FT_REF, 0x01, int)
6227 +#define FUSION_REF_UP_GLOBAL _IOW(FT_REF, 0x02, int)
6228 +#define FUSION_REF_DOWN _IOW(FT_REF, 0x03, int)
6229 +#define FUSION_REF_DOWN_GLOBAL _IOW(FT_REF, 0x04, int)
6230 +#define FUSION_REF_ZERO_LOCK _IOW(FT_REF, 0x05, int)
6231 +#define FUSION_REF_ZERO_TRYLOCK _IOW(FT_REF, 0x06, int)
6232 +#define FUSION_REF_UNLOCK _IOW(FT_REF, 0x07, int)
6233 +#define FUSION_REF_STAT _IOW(FT_REF, 0x08, int)
6234 +#define FUSION_REF_WATCH _IOW(FT_REF, 0x09, FusionRefWatch)
6235 +#define FUSION_REF_INHERIT _IOW(FT_REF, 0x0A, FusionRefInherit)
6236 +#define FUSION_REF_DESTROY _IOW(FT_REF, 0x0B, int)
6238 +#define FUSION_SKIRMISH_NEW _IOW(FT_SKIRMISH, 0x00, int)
6239 +#define FUSION_SKIRMISH_PREVAIL _IOW(FT_SKIRMISH, 0x01, int)
6240 +#define FUSION_SKIRMISH_SWOOP _IOW(FT_SKIRMISH, 0x02, int)
6241 +#define FUSION_SKIRMISH_DISMISS _IOW(FT_SKIRMISH, 0x03, int)
6242 +#define FUSION_SKIRMISH_DESTROY _IOW(FT_SKIRMISH, 0x04, int)
6243 +#define FUSION_SKIRMISH_LOCK_COUNT _IOW(FT_SKIRMISH, 0x05, int)
6245 +#define FUSION_PROPERTY_NEW _IOW(FT_PROPERTY, 0x00, int)
6246 +#define FUSION_PROPERTY_LEASE _IOW(FT_PROPERTY, 0x01, int)
6247 +#define FUSION_PROPERTY_PURCHASE _IOW(FT_PROPERTY, 0x02, int)
6248 +#define FUSION_PROPERTY_CEDE _IOW(FT_PROPERTY, 0x03, int)
6249 +#define FUSION_PROPERTY_HOLDUP _IOW(FT_PROPERTY, 0x04, int)
6250 +#define FUSION_PROPERTY_DESTROY _IOW(FT_PROPERTY, 0x05, int)
6252 +#define FUSION_REACTOR_NEW _IOW(FT_REACTOR, 0x00, int)
6253 +#define FUSION_REACTOR_ATTACH _IOW(FT_REACTOR, 0x01, int)
6254 +#define FUSION_REACTOR_DETACH _IOW(FT_REACTOR, 0x02, int)
6255 +#define FUSION_REACTOR_DISPATCH _IOW(FT_REACTOR, 0x03, FusionReactorDispatch)
6256 +#define FUSION_REACTOR_DESTROY _IOW(FT_REACTOR, 0x04, int)
6258 +#define FUSION_SHMPOOL_NEW _IOW(FT_SHMPOOL, 0x00, FusionSHMPoolNew)
6259 +#define FUSION_SHMPOOL_ATTACH _IOW(FT_SHMPOOL, 0x01, FusionSHMPoolAttach)
6260 +#define FUSION_SHMPOOL_DETACH _IOW(FT_SHMPOOL, 0x02, int)
6261 +#define FUSION_SHMPOOL_DISPATCH _IOW(FT_SHMPOOL, 0x03, FusionSHMPoolDispatch)
6262 +#define FUSION_SHMPOOL_DESTROY _IOW(FT_SHMPOOL, 0x04, int)
6264 +#endif