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
6 + * Fusion Kernel Module
8 + * (c) Copyright 2002-2003 Convergence GmbH
10 + * Written by Denis Oliver Kropp <dok@directfb.org>
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.
19 +#ifdef HAVE_LINUX_CONFIG_H
20 +#include <linux/config.h>
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"
44 + wait_queue_head_t wait;
45 +} FusionCallExecution;
50 + struct semaphore lock;
52 + int id; /* call id */
54 + int pid; /* owner pid */
55 + int fusion_id; /* owner fusion id */
60 + FusionLink *executions; /* prepending! */
61 + FusionLink *last; /* points to the last item of executions */
63 + int count; /* number of calls ever made */
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,
74 + FusionCallExecute *execute);
75 +static void remove_execution (FusionCall *call,
76 + FusionCallExecution *execution);
77 +static void free_all_executions (FusionCall *call);
79 +/******************************************************************************/
82 +fusion_call_read_proc (char *buf, char **start, off_t offset,
83 + int len, int *eof, void *private)
86 + FusionDev *dev = private;
89 + if (down_interruptible (&dev->call.lock))
92 + fusion_list_foreach (l, dev->call.list) {
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) {
117 + if (written >= len)
121 + up (&dev->call.lock);
123 + *start = buf + offset;
125 + if (written > len) {
131 + return(written<0) ? 0 : written;
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);
146 +fusion_call_deinit (FusionDev *dev)
150 + down (&dev->call.lock);
152 + remove_proc_entry ("calls", dev->proc_dir);
154 + l = dev->call.list;
156 + FusionLink *next = l->next;
157 + FusionCall *call = (FusionCall *) l;
159 + free_all_executions (call);
166 + up (&dev->call.lock);
169 +/******************************************************************************/
172 +fusion_call_new (FusionDev *dev, int fusion_id, FusionCallNew *call_new)
176 + call = kmalloc (sizeof(FusionCall), GFP_KERNEL);
180 + memset (call, 0, sizeof(FusionCall));
182 + if (down_interruptible (&dev->call.lock)) {
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;
205 +fusion_call_execute (FusionDev *dev, Fusionee *fusionee, FusionCallExecute *execute)
209 + FusionCallExecution *execution;
210 + FusionCallMessage message;
212 + ret = lock_call (dev, execute->call_id, &call);
216 + execution = add_execution (call, fusionee, execute);
218 + unlock_call (call);
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);
234 + remove_execution (call, execution);
236 + unlock_call (call);
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);
248 + return ret == -EINVAL ? -EIDRM : ret;
250 + if (signal_pending(current)) {
251 + execution->caller = 0;
252 + unlock_call (call);
256 + execute->ret_val = execution->ret_val;
258 + remove_execution (call, execution);
263 + unlock_call (call);
269 +fusion_call_return (FusionDev *dev, int fusion_id, FusionCallReturn *call_ret)
275 + ret = lock_call (dev, call_ret->call_id, &call);
281 + FusionCallExecution *execution = (FusionCallExecution*) l;
283 + if (execution->executed) {
288 + if (execution->caller) {
289 + execution->ret_val = call_ret->val;
290 + execution->executed = true;
292 + wake_up_interruptible_all (&execution->wait);
295 + remove_execution (call, execution);
300 + unlock_call (call);
305 + unlock_call (call);
311 +fusion_call_destroy (FusionDev *dev, int fusion_id, int call_id)
316 + ret = lookup_call (dev, call_id, &call);
320 + if (call->fusion_id != fusion_id) {
321 + up (&dev->call.lock);
325 + if (down_interruptible (&call->lock)) {
326 + up (&dev->call.lock);
330 + fusion_list_remove (&dev->call.list, &call->link);
332 + free_all_executions (call);
334 + up (&dev->call.lock);
344 +fusion_call_destroy_all (FusionDev *dev, int fusion_id)
348 + down (&dev->call.lock);
350 + l = dev->call.list;
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);
373 + up (&dev->call.lock);
376 +/******************************************************************************/
379 +lookup_call (FusionDev *dev, int id, FusionCall **ret_call)
383 + if (down_interruptible (&dev->call.lock))
386 + fusion_list_foreach (l, dev->call.list) {
387 + FusionCall *call = (FusionCall *) l;
389 + if (call->id == id) {
395 + up (&dev->call.lock);
401 +lock_call (FusionDev *dev, int id, FusionCall **ret_call)
406 + ret = lookup_call (dev, id, &call);
411 + fusion_list_move_to_front (&dev->call.list, &call->link);
413 + if (down_interruptible (&call->lock)) {
414 + up (&dev->call.lock);
418 + up (&dev->call.lock);
427 +unlock_call (FusionCall *call)
432 +static FusionCallExecution *
433 +add_execution (FusionCall *call,
435 + FusionCallExecute *execute)
437 + FusionCallExecution *execution;
439 + /* Allocate execution. */
440 + execution = kmalloc (sizeof(FusionCallExecution), GFP_KERNEL);
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);
455 + call->last = &execution->link;
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);
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);
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
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.
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);
516 +int fusion_call_new (FusionDev *dev,
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,
526 + FusionCallReturn *call_ret);
528 +int fusion_call_destroy (FusionDev *dev,
533 +/* internal functions */
535 +void fusion_call_destroy_all (FusionDev *dev,
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
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
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.
567 +#ifdef HAVE_LINUX_CONFIG_H
568 +#include <linux/config.h>
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"
585 +fusion_entries_init( FusionEntries *entries,
586 + FusionEntryClass *class,
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 );
602 +fusion_entries_deinit( FusionEntries *entries )
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 );
622 + up( &entries->lock );
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;
633 + struct timeval now;
635 + FUSION_ASSERT( entries != NULL );
636 + FUSION_ASSERT( entries->class != NULL );
638 + class = entries->class;
643 + if (down_interruptible (&entries->lock))
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);
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 );
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 );
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) {
683 + if (written >= len)
687 + up (&entries->lock);
689 + *start = buf + offset;
691 + if (written > len) {
698 + return (written<0) ? 0 : written;
702 +fusion_entry_create( FusionEntries *entries,
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 );
720 + memset( entry, 0, class->object_size );
722 + if (down_interruptible( &entries->lock )) {
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 );
736 + ret = class->Init( entry, entries->ctx, create_ctx );
738 + up( &entries->lock );
744 + fusion_list_prepend( &entries->list, &entry->link );
746 + up( &entries->lock );
748 + *ret_id = entry->id;
754 +fusion_entry_destroy( FusionEntries *entries,
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 ))
769 + /* Lookup the entry. */
770 + fusion_list_foreach (entry, entries->list) {
771 + if (entry->id == id)
775 + /* Check if no entry was found. */
777 + up( &entries->lock );
781 + /* Lock the entry. */
782 + if (down_interruptible( &entry->lock )) {
783 + up( &entries->lock );
787 + /* Destroy it now. */
788 + fusion_entry_destroy_locked( entries, entry );
790 + /* Unlock entries. */
791 + up( &entries->lock );
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. */
825 +fusion_entry_set_info( FusionEntries *entries,
826 + const FusionEntryInfo *info )
829 + FusionEntry *entry;
831 + FUSION_ASSERT( entries != NULL );
832 + FUSION_ASSERT( info != NULL );
834 + ret = fusion_entry_lock( entries, info->id, false, &entry );
838 + snprintf( entry->name, FUSION_ENTRY_INFO_NAME_LENGTH, info->name );
840 + fusion_entry_unlock( entry );
846 +fusion_entry_get_info( FusionEntries *entries,
847 + FusionEntryInfo *info )
850 + FusionEntry *entry;
852 + FUSION_ASSERT( entries != NULL );
853 + FUSION_ASSERT( info != NULL );
855 + ret = fusion_entry_lock( entries, info->id, false, &entry );
859 + snprintf( info->name, FUSION_ENTRY_INFO_NAME_LENGTH, entry->name );
861 + fusion_entry_unlock( entry );
867 +fusion_entry_lock( FusionEntries *entries,
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 ))
881 + /* Lookup the entry. */
882 + fusion_list_foreach (entry, entries->list) {
883 + if (entry->id == id)
887 + /* Check if no entry was found. */
889 + up( &entries->lock );
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 );
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;
913 + entry->last_lock = xtime;
916 + /* Unlock entries. */
917 + if (!keep_entries_lock)
918 + up( &entries->lock );
920 + /* Return the locked entry. */
921 + *ret_entry = entry;
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 );
939 +fusion_entry_wait( FusionEntry *entry, long *timeout )
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 );
951 + entries = entry->entries;
955 + entry->lock_pid = 0;
956 + fusion_sleep_on( &entry->wait, &entry->lock, timeout );
960 + if (signal_pending(current))
963 + if (timeout && !*timeout)
966 + ret = fusion_entry_lock( entries, id, false, &entry2 );
972 + if (entry != entry2)
980 +fusion_entry_notify( FusionEntry *entry, bool all )
982 + FUSION_ASSERT( entry != NULL );
983 + FUSION_ASSUME( entry->lock_pid == current->pid );
986 + wake_up_interruptible_all( &entry->wait );
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
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.
1009 +#ifndef __FUSION__ENTRIES_H__
1010 +#define __FUSION__ENTRIES_H__
1016 +typedef struct __FD_FusionEntry FusionEntry;
1019 +typedef const struct {
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;
1029 + FusionEntryClass *class;
1034 + struct semaphore lock;
1038 +struct __FD_FusionEntry {
1041 + FusionEntries *entries;
1048 + struct semaphore lock;
1049 + wait_queue_head_t wait;
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,
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,
1077 + void *create_ctx );
1079 +int fusion_entry_destroy ( FusionEntries *entries,
1082 +void fusion_entry_destroy_locked( FusionEntries *entries,
1083 + FusionEntry *entry );
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,
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.
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.
1120 +int fusion_entry_wait ( FusionEntry *entry,
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.
1128 +void fusion_entry_notify ( FusionEntry *entry,
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 \
1141 + static inline int fusion_##name##_lock( FusionEntries *entries, \
1144 + Type **ret_##name ) \
1147 + FusionEntry *entry; \
1149 + ret = fusion_entry_lock( entries, id, keep, &entry ); \
1152 + *ret_##name = (Type *) entry; \
1157 + static inline void fusion_##name##_unlock( Type *name ) \
1159 + fusion_entry_unlock( (FusionEntry*) name ); \
1162 + static inline int fusion_##name##_wait( Type *name, long *timeout ) \
1164 + return fusion_entry_wait( (FusionEntry*) name, timeout ); \
1167 + static inline void fusion_##name##_notify( Type *name, bool all ) \
1169 + fusion_entry_notify( (FusionEntry*) name, all ); \
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
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.
1192 +#include <linux/types.h>
1197 +fusion_fifo_put (FusionFifo *fifo, FusionLink *link)
1199 + link->prev = fifo->last;
1200 + link->next = NULL;
1203 + fifo->last->next = link;
1205 + fifo->first = link;
1207 + fifo->last = link;
1213 +fusion_fifo_get (FusionFifo *fifo)
1215 + FusionLink *first = fifo->first;
1220 + fifo->first = first->next;
1222 + if (fifo->last == first)
1223 + fifo->last = NULL;
1225 + fifo->first->prev = NULL;
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
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.
1249 +#ifndef __FUSION__FIFO_H__
1250 +#define __FUSION__FIFO_H__
1256 + FusionLink *first;
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
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.
1289 +#include <linux/version.h>
1290 +#include <linux/module.h>
1291 +#ifdef HAVE_LINUX_CONFIG_H
1292 +#include <linux/config.h>
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>
1301 +#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 19)
1302 +#include <linux/page-flags.h>
1303 +#include <linux/mm.h>
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>
1316 +#include <linux/fusion.h>
1319 +#include "fusiondev.h"
1320 +#include "fusionee.h"
1321 +#include "property.h"
1322 +#include "reactor.h"
1324 +#include "skirmish.h"
1325 +#include "shmpool.h"
1328 +#define DEBUG(x...) printk (KERN_DEBUG "Fusion: " x)
1330 +#define DEBUG(x...) do {} while (0)
1333 +#ifndef FUSION_MAJOR
1334 +#define FUSION_MAJOR 252
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);
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;
1359 +static struct class_simple *fusion_class;
1363 +/******************************************************************************/
1365 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
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 );
1376 + *timeout = schedule_timeout(*timeout);
1380 + finish_wait( q, &wait );
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);
1399 + *timeout = schedule_timeout(*timeout);
1403 + write_lock (&q->lock);
1404 + __remove_wait_queue (q, &wait);
1405 + write_unlock (&q->lock);
1409 +/******************************************************************************/
1412 +fusiondev_stat_read_proc(char *buf, char **start, off_t offset,
1413 + int len, int *eof, void *private)
1415 + FusionDev *dev = private;
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;
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,
1434 + dev->stat.ref_down,
1435 + dev->stat.skirmish_prevail_swoop,
1436 + dev->stat.skirmish_dismiss );
1437 + if (written < offset) {
1438 + offset -= written;
1443 + *start = buf + offset;
1444 + written -= offset;
1445 + if (written > len) {
1451 + return(written<0) ? 0 : written;
1454 +/******************************************************************************/
1457 +fusiondev_init (FusionDev *dev)
1461 + init_MUTEX( &dev->enter_lock );
1462 + init_waitqueue_head( &dev->enter_wait );
1464 + ret = fusionee_init (dev);
1466 + goto error_fusionee;
1468 + ret = fusion_ref_init (dev);
1472 + ret = fusion_skirmish_init (dev);
1474 + goto error_skirmish;
1476 + ret = fusion_property_init (dev);
1478 + goto error_property;
1480 + ret = fusion_reactor_init (dev);
1482 + goto error_reactor;
1484 + ret = fusion_shmpool_init (dev);
1486 + goto error_shmpool;
1488 + ret = fusion_call_init (dev);
1492 + create_proc_read_entry( "stat", 0, dev->proc_dir,
1493 + fusiondev_stat_read_proc, dev );
1499 + fusion_shmpool_deinit (dev);
1502 + fusion_reactor_deinit (dev);
1505 + fusion_property_deinit (dev);
1508 + fusion_skirmish_deinit (dev);
1511 + fusion_ref_deinit (dev);
1514 + fusionee_deinit (dev);
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 +/******************************************************************************/
1542 +fusion_open (struct inode *inode, struct file *file)
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))
1553 + if (!fusion_devs[minor]) {
1556 + fusion_devs[minor] = kmalloc (sizeof(FusionDev), GFP_KERNEL);
1557 + if (!fusion_devs[minor]) {
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]);
1571 + remove_proc_entry (buf, proc_fusion_dir);
1573 + kfree (fusion_devs[minor]);
1574 + fusion_devs[minor] = NULL;
1581 + else if (file->f_flags & O_EXCL) {
1582 + if (fusion_devs[minor]->fusionee.last_id) {
1588 + ret = fusionee_new (fusion_devs[minor], !!(file->f_flags & O_APPEND), &fusionee);
1590 + if (!fusion_devs[minor]->refs) {
1591 + fusiondev_deinit (fusion_devs[minor]);
1593 + remove_proc_entry (fusion_devs[minor]->proc_dir->name,
1596 + kfree (fusion_devs[minor]);
1597 + fusion_devs[minor] = NULL;
1605 + fusion_devs[minor]->refs++;
1610 + file->private_data = fusionee;
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,
1633 + kfree (fusion_devs[minor]);
1634 + fusion_devs[minor] = NULL;
1643 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18)
1644 +fusion_flush (struct file *file, fl_owner_t id)
1646 +fusion_flush (struct file *file)
1649 + Fusionee *fusionee = file->private_data;
1650 + FusionDev *dev = fusion_devs[iminor(file->f_dentry->d_inode)];
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);
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);
1686 +lounge_ioctl (struct file *file, FusionDev *dev, Fusionee *fusionee,
1687 + unsigned int cmd, unsigned long arg)
1690 + FusionEnter enter;
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)))
1700 + ret = fusionee_enter( dev, &enter, fusionee );
1704 + if (copy_to_user ((FusionEnter*) arg, &enter, sizeof(enter)))
1709 + case _IOC_NR(FUSION_UNBLOCK):
1710 + if (fusionee_id( fusionee ) != FUSION_ID_MASTER)
1713 + if (down_interruptible( &dev->enter_lock ))
1716 + dev->enter_ok = 1;
1718 + wake_up_interruptible_all( &dev->enter_wait );
1720 + up( &dev->enter_lock );
1724 + case _IOC_NR(FUSION_KILL):
1725 + if (copy_from_user (&kill, (FusionKill*) arg, sizeof(kill)))
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)))
1735 + switch (info.type) {
1737 + return fusion_entry_set_info (&dev->skirmish, &info);
1740 + return fusion_entry_set_info (&dev->properties, &info);
1743 + return fusion_entry_set_info (&dev->reactor, &info);
1746 + return fusion_entry_set_info (&dev->ref, &info);
1749 + return fusion_entry_set_info (&dev->shmpool, &info);
1755 + case _IOC_NR(FUSION_ENTRY_GET_INFO):
1756 + if (copy_from_user (&info, (FusionEntryInfo*) arg, sizeof(info)))
1759 + switch (info.type) {
1761 + ret = fusion_entry_get_info (&dev->skirmish, &info);
1765 + ret = fusion_entry_get_info (&dev->properties, &info);
1769 + ret = fusion_entry_get_info (&dev->reactor, &info);
1773 + ret = fusion_entry_get_info (&dev->ref, &info);
1777 + ret = fusion_entry_get_info (&dev->shmpool, &info);
1787 + if (copy_to_user ((FusionEntryInfo*) arg, &info, sizeof(info)))
1792 + case _IOC_NR(FUSION_FORK):
1793 + if (copy_from_user( &fork, (FusionFork*) arg, sizeof(fork) ))
1796 + ret = fusionee_fork( dev, &fork, fusionee );
1800 + if (copy_to_user( (FusionFork*) arg, &fork, sizeof(fork) ))
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)))
1820 + if (send.msg_size <= 0)
1823 + /* message data > 64k should be stored in shared memory */
1824 + if (send.msg_size > 0x10000)
1827 + return fusionee_send_message (dev, fusionee, send.fusion_id, FMT_SEND,
1828 + send.msg_id, send.msg_size, send.msg_data);
1835 +call_ioctl (FusionDev *dev, Fusionee *fusionee,
1836 + unsigned int cmd, unsigned long arg)
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)))
1850 + ret = fusion_call_new (dev, fusion_id, &call);
1854 + if (put_user (call.call_id, (int*) arg)) {
1855 + fusion_call_destroy (dev, fusion_id, call.call_id);
1860 + case _IOC_NR(FUSION_CALL_EXECUTE):
1861 + if (copy_from_user (&execute, (FusionCallExecute*) arg, sizeof(execute)))
1864 + ret = fusion_call_execute (dev, fusionee, &execute);
1868 + if (put_user (execute.ret_val, (int*) arg))
1872 + case _IOC_NR(FUSION_CALL_RETURN):
1873 + if (copy_from_user (&call_ret, (FusionCallReturn*) arg, sizeof(call_ret)))
1876 + return fusion_call_return (dev, fusion_id, &call_ret);
1878 + case _IOC_NR(FUSION_CALL_DESTROY):
1879 + if (get_user (id, (int*) arg))
1882 + return fusion_call_destroy (dev, fusion_id, id);
1889 +ref_ioctl (FusionDev *dev, Fusionee *fusionee,
1890 + unsigned int cmd, unsigned long arg)
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);
1905 + if (put_user (id, (int*) arg)) {
1906 + fusion_ref_destroy (dev, id);
1911 + case _IOC_NR(FUSION_REF_UP):
1912 + if (get_user (id, (int*) arg))
1915 + return fusion_ref_up (dev, id, fusion_id);
1917 + case _IOC_NR(FUSION_REF_UP_GLOBAL):
1918 + if (get_user (id, (int*) arg))
1921 + return fusion_ref_up (dev, id, 0);
1923 + case _IOC_NR(FUSION_REF_DOWN):
1924 + if (get_user (id, (int*) arg))
1927 + return fusion_ref_down (dev, id, fusion_id);
1929 + case _IOC_NR(FUSION_REF_DOWN_GLOBAL):
1930 + if (get_user (id, (int*) arg))
1933 + return fusion_ref_down (dev, id, 0);
1935 + case _IOC_NR(FUSION_REF_ZERO_LOCK):
1936 + if (get_user (id, (int*) arg))
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))
1945 + return fusion_ref_zero_trylock (dev, id, fusion_id);
1947 + case _IOC_NR(FUSION_REF_UNLOCK):
1948 + if (get_user (id, (int*) arg))
1951 + return fusion_ref_zero_unlock (dev, id, fusion_id);
1953 + case _IOC_NR(FUSION_REF_STAT):
1954 + if (get_user (id, (int*) arg))
1957 + ret = fusion_ref_stat (dev, id, &refs);
1963 + case _IOC_NR(FUSION_REF_WATCH):
1964 + if (copy_from_user (&watch, (FusionRefWatch*) arg, sizeof(watch)))
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)))
1973 + return fusion_ref_inherit (dev, inherit.id, inherit.from);
1975 + case _IOC_NR(FUSION_REF_DESTROY):
1976 + if (get_user (id, (int*) arg))
1979 + return fusion_ref_destroy (dev, id);
1986 +skirmish_ioctl (FusionDev *dev, Fusionee *fusionee,
1987 + unsigned int cmd, unsigned long arg)
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);
2000 + if (put_user (id, (int*) arg)) {
2001 + fusion_skirmish_destroy (dev, id);
2006 + case _IOC_NR(FUSION_SKIRMISH_PREVAIL):
2007 + if (get_user (id, (int*) arg))
2010 + return fusion_skirmish_prevail (dev, id, fusion_id);
2012 + case _IOC_NR(FUSION_SKIRMISH_SWOOP):
2013 + if (get_user (id, (int*) arg))
2016 + return fusion_skirmish_swoop (dev, id, fusion_id);
2018 + case _IOC_NR(FUSION_SKIRMISH_DISMISS):
2019 + if (get_user (id, (int*) arg))
2022 + return fusion_skirmish_dismiss (dev, id, fusion_id);
2024 + case _IOC_NR(FUSION_SKIRMISH_DESTROY):
2025 + if (get_user (id, (int*) arg))
2028 + return fusion_skirmish_destroy (dev, id);
2030 + case _IOC_NR(FUSION_SKIRMISH_LOCK_COUNT):
2031 + if (get_user (id, (int*) arg))
2034 + ret = fusion_skirmish_lock_count (dev, id, fusion_id, &lock_count);
2035 + if (put_user(lock_count, ((int*)arg)+1))
2045 +property_ioctl (FusionDev *dev, Fusionee *fusionee,
2046 + unsigned int cmd, unsigned long arg)
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);
2058 + if (put_user (id, (int*) arg)) {
2059 + fusion_property_destroy (dev, id);
2064 + case _IOC_NR(FUSION_PROPERTY_LEASE):
2065 + if (get_user (id, (int*) arg))
2068 + return fusion_property_lease (dev, id, fusion_id);
2070 + case _IOC_NR(FUSION_PROPERTY_PURCHASE):
2071 + if (get_user (id, (int*) arg))
2074 + return fusion_property_purchase (dev, id, fusion_id);
2076 + case _IOC_NR(FUSION_PROPERTY_CEDE):
2077 + if (get_user (id, (int*) arg))
2080 + return fusion_property_cede (dev, id, fusion_id);
2082 + case _IOC_NR(FUSION_PROPERTY_HOLDUP):
2083 + if (get_user (id, (int*) arg))
2086 + return fusion_property_holdup (dev, id, fusionee);
2088 + case _IOC_NR(FUSION_PROPERTY_DESTROY):
2089 + if (get_user (id, (int*) arg))
2092 + return fusion_property_destroy (dev, id);
2099 +reactor_ioctl (FusionDev *dev, Fusionee *fusionee,
2100 + unsigned int cmd, unsigned long arg)
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);
2113 + if (put_user (id, (int*) arg)) {
2114 + fusion_reactor_destroy (dev, id);
2119 + case _IOC_NR(FUSION_REACTOR_ATTACH):
2120 + if (get_user (id, (int*) arg))
2123 + return fusion_reactor_attach (dev, id, fusion_id);
2125 + case _IOC_NR(FUSION_REACTOR_DETACH):
2126 + if (get_user (id, (int*) arg))
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)))
2136 + if (dispatch.msg_size <= 0)
2139 + /* message data > 64k should be stored in shared memory */
2140 + if (dispatch.msg_size > 0x10000)
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))
2151 + return fusion_reactor_destroy (dev, id);
2158 +shmpool_ioctl (FusionDev *dev, Fusionee *fusionee,
2159 + unsigned int cmd, unsigned long arg)
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)))
2173 + ret = fusion_shmpool_new (dev, &pool);
2177 + if (copy_to_user ((FusionSHMPoolNew*) arg, &pool, sizeof(pool))) {
2178 + fusion_shmpool_destroy (dev, pool.pool_id);
2184 + case _IOC_NR(FUSION_SHMPOOL_ATTACH):
2185 + if (copy_from_user (&attach,
2186 + (FusionSHMPoolAttach*) arg, sizeof(attach)))
2189 + ret = fusion_shmpool_attach (dev, &attach, fusion_id);
2193 + if (copy_to_user ((FusionSHMPoolAttach*) arg, &attach, sizeof(attach))) {
2194 + fusion_shmpool_detach (dev, attach.pool_id, fusion_id);
2200 + case _IOC_NR(FUSION_SHMPOOL_DETACH):
2201 + if (get_user (id, (int*) arg))
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)))
2211 + return fusion_shmpool_dispatch (dev, &dispatch, fusionee);
2213 + case _IOC_NR(FUSION_SHMPOOL_DESTROY):
2214 + if (get_user (id, (int*) arg))
2217 + return fusion_shmpool_destroy (dev, id);
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)) {
2234 + return lounge_ioctl( file, dev, fusionee, cmd, arg );
2236 + case FT_MESSAGING:
2237 + return messaging_ioctl( dev, fusionee, cmd, arg );
2240 + return call_ioctl( dev, fusionee, cmd, arg );
2243 + return ref_ioctl( dev, fusionee, cmd, arg );
2246 + return skirmish_ioctl( dev, fusionee, cmd, arg );
2249 + return property_ioctl( dev, fusionee, cmd, arg );
2252 + return reactor_ioctl( dev, fusionee, cmd, arg );
2255 + return shmpool_ioctl( dev, fusionee, cmd, arg );
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)
2272 + size = vma->vm_end - vma->vm_start;
2273 + if (!size || size > PAGE_SIZE)
2276 + if (!dev->shared_area) {
2277 + if (fusionee_id( fusionee ) != FUSION_ID_MASTER)
2280 + dev->shared_area = get_zeroed_page( GFP_KERNEL );
2281 + if (!dev->shared_area)
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 );
2292 + return io_remap_page_range( vma->vm_start,
2293 + virt_to_phys((void*)dev->shared_area),
2294 + PAGE_SIZE, vma->vm_page_prot );
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)
2313 +register_devices(void)
2317 + if (register_chrdev (FUSION_MAJOR, "fusion", &fusion_fops)) {
2318 + printk (KERN_ERR "fusion: unable to get major %d\n", FUSION_MAJOR);
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");
2326 + fusion_class = class_simple_create (THIS_MODULE, "fusion");
2328 + if (IS_ERR(fusion_class)) {
2329 + unregister_chrdev (FUSION_MAJOR, "fusion");
2330 + return PTR_ERR(fusion_class);
2334 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18)
2335 + devfs_mk_dir("fusion");
2338 + for (i=0; i<NUM_MINORS; i++) {
2339 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 15)
2340 + class_device_create (fusion_class,
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);
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,
2365 +register_devices(void)
2370 + if (devfs_register_chrdev (FUSION_MAJOR, "fusion", &fusion_fops)) {
2371 + printk (KERN_ERR "fusion: unable to get major %d\n", FUSION_MAJOR);
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,
2380 + S_IFCHR | S_IRUSR | S_IWUSR,
2381 + &fusion_fops, NULL);
2393 + ret = register_devices();
2397 + proc_fusion_dir = proc_mkdir ("fusion", NULL);
2402 +/******************************************************************************/
2404 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
2406 +deregister_devices(void)
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));
2417 + class_simple_device_remove (MKDEV(FUSION_MAJOR, i));
2421 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18)
2422 + devfs_remove ("fusion/%d", i);
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);
2430 + class_simple_destroy (fusion_class);
2434 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18)
2435 + devfs_remove ("fusion");
2440 +deregister_devices(void)
2444 + devfs_unregister_chrdev (FUSION_MAJOR, "fusion");
2446 + for (i=0; i<NUM_MINORS; i++)
2447 + devfs_unregister (devfs_handles[i]);
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
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.
2480 +#ifndef __FUSIONDEV_H__
2481 +#define __FUSIONDEV_H__
2483 +#include <linux/proc_fs.h>
2485 +#include "entries.h"
2488 +#define FUSION_ASSERT(exp) if (!(exp)) BUG()
2489 +#define FUSION_ASSUME(exp) if (!(exp)) printk( KERN_ERR "fusiondev: assumption '" #exp "' failed!\n" )
2495 + struct semaphore enter_lock;
2497 + wait_queue_head_t enter_wait;
2499 + unsigned long shared_area;
2501 + struct proc_dir_entry *proc_dir;
2504 + int property_lease_purchase;
2505 + int property_cede;
2507 + int reactor_attach;
2508 + int reactor_detach;
2513 + int skirmish_prevail_swoop;
2514 + int skirmish_dismiss;
2516 + int shmpool_attach;
2517 + int shmpool_detach;
2523 + struct semaphore lock;
2529 + struct semaphore lock;
2530 + wait_queue_head_t wait;
2533 + FusionEntries properties;
2534 + FusionEntries reactor;
2535 + FusionEntries ref;
2536 + FusionEntries shmpool;
2537 + FusionEntries skirmish;
2541 + * Special version of interruptible_sleep_on() that unlocks the mutex
2542 + * after adding the entry to the queue (just before schedule).
2544 +void fusion_sleep_on (wait_queue_head_t *q,
2545 + struct semaphore *lock,
2546 + signed long *timeout_ms);
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
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.
2567 +#ifdef HAVE_LINUX_CONFIG_H
2568 +#include <linux/config.h>
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>
2581 +#include "fusiondev.h"
2582 +#include "fusionee.h"
2583 +#include "property.h"
2584 +#include "reactor.h"
2586 +#include "skirmish.h"
2587 +#include "shmpool.h"
2590 +#define DEBUG(x...) printk (KERN_DEBUG "Fusion: " x)
2592 +#define DEBUG(x...) do {} while (0)
2595 +struct __Fusion_Fusionee {
2598 + struct semaphore lock;
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;
2616 + FusionMessageType type;
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 +/******************************************************************************/
2631 +fusionees_read_proc(char *buf, char **start, off_t offset,
2632 + int len, int *eof, void *private)
2635 + FusionDev *dev = private;
2638 + if (down_interruptible (&dev->fusionee.lock))
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;
2651 + if (written >= len)
2655 + up (&dev->fusionee.lock);
2657 + *start = buf + offset;
2658 + written -= offset;
2659 + if (written > len) {
2665 + return(written<0) ? 0 : written;
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);
2682 +fusionee_deinit (FusionDev *dev)
2686 + down (&dev->fusionee.lock);
2688 + remove_proc_entry ("fusionees", dev->proc_dir);
2690 + l = dev->fusionee.list;
2692 + FusionLink *next = l->next;
2693 + Fusionee *fusionee = (Fusionee *) l;
2695 + while (fusionee->messages.count) {
2696 + Message *message = (Message*) fusion_fifo_get (&fusionee->messages);
2706 + up (&dev->fusionee.lock);
2709 +/******************************************************************************/
2712 +fusionee_new( FusionDev *dev,
2714 + Fusionee **ret_fusionee )
2716 + Fusionee *fusionee;
2718 + fusionee = kmalloc (sizeof(Fusionee), GFP_KERNEL);
2722 + memset (fusionee, 0, sizeof(Fusionee));
2724 + if (down_interruptible (&dev->fusionee.lock)) {
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;
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 ))
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))
2763 + if (down_interruptible( &dev->enter_lock ))
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;
2780 +fusionee_fork( FusionDev *dev,
2782 + Fusionee *fusionee )
2786 + ret = fusion_shmpool_fork_all( dev, fusionee->id, fork->fusion_id );
2790 + ret = fusion_reactor_fork_all( dev, fusionee->id, fork->fusion_id );
2794 + ret = fusion_ref_fork_all_local( dev, fusionee->id, fork->fusion_id );
2798 + fork->fusion_id = fusionee->id;
2804 +fusionee_send_message (FusionDev *dev,
2806 + FusionID recipient,
2807 + FusionMessageType msg_type,
2810 + const void *msg_data)
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);
2823 + if (down_interruptible (&fusionee->lock)) {
2824 + up (&dev->fusionee.lock);
2828 + if (sender && sender != fusionee) {
2829 + if (down_interruptible (&sender->lock)) {
2830 + unlock_fusionee (fusionee);
2831 + up (&dev->fusionee.lock);
2836 + up (&dev->fusionee.lock);
2839 + message = kmalloc (sizeof(Message) + msg_size, GFP_KERNEL);
2841 + if (sender && sender != fusionee)
2842 + unlock_fusionee (sender);
2843 + unlock_fusionee (fusionee);
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)) {
2853 + if (sender && sender != fusionee)
2854 + unlock_fusionee (sender);
2855 + unlock_fusionee (fusionee);
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++;
2867 + sender->snd_total++;
2869 + wake_up_interruptible_all (&fusionee->wait);
2871 + if (sender && sender != fusionee)
2872 + unlock_fusionee (sender);
2874 + unlock_fusionee (fusionee);
2880 +fusionee_get_messages (FusionDev *dev,
2881 + Fusionee *fusionee,
2888 + if (down_interruptible (&fusionee->lock))
2891 + while (!fusionee->messages.count) {
2893 + unlock_fusionee (fusionee);
2897 + fusion_sleep_on (&fusionee->wait, &fusionee->lock, 0);
2899 + if (signal_pending(current))
2902 + if (down_interruptible (&fusionee->lock))
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) {
2913 + unlock_fusionee (fusionee);
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);
2932 + buf_size -= bytes;
2934 + fusion_fifo_get (&fusionee->messages);
2939 + unlock_fusionee (fusionee);
2945 +fusionee_poll (FusionDev *dev,
2946 + Fusionee *fusionee,
2947 + struct file *file,
2951 + FusionID id = fusionee->id;
2953 + poll_wait (file, &fusionee->wait, wait);
2956 + ret = lock_fusionee (dev, id, &fusionee);
2960 + if (fusionee->messages.count) {
2961 + unlock_fusionee (fusionee);
2963 + return POLLIN | POLLRDNORM;
2966 + unlock_fusionee (fusionee);
2972 +fusionee_kill (FusionDev *dev,
2973 + Fusionee *fusionee,
2978 + long timeout = -1;
2984 + if (down_interruptible (&dev->fusionee.lock))
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);
2996 + if (!killed || timeout_ms < 0) {
2997 + up (&dev->fusionee.lock);
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;
3012 + /* fall through */
3015 + fusion_sleep_on (&dev->fusionee.wait,
3016 + &dev->fusionee.lock, &timeout);
3021 + fusion_sleep_on (&dev->fusionee.wait, &dev->fusionee.lock, NULL);
3023 + if (signal_pending(current))
3031 +fusionee_destroy (FusionDev *dev,
3032 + Fusionee *fusionee)
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);
3065 + /* Unlock fusionee. */
3066 + up (&fusionee->lock);
3069 + /* Free fusionee data. */
3074 +fusionee_id( const Fusionee *fusionee )
3076 + return fusionee->id;
3079 +/******************************************************************************/
3082 +lookup_fusionee (FusionDev *dev,
3084 + Fusionee **ret_fusionee)
3088 + if (down_interruptible (&dev->fusionee.lock))
3091 + fusion_list_foreach (l, dev->fusionee.list) {
3092 + Fusionee *fusionee = (Fusionee *) l;
3094 + if (fusionee->id == id) {
3095 + *ret_fusionee = fusionee;
3100 + up (&dev->fusionee.lock);
3106 +lock_fusionee (FusionDev *dev,
3108 + Fusionee **ret_fusionee)
3111 + Fusionee *fusionee;
3113 + ret = lookup_fusionee (dev, id, &fusionee);
3117 + fusion_list_move_to_front (&dev->fusionee.list, &fusionee->link);
3119 + if (down_interruptible (&fusionee->lock)) {
3120 + up (&dev->fusionee.lock);
3124 + up (&dev->fusionee.lock);
3126 + *ret_fusionee = fusionee;
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
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.
3155 +#ifndef __FUSIONEE_H__
3156 +#define __FUSIONEE_H__
3158 +#include <linux/poll.h>
3159 +#include <linux/fusion.h>
3161 +#include "fusiondev.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,
3174 + Fusionee **ret_fusionee);
3176 +int fusionee_enter (FusionDev *dev,
3177 + FusionEnter *enter,
3178 + Fusionee *fusionee);
3180 +int fusionee_fork (FusionDev *dev,
3182 + Fusionee *fusionee);
3184 +int fusionee_send_message (FusionDev *dev,
3185 + Fusionee *fusionee,
3186 + FusionID recipient,
3187 + FusionMessageType msg_type,
3190 + const void *msg_data);
3192 +int fusionee_get_messages (FusionDev *dev,
3193 + Fusionee *fusionee,
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,
3210 +void fusionee_destroy (FusionDev *dev,
3211 + Fusionee *fusionee);
3213 +FusionID fusionee_id( const Fusionee *fusionee );
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
3220 +config FUSION_DEVICE
3221 + tristate "Fusion device for DirectFB"
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
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.
3246 +#include <linux/types.h>
3251 +fusion_list_prepend (FusionLink **list, FusionLink *link)
3253 + link->prev = NULL;
3254 + link->next = *list;
3257 + (*list)->prev = link;
3263 +fusion_list_remove (FusionLink **list, FusionLink *link)
3266 + link->prev->next = link->next;
3268 + *list = link->next;
3271 + link->next->prev = link->prev;
3273 + link->next = link->prev = NULL;
3277 +fusion_list_move_to_front (FusionLink **list, FusionLink *link)
3279 + if (*list == link)
3282 + link->prev->next = link->next;
3285 + link->next->prev = link->prev;
3287 + link->prev = NULL;
3288 + link->next = *list;
3290 + (*list)->prev = 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
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.
3312 +#ifndef __FUSION__LIST_H__
3313 +#define __FUSION__LIST_H__
3315 +typedef struct _FusionLink {
3316 + struct _FusionLink *next;
3317 + struct _FusionLink *prev;
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); \
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); \
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
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
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.
3362 +#ifdef HAVE_LINUX_CONFIG_H
3363 +#include <linux/config.h>
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>
3372 +#define yield schedule
3375 +#include <linux/fusion.h>
3377 +#include "entries.h"
3378 +#include "fusiondev.h"
3379 +#include "fusionee.h"
3381 +#include "property.h"
3384 + FUSION_PROPERTY_AVAILABLE = 0,
3385 + FUSION_PROPERTY_LEASED,
3386 + FUSION_PROPERTY_PURCHASED
3387 +} FusionPropertyState;
3390 + FusionEntry entry;
3392 + FusionPropertyState state;
3393 + int fusion_id; /* non-zero if leased/purchased */
3394 + unsigned long purchase_stamp;
3396 + int count; /* lock counter */
3400 +fusion_property_print( FusionEntry *entry,
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 +/******************************************************************************/
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 );
3431 +fusion_property_deinit( FusionDev *dev )
3433 + remove_proc_entry( "properties", dev->proc_dir );
3435 + fusion_entries_deinit( &dev->properties );
3438 +/******************************************************************************/
3441 +fusion_property_new( FusionDev *dev, int *ret_id )
3443 + return fusion_entry_create( &dev->properties, ret_id, NULL );
3447 +fusion_property_lease( FusionDev *dev, int id, int fusion_id )
3450 + FusionProperty *property;
3451 + long timeout = -1;
3453 + dev->stat.property_lease_purchase++;
3455 + ret = fusion_property_lock( &dev->properties, id, false, &property );
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 );
3470 + case FUSION_PROPERTY_LEASED:
3471 + if (property->lock_pid == current->pid) {
3472 + property->count++;
3474 + fusion_property_unlock( property );
3478 + ret = fusion_property_wait( property, NULL );
3484 + case FUSION_PROPERTY_PURCHASED:
3485 + if (property->lock_pid == current->pid) {
3486 + fusion_property_unlock( property );
3490 + if (timeout == -1) {
3491 + if (jiffies - property->purchase_stamp > HZ / 10) {
3492 + fusion_property_unlock( property );
3496 + timeout = HZ / 10;
3499 + ret = fusion_property_wait( property, &timeout );
3512 + /* won't reach this */
3517 +fusion_property_purchase( FusionDev *dev, int id, int fusion_id )
3520 + FusionProperty *property;
3521 + signed long timeout = -1;
3523 + dev->stat.property_lease_purchase++;
3525 + ret = fusion_property_lock( &dev->properties, id, false, &property );
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 );
3543 + case FUSION_PROPERTY_LEASED:
3544 + if (property->lock_pid == current->pid) {
3545 + fusion_property_unlock( property );
3549 + ret = fusion_property_wait( property, NULL );
3555 + case FUSION_PROPERTY_PURCHASED:
3556 + if (property->lock_pid == current->pid) {
3557 + property->count++;
3559 + fusion_property_unlock( property );
3563 + if (timeout == -1) {
3564 + if (jiffies - property->purchase_stamp > HZ) {
3565 + fusion_property_unlock( property );
3572 + ret = fusion_property_wait( property, &timeout );
3585 + /* won't reach this */
3590 +fusion_property_cede( FusionDev *dev, int id, int fusion_id )
3593 + FusionProperty *property;
3596 + dev->stat.property_cede++;
3598 + ret = fusion_property_lock( &dev->properties, id, false, &property );
3602 + if (property->lock_pid != current->pid) {
3603 + fusion_property_unlock( property );
3607 + if (--property->count) {
3608 + fusion_property_unlock( property );
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 );
3629 +fusion_property_holdup( FusionDev *dev, int id, Fusionee *fusionee )
3632 + FusionProperty *property;
3633 + FusionID fusion_id = fusionee_id( fusionee );
3635 + if (fusion_id > 1)
3638 + ret = fusion_property_lock( &dev->properties, id, false, &property );
3642 + if (property->state == FUSION_PROPERTY_PURCHASED) {
3643 + if (property->fusion_id == fusion_id) {
3644 + fusion_property_unlock( property );
3648 + fusionee_kill( dev, fusionee, property->fusion_id, SIGKILL, -1 );
3651 + fusion_property_unlock( property );
3657 +fusion_property_destroy( FusionDev *dev, int id )
3659 + return fusion_entry_destroy( &dev->properties, id );
3663 +fusion_property_cede_all( FusionDev *dev, int fusion_id )
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
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.
3706 +#ifndef __FUSION__PROPERTY_H__
3707 +#define __FUSION__PROPERTY_H__
3709 +#include "fusiondev.h"
3713 +/* module init/cleanup */
3715 +int fusion_property_init (FusionDev *dev);
3716 +void fusion_property_deinit (FusionDev *dev);
3721 +int fusion_property_new (FusionDev *dev,
3724 +int fusion_property_lease (FusionDev *dev,
3728 +int fusion_property_purchase (FusionDev *dev,
3732 +int fusion_property_cede (FusionDev *dev,
3736 +int fusion_property_holdup (FusionDev *dev,
3738 + Fusionee *fusionee);
3740 +int fusion_property_destroy (FusionDev *dev,
3744 +/* internal functions */
3746 +void fusion_property_cede_all (FusionDev *dev,
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
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.
3768 +#ifdef HAVE_LINUX_CONFIG_H
3769 +#include <linux/config.h>
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"
3782 +#include "reactor.h"
3789 + int count; /* number of attach calls */
3793 + FusionEntry entry;
3795 + FusionLink *nodes;
3797 + int dispatch_count;
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)
3826 +/******************************************************************************/
3829 +fusion_reactor_destruct( FusionEntry *entry,
3832 + FusionReactor *reactor = (FusionReactor*) entry;
3834 + free_all_nodes( reactor );
3838 +fusion_reactor_print( FusionEntry *entry,
3843 + FusionReactor *reactor = (FusionReactor*) entry;
3844 + FusionLink *node = reactor->nodes;
3846 + fusion_list_foreach (node, reactor->nodes) {
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 +/******************************************************************************/
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 );
3872 +fusion_reactor_deinit (FusionDev *dev)
3874 + remove_proc_entry ("reactors", dev->proc_dir);
3876 + fusion_entries_deinit( &dev->reactor );
3879 +/******************************************************************************/
3882 +fusion_reactor_new (FusionDev *dev, int *ret_id)
3884 + return fusion_entry_create( &dev->reactor, ret_id, NULL );
3888 +fusion_reactor_attach (FusionDev *dev, int id, FusionID fusion_id)
3891 + ReactorNode *node;
3892 + FusionReactor *reactor;
3894 + ret = fusion_reactor_lock( &dev->reactor, id, false, &reactor );
3898 + if (reactor->destroyed) {
3899 + fusion_reactor_unlock( reactor );
3903 + dev->stat.reactor_attach++;
3905 + node = get_node (reactor, fusion_id);
3907 + node = kmalloc (sizeof(ReactorNode), GFP_KERNEL);
3909 + fusion_reactor_unlock( reactor );
3913 + node->fusion_id = fusion_id;
3916 + fusion_list_prepend (&reactor->nodes, &node->link);
3921 + fusion_reactor_unlock( reactor );
3927 +fusion_reactor_detach (FusionDev *dev, int id, FusionID fusion_id)
3930 + ReactorNode *node;
3931 + FusionReactor *reactor;
3933 + ret = fusion_reactor_lock( &dev->reactor, id, true, &reactor );
3937 + dev->stat.reactor_detach++;
3939 + node = get_node (reactor, fusion_id);
3941 + fusion_reactor_unlock( reactor );
3942 + up( &dev->reactor.lock );
3946 + if (! --node->count) {
3947 + fusion_list_remove (&reactor->nodes, &node->link);
3951 + if (reactor->destroyed && !reactor->nodes)
3952 + fusion_entry_destroy_locked( &dev->reactor, &reactor->entry );
3954 + fusion_reactor_unlock( reactor );
3956 + up( &dev->reactor.lock );
3962 +fusion_reactor_dispatch (FusionDev *dev, int id, Fusionee *fusionee,
3963 + int msg_size, const void *msg_data)
3967 + FusionReactor *reactor;
3968 + FusionID fusion_id = fusionee ? fusionee_id( fusionee ) : 0;
3970 + ret = fusion_reactor_lock( &dev->reactor, id, false, &reactor );
3974 + if (reactor->destroyed) {
3975 + fusion_reactor_unlock( reactor );
3979 + reactor->dispatch_count++;
3981 + fusion_list_foreach (l, reactor->nodes) {
3982 + ReactorNode *node = (ReactorNode *) l;
3984 + if (node->fusion_id == fusion_id)
3987 + fusionee_send_message (dev, fusionee, node->fusion_id, FMT_REACTOR,
3988 + reactor->entry.id, msg_size, msg_data);
3991 + fusion_reactor_unlock( reactor );
3997 +fusion_reactor_destroy (FusionDev *dev, int id)
4000 + FusionReactor *reactor;
4002 + ret = fusion_reactor_lock( &dev->reactor, id, true, &reactor );
4006 + if (reactor->destroyed) {
4007 + fusion_reactor_unlock( reactor );
4008 + up( &dev->reactor.lock );
4012 + reactor->destroyed = true;
4014 + if (!reactor->nodes)
4015 + fusion_entry_destroy_locked( &dev->reactor, &reactor->entry );
4017 + fusion_reactor_unlock( reactor );
4019 + up( &dev->reactor.lock );
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);
4045 + if (reactor->destroyed && !reactor->nodes)
4046 + fusion_entry_destroy_locked( &dev->reactor, &reactor->entry );
4048 + up (&reactor->entry.lock);
4051 + up (&dev->reactor.lock);
4055 +fusion_reactor_fork_all (FusionDev *dev, FusionID fusion_id, FusionID from_id)
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);
4070 + up (&dev->reactor.lock);
4075 +/******************************************************************************/
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);
4090 + up (&reactor->entry.lock);
4094 + new_node->fusion_id = fusion_id;
4095 + new_node->count = node->count;
4097 + fusion_list_prepend (&reactor->nodes, &new_node->link);
4103 + up (&reactor->entry.lock);
4109 +free_all_nodes (FusionReactor *reactor)
4113 + ReactorNode *node;
4115 + fusion_list_foreach_safe (node, n, reactor->nodes) {
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
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.
4139 +#ifndef __FUSION__REACTOR_H__
4140 +#define __FUSION__REACTOR_H__
4142 +#include "fusiondev.h"
4146 +/* module init/cleanup */
4148 +int fusion_reactor_init (FusionDev *dev);
4149 +void fusion_reactor_deinit (FusionDev *dev);
4154 +int fusion_reactor_new (FusionDev *dev,
4157 +int fusion_reactor_attach (FusionDev *dev,
4159 + FusionID fusion_id);
4161 +int fusion_reactor_detach (FusionDev *dev,
4163 + FusionID fusion_id);
4165 +int fusion_reactor_dispatch (FusionDev *dev,
4167 + Fusionee *fusionee,
4169 + const void *msg_data);
4171 +int fusion_reactor_destroy (FusionDev *dev,
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);
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
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.
4202 +#ifdef HAVE_LINUX_CONFIG_H
4203 +#include <linux/config.h>
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"
4218 +typedef struct __Fusion_FusionRef FusionRef;
4222 + FusionID fusion_id;
4231 +struct __Fusion_FusionRef {
4232 + FusionEntry entry;
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 +/**********************************************************************************************************************/
4267 +fusion_ref_destruct( FusionEntry *entry,
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 );
4282 +fusion_ref_print( FusionEntry *entry,
4286 + FusionRef *ref = (FusionRef*) entry;
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 +/**********************************************************************************************************************/
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 );
4310 +fusion_ref_deinit( FusionDev *dev )
4312 + remove_proc_entry( "refs", dev->proc_dir );
4314 + fusion_entries_deinit( &dev->ref );
4317 +/**********************************************************************************************************************/
4320 +fusion_ref_new( FusionDev *dev, int *ret_id )
4322 + return fusion_entry_create( &dev->ref, ret_id, NULL );
4326 +fusion_ref_up (FusionDev *dev, int id, FusionID fusion_id)
4331 + ret = fusion_ref_lock( &dev->ref, id, true, &ref );
4335 + dev->stat.ref_up++;
4337 + if (ref->locked) {
4343 + ret = add_local (ref, fusion_id, 1);
4347 + ret = propagate_local( dev, ref, 1 );
4354 + fusion_ref_unlock( ref );
4355 + up( &dev->ref.lock );
4361 +fusion_ref_down (FusionDev *dev, int id, FusionID fusion_id)
4366 + ret = fusion_ref_lock( &dev->ref, id, true, &ref );
4370 + dev->stat.ref_down++;
4372 + if (ref->locked) {
4382 + ret = add_local (ref, fusion_id, -1);
4386 + ret = propagate_local( dev, ref, -1 );
4389 + if (!ref->global) {
4396 + if (ref->local + ref->global == 0)
4397 + notify_ref (dev, ref);
4402 + fusion_ref_unlock( ref );
4403 + up( &dev->ref.lock );
4409 +fusion_ref_zero_lock (FusionDev *dev, int id, FusionID fusion_id)
4414 + ret = fusion_ref_lock( &dev->ref, id, false, &ref );
4419 + if (ref->watched) {
4420 + fusion_ref_unlock( ref );
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 );
4438 + ref->locked = fusion_id;
4440 + fusion_ref_unlock( ref );
4446 +fusion_ref_zero_trylock (FusionDev *dev, int id, FusionID fusion_id)
4451 + ret = fusion_ref_lock( &dev->ref, id, false, &ref );
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;
4463 + ref->locked = fusion_id;
4465 + fusion_ref_unlock( ref );
4471 +fusion_ref_zero_unlock (FusionDev *dev, int id, FusionID fusion_id)
4476 + ret = fusion_ref_lock( &dev->ref, id, false, &ref );
4480 + if (ref->locked != fusion_id) {
4481 + fusion_ref_unlock( ref );
4487 + fusion_ref_unlock( ref );
4493 +fusion_ref_stat (FusionDev *dev, int id, int *refs)
4498 + ret = fusion_ref_lock( &dev->ref, id, false, &ref );
4502 + *refs = ref->global + ref->local;
4504 + fusion_ref_unlock( ref );
4510 +fusion_ref_watch (FusionDev *dev,
4518 + ret = fusion_ref_lock( &dev->ref, id, false, &ref );
4522 + if (ref->entry.pid != current->pid) {
4523 + fusion_ref_unlock( ref );
4527 + if (ref->global + ref->local == 0) {
4528 + fusion_ref_unlock( ref );
4532 + if (ref->watched) {
4533 + fusion_ref_unlock( ref );
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 );
4549 +fusion_ref_inherit (FusionDev *dev,
4555 + FusionRef *from = NULL;
4557 + ret = fusion_ref_lock( &dev->ref, id, true, &ref );
4562 + if (ref->inherited)
4566 + fusion_list_foreach (from, dev->ref.list) {
4567 + if (from->entry.id == from_id) {
4568 + if (down_interruptible( &from->entry.lock )) {
4579 + ret = add_inheritor( ref, from );
4583 + ret = propagate_local( dev, ref, from->local );
4587 + ref->inherited = from;
4591 + up( &from->entry.lock );
4593 + fusion_ref_unlock( ref );
4594 + up ( &dev->ref.lock );
4600 +fusion_ref_destroy (FusionDev *dev, int id)
4602 + return fusion_entry_destroy( &dev->ref, id );
4606 +fusion_ref_clear_all_local( FusionDev *dev, FusionID fusion_id )
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 );
4619 +fusion_ref_fork_all_local( FusionDev *dev, FusionID fusion_id, FusionID from_id )
4624 + down( &dev->ref.lock );
4626 + fusion_list_foreach (ref, dev->ref.list) {
4627 + ret = fork_local( dev, ref, fusion_id, from_id );
4632 + up( &dev->ref.lock );
4637 +/**********************************************************************************************************************/
4640 +add_local (FusionRef *ref, FusionID fusion_id, int add)
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)
4654 + local->refs += add;
4659 + /* Can only create local node if value is positive. */
4663 + local = kmalloc (sizeof(LocalRef), GFP_KERNEL);
4667 + local->fusion_id = fusion_id;
4668 + local->refs = add;
4670 + fusion_list_prepend (&ref->local_refs, &local->link);
4676 +clear_local (FusionDev *dev, FusionRef *ref, FusionID fusion_id)
4680 + down (&ref->entry.lock);
4682 + if (ref->locked == fusion_id) {
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) {
4692 + propagate_local( dev, ref, - local->refs );
4694 + fusion_list_remove( &ref->local_refs, l );
4701 + up (&ref->entry.lock);
4705 +fork_local (FusionDev *dev, FusionRef *ref, FusionID fusion_id, FusionID from_id)
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);
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 );
4736 + up (&ref->entry.lock);
4742 +free_all_local (FusionRef *ref)
4744 + FusionLink *l = ref->local_refs;
4747 + FusionLink *next = l->next;
4754 + ref->local_refs = NULL;
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);
4770 + wake_up_interruptible_all (&ref->entry.wait);
4774 +propagate_local( FusionDev *dev, FusionRef *ref, int diff )
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" );
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 );
4803 +add_inheritor(FusionRef *ref, FusionRef *from)
4805 + Inheritor *inheritor;
4807 + inheritor = kmalloc (sizeof(Inheritor), GFP_KERNEL);
4811 + inheritor->ref = ref;
4813 + fusion_list_prepend( &from->inheritors, &inheritor->link );
4819 +remove_inheritor(FusionRef *ref, FusionRef *from)
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 );
4836 + up( &from->entry.lock );
4840 +drop_inheritors( FusionDev *dev, FusionRef *ref )
4842 + FusionLink *l = ref->inheritors;
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" );
4853 + propagate_local( dev, inheritor, - ref->local );
4855 + inheritor->inherited = NULL;
4857 + up( &inheritor->entry.lock );
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
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.
4886 +#ifndef __FUSION__REF_H__
4887 +#define __FUSION__REF_H__
4889 +#include "fusiondev.h"
4893 +/* module init/cleanup */
4895 +int fusion_ref_init (FusionDev *dev);
4896 +void fusion_ref_deinit (FusionDev *dev);
4901 +int fusion_ref_new (FusionDev *dev,
4904 +int fusion_ref_up (FusionDev *dev,
4906 + FusionID fusion_id);
4908 +int fusion_ref_down (FusionDev *dev,
4910 + FusionID fusion_id);
4912 +int fusion_ref_zero_lock (FusionDev *dev,
4914 + FusionID fusion_id);
4916 +int fusion_ref_zero_trylock (FusionDev *dev,
4918 + FusionID fusion_id);
4920 +int fusion_ref_zero_unlock (FusionDev *dev,
4922 + FusionID fusion_id);
4924 +int fusion_ref_stat (FusionDev *dev,
4928 +int fusion_ref_watch (FusionDev *dev,
4933 +int fusion_ref_inherit (FusionDev *dev,
4937 +int fusion_ref_destroy (FusionDev *dev,
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);
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
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.
4969 +#ifdef HAVE_LINUX_CONFIG_H
4970 +#include <linux/config.h>
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"
4983 +#include "shmpool.h"
4986 +#define SHM_BASE 0x20010000 /* virtual base address */
4987 +#define SHM_SIZE 0x1FFEF000 /* size of virtual address space */
4992 + unsigned long next_base;
4999 + FusionID fusion_id;
5001 + int count; /* number of attach calls */
5005 + FusionEntry entry;
5012 + AddrEntry *addr_entry;
5014 + FusionLink *nodes;
5016 + int dispatch_count;
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 +/******************************************************************************/
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 );
5054 +/******************************************************************************/
5057 +fusion_shmpool_construct( FusionEntry *entry,
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) {
5068 + printk( KERN_WARNING "%s: virtual address space exhausted! (FIXME)\n", __FUNCTION__ );
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 );
5085 +fusion_shmpool_destruct( FusionEntry *entry,
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 );
5100 + * free trailing address space
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;
5114 +fusion_shmpool_print( FusionEntry *entry,
5119 + FusionSHMPool *shmpool = (FusionSHMPool*) entry;
5120 + FusionLink *node = shmpool->nodes;
5122 + fusion_list_foreach (node, shmpool->nodes) {
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 +/******************************************************************************/
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 );
5149 +fusion_shmpool_deinit (FusionDev *dev)
5151 + remove_proc_entry ("shmpools", dev->proc_dir);
5153 + fusion_entries_deinit( &dev->shmpool );
5156 +/******************************************************************************/
5159 +fusion_shmpool_new (FusionDev *dev,
5160 + FusionSHMPoolNew *pool)
5162 + if (pool->max_size <= 0)
5165 + return fusion_entry_create( &dev->shmpool, &pool->pool_id, pool );
5169 +fusion_shmpool_attach (FusionDev *dev,
5170 + FusionSHMPoolAttach *attach,
5171 + FusionID fusion_id)
5174 + SHMPoolNode *node;
5175 + FusionSHMPool *shmpool;
5177 + ret = fusion_shmpool_lock( &dev->shmpool, attach->pool_id, false, &shmpool );
5181 + dev->stat.shmpool_attach++;
5183 + node = get_node (shmpool, fusion_id);
5185 + node = kmalloc (sizeof(SHMPoolNode), GFP_KERNEL);
5187 + fusion_shmpool_unlock( shmpool );
5191 + node->fusion_id = fusion_id;
5194 + fusion_list_prepend (&shmpool->nodes, &node->link);
5199 + attach->addr_base = shmpool->addr_base;
5200 + attach->size = shmpool->size;
5202 + fusion_shmpool_unlock( shmpool );
5208 +fusion_shmpool_detach (FusionDev *dev, int id, FusionID fusion_id)
5211 + SHMPoolNode *node;
5212 + FusionSHMPool *shmpool;
5214 + ret = fusion_shmpool_lock( &dev->shmpool, id, false, &shmpool );
5218 + dev->stat.shmpool_detach++;
5220 + node = get_node (shmpool, fusion_id);
5222 + fusion_shmpool_unlock( shmpool );
5226 + if (! --node->count) {
5227 + fusion_list_remove (&shmpool->nodes, &node->link);
5231 + fusion_shmpool_unlock( shmpool );
5237 +fusion_shmpool_dispatch( FusionDev *dev,
5238 + FusionSHMPoolDispatch *dispatch,
5239 + Fusionee *fusionee )
5243 + FusionSHMPool *shmpool;
5244 + FusionSHMPoolMessage message;
5245 + FusionID fusion_id = fusionee_id( fusionee );
5247 + if (dispatch->size <= 0)
5250 + ret = fusion_shmpool_lock( &dev->shmpool, dispatch->pool_id, false, &shmpool );
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)
5267 + fusionee_send_message (dev, fusionee, node->fusion_id, FMT_SHMPOOL,
5268 + shmpool->entry.id, sizeof(message), &message);
5271 + fusion_shmpool_unlock( shmpool );
5277 +fusion_shmpool_destroy (FusionDev *dev, int id)
5279 + return fusion_entry_destroy( &dev->shmpool, id );
5283 +fusion_shmpool_detach_all (FusionDev *dev, FusionID fusion_id)
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);
5299 +fusion_shmpool_fork_all( FusionDev *dev,
5300 + FusionID fusion_id,
5301 + FusionID from_id )
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 );
5316 + up (&dev->shmpool.lock);
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)
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);
5351 + up (&shmpool->entry.lock);
5355 +fork_node (FusionSHMPool *shmpool, FusionID fusion_id, FusionID from_id)
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);
5372 + new_node->fusion_id = fusion_id;
5373 + new_node->count = node->count;
5375 + fusion_list_prepend (&shmpool->nodes, &new_node->link);
5381 + up (&shmpool->entry.lock);
5387 +free_all_nodes (FusionSHMPool *shmpool)
5391 + SHMPoolNode *node;
5393 + fusion_list_foreach_safe (node, n, shmpool->nodes) {
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
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.
5417 +#ifndef __FUSION__SHMPOOL_H__
5418 +#define __FUSION__SHMPOOL_H__
5420 +#include "fusiondev.h"
5424 +/* module init/cleanup */
5426 +int fusion_shmpool_init (FusionDev *dev);
5427 +void fusion_shmpool_deinit (FusionDev *dev);
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,
5441 + FusionID fusion_id);
5443 +int fusion_shmpool_dispatch (FusionDev *dev,
5444 + FusionSHMPoolDispatch *dispatch,
5445 + Fusionee *fusionee );
5447 +int fusion_shmpool_destroy (FusionDev *dev,
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);
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
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.
5480 +#ifdef HAVE_LINUX_CONFIG_H
5481 +#include <linux/config.h>
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"
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 */
5511 +#ifdef FUSION_DEBUG_SKIRMISH_DEADLOCK
5512 + int pre_acquis[MAX_PRE_ACQUISITIONS];
5519 +fusion_skirmish_print( FusionEntry *entry,
5524 + FusionSkirmish *skirmish = (FusionSkirmish*) entry;
5526 +#ifdef FUSION_DEBUG_SKIRMISH_DEADLOCK
5530 + for (i=0, n=0; i<MAX_PRE_ACQUISITIONS; i++) {
5531 + if (skirmish->pre_acquis[i]) {
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 );
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;
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 +/******************************************************************************/
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 );
5577 +fusion_skirmish_deinit (FusionDev *dev)
5579 + remove_proc_entry ("skirmishs", dev->proc_dir);
5581 + fusion_entries_deinit( &dev->skirmish );
5584 +/******************************************************************************/
5587 +fusion_skirmish_new (FusionDev *dev, int *ret_id)
5589 + return fusion_entry_create( &dev->skirmish, ret_id, NULL );
5593 +fusion_skirmish_prevail (FusionDev *dev, int id, int fusion_id)
5596 + FusionSkirmish *skirmish;
5597 +#ifdef FUSION_DEBUG_SKIRMISH_DEADLOCK
5598 + FusionSkirmish *s;
5600 + bool outer = true;
5603 + dev->stat.skirmish_prevail_swoop++;
5605 + ret = fusion_skirmish_lock( &dev->skirmish, id, true, &skirmish );
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 );
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)
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 );
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) {
5643 + if (s->lock_pid != current->pid)
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) {
5657 + if (i == MAX_PRE_ACQUISITIONS) {
5659 + skirmish->pre_acquis[free] = s->entry.id + 1;
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 );
5675 + up( &dev->skirmish.lock );
5677 + while (skirmish->lock_pid) {
5678 + ret = fusion_skirmish_wait( skirmish, NULL );
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 );
5695 +fusion_skirmish_swoop (FusionDev *dev, int id, int fusion_id)
5698 + FusionSkirmish *skirmish;
5700 + ret = fusion_skirmish_lock( &dev->skirmish, id, false, &skirmish );
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 );
5714 + fusion_skirmish_unlock( skirmish );
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 );
5731 +fusion_skirmish_lock_count (FusionDev *dev, int id, int fusion_id, int *ret_lock_count)
5734 + FusionSkirmish *skirmish;
5736 + ret = fusion_skirmish_lock( &dev->skirmish, id, false, &skirmish );
5740 + if (skirmish->lock_fid == fusion_id &&
5741 + skirmish->lock_pid == current->pid)
5743 + *ret_lock_count = skirmish->lock_count;
5747 + *ret_lock_count = 0;
5750 + fusion_skirmish_unlock( skirmish );
5756 +fusion_skirmish_dismiss (FusionDev *dev, int id, int fusion_id)
5759 + FusionSkirmish *skirmish;
5761 + ret = fusion_skirmish_lock( &dev->skirmish, id, false, &skirmish );
5765 + dev->stat.skirmish_dismiss++;
5767 + if (skirmish->lock_pid != current->pid) {
5768 + fusion_skirmish_unlock( skirmish );
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 );
5785 +fusion_skirmish_destroy (FusionDev *dev, int id)
5787 +#ifdef FUSION_DEBUG_SKIRMISH_DEADLOCK
5789 + FusionSkirmish *s;
5791 + /* Lock entries. */
5792 + if (down_interruptible( &dev->skirmish.lock ))
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 );
5808 + return fusion_entry_destroy( &dev->skirmish, id );
5812 +fusion_skirmish_dismiss_all (FusionDev *dev, int fusion_id)
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);
5838 +fusion_skirmish_dismiss_all_from_pid (FusionDev *dev, int pid)
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
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.
5881 +#ifndef __FUSION__SKIRMISH_H__
5882 +#define __FUSION__SKIRMISH_H__
5884 +#include "fusiondev.h"
5888 +/* module init/cleanup */
5890 +int fusion_skirmish_init (FusionDev *dev);
5891 +void fusion_skirmish_deinit (FusionDev *dev);
5896 +int fusion_skirmish_new (FusionDev *dev,
5899 +int fusion_skirmish_prevail (FusionDev *dev,
5903 +int fusion_skirmish_swoop (FusionDev *dev,
5907 +int fusion_skirmish_lock_count (FusionDev *dev,
5910 + int *ret_lock_count);
5912 +int fusion_skirmish_dismiss (FusionDev *dev,
5916 +int fusion_skirmish_destroy (FusionDev *dev,
5920 +/* internal functions */
5922 +void fusion_skirmish_dismiss_all (FusionDev *dev,
5925 +void fusion_skirmish_dismiss_all_from_pid (FusionDev *dev,
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
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.
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)
5959 +typedef struct __Fusion_Fusionee Fusionee;
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
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"
5972 bool "Legacy (BSD) PTY support"
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
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
5989 +#ifndef __LINUX__FUSION_H__
5990 +#define __LINUX__FUSION_H__
5992 +#include <asm/ioctl.h>
5995 + * Fusion Kernel Device API Version
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.
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
6012 + int major; /* Must be set to FUSION_API_MAJOR before entering. */
6013 + int minor; /* Must be set to FUSION_API_MINOR before entering. */
6016 + FusionID fusion_id; /* Returns the fusion id of the entering process. */
6020 + * Forking in world
6023 + FusionID fusion_id; /* Returns the fusion id of the new (forked) fusionee. */
6027 + * Sending a message
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
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;
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
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)
6071 + int call_id; /* new call id returned */
6073 + void *handler; /* function pointer of handler to install */
6074 + void *ctx; /* optional handler context */
6078 + FCEF_NONE = 0x00000000,
6079 + FCEF_ONEWAY = 0x00000001,
6080 + FCEF_ALL = 0x00000001
6081 +} FusionCallExecFlags;
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;
6095 + int call_id; /* id of currently executing call */
6097 + int val; /* value to return */
6098 +} FusionCallReturn;
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.
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 */
6127 + * Inheriting local count from other reference
6130 + int id; /* own reference id */
6131 + int from; /* id of the reference to inherit from */
6132 +} FusionRefInherit;
6135 + * Killing other fusionees (experimental)
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 */
6146 + * Shared memory pools
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;
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;
6163 + int pool_id; /* The id of the pool to notify. */
6165 + int size; /* New size of the pool. */
6166 +} FusionSHMPoolDispatch;
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;
6174 + FusionSHMPoolMessageType type; /* Type of the message. */
6176 + int size; /* New size of the pool, if type is FSMT_REMAP. */
6177 +} FusionSHMPoolMessage;
6196 + * Set attributes like 'name' for an entry of the specified type.
6198 +#define FUSION_ENTRY_INFO_NAME_LENGTH 24
6204 + char name[FUSION_ENTRY_INFO_NAME_LENGTH];
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)