diff options
Diffstat (limited to 'Source/linux-fusion.patch')
-rwxr-xr-x | Source/linux-fusion.patch | 632 |
1 files changed, 632 insertions, 0 deletions
diff --git a/Source/linux-fusion.patch b/Source/linux-fusion.patch new file mode 100755 index 0000000..a5c32b6 --- /dev/null +++ b/Source/linux-fusion.patch @@ -0,0 +1,632 @@ +diff -uNrb linux-fusion-8.1.1_or/linux/drivers/char/fusion/call.c linux-fusion-8.1.1/linux/drivers/char/fusion/call.c +--- linux-fusion-8.1.1_or/linux/drivers/char/fusion/call.c 2009-03-31 15:04:32.000000000 +0200 ++++ linux-fusion-8.1.1/linux/drivers/char/fusion/call.c 2010-05-07 20:15:33.000000000 +0200 +@@ -42,6 +42,7 @@ + + int call_id; + unsigned int serial; ++ int caller_pid; + } FusionCallExecution; + + typedef struct { +@@ -102,6 +103,31 @@ + free_all_executions(call); + } + ++ ++static void print_call( FusionCall* call ) ++{ ++ FusionEntry *entry; ++ FusionLink *e; ++ ++ entry = &call->entry; ++ ++ printk( KERN_CRIT "%-2d %s, fid:%d, %d calls)", ++ entry->id, ++ entry->name[0] ? entry->name : "???", ++ call->fusion_id, ++ call->count); ++ ++ fusion_list_foreach(e, call->executions) { ++ FusionCallExecution *exec = (FusionCallExecution *) e; ++ ++ printk( "/%lx:%s", ++ exec->caller ? fusionee_id(exec->caller) : -1, ++ exec->executed ? "idle" : "busy" ); ++ } ++ ++ printk("\n"); ++} ++ + static void + fusion_call_print(FusionEntry * entry, void *ctx, struct seq_file *p) + { +@@ -221,14 +247,21 @@ + /* Transfer held skirmishs (locks). */ + fusion_skirmish_transfer_all(dev, call->fusion_id, + fusionee_id(fusionee), +- current->pid); ++ current->pid, ++ serial); + + /* Unlock call and wait for execution result. TODO: add timeout? */ ++ + fusion_sleep_on(&execution->wait, &call->entry.lock, 0); + + if (signal_pending(current)) { + /* Indicate that a signal was received and execution won't be freed by caller. */ + execution->caller = NULL; ++ printk( KERN_EMERG "NDC signal_pending(current) -> exit from fusion_call_execute() without reclaiming our skirmishes. current->pid=%d, fid=0x%08x, call->fusion_id=%d\n", ++ current->pid, ++ (int)(fusionee_id(fusionee)), ++ call->fusion_id ); ++ + return -EINTR; + } + +@@ -300,6 +333,9 @@ + /* FIXME: Caller might still have received a signal since check above. */ + FUSION_ASSERT(execution->caller != NULL); + ++ /* Return skirmishs. */ ++ fusion_skirmish_return_all(dev, fusion_id, execution->caller_pid, execution->serial); ++ + /* Wake up caller. */ + wake_up_interruptible(&execution->wait); + +@@ -349,8 +385,11 @@ + fusion_sleep_on(&execution->wait, &call->entry.lock, 0); + + if (signal_pending(current)) ++ { ++ printk( KERN_EMERG "NDC signal_pending(current) -> exit from fusion_call_destroy()\n"); + return -EINTR; + } ++ } + } while (execution); + + fusion_entry_destroy_locked(call->entry.entries, &call->entry); +@@ -402,6 +441,7 @@ + memset(execution, 0, sizeof(FusionCallExecution)); + + execution->caller = caller; ++ execution->caller_pid = current->pid; + execution->call_id = call->entry.id; + execution->serial = serial; + +diff -uNrb linux-fusion-8.1.1_or/linux/drivers/char/fusion/fusionee.c linux-fusion-8.1.1/linux/drivers/char/fusion/fusionee.c +--- linux-fusion-8.1.1_or/linux/drivers/char/fusion/fusionee.c 2009-03-31 15:04:32.000000000 +0200 ++++ linux-fusion-8.1.1/linux/drivers/char/fusion/fusionee.c 2010-04-06 14:10:06.000000000 +0200 +@@ -56,7 +56,8 @@ + int rcv_total; /* Total number of messages received. */ + int snd_total; /* Total number of messages sent. */ + +- wait_queue_head_t wait; ++ wait_queue_head_t wait_receive; ++ wait_queue_head_t wait_process; + + bool force_slave; + +@@ -196,7 +197,8 @@ + + init_MUTEX(&fusionee->lock); + +- init_waitqueue_head(&fusionee->wait); ++ init_waitqueue_head(&fusionee->wait_receive); ++ init_waitqueue_head(&fusionee->wait_process); + + fusion_list_prepend(&dev->fusionee.list, &fusionee->link); + +@@ -294,10 +296,7 @@ + if (ret) + return ret; + +- if (down_interruptible(&fusionee->lock)) { +- up(&dev->fusionee.lock); +- return -EINTR; +- } ++ down(&fusionee->lock); + + if (sender && sender != fusionee) { + if (down_interruptible(&sender->lock)) { +@@ -343,7 +342,7 @@ + if (sender) + sender->snd_total++; + +- wake_up_interruptible_all(&fusionee->wait); ++ wake_up_interruptible_all(&fusionee->wait_receive); + + if (sender && sender != fusionee) + unlock_fusionee(sender); +@@ -372,7 +371,7 @@ + + fusion_fifo_reset(&fusionee->prev_msgs); + +- wake_up_interruptible_all(&fusionee->wait); ++ wake_up_interruptible_all(&fusionee->wait_process); + + while (!fusionee->messages.count) { + if (!block) { +@@ -385,7 +384,7 @@ + unlock_fusionee(fusionee); + flush_messages(dev, &prev_msgs); + } else { +- fusion_sleep_on(&fusionee->wait, &fusionee->lock, 0); ++ fusion_sleep_on(&fusionee->wait_receive, &fusionee->lock, 0); + + if (signal_pending(current)) + return -EINTR; +@@ -494,7 +493,7 @@ + FUSION_ASSUME(fusionee->dispatcher_pid != current->pid); + + /* Otherwise unlock and wait. */ +- fusion_sleep_on(&fusionee->wait, &fusionee->lock, 0); ++ fusion_sleep_on(&fusionee->wait_process, &fusionee->lock, 0); + + if (signal_pending(current)) + return -EINTR; +@@ -525,9 +524,9 @@ + + flush_messages(dev, &prev_msgs); + +- wake_up_all(&fusionee->wait); ++ wake_up_all(&fusionee->wait_process); + +- poll_wait(file, &fusionee->wait, wait); ++ poll_wait(file, &fusionee->wait_receive, wait); + + ret = lock_fusionee(dev, id, &fusionee); + if (ret) +@@ -703,8 +702,7 @@ + { + FusionLink *l; + +- if (down_interruptible(&dev->fusionee.lock)) +- return -EINTR; ++ down(&dev->fusionee.lock); + + fusion_list_foreach(l, dev->fusionee.list) { + Fusionee *fusionee = (Fusionee *) l; +diff -uNrb linux-fusion-8.1.1_or/linux/drivers/char/fusion/skirmish.c linux-fusion-8.1.1/linux/drivers/char/fusion/skirmish.c +--- linux-fusion-8.1.1_or/linux/drivers/char/fusion/skirmish.c 2009-03-31 15:04:32.000000000 +0200 ++++ linux-fusion-8.1.1/linux/drivers/char/fusion/skirmish.c 2010-05-07 20:15:32.000000000 +0200 +@@ -52,6 +52,13 @@ + FusionID transfer_from; + int transfer_from_pid; + int transfer_count; ++ unsigned int transfer_serial; ++ ++ FusionID transfer2_to; ++ FusionID transfer2_from; ++ int transfer2_from_pid; ++ int transfer2_count; ++ unsigned int transfer2_serial; + + #ifdef FUSION_DEBUG_SKIRMISH_DEADLOCK + int pre_acquis[MAX_PRE_ACQUISITIONS]; +@@ -69,6 +76,87 @@ + static unsigned int m_pidlocks[PID_MAX_DEFAULT + 1]; /* FIXME: find cleaner, but still fast method */ + static sigset_t m_sigmask; + ++ ++static void ++print_skirmish_internal( FusionSkirmish* skirmish, const char* pHeader ) ++{ ++ FusionEntry *entry; ++ char p[16]; ++ struct timeval now; ++ static kaboemcount = 100; ++ ++ // kaboemcount--; ++ ++ do_gettimeofday(&now); ++ ++ entry = &skirmish->entry; ++ ++ if (entry->last_lock.tv_sec) { ++ int diff = ((now.tv_sec - entry->last_lock.tv_sec) * 1000 + ++ (now.tv_usec - entry->last_lock.tv_usec) / 1000); ++ ++ if (diff < 1000) { ++ sprintf(p, "%3d ms ", diff); ++ } else if (diff < 1000000) { ++ sprintf(p, "%3d.%d s ", diff / 1000, ++ (diff % 1000) / 100); ++ } else { ++ diff = (now.tv_sec - entry->last_lock.tv_sec + ++ (now.tv_usec - ++ entry->last_lock.tv_usec) / 1000000); ++ ++ sprintf(p, "%3d.%d h ", diff / 3600, ++ (diff % 3600) / 360); ++ } ++ } else ++ sprintf(p, " -.- "); ++ ++ ++ printk( "%s %s %-3d.%03d %d %-18s [1] t:%d f:%d fpid:%-4d c:%d s:%d [2] t:%d f:%d fpid:%-4d c:%d s:%d - c:%d f:%d p:%-4d w:%d\n", ++ pHeader ? pHeader : " ", ++ p, ++ entry->last_lock.tv_sec, ++ (entry->last_lock.tv_usec)/1000000 , ++ entry->id, ++ entry->name[0] ? entry->name : "???", ++ ++ skirmish->transfer_to, ++ skirmish->transfer_from, ++ skirmish->transfer_from_pid, ++ skirmish->transfer_count, ++ skirmish->transfer_serial, ++ ++ skirmish->transfer2_to, ++ skirmish->transfer2_from, ++ skirmish->transfer2_from_pid, ++ skirmish->transfer2_count, ++ skirmish->transfer2_serial, ++ ++ skirmish->lock_count, ++ skirmish->lock_fid, ++ skirmish->lock_pid, ++ skirmish->entry.waiters ++ ); ++ ++ if( kaboemcount <= 0 ) ++ { ++ printk( KERN_EMERG "boem !\n" ); ++ kill_pgrp(task_pgrp(current), SIGSEGV, 1); ++ while(1) ++ { ++ yield(); ++ } ++ } ++ ++} ++ ++static void ++print_skirmish( FusionSkirmish* skirmish ) ++{ ++ print_skirmish_internal( skirmish, KERN_EMERG " skirmish" ); ++} ++ ++ + #ifdef FUSION_BLOCK_SIGNALS + static int skirmish_signal_handler(void *ctx) + { +@@ -77,7 +165,7 @@ + return 1; + } + +- printk(KERN_DEBUG "FusionSkirmish: Blocking signal for process %d!\n", ++ printk(KERN_EMERG "FusionSkirmish: Blocking signal for process %d!\n", + current->pid); + + return 0; +@@ -111,20 +199,23 @@ + } + } + #endif +- +- if (skirmish->lock_fid) { +- if (skirmish->entry.waiters) +- seq_printf(p, " - %dx [0x%08x] (%d) %d WAITING\n", +- skirmish->lock_count, skirmish->lock_fid, +- skirmish->lock_pid, skirmish->entry.waiters); +- else +- seq_printf(p, " - %dx [0x%08x] (%d)\n", +- skirmish->lock_count, skirmish->lock_fid, +- skirmish->lock_pid); +- return; +- } +- +- seq_printf(p, "\n"); ++ seq_printf(p, "[1] t:%d, f:%d, fpid:%d, c:%d s:%d, [2] t:%d, f:%d, fpid:%d, c:%d, s:%d", ++ skirmish->transfer_to, ++ skirmish->transfer_from, ++ skirmish->transfer_from_pid, ++ skirmish->transfer_count, ++ skirmish->transfer_serial, ++ skirmish->transfer2_to, ++ skirmish->transfer2_from, ++ skirmish->transfer2_from_pid, ++ skirmish->transfer2_count, ++ skirmish->transfer2_serial ); ++ seq_printf(p, ", c:%d, f:0x%08x, p:%d, waiters:%d\n", ++ skirmish->lock_count, ++ skirmish->lock_fid, ++ skirmish->lock_pid, ++ skirmish->entry.waiters ++ ); + } + + FUSION_ENTRY_CLASS(FusionSkirmish, skirmish, NULL, NULL, fusion_skirmish_print) +@@ -245,11 +336,14 @@ + + up(&dev->skirmish.lock); + +- while (skirmish->lock_pid || (skirmish->transfer_to != 0 && +- fusionee_dispatcher_pid(dev, +- skirmish-> +- transfer_to) != +- current->pid)) { ++ ++ while ( skirmish->lock_pid ++ || ( (skirmish->transfer2_to == 0) ++ && skirmish->transfer_to ++ && (fusionee_dispatcher_pid(dev, skirmish-> transfer_to) != current->pid)) ++ || ( skirmish->transfer2_to ++ && (fusionee_dispatcher_pid(dev, skirmish-> transfer2_to) != current->pid)) ) ++ { + ret = fusion_skirmish_wait(skirmish, NULL); + if (ret) + return ret; +@@ -283,11 +377,13 @@ + + dev->stat.skirmish_prevail_swoop++; + +- if (skirmish->lock_fid || (skirmish->transfer_to != 0 && +- fusionee_dispatcher_pid(dev, +- skirmish-> +- transfer_to) != +- current->pid)) { ++ if ( skirmish->lock_fid ++ || ( (skirmish->transfer2_to == 0) ++ && skirmish->transfer_to ++ && (fusionee_dispatcher_pid(dev, skirmish->transfer_to) != current->pid)) ++ || ( skirmish->transfer2_to ++ && (fusionee_dispatcher_pid(dev, skirmish-> transfer2_to) != current->pid)) ) ++ { + if (skirmish->lock_pid == current->pid) { + skirmish->lock_count++; + skirmish->lock_total++; +@@ -515,6 +611,8 @@ + break; + + case -EINTR: ++ printk( KERN_EMERG "NDC fusion_skirmish_wait EINTR()\n"); ++ + /* Return immediately upon signal. */ + FUSION_SKIRMISH_LOG + ("FusionSkirmish: Interrupted while waiting for notification!\n"); +@@ -538,6 +636,7 @@ + break; + + case -EINTR: ++ printk( KERN_EMERG "NDC fusion_skirmish_wait 2 EINTR()\n"); + /* Return immediately upon signal. */ + FUSION_SKIRMISH_LOG + ("FusionSkirmish: Interrupted while waiting for relock!\n"); +@@ -614,11 +713,26 @@ + wake_up_interruptible_all(&skirmish->entry.wait); + } + ++ if (skirmish->transfer2_from == fusion_id) { ++ skirmish->transfer2_to = 0; ++ skirmish->transfer2_from = 0; ++ skirmish->transfer2_from_pid = 0; ++ skirmish->transfer2_count = 0; ++ ++ wake_up_interruptible_all(&skirmish->entry.wait); ++ } ++ + if (skirmish->transfer_from == fusion_id) { +- skirmish->transfer_to = 0; +- skirmish->transfer_from = 0; +- skirmish->transfer_from_pid = 0; +- skirmish->transfer_count = 0; ++ skirmish->transfer_to = skirmish->transfer2_to; ++ skirmish->transfer_from = skirmish->transfer2_from; ++ skirmish->transfer_from_pid = skirmish->transfer2_from_pid; ++ skirmish->transfer_count = skirmish->transfer2_count; ++ if (skirmish->transfer2_to) { ++ skirmish->transfer2_to = 0; ++ skirmish->transfer2_from = 0; ++ skirmish->transfer2_from_pid = 0; ++ skirmish->transfer2_count = 0; ++ } + + wake_up_interruptible_all(&skirmish->entry.wait); + } +@@ -650,11 +764,26 @@ + wake_up_interruptible_all(&skirmish->entry.wait); + } + ++ if (skirmish->transfer2_from_pid == pid) { ++ skirmish->transfer2_to = 0; ++ skirmish->transfer2_from = 0; ++ skirmish->transfer2_from_pid = 0; ++ skirmish->transfer2_count = 0; ++ ++ wake_up_interruptible_all(&skirmish->entry.wait); ++ } ++ + if (skirmish->transfer_from_pid == pid) { +- skirmish->transfer_to = 0; +- skirmish->transfer_from = 0; +- skirmish->transfer_from_pid = 0; +- skirmish->transfer_count = 0; ++ skirmish->transfer_to = skirmish->transfer2_to; ++ skirmish->transfer_from = skirmish->transfer2_from; ++ skirmish->transfer_from_pid = skirmish->transfer2_from_pid; ++ skirmish->transfer_count = skirmish->transfer2_count; ++ if (skirmish->transfer2_to) { ++ skirmish->transfer2_to = 0; ++ skirmish->transfer2_from = 0; ++ skirmish->transfer2_from_pid = 0; ++ skirmish->transfer2_count = 0; ++ } + + wake_up_interruptible_all(&skirmish->entry.wait); + } +@@ -667,7 +796,7 @@ + + void + fusion_skirmish_transfer_all(FusionDev * dev, +- FusionID to, FusionID from, int from_pid) ++ FusionID to, FusionID from, int from_pid, unsigned int serial) + { + FusionLink *l; + +@@ -679,7 +808,7 @@ + down(&skirmish->entry.lock); + + if (skirmish->lock_pid == from_pid) { +- FUSION_ASSERT(skirmish->transfer_to == 0); ++ if (skirmish->transfer_to == 0) { + FUSION_ASSERT(skirmish->transfer_from == 0); + FUSION_ASSERT(skirmish->transfer_from_pid == 0); + FUSION_ASSERT(skirmish->transfer_count == 0); +@@ -689,6 +818,24 @@ + skirmish->transfer_from = from; + skirmish->transfer_from_pid = from_pid; + skirmish->transfer_count = skirmish->lock_count; ++ skirmish->transfer_serial = serial; ++ ++ skirmish->lock_fid = 0; ++ skirmish->lock_pid = 0; ++ skirmish->lock_count = 0; ++ ++ wake_up_interruptible_all(&skirmish->entry.wait); ++ } else if (skirmish->transfer2_to == 0) { ++ FUSION_ASSERT(skirmish->transfer2_from == 0); ++ FUSION_ASSERT(skirmish->transfer2_from_pid == 0); ++ FUSION_ASSERT(skirmish->transfer2_count == 0); ++ FUSION_ASSERT(skirmish->lock_count > 0); ++ ++ skirmish->transfer2_to = to; ++ skirmish->transfer2_from = from; ++ skirmish->transfer2_from_pid = from_pid; ++ skirmish->transfer2_count = skirmish->lock_count; ++ skirmish->transfer2_serial = serial; + + skirmish->lock_fid = 0; + skirmish->lock_pid = 0; +@@ -696,6 +843,7 @@ + + wake_up_interruptible_all(&skirmish->entry.wait); + } ++ } + + up(&skirmish->entry.lock); + } +@@ -714,11 +862,18 @@ + + down(&skirmish->entry.lock); + +- if (skirmish->transfer_from_pid == from_pid) { ++ if ( (skirmish->transfer2_to == 0) ++ && skirmish->transfer_to ++ && (skirmish->transfer_from_pid == from_pid) ) ++ { + FUSION_ASSERT(skirmish->transfer_to != 0); + FUSION_ASSERT(skirmish->transfer_from != 0); + FUSION_ASSERT(skirmish->transfer_count > 0); +- FUSION_ASSUME(skirmish->lock_pid == 0); ++ if( skirmish->lock_pid != -1 ) ++ { ++ print_skirmish( skirmish ); ++ } ++ FUSION_ASSERT(skirmish->lock_pid == -1); + + skirmish->lock_fid = skirmish->transfer_from; + skirmish->lock_pid = skirmish->transfer_from_pid; +@@ -728,6 +883,68 @@ + skirmish->transfer_from = 0; + skirmish->transfer_from_pid = 0; + skirmish->transfer_count = 0; ++ } else if ( skirmish->transfer2_to ++ && (skirmish->transfer2_from_pid == from_pid) ) { ++ FUSION_ASSERT(skirmish->transfer2_to != 0); ++ FUSION_ASSERT(skirmish->transfer2_from != 0); ++ FUSION_ASSERT(skirmish->transfer2_count > 0); ++ FUSION_ASSERT(skirmish->lock_pid == -1); ++ ++ skirmish->lock_fid = skirmish->transfer2_from; ++ skirmish->lock_pid = skirmish->transfer2_from_pid; ++ skirmish->lock_count = skirmish->transfer2_count; ++ ++ skirmish->transfer2_to = 0; ++ skirmish->transfer2_from = 0; ++ skirmish->transfer2_from_pid = 0; ++ skirmish->transfer2_count = 0; ++ } ++ up(&skirmish->entry.lock); ++ } ++ ++ up(&dev->skirmish.lock); ++} ++ ++void fusion_skirmish_return_all(FusionDev * dev, int from_fusion_id, int to_pid, unsigned int serial) ++{ ++ FusionLink *l; ++ ++ down(&dev->skirmish.lock); ++ ++ fusion_list_foreach(l, dev->skirmish.list) { ++ FusionSkirmish *skirmish = (FusionSkirmish *) l; ++ ++ down(&skirmish->entry.lock); ++ ++ if (skirmish->transfer2_to == 0) { ++ if ( skirmish->transfer_to == from_fusion_id && ++ skirmish->transfer_from_pid == to_pid && ++ skirmish->transfer_serial == serial ) ++ { ++ FUSION_ASSERT(skirmish->transfer_from != 0); ++ FUSION_ASSERT(skirmish->transfer_count > 0); ++ if( skirmish->lock_count != 0 ) ++ { ++ print_skirmish( skirmish ); ++ } ++ FUSION_ASSERT(skirmish->lock_count == 0); ++ FUSION_ASSERT(skirmish->lock_fid == 0); ++ FUSION_ASSERT(skirmish->lock_pid == 0); ++ ++ skirmish->lock_pid = -1; ++ } ++ } ++ else if (skirmish->transfer2_from_pid == to_pid && ++ skirmish->transfer2_to == from_fusion_id && ++ skirmish->transfer2_serial == serial ) ++ { ++ FUSION_ASSERT(skirmish->transfer2_from != 0); ++ FUSION_ASSERT(skirmish->transfer2_count > 0); ++ FUSION_ASSERT(skirmish->lock_count == 0); ++ FUSION_ASSERT(skirmish->lock_fid == 0); ++ FUSION_ASSERT(skirmish->lock_pid == 0); ++ ++ skirmish->lock_pid = -1; + } + + up(&skirmish->entry.lock); +@@ -735,3 +952,4 @@ + + up(&dev->skirmish.lock); + } ++ +diff -uNrb linux-fusion-8.1.1_or/linux/drivers/char/fusion/skirmish.h linux-fusion-8.1.1/linux/drivers/char/fusion/skirmish.h +--- linux-fusion-8.1.1_or/linux/drivers/char/fusion/skirmish.h 2009-03-31 15:04:32.000000000 +0200 ++++ linux-fusion-8.1.1/linux/drivers/char/fusion/skirmish.h 2010-05-07 20:15:31.000000000 +0200 +@@ -50,8 +50,10 @@ + void fusion_skirmish_dismiss_all_from_pid(FusionDev * dev, int pid); + + void fusion_skirmish_transfer_all(FusionDev * dev, +- FusionID to, FusionID from, int from_pid); ++ FusionID to, FusionID from, int from_pid, unsigned int serial); + + void fusion_skirmish_reclaim_all(FusionDev * dev, int from_pid); + ++void fusion_skirmish_return_all(FusionDev * dev, int from_fusion_id, int to_fusion_id, unsigned int serial); ++ + #endif +diff -uNrb linux-fusion-8.1.1_or/Makefile linux-fusion-8.1.1/Makefile +--- linux-fusion-8.1.1_or/Makefile 2009-03-31 15:04:32.000000000 +0200 ++++ linux-fusion-8.1.1/Makefile 2010-06-04 23:41:54.140625000 +0200 +@@ -42,7 +42,7 @@ + + all: + rm -f $(SUB)/Makefile +- ln -s Makefile-2.$(K_PATCHLEVEL) $(SUB)/Makefile ++ cp $(SUB)/Makefile-2.$(K_PATCHLEVEL) $(SUB)/Makefile + ifeq ($(call check-version,2,6,24),1) + $(MAKE) -C $(KERNEL_BUILD) \ + KCPPFLAGS="$(CPPFLAGS) -I`pwd`/linux/include" \ |