# This is a BitKeeper generated diff -Nru style patch. # # net/core/dev.c # 2004/08/25 16:35:17-07:00 shemminger@osdl.org +16 -25 # [BRIDGE]: Fix oops when mangling and brouting and tcpdumping packets # # The ebtables brouting chain, traversed through the call # br_should_route_hook(), can alter a packet. The redirect target # does this, f.e., to change the MAC destination. # # Bart discovered this and proposed a patch; this is a revised version. # This version cleans up the handle_bridge code in net/core/dev.c as well # as getting rid of extra rcu_read_lock and only does the br_port checking # once. # # Signed-off-by: Stephen Hemminger # Signed-off-by: David S. Miller # # net/core/dev.c # 2004/08/24 17:09:48-07:00 shemminger@osdl.org +4 -3 # [NET]: Another cleanup in netif_receive_skb() # # Move rcu_read_lock up a little, since it needs to be # done in both branches anyway. Also whitespace fix. # # Signed-off-by: Stephen Hemminger # Signed-off-by: David S. Miller # # net/core/dev.c # 2004/08/24 17:07:59-07:00 shemminger@osdl.org +5 -6 # [NET]: deliver_skb() cleanup # # Cleanup of deliver_skb: get rid of unused argument and use it # in the NET_CLS_ACT hook. # # Signed-off-by: Stephen Hemminger # Signed-off-by: David S. Miller # # net/core/dev.c # 2004/08/24 17:03:04-07:00 herbert@gondor.apana.org.au +3 -9 # [NET]: Use pskb_expand_head() instead of skb_copy() in skb_checksum_help(). # # Here is the patch that you wanted to shoot holes at :) # # The idea is simple. None of the callers of skb_checksum are passing it # skb's which are shared. They may be cloned however. But the application # checksum is always in the skb header so there is no need to linearise it. # # Supposing all these assumptions are correct, then we can avoid the overhead # of skb_copy() and get away with pskb_expand_head(). # # If the assumption is wrong, we will find out because # pskb_expand_head() will BUG() if skb_shared() is true. # # Signed-off-by: Herbert Xu # Signed-off-by: David S. Miller # # lib/kobject.c # 2004/08/25 12:30:25-07:00 greg@kroah.com +10 -9 # kobject: convert struct kobject use kref. # # Signed-off-by: Greg Kroah-Hartman # # # lib/kobject.c # 2004/08/23 23:14:58-07:00 dtor_core@ameritech.net +1 -1 # kobject: fix kobject_set_name comment. # # lib/kobject.c # 2004/08/06 13:53:24-07:00 rml@ximian.com +27 -9 # KOBJECT: add kobject_get_path # # drivers/base/class.c # 2004/08/07 03:27:32-07:00 thomas.koeller@baslerweb.com +7 -2 # Driver Core: fix minor class reference counting issue on the error path # # include/linux/kobject.h # 2004/08/25 12:30:25-07:00 greg@kroah.com +2 -1 # kobject: convert struct kobject use kref. # # Signed-off-by: Greg Kroah-Hartman # # # include/linux/kobject.h # 2004/08/06 13:25:03-07:00 rml@ximian.com +2 -0 # KOBJECT: add kobject_get_path # # ChangeSet # 2004/08/25 21:31:10-07:00 torvalds@ppc970.osdl.org # Revert I2C keywest class fixup # # Benh says: "Please revert that for now, I need to figure out what they # were exactly trying to do and will come up with something if it makes # sense but the patch as-is doesn't" # # Cset exclude: khali@linux-fr.org|ChangeSet|20040825202122|07524 # # drivers/i2c/busses/i2c-keywest.c # 2004/08/25 21:30:53-07:00 torvalds@ppc970.osdl.org +0 -0 # Revert I2C keywest class fixup # # ChangeSet # 2004/08/25 20:20:04-07:00 laforge@netfilter.org # [NETFILTER]: Fix ip_nat_find_helper() locking. # # Signed-off-by: Harald Welte # Signed-off-by: David S. Miller # # net/ipv4/netfilter/ip_nat_standalone.c # 2004/08/25 20:19:30-07:00 laforge@netfilter.org +2 -0 # [NETFILTER]: Fix ip_nat_find_helper() locking. # # net/ipv4/netfilter/ip_nat_helper.c # 2004/08/25 20:19:30-07:00 laforge@netfilter.org +7 -1 # [NETFILTER]: Fix ip_nat_find_helper() locking. # # net/ipv4/netfilter/ip_nat_core.c # 2004/08/25 20:19:30-07:00 laforge@netfilter.org +1 -1 # [NETFILTER]: Fix ip_nat_find_helper() locking. # # include/linux/netfilter_ipv4/ip_nat_helper.h # 2004/08/25 20:19:30-07:00 laforge@netfilter.org +3 -0 # [NETFILTER]: Fix ip_nat_find_helper() locking. # # ChangeSet # 2004/08/25 18:06:16-07:00 davidm@napali.hpl.hp.com # [PATCH] signal-race-fix: ia64 # # It looks fine to me, except that I decided to play chicken as far as the # give_sigsegv update of sa_handler is concerned. # # Arun, I hope I got the ia32 emulation parts right, but you may want to # double-check. # # The patch seems to work fine as far as I have tested. I'm seeing some # oddity in context-switch overhead and pipe latency as reported by LMbench, # but I suspect that's due to another change that happened somewhere between # 2.6.5-rc1 and Linus' bk tree as of this morning. # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # arch/ia64/kernel/signal.c # 2004/08/25 10:13:41-07:00 davidm@napali.hpl.hp.com +38 -26 # signal-race-fix: ia64 # # ChangeSet # 2004/08/25 18:02:05-07:00 wli@holomorphy.com # [PATCH] alpha signal race fixes # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # arch/alpha/kernel/signal.c # 2004/08/25 10:13:42-07:00 wli@holomorphy.com +4 -5 # alpha signal race fixes # # ChangeSet # 2004/08/25 18:01:53-07:00 paulus@samba.org # [PATCH] ppc64: signal race fix # # Signed-off-by: Paul Mackerras # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # arch/ppc64/kernel/signal32.c # 2004/08/25 10:13:41-07:00 paulus@samba.org +10 -14 # ppc64: signal race fix # # arch/ppc64/kernel/signal.c # 2004/08/25 10:13:41-07:00 paulus@samba.org +5 -10 # ppc64: signal race fix # # ChangeSet # 2004/08/25 18:01:41-07:00 davem@redhat.com # [PATCH] signal handling race fixes: sparc and sparc64 # # Ok, here are the sparc64 and sparc32 versions. # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # arch/sparc64/kernel/signal32.c # 2004/08/25 10:13:41-07:00 davem@redhat.com +5 -9 # signal handling race fixes: sparc and sparc64 # # arch/sparc64/kernel/signal.c # 2004/08/25 10:13:41-07:00 davem@redhat.com +4 -9 # signal handling race fixes: sparc and sparc64 # # arch/sparc/kernel/signal.c # 2004/08/25 10:13:41-07:00 davem@redhat.com +5 -9 # signal handling race fixes: sparc and sparc64 # # ChangeSet # 2004/08/25 18:01:29-07:00 ak@muc.de # [PATCH] signal-race-fixes: x86-64 support # # Add the signal race changes to x86-64 to make it compile again. # # Didn't merge the more pointless changes from i386. # # Also remove the special SA_ONESHOT handling, doesn't seem to be needed # anymore. # # From: Mikael Pettersson # # The signal-race-fixes patch in 2.6.8-rc2-mm1 appears to have broken # x86-64's ia32 emulation. # # When forcing a SIGSEGV the old code updated "*ka", where ka was a pointer # to current's k_sigaction for SIGSEGV. Now "ka_copy" points to a copy of # that structure, so assigning "*ka_copy" doesn't do what we want. Instead do # the assignment via current->... just like the normal signal delivery code # does. # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # arch/x86_64/kernel/signal.c # 2004/08/25 10:13:41-07:00 ak@muc.de +6 -10 # signal-race-fixes: x86-64 support # # ChangeSet # 2004/08/25 18:01:20-07:00 mikpe@csd.uu.se # [PATCH] ppc signal handling fixes # # 2.6.8-rc2-mm1 reintroduced the signal-race-fixes patch for i386, x86_64, # s390, and ia64, breaking all other archs. # # The patch below updates ppc, following the pattern of i386. Compiled & # runtime tested. No observable breakage. # # Signed-off-by: Mikael Pettersson # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # arch/ppc/kernel/signal.c # 2004/08/25 10:13:41-07:00 mikpe@csd.uu.se +9 -14 # ppc signal handling fixes # # ChangeSet # 2004/08/25 18:01:08-07:00 schwidefsky@de.ibm.com # [PATCH] signal-race fixes for s390 # # Update s30 for the signal race fix # # From: Mikael Pettersson # # The signal-race-fixes patch in 2.6.8-rc2-mm1 appears to be a bit broken on # s390. # # When forcing a SIGSEGV the old code updated "*ka", where ka was a pointer # to current's k_sigaction for SIGSEGV. Now "ka_copy" points to a copy of # that structure, so assigning "*ka_copy" doesn't do what we want. Instead do # the assignment via current->... just like i386 and x86_64 do. # # Furthermore, the SA_ONESHOT handling wasn't deleted. That is now handled # by generic code in the kernel. # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # arch/s390/kernel/signal.c # 2004/08/25 10:13:41-07:00 schwidefsky@de.ibm.com +7 -10 # signal-race fixes for s390 # # arch/s390/kernel/compat_signal.c # 2004/08/25 10:13:41-07:00 schwidefsky@de.ibm.com +2 -7 # signal-race fixes for s390 # # ChangeSet # 2004/08/25 18:00:58-07:00 minyard@acm.org # [PATCH] signal handling race fix # # The problem: # # In arch/i386/signal.c, in the do_signal() function, it calls # get_signal_to_deliver() which returns the signal number to deliver (along # with siginfo). get_signal_to_deliver() grabs and releases the lock, so # the signal handler lock is not held in do_signal(). Then the do_signal() # calls handle_signal(), which uses the signal number to extract the # sa_handler, etc. # # Since no lock is held, it seems like another thread with the same # signal handler set can come in and call sigaction(), it can change # sa_handler between the call to get_signal_to_deliver() and fetching the # value of sa_handler. If the sigaction() call set it to SIG_IGN, SIG_DFL, # or some other fundamental change, that bad things can happen. # # The patch: # # You have to get the sigaction information that will be delivered while # holding sighand->siglock in get_signal_to_deliver(). # # In 2.4, it can be fixed per-arch and requires no change to the # arch-independent code because the arch fetches the signal with # dequeue_signal() and does all the checking. # # The test app: # # The program below has three threads that share signal handlers. Thread # 1 changes the signal handler for a signal from a handler to SIG_IGN and # back. Thread 0 sends signals to thread 3, which just receives them. # What I believe is happening is that thread 1 changes the signal handler # in the process of thread 3 receiving the signal, between the time that # thread 3 fetches the signal info using get_signal_to_deliver() and # actually delivers the signal with handle_signal(). # # Although the program is obvously an extreme case, it seems like any # time you set the handler value of a signal to SIG_IGN or SIG_DFL, you can # have this happen. Changing signal attributes might also cause problems, # although I am not so sure about that. # # (akpm: this test app segv'd on SMP within milliseconds for me) # # # #include # #include # #include # # char stack1[16384]; # char stack2[16384]; # # void sighnd(int sig) # { # } # # int child1(void *data) # { # struct sigaction act; # # sigemptyset(&act.sa_mask); # act.sa_flags = 0; # for (;;) { # act.sa_handler = sighnd; # sigaction(45, &act, NULL); # act.sa_handler = SIG_IGN; # sigaction(45, &act, NULL); # } # } # # int child2(void *data) # { # for (;;) { # sleep(100); # } # } # # int main(int argc, char *argv[]) # { # int pid1, pid2; # # signal(45, SIG_IGN); # pid2 = clone(child2, stack2 + sizeof(stack2) - 8, # CLONE_SIGHAND | CLONE_VM, NULL); # pid1 = clone(child1, stack1 + sizeof(stack2) - 8, # CLONE_SIGHAND | CLONE_VM, NULL); # # for (;;) { # kill(pid2, 45); # } # } # # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # kernel/signal.c # 2004/08/25 10:35:08-07:00 minyard@acm.org +10 -2 # signal handling race fix # # include/linux/signal.h # 2004/08/25 10:13:40-07:00 minyard@acm.org +1 -1 # signal handling race fix # # arch/i386/kernel/signal.c # 2004/08/25 10:13:40-07:00 minyard@acm.org +5 -9 # signal handling race fix # # ChangeSet # 2004/08/25 17:37:34-07:00 torvalds@ppc970.osdl.org # Merge common signal handling fault handling in generic code. # # kernel/signal.c # 2004/08/25 17:37:26-07:00 torvalds@ppc970.osdl.org +19 -0 # Merge common signal handling fault handling in generic code. # # include/linux/sched.h # 2004/08/25 17:37:26-07:00 torvalds@ppc970.osdl.org +1 -0 # Merge common signal handling fault handling in generic code. # # arch/x86_64/kernel/signal.c # 2004/08/25 17:37:26-07:00 torvalds@ppc970.osdl.org +1 -3 # Merge common signal handling fault handling in generic code. # # arch/x86_64/ia32/ia32_signal.c # 2004/08/25 17:37:26-07:00 torvalds@ppc970.osdl.org +2 -6 # Merge common signal handling fault handling in generic code. # # arch/v850/kernel/signal.c # 2004/08/25 17:37:26-07:00 torvalds@ppc970.osdl.org +2 -6 # Merge common signal handling fault handling in generic code. # # arch/um/kernel/signal_kern.c # 2004/08/25 17:37:26-07:00 torvalds@ppc970.osdl.org +1 -12 # Merge common signal handling fault handling in generic code. # # arch/sh64/kernel/signal.c # 2004/08/25 17:37:26-07:00 torvalds@ppc970.osdl.org +2 -6 # Merge common signal handling fault handling in generic code. # # arch/sh/kernel/signal.c # 2004/08/25 17:37:26-07:00 torvalds@ppc970.osdl.org +2 -6 # Merge common signal handling fault handling in generic code. # # arch/s390/kernel/signal.c # 2004/08/25 17:37:26-07:00 torvalds@ppc970.osdl.org +2 -6 # Merge common signal handling fault handling in generic code. # # arch/s390/kernel/compat_signal.c # 2004/08/25 17:37:26-07:00 torvalds@ppc970.osdl.org +2 -6 # Merge common signal handling fault handling in generic code. # # arch/ppc64/kernel/signal32.c # 2004/08/25 17:37:26-07:00 torvalds@ppc970.osdl.org +2 -6 # Merge common signal handling fault handling in generic code. # # arch/ppc/kernel/signal.c # 2004/08/25 17:37:26-07:00 torvalds@ppc970.osdl.org +2 -6 # Merge common signal handling fault handling in generic code. # # arch/mips/kernel/signal_n32.c # 2004/08/25 17:37:26-07:00 torvalds@ppc970.osdl.org +1 -3 # Merge common signal handling fault handling in generic code. # # arch/mips/kernel/signal32.c # 2004/08/25 17:37:26-07:00 torvalds@ppc970.osdl.org +2 -6 # Merge common signal handling fault handling in generic code. # # arch/mips/kernel/signal.c # 2004/08/25 17:37:25-07:00 torvalds@ppc970.osdl.org +2 -6 # Merge common signal handling fault handling in generic code. # # arch/mips/kernel/irixsig.c # 2004/08/25 17:37:25-07:00 torvalds@ppc970.osdl.org +1 -3 # Merge common signal handling fault handling in generic code. # # arch/m68knommu/kernel/signal.c # 2004/08/25 17:37:25-07:00 torvalds@ppc970.osdl.org +2 -6 # Merge common signal handling fault handling in generic code. # # arch/m68k/kernel/signal.c # 2004/08/25 17:37:25-07:00 torvalds@ppc970.osdl.org +2 -6 # Merge common signal handling fault handling in generic code. # # arch/ia64/ia32/ia32_signal.c # 2004/08/25 17:37:25-07:00 torvalds@ppc970.osdl.org +2 -6 # Merge common signal handling fault handling in generic code. # # arch/i386/kernel/signal.c # 2004/08/25 17:37:25-07:00 torvalds@ppc970.osdl.org +2 -6 # Merge common signal handling fault handling in generic code. # # arch/h8300/kernel/signal.c # 2004/08/25 17:37:25-07:00 torvalds@ppc970.osdl.org +2 -6 # Merge common signal handling fault handling in generic code. # # arch/cris/arch-v10/kernel/signal.c # 2004/08/25 17:37:25-07:00 torvalds@ppc970.osdl.org +2 -6 # Merge common signal handling fault handling in generic code. # # arch/arm26/kernel/signal.c # 2004/08/25 17:37:25-07:00 torvalds@ppc970.osdl.org +1 -3 # Merge common signal handling fault handling in generic code. # # arch/arm/kernel/signal.c # 2004/08/25 17:37:25-07:00 torvalds@ppc970.osdl.org +1 -3 # Merge common signal handling fault handling in generic code. # # arch/alpha/kernel/signal.c # 2004/08/25 17:37:25-07:00 torvalds@ppc970.osdl.org +2 -6 # Merge common signal handling fault handling in generic code. # # ChangeSet # 2004/08/25 17:28:57-07:00 torvalds@ppc970.osdl.org # vt: don't bother doing UTF translation in control states. # # And don't accept UTF translations as the start of a control # state either. # # drivers/char/vt.c # 2004/08/25 17:28:51-07:00 torvalds@ppc970.osdl.org +7 -3 # vt: don't bother doing UTF translation in control states. # # And don't accept UTF translations as the start of a control # state either. # # ChangeSet # 2004/08/25 16:35:34-07:00 shemminger@osdl.org # [BRIDGE]: Fix oops when mangling and brouting and tcpdumping packets # # The ebtables brouting chain, traversed through the call # br_should_route_hook(), can alter a packet. The redirect target # does this, f.e., to change the MAC destination. # # Bart discovered this and proposed a patch; this is a revised version. # This version cleans up the handle_bridge code in net/core/dev.c as well # as getting rid of extra rcu_read_lock and only does the br_port checking # once. # # Signed-off-by: Stephen Hemminger # Signed-off-by: David S. Miller # # net/bridge/br_private.h # 2004/08/25 16:35:17-07:00 shemminger@osdl.org +1 -1 # [BRIDGE]: Fix oops when mangling and brouting and tcpdumping packets # # The ebtables brouting chain, traversed through the call # br_should_route_hook(), can alter a packet. The redirect target # does this, f.e., to change the MAC destination. # # Bart discovered this and proposed a patch; this is a revised version. # This version cleans up the handle_bridge code in net/core/dev.c as well # as getting rid of extra rcu_read_lock and only does the br_port checking # once. # # Signed-off-by: Stephen Hemminger # Signed-off-by: David S. Miller # # net/bridge/br_input.c # 2004/08/25 16:35:17-07:00 shemminger@osdl.org +23 -34 # [BRIDGE]: Fix oops when mangling and brouting and tcpdumping packets # # The ebtables brouting chain, traversed through the call # br_should_route_hook(), can alter a packet. The redirect target # does this, f.e., to change the MAC destination. # # Bart discovered this and proposed a patch; this is a revised version. # This version cleans up the handle_bridge code in net/core/dev.c as well # as getting rid of extra rcu_read_lock and only does the br_port checking # once. # # Signed-off-by: Stephen Hemminger # Signed-off-by: David S. Miller # # include/linux/if_bridge.h # 2004/08/25 16:35:17-07:00 shemminger@osdl.org +1 -1 # [BRIDGE]: Fix oops when mangling and brouting and tcpdumping packets # # The ebtables brouting chain, traversed through the call # br_should_route_hook(), can alter a packet. The redirect target # does this, f.e., to change the MAC destination. # # Bart discovered this and proposed a patch; this is a revised version. # This version cleans up the handle_bridge code in net/core/dev.c as well # as getting rid of extra rcu_read_lock and only does the br_port checking # once. # # Signed-off-by: Stephen Hemminger # Signed-off-by: David S. Miller # # ChangeSet # 2004/08/25 16:11:20-07:00 viro@www.linux.org.uk # [PATCH] mda dependency # # MDA is ISA-only ;-) # # drivers/video/console/Kconfig # 2004/08/25 10:45:00-07:00 viro@www.linux.org.uk +1 -1 # mda dependency # # ChangeSet # 2004/08/25 16:11:09-07:00 viro@www.linux.org.uk # [PATCH] usb alignment fixes # # Several places did le16_to_cpup() on misaligned address, which blows on # any little-endian platform that doesn't like misaligned reads. # # drivers/usb/net/rtl8150.c # 2004/08/25 10:44:40-07:00 viro@www.linux.org.uk +1 -1 # usb alignment fixes # # drivers/usb/misc/auerswald.c # 2004/08/25 10:44:34-07:00 viro@www.linux.org.uk +4 -3 # usb alignment fixes # # ChangeSet # 2004/08/25 16:10:57-07:00 viro@www.linux.org.uk # [PATCH] warning fix in usb/gadget/inode.c # # wrong type of return value. # # drivers/usb/gadget/inode.c # 2004/08/25 10:43:51-07:00 viro@www.linux.org.uk +2 -2 # warning fix in usb/gadget/inode.c # # ChangeSet # 2004/08/25 16:10:46-07:00 viro@www.linux.org.uk # [PATCH] signed char bugs in ixj # # Fixed assumption that char is always unsigned # # drivers/telephony/ixj.h # 2004/08/25 10:42:07-07:00 viro@www.linux.org.uk +2 -2 # signed char bugs in ixj # # ChangeSet # 2004/08/25 16:10:34-07:00 viro@www.linux.org.uk # [PATCH] killed check_region() in ixj # # Killed check_region(), fixed an old bug in ISA case (we checked the wrong # region before claiming the right one - dumb typo back in 2.4.early) # # drivers/telephony/ixj.c # 2004/08/25 10:41:51-07:00 viro@www.linux.org.uk +24 -29 # killed check_region() in ixj # # ChangeSet # 2004/08/25 16:10:22-07:00 viro@www.linux.org.uk # [PATCH] annotation of xfs sendfile # # ->sendfile() takes kernel pointer, not userland one. # # fs/xfs/linux-2.6/xfs_vnode.h # 2004/08/25 10:39:31-07:00 viro@www.linux.org.uk +1 -1 # annotation of xfs sendfile # # fs/xfs/linux-2.6/xfs_lrw.h # 2004/08/25 10:39:23-07:00 viro@www.linux.org.uk +1 -1 # annotation of xfs sendfile # # fs/xfs/linux-2.6/xfs_lrw.c # 2004/08/25 10:39:15-07:00 viro@www.linux.org.uk +1 -1 # annotation of xfs sendfile # # fs/xfs/linux-2.6/xfs_file.c # 2004/08/25 10:39:05-07:00 viro@www.linux.org.uk +1 -1 # annotation of xfs sendfile # # ChangeSet # 2004/08/25 16:10:10-07:00 viro@www.linux.org.uk # [PATCH] annotation of ki_buf # # ->ki_buf is always a userland pointer. # # include/linux/aio.h # 2004/08/25 10:38:21-07:00 viro@www.linux.org.uk +1 -1 # annotation of ki_buf # # fs/aio.c # 2004/08/25 10:38:30-07:00 viro@www.linux.org.uk +1 -1 # annotation of ki_buf # # ChangeSet # 2004/08/25 16:09:58-07:00 viro@www.linux.org.uk # [PATCH] removed bogus casts of SPIN_LOCK_UNLOCKED # # drivers/net/tulip/de4x5.c # 2004/08/25 10:34:58-07:00 viro@www.linux.org.uk +2 -2 # removed bogus casts of SPIN_LOCK_UNLOCKED # # drivers/net/tokenring/ibmtr.c # 2004/08/25 10:35:11-07:00 viro@www.linux.org.uk +1 -1 # removed bogus casts of SPIN_LOCK_UNLOCKED # # drivers/net/sundance.c # 2004/08/25 10:34:48-07:00 viro@www.linux.org.uk +1 -1 # removed bogus casts of SPIN_LOCK_UNLOCKED # # drivers/media/video/meye.c # 2004/08/25 10:34:12-07:00 viro@www.linux.org.uk +1 -1 # removed bogus casts of SPIN_LOCK_UNLOCKED # # drivers/char/sonypi.c # 2004/08/25 10:33:35-07:00 viro@www.linux.org.uk +1 -1 # removed bogus casts of SPIN_LOCK_UNLOCKED # # ChangeSet # 2004/08/25 22:38:53+01:00 rmk@flint.arm.linux.org.uk # [ADFS] Fix sparse signed bitfield warning # # include/linux/adfs_fs_i.h # 2004/08/25 22:36:47+01:00 rmk@flint.arm.linux.org.uk +1 -1 # Make "stamped" bitfield unsigned. # # ChangeSet # 2004/08/25 13:23:54-07:00 johnrose@austin.ibm.com # [PATCH] PCI Hotplug: create pci_remove_bus() # # The following patch implements a pci_remove_bus() that can be used by # hotplug drivers for the removal of root buses. It also defines a # release function that frees the device struct for pci_bus->bridge when a # root bus class device is unregistered. # # Signed-off-by: John Rose # Signed-off-by: Greg Kroah-Hartman # # include/linux/pci.h # 2004/08/25 06:55:16-07:00 johnrose@austin.ibm.com +1 -1 # PCI Hotplug: create pci_remove_bus() # # drivers/pci/remove.c # 2004/08/25 06:55:16-07:00 johnrose@austin.ibm.com +13 -7 # PCI Hotplug: create pci_remove_bus() # # drivers/pci/probe.c # 2004/08/25 06:55:16-07:00 johnrose@austin.ibm.com +6 -0 # PCI Hotplug: create pci_remove_bus() # # ChangeSet # 2004/08/25 13:23:15-07:00 romieu@fr.zoreil.com # [PATCH] pci-driver: function documentation fix # # The returned value can not be null. Yet its description suggests differently. # # From: Francois Romieu # Signed-off-by: Andrew Morton # Signed-off-by: Greg Kroah-Hartman # # drivers/pci/pci-driver.c # 2004/08/21 14:13:40-07:00 romieu@fr.zoreil.com +3 -4 # pci-driver: function documentation fix # # ChangeSet # 2004/08/25 13:22:38-07:00 khali@linux-fr.org # [PATCH] I2C: update kernel credits/maintainers # # Signed-off-by: Jean Delvare # Signed-off-by: Greg Kroah-Hartman # # MAINTAINERS # 2004/08/25 12:21:44-07:00 khali@linux-fr.org +30 -0 # I2C: update kernel credits/maintainers # # CREDITS # 2004/08/25 12:11:37-07:00 khali@linux-fr.org +6 -0 # I2C: update kernel credits/maintainers # # ChangeSet # 2004/08/25 13:21:59-07:00 khali@linux-fr.org # [PATCH] I2C: rename in0_ref to cpu0_vid # # This patch changes all the i2c chip drivers and documentation to use the # name "cpu0_vid" instead of "in0_ref". The name "in0_ref" was an error in # the first place as motherboard manufacturers may fail to follow the chip # manufacturer's recommendation about which "in" channel to use for VCore # monitoring. # # The new name leaves room for chips able to monitor more than 1 vid # value, such as the LM93 and, to a lesser extent, the PC87360 family (all # by National Semiconductor). These chips are typically designed for # dual-CPU motherboards. # # This breaks the interface (obviously) so libsensors has been updated to # support both names. # # # Signed-off-by: Jean Delvare # Signed-off-by: Greg Kroah-Hartman # # drivers/i2c/chips/w83781d.c # 2004/08/12 12:59:39-07:00 khali@linux-fr.org +2 -2 # I2C: rename in0_ref to cpu0_vid # # drivers/i2c/chips/w83627hf.c # 2004/08/12 13:00:11-07:00 khali@linux-fr.org +2 -2 # I2C: rename in0_ref to cpu0_vid # # drivers/i2c/chips/lm85.c # 2004/08/12 13:00:12-07:00 khali@linux-fr.org +2 -2 # I2C: rename in0_ref to cpu0_vid # # drivers/i2c/chips/lm78.c # 2004/08/12 13:00:12-07:00 khali@linux-fr.org +2 -2 # I2C: rename in0_ref to cpu0_vid # # drivers/i2c/chips/it87.c # 2004/08/12 13:00:13-07:00 khali@linux-fr.org +2 -2 # I2C: rename in0_ref to cpu0_vid # # drivers/i2c/chips/asb100.c # 2004/08/12 13:00:14-07:00 khali@linux-fr.org +2 -2 # I2C: rename in0_ref to cpu0_vid # # Documentation/i2c/sysfs-interface # 2004/08/12 12:57:05-07:00 khali@linux-fr.org +1 -1 # I2C: rename in0_ref to cpu0_vid # # ChangeSet # 2004/08/25 12:45:48-07:00 greg@kroah.com # Merge kroah.com:/home/greg/linux/BK/bleed-2.6 # into kroah.com:/home/greg/linux/BK/driver-2.6 # # lib/Makefile # 2004/08/25 12:45:27-07:00 greg@kroah.com +0 -0 # Auto merged # # drivers/usb/core/urb.c # 2004/08/25 12:45:27-07:00 greg@kroah.com +0 -0 # Auto merged # # drivers/usb/core/message.c # 2004/08/25 12:45:27-07:00 greg@kroah.com +0 -0 # Auto merged # # drivers/scsi/sr.c # 2004/08/25 12:45:27-07:00 greg@kroah.com +0 -0 # Auto merged # # drivers/scsi/sd.c # 2004/08/25 12:45:27-07:00 greg@kroah.com +0 -0 # Auto merged # # drivers/char/tty_io.c # 2004/08/25 12:45:27-07:00 greg@kroah.com +0 -0 # Auto merged # # ChangeSet # 2004/08/25 12:43:29-07:00 torvalds@ppc970.osdl.org # Merge bk://linux-dj.bkbits.net/cpufreq # into ppc970.osdl.org:/home/torvalds/v2.6/linux # # arch/i386/kernel/smpboot.c # 2004/08/25 12:43:26-07:00 torvalds@ppc970.osdl.org +0 -0 # Auto merged # # ChangeSet # 2004/08/25 12:30:41-07:00 greg@kroah.com # kobject: convert struct kobject use kref. # # Signed-off-by: Greg Kroah-Hartman # # # lib/Makefile # 2004/08/25 12:30:25-07:00 greg@kroah.com +1 -4 # kobject: convert struct kobject use kref. # # Signed-off-by: Greg Kroah-Hartman # # # ChangeSet # 2004/08/25 20:13:02+01:00 rmk@flint.arm.linux.org.uk # [ARM] Fix some sparse complaints: # # Pointers are NULL not 0. # Remove obviously unnecessary iBCS2 shm stuff... we're ARM after all. # # arch/arm/kernel/sys_arm.c # 2004/08/25 20:10:44+01:00 rmk@flint.arm.linux.org.uk +2 -5 # Remove "iBCS2 emulator entry point"... its ARM after all. # # arch/arm/common/dmabounce.c # 2004/08/25 20:10:44+01:00 rmk@flint.arm.linux.org.uk +5 -5 # Pointers are NULL not 0. # # ChangeSet # 2004/08/25 10:46:37-07:00 icampbell@arcom.com # [PATCH] MTD: Additional JEDEC device types # # Add support for a couple of BIOS ROM devices. # # The patch has been committed to the MTD CVS tree and adds entries to # jedec_probe.c for AMD AM29F002T, Hyundai HY29F002T and Macronix # MX29F002T parts. # # This version is slightly updated from the previous once since I # accidentally added MANUFACTURER_MACRONIX when it already existed. I # also moved the new definitions to go along with the alphabetical by # manufacturer layout of the file. # # Signed-off-by: Ian Campbell # Signed-off-by: Linus Torvalds # # drivers/mtd/chips/jedec_probe.c # 2004/08/25 02:01:59-07:00 icampbell@arcom.com +39 -1 # MTD: Additional JEDEC device types # # ChangeSet # 2004/08/25 17:43:04+01:00 tony@com.rmk.(none) # [ARM PATCH] 2040/1: Increase ARM HARDIRQ_BITS to 9, version 2 # # Patch from Tony Lindgren # # This is an updated version of patch 2004/1 to optimize for immediate constant # # include/asm-arm/hardirq.h # 2004/08/20 09:06:19+01:00 tony@com.rmk.(none) +9 -1 # [PATCH] 2040/1: Increase ARM HARDIRQ_BITS to 9, version 2 # # ChangeSet # 2004/08/25 17:39:16+01:00 buytenh@org.rmk.(none) # [ARM PATCH] 2047/1: disable NWFPE_XP on big endian # # Patch from Lennert Buytenhek # # Hi, # # gcc doesn't understand 80-bit floating point on the ARM currently, # according to the kernel's Kconfig docs, but it would seem that the # current extended double emulation code is broken for big endian # platforms. # # So, this patch disables NWFPE_XP on big endian architectures, until # someone comes round and fixes it. # # # cheers, # Lennert # # arch/arm/Kconfig # 2004/08/19 00:03:18+01:00 buytenh@org.rmk.(none) +1 -1 # [PATCH] 2047/1: disable NWFPE_XP on big endian # # ChangeSet # 2004/08/25 17:35:00+01:00 buytenh@org.rmk.(none) # [ARM PATCH] 2046/1: fix nwfpe for double arithmetic on big-endian platforms # # Patch from Lennert Buytenhek # # Hi, # # I need the patch below (against 2.6.8-rc1-ds1) to make nwfpe properly # emulate arithmetic with doubles on a big endian ARM platform. # # From reading the mailing list archives and from helpful comments I've # received from people on this list, I gather that this has come up in # the past, but it appears that Russell King was never really convinced # as to why this patch is needed. I think I understand what's going on, # and will try to explain. # # On little endian ARM, the double value 1.0 looks like this when stored # in memory in FPA word ordering: # bytes: 0x00 0x00 0xf0 0x3f 0x00 0x00 0x00 0x00 # u32s: 0x3ff00000 0x00000000 # u64: 0x000000003ff00000 # # On big endian, it looks like this: # bytes: 0x3f 0xf0 0x00 0x00 0x00 0x00 0x00 0x00 # u32s: 0x3ff00000 0x00000000 # u64: 0x3ff0000000000000 # # It appears to be this way because once upon a time, somebody decided # that the sub-words of a double will use native endian word ordering # within themselves, but the two separate words will always be stored # with the most significant one first. God knows why they did it this # way, but they did. # # Anyway. The key observation is that nwfpe internally stores double # values in the type 'float64', which is basically just a typedef for # unsigned long long. It never accesses 'float64's on the byte level # by casting pointers around or anything like that, it just uses direct # u64 arithmetic primitives (add, shift, or, and) for float64 # manipulations and that's it. # # So. For little endian platforms, 1.0 looks like: # 0x00 0x00 0xf0 0x3f 0x00 0x00 0x00 0x00 # But since nwfpe treats it as a u64, it wants it to look like: # 0x00 0x00 0x00 0x00 0x00 0x00 0xf0 0x3f # So, that's why the current code swaps the words around when getting # doubles from userspace and putting them back (see fpa11_cpdt.c, # loadDouble and storeDouble.) # # On big endian, 1.0 looks like: # 0x3f 0xf0 0x00 0x00 0x00 0x00 0x00 0x00 # Since nwfpe treats it as a u64, it wants it to look like: # 0x3f 0xf0 0x00 0x00 0x00 0x00 0x00 0x00 # Hey! That's exactly the same. So in this case, it shouldn't be # swapping the halves around. However, it currently does that swapping # unconditionally, and that's why floating point emulation messes up. # # This is how I understand things -- hope it makes sense to other people # too. # # # cheers, # Lennert # # arch/arm/nwfpe/fpa11_cpdt.c # 2004/08/18 23:52:12+01:00 buytenh@org.rmk.(none) +10 -0 # [PATCH] 2046/1: fix nwfpe for double arithmetic on big-endian platforms # # ChangeSet # 2004/08/25 17:18:55+01:00 ben-linux@org.rmk.(none) # [ARM PATCH] 2044/1: S3C2410 - missing IRQ_TICK from RTC resources # # Patch from Ben Dooks # # Fixes missing IRQ_TICK from RTC resources # # arch/arm/mach-s3c2410/devs.c # 2004/08/21 10:13:16+01:00 ben-linux@org.rmk.(none) +6 -1 # [PATCH] 2044/1: S3C2410 - missing IRQ_TICK from RTC resources # # ChangeSet # 2004/08/25 17:14:27+01:00 ben-linux@org.rmk.(none) # [ARM PATCH] 2043/1: S3C2410 update to registered devices # # Patch from Ben Dooks # # Updated all arch/arm/mach-s3c2410/mach-XXX.c files to # register default set of devices # # Added new board struct to keep this sort of info, as it # isn't possible to register platform_devices until after # the init_io functions have been called. # # arch/arm/mach-s3c2410/s3c2410.h # 2004/08/21 01:12:12+01:00 ben-linux@org.rmk.(none) +14 -1 # [PATCH] 2043/1: S3C2410 update to registered devices # # arch/arm/mach-s3c2410/s3c2410.c # 2004/08/21 02:40:26+01:00 ben-linux@org.rmk.(none) +36 -20 # [PATCH] 2043/1: S3C2410 update to registered devices # # arch/arm/mach-s3c2410/mach-vr1000.c # 2004/08/21 02:47:09+01:00 ben-linux@org.rmk.(none) +17 -6 # [PATCH] 2043/1: S3C2410 update to registered devices # # arch/arm/mach-s3c2410/mach-smdk2410.c # 2004/08/21 02:47:20+01:00 ben-linux@org.rmk.(none) +15 -1 # [PATCH] 2043/1: S3C2410 update to registered devices # # arch/arm/mach-s3c2410/mach-h1940.c # 2004/08/21 02:46:58+01:00 ben-linux@org.rmk.(none) +21 -2 # [PATCH] 2043/1: S3C2410 update to registered devices # # arch/arm/mach-s3c2410/mach-bast.c # 2004/08/21 02:45:25+01:00 ben-linux@org.rmk.(none) +20 -4 # [PATCH] 2043/1: S3C2410 update to registered devices # # ChangeSet # 2004/08/25 17:09:50+01:00 ben-linux@org.rmk.(none) # [ARM PATCH] 2042/1: S3C2410 - Clock fixes, added watchdog clock # # Patch from Ben Dooks # # Added clock definition for watchdog, and fixed it so # that clocks that cannot be enabled/disabled will be # left alone. # # Fixed typo in naming of clocks when registering # # arch/arm/mach-s3c2410/clock.c # 2004/08/21 00:32:37+01:00 ben-linux@org.rmk.(none) +10 -4 # [PATCH] 2042/1: S3C2410 - Clock fixes, added watchdog clock # # ChangeSet # 2004/08/25 14:29:22+01:00 rmk@flint.arm.linux.org.uk # [ARM] Move DMA mask-based bounce detection to dmabounce code. # # arch/arm/common/sa1111.c # 2004/08/25 14:27:11+01:00 rmk@flint.arm.linux.org.uk +2 -11 # Move DMA mask-based bounce handling detection to generic dmabounce # code. # # arch/arm/common/dmabounce.c # 2004/08/25 14:27:10+01:00 rmk@flint.arm.linux.org.uk +15 -9 # If a device has a DMA mask, use it to work out if we need to # do DMA bounce handling. If the dma range falls outside memory # covered by the DMA mask, we need to do DMA bounce handling. # # ChangeSet # 2004/08/25 13:59:55+01:00 rmk@flint.arm.linux.org.uk # [ARM] Correct dma_to_virt()/virt_to_dma() return types. # # include/asm-arm/memory.h # 2004/08/25 13:57:41+01:00 rmk@flint.arm.linux.org.uk +2 -2 # dma_to_virt() should return a void pointer. # virt_to_dma() should return a dma_addr_t. # # ChangeSet # 2004/08/24 23:39:21-07:00 paulus@samba.org # [PATCH] ppc64: better handling of H_ENTER failures # # This changes the hash insertion routines to return an error instead of # calling panic() when HV refuses to insert a HPTE (the hypervisor call to # set up a hashtable PTE is H_ENTER). # # The error is now propagated upstream, and either bad_page_fault() is # called (kernel mode) or a SIGBUS signal is forced (user mode). Some # other panic() cases are also turned into BUG_ON. # # Overall, this should provide us with better debugging data if the # problem happens, and avoids errors from userland mapping /dev/mem and # trying to use forbidden IOs (XFree ?) to bring the whole kernel down. # # Signed-off-by: Benjamin Herrenschmidt # Signed-off-by: Paul Mackerras # Signed-off-by: Linus Torvalds # # include/asm-ppc64/system.h # 2004/08/23 23:49:57-07:00 paulus@samba.org +1 -0 # ppc64: better handling of H_ENTER failures # # arch/ppc64/mm/hash_utils.c # 2004/08/23 23:49:57-07:00 paulus@samba.org +24 -7 # ppc64: better handling of H_ENTER failures # # arch/ppc64/mm/hash_low.S # 2004/08/23 23:49:57-07:00 paulus@samba.org +5 -1 # ppc64: better handling of H_ENTER failures # # arch/ppc64/kernel/pSeries_lpar.c # 2004/08/24 00:29:18-07:00 paulus@samba.org +8 -16 # ppc64: better handling of H_ENTER failures # # arch/ppc64/kernel/head.S # 2004/08/23 23:51:40-07:00 paulus@samba.org +14 -0 # ppc64: better handling of H_ENTER failures # # ChangeSet # 2004/08/24 23:35:36-07:00 torvalds@ppc970.osdl.org # Use "insert_resource()" to add the PCI resources to the # resource tree. # # In contrast to the old "request_resource()", this allows # us to add a resource even when firmware (ACPI) has marked # part of it as being in use. # # arch/i386/pci/i386.c # 2004/08/24 23:35:30-07:00 torvalds@ppc970.osdl.org +1 -1 # Use "insert_resource()" to add the PCI resources to the # resource tree. # # In contrast to the old "request_resource()", this allows # us to add a resource even when firmware (ACPI) has marked # part of it as being in use. # # ChangeSet # 2004/08/24 23:35:02-04:00 akpm@osdl.org # [PATCH] via-rhine: small fixes # # From: Roger Luethi # # - remove Rhine model names (per Jeff's request) # - remove redundant calls to clear MII cmd # - fill some rhine_private fields earlier # # Signed-off-by: Roger Luethi # Signed-off-by: Andrew Morton # # drivers/net/via-rhine.c # 2004/08/24 22:18:35-04:00 akpm@osdl.org +16 -36 # via-rhine: small fixes # # ChangeSet # 2004/08/24 23:34:52-04:00 akpm@osdl.org # [PATCH] via-rhine: de-isolate PHY # # From: Roger Luethi # # PHYs may come up isolated. Make sure we can send data to them. This code # section needs a clean-up, but I prefer to merge this fix in isolation. # # Report and suggested fix by Tam, Ming Dat (Tommy). # # Signed-off-by: Roger Luethi # Signed-off-by: Andrew Morton # # drivers/net/via-rhine.c # 2004/08/24 22:18:35-04:00 akpm@osdl.org +3 -0 # via-rhine: de-isolate PHY # # ChangeSet # 2004/08/24 23:34:42-04:00 akpm@osdl.org # [PATCH] via-rhine: suspend/resume support # # From: Roger Luethi # # From: Arkadiusz Miskiewicz # # Signed-off-by: Arkadiusz Miskiewicz # Signed-off-by: Roger Luethi # Signed-off-by: Andrew Morton # # drivers/net/via-rhine.c # 2004/08/24 22:18:35-04:00 akpm@osdl.org +65 -0 # via-rhine: suspend/resume support # # ChangeSet # 2004/08/24 23:34:32-04:00 akpm@osdl.org # [PATCH] netdrv gianfar: fix printk output # # From: Kumar Gala # # Fix usage of printk on the output of mac address. # # Signed-off-by: Kumar Gala # Signed-off-by: Andrew Morton # # drivers/net/gianfar.c # 2004/08/24 22:18:40-04:00 akpm@osdl.org +2 -2 # netdrv gianfar: fix printk output # # ChangeSet # 2004/08/24 23:34:20-04:00 akpm@osdl.org # [PATCH] Typo in drivers/net/dl2k.h # # From: Alexander Shatohin # # # # Signed-off-by: Andrew Morton # # drivers/net/dl2k.h # 2004/08/24 22:18:37-04:00 akpm@osdl.org +1 -1 # Typo in drivers/net/dl2k.h # # ChangeSet # 2004/08/24 23:34:10-04:00 akpm@osdl.org # [PATCH] 8139too: be sure to progress during rtl8139_rx() # # From: Francois Romieu # # If the Rx buffer gets corrupted or the FIFO hangs in new interesting ways, # this code prevents the driver from looping in ksoftirqd context without # making any progress. # # Signed-off-by: Francois Romieu # Signed-off-by: Andrew Morton # # drivers/net/8139too.c # 2004/08/24 22:18:37-04:00 akpm@osdl.org +24 -1 # 8139too: be sure to progress during rtl8139_rx() # # ChangeSet # 2004/08/24 23:34:00-04:00 akpm@osdl.org # [PATCH] 8139too: Rx fifo/overflow recovery # # From: Francois Romieu # # This patch allows to update the interrupt status register after an Rx # overflow or a Rx fifo error even when the Rx buffer contains no packet. # The update must be kept in the packet processing loop to prevent an Rx # error storm. As an interesting behavior, the status of the interrupt # status register must not be read early. # # Signed-off-by: Francois Romieu # Signed-off-by: Andrew Morton # # drivers/net/8139too.c # 2004/08/24 22:18:36-04:00 akpm@osdl.org +26 -15 # 8139too: Rx fifo/overflow recovery # # ChangeSet # 2004/08/24 23:33:49-04:00 akpm@osdl.org # [PATCH] via-velocity: wrong module name in Kconfig documentation # # From: Francois Romieu # # Copy/paste abuse. # # Signed-off-by: Andrew Morton # # drivers/net/Kconfig # 2004/08/24 22:18:36-04:00 akpm@osdl.org +1 -1 # via-velocity: wrong module name in Kconfig documentation # # ChangeSet # 2004/08/24 23:33:39-04:00 akpm@osdl.org # [PATCH] drivers/net/wan/cycx_x25.c:189: warning: conflicting types for built-in function 'log2' # # From: Jesper Juhl # # To silence the warning in $subject, rename log2 to cycx_log2 in this file # to remove the clash, so there's no doubt that this file uses it's own # defined log2 function. # # Signed-off-by: Jesper Juhl # Signed-off-by: Andrew Morton # # drivers/net/wan/cycx_x25.c # 2004/08/24 22:18:34-04:00 akpm@osdl.org +3 -3 # drivers/net/wan/cycx_x25.c:189: warning: conflicting types for built-in function 'log2' # # ChangeSet # 2004/08/24 23:26:50-04:00 akpm@osdl.org # [PATCH] fix net/hamradio/dmascc with gcc 3.4 # # From: Adrian Bunk # # drivers/net/hamradio/dmascc.c: In function `scc_isr': # drivers/net/hamradio/dmascc.c:250: sorry, unimplemented: inlining # failed in call to 'z8530_isr': function body not available # drivers/net/hamradio/dmascc.c:969: sorry, unimplemented: called from # here # drivers/net/hamradio/dmascc.c:250: sorry, unimplemented: inlining # failed in call to 'z8530_isr': function body not available # drivers/net/hamradio/dmascc.c:978: sorry, unimplemented: called from # here # # Signed-off-by: Adrian Bunk # Signed-off-by: Andrew Morton # # drivers/net/hamradio/dmascc.c # 2004/08/24 22:18:35-04:00 akpm@osdl.org +144 -146 # fix net/hamradio/dmascc with gcc 3.4 # # ChangeSet # 2004/08/24 23:26:40-04:00 akpm@osdl.org # [PATCH] sk98lin/skge.c doesn't compile with PROC_FS=n # # From: Adrian Bunk # # drivers/net/sk98lin/skge.c: In function `skge_remove_one': # drivers/net/sk98lin/skge.c:5116: warning: implicit declaration of function `remove_proc_entry' # drivers/net/sk98lin/skge.c:5116: `pSkRootDir' undeclared (first use in this function) # drivers/net/sk98lin/skge.c:5116: (Each undeclared identifier is reported only once # drivers/net/sk98lin/skge.c:5116: for each function it appears in.) # drivers/net/sk98lin/skge.c: In function `skge_init': # drivers/net/sk98lin/skge.c:5188: `SK_Root_Dir_entry' undeclared (first use in this function) # # Signed-off-by: Adrian Bunk # Signed-off-by: Andrew Morton # # drivers/net/sk98lin/skge.c # 2004/08/24 22:18:35-04:00 akpm@osdl.org +1 -4 # sk98lin/skge.c doesn't compile with PROC_FS=n # # ChangeSet # 2004/08/24 23:26:28-04:00 akpm@osdl.org # [PATCH] via-velocity: more inetaddr_notifier fix # # From: Francois Romieu # # There is no guarantee that the event which gets passed is associated to a # via-velocity device, thus preventing to dereference dev->priv as if it # always was a struct velocity_info *. The via-velocity devices are kept in # a module private list for comparison. # # Signed-off-by: Francois Romieu # Signed-off-by: Andrew Morton # # drivers/net/via-velocity.h # 2004/08/24 22:18:34-04:00 akpm@osdl.org +1 -2 # via-velocity: more inetaddr_notifier fix # # drivers/net/via-velocity.c # 2004/08/24 22:18:34-04:00 akpm@osdl.org +54 -18 # via-velocity: more inetaddr_notifier fix # # ChangeSet # 2004/08/24 23:26:18-04:00 akpm@osdl.org # [PATCH] ixgb_main.c: fix inline compile errors # # From: Adrian Bunk # # drivers/net/ixgb/ixgb_main.c: In function `ixgb_up': # drivers/net/ixgb/ixgb_main.c:86: sorry, unimplemented: inlining failed # in call to 'ixgb_irq_enable': function body not available # drivers/net/ixgb/ixgb_main.c:234: sorry, unimplemented: called from here # # Signed-off-by: Adrian Bunk # Signed-off-by: Andrew Morton # # drivers/net/ixgb/ixgb_main.c # 2004/08/24 22:18:34-04:00 akpm@osdl.org +66 -66 # ixgb_main.c: fix inline compile errors # # ChangeSet # 2004/08/24 23:26:07-04:00 akpm@osdl.org # [PATCH] net/tulip/dmfe.c: gcc-3.5 fixes # # From: Adrian Bunk # # CC drivers/net/tulip/dmfe.o # drivers/net/tulip/dmfe.c: In function `dmfe_rx_packet': # drivers/net/tulip/dmfe.c:323: sorry, unimplemented: inlining failed in # call to 'cal_CRC': function body not available # drivers/net/tulip/dmfe.c:936: sorry, unimplemented: called from here # make[3]: *** [drivers/net/tulip/dmfe.o] Error 1 # # Signed-off-by: Adrian Bunk # Signed-off-by: Andrew Morton # # drivers/net/tulip/dmfe.c # 2004/08/24 22:18:33-04:00 akpm@osdl.org +15 -15 # net/tulip/dmfe.c: gcc-3.5 fixes # # ChangeSet # 2004/08/24 23:25:57-04:00 akpm@osdl.org # [PATCH] net/rrunner.c: gcc-3.5 fixes # # From: Adrian Bunk # # CC drivers/net/rrunner.o # drivers/net/rrunner.c: In function `rr_timer': # drivers/net/rrunner.h:846: sorry, unimplemented: inlining failed in call # to 'rr_raz_tx': function body not available # drivers/net/rrunner.c:1155: sorry, unimplemented: called from here # drivers/net/rrunner.h:847: sorry, unimplemented: inlining failed in call # to 'rr_raz_rx': function body not available # drivers/net/rrunner.c:1156: sorry, unimplemented: called from here # make[2]: *** [drivers/net/rrunner.o] Error 1 # # Signed-off-by: Adrian Bunk # Signed-off-by: Andrew Morton # # drivers/net/rrunner.c # 2004/08/24 22:18:33-04:00 akpm@osdl.org +43 -43 # net/rrunner.c: gcc-3.5 fixes # # ChangeSet # 2004/08/24 23:25:47-04:00 akpm@osdl.org # [PATCH] net/hamachi.c: gcc-3.5 build fixes # # From: Adrian Bunk # # CC drivers/net/hamachi.o # drivers/net/hamachi.c: In function `hamachi_interrupt': # drivers/net/hamachi.c:562: sorry, unimplemented: inlining failed in call # to 'hamachi_rx': function body not available # drivers/net/hamachi.c:1402: sorry, unimplemented: called from here # make[2]: *** [drivers/net/hamachi.o] Error 1 # # Signed-off-by: Adrian Bunk # Signed-off-by: Andrew Morton # # drivers/net/hamachi.c # 2004/08/24 22:18:33-04:00 akpm@osdl.org +1 -1 # net/hamachi.c: gcc-3.5 build fixes # # ChangeSet # 2004/08/24 23:25:36-04:00 akpm@osdl.org # [PATCH] net/smc9194.c: fix gcc-3.5 inline compile errors # # From: Adrian Bunk # # CC drivers/net/smc9194.o # drivers/net/smc9194.c: In function `smc_interrupt': # drivers/net/smc9194.c:278: sorry, unimplemented: inlining failed in call # to 'smc_rcv': function body not available # drivers/net/smc9194.c:1254: sorry, unimplemented: called from here # drivers/net/smc9194.c:283: sorry, unimplemented: inlining failed in call # to 'smc_tx': function body not available # drivers/net/smc9194.c:1258: sorry, unimplemented: called from here # make[2]: *** [drivers/net/smc9194.o] Error 1 # # Signed-off-by: Adrian Bunk # Signed-off-by: Andrew Morton # # drivers/net/smc9194.c # 2004/08/24 22:18:33-04:00 akpm@osdl.org +128 -127 # net/smc9194.c: fix gcc-3.5 inline compile errors # # ChangeSet # 2004/08/24 23:25:26-04:00 akpm@osdl.org # [PATCH] e1000 inlining fix # # From: Nick Orlov # # e1000 fixes for gcc-3.4.1 # # Signed-off-by: Andrew Morton # # drivers/net/e1000/e1000_main.c # 2004/08/24 22:18:32-04:00 akpm@osdl.org +6 -6 # e1000 inlining fix # # ChangeSet # 2004/08/24 23:25:15-04:00 akpm@osdl.org # [PATCH] e1000 build fix # # drivers/net/e1000/e1000_main.c: In function `e1000_up': # drivers/net/e1000/e1000_main.c:136: sorry, unimplemented: inlining failed # in call to 'e1000_irq_enable': function body not available # drivers/net/e1000/e1000_main.c:274: sorry, unimplemented: called from here # # # Signed-off-by: Andrew Morton # # drivers/net/e1000/e1000_main.c # 2004/08/24 22:18:32-04:00 akpm@osdl.org +2 -2 # e1000 build fix # # ChangeSet # 2004/08/24 23:25:05-04:00 akpm@osdl.org # [PATCH] sk98lin procfs fix # # From: Christoph Hellwig # # sk98line tries to register a procfile with the interfacename of the struct # net_device. The patch below (ontop of the previous one) makes it work # unless you change the interface name manually, but as Linux explicitly # allows that the interface is fundamentally broken and probably should just # go away. # # Signed-off-by: Andrew Morton # # drivers/net/sk98lin/skge.c # 2004/08/24 22:18:31-04:00 akpm@osdl.org +4 -1 # sk98lin procfs fix # # ChangeSet # 2004/08/24 23:24:55-04:00 akpm@osdl.org # [PATCH] R8169_NAPI help text # # From: Adrian Bunk # # Signed-off-by: Adrian Bunk # Signed-off-by: Andrew Morton # # drivers/net/Kconfig # 2004/08/24 22:18:31-04:00 akpm@osdl.org +13 -1 # R8169_NAPI help text # # ChangeSet # 2004/08/24 17:20:56-07:00 tgraf@suug.ch # [NET]: Device mtu/txqlen/ifmap via rtnetlink. # # Signed-off-by: Thomas Graf # Signed-off-by: David S. Miller # # net/core/rtnetlink.c # 2004/08/24 17:20:27-07:00 tgraf@suug.ch +74 -11 # [NET]: Device mtu/txqlen/ifmap via rtnetlink. # # include/linux/rtnetlink.h # 2004/08/24 17:20:27-07:00 tgraf@suug.ch +4 -0 # [NET]: Device mtu/txqlen/ifmap via rtnetlink. # # ChangeSet # 2004/08/24 17:10:20-07:00 shemminger@osdl.org # [NET]: Another cleanup in netif_receive_skb() # # Move rcu_read_lock up a little, since it needs to be # done in both branches anyway. Also whitespace fix. # # Signed-off-by: Stephen Hemminger # Signed-off-by: David S. Miller # # ChangeSet # 2004/08/24 17:08:33-07:00 shemminger@osdl.org # [NET]: deliver_skb() cleanup # # Cleanup of deliver_skb: get rid of unused argument and use it # in the NET_CLS_ACT hook. # # Signed-off-by: Stephen Hemminger # Signed-off-by: David S. Miller # # ChangeSet # 2004/08/24 17:03:36-07:00 herbert@gondor.apana.org.au # [NET]: Use pskb_expand_head() instead of skb_copy() in skb_checksum_help(). # # Here is the patch that you wanted to shoot holes at :) # # The idea is simple. None of the callers of skb_checksum are passing it # skb's which are shared. They may be cloned however. But the application # checksum is always in the skb header so there is no need to linearise it. # # Supposing all these assumptions are correct, then we can avoid the overhead # of skb_copy() and get away with pskb_expand_head(). # # If the assumption is wrong, we will find out because # pskb_expand_head() will BUG() if skb_shared() is true. # # Signed-off-by: Herbert Xu # Signed-off-by: David S. Miller # # ChangeSet # 2004/08/24 16:19:31-07:00 dtor_core@ameritech.net # [PATCH] kobject: fix kobject_set_name comment. # # Signed-off-by: Dmitry Torokhov # Signed-off-by: Greg Kroah-Hartman # # ChangeSet # 2004/08/24 22:36:35+02:00 sam@mars.ravnborg.org # kbuild: fix cc-version # # cc-version needs to use $(shell to get the gcc version. # Before if gave the following error when building the kernel: # # /bin/sh: line 1: [: too many arguments # # And all checks for gcc version were broken. # # Signed-off-by: Sam Ravnborg # # Makefile # 2004/08/24 22:34:30+02:00 sam@mars.ravnborg.org +2 -2 # fix cc-version # # ChangeSet # 2004/08/24 22:24:31+02:00 sam@mars.ravnborg.org # Merge mars.ravnborg.org:/home/sam/bk/linux-2.6 # into mars.ravnborg.org:/home/sam/bk/kbuild # # arch/arm/kernel/Makefile # 2004/08/24 22:24:23+02:00 sam@mars.ravnborg.org +0 -0 # Auto merged # # arch/arm/Makefile # 2004/08/24 22:24:23+02:00 sam@mars.ravnborg.org +0 -0 # Auto merged # # arch/arm/Kconfig # 2004/08/24 22:24:23+02:00 sam@mars.ravnborg.org +0 -0 # Auto merged # # ChangeSet # 2004/08/24 21:15:27+01:00 davej@redhat.com # [CPUFREQ] Remove fsb argument from longhauls calc_speed() # It's being passed a global everywhere, so it may as well directly reference it. # # Signed-off-by: Dave Jones # # arch/i386/kernel/cpu/cpufreq/longhaul.c # 2004/08/24 21:15:16+01:00 davej@redhat.com +8 -8 # [CPUFREQ] Remove fsb argument from longhauls calc_speed() # It's being passed a global everywhere, so it may as well directly reference it. # # Signed-off-by: Dave Jones # # ChangeSet # 2004/08/24 12:43:49-07:00 torvalds@ppc970.osdl.org # Merge bk://kernel.bkbits.net/davem/net-2.6 # into ppc970.osdl.org:/home/torvalds/v2.6/linux # # security/selinux/hooks.c # 2004/08/24 12:43:46-07:00 torvalds@ppc970.osdl.org +0 -0 # Auto merged # # ChangeSet # 2004/08/24 12:40:58-07:00 torvalds@ppc970.osdl.org # Merge bk://ppc.bkbits.net/for-linus-ppc # into ppc970.osdl.org:/home/torvalds/v2.6/linux # # kernel/sysctl.c # 2004/08/24 12:40:55-07:00 torvalds@ppc970.osdl.org +0 -0 # Auto merged # # arch/ppc/Kconfig # 2004/08/24 12:40:55-07:00 torvalds@ppc970.osdl.org +0 -0 # Auto merged # # Documentation/kernel-parameters.txt # 2004/08/24 12:40:54-07:00 torvalds@ppc970.osdl.org +0 -0 # Auto merged # # ChangeSet # 2004/08/24 12:33:27-07:00 axboe@suse.de # [PATCH] GPCMD_SEND_CUE_SHEET missing in scsi_ioctl # # Forgot one command, GPCMD_SEND_CUE_SHEET is also ok for write open. # # Signed-off-by: Jens Axboe # Signed-off-by: Linus Torvalds # # drivers/block/scsi_ioctl.c # 2004/08/24 06:10:37-07:00 axboe@suse.de +1 -0 # GPCMD_SEND_CUE_SHEET missing in scsi_ioctl # # ChangeSet # 2004/08/24 12:29:18-07:00 viro@parcelfarce.linux.theplanet.co.uk # [PATCH] /dev/ptmx open() fixes # # If tty_open() fails for a normal serial device, we end up doing cleanups # that should only happen for failed open of /dev/ptmx. The results are # not pretty - devpts et.al. end up very confused. That's what gave # problems with ptmx. # # This splits ptmx file_operations from the normal case and cleans up both # tty_open() and (new) ptmx_open(). Survived serious beating. # # drivers/char/tty_io.c # 2004/08/10 01:31:45-07:00 viro@parcelfarce.linux.theplanet.co.uk +77 -56 # /dev/ptmx open() fixes # # ChangeSet # 2004/08/24 12:29:06-07:00 wli@holomorphy.com # [PATCH] Missing free_area_init_node() conversions # # Update architectures for the free_area_init_node() API change. # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # arch/v850/kernel/setup.c # 2004/08/24 11:05:57-07:00 wli@holomorphy.com +2 -2 # Missing free_area_init_node() conversions # # arch/sh64/mm/init.c # 2004/08/24 11:05:57-07:00 wli@holomorphy.com +2 -2 # Missing free_area_init_node() conversions # # arch/sh/mm/init.c # 2004/08/24 11:05:57-07:00 wli@holomorphy.com +2 -2 # Missing free_area_init_node() conversions # # arch/ppc64/mm/numa.c # 2004/08/24 11:06:27-07:00 wli@holomorphy.com +5 -6 # Missing free_area_init_node() conversions # # arch/cris/arch-v10/mm/init.c # 2004/08/24 11:05:57-07:00 wli@holomorphy.com +1 -1 # Missing free_area_init_node() conversions # # arch/arm26/mm/init.c # 2004/08/24 11:05:57-07:00 wli@holomorphy.com +2 -2 # Missing free_area_init_node() conversions # # ChangeSet # 2004/08/24 12:28:55-07:00 trond.myklebust@fys.uio.no # [PATCH] Undo broken FH conversion that broke nfsroot compile # # That conversion to nfs_fh_copy() is bogus since we're not copying into # an nfs_fh anyway. Just revert it. # # fs/nfs/nfsroot.c # 2004/08/24 10:18:32-07:00 trond.myklebust@fys.uio.no +4 -2 # Undo broken FH conversion that broke nfsroot compile # # ChangeSet # 2004/08/24 21:23:46+02:00 sam@mars.ravnborg.org # Merge mars.ravnborg.org:/home/sam/bk/linux-2.6 # into mars.ravnborg.org:/home/sam/bk/kbuild # # arch/arm/kernel/Makefile # 2004/08/24 21:23:37+02:00 sam@mars.ravnborg.org +0 -0 # Auto merged # # arch/arm/Makefile # 2004/08/24 21:23:37+02:00 sam@mars.ravnborg.org +0 -0 # Auto merged # # arch/arm/Kconfig # 2004/08/24 21:23:37+02:00 sam@mars.ravnborg.org +0 -0 # Auto merged # # ChangeSet # 2004/08/24 11:46:22-07:00 bunk@fs.tum.de # [PATCH] Alex DeVries has moved # # The patch below replaces all occurences of two bouncing email addresses of # Alex deVries in the kernel with his current address. # # It's already ACK'ed by Alex deVries. # # Signed-off-by: Adrian Bunk # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # sound/oss/harmony.c # 2004/08/24 02:09:07-07:00 bunk@fs.tum.de +2 -2 # Alex DeVries has moved # # drivers/parisc/superio.c # 2004/08/24 02:09:07-07:00 bunk@fs.tum.de +1 -1 # Alex DeVries has moved # # drivers/parisc/lasi.c # 2004/08/24 02:09:07-07:00 bunk@fs.tum.de +1 -1 # Alex DeVries has moved # # drivers/input/serio/gscps2.c # 2004/08/24 02:09:07-07:00 bunk@fs.tum.de +1 -1 # Alex DeVries has moved # # arch/parisc/kernel/hardware.c # 2004/08/24 02:09:07-07:00 bunk@fs.tum.de +1 -1 # Alex DeVries has moved # # CREDITS # 2004/08/24 02:09:07-07:00 bunk@fs.tum.de +1 -1 # Alex DeVries has moved # # ChangeSet # 2004/08/24 11:46:09-07:00 davej@redhat.com # [PATCH] describe Intel cache descriptors. # # Describe what the Intel cache descriptors actually mean in comments. Taken # from 24151827.pdf. # # Signed-off-by: Dave Jones # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # arch/i386/kernel/cpu/intel.c # 2004/08/24 02:09:07-07:00 davej@redhat.com +38 -38 # describe Intel cache descriptors. # # ChangeSet # 2004/08/24 11:45:58-07:00 arjanv@redhat.com # [PATCH] Fix fs/locks.c init order # # The patch below fixes an interesting oddity we're seeing with fedora core # development (where we recently started using udev heavily); basically right # now filelock_init() is a module_init(), eg runs late. However that breaks # down because there are earlier /sbin/hotplug callouts, which with udev, do # locking operations. When that happens the kernel oopses because the slabs # for file locks aren't initialized yet. # # Solution: initialize this way early. It's only a kmem_cache_create after # all, so can happen early. # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # fs/locks.c # 2004/08/24 02:09:06-07:00 arjanv@redhat.com +1 -1 # Fix fs/locks.c init order # # ChangeSet # 2004/08/24 11:45:48-07:00 olh@suse.de # [PATCH] remove obsolete zero-paged in Documentation/sysctl/kernel.txt # # This entry was removed during 2.5 development. # # Signed-off-by: Olaf Hering # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # Documentation/sysctl/kernel.txt # 2004/08/24 02:09:06-07:00 olh@suse.de +0 -9 # remove obsolete zero-paged in Documentation/sysctl/kernel.txt # # ChangeSet # 2004/08/24 11:45:37-07:00 olh@suse.de # [PATCH] remove obsolete htab-reclaim in Documentation/sysctl/kernel.txt # # This entry is long gone, even 2.4 doesnt have it anymore. # # Signed-off-by: Olaf Hering # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # Documentation/sysctl/kernel.txt # 2004/08/24 02:09:06-07:00 olh@suse.de +0 -9 # remove obsolete htab-reclaim in Documentation/sysctl/kernel.txt # # ChangeSet # 2004/08/24 11:45:25-07:00 hch@lst.de # [PATCH] inode time update funnies in ncpfs # # ncfpfs seems to update inode times by hand everywhere instead of using # the proper helpers. This means: # # - the atime updates in mmap() and read() seems to miss various checks # upodate_atime or one of the wrappers does. Also it doesn't mark the # inode dirty. # - in write() you update mtime and _a_time instead of ctime as expected, # also the usual checks and optimizations are missing. # # In addition the fops contain some bogus checks like for a refular file (but # the fops are only used of ISREG files) and inode->i_sb although that is # guranteed to be non-zero. # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # fs/ncpfs/mmap.c # 2004/08/24 02:09:06-07:00 hch@lst.de +3 -7 # inode time update funnies in ncpfs # # fs/ncpfs/file.c # 2004/08/24 02:09:06-07:00 hch@lst.de +5 -16 # inode time update funnies in ncpfs # # ChangeSet # 2004/08/24 11:45:14-07:00 amgta@yacht.ocn.ne.jp # [PATCH] show Active/Inactive on per-node meminfo # # The patch below enable to display the size of Active/Inactive pages on # per-node meminfo (/sys/devices/system/node/node%d/meminfo) like # /proc/meminfo. # # By a little change to procps, "vmstat -a" can show these statistics about # particular node. # # From: mita akinobu # # get_zone_counts() is used by max_sane_readahead(), and # max_sane_readahead() is often called in filemap_nopage(). # # Signed-off-by: Akinobu Mita # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # mm/readahead.c # 2004/08/24 02:09:05-07:00 amgta@yacht.ocn.ne.jp +1 -1 # show Active/Inactive on per-node meminfo # # mm/page_alloc.c # 2004/08/24 02:09:05-07:00 amgta@yacht.ocn.ne.jp +23 -5 # show Active/Inactive on per-node meminfo # # include/linux/mmzone.h # 2004/08/24 02:09:05-07:00 amgta@yacht.ocn.ne.jp +2 -0 # show Active/Inactive on per-node meminfo # # drivers/base/node.c # 2004/08/24 02:09:05-07:00 amgta@yacht.ocn.ne.jp +10 -0 # show Active/Inactive on per-node meminfo # # ChangeSet # 2004/08/24 11:45:02-07:00 tim@physik3.uni-rostock.de # [PATCH] Fix bad URL in BSD acct help entry # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # init/Kconfig # 2004/08/24 02:09:05-07:00 tim@physik3.uni-rostock.de +1 -1 # Fix bad URL in BSD acct help entry # # ChangeSet # 2004/08/24 11:44:50-07:00 tytso@mit.edu # [PATCH] /dev/random: Remove RNDGETPOOL ioctl # # Recently, someone has kvetched that RNDGETPOOL is a "security # vulnerability". Never mind that it is superuser only, and with superuser # privs you could load a nasty kernel module, or read the entropy pool out of # /dev/mem directly, but they are nevertheless still spreading FUD. # # In any case, no one is using it (it was there for debugging purposes only), # so we can remove it as dead code. # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # drivers/char/random.c # 2004/08/24 02:09:05-07:00 tytso@mit.edu +1 -36 # /dev/random: Remove RNDGETPOOL ioctl # # ChangeSet # 2004/08/24 11:44:39-07:00 tytso@mit.edu # [PATCH] /dev/random: Use separate entropy store for /dev/urandom # # This patch adds a separate pool for use with /dev/urandom. This prevents a # /dev/urandom read from being able to completely drain the entropy in the # /dev/random pool, and also makes it much more difficult for an attacker to # carry out a state extension attack. # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # drivers/char/random.c # 2004/08/24 02:09:05-07:00 tytso@mit.edu +27 -9 # /dev/random: Use separate entropy store for /dev/urandom # # ChangeSet # 2004/08/24 11:44:27-07:00 tytso@mit.edu # [PATCH] /dev/random: Add pool name to entropy store # # This adds a pool name to the entropy_store data structure, which simplifies # the debugging code, and makes the code more generic for adding additional # entropy pools. # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # drivers/char/random.c # 2004/08/24 02:09:04-07:00 tytso@mit.edu +15 -21 # /dev/random: Add pool name to entropy store # # ChangeSet # 2004/08/24 11:44:18-07:00 tytso@mit.edu # [PATCH] dev/random: Fix latency in rekeying sequence number # # Based on reports from Ingo's Latency Tracer that the TCP sequence number # rekey code is causing latency problems, I've moved the sequence number # rekey to be done out of a workqueue. # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # drivers/char/random.c # 2004/08/24 02:09:04-07:00 tytso@mit.edu +16 -11 # dev/random: Fix latency in rekeying sequence number # # ChangeSet # 2004/08/24 11:44:06-07:00 akpm@osdl.org # [PATCH] file_ra_state_init speedup # # Marcelo points out that this function's main caller already memsets the # structure, so avoid doing it again. # # Also, an earlier knfsd patch withdrew file_ra_state_init()'s other caller, so # unexport this function. # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # mm/readahead.c # 2004/08/24 02:09:04-07:00 akpm@osdl.org +2 -3 # file_ra_state_init speedup # # ChangeSet # 2004/08/24 11:43:55-07:00 ramon.rey@hispalinux.es # [PATCH] Firmware Loader is orphan # # The author and maintainer of the firmware loader died in May. # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # MAINTAINERS # 2004/08/24 02:09:04-07:00 ramon.rey@hispalinux.es +1 -3 # Firmware Loader is orphan # # CREDITS # 2004/08/24 02:09:04-07:00 ramon.rey@hispalinux.es +3 -0 # Firmware Loader is orphan # # ChangeSet # 2004/08/24 11:43:44-07:00 linux@thorsten-knabe.de # [PATCH] ad1816 sound driver web page and email address # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # MAINTAINERS # 2004/08/24 02:09:03-07:00 linux@thorsten-knabe.de +2 -2 # ad1816 sound driver web page and email address # # ChangeSet # 2004/08/24 11:43:32-07:00 diegocg@teleline.es # [PATCH] ext3 documentation # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # Documentation/filesystems/ext3.txt # 2004/08/24 02:09:03-07:00 diegocg@teleline.es +58 -14 # ext3 documentation # # Documentation/filesystems/ext2.txt # 2004/08/24 02:09:03-07:00 diegocg@teleline.es +29 -5 # ext3 documentation # # ChangeSet # 2004/08/24 11:43:21-07:00 hirofumi@mail.parknet.co.jp # [PATCH] remove read-only/immutable checks from fat_truncate # # From: Christoph Hellwig # # There's two callers: # # - the truncate path via notify_change, ->setattr, vmtruncate. We # already check for permissions here at the upper level # - fat_delete_inode. This one looks bogus to me - even if we delete # an read-only or immutable inode we want to free the space allocated # by it, else you leak disk blocks. # # Signed-off-by: OGAWA Hirofumi # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # fs/fat/file.c # 2004/08/24 02:09:03-07:00 hirofumi@mail.parknet.co.jp +0 -6 # remove read-only/immutable checks from fat_truncate # # ChangeSet # 2004/08/24 11:43:09-07:00 ramon.rey@hispalinux.es # [PATCH] Update ACI MIXER DRIVER webpage # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # MAINTAINERS # 2004/08/24 02:09:03-07:00 ramon.rey@hispalinux.es +1 -1 # Update ACI MIXER DRIVER webpage # # ChangeSet # 2004/08/24 11:42:57-07:00 okir@suse.de # [PATCH] /proc/PID/cmdline truncates arguments early # # We received a bug report that /proc/PID/cmdline only shows argv[0] if the # total length of all arguments exceeds PAGE_SIZE. The problem is that # proc_pid_cmdline checks for the presence of a NUL byte at the end of the # args list, and assumes that the application did a setproctitle if there's # any other character. # # OTOH proc_pid_cmdline will read just the first PAGE_SIZE worth of arguments # at most, and if you have more arguments, it's quite likely that there won't # be a NUL byte at offset PAGE_SIZE-1. # # The attached patch fixes this. # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # fs/proc/base.c # 2004/08/24 02:09:03-07:00 okir@suse.de +1 -1 # /proc/PID/cmdline truncates arguments early # # ChangeSet # 2004/08/24 11:42:46-07:00 zach@vmware.com # [PATCH] i386-unbusy-tss cleanup # # The TSS no longer needs to be unbusied before loading the task register, since # the set_tss_desc macros set the system gate type to Available IA-32 TSS. This # obscure, uncommented legacy code can now be removed for better readability and # saves 20 bytes of code space. # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # arch/i386/kernel/cpu/common.c # 2004/08/24 02:09:02-07:00 zach@vmware.com +0 -2 # i386-unbusy-tss cleanup # # ChangeSet # 2004/08/24 11:42:34-07:00 garloff@suse.de # [PATCH] fix bio_uncopy_user() mem leak # # When using bounce buffers for SG_IO commands with unaligned buffers in # blk_rq_map_user(), we should free the pages from blk_rq_unmap_user() which # calls bio_uncopy_user() for the non-BIO_USER_MAPPED case. That function # failed to free the pages for write requests. # # So we leaked pages and you machine would go OOM. Rebooting helped ;-) # # This bug was triggered by writing audio CDs (but not on data CDs), as the # audio frames are not aligned well (2352 bytes), so the user pages don't just # get mapped. # # Bug was reported by Mathias Homan and debugged by Chris Mason + me. (Jens # is away.) # # From: Chris Mason # # Fix the leak for real # # Signed-off-by: Kurt Garloff # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # fs/bio.c # 2004/08/24 02:09:01-07:00 garloff@suse.de +11 -12 # fix bio_uncopy_user() mem leak # # ChangeSet # 2004/08/24 11:42:22-07:00 schwidefsky@de.ibm.com # [PATCH] s390: zfcp host adapter # # From: Heiko Carstens # From: Andreas Herrmann # From: Maxim Shchetynin # # zfcp host adapter changes: # - Use predefined macro to create in_recovery sysfs attributes. # - Add function to check CT_IU response. # - Fix handling of rejected ELS commands. # - Change return value of zfcp_fsf_req_sbal_get to -ERESTARTSYS in some cases. # - Return proper error code if control file upload/download failed. # - Remove dead code. # - Avoid sparse warnings. # # Signed-off-by: Martin Schwidefsky # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # drivers/s390/scsi/zfcp_sysfs_unit.c # 2004/08/24 02:09:01-07:00 schwidefsky@de.ibm.com +4 -25 # s390: zfcp host adapter # # drivers/s390/scsi/zfcp_sysfs_port.c # 2004/08/24 02:09:01-07:00 schwidefsky@de.ibm.com +6 -27 # s390: zfcp host adapter # # drivers/s390/scsi/zfcp_sysfs_driver.c # 2004/08/24 02:09:01-07:00 schwidefsky@de.ibm.com +2 -2 # s390: zfcp host adapter # # drivers/s390/scsi/zfcp_sysfs_adapter.c # 2004/08/24 02:09:01-07:00 schwidefsky@de.ibm.com +11 -32 # s390: zfcp host adapter # # drivers/s390/scsi/zfcp_scsi.c # 2004/08/24 02:09:01-07:00 schwidefsky@de.ibm.com +2 -2 # s390: zfcp host adapter # # drivers/s390/scsi/zfcp_fsf.h # 2004/08/24 02:09:01-07:00 schwidefsky@de.ibm.com +4 -0 # s390: zfcp host adapter # # drivers/s390/scsi/zfcp_fsf.c # 2004/08/24 02:09:01-07:00 schwidefsky@de.ibm.com +18 -103 # s390: zfcp host adapter # # drivers/s390/scsi/zfcp_ext.h # 2004/08/24 02:09:01-07:00 schwidefsky@de.ibm.com +4 -2 # s390: zfcp host adapter # # drivers/s390/scsi/zfcp_erp.c # 2004/08/24 02:09:01-07:00 schwidefsky@de.ibm.com +62 -147 # s390: zfcp host adapter # # drivers/s390/scsi/zfcp_def.h # 2004/08/24 02:09:01-07:00 schwidefsky@de.ibm.com +13 -10 # s390: zfcp host adapter # # drivers/s390/scsi/zfcp_aux.c # 2004/08/24 02:09:01-07:00 schwidefsky@de.ibm.com +185 -20 # s390: zfcp host adapter # # ChangeSet # 2004/08/24 11:42:10-07:00 schwidefsky@de.ibm.com # [PATCH] s390: core changes # # From: Jan Glauber # From: Martin Schwidefsky # # s390 core changes: # - Use copy_siginfo_from_user32 instead of copy_from_user to get the # siginfo structure in sys32_rt_sigqueueinfo. # - Remove prototype for non-existant stop_timers function. # - Regenerate default configuration. # # Signed-off-by: Martin Schwidefsky # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # include/asm-s390/timer.h # 2004/08/24 02:09:01-07:00 schwidefsky@de.ibm.com +0 -2 # s390: core changes # # arch/s390/kernel/vtime.c # 2004/08/24 02:09:01-07:00 schwidefsky@de.ibm.com +1 -1 # s390: core changes # # arch/s390/kernel/compat_linux.c # 2004/08/24 02:09:01-07:00 schwidefsky@de.ibm.com +1 -2 # s390: core changes # # arch/s390/defconfig # 2004/08/24 02:09:01-07:00 schwidefsky@de.ibm.com +2 -2 # s390: core changes # # ChangeSet # 2004/08/24 11:41:58-07:00 rusty@rustcorp.com.au # [PATCH] fix permissions on the `tainted' sysctl # # From: Arjan van de Ven # # The patch below sets the tainted sysctl file to read only, otherwise # userspace can just overwrite/reset it. # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # kernel/sysctl.c # 2004/08/24 02:09:00-07:00 rusty@rustcorp.com.au +1 -1 # fix permissions on the `tainted' sysctl # # ChangeSet # 2004/08/24 11:41:47-07:00 pavel@ucw.cz # [PATCH] typo in laptop_mode.txt # # This patch is thanks to pavouk. # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # Documentation/laptop-mode.txt # 2004/08/24 02:09:00-07:00 pavel@ucw.cz +1 -1 # typo in laptop_mode.txt # # ChangeSet # 2004/08/24 11:41:35-07:00 pavel@ucw.cz # [PATCH] Coding style: do_this(a,b) vs. do_this(a, b) # # Coding style document is not consistent with itself on whether there # should be space after ","... This makes it standardize on ", " option. # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # Documentation/CodingStyle # 2004/08/24 11:41:29-07:00 pavel@ucw.cz +2 -2 # Coding style: do_this(a,b) vs. do_this(a, b) # # ChangeSet # 2004/08/24 11:41:24-07:00 ebiederm@xmission.com # [PATCH] fix 4K ext2fs support in 2.6 initrd's # # The ramdisk_blocksize option has been broken for quite a while in 2.6. # Making an initrd with a 4K ext2 filesystem impossible to use. # # After digging into this, the problem turned out to that rd.c was not # setting the hard sector size. There were a few secondary problems like # i_blkbits was not being set, and the number KiB in uncompressed ext2 images # was not taking into account the block size. # # I have also corrected the surrounding comments as they were not just # incorrect but misleading. # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # init/do_mounts_rd.c # 2004/08/24 11:41:17-07:00 ebiederm@xmission.com +13 -7 # fix 4K ext2fs support in 2.6 initrd's # # drivers/block/rd.c # 2004/08/24 11:41:17-07:00 ebiederm@xmission.com +7 -2 # fix 4K ext2fs support in 2.6 initrd's # # ChangeSet # 2004/08/24 11:41:13-07:00 olh@suse.de # [PATCH] compat_do_execve() fix # # For some reasons ls -l /proc/$$/exe doesnt work all time for me, # with 2.6.8.1 on ppc64. Sometimes it does, sometimes not. No pattern. # A few printks show that this check in proc_pid_readlink() triggers # an -EACCES: # # current->fsuid != inode->i_uid # # proc_pid_readlink(755) error -13 ntptrace(11408) fsuid 100 i_uid 0 0 # sys_readlink(281) ntptrace(11408) error -13 readlink # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # fs/compat.c # 2004/08/24 02:08:59-07:00 olh@suse.de +2 -0 # compat_do_execve() fix # # ChangeSet # 2004/08/24 11:41:02-07:00 kernel@cornelia-huck.de # [PATCH] Add pci dependencies to drivers/media/dvb/ttpci/Kconfig # # The drivers under drivers/media/dvb/ttpci depend on pci (especially since # they select VIDEO_SAA7146, which depends on pci). # # Signed-off-by: Cornelia Huck # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # drivers/media/dvb/ttpci/Kconfig # 2004/08/24 02:08:59-07:00 kernel@cornelia-huck.de +4 -4 # Add pci dependencies to drivers/media/dvb/ttpci/Kconfig # # ChangeSet # 2004/08/24 11:40:50-07:00 janitor@sternwelten.at # [PATCH] remove last suser() call from drivers/char/rocket.c # # Signed-off-by: Maximilian Attems # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # drivers/char/rocket.c # 2004/08/24 02:08:59-07:00 janitor@sternwelten.at +0 -4 # remove last suser() call from drivers/char/rocket.c # # ChangeSet # 2004/08/24 11:40:38-07:00 jmorris@redhat.com # [PATCH] Reduce SELinux kernel memory use on 64-bit systems # # The patch below reduces kernel memory used by SELinux policy rules by about # 37% on 64-bit systems. This is because the size of struct avtab_node is 40 # bytes on 64-bit, and defaults to a size-64 slab. # # Creating a slab cache specifically for these structs saves considerable # amounts of kernel memory on 64-bit systems with large rulesets. 'Strict' # policy has over 300k rules, while 'targeted' policy has around 3k rules. # # Here's the slabtop output with 64 and 40 byte sized slabs to show the # memory savings, for strict policy: # # 303475 303447 99% 0.06K 4975 61 19900K avtab_node # 303456 303447 99% 0.04K 3161 96 12644K avtab_node # # Also, there are 57% more objects per slab. # # Signed-off-by: James Morris # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # security/selinux/ss/services.c # 2004/08/24 02:08:59-07:00 jmorris@redhat.com +1 -0 # Reduce SELinux kernel memory use on 64-bit systems # # security/selinux/ss/avtab.h # 2004/08/24 02:08:59-07:00 jmorris@redhat.com +2 -0 # Reduce SELinux kernel memory use on 64-bit systems # # security/selinux/ss/avtab.c # 2004/08/24 02:08:59-07:00 jmorris@redhat.com +10 -2 # Reduce SELinux kernel memory use on 64-bit systems # # ChangeSet # 2004/08/24 11:40:27-07:00 sds@epoch.ncsc.mil # [PATCH] SELinux: fix name_bind audit # # This patch restores the proper auditing behavior for the name_bind check. # # Author: James Morris # Signed-off-by: Stephen Smalley # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # security/selinux/hooks.c # 2004/08/24 02:08:58-07:00 sds@epoch.ncsc.mil +1 -0 # SELinux: fix name_bind audit # # ChangeSet # 2004/08/24 11:40:15-07:00 sds@epoch.ncsc.mil # [PATCH] SElinux; defer inode security initialization # # This patch defers setting the inode security state for newly created inodes # until after policy has been loaded. # # Signed-off-by: Stephen Smalley # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # security/selinux/hooks.c # 2004/08/24 02:08:58-07:00 sds@epoch.ncsc.mil +6 -0 # SElinux; defer inode security initialization # # ChangeSet # 2004/08/24 11:40:03-07:00 sds@epoch.ncsc.mil # [PATCH] SELinux: revalidate access to controlling tty # # This patch changes the SELinux flush_unauthorized_files function to also # recheck access to the controlling tty and reset it if it is no longer # accessible under the new security context. This patch is relative to the # selinuxfs devnull patch. # # Signed-off-by: Stephen Smalley # Signed-off-by: James Morris # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # security/selinux/hooks.c # 2004/08/24 02:08:58-07:00 sds@epoch.ncsc.mil +25 -0 # SELinux: revalidate access to controlling tty # # ChangeSet # 2004/08/24 11:39:52-07:00 sds@epoch.ncsc.mil # [PATCH] SELinux: add null device node to selinuxfs, remove open_devnull # # This patch adds a null device node to selinuxfs and replaces the SELinux # open_devnull() code by simply acquiring a reference to this node each time, # based on a comment by Al Viro on lkml (see # http://marc.theaimsgroup.com/?l=linux-kernel&m=108664922032035&w=2). # # Signed-off-by: Stephen Smalley # Signed-off-by: James Morris # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # security/selinux/selinuxfs.c # 2004/08/24 02:08:57-07:00 sds@epoch.ncsc.mil +42 -2 # SELinux: add null device node to selinuxfs, remove open_devnull # # security/selinux/hooks.c # 2004/08/24 02:08:57-07:00 sds@epoch.ncsc.mil +3 -60 # SELinux: add null device node to selinuxfs, remove open_devnull # # ChangeSet # 2004/08/24 11:39:40-07:00 jeffm@suse.com # [PATCH] Fix access of files up to 4 GB support for ISO9660 filesystems # # Since the filesystem doesn't explicitly set s->s_maxbytes, seeks will fail # beyond 2^32-1, due to s->s_maxbytes being set to the default of # MAX_NON_LFS. # # Attached is the quick one liner fix. # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # fs/isofs/inode.c # 2004/08/24 02:08:57-07:00 jeffm@suse.com +1 -0 # Fix access of files up to 4 GB support for ISO9660 filesystems # # ChangeSet # 2004/08/24 11:39:28-07:00 jeffm@suse.com # [PATCH] reiserfs: xattr/acl fixes # # Here are a few fixes for bugs noticed on reiserfs-list or our own bugzilla. # # Attached is a patch that fixes several problems with xattrs/acls: # [SECURITY] Fixes the inode not getting dirtied when mode is set # via setxattr() # [CORRECTNESS] Fixes the inode not getting ctime updated when an xattr is # removed # [DATA] Fixes an issue with dcache hash colliding names in the filesystem # root caused by the d_compare to hide .reiserfs_priv. The bug # can only occur in the filesystem root, which is why we haven't # seen many (any, outside of the suse bugzilla, afaik) reports on # this. The results are that dcache operations on colliding entries # in the fs root will choose the first match rather than the # correct entry. # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # fs/reiserfs/xattr_acl.c # 2004/08/24 02:08:56-07:00 jeffm@suse.com +7 -1 # reiserfs: xattr/acl fixes # # fs/reiserfs/xattr.c # 2004/08/24 02:08:56-07:00 jeffm@suse.com +9 -2 # reiserfs: xattr/acl fixes # # ChangeSet # 2004/08/24 11:39:17-07:00 paulkf@microgate.com # [PATCH] synclink_cs.c: replace syncppp with genhdlc # # Replace syncppp interface with generic HDLC interface. Generic HDLC # provides superset of syncppp function. # # Signed-off-by: Paul Fulghum # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # drivers/char/pcmcia/synclink_cs.c # 2004/08/24 02:08:56-07:00 paulkf@microgate.com +374 -187 # synclink_cs.c: replace syncppp with genhdlc # # ChangeSet # 2004/08/24 11:39:05-07:00 paulkf@microgate.com # [PATCH] synclinkmp.c: replace syncppp with genhdlc # # Replace syncppp interface with generic HDLC interface. Generic HDLC # provides superset of syncppp function. # # Signed-off-by: Paul Fulghum # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # drivers/char/synclinkmp.c # 2004/08/24 02:08:56-07:00 paulkf@microgate.com +372 -186 # synclinkmp.c: replace syncppp with genhdlc # # ChangeSet # 2004/08/24 11:38:55-07:00 paulkf@microgate.com # [PATCH] synclink.c: replace syncppp with genhdlc # # Replace syncppp interface with generic HDLC interface. Generic HDLC # provides superset of syncppp function. # # Signed-off-by: Paul Fulghum # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # drivers/char/synclink.c # 2004/08/24 02:08:56-07:00 paulkf@microgate.com +374 -182 # synclink.c: replace syncppp with genhdlc # # ChangeSet # 2004/08/24 11:38:43-07:00 rusty@rustcorp.com.au # [PATCH] Move param section out of init area, for export of built-in module params # # When exporting the module parameters of built-in modules, we need to access # the respective struct kernel_parameters. Currently, they're freed at init # time, and obviously this can't continue to be done. So, move them out of # __init_begin and __init_end and into RODATA in asm-generic/vmlinux.lds.h. # # Signed-off-by: Rusty Russell (modified) # Signed-off-by: Dominik Brodowski # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # include/asm-um/common.lds.S # 2004/08/24 02:08:55-07:00 rusty@rustcorp.com.au +0 -4 # Move param section out of init area, for export of built-in module params # # include/asm-generic/vmlinux.lds.h # 2004/08/24 02:08:55-07:00 rusty@rustcorp.com.au +7 -0 # Move param section out of init area, for export of built-in module params # # arch/x86_64/kernel/vmlinux.lds.S # 2004/08/24 02:08:55-07:00 rusty@rustcorp.com.au +0 -3 # Move param section out of init area, for export of built-in module params # # arch/v850/kernel/vmlinux.lds.S # 2004/08/24 02:08:55-07:00 rusty@rustcorp.com.au +0 -3 # Move param section out of init area, for export of built-in module params # # arch/sparc64/kernel/vmlinux.lds.S # 2004/08/24 02:08:55-07:00 rusty@rustcorp.com.au +0 -3 # Move param section out of init area, for export of built-in module params # # arch/sparc/kernel/vmlinux.lds.S # 2004/08/24 02:08:55-07:00 rusty@rustcorp.com.au +0 -3 # Move param section out of init area, for export of built-in module params # # arch/sh64/kernel/vmlinux.lds.S # 2004/08/24 02:08:55-07:00 rusty@rustcorp.com.au +0 -3 # Move param section out of init area, for export of built-in module params # # arch/sh/kernel/vmlinux.lds.S # 2004/08/24 02:08:55-07:00 rusty@rustcorp.com.au +0 -3 # Move param section out of init area, for export of built-in module params # # arch/s390/kernel/vmlinux.lds.S # 2004/08/24 02:08:55-07:00 rusty@rustcorp.com.au +0 -3 # Move param section out of init area, for export of built-in module params # # arch/ppc64/kernel/vmlinux.lds.S # 2004/08/24 02:08:55-07:00 rusty@rustcorp.com.au +0 -6 # Move param section out of init area, for export of built-in module params # # arch/ppc/kernel/vmlinux.lds.S # 2004/08/24 02:08:55-07:00 rusty@rustcorp.com.au +0 -3 # Move param section out of init area, for export of built-in module params # # arch/parisc/kernel/vmlinux.lds.S # 2004/08/24 02:08:55-07:00 rusty@rustcorp.com.au +0 -3 # Move param section out of init area, for export of built-in module params # # arch/mips/kernel/vmlinux.lds.S # 2004/08/24 02:08:55-07:00 rusty@rustcorp.com.au +0 -3 # Move param section out of init area, for export of built-in module params # # arch/m68knommu/kernel/vmlinux.lds.S # 2004/08/24 02:08:55-07:00 rusty@rustcorp.com.au +0 -3 # Move param section out of init area, for export of built-in module params # # arch/m68k/kernel/vmlinux-sun3.lds # 2004/08/24 02:08:55-07:00 rusty@rustcorp.com.au +0 -3 # Move param section out of init area, for export of built-in module params # # arch/m68k/kernel/vmlinux-std.lds # 2004/08/24 02:08:55-07:00 rusty@rustcorp.com.au +0 -3 # Move param section out of init area, for export of built-in module params # # arch/ia64/kernel/vmlinux.lds.S # 2004/08/24 02:08:55-07:00 rusty@rustcorp.com.au +0 -6 # Move param section out of init area, for export of built-in module params # # arch/i386/kernel/vmlinux.lds.S # 2004/08/24 02:08:55-07:00 rusty@rustcorp.com.au +0 -3 # Move param section out of init area, for export of built-in module params # # arch/h8300/kernel/vmlinux.lds.S # 2004/08/24 02:08:55-07:00 rusty@rustcorp.com.au +0 -3 # Move param section out of init area, for export of built-in module params # # arch/cris/arch-v10/vmlinux.lds.S # 2004/08/24 02:08:55-07:00 rusty@rustcorp.com.au +0 -3 # Move param section out of init area, for export of built-in module params # # arch/arm26/kernel/vmlinux-arm26.lds.in # 2004/08/24 02:08:55-07:00 rusty@rustcorp.com.au +0 -3 # Move param section out of init area, for export of built-in module params # # arch/arm26/kernel/vmlinux-arm26-xip.lds.in # 2004/08/24 02:08:55-07:00 rusty@rustcorp.com.au +0 -3 # Move param section out of init area, for export of built-in module params # # arch/arm/kernel/vmlinux.lds.S # 2004/08/24 02:08:55-07:00 rusty@rustcorp.com.au +0 -3 # Move param section out of init area, for export of built-in module params # # arch/alpha/kernel/vmlinux.lds.S # 2004/08/24 02:08:55-07:00 rusty@rustcorp.com.au +0 -5 # Move param section out of init area, for export of built-in module params # # ChangeSet # 2004/08/24 11:38:29-07:00 rusty@rustcorp.com.au # [PATCH] Fix Permissions on module_param Usage # # module_param() and family take a "perms" argument; several people have # incorrectly used "644" instead of "0644". # # (I have a patch which checks for sane perms at compile time, but it bloats # modules, so I haven't included it.) # # Signed-off-by: Rusty Russell (authored) # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # fs/lockd/svc.c # 2004/08/24 02:08:54-07:00 rusty@rustcorp.com.au +4 -4 # Fix Permissions on module_param Usage # # fs/jfs/super.c # 2004/08/24 02:08:54-07:00 rusty@rustcorp.com.au +1 -1 # Fix Permissions on module_param Usage # # drivers/usb/input/ati_remote.c # 2004/08/24 02:08:54-07:00 rusty@rustcorp.com.au +2 -2 # Fix Permissions on module_param Usage # # drivers/pci/hotplug/shpchp_core.c # 2004/08/24 02:08:54-07:00 rusty@rustcorp.com.au +3 -3 # Fix Permissions on module_param Usage # # drivers/pci/hotplug/pcihp_skeleton.c # 2004/08/24 02:08:54-07:00 rusty@rustcorp.com.au +1 -1 # Fix Permissions on module_param Usage # # drivers/pci/hotplug/pciehp_core.c # 2004/08/24 02:08:54-07:00 rusty@rustcorp.com.au +3 -3 # Fix Permissions on module_param Usage # # drivers/pci/hotplug/pci_hotplug_core.c # 2004/08/24 02:08:54-07:00 rusty@rustcorp.com.au +1 -1 # Fix Permissions on module_param Usage # # drivers/pci/hotplug/cpqphp_core.c # 2004/08/24 02:08:54-07:00 rusty@rustcorp.com.au +2 -2 # Fix Permissions on module_param Usage # # drivers/pci/hotplug/cpcihp_zt5550.c # 2004/08/24 02:08:54-07:00 rusty@rustcorp.com.au +2 -2 # Fix Permissions on module_param Usage # # drivers/pci/hotplug/acpiphp_core.c # 2004/08/24 02:08:54-07:00 rusty@rustcorp.com.au +1 -1 # Fix Permissions on module_param Usage # # ChangeSet # 2004/08/24 11:38:17-07:00 rusty@rustcorp.com.au # [PATCH] Centralize i386 Constants # # __FIXADDR_TOP and PAGE_OFFSET are hardcoded in various places. I had to # change it to run the kernel under qemu-fast, so I wanted to centralize # them. # # To do this, we rename vsyscall.lds to vsyscall.lds.s, and generate it from # vsyscall.lds.S. # # Signed-off-by: Rusty Russell (created) # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # include/asm-i386/fixmap.h # 2004/08/24 02:08:54-07:00 rusty@rustcorp.com.au +12 -7 # Centralize i386 Constants # # arch/i386/kernel/vsyscall.lds.S # 2004/08/24 02:08:54-07:00 rusty@rustcorp.com.au +2 -2 # Centralize i386 Constants # # arch/i386/kernel/vmlinux.lds.S # 2004/08/24 02:08:54-07:00 rusty@rustcorp.com.au +2 -1 # Centralize i386 Constants # # arch/i386/kernel/Makefile # 2004/08/24 02:08:54-07:00 rusty@rustcorp.com.au +4 -2 # Centralize i386 Constants # # ChangeSet # 2004/08/24 11:35:14-07:00 sds@epoch.ncsc.mil # [SELINUX]: Fix bugs introduced by skb_header_pointer() changes. # # Lines assigning initial value to 'ret' were removed # erroneously. # # Signed-off-by: Stephen Smalley # Signed-off-by: David S. Miller # # security/selinux/hooks.c # 2004/08/24 11:34:56-07:00 sds@epoch.ncsc.mil +4 -2 # [SELINUX]: Fix bugs introduced by skb_header_pointer() changes. # # Lines assigning initial value to 'ret' were removed # erroneously. # # Signed-off-by: Stephen Smalley # Signed-off-by: David S. Miller # # ChangeSet # 2004/08/24 11:34:21-07:00 rusty@rustcorp.com.au # [PATCH] Read cpumasks every time when exporting through sysfs # # Paul Jackson points out that the sysfs code saves a node's cpumask in the # sysfs node, although it can change with CPU hotplug. Don't do this. # # Signed-off-by: Rusty Russell # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # include/linux/node.h # 2004/08/24 02:08:54-07:00 rusty@rustcorp.com.au +0 -1 # Read cpumasks every time when exporting through sysfs # # drivers/base/node.c # 2004/08/24 02:08:54-07:00 rusty@rustcorp.com.au +1 -2 # Read cpumasks every time when exporting through sysfs # # ChangeSet # 2004/08/24 11:34:08-07:00 anton@samba.org # [PATCH] remove cacheline alignment from inode slabs # # Most of the inode slabs are cacheline aligned. This can waste a fair # amount of memory, especially on architectures with large cacheline sizes # (eg 128 bytes). # # Alignment has a few advantages. It prevents 2 cpus from accessing 2 data # structures in the same cacheline. Since struct inodes are well over a # cacheline and there are so many of them, there is little chance we will hit # this problem if we remove the alignment. # # Alignment also ensures the maximum amount of the data structure is in the # same cacheline (instead of straddling 2 for example). The large size of # struct inode reduces this advantage. # # With this patch the inode_cache slab goes from 640 bytes to 544 bytes, and # the number that fits in a 4kB slab goes from 6 to 7 on ppc64. A number of # other inode slabs also see improvements. # # Signed-off-by: Anton Blanchard # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # fs/xfs/linux-2.6/xfs_super.c # 2004/08/24 02:08:53-07:00 anton@samba.org +1 -2 # remove cacheline alignment from inode slabs # # fs/ufs/super.c # 2004/08/24 02:08:53-07:00 anton@samba.org +1 -1 # remove cacheline alignment from inode slabs # # fs/udf/super.c # 2004/08/24 02:08:53-07:00 anton@samba.org +1 -1 # remove cacheline alignment from inode slabs # # fs/sysv/inode.c # 2004/08/24 02:08:53-07:00 anton@samba.org +1 -1 # remove cacheline alignment from inode slabs # # fs/smbfs/inode.c # 2004/08/24 02:08:53-07:00 anton@samba.org +1 -1 # remove cacheline alignment from inode slabs # # fs/romfs/inode.c # 2004/08/24 02:08:53-07:00 anton@samba.org +1 -1 # remove cacheline alignment from inode slabs # # fs/reiserfs/super.c # 2004/08/24 02:08:53-07:00 anton@samba.org +1 -1 # remove cacheline alignment from inode slabs # # fs/qnx4/inode.c # 2004/08/24 02:08:53-07:00 anton@samba.org +1 -1 # remove cacheline alignment from inode slabs # # fs/proc/inode.c # 2004/08/24 02:08:53-07:00 anton@samba.org +1 -1 # remove cacheline alignment from inode slabs # # fs/ntfs/super.c # 2004/08/24 02:08:53-07:00 anton@samba.org +1 -1 # remove cacheline alignment from inode slabs # # fs/nfs/inode.c # 2004/08/24 02:08:53-07:00 anton@samba.org +1 -1 # remove cacheline alignment from inode slabs # # fs/ncpfs/inode.c # 2004/08/24 02:08:53-07:00 anton@samba.org +1 -1 # remove cacheline alignment from inode slabs # # fs/minix/inode.c # 2004/08/24 02:08:53-07:00 anton@samba.org +1 -1 # remove cacheline alignment from inode slabs # # fs/jffs2/super.c # 2004/08/24 02:08:53-07:00 anton@samba.org +1 -1 # remove cacheline alignment from inode slabs # # fs/isofs/inode.c # 2004/08/24 02:08:53-07:00 anton@samba.org +1 -1 # remove cacheline alignment from inode slabs # # fs/inode.c # 2004/08/24 02:08:53-07:00 anton@samba.org +1 -2 # remove cacheline alignment from inode slabs # # fs/hpfs/super.c # 2004/08/24 02:08:53-07:00 anton@samba.org +1 -1 # remove cacheline alignment from inode slabs # # fs/fat/inode.c # 2004/08/24 02:08:53-07:00 anton@samba.org +1 -1 # remove cacheline alignment from inode slabs # # fs/ext3/super.c # 2004/08/24 02:08:53-07:00 anton@samba.org +1 -1 # remove cacheline alignment from inode slabs # # fs/ext2/super.c # 2004/08/24 02:08:53-07:00 anton@samba.org +1 -1 # remove cacheline alignment from inode slabs # # fs/efs/super.c # 2004/08/24 02:08:53-07:00 anton@samba.org +1 -1 # remove cacheline alignment from inode slabs # # fs/coda/inode.c # 2004/08/24 02:08:53-07:00 anton@samba.org +1 -1 # remove cacheline alignment from inode slabs # # fs/cifs/cifsfs.c # 2004/08/24 02:08:53-07:00 anton@samba.org +1 -1 # remove cacheline alignment from inode slabs # # fs/bfs/inode.c # 2004/08/24 02:08:53-07:00 anton@samba.org +1 -1 # remove cacheline alignment from inode slabs # # fs/befs/linuxvfs.c # 2004/08/24 02:08:53-07:00 anton@samba.org +1 -1 # remove cacheline alignment from inode slabs # # fs/affs/super.c # 2004/08/24 02:08:53-07:00 anton@samba.org +1 -1 # remove cacheline alignment from inode slabs # # fs/adfs/super.c # 2004/08/24 02:08:53-07:00 anton@samba.org +1 -1 # remove cacheline alignment from inode slabs # # ChangeSet # 2004/08/24 11:33:55-07:00 anton@samba.org # [PATCH] reduce size of struct dentry on 64bit # # Reduce size of struct dentry from 248 to 232 bytes on 64bit. # # - Reduce size of qstr by 8 bytes, placing int hash and int len together. # We gain a further 4 byte saving when qstr is used in struct dentry # since qstr goes from 24 to 16 bytes and the next member (d_lru) # requires 8 byte alignment (which means 4 bytes of padding). # # - Move d_mounted to the end, since char d_iname[] only requires 1 byte # alignment. This reduces struct dentry by another 4 bytes. # # With these changes the number of objects we can fit into a 4kB slab # goes from 16 to 17 on ppc64. # # Note the above assumes the architecture naturally aligns types. # # Signed-off-by: Anton Blanchard # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # include/linux/dcache.h # 2004/08/24 02:08:53-07:00 anton@samba.org +2 -2 # reduce size of struct dentry on 64bit # # ChangeSet # 2004/08/24 11:33:43-07:00 anton@samba.org # [PATCH] reduce size of struct buffer_head on 64bit # # Reduce size of buffer_head from 96 to 88 bytes on 64bit architectures by # putting b_count and b_size together. b_count will still be in the first 16 # bytes on 32bit architectures, so 16 byte cacheline machines shouldnt be # affected. # # With this change the number of objects per 4kB slab goes up from 40 to 44 # on ppc64. # # Signed-off-by: Anton Blanchard # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # include/linux/buffer_head.h # 2004/08/24 02:08:52-07:00 anton@samba.org +2 -2 # reduce size of struct buffer_head on 64bit # # ChangeSet # 2004/08/24 11:33:32-07:00 pavel@ucw.cz # [PATCH] Fix ttyS0 vs. ttyS00 confusion # # According to devices.txt, serial ports are reffered as ttyS0 (and not # ttyS00). It would be nice to use that convention in printks, too. # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # drivers/tc/zs.c # 2004/08/24 02:08:52-07:00 pavel@ucw.cz +7 -7 # Fix ttyS0 vs. ttyS00 confusion # # drivers/serial/68360serial.c # 2004/08/24 02:08:52-07:00 pavel@ucw.cz +1 -1 # Fix ttyS0 vs. ttyS00 confusion # # drivers/char/serial167.c # 2004/08/24 02:08:52-07:00 pavel@ucw.cz +1 -1 # Fix ttyS0 vs. ttyS00 confusion # # drivers/char/amiserial.c # 2004/08/24 02:08:52-07:00 pavel@ucw.cz +2 -2 # Fix ttyS0 vs. ttyS00 confusion # # arch/ppc/8xx_io/uart.c # 2004/08/24 02:08:52-07:00 pavel@ucw.cz +1 -1 # Fix ttyS0 vs. ttyS00 confusion # # arch/ia64/hp/sim/simserial.c # 2004/08/24 02:08:52-07:00 pavel@ucw.cz +1 -1 # Fix ttyS0 vs. ttyS00 confusion # # ChangeSet # 2004/08/24 11:33:20-07:00 chrisw@osdl.org # [PATCH] use simple_read_from_buffer in proc_info_read and proc_pid_attr_read # # Use simple_read_from_buffer in proc_info_read and proc_pid_attr_read. Viro # had ack'd this earlier. # # Signed-off-by: Chris Wright # Signed-off-by: Stephen Smalley # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # fs/proc/base.c # 2004/08/24 02:08:51-07:00 chrisw@osdl.org +6 -36 # use simple_read_from_buffer in proc_info_read and proc_pid_attr_read # # ChangeSet # 2004/08/24 11:33:08-07:00 chrisw@osdl.org # [PATCH] use simple_read_from_buffer in selinuxfs # # Use simple_read_from_buffer. This also eliminates page allocation for the # sprintf buffer. Switch to get_zeroed_page instead of open-coding it. Viro # had ack'd this earlier. Still applies w/ the transaction update. # # Signed-off-by: Chris Wright # Signed-off-by: Stephen Smalley # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # security/selinux/selinuxfs.c # 2004/08/24 02:08:51-07:00 chrisw@osdl.org +17 -102 # use simple_read_from_buffer in selinuxfs # # ChangeSet # 2004/08/24 11:32:57-07:00 chrisw@osdl.org # [PATCH] Fix typos in security/security.c # # Fix typos in security/security.c. # # From: Nicolas Kaiser # Signed-off-by: Chris Wright # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # security/security.c # 2004/08/24 02:08:51-07:00 chrisw@osdl.org +2 -2 # Fix typos in security/security.c # # ChangeSet # 2004/08/24 11:32:45-07:00 chrisw@osdl.org # [PATCH] configurable SELinux bootparam value # # Add configure option for setting default SELinux bootparam value. Ack'd by # James Morris. # # Signed-off-by: Chris Wright # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # ChangeSet # 2004/08/24 11:32:44-07:00 yoshfuji@linux-ipv6.org # [IPSEC]: Add SCTP to xfrm_flowi_{sport,dport}() # # Signed-off-by: HIDEAKI Yoshifuji # Signed-off-by: David S. Miller # # security/selinux/hooks.c # 2004/08/24 02:08:51-07:00 chrisw@osdl.org +1 -1 # configurable SELinux bootparam value # # security/selinux/Kconfig # 2004/08/24 02:08:51-07:00 chrisw@osdl.org +15 -0 # configurable SELinux bootparam value # # ChangeSet # 2004/08/24 11:32:33-07:00 chrisw@osdl.org # [PATCH] small simplification for two SECURITY dependencies # # I'd suggest the patch below to let the SECURITY_CAPABILITIES and # SECURITY_ROOTPLUG dependencies look a bit more simple. # # Signed-off-by: Adrian Bunk # Signed-off-by: Chris Wright # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # include/net/xfrm.h # 2004/08/24 11:32:27-07:00 yoshfuji@linux-ipv6.org +2 -0 # [IPSEC]: Add SCTP to xfrm_flowi_{sport,dport}() # # Signed-off-by: HIDEAKI Yoshifuji # Signed-off-by: David S. Miller # # security/Kconfig # 2004/08/24 02:08:50-07:00 chrisw@osdl.org +2 -2 # small simplification for two SECURITY dependencies # # ChangeSet # 2004/08/24 11:32:21-07:00 hch@lst.de # [PATCH] fix some comments about epoch in arch/alpha/kernel/time.c # # (from the Debian kernel package) # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # arch/alpha/kernel/time.c # 2004/08/24 02:08:50-07:00 hch@lst.de +1 -1 # fix some comments about epoch in arch/alpha/kernel/time.c # # ChangeSet # 2004/08/24 11:32:10-07:00 hch@lst.de # [PATCH] ppc32: remove dead CONFIG_KERNEL_ELF Kconfig entry # # We don't allow non-ELF kernels since 2.0 days, and surprisingly this is not # actually checked anywhere. # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # arch/ppc/Kconfig # 2004/08/24 02:08:50-07:00 hch@lst.de +0 -4 # ppc32: remove dead CONFIG_KERNEL_ELF Kconfig entry # # ChangeSet # 2004/08/24 11:31:58-07:00 hch@lst.de # [PATCH] BUG() on inconsistant dcache tree in may_delete # # This can't happen with a sane filesystem (but is triggered by the buggy # clearcase bin only kernel module), so let's better BUG_ON early. # # Adopted from Al's patch in the RH tree. # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # fs/namei.c # 2004/08/24 02:08:50-07:00 hch@lst.de +5 -1 # BUG() on inconsistant dcache tree in may_delete # # ChangeSet # 2004/08/24 11:31:47-07:00 hch@lst.de # [PATCH] reduce pty.c ifdef clutter # # - build only if either CONFIG_LEGACY_PTYS or CONFIG_UNIX98_PTYS are set # instead of testing in the file # # - try to keep big CONFIG_LEGACY_PTYS and CONFIG_UNIX98_PTYS ifdef blocks # at the end of the file instead of cluttering all over # # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # drivers/char/pty.c # 2004/08/24 02:08:49-07:00 hch@lst.de +70 -92 # reduce pty.c ifdef clutter # # drivers/char/Makefile # 2004/08/24 02:08:49-07:00 hch@lst.de +4 -1 # reduce pty.c ifdef clutter # # ChangeSet # 2004/08/24 11:31:37-07:00 jbarnes@engr.sgi.com # [PATCH] fix sn_console for CONFIG_SMP=n # # I found that sn_console was missing an include and a fix if CONFIG_SMP=n. # This patch fixes up the two small problems I found. # # Signed-off-by: Jesse Barnes # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # drivers/serial/sn_console.c # 2004/08/24 02:08:49-07:00 jbarnes@engr.sgi.com +3 -0 # fix sn_console for CONFIG_SMP=n # # ChangeSet # 2004/08/24 11:31:25-07:00 jbarnes@engr.sgi.com # [PATCH] don't print per-cpu delay loop calibration # # People are mainly concerned with showing off their total bogomips, not # per-cpu bogomips, so turn it into a KERN_DEBUG message for the benefit of # systems with lots of CPUs. # # Signed-off-by: Jesse Barnes # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # init/main.c # 2004/08/24 02:08:49-07:00 jbarnes@engr.sgi.com +1 -1 # don't print per-cpu delay loop calibration # # ChangeSet # 2004/08/24 11:31:13-07:00 jmorris@redhat.com # [PATCH] libfs: move transaction file ops into libfs # # Below is an updated version of the patch which moves duplicated # transaction-based file operation code into libfs. Since the last post, the # patch has been through a couple of iterations with Al, who suggested a # number of cleanups including locking and interface simplification. # # For filesystem writers, the interface is now much simpler. The # simple_transaction_get() helper should be part of the file op write method. # This safely obtains the transaction request data during write(), allocates # a page for it and stores it there. The data is returned to the caller for # potential further processing, which then makes it available for the next # read() call via simple_transaction_set(). See the selinuxfs and nfsctl # code for examples of use. # # Signed-off-by: James Morris # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # security/selinux/selinuxfs.c # 2004/08/24 02:08:49-07:00 jmorris@redhat.com +17 -88 # libfs: move transaction file ops into libfs # # include/linux/fs.h # 2004/08/24 02:08:49-07:00 jmorris@redhat.com +33 -0 # libfs: move transaction file ops into libfs # # fs/nfsd/nfsctl.c # 2004/08/24 02:08:49-07:00 jmorris@redhat.com +13 -83 # libfs: move transaction file ops into libfs # # fs/libfs.c # 2004/08/24 02:08:49-07:00 jmorris@redhat.com +55 -0 # libfs: move transaction file ops into libfs # # ChangeSet # 2004/08/24 11:31:02-07:00 pluto@pld-linux.org # [PATCH] ix86,x86_64 cpu features # # Attached patch fix/add several cpu features. # # refs: # # [1] Intel Processor Identification and the CPUID instruction # Application Note 485. # http://developer.intel.ru/download/design/Xeon/applnots/24161826.pdf # # [2] http://www.sandpile.org/ia32/cpuid.htm # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # include/asm-x86_64/cpufeature.h # 2004/08/24 02:08:48-07:00 pluto@pld-linux.org +9 -1 # ix86,x86_64 cpu features # # include/asm-i386/cpufeature.h # 2004/08/24 02:08:48-07:00 pluto@pld-linux.org +8 -3 # ix86,x86_64 cpu features # # arch/x86_64/kernel/setup.c # 2004/08/24 02:08:48-07:00 pluto@pld-linux.org +2 -2 # ix86,x86_64 cpu features # # arch/i386/kernel/cpu/proc.c # 2004/08/24 02:08:48-07:00 pluto@pld-linux.org +2 -2 # ix86,x86_64 cpu features # # ChangeSet # 2004/08/24 11:30:50-07:00 davej@redhat.com # [PATCH] x86: quieten the "ESR value" printks # # Only print out the ESR value if it changes after enabling vector. # # Signed-off-by: Dave Jones # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # arch/i386/kernel/apic.c # 2004/08/24 02:08:48-07:00 davej@redhat.com +6 -6 # x86: quieten the "ESR value" printks # # ChangeSet # 2004/08/24 11:30:39-07:00 benjl@cse.unsw.edu.au # [PATCH] Use posix headers in sumversion.c # # When compiling Linux on Mac OSX I had trouble with scripts/sumversion.c. # It includes to obtain to definitions of htonl and ntohl. # # On Mac OSX these are found in . After checking the POSIX # specification it appears that this is the correct place to get the # definitons for these functions. # # (http://www.opengroup.org/onlinepubs/009695399/functions/htonl.html) # # Using this header also appears to work on Linux (at least with # Glibc-2.3.2). # # It seems clearer to me to go with the POSIX standard than implementing # #if __APPLE__ style macros, but if such an approach is preferred I can # supply patches for that instead. # # A patch against 2.6.7 which change -> is # attached. # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # scripts/mod/sumversion.c # 2004/08/24 02:08:48-07:00 benjl@cse.unsw.edu.au +1 -1 # Use posix headers in sumversion.c # # ChangeSet # 2004/08/24 11:30:31-07:00 herbert@gondor.apana.org.au # [IPSEC]: Set TTL from route. # # Here is the promised patch that sets the TTL from the route parameter. # I decided against adding an option to inherit the TTL like IPIP/GRE # as I think that it doesn't really make sense with IPsec. But it # can be easily added later if someone needs it. # # This isn't completely right when nested tunnels are involved. The # TTL for intervening tunnels should be set from the routes to the # intervening nodes. But fixing that involves using information that # isn't currently in the bundle. I'll revisit this once the MTU stuff # is fixed since that'll also involving adding the intervening routes # to the bundle. # # Signed-off-by: Herbert Xu # Signed-off-by: David S. Miller # # ChangeSet # 2004/08/24 11:30:27-07:00 bcasavan@sgi.com # [PATCH] Fix get_nodes() mask miscalculation # # It appears there is a nodemask miscalculation in the get_nodes() function # in mm/mempolicy.c. This bug has two effects: # # 1. It is impossible to specify a length 1 nodemask. # 2. It is impossible to specify a nodemask containing the last node. # # The following patch has been confirmed to solve both problems. # # Signed-off-by: Brent Casavant # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # mm/mempolicy.c # 2004/08/24 02:08:48-07:00 bcasavan@sgi.com +0 -1 # Fix get_nodes() mask miscalculation # # ChangeSet # 2004/08/24 11:30:15-07:00 michal@logix.cz # [PATCH] New cpu_has_ flags # # Add a couple more accessors for xstore features. # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # net/ipv6/xfrm6_output.c # 2004/08/24 11:30:14-07:00 herbert@gondor.apana.org.au +1 -1 # [IPSEC]: Set TTL from route. # # Here is the promised patch that sets the TTL from the route parameter. # I decided against adding an option to inherit the TTL like IPIP/GRE # as I think that it doesn't really make sense with IPsec. But it # can be easily added later if someone needs it. # # This isn't completely right when nested tunnels are involved. The # TTL for intervening tunnels should be set from the routes to the # intervening nodes. But fixing that involves using information that # isn't currently in the bundle. I'll revisit this once the MTU stuff # is fixed since that'll also involving adding the intervening routes # to the bundle. # # Signed-off-by: Herbert Xu # Signed-off-by: David S. Miller # # net/ipv4/xfrm4_output.c # 2004/08/24 11:30:14-07:00 herbert@gondor.apana.org.au +1 -2 # [IPSEC]: Set TTL from route. # # Here is the promised patch that sets the TTL from the route parameter. # I decided against adding an option to inherit the TTL like IPIP/GRE # as I think that it doesn't really make sense with IPsec. But it # can be easily added later if someone needs it. # # This isn't completely right when nested tunnels are involved. The # TTL for intervening tunnels should be set from the routes to the # intervening nodes. But fixing that involves using information that # isn't currently in the bundle. I'll revisit this once the MTU stuff # is fixed since that'll also involving adding the intervening routes # to the bundle. # # Signed-off-by: Herbert Xu # Signed-off-by: David S. Miller # # include/asm-i386/cpufeature.h # 2004/08/24 02:08:48-07:00 michal@logix.cz +2 -0 # New cpu_has_ flags # # ChangeSet # 2004/08/24 11:30:04-07:00 pj@sgi.com # [PATCH] hige2lowuid warning fixes # # fs/smbfs/inode.c: In function `smb_fill_super': # fs/smbfs/inode.c:563: warning: comparison is always false due to limited range of data type # # Unfortunately, this patch uses the notorious "gcc warning suppression by # obfuscation" technique. # # What seems to be going on is that the uid and gid convert macros in # include/linux/highuid.h: # # #define __convert_uid(size, uid) \ # (size >= sizeof(uid) ? (uid) : high2lowuid(uid)) # # only call high2lowuid in the case of trying to put a bigger (32 bit, say) # uid/gid in a smaller (16 bit, in this case) word. Gcc is smart enough to see # that the comparison in high2lowuid() macro is silly if called with a 16 bit # source uid, but not smart enough to understand from the __convert_uid() logic # that this is exactly the case that high2lowuid() won't be called. # # So replace the logical "<" operator with the bit op "&~". This obfuscates # things enough to shut gcc up. # # Only build the half-dozen files that use SET_UID/SET_GID, on arch i386 and # ia64. Only the file fs/smbfs/inode.c showed the warning, both arch's, and # this patch fixed both. Untested further, past staring at the code long enough # to convince myself the change has no actual affect on the code's results. # # Signed-off-by: Paul Jackson # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # include/linux/highuid.h # 2004/08/24 02:08:47-07:00 pj@sgi.com +4 -4 # hige2lowuid warning fixes # # ChangeSet # 2004/08/24 11:29:52-07:00 davej@redhat.com # [PATCH] fix inlining failures # # arch/i386/mach-generic/summit.c: In function `send_IPI_all': # include/asm/mach-summit/mach_ipi.h:4: sorry, unimplemented: inlining failed in call to 'send_IPI_mask_sequence': function body not available # arch/i386/mach-generic/summit.c:8: sorry, unimplemented: called from here # make[1]: *** [arch/i386/mach-generic/summit.o] Error 1 # make: *** [arch/i386/mach-generic] Error 2 # # arch/i386/mach-generic/bigsmp.c: In function `send_IPI_all': # include/asm/mach-bigsmp/mach_ipi.h:4: sorry, unimplemented: inlining failed in call to 'send_IPI_mask_sequence': function body not available # arch/i386/mach-generic/bigsmp.c:8: sorry, unimplemented: called from here # make[1]: *** [arch/i386/mach-generic/bigsmp.o] Error 1 # make: *** [arch/i386/mach-generic] Error 2 # # arch/i386/mach-generic/es7000.c: In function `send_IPI_all': # include/asm/mach-es7000/mach_ipi.h:4: sorry, unimplemented: inlining failed in call to 'send_IPI_mask_sequence': function body not available # arch/i386/mach-generic/es7000.c:8: sorry, unimplemented: called from here # make[1]: *** [arch/i386/mach-generic/es7000.o] Error 1 # make: *** [arch/i386/mach-generic] Error 2 # # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # include/asm-i386/mach-summit/mach_ipi.h # 2004/08/24 02:08:47-07:00 davej@redhat.com +1 -1 # fix inlining failures # # include/asm-i386/mach-es7000/mach_ipi.h # 2004/08/24 02:08:47-07:00 davej@redhat.com +1 -1 # fix inlining failures # # include/asm-i386/mach-bigsmp/mach_ipi.h # 2004/08/24 02:08:47-07:00 davej@redhat.com +1 -1 # fix inlining failures # # ChangeSet # 2004/08/24 11:29:41-07:00 pluto@pld-linux.org # [PATCH] apm_info.disabled fix # # This minor fix is required to proper init "APM emulation" on HP-OmniBooks. # (An external patch). "APM emulation" is very useful if you want to use a tool # which looks into /proc/apm for getting informations about battery charging. # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # arch/i386/kernel/apm.c # 2004/08/24 02:08:47-07:00 pluto@pld-linux.org +2 -0 # apm_info.disabled fix # # ChangeSet # 2004/08/24 11:29:29-07:00 josha@sgi.com # [PATCH] Reduce bkl usage in do_coredump # # A patch that reduces bkl usage in do_coredump. I don't see anywhere that # it is necessary except for the call to format_corename, which is controlled # via sysctl (sys_sysctl holds the bkl). # # Also make format_corename() static. # # Signed-off-by: Josh Aas # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # fs/exec.c # 2004/08/24 02:08:46-07:00 josha@sgi.com +8 -4 # Reduce bkl usage in do_coredump # # ChangeSet # 2004/08/24 11:29:18-07:00 ak@suse.de # [PATCH] Fix warnings in es7000 # # Fix warnings in es7000. # # Otherwise gcc 3.3 complains about too large integer values. # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # arch/i386/mach-es7000/es7000plat.c # 2004/08/24 02:08:46-07:00 ak@suse.de +1 -1 # Fix warnings in es7000 # # arch/i386/mach-es7000/es7000.h # 2004/08/24 02:08:46-07:00 ak@suse.de +1 -1 # Fix warnings in es7000 # # ChangeSet # 2004/08/24 11:29:06-07:00 neilb@cse.unsw.edu.au # [PATCH] md: RAID10 module # # This patch adds a 'raid10' module which provides features similar to both # raid0 and raid1 in the one array. Various combinations of layout are # supported. # # This code is still "experimental", but appears to work. # # Signed-off-by: Neil Brown # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # include/linux/raid/raid10.h # 2004/08/24 02:08:45-07:00 neilb@cse.unsw.edu.au +103 -0 # md: RAID10 module # # include/linux/raid/raid10.h # 2004/08/24 02:08:45-07:00 neilb@cse.unsw.edu.au +0 -0 # BitKeeper file /home/torvalds/v2.6/linux/include/linux/raid/raid10.h # # include/linux/raid/md_k.h # 2004/08/24 02:08:45-07:00 neilb@cse.unsw.edu.au +4 -1 # md: RAID10 module # # drivers/md/raid10.c # 2004/08/24 02:08:45-07:00 neilb@cse.unsw.edu.au +1780 -0 # md: RAID10 module # # drivers/md/Makefile # 2004/08/24 02:08:45-07:00 neilb@cse.unsw.edu.au +1 -0 # md: RAID10 module # # drivers/md/Kconfig # 2004/08/24 02:08:45-07:00 neilb@cse.unsw.edu.au +18 -0 # md: RAID10 module # # drivers/md/raid10.c # 2004/08/24 02:08:45-07:00 neilb@cse.unsw.edu.au +0 -0 # BitKeeper file /home/torvalds/v2.6/linux/drivers/md/raid10.c # # ChangeSet # 2004/08/24 11:28:54-07:00 neilb@cse.unsw.edu.au # [PATCH] md: remove most calls to __bdevname from md.c # # __bdevname now only prints major/minor number which isn't much help. So # remove most calls to it from md.c, replacing those that are useful by calls # to bdevname (often printing the message when the error is first detected # rather than higher up the call tree). # # Also discard hot_generate_error which doesn't do anything useful and never # has. # # Signed-off-by: Neil Brown # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # drivers/md/md.c # 2004/08/24 02:08:45-07:00 neilb@cse.unsw.edu.au +20 -76 # md: remove most calls to __bdevname from md.c # # ChangeSet # 2004/08/24 11:28:42-07:00 neilb@cse.unsw.edu.au # [PATCH] md: assorted minor md/raid1 fixes # # 1/ rationalise read_balance and "map" in raid1. Discard map and # tidyup the interface to read_balance so it can be used instead. # # 2/ use offsetof rather than a caclulation to find the size of an # structure with a var-length array at the end. # # 3/ remove some meaningless #defines # # 4/ use printk_ratelimit to limit reports of failed sectors being redirected. # # Signed-off-by: Neil Brown # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # drivers/md/raid1.c # 2004/08/24 02:08:45-07:00 neilb@cse.unsw.edu.au +36 -53 # md: assorted minor md/raid1 fixes # # ChangeSet # 2004/08/24 11:28:31-07:00 neilb@cse.unsw.edu.au # [PATCH] md: assorted fixes/improvemnet to generic md resync code. # # 1/ Introduce "mddev->resync_max_sectors" so that an md personality # can ask for resync to cover a different address range than that of a # single drive. raid10 will use this. # # 2/ fix is_mddev_idle so that if there seem to be a negative number # of events, it doesn't immediately assume activity. # # 3/ make "sync_io" (the count of IO sectors used for array resync) # an atomic_t to avoid SMP races. # # 4/ Pass md_sync_acct a "block_device" rather than the containing "rdev", # as the whole rdev isn't needed. Also make this an inline function. # # 5/ Make sure recovery gets interrupted on any error. # # Signed-off-by: Neil Brown # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # include/linux/raid/md_k.h # 2004/08/24 02:08:45-07:00 neilb@cse.unsw.edu.au +6 -0 # md: assorted fixes/improvemnet to generic md resync code. # # include/linux/raid/md.h # 2004/08/24 02:08:45-07:00 neilb@cse.unsw.edu.au +0 -1 # md: assorted fixes/improvemnet to generic md resync code. # # include/linux/genhd.h # 2004/08/24 02:08:45-07:00 neilb@cse.unsw.edu.au +1 -1 # md: assorted fixes/improvemnet to generic md resync code. # # drivers/md/raid6main.c # 2004/08/24 02:08:45-07:00 neilb@cse.unsw.edu.au +3 -2 # md: assorted fixes/improvemnet to generic md resync code. # # drivers/md/raid5.c # 2004/08/24 02:08:45-07:00 neilb@cse.unsw.edu.au +3 -2 # md: assorted fixes/improvemnet to generic md resync code. # # drivers/md/raid1.c # 2004/08/24 02:08:45-07:00 neilb@cse.unsw.edu.au +2 -2 # md: assorted fixes/improvemnet to generic md resync code. # # drivers/md/md.c # 2004/08/24 02:08:45-07:00 neilb@cse.unsw.edu.au +22 -10 # md: assorted fixes/improvemnet to generic md resync code. # # ChangeSet # 2004/08/24 11:28:18-07:00 wli@holomorphy.com # [PATCH] hugetlb: permit executable mappings # # During the kernel summit, some discussion was had about the support # requirements for a userspace program loader that loads executables into # hugetlb on behalf of a major application (Oracle). In order to support # this in a robust fashion, the cleanup of the hugetlb must be robust in the # presence of disorderly termination of the programs (e.g. kill -9). Hence, # the cleanup semantics are those of System V shared memory, but Linux' # System V shared memory needs one critical extension for this use: # executability. # # The following microscopic patch enables this major application to provide # robust hugetlb cleanup. # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # ChangeSet # 2004/08/24 11:28:16-07:00 ajgrothe@yahoo.com # [CRYPTO]: Add Whirlpool digest algorithm. # # Given the recent potential weaknesses in the SHA and MD families, # I thought it might not be a bad idea to include another hash/digest # algorithm in the kernel. # # So here is Whirlpool. I chose it for a couple of reasons. # # o - It is by the same people who did Khazad. I feel pretty good about their work. # o - It has been evaluated by NESSIE # https://www.cosic.esat.kuleuven.ac.be/nessie/reports/phase1/sagwp3-037_1.pdf # o - NESSIE has accepted it as one of the cryptographic primitives # o - It will be part of an ISO standard in the revised ISO/IEC 10118-3:2003(E) standard, thanks to # NESSIE # o - It is patent free and has an implementation in the public domain. # # Signed-off-by: Aaron Grothe # Signed-off-by: James Morris # Signed-off-by: David S. Miller # # ipc/shm.c # 2004/08/24 02:08:44-07:00 wli@holomorphy.com +4 -0 # hugetlb: permit executable mappings # # include/linux/shm.h # 2004/08/24 02:08:44-07:00 wli@holomorphy.com +1 -0 # hugetlb: permit executable mappings # # ChangeSet # 2004/08/24 11:28:07-07:00 wli@holomorphy.com # [PATCH] x86 PAE swapspace expansion # # PAE is artificially limited in terms of swapspace to the same bitsplit as # ordinary i386, a 5/24 split (32 swapfiles, 64GB max swapfile size), when a # 5/27 split (32 swapfiles, 512GB max swapfile size) is feasible. This patch # transparently removes that limitation by using more of the space available # in PAE's wider ptes for swap ptes. # # While this is obviously not likely to be used directly, it is important # from the standpoint of strict non-overcommit, where the swapspace must be # potentially usable in order to be reserved for non-overcommit. There are # workloads with Committed_AS of over 256GB on ia32 PAE wanting strict # non-overcommit to prevent being OOM killed. # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # include/asm-i386/pgtable.h # 2004/08/24 02:08:44-07:00 wli@holomorphy.com +0 -7 # x86 PAE swapspace expansion # # include/asm-i386/pgtable-3level.h # 2004/08/24 02:08:44-07:00 wli@holomorphy.com +7 -0 # x86 PAE swapspace expansion # # include/asm-i386/pgtable-2level.h # 2004/08/24 02:08:44-07:00 wli@holomorphy.com +7 -0 # x86 PAE swapspace expansion # # ChangeSet # 2004/08/24 11:27:55-07:00 zwane@fsmlabs.com # [PATCH] fix i386/x86_64 idle routine selection # # This was broken when the mwait stuff went in since it executes after the # initial idle_setup() has already selected an idle routine and overrides it # with default_idle. # # Signed-off-by: Venkatesh Pallipadi # Signed-off-by: Zwane Mwaikambo # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # arch/x86_64/kernel/process.c # 2004/08/24 02:08:44-07:00 zwane@fsmlabs.com +1 -6 # fix i386/x86_64 idle routine selection # # arch/i386/kernel/process.c # 2004/08/24 02:08:44-07:00 zwane@fsmlabs.com +1 -6 # fix i386/x86_64 idle routine selection # # ChangeSet # 2004/08/24 11:27:43-07:00 manfred@colorfullife.com # [PATCH] remove magic +1 from shm segment count # # Michael Kerrisk found a bug in the shm accounting code: sysv shm allows to # create SHMMNI+1 shared memory segments, instead of SHMMNI segments. The +1 # is probably from the first shared anonymous mapping implementation that # used the sysv code to implement shared anon mappings. # # The implementation got replaced, it's now the other way around (sysv uses # the shared anon code), but the +1 remained. # # Signed-off-by: Manfred Spraul # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # ipc/shm.c # 2004/08/24 02:08:43-07:00 manfred@colorfullife.com +1 -1 # remove magic +1 from shm segment count # # ChangeSet # 2004/08/24 11:27:32-07:00 zwane@arm.linux.org.uk # [PATCH] OProfile/XScale fixes for PXA270/XScale2 # # The incorrect mask was being used when writing back to PMNC write-only-zero # bits as well as only ticking the CCNT every 64 processor cycles. Tested on # IOP331 and PXA270, i'm still looking for XScale1 users... # # Signed-off-by: Luca Rossato # Signed-off-by: Zwane Mwaikambo # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # arch/arm/oprofile/op_model_xscale.c # 2004/08/24 02:08:43-07:00 zwane@arm.linux.org.uk +15 -6 # OProfile/XScale fixes for PXA270/XScale2 # # ChangeSet # 2004/08/24 11:27:20-07:00 wli@holomorphy.com # [PATCH] kill CLONE_IDLETASK # # The sole remaining usage of CLONE_IDLETASK is to determine whether pid # allocation should be performed in copy_process(). This patch eliminates # that last branch on CLONE_IDLETASK in the normal process creation path, # removes the masking of CLONE_IDLETASK from clone_flags as it's now ignored # under all circumstances, and furthermore eliminates the symbol # CLONE_IDLETASK entirely. # # From: William Lee Irwin III # # Fix the fork-idle consolidation. During that consolidation, the generic # code was made to pass a pointer to on-stack pt_regs that had been memset() # to 0. ia64, however, requires a NULL pt_regs pointer argument and # dispatches on that in its copy_thread() function to do SMP # trampoline-specific RSE -related setup. Passing pointers to zeroed pt_regs # resulted in SMP wakeup -time deadlocks and exceptions. # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # kernel/fork.c # 2004/08/24 02:08:43-07:00 wli@holomorphy.com +17 -20 # kill CLONE_IDLETASK # # arch/ia64/kernel/smpboot.c # 2004/08/24 02:08:43-07:00 wli@holomorphy.com +5 -0 # kill CLONE_IDLETASK # # ChangeSet # 2004/08/24 11:27:07-07:00 wli@holomorphy.com # [PATCH] sched: consolidate CLONE_IDLETASK masking # # Every arch now bears the burden of sanitizing CLONE_IDLETASK out of the # clone_flags passed to do_fork() by userspace. This patch hoists the # masking of CLONE_IDLETASK out of the system call entrypoints into # do_fork(), and thereby removes some small overheads from do_fork(), as # do_fork() may now assume that CLONE_IDLETASK has been cleared. # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # kernel/fork.c # 2004/08/24 02:08:42-07:00 wli@holomorphy.com +10 -8 # sched: consolidate CLONE_IDLETASK masking # # include/linux/sched.h # 2004/08/24 02:08:42-07:00 wli@holomorphy.com +0 -1 # sched: consolidate CLONE_IDLETASK masking # # arch/x86_64/kernel/process.c # 2004/08/24 02:08:42-07:00 wli@holomorphy.com +1 -2 # sched: consolidate CLONE_IDLETASK masking # # arch/x86_64/ia32/sys_ia32.c # 2004/08/24 02:08:42-07:00 wli@holomorphy.com +1 -2 # sched: consolidate CLONE_IDLETASK masking # # arch/sparc64/kernel/process.c # 2004/08/24 02:08:42-07:00 wli@holomorphy.com +0 -2 # sched: consolidate CLONE_IDLETASK masking # # arch/sparc/kernel/process.c # 2004/08/24 02:08:42-07:00 wli@holomorphy.com +0 -2 # sched: consolidate CLONE_IDLETASK masking # # arch/sh64/kernel/process.c # 2004/08/24 02:08:42-07:00 wli@holomorphy.com +1 -1 # sched: consolidate CLONE_IDLETASK masking # # arch/sh/kernel/process.c # 2004/08/24 02:08:42-07:00 wli@holomorphy.com +1 -1 # sched: consolidate CLONE_IDLETASK masking # # arch/s390/kernel/process.c # 2004/08/24 02:08:42-07:00 wli@holomorphy.com +1 -1 # sched: consolidate CLONE_IDLETASK masking # # arch/s390/kernel/compat_linux.c # 2004/08/24 02:08:42-07:00 wli@holomorphy.com +1 -1 # sched: consolidate CLONE_IDLETASK masking # # arch/ppc64/kernel/process.c # 2004/08/24 02:08:42-07:00 wli@holomorphy.com +1 -1 # sched: consolidate CLONE_IDLETASK masking # # arch/ppc/kernel/process.c # 2004/08/24 02:08:42-07:00 wli@holomorphy.com +1 -2 # sched: consolidate CLONE_IDLETASK masking # # arch/parisc/kernel/process.c # 2004/08/24 02:08:42-07:00 wli@holomorphy.com +1 -1 # sched: consolidate CLONE_IDLETASK masking # # arch/mips/kernel/syscall.c # 2004/08/24 02:08:42-07:00 wli@holomorphy.com +1 -1 # sched: consolidate CLONE_IDLETASK masking # # arch/m68knommu/kernel/process.c # 2004/08/24 02:08:42-07:00 wli@holomorphy.com +1 -1 # sched: consolidate CLONE_IDLETASK masking # # arch/m68k/kernel/process.c # 2004/08/24 02:08:42-07:00 wli@holomorphy.com +1 -1 # sched: consolidate CLONE_IDLETASK masking # # arch/ia64/kernel/entry.S # 2004/08/24 02:08:42-07:00 wli@holomorphy.com +2 -2 # sched: consolidate CLONE_IDLETASK masking # # arch/ia64/kernel/asm-offsets.c # 2004/08/24 02:08:42-07:00 wli@holomorphy.com +0 -5 # sched: consolidate CLONE_IDLETASK masking # # arch/ia64/ia32/ia32_entry.S # 2004/08/24 02:08:42-07:00 wli@holomorphy.com +1 -1 # sched: consolidate CLONE_IDLETASK masking # # arch/i386/kernel/process.c # 2004/08/24 02:08:42-07:00 wli@holomorphy.com +1 -1 # sched: consolidate CLONE_IDLETASK masking # # arch/h8300/kernel/process.c # 2004/08/24 02:08:42-07:00 wli@holomorphy.com +1 -1 # sched: consolidate CLONE_IDLETASK masking # # arch/cris/arch-v10/kernel/process.c # 2004/08/24 02:08:42-07:00 wli@holomorphy.com +1 -1 # sched: consolidate CLONE_IDLETASK masking # # arch/arm26/kernel/sys_arm.c # 2004/08/24 02:08:42-07:00 wli@holomorphy.com +1 -1 # sched: consolidate CLONE_IDLETASK masking # # arch/arm/kernel/sys_arm.c # 2004/08/24 02:08:42-07:00 wli@holomorphy.com +1 -1 # sched: consolidate CLONE_IDLETASK masking # # arch/alpha/kernel/process.c # 2004/08/24 02:08:42-07:00 wli@holomorphy.com +1 -2 # sched: consolidate CLONE_IDLETASK masking # # ChangeSet # 2004/08/24 11:26:54-07:00 josha@sgi.com # [PATCH] improve speed of freeing bootmem # # Attached is a patch that greatly improves the speed of freeing boot memory. # On ia64 machines with 2GB or more memory (I didn't test with less, but I # can't imagine there being a problem), the speed improvement is about 75% # for the function free_all_bootmem_core. This translates to savings on the # order of 1 minute / TB of memory during boot time. That number comes from # testing on a machine with 512GB, and extrapolating based on profiling of an # unpatched 4TB machine. For 4 and 8 TB machines, the time spent in this # function is about 1 minutes/TB, which is painful especially given that # there is no indication of what is going on put to the console (this issue # to possibly be addressed later). # # The basic idea is to free higher order pages instead of going through every # single one. Also, some unnecessary atomic operations are done away with # and replaced with non-atomic equivalents, and prefetching is done where it # helps the most. For a more in-depth discusion of this patch, please see # the linux-ia64 archives (topic is "free bootmem feedback patch"). # # The patch is originally Tony Luck's, and I added some further optimizations # (non-atomic ops improvements and prefetching). # # Signed-off-by: Tony Luck # Signed-off-by: Josh Aas # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # mm/bootmem.c # 2004/08/24 02:08:42-07:00 josha@sgi.com +22 -3 # improve speed of freeing bootmem # # include/linux/page-flags.h # 2004/08/24 02:08:42-07:00 josha@sgi.com +1 -0 # improve speed of freeing bootmem # # ChangeSet # 2004/08/24 11:26:42-07:00 pbadari@us.ibm.com # [PATCH] Fix mpage_readpage() for big requests # # The problem is, if we increase our readhead size arbitrarily (say 2M), we # call mpage_readpages() with 2M and when it tries to allocated a bio enough to # fit 2M it fails, then we kick it back to "confused" code - which does 4K at # a time. # # The fix is to ask for the maxium the driver can handle. # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # crypto/tcrypt.h # 2004/08/24 11:26:41-07:00 ajgrothe@yahoo.com +104 -0 # [CRYPTO]: Add Whirlpool digest algorithm. # # crypto/tcrypt.c # 2004/08/24 11:26:41-07:00 ajgrothe@yahoo.com +8 -1 # [CRYPTO]: Add Whirlpool digest algorithm. # # crypto/Makefile # 2004/08/24 11:26:41-07:00 ajgrothe@yahoo.com +1 -0 # [CRYPTO]: Add Whirlpool digest algorithm. # # crypto/Kconfig # 2004/08/24 11:26:41-07:00 ajgrothe@yahoo.com +15 -0 # [CRYPTO]: Add Whirlpool digest algorithm. # # Documentation/crypto/api-intro.txt # 2004/08/24 11:26:41-07:00 ajgrothe@yahoo.com +3 -0 # [CRYPTO]: Add Whirlpool digest algorithm. # # fs/mpage.c # 2004/08/24 02:08:42-07:00 pbadari@us.ibm.com +2 -1 # Fix mpage_readpage() for big requests # # crypto/whirlpool.c # 2004/08/24 11:26:34-07:00 ajgrothe@yahoo.com +1131 -0 # [CRYPTO]: Add Whirlpool digest algorithm. # # crypto/whirlpool.c # 2004/08/24 11:26:34-07:00 ajgrothe@yahoo.com +0 -0 # BitKeeper file /disk1/BK/net-2.6/crypto/whirlpool.c # # ChangeSet # 2004/08/24 11:26:31-07:00 roland@topspin.com # [PATCH] x86: remove hard-coded numbers from ptr_ok() # # Looks like arch/i386/kernel/doublefault.c is one place in the code that # hardcodes the assumption that PAGE_OFFSET == 0xC0000000. Here's a patch # that fixes that. # # Signed-off-by: Roland Dreier # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # arch/i386/kernel/doublefault.c # 2004/08/24 02:08:41-07:00 roland@topspin.com +1 -1 # x86: remove hard-coded numbers from ptr_ok() # # ChangeSet # 2004/08/24 11:26:19-07:00 James@superbug.demon.co.uk # [PATCH] emu10k1 maintainer update # # Rui Sousa has been unreachable for a long time now, so I have taken over # the emu10k1 project on sf.net. # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # MAINTAINERS # 2004/08/24 02:08:41-07:00 James@superbug.demon.co.uk +2 -2 # emu10k1 maintainer update # # ChangeSet # 2004/08/24 11:26:07-07:00 andrea@suse.de # [PATCH] Correctly handle d_path error returns # # There's some minor bug in the d_path handling (the nfsd one may not the the # correct fix, there's no failure path for it, so I just terminate the # string, and the last one in the audit subsystem is just a robustness # cleanup if somebody will extend d_path in the future, right now it's a # noop). # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # kernel/audit.c # 2004/08/24 02:08:41-07:00 andrea@suse.de +1 -1 # Correctly handle d_path error returns # # fs/nfsd/export.c # 2004/08/24 02:08:41-07:00 andrea@suse.de +5 -0 # Correctly handle d_path error returns # # fs/compat.c # 2004/08/24 02:08:41-07:00 andrea@suse.de +2 -0 # Correctly handle d_path error returns # # ChangeSet # 2004/08/24 11:25:56-07:00 akpm@osdl.org # [PATCH] alloc_pages priority tuning # # Fix up the logic which decides when the caller can dip into page reserves. # # - If the caller has realtime scheduling policy, or if the caller cannot run # direct reclaim, then allow the caller to use up to a quarter of the page # reserves. # # - If the caller has __GFP_HIGH then allow the caller to use up to half of # the page reserves. # # - If the caller has PF_MEMALLOC then the caller can use 100% of the page # reserves. # # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # mm/page_alloc.c # 2004/08/24 02:08:40-07:00 akpm@osdl.org +14 -6 # alloc_pages priority tuning # # ChangeSet # 2004/08/24 11:25:44-07:00 nickpiggin@yahoo.com.au # [PATCH] vm: alloc_pages watermark fixes # # Previously the ->protection[] logic was broken. It was difficult to follow # and basically didn't use the asynch reclaim watermarks (pages_min, # pages_low, pages_high) properly. # # Now use ->protection *only* for lower-zone protection. So the allocator # now explicitly uses the ->pages_low, ->pages_min watermarks and adds # ->protection on top of that, instead of trying to use ->protection for # everything. # # Pages are allocated down to (->pages_low + ->protection), once this is # reached, kswapd the background reclaim is started; after this, we can # allocate down to (->pages_min + ->protection) without blocking; the memory # below pages_min is reserved for __GFP_HIGH and PF_MEMALLOC allocations. # kswapd attempts to reclaim memory until ->pages_high is reached. # # Signed-off-by: Nick Piggin # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # mm/page_alloc.c # 2004/08/24 02:08:40-07:00 nickpiggin@yahoo.com.au +53 -66 # vm: alloc_pages watermark fixes # # ChangeSet # 2004/08/24 11:25:33-07:00 nickpiggin@yahoo.com.au # [PATCH] vm: writeout watermark tuning # # Slightly change the writeout watermark calculations so we keep background # and synchronous writeout watermarks in the same ratios after adjusting them # for the amout of mapped memory. This ensures we should always attempt to # start background writeout before synchronous writeout and preserves the # admin's desired background-versus-forground ratios after we've # auto-adjusted one of them. # # Signed-off-by: Nick Piggin # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # mm/page-writeback.c # 2004/08/24 02:08:40-07:00 nickpiggin@yahoo.com.au +5 -3 # vm: writeout watermark tuning # # ChangeSet # 2004/08/24 11:25:21-07:00 hugh@veritas.com # [PATCH] simple fs stop -ve dentries # # A tmpfs user reported increasingly slow directory reads when repeatedly # creating and unlinking in a mkstemp-like way. The negative dentries # accumulate alarmingly (until memory pressure finally frees them), and are # just a hindrance to any in-memory filesystem. simple_lookup set d_op to # arrange for negative dentries to be deleted immediately. # # (But I failed to discover how it is that on-disk filesystems seem to keep # their negative dentries within manageable bounds: this effect was gross # with tmpfs or ramfs, but no problem at all with extN or reiser.) # # Signed-off-by: Hugh Dickins # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # fs/libfs.c # 2004/08/24 02:08:40-07:00 hugh@veritas.com +15 -2 # simple fs stop -ve dentries # # ChangeSet # 2004/08/24 11:25:09-07:00 hugh@veritas.com # [PATCH] clarify get_task_mm (mmgrab) # # Clarify mmgrab by collapsing it into get_task_mm (in fork.c not inline), # and commenting on the special case it is guarding against: when use_mm in # an AIO daemon temporarily adopts the mm while it's on its way out. # # Signed-off-by: Hugh Dickins # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # kernel/fork.c # 2004/08/24 02:08:39-07:00 hugh@veritas.com +26 -12 # clarify get_task_mm (mmgrab) # # include/linux/sched.h # 2004/08/24 02:08:39-07:00 hugh@veritas.com +2 -22 # clarify get_task_mm (mmgrab) # # fs/proc/array.c # 2004/08/24 02:08:39-07:00 hugh@veritas.com +1 -5 # clarify get_task_mm (mmgrab) # # ChangeSet # 2004/08/24 11:24:57-07:00 marcelo.tosatti@cyclades.com # [PATCH] x86 bitops.h commentary on instruction reordering # # Back when we were discussing the need for a memory barrier in sync_page(), # it came to me (thanks Andrea!) that the bit operations can be perfectly # reordered on architectures other than x86. # # I think the commentary on i386 bitops.h is misleading, its worth to note # that that these operations are not guaranteed not to be reordered on # different architectures. # # clear_bit() already does that: # # * clear_bit() is atomic and may not be reordered. However, it does # * not contain a memory barrier, so if it is used for locking purposes, # * you should call smp_mb__before_clear_bit() and/or smp_mb__after_clear_bit() # * in order to ensure changes are visible on other processors. # # # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # include/asm-i386/bitops.h # 2004/08/24 02:08:39-07:00 marcelo.tosatti@cyclades.com +10 -2 # x86 bitops.h commentary on instruction reordering # # ChangeSet # 2004/08/24 11:24:46-07:00 hugh@veritas.com # [PATCH] rmaplock: swapoff use anon_vma # # Swapoff can make good use of a page's anon_vma and index, while it's still # left in swapcache, or once it's brought back in and the first pte mapped back: # unuse_vma go directly to just one page of only those vmas with the same # anon_vma. And unuse_process can skip any vmas without an anon_vma (extending # the hugetlb check: hugetlb vmas have no anon_vma). # # This just hacks in on top of the existing procedure, still going through all # the vmas of all the mms in mmlist. A more elegant procedure might replace # mmlist by a list of anon_vmas: but that would be more work to implement, with # apparently more overhead in the common paths. # # Signed-off-by: Hugh Dickins # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # mm/swapfile.c # 2004/08/24 02:08:39-07:00 hugh@veritas.com +16 -7 # rmaplock: swapoff use anon_vma # # mm/rmap.c # 2004/08/24 02:08:39-07:00 hugh@veritas.com +20 -0 # rmaplock: swapoff use anon_vma # # include/linux/rmap.h # 2004/08/24 02:08:39-07:00 hugh@veritas.com +5 -0 # rmaplock: swapoff use anon_vma # # ChangeSet # 2004/08/24 11:24:34-07:00 hugh@veritas.com # [PATCH] rmaplock: mm lock ordering # # With page_map_lock out of the way, there's no need for page_referenced and # try_to_unmap to use trylocks - provided we switch anon_vma->lock and # mm->page_table_lock around in anon_vma_prepare. Though I suppose it's # possible that we'll find that vmscan makes better progress with trylocks than # spinning - we're free to choose trylocks again if so. # # Try to update the mm lock ordering documentation in filemap.c. But I still # find it confusing, and I've no idea of where to stop. So add an mm lock # ordering list I can understand to rmap.c. # # Signed-off-by: Hugh Dickins # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # mm/rmap.c # 2004/08/24 02:08:39-07:00 hugh@veritas.com +45 -37 # rmaplock: mm lock ordering # # mm/filemap.c # 2004/08/24 02:08:39-07:00 hugh@veritas.com +9 -6 # rmaplock: mm lock ordering # # ChangeSet # 2004/08/24 11:24:22-07:00 hugh@veritas.com # [PATCH] rmaplock: SLAB_DESTROY_BY_RCU # # With page_map_lock gone, how to stabilize page->mapping's anon_vma while # acquiring anon_vma->lock in page_referenced_anon and try_to_unmap_anon? # # The page cannot actually be freed (vmscan holds reference), but however much # we check page_mapped (which guarantees that anon_vma is in use - or would # guarantee that if we added suitable barriers), there's no locking against page # becoming unmapped the instant after, then anon_vma freed. # # It's okay to take anon_vma->lock after it's freed, so long as it remains a # struct anon_vma (its list would become empty, or perhaps reused for an # unrelated anon_vma: but no problem since we always check that the page located # is the right one); but corruption if that memory gets reused for some other # purpose. # # This is not unique: it's liable to be problem whenever the kernel tries to # approach a structure obliquely. It's generally solved with an atomic # reference count; but one advantage of anon_vma over anonmm is that it does not # have such a count, and it would be a backward step to add one. # # Therefore... implement SLAB_DESTROY_BY_RCU flag, to guarantee that such a # kmem_cache_alloc'ed structure cannot get freed to other use while the # rcu_read_lock is held i.e. preempt disabled; and use that for anon_vma. # # Fix concerns raised by Manfred: this flag is incompatible with poisoning and # destructor, and kmem_cache_destroy needs to synchronize_kernel. # # I hope SLAB_DESTROY_BY_RCU may be useful elsewhere; but though it's safe for # little anon_vma, I'd be reluctant to use it on any caches whose immediate # shrinkage under pressure is important to the system. # # Signed-off-by: Hugh Dickins # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # mm/slab.c # 2004/08/24 02:08:38-07:00 hugh@veritas.com +62 -7 # rmaplock: SLAB_DESTROY_BY_RCU # # mm/rmap.c # 2004/08/24 02:08:38-07:00 hugh@veritas.com +33 -17 # rmaplock: SLAB_DESTROY_BY_RCU # # include/linux/slab.h # 2004/08/24 02:08:38-07:00 hugh@veritas.com +1 -0 # rmaplock: SLAB_DESTROY_BY_RCU # # ChangeSet # 2004/08/24 11:24:11-07:00 hugh@veritas.com # [PATCH] rmaplock: kill page_map_lock # # The pte_chains rmap used pte_chain_lock (bit_spin_lock on PG_chainlock) to # lock its pte_chains. We kept this (as page_map_lock: bit_spin_lock on # PG_maplock) when we moved to objrmap. But the file objrmap locks its vma tree # with mapping->i_mmap_lock, and the anon objrmap locks its vma list with # anon_vma->lock: so isn't the page_map_lock superfluous? # # Pretty much, yes. The mapcount was protected by it, and needs to become an # atomic: starting at -1 like page _count, so nr_mapped can be tracked precisely # up and down. The last page_remove_rmap can't clear anon page mapping any # more, because of races with page_add_rmap; from which some BUG_ONs must go for # the same reason, but they've served their purpose. # # vmscan decisions are naturally racy, little change there beyond removing # page_map_lock/unlock. But to stabilize the file-backed page->mapping against # truncation while acquiring i_mmap_lock, page_referenced_file now needs page # lock to be held even for refill_inactive_zone. There's a similar issue in # acquiring anon_vma->lock, where page lock doesn't help: which this patch # pretends to handle, but actually it needs the next. # # Roughly 10% cut off lmbench fork numbers on my 2*HT*P4. Must confess my # testing failed to show the races even while they were knowingly exposed: would # benefit from testing on racier equipment. # # Signed-off-by: Hugh Dickins # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # mm/vmscan.c # 2004/08/24 02:08:38-07:00 hugh@veritas.com +7 -30 # rmaplock: kill page_map_lock # # mm/rmap.c # 2004/08/24 02:08:38-07:00 hugh@veritas.com +76 -59 # rmaplock: kill page_map_lock # # mm/page_alloc.c # 2004/08/24 02:08:38-07:00 hugh@veritas.com +5 -5 # rmaplock: kill page_map_lock # # include/linux/rmap.h # 2004/08/24 02:08:38-07:00 hugh@veritas.com +3 -10 # rmaplock: kill page_map_lock # # include/linux/page-flags.h # 2004/08/24 02:08:38-07:00 hugh@veritas.com +1 -2 # rmaplock: kill page_map_lock # # include/linux/mm.h # 2004/08/24 02:08:38-07:00 hugh@veritas.com +18 -4 # rmaplock: kill page_map_lock # # ChangeSet # 2004/08/24 11:23:59-07:00 hugh@veritas.com # [PATCH] rmaplock: PageAnon in mapping # # First of a batch of five patches to eliminate rmap's page_map_lock, replace # its trylocking by spinlocking, and use anon_vma to speed up swapoff. # # Patches updated from the originals against 2.6.7-mm7: nothing new so I won't # spam the list, but including Manfred's SLAB_DESTROY_BY_RCU fixes, and omitting # the unuse_process mmap_sem fix already in 2.6.8-rc3. # # # This patch: # # Replace the PG_anon page->flags bit by setting the lower bit of the pointer in # page->mapping when it's anon_vma: PAGE_MAPPING_ANON bit. # # We're about to eliminate the locking which kept the flags and mapping in # synch: it's much easier to work on a local copy of page->mapping, than worry # about whether flags and mapping are in synch (though I imagine it could be # done, at greater cost, with some barriers). # # Signed-off-by: Hugh Dickins # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # ChangeSet # 2004/08/24 11:23:53-07:00 lkml@felipe-alfaro.com # [NETFILTER]: Missing netfilter_ipv4.c include in conntrack proto code. # # Signed-off-by: Felipe Alfaro Solana # Signed-off-by: David S. Miller # # mm/rmap.c # 2004/08/24 02:08:38-07:00 hugh@veritas.com +3 -17 # rmaplock: PageAnon in mapping # # mm/page_alloc.c # 2004/08/24 02:08:38-07:00 hugh@veritas.com +0 -3 # rmaplock: PageAnon in mapping # # include/linux/page-flags.h # 2004/08/24 02:08:38-07:00 hugh@veritas.com +0 -6 # rmaplock: PageAnon in mapping # # include/linux/mm.h # 2004/08/24 02:08:38-07:00 hugh@veritas.com +16 -7 # rmaplock: PageAnon in mapping # # ChangeSet # 2004/08/24 11:23:48-07:00 rl@hellgate.ch # [PATCH] Fix /proc/pid/statm documentation # # I really wanted /proc/pid/statm to die and I still believe the # reasoning is valid. As it doesn't look like that is going to happen, # though, I offer this fix for the respective documentation. Note: lrs/drs # fields are switched. # # Signed-off-by: Roger Luethi # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # Documentation/filesystems/proc.txt # 2004/08/24 02:08:38-07:00 rl@hellgate.ch +11 -9 # Fix /proc/pid/statm documentation # # ChangeSet # 2004/08/24 11:23:35-07:00 arjanv@redhat.com # [PATCH] Automatically enable bigsmp on big HP machines # # This enables apic=bigsmp automatically on some big HP machines that need # it. This makes them boot without kernel parameters on a generic arch # kernel. # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # arch/i386/mach-generic/bigsmp.c # 2004/08/24 02:08:37-07:00 arjanv@redhat.com +27 -1 # Automatically enable bigsmp on big HP machines # # arch/i386/kernel/io_apic.c # 2004/08/24 02:08:37-07:00 arjanv@redhat.com +1 -1 # Automatically enable bigsmp on big HP machines # # ChangeSet # 2004/08/24 11:23:25-07:00 wli@holomorphy.com # [PATCH] ia64: dma_mapping fix # # We need to be able to dereference struct device in # include/asm-ia64/dma-mapping.h. # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # include/asm-ia64/dma-mapping.h # 2004/08/24 02:08:37-07:00 wli@holomorphy.com +2 -1 # ia64: dma_mapping fix # # ChangeSet # 2004/08/24 11:23:14-07:00 ak@suse.de # [PATCH] md: make MD no device warning KERN_WARNING # # Prevents some noise during boot up when no MD volumes are found. # # I think I picked it up from someone else, but I cannot remember from whom # (sorry) # # Cc: Neil Brown # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # drivers/md/md.c # 2004/08/24 02:08:37-07:00 ak@suse.de +1 -1 # md: make MD no device warning KERN_WARNING # # ChangeSet # 2004/08/24 11:23:04-07:00 zaitcev@redhat.com # [PATCH] Make MAX_INIT_ARGS 32 # # We at Red Hat shipped a larger number of arguments for quite some time, it # was required for installations on IBM mainframe (s390), which doesn't have # a good way to pass arguments. # # There are a number of reasonable situations that go past the current limits # of 8. One that comes to mind is when you want to perform a manual vnc # install on a headless machine using anaconda. This requires passing in a # number of parameters to get anaconda past the initial (no-gui) loader # screens. # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # net/ipv4/netfilter/ip_conntrack_proto_udp.c # 2004/08/24 11:23:03-07:00 lkml@felipe-alfaro.com +1 -0 # [NETFILTER]: Missing netfilter_ipv4.c include in conntrack proto code. # # net/ipv4/netfilter/ip_conntrack_proto_tcp.c # 2004/08/24 11:23:03-07:00 lkml@felipe-alfaro.com +1 -0 # [NETFILTER]: Missing netfilter_ipv4.c include in conntrack proto code. # # net/ipv4/netfilter/ip_conntrack_proto_icmp.c # 2004/08/24 11:23:03-07:00 lkml@felipe-alfaro.com +1 -0 # [NETFILTER]: Missing netfilter_ipv4.c include in conntrack proto code. # # init/main.c # 2004/08/24 02:08:36-07:00 zaitcev@redhat.com +2 -2 # Make MAX_INIT_ARGS 32 # # ChangeSet # 2004/08/24 11:22:52-07:00 suparna@in.ibm.com # [PATCH] AIO: workqueue context switch reduction # # From: Chris Mason # # I compared the 2.6 pipetest results with the 2.4 suse kernel, and 2.6 was # roughly 40% slower. During the pipetest run, 2.6 generates ~600,000 # context switches per second while 2.4 generates 30 or so. # # aio-context-switch (attached) has a few changes that reduces our context # switch rate, and bring performance back up to 2.4 levels. These have only # really been tested against pipetest, they might make other workloads worse. # # The basic theory behind the patch is that it is better for the userland # process to call run_iocbs than it is to schedule away and let the worker # thread do it. # # # 1) on io_submit, use run_iocbs instead of run_iocb # 2) on io_getevents, call run_iocbs if no events were available. # # 3) don't let two procs call run_iocbs for the same context at the same # time. They just end up bouncing on spinlocks. # # The first three optimizations got me down to 360,000 context switches per # second, and they help build a little structure to allow optimization #4, # which uses queue_delayed_work(HZ/10) instead of queue_work. # # That brings down the number of context switches to 2.4 levels. # # Adds aio_run_all_iocbs so that normal processes can run all the pending # retries on the run list. This allows worker threads to keep using list # splicing, but regular procs get to run the list until it stays empty. The # end result should be less work for the worker threads. # # I was able to trigger short stalls (1sec) with aio-stress, and with the # current patch they are gone. Could be wishful thinking on my part though, # please let me know how this works for you. # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # fs/aio.c # 2004/08/24 02:08:36-07:00 suparna@in.ibm.com +46 -7 # AIO: workqueue context switch reduction # # ChangeSet # 2004/08/24 11:22:40-07:00 suparna@in.ibm.com # [PATCH] AIO: Splice runlist for fairness across io contexts # # This patch tries be a little fairer across multiple io contexts in handling # retries, helping make sure progress happens uniformly across different io # contexts (especially if they are acting on independent queues). # # It splices the ioctx runlist before processing it in __aio_run_iocbs. If # new iocbs get added to the ctx in meantime, it queues a fresh workqueue # entry instead of handling them righaway, so that other ioctxs' retries get # a chance to be processed before the newer entries in the queue. # # This might make a difference in a situation where retries are getting # queued very fast on one ioctx, while the workqueue entry for another ioctx # is stuck behind it. I've only seen this occasionally earlier and can't # recreate it consistently, but may be worth including anyway. # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # fs/aio.c # 2004/08/24 02:08:35-07:00 suparna@in.ibm.com +20 -6 # AIO: Splice runlist for fairness across io contexts # # ChangeSet # 2004/08/24 11:22:28-07:00 suparna@in.ibm.com # [PATCH] AIO: retry infrastructure fixes and enhancements # # From: Daniel McNeil # From: Chris Mason # # AIO: retry infrastructure fixes and enhancements # # Reorganises, comments and fixes the AIO retry logic. Fixes # and enhancements include: # # - Split iocb setup and execution in io_submit # (also fixes io_submit error reporting) # - Use aio workqueue instead of keventd for retries # - Default high level retry methods # - Subtle use_mm/unuse_mm fix # - Code commenting # - Fix aio process hang on EINVAL (Daniel McNeil) # - Hold the context lock across unuse_mm # - Acquire task_lock in use_mm() # - Allow fops to override the retry method with their own # - Elevated ref count for AIO retries (Daniel McNeil) # - set_fs needed when calling use_mm # - Flush workqueue on __put_ioctx (Chris Mason) # - Fix io_cancel to work with retries (Chris Mason) # - Read-immediate option for socket/pipe retry support # # Note on default high-level retry methods support # ================================================ # # High-level retry methods allows an AIO request to be executed as a series of # non-blocking iterations, where each iteration retries the remaining part of # the request from where the last iteration left off, by reissuing the # corresponding AIO fop routine with modified arguments representing the # remaining I/O. The retries are "kicked" via the AIO waitqueue callback # aio_wake_function() which replaces the default wait queue entry used for # blocking waits. # # The high level retry infrastructure is responsible for running the # iterations in the mm context (address space) of the caller, and ensures that # only one retry instance is active at a given time, thus relieving the fops # themselves from having to deal with potential races of that sort. # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # kernel/fork.c # 2004/08/24 02:08:35-07:00 suparna@in.ibm.com +13 -2 # AIO: retry infrastructure fixes and enhancements # # include/linux/wait.h # 2004/08/24 02:08:35-07:00 suparna@in.ibm.com +9 -0 # AIO: retry infrastructure fixes and enhancements # # include/linux/sched.h # 2004/08/24 02:08:35-07:00 suparna@in.ibm.com +7 -1 # AIO: retry infrastructure fixes and enhancements # # include/linux/errno.h # 2004/08/24 02:08:35-07:00 suparna@in.ibm.com +1 -0 # AIO: retry infrastructure fixes and enhancements # # include/linux/aio.h # 2004/08/24 02:08:35-07:00 suparna@in.ibm.com +27 -1 # AIO: retry infrastructure fixes and enhancements # # fs/aio.c # 2004/08/24 02:08:35-07:00 suparna@in.ibm.com +505 -95 # AIO: retry infrastructure fixes and enhancements # # ChangeSet # 2004/08/24 11:22:16-07:00 bjorn.helgaas@hp.com # [PATCH] cpqfc: add missing pci_enable_device() # # Add pci_enable_device()/pci_disable_device(). In the past, drivers # often worked without this, but it is now required in order to route # PCI interrupts correctly. # # Signed-off-by: Bjorn Helgaas # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # drivers/scsi/cpqfcTSinit.c # 2004/08/24 02:08:35-07:00 bjorn.helgaas@hp.com +35 -16 # cpqfc: add missing pci_enable_device() # # ChangeSet # 2004/08/24 11:22:05-07:00 bjorn.helgaas@hp.com # [PATCH] de4x5.c: add missing pci_enable_device() # # Add pci_enable_device()/pci_disable_device(). In the past, drivers # often worked without this, but it is now required in order to route # PCI interrupts correctly. # # Signed-off-by: Bjorn Helgaas # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # drivers/net/tulip/de4x5.c # 2004/08/24 02:08:34-07:00 bjorn.helgaas@hp.com +10 -2 # de4x5.c: add missing pci_enable_device() # # ChangeSet # 2004/08/24 11:21:53-07:00 bjorn.helgaas@hp.com # [PATCH] ioc3-eth.c: add missing pci_enable_device() # # Add pci_enable_device()/pci_disable_device(). In the past, drivers often # worked without this, but it is now required in order to route PCI interrupts # correctly. # # Signed-off-by: Bjorn Helgaas # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # drivers/net/ioc3-eth.c # 2004/08/24 02:08:34-07:00 bjorn.helgaas@hp.com +10 -2 # ioc3-eth.c: add missing pci_enable_device() # # ChangeSet # 2004/08/24 11:21:42-07:00 bjorn.helgaas@hp.com # [PATCH] hp100.c: add missing pci_enable_device() # # Add pci_enable_device()/pci_disable_device(). In the past, drivers often # worked without this, but it is now required in order to route PCI interrupts # correctly. # # Signed-off-by: Bjorn Helgaas # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # drivers/net/hp100.c # 2004/08/24 02:08:34-07:00 bjorn.helgaas@hp.com +9 -1 # hp100.c: add missing pci_enable_device() # # ChangeSet # 2004/08/24 11:21:30-07:00 bjorn.helgaas@hp.com # [PATCH] ibmasm: add missing pci_enable_device() # # Add pci_enable_device()/pci_disable_device(). In the past, drivers often # worked without this, but it is now required in order to route PCI # interrupts correctly. # # Signed-off-by: Bjorn Helgaas # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # drivers/misc/ibmasm/module.c # 2004/08/24 02:08:34-07:00 bjorn.helgaas@hp.com +11 -1 # ibmasm: add missing pci_enable_device() # # ChangeSet # 2004/08/24 11:21:20-07:00 bjorn.helgaas@hp.com # [PATCH] tpam_main.c: add missing pci_enable_device() # # Add pci_enable_device()/pci_disable_device(). In the past, drivers # often worked without this, but it is now required in order to route # PCI interrupts correctly. # # Signed-off-by: Bjorn Helgaas # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # drivers/isdn/tpam/tpam_main.c # 2004/08/24 02:08:33-07:00 bjorn.helgaas@hp.com +33 -14 # tpam_main.c: add missing pci_enable_device() # # ChangeSet # 2004/08/24 11:21:08-07:00 bjorn.helgaas@hp.com # [PATCH] ip2main.c: add missing pci_enable_device() # # I don't have this hardware, so this has been compiled but not tested. # # Add pci_enable_device()/pci_disable_device In the past, drivers often worked # without this, but it is now required in order to route PCI interrupts # correctly. In addition, this driver incorrectly used the IRQ value from PCI # config space rather than the one in the struct pci_dev. # # Signed-off-by: Bjorn Helgaas # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # drivers/char/ip2main.c # 2004/08/24 02:08:33-07:00 bjorn.helgaas@hp.com +13 -4 # ip2main.c: add missing pci_enable_device() # # drivers/char/ip2/ip2types.h # 2004/08/24 02:08:33-07:00 bjorn.helgaas@hp.com +3 -0 # ip2main.c: add missing pci_enable_device() # # ChangeSet # 2004/08/24 11:21:01-07:00 yoshfuji@linux-ipv6.org # [IPV6]: Fix device handling in ip6_route_add(). # # Signed-off-by: HIDEAKI Yoshifuji # Signed-off-by: David S. Miller # # ChangeSet # 2004/08/24 11:20:57-07:00 bjorn.helgaas@hp.com # [PATCH] idt77252.c: add missing pci_enable_device() # # Add pci_enable_device()/pci_disable_device(). In the past, drivers often # worked without this, but it is now required in order to route PCI # interrupts correctly. # # Signed-off-by: Bjorn Helgaas # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # drivers/atm/idt77252.c # 2004/08/24 02:08:33-07:00 bjorn.helgaas@hp.com +42 -26 # idt77252.c: add missing pci_enable_device() # # ChangeSet # 2004/08/24 11:20:45-07:00 haveblue@us.ibm.com # [PATCH] don't pass mem_map into init functions # # When using CONFIG_NONLINEAR, a zone's mem_map isn't contiguous, and isn't # allocated in the same place. This means that nonlinear doesn't really have # a mem_map[] to pass into free_area_init_node() or memmap_init_zone() which # makes any sense. # # So, this patch removes the 'struct page *mem_map' argument to both of # those functions. All non-NUMA architectures just pass a NULL in there, # which is ignored. The solution on the NUMA arches is to pass the mem_map in # via the pgdat, which works just fine. # # To replace the removed arguments, a call to pfn_to_page(node_start_pfn) is # made. This is valid because all of the pfn_to_page() implementations rely # only on the pgdats, which are already set up at this time. Plus, the # pfn_to_page() method should work for any future nonlinear-type code. # # Finally, the patch creates a function: node_alloc_mem_map(), which I plan # to effectively #ifdef out for nonlinear at some future date. # # Compile tested and booted on SMP x86, NUMAQ, and ppc64. # # From: Jesse Barnes # # Fix up ia64 specific memory map init function in light of Dave's # memmap_init cleanups. # # Signed-off-by: Jesse Barnes # # From: Dave Hansen # # Looks like I missed a couple of architectures. This patch, on top of my # previous one and Jesse's should clean up the rest. # # From: William Lee Irwin III # # x86-64 wouldn't compile with NUMA support on, as node_alloc_mem_map() # references mem_map outside #ifdefs on CONFIG_NUMA/CONFIG_DISCONTIGMEM. This # patch wraps that reference in such an #ifdef. # # From: William Lee Irwin III # # Initializing NODE_DATA(nid)->node_mem_map prior to calling it should do. # # From: Dave Hansen # # Rick, I bet you didn't think your nerf weapons would be so effective in # getting that compile error fixed, did you? # # Applying the attached patch and commenting out this line: # # arch/i386/kernel/nmi.c: In function `proc_unknown_nmi_panic': # arch/i386/kernel/nmi.c:558: too few arguments to function `proc_dointvec' # # will let it compile. # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # net/ipv6/route.c # 2004/08/24 11:20:43-07:00 yoshfuji@linux-ipv6.org +6 -3 # [IPV6]: Fix device handling in ip6_route_add(). # # Signed-off-by: HIDEAKI Yoshifuji # Signed-off-by: David S. Miller # # mm/page_alloc.c # 2004/08/24 02:08:33-07:00 haveblue@us.ibm.com +23 -18 # don't pass mem_map into init functions # # include/linux/mm.h # 2004/08/24 02:08:33-07:00 haveblue@us.ibm.com +2 -3 # don't pass mem_map into init functions # # include/asm-ia64/pgtable.h # 2004/08/24 02:08:33-07:00 haveblue@us.ibm.com +1 -1 # don't pass mem_map into init functions # # arch/x86_64/mm/numa.c # 2004/08/24 02:08:33-07:00 haveblue@us.ibm.com +1 -1 # don't pass mem_map into init functions # # arch/sparc64/mm/init.c # 2004/08/24 02:08:33-07:00 haveblue@us.ibm.com +1 -1 # don't pass mem_map into init functions # # arch/sparc/mm/sun4c.c # 2004/08/24 02:08:33-07:00 haveblue@us.ibm.com +1 -1 # don't pass mem_map into init functions # # arch/sparc/mm/srmmu.c # 2004/08/24 02:08:33-07:00 haveblue@us.ibm.com +1 -1 # don't pass mem_map into init functions # # arch/sh/mm/init.c # 2004/08/24 02:08:33-07:00 haveblue@us.ibm.com +1 -1 # don't pass mem_map into init functions # # arch/ppc64/mm/init.c # 2004/08/24 02:08:33-07:00 haveblue@us.ibm.com +1 -1 # don't pass mem_map into init functions # # arch/parisc/mm/init.c # 2004/08/24 02:08:33-07:00 haveblue@us.ibm.com +1 -1 # don't pass mem_map into init functions # # arch/mips/sgi-ip27/ip27-memory.c # 2004/08/24 02:08:33-07:00 haveblue@us.ibm.com +1 -1 # don't pass mem_map into init functions # # arch/ia64/mm/init.c # 2004/08/24 02:08:33-07:00 haveblue@us.ibm.com +6 -4 # don't pass mem_map into init functions # # arch/ia64/mm/discontig.c # 2004/08/24 02:08:33-07:00 haveblue@us.ibm.com +1 -2 # don't pass mem_map into init functions # # arch/ia64/mm/contig.c # 2004/08/24 02:08:33-07:00 haveblue@us.ibm.com +3 -2 # don't pass mem_map into init functions # # arch/i386/mm/discontig.c # 2004/08/24 02:08:33-07:00 haveblue@us.ibm.com +4 -4 # don't pass mem_map into init functions # # arch/arm/mm/init.c # 2004/08/24 02:08:33-07:00 haveblue@us.ibm.com +1 -1 # don't pass mem_map into init functions # # arch/alpha/mm/numa.c # 2004/08/24 02:08:33-07:00 haveblue@us.ibm.com +1 -1 # don't pass mem_map into init functions # # ChangeSet # 2004/08/24 11:20:32-07:00 guillaume.thouvenin@bull.net # [PATCH] watchdog: fix warning "defined but not used" # # Function wdtpci_init_one() in file wdt_pci.c generates a warning when # compiling the watchdog driver. # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # drivers/char/watchdog/wdt_pci.c # 2004/08/24 02:08:32-07:00 guillaume.thouvenin@bull.net +1 -1 # watchdog: fix warning "defined but not used" # # ChangeSet # 2004/08/24 11:20:21-07:00 wli@holomorphy.com # [PATCH] first/next_cpu returns values > NR_CPUS # # Zwane Mwaikambo wrote: # # The following caused some fireworks whilst merging i386 cpu hotplug. # any_online_cpu(0x2) returns 32 on i386 if we're forced to continue past the # only set bit due to the additional find_first_bit in the find_next_bit i386 # implementation. Not wanting to change current behaviour in the bitops # primitives and since the NR_CPUS thing is a cpumask issue, i've opted to fix # next_cpu() and first_cpu() instead. # # This might save a couple of lines of code. # # From: # # Fix cross-arch ulong/int disaster with find_next_bit(). # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # include/linux/cpumask.h # 2004/08/24 02:08:32-07:00 wli@holomorphy.com +3 -2 # first/next_cpu returns values > NR_CPUS # # ChangeSet # 2004/08/24 11:20:09-07:00 ak@suse.de # [PATCH] New x86-64 merge # # This fixes various issues in the previous update, in particular # a kernel without CONFIG_GART_IOMMU should boot now again, # # The kernel discoverys PCI BUS<->CPU affinity on AMD systems # now. It is so far used by dma_alloc_coherent to allocate memory # Experimental patches to add this to sysfs exist, but they're not # included yet. On systems with no memory on a CPU this information may # be wrong. # # It has a new experimental CONFIG_UNORDERED_IO option. When enabled # it uses write combining for stores to device iomemory mapping. This # may give better performance with some device drivers, but has a slight # risk of breaking drivers (in general if a driver works on ia64,ppc64,sparc64 # it should also work). Based on some discussions with Grant Grundler. # # It requires the driver to use memory barriers properly. I would be interested # in feedback on any performance changes you're seeing. For a production system I # would recommend to keep it turned off(although I run it on all my systems and # haven't run into any problems yet) # # ACPI and Centrino speedstep is enabled now for Nocona systems. # # The IOMMU code does lazy merging by default now, which should be safe # and may increase performance on block IO. It also avoids SAC force by default # now. # # The machine check code has been improved again, hopefully it is good # now. It will log now machine check events from before the last reset. # And various other fixes. # # The x86-64 parts are now gcc 3.5 clean. # # And various other fixes # # - Update defconfig # - Reset lost ticks on lost time warning, print RIP. # - Make TASK_SIZE test for 32bit (Arjan van de Ven) # - Work around bug in generic code that broke pcibus_to_cpumask # - Actually fix dummy iommu code # - Compile i386 acpi and speedstep-centrino cpufreq modules # - Export cpu_khz # - Fix compilation without GART_IOMMU # - Optimize find_*_bit functions for small fields # - Discover nodes near PCI busses on K8 (Travis Betak, changed by me) # - Optimize gart tlb flush slightly # - Add experimental CONFIG_UNORDERED_IO for unordered IO stores # - Add 32bit emulation for PTRACE_GETEVENTMSG # - Fix kernel_fpu_{begin,end} for preemptive kernels (Alexander Nyberg) # - Readd proper check for biomerge (got lost) # - Set up 32bit vsyscall page for ptrace early # - Add 32bit emulation for lookup_dcookie() for oprofile # - Export copy_page / clear_page # - Use rex prefix in save_init_fpu fxsave (Jan Beulich) # - Make it compile again # - Fix handling of hwdev == NULL (= ISA/LPC devices) in swiotlb # - Convert PCI DMA code to dma devices # - Change IOMMU code to use dummy fallback device instead of hardcoded # NULL tests everywhere. # - Test iommu_sac_force instead of nommu for DAC supported macro # (will cause more drivers to use DAC) # - Harden non IOMMU dma_alloc_consistent code to fail less likely. # - Remove use of strsep in option parsers # - Remove duplicated exports (Arjan van der Ven) # - Fix EFAULT checking in ptrace (John Blackwood) # - Update defconfig # - Remove dead URL from boot/setup.S (R.J. Wysocki) # - Use compat_sigval_t instead of sigval_t32 (Al Viro) # - Nanooptimization in 32bit ptregs calls # - Fix gcc 3.5 compilation in mtrr.h # - Pass pt_regs as pointer to avoid illegal pass by reference (for gcc 3.5) # - Make set_bit take int not long (Harald Dunkel) # - Avoid panic on pci_map_sg and pci_alloc_consistent overflow in GART IOMMU # - Handle large lost time delays in HPET code (Suresh B. Siddha) # - Work around theoretical bugs in prefetch handling (suggested by Jamie Lokier) # - Remove mtrr_strings declaration for gcc 3.5 # - Set KBUILD_IMAGE for make rpm (William Lee Irwin III) # - Add iommu=noaperture to not touch the aperture # - Clean up argument parsing for iommu= option # - Export symbols for xchgadd based rwsems (still disabled) # - Define iommu_bio_merge for !CONFIG_GART_IOMMU # - Don't use backwards rep ; movsb for memmove # - Out line bitmap search functions (saves 8k .text, from i386) # - Convert bitmap search functions to 64bit accesses and optimize them # a bit. # - Handle corrupted page tables in page fault handler # - Set iommu_merge (without force) to on by default again. # - Don't do bio merging by default for iommu=merge. This should make it # safe to use again # - Add iommu=biomerge option to enable BIO merging (like old iommu=merge) # - Fix iommu=memaper=... parsing # - More MCE fixes (based on a patch by Eric Morton, heavily changed by me) # - Fix check for banks causing exceptions # - Allow to reinit MCEs later even after mce=off, fix wrong # use of __initdata # to disable at boot, but reenable later. # - Log left over machine checks after boot and resume # - Fix missing prototype warning with CPU_FREQ on # - Fix parsing of noexec=on (Ian Hastie) # - Fix warning in ia32_binfmt.c # - Resync time variable cpu frequency handling with i386 # - Resync msr.c with i386 # - Add 0x60 level 1 intel cache descriptor (from i386) # - Remove duplicated 32bit ioctls (Arnd Bergmann) # - Enable -msoft-float (from i386) # - Use faster version of FPU hang fix - handle the exception # * a bit experimental, if you see "kernel ... math error" events # in the log please report. # # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # include/asm-x86_64/topology.h # 2004/08/24 02:08:31-07:00 ak@suse.de +7 -2 # New x86-64 merge # # include/asm-x86_64/system.h # 2004/08/24 02:08:31-07:00 ak@suse.de +4 -4 # New x86-64 merge # # include/asm-x86_64/swiotlb.h # 2004/08/24 11:20:02-07:00 ak@suse.de +36 -0 # # include/asm-x86_64/proto.h # 2004/08/24 02:08:31-07:00 ak@suse.de +2 -1 # New x86-64 merge # # include/asm-x86_64/pci.h # 2004/08/24 02:08:31-07:00 ak@suse.de +15 -238 # New x86-64 merge # # include/asm-x86_64/mtrr.h # 2004/08/24 02:08:31-07:00 ak@suse.de +0 -2 # New x86-64 merge # # include/asm-x86_64/mpspec.h # 2004/08/24 02:08:31-07:00 ak@suse.de +0 -1 # New x86-64 merge # # include/asm-x86_64/io.h # 2004/08/24 02:08:31-07:00 ak@suse.de +24 -7 # New x86-64 merge # # include/asm-x86_64/ia32.h # 2004/08/24 02:08:31-07:00 ak@suse.de +2 -8 # New x86-64 merge # # include/asm-x86_64/i387.h # 2004/08/24 02:08:31-07:00 ak@suse.de +20 -4 # New x86-64 merge # # include/asm-x86_64/dma-mapping.h # 2004/08/24 02:08:31-07:00 ak@suse.de +134 -1 # New x86-64 merge # # include/asm-x86_64/bitops.h # 2004/08/24 02:08:31-07:00 ak@suse.de +32 -123 # New x86-64 merge # # include/asm-x86_64/acpi.h # 2004/08/24 02:08:31-07:00 ak@suse.de +5 -0 # New x86-64 merge # # arch/x86_64/pci/k8-bus.c # 2004/08/24 11:20:02-07:00 ak@suse.de +74 -0 # # arch/x86_64/pci/Makefile # 2004/08/24 02:08:31-07:00 ak@suse.de +3 -1 # New x86-64 merge # # arch/x86_64/pci/Makefile-BUS # 2004/08/24 11:20:02-07:00 ak@suse.de +22 -0 # # arch/x86_64/mm/init.c # 2004/08/24 02:08:31-07:00 ak@suse.de +20 -2 # New x86-64 merge # # include/asm-x86_64/swiotlb.h # 2004/08/24 11:20:02-07:00 ak@suse.de +0 -0 # BitKeeper file /home/torvalds/v2.6/linux/include/asm-x86_64/swiotlb.h # # arch/x86_64/pci/k8-bus.c # 2004/08/24 11:20:02-07:00 ak@suse.de +0 -0 # BitKeeper file /home/torvalds/v2.6/linux/arch/x86_64/pci/k8-bus.c # # arch/x86_64/pci/Makefile-BUS # 2004/08/24 11:20:02-07:00 ak@suse.de +0 -0 # BitKeeper file /home/torvalds/v2.6/linux/arch/x86_64/pci/Makefile-BUS # # arch/x86_64/mm/fault.c # 2004/08/24 02:08:31-07:00 ak@suse.de +56 -21 # New x86-64 merge # # arch/x86_64/lib/memmove.c # 2004/08/24 02:08:31-07:00 ak@suse.de +4 -12 # New x86-64 merge # # arch/x86_64/lib/bitstr.c # 2004/08/24 02:08:31-07:00 ak@suse.de +3 -0 # New x86-64 merge # # arch/x86_64/lib/bitops.c # 2004/08/24 11:20:01-07:00 ak@suse.de +140 -0 # # arch/x86_64/lib/Makefile # 2004/08/24 02:08:31-07:00 ak@suse.de +1 -1 # New x86-64 merge # # arch/x86_64/kernel/x8664_ksyms.c # 2004/08/24 02:08:31-07:00 ak@suse.de +14 -11 # New x86-64 merge # # arch/x86_64/kernel/traps.c # 2004/08/24 02:08:31-07:00 ak@suse.de +37 -17 # New x86-64 merge # # arch/x86_64/kernel/time.c # 2004/08/24 02:08:31-07:00 ak@suse.de +80 -18 # New x86-64 merge # # arch/x86_64/kernel/signal.c # 2004/08/24 02:08:31-07:00 ak@suse.de +12 -11 # New x86-64 merge # # arch/x86_64/kernel/setup64.c # 2004/08/24 02:08:31-07:00 ak@suse.de +14 -12 # New x86-64 merge # # arch/x86_64/kernel/setup.c # 2004/08/24 02:08:31-07:00 ak@suse.de +3 -0 # New x86-64 merge # # arch/x86_64/kernel/ptrace.c # 2004/08/24 02:08:31-07:00 ak@suse.de +8 -6 # New x86-64 merge # # arch/x86_64/kernel/process.c # 2004/08/24 02:08:31-07:00 ak@suse.de +7 -7 # New x86-64 merge # # arch/x86_64/kernel/pci-nommu.c # 2004/08/24 02:08:31-07:00 ak@suse.de +44 -18 # New x86-64 merge # # arch/x86_64/kernel/pci-gart.c # 2004/08/24 02:08:31-07:00 ak@suse.de +168 -122 # New x86-64 merge # # arch/x86_64/kernel/pci-dma.c # 2004/08/24 02:08:31-07:00 ak@suse.de +10 -11 # New x86-64 merge # # arch/x86_64/kernel/msr.c # 2004/08/24 02:08:31-07:00 ak@suse.de +155 -160 # New x86-64 merge # # arch/x86_64/kernel/mce.c # 2004/08/24 02:08:31-07:00 ak@suse.de +62 -55 # New x86-64 merge # # arch/x86_64/kernel/ioport.c # 2004/08/24 02:08:31-07:00 ak@suse.de +3 -3 # New x86-64 merge # # arch/x86_64/kernel/entry.S # 2004/08/24 02:08:31-07:00 ak@suse.de +9 -7 # New x86-64 merge # # arch/x86_64/kernel/early_printk.c # 2004/08/24 02:08:31-07:00 ak@suse.de +9 -8 # New x86-64 merge # # arch/x86_64/kernel/cpufreq/Makefile # 2004/08/24 02:08:31-07:00 ak@suse.de +7 -1 # New x86-64 merge # # arch/x86_64/kernel/cpufreq/Kconfig # 2004/08/24 02:08:31-07:00 ak@suse.de +49 -0 # New x86-64 merge # # arch/x86_64/kernel/aperture.c # 2004/08/24 02:08:31-07:00 ak@suse.de +10 -13 # New x86-64 merge # # arch/x86_64/ia32/sys_ia32.c # 2004/08/24 02:08:31-07:00 ak@suse.de +14 -7 # New x86-64 merge # # arch/x86_64/ia32/ptrace32.c # 2004/08/24 02:08:31-07:00 ak@suse.de +5 -1 # New x86-64 merge # # arch/x86_64/ia32/ia32entry.S # 2004/08/24 02:08:31-07:00 ak@suse.de +15 -18 # New x86-64 merge # # arch/x86_64/ia32/ia32_signal.c # 2004/08/24 02:08:31-07:00 ak@suse.de +19 -14 # New x86-64 merge # # arch/x86_64/ia32/ia32_ioctl.c # 2004/08/24 02:08:31-07:00 ak@suse.de +0 -15 # New x86-64 merge # # arch/x86_64/ia32/ia32_binfmt.c # 2004/08/24 02:08:31-07:00 ak@suse.de +3 -0 # New x86-64 merge # # arch/x86_64/defconfig # 2004/08/24 02:08:31-07:00 ak@suse.de +76 -33 # New x86-64 merge # # arch/x86_64/Makefile # 2004/08/24 02:08:31-07:00 ak@suse.de +1 -0 # New x86-64 merge # # arch/x86_64/Kconfig # 2004/08/24 02:08:31-07:00 ak@suse.de +11 -0 # New x86-64 merge # # Documentation/x86_64/boot-options.txt # 2004/08/24 02:08:31-07:00 ak@suse.de +14 -6 # New x86-64 merge # # arch/x86_64/lib/bitops.c # 2004/08/24 11:20:01-07:00 ak@suse.de +0 -0 # BitKeeper file /home/torvalds/v2.6/linux/arch/x86_64/lib/bitops.c # # BitKeeper/deleted/.del-Makefile-HEAD~f95e78db221bb7a8 # 2004/08/24 11:20:01-07:00 ak@suse.de +0 -0 # Delete: arch/x86_64/kernel/Makefile-HEAD # # ChangeSet # 2004/08/24 11:19:45-07:00 akropel1@rochester.rr.com # [PATCH] preset loops_per_jiffy for faster booting # # Adds a kernel boot parameter "lpj=NNN" which allows the operator to specify # the loops-per-jiffy value. This shaves up to a quarter of a second off # boot times, which are critical for embedded appliances. # # It's a bit thin, but the code is in __init. # # Signed-off-by: Adam Kropelin # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # init/main.c # 2004/08/24 02:08:30-07:00 akropel1@rochester.rr.com +71 -40 # preset loops_per_jiffy for faster booting # # Documentation/kernel-parameters.txt # 2004/08/24 02:08:30-07:00 akropel1@rochester.rr.com +14 -0 # preset loops_per_jiffy for faster booting # # ChangeSet # 2004/08/24 11:19:34-07:00 mika@osdl.org # [PATCH] Fix drivers/isdn/hisax/avm_pci.c build warning when !CONFIG_ISAPNP # # CC [M] drivers/isdn/hisax/avm_pci.o # drivers/isdn/hisax/avm_pci.c: In function `setup_avm_pcipnp': # drivers/isdn/hisax/avm_pci.c:817: warning: label `ready' defined but not used # # Patch is big because I replaced the '} else { ... }' with 'goto ready; }' # and so had to remove one level of indentation from code. # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # drivers/isdn/hisax/avm_pci.c # 2004/08/24 02:08:30-07:00 mika@osdl.org +52 -52 # Fix drivers/isdn/hisax/avm_pci.c build warning when !CONFIG_ISAPNP # # ChangeSet # 2004/08/24 11:19:22-07:00 jdike@addtoit.com # [PATCH] Make UML build and run # # This patch includes the following - # updated defconfig # move uml.lds.S and main.c from arch/um to arch/um/kernel per Sam's suggestions # steal bitops.c from arch/i386 # convert all calls to open_private_file to dentry_open # # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # fs/hppfs/hppfs_kern.c # 2004/08/24 02:08:30-07:00 jdike@addtoit.com +21 -17 # Make UML build and run # # arch/um/sys-i386/Makefile # 2004/08/24 02:08:30-07:00 jdike@addtoit.com +4 -3 # Make UML build and run # # arch/um/kernel/uml.lds.S # 2004/08/24 02:08:30-07:00 jdike@addtoit.com +4 -4 # Make UML build and run # # arch/um/kernel/main.c # 2004/08/24 02:08:30-07:00 jdike@addtoit.com +12 -12 # Make UML build and run # # arch/um/kernel/Makefile # 2004/08/24 02:08:30-07:00 jdike@addtoit.com +3 -3 # Make UML build and run # # arch/um/defconfig # 2004/08/24 02:08:30-07:00 jdike@addtoit.com +6 -3 # Make UML build and run # # arch/um/Makefile # 2004/08/24 02:08:30-07:00 jdike@addtoit.com +2 -11 # Make UML build and run # # ChangeSet # 2004/08/24 11:18:53-07:00 jdike@addtoit.com # [PATCH] UML fixes # # The patch below fixes a few UML-specific bugs not related to the rest of the # kernel # a bogus error return and some formatting in the fork code # correct calculation of task.thread.kernel_stack # remove a bogus panic # a couple of fixes to allow UML to boot in the presence of exec-shield # # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # arch/um/kernel/tt/process_kern.c # 2004/08/24 02:08:29-07:00 jdike@addtoit.com +1 -1 # UML fixes # # arch/um/kernel/tt/mem.c # 2004/08/24 02:08:29-07:00 jdike@addtoit.com +1 -1 # UML fixes # # arch/um/kernel/trap_kern.c # 2004/08/24 02:08:29-07:00 jdike@addtoit.com +0 -2 # UML fixes # # arch/um/kernel/process_kern.c # 2004/08/24 02:08:29-07:00 jdike@addtoit.com +1 -1 # UML fixes # # arch/um/kernel/process.c # 2004/08/24 02:08:29-07:00 jdike@addtoit.com +7 -3 # UML fixes # # ChangeSet # 2004/08/24 11:18:42-07:00 jdike@addtoit.com # [PATCH] UML updates # # The patch below brings UML up to date with interface changes and the like # irq.c includes profile.h to bring in a missing definition # use the cpu_{set,clear} interface # use the new get_signal_to_deliver interface # define instruction_pointer # # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # include/asm-um/ptrace-generic.h # 2004/08/24 02:08:29-07:00 jdike@addtoit.com +2 -0 # UML updates # # arch/um/kernel/signal_kern.c # 2004/08/24 02:08:29-07:00 jdike@addtoit.com +5 -5 # UML updates # # arch/um/kernel/process_kern.c # 2004/08/24 02:08:29-07:00 jdike@addtoit.com +4 -3 # UML updates # # arch/um/kernel/irq.c # 2004/08/24 02:08:29-07:00 jdike@addtoit.com +1 -0 # UML updates # # ChangeSet # 2004/08/24 11:18:30-07:00 coywolf@greatcn.org # [PATCH] uml: remove a group of unused bh functions # # This patch removes a group of unused bh functions in um. This 2.2 legacy # code should be cleaned up. # # Signed-off-by: Coywolf Qi Hunt # Cc: Jeff Dike # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # arch/um/kernel/smp.c # 2004/08/24 02:08:29-07:00 coywolf@greatcn.org +0 -43 # uml: remove a group of unused bh functions # # ChangeSet # 2004/08/24 11:18:19-07:00 blaisorblade_spam@yahoo.it # [PATCH] uml: Fix os_process_pc and os_process_parent for corner cases. # # Update os_process_pc and os_process_parent: now a PID can be > 32768 (so # increase number of digits) and make it work even with spaces in the command # name. # # Signed-off-by: Paolo 'Blaisorblade' Giarrusso # Cc: Jeff Dike # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # arch/um/os-Linux/process.c # 2004/08/24 02:08:28-07:00 blaisorblade_spam@yahoo.it +8 -6 # uml: Fix os_process_pc and os_process_parent for corner cases. # # ChangeSet # 2004/08/24 11:18:07-07:00 blaisorblade_spam@yahoo.it # [PATCH] uml: little-kmalloc # # Signed-off-by: Paolo 'Blaisorblade' Giarrusso # Cc: Jeff Dike # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # arch/um/main.c # 2004/08/24 02:08:28-07:00 blaisorblade_spam@yahoo.it +1 -1 # uml: little-kmalloc # # ChangeSet # 2004/08/24 11:17:56-07:00 blaisorblade_spam@yahoo.it # [PATCH] uml: Make malloc() call vmalloc if needed. Needed for hostfs on 2.6 host. # # From: Oleg Drokin , Jeff Dike , and # me # # If size > 128K, with this patch malloc will call vmalloc; free will detect # whether to call vfree or kfree or __real_free(). The 2.4 version could forget # free()ing something; this has been fixed. # # Signed-off-by: Paolo 'Blaisorblade' Giarrusso # Cc: Jeff Dike # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # arch/um/main.c # 2004/08/24 02:08:28-07:00 blaisorblade_spam@yahoo.it +36 -4 # uml: Make malloc() call vmalloc if needed. Needed for hostfs on 2.6 host. # # arch/um/kernel/process_kern.c # 2004/08/24 02:08:28-07:00 blaisorblade_spam@yahoo.it +6 -0 # uml: Make malloc() call vmalloc if needed. Needed for hostfs on 2.6 host. # # arch/um/include/user.h # 2004/08/24 02:08:28-07:00 blaisorblade_spam@yahoo.it +2 -0 # uml: Make malloc() call vmalloc if needed. Needed for hostfs on 2.6 host. # # ChangeSet # 2004/08/24 11:17:44-07:00 blaisorblade_spam@yahoo.it # [PATCH] uml: Removes dead code in trap_kern.c # # That code comes from the out_of_memory section; in 2.4 it was correct to put # it for "default:", since it was called when handle_mm_fault() return value was # != 0, 1, 2, i.e. it was 3, OOM (but the i386 code put it out of line, for # better performance). Here, instead, the OOM case is handled on its own, so if # handle_mm_fault() != from the listed cases we must BUG(). # # Signed-off-by: Paolo 'Blaisorblade' Giarrusso # Cc: Jeff Dike # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # arch/um/kernel/trap_kern.c # 2004/08/24 02:08:28-07:00 blaisorblade_spam@yahoo.it +1 -8 # uml: Removes dead code in trap_kern.c # # ChangeSet # 2004/08/24 11:17:33-07:00 blaisorblade_spam@yahoo.it # [PATCH] uml: Avoids a panic for a legal situation # # From: Alex Züpke , and me # # SKAS mode is like 4G/4G (here we have actually 3G/3G) for guest processes, so # when checking for kernel stack overflow, we must first make sure we are # checking a kernel-space address. Also, correctly test for stack overflows # (i.e. check if there is less than 1k of stack left; see # arch/i386/kernel/irq.c:do_IRQ()). And also, THREAD_SIZE != PAGE_SIZE * 2, in # general (though this setting is almost never changed, so we didn't notice # this1). Thanks to the good eye of Alex Züpke for first seeing # this bug, and providing a test program: # # /* # * trigger.c - triggers panic("Kernel stack overflow") in UML # * # * 20040630, azu@sysgo.de # */ # # #include # #include # #include # #include # #include # #include # #include # # #define LOW 0xa0000000 # #define HIGH 0xb0000000 # # int main(int argc, char **argv) # { # unsigned long addr; # int fd; # # fd = open("/dev/zero", O_RDWR); # # printf("This may take some time ... one more cup of coffee ...\n"); # # for(addr = LOW; addr < HIGH; addr += 0x1000) # { # pid_t p; # if(mmap((void*)addr, 0x1000, PROT_READ, MAP_SHARED | MAP_FIXED, fd, 0) == MAP_FAILED) # printf("mmap failed\n"); # # p = fork(); # if(p == -1) # printf("fork failed\n"); # # if(p == 0) # { # /* child context */ # int *p = (int *)addr; # volatile int x; # # x = *p; # return 0; # } # /* father context */ # waitpid(p, 0, 0); # # if(munmap((void*)addr, 0x1000) == -1) # printf("munmap failed\n"); # } # # close(fd); # printf("done\n"); # } # # Signed-off-by: Paolo 'Blaisorblade' Giarrusso # Cc: Jeff Dike # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # ChangeSet # 2004/08/24 19:17:29+01:00 davej@redhat.com # [CPUFREQ] Fix silly typo that broke the compile. # # Signed-off-by: Dave Jones # # arch/um/kernel/trap_kern.c # 2004/08/24 02:08:28-07:00 blaisorblade_spam@yahoo.it +1 -1 # uml: Avoids a panic for a legal situation # # arch/um/kernel/skas/uaccess.c # 2004/08/24 02:08:28-07:00 blaisorblade_spam@yahoo.it +1 -1 # uml: Avoids a panic for a legal situation # # arch/um/kernel/process_kern.c # 2004/08/24 02:08:28-07:00 blaisorblade_spam@yahoo.it +1 -1 # uml: Avoids a panic for a legal situation # # ChangeSet # 2004/08/24 11:17:21-07:00 blaisorblade_spam@yahoo.it # [PATCH] uml: Adds some exports # # Adds some exports # # Signed-off-by: Paolo 'Blaisorblade' Giarrusso # Cc: Jeff Dike # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # arch/um/kernel/ksyms.c # 2004/08/24 02:08:27-07:00 blaisorblade_spam@yahoo.it +2 -0 # uml: Adds some exports # # arch/i386/kernel/cpu/cpufreq/longhaul.c # 2004/08/24 19:17:13+01:00 davej@redhat.com +1 -1 # [CPUFREQ] Fix silly typo that broke the compile. # # Signed-off-by: Dave Jones # # ChangeSet # 2004/08/24 11:17:10-07:00 blaisorblade_spam@yahoo.it # [PATCH] uml: Handles correctly errno == EINTR in lots of places. # # On various places (mostly waitpid() calls) this patch makes sure that if errno # == EINTR on return, then the syscall is endlessly retried. It also defines a # simple generic way to do this. # # Signed-off-by: # Cc: Jeff Dike # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # arch/um/os-Linux/process.c # 2004/08/24 02:08:27-07:00 blaisorblade_spam@yahoo.it +2 -1 # uml: Handles correctly errno == EINTR in lots of places. # # arch/um/os-Linux/drivers/tuntap_user.c # 2004/08/24 02:08:27-07:00 blaisorblade_spam@yahoo.it +2 -1 # uml: Handles correctly errno == EINTR in lots of places. # # arch/um/os-Linux/drivers/ethertap_user.c # 2004/08/24 02:08:27-07:00 blaisorblade_spam@yahoo.it +3 -1 # uml: Handles correctly errno == EINTR in lots of places. # # arch/um/kernel/user_util.c # 2004/08/24 02:08:27-07:00 blaisorblade_spam@yahoo.it +4 -6 # uml: Handles correctly errno == EINTR in lots of places. # # arch/um/kernel/tt/tracer.c # 2004/08/24 02:08:27-07:00 blaisorblade_spam@yahoo.it +2 -2 # uml: Handles correctly errno == EINTR in lots of places. # # arch/um/kernel/tt/ptproxy/proxy.c # 2004/08/24 02:08:27-07:00 blaisorblade_spam@yahoo.it +2 -2 # uml: Handles correctly errno == EINTR in lots of places. # # arch/um/kernel/tt/exec_user.c # 2004/08/24 02:08:27-07:00 blaisorblade_spam@yahoo.it +7 -2 # uml: Handles correctly errno == EINTR in lots of places. # # arch/um/kernel/trap_user.c # 2004/08/24 02:08:27-07:00 blaisorblade_spam@yahoo.it +8 -1 # uml: Handles correctly errno == EINTR in lots of places. # # arch/um/kernel/skas/process.c # 2004/08/24 02:08:27-07:00 blaisorblade_spam@yahoo.it +3 -3 # uml: Handles correctly errno == EINTR in lots of places. # # arch/um/kernel/skas/exec_user.c # 2004/08/24 02:08:27-07:00 blaisorblade_spam@yahoo.it +4 -2 # uml: Handles correctly errno == EINTR in lots of places. # # arch/um/kernel/process.c # 2004/08/24 02:08:27-07:00 blaisorblade_spam@yahoo.it +6 -5 # uml: Handles correctly errno == EINTR in lots of places. # # arch/um/kernel/helper.c # 2004/08/24 02:08:27-07:00 blaisorblade_spam@yahoo.it +2 -1 # uml: Handles correctly errno == EINTR in lots of places. # # arch/um/kernel/frame.c # 2004/08/24 02:08:27-07:00 blaisorblade_spam@yahoo.it +5 -3 # uml: Handles correctly errno == EINTR in lots of places. # # arch/um/include/user_util.h # 2004/08/24 02:08:27-07:00 blaisorblade_spam@yahoo.it +1 -0 # uml: Handles correctly errno == EINTR in lots of places. # # arch/um/drivers/slirp_user.c # 2004/08/24 02:08:27-07:00 blaisorblade_spam@yahoo.it +4 -4 # uml: Handles correctly errno == EINTR in lots of places. # # arch/um/drivers/slip_user.c # 2004/08/24 02:08:27-07:00 blaisorblade_spam@yahoo.it +4 -2 # uml: Handles correctly errno == EINTR in lots of places. # # arch/um/drivers/net_user.c # 2004/08/24 02:08:27-07:00 blaisorblade_spam@yahoo.it +2 -1 # uml: Handles correctly errno == EINTR in lots of places. # # ChangeSet # 2004/08/24 11:17:00-07:00 blaisorblade_spam@yahoo.it # [PATCH] uml: Fix for sysemu patches # # - Correct some silly errors (dereferencing a pointer before checking if it's # != NULL when creating /proc/sysemu, some error messages) # # - separate using_sysemu from sysemu_supported (so to refuse to activate # sysemu if it is not supported, avoiding panics) # # - not probe sysemu if in tt mode. # # Signed-off-by: # Cc: Jeff Dike # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # arch/um/kernel/skas/process_kern.c # 2004/08/24 02:08:26-07:00 blaisorblade_spam@yahoo.it +8 -6 # uml: Fix for sysemu patches # # arch/um/kernel/skas/process.c # 2004/08/24 02:08:26-07:00 blaisorblade_spam@yahoo.it +5 -4 # uml: Fix for sysemu patches # # arch/um/kernel/skas/include/ptrace-skas.h # 2004/08/24 02:08:26-07:00 blaisorblade_spam@yahoo.it +1 -0 # uml: Fix for sysemu patches # # arch/um/kernel/process.c # 2004/08/24 02:08:26-07:00 blaisorblade_spam@yahoo.it +44 -36 # uml: Fix for sysemu patches # # ChangeSet # 2004/08/24 11:16:48-07:00 blaisorblade_spam@yahoo.it # [PATCH] uml: Adds /proc/sysemu to toggle SYSEMU usage. # # Adds /proc/sysemu to toggle SYSEMU usage. # # Signed-off-by: Paolo 'Blaisorblade' Giarrusso # Cc: Jeff Dike # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # arch/um/kernel/skas/process_kern.c # 2004/08/24 02:08:26-07:00 blaisorblade_spam@yahoo.it +59 -0 # uml: Adds /proc/sysemu to toggle SYSEMU usage. # # arch/um/kernel/skas/process.c # 2004/08/24 02:08:26-07:00 blaisorblade_spam@yahoo.it +29 -33 # uml: Adds /proc/sysemu to toggle SYSEMU usage. # # arch/um/kernel/skas/include/ptrace-skas.h # 2004/08/24 02:08:26-07:00 blaisorblade_spam@yahoo.it +3 -1 # uml: Adds /proc/sysemu to toggle SYSEMU usage. # # arch/um/kernel/process.c # 2004/08/24 02:08:26-07:00 blaisorblade_spam@yahoo.it +2 -2 # uml: Adds /proc/sysemu to toggle SYSEMU usage. # # ChangeSet # 2004/08/24 11:16:37-07:00 blaisorblade_spam@yahoo.it # [PATCH] uml: Adds the "nosysemu" command line parameter to disable SYSEMU # # Adds the "nosysemu" command line parameter to disable SYSEMU # # Signed-off-by: Paolo 'Blaisorblade' Giarrusso # Cc: Jeff Dike # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # arch/um/kernel/process.c # 2004/08/24 02:08:26-07:00 blaisorblade_spam@yahoo.it +22 -4 # uml: Adds the "nosysemu" command line parameter to disable SYSEMU # # ChangeSet # 2004/08/24 11:16:25-07:00 blaisorblade_spam@yahoo.it # [PATCH] uml: Use PTRACE_SCEMU (the so-called SYSEMU) to reduce syscall cost. # # Turns off syscall emulation patch for ptrace (SYSEMU) on. SYSEMU is a # performance-patch introduced by Laurent Vivier. It changes behaviour of # ptrace() and helps reducing host context switch rate. To make it working, you # need a kernel patch for your host, too. See # http://perso.wanadoo.fr/laurent.vivier/UML/ for further information. # # Signed-off-by: Paolo 'Blaisorblade' Giarrusso # Cc: Jeff Dike # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # arch/um/kernel/skas/process.c # 2004/08/24 02:08:25-07:00 blaisorblade_spam@yahoo.it +22 -0 # uml: Use PTRACE_SCEMU (the so-called SYSEMU) to reduce syscall cost. # # arch/um/kernel/skas/include/ptrace-skas.h # 2004/08/24 02:08:25-07:00 blaisorblade_spam@yahoo.it +7 -0 # uml: Use PTRACE_SCEMU (the so-called SYSEMU) to reduce syscall cost. # # arch/um/kernel/process.c # 2004/08/24 02:08:25-07:00 blaisorblade_spam@yahoo.it +35 -0 # uml: Use PTRACE_SCEMU (the so-called SYSEMU) to reduce syscall cost. # # ChangeSet # 2004/08/24 11:16:14-07:00 blaisorblade_spam@yahoo.it # [PATCH] uml: Folds hostaudio_user.c into hostaudio_kern.c. # # Folds hostaudio_user.c into hostaudio_kern.c. A lot of code less. Also note # that I no more update ppos(as I used to do in the 2.4 patch): I checked that # OSS never changes ppos, so hostaudio did the right thing. # # Signed-off-by: Paolo 'Blaisorblade' Giarrusso # Cc: Jeff Dike # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # arch/um/drivers/hostaudio_kern.c # 2004/08/24 02:08:25-07:00 blaisorblade_spam@yahoo.it +49 -24 # uml: Folds hostaudio_user.c into hostaudio_kern.c. # # arch/um/drivers/Makefile # 2004/08/24 02:08:25-07:00 blaisorblade_spam@yahoo.it +1 -1 # uml: Folds hostaudio_user.c into hostaudio_kern.c. # # BitKeeper/deleted/.del-hostaudio_user.c~f70654a46a8dd652 # 2004/08/24 11:16:08-07:00 blaisorblade_spam@yahoo.it +0 -0 # Delete: arch/um/drivers/hostaudio_user.c # # BitKeeper/deleted/.del-hostaudio.h~1b691cc72344dc1 # 2004/08/24 11:16:08-07:00 blaisorblade_spam@yahoo.it +0 -0 # Delete: arch/um/include/hostaudio.h # # ChangeSet # 2004/08/24 11:16:02-07:00 blaisorblade_spam@yahoo.it # [PATCH] uml: Fixes raw() and uses it in check_one_sigio; also fixes a silly panic (EINTR returned by call). # # Fixes raw() and uses it in check_one_sigio; also fixes a silly panic (EINTR # returned by call). # # Signed-off-by: Paolo 'Blaisorblade' Giarrusso # Cc: Jeff Dike # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # arch/um/kernel/user_util.c # 2004/08/24 02:08:25-07:00 blaisorblade_spam@yahoo.it +24 -5 # uml: Fixes raw() and uses it in check_one_sigio; also fixes a silly panic (EINTR returned by call). # # arch/um/kernel/sigio_user.c # 2004/08/24 02:08:25-07:00 blaisorblade_spam@yahoo.it +4 -7 # uml: Fixes raw() and uses it in check_one_sigio; also fixes a silly panic (EINTR returned by call). # # arch/um/include/user_util.h # 2004/08/24 02:08:25-07:00 blaisorblade_spam@yahoo.it +3 -1 # uml: Fixes raw() and uses it in check_one_sigio; also fixes a silly panic (EINTR returned by call). # # ChangeSet # 2004/08/24 11:15:51-07:00 blaisorblade_spam@yahoo.it # [PATCH] uml: Reduces code in *_user files, by moving it in _kern files if already possible. # # Reduces code in *_user files, by moving it in _kern files if already possible. # # Signed-off-by: Paolo 'Blaisorblade' Giarrusso # Cc: Jeff Dike # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # arch/um/drivers/chan_user.c # 2004/08/24 02:08:25-07:00 blaisorblade_spam@yahoo.it +0 -48 # uml: Reduces code in *_user files, by moving it in _kern files if already possible. # # arch/um/drivers/chan_kern.c # 2004/08/24 02:08:25-07:00 blaisorblade_spam@yahoo.it +47 -0 # uml: Reduces code in *_user files, by moving it in _kern files if already possible. # # ChangeSet # 2004/08/24 11:15:40-07:00 blaisorblade_spam@yahoo.it # [PATCH] uml: Avoids compile failure when host misses tkill(). # # Avoids compile failure when host misses tkill(), by simply using kill() in # that case. # # Signed-off-by: Paolo 'Blaisorblade' Giarrusso # Cc: Jeff Dike # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # arch/um/os-Linux/process.c # 2004/08/24 02:08:24-07:00 blaisorblade_spam@yahoo.it +4 -1 # uml: Avoids compile failure when host misses tkill(). # # ChangeSet # 2004/08/24 11:15:29-07:00 blaisorblade_spam@yahoo.it # [PATCH] uml: Kill useless warnings # # Fixes some little warnings about "Defined but not used ..." by #ifdef'ing # things # # Signed-off-by: Paolo 'Blaisorblade' Giarrusso # Cc: Jeff Dike # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # fs/hostfs/hostfs_kern.c # 2004/08/24 02:08:24-07:00 blaisorblade_spam@yahoo.it +2 -0 # uml: Kill useless warnings # # arch/um/kernel/time_kern.c # 2004/08/24 02:08:24-07:00 blaisorblade_spam@yahoo.it +3 -1 # uml: Kill useless warnings # # arch/um/kernel/time.c # 2004/08/24 02:08:24-07:00 blaisorblade_spam@yahoo.it +1 -0 # uml: Kill useless warnings # # ChangeSet # 2004/08/24 11:15:17-07:00 blaisorblade_spam@yahoo.it # [PATCH] uml: Fixes "fixdep.c" to support arch/um/include/uml-config.h. # # You probably saw that if you change one config option, even if # linux/autoconf.h (which is included by everything) changes, the kernel is # smart enough not to recompile everything. But with UML this no more holds. # Why? Because, as you see in this patch, fixdep avoids making anything depend # onto linux/autoconf.h *explicitly*, but nobody taught him to do the same for # arch/um/include/uml-config.h. So apply this patch. Do not say "I don't want # to change the generic Kbuild for one arch": this cannot hurt. It's a bugfix # for us, a no-op for others. # # Note: with this patch, fixdep will still add a dependency from a file # containing UML_CONFIG_BYE onto CONFIG_BYE. Since someone could think that # fixdep should grep for [^A-Z_]CONFIG_ rather than simply for CONFIG_, I've # added a comment that ask *not to fix* this "bug". # # Signed-off-by: Paolo 'Blaisorblade' Giarrusso # Cc: Jeff Dike # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # scripts/basic/fixdep.c # 2004/08/24 02:08:24-07:00 blaisorblade_spam@yahoo.it +9 -0 # uml: Fixes "fixdep.c" to support arch/um/include/uml-config.h. # # ChangeSet # 2004/08/24 11:15:06-07:00 blaisorblade_spam@yahoo.it # [PATCH] uml: Makes "make help ARCH=um" work. # # Makes "make help ARCH=um" work. # # Signed-off-by: Paolo 'Blaisorblade' Giarrusso # Cc: Jeff Dike # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # arch/um/Makefile # 2004/08/24 02:08:24-07:00 blaisorblade_spam@yahoo.it +6 -0 # uml: Makes "make help ARCH=um" work. # # ChangeSet # 2004/08/24 11:14:54-07:00 blaisorblade_spam@yahoo.it # [PATCH] uml: Adds LEGACY_PTY config option # # The second adds the LEGACY_PTY config option. Without it, with late 2.6 kernels # /dev/ptyxx won't work. In fact, with those kernels, root_fs_toms does not # work, because it's "unable to allocate TTY pair". And removes the dead option # "UNIX98_PTY_COUNT" (just commented out for now). # # Signed-off-by: Paolo 'Blaisorblade' Giarrusso # Cc: Jeff Dike # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # arch/um/Kconfig_char # 2004/08/24 02:08:23-07:00 blaisorblade_spam@yahoo.it +52 -3 # uml: Adds LEGACY_PTY config option # # ChangeSet # 2004/08/24 11:14:43-07:00 blaisorblade_spam@yahoo.it # [PATCH] uml: Fixes an host fd leak caused by hostfs. # # In detail, on 2.4 we used force_delete() to make sure inode were not cached, # and we then close the host file when the inode is cleared; when porting to 2.6 # the "force_delete" thing was dropped, and this patch adds a fix for this (by # setting drop_inode = generic_delete_inode). Search for drop_inode in the 2.6 # Documentation/filesystems/vfs.txt for info about this. # # Signed-off-by: Paolo 'Blaisorblade' Giarrusso # Cc: Jeff Dike # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # fs/hostfs/hostfs_kern.c # 2004/08/24 02:08:23-07:00 blaisorblade_spam@yahoo.it +15 -1 # uml: Fixes an host fd leak caused by hostfs. # # ChangeSet # 2004/08/24 11:14:34-07:00 blaisorblade_spam@yahoo.it # [PATCH] uml: Avoid that gcc breaks UML with "unit at a time" compilation mode. # # Avoid that gcc breaks UML with "unit at a time" compilation mode. # # Signed-off-by: Paolo 'Blaisorblade' Giarrusso # Cc: Jeff Dike # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # arch/um/Makefile # 2004/08/24 02:08:23-07:00 blaisorblade_spam@yahoo.it +2 -0 # uml: Avoid that gcc breaks UML with "unit at a time" compilation mode. # # ChangeSet # 2004/08/24 11:14:22-07:00 blaisorblade_spam@yahoo.it # [PATCH] uml: Readds (just for now) ghash.h for UML # # Just for now and just for UML; it will go away. # # Signed-off-by: Paolo 'Blaisorblade' Giarrusso # Cc: Jeff Dike # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # include/linux/ghash.h # 2004/08/24 02:08:23-07:00 blaisorblade_spam@yahoo.it +236 -0 # uml: Readds (just for now) ghash.h for UML # # include/linux/ghash.h # 2004/08/24 02:08:23-07:00 blaisorblade_spam@yahoo.it +0 -0 # BitKeeper file /home/torvalds/v2.6/linux/include/linux/ghash.h # # ChangeSet # 2004/08/24 11:14:10-07:00 blaisorblade_spam@yahoo.it # [PATCH] uml: rename console_device # # In the -mm tree (in this moment) and not in 2.6.7 there is another # console_device in include/linux/console.h; so I renamed the UML one (it's # static). # # Cc: Jeff Dike # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # arch/um/drivers/stdio_console.c # 2004/08/24 02:08:22-07:00 blaisorblade_spam@yahoo.it +2 -2 # uml: rename console_device # # ChangeSet # 2004/08/24 11:13:58-07:00 akpm@osdl.org # [PATCH] uml: CPU scheduler update # # Update UML for CPU scheduler changes # # Cc: Jeff Dike # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # arch/um/kernel/smp.c # 2004/08/24 02:08:22-07:00 akpm@osdl.org +1 -3 # uml: CPU scheduler update # # ChangeSet # 2004/08/24 11:13:46-07:00 jdike@addtoit.com # [PATCH] UML updates # # The patch below brings UML up to date with some changes in the rest of the # kernel: # an updated defconfig # checksum.h includes in6.h to get a definition of in6_addr # added a missing cpu_{set,clear} change # removed include/asm-um/module.h since it's really a link # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # include/asm-um/mmu_context.h # 2004/08/24 02:08:22-07:00 jdike@addtoit.com +2 -2 # UML updates # # arch/um/util/Makefile # 2004/08/24 02:08:22-07:00 jdike@addtoit.com +2 -2 # UML updates # # arch/um/kernel/skas/Makefile # 2004/08/24 02:08:22-07:00 jdike@addtoit.com +1 -1 # UML updates # # arch/um/include/sysdep-i386/checksum.h # 2004/08/24 02:08:22-07:00 jdike@addtoit.com +1 -0 # UML updates # # arch/um/defconfig # 2004/08/24 02:08:22-07:00 jdike@addtoit.com +61 -38 # UML updates # # BitKeeper/deleted/.del-module.h~8f403f09bbc33f5f # 2004/08/24 11:13:40-07:00 jdike@addtoit.com +0 -0 # Delete: include/asm-um/module.h # # ChangeSet # 2004/08/24 11:13:34-07:00 jdike@addtoit.com # [PATCH] UML: remove the COW block driver # # The code is still there but it's not built. Below is a patch which removes # it totally. # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # arch/um/drivers/Makefile # 2004/08/24 02:08:21-07:00 jdike@addtoit.com +0 -1 # UML: remove the COW block driver # # arch/um/Kconfig_block # 2004/08/24 02:08:21-07:00 jdike@addtoit.com +1 -11 # UML: remove the COW block driver # # BitKeeper/deleted/.del-cow_kern.c~32cc72171d064720 # 2004/08/24 11:13:28-07:00 jdike@addtoit.com +0 -0 # Delete: arch/um/drivers/cow_kern.c # # ChangeSet # 2004/08/24 11:13:23-07:00 blaisorblade_spam@yahoo.it # [PATCH] uml: Uml base patch # # The main part of UML; it is the last distributed patch for 2.6.7 Removes skas # support from the main UML patch; apply or get conflicts. # # Signed-off-by: Paolo 'Blaisorblade' Giarrusso # Cc: Jeff Dike # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # mm/page_alloc.c # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +4 -0 # uml: Uml base patch # # include/linux/time.h # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +1 -1 # uml: Uml base patch # # include/linux/gfp.h # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +5 -0 # uml: Uml base patch # # include/asm-um/unistd.h # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +4 -1 # uml: Uml base patch # # include/asm-um/uaccess.h # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +2 -0 # uml: Uml base patch # # include/asm-um/timex.h # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +0 -2 # uml: Uml base patch # # include/asm-um/thread_info.h # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +11 -5 # uml: Uml base patch # # include/asm-um/system-i386.h # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +0 -31 # uml: Uml base patch # # include/asm-um/system-generic.h # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +7 -2 # uml: Uml base patch # # include/asm-um/smp.h # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +1 -1 # uml: Uml base patch # # include/asm-um/processor-i386.h # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +2 -2 # uml: Uml base patch # # include/asm-um/processor-generic.h # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +20 -23 # uml: Uml base patch # # include/asm-um/pgtable.h # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +69 -42 # uml: Uml base patch # # include/asm-um/page.h # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +19 -15 # uml: Uml base patch # # include/asm-um/irq.h # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +0 -18 # uml: Uml base patch # # include/asm-um/fixmap.h # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +8 -0 # uml: Uml base patch # # include/asm-um/elf.h # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +13 -0 # uml: Uml base patch # # include/asm-um/dma-mapping.h # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +119 -1 # uml: Uml base patch # # include/asm-um/current.h # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +4 -2 # uml: Uml base patch # # include/asm-um/common.lds.S # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +35 -13 # uml: Uml base patch # # include/asm-um/archparam-i386.h # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +88 -1 # uml: Uml base patch # # fs/Makefile # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +2 -0 # uml: Uml base patch # # arch/um/util/mk_constants_kern.c # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +4 -0 # uml: Uml base patch # # arch/um/util/Makefile # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +6 -21 # uml: Uml base patch # # arch/um/uml.lds.S # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +7 -3 # uml: Uml base patch # # arch/um/sys-ppc/Makefile # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +1 -10 # uml: Uml base patch # # arch/um/sys-ia64/Makefile # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +1 -14 # uml: Uml base patch # # arch/um/sys-i386/util/mk_sc.c # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +1 -0 # uml: Uml base patch # # arch/um/sys-i386/util/Makefile # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +5 -9 # uml: Uml base patch # # arch/um/sys-i386/ptrace_user.c # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +4 -4 # uml: Uml base patch # # arch/um/sys-i386/fault.c # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +12 -4 # uml: Uml base patch # # arch/um/sys-i386/bugs.c # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +102 -38 # uml: Uml base patch # # arch/um/sys-i386/Makefile # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +6 -18 # uml: Uml base patch # # arch/um/os-Linux/tty.c # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +5 -5 # uml: Uml base patch # # arch/um/os-Linux/process.c # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +33 -25 # uml: Uml base patch # # arch/um/os-Linux/file.c # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +382 -68 # uml: Uml base patch # # arch/um/os-Linux/drivers/tuntap_user.c # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +29 -28 # uml: Uml base patch # # arch/um/os-Linux/drivers/ethertap_user.c # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +28 -28 # uml: Uml base patch # # arch/um/os-Linux/drivers/ethertap_kern.c # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +0 -1 # uml: Uml base patch # # arch/um/os-Linux/Makefile # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +1 -5 # uml: Uml base patch # # arch/um/main.c # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +5 -2 # uml: Uml base patch # # arch/um/kernel/user_util.c # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +2 -13 # uml: Uml base patch # # arch/um/kernel/umid.c # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +46 -34 # uml: Uml base patch # # arch/um/kernel/um_arch.c # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +50 -26 # uml: Uml base patch # # arch/um/kernel/uaccess_user.c # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +1 -1 # uml: Uml base patch # # arch/um/kernel/tty_log.c # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +117 -19 # uml: Uml base patch # # arch/um/kernel/tt/unmap.c # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +0 -3 # uml: Uml base patch # # include/asm-um/sections.h # 2004/08/24 11:13:14-07:00 blaisorblade_spam@yahoo.it +7 -0 # # include/asm-um/module-i386.h # 2004/08/24 11:13:14-07:00 blaisorblade_spam@yahoo.it +13 -0 # # include/asm-um/module-generic.h # 2004/08/24 11:13:14-07:00 blaisorblade_spam@yahoo.it +6 -0 # # include/asm-um/local.h # 2004/08/24 11:13:14-07:00 blaisorblade_spam@yahoo.it +6 -0 # # include/asm-um/cpufeature.h # 2004/08/24 11:13:14-07:00 blaisorblade_spam@yahoo.it +6 -0 # # fs/hppfs/hppfs_kern.c # 2004/08/24 11:13:14-07:00 blaisorblade_spam@yahoo.it +811 -0 # # fs/hppfs/Makefile # 2004/08/24 11:13:14-07:00 blaisorblade_spam@yahoo.it +19 -0 # # fs/hostfs/hostfs_user.c # 2004/08/24 11:13:14-07:00 blaisorblade_spam@yahoo.it +361 -0 # # fs/hostfs/hostfs_kern.c # 2004/08/24 11:13:14-07:00 blaisorblade_spam@yahoo.it +1008 -0 # # fs/hostfs/hostfs.h # 2004/08/24 11:13:14-07:00 blaisorblade_spam@yahoo.it +79 -0 # # fs/hostfs/Makefile # 2004/08/24 11:13:14-07:00 blaisorblade_spam@yahoo.it +26 -0 # # arch/um/sys-i386/time.c # 2004/08/24 11:13:14-07:00 blaisorblade_spam@yahoo.it +24 -0 # # arch/um/os-Linux/user_syms.c # 2004/08/24 11:13:14-07:00 blaisorblade_spam@yahoo.it +88 -0 # # arch/um/kernel/tt/uaccess_user.c # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +17 -5 # uml: Uml base patch # # arch/um/kernel/tt/uaccess.c # 2004/08/24 11:13:14-07:00 blaisorblade_spam@yahoo.it +73 -0 # # arch/um/kernel/tt/tracer.c # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +14 -13 # uml: Uml base patch # # arch/um/kernel/tt/tlb.c # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +1 -0 # uml: Uml base patch # # arch/um/kernel/tt/syscall_user.c # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +2 -2 # uml: Uml base patch # # arch/um/kernel/tt/syscall_kern.c # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +1 -1 # uml: Uml base patch # # arch/um/kernel/tt/sys-i386/Makefile # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +0 -2 # uml: Uml base patch # # arch/um/kernel/tt/ptproxy/wait.c # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +7 -5 # uml: Uml base patch # # arch/um/kernel/tt/ptproxy/sysdep.c # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +1 -0 # uml: Uml base patch # # arch/um/kernel/tt/ptproxy/proxy.c # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +13 -12 # uml: Uml base patch # # arch/um/kernel/tt/ptproxy/Makefile # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +0 -2 # uml: Uml base patch # # arch/um/kernel/tt/process_kern.c # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +52 -30 # uml: Uml base patch # # arch/um/kernel/tt/mem_user.c # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +3 -4 # uml: Uml base patch # # arch/um/kernel/tt/include/uaccess.h # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +7 -53 # uml: Uml base patch # # arch/um/kernel/tt/include/mode.h # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +2 -0 # uml: Uml base patch # # arch/um/kernel/tt/exec_kern.c # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +4 -3 # uml: Uml base patch # # arch/um/kernel/tt/Makefile # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +2 -4 # uml: Uml base patch # # arch/um/kernel/trap_user.c # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +4 -5 # uml: Uml base patch # # arch/um/kernel/trap_kern.c # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +49 -9 # uml: Uml base patch # # arch/um/kernel/time_kern.c # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +59 -18 # uml: Uml base patch # # arch/um/kernel/time.c # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +61 -8 # uml: Uml base patch # # arch/um/kernel/tempfile.c # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +5 -2 # uml: Uml base patch # # arch/um/kernel/sysrq.c # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +5 -0 # uml: Uml base patch # # arch/um/kernel/syscall_kern.c # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +15 -49 # uml: Uml base patch # # arch/um/kernel/sys_call_table.c # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +252 -434 # uml: Uml base patch # # arch/um/kernel/smp.c # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +37 -26 # uml: Uml base patch # # arch/um/kernel/skas/util/mk_ptregs.c # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +1 -0 # uml: Uml base patch # # arch/um/kernel/skas/util/Makefile # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +3 -4 # uml: Uml base patch # # arch/um/kernel/skas/uaccess.c # 2004/08/24 11:13:14-07:00 blaisorblade_spam@yahoo.it +219 -0 # # arch/um/kernel/skas/trap_user.c # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +1 -5 # uml: Uml base patch # # arch/um/kernel/skas/syscall_user.c # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +2 -2 # uml: Uml base patch # # arch/um/kernel/skas/syscall_kern.c # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +1 -1 # uml: Uml base patch # # arch/um/kernel/skas/sys-i386/sigcontext.c # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +7 -8 # uml: Uml base patch # # arch/um/kernel/skas/sys-i386/Makefile # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +0 -2 # uml: Uml base patch # # arch/um/kernel/skas/process_kern.c # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +15 -11 # uml: Uml base patch # # arch/um/kernel/skas/process.c # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +71 -36 # uml: Uml base patch # # arch/um/kernel/skas/mmu.c # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +5 -3 # uml: Uml base patch # # arch/um/kernel/skas/mem_user.c # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +21 -11 # uml: Uml base patch # # arch/um/kernel/skas/include/uaccess.h # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +7 -200 # uml: Uml base patch # # arch/um/kernel/skas/include/skas.h # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +2 -2 # uml: Uml base patch # # arch/um/kernel/skas/include/mode.h # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +4 -2 # uml: Uml base patch # # arch/um/kernel/skas/Makefile # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +14 -10 # uml: Uml base patch # # arch/um/kernel/signal_kern.c # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +49 -11 # uml: Uml base patch # # arch/um/kernel/sigio_user.c # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +47 -49 # uml: Uml base patch # # arch/um/kernel/sigio_kern.c # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +5 -2 # uml: Uml base patch # # arch/um/kernel/reboot.c # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +2 -0 # uml: Uml base patch # # arch/um/kernel/ptrace.c # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +12 -11 # uml: Uml base patch # # arch/um/kernel/process_kern.c # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +26 -19 # uml: Uml base patch # # arch/um/kernel/process.c # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +11 -9 # uml: Uml base patch # # arch/um/kernel/physmem.c # 2004/08/24 11:13:14-07:00 blaisorblade_spam@yahoo.it +468 -0 # # arch/um/kernel/mem_user.c # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +108 -122 # uml: Uml base patch # # arch/um/kernel/mem.c # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +74 -583 # uml: Uml base patch # # arch/um/kernel/ksyms.c # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +47 -6 # uml: Uml base patch # # arch/um/kernel/irq_user.c # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +17 -20 # uml: Uml base patch # # arch/um/kernel/irq.c # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +52 -53 # uml: Uml base patch # # arch/um/kernel/initrd_user.c # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +7 -6 # uml: Uml base patch # # arch/um/kernel/init_task.c # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +1 -16 # uml: Uml base patch # # arch/um/kernel/helper.c # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +36 -19 # uml: Uml base patch # # arch/um/kernel/frame_kern.c # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +4 -2 # uml: Uml base patch # # arch/um/kernel/frame.c # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +1 -2 # uml: Uml base patch # # arch/um/kernel/exec_kern.c # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +5 -0 # uml: Uml base patch # # arch/um/kernel/config.c.in # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +1 -3 # uml: Uml base patch # # arch/um/kernel/Makefile # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +14 -30 # uml: Uml base patch # # arch/um/include/user_util.h # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +3 -4 # uml: Uml base patch # # arch/um/include/user.h # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +1 -0 # uml: Uml base patch # # arch/um/include/um_uaccess.h # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +51 -0 # uml: Uml base patch # # arch/um/include/ubd_user.h # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +5 -4 # uml: Uml base patch # # arch/um/include/sysdep-i386/syscalls.h # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +27 -32 # uml: Uml base patch # # arch/um/include/sysdep-i386/sigcontext.h # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +2 -2 # uml: Uml base patch # # arch/um/include/sysdep-i386/frame_user.h # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +14 -14 # uml: Uml base patch # # arch/um/include/skas_ptrace.h # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +1 -1 # uml: Uml base patch # # arch/um/include/signal_user.h # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +2 -0 # uml: Uml base patch # # arch/um/include/os.h # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +49 -4 # uml: Uml base patch # # arch/um/include/mem_user.h # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +13 -18 # uml: Uml base patch # # arch/um/include/mem_kern.h # 2004/08/24 11:13:14-07:00 blaisorblade_spam@yahoo.it +30 -0 # # arch/um/include/mem.h # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +7 -8 # uml: Uml base patch # # arch/um/include/mconsole.h # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +5 -1 # uml: Uml base patch # # arch/um/include/line.h # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +2 -2 # uml: Uml base patch # # arch/um/include/kern_util.h # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +6 -5 # uml: Uml base patch # # arch/um/include/irq_kern.h # 2004/08/24 11:13:14-07:00 blaisorblade_spam@yahoo.it +28 -0 # # arch/um/include/2_5compat.h # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +0 -14 # uml: Uml base patch # # arch/um/dyn.lds.S # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +11 -4 # uml: Uml base patch # # arch/um/drivers/xterm_kern.c # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +9 -3 # uml: Uml base patch # # arch/um/drivers/xterm.c # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +11 -10 # uml: Uml base patch # # arch/um/drivers/ubd_user.c # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +126 -371 # uml: Uml base patch # # arch/um/drivers/ubd_kern.c # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +467 -133 # uml: Uml base patch # # arch/um/drivers/tty.c # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +2 -2 # uml: Uml base patch # # arch/um/drivers/stdio_console.c # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +33 -21 # uml: Uml base patch # # arch/um/drivers/ssl.c # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +43 -6 # uml: Uml base patch # # arch/um/drivers/slirp_user.c # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +7 -8 # uml: Uml base patch # # arch/um/drivers/slip_user.c # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +34 -39 # uml: Uml base patch # # arch/um/drivers/pty.c # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +11 -11 # uml: Uml base patch # # arch/um/drivers/port_user.c # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +19 -12 # uml: Uml base patch # # arch/um/drivers/port_kern.c # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +10 -7 # uml: Uml base patch # # arch/um/drivers/null.c # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +0 -1 # uml: Uml base patch # # arch/um/drivers/net_user.c # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +22 -24 # uml: Uml base patch # # arch/um/drivers/net_kern.c # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +32 -57 # uml: Uml base patch # # arch/um/drivers/mmapper_kern.c # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +4 -1 # uml: Uml base patch # # arch/um/drivers/mconsole_user.c # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +14 -11 # uml: Uml base patch # # arch/um/drivers/mconsole_kern.c # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +120 -20 # uml: Uml base patch # # arch/um/drivers/mcast_user.c # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +9 -7 # uml: Uml base patch # # arch/um/drivers/cow_user.c # 2004/08/24 11:13:14-07:00 blaisorblade_spam@yahoo.it +375 -0 # # arch/um/drivers/cow_sys.h # 2004/08/24 11:13:14-07:00 blaisorblade_spam@yahoo.it +48 -0 # # arch/um/drivers/cow_kern.c # 2004/08/24 11:13:14-07:00 blaisorblade_spam@yahoo.it +630 -0 # # include/asm-um/sections.h # 2004/08/24 11:13:14-07:00 blaisorblade_spam@yahoo.it +0 -0 # BitKeeper file /home/torvalds/v2.6/linux/include/asm-um/sections.h # # include/asm-um/module-i386.h # 2004/08/24 11:13:14-07:00 blaisorblade_spam@yahoo.it +0 -0 # BitKeeper file /home/torvalds/v2.6/linux/include/asm-um/module-i386.h # # include/asm-um/module-generic.h # 2004/08/24 11:13:14-07:00 blaisorblade_spam@yahoo.it +0 -0 # BitKeeper file /home/torvalds/v2.6/linux/include/asm-um/module-generic.h # # include/asm-um/local.h # 2004/08/24 11:13:14-07:00 blaisorblade_spam@yahoo.it +0 -0 # BitKeeper file /home/torvalds/v2.6/linux/include/asm-um/local.h # # include/asm-um/cpufeature.h # 2004/08/24 11:13:14-07:00 blaisorblade_spam@yahoo.it +0 -0 # BitKeeper file /home/torvalds/v2.6/linux/include/asm-um/cpufeature.h # # fs/hppfs/hppfs_kern.c # 2004/08/24 11:13:14-07:00 blaisorblade_spam@yahoo.it +0 -0 # BitKeeper file /home/torvalds/v2.6/linux/fs/hppfs/hppfs_kern.c # # fs/hppfs/Makefile # 2004/08/24 11:13:14-07:00 blaisorblade_spam@yahoo.it +0 -0 # BitKeeper file /home/torvalds/v2.6/linux/fs/hppfs/Makefile # # fs/hostfs/hostfs_user.c # 2004/08/24 11:13:14-07:00 blaisorblade_spam@yahoo.it +0 -0 # BitKeeper file /home/torvalds/v2.6/linux/fs/hostfs/hostfs_user.c # # fs/hostfs/hostfs_kern.c # 2004/08/24 11:13:14-07:00 blaisorblade_spam@yahoo.it +0 -0 # BitKeeper file /home/torvalds/v2.6/linux/fs/hostfs/hostfs_kern.c # # fs/hostfs/hostfs.h # 2004/08/24 11:13:14-07:00 blaisorblade_spam@yahoo.it +0 -0 # BitKeeper file /home/torvalds/v2.6/linux/fs/hostfs/hostfs.h # # fs/hostfs/Makefile # 2004/08/24 11:13:14-07:00 blaisorblade_spam@yahoo.it +0 -0 # BitKeeper file /home/torvalds/v2.6/linux/fs/hostfs/Makefile # # arch/um/sys-i386/time.c # 2004/08/24 11:13:14-07:00 blaisorblade_spam@yahoo.it +0 -0 # BitKeeper file /home/torvalds/v2.6/linux/arch/um/sys-i386/time.c # # arch/um/os-Linux/user_syms.c # 2004/08/24 11:13:14-07:00 blaisorblade_spam@yahoo.it +0 -0 # BitKeeper file /home/torvalds/v2.6/linux/arch/um/os-Linux/user_syms.c # # arch/um/kernel/tt/uaccess.c # 2004/08/24 11:13:14-07:00 blaisorblade_spam@yahoo.it +0 -0 # BitKeeper file /home/torvalds/v2.6/linux/arch/um/kernel/tt/uaccess.c # # arch/um/kernel/skas/uaccess.c # 2004/08/24 11:13:14-07:00 blaisorblade_spam@yahoo.it +0 -0 # BitKeeper file /home/torvalds/v2.6/linux/arch/um/kernel/skas/uaccess.c # # arch/um/kernel/physmem.c # 2004/08/24 11:13:14-07:00 blaisorblade_spam@yahoo.it +0 -0 # BitKeeper file /home/torvalds/v2.6/linux/arch/um/kernel/physmem.c # # arch/um/include/mem_kern.h # 2004/08/24 11:13:14-07:00 blaisorblade_spam@yahoo.it +0 -0 # BitKeeper file /home/torvalds/v2.6/linux/arch/um/include/mem_kern.h # # arch/um/include/irq_kern.h # 2004/08/24 11:13:14-07:00 blaisorblade_spam@yahoo.it +0 -0 # BitKeeper file /home/torvalds/v2.6/linux/arch/um/include/irq_kern.h # # arch/um/drivers/line.c # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +93 -59 # uml: Uml base patch # # arch/um/drivers/hostaudio_user.c # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +22 -41 # uml: Uml base patch # # arch/um/drivers/hostaudio_kern.c # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +90 -17 # uml: Uml base patch # # arch/um/drivers/harddog_user.c # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +34 -28 # uml: Uml base patch # # arch/um/drivers/fd.c # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +2 -1 # uml: Uml base patch # # arch/um/drivers/daemon_user.c # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +14 -12 # uml: Uml base patch # # arch/um/drivers/cow_user.c # 2004/08/24 11:13:14-07:00 blaisorblade_spam@yahoo.it +0 -0 # BitKeeper file /home/torvalds/v2.6/linux/arch/um/drivers/cow_user.c # # arch/um/drivers/cow_sys.h # 2004/08/24 11:13:14-07:00 blaisorblade_spam@yahoo.it +0 -0 # BitKeeper file /home/torvalds/v2.6/linux/arch/um/drivers/cow_sys.h # # arch/um/drivers/cow_kern.c # 2004/08/24 11:13:14-07:00 blaisorblade_spam@yahoo.it +0 -0 # BitKeeper file /home/torvalds/v2.6/linux/arch/um/drivers/cow_kern.c # # arch/um/drivers/cow.h # 2004/08/24 11:13:13-07:00 blaisorblade_spam@yahoo.it +41 -0 # # arch/um/drivers/chan_user.c # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +52 -48 # uml: Uml base patch # # arch/um/drivers/chan_kern.c # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +13 -3 # uml: Uml base patch # # arch/um/drivers/Makefile # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +4 -13 # uml: Uml base patch # # arch/um/defconfig # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +135 -95 # uml: Uml base patch # # arch/um/config.release # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +0 -1 # uml: Uml base patch # # arch/um/Makefile # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +69 -39 # uml: Uml base patch # # arch/um/Makefile-skas # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +3 -3 # uml: Uml base patch # # arch/um/Makefile-i386 # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +14 -9 # uml: Uml base patch # # arch/um/Kconfig # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +38 -0 # uml: Uml base patch # # arch/um/Kconfig_net # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +1 -69 # uml: Uml base patch # # arch/um/Kconfig_block # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +14 -0 # uml: Uml base patch # # arch/um/Kconfig.debug # 2004/08/24 02:08:18-07:00 blaisorblade_spam@yahoo.it +4 -0 # uml: Uml base patch # # arch/um/drivers/cow.h # 2004/08/24 11:13:13-07:00 blaisorblade_spam@yahoo.it +0 -0 # BitKeeper file /home/torvalds/v2.6/linux/arch/um/drivers/cow.h # # BitKeeper/deleted/.del-user_syms.c~3721953e2e77c594 # 2004/08/24 11:13:13-07:00 blaisorblade_spam@yahoo.it +0 -0 # Delete: arch/um/kernel/user_syms.c # # BitKeeper/deleted/.del-spinlock.h~99a286c9bb0cdcd3 # 2004/08/24 11:13:13-07:00 blaisorblade_spam@yahoo.it +0 -0 # Delete: include/asm-um/spinlock.h # # BitKeeper/deleted/.del-smplock.h~2fcbcd2e6471a0e5 # 2004/08/24 11:13:13-07:00 blaisorblade_spam@yahoo.it +0 -0 # Delete: include/asm-um/smplock.h # # BitKeeper/deleted/.del-extable.c~8beb382d1d62f6d4 # 2004/08/24 11:13:13-07:00 blaisorblade_spam@yahoo.it +0 -0 # Delete: arch/um/sys-i386/extable.c # # ChangeSet # 2004/08/24 11:12:38-07:00 anton@samba.org # [PATCH] flexible-mmap for ppc64 # # From: # # Implement the new address space layout for 32-bit apps running on ppc64. # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # include/asm-ppc64/processor.h # 2004/08/24 02:08:17-07:00 anton@samba.org +2 -0 # flexible-mmap for ppc64 # # arch/ppc64/mm/mmap.c # 2004/08/24 02:08:17-07:00 anton@samba.org +86 -0 # flexible-mmap for ppc64 # # arch/ppc64/mm/mmap.c # 2004/08/24 02:08:17-07:00 anton@samba.org +0 -0 # BitKeeper file /home/torvalds/v2.6/linux/arch/ppc64/mm/mmap.c # # arch/ppc64/mm/Makefile # 2004/08/24 02:08:17-07:00 anton@samba.org +1 -1 # flexible-mmap for ppc64 # # ChangeSet # 2004/08/24 11:12:26-07:00 arjanv@redhat.com # [PATCH] flex mmap for s390(x) # # Below is a patch from Pete Zaitcev (zaitcev@redhat.com) to also use the # flex mmap infrastructure for s390(x). The IBM Domino guys *really* seem to # want this. # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # arch/s390/mm/mmap.c # 2004/08/24 02:08:16-07:00 arjanv@redhat.com +83 -0 # flex mmap for s390(x) # # include/asm-s390/processor.h # 2004/08/24 02:08:16-07:00 arjanv@redhat.com +2 -0 # flex mmap for s390(x) # # arch/s390/mm/mmap.c # 2004/08/24 02:08:16-07:00 arjanv@redhat.com +0 -0 # BitKeeper file /home/torvalds/v2.6/linux/arch/s390/mm/mmap.c # # arch/s390/mm/Makefile # 2004/08/24 02:08:16-07:00 arjanv@redhat.com +1 -1 # flex mmap for s390(x) # # ChangeSet # 2004/08/24 11:12:13-07:00 arjanv@redhat.com # [PATCH] sysctl tunable for flexmmap # # Create /proc/sys/vm/legacy_va_layout. If this is non-zero, the kernel # will use the old mmap layout for all tasks. it presently defaults to zero # (the new layout). # # From: William Lee Irwin III # # hugetlb CONFIG_SYSCTL=n fix # # Signed-off-by: Ingo Molnar # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # mm/hugetlb.c # 2004/08/24 02:08:15-07:00 arjanv@redhat.com +1 -1 # sysctl tunable for flexmmap # # kernel/sysctl.c # 2004/08/24 02:08:15-07:00 arjanv@redhat.com +17 -0 # sysctl tunable for flexmmap # # include/linux/sysctl.h # 2004/08/24 02:08:15-07:00 arjanv@redhat.com +1 -0 # sysctl tunable for flexmmap # # include/linux/mm.h # 2004/08/24 02:08:15-07:00 arjanv@redhat.com +6 -0 # sysctl tunable for flexmmap # # include/asm-i386/page.h # 2004/08/24 02:08:15-07:00 arjanv@redhat.com +2 -0 # sysctl tunable for flexmmap # # arch/i386/mm/mmap.c # 2004/08/24 02:08:15-07:00 arjanv@redhat.com +2 -1 # sysctl tunable for flexmmap # # Documentation/filesystems/proc.txt # 2004/08/24 02:08:15-07:00 arjanv@redhat.com +6 -0 # sysctl tunable for flexmmap # # ChangeSet # 2004/08/24 11:12:01-07:00 arjanv@redhat.com # [PATCH] flexmmap patchkit: fix for 32 bit emu for 64 bit arches # # Utz Lehmann found a problem with the flexmmap # patches on x86-64, what he is seeing is that the 32 bit personality isn't # set at the first point of setting the allocator strategy. The solution is # simple, in binfmt_elf the personality is set so put the pick-layout # function there. Please consider, # # Signed-off-by: Arjan van de Ven # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # fs/binfmt_elf.c # 2004/08/24 02:08:15-07:00 arjanv@redhat.com +2 -0 # flexmmap patchkit: fix for 32 bit emu for 64 bit arches # # ChangeSet # 2004/08/24 11:11:50-07:00 mingo@elte.hu # [PATCH] i386 virtual memory layout rework # # Rework the i386 mm layout to allow applications to allocate more virtual # memory, and larger contiguous chunks. # # # - the patch is compatible with existing architectures that either make # use of HAVE_ARCH_UNMAPPED_AREA or use the default mmap() allocator - there # is no change in behavior. # # - 64-bit architectures can use the same mechanism to clean up 32-bit # compatibility layouts: by defining HAVE_ARCH_PICK_MMAP_LAYOUT and # providing a arch_pick_mmap_layout() function - which can then decide # between various mmap() layout functions. # # - I also introduced a new personality bit (ADDR_COMPAT_LAYOUT) to signal # older binaries that dont have PT_GNU_STACK. x86 uses this to revert back # to the stock layout. I also changed x86 to not clear the personality bits # upon exec(), like x86-64 already does. # # - once every architecture that uses HAVE_ARCH_UNMAPPED_AREA has defined # its arch_pick_mmap_layout() function, we can get rid of # HAVE_ARCH_UNMAPPED_AREA altogether, as a final cleanup. # # the new layout generation function (__get_unmapped_area()) got significant # testing in FC1/2, so i'm pretty confident it's robust. # # # Compiles & boots fine on an 'old' and on a 'new' x86 distro as well. # # The two known breakages were: # # http://www.redhatconfig.com/msg/67248.html # # [ 'cyzload' third-party utility broke. ] # # http://www.zipworld.com/au/~akpm/dde.tar.gz # # [ your editor broke :-) ] # # both were caused by application bugs that did: # # int ret = malloc(); # # if (ret <= 0) # failure; # # such bugs are easy to spot if they happen, and if it happens it's possible # to work it around immediately without having to change the binary, via the # setarch patch. # # No other application has been found to be affected, and this particular # change got pretty wide coverage already over RHEL3 and exec-shield, it's in # use for more than a year. # # # The setarch utility can be used to trigger the compatibility layout on # x86, the following version has been patched to take the `-L' option: # # http://people.redhat.com/mingo/flexible-mmap/setarch-1.4-2.tar.gz # # "setarch -L i386 " will run the command with the old layout. # # From: Hugh Dickins # # The problem is in the flexible mmap patch: arch_get_unmapped_area_topdown # is liable to give your mmap vm_start above TASK_SIZE with vm_end wrapped; # which is confusing, and ends up as that BUG_ON(mm->map_count). # # The patch below stops that behaviour, but it's not the full solution: # wilson_mmap_test -s 1000 then simply cannot allocate memory for the large # mmap, whereas it works fine non-top-down. # # I think it's wrong to interpret a large or rlim_infinite stack rlimit as # an inviolable request to reserve that much for the stack: it makes much less # VM available than bottom up, not what was intended. Perhaps top down should # go bottom up (instead of belly up) when it fails - but I'd probably better # leave that to Ingo. # # Or perhaps the default should place stack below text (as WLI suggested and # ELF intended, with its text defaulting to 0x08048000, small progs sharing # page table between stack and text and data); with a further personality for # those needing bigger stack. # # From: Ingo Molnar # # - fall back to the bottom-up layout if the stack can grow unlimited (if # the stack ulimit has been set to RLIM_INFINITY) # # - try the bottom-up allocator if the top-down allocator fails - this can # utilize the hole between the true bottom of the stack and its ulimit, as a # last-resort effort. # # Signed-off-by: Ingo Molnar # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # arch/i386/mm/mmap.c # 2004/08/24 02:08:15-07:00 mingo@elte.hu +70 -0 # i386 virtual memory layout rework # # mm/mmap.c # 2004/08/24 02:08:15-07:00 mingo@elte.hu +111 -13 # i386 virtual memory layout rework # # kernel/fork.c # 2004/08/24 02:08:15-07:00 mingo@elte.hu +1 -1 # i386 virtual memory layout rework # # include/linux/sched.h # 2004/08/24 02:08:15-07:00 mingo@elte.hu +27 -0 # i386 virtual memory layout rework # # include/linux/personality.h # 2004/08/24 02:08:15-07:00 mingo@elte.hu +1 -0 # i386 virtual memory layout rework # # include/asm-i386/processor.h # 2004/08/24 02:08:15-07:00 mingo@elte.hu +2 -0 # i386 virtual memory layout rework # # fs/exec.c # 2004/08/24 02:08:15-07:00 mingo@elte.hu +1 -0 # i386 virtual memory layout rework # # fs/binfmt_elf.c # 2004/08/24 02:08:15-07:00 mingo@elte.hu +1 -1 # i386 virtual memory layout rework # # fs/binfmt_aout.c # 2004/08/24 02:08:15-07:00 mingo@elte.hu +1 -1 # i386 virtual memory layout rework # # arch/i386/mm/mmap.c # 2004/08/24 02:08:15-07:00 mingo@elte.hu +0 -0 # BitKeeper file /home/torvalds/v2.6/linux/arch/i386/mm/mmap.c # # arch/i386/mm/Makefile # 2004/08/24 02:08:15-07:00 mingo@elte.hu +1 -1 # i386 virtual memory layout rework # # ChangeSet # 2004/08/24 11:11:37-07:00 mingo@elte.hu # [PATCH] sched: smt fixes # # while looking at HT scheduler bugreports and boot failures i discovered a # bad assumption in most of the HT scheduling code: that resched_task() can # be called without holding the task's runqueue. # # This is most definitely not valid - doing it without locking can lead to # the task on that CPU exiting, and this CPU corrupting the (ex-) task_info # struct. It can also lead to HT-wakeup races with task switching on that # other CPU. (this_CPU marking the wrong task on that_CPU as need_resched - # resulting in e.g. idle wakeups not working.) # # The attached patch against fixes it all up. Changes: # # - resched_task() needs to touch the task so the runqueue lock of that CPU # must be held: resched_task() now enforces this rule. # # - wake_priority_sleeper() was called without holding the runqueue lock. # # - wake_sleeping_dependent() needs to hold the runqueue locks of all # siblings (2 typically). Effects of this ripples back to schedule() as # well - in the non-SMT case it gets compiled out so it's fine. # # - dependent_sleeper() needs the runqueue locks too - and it's slightly # harder because it wants to know the 'next task' info which might change # during the lock-drop/reacquire. Ripple effect on schedule() => compiled # out on non-SMT so fine. # # - resched_task() was disabling preemption for no good reason - all paths # that called this function had either a spinlock held or irqs disabled. # # Compiled & booted on x86 SMP and UP, with and without SMT. Booted the # SMT kernel on a real SMP+HT box as well. (Unpatched kernel wouldn't even # boot with the resched_task() assert in place.) # # Signed-off-by: Ingo Molnar # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # kernel/sched.c # 2004/08/24 02:08:14-07:00 mingo@elte.hu +86 -29 # sched: smt fixes # # ChangeSet # 2004/08/24 11:11:26-07:00 mingo@elte.hu # [PATCH] sched: self-reaping atomicity fix # # disable preemption in the self-reap codepath, as such tasks may not be on # the tasklist anymore and CPU-hotplug relies on the tasklist to migrate # tasks. # # Signed-off-by: Ingo Molnar # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # kernel/exit.c # 2004/08/24 02:08:14-07:00 mingo@elte.hu +7 -0 # sched: self-reaping atomicity fix # # ChangeSet # 2004/08/24 11:11:14-07:00 mingo@redhat.com # [PATCH] permit sleeping in release_task() # # release_task() calls proc_pid_flush() call dput(), which can sleep. But # that's a late-in-exit no-preempt path with CONFIG_PREEMPT. # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # kernel/exit.c # 2004/08/24 02:08:14-07:00 mingo@redhat.com +18 -18 # permit sleeping in release_task() # # ChangeSet # 2004/08/24 11:11:02-07:00 mingo@elte.hu # [PATCH] sched: new task fix # # Rusty noticed that we update the parent ->avg_sleep without holding the # runqueue lock. Also the code needed cleanups. # # Signed-off-by: Ingo Molnar # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # kernel/sched.c # 2004/08/24 02:08:13-07:00 mingo@elte.hu +15 -9 # sched: new task fix # # ChangeSet # 2004/08/24 11:10:51-07:00 mingo@elte.hu # [PATCH] sched: nonlinear timeslices # # * Nick Piggin wrote: # # > Increasing priority (negative nice) doesn't have much impact. -20 CPU # > hog only gets about double the CPU of a 0 priority CPU hog and only # > about 120% the CPU time of a nice -10 hog. # # this is a property of the base scheduler as well. # # We can do a nonlinear timeslice distribution trivially - the attached # patch implements the following timeslice distribution ontop of # 2.6.8-rc3-mm1: # # [ -20 ... 0 ... 19 ] => [800ms ... 100ms ... 5ms] # # the nice-20/nice+19 ratio is now 1:160 - sufficient for all aspects. # # Signed-off-by: Ingo Molnar # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # kernel/sched.c # 2004/08/24 02:08:13-07:00 mingo@elte.hu +14 -17 # sched: nonlinear timeslices # # ChangeSet # 2004/08/24 11:10:39-07:00 mingo@elte.hu # [PATCH] sched: whitespace cleanups # # - whitespace and style cleanups # # Signed-off-by: Ingo Molnar # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # kernel/sched.c # 2004/08/24 02:08:13-07:00 mingo@elte.hu +33 -32 # sched: whitespace cleanups # # ChangeSet # 2004/08/24 11:10:27-07:00 akpm@osdl.org # [PATCH] schedstat: UP fix # # SMP fix -- # for_each_domain() is not defined if not CONFIG_SMP, so show_schedstat # needed a couple of extra ifdefs. # # Signed-off-by: Rick Lindsley # Signed-off-by: Ingo Molnar # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # kernel/sched.c # 2004/08/24 02:08:12-07:00 akpm@osdl.org +4 -0 # schedstat: UP fix # # Documentation/sched-stats.txt # 2004/08/24 02:08:12-07:00 akpm@osdl.org +6 -2 # schedstat: UP fix # # ChangeSet # 2004/08/24 11:10:16-07:00 wli@holomorphy.com # [PATCH] sched: sparc32 fixes # # Fix up sparc32 properly. # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # arch/sparc/kernel/sun4m_smp.c # 2004/08/24 02:08:12-07:00 wli@holomorphy.com +1 -10 # sched: sparc32 fixes # # arch/sparc/kernel/sun4d_smp.c # 2004/08/24 02:08:12-07:00 wli@holomorphy.com +1 -1 # sched: sparc32 fixes # # ChangeSet # 2004/08/24 11:10:03-07:00 wli@holomorphy.com # [PATCH] sched: consolidate init_idle() and fork_by_hand() # # It appears that init_idle() and fork_by_hand() could be combined into a # single method that calls init_idle() on behalf of the caller. # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # kernel/sched.c # 2004/08/24 02:08:12-07:00 wli@holomorphy.com +8 -0 # sched: consolidate init_idle() and fork_by_hand() # # kernel/fork.c # 2004/08/24 02:08:12-07:00 wli@holomorphy.com +15 -1 # sched: consolidate init_idle() and fork_by_hand() # # init/main.c # 2004/08/24 02:08:12-07:00 wli@holomorphy.com +0 -9 # sched: consolidate init_idle() and fork_by_hand() # # include/linux/sched.h # 2004/08/24 02:08:12-07:00 wli@holomorphy.com +1 -1 # sched: consolidate init_idle() and fork_by_hand() # # arch/x86_64/kernel/smpboot.c # 2004/08/24 02:08:12-07:00 wli@holomorphy.com +1 -17 # sched: consolidate init_idle() and fork_by_hand() # # arch/sparc64/kernel/smp.c # 2004/08/24 02:08:12-07:00 wli@holomorphy.com +1 -8 # sched: consolidate init_idle() and fork_by_hand() # # arch/sparc/kernel/sun4d_smp.c # 2004/08/24 02:08:12-07:00 wli@holomorphy.com +1 -10 # sched: consolidate init_idle() and fork_by_hand() # # arch/sh/kernel/smp.c # 2004/08/24 02:08:12-07:00 wli@holomorphy.com +1 -6 # sched: consolidate init_idle() and fork_by_hand() # # arch/s390/kernel/smp.c # 2004/08/24 02:08:12-07:00 wli@holomorphy.com +1 -10 # sched: consolidate init_idle() and fork_by_hand() # # arch/ppc64/kernel/smp.c # 2004/08/24 02:08:12-07:00 wli@holomorphy.com +1 -9 # sched: consolidate init_idle() and fork_by_hand() # # arch/ppc/kernel/smp.c # 2004/08/24 02:08:12-07:00 wli@holomorphy.com +1 -6 # sched: consolidate init_idle() and fork_by_hand() # # arch/parisc/kernel/smp.c # 2004/08/24 02:08:12-07:00 wli@holomorphy.com +1 -21 # sched: consolidate init_idle() and fork_by_hand() # # arch/mips/kernel/smp.c # 2004/08/24 02:08:12-07:00 wli@holomorphy.com +1 -17 # sched: consolidate init_idle() and fork_by_hand() # # arch/ia64/kernel/smpboot.c # 2004/08/24 02:08:12-07:00 wli@holomorphy.com +6 -21 # sched: consolidate init_idle() and fork_by_hand() # # arch/i386/mach-voyager/voyager_smp.c # 2004/08/24 02:08:12-07:00 wli@holomorphy.com +1 -17 # sched: consolidate init_idle() and fork_by_hand() # # arch/i386/kernel/smpboot.c # 2004/08/24 02:08:12-07:00 wli@holomorphy.com +1 -19 # sched: consolidate init_idle() and fork_by_hand() # # arch/alpha/kernel/smp.c # 2004/08/24 02:08:12-07:00 wli@holomorphy.com +1 -13 # sched: consolidate init_idle() and fork_by_hand() # # ChangeSet # 2004/08/24 11:09:52-07:00 nathanl@austin.ibm.com # [PATCH] move CONFIG_SCHEDSTATS to arch/ppc64/Kconfig.debug # # Otherwise it shows up under "iSeries device drivers", which doesn't seem # right. # # Signed-off-by: Nathan Lynch # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # arch/ppc64/Kconfig # 2004/08/24 02:08:11-07:00 nathanl@austin.ibm.com +0 -12 # move CONFIG_SCHEDSTATS to arch/ppc64/Kconfig.debug # # arch/ppc64/Kconfig.debug # 2004/08/24 02:08:11-07:00 nathanl@austin.ibm.com +12 -0 # move CONFIG_SCHEDSTATS to arch/ppc64/Kconfig.debug # # ChangeSet # 2004/08/24 11:09:41-07:00 ricklind@us.ibm.com # [PATCH] scheduler statistics # # It adds lots of CPU scheduler stats in /proc/pid/stat. They are described in # the new Documentation//sched-stats.txt # # We were carrying this patch offline for some time, but as there's still # considerable ongoing work in this area, and as the new stats are a # configuration option, I think it's best that this capability be in the base # kernel. # # Nick removed a fair amount of statistics that he wasn't using. The full patch # gathers more information. In particular, his patch doesn't include the code # to measure the latency between the time a process is made runnable and the # time it hits a processor which will be key to measuring interactivity changes. # # He passed his changes back to me and I got finished merging his changes with # the current statistics patches just before OLS. I believe this is largely a # superset of the patch you grabbed and should port relatively easily too. # # Versions also exist for # # 2.6.8-rc2 # 2.6.8-rc2-mm1 # 2.6.8-rc2-mm2 # # at # http://eaglet.rain.com/rick/linux/schedstat/patches/ # # and within 24 hours at # # http://oss.software.ibm.com/linux/patches/?patch_id=730&show=all # # The version below is for 2.6.8-rc2-mm2 without the staircase code and has # been compiled cleanly but not yet run. # # From: Ingo Molnar # # this code needs a couple of cleanups before it can go into mainline: # # fs/proc/array.c, fs/proc/base.c, fs/proc/proc_misc.c: # # - moved the new /proc//stat fields to /proc//schedstat, # because the new fields break older procps. It's cleaner this way # anyway. This moving of fields necessiated a bump to version 10. # # Documentation/sched-stats.txt: # # - updated sched-stats.txt for version 10 # # - wake_up_forked_thread() => wake_up_new_task() # # - updated the per-process field description # # Kconfig: # # - removed the default y and made the option dependent on DEBUG_KERNEL. # This is really for scheduler analysis, normal users dont need the # overhead. # # include/linux/sched.h: # # - moved the definitions into kernel/sched.c - this fixes UP compilation # and is cleaner. # # - also moved the sched-domain definitions to sched.c - now that the # sched-domains internals are not exposed to architectures this is # doable. It's also necessary due to the previous change. # # kernel/fork.c: # # - moved the ->sched_info init to sched_fork() where it belongs. # # kernel/sched.c: # # - wake_up_forked_thread() -> wake_up_new_task(), wuft_cnt -> wunt_cnt, # wuft_moved -> wunt_moved. # # - wunt_cnt and wunt_moved were defined by never updated - added the # missing code to wake_up_new_task(). # # - whitespace/style police # # - removed whitespace changes done to code not related to schedstats - # i'll send a separate patch for these (and more). # # Signed-off-by: Ingo Molnar # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # Documentation/sched-stats.txt # 2004/08/24 02:08:10-07:00 ricklind@us.ibm.com +149 -0 # scheduler statistics # # kernel/sched.c # 2004/08/24 02:08:10-07:00 ricklind@us.ibm.com +470 -21 # scheduler statistics # # include/linux/sched.h # 2004/08/24 02:08:10-07:00 ricklind@us.ibm.com +18 -113 # scheduler statistics # # fs/proc/proc_misc.c # 2004/08/24 02:08:10-07:00 ricklind@us.ibm.com +3 -0 # scheduler statistics # # fs/proc/base.c # 2004/08/24 02:08:10-07:00 ricklind@us.ibm.com +32 -0 # scheduler statistics # # arch/x86_64/Kconfig.debug # 2004/08/24 02:08:10-07:00 ricklind@us.ibm.com +12 -0 # scheduler statistics # # arch/ppc64/Kconfig # 2004/08/24 02:08:10-07:00 ricklind@us.ibm.com +12 -0 # scheduler statistics # # arch/ppc/Kconfig.debug # 2004/08/24 02:08:10-07:00 ricklind@us.ibm.com +12 -0 # scheduler statistics # # arch/i386/Kconfig.debug # 2004/08/24 02:08:10-07:00 ricklind@us.ibm.com +12 -0 # scheduler statistics # # Documentation/sched-stats.txt # 2004/08/24 02:08:10-07:00 ricklind@us.ibm.com +0 -0 # BitKeeper file /home/torvalds/v2.6/linux/Documentation/sched-stats.txt # # ChangeSet # 2004/08/24 11:09:28-07:00 kernel@kolivas.org # [PATCH] sched: adjust p4 per-cpu gain # # The smt-nice handling is a little too aggressive by not estimating the per cpu # gain as high enough for pentium4 hyperthread. This patch changes the per # sibling cpu gain from 15% to 25%. The true per cpu gain is entirely dependant # on the workload but overall the 2 species of Pentium4 that support # hyperthreading have about 20-30% gain. # # P.S: Anton - For the power processors that are now using this SMT nice # infrastructure it would be worth setting this value separately at 40%. # # Signed-off-by: Con Kolivas # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # include/linux/sched.h # 2004/08/24 02:08:10-07:00 kernel@kolivas.org +1 -1 # sched: adjust p4 per-cpu gain # # ChangeSet # 2004/08/24 11:09:16-07:00 colpatch@us.ibm.com # [PATCH] Create cpu_sibling_map for PPC64 # # In light of some proposed changes in the sched_domains code, I coded up # this little ditty that simply creates and populates a cpu_sibling_map for # PPC64 machines. The patch just checks the CPU flags to determine if the # CPU supports SMT (aka Hyper-Threading aka Multi-Threading aka ...) and # fills in a mask of the siblings for each CPU in the system. This should # allow us to build sched_domains for PPC64 with generic code in # kernel/sched.c for the SMT systems. SMT is becoming more popular and is # turning up in more and more architectures. I don't think it will be too # long until this feature is supported by most arches... # # Signed-off-by: Matthew Dobson # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # include/asm-ppc64/smp.h # 2004/08/24 02:08:10-07:00 colpatch@us.ibm.com +2 -0 # Create cpu_sibling_map for PPC64 # # arch/ppc64/kernel/smp.c # 2004/08/24 02:08:10-07:00 colpatch@us.ibm.com +7 -0 # Create cpu_sibling_map for PPC64 # # ChangeSet # 2004/08/24 11:09:04-07:00 sivanich@sgi.com # [PATCH] sched: isolated sched domains # # Here's a version of the isolated scheduler domain code that I mentioned in # an RFC on 7/22. This patch applies on top of 2.6.8-rc2-mm1 (to include all # of the new arch_init_sched_domain code). This patch also contains the 2 # line fix to remove the check of first_cpu(sd->groups->cpumask)) that Jesse # sent in earlier. # # Note that this has not been tested with CONFIG_SCHED_SMT. I hope that my # handling of those instances is OK. # # Signed-off-by: Dimitri Sivanich # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # kernel/sched.c # 2004/08/24 02:08:10-07:00 sivanich@sgi.com +76 -5 # sched: isolated sched domains # # ChangeSet # 2004/08/24 11:08:53-07:00 jbarnes@engr.sgi.com # [PATCH] sched: limit cpuspan of node scheduler domains # # This patch limits the cpu span of each node's scheduler domain to prevent # balancing across too many cpus. The cpus included in a node's domain are # determined by the SD_NODES_PER_DOMAIN define and the arch specific # sched_domain_node_span routine if ARCH_HAS_SCHED_DOMAIN is defined. If # ARCH_HAS_SCHED_DOMAIN is not defined, behavior is unchanged--all possible # cpus will be included in each node's scheduling domain. Currently, only # ia64 provides an arch specific sched_domain_node_span routine. # # From: Jesse Barnes # # This patch adds some more NUMA specific logic to the creation of scheduler # domains. Domains spanning all CPUs in a large system are too large to # schedule across efficiently, leading to livelocks and inordinate amounts of # time being spent in scheduler routines. With this patch applied, the node # scheduling domains for NUMA platforms will only contain a specified number # of nearby CPUs, based on the value of SD_NODES_PER_DOMAIN. It also allows # arches to override SD_NODE_INIT, which sets the domain scheduling parameters # for each node's domain. This is necessary especially for large systems. # # Possible future directions: # # o multilevel node hierarchy (e.g. node domains could contain 4 nodes # worth of CPUs, supernode domains could contain 32 nodes worth, etc. each # with their own SD_NODE_INIT values) # # o more tweaking of SD_NODE_INIT values for good load balancing vs. # overhead tradeoffs # # From: mita akinobu # # Compile fix # # Signed-off-by: Jesse Barnes # Signed-off-by: Ingo Molnar # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # kernel/sched.c # 2004/08/24 02:08:09-07:00 jbarnes@engr.sgi.com +74 -8 # sched: limit cpuspan of node scheduler domains # # include/asm-ia64/processor.h # 2004/08/24 02:08:09-07:00 jbarnes@engr.sgi.com +20 -0 # sched: limit cpuspan of node scheduler domains # # arch/ia64/kernel/smpboot.c # 2004/08/24 02:08:09-07:00 jbarnes@engr.sgi.com +1 -0 # sched: limit cpuspan of node scheduler domains # # ChangeSet # 2004/08/24 11:08:41-07:00 nickpiggin@yahoo.com.au # [PATCH] sched: consolidate sched domains # # Teach the generic domains builder about SMT, and consolidate all # architecture specific domain code into that. Also, the SD_*_INIT macros can # now be redefined by arch code without duplicating the entire setup code. # This can be done by defining ARCH_HASH_SCHED_TUNE. # # The generic builder has been simplified with the addition of a helper # macro which will probably prove to be useful to arch specific code as well # and should be exported if that is the case. # # Signed-off-by: Nick Piggin # # From: Matthew Dobson # # The attached patch is against 2.6.8-rc2-mm2, and removes Nick's # conditional definition & population of cpu_sibling_map[] in favor of my # unconditional ones. This does not affect how cpu_sibling_map is used, just # gives it broader scope. # # From: Nick Piggin # # Small fix to sched-consolidate-domains.patch picked up by # # From: Suresh # # another sched consolidate domains fix # # From: Nick Piggin # # Don't use cpu_sibling_map if !CONFIG_SCHED_SMT # # This one spotted by Dimitri Sivanich # # Signed-off-by: Nick Piggin # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # kernel/sched.c # 2004/08/24 02:08:09-07:00 nickpiggin@yahoo.com.au +145 -81 # sched: consolidate sched domains # # include/linux/sched.h # 2004/08/24 02:08:09-07:00 nickpiggin@yahoo.com.au +5 -0 # sched: consolidate sched domains # # include/asm-x86_64/processor.h # 2004/08/24 02:08:09-07:00 nickpiggin@yahoo.com.au +0 -5 # sched: consolidate sched domains # # include/asm-ppc64/processor.h # 2004/08/24 02:08:09-07:00 nickpiggin@yahoo.com.au +0 -5 # sched: consolidate sched domains # # include/asm-i386/processor.h # 2004/08/24 02:08:09-07:00 nickpiggin@yahoo.com.au +0 -5 # sched: consolidate sched domains # # arch/x86_64/kernel/Makefile # 2004/08/24 02:08:09-07:00 nickpiggin@yahoo.com.au +0 -1 # sched: consolidate sched domains # # arch/x86_64/kernel/Makefile-HEAD # 2004/08/24 02:08:09-07:00 nickpiggin@yahoo.com.au +0 -1 # sched: consolidate sched domains # # arch/ppc64/kernel/smp.c # 2004/08/24 02:08:09-07:00 nickpiggin@yahoo.com.au +0 -215 # sched: consolidate sched domains # # arch/i386/kernel/smpboot.c # 2004/08/24 02:08:09-07:00 nickpiggin@yahoo.com.au +0 -207 # sched: consolidate sched domains # # Documentation/sched-domains.txt # 2004/08/24 02:08:09-07:00 nickpiggin@yahoo.com.au +21 -6 # sched: consolidate sched domains # # BitKeeper/deleted/.del-domain.c~ae619231167b63a1 # 2004/08/24 11:08:35-07:00 nickpiggin@yahoo.com.au +0 -0 # Delete: arch/x86_64/kernel/domain.c # # ChangeSet # 2004/08/24 11:08:29-07:00 mingo@elte.hu # [PATCH] sched: fork hotplug hanling cleanup # # - remove the hotplug lock from around much of fork(), and re-copy the # cpus_allowed mask to solve the hotplug race cleanly. # # Signed-off-by: Ingo Molnar # Signed-off-by: Srivatsa Vaddagiri # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # kernel/sched.c # 2004/08/24 02:08:08-07:00 mingo@elte.hu +1 -13 # sched: fork hotplug hanling cleanup # # kernel/fork.c # 2004/08/24 02:08:08-07:00 mingo@elte.hu +11 -11 # sched: fork hotplug hanling cleanup # # ChangeSet # 2004/08/24 11:08:17-07:00 nickpiggin@yahoo.com.au # [PATCH] sched: remove balance on clone # # This removes balance on clone capability altogether. I told Andi we wouldn't # remove it yet, but provided it is in a single small patch, he mightn't get too # upset. # # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # kernel/sched.c # 2004/08/24 02:08:08-07:00 nickpiggin@yahoo.com.au +2 -22 # sched: remove balance on clone # # kernel/fork.c # 2004/08/24 02:08:08-07:00 nickpiggin@yahoo.com.au +1 -1 # sched: remove balance on clone # # include/linux/sched.h # 2004/08/24 02:08:08-07:00 nickpiggin@yahoo.com.au +5 -6 # sched: remove balance on clone # # ChangeSet # 2004/08/24 11:08:06-07:00 nickpiggin@yahoo.com.au # [PATCH] sched: disable balance on clone # # Don't balance on clone by default. # # Balance on clone has a number of trivial performance failure cases, but it was # needed to get decent OpenMP performance on NUMA (Opteron) systems. Not doing # child-runs-first for new threads also solves this problem in a nicer way # (implemented in a previous patch). # # Signed-off-by: Nick Piggin # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # include/linux/sched.h # 2004/08/24 02:08:08-07:00 nickpiggin@yahoo.com.au +0 -3 # sched: disable balance on clone # # ChangeSet # 2004/08/24 11:07:54-07:00 nickpiggin@yahoo.com.au # [PATCH] sched: sched misc changes # # Add some likely/unliklies, a for_each_cpu => for_each_cpu_online, and close # the sched_exit race. # # From: Ingo Molnar # # fix a typo in a previous patch breaking RT scheduling & interactivity. # # Signed-off-by: Nick Piggin # Signed-off-by: Ingo Molnar # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # kernel/sched.c # 2004/08/24 02:08:08-07:00 nickpiggin@yahoo.com.au +8 -10 # sched: sched misc changes # # ChangeSet # 2004/08/24 11:07:42-07:00 nickpiggin@yahoo.com.au # [PATCH] sched: make rt_task unlikely # # From: Ingo Molnar # # RT tasks are unlikely, move this into rt_task() instead of open-coding it. # # Signed-off-by: Ingo Molnar # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # kernel/sched.c # 2004/08/24 02:08:07-07:00 nickpiggin@yahoo.com.au +2 -2 # sched: make rt_task unlikely # # include/linux/sched.h # 2004/08/24 02:08:07-07:00 nickpiggin@yahoo.com.au +1 -1 # sched: make rt_task unlikely # # ChangeSet # 2004/08/24 11:07:30-07:00 mingo@elte.hu # [PATCH] sched: misc cleanups #2 # # - fix two stale comments # - cleanup # # Signed-off-by: Ingo Molnar # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # kernel/sched.c # 2004/08/24 02:08:07-07:00 mingo@elte.hu +3 -5 # sched: misc cleanups #2 # # ChangeSet # 2004/08/24 11:07:19-07:00 nickpiggin@yahoo.com.au # [PATCH] kernel thread idle fix # # Now that init_idle does not remove tasks from the runqueue, those # architectures that use kernel_thread instead of copy_process for the idle # task will break. To fix, ensure that CLONE_IDLETASK tasks are not put on # the runqueue in the first place. # # Signed-off-by: Nick Piggin # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # kernel/fork.c # 2004/08/24 02:08:07-07:00 nickpiggin@yahoo.com.au +7 -5 # kernel thread idle fix # # ChangeSet # 2004/08/24 11:07:08-07:00 nickpiggin@yahoo.com.au # [PATCH] sched: cleanup, improve sched <=> fork APIs # # Move balancing and child-runs-first logic from fork.c into sched.c where # it belongs. # # * Consolidate wake_up_forked_process and wake_up_forked_thread into # wake_up_new_process, and pass in clone_flags as suggested by Linus. This # removes a lot of code duplication and allows all logic to be handled in that # function. # # * Don't do balance-on-clone balancing for vfork'ed threads. # # * Don't do set_task_cpu or balance one clone in wake_up_new_process. # Instead do it in sched_fork to fix set_cpus_allowed races. # # * Don't do child-runs-first for CLONE_VM processes, as there is obviously no # COW benifit to be had. This is a big one, it enables Andi's workload to run # well without clone balancing, because the OpenMP child threads can get # balanced off to other nodes *before* they start running and allocating # memory. # # * Rename sched_balance_exec to sched_exec: hide the policy from the API. # # # From: Ingo Molnar # # rename wake_up_new_process -> wake_up_new_task. # # in sched.c we are gradually moving away from the overloaded 'process' or # 'thread' notion to the traditional task (or context) naming. # # Signed-off-by: Nick Piggin # Signed-off-by: Ingo Molnar # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # kernel/sched.c # 2004/08/24 02:08:07-07:00 nickpiggin@yahoo.com.au +96 -103 # sched: cleanup, improve sched <=> fork APIs # # kernel/fork.c # 2004/08/24 02:08:07-07:00 nickpiggin@yahoo.com.au +16 -31 # sched: cleanup, improve sched <=> fork APIs # # include/linux/sched.h # 2004/08/24 02:08:07-07:00 nickpiggin@yahoo.com.au +6 -9 # sched: cleanup, improve sched <=> fork APIs # # fs/exec.c # 2004/08/24 02:08:07-07:00 nickpiggin@yahoo.com.au +1 -1 # sched: cleanup, improve sched <=> fork APIs # # fs/compat.c # 2004/08/24 02:08:07-07:00 nickpiggin@yahoo.com.au +2 -2 # sched: cleanup, improve sched <=> fork APIs # # ChangeSet # 2004/08/24 11:06:56-07:00 nickpiggin@yahoo.com.au # [PATCH] sched: cleanup init_idle() # # Clean up init_idle to not use wake_up_forked_process, then undo all the stuff # that call does. Instead, do everything in init_idle. # # Make double_rq_lock depend on CONFIG_SMP because it is no longer used on UP. # # Signed-off-by: Nick Piggin # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # kernel/sched.c # 2004/08/24 02:08:06-07:00 nickpiggin@yahoo.com.au +38 -39 # sched: cleanup init_idle() # # init/main.c # 2004/08/24 02:08:06-07:00 nickpiggin@yahoo.com.au +8 -7 # sched: cleanup init_idle() # # arch/x86_64/kernel/smpboot.c # 2004/08/24 02:08:06-07:00 nickpiggin@yahoo.com.au +2 -5 # sched: cleanup init_idle() # # arch/sh/kernel/smp.c # 2004/08/24 02:08:06-07:00 nickpiggin@yahoo.com.au +0 -2 # sched: cleanup init_idle() # # arch/s390/kernel/smp.c # 2004/08/24 02:08:06-07:00 nickpiggin@yahoo.com.au +4 -1 # sched: cleanup init_idle() # # arch/ppc64/kernel/smp.c # 2004/08/24 02:08:06-07:00 nickpiggin@yahoo.com.au +0 -1 # sched: cleanup init_idle() # # arch/ppc/kernel/smp.c # 2004/08/24 02:08:06-07:00 nickpiggin@yahoo.com.au +0 -2 # sched: cleanup init_idle() # # arch/parisc/kernel/smp.c # 2004/08/24 02:08:06-07:00 nickpiggin@yahoo.com.au +0 -1 # sched: cleanup init_idle() # # arch/mips/kernel/smp.c # 2004/08/24 02:08:06-07:00 nickpiggin@yahoo.com.au +2 -6 # sched: cleanup init_idle() # # arch/ia64/kernel/smpboot.c # 2004/08/24 02:08:06-07:00 nickpiggin@yahoo.com.au +2 -5 # sched: cleanup init_idle() # # arch/i386/mach-voyager/voyager_smp.c # 2004/08/24 02:08:06-07:00 nickpiggin@yahoo.com.au +3 -2 # sched: cleanup init_idle() # # arch/i386/kernel/smpboot.c # 2004/08/24 02:08:06-07:00 nickpiggin@yahoo.com.au +2 -5 # sched: cleanup init_idle() # # arch/alpha/kernel/smp.c # 2004/08/24 02:08:06-07:00 nickpiggin@yahoo.com.au +0 -2 # sched: cleanup init_idle() # # ChangeSet # 2004/08/24 11:06:43-07:00 mingo@elte.hu # [PATCH] sched: fix timeslice calculations for HZ=1000. # # The main benefit is that with the default HZ=1000 nice +19 tasks now get 5 # msecs of timeslices, so the ratio of CPU use is linear. (nice 0 task gets # 20 times more CPU time than a nice 19 task. Prior this change the ratio # was 1:10) # # another effect is that nice 0 tasks now get a round 100 msecs of timeslices # (as intended), instead of 102 msecs. # # here's a table of old/new timeslice values, for HZ=1000 and 100: # # HZ=1000 ( HZ=100 ) # old new ( old new ) # # nice -20: 200 200 ( 200 200 ) # nice -19: 195 195 ( 190 190 ) # ... # nice 0: 102 100 ( 100 100 ) # nice 1: 97 95 ( 90 90 ) # nice 2: 92 90 ( 90 90 ) # ... # nice 17: 19 15 ( 10 10 ) # nice 18: 14 10 ( 10 10 ) # nice 19: 10 5 ( 10 10 ) # # i've tested the patch on x86. # # Signed-off-by: Ingo Molnar # Signed-off-by: Andrew Morton # Signed-off-by: Linus Torvalds # # kernel/sched.c # 2004/08/24 02:08:06-07:00 mingo@elte.hu +7 -7 # sched: fix timeslice calculations for HZ=1000. # # ChangeSet # 2004/08/24 18:49:29+01:00 davej@redhat.com # [CPUFREQ] Work around some broken userspace daemons. # Some daemons try to set the speed to the same speed we're currently # running at. Detect that, and bail out early before we fiddle # with registers and such. # # Signed-off-by: Dave Jones # # arch/i386/kernel/cpu/cpufreq/longhaul.c # 2004/08/24 18:49:20+01:00 davej@redhat.com +7 -2 # [CPUFREQ] Work around some broken userspace daemons. # Some daemons try to set the speed to the same speed we're currently # running at. Detect that, and bail out early before we fiddle # with registers and such. # # Signed-off-by: Dave Jones # # ChangeSet # 2004/08/24 18:27:53+01:00 davej@redhat.com # [CPUFREQ] Merge on-demand cpufreq policy governor. # # From: "Pallipadi, Venkatesh" # Signed-off-by: Dave Jones # # drivers/cpufreq/cpufreq_ondemand.c # 2004/08/24 18:27:44+01:00 davej@redhat.com +424 -0 # # drivers/cpufreq/cpufreq_ondemand.c # 2004/08/24 18:27:44+01:00 davej@redhat.com +0 -0 # BitKeeper file /mnt/data/src/bk/cpufreq/drivers/cpufreq/cpufreq_ondemand.c # # drivers/cpufreq/Makefile # 2004/08/24 18:27:44+01:00 davej@redhat.com +1 -0 # [CPUFREQ] Merge on-demand cpufreq policy governor. # # From: "Pallipadi, Venkatesh" # Signed-off-by: Dave Jones # # drivers/cpufreq/Kconfig # 2004/08/24 18:27:44+01:00 davej@redhat.com +15 -0 # [CPUFREQ] Merge on-demand cpufreq policy governor. # # From: "Pallipadi, Venkatesh" # Signed-off-by: Dave Jones # # ChangeSet # 2004/08/24 18:21:37+01:00 davej@redhat.com # [CPUFREQ] Fix reset-to-max-speed on unloading of longhaul driver. # # From: Sven Traenkle # # The second part adresses a problem of resetting the max cpu-freq when # unloading the driver. This didn't work for my cpu and I doubt it does # for other. There is no need to pass the computed index of the max. # multiplier in the clock_ratio[] table to longhault_table[] cause the # longhaul_setstate function works with the clock_ratio[] index. # # Changing the while loop to a for loop with upper limit isn't actually # necessary as long as the driver is bug free, but thats IMHO not yet the # case, so I suggest this change in order to not loop endlessly or read # beyond the limits of the clock_ratio array. # # Signed-off-by: Dave Jones # # arch/i386/kernel/cpu/cpufreq/longhaul.c # 2004/08/24 18:21:29+01:00 davej@redhat.com +6 -6 # [CPUFREQ] Fix reset-to-max-speed on unloading of longhaul driver. # # From: Sven Traenkle # # The second part adresses a problem of resetting the max cpu-freq when # unloading the driver. This didn't work for my cpu and I doubt it does # for other. There is no need to pass the computed index of the max. # multiplier in the clock_ratio[] table to longhault_table[] cause the # longhaul_setstate function works with the clock_ratio[] index. # # Changing the while loop to a for loop with upper limit isn't actually # necessary as long as the driver is bug free, but thats IMHO not yet the # case, so I suggest this change in order to not loop endlessly or read # beyond the limits of the clock_ratio array. # # Signed-off-by: Dave Jones # # ChangeSet # 2004/08/24 18:17:48+01:00 davej@redhat.com # [CPUFREQ] Samuel2 can use eblcr to determine FSB. # # From: Sven Traenkle. # # here's a patch that solves some issues I have with the longhaul cpufreq # driver on my epia 6000CL/Via EDEN (actually reporting as CentaurHauls, # family 6, model 7, VIA Samuel 2). The driver tries to compute the fsb speed # while it could actually use the fixed values (as it does for model == 6). # I got this change from the via forum, so no credits to me. # # Signed-off-by: Dave Jones # # arch/i386/kernel/cpu/cpufreq/longhaul.c # 2004/08/24 18:17:41+01:00 davej@redhat.com +1 -1 # [CPUFREQ] Samuel2 can use eblcr to determine FSB. # # From: Sven Traenkle. # # here's a patch that solves some issues I have with the longhaul cpufreq # driver on my epia 6000CL/Via EDEN (actually reporting as CentaurHauls, # family 6, model 7, VIA Samuel 2). The driver tries to compute the fsb speed # while it could actually use the fixed values (as it does for model == 6). # I got this change from the via forum, so no credits to me. # # Signed-off-by: Dave Jones # # ChangeSet # 2004/08/24 18:11:49+01:00 davej@redhat.com # [CPUFREQ] fix up random CodingStyle /whitespace regressions. # # Signed-off-by: Dave Jones # # arch/i386/kernel/cpu/cpufreq/longhaul.c # 2004/08/24 18:11:42+01:00 davej@redhat.com +20 -18 # [CPUFREQ] fix up random CodingStyle /whitespace regressions. # # Signed-off-by: Dave Jones # # ChangeSet # 2004/08/24 18:08:43+01:00 davej@redhat.com # [CPUFREQ] Further cleanups to longhaul driver using defines. # By defining the cpu type at startup, we can make a lot of comparisons # a lot more obvious what they are meaning. # # Signed-off-by: Dave Jones # # arch/i386/kernel/cpu/cpufreq/longhaul.c # 2004/08/24 18:08:35+01:00 davej@redhat.com +28 -13 # [CPUFREQ] Further cleanups to longhaul driver using defines. # By defining the cpu type at startup, we can make a lot of comparisons # a lot more obvious what they are meaning. # # Signed-off-by: Dave Jones # # ChangeSet # 2004/08/24 17:48:56+01:00 davej@redhat.com # [CPUFREQ] Prettyprint longhaul speeds. # If its >= 1000MHz print it as GHz. # # Signed-off-by: Dave Jones # # arch/i386/kernel/cpu/cpufreq/longhaul.c # 2004/08/24 17:48:48+01:00 davej@redhat.com +20 -4 # [CPUFREQ] Prettyprint longhaul speeds. # If its >= 1000MHz print it as GHz. # # Signed-off-by: Dave Jones # # ChangeSet # 2004/08/24 17:15:25+01:00 davej@delerium.codemonkey.org.uk # Merge delerium.codemonkey.org.uk:/mnt/data/src/bk/bk-linus # into delerium.codemonkey.org.uk:/mnt/data/src/bk/cpufreq # # include/asm-i386/acpi.h # 2004/08/24 17:15:18+01:00 davej@delerium.codemonkey.org.uk +0 -0 # Auto merged # # drivers/cpufreq/cpufreq_userspace.c # 2004/08/24 17:15:18+01:00 davej@delerium.codemonkey.org.uk +0 -0 # Auto merged # # arch/i386/kernel/smpboot.c # 2004/08/24 17:15:18+01:00 davej@delerium.codemonkey.org.uk +0 -0 # Auto merged # # ChangeSet # 2004/08/24 09:05:11-07:00 trini@kernel.crashing.org # Merge upstream changes by hand. # # arch/ppc/platforms/sbc82xx.c # 2004/08/24 09:04:53-07:00 trini@kernel.crashing.org +20 -0 # Merge by hand. # # kernel/sysctl.c # 2004/08/24 09:02:24-07:00 trini@kernel.crashing.org +0 -0 # Auto merged # # arch/ppc/kernel/setup.c # 2004/08/24 09:02:24-07:00 trini@kernel.crashing.org +0 -0 # Auto merged # # arch/ppc/Kconfig # 2004/08/24 09:02:23-07:00 trini@kernel.crashing.org +0 -0 # Auto merged # # Documentation/kernel-parameters.txt # 2004/08/24 09:02:23-07:00 trini@kernel.crashing.org +0 -0 # Auto merged # # ChangeSet # 2004/08/24 08:31:24-07:00 trini@kernel.crashing.org # Merge kernel.crashing.org:/home/trini/work/kernel/devel/linux-2.6-reorg # into kernel.crashing.org:/home/trini/work/kernel/pristine/for-linus-ppc # # arch/ppc/syslib/m8260_setup.c # 2004/08/24 08:31:20-07:00 trini@kernel.crashing.org +0 -0 # Auto merged # # arch/ppc/platforms/mvme5100.c # 2004/08/24 08:31:19-07:00 trini@kernel.crashing.org +0 -0 # Auto merged # # arch/ppc/platforms/lopec.c # 2004/08/24 08:31:19-07:00 trini@kernel.crashing.org +0 -0 # Auto merged # # arch/ppc/platforms/mvme5100.c # 2004/08/24 08:31:19-07:00 trini@kernel.crashing.org +0 -0 # Merge rename: arch/ppc/platforms/mvme5100_setup.c -> arch/ppc/platforms/mvme5100.c # # arch/ppc/platforms/mcpn765.c # 2004/08/24 08:31:19-07:00 trini@kernel.crashing.org +0 -0 # Auto merged # # arch/ppc/platforms/lopec.c # 2004/08/24 08:31:19-07:00 trini@kernel.crashing.org +0 -0 # Merge rename: arch/ppc/platforms/lopec_setup.c -> arch/ppc/platforms/lopec.c # # arch/ppc/Kconfig # 2004/08/24 08:31:19-07:00 trini@kernel.crashing.org +0 -0 # Auto merged # # ChangeSet # 2004/08/24 08:30:23-07:00 trini@kernel.crashing.org # ppc32: Fix a typo in cputable.c # # Signed-off-by: Tom Rini # # arch/ppc/kernel/cputable.c # 2004/08/24 08:30:14-07:00 trini@kernel.crashing.org +1 -1 # Fix a typo # # ChangeSet # 2004/08/24 08:29:42-07:00 trini@kernel.crashing.org # ppc32: Fix a compile error when CONFIG_PREP && !CONFIG_PREP_RESIDUAL # # Signed-off-by: Tom Rini # # arch/ppc/platforms/prep_setup.c # 2004/08/24 08:29:33-07:00 trini@kernel.crashing.org +2 -0 # Only check for noresidual on CONFIG_PREP_RESIDUAL. # # ChangeSet # 2004/08/24 15:42:53+01:00 davej@redhat.com # [CPUFREQ] Remove extraneous comment # # Signed-off-by: Dave Jones # # arch/i386/kernel/cpu/cpufreq/longhaul.c # 2004/08/24 15:42:41+01:00 davej@redhat.com +1 -1 # [CPUFREQ] Remove extraneous comment # # Signed-off-by: Dave Jones # # ChangeSet # 2004/08/24 15:38:01+01:00 davej@redhat.com # [CPUFREQ] Powersaver also has voltage scaling abilities. # We currently don't do voltage scaling, but we can at least set things up # to prepare for when we do. # # Signed-off-by: Dave Jones # # arch/i386/kernel/cpu/cpufreq/longhaul.c # 2004/08/24 15:37:49+01:00 davej@redhat.com +2 -1 # [CPUFREQ] Powersaver also has voltage scaling abilities. # We currently don't do voltage scaling, but we can at least set things up # to prepare for when we do. # # Signed-off-by: Dave Jones # # ChangeSet # 2004/08/24 15:35:28+01:00 davej@redhat.com # [CPUFREQ] Introduce some defines for the longhaul version, and use them. # This makes some of the code quite a bit cleaner, and a lot more # obvious whats going on on which CPUs. # # Signed-off-by: Dave Jones # # arch/i386/kernel/cpu/cpufreq/longhaul.c # 2004/08/24 15:33:10+01:00 davej@redhat.com +83 -62 # [CPUFREQ] Introduce some defines for the longhaul version, and use them. # This makes some of the code quite a bit cleaner, and a lot more # obvious whats going on on which CPUs. # # Signed-off-by: Dave Jones # # ChangeSet # 2004/08/24 00:09:55-07:00 corbet@lwn.net # [PATCH] Remove struct bus_type->add() # # I recently went looking for users of the add() method in struct # bus_type, only to discover that there are none. A query to Pat # confirmed that it is surplus and should come out. So here's a patch # that does it. # # While I was at it, I updated Documentation/driver-model/bus.txt to at # least get rid of the blatantly untrue stuff; it is still rather far from # being up to date, however. I may be able to fix that later on. # # Signed-off-by: Jonathan Corbet # Signed-off-by: Andrew Morton # Signed-off-by: Greg Kroah-Hartman # # include/linux/device.h # 2004/08/19 12:26:00-07:00 corbet@lwn.net +0 -1 # Remove struct bus_type->add() # # Documentation/driver-model/bus.txt # 2004/08/19 12:32:58-07:00 corbet@lwn.net +23 -55 # Remove struct bus_type->add() # # ChangeSet # 2004/08/23 13:17:08-07:00 greg@kroah.com # KREF: make kref_get() return void as it makes sense to do so. # # Thanks to Kiran for bugging me to do this. # # Signed-off-by: Greg Kroah-Hartman # # lib/kref.c # 2004/08/23 13:16:09-07:00 greg@kroah.com +1 -2 # KREF: make kref_get() return void as it makes sense to do so. # # Thanks to Kiran for bugging me to do this. # # Signed-off-by: Greg Kroah-Hartman # # include/linux/kref.h # 2004/08/23 13:16:09-07:00 greg@kroah.com +1 -1 # KREF: make kref_get() return void as it makes sense to do so. # # Thanks to Kiran for bugging me to do this. # # Signed-off-by: Greg Kroah-Hartman # # drivers/scsi/sr.c # 2004/08/23 13:16:09-07:00 greg@kroah.com +1 -3 # KREF: make kref_get() return void as it makes sense to do so. # # Thanks to Kiran for bugging me to do this. # # Signed-off-by: Greg Kroah-Hartman # # drivers/scsi/sd.c # 2004/08/23 13:16:09-07:00 greg@kroah.com +1 -3 # KREF: make kref_get() return void as it makes sense to do so. # # Thanks to Kiran for bugging me to do this. # # Signed-off-by: Greg Kroah-Hartman # # ChangeSet # 2004/08/23 11:08:49-07:00 trini@kernel.crashing.org # We weren't including from , so # _IO_BASE was defined to zero instead of isa_io_base. # # Signed-Off-By: David Woodhouse # Signed-Off-By: Tom Rini # # include/asm-ppc/mpc8260.h # 2004/08/23 11:08:39-07:00 trini@kernel.crashing.org +4 -0 # Add before we look at _IO_BASE, etc, # otherwise it cannot be redefined. # # arch/ppc/syslib/m8260_pci.h # 2004/08/23 11:08:39-07:00 trini@kernel.crashing.org +1 -0 # Add a forward declaration of pci_controller. # # ChangeSet # 2004/08/23 13:00:48+01:00 davej@delerium.codemonkey.org.uk # Merge delerium.codemonkey.org.uk:/mnt/data/src/bk/bk-linus # into delerium.codemonkey.org.uk:/mnt/data/src/bk/cpufreq # # include/asm-i386/acpi.h # 2004/08/23 13:00:43+01:00 davej@delerium.codemonkey.org.uk +0 -0 # Auto merged # # drivers/cpufreq/cpufreq_userspace.c # 2004/08/23 13:00:43+01:00 davej@delerium.codemonkey.org.uk +0 -0 # Auto merged # # arch/i386/kernel/smpboot.c # 2004/08/23 13:00:43+01:00 davej@delerium.codemonkey.org.uk +0 -0 # Auto merged # # ChangeSet # 2004/08/22 15:41:39+01:00 rmk@flint.arm.linux.org.uk # [PCMCIA] Remove pccard_mem_map's sys_start and sys_stop elements. # # include/pcmcia/ss.h # 2004/08/22 15:39:16+01:00 rmk@flint.arm.linux.org.uk +0 -1 # Remove pccard_mem_map's sys_start and sys_stop elements. # # drivers/pcmcia/yenta_socket.c # 2004/08/22 15:39:15+01:00 rmk@flint.arm.linux.org.uk +1 -1 # Remove pccard_mem_map's sys_start and sys_stop elements. # # drivers/pcmcia/tcic.c # 2004/08/22 15:39:15+01:00 rmk@flint.arm.linux.org.uk +1 -1 # Remove pccard_mem_map's sys_start and sys_stop elements. # # drivers/pcmcia/rsrc_mgr.c # 2004/08/22 15:39:15+01:00 rmk@flint.arm.linux.org.uk +0 -6 # Remove pccard_mem_map's sys_start and sys_stop elements. # # drivers/pcmcia/pd6729.c # 2004/08/22 15:39:15+01:00 rmk@flint.arm.linux.org.uk +1 -1 # Remove pccard_mem_map's sys_start and sys_stop elements. # # drivers/pcmcia/i82365.c # 2004/08/22 15:39:15+01:00 rmk@flint.arm.linux.org.uk +1 -1 # Remove pccard_mem_map's sys_start and sys_stop elements. # # drivers/pcmcia/i82092.c # 2004/08/22 15:39:14+01:00 rmk@flint.arm.linux.org.uk +1 -1 # Remove pccard_mem_map's sys_start and sys_stop elements. # # drivers/pcmcia/cs.c # 2004/08/22 15:39:14+01:00 rmk@flint.arm.linux.org.uk +0 -7 # Remove pccard_mem_map's sys_start and sys_stop elements. # # drivers/pcmcia/cistpl.c # 2004/08/22 15:39:14+01:00 rmk@flint.arm.linux.org.uk +0 -2 # Remove pccard_mem_map's sys_start and sys_stop elements. # # ChangeSet # 2004/08/22 15:12:37+01:00 rmk@flint.arm.linux.org.uk # [PCMCIA] Don't use sys_start for static-mapped sockets. # # Add static_start element to pccard_mem_map - which is used by # statically mapped sockets to return the physical address which # should be used to access the memory region. # # include/pcmcia/ss.h # 2004/08/22 15:10:24+01:00 rmk@flint.arm.linux.org.uk +1 -0 # Add static_start element to pccard_mem_map - which is used by # statically mapped sockets to return the physical address which # should be used to access the memory region. # # drivers/pcmcia/soc_common.c # 2004/08/22 15:10:24+01:00 rmk@flint.arm.linux.org.uk +1 -3 # Add static_start element to pccard_mem_map - which is used by # statically mapped sockets to return the physical address which # should be used to access the memory region. # # drivers/pcmcia/hd64465_ss.c # 2004/08/22 15:10:24+01:00 rmk@flint.arm.linux.org.uk +4 -7 # Add static_start element to pccard_mem_map - which is used by # statically mapped sockets to return the physical address which # should be used to access the memory region. # # drivers/pcmcia/cs.c # 2004/08/22 15:10:23+01:00 rmk@flint.arm.linux.org.uk +7 -1 # Add static_start element to pccard_mem_map - which is used by # statically mapped sockets to return the physical address which # should be used to access the memory region. # # drivers/pcmcia/cistpl.c # 2004/08/22 15:10:23+01:00 rmk@flint.arm.linux.org.uk +1 -1 # Add static_start element to pccard_mem_map - which is used by # statically mapped sockets to return the physical address which # should be used to access the memory region. # # drivers/pcmcia/au1000_generic.c # 2004/08/22 15:10:23+01:00 rmk@flint.arm.linux.org.uk +4 -11 # Add static_start element to pccard_mem_map - which is used by # statically mapped sockets to return the physical address which # should be used to access the memory region. # # ChangeSet # 2004/08/22 15:02:41+01:00 rmk@flint.arm.linux.org.uk # [PCMCIA] Convert PCI socket drivers to use struct resource. # # Convert PCI socket drivers to use the resource passed in rather than # pccard_mem_map's sys_start and sys_stop elements. This also means # that we convert the struct resource to a PCI bus region, thereby # performing any platform specific fixups which may be necessary. # # drivers/pcmcia/yenta_socket.c # 2004/08/22 14:59:58+01:00 rmk@flint.arm.linux.org.uk +5 -2 # Convert PCI socket drivers to use the resource passed in rather than # pccard_mem_map's sys_start and sys_stop elements. This also means # that we convert the struct resource to a PCI bus region, thereby # performing any platform specific fixups which may be necessary. # # drivers/pcmcia/i82092.c # 2004/08/22 14:59:58+01:00 rmk@flint.arm.linux.org.uk +11 -7 # Convert PCI socket drivers to use the resource passed in rather than # pccard_mem_map's sys_start and sys_stop elements. This also means # that we convert the struct resource to a PCI bus region, thereby # performing any platform specific fixups which may be necessary. # # ChangeSet # 2004/08/22 14:56:24+01:00 rmk@flint.arm.linux.org.uk # [PCMCIA] Use struct resource rather than sys_start/sys_stop # # Convert 16-bit PCMCIA socket drivers to use the struct resource # rather than the sys_start and sys_stop members of pccard_mem_map. # # drivers/pcmcia/tcic.c # 2004/08/22 14:53:56+01:00 rmk@flint.arm.linux.org.uk +5 -5 # Convert 16-bit PCMCIA socket drivers to use the struct resource # rather than the sys_start and sys_stop members of pccard_mem_map. # # drivers/pcmcia/pd6729.c # 2004/08/22 14:53:56+01:00 rmk@flint.arm.linux.org.uk +6 -6 # Convert 16-bit PCMCIA socket drivers to use the struct resource # rather than the sys_start and sys_stop members of pccard_mem_map. # # drivers/pcmcia/i82365.c # 2004/08/22 14:53:55+01:00 rmk@flint.arm.linux.org.uk +6 -6 # Convert 16-bit PCMCIA socket drivers to use the struct resource # rather than the sys_start and sys_stop members of pccard_mem_map. # # ChangeSet # 2004/08/18 11:19:19-07:00 trini@kernel.crashing.org # ppc32: Move ppc32-specific sysctls to arch/ppc # # Remove both of the PPC32 && 6xx sysctls from kernel/sysctl.c to # arch/ppc/ # # Signed-off-by: Tom Rini # # kernel/sysctl.c # 2004/08/18 11:19:09-07:00 trini@kernel.crashing.org +0 -22 # Remove both PPC32-specific sysctls. # # arch/ppc/kernel/ppc_htab.c # 2004/08/18 11:19:09-07:00 trini@kernel.crashing.org +30 -3 # Add a sysctl for l2cr (/proc/sys/kernel/l2cr). # # arch/ppc/kernel/idle.c # 2004/08/18 11:19:09-07:00 trini@kernel.crashing.org +34 -0 # Add a sysctl for powersave-nap (/proc/sys/kernel/powersave-nap). # # ChangeSet # 2004/08/17 10:43:05-07:00 trini@kernel.crashing.org # ppc32: Make use of cpufeatures in some flush rountines # # This is based on an observation from Pantelis Antoniou. We get # a minor speedup of flush_icache_range, __flush_dcache_icache and # __flush_dcache_icache_phys, in that we do not need to do this on # CPUs with a unified cache (601), so check for that feature bit # instead of a PVR check. # # Signed-off-by: Tom Rini # # arch/ppc/kernel/misc.S # 2004/08/17 10:42:55-07:00 trini@kernel.crashing.org +9 -12 # In flush_icache_range, __flush_dcache_icache and # __flush_dcache_icache_phys use the PPC_FEATURE_UNIFIED_CACHE # check, instead of an explicit check for 601 (601 has this feature # which is actually what we want). # # ChangeSet # 2004/08/17 10:40:49-07:00 trini@kernel.crashing.org # ppc32: Fix an LSB floating-point test failure. # # Signed-off-by: Greg Weeks under TS0087 # Signed-off-by: Tom Rini # # arch/ppc/math-emu/op-common.h # 2004/08/17 10:40:39-07:00 trini@kernel.crashing.org +0 -1 # Currently, one of the LSB tests fails here (while it's fine # on ppc_8260 and i386). What we do is remove the round in # the denormalised underflow case. This appears to match the # hardware behavior. # # ChangeSet # 2004/08/17 10:37:47-07:00 trini@kernel.crashing.org # ppc32: Add a 'noresidual' option, to ignore residual data. # # Signed-off-by: Leigh Brown # Signed-off-by: Tom Rini # # arch/ppc/platforms/prep_setup.c # 2004/08/17 10:37:37-07:00 trini@kernel.crashing.org +4 -0 # Add a 'noresidual' option to disable reading of residual data. # # arch/ppc/Kconfig # 2004/08/17 10:37:37-07:00 trini@kernel.crashing.org +4 -3 # Update the help for PREP_RESIDUAL. # # Documentation/kernel-parameters.txt # 2004/08/17 10:37:37-07:00 trini@kernel.crashing.org +2 -0 # Document noresidual. # # ChangeSet # 2004/08/17 10:08:38+01:00 rmk@flint.arm.linux.org.uk # [PCMCIA] Fix case of two "skt" variables. # # We want the value preserved across both sections of code such that # the cleanup works as expected. # # drivers/pcmcia/soc_common.c # 2004/08/17 10:06:38+01:00 rmk@flint.arm.linux.org.uk +3 -2 # Don't declare two 'skt' variables - we want the value to be preserved # across both sections of code. # # ChangeSet # 2004/08/16 10:56:35-07:00 trini@kernel.crashing.org # ppc32: Correct the output of /proc/interrupts on PReP. # # Signed-off-by: Leigh Brown # Signed-off-by: Tom Rini # # arch/ppc/platforms/prep_pci.c # 2004/08/16 10:56:27-07:00 trini@kernel.crashing.org +7 -0 # This makes the /proc/interrupts display the correct edge/level # indicator for each interrupt. This is purely cosmetic, but does # reduce confusion. # # ChangeSet # 2004/08/16 10:53:48-07:00 trini@kernel.crashing.org # ppc32: The planar id is only 1 byte, so only display that much. # # Signed-off-by: Leigh Brown # Signed-off-by: Tom Rini # # arch/ppc/platforms/prep_setup.c # 2004/08/16 10:53:39-07:00 trini@kernel.crashing.org +1 -1 # The planar id is only a byte, so why waste 8 characters displaying # it? # # ChangeSet # 2004/08/16 10:52:25-07:00 trini@kernel.crashing.org # ppc32: Fixup the OpenPIC code for older implementations. # # Signed-off-by: Leigh Brown # Signed-off-by: Tom Rini # # include/asm-ppc/open_pic.h # 2004/08/16 10:52:16-07:00 trini@kernel.crashing.org +1 -1 # Some older E20/E30 machines have a very old implementation of the # OpenPIC which trips up the existing ibm_prep_init() function. This # adds support for it. It also changes the OPENPIC_VEC_SPURIOUS # constant to work around the buggy OpenPIC in those machines. # # arch/ppc/platforms/prep_pci.c # 2004/08/16 10:52:16-07:00 trini@kernel.crashing.org +11 -4 # Some older E20/E30 machines have a very old implementation of the # OpenPIC which trips up the existing ibm_prep_init() function. This # adds support for it. It also changes the OPENPIC_VEC_SPURIOUS # constant to work around the buggy OpenPIC in those machines. # # ChangeSet # 2004/08/16 10:48:13-07:00 trini@kernel.crashing.org # ppc32: Add support for PCIBridgeRS6K to prep_find_bridges(). # # Signed-off-by: Leigh Brown # Signed-off-by: Tom Rini # # arch/ppc/platforms/prep_pci.c # 2004/08/16 10:48:04-07:00 trini@kernel.crashing.org +2 -1 # This adds support for the "PCIBridgeRS6K" bridge type in residual # data to prep_find_bridges() - this is for the 7043-240. # # ChangeSet # 2004/08/16 10:43:48-07:00 trini@kernel.crashing.org # ppc32: Use residual data to determine the addr to pass i8259_init() # # Signed-off-by: Leigh Brown # Signed-off-by: Tom Rini # # include/asm-ppc/residual.h # 2004/08/16 10:43:39-07:00 trini@kernel.crashing.org +1 -0 # This adds a function to use the residual data to determine the # address to pass to i8259_init(). # # arch/ppc/platforms/residual.c # 2004/08/16 10:43:39-07:00 trini@kernel.crashing.org +33 -0 # This adds a function to use the residual data to determine the # address to pass to i8259_init(). # # arch/ppc/platforms/prep_setup.c # 2004/08/16 10:43:39-07:00 trini@kernel.crashing.org +6 -0 # This adds a function to use the residual data to determine the # address to pass to i8259_init(). # # ChangeSet # 2004/08/16 10:40:01-07:00 trini@kernel.crashing.org # ppc32: On PReP, allow for residual data to provide IRQ level/edge info # # This adds a function to determine the 8259 level/edge mask word. # With this function we can now (in theory) support any IBM PReP # machine. We therefore add a little bit more code to fallback # to using residual data if we don't recognise the machine. # # Signed-off-by: Leigh Brown # Signed-off-by: Tom Rini # # include/asm-ppc/residual.h # 2004/08/16 10:39:52-07:00 trini@kernel.crashing.org +1 -0 # This adds a function to determine the 8259 level/edge mask word. # With this function we can now (in theory) support any IBM PReP # machine. We therefore add a little bit more code to fallback # to using residual data if we don't recognise the machine. # # arch/ppc/platforms/residual.c # 2004/08/16 10:39:52-07:00 trini@kernel.crashing.org +30 -0 # This adds a function to determine the 8259 level/edge mask word. # With this function we can now (in theory) support any IBM PReP # machine. We therefore add a little bit more code to fallback # to using residual data if we don't recognise the machine. # # arch/ppc/platforms/prep_setup.c # 2004/08/16 10:39:52-07:00 trini@kernel.crashing.org +18 -1 # This adds a function to determine the 8259 level/edge mask word. # With this function we can now (in theory) support any IBM PReP # machine. We therefore add a little bit more code to fallback # to using residual data if we don't recognise the machine. # # arch/ppc/platforms/prep_pci.c # 2004/08/16 10:39:52-07:00 trini@kernel.crashing.org +18 -4 # This adds a function to determine the 8259 level/edge mask word. # With this function we can now (in theory) support any IBM PReP # machine. We therefore add a little bit more code to fallback # to using residual data if we don't recognise the machine. # # ChangeSet # 2004/08/16 10:35:18-07:00 trini@kernel.crashing.org # ppc32: On PReP, use residual data for PCI dev -> IRQ, and use it. # # Signed-off-by: Leigh Brown # Signed-off-by: Tom Rini # # include/asm-ppc/residual.h # 2004/08/16 10:35:09-07:00 trini@kernel.crashing.org +7 -0 # This adds a function to use the residual data to determine the IRQ # for a given PCI device, and changes prep_pcibios_fixup() to use it. # # arch/ppc/platforms/residual.c # 2004/08/16 10:35:09-07:00 trini@kernel.crashing.org +60 -0 # This adds a function to use the residual data to determine the IRQ # for a given PCI device, and changes prep_pcibios_fixup() to use it. # # arch/ppc/platforms/prep_pci.c # 2004/08/16 10:35:09-07:00 trini@kernel.crashing.org +37 -23 # This adds a function to use the residual data to determine the IRQ # for a given PCI device, and changes prep_pcibios_fixup() to use it. # # ChangeSet # 2004/08/16 10:32:34-07:00 trini@kernel.crashing.org # # This allows use of the IBM status LED if it's found in the residual # data, plus a couple of other bells and whistles. It removes the # 140-specific code. # Signed-off-by: Leigh Brown # Signed-off-by: Tom Rini # # arch/ppc/platforms/prep_setup.c # 2004/08/16 10:32:25-07:00 trini@kernel.crashing.org +109 -7 # This allows use of the IBM status LED if it's found in the residual # data, plus a couple of other bells and whistles. It removes the # 140-specific code. # # ChangeSet # 2004/08/16 10:26:23-07:00 trini@kernel.crashing.org # ppc32: Introduce a have_residual_data macro and switch to it. # # This is mainly to avoid my additions adding loads of ugly # #ifdef CONFIG_RESIDUAL_DATA sections. # # Signed-off-by: Leigh Brown # Signed-off-by: Tom Rini # # include/asm-ppc/residual.h # 2004/08/16 10:26:14-07:00 trini@kernel.crashing.org +7 -0 # Introduce have_residual_data macro and change existing code to # use it. This is mainly to avoid my additions adding loads of # ugly #ifdef CONFIG_RESIDUAL_DATA sections. # # arch/ppc/platforms/residual.c # 2004/08/16 10:26:14-07:00 trini@kernel.crashing.org +5 -5 # Introduce have_residual_data macro and change existing code to # use it. This is mainly to avoid my additions adding loads of # ugly #ifdef CONFIG_RESIDUAL_DATA sections. # # arch/ppc/platforms/prep_setup.c # 2004/08/16 10:26:14-07:00 trini@kernel.crashing.org +30 -35 # Introduce have_residual_data macro and change existing code to # use it. This is mainly to avoid my additions adding loads of # ugly #ifdef CONFIG_RESIDUAL_DATA sections. # # arch/ppc/platforms/prep_pci.c # 2004/08/16 10:26:14-07:00 trini@kernel.crashing.org +40 -41 # Introduce have_residual_data macro and change existing code to # use it. This is mainly to avoid my additions adding loads of # ugly #ifdef CONFIG_RESIDUAL_DATA sections. # # ChangeSet # 2004/08/16 09:13:40-07:00 trini@kernel.crashing.org # ppc32: Fix MPC8260 with an initrd and no root=/dev/ram0 # # Signed-off-by: Tom Rini # # arch/ppc/syslib/m8260_setup.c # 2004/08/16 09:13:31-07:00 trini@kernel.crashing.org +4 -0 # Fix the initrd case. # # ChangeSet # 2004/08/16 09:08:44-07:00 trini@kernel.crashing.org # [PPC32] Default to conswitchp=&dummy_con if DUMMY_CONSOLE. # # Signed-off-by: Tom Rini # # arch/ppc/syslib/ppc4xx_setup.c # 2004/08/16 09:04:08-07:00 trini@kernel.crashing.org +0 -4 # - Don't manually set conswitchp. # # arch/ppc/platforms/spruce.c # 2004/08/16 09:04:08-07:00 trini@kernel.crashing.org +0 -5 # - Don't manually set conswitchp. # # arch/ppc/platforms/sandpoint.c # 2004/08/16 09:04:08-07:00 trini@kernel.crashing.org +0 -4 # - Don't manually set conswitchp. # # arch/ppc/platforms/prpmc800.c # 2004/08/16 09:04:08-07:00 trini@kernel.crashing.org +0 -4 # - Don't manually set conswitchp. # # arch/ppc/platforms/prpmc750.c # 2004/08/16 09:04:08-07:00 trini@kernel.crashing.org +0 -4 # - Don't manually set conswitchp. # # arch/ppc/platforms/prep_setup.c # 2004/08/16 09:04:08-07:00 trini@kernel.crashing.org +0 -2 # - Only set conswitchp if VGA_CONSOLE. # # arch/ppc/platforms/pplus.c # 2004/08/16 09:04:08-07:00 trini@kernel.crashing.org +0 -2 # - Only set conswitchp if VGA_CONSOLE. # # arch/ppc/platforms/pmac_setup.c # 2004/08/16 09:04:08-07:00 trini@kernel.crashing.org +0 -3 # - Don't manually set conswitchp. # # arch/ppc/platforms/pcore.c # 2004/08/16 09:04:08-07:00 trini@kernel.crashing.org +0 -4 # - Don't manually set conswitchp. # # arch/ppc/platforms/mvme5100_setup.c # 2004/08/16 09:04:08-07:00 trini@kernel.crashing.org +0 -4 # - Don't manually set conswitchp. # # arch/ppc/platforms/mcpn765.c # 2004/08/16 09:04:08-07:00 trini@kernel.crashing.org +0 -4 # - Don't manually set conswitchp. # # arch/ppc/platforms/lopec_setup.c # 2004/08/16 09:04:08-07:00 trini@kernel.crashing.org +0 -3 # - Don't manually set conswitchp. # # arch/ppc/platforms/k2.c # 2004/08/16 09:04:08-07:00 trini@kernel.crashing.org +0 -4 # - Don't manually set conswitchp. # # arch/ppc/platforms/chrp_setup.c # 2004/08/16 09:04:08-07:00 trini@kernel.crashing.org +0 -7 # - Don't manually set conswitchp. # # arch/ppc/platforms/85xx/sbc8560.c # 2004/08/16 09:04:08-07:00 trini@kernel.crashing.org +0 -3 # - Don't manually set conswitchp. # # arch/ppc/platforms/85xx/mpc85xx_cds_common.c # 2004/08/16 09:04:08-07:00 trini@kernel.crashing.org +0 -4 # - Don't manually set conswitchp. # # arch/ppc/platforms/85xx/mpc8540_ads.c # 2004/08/16 09:04:08-07:00 trini@kernel.crashing.org +0 -4 # - Don't manually set conswitchp. # # arch/ppc/platforms/4xx/ocotea.c # 2004/08/16 09:04:08-07:00 trini@kernel.crashing.org +0 -4 # - Don't manually set conswitchp. # # arch/ppc/platforms/4xx/ebony.c # 2004/08/16 09:04:08-07:00 trini@kernel.crashing.org +0 -4 # - Don't manually set conswitchp. # # arch/ppc/kernel/setup.c # 2004/08/16 09:04:08-07:00 trini@kernel.crashing.org +4 -0 # - By default, set conswitchp to dummy_con, if DUMMY_CONSOLE. # # arch/ppc/amiga/config.c # 2004/08/16 09:04:08-07:00 trini@kernel.crashing.org +0 -3 # - Don't manually set conswitchp. # # ChangeSet # 2004/08/16 08:57:02-07:00 trini@kernel.crashing.org # Merge kernel.crashing.org:/home/trini/work/kernel/pristine/linux-2.6 # into kernel.crashing.org:/home/trini/work/kernel/pristine/for-linus-ppc # # arch/ppc/syslib/Makefile # 2004/08/16 08:56:56-07:00 trini@kernel.crashing.org +0 -0 # Auto merged # # ChangeSet # 2004/08/13 16:34:31-07:00 trini@kernel.crashing.org # ppc32: Redo the MPC82xx set of call-backs. # # This removes at lot of the nearly empty files, and allows for # boards to do the board-specific init stuff they need in their own # file still. # # arch/ppc/syslib/m8260_setup.c # 2004/08/13 16:33:54-07:00 trini@kernel.crashing.org +18 -35 # - Re-order and cleanup include list. # - Print out vendor and machine in m8260_setup_arch, as that's # what most of the board-specific versions did. # - Simplify getting bd_t infos into one line. # - Rename m8260_init() to platform_init(), add m82xx_board_init() # weak version and call it. # - Remove some extraneous ppc_md.foo = NULLs. # # arch/ppc/platforms/tqm8260_setup.c # 2004/08/13 16:33:54-07:00 trini@kernel.crashing.org +3 -22 # - Cleanup include list. # - No need for callback_setup_arch(). # - Rename platform_init into m82xx_board_init(). # # arch/ppc/platforms/sbc82xx.c # 2004/08/13 16:33:54-07:00 trini@kernel.crashing.org +2 -20 # - Cleanup include list. # - No need for callback_setup_arch(). # - Rename platform_init into m82xx_board_init(). # # arch/ppc/platforms/pq2ads.c # 2004/08/13 16:33:54-07:00 trini@kernel.crashing.org +4 -24 # - No need for _setup_arch anymore. Move that work into # m82xx_board_init(). # - Cleanup include list. # # arch/ppc/platforms/Makefile # 2004/08/13 16:33:53-07:00 trini@kernel.crashing.org +0 -2 # est8260_setup.c and rpx8260.c are gone. # # ChangeSet # 2004/08/13 16:24:02-07:00 trini@kernel.crashing.org # ppc32: Small cleanups to the CPM2 PIC code. # # Signed-off-by: Tom Rini # # arch/ppc/syslib/cpm2_pic.h # 2004/08/13 16:23:50-07:00 trini@kernel.crashing.org +1 -7 # - Remove externs for non-existant functions # - Don't include anything in here. # # arch/ppc/syslib/cpm2_pic.c # 2004/08/13 16:23:50-07:00 trini@kernel.crashing.org +12 -13 # - Re-arrange and cleanup include list. # - Remove old code. # # BitKeeper/deleted/.del-rpx8260.c~f69dcf6ff5e2256 # 2004/08/13 15:40:47-07:00 trini@kernel.crashing.org +1 -18 # Delete: arch/ppc/platforms/rpx8260.c # # BitKeeper/deleted/.del-est8260_setup.c~d56081c82a335303 # 2004/08/13 15:40:47-07:00 trini@kernel.crashing.org +1 -18 # Delete: arch/ppc/platforms/est8260_setup.c # # ChangeSet # 2004/08/13 14:03:42-07:00 trini@kernel.crashing.org # ppc32: Re-work the cpuinfo hooks on MPC82xx # # Now we define CPUINFO_VENDOR and CPUINFO_MACHINE in one callback # instead of using show_cpuinfo and show_percpuinfo call-backs to # print constant per-board information. # # Signed-off-by: Tom Rini # # arch/ppc/syslib/m8260_setup.c # 2004/08/13 14:03:33-07:00 trini@kernel.crashing.org +15 -10 # - Correct file location. # - Convert m8260_show_percpuinfo into m8260_show_cpuinfo, making # use of CPUINFO_{VENDOR,MACHINE} defines. # # arch/ppc/platforms/tqm8260_setup.c # 2004/08/13 14:03:33-07:00 trini@kernel.crashing.org +0 -16 # Remove show_cpuinfo. # # arch/ppc/platforms/tqm8260.h # 2004/08/13 14:03:33-07:00 trini@kernel.crashing.org +4 -0 # Add CPUINFO defines. # # arch/ppc/platforms/sbc82xx.h # 2004/08/13 14:03:33-07:00 trini@kernel.crashing.org +4 -0 # Add CPUINFO defines. # # arch/ppc/platforms/sbc82xx.c # 2004/08/13 14:03:33-07:00 trini@kernel.crashing.org +0 -18 # Remove show_cpuinfo. # # arch/ppc/platforms/rpx8260.h # 2004/08/13 14:03:33-07:00 trini@kernel.crashing.org +7 -0 # Add CPUINFO defines and the correct BOOTROM_RESTART_ADDR. # # arch/ppc/platforms/rpx8260.c # 2004/08/13 14:03:33-07:00 trini@kernel.crashing.org +0 -20 # Remove show_cpuinfo. # # arch/ppc/platforms/pq2ads.h # 2004/08/13 14:03:33-07:00 trini@kernel.crashing.org +4 -0 # Add CPUINFO defines. # # arch/ppc/platforms/pq2ads.c # 2004/08/13 14:03:33-07:00 trini@kernel.crashing.org +0 -20 # Remove show_cpuinfo. # # arch/ppc/platforms/est8260_setup.c # 2004/08/13 14:03:33-07:00 trini@kernel.crashing.org +0 -20 # Remove show_cpuinfo. # # arch/ppc/platforms/est8260.h # 2004/08/13 14:03:33-07:00 trini@kernel.crashing.org +3 -0 # Add CPUINFO defines. # # ChangeSet # 2004/08/12 16:44:55-07:00 trini@kernel.crashing.org # PPC32: Update the Motorola MVME5100 support. # # Signed-off-by: Tom Rini # # include/asm-ppc/serial.h # 2004/08/12 16:44:46-07:00 trini@kernel.crashing.org +1 -1 # s/mvme5100_serial.h/mvme5100.h/ # # arch/ppc/syslib/hawk_common.c # 2004/08/12 16:44:46-07:00 trini@kernel.crashing.org +32 -0 # Add back hawk_mpic_init(pci_mem_offset). # # arch/ppc/platforms/mvme5100.h # 2004/08/12 16:44:46-07:00 trini@kernel.crashing.org +22 -3 # Merge in mvme5100_serial.h # # arch/ppc/platforms/mvme5100.c # 2004/08/12 16:44:46-07:00 trini@kernel.crashing.org +130 -61 # - Merge in mvme5100_pci.c # - Update openpic_initsenses based on documentation. # - s/pplus/hawk/ fixes # - Update openpic calls. # - Update _set_bat(). # # arch/ppc/platforms/Makefile # 2004/08/12 16:44:46-07:00 trini@kernel.crashing.org +1 -1 # Just mvme5100.o now. # # arch/ppc/configs/mvme5100_defconfig # 2004/08/12 16:44:46-07:00 trini@kernel.crashing.org +245 -158 # Update. # # BitKeeper/deleted/.del-mvme5100_serial.h~5d40325917f50f1d # 2004/08/12 15:54:44-07:00 trini@kernel.crashing.org +0 -0 # Delete: arch/ppc/platforms/mvme5100_serial.h # # BitKeeper/deleted/.del-mvme5100_pci.c~e2b80b5ada902aca # 2004/08/12 15:54:44-07:00 trini@kernel.crashing.org +0 -0 # Delete: arch/ppc/platforms/mvme5100_pci.c # # arch/ppc/platforms/mvme5100.c # 2004/08/12 15:28:23-07:00 trini@kernel.crashing.org +0 -0 # Rename: arch/ppc/platforms/mvme5100_setup.c -> arch/ppc/platforms/mvme5100.c # # ChangeSet # 2004/08/12 15:19:38-07:00 trini@kernel.crashing.org # PPC32: Finish cleanup of platforms that just needed _serial.h merged. # # Signed-off-by: Tom Rini # # include/asm-ppc/serial.h # 2004/08/12 15:19:29-07:00 trini@kernel.crashing.org +3 -3 # Remove _serial from powerpmc250/prpmc750/prpmc800 # # arch/ppc/platforms/prpmc800.h # 2004/08/12 15:19:29-07:00 trini@kernel.crashing.org +22 -6 # Merge in _serial.h. # # arch/ppc/platforms/prpmc750.h # 2004/08/12 15:19:29-07:00 trini@kernel.crashing.org +18 -8 # Merge in _serial.h and remove extra #include. # # arch/ppc/platforms/powerpmc250.h # 2004/08/12 15:19:29-07:00 trini@kernel.crashing.org +15 -3 # Merge in _serial.h and remove extra #include. # # BitKeeper/deleted/.del-prpmc800_serial.h~ae077ff6a76997f0 # 2004/08/12 15:16:32-07:00 trini@kernel.crashing.org +0 -0 # Delete: arch/ppc/platforms/prpmc800_serial.h # # BitKeeper/deleted/.del-powerpmc250_serial.h~814b823ebe2f7f52 # 2004/08/12 15:16:32-07:00 trini@kernel.crashing.org +0 -0 # Delete: arch/ppc/platforms/powerpmc250_serial.h # # BitKeeper/deleted/.del-prpmc750_serial.h~897fda58b650902b # 2004/08/12 15:16:31-07:00 trini@kernel.crashing.org +0 -0 # Delete: arch/ppc/platforms/prpmc750_serial.h # # ChangeSet # 2004/08/12 12:57:22-07:00 trini@kernel.crashing.org # PPC32: Update the Motorola LoPEC support # # Signed-off-by: Tom Rini # # include/asm-ppc/serial.h # 2004/08/12 12:57:13-07:00 trini@kernel.crashing.org +1 -1 # s/lopec_serial.h/lopec.h/ # # arch/ppc/platforms/lopec.c # 2004/08/12 12:57:13-07:00 trini@kernel.crashing.org +97 -62 # - Merge in lopec_pci.c # - Take over maintainership. # - Update lopec_set_bat() # - Switch over to GEN550 (do-nothing in this case). # - Only set default ROOT_DEV if BLK_DEV_IDEDISK=y # # arch/ppc/platforms/Makefile # 2004/08/12 12:57:13-07:00 trini@kernel.crashing.org +1 -1 # We just have lopec.o now. # # arch/ppc/Kconfig # 2004/08/12 12:57:13-07:00 trini@kernel.crashing.org +2 -1 # Add LOPEC to the PPC_GEN550 list. # # BitKeeper/deleted/.del-lopec_pci.c~135676742c1bc14b # 2004/08/12 12:27:27-07:00 trini@kernel.crashing.org +0 -0 # Delete: arch/ppc/platforms/lopec_pci.c # # arch/ppc/platforms/lopec.h # 2004/08/12 12:27:25-07:00 trini@kernel.crashing.org +0 -0 # Rename: arch/ppc/platforms/lopec_serial.h -> arch/ppc/platforms/lopec.h # # arch/ppc/platforms/lopec.c # 2004/08/12 12:23:20-07:00 trini@kernel.crashing.org +0 -0 # Rename: arch/ppc/platforms/lopec_setup.c -> arch/ppc/platforms/lopec.c # # ChangeSet # 2004/08/12 12:16:07-07:00 trini@kernel.crashing.org # PPC32: Merge mcpn765_serial.h into mcpn765.h # # Signed-off-by: Tom Rini # # include/asm-ppc/serial.h # 2004/08/12 12:15:58-07:00 trini@kernel.crashing.org +1 -1 # s/mcpn765_serial/mcpn765/ # # arch/ppc/platforms/mcpn765.h # 2004/08/12 12:15:58-07:00 trini@kernel.crashing.org +47 -3 # Merge in mcpn765_serial.h # # arch/ppc/platforms/mcpn765.c # 2004/08/12 12:15:58-07:00 trini@kernel.crashing.org +0 -2 # Remove mcpn765_serial.h # # BitKeeper/deleted/.del-mcpn765_serial.h~fe2a17546689ebde # 2004/08/12 12:11:55-07:00 trini@kernel.crashing.org +0 -0 # Delete: arch/ppc/platforms/mcpn765_serial.h # # ChangeSet # 2004/08/12 11:24:21-07:00 trini@kernel.crashing.org # PPC32: Rename pq2ads_setup.c to pq2ads.c # # Signed-off-by: Tom Rini # # arch/ppc/platforms/pq2ads.c # 2004/08/12 11:24:11-07:00 trini@kernel.crashing.org +1 -1 # Rename pq2ads_setup.c to pq2ads.c # # arch/ppc/platforms/Makefile # 2004/08/12 11:24:11-07:00 trini@kernel.crashing.org +1 -1 # Rename pq2ads_setup.c to pq2ads.c # # arch/ppc/platforms/pq2ads.c # 2004/08/12 11:22:40-07:00 trini@kernel.crashing.org +0 -0 # Rename: arch/ppc/platforms/pq2ads_setup.c -> arch/ppc/platforms/pq2ads.c # # ChangeSet # 2004/08/10 14:49:28-07:00 thomas.koeller@baslerweb.com # [PATCH] Driver Core: fix minor class reference counting issue on the error path # # Signed-off-by: Thomas Koeller # Signed-off-by: Greg Kroah-Hartman # # ChangeSet # 2004/08/10 14:47:24-07:00 olh@suse.de # [PATCH] export legacy pty info via sysfs # # You missed that one last year. # # # export the legacy pty/tty device nodes via sysfs, # so udev has a chance to create them if /dev is in tmpfs. # # Signed-off-by: Olaf Hering # Signed-off-by: Greg Kroah-Hartman # # drivers/char/tty_io.c # 2004/08/10 05:04:53-07:00 olh@suse.de +16 -6 # export legacy pty info via sysfs # # ChangeSet # 2004/08/06 14:18:50-07:00 rml@ximian.com # [PATCH] KOBJECT: add kobject_get_path # # Add a new kobject helper, kobject_get_path(), which is the greatest # function ever. # # Signed-Off-By: Robert Love # Signed-off-by: Greg Kroah-Hartman # # ChangeSet # 2004/08/03 11:14:08-07:00 trini@kernel.crashing.org # [PPC32] Add a watchdog driver on PPC8xx. # # Signed-off-by: Andreas Oberritter # Signed-off-by: Tom Rini # # drivers/char/watchdog/mpc8xx_wdt.c # 2004/08/03 11:13:57-07:00 trini@kernel.crashing.org +164 -0 # # drivers/char/watchdog/mpc8xx_wdt.c # 2004/08/03 11:13:57-07:00 trini@kernel.crashing.org +0 -0 # BitKeeper file /home/trini/work/kernel/pristine/for-linus-ppc/drivers/char/watchdog/mpc8xx_wdt.c # # arch/ppc/syslib/m8xx_wdt.h # 2004/08/03 11:13:56-07:00 trini@kernel.crashing.org +16 -0 # # arch/ppc/syslib/m8xx_wdt.c # 2004/08/03 11:13:56-07:00 trini@kernel.crashing.org +99 -0 # # drivers/char/watchdog/Makefile # 2004/08/03 11:13:56-07:00 trini@kernel.crashing.org +1 -0 # Add 8xx_WDT. # # drivers/char/watchdog/Kconfig # 2004/08/03 11:13:56-07:00 trini@kernel.crashing.org +6 -0 # Add 8xx_WDT. # # arch/ppc/syslib/m8xx_wdt.h # 2004/08/03 11:13:56-07:00 trini@kernel.crashing.org +0 -0 # BitKeeper file /home/trini/work/kernel/pristine/for-linus-ppc/arch/ppc/syslib/m8xx_wdt.h # # arch/ppc/syslib/m8xx_wdt.c # 2004/08/03 11:13:56-07:00 trini@kernel.crashing.org +0 -0 # BitKeeper file /home/trini/work/kernel/pristine/for-linus-ppc/arch/ppc/syslib/m8xx_wdt.c # # arch/ppc/syslib/Makefile # 2004/08/03 11:13:56-07:00 trini@kernel.crashing.org +3 -1 # Add m8xx_wdt.o on CONFIG_8xx_WDT and CONFIG_8xx. # # ChangeSet # 2004/08/03 11:04:30-07:00 trini@kernel.crashing.org # [PPC32] Give PPC8xx a callback into board-specific code in # m8xx_setup_arch(). # # Signed-off-by: Andreas Oberritter # Signed-off-by: Tom Rini # # arch/ppc/syslib/m8xx_setup.c # 2004/08/03 11:04:21-07:00 trini@kernel.crashing.org +6 -0 # Add a hook to allow board-specific initalization to be performed # from m8xx_setup_arch(). # # ChangeSet # 2004/08/03 11:01:58-07:00 trini@kernel.crashing.org # [PPC32] Add a weak version of embed_config(). # # This allows boards with U-Boot to have a functional 'all' target. # # Signed-off-by: Andreas Oberritter # Signed-off-by: Tom Rini # # arch/ppc/boot/simple/misc-embedded.c # 2004/08/03 11:01:47-07:00 trini@kernel.crashing.org +8 -0 # Add a weak version of embed_config(). This allows boards with # U-Boot to have a functional 'all' target. # # ChangeSet # 2004/08/02 17:08:20-07:00 greg@kroah.com # KREF: fix up the current kref users for the changed api. # # Based on work from Kiran, but fixed up by me to actually build and # link properly. # # Signed-off-by: Ravikiran Thirumalai # Signed-off-by: Greg Kroah-Hartman # # # drivers/usb/serial/usb-serial.c # 2004/08/02 17:08:07-07:00 greg@kroah.com +62 -68 # KREF: fix up the current kref users for the changed api. # # Based on work from Kiran, but fixed up by me to actually build and # link properly. # # Signed-off-by: Ravikiran Thirumalai # Signed-off-by: Greg Kroah-Hartman # # # drivers/usb/host/ehci-mem.c # 2004/08/02 17:08:07-07:00 greg@kroah.com +2 -2 # KREF: fix up the current kref users for the changed api. # # Based on work from Kiran, but fixed up by me to actually build and # link properly. # # Signed-off-by: Ravikiran Thirumalai # Signed-off-by: Greg Kroah-Hartman # # # drivers/usb/core/usb.h # 2004/08/02 17:08:07-07:00 greg@kroah.com +1 -0 # KREF: fix up the current kref users for the changed api. # # Based on work from Kiran, but fixed up by me to actually build and # link properly. # # Signed-off-by: Ravikiran Thirumalai # Signed-off-by: Greg Kroah-Hartman # # # drivers/usb/core/urb.c # 2004/08/02 17:08:07-07:00 greg@kroah.com +2 -2 # KREF: fix up the current kref users for the changed api. # # Based on work from Kiran, but fixed up by me to actually build and # link properly. # # Signed-off-by: Ravikiran Thirumalai # Signed-off-by: Greg Kroah-Hartman # # # drivers/usb/core/message.c # 2004/08/02 17:08:07-07:00 greg@kroah.com +1 -1 # KREF: fix up the current kref users for the changed api. # # Based on work from Kiran, but fixed up by me to actually build and # link properly. # # Signed-off-by: Ravikiran Thirumalai # Signed-off-by: Greg Kroah-Hartman # # # drivers/usb/core/config.c # 2004/08/02 17:08:07-07:00 greg@kroah.com +4 -3 # KREF: fix up the current kref users for the changed api. # # Based on work from Kiran, but fixed up by me to actually build and # link properly. # # Signed-off-by: Ravikiran Thirumalai # Signed-off-by: Greg Kroah-Hartman # # # drivers/scsi/sr.c # 2004/08/02 17:08:07-07:00 greg@kroah.com +4 -4 # KREF: fix up the current kref users for the changed api. # # Based on work from Kiran, but fixed up by me to actually build and # link properly. # # Signed-off-by: Ravikiran Thirumalai # Signed-off-by: Greg Kroah-Hartman # # # drivers/scsi/sd.c # 2004/08/02 17:08:07-07:00 greg@kroah.com +4 -4 # KREF: fix up the current kref users for the changed api. # # Based on work from Kiran, but fixed up by me to actually build and # link properly. # # Signed-off-by: Ravikiran Thirumalai # Signed-off-by: Greg Kroah-Hartman # # # ChangeSet # 2004/08/02 17:02:58-07:00 greg@kroah.com # KREF: shrink the size of struct kref down to just a single atomic_t # # This was based on a patch from Kiran, but tweaked further by me. # # Signed-off-by: Ravikiran Thirumalai # Signed-off-by: Greg Kroah-Hartman # # lib/kref.c # 2004/08/02 17:02:45-07:00 greg@kroah.com +12 -14 # KREF: shrink the size of struct kref down to just a single atomic_t # # This was based on a patch from Kiran, but tweaked further by me. # # Signed-off-by: Ravikiran Thirumalai # Signed-off-by: Greg Kroah-Hartman # # include/linux/kref.h # 2004/08/02 17:02:45-07:00 greg@kroah.com +2 -5 # KREF: shrink the size of struct kref down to just a single atomic_t # # This was based on a patch from Kiran, but tweaked further by me. # # Signed-off-by: Ravikiran Thirumalai # Signed-off-by: Greg Kroah-Hartman # diff -Nru a/CREDITS b/CREDITS --- a/CREDITS 2004-08-25 22:01:56 -07:00 +++ b/CREDITS 2004-08-25 22:01:56 -07:00 @@ -735,6 +735,12 @@ S: D-69231 Rauenberg S: Germany +N: Jean Delvare +E: khali@linux-fr.org +W: http://khali.linux-fr.org/ +D: Several hardware monitoring drivers +S: France + N: Peter Denison E: peterd@pnd-pc.demon.co.uk W: http://www.pnd-pc.demon.co.uk/promise/ @@ -754,7 +760,7 @@ D: HTB qdisc and random networking hacks N: Alex deVries -E: adevries@thepuffingroup.com +E: alex@onefishtwo.ca D: Various SGI parts, bits of HAL2 and Newport, PA-RISC Linux. S: 41.5 William Street S: Ottawa, Ontario @@ -2837,6 +2843,9 @@ S: Markusstrasse 18 S: 8006 Zuerich S: Switzerland + +N: Manuel Estrada Sainz +D: Firmware loader (request_firmware) N: Wayne Salamon E: wsalamon@tislabs.com diff -Nru a/Documentation/CodingStyle b/Documentation/CodingStyle --- a/Documentation/CodingStyle 2004-08-25 22:01:55 -07:00 +++ b/Documentation/CodingStyle 2004-08-25 22:01:55 -07:00 @@ -356,10 +356,10 @@ Macros with multiple statements should be enclosed in a do - while block: -#define macrofun(a,b,c) \ +#define macrofun(a, b, c) \ do { \ if (a == 5) \ - do_this(b,c); \ + do_this(b, c); \ } while (0) Things to avoid when using macros: diff -Nru a/Documentation/crypto/api-intro.txt b/Documentation/crypto/api-intro.txt --- a/Documentation/crypto/api-intro.txt 2004-08-25 22:01:55 -07:00 +++ b/Documentation/crypto/api-intro.txt 2004-08-25 22:01:55 -07:00 @@ -227,6 +227,9 @@ Khazad algorithm contributors: Aaron Grothe +Whirlpool algorithm contributors: + Aaron Grothe + Generic scatterwalk code by Adam J. Richter Please send any credits updates or corrections to: diff -Nru a/Documentation/driver-model/bus.txt b/Documentation/driver-model/bus.txt --- a/Documentation/driver-model/bus.txt 2004-08-25 22:01:55 -07:00 +++ b/Documentation/driver-model/bus.txt 2004-08-25 22:01:55 -07:00 @@ -5,20 +5,21 @@ ~~~~~~~~~~ struct bus_type { - char * name; - rwlock_t lock; - atomic_t refcount; - - struct list_head node; - struct list_head devices; - struct list_head drivers; - - struct driver_dir_entry dir; - struct driver_dir_entry device_dir; - struct driver_dir_entry driver_dir; + char * name; - int (*match) (struct device * dev, struct device_driver * drv); - struct device (*add) (struct device * parent, char * bus_id); + struct subsystem subsys; + struct kset drivers; + struct kset devices; + + struct bus_attribute * bus_attrs; + struct device_attribute * dev_attrs; + struct driver_attribute * drv_attrs; + + int (*match)(struct device * dev, struct device_driver * drv); + int (*hotplug) (struct device *dev, char **envp, + int num_envp, char *buffer, int buffer_size); + int (*suspend)(struct device * dev, u32 state); + int (*resume)(struct device * dev); }; int bus_register(struct bus_type * bus); @@ -47,7 +48,7 @@ When a bus driver is initialized, it calls bus_register. This initializes the rest of the fields in the bus object and inserts it into a global list of bus types. Once the bus object is registered, -the fields in it (e.g. the rwlock_t) are usable by the bus driver. +the fields in it are usable by the bus driver. Callbacks @@ -71,40 +72,6 @@ iterated over, and the match callback is called for each device that does not have a driver associated with it. -add(): Adding a child device -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The add callback is available to notify the bus about a child device -at a particular location. - -The parent parameter is the parent device of the child to be added. If -parent == NULL, the bus should add the device as a child of a default -parent device or as a child of the root. This policy decision is up to -the bus driver. - -The format of the bus_id field should be consistent with the format of -the bus_id field of the rest of the devices on the bus. This requires -the caller to know the format. - -On return, the bus driver should return a pointer to the device that -was created. If the device was not created, the bus driver should -return an appropriate error code. Refer to include/linux/err.h for -helper functions to encode errors. Some sample code: - -struct device * pci_bus_add(struct device * parent, char * bus_id) -{ - ... - /* the device already exists */ - return ERR_PTR(-EEXIST); - ... -} - -The caller can check the return value using IS_ERR(): - - struct device * newdev = pci_bus_type.add(parent,bus_id); - if (IS_ERR(newdev)) { - ... - } Device and Driver Lists @@ -118,10 +85,11 @@ The LDM core provides helper functions for iterating over each list. -int bus_for_each_dev(struct bus_type * bus, void * data, - int (*callback)(struct device * dev, void * data)); -int bus_for_each_drv(struct bus_type * bus, void * data, - int (*callback)(struct device_driver * drv, void * data)); +int bus_for_each_dev(struct bus_type * bus, struct device * start, void * data, + int (*fn)(struct device *, void *)); + +int bus_for_each_drv(struct bus_type * bus, struct device_driver * start, + void * data, int (*fn)(struct device_driver *, void *)); These helpers iterate over the respective list, and call the callback for each device or driver in the list. All list accesses are @@ -168,9 +136,9 @@ Exporting Attributes ~~~~~~~~~~~~~~~~~~~~ struct bus_attribute { - struct attribute attr; - ssize_t (*show)(struct bus_type *, char * buf, size_t count, loff_t off); - ssize_t (*store)(struct bus_type *, const char * buf, size_t count, loff_t off); + struct attribute attr; + ssize_t (*show)(struct bus_type *, char * buf); + ssize_t (*store)(struct bus_type *, const char * buf, size_t count); }; Bus drivers can export attributes using the BUS_ATTR macro that works diff -Nru a/Documentation/filesystems/ext2.txt b/Documentation/filesystems/ext2.txt --- a/Documentation/filesystems/ext2.txt 2004-08-25 22:01:54 -07:00 +++ b/Documentation/filesystems/ext2.txt 2004-08-25 22:01:54 -07:00 @@ -17,6 +17,33 @@ bsddf (*) Makes `df' act like BSD. minixdf Makes `df' act like Minix. +barrier=1 This enables/disables barriers. barrier=0 disables it, + barrier=1 enables it. + +orlov (*) This enables the new Orlov block allocator. It's + enabled by default. + +oldalloc This disables the Orlov block allocator and + enables the old block allocator. Orlov should + have better performance, we'd like to get some + feedback if it's the contrary for you. + +user_xattr (*) Enables POSIX Extended Attributes. It's enabled by + default, however you need to confifure its support + (CONFIG_EXT2_FS_XATTR). This is neccesary if you want + to use POSIX Acces Control Lists support. You can visit + http://acl.bestbits.at to know more about POSIX Extended + attributes. + +nouser_xattr Disables POSIX Extended Attributes. + +acl (*) Enables POSIX Access Control Lists support. This is + enabled by default, however you need to configure + its support (CONFIG_EXT2_FS_POSIX_ACL). If you want + to know more about ACLs visit http://acl.bestbits.at + +noacl This option disables POSIX Access Control List support. + check=none, nocheck (*) Don't do extra checking of bitmaps on mount (check=normal and check=strict options removed) @@ -336,9 +363,8 @@ the time of the crash, then there is no guarantee of consistency for the blocks in that transaction so they are discarded (which means any filesystem changes they represent are also lost). - -The ext3 code is currently (Apr 2001) available for 2.2 kernels only, -and not yet available for 2.4 kernels. +Check Documentation/filesystems/ext3.txt if you want to read more about +ext3 and journaling. References ========== @@ -349,8 +375,6 @@ Journaling (ext3) ftp://ftp.uk.linux.org/pub/linux/sct/fs/jfs/ Hashed Directories http://kernelnewbies.org/~phillips/htree/ Filesystem Resizing http://ext2resize.sourceforge.net/ -Extended Attributes & -Access Control Lists http://acl.bestbits.at/ Compression (*) http://www.netspace.net.au/~reiter/e2compr/ Implementations for: diff -Nru a/Documentation/filesystems/ext3.txt b/Documentation/filesystems/ext3.txt --- a/Documentation/filesystems/ext3.txt 2004-08-25 22:01:55 -07:00 +++ b/Documentation/filesystems/ext3.txt 2004-08-25 22:01:55 -07:00 @@ -22,6 +22,63 @@ the inode which will represent the ext3 file system's journal file. +noload Don't load the journal on mounting. + +data=journal All data are committed into the journal prior + to being written into the main file system. + +data=ordered (*) All data are forced directly out to the main file + system prior to its metadata being committed to + the journal. + +data=writeback Data ordering is not preserved, data may be + written into the main file system after its + metadata has been committed to the journal. + +commit=nrsec (*) Ext3 can be told to sync all its data and metadata + every 'nrsec' seconds. The default value is 5 seconds. + This means that if you lose your power, you will lose, + as much, the latest 5 seconds of work (your filesystem + will not be damaged though, thanks to journaling). This + default value (or any low value) will hurt performance, + but it's good for data-safety. Setting it to 0 will + have the same effect than leaving the default 5 sec. + Setting it to very large values will improve + performance. + +barrier=1 This enables/disables barriers. barrier=0 disables it, + barrier=1 enables it. + +orlov (*) This enables the new Orlov block allocator. It's enabled + by default. + +oldalloc This disables the Orlov block allocator and enables the + old block allocator. Orlov should have better performance, + we'd like to get some feedback if it's the contrary for + you. + +user_xattr (*) Enables POSIX Extended Attributes. It's enabled by + default, however you need to confifure its support + (CONFIG_EXT3_FS_XATTR). This is neccesary if you want + to use POSIX Acces Control Lists support. You can visit + http://acl.bestbits.at to know more about POSIX Extended + attributes. + +nouser_xattr Disables POSIX Extended Attributes. + +acl (*) Enables POSIX Access Control Lists support. This is + enabled by default, however you need to configure + its support (CONFIG_EXT3_FS_POSIX_ACL). If you want + to know more about ACLs visit http://acl.bestbits.at + +noacl This option disables POSIX Access Control List support. + +reservation + +noreservation + +resize= + bsddf (*) Make 'df' act like BSD. minixdf Make 'df' act like Minix. @@ -30,8 +87,6 @@ debug Extra debugging information is sent to syslog. -noload Don't load the journal on mounting. - errors=remount-ro(*) Remount the filesystem read-only on an error. errors=continue Keep going on a filesystem error. errors=panic Panic and halt the machine if an error occurs. @@ -48,17 +103,6 @@ sb=n Use alternate superblock at this location. -data=journal All data are committed into the journal prior - to being written into the main file system. - -data=ordered (*) All data are forced directly out to the main file - system prior to its metadata being committed to - the journal. - -data=writeback Data ordering is not preserved, data may be - written into the main file system after its - metadata has been committed to the journal. - quota Quota options are currently silently ignored. noquota (see fs/ext3/super.c, line 594) grpquota @@ -114,7 +158,7 @@ ------------- Ext2 partitions can be easily convert to ext3, with `tune2fs -j `. - Ext3 is fully compatible with Ext2. Ext3 partitions can easily be +Ext3 is fully compatible with Ext2. Ext3 partitions can easily be mounted as Ext2. External Tools diff -Nru a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt --- a/Documentation/filesystems/proc.txt 2004-08-25 22:01:55 -07:00 +++ b/Documentation/filesystems/proc.txt 2004-08-25 22:01:55 -07:00 @@ -169,16 +169,18 @@ process memory usage. Its seven fields are explained in Table 1-2. -Table 1-2: Contents of the statm files +Table 1-2: Contents of the statm files (as of 2.6.8-rc3) .............................................................................. - File Content - size total program size - resident size of memory portions - shared number of pages that are shared - trs number of pages that are 'code' - drs number of pages of data/stack - lrs number of pages of library - dt number of dirty pages + Field Content + size total program size (pages) (same as VmSize in status) + resident size of memory portions (pages) (same as VmRSS in status) + shared number of pages that are shared (i.e. backed by a file) + trs number of pages that are 'code' (not including libs; broken, + includes data segment) + lrs number of pages of library (always 0 on 2.6) + drs number of pages of data/stack (including libs; broken, + includes library text) + dt number of dirty pages (always 0 on 2.6) .............................................................................. 1.2 Kernel data @@ -1173,6 +1175,12 @@ for writeout by the pdflush daemons. It is expressed in 100'ths of a second. Data which has been dirty in-memory for longer than this interval will be written out next time a pdflush daemon wakes up. + +legacy_va_layout +---------------- + +If non-zero, this sysctl disables the new 32-bit mmap mmap layout - the kernel +will use the legacy (2.4) layout for all processes. lower_zone_protection --------------------- diff -Nru a/Documentation/i2c/sysfs-interface b/Documentation/i2c/sysfs-interface --- a/Documentation/i2c/sysfs-interface 2004-08-25 22:01:54 -07:00 +++ b/Documentation/i2c/sysfs-interface 2004-08-25 22:01:54 -07:00 @@ -104,7 +104,7 @@ in7_* varies in8_* varies -in0_ref CPU core reference voltage. +cpu[0-1]_vid CPU core reference voltage. Unit: millivolt Read only. Not always correct. diff -Nru a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt --- a/Documentation/kernel-parameters.txt 2004-08-25 22:01:56 -07:00 +++ b/Documentation/kernel-parameters.txt 2004-08-25 22:01:56 -07:00 @@ -579,6 +579,20 @@ so, the driver will manage that printer. See also header of drivers/char/lp.c. + lpj=n [KNL] + Sets loops_per_jiffy to given constant, thus avoiding + time-consuming boot-time autodetection (up to 250 ms per + CPU). 0 enables autodetection (default). To determine + the correct value for your kernel, boot with normal + autodetection and see what value is printed. Note that + on SMP systems the preset will be applied to all CPUs, + which is likely to cause problems if your CPUs need + significantly divergent settings. An incorrect value + will cause delays in the kernel to be wrong, leading to + unpredictable I/O errors and other breakage. Although + unlikely, in the extreme case this might damage your + hardware. + ltpc= [NET] Format: ,, @@ -751,6 +765,8 @@ lowmem mapping on PPC40x. nomce [IA-32] Machine Check Exception + + noresidual [PPC] Don't use residual data on PReP machines. noresume [SWSUSP] Disables resume and restore original swap space. diff -Nru a/Documentation/laptop-mode.txt b/Documentation/laptop-mode.txt --- a/Documentation/laptop-mode.txt 2004-08-25 22:01:56 -07:00 +++ b/Documentation/laptop-mode.txt 2004-08-25 22:01:56 -07:00 @@ -249,7 +249,7 @@ # playing. #READAHEAD=4096 -# Shall we remount journaled fs. with appropiate commit interval? (1=yes) +# Shall we remount journaled fs. with appropriate commit interval? (1=yes) #DO_REMOUNTS=1 # And shall we add the "noatime" option to that as well? (1=yes) diff -Nru a/Documentation/sched-domains.txt b/Documentation/sched-domains.txt --- a/Documentation/sched-domains.txt 2004-08-25 22:01:54 -07:00 +++ b/Documentation/sched-domains.txt 2004-08-25 22:01:54 -07:00 @@ -5,12 +5,13 @@ are locklessly updated. Each scheduling domain spans a number of CPUs (stored in the ->span field). -A domain's span MUST be a superset of it child's span, and a base domain -for CPU i MUST span at least i. The top domain for each CPU will generally -span all CPUs in the system although strictly it doesn't have to, but this -could lead to a case where some CPUs will never be given tasks to run unless -the CPUs allowed mask is explicitly set. A sched domain's span means "balance -process load among these CPUs". +A domain's span MUST be a superset of it child's span (this restriction could +be relaxed if the need arises), and a base domain for CPU i MUST span at least +i. The top domain for each CPU will generally span all CPUs in the system +although strictly it doesn't have to, but this could lead to a case where some +CPUs will never be given tasks to run unless the CPUs allowed mask is +explicitly set. A sched domain's span means "balance process load among these +CPUs". Each scheduling domain must have one or more CPU groups (struct sched_group) which are organised as a circular one way linked list from the ->groups @@ -45,6 +46,20 @@ The implementor should read comments in include/linux/sched.h: struct sched_domain fields, SD_FLAG_*, SD_*_INIT to get an idea of the specifics and what to tune. + +For SMT, the architecture must define CONFIG_SCHED_SMT and provide a +cpumask_t cpu_sibling_map[NR_CPUS], where cpu_sibling_map[i] is the mask of +all "i"'s siblings as well as "i" itself. + +Architectures may retain the regular override the default SD_*_INIT flags +while using the generic domain builder in kernel/sched.c if they wish to +retain the traditional SMT->SMP->NUMA topology (or some subset of that). This +can be done by #define'ing ARCH_HASH_SCHED_TUNE. + +Alternatively, the architecture may completely override the generic domain +builder by #define'ing ARCH_HASH_SCHED_DOMAIN, and exporting your +arch_init_sched_domains function. This function will attach domains to all +CPUs using cpu_attach_domain. Implementors should change the line #undef SCHED_DOMAIN_DEBUG diff -Nru a/Documentation/sched-stats.txt b/Documentation/sched-stats.txt --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/Documentation/sched-stats.txt 2004-08-25 22:01:56 -07:00 @@ -0,0 +1,153 @@ +Version 10 of schedstats includes support for sched_domains, which +hit the mainline kernel in 2.6.7. Some counters make more sense to be +per-runqueue; other to be per-domain. Note that domains (and their associated +information) will only be pertinent and available on machines utilizing +CONFIG_SMP. + +In version 10 of schedstat, there is at least one level of domain +statistics for each cpu listed, and there may well be more than one +domain. Domains have no particular names in this implementation, but +the highest numbered one typically arbitrates balancing across all the +cpus on the machine, while domain0 is the most tightly focused domain, +sometimes balancing only between pairs of cpus. At this time, there +are no architectures which need more than three domain levels. The first +field in the domain stats is a bit map indicating which cpus are affected +by that domain. + +These fields are counters, and only increment. Programs which make use +of these will need to start with a baseline observation and then calculate +the change in the counters at each subsequent observation. A perl script +which does this for many of the fields is available at + + http://eaglet.rain.com/rick/linux/schedstat/ + +Note that any such script will necessarily be version-specific, as the main +reason to change versions is changes in the output format. For those wishing +to write their own scripts, the fields are described here. + +CPU statistics +-------------- +cpu 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 + +NOTE: In the sched_yield() statistics, the active queue is considered empty + if it has only one process in it, since obviously the process calling + sched_yield() is that process. + +First four fields are sched_yield() statistics: + 1) # of times both the active and the expired queue were empty + 2) # of times just the active queue was empty + 3) # of times just the expired queue was empty + 4) # of times sched_yield() was called + +Next four are schedule() statistics: + 5) # of times the active queue had at least one other process on it + 6) # of times we switched to the expired queue and reused it + 7) # of times schedule() was called + 8) # of times schedule() left the processor idle + +Next four are active_load_balance() statistics: + 9) # of times active_load_balance() was called + 10) # of times active_load_balance() caused this cpu to gain a task + 11) # of times active_load_balance() caused this cpu to lose a task + 12) # of times active_load_balance() tried to move a task and failed + +Next three are try_to_wake_up() statistics: + 13) # of times try_to_wake_up() was called + 14) # of times try_to_wake_up() successfully moved the awakening task + 15) # of times try_to_wake_up() attempted to move the awakening task + +Next two are wake_up_new_task() statistics: + 16) # of times wake_up_new_task() was called + 17) # of times wake_up_new_task() successfully moved the new task + +Next one is a sched_migrate_task() statistic: + 18) # of times sched_migrate_task() was called + +Next one is a sched_balance_exec() statistic: + 19) # of times sched_balance_exec() was called + +Next three are statistics describing scheduling latency: + 20) sum of all time spent running by tasks on this processor (in ms) + 21) sum of all time spent waiting to run by tasks on this processor (in ms) + 22) # of tasks (not necessarily unique) given to the processor + +The last six are statistics dealing with pull_task(): + 23) # of times pull_task() moved a task to this cpu when newly idle + 24) # of times pull_task() stole a task from this cpu when another cpu + was newly idle + 25) # of times pull_task() moved a task to this cpu when idle + 26) # of times pull_task() stole a task from this cpu when another cpu + was idle + 27) # of times pull_task() moved a task to this cpu when busy + 28) # of times pull_task() stole a task from this cpu when another cpu + was busy + + +Domain statistics +----------------- +One of these is produced per domain for each cpu described. (Note that if +CONFIG_SMP is not defined, *no* domains are utilized and these lines +will not appear in the output.) + +domain 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 + +The first field is a bit mask indicating what cpus this domain operates over. + +The next fifteen are a variety of load_balance() statistics: + + 1) # of times in this domain load_balance() was called when the cpu + was idle + 2) # of times in this domain load_balance() was called when the cpu + was busy + 3) # of times in this domain load_balance() was called when the cpu + was just becoming idle + 4) # of times in this domain load_balance() tried to move one or more + tasks and failed, when the cpu was idle + 5) # of times in this domain load_balance() tried to move one or more + tasks and failed, when the cpu was busy + 6) # of times in this domain load_balance() tried to move one or more + tasks and failed, when the cpu was just becoming idle + 7) sum of imbalances discovered (if any) with each call to + load_balance() in this domain when the cpu was idle + 8) sum of imbalances discovered (if any) with each call to + load_balance() in this domain when the cpu was busy + 9) sum of imbalances discovered (if any) with each call to + load_balance() in this domain when the cpu was just becoming idle + 10) # of times in this domain load_balance() was called but did not find + a busier queue while the cpu was idle + 11) # of times in this domain load_balance() was called but did not find + a busier queue while the cpu was busy + 12) # of times in this domain load_balance() was called but did not find + a busier queue while the cpu was just becoming idle + 13) # of times in this domain a busier queue was found while the cpu was + idle but no busier group was found + 14) # of times in this domain a busier queue was found while the cpu was + busy but no busier group was found + 15) # of times in this domain a busier queue was found while the cpu was + just becoming idle but no busier group was found + +Next two are sched_balance_exec() statistics: + 17) # of times in this domain sched_balance_exec() successfully pushed + a task to a new cpu + 18) # of times in this domain sched_balance_exec() tried but failed to + push a task to a new cpu + +Next two are try_to_wake_up() statistics: + 19) # of times in this domain try_to_wake_up() tried to move a task based + on affinity and cache warmth + 20) # of times in this domain try_to_wake_up() tried to move a task based + on load balancing + + +/proc//schedstat +---------------- +schedstats also adds a new /proc/= 2.4.9 and module-init-tools. 4 - Unsafe SMP processors: SMP with CPUs not designed for SMP. -============================================================== - -zero-paged: (PPC only) - -When enabled (non-zero), Linux-PPC will pre-zero pages in -the idle loop, possibly speeding up get_free_pages. Since -this only affects what the idle loop is doing, you should -enable this and see if anything changes. diff -Nru a/Documentation/x86_64/boot-options.txt b/Documentation/x86_64/boot-options.txt --- a/Documentation/x86_64/boot-options.txt 2004-08-25 22:01:56 -07:00 +++ b/Documentation/x86_64/boot-options.txt 2004-08-25 22:01:56 -07:00 @@ -136,17 +136,25 @@ IOMMU - iommu=[size][,noagp][,off][,force][,noforce][,leak][,memaper[=order]][,soft] + iommu=[size][,noagp][,off][,force][,noforce][,leak][,memaper[=order]][,merge] + [,forcesac][,fullflush][,nomerge][,noaperture] size set size of iommu (in bytes) noagp don't initialize the AGP driver and use full aperture. off don't use the IOMMU leak turn on simple iommu leak tracing (only when CONFIG_IOMMU_LEAK is on) memaper[=order] allocate an own aperture over RAM with size 32MB^order. noforce don't force IOMMU usage. Default. - force Force IOMMU - soft Use software bounce buffering for non 32bit IO. Default on Intel - machines. + force Force IOMMU. + merge Do SG merging. Implies force (experimental) + nomerge Don't do SG merging. + forcesac For SAC mode for masks <40bits (experimental) + fullflush Flush IOMMU on each allocation (default) + nofullflush Don't use IOMMU fullflush + allowed overwrite iommu off workarounds for specific chipsets. + soft Use software bounce buffering (default for Intel machines) + noaperture Don't touch the aperture for AGP. - swiotlb=pages + swiotlb=pages[,force] - Prereserve that many 4K pages for the software IO bounce buffering. + pages Prereserve that many 128K pages for the software IO bounce buffering. + force Force all IO through the software TLB. diff -Nru a/MAINTAINERS b/MAINTAINERS --- a/MAINTAINERS 2004-08-25 22:01:55 -07:00 +++ b/MAINTAINERS 2004-08-25 22:01:55 -07:00 @@ -169,7 +169,7 @@ P: Robert Siemer M: Robert.Siemer@gmx.de L: linux-sound@vger.kernel.org -W: http://www.uni-karlsruhe.de/~Robert.Siemer/Private/ +W: http://www.stud.uni-karlsruhe.de/~uh1b/ S: Maintained ACP/MWAVE MODEM @@ -195,8 +195,14 @@ AD1816 SOUND DRIVER P: Thorsten Knabe -W: http://www.student.informatik.tu-darmstadt.de/~tek/projects/linux.html -W: http://www.tu-darmstadt.de/~tek01/projects/linux.html +M: Thorsten Knabe +W: http://linux.thorsten-knabe.de +S: Maintained + +ADM1025 HARDWARE MONITOR DRIVER +P: Jean Delvare +M: khali@linux-fr.org +L: sensors@stimpy.netroedge.com S: Maintained ADT746X FAN DRIVER @@ -762,8 +768,8 @@ S: Maintained EMU10K1 SOUND DRIVER -P: Rui Sousa -M: rui.p.m.sousa@clix.pt +P: James Courtier-Dutton +M: James@superbug.demon.co.uk L: emu10k1-devel@lists.sourceforge.net W: http://sourceforge.net/projects/emu10k1/ S: Maintained @@ -827,10 +833,8 @@ S: Maintained FIRMWARE LOADER (request_firmware) -P: Manuel Estrada Sainz -M: ranty@debian.org L: linux-kernel@vger.kernel.org -S: Maintained +S: Orphan FPU EMULATOR P: Bill Metzenthen @@ -1329,6 +1333,18 @@ W: http://lsm.immunix.org S: Supported +LM83 HARDWARE MONITOR DRIVER +P: Jean Delvare +M: khali@linux-fr.org +L: sensors@stimpy.netroedge.com +S: Maintained + +LM90 HARDWARE MONITOR DRIVER +P: Jean Delvare +M: khali@linux-fr.org +L: sensors@stimpy.netroedge.com +S: Maintained + LOGICAL DISK MANAGER SUPPORT (LDM, Windows 2000/XP Dynamic Disks) P: Richard Russon (FlatCap) M: ldm@flatcap.org @@ -1908,6 +1924,12 @@ W: http://www.winischhofer.net/linuxsisvga.shtml S: Maintained +SMSC47M1 HARDWARE MONITOR DRIVER +P: Jean Delvare +M: khali@linux-fr.org +L: sensors@stimpy.netroedge.com +S: Odd Fixes + SMB FILESYSTEM P: Urban Widmark M: urban@teststation.com @@ -2411,6 +2433,12 @@ M: johnpol@2ka.mipt.ru L: sensors@stimpy.netroedge.com S: Maintained + +W83L785TS HARDWARE MONITOR DRIVER +P: Jean Delvare +M: khali@linux-fr.org +L: sensors@stimpy.netroedge.com +S: Odd Fixes WAN ROUTER & SANGOMA WANPIPE DRIVERS & API (X.25, FRAME RELAY, PPP, CISCO HDLC) P: Nenad Corbic diff -Nru a/Makefile b/Makefile --- a/Makefile 2004-08-25 22:01:55 -07:00 +++ b/Makefile 2004-08-25 22:01:55 -07:00 @@ -279,8 +279,8 @@ # cc-version # Usage gcc-ver := $(call cc-version $(CC)) -cc-version = $(CONFIG_SHELL) $(srctree)/scripts/gcc-version.sh \ - $(if $(1), $(1), $(CC)) +cc-version = $(shell $(CONFIG_SHELL) $(srctree)/scripts/gcc-version.sh \ + $(if $(1), $(1), $(CC))) # Look for make include files relative to root of kernel src diff -Nru a/arch/alpha/kernel/process.c b/arch/alpha/kernel/process.c --- a/arch/alpha/kernel/process.c 2004-08-25 22:01:56 -07:00 +++ b/arch/alpha/kernel/process.c 2004-08-25 22:01:56 -07:00 @@ -246,8 +246,7 @@ if (!usp) usp = rdusp(); - return do_fork(clone_flags & ~CLONE_IDLETASK, usp, regs, 0, - parent_tid, child_tid); + return do_fork(clone_flags, usp, regs, 0, parent_tid, child_tid); } int diff -Nru a/arch/alpha/kernel/signal.c b/arch/alpha/kernel/signal.c --- a/arch/alpha/kernel/signal.c 2004-08-25 22:01:55 -07:00 +++ b/arch/alpha/kernel/signal.c 2004-08-25 22:01:55 -07:00 @@ -469,9 +469,7 @@ return; give_sigsegv: - if (sig == SIGSEGV) - ka->sa.sa_handler = SIG_DFL; - force_sig(SIGSEGV, current); + force_sigsegv(sig, current); } static void @@ -533,9 +531,7 @@ return; give_sigsegv: - if (sig == SIGSEGV) - ka->sa.sa_handler = SIG_DFL; - force_sig(SIGSEGV, current); + force_sigsegv(sig, current); } @@ -608,21 +604,20 @@ siginfo_t info; int signr; unsigned long single_stepping = ptrace_cancel_bpt(current); + struct k_sigaction ka; if (!oldset) oldset = ¤t->blocked; /* This lets the debugger run, ... */ - signr = get_signal_to_deliver(&info, regs, NULL); + signr = get_signal_to_deliver(&info, &ka, regs, NULL); /* ... so re-check the single stepping. */ single_stepping |= ptrace_cancel_bpt(current); if (signr > 0) { /* Whee! Actually deliver the signal. */ - struct k_sigaction *ka = ¤t->sighand->action[signr-1]; - - if (r0) syscall_restart(r0, r19, regs, ka); - handle_signal(signr, ka, &info, oldset, regs, sw); + if (r0) syscall_restart(r0, r19, regs, &ka); + handle_signal(signr, &ka, &info, oldset, regs, sw); if (single_stepping) ptrace_set_bpt(current); /* re-set bpt */ return 1; diff -Nru a/arch/alpha/kernel/smp.c b/arch/alpha/kernel/smp.c --- a/arch/alpha/kernel/smp.c 2004-08-25 22:01:55 -07:00 +++ b/arch/alpha/kernel/smp.c 2004-08-25 22:01:55 -07:00 @@ -411,15 +411,6 @@ return 0; } -static struct task_struct * __init -fork_by_hand(void) -{ - /* Don't care about the contents of regs since we'll never - reschedule the forked task. */ - struct pt_regs regs; - return copy_process(CLONE_VM|CLONE_IDLETASK, 0, ®s, 0, NULL, NULL); -} - /* * Bring one cpu online. */ @@ -435,14 +426,9 @@ the other task-y sort of data structures set up like we wish. We can't use kernel_thread since we must avoid rescheduling the child. */ - idle = fork_by_hand(); + idle = fork_idle(cpuid); if (IS_ERR(idle)) panic("failed fork for CPU %d", cpuid); - - wake_up_forked_process(idle); - - init_idle(idle, cpuid); - unhash_process(idle); DBGS(("smp_boot_one_cpu: CPU %d state 0x%lx flags 0x%lx\n", cpuid, idle->state, idle->flags)); diff -Nru a/arch/alpha/kernel/time.c b/arch/alpha/kernel/time.c --- a/arch/alpha/kernel/time.c 2004-08-25 22:01:55 -07:00 +++ b/arch/alpha/kernel/time.c 2004-08-25 22:01:55 -07:00 @@ -366,7 +366,7 @@ BCD_TO_BIN(year); } - /* PC-like is standard; used for year < 20 || year >= 70 */ + /* PC-like is standard; used for year >= 70 */ epoch = 1900; if (year < 20) epoch = 2000; diff -Nru a/arch/alpha/kernel/vmlinux.lds.S b/arch/alpha/kernel/vmlinux.lds.S --- a/arch/alpha/kernel/vmlinux.lds.S 2004-08-25 22:01:55 -07:00 +++ b/arch/alpha/kernel/vmlinux.lds.S 2004-08-25 22:01:55 -07:00 @@ -46,11 +46,6 @@ __setup_end = .; . = ALIGN(8); - __start___param = .; - __param : { *(__param) } - __stop___param = .; - - . = ALIGN(8); __initcall_start = .; .initcall.init : { *(.initcall1.init) diff -Nru a/arch/alpha/mm/numa.c b/arch/alpha/mm/numa.c --- a/arch/alpha/mm/numa.c 2004-08-25 22:01:54 -07:00 +++ b/arch/alpha/mm/numa.c 2004-08-25 22:01:54 -07:00 @@ -313,7 +313,7 @@ zones_size[ZONE_DMA] = dma_local_pfn; zones_size[ZONE_NORMAL] = (end_pfn - start_pfn) - dma_local_pfn; } - free_area_init_node(nid, NODE_DATA(nid), NULL, zones_size, start_pfn, NULL); + free_area_init_node(nid, NODE_DATA(nid), zones_size, start_pfn, NULL); } /* Initialize the kernel's ZERO_PGE. */ diff -Nru a/arch/arm/Kconfig b/arch/arm/Kconfig --- a/arch/arm/Kconfig 2004-08-25 22:01:55 -07:00 +++ b/arch/arm/Kconfig 2004-08-25 22:01:55 -07:00 @@ -402,7 +402,7 @@ config FPE_NWFPE_XP bool "Support extended precision" - depends on FPE_NWFPE + depends on FPE_NWFPE && !CPU_BIG_ENDIAN help Say Y to include 80-bit support in the kernel floating-point emulator. Otherwise, only 32 and 64-bit support is compiled in. diff -Nru a/arch/arm/common/dmabounce.c b/arch/arm/common/dmabounce.c --- a/arch/arm/common/dmabounce.c 2004-08-25 22:01:54 -07:00 +++ b/arch/arm/common/dmabounce.c 2004-08-25 22:01:54 -07:00 @@ -121,9 +121,9 @@ DO_STATS ( device_info->total_allocs++ ); buf = kmalloc(sizeof(struct safe_buffer), GFP_ATOMIC); - if (buf == 0) { + if (buf == NULL) { dev_warn(dev, "%s: kmalloc failed\n", __func__); - return 0; + return NULL; } if (size <= device_info->small_buffer_size) { @@ -137,16 +137,16 @@ DO_STATS ( device_info->lbp_allocs++ ); } else { - pool = 0; + pool = NULL; safe = dma_alloc_coherent(dev, size, &safe_dma_addr, GFP_ATOMIC); } - if (safe == 0) { + if (safe == NULL) { dev_warn(device_info->dev, "%s: could not alloc dma memory (size=%d)\n", __func__, size); kfree(buf); - return 0; + return NULL; } #ifdef STATS @@ -216,27 +216,33 @@ map_single(struct device *dev, void *ptr, size_t size, enum dma_data_direction dir) { - dma_addr_t dma_addr; struct dmabounce_device_info *device_info = find_dmabounce_dev(dev); + dma_addr_t dma_addr; + int needs_bounce = 0; if (device_info) DO_STATS ( device_info->map_op_count++ ); + dma_addr = virt_to_dma(dev, ptr); + if (dev->dma_mask) { + unsigned long mask = *dev->dma_mask; unsigned long limit; - limit = (*dev->dma_mask + 1) & ~(*dev->dma_mask); - if (limit && (size > limit)) { - dev_err(dev, "DMA mapping too big " - "(requested %#x mask %#Lx)\n", - size, *dev->dma_mask); + limit = (mask + 1) & ~mask; + if (limit && size > limit) { + dev_err(dev, "DMA mapping too big (requested %#x " + "mask %#Lx)\n", size, *dev->dma_mask); return ~0; } - } - dma_addr = virt_to_dma(dev, ptr); + /* + * Figure out if we need to bounce from the DMA mask. + */ + needs_bounce = (dma_addr | (dma_addr + size - 1)) & ~mask; + } - if (device_info && dma_needs_bounce(dev, dma_addr, size)) { + if (device_info && (needs_bounce || dma_needs_bounce(dev, dma_addr, size))) { struct safe_buffer *buf; buf = alloc_safe_buffer(device_info, ptr, size, dir); diff -Nru a/arch/arm/common/sa1111.c b/arch/arm/common/sa1111.c --- a/arch/arm/common/sa1111.c 2004-08-25 22:01:56 -07:00 +++ b/arch/arm/common/sa1111.c 2004-08-25 22:01:56 -07:00 @@ -761,9 +761,6 @@ */ int dma_needs_bounce(struct device *dev, dma_addr_t addr, size_t size) { - unsigned int physaddr = SA1111_DMA_ADDR((unsigned int)addr); - u32 dma_mask = *dev->dma_mask; - /* * Section 4.6 of the "Intel StrongARM SA-1111 Development Module * User's Guide" mentions that jumpers R51 and R52 control the @@ -771,14 +768,8 @@ * SDRAM bank 1 on Neponset). The default configuration selects * Assabet, so any address in bank 1 is necessarily invalid. */ - if ((machine_is_assabet() || machine_is_pfs168()) && - (addr >= 0xc8000000 || (addr + size) >= 0xc8000000)) - return 1; - - /* - * Check to see if either the start or end are illegal. - */ - return ((addr & ~dma_mask)) || ((addr + size - 1) & ~dma_mask); + return ((machine_is_assabet() || machine_is_pfs168()) && + (addr >= 0xc8000000 || (addr + size) >= 0xc8000000)); } struct sa1111_save_data { diff -Nru a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c --- a/arch/arm/kernel/signal.c 2004-08-25 22:01:54 -07:00 +++ b/arch/arm/kernel/signal.c 2004-08-25 22:01:54 -07:00 @@ -639,9 +639,7 @@ return; } - if (sig == SIGSEGV) - ka->sa.sa_handler = SIG_DFL; - force_sig(SIGSEGV, tsk); + force_sigsegv(sig, tsk); } /* diff -Nru a/arch/arm/kernel/sys_arm.c b/arch/arm/kernel/sys_arm.c --- a/arch/arm/kernel/sys_arm.c 2004-08-25 22:01:54 -07:00 +++ b/arch/arm/kernel/sys_arm.c 2004-08-25 22:01:54 -07:00 @@ -217,11 +217,8 @@ return ret; return put_user(raddr, (ulong __user *)third); } - case 1: /* iBCS2 emulator entry point */ - if (!segment_eq(get_fs(), get_ds())) - return -EINVAL; - return do_shmat(first, (char __user *) ptr, - second, (ulong __user *) third); + case 1: /* Of course, we don't support iBCS2! */ + return -EINVAL; } case SHMDT: return sys_shmdt ((char __user *)ptr); @@ -257,7 +254,7 @@ if (!newsp) newsp = regs->ARM_sp; - return do_fork(clone_flags & ~CLONE_IDLETASK, newsp, regs, 0, NULL, NULL); + return do_fork(clone_flags, newsp, regs, 0, NULL, NULL); } asmlinkage int sys_vfork(struct pt_regs *regs) diff -Nru a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S --- a/arch/arm/kernel/vmlinux.lds.S 2004-08-25 22:01:55 -07:00 +++ b/arch/arm/kernel/vmlinux.lds.S 2004-08-25 22:01:55 -07:00 @@ -38,9 +38,6 @@ __early_begin = .; *(__early_param) __early_end = .; - __start___param = .; - *(__param) - __stop___param = .; __initcall_start = .; *(.initcall1.init) *(.initcall2.init) diff -Nru a/arch/arm/mach-s3c2410/clock.c b/arch/arm/mach-s3c2410/clock.c --- a/arch/arm/mach-s3c2410/clock.c 2004-08-25 22:01:54 -07:00 +++ b/arch/arm/mach-s3c2410/clock.c 2004-08-25 22:01:54 -07:00 @@ -1,4 +1,4 @@ -/* linux/arch/arm/mach-s3c2410/gpio.c +/* linux/arch/arm/mach-s3c2410/clock.c * * Copyright (c) 2004 Simtec Electronics * Ben Dooks @@ -99,7 +99,9 @@ int clk_enable(struct clk *clk) { - s3c2410_clk_enable(clk->ctrlbit, 1); + if (clk->ctrlbit != 0) + s3c2410_clk_enable(clk->ctrlbit, 1); + return 0; } @@ -240,6 +242,10 @@ { .name = "spi", .parent = &clk_p, .ctrlbit = S3C2410_CLKCON_SPI + }, + { .name = "watchdog", + .parent = &clk_p, + .ctrlbit = 0 } }; @@ -284,10 +290,10 @@ printk(KERN_ERR "failed to register cpu fclk\n"); if (s3c2410_register_clock(&clk_h) < 0) - printk(KERN_ERR "failed to register cpu fclk\n"); + printk(KERN_ERR "failed to register cpu hclk\n"); if (s3c2410_register_clock(&clk_p) < 0) - printk(KERN_ERR "failed to register cpu fclk\n"); + printk(KERN_ERR "failed to register cpu pclk\n"); for (ptr = 0; ptr < ARRAY_SIZE(init_clocks); ptr++, clkp++) { ret = s3c2410_register_clock(clkp); diff -Nru a/arch/arm/mach-s3c2410/devs.c b/arch/arm/mach-s3c2410/devs.c --- a/arch/arm/mach-s3c2410/devs.c 2004-08-25 22:01:54 -07:00 +++ b/arch/arm/mach-s3c2410/devs.c 2004-08-25 22:01:54 -07:00 @@ -10,6 +10,7 @@ * published by the Free Software Foundation. * * Modifications: + * 21-Aug-2004 BJD Added IRQ_TICK to RTC resources * 18-Aug-2004 BJD Created initial version */ @@ -229,8 +230,12 @@ .start = IRQ_RTC, .end = IRQ_RTC, .flags = IORESOURCE_IRQ, + }, + [2] = { + .start = IRQ_TICK, + .end = IRQ_TICK, + .flags = IORESOURCE_IRQ } - }; struct platform_device s3c_device_rtc = { diff -Nru a/arch/arm/mach-s3c2410/mach-bast.c b/arch/arm/mach-s3c2410/mach-bast.c --- a/arch/arm/mach-s3c2410/mach-bast.c 2004-08-25 22:01:55 -07:00 +++ b/arch/arm/mach-s3c2410/mach-bast.c 2004-08-25 22:01:55 -07:00 @@ -1,6 +1,6 @@ /* linux/arch/arm/mach-s3c2410/mach-bast.c * - * Copyright (c) 2003 Simtec Electronics + * Copyright (c) 2003,2004 Simtec Electronics * Ben Dooks * * http://www.simtec.co.uk/products/EB2410ITX/ @@ -10,6 +10,8 @@ * published by the Free Software Foundation. * * Modifications: + * 20-Aug-2004 BJD Added s3c2410_board struct + * 18-Aug-2004 BJD Added platform devices from default set * 16-May-2003 BJD Created initial version * 16-Aug-2003 BJD Fixed header files and copyright, added URL * 05-Sep-2003 BJD Moved to v2.6 kernel @@ -23,6 +25,7 @@ #include #include #include +#include #include #include @@ -39,6 +42,7 @@ #include #include "s3c2410.h" +#include "devs.h" /* macros for virtual address mods for the io space entries */ #define VA_C5(item) ((item) + BAST_VAM_CS5) @@ -154,6 +158,7 @@ [1] = { .hwport = 1, .flags = 0, + .clock = &bast_serial_clock, .ucon = UCON, .ulcon = ULCON, @@ -170,19 +175,30 @@ } }; +static struct platform_device *bast_devices[] __initdata = { + &s3c_device_usb, + &s3c_device_lcd, + &s3c_device_wdt, + &s3c_device_i2c, + &s3c_device_iis, +}; + +static struct s3c2410_board bast_board __initdata = { + .devices = bast_devices, + .devices_count = ARRAY_SIZE(bast_devices) +}; void __init bast_map_io(void) { s3c2410_map_io(bast_iodesc, ARRAY_SIZE(bast_iodesc)); s3c2410_uartcfgs = bast_uartcfgs; + + s3c2410_set_board(&bast_board); } void __init bast_init_irq(void) { - //llprintk("bast_init_irq:\n"); - s3c2410_init_irq(); - } void __init bast_init_time(void) diff -Nru a/arch/arm/mach-s3c2410/mach-h1940.c b/arch/arm/mach-s3c2410/mach-h1940.c --- a/arch/arm/mach-s3c2410/mach-h1940.c 2004-08-25 22:01:56 -07:00 +++ b/arch/arm/mach-s3c2410/mach-h1940.c 2004-08-25 22:01:56 -07:00 @@ -1,6 +1,6 @@ -/* linux/arch/arm/mach-s3c2410/mach-ipaq.c +/* linux/arch/arm/mach-s3c2410/mach-h1940.c * - * Copyright (c) 2003 Simtec Electronics + * Copyright (c) 2003,2004 Simtec Electronics * Ben Dooks * * http://www.handhelds.org/projects/h1940.html @@ -16,6 +16,7 @@ * 06-Jan-2003 BJD Updates for * 18-Jan-2003 BJD Added serial port configuration * 17-Feb-2003 BJD Copied to mach-ipaq.c + * 21-Aug-2004 BJD Added struct s3c2410_board */ #include @@ -39,6 +40,7 @@ #include #include "s3c2410.h" +#include "devs.h" static struct map_desc ipaq_iodesc[] __initdata = { /* nothing here yet */ @@ -77,10 +79,27 @@ }; + + +static struct platform_device *h1940_devices[] __initdata = { + &s3c_device_usb, + &s3c_device_lcd, + &s3c_device_wdt, + &s3c_device_i2c, + &s3c_device_iis, +}; + +static struct s3c2410_board h1940_board __initdata = { + .devices = h1940_devices, + .devices_count = ARRAY_SIZE(h1940_devices) +}; + void __init ipaq_map_io(void) { s3c2410_map_io(ipaq_iodesc, ARRAY_SIZE(ipaq_iodesc)); s3c2410_uartcfgs = ipaq_uartcfgs; + + s3c2410_set_board(&h1940_board); } void __init ipaq_init_irq(void) diff -Nru a/arch/arm/mach-s3c2410/mach-smdk2410.c b/arch/arm/mach-s3c2410/mach-smdk2410.c --- a/arch/arm/mach-s3c2410/mach-smdk2410.c 2004-08-25 22:01:55 -07:00 +++ b/arch/arm/mach-s3c2410/mach-smdk2410.c 2004-08-25 22:01:55 -07:00 @@ -47,7 +47,7 @@ #include #include "s3c2410.h" - +#include "devs.h" static struct map_desc smdk2410_iodesc[] __initdata = { /* nothing here yet */ @@ -87,11 +87,25 @@ } }; +static struct platform_device *smdk2410_devices[] __initdata = { + &s3c_device_usb, + &s3c_device_lcd, + &s3c_device_wdt, + &s3c_device_i2c, + &s3c_device_iis, +}; + +static struct s3c2410_board smdk2410_board __initdata = { + .devices = smdk2410_devices, + .devices_count = ARRAY_SIZE(smdk2410_devices) +}; void __init smdk2410_map_io(void) { s3c2410_map_io(smdk2410_iodesc, ARRAY_SIZE(smdk2410_iodesc)); s3c2410_uartcfgs = smdk2410_uartcfgs; + + s3c2410_set_board(&smdk2410_board); } void __init smdk2410_init_irq(void) diff -Nru a/arch/arm/mach-s3c2410/mach-vr1000.c b/arch/arm/mach-s3c2410/mach-vr1000.c --- a/arch/arm/mach-s3c2410/mach-vr1000.c 2004-08-25 22:01:56 -07:00 +++ b/arch/arm/mach-s3c2410/mach-vr1000.c 2004-08-25 22:01:56 -07:00 @@ -11,13 +11,8 @@ * published by the Free Software Foundation. * * Modifications: + * 21-Aug-2004 BJD Added struct s3c2410_board * 06-Aug-2004 BJD Fixed call to time initialisation - * 12-Jul-2004 BJD Renamed machine - * 16-May-2003 BJD Created initial version - * 16-Aug-2003 BJD Fixed header files and copyright, added URL - * 05-Sep-2003 BJD Moved to v2.6 kernel - * 06-Jan-2003 BJD Updates for - * 18-Jan-2003 BJD Added serial port configuration * 05-Apr-2004 BJD Copied to make mach-vr1000.c */ @@ -44,6 +39,7 @@ #include #include "s3c2410.h" +#include "devs.h" /* macros for virtual address mods for the io space entries */ #define VA_C5(item) ((item) + BAST_VAM_CS5) @@ -143,11 +139,26 @@ } }; +static struct platform_device *vr1000_devices[] __initdata = { + &s3c_device_usb, + &s3c_device_lcd, + &s3c_device_wdt, + &s3c_device_i2c, + &s3c_device_iis, +}; + +static struct s3c2410_board vr1000_board __initdata = { + .devices = vr1000_devices, + .devices_count = ARRAY_SIZE(vr1000_devices) +}; + void __init vr1000_map_io(void) { s3c2410_map_io(vr1000_iodesc, ARRAY_SIZE(vr1000_iodesc)); s3c2410_uartcfgs = vr1000_uartcfgs; + + s3c2410_set_board(&vr1000_board); } void __init vr1000_init_irq(void) diff -Nru a/arch/arm/mach-s3c2410/s3c2410.c b/arch/arm/mach-s3c2410/s3c2410.c --- a/arch/arm/mach-s3c2410/s3c2410.c 2004-08-25 22:01:55 -07:00 +++ b/arch/arm/mach-s3c2410/s3c2410.c 2004-08-25 22:01:55 -07:00 @@ -1,6 +1,6 @@ /* linux/arch/arm/mach-s3c2410/s3c2410.c * - * Copyright (c) 2003 Simtec Electronics + * Copyright (c) 2003,2004 Simtec Electronics * Ben Dooks * * http://www.simtec.co.uk/products/EB2410ITX/ @@ -13,7 +13,8 @@ * 16-May-2003 BJD Created initial version * 16-Aug-2003 BJD Fixed header files and copyright, added URL * 05-Sep-2003 BJD Moved to kernel v2.6 - * 18-Jan-2003 BJD Added serial port configuration + * 18-Jan-2004 BJD Added serial port configuration + * 21-Aug-2004 BJD Added new struct s3c2410_board handler */ #include @@ -35,6 +36,8 @@ #include #include +#include "s3c2410.h" + int s3c2410_clock_tick_rate = 12*1000*1000; /* current timers at 12MHz */ /* serial port setup */ @@ -56,24 +59,15 @@ #define IODESC_ENT(x) { S3C2410_VA_##x, S3C2410_PA_##x, S3C2410_SZ_##x, MT_DEVICE } static struct map_desc s3c2410_iodesc[] __initdata = { - IODESC_ENT(IRQ), - IODESC_ENT(MEMCTRL), - IODESC_ENT(USBHOST), - IODESC_ENT(DMA), - IODESC_ENT(CLKPWR), - IODESC_ENT(LCD), - IODESC_ENT(NAND), - IODESC_ENT(UART), - IODESC_ENT(TIMER), - IODESC_ENT(USBDEV), - IODESC_ENT(WATCHDOG), - IODESC_ENT(IIC), - IODESC_ENT(IIS), - IODESC_ENT(GPIO), - IODESC_ENT(RTC), - IODESC_ENT(ADC), - IODESC_ENT(SPI), - IODESC_ENT(SDI) + IODESC_ENT(IRQ), + IODESC_ENT(MEMCTRL), + IODESC_ENT(USBHOST), + IODESC_ENT(CLKPWR), + IODESC_ENT(LCD), + IODESC_ENT(UART), + IODESC_ENT(TIMER), + IODESC_ENT(GPIO), + IODESC_ENT(ADC), }; static struct resource s3c_uart0_resource[] = { @@ -175,6 +169,12 @@ print_mhz(s3c2410_pclk)); } +static struct s3c2410_board *board; + +void s3c2410_set_board(struct s3c2410_board *b) +{ + board = b; +} static int __init s3c2410_init(void) { @@ -183,6 +183,22 @@ printk("S3C2410: Initialising architecture\n"); ret = platform_add_devices(uart_devices, ARRAY_SIZE(uart_devices)); + if (ret) + return ret; + + if (board != NULL) { + if (board->devices != NULL) { + ret = platform_add_devices(board->devices, + board->devices_count); + + if (ret) { + printk(KERN_ERR "s3c2410: failed to add board devices (%d)\n", ret); + } + } + + /* not adding board devices may not be fatal */ + ret = 0; + } return ret; } diff -Nru a/arch/arm/mach-s3c2410/s3c2410.h b/arch/arm/mach-s3c2410/s3c2410.h --- a/arch/arm/mach-s3c2410/s3c2410.h 2004-08-25 22:01:55 -07:00 +++ b/arch/arm/mach-s3c2410/s3c2410.h 2004-08-25 22:01:55 -07:00 @@ -11,7 +11,7 @@ * * Modifications: * 18-Aug-2004 BJD Created initial version - * + * 20-Aug-2004 BJD Added s3c2410_board struct */ extern void s3c2410_map_io(struct map_desc *, int count); @@ -20,3 +20,16 @@ extern void s3c2410_init_time(void); +/* the board structure is used at first initialsation time + * to get info such as the devices to register for this + * board. This is done because platfrom_add_devices() cannot + * be called from the map_io entry. + * +*/ + +struct s3c2410_board { + struct platform_device **devices; + unsigned int devices_count; +}; + +extern void s3c2410_set_board(struct s3c2410_board *board); diff -Nru a/arch/arm/mm/init.c b/arch/arm/mm/init.c --- a/arch/arm/mm/init.c 2004-08-25 22:01:54 -07:00 +++ b/arch/arm/mm/init.c 2004-08-25 22:01:54 -07:00 @@ -495,7 +495,7 @@ */ arch_adjust_zones(node, zone_size, zhole_size); - free_area_init_node(node, pgdat, NULL, zone_size, + free_area_init_node(node, pgdat, zone_size, bdata->node_boot_start >> PAGE_SHIFT, zhole_size); } diff -Nru a/arch/arm/nwfpe/fpa11_cpdt.c b/arch/arm/nwfpe/fpa11_cpdt.c --- a/arch/arm/nwfpe/fpa11_cpdt.c 2004-08-25 22:01:56 -07:00 +++ b/arch/arm/nwfpe/fpa11_cpdt.c 2004-08-25 22:01:56 -07:00 @@ -42,8 +42,13 @@ unsigned int *p; p = (unsigned int *) &fpa11->fpreg[Fn].fDouble; fpa11->fType[Fn] = typeDouble; +#ifdef __ARMEB__ + get_user(p[0], &pMem[0]); /* sign & exponent */ + get_user(p[1], &pMem[1]); +#else get_user(p[0], &pMem[1]); get_user(p[1], &pMem[0]); /* sign & exponent */ +#endif } #ifdef CONFIG_FPE_NWFPE_XP @@ -140,8 +145,13 @@ val.f = fpa11->fpreg[Fn].fDouble; } +#ifdef __ARMEB__ + put_user(val.i[0], &pMem[0]); /* msw */ + put_user(val.i[1], &pMem[1]); /* lsw */ +#else put_user(val.i[1], &pMem[0]); /* msw */ put_user(val.i[0], &pMem[1]); /* lsw */ +#endif } #ifdef CONFIG_FPE_NWFPE_XP diff -Nru a/arch/arm/oprofile/op_model_xscale.c b/arch/arm/oprofile/op_model_xscale.c --- a/arch/arm/oprofile/op_model_xscale.c 2004-08-25 22:01:55 -07:00 +++ b/arch/arm/oprofile/op_model_xscale.c 2004-08-25 22:01:55 -07:00 @@ -30,6 +30,7 @@ #define PMN_RESET 0x002 /* Reset event counters */ #define CCNT_RESET 0x004 /* Reset clock counter */ #define PMU_RESET (CCNT_RESET | PMN_RESET) +#define PMU_CNT64 0x008 /* Make CCNT count every 64th cycle */ /* TODO do runtime detection */ #ifdef CONFIG_ARCH_IOP310 @@ -125,12 +126,15 @@ static void write_pmnc(u32 val) { - /* upper 4bits and 7, 11 are write-as-0 */ - val &= 0xffff77f; - if (pmu->id == PMU_XSC1) + if (pmu->id == PMU_XSC1) { + /* upper 4bits and 7, 11 are write-as-0 */ + val &= 0xffff77f; __asm__ __volatile__ ("mcr p14, 0, %0, c0, c0, 0" : : "r" (val)); - else + } else { + /* bits 4-23 are write-as-0, 24-31 are write ignored */ + val &= 0xf; __asm__ __volatile__ ("mcr p14, 0, %0, c0, c1, 0" : : "r" (val)); + } } static u32 read_pmnc(void) @@ -139,8 +143,11 @@ if (pmu->id == PMU_XSC1) __asm__ __volatile__ ("mrc p14, 0, %0, c0, c0, 0" : "=r" (val)); - else + else { __asm__ __volatile__ ("mrc p14, 0, %0, c0, c1, 0" : "=r" (val)); + /* bits 1-2 and 4-23 are read-unpredictable */ + val &= 0xff000009; + } return val; } @@ -386,8 +393,10 @@ if (pmu->id == PMU_XSC1) pmnc |= pmu->int_enable; - else + else { __asm__ __volatile__ ("mcr p14, 0, %0, c4, c1, 0" : : "r" (pmu->int_enable)); + pmnc &= ~PMU_CNT64; + } pmnc |= PMU_ENABLE; write_pmnc(pmnc); diff -Nru a/arch/arm26/kernel/signal.c b/arch/arm26/kernel/signal.c --- a/arch/arm26/kernel/signal.c 2004-08-25 22:01:54 -07:00 +++ b/arch/arm26/kernel/signal.c 2004-08-25 22:01:54 -07:00 @@ -465,9 +465,7 @@ return; } - if (sig == SIGSEGV) - ka->sa.sa_handler = SIG_DFL; - force_sig(SIGSEGV, tsk); + force_sigsegv(sig, tsk); } /* diff -Nru a/arch/arm26/kernel/sys_arm.c b/arch/arm26/kernel/sys_arm.c --- a/arch/arm26/kernel/sys_arm.c 2004-08-25 22:01:55 -07:00 +++ b/arch/arm26/kernel/sys_arm.c 2004-08-25 22:01:55 -07:00 @@ -256,7 +256,7 @@ if (!newsp) newsp = regs->ARM_sp; - return do_fork(clone_flags & ~CLONE_IDLETASK, newsp, regs, 0, NULL, NULL); + return do_fork(clone_flags, newsp, regs, 0, NULL, NULL); } asmlinkage int sys_vfork(struct pt_regs *regs) diff -Nru a/arch/arm26/kernel/vmlinux-arm26-xip.lds.in b/arch/arm26/kernel/vmlinux-arm26-xip.lds.in --- a/arch/arm26/kernel/vmlinux-arm26-xip.lds.in 2004-08-25 22:01:56 -07:00 +++ b/arch/arm26/kernel/vmlinux-arm26-xip.lds.in 2004-08-25 22:01:56 -07:00 @@ -34,9 +34,6 @@ __early_begin = .; *(__early_param) __early_end = .; - __start___param = .; - *(__param) - __stop___param = .; __initcall_start = .; *(.initcall1.init) *(.initcall2.init) diff -Nru a/arch/arm26/kernel/vmlinux-arm26.lds.in b/arch/arm26/kernel/vmlinux-arm26.lds.in --- a/arch/arm26/kernel/vmlinux-arm26.lds.in 2004-08-25 22:01:54 -07:00 +++ b/arch/arm26/kernel/vmlinux-arm26.lds.in 2004-08-25 22:01:54 -07:00 @@ -35,9 +35,6 @@ __early_begin = .; *(__early_param) __early_end = .; - __start___param = .; - *(__param) - __stop___param = .; __initcall_start = .; *(.initcall1.init) *(.initcall2.init) diff -Nru a/arch/arm26/mm/init.c b/arch/arm26/mm/init.c --- a/arch/arm26/mm/init.c 2004-08-25 22:01:56 -07:00 +++ b/arch/arm26/mm/init.c 2004-08-25 22:01:56 -07:00 @@ -305,8 +305,8 @@ (bdata->node_boot_start >> PAGE_SHIFT); if (!zone_size[0]) BUG(); - - free_area_init_node(0, pgdat, 0, zone_size, + pgdat->node_mem_map = NULL; + free_area_init_node(0, pgdat, zone_size, bdata->node_boot_start >> PAGE_SHIFT, zhole_size); mem_map = NODE_DATA(0)->node_mem_map; diff -Nru a/arch/cris/arch-v10/kernel/process.c b/arch/cris/arch-v10/kernel/process.c --- a/arch/cris/arch-v10/kernel/process.c 2004-08-25 22:01:55 -07:00 +++ b/arch/cris/arch-v10/kernel/process.c 2004-08-25 22:01:55 -07:00 @@ -180,7 +180,7 @@ { if (!newusp) newusp = rdusp(); - return do_fork(flags & ~CLONE_IDLETASK, newusp, regs, 0, parent_tid, child_tid); + return do_fork(flags, newusp, regs, 0, parent_tid, child_tid); } /* vfork is a system call in i386 because of register-pressure - maybe diff -Nru a/arch/cris/arch-v10/kernel/signal.c b/arch/cris/arch-v10/kernel/signal.c --- a/arch/cris/arch-v10/kernel/signal.c 2004-08-25 22:01:54 -07:00 +++ b/arch/cris/arch-v10/kernel/signal.c 2004-08-25 22:01:54 -07:00 @@ -409,9 +409,7 @@ return; give_sigsegv: - if (sig == SIGSEGV) - ka->sa.sa_handler = SIG_DFL; - force_sig(SIGSEGV, current); + force_sigsegv(sig, current); } static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, @@ -475,9 +473,7 @@ return; give_sigsegv: - if (sig == SIGSEGV) - ka->sa.sa_handler = SIG_DFL; - force_sig(SIGSEGV, current); + force_sigsegv(sig, current); } /* diff -Nru a/arch/cris/arch-v10/mm/init.c b/arch/cris/arch-v10/mm/init.c --- a/arch/cris/arch-v10/mm/init.c 2004-08-25 22:01:54 -07:00 +++ b/arch/cris/arch-v10/mm/init.c 2004-08-25 22:01:54 -07:00 @@ -183,7 +183,7 @@ * mem_map page array. */ - free_area_init_node(0, &contig_page_data, 0, zones_size, PAGE_OFFSET >> PAGE_SHIFT, 0); + free_area_init_node(0, &contig_page_data, zones_size, PAGE_OFFSET >> PAGE_SHIFT, 0); mem_map = contig_page_data.node_mem_map; } diff -Nru a/arch/cris/arch-v10/vmlinux.lds.S b/arch/cris/arch-v10/vmlinux.lds.S --- a/arch/cris/arch-v10/vmlinux.lds.S 2004-08-25 22:01:55 -07:00 +++ b/arch/cris/arch-v10/vmlinux.lds.S 2004-08-25 22:01:55 -07:00 @@ -64,9 +64,6 @@ __setup_start = .; .init.setup : { *(.init.setup) } __setup_end = .; - __start___param = .; - __param : { *(__param) } - __stop___param = .; .initcall.init : { __initcall_start = .; *(.initcall1.init); diff -Nru a/arch/h8300/kernel/process.c b/arch/h8300/kernel/process.c --- a/arch/h8300/kernel/process.c 2004-08-25 22:01:54 -07:00 +++ b/arch/h8300/kernel/process.c 2004-08-25 22:01:54 -07:00 @@ -189,7 +189,7 @@ newsp = regs->er2; if (!newsp) newsp = rdusp(); - return do_fork(clone_flags & ~CLONE_IDLETASK, newsp, regs, 0, NULL, NULL); + return do_fork(clone_flags, newsp, regs, 0, NULL, NULL); } diff -Nru a/arch/h8300/kernel/signal.c b/arch/h8300/kernel/signal.c --- a/arch/h8300/kernel/signal.c 2004-08-25 22:01:55 -07:00 +++ b/arch/h8300/kernel/signal.c 2004-08-25 22:01:55 -07:00 @@ -391,9 +391,7 @@ return; give_sigsegv: - if (sig == SIGSEGV) - ka->sa.sa_handler = SIG_DFL; - force_sig(SIGSEGV, current); + force_sigsegv(sig, current); } static void setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info, @@ -443,9 +441,7 @@ return; give_sigsegv: - if (sig == SIGSEGV) - ka->sa.sa_handler = SIG_DFL; - force_sig(SIGSEGV, current); + force_sigsegv(sig, current); } static inline void diff -Nru a/arch/h8300/kernel/vmlinux.lds.S b/arch/h8300/kernel/vmlinux.lds.S --- a/arch/h8300/kernel/vmlinux.lds.S 2004-08-25 22:01:55 -07:00 +++ b/arch/h8300/kernel/vmlinux.lds.S 2004-08-25 22:01:55 -07:00 @@ -150,9 +150,6 @@ *(.init.setup) . = ALIGN(0x4) ; ___setup_end = .; - ___start___param = .; - *(__param) - ___stop___param = .; ___initcall_start = .; *(.initcall1.init) *(.initcall2.init) diff -Nru a/arch/i386/Kconfig.debug b/arch/i386/Kconfig.debug --- a/arch/i386/Kconfig.debug 2004-08-25 22:01:55 -07:00 +++ b/arch/i386/Kconfig.debug 2004-08-25 22:01:55 -07:00 @@ -45,6 +45,18 @@ on the VM subsystem for higher order allocations. This option will also use IRQ stacks to compensate for the reduced stackspace. +config SCHEDSTATS + bool "Collect scheduler statistics" + depends on DEBUG_KERNEL && PROC_FS + help + If you say Y here, additional code will be inserted into the + scheduler and related routines to collect statistics about + scheduler behavior and provide them in /proc/schedstat. These + stats may be useful for both tuning and debugging the scheduler + If you aren't debugging the scheduler or trying to tune a specific + application, you can say N to avoid the very slight overhead + this adds. + config X86_FIND_SMP_CONFIG bool depends on X86_LOCAL_APIC || X86_VOYAGER diff -Nru a/arch/i386/kernel/Makefile b/arch/i386/kernel/Makefile --- a/arch/i386/kernel/Makefile 2004-08-25 22:01:54 -07:00 +++ b/arch/i386/kernel/Makefile 2004-08-25 22:01:54 -07:00 @@ -47,12 +47,14 @@ cmd_syscall = $(CC) -nostdlib $(SYSCFLAGS_$(@F)) \ -Wl,-T,$(filter-out FORCE,$^) -o $@ +export AFLAGS_vsyscall.lds.o += -P -C -U$(ARCH) + vsyscall-flags = -shared -s -Wl,-soname=linux-gate.so.1 SYSCFLAGS_vsyscall-sysenter.so = $(vsyscall-flags) SYSCFLAGS_vsyscall-int80.so = $(vsyscall-flags) $(obj)/vsyscall-int80.so $(obj)/vsyscall-sysenter.so: \ -$(obj)/vsyscall-%.so: $(src)/vsyscall.lds $(obj)/vsyscall-%.o FORCE +$(obj)/vsyscall-%.so: $(src)/vsyscall.lds.s $(obj)/vsyscall-%.o FORCE $(call if_changed,syscall) # We also create a special relocatable object that should mirror the symbol @@ -63,5 +65,5 @@ $(obj)/built-in.o: ld_flags += -R $(obj)/vsyscall-syms.o SYSCFLAGS_vsyscall-syms.o = -r -$(obj)/vsyscall-syms.o: $(src)/vsyscall.lds $(obj)/vsyscall-sysenter.o FORCE +$(obj)/vsyscall-syms.o: $(src)/vsyscall.lds.s $(obj)/vsyscall-sysenter.o FORCE $(call if_changed,syscall) diff -Nru a/arch/i386/kernel/apic.c b/arch/i386/kernel/apic.c --- a/arch/i386/kernel/apic.c 2004-08-25 22:01:56 -07:00 +++ b/arch/i386/kernel/apic.c 2004-08-25 22:01:56 -07:00 @@ -343,7 +343,7 @@ void __init setup_local_APIC (void) { - unsigned long value, ver, maxlvt; + unsigned long oldvalue, value, ver, maxlvt; /* Pound the ESR really hard over the head with a big hammer - mbligh */ if (esr_disable) { @@ -459,9 +459,7 @@ maxlvt = get_maxlvt(); if (maxlvt > 3) /* Due to the Pentium erratum 3AP. */ apic_write(APIC_ESR, 0); - value = apic_read(APIC_ESR); - apic_printk(APIC_VERBOSE, "ESR value before enabling vector:" - " %08lx\n", value); + oldvalue = apic_read(APIC_ESR); value = ERROR_APIC_VECTOR; // enables sending errors apic_write_around(APIC_LVTERR, value); @@ -471,8 +469,10 @@ if (maxlvt > 3) apic_write(APIC_ESR, 0); value = apic_read(APIC_ESR); - apic_printk(APIC_VERBOSE, "ESR value after enabling vector:" - " %08lx\n", value); + if (value != oldvalue) + apic_printk(APIC_VERBOSE, "ESR value before enabling " + "vector: 0x%08lx after: 0x%08lx\n", + oldvalue, value); } else { if (esr_disable) /* diff -Nru a/arch/i386/kernel/apm.c b/arch/i386/kernel/apm.c --- a/arch/i386/kernel/apm.c 2004-08-25 22:01:54 -07:00 +++ b/arch/i386/kernel/apm.c 2004-08-25 22:01:54 -07:00 @@ -2271,10 +2271,12 @@ } if ((num_online_cpus() > 1) && !power_off && !smp) { printk(KERN_NOTICE "apm: disabled - APM is not SMP safe.\n"); + apm_info.disabled = 1; return -ENODEV; } if (PM_IS_ACTIVE()) { printk(KERN_NOTICE "apm: overridden by ACPI.\n"); + apm_info.disabled = 1; return -ENODEV; } pm_active = 1; diff -Nru a/arch/i386/kernel/cpu/common.c b/arch/i386/kernel/cpu/common.c --- a/arch/i386/kernel/cpu/common.c 2004-08-25 22:01:54 -07:00 +++ b/arch/i386/kernel/cpu/common.c 2004-08-25 22:01:54 -07:00 @@ -559,13 +559,11 @@ load_esp0(t, thread); set_tss_desc(cpu,t); - per_cpu(cpu_gdt_table,cpu)[GDT_ENTRY_TSS].b &= 0xfffffdff; load_TR_desc(); load_LDT(&init_mm.context); /* Set up doublefault TSS pointer in the GDT */ __set_tss_desc(cpu, GDT_ENTRY_DOUBLEFAULT_TSS, &doublefault_tss); - per_cpu(cpu_gdt_table, cpu)[GDT_ENTRY_DOUBLEFAULT_TSS].b &= 0xfffffdff; /* Clear %fs and %gs. */ asm volatile ("xorl %eax, %eax; movl %eax, %fs; movl %eax, %gs"); diff -Nru a/arch/i386/kernel/cpu/cpufreq/longhaul.c b/arch/i386/kernel/cpu/cpufreq/longhaul.c --- a/arch/i386/kernel/cpu/cpufreq/longhaul.c 2004-08-25 22:01:54 -07:00 +++ b/arch/i386/kernel/cpu/cpufreq/longhaul.c 2004-08-25 22:01:54 -07:00 @@ -38,6 +38,17 @@ #define PFX "longhaul: " +#define TYPE_LONGHAUL_V1 1 +#define TYPE_LONGHAUL_V2 2 +#define TYPE_POWERSAVER 3 + +#define CPU_SAMUEL 1 +#define CPU_SAMUEL2 2 +#define CPU_EZRA 3 +#define CPU_EZRA_T 4 +#define CPU_NEHEMIAH 5 + +static int cpu_model; static unsigned int numscales=16, numvscales; static unsigned int fsb; static int minvid, maxvid; @@ -73,9 +84,23 @@ static unsigned int highest_speed, lowest_speed; /* kHz */ static int longhaul_version; static struct cpufreq_frequency_table *longhaul_table; +static char speedbuffer[8]; + +static char *print_speed(int speed) +{ + if (speed > 1000) { + if (speed%1000 == 0) + sprintf (speedbuffer, "%dGHz", speed/1000); + else + sprintf (speedbuffer, "%d.%dGHz", speed/1000, (speed%1000)/100); + } else + sprintf (speedbuffer, "%dMHz", speed); + + return speedbuffer; +} -static unsigned int calc_speed(int mult, int fsb) +static unsigned int calc_speed(int mult) { int khz; khz = (mult/10)*fsb; @@ -92,7 +117,7 @@ rdmsr (MSR_IA32_EBL_CR_POWERON, lo, hi); invalue = (lo & (1<<22|1<<23|1<<24|1<<25)) >>22; - if (longhaul_version==2 || longhaul_version==3) { + if (longhaul_version==TYPE_LONGHAUL_V2 || longhaul_version==TYPE_POWERSAVER) { if (lo & (1<<27)) invalue+=16; } @@ -101,8 +126,21 @@ static void do_powersaver(union msr_longhaul *longhaul, - unsigned int clock_ratio_index, int version) + unsigned int clock_ratio_index) { + int version; + + switch (cpu_model) { + case CPU_EZRA_T: + version = 3; + break; + case CPU_NEHEMIAH: + version = 0xf; + break; + default: + return; + } + rdmsrl(MSR_VIA_LONGHAUL, longhaul->val); longhaul->bits.SoftBusRatio = clock_ratio_index & 0xf; longhaul->bits.SoftBusRatio4 = (clock_ratio_index & 0x10) >> 4; @@ -125,7 +163,7 @@ * longhaul_set_cpu_frequency() * @clock_ratio_index : bitpattern of the new multiplier. * - * Sets a new clock ratio, and -if applicable- a new Front Side Bus + * Sets a new clock ratio. */ static void longhaul_setstate(unsigned int clock_ratio_index) @@ -134,22 +172,28 @@ struct cpufreq_freqs freqs; union msr_longhaul longhaul; union msr_bcr2 bcr2; + static unsigned int old_ratio=-1; + + if (old_ratio == clock_ratio_index) + return; + old_ratio = clock_ratio_index; mult = clock_ratio[clock_ratio_index]; if (mult == -1) return; - speed = calc_speed (mult, fsb); + speed = calc_speed(mult); if ((speed > highest_speed) || (speed < lowest_speed)) return; - freqs.old = calc_speed (longhaul_get_cpu_mult(), fsb); + freqs.old = calc_speed(longhaul_get_cpu_mult()); freqs.new = speed; freqs.cpu = 0; /* longhaul.c is UP only driver */ cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); - dprintk (KERN_INFO PFX "FSB:%d Mult:%d.%dx\n", fsb, mult/10, mult%10); + dprintk (KERN_INFO PFX "Setting to FSB:%dMHz Mult:%d.%dx (%s)\n", + fsb, mult/10, mult%10, print_speed(speed/1000)); switch (longhaul_version) { @@ -160,7 +204,8 @@ * *NB* Until we get voltage scaling working v1 & v2 are the same code. * Longhaul v2 appears in Samuel2 Steppings 1->7 [C5b] and Ezra [C5C] */ - case 1: + case TYPE_LONGHAUL_V1: + case TYPE_LONGHAUL_V2: rdmsrl (MSR_VIA_BCR2, bcr2.val); /* Enable software clock multiplier */ bcr2.bits.ESOFTBF = 1; @@ -180,26 +225,18 @@ break; /* - * Longhaul v3 (aka Powersaver). (Ezra-T [C5M]) + * Longhaul v3 (aka Powersaver). (Ezra-T [C5M] & Nehemiah [C5N]) * We can scale voltage with this too, but that's currently * disabled until we come up with a decent 'match freq to voltage' * algorithm. * When we add voltage scaling, we will also need to do the * voltage/freq setting in order depending on the direction * of scaling (like we do in powernow-k7.c) - */ - case 2: - do_powersaver(&longhaul, clock_ratio_index, 3); - break; - - /* - * Powersaver. (Nehemiah [C5N]) - * As for Ezra-T, we don't do voltage yet. - * This can do FSB scaling too, but it has never been proven + * Nehemiah can do FSB scaling too, but this has never been proven * to work in practice. */ - case 3: - do_powersaver(&longhaul, clock_ratio_index, 0xf); + case TYPE_POWERSAVER: + do_powersaver(&longhaul, clock_ratio_index); break; } @@ -249,7 +286,6 @@ static int __init longhaul_get_ranges(void) { - struct cpuinfo_x86 *c = cpu_data; unsigned long invalue; unsigned int multipliers[32]= { 50,30,40,100,55,35,45,95,90,70,80,60,120,75,85,65, @@ -261,62 +297,66 @@ unsigned int eblcr_fsb_table_v2[] = { 133, 100, -1, 66 }; switch (longhaul_version) { - case 1: + case TYPE_LONGHAUL_V1: + case TYPE_LONGHAUL_V2: /* Ugh, Longhaul v1 didn't have the min/max MSRs. Assume min=3.0x & max = whatever we booted at. */ minmult = 30; maxmult = longhaul_get_cpu_mult(); rdmsr (MSR_IA32_EBL_CR_POWERON, lo, hi); invalue = (lo & (1<<18|1<<19)) >>18; - if (c->x86_model==6) + if (cpu_model==CPU_SAMUEL || cpu_model==CPU_SAMUEL2) fsb = eblcr_fsb_table_v1[invalue]; else fsb = guess_fsb(); break; - case 2: - rdmsrl (MSR_VIA_LONGHAUL, longhaul.val); - - invalue = longhaul.bits.MaxMHzBR; - if (longhaul.bits.MaxMHzBR4) - invalue += 16; - maxmult=multipliers[invalue]; - - invalue = longhaul.bits.MinMHzBR; - if (longhaul.bits.MinMHzBR4 == 1) - minmult = 30; - else - minmult = multipliers[invalue]; - - fsb = eblcr_fsb_table_v2[longhaul.bits.MaxMHzFSB]; - break; - - case 3: - rdmsrl (MSR_VIA_LONGHAUL, longhaul.val); - - /* - * TODO: This code works, but raises a lot of questions. - * - Some Nehemiah's seem to have broken Min/MaxMHzBR's. - * We get around this by using a hardcoded multiplier of 5.0x - * for the minimimum speed, and the speed we booted up at for the max. - * This is done in longhaul_get_cpu_mult() by reading the EBLCR register. - * - According to some VIA documentation EBLCR is only - * in pre-Nehemiah C3s. How this still works is a mystery. - * We're possibly using something undocumented and unsupported, - * But it works, so we don't grumble. - */ - minmult=50; - maxmult=longhaul_get_cpu_mult(); - - /* Starting with the 1.2GHz parts, theres a 200MHz bus. */ - if ((cpu_khz/1000) > 1200) - fsb = 200; - else + case TYPE_POWERSAVER: + /* Ezra-T */ + if (cpu_model==CPU_EZRA_T) { + rdmsrl (MSR_VIA_LONGHAUL, longhaul.val); + invalue = longhaul.bits.MaxMHzBR; + if (longhaul.bits.MaxMHzBR4) + invalue += 16; + maxmult=multipliers[invalue]; + + invalue = longhaul.bits.MinMHzBR; + if (longhaul.bits.MinMHzBR4 == 1) + minmult = 30; + else + minmult = multipliers[invalue]; fsb = eblcr_fsb_table_v2[longhaul.bits.MaxMHzFSB]; - break; + break; + } + + /* Nehemiah */ + if (cpu_model==CPU_NEHEMIAH) { + rdmsrl (MSR_VIA_LONGHAUL, longhaul.val); + + /* + * TODO: This code works, but raises a lot of questions. + * - Some Nehemiah's seem to have broken Min/MaxMHzBR's. + * We get around this by using a hardcoded multiplier of 4.0x + * for the minimimum speed, and the speed we booted up at for the max. + * This is done in longhaul_get_cpu_mult() by reading the EBLCR register. + * - According to some VIA documentation EBLCR is only + * in pre-Nehemiah C3s. How this still works is a mystery. + * We're possibly using something undocumented and unsupported, + * But it works, so we don't grumble. + */ + minmult=40; + maxmult=longhaul_get_cpu_mult(); + + /* Starting with the 1.2GHz parts, theres a 200MHz bus. */ + if ((cpu_khz/1000) > 1200) + fsb = 200; + else + fsb = eblcr_fsb_table_v2[longhaul.bits.MaxMHzFSB]; + break; + } } - dprintk (KERN_INFO PFX "MinMult=%d.%dx MaxMult=%d.%dx\n", + dprintk (KERN_INFO PFX "MinMult:%d.%dx MaxMult:%d.%dx\n", minmult/10, minmult%10, maxmult/10, maxmult%10); if (fsb == -1) { @@ -324,10 +364,11 @@ return -EINVAL; } - highest_speed = calc_speed (maxmult, fsb); - lowest_speed = calc_speed (minmult,fsb); - dprintk (KERN_INFO PFX "FSB: %dMHz Lowestspeed=%dMHz Highestspeed=%dMHz\n", - fsb, lowest_speed/1000, highest_speed/1000); + highest_speed = calc_speed(maxmult); + lowest_speed = calc_speed(minmult); + dprintk (KERN_INFO PFX "FSB:%dMHz ", fsb); + dprintk ("Lowest speed:%s ", print_speed(lowest_speed/1000)); + dprintk ("Highest speed:%s\n", print_speed(highest_speed/1000)); if (lowest_speed == highest_speed) { printk (KERN_INFO PFX "highestspeed == lowest, aborting.\n"); @@ -350,7 +391,7 @@ continue; if (ratio > maxmult || ratio < minmult) continue; - longhaul_table[k].frequency = calc_speed (ratio, fsb); + longhaul_table[k].frequency = calc_speed(ratio); longhaul_table[k].index = j; k++; } @@ -426,8 +467,7 @@ static int longhaul_target(struct cpufreq_policy *policy, - unsigned int target_freq, - unsigned int relation) + unsigned int target_freq, unsigned int relation) { unsigned int table_index = 0; unsigned int new_clock_ratio = 0; @@ -442,13 +482,15 @@ return 0; } + static unsigned int longhaul_get(unsigned int cpu) { if (cpu) return 0; - return (calc_speed (longhaul_get_cpu_mult(), fsb)); + return calc_speed(longhaul_get_cpu_mult()); } + static int __init longhaul_cpu_init(struct cpufreq_policy *policy) { struct cpuinfo_x86 *c = cpu_data; @@ -457,26 +499,31 @@ switch (c->x86_model) { case 6: + cpu_model = CPU_SAMUEL; cpuname = "C3 'Samuel' [C5A]"; - longhaul_version=1; + longhaul_version = TYPE_LONGHAUL_V1; memcpy (clock_ratio, samuel1_clock_ratio, sizeof(samuel1_clock_ratio)); memcpy (eblcr_table, samuel1_eblcr, sizeof(samuel1_eblcr)); break; - case 7: /* C5B / C5C */ - longhaul_version=1; + case 7: + longhaul_version = TYPE_LONGHAUL_V1; switch (c->x86_mask) { case 0: + cpu_model = CPU_SAMUEL2; cpuname = "C3 'Samuel 2' [C5B]"; /* Note, this is not a typo, early Samuel2's had Samuel1 ratios. */ memcpy (clock_ratio, samuel1_clock_ratio, sizeof(samuel1_clock_ratio)); memcpy (eblcr_table, samuel2_eblcr, sizeof(samuel2_eblcr)); break; case 1 ... 15: - if (c->x86_mask < 8) + if (c->x86_mask < 8) { + cpu_model = CPU_SAMUEL2; cpuname = "C3 'Samuel 2' [C5B]"; - else + } else { + cpu_model = CPU_EZRA; cpuname = "C3 'Ezra' [C5C]"; + } memcpy (clock_ratio, ezra_clock_ratio, sizeof(ezra_clock_ratio)); memcpy (eblcr_table, ezra_eblcr, sizeof(ezra_eblcr)); break; @@ -484,15 +531,17 @@ break; case 8: + cpu_model = CPU_EZRA_T; cpuname = "C3 'Ezra-T' [C5M]"; - longhaul_version=2; + longhaul_version = TYPE_POWERSAVER; numscales=32; memcpy (clock_ratio, ezrat_clock_ratio, sizeof(ezrat_clock_ratio)); memcpy (eblcr_table, ezrat_eblcr, sizeof(ezrat_eblcr)); break; case 9: - longhaul_version=3; + cpu_model = CPU_NEHEMIAH; + longhaul_version = TYPE_POWERSAVER; numscales=32; switch (c->x86_mask) { case 0 ... 1: @@ -518,19 +567,28 @@ break; } - printk (KERN_INFO PFX "VIA %s CPU detected. Longhaul v%d supported.\n", - cpuname, longhaul_version); + printk (KERN_INFO PFX "VIA %s CPU detected. ", cpuname); + switch (longhaul_version) { + case TYPE_LONGHAUL_V1: + case TYPE_LONGHAUL_V2: + printk ("Longhaul v%d supported.\n", longhaul_version); + break; + case TYPE_POWERSAVER: + printk ("Powersaver supported.\n"); + break; + }; ret = longhaul_get_ranges(); if (ret != 0) return ret; - if ((longhaul_version==2) && (dont_scale_voltage==0)) + if ((longhaul_version==TYPE_LONGHAUL_V2 || longhaul_version==TYPE_POWERSAVER) && + (dont_scale_voltage==0)) longhaul_setup_voltagescaling(); policy->governor = CPUFREQ_DEFAULT_GOVERNOR; policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; - policy->cur = calc_speed (longhaul_get_cpu_mult(), fsb); + policy->cur = calc_speed(longhaul_get_cpu_mult()); ret = cpufreq_frequency_table_cpuinfo(policy, longhaul_table); if (ret) @@ -563,6 +621,7 @@ .attr = longhaul_attr, }; + static int __init longhaul_init(void) { struct cpuinfo_x86 *c = cpu_data; @@ -580,16 +639,17 @@ return -ENODEV; } + static void __exit longhaul_exit(void) { int i=0; - unsigned int new_clock_ratio; - - while (clock_ratio[i] != maxmult) - i++; - new_clock_ratio = longhaul_table[i].index & 0xFF; - longhaul_setstate(new_clock_ratio); + for (i=0; i < numscales; i++) { + if (clock_ratio[i] == maxmult) { + longhaul_setstate(i); + break; + } + } cpufreq_unregister_driver(&longhaul_driver); kfree(longhaul_table); diff -Nru a/arch/i386/kernel/cpu/intel.c b/arch/i386/kernel/cpu/intel.c --- a/arch/i386/kernel/cpu/intel.c 2004-08-25 22:01:54 -07:00 +++ b/arch/i386/kernel/cpu/intel.c 2004-08-25 22:01:54 -07:00 @@ -72,44 +72,44 @@ /* all the cache descriptor types we care about (no TLB or trace cache entries) */ static struct _cache_table cache_table[] __initdata = { - { 0x06, LVL_1_INST, 8 }, - { 0x08, LVL_1_INST, 16 }, - { 0x0a, LVL_1_DATA, 8 }, - { 0x0c, LVL_1_DATA, 16 }, - { 0x22, LVL_3, 512 }, - { 0x23, LVL_3, 1024 }, - { 0x25, LVL_3, 2048 }, - { 0x29, LVL_3, 4096 }, - { 0x2c, LVL_1_DATA, 32 }, - { 0x30, LVL_1_INST, 32 }, - { 0x39, LVL_2, 128 }, - { 0x3b, LVL_2, 128 }, - { 0x3c, LVL_2, 256 }, - { 0x41, LVL_2, 128 }, - { 0x42, LVL_2, 256 }, - { 0x43, LVL_2, 512 }, - { 0x44, LVL_2, 1024 }, - { 0x45, LVL_2, 2048 }, - { 0x60, LVL_1_DATA, 16 }, - { 0x66, LVL_1_DATA, 8 }, - { 0x67, LVL_1_DATA, 16 }, - { 0x68, LVL_1_DATA, 32 }, - { 0x70, LVL_TRACE, 12 }, - { 0x71, LVL_TRACE, 16 }, - { 0x72, LVL_TRACE, 32 }, - { 0x78, LVL_2, 1024 }, - { 0x79, LVL_2, 128 }, - { 0x7a, LVL_2, 256 }, - { 0x7b, LVL_2, 512 }, - { 0x7c, LVL_2, 1024 }, - { 0x7d, LVL_2, 2048 }, - { 0x7f, LVL_2, 512 }, - { 0x82, LVL_2, 256 }, - { 0x83, LVL_2, 512 }, - { 0x84, LVL_2, 1024 }, - { 0x85, LVL_2, 2048 }, - { 0x86, LVL_2, 512 }, - { 0x87, LVL_2, 1024 }, + { 0x06, LVL_1_INST, 8 }, /* 4-way set assoc, 32 byte line size */ + { 0x08, LVL_1_INST, 16 }, /* 4-way set assoc, 32 byte line size */ + { 0x0a, LVL_1_DATA, 8 }, /* 2 way set assoc, 32 byte line size */ + { 0x0c, LVL_1_DATA, 16 }, /* 4-way set assoc, 32 byte line size */ + { 0x22, LVL_3, 512 }, /* 4-way set assoc, sectored cache, 64 byte line size */ + { 0x23, LVL_3, 1024 }, /* 8-way set assoc, sectored cache, 64 byte line size */ + { 0x25, LVL_3, 2048 }, /* 8-way set assoc, sectored cache, 64 byte line size */ + { 0x29, LVL_3, 4096 }, /* 8-way set assoc, sectored cache, 64 byte line size */ + { 0x2c, LVL_1_DATA, 32 }, /* 8-way set assoc, 64 byte line size */ + { 0x30, LVL_1_INST, 32 }, /* 8-way set assoc, 64 byte line size */ + { 0x39, LVL_2, 128 }, /* 4-way set assoc, sectored cache, 64 byte line size */ + { 0x3b, LVL_2, 128 }, /* 2-way set assoc, sectored cache, 64 byte line size */ + { 0x3c, LVL_2, 256 }, /* 4-way set assoc, sectored cache, 64 byte line size */ + { 0x41, LVL_2, 128 }, /* 4-way set assoc, 32 byte line size */ + { 0x42, LVL_2, 256 }, /* 4-way set assoc, 32 byte line size */ + { 0x43, LVL_2, 512 }, /* 4-way set assoc, 32 byte line size */ + { 0x44, LVL_2, 1024 }, /* 4-way set assoc, 32 byte line size */ + { 0x45, LVL_2, 2048 }, /* 4-way set assoc, 32 byte line size */ + { 0x60, LVL_1_DATA, 16 }, /* 8-way set assoc, sectored cache, 64 byte line size */ + { 0x66, LVL_1_DATA, 8 }, /* 4-way set assoc, sectored cache, 64 byte line size */ + { 0x67, LVL_1_DATA, 16 }, /* 4-way set assoc, sectored cache, 64 byte line size */ + { 0x68, LVL_1_DATA, 32 }, /* 4-way set assoc, sectored cache, 64 byte line size */ + { 0x70, LVL_TRACE, 12 }, /* 8-way set assoc */ + { 0x71, LVL_TRACE, 16 }, /* 8-way set assoc */ + { 0x72, LVL_TRACE, 32 }, /* 8-way set assoc */ + { 0x78, LVL_2, 1024 }, /* 4-way set assoc, 64 byte line size */ + { 0x79, LVL_2, 128 }, /* 8-way set assoc, sectored cache, 64 byte line size */ + { 0x7a, LVL_2, 256 }, /* 8-way set assoc, sectored cache, 64 byte line size */ + { 0x7b, LVL_2, 512 }, /* 8-way set assoc, sectored cache, 64 byte line size */ + { 0x7c, LVL_2, 1024 }, /* 8-way set assoc, sectored cache, 64 byte line size */ + { 0x7d, LVL_2, 2048 }, /* 8-way set assoc, 64 byte line size */ + { 0x7f, LVL_2, 512 }, /* 2-way set assoc, 64 byte line size */ + { 0x82, LVL_2, 256 }, /* 8-way set assoc, 32 byte line size */ + { 0x83, LVL_2, 512 }, /* 8-way set assoc, 32 byte line size */ + { 0x84, LVL_2, 1024 }, /* 8-way set assoc, 32 byte line size */ + { 0x85, LVL_2, 2048 }, /* 8-way set assoc, 32 byte line size */ + { 0x86, LVL_2, 512 }, /* 4-way set assoc, 64 byte line size */ + { 0x87, LVL_2, 1024 }, /* 8-way set assoc, 64 byte line size */ { 0x00, 0, 0} }; diff -Nru a/arch/i386/kernel/cpu/proc.c b/arch/i386/kernel/cpu/proc.c --- a/arch/i386/kernel/cpu/proc.c 2004-08-25 22:01:56 -07:00 +++ b/arch/i386/kernel/cpu/proc.c 2004-08-25 22:01:56 -07:00 @@ -44,8 +44,8 @@ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* Intel-defined (#2) */ - "pni", NULL, NULL, "monitor", "ds_cpl", NULL, NULL, "tm2", - "est", NULL, "cid", NULL, NULL, NULL, NULL, NULL, + "pni", NULL, NULL, "monitor", "ds_cpl", NULL, NULL, "est", + "tm2", NULL, "cid", NULL, NULL, NULL, "xtpr", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, diff -Nru a/arch/i386/kernel/doublefault.c b/arch/i386/kernel/doublefault.c --- a/arch/i386/kernel/doublefault.c 2004-08-25 22:01:54 -07:00 +++ b/arch/i386/kernel/doublefault.c 2004-08-25 22:01:54 -07:00 @@ -13,7 +13,7 @@ static unsigned long doublefault_stack[DOUBLEFAULT_STACKSIZE]; #define STACK_START (unsigned long)(doublefault_stack+DOUBLEFAULT_STACKSIZE) -#define ptr_ok(x) ((x) > 0xc0000000 && (x) < 0xc1000000) +#define ptr_ok(x) ((x) > PAGE_OFFSET && (x) < PAGE_OFFSET + 0x1000000) static void doublefault_fn(void) { diff -Nru a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c --- a/arch/i386/kernel/io_apic.c 2004-08-25 22:01:55 -07:00 +++ b/arch/i386/kernel/io_apic.c 2004-08-25 22:01:55 -07:00 @@ -1739,7 +1739,7 @@ reg_00.raw = io_apic_read(apic, 0); spin_unlock_irqrestore(&ioapic_lock, flags); if (reg_00.bits.ID != mp_ioapics[apic].mpc_apicid) - panic("could not set ID!\n"); + printk("could not set ID!\n"); else apic_printk(APIC_VERBOSE, " ok.\n"); } diff -Nru a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c --- a/arch/i386/kernel/process.c 2004-08-25 22:01:54 -07:00 +++ b/arch/i386/kernel/process.c 2004-08-25 22:01:54 -07:00 @@ -183,18 +183,13 @@ printk("monitor/mwait feature present.\n"); /* * Skip, if setup has overridden idle. - * Also, take care of system with asymmetric CPUs. - * Use, mwait_idle only if all cpus support it. - * If not, we fallback to default_idle() + * One CPU supports mwait => All CPUs supports mwait */ if (!pm_idle) { printk("using mwait in idle threads.\n"); pm_idle = mwait_idle; } - return; } - pm_idle = default_idle; - return; } static int __init idle_setup (char *str) @@ -595,7 +590,7 @@ child_tidptr = (int __user *)regs.edi; if (!newsp) newsp = regs.esp; - return do_fork(clone_flags & ~CLONE_IDLETASK, newsp, ®s, 0, parent_tidptr, child_tidptr); + return do_fork(clone_flags, newsp, ®s, 0, parent_tidptr, child_tidptr); } /* diff -Nru a/arch/i386/kernel/signal.c b/arch/i386/kernel/signal.c --- a/arch/i386/kernel/signal.c 2004-08-25 22:01:55 -07:00 +++ b/arch/i386/kernel/signal.c 2004-08-25 22:01:55 -07:00 @@ -411,9 +411,7 @@ return; give_sigsegv: - if (sig == SIGSEGV) - ka->sa.sa_handler = SIG_DFL; - force_sig(SIGSEGV, current); + force_sigsegv(sig, current); } static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, @@ -492,9 +490,7 @@ return; give_sigsegv: - if (sig == SIGSEGV) - ka->sa.sa_handler = SIG_DFL; - force_sig(SIGSEGV, current); + force_sigsegv(sig, current); } /* @@ -502,11 +498,9 @@ */ static void -handle_signal(unsigned long sig, siginfo_t *info, sigset_t *oldset, - struct pt_regs * regs) +handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, + sigset_t *oldset, struct pt_regs * regs) { - struct k_sigaction *ka = ¤t->sighand->action[sig-1]; - /* Are we from a system call? */ if (regs->orig_eax >= 0) { /* If so, check system call restarting.. */ @@ -534,9 +528,6 @@ else setup_frame(sig, ka, oldset, regs); - if (ka->sa.sa_flags & SA_ONESHOT) - ka->sa.sa_handler = SIG_DFL; - if (!(ka->sa.sa_flags & SA_NODEFER)) { spin_lock_irq(¤t->sighand->siglock); sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); @@ -555,6 +546,7 @@ { siginfo_t info; int signr; + struct k_sigaction ka; /* * We want the common case to go fast, which @@ -573,7 +565,7 @@ if (!oldset) oldset = ¤t->blocked; - signr = get_signal_to_deliver(&info, regs, NULL); + signr = get_signal_to_deliver(&info, &ka, regs, NULL); if (signr > 0) { /* Reenable any watchpoints before delivering the * signal to user space. The processor register will @@ -583,7 +575,7 @@ __asm__("movl %0,%%db7" : : "r" (current->thread.debugreg[7])); /* Whee! Actually deliver the signal. */ - handle_signal(signr, &info, oldset, regs); + handle_signal(signr, &info, &ka, oldset, regs); return 1; } diff -Nru a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c --- a/arch/i386/kernel/smpboot.c 2004-08-25 22:01:55 -07:00 +++ b/arch/i386/kernel/smpboot.c 2004-08-25 22:01:55 -07:00 @@ -496,16 +496,6 @@ unsigned short ss; } stack_start; -static struct task_struct * __init fork_by_hand(void) -{ - struct pt_regs regs; - /* - * don't care about the eip and regs settings since - * we'll never reschedule the forked task. - */ - return copy_process(CLONE_VM|CLONE_IDLETASK, 0, ®s, 0, NULL, NULL); -} - #ifdef CONFIG_NUMA /* which logical CPUs are on which nodes */ @@ -801,21 +791,10 @@ * We can't use kernel_thread since we must avoid to * reschedule the child. */ - idle = fork_by_hand(); + idle = fork_idle(cpu); if (IS_ERR(idle)) panic("failed fork for CPU %d", cpu); - wake_up_forked_process(idle); - - /* - * We remove it from the pidhash and the runqueue - * once we got the process: - */ - init_idle(idle, cpu); - idle->thread.eip = (unsigned long) start_secondary; - - unhash_process(idle); - /* start_eip had better be page-aligned! */ start_eip = setup_trampoline(); @@ -1137,213 +1116,6 @@ if (cpu_has_tsc && cpucount && cpu_khz) synchronize_tsc_bp(); } - -#ifdef CONFIG_SCHED_SMT -#ifdef CONFIG_NUMA -static struct sched_group sched_group_cpus[NR_CPUS]; -static struct sched_group sched_group_phys[NR_CPUS]; -static struct sched_group sched_group_nodes[MAX_NUMNODES]; -static DEFINE_PER_CPU(struct sched_domain, cpu_domains); -static DEFINE_PER_CPU(struct sched_domain, phys_domains); -static DEFINE_PER_CPU(struct sched_domain, node_domains); -__init void arch_init_sched_domains(void) -{ - int i; - struct sched_group *first = NULL, *last = NULL; - - /* Set up domains */ - for_each_cpu(i) { - struct sched_domain *cpu_domain = &per_cpu(cpu_domains, i); - struct sched_domain *phys_domain = &per_cpu(phys_domains, i); - struct sched_domain *node_domain = &per_cpu(node_domains, i); - int node = cpu_to_node(i); - cpumask_t nodemask = node_to_cpumask(node); - - *cpu_domain = SD_SIBLING_INIT; - cpu_domain->span = cpu_sibling_map[i]; - cpu_domain->parent = phys_domain; - cpu_domain->groups = &sched_group_cpus[i]; - - *phys_domain = SD_CPU_INIT; - phys_domain->span = nodemask; - phys_domain->parent = node_domain; - phys_domain->groups = &sched_group_phys[first_cpu(cpu_domain->span)]; - - *node_domain = SD_NODE_INIT; - node_domain->span = cpu_possible_map; - node_domain->groups = &sched_group_nodes[cpu_to_node(i)]; - } - - /* Set up CPU (sibling) groups */ - for_each_cpu(i) { - struct sched_domain *cpu_domain = &per_cpu(cpu_domains, i); - int j; - first = last = NULL; - - if (i != first_cpu(cpu_domain->span)) - continue; - - for_each_cpu_mask(j, cpu_domain->span) { - struct sched_group *cpu = &sched_group_cpus[j]; - - cpu->cpumask = CPU_MASK_NONE; - cpu_set(j, cpu->cpumask); - cpu->cpu_power = SCHED_LOAD_SCALE; - - if (!first) - first = cpu; - if (last) - last->next = cpu; - last = cpu; - } - last->next = first; - } - - for (i = 0; i < MAX_NUMNODES; i++) { - int j; - cpumask_t nodemask; - struct sched_group *node = &sched_group_nodes[i]; - cpumask_t node_cpumask = node_to_cpumask(i); - - cpus_and(nodemask, node_cpumask, cpu_possible_map); - - if (cpus_empty(nodemask)) - continue; - - first = last = NULL; - /* Set up physical groups */ - for_each_cpu_mask(j, nodemask) { - struct sched_domain *cpu_domain = &per_cpu(cpu_domains, j); - struct sched_group *cpu = &sched_group_phys[j]; - - if (j != first_cpu(cpu_domain->span)) - continue; - - cpu->cpumask = cpu_domain->span; - /* - * Make each extra sibling increase power by 10% of - * the basic CPU. This is very arbitrary. - */ - cpu->cpu_power = SCHED_LOAD_SCALE + SCHED_LOAD_SCALE*(cpus_weight(cpu->cpumask)-1) / 10; - node->cpu_power += cpu->cpu_power; - - if (!first) - first = cpu; - if (last) - last->next = cpu; - last = cpu; - } - last->next = first; - } - - /* Set up nodes */ - first = last = NULL; - for (i = 0; i < MAX_NUMNODES; i++) { - struct sched_group *cpu = &sched_group_nodes[i]; - cpumask_t nodemask; - cpumask_t node_cpumask = node_to_cpumask(i); - - cpus_and(nodemask, node_cpumask, cpu_possible_map); - - if (cpus_empty(nodemask)) - continue; - - cpu->cpumask = nodemask; - /* ->cpu_power already setup */ - - if (!first) - first = cpu; - if (last) - last->next = cpu; - last = cpu; - } - last->next = first; - - mb(); - for_each_cpu(i) { - struct sched_domain *cpu_domain = &per_cpu(cpu_domains, i); - cpu_attach_domain(cpu_domain, i); - } -} -#else /* !CONFIG_NUMA */ -static struct sched_group sched_group_cpus[NR_CPUS]; -static struct sched_group sched_group_phys[NR_CPUS]; -static DEFINE_PER_CPU(struct sched_domain, cpu_domains); -static DEFINE_PER_CPU(struct sched_domain, phys_domains); -__init void arch_init_sched_domains(void) -{ - int i; - struct sched_group *first = NULL, *last = NULL; - - /* Set up domains */ - for_each_cpu(i) { - struct sched_domain *cpu_domain = &per_cpu(cpu_domains, i); - struct sched_domain *phys_domain = &per_cpu(phys_domains, i); - - *cpu_domain = SD_SIBLING_INIT; - cpu_domain->span = cpu_sibling_map[i]; - cpu_domain->parent = phys_domain; - cpu_domain->groups = &sched_group_cpus[i]; - - *phys_domain = SD_CPU_INIT; - phys_domain->span = cpu_possible_map; - phys_domain->groups = &sched_group_phys[first_cpu(cpu_domain->span)]; - } - - /* Set up CPU (sibling) groups */ - for_each_cpu(i) { - struct sched_domain *cpu_domain = &per_cpu(cpu_domains, i); - int j; - first = last = NULL; - - if (i != first_cpu(cpu_domain->span)) - continue; - - for_each_cpu_mask(j, cpu_domain->span) { - struct sched_group *cpu = &sched_group_cpus[j]; - - cpus_clear(cpu->cpumask); - cpu_set(j, cpu->cpumask); - cpu->cpu_power = SCHED_LOAD_SCALE; - - if (!first) - first = cpu; - if (last) - last->next = cpu; - last = cpu; - } - last->next = first; - } - - first = last = NULL; - /* Set up physical groups */ - for_each_cpu(i) { - struct sched_domain *cpu_domain = &per_cpu(cpu_domains, i); - struct sched_group *cpu = &sched_group_phys[i]; - - if (i != first_cpu(cpu_domain->span)) - continue; - - cpu->cpumask = cpu_domain->span; - /* See SMT+NUMA setup for comment */ - cpu->cpu_power = SCHED_LOAD_SCALE + SCHED_LOAD_SCALE*(cpus_weight(cpu->cpumask)-1) / 10; - - if (!first) - first = cpu; - if (last) - last->next = cpu; - last = cpu; - } - last->next = first; - - mb(); - for_each_cpu(i) { - struct sched_domain *cpu_domain = &per_cpu(cpu_domains, i); - cpu_attach_domain(cpu_domain, i); - } -} -#endif /* CONFIG_NUMA */ -#endif /* CONFIG_SCHED_SMT */ /* These are wrappers to interface to the new boot process. Someone who understands all this stuff should rewrite it properly. --RR 15/Jul/02 */ diff -Nru a/arch/i386/kernel/vmlinux.lds.S b/arch/i386/kernel/vmlinux.lds.S --- a/arch/i386/kernel/vmlinux.lds.S 2004-08-25 22:01:54 -07:00 +++ b/arch/i386/kernel/vmlinux.lds.S 2004-08-25 22:01:54 -07:00 @@ -4,6 +4,7 @@ #include #include +#include OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386") OUTPUT_ARCH(i386) @@ -11,7 +12,7 @@ jiffies = jiffies_64; SECTIONS { - . = 0xC0000000 + 0x100000; + . = __PAGE_OFFSET + 0x100000; /* read-only */ _text = .; /* Text and read-only data */ .text : { @@ -66,9 +67,6 @@ __setup_start = .; .init.setup : { *(.init.setup) } __setup_end = .; - __start___param = .; - __param : { *(__param) } - __stop___param = .; __initcall_start = .; .initcall.init : { *(.initcall1.init) diff -Nru a/arch/i386/kernel/vsyscall.lds b/arch/i386/kernel/vsyscall.lds --- a/arch/i386/kernel/vsyscall.lds 2004-08-25 22:01:55 -07:00 +++ /dev/null Wed Dec 31 16:00:00 196900 @@ -1,67 +0,0 @@ -/* - * Linker script for vsyscall DSO. The vsyscall page is an ELF shared - * object prelinked to its virtual address, and with only one read-only - * segment (that fits in one page). This script controls its layout. - */ - -/* This must match . */ -VSYSCALL_BASE = 0xffffe000; - -SECTIONS -{ - . = VSYSCALL_BASE + SIZEOF_HEADERS; - - .hash : { *(.hash) } :text - .dynsym : { *(.dynsym) } - .dynstr : { *(.dynstr) } - .gnu.version : { *(.gnu.version) } - .gnu.version_d : { *(.gnu.version_d) } - .gnu.version_r : { *(.gnu.version_r) } - - /* This linker script is used both with -r and with -shared. - For the layouts to match, we need to skip more than enough - space for the dynamic symbol table et al. If this amount - is insufficient, ld -shared will barf. Just increase it here. */ - . = VSYSCALL_BASE + 0x400; - - .text : { *(.text) } :text =0x90909090 - - .eh_frame_hdr : { *(.eh_frame_hdr) } :text :eh_frame_hdr - .eh_frame : { KEEP (*(.eh_frame)) } :text - .dynamic : { *(.dynamic) } :text :dynamic - .useless : { - *(.got.plt) *(.got) - *(.data .data.* .gnu.linkonce.d.*) - *(.dynbss) - *(.bss .bss.* .gnu.linkonce.b.*) - } :text -} - -/* - * We must supply the ELF program headers explicitly to get just one - * PT_LOAD segment, and set the flags explicitly to make segments read-only. - */ -PHDRS -{ - text PT_LOAD FILEHDR PHDRS FLAGS(5); /* PF_R|PF_X */ - dynamic PT_DYNAMIC FLAGS(4); /* PF_R */ - eh_frame_hdr 0x6474e550; /* PT_GNU_EH_FRAME, but ld doesn't match the name */ -} - -/* - * This controls what symbols we export from the DSO. - */ -VERSION -{ - LINUX_2.5 { - global: - __kernel_vsyscall; - __kernel_sigreturn; - __kernel_rt_sigreturn; - - local: *; - }; -} - -/* The ELF entry point can be used to set the AT_SYSINFO value. */ -ENTRY(__kernel_vsyscall); diff -Nru a/arch/i386/kernel/vsyscall.lds.S b/arch/i386/kernel/vsyscall.lds.S --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/arch/i386/kernel/vsyscall.lds.S 2004-08-25 22:01:55 -07:00 @@ -0,0 +1,67 @@ +/* + * Linker script for vsyscall DSO. The vsyscall page is an ELF shared + * object prelinked to its virtual address, and with only one read-only + * segment (that fits in one page). This script controls its layout. + */ +#include + +VSYSCALL_BASE = __FIXADDR_TOP - 0x1000; + +SECTIONS +{ + . = VSYSCALL_BASE + SIZEOF_HEADERS; + + .hash : { *(.hash) } :text + .dynsym : { *(.dynsym) } + .dynstr : { *(.dynstr) } + .gnu.version : { *(.gnu.version) } + .gnu.version_d : { *(.gnu.version_d) } + .gnu.version_r : { *(.gnu.version_r) } + + /* This linker script is used both with -r and with -shared. + For the layouts to match, we need to skip more than enough + space for the dynamic symbol table et al. If this amount + is insufficient, ld -shared will barf. Just increase it here. */ + . = VSYSCALL_BASE + 0x400; + + .text : { *(.text) } :text =0x90909090 + + .eh_frame_hdr : { *(.eh_frame_hdr) } :text :eh_frame_hdr + .eh_frame : { KEEP (*(.eh_frame)) } :text + .dynamic : { *(.dynamic) } :text :dynamic + .useless : { + *(.got.plt) *(.got) + *(.data .data.* .gnu.linkonce.d.*) + *(.dynbss) + *(.bss .bss.* .gnu.linkonce.b.*) + } :text +} + +/* + * We must supply the ELF program headers explicitly to get just one + * PT_LOAD segment, and set the flags explicitly to make segments read-only. + */ +PHDRS +{ + text PT_LOAD FILEHDR PHDRS FLAGS(5); /* PF_R|PF_X */ + dynamic PT_DYNAMIC FLAGS(4); /* PF_R */ + eh_frame_hdr 0x6474e550; /* PT_GNU_EH_FRAME, but ld doesn't match the name */ +} + +/* + * This controls what symbols we export from the DSO. + */ +VERSION +{ + LINUX_2.5 { + global: + __kernel_vsyscall; + __kernel_sigreturn; + __kernel_rt_sigreturn; + + local: *; + }; +} + +/* The ELF entry point can be used to set the AT_SYSINFO value. */ +ENTRY(__kernel_vsyscall); diff -Nru a/arch/i386/mach-es7000/es7000.h b/arch/i386/mach-es7000/es7000.h --- a/arch/i386/mach-es7000/es7000.h 2004-08-25 22:01:54 -07:00 +++ b/arch/i386/mach-es7000/es7000.h 2004-08-25 22:01:54 -07:00 @@ -29,7 +29,7 @@ #define MIP_BUSY 1 #define MIP_SPIN 0xf0000 -#define MIP_VALID 0x0100000000000000 +#define MIP_VALID 0x0100000000000000ULL #define MIP_PORT(VALUE) ((VALUE >> 32) & 0xffff) #define MIP_RD_LO(VALUE) (VALUE & 0xffffffff) diff -Nru a/arch/i386/mach-es7000/es7000plat.c b/arch/i386/mach-es7000/es7000plat.c --- a/arch/i386/mach-es7000/es7000plat.c 2004-08-25 22:01:56 -07:00 +++ b/arch/i386/mach-es7000/es7000plat.c 2004-08-25 22:01:56 -07:00 @@ -237,7 +237,7 @@ } status = ((unsigned long long)mip_reg->off_0 & - (unsigned long long)0xffff0000000000) >> 48; + (unsigned long long)0xffff0000000000ULL) >> 48; mip_reg->off_38 = ((unsigned long long)mip_reg->off_38 & (unsigned long long)~MIP_VALID); return status; diff -Nru a/arch/i386/mach-generic/bigsmp.c b/arch/i386/mach-generic/bigsmp.c --- a/arch/i386/mach-generic/bigsmp.c 2004-08-25 22:01:54 -07:00 +++ b/arch/i386/mach-generic/bigsmp.c 2004-08-25 22:01:54 -07:00 @@ -13,15 +13,41 @@ #include #include #include +#include #include #include #include #include -int dmi_bigsmp; /* can be set by dmi scanners */ +static int dmi_bigsmp; /* can be set by dmi scanners */ + +static __init int hp_ht_bigsmp(struct dmi_system_id *d) +{ +#ifdef CONFIG_X86_GENERICARCH + printk(KERN_NOTICE "%s detected: force use of apic=bigsmp\n", d->ident); + dmi_bigsmp = 1; +#endif + return 0; +} + + +static struct dmi_system_id __initdata bigsmp_dmi_table[] = { + { hp_ht_bigsmp, "HP ProLiant DL760 G2", { + DMI_MATCH(DMI_BIOS_VENDOR, "HP"), + DMI_MATCH(DMI_BIOS_VERSION, "P44-"), + }}, + + { hp_ht_bigsmp, "HP ProLiant DL740", { + DMI_MATCH(DMI_BIOS_VENDOR, "HP"), + DMI_MATCH(DMI_BIOS_VERSION, "P47-"), + }}, + { } +}; + static __init int probe_bigsmp(void) { + dmi_check_system(bigsmp_dmi_table); return dmi_bigsmp; } diff -Nru a/arch/i386/mach-voyager/voyager_smp.c b/arch/i386/mach-voyager/voyager_smp.c --- a/arch/i386/mach-voyager/voyager_smp.c 2004-08-25 22:01:55 -07:00 +++ b/arch/i386/mach-voyager/voyager_smp.c 2004-08-25 22:01:55 -07:00 @@ -523,15 +523,6 @@ return cpu_idle(); } -static struct task_struct * __init -fork_by_hand(void) -{ - struct pt_regs regs; - /* don't care about the eip and regs settings since we'll - * never reschedule the forked task. */ - return copy_process(CLONE_VM|CLONE_IDLETASK, 0, ®s, 0, NULL, NULL); -} - /* Routine to kick start the given CPU and wait for it to report ready * (or timeout in startup). When this routine returns, the requested @@ -587,16 +578,10 @@ hijack_source.idt.Segment = (start_phys_address >> 4) & 0xFFFF; cpucount++; - idle = fork_by_hand(); + idle = fork_idle(cpu); if(IS_ERR(idle)) panic("failed fork for CPU%d", cpu); - - wake_up_forked_process(idle); - - init_idle(idle, cpu); - idle->thread.eip = (unsigned long) start_secondary; - unhash_process(idle); /* init_tasks (in sched.c) is indexed logically */ stack_start.esp = (void *) idle->thread.esp; diff -Nru a/arch/i386/mm/Makefile b/arch/i386/mm/Makefile --- a/arch/i386/mm/Makefile 2004-08-25 22:01:54 -07:00 +++ b/arch/i386/mm/Makefile 2004-08-25 22:01:54 -07:00 @@ -2,7 +2,7 @@ # Makefile for the linux i386-specific parts of the memory manager. # -obj-y := init.o pgtable.o fault.o ioremap.o extable.o pageattr.o +obj-y := init.o pgtable.o fault.o ioremap.o extable.o pageattr.o mmap.o obj-$(CONFIG_DISCONTIGMEM) += discontig.o obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o diff -Nru a/arch/i386/mm/discontig.c b/arch/i386/mm/discontig.c --- a/arch/i386/mm/discontig.c 2004-08-25 22:01:55 -07:00 +++ b/arch/i386/mm/discontig.c 2004-08-25 22:01:55 -07:00 @@ -417,15 +417,15 @@ * remapped KVA area - mbligh */ if (!nid) - free_area_init_node(nid, NODE_DATA(nid), 0, - zones_size, start, zholes_size); + free_area_init_node(nid, NODE_DATA(nid), + zones_size, start, zholes_size); else { unsigned long lmem_map; lmem_map = (unsigned long)node_remap_start_vaddr[nid]; lmem_map += sizeof(pg_data_t) + PAGE_SIZE - 1; lmem_map &= PAGE_MASK; - free_area_init_node(nid, NODE_DATA(nid), - (struct page *)lmem_map, zones_size, + NODE_DATA(nid)->node_mem_map = (struct page *)lmem_map; + free_area_init_node(nid, NODE_DATA(nid), zones_size, start, zholes_size); } } diff -Nru a/arch/i386/mm/mmap.c b/arch/i386/mm/mmap.c --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/arch/i386/mm/mmap.c 2004-08-25 22:01:56 -07:00 @@ -0,0 +1,71 @@ +/* + * linux/arch/i386/mm/mmap.c + * + * flexible mmap layout support + * + * Copyright 2003-2004 Red Hat Inc., Durham, North Carolina. + * All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * + * Started by Ingo Molnar + */ + +#include +#include + +/* + * Top of mmap area (just below the process stack). + * + * Leave an at least ~128 MB hole. + */ +#define MIN_GAP (128*1024*1024) +#define MAX_GAP (TASK_SIZE/6*5) + +static inline unsigned long mmap_base(struct mm_struct *mm) +{ + unsigned long gap = current->rlim[RLIMIT_STACK].rlim_cur; + + if (gap < MIN_GAP) + gap = MIN_GAP; + else if (gap > MAX_GAP) + gap = MAX_GAP; + + return TASK_SIZE - (gap & PAGE_MASK); +} + +/* + * This function, called very early during the creation of a new + * process VM image, sets up which VM layout function to use: + */ +void arch_pick_mmap_layout(struct mm_struct *mm) +{ + /* + * Fall back to the standard layout if the personality + * bit is set, or if the expected stack growth is unlimited: + */ + if (sysctl_legacy_va_layout || + (current->personality & ADDR_COMPAT_LAYOUT) || + current->rlim[RLIMIT_STACK].rlim_cur == RLIM_INFINITY) { + mm->mmap_base = TASK_UNMAPPED_BASE; + mm->get_unmapped_area = arch_get_unmapped_area; + mm->unmap_area = arch_unmap_area; + } else { + mm->mmap_base = mmap_base(mm); + mm->get_unmapped_area = arch_get_unmapped_area_topdown; + mm->unmap_area = arch_unmap_area_topdown; + } +} diff -Nru a/arch/i386/pci/i386.c b/arch/i386/pci/i386.c --- a/arch/i386/pci/i386.c 2004-08-25 22:01:54 -07:00 +++ b/arch/i386/pci/i386.c 2004-08-25 22:01:54 -07:00 @@ -142,7 +142,7 @@ DBG("PCI: Resource %08lx-%08lx (f=%lx, d=%d, p=%d)\n", r->start, r->end, r->flags, disabled, pass); pr = pci_find_parent_resource(dev, r); - if (!pr || request_resource(pr, r) < 0) { + if (!pr || insert_resource(pr, r) < 0) { printk(KERN_ERR "PCI: Cannot allocate resource region %d of device %s\n", idx, pci_name(dev)); /* We'll assign a new address later */ r->end -= r->start; diff -Nru a/arch/ia64/hp/sim/simserial.c b/arch/ia64/hp/sim/simserial.c --- a/arch/ia64/hp/sim/simserial.c 2004-08-25 22:01:55 -07:00 +++ b/arch/ia64/hp/sim/simserial.c 2004-08-25 22:01:55 -07:00 @@ -1055,7 +1055,7 @@ ia64_ssc_connect_irq(KEYBOARD_INTR, state->irq); } - printk(KERN_INFO "ttyS%02d at 0x%04lx (irq = %d) is a %s\n", + printk(KERN_INFO "ttyS%d at 0x%04lx (irq = %d) is a %s\n", state->line, state->port, state->irq, uart_config[state->type].name); diff -Nru a/arch/ia64/ia32/ia32_entry.S b/arch/ia64/ia32/ia32_entry.S --- a/arch/ia64/ia32/ia32_entry.S 2004-08-25 22:01:55 -07:00 +++ b/arch/ia64/ia32/ia32_entry.S 2004-08-25 22:01:55 -07:00 @@ -41,7 +41,7 @@ zxt4 out1=in1 // newsp mov out3=16 // stacksize (compensates for 16-byte scratch area) adds out2=IA64_SWITCH_STACK_SIZE+16,sp // out2 = ®s - dep out0=0,in0,CLONE_IDLETASK_BIT,1 // out0 = clone_flags & ~CLONE_IDLETASK + mov out0=in0 // out0 = clone_flags zxt4 out4=in2 // out4 = parent_tidptr zxt4 out5=in4 // out5 = child_tidptr br.call.sptk.many rp=do_fork diff -Nru a/arch/ia64/ia32/ia32_signal.c b/arch/ia64/ia32/ia32_signal.c --- a/arch/ia64/ia32/ia32_signal.c 2004-08-25 22:01:54 -07:00 +++ b/arch/ia64/ia32/ia32_signal.c 2004-08-25 22:01:54 -07:00 @@ -882,9 +882,7 @@ return 1; give_sigsegv: - if (sig == SIGSEGV) - ka->sa.sa_handler = SIG_DFL; - force_sig(SIGSEGV, current); + force_sigsegv(sig, current); return 0; } @@ -952,9 +950,7 @@ return 1; give_sigsegv: - if (sig == SIGSEGV) - ka->sa.sa_handler = SIG_DFL; - force_sig(SIGSEGV, current); + force_sigsegv(sig, current); return 0; } diff -Nru a/arch/ia64/kernel/asm-offsets.c b/arch/ia64/kernel/asm-offsets.c --- a/arch/ia64/kernel/asm-offsets.c 2004-08-25 22:01:56 -07:00 +++ b/arch/ia64/kernel/asm-offsets.c 2004-08-25 22:01:56 -07:00 @@ -195,11 +195,6 @@ DEFINE(IA64_TIMESPEC_TV_NSEC_OFFSET, offsetof (struct timespec, tv_nsec)); - DEFINE(CLONE_IDLETASK_BIT, 12); -#if CLONE_IDLETASK != (1 << 12) -# error "CLONE_IDLETASK_BIT incorrect, please fix" -#endif - DEFINE(CLONE_SETTLS_BIT, 19); #if CLONE_SETTLS != (1<<19) # error "CLONE_SETTLS_BIT incorrect, please fix" diff -Nru a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S --- a/arch/ia64/kernel/entry.S 2004-08-25 22:01:54 -07:00 +++ b/arch/ia64/kernel/entry.S 2004-08-25 22:01:54 -07:00 @@ -128,7 +128,7 @@ (p6) st8 [r2]=in5 // store TLS in r16 for copy_thread() mov out5=in4 // child_tidptr: valid only w/CLONE_CHILD_SETTID or CLONE_CHILD_CLEARTID adds out2=IA64_SWITCH_STACK_SIZE+16,sp // out2 = ®s - dep out0=0,in0,CLONE_IDLETASK_BIT,1 // out0 = clone_flags & ~CLONE_IDLETASK + mov out0=in0 // out0 = clone_flags br.call.sptk.many rp=do_fork .ret1: .restore sp adds sp=IA64_SWITCH_STACK_SIZE,sp // pop the switch stack @@ -157,7 +157,7 @@ (p6) st8 [r2]=in4 // store TLS in r13 (tp) mov out5=in3 // child_tidptr: valid only w/CLONE_CHILD_SETTID or CLONE_CHILD_CLEARTID adds out2=IA64_SWITCH_STACK_SIZE+16,sp // out2 = ®s - dep out0=0,in0,CLONE_IDLETASK_BIT,1 // out0 = clone_flags & ~CLONE_IDLETASK + mov out0=in0 // out0 = clone_flags br.call.sptk.many rp=do_fork .ret2: .restore sp adds sp=IA64_SWITCH_STACK_SIZE,sp // pop the switch stack diff -Nru a/arch/ia64/kernel/signal.c b/arch/ia64/kernel/signal.c --- a/arch/ia64/kernel/signal.c 2004-08-25 22:01:55 -07:00 +++ b/arch/ia64/kernel/signal.c 2004-08-25 22:01:55 -07:00 @@ -1,7 +1,7 @@ /* * Architecture-specific signal handling support. * - * Copyright (C) 1999-2003 Hewlett-Packard Co + * Copyright (C) 1999-2004 Hewlett-Packard Co * David Mosberger-Tang * * Derived from i386 and Alpha versions. @@ -352,13 +352,42 @@ } static long +force_sigsegv_info (int sig, void *addr) +{ + unsigned long flags; + struct siginfo si; + + if (sig == SIGSEGV) { + /* + * Acquiring siglock around the sa_handler-update is almost + * certainly overkill, but this isn't a + * performance-critical path and I'd rather play it safe + * here than having to debug a nasty race if and when + * something changes in kernel/signal.c that would make it + * no longer safe to modify sa_handler without holding the + * lock. + */ + spin_lock_irqsave(¤t->sighand->siglock, flags); + current->sighand->action[sig - 1].sa.sa_handler = SIG_DFL; + spin_unlock_irqrestore(¤t->sighand->siglock, flags); + } + si.si_signo = SIGSEGV; + si.si_errno = 0; + si.si_code = SI_KERNEL; + si.si_pid = current->pid; + si.si_uid = current->uid; + si.si_addr = addr; + force_sig_info(SIGSEGV, &si, current); + return 0; +} + +static long setup_frame (int sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *set, struct sigscratch *scr) { extern char __kernel_sigtramp[]; unsigned long tramp_addr, new_rbs = 0; struct sigframe *frame; - struct siginfo si; long err; frame = (void *) scr->pt.r12; @@ -377,7 +406,7 @@ frame = (void *) frame - ((sizeof(*frame) + STACK_ALIGN - 1) & ~(STACK_ALIGN - 1)); if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) - goto give_sigsegv; + return force_sigsegv_info(sig, frame); err = __put_user(sig, &frame->arg0); err |= __put_user(&frame->info, &frame->arg1); @@ -393,8 +422,8 @@ err |= __put_user(sas_ss_flags(scr->pt.r12), &frame->sc.sc_stack.ss_flags); err |= setup_sigcontext(&frame->sc, set, scr); - if (err) - goto give_sigsegv; + if (unlikely(err)) + return force_sigsegv_info(sig, frame); scr->pt.r12 = (unsigned long) frame - 16; /* new stack pointer */ scr->pt.ar_fpsr = FPSR_DEFAULT; /* reset fpsr for signal handler */ @@ -422,18 +451,6 @@ current->comm, current->pid, sig, scr->pt.r12, frame->sc.sc_ip, frame->handler); #endif return 1; - - give_sigsegv: - if (sig == SIGSEGV) - ka->sa.sa_handler = SIG_DFL; - si.si_signo = SIGSEGV; - si.si_errno = 0; - si.si_code = SI_KERNEL; - si.si_pid = current->pid; - si.si_uid = current->uid; - si.si_addr = frame; - force_sig_info(SIGSEGV, &si, current); - return 0; } static long @@ -449,9 +466,6 @@ if (!setup_frame(sig, ka, info, oldset, scr)) return 0; - if (ka->sa.sa_flags & SA_ONESHOT) - ka->sa.sa_handler = SIG_DFL; - if (!(ka->sa.sa_flags & SA_NODEFER)) { spin_lock_irq(¤t->sighand->siglock); { @@ -471,7 +485,7 @@ long ia64_do_signal (sigset_t *oldset, struct sigscratch *scr, long in_syscall) { - struct k_sigaction *ka; + struct k_sigaction ka; siginfo_t info; long restart = in_syscall; long errno = scr->pt.r8; @@ -493,7 +507,7 @@ * need to push through a forced SIGSEGV. */ while (1) { - int signr = get_signal_to_deliver(&info, &scr->pt, NULL); + int signr = get_signal_to_deliver(&info, &ka, &scr->pt, NULL); /* * get_signal_to_deliver() may have run a debugger (via notify_parent()) @@ -520,8 +534,6 @@ if (signr <= 0) break; - ka = ¤t->sighand->action[signr - 1]; - if (unlikely(restart)) { switch (errno) { case ERESTART_RESTARTBLOCK: @@ -531,7 +543,7 @@ break; case ERESTARTSYS: - if ((ka->sa.sa_flags & SA_RESTART) == 0) { + if ((ka.sa.sa_flags & SA_RESTART) == 0) { scr->pt.r8 = ERR_CODE(EINTR); /* note: scr->pt.r10 is already -1 */ break; @@ -550,7 +562,7 @@ * Whee! Actually deliver the signal. If the delivery failed, we need to * continue to iterate in this loop so we can deliver the SIGSEGV... */ - if (handle_signal(signr, ka, &info, oldset, scr)) + if (handle_signal(signr, &ka, &info, oldset, scr)) return 1; } diff -Nru a/arch/ia64/kernel/smpboot.c b/arch/ia64/kernel/smpboot.c --- a/arch/ia64/kernel/smpboot.c 2004-08-25 22:01:54 -07:00 +++ b/arch/ia64/kernel/smpboot.c 2004-08-25 22:01:54 -07:00 @@ -356,19 +356,15 @@ return cpu_idle(); } -static struct task_struct * __devinit -fork_by_hand (void) +struct pt_regs * __init idle_regs(struct pt_regs *regs) { - /* - * Don't care about the IP and regs settings since we'll never reschedule the - * forked task. - */ - return copy_process(CLONE_VM|CLONE_IDLETASK, 0, 0, 0, NULL, NULL); + return NULL; } struct create_idle { struct task_struct *idle; struct completion done; + int cpu; }; void @@ -376,7 +372,7 @@ { struct create_idle *c_idle = _c_idle; - c_idle->idle = fork_by_hand(); + c_idle->idle = fork_idle(c_idle->cpu); complete(&c_idle->done); } @@ -384,10 +380,11 @@ do_boot_cpu (int sapicid, int cpu) { int timeout; - struct create_idle c_idle; + struct create_idle c_idle = { + .cpu = cpu, + .done = COMPLETION_INITIALIZER(c_idle.done), + }; DECLARE_WORK(work, do_fork_idle, &c_idle); - - init_completion(&c_idle.done); /* * We can't use kernel_thread since we must avoid to reschedule the child. */ @@ -400,16 +397,6 @@ if (IS_ERR(c_idle.idle)) panic("failed fork for CPU %d", cpu); - wake_up_forked_process(c_idle.idle); - - /* - * We remove it from the pidhash and the runqueue - * once we got the process: - */ - init_idle(c_idle.idle, cpu); - - unhash_process(c_idle.idle); - task_for_booting_cpu = c_idle.idle; Dprintk("Sending wakeup vector %lu to AP 0x%x/0x%x.\n", ap_wakeup_vector, cpu, sapicid); @@ -719,3 +706,4 @@ printk(KERN_ERR "SMP: Can't set SAL AP Boot Rendezvous: %s\n", ia64_sal_strerror(sal_ret)); } + diff -Nru a/arch/ia64/kernel/vmlinux.lds.S b/arch/ia64/kernel/vmlinux.lds.S --- a/arch/ia64/kernel/vmlinux.lds.S 2004-08-25 22:01:56 -07:00 +++ b/arch/ia64/kernel/vmlinux.lds.S 2004-08-25 22:01:56 -07:00 @@ -135,12 +135,6 @@ *(.init.setup) __setup_end = .; } - __param : AT(ADDR(__param) - LOAD_OFFSET) - { - __start___param = .; - *(__param) - __stop___param = .; - } .initcall.init : AT(ADDR(.initcall.init) - LOAD_OFFSET) { __initcall_start = .; diff -Nru a/arch/ia64/mm/contig.c b/arch/ia64/mm/contig.c --- a/arch/ia64/mm/contig.c 2004-08-25 22:01:55 -07:00 +++ b/arch/ia64/mm/contig.c 2004-08-25 22:01:55 -07:00 @@ -267,7 +267,7 @@ efi_memmap_walk(find_largest_hole, (u64 *)&max_gap); if (max_gap < LARGE_GAP) { vmem_map = (struct page *) 0; - free_area_init_node(0, &contig_page_data, NULL, zones_size, 0, + free_area_init_node(0, &contig_page_data, zones_size, 0, zholes_size); mem_map = contig_page_data.node_mem_map; } else { @@ -280,7 +280,8 @@ vmem_map = (struct page *) vmalloc_end; efi_memmap_walk(create_mem_map_page_table, 0); - free_area_init_node(0, &contig_page_data, vmem_map, zones_size, + contig_page_data.node_mem_map = vmem_map; + free_area_init_node(0, &contig_page_data, zones_size, 0, zholes_size); mem_map = contig_page_data.node_mem_map; diff -Nru a/arch/ia64/mm/discontig.c b/arch/ia64/mm/discontig.c --- a/arch/ia64/mm/discontig.c 2004-08-25 22:01:56 -07:00 +++ b/arch/ia64/mm/discontig.c 2004-08-25 22:01:56 -07:00 @@ -664,8 +664,7 @@ pfn_offset = mem_data[node].min_pfn; - free_area_init_node(node, NODE_DATA(node), - vmem_map + pfn_offset, zones_size, + free_area_init_node(node, NODE_DATA(node), zones_size, pfn_offset, zholes_size); } diff -Nru a/arch/ia64/mm/init.c b/arch/ia64/mm/init.c --- a/arch/ia64/mm/init.c 2004-08-25 22:01:55 -07:00 +++ b/arch/ia64/mm/init.c 2004-08-25 22:01:55 -07:00 @@ -429,20 +429,22 @@ / sizeof(struct page)); if (map_start < map_end) - memmap_init_zone(map_start, (unsigned long) (map_end - map_start), + memmap_init_zone((unsigned long)(map_end - map_start), args->nid, args->zone, page_to_pfn(map_start)); return 0; } void -memmap_init (struct page *start, unsigned long size, int nid, - unsigned long zone, unsigned long start_pfn) +memmap_init (unsigned long size, int nid, unsigned long zone, + unsigned long start_pfn) { if (!vmem_map) - memmap_init_zone(start, size, nid, zone, start_pfn); + memmap_init_zone(size, nid, zone, start_pfn); else { + struct page *start; struct memmap_init_callback_data args; + start = pfn_to_page(start_pfn); args.start = start; args.end = start + size; args.nid = nid; diff -Nru a/arch/m68k/kernel/process.c b/arch/m68k/kernel/process.c --- a/arch/m68k/kernel/process.c 2004-08-25 22:01:56 -07:00 +++ b/arch/m68k/kernel/process.c 2004-08-25 22:01:56 -07:00 @@ -232,7 +232,7 @@ child_tidptr = (int *)regs->d4; if (!newsp) newsp = rdusp(); - return do_fork(clone_flags & ~CLONE_IDLETASK, newsp, regs, 0, + return do_fork(clone_flags, newsp, regs, 0, parent_tidptr, child_tidptr); } diff -Nru a/arch/m68k/kernel/signal.c b/arch/m68k/kernel/signal.c --- a/arch/m68k/kernel/signal.c 2004-08-25 22:01:55 -07:00 +++ b/arch/m68k/kernel/signal.c 2004-08-25 22:01:55 -07:00 @@ -842,9 +842,7 @@ return; give_sigsegv: - if (sig == SIGSEGV) - ka->sa.sa_handler = SIG_DFL; - force_sig(SIGSEGV, current); + force_sigsegv(sig, current); goto adjust_stack; } @@ -925,9 +923,7 @@ return; give_sigsegv: - if (sig == SIGSEGV) - ka->sa.sa_handler = SIG_DFL; - force_sig(SIGSEGV, current); + force_sigsegv(sig, current); goto adjust_stack; } diff -Nru a/arch/m68k/kernel/vmlinux-std.lds b/arch/m68k/kernel/vmlinux-std.lds --- a/arch/m68k/kernel/vmlinux-std.lds 2004-08-25 22:01:56 -07:00 +++ b/arch/m68k/kernel/vmlinux-std.lds 2004-08-25 22:01:56 -07:00 @@ -51,9 +51,6 @@ __setup_start = .; .init.setup : { *(.init.setup) } __setup_end = .; - __start___param = .; - __param : { *(__param) } - __stop___param = .; __initcall_start = .; .initcall.init : { *(.initcall1.init) diff -Nru a/arch/m68k/kernel/vmlinux-sun3.lds b/arch/m68k/kernel/vmlinux-sun3.lds --- a/arch/m68k/kernel/vmlinux-sun3.lds 2004-08-25 22:01:54 -07:00 +++ b/arch/m68k/kernel/vmlinux-sun3.lds 2004-08-25 22:01:54 -07:00 @@ -45,9 +45,6 @@ __setup_start = .; .init.setup : { *(.init.setup) } __setup_end = .; - __start___param = .; - __param : { *(__param) } - __stop___param = .; __initcall_start = .; .initcall.init : { *(.initcall1.init) diff -Nru a/arch/m68knommu/kernel/process.c b/arch/m68knommu/kernel/process.c --- a/arch/m68knommu/kernel/process.c 2004-08-25 22:01:54 -07:00 +++ b/arch/m68knommu/kernel/process.c 2004-08-25 22:01:54 -07:00 @@ -188,7 +188,7 @@ newsp = regs->d2; if (!newsp) newsp = rdusp(); - return do_fork(clone_flags & ~CLONE_IDLETASK, newsp, regs, 0, NULL, NULL); + return do_fork(clone_flags, newsp, regs, 0, NULL, NULL); } int copy_thread(int nr, unsigned long clone_flags, diff -Nru a/arch/m68knommu/kernel/signal.c b/arch/m68knommu/kernel/signal.c --- a/arch/m68knommu/kernel/signal.c 2004-08-25 22:01:55 -07:00 +++ b/arch/m68knommu/kernel/signal.c 2004-08-25 22:01:55 -07:00 @@ -616,9 +616,7 @@ return; give_sigsegv: - if (sig == SIGSEGV) - ka->sa.sa_handler = SIG_DFL; - force_sig(SIGSEGV, current); + force_sigsegv(sig, current); goto adjust_stack; } @@ -685,9 +683,7 @@ return; give_sigsegv: - if (sig == SIGSEGV) - ka->sa.sa_handler = SIG_DFL; - force_sig(SIGSEGV, current); + force_sigsegv(sig, current); goto adjust_stack; } diff -Nru a/arch/m68knommu/kernel/vmlinux.lds.S b/arch/m68knommu/kernel/vmlinux.lds.S --- a/arch/m68knommu/kernel/vmlinux.lds.S 2004-08-25 22:01:55 -07:00 +++ b/arch/m68knommu/kernel/vmlinux.lds.S 2004-08-25 22:01:55 -07:00 @@ -284,9 +284,6 @@ __setup_start = .; *(.init.setup) __setup_end = .; - __start___param = .; - *(__param) - __stop___param = .; __initcall_start = .; *(.initcall1.init) *(.initcall2.init) diff -Nru a/arch/mips/kernel/irixsig.c b/arch/mips/kernel/irixsig.c --- a/arch/mips/kernel/irixsig.c 2004-08-25 22:01:56 -07:00 +++ b/arch/mips/kernel/irixsig.c 2004-08-25 22:01:56 -07:00 @@ -121,9 +121,7 @@ return; segv_and_exit: - if (signr == SIGSEGV) - ka->sa.sa_handler = SIG_DFL; - force_sig(SIGSEGV, current); + force_sigsegv(signr, current); } static void inline diff -Nru a/arch/mips/kernel/signal.c b/arch/mips/kernel/signal.c --- a/arch/mips/kernel/signal.c 2004-08-25 22:01:56 -07:00 +++ b/arch/mips/kernel/signal.c 2004-08-25 22:01:56 -07:00 @@ -406,9 +406,7 @@ return; give_sigsegv: - if (signr == SIGSEGV) - ka->sa.sa_handler = SIG_DFL; - force_sig(SIGSEGV, current); + force_sigsegv(signr, current); } #endif @@ -475,9 +473,7 @@ return; give_sigsegv: - if (signr == SIGSEGV) - ka->sa.sa_handler = SIG_DFL; - force_sig(SIGSEGV, current); + force_sigsegv(signr, current); } extern void setup_rt_frame_n32(struct k_sigaction * ka, diff -Nru a/arch/mips/kernel/signal32.c b/arch/mips/kernel/signal32.c --- a/arch/mips/kernel/signal32.c 2004-08-25 22:01:55 -07:00 +++ b/arch/mips/kernel/signal32.c 2004-08-25 22:01:55 -07:00 @@ -574,9 +574,7 @@ return; give_sigsegv: - if (signr == SIGSEGV) - ka->sa.sa_handler = SIG_DFL; - force_sig(SIGSEGV, current); + force_sigsegv(signr, current); } static inline void setup_rt_frame(struct k_sigaction * ka, @@ -647,9 +645,7 @@ return; give_sigsegv: - if (signr == SIGSEGV) - ka->sa.sa_handler = SIG_DFL; - force_sig(SIGSEGV, current); + force_sigsegv(signr, current); } static inline void handle_signal(unsigned long sig, siginfo_t *info, diff -Nru a/arch/mips/kernel/signal_n32.c b/arch/mips/kernel/signal_n32.c --- a/arch/mips/kernel/signal_n32.c 2004-08-25 22:01:55 -07:00 +++ b/arch/mips/kernel/signal_n32.c 2004-08-25 22:01:55 -07:00 @@ -208,7 +208,5 @@ return; give_sigsegv: - if (signr == SIGSEGV) - ka->sa.sa_handler = SIG_DFL; - force_sig(SIGSEGV, current); + force_sigsegv(signr, current); } diff -Nru a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c --- a/arch/mips/kernel/smp.c 2004-08-25 22:01:54 -07:00 +++ b/arch/mips/kernel/smp.c 2004-08-25 22:01:54 -07:00 @@ -254,16 +254,6 @@ cpu_set(0, cpu_callin_map); } -static struct task_struct * __init fork_by_hand(void) -{ - struct pt_regs regs; - /* - * don't care about the eip and regs settings since - * we'll never reschedule the forked task. - */ - return copy_process(CLONE_VM|CLONE_IDLETASK, 0, ®s, 0, NULL, NULL); -} - /* * Startup the CPU with this logical number */ @@ -275,19 +265,9 @@ * The following code is purely to make sure * Linux can schedule processes on this slave. */ - idle = fork_by_hand(); + idle = fork_idle(cpu); if (IS_ERR(idle)) panic("failed fork for CPU %d\n", cpu); - - wake_up_forked_process(idle); - - /* - * We remove it from the pidhash and the runqueue once we've - * got the process: - */ - init_idle(idle, cpu); - - unhash_process(idle); prom_boot_secondary(cpu, idle); diff -Nru a/arch/mips/kernel/syscall.c b/arch/mips/kernel/syscall.c --- a/arch/mips/kernel/syscall.c 2004-08-25 22:01:56 -07:00 +++ b/arch/mips/kernel/syscall.c 2004-08-25 22:01:56 -07:00 @@ -180,7 +180,7 @@ newsp = regs.regs[29]; parent_tidptr = (int *) regs.regs[6]; child_tidptr = (int *) regs.regs[7]; - return do_fork(clone_flags & ~CLONE_IDLETASK, newsp, ®s, 0, + return do_fork(clone_flags, newsp, ®s, 0, parent_tidptr, child_tidptr); } diff -Nru a/arch/mips/kernel/vmlinux.lds.S b/arch/mips/kernel/vmlinux.lds.S --- a/arch/mips/kernel/vmlinux.lds.S 2004-08-25 22:01:55 -07:00 +++ b/arch/mips/kernel/vmlinux.lds.S 2004-08-25 22:01:55 -07:00 @@ -96,9 +96,6 @@ __setup_start = .; .init.setup : { *(.init.setup) } __setup_end = .; - __start___param = .; - __param : { *(__param) } - __stop___param = .; .early_initcall.init : { __earlyinitcall_start = .; diff -Nru a/arch/mips/sgi-ip27/ip27-memory.c b/arch/mips/sgi-ip27/ip27-memory.c --- a/arch/mips/sgi-ip27/ip27-memory.c 2004-08-25 22:01:54 -07:00 +++ b/arch/mips/sgi-ip27/ip27-memory.c 2004-08-25 22:01:54 -07:00 @@ -225,7 +225,7 @@ pfn_t end_pfn = node_getmaxclick(node) + 1; zones_size[ZONE_DMA] = end_pfn - start_pfn; - free_area_init_node(node, NODE_DATA(node), NULL, + free_area_init_node(node, NODE_DATA(node), zones_size, start_pfn, NULL); if (end_pfn > max_low_pfn) diff -Nru a/arch/parisc/kernel/hardware.c b/arch/parisc/kernel/hardware.c --- a/arch/parisc/kernel/hardware.c 2004-08-25 22:01:55 -07:00 +++ b/arch/parisc/kernel/hardware.c 2004-08-25 22:01:55 -07:00 @@ -7,7 +7,7 @@ * Reference Specification", March 7, 1999, version 0.96. This * is available at http://parisc-linux.org/documentation/ * - * Copyright 1999 by Alex deVries + * Copyright 1999 by Alex deVries * and copyright 1999 The Puffin Group Inc. * * This program is free software; you can redistribute it and/or modify diff -Nru a/arch/parisc/kernel/process.c b/arch/parisc/kernel/process.c --- a/arch/parisc/kernel/process.c 2004-08-25 22:01:56 -07:00 +++ b/arch/parisc/kernel/process.c 2004-08-25 22:01:56 -07:00 @@ -262,7 +262,7 @@ if(usp == 0) usp = regs->gr[30]; - return do_fork(clone_flags & ~CLONE_IDLETASK, usp, regs, 0, user_tid, NULL); + return do_fork(clone_flags, usp, regs, 0, user_tid, NULL); } int diff -Nru a/arch/parisc/kernel/smp.c b/arch/parisc/kernel/smp.c --- a/arch/parisc/kernel/smp.c 2004-08-25 22:01:56 -07:00 +++ b/arch/parisc/kernel/smp.c 2004-08-25 22:01:56 -07:00 @@ -486,24 +486,6 @@ } /* - * Create the idle task for a new Slave CPU. DO NOT use kernel_thread() - * because that could end up calling schedule(). If it did, the new idle - * task could get scheduled before we had a chance to remove it from the - * run-queue... - */ -static struct task_struct *fork_by_hand(void) -{ - struct pt_regs regs; - - /* - * don't care about the regs settings since - * we'll never reschedule the forked task. - */ - return copy_process(CLONE_VM|CLONE_IDLETASK, 0, ®s, 0, NULL, NULL); -} - - -/* * Bring one cpu online. */ int __init smp_boot_one_cpu(int cpuid) @@ -521,13 +503,10 @@ * Sheesh . . . */ - idle = fork_by_hand(); if (IS_ERR(idle)) panic("SMP: fork failed for CPU:%d", cpuid); - wake_up_forked_process(idle); - init_idle(idle, cpuid); - unhash_process(idle); + idle = fork_idle(cpunum); idle->thread_info->cpu = cpuid; /* Let _start know what logical CPU we're booting diff -Nru a/arch/parisc/kernel/vmlinux.lds.S b/arch/parisc/kernel/vmlinux.lds.S --- a/arch/parisc/kernel/vmlinux.lds.S 2004-08-25 22:01:54 -07:00 +++ b/arch/parisc/kernel/vmlinux.lds.S 2004-08-25 22:01:54 -07:00 @@ -130,9 +130,6 @@ __setup_start = .; .init.setup : { *(.init.setup) } __setup_end = .; - __start___param = .; - __param : { *(__param) } - __stop___param = .; __initcall_start = .; .initcall.init : { *(.initcall1.init) diff -Nru a/arch/parisc/mm/init.c b/arch/parisc/mm/init.c --- a/arch/parisc/mm/init.c 2004-08-25 22:01:55 -07:00 +++ b/arch/parisc/mm/init.c 2004-08-25 22:01:55 -07:00 @@ -804,7 +804,7 @@ ZONE_DMA zone. */ zones_size[ZONE_DMA] = pmem_ranges[i].pages; - free_area_init_node(i,NODE_DATA(i),NULL,zones_size, + free_area_init_node(i, NODE_DATA(i), zones_size, pmem_ranges[i].start_pfn, 0); #ifdef CONFIG_DISCONTIGMEM diff -Nru a/arch/ppc/8xx_io/uart.c b/arch/ppc/8xx_io/uart.c --- a/arch/ppc/8xx_io/uart.c 2004-08-25 22:01:56 -07:00 +++ b/arch/ppc/8xx_io/uart.c 2004-08-25 22:01:56 -07:00 @@ -2592,7 +2592,7 @@ state->icount.rx = state->icount.tx = 0; state->icount.frame = state->icount.parity = 0; state->icount.overrun = state->icount.brk = 0; - printk(KERN_INFO "ttyS%02d at 0x%04x is a %s\n", + printk(KERN_INFO "ttyS%d at 0x%04x is a %s\n", i, (unsigned int)(state->port), (state->smc_scc_num & NUM_IS_SCC) ? "SCC" : "SMC"); #ifdef CONFIG_SERIAL_CONSOLE diff -Nru a/arch/ppc/Kconfig b/arch/ppc/Kconfig --- a/arch/ppc/Kconfig 2004-08-25 22:01:56 -07:00 +++ b/arch/ppc/Kconfig 2004-08-25 22:01:56 -07:00 @@ -685,7 +685,8 @@ config PPC_GEN550 bool - depends on SANDPOINT || MCPN765 || SPRUCE || PPLUS || PCORE || PRPMC750 || K2 || PRPMC800 + depends on SANDPOINT || MCPN765 || SPRUCE || PPLUS || PCORE || \ + PRPMC750 || K2 || PRPMC800 || LOPEC default y config FORCE @@ -811,10 +812,6 @@ config HIGHMEM bool "High memory support" -config KERNEL_ELF - bool - default y - source "fs/Kconfig.binfmt" config PROC_DEVICETREE @@ -832,10 +829,11 @@ Some PReP systems have residual data passed to the kernel by the firmware. This allows detection of memory size, devices present and other useful pieces of information. Sometimes this information is - not present or incorrect. + not present or incorrect, in which case it could lead to the machine + behaving incorrectly. If this happens, either disable PREP_RESIDUAL + or pass the 'noresidual' option to the kernel. - Unless you expect to boot on a PReP system, there is no need to - select Y. + If you are running a PReP system, say Y here, otherwise say N. config PROC_PREPRESIDUAL bool "Support for reading of PReP Residual Data in /proc" diff -Nru a/arch/ppc/Kconfig.debug b/arch/ppc/Kconfig.debug --- a/arch/ppc/Kconfig.debug 2004-08-25 22:01:56 -07:00 +++ b/arch/ppc/Kconfig.debug 2004-08-25 22:01:56 -07:00 @@ -53,6 +53,18 @@ Unless you are intending to debug the kernel with one of these machines, say N here. +config SCHEDSTATS + bool "Collect scheduler statistics" + depends on DEBUG_KERNEL && PROC_FS + help + If you say Y here, additional code will be inserted into the + scheduler and related routines to collect statistics about + scheduler behavior and provide them in /proc/schedstat. These + stats may be useful for both tuning and debugging the scheduler + If you aren't debugging the scheduler or trying to tune a specific + application, you can say N to avoid the very slight overhead + this adds. + config BOOTX_TEXT bool "Support for early boot text console (BootX or OpenFirmware only)" depends PPC_OF diff -Nru a/arch/ppc/amiga/config.c b/arch/ppc/amiga/config.c --- a/arch/ppc/amiga/config.c 2004-08-25 22:01:56 -07:00 +++ b/arch/ppc/amiga/config.c 2004-08-25 22:01:56 -07:00 @@ -423,9 +423,6 @@ mach_floppy_setup = amiga_floppy_setup; #endif mach_reset = amiga_reset; -#ifdef CONFIG_DUMMY_CONSOLE - conswitchp = &dummy_con; -#endif #ifdef CONFIG_HEARTBEAT mach_heartbeat = amiga_heartbeat; #endif diff -Nru a/arch/ppc/boot/simple/misc-embedded.c b/arch/ppc/boot/simple/misc-embedded.c --- a/arch/ppc/boot/simple/misc-embedded.c 2004-08-25 22:01:54 -07:00 +++ b/arch/ppc/boot/simple/misc-embedded.c 2004-08-25 22:01:54 -07:00 @@ -72,6 +72,14 @@ extern void gunzip(void *, int, unsigned char *, int *); extern void embed_config(bd_t **bp); +/* Weak function for boards which don't need to build the + * board info struct because they are using PPCBoot/U-Boot. + */ +void __attribute__ ((weak)) +embed_config(bd_t **bdp) +{ +} + unsigned long load_kernel(unsigned long load_addr, int num_words, unsigned long cksum, bd_t *bp) { diff -Nru a/arch/ppc/configs/mvme5100_defconfig b/arch/ppc/configs/mvme5100_defconfig --- a/arch/ppc/configs/mvme5100_defconfig 2004-08-25 22:01:54 -07:00 +++ b/arch/ppc/configs/mvme5100_defconfig 2004-08-25 22:01:54 -07:00 @@ -4,23 +4,39 @@ CONFIG_MMU=y CONFIG_RWSEM_XCHGADD_ALGORITHM=y CONFIG_HAVE_DEC_LOCK=y +CONFIG_PPC=y +CONFIG_PPC32=y +CONFIG_GENERIC_NVRAM=y # # Code maturity level options # CONFIG_EXPERIMENTAL=y +CONFIG_CLEAN_COMPILE=y +CONFIG_BROKEN_ON_SMP=y # # General setup # CONFIG_SWAP=y CONFIG_SYSVIPC=y +# CONFIG_POSIX_MQUEUE is not set # CONFIG_BSD_PROCESS_ACCT is not set CONFIG_SYSCTL=y +# CONFIG_AUDIT is not set CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_HOTPLUG is not set +# CONFIG_IKCONFIG is not set # CONFIG_EMBEDDED is not set +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_EXTRA_PASS is not set CONFIG_FUTEX=y CONFIG_EPOLL=y +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set # # Loadable module support @@ -33,24 +49,26 @@ CONFIG_KMOD=y # -# Platform support +# Processor # -CONFIG_PPC=y -CONFIG_PPC32=y CONFIG_6xx=y # CONFIG_40x is not set +# CONFIG_44x is not set # CONFIG_POWER3 is not set +# CONFIG_POWER4 is not set # CONFIG_8xx is not set +# CONFIG_E500 is not set +CONFIG_ALTIVEC=y +# CONFIG_TAU is not set +# CONFIG_CPU_FREQ is not set +CONFIG_PPC_STD_MMU=y # -# IBM 4xx options +# Platform options # -# CONFIG_8260 is not set -CONFIG_GENERIC_ISA_DMA=y -CONFIG_PPC_STD_MMU=y # CONFIG_PPC_MULTIPLATFORM is not set # CONFIG_APUS is not set -# CONFIG_WILLOW_2 is not set +# CONFIG_WILLOW is not set # CONFIG_PCORE is not set # CONFIG_POWERPMC250 is not set # CONFIG_EV64260 is not set @@ -66,34 +84,31 @@ # CONFIG_K2 is not set # CONFIG_PAL4 is not set # CONFIG_GEMINI is not set +# CONFIG_EST8260 is not set +# CONFIG_SBC82xx is not set +# CONFIG_SBS8260 is not set +# CONFIG_RPX8260 is not set +# CONFIG_TQM8260 is not set +# CONFIG_ADS8272 is not set +# CONFIG_LITE5200 is not set # CONFIG_MVME5100_IPMC761_PRESENT is not set # CONFIG_SMP is not set # CONFIG_PREEMPT is not set -CONFIG_ALTIVEC=y -# CONFIG_TAU is not set -# CONFIG_CPU_FREQ is not set +# CONFIG_HIGHMEM is not set +CONFIG_KERNEL_ELF=y +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +CONFIG_CMDLINE_BOOL=y +CONFIG_CMDLINE="ip=on" # -# General setup +# Bus options # -# CONFIG_HIGHMEM is not set +CONFIG_GENERIC_ISA_DMA=y CONFIG_PCI=y CONFIG_PCI_DOMAINS=y -CONFIG_KCORE_ELF=y -CONFIG_BINFMT_ELF=y -CONFIG_KERNEL_ELF=y -# CONFIG_BINFMT_MISC is not set # CONFIG_PCI_LEGACY_PROC is not set # CONFIG_PCI_NAMES is not set -# CONFIG_HOTPLUG is not set - -# -# Parallel port support -# -# CONFIG_PARPORT is not set -# CONFIG_PPC601_SYNC_FIX is not set -CONFIG_CMDLINE_BOOL=y -CONFIG_CMDLINE="ip=on" # # Advanced setup @@ -110,14 +125,28 @@ CONFIG_BOOT_LOAD=0x00800000 # +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y + +# # Memory Technology Devices (MTD) # # CONFIG_MTD is not set # +# Parallel port support +# +# CONFIG_PARPORT is not set + +# # Plug and Play support # -# CONFIG_PNP is not set # # Block devices @@ -129,46 +158,46 @@ # CONFIG_BLK_DEV_UMEM is not set # CONFIG_BLK_DEV_LOOP is not set # CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_SX8 is not set CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_SIZE=4096 CONFIG_BLK_DEV_INITRD=y +# CONFIG_LBD is not set # -# Multi-device support (RAID and LVM) -# -# CONFIG_MD is not set - -# -# ATA/IDE/MFM/RLL support +# ATA/ATAPI/MFM/RLL support # CONFIG_IDE=y - -# -# IDE, ATA and ATAPI Block devices -# CONFIG_BLK_DEV_IDE=y # # Please see Documentation/ide.txt for help/info on IDE drives # -# CONFIG_BLK_DEV_HD is not set +# CONFIG_BLK_DEV_IDE_SATA is not set CONFIG_BLK_DEV_IDEDISK=y # CONFIG_IDEDISK_MULTI_MODE is not set -# CONFIG_IDEDISK_STROKE is not set # CONFIG_BLK_DEV_IDECD is not set +# CONFIG_BLK_DEV_IDETAPE is not set # CONFIG_BLK_DEV_IDEFLOPPY is not set # CONFIG_BLK_DEV_IDESCSI is not set # CONFIG_IDE_TASK_IOCTL is not set +# CONFIG_IDE_TASKFILE_IO is not set # # IDE chipset support/bugfixes # +CONFIG_IDE_GENERIC=y # CONFIG_BLK_DEV_IDEPCI is not set +# CONFIG_IDE_ARM is not set +# CONFIG_BLK_DEV_IDEDMA is not set +# CONFIG_IDEDMA_AUTO is not set +# CONFIG_BLK_DEV_HD is not set # -# SCSI support +# SCSI device support # CONFIG_SCSI=y +CONFIG_SCSI_PROC_FS=y # # SCSI support type (disk, tape, CD-ROM) @@ -184,64 +213,69 @@ # Some SCSI devices (e.g. CD jukebox) support multiple LUNs # # CONFIG_SCSI_MULTI_LUN is not set -# CONFIG_SCSI_REPORT_LUNS is not set # CONFIG_SCSI_CONSTANTS is not set # CONFIG_SCSI_LOGGING is not set # +# SCSI Transport Attributes +# +CONFIG_SCSI_SPI_ATTRS=y +# CONFIG_SCSI_FC_ATTRS is not set + +# # SCSI low-level drivers # # CONFIG_BLK_DEV_3W_XXXX_RAID is not set +# CONFIG_SCSI_3W_9XXX is not set # CONFIG_SCSI_ACARD is not set # CONFIG_SCSI_AACRAID is not set # CONFIG_SCSI_AIC7XXX is not set # CONFIG_SCSI_AIC7XXX_OLD is not set # CONFIG_SCSI_AIC79XX is not set # CONFIG_SCSI_DPT_I2O is not set -# CONFIG_SCSI_ADVANSYS is not set -# CONFIG_SCSI_IN2000 is not set -# CONFIG_SCSI_AM53C974 is not set # CONFIG_SCSI_MEGARAID is not set +# CONFIG_SCSI_SATA is not set # CONFIG_SCSI_BUSLOGIC is not set -# CONFIG_SCSI_CPQFCTS is not set # CONFIG_SCSI_DMX3191D is not set # CONFIG_SCSI_EATA is not set # CONFIG_SCSI_EATA_PIO is not set # CONFIG_SCSI_FUTURE_DOMAIN is not set # CONFIG_SCSI_GDTH is not set -# CONFIG_SCSI_GENERIC_NCR5380 is not set -# CONFIG_SCSI_GENERIC_NCR5380_MMIO is not set -# CONFIG_SCSI_INITIO is not set +# CONFIG_SCSI_IPS is not set # CONFIG_SCSI_INIA100 is not set -# CONFIG_SCSI_NCR53C7xx is not set -# CONFIG_SCSI_SYM53C8XX_2 is not set -# CONFIG_SCSI_NCR53C8XX is not set -CONFIG_SCSI_SYM53C8XX=y -CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS=8 -CONFIG_SCSI_NCR53C8XX_MAX_TAGS=32 -CONFIG_SCSI_NCR53C8XX_SYNC=20 -# CONFIG_SCSI_NCR53C8XX_PROFILE is not set -# CONFIG_SCSI_NCR53C8XX_IOMAPPED is not set -# CONFIG_SCSI_NCR53C8XX_PQS_PDS is not set -# CONFIG_SCSI_NCR53C8XX_SYMBIOS_COMPAT is not set -# CONFIG_SCSI_PCI2000 is not set -# CONFIG_SCSI_PCI2220I is not set +CONFIG_SCSI_SYM53C8XX_2=y +CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=0 +CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=8 +CONFIG_SCSI_SYM53C8XX_MAX_TAGS=32 +# CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set +# CONFIG_SCSI_IPR is not set # CONFIG_SCSI_QLOGIC_ISP is not set # CONFIG_SCSI_QLOGIC_FC is not set # CONFIG_SCSI_QLOGIC_1280 is not set +CONFIG_SCSI_QLA2XXX=y +# CONFIG_SCSI_QLA21XX is not set +# CONFIG_SCSI_QLA22XX is not set +# CONFIG_SCSI_QLA2300 is not set +# CONFIG_SCSI_QLA2322 is not set +# CONFIG_SCSI_QLA6312 is not set +# CONFIG_SCSI_QLA6322 is not set # CONFIG_SCSI_DC395x is not set # CONFIG_SCSI_DC390T is not set -# CONFIG_SCSI_U14_34F is not set # CONFIG_SCSI_NSP32 is not set # CONFIG_SCSI_DEBUG is not set # +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# # Fusion MPT device support # # CONFIG_FUSION is not set # -# IEEE 1394 (FireWire) support (EXPERIMENTAL) +# IEEE 1394 (FireWire) support # # CONFIG_IEEE1394 is not set @@ -251,6 +285,10 @@ # CONFIG_I2O is not set # +# Macintosh device drivers +# + +# # Networking support # CONFIG_NET=y @@ -261,28 +299,33 @@ CONFIG_PACKET=y # CONFIG_PACKET_MMAP is not set # CONFIG_NETLINK_DEV is not set -CONFIG_NETFILTER=y -# CONFIG_NETFILTER_DEBUG is not set CONFIG_UNIX=y # CONFIG_NET_KEY is not set CONFIG_INET=y CONFIG_IP_MULTICAST=y # CONFIG_IP_ADVANCED_ROUTER is not set CONFIG_IP_PNP=y -CONFIG_IP_PNP_DHCP=y -# CONFIG_IP_PNP_BOOTP is not set +# CONFIG_IP_PNP_DHCP is not set +CONFIG_IP_PNP_BOOTP=y # CONFIG_IP_PNP_RARP is not set # CONFIG_NET_IPIP is not set # CONFIG_NET_IPGRE is not set # CONFIG_IP_MROUTE is not set # CONFIG_ARPD is not set -# CONFIG_INET_ECN is not set # CONFIG_SYN_COOKIES is not set # CONFIG_INET_AH is not set # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set # +# IP: Virtual Server Configuration +# +# CONFIG_IP_VS is not set +# CONFIG_IPV6 is not set +CONFIG_NETFILTER=y +# CONFIG_NETFILTER_DEBUG is not set + +# # IP: Netfilter Configuration # CONFIG_IP_NF_CONNTRACK=m @@ -293,11 +336,13 @@ # CONFIG_IP_NF_QUEUE is not set CONFIG_IP_NF_IPTABLES=m CONFIG_IP_NF_MATCH_LIMIT=m +# CONFIG_IP_NF_MATCH_IPRANGE is not set CONFIG_IP_NF_MATCH_MAC=m CONFIG_IP_NF_MATCH_PKTTYPE=m CONFIG_IP_NF_MATCH_MARK=m CONFIG_IP_NF_MATCH_MULTIPORT=m CONFIG_IP_NF_MATCH_TOS=m +# CONFIG_IP_NF_MATCH_RECENT is not set CONFIG_IP_NF_MATCH_ECN=m CONFIG_IP_NF_MATCH_DSCP=m CONFIG_IP_NF_MATCH_AH_ESP=m @@ -307,15 +352,15 @@ CONFIG_IP_NF_MATCH_HELPER=m CONFIG_IP_NF_MATCH_STATE=m CONFIG_IP_NF_MATCH_CONNTRACK=m -CONFIG_IP_NF_MATCH_UNCLEAN=m CONFIG_IP_NF_MATCH_OWNER=m CONFIG_IP_NF_FILTER=m CONFIG_IP_NF_TARGET_REJECT=m -CONFIG_IP_NF_TARGET_MIRROR=m CONFIG_IP_NF_NAT=m CONFIG_IP_NF_NAT_NEEDED=y CONFIG_IP_NF_TARGET_MASQUERADE=m CONFIG_IP_NF_TARGET_REDIRECT=m +# CONFIG_IP_NF_TARGET_NETMAP is not set +# CONFIG_IP_NF_TARGET_SAME is not set # CONFIG_IP_NF_NAT_LOCAL is not set # CONFIG_IP_NF_NAT_SNMP_BASIC is not set CONFIG_IP_NF_NAT_IRC=m @@ -326,21 +371,24 @@ CONFIG_IP_NF_TARGET_TCPMSS=m CONFIG_IP_NF_ARPTABLES=m CONFIG_IP_NF_ARPFILTER=m +# CONFIG_IP_NF_ARP_MANGLE is not set CONFIG_IP_NF_COMPAT_IPCHAINS=m # CONFIG_IP_NF_COMPAT_IPFWADM is not set -# CONFIG_IPV6 is not set -# CONFIG_XFRM_USER is not set +# CONFIG_IP_NF_RAW is not set +# CONFIG_IP_NF_MATCH_ADDRTYPE is not set +# CONFIG_IP_NF_MATCH_REALM is not set # # SCTP Configuration (EXPERIMENTAL) # -CONFIG_IPV6_SCTP__=y # CONFIG_IP_SCTP is not set # CONFIG_ATM is not set +# CONFIG_BRIDGE is not set # CONFIG_VLAN_8021Q is not set -# CONFIG_LLC is not set # CONFIG_DECNET is not set -# CONFIG_BRIDGE is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set # CONFIG_X25 is not set # CONFIG_LAPB is not set # CONFIG_NET_DIVERT is not set @@ -352,29 +400,33 @@ # QoS and/or fair queueing # # CONFIG_NET_SCHED is not set +# CONFIG_NET_CLS_ROUTE is not set # # Network testing # # CONFIG_NET_PKTGEN is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set # # ARCnet devices # # CONFIG_ARCNET is not set -# CONFIG_DUMMY is not set -# CONFIG_BONDING is not set -# CONFIG_EQUALIZER is not set -# CONFIG_TUN is not set -# CONFIG_ETHERTAP is not set # # Ethernet (10 or 100Mbit) # CONFIG_NET_ETHERNET=y CONFIG_MII=y -# CONFIG_OAKNET is not set # CONFIG_HAPPYMEAL is not set # CONFIG_SUNGEM is not set # CONFIG_NET_VENDOR_3COM is not set @@ -389,10 +441,11 @@ # CONFIG_AMD8111_ETH is not set # CONFIG_ADAPTEC_STARFIRE is not set # CONFIG_B44 is not set +# CONFIG_FORCEDETH is not set # CONFIG_DGRS is not set -CONFIG_EEPRO100=y -# CONFIG_EEPRO100_PIO is not set -# CONFIG_E100 is not set +# CONFIG_EEPRO100 is not set +CONFIG_E100=y +# CONFIG_E100_NAPI is not set # CONFIG_FEALNX is not set # CONFIG_NATSEMI is not set # CONFIG_NE2K_PCI is not set @@ -403,6 +456,7 @@ # CONFIG_SUNDANCE is not set # CONFIG_TLAN is not set # CONFIG_VIA_RHINE is not set +# CONFIG_VIA_VELOCITY is not set # # Ethernet (1000 Mbit) @@ -421,80 +475,91 @@ # Ethernet (10000 Mbit) # # CONFIG_IXGB is not set -# CONFIG_FDDI is not set -# CONFIG_HIPPI is not set -# CONFIG_PPP is not set -# CONFIG_SLIP is not set +# CONFIG_S2IO is not set # -# Wireless LAN (non-hamradio) +# Token Ring devices # -# CONFIG_NET_RADIO is not set +# CONFIG_TR is not set # -# Token Ring devices (depends on LLC=y) +# Wireless LAN (non-hamradio) # -# CONFIG_NET_FC is not set -# CONFIG_RCPCI is not set -# CONFIG_SHAPER is not set +# CONFIG_NET_RADIO is not set # # Wan interfaces # # CONFIG_WAN is not set - -# -# Amateur Radio support -# -# CONFIG_HAMRADIO is not set - -# -# IrDA (infrared) support -# -# CONFIG_IRDA is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_NET_FC is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set # # ISDN subsystem # -# CONFIG_ISDN_BOOL is not set - -# -# Graphics support -# -# CONFIG_FB is not set +# CONFIG_ISDN is not set # -# Old CD-ROM drivers (not SCSI, not IDE) +# Telephony Support # -# CONFIG_CD_NO_IDESCSI is not set +# CONFIG_PHONE is not set # # Input device support # -# CONFIG_INPUT is not set +CONFIG_INPUT=y # # Userland interfaces # +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set # # Input I/O drivers # # CONFIG_GAMEPORT is not set CONFIG_SOUND_GAMEPORT=y -# CONFIG_SERIO is not set +CONFIG_SERIO=y +CONFIG_SERIO_I8042=y +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_CT82C710 is not set +# CONFIG_SERIO_PCIPS2 is not set # # Input Device Drivers # - -# -# Macintosh device drivers -# +CONFIG_INPUT_KEYBOARD=y +CONFIG_KEYBOARD_ATKBD=y +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_LKKBD is not set +# CONFIG_KEYBOARD_XTKBD is not set +# CONFIG_KEYBOARD_NEWTON is not set +CONFIG_INPUT_MOUSE=y +CONFIG_MOUSE_PS2=y +# CONFIG_MOUSE_SERIAL is not set +# CONFIG_MOUSE_VSXXXAA is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set # # Character devices # +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y # CONFIG_SERIAL_NONSTANDARD is not set # @@ -502,6 +567,7 @@ # CONFIG_SERIAL_8250=y CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_NR_UARTS=4 # CONFIG_SERIAL_8250_EXTENDED is not set # @@ -510,26 +576,8 @@ CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y CONFIG_UNIX98_PTYS=y -CONFIG_UNIX98_PTY_COUNT=256 - -# -# I2C support -# -# CONFIG_I2C is not set - -# -# I2C Hardware Sensors Mainboard support -# - -# -# I2C Hardware Sensors Chip support -# -# CONFIG_I2C_SENSOR is not set - -# -# Mice -# -# CONFIG_BUSMOUSE is not set +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 # CONFIG_QIC02_TAPE is not set # @@ -551,11 +599,23 @@ # # Ftape, the floppy tape device driver # -# CONFIG_FTAPE is not set # CONFIG_AGP is not set # CONFIG_DRM is not set # CONFIG_RAW_DRIVER is not set -# CONFIG_HANGCHECK_TIMER is not set + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# Dallas's 1-wire bus +# +# CONFIG_W1 is not set + +# +# Misc devices +# # # Multimedia devices @@ -568,6 +628,33 @@ # CONFIG_DVB is not set # +# Graphics support +# +# CONFIG_FB is not set + +# +# Console display driver support +# +CONFIG_VGA_CONSOLE=y +# CONFIG_MDA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +# CONFIG_USB is not set + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# # File systems # CONFIG_EXT2_FS=y @@ -592,17 +679,20 @@ # # DOS/FAT/NT Filesystems # -# CONFIG_FAT_FS is not set +# CONFIG_MSDOS_FS is not set +# CONFIG_VFAT_FS is not set # CONFIG_NTFS_FS is not set # # Pseudo filesystems # CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +CONFIG_SYSFS=y # CONFIG_DEVFS_FS is not set -CONFIG_DEVPTS_FS=y # CONFIG_DEVPTS_FS_XATTR is not set CONFIG_TMPFS=y +# CONFIG_HUGETLB_PAGE is not set CONFIG_RAMFS=y # @@ -611,6 +701,7 @@ # CONFIG_ADFS_FS is not set # CONFIG_AFFS_FS is not set # CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set # CONFIG_BEFS_FS is not set # CONFIG_BFS_FS is not set # CONFIG_EFS_FS is not set @@ -625,19 +716,20 @@ # Network File Systems # CONFIG_NFS_FS=y -# CONFIG_NFS_V3 is not set +CONFIG_NFS_V3=y # CONFIG_NFS_V4 is not set +# CONFIG_NFS_DIRECTIO is not set # CONFIG_NFSD is not set CONFIG_ROOT_NFS=y CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y # CONFIG_EXPORTFS is not set CONFIG_SUNRPC=y -# CONFIG_SUNRPC_GSS is not set +# CONFIG_RPCSEC_GSS_KRB5 is not set # CONFIG_SMB_FS is not set # CONFIG_CIFS is not set # CONFIG_NCP_FS is not set # CONFIG_CODA_FS is not set -# CONFIG_INTERMEZZO_FS is not set # CONFIG_AFS_FS is not set # @@ -647,31 +739,26 @@ CONFIG_MSDOS_PARTITION=y # -# Sound -# -# CONFIG_SOUND is not set - -# -# USB support +# Native Language Support # -# CONFIG_USB is not set -# CONFIG_USB_GADGET is not set +# CONFIG_NLS is not set # -# Bluetooth support +# Library routines # -# CONFIG_BT is not set +# CONFIG_CRC_CCITT is not set +# CONFIG_CRC32 is not set +# CONFIG_LIBCRC32C is not set # -# Library routines +# Profiling support # -# CONFIG_CRC32 is not set +# CONFIG_PROFILING is not set # # Kernel hacking # # CONFIG_DEBUG_KERNEL is not set -# CONFIG_KALLSYMS is not set # # Security options diff -Nru a/arch/ppc/kernel/cputable.c b/arch/ppc/kernel/cputable.c --- a/arch/ppc/kernel/cputable.c 2004-08-25 22:01:55 -07:00 +++ b/arch/ppc/kernel/cputable.c 2004-08-25 22:01:55 -07:00 @@ -55,7 +55,7 @@ #endif /* We need to mark all pages as being coherent if we're SMP or we - * have a 754x and an MPC107 host bridge. + * have a 74[45]x and an MPC107 host bridge. */ #if defined(CONFIG_SMP) || defined(CONFIG_MPC10X_BRIDGE) #define CPU_FTR_COMMON CPU_FTR_NEED_COHERENT diff -Nru a/arch/ppc/kernel/idle.c b/arch/ppc/kernel/idle.c --- a/arch/ppc/kernel/idle.c 2004-08-25 22:01:54 -07:00 +++ b/arch/ppc/kernel/idle.c 2004-08-25 22:01:54 -07:00 @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -65,3 +66,36 @@ default_idle(); return 0; } + +#if defined(CONFIG_SYSCTL) && defined(CONFIG_6xx) +/* + * Register the sysctl to set/clear powersave_nap. + */ +extern unsigned long powersave_nap; + +static ctl_table powersave_nap_ctl_table[]={ + { + .ctl_name = KERN_PPC_POWERSAVE_NAP, + .procname = "powersave-nap", + .data = &powersave_nap, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = &proc_dointvec, + }, + { 0, }, +}; +static ctl_table powersave_nap_sysctl_root[] = { + { 1, "kernel", NULL, 0, 0755, powersave_nap_ctl_table, }, + { 0,}, +}; + +static int __init +register_powersave_nap_sysctl(void) +{ + register_sysctl_table(powersave_nap_sysctl_root, 0); + + return 0; +} + +__initcall(register_powersave_nap_sysctl); +#endif diff -Nru a/arch/ppc/kernel/misc.S b/arch/ppc/kernel/misc.S --- a/arch/ppc/kernel/misc.S 2004-08-25 22:01:56 -07:00 +++ b/arch/ppc/kernel/misc.S 2004-08-25 22:01:56 -07:00 @@ -617,10 +617,9 @@ * flush_icache_range(unsigned long start, unsigned long stop) */ _GLOBAL(flush_icache_range) - mfspr r5,PVR - rlwinm r5,r5,16,16,31 - cmpi 0,r5,1 - beqlr /* for 601, do nothing */ +BEGIN_FTR_SECTION + blr /* for 601, do nothing */ +END_FTR_SECTION_IFSET(PPC_FEATURE_UNIFIED_CACHE) li r5,L1_CACHE_LINE_SIZE-1 andc r3,r3,r5 subf r4,r3,r4 @@ -735,10 +734,9 @@ * void __flush_dcache_icache(void *page) */ _GLOBAL(__flush_dcache_icache) - mfspr r5,PVR - rlwinm r5,r5,16,16,31 - cmpi 0,r5,1 - beqlr /* for 601, do nothing */ +BEGIN_FTR_SECTION + blr /* for 601, do nothing */ +END_FTR_SECTION_IFSET(PPC_FEATURE_UNIFIED_CACHE) rlwinm r3,r3,0,0,19 /* Get page base address */ li r4,4096/L1_CACHE_LINE_SIZE /* Number of lines in a page */ mtctr r4 @@ -764,10 +762,9 @@ * void __flush_dcache_icache_phys(unsigned long physaddr) */ _GLOBAL(__flush_dcache_icache_phys) - mfspr r5,PVR - rlwinm r5,r5,16,16,31 - cmpi 0,r5,1 - beqlr /* for 601, do nothing */ +BEGIN_FTR_SECTION + blr /* for 601, do nothing */ +END_FTR_SECTION_IFSET(PPC_FEATURE_UNIFIED_CACHE) mfmsr r10 rlwinm r0,r10,0,28,26 /* clear DR */ mtmsr r0 diff -Nru a/arch/ppc/kernel/ppc_htab.c b/arch/ppc/kernel/ppc_htab.c --- a/arch/ppc/kernel/ppc_htab.c 2004-08-25 22:01:54 -07:00 +++ b/arch/ppc/kernel/ppc_htab.c 2004-08-25 22:01:54 -07:00 @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -34,9 +35,6 @@ static int ppc_htab_show(struct seq_file *m, void *v); static ssize_t ppc_htab_write(struct file * file, const char __user * buffer, size_t count, loff_t *ppos); -int proc_dol2crvec(ctl_table *table, int write, struct file *filp, - void __user *buffer, size_t *lenp, loff_t *ppos); - extern PTE *Hash, *Hash_end; extern unsigned long Hash_size, Hash_mask; extern unsigned long _SDR1; @@ -438,3 +436,32 @@ *ppos += *lenp; return 0; } + +#ifdef CONFIG_SYSCTL +/* + * Register our sysctl. + */ +static ctl_table htab_ctl_table[]={ + { + .ctl_name = KERN_PPC_L2CR, + .procname = "l2cr", + .mode = 0644, + .proc_handler = &proc_dol2crvec, + }, + { 0, }, +}; +static ctl_table htab_sysctl_root[] = { + { 1, "kernel", NULL, 0, 0755, htab_ctl_table, }, + { 0,}, +}; + +static int __init +register_ppc_htab_sysctl(void) +{ + register_sysctl_table(htab_sysctl_root, 0); + + return 0; +} + +__initcall(register_ppc_htab_sysctl); +#endif diff -Nru a/arch/ppc/kernel/process.c b/arch/ppc/kernel/process.c --- a/arch/ppc/kernel/process.c 2004-08-25 22:01:55 -07:00 +++ b/arch/ppc/kernel/process.c 2004-08-25 22:01:55 -07:00 @@ -555,8 +555,7 @@ CHECK_FULL_REGS(regs); if (usp == 0) usp = regs->gpr[1]; /* stack pointer for child */ - return do_fork(clone_flags & ~CLONE_IDLETASK, usp, regs, 0, - parent_tidp, child_tidp); + return do_fork(clone_flags, usp, regs, 0, parent_tidp, child_tidp); } int sys_fork(int p1, int p2, int p3, int p4, int p5, int p6, diff -Nru a/arch/ppc/kernel/setup.c b/arch/ppc/kernel/setup.c --- a/arch/ppc/kernel/setup.c 2004-08-25 22:01:56 -07:00 +++ b/arch/ppc/kernel/setup.c 2004-08-25 22:01:56 -07:00 @@ -747,6 +747,10 @@ if ( ppc_md.progress ) ppc_md.progress("ocp: exit", 0x3eab); #endif +#ifdef CONFIG_DUMMY_CONSOLE + conswitchp = &dummy_con; +#endif + ppc_md.setup_arch(); if ( ppc_md.progress ) ppc_md.progress("arch: exit", 0x3eab); diff -Nru a/arch/ppc/kernel/signal.c b/arch/ppc/kernel/signal.c --- a/arch/ppc/kernel/signal.c 2004-08-25 22:01:56 -07:00 +++ b/arch/ppc/kernel/signal.c 2004-08-25 22:01:56 -07:00 @@ -404,9 +404,7 @@ printk("badframe in handle_rt_signal, regs=%p frame=%p newsp=%lx\n", regs, frame, newsp); #endif - if (sig == SIGSEGV) - ka->sa.sa_handler = SIG_DFL; - force_sig(SIGSEGV, current); + force_sigsegv(sig, current); } static int do_setcontext(struct ucontext __user *ucp, struct pt_regs *regs, int sig) @@ -556,9 +554,7 @@ printk("badframe in handle_signal, regs=%p frame=%p newsp=%lx\n", regs, frame, newsp); #endif - if (sig == SIGSEGV) - ka->sa.sa_handler = SIG_DFL; - force_sig(SIGSEGV, current); + force_sigsegv(sig, current); } /* @@ -604,7 +600,7 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs) { siginfo_t info; - struct k_sigaction *ka; + struct k_sigaction ka; unsigned long frame, newsp; int signr, ret; @@ -613,9 +609,7 @@ newsp = frame = 0; - signr = get_signal_to_deliver(&info, regs, NULL); - - ka = (signr == 0)? NULL: ¤t->sighand->action[signr-1]; + signr = get_signal_to_deliver(&info, &ka, regs, NULL); if (TRAP(regs) == 0x0C00 /* System Call! */ && regs->ccr & 0x10000000 /* error signalled */ @@ -626,7 +620,7 @@ if (signr > 0 && (ret == ERESTARTNOHAND || ret == ERESTART_RESTARTBLOCK || (ret == ERESTARTSYS - && !(ka->sa.sa_flags & SA_RESTART)))) { + && !(ka.sa.sa_flags & SA_RESTART)))) { /* make the system call return an EINTR error */ regs->result = -EINTR; regs->gpr[3] = EINTR; @@ -645,7 +639,7 @@ if (signr == 0) return 0; /* no signals delivered */ - if ((ka->sa.sa_flags & SA_ONSTACK) && current->sas_ss_size + if ((ka.sa.sa_flags & SA_ONSTACK) && current->sas_ss_size && !on_sig_stack(regs->gpr[1])) newsp = current->sas_ss_sp + current->sas_ss_size; else @@ -653,17 +647,14 @@ newsp &= ~0xfUL; /* Whee! Actually deliver the signal. */ - if (ka->sa.sa_flags & SA_SIGINFO) - handle_rt_signal(signr, ka, &info, oldset, regs, newsp); + if (ka.sa.sa_flags & SA_SIGINFO) + handle_rt_signal(signr, &ka, &info, oldset, regs, newsp); else - handle_signal(signr, ka, &info, oldset, regs, newsp); - - if (ka->sa.sa_flags & SA_ONESHOT) - ka->sa.sa_handler = SIG_DFL; + handle_signal(signr, &ka, &info, oldset, regs, newsp); - if (!(ka->sa.sa_flags & SA_NODEFER)) { + if (!(ka.sa.sa_flags & SA_NODEFER)) { spin_lock_irq(¤t->sighand->siglock); - sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); + sigorsets(¤t->blocked,¤t->blocked,&ka.sa.sa_mask); sigaddset(¤t->blocked, signr); recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); diff -Nru a/arch/ppc/kernel/smp.c b/arch/ppc/kernel/smp.c --- a/arch/ppc/kernel/smp.c 2004-08-25 22:01:56 -07:00 +++ b/arch/ppc/kernel/smp.c 2004-08-25 22:01:56 -07:00 @@ -364,22 +364,15 @@ int __cpu_up(unsigned int cpu) { - struct pt_regs regs; struct task_struct *p; char buf[32]; int c; /* create a process for the processor */ /* only regs.msr is actually used, and 0 is OK for it */ - memset(®s, 0, sizeof(struct pt_regs)); - p = copy_process(CLONE_VM|CLONE_IDLETASK, 0, ®s, 0, NULL, NULL); + p = fork_idle(cpu); if (IS_ERR(p)) panic("failed fork for CPU %u: %li", cpu, PTR_ERR(p)); - wake_up_forked_process(p); - - init_idle(p, cpu); - unhash_process(p); - secondary_ti = p->thread_info; p->thread_info->cpu = cpu; diff -Nru a/arch/ppc/kernel/vmlinux.lds.S b/arch/ppc/kernel/vmlinux.lds.S --- a/arch/ppc/kernel/vmlinux.lds.S 2004-08-25 22:01:56 -07:00 +++ b/arch/ppc/kernel/vmlinux.lds.S 2004-08-25 22:01:56 -07:00 @@ -102,9 +102,6 @@ __setup_start = .; .init.setup : { *(.init.setup) } __setup_end = .; - __start___param = .; - __param : { *(__param) } - __stop___param = .; __initcall_start = .; .initcall.init : { *(.initcall1.init) diff -Nru a/arch/ppc/math-emu/op-common.h b/arch/ppc/math-emu/op-common.h --- a/arch/ppc/math-emu/op-common.h 2004-08-25 22:01:56 -07:00 +++ b/arch/ppc/math-emu/op-common.h 2004-08-25 22:01:56 -07:00 @@ -82,7 +82,6 @@ if (X##_e <= _FP_WFRACBITS_##fs) \ { \ _FP_FRAC_SRS_##wc(X, X##_e, _FP_WFRACBITS_##fs); \ - __ret |= _FP_ROUND(wc, X); \ _FP_FRAC_SLL_##wc(X, 1); \ if (_FP_FRAC_OVERP_##wc(fs, X)) \ { \ diff -Nru a/arch/ppc/platforms/4xx/ebony.c b/arch/ppc/platforms/4xx/ebony.c --- a/arch/ppc/platforms/4xx/ebony.c 2004-08-25 22:01:56 -07:00 +++ b/arch/ppc/platforms/4xx/ebony.c 2004-08-25 22:01:56 -07:00 @@ -361,10 +361,6 @@ ROOT_DEV = Root_HDA1; #endif -#ifdef CONFIG_VT - conswitchp = &dummy_con; -#endif - ebony_early_serial_map(); ibm4xxPIC_InitSenses = ebony_IRQ_initsenses; diff -Nru a/arch/ppc/platforms/4xx/ocotea.c b/arch/ppc/platforms/4xx/ocotea.c --- a/arch/ppc/platforms/4xx/ocotea.c 2004-08-25 22:01:56 -07:00 +++ b/arch/ppc/platforms/4xx/ocotea.c 2004-08-25 22:01:56 -07:00 @@ -319,10 +319,6 @@ ROOT_DEV = Root_HDA1; #endif -#ifdef CONFIG_DUMMY_CONSOLE - conswitchp = &dummy_con; -#endif - ocotea_early_serial_map(&clocks); /* Identify the system */ diff -Nru a/arch/ppc/platforms/85xx/mpc8540_ads.c b/arch/ppc/platforms/85xx/mpc8540_ads.c --- a/arch/ppc/platforms/85xx/mpc8540_ads.c 2004-08-25 22:01:55 -07:00 +++ b/arch/ppc/platforms/85xx/mpc8540_ads.c 2004-08-25 22:01:55 -07:00 @@ -120,10 +120,6 @@ mpc85xx_setup_hose(); #endif -#ifdef CONFIG_DUMMY_CONSOLE - conswitchp = &dummy_con; -#endif - #ifdef CONFIG_SERIAL_8250 mpc85xx_early_serial_map(); #endif diff -Nru a/arch/ppc/platforms/85xx/mpc85xx_cds_common.c b/arch/ppc/platforms/85xx/mpc85xx_cds_common.c --- a/arch/ppc/platforms/85xx/mpc85xx_cds_common.c 2004-08-25 22:01:56 -07:00 +++ b/arch/ppc/platforms/85xx/mpc85xx_cds_common.c 2004-08-25 22:01:56 -07:00 @@ -358,10 +358,6 @@ mpc85xx_setup_hose(); #endif -#ifdef CONFIG_DUMMY_CONSOLE - conswitchp = &dummy_con; -#endif - #ifdef CONFIG_SERIAL_8250 mpc85xx_early_serial_map(); #endif diff -Nru a/arch/ppc/platforms/85xx/sbc8560.c b/arch/ppc/platforms/85xx/sbc8560.c --- a/arch/ppc/platforms/85xx/sbc8560.c 2004-08-25 22:01:54 -07:00 +++ b/arch/ppc/platforms/85xx/sbc8560.c 2004-08-25 22:01:54 -07:00 @@ -144,9 +144,6 @@ /* setup PCI host bridges */ mpc85xx_setup_hose(); #endif -#ifdef CONFIG_DUMMY_CONSOLE - conswitchp = &dummy_con; -#endif #ifdef CONFIG_SERIAL_8250 sbc8560_early_serial_map(); #endif diff -Nru a/arch/ppc/platforms/Makefile b/arch/ppc/platforms/Makefile --- a/arch/ppc/platforms/Makefile 2004-08-25 22:01:56 -07:00 +++ b/arch/ppc/platforms/Makefile 2004-08-25 22:01:56 -07:00 @@ -21,23 +21,21 @@ obj-$(CONFIG_PMAC_BACKLIGHT) += pmac_backlight.o obj-$(CONFIG_PREP_RESIDUAL) += residual.o obj-$(CONFIG_ADIR) += adir_setup.o adir_pic.o adir_pci.o -obj-$(CONFIG_EST8260) += est8260_setup.o -obj-$(CONFIG_PQ2ADS) += pq2ads_setup.o +obj-$(CONFIG_PQ2ADS) += pq2ads.o obj-$(CONFIG_TQM8260) += tqm8260_setup.o obj-$(CONFIG_EV64260) += ev64260_setup.o obj-$(CONFIG_GEMINI) += gemini_pci.o gemini_setup.o gemini_prom.o obj-$(CONFIG_K2) += k2.o -obj-$(CONFIG_LOPEC) += lopec_setup.o lopec_pci.o +obj-$(CONFIG_LOPEC) += lopec.o obj-$(CONFIG_MCPN765) += mcpn765.o obj-$(CONFIG_MENF1) += menf1_setup.o menf1_pci.o -obj-$(CONFIG_MVME5100) += mvme5100_setup.o mvme5100_pci.o +obj-$(CONFIG_MVME5100) += mvme5100.o obj-$(CONFIG_PAL4) += pal4_setup.o pal4_pci.o obj-$(CONFIG_PCORE) += pcore.o obj-$(CONFIG_POWERPMC250) += powerpmc250.o obj-$(CONFIG_PPLUS) += pplus.o obj-$(CONFIG_PRPMC750) += prpmc750.o obj-$(CONFIG_PRPMC800) += prpmc800.o -obj-$(CONFIG_RPX8260) += rpx8260.o obj-$(CONFIG_SANDPOINT) += sandpoint.o obj-$(CONFIG_SBC82xx) += sbc82xx.o obj-$(CONFIG_SPRUCE) += spruce.o diff -Nru a/arch/ppc/platforms/chrp_setup.c b/arch/ppc/platforms/chrp_setup.c --- a/arch/ppc/platforms/chrp_setup.c 2004-08-25 22:01:56 -07:00 +++ b/arch/ppc/platforms/chrp_setup.c 2004-08-25 22:01:56 -07:00 @@ -250,13 +250,6 @@ */ sio_init(); - /* - * Setup the console operations - */ -#ifdef CONFIG_DUMMY_CONSOLE - conswitchp = &dummy_con; -#endif - /* Get the event scan rate for the rtas so we know how * often it expects a heartbeat. -- Cort */ diff -Nru a/arch/ppc/platforms/est8260.h b/arch/ppc/platforms/est8260.h --- a/arch/ppc/platforms/est8260.h 2004-08-25 22:01:56 -07:00 +++ b/arch/ppc/platforms/est8260.h 2004-08-25 22:01:56 -07:00 @@ -10,6 +10,9 @@ #define BOOTROM_RESTART_ADDR ((uint)0xff000104) +/* For our show_cpuinfo hooks. */ +#define CPUINFO_VENDOR "EST Corporation" +#define CPUINFO_MACHINE "SBC8260 PowerPC" /* A Board Information structure that is given to a program when * prom starts it up. diff -Nru a/arch/ppc/platforms/est8260_setup.c b/arch/ppc/platforms/est8260_setup.c --- a/arch/ppc/platforms/est8260_setup.c 2004-08-25 22:01:54 -07:00 +++ /dev/null Wed Dec 31 16:00:00 196900 @@ -1,65 +0,0 @@ -/* - * arch/ppc/platforms/est8260_setup.c - * - * EST8260 platform support - * - * Author: Allen Curtis - * Derived from: m8260_setup.c by Dan Malek, MVista - * - * Copyright 2002 Ones and Zeros, Inc. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - */ - -#include -#include - -#include -#include - -static void (*callback_setup_arch)(void); - -extern unsigned char __res[sizeof(bd_t)]; - -extern void m8260_init(unsigned long r3, unsigned long r4, - unsigned long r5, unsigned long r6, unsigned long r7); - -static int -est8260_show_cpuinfo(struct seq_file *m) -{ - bd_t *binfo = (bd_t *)__res; - - seq_printf(m, "vendor\t\t: EST Corporation\n" - "machine\t\t: SBC8260 PowerPC\n" - "\n" - "mem size\t\t: 0x%08x\n" - "console baud\t\t: %d\n" - "\n", - binfo->bi_memsize, - binfo->bi_baudrate); - return 0; -} - -static void __init -est8260_setup_arch(void) -{ - printk("EST SBC8260 Port\n"); - callback_setup_arch(); -} - -void __init -platform_init(unsigned long r3, unsigned long r4, unsigned long r5, - unsigned long r6, unsigned long r7) -{ - /* Generic 8260 platform initialization */ - m8260_init(r3, r4, r5, r6, r7); - - /* Anything special for this platform */ - ppc_md.show_cpuinfo = est8260_show_cpuinfo; - - callback_setup_arch = ppc_md.setup_arch; - ppc_md.setup_arch = est8260_setup_arch; -} diff -Nru a/arch/ppc/platforms/k2.c b/arch/ppc/platforms/k2.c --- a/arch/ppc/platforms/k2.c 2004-08-25 22:01:54 -07:00 +++ b/arch/ppc/platforms/k2.c 2004-08-25 22:01:54 -07:00 @@ -464,10 +464,6 @@ ROOT_DEV = Root_HDC1; #endif -#ifdef CONFIG_DUMMY_CONSOLE - conswitchp = &dummy_con; -#endif - /* Identify the system */ printk(KERN_INFO "System Identification: SBS K2 - PowerPC 750 @ " "%d Mhz\n", k2_get_cpu_speed() / 1000000); diff -Nru a/arch/ppc/platforms/lopec.c b/arch/ppc/platforms/lopec.c --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/arch/ppc/platforms/lopec.c 2004-08-25 22:01:55 -07:00 @@ -0,0 +1,410 @@ +/* + * arch/ppc/platforms/lopec.c + * + * Setup routines for the Motorola LoPEC. + * + * Author: Dan Cox + * Maintainer: Tom Rini + * + * 2001-2004 (c) MontaVista, Software, Inc. This file is licensed under + * the terms of the GNU General Public License version 2. This program + * is licensed "as is" without any warranty of any kind, whether express + * or implied. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Define all of the IRQ senses and polarities. Taken from the + * LoPEC Programmer's Reference Guide. + */ +static u_char lopec_openpic_initsenses[16] __initdata = { + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* IRQ 0 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* IRQ 1 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* IRQ 2 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* IRQ 3 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* IRQ 4 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* IRQ 5 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* IRQ 6 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* IRQ 7 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* IRQ 8 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* IRQ 9 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* IRQ 10 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* IRQ 11 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* IRQ 12 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* IRQ 13 */ + (IRQ_SENSE_EDGE | IRQ_POLARITY_NEGATIVE), /* IRQ 14 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE) /* IRQ 15 */ +}; + +static inline int __init +lopec_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin) +{ + int irq; + static char pci_irq_table[][4] = { + {16, 0, 0, 0}, /* ID 11 - Winbond */ + {22, 0, 0, 0}, /* ID 12 - SCSI */ + {0, 0, 0, 0}, /* ID 13 - nothing */ + {17, 0, 0, 0}, /* ID 14 - 82559 Ethernet */ + {27, 0, 0, 0}, /* ID 15 - USB */ + {23, 0, 0, 0}, /* ID 16 - PMC slot 1 */ + {24, 0, 0, 0}, /* ID 17 - PMC slot 2 */ + {25, 0, 0, 0}, /* ID 18 - PCI slot */ + {0, 0, 0, 0}, /* ID 19 - nothing */ + {0, 0, 0, 0}, /* ID 20 - nothing */ + {0, 0, 0, 0}, /* ID 21 - nothing */ + {0, 0, 0, 0}, /* ID 22 - nothing */ + {0, 0, 0, 0}, /* ID 23 - nothing */ + {0, 0, 0, 0}, /* ID 24 - PMC slot 1b */ + {0, 0, 0, 0}, /* ID 25 - nothing */ + {0, 0, 0, 0} /* ID 26 - PMC Slot 2b */ + }; + const long min_idsel = 11, max_idsel = 26, irqs_per_slot = 4; + + irq = PCI_IRQ_TABLE_LOOKUP; + if (!irq) + return 0; + + return irq; +} + +static void __init +lopec_setup_winbond_83553(struct pci_controller *hose) +{ + int devfn; + + devfn = PCI_DEVFN(11,0); + + /* IDE interrupt routing (primary 14, secondary 15) */ + early_write_config_byte(hose, 0, devfn, 0x43, 0xef); + /* PCI interrupt routing */ + early_write_config_word(hose, 0, devfn, 0x44, 0x0000); + + /* ISA-PCI address decoder */ + early_write_config_byte(hose, 0, devfn, 0x48, 0xf0); + + /* RTC, kb, not used in PPC */ + early_write_config_byte(hose, 0, devfn, 0x4d, 0x00); + early_write_config_byte(hose, 0, devfn, 0x4e, 0x04); + devfn = PCI_DEVFN(11, 1); + early_write_config_byte(hose, 0, devfn, 0x09, 0x8f); + early_write_config_dword(hose, 0, devfn, 0x40, 0x00ff0011); +} + +static void __init +lopec_find_bridges(void) +{ + struct pci_controller *hose; + + hose = pcibios_alloc_controller(); + if (!hose) + return; + + hose->first_busno = 0; + hose->last_busno = 0xff; + + if (mpc10x_bridge_init(hose, MPC10X_MEM_MAP_B, MPC10X_MEM_MAP_B, + MPC10X_MAPB_EUMB_BASE) == 0) { + + hose->mem_resources[0].end = 0xffffffff; + lopec_setup_winbond_83553(hose); + hose->last_busno = pciauto_bus_scan(hose, hose->first_busno); + ppc_md.pci_swizzle = common_swizzle; + ppc_md.pci_map_irq = lopec_map_irq; + } +} + +static int +lopec_show_cpuinfo(struct seq_file *m) +{ + seq_printf(m, "machine\t\t: Motorola LoPEC\n"); + return 0; +} + +static u32 +lopec_irq_canonicalize(u32 irq) +{ + if (irq == 2) + return 9; + else + return irq; +} + +static void +lopec_restart(char *cmd) +{ +#define LOPEC_SYSSTAT1 0xffe00000 + /* force a hard reset, if possible */ + unsigned char reg = *((unsigned char *) LOPEC_SYSSTAT1); + reg |= 0x80; + *((unsigned char *) LOPEC_SYSSTAT1) = reg; + + local_irq_disable(); + while(1); +#undef LOPEC_SYSSTAT1 +} + +static void +lopec_halt(void) +{ + local_irq_disable(); + while(1); +} + +static void +lopec_power_off(void) +{ + lopec_halt(); +} + +#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) +int lopec_ide_ports_known = 0; +static unsigned long lopec_ide_regbase[MAX_HWIFS]; +static unsigned long lopec_ide_ctl_regbase[MAX_HWIFS]; +static unsigned long lopec_idedma_regbase; + +static void +lopec_ide_probe(void) +{ + struct pci_dev *dev = pci_find_device(PCI_VENDOR_ID_WINBOND, + PCI_DEVICE_ID_WINBOND_82C105, + NULL); + lopec_ide_ports_known = 1; + + if (dev) { + lopec_ide_regbase[0] = dev->resource[0].start; + lopec_ide_regbase[1] = dev->resource[2].start; + lopec_ide_ctl_regbase[0] = dev->resource[1].start; + lopec_ide_ctl_regbase[1] = dev->resource[3].start; + lopec_idedma_regbase = dev->resource[4].start; + } +} + +static int +lopec_ide_default_irq(unsigned long base) +{ + if (lopec_ide_ports_known == 0) + lopec_ide_probe(); + + if (base == lopec_ide_regbase[0]) + return 14; + else if (base == lopec_ide_regbase[1]) + return 15; + else + return 0; +} + +static unsigned long +lopec_ide_default_io_base(int index) +{ + if (lopec_ide_ports_known == 0) + lopec_ide_probe(); + return lopec_ide_regbase[index]; +} + +static void __init +lopec_ide_init_hwif_ports(hw_regs_t *hw, unsigned long data, + unsigned long ctl, int *irq) +{ + unsigned long reg = data; + uint alt_status_base; + int i; + + for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) + hw->io_ports[i] = reg++; + + if (data == lopec_ide_regbase[0]) { + alt_status_base = lopec_ide_ctl_regbase[0] + 2; + hw->irq = 14; + } else if (data == lopec_ide_regbase[1]) { + alt_status_base = lopec_ide_ctl_regbase[1] + 2; + hw->irq = 15; + } else { + alt_status_base = 0; + hw->irq = 0; + } + + if (ctl) + hw->io_ports[IDE_CONTROL_OFFSET] = ctl; + else + hw->io_ports[IDE_CONTROL_OFFSET] = alt_status_base; + + if (irq != NULL) + *irq = hw->irq; + +} +#endif /* BLK_DEV_IDE */ + +static void __init +lopec_init_IRQ(void) +{ + int i; + + /* + * Provide the open_pic code with the correct table of interrupts. + */ + OpenPIC_InitSenses = lopec_openpic_initsenses; + OpenPIC_NumInitSenses = sizeof(lopec_openpic_initsenses); + + mpc10x_set_openpic(); + + /* We have a cascade on OpenPIC IRQ 0, Linux IRQ 16 */ + openpic_hookup_cascade(NUM_8259_INTERRUPTS, "82c59 cascade", + &i8259_irq); + + /* Map i8259 interrupts */ + for(i = 0; i < NUM_8259_INTERRUPTS; i++) + irq_desc[i].handler = &i8259_pic; + + /* + * The EPIC allows for a read in the range of 0xFEF00000 -> + * 0xFEFFFFFF to generate a PCI interrupt-acknowledge transaction. + */ + i8259_init(0xfef00000); +} + +static int __init +lopec_request_io(void) +{ + outb(0x00, 0x4d0); + outb(0xc0, 0x4d1); + + request_region(0x00, 0x20, "dma1"); + request_region(0x20, 0x20, "pic1"); + request_region(0x40, 0x20, "timer"); + request_region(0x80, 0x10, "dma page reg"); + request_region(0xa0, 0x20, "pic2"); + request_region(0xc0, 0x20, "dma2"); + + return 0; +} + +device_initcall(lopec_request_io); + +static void __init +lopec_map_io(void) +{ + io_block_mapping(0xf0000000, 0xf0000000, 0x10000000, _PAGE_IO); + io_block_mapping(0xb0000000, 0xb0000000, 0x10000000, _PAGE_IO); +} + +/* + * Set BAT 3 to map 0xf8000000 to end of physical memory space 1-to-1. + */ +static __inline__ void +lopec_set_bat(void) +{ + mb(); + mtspr(DBAT1U, 0xf8000ffe); + mtspr(DBAT1L, 0xf800002a); + mb(); +} + +TODC_ALLOC(); + +static void __init +lopec_setup_arch(void) +{ + + TODC_INIT(TODC_TYPE_MK48T37, 0, 0, + ioremap(0xffe80000, 0x8000), 8); + + loops_per_jiffy = 100000000/HZ; + + lopec_find_bridges(); + +#ifdef CONFIG_BLK_DEV_INITRD + if (initrd_start) + ROOT_DEV = Root_RAM0; + else +#elif defined(CONFIG_ROOT_NFS) + ROOT_DEV = Root_NFS; +#elif defined(CONFIG_BLK_DEV_IDEDISK) + ROOT_DEV = Root_HDA1; +#else + ROOT_DEV = Root_SDA1; +#endif + +#ifdef CONFIG_PPCBUG_NVRAM + /* Read in NVRAM data */ + init_prep_nvram(); + + /* if no bootargs, look in NVRAM */ + if ( cmd_line[0] == '\0' ) { + char *bootargs; + bootargs = prep_nvram_get_var("bootargs"); + if (bootargs != NULL) { + strcpy(cmd_line, bootargs); + /* again.. */ + strcpy(saved_command_line, cmd_line); + } + } +#endif +} + +void __init +platform_init(unsigned long r3, unsigned long r4, unsigned long r5, + unsigned long r6, unsigned long r7) +{ + parse_bootinfo(find_bootinfo()); + lopec_set_bat(); + + isa_io_base = MPC10X_MAPB_ISA_IO_BASE; + isa_mem_base = MPC10X_MAPB_ISA_MEM_BASE; + pci_dram_offset = MPC10X_MAPB_DRAM_OFFSET; + ISA_DMA_THRESHOLD = 0x00ffffff; + DMA_MODE_READ = 0x44; + DMA_MODE_WRITE = 0x48; + + ppc_md.setup_arch = lopec_setup_arch; + ppc_md.show_cpuinfo = lopec_show_cpuinfo; + ppc_md.irq_canonicalize = lopec_irq_canonicalize; + ppc_md.init_IRQ = lopec_init_IRQ; + ppc_md.get_irq = openpic_get_irq; + + ppc_md.restart = lopec_restart; + ppc_md.power_off = lopec_power_off; + ppc_md.halt = lopec_halt; + + ppc_md.setup_io_mappings = lopec_map_io; + + ppc_md.time_init = todc_time_init; + ppc_md.set_rtc_time = todc_set_rtc_time; + ppc_md.get_rtc_time = todc_get_rtc_time; + ppc_md.calibrate_decr = todc_calibrate_decr; + + ppc_md.nvram_read_val = todc_direct_read_val; + ppc_md.nvram_write_val = todc_direct_write_val; + +#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) + ppc_ide_md.default_irq = lopec_ide_default_irq; + ppc_ide_md.default_io_base = lopec_ide_default_io_base; + ppc_ide_md.ide_init_hwif = lopec_ide_init_hwif_ports; +#endif +#ifdef CONFIG_SERIAL_TEXT_DEBUG + ppc_md.progress = gen550_progress; +#endif +} diff -Nru a/arch/ppc/platforms/lopec.h b/arch/ppc/platforms/lopec.h --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/arch/ppc/platforms/lopec.h 2004-08-25 22:01:56 -07:00 @@ -0,0 +1,39 @@ +/* + * include/asm-ppc/lopec_serial.h + * + * Definitions for Motorola LoPEC board. + * + * Author: Dan Cox + * danc@mvista.com (or, alternately, source@mvista.com) + * + * 2001 (c) MontaVista, Software, Inc. This file is licensed under + * the terms of the GNU General Public License version 2. This program + * is licensed "as is" without any warranty of any kind, whether express + * or implied. + */ + +#ifndef __H_LOPEC_SERIAL +#define __H_LOPEC_SERIAL + +#define RS_TABLE_SIZE 3 + +#define BASE_BAUD (1843200 / 16) + +#ifdef CONFIG_SERIAL_DETECT_IRQ +#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_SKIP_TEST|ASYNC_AUTO_IRQ) +#else +#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_SKIP_TEST) +#endif + +#define SERIAL_PORT_DFNS \ + { 0, BASE_BAUD, 0xffe10000, 29, STD_COM_FLAGS, \ + iomem_base: (u8 *) 0xffe10000, \ + io_type: SERIAL_IO_MEM }, \ + { 0, BASE_BAUD, 0xffe11000, 20, STD_COM_FLAGS, \ + iomem_base: (u8 *) 0xffe11000, \ + io_type: SERIAL_IO_MEM }, \ + { 0, BASE_BAUD, 0xffe12000, 21, STD_COM_FLAGS, \ + iomem_base: (u8 *) 0xffe12000, \ + io_type: SERIAL_IO_MEM } + +#endif diff -Nru a/arch/ppc/platforms/lopec_pci.c b/arch/ppc/platforms/lopec_pci.c --- a/arch/ppc/platforms/lopec_pci.c 2004-08-25 22:01:55 -07:00 +++ /dev/null Wed Dec 31 16:00:00 196900 @@ -1,99 +0,0 @@ -/* - * arch/ppc/platforms/lopec_pci.c - * - * PCI setup routines for the Motorola LoPEC. - * - * Author: Dan Cox - * danc@mvista.com (or, alternately, source@mvista.com) - * - * 2001-2002 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2. This program - * is licensed "as is" without any warranty of any kind, whether express - * or implied. - */ - -#include -#include - -#include -#include -#include - -static inline int __init -lopec_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin) -{ - int irq; - static char pci_irq_table[][4] = { - {16, 0, 0, 0}, /* ID 11 - Winbond */ - {22, 0, 0, 0}, /* ID 12 - SCSI */ - {0, 0, 0, 0}, /* ID 13 - nothing */ - {17, 0, 0, 0}, /* ID 14 - 82559 Ethernet */ - {27, 0, 0, 0}, /* ID 15 - USB */ - {23, 0, 0, 0}, /* ID 16 - PMC slot 1 */ - {24, 0, 0, 0}, /* ID 17 - PMC slot 2 */ - {25, 0, 0, 0}, /* ID 18 - PCI slot */ - {0, 0, 0, 0}, /* ID 19 - nothing */ - {0, 0, 0, 0}, /* ID 20 - nothing */ - {0, 0, 0, 0}, /* ID 21 - nothing */ - {0, 0, 0, 0}, /* ID 22 - nothing */ - {0, 0, 0, 0}, /* ID 23 - nothing */ - {0, 0, 0, 0}, /* ID 24 - PMC slot 1b */ - {0, 0, 0, 0}, /* ID 25 - nothing */ - {0, 0, 0, 0} /* ID 26 - PMC Slot 2b */ - }; - const long min_idsel = 11, max_idsel = 26, irqs_per_slot = 4; - - irq = PCI_IRQ_TABLE_LOOKUP; - if (!irq) - return 0; - - return irq; -} - -void __init -lopec_setup_winbond_83553(struct pci_controller *hose) -{ - int devfn; - - devfn = PCI_DEVFN(11,0); - - /* IDE interrupt routing (primary 14, secondary 15) */ - early_write_config_byte(hose, 0, devfn, 0x43, 0xef); - /* PCI interrupt routing */ - early_write_config_word(hose, 0, devfn, 0x44, 0x0000); - - /* ISA-PCI address decoder */ - early_write_config_byte(hose, 0, devfn, 0x48, 0xf0); - - /* RTC, kb, not used in PPC */ - early_write_config_byte(hose, 0, devfn, 0x4d, 0x00); - early_write_config_byte(hose, 0, devfn, 0x4e, 0x04); - devfn = PCI_DEVFN(11, 1); - early_write_config_byte(hose, 0, devfn, 0x09, 0x8f); - early_write_config_dword(hose, 0, devfn, 0x40, 0x00ff0011); -} - -void __init -lopec_find_bridges(void) -{ - struct pci_controller *hose; - - hose = pcibios_alloc_controller(); - if (!hose) - return; - - hose->first_busno = 0; - hose->last_busno = 0xff; - - if (mpc10x_bridge_init(hose, - MPC10X_MEM_MAP_B, - MPC10X_MEM_MAP_B, - MPC10X_MAPB_EUMB_BASE) == 0) { - - hose->mem_resources[0].end = 0xffffffff; - lopec_setup_winbond_83553(hose); - hose->last_busno = pciauto_bus_scan(hose, hose->first_busno); - ppc_md.pci_swizzle = common_swizzle; - ppc_md.pci_map_irq = lopec_map_irq; - } -} diff -Nru a/arch/ppc/platforms/lopec_serial.h b/arch/ppc/platforms/lopec_serial.h --- a/arch/ppc/platforms/lopec_serial.h 2004-08-25 22:01:56 -07:00 +++ /dev/null Wed Dec 31 16:00:00 196900 @@ -1,39 +0,0 @@ -/* - * include/asm-ppc/lopec_serial.h - * - * Definitions for Motorola LoPEC board. - * - * Author: Dan Cox - * danc@mvista.com (or, alternately, source@mvista.com) - * - * 2001 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2. This program - * is licensed "as is" without any warranty of any kind, whether express - * or implied. - */ - -#ifndef __H_LOPEC_SERIAL -#define __H_LOPEC_SERIAL - -#define RS_TABLE_SIZE 3 - -#define BASE_BAUD (1843200 / 16) - -#ifdef CONFIG_SERIAL_DETECT_IRQ -#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_SKIP_TEST|ASYNC_AUTO_IRQ) -#else -#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_SKIP_TEST) -#endif - -#define SERIAL_PORT_DFNS \ - { 0, BASE_BAUD, 0xffe10000, 29, STD_COM_FLAGS, \ - iomem_base: (u8 *) 0xffe10000, \ - io_type: SERIAL_IO_MEM }, \ - { 0, BASE_BAUD, 0xffe11000, 20, STD_COM_FLAGS, \ - iomem_base: (u8 *) 0xffe11000, \ - io_type: SERIAL_IO_MEM }, \ - { 0, BASE_BAUD, 0xffe12000, 21, STD_COM_FLAGS, \ - iomem_base: (u8 *) 0xffe12000, \ - io_type: SERIAL_IO_MEM } - -#endif diff -Nru a/arch/ppc/platforms/lopec_setup.c b/arch/ppc/platforms/lopec_setup.c --- a/arch/ppc/platforms/lopec_setup.c 2004-08-25 22:01:55 -07:00 +++ /dev/null Wed Dec 31 16:00:00 196900 @@ -1,378 +0,0 @@ -/* - * arch/ppc/platforms/lopec_setup.c - * - * Setup routines for the Motorola LoPEC. - * - * Author: Dan Cox - * danc@mvista.com - * - * 2001-2002 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2. This program - * is licensed "as is" without any warranty of any kind, whether express - * or implied. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -extern void lopec_find_bridges(void); - -/* - * Define all of the IRQ senses and polarities. Taken from the - * LoPEC Programmer's Reference Guide. - */ -static u_char lopec_openpic_initsenses[16] __initdata = { - (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* IRQ 0 */ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* IRQ 1 */ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* IRQ 2 */ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* IRQ 3 */ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* IRQ 4 */ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* IRQ 5 */ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* IRQ 6 */ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* IRQ 7 */ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* IRQ 8 */ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* IRQ 9 */ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* IRQ 10 */ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* IRQ 11 */ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* IRQ 12 */ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* IRQ 13 */ - (IRQ_SENSE_EDGE | IRQ_POLARITY_NEGATIVE), /* IRQ 14 */ - (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE) /* IRQ 15 */ -}; - -static int -lopec_show_cpuinfo(struct seq_file *m) -{ - seq_printf(m, "machine\t\t: Motorola LoPEC\n"); - return 0; -} - -static u32 -lopec_irq_canonicalize(u32 irq) -{ - if (irq == 2) - return 9; - else - return irq; -} - -static void -lopec_restart(char *cmd) -{ -#define LOPEC_SYSSTAT1 0xffe00000 - /* force a hard reset, if possible */ - unsigned char reg = *((unsigned char *) LOPEC_SYSSTAT1); - reg |= 0x80; - *((unsigned char *) LOPEC_SYSSTAT1) = reg; - - local_irq_disable(); - while(1); -#undef LOPEC_SYSSTAT1 -} - -static void -lopec_halt(void) -{ - local_irq_disable(); - while(1); -} - -static void -lopec_power_off(void) -{ - lopec_halt(); -} - -#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) -int lopec_ide_ports_known = 0; -static unsigned long lopec_ide_regbase[MAX_HWIFS]; -static unsigned long lopec_ide_ctl_regbase[MAX_HWIFS]; -static unsigned long lopec_idedma_regbase; - -static void -lopec_ide_probe(void) -{ - struct pci_dev *dev = pci_find_device(PCI_VENDOR_ID_WINBOND, - PCI_DEVICE_ID_WINBOND_82C105, - NULL); - lopec_ide_ports_known = 1; - - if (dev) { - lopec_ide_regbase[0] = dev->resource[0].start; - lopec_ide_regbase[1] = dev->resource[2].start; - lopec_ide_ctl_regbase[0] = dev->resource[1].start; - lopec_ide_ctl_regbase[1] = dev->resource[3].start; - lopec_idedma_regbase = dev->resource[4].start; - } -} - -static int -lopec_ide_default_irq(unsigned long base) -{ - if (lopec_ide_ports_known == 0) - lopec_ide_probe(); - - if (base == lopec_ide_regbase[0]) - return 14; - else if (base == lopec_ide_regbase[1]) - return 15; - else - return 0; -} - -static unsigned long -lopec_ide_default_io_base(int index) -{ - if (lopec_ide_ports_known == 0) - lopec_ide_probe(); - return lopec_ide_regbase[index]; -} - -static void __init -lopec_ide_init_hwif_ports(hw_regs_t *hw, unsigned long data, - unsigned long ctl, int *irq) -{ - unsigned long reg = data; - uint alt_status_base; - int i; - - for(i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) - hw->io_ports[i] = reg++; - - if (data == lopec_ide_regbase[0]) { - alt_status_base = lopec_ide_ctl_regbase[0] + 2; - hw->irq = 14; - } - else if (data == lopec_ide_regbase[1]) { - alt_status_base = lopec_ide_ctl_regbase[1] + 2; - hw->irq = 15; - } - else { - alt_status_base = 0; - hw->irq = 0; - } - - if (ctl) - hw->io_ports[IDE_CONTROL_OFFSET] = ctl; - else - hw->io_ports[IDE_CONTROL_OFFSET] = alt_status_base; - - if (irq != NULL) - *irq = hw->irq; - -} -#endif /* BLK_DEV_IDE */ - -static void __init -lopec_init_IRQ(void) -{ - int i; - - /* - * Provide the open_pic code with the correct table of interrupts. - */ - OpenPIC_InitSenses = lopec_openpic_initsenses; - OpenPIC_NumInitSenses = sizeof(lopec_openpic_initsenses); - - mpc10x_set_openpic(); - - /* We have a cascade on OpenPIC IRQ 0, Linux IRQ 16 */ - openpic_hookup_cascade(NUM_8259_INTERRUPTS, "82c59 cascade", - &i8259_irq); - - /* Map i8259 interrupts */ - for(i = 0; i < NUM_8259_INTERRUPTS; i++) - irq_desc[i].handler = &i8259_pic; - - /* - * The EPIC allows for a read in the range of 0xFEF00000 -> - * 0xFEFFFFFF to generate a PCI interrupt-acknowledge transaction. - */ - i8259_init(0xfef00000); -} - -static int __init -lopec_request_io(void) -{ - outb(0x00, 0x4d0); - outb(0xc0, 0x4d1); - - request_region(0x00, 0x20, "dma1"); - request_region(0x20, 0x20, "pic1"); - request_region(0x40, 0x20, "timer"); - request_region(0x80, 0x10, "dma page reg"); - request_region(0xa0, 0x20, "pic2"); - request_region(0xc0, 0x20, "dma2"); - - return 0; -} - -device_initcall(lopec_request_io); - -static void __init -lopec_map_io(void) -{ - io_block_mapping(0xf0000000, 0xf0000000, 0x10000000, _PAGE_IO); - io_block_mapping(0xb0000000, 0xb0000000, 0x10000000, _PAGE_IO); -} - -static void __init -lopec_set_bat(void) -{ - unsigned long batu, batl; - - __asm__ __volatile__( - "lis %0,0xf800\n \ - ori %1,%0,0x002a\n \ - ori %0,%0,0x0ffe\n \ - mtspr 0x21e,%0\n \ - mtspr 0x21f,%1\n \ - isync\n \ - sync " - : "=r" (batu), "=r" (batl)); -} - -#ifdef CONFIG_SERIAL_TEXT_DEBUG -#include -#include -#include -#include - -static struct serial_state rs_table[RS_TABLE_SIZE] = { - SERIAL_PORT_DFNS /* Defined in */ -}; - -volatile unsigned char *com_port; -volatile unsigned char *com_port_lsr; - -static void -serial_writechar(char c) -{ - while ((*com_port_lsr & UART_LSR_THRE) == 0) - ; - *com_port = c; -} - -void -lopec_progress(char *s, unsigned short hex) -{ - volatile char c; - - com_port = (volatile unsigned char *) rs_table[0].port; - com_port_lsr = com_port + UART_LSR; - - while ((c = *s++) != 0) - serial_writechar(c); - - /* Most messages don't have a newline in them */ - serial_writechar('\n'); - serial_writechar('\r'); -} -#endif /* CONFIG_SERIAL_TEXT_DEBUG */ - -TODC_ALLOC(); - -static void __init -lopec_setup_arch(void) -{ - - TODC_INIT(TODC_TYPE_MK48T37, 0, 0, - ioremap(0xffe80000, 0x8000), 8); - - loops_per_jiffy = 100000000/HZ; - - lopec_find_bridges(); - -#ifdef CONFIG_BLK_DEV_INITRD - if (initrd_start) - ROOT_DEV = Root_RAM0; - else -#elif defined(CONFIG_ROOT_NFS) - ROOT_DEV = Root_NFS; -#elif defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) - ROOT_DEV = Root_HDA1; -#else - ROOT_DEV = Root_SDA1; -#endif - -#ifdef CONFIG_VT - conswitchp = &dummy_con; -#endif -#ifdef CONFIG_PPCBUG_NVRAM - /* Read in NVRAM data */ - init_prep_nvram(); - - /* if no bootargs, look in NVRAM */ - if ( cmd_line[0] == '\0' ) { - char *bootargs; - bootargs = prep_nvram_get_var("bootargs"); - if (bootargs != NULL) { - strcpy(cmd_line, bootargs); - /* again.. */ - strcpy(saved_command_line, cmd_line); - } - } -#endif -} - -void __init -platform_init(unsigned long r3, unsigned long r4, unsigned long r5, - unsigned long r6, unsigned long r7) -{ - parse_bootinfo(find_bootinfo()); - lopec_set_bat(); - - isa_io_base = MPC10X_MAPB_ISA_IO_BASE; - isa_mem_base = MPC10X_MAPB_ISA_MEM_BASE; - pci_dram_offset = MPC10X_MAPB_DRAM_OFFSET; - ISA_DMA_THRESHOLD = 0x00ffffff; - DMA_MODE_READ = 0x44; - DMA_MODE_WRITE = 0x48; - - ppc_md.setup_arch = lopec_setup_arch; - ppc_md.show_cpuinfo = lopec_show_cpuinfo; - ppc_md.irq_canonicalize = lopec_irq_canonicalize; - ppc_md.init_IRQ = lopec_init_IRQ; - ppc_md.get_irq = openpic_get_irq; - - ppc_md.restart = lopec_restart; - ppc_md.power_off = lopec_power_off; - ppc_md.halt = lopec_halt; - - ppc_md.setup_io_mappings = lopec_map_io; - - ppc_md.time_init = todc_time_init; - ppc_md.set_rtc_time = todc_set_rtc_time; - ppc_md.get_rtc_time = todc_get_rtc_time; - ppc_md.calibrate_decr = todc_calibrate_decr; - - ppc_md.nvram_read_val = todc_direct_read_val; - ppc_md.nvram_write_val = todc_direct_write_val; - -#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) - ppc_ide_md.default_irq = lopec_ide_default_irq; - ppc_ide_md.default_io_base = lopec_ide_default_io_base; - ppc_ide_md.ide_init_hwif = lopec_ide_init_hwif_ports; -#endif -#ifdef CONFIG_SERIAL_TEXT_DEBUG - ppc_md.progress = lopec_progress; -#endif -} diff -Nru a/arch/ppc/platforms/mcpn765.c b/arch/ppc/platforms/mcpn765.c --- a/arch/ppc/platforms/mcpn765.c 2004-08-25 22:01:55 -07:00 +++ b/arch/ppc/platforms/mcpn765.c 2004-08-25 22:01:55 -07:00 @@ -58,8 +58,6 @@ #include #include "mcpn765.h" -#include "mcpn765_serial.h" - static u_char mcpn765_openpic_initsenses[] __initdata = { (IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE),/* 16: i8259 cascade */ @@ -322,10 +320,6 @@ ROOT_DEV = Root_NFS; #else ROOT_DEV = Root_SDA2; -#endif - -#ifdef CONFIG_DUMMY_CONSOLE - conswitchp = &dummy_con; #endif if ( ppc_md.progress ) diff -Nru a/arch/ppc/platforms/mcpn765.h b/arch/ppc/platforms/mcpn765.h --- a/arch/ppc/platforms/mcpn765.h 2004-08-25 22:01:54 -07:00 +++ b/arch/ppc/platforms/mcpn765.h 2004-08-25 22:01:54 -07:00 @@ -6,7 +6,7 @@ * Author: Mark A. Greer * mgreer@mvista.com * - * 2001 (c) MontaVista, Software, Inc. This file is licensed under + * 2001-2004 (c) MontaVista, Software, Inc. This file is licensed under * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. @@ -25,6 +25,7 @@ #ifndef __PPC_PLATFORMS_MCPN765_H #define __PPC_PLATFORMS_MCPN765_H +#include /* PCI Memory space mapping info */ #define MCPN765_PCI_MEM_SIZE 0x40000000U @@ -65,13 +66,56 @@ #define MCPN765_BOARD_EXT_FEATURE_REG 0xfef880f0U #define MCPN765_BOARD_LAST_RESET_REG 0xfef880f8U -/* UART base addresses are defined in */ +/* Defines for UART */ + +/* Define the UART base addresses */ +#define MCPN765_SERIAL_1 0xfef88000 +#define MCPN765_SERIAL_2 0xfef88200 +#define MCPN765_SERIAL_3 0xfef88400 +#define MCPN765_SERIAL_4 0xfef88600 + +#ifdef CONFIG_SERIAL_MANY_PORTS +#define RS_TABLE_SIZE 64 +#else +#define RS_TABLE_SIZE 4 +#endif + +/* Rate for the 1.8432 Mhz clock for the onboard serial chip */ +#define BASE_BAUD ( 1843200 / 16 ) +#define UART_CLK 1843200 + +#ifdef CONFIG_SERIAL_DETECT_IRQ +#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_SKIP_TEST|ASYNC_AUTO_IRQ) +#else +#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_SKIP_TEST) +#endif + +/* All UART IRQ's are wire-OR'd to IRQ 17 */ +#define STD_SERIAL_PORT_DFNS \ + { 0, BASE_BAUD, MCPN765_SERIAL_1, 17, STD_COM_FLAGS, /* ttyS0 */\ + iomem_base: (u8 *)MCPN765_SERIAL_1, \ + iomem_reg_shift: 4, \ + io_type: SERIAL_IO_MEM }, \ + { 0, BASE_BAUD, MCPN765_SERIAL_2, 17, STD_COM_FLAGS, /* ttyS1 */\ + iomem_base: (u8 *)MCPN765_SERIAL_2, \ + iomem_reg_shift: 4, \ + io_type: SERIAL_IO_MEM }, \ + { 0, BASE_BAUD, MCPN765_SERIAL_3, 17, STD_COM_FLAGS, /* ttyS2 */\ + iomem_base: (u8 *)MCPN765_SERIAL_3, \ + iomem_reg_shift: 4, \ + io_type: SERIAL_IO_MEM }, \ + { 0, BASE_BAUD, MCPN765_SERIAL_4, 17, STD_COM_FLAGS, /* ttyS3 */\ + iomem_base: (u8 *)MCPN765_SERIAL_4, \ + iomem_reg_shift: 4, \ + io_type: SERIAL_IO_MEM }, + +#define SERIAL_PORT_DFNS \ + STD_SERIAL_PORT_DFNS /* Define the NVRAM/RTC address strobe & data registers */ #define MCPN765_PHYS_NVRAM_AS0 0xfef880c8U #define MCPN765_PHYS_NVRAM_AS1 0xfef880d0U #define MCPN765_PHYS_NVRAM_DATA 0xfef880d8U - extern void mcpn765_find_bridges(void); diff -Nru a/arch/ppc/platforms/mcpn765_serial.h b/arch/ppc/platforms/mcpn765_serial.h --- a/arch/ppc/platforms/mcpn765_serial.h 2004-08-25 22:01:56 -07:00 +++ /dev/null Wed Dec 31 16:00:00 196900 @@ -1,64 +0,0 @@ -/* - * include/asm-ppc/mcpn765_serial.h - * - * Definitions for Motorola MCG MCPN765 cPCI board support - * - * Author: Mark A. Greer - * mgreer@mvista.com - * - * 2001 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2. This program - * is licensed "as is" without any warranty of any kind, whether express - * or implied. - */ - -#ifndef __ASMPPC_MCPN765_SERIAL_H -#define __ASMPPC_MCPN765_SERIAL_H - -#include - -/* Define the UART base addresses */ -#define MCPN765_SERIAL_1 0xfef88000 -#define MCPN765_SERIAL_2 0xfef88200 -#define MCPN765_SERIAL_3 0xfef88400 -#define MCPN765_SERIAL_4 0xfef88600 - -#ifdef CONFIG_SERIAL_MANY_PORTS -#define RS_TABLE_SIZE 64 -#else -#define RS_TABLE_SIZE 4 -#endif - -/* Rate for the 1.8432 Mhz clock for the onboard serial chip */ -#define BASE_BAUD ( 1843200 / 16 ) -#define UART_CLK 1843200 - -#ifdef CONFIG_SERIAL_DETECT_IRQ -#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_SKIP_TEST|ASYNC_AUTO_IRQ) -#else -#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_SKIP_TEST) -#endif - -/* All UART IRQ's are wire-OR'd to IRQ 17 */ -#define STD_SERIAL_PORT_DFNS \ - { 0, BASE_BAUD, MCPN765_SERIAL_1, 17, STD_COM_FLAGS, /* ttyS0 */\ - iomem_base: (u8 *)MCPN765_SERIAL_1, \ - iomem_reg_shift: 4, \ - io_type: SERIAL_IO_MEM }, \ - { 0, BASE_BAUD, MCPN765_SERIAL_2, 17, STD_COM_FLAGS, /* ttyS1 */\ - iomem_base: (u8 *)MCPN765_SERIAL_2, \ - iomem_reg_shift: 4, \ - io_type: SERIAL_IO_MEM }, \ - { 0, BASE_BAUD, MCPN765_SERIAL_3, 17, STD_COM_FLAGS, /* ttyS2 */\ - iomem_base: (u8 *)MCPN765_SERIAL_3, \ - iomem_reg_shift: 4, \ - io_type: SERIAL_IO_MEM }, \ - { 0, BASE_BAUD, MCPN765_SERIAL_4, 17, STD_COM_FLAGS, /* ttyS3 */\ - iomem_base: (u8 *)MCPN765_SERIAL_4, \ - iomem_reg_shift: 4, \ - io_type: SERIAL_IO_MEM }, - -#define SERIAL_PORT_DFNS \ - STD_SERIAL_PORT_DFNS - -#endif /* __ASMPPC_MCPN765_SERIAL_H */ diff -Nru a/arch/ppc/platforms/mvme5100.c b/arch/ppc/platforms/mvme5100.c --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/arch/ppc/platforms/mvme5100.c 2004-08-25 22:01:55 -07:00 @@ -0,0 +1,349 @@ +/* + * arch/ppc/platforms/mvme5100.c + * + * Board setup routines for the Motorola MVME5100. + * + * Author: Matt Porter + * + * 2001-2004 (c) MontaVista, Software, Inc. This file is licensed under + * the terms of the GNU General Public License version 2. This program + * is licensed "as is" without any warranty of any kind, whether express + * or implied. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +static u_char mvme5100_openpic_initsenses[16] __initdata = { + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* i8259 cascade */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* TL16C550 UART 1,2 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Enet1 front panel or P2 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Hawk Watchdog 1,2 */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* DS1621 thermal alarm */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Universe II LINT0# */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Universe II LINT1# */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Universe II LINT2# */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Universe II LINT3# */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* PMC1 INTA#, PMC2 INTB# */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* PMC1 INTB#, PMC2 INTC# */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* PMC1 INTC#, PMC2 INTD# */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* PMC1 INTD#, PMC2 INTA# */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Enet 2 (front panel) */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Abort Switch */ + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* RTC Alarm */ +}; + +static inline int +mvme5100_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin) +{ + int irq; + + static char pci_irq_table[][4] = + /* + * PCI IDSEL/INTPIN->INTLINE + * A B C D + */ + { + { 0, 0, 0, 0 }, /* IDSEL 11 - Winbond */ + { 0, 0, 0, 0 }, /* IDSEL 12 - unused */ + { 21, 22, 23, 24 }, /* IDSEL 13 - Universe II */ + { 18, 0, 0, 0 }, /* IDSEL 14 - Enet 1 */ + { 0, 0, 0, 0 }, /* IDSEL 15 - unused */ + { 25, 26, 27, 28 }, /* IDSEL 16 - PMC Slot 1 */ + { 28, 25, 26, 27 }, /* IDSEL 17 - PMC Slot 2 */ + { 0, 0, 0, 0 }, /* IDSEL 18 - unused */ + { 29, 0, 0, 0 }, /* IDSEL 19 - Enet 2 */ + { 0, 0, 0, 0 }, /* IDSEL 20 - PMCSPAN */ + }; + + const long min_idsel = 11, max_idsel = 20, irqs_per_slot = 4; + irq = PCI_IRQ_TABLE_LOOKUP; + /* If lookup is zero, always return 0 */ + if (!irq) + return 0; + else +#ifdef CONFIG_MVME5100_IPMC761_PRESENT + /* If IPMC761 present, return table value */ + return irq; +#else + /* If IPMC761 not present, we don't have an i8259 so adjust */ + return (irq - NUM_8259_INTERRUPTS); +#endif +} + +static void +mvme5100_pcibios_fixup_resources(struct pci_dev *dev) +{ + int i; + + if ((dev->vendor == PCI_VENDOR_ID_MOTOROLA) && + (dev->device == PCI_DEVICE_ID_MOTOROLA_HAWK)) + for (i=0; iresource[i].start = 0; + dev->resource[i].end = 0; + } +} + +static void __init +mvme5100_setup_bridge(void) +{ + struct pci_controller* hose; + + hose = pcibios_alloc_controller(); + + if (!hose) + return; + + hose->first_busno = 0; + hose->last_busno = 0xff; + hose->pci_mem_offset = MVME5100_PCI_MEM_OFFSET; + + pci_init_resource(&hose->io_resource, MVME5100_PCI_LOWER_IO, + MVME5100_PCI_UPPER_IO, IORESOURCE_IO, + "PCI host bridge"); + + pci_init_resource(&hose->mem_resources[0], MVME5100_PCI_LOWER_MEM, + MVME5100_PCI_UPPER_MEM, IORESOURCE_MEM, + "PCI host bridge"); + + hose->io_space.start = MVME5100_PCI_LOWER_IO; + hose->io_space.end = MVME5100_PCI_UPPER_IO; + hose->mem_space.start = MVME5100_PCI_LOWER_MEM; + hose->mem_space.end = MVME5100_PCI_UPPER_MEM; + hose->io_base_virt = (void *)MVME5100_ISA_IO_BASE; + + /* Use indirect method of Hawk */ + setup_indirect_pci(hose, MVME5100_PCI_CONFIG_ADDR, + MVME5100_PCI_CONFIG_DATA); + + hose->last_busno = pciauto_bus_scan(hose, hose->first_busno); + + ppc_md.pcibios_fixup_resources = mvme5100_pcibios_fixup_resources; + ppc_md.pci_swizzle = common_swizzle; + ppc_md.pci_map_irq = mvme5100_map_irq; +} + +static void __init +mvme5100_setup_arch(void) +{ + if ( ppc_md.progress ) + ppc_md.progress("mvme5100_setup_arch: enter", 0); + + loops_per_jiffy = 50000000 / HZ; + +#ifdef CONFIG_BLK_DEV_INITRD + if (initrd_start) + ROOT_DEV = Root_RAM0; + else +#endif +#ifdef CONFIG_ROOT_NFS + ROOT_DEV = Root_NFS; +#else + ROOT_DEV = Root_SDA2; +#endif + + if ( ppc_md.progress ) + ppc_md.progress("mvme5100_setup_arch: find_bridges", 0); + + /* Setup PCI host bridge */ + mvme5100_setup_bridge(); + + /* Find and map our OpenPIC */ + hawk_mpic_init(MVME5100_PCI_MEM_OFFSET); + OpenPIC_InitSenses = mvme5100_openpic_initsenses; + OpenPIC_NumInitSenses = sizeof(mvme5100_openpic_initsenses); + + printk("MVME5100 port (C) 2001 MontaVista Software, Inc. (source@mvista.com)\n"); + + if ( ppc_md.progress ) + ppc_md.progress("mvme5100_setup_arch: exit", 0); + + return; +} + +static void __init +mvme5100_init2(void) +{ +#ifdef CONFIG_MVME5100_IPMC761_PRESENT + request_region(0x00,0x20,"dma1"); + request_region(0x20,0x20,"pic1"); + request_region(0x40,0x20,"timer"); + request_region(0x80,0x10,"dma page reg"); + request_region(0xa0,0x20,"pic2"); + request_region(0xc0,0x20,"dma2"); +#endif + return; +} + +/* + * Interrupt setup and service. + * Have MPIC on HAWK and cascaded 8259s on Winbond cascaded to MPIC. + */ +static void __init +mvme5100_init_IRQ(void) +{ +#ifdef CONFIG_MVME5100_IPMC761_PRESENT + int i; +#endif + + if ( ppc_md.progress ) + ppc_md.progress("init_irq: enter", 0); + + openpic_set_sources(0, 16, OpenPIC_Addr + 0x10000); +#ifdef CONFIG_MVME5100_IPMC761_PRESENT + openpic_init(NUM_8259_INTERRUPTS); + openpic_hookup_cascade(NUM_8259_INTERRUPTS, "82c59 cascade", + &i8259_irq); + + /* Map i8259 interrupts. */ + for (i = 0; i < NUM_8259_INTERRUPTS; i++) + irq_desc[i].handler = &i8259_pic; + + i8259_init(NULL); +#else + openpic_init(0); +#endif + + if ( ppc_md.progress ) + ppc_md.progress("init_irq: exit", 0); + + return; +} + +/* + * Set BAT 3 to map 0xf0000000 to end of physical memory space. + */ +static __inline__ void +mvme5100_set_bat(void) +{ + mb(); + mtspr(DBAT1U, 0xf0001ffe); + mtspr(DBAT1L, 0xf000002a); + mb(); +} + +static unsigned long __init +mvme5100_find_end_of_memory(void) +{ + return hawk_get_mem_size(MVME5100_HAWK_SMC_BASE); +} + +static void __init +mvme5100_map_io(void) +{ + io_block_mapping(0xfe000000, 0xfe000000, 0x02000000, _PAGE_IO); + ioremap_base = 0xfe000000; +} + +static void +mvme5100_reset_board(void) +{ + local_irq_disable(); + + /* Set exception prefix high - to the firmware */ + _nmask_and_or_msr(0, MSR_IP); + + out_8((u_char *)MVME5100_BOARD_MODRST_REG, 0x01); + + return; +} + +static void +mvme5100_restart(char *cmd) +{ + volatile ulong i = 10000000; + + mvme5100_reset_board(); + + while (i-- > 0); + panic("restart failed\n"); +} + +static void +mvme5100_halt(void) +{ + local_irq_disable(); + while (1); +} + +static void +mvme5100_power_off(void) +{ + mvme5100_halt(); +} + +static int +mvme5100_show_cpuinfo(struct seq_file *m) +{ + seq_printf(m, "vendor\t\t: Motorola\n"); + seq_printf(m, "machine\t\t: MVME5100\n"); + + return 0; +} + +TODC_ALLOC(); + +void __init +platform_init(unsigned long r3, unsigned long r4, unsigned long r5, + unsigned long r6, unsigned long r7) +{ + parse_bootinfo(find_bootinfo()); + mvme5100_set_bat(); + + isa_io_base = MVME5100_ISA_IO_BASE; + isa_mem_base = MVME5100_ISA_MEM_BASE; + pci_dram_offset = MVME5100_PCI_DRAM_OFFSET; + + ppc_md.setup_arch = mvme5100_setup_arch; + ppc_md.show_cpuinfo = mvme5100_show_cpuinfo; + ppc_md.init_IRQ = mvme5100_init_IRQ; + ppc_md.get_irq = openpic_get_irq; + ppc_md.init = mvme5100_init2; + + ppc_md.restart = mvme5100_restart; + ppc_md.power_off = mvme5100_power_off; + ppc_md.halt = mvme5100_halt; + + ppc_md.find_end_of_memory = mvme5100_find_end_of_memory; + ppc_md.setup_io_mappings = mvme5100_map_io; + + TODC_INIT(TODC_TYPE_MK48T37, MVME5100_NVRAM_AS0, MVME5100_NVRAM_AS1, + MVME5100_NVRAM_DATA, 8); + + ppc_md.time_init = todc_time_init; + ppc_md.set_rtc_time = todc_set_rtc_time; + ppc_md.get_rtc_time = todc_get_rtc_time; + ppc_md.calibrate_decr = todc_calibrate_decr; + + ppc_md.nvram_read_val = todc_m48txx_read_val; + ppc_md.nvram_write_val = todc_m48txx_write_val; +} diff -Nru a/arch/ppc/platforms/mvme5100.h b/arch/ppc/platforms/mvme5100.h --- a/arch/ppc/platforms/mvme5100.h 2004-08-25 22:01:56 -07:00 +++ b/arch/ppc/platforms/mvme5100.h 2004-08-25 22:01:56 -07:00 @@ -63,10 +63,29 @@ #define MVME5100_SERIAL_IRQ 1 #endif -#define MVME5100_WINBOND_DEVFN 0x58 -#define MVME5100_WINBOND_VIDDID 0x056510ad +#define RS_TABLE_SIZE 4 -extern void mvme5100_setup_bridge(void); +#define BASE_BAUD ( MVME5100_BASE_BAUD / 16 ) + +#define STD_COM_FLAGS ASYNC_BOOT_AUTOCONF + +/* All UART IRQ's are wire-OR'd to one MPIC IRQ */ +#define STD_SERIAL_PORT_DFNS \ + { 0, BASE_BAUD, MVME5100_SERIAL_1, \ + MVME5100_SERIAL_IRQ, \ + STD_COM_FLAGS, /* ttyS0 */ \ + iomem_base: (unsigned char *)MVME5100_SERIAL_1, \ + iomem_reg_shift: 4, \ + io_type: SERIAL_IO_MEM }, \ + { 0, BASE_BAUD, MVME5100_SERIAL_2, \ + MVME5100_SERIAL_IRQ, \ + STD_COM_FLAGS, /* ttyS1 */ \ + iomem_base: (unsigned char *)MVME5100_SERIAL_2, \ + iomem_reg_shift: 4, \ + io_type: SERIAL_IO_MEM }, + +#define SERIAL_PORT_DFNS \ + STD_SERIAL_PORT_DFNS #endif /* __ASM_MVME5100_H__ */ #endif /* __KERNEL__ */ diff -Nru a/arch/ppc/platforms/mvme5100_pci.c b/arch/ppc/platforms/mvme5100_pci.c --- a/arch/ppc/platforms/mvme5100_pci.c 2004-08-25 22:01:54 -07:00 +++ /dev/null Wed Dec 31 16:00:00 196900 @@ -1,121 +0,0 @@ -/* - * arch/ppc/platforms/mvme5100_pci.c - * - * PCI setup routines for the Motorola MVME5100. - * - * Author: Matt Porter - * - * 2001 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2. This program - * is licensed "as is" without any warranty of any kind, whether express - * or implied. - */ -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -static inline int -mvme5100_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin) -{ - int irq; - - static char pci_irq_table[][4] = - /* - * PCI IDSEL/INTPIN->INTLINE - * A B C D - */ - { - { 0, 0, 0, 0 }, /* IDSEL 11 - Winbond */ - { 0, 0, 0, 0 }, /* IDSEL 12 - unused */ - { 21, 22, 23, 24 }, /* IDSEL 13 - Universe II */ - { 18, 0, 0, 0 }, /* IDSEL 14 - Enet 1 */ - { 0, 0, 0, 0 }, /* IDSEL 15 - unused */ - { 25, 26, 27, 28 }, /* IDSEL 16 - PMC Slot 1 */ - { 28, 25, 26, 27 }, /* IDSEL 17 - PMC Slot 2 */ - { 0, 0, 0, 0 }, /* IDSEL 18 - unused */ - { 29, 0, 0, 0 }, /* IDSEL 19 - Enet 2 */ - { 0, 0, 0, 0 }, /* IDSEL 20 - PMCSPAN */ - }; - - const long min_idsel = 11, max_idsel = 20, irqs_per_slot = 4; - irq = PCI_IRQ_TABLE_LOOKUP; - /* If lookup is zero, always return 0 */ - if (!irq) - return 0; - else -#ifdef CONFIG_MVME5100_IPMC761_PRESENT - /* If IPMC761 present, return table value */ - return irq; -#else - /* If IPMC761 not present, we don't have an i8259 so adjust */ - return (irq - NUM_8259_INTERRUPTS); -#endif -} - -static void -mvme5100_pcibios_fixup_resources(struct pci_dev *dev) -{ - int i; - - if ((dev->vendor == PCI_VENDOR_ID_MOTOROLA) && - (dev->device == PCI_DEVICE_ID_MOTOROLA_HAWK)) - for (i=0; iresource[i].start = 0; - dev->resource[i].end = 0; - } -} - -void __init -mvme5100_setup_bridge(void) -{ - struct pci_controller* hose; - - hose = pcibios_alloc_controller(); - - if (!hose) - return; - - hose->first_busno = 0; - hose->last_busno = 0xff; - hose->pci_mem_offset = MVME5100_PCI_MEM_OFFSET; - - pci_init_resource(&hose->io_resource, - MVME5100_PCI_LOWER_IO, - MVME5100_PCI_UPPER_IO, - IORESOURCE_IO, - "PCI host bridge"); - - pci_init_resource(&hose->mem_resources[0], - MVME5100_PCI_LOWER_MEM, - MVME5100_PCI_UPPER_MEM, - IORESOURCE_MEM, - "PCI host bridge"); - - hose->io_space.start = MVME5100_PCI_LOWER_IO; - hose->io_space.end = MVME5100_PCI_UPPER_IO; - hose->mem_space.start = MVME5100_PCI_LOWER_MEM; - hose->mem_space.end = MVME5100_PCI_UPPER_MEM; - hose->io_base_virt = (void *)MVME5100_ISA_IO_BASE; - - /* Use indirect method of Hawk */ - setup_indirect_pci(hose, - MVME5100_PCI_CONFIG_ADDR, - MVME5100_PCI_CONFIG_DATA); - - hose->last_busno = pciauto_bus_scan(hose, hose->first_busno); - - ppc_md.pcibios_fixup_resources = mvme5100_pcibios_fixup_resources; - ppc_md.pci_swizzle = common_swizzle; - ppc_md.pci_map_irq = mvme5100_map_irq; -} diff -Nru a/arch/ppc/platforms/mvme5100_serial.h b/arch/ppc/platforms/mvme5100_serial.h --- a/arch/ppc/platforms/mvme5100_serial.h 2004-08-25 22:01:55 -07:00 +++ /dev/null Wed Dec 31 16:00:00 196900 @@ -1,54 +0,0 @@ -/* - * include/asm-ppc/mvme5100_serial.h - * - * Definitions for Motorola MVME5100 support - * - * Author: Matt Porter - * - * 2001 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2. This program - * is licensed "as is" without any warranty of any kind, whether express - * or implied. - */ - -#ifdef __KERNEL__ -#ifndef __ASM_MVME5100_SERIAL_H__ -#define __ASM_MVME5100_SERIAL_H__ - -#include -#include - -#ifdef CONFIG_SERIAL_MANY_PORTS -#define RS_TABLE_SIZE 64 -#else -#define RS_TABLE_SIZE 4 -#endif - -#define BASE_BAUD ( MVME5100_BASE_BAUD / 16 ) - -#ifdef CONFIG_SERIAL_DETECT_IRQ -#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_SKIP_TEST|ASYNC_AUTO_IRQ) -#else -#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_SKIP_TEST) -#endif - -/* All UART IRQ's are wire-OR'd to one MPIC IRQ */ -#define STD_SERIAL_PORT_DFNS \ - { 0, BASE_BAUD, MVME5100_SERIAL_1, \ - MVME5100_SERIAL_IRQ, \ - STD_COM_FLAGS, /* ttyS0 */ \ - iomem_base: (unsigned char *)MVME5100_SERIAL_1, \ - iomem_reg_shift: 4, \ - io_type: SERIAL_IO_MEM }, \ - { 0, BASE_BAUD, MVME5100_SERIAL_2, \ - MVME5100_SERIAL_IRQ, \ - STD_COM_FLAGS, /* ttyS1 */ \ - iomem_base: (unsigned char *)MVME5100_SERIAL_2, \ - iomem_reg_shift: 4, \ - io_type: SERIAL_IO_MEM }, - -#define SERIAL_PORT_DFNS \ - STD_SERIAL_PORT_DFNS - -#endif /* __ASM_MVME5100_SERIAL_H__ */ -#endif /* __KERNEL__ */ diff -Nru a/arch/ppc/platforms/mvme5100_setup.c b/arch/ppc/platforms/mvme5100_setup.c --- a/arch/ppc/platforms/mvme5100_setup.c 2004-08-25 22:01:55 -07:00 +++ /dev/null Wed Dec 31 16:00:00 196900 @@ -1,284 +0,0 @@ -/* - * arch/ppc/platforms/mvme5100_setup.c - * - * Board setup routines for the Motorola MVME5100. - * - * Author: Matt Porter - * - * 2001 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2. This program - * is licensed "as is" without any warranty of any kind, whether express - * or implied. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -extern char cmd_line[]; - -static u_char mvme5100_openpic_initsenses[] __initdata = { - 0, /* 16: i8259 cascade (active high) */ - 1, /* 17: TL16C550 UART 1,2 */ - 1, /* 18: Enet 1 (front panel or P2) */ - 1, /* 19: Hawk Watchdog 1,2 */ - 1, /* 20: DS1621 thermal alarm */ - 1, /* 21: Universe II LINT0# */ - 1, /* 22: Universe II LINT1# */ - 1, /* 23: Universe II LINT2# */ - 1, /* 24: Universe II LINT3# */ - 1, /* 25: PMC1 INTA#, PMC2 INTB# */ - 1, /* 26: PMC1 INTB#, PMC2 INTC# */ - 1, /* 27: PMC1 INTC#, PMC2 INTD# */ - 1, /* 28: PMC1 INTD#, PMC2 INTA# */ - 1, /* 29: Enet 2 (front panel) */ - 1, /* 30: Abort Switch */ - 1, /* 31: RTC Alarm */ -}; - -static void __init -mvme5100_setup_arch(void) -{ - if ( ppc_md.progress ) - ppc_md.progress("mvme5100_setup_arch: enter", 0); - - loops_per_jiffy = 50000000 / HZ; - -#ifdef CONFIG_BLK_DEV_INITRD - if (initrd_start) - ROOT_DEV = Root_RAM0; - else -#endif -#ifdef CONFIG_ROOT_NFS - ROOT_DEV = Root_NFS; -#else - ROOT_DEV = Root_SDA2; -#endif - -#ifdef CONFIG_DUMMY_CONSOLE - conswitchp = &dummy_con; -#endif - - if ( ppc_md.progress ) - ppc_md.progress("mvme5100_setup_arch: find_bridges", 0); - - /* Setup PCI host bridge */ - mvme5100_setup_bridge(); - - /* Find and map our OpenPIC */ - pplus_mpic_init(MVME5100_PCI_MEM_OFFSET); - OpenPIC_InitSenses = mvme5100_openpic_initsenses; - OpenPIC_NumInitSenses = sizeof(mvme5100_openpic_initsenses); - - printk("MVME5100 port (C) 2001 MontaVista Software, Inc. (source@mvista.com)\n"); - - if ( ppc_md.progress ) - ppc_md.progress("mvme5100_setup_arch: exit", 0); - - return; -} - -static void __init -mvme5100_init2(void) -{ -#ifdef CONFIG_MVME5100_IPMC761_PRESENT - request_region(0x00,0x20,"dma1"); - request_region(0x20,0x20,"pic1"); - request_region(0x40,0x20,"timer"); - request_region(0x80,0x10,"dma page reg"); - request_region(0xa0,0x20,"pic2"); - request_region(0xc0,0x20,"dma2"); -#endif - return; -} - -/* - * Interrupt setup and service. - * Have MPIC on HAWK and cascaded 8259s on Winbond cascaded to MPIC. - */ -static void __init -mvme5100_init_IRQ(void) -{ -#ifdef CONFIG_MVME5100_IPMC761_PRESENT - int i; -#endif - - if ( ppc_md.progress ) - ppc_md.progress("init_irq: enter", 0); - -#ifdef CONFIG_MVME5100_IPMC761_PRESENT - openpic_init(1, NUM_8259_INTERRUPTS, NULL, -1); - openpic_hookup_cascade(NUM_8259_INTERRUPTS,"82c59 cascade",&i8259_irq); - - for(i=0; i < NUM_8259_INTERRUPTS; i++) - irq_desc[i].handler = &i8259_pic; - - i8259_init(NULL); -#else - openpic_init(1, 0, NULL, -1); -#endif - - if ( ppc_md.progress ) - ppc_md.progress("init_irq: exit", 0); - - return; -} - -/* - * Set BAT 3 to map 0xf0000000 to end of physical memory space. - */ -static __inline__ void -mvme5100_set_bat(void) -{ - unsigned long bat3u, bat3l; - static int mapping_set = 0; - - if (!mapping_set) { - - __asm__ __volatile__( - " lis %0,0xf000\n \ - ori %1,%0,0x002a\n \ - ori %0,%0,0x1ffe\n \ - mtspr 0x21e,%0\n \ - mtspr 0x21f,%1\n \ - isync\n \ - sync " - : "=r" (bat3u), "=r" (bat3l)); - - mapping_set = 1; - } - - return; -} - -static unsigned long __init -mvme5100_find_end_of_memory(void) -{ - mvme5100_set_bat(); - return pplus_get_mem_size(MVME5100_HAWK_SMC_BASE); -} - -static void __init -mvme5100_map_io(void) -{ - io_block_mapping(0xfe000000, 0xfe000000, 0x02000000, _PAGE_IO); - ioremap_base = 0xfe000000; -} - -static void -mvme5100_reset_board(void) -{ - local_irq_disable(); - - /* Set exception prefix high - to the firmware */ - _nmask_and_or_msr(0, MSR_IP); - - out_8((u_char *)MVME5100_BOARD_MODRST_REG, 0x01); - - return; -} - -static void -mvme5100_restart(char *cmd) -{ - volatile ulong i = 10000000; - - mvme5100_reset_board(); - - while (i-- > 0); - panic("restart failed\n"); -} - -static void -mvme5100_halt(void) -{ - local_irq_disable(); - while (1); -} - -static void -mvme5100_power_off(void) -{ - mvme5100_halt(); -} - -static int -mvme5100_show_cpuinfo(struct seq_file *m) -{ - seq_printf(m, "vendor\t\t: Motorola\n"); - seq_printf(m, "machine\t\t: MVME5100\n"); - - return 0; -} - -TODC_ALLOC(); - -void __init -platform_init(unsigned long r3, unsigned long r4, unsigned long r5, - unsigned long r6, unsigned long r7) -{ - parse_bootinfo(find_bootinfo()); - - isa_io_base = MVME5100_ISA_IO_BASE; - isa_mem_base = MVME5100_ISA_MEM_BASE; - pci_dram_offset = MVME5100_PCI_DRAM_OFFSET; - - ppc_md.setup_arch = mvme5100_setup_arch; - ppc_md.show_cpuinfo = mvme5100_show_cpuinfo; - ppc_md.init_IRQ = mvme5100_init_IRQ; - ppc_md.get_irq = openpic_get_irq; - ppc_md.init = mvme5100_init2; - - ppc_md.restart = mvme5100_restart; - ppc_md.power_off = mvme5100_power_off; - ppc_md.halt = mvme5100_halt; - - ppc_md.find_end_of_memory = mvme5100_find_end_of_memory; - ppc_md.setup_io_mappings = mvme5100_map_io; - - TODC_INIT(TODC_TYPE_MK48T37, - MVME5100_NVRAM_AS0, - MVME5100_NVRAM_AS1, - MVME5100_NVRAM_DATA, - 8); - - ppc_md.time_init = todc_time_init; - ppc_md.set_rtc_time = todc_set_rtc_time; - ppc_md.get_rtc_time = todc_get_rtc_time; - ppc_md.calibrate_decr = todc_calibrate_decr; - - ppc_md.nvram_read_val = todc_m48txx_read_val; - ppc_md.nvram_write_val = todc_m48txx_write_val; - - ppc_md.progress = NULL; -} diff -Nru a/arch/ppc/platforms/pcore.c b/arch/ppc/platforms/pcore.c --- a/arch/ppc/platforms/pcore.c 2004-08-25 22:01:54 -07:00 +++ b/arch/ppc/platforms/pcore.c 2004-08-25 22:01:54 -07:00 @@ -228,10 +228,6 @@ ROOT_DEV = Root_SDA2; #endif -#ifdef CONFIG_DUMMY_CONSOLE - conswitchp = &dummy_con; -#endif - printk(KERN_INFO "Force PowerCore "); if (board_type == PCORE_TYPE_6750) printk("6750\n"); diff -Nru a/arch/ppc/platforms/pmac_setup.c b/arch/ppc/platforms/pmac_setup.c --- a/arch/ppc/platforms/pmac_setup.c 2004-08-25 22:01:55 -07:00 +++ b/arch/ppc/platforms/pmac_setup.c 2004-08-25 22:01:55 -07:00 @@ -318,9 +318,6 @@ #ifdef CONFIG_NVRAM pmac_nvram_init(); #endif -#ifdef CONFIG_DUMMY_CONSOLE - conswitchp = &dummy_con; -#endif #ifdef CONFIG_BLK_DEV_INITRD if (initrd_start) ROOT_DEV = Root_RAM0; diff -Nru a/arch/ppc/platforms/powerpmc250.h b/arch/ppc/platforms/powerpmc250.h --- a/arch/ppc/platforms/powerpmc250.h 2004-08-25 22:01:55 -07:00 +++ b/arch/ppc/platforms/powerpmc250.h 2004-08-25 22:01:55 -07:00 @@ -7,7 +7,7 @@ * * Borrowed heavily from prpmc750.h by Matt Porter * - * 2001 (c) MontaVista, Software, Inc. This file is licensed under + * 2001-2004 (c) MontaVista, Software, Inc. This file is licensed under * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. @@ -16,8 +16,6 @@ #ifndef __ASMPPC_POWERPMC250_H #define __ASMPPC_POWERPMC250_H -#include - #define POWERPMC250_PCI_CONFIG_ADDR 0x80000cf8 #define POWERPMC250_PCI_CONFIG_DATA 0x80000cfc @@ -36,5 +34,19 @@ #define POWERPMC250_BASE_BAUD 12288000 #define POWERPMC250_SERIAL 0xff000000 #define POWERPMC250_SERIAL_IRQ 20 + +/* UART Defines. */ +#define RS_TABLE_SIZE 1 + +#define BASE_BAUD (POWERPMC250_BASE_BAUD / 16) + +#define STD_COM_FLAGS ASYNC_BOOT_AUTOCONF + +#define SERIAL_PORT_DFNS \ + { 0, BASE_BAUD, POWERPMC250_SERIAL, POWERPMC250_SERIAL_IRQ, \ + STD_COM_FLAGS, /* ttyS0 */ \ + iomem_base: (u8 *)POWERPMC250_SERIAL, \ + iomem_reg_shift: 0, \ + io_type: SERIAL_IO_MEM } #endif /* __ASMPPC_POWERPMC250_H */ diff -Nru a/arch/ppc/platforms/powerpmc250_serial.h b/arch/ppc/platforms/powerpmc250_serial.h --- a/arch/ppc/platforms/powerpmc250_serial.h 2004-08-25 22:01:55 -07:00 +++ /dev/null Wed Dec 31 16:00:00 196900 @@ -1,40 +0,0 @@ -/* - * include/asm-ppc/platforms/powerpmc250_serial.h - * - * Motorola PrPMC750 serial support - * - * Author: Troy Benjegerdes - * - * 2001 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2. This program - * is licensed "as is" without any warranty of any kind, whether express - * or implied. - */ - -#ifdef __KERNEL__ -#ifndef __ASMPPC_POWERPMC250_SERIAL_H -#define __ASMPPC_POWERPMC250_SERIAL_H - -#include -#include - -#define RS_TABLE_SIZE 1 - -#define BASE_BAUD (POWERPMC250_BASE_BAUD / 16) - -#ifdef CONFIG_SERIAL_DETECT_IRQ -#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_SKIP_TEST|ASYNC_AUTO_IRQ) -#define STD_COM4_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_AUTO_IRQ) -#else -#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_SKIP_TEST) -#define STD_COM4_FLAGS (ASYNC_BOOT_AUTOCONF) -#endif - -#define SERIAL_PORT_DFNS \ -{ 0, BASE_BAUD, POWERPMC250_SERIAL, POWERPMC250_SERIAL_IRQ, STD_COM_FLAGS, /* ttyS0 */\ - iomem_base: (u8 *)POWERPMC250_SERIAL, \ - iomem_reg_shift: 0, \ - io_type: SERIAL_IO_MEM } - -#endif -#endif /* __KERNEL__ */ diff -Nru a/arch/ppc/platforms/pplus.c b/arch/ppc/platforms/pplus.c --- a/arch/ppc/platforms/pplus.c 2004-08-25 22:01:56 -07:00 +++ b/arch/ppc/platforms/pplus.c 2004-08-25 22:01:56 -07:00 @@ -583,8 +583,6 @@ vgacon_remap_base = (unsigned long)ioremap(PPLUS_ISA_MEM_BASE, 0x08000000); conswitchp = &vga_con; -#elif defined(CONFIG_DUMMY_CONSOLE) - conswitchp = &dummy_con; #endif #ifdef CONFIG_PPCBUG_NVRAM /* Read in NVRAM data */ diff -Nru a/arch/ppc/platforms/pq2ads.c b/arch/ppc/platforms/pq2ads.c --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/arch/ppc/platforms/pq2ads.c 2004-08-25 22:01:56 -07:00 @@ -0,0 +1,26 @@ +/* + * arch/ppc/platforms/pq2ads.c + * + * PQ2ADS platform support + * + * Author: Kumar Gala + * Derived from: est8260_setup.c by Allen Curtis + * + * Copyright 2004 Freescale Semiconductor, Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include + +#include + +void __init +m82xx_board_init(void) +{ + /* Enable the 2nd UART port */ + *(volatile uint *)(BCSR_ADDR + 4) &= ~BCSR1_RS232_EN2; +} diff -Nru a/arch/ppc/platforms/pq2ads.h b/arch/ppc/platforms/pq2ads.h --- a/arch/ppc/platforms/pq2ads.h 2004-08-25 22:01:55 -07:00 +++ b/arch/ppc/platforms/pq2ads.h 2004-08-25 22:01:55 -07:00 @@ -23,6 +23,10 @@ #define BOOTROM_RESTART_ADDR ((uint)0xff000104) +/* For our show_cpuinfo hooks. */ +#define CPUINFO_VENDOR "Motorola" +#define CPUINFO_MACHINE "PQ2 ADS PowerPC" + /* The ADS8260 has 16, 32-bit wide control/status registers, accessed * only on word boundaries. * Not all are used (yet), or are interesting to us (yet). diff -Nru a/arch/ppc/platforms/pq2ads_setup.c b/arch/ppc/platforms/pq2ads_setup.c --- a/arch/ppc/platforms/pq2ads_setup.c 2004-08-25 22:01:56 -07:00 +++ /dev/null Wed Dec 31 16:00:00 196900 @@ -1,66 +0,0 @@ -/* - * arch/ppc/platforms/pq2ads_setup.c - * - * PQ2ADS platform support - * - * Author: Kumar Gala - * Derived from: est8260_setup.c by Allen Curtis - * - * Copyright 2004 Freescale Semiconductor, Inc. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - */ - -#include -#include - -#include -#include - -static void (*callback_setup_arch)(void); - -extern unsigned char __res[sizeof(bd_t)]; - -extern void m8260_init(unsigned long r3, unsigned long r4, - unsigned long r5, unsigned long r6, unsigned long r7); - -static int -pq2ads_show_cpuinfo(struct seq_file *m) -{ - bd_t *binfo = (bd_t *)__res; - - seq_printf(m, "vendor\t\t: Motorola\n" - "machine\t\t: PQ2 ADS PowerPC\n" - "\n" - "mem size\t\t: 0x%08lx\n" - "console baud\t\t: %ld\n" - "\n", - binfo->bi_memsize, - binfo->bi_baudrate); - return 0; -} - -static void __init -pq2ads_setup_arch(void) -{ - printk("PQ2 ADS Port\n"); - callback_setup_arch(); - *(volatile uint *)(BCSR_ADDR + 4) &= ~BCSR1_RS232_EN2; -} - -void __init -platform_init(unsigned long r3, unsigned long r4, unsigned long r5, - unsigned long r6, unsigned long r7) -{ - /* Generic 8260 platform initialization */ - m8260_init(r3, r4, r5, r6, r7); - - /* Anything special for this platform */ - ppc_md.show_cpuinfo = pq2ads_show_cpuinfo; - - callback_setup_arch = ppc_md.setup_arch; - ppc_md.setup_arch = pq2ads_setup_arch; -} diff -Nru a/arch/ppc/platforms/prep_pci.c b/arch/ppc/platforms/prep_pci.c --- a/arch/ppc/platforms/prep_pci.c 2004-08-25 22:01:56 -07:00 +++ b/arch/ppc/platforms/prep_pci.c 2004-08-25 22:01:56 -07:00 @@ -836,52 +836,59 @@ void __init ibm_prep_init(void) { -#ifdef CONFIG_PREP_RESIDUAL - u32 addr, real_addr, len; - PPC_DEVICE *mpic; - PnP_TAG_PACKET *pkt; - - /* Use the PReP residual data to determine if an OpenPIC is - * present. If so, get the large vendor packet which will - * tell us the base address and length in memory. - * If we are successful, ioremap the memory area and set - * OpenPIC_Addr (this indicates that the OpenPIC was found). - */ - mpic = residual_find_device(-1, NULL, SystemPeripheral, - ProgrammableInterruptController, MPIC, 0); - if (!mpic) - return; + if (have_residual_data) { + u32 addr, real_addr, len, offset; + PPC_DEVICE *mpic; + PnP_TAG_PACKET *pkt; + + /* Use the PReP residual data to determine if an OpenPIC is + * present. If so, get the large vendor packet which will + * tell us the base address and length in memory. + * If we are successful, ioremap the memory area and set + * OpenPIC_Addr (this indicates that the OpenPIC was found). + */ + mpic = residual_find_device(-1, NULL, SystemPeripheral, + ProgrammableInterruptController, MPIC, 0); + if (!mpic) + return; - pkt = PnP_find_large_vendor_packet(res->DevicePnPHeap + - mpic->AllocatedOffset, 9, 0); + pkt = PnP_find_large_vendor_packet(res->DevicePnPHeap + + mpic->AllocatedOffset, 9, 0); - if (!pkt) - return; + if (!pkt) + return; #define p pkt->L4_Pack.L4_Data.L4_PPCPack - if (!((p.PPCData[0] == 2) && (p.PPCData[1] == 32))) - return; /* not a 32-bit memory address */ - - real_addr = ld_le32((unsigned int *) (p.PPCData + 4)); - if (real_addr == 0xffffffff) - return; - - /* Adjust address to be as seen by CPU */ - addr = real_addr + PREP_ISA_MEM_BASE; + if (p.PPCData[1] == 32) { + switch (p.PPCData[0]) { + case 1: offset = PREP_ISA_IO_BASE; break; + case 2: offset = PREP_ISA_MEM_BASE; break; + default: return; /* Not I/O or memory?? */ + } + } + else + return; /* Not a 32-bit address */ - len = ld_le32((unsigned int *) (p.PPCData + 12)); - if (!len) - return; + real_addr = ld_le32((unsigned int *) (p.PPCData + 4)); + if (real_addr == 0xffffffff) + return; + + /* Adjust address to be as seen by CPU */ + addr = real_addr + offset; + + len = ld_le32((unsigned int *) (p.PPCData + 12)); + if (!len) + return; #undef p - OpenPIC_Addr = ioremap(addr, len); - ppc_md.get_irq = openpic_get_irq; + OpenPIC_Addr = ioremap(addr, len); + ppc_md.get_irq = openpic_get_irq; - OpenPIC_InitSenses = prep_openpic_initsenses; - OpenPIC_NumInitSenses = sizeof(prep_openpic_initsenses); + OpenPIC_InitSenses = prep_openpic_initsenses; + OpenPIC_NumInitSenses = sizeof(prep_openpic_initsenses); - printk(KERN_INFO "MPIC at 0x%08x (0x%08x), length 0x%08x " - "mapped to 0x%p\n", addr, real_addr, len, OpenPIC_Addr); -#endif + printk(KERN_INFO "MPIC at 0x%08x (0x%08x), length 0x%08x " + "mapped to 0x%p\n", addr, real_addr, len, OpenPIC_Addr); + } } static void __init @@ -901,6 +908,17 @@ } void __init +prep_residual_setup_pci(char *irq_edge_mask_lo, char *irq_edge_mask_hi) +{ + if (have_residual_data) { + Motherboard_map_name = res->VitalProductData.PrintableModel; + Motherboard_map = NULL; + Motherboard_routes = NULL; + residual_irq_mask(irq_edge_mask_lo, irq_edge_mask_hi); + } +} + +void __init prep_sandalfoot_setup_pci(char *irq_edge_mask_lo, char *irq_edge_mask_hi) { Motherboard_map_name = "IBM 6015/7020 (Sandalfoot/Sandalbow)"; @@ -1011,21 +1029,31 @@ } } else if ( _prep_type == _PREP_IBM ) { unsigned char irq_edge_mask_lo, irq_edge_mask_hi; + unsigned short irq_edge_mask; + int i; setup_ibm_pci(&irq_edge_mask_lo, &irq_edge_mask_hi); outb(inb(0x04d0)|irq_edge_mask_lo, 0x4d0); /* primary 8259 */ outb(inb(0x04d1)|irq_edge_mask_hi, 0x4d1); /* cascaded 8259 */ + + irq_edge_mask = (irq_edge_mask_hi << 8) | irq_edge_mask_lo; + for (i = 0; i < 16; ++i, irq_edge_mask >>= 1) + if (irq_edge_mask & 1) + irq_desc[i].status |= IRQ_LEVEL; } else { printk("No known machine pci routing!\n"); return; } /* Set up mapping from slots */ - for (i = 1; i <= 4; i++) - ibc_pirq[i-1] = Motherboard_routes[i]; - /* Enable PCI interrupts */ - *ibc_pcicon |= 0x20; + if (Motherboard_routes) { + for (i = 1; i <= 4; i++) + ibc_pirq[i-1] = Motherboard_routes[i]; + + /* Enable PCI interrupts */ + *ibc_pcicon |= 0x20; + } } void __init @@ -1171,38 +1199,52 @@ prep_pcibios_fixup(void) { struct pci_dev *dev = NULL; + int irq; + int have_openpic = (OpenPIC_Addr != NULL); prep_route_pci_interrupts(); printk("Setting PCI interrupts for a \"%s\"\n", Motherboard_map_name); - if (OpenPIC_Addr) { - /* PCI interrupts are controlled by the OpenPIC */ - while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { - if (dev->bus->number == 0) { - dev->irq = openpic_to_irq(Motherboard_map[PCI_SLOT(dev->devfn)]); - pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq); - } else { - if (Motherboard_non0 != NULL) - Motherboard_non0(dev); - } - } - - /* Setup the Winbond or Via PIB */ - prep_pib_init(); - - return; - } - dev = NULL; + /* Iterate through all the PCI devices, setting the IRQ */ while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { /* - * Use our old hard-coded kludge to figure out what - * irq this device uses. This is necessary on things - * without residual data. -- Cort + * If we have residual data, then this is easy: query the + * residual data for the IRQ line allocated to the device. + * This works the same whether we have an OpenPic or not. + */ + if (have_residual_data) { + irq = residual_pcidev_irq(dev); + dev->irq = have_openpic ? openpic_to_irq(irq) : irq; + } + /* + * If we don't have residual data, then we need to use + * tables to determine the IRQ. The table organisation + * is different depending on whether there is an OpenPIC + * or not. The tables are only used for bus 0, so check + * this first. */ - unsigned char d = PCI_SLOT(dev->devfn); - dev->irq = Motherboard_routes[Motherboard_map[d]]; + else if (dev->bus->number == 0) { + irq = Motherboard_map[PCI_SLOT(dev->devfn)]; + dev->irq = have_openpic ? openpic_to_irq(irq) + : Motherboard_routes[irq]; + } + /* + * Finally, if we don't have residual data and the bus is + * non-zero, use the callback (if provided) + */ + else { + if (Motherboard_non0 != NULL) + Motherboard_non0(dev); + + continue; + } + + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq); } + + /* Setup the Winbond or Via PIB */ + prep_pib_init(); } static void __init @@ -1262,14 +1304,15 @@ PREP_ISA_IO_BASE + 0xcfc); printk("PReP architecture\n"); -#ifdef CONFIG_PREP_RESIDUAL - { + + if (have_residual_data) { PPC_DEVICE *hostbridge; hostbridge = residual_find_device(PROCESSORDEVICE, NULL, BridgeController, PCIBridge, -1, 0); if (hostbridge && - hostbridge->DeviceId.Interface == PCIBridgeIndirect) { + ((hostbridge->DeviceId.Interface == PCIBridgeIndirect) || + (hostbridge->DeviceId.Interface == PCIBridgeRS6K))) { PnP_TAG_PACKET * pkt; pkt = PnP_find_large_vendor_packet( res->DevicePnPHeap+hostbridge->AllocatedOffset, @@ -1284,7 +1327,6 @@ setup_indirect_pci(hose, 0x80000cf8, 0x80000cfc); } } -#endif /* CONFIG_PREP_RESIDUAL */ ppc_md.pcibios_fixup = prep_pcibios_fixup; ppc_md.pcibios_after_init = prep_pcibios_after_init; diff -Nru a/arch/ppc/platforms/prep_setup.c b/arch/ppc/platforms/prep_setup.c --- a/arch/ppc/platforms/prep_setup.c 2004-08-25 22:01:56 -07:00 +++ b/arch/ppc/platforms/prep_setup.c 2004-08-25 22:01:56 -07:00 @@ -79,6 +79,7 @@ int _prep_type; +extern void prep_residual_setup_pci(char *irq_edge_mask_lo, char *irq_edge_mask_hi); extern void prep_sandalfoot_setup_pci(char *irq_edge_mask_lo, char *irq_edge_mask_hi); extern void prep_thinkpad_setup_pci(char *irq_edge_mask_lo, char *irq_edge_mask_hi); extern void prep_carolina_setup_pci(char *irq_edge_mask_lo, char *irq_edge_mask_hi); @@ -193,9 +194,8 @@ seq_printf(m, "bad"); seq_printf(m, "\n"); -#ifdef CONFIG_PREP_RESIDUAL /* print info about SIMMs */ - if (res->ResidualLength != 0) { + if (have_residual_data) { int i; seq_printf(m, "simms\t\t: "); for (i = 0; (res->ActualNumMemories) && (i < MAX_MEMS); i++) { @@ -207,7 +207,13 @@ } seq_printf(m, "\n"); } -#endif +} + +static int __prep +prep_gen_cpuinfo(struct seq_file *m) +{ + prep_ibm_cpuinfo(m); + return 0; } static int __prep @@ -431,9 +437,8 @@ } no_l2: -#ifdef CONFIG_PREP_RESIDUAL /* print info about SIMMs */ - if (res->ResidualLength != 0) { + if (have_residual_data) { int i; seq_printf(m, "simms\t\t: "); for (i = 0; (res->ActualNumMemories) && (i < MAX_MEMS); i++) { @@ -445,18 +450,11 @@ } seq_printf(m, "\n"); } -#endif return 0; } static void __prep -prep_tiger1_progress(char *msg, unsigned short code) -{ - outw(code, PREP_IBM_DISP); -} - -static void __prep prep_restart(char *cmd) { #define PREP_SP92 0x92 /* Special Port 92 */ @@ -561,14 +559,12 @@ { /* PREP's without residual data will give incorrect values here */ seq_printf(m, "clock\t\t: "); -#ifdef CONFIG_PREP_RESIDUAL - if (res->ResidualLength) + if (have_residual_data) seq_printf(m, "%ldMHz\n", (res->VitalProductData.ProcessorHz > 1024) ? res->VitalProductData.ProcessorHz / 1000000 : res->VitalProductData.ProcessorHz); else -#endif /* CONFIG_PREP_RESIDUAL */ seq_printf(m, "???\n"); return 0; @@ -598,9 +594,10 @@ * Get the needed resource informations from residual data. * */ -#ifdef CONFIG_PREP_RESIDUAL - audiodevice = residual_find_device(~0, NULL, MultimediaController, - AudioController, -1, 0); + if (have_residual_data) + audiodevice = residual_find_device(~0, NULL, + MultimediaController, AudioController, -1, 0); + if (audiodevice != NULL) { PnP_TAG_PACKET *pkt; @@ -613,7 +610,6 @@ if (pkt != NULL) ppc_cs4232_dma2 = masktoint(pkt->S5_Pack.DMAMask); } -#endif /* * These are the PReP specs' defaults for the cs4231. We use these @@ -649,13 +645,14 @@ static void __init prep_init_vesa(void) { -#if defined(CONFIG_PREP_RESIDUAL) && \ - (defined(CONFIG_FB_VGA16) || defined(CONFIG_FB_VGA_16_MODULE) || \ +#if (defined(CONFIG_FB_VGA16) || defined(CONFIG_FB_VGA_16_MODULE) || \ defined(CONFIG_FB_VESA)) - PPC_DEVICE *vgadev; + PPC_DEVICE *vgadev = NULL; + + if (have_residual_data) + vgadev = residual_find_device(~0, NULL, DisplayController, + SVGAController, -1, 0); - vgadev = residual_find_device(~0, NULL, DisplayController, SVGAController, - -1, 0); if (vgadev != NULL) { PnP_TAG_PACKET *pkt; @@ -680,7 +677,112 @@ } } } -#endif /* CONFIG_PREP_RESIDUAL */ +#endif +} + +/* + * Set DBAT 2 to access 0x80000000 so early progress messages will work + */ +static __inline__ void +prep_set_bat(void) +{ + /* wait for all outstanding memory access to complete */ + mb(); + + /* setup DBATs */ + mtspr(DBAT2U, 0x80001ffe); + mtspr(DBAT2L, 0x8000002a); + + /* wait for updates */ + mb(); +} + +/* + * IBM 3-digit status LED + */ +static unsigned int ibm_statusled_base __prepdata; + +static void __prep +ibm_statusled_progress(char *s, unsigned short hex); + +static int __prep +ibm_statusled_panic(struct notifier_block *dummy1, unsigned long dummy2, + void * dummy3) +{ + ibm_statusled_progress(NULL, 0x505); /* SOS */ + return NOTIFY_DONE; +} + +static struct notifier_block ibm_statusled_block __prepdata = { + ibm_statusled_panic, + NULL, + INT_MAX /* try to do it first */ +}; + +static void __prep +ibm_statusled_progress(char *s, unsigned short hex) +{ + static int notifier_installed; + /* + * Progress uses 4 digits and we have only 3. So, we map 0xffff to + * 0xfff for display switch off. Out of range values are mapped to + * 0xeff, as I'm told 0xf00 and above are reserved for hardware codes. + * Install the panic notifier when the display is first switched off. + */ + if (hex == 0xffff) { + hex = 0xfff; + if (!notifier_installed) { + ++notifier_installed; + notifier_chain_register(&panic_notifier_list, + &ibm_statusled_block); + } + } + else + if (hex > 0xfff) + hex = 0xeff; + + mb(); + outw(hex, ibm_statusled_base); +} + +static void __init +ibm_statusled_init(void) +{ + /* + * The IBM 3-digit LED display is specified in the residual data + * as an operator panel device, type "System Status LED". Find + * that device and determine its address. We validate all the + * other parameters on the off-chance another, similar device + * exists. + */ + if (have_residual_data) { + PPC_DEVICE *led; + PnP_TAG_PACKET *pkt; + + led = residual_find_device(~0, NULL, SystemPeripheral, + OperatorPanel, SystemStatusLED, 0); + if (!led) + return; + + pkt = PnP_find_packet((unsigned char *) + &res->DevicePnPHeap[led->AllocatedOffset], S8_Packet, 0); + if (!pkt) + return; + + if (pkt->S8_Pack.IOInfo != ISAAddr16bit) + return; + if (*(unsigned short *)pkt->S8_Pack.RangeMin != + *(unsigned short *)pkt->S8_Pack.RangeMax) + return; + if (pkt->S8_Pack.IOAlign != 2) + return; + if (pkt->S8_Pack.IONum != 2) + return; + + ibm_statusled_base = ld_le16((unsigned short *) + (pkt->S8_Pack.RangeMin)); + ppc_md.progress = ibm_statusled_progress; + } } static void __init @@ -706,7 +808,7 @@ { case _PREP_IBM: reg = inb(PREP_IBM_PLANAR); - printk(KERN_INFO "IBM planar ID: %08x", reg); + printk(KERN_INFO "IBM planar ID: %02x", reg); switch (reg) { case PREP_IBM_SANDALFOOT: prep_gen_enable_l2(); @@ -721,7 +823,16 @@ ppc_md.show_cpuinfo = prep_thinkpad_cpuinfo; break; default: - printk(" -- unknown! Assuming Carolina"); + if (have_residual_data) { + prep_gen_enable_l2(); + setup_ibm_pci = prep_residual_setup_pci; + ppc_md.power_off = prep_halt; + ppc_md.show_cpuinfo = prep_gen_cpuinfo; + break; + } + else + printk(" - unknown! Assuming Carolina"); + /* fall through */ case PREP_IBM_CAROLINA_IDE_0: case PREP_IBM_CAROLINA_IDE_1: case PREP_IBM_CAROLINA_IDE_2: @@ -745,7 +856,6 @@ setup_ibm_pci = prep_tiger1_setup_pci; ppc_md.power_off = prep_sig750_poweroff; ppc_md.show_cpuinfo = prep_tiger1_cpuinfo; - ppc_md.progress = prep_tiger1_progress; break; } printk("\n"); @@ -808,8 +918,6 @@ /* vgacon.c needs to know where we mapped IO memory in io_block_mapping() */ vgacon_remap_base = 0xf0000000; conswitchp = &vga_con; -#elif defined(CONFIG_DUMMY_CONSOLE) - conswitchp = &dummy_con; #endif } @@ -821,18 +929,19 @@ static void __init prep_calibrate_decr(void) { -#ifdef CONFIG_PREP_RESIDUAL - unsigned long freq, divisor = 4; + if (have_residual_data) { + unsigned long freq, divisor = 4; - if ( res->VitalProductData.ProcessorBusHz ) { - freq = res->VitalProductData.ProcessorBusHz; - printk("time_init: decrementer frequency = %lu.%.6lu MHz\n", - (freq/divisor)/1000000, - (freq/divisor)%1000000); - tb_to_us = mulhwu_scale_factor(freq/divisor, 1000000); - tb_ticks_per_jiffy = freq / HZ / divisor; - } else -#endif + if ( res->VitalProductData.ProcessorBusHz ) { + freq = res->VitalProductData.ProcessorBusHz; + printk("time_init: decrementer frequency = %lu.%.6lu MHz\n", + (freq/divisor)/1000000, + (freq/divisor)%1000000); + tb_to_us = mulhwu_scale_factor(freq/divisor, 1000000); + tb_ticks_per_jiffy = freq / HZ / divisor; + } + } + else todc_calibrate_decr(); } @@ -863,6 +972,12 @@ } for ( i = 0 ; i < NUM_8259_INTERRUPTS ; i++ ) irq_desc[i].handler = &i8259_pic; + + if (have_residual_data) { + i8259_init(residual_isapic_addr()); + return; + } + /* If we have a Raven PCI bridge or a Hawk PCI bridge / Memory * controller, we poll (as they have a different int-ack address). */ early_read_config_dword(NULL, 0, 0, PCI_VENDOR_ID, &pci_viddid); @@ -1000,17 +1115,26 @@ DMA_MODE_WRITE = 0x48; /* figure out what kind of prep workstation we are */ -#ifdef CONFIG_PREP_RESIDUAL - if ( res->ResidualLength != 0 ) { + if (have_residual_data) { if ( !strncmp(res->VitalProductData.PrintableModel,"IBM",3) ) _prep_type = _PREP_IBM; else _prep_type = _PREP_Motorola; - } else /* assume motorola if no residual (netboot?) */ -#endif - { + } + else { + /* assume motorola if no residual (netboot?) */ _prep_type = _PREP_Motorola; } + +#ifdef CONFIG_PREP_PRESIDUAL + /* Switch off all residual data processing if the user requests it */ + if (strstr(cmd_line, "noresidual") != NULL) + res = NULL; +#endif + + /* Initialise progress early to get maximum benefit */ + prep_set_bat(); + ibm_statusled_init(); ppc_md.setup_arch = prep_setup_arch; ppc_md.show_percpuinfo = prep_show_percpuinfo; diff -Nru a/arch/ppc/platforms/prpmc750.c b/arch/ppc/platforms/prpmc750.c --- a/arch/ppc/platforms/prpmc750.c 2004-08-25 22:01:56 -07:00 +++ b/arch/ppc/platforms/prpmc750.c 2004-08-25 22:01:56 -07:00 @@ -193,10 +193,6 @@ ROOT_DEV = Root_SDA2; #endif -#ifdef CONFIG_DUMMY_CONSOLE - conswitchp = &dummy_con; -#endif - OpenPIC_InitSenses = prpmc750_openpic_initsenses; OpenPIC_NumInitSenses = sizeof(prpmc750_openpic_initsenses); diff -Nru a/arch/ppc/platforms/prpmc750.h b/arch/ppc/platforms/prpmc750.h --- a/arch/ppc/platforms/prpmc750.h 2004-08-25 22:01:54 -07:00 +++ b/arch/ppc/platforms/prpmc750.h 2004-08-25 22:01:54 -07:00 @@ -5,20 +5,16 @@ * * Author: Matt Porter * - * Copyright 2001 MontaVista Software Inc. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. + * 2001-2004 (c) MontaVista, Software, Inc. This file is licensed under + * the terms of the GNU General Public License version 2. This program + * is licensed "as is" without any warranty of any kind, whether express + * or implied. */ #ifdef __KERNEL__ #ifndef __ASM_PRPMC750_H__ #define __ASM_PRPMC750_H__ -#include - /* * Due to limiations imposed by legacy hardware (primaryily IDE controllers), * the PrPMC750 carrier board operates using a PReP address map. @@ -80,6 +76,20 @@ #define PRPMC750_TBEN_REG 0xfef880c0 #define PRPMC750_TBEN_MASK 0x01 + +/* UART Defines. */ +#define RS_TABLE_SIZE 4 + +/* Rate for the 1.8432 Mhz clock for the onboard serial chip */ +#define BASE_BAUD (PRPMC750_BASE_BAUD / 16) + +#define STD_COM_FLAGS ASYNC_BOOT_AUTOCONF + +#define SERIAL_PORT_DFNS \ + { 0, BASE_BAUD, PRPMC750_SERIAL_0, 1, STD_COM_FLAGS, \ + iomem_base: (unsigned char *)PRPMC750_SERIAL_0, \ + iomem_reg_shift: 4, \ + io_type: SERIAL_IO_MEM } /* ttyS0 */ #endif /* __ASM_PRPMC750_H__ */ #endif /* __KERNEL__ */ diff -Nru a/arch/ppc/platforms/prpmc750_serial.h b/arch/ppc/platforms/prpmc750_serial.h --- a/arch/ppc/platforms/prpmc750_serial.h 2004-08-25 22:01:54 -07:00 +++ /dev/null Wed Dec 31 16:00:00 196900 @@ -1,43 +0,0 @@ -/* - * include/asm-ppc/platforms/prpmc750_serial.h - * - * Motorola PrPMC750 serial support - * - * Author: Matt Porter - * - * 2001 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2. This program - * is licensed "as is" without any warranty of any kind, whether express - * or implied. - */ - -#ifdef __KERNEL__ -#ifndef __ASM_PRPMC750_SERIAL_H__ -#define __ASM_PRPMC750_SERIAL_H__ - -#include -#include - -#define RS_TABLE_SIZE 4 - -/* Rate for the 1.8432 Mhz clock for the onboard serial chip */ -#define BASE_BAUD (PRPMC750_BASE_BAUD / 16) - -#ifndef SERIAL_MAGIC_KEY -#define kernel_debugger ppc_kernel_debug -#endif - -#ifdef CONFIG_SERIAL_DETECT_IRQ -#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_SKIP_TEST|ASYNC_AUTO_IRQ) -#else -#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_SKIP_TEST) -#endif - -#define SERIAL_PORT_DFNS \ - { 0, BASE_BAUD, PRPMC750_SERIAL_0, 1, STD_COM_FLAGS, \ - iomem_base: (unsigned char *)PRPMC750_SERIAL_0, \ - iomem_reg_shift: 4, \ - io_type: SERIAL_IO_MEM } /* ttyS0 */ - -#endif /* __ASM_PRPMC750_SERIAL_H__ */ -#endif /* __KERNEL__ */ diff -Nru a/arch/ppc/platforms/prpmc800.c b/arch/ppc/platforms/prpmc800.c --- a/arch/ppc/platforms/prpmc800.c 2004-08-25 22:01:55 -07:00 +++ b/arch/ppc/platforms/prpmc800.c 2004-08-25 22:01:55 -07:00 @@ -309,10 +309,6 @@ ROOT_DEV = Root_SDA2; #endif -#ifdef CONFIG_DUMMY_CONSOLE - conswitchp = &dummy_con; -#endif - printk(KERN_INFO "Port by MontaVista Software, Inc. " "(source@mvista.com)\n"); } diff -Nru a/arch/ppc/platforms/prpmc800.h b/arch/ppc/platforms/prpmc800.h --- a/arch/ppc/platforms/prpmc800.h 2004-08-25 22:01:56 -07:00 +++ b/arch/ppc/platforms/prpmc800.h 2004-08-25 22:01:56 -07:00 @@ -5,12 +5,10 @@ * * Author: Dale Farnsworth * - * Copyright 2001 MontaVista Software Inc. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. + * 2001-2004 (c) MontaVista, Software, Inc. This file is licensed under + * the terms of the GNU General Public License version 2. This program + * is licensed "as is" without any warranty of any kind, whether express + * or implied. */ /* * From Processor to PCI: @@ -62,5 +60,23 @@ */ #define PRPMC800_INT_IRQ 16 #define PRPMC800_INT_PRI 15 + +/* UART Defines. */ +#define RS_TABLE_SIZE 4 + +/* Rate for the 1.8432 Mhz clock for the onboard serial chip */ +#define BASE_BAUD (PRPMC800_BASE_BAUD / 16) + +#define STD_COM_FLAGS ASYNC_BOOT_AUTOCONF + +/* UARTS are at IRQ 16 */ +#define STD_SERIAL_PORT_DFNS \ + { 0, BASE_BAUD, PRPMC800_SERIAL_1, 16, STD_COM_FLAGS, /* ttyS0 */\ + iomem_base: (unsigned char *)PRPMC800_SERIAL_1, \ + iomem_reg_shift: 0, \ + io_type: SERIAL_IO_MEM }, + +#define SERIAL_PORT_DFNS \ + STD_SERIAL_PORT_DFNS #endif /* __ASMPPC_PRPMC800_H */ diff -Nru a/arch/ppc/platforms/prpmc800_serial.h b/arch/ppc/platforms/prpmc800_serial.h --- a/arch/ppc/platforms/prpmc800_serial.h 2004-08-25 22:01:56 -07:00 +++ /dev/null Wed Dec 31 16:00:00 196900 @@ -1,49 +0,0 @@ -/* - * arch/ppc/platforms/prpmc800_serial.h - * - * Definitions for Motorola MCG PRPMC800 cPCI board support - * - * Author: Dale Farnsworth dale.farnsworth@mvista.com - * - * 2001 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2. This program - * is licensed "as is" without any warranty of any kind, whether express - * or implied. - */ - -#ifndef __ASMPPC_PRPMC800_SERIAL_H -#define __ASMPPC_PRPMC800_SERIAL_H - -#include -#include - -#ifdef CONFIG_SERIAL_MANY_PORTS -#define RS_TABLE_SIZE 64 -#else -#define RS_TABLE_SIZE 4 -#endif - -/* Rate for the 1.8432 Mhz clock for the onboard serial chip */ -#define BASE_BAUD (PRPMC800_BASE_BAUD / 16) - -#ifndef SERIAL_MAGIC_KEY -#define kernel_debugger ppc_kernel_debug -#endif - -#ifdef CONFIG_SERIAL_DETECT_IRQ -#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_SKIP_TEST|ASYNC_AUTO_IRQ) -#else -#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_SKIP_TEST) -#endif - -/* UARTS are at IRQ 16 */ -#define STD_SERIAL_PORT_DFNS \ - { 0, BASE_BAUD, PRPMC800_SERIAL_1, 16, STD_COM_FLAGS, /* ttyS0 */\ - iomem_base: (unsigned char *)PRPMC800_SERIAL_1, \ - iomem_reg_shift: 0, \ - io_type: SERIAL_IO_MEM }, - -#define SERIAL_PORT_DFNS \ - STD_SERIAL_PORT_DFNS - -#endif /* __ASMPPC_PRPMC800_SERIAL_H */ diff -Nru a/arch/ppc/platforms/residual.c b/arch/ppc/platforms/residual.c --- a/arch/ppc/platforms/residual.c 2004-08-25 22:01:54 -07:00 +++ b/arch/ppc/platforms/residual.c 2004-08-25 22:01:54 -07:00 @@ -504,7 +504,7 @@ #define did dev->DeviceId /* make sure we have residual data first */ - if ( res->ResidualLength == 0 ) + if (!have_residual_data) return; printk("Residual: %ld devices\n", res->ActualNumDevices); @@ -639,7 +639,7 @@ #define did dev->DeviceId /* make sure we have residual data first */ - if ( res->ResidualLength == 0 ) + if (!have_residual_data) return; printk("Residual: %ld devices\n", res->ActualNumDevices); for ( i = 0; @@ -790,7 +790,7 @@ int n) { int i; - if ( !res->ResidualLength ) return NULL; + if (!have_residual_data) return NULL; for (i=0; iActualNumDevices; i++) { #define Dev res->Devices[i].DeviceId if ( (Dev.BusId&BusMask) && @@ -813,7 +813,7 @@ int n) { int i; - if ( !res->ResidualLength ) return NULL; + if (!have_residual_data) return NULL; for (i=0; iActualNumDevices; i++) { #define Dev res->Devices[i].DeviceId if ( (Dev.BusId&BusMask) && @@ -827,6 +827,129 @@ return NULL; } +static int __init +residual_scan_pcibridge(PnP_TAG_PACKET * pkt, struct pci_dev *dev) +{ + int irq = -1; + +#define data pkt->L4_Pack.L4_Data.L4_PPCPack.PPCData + if (dev->bus->number == data[16]) { + int i, size; + + size = 3 + ld_le16((u_short *) (&pkt->L4_Pack.Count0)); + for (i = 20; i < size - 4; i += 12) { + unsigned char pin; + int line_irq; + + if (dev->devfn != data[i + 1]) + continue; + + pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin); + if (pin) { + line_irq = ld_le16((unsigned short *) + (&data[i + 4 + 2 * (pin - 1)])); + irq = (line_irq == 0xffff) ? 0 + : line_irq & 0x7fff; + } else + irq = 0; + + break; + } + } +#undef data + + return irq; +} + +int __init +residual_pcidev_irq(struct pci_dev *dev) +{ + int i = 0; + int irq = -1; + PPC_DEVICE *bridge; + + while ((bridge = residual_find_device + (-1, NULL, BridgeController, PCIBridge, -1, i++))) { + + PnP_TAG_PACKET *pkt; + if (bridge->AllocatedOffset) { + pkt = PnP_find_large_vendor_packet(res->DevicePnPHeap + + bridge->AllocatedOffset, 3, 0); + if (!pkt) + continue; + + irq = residual_scan_pcibridge(pkt, dev); + if (irq != -1) + break; + } + } + + return (irq < 0) ? 0 : irq; +} + +void __init residual_irq_mask(char *irq_edge_mask_lo, char *irq_edge_mask_hi) +{ + PPC_DEVICE *dev; + int i = 0; + unsigned short irq_mask = 0x000; /* default to edge */ + + while ((dev = residual_find_device(-1, NULL, -1, -1, -1, i++))) { + PnP_TAG_PACKET *pkt; + unsigned short mask; + int size; + int offset = dev->AllocatedOffset; + + if (!offset) + continue; + + pkt = PnP_find_packet(res->DevicePnPHeap + offset, + IRQFormat, 0); + if (!pkt) + continue; + + size = tag_small_count(pkt->S1_Pack.Tag) + 1; + mask = ld_le16((unsigned short *)pkt->S4_Pack.IRQMask); + if (size > 3 && (pkt->S4_Pack.IRQInfo & 0x0c)) + irq_mask |= mask; + } + + *irq_edge_mask_lo = irq_mask & 0xff; + *irq_edge_mask_hi = irq_mask >> 8; +} + +unsigned int __init residual_isapic_addr(void) +{ + PPC_DEVICE *isapic; + PnP_TAG_PACKET *pkt; + unsigned int addr; + + isapic = residual_find_device(~0, NULL, SystemPeripheral, + ProgrammableInterruptController, + ISA_PIC, 0); + if (!isapic) + goto unknown; + + pkt = PnP_find_large_vendor_packet(res->DevicePnPHeap + + isapic->AllocatedOffset, 9, 0); + if (!pkt) + goto unknown; + +#define p pkt->L4_Pack.L4_Data.L4_PPCPack + /* Must be 32-bit memory address */ + if (!((p.PPCData[0] == 2) && (p.PPCData[1] == 32))) + goto unknown; + + /* It doesn't seem to work where length != 1 (what can I say? :-/ ) */ + if (ld_le32((unsigned int *)(p.PPCData + 12)) != 1) + goto unknown; + + addr = ld_le32((unsigned int *) (p.PPCData + 4)); +#undef p + return addr; +unknown: + return 0; +} + PnP_TAG_PACKET *PnP_find_packet(unsigned char *p, unsigned packet_tag, int n) @@ -901,7 +1024,7 @@ int __init proc_prep_residual_init(void) { - if (res->ResidualLength) + if (have_residual_data) create_proc_read_entry("residual", S_IRUGO, NULL, proc_prep_residual_read, NULL); return 0; diff -Nru a/arch/ppc/platforms/rpx8260.c b/arch/ppc/platforms/rpx8260.c --- a/arch/ppc/platforms/rpx8260.c 2004-08-25 22:01:55 -07:00 +++ /dev/null Wed Dec 31 16:00:00 196900 @@ -1,65 +0,0 @@ -/* - * arch/ppc/platforms/rpx8260.c - * - * RPC EP8260 platform support - * - * Author: Dan Malek - * Derived from: pq2ads_setup.c by Kumar - * - * Copyright 2004 Embedded Edge, LLC - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - */ - -#include -#include - -#include -#include - -static void (*callback_setup_arch)(void); - -extern unsigned char __res[sizeof(bd_t)]; - -extern void m8260_init(unsigned long r3, unsigned long r4, - unsigned long r5, unsigned long r6, unsigned long r7); - -static int -ep8260_show_cpuinfo(struct seq_file *m) -{ - bd_t *binfo = (bd_t *)__res; - - seq_printf(m, "vendor\t\t: RPC\n" - "machine\t\t: EP8260 PPC\n" - "\n" - "mem size\t\t: 0x%08x\n" - "console baud\t\t: %d\n" - "\n", - binfo->bi_memsize, - binfo->bi_baudrate); - return 0; -} - -static void __init -ep8260_setup_arch(void) -{ - printk("RPC EP8260 Port\n"); - callback_setup_arch(); -} - -void __init -platform_init(unsigned long r3, unsigned long r4, unsigned long r5, - unsigned long r6, unsigned long r7) -{ - /* Generic 8260 platform initialization */ - m8260_init(r3, r4, r5, r6, r7); - - /* Anything special for this platform */ - ppc_md.show_cpuinfo = ep8260_show_cpuinfo; - - callback_setup_arch = ppc_md.setup_arch; - ppc_md.setup_arch = ep8260_setup_arch; -} diff -Nru a/arch/ppc/platforms/rpx8260.h b/arch/ppc/platforms/rpx8260.h --- a/arch/ppc/platforms/rpx8260.h 2004-08-25 22:01:55 -07:00 +++ b/arch/ppc/platforms/rpx8260.h 2004-08-25 22:01:55 -07:00 @@ -70,5 +70,12 @@ #define PHY_INTERRUPT SIU_INT_IRQ7 +/* For our show_cpuinfo hooks. */ +#define CPUINFO_VENDOR "Embedded Planet" +#define CPUINFO_MACHINE "EP8260 PowerPC" + +/* Warm reset vector. */ +#define BOOTROM_RESTART_ADDR ((uint)0xfff00104) + #endif /* __ASM_PLATFORMS_RPX8260_H__ */ #endif /* __KERNEL__ */ diff -Nru a/arch/ppc/platforms/sandpoint.c b/arch/ppc/platforms/sandpoint.c --- a/arch/ppc/platforms/sandpoint.c 2004-08-25 22:01:56 -07:00 +++ b/arch/ppc/platforms/sandpoint.c 2004-08-25 22:01:56 -07:00 @@ -303,10 +303,6 @@ /* Lookup PCI host bridges */ sandpoint_find_bridges(); -#ifdef CONFIG_DUMMY_CONSOLE - conswitchp = &dummy_con; -#endif - printk(KERN_INFO "Motorola SPS Sandpoint Test Platform\n"); printk(KERN_INFO "Port by MontaVista Software, Inc. (source@mvista.com)\n"); diff -Nru a/arch/ppc/platforms/sbc82xx.c b/arch/ppc/platforms/sbc82xx.c --- a/arch/ppc/platforms/sbc82xx.c 2004-08-25 22:01:54 -07:00 +++ b/arch/ppc/platforms/sbc82xx.c 2004-08-25 22:01:54 -07:00 @@ -16,10 +16,10 @@ */ #include -#include #include #include #include +#include #include #include @@ -29,39 +29,12 @@ #include #include -static void (*callback_setup_arch)(void); static void (*callback_init_IRQ)(void); extern unsigned char __res[sizeof(bd_t)]; -extern void m8260_init(unsigned long r3, unsigned long r4, - unsigned long r5, unsigned long r6, unsigned long r7); - extern void (*late_time_init)(void); -static int -sbc82xx_show_cpuinfo(struct seq_file *m) -{ - bd_t *binfo = (bd_t *)__res; - - seq_printf(m, "vendor\t\t: Wind River\n" - "machine\t\t: SBC PowerQUICC II\n" - "\n" - "mem size\t\t: 0x%08lx\n" - "console baud\t\t: %ld\n" - "\n", - binfo->bi_memsize, - binfo->bi_baudrate); - return 0; -} - -static void __init -sbc82xx_setup_arch(void) -{ - printk("SBC PowerQUICC II Port\n"); - callback_setup_arch(); -} - #ifdef CONFIG_GEN_RTC TODC_ALLOC(); @@ -237,7 +210,6 @@ return PCI_IRQ_TABLE_LOOKUP; } - static void __devinit quirk_sbc8260_cardbus(struct pci_dev *pdev) { uint32_t ctrl; @@ -259,20 +231,13 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1420, quirk_sbc8260_cardbus); void __init -platform_init(unsigned long r3, unsigned long r4, unsigned long r5, - unsigned long r6, unsigned long r7) +m82xx_board_init(void) { - /* Generic 8260 platform initialization */ - m8260_init(r3, r4, r5, r6, r7); - /* u-boot may be using one of the FCC Ethernet devices. Use the MAC address to the SCC. */ __res[offsetof(bd_t, bi_enetaddr[5])] &= ~3; /* Anything special for this platform */ - ppc_md.show_cpuinfo = sbc82xx_show_cpuinfo; - - callback_setup_arch = ppc_md.setup_arch; callback_init_IRQ = ppc_md.init_IRQ; ppc_md.setup_arch = sbc82xx_setup_arch; diff -Nru a/arch/ppc/platforms/sbc82xx.h b/arch/ppc/platforms/sbc82xx.h --- a/arch/ppc/platforms/sbc82xx.h 2004-08-25 22:01:56 -07:00 +++ b/arch/ppc/platforms/sbc82xx.h 2004-08-25 22:01:56 -07:00 @@ -18,6 +18,10 @@ #define SBC82xx_MACADDR_NVRAM_FCC2 0x220000d5 /* JP7A */ #define SBC82xx_MACADDR_NVRAM_FCC3 0x220000db /* JP7B */ +/* For our show_cpuinfo hooks. */ +#define CPUINFO_VENDOR "Wind River" +#define CPUINFO_MACHINE "SBC PowerQUICC II" + #define BOOTROM_RESTART_ADDR ((uint)0x40000104) #define SBC82xx_PC_IRQA (NR_SIU_INTS+0) diff -Nru a/arch/ppc/platforms/spruce.c b/arch/ppc/platforms/spruce.c --- a/arch/ppc/platforms/spruce.c 2004-08-25 22:01:54 -07:00 +++ b/arch/ppc/platforms/spruce.c 2004-08-25 22:01:54 -07:00 @@ -228,11 +228,6 @@ ROOT_DEV = Root_SDA1; #endif -#ifdef CONFIG_VT - conswitchp = &dummy_con; -#endif - - /* Identify the system */ printk(KERN_INFO "System Identification: IBM Spruce\n"); printk(KERN_INFO "Port by MontaVista Software, Inc. (source@mvista.com)\n"); diff -Nru a/arch/ppc/platforms/tqm8260.h b/arch/ppc/platforms/tqm8260.h --- a/arch/ppc/platforms/tqm8260.h 2004-08-25 22:01:55 -07:00 +++ b/arch/ppc/platforms/tqm8260.h 2004-08-25 22:01:55 -07:00 @@ -14,6 +14,10 @@ #define CPM_MAP_ADDR ((uint)0xFFF00000) #define PHY_INTERRUPT 25 +/* For our show_cpuinfo hooks. */ +#define CPUINFO_VENDOR "IN2 Systems" +#define CPUINFO_MACHINE "TQM8260 PowerPC" + #define BOOTROM_RESTART_ADDR ((uint)0x40000104) #endif /* __TQM8260_PLATFORM */ diff -Nru a/arch/ppc/platforms/tqm8260_setup.c b/arch/ppc/platforms/tqm8260_setup.c --- a/arch/ppc/platforms/tqm8260_setup.c 2004-08-25 22:01:55 -07:00 +++ b/arch/ppc/platforms/tqm8260_setup.c 2004-08-25 22:01:55 -07:00 @@ -14,33 +14,12 @@ * option) any later version. */ -#include -#include +#include #include #include #include -static void (*callback_setup_arch)(void); - -extern unsigned char __res[sizeof(bd_t)]; - -extern void m8260_init(unsigned long r3, unsigned long r4, - unsigned long r5, unsigned long r6, unsigned long r7); - -static int -tqm8260_show_cpuinfo(struct seq_file *m) -{ - bd_t *binfo = (bd_t *)__res; - - seq_printf(m, "vendor\t\t: IN2 Systems\n" - "machine\t\t: TQM8260 PowerPC\n" - "mem size\t\t: 0x%08x\n" - "\n", - binfo->bi_memsize); - return 0; -} - static int tqm8260_set_rtc_time(unsigned long time) { @@ -56,24 +35,10 @@ return ((cpm2_map_t *)CPM_MAP_ADDR)->im_sit.sit_tmcnt; } -static void __init -tqm8260_setup_arch(void) -{ - printk("IN2 Systems TQM8260 port\n"); - callback_setup_arch(); -} - void __init -platform_init(unsigned long r3, unsigned long r4, unsigned long r5, - unsigned long r6, unsigned long r7) +m82xx_board_init(void) { - /* Generic 8260 platform initialization */ - m8260_init(r3, r4, r5, r6, r7); - /* Anything special for this platform */ - ppc_md.show_cpuinfo = tqm8260_show_cpuinfo; ppc_md.set_rtc_time = tqm8260_set_rtc_time; ppc_md.get_rtc_time = tqm8260_get_rtc_time; - - callback_setup_arch = ppc_md.setup_arch; - ppc_md.setup_arch = tqm8260_setup_arch; +} diff -Nru a/arch/ppc/syslib/Makefile b/arch/ppc/syslib/Makefile --- a/arch/ppc/syslib/Makefile 2004-08-25 22:01:54 -07:00 +++ b/arch/ppc/syslib/Makefile 2004-08-25 22:01:54 -07:00 @@ -5,6 +5,8 @@ CFLAGS_prom_init.o += -fPIC CFLAGS_btext.o += -fPIC +wdt-mpc8xx-$(CONFIG_8xx_WDT) += m8xx_wdt.o + obj-$(CONFIG_PPCBUG_NVRAM) += prep_nvram.o obj-$(CONFIG_PPC_OCP) += ocp.o obj-$(CONFIG_IBM_OCP) += ibm_ocp.o @@ -22,7 +24,7 @@ obj-$(CONFIG_PCI) += indirect_pci.o pci_auto.o ppc405_pci.o endif endif -obj-$(CONFIG_8xx) += m8xx_setup.o ppc8xx_pic.o +obj-$(CONFIG_8xx) += m8xx_setup.o ppc8xx_pic.o $(wdt-mpc8xx-y) ifeq ($(CONFIG_8xx),y) obj-$(CONFIG_PCI) += qspan_pci.o i8259.o endif diff -Nru a/arch/ppc/syslib/cpm2_pic.c b/arch/ppc/syslib/cpm2_pic.c --- a/arch/ppc/syslib/cpm2_pic.c 2004-08-25 22:01:55 -07:00 +++ b/arch/ppc/syslib/cpm2_pic.c 2004-08-25 22:01:55 -07:00 @@ -1,12 +1,3 @@ -#include -#include -#include -#include -#include -#include -#include -#include "cpm2_pic.h" - /* The CPM2 internal interrupt controller. It is usually * the only interrupt controller. * There are two 32-bit registers (high/low) for up to 64 @@ -18,6 +9,18 @@ * We create two tables, indexed by vector number, to indicate * which register to use and which bit in the register to use. */ + +#include +#include +#include +#include +#include + +#include +#include + +#include "cpm2_pic.h" + static u_char irq_to_siureg[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, @@ -123,9 +126,5 @@ if (irq == 0) return(-1); -#if 0 - irq += ppc8260_pic.irq_offset; -#endif return irq; } - diff -Nru a/arch/ppc/syslib/cpm2_pic.h b/arch/ppc/syslib/cpm2_pic.h --- a/arch/ppc/syslib/cpm2_pic.h 2004-08-25 22:01:56 -07:00 +++ b/arch/ppc/syslib/cpm2_pic.h 2004-08-25 22:01:56 -07:00 @@ -1,13 +1,7 @@ #ifndef _PPC_KERNEL_CPM2_H #define _PPC_KERNEL_CPM2_H -#include - extern struct hw_interrupt_type cpm2_pic; - -void cpm2_pic_init(void); -void cpm2_do_IRQ(struct pt_regs *regs, - int cpu); -int cpm2_get_irq(struct pt_regs *regs); +extern int cpm2_get_irq(struct pt_regs *regs); #endif /* _PPC_KERNEL_CPM2_H */ diff -Nru a/arch/ppc/syslib/hawk_common.c b/arch/ppc/syslib/hawk_common.c --- a/arch/ppc/syslib/hawk_common.c 2004-08-25 22:01:55 -07:00 +++ b/arch/ppc/syslib/hawk_common.c 2004-08-25 22:01:55 -07:00 @@ -285,3 +285,35 @@ return total; } + +int __init +hawk_mpic_init(unsigned int pci_mem_offset) +{ + unsigned short devid; + unsigned int pci_membase; + + /* Check the first PCI device to see if it is a Raven or Hawk. */ + early_read_config_word(0, 0, 0, PCI_DEVICE_ID, &devid); + + switch (devid) { + case PCI_DEVICE_ID_MOTOROLA_RAVEN: + case PCI_DEVICE_ID_MOTOROLA_HAWK: + break; + default: + OpenPIC_Addr = NULL; + return 1; + } + + /* Read the memory base register. */ + early_read_config_dword(0, 0, 0, PCI_BASE_ADDRESS_1, &pci_membase); + + if (pci_membase == 0) { + OpenPIC_Addr = NULL; + return 1; + } + + /* Map the MPIC registers to virtual memory. */ + OpenPIC_Addr = ioremap(pci_membase + pci_mem_offset, 0x22000); + + return 0; +} diff -Nru a/arch/ppc/syslib/m8260_pci.h b/arch/ppc/syslib/m8260_pci.h --- a/arch/ppc/syslib/m8260_pci.h 2004-08-25 22:01:56 -07:00 +++ b/arch/ppc/syslib/m8260_pci.h 2004-08-25 22:01:56 -07:00 @@ -66,6 +66,7 @@ #endif #ifdef CONFIG_8260_PCI9 +struct pci_controller; extern void setup_m8260_indirect_pci(struct pci_controller* hose, u32 cfg_addr, u32 cfg_data); #else diff -Nru a/arch/ppc/syslib/m8260_setup.c b/arch/ppc/syslib/m8260_setup.c --- a/arch/ppc/syslib/m8260_setup.c 2004-08-25 22:01:55 -07:00 +++ b/arch/ppc/syslib/m8260_setup.c 2004-08-25 22:01:55 -07:00 @@ -1,5 +1,5 @@ /* - * arch/ppc/kernel/setup.c + * arch/ppc/syslib/m8260_setup.c * * Copyright (C) 1995 Linus Torvalds * Adapted from 'alpha' version by Gary Thomas @@ -8,36 +8,20 @@ * Further modified for generic 8xx and 8260 by Dan. */ -/* - * bootup setup stuff.. - */ - #include -#include #include #include #include #include -#include -#include #include -#include -#include -#include -#include -#include -#include #include #include -#include -#include #include +#include #include -#include #include #include -#include #include #include #include @@ -46,10 +30,6 @@ #include "cpm2_pic.h" -static int m8260_set_rtc_time(unsigned long time); -static unsigned long m8260_get_rtc_time(void); -static void m8260_calibrate_decr(void); - unsigned char __res[sizeof(bd_t)]; extern void cpm2_reset(void); @@ -59,8 +39,10 @@ static void __init m8260_setup_arch(void) { - /* Reset the Communication Processor Module. - */ + /* Print out Vendor and Machine info. */ + printk(KERN_INFO "%s %s port\n", CPUINFO_VENDOR, CPUINFO_MACHINE); + + /* Reset the Communication Processor Module. */ cpm2_reset(); #ifdef CONFIG_8260_PCI9 /* Initialise IDMA for PCI erratum workaround */ @@ -69,6 +51,10 @@ #ifdef CONFIG_PCI_8260 m8260_find_bridges(); #endif +#ifdef CONFIG_BLK_DEV_INITRD + if (initrd_start) + ROOT_DEV = Root_RAM0; +#endif } /* The decrementer counts at the system (internal) clock frequency @@ -77,7 +63,7 @@ static void __init m8260_calibrate_decr(void) { - bd_t *binfo = (bd_t *)__res; + bd_t *binfo = (bd_t *)__res; int freq, divisor; freq = binfo->bi_busfreq; @@ -145,18 +131,22 @@ } static int -m8260_show_percpuinfo(struct seq_file *m, int i) +m8260_show_cpuinfo(struct seq_file *m) { - bd_t *bp; - - bp = (bd_t *)__res; + bd_t *bp = (bd_t *)__res; - seq_printf(m, "core clock\t: %ld MHz\n" - "CPM clock\t: %ld MHz\n" - "bus clock\t: %ld MHz\n", - bp->bi_intfreq / 1000000, - bp->bi_cpmfreq / 1000000, - bp->bi_busfreq / 1000000); + seq_printf(m, "vendor\t\t: %s\n" + "machine\t\t: %s\n" + "\n" + "mem size\t\t: 0x%08x\n" + "console baud\t\t: %d\n" + "\n" + "core clock\t: %u MHz\n" + "CPM clock\t: %u MHz\n" + "bus clock\t: %u MHz\n", + CPUINFO_VENDOR, CPUINFO_MACHINE, bp->bi_memsize, + bp->bi_baudrate, bp->bi_intfreq / 1000000, + bp->bi_cpmfreq / 1000000, bp->bi_busfreq / 1000000); return 0; } @@ -170,7 +160,6 @@ m8260_init_IRQ(void) { int i; - void cpm_interrupt_init(void); for ( i = 0 ; i < NR_SIU_INTS ; i++ ) irq_desc[i].handler = &cpm2_pic; @@ -190,10 +179,7 @@ static unsigned long __init m8260_find_end_of_memory(void) { - bd_t *binfo; - extern unsigned char __res[]; - - binfo = (bd_t *)__res; + bd_t *binfo = (bd_t *)__res; return binfo->bi_memsize; } @@ -216,6 +202,12 @@ io_block_mapping(IO_VIRT_ADDR, IO_PHYS_ADDR, 0x10000000, _PAGE_IO); } +/* Place-holder for board-specific init */ +void __attribute__ ((weak)) __init +m82xx_board_init(void) +{ +} + /* Inputs: * r3 - Optional pointer to a board information structure. * r4 - Optional pointer to the physical starting address of the init RAM @@ -228,7 +220,7 @@ * command-line parameters. */ void __init -m8260_init(unsigned long r3, unsigned long r4, unsigned long r5, +platform_init(unsigned long r3, unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7) { parse_bootinfo(find_bootinfo()); @@ -249,18 +241,18 @@ strcpy(cmd_line, (char *)(r6+KERNELBASE)); } + /* Call back for board-specific settings. */ + m82xx_board_init(); + ppc_md.setup_arch = m8260_setup_arch; - ppc_md.show_percpuinfo = m8260_show_percpuinfo; - ppc_md.irq_canonicalize = NULL; + ppc_md.show_cpuinfo = m8260_show_cpuinfo; ppc_md.init_IRQ = m8260_init_IRQ; ppc_md.get_irq = cpm2_get_irq; - ppc_md.init = NULL; ppc_md.restart = m8260_restart; ppc_md.power_off = m8260_power_off; ppc_md.halt = m8260_halt; - ppc_md.time_init = NULL; ppc_md.set_rtc_time = m8260_set_rtc_time; ppc_md.get_rtc_time = m8260_get_rtc_time; ppc_md.calibrate_decr = m8260_calibrate_decr; diff -Nru a/arch/ppc/syslib/m8xx_setup.c b/arch/ppc/syslib/m8xx_setup.c --- a/arch/ppc/syslib/m8xx_setup.c 2004-08-25 22:01:55 -07:00 +++ b/arch/ppc/syslib/m8xx_setup.c 2004-08-25 22:01:55 -07:00 @@ -60,6 +60,11 @@ extern void m8xx_cpm_reset(uint); extern void rpxfb_alloc_pages(void); +void __attribute__ ((weak)) +board_init(void) +{ +} + void __init m8xx_setup_arch(void) { @@ -102,6 +107,7 @@ } #endif #endif + board_init(); } void diff -Nru a/arch/ppc/syslib/m8xx_wdt.c b/arch/ppc/syslib/m8xx_wdt.c --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/arch/ppc/syslib/m8xx_wdt.c 2004-08-25 22:01:56 -07:00 @@ -0,0 +1,99 @@ +/* + * m8xx_wdt.c - MPC8xx watchdog driver + * + * Author: Florian Schirmer + * + * 2002 (c) Florian Schirmer This file is licensed under + * the terms of the GNU General Public License version 2. This program + * is licensed "as is" without any warranty of any kind, whether express + * or implied. + */ + +#include +#include +#include +#include +#include +#include + +static int wdt_timeout; + +void m8xx_wdt_reset(void) +{ + volatile immap_t *imap = (volatile immap_t *)IMAP_ADDR; + + imap->im_siu_conf.sc_swsr = 0x556c; /* write magic1 */ + imap->im_siu_conf.sc_swsr = 0xaa39; /* write magic2 */ +} + +static irqreturn_t m8xx_wdt_interrupt(int irq, void *dev, struct pt_regs *regs) +{ + volatile immap_t *imap = (volatile immap_t *)IMAP_ADDR; + + m8xx_wdt_reset(); + + imap->im_sit.sit_piscr |= PISCR_PS; /* clear irq */ + + return IRQ_HANDLED; +} + +void __init m8xx_wdt_handler_install(bd_t * binfo) +{ + volatile immap_t *imap = (volatile immap_t *)IMAP_ADDR; + u32 pitc; + u32 sypcr; + u32 pitrtclk; + + sypcr = imap->im_siu_conf.sc_sypcr; + + if (!(sypcr & 0x04)) { + printk(KERN_NOTICE "m8xx_wdt: wdt disabled (SYPCR: 0x%08X)\n", + sypcr); + return; + } + + m8xx_wdt_reset(); + + printk(KERN_NOTICE + "m8xx_wdt: active wdt found (SWTC: 0x%04X, SWP: 0x%01X)\n", + (sypcr >> 16), sypcr & 0x01); + + wdt_timeout = (sypcr >> 16) & 0xFFFF; + + if (!wdt_timeout) + wdt_timeout = 0xFFFF; + + if (sypcr & 0x01) + wdt_timeout *= 2048; + + /* + * Fire trigger if half of the wdt ticked down + */ + + if (imap->im_sit.sit_rtcsc & RTCSC_38K) + pitrtclk = 9600; + else + pitrtclk = 8192; + + if ((wdt_timeout) > (UINT_MAX / pitrtclk)) + pitc = wdt_timeout / binfo->bi_intfreq * pitrtclk / 2; + else + pitc = pitrtclk * wdt_timeout / binfo->bi_intfreq / 2; + + imap->im_sit.sit_pitc = pitc << 16; + imap->im_sit.sit_piscr = + (mk_int_int_mask(PIT_INTERRUPT) << 8) | PISCR_PIE | PISCR_PTE; + + if (request_irq(PIT_INTERRUPT, m8xx_wdt_interrupt, 0, "watchdog", NULL)) + panic("m8xx_wdt: could not allocate watchdog irq!"); + + printk(KERN_NOTICE + "m8xx_wdt: keep-alive trigger installed (PITC: 0x%04X)\n", pitc); + + wdt_timeout /= binfo->bi_intfreq; +} + +int m8xx_wdt_get_timeout(void) +{ + return wdt_timeout; +} diff -Nru a/arch/ppc/syslib/m8xx_wdt.h b/arch/ppc/syslib/m8xx_wdt.h --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/arch/ppc/syslib/m8xx_wdt.h 2004-08-25 22:01:56 -07:00 @@ -0,0 +1,16 @@ +/* + * Author: Florian Schirmer + * + * 2002 (c) Florian Schirmer This file is licensed under + * the terms of the GNU General Public License version 2. This program + * is licensed "as is" without any warranty of any kind, whether express + * or implied. + */ +#ifndef _PPC_SYSLIB_M8XX_WDT_H +#define _PPC_SYSLIB_M8XX_WDT_H + +extern void m8xx_wdt_handler_install(bd_t * binfo); +extern int m8xx_wdt_get_timeout(void); +extern void m8xx_wdt_reset(void); + +#endif /* _PPC_SYSLIB_M8XX_WDT_H */ diff -Nru a/arch/ppc/syslib/ppc4xx_setup.c b/arch/ppc/syslib/ppc4xx_setup.c --- a/arch/ppc/syslib/ppc4xx_setup.c 2004-08-25 22:01:54 -07:00 +++ b/arch/ppc/syslib/ppc4xx_setup.c 2004-08-25 22:01:54 -07:00 @@ -61,10 +61,6 @@ #ifdef CONFIG_PCI ppc4xx_find_bridges(); #endif - -#if defined(CONFIG_FB) - conswitchp = &dummy_con; -#endif } /* diff -Nru a/arch/ppc64/Kconfig.debug b/arch/ppc64/Kconfig.debug --- a/arch/ppc64/Kconfig.debug 2004-08-25 22:01:56 -07:00 +++ b/arch/ppc64/Kconfig.debug 2004-08-25 22:01:56 -07:00 @@ -54,4 +54,16 @@ If in doubt, say N. +config SCHEDSTATS + bool "Collect scheduler statistics" + depends on DEBUG_KERNEL && PROC_FS + help + If you say Y here, additional code will be inserted into the + scheduler and related routines to collect statistics about + scheduler behavior and provide them in /proc/schedstat. These + stats may be useful for both tuning and debugging the scheduler + If you aren't debugging the scheduler or trying to tune a specific + application, you can say N to avoid the very slight overhead + this adds. + endmenu diff -Nru a/arch/ppc64/kernel/head.S b/arch/ppc64/kernel/head.S --- a/arch/ppc64/kernel/head.S 2004-08-25 22:01:55 -07:00 +++ b/arch/ppc64/kernel/head.S 2004-08-25 22:01:55 -07:00 @@ -1037,6 +1037,9 @@ * interrupts if necessary. */ beq .ret_from_except_lite + /* For a hash failure, we don't bother re-enabling interrupts */ + ble- 12f + /* * hash_page couldn't handle it, set soft interrupt enable back * to what it was before the trap. Note that .local_irq_restore @@ -1047,6 +1050,8 @@ b 11f #else beq fast_exception_return /* Return from exception on success */ + ble- 12f /* Failure return from hash_page */ + /* fall through */ #endif @@ -1064,6 +1069,15 @@ addi r3,r1,STACK_FRAME_OVERHEAD lwz r4,_DAR(r1) bl .bad_page_fault + b .ret_from_except + +/* We have a page fault that hash_page could handle but HV refused + * the PTE insertion + */ +12: bl .save_nvgprs + addi r3,r1,STACK_FRAME_OVERHEAD + lwz r4,_DAR(r1) + bl .low_hash_fault b .ret_from_except /* here we have a segment miss */ diff -Nru a/arch/ppc64/kernel/pSeries_lpar.c b/arch/ppc64/kernel/pSeries_lpar.c --- a/arch/ppc64/kernel/pSeries_lpar.c 2004-08-25 22:01:56 -07:00 +++ b/arch/ppc64/kernel/pSeries_lpar.c 2004-08-25 22:01:56 -07:00 @@ -377,7 +377,7 @@ lpar_rc = plpar_hcall(H_ENTER, flags, hpte_group, lhpte.dw0.dword0, lhpte.dw1.dword1, &slot, &dummy0, &dummy1); - if (lpar_rc == H_PTEG_Full) + if (unlikely(lpar_rc == H_PTEG_Full)) return -1; /* @@ -385,7 +385,7 @@ * will fail. However we must catch the failure in hash_page * or we will loop forever, so return -2 in this case. */ - if (lpar_rc != H_Success) + if (unlikely(lpar_rc != H_Success)) return -2; /* Because of iSeries, we have to pass down the secondary @@ -415,9 +415,7 @@ if (lpar_rc == H_Success) return i; - if (lpar_rc != H_Not_Found) - panic("Bad return code from pte remove rc = %lx\n", - lpar_rc); + BUG_ON(lpar_rc != H_Not_Found); slot_offset++; slot_offset &= 0x7; @@ -447,8 +445,7 @@ if (lpar_rc == H_Not_Found) return -1; - if (lpar_rc != H_Success) - panic("bad return code from pte protect rc = %lx\n", lpar_rc); + BUG_ON(lpar_rc != H_Success); return 0; } @@ -467,8 +464,7 @@ lpar_rc = plpar_pte_read(flags, slot, &dword0, &dummy_word1); - if (lpar_rc != H_Success) - panic("Error on pte read in get_hpte0 rc = %lx\n", lpar_rc); + BUG_ON(lpar_rc != H_Success); return dword0; } @@ -519,15 +515,12 @@ vpn = va >> PAGE_SHIFT; slot = pSeries_lpar_hpte_find(vpn); - if (slot == -1) - panic("updateboltedpp: Could not find page to bolt\n"); + BUG_ON(slot == -1); flags = newpp & 3; lpar_rc = plpar_pte_protect(flags, slot, 0); - if (lpar_rc != H_Success) - panic("Bad return code from pte bolted protect rc = %lx\n", - lpar_rc); + BUG_ON(lpar_rc != H_Success); } static void pSeries_lpar_hpte_invalidate(unsigned long slot, unsigned long va, @@ -546,8 +539,7 @@ if (lpar_rc == H_Not_Found) return; - if (lpar_rc != H_Success) - panic("Bad return code from invalidate rc = %lx\n", lpar_rc); + BUG_ON(lpar_rc != H_Success); } /* diff -Nru a/arch/ppc64/kernel/process.c b/arch/ppc64/kernel/process.c --- a/arch/ppc64/kernel/process.c 2004-08-25 22:01:55 -07:00 +++ b/arch/ppc64/kernel/process.c 2004-08-25 22:01:55 -07:00 @@ -458,7 +458,7 @@ } } - return do_fork(clone_flags & ~CLONE_IDLETASK, p2, regs, 0, + return do_fork(clone_flags, p2, regs, 0, (int __user *)parent_tidptr, (int __user *)child_tidptr); } diff -Nru a/arch/ppc64/kernel/signal.c b/arch/ppc64/kernel/signal.c --- a/arch/ppc64/kernel/signal.c 2004-08-25 22:01:54 -07:00 +++ b/arch/ppc64/kernel/signal.c 2004-08-25 22:01:54 -07:00 @@ -459,17 +459,13 @@ /* Set up Signal Frame */ setup_rt_frame(sig, ka, info, oldset, regs); - if (ka->sa.sa_flags & SA_ONESHOT) - ka->sa.sa_handler = SIG_DFL; - if (!(ka->sa.sa_flags & SA_NODEFER)) { spin_lock_irq(¤t->sighand->siglock); - sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); + sigorsets(¤t->blocked, ¤t->blocked, &ka->sa.sa_mask); sigaddset(¤t->blocked,sig); recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); } - return; } static inline void syscall_restart(struct pt_regs *regs, struct k_sigaction *ka) @@ -512,6 +508,7 @@ { siginfo_t info; int signr; + struct k_sigaction ka; /* * If the current thread is 32 bit - invoke the @@ -523,14 +520,12 @@ if (!oldset) oldset = ¤t->blocked; - signr = get_signal_to_deliver(&info, regs, NULL); + signr = get_signal_to_deliver(&info, &ka, regs, NULL); if (signr > 0) { - struct k_sigaction *ka = ¤t->sighand->action[signr-1]; - /* Whee! Actually deliver the signal. */ if (TRAP(regs) == 0x0C00) - syscall_restart(regs, ka); - handle_signal(signr, ka, &info, oldset, regs); + syscall_restart(regs, &ka); + handle_signal(signr, &ka, &info, oldset, regs); return 1; } diff -Nru a/arch/ppc64/kernel/signal32.c b/arch/ppc64/kernel/signal32.c --- a/arch/ppc64/kernel/signal32.c 2004-08-25 22:01:56 -07:00 +++ b/arch/ppc64/kernel/signal32.c 2004-08-25 22:01:56 -07:00 @@ -699,9 +699,7 @@ printk("badframe in handle_rt_signal, regs=%p frame=%p newsp=%lx\n", regs, frame, newsp); #endif - if (sig == SIGSEGV) - ka->sa.sa_handler = SIG_DFL; - force_sig(SIGSEGV, current); + force_sigsegv(sig, current); } static long do_setcontext32(struct ucontext32 __user *ucp, struct pt_regs *regs, int sig) @@ -864,9 +862,7 @@ printk("badframe in handle_signal, regs=%p frame=%x newsp=%x\n", regs, frame, *newspp); #endif - if (sig == SIGSEGV) - ka->sa.sa_handler = SIG_DFL; - force_sig(SIGSEGV, current); + force_sigsegv(sig, current); } /* @@ -928,18 +924,16 @@ int do_signal32(sigset_t *oldset, struct pt_regs *regs) { siginfo_t info; - struct k_sigaction *ka; unsigned int frame, newsp; int signr, ret; + struct k_sigaction ka; if (!oldset) oldset = ¤t->blocked; newsp = frame = 0; - signr = get_signal_to_deliver(&info, regs, NULL); - - ka = (signr == 0)? NULL: ¤t->sighand->action[signr-1]; + signr = get_signal_to_deliver(&info, &ka, regs, NULL); if (TRAP(regs) == 0x0C00 /* System Call! */ && regs->ccr & 0x10000000 /* error signalled */ @@ -950,7 +944,7 @@ if (signr > 0 && (ret == ERESTARTNOHAND || ret == ERESTART_RESTARTBLOCK || (ret == ERESTARTSYS - && !(ka->sa.sa_flags & SA_RESTART)))) { + && !(ka.sa.sa_flags & SA_RESTART)))) { /* make the system call return an EINTR error */ regs->result = -EINTR; regs->gpr[3] = EINTR; @@ -969,7 +963,7 @@ if (signr == 0) return 0; /* no signals delivered */ - if ((ka->sa.sa_flags & SA_ONSTACK) && current->sas_ss_size + if ((ka.sa.sa_flags & SA_ONSTACK) && current->sas_ss_size && (!on_sig_stack(regs->gpr[1]))) newsp = (current->sas_ss_sp + current->sas_ss_size); else @@ -977,17 +971,15 @@ newsp &= ~0xfUL; /* Whee! Actually deliver the signal. */ - if (ka->sa.sa_flags & SA_SIGINFO) - handle_rt_signal32(signr, ka, &info, oldset, regs, newsp); + if (ka.sa.sa_flags & SA_SIGINFO) + handle_rt_signal32(signr, &ka, &info, oldset, regs, newsp); else - handle_signal32(signr, ka, &info, oldset, regs, newsp); - - if (ka->sa.sa_flags & SA_ONESHOT) - ka->sa.sa_handler = SIG_DFL; + handle_signal32(signr, &ka, &info, oldset, regs, newsp); - if (!(ka->sa.sa_flags & SA_NODEFER)) { + if (!(ka.sa.sa_flags & SA_NODEFER)) { spin_lock_irq(¤t->sighand->siglock); - sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); + sigorsets(¤t->blocked, ¤t->blocked, + &ka.sa.sa_mask); sigaddset(¤t->blocked, signr); recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); diff -Nru a/arch/ppc64/kernel/smp.c b/arch/ppc64/kernel/smp.c --- a/arch/ppc64/kernel/smp.c 2004-08-25 22:01:56 -07:00 +++ b/arch/ppc64/kernel/smp.c 2004-08-25 22:01:56 -07:00 @@ -59,6 +59,7 @@ cpumask_t cpu_possible_map = CPU_MASK_NONE; cpumask_t cpu_online_map = CPU_MASK_NONE; +cpumask_t cpu_sibling_map[NR_CPUS] = { [0 ... NR_CPUS-1] = CPU_MASK_NONE }; EXPORT_SYMBOL(cpu_online_map); EXPORT_SYMBOL(cpu_possible_map); @@ -800,21 +801,12 @@ static void __init smp_create_idle(unsigned int cpu) { - struct pt_regs regs; struct task_struct *p; /* create a process for the processor */ - /* only regs.msr is actually used, and 0 is OK for it */ - memset(®s, 0, sizeof(struct pt_regs)); - p = copy_process(CLONE_VM | CLONE_IDLETASK, - 0, ®s, 0, NULL, NULL); + p = fork_idle(cpu); if (IS_ERR(p)) panic("failed fork for CPU %u: %li", cpu, PTR_ERR(p)); - - wake_up_forked_process(p); - init_idle(p, cpu); - unhash_process(p); - paca[cpu].__current = p; current_set[cpu] = p->thread_info; } @@ -859,6 +851,12 @@ for_each_cpu(cpu) if (cpu != boot_cpuid) smp_create_idle(cpu); + + for_each_cpu(cpu) { + cpu_set(cpu, cpu_sibling_map[cpu]); + if (cur_cpu_spec->cpu_features & CPU_FTR_SMT) + cpu_set(cpu ^ 0x1, cpu_sibling_map[cpu]); + } } void __devinit smp_prepare_boot_cpu(void) @@ -1007,218 +1005,3 @@ set_cpus_allowed(current, old_mask); } - -#ifdef CONFIG_SCHED_SMT -#ifdef CONFIG_NUMA -static struct sched_group sched_group_cpus[NR_CPUS]; -static struct sched_group sched_group_phys[NR_CPUS]; -static struct sched_group sched_group_nodes[MAX_NUMNODES]; -static DEFINE_PER_CPU(struct sched_domain, cpu_domains); -static DEFINE_PER_CPU(struct sched_domain, phys_domains); -static DEFINE_PER_CPU(struct sched_domain, node_domains); -__init void arch_init_sched_domains(void) -{ - int i; - struct sched_group *first = NULL, *last = NULL; - - /* Set up domains */ - for_each_cpu(i) { - struct sched_domain *cpu_domain = &per_cpu(cpu_domains, i); - struct sched_domain *phys_domain = &per_cpu(phys_domains, i); - struct sched_domain *node_domain = &per_cpu(node_domains, i); - int node = cpu_to_node(i); - cpumask_t nodemask = node_to_cpumask(node); - cpumask_t my_cpumask = cpumask_of_cpu(i); - cpumask_t sibling_cpumask = cpumask_of_cpu(i ^ 0x1); - - *cpu_domain = SD_SIBLING_INIT; - if (cur_cpu_spec->cpu_features & CPU_FTR_SMT) - cpus_or(cpu_domain->span, my_cpumask, sibling_cpumask); - else - cpu_domain->span = my_cpumask; - cpu_domain->parent = phys_domain; - cpu_domain->groups = &sched_group_cpus[i]; - - *phys_domain = SD_CPU_INIT; - phys_domain->span = nodemask; - phys_domain->parent = node_domain; - phys_domain->groups = &sched_group_phys[first_cpu(cpu_domain->span)]; - - *node_domain = SD_NODE_INIT; - node_domain->span = cpu_possible_map; - node_domain->groups = &sched_group_nodes[node]; - } - - /* Set up CPU (sibling) groups */ - for_each_cpu(i) { - struct sched_domain *cpu_domain = &per_cpu(cpu_domains, i); - int j; - first = last = NULL; - - if (i != first_cpu(cpu_domain->span)) - continue; - - for_each_cpu_mask(j, cpu_domain->span) { - struct sched_group *cpu = &sched_group_cpus[j]; - - cpus_clear(cpu->cpumask); - cpu_set(j, cpu->cpumask); - cpu->cpu_power = SCHED_LOAD_SCALE; - - if (!first) - first = cpu; - if (last) - last->next = cpu; - last = cpu; - } - last->next = first; - } - - for (i = 0; i < MAX_NUMNODES; i++) { - int j; - cpumask_t nodemask; - struct sched_group *node = &sched_group_nodes[i]; - cpumask_t node_cpumask = node_to_cpumask(i); - cpus_and(nodemask, node_cpumask, cpu_possible_map); - - if (cpus_empty(nodemask)) - continue; - - first = last = NULL; - /* Set up physical groups */ - for_each_cpu_mask(j, nodemask) { - struct sched_domain *cpu_domain = &per_cpu(cpu_domains, j); - struct sched_group *cpu = &sched_group_phys[j]; - - if (j != first_cpu(cpu_domain->span)) - continue; - - cpu->cpumask = cpu_domain->span; - /* - * Make each extra sibling increase power by 10% of - * the basic CPU. This is very arbitrary. - */ - cpu->cpu_power = SCHED_LOAD_SCALE + SCHED_LOAD_SCALE*(cpus_weight(cpu->cpumask)-1) / 10; - node->cpu_power += cpu->cpu_power; - - if (!first) - first = cpu; - if (last) - last->next = cpu; - last = cpu; - } - last->next = first; - } - - /* Set up nodes */ - first = last = NULL; - for (i = 0; i < MAX_NUMNODES; i++) { - struct sched_group *cpu = &sched_group_nodes[i]; - cpumask_t nodemask; - cpumask_t node_cpumask = node_to_cpumask(i); - cpus_and(nodemask, node_cpumask, cpu_possible_map); - - if (cpus_empty(nodemask)) - continue; - - cpu->cpumask = nodemask; - /* ->cpu_power already setup */ - - if (!first) - first = cpu; - if (last) - last->next = cpu; - last = cpu; - } - last->next = first; - - mb(); - for_each_cpu(i) { - struct sched_domain *cpu_domain = &per_cpu(cpu_domains, i); - cpu_attach_domain(cpu_domain, i); - } -} -#else /* !CONFIG_NUMA */ -static struct sched_group sched_group_cpus[NR_CPUS]; -static struct sched_group sched_group_phys[NR_CPUS]; -static DEFINE_PER_CPU(struct sched_domain, cpu_domains); -static DEFINE_PER_CPU(struct sched_domain, phys_domains); -__init void arch_init_sched_domains(void) -{ - int i; - struct sched_group *first = NULL, *last = NULL; - - /* Set up domains */ - for_each_cpu(i) { - struct sched_domain *cpu_domain = &per_cpu(cpu_domains, i); - struct sched_domain *phys_domain = &per_cpu(phys_domains, i); - cpumask_t my_cpumask = cpumask_of_cpu(i); - cpumask_t sibling_cpumask = cpumask_of_cpu(i ^ 0x1); - - *cpu_domain = SD_SIBLING_INIT; - if (cur_cpu_spec->cpu_features & CPU_FTR_SMT) - cpus_or(cpu_domain->span, my_cpumask, sibling_cpumask); - else - cpu_domain->span = my_cpumask; - cpu_domain->parent = phys_domain; - cpu_domain->groups = &sched_group_cpus[i]; - - *phys_domain = SD_CPU_INIT; - phys_domain->span = cpu_possible_map; - phys_domain->groups = &sched_group_phys[first_cpu(cpu_domain->span)]; - } - - /* Set up CPU (sibling) groups */ - for_each_cpu(i) { - struct sched_domain *cpu_domain = &per_cpu(cpu_domains, i); - int j; - first = last = NULL; - - if (i != first_cpu(cpu_domain->span)) - continue; - - for_each_cpu_mask(j, cpu_domain->span) { - struct sched_group *cpu = &sched_group_cpus[j]; - - cpus_clear(cpu->cpumask); - cpu_set(j, cpu->cpumask); - cpu->cpu_power = SCHED_LOAD_SCALE; - - if (!first) - first = cpu; - if (last) - last->next = cpu; - last = cpu; - } - last->next = first; - } - - first = last = NULL; - /* Set up physical groups */ - for_each_cpu(i) { - struct sched_domain *cpu_domain = &per_cpu(cpu_domains, i); - struct sched_group *cpu = &sched_group_phys[i]; - - if (i != first_cpu(cpu_domain->span)) - continue; - - cpu->cpumask = cpu_domain->span; - /* See SMT+NUMA setup for comment */ - cpu->cpu_power = SCHED_LOAD_SCALE + SCHED_LOAD_SCALE*(cpus_weight(cpu->cpumask)-1) / 10; - - if (!first) - first = cpu; - if (last) - last->next = cpu; - last = cpu; - } - last->next = first; - - mb(); - for_each_cpu(i) { - struct sched_domain *cpu_domain = &per_cpu(cpu_domains, i); - cpu_attach_domain(cpu_domain, i); - } -} -#endif /* CONFIG_NUMA */ -#endif /* CONFIG_SCHED_SMT */ diff -Nru a/arch/ppc64/kernel/vmlinux.lds.S b/arch/ppc64/kernel/vmlinux.lds.S --- a/arch/ppc64/kernel/vmlinux.lds.S 2004-08-25 22:01:56 -07:00 +++ b/arch/ppc64/kernel/vmlinux.lds.S 2004-08-25 22:01:56 -07:00 @@ -61,12 +61,6 @@ __setup_end = .; } - __param : { - __start___param = .; - *(__param) - __stop___param = .; - } - .initcall.init : { __initcall_start = .; *(.initcall1.init) diff -Nru a/arch/ppc64/mm/Makefile b/arch/ppc64/mm/Makefile --- a/arch/ppc64/mm/Makefile 2004-08-25 22:01:54 -07:00 +++ b/arch/ppc64/mm/Makefile 2004-08-25 22:01:54 -07:00 @@ -5,6 +5,6 @@ EXTRA_CFLAGS += -mno-minimal-toc obj-y := fault.o init.o imalloc.o hash_utils.o hash_low.o tlb.o \ - slb_low.o slb.o stab.o + slb_low.o slb.o stab.o mmap.o obj-$(CONFIG_DISCONTIGMEM) += numa.o obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o diff -Nru a/arch/ppc64/mm/hash_low.S b/arch/ppc64/mm/hash_low.S --- a/arch/ppc64/mm/hash_low.S 2004-08-25 22:01:56 -07:00 +++ b/arch/ppc64/mm/hash_low.S 2004-08-25 22:01:56 -07:00 @@ -278,6 +278,10 @@ b bail htab_pte_insert_failure: - b .htab_insert_failure + /* Bail out restoring old PTE */ + ld r6,STK_PARM(r6)(r1) + std r31,0(r6) + li r3,-1 + b bail diff -Nru a/arch/ppc64/mm/hash_utils.c b/arch/ppc64/mm/hash_utils.c --- a/arch/ppc64/mm/hash_utils.c 2004-08-25 22:01:55 -07:00 +++ b/arch/ppc64/mm/hash_utils.c 2004-08-25 22:01:55 -07:00 @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -236,14 +237,11 @@ return pp; } -/* - * Called by asm hashtable.S in case of critical insert failure +/* Result code is: + * 0 - handled + * 1 - normal page fault + * -1 - critical hash insertion error */ -void htab_insert_failure(void) -{ - panic("hash_page: pte_insert failed\n"); -} - int hash_page(unsigned long ea, unsigned long access, unsigned long trap) { void *pgdir; @@ -369,6 +367,25 @@ *insn_addr = (unsigned int)(0x48000001 | (offset & 0x03fffffc)); flush_icache_range((unsigned long)insn_addr, 4+ (unsigned long)insn_addr); +} + +/* + * low_hash_fault is called when we the low level hash code failed + * to instert a PTE due to an hypervisor error + */ +void low_hash_fault(struct pt_regs *regs, unsigned long address) +{ + if (user_mode(regs)) { + siginfo_t info; + + info.si_signo = SIGBUS; + info.si_errno = 0; + info.si_code = BUS_ADRERR; + info.si_addr = (void *)address; + force_sig_info(SIGBUS, &info, current); + return; + } + bad_page_fault(regs, address, SIGBUS); } void __init htab_finish_init(void) diff -Nru a/arch/ppc64/mm/init.c b/arch/ppc64/mm/init.c --- a/arch/ppc64/mm/init.c 2004-08-25 22:01:55 -07:00 +++ b/arch/ppc64/mm/init.c 2004-08-25 22:01:55 -07:00 @@ -613,7 +613,7 @@ zones_size[ZONE_DMA] = top_of_ram >> PAGE_SHIFT; zholes_size[ZONE_DMA] = (top_of_ram - total_ram) >> PAGE_SHIFT; - free_area_init_node(0, &contig_page_data, NULL, zones_size, + free_area_init_node(0, &contig_page_data, zones_size, __pa(PAGE_OFFSET) >> PAGE_SHIFT, zholes_size); mem_map = contig_page_data.node_mem_map; } diff -Nru a/arch/ppc64/mm/mmap.c b/arch/ppc64/mm/mmap.c --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/arch/ppc64/mm/mmap.c 2004-08-25 22:01:56 -07:00 @@ -0,0 +1,86 @@ +/* + * linux/arch/ppc64/mm/mmap.c + * + * flexible mmap layout support + * + * Copyright 2003-2004 Red Hat Inc., Durham, North Carolina. + * All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * + * Started by Ingo Molnar + */ + +#include +#include + +/* + * Top of mmap area (just below the process stack). + * + * Leave an at least ~128 MB hole. + */ +#define MIN_GAP (128*1024*1024) +#define MAX_GAP (TASK_SIZE/6*5) + +static inline unsigned long mmap_base(void) +{ + unsigned long gap = current->rlim[RLIMIT_STACK].rlim_cur; + + if (gap < MIN_GAP) + gap = MIN_GAP; + else if (gap > MAX_GAP) + gap = MAX_GAP; + + return TASK_SIZE - (gap & PAGE_MASK); +} + +static inline int mmap_is_legacy(void) +{ + /* + * Force standard allocation for 64 bit programs. + */ + if (!test_thread_flag(TIF_32BIT)) + return 1; + + if (current->personality & ADDR_COMPAT_LAYOUT) + return 1; + + if (current->rlim[RLIMIT_STACK].rlim_cur == RLIM_INFINITY) + return 1; + + return sysctl_legacy_va_layout; +} + +/* + * This function, called very early during the creation of a new + * process VM image, sets up which VM layout function to use: + */ +void arch_pick_mmap_layout(struct mm_struct *mm) +{ + /* + * Fall back to the standard layout if the personality + * bit is set, or if the expected stack growth is unlimited: + */ + if (mmap_is_legacy()) { + mm->mmap_base = TASK_UNMAPPED_BASE; + mm->get_unmapped_area = arch_get_unmapped_area; + mm->unmap_area = arch_unmap_area; + } else { + mm->mmap_base = mmap_base(); + mm->get_unmapped_area = arch_get_unmapped_area_topdown; + mm->unmap_area = arch_unmap_area_topdown; + } +} diff -Nru a/arch/ppc64/mm/numa.c b/arch/ppc64/mm/numa.c --- a/arch/ppc64/mm/numa.c 2004-08-25 22:01:55 -07:00 +++ b/arch/ppc64/mm/numa.c 2004-08-25 22:01:55 -07:00 @@ -442,7 +442,6 @@ { unsigned long zones_size[MAX_NR_ZONES]; unsigned long zholes_size[MAX_NR_ZONES]; - struct page *node_mem_map; int nid; memset(zones_size, 0, sizeof(zones_size)); @@ -469,11 +468,11 @@ * in free_area_init_node (which will fail). */ if (!node_data[nid].node_spanned_pages) - node_mem_map = alloc_bootmem(sizeof(struct page)); + NODE_DATA(nid)->node_mem_map + = alloc_bootmem(sizeof(struct page)); else - node_mem_map = NULL; - - free_area_init_node(nid, NODE_DATA(nid), node_mem_map, - zones_size, start_pfn, zholes_size); + NODE_DATA(nid)->node_mem_map = NULL; + free_area_init_node(nid, NODE_DATA(nid), zones_size, + start_pfn, zholes_size); } } diff -Nru a/arch/s390/defconfig b/arch/s390/defconfig --- a/arch/s390/defconfig 2004-08-25 22:01:56 -07:00 +++ b/arch/s390/defconfig 2004-08-25 22:01:56 -07:00 @@ -419,7 +419,6 @@ # CONFIG_BEFS_FS is not set # CONFIG_BFS_FS is not set # CONFIG_EFS_FS is not set -# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set # CONFIG_CRAMFS is not set # CONFIG_VXFS_FS is not set # CONFIG_HPFS_FS is not set @@ -511,11 +510,12 @@ # CONFIG_CRYPTO_BLOWFISH is not set # CONFIG_CRYPTO_TWOFISH is not set # CONFIG_CRYPTO_SERPENT is not set -# CONFIG_CRYPTO_AES_GENERIC is not set +# CONFIG_CRYPTO_AES is not set # CONFIG_CRYPTO_CAST5 is not set # CONFIG_CRYPTO_CAST6 is not set # CONFIG_CRYPTO_TEA is not set # CONFIG_CRYPTO_ARC4 is not set +# CONFIG_CRYPTO_KHAZAD is not set # CONFIG_CRYPTO_DEFLATE is not set # CONFIG_CRYPTO_MICHAEL_MIC is not set # CONFIG_CRYPTO_CRC32C is not set diff -Nru a/arch/s390/kernel/compat_linux.c b/arch/s390/kernel/compat_linux.c --- a/arch/s390/kernel/compat_linux.c 2004-08-25 22:01:56 -07:00 +++ b/arch/s390/kernel/compat_linux.c 2004-08-25 22:01:56 -07:00 @@ -725,8 +725,7 @@ int ret; mm_segment_t old_fs = get_fs(); - if (copy_from_user (&info, uinfo, 3*sizeof(int)) || - copy_from_user (info._sifields._pad, uinfo->_sifields._pad, SI_PAD_SIZE)) + if (copy_siginfo_from_user32(&info, uinfo)) return -EFAULT; set_fs (KERNEL_DS); ret = sys_rt_sigqueueinfo(pid, sig, &info); @@ -1219,7 +1218,7 @@ child_tidptr = (int *) (regs.gprs[5] & 0x7fffffffUL); if (!newsp) newsp = regs.gprs[15]; - return do_fork(clone_flags & ~CLONE_IDLETASK, newsp, ®s, 0, + return do_fork(clone_flags, newsp, ®s, 0, parent_tidptr, child_tidptr); } diff -Nru a/arch/s390/kernel/compat_signal.c b/arch/s390/kernel/compat_signal.c --- a/arch/s390/kernel/compat_signal.c 2004-08-25 22:01:56 -07:00 +++ b/arch/s390/kernel/compat_signal.c 2004-08-25 22:01:56 -07:00 @@ -552,9 +552,7 @@ return; give_sigsegv: - if (sig == SIGSEGV) - ka->sa.sa_handler = SIG_DFL; - force_sig(SIGSEGV, current); + force_sigsegv(sig, current); } static void setup_rt_frame32(int sig, struct k_sigaction *ka, siginfo_t *info, @@ -604,9 +602,7 @@ return; give_sigsegv: - if (sig == SIGSEGV) - ka->sa.sa_handler = SIG_DFL; - force_sig(SIGSEGV, current); + force_sigsegv(sig, current); } /* @@ -614,19 +610,14 @@ */ void -handle_signal32(unsigned long sig, siginfo_t *info, sigset_t *oldset, - struct pt_regs * regs) +handle_signal32(unsigned long sig, struct k_sigaction *ka, + siginfo_t *info, sigset_t *oldset, struct pt_regs * regs) { - struct k_sigaction *ka = ¤t->sighand->action[sig-1]; - /* Set up the stack frame */ if (ka->sa.sa_flags & SA_SIGINFO) setup_rt_frame32(sig, ka, info, oldset, regs); else setup_frame32(sig, ka, oldset, regs); - - if (ka->sa.sa_flags & SA_ONESHOT) - ka->sa.sa_handler = SIG_DFL; if (!(ka->sa.sa_flags & SA_NODEFER)) { spin_lock_irq(¤t->sighand->siglock); diff -Nru a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c --- a/arch/s390/kernel/process.c 2004-08-25 22:01:56 -07:00 +++ b/arch/s390/kernel/process.c 2004-08-25 22:01:56 -07:00 @@ -336,7 +336,7 @@ child_tidptr = (int __user *) regs.gprs[5]; if (!newsp) newsp = regs.gprs[15]; - return do_fork(clone_flags & ~CLONE_IDLETASK, newsp, ®s, 0, + return do_fork(clone_flags, newsp, ®s, 0, parent_tidptr, child_tidptr); } diff -Nru a/arch/s390/kernel/signal.c b/arch/s390/kernel/signal.c --- a/arch/s390/kernel/signal.c 2004-08-25 22:01:56 -07:00 +++ b/arch/s390/kernel/signal.c 2004-08-25 22:01:56 -07:00 @@ -358,9 +358,7 @@ return; give_sigsegv: - if (sig == SIGSEGV) - ka->sa.sa_handler = SIG_DFL; - force_sig(SIGSEGV, current); + force_sigsegv(sig, current); } static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, @@ -414,9 +412,7 @@ return; give_sigsegv: - if (sig == SIGSEGV) - ka->sa.sa_handler = SIG_DFL; - force_sig(SIGSEGV, current); + force_sigsegv(sig, current); } /* @@ -424,20 +420,15 @@ */ static void -handle_signal(unsigned long sig, siginfo_t *info, sigset_t *oldset, - struct pt_regs * regs) +handle_signal(unsigned long sig, struct k_sigaction *ka, + siginfo_t *info, sigset_t *oldset, struct pt_regs * regs) { - struct k_sigaction *ka = ¤t->sighand->action[sig-1]; - /* Set up the stack frame */ if (ka->sa.sa_flags & SA_SIGINFO) setup_rt_frame(sig, ka, info, oldset, regs); else setup_frame(sig, ka, oldset, regs); - if (ka->sa.sa_flags & SA_ONESHOT) - ka->sa.sa_handler = SIG_DFL; - if (!(ka->sa.sa_flags & SA_NODEFER)) { spin_lock_irq(¤t->sighand->siglock); sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); @@ -461,6 +452,7 @@ unsigned long retval = 0, continue_addr = 0, restart_addr = 0; siginfo_t info; int signr; + struct k_sigaction ka; /* * We want the common case to go fast, which @@ -494,7 +486,7 @@ /* Get signal to deliver. When running under ptrace, at this point the debugger may change all our registers ... */ - signr = get_signal_to_deliver(&info, regs, NULL); + signr = get_signal_to_deliver(&info, &ka, regs, NULL); /* Depending on the signal settings we may need to revert the decision to restart the system call. */ @@ -513,14 +505,15 @@ #ifdef CONFIG_S390_SUPPORT if (test_thread_flag(TIF_31BIT)) { extern void handle_signal32(unsigned long sig, + struct k_sigaction *ka, siginfo_t *info, sigset_t *oldset, struct pt_regs *regs); - handle_signal32(signr, &info, oldset, regs); + handle_signal32(signr, &ka, &info, oldset, regs); return 1; } #endif - handle_signal(signr, &info, oldset, regs); + handle_signal(signr, &ka, &info, oldset, regs); return 1; } diff -Nru a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c --- a/arch/s390/kernel/smp.c 2004-08-25 22:01:54 -07:00 +++ b/arch/s390/kernel/smp.c 2004-08-25 22:01:54 -07:00 @@ -562,21 +562,15 @@ static void __init smp_create_idle(unsigned int cpu) { - struct pt_regs regs; struct task_struct *p; /* * don't care about the psw and regs settings since we'll never * reschedule the forked task. */ - memset(®s, 0, sizeof(struct pt_regs)); - p = copy_process(CLONE_VM | CLONE_IDLETASK, 0, ®s, 0, NULL, NULL); + p = fork_idle(cpu); if (IS_ERR(p)) panic("failed fork for CPU %u: %li", cpu, PTR_ERR(p)); - - wake_up_forked_process(p); - init_idle(p, cpu); - unhash_process(p); current_set[cpu] = p; } diff -Nru a/arch/s390/kernel/vmlinux.lds.S b/arch/s390/kernel/vmlinux.lds.S --- a/arch/s390/kernel/vmlinux.lds.S 2004-08-25 22:01:55 -07:00 +++ b/arch/s390/kernel/vmlinux.lds.S 2004-08-25 22:01:55 -07:00 @@ -78,9 +78,6 @@ __setup_start = .; .init.setup : { *(.init.setup) } __setup_end = .; - __start___param = .; - __param : { *(__param) } - __stop___param = .; __initcall_start = .; .initcall.init : { *(.initcall1.init) diff -Nru a/arch/s390/kernel/vtime.c b/arch/s390/kernel/vtime.c --- a/arch/s390/kernel/vtime.c 2004-08-25 22:01:56 -07:00 +++ b/arch/s390/kernel/vtime.c 2004-08-25 22:01:56 -07:00 @@ -21,7 +21,7 @@ #include #include -#define VTIMER_MAGIC (0x4b87ad6e + 1) +#define VTIMER_MAGIC (TIMER_MAGIC + 1) static ext_int_info_t ext_int_info_timer; DEFINE_PER_CPU(struct vtimer_queue, virt_cpu_timer); diff -Nru a/arch/s390/mm/Makefile b/arch/s390/mm/Makefile --- a/arch/s390/mm/Makefile 2004-08-25 22:01:56 -07:00 +++ b/arch/s390/mm/Makefile 2004-08-25 22:01:56 -07:00 @@ -2,6 +2,6 @@ # Makefile for the linux s390-specific parts of the memory manager. # -obj-y := init.o fault.o ioremap.o extmem.o +obj-y := init.o fault.o ioremap.o extmem.o mmap.o obj-$(CONFIG_CMM) += cmm.o diff -Nru a/arch/s390/mm/mmap.c b/arch/s390/mm/mmap.c --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/arch/s390/mm/mmap.c 2004-08-25 22:01:56 -07:00 @@ -0,0 +1,83 @@ +/* + * linux/arch/s390/mm/mmap.c + * + * flexible mmap layout support + * + * Copyright 2003-2004 Red Hat Inc., Durham, North Carolina. + * All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * + * Started by Ingo Molnar + */ + +#include +#include + +/* + * Top of mmap area (just below the process stack). + * + * Leave an at least ~128 MB hole. + */ +#define MIN_GAP (128*1024*1024) +#define MAX_GAP (TASK_SIZE/6*5) + +static inline unsigned long mmap_base(void) +{ + unsigned long gap = current->rlim[RLIMIT_STACK].rlim_cur; + + if (gap < MIN_GAP) + gap = MIN_GAP; + else if (gap > MAX_GAP) + gap = MAX_GAP; + + return TASK_SIZE - (gap & PAGE_MASK); +} + +static inline int mmap_is_legacy(void) +{ +#ifdef CONFIG_ARCH_S390X + /* + * Force standard allocation for 64 bit programs. + */ + if (!test_thread_flag(TIF_31BIT)) + return 1; +#endif + return sysctl_legacy_va_layout || + (current->personality & ADDR_COMPAT_LAYOUT) || + current->rlim[RLIMIT_STACK].rlim_cur == RLIM_INFINITY; +} + +/* + * This function, called very early during the creation of a new + * process VM image, sets up which VM layout function to use: + */ +void arch_pick_mmap_layout(struct mm_struct *mm) +{ + /* + * Fall back to the standard layout if the personality + * bit is set, or if the expected stack growth is unlimited: + */ + if (mmap_is_legacy()) { + mm->mmap_base = TASK_UNMAPPED_BASE; + mm->get_unmapped_area = arch_get_unmapped_area; + mm->unmap_area = arch_unmap_area; + } else { + mm->mmap_base = mmap_base(); + mm->get_unmapped_area = arch_get_unmapped_area_topdown; + mm->unmap_area = arch_unmap_area_topdown; + } +} diff -Nru a/arch/sh/kernel/process.c b/arch/sh/kernel/process.c --- a/arch/sh/kernel/process.c 2004-08-25 22:01:56 -07:00 +++ b/arch/sh/kernel/process.c 2004-08-25 22:01:56 -07:00 @@ -440,7 +440,7 @@ { if (!newsp) newsp = regs.regs[15]; - return do_fork(clone_flags & ~CLONE_IDLETASK, newsp, ®s, 0, + return do_fork(clone_flags, newsp, ®s, 0, (int __user *)parent_tidptr, (int __user *)child_tidptr); } diff -Nru a/arch/sh/kernel/signal.c b/arch/sh/kernel/signal.c --- a/arch/sh/kernel/signal.c 2004-08-25 22:01:56 -07:00 +++ b/arch/sh/kernel/signal.c 2004-08-25 22:01:56 -07:00 @@ -413,9 +413,7 @@ return; give_sigsegv: - if (sig == SIGSEGV) - ka->sa.sa_handler = SIG_DFL; - force_sig(SIGSEGV, current); + force_sigsegv(sig, current); } static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, @@ -490,9 +488,7 @@ return; give_sigsegv: - if (sig == SIGSEGV) - ka->sa.sa_handler = SIG_DFL; - force_sig(SIGSEGV, current); + force_sigsegv(sig, current); } /* diff -Nru a/arch/sh/kernel/smp.c b/arch/sh/kernel/smp.c --- a/arch/sh/kernel/smp.c 2004-08-25 22:01:55 -07:00 +++ b/arch/sh/kernel/smp.c 2004-08-25 22:01:55 -07:00 @@ -98,18 +98,11 @@ int __cpu_up(unsigned int cpu) { struct task_struct *tsk; - struct pt_regs regs; - memset(®s, 0, sizeof(struct pt_regs)); - tsk = copy_process(CLONE_VM | CLONE_IDLETASK, 0, ®s, 0, 0, 0); + tsk = fork_idle(cpu); if (IS_ERR(tsk)) panic("Failed forking idle task for cpu %d\n", cpu); - - wake_up_forked_process(tsk); - - init_idle(tsk, cpu); - unhash_process(tsk); tsk->thread_info->cpu = cpu; diff -Nru a/arch/sh/kernel/vmlinux.lds.S b/arch/sh/kernel/vmlinux.lds.S --- a/arch/sh/kernel/vmlinux.lds.S 2004-08-25 22:01:55 -07:00 +++ b/arch/sh/kernel/vmlinux.lds.S 2004-08-25 22:01:55 -07:00 @@ -75,9 +75,6 @@ __setup_start = .; .init.setup : { *(.init.setup) } __setup_end = .; - __start___param = .; - __param : { *(__param) } - __stop___param = .; __initcall_start = .; .initcall.init : { *(.initcall1.init) diff -Nru a/arch/sh/mm/init.c b/arch/sh/mm/init.c --- a/arch/sh/mm/init.c 2004-08-25 22:01:56 -07:00 +++ b/arch/sh/mm/init.c 2004-08-25 22:01:56 -07:00 @@ -214,8 +214,8 @@ */ disable_mmu(); #endif - - free_area_init_node(0, NODE_DATA(0), 0, zones_size, __MEMORY_START >> PAGE_SHIFT, 0); + NODE_DATA(0)->node_mem_map = NULL; + free_area_init_node(0, NODE_DATA(0), zones_size, __MEMORY_START >> PAGE_SHIFT, 0); /* XXX: MRB-remove - this doesn't seem sane, should this be done somewhere else ?*/ mem_map = NODE_DATA(0)->node_mem_map; @@ -225,7 +225,7 @@ */ zones_size[ZONE_DMA] = __MEMORY_SIZE_2ND >> PAGE_SHIFT; zones_size[ZONE_NORMAL] = 0; - free_area_init_node(1, NODE_DATA(1), 0, zones_size, __MEMORY_START_2ND >> PAGE_SHIFT, 0); + free_area_init_node(1, NODE_DATA(1), zones_size, __MEMORY_START_2ND >> PAGE_SHIFT, 0); #endif } diff -Nru a/arch/sh64/kernel/process.c b/arch/sh64/kernel/process.c --- a/arch/sh64/kernel/process.c 2004-08-25 22:01:56 -07:00 +++ b/arch/sh64/kernel/process.c 2004-08-25 22:01:56 -07:00 @@ -820,7 +820,7 @@ { if (!newsp) newsp = pregs->regs[15]; - return do_fork(clone_flags & ~CLONE_IDLETASK, newsp, pregs, 0, 0, 0); + return do_fork(clone_flags, newsp, pregs, 0, 0, 0); } /* diff -Nru a/arch/sh64/kernel/signal.c b/arch/sh64/kernel/signal.c --- a/arch/sh64/kernel/signal.c 2004-08-25 22:01:55 -07:00 +++ b/arch/sh64/kernel/signal.c 2004-08-25 22:01:55 -07:00 @@ -520,9 +520,7 @@ return; give_sigsegv: - if (sig == SIGSEGV) - ka->sa.sa_handler = SIG_DFL; - force_sig(SIGSEGV, current); + force_sigsegv(sig, current); } static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, @@ -628,9 +626,7 @@ return; give_sigsegv: - if (sig == SIGSEGV) - ka->sa.sa_handler = SIG_DFL; - force_sig(SIGSEGV, current); + force_sigsegv(sig, current); } /* diff -Nru a/arch/sh64/kernel/vmlinux.lds.S b/arch/sh64/kernel/vmlinux.lds.S --- a/arch/sh64/kernel/vmlinux.lds.S 2004-08-25 22:01:54 -07:00 +++ b/arch/sh64/kernel/vmlinux.lds.S 2004-08-25 22:01:54 -07:00 @@ -106,9 +106,6 @@ __setup_start = .; .init.setup : C_PHYS(.init.setup) { *(.init.setup) } __setup_end = .; - __start___param = .; - __param : C_PHYS(__param) { *(__param) } - __stop___param = .; __initcall_start = .; .initcall.init : C_PHYS(.initcall.init) { *(.initcall1.init) diff -Nru a/arch/sh64/mm/init.c b/arch/sh64/mm/init.c --- a/arch/sh64/mm/init.c 2004-08-25 22:01:56 -07:00 +++ b/arch/sh64/mm/init.c 2004-08-25 22:01:56 -07:00 @@ -122,8 +122,8 @@ * All memory is good as ZONE_NORMAL (fall-through) and ZONE_DMA. */ zones_size[ZONE_DMA] = MAX_LOW_PFN - START_PFN; - - free_area_init_node(0, NODE_DATA(0), 0, zones_size, __MEMORY_START >> PAGE_SHIFT, 0); + NODE_DATA(0)->node_mem_map = NULL; + free_area_init_node(0, NODE_DATA(0), zones_size, __MEMORY_START >> PAGE_SHIFT, 0); /* XXX: MRB-remove - this doesn't seem sane, should this be done somewhere else ?*/ mem_map = NODE_DATA(0)->node_mem_map; diff -Nru a/arch/sparc/kernel/process.c b/arch/sparc/kernel/process.c --- a/arch/sparc/kernel/process.c 2004-08-25 22:01:54 -07:00 +++ b/arch/sparc/kernel/process.c 2004-08-25 22:01:54 -07:00 @@ -435,8 +435,6 @@ { unsigned long parent_tid_ptr, child_tid_ptr; - clone_flags &= ~CLONE_IDLETASK; - parent_tid_ptr = regs->u_regs[UREG_I2]; child_tid_ptr = regs->u_regs[UREG_I4]; diff -Nru a/arch/sparc/kernel/signal.c b/arch/sparc/kernel/signal.c --- a/arch/sparc/kernel/signal.c 2004-08-25 22:01:55 -07:00 +++ b/arch/sparc/kernel/signal.c 2004-08-25 22:01:55 -07:00 @@ -1036,8 +1036,6 @@ else setup_frame(&ka->sa, regs, signr, oldset, info); } - if (ka->sa.sa_flags & SA_ONESHOT) - ka->sa.sa_handler = SIG_DFL; if (!(ka->sa.sa_flags & SA_NOMASK)) { spin_lock_irq(¤t->sighand->siglock); sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); @@ -1077,6 +1075,7 @@ { siginfo_t info; struct sparc_deliver_cookie cookie; + struct k_sigaction ka; int signr; /* @@ -1096,15 +1095,12 @@ if (!oldset) oldset = ¤t->blocked; - signr = get_signal_to_deliver(&info, regs, &cookie); + signr = get_signal_to_deliver(&info, &ka, regs, &cookie); if (signr > 0) { - struct k_sigaction *ka; - - ka = ¤t->sighand->action[signr-1]; - if (cookie.restart_syscall) - syscall_restart(cookie.orig_i0, regs, &ka->sa); - handle_signal(signr, ka, &info, oldset, regs, svr4_signal); + syscall_restart(cookie.orig_i0, regs, &ka.sa); + handle_signal(signr, &ka, &info, oldset, + regs, svr4_signal); return 1; } if (cookie.restart_syscall && diff -Nru a/arch/sparc/kernel/sun4d_smp.c b/arch/sparc/kernel/sun4d_smp.c --- a/arch/sparc/kernel/sun4d_smp.c 2004-08-25 22:01:54 -07:00 +++ b/arch/sparc/kernel/sun4d_smp.c 2004-08-25 22:01:54 -07:00 @@ -201,18 +201,9 @@ int no; /* Cook up an idler for this guy. */ - kernel_thread(start_secondary, NULL, CLONE_IDLETASK); - + p = fork_idle(i); cpucount++; - - p = prev_task(&init_task); - - init_idle(p, i); - current_set[i] = p->thread_info; - - unhash_process(p); - for (no = 0; !cpu_find_by_instance(no, NULL, &mid) && mid != i; no++) ; diff -Nru a/arch/sparc/kernel/sun4m_smp.c b/arch/sparc/kernel/sun4m_smp.c --- a/arch/sparc/kernel/sun4m_smp.c 2004-08-25 22:01:56 -07:00 +++ b/arch/sparc/kernel/sun4m_smp.c 2004-08-25 22:01:56 -07:00 @@ -173,18 +173,9 @@ int timeout; /* Cook up an idler for this guy. */ - kernel_thread(start_secondary, NULL, CLONE_IDLETASK); - + p = fork_idle(i); cpucount++; - - p = prev_task(&init_task); - - init_idle(p, i); - current_set[i] = p->thread_info; - - unhash_process(p); - /* See trampoline.S for details... */ entry += ((i-1) * 3); diff -Nru a/arch/sparc/kernel/vmlinux.lds.S b/arch/sparc/kernel/vmlinux.lds.S --- a/arch/sparc/kernel/vmlinux.lds.S 2004-08-25 22:01:54 -07:00 +++ b/arch/sparc/kernel/vmlinux.lds.S 2004-08-25 22:01:54 -07:00 @@ -46,9 +46,6 @@ __setup_start = .; .init.setup : { *(.init.setup) } __setup_end = .; - __start___param = .; - __param : { *(__param) } - __stop___param = .; __initcall_start = .; .initcall.init : { *(.initcall1.init) diff -Nru a/arch/sparc/mm/srmmu.c b/arch/sparc/mm/srmmu.c --- a/arch/sparc/mm/srmmu.c 2004-08-25 22:01:55 -07:00 +++ b/arch/sparc/mm/srmmu.c 2004-08-25 22:01:55 -07:00 @@ -1341,7 +1341,7 @@ zones_size[ZONE_HIGHMEM] = npages; zholes_size[ZONE_HIGHMEM] = npages - calc_highpages(); - free_area_init_node(0, &contig_page_data, NULL, zones_size, + free_area_init_node(0, &contig_page_data, zones_size, pfn_base, zholes_size); mem_map = contig_page_data.node_mem_map; } diff -Nru a/arch/sparc/mm/sun4c.c b/arch/sparc/mm/sun4c.c --- a/arch/sparc/mm/sun4c.c 2004-08-25 22:01:56 -07:00 +++ b/arch/sparc/mm/sun4c.c 2004-08-25 22:01:56 -07:00 @@ -2114,7 +2114,7 @@ zones_size[ZONE_HIGHMEM] = npages; zholes_size[ZONE_HIGHMEM] = npages - calc_highpages(); - free_area_init_node(0, &contig_page_data, NULL, zones_size, + free_area_init_node(0, &contig_page_data, zones_size, pfn_base, zholes_size); mem_map = contig_page_data.node_mem_map; } diff -Nru a/arch/sparc64/kernel/process.c b/arch/sparc64/kernel/process.c --- a/arch/sparc64/kernel/process.c 2004-08-25 22:01:55 -07:00 +++ b/arch/sparc64/kernel/process.c 2004-08-25 22:01:55 -07:00 @@ -588,8 +588,6 @@ { int __user *parent_tid_ptr, *child_tid_ptr; - clone_flags &= ~CLONE_IDLETASK; - #ifdef CONFIG_COMPAT if (test_thread_flag(TIF_32BIT)) { parent_tid_ptr = compat_ptr(regs->u_regs[UREG_I2]); diff -Nru a/arch/sparc64/kernel/signal.c b/arch/sparc64/kernel/signal.c --- a/arch/sparc64/kernel/signal.c 2004-08-25 22:01:55 -07:00 +++ b/arch/sparc64/kernel/signal.c 2004-08-25 22:01:55 -07:00 @@ -574,8 +574,6 @@ { setup_rt_frame(ka, regs, signr, oldset, (ka->sa.sa_flags & SA_SIGINFO) ? info : NULL); - if (ka->sa.sa_flags & SA_ONESHOT) - ka->sa.sa_handler = SIG_DFL; if (!(ka->sa.sa_flags & SA_NOMASK)) { spin_lock_irq(¤t->sighand->siglock); sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); @@ -615,6 +613,7 @@ { siginfo_t info; struct signal_deliver_cookie cookie; + struct k_sigaction ka; int signr; cookie.restart_syscall = restart_syscall; @@ -632,15 +631,11 @@ } #endif - signr = get_signal_to_deliver(&info, regs, &cookie); + signr = get_signal_to_deliver(&info, &ka, regs, &cookie); if (signr > 0) { - struct k_sigaction *ka; - - ka = ¤t->sighand->action[signr-1]; - if (cookie.restart_syscall) - syscall_restart(orig_i0, regs, &ka->sa); - handle_signal(signr, ka, &info, oldset, regs); + syscall_restart(orig_i0, regs, &ka.sa); + handle_signal(signr, &ka, &info, oldset, regs); return 1; } if (cookie.restart_syscall && diff -Nru a/arch/sparc64/kernel/signal32.c b/arch/sparc64/kernel/signal32.c --- a/arch/sparc64/kernel/signal32.c 2004-08-25 22:01:54 -07:00 +++ b/arch/sparc64/kernel/signal32.c 2004-08-25 22:01:54 -07:00 @@ -1227,8 +1227,6 @@ else setup_frame32(&ka->sa, regs, signr, oldset, info); } - if (ka->sa.sa_flags & SA_ONESHOT) - ka->sa.sa_handler = SIG_DFL; if (!(ka->sa.sa_flags & SA_NOMASK)) { spin_lock_irq(¤t->sighand->siglock); sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); @@ -1268,21 +1266,19 @@ { siginfo_t info; struct signal_deliver_cookie cookie; + struct k_sigaction ka; int signr; int svr4_signal = current->personality == PER_SVR4; cookie.restart_syscall = restart_syscall; cookie.orig_i0 = orig_i0; - signr = get_signal_to_deliver(&info, regs, &cookie); + signr = get_signal_to_deliver(&info, &ka, regs, &cookie); if (signr > 0) { - struct k_sigaction *ka; - - ka = ¤t->sighand->action[signr-1]; - if (cookie.restart_syscall) - syscall_restart32(orig_i0, regs, &ka->sa); - handle_signal32(signr, ka, &info, oldset, regs, svr4_signal); + syscall_restart32(orig_i0, regs, &ka.sa); + handle_signal32(signr, &ka, &info, oldset, + regs, svr4_signal); return 1; } if (cookie.restart_syscall && diff -Nru a/arch/sparc64/kernel/smp.c b/arch/sparc64/kernel/smp.c --- a/arch/sparc64/kernel/smp.c 2004-08-25 22:01:54 -07:00 +++ b/arch/sparc64/kernel/smp.c 2004-08-25 22:01:54 -07:00 @@ -303,14 +303,7 @@ struct task_struct *p; int timeout, ret, cpu_node; - kernel_thread(NULL, NULL, CLONE_IDLETASK); - - p = prev_task(&init_task); - - init_idle(p, cpu); - - unhash_process(p); - + p = fork_idle(cpu); callin_flag = 0; cpu_new_thread = p->thread_info; cpu_set(cpu, cpu_callout_map); diff -Nru a/arch/sparc64/kernel/vmlinux.lds.S b/arch/sparc64/kernel/vmlinux.lds.S --- a/arch/sparc64/kernel/vmlinux.lds.S 2004-08-25 22:01:56 -07:00 +++ b/arch/sparc64/kernel/vmlinux.lds.S 2004-08-25 22:01:56 -07:00 @@ -52,9 +52,6 @@ __setup_start = .; .init.setup : { *(.init.setup) } __setup_end = .; - __start___param = .; - __param : { *(__param) } - __stop___param = .; __initcall_start = .; .initcall.init : { *(.initcall1.init) diff -Nru a/arch/sparc64/mm/init.c b/arch/sparc64/mm/init.c --- a/arch/sparc64/mm/init.c 2004-08-25 22:01:55 -07:00 +++ b/arch/sparc64/mm/init.c 2004-08-25 22:01:55 -07:00 @@ -1502,7 +1502,7 @@ zones_size[ZONE_DMA] = npages; zholes_size[ZONE_DMA] = npages - pages_avail; - free_area_init_node(0, &contig_page_data, NULL, zones_size, + free_area_init_node(0, &contig_page_data, zones_size, phys_base >> PAGE_SHIFT, zholes_size); mem_map = contig_page_data.node_mem_map; } diff -Nru a/arch/um/Kconfig b/arch/um/Kconfig --- a/arch/um/Kconfig 2004-08-25 22:01:55 -07:00 +++ b/arch/um/Kconfig 2004-08-25 22:01:55 -07:00 @@ -61,6 +61,20 @@ config NET bool "Networking support" + help + Unless you really know what you are doing, you should say Y here. + The reason is that some programs need kernel networking support even + when running on a stand-alone machine that isn't connected to any + other computer. If you are upgrading from an older kernel, you + should consider updating your networking tools too because changes + in the kernel and the tools often go hand in hand. The tools are + contained in the package net-tools, the location and version number + of which are given in Documentation/Changes. + + For a general introduction to Linux networking, it is highly + recommended to read the NET-HOWTO, available from + . + source "fs/Kconfig.binfmt" @@ -85,6 +99,19 @@ If you'd like to be able to work with files stored on the host, say Y or M here; otherwise say N. +config HPPFS + tristate "HoneyPot ProcFS" + help + hppfs (HoneyPot ProcFS) is a filesystem which allows UML /proc + entries to be overridden, removed, or fabricated from the host. + Its purpose is to allow a UML to appear to be a physical machine + by removing or changing anything in /proc which gives away the + identity of a UML. + + See http://user-mode-linux.sf.net/hppfs.html for more information. + + You only need this if you are setting up a UML honeypot. Otherwise, + it is safe to say 'N' here. config MCONSOLE bool "Management console" @@ -163,6 +190,17 @@ This option determines the size of UML kernel stacks. They will be 1 << order pages. The default is OK unless you're running Valgrind on UML, in which case, set this to 3. + +config UML_REAL_TIME_CLOCK + bool "Real-time Clock" + default y + help + This option makes UML time deltas match wall clock deltas. This should + normally be enabled. The exception would be if you are debugging with + UML and spend long times with UML stopped at a breakpoint. In this + case, when UML is restarted, it will call the timer enough times to make + up for the time spent at the breakpoint. This could result in a + noticable lag. If this is a problem, then disable this option. endmenu diff -Nru a/arch/um/Kconfig.debug b/arch/um/Kconfig.debug --- a/arch/um/Kconfig.debug 2004-08-25 22:01:54 -07:00 +++ b/arch/um/Kconfig.debug 2004-08-25 22:01:54 -07:00 @@ -9,6 +9,10 @@ config PT_PROXY bool "Enable ptrace proxy" depends on XTERM_CHAN && DEBUG_INFO + help + This option enables a debugging interface which allows gdb to debug + the kernel without needing to actually attach to kernel threads. + If you want to do kernel debugging, say Y here; otherwise say N. config GPROF bool "Enable gprof support" diff -Nru a/arch/um/Kconfig_block b/arch/um/Kconfig_block --- a/arch/um/Kconfig_block 2004-08-25 22:01:55 -07:00 +++ b/arch/um/Kconfig_block 2004-08-25 22:01:55 -07:00 @@ -29,6 +29,10 @@ wise choice too. In all other cases (for example, if you're just playing around with User-Mode Linux) you can choose N. +config BLK_DEV_COW_COMMON + bool + default BLK_DEV_UBD + config BLK_DEV_LOOP tristate "Loopback device support" diff -Nru a/arch/um/Kconfig_char b/arch/um/Kconfig_char --- a/arch/um/Kconfig_char 2004-08-25 22:01:55 -07:00 +++ b/arch/um/Kconfig_char 2004-08-25 22:01:55 -07:00 @@ -108,11 +108,60 @@ config UNIX98_PTYS bool "Unix98 PTY support" + ---help--- + A pseudo terminal (PTY) is a software device consisting of two + halves: a master and a slave. The slave device behaves identical to + a physical terminal; the master device is used by a process to + read data from and write data to the slave, thereby emulating a + terminal. Typical programs for the master side are telnet servers + and xterms. -config UNIX98_PTY_COUNT - int "Maximum number of Unix98 PTYs in use (0-2048)" - depends on UNIX98_PTYS + Linux has traditionally used the BSD-like names /dev/ptyxx for + masters and /dev/ttyxx for slaves of pseudo terminals. This scheme + has a number of problems. The GNU C library glibc 2.1 and later, + however, supports the Unix98 naming standard: in order to acquire a + pseudo terminal, a process opens /dev/ptmx; the number of the pseudo + terminal is then made available to the process and the pseudo + terminal slave can be accessed as /dev/pts/. What was + traditionally /dev/ttyp2 will then be /dev/pts/2, for example. + + All modern Linux systems use the Unix98 ptys. Say Y unless + you're on an embedded system and want to conserve memory. + +config LEGACY_PTYS + bool "Legacy (BSD) PTY support" + default y + ---help--- + A pseudo terminal (PTY) is a software device consisting of two + halves: a master and a slave. The slave device behaves identical to + a physical terminal; the master device is used by a process to + read data from and write data to the slave, thereby emulating a + terminal. Typical programs for the master side are telnet servers + and xterms. + + Linux has traditionally used the BSD-like names /dev/ptyxx + for masters and /dev/ttyxx for slaves of pseudo + terminals. This scheme has a number of problems, including + security. This option enables these legacy devices; on most + systems, it is safe to say N. + + +config LEGACY_PTY_COUNT + int "Maximum number of legacy PTY in use" + depends on LEGACY_PTYS default "256" + ---help--- + The maximum number of legacy PTYs that can be used at any one time. + The default is 256, and should be more than enough. Embedded + systems may want to reduce this to save memory. + + When not in use, each legacy PTY occupies 12 bytes on 32-bit + architectures and 24 bytes on 64-bit architectures. + +#config UNIX98_PTY_COUNT +# int "Maximum number of Unix98 PTYs in use (0-2048)" +# depends on UNIX98_PTYS +# default "256" config WATCHDOG bool "Watchdog Timer Support" diff -Nru a/arch/um/Kconfig_net b/arch/um/Kconfig_net --- a/arch/um/Kconfig_net 2004-08-25 22:01:55 -07:00 +++ b/arch/um/Kconfig_net 2004-08-25 22:01:55 -07:00 @@ -1,5 +1,5 @@ -menu "Network Devices" +menu "UML Network Devices" depends on NET # UML virtual driver @@ -175,74 +175,6 @@ don't need UML networking, say N. Startup example: "eth0=slirp,FE:FD:01:02:03:04,/usr/local/bin/slirp" - - -# Below are hardware-independent drivers mirrored from -# drivers/net/Config.in. It would be nice if Linux -# had HW independent drivers separated from the other -# but it does not. Until then each non-ISA/PCI arch -# needs to provide it's own menu of network drivers -config DUMMY - tristate "Dummy net driver support" - -config BONDING - tristate "Bonding driver support" - -config EQUALIZER - tristate "EQL (serial line load balancing) support" - -config TUN - tristate "Universal TUN/TAP device driver support" - -config ETHERTAP - tristate "Ethertap network tap (OBSOLETE)" - depends on EXPERIMENTAL && NETLINK - -config PPP - tristate "PPP (point-to-point protocol) support" - -config PPP_MULTILINK - bool "PPP multilink support (EXPERIMENTAL)" - depends on PPP && EXPERIMENTAL - -config PPP_FILTER - bool "PPP filtering" - depends on PPP && FILTER - -config PPP_ASYNC - tristate "PPP support for async serial ports" - depends on PPP - -config PPP_SYNC_TTY - tristate "PPP support for sync tty ports" - depends on PPP - -config PPP_DEFLATE - tristate "PPP Deflate compression" - depends on PPP - -config PPP_BSDCOMP - tristate "PPP BSD-Compress compression" - depends on PPP - -config PPPOE - tristate "PPP over Ethernet (EXPERIMENTAL)" - depends on PPP && EXPERIMENTAL - -config SLIP - tristate "SLIP (serial line) support" - -config SLIP_COMPRESSED - bool "CSLIP compressed headers" - depends on SLIP=y - -config SLIP_SMART - bool "Keepalive and linefill" - depends on SLIP=y - -config SLIP_MODE_SLIP6 - bool "Six bit SLIP encapsulation" - depends on SLIP=y endmenu diff -Nru a/arch/um/Makefile b/arch/um/Makefile --- a/arch/um/Makefile 2004-08-25 22:01:55 -07:00 +++ b/arch/um/Makefile 2004-08-25 22:01:55 -07:00 @@ -22,17 +22,21 @@ $(ARCH_DIR)/sys-$(SUBARCH)/ # Have to precede the include because the included Makefiles reference them. -SYMLINK_HEADERS = include/asm-um/archparam.h include/asm-um/system.h \ - include/asm-um/sigcontext.h include/asm-um/processor.h \ - include/asm-um/ptrace.h include/asm-um/arch-signal.h +SYMLINK_HEADERS = archparam.h system.h sigcontext.h processor.h ptrace.h \ + arch-signal.h module.h +SYMLINK_HEADERS := $(foreach header,$(SYMLINK_HEADERS),include/asm-um/$(header)) ARCH_SYMLINKS = include/asm-um/arch $(ARCH_DIR)/include/sysdep $(ARCH_DIR)/os \ $(SYMLINK_HEADERS) $(ARCH_DIR)/include/uml-config.h GEN_HEADERS += $(ARCH_DIR)/include/task.h $(ARCH_DIR)/include/kern_constants.h -include $(ARCH_DIR)/Makefile-$(SUBARCH) -include $(ARCH_DIR)/Makefile-os-$(OS) +# This target adds dependencies to "prepare". They are defined in the included +# Makefiles (see Makefile-i386). + +.PHONY: sys_prepare +sys_prepare: + @: MAKEFILE-$(CONFIG_MODE_TT) += Makefile-tt MAKEFILE-$(CONFIG_MODE_SKAS) += Makefile-skas @@ -41,6 +45,9 @@ include $(addprefix $(ARCH_DIR)/,$(MAKEFILE-y)) endif +include $(ARCH_DIR)/Makefile-$(SUBARCH) +include $(ARCH_DIR)/Makefile-os-$(OS) + EXTRAVERSION := $(EXTRAVERSION)-1um ARCH_INCLUDE = -I$(ARCH_DIR)/include @@ -52,14 +59,22 @@ CFLAGS += $(CFLAGS-y) -D__arch_um__ -DSUBARCH=\"$(SUBARCH)\" \ -D_LARGEFILE64_SOURCE $(ARCH_INCLUDE) -Derrno=kernel_errno \ - $(MODE_INCLUDE) + -Dsigprocmask=kernel_sigprocmask $(MODE_INCLUDE) + +CFLAGS += $(call check_gcc,-fno-unit-at-a-time,) LINK_WRAPS = -Wl,--wrap,malloc -Wl,--wrap,free -Wl,--wrap,calloc +# These are needed for clean and mrproper, since in that case .config is not +# included; the values here are meaningless + +CONFIG_NEST_LEVEL ?= 0 +CONFIG_KERNEL_HALF_GIGS ?= 0 + SIZE = (($(CONFIG_NEST_LEVEL) + $(CONFIG_KERNEL_HALF_GIGS)) * 0x20000000) ifeq ($(CONFIG_MODE_SKAS), y) -$(SYS_HEADERS) : $(ARCH_DIR)/kernel/skas/include/skas_ptregs.h +$(SYS_HEADERS) : $(TOPDIR)/$(ARCH_DIR)/include/skas_ptregs.h endif include/linux/version.h: arch/$(ARCH)/Makefile @@ -71,8 +86,6 @@ LDFLAGS_vmlinux = -r -vmlinux: $(ARCH_DIR)/main.o - # These aren't in Makefile-tt because they are needed in the !CONFIG_MODE_TT + # CONFIG_MODE_SKAS + CONFIG_STATIC_LINK case. @@ -98,55 +111,58 @@ CONFIG_KERNEL_STACK_ORDER ?= 2 STACK_SIZE := $(shell echo $$[ 4096 * (1 << $(CONFIG_KERNEL_STACK_ORDER)) ] ) -CPPFLAGS_vmlinux.lds = -U$(SUBARCH) \ +CPPFLAGS_vmlinux.lds = $(shell echo -U$(SUBARCH) \ -DSTART=$$(($(TOP_ADDR) - $(SIZE))) -DELF_ARCH=$(ELF_ARCH) \ -DELF_FORMAT=\"$(ELF_FORMAT)\" $(CPP_MODE_TT) \ - -DKERNEL_STACK_SIZE=$(STACK_SIZE) - -CPPFLAGS_$(LD_SCRIPT-y) = $(CPPFLAGS_vmlinux.lds) -P -C -Uum + -DKERNEL_STACK_SIZE=$(STACK_SIZE)) -LD_SCRIPT-y := $(ARCH_DIR)/$(LD_SCRIPT-y) +export CPPFLAGS_$(LD_SCRIPT-y) = $(CPPFLAGS_vmlinux.lds) -P -C -Uum -$(LD_SCRIPT-y) : $(LD_SCRIPT-y:.s=.S) scripts FORCE - $(call if_changed_dep,as_s_S) +LD_SCRIPT-y := $(ARCH_DIR)/kernel/$(LD_SCRIPT-y) linux: vmlinux $(LD_SCRIPT-y) $(CC) -Wl,-T,$(LD_SCRIPT-y) $(LINK-y) $(LINK_WRAPS) \ - -o linux $(ARCH_DIR)/main.o vmlinux -L/usr/lib -lutil + -o linux vmlinux -L/usr/lib -lutil USER_CFLAGS := $(patsubst -I%,,$(CFLAGS)) USER_CFLAGS := $(patsubst -Derrno=kernel_errno,,$(USER_CFLAGS)) +USER_CFLAGS := $(patsubst -Dsigprocmask=kernel_sigprocmask,,$(USER_CFLAGS)) USER_CFLAGS := $(patsubst -D__KERNEL__,,$(USER_CFLAGS)) $(ARCH_INCLUDE) \ $(MODE_INCLUDE) # To get a definition of F_SETSIG USER_CFLAGS += -D_GNU_SOURCE +# From main Makefile, these options are set after including the ARCH makefile. +# So copy them here. + +ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE +USER_CFLAGS += -Os +else +USER_CFLAGS += -O2 +endif + +ifndef CONFIG_FRAME_POINTER +USER_CFLAGS += -fomit-frame-pointer +endif + +ifdef CONFIG_DEBUG_INFO +USER_CFLAGS += -g +endif + CLEAN_FILES += linux x.i gmon.out $(ARCH_DIR)/uml.lds \ - $(ARCH_DIR)/dyn_link.ld.s $(GEN_HEADERS) + $(ARCH_DIR)/dyn_link.ld.s $(ARCH_DIR)/include/uml-config.h \ + $(GEN_HEADERS) -$(ARCH_DIR)/main.o: $(ARCH_DIR)/main.c - $(CC) $(USER_CFLAGS) $(EXTRA_CFLAGS) -c -o $@ $< +MRPROPER_FILES += $(SYMLINK_HEADERS) $(ARCH_SYMLINKS) \ + $(addprefix $(ARCH_DIR)/kernel/,$(KERN_SYMLINKS)) archmrproper: - for d in $(ARCH_SUBDIRS) $(ARCH_DIR)/util; \ - do \ - $(MAKE) -C $$d archmrproper; \ - done - rm -f $(CLEAN_FILES) $(SYMLINK_HEADERS) $(ARCH_SYMLINKS) include/asm \ - $(addprefix $(ARCH_DIR)/kernel/,$(KERN_SYMLINKS)) - -archclean: sysclean - for d in $(ARCH_SUBDIRS) $(ARCH_DIR)/util; \ - do \ - $(MAKE) -C $$d clean; \ - done - find . \( -name '*.bb' -o -name '*.bbg' -o -name '*.da' \ - -o -name '*.gcov' \) -type f -print | xargs rm -f - rm -f linux x.i gmon.out $(ARCH_DIR)/link.ld $(GEN_HEADERS) + @: -archdep: - for d in $(ARCH_SUBDIRS); do $(MAKE) -C $$d fastdep; done +archclean: + @find . \( -name '*.bb' -o -name '*.bbg' -o -name '*.da' \ + -o -name '*.gcov' \) -type f -print | xargs rm -f $(SYMLINK_HEADERS): cd $(TOPDIR)/$(dir $@) ; \ @@ -161,19 +177,32 @@ $(ARCH_DIR)/os: cd $(ARCH_DIR) && ln -sf os-$(OS) os -$(ARCH_DIR)/include/uml-config.h : - sed 's/ CONFIG/ UML_CONFIG/' $(TOPDIR)/include/linux/autoconf.h > $@ +# Generated files +define filechk_umlconfig + sed 's/ CONFIG/ UML_CONFIG/' +endef + +$(ARCH_DIR)/include/uml-config.h : $(TOPDIR)/include/linux/autoconf.h + $(call filechk,umlconfig) + +filechk_gen_header = $< $(ARCH_DIR)/include/task.h : $(ARCH_DIR)/util/mk_task - $< > $@ + $(call filechk,gen_header) $(ARCH_DIR)/include/kern_constants.h : $(ARCH_DIR)/util/mk_constants - $< > $@ + $(call filechk,gen_header) -$(ARCH_DIR)/util/mk_task : $(ARCH_DIR)/kernel/skas/include/skas_ptregs.h \ - $(ARCH_DIR)/util FORCE ; +$(ARCH_DIR)/util/mk_task $(ARCH_DIR)/util/mk_constants : $(ARCH_DIR)/util \ + sys_prepare FORCE ; $(ARCH_DIR)/util: FORCE - @$(call descend,$@,) + $(Q)$(MAKE) $(build)=$@ export SUBARCH USER_CFLAGS OS + +all: linux + +define archhelp + echo '* linux - Binary kernel image (./linux)' +endef diff -Nru a/arch/um/Makefile-i386 b/arch/um/Makefile-i386 --- a/arch/um/Makefile-i386 2004-08-25 22:01:56 -07:00 +++ b/arch/um/Makefile-i386 2004-08-25 22:01:56 -07:00 @@ -16,22 +16,27 @@ SYS_HEADERS = $(SYS_DIR)/sc.h $(SYS_DIR)/thread.h +sys_prepare: $(SYS_DIR)/sc.h + prepare: $(SYS_HEADERS) +filechk_$(SYS_DIR)/sc.h := $(SYS_UTIL_DIR)/mk_sc + $(SYS_DIR)/sc.h: $(SYS_UTIL_DIR)/mk_sc - $< > $@ + $(call filechk,$@) + +filechk_$(SYS_DIR)/thread.h := $(SYS_UTIL_DIR)/mk_thread $(SYS_DIR)/thread.h: $(SYS_UTIL_DIR)/mk_thread - $< > $@ + $(call filechk,$@) -$(SYS_UTIL_DIR)/mk_sc: FORCE ; - @$(call descend,$(SYS_UTIL_DIR),$@) +$(SYS_UTIL_DIR)/mk_sc: scripts/basic/fixdep include/config/MARKER FORCE ; + $(Q)$(MAKE) $(build)=$(SYS_UTIL_DIR) $@ -$(SYS_UTIL_DIR)/mk_thread: $(ARCH_SYMLINKS) $(GEN_HEADERS) FORCE ; - @$(call descend,$(SYS_UTIL_DIR),$@) +$(SYS_UTIL_DIR)/mk_thread: $(ARCH_SYMLINKS) $(GEN_HEADERS) sys_prepare FORCE ; + $(Q)$(MAKE) $(build)=$(SYS_UTIL_DIR) $@ $(SYS_UTIL_DIR): include/asm FORCE - @$(call descend,$@,) + $(Q)$(MAKE) $(build)=$(SYS_UTIL_DIR) -sysclean : - rm -f $(SYS_HEADERS) +CLEAN_FILES += $(SYS_HEADERS) diff -Nru a/arch/um/Makefile-skas b/arch/um/Makefile-skas --- a/arch/um/Makefile-skas 2004-08-25 22:01:55 -07:00 +++ b/arch/um/Makefile-skas 2004-08-25 22:01:55 -07:00 @@ -14,7 +14,7 @@ LINK_SKAS = -Wl,-rpath,/lib LD_SCRIPT_SKAS = dyn.lds -GEN_HEADERS += $(ARCH_DIR)/kernel/skas/include/skas_ptregs.h +GEN_HEADERS += $(TOPDIR)/$(ARCH_DIR)/include/skas_ptregs.h -$(ARCH_DIR)/kernel/skas/include/skas_ptregs.h : - $(MAKE) -C $(ARCH_DIR)/kernel/skas include/skas_ptregs.h +$(TOPDIR)/$(ARCH_DIR)/include/skas_ptregs.h : + $(Q)$(MAKE) $(build)=$(ARCH_DIR)/kernel/skas $@ diff -Nru a/arch/um/config.release b/arch/um/config.release --- a/arch/um/config.release 2004-08-25 22:01:56 -07:00 +++ b/arch/um/config.release 2004-08-25 22:01:56 -07:00 @@ -227,7 +227,6 @@ CONFIG_EXT2_FS=y CONFIG_SYSV_FS=m CONFIG_UDF_FS=m -# CONFIG_UDF_RW is not set CONFIG_UFS_FS=m # CONFIG_UFS_FS_WRITE is not set diff -Nru a/arch/um/defconfig b/arch/um/defconfig --- a/arch/um/defconfig 2004-08-25 22:01:55 -07:00 +++ b/arch/um/defconfig 2004-08-25 22:01:55 -07:00 @@ -1,47 +1,77 @@ # # Automatically generated make config: don't edit +# Linux kernel version: 2.6.8.1-mm3 +# Fri Aug 20 13:03:03 2004 # CONFIG_USERMODE=y CONFIG_MMU=y -CONFIG_SWAP=y CONFIG_UID16=y CONFIG_RWSEM_GENERIC_SPINLOCK=y -CONFIG_CONFIG_LOG_BUF_SHIFT=14 - -# -# Code maturity level options -# -CONFIG_EXPERIMENTAL=y # -# General Setup +# UML-specific options # CONFIG_MODE_TT=y CONFIG_MODE_SKAS=y CONFIG_NET=y -CONFIG_SYSVIPC=y -CONFIG_BSD_PROCESS_ACCT=y -CONFIG_SYSCTL=y -CONFIG_BINFMT_AOUT=y CONFIG_BINFMT_ELF=y CONFIG_BINFMT_MISC=y CONFIG_HOSTFS=y +CONFIG_HPPFS=y CONFIG_MCONSOLE=y -CONFIG_MAGIC_SYSRQ=y # CONFIG_HOST_2G_2G is not set # CONFIG_UML_SMP is not set # CONFIG_SMP is not set CONFIG_NEST_LEVEL=0 CONFIG_KERNEL_HALF_GIGS=1 # CONFIG_HIGHMEM is not set -CONFIG_PROC_MM=y CONFIG_KERNEL_STACK_ORDER=2 +CONFIG_UML_REAL_TIME_CLOCK=y + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_CLEAN_COMPILE=y +CONFIG_BROKEN_ON_SMP=y + +# +# General setup +# +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +# CONFIG_POSIX_MQUEUE is not set +CONFIG_BSD_PROCESS_ACCT=y +# CONFIG_BSD_PROCESS_ACCT_V3 is not set +CONFIG_SYSCTL=y +# CONFIG_AUDIT is not set +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_HOTPLUG is not set +# CONFIG_IKCONFIG is not set +# CONFIG_EMBEDDED is not set +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set +# CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_FUTEX=y +CONFIG_EPOLL=y +# CONFIG_CPUSETS is not set +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set # # Loadable module support # -CONFIG_MODULES=y -# CONFIG_KMOD is not set +# CONFIG_MODULES is not set + +# +# Generic Driver Options +# +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +# CONFIG_DEBUG_DRIVER is not set # # Character Devices @@ -58,7 +88,8 @@ CONFIG_CON_CHAN="xterm" CONFIG_SSL_CHAN="pty" CONFIG_UNIX98_PTYS=y -CONFIG_UNIX98_PTY_COUNT=256 +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 # CONFIG_WATCHDOG is not set CONFIG_UML_SOUND=y CONFIG_SOUND=y @@ -69,6 +100,7 @@ # CONFIG_BLK_DEV_UBD=y # CONFIG_BLK_DEV_UBD_SYNC is not set +CONFIG_BLK_DEV_COW_COMMON=y CONFIG_BLK_DEV_LOOP=y CONFIG_BLK_DEV_NBD=y CONFIG_BLK_DEV_RAM=y @@ -78,7 +110,7 @@ CONFIG_NETDEVICES=y # -# Network Devices +# UML Network Devices # CONFIG_UML_NET=y CONFIG_UML_NET_ETHERTAP=y @@ -88,22 +120,6 @@ CONFIG_UML_NET_MCAST=y # CONFIG_UML_NET_PCAP is not set CONFIG_UML_NET_SLIRP=y -CONFIG_DUMMY=y -# CONFIG_BONDING is not set -# CONFIG_EQUALIZER is not set -CONFIG_TUN=y -# CONFIG_ETHERTAP is not set -CONFIG_PPP=y -# CONFIG_PPP_MULTILINK is not set -# CONFIG_PPP_ASYNC is not set -# CONFIG_PPP_SYNC_TTY is not set -# CONFIG_PPP_DEFLATE is not set -# CONFIG_PPP_BSDCOMP is not set -# CONFIG_PPPOE is not set -CONFIG_SLIP=y -# CONFIG_SLIP_COMPRESSED is not set -# CONFIG_SLIP_SMART is not set -# CONFIG_SLIP_MODE_SLIP6 is not set # # Networking support @@ -115,8 +131,6 @@ CONFIG_PACKET=y CONFIG_PACKET_MMAP=y # CONFIG_NETLINK_DEV is not set -# CONFIG_NETFILTER is not set -# CONFIG_FILTER is not set CONFIG_UNIX=y # CONFIG_NET_KEY is not set CONFIG_INET=y @@ -126,23 +140,24 @@ # CONFIG_NET_IPIP is not set # CONFIG_NET_IPGRE is not set # CONFIG_ARPD is not set -# CONFIG_INET_ECN is not set # CONFIG_SYN_COOKIES is not set # CONFIG_INET_AH is not set # CONFIG_INET_ESP is not set -# CONFIG_XFRM_USER is not set +# CONFIG_INET_IPCOMP is not set # CONFIG_IPV6 is not set +# CONFIG_NETFILTER is not set # # SCTP Configuration (EXPERIMENTAL) # -CONFIG_IPV6_SCTP__=y # CONFIG_IP_SCTP is not set # CONFIG_ATM is not set +# CONFIG_BRIDGE is not set # CONFIG_VLAN_8021Q is not set -# CONFIG_LLC is not set # CONFIG_DECNET is not set -# CONFIG_BRIDGE is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set # CONFIG_X25 is not set # CONFIG_LAPB is not set # CONFIG_NET_DIVERT is not set @@ -154,11 +169,24 @@ # QoS and/or fair queueing # # CONFIG_NET_SCHED is not set +# CONFIG_NET_CLS_ROUTE is not set # # Network testing # # CONFIG_NET_PKTGEN is not set +# CONFIG_KGDBOE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NETPOLL_RX is not set +# CONFIG_NETPOLL_TRAP is not set +# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +CONFIG_DUMMY=y +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +CONFIG_TUN=y # # Ethernet (10 or 100Mbit) @@ -170,83 +198,125 @@ # # -# Wireless LAN (non-hamradio) +# Ethernet (10000 Mbit) # -# CONFIG_NET_RADIO is not set # -# Token Ring devices (depends on LLC=y) +# Token Ring devices # -# CONFIG_SHAPER is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set # # Wan interfaces # # CONFIG_WAN is not set +CONFIG_PPP=y +# CONFIG_PPP_MULTILINK is not set +# CONFIG_PPP_FILTER is not set +# CONFIG_PPP_ASYNC is not set +# CONFIG_PPP_SYNC_TTY is not set +# CONFIG_PPP_DEFLATE is not set +# CONFIG_PPP_BSDCOMP is not set +# CONFIG_PPPOE is not set +CONFIG_SLIP=y +# CONFIG_SLIP_COMPRESSED is not set +# CONFIG_SLIP_SMART is not set +# CONFIG_SLIP_MODE_SLIP6 is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set # # File systems # +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT3_FS is not set +# CONFIG_JBD is not set +CONFIG_REISER4_FS=y +CONFIG_REISER4_LARGE_KEY=y +# CONFIG_REISER4_CHECK is not set +CONFIG_REISERFS_FS=y +# CONFIG_REISERFS_CHECK is not set +# CONFIG_REISERFS_PROC_INFO is not set +# CONFIG_REISERFS_FS_XATTR is not set +# CONFIG_JFS_FS is not set +# CONFIG_XFS_FS is not set +CONFIG_MINIX_FS=y +# CONFIG_ROMFS_FS is not set CONFIG_QUOTA=y # CONFIG_QFMT_V1 is not set # CONFIG_QFMT_V2 is not set CONFIG_QUOTACTL=y -CONFIG_AUTOFS_FS=m -CONFIG_AUTOFS4_FS=m -CONFIG_REISERFS_FS=m -# CONFIG_REISERFS_CHECK is not set -# CONFIG_REISERFS_PROC_INFO is not set +CONFIG_AUTOFS_FS=y +CONFIG_AUTOFS4_FS=y + +# +# CD-ROM/DVD Filesystems +# +CONFIG_ISO9660_FS=y +# CONFIG_JOLIET is not set +# CONFIG_ZISOFS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=y +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=y +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +CONFIG_SYSFS=y +CONFIG_DEVFS_FS=y +CONFIG_DEVFS_MOUNT=y +# CONFIG_DEVFS_DEBUG is not set +# CONFIG_DEVPTS_FS_XATTR is not set +CONFIG_TMPFS=y +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y + +# +# Miscellaneous filesystems +# # CONFIG_ADFS_FS is not set # CONFIG_AFFS_FS is not set # CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set # CONFIG_BEFS_FS is not set # CONFIG_BFS_FS is not set -# CONFIG_EXT3_FS is not set -# CONFIG_JBD is not set -CONFIG_FAT_FS=m -CONFIG_MSDOS_FS=m -CONFIG_VFAT_FS=m # CONFIG_EFS_FS is not set CONFIG_JFFS_FS=y CONFIG_JFFS_FS_VERBOSE=0 -CONFIG_JFFS_PROC_FS=y +# CONFIG_JFFS_PROC_FS is not set # CONFIG_JFFS2_FS is not set # CONFIG_CRAMFS is not set -# CONFIG_TMPFS is not set -CONFIG_RAMFS=y -CONFIG_ISO9660_FS=m -# CONFIG_JOLIET is not set -# CONFIG_ZISOFS is not set -# CONFIG_JFS_FS is not set -CONFIG_MINIX_FS=m # CONFIG_VXFS_FS is not set -# CONFIG_NTFS_FS is not set # CONFIG_HPFS_FS is not set -CONFIG_PROC_FS=y -CONFIG_DEVFS_FS=y -CONFIG_DEVFS_MOUNT=y -# CONFIG_DEVFS_DEBUG is not set -CONFIG_DEVPTS_FS=y # CONFIG_QNX4FS_FS is not set -# CONFIG_ROMFS_FS is not set -CONFIG_EXT2_FS=y -# CONFIG_EXT2_FS_XATTR is not set # CONFIG_SYSV_FS is not set -# CONFIG_UDF_FS is not set # CONFIG_UFS_FS is not set -# CONFIG_XFS_FS is not set # # Network File Systems # -# CONFIG_CODA_FS is not set -# CONFIG_INTERMEZZO_FS is not set # CONFIG_NFS_FS is not set # CONFIG_NFSD is not set # CONFIG_EXPORTFS is not set -# CONFIG_CIFS is not set # CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set # CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set # CONFIG_AFS_FS is not set # @@ -254,11 +324,11 @@ # # CONFIG_PARTITION_ADVANCED is not set CONFIG_MSDOS_PARTITION=y -CONFIG_NLS=y # # Native Language Support # +CONFIG_NLS=y CONFIG_NLS_DEFAULT="iso8859-1" # CONFIG_NLS_CODEPAGE_437 is not set # CONFIG_NLS_CODEPAGE_737 is not set @@ -283,6 +353,7 @@ # CONFIG_NLS_ISO8859_8 is not set # CONFIG_NLS_CODEPAGE_1250 is not set # CONFIG_NLS_CODEPAGE_1251 is not set +# CONFIG_NLS_ASCII is not set # CONFIG_NLS_ISO8859_1 is not set # CONFIG_NLS_ISO8859_2 is not set # CONFIG_NLS_ISO8859_3 is not set @@ -301,6 +372,7 @@ # # Security options # +# CONFIG_KEYS is not set # CONFIG_SECURITY is not set # @@ -311,33 +383,14 @@ # # Library routines # +# CONFIG_CRC_CCITT is not set # CONFIG_CRC32 is not set +# CONFIG_LIBCRC32C is not set # # SCSI support # -CONFIG_SCSI=y -CONFIG_GENERIC_ISA_DMA=y - -# -# SCSI support type (disk, tape, CD-ROM) -# -CONFIG_BLK_DEV_SD=y -CONFIG_SD_EXTRA_DEVS=40 -CONFIG_CHR_DEV_ST=y -CONFIG_BLK_DEV_SR=y -CONFIG_BLK_DEV_SR_VENDOR=y -CONFIG_SR_EXTRA_DEVS=2 -CONFIG_CHR_DEV_SG=y - -# -# Some SCSI devices (e.g. CD jukebox) support multiple LUNs -# -CONFIG_SCSI_DEBUG_QUEUES=y -CONFIG_SCSI_MULTI_LUN=y -CONFIG_SCSI_CONSTANTS=y -CONFIG_SCSI_LOGGING=y -CONFIG_SCSI_DEBUG=y +# CONFIG_SCSI is not set # # Multi-device support (RAID and LVM) @@ -359,34 +412,46 @@ CONFIG_MTD_BLOCK=y # CONFIG_FTL is not set # CONFIG_NFTL is not set +# CONFIG_INFTL is not set # # RAM/ROM/Flash chip drivers # # CONFIG_MTD_CFI is not set # CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set # CONFIG_MTD_RAM is not set # CONFIG_MTD_ROM is not set # CONFIG_MTD_ABSENT is not set -# CONFIG_MTD_OBSOLETE_CHIPS is not set # # Mapping drivers for chip access # +# CONFIG_MTD_COMPLEX_MAPPINGS is not set # # Self-contained MTD device drivers # # CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set # CONFIG_MTD_MTDRAM is not set -CONFIG_MTD_BLKMTD=m +CONFIG_MTD_BLKMTD=y # # Disk-On-Chip Device Drivers # -# CONFIG_MTD_DOC1000 is not set # CONFIG_MTD_DOC2000 is not set # CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set # # NAND Flash Device Drivers @@ -396,6 +461,7 @@ # # Kernel hacking # +CONFIG_DEBUG_KERNEL=y # CONFIG_DEBUG_SLAB is not set # CONFIG_DEBUG_SPINLOCK is not set CONFIG_DEBUG_INFO=y diff -Nru a/arch/um/drivers/Makefile b/arch/um/drivers/Makefile --- a/arch/um/drivers/Makefile 2004-08-25 22:01:55 -07:00 +++ b/arch/um/drivers/Makefile 2004-08-25 22:01:55 -07:00 @@ -1,5 +1,5 @@ # -# Copyright (C) 2000, 2002 Jeff Dike (jdike@karaya.com) +# Copyright (C) 2000, 2002, 2003 Jeff Dike (jdike@karaya.com) # Licensed under the GPL # @@ -15,7 +15,7 @@ #pcap-objs := pcap_kern.o pcap_user.o $(PCAP) net-objs := net_kern.o net_user.o mconsole-objs := mconsole_kern.o mconsole_user.o -hostaudio-objs := hostaudio_kern.o hostaudio_user.o +hostaudio-objs := hostaudio_kern.o ubd-objs := ubd_kern.o ubd_user.o port-objs := port_kern.o port_user.o harddog-objs := harddog_kern.o harddog_user.o @@ -39,6 +39,7 @@ obj-$(CONFIG_TTY_CHAN) += tty.o obj-$(CONFIG_XTERM_CHAN) += xterm.o xterm_kern.o obj-$(CONFIG_UML_WATCHDOG) += harddog.o +obj-$(CONFIG_BLK_DEV_COW_COMMON) += cow_user.o obj-y += stdio_console.o $(CHAN_OBJS) @@ -46,18 +47,7 @@ USER_OBJS := $(filter %_user.o,$(obj-y) $(obj-m) $(USER_SINGLE_OBJS)) fd.o \ null.o pty.o tty.o xterm.o -USER_OBJS := $(foreach file,$(USER_OBJS),arch/um/drivers/$(file)) +USER_OBJS := $(foreach file,$(USER_OBJS),$(obj)/$(file)) $(USER_OBJS) : %.o: %.c $(CC) $(CFLAGS_$(notdir $@)) $(USER_CFLAGS) -c -o $@ $< - -clean: - -modules: - -fastdep: - -dep: - -archmrproper: clean - diff -Nru a/arch/um/drivers/chan_kern.c b/arch/um/drivers/chan_kern.c --- a/arch/um/drivers/chan_kern.c 2004-08-25 22:01:56 -07:00 +++ b/arch/um/drivers/chan_kern.c 2004-08-25 22:01:56 -07:00 @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include "chan_kern.h" @@ -16,6 +17,7 @@ #include "irq_user.h" #include "sigio.h" #include "line.h" +#include "os.h" static void *not_configged_init(char *str, int device, struct chan_opts *opts) { @@ -86,6 +88,52 @@ .winch = 0, }; +void generic_close(int fd, void *unused) +{ + os_close_file(fd); +} + +int generic_read(int fd, char *c_out, void *unused) +{ + int n; + + n = os_read_file(fd, c_out, sizeof(*c_out)); + + if(n == -EAGAIN) + return(0); + else if(n == 0) + return(-EIO); + return(n); +} + +int generic_write(int fd, const char *buf, int n, void *unused) +{ + return(os_write_file(fd, buf, n)); +} + +int generic_window_size(int fd, void *unused, unsigned short *rows_out, + unsigned short *cols_out) +{ + int rows, cols; + int ret; + + ret = os_window_size(fd, &rows, &cols); + if(ret < 0) + return(ret); + + ret = ((*rows_out != rows) || (*cols_out != cols)); + + *rows_out = rows; + *cols_out = cols; + + return(ret); +} + +void generic_free(void *data) +{ + kfree(data); +} + static void tty_receive_char(struct tty_struct *tty, char ch) { if(tty == NULL) return; @@ -265,6 +313,11 @@ { int n = 0; + if(chan == NULL){ + CONFIG_CHUNK(str, size, n, "none", 1); + return(n); + } + CONFIG_CHUNK(str, size, n, chan->ops->type, 0); if(chan->dev == NULL){ @@ -420,7 +473,8 @@ INIT_LIST_HEAD(chans); } - if((out = strchr(str, ',')) != NULL){ + out = strchr(str, ','); + if(out != NULL){ in = str; *out = '\0'; out++; @@ -475,12 +529,15 @@ goto out; } err = chan->ops->read(chan->fd, &c, chan->data); - if(err > 0) tty_receive_char(tty, c); + if(err > 0) + tty_receive_char(tty, c); } while(err > 0); + if(err == 0) reactivate_fd(chan->fd, irq); if(err == -EIO){ if(chan->primary){ - if(tty != NULL) tty_hangup(tty); + if(tty != NULL) + tty_hangup(tty); line_disable(dev, irq); close_chan(chans); free_chan(chans); diff -Nru a/arch/um/drivers/chan_user.c b/arch/um/drivers/chan_user.c --- a/arch/um/drivers/chan_user.c 2004-08-25 22:01:54 -07:00 +++ b/arch/um/drivers/chan_user.c 2004-08-25 22:01:54 -07:00 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com) + * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com) * Licensed under the GPL */ @@ -7,7 +7,6 @@ #include #include #include -#include #include #include #include @@ -22,33 +21,6 @@ #include "choose-mode.h" #include "mode.h" -void generic_close(int fd, void *unused) -{ - close(fd); -} - -int generic_read(int fd, char *c_out, void *unused) -{ - int n; - - n = read(fd, c_out, sizeof(*c_out)); - if(n < 0){ - if(errno == EAGAIN) return(0); - return(-errno); - } - else if(n == 0) return(-EIO); - return(1); -} - -int generic_write(int fd, const char *buf, int n, void *unused) -{ - int count; - - count = write(fd, buf, n); - if(count < 0) return(-errno); - return(count); -} - int generic_console_write(int fd, const char *buf, int n, void *unused) { struct termios save, new; @@ -65,26 +37,6 @@ return(err); } -int generic_window_size(int fd, void *unused, unsigned short *rows_out, - unsigned short *cols_out) -{ - struct winsize size; - int ret = 0; - - if(ioctl(fd, TIOCGWINSZ, &size) == 0){ - ret = ((*rows_out != size.ws_row) || - (*cols_out != size.ws_col)); - *rows_out = size.ws_row; - *cols_out = size.ws_col; - } - return(ret); -} - -void generic_free(void *data) -{ - kfree(data); -} - static void winch_handler(int sig) { } @@ -100,14 +52,16 @@ struct winch_data *data = arg; sigset_t sigs; int pty_fd, pipe_fd; + int count, err; char c = 1; - close(data->close_me); + os_close_file(data->close_me); pty_fd = data->pty_fd; pipe_fd = data->pipe_fd; - if(write(pipe_fd, &c, sizeof(c)) != sizeof(c)) + count = os_write_file(pipe_fd, &c, sizeof(c)); + if(count != sizeof(c)) printk("winch_thread : failed to write synchronization " - "byte, errno = %d\n", errno); + "byte, err = %d\n", -count); signal(SIGWINCH, winch_handler); sigfillset(&sigs); @@ -123,26 +77,24 @@ exit(1); } - if(ioctl(pty_fd, TIOCSCTTY, 0) < 0){ - printk("winch_thread : TIOCSCTTY failed, errno = %d\n", errno); - exit(1); - } - if(tcsetpgrp(pty_fd, os_getpid()) < 0){ - printk("winch_thread : tcsetpgrp failed, errno = %d\n", errno); + err = os_new_tty_pgrp(pty_fd, os_getpid()); + if(err < 0){ + printk("winch_thread : new_tty_pgrp failed, err = %d\n", -err); exit(1); } - if(read(pipe_fd, &c, sizeof(c)) != sizeof(c)) + count = os_read_file(pipe_fd, &c, sizeof(c)); + if(count != sizeof(c)) printk("winch_thread : failed to read synchronization byte, " - "errno = %d\n", errno); + "err = %d\n", -count); while(1){ pause(); - if(write(pipe_fd, &c, sizeof(c)) != sizeof(c)){ - printk("winch_thread : write failed, errno = %d\n", - errno); - } + count = os_write_file(pipe_fd, &c, sizeof(c)); + if(count != sizeof(c)) + printk("winch_thread : write failed, err = %d\n", + -count); } } @@ -154,8 +106,8 @@ char c; err = os_pipe(fds, 1, 1); - if(err){ - printk("winch_tramp : os_pipe failed, errno = %d\n", -err); + if(err < 0){ + printk("winch_tramp : os_pipe failed, err = %d\n", -err); return(err); } @@ -168,12 +120,12 @@ return(pid); } - close(fds[1]); + os_close_file(fds[1]); *fd_out = fds[0]; - n = read(fds[0], &c, sizeof(c)); + n = os_read_file(fds[0], &c, sizeof(c)); if(n != sizeof(c)){ printk("winch_tramp : failed to read synchronization byte\n"); - printk("read returned %d, errno = %d\n", n, errno); + printk("read failed, err = %d\n", -n); printk("fd %d will not support SIGWINCH\n", fd); *fd_out = -1; } @@ -183,20 +135,24 @@ void register_winch(int fd, void *device_data) { int pid, thread, thread_fd; + int count; char c = 1; - if(!isatty(fd)) return; + if(!isatty(fd)) + return; pid = tcgetpgrp(fd); - if(!CHOOSE_MODE(is_tracer_winch(pid, fd, device_data), 0) && - (pid == -1)){ + if(!CHOOSE_MODE_PROC(is_tracer_winch, is_skas_winch, pid, fd, + device_data) && (pid == -1)){ thread = winch_tramp(fd, device_data, &thread_fd); if(fd != -1){ register_winch_irq(thread_fd, fd, thread, device_data); - if(write(thread_fd, &c, sizeof(c)) != sizeof(c)) + count = os_write_file(thread_fd, &c, sizeof(c)); + if(count != sizeof(c)) printk("register_winch : failed to write " - "synchronization byte\n"); + "synchronization byte, err = %d\n", + -count); } } } diff -Nru a/arch/um/drivers/cow.h b/arch/um/drivers/cow.h --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/arch/um/drivers/cow.h 2004-08-25 22:01:56 -07:00 @@ -0,0 +1,41 @@ +#ifndef __COW_H__ +#define __COW_H__ + +#include + +#if __BYTE_ORDER == __BIG_ENDIAN +# define ntohll(x) (x) +# define htonll(x) (x) +#elif __BYTE_ORDER == __LITTLE_ENDIAN +# define ntohll(x) bswap_64(x) +# define htonll(x) bswap_64(x) +#else +#error "__BYTE_ORDER not defined" +#endif + +extern int init_cow_file(int fd, char *cow_file, char *backing_file, + int sectorsize, int alignment, int *bitmap_offset_out, + unsigned long *bitmap_len_out, int *data_offset_out); + +extern int file_reader(__u64 offset, char *buf, int len, void *arg); +extern int read_cow_header(int (*reader)(__u64, char *, int, void *), + void *arg, __u32 *version_out, + char **backing_file_out, time_t *mtime_out, + __u64 *size_out, int *sectorsize_out, + __u32 *align_out, int *bitmap_offset_out); + +extern int write_cow_header(char *cow_file, int fd, char *backing_file, + int sectorsize, int alignment, long long *size); + +extern void cow_sizes(int version, __u64 size, int sectorsize, int align, + int bitmap_offset, unsigned long *bitmap_len_out, + int *data_offset_out); + +#endif + +/* + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff -Nru a/arch/um/drivers/cow_sys.h b/arch/um/drivers/cow_sys.h --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/arch/um/drivers/cow_sys.h 2004-08-25 22:01:56 -07:00 @@ -0,0 +1,48 @@ +#ifndef __COW_SYS_H__ +#define __COW_SYS_H__ + +#include "kern_util.h" +#include "user_util.h" +#include "os.h" +#include "user.h" + +static inline void *cow_malloc(int size) +{ + return(um_kmalloc(size)); +} + +static inline void cow_free(void *ptr) +{ + kfree(ptr); +} + +#define cow_printf printk + +static inline char *cow_strdup(char *str) +{ + return(uml_strdup(str)); +} + +static inline int cow_seek_file(int fd, __u64 offset) +{ + return(os_seek_file(fd, offset)); +} + +static inline int cow_file_size(char *file, __u64 *size_out) +{ + return(os_file_size(file, size_out)); +} + +static inline int cow_write_file(int fd, char *buf, int size) +{ + return(os_write_file(fd, buf, size)); +} + +#endif + +/* + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff -Nru a/arch/um/drivers/cow_user.c b/arch/um/drivers/cow_user.c --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/arch/um/drivers/cow_user.c 2004-08-25 22:01:56 -07:00 @@ -0,0 +1,375 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "os.h" + +#include "cow.h" +#include "cow_sys.h" + +#define PATH_LEN_V1 256 + +struct cow_header_v1 { + int magic; + int version; + char backing_file[PATH_LEN_V1]; + time_t mtime; + __u64 size; + int sectorsize; +}; + +#define PATH_LEN_V2 MAXPATHLEN + +struct cow_header_v2 { + unsigned long magic; + unsigned long version; + char backing_file[PATH_LEN_V2]; + time_t mtime; + __u64 size; + int sectorsize; +}; + +/* Define PATH_LEN_V3 as the usual value of MAXPATHLEN, just hard-code it in + * case other systems have different values for MAXPATHLEN + */ +#define PATH_LEN_V3 4096 + +/* Changes from V2 - + * PATH_LEN_V3 as described above + * Explicitly specify field bit lengths for systems with different + * lengths for the usual C types. Not sure whether char or + * time_t should be changed, this can be changed later without + * breaking compatibility + * Add alignment field so that different alignments can be used for the + * bitmap and data + * Add cow_format field to allow for the possibility of different ways + * of specifying the COW blocks. For now, the only value is 0, + * for the traditional COW bitmap. + * Move the backing_file field to the end of the header. This allows + * for the possibility of expanding it into the padding required + * by the bitmap alignment. + * The bitmap and data portions of the file will be aligned as specified + * by the alignment field. This is to allow COW files to be + * put on devices with restrictions on access alignments, such as + * /dev/raw, with a 512 byte alignment restriction. This also + * allows the data to be more aligned more strictly than on + * sector boundaries. This is needed for ubd-mmap, which needs + * the data to be page aligned. + * Fixed (finally!) the rounding bug + */ + +struct cow_header_v3 { + __u32 magic; + __u32 version; + time_t mtime; + __u64 size; + __u32 sectorsize; + __u32 alignment; + __u32 cow_format; + char backing_file[PATH_LEN_V3]; +}; + +/* COW format definitions - for now, we have only the usual COW bitmap */ +#define COW_BITMAP 0 + +union cow_header { + struct cow_header_v1 v1; + struct cow_header_v2 v2; + struct cow_header_v3 v3; +}; + +#define COW_MAGIC 0x4f4f4f4d /* MOOO */ +#define COW_VERSION 3 + +#define DIV_ROUND(x, len) (((x) + (len) - 1) / (len)) +#define ROUND_UP(x, align) DIV_ROUND(x, align) * (align) + +void cow_sizes(int version, __u64 size, int sectorsize, int align, + int bitmap_offset, unsigned long *bitmap_len_out, + int *data_offset_out) +{ + if(version < 3){ + *bitmap_len_out = (size + sectorsize - 1) / (8 * sectorsize); + + *data_offset_out = bitmap_offset + *bitmap_len_out; + *data_offset_out = (*data_offset_out + sectorsize - 1) / + sectorsize; + *data_offset_out *= sectorsize; + } + else { + *bitmap_len_out = DIV_ROUND(size, sectorsize); + *bitmap_len_out = DIV_ROUND(*bitmap_len_out, 8); + + *data_offset_out = bitmap_offset + *bitmap_len_out; + *data_offset_out = ROUND_UP(*data_offset_out, align); + } +} + +static int absolutize(char *to, int size, char *from) +{ + char save_cwd[256], *slash; + int remaining; + + if(getcwd(save_cwd, sizeof(save_cwd)) == NULL) { + cow_printf("absolutize : unable to get cwd - errno = %d\n", + errno); + return(-1); + } + slash = strrchr(from, '/'); + if(slash != NULL){ + *slash = '\0'; + if(chdir(from)){ + *slash = '/'; + cow_printf("absolutize : Can't cd to '%s' - " + "errno = %d\n", from, errno); + return(-1); + } + *slash = '/'; + if(getcwd(to, size) == NULL){ + cow_printf("absolutize : unable to get cwd of '%s' - " + "errno = %d\n", from, errno); + return(-1); + } + remaining = size - strlen(to); + if(strlen(slash) + 1 > remaining){ + cow_printf("absolutize : unable to fit '%s' into %d " + "chars\n", from, size); + return(-1); + } + strcat(to, slash); + } + else { + if(strlen(save_cwd) + 1 + strlen(from) + 1 > size){ + cow_printf("absolutize : unable to fit '%s' into %d " + "chars\n", from, size); + return(-1); + } + strcpy(to, save_cwd); + strcat(to, "/"); + strcat(to, from); + } + chdir(save_cwd); + return(0); +} + +int write_cow_header(char *cow_file, int fd, char *backing_file, + int sectorsize, int alignment, long long *size) +{ + struct cow_header_v3 *header; + unsigned long modtime; + int err; + + err = cow_seek_file(fd, 0); + if(err < 0){ + cow_printf("write_cow_header - lseek failed, err = %d\n", -err); + goto out; + } + + err = -ENOMEM; + header = cow_malloc(sizeof(*header)); + if(header == NULL){ + cow_printf("Failed to allocate COW V3 header\n"); + goto out; + } + header->magic = htonl(COW_MAGIC); + header->version = htonl(COW_VERSION); + + err = -EINVAL; + if(strlen(backing_file) > sizeof(header->backing_file) - 1){ + cow_printf("Backing file name \"%s\" is too long - names are " + "limited to %d characters\n", backing_file, + sizeof(header->backing_file) - 1); + goto out_free; + } + + if(absolutize(header->backing_file, sizeof(header->backing_file), + backing_file)) + goto out_free; + + err = os_file_modtime(header->backing_file, &modtime); + if(err < 0){ + cow_printf("Backing file '%s' mtime request failed, " + "err = %d\n", header->backing_file, -err); + goto out_free; + } + + err = cow_file_size(header->backing_file, size); + if(err < 0){ + cow_printf("Couldn't get size of backing file '%s', " + "err = %d\n", header->backing_file, -err); + goto out_free; + } + + header->mtime = htonl(modtime); + header->size = htonll(*size); + header->sectorsize = htonl(sectorsize); + header->alignment = htonl(alignment); + header->cow_format = COW_BITMAP; + + err = os_write_file(fd, header, sizeof(*header)); + if(err != sizeof(*header)){ + cow_printf("Write of header to new COW file '%s' failed, " + "err = %d\n", cow_file, -err); + goto out_free; + } + err = 0; + out_free: + cow_free(header); + out: + return(err); +} + +int file_reader(__u64 offset, char *buf, int len, void *arg) +{ + int fd = *((int *) arg); + + return(pread(fd, buf, len, offset)); +} + +/* XXX Need to sanity-check the values read from the header */ + +int read_cow_header(int (*reader)(__u64, char *, int, void *), void *arg, + __u32 *version_out, char **backing_file_out, + time_t *mtime_out, __u64 *size_out, + int *sectorsize_out, __u32 *align_out, + int *bitmap_offset_out) +{ + union cow_header *header; + char *file; + int err, n; + unsigned long version, magic; + + header = cow_malloc(sizeof(*header)); + if(header == NULL){ + cow_printf("read_cow_header - Failed to allocate header\n"); + return(-ENOMEM); + } + err = -EINVAL; + n = (*reader)(0, (char *) header, sizeof(*header), arg); + if(n < offsetof(typeof(header->v1), backing_file)){ + cow_printf("read_cow_header - short header\n"); + goto out; + } + + magic = header->v1.magic; + if(magic == COW_MAGIC) { + version = header->v1.version; + } + else if(magic == ntohl(COW_MAGIC)){ + version = ntohl(header->v1.version); + } + /* No error printed because the non-COW case comes through here */ + else goto out; + + *version_out = version; + + if(version == 1){ + if(n < sizeof(header->v1)){ + cow_printf("read_cow_header - failed to read V1 " + "header\n"); + goto out; + } + *mtime_out = header->v1.mtime; + *size_out = header->v1.size; + *sectorsize_out = header->v1.sectorsize; + *bitmap_offset_out = sizeof(header->v1); + *align_out = *sectorsize_out; + file = header->v1.backing_file; + } + else if(version == 2){ + if(n < sizeof(header->v2)){ + cow_printf("read_cow_header - failed to read V2 " + "header\n"); + goto out; + } + *mtime_out = ntohl(header->v2.mtime); + *size_out = ntohll(header->v2.size); + *sectorsize_out = ntohl(header->v2.sectorsize); + *bitmap_offset_out = sizeof(header->v2); + *align_out = *sectorsize_out; + file = header->v2.backing_file; + } + else if(version == 3){ + if(n < sizeof(header->v3)){ + cow_printf("read_cow_header - failed to read V2 " + "header\n"); + goto out; + } + *mtime_out = ntohl(header->v3.mtime); + *size_out = ntohll(header->v3.size); + *sectorsize_out = ntohl(header->v3.sectorsize); + *align_out = ntohl(header->v3.alignment); + *bitmap_offset_out = ROUND_UP(sizeof(header->v3), *align_out); + file = header->v3.backing_file; + } + else { + cow_printf("read_cow_header - invalid COW version\n"); + goto out; + } + err = -ENOMEM; + *backing_file_out = cow_strdup(file); + if(*backing_file_out == NULL){ + cow_printf("read_cow_header - failed to allocate backing " + "file\n"); + goto out; + } + err = 0; + out: + cow_free(header); + return(err); +} + +int init_cow_file(int fd, char *cow_file, char *backing_file, int sectorsize, + int alignment, int *bitmap_offset_out, + unsigned long *bitmap_len_out, int *data_offset_out) +{ + __u64 size, offset; + char zero = 0; + int err; + + err = write_cow_header(cow_file, fd, backing_file, sectorsize, + alignment, &size); + if(err) + goto out; + + *bitmap_offset_out = ROUND_UP(sizeof(struct cow_header_v3), alignment); + cow_sizes(COW_VERSION, size, sectorsize, alignment, *bitmap_offset_out, + bitmap_len_out, data_offset_out); + + offset = *data_offset_out + size - sizeof(zero); + err = cow_seek_file(fd, offset); + if(err < 0){ + cow_printf("cow bitmap lseek failed : err = %d\n", -err); + goto out; + } + + /* does not really matter how much we write it is just to set EOF + * this also sets the entire COW bitmap + * to zero without having to allocate it + */ + err = cow_write_file(fd, &zero, sizeof(zero)); + if(err != sizeof(zero)){ + cow_printf("Write of bitmap to new COW file '%s' failed, " + "err = %d\n", cow_file, -err); + err = -EINVAL; + goto out; + } + + return(0); + + out: + return(err); +} + +/* + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff -Nru a/arch/um/drivers/daemon_user.c b/arch/um/drivers/daemon_user.c --- a/arch/um/drivers/daemon_user.c 2004-08-25 22:01:55 -07:00 +++ b/arch/um/drivers/daemon_user.c 2004-08-25 22:01:55 -07:00 @@ -53,7 +53,8 @@ struct request_v3 req; int fd, n, err; - if((pri->control = socket(AF_UNIX, SOCK_STREAM, 0)) < 0){ + pri->control = socket(AF_UNIX, SOCK_STREAM, 0); + if(pri->control < 0){ printk("daemon_open : control socket failed, errno = %d\n", errno); return(-errno); @@ -67,7 +68,8 @@ goto out; } - if((fd = socket(AF_UNIX, SOCK_DGRAM, 0)) < 0){ + fd = socket(AF_UNIX, SOCK_DGRAM, 0); + if(fd < 0){ printk("daemon_open : data socket failed, errno = %d\n", errno); err = -errno; @@ -91,18 +93,18 @@ req.version = SWITCH_VERSION; req.type = REQ_NEW_CONTROL; req.sock = *local_addr; - n = write(pri->control, &req, sizeof(req)); + n = os_write_file(pri->control, &req, sizeof(req)); if(n != sizeof(req)){ - printk("daemon_open : control setup request returned %d, " - "errno = %d\n", n, errno); + printk("daemon_open : control setup request failed, err = %d\n", + -n); err = -ENOTCONN; goto out; } - n = read(pri->control, sun, sizeof(*sun)); + n = os_read_file(pri->control, sun, sizeof(*sun)); if(n != sizeof(*sun)){ - printk("daemon_open : read of data socket returned %d, " - "errno = %d\n", n, errno); + printk("daemon_open : read of data socket failed, err = %d\n", + -n); err = -ENOTCONN; goto out_close; } @@ -111,9 +113,9 @@ return(fd); out_close: - close(fd); + os_close_file(fd); out: - close(pri->control); + os_close_file(pri->control); return(err); } @@ -153,8 +155,8 @@ { struct daemon_data *pri = data; - close(pri->fd); - close(pri->control); + os_close_file(pri->fd); + os_close_file(pri->control); if(pri->data_addr != NULL) kfree(pri->data_addr); if(pri->ctl_addr != NULL) kfree(pri->ctl_addr); if(pri->local_addr != NULL) kfree(pri->local_addr); diff -Nru a/arch/um/drivers/fd.c b/arch/um/drivers/fd.c --- a/arch/um/drivers/fd.c 2004-08-25 22:01:56 -07:00 +++ b/arch/um/drivers/fd.c 2004-08-25 22:01:56 -07:00 @@ -35,7 +35,8 @@ printk("fd_init : couldn't parse file descriptor '%s'\n", str); return(NULL); } - if((data = um_kmalloc(sizeof(*data))) == NULL) return(NULL); + data = um_kmalloc(sizeof(*data)); + if(data == NULL) return(NULL); *data = ((struct fd_chan) { .fd = n, .raw = opts->raw }); return(data); diff -Nru a/arch/um/drivers/harddog_user.c b/arch/um/drivers/harddog_user.c --- a/arch/um/drivers/harddog_user.c 2004-08-25 22:01:55 -07:00 +++ b/arch/um/drivers/harddog_user.c 2004-08-25 22:01:55 -07:00 @@ -27,10 +27,10 @@ dup2(data->stdin, 0); dup2(data->stdout, 1); dup2(data->stdout, 2); - close(data->stdin); - close(data->stdout); - close(data->close_me[0]); - close(data->close_me[1]); + os_close_file(data->stdin); + os_close_file(data->stdout); + os_close_file(data->close_me[0]); + os_close_file(data->close_me[1]); } int start_watchdog(int *in_fd_ret, int *out_fd_ret, char *sock) @@ -44,15 +44,15 @@ char **args = NULL; err = os_pipe(in_fds, 1, 0); - if(err){ - printk("harddog_open - os_pipe failed, errno = %d\n", -err); - return(err); + if(err < 0){ + printk("harddog_open - os_pipe failed, err = %d\n", -err); + goto out; } err = os_pipe(out_fds, 1, 0); - if(err){ - printk("harddog_open - os_pipe failed, errno = %d\n", -err); - return(err); + if(err < 0){ + printk("harddog_open - os_pipe failed, err = %d\n", -err); + goto out_close_in; } data.stdin = out_fds[0]; @@ -72,42 +72,47 @@ pid = run_helper(pre_exec, &data, args, NULL); - close(out_fds[0]); - close(in_fds[1]); + os_close_file(out_fds[0]); + os_close_file(in_fds[1]); if(pid < 0){ err = -pid; - printk("harddog_open - run_helper failed, errno = %d\n", err); - goto out; + printk("harddog_open - run_helper failed, errno = %d\n", -err); + goto out_close_out; } - n = read(in_fds[0], &c, sizeof(c)); + n = os_read_file(in_fds[0], &c, sizeof(c)); if(n == 0){ printk("harddog_open - EOF on watchdog pipe\n"); helper_wait(pid); err = -EIO; - goto out; + goto out_close_out; } else if(n < 0){ printk("harddog_open - read of watchdog pipe failed, " - "errno = %d\n", errno); + "err = %d\n", -n); helper_wait(pid); - err = -errno; - goto out; + err = n; + goto out_close_out; } *in_fd_ret = in_fds[0]; *out_fd_ret = out_fds[1]; return(0); + + out_close_in: + os_close_file(in_fds[0]); + os_close_file(in_fds[1]); + out_close_out: + os_close_file(out_fds[0]); + os_close_file(out_fds[1]); out: - close(out_fds[1]); - close(in_fds[0]); return(err); } void stop_watchdog(int in_fd, int out_fd) { - close(in_fd); - close(out_fd); + os_close_file(in_fd); + os_close_file(out_fd); } int ping_watchdog(int fd) @@ -115,11 +120,12 @@ int n; char c = '\n'; - n = write(fd, &c, sizeof(c)); - if(n < sizeof(c)){ - printk("ping_watchdog - write failed, errno = %d\n", - errno); - return(-errno); + n = os_write_file(fd, &c, sizeof(c)); + if(n != sizeof(c)){ + printk("ping_watchdog - write failed, err = %d\n", -n); + if(n < 0) + return(n); + return(-EIO); } return 1; diff -Nru a/arch/um/drivers/hostaudio_kern.c b/arch/um/drivers/hostaudio_kern.c --- a/arch/um/drivers/hostaudio_kern.c 2004-08-25 22:01:56 -07:00 +++ b/arch/um/drivers/hostaudio_kern.c 2004-08-25 22:01:56 -07:00 @@ -5,44 +5,64 @@ #include "linux/config.h" #include "linux/module.h" -#include "linux/version.h" #include "linux/init.h" #include "linux/slab.h" #include "linux/fs.h" #include "linux/sound.h" #include "linux/soundcard.h" +#include "asm/uaccess.h" #include "kern_util.h" #include "init.h" -#include "hostaudio.h" +#include "os.h" + +struct hostaudio_state { + int fd; +}; + +struct hostmixer_state { + int fd; +}; + +#define HOSTAUDIO_DEV_DSP "/dev/sound/dsp" +#define HOSTAUDIO_DEV_MIXER "/dev/sound/mixer" /* Only changed from linux_main at boot time */ char *dsp = HOSTAUDIO_DEV_DSP; char *mixer = HOSTAUDIO_DEV_MIXER; +#define DSP_HELP \ +" This is used to specify the host dsp device to the hostaudio driver.\n" \ +" The default is \"" HOSTAUDIO_DEV_DSP "\".\n\n" + +#define MIXER_HELP \ +" This is used to specify the host mixer device to the hostaudio driver.\n" \ +" The default is \"" HOSTAUDIO_DEV_MIXER "\".\n\n" + #ifndef MODULE static int set_dsp(char *name, int *add) { - dsp = uml_strdup(name); + dsp = name; return(0); } -__uml_setup("dsp=", set_dsp, -"dsp=\n" -" This is used to specify the host dsp device to the hostaudio driver.\n" -" The default is \"" HOSTAUDIO_DEV_DSP "\".\n\n" -); +__uml_setup("dsp=", set_dsp, "dsp=\n" DSP_HELP); static int set_mixer(char *name, int *add) { - mixer = uml_strdup(name); + mixer = name; return(0); } -__uml_setup("mixer=", set_mixer, -"mixer=\n" -" This is used to specify the host mixer device to the hostaudio driver.\n" -" The default is \"" HOSTAUDIO_DEV_MIXER "\".\n\n" -); +__uml_setup("mixer=", set_mixer, "mixer=\n" MIXER_HELP); + +#else /*MODULE*/ + +MODULE_PARM(dsp, "s"); +MODULE_PARM_DESC(dsp, DSP_HELP); + +MODULE_PARM(mixer, "s"); +MODULE_PARM_DESC(mixer, MIXER_HELP); + #endif /* /dev/dsp file operations */ @@ -51,23 +71,55 @@ loff_t *ppos) { struct hostaudio_state *state = file->private_data; + void *kbuf; + int ret; #ifdef DEBUG printk("hostaudio: read called, count = %d\n", count); #endif - return(hostaudio_read_user(state, buffer, count, ppos)); + kbuf = kmalloc(count, GFP_KERNEL); + if(kbuf == NULL) + return(-ENOMEM); + + ret = os_read_file(state->fd, kbuf, count); + if(ret < 0) + goto out; + + if(copy_to_user(buffer, kbuf, ret)) + ret = -EFAULT; + + out: + kfree(kbuf); + return(ret); } static ssize_t hostaudio_write(struct file *file, const char *buffer, size_t count, loff_t *ppos) { struct hostaudio_state *state = file->private_data; + void *kbuf; + int ret; #ifdef DEBUG printk("hostaudio: write called, count = %d\n", count); #endif - return(hostaudio_write_user(state, buffer, count, ppos)); + + kbuf = kmalloc(count, GFP_KERNEL); + if(kbuf == NULL) + return(-ENOMEM); + + ret = -EFAULT; + if(copy_from_user(kbuf, buffer, count)) + goto out; + + ret = os_write_file(state->fd, kbuf, count); + if(ret < 0) + goto out; + + out: + kfree(kbuf); + return(ret); } static unsigned int hostaudio_poll(struct file *file, @@ -86,12 +138,43 @@ unsigned int cmd, unsigned long arg) { struct hostaudio_state *state = file->private_data; + unsigned long data = 0; + int ret; #ifdef DEBUG printk("hostaudio: ioctl called, cmd = %u\n", cmd); #endif + switch(cmd){ + case SNDCTL_DSP_SPEED: + case SNDCTL_DSP_STEREO: + case SNDCTL_DSP_GETBLKSIZE: + case SNDCTL_DSP_CHANNELS: + case SNDCTL_DSP_SUBDIVIDE: + case SNDCTL_DSP_SETFRAGMENT: + if(get_user(data, (int *) arg)) + return(-EFAULT); + break; + default: + break; + } + + ret = os_ioctl_generic(state->fd, cmd, (unsigned long) &data); + + switch(cmd){ + case SNDCTL_DSP_SPEED: + case SNDCTL_DSP_STEREO: + case SNDCTL_DSP_GETBLKSIZE: + case SNDCTL_DSP_CHANNELS: + case SNDCTL_DSP_SUBDIVIDE: + case SNDCTL_DSP_SETFRAGMENT: + if(put_user(data, (int *) arg)) + return(-EFAULT); + break; + default: + break; + } - return(hostaudio_ioctl_user(state, cmd, arg)); + return(ret); } static int hostaudio_open(struct inode *inode, struct file *file) @@ -110,12 +193,17 @@ if(file->f_mode & FMODE_READ) r = 1; if(file->f_mode & FMODE_WRITE) w = 1; - ret = hostaudio_open_user(state, r, w, dsp); + ret = os_open_file(dsp, of_set_rw(OPENFLAGS(), r, w), 0); + if(ret < 0){ + printk("hostaudio_open failed to open '%s', err = %d\n", + dsp, -ret); kfree(state); return(ret); } + state->fd = ret; + file->private_data = state; return(0); } @@ -123,16 +211,19 @@ static int hostaudio_release(struct inode *inode, struct file *file) { struct hostaudio_state *state = file->private_data; - int ret; #ifdef DEBUG printk("hostaudio: release called\n"); #endif - ret = hostaudio_release_user(state); + if(state->fd >= 0){ + os_close_file(state->fd); + state->fd = -1; + } + kfree(state); - return(ret); + return(0); } /* /dev/mixer file operations */ @@ -146,7 +237,7 @@ printk("hostmixer: ioctl called\n"); #endif - return(hostmixer_ioctl_mixdev_user(state, cmd, arg)); + return(os_ioctl_generic(state->fd, cmd, arg)); } static int hostmixer_open_mixdev(struct inode *inode, struct file *file) @@ -165,13 +256,17 @@ if(file->f_mode & FMODE_READ) r = 1; if(file->f_mode & FMODE_WRITE) w = 1; - ret = hostmixer_open_mixdev_user(state, r, w, mixer); + ret = os_open_file(mixer, of_set_rw(OPENFLAGS(), r, w), 0); if(ret < 0){ + printk("hostaudio_open_mixdev failed to open '%s', err = %d\n", + dsp, -ret); kfree(state); return(ret); } + state->fd = ret; + file->private_data = state; return(0); } @@ -179,16 +274,18 @@ static int hostmixer_release(struct inode *inode, struct file *file) { struct hostmixer_state *state = file->private_data; - int ret; #ifdef DEBUG printk("hostmixer: release called\n"); #endif - ret = hostmixer_release_mixdev_user(state); + if(state->fd >= 0){ + os_close_file(state->fd); + state->fd = -1; + } kfree(state); - return(ret); + return(0); } @@ -225,7 +322,8 @@ static int __init hostaudio_init_module(void) { - printk(KERN_INFO "UML Audio Relay\n"); + printk(KERN_INFO "UML Audio Relay (host dsp = %s, host mixer = %s)\n", + dsp, mixer); module_data.dev_audio = register_sound_dsp(&hostaudio_fops, -1); if(module_data.dev_audio < 0){ diff -Nru a/arch/um/drivers/hostaudio_user.c b/arch/um/drivers/hostaudio_user.c --- a/arch/um/drivers/hostaudio_user.c 2004-08-25 22:01:56 -07:00 +++ /dev/null Wed Dec 31 16:00:00 196900 @@ -1,149 +0,0 @@ -/* - * Copyright (C) 2002 Steve Schmidtke - * Licensed under the GPL - */ - -#include -#include -#include -#include -#include -#include -#include "hostaudio.h" -#include "user_util.h" -#include "kern_util.h" -#include "user.h" -#include "os.h" - -/* /dev/dsp file operations */ - -ssize_t hostaudio_read_user(struct hostaudio_state *state, char *buffer, - size_t count, loff_t *ppos) -{ - ssize_t ret; - -#ifdef DEBUG - printk("hostaudio: read_user called, count = %d\n", count); -#endif - - ret = read(state->fd, buffer, count); - - if(ret < 0) return(-errno); - return(ret); -} - -ssize_t hostaudio_write_user(struct hostaudio_state *state, const char *buffer, - size_t count, loff_t *ppos) -{ - ssize_t ret; - -#ifdef DEBUG - printk("hostaudio: write_user called, count = %d\n", count); -#endif - - ret = write(state->fd, buffer, count); - - if(ret < 0) return(-errno); - return(ret); -} - -int hostaudio_ioctl_user(struct hostaudio_state *state, unsigned int cmd, - unsigned long arg) -{ - int ret; -#ifdef DEBUG - printk("hostaudio: ioctl_user called, cmd = %u\n", cmd); -#endif - - ret = ioctl(state->fd, cmd, arg); - - if(ret < 0) return(-errno); - return(ret); -} - -int hostaudio_open_user(struct hostaudio_state *state, int r, int w, char *dsp) -{ -#ifdef DEBUG - printk("hostaudio: open_user called\n"); -#endif - - state->fd = os_open_file(dsp, of_set_rw(OPENFLAGS(), r, w), 0); - - if(state->fd >= 0) return(0); - - printk("hostaudio_open_user failed to open '%s', errno = %d\n", - dsp, errno); - - return(-errno); -} - -int hostaudio_release_user(struct hostaudio_state *state) -{ -#ifdef DEBUG - printk("hostaudio: release called\n"); -#endif - if(state->fd >= 0){ - close(state->fd); - state->fd=-1; - } - - return(0); -} - -/* /dev/mixer file operations */ - -int hostmixer_ioctl_mixdev_user(struct hostmixer_state *state, - unsigned int cmd, unsigned long arg) -{ - int ret; -#ifdef DEBUG - printk("hostmixer: ioctl_user called cmd = %u\n",cmd); -#endif - - ret = ioctl(state->fd, cmd, arg); - if(ret < 0) - return(-errno); - return(ret); -} - -int hostmixer_open_mixdev_user(struct hostmixer_state *state, int r, int w, - char *mixer) -{ -#ifdef DEBUG - printk("hostmixer: open_user called\n"); -#endif - - state->fd = os_open_file(mixer, of_set_rw(OPENFLAGS(), r, w), 0); - - if(state->fd >= 0) return(0); - - printk("hostaudio_open_mixdev_user failed to open '%s', errno = %d\n", - mixer, errno); - - return(-errno); -} - -int hostmixer_release_mixdev_user(struct hostmixer_state *state) -{ -#ifdef DEBUG - printk("hostmixer: release_user called\n"); -#endif - - if(state->fd >= 0){ - close(state->fd); - state->fd = -1; - } - - return 0; -} - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-file-style: "linux" - * End: - */ diff -Nru a/arch/um/drivers/line.c b/arch/um/drivers/line.c --- a/arch/um/drivers/line.c 2004-08-25 22:01:56 -07:00 +++ b/arch/um/drivers/line.c 2004-08-25 22:01:56 -07:00 @@ -6,8 +6,8 @@ #include "linux/sched.h" #include "linux/slab.h" #include "linux/list.h" +#include "linux/interrupt.h" #include "linux/devfs_fs_kernel.h" -#include "asm/irq.h" #include "asm/uaccess.h" #include "chan_kern.h" #include "irq_user.h" @@ -16,38 +16,55 @@ #include "user_util.h" #include "kern_util.h" #include "os.h" +#include "irq_kern.h" #define LINE_BUFSIZE 4096 -void line_interrupt(int irq, void *data, struct pt_regs *unused) +static irqreturn_t line_interrupt(int irq, void *data, struct pt_regs *unused) { struct line *dev = data; if(dev->count > 0) chan_interrupt(&dev->chan_list, &dev->task, dev->tty, irq, dev); + return IRQ_HANDLED; } -void line_timer_cb(void *arg) +static void line_timer_cb(void *arg) { struct line *dev = arg; line_interrupt(dev->driver->read_irq, dev, NULL); } -static void buffer_data(struct line *line, const char *buf, int len) +static int write_room(struct line *dev) { - int end; + int n; + + if(dev->buffer == NULL) return(LINE_BUFSIZE - 1); + + n = dev->head - dev->tail; + if(n <= 0) n = LINE_BUFSIZE + n; + return(n - 1); +} + +static int buffer_data(struct line *line, const char *buf, int len) +{ + int end, room; if(line->buffer == NULL){ line->buffer = kmalloc(LINE_BUFSIZE, GFP_ATOMIC); if(line->buffer == NULL){ printk("buffer_data - atomic allocation failed\n"); - return; + return(0); } line->head = line->buffer; line->tail = line->buffer; } + + room = write_room(line); + len = (len > room) ? room : len; + end = line->buffer + LINE_BUFSIZE - line->tail; if(len < end){ memcpy(line->tail, buf, len); @@ -60,6 +77,8 @@ memcpy(line->buffer, buf, len); line->tail = line->buffer + len; } + + return(len); } static int flush_buffer(struct line *line) @@ -95,7 +114,7 @@ struct line *line; char *new; unsigned long flags; - int n, err, i; + int n, err, i, ret = 0; if(tty->stopped) return 0; @@ -104,9 +123,13 @@ if(new == NULL) return(0); n = copy_from_user(new, buf, len); - if(n == len) - return(-EFAULT); buf = new; + if(n == len){ + len = -EFAULT; + goto out_free; + } + + len -= n; } i = tty->index; @@ -115,41 +138,50 @@ down(&line->sem); if(line->head != line->tail){ local_irq_save(flags); - buffer_data(line, buf, len); + ret += buffer_data(line, buf, len); err = flush_buffer(line); local_irq_restore(flags); if(err <= 0) - goto out; + goto out_up; } else { n = write_chan(&line->chan_list, buf, len, line->driver->write_irq); if(n < 0){ - len = n; - goto out; + ret = n; + goto out_up; } - if(n < len) - buffer_data(line, buf + n, len - n); + + len -= n; + ret += n; + if(len > 0) + ret += buffer_data(line, buf + n, len); } - out: + out_up: up(&line->sem); - return(len); + out_free: + if(from_user) + kfree(buf); + return(ret); } -void line_write_interrupt(int irq, void *data, struct pt_regs *unused) +static irqreturn_t line_write_interrupt(int irq, void *data, + struct pt_regs *unused) { struct line *dev = data; struct tty_struct *tty = dev->tty; int err; err = flush_buffer(dev); - if(err == 0) return; + if(err == 0) + return(IRQ_NONE); else if(err < 0){ dev->head = dev->buffer; dev->tail = dev->buffer; } - if(tty == NULL) return; + if(tty == NULL) + return(IRQ_NONE); if(test_bit(TTY_DO_WRITE_WAKEUP, &tty->flags) && (tty->ldisc.write_wakeup != NULL)) @@ -161,21 +193,9 @@ * writes. */ - if (waitqueue_active(&tty->write_wait)) + if(waitqueue_active(&tty->write_wait)) wake_up_interruptible(&tty->write_wait); - -} - -int line_write_room(struct tty_struct *tty) -{ - struct line *dev = tty->driver_data; - int n; - - if(dev->buffer == NULL) return(LINE_BUFSIZE - 1); - - n = dev->head - dev->tail; - if(n <= 0) n = LINE_BUFSIZE + n; - return(n - 1); + return(IRQ_HANDLED); } int line_setup_irq(int fd, int input, int output, void *data) @@ -305,7 +325,7 @@ if(*end != '='){ printk(KERN_ERR "line_setup failed to parse \"%s\"\n", init); - return(1); + return(0); } init = end; } @@ -313,12 +333,12 @@ if((n >= 0) && (n >= num)){ printk("line_setup - %d out of range ((0 ... %d) allowed)\n", n, num); - return(1); + return(0); } else if(n >= 0){ if(lines[n].count > 0){ printk("line_setup - device %d is open\n", n); - return(1); + return(0); } if(lines[n].init_pri <= INIT_ONE){ lines[n].init_pri = INIT_ONE; @@ -332,7 +352,7 @@ else if(!all_allowed){ printk("line_setup - can't configure all devices from " "mconsole\n"); - return(1); + return(0); } else { for(i = 0; i < num; i++){ @@ -346,7 +366,7 @@ } } } - return(0); + return(1); } int line_config(struct line *lines, int num, char *str) @@ -357,7 +377,7 @@ printk("line_config - uml_strdup failed\n"); return(-ENOMEM); } - return(line_setup(lines, num, new, 0)); + return(!line_setup(lines, num, new, 0)); } int line_get_config(char *name, struct line *lines, int num, char *str, @@ -369,7 +389,7 @@ dev = simple_strtoul(name, &end, 0); if((*end != '\0') || (end == name)){ - *error_out = "line_setup failed to parse device number"; + *error_out = "line_get_config failed to parse device number"; return(0); } @@ -379,15 +399,15 @@ } line = &lines[dev]; + down(&line->sem); - if(!line->valid) CONFIG_CHUNK(str, size, n, "none", 1); else if(line->count == 0) CONFIG_CHUNK(str, size, n, line->init_str, 1); else n = chan_config_string(&line->chan_list, str, size, error_out); - up(&line->sem); + return(n); } @@ -396,7 +416,14 @@ char config[sizeof("conxxxx=none\0")]; sprintf(config, "%s=none", str); - return(line_setup(lines, num, config, 0)); + return(!line_setup(lines, num, config, 0)); +} + +int line_write_room(struct tty_struct *tty) +{ + struct line *dev = tty->driver_data; + + return(write_room(dev)); } struct tty_driver *line_register_devfs(struct lines *set, @@ -412,7 +439,8 @@ return NULL; driver->driver_name = line_driver->name; - driver->name = line_driver->devfs_name; + driver->name = line_driver->device_name; + driver->devfs_name = line_driver->devfs_name; driver->major = line_driver->major; driver->minor_start = line_driver->minor_start; driver->type = line_driver->type; @@ -432,7 +460,7 @@ for(i = 0; i < nlines; i++){ if(!lines[i].valid) - tty_unregister_devfs(driver, i); + tty_unregister_device(driver, i); } mconsole_register_dev(&line_driver->mc); @@ -465,24 +493,25 @@ struct line *line; }; -void winch_interrupt(int irq, void *data, struct pt_regs *unused) +irqreturn_t winch_interrupt(int irq, void *data, struct pt_regs *unused) { struct winch *winch = data; struct tty_struct *tty; int err; char c; - err = generic_read(winch->fd, &c, NULL); - if(err < 0){ - if(err != -EAGAIN){ - printk("winch_interrupt : read failed, errno = %d\n", - -err); - printk("fd %d is losing SIGWINCH support\n", - winch->tty_fd); - free_irq(irq, data); - return; + if(winch->fd != -1){ + err = generic_read(winch->fd, &c, NULL); + if(err < 0){ + if(err != -EAGAIN){ + printk("winch_interrupt : read failed, " + "errno = %d\n", -err); + printk("fd %d is losing SIGWINCH support\n", + winch->tty_fd); + return(IRQ_HANDLED); + } + goto out; } - goto out; } tty = winch->line->tty; if(tty != NULL){ @@ -492,7 +521,9 @@ kill_pg(tty->pgrp, SIGWINCH, 1); } out: - reactivate_fd(winch->fd, WINCH_IRQ); + if(winch->fd != -1) + reactivate_fd(winch->fd, WINCH_IRQ); + return(IRQ_HANDLED); } DECLARE_MUTEX(winch_handler_sem); @@ -529,7 +560,10 @@ list_for_each(ele, &winch_handlers){ winch = list_entry(ele, struct winch, list); - close(winch->fd); + if(winch->fd != -1){ + deactivate_fd(winch->fd, WINCH_IRQ); + os_close_file(winch->fd); + } if(winch->pid != -1) os_kill_process(winch->pid, 1); } diff -Nru a/arch/um/drivers/mcast_user.c b/arch/um/drivers/mcast_user.c --- a/arch/um/drivers/mcast_user.c 2004-08-25 22:01:55 -07:00 +++ b/arch/um/drivers/mcast_user.c 2004-08-25 22:01:55 -07:00 @@ -23,6 +23,7 @@ #include "kern_util.h" #include "user_util.h" #include "user.h" +#include "os.h" #define MAX_PACKET (ETH_MAX_PACKET + ETH_HEADER_OTHER) @@ -62,7 +63,8 @@ goto out; } - if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0){ + fd = socket(AF_INET, SOCK_DGRAM, 0); + if (fd < 0){ printk("mcast_open : data socket failed, errno = %d\n", errno); fd = -ENOMEM; @@ -72,7 +74,7 @@ if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0) { printk("mcast_open: SO_REUSEADDR failed, errno = %d\n", errno); - close(fd); + os_close_file(fd); fd = -EINVAL; goto out; } @@ -82,7 +84,7 @@ sizeof(pri->ttl)) < 0) { printk("mcast_open: IP_MULTICAST_TTL failed, error = %d\n", errno); - close(fd); + os_close_file(fd); fd = -EINVAL; goto out; } @@ -91,7 +93,7 @@ if (setsockopt(fd, SOL_IP, IP_MULTICAST_LOOP, &yes, sizeof(yes)) < 0) { printk("mcast_open: IP_MULTICAST_LOOP failed, error = %d\n", errno); - close(fd); + os_close_file(fd); fd = -EINVAL; goto out; } @@ -99,7 +101,7 @@ /* bind socket to mcast address */ if (bind(fd, (struct sockaddr *) sin, sizeof(*sin)) < 0) { printk("mcast_open : data bind failed, errno = %d\n", errno); - close(fd); + os_close_file(fd); fd = -EINVAL; goto out; } @@ -115,7 +117,7 @@ "interface on the host.\n"); printk("eth0 should be configured in order to use the " "multicast transport.\n"); - close(fd); + os_close_file(fd); fd = -EINVAL; } @@ -137,7 +139,7 @@ errno); } - close(fd); + os_close_file(fd); } int mcast_user_write(int fd, void *buf, int len, struct mcast_data *pri) diff -Nru a/arch/um/drivers/mconsole_kern.c b/arch/um/drivers/mconsole_kern.c --- a/arch/um/drivers/mconsole_kern.c 2004-08-25 22:01:54 -07:00 +++ b/arch/um/drivers/mconsole_kern.c 2004-08-25 22:01:54 -07:00 @@ -1,6 +1,6 @@ /* * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) - * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) + * Copyright (C) 2001 - 2003 Jeff Dike (jdike@addtoit.com) * Licensed under the GPL */ @@ -15,6 +15,9 @@ #include "linux/sysrq.h" #include "linux/workqueue.h" #include "linux/module.h" +#include "linux/file.h" +#include "linux/fs.h" +#include "linux/namei.h" #include "linux/proc_fs.h" #include "asm/irq.h" #include "asm/uaccess.h" @@ -27,6 +30,7 @@ #include "init.h" #include "os.h" #include "umid.h" +#include "irq_kern.h" static int do_unlink_socket(struct notifier_block *notifier, unsigned long what, void *data) @@ -67,7 +71,7 @@ DECLARE_WORK(mconsole_work, mc_work_proc, NULL); -void mconsole_interrupt(int irq, void *dev_id, struct pt_regs *regs) +irqreturn_t mconsole_interrupt(int irq, void *dev_id, struct pt_regs *regs) { int fd; struct mconsole_entry *new; @@ -75,9 +79,10 @@ fd = (int) dev_id; while (mconsole_get_request(fd, &req)){ - if(req.cmd->as_interrupt) (*req.cmd->handler)(&req); + if(req.cmd->context == MCONSOLE_INTR) + (*req.cmd->handler)(&req); else { - new = kmalloc(sizeof(req), GFP_ATOMIC); + new = kmalloc(sizeof(*new), GFP_ATOMIC); if(new == NULL) mconsole_reply(&req, "Out of memory", 1, 0); else { @@ -88,6 +93,7 @@ } if(!list_empty(&mc_requests)) schedule_work(&mconsole_work); reactivate_fd(fd, MCONSOLE_IRQ); + return(IRQ_HANDLED); } void mconsole_version(struct mc_request *req) @@ -100,20 +106,109 @@ mconsole_reply(req, version, 0, 0); } +void mconsole_log(struct mc_request *req) +{ + int len; + char *ptr = req->request.data; + + ptr += strlen("log "); + + len = req->len - (ptr - req->request.data); + printk("%.*s", len, ptr); + mconsole_reply(req, "", 0, 0); +} + +void mconsole_proc(struct mc_request *req) +{ + struct nameidata nd; + struct file_system_type *proc; + struct super_block *super; + struct file *file; + int n, err; + char *ptr = req->request.data, *buf; + + ptr += strlen("proc"); + while(isspace(*ptr)) ptr++; + + proc = get_fs_type("proc"); + if(proc == NULL){ + mconsole_reply(req, "procfs not registered", 1, 0); + goto out; + } + + super = (*proc->get_sb)(proc, 0, NULL, NULL); + put_filesystem(proc); + if(super == NULL){ + mconsole_reply(req, "Failed to get procfs superblock", 1, 0); + goto out; + } + up_write(&super->s_umount); + + nd.dentry = super->s_root; + nd.mnt = NULL; + nd.flags = O_RDONLY + 1; + nd.last_type = LAST_ROOT; + + err = link_path_walk(ptr, &nd); + if(err){ + mconsole_reply(req, "Failed to look up file", 1, 0); + goto out_kill; + } + + file = dentry_open(nd.dentry, nd.mnt, O_RDONLY); + if(IS_ERR(file)){ + mconsole_reply(req, "Failed to open file", 1, 0); + goto out_kill; + } + + buf = kmalloc(PAGE_SIZE, GFP_KERNEL); + if(buf == NULL){ + mconsole_reply(req, "Failed to allocate buffer", 1, 0); + goto out_fput; + } + + if((file->f_op != NULL) && (file->f_op->read != NULL)){ + do { + n = (*file->f_op->read)(file, buf, PAGE_SIZE - 1, + &file->f_pos); + if(n >= 0){ + buf[n] = '\0'; + mconsole_reply(req, buf, 0, (n > 0)); + } + else { + mconsole_reply(req, "Read of file failed", + 1, 0); + goto out_free; + } + } while(n > 0); + } + else mconsole_reply(req, "", 0, 0); + + out_free: + kfree(buf); + out_fput: + fput(file); + out_kill: + deactivate_super(super); + out: ; +} + #define UML_MCONSOLE_HELPTEXT \ -"Commands: - version - Get kernel version - help - Print this message - halt - Halt UML - reboot - Reboot UML - config = - Add a new device to UML; - same syntax as command line - config - Query the configuration of a device - remove - Remove a device from UML - sysrq - Performs the SysRq action controlled by the letter - cad - invoke the Ctl-Alt-Del handler - stop - pause the UML; it will do nothing until it receives a 'go' - go - continue the UML after a 'stop' +"Commands: \n\ + version - Get kernel version \n\ + help - Print this message \n\ + halt - Halt UML \n\ + reboot - Reboot UML \n\ + config = - Add a new device to UML; \n\ + same syntax as command line \n\ + config - Query the configuration of a device \n\ + remove - Remove a device from UML \n\ + sysrq - Performs the SysRq action controlled by the letter \n\ + cad - invoke the Ctl-Alt-Del handler \n\ + stop - pause the UML; it will do nothing until it receives a 'go' \n\ + go - continue the UML after a 'stop' \n\ + log - make UML enter into the kernel log\n\ + proc - returns the contents of the UML's /proc/\n\ " void mconsole_help(struct mc_request *req) @@ -302,7 +397,7 @@ if(umid_file_name("mconsole", file, sizeof(file))) return(-1); snprintf(mconsole_socket_name, sizeof(file), "%s", file); - sock = create_unix_socket(file, sizeof(file)); + sock = os_create_unix_socket(file, sizeof(file), 1); if (sock < 0){ printk("Failed to initialize management console\n"); return(1); @@ -344,11 +439,16 @@ if(buf == NULL) return(-ENOMEM); - if(copy_from_user(buf, buffer, count)) - return(-EFAULT); + if(copy_from_user(buf, buffer, count)){ + count = -EFAULT; + goto out; + } + buf[count] = '\0'; mconsole_notify(notify_socket, MCONSOLE_USER_NOTIFY, buf, count); + out: + kfree(buf); return(count); } diff -Nru a/arch/um/drivers/mconsole_user.c b/arch/um/drivers/mconsole_user.c --- a/arch/um/drivers/mconsole_user.c 2004-08-25 22:01:54 -07:00 +++ b/arch/um/drivers/mconsole_user.c 2004-08-25 22:01:54 -07:00 @@ -1,6 +1,6 @@ /* * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) - * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) + * Copyright (C) 2001 - 2003 Jeff Dike (jdike@addtoit.com) * Licensed under the GPL */ @@ -18,16 +18,18 @@ #include "umid.h" static struct mconsole_command commands[] = { - { "version", mconsole_version, 1 }, - { "halt", mconsole_halt, 0 }, - { "reboot", mconsole_reboot, 0 }, - { "config", mconsole_config, 0 }, - { "remove", mconsole_remove, 0 }, - { "sysrq", mconsole_sysrq, 1 }, - { "help", mconsole_help, 1 }, - { "cad", mconsole_cad, 1 }, - { "stop", mconsole_stop, 0 }, - { "go", mconsole_go, 1 }, + { "version", mconsole_version, MCONSOLE_INTR }, + { "halt", mconsole_halt, MCONSOLE_PROC }, + { "reboot", mconsole_reboot, MCONSOLE_PROC }, + { "config", mconsole_config, MCONSOLE_PROC }, + { "remove", mconsole_remove, MCONSOLE_PROC }, + { "sysrq", mconsole_sysrq, MCONSOLE_INTR }, + { "help", mconsole_help, MCONSOLE_INTR }, + { "cad", mconsole_cad, MCONSOLE_INTR }, + { "stop", mconsole_stop, MCONSOLE_PROC }, + { "go", mconsole_go, MCONSOLE_INTR }, + { "log", mconsole_log, MCONSOLE_INTR }, + { "proc", mconsole_proc, MCONSOLE_PROC }, }; /* Initialized in mconsole_init, which is an initcall */ @@ -139,6 +141,7 @@ memcpy(reply.data, str, len); reply.data[len] = '\0'; total -= len; + str += len; reply.len = len + 1; len = sizeof(reply) + reply.len - sizeof(reply.data); diff -Nru a/arch/um/drivers/mmapper_kern.c b/arch/um/drivers/mmapper_kern.c --- a/arch/um/drivers/mmapper_kern.c 2004-08-25 22:01:54 -07:00 +++ b/arch/um/drivers/mmapper_kern.c 2004-08-25 22:01:54 -07:00 @@ -120,7 +120,10 @@ printk(KERN_INFO "Mapper v0.1\n"); v_buf = (char *) find_iomem("mmapper", &mmapper_size); - if(mmapper_size == 0) return(0); + if(mmapper_size == 0){ + printk(KERN_ERR "mmapper_init - find_iomem failed\n"); + return(0); + } p_buf = __pa(v_buf); diff -Nru a/arch/um/drivers/net_kern.c b/arch/um/drivers/net_kern.c --- a/arch/um/drivers/net_kern.c 2004-08-25 22:01:55 -07:00 +++ b/arch/um/drivers/net_kern.c 2004-08-25 22:01:55 -07:00 @@ -26,6 +26,7 @@ #include "mconsole_kern.h" #include "init.h" #include "irq_user.h" +#include "irq_kern.h" static spinlock_t opened_lock = SPIN_LOCK_UNLOCKED; LIST_HEAD(opened); @@ -37,7 +38,8 @@ struct sk_buff *skb; /* If we can't allocate memory, try again next round. */ - if ((skb = dev_alloc_skb(dev->mtu)) == NULL) { + skb = dev_alloc_skb(dev->mtu); + if (skb == NULL) { lp->stats.rx_dropped++; return 0; } @@ -61,14 +63,14 @@ return pkt_len; } -void uml_net_interrupt(int irq, void *dev_id, struct pt_regs *regs) +irqreturn_t uml_net_interrupt(int irq, void *dev_id, struct pt_regs *regs) { struct net_device *dev = dev_id; struct uml_net_private *lp = dev->priv; int err; if(!netif_running(dev)) - return; + return(IRQ_NONE); spin_lock(&lp->lock); while((err = uml_net_rx(dev)) > 0) ; @@ -83,6 +85,7 @@ out: spin_unlock(&lp->lock); + return(IRQ_HANDLED); } static int uml_net_open(struct net_device *dev) @@ -250,37 +253,6 @@ #endif } -/* - * default do nothing hard header packet routines for struct net_device init. - * real ethernet transports will overwrite with real routines. - */ -static int uml_net_hard_header(struct sk_buff *skb, struct net_device *dev, - unsigned short type, void *daddr, void *saddr, unsigned len) -{ - return(0); /* no change */ -} - -static int uml_net_rebuild_header(struct sk_buff *skb) -{ - return(0); /* ignore */ -} - -static int uml_net_header_cache(struct neighbour *neigh, struct hh_cache *hh) -{ - return(-1); /* fail */ -} - -static void uml_net_header_cache_update(struct hh_cache *hh, - struct net_device *dev, unsigned char * haddr) -{ - /* ignore */ -} - -static int uml_net_header_parse(struct sk_buff *skb, unsigned char *haddr) -{ - return(0); /* nothing */ -} - static spinlock_t devices_lock = SPIN_LOCK_UNLOCKED; static struct list_head devices = LIST_HEAD_INIT(devices); @@ -290,7 +262,7 @@ struct uml_net *device; struct net_device *dev; struct uml_net_private *lp; - int err, size; + int save, err, size; size = transport->private_size + sizeof(struct uml_net_private) + sizeof(((struct uml_net_private *) 0)->user); @@ -332,12 +304,6 @@ snprintf(dev->name, sizeof(dev->name), "eth%d", n); device->dev = dev; - dev->hard_header = uml_net_hard_header; - dev->rebuild_header = uml_net_rebuild_header; - dev->hard_header_cache = uml_net_header_cache; - dev->header_cache_update= uml_net_header_cache_update; - dev->hard_header_parse = uml_net_header_parse; - (*transport->kern->init)(dev, init); dev->mtu = transport->user->max_packet; @@ -364,21 +330,29 @@ } lp = dev->priv; - INIT_LIST_HEAD(&lp->list); - spin_lock_init(&lp->lock); - lp->dev = dev; - lp->fd = -1; - lp->mac = { 0xfe, 0xfd, 0x0, 0x0, 0x0, 0x0 }; - lp->have_mac = device->have_mac; - lp->protocol = transport->kern->protocol; - lp->open = transport->user->open; - lp->close = transport->user->close; - lp->remove = transport->user->remove; - lp->read = transport->kern->read; - lp->write = transport->kern->write; - lp->add_address = transport->user->add_address; - lp->delete_address = transport->user->delete_address; - lp->set_mtu = transport->user->set_mtu; + /* lp.user is the first four bytes of the transport data, which + * has already been initialized. This structure assignment will + * overwrite that, so we make sure that .user gets overwritten with + * what it already has. + */ + save = lp->user[0]; + *lp = ((struct uml_net_private) + { .list = LIST_HEAD_INIT(lp->list), + .lock = SPIN_LOCK_UNLOCKED, + .dev = dev, + .fd = -1, + .mac = { 0xfe, 0xfd, 0x0, 0x0, 0x0, 0x0}, + .have_mac = device->have_mac, + .protocol = transport->kern->protocol, + .open = transport->user->open, + .close = transport->user->close, + .remove = transport->user->remove, + .read = transport->kern->read, + .write = transport->kern->write, + .add_address = transport->user->add_address, + .delete_address = transport->user->delete_address, + .set_mtu = transport->user->set_mtu, + .user = { save } }); init_timer(&lp->tl); lp->tl.function = uml_net_user_timer_expire; @@ -611,7 +585,8 @@ unregister_netdev(dev); list_del(&device->list); - free_netdev(device); + kfree(device); + free_netdev(dev); return(0); } diff -Nru a/arch/um/drivers/net_user.c b/arch/um/drivers/net_user.c --- a/arch/um/drivers/net_user.c 2004-08-25 22:01:54 -07:00 +++ b/arch/um/drivers/net_user.c 2004-08-25 22:01:54 -07:00 @@ -26,8 +26,7 @@ if(gate_addr == NULL) return(0); if(sscanf(gate_addr, "%d.%d.%d.%d", &tap_addr[0], &tap_addr[1], &tap_addr[2], &tap_addr[3]) != 4){ - printk("Invalid tap IP address - '%s'\n", - gate_addr); + printk("Invalid tap IP address - '%s'\n", gate_addr); return(-EINVAL); } return(0); @@ -60,18 +59,18 @@ } *output = '\0'; - if(read(fd, &remain, sizeof(remain)) != sizeof(remain)){ - printk("read_output - read of length failed, errno = %d\n", - errno); + n = os_read_file(fd, &remain, sizeof(remain)); + if(n != sizeof(remain)){ + printk("read_output - read of length failed, err = %d\n", -n); return; } while(remain != 0){ n = (remain < len) ? remain : len; - actual = read(fd, output, n); + actual = os_read_file(fd, output, n); if(actual != n){ printk("read_output - read of data failed, " - "errno = %d\n", errno); + "err = %d\n", -actual); return; } remain -= actual; @@ -83,13 +82,12 @@ { int n; - while(((n = read(fd, buf, len)) < 0) && (errno == EINTR)) ; + n = os_read_file(fd, buf, len); - if(n < 0){ - if(errno == EAGAIN) return(0); - return(-errno); - } - else if(n == 0) return(-ENOTCONN); + if(n == -EAGAIN) + return(0); + else if(n == 0) + return(-ENOTCONN); return(n); } @@ -112,13 +110,13 @@ { int n; - while(((n = write(fd, buf, len)) < 0) && (errno == EINTR)) ; - if(n < 0){ - if(errno == EAGAIN) return(0); - return(-errno); - } - else if(n == 0) return(-ENOTCONN); - return(n); + n = os_write_file(fd, buf, len); + + if(n == -EAGAIN) + return(0); + else if(n == 0) + return(-ENOTCONN); + return(n); } int net_send(int fd, void *buf, int len) @@ -157,7 +155,7 @@ { struct change_pre_exec_data *data = arg; - close(data->close_me); + os_close_file(data->close_me); dup2(data->stdout, 1); } @@ -167,17 +165,18 @@ struct change_pre_exec_data pe_data; err = os_pipe(fds, 1, 0); - if(err){ - printk("change_tramp - pipe failed, errno = %d\n", -err); + if(err < 0){ + printk("change_tramp - pipe failed, err = %d\n", -err); return(err); } pe_data.close_me = fds[0]; pe_data.stdout = fds[1]; pid = run_helper(change_pre_exec, &pe_data, argv, NULL); - close(fds[1]); + os_close_file(fds[1]); read_output(fds[0], output, output_len); - waitpid(pid, NULL, 0); + + CATCH_EINTR(err = waitpid(pid, NULL, 0)); return(pid); } diff -Nru a/arch/um/drivers/null.c b/arch/um/drivers/null.c --- a/arch/um/drivers/null.c 2004-08-25 22:01:54 -07:00 +++ b/arch/um/drivers/null.c 2004-08-25 22:01:54 -07:00 @@ -5,7 +5,6 @@ #include #include -#include #include "chan_user.h" #include "os.h" diff -Nru a/arch/um/drivers/port_kern.c b/arch/um/drivers/port_kern.c --- a/arch/um/drivers/port_kern.c 2004-08-25 22:01:54 -07:00 +++ b/arch/um/drivers/port_kern.c 2004-08-25 22:01:54 -07:00 @@ -6,6 +6,7 @@ #include "linux/list.h" #include "linux/sched.h" #include "linux/slab.h" +#include "linux/interrupt.h" #include "linux/irq.h" #include "linux/spinlock.h" #include "linux/errno.h" @@ -14,6 +15,7 @@ #include "kern_util.h" #include "kern.h" #include "irq_user.h" +#include "irq_kern.h" #include "port.h" #include "init.h" #include "os.h" @@ -38,21 +40,21 @@ struct connection { struct list_head list; int fd; - int helper_pid; + int helper_pid; int socket[2]; int telnetd_pid; struct port_list *port; }; -static void pipe_interrupt(int irq, void *data, struct pt_regs *regs) +static irqreturn_t pipe_interrupt(int irq, void *data, struct pt_regs *regs) { struct connection *conn = data; int fd; - fd = os_rcv_fd(conn->socket[0], &conn->helper_pid); + fd = os_rcv_fd(conn->socket[0], &conn->helper_pid); if(fd < 0){ if(fd == -EAGAIN) - return; + return(IRQ_NONE); printk(KERN_ERR "pipe_interrupt : os_rcv_fd returned %d\n", -fd); @@ -65,6 +67,7 @@ list_add(&conn->list, &conn->port->connections); up(&conn->port->sem); + return(IRQ_HANDLED); } static int port_accept(struct port_list *port) @@ -102,8 +105,7 @@ } list_add(&conn->list, &port->pending); - ret = 1; - goto out; + return(1); out_free: kfree(conn); @@ -138,12 +140,13 @@ DECLARE_WORK(port_work, port_work_proc, NULL); -static void port_interrupt(int irq, void *data, struct pt_regs *regs) +static irqreturn_t port_interrupt(int irq, void *data, struct pt_regs *regs) { struct port_list *port = data; port->has_connection = 1; schedule_work(&port_work); + return(IRQ_HANDLED); } void *port_data(int port_num) diff -Nru a/arch/um/drivers/port_user.c b/arch/um/drivers/port_user.c --- a/arch/um/drivers/port_user.c 2004-08-25 22:01:55 -07:00 +++ b/arch/um/drivers/port_user.c 2004-08-25 22:01:55 -07:00 @@ -47,10 +47,12 @@ return(NULL); } - if((kern_data = port_data(port)) == NULL) + kern_data = port_data(port); + if(kern_data == NULL) return(NULL); - if((data = um_kmalloc(sizeof(*data))) == NULL) + data = um_kmalloc(sizeof(*data)); + if(data == NULL) goto err; *data = ((struct port_chan) { .raw = opts->raw, @@ -90,7 +92,7 @@ struct port_chan *data = d; port_remove_dev(data->kernel_data); - close(fd); + os_close_file(fd); } int port_console_write(int fd, const char *buf, int n, void *d) @@ -130,11 +132,15 @@ goto out; } - if((listen(fd, 1) < 0) || (os_set_fd_block(fd, 0))){ + if(listen(fd, 1) < 0){ err = -errno; goto out; } + err = os_set_fd_block(fd, 0); + if(err < 0) + goto out; + return(fd); out: os_close_file(fd); @@ -153,10 +159,10 @@ dup2(data->sock_fd, 0); dup2(data->sock_fd, 1); dup2(data->sock_fd, 2); - close(data->sock_fd); + os_close_file(data->sock_fd); dup2(data->pipe_fd, 3); os_shutdown_socket(3, 1, 0); - close(data->pipe_fd); + os_close_file(data->pipe_fd); } int port_connection(int fd, int *socket, int *pid_out) @@ -166,11 +172,12 @@ "/usr/lib/uml/port-helper", NULL }; struct port_pre_exec_data data; - if((new = os_accept_connection(fd)) < 0) - return(-errno); + new = os_accept_connection(fd); + if(new < 0) + return(new); err = os_pipe(socket, 0, 0); - if(err) + if(err < 0) goto out_close; data = ((struct port_pre_exec_data) @@ -186,11 +193,11 @@ out_shutdown: os_shutdown_socket(socket[0], 1, 1); - close(socket[0]); + os_close_file(socket[0]); os_shutdown_socket(socket[1], 1, 1); - close(socket[1]); + os_close_file(socket[1]); out_close: - close(new); + os_close_file(new); return(err); } diff -Nru a/arch/um/drivers/pty.c b/arch/um/drivers/pty.c --- a/arch/um/drivers/pty.c 2004-08-25 22:01:56 -07:00 +++ b/arch/um/drivers/pty.c 2004-08-25 22:01:56 -07:00 @@ -7,12 +7,12 @@ #include #include #include -#include #include #include "chan_user.h" #include "user.h" #include "user_util.h" #include "kern_util.h" +#include "os.h" struct pty_chan { void (*announce)(char *dev_name, int dev); @@ -26,7 +26,8 @@ { struct pty_chan *data; - if((data = um_kmalloc(sizeof(*data))) == NULL) return(NULL); + data = um_kmalloc(sizeof(*data)); + if(data == NULL) return(NULL); *data = ((struct pty_chan) { .announce = opts->announce, .dev = device, .raw = opts->raw }); @@ -39,7 +40,8 @@ char *dev; int fd; - if((fd = get_pty()) < 0){ + fd = get_pty(); + if(fd < 0){ printk("open_pts : Failed to open pts\n"); return(-errno); } @@ -57,29 +59,27 @@ int getmaster(char *line) { - struct stat stb; char *pty, *bank, *cp; - int master; + int master, err; pty = &line[strlen("/dev/ptyp")]; for (bank = "pqrs"; *bank; bank++) { line[strlen("/dev/pty")] = *bank; *pty = '0'; - if (stat(line, &stb) < 0) + if (os_stat_file(line, NULL) < 0) break; for (cp = "0123456789abcdef"; *cp; cp++) { *pty = *cp; - master = open(line, O_RDWR); + master = os_open_file(line, of_rdwr(OPENFLAGS()), 0); if (master >= 0) { char *tp = &line[strlen("/dev/")]; - int ok; /* verify slave side is usable */ *tp = 't'; - ok = access(line, R_OK|W_OK) == 0; + err = os_access(line, OS_ACC_RW_OK); *tp = 'p'; - if (ok) return(master); - (void) close(master); + if(err == 0) return(master); + (void) os_close_file(master); } } } diff -Nru a/arch/um/drivers/slip_user.c b/arch/um/drivers/slip_user.c --- a/arch/um/drivers/slip_user.c 2004-08-25 22:01:56 -07:00 +++ b/arch/um/drivers/slip_user.c 2004-08-25 22:01:56 -07:00 @@ -4,11 +4,9 @@ #include #include #include -#include -#include +#include #include #include -#include #include #include "user_util.h" #include "kern_util.h" @@ -65,9 +63,9 @@ { struct slip_pre_exec_data *data = arg; - if(data->stdin != -1) dup2(data->stdin, 0); + if(data->stdin >= 0) dup2(data->stdin, 0); dup2(data->stdout, 1); - if(data->close_me != -1) close(data->close_me); + if(data->close_me >= 0) os_close_file(data->close_me); } static int slip_tramp(char **argv, int fd) @@ -77,8 +75,8 @@ int status, pid, fds[2], err, output_len; err = os_pipe(fds, 1, 0); - if(err){ - printk("slip_tramp : pipe failed, errno = %d\n", -err); + if(err < 0){ + printk("slip_tramp : pipe failed, err = %d\n", -err); return(err); } @@ -96,16 +94,18 @@ printk("slip_tramp : failed to allocate output " "buffer\n"); - close(fds[1]); + os_close_file(fds[1]); read_output(fds[0], output, output_len); if(output != NULL){ printk("%s", output); kfree(output); } - if(waitpid(pid, &status, 0) < 0) err = errno; + CATCH_EINTR(err = waitpid(pid, &status, 0)); + if(err < 0) + err = errno; else if(!WIFEXITED(status) || (WEXITSTATUS(status) != 0)){ printk("'%s' didn't exit with status 0\n", argv[0]); - err = EINVAL; + err = -EINVAL; } } return(err); @@ -118,15 +118,17 @@ char gate_buf[sizeof("nnn.nnn.nnn.nnn\0")]; char *argv[] = { "uml_net", version_buf, "slip", "up", gate_buf, NULL }; - int sfd, mfd, disc, sencap, err; + int sfd, mfd, err; - if((mfd = get_pty()) < 0){ - printk("umn : Failed to open pty\n"); - return(-1); - } - if((sfd = os_open_file(ptsname(mfd), of_rdwr(OPENFLAGS()), 0)) < 0){ - printk("Couldn't open tty for slip line\n"); - return(-1); + mfd = get_pty(); + if(mfd < 0){ + printk("umn : Failed to open pty, err = %d\n", -mfd); + return(mfd); + } + sfd = os_open_file(ptsname(mfd), of_rdwr(OPENFLAGS()), 0); + if(sfd < 0){ + printk("Couldn't open tty for slip line, err = %d\n", -sfd); + return(sfd); } if(set_up_tty(sfd)) return(-1); pri->slave = sfd; @@ -138,28 +140,23 @@ err = slip_tramp(argv, sfd); - if(err != 0){ - printk("slip_tramp failed - errno = %d\n", err); - return(-err); - } - if(ioctl(pri->slave, SIOCGIFNAME, pri->name) < 0){ - printk("SIOCGIFNAME failed, errno = %d\n", errno); - return(-errno); + if(err < 0){ + printk("slip_tramp failed - err = %d\n", -err); + return(err); + } + err = os_get_ifname(pri->slave, pri->name); + if(err < 0){ + printk("get_ifname failed, err = %d\n", -err); + return(err); } iter_addresses(pri->dev, open_addr, pri->name); } else { - disc = N_SLIP; - if(ioctl(sfd, TIOCSETD, &disc) < 0){ - printk("Failed to set slip line discipline - " - "errno = %d\n", errno); - return(-errno); - } - sencap = 0; - if(ioctl(sfd, SIOCSIFENCAP, &sencap) < 0){ - printk("Failed to set slip encapsulation - " - "errno = %d\n", errno); - return(-errno); + err = os_set_slip(sfd); + if(err < 0){ + printk("Failed to set slip discipline encapsulation - " + "err = %d\n", -err); + return(err); } } return(mfd); @@ -181,9 +178,9 @@ err = slip_tramp(argv, -1); if(err != 0) - printk("slip_tramp failed - errno = %d\n", err); - close(fd); - close(pri->slave); + printk("slip_tramp failed - errno = %d\n", -err); + os_close_file(fd); + os_close_file(pri->slave); pri->slave = -1; } @@ -243,7 +240,7 @@ { struct slip_data *pri = data; - if(pri->slave == -1) return; + if(pri->slave < 0) return; open_addr(addr, netmask, pri->name); } @@ -252,7 +249,7 @@ { struct slip_data *pri = data; - if(pri->slave == -1) return; + if(pri->slave < 0) return; close_addr(addr, netmask, pri->name); } diff -Nru a/arch/um/drivers/slirp_user.c b/arch/um/drivers/slirp_user.c --- a/arch/um/drivers/slirp_user.c 2004-08-25 22:01:55 -07:00 +++ b/arch/um/drivers/slirp_user.c 2004-08-25 22:01:55 -07:00 @@ -4,8 +4,7 @@ #include #include #include -#include -#include +#include #include #include #include "user_util.h" @@ -48,15 +47,15 @@ return(pid); } - + +/* XXX This is just a trivial wrapper around os_pipe */ static int slirp_datachan(int *mfd, int *sfd) { int fds[2], err; err = os_pipe(fds, 1, 1); - if(err){ - printk("slirp_datachan: Failed to open pipe, errno = %d\n", - -err); + if(err < 0){ + printk("slirp_datachan: Failed to open pipe, err = %d\n", -err); return(err); } @@ -77,7 +76,7 @@ pid = slirp_tramp(pri->argw.argv, sfd); if(pid < 0){ - printk("slirp_tramp failed - errno = %d\n", pid); + printk("slirp_tramp failed - errno = %d\n", -pid); os_close_file(sfd); os_close_file(mfd); return(pid); @@ -97,8 +96,8 @@ struct slirp_data *pri = data; int status,err; - close(fd); - close(pri->slave); + os_close_file(fd); + os_close_file(pri->slave); pri->slave = -1; @@ -114,13 +113,13 @@ } #endif - err = waitpid(pri->pid, &status, WNOHANG); - if(err<0) { + CATCH_EINTR(err = waitpid(pri->pid, &status, WNOHANG)); + if(err < 0) { printk("slirp_close: waitpid returned %d\n", errno); return; } - if(err==0) { + if(err == 0) { printk("slirp_close: process %d has not exited\n"); return; } diff -Nru a/arch/um/drivers/ssl.c b/arch/um/drivers/ssl.c --- a/arch/um/drivers/ssl.c 2004-08-25 22:01:55 -07:00 +++ b/arch/um/drivers/ssl.c 2004-08-25 22:01:55 -07:00 @@ -10,6 +10,7 @@ #include "linux/major.h" #include "linux/mm.h" #include "linux/init.h" +#include "linux/console.h" #include "asm/termbits.h" #include "asm/irq.h" #include "line.h" @@ -53,8 +54,9 @@ static struct line_driver driver = { .name = "UML serial line", - .devfs_name = "tts/%d", - .major = TTYAUX_MAJOR, + .device_name = "ttS", + .devfs_name = "tts/", + .major = TTY_MAJOR, .minor_start = 64, .type = TTY_DRIVER_TYPE_SERIAL, .subtype = 0, @@ -149,6 +151,9 @@ case TCSETSW: case TCGETA: case TIOCMGET: + case TCSBRK: + case TCSBRKP: + case TIOCMSET: ret = -ENOIOCTLCMD; break; default: @@ -212,6 +217,37 @@ */ static int ssl_init_done = 0; +static void ssl_console_write(struct console *c, const char *string, + unsigned len) +{ + struct line *line = &serial_lines[c->index]; + if(ssl_init_done) + down(&line->sem); + console_write_chan(&line->chan_list, string, len); + if(ssl_init_done) + up(&line->sem); +} + +static struct tty_driver *ssl_console_device(struct console *c, int *index) +{ + *index = c->index; + return ssl_driver; +} + +static int ssl_console_setup(struct console *co, char *options) +{ + return(0); +} + +static struct console ssl_cons = { + name: "ttyS", + write: ssl_console_write, + device: ssl_console_device, + setup: ssl_console_setup, + flags: CON_PRINTBUFFER, + index: -1, +}; + int ssl_init(void) { char *new_title; @@ -227,17 +263,18 @@ new_title = add_xterm_umid(opts.xterm_title); if(new_title != NULL) opts.xterm_title = new_title; + register_console(&ssl_cons); ssl_init_done = 1; return(0); } -__initcall(ssl_init); +late_initcall(ssl_init); static int ssl_chan_setup(char *str) { - line_setup(serial_lines, sizeof(serial_lines)/sizeof(serial_lines[0]), - str, 1); - return(1); + return(line_setup(serial_lines, + sizeof(serial_lines)/sizeof(serial_lines[0]), + str, 1)); } __setup("ssl", ssl_chan_setup); diff -Nru a/arch/um/drivers/stdio_console.c b/arch/um/drivers/stdio_console.c --- a/arch/um/drivers/stdio_console.c 2004-08-25 22:01:54 -07:00 +++ b/arch/um/drivers/stdio_console.c 2004-08-25 22:01:54 -07:00 @@ -83,7 +83,8 @@ static struct line_driver driver = { .name = "UML console", - .devfs_name = "vc/%d", + .device_name = "tty", + .devfs_name = "vc/", .major = TTY_MAJOR, .minor_start = 0, .type = TTY_DRIVER_TYPE_CONSOLE, @@ -159,6 +160,15 @@ static int con_init_done = 0; +static struct tty_operations console_ops = { + .open = con_open, + .close = con_close, + .write = con_write, + .chars_in_buffer = chars_in_buffer, + .set_termios = set_termios, + .write_room = line_write_room, +}; + int stdio_init(void) { char *new_title; @@ -166,7 +176,8 @@ printk(KERN_INFO "Initializing stdio console driver\n"); console_driver = line_register_devfs(&console_lines, &driver, - &console_ops, vts, sizeof(vts)/sizeof(vts[0])); + &console_ops, vts, + sizeof(vts)/sizeof(vts[0])); lines_init(vts, sizeof(vts)/sizeof(vts[0])); @@ -178,26 +189,21 @@ return(0); } -__initcall(stdio_init); +late_initcall(stdio_init); static void console_write(struct console *console, const char *string, unsigned len) { - if(con_init_done) down(&vts[console->index].sem); - console_write_chan(&vts[console->index].chan_list, string, len); - if(con_init_done) up(&vts[console->index].sem); -} + struct line *line = &vts[console->index]; -static struct tty_operations console_ops = { - .open = con_open, - .close = con_close, - .write = con_write, - .chars_in_buffer = chars_in_buffer, - .set_termios = set_termios, - .write_room = line_write_room, -}; + if(con_init_done) + down(&line->sem); + console_write_chan(&line->chan_list, string, len); + if(con_init_done) + up(&line->sem); +} -static struct tty_driver *console_device(struct console *c, int *index) +static struct tty_driver *um_console_device(struct console *c, int *index) { *index = c->index; return console_driver; @@ -208,22 +214,28 @@ return(0); } -static struct console stdiocons = INIT_CONSOLE("tty", console_write, - console_device, console_setup, - CON_PRINTBUFFER); +static struct console stdiocons = { + name: "tty", + write: console_write, + device: um_console_device, + setup: console_setup, + flags: CON_PRINTBUFFER, + index: -1, +}; -static void __init stdio_console_init(void) +static int __init stdio_console_init(void) { INIT_LIST_HEAD(&vts[0].chan_list); list_add(&init_console_chan.list, &vts[0].chan_list); register_console(&stdiocons); + return(0); } + console_initcall(stdio_console_init); static int console_chan_setup(char *str) { - line_setup(vts, sizeof(vts)/sizeof(vts[0]), str, 1); - return(1); + return(line_setup(vts, sizeof(vts)/sizeof(vts[0]), str, 1)); } __setup("con", console_chan_setup); diff -Nru a/arch/um/drivers/tty.c b/arch/um/drivers/tty.c --- a/arch/um/drivers/tty.c 2004-08-25 22:01:55 -07:00 +++ b/arch/um/drivers/tty.c 2004-08-25 22:01:55 -07:00 @@ -5,7 +5,6 @@ #include #include -#include #include #include #include "chan_user.h" @@ -30,7 +29,8 @@ } str++; - if((data = um_kmalloc(sizeof(*data))) == NULL) + data = um_kmalloc(sizeof(*data)); + if(data == NULL) return(NULL); *data = ((struct tty_chan) { .dev = str, .raw = opts->raw }); diff -Nru a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c --- a/arch/um/drivers/ubd_kern.c 2004-08-25 22:01:55 -07:00 +++ b/arch/um/drivers/ubd_kern.c 2004-08-25 22:01:55 -07:00 @@ -8,6 +8,13 @@ * old style ubd by setting UBD_SHIFT to 0 * 2002-09-27...2002-10-18 massive tinkering for 2.5 * partitions have changed in 2.5 + * 2003-01-29 more tinkering for 2.5.59-1 + * This should now address the sysfs problems and has + * the symlink for devfs to allow for booting with + * the common /dev/ubd/discX/... names rather than + * only /dev/ubdN/discN this version also has lots of + * clean ups preparing for ubd-many. + * James McMechan */ #define MAJOR_NR UBD_MAJOR @@ -40,9 +47,12 @@ #include "mconsole_kern.h" #include "init.h" #include "irq_user.h" +#include "irq_kern.h" #include "ubd_user.h" #include "2_5compat.h" #include "os.h" +#include "mem.h" +#include "mem_kern.h" static spinlock_t ubd_io_lock = SPIN_LOCK_UNLOCKED; static spinlock_t ubd_lock = SPIN_LOCK_UNLOCKED; @@ -56,6 +66,10 @@ #define MAX_DEV (8) +/* Changed in early boot */ +static int ubd_do_mmap = 0; +#define UBD_MMAP_BLOCK_SIZE PAGE_SIZE + static struct block_device_operations ubd_blops = { .owner = THIS_MODULE, .open = ubd_open, @@ -67,7 +81,7 @@ static request_queue_t *ubd_queue; /* Protected by ubd_lock */ -static int fake_major = 0; +static int fake_major = MAJOR_NR; static struct gendisk *ubd_gendisk[MAX_DEV]; static struct gendisk *fake_gendisk[MAX_DEV]; @@ -96,13 +110,19 @@ struct ubd { char *file; - int is_dir; int count; int fd; __u64 size; struct openflags boot_openflags; struct openflags openflags; + int no_cow; struct cow cow; + + int map_writes; + int map_reads; + int nomap_writes; + int nomap_reads; + int write_maps; }; #define DEFAULT_COW { \ @@ -115,21 +135,28 @@ #define DEFAULT_UBD { \ .file = NULL, \ - .is_dir = 0, \ .count = 0, \ .fd = -1, \ .size = -1, \ .boot_openflags = OPEN_FLAGS, \ .openflags = OPEN_FLAGS, \ + .no_cow = 0, \ .cow = DEFAULT_COW, \ + .map_writes = 0, \ + .map_reads = 0, \ + .nomap_writes = 0, \ + .nomap_reads = 0, \ + .write_maps = 0, \ } struct ubd ubd_dev[MAX_DEV] = { [ 0 ... MAX_DEV - 1 ] = DEFAULT_UBD }; static int ubd0_init(void) { - if(ubd_dev[0].file == NULL) - ubd_dev[0].file = "root_fs"; + struct ubd *dev = &ubd_dev[0]; + + if(dev->file == NULL) + dev->file = "root_fs"; return(0); } @@ -196,19 +223,46 @@ " Create ide0 entries that map onto ubd devices.\n\n" ); +static int parse_unit(char **ptr) +{ + char *str = *ptr, *end; + int n = -1; + + if(isdigit(*str)) { + n = simple_strtoul(str, &end, 0); + if(end == str) + return(-1); + *ptr = end; + } + else if (('a' <= *str) && (*str <= 'h')) { + n = *str - 'a'; + str++; + *ptr = str; + } + return(n); +} + static int ubd_setup_common(char *str, int *index_out) { + struct ubd *dev; struct openflags flags = global_openflags; char *backing_file; int n, err; if(index_out) *index_out = -1; - n = *str++; + n = *str; if(n == '='){ - static int fake_major_allowed = 1; char *end; int major; + str++; + if(!strcmp(str, "mmap")){ + CHOOSE_MODE(printk("mmap not supported by the ubd " + "driver in tt mode\n"), + ubd_do_mmap = 1); + return(0); + } + if(!strcmp(str, "sync")){ global_openflags.s = 1; return(0); @@ -220,20 +274,14 @@ return(1); } - if(!fake_major_allowed){ - printk(KERN_ERR "Can't assign a fake major twice\n"); - return(1); - } - err = 1; spin_lock(&ubd_lock); - if(!fake_major_allowed){ + if(fake_major != MAJOR_NR){ printk(KERN_ERR "Can't assign a fake major twice\n"); goto out1; } fake_major = major; - fake_major_allowed = 0; printk(KERN_INFO "Setting extra ubd major number to %d\n", major); @@ -243,25 +291,23 @@ return(err); } - if(n < '0'){ - printk(KERN_ERR "ubd_setup : index out of range\n"); } - - if((n >= '0') && (n <= '9')) n -= '0'; - else if((n >= 'a') && (n <= 'z')) n -= 'a'; - else { - printk(KERN_ERR "ubd_setup : device syntax invalid\n"); + n = parse_unit(&str); + if(n < 0){ + printk(KERN_ERR "ubd_setup : couldn't parse unit number " + "'%s'\n", str); return(1); } if(n >= MAX_DEV){ - printk(KERN_ERR "ubd_setup : index out of range " - "(%d devices)\n", MAX_DEV); + printk(KERN_ERR "ubd_setup : index %d out of range " + "(%d devices)\n", n, MAX_DEV); return(1); } err = 1; spin_lock(&ubd_lock); - if(ubd_dev[n].file != NULL){ + dev = &ubd_dev[n]; + if(dev->file != NULL){ printk(KERN_ERR "ubd_setup : device already configured\n"); goto out2; } @@ -276,6 +322,11 @@ flags.s = 1; str++; } + if (*str == 'd'){ + dev->no_cow = 1; + str++; + } + if(*str++ != '='){ printk(KERN_ERR "ubd_setup : Expected '='\n"); goto out2; @@ -284,14 +335,17 @@ err = 0; backing_file = strchr(str, ','); if(backing_file){ - *backing_file = '\0'; - backing_file++; + if(dev->no_cow) + printk(KERN_ERR "Can't specify both 'd' and a " + "cow file\n"); + else { + *backing_file = '\0'; + backing_file++; + } } - ubd_dev[n].file = str; - if(ubd_is_dir(ubd_dev[n].file)) - ubd_dev[n].is_dir = 1; - ubd_dev[n].cow.file = backing_file; - ubd_dev[n].boot_openflags = flags; + dev->file = str; + dev->cow.file = backing_file; + dev->boot_openflags = flags; out2: spin_unlock(&ubd_lock); return(err); @@ -321,8 +375,7 @@ static int fakehd_set = 0; static int fakehd(char *str) { - printk(KERN_INFO - "fakehd : Changing ubd name to \"hd\".\n"); + printk(KERN_INFO "fakehd : Changing ubd name to \"hd\".\n"); fakehd_set = 1; return 1; } @@ -368,32 +421,42 @@ { struct io_thread_req req; struct request *rq = elv_next_request(ubd_queue); - int n; + int n, err; do_ubd = NULL; intr_count++; n = read_ubd_fs(thread_fd, &req, sizeof(req)); if(n != sizeof(req)){ printk(KERN_ERR "Pid %d - spurious interrupt in ubd_handler, " - "errno = %d\n", os_getpid(), -n); + "err = %d\n", os_getpid(), -n); spin_lock(&ubd_io_lock); end_request(rq, 0); spin_unlock(&ubd_io_lock); return; } - if((req.offset != ((__u64) (rq->sector)) << 9) || - (req.length != (rq->current_nr_sectors) << 9)) + if((req.op != UBD_MMAP) && + ((req.offset != ((__u64) (rq->sector)) << 9) || + (req.length != (rq->current_nr_sectors) << 9))) panic("I/O op mismatch"); + if(req.map_fd != -1){ + err = physmem_subst_mapping(req.buffer, req.map_fd, + req.map_offset, 1); + if(err) + printk("ubd_handler - physmem_subst_mapping failed, " + "err = %d\n", -err); + } + ubd_finish(rq, req.error); reactivate_fd(thread_fd, UBD_IRQ); do_ubd_request(ubd_queue); } -static void ubd_intr(int irq, void *dev, struct pt_regs *unused) +static irqreturn_t ubd_intr(int irq, void *dev, struct pt_regs *unused) { ubd_handler(); + return(IRQ_HANDLED); } /* Only changed by ubd_init, which is an initcall. */ @@ -417,10 +480,14 @@ static void ubd_close(struct ubd *dev) { + if(ubd_do_mmap) + physmem_forget_descriptor(dev->fd); os_close_file(dev->fd); if(dev->cow.file == NULL) return; + if(ubd_do_mmap) + physmem_forget_descriptor(dev->cow.fd); os_close_file(dev->cow.fd); vfree(dev->cow.bitmap); dev->cow.bitmap = NULL; @@ -429,18 +496,20 @@ static int ubd_open_dev(struct ubd *dev) { struct openflags flags; - int err, n, create_cow, *create_ptr; + char **back_ptr; + int err, create_cow, *create_ptr; + dev->openflags = dev->boot_openflags; create_cow = 0; create_ptr = (dev->cow.file != NULL) ? &create_cow : NULL; - dev->fd = open_ubd_file(dev->file, &dev->openflags, &dev->cow.file, + back_ptr = dev->no_cow ? NULL : &dev->cow.file; + dev->fd = open_ubd_file(dev->file, &dev->openflags, back_ptr, &dev->cow.bitmap_offset, &dev->cow.bitmap_len, &dev->cow.data_offset, create_ptr); if((dev->fd == -ENOENT) && create_cow){ - n = dev - ubd_dev; dev->fd = create_cow_file(dev->file, dev->cow.file, - dev->openflags, 1 << 9, + dev->openflags, 1 << 9, PAGE_SIZE, &dev->cow.bitmap_offset, &dev->cow.bitmap_len, &dev->cow.data_offset); @@ -455,13 +524,17 @@ if(dev->cow.file != NULL){ err = -ENOMEM; dev->cow.bitmap = (void *) vmalloc(dev->cow.bitmap_len); - if(dev->cow.bitmap == NULL) goto error; + if(dev->cow.bitmap == NULL){ + printk(KERN_ERR "Failed to vmalloc COW bitmap\n"); + goto error; + } flush_tlb_kernel_vm(); err = read_cow_bitmap(dev->fd, dev->cow.bitmap, dev->cow.bitmap_offset, dev->cow.bitmap_len); - if(err) goto error; + if(err < 0) + goto error; flags = dev->openflags; flags.w = 0; @@ -481,17 +554,31 @@ { struct gendisk *disk; + char from[sizeof("ubd/nnnnn\0")], to[sizeof("discnnnnn/disc\0")]; + int err; disk = alloc_disk(1 << UBD_SHIFT); - if (!disk) - return -ENOMEM; + if(disk == NULL) + return(-ENOMEM); disk->major = major; disk->first_minor = unit << UBD_SHIFT; disk->fops = &ubd_blops; set_capacity(disk, size / 512); - sprintf(disk->disk_name, "ubd"); - sprintf(disk->devfs_name, "ubd/disc%d", unit); + if(major == MAJOR_NR){ + sprintf(disk->disk_name, "ubd%c", 'a' + unit); + sprintf(disk->devfs_name, "ubd/disc%d", unit); + sprintf(from, "ubd/%d", unit); + sprintf(to, "disc%d/disc", unit); + err = devfs_mk_symlink(from, to); + if(err) + printk("ubd_new_disk failed to make link from %s to " + "%s, error = %d\n", from, to, err); + } + else { + sprintf(disk->disk_name, "ubd_fake%d", unit); + sprintf(disk->devfs_name, "ubd_fake/disc%d", unit); + } disk->private_data = &ubd_dev[unit]; disk->queue = ubd_queue; @@ -506,24 +593,21 @@ struct ubd *dev = &ubd_dev[n]; int err; - if(dev->is_dir) - return(-EISDIR); - - if (!dev->file) + if(dev->file == NULL) return(-ENODEV); if (ubd_open_dev(dev)) return(-ENODEV); err = ubd_file_size(dev, &dev->size); - if(err) + if(err < 0) return(err); err = ubd_new_disk(MAJOR_NR, dev->size, n, &ubd_gendisk[n]); if(err) return(err); - if(fake_major) + if(fake_major != MAJOR_NR) ubd_new_disk(fake_major, dev->size, n, &fake_gendisk[n]); @@ -561,42 +645,42 @@ return(err); } -static int ubd_get_config(char *dev, char *str, int size, char **error_out) +static int ubd_get_config(char *name, char *str, int size, char **error_out) { - struct ubd *ubd; + struct ubd *dev; char *end; - int major, n = 0; + int n, len = 0; - major = simple_strtoul(dev, &end, 0); - if((*end != '\0') || (end == dev)){ - *error_out = "ubd_get_config : didn't parse major number"; + n = simple_strtoul(name, &end, 0); + if((*end != '\0') || (end == name)){ + *error_out = "ubd_get_config : didn't parse device number"; return(-1); } - if((major >= MAX_DEV) || (major < 0)){ - *error_out = "ubd_get_config : major number out of range"; + if((n >= MAX_DEV) || (n < 0)){ + *error_out = "ubd_get_config : device number out of range"; return(-1); } - ubd = &ubd_dev[major]; + dev = &ubd_dev[n]; spin_lock(&ubd_lock); - if(ubd->file == NULL){ - CONFIG_CHUNK(str, size, n, "", 1); + if(dev->file == NULL){ + CONFIG_CHUNK(str, size, len, "", 1); goto out; } - CONFIG_CHUNK(str, size, n, ubd->file, 0); + CONFIG_CHUNK(str, size, len, dev->file, 0); - if(ubd->cow.file != NULL){ - CONFIG_CHUNK(str, size, n, ",", 0); - CONFIG_CHUNK(str, size, n, ubd->cow.file, 1); + if(dev->cow.file != NULL){ + CONFIG_CHUNK(str, size, len, ",", 0); + CONFIG_CHUNK(str, size, len, dev->cow.file, 1); } - else CONFIG_CHUNK(str, size, n, "", 1); + else CONFIG_CHUNK(str, size, len, "", 1); out: spin_unlock(&ubd_lock); - return(n); + return(len); } static int ubd_remove(char *str) @@ -604,11 +688,9 @@ struct ubd *dev; int n, err = -ENODEV; - if(!isdigit(*str)) - return(err); /* it should be a number 0-7/a-h */ + n = parse_unit(&str); - n = *str - '0'; - if(n >= MAX_DEV) + if((n < 0) || (n >= MAX_DEV)) return(err); dev = &ubd_dev[n]; @@ -669,7 +751,7 @@ elevator_init(ubd_queue, &elevator_noop); - if (fake_major != 0) { + if (fake_major != MAJOR_NR) { char name[sizeof("ubd_nnn\0")]; snprintf(name, sizeof(name), "ubd_%d", fake_major); @@ -696,6 +778,7 @@ io_pid = start_io_thread(stack + PAGE_SIZE - sizeof(void *), &thread_fd); if(io_pid < 0){ + io_pid = -1; printk(KERN_ERR "ubd : Failed to start I/O thread (errno = %d) - " "falling back to synchronous I/O\n", -io_pid); @@ -703,8 +786,8 @@ } err = um_request_irq(UBD_IRQ, thread_fd, IRQ_READ, ubd_intr, SA_INTERRUPT, "ubd", ubd_dev); - if(err != 0) printk(KERN_ERR - "um_request_irq failed - errno = %d\n", -err); + if(err != 0) + printk(KERN_ERR "um_request_irq failed - errno = %d\n", -err); return(err); } @@ -714,15 +797,9 @@ { struct gendisk *disk = inode->i_bdev->bd_disk; struct ubd *dev = disk->private_data; - int err = -EISDIR; + int err = 0; - if(dev->is_dir == 1) - goto out; - - err = 0; if(dev->count == 0){ - dev->openflags = dev->boot_openflags; - err = ubd_open_dev(dev); if(err){ printk(KERN_ERR "%s: Can't open \"%s\": errno = %d\n", @@ -749,62 +826,156 @@ return(0); } -void cowify_req(struct io_thread_req *req, struct ubd *dev) +static void cowify_bitmap(__u64 io_offset, int length, unsigned long *cow_mask, + __u64 *cow_offset, unsigned long *bitmap, + __u64 bitmap_offset, unsigned long *bitmap_words, + __u64 bitmap_len) +{ + __u64 sector = io_offset >> 9; + int i, update_bitmap = 0; + + for(i = 0; i < length >> 9; i++){ + if(cow_mask != NULL) + ubd_set_bit(i, (unsigned char *) cow_mask); + if(ubd_test_bit(sector + i, (unsigned char *) bitmap)) + continue; + + update_bitmap = 1; + ubd_set_bit(sector + i, (unsigned char *) bitmap); + } + + if(!update_bitmap) + return; + + *cow_offset = sector / (sizeof(unsigned long) * 8); + + /* This takes care of the case where we're exactly at the end of the + * device, and *cow_offset + 1 is off the end. So, just back it up + * by one word. Thanks to Lynn Kerby for the fix and James McMechan + * for the original diagnosis. + */ + if(*cow_offset == ((bitmap_len + sizeof(unsigned long) - 1) / + sizeof(unsigned long) - 1)) + (*cow_offset)--; + + bitmap_words[0] = bitmap[*cow_offset]; + bitmap_words[1] = bitmap[*cow_offset + 1]; + + *cow_offset *= sizeof(unsigned long); + *cow_offset += bitmap_offset; +} + +static void cowify_req(struct io_thread_req *req, unsigned long *bitmap, + __u64 bitmap_offset, __u64 bitmap_len) { - int i, update_bitmap, sector = req->offset >> 9; + __u64 sector = req->offset >> 9; + int i; if(req->length > (sizeof(req->sector_mask) * 8) << 9) panic("Operation too long"); + if(req->op == UBD_READ) { for(i = 0; i < req->length >> 9; i++){ - if(ubd_test_bit(sector + i, (unsigned char *) - dev->cow.bitmap)){ + if(ubd_test_bit(sector + i, (unsigned char *) bitmap)) ubd_set_bit(i, (unsigned char *) &req->sector_mask); - } } - } - else { - update_bitmap = 0; - for(i = 0; i < req->length >> 9; i++){ - ubd_set_bit(i, (unsigned char *) - &req->sector_mask); - if(!ubd_test_bit(sector + i, (unsigned char *) - dev->cow.bitmap)) - update_bitmap = 1; - ubd_set_bit(sector + i, (unsigned char *) - dev->cow.bitmap); - } - if(update_bitmap){ - req->cow_offset = sector / (sizeof(unsigned long) * 8); - req->bitmap_words[0] = - dev->cow.bitmap[req->cow_offset]; - req->bitmap_words[1] = - dev->cow.bitmap[req->cow_offset + 1]; - req->cow_offset *= sizeof(unsigned long); - req->cow_offset += dev->cow.bitmap_offset; + } + else cowify_bitmap(req->offset, req->length, &req->sector_mask, + &req->cow_offset, bitmap, bitmap_offset, + req->bitmap_words, bitmap_len); +} + +static int mmap_fd(struct request *req, struct ubd *dev, __u64 offset) +{ + __u64 sector; + unsigned char *bitmap; + int bit, i; + + /* mmap must have been requested on the command line */ + if(!ubd_do_mmap) + return(-1); + + /* The buffer must be page aligned */ + if(((unsigned long) req->buffer % UBD_MMAP_BLOCK_SIZE) != 0) + return(-1); + + /* The request must be a page long */ + if((req->current_nr_sectors << 9) != PAGE_SIZE) + return(-1); + + if(dev->cow.file == NULL) + return(dev->fd); + + sector = offset >> 9; + bitmap = (unsigned char *) dev->cow.bitmap; + bit = ubd_test_bit(sector, bitmap); + + for(i = 1; i < req->current_nr_sectors; i++){ + if(ubd_test_bit(sector + i, bitmap) != bit) + return(-1); + } + + if(bit || (rq_data_dir(req) == WRITE)) + offset += dev->cow.data_offset; + + /* The data on disk must be page aligned */ + if((offset % UBD_MMAP_BLOCK_SIZE) != 0) + return(-1); + + return(bit ? dev->fd : dev->cow.fd); +} + +static int prepare_mmap_request(struct ubd *dev, int fd, __u64 offset, + struct request *req, + struct io_thread_req *io_req) +{ + int err; + + if(rq_data_dir(req) == WRITE){ + /* Writes are almost no-ops since the new data is already in the + * host page cache + */ + dev->map_writes++; + if(dev->cow.file != NULL) + cowify_bitmap(io_req->offset, io_req->length, + &io_req->sector_mask, &io_req->cow_offset, + dev->cow.bitmap, dev->cow.bitmap_offset, + io_req->bitmap_words, + dev->cow.bitmap_len); + } + else { + int w; + + if((dev->cow.file != NULL) && (fd == dev->cow.fd)) + w = 0; + else w = dev->openflags.w; + + if((dev->cow.file != NULL) && (fd == dev->fd)) + offset += dev->cow.data_offset; + + err = physmem_subst_mapping(req->buffer, fd, offset, w); + if(err){ + printk("physmem_subst_mapping failed, err = %d\n", + -err); + return(1); } + dev->map_reads++; } + io_req->op = UBD_MMAP; + io_req->buffer = req->buffer; + return(0); } static int prepare_request(struct request *req, struct io_thread_req *io_req) { struct gendisk *disk = req->rq_disk; struct ubd *dev = disk->private_data; - __u64 block; - int nsect; + __u64 offset; + int len, fd; if(req->rq_status == RQ_INACTIVE) return(1); - if(dev->is_dir){ - strcpy(req->buffer, "HOSTFS:"); - strcat(req->buffer, dev->file); - spin_lock(&ubd_io_lock); - end_request(req, 1); - spin_unlock(&ubd_io_lock); - return(1); - } - if((rq_data_dir(req) == WRITE) && !dev->openflags.w){ printk("Write attempted on readonly ubd device %s\n", disk->disk_name); @@ -814,23 +985,49 @@ return(1); } - block = req->sector; - nsect = req->current_nr_sectors; + offset = ((__u64) req->sector) << 9; + len = req->current_nr_sectors << 9; - io_req->op = rq_data_dir(req) == READ ? UBD_READ : UBD_WRITE; io_req->fds[0] = (dev->cow.file != NULL) ? dev->cow.fd : dev->fd; io_req->fds[1] = dev->fd; + io_req->map_fd = -1; + io_req->cow_offset = -1; + io_req->offset = offset; + io_req->length = len; + io_req->error = 0; + io_req->sector_mask = 0; + + fd = mmap_fd(req, dev, io_req->offset); + if(fd > 0){ + /* If mmapping is otherwise OK, but the first access to the + * page is a write, then it's not mapped in yet. So we have + * to write the data to disk first, then we can map the disk + * page in and continue normally from there. + */ + if((rq_data_dir(req) == WRITE) && !is_remapped(req->buffer)){ + io_req->map_fd = dev->fd; + io_req->map_offset = io_req->offset + + dev->cow.data_offset; + dev->write_maps++; + } + else return(prepare_mmap_request(dev, fd, io_req->offset, req, + io_req)); + } + + if(rq_data_dir(req) == READ) + dev->nomap_reads++; + else dev->nomap_writes++; + + io_req->op = (rq_data_dir(req) == READ) ? UBD_READ : UBD_WRITE; io_req->offsets[0] = 0; io_req->offsets[1] = dev->cow.data_offset; - io_req->offset = ((__u64) block) << 9; - io_req->length = nsect << 9; io_req->buffer = req->buffer; io_req->sectorsize = 1 << 9; - io_req->sector_mask = 0; - io_req->cow_offset = -1; - io_req->error = 0; - if(dev->cow.file != NULL) cowify_req(io_req, dev); + if(dev->cow.file != NULL) + cowify_req(io_req, dev->cow.bitmap, dev->cow.bitmap_offset, + dev->cow.bitmap_len); + return(0); } @@ -841,7 +1038,7 @@ int err, n; if(thread_fd == -1){ - while(!list_empty(&q->queue_head)){ + while(!elv_queue_empty(q)){ req = elv_next_request(q); err = prepare_request(req, &io_req); if(!err){ @@ -851,7 +1048,8 @@ } } else { - if(do_ubd || list_empty(&q->queue_head)) return; + if(do_ubd || elv_queue_empty(q)) + return; req = elv_next_request(q); err = prepare_request(req, &io_req); if(!err){ @@ -885,7 +1083,7 @@ g.heads = 128; g.sectors = 32; g.cylinders = dev->size / (128 * 32 * 512); - g.start = 2; + g.start = get_start_sect(inode->i_bdev); return(copy_to_user(loc, &g, sizeof(g)) ? -EFAULT : 0); case HDIO_SET_UNMASKINTR: @@ -934,6 +1132,142 @@ } return(-EINVAL); } + +static int ubd_check_remapped(int fd, unsigned long address, int is_write, + __u64 offset) +{ + __u64 bitmap_offset; + unsigned long new_bitmap[2]; + int i, err, n; + + /* If it's not a write access, we can't do anything about it */ + if(!is_write) + return(0); + + /* We have a write */ + for(i = 0; i < sizeof(ubd_dev) / sizeof(ubd_dev[0]); i++){ + struct ubd *dev = &ubd_dev[i]; + + if((dev->fd != fd) && (dev->cow.fd != fd)) + continue; + + /* It's a write to a ubd device */ + + if(!dev->openflags.w){ + /* It's a write access on a read-only device - probably + * shouldn't happen. If the kernel is trying to change + * something with no intention of writing it back out, + * then this message will clue us in that this needs + * fixing + */ + printk("Write access to mapped page from readonly ubd " + "device %d\n", i); + return(0); + } + + /* It's a write to a writeable ubd device - it must be COWed + * because, otherwise, the page would have been mapped in + * writeable + */ + + if(!dev->cow.file) + panic("Write fault on writeable non-COW ubd device %d", + i); + + /* It should also be an access to the backing file since the + * COW pages should be mapped in read-write + */ + + if(fd == dev->fd) + panic("Write fault on a backing page of ubd " + "device %d\n", i); + + /* So, we do the write, copying the backing data to the COW + * file... + */ + + err = os_seek_file(dev->fd, offset + dev->cow.data_offset); + if(err < 0) + panic("Couldn't seek to %lld in COW file of ubd " + "device %d, err = %d", + offset + dev->cow.data_offset, i, -err); + + n = os_write_file(dev->fd, (void *) address, PAGE_SIZE); + if(n != PAGE_SIZE) + panic("Couldn't copy data to COW file of ubd " + "device %d, err = %d", i, -n); + + /* ... updating the COW bitmap... */ + + cowify_bitmap(offset, PAGE_SIZE, NULL, &bitmap_offset, + dev->cow.bitmap, dev->cow.bitmap_offset, + new_bitmap, dev->cow.bitmap_len); + + err = os_seek_file(dev->fd, bitmap_offset); + if(err < 0) + panic("Couldn't seek to %lld in COW file of ubd " + "device %d, err = %d", bitmap_offset, i, -err); + + n = os_write_file(dev->fd, new_bitmap, sizeof(new_bitmap)); + if(n != sizeof(new_bitmap)) + panic("Couldn't update bitmap of ubd device %d, " + "err = %d", i, -n); + + /* Maybe we can map the COW page in, and maybe we can't. If + * it is a pre-V3 COW file, we can't, since the alignment will + * be wrong. If it is a V3 or later COW file which has been + * moved to a system with a larger page size, then maybe we + * can't, depending on the exact location of the page. + */ + + offset += dev->cow.data_offset; + + /* Remove the remapping, putting the original anonymous page + * back. If the COW file can be mapped in, that is done. + * Otherwise, the COW page is read in. + */ + + if(!physmem_remove_mapping((void *) address)) + panic("Address 0x%lx not remapped by ubd device %d", + address, i); + if((offset % UBD_MMAP_BLOCK_SIZE) == 0) + physmem_subst_mapping((void *) address, dev->fd, + offset, 1); + else { + err = os_seek_file(dev->fd, offset); + if(err < 0) + panic("Couldn't seek to %lld in COW file of " + "ubd device %d, err = %d", offset, i, + -err); + + n = os_read_file(dev->fd, (void *) address, PAGE_SIZE); + if(n != PAGE_SIZE) + panic("Failed to read page from offset %llx of " + "COW file of ubd device %d, err = %d", + offset, i, -n); + } + + return(1); + } + + /* It's not a write on a ubd device */ + return(0); +} + +static struct remapper ubd_remapper = { + .list = LIST_HEAD_INIT(ubd_remapper.list), + .proc = ubd_check_remapped, +}; + +static int ubd_remapper_setup(void) +{ + if(ubd_do_mmap) + register_remapper(&ubd_remapper); + + return(0); +} + +__initcall(ubd_remapper_setup); /* * Overrides for Emacs so that we follow Linus's tabbing style. diff -Nru a/arch/um/drivers/ubd_user.c b/arch/um/drivers/ubd_user.c --- a/arch/um/drivers/ubd_user.c 2004-08-25 22:01:54 -07:00 +++ b/arch/um/drivers/ubd_user.c 2004-08-25 22:01:54 -07:00 @@ -11,11 +11,8 @@ #include #include #include -#include #include -#include #include -#include #include #include #include "asm/types.h" @@ -24,146 +21,30 @@ #include "user.h" #include "ubd_user.h" #include "os.h" +#include "cow.h" #include #include -#if __BYTE_ORDER == __BIG_ENDIAN -# define ntohll(x) (x) -# define htonll(x) (x) -#elif __BYTE_ORDER == __LITTLE_ENDIAN -# define ntohll(x) bswap_64(x) -# define htonll(x) bswap_64(x) -#else -#error "__BYTE_ORDER not defined" -#endif - -#define PATH_LEN_V1 256 - -struct cow_header_v1 { - int magic; - int version; - char backing_file[PATH_LEN_V1]; - time_t mtime; - __u64 size; - int sectorsize; -}; - -#define PATH_LEN_V2 MAXPATHLEN - -struct cow_header_v2 { - unsigned long magic; - unsigned long version; - char backing_file[PATH_LEN_V2]; - time_t mtime; - __u64 size; - int sectorsize; -}; - -union cow_header { - struct cow_header_v1 v1; - struct cow_header_v2 v2; -}; - -#define COW_MAGIC 0x4f4f4f4d /* MOOO */ -#define COW_VERSION 2 - -static void sizes(__u64 size, int sectorsize, int bitmap_offset, - unsigned long *bitmap_len_out, int *data_offset_out) -{ - *bitmap_len_out = (size + sectorsize - 1) / (8 * sectorsize); - - *data_offset_out = bitmap_offset + *bitmap_len_out; - *data_offset_out = (*data_offset_out + sectorsize - 1) / sectorsize; - *data_offset_out *= sectorsize; -} - -static int read_cow_header(int fd, int *magic_out, char **backing_file_out, - time_t *mtime_out, __u64 *size_out, - int *sectorsize_out, int *bitmap_offset_out) -{ - union cow_header *header; - char *file; - int err, n; - unsigned long version, magic; - - header = um_kmalloc(sizeof(*header)); - if(header == NULL){ - printk("read_cow_header - Failed to allocate header\n"); - return(-ENOMEM); - } - err = -EINVAL; - n = read(fd, header, sizeof(*header)); - if(n < offsetof(typeof(header->v1), backing_file)){ - printk("read_cow_header - short header\n"); - goto out; - } - - magic = header->v1.magic; - if(magic == COW_MAGIC) { - version = header->v1.version; - } - else if(magic == ntohl(COW_MAGIC)){ - version = ntohl(header->v1.version); - } - else goto out; - - *magic_out = COW_MAGIC; - - if(version == 1){ - if(n < sizeof(header->v1)){ - printk("read_cow_header - failed to read V1 header\n"); - goto out; - } - *mtime_out = header->v1.mtime; - *size_out = header->v1.size; - *sectorsize_out = header->v1.sectorsize; - *bitmap_offset_out = sizeof(header->v1); - file = header->v1.backing_file; - } - else if(version == 2){ - if(n < sizeof(header->v2)){ - printk("read_cow_header - failed to read V2 header\n"); - goto out; - } - *mtime_out = ntohl(header->v2.mtime); - *size_out = ntohll(header->v2.size); - *sectorsize_out = ntohl(header->v2.sectorsize); - *bitmap_offset_out = sizeof(header->v2); - file = header->v2.backing_file; - } - else { - printk("read_cow_header - invalid COW version\n"); - goto out; - } - err = -ENOMEM; - *backing_file_out = uml_strdup(file); - if(*backing_file_out == NULL){ - printk("read_cow_header - failed to allocate backing file\n"); - goto out; - } - err = 0; - out: - kfree(header); - return(err); -} static int same_backing_files(char *from_cmdline, char *from_cow, char *cow) { - struct stat buf1, buf2; + struct uml_stat buf1, buf2; + int err; if(from_cmdline == NULL) return(1); if(!strcmp(from_cmdline, from_cow)) return(1); - if(stat(from_cmdline, &buf1) < 0){ - printk("Couldn't stat '%s', errno = %d\n", from_cmdline, - errno); + err = os_stat_file(from_cmdline, &buf1); + if(err < 0){ + printk("Couldn't stat '%s', err = %d\n", from_cmdline, -err); return(1); } - if(stat(from_cow, &buf2) < 0){ - printk("Couldn't stat '%s', errno = %d\n", from_cow, errno); + err = os_stat_file(from_cow, &buf2); + if(err < 0){ + printk("Couldn't stat '%s', err = %d\n", from_cow, -err); return(1); } - if((buf1.st_dev == buf2.st_dev) && (buf1.st_ino == buf2.st_ino)) + if((buf1.ust_dev == buf2.ust_dev) && (buf1.ust_ino == buf2.ust_ino)) return(1); printk("Backing file mismatch - \"%s\" requested,\n" @@ -174,20 +55,21 @@ static int backing_file_mismatch(char *file, __u64 size, time_t mtime) { - struct stat64 buf; + unsigned long modtime; long long actual; int err; - if(stat64(file, &buf) < 0){ - printk("Failed to stat backing file \"%s\", errno = %d\n", - file, errno); - return(-errno); + err = os_file_modtime(file, &modtime); + if(err < 0){ + printk("Failed to get modification time of backing file " + "\"%s\", err = %d\n", file, -err); + return(err); } err = os_file_size(file, &actual); - if(err){ + if(err < 0){ printk("Failed to get size of backing file \"%s\", " - "errno = %d\n", file, -err); + "err = %d\n", file, -err); return(err); } @@ -196,9 +78,9 @@ "file\n", size, actual); return(-EINVAL); } - if(buf.st_mtime != mtime){ + if(modtime != mtime){ printk("mtime mismatch (%ld vs %ld) of COW header vs backing " - "file\n", mtime, buf.st_mtime); + "file\n", mtime, modtime); return(-EINVAL); } return(0); @@ -209,124 +91,16 @@ int err; err = os_seek_file(fd, offset); - if(err != 0) return(-errno); - err = read(fd, buf, len); - if(err < 0) return(-errno); - return(0); -} + if(err < 0) + return(err); -static int absolutize(char *to, int size, char *from) -{ - char save_cwd[256], *slash; - int remaining; + err = os_read_file(fd, buf, len); + if(err < 0) + return(err); - if(getcwd(save_cwd, sizeof(save_cwd)) == NULL) { - printk("absolutize : unable to get cwd - errno = %d\n", errno); - return(-1); - } - slash = strrchr(from, '/'); - if(slash != NULL){ - *slash = '\0'; - if(chdir(from)){ - *slash = '/'; - printk("absolutize : Can't cd to '%s' - errno = %d\n", - from, errno); - return(-1); - } - *slash = '/'; - if(getcwd(to, size) == NULL){ - printk("absolutize : unable to get cwd of '%s' - " - "errno = %d\n", from, errno); - return(-1); - } - remaining = size - strlen(to); - if(strlen(slash) + 1 > remaining){ - printk("absolutize : unable to fit '%s' into %d " - "chars\n", from, size); - return(-1); - } - strcat(to, slash); - } - else { - if(strlen(save_cwd) + 1 + strlen(from) + 1 > size){ - printk("absolutize : unable to fit '%s' into %d " - "chars\n", from, size); - return(-1); - } - strcpy(to, save_cwd); - strcat(to, "/"); - strcat(to, from); - } - chdir(save_cwd); return(0); } -static int write_cow_header(char *cow_file, int fd, char *backing_file, - int sectorsize, long long *size) -{ - struct cow_header_v2 *header; - struct stat64 buf; - int err; - - err = os_seek_file(fd, 0); - if(err != 0){ - printk("write_cow_header - lseek failed, errno = %d\n", errno); - return(-errno); - } - - err = -ENOMEM; - header = um_kmalloc(sizeof(*header)); - if(header == NULL){ - printk("Failed to allocate COW V2 header\n"); - goto out; - } - header->magic = htonl(COW_MAGIC); - header->version = htonl(COW_VERSION); - - err = -EINVAL; - if(strlen(backing_file) > sizeof(header->backing_file) - 1){ - printk("Backing file name \"%s\" is too long - names are " - "limited to %d characters\n", backing_file, - sizeof(header->backing_file) - 1); - goto out_free; - } - - if(absolutize(header->backing_file, sizeof(header->backing_file), - backing_file)) - goto out_free; - - err = stat64(header->backing_file, &buf); - if(err < 0){ - printk("Stat of backing file '%s' failed, errno = %d\n", - header->backing_file, errno); - err = -errno; - goto out_free; - } - - err = os_file_size(header->backing_file, size); - if(err){ - printk("Couldn't get size of backing file '%s', errno = %d\n", - header->backing_file, -*size); - goto out_free; - } - - header->mtime = htonl(buf.st_mtime); - header->size = htonll(*size); - header->sectorsize = htonl(sectorsize); - - err = write(fd, header, sizeof(*header)); - if(err != sizeof(*header)){ - printk("Write of header to new COW file '%s' failed, " - "errno = %d\n", cow_file, errno); - goto out_free; - } - err = 0; - out_free: - kfree(header); - out: - return(err); -} - int open_ubd_file(char *file, struct openflags *openflags, char **backing_file_out, int *bitmap_offset_out, unsigned long *bitmap_len_out, int *data_offset_out, @@ -334,26 +108,36 @@ { time_t mtime; __u64 size; + __u32 version, align; char *backing_file; - int fd, err, sectorsize, magic, same, mode = 0644; + int fd, err, sectorsize, same, mode = 0644; - if((fd = os_open_file(file, *openflags, mode)) < 0){ + fd = os_open_file(file, *openflags, mode); + if(fd < 0){ if((fd == -ENOENT) && (create_cow_out != NULL)) *create_cow_out = 1; if(!openflags->w || ((errno != EROFS) && (errno != EACCES))) return(-errno); openflags->w = 0; - if((fd = os_open_file(file, *openflags, mode)) < 0) + fd = os_open_file(file, *openflags, mode); + if(fd < 0) return(fd); } + + err = os_lock_file(fd, openflags->w); + if(err < 0){ + printk("Failed to lock '%s', err = %d\n", file, -err); + goto out_close; + } + if(backing_file_out == NULL) return(fd); - err = read_cow_header(fd, &magic, &backing_file, &mtime, &size, - §orsize, bitmap_offset_out); + err = read_cow_header(file_reader, &fd, &version, &backing_file, &mtime, + &size, §orsize, &align, bitmap_offset_out); if(err && (*backing_file_out != NULL)){ printk("Failed to read COW header from COW file \"%s\", " - "errno = %d\n", file, err); - goto error; + "errno = %d\n", file, -err); + goto out_close; } if(err) return(fd); @@ -363,36 +147,33 @@ if(!same && !backing_file_mismatch(*backing_file_out, size, mtime)){ printk("Switching backing file to '%s'\n", *backing_file_out); - err = write_cow_header(file, fd, *backing_file_out, - sectorsize, &size); + err = write_cow_header(file, fd, *backing_file_out, + sectorsize, align, &size); if(err){ - printk("Switch failed, errno = %d\n", err); + printk("Switch failed, errno = %d\n", -err); return(err); } } else { *backing_file_out = backing_file; err = backing_file_mismatch(*backing_file_out, size, mtime); - if(err) goto error; + if(err) goto out_close; } - sizes(size, sectorsize, *bitmap_offset_out, bitmap_len_out, - data_offset_out); + cow_sizes(version, size, sectorsize, align, *bitmap_offset_out, + bitmap_len_out, data_offset_out); return(fd); - error: - close(fd); + out_close: + os_close_file(fd); return(err); } int create_cow_file(char *cow_file, char *backing_file, struct openflags flags, - int sectorsize, int *bitmap_offset_out, + int sectorsize, int alignment, int *bitmap_offset_out, unsigned long *bitmap_len_out, int *data_offset_out) { - __u64 blocks; - long zero; - int err, fd, i; - long long size; + int err, fd; flags.c = 1; fd = open_ubd_file(cow_file, &flags, NULL, NULL, NULL, NULL, NULL); @@ -403,57 +184,49 @@ goto out; } - err = write_cow_header(cow_file, fd, backing_file, sectorsize, &size); - if(err) goto out_close; - - blocks = (size + sectorsize - 1) / sectorsize; - blocks = (blocks + sizeof(long) * 8 - 1) / (sizeof(long) * 8); - zero = 0; - for(i = 0; i < blocks; i++){ - err = write(fd, &zero, sizeof(zero)); - if(err != sizeof(zero)){ - printk("Write of bitmap to new COW file '%s' failed, " - "errno = %d\n", cow_file, errno); - goto out_close; - } - } - - sizes(size, sectorsize, sizeof(struct cow_header_v2), - bitmap_len_out, data_offset_out); - *bitmap_offset_out = sizeof(struct cow_header_v2); - - return(fd); - - out_close: - close(fd); + err = init_cow_file(fd, cow_file, backing_file, sectorsize, alignment, + bitmap_offset_out, bitmap_len_out, + data_offset_out); + if(!err) + return(fd); + os_close_file(fd); out: return(err); } +/* XXX Just trivial wrappers around os_read_file and os_write_file */ int read_ubd_fs(int fd, void *buffer, int len) { - int n; - - n = read(fd, buffer, len); - if(n < 0) return(-errno); - else return(n); + return(os_read_file(fd, buffer, len)); } int write_ubd_fs(int fd, char *buffer, int len) { - int n; - - n = write(fd, buffer, len); - if(n < 0) return(-errno); - else return(n); + return(os_write_file(fd, buffer, len)); } -int ubd_is_dir(char *file) +static int update_bitmap(struct io_thread_req *req) { - struct stat64 buf; + int n; + + if(req->cow_offset == -1) + return(0); + + n = os_seek_file(req->fds[1], req->cow_offset); + if(n < 0){ + printk("do_io - bitmap lseek failed : err = %d\n", -n); + return(1); + } + + n = os_write_file(req->fds[1], &req->bitmap_words, + sizeof(req->bitmap_words)); + if(n != sizeof(req->bitmap_words)){ + printk("do_io - bitmap update failed, err = %d fd = %d\n", -n, + req->fds[1]); + return(1); + } - if(stat64(file, &buf) < 0) return(0); - return(S_ISDIR(buf.st_mode)); + return(0); } void do_io(struct io_thread_req *req) @@ -461,8 +234,18 @@ char *buf; unsigned long len; int n, nsectors, start, end, bit; + int err; __u64 off; + if(req->op == UBD_MMAP){ + /* Touch the page to force the host to do any necessary IO to + * get it into memory + */ + n = *((volatile int *) req->buffer); + req->error = update_bitmap(req); + return; + } + nsectors = req->length / req->sectorsize; start = 0; do { @@ -473,15 +256,14 @@ &req->sector_mask) == bit)) end++; - if(end != nsectors) - printk("end != nsectors\n"); off = req->offset + req->offsets[bit] + start * req->sectorsize; len = (end - start) * req->sectorsize; buf = &req->buffer[start * req->sectorsize]; - if(os_seek_file(req->fds[bit], off) != 0){ - printk("do_io - lseek failed : errno = %d\n", errno); + err = os_seek_file(req->fds[bit], off); + if(err < 0){ + printk("do_io - lseek failed : err = %d\n", -err); req->error = 1; return; } @@ -490,11 +272,10 @@ do { buf = &buf[n]; len -= n; - n = read(req->fds[bit], buf, len); + n = os_read_file(req->fds[bit], buf, len); if (n < 0) { - printk("do_io - read returned %d : " - "errno = %d fd = %d\n", n, - errno, req->fds[bit]); + printk("do_io - read failed, err = %d " + "fd = %d\n", -n, req->fds[bit]); req->error = 1; return; } @@ -502,11 +283,10 @@ if (n < len) memset(&buf[n], 0, len - n); } else { - n = write(req->fds[bit], buf, len); + n = os_write_file(req->fds[bit], buf, len); if(n != len){ - printk("do_io - write returned %d : " - "errno = %d fd = %d\n", n, - errno, req->fds[bit]); + printk("do_io - write failed err = %d " + "fd = %d\n", -n, req->fds[bit]); req->error = 1; return; } @@ -515,24 +295,7 @@ start = end; } while(start < nsectors); - if(req->cow_offset != -1){ - if(os_seek_file(req->fds[1], req->cow_offset) != 0){ - printk("do_io - bitmap lseek failed : errno = %d\n", - errno); - req->error = 1; - return; - } - n = write(req->fds[1], &req->bitmap_words, - sizeof(req->bitmap_words)); - if(n != sizeof(req->bitmap_words)){ - printk("do_io - bitmap update returned %d : " - "errno = %d fd = %d\n", n, errno, req->fds[1]); - req->error = 1; - return; - } - } - req->error = 0; - return; + req->error = update_bitmap(req); } /* Changed in start_io_thread, which is serialized by being called only @@ -550,19 +313,23 @@ signal(SIGWINCH, SIG_IGN); while(1){ - n = read(kernel_fd, &req, sizeof(req)); - if(n < 0) printk("io_thread - read returned %d, errno = %d\n", - n, errno); - else if(n < sizeof(req)){ - printk("io_thread - short read : length = %d\n", n); + n = os_read_file(kernel_fd, &req, sizeof(req)); + if(n != sizeof(req)){ + if(n < 0) + printk("io_thread - read failed, fd = %d, " + "err = %d\n", kernel_fd, -n); + else { + printk("io_thread - short read, fd = %d, " + "length = %d\n", kernel_fd, n); + } continue; } io_count++; do_io(&req); - n = write(kernel_fd, &req, sizeof(req)); + n = os_write_file(kernel_fd, &req, sizeof(req)); if(n != sizeof(req)) - printk("io_thread - write failed, errno = %d\n", - errno); + printk("io_thread - write failed, fd = %d, err = %d\n", + kernel_fd, -n); } } @@ -571,10 +338,11 @@ int pid, fds[2], err; err = os_pipe(fds, 1, 1); - if(err){ - printk("start_io_thread - os_pipe failed, errno = %d\n", -err); - return(-1); + if(err < 0){ + printk("start_io_thread - os_pipe failed, err = %d\n", -err); + goto out; } + kernel_fd = fds[0]; *fd_out = fds[1]; @@ -582,32 +350,19 @@ NULL); if(pid < 0){ printk("start_io_thread - clone failed : errno = %d\n", errno); - return(-errno); + goto out_close; } - return(pid); -} - -#ifdef notdef -int start_io_thread(unsigned long sp, int *fd_out) -{ - int pid; - if((kernel_fd = get_pty()) < 0) return(-1); - raw(kernel_fd, 0); - if((*fd_out = open(ptsname(kernel_fd), O_RDWR)) < 0){ - printk("Couldn't open tty for IO\n"); - return(-1); - } - - pid = clone(io_thread, (void *) sp, CLONE_FILES | CLONE_VM | SIGCHLD, - NULL); - if(pid < 0){ - printk("start_io_thread - clone failed : errno = %d\n", errno); - return(-errno); - } return(pid); + + out_close: + os_close_file(fds[0]); + os_close_file(fds[1]); + kernel_fd = -1; + *fd_out = -1; + out: + return(err); } -#endif /* * Overrides for Emacs so that we follow Linus's tabbing style. diff -Nru a/arch/um/drivers/xterm.c b/arch/um/drivers/xterm.c --- a/arch/um/drivers/xterm.c 2004-08-25 22:01:54 -07:00 +++ b/arch/um/drivers/xterm.c 2004-08-25 22:01:54 -07:00 @@ -8,7 +8,6 @@ #include #include #include -#include #include #include #include @@ -36,7 +35,8 @@ { struct xterm_chan *data; - if((data = malloc(sizeof(*data))) == NULL) return(NULL); + data = malloc(sizeof(*data)); + if(data == NULL) return(NULL); *data = ((struct xterm_chan) { .pid = -1, .helper_pid = -1, .device = device, @@ -93,7 +93,7 @@ "/usr/lib/uml/port-helper", "-uml-socket", file, NULL }; - if(access(argv[4], X_OK)) + if(os_access(argv[4], OS_ACC_X_OK) < 0) argv[4] = "port-helper"; fd = mkstemp(file); @@ -106,13 +106,13 @@ printk("xterm_open : unlink failed, errno = %d\n", errno); return(-errno); } - close(fd); + os_close_file(fd); - fd = create_unix_socket(file, sizeof(file)); + fd = os_create_unix_socket(file, sizeof(file), 1); if(fd < 0){ printk("xterm_open : create_unix_socket failed, errno = %d\n", -fd); - return(-fd); + return(fd); } sprintf(title, data->title, data->device); @@ -128,15 +128,16 @@ if(data->direct_rcv) new = os_rcv_fd(fd, &data->helper_pid); else { - if((err = os_set_fd_block(fd, 0)) != 0){ + err = os_set_fd_block(fd, 0); + if(err < 0){ printk("xterm_open : failed to set descriptor " - "non-blocking, errno = %d\n", err); + "non-blocking, err = %d\n", -err); return(err); } new = xterm_fd(fd, &data->helper_pid); } if(new < 0){ - printk("xterm_open : os_rcv_fd failed, errno = %d\n", -new); + printk("xterm_open : os_rcv_fd failed, err = %d\n", -new); goto out; } @@ -160,7 +161,7 @@ if(data->helper_pid != -1) os_kill_process(data->helper_pid, 0); data->helper_pid = -1; - close(fd); + os_close_file(fd); } void xterm_free(void *d) diff -Nru a/arch/um/drivers/xterm_kern.c b/arch/um/drivers/xterm_kern.c --- a/arch/um/drivers/xterm_kern.c 2004-08-25 22:01:56 -07:00 +++ b/arch/um/drivers/xterm_kern.c 2004-08-25 22:01:56 -07:00 @@ -5,9 +5,12 @@ #include "linux/errno.h" #include "linux/slab.h" +#include "linux/signal.h" +#include "linux/interrupt.h" #include "asm/semaphore.h" #include "asm/irq.h" #include "irq_user.h" +#include "irq_kern.h" #include "kern_util.h" #include "os.h" #include "xterm.h" @@ -19,17 +22,18 @@ int new_fd; }; -static void xterm_interrupt(int irq, void *data, struct pt_regs *regs) +static irqreturn_t xterm_interrupt(int irq, void *data, struct pt_regs *regs) { struct xterm_wait *xterm = data; int fd; fd = os_rcv_fd(xterm->fd, &xterm->pid); if(fd == -EAGAIN) - return; + return(IRQ_NONE); xterm->new_fd = fd; up(&xterm->sem); + return(IRQ_HANDLED); } int xterm_fd(int socket, int *pid_out) @@ -54,7 +58,8 @@ if(err){ printk(KERN_ERR "xterm_fd : failed to get IRQ for xterm, " "err = %d\n", err); - return(err); + ret = err; + goto out; } down(&data->sem); @@ -62,6 +67,7 @@ ret = data->new_fd; *pid_out = data->pid; + out: kfree(data); return(ret); diff -Nru a/arch/um/dyn.lds.S b/arch/um/dyn.lds.S --- a/arch/um/dyn.lds.S 2004-08-25 22:01:55 -07:00 +++ b/arch/um/dyn.lds.S 2004-08-25 22:01:55 -07:00 @@ -1,3 +1,5 @@ +#include + OUTPUT_FORMAT(ELF_FORMAT) OUTPUT_ARCH(ELF_ARCH) ENTRY(_start) @@ -10,12 +12,15 @@ { . = START + SIZEOF_HEADERS; .interp : { *(.interp) } - . = ALIGN(4096); __binary_start = .; . = ALIGN(4096); /* Init code and data */ _stext = .; __init_begin = .; - .text.init : { *(.text.init) } + .init.text : { + _sinittext = .; + *(.init.text) + _einittext = .; + } . = ALIGN(4096); @@ -55,7 +60,9 @@ } =0x90909090 .plt : { *(.plt) } .text : { - *(.text .stub .text.* .gnu.linkonce.t.*) + *(.text) + SCHED_TEXT + *(.stub .text.* .gnu.linkonce.t.*) /* .gnu.warning sections are handled specially by elf32.em. */ *(.gnu.warning) } =0x90909090 @@ -67,7 +74,7 @@ #include "asm/common.lds.S" - .data.init : { *(.data.init) } + init.data : { *(.init.data) } /* Ensure the __preinit_array_start label is properly aligned. We could instead move the label definition inside the section, but diff -Nru a/arch/um/include/2_5compat.h b/arch/um/include/2_5compat.h --- a/arch/um/include/2_5compat.h 2004-08-25 22:01:55 -07:00 +++ b/arch/um/include/2_5compat.h 2004-08-25 22:01:55 -07:00 @@ -6,20 +6,6 @@ #ifndef __2_5_COMPAT_H__ #define __2_5_COMPAT_H__ -#include "linux/version.h" - -#define INIT_CONSOLE(dev_name, write_proc, device_proc, setup_proc, f) { \ - name : dev_name, \ - write : write_proc, \ - read : NULL, \ - device : device_proc, \ - setup : setup_proc, \ - flags : f, \ - index : -1, \ - cflag : 0, \ - next : NULL \ -} - #define INIT_HARDSECT(arr, maj, sizes) #define SET_PRI(task) do ; while(0) diff -Nru a/arch/um/include/hostaudio.h b/arch/um/include/hostaudio.h --- a/arch/um/include/hostaudio.h 2004-08-25 22:01:55 -07:00 +++ /dev/null Wed Dec 31 16:00:00 196900 @@ -1,48 +0,0 @@ -/* - * Copyright (C) 2002 Steve Schmidtke - * Licensed under the GPL - */ - -#ifndef HOSTAUDIO_H -#define HOSTAUDIO_H - -#define HOSTAUDIO_DEV_DSP "/dev/sound/dsp" -#define HOSTAUDIO_DEV_MIXER "/dev/sound/mixer" - -struct hostaudio_state { - int fd; -}; - -struct hostmixer_state { - int fd; -}; - -/* UML user-side protoypes */ -extern ssize_t hostaudio_read_user(struct hostaudio_state *state, char *buffer, - size_t count, loff_t *ppos); -extern ssize_t hostaudio_write_user(struct hostaudio_state *state, - const char *buffer, size_t count, - loff_t *ppos); -extern int hostaudio_ioctl_user(struct hostaudio_state *state, - unsigned int cmd, unsigned long arg); -extern int hostaudio_open_user(struct hostaudio_state *state, int r, int w, - char *dsp); -extern int hostaudio_release_user(struct hostaudio_state *state); -extern int hostmixer_ioctl_mixdev_user(struct hostmixer_state *state, - unsigned int cmd, unsigned long arg); -extern int hostmixer_open_mixdev_user(struct hostmixer_state *state, int r, - int w, char *mixer); -extern int hostmixer_release_mixdev_user(struct hostmixer_state *state); - -#endif /* HOSTAUDIO_H */ - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-file-style: "linux" - * End: - */ diff -Nru a/arch/um/include/irq_kern.h b/arch/um/include/irq_kern.h --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/arch/um/include/irq_kern.h 2004-08-25 22:01:56 -07:00 @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) + * Licensed under the GPL + */ + +#ifndef __IRQ_KERN_H__ +#define __IRQ_KERN_H__ + +#include "linux/interrupt.h" + +extern int um_request_irq(unsigned int irq, int fd, int type, + irqreturn_t (*handler)(int, void *, + struct pt_regs *), + unsigned long irqflags, const char * devname, + void *dev_id); + +#endif + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff -Nru a/arch/um/include/kern_util.h b/arch/um/include/kern_util.h --- a/arch/um/include/kern_util.h 2004-08-25 22:01:55 -07:00 +++ b/arch/um/include/kern_util.h 2004-08-25 22:01:55 -07:00 @@ -60,12 +60,11 @@ extern void paging_init(void); extern void init_flush_vm(void); extern void *syscall_sp(void *t); -extern void syscall_trace(void); +extern void syscall_trace(union uml_pt_regs *regs, int entryexit); extern int hz(void); -extern void idle_timer(void); +extern void uml_idle_timer(void); extern unsigned int do_IRQ(int irq, union uml_pt_regs *regs); extern int external_pid(void *t); -extern int pid_to_processor_id(int pid); extern void boot_timer_handler(int sig); extern void interrupt_end(void); extern void initial_thread_cb(void (*proc)(void *), void *arg); @@ -89,9 +88,7 @@ extern char *uml_strdup(char *string); extern void unprotect_kernel_mem(void); extern void protect_kernel_mem(void); -extern void set_kmem_end(unsigned long); extern void uml_cleanup(void); -extern int pid_to_processor_id(int pid); extern void set_current(void *t); extern void lock_signalled_task(void *t); extern void IPI_handler(int cpu); @@ -100,7 +97,9 @@ extern int clear_user_proc(void *buf, int size); extern int copy_to_user_proc(void *to, void *from, int size); extern int copy_from_user_proc(void *to, void *from, int size); +extern int strlen_user_proc(char *str); extern void bus_handler(int sig, union uml_pt_regs *regs); +extern void winch(int sig, union uml_pt_regs *regs); extern long execute_syscall(void *r); extern int smp_sigio_handler(void); extern void *get_current(void); @@ -111,6 +110,8 @@ extern void free_irq(unsigned int, void *); extern int um_in_interrupt(void); extern int cpu(void); +extern unsigned long long time_stamp(void); + #endif /* diff -Nru a/arch/um/include/line.h b/arch/um/include/line.h --- a/arch/um/include/line.h 2004-08-25 22:01:56 -07:00 +++ b/arch/um/include/line.h 2004-08-25 22:01:56 -07:00 @@ -9,12 +9,14 @@ #include "linux/list.h" #include "linux/workqueue.h" #include "linux/tty.h" +#include "linux/interrupt.h" #include "asm/semaphore.h" #include "chan_user.h" #include "mconsole_kern.h" struct line_driver { char *name; + char *device_name; char *devfs_name; short major; short minor_start; @@ -67,8 +69,6 @@ #define LINES_INIT(n) { num : n } -extern void line_interrupt(int irq, void *data, struct pt_regs *unused); -extern void line_write_interrupt(int irq, void *data, struct pt_regs *unused); extern void line_close(struct line *lines, struct tty_struct *tty); extern int line_open(struct line *lines, struct tty_struct *tty, struct chan_opts *opts); diff -Nru a/arch/um/include/mconsole.h b/arch/um/include/mconsole.h --- a/arch/um/include/mconsole.h 2004-08-25 22:01:55 -07:00 +++ b/arch/um/include/mconsole.h 2004-08-25 22:01:55 -07:00 @@ -41,11 +41,13 @@ struct mc_request; +enum mc_context { MCONSOLE_INTR, MCONSOLE_PROC }; + struct mconsole_command { char *command; void (*handler)(struct mc_request *req); - int as_interrupt; + enum mc_context context; }; struct mc_request @@ -77,6 +79,8 @@ extern void mconsole_cad(struct mc_request *req); extern void mconsole_stop(struct mc_request *req); extern void mconsole_go(struct mc_request *req); +extern void mconsole_log(struct mc_request *req); +extern void mconsole_proc(struct mc_request *req); extern int mconsole_get_request(int fd, struct mc_request *req); extern int mconsole_notify(char *sock_name, int type, const void *data, diff -Nru a/arch/um/include/mem.h b/arch/um/include/mem.h --- a/arch/um/include/mem.h 2004-08-25 22:01:56 -07:00 +++ b/arch/um/include/mem.h 2004-08-25 22:01:56 -07:00 @@ -1,19 +1,18 @@ /* - * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) + * Copyright (C) 2002, 2003 Jeff Dike (jdike@addtoit.com) * Licensed under the GPL */ #ifndef __MEM_H__ #define __MEM_H__ -struct vm_reserved { - struct list_head list; - unsigned long start; - unsigned long end; -}; +#include "linux/types.h" -extern void set_usable_vm(unsigned long start, unsigned long end); -extern void set_kmem_end(unsigned long new); +extern int phys_mapping(unsigned long phys, __u64 *offset_out); +extern int physmem_subst_mapping(void *virt, int fd, __u64 offset, int w); +extern int is_remapped(void *virt); +extern int physmem_remove_mapping(void *virt); +extern void physmem_forget_descriptor(int fd); #endif diff -Nru a/arch/um/include/mem_kern.h b/arch/um/include/mem_kern.h --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/arch/um/include/mem_kern.h 2004-08-25 22:01:56 -07:00 @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2003 Jeff Dike (jdike@addtoit.com) + * Licensed under the GPL + */ + +#ifndef __MEM_KERN_H__ +#define __MEM_KERN_H__ + +#include "linux/list.h" +#include "linux/types.h" + +struct remapper { + struct list_head list; + int (*proc)(int, unsigned long, int, __u64); +}; + +extern void register_remapper(struct remapper *info); + +#endif + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff -Nru a/arch/um/include/mem_user.h b/arch/um/include/mem_user.h --- a/arch/um/include/mem_user.h 2004-08-25 22:01:55 -07:00 +++ b/arch/um/include/mem_user.h 2004-08-25 22:01:55 -07:00 @@ -32,43 +32,38 @@ #ifndef _MEM_USER_H #define _MEM_USER_H -struct mem_region { +struct iomem_region { + struct iomem_region *next; char *driver; - unsigned long start_pfn; - unsigned long start; - unsigned long len; - void *mem_map; int fd; + int size; + unsigned long phys; + unsigned long virt; }; -extern struct mem_region *regions[]; -extern struct mem_region physmem_region; +extern struct iomem_region *iomem_regions; +extern int iomem_size; #define ROUND_4M(n) ((((unsigned long) (n)) + (1 << 22)) & ~((1 << 22) - 1)) extern unsigned long host_task_size; extern unsigned long task_size; +extern void check_devanon(void); extern int init_mem_user(void); extern int create_mem_file(unsigned long len); -extern void setup_range(int fd, char *driver, unsigned long start, - unsigned long pfn, unsigned long total, int need_vm, - struct mem_region *region, void *reserved); extern void setup_memory(void *entry); extern unsigned long find_iomem(char *driver, unsigned long *len_out); -extern int init_maps(struct mem_region *region); -extern int nregions(void); -extern int reserve_vm(unsigned long start, unsigned long end, void *e); +extern int init_maps(unsigned long physmem, unsigned long iomem, + unsigned long highmem); extern unsigned long get_vm(unsigned long len); extern void setup_physmem(unsigned long start, unsigned long usable, - unsigned long len); -extern int setup_region(struct mem_region *region, void *entry); + unsigned long len, unsigned long highmem); extern void add_iomem(char *name, int fd, unsigned long size); -extern struct mem_region *phys_region(unsigned long phys); extern unsigned long phys_offset(unsigned long phys); extern void unmap_physmem(void); -extern int map_memory(unsigned long virt, unsigned long phys, - unsigned long len, int r, int w, int x); +extern void map_memory(unsigned long virt, unsigned long phys, + unsigned long len, int r, int w, int x); extern int protect_memory(unsigned long addr, unsigned long len, int r, int w, int x, int must_succeed); extern unsigned long get_kmem_end(void); diff -Nru a/arch/um/include/os.h b/arch/um/include/os.h --- a/arch/um/include/os.h 2004-08-25 22:01:54 -07:00 +++ b/arch/um/include/os.h 2004-08-25 22:01:54 -07:00 @@ -17,6 +17,32 @@ #define OS_TYPE_FIFO 6 #define OS_TYPE_SOCK 7 +/* os_access() flags */ +#define OS_ACC_F_OK 0 /* Test for existence. */ +#define OS_ACC_X_OK 1 /* Test for execute permission. */ +#define OS_ACC_W_OK 2 /* Test for write permission. */ +#define OS_ACC_R_OK 4 /* Test for read permission. */ +#define OS_ACC_RW_OK (OS_ACC_W_OK | OS_ACC_R_OK) /* Test for RW permission */ + +/* + * types taken from stat_file() in hostfs_user.c + * (if they are wrong here, they are wrong there...). + */ +struct uml_stat { + int ust_dev; /* device */ + unsigned long long ust_ino; /* inode */ + int ust_mode; /* protection */ + int ust_nlink; /* number of hard links */ + int ust_uid; /* user ID of owner */ + int ust_gid; /* group ID of owner */ + unsigned long long ust_size; /* total size, in bytes */ + int ust_blksize; /* blocksize for filesystem I/O */ + unsigned long long ust_blocks; /* number of blocks allocated */ + unsigned long ust_atime; /* time of last access */ + unsigned long ust_mtime; /* time of last modification */ + unsigned long ust_ctime; /* time of last change */ +}; + struct openflags { unsigned int r : 1; unsigned int w : 1; @@ -84,29 +110,47 @@ flags.e = 1; return(flags); } - + static inline struct openflags of_cloexec(struct openflags flags) { flags.cl = 1; return(flags); } +extern int os_stat_file(const char *file_name, struct uml_stat *buf); +extern int os_stat_fd(const int fd, struct uml_stat *buf); +extern int os_access(const char *file, int mode); +extern void os_print_error(int error, const char* str); +extern int os_get_exec_close(int fd, int *close_on_exec); +extern int os_set_exec_close(int fd, int close_on_exec); +extern int os_ioctl_generic(int fd, unsigned int cmd, unsigned long arg); +extern int os_window_size(int fd, int *rows, int *cols); +extern int os_new_tty_pgrp(int fd, int pid); +extern int os_get_ifname(int fd, char *namebuf); +extern int os_set_slip(int fd); +extern int os_set_owner(int fd, int pid); +extern int os_sigio_async(int master, int slave); +extern int os_mode_fd(int fd, int mode); + extern int os_seek_file(int fd, __u64 offset); extern int os_open_file(char *file, struct openflags flags, int mode); extern int os_read_file(int fd, void *buf, int len); -extern int os_write_file(int fd, void *buf, int count); +extern int os_write_file(int fd, const void *buf, int count); extern int os_file_size(char *file, long long *size_out); +extern int os_file_modtime(char *file, unsigned long *modtime); extern int os_pipe(int *fd, int stream, int close_on_exec); extern int os_set_fd_async(int fd, int owner); extern int os_set_fd_block(int fd, int blocking); extern int os_accept_connection(int fd); +extern int os_create_unix_socket(char *file, int len, int close_on_exec); extern int os_shutdown_socket(int fd, int r, int w); extern void os_close_file(int fd); extern int os_rcv_fd(int fd, int *helper_pid_out); -extern int create_unix_socket(char *file, int len); +extern int create_unix_socket(char *file, int len, int close_on_exec); extern int os_connect_socket(char *name); extern int os_file_type(char *file); extern int os_file_mode(char *file, struct openflags *mode_out); +extern int os_lock_file(int fd, int excl); extern unsigned long os_process_pc(int pid); extern int os_process_parent(int pid); @@ -115,11 +159,12 @@ extern void os_usr1_process(int pid); extern int os_getpid(void); -extern int os_map_memory(void *virt, int fd, unsigned long off, +extern int os_map_memory(void *virt, int fd, unsigned long long off, unsigned long len, int r, int w, int x); extern int os_protect_memory(void *addr, unsigned long len, int r, int w, int x); extern int os_unmap_memory(void *addr, int len); +extern void os_flush_stdout(void); #endif diff -Nru a/arch/um/include/signal_user.h b/arch/um/include/signal_user.h --- a/arch/um/include/signal_user.h 2004-08-25 22:01:54 -07:00 +++ b/arch/um/include/signal_user.h 2004-08-25 22:01:54 -07:00 @@ -11,6 +11,8 @@ extern int change_sig(int signal, int on); extern void set_sigstack(void *stack, int size); extern void set_handler(int sig, void (*handler)(int), int flags, ...); +extern int set_signals(int enable); +extern int get_signals(void); #endif diff -Nru a/arch/um/include/skas_ptrace.h b/arch/um/include/skas_ptrace.h --- a/arch/um/include/skas_ptrace.h 2004-08-25 22:01:56 -07:00 +++ b/arch/um/include/skas_ptrace.h 2004-08-25 22:01:56 -07:00 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) + * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) * Licensed under the GPL */ diff -Nru a/arch/um/include/sysdep-i386/checksum.h b/arch/um/include/sysdep-i386/checksum.h --- a/arch/um/include/sysdep-i386/checksum.h 2004-08-25 22:01:56 -07:00 +++ b/arch/um/include/sysdep-i386/checksum.h 2004-08-25 22:01:56 -07:00 @@ -5,6 +5,7 @@ #ifndef __UM_SYSDEP_CHECKSUM_H #define __UM_SYSDEP_CHECKSUM_H +#include "linux/in6.h" #include "linux/string.h" /* diff -Nru a/arch/um/include/sysdep-i386/frame_user.h b/arch/um/include/sysdep-i386/frame_user.h --- a/arch/um/include/sysdep-i386/frame_user.h 2004-08-25 22:01:56 -07:00 +++ b/arch/um/include/sysdep-i386/frame_user.h 2004-08-25 22:01:56 -07:00 @@ -56,26 +56,26 @@ * it would have to be __builtin_frame_address(1). */ -static inline unsigned long frame_restorer(void) -{ - unsigned long *fp; - - fp = __builtin_frame_address(0); - return((unsigned long) (fp + 1)); -} +#define frame_restorer() \ +({ \ + unsigned long *fp; \ +\ + fp = __builtin_frame_address(0); \ + ((unsigned long) (fp + 1)); \ +}) /* Similarly, this returns the value of sp when the handler was first * entered. This is used to calculate the proper sp when delivering * signals. */ -static inline unsigned long frame_sp(void) -{ - unsigned long *fp; - - fp = __builtin_frame_address(0); - return((unsigned long) (fp + 1)); -} +#define frame_sp() \ +({ \ + unsigned long *fp; \ +\ + fp = __builtin_frame_address(0); \ + ((unsigned long) (fp + 1)); \ +}) #endif diff -Nru a/arch/um/include/sysdep-i386/sigcontext.h b/arch/um/include/sysdep-i386/sigcontext.h --- a/arch/um/include/sysdep-i386/sigcontext.h 2004-08-25 22:01:56 -07:00 +++ b/arch/um/include/sysdep-i386/sigcontext.h 2004-08-25 22:01:56 -07:00 @@ -28,8 +28,8 @@ */ #define SC_START_SYSCALL(sc) do SC_EAX(sc) = -ENOSYS; while(0) -/* These are General Protection and Page Fault */ -#define SEGV_IS_FIXABLE(trap) ((trap == 13) || (trap == 14)) +/* This is Page Fault */ +#define SEGV_IS_FIXABLE(trap) (trap == 14) #define SC_SEGV_IS_FIXABLE(sc) (SEGV_IS_FIXABLE(SC_TRAPNO(sc))) diff -Nru a/arch/um/include/sysdep-i386/syscalls.h b/arch/um/include/sysdep-i386/syscalls.h --- a/arch/um/include/sysdep-i386/syscalls.h 2004-08-25 22:01:54 -07:00 +++ b/arch/um/include/sysdep-i386/syscalls.h 2004-08-25 22:01:54 -07:00 @@ -11,39 +11,34 @@ #define EXECUTE_SYSCALL(syscall, regs) \ ((long (*)(struct syscall_args)) (*sys_call_table[syscall]))(SYSCALL_ARGS(®s->regs)) -extern syscall_handler_t sys_modify_ldt; -extern syscall_handler_t old_mmap_i386; -extern syscall_handler_t old_select; -extern syscall_handler_t sys_ni_syscall; - #define ARCH_SYSCALLS \ - [ __NR_mmap ] = old_mmap_i386, \ - [ __NR_select ] = old_select, \ - [ __NR_vm86old ] = sys_ni_syscall, \ - [ __NR_modify_ldt ] = sys_modify_ldt, \ - [ __NR_lchown32 ] = sys_lchown, \ - [ __NR_getuid32 ] = sys_getuid, \ - [ __NR_getgid32 ] = sys_getgid, \ - [ __NR_geteuid32 ] = sys_geteuid, \ - [ __NR_getegid32 ] = sys_getegid, \ - [ __NR_setreuid32 ] = sys_setreuid, \ - [ __NR_setregid32 ] = sys_setregid, \ - [ __NR_getgroups32 ] = sys_getgroups, \ - [ __NR_setgroups32 ] = sys_setgroups, \ - [ __NR_fchown32 ] = sys_fchown, \ - [ __NR_setresuid32 ] = sys_setresuid, \ - [ __NR_getresuid32 ] = sys_getresuid, \ - [ __NR_setresgid32 ] = sys_setresgid, \ - [ __NR_getresgid32 ] = sys_getresgid, \ - [ __NR_chown32 ] = sys_chown, \ - [ __NR_setuid32 ] = sys_setuid, \ - [ __NR_setgid32 ] = sys_setgid, \ - [ __NR_setfsuid32 ] = sys_setfsuid, \ - [ __NR_setfsgid32 ] = sys_setfsgid, \ - [ __NR_pivot_root ] = sys_pivot_root, \ - [ __NR_mincore ] = sys_mincore, \ - [ __NR_madvise ] = sys_madvise, \ - [ 222 ] = sys_ni_syscall, + [ __NR_mmap ] = (syscall_handler_t *) old_mmap_i386, \ + [ __NR_select ] = (syscall_handler_t *) old_select, \ + [ __NR_vm86old ] = (syscall_handler_t *) sys_ni_syscall, \ + [ __NR_modify_ldt ] = (syscall_handler_t *) sys_modify_ldt, \ + [ __NR_lchown32 ] = (syscall_handler_t *) sys_lchown, \ + [ __NR_getuid32 ] = (syscall_handler_t *) sys_getuid, \ + [ __NR_getgid32 ] = (syscall_handler_t *) sys_getgid, \ + [ __NR_geteuid32 ] = (syscall_handler_t *) sys_geteuid, \ + [ __NR_getegid32 ] = (syscall_handler_t *) sys_getegid, \ + [ __NR_setreuid32 ] = (syscall_handler_t *) sys_setreuid, \ + [ __NR_setregid32 ] = (syscall_handler_t *) sys_setregid, \ + [ __NR_getgroups32 ] = (syscall_handler_t *) sys_getgroups, \ + [ __NR_setgroups32 ] = (syscall_handler_t *) sys_setgroups, \ + [ __NR_fchown32 ] = (syscall_handler_t *) sys_fchown, \ + [ __NR_setresuid32 ] = (syscall_handler_t *) sys_setresuid, \ + [ __NR_getresuid32 ] = (syscall_handler_t *) sys_getresuid, \ + [ __NR_setresgid32 ] = (syscall_handler_t *) sys_setresgid, \ + [ __NR_getresgid32 ] = (syscall_handler_t *) sys_getresgid, \ + [ __NR_chown32 ] = (syscall_handler_t *) sys_chown, \ + [ __NR_setuid32 ] = (syscall_handler_t *) sys_setuid, \ + [ __NR_setgid32 ] = (syscall_handler_t *) sys_setgid, \ + [ __NR_setfsuid32 ] = (syscall_handler_t *) sys_setfsuid, \ + [ __NR_setfsgid32 ] = (syscall_handler_t *) sys_setfsgid, \ + [ __NR_pivot_root ] = (syscall_handler_t *) sys_pivot_root, \ + [ __NR_mincore ] = (syscall_handler_t *) sys_mincore, \ + [ __NR_madvise ] = (syscall_handler_t *) sys_madvise, \ + [ 222 ] = (syscall_handler_t *) sys_ni_syscall, /* 222 doesn't yet have a name in include/asm-i386/unistd.h */ diff -Nru a/arch/um/include/ubd_user.h b/arch/um/include/ubd_user.h --- a/arch/um/include/ubd_user.h 2004-08-25 22:01:55 -07:00 +++ b/arch/um/include/ubd_user.h 2004-08-25 22:01:55 -07:00 @@ -9,7 +9,7 @@ #include "os.h" -enum ubd_req { UBD_READ, UBD_WRITE }; +enum ubd_req { UBD_READ, UBD_WRITE, UBD_MMAP }; struct io_thread_req { enum ubd_req op; @@ -20,8 +20,10 @@ char *buffer; int sectorsize; unsigned long sector_mask; - unsigned long cow_offset; + unsigned long long cow_offset; unsigned long bitmap_words[2]; + int map_fd; + unsigned long long map_offset; int error; }; @@ -31,7 +33,7 @@ int *create_cow_out); extern int create_cow_file(char *cow_file, char *backing_file, struct openflags flags, int sectorsize, - int *bitmap_offset_out, + int alignment, int *bitmap_offset_out, unsigned long *bitmap_len_out, int *data_offset_out); extern int read_cow_bitmap(int fd, void *buf, int offset, int len); @@ -39,7 +41,6 @@ extern int write_ubd_fs(int fd, char *buffer, int len); extern int start_io_thread(unsigned long sp, int *fds_out); extern void do_io(struct io_thread_req *req); -extern int ubd_is_dir(char *file); static inline int ubd_test_bit(__u64 bit, unsigned char *data) { diff -Nru a/arch/um/include/um_uaccess.h b/arch/um/include/um_uaccess.h --- a/arch/um/include/um_uaccess.h 2004-08-25 22:01:55 -07:00 +++ b/arch/um/include/um_uaccess.h 2004-08-25 22:01:55 -07:00 @@ -38,22 +38,73 @@ from, n)); } +/* + * strncpy_from_user: - Copy a NUL terminated string from userspace. + * @dst: Destination address, in kernel space. This buffer must be at + * least @count bytes long. + * @src: Source address, in user space. + * @count: Maximum number of bytes to copy, including the trailing NUL. + * + * Copies a NUL-terminated string from userspace to kernel space. + * + * On success, returns the length of the string (not including the trailing + * NUL). + * + * If access to userspace fails, returns -EFAULT (some data may have been + * copied). + * + * If @count is smaller than the length of the string, copies @count bytes + * and returns @count. + */ + static inline int strncpy_from_user(char *dst, const char *src, int count) { return(CHOOSE_MODE_PROC(strncpy_from_user_tt, strncpy_from_user_skas, dst, src, count)); } +/* + * __clear_user: - Zero a block of memory in user space, with less checking. + * @to: Destination address, in user space. + * @n: Number of bytes to zero. + * + * Zero a block of memory in user space. Caller must check + * the specified block with access_ok() before calling this function. + * + * Returns number of bytes that could not be cleared. + * On success, this will be zero. + */ static inline int __clear_user(void *mem, int len) { return(CHOOSE_MODE_PROC(__clear_user_tt, __clear_user_skas, mem, len)); } +/* + * clear_user: - Zero a block of memory in user space. + * @to: Destination address, in user space. + * @n: Number of bytes to zero. + * + * Zero a block of memory in user space. + * + * Returns number of bytes that could not be cleared. + * On success, this will be zero. + */ static inline int clear_user(void *mem, int len) { return(CHOOSE_MODE_PROC(clear_user_tt, clear_user_skas, mem, len)); } +/* + * strlen_user: - Get the size of a string in user space. + * @str: The string to measure. + * @n: The maximum valid length + * + * Get the size of a NUL-terminated string in user space. + * + * Returns the size of the string INCLUDING the terminating NUL. + * On exception, returns 0. + * If the string is too long, returns a value greater than @n. + */ static inline int strnlen_user(const void *str, int len) { return(CHOOSE_MODE_PROC(strnlen_user_tt, strnlen_user_skas, str, len)); diff -Nru a/arch/um/include/user.h b/arch/um/include/user.h --- a/arch/um/include/user.h 2004-08-25 22:01:54 -07:00 +++ b/arch/um/include/user.h 2004-08-25 22:01:54 -07:00 @@ -14,6 +14,9 @@ extern void kfree(void *ptr); extern int in_aton(char *str); extern int open_gdb_chan(void); +extern int strlcpy(char *, const char *, int); +extern void *um_vmalloc(int size); +extern void vfree(void *ptr); #endif diff -Nru a/arch/um/include/user_util.h b/arch/um/include/user_util.h --- a/arch/um/include/user_util.h 2004-08-25 22:01:54 -07:00 +++ b/arch/um/include/user_util.h 2004-08-25 22:01:54 -07:00 @@ -14,8 +14,6 @@ extern int unlockpt(int __fd); extern char *ptsname(int __fd); -enum { OP_NONE, OP_EXEC, OP_FORK, OP_TRACE_ON, OP_REBOOT, OP_HALT, OP_CB }; - struct cpu_task { int pid; void *task; @@ -59,13 +57,11 @@ extern void *add_signal_handler(int sig, void (*handler)(int)); extern int start_fork_tramp(void *arg, unsigned long temp_stack, int clone_flags, int (*tramp)(void *)); -extern int clone_and_wait(int (*fn)(void *), void *arg, void *sp, int flags); extern int linux_main(int argc, char **argv); extern void set_cmdline(char *cmd); extern void input_cb(void (*proc)(void *), void *arg, int arg_len); extern int get_pty(void); extern void *um_kmalloc(int size); -extern int raw(int fd, int complain); extern int switcheroo(int fd, int prot, void *from, void *to, int size); extern void setup_machinename(char *machine_out); extern void setup_hostinfo(void); @@ -86,11 +82,17 @@ extern int run_kernel_thread(int (*fn)(void *), void *arg, void **jmp_ptr); extern void write_sigio_workaround(void); extern void arch_check_bugs(void); +extern int cpu_feature(char *what, char *buf, int len); extern int arch_handle_signal(int sig, union uml_pt_regs *regs); extern int arch_fixup(unsigned long address, void *sc_ptr); extern void forward_pending_sigio(int target); extern int can_do_skas(void); - +extern void arch_init_thread(void); + +extern int __raw(int fd, int complain, int now); +#define raw(fd, complain) __raw((fd), (complain), 1) + +#define CATCH_EINTR(expr) while ( ((expr) < 0) && errno == EINTR) #endif /* diff -Nru a/arch/um/kernel/Makefile b/arch/um/kernel/Makefile --- a/arch/um/kernel/Makefile 2004-08-25 22:01:55 -07:00 +++ b/arch/um/kernel/Makefile 2004-08-25 22:01:55 -07:00 @@ -3,15 +3,15 @@ # Licensed under the GPL # -extra-y := vmlinux.lds +extra-y := vmlinux.lds uml.lds obj-y = checksum.o config.o exec_kern.o exitcode.o frame_kern.o frame.o \ - helper.o init_task.o irq.o irq_user.o ksyms.o mem.o mem_user.o \ - process.o process_kern.o ptrace.o reboot.o resource.o sigio_user.o \ - sigio_kern.o signal_kern.o signal_user.o smp.o syscall_kern.o \ - syscall_user.o sysrq.o sys_call_table.o tempfile.o time.o \ - time_kern.o tlb.o trap_kern.o trap_user.o uaccess_user.o um_arch.o \ - umid.o user_syms.o user_util.o + helper.o init_task.o irq.o irq_user.o ksyms.o main.o mem.o mem_user.o \ + physmem.o process.o process_kern.o ptrace.o reboot.o resource.o \ + sigio_user.o sigio_kern.o signal_kern.o signal_user.o smp.o \ + syscall_kern.o syscall_user.o sysrq.o sys_call_table.o tempfile.o \ + time.o time_kern.o tlb.o trap_kern.o trap_user.o uaccess_user.o \ + um_arch.o umid.o user_util.o obj-$(CONFIG_BLK_DEV_INITRD) += initrd_kern.o initrd_user.o obj-$(CONFIG_GPROF) += gprof_syms.o @@ -24,43 +24,27 @@ user-objs-$(CONFIG_TTY_LOG) += tty_log.o USER_OBJS := $(filter %_user.o,$(obj-y)) $(user-objs-y) config.o helper.o \ - process.o tempfile.o time.o tty_log.o umid.o user_util.o user_syms.o + main.o process.o tempfile.o time.o tty_log.o umid.o user_util.o USER_OBJS := $(foreach file,$(USER_OBJS),$(obj)/$(file)) -DMODULES-$(CONFIG_MODULES) = -D__CONFIG_MODULES__ -DMODVERSIONS-$(CONFIG_MODVERSIONS) = -D__CONFIG_MODVERSIONS__ - - -CFLAGS_user_syms.o = -D__AUTOCONF_INCLUDED__ $(DMODULES-y) $(DMODVERSIONS-y) \ - -I/usr/include -I../include - CFLAGS_frame.o := $(patsubst -fomit-frame-pointer,,$(USER_CFLAGS)) -$(USER_OBJS) : %.o: %.c - $(CC) $(CFLAGS_$(notdir $@)) $(USER_CFLAGS) -c -o $@ $< - # This has to be separate because it needs be compiled with frame pointers # regardless of how the rest of the kernel is built. $(obj)/frame.o: $(src)/frame.c $(CC) $(CFLAGS_$(notdir $@)) -c -o $@ $< -QUOTE = 'my $$config=`cat $(TOPDIR)/.config`; $$config =~ s/"/\\"/g ; while() { $$_ =~ s/CONFIG/$$config/; print $$_ }' +$(USER_OBJS) : %.o: %.c + $(CC) $(CFLAGS_$(notdir $@)) $(USER_CFLAGS) -c -o $@ $< -$(obj)/config.c : $(src)/config.c.in $(TOPDIR)/.config - $(PERL) -e $(QUOTE) < $(src)/config.c.in > $@ +QUOTE = 'my $$config=`cat $(TOPDIR)/.config`; $$config =~ s/"/\\"/g ; $$config =~ s/\n/\\n"\n"/g ; while() { $$_ =~ s/CONFIG/$$config/; print $$_ }' $(obj)/config.o : $(obj)/config.c -clean: - rm -f config.c - for dir in $(subdir-y) ; do $(MAKE) -C $$dir clean; done - -modules: - -fastdep: - -dep: - -archmrproper: clean +quiet_cmd_quote = QUOTE $@ +cmd_quote = $(PERL) -e $(QUOTE) < $< > $@ +targets += config.c +$(obj)/config.c : $(src)/config.c.in $(TOPDIR)/.config FORCE + $(call if_changed,quote) diff -Nru a/arch/um/kernel/config.c.in b/arch/um/kernel/config.c.in --- a/arch/um/kernel/config.c.in 2004-08-25 22:01:56 -07:00 +++ b/arch/um/kernel/config.c.in 2004-08-25 22:01:56 -07:00 @@ -7,9 +7,7 @@ #include #include "init.h" -static __initdata char *config = " -CONFIG -"; +static __initdata char *config = "CONFIG"; static int __init print_config(char *line, int *add) { diff -Nru a/arch/um/kernel/exec_kern.c b/arch/um/kernel/exec_kern.c --- a/arch/um/kernel/exec_kern.c 2004-08-25 22:01:54 -07:00 +++ b/arch/um/kernel/exec_kern.c 2004-08-25 22:01:54 -07:00 @@ -32,10 +32,15 @@ CHOOSE_MODE_PROC(start_thread_tt, start_thread_skas, regs, eip, esp); } +extern void log_exec(char **argv, void *tty); + static int execve1(char *file, char **argv, char **env) { int error; +#ifdef CONFIG_TTY_LOG + log_exec(argv, current->tty); +#endif error = do_execve(file, argv, env, ¤t->thread.regs); if (error == 0){ current->ptrace &= ~PT_DTRACE; diff -Nru a/arch/um/kernel/frame.c b/arch/um/kernel/frame.c --- a/arch/um/kernel/frame.c 2004-08-25 22:01:55 -07:00 +++ b/arch/um/kernel/frame.c 2004-08-25 22:01:55 -07:00 @@ -21,6 +21,7 @@ #include "sysdep/sigcontext.h" #include "frame_user.h" #include "kern_util.h" +#include "user_util.h" #include "ptrace_user.h" #include "os.h" @@ -40,7 +41,7 @@ /* Wait for it to stop itself and continue it with a SIGUSR1 to force * it into the signal handler. */ - n = waitpid(pid, &status, WUNTRACED); + CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED)); if(n < 0){ printf("capture_stack : waitpid failed - errno = %d\n", errno); exit(1); @@ -60,7 +61,7 @@ * At this point, the handler has stuffed the addresses of * sig, sc, and SA_RESTORER in raw. */ - n = waitpid(pid, &status, WUNTRACED); + CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED)); if(n < 0){ printf("capture_stack : waitpid failed - errno = %d\n", errno); exit(1); @@ -82,7 +83,8 @@ errno); exit(1); } - if(waitpid(pid, &status, 0) < 0){ + CATCH_EINTR(n = waitpid(pid, &status, 0)); + if(n < 0){ printf("capture_stack : waitpid failed - errno = %d\n", errno); exit(1); } @@ -279,7 +281,7 @@ struct sc_frame_raw raw_sc; struct si_frame_raw raw_si; void *stack, *sigstack; - unsigned long top, sig_top, base; + unsigned long top, base; stack = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); @@ -292,7 +294,6 @@ } top = (unsigned long) stack + PAGE_SIZE - sizeof(void *); - sig_top = (unsigned long) sigstack + PAGE_SIZE; /* Get the sigcontext, no sigrestorer layout */ raw_sc.restorer = 0; diff -Nru a/arch/um/kernel/frame_kern.c b/arch/um/kernel/frame_kern.c --- a/arch/um/kernel/frame_kern.c 2004-08-25 22:01:56 -07:00 +++ b/arch/um/kernel/frame_kern.c 2004-08-25 22:01:56 -07:00 @@ -6,7 +6,6 @@ #include "asm/ptrace.h" #include "asm/uaccess.h" #include "asm/signal.h" -#include "asm/uaccess.h" #include "asm/ucontext.h" #include "frame_kern.h" #include "sigcontext.h" @@ -29,12 +28,15 @@ sizeof(restorer))); } +extern int userspace_pid[]; + static int copy_sc_to_user(void *to, void *fp, struct pt_regs *from, struct arch_frame_data *arch) { return(CHOOSE_MODE(copy_sc_to_user_tt(to, fp, UPT_SC(&from->regs), arch), - copy_sc_to_user_skas(to, fp, &from->regs, + copy_sc_to_user_skas(userspace_pid[0], to, fp, + &from->regs, current->thread.cr2, current->thread.err))); } diff -Nru a/arch/um/kernel/helper.c b/arch/um/kernel/helper.c --- a/arch/um/kernel/helper.c 2004-08-25 22:01:55 -07:00 +++ b/arch/um/kernel/helper.c 2004-08-25 22:01:55 -07:00 @@ -7,12 +7,12 @@ #include #include #include -#include #include #include #include #include "user.h" #include "kern_util.h" +#include "user_util.h" #include "os.h" struct helper_data { @@ -33,6 +33,7 @@ { struct helper_data *data = arg; char **argv = data->argv; + int errval; if(helper_pause){ signal(SIGHUP, helper_hup); @@ -41,8 +42,9 @@ if(data->pre_exec != NULL) (*data->pre_exec)(data->pre_data); execvp(argv[0], argv); + errval = errno; printk("execvp of '%s' failed - errno = %d\n", argv[0], errno); - write(data->fd, &errno, sizeof(errno)); + os_write_file(data->fd, &errval, sizeof(errval)); os_kill_process(os_getpid(), 0); return(0); } @@ -59,17 +61,20 @@ if((stack_out != NULL) && (*stack_out != 0)) stack = *stack_out; else stack = alloc_stack(0, um_in_interrupt()); - if(stack == 0) return(-ENOMEM); + if(stack == 0) + return(-ENOMEM); err = os_pipe(fds, 1, 0); - if(err){ - printk("run_helper : pipe failed, errno = %d\n", -err); - return(err); + if(err < 0){ + printk("run_helper : pipe failed, err = %d\n", -err); + goto out_free; } - if(fcntl(fds[1], F_SETFD, 1) != 0){ - printk("run_helper : setting FD_CLOEXEC failed, errno = %d\n", - errno); - return(-errno); + + err = os_set_exec_close(fds[1], 1); + if(err < 0){ + printk("run_helper : setting FD_CLOEXEC failed, err = %d\n", + -err); + goto out_close; } sp = stack + page_size() - sizeof(void *); @@ -80,23 +85,34 @@ pid = clone(helper_child, (void *) sp, CLONE_VM | SIGCHLD, &data); if(pid < 0){ printk("run_helper : clone failed, errno = %d\n", errno); - return(-errno); + err = -errno; + goto out_close; } - close(fds[1]); - n = read(fds[0], &err, sizeof(err)); + + os_close_file(fds[1]); + n = os_read_file(fds[0], &err, sizeof(err)); if(n < 0){ - printk("run_helper : read on pipe failed, errno = %d\n", - errno); - return(-errno); + printk("run_helper : read on pipe failed, err = %d\n", -n); + err = n; + goto out_kill; } else if(n != 0){ - waitpid(pid, NULL, 0); - pid = -err; + CATCH_EINTR(n = waitpid(pid, NULL, 0)); + pid = -errno; } if(stack_out == NULL) free_stack(stack, 0); else *stack_out = stack; return(pid); + + out_kill: + os_kill_process(pid, 1); + out_close: + os_close_file(fds[0]); + os_close_file(fds[1]); + out_free: + free_stack(stack, 0); + return(err); } int run_helper_thread(int (*proc)(void *), void *arg, unsigned int flags, @@ -117,9 +133,11 @@ } if(stack_out == NULL){ pid = waitpid(pid, &status, 0); - if(pid < 0) + if(pid < 0){ printk("run_helper_thread - wait failed, errno = %d\n", - pid); + errno); + pid = -errno; + } if(!WIFEXITED(status) || (WEXITSTATUS(status) != 0)) printk("run_helper_thread - thread returned status " "0x%x\n", status); diff -Nru a/arch/um/kernel/init_task.c b/arch/um/kernel/init_task.c --- a/arch/um/kernel/init_task.c 2004-08-25 22:01:56 -07:00 +++ b/arch/um/kernel/init_task.c 2004-08-25 22:01:56 -07:00 @@ -8,7 +8,6 @@ #include "linux/module.h" #include "linux/sched.h" #include "linux/init_task.h" -#include "linux/version.h" #include "linux/mqueue.h" #include "asm/uaccess.h" #include "asm/pgtable.h" @@ -19,7 +18,7 @@ struct mm_struct init_mm = INIT_MM(init_mm); static struct files_struct init_files = INIT_FILES; static struct signal_struct init_signals = INIT_SIGNALS(init_signals); - +static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); EXPORT_SYMBOL(init_mm); /* @@ -44,24 +43,10 @@ __attribute__((__section__(".data.init_task"))) = { INIT_THREAD_INFO(init_task) }; -struct task_struct *alloc_task_struct(void) -{ - return((struct task_struct *) - __get_free_pages(GFP_KERNEL, CONFIG_KERNEL_STACK_ORDER)); -} - void unprotect_stack(unsigned long stack) { protect_memory(stack, (1 << CONFIG_KERNEL_STACK_ORDER) * PAGE_SIZE, 1, 1, 0, 1); -} - -void free_task_struct(struct task_struct *task) -{ - /* free_pages decrements the page counter and only actually frees - * the pages if they are now not accessed by anything. - */ - free_pages((unsigned long) task, CONFIG_KERNEL_STACK_ORDER); } /* diff -Nru a/arch/um/kernel/initrd_user.c b/arch/um/kernel/initrd_user.c --- a/arch/um/kernel/initrd_user.c 2004-08-25 22:01:54 -07:00 +++ b/arch/um/kernel/initrd_user.c 2004-08-25 22:01:54 -07:00 @@ -6,7 +6,6 @@ #include #include #include -#include #include #include "user_util.h" @@ -19,13 +18,15 @@ { int fd, n; - if((fd = os_open_file(filename, of_read(OPENFLAGS()), 0)) < 0){ - printk("Opening '%s' failed - errno = %d\n", filename, errno); + fd = os_open_file(filename, of_read(OPENFLAGS()), 0); + if(fd < 0){ + printk("Opening '%s' failed - err = %d\n", filename, -fd); return(-1); } - if((n = read(fd, buf, size)) != size){ - printk("Read of %d bytes from '%s' returned %d, errno = %d\n", - size, filename, n, errno); + n = os_read_file(fd, buf, size); + if(n != size){ + printk("Read of %d bytes from '%s' failed, err = %d\n", size, + filename, -n); return(-1); } return(0); diff -Nru a/arch/um/kernel/irq.c b/arch/um/kernel/irq.c --- a/arch/um/kernel/irq.c 2004-08-25 22:01:56 -07:00 +++ b/arch/um/kernel/irq.c 2004-08-25 22:01:56 -07:00 @@ -18,6 +18,7 @@ #include "linux/proc_fs.h" #include "linux/init.h" #include "linux/seq_file.h" +#include "linux/profile.h" #include "asm/irq.h" #include "asm/hw_irq.h" #include "asm/hardirq.h" @@ -29,6 +30,7 @@ #include "user_util.h" #include "kern_util.h" #include "irq_user.h" +#include "irq_kern.h" static void register_irq_proc (unsigned int irq); @@ -83,65 +85,55 @@ end_none }; -/* Not changed */ -volatile unsigned long irq_err_count; - /* * Generic, controller-independent functions: */ -int get_irq_list(char *buf) +int show_interrupts(struct seq_file *p, void *v) { - int i, j; - unsigned long flags; + int i = *(loff_t *) v, j; struct irqaction * action; - char *p = buf; + unsigned long flags; - p += sprintf(p, " "); - for (j=0; jtypename); - p += sprintf(p, " %s", action->name); + seq_printf(p, " %14s", irq_desc[i].handler->typename); + seq_printf(p, " %s", action->name); for (action=action->next; action; action = action->next) - p += sprintf(p, ", %s", action->name); - *p++ = '\n'; - end: + seq_printf(p, ", %s", action->name); + + seq_putc(p, '\n'); +skip: spin_unlock_irqrestore(&irq_desc[i].lock, flags); + } else if (i == NR_IRQS) { + seq_printf(p, "NMI: "); + for (j = 0; j < NR_CPUS; j++) + if (cpu_online(j)) + seq_printf(p, "%10u ", nmi_count(j)); + seq_putc(p, '\n'); } - p += sprintf(p, "\n"); -#ifdef notdef -#ifdef CONFIG_SMP - p += sprintf(p, "LOC: "); - for (j = 0; j < num_online_cpus(); j++) - p += sprintf(p, "%10u ", - apic_timer_irqs[cpu_logical_map(j)]); - p += sprintf(p, "\n"); -#endif -#endif - p += sprintf(p, "ERR: %10lu\n", irq_err_count); - return p - buf; -} - -int show_interrupts(struct seq_file *p, void *v) -{ - return(0); + return 0; } /* @@ -282,13 +274,12 @@ * 0 return value means that this irq is already being * handled by some other CPU. (or is disabled) */ - int cpu = smp_processor_id(); irq_desc_t *desc = irq_desc + irq; struct irqaction * action; unsigned int status; irq_enter(); - kstat_cpu(cpu).irqs[irq]++; + kstat_this_cpu.irqs[irq]++; spin_lock(&desc->lock); desc->handler->ack(irq); /* @@ -385,7 +376,7 @@ */ int request_irq(unsigned int irq, - void (*handler)(int, void *, struct pt_regs *), + irqreturn_t (*handler)(int, void *, struct pt_regs *), unsigned long irqflags, const char * devname, void *dev_id) @@ -433,15 +424,19 @@ EXPORT_SYMBOL(request_irq); int um_request_irq(unsigned int irq, int fd, int type, - void (*handler)(int, void *, struct pt_regs *), + irqreturn_t (*handler)(int, void *, struct pt_regs *), unsigned long irqflags, const char * devname, void *dev_id) { - int retval; + int err; - retval = request_irq(irq, handler, irqflags, devname, dev_id); - if(retval) return(retval); - return(activate_fd(irq, fd, type, dev_id)); + err = request_irq(irq, handler, irqflags, devname, dev_id); + if(err) + return(err); + + if(fd != -1) + err = activate_fd(irq, fd, type, dev_id); + return(err); } /* this was setup_x86_irq but it seems pretty generic */ @@ -474,7 +469,8 @@ */ spin_lock_irqsave(&desc->lock,flags); p = &desc->action; - if ((old = *p) != NULL) { + old = *p; + if (old != NULL) { /* Can't share interrupts unless both agree to */ if (!(old->flags & new->flags & SA_SHIRQ)) { spin_unlock_irqrestore(&desc->lock,flags); @@ -586,12 +582,14 @@ unsigned long count, void *data) { int irq = (long) data, full_count = count, err; - cpumask_t new_value, tmp; + cpumask_t new_value; if (!irq_desc[irq].handler->set_affinity) return -EIO; err = cpumask_parse(buffer, count, new_value); + if(err) + return(err); #ifdef CONFIG_SMP /* @@ -599,9 +597,11 @@ * way to make the system unusable accidentally :-) At least * one online CPU still has to be targeted. */ - cpus_and(tmp, new_value, cpu_online_map); - if (cpus_empty(tmp)) - return -EINVAL; + { cpumask_t tmp; + cpus_and(tmp, new_value, cpu_online_map); + if (cpus_empty(tmp)) + return -EINVAL; + } #endif irq_affinity[irq] = new_value; diff -Nru a/arch/um/kernel/irq_user.c b/arch/um/kernel/irq_user.c --- a/arch/um/kernel/irq_user.c 2004-08-25 22:01:55 -07:00 +++ b/arch/um/kernel/irq_user.c 2004-08-25 22:01:55 -07:00 @@ -6,7 +6,6 @@ #include #include #include -#include #include #include #include @@ -49,7 +48,8 @@ if(smp_sigio_handler()) return; while(1){ - if((n = poll(pollfds, pollfds_num, 0)) < 0){ + n = poll(pollfds, pollfds_num, 0); + if(n < 0){ if(errno == EINTR) continue; printk("sigio_handler : poll returned %d, " "errno = %d\n", n, errno); @@ -366,34 +366,31 @@ void forward_ipi(int fd, int pid) { - if(fcntl(fd, F_SETOWN, pid) < 0){ - int save_errno = errno; - if(fcntl(fd, F_GETOWN, 0) != pid){ - printk("forward_ipi: F_SETOWN failed, fd = %d, " - "me = %d, target = %d, errno = %d\n", fd, - os_getpid(), pid, save_errno); - } - } + int err; + + err = os_set_owner(fd, pid); + if(err < 0) + printk("forward_ipi: set_owner failed, fd = %d, me = %d, " + "target = %d, err = %d\n", fd, os_getpid(), pid, -err); } void forward_interrupts(int pid) { struct irq_fd *irq; unsigned long flags; + int err; flags = irq_lock(); for(irq=active_fds;irq != NULL;irq = irq->next){ - if(fcntl(irq->fd, F_SETOWN, pid) < 0){ - int save_errno = errno; - if(fcntl(irq->fd, F_GETOWN, 0) != pid){ - /* XXX Just remove the irq rather than - * print out an infinite stream of these - */ - printk("Failed to forward %d to pid %d, " - "errno = %d\n", irq->fd, pid, - save_errno); - } + err = os_set_owner(irq->fd, pid); + if(err < 0){ + /* XXX Just remove the irq rather than + * print out an infinite stream of these + */ + printk("Failed to forward %d to pid %d, err = %d\n", + irq->fd, pid, -err); } + irq->pid = pid; } irq_unlock(flags); diff -Nru a/arch/um/kernel/ksyms.c b/arch/um/kernel/ksyms.c --- a/arch/um/kernel/ksyms.c 2004-08-25 22:01:54 -07:00 +++ b/arch/um/kernel/ksyms.c 2004-08-25 22:01:54 -07:00 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) + * Copyright (C) 2001 - 2004 Jeff Dike (jdike@addtoit.com) * Licensed under the GPL */ @@ -8,7 +8,7 @@ #include "linux/string.h" #include "linux/smp_lock.h" #include "linux/spinlock.h" -#include +#include "linux/highmem.h" #include "asm/current.h" #include "asm/delay.h" #include "asm/processor.h" @@ -19,6 +19,7 @@ #include "asm/tlbflush.h" #include "kern_util.h" #include "user_util.h" +#include "mem_user.h" #include "os.h" #include "helper.h" @@ -34,34 +35,66 @@ EXPORT_SYMBOL(flush_tlb_range); EXPORT_SYMBOL(host_task_size); EXPORT_SYMBOL(arch_validate); +EXPORT_SYMBOL(get_kmem_end); -EXPORT_SYMBOL(region_pa); -EXPORT_SYMBOL(region_va); -EXPORT_SYMBOL(phys_mem_map); -EXPORT_SYMBOL(page_mem_map); EXPORT_SYMBOL(page_to_phys); EXPORT_SYMBOL(phys_to_page); EXPORT_SYMBOL(high_physmem); EXPORT_SYMBOL(empty_zero_page); EXPORT_SYMBOL(um_virt_to_phys); +EXPORT_SYMBOL(__virt_to_page); +EXPORT_SYMBOL(to_phys); +EXPORT_SYMBOL(to_virt); EXPORT_SYMBOL(mode_tt); EXPORT_SYMBOL(handle_page_fault); +EXPORT_SYMBOL(find_iomem); +#ifdef CONFIG_MODE_TT +EXPORT_SYMBOL(strncpy_from_user_tt); +EXPORT_SYMBOL(copy_from_user_tt); +EXPORT_SYMBOL(copy_to_user_tt); +#endif + +#ifdef CONFIG_MODE_SKAS +EXPORT_SYMBOL(strncpy_from_user_skas); +EXPORT_SYMBOL(copy_to_user_skas); +EXPORT_SYMBOL(copy_from_user_skas); +#endif + +EXPORT_SYMBOL(os_stat_fd); +EXPORT_SYMBOL(os_stat_file); +EXPORT_SYMBOL(os_access); +EXPORT_SYMBOL(os_print_error); +EXPORT_SYMBOL(os_get_exec_close); +EXPORT_SYMBOL(os_set_exec_close); EXPORT_SYMBOL(os_getpid); EXPORT_SYMBOL(os_open_file); EXPORT_SYMBOL(os_read_file); EXPORT_SYMBOL(os_write_file); EXPORT_SYMBOL(os_seek_file); +EXPORT_SYMBOL(os_lock_file); +EXPORT_SYMBOL(os_ioctl_generic); EXPORT_SYMBOL(os_pipe); EXPORT_SYMBOL(os_file_type); +EXPORT_SYMBOL(os_file_mode); +EXPORT_SYMBOL(os_file_size); +EXPORT_SYMBOL(os_flush_stdout); EXPORT_SYMBOL(os_close_file); +EXPORT_SYMBOL(os_set_fd_async); +EXPORT_SYMBOL(os_set_fd_block); EXPORT_SYMBOL(helper_wait); EXPORT_SYMBOL(os_shutdown_socket); +EXPORT_SYMBOL(os_create_unix_socket); EXPORT_SYMBOL(os_connect_socket); +EXPORT_SYMBOL(os_accept_connection); +EXPORT_SYMBOL(os_rcv_fd); EXPORT_SYMBOL(run_helper); EXPORT_SYMBOL(start_thread); EXPORT_SYMBOL(dump_thread); +EXPORT_SYMBOL(do_gettimeofday); +EXPORT_SYMBOL(do_settimeofday); + /* This is here because UML expands open to sys_open, not to a system * call instruction. */ @@ -90,3 +123,13 @@ EXPORT_SYMBOL(kmap_atomic_to_page); #endif +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff -Nru a/arch/um/kernel/main.c b/arch/um/kernel/main.c --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/arch/um/kernel/main.c 2004-08-25 22:01:56 -07:00 @@ -0,0 +1,230 @@ +/* + * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com) + * Licensed under the GPL + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "user_util.h" +#include "kern_util.h" +#include "mem_user.h" +#include "signal_user.h" +#include "user.h" +#include "init.h" +#include "mode.h" +#include "choose-mode.h" +#include "uml-config.h" + +/* Set in set_stklim, which is called from main and __wrap_malloc. + * __wrap_malloc only calls it if main hasn't started. + */ +unsigned long stacksizelim; + +/* Set in main */ +char *linux_prog; + +#define PGD_BOUND (4 * 1024 * 1024) +#define STACKSIZE (8 * 1024 * 1024) +#define THREAD_NAME_LEN (256) + +static void set_stklim(void) +{ + struct rlimit lim; + + if(getrlimit(RLIMIT_STACK, &lim) < 0){ + perror("getrlimit"); + exit(1); + } + if((lim.rlim_cur == RLIM_INFINITY) || (lim.rlim_cur > STACKSIZE)){ + lim.rlim_cur = STACKSIZE; + if(setrlimit(RLIMIT_STACK, &lim) < 0){ + perror("setrlimit"); + exit(1); + } + } + stacksizelim = (lim.rlim_cur + PGD_BOUND - 1) & ~(PGD_BOUND - 1); +} + +static __init void do_uml_initcalls(void) +{ + initcall_t *call; + + call = &__uml_initcall_start; + while (call < &__uml_initcall_end){; + (*call)(); + call++; + } +} + +static void last_ditch_exit(int sig) +{ + CHOOSE_MODE(kmalloc_ok = 0, (void) 0); + signal(SIGINT, SIG_DFL); + signal(SIGTERM, SIG_DFL); + signal(SIGHUP, SIG_DFL); + uml_cleanup(); + exit(1); +} + +extern int uml_exitcode; + +int main(int argc, char **argv, char **envp) +{ + char **new_argv; + sigset_t mask; + int ret, i; + + /* Enable all signals except SIGIO - in some environments, we can + * enter with some signals blocked + */ + + sigemptyset(&mask); + sigaddset(&mask, SIGIO); + if(sigprocmask(SIG_SETMASK, &mask, NULL) < 0){ + perror("sigprocmask"); + exit(1); + } + +#ifdef UML_CONFIG_MODE_TT + /* Allocate memory for thread command lines */ + if(argc < 2 || strlen(argv[1]) < THREAD_NAME_LEN - 1){ + + char padding[THREAD_NAME_LEN] = { + [ 0 ... THREAD_NAME_LEN - 2] = ' ', '\0' + }; + + new_argv = malloc((argc + 2) * sizeof(char*)); + if(!new_argv) { + perror("Allocating extended argv"); + exit(1); + } + + new_argv[0] = argv[0]; + new_argv[1] = padding; + + for(i = 2; i <= argc; i++) + new_argv[i] = argv[i - 1]; + new_argv[argc + 1] = NULL; + + execvp(new_argv[0], new_argv); + perror("execing with extended args"); + exit(1); + } +#endif + + linux_prog = argv[0]; + + set_stklim(); + + new_argv = malloc((argc + 1) * sizeof(char *)); + if(new_argv == NULL){ + perror("Mallocing argv"); + exit(1); + } + for(i=0;i= uml_physmem) && (addr <= high_physmem)) + kfree(ptr); + else if((addr >= start_vm) && (addr <= end_vm)) + vfree(ptr); + else + __real_free(ptr); + } + else __real_free(ptr); +} + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff -Nru a/arch/um/kernel/mem.c b/arch/um/kernel/mem.c --- a/arch/um/kernel/mem.c 2004-08-25 22:01:55 -07:00 +++ b/arch/um/kernel/mem.c 2004-08-25 22:01:55 -07:00 @@ -1,74 +1,66 @@ /* - * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) + * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com) * Licensed under the GPL */ -#include "linux/config.h" -#include "linux/module.h" -#include "linux/types.h" +#include "linux/stddef.h" +#include "linux/kernel.h" #include "linux/mm.h" -#include "linux/fs.h" -#include "linux/init.h" #include "linux/bootmem.h" #include "linux/swap.h" -#include "linux/slab.h" -#include "linux/vmalloc.h" #include "linux/highmem.h" +#include "linux/gfp.h" #include "asm/page.h" -#include "asm/pgtable.h" +#include "asm/fixmap.h" #include "asm/pgalloc.h" -#include "asm/bitops.h" -#include "asm/uaccess.h" -#include "asm/tlb.h" #include "user_util.h" #include "kern_util.h" -#include "mem_user.h" -#include "mem.h" #include "kern.h" -#include "init.h" -#include "os.h" -#include "mode_kern.h" +#include "mem_user.h" #include "uml_uaccess.h" +#include "os.h" + +extern char __binary_start; /* Changed during early boot */ -pgd_t swapper_pg_dir[1024]; -unsigned long high_physmem; -unsigned long vm_start; -unsigned long vm_end; -unsigned long highmem; unsigned long *empty_zero_page = NULL; unsigned long *empty_bad_page = NULL; - -/* Not modified */ -const char bad_pmd_string[] = "Bad pmd in pte_alloc: %08lx\n"; - -extern char __init_begin, __init_end; -extern long physmem_size; - -/* Not changed by UML */ -DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); - -/* Changed during early boot */ +pgd_t swapper_pg_dir[1024]; +unsigned long highmem; int kmalloc_ok = 0; -#define NREGIONS (phys_region_index(0xffffffff) - phys_region_index(0x0) + 1) -struct mem_region *regions[NREGIONS] = { [ 0 ... NREGIONS - 1 ] = NULL }; -#define REGION_SIZE ((0xffffffff & ~REGION_MASK) + 1) - -/* Changed during early boot */ static unsigned long brk_end; +void unmap_physmem(void) +{ + os_unmap_memory((void *) brk_end, uml_reserved - brk_end); +} + static void map_cb(void *unused) { map_memory(brk_end, __pa(brk_end), uml_reserved - brk_end, 1, 1, 0); } -void unmap_physmem(void) +#ifdef CONFIG_HIGHMEM +static void setup_highmem(unsigned long highmem_start, + unsigned long highmem_len) { - os_unmap_memory((void *) brk_end, uml_reserved - brk_end); -} + struct page *page; + unsigned long highmem_pfn; + int i; -extern char __binary_start; + highmem_start_page = virt_to_page(highmem_start); + + highmem_pfn = __pa(highmem_start) >> PAGE_SHIFT; + for(i = 0; i < highmem_len >> PAGE_SHIFT; i++){ + page = &mem_map[highmem_pfn + i]; + ClearPageReserved(page); + set_bit(PG_highmem, &page->flags); + set_page_count(page, 1); + __free_page(page); + } +} +#endif void mem_init(void) { @@ -103,50 +95,15 @@ totalhigh_pages = highmem >> PAGE_SHIFT; totalram_pages += totalhigh_pages; num_physpages = totalram_pages; - max_mapnr = totalram_pages; max_pfn = totalram_pages; printk(KERN_INFO "Memory: %luk available\n", (unsigned long) nr_free_pages() << (PAGE_SHIFT-10)); kmalloc_ok = 1; -} - -/* Changed during early boot */ -static unsigned long kmem_top = 0; - -unsigned long get_kmem_end(void) -{ - if(kmem_top == 0) - kmem_top = CHOOSE_MODE(kmem_end_tt, kmem_end_skas); - return(kmem_top); -} - -void set_kmem_end(unsigned long new) -{ - kmem_top = new; -} #ifdef CONFIG_HIGHMEM -/* Changed during early boot */ -pte_t *kmap_pte; -pgprot_t kmap_prot; - -EXPORT_SYMBOL(kmap_prot); -EXPORT_SYMBOL(kmap_pte); - -#define kmap_get_fixmap_pte(vaddr) \ - pte_offset_kernel(pmd_offset(pgd_offset_k(vaddr), (vaddr)), (vaddr)) - -void __init kmap_init(void) -{ - unsigned long kmap_vstart; - - /* cache the first kmap pte */ - kmap_vstart = __fix_to_virt(FIX_KMAP_BEGIN); - kmap_pte = kmap_get_fixmap_pte(kmap_vstart); - - kmap_prot = PAGE_KERNEL; + setup_highmem(end_iomem, highmem); +#endif } -#endif /* CONFIG_HIGHMEM */ static void __init fixrange_init(unsigned long start, unsigned long end, pgd_t *pgd_base) @@ -178,76 +135,24 @@ } } -int init_maps(struct mem_region *region) -{ - struct page *p, *map; - int i, n, len; - - if(region == &physmem_region){ - region->mem_map = mem_map; - return(0); - } - else if(region->mem_map != NULL) return(0); - - n = region->len >> PAGE_SHIFT; - len = n * sizeof(struct page); - if(kmalloc_ok){ - map = kmalloc(len, GFP_KERNEL); - if(map == NULL) map = vmalloc(len); - } - else map = alloc_bootmem_low_pages(len); - - if(map == NULL) - return(-ENOMEM); - for(i = 0; i < n; i++){ - p = &map[i]; - set_page_count(p, 0); - SetPageReserved(p); - INIT_LIST_HEAD(&p->list); - } - region->mem_map = map; - return(0); -} +#if CONFIG_HIGHMEM +pte_t *kmap_pte; +pgprot_t kmap_prot; -DECLARE_MUTEX(regions_sem); +#define kmap_get_fixmap_pte(vaddr) \ + pte_offset(pmd_offset(pgd_offset_k(vaddr), (vaddr)), (vaddr)) -static int setup_one_range(int fd, char *driver, unsigned long start, - unsigned long pfn, int len, - struct mem_region *region) +void __init kmap_init(void) { - int i; - - down(®ions_sem); - for(i = 0; i < NREGIONS; i++){ - if(regions[i] == NULL) break; - } - if(i == NREGIONS){ - printk("setup_range : no free regions\n"); - i = -1; - goto out; - } - - if(fd == -1) - fd = create_mem_file(len); + unsigned long kmap_vstart; - if(region == NULL){ - region = alloc_bootmem_low_pages(sizeof(*region)); - if(region == NULL) - panic("Failed to allocating mem_region"); - } + /* cache the first kmap pte */ + kmap_vstart = __fix_to_virt(FIX_KMAP_BEGIN); + kmap_pte = kmap_get_fixmap_pte(kmap_vstart); - *region = ((struct mem_region) { .driver = driver, - .start_pfn = pfn, - .start = start, - .len = len, - .fd = fd } ); - regions[i] = region; - out: - up(®ions_sem); - return(i); + kmap_prot = PAGE_KERNEL; } -#ifdef CONFIG_HIGHMEM static void init_highmem(void) { pgd_t *pgd; @@ -268,63 +173,20 @@ kmap_init(); } - -void setup_highmem(unsigned long len) -{ - struct mem_region *region; - struct page *page, *map; - unsigned long phys; - int i, cur, index; - - phys = physmem_size; - do { - cur = min(len, (unsigned long) REGION_SIZE); - i = setup_one_range(-1, NULL, -1, phys >> PAGE_SHIFT, cur, - NULL); - if(i == -1){ - printk("setup_highmem - setup_one_range failed\n"); - return; - } - region = regions[i]; - index = phys / PAGE_SIZE; - region->mem_map = &mem_map[index]; - - map = region->mem_map; - for(i = 0; i < (cur >> PAGE_SHIFT); i++){ - page = &map[i]; - ClearPageReserved(page); - set_bit(PG_highmem, &page->flags); - set_page_count(page, 1); - __free_page(page); - } - phys += cur; - len -= cur; - } while(len > 0); -} -#endif +#endif /* CONFIG_HIGHMEM */ void paging_init(void) { - struct mem_region *region; - unsigned long zones_size[MAX_NR_ZONES], start, end, vaddr; - int i, index; + unsigned long zones_size[MAX_NR_ZONES], vaddr; + int i; empty_zero_page = (unsigned long *) alloc_bootmem_low_pages(PAGE_SIZE); empty_bad_page = (unsigned long *) alloc_bootmem_low_pages(PAGE_SIZE); for(i=0;i> PAGE_SHIFT) - - (uml_physmem >> PAGE_SHIFT); + zones_size[0] = (end_iomem >> PAGE_SHIFT) - (uml_physmem >> PAGE_SHIFT); zones_size[2] = highmem >> PAGE_SHIFT; free_area_init(zones_size); - start = phys_region_index(__pa(uml_physmem)); - end = phys_region_index(__pa(high_physmem - 1)); - for(i = start; i <= end; i++){ - region = regions[i]; - index = (region->start - uml_physmem) / PAGE_SIZE; - region->mem_map = &mem_map[index]; - if(i > start) free_bootmem(__pa(region->start), region->len); - } /* * Fixed mappings, only the page table structure has to be @@ -335,15 +197,33 @@ #ifdef CONFIG_HIGHMEM init_highmem(); - setup_highmem(highmem); #endif } -pte_t __bad_page(void) +struct page *arch_validate(struct page *page, int mask, int order) { - clear_page(empty_bad_page); - return pte_mkdirty(mk_pte((struct page *) empty_bad_page, - PAGE_SHARED)); + unsigned long addr, zero = 0; + int i; + + again: + if(page == NULL) return(page); + if(PageHighMem(page)) return(page); + + addr = (unsigned long) page_address(page); + for(i = 0; i < (1 << order); i++){ + current->thread.fault_addr = (void *) addr; + if(__do_copy_to_user((void *) addr, &zero, + sizeof(zero), + ¤t->thread.fault_addr, + ¤t->thread.fault_catcher)){ + if(!(mask & __GFP_WAIT)) return(NULL); + else break; + } + addr += PAGE_SIZE; + } + if(i == (1 << order)) return(page); + page = alloc_pages(mask, order); + goto again; } /* This can't do anything because nothing in the kernel image can be freed @@ -400,395 +280,6 @@ printk("%d pages shared\n", shared); printk("%d pages swap cached\n", cached); } - -static int __init uml_mem_setup(char *line, int *add) -{ - char *retptr; - physmem_size = memparse(line,&retptr); - return 0; -} -__uml_setup("mem=", uml_mem_setup, -"mem=\n" -" This controls how much \"physical\" memory the kernel allocates\n" -" for the system. The size is specified as a number followed by\n" -" one of 'k', 'K', 'm', 'M', which have the obvious meanings.\n" -" This is not related to the amount of memory in the physical\n" -" machine. It can be more, and the excess, if it's ever used, will\n" -" just be swapped out.\n Example: mem=64M\n\n" -); - -struct page *arch_validate(struct page *page, int mask, int order) -{ - unsigned long addr, zero = 0; - int i; - - again: - if(page == NULL) return(page); - if(PageHighMem(page)) return(page); - - addr = (unsigned long) page_address(page); - for(i = 0; i < (1 << order); i++){ - current->thread.fault_addr = (void *) addr; - if(__do_copy_to_user((void *) addr, &zero, - sizeof(zero), - ¤t->thread.fault_addr, - ¤t->thread.fault_catcher)){ - if(!(mask & __GFP_WAIT)) return(NULL); - else break; - } - addr += PAGE_SIZE; - } - if(i == (1 << order)) return(page); - page = alloc_pages(mask, order); - goto again; -} - -DECLARE_MUTEX(vm_reserved_sem); -static struct list_head vm_reserved = LIST_HEAD_INIT(vm_reserved); - -/* Static structures, linked in to the list in early boot */ -static struct vm_reserved head = { - .list = LIST_HEAD_INIT(head.list), - .start = 0, - .end = 0xffffffff -}; - -static struct vm_reserved tail = { - .list = LIST_HEAD_INIT(tail.list), - .start = 0, - .end = 0xffffffff -}; - -void set_usable_vm(unsigned long start, unsigned long end) -{ - list_add(&head.list, &vm_reserved); - list_add(&tail.list, &head.list); - head.end = start; - tail.start = end; -} - -int reserve_vm(unsigned long start, unsigned long end, void *e) - -{ - struct vm_reserved *entry = e, *reserved, *prev; - struct list_head *ele; - int err; - - down(&vm_reserved_sem); - list_for_each(ele, &vm_reserved){ - reserved = list_entry(ele, struct vm_reserved, list); - if(reserved->start >= end) goto found; - } - panic("Reserved vm out of range"); - found: - prev = list_entry(ele->prev, struct vm_reserved, list); - if(prev->end > start) - panic("Can't reserve vm"); - if(entry == NULL) - entry = kmalloc(sizeof(*entry), GFP_KERNEL); - if(entry == NULL){ - printk("reserve_vm : Failed to allocate entry\n"); - err = -ENOMEM; - goto out; - } - *entry = ((struct vm_reserved) - { .list = LIST_HEAD_INIT(entry->list), - .start = start, - .end = end }); - list_add(&entry->list, &prev->list); - err = 0; - out: - up(&vm_reserved_sem); - return(0); -} - -unsigned long get_vm(unsigned long len) -{ - struct vm_reserved *this, *next; - struct list_head *ele; - unsigned long start; - int err; - - down(&vm_reserved_sem); - list_for_each(ele, &vm_reserved){ - this = list_entry(ele, struct vm_reserved, list); - next = list_entry(ele->next, struct vm_reserved, list); - if((this->start < next->start) && - (this->end + len + PAGE_SIZE <= next->start)) - goto found; - } - up(&vm_reserved_sem); - return(0); - found: - up(&vm_reserved_sem); - start = (unsigned long) UML_ROUND_UP(this->end) + PAGE_SIZE; - err = reserve_vm(start, start + len, NULL); - if(err) return(0); - return(start); -} - -int nregions(void) -{ - return(NREGIONS); -} - -void setup_range(int fd, char *driver, unsigned long start, unsigned long pfn, - unsigned long len, int need_vm, struct mem_region *region, - void *reserved) -{ - int i, cur; - - do { - cur = min(len, (unsigned long) REGION_SIZE); - i = setup_one_range(fd, driver, start, pfn, cur, region); - region = regions[i]; - if(need_vm && setup_region(region, reserved)){ - kfree(region); - regions[i] = NULL; - return; - } - start += cur; - if(pfn != -1) pfn += cur; - len -= cur; - } while(len > 0); -} - -struct iomem { - char *name; - int fd; - unsigned long size; -}; - -/* iomem regions can only be added on the command line at the moment. - * Locking will be needed when they can be added via mconsole. - */ - -struct iomem iomem_regions[NREGIONS] = { [ 0 ... NREGIONS - 1 ] = - { .name = NULL, - .fd = -1, - .size = 0 } }; - -int num_iomem_regions = 0; - -void add_iomem(char *name, int fd, unsigned long size) -{ - if(num_iomem_regions == sizeof(iomem_regions)/sizeof(iomem_regions[0])) - return; - size = (size + PAGE_SIZE - 1) & PAGE_MASK; - iomem_regions[num_iomem_regions++] = - ((struct iomem) { .name = name, - .fd = fd, - .size = size } ); -} - -int setup_iomem(void) -{ - struct iomem *iomem; - int i; - - for(i = 0; i < num_iomem_regions; i++){ - iomem = &iomem_regions[i]; - setup_range(iomem->fd, iomem->name, -1, -1, iomem->size, 1, - NULL, NULL); - } - return(0); -} - -__initcall(setup_iomem); - -#define PFN_UP(x) (((x) + PAGE_SIZE-1) >> PAGE_SHIFT) -#define PFN_DOWN(x) ((x) >> PAGE_SHIFT) - -/* Changed during early boot */ -static struct mem_region physmem_region; -static struct vm_reserved physmem_reserved; - -void setup_physmem(unsigned long start, unsigned long reserve_end, - unsigned long len) -{ - struct mem_region *region = &physmem_region; - struct vm_reserved *reserved = &physmem_reserved; - unsigned long cur, pfn = 0; - int do_free = 1, bootmap_size; - - do { - cur = min(len, (unsigned long) REGION_SIZE); - if(region == NULL) - region = alloc_bootmem_low_pages(sizeof(*region)); - if(reserved == NULL) - reserved = alloc_bootmem_low_pages(sizeof(*reserved)); - if((region == NULL) || (reserved == NULL)) - panic("Couldn't allocate physmem region or vm " - "reservation\n"); - setup_range(-1, NULL, start, pfn, cur, 1, region, reserved); - - if(do_free){ - unsigned long reserve = reserve_end - start; - int pfn = PFN_UP(__pa(reserve_end)); - int delta = (len - reserve) >> PAGE_SHIFT; - - bootmap_size = init_bootmem(pfn, pfn + delta); - free_bootmem(__pa(reserve_end) + bootmap_size, - cur - bootmap_size - reserve); - do_free = 0; - } - start += cur; - pfn += cur >> PAGE_SHIFT; - len -= cur; - region = NULL; - reserved = NULL; - } while(len > 0); -} - -struct mem_region *phys_region(unsigned long phys) -{ - unsigned int n = phys_region_index(phys); - - if(regions[n] == NULL) - panic("Physical address in uninitialized region"); - return(regions[n]); -} - -unsigned long phys_offset(unsigned long phys) -{ - return(phys_addr(phys)); -} - -struct page *phys_mem_map(unsigned long phys) -{ - return((struct page *) phys_region(phys)->mem_map); -} - -struct page *pte_mem_map(pte_t pte) -{ - return(phys_mem_map(pte_val(pte))); -} - -struct mem_region *page_region(struct page *page, int *index_out) -{ - int i; - struct mem_region *region; - struct page *map; - - for(i = 0; i < NREGIONS; i++){ - region = regions[i]; - if(region == NULL) continue; - map = region->mem_map; - if((page >= map) && (page < &map[region->len >> PAGE_SHIFT])){ - if(index_out != NULL) *index_out = i; - return(region); - } - } - panic("No region found for page"); - return(NULL); -} - -unsigned long page_to_pfn(struct page *page) -{ - struct mem_region *region = page_region(page, NULL); - - return(region->start_pfn + (page - (struct page *) region->mem_map)); -} - -struct mem_region *pfn_to_region(unsigned long pfn, int *index_out) -{ - struct mem_region *region; - int i; - - for(i = 0; i < NREGIONS; i++){ - region = regions[i]; - if(region == NULL) - continue; - - if((region->start_pfn <= pfn) && - (region->start_pfn + (region->len >> PAGE_SHIFT) > pfn)){ - if(index_out != NULL) - *index_out = i; - return(region); - } - } - return(NULL); -} - -struct page *pfn_to_page(unsigned long pfn) -{ - struct mem_region *region = pfn_to_region(pfn, NULL); - struct page *mem_map = (struct page *) region->mem_map; - - return(&mem_map[pfn - region->start_pfn]); -} - -unsigned long phys_to_pfn(unsigned long p) -{ - struct mem_region *region = regions[phys_region_index(p)]; - - return(region->start_pfn + (phys_addr(p) >> PAGE_SHIFT)); -} - -unsigned long pfn_to_phys(unsigned long pfn) -{ - int n; - struct mem_region *region = pfn_to_region(pfn, &n); - - return(mk_phys((pfn - region->start_pfn) << PAGE_SHIFT, n)); -} - -struct page *page_mem_map(struct page *page) -{ - return((struct page *) page_region(page, NULL)->mem_map); -} - -extern unsigned long region_pa(void *virt) -{ - struct mem_region *region; - unsigned long addr = (unsigned long) virt; - int i; - - for(i = 0; i < NREGIONS; i++){ - region = regions[i]; - if(region == NULL) continue; - if((region->start <= addr) && - (addr <= region->start + region->len)) - return(mk_phys(addr - region->start, i)); - } - panic("region_pa : no region for virtual address"); - return(0); -} - -extern void *region_va(unsigned long phys) -{ - return((void *) (phys_region(phys)->start + phys_addr(phys))); -} - -unsigned long page_to_phys(struct page *page) -{ - int n; - struct mem_region *region = page_region(page, &n); - struct page *map = region->mem_map; - return(mk_phys((page - map) << PAGE_SHIFT, n)); -} - -struct page *phys_to_page(unsigned long phys) -{ - struct page *mem_map; - - mem_map = phys_mem_map(phys); - return(mem_map + (phys_offset(phys) >> PAGE_SHIFT)); -} - -static int setup_mem_maps(void) -{ - struct mem_region *region; - int i; - - for(i = 0; i < NREGIONS; i++){ - region = regions[i]; - if((region != NULL) && (region->fd > 0)) init_maps(region); - } - return(0); -} - -__initcall(setup_mem_maps); /* * Allocate and free page tables. diff -Nru a/arch/um/kernel/mem_user.c b/arch/um/kernel/mem_user.c --- a/arch/um/kernel/mem_user.c 2004-08-25 22:01:55 -07:00 +++ b/arch/um/kernel/mem_user.c 2004-08-25 22:01:55 -07:00 @@ -34,10 +34,9 @@ #include #include #include -#include #include #include -#include +#include #include #include #include "kern_util.h" @@ -47,105 +46,145 @@ #include "init.h" #include "os.h" #include "tempfile.h" +#include "kern_constants.h" extern struct mem_region physmem_region; #define TEMPNAME_TEMPLATE "vm_file-XXXXXX" -int create_mem_file(unsigned long len) +static int create_tmp_file(unsigned long len) { - int fd; + int fd, err; char zero; fd = make_tempfile(TEMPNAME_TEMPLATE, NULL, 1); - if (fchmod(fd, 0777) < 0){ - perror("fchmod"); + if(fd < 0) { + os_print_error(fd, "make_tempfile"); + exit(1); + } + + err = os_mode_fd(fd, 0777); + if(err < 0){ + os_print_error(err, "os_mode_fd"); exit(1); } - if(os_seek_file(fd, len) < 0){ - perror("lseek"); + err = os_seek_file(fd, len); + if(err < 0){ + os_print_error(err, "os_seek_file"); exit(1); } zero = 0; - if(write(fd, &zero, 1) != 1){ - perror("write"); + err = os_write_file(fd, &zero, 1); + if(err != 1){ + os_print_error(err, "os_write_file"); exit(1); } - if(fcntl(fd, F_SETFD, 1) != 0) - perror("Setting FD_CLOEXEC failed"); + return(fd); } -int setup_region(struct mem_region *region, void *entry) +static int have_devanon = 0; + +void check_devanon(void) +{ + int fd; + + printk("Checking for /dev/anon on the host..."); + fd = open("/dev/anon", O_RDWR); + if(fd < 0){ + printk("Not available (open failed with errno %d)\n", errno); + return; + } + + printk("OK\n"); + have_devanon = 1; +} + +static int create_anon_file(unsigned long len) { - void *loc, *start; - char *driver; - int err, offset; - - if(region->start != -1){ - err = reserve_vm(region->start, - region->start + region->len, entry); - if(err){ - printk("setup_region : failed to reserve " - "0x%x - 0x%x for driver '%s'\n", - region->start, - region->start + region->len, - region->driver); - return(-1); - } - } - else region->start = get_vm(region->len); - if(region->start == 0){ - if(region->driver == NULL) driver = "physmem"; - else driver = region->driver; - printk("setup_region : failed to find vm for " - "driver '%s' (length %d)\n", driver, region->len); - return(-1); - } - if(region->start == uml_physmem){ - start = (void *) uml_reserved; - offset = uml_reserved - uml_physmem; - } - else { - start = (void *) region->start; - offset = 0; - } - - loc = mmap(start, region->len - offset, PROT_READ | PROT_WRITE, - MAP_SHARED | MAP_FIXED, region->fd, offset); - if(loc != start){ - perror("Mapping memory"); + void *addr; + int fd; + + fd = open("/dev/anon", O_RDWR); + if(fd < 0) { + os_print_error(fd, "opening /dev/anon"); exit(1); } - return(0); + + addr = mmap(NULL, len, PROT_READ | PROT_WRITE , MAP_PRIVATE, fd, 0); + if(addr == MAP_FAILED){ + os_print_error((int) addr, "mapping physmem file"); + exit(1); + } + munmap(addr, len); + + return(fd); +} + +int create_mem_file(unsigned long len) +{ + int err, fd; + + if(have_devanon) + fd = create_anon_file(len); + else fd = create_tmp_file(len); + + err = os_set_exec_close(fd, 1); + if(err < 0) + os_print_error(err, "exec_close"); + return(fd); } +struct iomem_region *iomem_regions = NULL; +int iomem_size = 0; + static int __init parse_iomem(char *str, int *add) { - struct stat buf; + struct iomem_region *new; + struct uml_stat buf; char *file, *driver; - int fd; + int fd, err; driver = str; file = strchr(str,','); if(file == NULL){ - printk("parse_iomem : failed to parse iomem\n"); - return(1); + printf("parse_iomem : failed to parse iomem\n"); + goto out; } *file = '\0'; file++; fd = os_open_file(file, of_rdwr(OPENFLAGS()), 0); if(fd < 0){ - printk("parse_iomem - Couldn't open io file, errno = %d\n", - errno); - return(1); - } - if(fstat(fd, &buf) < 0) { - printk("parse_iomem - cannot fstat file, errno = %d\n", errno); - return(1); + os_print_error(fd, "parse_iomem - Couldn't open io file"); + goto out; } - add_iomem(driver, fd, buf.st_size); + + err = os_stat_fd(fd, &buf); + if(err < 0){ + os_print_error(err, "parse_iomem - cannot stat_fd file"); + goto out_close; + } + + new = malloc(sizeof(*new)); + if(new == NULL){ + perror("Couldn't allocate iomem_region struct"); + goto out_close; + } + + *new = ((struct iomem_region) { .next = iomem_regions, + .driver = driver, + .fd = fd, + .size = buf.ust_size, + .phys = 0, + .virt = 0 }); + iomem_regions = new; + iomem_size += new->size + UM_KERN_PAGE_SIZE; + return(0); + out_close: + os_close_file(fd); + out: + return(1); } __uml_setup("iomem=", parse_iomem, @@ -153,71 +192,18 @@ " Configure as an IO memory region named .\n\n" ); -#ifdef notdef -int logging = 0; -int logging_fd = -1; - -int logging_line = 0; -char logging_buf[256]; - -void log(char *fmt, ...) -{ - va_list ap; - struct timeval tv; - struct openflags flags; - - if(logging == 0) return; - if(logging_fd < 0){ - flags = of_create(of_trunc(of_rdrw(OPENFLAGS()))); - logging_fd = os_open_file("log", flags, 0644); - } - gettimeofday(&tv, NULL); - sprintf(logging_buf, "%d\t %u.%u ", logging_line++, tv.tv_sec, - tv.tv_usec); - va_start(ap, fmt); - vsprintf(&logging_buf[strlen(logging_buf)], fmt, ap); - va_end(ap); - write(logging_fd, logging_buf, strlen(logging_buf)); -} -#endif - -int map_memory(unsigned long virt, unsigned long phys, unsigned long len, - int r, int w, int x) -{ - struct mem_region *region = phys_region(phys); - - return(os_map_memory((void *) virt, region->fd, phys_offset(phys), len, - r, w, x)); -} - int protect_memory(unsigned long addr, unsigned long len, int r, int w, int x, int must_succeed) { - if(os_protect_memory((void *) addr, len, r, w, x) < 0){ + int err; + + err = os_protect_memory((void *) addr, len, r, w, x); + if(err < 0){ if(must_succeed) - panic("protect failed, errno = %d", errno); - else return(-errno); + panic("protect failed, err = %d", -err); + else return(err); } return(0); -} - -unsigned long find_iomem(char *driver, unsigned long *len_out) -{ - struct mem_region *region; - int i, n; - - n = nregions(); - for(i = 0; i < n; i++){ - region = regions[i]; - if(region == NULL) continue; - if((region->driver != NULL) && - !strcmp(region->driver, driver)){ - *len_out = region->len; - return(region->start); - } - } - *len_out = 0; - return 0; } /* diff -Nru a/arch/um/kernel/physmem.c b/arch/um/kernel/physmem.c --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/arch/um/kernel/physmem.c 2004-08-25 22:01:56 -07:00 @@ -0,0 +1,468 @@ +/* + * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com) + * Licensed under the GPL + */ + +#include "linux/mm.h" +#include "linux/ghash.h" +#include "linux/slab.h" +#include "linux/vmalloc.h" +#include "linux/bootmem.h" +#include "asm/types.h" +#include "asm/pgtable.h" +#include "kern_util.h" +#include "user_util.h" +#include "mode_kern.h" +#include "mem.h" +#include "mem_user.h" +#include "os.h" +#include "kern.h" +#include "init.h" + +#if 0 +static pgd_t physmem_pgd[PTRS_PER_PGD]; + +static struct phys_desc *lookup_mapping(void *addr) +{ + pgd = &physmem_pgd[pgd_index(addr)]; + if(pgd_none(pgd)) + return(NULL); + + pmd = pmd_offset(pgd, addr); + if(pmd_none(pmd)) + return(NULL); + + pte = pte_offset_kernel(pmd, addr); + return((struct phys_desc *) pte_val(pte)); +} + +static struct add_mapping(void *addr, struct phys_desc *new) +{ +} +#endif + +#define PHYS_HASHSIZE (8192) + +struct phys_desc; + +DEF_HASH_STRUCTS(virtmem, PHYS_HASHSIZE, struct phys_desc); + +struct phys_desc { + struct virtmem_ptrs virt_ptrs; + int fd; + __u64 offset; + void *virt; + unsigned long phys; + struct list_head list; +}; + +struct virtmem_table virtmem_hash; + +static int virt_cmp(void *virt1, void *virt2) +{ + return(virt1 != virt2); +} + +static int virt_hash(void *virt) +{ + unsigned long addr = ((unsigned long) virt) >> PAGE_SHIFT; + return(addr % PHYS_HASHSIZE); +} + +DEF_HASH(static, virtmem, struct phys_desc, virt_ptrs, void *, virt, virt_cmp, + virt_hash); + +LIST_HEAD(descriptor_mappings); + +struct desc_mapping { + int fd; + struct list_head list; + struct list_head pages; +}; + +static struct desc_mapping *find_mapping(int fd) +{ + struct desc_mapping *desc; + struct list_head *ele; + + list_for_each(ele, &descriptor_mappings){ + desc = list_entry(ele, struct desc_mapping, list); + if(desc->fd == fd) + return(desc); + } + + return(NULL); +} + +static struct desc_mapping *descriptor_mapping(int fd) +{ + struct desc_mapping *desc; + + desc = find_mapping(fd); + if(desc != NULL) + return(desc); + + desc = kmalloc(sizeof(*desc), GFP_ATOMIC); + if(desc == NULL) + return(NULL); + + *desc = ((struct desc_mapping) + { .fd = fd, + .list = LIST_HEAD_INIT(desc->list), + .pages = LIST_HEAD_INIT(desc->pages) }); + list_add(&desc->list, &descriptor_mappings); + + return(desc); +} + +int physmem_subst_mapping(void *virt, int fd, __u64 offset, int w) +{ + struct desc_mapping *fd_maps; + struct phys_desc *desc; + unsigned long phys; + int err; + + fd_maps = descriptor_mapping(fd); + if(fd_maps == NULL) + return(-ENOMEM); + + phys = __pa(virt); + if(find_virtmem_hash(&virtmem_hash, virt) != NULL) + panic("Address 0x%p is already substituted\n", virt); + + err = -ENOMEM; + desc = kmalloc(sizeof(*desc), GFP_ATOMIC); + if(desc == NULL) + goto out; + + *desc = ((struct phys_desc) + { .virt_ptrs = { NULL, NULL }, + .fd = fd, + .offset = offset, + .virt = virt, + .phys = __pa(virt), + .list = LIST_HEAD_INIT(desc->list) }); + insert_virtmem_hash(&virtmem_hash, desc); + + list_add(&desc->list, &fd_maps->pages); + + virt = (void *) ((unsigned long) virt & PAGE_MASK); + err = os_map_memory(virt, fd, offset, PAGE_SIZE, 1, w, 0); + if(!err) + goto out; + + remove_virtmem_hash(&virtmem_hash, desc); + kfree(desc); + out: + return(err); +} + +static int physmem_fd = -1; + +static void remove_mapping(struct phys_desc *desc) +{ + void *virt = desc->virt; + int err; + + remove_virtmem_hash(&virtmem_hash, desc); + list_del(&desc->list); + kfree(desc); + + err = os_map_memory(virt, physmem_fd, __pa(virt), PAGE_SIZE, 1, 1, 0); + if(err) + panic("Failed to unmap block device page from physical memory, " + "errno = %d", -err); +} + +int physmem_remove_mapping(void *virt) +{ + struct phys_desc *desc; + + virt = (void *) ((unsigned long) virt & PAGE_MASK); + desc = find_virtmem_hash(&virtmem_hash, virt); + if(desc == NULL) + return(0); + + remove_mapping(desc); + return(1); +} + +void physmem_forget_descriptor(int fd) +{ + struct desc_mapping *desc; + struct phys_desc *page; + struct list_head *ele, *next; + __u64 offset; + void *addr; + int err; + + desc = find_mapping(fd); + if(desc == NULL) + return; + + list_for_each_safe(ele, next, &desc->pages){ + page = list_entry(ele, struct phys_desc, list); + offset = page->offset; + addr = page->virt; + remove_mapping(page); + err = os_seek_file(fd, offset); + if(err) + panic("physmem_forget_descriptor - failed to seek " + "to %lld in fd %d, error = %d\n", + offset, fd, -err); + err = os_read_file(fd, addr, PAGE_SIZE); + if(err < 0) + panic("physmem_forget_descriptor - failed to read " + "from fd %d to 0x%p, error = %d\n", + fd, addr, -err); + } + + list_del(&desc->list); + kfree(desc); +} + +void arch_free_page(struct page *page, int order) +{ + void *virt; + int i; + + for(i = 0; i < (1 << order); i++){ + virt = __va(page_to_phys(page + i)); + physmem_remove_mapping(virt); + } +} + +int is_remapped(void *virt) +{ + return(find_virtmem_hash(&virtmem_hash, virt) != NULL); +} + +/* Changed during early boot */ +unsigned long high_physmem; + +extern unsigned long physmem_size; + +void *to_virt(unsigned long phys) +{ + return((void *) uml_physmem + phys); +} + +unsigned long to_phys(void *virt) +{ + return(((unsigned long) virt) - uml_physmem); +} + +int init_maps(unsigned long physmem, unsigned long iomem, unsigned long highmem) +{ + struct page *p, *map; + unsigned long phys_len, phys_pages, highmem_len, highmem_pages; + unsigned long iomem_len, iomem_pages, total_len, total_pages; + int i; + + phys_pages = physmem >> PAGE_SHIFT; + phys_len = phys_pages * sizeof(struct page); + + iomem_pages = iomem >> PAGE_SHIFT; + iomem_len = iomem_pages * sizeof(struct page); + + highmem_pages = highmem >> PAGE_SHIFT; + highmem_len = highmem_pages * sizeof(struct page); + + total_pages = phys_pages + iomem_pages + highmem_pages; + total_len = phys_len + iomem_pages + highmem_len; + + if(kmalloc_ok){ + map = kmalloc(total_len, GFP_KERNEL); + if(map == NULL) + map = vmalloc(total_len); + } + else map = alloc_bootmem_low_pages(total_len); + + if(map == NULL) + return(-ENOMEM); + + for(i = 0; i < total_pages; i++){ + p = &map[i]; + set_page_count(p, 0); + SetPageReserved(p); + INIT_LIST_HEAD(&p->lru); + } + + mem_map = map; + max_mapnr = total_pages; + return(0); +} + +struct page *phys_to_page(const unsigned long phys) +{ + return(&mem_map[phys >> PAGE_SHIFT]); +} + +struct page *__virt_to_page(const unsigned long virt) +{ + return(&mem_map[__pa(virt) >> PAGE_SHIFT]); +} + +unsigned long page_to_phys(struct page *page) +{ + return((page - mem_map) << PAGE_SHIFT); +} + +pte_t mk_pte(struct page *page, pgprot_t pgprot) +{ + pte_t pte; + + pte_val(pte) = page_to_phys(page) + pgprot_val(pgprot); + if(pte_present(pte)) pte_mknewprot(pte_mknewpage(pte)); + return(pte); +} + +/* Changed during early boot */ +static unsigned long kmem_top = 0; + +unsigned long get_kmem_end(void) +{ + if(kmem_top == 0) + kmem_top = CHOOSE_MODE(kmem_end_tt, kmem_end_skas); + return(kmem_top); +} + +void map_memory(unsigned long virt, unsigned long phys, unsigned long len, + int r, int w, int x) +{ + __u64 offset; + int fd, err; + + fd = phys_mapping(phys, &offset); + err = os_map_memory((void *) virt, fd, offset, len, r, w, x); + if(err) + panic("map_memory(0x%lx, %d, 0x%llx, %ld, %d, %d, %d) failed, " + "err = %d\n", virt, fd, offset, len, r, w, x, err); +} + +#define PFN_UP(x) (((x) + PAGE_SIZE-1) >> PAGE_SHIFT) + +void setup_physmem(unsigned long start, unsigned long reserve_end, + unsigned long len, unsigned long highmem) +{ + unsigned long reserve = reserve_end - start; + int pfn = PFN_UP(__pa(reserve_end)); + int delta = (len - reserve) >> PAGE_SHIFT; + int err, offset, bootmap_size; + + physmem_fd = create_mem_file(len + highmem); + + offset = uml_reserved - uml_physmem; + err = os_map_memory((void *) uml_reserved, physmem_fd, offset, + len - offset, 1, 1, 0); + if(err < 0){ + os_print_error(err, "Mapping memory"); + exit(1); + } + + bootmap_size = init_bootmem(pfn, pfn + delta); + free_bootmem(__pa(reserve_end) + bootmap_size, + len - bootmap_size - reserve); +} + +int phys_mapping(unsigned long phys, __u64 *offset_out) +{ + struct phys_desc *desc = find_virtmem_hash(&virtmem_hash, + __va(phys & PAGE_MASK)); + int fd = -1; + + if(desc != NULL){ + fd = desc->fd; + *offset_out = desc->offset; + } + else if(phys < physmem_size){ + fd = physmem_fd; + *offset_out = phys; + } + else if(phys < __pa(end_iomem)){ + struct iomem_region *region = iomem_regions; + + while(region != NULL){ + if((phys >= region->phys) && + (phys < region->phys + region->size)){ + fd = region->fd; + *offset_out = phys - region->phys; + break; + } + region = region->next; + } + } + else if(phys < __pa(end_iomem) + highmem){ + fd = physmem_fd; + *offset_out = phys - iomem_size; + } + + return(fd); +} + +static int __init uml_mem_setup(char *line, int *add) +{ + char *retptr; + physmem_size = memparse(line,&retptr); + return 0; +} +__uml_setup("mem=", uml_mem_setup, +"mem=\n" +" This controls how much \"physical\" memory the kernel allocates\n" +" for the system. The size is specified as a number followed by\n" +" one of 'k', 'K', 'm', 'M', which have the obvious meanings.\n" +" This is not related to the amount of memory in the host. It can\n" +" be more, and the excess, if it's ever used, will just be swapped out.\n" +" Example: mem=64M\n\n" +); + +unsigned long find_iomem(char *driver, unsigned long *len_out) +{ + struct iomem_region *region = iomem_regions; + + while(region != NULL){ + if(!strcmp(region->driver, driver)){ + *len_out = region->size; + return(region->virt); + } + } + + return(0); +} + +int setup_iomem(void) +{ + struct iomem_region *region = iomem_regions; + unsigned long iomem_start = high_physmem + PAGE_SIZE; + int err; + + while(region != NULL){ + err = os_map_memory((void *) iomem_start, region->fd, 0, + region->size, 1, 1, 0); + if(err) + printk("Mapping iomem region for driver '%s' failed, " + "errno = %d\n", region->driver, -err); + else { + region->virt = iomem_start; + region->phys = __pa(region->virt); + } + + iomem_start += region->size + PAGE_SIZE; + region = region->next; + } + + return(0); +} + +__initcall(setup_iomem); + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff -Nru a/arch/um/kernel/process.c b/arch/um/kernel/process.c --- a/arch/um/kernel/process.c 2004-08-25 22:01:56 -07:00 +++ b/arch/um/kernel/process.c 2004-08-25 22:01:56 -07:00 @@ -9,18 +9,17 @@ #include #include #include -#include #include #include #include #include -#include #include #include #include #include #include #include +#include #include "user_util.h" #include "kern_util.h" #include "user.h" @@ -58,7 +57,11 @@ { int flags = altstack ? SA_ONSTACK : 0; - set_handler(SIGSEGV, (__sighandler_t) sig_handler, flags, + /* NODEFER is set here because SEGV isn't turned back on when the + * handler is ready to receive signals. This causes any segfault + * during a copy_user to kill the process because the fault is blocked. + */ + set_handler(SIGSEGV, (__sighandler_t) sig_handler, flags | SA_NODEFER, SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1); set_handler(SIGTRAP, (__sighandler_t) sig_handler, flags, SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1); @@ -72,7 +75,6 @@ SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1); set_handler(SIGUSR2, (__sighandler_t) sig_handler, SA_NOMASK | flags, -1); - (void) CHOOSE_MODE(signal(SIGCHLD, SIG_IGN), (void *) 0); signal(SIGHUP, SIG_IGN); init_irq_signals(altstack); @@ -122,12 +124,17 @@ /* Start the process and wait for it to kill itself */ new_pid = clone(outer_tramp, (void *) sp, clone_flags, &arg); - if(new_pid < 0) return(-errno); - while((err = waitpid(new_pid, &status, 0) < 0) && (errno == EINTR)) ; - if(err < 0) panic("Waiting for outer trampoline failed - errno = %d", - errno); + if(new_pid < 0) + return(new_pid); + + CATCH_EINTR(err = waitpid(new_pid, &status, 0)); + if(err < 0) + panic("Waiting for outer trampoline failed - errno = %d", + errno); + if(!WIFSIGNALED(status) || (WTERMSIG(status) != SIGKILL)) - panic("outer trampoline didn't exit with SIGKILL"); + panic("outer trampoline didn't exit with SIGKILL, " + "status = %d", status); return(arg.pid); } @@ -138,7 +145,7 @@ os_stop_process(os_getpid()); - if(read(fd, &c, sizeof(c)) != sizeof(c)) + if(os_read_file(fd, &c, sizeof(c)) != sizeof(c)) panic("read failed in suspend_new_thread"); } @@ -168,7 +175,7 @@ pid = clone(ptrace_child, (void *) sp, SIGCHLD, NULL); if(pid < 0) panic("check_ptrace : clone failed, errno = %d", errno); - n = waitpid(pid, &status, WUNTRACED); + CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED)); if(n < 0) panic("check_ptrace : wait failed, errno = %d", errno); if(!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGSTOP)) @@ -185,7 +192,7 @@ if(ptrace(PTRACE_CONT, pid, 0, 0) < 0) panic("check_ptrace : ptrace failed, errno = %d", errno); - n = waitpid(pid, &status, 0); + CATCH_EINTR(n = waitpid(pid, &status, 0)); if(!WIFEXITED(status) || (WEXITSTATUS(status) != exitcode)) panic("check_ptrace : child exited with status 0x%x", status); @@ -193,6 +200,66 @@ panic("check_ptrace : munmap failed, errno = %d", errno); } +static int force_sysemu_disabled = 0; + +static int __init nosysemu_cmd_param(char *str, int* add) +{ + force_sysemu_disabled = 1; + return 0; +} + +__uml_setup("nosysemu", nosysemu_cmd_param, + "nosysemu\n" + " Turns off syscall emulation patch for ptrace (SYSEMU) on.\n" + " SYSEMU is a performance-patch introduced by Laurent Vivier. It changes\n" + " behaviour of ptrace() and helps reducing host context switch rate.\n" + " To make it working, you need a kernel patch for your host, too.\n" + " See http://perso.wanadoo.fr/laurent.vivier/UML/ for further information.\n"); + +static void __init check_sysemu(void) +{ + void *stack; + int pid, n, status; + + if (mode_tt) + return; + + printk("Checking syscall emulation patch for ptrace..."); + sysemu_supported = 0; + pid = start_ptraced_child(&stack); + if(ptrace(PTRACE_SYSEMU, pid, 0, 0) >= 0) { + struct user_regs_struct regs; + + CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED)); + if (n < 0) + panic("check_ptrace : wait failed, errno = %d", errno); + if(!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGTRAP)) + panic("check_ptrace : expected SIGTRAP, " + "got status = %d", status); + + if (ptrace(PTRACE_GETREGS, pid, 0, ®s) < 0) + panic("check_ptrace : failed to read child " + "registers, errno = %d", errno); + regs.orig_eax = pid; + if (ptrace(PTRACE_SETREGS, pid, 0, ®s) < 0) + panic("check_ptrace : failed to modify child " + "registers, errno = %d", errno); + + stop_ptraced_child(pid, stack, 0); + + sysemu_supported = 1; + printk("found\n"); + } + else + { + stop_ptraced_child(pid, stack, 1); + sysemu_supported = 0; + printk("missing\n"); + } + + set_using_sysemu(!force_sysemu_disabled); +} + void __init check_ptrace(void) { void *stack; @@ -205,7 +272,7 @@ if(ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0) panic("check_ptrace : ptrace failed, errno = %d", errno); - n = waitpid(pid, &status, WUNTRACED); + CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED)); if(n < 0) panic("check_ptrace : wait failed, errno = %d", errno); if(!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGTRAP)) @@ -225,6 +292,7 @@ } stop_ptraced_child(pid, stack, 0); printk("OK\n"); + check_sysemu(); } int run_kernel_thread(int (*fn)(void *), void *arg, void **jmp_ptr) @@ -233,7 +301,7 @@ int n; *jmp_ptr = &buf; - n = setjmp(buf); + n = sigsetjmp(buf, 1); if(n != 0) return(n); (*fn)(arg); @@ -273,7 +341,7 @@ stop_ptraced_child(pid, stack, 1); printf("Checking for /proc/mm..."); - if(access("/proc/mm", W_OK)){ + if(os_access("/proc/mm", OS_ACC_W_OK) < 0){ printf("not found\n"); ret = 0; } diff -Nru a/arch/um/kernel/process_kern.c b/arch/um/kernel/process_kern.c --- a/arch/um/kernel/process_kern.c 2004-08-25 22:01:55 -07:00 +++ b/arch/um/kernel/process_kern.c 2004-08-25 22:01:55 -07:00 @@ -16,6 +16,8 @@ #include "linux/module.h" #include "linux/init.h" #include "linux/capability.h" +#include "linux/vmalloc.h" +#include "linux/spinlock.h" #include "asm/unistd.h" #include "asm/mman.h" #include "asm/segment.h" @@ -23,7 +25,6 @@ #include "asm/pgtable.h" #include "asm/processor.h" #include "asm/tlbflush.h" -#include "asm/spinlock.h" #include "asm/uaccess.h" #include "asm/user.h" #include "user_util.h" @@ -52,17 +53,12 @@ struct task_struct *get_task(int pid, int require) { - struct task_struct *task, *ret; + struct task_struct *ret; - ret = NULL; read_lock(&tasklist_lock); - for_each_process(task){ - if(task->pid == pid){ - ret = task; - break; - } - } + ret = find_task_by_pid(pid); read_unlock(&tasklist_lock); + if(require && (ret == NULL)) panic("get_task couldn't find a task\n"); return(ret); } @@ -95,7 +91,8 @@ int flags = GFP_KERNEL; if(atomic) flags |= GFP_ATOMIC; - if((page = __get_free_pages(flags, order)) == 0) + page = __get_free_pages(flags, order); + if(page == 0) return(0); stack_protections(page); return(page); @@ -103,22 +100,25 @@ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) { - struct task_struct *p; + int pid; current->thread.request.u.thread.proc = fn; current->thread.request.u.thread.arg = arg; - p = do_fork(CLONE_VM | flags, 0, NULL, 0, NULL, NULL); - if(IS_ERR(p)) panic("do_fork failed in kernel_thread"); - return(p->pid); + pid = do_fork(CLONE_VM | CLONE_UNTRACED | flags, 0, NULL, 0, NULL, + NULL); + if(pid < 0) + panic("do_fork failed in kernel_thread, errno = %d", pid); + return(pid); } void switch_mm(struct mm_struct *prev, struct mm_struct *next, struct task_struct *tsk) { - unsigned cpu = smp_processor_id(); + int cpu = smp_processor_id(); + if (prev != next) - clear_bit(cpu, &prev->cpu_vm_mask); - set_bit(cpu, &next->cpu_vm_mask); + cpu_clear(cpu, prev->cpu_vm_mask); + cpu_set(cpu, next->cpu_vm_mask); } void set_current(void *t) @@ -129,7 +129,7 @@ { external_pid(task), task }); } -void *switch_to(void *prev, void *next, void *last) +void *_switch_to(void *prev, void *next, void *last) { return(CHOOSE_MODE(switch_to_tt(prev, next), switch_to_skas(prev, next))); @@ -149,7 +149,7 @@ void exit_thread(void) { CHOOSE_MODE(exit_thread_tt(), exit_thread_skas()); - unprotect_stack((unsigned long) current->thread_info); + unprotect_stack((unsigned long) current_thread); } void *get_current(void) @@ -157,6 +157,10 @@ return(current); } +void prepare_to_copy(struct task_struct *tsk) +{ +} + int copy_thread(int nr, unsigned long clone_flags, unsigned long sp, unsigned long stack_top, struct task_struct * p, struct pt_regs *regs) @@ -190,7 +194,7 @@ void default_idle(void) { - idle_timer(); + uml_idle_timer(); atomic_inc(&init_mm.mm_count); current->mm = &init_mm; @@ -299,6 +303,11 @@ return(kmalloc(size, GFP_ATOMIC)); } +void *um_vmalloc(int size) +{ + return(vmalloc(size)); +} + unsigned long get_fault_addr(void) { return((unsigned long) current->thread.fault_addr); @@ -367,10 +376,15 @@ return(clear_user(buf, size)); } +int strlen_user_proc(char *str) +{ + return(strlen_user(str)); +} + int smp_sigio_handler(void) { #ifdef CONFIG_SMP - int cpu = current->thread_info->cpu; + int cpu = current_thread->cpu; IPI_handler(cpu); if(cpu != 0) return(1); @@ -385,7 +399,7 @@ int cpu(void) { - return(current->thread_info->cpu); + return(current_thread->cpu); } /* diff -Nru a/arch/um/kernel/ptrace.c b/arch/um/kernel/ptrace.c --- a/arch/um/kernel/ptrace.c 2004-08-25 22:01:56 -07:00 +++ b/arch/um/kernel/ptrace.c 2004-08-25 22:01:56 -07:00 @@ -24,11 +24,6 @@ { } -extern long do_mmap2(struct task_struct *task, unsigned long addr, - unsigned long len, unsigned long prot, - unsigned long flags, unsigned long fd, - unsigned long pgoff); - int sys_ptrace(long request, long pid, long addr, long data) { struct task_struct *child; @@ -302,8 +297,17 @@ return ret; } -void syscall_trace(void) +void syscall_trace(union uml_pt_regs *regs, int entryexit) { + if (unlikely(current->audit_context)) { + if (!entryexit) + audit_syscall_entry(current, regs->orig_eax, + regs->ebx, regs->ecx, + regs->edx, regs->esi); + else + audit_syscall_exit(current, regs->eax); + } + if (!test_thread_flag(TIF_SYSCALL_TRACE)) return; if (!(current->ptrace & PT_PTRACED)) @@ -311,11 +315,8 @@ /* the 0x80 provides a way for the tracing parent to distinguish between a syscall stop and SIGTRAP delivery */ - current->exit_code = SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) - ? 0x80 : 0); - current->state = TASK_STOPPED; - notify_parent(current, SIGCHLD); - schedule(); + ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) + ? 0x80 : 0)); /* * this isn't the same as continuing with a signal, but it will do diff -Nru a/arch/um/kernel/reboot.c b/arch/um/kernel/reboot.c --- a/arch/um/kernel/reboot.c 2004-08-25 22:01:55 -07:00 +++ b/arch/um/kernel/reboot.c 2004-08-25 22:01:55 -07:00 @@ -15,6 +15,7 @@ #ifdef CONFIG_SMP static void kill_idlers(int me) { +#ifdef CONFIG_MODE_TT struct task_struct *p; int i; @@ -23,6 +24,7 @@ if((p != NULL) && (p->thread.mode.tt.extern_pid != me)) os_kill_process(p->thread.mode.tt.extern_pid, 0); } +#endif } #endif diff -Nru a/arch/um/kernel/sigio_kern.c b/arch/um/kernel/sigio_kern.c --- a/arch/um/kernel/sigio_kern.c 2004-08-25 22:01:54 -07:00 +++ b/arch/um/kernel/sigio_kern.c 2004-08-25 22:01:54 -07:00 @@ -6,18 +6,21 @@ #include "linux/kernel.h" #include "linux/list.h" #include "linux/slab.h" -#include "asm/irq.h" +#include "linux/signal.h" +#include "linux/interrupt.h" #include "init.h" #include "sigio.h" #include "irq_user.h" +#include "irq_kern.h" /* Protected by sigio_lock() called from write_sigio_workaround */ static int sigio_irq_fd = -1; -void sigio_interrupt(int irq, void *data, struct pt_regs *unused) +irqreturn_t sigio_interrupt(int irq, void *data, struct pt_regs *unused) { read_sigio_fd(sigio_irq_fd); reactivate_fd(sigio_irq_fd, SIGIO_WRITE_IRQ); + return(IRQ_HANDLED); } int write_sigio_irq(int fd) diff -Nru a/arch/um/kernel/sigio_user.c b/arch/um/kernel/sigio_user.c --- a/arch/um/kernel/sigio_user.c 2004-08-25 22:01:56 -07:00 +++ b/arch/um/kernel/sigio_user.c 2004-08-25 22:01:56 -07:00 @@ -7,7 +7,6 @@ #include #include #include -#include #include #include #include @@ -17,6 +16,7 @@ #include "init.h" #include "user.h" #include "kern_util.h" +#include "user_util.h" #include "sigio.h" #include "helper.h" #include "os.h" @@ -26,7 +26,7 @@ int pty_close_sigio = 0; /* Used as a flag during SIGIO testing early in boot */ -static int got_sigio = 0; +static volatile int got_sigio = 0; void __init handler(int sig) { @@ -45,19 +45,18 @@ info->err = 0; if(openpty(&info->master, &info->slave, NULL, NULL, NULL)) - info->err = errno; + info->err = -errno; } void __init check_one_sigio(void (*proc)(int, int)) { struct sigaction old, new; - struct termios tt; struct openpty_arg pty = { .master = -1, .slave = -1 }; - int master, slave, flags; + int master, slave, err; initial_thread_cb(openpty_cb, &pty); if(pty.err){ - printk("openpty failed, errno = %d\n", pty.err); + printk("openpty failed, errno = %d\n", -pty.err); return; } @@ -69,23 +68,13 @@ return; } - if(tcgetattr(master, &tt) < 0) - panic("check_sigio : tcgetattr failed, errno = %d\n", errno); - cfmakeraw(&tt); - if(tcsetattr(master, TCSADRAIN, &tt) < 0) - panic("check_sigio : tcsetattr failed, errno = %d\n", errno); - - if((flags = fcntl(master, F_GETFL)) < 0) - panic("tty_fds : fcntl F_GETFL failed, errno = %d\n", errno); - - if((fcntl(master, F_SETFL, flags | O_NONBLOCK | O_ASYNC) < 0) || - (fcntl(master, F_SETOWN, os_getpid()) < 0)) - panic("check_sigio : fcntl F_SETFL or F_SETOWN failed, " - "errno = %d\n", errno); - - if((fcntl(slave, F_SETFL, flags | O_NONBLOCK) < 0)) - panic("check_sigio : fcntl F_SETFL failed, errno = %d\n", - errno); + err = __raw(master, 1, 0); //Not now, but complain so we now where we failed. + if (err < 0) + panic("check_sigio : __raw failed, errno = %d\n", -err); + + err = os_sigio_async(master, slave); + if(err < 0) + panic("tty_fds : sigio_async failed, err = %d\n", -err); if(sigaction(SIGIO, NULL, &old) < 0) panic("check_sigio : sigaction 1 failed, errno = %d\n", errno); @@ -97,8 +86,8 @@ got_sigio = 0; (*proc)(master, slave); - close(master); - close(slave); + os_close_file(master); + os_close_file(slave); if(sigaction(SIGIO, &old, NULL) < 0) panic("check_sigio : sigaction 3 failed, errno = %d\n", errno); @@ -112,25 +101,25 @@ printk("Checking that host ptys support output SIGIO..."); memset(buf, 0, sizeof(buf)); - while(write(master, buf, sizeof(buf)) > 0) ; + + while(os_write_file(master, buf, sizeof(buf)) > 0) ; if(errno != EAGAIN) panic("check_sigio : write failed, errno = %d\n", errno); - - while(((n = read(slave, buf, sizeof(buf))) > 0) && !got_sigio) ; + while(((n = os_read_file(slave, buf, sizeof(buf))) > 0) && !got_sigio) ; if(got_sigio){ printk("Yes\n"); pty_output_sigio = 1; } - else if(errno == EAGAIN) printk("No, enabling workaround\n"); - else panic("check_sigio : read failed, errno = %d\n", errno); + else if(n == -EAGAIN) printk("No, enabling workaround\n"); + else panic("check_sigio : read failed, err = %d\n", n); } static void tty_close(int master, int slave) { printk("Checking that host ptys support SIGIO on close..."); - close(slave); + os_close_file(slave); if(got_sigio){ printk("Yes\n"); pty_close_sigio = 1; @@ -140,7 +129,8 @@ void __init check_sigio(void) { - if(access("/dev/ptmx", R_OK) && access("/dev/ptyp0", R_OK)){ + if((os_access("/dev/ptmx", OS_ACC_R_OK) < 0) && + (os_access("/dev/ptyp0", OS_ACC_R_OK) < 0)){ printk("No pseudo-terminals available - skipping pty SIGIO " "check\n"); return; @@ -201,11 +191,10 @@ p = &fds->poll[i]; if(p->revents == 0) continue; if(p->fd == sigio_private[1]){ - n = read(sigio_private[1], &c, sizeof(c)); + n = os_read_file(sigio_private[1], &c, sizeof(c)); if(n != sizeof(c)) printk("write_sigio_thread : " - "read failed, errno = %d\n", - errno); + "read failed, err = %d\n", -n); tmp = current_poll; current_poll = next_poll; next_poll = tmp; @@ -218,10 +207,10 @@ (fds->used - i) * sizeof(*fds->poll)); } - n = write(respond_fd, &c, sizeof(c)); + n = os_write_file(respond_fd, &c, sizeof(c)); if(n != sizeof(c)) printk("write_sigio_thread : write failed, " - "errno = %d\n", errno); + "err = %d\n", -n); } } } @@ -252,15 +241,15 @@ char c; flags = set_signals(0); - n = write(sigio_private[0], &c, sizeof(c)); + n = os_write_file(sigio_private[0], &c, sizeof(c)); if(n != sizeof(c)){ - printk("update_thread : write failed, errno = %d\n", errno); + printk("update_thread : write failed, err = %d\n", -n); goto fail; } - n = read(sigio_private[0], &c, sizeof(c)); + n = os_read_file(sigio_private[0], &c, sizeof(c)); if(n != sizeof(c)){ - printk("update_thread : read failed, errno = %d\n", errno); + printk("update_thread : read failed, err = %d\n", -n); goto fail; } @@ -271,10 +260,10 @@ if(write_sigio_pid != -1) os_kill_process(write_sigio_pid, 1); write_sigio_pid = -1; - close(sigio_private[0]); - close(sigio_private[1]); - close(write_sigio_fds[0]); - close(write_sigio_fds[1]); + os_close_file(sigio_private[0]); + os_close_file(sigio_private[1]); + os_close_file(write_sigio_fds[0]); + os_close_file(write_sigio_fds[1]); sigio_unlock(); set_signals(flags); } @@ -369,15 +358,15 @@ goto out; err = os_pipe(write_sigio_fds, 1, 1); - if(err){ + if(err < 0){ printk("write_sigio_workaround - os_pipe 1 failed, " - "errno = %d\n", -err); + "err = %d\n", -err); goto out; } err = os_pipe(sigio_private, 1, 1); - if(err){ + if(err < 0){ printk("write_sigio_workaround - os_pipe 2 failed, " - "errno = %d\n", -err); + "err = %d\n", -err); goto out_close1; } if(setup_initial_poll(sigio_private[1])) @@ -399,11 +388,11 @@ os_kill_process(write_sigio_pid, 1); write_sigio_pid = -1; out_close2: - close(sigio_private[0]); - close(sigio_private[1]); + os_close_file(sigio_private[0]); + os_close_file(sigio_private[1]); out_close1: - close(write_sigio_fds[0]); - close(write_sigio_fds[1]); + os_close_file(write_sigio_fds[0]); + os_close_file(write_sigio_fds[1]); sigio_unlock(); } @@ -412,10 +401,16 @@ int n; char c; - n = read(fd, &c, sizeof(c)); + n = os_read_file(fd, &c, sizeof(c)); if(n != sizeof(c)){ - printk("read_sigio_fd - read failed, errno = %d\n", errno); - return(-errno); + if(n < 0) { + printk("read_sigio_fd - read failed, err = %d\n", -n); + return(n); + } + else { + printk("read_sigio_fd - short read, bytes = %d\n", n); + return(-EIO); + } } return(n); } diff -Nru a/arch/um/kernel/signal_kern.c b/arch/um/kernel/signal_kern.c --- a/arch/um/kernel/signal_kern.c 2004-08-25 22:01:55 -07:00 +++ b/arch/um/kernel/signal_kern.c 2004-08-25 22:01:55 -07:00 @@ -31,17 +31,6 @@ EXPORT_SYMBOL(block_signals); EXPORT_SYMBOL(unblock_signals); -static void force_segv(int sig) -{ - if(sig == SIGSEGV){ - struct k_sigaction *ka; - - ka = ¤t->sig->action[SIGSEGV - 1]; - ka->sa.sa_handler = SIG_DFL; - } - force_sig(SIGSEGV, current); -} - #define _S(nr) (1<<((nr)-1)) #define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP))) @@ -60,10 +49,10 @@ int err, ret; ret = 0; + /* Always make any pending restarted system calls return -EINTR */ + current_thread_info()->restart_block.fn = do_no_restart_syscall; switch(error){ case -ERESTART_RESTARTBLOCK: - current_thread_info()->restart_block.fn = - do_no_restart_syscall; case -ERESTARTNOHAND: ret = -EINTR; break; @@ -124,27 +113,27 @@ return(0); segv: - force_segv(signr); + force_sigsegv(signr, current); return(1); } static int kern_do_signal(struct pt_regs *regs, sigset_t *oldset, int error) { + struct k_sigaction ka_copy; siginfo_t info; - struct k_sigaction *ka; int err, sig; if (!oldset) oldset = ¤t->blocked; - sig = get_signal_to_deliver(&info, regs, NULL); + sig = get_signal_to_deliver(&info, &ka_copy, regs, NULL); if(sig == 0) return(0); /* Whee! Actually deliver the signal. */ - ka = ¤t->sig->action[sig -1 ]; - err = handle_signal(regs, sig, ka, &info, oldset, error); - if(!err) return(1); + err = handle_signal(regs, sig, &ka_copy, &info, oldset, error); + if(!err) + return(1); /* Did we come from a system call? */ if(PT_REGS_SYSCALL_NR(regs) >= 0){ @@ -201,7 +190,7 @@ } } -int sys_rt_sigsuspend(sigset_t *unewset, size_t sigsetsize) +int sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize) { sigset_t saveset, newset; @@ -227,20 +216,59 @@ } } +int sys_sigaction(int sig, const struct old_sigaction __user *act, + struct old_sigaction __user *oact) +{ + struct k_sigaction new_ka, old_ka; + int ret; + + if (act) { + old_sigset_t mask; + if (verify_area(VERIFY_READ, act, sizeof(*act)) || + __get_user(new_ka.sa.sa_handler, &act->sa_handler) || + __get_user(new_ka.sa.sa_restorer, &act->sa_restorer)) + return -EFAULT; + __get_user(new_ka.sa.sa_flags, &act->sa_flags); + __get_user(mask, &act->sa_mask); + siginitset(&new_ka.sa.sa_mask, mask); + } + + ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); + + if (!ret && oact) { + if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) || + __put_user(old_ka.sa.sa_handler, &oact->sa_handler) || + __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer)) + return -EFAULT; + __put_user(old_ka.sa.sa_flags, &oact->sa_flags); + __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask); + } + + return ret; +} + +int sys_sigaltstack(const stack_t *uss, stack_t *uoss) +{ + return(do_sigaltstack(uss, uoss, PT_REGS_SP(¤t->thread.regs))); +} + +extern int userspace_pid[]; + static int copy_sc_from_user(struct pt_regs *to, void *from, struct arch_frame_data *arch) { int ret; ret = CHOOSE_MODE(copy_sc_from_user_tt(UPT_SC(&to->regs), from, arch), - copy_sc_from_user_skas(&to->regs, from)); + copy_sc_from_user_skas(userspace_pid[0], + &to->regs, from)); return(ret); } int sys_sigreturn(struct pt_regs regs) { - void *sc = sp_to_sc(PT_REGS_SP(¤t->thread.regs)); - void *mask = sp_to_mask(PT_REGS_SP(¤t->thread.regs)); + void __user *sc = sp_to_sc(PT_REGS_SP(¤t->thread.regs)); + void __user *mask = sp_to_mask(PT_REGS_SP(¤t->thread.regs)); int sig_size = (_NSIG_WORDS - 1) * sizeof(unsigned long); spin_lock_irq(¤t->sighand->siglock); @@ -257,8 +285,8 @@ int sys_rt_sigreturn(struct pt_regs regs) { - struct ucontext *uc = sp_to_uc(PT_REGS_SP(¤t->thread.regs)); - void *fp; + unsigned long sp = PT_REGS_SP(¤t->thread.regs); + struct ucontext __user *uc = sp_to_uc(sp); int sig_size = _NSIG_WORDS * sizeof(unsigned long); spin_lock_irq(¤t->sighand->siglock); @@ -266,7 +294,6 @@ sigdelsetmask(¤t->blocked, ~_BLOCKABLE); recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); - fp = (void *) (((unsigned long) uc) + sizeof(struct ucontext)); copy_sc_from_user(¤t->thread.regs, &uc->uc_mcontext, &signal_frame_si.common.arch); return(PT_REGS_SYSCALL_RET(¤t->thread.regs)); diff -Nru a/arch/um/kernel/skas/Makefile b/arch/um/kernel/skas/Makefile --- a/arch/um/kernel/skas/Makefile 2004-08-25 22:01:55 -07:00 +++ b/arch/um/kernel/skas/Makefile 2004-08-25 22:01:55 -07:00 @@ -5,20 +5,24 @@ obj-y = exec_kern.o exec_user.o mem.o mem_user.o mmu.o process.o \ process_kern.o syscall_kern.o syscall_user.o time.o tlb.o trap_user.o \ - sys-$(SUBARCH)/ + uaccess.o sys-$(SUBARCH)/ + +hostprogs-y := util/mk_ptregs +clean-files := include/skas_ptregs.h USER_OBJS = $(filter %_user.o,$(obj-y)) process.o time.o USER_OBJS := $(foreach file,$(USER_OBJS),$(obj)/$(file)) -include/skas_ptregs.h : util/mk_ptregs - util/mk_ptregs > $@ - -util/mk_ptregs : - $(MAKE) -C util +$(TOPDIR)/arch/um/include/skas_ptregs.h : $(src)/util/mk_ptregs + @echo -n ' Generating $@' + @$< > $@.tmp + @if [ -r $@ ] && cmp -s $@ $@.tmp; then \ + echo ' (unchanged)'; \ + rm -f $@.tmp; \ + else \ + echo ' (updated)'; \ + mv -f $@.tmp $@; \ + fi $(USER_OBJS) : %.o: %.c $(CC) $(CFLAGS_$(notdir $@)) $(USER_CFLAGS) -c -o $@ $< - -clean : - $(MAKE) -C util clean - $(RM) -f include/skas_ptregs.h diff -Nru a/arch/um/kernel/skas/exec_user.c b/arch/um/kernel/skas/exec_user.c --- a/arch/um/kernel/skas/exec_user.c 2004-08-25 22:01:54 -07:00 +++ b/arch/um/kernel/skas/exec_user.c 2004-08-25 22:01:54 -07:00 @@ -11,6 +11,7 @@ #include #include "user.h" #include "kern_util.h" +#include "user_util.h" #include "os.h" #include "time_user.h" @@ -26,7 +27,7 @@ int user_thread(unsigned long stack, int flags) { - int pid, status; + int pid, status, err; pid = clone(user_thread_tramp, (void *) stack_sp(stack), flags | CLONE_FILES | SIGCHLD, NULL); @@ -35,7 +36,8 @@ return(pid); } - if(waitpid(pid, &status, WUNTRACED) < 0){ + CATCH_EINTR(err = waitpid(pid, &status, WUNTRACED)); + if(err < 0){ printk("user_thread - waitpid failed, errno = %d\n", errno); return(-errno); } diff -Nru a/arch/um/kernel/skas/include/mode.h b/arch/um/kernel/skas/include/mode.h --- a/arch/um/kernel/skas/include/mode.h 2004-08-25 22:01:55 -07:00 +++ b/arch/um/kernel/skas/include/mode.h 2004-08-25 22:01:55 -07:00 @@ -12,14 +12,16 @@ extern int have_fpx_regs; extern void user_time_init_skas(void); -extern int copy_sc_from_user_skas(union uml_pt_regs *regs, void *from_ptr); -extern int copy_sc_to_user_skas(void *to_ptr, void *fp, +extern int copy_sc_from_user_skas(int pid, union uml_pt_regs *regs, + void *from_ptr); +extern int copy_sc_to_user_skas(int pid, void *to_ptr, void *fp, union uml_pt_regs *regs, unsigned long fault_addr, int fault_type); extern void sig_handler_common_skas(int sig, void *sc_ptr); extern void halt_skas(void); extern void reboot_skas(void); extern void kill_off_processes_skas(void); +extern int is_skas_winch(int pid, int fd, void *data); #endif diff -Nru a/arch/um/kernel/skas/include/ptrace-skas.h b/arch/um/kernel/skas/include/ptrace-skas.h --- a/arch/um/kernel/skas/include/ptrace-skas.h 2004-08-25 22:01:54 -07:00 +++ b/arch/um/kernel/skas/include/ptrace-skas.h 2004-08-25 22:01:54 -07:00 @@ -10,6 +10,16 @@ #ifdef UML_CONFIG_MODE_SKAS +/* syscall emulation path in ptrace */ + +#ifndef PTRACE_SYSEMU +#define PTRACE_SYSEMU 31 +#endif + +void set_using_sysemu(int value); +int get_using_sysemu(void); +extern int sysemu_supported; + #include "skas_ptregs.h" #define HOST_FRAME_SIZE 17 diff -Nru a/arch/um/kernel/skas/include/skas.h b/arch/um/kernel/skas/include/skas.h --- a/arch/um/kernel/skas/include/skas.h 2004-08-25 22:01:55 -07:00 +++ b/arch/um/kernel/skas/include/skas.h 2004-08-25 22:01:55 -07:00 @@ -8,7 +8,7 @@ #include "sysdep/ptrace.h" -extern int userspace_pid; +extern int userspace_pid[]; extern void switch_threads(void *me, void *next); extern void thread_wait(void *sw, void *fb); @@ -32,7 +32,7 @@ extern int new_mm(int from); extern void save_registers(union uml_pt_regs *regs); extern void restore_registers(union uml_pt_regs *regs); -extern void start_userspace(void); +extern void start_userspace(int cpu); extern void init_registers(int pid); #endif diff -Nru a/arch/um/kernel/skas/include/uaccess.h b/arch/um/kernel/skas/include/uaccess.h --- a/arch/um/kernel/skas/include/uaccess.h 2004-08-25 22:01:55 -07:00 +++ b/arch/um/kernel/skas/include/uaccess.h 2004-08-25 22:01:55 -07:00 @@ -6,20 +6,12 @@ #ifndef __SKAS_UACCESS_H #define __SKAS_UACCESS_H -#include "linux/string.h" -#include "linux/sched.h" -#include "linux/err.h" -#include "asm/processor.h" -#include "asm/pgtable.h" #include "asm/errno.h" -#include "asm/current.h" -#include "asm/a.out.h" -#include "kern_util.h" #define access_ok_skas(type, addr, size) \ ((segment_eq(get_fs(), KERNEL_DS)) || \ (((unsigned long) (addr) < TASK_SIZE) && \ - ((unsigned long) (addr) + (size) < TASK_SIZE))) + ((unsigned long) (addr) + (size) <= TASK_SIZE))) static inline int verify_area_skas(int type, const void * addr, unsigned long size) @@ -27,197 +19,12 @@ return(access_ok_skas(type, addr, size) ? 0 : -EFAULT); } -static inline unsigned long maybe_map(unsigned long virt, int is_write) -{ - pte_t pte; - - void *phys = um_virt_to_phys(current, virt, &pte); - int dummy_code; - - if(IS_ERR(phys) || (is_write && !pte_write(pte))){ - if(handle_page_fault(virt, 0, is_write, 0, &dummy_code)) - return(0); - phys = um_virt_to_phys(current, virt, NULL); - } - return((unsigned long) __va((unsigned long) phys)); -} - -static inline int buffer_op(unsigned long addr, int len, - int (*op)(unsigned long addr, int len, void *arg), - void *arg) -{ - int size = min(PAGE_ALIGN(addr) - addr, (unsigned long) len); - int remain = len, n; - - n = (*op)(addr, size, arg); - if(n != 0) - return(n < 0 ? remain : 0); - - addr += size; - remain -= size; - if(remain == 0) - return(0); - - while(addr < ((addr + remain) & PAGE_MASK)){ - n = (*op)(addr, PAGE_SIZE, arg); - if(n != 0) - return(n < 0 ? remain : 0); - - addr += PAGE_SIZE; - remain -= PAGE_SIZE; - } - if(remain == 0) - return(0); - - n = (*op)(addr, remain, arg); - if(n != 0) - return(n < 0 ? remain : 0); - return(0); -} - -static inline int copy_chunk_from_user(unsigned long from, int len, void *arg) -{ - unsigned long *to_ptr = arg, to = *to_ptr; - - from = maybe_map(from, 0); - if(from == 0) - return(-1); - - memcpy((void *) to, (void *) from, len); - *to_ptr += len; - return(0); -} - -static inline int copy_from_user_skas(void *to, const void *from, int n) -{ - if(segment_eq(get_fs(), KERNEL_DS)){ - memcpy(to, from, n); - return(0); - } - - return(access_ok_skas(VERIFY_READ, from, n) ? - buffer_op((unsigned long) from, n, copy_chunk_from_user, &to) : - n); -} - -static inline int copy_chunk_to_user(unsigned long to, int len, void *arg) -{ - unsigned long *from_ptr = arg, from = *from_ptr; - - to = maybe_map(to, 1); - if(to == 0) - return(-1); - - memcpy((void *) to, (void *) from, len); - *from_ptr += len; - return(0); -} - -static inline int copy_to_user_skas(void *to, const void *from, int n) -{ - if(segment_eq(get_fs(), KERNEL_DS)){ - memcpy(to, from, n); - return(0); - } - - return(access_ok_skas(VERIFY_WRITE, to, n) ? - buffer_op((unsigned long) to, n, copy_chunk_to_user, &from) : - n); -} - -static inline int strncpy_chunk_from_user(unsigned long from, int len, - void *arg) -{ - char **to_ptr = arg, *to = *to_ptr; - int n; - - from = maybe_map(from, 0); - if(from == 0) - return(-1); - - strncpy(to, (void *) from, len); - n = strnlen(to, len); - *to_ptr += n; - - if(n < len) - return(1); - return(0); -} - -static inline int strncpy_from_user_skas(char *dst, const char *src, int count) -{ - int n; - char *ptr = dst; - - if(segment_eq(get_fs(), KERNEL_DS)){ - strncpy(dst, src, count); - return(strnlen(dst, count)); - } - - if(!access_ok_skas(VERIFY_READ, src, 1)) - return(-EFAULT); - - n = buffer_op((unsigned long) src, count, strncpy_chunk_from_user, - &ptr); - if(n != 0) - return(-EFAULT); - return(strnlen(dst, count)); -} - -static inline int clear_chunk(unsigned long addr, int len, void *unused) -{ - addr = maybe_map(addr, 1); - if(addr == 0) - return(-1); - - memset((void *) addr, 0, len); - return(0); -} - -static inline int __clear_user_skas(void *mem, int len) -{ - return(buffer_op((unsigned long) mem, len, clear_chunk, NULL)); -} - -static inline int clear_user_skas(void *mem, int len) -{ - if(segment_eq(get_fs(), KERNEL_DS)){ - memset(mem, 0, len); - return(0); - } - - return(access_ok_skas(VERIFY_WRITE, mem, len) ? - buffer_op((unsigned long) mem, len, clear_chunk, NULL) : len); -} - -static inline int strnlen_chunk(unsigned long str, int len, void *arg) -{ - int *len_ptr = arg, n; - - str = maybe_map(str, 0); - if(str == 0) - return(-1); - - n = strnlen((void *) str, len); - *len_ptr += n; - - if(n < len) - return(1); - return(0); -} - -static inline int strnlen_user_skas(const void *str, int len) -{ - int count = 0, n; - - if(segment_eq(get_fs(), KERNEL_DS)) - return(strnlen(str, len) + 1); - - n = buffer_op((unsigned long) str, len, strnlen_chunk, &count); - if(n == 0) - return(count + 1); - return(-EFAULT); -} +extern int copy_from_user_skas(void *to, const void *from, int n); +extern int copy_to_user_skas(void *to, const void *from, int n); +extern int strncpy_from_user_skas(char *dst, const char *src, int count); +extern int __clear_user_skas(void *mem, int len); +extern int clear_user_skas(void *mem, int len); +extern int strnlen_user_skas(const void *str, int len); #endif diff -Nru a/arch/um/kernel/skas/mem_user.c b/arch/um/kernel/skas/mem_user.c --- a/arch/um/kernel/skas/mem_user.c 2004-08-25 22:01:55 -07:00 +++ b/arch/um/kernel/skas/mem_user.c 2004-08-25 22:01:55 -07:00 @@ -7,6 +7,7 @@ #include #include #include "mem_user.h" +#include "mem.h" #include "user.h" #include "os.h" #include "proc_mm.h" @@ -15,12 +16,12 @@ int r, int w, int x) { struct proc_mm_op map; - struct mem_region *region; - int prot, n; + __u64 offset; + int prot, n, phys_fd; prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) | (x ? PROT_EXEC : 0); - region = phys_region(phys); + phys_fd = phys_mapping(phys, &offset); map = ((struct proc_mm_op) { .op = MM_MMAP, .u = @@ -30,12 +31,12 @@ .prot = prot, .flags = MAP_SHARED | MAP_FIXED, - .fd = region->fd, - .offset = phys_offset(phys) + .fd = phys_fd, + .offset = offset } } } ); n = os_write_file(fd, &map, sizeof(map)); if(n != sizeof(map)) - printk("map : /proc/mm map failed, errno = %d\n", errno); + printk("map : /proc/mm map failed, err = %d\n", -n); } int unmap(int fd, void *addr, int len) @@ -49,8 +50,13 @@ { .addr = (unsigned long) addr, .len = len } } } ); n = os_write_file(fd, &unmap, sizeof(unmap)); - if((n != 0) && (n != sizeof(unmap))) - return(-errno); + if(n != sizeof(unmap)) { + if(n < 0) + return(n); + else if(n > 0) + return(-EIO); + } + return(0); } @@ -71,11 +77,15 @@ .prot = prot } } } ); n = os_write_file(fd, &protect, sizeof(protect)); - if((n != 0) && (n != sizeof(protect))){ + if(n != sizeof(protect)) { + if(n == 0) return(0); + if(must_succeed) - panic("protect failed, errno = %d", errno); - return(-errno); + panic("protect failed, err = %d", -n); + + return(-EIO); } + return(0); } diff -Nru a/arch/um/kernel/skas/mmu.c b/arch/um/kernel/skas/mmu.c --- a/arch/um/kernel/skas/mmu.c 2004-08-25 22:01:56 -07:00 +++ b/arch/um/kernel/skas/mmu.c 2004-08-25 22:01:56 -07:00 @@ -22,9 +22,11 @@ else from = -1; mm->context.skas.mm_fd = new_mm(from); - if(mm->context.skas.mm_fd < 0) - panic("init_new_context_skas - new_mm failed, errno = %d\n", - mm->context.skas.mm_fd); + if(mm->context.skas.mm_fd < 0){ + printk("init_new_context_skas - new_mm failed, errno = %d\n", + mm->context.skas.mm_fd); + return(mm->context.skas.mm_fd); + } return(0); } diff -Nru a/arch/um/kernel/skas/process.c b/arch/um/kernel/skas/process.c --- a/arch/um/kernel/skas/process.c 2004-08-25 22:01:56 -07:00 +++ b/arch/um/kernel/skas/process.c 2004-08-25 22:01:56 -07:00 @@ -4,6 +4,7 @@ */ #include +#include #include #include #include @@ -24,6 +25,19 @@ #include "os.h" #include "proc_mm.h" #include "skas_ptrace.h" +#include "chan_user.h" +#include "signal_user.h" + +int is_skas_winch(int pid, int fd, void *data) +{ + if(pid != getpid()) + return(0); + + register_winch_irq(-1, fd, -1, data); + return(1); +} + +/* These are set once at boot time and not changed thereafter */ unsigned long exec_regs[FRAME_SIZE]; unsigned long exec_fp_regs[HOST_FP_SIZE]; @@ -43,37 +57,39 @@ segv(fault.addr, 0, FAULT_WRITE(fault.is_write), 1, NULL); } -static void handle_trap(int pid, union uml_pt_regs *regs) +/*To use the same value of using_sysemu as the caller, ask it that value (in local_using_sysemu)*/ +static void handle_trap(int pid, union uml_pt_regs *regs, int local_using_sysemu) { int err, syscall_nr, status; syscall_nr = PT_SYSCALL_NR(regs->skas.regs); + UPT_SYSCALL_NR(regs) = syscall_nr; if(syscall_nr < 1){ relay_signal(SIGTRAP, regs); return; } - UPT_SYSCALL_NR(regs) = syscall_nr; - err = ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_NR_OFFSET, __NR_getpid); - if(err < 0) - panic("handle_trap - nullifying syscall failed errno = %d\n", - errno); + if (!local_using_sysemu) + { + err = ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_NR_OFFSET, __NR_getpid); + if(err < 0) + panic("handle_trap - nullifying syscall failed errno = %d\n", + errno); + + err = ptrace(PTRACE_SYSCALL, pid, 0, 0); + if(err < 0) + panic("handle_trap - continuing to end of syscall failed, " + "errno = %d\n", errno); - err = ptrace(PTRACE_SYSCALL, pid, 0, 0); - if(err < 0) - panic("handle_trap - continuing to end of syscall failed, " - "errno = %d\n", errno); - - err = waitpid(pid, &status, WUNTRACED); - if((err < 0) || !WIFSTOPPED(status) || (WSTOPSIG(status) != SIGTRAP)) - panic("handle_trap - failed to wait at end of syscall, " - "errno = %d, status = %d\n", errno, status); + CATCH_EINTR(err = waitpid(pid, &status, WUNTRACED)); + if((err < 0) || !WIFSTOPPED(status) || (WSTOPSIG(status) != SIGTRAP)) + panic("handle_trap - failed to wait at end of syscall, " + "errno = %d, status = %d\n", errno, status); + } handle_syscall(regs); } -int userspace_pid; - static int userspace_tramp(void *arg) { init_new_thread_signals(0); @@ -83,7 +99,11 @@ return(0); } -void start_userspace(void) +/* Each element set once, and only accessed by a single processor anyway */ +#define NR_CPUS 1 +int userspace_pid[NR_CPUS]; + +void start_userspace(int cpu) { void *stack; unsigned long sp; @@ -101,7 +121,7 @@ panic("start_userspace : clone failed, errno = %d", errno); do { - n = waitpid(pid, &status, WUNTRACED); + CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED)); if(n < 0) panic("start_userspace : wait failed, errno = %d", errno); @@ -114,21 +134,27 @@ if(munmap(stack, PAGE_SIZE) < 0) panic("start_userspace : munmap failed, errno = %d\n", errno); - userspace_pid = pid; + userspace_pid[cpu] = pid; } void userspace(union uml_pt_regs *regs) { - int err, status, op; + int err, status, op, pid = userspace_pid[0]; + int local_using_sysemu; /*To prevent races if using_sysemu changes under us.*/ restore_registers(regs); - err = ptrace(PTRACE_SYSCALL, userspace_pid, 0, 0); + local_using_sysemu = get_using_sysemu(); + + if (local_using_sysemu) + err = ptrace(PTRACE_SYSEMU, pid, 0, 0); + else + err = ptrace(PTRACE_SYSCALL, pid, 0, 0); if(err) - panic("userspace - PTRACE_SYSCALL failed, errno = %d\n", - errno); + panic("userspace - PTRACE_%s failed, errno = %d\n", + local_using_sysemu ? "SYSEMU" : "SYSCALL", errno); while(1){ - err = waitpid(userspace_pid, &status, WUNTRACED); + CATCH_EINTR(err = waitpid(pid, &status, WUNTRACED)); if(err < 0) panic("userspace - waitpid failed, errno = %d\n", errno); @@ -139,16 +165,17 @@ if(WIFSTOPPED(status)){ switch(WSTOPSIG(status)){ case SIGSEGV: - handle_segv(userspace_pid); + handle_segv(pid); break; case SIGTRAP: - handle_trap(userspace_pid, regs); + handle_trap(pid, regs, local_using_sysemu); break; case SIGIO: case SIGVTALRM: case SIGILL: case SIGBUS: case SIGFPE: + case SIGWINCH: user_signal(WSTOPSIG(status), regs); break; default: @@ -160,25 +187,46 @@ restore_registers(regs); - op = singlestepping_skas() ? PTRACE_SINGLESTEP : - PTRACE_SYSCALL; - err = ptrace(op, userspace_pid, 0, 0); + /*Now we ended the syscall, so re-read local_using_sysemu.*/ + local_using_sysemu = get_using_sysemu(); + + if (local_using_sysemu) + op = singlestepping_skas() ? PTRACE_SINGLESTEP : + PTRACE_SYSEMU; + else + op = singlestepping_skas() ? PTRACE_SINGLESTEP : + PTRACE_SYSCALL; + + err = ptrace(op, pid, 0, 0); if(err) - panic("userspace - PTRACE_SYSCALL failed, " - "errno = %d\n", errno); + panic("userspace - PTRACE_%s failed, " + "errno = %d\n", + local_using_sysemu ? "SYSEMU" : "SYSCALL", errno); } } void new_thread(void *stack, void **switch_buf_ptr, void **fork_buf_ptr, void (*handler)(int)) { + unsigned long flags; jmp_buf switch_buf, fork_buf; *switch_buf_ptr = &switch_buf; *fork_buf_ptr = &fork_buf; - if(setjmp(fork_buf) == 0) + /* Somewhat subtle - siglongjmp restores the signal mask before doing + * the longjmp. This means that when jumping from one stack to another + * when the target stack has interrupts enabled, an interrupt may occur + * on the source stack. This is bad when starting up a process because + * it's not supposed to get timer ticks until it has been scheduled. + * So, we disable interrupts around the sigsetjmp to ensure that + * they can't happen until we get back here where they are safe. + */ + flags = get_signals(); + block_signals(); + if(sigsetjmp(fork_buf, 1) == 0) new_thread_proc(stack, handler); + set_signals(flags); remove_sigstack(); } @@ -189,16 +237,16 @@ *switch_buf = &buf; fork_buf = fb; - if(setjmp(buf) == 0) - longjmp(*fork_buf, 1); + if(sigsetjmp(buf, 1) == 0) + siglongjmp(*fork_buf, 1); } -static int move_registers(int int_op, int fp_op, union uml_pt_regs *regs, - unsigned long *fp_regs) +static int move_registers(int pid, int int_op, int fp_op, + union uml_pt_regs *regs, unsigned long *fp_regs) { - if(ptrace(int_op, userspace_pid, 0, regs->skas.regs) < 0) + if(ptrace(int_op, pid, 0, regs->skas.regs) < 0) return(-errno); - if(ptrace(fp_op, userspace_pid, 0, fp_regs) < 0) + if(ptrace(fp_op, pid, 0, fp_regs) < 0) return(-errno); return(0); } @@ -217,10 +265,11 @@ fp_regs = regs->skas.fp; } - err = move_registers(PTRACE_GETREGS, fp_op, regs, fp_regs); + err = move_registers(userspace_pid[0], PTRACE_GETREGS, fp_op, regs, + fp_regs); if(err) panic("save_registers - saving registers failed, errno = %d\n", - err); + -err); } void restore_registers(union uml_pt_regs *regs) @@ -237,10 +286,11 @@ fp_regs = regs->skas.fp; } - err = move_registers(PTRACE_SETREGS, fp_op, regs, fp_regs); + err = move_registers(userspace_pid[0], PTRACE_SETREGS, fp_op, regs, + fp_regs); if(err) panic("restore_registers - saving registers failed, " - "errno = %d\n", err); + "errno = %d\n", -err); } void switch_threads(void *me, void *next) @@ -248,8 +298,8 @@ jmp_buf my_buf, **me_ptr = me, *next_buf = next; *me_ptr = &my_buf; - if(setjmp(my_buf) == 0) - longjmp(*next_buf, 1); + if(sigsetjmp(my_buf, 1) == 0) + siglongjmp(*next_buf, 1); } static jmp_buf initial_jmpbuf; @@ -265,14 +315,14 @@ int n; *fork_buf_ptr = &initial_jmpbuf; - n = setjmp(initial_jmpbuf); + n = sigsetjmp(initial_jmpbuf, 1); if(n == 0) new_thread_proc((void *) stack, new_thread_handler); else if(n == 1) remove_sigstack(); else if(n == 2){ (*cb_proc)(cb_arg); - longjmp(*cb_back, 1); + siglongjmp(*cb_back, 1); } else if(n == 3){ kmalloc_ok = 0; @@ -282,7 +332,7 @@ kmalloc_ok = 0; return(1); } - longjmp(**switch_buf, 1); + siglongjmp(**switch_buf, 1); } void remove_sigstack(void) @@ -304,8 +354,8 @@ cb_back = &here; block_signals(); - if(setjmp(here) == 0) - longjmp(initial_jmpbuf, 2); + if(sigsetjmp(here, 1) == 0) + siglongjmp(initial_jmpbuf, 2); unblock_signals(); cb_proc = NULL; @@ -316,22 +366,23 @@ void halt_skas(void) { block_signals(); - longjmp(initial_jmpbuf, 3); + siglongjmp(initial_jmpbuf, 3); } void reboot_skas(void) { block_signals(); - longjmp(initial_jmpbuf, 4); + siglongjmp(initial_jmpbuf, 4); } int new_mm(int from) { struct proc_mm_op copy; - int n, fd = os_open_file("/proc/mm", of_write(OPENFLAGS()), 0); + int n, fd = os_open_file("/proc/mm", + of_cloexec(of_write(OPENFLAGS())), 0); if(fd < 0) - return(-errno); + return(fd); if(from != -1){ copy = ((struct proc_mm_op) { .op = MM_COPY_SEGMENTS, @@ -340,8 +391,9 @@ n = os_write_file(fd, ©, sizeof(copy)); if(n != sizeof(copy)) printk("new_mm : /proc/mm copy_segments failed, " - "errno = %d\n", errno); + "err = %d\n", -n); } + return(fd); } @@ -349,7 +401,8 @@ { int err; - err = ptrace(PTRACE_SWITCH_MM, userspace_pid, 0, mm_fd); +#warning need cpu pid in switch_mm_skas + err = ptrace(PTRACE_SWITCH_MM, userspace_pid[0], 0, mm_fd); if(err) panic("switch_mm_skas - PTRACE_SWITCH_MM failed, errno = %d\n", errno); @@ -357,7 +410,8 @@ void kill_off_processes_skas(void) { - os_kill_process(userspace_pid, 1); +#warning need to loop over userspace_pids in kill_off_processes_skas + os_kill_process(userspace_pid[0], 1); } void init_registers(int pid) diff -Nru a/arch/um/kernel/skas/process_kern.c b/arch/um/kernel/skas/process_kern.c --- a/arch/um/kernel/skas/process_kern.c 2004-08-25 22:01:56 -07:00 +++ b/arch/um/kernel/skas/process_kern.c 2004-08-25 22:01:56 -07:00 @@ -6,6 +6,12 @@ #include "linux/sched.h" #include "linux/slab.h" #include "linux/ptrace.h" +#include "linux/proc_fs.h" +#include "linux/file.h" +#include "linux/errno.h" +#include "linux/init.h" +#include "asm/uaccess.h" +#include "asm/atomic.h" #include "kern_util.h" #include "time_user.h" #include "signal_user.h" @@ -17,6 +23,61 @@ #include "kern.h" #include "mode.h" +static atomic_t using_sysemu; +int sysemu_supported; + +void set_using_sysemu(int value) +{ + atomic_set(&using_sysemu, sysemu_supported && value); +} + +int get_using_sysemu(void) +{ + return atomic_read(&using_sysemu); +} + +int proc_read_sysemu(char *buf, char **start, off_t offset, int size,int *eof, void *data) +{ + if (snprintf(buf, size, "%d\n", get_using_sysemu()) < size) /*No overflow*/ + *eof = 1; + + return strlen(buf); +} + +int proc_write_sysemu(struct file *file,const char *buf, unsigned long count,void *data) +{ + char tmp[2]; + + if (copy_from_user(tmp, buf, 1)) + return -EFAULT; + + if (tmp[0] == '0' || tmp[0] == '1') + set_using_sysemu(tmp[0] - '0'); + return count; /*We use the first char, but pretend to write everything*/ +} + +int __init make_proc_sysemu(void) +{ + struct proc_dir_entry *ent; + if (mode_tt || !sysemu_supported) + return 0; + + ent = create_proc_entry("sysemu", 0600, &proc_root); + + if (ent == NULL) + { + printk("Failed to register /proc/sysemu\n"); + return(0); + } + + ent->read_proc = proc_read_sysemu; + ent->write_proc = proc_write_sysemu; + + return 0; +} + +late_initcall(make_proc_sysemu); + int singlestepping_skas(void) { int ret = current->ptrace & PT_DTRACE; @@ -61,11 +122,13 @@ thread_wait(¤t->thread.mode.skas.switch_buf, current->thread.mode.skas.fork_buf); -#ifdef CONFIG_SMP - schedule_tail(NULL); -#endif + if(current->thread.prev_sched != NULL) + schedule_tail(current->thread.prev_sched); current->thread.prev_sched = NULL; + /* The return value is 1 if the kernel thread execs a process, + * 0 if it just exits + */ n = run_kernel_thread(fn, arg, ¤t->thread.exec_buf); if(n == 1) userspace(¤t->thread.regs.regs); @@ -93,11 +156,11 @@ current->thread.mode.skas.fork_buf); force_flush_all(); -#ifdef CONFIG_SMP + if(current->thread.prev_sched == NULL) + panic("blech"); + schedule_tail(current->thread.prev_sched); -#endif current->thread.prev_sched = NULL; - unblock_signals(); userspace(¤t->thread.regs.regs); } @@ -136,7 +199,7 @@ void init_idle_skas(void) { - cpu_tasks[current->thread_info->cpu].pid = os_getpid(); + cpu_tasks[current_thread->cpu].pid = os_getpid(); default_idle(); } @@ -160,11 +223,11 @@ int start_uml_skas(void) { - start_userspace(); + start_userspace(0); capture_signal_stack(); + uml_idle_timer(); init_new_thread_signals(1); - idle_timer(); init_task.thread.request.u.thread.proc = start_kernel_proc; init_task.thread.request.u.thread.arg = NULL; @@ -175,12 +238,14 @@ int external_pid_skas(struct task_struct *task) { - return(userspace_pid); +#warning Need to look up userspace_pid by cpu + return(userspace_pid[0]); } int thread_pid_skas(struct task_struct *task) { - return(userspace_pid); +#warning Need to look up userspace_pid by cpu + return(userspace_pid[0]); } /* diff -Nru a/arch/um/kernel/skas/sys-i386/Makefile b/arch/um/kernel/skas/sys-i386/Makefile --- a/arch/um/kernel/skas/sys-i386/Makefile 2004-08-25 22:01:56 -07:00 +++ b/arch/um/kernel/skas/sys-i386/Makefile 2004-08-25 22:01:56 -07:00 @@ -10,5 +10,3 @@ $(USER_OBJS) : %.o: %.c $(CC) $(CFLAGS_$(notdir $@)) $(USER_CFLAGS) -c -o $@ $< - -clean : diff -Nru a/arch/um/kernel/skas/sys-i386/sigcontext.c b/arch/um/kernel/skas/sys-i386/sigcontext.c --- a/arch/um/kernel/skas/sys-i386/sigcontext.c 2004-08-25 22:01:54 -07:00 +++ b/arch/um/kernel/skas/sys-i386/sigcontext.c 2004-08-25 22:01:54 -07:00 @@ -12,10 +12,9 @@ #include "kern_util.h" #include "user.h" #include "sigcontext.h" +#include "mode.h" -extern int userspace_pid; - -int copy_sc_from_user_skas(union uml_pt_regs *regs, void *from_ptr) +int copy_sc_from_user_skas(int pid, union uml_pt_regs *regs, void *from_ptr) { struct sigcontext sc, *from = from_ptr; unsigned long fpregs[FP_FRAME_SIZE]; @@ -41,13 +40,12 @@ regs->skas.regs[EIP] = sc.eip; regs->skas.regs[CS] = sc.cs; regs->skas.regs[EFL] = sc.eflags; - regs->skas.regs[UESP] = sc.esp_at_signal; regs->skas.regs[SS] = sc.ss; regs->skas.fault_addr = sc.cr2; regs->skas.fault_type = FAULT_WRITE(sc.err); regs->skas.trap_type = sc.trapno; - err = ptrace(PTRACE_SETFPREGS, userspace_pid, 0, fpregs); + err = ptrace(PTRACE_SETFPREGS, pid, 0, fpregs); if(err < 0){ printk("copy_sc_to_user - PTRACE_SETFPREGS failed, " "errno = %d\n", errno); @@ -57,8 +55,9 @@ return(0); } -int copy_sc_to_user_skas(void *to_ptr, void *fp, union uml_pt_regs *regs, - unsigned long fault_addr, int fault_type) +int copy_sc_to_user_skas(int pid, void *to_ptr, void *fp, + union uml_pt_regs *regs, unsigned long fault_addr, + int fault_type) { struct sigcontext sc, *to = to_ptr; struct _fpstate *to_fp; @@ -86,7 +85,7 @@ sc.err = TO_SC_ERR(fault_type); sc.trapno = regs->skas.trap_type; - err = ptrace(PTRACE_GETFPREGS, userspace_pid, 0, fpregs); + err = ptrace(PTRACE_GETFPREGS, pid, 0, fpregs); if(err < 0){ printk("copy_sc_to_user - PTRACE_GETFPREGS failed, " "errno = %d\n", errno); diff -Nru a/arch/um/kernel/skas/syscall_kern.c b/arch/um/kernel/skas/syscall_kern.c --- a/arch/um/kernel/skas/syscall_kern.c 2004-08-25 22:01:55 -07:00 +++ b/arch/um/kernel/skas/syscall_kern.c 2004-08-25 22:01:55 -07:00 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) + * Copyright (C) 2002 - 2003 Jeff Dike (jdike@addtoit.com) * Licensed under the GPL */ diff -Nru a/arch/um/kernel/skas/syscall_user.c b/arch/um/kernel/skas/syscall_user.c --- a/arch/um/kernel/skas/syscall_user.c 2004-08-25 22:01:56 -07:00 +++ b/arch/um/kernel/skas/syscall_user.c 2004-08-25 22:01:56 -07:00 @@ -22,7 +22,7 @@ index = record_syscall_start(UPT_SYSCALL_NR(regs)); - syscall_trace(); + syscall_trace(regs, 1); result = execute_syscall(regs); REGS_SET_SYSCALL_RETURN(regs->skas.regs, result); @@ -30,7 +30,7 @@ (result == -ERESTARTNOINTR)) do_signal(result); - syscall_trace(); + syscall_trace(regs, 0); record_syscall_end(index, result); } diff -Nru a/arch/um/kernel/skas/trap_user.c b/arch/um/kernel/skas/trap_user.c --- a/arch/um/kernel/skas/trap_user.c 2004-08-25 22:01:55 -07:00 +++ b/arch/um/kernel/skas/trap_user.c 2004-08-25 22:01:55 -07:00 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) + * Copyright (C) 2002 - 2003 Jeff Dike (jdike@addtoit.com) * Licensed under the GPL */ @@ -35,14 +35,10 @@ errno = save_errno; } -extern int missed_ticks[]; - void user_signal(int sig, union uml_pt_regs *regs) { struct signal_info *info; - if(sig == SIGVTALRM) - missed_ticks[cpu()]++; regs->skas.is_user = 1; regs->skas.fault_addr = 0; regs->skas.fault_type = 0; diff -Nru a/arch/um/kernel/skas/uaccess.c b/arch/um/kernel/skas/uaccess.c --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/arch/um/kernel/skas/uaccess.c 2004-08-25 22:01:56 -07:00 @@ -0,0 +1,219 @@ +/* + * Copyright (C) 2002 - 2003 Jeff Dike (jdike@addtoit.com) + * Licensed under the GPL + */ + +#include "linux/stddef.h" +#include "linux/kernel.h" +#include "linux/string.h" +#include "linux/fs.h" +#include "linux/highmem.h" +#include "asm/page.h" +#include "asm/pgtable.h" +#include "asm/uaccess.h" +#include "kern_util.h" + +extern void *um_virt_to_phys(struct task_struct *task, unsigned long addr, + pte_t *pte_out); + +static unsigned long maybe_map(unsigned long virt, int is_write) +{ + pte_t pte; + int err; + + void *phys = um_virt_to_phys(current, virt, &pte); + int dummy_code; + + if(IS_ERR(phys) || (is_write && !pte_write(pte))){ + err = handle_page_fault(virt, 0, is_write, 1, &dummy_code); + if(err) + return(0); + phys = um_virt_to_phys(current, virt, NULL); + } + return((unsigned long) phys); +} + +static int do_op(unsigned long addr, int len, int is_write, + int (*op)(unsigned long addr, int len, void *arg), void *arg) +{ + struct page *page; + int n; + + addr = maybe_map(addr, is_write); + if(addr == -1) + return(-1); + + page = phys_to_page(addr); + addr = (unsigned long) kmap(page) + (addr & ~PAGE_MASK); + n = (*op)(addr, len, arg); + kunmap(page); + + return(n); +} + +static int buffer_op(unsigned long addr, int len, int is_write, + int (*op)(unsigned long addr, int len, void *arg), + void *arg) +{ + int size = min(PAGE_ALIGN(addr) - addr, (unsigned long) len); + int remain = len, n; + + n = do_op(addr, size, is_write, op, arg); + if(n != 0) + return(n < 0 ? remain : 0); + + addr += size; + remain -= size; + if(remain == 0) + return(0); + + while(addr < ((addr + remain) & PAGE_MASK)){ + n = do_op(addr, PAGE_SIZE, is_write, op, arg); + if(n != 0) + return(n < 0 ? remain : 0); + + addr += PAGE_SIZE; + remain -= PAGE_SIZE; + } + if(remain == 0) + return(0); + + n = do_op(addr, remain, is_write, op, arg); + if(n != 0) + return(n < 0 ? remain : 0); + return(0); +} + +static int copy_chunk_from_user(unsigned long from, int len, void *arg) +{ + unsigned long *to_ptr = arg, to = *to_ptr; + + memcpy((void *) to, (void *) from, len); + *to_ptr += len; + return(0); +} + +int copy_from_user_skas(void *to, const void *from, int n) +{ + if(segment_eq(get_fs(), KERNEL_DS)){ + memcpy(to, from, n); + return(0); + } + + return(access_ok_skas(VERIFY_READ, from, n) ? + buffer_op((unsigned long) from, n, 0, copy_chunk_from_user, &to): + n); +} + +static int copy_chunk_to_user(unsigned long to, int len, void *arg) +{ + unsigned long *from_ptr = arg, from = *from_ptr; + + memcpy((void *) to, (void *) from, len); + *from_ptr += len; + return(0); +} + +int copy_to_user_skas(void *to, const void *from, int n) +{ + if(segment_eq(get_fs(), KERNEL_DS)){ + memcpy(to, from, n); + return(0); + } + + return(access_ok_skas(VERIFY_WRITE, to, n) ? + buffer_op((unsigned long) to, n, 1, copy_chunk_to_user, &from) : + n); +} + +static int strncpy_chunk_from_user(unsigned long from, int len, void *arg) +{ + char **to_ptr = arg, *to = *to_ptr; + int n; + + strncpy(to, (void *) from, len); + n = strnlen(to, len); + *to_ptr += n; + + if(n < len) + return(1); + return(0); +} + +int strncpy_from_user_skas(char *dst, const char *src, int count) +{ + int n; + char *ptr = dst; + + if(segment_eq(get_fs(), KERNEL_DS)){ + strncpy(dst, src, count); + return(strnlen(dst, count)); + } + + if(!access_ok_skas(VERIFY_READ, src, 1)) + return(-EFAULT); + + n = buffer_op((unsigned long) src, count, 0, strncpy_chunk_from_user, + &ptr); + if(n != 0) + return(-EFAULT); + return(strnlen(dst, count)); +} + +static int clear_chunk(unsigned long addr, int len, void *unused) +{ + memset((void *) addr, 0, len); + return(0); +} + +int __clear_user_skas(void *mem, int len) +{ + return(buffer_op((unsigned long) mem, len, 1, clear_chunk, NULL)); +} + +int clear_user_skas(void *mem, int len) +{ + if(segment_eq(get_fs(), KERNEL_DS)){ + memset(mem, 0, len); + return(0); + } + + return(access_ok_skas(VERIFY_WRITE, mem, len) ? + buffer_op((unsigned long) mem, len, 1, clear_chunk, NULL) : len); +} + +static int strnlen_chunk(unsigned long str, int len, void *arg) +{ + int *len_ptr = arg, n; + + n = strnlen((void *) str, len); + *len_ptr += n; + + if(n < len) + return(1); + return(0); +} + +int strnlen_user_skas(const void *str, int len) +{ + int count = 0, n; + + if(segment_eq(get_fs(), KERNEL_DS)) + return(strnlen(str, len) + 1); + + n = buffer_op((unsigned long) str, len, 0, strnlen_chunk, &count); + if(n == 0) + return(count + 1); + return(-EFAULT); +} + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff -Nru a/arch/um/kernel/skas/util/Makefile b/arch/um/kernel/skas/util/Makefile --- a/arch/um/kernel/skas/util/Makefile 2004-08-25 22:01:56 -07:00 +++ b/arch/um/kernel/skas/util/Makefile 2004-08-25 22:01:56 -07:00 @@ -1,10 +1,9 @@ all: mk_ptregs mk_ptregs : mk_ptregs.o - $(CC) -o mk_ptregs mk_ptregs.o + $(HOSTCC) -o mk_ptregs mk_ptregs.o mk_ptregs.o : mk_ptregs.c - $(CC) -c $< + $(HOSTCC) -c $< -clean : - $(RM) -f mk_ptregs *.o *~ +clean-files := mk_ptregs *.o *~ diff -Nru a/arch/um/kernel/skas/util/mk_ptregs.c b/arch/um/kernel/skas/util/mk_ptregs.c --- a/arch/um/kernel/skas/util/mk_ptregs.c 2004-08-25 22:01:55 -07:00 +++ b/arch/um/kernel/skas/util/mk_ptregs.c 2004-08-25 22:01:55 -07:00 @@ -1,3 +1,4 @@ +#include #include #include diff -Nru a/arch/um/kernel/smp.c b/arch/um/kernel/smp.c --- a/arch/um/kernel/smp.c 2004-08-25 22:01:54 -07:00 +++ b/arch/um/kernel/smp.c 2004-08-25 22:01:54 -07:00 @@ -1,9 +1,15 @@ /* - * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) + * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com) * Licensed under the GPL */ #include "linux/config.h" +#include "linux/percpu.h" +#include "asm/pgalloc.h" +#include "asm/tlb.h" + +/* For some reason, mmu_gathers are referenced when CONFIG_SMP is off. */ +DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); #ifdef CONFIG_SMP @@ -23,7 +29,7 @@ #include "os.h" /* CPU online map, set by smp_boot_cpus */ -unsigned long cpu_online_map = cpumask_of_cpu(0); +unsigned long cpu_online_map = CPU_MASK_NONE; EXPORT_SYMBOL(cpu_online_map); @@ -33,14 +39,6 @@ */ struct cpuinfo_um cpu_data[NR_CPUS]; -spinlock_t um_bh_lock = SPIN_LOCK_UNLOCKED; - -atomic_t global_bh_count; - -/* Not used by UML */ -unsigned char global_irq_holder = NO_PROC_ID; -unsigned volatile long global_irq_lock; - /* Set when the idlers are all forked */ int smp_threads_ready = 0; @@ -55,80 +53,44 @@ void smp_send_reschedule(int cpu) { - write(cpu_data[cpu].ipi_pipe[1], "R", 1); + os_write_file(cpu_data[cpu].ipi_pipe[1], "R", 1); num_reschedules_sent++; } -static void show(char * str) -{ - int cpu = smp_processor_id(); - - printk(KERN_INFO "\n%s, CPU %d:\n", str, cpu); -} - -#define MAXCOUNT 100000000 - -static inline void wait_on_bh(void) -{ - int count = MAXCOUNT; - do { - if (!--count) { - show("wait_on_bh"); - count = ~0; - } - /* nothing .. wait for the other bh's to go away */ - } while (atomic_read(&global_bh_count) != 0); -} - -/* - * This is called when we want to synchronize with - * bottom half handlers. We need to wait until - * no other CPU is executing any bottom half handler. - * - * Don't wait if we're already running in an interrupt - * context or are inside a bh handler. - */ -void synchronize_bh(void) -{ - if (atomic_read(&global_bh_count) && !in_interrupt()) - wait_on_bh(); -} - void smp_send_stop(void) { int i; printk(KERN_INFO "Stopping all CPUs..."); for(i = 0; i < num_online_cpus(); i++){ - if(i == current->thread_info->cpu) + if(i == current_thread->cpu) continue; - write(cpu_data[i].ipi_pipe[1], "S", 1); + os_write_file(cpu_data[i].ipi_pipe[1], "S", 1); } printk("done\n"); } -static cpumask_t smp_commenced_mask; -static cpumask_t smp_callin_map = CPU_MASK_NONE; +static cpumask_t smp_commenced_mask = CPU_MASK_NONE; +static cpumask_t cpu_callin_map = CPU_MASK_NONE; static int idle_proc(void *cpup) { int cpu = (int) cpup, err; err = os_pipe(cpu_data[cpu].ipi_pipe, 1, 1); - if(err) - panic("CPU#%d failed to create IPI pipe, errno = %d", cpu, - -err); + if(err < 0) + panic("CPU#%d failed to create IPI pipe, err = %d", cpu, -err); activate_ipi(cpu_data[cpu].ipi_pipe[0], current->thread.mode.tt.extern_pid); wmb(); - if (cpu_test_and_set(cpu, &smp_callin_map)) { + if (cpu_test_and_set(cpu, cpu_callin_map)) { printk("huh, CPU#%d already present??\n", cpu); BUG(); } - while (!cpu_isset(cpu, &smp_commenced_mask)) + while (!cpu_isset(cpu, smp_commenced_mask)) cpu_relax(); cpu_set(cpu, cpu_online_map); @@ -143,14 +105,16 @@ current->thread.request.u.thread.proc = idle_proc; current->thread.request.u.thread.arg = (void *) cpu; - new_task = do_fork(CLONE_VM | CLONE_IDLETASK, 0, NULL, 0, NULL, NULL); - if(IS_ERR(new_task)) panic("do_fork failed in idle_thread"); + new_task = fork_idle(cpu); + if(IS_ERR(new_task)) + panic("copy_process failed in idle_thread, error = %ld", + PTR_ERR(new_task)); cpu_tasks[cpu] = ((struct cpu_task) { .pid = new_task->thread.mode.tt.extern_pid, .task = new_task } ); idle_threads[cpu] = new_task; - CHOOSE_MODE(write(new_task->thread.mode.tt.switch_pipe[1], &c, + CHOOSE_MODE(os_write_file(new_task->thread.mode.tt.switch_pipe[1], &c, sizeof(c)), ({ panic("skas mode doesn't support SMP"); })); return(new_task); @@ -160,15 +124,17 @@ { struct task_struct *idle; unsigned long waittime; - int err, cpu; + int err, cpu, me = smp_processor_id(); - cpu_set(0, cpu_online_map); - cpu_set(0, smp_callin_map); + cpu_clear(me, cpu_online_map); + cpu_set(me, cpu_online_map); + cpu_set(me, cpu_callin_map); - err = os_pipe(cpu_data[0].ipi_pipe, 1, 1); - if(err) panic("CPU#0 failed to create IPI pipe, errno = %d", -err); + err = os_pipe(cpu_data[me].ipi_pipe, 1, 1); + if(err < 0) + panic("CPU#0 failed to create IPI pipe, errno = %d", -err); - activate_ipi(cpu_data[0].ipi_pipe[0], + activate_ipi(cpu_data[me].ipi_pipe[0], current->thread.mode.tt.extern_pid); for(cpu = 1; cpu < ncpus; cpu++){ @@ -180,10 +146,10 @@ unhash_process(idle); waittime = 200000000; - while (waittime-- && !cpu_isset(cpu, smp_callin_map)) + while (waittime-- && !cpu_isset(cpu, cpu_callin_map)) cpu_relax(); - if (cpu_isset(cpu, smp_callin_map)) + if (cpu_isset(cpu, cpu_callin_map)) printk("done\n"); else printk("failed\n"); } @@ -216,7 +182,7 @@ int fd; fd = cpu_data[cpu].ipi_pipe[0]; - while (read(fd, &c, 1) == 1) { + while (os_read_file(fd, &c, 1) == 1) { switch (c) { case 'C': smp_call_function_slave(cpu); @@ -276,9 +242,9 @@ info = _info; for (i=0;ithread_info->cpu) && + if((i != current_thread->cpu) && cpu_isset(i, cpu_online_map)) - write(cpu_data[i].ipi_pipe[1], "C", 1); + os_write_file(cpu_data[i].ipi_pipe[1], "C", 1); while (atomic_read(&scf_started) != cpus) barrier(); diff -Nru a/arch/um/kernel/sys_call_table.c b/arch/um/kernel/sys_call_table.c --- a/arch/um/kernel/sys_call_table.c 2004-08-25 22:01:56 -07:00 +++ b/arch/um/kernel/sys_call_table.c 2004-08-25 22:01:56 -07:00 @@ -5,7 +5,6 @@ #include "linux/config.h" #include "linux/unistd.h" -#include "linux/version.h" #include "linux/sys.h" #include "linux/swap.h" #include "linux/syscalls.h" @@ -14,251 +13,50 @@ #include "sysdep/syscalls.h" #include "kern_util.h" -extern syscall_handler_t sys_restart_syscall; -extern syscall_handler_t sys_ni_syscall; -extern syscall_handler_t sys_exit; +#ifdef CONFIG_NFSD +#define NFSSERVCTL sys_nfsservctl +#else +#define NFSSERVCTL sys_ni_syscall +#endif + +#define LAST_GENERIC_SYSCALL __NR_vserver + +#if LAST_GENERIC_SYSCALL > LAST_ARCH_SYSCALL +#define LAST_SYSCALL LAST_GENERIC_SYSCALL +#else +#define LAST_SYSCALL LAST_ARCH_SYSCALL +#endif + extern syscall_handler_t sys_fork; -extern syscall_handler_t sys_creat; -extern syscall_handler_t sys_link; -extern syscall_handler_t sys_unlink; -extern syscall_handler_t sys_chdir; -extern syscall_handler_t sys_mknod; -extern syscall_handler_t sys_chmod; -extern syscall_handler_t sys_lchown16; -extern syscall_handler_t sys_ni_syscall; -extern syscall_handler_t sys_stat; -extern syscall_handler_t sys_getpid; -extern syscall_handler_t sys_oldumount; -extern syscall_handler_t sys_setuid16; -extern syscall_handler_t sys_getuid16; +extern syscall_handler_t sys_execve; +extern syscall_handler_t um_time; +extern syscall_handler_t um_mount; +extern syscall_handler_t um_stime; extern syscall_handler_t sys_ptrace; -extern syscall_handler_t sys_alarm; -extern syscall_handler_t sys_fstat; -extern syscall_handler_t sys_pause; -extern syscall_handler_t sys_utime; -extern syscall_handler_t sys_ni_syscall; -extern syscall_handler_t sys_ni_syscall; -extern syscall_handler_t sys_access; -extern syscall_handler_t sys_nice; -extern syscall_handler_t sys_ni_syscall; -extern syscall_handler_t sys_sync; -extern syscall_handler_t sys_kill; -extern syscall_handler_t sys_rename; -extern syscall_handler_t sys_mkdir; -extern syscall_handler_t sys_rmdir; extern syscall_handler_t sys_pipe; -extern syscall_handler_t sys_times; -extern syscall_handler_t sys_ni_syscall; -extern syscall_handler_t sys_brk; -extern syscall_handler_t sys_setgid16; -extern syscall_handler_t sys_getgid16; -extern syscall_handler_t sys_signal; -extern syscall_handler_t sys_geteuid16; -extern syscall_handler_t sys_getegid16; -extern syscall_handler_t sys_acct; -extern syscall_handler_t sys_umount; -extern syscall_handler_t sys_ni_syscall; -extern syscall_handler_t sys_ioctl; -extern syscall_handler_t sys_fcntl; -extern syscall_handler_t sys_ni_syscall; -extern syscall_handler_t sys_setpgid; -extern syscall_handler_t sys_ni_syscall; extern syscall_handler_t sys_olduname; -extern syscall_handler_t sys_umask; -extern syscall_handler_t sys_chroot; -extern syscall_handler_t sys_ustat; -extern syscall_handler_t sys_dup2; -extern syscall_handler_t sys_getppid; -extern syscall_handler_t sys_getpgrp; extern syscall_handler_t sys_sigaction; -extern syscall_handler_t sys_sgetmask; -extern syscall_handler_t sys_ssetmask; -extern syscall_handler_t sys_setreuid16; -extern syscall_handler_t sys_setregid16; extern syscall_handler_t sys_sigsuspend; -extern syscall_handler_t sys_sigpending; -extern syscall_handler_t sys_sethostname; -extern syscall_handler_t sys_setrlimit; -extern syscall_handler_t sys_old_getrlimit; -extern syscall_handler_t sys_getrusage; -extern syscall_handler_t sys_gettimeofday; -extern syscall_handler_t sys_settimeofday; -extern syscall_handler_t sys_getgroups16; -extern syscall_handler_t sys_setgroups16; -extern syscall_handler_t sys_symlink; -extern syscall_handler_t sys_lstat; -extern syscall_handler_t sys_readlink; -extern syscall_handler_t sys_swapon; -extern syscall_handler_t sys_uselib; -extern syscall_handler_t sys_reboot; extern syscall_handler_t old_readdir; -extern syscall_handler_t sys_munmap; -extern syscall_handler_t sys_truncate; -extern syscall_handler_t sys_ftruncate; -extern syscall_handler_t sys_fchmod; -extern syscall_handler_t sys_fchown16; -extern syscall_handler_t sys_getpriority; -extern syscall_handler_t sys_setpriority; -extern syscall_handler_t sys_ni_syscall; -extern syscall_handler_t sys_statfs; -extern syscall_handler_t sys_fstatfs; -extern syscall_handler_t sys_ni_syscall; -extern syscall_handler_t sys_socketcall; -extern syscall_handler_t sys_syslog; -extern syscall_handler_t sys_setitimer; -extern syscall_handler_t sys_getitimer; -extern syscall_handler_t sys_newstat; -extern syscall_handler_t sys_newlstat; -extern syscall_handler_t sys_newfstat; extern syscall_handler_t sys_uname; -extern syscall_handler_t sys_ni_syscall; -extern syscall_handler_t sys_vhangup; -extern syscall_handler_t sys_ni_syscall; -extern syscall_handler_t sys_ni_syscall; -extern syscall_handler_t sys_swapoff; -extern syscall_handler_t sys_sysinfo; extern syscall_handler_t sys_ipc; -extern syscall_handler_t sys_fsync; extern syscall_handler_t sys_sigreturn; -extern syscall_handler_t sys_rt_sigreturn; extern syscall_handler_t sys_clone; -extern syscall_handler_t sys_setdomainname; -extern syscall_handler_t sys_newuname; -extern syscall_handler_t sys_ni_syscall; -extern syscall_handler_t sys_adjtimex; -extern syscall_handler_t sys_mprotect; -extern syscall_handler_t sys_sigprocmask; -extern syscall_handler_t sys_init_module; -extern syscall_handler_t sys_delete_module; -extern syscall_handler_t sys_quotactl; -extern syscall_handler_t sys_getpgid; -extern syscall_handler_t sys_fchdir; -extern syscall_handler_t sys_bdflush; -extern syscall_handler_t sys_sysfs; -extern syscall_handler_t sys_personality; -extern syscall_handler_t sys_ni_syscall; -extern syscall_handler_t sys_setfsuid16; -extern syscall_handler_t sys_setfsgid16; -extern syscall_handler_t sys_llseek; -extern syscall_handler_t sys_getdents; -extern syscall_handler_t sys_flock; -extern syscall_handler_t sys_msync; -extern syscall_handler_t sys_readv; -extern syscall_handler_t sys_writev; -extern syscall_handler_t sys_getsid; -extern syscall_handler_t sys_fdatasync; -extern syscall_handler_t sys_mlock; -extern syscall_handler_t sys_munlock; -extern syscall_handler_t sys_mlockall; -extern syscall_handler_t sys_munlockall; -extern syscall_handler_t sys_sched_setparam; -extern syscall_handler_t sys_sched_getparam; -extern syscall_handler_t sys_sched_setscheduler; -extern syscall_handler_t sys_sched_getscheduler; -extern syscall_handler_t sys_sched_get_priority_max; -extern syscall_handler_t sys_sched_get_priority_min; -extern syscall_handler_t sys_sched_rr_get_interval; -extern syscall_handler_t sys_nanosleep; -extern syscall_handler_t sys_mremap; -extern syscall_handler_t sys_setresuid16; -extern syscall_handler_t sys_getresuid16; -extern syscall_handler_t sys_ni_syscall; -extern syscall_handler_t sys_poll; -extern syscall_handler_t sys_nfsservctl; -extern syscall_handler_t sys_setresgid16; -extern syscall_handler_t sys_getresgid16; -extern syscall_handler_t sys_prctl; -extern syscall_handler_t sys_ni_syscall; +extern syscall_handler_t sys_rt_sigreturn; extern syscall_handler_t sys_rt_sigaction; -extern syscall_handler_t sys_rt_sigprocmask; -extern syscall_handler_t sys_rt_sigpending; -extern syscall_handler_t sys_rt_sigtimedwait; -extern syscall_handler_t sys_rt_sigqueueinfo; -extern syscall_handler_t sys_rt_sigsuspend; -extern syscall_handler_t sys_pread64; -extern syscall_handler_t sys_pwrite64; -extern syscall_handler_t sys_chown16; -extern syscall_handler_t sys_getcwd; -extern syscall_handler_t sys_capget; -extern syscall_handler_t sys_capset; extern syscall_handler_t sys_sigaltstack; -extern syscall_handler_t sys_sendfile; -extern syscall_handler_t sys_ni_syscall; -extern syscall_handler_t sys_ni_syscall; extern syscall_handler_t sys_vfork; -extern syscall_handler_t sys_getrlimit; extern syscall_handler_t sys_mmap2; -extern syscall_handler_t sys_truncate64; -extern syscall_handler_t sys_ftruncate64; -extern syscall_handler_t sys_stat64; -extern syscall_handler_t sys_lstat64; -extern syscall_handler_t sys_fstat64; -extern syscall_handler_t sys_lchown; -extern syscall_handler_t sys_getuid; -extern syscall_handler_t sys_getgid; -extern syscall_handler_t sys_geteuid; -extern syscall_handler_t sys_getegid; -extern syscall_handler_t sys_setreuid; -extern syscall_handler_t sys_setregid; -extern syscall_handler_t sys_getgroups; -extern syscall_handler_t sys_setgroups; -extern syscall_handler_t sys_fchown; -extern syscall_handler_t sys_setresuid; -extern syscall_handler_t sys_getresuid; -extern syscall_handler_t sys_setresgid; -extern syscall_handler_t sys_getresgid; -extern syscall_handler_t sys_chown; -extern syscall_handler_t sys_setuid; -extern syscall_handler_t sys_setgid; -extern syscall_handler_t sys_setfsuid; -extern syscall_handler_t sys_setfsgid; -extern syscall_handler_t sys_pivot_root; -extern syscall_handler_t sys_mincore; -extern syscall_handler_t sys_madvise; -extern syscall_handler_t sys_fcntl64; -extern syscall_handler_t sys_getdents64; -extern syscall_handler_t sys_gettid; -extern syscall_handler_t sys_readahead; -extern syscall_handler_t sys_tkill; -extern syscall_handler_t sys_sendfile64; -extern syscall_handler_t sys_futex; -extern syscall_handler_t sys_sched_setaffinity; -extern syscall_handler_t sys_sched_getaffinity; -extern syscall_handler_t sys_io_setup; -extern syscall_handler_t sys_io_destroy; -extern syscall_handler_t sys_io_getevents; -extern syscall_handler_t sys_io_submit; -extern syscall_handler_t sys_io_cancel; -extern syscall_handler_t sys_exit_group; -extern syscall_handler_t sys_lookup_dcookie; -extern syscall_handler_t sys_epoll_create; -extern syscall_handler_t sys_epoll_ctl; -extern syscall_handler_t sys_epoll_wait; -extern syscall_handler_t sys_remap_file_pages; -extern syscall_handler_t sys_set_tid_address; - -#ifdef CONFIG_NFSD -#define NFSSERVCTL sys_nfsservctl -#else -#define NFSSERVCTL sys_ni_syscall -#endif - -extern syscall_handler_t um_mount; -extern syscall_handler_t um_time; -extern syscall_handler_t um_stime; - -#define LAST_GENERIC_SYSCALL __NR_set_tid_address - -#if LAST_GENERIC_SYSCALL > LAST_ARCH_SYSCALL -#define LAST_SYSCALL LAST_GENERIC_SYSCALL -#else -#define LAST_SYSCALL LAST_ARCH_SYSCALL -#endif +extern syscall_handler_t sys_timer_create; +extern syscall_handler_t old_mmap_i386; +extern syscall_handler_t old_select; +extern syscall_handler_t sys_modify_ldt; +extern syscall_handler_t sys_rt_sigsuspend; syscall_handler_t *sys_call_table[] = { - [ __NR_restart_syscall ] = sys_restart_syscall, - [ __NR_exit ] = sys_exit, - [ __NR_fork ] = sys_fork, + [ __NR_restart_syscall ] = (syscall_handler_t *) sys_restart_syscall, + [ __NR_exit ] (syscall_handler_t *) sys_exit, + [ __NR_fork ] (syscall_handler_t *) sys_fork, [ __NR_read ] = (syscall_handler_t *) sys_read, [ __NR_write ] = (syscall_handler_t *) sys_write, @@ -266,229 +64,249 @@ [ __NR_open ] = (syscall_handler_t *) sys_open, [ __NR_close ] = (syscall_handler_t *) sys_close, [ __NR_waitpid ] = (syscall_handler_t *) sys_waitpid, - [ __NR_creat ] = sys_creat, - [ __NR_link ] = sys_link, - [ __NR_unlink ] = sys_unlink, + [ __NR_creat ] (syscall_handler_t *) sys_creat, + [ __NR_link ] (syscall_handler_t *) sys_link, + [ __NR_unlink ] (syscall_handler_t *) sys_unlink, [ __NR_execve ] = (syscall_handler_t *) sys_execve, /* declared differently in kern_util.h */ - [ __NR_chdir ] = sys_chdir, + [ __NR_chdir ] (syscall_handler_t *) sys_chdir, [ __NR_time ] = um_time, - [ __NR_mknod ] = sys_mknod, - [ __NR_chmod ] = sys_chmod, - [ __NR_lchown ] = sys_lchown16, - [ __NR_break ] = sys_ni_syscall, - [ __NR_oldstat ] = sys_stat, + [ __NR_mknod ] (syscall_handler_t *) sys_mknod, + [ __NR_chmod ] (syscall_handler_t *) sys_chmod, + [ __NR_lchown ] (syscall_handler_t *) sys_lchown16, + [ __NR_break ] (syscall_handler_t *) sys_ni_syscall, + [ __NR_oldstat ] (syscall_handler_t *) sys_stat, [ __NR_lseek ] = (syscall_handler_t *) sys_lseek, - [ __NR_getpid ] = sys_getpid, + [ __NR_getpid ] (syscall_handler_t *) sys_getpid, [ __NR_mount ] = um_mount, - [ __NR_umount ] = sys_oldumount, - [ __NR_setuid ] = sys_setuid16, - [ __NR_getuid ] = sys_getuid16, + [ __NR_umount ] (syscall_handler_t *) sys_oldumount, + [ __NR_setuid ] (syscall_handler_t *) sys_setuid16, + [ __NR_getuid ] (syscall_handler_t *) sys_getuid16, [ __NR_stime ] = um_stime, - [ __NR_ptrace ] = sys_ptrace, - [ __NR_alarm ] = sys_alarm, - [ __NR_oldfstat ] = sys_fstat, - [ __NR_pause ] = sys_pause, - [ __NR_utime ] = sys_utime, - [ __NR_stty ] = sys_ni_syscall, - [ __NR_gtty ] = sys_ni_syscall, - [ __NR_access ] = sys_access, - [ __NR_nice ] = sys_nice, - [ __NR_ftime ] = sys_ni_syscall, - [ __NR_sync ] = sys_sync, - [ __NR_kill ] = sys_kill, - [ __NR_rename ] = sys_rename, - [ __NR_mkdir ] = sys_mkdir, - [ __NR_rmdir ] = sys_rmdir, + [ __NR_ptrace ] (syscall_handler_t *) sys_ptrace, + [ __NR_alarm ] (syscall_handler_t *) sys_alarm, + [ __NR_oldfstat ] (syscall_handler_t *) sys_fstat, + [ __NR_pause ] (syscall_handler_t *) sys_pause, + [ __NR_utime ] (syscall_handler_t *) sys_utime, + [ __NR_stty ] (syscall_handler_t *) sys_ni_syscall, + [ __NR_gtty ] (syscall_handler_t *) sys_ni_syscall, + [ __NR_access ] (syscall_handler_t *) sys_access, + [ __NR_nice ] (syscall_handler_t *) sys_nice, + [ __NR_ftime ] (syscall_handler_t *) sys_ni_syscall, + [ __NR_sync ] (syscall_handler_t *) sys_sync, + [ __NR_kill ] (syscall_handler_t *) sys_kill, + [ __NR_rename ] (syscall_handler_t *) sys_rename, + [ __NR_mkdir ] (syscall_handler_t *) sys_mkdir, + [ __NR_rmdir ] (syscall_handler_t *) sys_rmdir, /* Declared differently in asm/unistd.h */ [ __NR_dup ] = (syscall_handler_t *) sys_dup, - [ __NR_pipe ] = sys_pipe, - [ __NR_times ] = sys_times, - [ __NR_prof ] = sys_ni_syscall, - [ __NR_brk ] = sys_brk, - [ __NR_setgid ] = sys_setgid16, - [ __NR_getgid ] = sys_getgid16, - [ __NR_signal ] = sys_signal, - [ __NR_geteuid ] = sys_geteuid16, - [ __NR_getegid ] = sys_getegid16, - [ __NR_acct ] = sys_acct, - [ __NR_umount2 ] = sys_umount, - [ __NR_lock ] = sys_ni_syscall, - [ __NR_ioctl ] = sys_ioctl, - [ __NR_fcntl ] = sys_fcntl, - [ __NR_mpx ] = sys_ni_syscall, - [ __NR_setpgid ] = sys_setpgid, - [ __NR_ulimit ] = sys_ni_syscall, - [ __NR_oldolduname ] = sys_olduname, - [ __NR_umask ] = sys_umask, - [ __NR_chroot ] = sys_chroot, - [ __NR_ustat ] = sys_ustat, - [ __NR_dup2 ] = sys_dup2, - [ __NR_getppid ] = sys_getppid, - [ __NR_getpgrp ] = sys_getpgrp, + [ __NR_pipe ] (syscall_handler_t *) sys_pipe, + [ __NR_times ] (syscall_handler_t *) sys_times, + [ __NR_prof ] (syscall_handler_t *) sys_ni_syscall, + [ __NR_brk ] (syscall_handler_t *) sys_brk, + [ __NR_setgid ] (syscall_handler_t *) sys_setgid16, + [ __NR_getgid ] (syscall_handler_t *) sys_getgid16, + [ __NR_signal ] (syscall_handler_t *) sys_signal, + [ __NR_geteuid ] (syscall_handler_t *) sys_geteuid16, + [ __NR_getegid ] (syscall_handler_t *) sys_getegid16, + [ __NR_acct ] (syscall_handler_t *) sys_acct, + [ __NR_umount2 ] (syscall_handler_t *) sys_umount, + [ __NR_lock ] (syscall_handler_t *) sys_ni_syscall, + [ __NR_ioctl ] (syscall_handler_t *) sys_ioctl, + [ __NR_fcntl ] (syscall_handler_t *) sys_fcntl, + [ __NR_mpx ] (syscall_handler_t *) sys_ni_syscall, + [ __NR_setpgid ] (syscall_handler_t *) sys_setpgid, + [ __NR_ulimit ] (syscall_handler_t *) sys_ni_syscall, + [ __NR_oldolduname ] (syscall_handler_t *) sys_olduname, + [ __NR_umask ] (syscall_handler_t *) sys_umask, + [ __NR_chroot ] (syscall_handler_t *) sys_chroot, + [ __NR_ustat ] (syscall_handler_t *) sys_ustat, + [ __NR_dup2 ] (syscall_handler_t *) sys_dup2, + [ __NR_getppid ] (syscall_handler_t *) sys_getppid, + [ __NR_getpgrp ] (syscall_handler_t *) sys_getpgrp, [ __NR_setsid ] = (syscall_handler_t *) sys_setsid, - [ __NR_sigaction ] = sys_sigaction, - [ __NR_sgetmask ] = sys_sgetmask, - [ __NR_ssetmask ] = sys_ssetmask, - [ __NR_setreuid ] = sys_setreuid16, - [ __NR_setregid ] = sys_setregid16, - [ __NR_sigsuspend ] = sys_sigsuspend, - [ __NR_sigpending ] = sys_sigpending, - [ __NR_sethostname ] = sys_sethostname, - [ __NR_setrlimit ] = sys_setrlimit, - [ __NR_getrlimit ] = sys_old_getrlimit, - [ __NR_getrusage ] = sys_getrusage, - [ __NR_gettimeofday ] = sys_gettimeofday, - [ __NR_settimeofday ] = sys_settimeofday, - [ __NR_getgroups ] = sys_getgroups16, - [ __NR_setgroups ] = sys_setgroups16, - [ __NR_symlink ] = sys_symlink, - [ __NR_oldlstat ] = sys_lstat, - [ __NR_readlink ] = sys_readlink, - [ __NR_uselib ] = sys_uselib, + [ __NR_sigaction ] (syscall_handler_t *) sys_sigaction, + [ __NR_sgetmask ] (syscall_handler_t *) sys_sgetmask, + [ __NR_ssetmask ] (syscall_handler_t *) sys_ssetmask, + [ __NR_setreuid ] (syscall_handler_t *) sys_setreuid16, + [ __NR_setregid ] (syscall_handler_t *) sys_setregid16, + [ __NR_sigsuspend ] (syscall_handler_t *) sys_sigsuspend, + [ __NR_sigpending ] (syscall_handler_t *) sys_sigpending, + [ __NR_sethostname ] (syscall_handler_t *) sys_sethostname, + [ __NR_setrlimit ] (syscall_handler_t *) sys_setrlimit, + [ __NR_getrlimit ] (syscall_handler_t *) sys_old_getrlimit, + [ __NR_getrusage ] (syscall_handler_t *) sys_getrusage, + [ __NR_gettimeofday ] (syscall_handler_t *) sys_gettimeofday, + [ __NR_settimeofday ] (syscall_handler_t *) sys_settimeofday, + [ __NR_getgroups ] (syscall_handler_t *) sys_getgroups16, + [ __NR_setgroups ] (syscall_handler_t *) sys_setgroups16, + [ __NR_symlink ] (syscall_handler_t *) sys_symlink, + [ __NR_oldlstat ] (syscall_handler_t *) sys_lstat, + [ __NR_readlink ] (syscall_handler_t *) sys_readlink, + [ __NR_uselib ] (syscall_handler_t *) sys_uselib, [ __NR_swapon ] = (syscall_handler_t *) sys_swapon, - [ __NR_reboot ] = sys_reboot, + [ __NR_reboot ] (syscall_handler_t *) sys_reboot, [ __NR_readdir ] = old_readdir, - [ __NR_munmap ] = sys_munmap, - [ __NR_truncate ] = sys_truncate, - [ __NR_ftruncate ] = sys_ftruncate, - [ __NR_fchmod ] = sys_fchmod, - [ __NR_fchown ] = sys_fchown16, - [ __NR_getpriority ] = sys_getpriority, - [ __NR_setpriority ] = sys_setpriority, - [ __NR_profil ] = sys_ni_syscall, - [ __NR_statfs ] = sys_statfs, - [ __NR_fstatfs ] = sys_fstatfs, - [ __NR_ioperm ] = sys_ni_syscall, - [ __NR_socketcall ] = sys_socketcall, - [ __NR_syslog ] = sys_syslog, - [ __NR_setitimer ] = sys_setitimer, - [ __NR_getitimer ] = sys_getitimer, - [ __NR_stat ] = sys_newstat, - [ __NR_lstat ] = sys_newlstat, - [ __NR_fstat ] = sys_newfstat, - [ __NR_olduname ] = sys_uname, - [ __NR_iopl ] = sys_ni_syscall, - [ __NR_vhangup ] = sys_vhangup, - [ __NR_idle ] = sys_ni_syscall, + [ __NR_munmap ] (syscall_handler_t *) sys_munmap, + [ __NR_truncate ] (syscall_handler_t *) sys_truncate, + [ __NR_ftruncate ] (syscall_handler_t *) sys_ftruncate, + [ __NR_fchmod ] (syscall_handler_t *) sys_fchmod, + [ __NR_fchown ] (syscall_handler_t *) sys_fchown16, + [ __NR_getpriority ] (syscall_handler_t *) sys_getpriority, + [ __NR_setpriority ] (syscall_handler_t *) sys_setpriority, + [ __NR_profil ] (syscall_handler_t *) sys_ni_syscall, + [ __NR_statfs ] (syscall_handler_t *) sys_statfs, + [ __NR_fstatfs ] (syscall_handler_t *) sys_fstatfs, + [ __NR_ioperm ] (syscall_handler_t *) sys_ni_syscall, + [ __NR_socketcall ] (syscall_handler_t *) sys_socketcall, + [ __NR_syslog ] (syscall_handler_t *) sys_syslog, + [ __NR_setitimer ] (syscall_handler_t *) sys_setitimer, + [ __NR_getitimer ] (syscall_handler_t *) sys_getitimer, + [ __NR_stat ] (syscall_handler_t *) sys_newstat, + [ __NR_lstat ] (syscall_handler_t *) sys_newlstat, + [ __NR_fstat ] (syscall_handler_t *) sys_newfstat, + [ __NR_olduname ] (syscall_handler_t *) sys_uname, + [ __NR_iopl ] (syscall_handler_t *) sys_ni_syscall, + [ __NR_vhangup ] (syscall_handler_t *) sys_vhangup, + [ __NR_idle ] (syscall_handler_t *) sys_ni_syscall, [ __NR_wait4 ] = (syscall_handler_t *) sys_wait4, [ __NR_swapoff ] = (syscall_handler_t *) sys_swapoff, - [ __NR_sysinfo ] = sys_sysinfo, - [ __NR_ipc ] = sys_ipc, - [ __NR_fsync ] = sys_fsync, - [ __NR_sigreturn ] = sys_sigreturn, - [ __NR_clone ] = sys_clone, - [ __NR_setdomainname ] = sys_setdomainname, - [ __NR_uname ] = sys_newuname, - [ __NR_adjtimex ] = sys_adjtimex, - [ __NR_mprotect ] = sys_mprotect, - [ __NR_sigprocmask ] = sys_sigprocmask, - [ __NR_create_module ] = sys_ni_syscall, - [ __NR_init_module ] = sys_init_module, - [ __NR_delete_module ] = sys_delete_module, - [ __NR_get_kernel_syms ] = sys_ni_syscall, - [ __NR_quotactl ] = sys_quotactl, - [ __NR_getpgid ] = sys_getpgid, - [ __NR_fchdir ] = sys_fchdir, - [ __NR_bdflush ] = sys_bdflush, - [ __NR_sysfs ] = sys_sysfs, - [ __NR_personality ] = sys_personality, - [ __NR_afs_syscall ] = sys_ni_syscall, - [ __NR_setfsuid ] = sys_setfsuid16, - [ __NR_setfsgid ] = sys_setfsgid16, - [ __NR__llseek ] = sys_llseek, - [ __NR_getdents ] = sys_getdents, + [ __NR_sysinfo ] (syscall_handler_t *) sys_sysinfo, + [ __NR_ipc ] (syscall_handler_t *) sys_ipc, + [ __NR_fsync ] (syscall_handler_t *) sys_fsync, + [ __NR_sigreturn ] (syscall_handler_t *) sys_sigreturn, + [ __NR_clone ] (syscall_handler_t *) sys_clone, + [ __NR_setdomainname ] (syscall_handler_t *) sys_setdomainname, + [ __NR_uname ] (syscall_handler_t *) sys_newuname, + [ __NR_adjtimex ] (syscall_handler_t *) sys_adjtimex, + [ __NR_mprotect ] (syscall_handler_t *) sys_mprotect, + [ __NR_sigprocmask ] (syscall_handler_t *) sys_sigprocmask, + [ __NR_create_module ] (syscall_handler_t *) sys_ni_syscall, + [ __NR_init_module ] (syscall_handler_t *) sys_init_module, + [ __NR_delete_module ] (syscall_handler_t *) sys_delete_module, + [ __NR_get_kernel_syms ] (syscall_handler_t *) sys_ni_syscall, + [ __NR_quotactl ] (syscall_handler_t *) sys_quotactl, + [ __NR_getpgid ] (syscall_handler_t *) sys_getpgid, + [ __NR_fchdir ] (syscall_handler_t *) sys_fchdir, + [ __NR_bdflush ] (syscall_handler_t *) sys_bdflush, + [ __NR_sysfs ] (syscall_handler_t *) sys_sysfs, + [ __NR_personality ] (syscall_handler_t *) sys_personality, + [ __NR_afs_syscall ] (syscall_handler_t *) sys_ni_syscall, + [ __NR_setfsuid ] (syscall_handler_t *) sys_setfsuid16, + [ __NR_setfsgid ] (syscall_handler_t *) sys_setfsgid16, + [ __NR__llseek ] (syscall_handler_t *) sys_llseek, + [ __NR_getdents ] (syscall_handler_t *) sys_getdents, [ __NR__newselect ] = (syscall_handler_t *) sys_select, - [ __NR_flock ] = sys_flock, - [ __NR_msync ] = sys_msync, - [ __NR_readv ] = sys_readv, - [ __NR_writev ] = sys_writev, - [ __NR_getsid ] = sys_getsid, - [ __NR_fdatasync ] = sys_fdatasync, + [ __NR_flock ] (syscall_handler_t *) sys_flock, + [ __NR_msync ] (syscall_handler_t *) sys_msync, + [ __NR_readv ] (syscall_handler_t *) sys_readv, + [ __NR_writev ] (syscall_handler_t *) sys_writev, + [ __NR_getsid ] (syscall_handler_t *) sys_getsid, + [ __NR_fdatasync ] (syscall_handler_t *) sys_fdatasync, [ __NR__sysctl ] = (syscall_handler_t *) sys_sysctl, - [ __NR_mlock ] = sys_mlock, - [ __NR_munlock ] = sys_munlock, - [ __NR_mlockall ] = sys_mlockall, - [ __NR_munlockall ] = sys_munlockall, - [ __NR_sched_setparam ] = sys_sched_setparam, - [ __NR_sched_getparam ] = sys_sched_getparam, - [ __NR_sched_setscheduler ] = sys_sched_setscheduler, - [ __NR_sched_getscheduler ] = sys_sched_getscheduler, + [ __NR_mlock ] (syscall_handler_t *) sys_mlock, + [ __NR_munlock ] (syscall_handler_t *) sys_munlock, + [ __NR_mlockall ] (syscall_handler_t *) sys_mlockall, + [ __NR_munlockall ] (syscall_handler_t *) sys_munlockall, + [ __NR_sched_setparam ] (syscall_handler_t *) sys_sched_setparam, + [ __NR_sched_getparam ] (syscall_handler_t *) sys_sched_getparam, + [ __NR_sched_setscheduler ] (syscall_handler_t *) sys_sched_setscheduler, + [ __NR_sched_getscheduler ] (syscall_handler_t *) sys_sched_getscheduler, [ __NR_sched_yield ] = (syscall_handler_t *) yield, - [ __NR_sched_get_priority_max ] = sys_sched_get_priority_max, - [ __NR_sched_get_priority_min ] = sys_sched_get_priority_min, - [ __NR_sched_rr_get_interval ] = sys_sched_rr_get_interval, - [ __NR_nanosleep ] = sys_nanosleep, - [ __NR_mremap ] = sys_mremap, - [ __NR_setresuid ] = sys_setresuid16, - [ __NR_getresuid ] = sys_getresuid16, - [ __NR_vm86 ] = sys_ni_syscall, - [ __NR_query_module ] = sys_ni_syscall, - [ __NR_poll ] = sys_poll, - [ __NR_nfsservctl ] = NFSSERVCTL, - [ __NR_setresgid ] = sys_setresgid16, - [ __NR_getresgid ] = sys_getresgid16, - [ __NR_prctl ] = sys_prctl, - [ __NR_rt_sigreturn ] = sys_rt_sigreturn, - [ __NR_rt_sigaction ] = sys_rt_sigaction, - [ __NR_rt_sigprocmask ] = sys_rt_sigprocmask, - [ __NR_rt_sigpending ] = sys_rt_sigpending, - [ __NR_rt_sigtimedwait ] = sys_rt_sigtimedwait, - [ __NR_rt_sigqueueinfo ] = sys_rt_sigqueueinfo, - [ __NR_rt_sigsuspend ] = sys_rt_sigsuspend, - [ __NR_pread64 ] = sys_pread64, - [ __NR_pwrite64 ] = sys_pwrite64, - [ __NR_chown ] = sys_chown16, - [ __NR_getcwd ] = sys_getcwd, - [ __NR_capget ] = sys_capget, - [ __NR_capset ] = sys_capset, - [ __NR_sigaltstack ] = sys_sigaltstack, - [ __NR_sendfile ] = sys_sendfile, - [ __NR_getpmsg ] = sys_ni_syscall, - [ __NR_putpmsg ] = sys_ni_syscall, - [ __NR_vfork ] = sys_vfork, - [ __NR_ugetrlimit ] = sys_getrlimit, - [ __NR_mmap2 ] = sys_mmap2, - [ __NR_truncate64 ] = sys_truncate64, - [ __NR_ftruncate64 ] = sys_ftruncate64, - [ __NR_stat64 ] = sys_stat64, - [ __NR_lstat64 ] = sys_lstat64, - [ __NR_fstat64 ] = sys_fstat64, - [ __NR_fcntl64 ] = sys_fcntl64, - [ __NR_getdents64 ] = sys_getdents64, - [ __NR_gettid ] = sys_gettid, - [ __NR_readahead ] = sys_readahead, - [ __NR_setxattr ] = sys_ni_syscall, - [ __NR_lsetxattr ] = sys_ni_syscall, - [ __NR_fsetxattr ] = sys_ni_syscall, - [ __NR_getxattr ] = sys_ni_syscall, - [ __NR_lgetxattr ] = sys_ni_syscall, - [ __NR_fgetxattr ] = sys_ni_syscall, - [ __NR_listxattr ] = sys_ni_syscall, - [ __NR_llistxattr ] = sys_ni_syscall, - [ __NR_flistxattr ] = sys_ni_syscall, - [ __NR_removexattr ] = sys_ni_syscall, - [ __NR_lremovexattr ] = sys_ni_syscall, - [ __NR_fremovexattr ] = sys_ni_syscall, - [ __NR_tkill ] = sys_tkill, - [ __NR_sendfile64 ] = sys_sendfile64, - [ __NR_futex ] = sys_futex, - [ __NR_sched_setaffinity ] = sys_sched_setaffinity, - [ __NR_sched_getaffinity ] = sys_sched_getaffinity, - [ __NR_io_setup ] = sys_io_setup, - [ __NR_io_destroy ] = sys_io_destroy, - [ __NR_io_getevents ] = sys_io_getevents, - [ __NR_io_submit ] = sys_io_submit, - [ __NR_io_cancel ] = sys_io_cancel, - [ __NR_exit_group ] = sys_exit_group, - [ __NR_lookup_dcookie ] = sys_lookup_dcookie, - [ __NR_epoll_create ] = sys_epoll_create, - [ __NR_epoll_ctl ] = sys_epoll_ctl, - [ __NR_epoll_wait ] = sys_epoll_wait, - [ __NR_remap_file_pages ] = sys_remap_file_pages, - [ __NR_set_tid_address ] = sys_set_tid_address, + [ __NR_sched_get_priority_max ] (syscall_handler_t *) sys_sched_get_priority_max, + [ __NR_sched_get_priority_min ] (syscall_handler_t *) sys_sched_get_priority_min, + [ __NR_sched_rr_get_interval ] (syscall_handler_t *) sys_sched_rr_get_interval, + [ __NR_nanosleep ] (syscall_handler_t *) sys_nanosleep, + [ __NR_mremap ] (syscall_handler_t *) sys_mremap, + [ __NR_setresuid ] (syscall_handler_t *) sys_setresuid16, + [ __NR_getresuid ] (syscall_handler_t *) sys_getresuid16, + [ __NR_vm86 ] (syscall_handler_t *) sys_ni_syscall, + [ __NR_query_module ] (syscall_handler_t *) sys_ni_syscall, + [ __NR_poll ] (syscall_handler_t *) sys_poll, + [ __NR_nfsservctl ] = (syscall_handler_t *) NFSSERVCTL, + [ __NR_setresgid ] (syscall_handler_t *) sys_setresgid16, + [ __NR_getresgid ] (syscall_handler_t *) sys_getresgid16, + [ __NR_prctl ] (syscall_handler_t *) sys_prctl, + [ __NR_rt_sigreturn ] (syscall_handler_t *) sys_rt_sigreturn, + [ __NR_rt_sigaction ] (syscall_handler_t *) sys_rt_sigaction, + [ __NR_rt_sigprocmask ] (syscall_handler_t *) sys_rt_sigprocmask, + [ __NR_rt_sigpending ] (syscall_handler_t *) sys_rt_sigpending, + [ __NR_rt_sigtimedwait ] (syscall_handler_t *) sys_rt_sigtimedwait, + [ __NR_rt_sigqueueinfo ] (syscall_handler_t *) sys_rt_sigqueueinfo, + [ __NR_rt_sigsuspend ] (syscall_handler_t *) sys_rt_sigsuspend, + [ __NR_pread64 ] (syscall_handler_t *) sys_pread64, + [ __NR_pwrite64 ] (syscall_handler_t *) sys_pwrite64, + [ __NR_chown ] (syscall_handler_t *) sys_chown16, + [ __NR_getcwd ] (syscall_handler_t *) sys_getcwd, + [ __NR_capget ] (syscall_handler_t *) sys_capget, + [ __NR_capset ] (syscall_handler_t *) sys_capset, + [ __NR_sigaltstack ] (syscall_handler_t *) sys_sigaltstack, + [ __NR_sendfile ] (syscall_handler_t *) sys_sendfile, + [ __NR_getpmsg ] (syscall_handler_t *) sys_ni_syscall, + [ __NR_putpmsg ] (syscall_handler_t *) sys_ni_syscall, + [ __NR_vfork ] (syscall_handler_t *) sys_vfork, + [ __NR_ugetrlimit ] (syscall_handler_t *) sys_getrlimit, + [ __NR_mmap2 ] (syscall_handler_t *) sys_mmap2, + [ __NR_truncate64 ] (syscall_handler_t *) sys_truncate64, + [ __NR_ftruncate64 ] (syscall_handler_t *) sys_ftruncate64, + [ __NR_stat64 ] (syscall_handler_t *) sys_stat64, + [ __NR_lstat64 ] (syscall_handler_t *) sys_lstat64, + [ __NR_fstat64 ] (syscall_handler_t *) sys_fstat64, + [ __NR_getdents64 ] (syscall_handler_t *) sys_getdents64, + [ __NR_fcntl64 ] (syscall_handler_t *) sys_fcntl64, + [ 223 ] (syscall_handler_t *) sys_ni_syscall, + [ __NR_gettid ] (syscall_handler_t *) sys_gettid, + [ __NR_readahead ] (syscall_handler_t *) sys_readahead, + [ __NR_setxattr ] (syscall_handler_t *) sys_setxattr, + [ __NR_lsetxattr ] (syscall_handler_t *) sys_lsetxattr, + [ __NR_fsetxattr ] (syscall_handler_t *) sys_fsetxattr, + [ __NR_getxattr ] (syscall_handler_t *) sys_getxattr, + [ __NR_lgetxattr ] (syscall_handler_t *) sys_lgetxattr, + [ __NR_fgetxattr ] (syscall_handler_t *) sys_fgetxattr, + [ __NR_listxattr ] (syscall_handler_t *) sys_listxattr, + [ __NR_llistxattr ] (syscall_handler_t *) sys_llistxattr, + [ __NR_flistxattr ] (syscall_handler_t *) sys_flistxattr, + [ __NR_removexattr ] (syscall_handler_t *) sys_removexattr, + [ __NR_lremovexattr ] (syscall_handler_t *) sys_lremovexattr, + [ __NR_fremovexattr ] (syscall_handler_t *) sys_fremovexattr, + [ __NR_tkill ] (syscall_handler_t *) sys_tkill, + [ __NR_sendfile64 ] (syscall_handler_t *) sys_sendfile64, + [ __NR_futex ] (syscall_handler_t *) sys_futex, + [ __NR_sched_setaffinity ] (syscall_handler_t *) sys_sched_setaffinity, + [ __NR_sched_getaffinity ] (syscall_handler_t *) sys_sched_getaffinity, + [ __NR_set_thread_area ] (syscall_handler_t *) sys_ni_syscall, + [ __NR_get_thread_area ] (syscall_handler_t *) sys_ni_syscall, + [ __NR_io_setup ] (syscall_handler_t *) sys_io_setup, + [ __NR_io_destroy ] (syscall_handler_t *) sys_io_destroy, + [ __NR_io_getevents ] (syscall_handler_t *) sys_io_getevents, + [ __NR_io_submit ] (syscall_handler_t *) sys_io_submit, + [ __NR_io_cancel ] (syscall_handler_t *) sys_io_cancel, + [ __NR_fadvise64 ] (syscall_handler_t *) sys_fadvise64, + [ 251 ] (syscall_handler_t *) sys_ni_syscall, + [ __NR_exit_group ] (syscall_handler_t *) sys_exit_group, + [ __NR_lookup_dcookie ] (syscall_handler_t *) sys_lookup_dcookie, + [ __NR_epoll_create ] (syscall_handler_t *) sys_epoll_create, + [ __NR_epoll_ctl ] (syscall_handler_t *) sys_epoll_ctl, + [ __NR_epoll_wait ] (syscall_handler_t *) sys_epoll_wait, + [ __NR_remap_file_pages ] (syscall_handler_t *) sys_remap_file_pages, + [ __NR_set_tid_address ] (syscall_handler_t *) sys_set_tid_address, + [ __NR_timer_create ] (syscall_handler_t *) sys_timer_create, + [ __NR_timer_settime ] (syscall_handler_t *) sys_timer_settime, + [ __NR_timer_gettime ] (syscall_handler_t *) sys_timer_gettime, + [ __NR_timer_getoverrun ] (syscall_handler_t *) sys_timer_getoverrun, + [ __NR_timer_delete ] (syscall_handler_t *) sys_timer_delete, + [ __NR_clock_settime ] (syscall_handler_t *) sys_clock_settime, + [ __NR_clock_gettime ] (syscall_handler_t *) sys_clock_gettime, + [ __NR_clock_getres ] (syscall_handler_t *) sys_clock_getres, + [ __NR_clock_nanosleep ] (syscall_handler_t *) sys_clock_nanosleep, + [ __NR_statfs64 ] (syscall_handler_t *) sys_statfs64, + [ __NR_fstatfs64 ] (syscall_handler_t *) sys_fstatfs64, + [ __NR_tgkill ] (syscall_handler_t *) sys_tgkill, + [ __NR_utimes ] (syscall_handler_t *) sys_utimes, + [ __NR_fadvise64_64 ] (syscall_handler_t *) sys_fadvise64_64, + [ __NR_vserver ] (syscall_handler_t *) sys_ni_syscall, ARCH_SYSCALLS [ LAST_SYSCALL + 1 ... NR_syscalls ] = diff -Nru a/arch/um/kernel/syscall_kern.c b/arch/um/kernel/syscall_kern.c --- a/arch/um/kernel/syscall_kern.c 2004-08-25 22:01:56 -07:00 +++ b/arch/um/kernel/syscall_kern.c 2004-08-25 22:01:56 -07:00 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) + * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com) * Licensed under the GPL */ @@ -36,32 +36,34 @@ long sys_fork(void) { - struct task_struct *p; + long ret; current->thread.forking = 1; - p = do_fork(SIGCHLD, 0, NULL, 0, NULL, NULL); + ret = do_fork(SIGCHLD, 0, NULL, 0, NULL, NULL); current->thread.forking = 0; - return(IS_ERR(p) ? PTR_ERR(p) : p->pid); + return(ret); } -long sys_clone(unsigned long clone_flags, unsigned long newsp) +long sys_clone(unsigned long clone_flags, unsigned long newsp, + int *parent_tid, int *child_tid) { - struct task_struct *p; + long ret; current->thread.forking = 1; - p = do_fork(clone_flags, newsp, NULL, 0, NULL, NULL); + ret = do_fork(clone_flags, newsp, NULL, 0, parent_tid, child_tid); current->thread.forking = 0; - return(IS_ERR(p) ? PTR_ERR(p) : p->pid); + return(ret); } long sys_vfork(void) { - struct task_struct *p; + long ret; current->thread.forking = 1; - p = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, 0, NULL, 0, NULL, NULL); + ret = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, 0, NULL, 0, NULL, + NULL); current->thread.forking = 0; - return(IS_ERR(p) ? PTR_ERR(p) : p->pid); + return(ret); } /* common code for old and new mmaps */ @@ -136,43 +138,12 @@ error = do_pipe(fd); if (!error) { - if (copy_to_user(fildes, fd, 2*sizeof(int))) + if (copy_to_user(fildes, fd, sizeof(fd))) error = -EFAULT; } return error; } -int sys_sigaction(int sig, const struct old_sigaction *act, - struct old_sigaction *oact) -{ - struct k_sigaction new_ka, old_ka; - int ret; - - if (act) { - old_sigset_t mask; - if (verify_area(VERIFY_READ, act, sizeof(*act)) || - __get_user(new_ka.sa.sa_handler, &act->sa_handler) || - __get_user(new_ka.sa.sa_restorer, &act->sa_restorer)) - return -EFAULT; - __get_user(new_ka.sa.sa_flags, &act->sa_flags); - __get_user(mask, &act->sa_mask); - siginitset(&new_ka.sa.sa_mask, mask); - } - - ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); - - if (!ret && oact) { - if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) || - __put_user(old_ka.sa.sa_handler, &oact->sa_handler) || - __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer)) - return -EFAULT; - __put_user(old_ka.sa.sa_flags, &oact->sa_flags); - __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask); - } - - return ret; -} - /* * sys_ipc() is the de-multiplexer for the SysV IPC calls.. * @@ -254,7 +225,7 @@ return sys_shmctl (first, second, (struct shmid_ds *) ptr); default: - return -EINVAL; + return -ENOSYS; } } @@ -301,11 +272,6 @@ error = error ? -EFAULT : 0; return error; -} - -int sys_sigaltstack(const stack_t *uss, stack_t *uoss) -{ - return(do_sigaltstack(uss, uoss, PT_REGS_SP(¤t->thread.regs))); } long execute_syscall(void *r) diff -Nru a/arch/um/kernel/sysrq.c b/arch/um/kernel/sysrq.c --- a/arch/um/kernel/sysrq.c 2004-08-25 22:01:55 -07:00 +++ b/arch/um/kernel/sysrq.c 2004-08-25 22:01:55 -07:00 @@ -44,6 +44,11 @@ } EXPORT_SYMBOL(dump_stack); +void show_stack(struct task_struct *task, unsigned long *sp) +{ + show_trace(sp); +} + /* * Overrides for Emacs so that we follow Linus's tabbing style. * Emacs will notice this stuff at the end of the file and automatically diff -Nru a/arch/um/kernel/tempfile.c b/arch/um/kernel/tempfile.c --- a/arch/um/kernel/tempfile.c 2004-08-25 22:01:55 -07:00 +++ b/arch/um/kernel/tempfile.c 2004-08-25 22:01:55 -07:00 @@ -28,6 +28,7 @@ } if((dir == NULL) || (*dir == '\0')) dir = "/tmp"; + tempdir = malloc(strlen(dir) + 2); if(tempdir == NULL){ fprintf(stderr, "Failed to malloc tempdir, " @@ -49,7 +50,8 @@ else *tempname = 0; strcat(tempname, template); - if((fd = mkstemp(tempname)) < 0){ + fd = mkstemp(tempname); + if(fd < 0){ fprintf(stderr, "open - cannot create %s: %s\n", tempname, strerror(errno)); return -1; @@ -59,7 +61,8 @@ return -1; } if(out_tempname){ - if((*out_tempname = strdup(tempname)) == NULL){ + *out_tempname = strdup(tempname); + if(*out_tempname == NULL){ perror("strdup"); return -1; } diff -Nru a/arch/um/kernel/time.c b/arch/um/kernel/time.c --- a/arch/um/kernel/time.c 2004-08-25 22:01:54 -07:00 +++ b/arch/um/kernel/time.c 2004-08-25 22:01:54 -07:00 @@ -4,24 +4,34 @@ */ #include +#include #include #include #include #include #include -#include "linux/module.h" +#include #include "user_util.h" #include "kern_util.h" #include "user.h" #include "process.h" #include "signal_user.h" #include "time_user.h" +#include "kern_constants.h" + +/* XXX This really needs to be declared and initialized in a kernel file since + * it's in + */ +extern struct timespec wall_to_monotonic; extern struct timeval xtime; +struct timeval local_offset = { 0, 0 }; + void timer(void) { gettimeofday(&xtime, NULL); + timeradd(&xtime, &local_offset, &xtime); } void set_interval(int timer_type) @@ -66,7 +76,7 @@ errno); } -void idle_timer(void) +void uml_idle_timer(void) { if(signal(SIGVTALRM, SIG_IGN) == SIG_ERR) panic("Couldn't unset SIGVTALRM handler"); @@ -76,14 +86,60 @@ set_interval(ITIMER_REAL); } +static unsigned long long get_host_hz(void) +{ + char mhzline[16], *end; + unsigned long long mhz; + int ret, mult, rest, len; + + ret = cpu_feature("cpu MHz", mhzline, + sizeof(mhzline) / sizeof(mhzline[0])); + if(!ret) + panic ("Could not get host MHZ"); + + mhz = strtoul(mhzline, &end, 10); + + /* This business is to parse a floating point number without using + * floating types. + */ + + rest = 0; + mult = 0; + if(*end == '.'){ + end++; + len = strlen(end); + if(len < 6) + mult = 6 - len; + else if(len > 6) + end[6] = '\0'; + rest = strtoul(end, NULL, 10); + while(mult-- > 0) + rest *= 10; + } + + return(1000000 * mhz + rest); +} + +unsigned long long host_hz = 0; + +extern int do_posix_clock_monotonic_gettime(struct timespec *tp); + void time_init(void) { + struct timespec now; + + host_hz = get_host_hz(); if(signal(SIGVTALRM, boot_timer_handler) == SIG_ERR) panic("Couldn't set SIGVTALRM handler"); set_interval(ITIMER_VIRTUAL); + + do_posix_clock_monotonic_gettime(&now); + wall_to_monotonic.tv_sec = -now.tv_sec; + wall_to_monotonic.tv_nsec = -now.tv_nsec; } -struct timeval local_offset = { 0, 0 }; +/* Declared in linux/time.h, which can't be included here */ +extern void clock_was_set(void); void do_gettimeofday(struct timeval *tv) { @@ -96,15 +152,13 @@ clock_was_set(); } -EXPORT_SYMBOL(do_gettimeofday); - int do_settimeofday(struct timespec *tv) { struct timeval now; unsigned long flags; struct timeval tv_in; - if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC) + if ((unsigned long) tv->tv_nsec >= UM_NSEC_PER_SEC) return -EINVAL; tv_in.tv_sec = tv->tv_sec; @@ -114,9 +168,9 @@ gettimeofday(&now, NULL); timersub(&tv_in, &now, &local_offset); time_unlock(flags); -} -EXPORT_SYMBOL(do_settimeofday); + return(0); +} void idle_sleep(int secs) { diff -Nru a/arch/um/kernel/time_kern.c b/arch/um/kernel/time_kern.c --- a/arch/um/kernel/time_kern.c 2004-08-25 22:01:55 -07:00 +++ b/arch/um/kernel/time_kern.c 2004-08-25 22:01:55 -07:00 @@ -30,22 +30,60 @@ return(HZ); } +/* + * Scheduler clock - returns current time in nanosec units. + */ +unsigned long long sched_clock(void) +{ + return (unsigned long long)jiffies_64 * (1000000000 / HZ); +} + /* Changed at early boot */ int timer_irq_inited = 0; -/* missed_ticks will be modified after kernel memory has been - * write-protected, so this puts it in a section which will be left - * write-enabled. - */ -int __attribute__ ((__section__ (".unprotected"))) missed_ticks[NR_CPUS]; +static int first_tick; +static unsigned long long prev_tsc; +#ifdef CONFIG_UML_REAL_TIME_CLOCK +static long long delta; /* Deviation per interval */ +#endif + +extern unsigned long long host_hz; void timer_irq(union uml_pt_regs *regs) { - int cpu = current->thread_info->cpu, ticks = missed_ticks[cpu]; + unsigned long long ticks = 0; + + if(!timer_irq_inited){ + /* This is to ensure that ticks don't pile up when + * the timer handler is suspended */ + first_tick = 0; + return; + } - if(!timer_irq_inited) return; - missed_ticks[cpu] = 0; - while(ticks--) do_IRQ(TIMER_IRQ, regs); + if(first_tick){ +#ifdef CONFIG_UML_REAL_TIME_CLOCK + unsigned long long tsc; + /* We've had 1 tick */ + tsc = time_stamp(); + + delta += tsc - prev_tsc; + prev_tsc = tsc; + + ticks += (delta * HZ) / host_hz; + delta -= (ticks * host_hz) / HZ; +#else + ticks = 1; +#endif + } + else { + prev_tsc = time_stamp(); + first_tick = 1; + } + + while(ticks > 0){ + do_IRQ(TIMER_IRQ, regs); + ticks--; + } } void boot_timer_handler(int sig) @@ -58,12 +96,15 @@ do_timer(®s); } -void um_timer(int irq, void *dev, struct pt_regs *regs) +irqreturn_t um_timer(int irq, void *dev, struct pt_regs *regs) { + unsigned long flags; + do_timer(regs); - write_seqlock(&xtime_lock); + write_seqlock_irqsave(&xtime_lock, flags); timer(); - write_sequnlock(&xtime_lock); + write_sequnlock_irqrestore(&xtime_lock, flags); + return(IRQ_HANDLED); } long um_time(int * tloc) @@ -81,12 +122,12 @@ long um_stime(int * tptr) { int value; - struct timeval new; + struct timespec new; if (get_user(value, tptr)) return -EFAULT; new.tv_sec = value; - new.tv_usec = 0; + new.tv_nsec = 0; do_settimeofday(&new); return 0; } @@ -125,9 +166,11 @@ void timer_handler(int sig, union uml_pt_regs *regs) { #ifdef CONFIG_SMP + local_irq_disable(); update_process_times(user_context(UPT_SP(regs))); + local_irq_enable(); #endif - if(current->thread_info->cpu == 0) + if(current_thread->cpu == 0) timer_irq(regs); } @@ -136,6 +179,7 @@ unsigned long time_lock(void) { unsigned long flags; + spin_lock_irqsave(&timer_spinlock, flags); return(flags); } @@ -150,8 +194,8 @@ int err; CHOOSE_MODE(user_time_init_tt(), user_time_init_skas()); - if((err = request_irq(TIMER_IRQ, um_timer, SA_INTERRUPT, "timer", - NULL)) != 0) + err = request_irq(TIMER_IRQ, um_timer, SA_INTERRUPT, "timer", NULL); + if(err != 0) printk(KERN_ERR "timer_init : request_irq failed - " "errno = %d\n", -err); timer_irq_inited = 1; @@ -159,7 +203,6 @@ } __initcall(timer_init); - /* * Overrides for Emacs so that we follow Linus's tabbing style. diff -Nru a/arch/um/kernel/trap_kern.c b/arch/um/kernel/trap_kern.c --- a/arch/um/kernel/trap_kern.c 2004-08-25 22:01:54 -07:00 +++ b/arch/um/kernel/trap_kern.c 2004-08-25 22:01:54 -07:00 @@ -16,12 +16,15 @@ #include "asm/tlbflush.h" #include "asm/a.out.h" #include "asm/current.h" +#include "asm/irq.h" #include "user_util.h" #include "kern_util.h" #include "kern.h" #include "chan_kern.h" #include "mconsole_kern.h" #include "2_5compat.h" +#include "mem.h" +#include "mem_kern.h" int handle_page_fault(unsigned long address, unsigned long ip, int is_write, int is_user, int *code_out) @@ -51,12 +54,10 @@ if(is_write && !(vma->vm_flags & VM_WRITE)) goto out; page = address & PAGE_MASK; - if(page == (unsigned long) current->thread_info + PAGE_SIZE) - panic("Kernel stack overflow"); pgd = pgd_offset(mm, page); pmd = pmd_offset(pgd, page); - survive: do { + survive: switch (handle_mm_fault(mm, vma, address, is_write)){ case VM_FAULT_MINOR: current->min_flt++; @@ -75,10 +76,10 @@ } pte = pte_offset_kernel(pmd, page); } while(!pte_present(*pte)); + err = 0; *pte = pte_mkyoung(*pte); if(pte_write(*pte)) *pte = pte_mkdirty(*pte); flush_tlb_page(vma, page); - err = 0; out: up_read(&mm->mmap_sem); return(err); @@ -94,10 +95,36 @@ down_read(&mm->mmap_sem); goto survive; } - err = -ENOMEM; goto out; } +LIST_HEAD(physmem_remappers); + +void register_remapper(struct remapper *info) +{ + list_add(&info->list, &physmem_remappers); +} + +static int check_remapped_addr(unsigned long address, int is_write) +{ + struct remapper *remapper; + struct list_head *ele; + __u64 offset; + int fd; + + fd = phys_mapping(__pa(address), &offset); + if(fd == -1) + return(0); + + list_for_each(ele, &physmem_remappers){ + remapper = list_entry(ele, struct remapper, list); + if((*remapper->proc)(fd, address, is_write, offset)) + return(1); + } + + return(0); +} + unsigned long segv(unsigned long address, unsigned long ip, int is_write, int is_user, void *sc) { @@ -109,7 +136,9 @@ flush_tlb_kernel_vm(); return(0); } - if(current->mm == NULL) + else if(check_remapped_addr(address & PAGE_MASK, is_write)) + return(0); + else if(current->mm == NULL) panic("Segfault with no mm"); err = handle_page_fault(address, ip, is_write, is_user, &si.si_code); @@ -120,9 +149,8 @@ current->thread.fault_addr = (void *) address; do_longjmp(catcher, 1); } - else if(current->thread.fault_addr != NULL){ + else if(current->thread.fault_addr != NULL) panic("fault_addr set but no fault catcher"); - } else if(arch_fixup(ip, sc)) return(0); @@ -155,8 +183,6 @@ { struct siginfo si; - printk(KERN_ERR "Unfixable SEGV in '%s' (pid %d) at 0x%lx " - "(ip 0x%lx)\n", current->comm, current->pid, address, ip); si.si_signo = SIGSEGV; si.si_code = SEGV_ACCERR; si.si_addr = (void *) address; @@ -178,6 +204,11 @@ if(current->thread.fault_catcher != NULL) do_longjmp(current->thread.fault_catcher, 1); else relay_signal(sig, regs); +} + +void winch(int sig, union uml_pt_regs *regs) +{ + do_IRQ(WINCH_IRQ, regs); } void trap_init(void) diff -Nru a/arch/um/kernel/trap_user.c b/arch/um/kernel/trap_user.c --- a/arch/um/kernel/trap_user.c 2004-08-25 22:01:55 -07:00 +++ b/arch/um/kernel/trap_user.c 2004-08-25 22:01:55 -07:00 @@ -5,11 +5,9 @@ #include #include -#include #include #include #include -#include #include #include #include @@ -34,7 +32,14 @@ { kill(pid, SIGKILL); kill(pid, SIGCONT); - while(waitpid(pid, NULL, 0) > 0) kill(pid, SIGCONT); + do { + int n; + CATCH_EINTR(n = waitpid(pid, NULL, 0)); + if (n > 0) + kill(pid, SIGCONT); + else + break; + } while(1); } /* Unlocked - don't care if this is a bit off */ @@ -82,6 +87,8 @@ .is_irq = 0 }, [ SIGILL ] { .handler = relay_signal, .is_irq = 0 }, + [ SIGWINCH ] { .handler = winch, + .is_irq = 1 }, [ SIGBUS ] { .handler = bus_handler, .is_irq = 0 }, [ SIGSEGV] { .handler = segv_handler, @@ -102,12 +109,11 @@ sig, &sc); } -extern int timer_irq_inited, missed_ticks[]; +extern int timer_irq_inited; void alarm_handler(int sig, struct sigcontext sc) { if(!timer_irq_inited) return; - missed_ticks[cpu()]++; if(sig == SIGALRM) switch_timers(0); @@ -123,7 +129,7 @@ { jmp_buf *buf = b; - longjmp(*buf, val); + siglongjmp(*buf, val); } /* diff -Nru a/arch/um/kernel/tt/Makefile b/arch/um/kernel/tt/Makefile --- a/arch/um/kernel/tt/Makefile 2004-08-25 22:01:55 -07:00 +++ b/arch/um/kernel/tt/Makefile 2004-08-25 22:01:55 -07:00 @@ -1,5 +1,5 @@ # -# Copyright (C) 2002 Jeff Dike (jdike@karaya.com) +# Copyright (C) 2002 - 2003 Jeff Dike (jdike@addtoit.com) # Licensed under the GPL # @@ -7,7 +7,7 @@ obj-y = exec_kern.o exec_user.o gdb.o ksyms.o mem.o mem_user.o process_kern.o \ syscall_kern.o syscall_user.o time.o tlb.o tracer.o trap_user.o \ - uaccess_user.o sys-$(SUBARCH)/ + uaccess.o uaccess_user.o sys-$(SUBARCH)/ obj-$(CONFIG_PT_PROXY) += gdb_kern.o ptproxy/ @@ -27,5 +27,3 @@ $(obj)/unmap_fin.o : $(src)/unmap.o ld -r -o $@ $< -lc -L/usr/lib - -clean : diff -Nru a/arch/um/kernel/tt/exec_kern.c b/arch/um/kernel/tt/exec_kern.c --- a/arch/um/kernel/tt/exec_kern.c 2004-08-25 22:01:54 -07:00 +++ b/arch/um/kernel/tt/exec_kern.c 2004-08-25 22:01:54 -07:00 @@ -17,6 +17,7 @@ #include "mem_user.h" #include "os.h" #include "tlb.h" +#include "mode.h" static int exec_tramp(void *sig_stack) { @@ -47,17 +48,17 @@ do_exit(SIGKILL); } - if(current->thread_info->cpu == 0) + if(current_thread->cpu == 0) forward_interrupts(new_pid); current->thread.request.op = OP_EXEC; current->thread.request.u.exec.pid = new_pid; - unprotect_stack((unsigned long) current->thread_info); + unprotect_stack((unsigned long) current_thread); os_usr1_process(os_getpid()); enable_timer(); free_page(stack); protect_memory(uml_reserved, high_physmem - uml_reserved, 1, 1, 0, 1); - task_protections((unsigned long) current->thread_info); + task_protections((unsigned long) current_thread); force_flush_all(); unblock_signals(); } diff -Nru a/arch/um/kernel/tt/exec_user.c b/arch/um/kernel/tt/exec_user.c --- a/arch/um/kernel/tt/exec_user.c 2004-08-25 22:01:56 -07:00 +++ b/arch/um/kernel/tt/exec_user.c 2004-08-25 22:01:56 -07:00 @@ -19,11 +19,16 @@ void do_exec(int old_pid, int new_pid) { unsigned long regs[FRAME_SIZE]; + int err; if((ptrace(PTRACE_ATTACH, new_pid, 0, 0) < 0) || - (ptrace(PTRACE_CONT, new_pid, 0, 0) < 0) || - (waitpid(new_pid, 0, WUNTRACED) < 0)) + (ptrace(PTRACE_CONT, new_pid, 0, 0) < 0)) tracer_panic("do_exec failed to attach proc - errno = %d", + errno); + + CATCH_EINTR(err = waitpid(new_pid, 0, WUNTRACED)); + if (err < 0) + tracer_panic("do_exec failed to attach proc in waitpid - errno = %d", errno); if(ptrace_getregs(old_pid, regs) < 0) diff -Nru a/arch/um/kernel/tt/include/mode.h b/arch/um/kernel/tt/include/mode.h --- a/arch/um/kernel/tt/include/mode.h 2004-08-25 22:01:55 -07:00 +++ b/arch/um/kernel/tt/include/mode.h 2004-08-25 22:01:55 -07:00 @@ -8,6 +8,8 @@ #include "sysdep/ptrace.h" +enum { OP_NONE, OP_EXEC, OP_FORK, OP_TRACE_ON, OP_REBOOT, OP_HALT, OP_CB }; + extern int tracing_pid; extern int tracer(int (*init_proc)(void *), void *sp); diff -Nru a/arch/um/kernel/tt/include/uaccess.h b/arch/um/kernel/tt/include/uaccess.h --- a/arch/um/kernel/tt/include/uaccess.h 2004-08-25 22:01:55 -07:00 +++ b/arch/um/kernel/tt/include/uaccess.h 2004-08-25 22:01:55 -07:00 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com) + * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com) * Licensed under the GPL */ @@ -43,65 +43,19 @@ extern int __do_copy_from_user(void *to, const void *from, int n, void **fault_addr, void **fault_catcher); - -static inline int copy_from_user_tt(void *to, const void *from, int n) -{ - return(access_ok_tt(VERIFY_READ, from, n) ? - __do_copy_from_user(to, from, n, - ¤t->thread.fault_addr, - ¤t->thread.fault_catcher) : n); -} - -static inline int copy_to_user_tt(void *to, const void *from, int n) -{ - return(access_ok_tt(VERIFY_WRITE, to, n) ? - __do_copy_to_user(to, from, n, - ¤t->thread.fault_addr, - ¤t->thread.fault_catcher) : n); -} - extern int __do_strncpy_from_user(char *dst, const char *src, size_t n, void **fault_addr, void **fault_catcher); - -static inline int strncpy_from_user_tt(char *dst, const char *src, int count) -{ - int n; - - if(!access_ok_tt(VERIFY_READ, src, 1)) return(-EFAULT); - n = __do_strncpy_from_user(dst, src, count, - ¤t->thread.fault_addr, - ¤t->thread.fault_catcher); - if(n < 0) return(-EFAULT); - return(n); -} - extern int __do_clear_user(void *mem, size_t len, void **fault_addr, void **fault_catcher); - -static inline int __clear_user_tt(void *mem, int len) -{ - return(__do_clear_user(mem, len, - ¤t->thread.fault_addr, - ¤t->thread.fault_catcher)); -} - -static inline int clear_user_tt(void *mem, int len) -{ - return(access_ok_tt(VERIFY_WRITE, mem, len) ? - __do_clear_user(mem, len, - ¤t->thread.fault_addr, - ¤t->thread.fault_catcher) : len); -} - extern int __do_strnlen_user(const char *str, unsigned long n, void **fault_addr, void **fault_catcher); -static inline int strnlen_user_tt(const void *str, int len) -{ - return(__do_strnlen_user(str, len, - ¤t->thread.fault_addr, - ¤t->thread.fault_catcher)); -} +extern int copy_from_user_tt(void *to, const void *from, int n); +extern int copy_to_user_tt(void *to, const void *from, int n); +extern int strncpy_from_user_tt(char *dst, const char *src, int count); +extern int __clear_user_tt(void *mem, int len); +extern int clear_user_tt(void *mem, int len); +extern int strnlen_user_tt(const void *str, int len); #endif diff -Nru a/arch/um/kernel/tt/mem.c b/arch/um/kernel/tt/mem.c --- a/arch/um/kernel/tt/mem.c 2004-08-25 22:01:55 -07:00 +++ b/arch/um/kernel/tt/mem.c 2004-08-25 22:01:55 -07:00 @@ -18,7 +18,7 @@ if(!jail || debug) remap_data(UML_ROUND_DOWN(&_stext), UML_ROUND_UP(&_etext), 1); remap_data(UML_ROUND_DOWN(&_sdata), UML_ROUND_UP(&_edata), 1); - remap_data(UML_ROUND_DOWN(&__bss_start), UML_ROUND_UP(brk_start), 1); + remap_data(UML_ROUND_DOWN(&__bss_start), UML_ROUND_UP(&_end), 1); } #ifdef CONFIG_HOST_2G_2G diff -Nru a/arch/um/kernel/tt/mem_user.c b/arch/um/kernel/tt/mem_user.c --- a/arch/um/kernel/tt/mem_user.c 2004-08-25 22:01:54 -07:00 +++ b/arch/um/kernel/tt/mem_user.c 2004-08-25 22:01:54 -07:00 @@ -25,14 +25,13 @@ size = (unsigned long) segment_end - (unsigned long) segment_start; data = create_mem_file(size); - if((addr = mmap(NULL, size, PROT_WRITE | PROT_READ, - MAP_SHARED, data, 0)) == MAP_FAILED){ + addr = mmap(NULL, size, PROT_WRITE | PROT_READ, MAP_SHARED, data, 0); + if(addr == MAP_FAILED){ perror("mapping new data segment"); exit(1); } memcpy(addr, segment_start, size); - if(switcheroo(data, prot, addr, segment_start, - size) < 0){ + if(switcheroo(data, prot, addr, segment_start, size) < 0){ printf("switcheroo failed\n"); exit(1); } diff -Nru a/arch/um/kernel/tt/process_kern.c b/arch/um/kernel/tt/process_kern.c --- a/arch/um/kernel/tt/process_kern.c 2004-08-25 22:01:56 -07:00 +++ b/arch/um/kernel/tt/process_kern.c 2004-08-25 22:01:56 -07:00 @@ -62,7 +62,7 @@ reading = 0; err = os_write_file(to->thread.mode.tt.switch_pipe[1], &c, sizeof(c)); if(err != sizeof(c)) - panic("write of switch_pipe failed, errno = %d", -err); + panic("write of switch_pipe failed, err = %d", -err); reading = 1; if((from->state == TASK_ZOMBIE) || (from->state == TASK_DEAD)) @@ -104,48 +104,72 @@ void release_thread_tt(struct task_struct *task) { - os_kill_process(task->thread.mode.tt.extern_pid, 0); + int pid = task->thread.mode.tt.extern_pid; + + if(os_getpid() != pid) + os_kill_process(pid, 0); } void exit_thread_tt(void) { - close(current->thread.mode.tt.switch_pipe[0]); - close(current->thread.mode.tt.switch_pipe[1]); + os_close_file(current->thread.mode.tt.switch_pipe[0]); + os_close_file(current->thread.mode.tt.switch_pipe[1]); } void schedule_tail(task_t *prev); static void new_thread_handler(int sig) { + unsigned long disable; int (*fn)(void *); void *arg; fn = current->thread.request.u.thread.proc; arg = current->thread.request.u.thread.arg; + UPT_SC(¤t->thread.regs.regs) = (void *) (&sig + 1); + disable = (1 << (SIGVTALRM - 1)) | (1 << (SIGALRM - 1)) | + (1 << (SIGIO - 1)) | (1 << (SIGPROF - 1)); + SC_SIGMASK(UPT_SC(¤t->thread.regs.regs)) &= ~disable; + suspend_new_thread(current->thread.mode.tt.switch_pipe[0]); - block_signals(); + force_flush_all(); + if(current->thread.prev_sched != NULL) + schedule_tail(current->thread.prev_sched); + current->thread.prev_sched = NULL; + init_new_thread_signals(1); -#ifdef CONFIG_SMP - schedule_tail(current->thread.prev_sched); -#endif enable_timer(); free_page(current->thread.temp_stack); set_cmdline("(kernel thread)"); - force_flush_all(); - current->thread.prev_sched = NULL; change_sig(SIGUSR1, 1); change_sig(SIGVTALRM, 1); change_sig(SIGPROF, 1); - unblock_signals(); + local_irq_enable(); if(!run_kernel_thread(fn, arg, ¤t->thread.exec_buf)) do_exit(0); } static int new_thread_proc(void *stack) { + /* local_irq_disable is needed to block out signals until this thread is + * properly scheduled. Otherwise, the tracing thread will get mighty + * upset about any signals that arrive before that. + * This has the complication that it sets the saved signal mask in + * the sigcontext to block signals. This gets restored when this + * thread (or a descendant, since they get a copy of this sigcontext) + * returns to userspace. + * So, this is compensated for elsewhere. + * XXX There is still a small window until local_irq_disable() actually + * finishes where signals are possible - shouldn't be a problem in + * practice since SIGIO hasn't been forwarded here yet, and the + * local_irq_disable should finish before a SIGVTALRM has time to be + * delivered. + */ + + local_irq_disable(); init_new_thread_stack(stack, new_thread_handler); os_usr1_process(os_getpid()); return(0); @@ -156,7 +180,7 @@ * itself with a SIGUSR1. set_user_mode has to be run with SIGUSR1 off, * so it is blocked before it's called. They are re-enabled on sigreturn * despite the fact that they were blocked when the SIGUSR1 was issued because - * copy_thread copies the parent's signcontext, including the signal mask + * copy_thread copies the parent's sigcontext, including the signal mask * onto the signal frame. */ @@ -165,35 +189,32 @@ UPT_SC(¤t->thread.regs.regs) = (void *) (&sig + 1); suspend_new_thread(current->thread.mode.tt.switch_pipe[0]); -#ifdef CONFIG_SMP - schedule_tail(NULL); -#endif + force_flush_all(); + if(current->thread.prev_sched != NULL) + schedule_tail(current->thread.prev_sched); + current->thread.prev_sched = NULL; + enable_timer(); change_sig(SIGVTALRM, 1); local_irq_enable(); - force_flush_all(); if(current->mm != current->parent->mm) protect_memory(uml_reserved, high_physmem - uml_reserved, 1, 1, 0, 1); - task_protections((unsigned long) current->thread_info); - - current->thread.prev_sched = NULL; + task_protections((unsigned long) current_thread); free_page(current->thread.temp_stack); + local_irq_disable(); change_sig(SIGUSR1, 0); set_user_mode(current); } -static int sigusr1 = SIGUSR1; - int fork_tramp(void *stack) { - int sig = sigusr1; - local_irq_disable(); + arch_init_thread(); init_new_thread_stack(stack, finish_fork_handler); - kill(os_getpid(), sig); + os_usr1_process(os_getpid()); return(0); } @@ -213,8 +234,8 @@ } err = os_pipe(p->thread.mode.tt.switch_pipe, 1, 1); - if(err){ - printk("copy_thread : pipe failed, errno = %d\n", -err); + if(err < 0){ + printk("copy_thread : pipe failed, err = %d\n", -err); return(err); } @@ -377,8 +398,8 @@ pages = (1 << CONFIG_KERNEL_STACK_ORDER); - start = (unsigned long) current->thread_info + PAGE_SIZE; - end = (unsigned long) current + PAGE_SIZE * pages; + start = (unsigned long) current_thread + PAGE_SIZE; + end = (unsigned long) current_thread + PAGE_SIZE * pages; protect_memory(uml_reserved, start - uml_reserved, 1, w, 1, 1); protect_memory(end, high_physmem - end, 1, w, 1, 1); @@ -391,7 +412,7 @@ protect_memory(start, end - start, 1, w, 1, 1); start = (unsigned long) UML_ROUND_DOWN(&__bss_start); - end = (unsigned long) UML_ROUND_UP(brk_start); + end = (unsigned long) UML_ROUND_UP(&_end); protect_memory(start, end - start, 1, w, 1, 1); mprotect_kernel_vm(w); @@ -454,8 +475,9 @@ init_task.thread.mode.tt.extern_pid = pid; err = os_pipe(init_task.thread.mode.tt.switch_pipe, 1, 1); - if(err) panic("Can't create switch pipe for init_task, errno = %d", - err); + if(err) + panic("Can't create switch pipe for init_task, errno = %d", + -err); } int singlestepping_tt(void *t) diff -Nru a/arch/um/kernel/tt/ptproxy/Makefile b/arch/um/kernel/tt/ptproxy/Makefile --- a/arch/um/kernel/tt/ptproxy/Makefile 2004-08-25 22:01:55 -07:00 +++ b/arch/um/kernel/tt/ptproxy/Makefile 2004-08-25 22:01:55 -07:00 @@ -9,5 +9,3 @@ $(USER_OBJS) : %.o: %.c $(CC) $(CFLAGS_$(notdir $@)) $(USER_CFLAGS) -c -o $@ $< - -clean: diff -Nru a/arch/um/kernel/tt/ptproxy/proxy.c b/arch/um/kernel/tt/ptproxy/proxy.c --- a/arch/um/kernel/tt/ptproxy/proxy.c 2004-08-25 22:01:55 -07:00 +++ b/arch/um/kernel/tt/ptproxy/proxy.c 2004-08-25 22:01:55 -07:00 @@ -15,7 +15,6 @@ #include #include #include -#include #include #include #include @@ -273,7 +272,7 @@ child_proxy(1, W_EXITCODE(0, 0)); while(debugger.waiting == 1){ - pid = waitpid(debugger.pid, &status, WUNTRACED); + CATCH_EINTR(pid = waitpid(debugger.pid, &status, WUNTRACED)); if(pid != debugger.pid){ printk("fake_child_exit - waitpid failed, " "errno = %d\n", errno); @@ -281,7 +280,7 @@ } debugger_proxy(status, debugger.pid); } - pid = waitpid(debugger.pid, &status, WUNTRACED); + CATCH_EINTR(pid = waitpid(debugger.pid, &status, WUNTRACED)); if(pid != debugger.pid){ printk("fake_child_exit - waitpid failed, " "errno = %d\n", errno); @@ -293,10 +292,10 @@ } char gdb_init_string[] = -"att 1 -b panic -b stop -handle SIGWINCH nostop noprint pass +"att 1 \n\ +b panic \n\ +b stop \n\ +handle SIGWINCH nostop noprint pass \n\ "; int start_debugger(char *prog, int startup, int stop, int *fd_out) @@ -304,7 +303,8 @@ int slave, child; slave = open_gdb_chan(); - if((child = fork()) == 0){ + child = fork(); + if(child == 0){ char *tempname = NULL; int fd; @@ -327,18 +327,19 @@ exit(1); #endif } - if((fd = make_tempfile("/tmp/gdb_init-XXXXXX", &tempname, 0)) < 0){ - printk("start_debugger : make_tempfile failed, errno = %d\n", - errno); + fd = make_tempfile("/tmp/gdb_init-XXXXXX", &tempname, 0); + if(fd < 0){ + printk("start_debugger : make_tempfile failed," + "err = %d\n", -fd); exit(1); } - write(fd, gdb_init_string, sizeof(gdb_init_string) - 1); + os_write_file(fd, gdb_init_string, sizeof(gdb_init_string) - 1); if(startup){ if(stop){ - write(fd, "b start_kernel\n", + os_write_file(fd, "b start_kernel\n", strlen("b start_kernel\n")); } - write(fd, "c\n", strlen("c\n")); + os_write_file(fd, "c\n", strlen("c\n")); } if(ptrace(PTRACE_TRACEME, 0, 0, 0) < 0){ printk("start_debugger : PTRACE_TRACEME failed, " diff -Nru a/arch/um/kernel/tt/ptproxy/sysdep.c b/arch/um/kernel/tt/ptproxy/sysdep.c --- a/arch/um/kernel/tt/ptproxy/sysdep.c 2004-08-25 22:01:56 -07:00 +++ b/arch/um/kernel/tt/ptproxy/sysdep.c 2004-08-25 22:01:56 -07:00 @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include diff -Nru a/arch/um/kernel/tt/ptproxy/wait.c b/arch/um/kernel/tt/ptproxy/wait.c --- a/arch/um/kernel/tt/ptproxy/wait.c 2004-08-25 22:01:56 -07:00 +++ b/arch/um/kernel/tt/ptproxy/wait.c 2004-08-25 22:01:56 -07:00 @@ -56,21 +56,23 @@ int real_wait_return(struct debugger *debugger) { unsigned long ip; - int err, pid; + int pid; pid = debugger->pid; + ip = ptrace(PTRACE_PEEKUSER, pid, PT_IP_OFFSET, 0); - ip = IP_RESTART_SYSCALL(ip); - err = ptrace(PTRACE_POKEUSER, pid, PT_IP_OFFSET, ip); + IP_RESTART_SYSCALL(ip); + if(ptrace(PTRACE_POKEUSER, pid, PT_IP_OFFSET, ip) < 0) tracer_panic("real_wait_return : Failed to restart system " - "call, errno = %d\n"); + "call, errno = %d\n", errno); + if((ptrace(PTRACE_SYSCALL, debugger->pid, 0, SIGCHLD) < 0) || (ptrace(PTRACE_SYSCALL, debugger->pid, 0, 0) < 0) || (ptrace(PTRACE_SYSCALL, debugger->pid, 0, 0) < 0) || debugger_normal_return(debugger, -1)) tracer_panic("real_wait_return : gdb failed to wait, " - "errno = %d\n"); + "errno = %d\n", errno); return(0); } diff -Nru a/arch/um/kernel/tt/sys-i386/Makefile b/arch/um/kernel/tt/sys-i386/Makefile --- a/arch/um/kernel/tt/sys-i386/Makefile 2004-08-25 22:01:55 -07:00 +++ b/arch/um/kernel/tt/sys-i386/Makefile 2004-08-25 22:01:55 -07:00 @@ -10,5 +10,3 @@ $(USER_OBJS) : %.o: %.c $(CC) $(CFLAGS_$(notdir $@)) $(USER_CFLAGS) -c -o $@ $< - -clean : diff -Nru a/arch/um/kernel/tt/syscall_kern.c b/arch/um/kernel/tt/syscall_kern.c --- a/arch/um/kernel/tt/syscall_kern.c 2004-08-25 22:01:54 -07:00 +++ b/arch/um/kernel/tt/syscall_kern.c 2004-08-25 22:01:54 -07:00 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) + * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com) * Licensed under the GPL */ diff -Nru a/arch/um/kernel/tt/syscall_user.c b/arch/um/kernel/tt/syscall_user.c --- a/arch/um/kernel/tt/syscall_user.c 2004-08-25 22:01:55 -07:00 +++ b/arch/um/kernel/tt/syscall_user.c 2004-08-25 22:01:55 -07:00 @@ -33,7 +33,7 @@ SC_START_SYSCALL(sc); index = record_syscall_start(syscall); - syscall_trace(); + syscall_trace(regs, 1); result = execute_syscall(regs); /* regs->sc may have changed while the system call ran (there may @@ -46,7 +46,7 @@ (result == -ERESTARTNOINTR)) do_signal(result); - syscall_trace(); + syscall_trace(regs, 0); record_syscall_end(index, result); } diff -Nru a/arch/um/kernel/tt/tlb.c b/arch/um/kernel/tt/tlb.c --- a/arch/um/kernel/tt/tlb.c 2004-08-25 22:01:54 -07:00 +++ b/arch/um/kernel/tt/tlb.c 2004-08-25 22:01:54 -07:00 @@ -10,6 +10,7 @@ #include "asm/page.h" #include "asm/pgtable.h" #include "asm/uaccess.h" +#include "asm/tlbflush.h" #include "user_util.h" #include "mem_user.h" #include "os.h" diff -Nru a/arch/um/kernel/tt/tracer.c b/arch/um/kernel/tt/tracer.c --- a/arch/um/kernel/tt/tracer.c 2004-08-25 22:01:54 -07:00 +++ b/arch/um/kernel/tt/tracer.c 2004-08-25 22:01:54 -07:00 @@ -39,16 +39,17 @@ return(0); register_winch_irq(tracer_winch[0], fd, -1, data); - return(0); + return(1); } static void tracer_winch_handler(int sig) { + int n; char c = 1; - if(write(tracer_winch[1], &c, sizeof(c)) != sizeof(c)) - printk("tracer_winch_handler - write failed, errno = %d\n", - errno); + n = os_write_file(tracer_winch[1], &c, sizeof(c)); + if(n != sizeof(c)) + printk("tracer_winch_handler - write failed, err = %d\n", -n); } /* Called only by the tracing thread during initialization */ @@ -58,9 +59,8 @@ int err; err = os_pipe(tracer_winch, 1, 1); - if(err){ - printk("setup_tracer_winch : os_pipe failed, errno = %d\n", - -err); + if(err < 0){ + printk("setup_tracer_winch : os_pipe failed, err = %d\n", -err); return; } signal(SIGWINCH, tracer_winch_handler); @@ -130,8 +130,8 @@ case SIGTSTP: if(ptrace(PTRACE_CONT, pid, 0, sig) < 0) tracer_panic("sleeping_process_signal : Failed to " - "continue pid %d, errno = %d\n", pid, - sig); + "continue pid %d, signal = %d, " + "errno = %d\n", pid, sig, errno); break; /* This happens when the debugger (e.g. strace) is doing system call @@ -145,7 +145,7 @@ if(ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0) tracer_panic("sleeping_process_signal : Failed to " "PTRACE_SYSCALL pid %d, errno = %d\n", - pid, sig); + pid, errno); break; case SIGSTOP: break; @@ -192,7 +192,7 @@ printf("tracing thread pid = %d\n", tracing_pid); pid = clone(signal_tramp, sp, CLONE_FILES | SIGCHLD, init_proc); - n = waitpid(pid, &status, WUNTRACED); + CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED)); if(n < 0){ printf("waitpid on idle thread failed, errno = %d\n", errno); exit(1); @@ -218,7 +218,7 @@ err = attach(debugger_parent); if(err){ printf("Failed to attach debugger parent %d, " - "errno = %d\n", debugger_parent, err); + "errno = %d\n", debugger_parent, -err); debugger_parent = -1; } else { @@ -233,7 +233,8 @@ } set_cmdline("(tracing thread)"); while(1){ - if((pid = waitpid(-1, &status, WUNTRACED)) <= 0){ + CATCH_EINTR(pid = waitpid(-1, &status, WUNTRACED)); + if(pid <= 0){ if(errno != ECHILD){ printf("wait failed - errno = %d\n", errno); } @@ -401,7 +402,7 @@ if(!strcmp(line, "go")) debug_stop = 0; else if(!strcmp(line, "parent")) debug_parent = 1; - else printk("Unknown debug option : '%s'\n", line); + else printf("Unknown debug option : '%s'\n", line); line = next; } diff -Nru a/arch/um/kernel/tt/uaccess.c b/arch/um/kernel/tt/uaccess.c --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/arch/um/kernel/tt/uaccess.c 2004-08-25 22:01:56 -07:00 @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com) + * Licensed under the GPL + */ + +#include "linux/sched.h" +#include "asm/uaccess.h" + +int copy_from_user_tt(void *to, const void *from, int n) +{ + if(!access_ok_tt(VERIFY_READ, from, n)) + return(n); + + return(__do_copy_from_user(to, from, n, ¤t->thread.fault_addr, + ¤t->thread.fault_catcher)); +} + +int copy_to_user_tt(void *to, const void *from, int n) +{ + if(!access_ok_tt(VERIFY_WRITE, to, n)) + return(n); + + return(__do_copy_to_user(to, from, n, ¤t->thread.fault_addr, + ¤t->thread.fault_catcher)); +} + +int strncpy_from_user_tt(char *dst, const char *src, int count) +{ + int n; + + if(!access_ok_tt(VERIFY_READ, src, 1)) + return(-EFAULT); + + n = __do_strncpy_from_user(dst, src, count, + ¤t->thread.fault_addr, + ¤t->thread.fault_catcher); + if(n < 0) return(-EFAULT); + return(n); +} + +int __clear_user_tt(void *mem, int len) +{ + return(__do_clear_user(mem, len, + ¤t->thread.fault_addr, + ¤t->thread.fault_catcher)); +} + +int clear_user_tt(void *mem, int len) +{ + if(!access_ok_tt(VERIFY_WRITE, mem, len)) + return(len); + + return(__do_clear_user(mem, len, ¤t->thread.fault_addr, + ¤t->thread.fault_catcher)); +} + +int strnlen_user_tt(const void *str, int len) +{ + return(__do_strnlen_user(str, len, + ¤t->thread.fault_addr, + ¤t->thread.fault_catcher)); +} + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff -Nru a/arch/um/kernel/tt/uaccess_user.c b/arch/um/kernel/tt/uaccess_user.c --- a/arch/um/kernel/tt/uaccess_user.c 2004-08-25 22:01:55 -07:00 +++ b/arch/um/kernel/tt/uaccess_user.c 2004-08-25 22:01:55 -07:00 @@ -8,15 +8,20 @@ #include #include "user_util.h" #include "uml_uaccess.h" +#include "task.h" +#include "kern_util.h" int __do_copy_from_user(void *to, const void *from, int n, void **fault_addr, void **fault_catcher) { + struct tt_regs save = TASK_REGS(get_current())->tt; unsigned long fault; int faulted; fault = __do_user_copy(to, from, n, fault_addr, fault_catcher, __do_copy, &faulted); + TASK_REGS(get_current())->tt = save; + if(!faulted) return(0); else return(n - (fault - (unsigned long) from)); } @@ -29,11 +34,14 @@ int __do_strncpy_from_user(char *dst, const char *src, unsigned long count, void **fault_addr, void **fault_catcher) { + struct tt_regs save = TASK_REGS(get_current())->tt; unsigned long fault; int faulted; fault = __do_user_copy(dst, src, count, fault_addr, fault_catcher, __do_strncpy, &faulted); + TASK_REGS(get_current())->tt = save; + if(!faulted) return(strlen(dst)); else return(-1); } @@ -46,11 +54,14 @@ int __do_clear_user(void *mem, unsigned long len, void **fault_addr, void **fault_catcher) { + struct tt_regs save = TASK_REGS(get_current())->tt; unsigned long fault; int faulted; fault = __do_user_copy(mem, NULL, len, fault_addr, fault_catcher, __do_clear, &faulted); + TASK_REGS(get_current())->tt = save; + if(!faulted) return(0); else return(len - (fault - (unsigned long) mem)); } @@ -58,19 +69,20 @@ int __do_strnlen_user(const char *str, unsigned long n, void **fault_addr, void **fault_catcher) { + struct tt_regs save = TASK_REGS(get_current())->tt; int ret; unsigned long *faddrp = (unsigned long *)fault_addr; jmp_buf jbuf; *fault_catcher = &jbuf; - if(setjmp(jbuf) == 0){ + if(sigsetjmp(jbuf, 1) == 0) ret = strlen(str) + 1; - } - else { - ret = *faddrp - (unsigned long) str; - } + else ret = *faddrp - (unsigned long) str; + *fault_addr = NULL; *fault_catcher = NULL; + + TASK_REGS(get_current())->tt = save; return ret; } diff -Nru a/arch/um/kernel/tt/unmap.c b/arch/um/kernel/tt/unmap.c --- a/arch/um/kernel/tt/unmap.c 2004-08-25 22:01:56 -07:00 +++ b/arch/um/kernel/tt/unmap.c 2004-08-25 22:01:56 -07:00 @@ -3,10 +3,7 @@ * Licensed under the GPL */ -#include -#include #include -#include "user.h" int switcheroo(int fd, int prot, void *from, void *to, int size) { diff -Nru a/arch/um/kernel/tty_log.c b/arch/um/kernel/tty_log.c --- a/arch/um/kernel/tty_log.c 2004-08-25 22:01:55 -07:00 +++ b/arch/um/kernel/tty_log.c 2004-08-25 22:01:55 -07:00 @@ -9,10 +9,10 @@ #include #include #include -#include #include #include "init.h" #include "user.h" +#include "kern_util.h" #include "os.h" #define TTY_LOG_DIR "./" @@ -24,29 +24,40 @@ #define TTY_LOG_OPEN 1 #define TTY_LOG_CLOSE 2 #define TTY_LOG_WRITE 3 +#define TTY_LOG_EXEC 4 + +#define TTY_READ 1 +#define TTY_WRITE 2 struct tty_log_buf { int what; unsigned long tty; int len; + int direction; + unsigned long sec; + unsigned long usec; }; -int open_tty_log(void *tty) +int open_tty_log(void *tty, void *current_tty) { struct timeval tv; struct tty_log_buf data; char buf[strlen(tty_log_dir) + sizeof("01234567890-01234567\0")]; int fd; + gettimeofday(&tv, NULL); if(tty_log_fd != -1){ - data = ((struct tty_log_buf) { what : TTY_LOG_OPEN, - tty : (unsigned long) tty, - len : 0 }); - write(tty_log_fd, &data, sizeof(data)); + data = ((struct tty_log_buf) { .what = TTY_LOG_OPEN, + .tty = (unsigned long) tty, + .len = sizeof(current_tty), + .direction = 0, + .sec = tv.tv_sec, + .usec = tv.tv_usec } ); + os_write_file(tty_log_fd, &data, sizeof(data)); + os_write_file(tty_log_fd, ¤t_tty, data.len); return(tty_log_fd); } - gettimeofday(&tv, NULL); sprintf(buf, "%s/%0u-%0u", tty_log_dir, (unsigned int) tv.tv_sec, (unsigned int) tv.tv_usec); @@ -62,30 +73,117 @@ void close_tty_log(int fd, void *tty) { struct tty_log_buf data; + struct timeval tv; if(tty_log_fd != -1){ - data = ((struct tty_log_buf) { what : TTY_LOG_CLOSE, - tty : (unsigned long) tty, - len : 0 }); - write(tty_log_fd, &data, sizeof(data)); + gettimeofday(&tv, NULL); + data = ((struct tty_log_buf) { .what = TTY_LOG_CLOSE, + .tty = (unsigned long) tty, + .len = 0, + .direction = 0, + .sec = tv.tv_sec, + .usec = tv.tv_usec } ); + os_write_file(tty_log_fd, &data, sizeof(data)); return; } - close(fd); + os_close_file(fd); } -int write_tty_log(int fd, char *buf, int len, void *tty) +static int log_chunk(int fd, const char *buf, int len) { + int total = 0, try, missed, n; + char chunk[64]; + + while(len > 0){ + try = (len > sizeof(chunk)) ? sizeof(chunk) : len; + missed = copy_from_user_proc(chunk, (char *) buf, try); + try -= missed; + n = os_write_file(fd, chunk, try); + if(n != try) { + if(n < 0) + return(n); + return(-EIO); + } + if(missed != 0) + return(-EFAULT); + + len -= try; + total += try; + buf += try; + } + + return(total); +} + +int write_tty_log(int fd, const char *buf, int len, void *tty, int is_read) +{ + struct timeval tv; struct tty_log_buf data; + int direction; if(fd == tty_log_fd){ - data = ((struct tty_log_buf) { what : TTY_LOG_WRITE, - tty : (unsigned long) tty, - len : len }); - write(tty_log_fd, &data, sizeof(data)); + gettimeofday(&tv, NULL); + direction = is_read ? TTY_READ : TTY_WRITE; + data = ((struct tty_log_buf) { .what = TTY_LOG_WRITE, + .tty = (unsigned long) tty, + .len = len, + .direction = direction, + .sec = tv.tv_sec, + .usec = tv.tv_usec } ); + os_write_file(tty_log_fd, &data, sizeof(data)); + } + + return(log_chunk(fd, buf, len)); +} + +void log_exec(char **argv, void *tty) +{ + struct timeval tv; + struct tty_log_buf data; + char **ptr,*arg; + int len; + + if(tty_log_fd == -1) return; + + gettimeofday(&tv, NULL); + + len = 0; + for(ptr = argv; ; ptr++){ + if(copy_from_user_proc(&arg, ptr, sizeof(arg))) + return; + if(arg == NULL) break; + len += strlen_user_proc(arg); + } + + data = ((struct tty_log_buf) { .what = TTY_LOG_EXEC, + .tty = (unsigned long) tty, + .len = len, + .direction = 0, + .sec = tv.tv_sec, + .usec = tv.tv_usec } ); + os_write_file(tty_log_fd, &data, sizeof(data)); + + for(ptr = argv; ; ptr++){ + if(copy_from_user_proc(&arg, ptr, sizeof(arg))) + return; + if(arg == NULL) break; + log_chunk(tty_log_fd, arg, strlen_user_proc(arg)); } - return(write(fd, buf, len)); } +extern void register_tty_logger(int (*opener)(void *, void *), + int (*writer)(int, const char *, int, + void *, int), + void (*closer)(int, void *)); + +static int register_logger(void) +{ + register_tty_logger(open_tty_log, write_tty_log, close_tty_log); + return(0); +} + +__uml_initcall(register_logger); + static int __init set_tty_log_dir(char *name, int *add) { tty_log_dir = name; @@ -104,7 +202,7 @@ tty_log_fd = strtoul(name, &end, 0); if((*end != '\0') || (end == name)){ - printk("set_tty_log_fd - strtoul failed on '%s'\n", name); + printf("set_tty_log_fd - strtoul failed on '%s'\n", name); tty_log_fd = -1; } return 0; diff -Nru a/arch/um/kernel/uaccess_user.c b/arch/um/kernel/uaccess_user.c --- a/arch/um/kernel/uaccess_user.c 2004-08-25 22:01:56 -07:00 +++ b/arch/um/kernel/uaccess_user.c 2004-08-25 22:01:56 -07:00 @@ -20,7 +20,7 @@ jmp_buf jbuf; *fault_catcher = &jbuf; - if(setjmp(jbuf) == 0){ + if(sigsetjmp(jbuf, 1) == 0){ (*op)(to, from, n); ret = 0; *faulted_out = 0; diff -Nru a/arch/um/kernel/um_arch.c b/arch/um/kernel/um_arch.c --- a/arch/um/kernel/um_arch.c 2004-08-25 22:01:56 -07:00 +++ b/arch/um/kernel/um_arch.c 2004-08-25 22:01:56 -07:00 @@ -38,13 +38,18 @@ #include "mode_kern.h" #include "mode.h" -#define DEFAULT_COMMAND_LINE "root=6200" +#define DEFAULT_COMMAND_LINE "root=98:0" struct cpuinfo_um boot_cpu_data = { .loops_per_jiffy = 0, .ipi_pipe = { -1, -1 } }; +/* Placeholder to make UML link until the vsyscall stuff is actually + * implemented + */ +void *__kernel_vsyscall; + unsigned long thread_saved_pc(struct task_struct *task) { return(os_process_pc(CHOOSE_MODE_PROC(thread_pid_tt, thread_pid_skas, @@ -53,18 +58,22 @@ static int show_cpuinfo(struct seq_file *m, void *v) { - int index; + int index = 0; - index = (struct cpuinfo_um *)v - cpu_data; #ifdef CONFIG_SMP + index = (struct cpuinfo_um *) v - cpu_data; if (!cpu_online(index)) return 0; #endif - seq_printf(m, "bogomips\t: %lu.%02lu\n", + seq_printf(m, "processor\t: %d\n", index); + seq_printf(m, "vendor_id\t: User Mode Linux\n"); + seq_printf(m, "model name\t: UML\n"); + seq_printf(m, "mode\t\t: %s\n", CHOOSE_MODE("tt", "skas")); + seq_printf(m, "host\t\t: %s\n", host_info); + seq_printf(m, "bogomips\t: %lu.%02lu\n\n", loops_per_jiffy/(500000/HZ), (loops_per_jiffy/(5000/HZ)) % 100); - seq_printf(m, "host\t\t: %s\n", host_info); return(0); } @@ -134,12 +143,12 @@ if(umid != NULL){ snprintf(argv1_begin, (argv1_end - argv1_begin) * sizeof(*ptr), - "(%s)", umid); + "(%s) ", umid); ptr = &argv1_begin[strlen(argv1_begin)]; } else ptr = argv1_begin; - snprintf(ptr, (argv1_end - ptr) * sizeof(*ptr), " [%s]", cmd); + snprintf(ptr, (argv1_end - ptr) * sizeof(*ptr), "[%s]", cmd); memset(argv1_begin + strlen(argv1_begin), '\0', argv1_end - argv1_begin - strlen(argv1_begin)); #endif @@ -179,7 +188,7 @@ static int __init uml_ncpus_setup(char *line, int *add) { if (!sscanf(line, "%d", &ncpus)) { - printk("Couldn't parse [%s]\n", line); + printf("Couldn't parse [%s]\n", line); return -1; } @@ -210,7 +219,7 @@ static int __init mode_tt_setup(char *line, int *add) { - printk("CONFIG_MODE_TT disabled - 'mode=tt' ignored\n"); + printf("CONFIG_MODE_TT disabled - 'mode=tt' ignored\n"); return(0); } @@ -221,7 +230,7 @@ static int __init mode_tt_setup(char *line, int *add) { - printk("CONFIG_MODE_SKAS disabled - 'mode=tt' redundant\n"); + printf("CONFIG_MODE_SKAS disabled - 'mode=tt' redundant\n"); return(0); } @@ -291,7 +300,7 @@ /* Set during early boot */ unsigned long brk_start; -static struct vm_reserved kernel_vm_reserved; +unsigned long end_iomem; #define MIN_VMALLOC (32 * 1024 * 1024) @@ -299,7 +308,7 @@ { unsigned long avail; unsigned long virtmem_size, max_physmem; - unsigned int i, add, err; + unsigned int i, add; for (i = 1; i < argc; i++){ if((i == 1) && (argv[i][0] == ' ')) continue; @@ -328,12 +337,16 @@ argv1_end = &argv[1][strlen(argv[1])]; #endif - set_usable_vm(uml_physmem, get_kmem_end()); - highmem = 0; - max_physmem = get_kmem_end() - uml_physmem - MIN_VMALLOC; - if(physmem_size > max_physmem){ - highmem = physmem_size - max_physmem; + iomem_size = (iomem_size + PAGE_SIZE - 1) & PAGE_MASK; + max_physmem = get_kmem_end() - uml_physmem - iomem_size - MIN_VMALLOC; + + /* Zones have to begin on a 1 << MAX_ORDER page boundary, + * so this makes sure that's true for highmem + */ + max_physmem &= ~((1 << (PAGE_SHIFT + MAX_ORDER)) - 1); + if(physmem_size + iomem_size > max_physmem){ + highmem = physmem_size + iomem_size - max_physmem; physmem_size -= highmem; #ifndef CONFIG_HIGHMEM highmem = 0; @@ -343,11 +356,19 @@ } high_physmem = uml_physmem + physmem_size; - high_memory = (void *) high_physmem; + end_iomem = high_physmem + iomem_size; + high_memory = (void *) end_iomem; start_vm = VMALLOC_START; - setup_physmem(uml_physmem, uml_reserved, physmem_size); + setup_physmem(uml_physmem, uml_reserved, physmem_size, highmem); + if(init_maps(physmem_size, iomem_size, highmem)){ + printf("Failed to allocate mem_map for %ld bytes of physical " + "memory and %ld bytes of highmem\n", physmem_size, + highmem); + exit(1); + } + virtmem_size = physmem_size; avail = get_kmem_end() - start_vm; if(physmem_size > avail) virtmem_size = avail; @@ -357,28 +378,26 @@ printf("Kernel virtual memory size shrunk to %ld bytes\n", virtmem_size); - err = reserve_vm(high_physmem, end_vm, &kernel_vm_reserved); - if(err){ - printf("Failed to reserve VM area for kernel VM\n"); - exit(1); - } - uml_postsetup(); init_task.thread.kernel_stack = (unsigned long) &init_thread_info + 2 * PAGE_SIZE; task_protections((unsigned long) &init_thread_info); + os_flush_stdout(); return(CHOOSE_MODE(start_uml_tt(), start_uml_skas())); } +extern int uml_exitcode; + static int panic_exit(struct notifier_block *self, unsigned long unused1, void *unused2) { #ifdef CONFIG_MAGIC_SYSRQ - handle_sysrq('p', ¤t->thread.regs, NULL, NULL); + handle_sysrq('p', ¤t->thread.regs, NULL); #endif + uml_exitcode = 1; machine_halt(); return(0); } @@ -403,6 +422,11 @@ arch_check_bugs(); check_ptrace(); check_sigio(); + check_devanon(); +} + +void apply_alternatives(void *start, void *end) +{ } /* diff -Nru a/arch/um/kernel/umid.c b/arch/um/kernel/umid.c --- a/arch/um/kernel/umid.c 2004-08-25 22:01:56 -07:00 +++ b/arch/um/kernel/umid.c 2004-08-25 22:01:56 -07:00 @@ -5,7 +5,6 @@ #include #include -#include #include #include #include @@ -33,18 +32,19 @@ static int umid_is_random = 1; static int umid_inited = 0; -static int make_umid(void); +static int make_umid(int (*printer)(const char *fmt, ...)); -static int __init set_umid(char *name, int is_random) +static int __init set_umid(char *name, int is_random, + int (*printer)(const char *fmt, ...)) { if(umid_inited){ - printk("Unique machine name can't be set twice\n"); + (*printer)("Unique machine name can't be set twice\n"); return(-1); } if(strlen(name) > UMID_LEN - 1) - printk("Unique machine name is being truncated to %s " - "characters\n", UMID_LEN); + (*printer)("Unique machine name is being truncated to %s " + "characters\n", UMID_LEN); strlcpy(umid, name, sizeof(umid)); umid_is_random = is_random; @@ -54,7 +54,7 @@ static int __init set_umid_arg(char *name, int *add) { - return(set_umid(name, 0)); + return(set_umid(name, 0, printf)); } __uml_setup("umid=", set_umid_arg, @@ -67,7 +67,7 @@ { int n; - if(!umid_inited && make_umid()) return(-1); + if(!umid_inited && make_umid(printk)) return(-1); n = strlen(uml_dir) + strlen(umid) + strlen(name) + 1; if(n > len){ @@ -85,22 +85,23 @@ { char file[strlen(uml_dir) + UMID_LEN + sizeof("/pid\0")]; char pid[sizeof("nnnnn\0")]; - int fd; + int fd, n; if(umid_file_name("pid", file, sizeof(file))) return 0; fd = os_open_file(file, of_create(of_excl(of_rdwr(OPENFLAGS()))), 0644); if(fd < 0){ - printk("Open of machine pid file \"%s\" failed - " - "errno = %d\n", file, -fd); + printf("Open of machine pid file \"%s\" failed - " + "err = %d\n", file, -fd); return 0; } sprintf(pid, "%d\n", os_getpid()); - if(write(fd, pid, strlen(pid)) != strlen(pid)) - printk("Write of pid file failed - errno = %d\n", errno); - close(fd); + n = os_write_file(fd, pid, strlen(pid)); + if(n != strlen(pid)) + printf("Write of pid file failed - err = %d\n", -n); + os_close_file(fd); return 0; } @@ -111,7 +112,8 @@ int len; char file[256]; - if((directory = opendir(dir)) == NULL){ + directory = opendir(dir); + if(directory == NULL){ printk("actually_do_remove : couldn't open directory '%s', " "errno = %d\n", dir, errno); return(1); @@ -160,22 +162,24 @@ { char file[strlen(uml_dir) + UMID_LEN + sizeof("/pid\0")]; char pid[sizeof("nnnnn\0")], *end; - int dead, fd, p; + int dead, fd, p, n; sprintf(file, "%s/pid", dir); dead = 0; - if((fd = os_open_file(file, of_read(OPENFLAGS()), 0)) < 0){ + fd = os_open_file(file, of_read(OPENFLAGS()), 0); + if(fd < 0){ if(fd != -ENOENT){ printk("not_dead_yet : couldn't open pid file '%s', " - "errno = %d\n", file, -fd); + "err = %d\n", file, -fd); return(1); } dead = 1; } if(fd > 0){ - if(read(fd, pid, sizeof(pid)) < 0){ + n = os_read_file(fd, pid, sizeof(pid)); + if(n < 0){ printk("not_dead_yet : couldn't read pid file '%s', " - "errno = %d\n", file, errno); + "err = %d\n", file, -n); return(1); } p = strtoul(pid, &end, 0); @@ -197,7 +201,7 @@ if((strlen(name) > 0) && (name[strlen(name) - 1] != '/')){ uml_dir = malloc(strlen(name) + 1); if(uml_dir == NULL){ - printk("Failed to malloc uml_dir - error = %d\n", + printf("Failed to malloc uml_dir - error = %d\n", errno); uml_dir = name; return(0); @@ -217,7 +221,7 @@ char *home = getenv("HOME"); if(home == NULL){ - printk("make_uml_dir : no value in environment for " + printf("make_uml_dir : no value in environment for " "$HOME\n"); exit(1); } @@ -232,57 +236,59 @@ dir[len + 1] = '\0'; } - if((uml_dir = malloc(strlen(dir) + 1)) == NULL){ + uml_dir = malloc(strlen(dir) + 1); + if(uml_dir == NULL){ printf("make_uml_dir : malloc failed, errno = %d\n", errno); exit(1); } strcpy(uml_dir, dir); if((mkdir(uml_dir, 0777) < 0) && (errno != EEXIST)){ - printk("Failed to mkdir %s - errno = %i\n", uml_dir, errno); + printf("Failed to mkdir %s - errno = %i\n", uml_dir, errno); return(-1); } return 0; } -static int __init make_umid(void) +static int __init make_umid(int (*printer)(const char *fmt, ...)) { int fd, err; char tmp[strlen(uml_dir) + UMID_LEN + 1]; strlcpy(tmp, uml_dir, sizeof(tmp)); - if(*umid == 0){ + if(!umid_inited){ strcat(tmp, "XXXXXX"); fd = mkstemp(tmp); if(fd < 0){ - printk("make_umid - mkstemp failed, errno = %d\n", - errno); + (*printer)("make_umid - mkstemp failed, errno = %d\n", + errno); return(1); } - close(fd); + os_close_file(fd); /* There's a nice tiny little race between this unlink and * the mkdir below. It'd be nice if there were a mkstemp * for directories. */ unlink(tmp); - set_umid(&tmp[strlen(uml_dir)], 1); + set_umid(&tmp[strlen(uml_dir)], 1, printer); } sprintf(tmp, "%s%s", uml_dir, umid); - if((err = mkdir(tmp, 0777)) < 0){ + err = mkdir(tmp, 0777); + if(err < 0){ if(errno == EEXIST){ if(not_dead_yet(tmp)){ - printk("umid '%s' is in use\n", umid); + (*printer)("umid '%s' is in use\n", umid); return(-1); } err = mkdir(tmp, 0777); } } if(err < 0){ - printk("Failed to create %s - errno = %d\n", umid, errno); + (*printer)("Failed to create %s - errno = %d\n", umid, errno); return(-1); } @@ -295,7 +301,13 @@ ); __uml_postsetup(make_uml_dir); -__uml_postsetup(make_umid); + +static int __init make_umid_setup(void) +{ + return(make_umid(printf)); +} + +__uml_postsetup(make_umid_setup); __uml_postsetup(create_pid_file); /* diff -Nru a/arch/um/kernel/uml.lds.S b/arch/um/kernel/uml.lds.S --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/arch/um/kernel/uml.lds.S 2004-08-25 22:01:55 -07:00 @@ -0,0 +1,96 @@ +#include + +OUTPUT_FORMAT(ELF_FORMAT) +OUTPUT_ARCH(ELF_ARCH) +ENTRY(_start) +jiffies = jiffies_64; + +SECTIONS +{ + . = START + SIZEOF_HEADERS; + + __binary_start = .; +#ifdef MODE_TT + .thread_private : { + __start_thread_private = .; + errno = .; + . += 4; + arch/um/kernel/tt/unmap_fin.o (.data) + __end_thread_private = .; + } + . = ALIGN(4096); + .remap : { arch/um/kernel/tt/unmap_fin.o (.text) } +#endif + + . = ALIGN(4096); /* Init code and data */ + _stext = .; + __init_begin = .; + .init.text : { + _sinittext = .; + *(.init.text) + _einittext = .; + } + . = ALIGN(4096); + .text : + { + *(.text) + SCHED_TEXT + /* .gnu.warning sections are handled specially by elf32.em. */ + *(.gnu.warning) + *(.gnu.linkonce.t*) + } + + #include "asm/common.lds.S" + + init.data : { *(init.data) } + .data : + { + . = ALIGN(KERNEL_STACK_SIZE); /* init_task */ + *(.data.init_task) + *(.data) + *(.gnu.linkonce.d*) + CONSTRUCTORS + } + .data1 : { *(.data1) } + .ctors : + { + *(.ctors) + } + .dtors : + { + *(.dtors) + } + + .got : { *(.got.plt) *(.got) } + .dynamic : { *(.dynamic) } + /* We want the small data sections together, so single-instruction offsets + can access them all, and initialized data all before uninitialized, so + we can shorten the on-disk segment size. */ + .sdata : { *(.sdata) } + _edata = .; + PROVIDE (edata = .); + . = ALIGN(0x1000); + .sbss : + { + __bss_start = .; + PROVIDE(_bss_start = .); + *(.sbss) + *(.scommon) + } + .bss : + { + *(.dynbss) + *(.bss) + *(COMMON) + } + _end = . ; + PROVIDE (end = .); + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } +} diff -Nru a/arch/um/kernel/user_syms.c b/arch/um/kernel/user_syms.c --- a/arch/um/kernel/user_syms.c 2004-08-25 22:01:56 -07:00 +++ /dev/null Wed Dec 31 16:00:00 196900 @@ -1,113 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "user_util.h" -#include "mem_user.h" -#include "uml-config.h" - -/* Had to steal this from linux/module.h because that file can't be included - * since this includes various user-level headers. - */ - -struct module_symbol -{ - unsigned long value; - const char *name; -}; - -/* Indirect stringification. */ - -#define __MODULE_STRING_1(x) #x -#define __MODULE_STRING(x) __MODULE_STRING_1(x) - -#if !defined(__AUTOCONF_INCLUDED__) - -#define __EXPORT_SYMBOL(sym,str) error config_must_be_included_before_module -#define EXPORT_SYMBOL(var) error config_must_be_included_before_module -#define EXPORT_SYMBOL_NOVERS(var) error config_must_be_included_before_module - -#elif !defined(UML_CONFIG_MODULES) - -#define __EXPORT_SYMBOL(sym,str) -#define EXPORT_SYMBOL(var) -#define EXPORT_SYMBOL_NOVERS(var) - -#else - -#define __EXPORT_SYMBOL(sym, str) \ -const char __kstrtab_##sym[] \ -__attribute__((section(".kstrtab"))) = str; \ -const struct module_symbol __ksymtab_##sym \ -__attribute__((section("__ksymtab"))) = \ -{ (unsigned long)&sym, __kstrtab_##sym } - -#if defined(__MODVERSIONS__) || !defined(UML_CONFIG_MODVERSIONS) -#define EXPORT_SYMBOL(var) __EXPORT_SYMBOL(var, __MODULE_STRING(var)) -#else -#define EXPORT_SYMBOL(var) __EXPORT_SYMBOL(var, __MODULE_STRING(__VERSIONED_SYMBOL(var))) -#endif - -#define EXPORT_SYMBOL_NOVERS(var) __EXPORT_SYMBOL(var, __MODULE_STRING(var)) - -#endif - -EXPORT_SYMBOL(__errno_location); - -EXPORT_SYMBOL(access); -EXPORT_SYMBOL(open); -EXPORT_SYMBOL(open64); -EXPORT_SYMBOL(close); -EXPORT_SYMBOL(read); -EXPORT_SYMBOL(write); -EXPORT_SYMBOL(dup2); -EXPORT_SYMBOL(__xstat); -EXPORT_SYMBOL(__lxstat); -EXPORT_SYMBOL(__lxstat64); -EXPORT_SYMBOL(lseek); -EXPORT_SYMBOL(lseek64); -EXPORT_SYMBOL(chown); -EXPORT_SYMBOL(truncate); -EXPORT_SYMBOL(utime); -EXPORT_SYMBOL(chmod); -EXPORT_SYMBOL(rename); -EXPORT_SYMBOL(__xmknod); - -EXPORT_SYMBOL(symlink); -EXPORT_SYMBOL(link); -EXPORT_SYMBOL(unlink); -EXPORT_SYMBOL(readlink); - -EXPORT_SYMBOL(mkdir); -EXPORT_SYMBOL(rmdir); -EXPORT_SYMBOL(opendir); -EXPORT_SYMBOL(readdir); -EXPORT_SYMBOL(closedir); -EXPORT_SYMBOL(seekdir); -EXPORT_SYMBOL(telldir); - -EXPORT_SYMBOL(ioctl); - -extern ssize_t pread64 (int __fd, void *__buf, size_t __nbytes, - __off64_t __offset); -extern ssize_t pwrite64 (int __fd, __const void *__buf, size_t __n, - __off64_t __offset); -EXPORT_SYMBOL(pread64); -EXPORT_SYMBOL(pwrite64); - -EXPORT_SYMBOL(statfs); -EXPORT_SYMBOL(statfs64); - -EXPORT_SYMBOL(memcpy); -EXPORT_SYMBOL(getuid); - -EXPORT_SYMBOL(memset); -EXPORT_SYMBOL(strstr); - -EXPORT_SYMBOL(find_iomem); diff -Nru a/arch/um/kernel/user_util.c b/arch/um/kernel/user_util.c --- a/arch/um/kernel/user_util.c 2004-08-25 22:01:54 -07:00 +++ b/arch/um/kernel/user_util.c 2004-08-25 22:01:54 -07:00 @@ -5,7 +5,6 @@ #include #include -#include #include #include #include @@ -81,10 +80,10 @@ int status, ret; while(1){ - if(((ret = waitpid(pid, &status, WUNTRACED)) < 0) || + CATCH_EINTR(ret = waitpid(pid, &status, WUNTRACED)); + if((ret < 0) || !WIFSTOPPED(status) || (WSTOPSIG(status) != sig)){ if(ret < 0){ - if(errno == EINTR) continue; printk("wait failed, errno = %d\n", errno); } @@ -118,29 +117,36 @@ } } -int clone_and_wait(int (*fn)(void *), void *arg, void *sp, int flags) -{ - int pid; - - pid = clone(fn, sp, flags, arg); - if(pid < 0) return(-1); - wait_for_stop(pid, SIGSTOP, PTRACE_CONT, NULL); - ptrace(PTRACE_CONT, pid, 0, 0); - return(pid); -} - -int raw(int fd, int complain) +int __raw(int fd, int complain, int now) { struct termios tt; int err; + int when; + + CATCH_EINTR(err = tcgetattr(fd, &tt)); + + if (err < 0) { + if (complain) + printk("tcgetattr failed, errno = %d\n", errno); + return(-errno); + } - tcgetattr(fd, &tt); cfmakeraw(&tt); - err = tcsetattr(fd, TCSANOW, &tt); - if((err < 0) && complain){ - printk("tcsetattr failed, errno = %d\n", errno); + + if (now) + when = TCSANOW; + else + when = TCSADRAIN; + + CATCH_EINTR(err = tcsetattr(fd, when, &tt)); + + if (err < 0) { + if (complain) + printk("tcsetattr failed, errno = %d\n", errno); return(-errno); } + /*XXX: tcsetattr could have applied only some changes + * (and cfmakeraw() is a set of changes) */ return(0); } diff -Nru a/arch/um/main.c b/arch/um/main.c --- a/arch/um/main.c 2004-08-25 22:01:56 -07:00 +++ /dev/null Wed Dec 31 16:00:00 196900 @@ -1,195 +0,0 @@ -/* - * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com) - * Licensed under the GPL - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "user_util.h" -#include "kern_util.h" -#include "mem_user.h" -#include "signal_user.h" -#include "user.h" -#include "init.h" -#include "mode.h" -#include "choose-mode.h" -#include "uml-config.h" - -/* Set in set_stklim, which is called from main and __wrap_malloc. - * __wrap_malloc only calls it if main hasn't started. - */ -unsigned long stacksizelim; - -/* Set in main */ -char *linux_prog; - -#define PGD_BOUND (4 * 1024 * 1024) -#define STACKSIZE (8 * 1024 * 1024) -#define THREAD_NAME_LEN (256) - -static void set_stklim(void) -{ - struct rlimit lim; - - if(getrlimit(RLIMIT_STACK, &lim) < 0){ - perror("getrlimit"); - exit(1); - } - if((lim.rlim_cur == RLIM_INFINITY) || (lim.rlim_cur > STACKSIZE)){ - lim.rlim_cur = STACKSIZE; - if(setrlimit(RLIMIT_STACK, &lim) < 0){ - perror("setrlimit"); - exit(1); - } - } - stacksizelim = (lim.rlim_cur + PGD_BOUND - 1) & ~(PGD_BOUND - 1); -} - -static __init void do_uml_initcalls(void) -{ - initcall_t *call; - - call = &__uml_initcall_start; - while (call < &__uml_initcall_end){; - (*call)(); - call++; - } -} - -static void last_ditch_exit(int sig) -{ - CHOOSE_MODE(kmalloc_ok = 0, (void) 0); - signal(SIGINT, SIG_DFL); - signal(SIGTERM, SIG_DFL); - signal(SIGHUP, SIG_DFL); - uml_cleanup(); - exit(1); -} - -extern int uml_exitcode; - -int main(int argc, char **argv, char **envp) -{ - char **new_argv; - sigset_t mask; - int ret, i; - - /* Enable all signals except SIGIO - in some environments, we can - * enter with some signals blocked - */ - - sigemptyset(&mask); - sigaddset(&mask, SIGIO); - if(sigprocmask(SIG_SETMASK, &mask, NULL) < 0){ - perror("sigprocmask"); - exit(1); - } - -#ifdef UML_CONFIG_MODE_TT - /* Allocate memory for thread command lines */ - if(argc < 2 || strlen(argv[1]) < THREAD_NAME_LEN - 1){ - - char padding[THREAD_NAME_LEN] = { - [ 0 ... THREAD_NAME_LEN - 2] = ' ', '\0' - }; - - new_argv = malloc((argc + 2) * sizeof(char*)); - if(!new_argv) { - perror("Allocating extended argv"); - exit(1); - } - - new_argv[0] = argv[0]; - new_argv[1] = padding; - - for(i = 2; i <= argc; i++) - new_argv[i] = argv[i - 1]; - new_argv[argc + 1] = NULL; - - execvp(new_argv[0], new_argv); - perror("execing with extended args"); - exit(1); - } -#endif - - linux_prog = argv[0]; - - set_stklim(); - - if((new_argv = malloc((argc + 1) * sizeof(char *))) == NULL){ - perror("Mallocing argv"); - exit(1); - } - for(i=0;i #include #include -#include #include #include #include @@ -17,6 +16,7 @@ #include #include "user.h" #include "kern_util.h" +#include "user_util.h" #include "net_user.h" #include "etap.h" #include "helper.h" @@ -42,13 +42,14 @@ { struct addr_change change; void *output; + int n; change.what = op; memcpy(change.addr, addr, sizeof(change.addr)); memcpy(change.netmask, netmask, sizeof(change.netmask)); - if(write(fd, &change, sizeof(change)) != sizeof(change)) - printk("etap_change - request failed, errno = %d\n", - errno); + n = os_write_file(fd, &change, sizeof(change)); + if(n != sizeof(change)) + printk("etap_change - request failed, err = %d\n", -n); output = um_kmalloc(page_size()); if(output == NULL) printk("etap_change : Failed to allocate output buffer\n"); @@ -82,15 +83,15 @@ struct etap_pre_exec_data *data = arg; dup2(data->control_remote, 1); - close(data->data_me); - close(data->control_me); + os_close_file(data->data_me); + os_close_file(data->control_me); } static int etap_tramp(char *dev, char *gate, int control_me, int control_remote, int data_me, int data_remote) { struct etap_pre_exec_data pe_data; - int pid, status, err; + int pid, status, err, n; char version_buf[sizeof("nnnnn\0")]; char data_fd_buf[sizeof("nnnnnn\0")]; char gate_buf[sizeof("nnn.nnn.nnn.nnn\0")]; @@ -114,21 +115,22 @@ pe_data.data_me = data_me; pid = run_helper(etap_pre_exec, &pe_data, args, NULL); - if(pid < 0) err = errno; - close(data_remote); - close(control_remote); - if(read(control_me, &c, sizeof(c)) != sizeof(c)){ - printk("etap_tramp : read of status failed, errno = %d\n", - errno); - return(EINVAL); + if(pid < 0) err = pid; + os_close_file(data_remote); + os_close_file(control_remote); + n = os_read_file(control_me, &c, sizeof(c)); + if(n != sizeof(c)){ + printk("etap_tramp : read of status failed, err = %d\n", -n); + return(-EINVAL); } if(c != 1){ printk("etap_tramp : uml_net failed\n"); - err = EINVAL; - if(waitpid(pid, &status, 0) < 0) err = errno; - else if(!WIFEXITED(status) || (WEXITSTATUS(status) != 1)){ + err = -EINVAL; + CATCH_EINTR(n = waitpid(pid, &status, 0)); + if(n < 0) + err = -errno; + else if(!WIFEXITED(status) || (WEXITSTATUS(status) != 1)) printk("uml_net didn't exit with status 1\n"); - } } return(err); } @@ -143,14 +145,14 @@ if(err) return(err); err = os_pipe(data_fds, 0, 0); - if(err){ - printk("data os_pipe failed - errno = %d\n", -err); + if(err < 0){ + printk("data os_pipe failed - err = %d\n", -err); return(err); } err = os_pipe(control_fds, 1, 0); - if(err){ - printk("control os_pipe failed - errno = %d\n", -err); + if(err < 0){ + printk("control os_pipe failed - err = %d\n", -err); return(err); } @@ -167,9 +169,9 @@ kfree(output); } - if(err != 0){ - printk("etap_tramp failed - errno = %d\n", err); - return(-err); + if(err < 0){ + printk("etap_tramp failed - err = %d\n", -err); + return(err); } pri->data_fd = data_fds[0]; @@ -183,11 +185,11 @@ struct ethertap_data *pri = data; iter_addresses(pri->dev, etap_close_addr, &pri->control_fd); - close(fd); + os_close_file(fd); os_shutdown_socket(pri->data_fd, 1, 1); - close(pri->data_fd); + os_close_file(pri->data_fd); pri->data_fd = -1; - close(pri->control_fd); + os_close_file(pri->control_fd); pri->control_fd = -1; } diff -Nru a/arch/um/os-Linux/drivers/tuntap_user.c b/arch/um/os-Linux/drivers/tuntap_user.c --- a/arch/um/os-Linux/drivers/tuntap_user.c 2004-08-25 22:01:56 -07:00 +++ b/arch/um/os-Linux/drivers/tuntap_user.c 2004-08-25 22:01:56 -07:00 @@ -8,7 +8,6 @@ #include #include #include -#include #include #include #include @@ -19,6 +18,7 @@ #include "net_user.h" #include "tuntap.h" #include "kern_util.h" +#include "user_util.h" #include "user.h" #include "helper.h" #include "os.h" @@ -61,7 +61,7 @@ struct tuntap_pre_exec_data *data = arg; dup2(data->stdout, 1); - close(data->close_me); + os_close_file(data->close_me); } static int tuntap_open_tramp(char *gate, int *fd_out, int me, int remote, @@ -86,7 +86,7 @@ if(pid < 0) return(-pid); - close(remote); + os_close_file(remote); msg.msg_name = NULL; msg.msg_namelen = 0; @@ -107,19 +107,19 @@ if(n < 0){ printk("tuntap_open_tramp : recvmsg failed - errno = %d\n", errno); - return(errno); + return(-errno); } - waitpid(pid, NULL, 0); + CATCH_EINTR(waitpid(pid, NULL, 0)); cmsg = CMSG_FIRSTHDR(&msg); if(cmsg == NULL){ printk("tuntap_open_tramp : didn't receive a message\n"); - return(EINVAL); + return(-EINVAL); } if((cmsg->cmsg_level != SOL_SOCKET) || (cmsg->cmsg_type != SCM_RIGHTS)){ printk("tuntap_open_tramp : didn't receive a descriptor\n"); - return(EINVAL); + return(-EINVAL); } *fd_out = ((int *) CMSG_DATA(cmsg))[0]; return(0); @@ -133,27 +133,29 @@ int err, fds[2], len, used; err = tap_open_common(pri->dev, pri->gate_addr); - if(err) return(err); + if(err < 0) + return(err); if(pri->fixed_config){ - if((pri->fd = open("/dev/net/tun", O_RDWR)) < 0){ - printk("Failed to open /dev/net/tun, errno = %d\n", - errno); - return(-errno); + pri->fd = os_open_file("/dev/net/tun", of_rdwr(OPENFLAGS()), 0); + if(pri->fd < 0){ + printk("Failed to open /dev/net/tun, err = %d\n", + -pri->fd); + return(pri->fd); } memset(&ifr, 0, sizeof(ifr)); - ifr.ifr_flags = IFF_TAP; + ifr.ifr_flags = IFF_TAP | IFF_NO_PI; strlcpy(ifr.ifr_name, pri->dev_name, sizeof(ifr.ifr_name)); if(ioctl(pri->fd, TUNSETIFF, (void *) &ifr) < 0){ - printk("TUNSETIFF failed, errno = %d", errno); - close(pri->fd); + printk("TUNSETIFF failed, errno = %d\n", errno); + os_close_file(pri->fd); return(-errno); } } else { err = os_pipe(fds, 0, 0); - if(err){ - printk("tuntap_open : os_pipe failed - errno = %d\n", + if(err < 0){ + printk("tuntap_open : os_pipe failed - err = %d\n", -err); return(err); } @@ -166,19 +168,19 @@ fds[1], buffer, len, &used); output = buffer; - if(err == 0){ - pri->dev_name = uml_strdup(buffer); - output += IFNAMSIZ; - printk(output); - free_output_buffer(buffer); - } - else { - printk(output); + if(err < 0) { + printk("%s", output); free_output_buffer(buffer); - printk("tuntap_open_tramp failed - errno = %d\n", err); - return(-err); + printk("tuntap_open_tramp failed - err = %d\n", -err); + return(err); } - close(fds[0]); + + pri->dev_name = uml_strdup(buffer); + output += IFNAMSIZ; + printk("%s", output); + free_output_buffer(buffer); + + os_close_file(fds[0]); iter_addresses(pri->dev, open_addr, pri->dev_name); } @@ -191,7 +193,7 @@ if(!pri->fixed_config) iter_addresses(pri->dev, close_addr, pri->dev_name); - close(fd); + os_close_file(fd); pri->fd = -1; } diff -Nru a/arch/um/os-Linux/file.c b/arch/um/os-Linux/file.c --- a/arch/um/os-Linux/file.c 2004-08-25 22:01:56 -07:00 +++ b/arch/um/os-Linux/file.c 2004-08-25 22:01:56 -07:00 @@ -8,6 +8,8 @@ #include #include #include +#include +#include #include #include #include @@ -17,33 +19,235 @@ #include "user.h" #include "kern_util.h" -int os_file_type(char *file) +static void copy_stat(struct uml_stat *dst, struct stat64 *src) +{ + *dst = ((struct uml_stat) { + .ust_dev = src->st_dev, /* device */ + .ust_ino = src->st_ino, /* inode */ + .ust_mode = src->st_mode, /* protection */ + .ust_nlink = src->st_nlink, /* number of hard links */ + .ust_uid = src->st_uid, /* user ID of owner */ + .ust_gid = src->st_gid, /* group ID of owner */ + .ust_size = src->st_size, /* total size, in bytes */ + .ust_blksize = src->st_blksize, /* blocksize for filesys I/O */ + .ust_blocks = src->st_blocks, /* number of blocks allocated */ + .ust_atime = src->st_atime, /* time of last access */ + .ust_mtime = src->st_mtime, /* time of last modification */ + .ust_ctime = src->st_ctime, /* time of last change */ + }); +} + +int os_stat_fd(const int fd, struct uml_stat *ubuf) +{ + struct stat64 sbuf; + int err; + + do { + err = fstat64(fd, &sbuf); + } while((err < 0) && (errno == EINTR)) ; + + if(err < 0) + return(-errno); + + if(ubuf != NULL) + copy_stat(ubuf, &sbuf); + return(err); +} + +int os_stat_file(const char *file_name, struct uml_stat *ubuf) +{ + struct stat64 sbuf; + int err; + + do { + err = stat64(file_name, &sbuf); + } while((err < 0) && (errno == EINTR)) ; + + if(err < 0) + return(-errno); + + if(ubuf != NULL) + copy_stat(ubuf, &sbuf); + return(err); +} + +int os_access(const char* file, int mode) +{ + int amode, err; + + amode=(mode&OS_ACC_R_OK ? R_OK : 0) | (mode&OS_ACC_W_OK ? W_OK : 0) | + (mode&OS_ACC_X_OK ? X_OK : 0) | (mode&OS_ACC_F_OK ? F_OK : 0) ; + + err = access(file, amode); + if(err < 0) + return(-errno); + + return(0); +} + +void os_print_error(int error, const char* str) +{ + errno = error < 0 ? -error : error; + + perror(str); +} + +/* FIXME? required only by hostaudio (because it passes ioctls verbatim) */ +int os_ioctl_generic(int fd, unsigned int cmd, unsigned long arg) +{ + int err; + + err = ioctl(fd, cmd, arg); + if(err < 0) + return(-errno); + + return(err); +} + +int os_window_size(int fd, int *rows, int *cols) +{ + struct winsize size; + + if(ioctl(fd, TIOCGWINSZ, &size) < 0) + return(-errno); + + *rows = size.ws_row; + *cols = size.ws_col; + + return(0); +} + +int os_new_tty_pgrp(int fd, int pid) { - struct stat64 buf; + if(ioctl(fd, TIOCSCTTY, 0) < 0){ + printk("TIOCSCTTY failed, errno = %d\n", errno); + return(-errno); + } + + if(tcsetpgrp(fd, pid) < 0){ + printk("tcsetpgrp failed, errno = %d\n", errno); + return(-errno); + } + + return(0); +} + +/* FIXME: ensure namebuf in os_get_if_name is big enough */ +int os_get_ifname(int fd, char* namebuf) +{ + if(ioctl(fd, SIOCGIFNAME, namebuf) < 0) + return(-errno); + + return(0); +} + +int os_set_slip(int fd) +{ + int disc, sencap; + + disc = N_SLIP; + if(ioctl(fd, TIOCSETD, &disc) < 0){ + printk("Failed to set slip line discipline - " + "errno = %d\n", errno); + return(-errno); + } + + sencap = 0; + if(ioctl(fd, SIOCSIFENCAP, &sencap) < 0){ + printk("Failed to set slip encapsulation - " + "errno = %d\n", errno); + return(-errno); + } + + return(0); +} + +int os_set_owner(int fd, int pid) +{ + if(fcntl(fd, F_SETOWN, pid) < 0){ + int save_errno = errno; + + if(fcntl(fd, F_GETOWN, 0) != pid) + return(-save_errno); + } + + return(0); +} + +/* FIXME? moved wholesale from sigio_user.c to get fcntls out of that file */ +int os_sigio_async(int master, int slave) +{ + int flags; - if(stat64(file, &buf) == -1) + flags = fcntl(master, F_GETFL); + if(flags < 0) { + printk("fcntl F_GETFL failed, errno = %d\n", errno); return(-errno); + } + + if((fcntl(master, F_SETFL, flags | O_NONBLOCK | O_ASYNC) < 0) || + (fcntl(master, F_SETOWN, os_getpid()) < 0)){ + printk("fcntl F_SETFL or F_SETOWN failed, errno = %d\n", errno); + return(-errno); + } + + if((fcntl(slave, F_SETFL, flags | O_NONBLOCK) < 0)){ + printk("fcntl F_SETFL failed, errno = %d\n", errno); + return(-errno); + } - if(S_ISDIR(buf.st_mode)) return(OS_TYPE_DIR); - else if(S_ISLNK(buf.st_mode)) return(OS_TYPE_SYMLINK); - else if(S_ISCHR(buf.st_mode)) return(OS_TYPE_CHARDEV); - else if(S_ISBLK(buf.st_mode)) return(OS_TYPE_BLOCKDEV); - else if(S_ISFIFO(buf.st_mode)) return(OS_TYPE_FIFO); - else if(S_ISSOCK(buf.st_mode)) return(OS_TYPE_SOCK); + return(0); +} + +int os_mode_fd(int fd, int mode) +{ + int err; + + do { + err = fchmod(fd, mode); + } while((err < 0) && (errno==EINTR)) ; + + if(err < 0) + return(-errno); + + return(0); +} + +int os_file_type(char *file) +{ + struct uml_stat buf; + int err; + + err = os_stat_file(file, &buf); + if(err < 0) + return(err); + + if(S_ISDIR(buf.ust_mode)) return(OS_TYPE_DIR); + else if(S_ISLNK(buf.ust_mode)) return(OS_TYPE_SYMLINK); + else if(S_ISCHR(buf.ust_mode)) return(OS_TYPE_CHARDEV); + else if(S_ISBLK(buf.ust_mode)) return(OS_TYPE_BLOCKDEV); + else if(S_ISFIFO(buf.ust_mode)) return(OS_TYPE_FIFO); + else if(S_ISSOCK(buf.ust_mode)) return(OS_TYPE_SOCK); else return(OS_TYPE_FILE); } int os_file_mode(char *file, struct openflags *mode_out) { + int err; + *mode_out = OPENFLAGS(); - if(!access(file, W_OK)) *mode_out = of_write(*mode_out); - else if(errno != EACCES) - return(-errno); + err = os_access(file, OS_ACC_W_OK); + if((err < 0) && (err != -EACCES)) + return(err); - if(!access(file, R_OK)) *mode_out = of_read(*mode_out); - else if(errno != EACCES) - return(-errno); + *mode_out = of_write(*mode_out); + + err = os_access(file, OS_ACC_R_OK); + if((err < 0) && (err != -EACCES)) + return(err); + + *mode_out = of_read(*mode_out); return(0); } @@ -63,16 +267,14 @@ if(flags.e) f |= O_EXCL; fd = open64(file, f, mode); - if(fd < 0) return(-errno); - - if(flags.cl){ - if(fcntl(fd, F_SETFD, 1)){ - close(fd); - return(-errno); - } + if(fd < 0) + return(-errno); + + if(flags.cl && fcntl(fd, F_SETFD, 1)){ + os_close_file(fd); + return(-errno); } - return(fd); return(fd); } @@ -90,7 +292,7 @@ err = connect(fd, (struct sockaddr *) &sock, sizeof(sock)); if(err) - return(err); + return(-errno); return(fd); } @@ -109,88 +311,162 @@ return(0); } -int os_read_file(int fd, void *buf, int len) +static int fault_buffer(void *start, int len, + int (*copy_proc)(void *addr, void *buf, int len)) { - int n; + int page = getpagesize(), i; + char c; - /* Force buf into memory if it's not already. */ + for(i = 0; i < len; i += page){ + if((*copy_proc)(start + i, &c, sizeof(c))) + return(-EFAULT); + } + if((len % page) != 0){ + if((*copy_proc)(start + len - 1, &c, sizeof(c))) + return(-EFAULT); + } + return(0); +} - /* XXX This fails if buf is kernel memory */ -#ifdef notdef - if(copy_to_user_proc(buf, &c, sizeof(c))) - return(-EFAULT); -#endif +static int file_io(int fd, void *buf, int len, + int (*io_proc)(int fd, void *buf, int len), + int (*copy_user_proc)(void *addr, void *buf, int len)) +{ + int n, err; + + do { + n = (*io_proc)(fd, buf, len); + if((n < 0) && (errno == EFAULT)){ + err = fault_buffer(buf, len, copy_user_proc); + if(err) + return(err); + n = (*io_proc)(fd, buf, len); + } + } while((n < 0) && (errno == EINTR)); - n = read(fd, buf, len); if(n < 0) return(-errno); return(n); } -int os_write_file(int fd, void *buf, int count) +int os_read_file(int fd, void *buf, int len) { - int n; - - /* Force buf into memory if it's not already. */ - - /* XXX This fails if buf is kernel memory */ -#ifdef notdef - if(copy_to_user_proc(buf, buf, buf[0])) - return(-EFAULT); -#endif + return(file_io(fd, buf, len, (int (*)(int, void *, int)) read, + copy_from_user_proc)); +} - n = write(fd, buf, count); - if(n < 0) - return(-errno); - return(n); +int os_write_file(int fd, const void *buf, int len) +{ + return(file_io(fd, (void *) buf, len, + (int (*)(int, void *, int)) write, copy_to_user_proc)); } int os_file_size(char *file, long long *size_out) { - struct stat64 buf; + struct uml_stat buf; + int err; - if(stat64(file, &buf) == -1){ - printk("Couldn't stat \"%s\" : errno = %d\n", file, errno); - return(-errno); + err = os_stat_file(file, &buf); + if(err < 0){ + printk("Couldn't stat \"%s\" : err = %d\n", file, -err); + return(err); } - if(S_ISBLK(buf.st_mode)){ + + if(S_ISBLK(buf.ust_mode)){ int fd, blocks; - if((fd = open64(file, O_RDONLY)) < 0){ - printk("Couldn't open \"%s\", errno = %d\n", file, - errno); - return(-errno); + fd = os_open_file(file, of_read(OPENFLAGS()), 0); + if(fd < 0){ + printk("Couldn't open \"%s\", errno = %d\n", file, -fd); + return(fd); } if(ioctl(fd, BLKGETSIZE, &blocks) < 0){ printk("Couldn't get the block size of \"%s\", " "errno = %d\n", file, errno); - close(fd); - return(-errno); + err = -errno; + os_close_file(fd); + return(err); } *size_out = ((long long) blocks) * 512; - close(fd); + os_close_file(fd); return(0); } - *size_out = buf.st_size; + *size_out = buf.ust_size; + return(0); +} + +int os_file_modtime(char *file, unsigned long *modtime) +{ + struct uml_stat buf; + int err; + + err = os_stat_file(file, &buf); + if(err < 0){ + printk("Couldn't stat \"%s\" : err = %d\n", file, -err); + return(err); + } + + *modtime = buf.ust_mtime; return(0); } +int os_get_exec_close(int fd, int* close_on_exec) +{ + int ret; + + do { + ret = fcntl(fd, F_GETFD); + } while((ret < 0) && (errno == EINTR)) ; + + if(ret < 0) + return(-errno); + + *close_on_exec = (ret&FD_CLOEXEC) ? 1 : 0; + return(ret); +} + +int os_set_exec_close(int fd, int close_on_exec) +{ + int flag, err; + + if(close_on_exec) flag = FD_CLOEXEC; + else flag = 0; + + do { + err = fcntl(fd, F_SETFD, flag); + } while((err < 0) && (errno == EINTR)) ; + + if(err < 0) + return(-errno); + return(err); +} + int os_pipe(int *fds, int stream, int close_on_exec) { int err, type = stream ? SOCK_STREAM : SOCK_DGRAM; err = socketpair(AF_UNIX, type, 0, fds); - if(err) + if(err < 0) return(-errno); if(!close_on_exec) return(0); - if((fcntl(fds[0], F_SETFD, 1) < 0) || (fcntl(fds[1], F_SETFD, 1) < 0)) - printk("os_pipe : Setting FD_CLOEXEC failed, errno = %d", - errno); + err = os_set_exec_close(fds[0], 1); + if(err < 0) + goto error; + + err = os_set_exec_close(fds[1], 1); + if(err < 0) + goto error; return(0); + + error: + printk("os_pipe : Setting FD_CLOEXEC failed, err = %d\n", -err); + os_close_file(fds[1]); + os_close_file(fds[0]); + return(err); } int os_set_fd_async(int fd, int owner) @@ -270,7 +546,7 @@ return(-EINVAL); } err = shutdown(fd, what); - if(err) + if(err < 0) return(-errno); return(0); } @@ -315,7 +591,7 @@ return(new); } -int create_unix_socket(char *file, int len) +int os_create_unix_socket(char *file, int len, int close_on_exec) { struct sockaddr_un addr; int sock, err; @@ -327,6 +603,13 @@ return(-errno); } + if(close_on_exec) { + err = os_set_exec_close(sock, 1); + if(err < 0) + printk("create_unix_socket : close_on_exec failed, " + "err = %d", -err); + } + addr.sun_family = AF_UNIX; /* XXX Be more careful about overflow */ @@ -334,12 +617,43 @@ err = bind(sock, (struct sockaddr *) &addr, sizeof(addr)); if (err < 0){ - printk("create_listening_socket - bind failed, errno = %d\n", - errno); + printk("create_listening_socket at '%s' - bind failed, " + "errno = %d\n", file, errno); return(-errno); } return(sock); +} + +void os_flush_stdout(void) +{ + fflush(stdout); +} + +int os_lock_file(int fd, int excl) +{ + int type = excl ? F_WRLCK : F_RDLCK; + struct flock lock = ((struct flock) { .l_type = type, + .l_whence = SEEK_SET, + .l_start = 0, + .l_len = 0 } ); + int err, save; + + err = fcntl(fd, F_SETLK, &lock); + if(!err) + goto out; + + save = -errno; + err = fcntl(fd, F_GETLK, &lock); + if(err){ + err = -errno; + goto out; + } + + printk("F_SETLK failed, file already locked by pid %d\n", lock.l_pid); + err = save; + out: + return(err); } /* diff -Nru a/arch/um/os-Linux/process.c b/arch/um/os-Linux/process.c --- a/arch/um/os-Linux/process.c 2004-08-25 22:01:54 -07:00 +++ b/arch/um/os-Linux/process.c 2004-08-25 22:01:54 -07:00 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) + * Copyright (C) 2002 Jeff Dike (jdike@addtoit.com) * Licensed under the GPL */ @@ -7,35 +7,44 @@ #include #include #include +#include #include #include #include "os.h" #include "user.h" +#include "user_util.h" + +#define ARBITRARY_ADDR -1 +#define FAILURE_PID -1 + +#define STAT_PATH_LEN sizeof("/proc/#######/stat\0") +#define COMM_SCANF "%*[^)])" unsigned long os_process_pc(int pid) { - char proc_stat[sizeof("/proc/#####/stat\0")], buf[256]; + char proc_stat[STAT_PATH_LEN], buf[256]; unsigned long pc; - int fd; + int fd, err; sprintf(proc_stat, "/proc/%d/stat", pid); fd = os_open_file(proc_stat, of_read(OPENFLAGS()), 0); if(fd < 0){ - printk("os_process_pc - couldn't open '%s', errno = %d\n", - proc_stat, errno); - return(-1); + printk("os_process_pc - couldn't open '%s', err = %d\n", + proc_stat, -fd); + return(ARBITRARY_ADDR); } - if(read(fd, buf, sizeof(buf)) < 0){ - printk("os_process_pc - couldn't read '%s', errno = %d\n", - proc_stat, errno); - close(fd); - return(-1); + err = os_read_file(fd, buf, sizeof(buf)); + if(err < 0){ + printk("os_process_pc - couldn't read '%s', err = %d\n", + proc_stat, -err); + os_close_file(fd); + return(ARBITRARY_ADDR); } - close(fd); - pc = -1; - if(sscanf(buf, "%*d %*s %*c %*d %*d %*d %*d %*d %*d %*d %*d " + os_close_file(fd); + pc = ARBITRARY_ADDR; + if(sscanf(buf, "%*d " COMM_SCANF " %*c %*d %*d %*d %*d %*d %*d %*d %*d " "%*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d " - "%*d %*d %*d %*d %ld", &pc) != 1){ + "%*d %*d %*d %*d %lu", &pc) != 1){ printk("os_process_pc - couldn't find pc in '%s'\n", buf); } return(pc); @@ -43,7 +52,7 @@ int os_process_parent(int pid) { - char stat[sizeof("/proc/nnnnn/stat\0")]; + char stat[STAT_PATH_LEN]; char data[256]; int parent, n, fd; @@ -52,22 +61,22 @@ snprintf(stat, sizeof(stat), "/proc/%d/stat", pid); fd = os_open_file(stat, of_read(OPENFLAGS()), 0); if(fd < 0){ - printk("Couldn't open '%s', errno = %d\n", stat, -fd); - return(-1); + printk("Couldn't open '%s', err = %d\n", stat, -fd); + return(FAILURE_PID); } - n = read(fd, data, sizeof(data)); - close(fd); + n = os_read_file(fd, data, sizeof(data)); + os_close_file(fd); if(n < 0){ - printk("Couldn't read '%s', errno = %d\n", stat); - return(-1); + printk("Couldn't read '%s', err = %d\n", stat, -n); + return(FAILURE_PID); } - parent = -1; - /* XXX This will break if there is a space in the command */ - n = sscanf(data, "%*d %*s %*c %d", &parent); - if(n != 1) printk("Failed to scan '%s'\n", data); + parent = FAILURE_PID; + n = sscanf(data, "%*d " COMM_SCANF " %*c %d", &parent); + if(n != 1) + printk("Failed to scan '%s'\n", data); return(parent); } @@ -81,13 +90,17 @@ { kill(pid, SIGKILL); if(reap_child) - waitpid(pid, NULL, 0); + CATCH_EINTR(waitpid(pid, NULL, 0)); } void os_usr1_process(int pid) { +#ifdef __NR_tkill + syscall(__NR_tkill, pid, SIGUSR1); +#else kill(pid, SIGUSR1); +#endif } int os_getpid(void) @@ -95,7 +108,7 @@ return(getpid()); } -int os_map_memory(void *virt, int fd, unsigned long off, unsigned long len, +int os_map_memory(void *virt, int fd, unsigned long long off, unsigned long len, int r, int w, int x) { void *loc; @@ -104,8 +117,8 @@ prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) | (x ? PROT_EXEC : 0); - loc = mmap((void *) virt, len, prot, MAP_SHARED | MAP_FIXED, - fd, off); + loc = mmap64((void *) virt, len, prot, MAP_SHARED | MAP_FIXED, + fd, off); if(loc == MAP_FAILED) return(-errno); return(0); @@ -126,7 +139,8 @@ int err; err = munmap(addr, len); - if(err < 0) return(-errno); + if(err < 0) + return(-errno); return(0); } diff -Nru a/arch/um/os-Linux/tty.c b/arch/um/os-Linux/tty.c --- a/arch/um/os-Linux/tty.c 2004-08-25 22:01:55 -07:00 +++ b/arch/um/os-Linux/tty.c 2004-08-25 22:01:55 -07:00 @@ -28,10 +28,10 @@ struct grantpt_info info; int fd; - if((fd = os_open_file("/dev/ptmx", of_rdwr(OPENFLAGS()), 0)) < 0){ - printk("get_pty : Couldn't open /dev/ptmx - errno = %d\n", - errno); - return(-1); + fd = os_open_file("/dev/ptmx", of_rdwr(OPENFLAGS()), 0); + if(fd < 0){ + printk("get_pty : Couldn't open /dev/ptmx - err = %d\n", -fd); + return(fd); } info.fd = fd; @@ -39,7 +39,7 @@ if(info.res < 0){ printk("get_pty : Couldn't grant pty - errno = %d\n", - info.err); + -info.err); return(-1); } if(unlockpt(fd) < 0){ diff -Nru a/arch/um/os-Linux/user_syms.c b/arch/um/os-Linux/user_syms.c --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/arch/um/os-Linux/user_syms.c 2004-08-25 22:01:56 -07:00 @@ -0,0 +1,88 @@ +#include "linux/types.h" +#include "linux/module.h" + +/* Some of this are builtin function (some are not but could in the future), + * so I *must* declare good prototypes for them and then EXPORT them. + * The kernel code uses the macro defined by include/linux/string.h, + * so I undef macros; the userspace code does not include that and I + * add an EXPORT for the glibc one.*/ + +#undef strlen +#undef strstr +#undef memcpy +#undef memset + +extern size_t strlen(const char *); +extern void *memcpy(void *, const void *, size_t); +extern void *memset(void *, int, size_t); +extern int printf(const char *, ...); + +EXPORT_SYMBOL(strlen); +EXPORT_SYMBOL(memcpy); +EXPORT_SYMBOL(memset); +EXPORT_SYMBOL(printf); + +EXPORT_SYMBOL(strstr); + +/* Here, instead, I can provide a fake prototype. Yes, someone cares: genksyms. + * However, the modules will use the CRC defined *here*, no matter if it is + * good; so the versions of these symbols will always match + */ +#define EXPORT_SYMBOL_PROTO(sym) \ + int sym(void); \ + EXPORT_SYMBOL(sym); + +EXPORT_SYMBOL_PROTO(__errno_location); + +EXPORT_SYMBOL_PROTO(access); +EXPORT_SYMBOL_PROTO(open); +EXPORT_SYMBOL_PROTO(open64); +EXPORT_SYMBOL_PROTO(close); +EXPORT_SYMBOL_PROTO(read); +EXPORT_SYMBOL_PROTO(write); +EXPORT_SYMBOL_PROTO(dup2); +EXPORT_SYMBOL_PROTO(__xstat); +EXPORT_SYMBOL_PROTO(__lxstat); +EXPORT_SYMBOL_PROTO(__lxstat64); +EXPORT_SYMBOL_PROTO(lseek); +EXPORT_SYMBOL_PROTO(lseek64); +EXPORT_SYMBOL_PROTO(chown); +EXPORT_SYMBOL_PROTO(truncate); +EXPORT_SYMBOL_PROTO(utime); +EXPORT_SYMBOL_PROTO(chmod); +EXPORT_SYMBOL_PROTO(rename); +EXPORT_SYMBOL_PROTO(__xmknod); + +EXPORT_SYMBOL_PROTO(symlink); +EXPORT_SYMBOL_PROTO(link); +EXPORT_SYMBOL_PROTO(unlink); +EXPORT_SYMBOL_PROTO(readlink); + +EXPORT_SYMBOL_PROTO(mkdir); +EXPORT_SYMBOL_PROTO(rmdir); +EXPORT_SYMBOL_PROTO(opendir); +EXPORT_SYMBOL_PROTO(readdir); +EXPORT_SYMBOL_PROTO(closedir); +EXPORT_SYMBOL_PROTO(seekdir); +EXPORT_SYMBOL_PROTO(telldir); + +EXPORT_SYMBOL_PROTO(ioctl); + +EXPORT_SYMBOL_PROTO(pread64); +EXPORT_SYMBOL_PROTO(pwrite64); + +EXPORT_SYMBOL_PROTO(statfs); +EXPORT_SYMBOL_PROTO(statfs64); + +EXPORT_SYMBOL_PROTO(getuid); + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff -Nru a/arch/um/sys-i386/Makefile b/arch/um/sys-i386/Makefile --- a/arch/um/sys-i386/Makefile 2004-08-25 22:01:54 -07:00 +++ b/arch/um/sys-i386/Makefile 2004-08-25 22:01:54 -07:00 @@ -1,14 +1,18 @@ -obj-y = bugs.o checksum.o extable.o fault.o ksyms.o ldt.o module.o \ - ptrace.o ptrace_user.o semaphore.o sigcontext.o syscalls.o sysrq.o +obj-y = bitops.o bugs.o checksum.o fault.o ksyms.o ldt.o ptrace.o \ + ptrace_user.o semaphore.o sigcontext.o syscalls.o sysrq.o time.o obj-$(CONFIG_HIGHMEM) += highmem.o +obj-$(CONFIG_MODULES) += module.o USER_OBJS := bugs.o ptrace_user.o sigcontext.o fault.o USER_OBJS := $(foreach file,$(USER_OBJS),$(obj)/$(file)) -SYMLINKS = semaphore.c highmem.c module.c +SYMLINKS = bitops.c semaphore.c highmem.c module.c SYMLINKS := $(foreach f,$(SYMLINKS),$(src)/$f) +clean-files := $(SYMLINKS) + +bitops.c-dir = lib semaphore.c-dir = kernel highmem.c-dir = mm module.c-dir = kernel @@ -24,19 +28,4 @@ $(SYMLINKS): $(call make_link,$@) -clean: - $(MAKE) -C util clean - -fastdep: - -dep: - -archmrproper: - rm -f $(SYMLINKS) - -archclean: - -archdep: - -modules: - +subdir- := util diff -Nru a/arch/um/sys-i386/bugs.c b/arch/um/sys-i386/bugs.c --- a/arch/um/sys-i386/bugs.c 2004-08-25 22:01:56 -07:00 +++ b/arch/um/sys-i386/bugs.c 2004-08-25 22:01:56 -07:00 @@ -4,20 +4,21 @@ */ #include -#include #include #include #include +#include #include "kern_util.h" #include "user.h" #include "sysdep/ptrace.h" #include "task.h" +#include "os.h" #define MAXTOKEN 64 /* Set during early boot */ -int cpu_has_cmov = 1; -int cpu_has_xmm = 0; +int host_has_cmov = 1; +int host_has_xmm = 0; static char token(int fd, char *buf, int len, char stop) { @@ -27,13 +28,15 @@ ptr = buf; end = &buf[len]; do { - n = read(fd, ptr, sizeof(*ptr)); + n = os_read_file(fd, ptr, sizeof(*ptr)); c = *ptr++; - if(n == 0) return(0); - else if(n != sizeof(*ptr)){ - printk("Reading /proc/cpuinfo failed, " - "errno = %d\n", errno); - return(-errno); + if(n != sizeof(*ptr)){ + if(n == 0) return(0); + printk("Reading /proc/cpuinfo failed, err = %d\n", -n); + if(n < 0) + return(n); + else + return(-EIO); } } while((c != '\n') && (c != stop) && (ptr < end)); @@ -45,45 +48,79 @@ return(c); } -static int check_cpu_feature(char *feature, int *have_it) +static int find_cpuinfo_line(int fd, char *key, char *scratch, int len) { - char buf[MAXTOKEN], c; - int fd, len = sizeof(buf)/sizeof(buf[0]), n; - - printk("Checking for host processor %s support...", feature); - fd = open("/proc/cpuinfo", O_RDONLY); - if(fd < 0){ - printk("Couldn't open /proc/cpuinfo, errno = %d\n", errno); - return(0); - } + int n; + char c; - *have_it = 0; - buf[len - 1] = '\0'; + scratch[len - 1] = '\0'; while(1){ - c = token(fd, buf, len - 1, ':'); - if(c <= 0) goto out; + c = token(fd, scratch, len - 1, ':'); + if(c <= 0) + return(0); else if(c != ':'){ printk("Failed to find ':' in /proc/cpuinfo\n"); - goto out; + return(0); } - if(!strncmp(buf, "flags", strlen("flags"))) break; + if(!strncmp(scratch, key, strlen(key))) + return(1); do { - n = read(fd, &c, sizeof(c)); + n = os_read_file(fd, &c, sizeof(c)); if(n != sizeof(c)){ printk("Failed to find newline in " - "/proc/cpuinfo, n = %d, errno = %d\n", - n, errno); - goto out; + "/proc/cpuinfo, err = %d\n", -n); + return(0); } } while(c != '\n'); } + return(0); +} + +int cpu_feature(char *what, char *buf, int len) +{ + int fd, ret = 0; + + fd = os_open_file("/proc/cpuinfo", of_read(OPENFLAGS()), 0); + if(fd < 0){ + printk("Couldn't open /proc/cpuinfo, err = %d\n", -fd); + return(0); + } + + if(!find_cpuinfo_line(fd, what, buf, len)){ + printk("Couldn't find '%s' line in /proc/cpuinfo\n", what); + goto out_close; + } + + token(fd, buf, len, '\n'); + ret = 1; + + out_close: + os_close_file(fd); + return(ret); +} + +static int check_cpu_flag(char *feature, int *have_it) +{ + char buf[MAXTOKEN], c; + int fd, len = sizeof(buf)/sizeof(buf[0]); + + printk("Checking for host processor %s support...", feature); + fd = os_open_file("/proc/cpuinfo", of_read(OPENFLAGS()), 0); + if(fd < 0){ + printk("Couldn't open /proc/cpuinfo, err = %d\n", -fd); + return(0); + } + + *have_it = 0; + if(!find_cpuinfo_line(fd, "flags", buf, sizeof(buf) / sizeof(buf[0]))) + goto out; c = token(fd, buf, len - 1, ' '); if(c < 0) goto out; else if(c != ' '){ - printk("Failed to find ':' in /proc/cpuinfo\n"); + printk("Failed to find ' ' in /proc/cpuinfo\n"); goto out; } @@ -100,21 +137,48 @@ out: if(*have_it == 0) printk("No\n"); else if(*have_it == 1) printk("Yes\n"); - close(fd); + os_close_file(fd); return(1); } +#if 0 /* This doesn't work in tt mode, plus it's causing compilation problems + * for some people. + */ +static void disable_lcall(void) +{ + struct modify_ldt_ldt_s ldt; + int err; + + bzero(&ldt, sizeof(ldt)); + ldt.entry_number = 7; + ldt.base_addr = 0; + ldt.limit = 0; + err = modify_ldt(1, &ldt, sizeof(ldt)); + if(err) + printk("Failed to disable lcall7 - errno = %d\n", errno); +} +#endif + +void arch_init_thread(void) +{ +#if 0 + disable_lcall(); +#endif +} + void arch_check_bugs(void) { int have_it; - if(access("/proc/cpuinfo", R_OK)){ + if(os_access("/proc/cpuinfo", OS_ACC_R_OK) < 0){ printk("/proc/cpuinfo not available - skipping CPU capability " "checks\n"); return; } - if(check_cpu_feature("cmov", &have_it)) cpu_has_cmov = have_it; - if(check_cpu_feature("xmm", &have_it)) cpu_has_xmm = have_it; + if(check_cpu_flag("cmov", &have_it)) + host_has_cmov = have_it; + if(check_cpu_flag("xmm", &have_it)) + host_has_xmm = have_it; } int arch_handle_signal(int sig, union uml_pt_regs *regs) @@ -130,18 +194,18 @@ if((*((char *) ip) != 0x0f) || ((*((char *) (ip + 1)) & 0xf0) != 0x40)) return(0); - if(cpu_has_cmov == 0) + if(host_has_cmov == 0) panic("SIGILL caused by cmov, which this processor doesn't " "implement, boot a filesystem compiled for older " "processors"); - else if(cpu_has_cmov == 1) + else if(host_has_cmov == 1) panic("SIGILL caused by cmov, which this processor claims to " "implement"); - else if(cpu_has_cmov == -1) + else if(host_has_cmov == -1) panic("SIGILL caused by cmov, couldn't tell if this processor " "implements it, boot a filesystem compiled for older " "processors"); - else panic("Bad value for cpu_has_cmov (%d)", cpu_has_cmov); + else panic("Bad value for host_has_cmov (%d)", host_has_cmov); return(0); } diff -Nru a/arch/um/sys-i386/extable.c b/arch/um/sys-i386/extable.c --- a/arch/um/sys-i386/extable.c 2004-08-25 22:01:56 -07:00 +++ /dev/null Wed Dec 31 16:00:00 196900 @@ -1,30 +0,0 @@ -/* - * linux/arch/i386/mm/extable.c - */ - -#include -#include -#include -#include - -/* Simple binary search */ -const struct exception_table_entry * -search_extable(const struct exception_table_entry *first, - const struct exception_table_entry *last, - unsigned long value) -{ - while (first <= last) { - const struct exception_table_entry *mid; - long diff; - - mid = (last - first) / 2 + first; - diff = mid->insn - value; - if (diff == 0) - return mid; - else if (diff < 0) - first = mid+1; - else - last = mid-1; - } - return NULL; -} diff -Nru a/arch/um/sys-i386/fault.c b/arch/um/sys-i386/fault.c --- a/arch/um/sys-i386/fault.c 2004-08-25 22:01:55 -07:00 +++ b/arch/um/sys-i386/fault.c 2004-08-25 22:01:55 -07:00 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) + * Copyright (C) 2002 - 2004 Jeff Dike (jdike@addtoit.com) * Licensed under the GPL */ @@ -7,16 +7,24 @@ #include "sysdep/ptrace.h" #include "sysdep/sigcontext.h" -extern unsigned long search_exception_table(unsigned long addr); +/* These two are from asm-um/uaccess.h and linux/module.h, check them. */ +struct exception_table_entry +{ + unsigned long insn; + unsigned long fixup; +}; +const struct exception_table_entry *search_exception_tables(unsigned long add); + +/* Compare this to arch/i386/mm/extable.c:fixup_exception() */ int arch_fixup(unsigned long address, void *sc_ptr) { struct sigcontext *sc = sc_ptr; - unsigned long fixup; + const struct exception_table_entry *fixup; fixup = search_exception_tables(address); if(fixup != 0){ - sc->eip = fixup; + sc->eip = fixup->fixup; return(1); } return(0); diff -Nru a/arch/um/sys-i386/ptrace_user.c b/arch/um/sys-i386/ptrace_user.c --- a/arch/um/sys-i386/ptrace_user.c 2004-08-25 22:01:56 -07:00 +++ b/arch/um/sys-i386/ptrace_user.c 2004-08-25 22:01:56 -07:00 @@ -39,10 +39,10 @@ nregs = sizeof(dummy->u_debugreg)/sizeof(dummy->u_debugreg[0]); for(i = 0; i < nregs; i++){ if((i == 4) || (i == 5)) continue; - if(ptrace(PTRACE_POKEUSR, pid, &dummy->u_debugreg[i], + if(ptrace(PTRACE_POKEUSER, pid, &dummy->u_debugreg[i], regs[i]) < 0) - printk("write_debugregs - ptrace failed, " - "errno = %d\n", errno); + printk("write_debugregs - ptrace failed on " + "register %d, errno = %d\n", errno); } } @@ -54,7 +54,7 @@ dummy = NULL; nregs = sizeof(dummy->u_debugreg)/sizeof(dummy->u_debugreg[0]); for(i = 0; i < nregs; i++){ - regs[i] = ptrace(PTRACE_PEEKUSR, pid, + regs[i] = ptrace(PTRACE_PEEKUSER, pid, &dummy->u_debugreg[i], 0); } } diff -Nru a/arch/um/sys-i386/time.c b/arch/um/sys-i386/time.c --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/arch/um/sys-i386/time.c 2004-08-25 22:01:56 -07:00 @@ -0,0 +1,24 @@ +/* + * sys-i386/time.c + * Created 25.9.2002 Sapan Bhatia + * + */ + +unsigned long long time_stamp(void) +{ + unsigned long low, high; + + asm("rdtsc" : "=a" (low), "=d" (high)); + return((((unsigned long long) high) << 32) + low); +} + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff -Nru a/arch/um/sys-i386/util/Makefile b/arch/um/sys-i386/util/Makefile --- a/arch/um/sys-i386/util/Makefile 2004-08-25 22:01:56 -07:00 +++ b/arch/um/sys-i386/util/Makefile 2004-08-25 22:01:56 -07:00 @@ -1,15 +1,11 @@ -hostprogs-y := mk_sc -always := $(hostprogs-y) mk_thread -targets := mk_thread_kern.o mk_thread_user.o +hostprogs-y := mk_sc mk_thread +always := $(hostprogs-y) -mk_sc-objs := mk_sc.o +mk_thread-objs := mk_thread_kern.o mk_thread_user.o -$(obj)/mk_thread : $(obj)/mk_thread_kern.o $(obj)/mk_thread_user.o - $(CC) $(CFLAGS) -o $@ $^ - -$(obj)/mk_thread_user.o : $(src)/mk_thread_user.c - $(CC) $(USER_CFLAGS) -c -o $@ $< +HOSTCFLAGS_mk_thread_kern.o := $(CFLAGS) $(CPPFLAGS) +HOSTCFLAGS_mk_thread_user.o := $(USER_CFLAGS) clean : $(RM) -f $(build-targets) diff -Nru a/arch/um/sys-i386/util/mk_sc.c b/arch/um/sys-i386/util/mk_sc.c --- a/arch/um/sys-i386/util/mk_sc.c 2004-08-25 22:01:56 -07:00 +++ b/arch/um/sys-i386/util/mk_sc.c 2004-08-25 22:01:56 -07:00 @@ -38,6 +38,7 @@ SC_OFFSET("SC_ERR", err); SC_OFFSET("SC_CR2", cr2); SC_OFFSET("SC_FPSTATE", fpstate); + SC_OFFSET("SC_SIGMASK", oldmask); SC_FP_OFFSET("SC_FP_CW", cw); SC_FP_OFFSET("SC_FP_SW", sw); SC_FP_OFFSET("SC_FP_TAG", tag); diff -Nru a/arch/um/sys-ia64/Makefile b/arch/um/sys-ia64/Makefile --- a/arch/um/sys-ia64/Makefile 2004-08-25 22:01:54 -07:00 +++ b/arch/um/sys-ia64/Makefile 2004-08-25 22:01:54 -07:00 @@ -7,18 +7,5 @@ $(OBJ): $(OBJS) rm -f $@ $(LD) $(LINKFLAGS) --start-group $^ --end-group -o $@ -clean: - rm -f $(OBJS) -fastdep: - -archmrproper: - -archclean: - rm -f link.ld - @$(MAKEBOOT) clean - -archdep: - @$(MAKEBOOT) dep - -modules: +clean-files := $(OBJS) link.ld diff -Nru a/arch/um/sys-ppc/Makefile b/arch/um/sys-ppc/Makefile --- a/arch/um/sys-ppc/Makefile 2004-08-25 22:01:55 -07:00 +++ b/arch/um/sys-ppc/Makefile 2004-08-25 22:01:55 -07:00 @@ -66,13 +66,4 @@ $(CC) $(EXTRA_AFLAGS) $(AFLAGS) -D__ASSEMBLY__ -D__UM_PPC__ -c $< -o $*.o rm -f asm -clean: - rm -f $(OBJS) - rm -f ppc_defs.h - rm -f checksum.S semaphore.c mk_defs.c - -fastdep: - -dep: - -modules: +clean-files := $(OBJS) ppc_defs.h checksum.S semaphore.c mk_defs.c diff -Nru a/arch/um/uml.lds.S b/arch/um/uml.lds.S --- a/arch/um/uml.lds.S 2004-08-25 22:01:55 -07:00 +++ /dev/null Wed Dec 31 16:00:00 196900 @@ -1,92 +0,0 @@ -#include - -OUTPUT_FORMAT(ELF_FORMAT) -OUTPUT_ARCH(ELF_ARCH) -ENTRY(_start) -jiffies = jiffies_64; - -SECTIONS -{ - . = START + SIZEOF_HEADERS; - - . = ALIGN(4096); - __binary_start = .; -#ifdef MODE_TT - .thread_private : { - __start_thread_private = .; - errno = .; - . += 4; - arch/um/kernel/tt/unmap_fin.o (.data) - __end_thread_private = .; - } - . = ALIGN(4096); - .remap : { arch/um/kernel/tt/unmap_fin.o (.text) } -#endif - - . = ALIGN(4096); /* Init code and data */ - _stext = .; - __init_begin = .; - .text.init : { *(.text.init) } - . = ALIGN(4096); - .text : - { - *(.text) - /* .gnu.warning sections are handled specially by elf32.em. */ - *(.gnu.warning) - *(.gnu.linkonce.t*) - } - - #include "asm/common.lds.S" - - .data.init : { *(.data.init) } - .data : - { - . = ALIGN(KERNEL_STACK_SIZE); /* init_task */ - *(.data.init_task) - *(.data) - *(.gnu.linkonce.d*) - CONSTRUCTORS - } - .data1 : { *(.data1) } - .ctors : - { - *(.ctors) - } - .dtors : - { - *(.dtors) - } - - .got : { *(.got.plt) *(.got) } - .dynamic : { *(.dynamic) } - /* We want the small data sections together, so single-instruction offsets - can access them all, and initialized data all before uninitialized, so - we can shorten the on-disk segment size. */ - .sdata : { *(.sdata) } - _edata = .; - PROVIDE (edata = .); - . = ALIGN(0x1000); - .sbss : - { - __bss_start = .; - PROVIDE(_bss_start = .); - *(.sbss) - *(.scommon) - } - .bss : - { - *(.dynbss) - *(.bss) - *(COMMON) - } - _end = . ; - PROVIDE (end = .); - /* Stabs debugging sections. */ - .stab 0 : { *(.stab) } - .stabstr 0 : { *(.stabstr) } - .stab.excl 0 : { *(.stab.excl) } - .stab.exclstr 0 : { *(.stab.exclstr) } - .stab.index 0 : { *(.stab.index) } - .stab.indexstr 0 : { *(.stab.indexstr) } - .comment 0 : { *(.comment) } -} diff -Nru a/arch/um/util/Makefile b/arch/um/util/Makefile --- a/arch/um/util/Makefile 2004-08-25 22:01:56 -07:00 +++ b/arch/um/util/Makefile 2004-08-25 22:01:56 -07:00 @@ -1,23 +1,8 @@ -always := mk_task mk_constants -targets := mk_task_user.o mk_task_kern.o \ - mk_constants_user.o mk_constants_kern.o +hostprogs-y := mk_task mk_constants +always := $(hostprogs-y) -$(obj)/mk_task: $(obj)/mk_task_user.o $(obj)/mk_task_kern.o - $(CC) -o $@ $^ +mk_task-objs := mk_task_user.o mk_task_kern.o +mk_constants-objs := mk_constants_user.o mk_constants_kern.o -$(obj)/mk_task_user.o: $(src)/mk_task_user.c - $(CC) -o $@ -c $< - -$(obj)/mk_constants : $(obj)/mk_constants_user.o $(obj)/mk_constants_kern.o - $(CC) -o $@ $^ - -$(obj)/mk_constants_user.o : $(src)/mk_constants_user.c - $(CC) -c $< -o $@ - -$(obj)/mk_constants_kern.o : $(src)/mk_constants_kern.c - $(CC) $(CFLAGS) -c $< -o $@ - -clean: - $(RM) $(build-targets) - -archmrproper: +HOSTCFLAGS_mk_task_kern.o := $(CFLAGS) $(CPPFLAGS) +HOSTCFLAGS_mk_constants_kern.o := $(CFLAGS) $(CPPFLAGS) diff -Nru a/arch/um/util/mk_constants_kern.c b/arch/um/util/mk_constants_kern.c --- a/arch/um/util/mk_constants_kern.c 2004-08-25 22:01:54 -07:00 +++ b/arch/um/util/mk_constants_kern.c 2004-08-25 22:01:54 -07:00 @@ -1,5 +1,6 @@ #include "linux/kernel.h" #include "linux/stringify.h" +#include "linux/time.h" #include "asm/page.h" extern void print_head(void); @@ -11,6 +12,7 @@ { print_head(); print_constant_int("UM_KERN_PAGE_SIZE", PAGE_SIZE); + print_constant_str("UM_KERN_EMERG", KERN_EMERG); print_constant_str("UM_KERN_ALERT", KERN_ALERT); print_constant_str("UM_KERN_CRIT", KERN_CRIT); @@ -19,6 +21,8 @@ print_constant_str("UM_KERN_NOTICE", KERN_NOTICE); print_constant_str("UM_KERN_INFO", KERN_INFO); print_constant_str("UM_KERN_DEBUG", KERN_DEBUG); + + print_constant_int("UM_NSEC_PER_SEC", NSEC_PER_SEC); print_tail(); return(0); } diff -Nru a/arch/v850/kernel/setup.c b/arch/v850/kernel/setup.c --- a/arch/v850/kernel/setup.c 2004-08-25 22:01:55 -07:00 +++ b/arch/v850/kernel/setup.c 2004-08-25 22:01:55 -07:00 @@ -280,8 +280,8 @@ #if ((PAGE_OFFSET >> PAGE_SHIFT) & ((1UL << (MAX_ORDER - 1)) - 1)) #error MAX_ORDER is too large for given PAGE_OFFSET (use CONFIG_FORCE_MAX_ZONEORDER to change it) #endif - - free_area_init_node (0, NODE_DATA(0), 0, zones_size, + NODE_DATA(0)->node_mem_map = NULL; + free_area_init_node (0, NODE_DATA(0), zones_size, ADDR_TO_PAGE (PAGE_OFFSET), 0); mem_map = NODE_DATA(0)->node_mem_map; } diff -Nru a/arch/v850/kernel/signal.c b/arch/v850/kernel/signal.c --- a/arch/v850/kernel/signal.c 2004-08-25 22:01:56 -07:00 +++ b/arch/v850/kernel/signal.c 2004-08-25 22:01:56 -07:00 @@ -344,9 +344,7 @@ return; give_sigsegv: - if (sig == SIGSEGV) - ka->sa.sa_handler = SIG_DFL; - force_sig(SIGSEGV, current); + force_sigsegv(sig, current); } static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, @@ -421,9 +419,7 @@ return; give_sigsegv: - if (sig == SIGSEGV) - ka->sa.sa_handler = SIG_DFL; - force_sig(SIGSEGV, current); + force_sigsegv(sig, current); } /* diff -Nru a/arch/v850/kernel/vmlinux.lds.S b/arch/v850/kernel/vmlinux.lds.S --- a/arch/v850/kernel/vmlinux.lds.S 2004-08-25 22:01:55 -07:00 +++ b/arch/v850/kernel/vmlinux.lds.S 2004-08-25 22:01:55 -07:00 @@ -111,9 +111,6 @@ *(.init.setup) /* 2.5 convention */ \ *(.setup.init) /* 2.4 convention */ \ ___setup_end = . ; \ - ___start___param = . ; \ - *(__param) \ - ___stop___param = . ; \ ___initcall_start = . ; \ *(.initcall.init) \ *(.initcall1.init) \ diff -Nru a/arch/x86_64/Kconfig b/arch/x86_64/Kconfig --- a/arch/x86_64/Kconfig 2004-08-25 22:01:56 -07:00 +++ b/arch/x86_64/Kconfig 2004-08-25 22:01:56 -07:00 @@ -347,6 +347,17 @@ depends on PCI select ACPI_BOOT +config UNORDERED_IO + bool "Unordered IO mapping access" + depends on EXPERIMENTAL + select UNORDERED_IO + help + Use unordered stores to access IO memory mappings in device drivers. + Still very experimental. When a driver works on IA64/ppc64/pa-risc it should + work with this option, but it makes the drivers behave differently + from i386. Requires that the driver writer used memory barriers + properly. + source "drivers/pci/Kconfig" source "drivers/pcmcia/Kconfig" diff -Nru a/arch/x86_64/Kconfig.debug b/arch/x86_64/Kconfig.debug --- a/arch/x86_64/Kconfig.debug 2004-08-25 22:01:54 -07:00 +++ b/arch/x86_64/Kconfig.debug 2004-08-25 22:01:54 -07:00 @@ -18,6 +18,18 @@ Fill __init and __initdata at the end of boot. This helps debugging illegal uses of __init and __initdata after initialization. +config SCHEDSTATS + bool "Collect scheduler statistics" + depends on DEBUG_KERNEL && PROC_FS + help + If you say Y here, additional code will be inserted into the + scheduler and related routines to collect statistics about + scheduler behavior and provide them in /proc/schedstat. These + stats may be useful for both tuning and debugging the scheduler + If you aren't debugging the scheduler or trying to tune a specific + application, you can say N to avoid the very slight overhead + this adds. + config FRAME_POINTER bool "Compile the kernel with frame pointers" help diff -Nru a/arch/x86_64/Makefile b/arch/x86_64/Makefile --- a/arch/x86_64/Makefile 2004-08-25 22:01:56 -07:00 +++ b/arch/x86_64/Makefile 2004-08-25 22:01:56 -07:00 @@ -77,6 +77,7 @@ all: bzImage BOOTIMAGE := arch/x86_64/boot/bzImage +KBUILD_IMAGE := $(BOOTIMAGE) bzImage: vmlinux $(Q)$(MAKE) $(build)=$(boot) $(BOOTIMAGE) diff -Nru a/arch/x86_64/defconfig b/arch/x86_64/defconfig --- a/arch/x86_64/defconfig 2004-08-25 22:01:55 -07:00 +++ b/arch/x86_64/defconfig 2004-08-25 22:01:55 -07:00 @@ -17,7 +17,6 @@ # CONFIG_EXPERIMENTAL=y CONFIG_CLEAN_COMPILE=y -CONFIG_STANDALONE=y # # General setup @@ -29,12 +28,13 @@ CONFIG_SYSCTL=y # CONFIG_AUDIT is not set CONFIG_LOG_BUF_SHIFT=18 -# CONFIG_HOTPLUG is not set +CONFIG_HOTPLUG=y CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y # CONFIG_EMBEDDED is not set CONFIG_KALLSYMS=y CONFIG_KALLSYMS_ALL=y +CONFIG_KALLSYMS_EXTRA_PASS=y CONFIG_FUTEX=y CONFIG_EPOLL=y CONFIG_IOSCHED_NOOP=y @@ -104,8 +104,8 @@ CONFIG_ACPI_PROCESSOR=y CONFIG_ACPI_THERMAL=y # CONFIG_ACPI_ASUS is not set -CONFIG_ACPI_TOSHIBA=y -CONFIG_ACPI_DEBUG=y +# CONFIG_ACPI_TOSHIBA is not set +# CONFIG_ACPI_DEBUG is not set CONFIG_ACPI_BUS=y CONFIG_ACPI_EC=y CONFIG_ACPI_POWER=y @@ -115,7 +115,23 @@ # # CPU Frequency scaling # -# CONFIG_CPU_FREQ is not set +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_PROC_INTF=y +CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y +# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=y +CONFIG_CPU_FREQ_GOV_USERSPACE=y +# CONFIG_CPU_FREQ_24_API is not set +CONFIG_CPU_FREQ_TABLE=y + +# +# CPUFreq processor drivers +# +CONFIG_X86_POWERNOW_K8=y +# CONFIG_X86_SPEEDSTEP_CENTRINO is not set +CONFIG_X86_ACPI_CPUFREQ=y +CONFIG_X86_ACPI_CPUFREQ_PROC_INTF=y # # Bus options (PCI etc.) @@ -123,10 +139,27 @@ CONFIG_PCI=y CONFIG_PCI_DIRECT=y CONFIG_PCI_MMCONFIG=y +CONFIG_UNORDERED_IO=y +CONFIG_PCI_MSI=y # CONFIG_PCI_LEGACY_PROC is not set # CONFIG_PCI_NAMES is not set # +# PCMCIA/CardBus support +# +# CONFIG_PCMCIA is not set + +# +# PCI Hotplug Support +# +CONFIG_HOTPLUG_PCI=y +# CONFIG_HOTPLUG_PCI_FAKE is not set +# CONFIG_HOTPLUG_PCI_ACPI is not set +# CONFIG_HOTPLUG_PCI_CPCI is not set +# CONFIG_HOTPLUG_PCI_PCIE is not set +# CONFIG_HOTPLUG_PCI_SHPC is not set + +# # Executable file formats / Emulations # CONFIG_BINFMT_ELF=y @@ -144,6 +177,9 @@ # # Generic Driver Options # +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +# CONFIG_FW_LOADER is not set # CONFIG_DEBUG_DRIVER is not set # @@ -171,7 +207,7 @@ CONFIG_BLK_DEV_LOOP=y # CONFIG_BLK_DEV_CRYPTOLOOP is not set # CONFIG_BLK_DEV_NBD is not set -# CONFIG_BLK_DEV_CARMEL is not set +# CONFIG_BLK_DEV_SX8 is not set CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_SIZE=4096 CONFIG_BLK_DEV_INITRD=y @@ -186,10 +222,10 @@ # # Please see Documentation/ide.txt for help/info on IDE drives # +# CONFIG_BLK_DEV_IDE_SATA is not set # CONFIG_BLK_DEV_HD_IDE is not set CONFIG_BLK_DEV_IDEDISK=y CONFIG_IDEDISK_MULTI_MODE=y -# CONFIG_IDEDISK_STROKE is not set CONFIG_BLK_DEV_IDECD=y # CONFIG_BLK_DEV_IDETAPE is not set # CONFIG_BLK_DEV_IDEFLOPPY is not set @@ -234,7 +270,7 @@ # CONFIG_BLK_DEV_SIS5513 is not set # CONFIG_BLK_DEV_SLC90E66 is not set # CONFIG_BLK_DEV_TRM290 is not set -# CONFIG_BLK_DEV_VIA82CXXX is not set +CONFIG_BLK_DEV_VIA82CXXX=y # CONFIG_IDE_ARM is not set CONFIG_BLK_DEV_IDEDMA=y # CONFIG_IDEDMA_IVB is not set @@ -273,16 +309,24 @@ # SCSI low-level drivers # CONFIG_BLK_DEV_3W_XXXX_RAID=y +# CONFIG_SCSI_3W_9XXX is not set # CONFIG_SCSI_ACARD is not set # CONFIG_SCSI_AACRAID is not set # CONFIG_SCSI_AIC7XXX is not set # CONFIG_SCSI_AIC7XXX_OLD is not set -# CONFIG_SCSI_AIC79XX is not set -# CONFIG_SCSI_ADVANSYS is not set +CONFIG_SCSI_AIC79XX=y +CONFIG_AIC79XX_CMDS_PER_DEVICE=32 +CONFIG_AIC79XX_RESET_DELAY_MS=2000 +# CONFIG_AIC79XX_BUILD_FIRMWARE is not set +# CONFIG_AIC79XX_ENABLE_RD_STRM is not set +# CONFIG_AIC79XX_DEBUG_ENABLE is not set +CONFIG_AIC79XX_DEBUG_MASK=0 +CONFIG_AIC79XX_REG_PRETTY_PRINT=y # CONFIG_SCSI_MEGARAID is not set CONFIG_SCSI_SATA=y # CONFIG_SCSI_SATA_SVW is not set CONFIG_SCSI_ATA_PIIX=y +# CONFIG_SCSI_SATA_NV is not set # CONFIG_SCSI_SATA_PROMISE is not set # CONFIG_SCSI_SATA_SX4 is not set # CONFIG_SCSI_SATA_SIL is not set @@ -290,7 +334,6 @@ CONFIG_SCSI_SATA_VIA=y # CONFIG_SCSI_SATA_VITESSE is not set # CONFIG_SCSI_BUSLOGIC is not set -# CONFIG_SCSI_CPQFCTS is not set # CONFIG_SCSI_DMX3191D is not set # CONFIG_SCSI_EATA is not set # CONFIG_SCSI_EATA_PIO is not set @@ -392,6 +435,7 @@ # QoS and/or fair queueing # # CONFIG_NET_SCHED is not set +# CONFIG_NET_CLS_ROUTE is not set # # Network testing @@ -431,8 +475,7 @@ # CONFIG_HP100 is not set CONFIG_NET_PCI=y # CONFIG_PCNET32 is not set -CONFIG_AMD8111_ETH=y -# CONFIG_AMD8111E_NAPI is not set +# CONFIG_AMD8111_ETH is not set # CONFIG_ADAPTEC_STARFIRE is not set # CONFIG_B44 is not set CONFIG_FORCEDETH=y @@ -442,16 +485,13 @@ # CONFIG_FEALNX is not set # CONFIG_NATSEMI is not set # CONFIG_NE2K_PCI is not set -CONFIG_8139CP=m -CONFIG_8139TOO=m -# CONFIG_8139TOO_PIO is not set -# CONFIG_8139TOO_TUNE_TWISTER is not set -# CONFIG_8139TOO_8129 is not set -# CONFIG_8139_OLD_RX_RESET is not set +# CONFIG_8139CP is not set +# CONFIG_8139TOO is not set # CONFIG_SIS900 is not set # CONFIG_EPIC100 is not set # CONFIG_SUNDANCE is not set # CONFIG_VIA_RHINE is not set +# CONFIG_VIA_VELOCITY is not set # # Ethernet (1000 Mbit) @@ -602,6 +642,9 @@ # CONFIG_DRM is not set # CONFIG_MWAVE is not set CONFIG_RAW_DRIVER=y +CONFIG_HPET=y +# CONFIG_HPET_RTC_IRQ is not set +CONFIG_HPET_MMAP=y CONFIG_MAX_RAW_DEVS=256 CONFIG_HANGCHECK_TIMER=y @@ -611,6 +654,11 @@ # CONFIG_I2C is not set # +# Dallas's 1-wire bus +# +# CONFIG_W1 is not set + +# # Misc devices # # CONFIG_IBM_ASM is not set @@ -703,17 +751,8 @@ # CONFIG_USB_BLUETOOTH_TTY is not set # CONFIG_USB_MIDI is not set # CONFIG_USB_ACM is not set -CONFIG_USB_PRINTER=y -CONFIG_USB_STORAGE=y -# CONFIG_USB_STORAGE_DEBUG is not set -# CONFIG_USB_STORAGE_DATAFAB is not set -# CONFIG_USB_STORAGE_FREECOM is not set -# CONFIG_USB_STORAGE_ISD200 is not set -# CONFIG_USB_STORAGE_DPCM is not set -# CONFIG_USB_STORAGE_HP8200e is not set -# CONFIG_USB_STORAGE_SDDR09 is not set -# CONFIG_USB_STORAGE_SDDR55 is not set -# CONFIG_USB_STORAGE_JUMPSHOT is not set +# CONFIG_USB_PRINTER is not set +# CONFIG_USB_STORAGE is not set # # USB Human Interface Devices (HID) @@ -830,7 +869,8 @@ # # DOS/FAT/NT Filesystems # -# CONFIG_FAT_FS is not set +# CONFIG_MSDOS_FS is not set +# CONFIG_VFAT_FS is not set # CONFIG_NTFS_FS is not set # @@ -856,6 +896,7 @@ # CONFIG_BEFS_FS is not set # CONFIG_BFS_FS is not set # CONFIG_EFS_FS is not set +# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set # CONFIG_CRAMFS is not set # CONFIG_VXFS_FS is not set # CONFIG_HPFS_FS is not set @@ -909,10 +950,11 @@ # CONFIG_DEBUG_SLAB is not set CONFIG_MAGIC_SYSRQ=y # CONFIG_DEBUG_SPINLOCK is not set -# CONFIG_INIT_DEBUG is not set +CONFIG_INIT_DEBUG=y # CONFIG_DEBUG_INFO is not set # CONFIG_FRAME_POINTER is not set -# CONFIG_IOMMU_DEBUG is not set +CONFIG_IOMMU_DEBUG=y +# CONFIG_IOMMU_LEAK is not set # # Security options @@ -927,5 +969,6 @@ # # Library routines # +# CONFIG_CRC_CCITT is not set CONFIG_CRC32=y # CONFIG_LIBCRC32C is not set diff -Nru a/arch/x86_64/ia32/ia32_binfmt.c b/arch/x86_64/ia32/ia32_binfmt.c --- a/arch/x86_64/ia32/ia32_binfmt.c 2004-08-25 22:01:54 -07:00 +++ b/arch/x86_64/ia32/ia32_binfmt.c 2004-08-25 22:01:54 -07:00 @@ -301,6 +301,9 @@ #define elf_addr_t __u32 +#undef TASK_SIZE +#define TASK_SIZE 0xffffffff + static void elf32_init(struct pt_regs *); #include "../../../fs/binfmt_elf.c" diff -Nru a/arch/x86_64/ia32/ia32_ioctl.c b/arch/x86_64/ia32/ia32_ioctl.c --- a/arch/x86_64/ia32/ia32_ioctl.c 2004-08-25 22:01:55 -07:00 +++ b/arch/x86_64/ia32/ia32_ioctl.c 2004-08-25 22:01:55 -07:00 @@ -171,23 +171,8 @@ COMPATIBLE_IOCTL(HDIO_SET_KEEPSETTINGS) COMPATIBLE_IOCTL(HDIO_SCAN_HWIF) COMPATIBLE_IOCTL(BLKRASET) -COMPATIBLE_IOCTL(BLKFRASET) COMPATIBLE_IOCTL(0x4B50) /* KDGHWCLK - not in the kernel, but don't complain */ COMPATIBLE_IOCTL(0x4B51) /* KDSHWCLK - not in the kernel, but don't complain */ -COMPATIBLE_IOCTL(RTC_AIE_ON) -COMPATIBLE_IOCTL(RTC_AIE_OFF) -COMPATIBLE_IOCTL(RTC_UIE_ON) -COMPATIBLE_IOCTL(RTC_UIE_OFF) -COMPATIBLE_IOCTL(RTC_PIE_ON) -COMPATIBLE_IOCTL(RTC_PIE_OFF) -COMPATIBLE_IOCTL(RTC_WIE_ON) -COMPATIBLE_IOCTL(RTC_WIE_OFF) -COMPATIBLE_IOCTL(RTC_ALM_SET) -COMPATIBLE_IOCTL(RTC_ALM_READ) -COMPATIBLE_IOCTL(RTC_RD_TIME) -COMPATIBLE_IOCTL(RTC_SET_TIME) -COMPATIBLE_IOCTL(RTC_WKALM_SET) -COMPATIBLE_IOCTL(RTC_WKALM_RD) COMPATIBLE_IOCTL(FIOQSIZE) /* And these ioctls need translation */ diff -Nru a/arch/x86_64/ia32/ia32_signal.c b/arch/x86_64/ia32/ia32_signal.c --- a/arch/x86_64/ia32/ia32_signal.c 2004-08-25 22:01:56 -07:00 +++ b/arch/x86_64/ia32/ia32_signal.c 2004-08-25 22:01:56 -07:00 @@ -115,7 +115,8 @@ } asmlinkage long -sys32_sigsuspend(int history0, int history1, old_sigset_t mask, struct pt_regs regs) +sys32_sigsuspend(int history0, int history1, old_sigset_t mask, + struct pt_regs *regs) { sigset_t saveset; @@ -126,11 +127,11 @@ recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); - regs.rax = -EINTR; + regs->rax = -EINTR; while (1) { current->state = TASK_INTERRUPTIBLE; schedule(); - if (do_signal(®s, &saveset)) + if (do_signal(regs, &saveset)) return -EINTR; } } @@ -138,7 +139,7 @@ asmlinkage long sys32_sigaltstack(const stack_ia32_t __user *uss_ptr, stack_ia32_t __user *uoss_ptr, - struct pt_regs regs) + struct pt_regs *regs) { stack_t uss,uoss; int ret; @@ -155,7 +156,7 @@ } seg = get_fs(); set_fs(KERNEL_DS); - ret = do_sigaltstack(uss_ptr ? &uss : NULL, &uoss, regs.rsp); + ret = do_sigaltstack(uss_ptr ? &uss : NULL, &uoss, regs->rsp); set_fs(seg); if (ret >= 0 && uoss_ptr) { if (!access_ok(VERIFY_WRITE,uoss_ptr,sizeof(stack_ia32_t)) || @@ -274,9 +275,9 @@ return 1; } -asmlinkage long sys32_sigreturn(struct pt_regs regs) +asmlinkage long sys32_sigreturn(struct pt_regs *regs) { - struct sigframe __user *frame = (struct sigframe __user *)(regs.rsp-8); + struct sigframe __user *frame = (struct sigframe __user *)(regs->rsp-8); sigset_t set; unsigned int eax; @@ -294,20 +295,23 @@ recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); - if (ia32_restore_sigcontext(®s, &frame->sc, &eax)) + if (ia32_restore_sigcontext(regs, &frame->sc, &eax)) goto badframe; return eax; badframe: - signal_fault(®s, frame, "32bit sigreturn"); + signal_fault(regs, frame, "32bit sigreturn"); return 0; } -asmlinkage long sys32_rt_sigreturn(struct pt_regs regs) +asmlinkage long sys32_rt_sigreturn(struct pt_regs *regs) { - struct rt_sigframe __user *frame = (struct rt_sigframe __user *)(regs.rsp - 4); + struct rt_sigframe __user *frame; sigset_t set; unsigned int eax; + struct pt_regs tregs; + + frame = (struct rt_sigframe __user *)(regs->rsp - 4); if (verify_area(VERIFY_READ, frame, sizeof(*frame))) goto badframe; @@ -320,16 +324,17 @@ recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); - if (ia32_restore_sigcontext(®s, &frame->uc.uc_mcontext, &eax)) + if (ia32_restore_sigcontext(regs, &frame->uc.uc_mcontext, &eax)) goto badframe; - if (sys32_sigaltstack(&frame->uc.uc_stack, NULL, regs) == -EFAULT) + tregs = *regs; + if (sys32_sigaltstack(&frame->uc.uc_stack, NULL, &tregs) == -EFAULT) goto badframe; return eax; badframe: - signal_fault(®s,frame,"32bit rt sigreturn"); + signal_fault(regs,frame,"32bit rt sigreturn"); return 0; } @@ -494,9 +499,7 @@ return; give_sigsegv: - if (sig == SIGSEGV) - ka->sa.sa_handler = SIG_DFL; - signal_fault(regs,frame,"32bit signal deliver"); + force_sigsegv(sig, current); } void ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, @@ -590,8 +593,6 @@ return; give_sigsegv: - if (sig == SIGSEGV) - ka->sa.sa_handler = SIG_DFL; - signal_fault(regs, frame, "32bit rt signal setup"); + force_sigsegv(sig, current); } diff -Nru a/arch/x86_64/ia32/ia32entry.S b/arch/x86_64/ia32/ia32entry.S --- a/arch/x86_64/ia32/ia32entry.S 2004-08-25 22:01:55 -07:00 +++ b/arch/x86_64/ia32/ia32entry.S 2004-08-25 22:01:55 -07:00 @@ -270,35 +270,32 @@ ret CFI_ENDPROC - .macro PTREGSCALL label, func + .macro PTREGSCALL label, func, arg .globl \label \label: leaq \func(%rip),%rax + leaq -ARGOFFSET+8(%rsp),\arg /* 8 for return address */ jmp ia32_ptregs_common .endm - PTREGSCALL stub32_rt_sigreturn, sys32_rt_sigreturn - PTREGSCALL stub32_sigreturn, sys32_sigreturn - PTREGSCALL stub32_sigaltstack, sys32_sigaltstack - PTREGSCALL stub32_sigsuspend, sys32_sigsuspend - PTREGSCALL stub32_execve, sys32_execve - PTREGSCALL stub32_fork, sys_fork - PTREGSCALL stub32_clone, sys32_clone - PTREGSCALL stub32_vfork, sys_vfork - PTREGSCALL stub32_iopl, sys_iopl - PTREGSCALL stub32_rt_sigsuspend, sys_rt_sigsuspend + PTREGSCALL stub32_rt_sigreturn, sys32_rt_sigreturn, %rdi + PTREGSCALL stub32_sigreturn, sys32_sigreturn, %rdi + PTREGSCALL stub32_sigaltstack, sys32_sigaltstack, %rdx + PTREGSCALL stub32_sigsuspend, sys32_sigsuspend, %rcx + PTREGSCALL stub32_execve, sys32_execve, %rcx + PTREGSCALL stub32_fork, sys_fork, %rdi + PTREGSCALL stub32_clone, sys32_clone, %rdx + PTREGSCALL stub32_vfork, sys_vfork, %rdi + PTREGSCALL stub32_iopl, sys_iopl, %rsi + PTREGSCALL stub32_rt_sigsuspend, sys_rt_sigsuspend, %rdx ENTRY(ia32_ptregs_common) CFI_STARTPROC popq %r11 SAVE_REST - movq %r11, %r15 call *%rax - movq %r15, %r11 RESTORE_REST - leaq ia32_sysret(%rip),%r11 - pushq %r11 - ret + jmp ia32_sysret /* misbalances the return cache */ CFI_ENDPROC .data @@ -332,7 +329,7 @@ .quad sys_getuid16 .quad sys_stime /* stime */ /* 25 */ .quad sys32_ptrace /* ptrace */ - .quad sys_alarm /* XXX sign extension??? */ + .quad sys_alarm .quad sys_fstat /* (old)fstat */ .quad sys_pause .quad compat_sys_utime /* 30 */ @@ -558,7 +555,7 @@ .quad sys_fadvise64 /* 250 */ .quad quiet_ni_syscall /* free_huge_pages */ .quad sys_exit_group - .quad sys_lookup_dcookie + .quad sys32_lookup_dcookie .quad sys_epoll_create .quad sys_epoll_ctl /* 255 */ .quad sys_epoll_wait diff -Nru a/arch/x86_64/ia32/ptrace32.c b/arch/x86_64/ia32/ptrace32.c --- a/arch/x86_64/ia32/ptrace32.c 2004-08-25 22:01:55 -07:00 +++ b/arch/x86_64/ia32/ptrace32.c 2004-08-25 22:01:55 -07:00 @@ -249,8 +249,8 @@ case PTRACE_GETFPREGS: case PTRACE_SETFPXREGS: case PTRACE_GETFPXREGS: + case PTRACE_GETEVENTMSG: break; - } child = find_target(request, pid, &ret); @@ -362,6 +362,10 @@ ret = 0; break; } + + case PTRACE_GETEVENTMSG: + ret = put_user(child->ptrace_message,(unsigned int __user *)(u64)data); + break; default: ret = -EINVAL; diff -Nru a/arch/x86_64/ia32/sys_ia32.c b/arch/x86_64/ia32/sys_ia32.c --- a/arch/x86_64/ia32/sys_ia32.c 2004-08-25 22:01:55 -07:00 +++ b/arch/x86_64/ia32/sys_ia32.c 2004-08-25 22:01:55 -07:00 @@ -1125,7 +1125,7 @@ } asmlinkage long sys32_execve(char __user *name, compat_uptr_t __user *argv, - compat_uptr_t __user *envp, struct pt_regs regs) + compat_uptr_t __user *envp, struct pt_regs *regs) { long error; char * filename; @@ -1134,21 +1134,21 @@ error = PTR_ERR(filename); if (IS_ERR(filename)) return error; - error = compat_do_execve(filename, argv, envp, ®s); + error = compat_do_execve(filename, argv, envp, regs); if (error == 0) current->ptrace &= ~PT_DTRACE; putname(filename); return error; } -asmlinkage long sys32_clone(unsigned int clone_flags, unsigned int newsp, struct pt_regs regs) +asmlinkage long sys32_clone(unsigned int clone_flags, unsigned int newsp, + struct pt_regs *regs) { - void __user *parent_tid = (void __user *)regs.rdx; - void __user *child_tid = (void __user *)regs.rdi; + void __user *parent_tid = (void __user *)regs->rdx; + void __user *child_tid = (void __user *)regs->rdi; if (!newsp) - newsp = regs.rsp; - return do_fork(clone_flags & ~CLONE_IDLETASK, newsp, ®s, 0, - parent_tid, child_tid); + newsp = regs->rsp; + return do_fork(clone_flags, newsp, regs, 0, parent_tid, child_tid); } /* @@ -1336,6 +1336,12 @@ } return -ENOSYS; } + +long sys32_lookup_dcookie(u32 addr_low, u32 addr_high, + char __user * buf, size_t len) +{ + return sys_lookup_dcookie(((u64)addr_high << 32) | addr_low, buf, len); +} cond_syscall(sys32_ipc) diff -Nru a/arch/x86_64/kernel/Makefile b/arch/x86_64/kernel/Makefile --- a/arch/x86_64/kernel/Makefile 2004-08-25 22:01:56 -07:00 +++ b/arch/x86_64/kernel/Makefile 2004-08-25 22:01:56 -07:00 @@ -25,7 +25,6 @@ obj-$(CONFIG_GART_IOMMU) += pci-gart.o aperture.o obj-$(CONFIG_DUMMY_IOMMU) += pci-nommu.o pci-dma.o obj-$(CONFIG_SWIOTLB) += swiotlb.o -obj-$(CONFIG_SCHED_SMT) += domain.o obj-$(CONFIG_MODULES) += module.o diff -Nru a/arch/x86_64/kernel/Makefile-HEAD b/arch/x86_64/kernel/Makefile-HEAD --- a/arch/x86_64/kernel/Makefile-HEAD 2004-08-25 22:01:56 -07:00 +++ /dev/null Wed Dec 31 16:00:00 196900 @@ -1,38 +0,0 @@ -# -# Makefile for the linux kernel. -# - -extra-y := head.o head64.o init_task.o vmlinux.lds -EXTRA_AFLAGS := -traditional -obj-y := process.o semaphore.o signal.o entry.o traps.o irq.o \ - ptrace.o i8259.o ioport.o ldt.o setup.o time.o sys_x86_64.o \ - x8664_ksyms.o i387.o syscall.o vsyscall.o \ - setup64.o bootflag.o e820.o reboot.o warmreboot.o -obj-y += mce.o - -obj-$(CONFIG_MTRR) += ../../i386/kernel/cpu/mtrr/ -obj-$(CONFIG_ACPI_BOOT) += acpi/ -obj-$(CONFIG_X86_MSR) += msr.o -obj-$(CONFIG_MICROCODE) += microcode.o -obj-$(CONFIG_X86_CPUID) += cpuid.o -obj-$(CONFIG_SMP) += smp.o smpboot.o trampoline.o -obj-$(CONFIG_X86_LOCAL_APIC) += apic.o nmi.o -obj-$(CONFIG_X86_IO_APIC) += io_apic.o mpparse.o -obj-$(CONFIG_PM) += suspend.o -obj-$(CONFIG_SOFTWARE_SUSPEND) += suspend_asm.o -obj-$(CONFIG_CPU_FREQ) += cpufreq/ -obj-$(CONFIG_EARLY_PRINTK) += early_printk.o -obj-$(CONFIG_GART_IOMMU) += pci-gart.o aperture.o -obj-$(CONFIG_DUMMY_IOMMU) += pci-nommu.o pci-dma.o -obj-$(CONFIG_SWIOTLB) += swiotlb.o -obj-$(CONFIG_SCHED_SMT) += domain.o - -obj-$(CONFIG_MODULES) += module.o - -obj-y += topology.o - -bootflag-y += ../../i386/kernel/bootflag.o -cpuid-$(subst m,y,$(CONFIG_X86_CPUID)) += ../../i386/kernel/cpuid.o -topology-y += ../../i386/mach-default/topology.o -swiotlb-$(CONFIG_SWIOTLB) += ../../ia64/lib/swiotlb.o -microcode-$(subst m,y,$(CONFIG_MICROCODE)) += ../../i386/kernel/microcode.o diff -Nru a/arch/x86_64/kernel/aperture.c b/arch/x86_64/kernel/aperture.c --- a/arch/x86_64/kernel/aperture.c 2004-08-25 22:01:56 -07:00 +++ b/arch/x86_64/kernel/aperture.c 2004-08-25 22:01:56 -07:00 @@ -31,6 +31,8 @@ int fallback_aper_order __initdata = 1; /* 64MB */ int fallback_aper_force __initdata = 0; +int fix_aperture __initdata = 1; + /* This code runs before the PCI subsystem is initialized, so just access the northbridge directly. */ @@ -202,7 +204,7 @@ u64 aper_base; int valid_agp = 0; - if (iommu_aperture_disabled) + if (iommu_aperture_disabled || !fix_aperture) return; printk("Checking aperture...\n"); @@ -241,20 +243,15 @@ /* Got the aperture from the AGP bridge */ } else if ((!no_iommu && end_pfn >= 0xffffffff>>PAGE_SHIFT) || force_iommu || - valid_agp || + valid_agp || fallback_aper_force) { - /* When there is a AGP bridge in the system assume the - user wants to use the AGP driver too and needs an - aperture. However this case (AGP but no good - aperture) should only happen with a more broken than - usual BIOS, because it would even break Windows. */ - - printk("Your BIOS doesn't leave a aperture memory hole\n"); - printk("Please enable the IOMMU option in the BIOS setup\n"); - printk("This costs you %d MB of RAM\n", 32 << fallback_aper_order); - + printk("Your BIOS doesn't leave a aperture memory hole\n"); + printk("Please enable the IOMMU option in the BIOS setup\n"); + printk("This costs you %d MB of RAM\n", + 32 << fallback_aper_order); + aper_order = fallback_aper_order; - aper_alloc = allocate_aperture(); + aper_alloc = allocate_aperture(); if (!aper_alloc) { /* Could disable AGP and IOMMU here, but it's probably not worth it. But the later users cannot deal with diff -Nru a/arch/x86_64/kernel/cpufreq/Kconfig b/arch/x86_64/kernel/cpufreq/Kconfig --- a/arch/x86_64/kernel/cpufreq/Kconfig 2004-08-25 22:01:56 -07:00 +++ b/arch/x86_64/kernel/cpufreq/Kconfig 2004-08-25 22:01:56 -07:00 @@ -46,4 +46,53 @@ depends on ((X86_POWERNOW_K8 = "m" && ACPI_PROCESSOR) || (X86_POWERNOW_K8 = "y" && ACPI_PROCESSOR = "y")) default y +config X86_SPEEDSTEP_CENTRINO + tristate "Intel Enhanced SpeedStep" + depends on CPU_FREQ_TABLE + help + This adds the CPUFreq driver for Enhanced SpeedStep enabled + mobile CPUs. This means Intel Pentium M (Centrino) CPUs + or 64bit enabled Intel Xeons. + + For details, take a look at . + + If in doubt, say N. + +config X86_SPEEDSTEP_CENTRINO_TABLE + bool + depends on X86_SPEEDSTEP_CENTRINO + default y + +config X86_SPEEDSTEP_CENTRINO_ACPI + bool "Use ACPI tables to decode valid frequency/voltage pairs (EXPERIMENTAL)" + depends on EXPERIMENTAL + depends on ((X86_SPEEDSTEP_CENTRINO = "m" && ACPI_PROCESSOR) || (X86_SPEEDSTEP_CENTRINO = "y" && ACPI_PROCESSOR = "y")) + help + Use primarily the information provided in the BIOS ACPI tables + to determine valid CPU frequency and voltage pairings. + + If in doubt, say Y. + +config X86_ACPI_CPUFREQ + tristate "ACPI Processor P-States driver" + depends on CPU_FREQ_TABLE && ACPI_PROCESSOR + help + This driver adds a CPUFreq driver which utilizes the ACPI + Processor Performance States. + + For details, take a look at . + + If in doubt, say N. + +config X86_ACPI_CPUFREQ_PROC_INTF + bool "/proc/acpi/processor/../performance interface (deprecated)" + depends on X86_ACPI_CPUFREQ && PROC_FS + help + This enables the deprecated /proc/acpi/processor/../performance + interface. While it is helpful for debugging, the generic, + cross-architecture cpufreq interfaces should be used. + + If in doubt, say N. + endmenu + diff -Nru a/arch/x86_64/kernel/cpufreq/Makefile b/arch/x86_64/kernel/cpufreq/Makefile --- a/arch/x86_64/kernel/cpufreq/Makefile 2004-08-25 22:01:55 -07:00 +++ b/arch/x86_64/kernel/cpufreq/Makefile 2004-08-25 22:01:55 -07:00 @@ -2,6 +2,12 @@ # Reuse the i386 cpufreq drivers # +SRCDIR := ../../../i386/kernel/cpu/cpufreq + obj-$(CONFIG_X86_POWERNOW_K8) += powernow-k8.o +obj-$(CONFIG_X86_SPEEDSTEP_CENTRINO) += speedstep-centrino.o +obj-$(CONFIG_X86_ACPI_CPUFREQ) += acpi.o -powernow-k8-objs := ../../../i386/kernel/cpu/cpufreq/powernow-k8.o +powernow-k8-objs := ${SRCDIR}/powernow-k8.o +speedstep-centrino-objs := ${SRCDIR}/speedstep-centrino.o +acpi-objs := ${SRCDIR}/acpi.o diff -Nru a/arch/x86_64/kernel/domain.c b/arch/x86_64/kernel/domain.c --- a/arch/x86_64/kernel/domain.c 2004-08-25 22:01:55 -07:00 +++ /dev/null Wed Dec 31 16:00:00 196900 @@ -1,93 +0,0 @@ -#include -#include - -/* Don't do any NUMA setup on Opteron right now. They seem to be - better off with flat scheduling. This is just for SMT. */ - -#ifdef CONFIG_SCHED_SMT - -static struct sched_group sched_group_cpus[NR_CPUS]; -static struct sched_group sched_group_phys[NR_CPUS]; -static DEFINE_PER_CPU(struct sched_domain, cpu_domains); -static DEFINE_PER_CPU(struct sched_domain, phys_domains); -__init void arch_init_sched_domains(void) -{ - int i; - struct sched_group *first = NULL, *last = NULL; - - /* Set up domains */ - for_each_cpu(i) { - struct sched_domain *cpu_domain = &per_cpu(cpu_domains, i); - struct sched_domain *phys_domain = &per_cpu(phys_domains, i); - - *cpu_domain = SD_SIBLING_INIT; - /* Disable SMT NICE for CMP */ - /* RED-PEN use a generic flag */ - if (cpu_data[i].x86_vendor == X86_VENDOR_AMD) - cpu_domain->flags &= ~SD_SHARE_CPUPOWER; - cpu_domain->span = cpu_sibling_map[i]; - cpu_domain->parent = phys_domain; - cpu_domain->groups = &sched_group_cpus[i]; - - *phys_domain = SD_CPU_INIT; - phys_domain->span = cpu_possible_map; - phys_domain->groups = &sched_group_phys[first_cpu(cpu_domain->span)]; - } - - /* Set up CPU (sibling) groups */ - for_each_cpu(i) { - struct sched_domain *cpu_domain = &per_cpu(cpu_domains, i); - int j; - first = last = NULL; - - if (i != first_cpu(cpu_domain->span)) - continue; - - for_each_cpu_mask(j, cpu_domain->span) { - struct sched_group *cpu = &sched_group_cpus[j]; - - cpus_clear(cpu->cpumask); - cpu_set(j, cpu->cpumask); - cpu->cpu_power = SCHED_LOAD_SCALE; - - if (!first) - first = cpu; - if (last) - last->next = cpu; - last = cpu; - } - last->next = first; - } - - first = last = NULL; - /* Set up physical groups */ - for_each_cpu(i) { - struct sched_domain *cpu_domain = &per_cpu(cpu_domains, i); - struct sched_group *cpu = &sched_group_phys[i]; - - if (i != first_cpu(cpu_domain->span)) - continue; - - cpu->cpumask = cpu_domain->span; - /* - * Make each extra sibling increase power by 10% of - * the basic CPU. This is very arbitrary. - */ - cpu->cpu_power = SCHED_LOAD_SCALE + SCHED_LOAD_SCALE*(cpus_weight(cpu->cpumask)-1) / 10; - - if (!first) - first = cpu; - if (last) - last->next = cpu; - last = cpu; - } - last->next = first; - - mb(); - for_each_cpu(i) { - struct sched_domain *cpu_domain = &per_cpu(cpu_domains, i); - cpu_attach_domain(cpu_domain, i); - } -} - -#endif diff -Nru a/arch/x86_64/kernel/early_printk.c b/arch/x86_64/kernel/early_printk.c --- a/arch/x86_64/kernel/early_printk.c 2004-08-25 22:01:55 -07:00 +++ b/arch/x86_64/kernel/early_printk.c 2004-08-25 22:01:55 -07:00 @@ -99,18 +99,17 @@ #define DEFAULT_BAUD 9600 -static __init void early_serial_init(char *opt) +static __init void early_serial_init(char *s) { unsigned char c; unsigned divisor; unsigned baud = DEFAULT_BAUD; - char *s, *e; + char *e; - if (*opt == ',') - ++opt; + if (*s == ',') + ++s; - s = strsep(&opt, ","); - if (s != NULL) { + if (*s) { unsigned port; if (!strncmp(s,"0x",2)) { early_serial_base = simple_strtoul(s, &e, 16); @@ -124,6 +123,9 @@ port = 0; early_serial_base = bases[port]; } + s += strcspn(s, ","); + if (*s == ',') + s++; } outb(0x3, early_serial_base + LCR); /* 8n1 */ @@ -131,8 +133,7 @@ outb(0, early_serial_base + FCR); /* no fifo */ outb(0x3, early_serial_base + MCR); /* DTR + RTS */ - s = strsep(&opt, ","); - if (s != NULL) { + if (*s) { baud = simple_strtoul(s, &e, 0); if (baud == 0 || s == e) baud = DEFAULT_BAUD; diff -Nru a/arch/x86_64/kernel/entry.S b/arch/x86_64/kernel/entry.S --- a/arch/x86_64/kernel/entry.S 2004-08-25 22:01:55 -07:00 +++ b/arch/x86_64/kernel/entry.S 2004-08-25 22:01:55 -07:00 @@ -324,19 +324,20 @@ * Certain special system calls that need to save a complete full stack frame. */ - .macro PTREGSCALL label,func + .macro PTREGSCALL label,func,arg .globl \label \label: leaq \func(%rip),%rax + leaq -ARGOFFSET+8(%rsp),\arg /* 8 for return address */ jmp ptregscall_common .endm - PTREGSCALL stub_clone, sys_clone - PTREGSCALL stub_fork, sys_fork - PTREGSCALL stub_vfork, sys_vfork - PTREGSCALL stub_rt_sigsuspend, sys_rt_sigsuspend - PTREGSCALL stub_sigaltstack, sys_sigaltstack - PTREGSCALL stub_iopl, sys_iopl + PTREGSCALL stub_clone, sys_clone, %r8 + PTREGSCALL stub_fork, sys_fork, %rdi + PTREGSCALL stub_vfork, sys_vfork, %rdi + PTREGSCALL stub_rt_sigsuspend, sys_rt_sigsuspend, %rdx + PTREGSCALL stub_sigaltstack, sys_sigaltstack, %rdx + PTREGSCALL stub_iopl, sys_iopl, %rsi ENTRY(ptregscall_common) CFI_STARTPROC @@ -386,6 +387,7 @@ CFI_STARTPROC addq $8, %rsp SAVE_REST + movq %rsp,%rdi FIXUP_TOP_OF_STACK %r11 call sys_rt_sigreturn movq %rax,RAX(%rsp) # fixme, this could be done at the higher layer diff -Nru a/arch/x86_64/kernel/ioport.c b/arch/x86_64/kernel/ioport.c --- a/arch/x86_64/kernel/ioport.c 2004-08-25 22:01:54 -07:00 +++ b/arch/x86_64/kernel/ioport.c 2004-08-25 22:01:54 -07:00 @@ -83,9 +83,9 @@ * code. */ -asmlinkage long sys_iopl(unsigned int level, struct pt_regs regs) +asmlinkage long sys_iopl(unsigned int level, struct pt_regs *regs) { - unsigned int old = (regs.eflags >> 12) & 3; + unsigned int old = (regs->eflags >> 12) & 3; if (level > 3) return -EINVAL; @@ -94,6 +94,6 @@ if (!capable(CAP_SYS_RAWIO)) return -EPERM; } - regs.eflags = (regs.eflags &~ 0x3000UL) | (level << 12); + regs->eflags = (regs->eflags &~ 0x3000UL) | (level << 12); return 0; } diff -Nru a/arch/x86_64/kernel/mce.c b/arch/x86_64/kernel/mce.c --- a/arch/x86_64/kernel/mce.c 2004-08-25 22:01:55 -07:00 +++ b/arch/x86_64/kernel/mce.c 2004-08-25 22:01:55 -07:00 @@ -24,7 +24,8 @@ #define MISC_MCELOG_MINOR 227 #define NR_BANKS 5 -static int mce_disabled __initdata; +static int mce_dont_init; + /* 0: always panic, 1: panic if deadlock possible, 2: try to avoid panic, 3: never panic or exit (for testing only) */ static int tolerant = 1; @@ -113,9 +114,8 @@ static int mce_available(struct cpuinfo_x86 *c) { - return !mce_disabled && - test_bit(X86_FEATURE_MCE, &c->x86_capability) && - test_bit(X86_FEATURE_MCA, &c->x86_capability); + return test_bit(X86_FEATURE_MCE, &c->x86_capability) && + test_bit(X86_FEATURE_MCA, &c->x86_capability); } /* @@ -127,8 +127,9 @@ struct mce m, panicm; int nowayout = (tolerant < 1); int kill_it = 0; - u64 mcestart; + u64 mcestart = 0; int i; + int panicm_found = 0; if (regs) notify_die(DIE_NMI, "machine check", regs, error_code, 255, SIGKILL); @@ -138,17 +139,11 @@ memset(&m, 0, sizeof(struct mce)); m.cpu = hard_smp_processor_id(); rdmsrl(MSR_IA32_MCG_STATUS, m.mcgstatus); - if (!regs && (m.mcgstatus & MCG_STATUS_MCIP)) - return; if (!(m.mcgstatus & MCG_STATUS_RIPV)) kill_it = 1; - if (regs) { - m.rip = regs->rip; - m.cs = regs->cs; - } rdtscll(mcestart); - mb(); + barrier(); for (i = 0; i < banks; i++) { if (!bank[i]) @@ -156,52 +151,62 @@ m.misc = 0; m.addr = 0; + m.bank = i; + m.tsc = 0; rdmsrl(MSR_IA32_MC0_STATUS + i*4, m.status); if ((m.status & MCI_STATUS_VAL) == 0) continue; - /* Should be implied by the banks check above, but - check it anyways */ - if ((m.status & MCI_STATUS_EN) == 0) - continue; - /* Did this bank cause the exception? */ - /* Assume that the bank with uncorrectable errors did it, - and that there is only a single one. */ - if (m.status & MCI_STATUS_UC) { - panicm = m; - } else { - m.rip = 0; - m.cs = 0; + if (m.status & MCI_STATUS_EN) { + /* In theory _OVER could be a nowayout too, but + assume any overflowed errors were no fatal. */ + nowayout |= !!(m.status & MCI_STATUS_PCC); + kill_it |= !!(m.status & MCI_STATUS_UC); } - /* In theory _OVER could be a nowayout too, but - assume any overflowed errors were no fatal. */ - nowayout |= !!(m.status & MCI_STATUS_PCC); - kill_it |= !!(m.status & MCI_STATUS_UC); - m.bank = i; - if (m.status & MCI_STATUS_MISCV) rdmsrl(MSR_IA32_MC0_MISC + i*4, m.misc); if (m.status & MCI_STATUS_ADDRV) rdmsrl(MSR_IA32_MC0_ADDR + i*4, m.addr); - rdtscll(m.tsc); + if (regs && (m.mcgstatus & MCG_STATUS_RIPV)) { + m.rip = regs->rip; + m.cs = regs->cs; + } else { + m.rip = 0; + m.cs = 0; + } + + if (error_code != -1) + rdtscll(m.tsc); wrmsrl(MSR_IA32_MC0_STATUS + i*4, 0); mce_log(&m); + + /* Did this bank cause the exception? */ + /* Assume that the bank with uncorrectable errors did it, + and that there is only a single one. */ + if ((m.status & MCI_STATUS_UC) && (m.status & MCI_STATUS_EN)) { + panicm = m; + panicm_found = 1; + } } - wrmsrl(MSR_IA32_MCG_STATUS, 0); /* Never do anything final in the polling timer */ if (!regs) - return; + goto out; + + /* If we didn't find an uncorrectable error, pick + the last one (shouldn't happen, just being safe). */ + if (!panicm_found) + panicm = m; if (nowayout) - mce_panic("Machine check", &m, mcestart); + mce_panic("Machine check", &panicm, mcestart); if (kill_it) { int user_space = 0; if (m.mcgstatus & MCG_STATUS_RIPV) - user_space = m.rip && (m.cs & 3); + user_space = panicm.rip && (panicm.cs & 3); /* When the machine was in user space and the CPU didn't get confused it's normally not necessary to panic, unless you @@ -214,18 +219,15 @@ (unsigned)current->pid <= 1) mce_panic("Uncorrected machine check", &panicm, mcestart); - /* do_exit takes an awful lot of locks and has as slight risk - of deadlocking. If you don't want that don't set tolerant >= 2 */ + /* do_exit takes an awful lot of locks and has as + slight risk of deadlocking. If you don't want that + don't set tolerant >= 2 */ if (tolerant < 3) do_exit(SIGBUS); } -} -static void mce_clear_all(void) -{ - int i; - for (i = 0; i < banks; i++) - wrmsrl(MSR_IA32_MC0_STATUS + i*4, 0); + out: + /* Last thing done in the machine check exception to clear state. */ wrmsrl(MSR_IA32_MCG_STATUS, 0); } @@ -268,22 +270,25 @@ int i; rdmsrl(MSR_IA32_MCG_CAP, cap); - if (cap & MCG_CTL_P) - wrmsr(MSR_IA32_MCG_CTL, 0xffffffff, 0xffffffff); - banks = cap & 0xff; if (banks > NR_BANKS) { printk(KERN_INFO "MCE: warning: using only %d banks\n", banks); banks = NR_BANKS; } - mce_clear_all(); + /* Log the machine checks left over from the previous reset. + This also clears all registers */ + do_machine_check(NULL, -1); + + set_in_cr4(X86_CR4_MCE); + + if (cap & MCG_CTL_P) + wrmsr(MSR_IA32_MCG_CTL, 0xffffffff, 0xffffffff); + for (i = 0; i < banks; i++) { wrmsrl(MSR_IA32_MC0_CTL+4*i, bank[i]); wrmsrl(MSR_IA32_MC0_STATUS+4*i, 0); } - - set_in_cr4(X86_CR4_MCE); } /* Add per CPU specific workarounds here */ @@ -307,7 +312,9 @@ mce_cpu_quirks(c); - if (test_and_set_bit(smp_processor_id(), &mce_cpus) || !mce_available(c)) + if (mce_dont_init || + test_and_set_bit(smp_processor_id(), &mce_cpus) || + !mce_available(c)) return; mce_init(NULL); @@ -410,15 +417,16 @@ static int __init mcheck_disable(char *str) { - mce_disabled = 1; + mce_dont_init = 1; return 0; } -/* mce=off disable machine check */ +/* mce=off disables machine check. Note you can reenable it later + using sysfs */ static int __init mcheck_enable(char *str) { if (!strcmp(str, "off")) - mce_disabled = 1; + mce_dont_init = 1; else printk("mce= argument %s ignored. Please use /sys", str); return 0; @@ -434,7 +442,6 @@ /* On resume clear all MCE state. Don't want to see leftovers from the BIOS. */ static int mce_resume(struct sys_device *dev) { - mce_clear_all(); on_each_cpu(mce_init, NULL, 1, 1); return 0; } @@ -492,7 +499,7 @@ if (!err) err = sysdev_register(&device_mce); if (!err) { - /* could create per CPU objects, but is not worth it. */ + /* could create per CPU objects, but it is not worth it. */ sysdev_create_file(&device_mce, &attr_bank0ctl); sysdev_create_file(&device_mce, &attr_bank1ctl); sysdev_create_file(&device_mce, &attr_bank2ctl); diff -Nru a/arch/x86_64/kernel/msr.c b/arch/x86_64/kernel/msr.c --- a/arch/x86_64/kernel/msr.c 2004-08-25 22:01:54 -07:00 +++ b/arch/x86_64/kernel/msr.c 2004-08-25 22:01:54 -07:00 @@ -46,234 +46,229 @@ static inline int wrmsr_eio(u32 reg, u32 eax, u32 edx) { - int err; + int err; - asm volatile( - "1: wrmsr\n" - "2:\n" - ".section .fixup,\"ax\"\n" - "3: movl %4,%0\n" - " jmp 2b\n" - ".previous\n" - ".section __ex_table,\"a\"\n" - " .align 8\n" - " .quad 1b,3b\n" - ".previous" - : "=&bDS" (err) - : "a" (eax), "d" (edx), "c" (reg), "i" (-EIO), "0" (0)); + asm volatile ("1: wrmsr\n" + "2:\n" + ".section .fixup,\"ax\"\n" + "3: movl %4,%0\n" + " jmp 2b\n" + ".previous\n" + ".section __ex_table,\"a\"\n" + " .align 8\n" " .quad 1b,3b\n" ".previous":"=&bDS" (err) + :"a"(eax), "d"(edx), "c"(reg), "i"(-EIO), "0"(0)); - return err; + return err; } static inline int rdmsr_eio(u32 reg, u32 *eax, u32 *edx) { - int err; + int err; - asm volatile( - "1: rdmsr\n" - "2:\n" - ".section .fixup,\"ax\"\n" - "3: movl %4,%0\n" - " jmp 2b\n" - ".previous\n" - ".section __ex_table,\"a\"\n" - " .align 8\n" - " .quad 1b,3b\n" - ".previous" - : "=&bDS" (err), "=a" (*eax), "=d" (*edx) - : "c" (reg), "i" (-EIO), "0" (0)); + asm volatile ("1: rdmsr\n" + "2:\n" + ".section .fixup,\"ax\"\n" + "3: movl %4,%0\n" + " jmp 2b\n" + ".previous\n" + ".section __ex_table,\"a\"\n" + " .align 8\n" + " .quad 1b,3b\n" + ".previous":"=&bDS" (err), "=a"(*eax), "=d"(*edx) + :"c"(reg), "i"(-EIO), "0"(0)); - return err; + return err; } #ifdef CONFIG_SMP struct msr_command { - int cpu; - int err; - u32 reg; - u32 data[2]; + int cpu; + int err; + u32 reg; + u32 data[2]; }; static void msr_smp_wrmsr(void *cmd_block) { - struct msr_command *cmd = (struct msr_command *) cmd_block; - - if ( cmd->cpu == smp_processor_id() ) - cmd->err = wrmsr_eio(cmd->reg, cmd->data[0], cmd->data[1]); + struct msr_command *cmd = (struct msr_command *)cmd_block; + + if (cmd->cpu == smp_processor_id()) + cmd->err = wrmsr_eio(cmd->reg, cmd->data[0], cmd->data[1]); } static void msr_smp_rdmsr(void *cmd_block) { - struct msr_command *cmd = (struct msr_command *) cmd_block; - - if ( cmd->cpu == smp_processor_id() ) - cmd->err = rdmsr_eio(cmd->reg, &cmd->data[0], &cmd->data[1]); + struct msr_command *cmd = (struct msr_command *)cmd_block; + + if (cmd->cpu == smp_processor_id()) + cmd->err = rdmsr_eio(cmd->reg, &cmd->data[0], &cmd->data[1]); } static inline int do_wrmsr(int cpu, u32 reg, u32 eax, u32 edx) { - struct msr_command cmd; - int ret; + struct msr_command cmd; + int ret; + + preempt_disable(); + if (cpu == smp_processor_id()) { + ret = wrmsr_eio(reg, eax, edx); + } else { + cmd.cpu = cpu; + cmd.reg = reg; + cmd.data[0] = eax; + cmd.data[1] = edx; - preempt_disable(); - if ( cpu == smp_processor_id() ) { - ret = wrmsr_eio(reg, eax, edx); - } else { - cmd.cpu = cpu; - cmd.reg = reg; - cmd.data[0] = eax; - cmd.data[1] = edx; - - smp_call_function(msr_smp_wrmsr, &cmd, 1, 1); - ret = cmd.err; - } - preempt_enable(); - return ret; + smp_call_function(msr_smp_wrmsr, &cmd, 1, 1); + ret = cmd.err; + } + preempt_enable(); + return ret; } -static inline int do_rdmsr(int cpu, u32 reg, u32 *eax, u32 *edx) +static inline int do_rdmsr(int cpu, u32 reg, u32 * eax, u32 * edx) { - struct msr_command cmd; - int ret; + struct msr_command cmd; + int ret; + + preempt_disable(); + if (cpu == smp_processor_id()) { + ret = rdmsr_eio(reg, eax, edx); + } else { + cmd.cpu = cpu; + cmd.reg = reg; + + smp_call_function(msr_smp_rdmsr, &cmd, 1, 1); - preempt_disable(); - if ( cpu == smp_processor_id() ) { - ret = rdmsr_eio(reg, eax, edx); - } else { - cmd.cpu = cpu; - cmd.reg = reg; - - smp_call_function(msr_smp_rdmsr, &cmd, 1, 1); - - *eax = cmd.data[0]; - *edx = cmd.data[1]; - - ret = cmd.err; - } - preempt_enable(); - return ret; + *eax = cmd.data[0]; + *edx = cmd.data[1]; + + ret = cmd.err; + } + preempt_enable(); + return ret; } -#else /* ! CONFIG_SMP */ +#else /* ! CONFIG_SMP */ static inline int do_wrmsr(int cpu, u32 reg, u32 eax, u32 edx) { - return wrmsr_eio(reg, eax, edx); + return wrmsr_eio(reg, eax, edx); } static inline int do_rdmsr(int cpu, u32 reg, u32 *eax, u32 *edx) { - return rdmsr_eio(reg, eax, edx); + return rdmsr_eio(reg, eax, edx); } -#endif /* ! CONFIG_SMP */ +#endif /* ! CONFIG_SMP */ static loff_t msr_seek(struct file *file, loff_t offset, int orig) { - loff_t ret = -EINVAL; - lock_kernel(); - switch (orig) { - case 0: - file->f_pos = offset; - ret = file->f_pos; - break; - case 1: - file->f_pos += offset; - ret = file->f_pos; - } - unlock_kernel(); - return ret; -} - -static ssize_t msr_read(struct file * file, char __user * buf, - size_t count, loff_t *ppos) -{ - char __user *tmp = buf; - u32 data[2]; - size_t rv; - u32 reg = *ppos; - int cpu = iminor(file->f_dentry->d_inode); - int err; - - if ( count % 8 ) - return -EINVAL; /* Invalid chunk size */ - - for ( rv = 0 ; count ; count -= 8 ) { - err = do_rdmsr(cpu, reg, &data[0], &data[1]); - if ( err ) - return err; - if ( copy_to_user(tmp,&data,8) ) - return -EFAULT; - tmp += 8; - } + loff_t ret = -EINVAL; + + lock_kernel(); + switch (orig) { + case 0: + file->f_pos = offset; + ret = file->f_pos; + break; + case 1: + file->f_pos += offset; + ret = file->f_pos; + } + unlock_kernel(); + return ret; +} + +static ssize_t msr_read(struct file *file, char __user * buf, + size_t count, loff_t * ppos) +{ + u32 __user *tmp = (u32 __user *) buf; + u32 data[2]; + size_t rv; + u32 reg = *ppos; + int cpu = iminor(file->f_dentry->d_inode); + int err; + + if (count % 8) + return -EINVAL; /* Invalid chunk size */ + + for (rv = 0; count; count -= 8) { + err = do_rdmsr(cpu, reg, &data[0], &data[1]); + if (err) + return err; + if (copy_to_user(tmp, &data, 8)) + return -EFAULT; + tmp += 2; + } - return tmp - buf; + return ((char __user *)tmp) - buf; } -static ssize_t msr_write(struct file * file, const char __user * buf, +static ssize_t msr_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { - const char __user *tmp = buf; - u32 data[2]; - size_t rv; - u32 reg = *ppos; - int cpu = iminor(file->f_dentry->d_inode); - int err; - - if ( count % 8 ) - return -EINVAL; /* Invalid chunk size */ - - for ( rv = 0 ; count ; count -= 8 ) { - if ( copy_from_user(&data,tmp,8) ) - return -EFAULT; - err = do_wrmsr(cpu, reg, data[0], data[1]); - if ( err ) - return err; - tmp += 8; - } + const u32 __user *tmp = (const u32 __user *)buf; + u32 data[2]; + size_t rv; + u32 reg = *ppos; + int cpu = iminor(file->f_dentry->d_inode); + int err; + + if (count % 8) + return -EINVAL; /* Invalid chunk size */ + + for (rv = 0; count; count -= 8) { + if (copy_from_user(&data, tmp, 8)) + return -EFAULT; + err = do_wrmsr(cpu, reg, data[0], data[1]); + if (err) + return err; + tmp += 2; + } - return tmp - buf; + return ((char __user *)tmp) - buf; } static int msr_open(struct inode *inode, struct file *file) { - int cpu = iminor(file->f_dentry->d_inode); - struct cpuinfo_x86 *c = &(cpu_data)[cpu]; - - if (cpu >= NR_CPUS || !cpu_online(cpu)) - return -ENXIO; /* No such CPU */ - if ( !cpu_has(c, X86_FEATURE_MSR) ) - return -EIO; /* MSR not supported */ - - return 0; + unsigned int cpu = iminor(file->f_dentry->d_inode); + struct cpuinfo_x86 *c = &(cpu_data)[cpu]; + + if (cpu >= NR_CPUS || !cpu_online(cpu)) + return -ENXIO; /* No such CPU */ + if (!cpu_has(c, X86_FEATURE_MSR)) + return -EIO; /* MSR not supported */ + + return 0; } /* * File operations we support */ static struct file_operations msr_fops = { - .owner = THIS_MODULE, - .llseek = msr_seek, - .read = msr_read, - .write = msr_write, - .open = msr_open, + .owner = THIS_MODULE, + .llseek = msr_seek, + .read = msr_read, + .write = msr_write, + .open = msr_open, }; int __init msr_init(void) { - if (register_chrdev(MSR_MAJOR, "cpu/msr", &msr_fops)) { - printk(KERN_ERR "msr: unable to get major %d for msr\n", - MSR_MAJOR); - return -EBUSY; - } - - return 0; + if (register_chrdev(MSR_MAJOR, "cpu/msr", &msr_fops)) { + printk(KERN_ERR "msr: unable to get major %d for msr\n", + MSR_MAJOR); + return -EBUSY; + } + + return 0; } void __exit msr_exit(void) { - unregister_chrdev(MSR_MAJOR, "cpu/msr"); + unregister_chrdev(MSR_MAJOR, "cpu/msr"); } module_init(msr_init); diff -Nru a/arch/x86_64/kernel/pci-dma.c b/arch/x86_64/kernel/pci-dma.c --- a/arch/x86_64/kernel/pci-dma.c 2004-08-25 22:01:56 -07:00 +++ b/arch/x86_64/kernel/pci-dma.c 2004-08-25 22:01:56 -07:00 @@ -1,5 +1,5 @@ /* - * Dynamic DMA mapping support. Common code + * Dynamic DMA mapping support. */ #include @@ -24,38 +24,37 @@ * Device ownership issues as mentioned above for pci_map_single are * the same here. */ -int pci_map_sg(struct pci_dev *hwdev, struct scatterlist *sg, - int nents, int direction) +int dma_map_sg(struct device *hwdev, struct scatterlist *sg, + int nents, int direction) { int i; - BUG_ON(direction == PCI_DMA_NONE); + BUG_ON(direction == DMA_NONE); for (i = 0; i < nents; i++ ) { struct scatterlist *s = &sg[i]; BUG_ON(!s->page); - s->dma_address = pci_map_page(hwdev, s->page, s->offset, - s->length, direction); + s->dma_address = virt_to_bus(page_address(s->page) +s->offset); s->dma_length = s->length; } return nents; } -EXPORT_SYMBOL(pci_map_sg); +EXPORT_SYMBOL(dma_map_sg); /* Unmap a set of streaming mode DMA translations. * Again, cpu read rules concerning calls here are the same as for * pci_unmap_single() above. */ -void pci_unmap_sg(struct pci_dev *dev, struct scatterlist *sg, - int nents, int dir) +void dma_unmap_sg(struct device *dev, struct scatterlist *sg, + int nents, int dir) { int i; for (i = 0; i < nents; i++) { struct scatterlist *s = &sg[i]; BUG_ON(s->page == NULL); BUG_ON(s->dma_address == 0); - pci_unmap_single(dev, s->dma_address, s->dma_length, dir); + dma_unmap_single(dev, s->dma_address, s->dma_length, dir); } } -EXPORT_SYMBOL(pci_unmap_sg); +EXPORT_SYMBOL(dma_unmap_sg); diff -Nru a/arch/x86_64/kernel/pci-gart.c b/arch/x86_64/kernel/pci-gart.c --- a/arch/x86_64/kernel/pci-gart.c 2004-08-25 22:01:55 -07:00 +++ b/arch/x86_64/kernel/pci-gart.c 2004-08-25 22:01:55 -07:00 @@ -31,12 +31,6 @@ #include #include -#ifdef CONFIG_PREEMPT -#define preempt_atomic() in_atomic() -#else -#define preempt_atomic() 1 -#endif - dma_addr_t bad_dma_address; unsigned long iommu_bus_base; /* GART remapping area (physical) */ @@ -54,7 +48,7 @@ int panic_on_overflow = 0; int force_iommu = 0; #endif -int iommu_merge = 0; +int iommu_merge = 1; int iommu_sac_force = 0; /* If this is disabled the IOMMU will use an optimized flushing strategy @@ -64,6 +58,10 @@ also seen with Qlogic at least). */ int iommu_fullflush = 1; +/* This tells the BIO block layer to assume merging. Default to off + because we cannot guarantee merging later. */ +int iommu_bio_merge = 0; + #define MAX_NB 8 /* Allocation bitmap for the remapping area */ @@ -104,8 +102,16 @@ static unsigned long next_bit; /* protected by iommu_bitmap_lock */ static int need_flush; /* global flush state. set for each gart wrap */ -static dma_addr_t pci_map_area(struct pci_dev *dev, unsigned long phys_mem, - size_t size, int dir); +static dma_addr_t dma_map_area(struct device *dev, unsigned long phys_mem, + size_t size, int dir, int do_panic); + +/* Dummy device used for NULL arguments (normally ISA). Better would + be probably a smaller DMA mask, but this is bug-to-bug compatible to i386. */ +static struct device fallback_dev = { + .bus_id = "fallback device", + .coherent_dma_mask = 0xffffffff, + .dma_mask = &fallback_dev.coherent_dma_mask, +}; static unsigned long alloc_iommu(int size) { @@ -146,25 +152,31 @@ /* * Use global flush state to avoid races with multiple flushers. */ -static void flush_gart(struct pci_dev *dev) +static void flush_gart(struct device *dev) { unsigned long flags; int flushed = 0; - int i; + int i, max; spin_lock_irqsave(&iommu_bitmap_lock, flags); if (need_flush) { + max = 0; for (i = 0; i < MAX_NB; i++) { - u32 w; if (!northbridges[i]) continue; pci_write_config_dword(northbridges[i], 0x9c, northbridge_flush_word[i] | 1); + flushed++; + max = i; + } + for (i = 0; i <= max; i++) { + u32 w; + if (!northbridges[i]) + continue; /* Make sure the hardware actually executed the flush. */ do { pci_read_config_dword(northbridges[i], 0x9c, &w); } while (w & 1); - flushed++; } if (!flushed) printk("nothing to flush?\n"); @@ -173,31 +185,47 @@ spin_unlock_irqrestore(&iommu_bitmap_lock, flags); } +/* Allocate DMA memory on node near device */ +noinline +static void *dma_alloc_pages(struct device *dev, unsigned gfp, unsigned order) +{ + struct page *page; + int node; + if (dev->bus == &pci_bus_type) { + cpumask_t mask; + mask = pcibus_to_cpumask(to_pci_dev(dev)->bus->number); + node = cpu_to_node(first_cpu(mask)); + } else + node = numa_node_id(); + page = alloc_pages_node(node, gfp, order); + return page ? page_address(page) : NULL; +} + /* - * Allocate memory for a consistent mapping. + * Allocate memory for a coherent mapping. */ -void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size, - dma_addr_t *dma_handle) +void * +dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle, + unsigned gfp) { void *memory; - int gfp = preempt_atomic() ? GFP_ATOMIC : GFP_KERNEL; unsigned long dma_mask = 0; u64 bus; - if (hwdev) - dma_mask = hwdev->dev.coherent_dma_mask; + if (!dev) + dev = &fallback_dev; + dma_mask = dev->coherent_dma_mask; if (dma_mask == 0) dma_mask = 0xffffffff; /* Kludge to make it bug-to-bug compatible with i386. i386 - uses the normal dma_mask for alloc_consistent. */ - if (hwdev) - dma_mask &= hwdev->dma_mask; + uses the normal dma_mask for alloc_coherent. */ + dma_mask &= *dev->dma_mask; again: - memory = (void *)__get_free_pages(gfp, get_order(size)); + memory = dma_alloc_pages(dev, gfp, get_order(size)); if (memory == NULL) - return NULL; + return NULL; { int high, mmu; @@ -223,28 +251,29 @@ } } - *dma_handle = pci_map_area(hwdev, bus, size, PCI_DMA_BIDIRECTIONAL); + *dma_handle = dma_map_area(dev, bus, size, PCI_DMA_BIDIRECTIONAL, 0); if (*dma_handle == bad_dma_address) goto error; - flush_gart(hwdev); + flush_gart(dev); return memory; error: if (panic_on_overflow) - panic("pci_alloc_consistent: overflow %lu bytes\n", size); + panic("dma_alloc_coherent: IOMMU overflow by %lu bytes\n", size); free: free_pages((unsigned long)memory, get_order(size)); + /* XXX Could use the swiotlb pool here too */ return NULL; } /* - * Unmap consistent memory. + * Unmap coherent memory. * The caller must ensure that the device has finished accessing the mapping. */ -void pci_free_consistent(struct pci_dev *hwdev, size_t size, +void dma_free_coherent(struct device *dev, size_t size, void *vaddr, dma_addr_t bus) { - pci_unmap_single(hwdev, bus, size, 0); + dma_unmap_single(dev, bus, size, 0); free_pages((unsigned long)vaddr, get_order(size)); } @@ -280,7 +309,7 @@ #define CLEAR_LEAK(x) #endif -static void iommu_full(struct pci_dev *dev, size_t size, int dir) +static void iommu_full(struct device *dev, size_t size, int dir, int do_panic) { /* * Ran out of IOMMU space for this operation. This is very bad. @@ -293,14 +322,14 @@ */ printk(KERN_ERR - "PCI-DMA: Out of IOMMU space for %lu bytes at device %s[%s]\n", - size, dev ? pci_pretty_name(dev) : "", dev ? dev->slot_name : "?"); + "PCI-DMA: Out of IOMMU space for %lu bytes at device %s\n", + size, dev->bus_id); - if (size > PAGE_SIZE*EMERGENCY_PAGES) { + if (size > PAGE_SIZE*EMERGENCY_PAGES && do_panic) { if (dir == PCI_DMA_FROMDEVICE || dir == PCI_DMA_BIDIRECTIONAL) - panic("PCI-DMA: Memory will be corrupted\n"); + panic("PCI-DMA: Memory would be corrupted\n"); if (dir == PCI_DMA_TODEVICE || dir == PCI_DMA_BIDIRECTIONAL) - panic("PCI-DMA: Random memory will be DMAed\n"); + panic("PCI-DMA: Random memory would be DMAed\n"); } #ifdef CONFIG_IOMMU_LEAK @@ -308,9 +337,9 @@ #endif } -static inline int need_iommu(struct pci_dev *dev, unsigned long addr, size_t size) +static inline int need_iommu(struct device *dev, unsigned long addr, size_t size) { - u64 mask = dev ? dev->dma_mask : 0xffffffff; + u64 mask = *dev->dma_mask; int high = addr + size >= mask; int mmu = high; if (force_iommu) @@ -323,9 +352,9 @@ return mmu; } -static inline int nonforced_iommu(struct pci_dev *dev, unsigned long addr, size_t size) +static inline int nonforced_iommu(struct device *dev, unsigned long addr, size_t size) { - u64 mask = dev ? dev->dma_mask : 0xffffffff; + u64 mask = *dev->dma_mask; int high = addr + size >= mask; int mmu = high; if (no_iommu) { @@ -339,8 +368,8 @@ /* Map a single continuous physical area into the IOMMU. * Caller needs to check if the iommu is needed and flush. */ -static dma_addr_t pci_map_area(struct pci_dev *dev, unsigned long phys_mem, - size_t size, int dir) +static dma_addr_t dma_map_area(struct device *dev, unsigned long phys_mem, + size_t size, int dir, int do_panic) { unsigned long npages = to_pages(phys_mem, size); unsigned long iommu_page = alloc_iommu(npages); @@ -349,8 +378,8 @@ if (!nonforced_iommu(dev, phys_mem, size)) return phys_mem; if (panic_on_overflow) - panic("pci_map_area overflow %lu bytes\n", size); - iommu_full(dev, size, dir); + panic("dma_map_area overflow %lu bytes\n", size); + iommu_full(dev, size, dir, do_panic); return bad_dma_address; } @@ -363,44 +392,44 @@ } /* Map a single area into the IOMMU */ -dma_addr_t pci_map_single(struct pci_dev *dev, void *addr, size_t size, int dir) -{ +dma_addr_t dma_map_single(struct device *dev, void *addr, size_t size, int dir) +{ unsigned long phys_mem, bus; - BUG_ON(dir == PCI_DMA_NONE); + BUG_ON(dir == DMA_NONE); -#ifdef CONFIG_SWIOTLB if (swiotlb) - return swiotlb_map_single(&dev->dev,addr,size,dir); -#endif + return swiotlb_map_single(dev,addr,size,dir); + if (!dev) + dev = &fallback_dev; phys_mem = virt_to_phys(addr); if (!need_iommu(dev, phys_mem, size)) return phys_mem; - bus = pci_map_area(dev, phys_mem, size, dir); + bus = dma_map_area(dev, phys_mem, size, dir, 1); flush_gart(dev); return bus; } -/* Fallback for pci_map_sg in case of overflow */ -static int pci_map_sg_nonforce(struct pci_dev *dev, struct scatterlist *sg, +/* Fallback for dma_map_sg in case of overflow */ +static int dma_map_sg_nonforce(struct device *dev, struct scatterlist *sg, int nents, int dir) { int i; #ifdef CONFIG_IOMMU_DEBUG - printk(KERN_DEBUG "pci_map_sg overflow\n"); + printk(KERN_DEBUG "dma_map_sg overflow\n"); #endif for (i = 0; i < nents; i++ ) { struct scatterlist *s = &sg[i]; unsigned long addr = page_to_phys(s->page) + s->offset; if (nonforced_iommu(dev, addr, s->length)) { - addr = pci_map_area(dev, addr, s->length, dir); + addr = dma_map_area(dev, addr, s->length, dir, 0); if (addr == bad_dma_address) { if (i > 0) - pci_unmap_sg(dev, sg, i, dir); + dma_unmap_sg(dev, sg, i, dir); nents = 0; sg[0].dma_length = 0; break; @@ -414,7 +443,7 @@ } /* Map multiple scatterlist entries continuous into the first. */ -static int __pci_map_cont(struct scatterlist *sg, int start, int stopat, +static int __dma_map_cont(struct scatterlist *sg, int start, int stopat, struct scatterlist *sout, unsigned long pages) { unsigned long iommu_start = alloc_iommu(pages); @@ -452,7 +481,7 @@ return 0; } -static inline int pci_map_cont(struct scatterlist *sg, int start, int stopat, +static inline int dma_map_cont(struct scatterlist *sg, int start, int stopat, struct scatterlist *sout, unsigned long pages, int need) { @@ -462,14 +491,14 @@ sout->dma_length = sg[start].length; return 0; } - return __pci_map_cont(sg, start, stopat, sout, pages); + return __dma_map_cont(sg, start, stopat, sout, pages); } /* * DMA map all entries in a scatterlist. * Merge chunks that have page aligned sizes into a continuous mapping. - */ -int pci_map_sg(struct pci_dev *dev, struct scatterlist *sg, int nents, int dir) + */ +int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, int dir) { int i; int out; @@ -477,19 +506,14 @@ unsigned long pages = 0; int need = 0, nextneed; -#ifdef CONFIG_SWIOTLB - if (swiotlb) - return swiotlb_map_sg(&dev->dev,sg,nents,dir); -#endif - - BUG_ON(dir == PCI_DMA_NONE); + BUG_ON(dir == DMA_NONE); if (nents == 0) return 0; -#ifdef CONFIG_SWIOTLB if (swiotlb) - return swiotlb_map_sg(&dev->dev,sg,nents,dir); -#endif + return swiotlb_map_sg(dev,sg,nents,dir); + if (!dev) + dev = &fallback_dev; out = 0; start = 0; @@ -508,19 +532,19 @@ boundary and the new one doesn't have an offset. */ if (!iommu_merge || !nextneed || !need || s->offset || (ps->offset + ps->length) % PAGE_SIZE) { - if (pci_map_cont(sg, start, i, sg+out, pages, + if (dma_map_cont(sg, start, i, sg+out, pages, need) < 0) goto error; out++; pages = 0; start = i; } - } + } need = nextneed; pages += to_pages(s->offset, s->length); } - if (pci_map_cont(sg, start, i, sg+out, pages, need) < 0) + if (dma_map_cont(sg, start, i, sg+out, pages, need) < 0) goto error; out++; flush_gart(dev); @@ -530,34 +554,32 @@ error: flush_gart(NULL); - pci_unmap_sg(dev, sg, nents, dir); + dma_unmap_sg(dev, sg, nents, dir); /* When it was forced try again unforced */ if (force_iommu) - return pci_map_sg_nonforce(dev, sg, nents, dir); + return dma_map_sg_nonforce(dev, sg, nents, dir); if (panic_on_overflow) - panic("pci_map_sg: overflow on %lu pages\n", pages); - iommu_full(dev, pages << PAGE_SHIFT, dir); + panic("dma_map_sg: overflow on %lu pages\n", pages); + iommu_full(dev, pages << PAGE_SHIFT, dir, 0); for (i = 0; i < nents; i++) sg[i].dma_address = bad_dma_address; return 0; } /* - * Free a PCI mapping. + * Free a DMA mapping. */ -void pci_unmap_single(struct pci_dev *hwdev, dma_addr_t dma_addr, +void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size, int direction) { unsigned long iommu_page; int npages; int i; -#ifdef CONFIG_SWIOTLB if (swiotlb) { - swiotlb_unmap_single(&hwdev->dev,dma_addr,size,direction); + swiotlb_unmap_single(dev,dma_addr,size,direction); return; } -#endif if (dma_addr < iommu_bus_base + EMERGENCY_PAGES*PAGE_SIZE || dma_addr >= iommu_bus_base + iommu_size) @@ -574,22 +596,25 @@ /* * Wrapper for pci_unmap_single working with scatterlists. */ -void pci_unmap_sg(struct pci_dev *dev, struct scatterlist *sg, int nents, - int dir) +void dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nents, int dir) { int i; + if (swiotlb) { + swiotlb_unmap_sg(dev,sg,nents,dir); + return; + } for (i = 0; i < nents; i++) { struct scatterlist *s = &sg[i]; if (!s->dma_length || !s->length) break; - pci_unmap_single(dev, s->dma_address, s->dma_length, dir); + dma_unmap_single(dev, s->dma_address, s->dma_length, dir); } } -int pci_dma_supported(struct pci_dev *dev, u64 mask) +int dma_supported(struct device *dev, u64 mask) { /* Copied from i386. Doesn't make much sense, because it will - only work for pci_alloc_consistent. + only work for pci_alloc_coherent. The caller just has to use GFP_DMA in this case. */ if (mask < 0x00ffffff) return 0; @@ -605,22 +630,31 @@ Assume all masks <= 40 bits are of this type. Normally this doesn't make any difference, but gives more gentle handling of IOMMU overflow. */ if (iommu_sac_force && (mask >= 0xffffffffffULL)) { - printk(KERN_INFO "%s: Force SAC with mask %Lx\n", dev->slot_name,mask); + printk(KERN_INFO "%s: Force SAC with mask %Lx\n", dev->bus_id,mask); return 0; } return 1; } -EXPORT_SYMBOL(pci_unmap_sg); -EXPORT_SYMBOL(pci_map_sg); -EXPORT_SYMBOL(pci_map_single); -EXPORT_SYMBOL(pci_unmap_single); -EXPORT_SYMBOL(pci_dma_supported); +int dma_get_cache_alignment(void) +{ + return boot_cpu_data.x86_clflush_size; +} + +EXPORT_SYMBOL(dma_unmap_sg); +EXPORT_SYMBOL(dma_map_sg); +EXPORT_SYMBOL(dma_map_single); +EXPORT_SYMBOL(dma_unmap_single); +EXPORT_SYMBOL(dma_supported); EXPORT_SYMBOL(no_iommu); EXPORT_SYMBOL(force_iommu); EXPORT_SYMBOL(bad_dma_address); -EXPORT_SYMBOL(iommu_merge); +EXPORT_SYMBOL(iommu_bio_merge); +EXPORT_SYMBOL(iommu_sac_force); +EXPORT_SYMBOL(dma_get_cache_alignment); +EXPORT_SYMBOL(dma_alloc_coherent); +EXPORT_SYMBOL(dma_free_coherent); static __init unsigned long check_iommu_size(unsigned long aper, u64 aper_size) { @@ -747,7 +781,7 @@ if (swiotlb) { no_iommu = 1; - printk(KERN_INFO "PCI-DMA: Using software bounce buffering for IO (SWIOTLB)\n"); + printk(KERN_INFO "PCI-DMA: Using software bounce buffering for IO (SWIOTLB)\n"); return -1; } @@ -851,7 +885,7 @@ fs_initcall(pci_iommu_init); /* iommu=[size][,noagp][,off][,force][,noforce][,leak][,memaper[=order]][,merge] - [,forcesac][,fullflush][,nomerge] + [,forcesac][,fullflush][,nomerge][,biomerge] size set size of iommu (in bytes) noagp don't initialize the AGP driver and use full aperture. off don't use the IOMMU @@ -859,60 +893,73 @@ memaper[=order] allocate an own aperture over RAM with size 32MB^order. noforce don't force IOMMU usage. Default. force Force IOMMU. - merge Do SG merging. Implies force (experimental) + merge Do lazy merging. This may improve performance on some block devices. + Implies force (experimental) + biomerge Do merging at the BIO layer. This is more efficient than merge, + but should be only done with very big IOMMUs. Implies merge,force. nomerge Don't do SG merging. forcesac For SAC mode for masks <40bits (experimental) fullflush Flush IOMMU on each allocation (default) nofullflush Don't use IOMMU fullflush allowed overwrite iommu off workarounds for specific chipsets. soft Use software bounce buffering (default for Intel machines) + noaperture Don't touch the aperture for AGP. */ -__init int iommu_setup(char *opt) +__init int iommu_setup(char *p) { int arg; - char *p = opt; - - for (;;) { - if (!memcmp(p,"noagp", 5)) + + while (*p) { + if (!strncmp(p,"noagp",5)) no_agp = 1; - if (!memcmp(p,"off", 3)) + if (!strncmp(p,"off",3)) no_iommu = 1; - if (!memcmp(p,"force", 5)) { + if (!strncmp(p,"force",5)) { force_iommu = 1; iommu_aperture_allowed = 1; } - if (!memcmp(p,"allowed",7)) + if (!strncmp(p,"allowed",7)) iommu_aperture_allowed = 1; - if (!memcmp(p,"noforce", 7)) { + if (!strncmp(p,"noforce",7)) { iommu_merge = 0; force_iommu = 0; } - if (!memcmp(p, "memaper", 7)) { + if (!strncmp(p, "memaper", 7)) { fallback_aper_force = 1; p += 7; - if (*p == '=' && get_option(&p, &arg)) - fallback_aper_order = arg; + if (*p == '=') { + ++p; + if (get_option(&p, &arg)) + fallback_aper_order = arg; + } } - if (!memcmp(p, "panic", 5)) + if (!strncmp(p, "biomerge",8)) { + iommu_bio_merge = 4096; + iommu_merge = 1; + force_iommu = 1; + } + if (!strncmp(p, "panic",5)) panic_on_overflow = 1; - if (!memcmp(p, "nopanic", 7)) + if (!strncmp(p, "nopanic",7)) panic_on_overflow = 0; - if (!memcmp(p, "merge", 5)) { + if (!strncmp(p, "merge",5)) { iommu_merge = 1; force_iommu = 1; } - if (!memcmp(p, "nomerge", 7)) + if (!strncmp(p, "nomerge",7)) iommu_merge = 0; - if (!memcmp(p, "forcesac", 8)) + if (!strncmp(p, "forcesac",8)) iommu_sac_force = 1; - if (!memcmp(p, "fullflush", 9)) + if (!strncmp(p, "fullflush",8)) iommu_fullflush = 1; - if (!memcmp(p, "nofullflush", 11)) + if (!strncmp(p, "nofullflush",11)) iommu_fullflush = 0; - if (!memcmp(p, "soft", 4)) + if (!strncmp(p, "soft",4)) swiotlb = 1; + if (!strncmp(p, "noaperture",10)) + fix_aperture = 0; #ifdef CONFIG_IOMMU_LEAK - if (!memcmp(p,"leak", 4)) { + if (!strncmp(p,"leak",4)) { leak_trace = 1; p += 4; if (*p == '=') ++p; @@ -922,10 +969,9 @@ #endif if (isdigit(*p) && get_option(&p, &arg)) iommu_size = arg; - do { - if (*p == ' ' || *p == 0) - return 0; - } while (*p++ != ','); + p += strcspn(p, ","); + if (*p == ',') + ++p; } return 1; } diff -Nru a/arch/x86_64/kernel/pci-nommu.c b/arch/x86_64/kernel/pci-nommu.c --- a/arch/x86_64/kernel/pci-nommu.c 2004-08-25 22:01:56 -07:00 +++ b/arch/x86_64/kernel/pci-nommu.c 2004-08-25 22:01:56 -07:00 @@ -1,8 +1,11 @@ +/* Fallback functions when the main IOMMU code is not compiled in. This + code is roughly equivalent to i386. */ #include #include #include #include #include +#include int iommu_merge = 0; EXPORT_SYMBOL(iommu_merge); @@ -10,57 +13,80 @@ dma_addr_t bad_dma_address; EXPORT_SYMBOL(bad_dma_address); +int iommu_bio_merge = 0; +EXPORT_SYMBOL(iommu_bio_merge); + +int iommu_sac_force = 0; +EXPORT_SYMBOL(iommu_sac_force); + /* * Dummy IO MMU functions */ -void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size, - dma_addr_t *dma_handle) +void *dma_alloc_coherent(struct device *hwdev, size_t size, + dma_addr_t *dma_handle, unsigned gfp) { void *ret; - int gfp = GFP_ATOMIC; - - if (hwdev == NULL || - end_pfn > (hwdev->dma_mask>>PAGE_SHIFT) || /* XXX */ - (u32)hwdev->dma_mask < 0xffffffff) - gfp |= GFP_DMA; - ret = (void *)__get_free_pages(gfp, get_order(size)); + u64 mask; + int order = get_order(size); - if (ret != NULL) { - memset(ret, 0, size); + if (hwdev) + mask = hwdev->coherent_dma_mask & *hwdev->dma_mask; + else + mask = 0xffffffff; + for (;;) { + ret = (void *)__get_free_pages(gfp, order); + if (ret == NULL) + return NULL; *dma_handle = virt_to_bus(ret); + if ((*dma_handle & ~mask) == 0) + break; + free_pages((unsigned long)ret, order); + if (gfp & GFP_DMA) + return NULL; + gfp |= GFP_DMA; } + + memset(ret, 0, size); return ret; } +EXPORT_SYMBOL(dma_alloc_coherent); -void pci_free_consistent(struct pci_dev *hwdev, size_t size, +void dma_free_coherent(struct device *hwdev, size_t size, void *vaddr, dma_addr_t dma_handle) { free_pages((unsigned long)vaddr, get_order(size)); } +EXPORT_SYMBOL(dma_free_coherent); -int pci_dma_supported(struct pci_dev *hwdev, u64 mask) +int dma_supported(struct device *hwdev, u64 mask) { /* * we fall back to GFP_DMA when the mask isn't all 1s, * so we can't guarantee allocations that must be * within a tighter range than GFP_DMA.. - * RED-PEN this won't work for pci_map_single. Caller has to - * use GFP_DMA in the first place. + * RED-PEN this won't work for pci_map_single. Caller has to + * use GFP_DMA in the first place. */ if (mask < 0x00ffffff) return 0; return 1; } +EXPORT_SYMBOL(dma_supported); -EXPORT_SYMBOL(pci_dma_supported); +int dma_get_cache_alignment(void) +{ + return boot_cpu_data.x86_clflush_size; +} +EXPORT_SYMBOL(dma_get_cache_alignment); static int __init check_ram(void) { if (end_pfn >= 0xffffffff>>PAGE_SHIFT) { - printk(KERN_ERR "WARNING more than 4GB of memory but no IOMMU.\n" - KERN_ERR "WARNING 32bit PCI may malfunction.\n"); + printk( + KERN_ERR "WARNING more than 4GB of memory but IOMMU not compiled in.\n" + KERN_ERR "WARNING 32bit PCI may malfunction.\n"); } return 0; } diff -Nru a/arch/x86_64/kernel/process.c b/arch/x86_64/kernel/process.c --- a/arch/x86_64/kernel/process.c 2004-08-25 22:01:55 -07:00 +++ b/arch/x86_64/kernel/process.c 2004-08-25 22:01:55 -07:00 @@ -168,9 +168,7 @@ if (cpu_has(c, X86_FEATURE_MWAIT)) { /* * Skip, if setup has overridden idle. - * Also, take care of system with asymmetric CPUs. - * Use, mwait_idle only if all cpus support it. - * If not, we fallback to default_idle() + * One CPU supports mwait => All CPUs supports mwait */ if (!pm_idle) { if (!printed) { @@ -179,10 +177,7 @@ } pm_idle = mwait_idle; } - return; } - pm_idle = default_idle; - return; } static int __init idle_setup (char *str) @@ -546,17 +541,16 @@ clear_thread_flag(TIF_IA32); } -asmlinkage long sys_fork(struct pt_regs regs) +asmlinkage long sys_fork(struct pt_regs *regs) { - return do_fork(SIGCHLD, regs.rsp, ®s, 0, NULL, NULL); + return do_fork(SIGCHLD, regs->rsp, regs, 0, NULL, NULL); } -asmlinkage long sys_clone(unsigned long clone_flags, unsigned long newsp, void __user *parent_tid, void __user *child_tid, struct pt_regs regs) +asmlinkage long sys_clone(unsigned long clone_flags, unsigned long newsp, void __user *parent_tid, void __user *child_tid, struct pt_regs *regs) { if (!newsp) - newsp = regs.rsp; - return do_fork(clone_flags & ~CLONE_IDLETASK, newsp, ®s, 0, - parent_tid, child_tid); + newsp = regs->rsp; + return do_fork(clone_flags, newsp, regs, 0, parent_tid, child_tid); } /* @@ -569,9 +563,9 @@ * do not have enough call-clobbered registers to hold all * the information you need. */ -asmlinkage long sys_vfork(struct pt_regs regs) +asmlinkage long sys_vfork(struct pt_regs *regs) { - return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs.rsp, ®s, 0, + return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->rsp, regs, 0, NULL, NULL); } diff -Nru a/arch/x86_64/kernel/ptrace.c b/arch/x86_64/kernel/ptrace.c --- a/arch/x86_64/kernel/ptrace.c 2004-08-25 22:01:55 -07:00 +++ b/arch/x86_64/kernel/ptrace.c 2004-08-25 22:01:55 -07:00 @@ -433,30 +433,32 @@ break; case PTRACE_GETREGS: { /* Get all gp regs from the child. */ - if (!access_ok(VERIFY_WRITE, (unsigned __user *)data, FRAME_SIZE)) { + if (!access_ok(VERIFY_WRITE, (unsigned __user *)data, + sizeof(struct user_regs_struct))) { ret = -EIO; break; } + ret = 0; for (ui = 0; ui < sizeof(struct user_regs_struct); ui += sizeof(long)) { - __put_user(getreg(child, ui),(unsigned long __user *) data); + ret |= __put_user(getreg(child, ui),(unsigned long __user *) data); data += sizeof(long); } - ret = 0; break; } case PTRACE_SETREGS: { /* Set all gp regs in the child. */ unsigned long tmp; - if (!access_ok(VERIFY_READ, (unsigned __user *)data, FRAME_SIZE)) { + if (!access_ok(VERIFY_READ, (unsigned __user *)data, + sizeof(struct user_regs_struct))) { ret = -EIO; break; } + ret = 0; for (ui = 0; ui < sizeof(struct user_regs_struct); ui += sizeof(long)) { - __get_user(tmp, (unsigned long __user *) data); + ret |= __get_user(tmp, (unsigned long __user *) data); putreg(child, ui, tmp); data += sizeof(long); } - ret = 0; break; } diff -Nru a/arch/x86_64/kernel/setup.c b/arch/x86_64/kernel/setup.c --- a/arch/x86_64/kernel/setup.c 2004-08-25 22:01:54 -07:00 +++ b/arch/x86_64/kernel/setup.c 2004-08-25 22:01:54 -07:00 @@ -79,8 +79,10 @@ unsigned long saved_video_mode; +#ifdef CONFIG_SWIOTLB int swiotlb; EXPORT_SYMBOL(swiotlb); +#endif /* * Setup options @@ -765,6 +767,7 @@ { 0x43, LVL_2, 512 }, { 0x44, LVL_2, 1024 }, { 0x45, LVL_2, 2048 }, + { 0x60, LVL_1_DATA, 16 }, { 0x66, LVL_1_DATA, 8 }, { 0x67, LVL_1_DATA, 16 }, { 0x68, LVL_1_DATA, 32 }, @@ -1059,8 +1062,8 @@ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* Intel-defined (#2) */ - "pni", NULL, NULL, "monitor", "ds_cpl", NULL, NULL, "tm2", - "est", NULL, "cid", NULL, NULL, "cmpxchg16b", NULL, NULL, + "pni", NULL, NULL, "monitor", "ds_cpl", NULL, NULL, "est", + "tm2", NULL, "cid", NULL, NULL, "cx16", "xtpr", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, }; diff -Nru a/arch/x86_64/kernel/setup64.c b/arch/x86_64/kernel/setup64.c --- a/arch/x86_64/kernel/setup64.c 2004-08-25 22:01:55 -07:00 +++ b/arch/x86_64/kernel/setup64.c 2004-08-25 22:01:55 -07:00 @@ -60,12 +60,12 @@ */ static int __init nonx_setup(char *str) { - if (!strncmp(str, "on",3)) { + if (!strcmp(str, "on")) { __supported_pte_mask |= _PAGE_NX; do_not_nx = 0; vm_data_default_flags &= ~VM_EXEC; vm_stack_flags &= ~VM_EXEC; - } else if (!strncmp(str, "noforce",7) || !strncmp(str,"off",3)) { + } else if (!strcmp(str, "noforce") || !strcmp(str, "off")) { do_not_nx = (str[0] == 'o'); if (do_not_nx) __supported_pte_mask &= ~_PAGE_NX; @@ -91,26 +91,28 @@ compat (default) Imply PROT_EXEC for PROT_READ */ - static int __init nonx32_setup(char *str) + static int __init nonx32_setup(char *s) { - char *s; - while ((s = strsep(&str, ",")) != NULL) { - if (!strcmp(s, "all") || !strcmp(s,"on")) { + while (*s) { + if (!strncmp(s, "all", 3) || !strncmp(s,"on",2)) { vm_data_default_flags32 &= ~VM_EXEC; vm_stack_flags32 &= ~VM_EXEC; - } else if (!strcmp(s, "off")) { + } else if (!strncmp(s, "off",3)) { vm_data_default_flags32 |= VM_EXEC; vm_stack_flags32 |= VM_EXEC; - } else if (!strcmp(s, "stack")) { + } else if (!strncmp(s, "stack", 5)) { vm_data_default_flags32 |= VM_EXEC; vm_stack_flags32 &= ~VM_EXEC; - } else if (!strcmp(s, "force")) { + } else if (!strncmp(s, "force",5)) { vm_force_exec32 = 0; - } else if (!strcmp(s, "compat")) { + } else if (!strncmp(s, "compat",5)) { vm_force_exec32 = PROT_EXEC; } - } - return 1; + s += strcspn(s, ","); + if (*s == ',') + ++s; + } + return 1; } __setup("noexec32=", nonx32_setup); diff -Nru a/arch/x86_64/kernel/signal.c b/arch/x86_64/kernel/signal.c --- a/arch/x86_64/kernel/signal.c 2004-08-25 22:01:55 -07:00 +++ b/arch/x86_64/kernel/signal.c 2004-08-25 22:01:55 -07:00 @@ -40,7 +40,7 @@ sigset_t *set, struct pt_regs * regs); asmlinkage long -sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize, struct pt_regs regs) +sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize, struct pt_regs *regs) { sigset_t saveset, newset; @@ -59,21 +59,22 @@ spin_unlock_irq(¤t->sighand->siglock); #ifdef DEBUG_SIG printk("rt_sigsuspend savset(%lx) newset(%lx) regs(%p) rip(%lx)\n", - saveset, newset, ®s, regs.rip); + saveset, newset, regs, regs->rip); #endif - regs.rax = -EINTR; + regs->rax = -EINTR; while (1) { current->state = TASK_INTERRUPTIBLE; schedule(); - if (do_signal(®s, &saveset)) + if (do_signal(regs, &saveset)) return -EINTR; } } asmlinkage long -sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, struct pt_regs regs) +sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, + struct pt_regs *regs) { - return do_sigaltstack(uss, uoss, regs.rsp); + return do_sigaltstack(uss, uoss, regs->rsp); } @@ -134,13 +135,13 @@ return 1; } -asmlinkage long sys_rt_sigreturn(struct pt_regs regs) +asmlinkage long sys_rt_sigreturn(struct pt_regs *regs) { struct rt_sigframe __user *frame; sigset_t set; long eax; - frame = (struct rt_sigframe __user *)(regs.rsp - 8); + frame = (struct rt_sigframe __user *)(regs->rsp - 8); if (verify_area(VERIFY_READ, frame, sizeof(*frame))) { goto badframe; } @@ -154,7 +155,7 @@ recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); - if (restore_sigcontext(®s, &frame->uc.uc_mcontext, &eax)) { + if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &eax)) { goto badframe; } @@ -162,13 +163,13 @@ printk("%d sigreturn rip:%lx rsp:%lx frame:%p rax:%lx\n",current->pid,regs.rip,regs.rsp,frame,eax); #endif - if (do_sigaltstack(&frame->uc.uc_stack, NULL, regs.rsp) == -EFAULT) + if (do_sigaltstack(&frame->uc.uc_stack, NULL, regs->rsp) == -EFAULT) goto badframe; return eax; badframe: - signal_fault(®s,frame,"sigreturn"); + signal_fault(regs,frame,"sigreturn"); return 0; } @@ -287,7 +288,7 @@ if (ka->sa.sa_flags & SA_RESTORER) { err |= __put_user(ka->sa.sa_restorer, &frame->pretcode); } else { - printk("%s forgot to set SA_RESTORER for signal %d.\n", me->comm, sig); + /* could use a vstub here */ goto give_sigsegv; } @@ -328,9 +329,7 @@ return; give_sigsegv: - if (sig == SIGSEGV) - ka->sa.sa_handler = SIG_DFL; - signal_fault(regs,frame,"signal deliver"); + force_sigsegv(sig, current); } /* @@ -338,11 +337,9 @@ */ static void -handle_signal(unsigned long sig, siginfo_t *info, sigset_t *oldset, - struct pt_regs * regs) +handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, + sigset_t *oldset, struct pt_regs *regs) { - struct k_sigaction *ka = ¤t->sighand->action[sig-1]; - #ifdef DEBUG_SIG printk("handle_signal pid:%d sig:%lu rip:%lx rsp:%lx regs=%p\n", current->pid, sig, regs->rip, regs->rsp, regs); @@ -379,9 +376,6 @@ #endif setup_rt_frame(sig, ka, info, oldset, regs); - if (ka->sa.sa_flags & SA_ONESHOT) - ka->sa.sa_handler = SIG_DFL; - if (!(ka->sa.sa_flags & SA_NODEFER)) { spin_lock_irq(¤t->sighand->siglock); sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); @@ -398,6 +392,7 @@ */ int do_signal(struct pt_regs *regs, sigset_t *oldset) { + struct k_sigaction ka; siginfo_t info; int signr; @@ -419,7 +414,7 @@ if (!oldset) oldset = ¤t->blocked; - signr = get_signal_to_deliver(&info, regs, NULL); + signr = get_signal_to_deliver(&info, &ka, regs, NULL); if (signr > 0) { /* Reenable any watchpoints before delivering the * signal to user space. The processor register will @@ -430,7 +425,7 @@ asm volatile("movq %0,%%db7" : : "r" (current->thread.debugreg7)); /* Whee! Actually deliver the signal. */ - handle_signal(signr, &info, oldset, regs); + handle_signal(signr, &info, &ka, oldset, regs); return 1; } diff -Nru a/arch/x86_64/kernel/smpboot.c b/arch/x86_64/kernel/smpboot.c --- a/arch/x86_64/kernel/smpboot.c 2004-08-25 22:01:56 -07:00 +++ b/arch/x86_64/kernel/smpboot.c 2004-08-25 22:01:56 -07:00 @@ -392,16 +392,6 @@ extern volatile unsigned long init_rsp; extern void (*initial_code)(void); -static struct task_struct * __init fork_by_hand(void) -{ - struct pt_regs regs; - /* - * don't care about the eip and regs settings since - * we'll never reschedule the forked task. - */ - return copy_process(CLONE_VM|CLONE_IDLETASK, 0, ®s, 0, NULL, NULL); -} - #if APIC_DEBUG static inline void inquire_remote_apic(int apicid) { @@ -575,19 +565,10 @@ * We can't use kernel_thread since we must avoid to * reschedule the child. */ - idle = fork_by_hand(); + idle = fork_idle(cpu); if (IS_ERR(idle)) panic("failed fork for CPU %d", cpu); - wake_up_forked_process(idle); x86_cpu_to_apicid[cpu] = apicid; - - /* - * We remove it from the pidhash and the runqueue - * once we got the process: - */ - init_idle(idle,cpu); - - unhash_process(idle); cpu_pda[cpu].pcurrent = idle; diff -Nru a/arch/x86_64/kernel/time.c b/arch/x86_64/kernel/time.c --- a/arch/x86_64/kernel/time.c 2004-08-25 22:01:55 -07:00 +++ b/arch/x86_64/kernel/time.c 2004-08-25 22:01:55 -07:00 @@ -11,7 +11,6 @@ * Copyright (c) 2002 Vojtech Pavlik * Copyright (c) 2003 Andi Kleen * RTC support code taken from arch/i386/kernel/timers/time_hpet.c - * */ #include @@ -42,6 +41,10 @@ EXPORT_SYMBOL(jiffies_64); +#ifdef CONFIG_CPU_FREQ +static void cpufreq_delayed_get(void); +#endif + extern int using_apic_timer; spinlock_t rtc_lock = SPIN_LOCK_UNLOCKED; @@ -82,7 +85,7 @@ * timer interrupt has happened already, but vxtime.trigger wasn't updated yet. * This is not a problem, because jiffies hasn't updated either. They are bound * together by xtime_lock. - */ + */ static inline unsigned int do_gettimeoffset_tsc(void) { @@ -119,7 +122,7 @@ usec = xtime.tv_nsec / 1000; /* i386 does some correction here to keep the clock - monotonus even when ntpd is fixing drift. + monotonous even when ntpd is fixing drift. But they didn't work for me, there is a non monotonic clock anyways with ntp. I dropped all corrections now until a real solution can @@ -214,7 +217,7 @@ * overflow. This avoids messing with unknown time zones but requires your RTC * not to be off by more than 15 minutes. Since we're calling it only when * our clock is externally synchronized using NTP, this shouldn't be a problem. - */ + */ real_seconds = nowtime % 60; real_minutes = nowtime / 60; @@ -297,15 +300,15 @@ static irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) { static unsigned long rtc_update = 0; - unsigned long tsc, lost = 0; - int delay, offset = 0; + unsigned long tsc; + int delay, offset = 0, lost = 0; /* * Here we are in the timer irq handler. We have irqs locally disabled (so we * don't need spin_lock_irqsave()) but we don't know if the timer_bh is running * on the other CPU, so we need a lock. We also need to lock the vsyscall * variables, because both do_timer() and us change them -arca+vojtech - */ + */ write_seqlock(&xtime_lock); @@ -354,12 +357,29 @@ (((long) offset << 32) / vxtime.tsc_quot) - 1; } - if (lost) { + if (lost > 0) { + static long lost_count; + if (report_lost_ticks) { - printk(KERN_WARNING "time.c: Lost %ld timer " + printk(KERN_WARNING "time.c: Lost %d timer " "tick(s)! ", lost); print_symbol("rip %s)\n", regs->rip); } + + if (lost_count == 100) { + printk(KERN_WARNING + "warning: many lost ticks.\n" + KERN_WARNING "Your time source seems to be instable or some driver is hogging interupts\n"); + print_symbol("rip %s\n", regs->rip); + lost_count = 0; + } else + lost_count++; + + if ((lost_count % 25) == 0) { +#ifdef CONFIG_CPU_FREQ + cpufreq_delayed_get(); +#endif + } jiffies += lost; } @@ -509,6 +529,34 @@ Should fix up last_tsc too. Currently gettimeofday in the first tick after the change will be slightly wrong. */ +#include + +static unsigned int cpufreq_delayed_issched = 0; +static unsigned int cpufreq_init = 0; +static struct work_struct cpufreq_delayed_get_work; + +static void handle_cpufreq_delayed_get(void *v) +{ + unsigned int cpu; + for_each_online_cpu(cpu) { + cpufreq_get(cpu); + } + cpufreq_delayed_issched = 0; +} + +/* if we notice lost ticks, schedule a call to cpufreq_get() as it tries + * to verify the CPU frequency the timing core thinks the CPU is running + * at is still correct. + */ +static void cpufreq_delayed_get(void) +{ + if (cpufreq_init && !cpufreq_delayed_issched) { + cpufreq_delayed_issched = 1; + printk(KERN_DEBUG "Losing some ticks... checking if CPU frequency changed.\n"); + schedule_work(&cpufreq_delayed_get_work); + } +} + static unsigned int ref_freq = 0; static unsigned long loops_per_jiffy_ref = 0; @@ -518,14 +566,18 @@ void *data) { struct cpufreq_freqs *freq = data; - unsigned long *lpj; + unsigned long *lpj, dummy; + lpj = &dummy; + if (!(freq->flags & CPUFREQ_CONST_LOOPS)) #ifdef CONFIG_SMP lpj = &cpu_data[freq->cpu].loops_per_jiffy; #else lpj = &boot_cpu_data.loops_per_jiffy; #endif + + if (!ref_freq) { ref_freq = freq->old; loops_per_jiffy_ref = *lpj; @@ -538,7 +590,8 @@ cpufreq_scale(loops_per_jiffy_ref, ref_freq, freq->new); cpu_khz = cpufreq_scale(cpu_khz_ref, ref_freq, freq->new); - vxtime.tsc_quot = (1000L << 32) / cpu_khz; + if (!(freq->flags & CPUFREQ_CONST_LOOPS)) + vxtime.tsc_quot = (1000L << 32) / cpu_khz; } set_cyc2ns_scale(cpu_khz_ref / 1000); @@ -549,6 +602,18 @@ static struct notifier_block time_cpufreq_notifier_block = { .notifier_call = time_cpufreq_notifier }; + +static int __init cpufreq_tsc(void) +{ + INIT_WORK(&cpufreq_delayed_get_work, handle_cpufreq_delayed_get, NULL); + if (!cpufreq_register_notifier(&time_cpufreq_notifier_block, + CPUFREQ_TRANSITION_NOTIFIER)) + cpufreq_init = 1; + return 0; +} + +core_initcall(cpufreq_tsc); + #endif /* @@ -725,8 +790,8 @@ cpu_khz = hpet_calibrate_tsc(); timename = "HPET"; } else { - pit_init(); - cpu_khz = pit_calibrate_tsc(); + pit_init(); + cpu_khz = pit_calibrate_tsc(); timename = "PIT"; } @@ -742,11 +807,6 @@ setup_irq(0, &irq0); set_cyc2ns_scale(cpu_khz / 1000); - -#ifdef CONFIG_CPU_FREQ - cpufreq_register_notifier(&time_cpufreq_notifier_block, - CPUFREQ_TRANSITION_NOTIFIER); -#endif } void __init time_init_smp(void) @@ -1037,6 +1097,8 @@ return IRQ_HANDLED; } #endif + + static int __init nohpet_setup(char *s) { diff -Nru a/arch/x86_64/kernel/traps.c b/arch/x86_64/kernel/traps.c --- a/arch/x86_64/kernel/traps.c 2004-08-25 22:01:54 -07:00 +++ b/arch/x86_64/kernel/traps.c 2004-08-25 22:01:54 -07:00 @@ -352,7 +352,7 @@ #ifdef CONFIG_DEBUG_PAGEALLOC printk("DEBUG_PAGEALLOC"); #endif - printk("\n"); + printk("\n"); notify_die(DIE_OOPS, (char *)str, regs, err, 255, SIGSEGV); show_registers(regs); /* Executive summary in case the oops scrolled away */ @@ -513,7 +513,7 @@ tsk->thread.error_code = error_code; tsk->thread.trap_no = 13; force_sig(SIGSEGV, tsk); - return; + return; } /* kernel gp */ @@ -670,7 +670,6 @@ return regs; clear_TF_reenable: - printk("clear_tf_reenable\n"); set_tsk_thread_flag(tsk, TIF_SINGLESTEP); clear_TF: @@ -681,16 +680,43 @@ return regs; } +static int kernel_math_error(struct pt_regs *regs, char *str) +{ + const struct exception_table_entry *fixup; + fixup = search_exception_tables(regs->rip); + if (fixup) { + regs->rip = fixup->fixup; + return 1; + } + notify_die(DIE_GPF, str, regs, 0, 16, SIGFPE); +#if 0 + /* This should be a die, but warn only for now */ + die(str, regs, 0); +#else + printk(KERN_DEBUG "%s: %s at ", current->comm, str); + printk_address(regs->rip); + printk("\n"); +#endif + return 0; +} + /* * Note that we play around with the 'TS' bit in an attempt to get * the correct behaviour even in the presence of the asynchronous * IRQ13 behaviour */ -void math_error(void __user *rip) +asmlinkage void do_coprocessor_error(struct pt_regs *regs) { + void __user *rip = (void __user *)(regs->rip); struct task_struct * task; siginfo_t info; unsigned short cwd, swd; + + conditional_sti(regs); + if ((regs->cs & 3) == 0 && + kernel_math_error(regs, "kernel x87 math error")) + return; + /* * Save the info for the exception handler and clear the error. */ @@ -740,23 +766,23 @@ force_sig_info(SIGFPE, &info, task); } -asmlinkage void do_coprocessor_error(struct pt_regs * regs) -{ - conditional_sti(regs); - math_error((void __user *)regs->rip); -} - asmlinkage void bad_intr(void) { printk("bad interrupt"); } -static inline void simd_math_error(void __user *rip) +asmlinkage void do_simd_coprocessor_error(struct pt_regs *regs) { + void __user *rip = (void __user *)(regs->rip); struct task_struct * task; siginfo_t info; unsigned short mxcsr; + conditional_sti(regs); + if ((regs->cs & 3) == 0 && + kernel_math_error(regs, "simd math error")) + return; + /* * Save the info for the exception handler and clear the error. */ @@ -797,12 +823,6 @@ break; } force_sig_info(SIGFPE, &info, task); -} - -asmlinkage void do_simd_coprocessor_error(struct pt_regs * regs) -{ - conditional_sti(regs); - simd_math_error((void __user *)regs->rip); } asmlinkage void do_spurious_interrupt_bug(struct pt_regs * regs) diff -Nru a/arch/x86_64/kernel/vmlinux.lds.S b/arch/x86_64/kernel/vmlinux.lds.S --- a/arch/x86_64/kernel/vmlinux.lds.S 2004-08-25 22:01:54 -07:00 +++ b/arch/x86_64/kernel/vmlinux.lds.S 2004-08-25 22:01:54 -07:00 @@ -91,9 +91,6 @@ __setup_start = .; .init.setup : { *(.init.setup) } __setup_end = .; - __start___param = .; - __param : { *(__param) } - __stop___param = .; __initcall_start = .; .initcall.init : { *(.initcall1.init) diff -Nru a/arch/x86_64/kernel/x8664_ksyms.c b/arch/x86_64/kernel/x8664_ksyms.c --- a/arch/x86_64/kernel/x8664_ksyms.c 2004-08-25 22:01:54 -07:00 +++ b/arch/x86_64/kernel/x8664_ksyms.c 2004-08-25 22:01:54 -07:00 @@ -108,11 +108,8 @@ EXPORT_SYMBOL(pci_mem_start); #endif -#ifdef CONFIG_X86_USE_3DNOW -EXPORT_SYMBOL(_mmx_memcpy); -EXPORT_SYMBOL(mmx_clear_page); -EXPORT_SYMBOL(mmx_copy_page); -#endif +EXPORT_SYMBOL(copy_page); +EXPORT_SYMBOL(clear_page); EXPORT_SYMBOL(cpu_pda); #ifdef CONFIG_SMP @@ -182,10 +179,17 @@ EXPORT_SYMBOL_NOVERS(__memcpy); EXPORT_SYMBOL_NOVERS(memcmp); -/* syscall export needed for misdesigned sound drivers. */ -EXPORT_SYMBOL(sys_read); -EXPORT_SYMBOL(sys_lseek); -EXPORT_SYMBOL(sys_open); +#ifdef CONFIG_RWSEM_XCHGADD_ALGORITHM +/* prototypes are wrong, these are assembly with custom calling functions */ +extern void rwsem_down_read_failed_thunk(void); +extern void rwsem_wake_thunk(void); +extern void rwsem_downgrade_thunk(void); +extern void rwsem_down_write_failed_thunk(void); +EXPORT_SYMBOL(rwsem_down_read_failed_thunk); +EXPORT_SYMBOL(rwsem_wake_thunk); +EXPORT_SYMBOL(rwsem_downgrade_thunk); +EXPORT_SYMBOL(rwsem_down_write_failed_thunk); +#endif EXPORT_SYMBOL(empty_zero_page); @@ -211,10 +215,9 @@ extern unsigned long __supported_pte_mask; EXPORT_SYMBOL(__supported_pte_mask); -EXPORT_SYMBOL(clear_page); - #ifdef CONFIG_SMP EXPORT_SYMBOL(flush_tlb_page); EXPORT_SYMBOL_GPL(flush_tlb_all); #endif +EXPORT_SYMBOL(cpu_khz); diff -Nru a/arch/x86_64/lib/Makefile b/arch/x86_64/lib/Makefile --- a/arch/x86_64/lib/Makefile 2004-08-25 22:01:54 -07:00 +++ b/arch/x86_64/lib/Makefile 2004-08-25 22:01:54 -07:00 @@ -8,7 +8,7 @@ lib-y := csum-partial.o csum-copy.o csum-wrappers.o delay.o \ usercopy.o getuser.o putuser.o \ - thunk.o clear_page.o copy_page.o bitstr.o + thunk.o clear_page.o copy_page.o bitstr.o bitops.o lib-y += memcpy.o memmove.o memset.o copy_user.o lib-$(CONFIG_HAVE_DEC_LOCK) += dec_and_lock.o diff -Nru a/arch/x86_64/lib/bitops.c b/arch/x86_64/lib/bitops.c --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/arch/x86_64/lib/bitops.c 2004-08-25 22:01:56 -07:00 @@ -0,0 +1,140 @@ +#include +#include + +#undef find_first_zero_bit +#undef find_next_zero_bit +#undef find_first_bit +#undef find_next_bit + +/** + * find_first_zero_bit - find the first zero bit in a memory region + * @addr: The address to start the search at + * @size: The maximum size to search + * + * Returns the bit-number of the first zero bit, not the number of the byte + * containing a bit. + */ +inline long find_first_zero_bit(const unsigned long * addr, unsigned long size) +{ + long d0, d1, d2; + long res; + + if (!size) + return 0; + asm volatile( + " repe; scasq\n" + " je 1f\n" + " xorq -8(%%rdi),%%rax\n" + " subq $8,%%rdi\n" + " bsfq %%rax,%%rdx\n" + "1: subq %[addr],%%rdi\n" + " shlq $3,%%rdi\n" + " addq %%rdi,%%rdx" + :"=d" (res), "=&c" (d0), "=&D" (d1), "=&a" (d2) + :"0" (0ULL), "1" ((size + 63) >> 6), "2" (addr), "3" (-1ULL), + [addr] "r" (addr) : "memory"); + return res; +} + +/** + * find_next_zero_bit - find the first zero bit in a memory region + * @addr: The address to base the search on + * @offset: The bitnumber to start searching at + * @size: The maximum size to search + */ +long find_next_zero_bit (const unsigned long * addr, long size, long offset) +{ + unsigned long * p = ((unsigned long *) addr) + (offset >> 6); + unsigned long set = 0; + unsigned long res, bit = offset&63; + + if (bit) { + /* + * Look for zero in first word + */ + asm("bsfq %1,%0\n\t" + "cmoveq %2,%0" + : "=r" (set) + : "r" (~(*p >> bit)), "r"(64L)); + if (set < (64 - bit)) + return set + offset; + set = 64 - bit; + p++; + } + /* + * No zero yet, search remaining full words for a zero + */ + res = find_first_zero_bit ((const unsigned long *)p, + size - 64 * (p - (unsigned long *) addr)); + return (offset + set + res); +} + +static inline long +__find_first_bit(const unsigned long * addr, unsigned long size) +{ + long d0, d1; + long res; + + asm volatile( + " repe; scasq\n" + " jz 1f\n" + " subq $8,%%rdi\n" + " bsfq (%%rdi),%%rax\n" + "1: subq %[addr],%%rdi\n" + " shlq $3,%%rdi\n" + " addq %%rdi,%%rax" + :"=a" (res), "=&c" (d0), "=&D" (d1) + :"0" (0ULL), + "1" ((size + 63) >> 6), "2" (addr), + [addr] "r" (addr) : "memory"); + return res; +} + +/** + * find_first_bit - find the first set bit in a memory region + * @addr: The address to start the search at + * @size: The maximum size to search + * + * Returns the bit-number of the first set bit, not the number of the byte + * containing a bit. + */ +long find_first_bit(const unsigned long * addr, unsigned long size) +{ + return __find_first_bit(addr,size); +} + +/** + * find_next_bit - find the first set bit in a memory region + * @addr: The address to base the search on + * @offset: The bitnumber to start searching at + * @size: The maximum size to search + */ +long find_next_bit(const unsigned long * addr, long size, long offset) +{ + const unsigned long * p = addr + (offset >> 6); + unsigned long set = 0, bit = offset & 63, res; + + if (bit) { + /* + * Look for nonzero in the first 64 bits: + */ + asm("bsfq %1,%0\n\t" + "cmoveq %2,%0\n\t" + : "=r" (set) + : "r" (*p >> bit), "r" (64L)); + if (set < (64 - bit)) + return set + offset; + set = 64 - bit; + p++; + } + /* + * No set bit yet, search remaining full words for a bit + */ + res = __find_first_bit (p, size - 64 * (p - addr)); + return (offset + set + res); +} + +EXPORT_SYMBOL(find_next_bit); +EXPORT_SYMBOL(find_first_bit); +EXPORT_SYMBOL(find_first_zero_bit); +EXPORT_SYMBOL(find_next_zero_bit); diff -Nru a/arch/x86_64/lib/bitstr.c b/arch/x86_64/lib/bitstr.c --- a/arch/x86_64/lib/bitstr.c 2004-08-25 22:01:55 -07:00 +++ b/arch/x86_64/lib/bitstr.c 2004-08-25 22:01:55 -07:00 @@ -1,3 +1,4 @@ +#include #include /* Find string of zero bits in a bitmap */ @@ -23,3 +24,5 @@ } return n; } + +EXPORT_SYMBOL(find_next_zero_string); diff -Nru a/arch/x86_64/lib/memmove.c b/arch/x86_64/lib/memmove.c --- a/arch/x86_64/lib/memmove.c 2004-08-25 22:01:55 -07:00 +++ b/arch/x86_64/lib/memmove.c 2004-08-25 22:01:55 -07:00 @@ -10,18 +10,10 @@ if (dest < src) { __inline_memcpy(dest,src,count); } else { - /* Could be more clever and move longs */ - unsigned long d0, d1, d2; - __asm__ __volatile__( - "std\n\t" - "rep\n\t" - "movsb\n\t" - "cld" - : "=&c" (d0), "=&S" (d1), "=&D" (d2) - :"0" (count), - "1" (count-1+(const char *)src), - "2" (count-1+(char *)dest) - :"memory"); + char *p = (char *) dest + count; + char *s = (char *) src + count; + while (count--) + *--p = *--s; } return dest; } diff -Nru a/arch/x86_64/mm/fault.c b/arch/x86_64/mm/fault.c --- a/arch/x86_64/mm/fault.c 2004-08-25 22:01:54 -07:00 +++ b/arch/x86_64/mm/fault.c 2004-08-25 22:01:54 -07:00 @@ -58,16 +58,17 @@ /* Sometimes the CPU reports invalid exceptions on prefetch. Check that here and ignore. Opcode checker based on code by Richard Brunner */ -static int is_prefetch(struct pt_regs *regs, unsigned long addr) +static noinline int is_prefetch(struct pt_regs *regs, unsigned long addr, + unsigned long error_code) { unsigned char *instr = (unsigned char *)(regs->rip); int scan_more = 1; int prefetch = 0; unsigned char *max_instr = instr + 15; - /* Avoid recursive faults for this common case */ - if (regs->rip == addr) - return 0; + /* If it was a exec fault ignore */ + if (error_code & (1<<4)) + return 0; /* Code segments in LDT could have a non zero base. Don't check when that's possible */ @@ -218,6 +219,18 @@ (tsk->sighand->action[sig-1].sa.sa_handler == SIG_DFL); } +static noinline void pgtable_bad(unsigned long address, struct pt_regs *regs, + unsigned long error_code) +{ + oops_begin(); + printk(KERN_ALERT "%s: Corrupted page table at address %lx\n", + current->comm, address); + dump_pagetable(address); + __die("Bad pagetable", regs, error_code); + oops_end(); + do_exit(SIGKILL); +} + int page_fault_trace; int exception_trace = 1; @@ -268,11 +281,32 @@ mm = tsk->mm; info.si_code = SEGV_MAPERR; - /* 5 => page not present and from supervisor mode */ - if (unlikely(!(error_code & 5) && - ((address >= VMALLOC_START && address <= VMALLOC_END) || - (address >= MODULES_VADDR && address <= MODULES_END)))) - goto vmalloc_fault; + + /* + * We fault-in kernel-space virtual memory on-demand. The + * 'reference' page table is init_mm.pgd. + * + * NOTE! We MUST NOT take any locks for this case. We may + * be in an interrupt or a critical region, and should + * only copy the information from the master page table, + * nothing more. + * + * This verifies that the fault happens in kernel space + * (error_code & 4) == 0, and that the fault was not a + * protection error (error_code & 1) == 0. + */ + if (unlikely(address >= TASK_SIZE)) { + if (!(error_code & 5)) + goto vmalloc_fault; + /* + * Don't take the mm semaphore here. If we fixup a prefetch + * fault we could otherwise deadlock. + */ + goto bad_area_nosemaphore; + } + + if (unlikely(error_code & (1 << 3))) + goto page_table_corruption; /* * If we're in an interrupt or have no user @@ -351,18 +385,18 @@ bad_area_nosemaphore: #ifdef CONFIG_IA32_EMULATION - /* 32bit vsyscall. map on demand. */ - if (test_thread_flag(TIF_IA32) && + /* 32bit vsyscall. map on demand. */ + if (test_thread_flag(TIF_IA32) && address >= 0xffffe000 && address < 0xffffe000 + PAGE_SIZE) { - if (map_syscall32(mm, address) < 0) - goto out_of_memory2; - return; - } + if (map_syscall32(mm, address) < 0) + goto out_of_memory2; + return; + } #endif /* User mode accesses just cause a SIGSEGV */ if (error_code & 4) { - if (is_prefetch(regs, address)) + if (is_prefetch(regs, address, error_code)) return; /* Work around K8 erratum #100 K8 in compat mode @@ -376,7 +410,7 @@ return; if (exception_trace && unhandled_signal(tsk, SIGSEGV)) { - printk(KERN_INFO + printk(KERN_INFO "%s[%d]: segfault at %016lx rip %016lx rsp %016lx error %lx\n", tsk->comm, tsk->pid, address, regs->rip, regs->rsp, error_code); @@ -407,7 +441,7 @@ * Hall of shame of CPU/BIOS bugs. */ - if (is_prefetch(regs, address)) + if (is_prefetch(regs, address, error_code)) return; if (is_errata93(regs, address)) @@ -481,10 +515,8 @@ * is really there and when yes flush the local TLB. */ pgd = pgd_offset_k(address); - if (pgd != current_pgd_offset_k(address)) - BUG(); if (!pgd_present(*pgd)) - goto bad_area_nosemaphore; + goto bad_area_nosemaphore; pmd = pmd_offset(pgd, address); if (!pmd_present(*pmd)) goto bad_area_nosemaphore; @@ -495,4 +527,7 @@ __flush_tlb_all(); return; } + +page_table_corruption: + pgtable_bad(address, regs, error_code); } diff -Nru a/arch/x86_64/mm/init.c b/arch/x86_64/mm/init.c --- a/arch/x86_64/mm/init.c 2004-08-25 22:01:54 -07:00 +++ b/arch/x86_64/mm/init.c 2004-08-25 22:01:54 -07:00 @@ -41,6 +41,10 @@ #define Dprintk(x...) #endif +#ifdef CONFIG_GART_IOMMU +extern int swiotlb; +#endif + extern char _stext[]; DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); @@ -396,6 +400,8 @@ return 0; } +extern int swiotlb_force; + static struct kcore_list kcore_mem, kcore_vmalloc, kcore_kernel, kcore_modules, kcore_vsyscall; @@ -405,7 +411,10 @@ int tmp; #ifdef CONFIG_SWIOTLB - if (!iommu_aperture && end_pfn >= 0xffffffff>>PAGE_SHIFT) + if (swiotlb_force) + swiotlb = 1; + if (!iommu_aperture && + (end_pfn >= 0xffffffff>>PAGE_SHIFT || force_iommu)) swiotlb = 1; if (swiotlb) swiotlb_init(); @@ -596,7 +605,16 @@ struct vm_area_struct *get_gate_vma(struct task_struct *tsk) { - return test_tsk_thread_flag(tsk, TIF_IA32) ? &gate32_vma : &gate_vma; +#ifdef CONFIG_IA32_EMULATION + if (test_tsk_thread_flag(tsk, TIF_IA32)) { + /* lookup code assumes the pages are present. set them up + now */ + if (map_syscall32(tsk->mm, 0xfffe000) < 0) + return NULL; + return &gate32_vma; + } +#endif + return &gate_vma; } int in_gate_area(struct task_struct *task, unsigned long addr) diff -Nru a/arch/x86_64/mm/numa.c b/arch/x86_64/mm/numa.c --- a/arch/x86_64/mm/numa.c 2004-08-25 22:01:56 -07:00 +++ b/arch/x86_64/mm/numa.c 2004-08-25 22:01:56 -07:00 @@ -135,7 +135,7 @@ zones[ZONE_NORMAL] = end_pfn - start_pfn; } - free_area_init_node(nodeid, NODE_DATA(nodeid), NULL, zones, + free_area_init_node(nodeid, NODE_DATA(nodeid), zones, start_pfn, NULL); } diff -Nru a/arch/x86_64/pci/Makefile b/arch/x86_64/pci/Makefile --- a/arch/x86_64/pci/Makefile 2004-08-25 22:01:54 -07:00 +++ b/arch/x86_64/pci/Makefile 2004-08-25 22:01:54 -07:00 @@ -3,7 +3,7 @@ # # Reuse the i386 PCI subsystem # -CFLAGS += -I arch/i386/pci +CFLAGS += -Iarch/i386/pci obj-y := i386.o obj-$(CONFIG_PCI_DIRECT)+= direct.o @@ -12,6 +12,8 @@ obj-y += legacy.o irq.o common.o # mmconfig has a 64bit special obj-$(CONFIG_PCI_MMCONFIG) += mmconfig.o + +obj-$(CONFIG_NUMA) += k8-bus.o direct-y += ../../i386/pci/direct.o acpi-y += ../../i386/pci/acpi.o diff -Nru a/arch/x86_64/pci/Makefile-BUS b/arch/x86_64/pci/Makefile-BUS --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/arch/x86_64/pci/Makefile-BUS 2004-08-25 22:01:56 -07:00 @@ -0,0 +1,22 @@ +# +# Makefile for X86_64 specific PCI routines +# +# Reuse the i386 PCI subsystem +# +CFLAGS += -I arch/i386/pci + +obj-y := i386.o +obj-$(CONFIG_PCI_DIRECT)+= direct.o +obj-y += fixup.o +obj-$(CONFIG_ACPI_PCI) += acpi.o +obj-y += legacy.o irq.o common.o +# mmconfig has a 64bit special +obj-$(CONFIG_PCI_MMCONFIG) += mmconfig.o + +direct-y += ../../i386/pci/direct.o +acpi-y += ../../i386/pci/acpi.o +legacy-y += ../../i386/pci/legacy.o +irq-y += ../../i386/pci/irq.o +common-y += ../../i386/pci/common.o +fixup-y += ../../i386/pci/fixup.o +i386-y += ../../i386/pci/i386.o diff -Nru a/arch/x86_64/pci/k8-bus.c b/arch/x86_64/pci/k8-bus.c --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/arch/x86_64/pci/k8-bus.c 2004-08-25 22:01:56 -07:00 @@ -0,0 +1,74 @@ +#include +#include +#include +#include + +/* + * This discovers the pcibus <-> node mapping on AMD K8. + * + * RED-PEN need to call this again on PCI hotplug + * RED-PEN empty cpus get reported wrong + */ + +#define NODE_ID_REGISTER 0x60 +#define NODE_ID(dword) (dword & 0x07) +#define LDT_BUS_NUMBER_REGISTER_0 0x94 +#define LDT_BUS_NUMBER_REGISTER_1 0xB4 +#define LDT_BUS_NUMBER_REGISTER_2 0xD4 +#define NR_LDT_BUS_NUMBER_REGISTERS 3 +#define SECONDARY_LDT_BUS_NUMBER(dword) ((dword >> 8) & 0xFF) +#define SUBORDINATE_LDT_BUS_NUMBER(dword) ((dword >> 16) & 0xFF) +#define PCI_DEVICE_ID_K8HTCONFIG 0x1100 + +/** + * fill_mp_bus_to_cpumask() + * fills the mp_bus_to_cpumask array based according to the LDT Bus Number + * Registers found in the K8 northbridge + */ +__init static int +fill_mp_bus_to_cpumask(void) +{ + struct pci_dev *nb_dev = NULL; + int i, j; + u32 ldtbus, nid; + static int lbnr[3] = { + LDT_BUS_NUMBER_REGISTER_0, + LDT_BUS_NUMBER_REGISTER_1, + LDT_BUS_NUMBER_REGISTER_2 + }; + + while ((nb_dev = pci_get_device(PCI_VENDOR_ID_AMD, + PCI_DEVICE_ID_K8HTCONFIG, nb_dev))) { + pci_read_config_dword(nb_dev, NODE_ID_REGISTER, &nid); + + for (i = 0; i < NR_LDT_BUS_NUMBER_REGISTERS; i++) { + pci_read_config_dword(nb_dev, lbnr[i], &ldtbus); + /* + * if there are no busses hanging off of the current + * ldt link then both the secondary and subordinate + * bus number fields are set to 0. + */ + if (!(SECONDARY_LDT_BUS_NUMBER(ldtbus) == 0 + && SUBORDINATE_LDT_BUS_NUMBER(ldtbus) == 0)) { + for (j = SECONDARY_LDT_BUS_NUMBER(ldtbus); + j <= SUBORDINATE_LDT_BUS_NUMBER(ldtbus); + j++) + pci_bus_to_cpumask[j] = + node_to_cpumask(NODE_ID(nid)); + } + } + } + + /* quick sanity check */ + for (i = 0; i < 256; i++) { + if (cpus_empty(pci_bus_to_cpumask[i])) { + printk(KERN_ERR + "k8-bus.c: bus %i has empty cpu mask\n", i); + pci_bus_to_cpumask[i] = CPU_MASK_ALL; + } + } + + return 0; +} + +fs_initcall(fill_mp_bus_to_cpumask); diff -Nru a/crypto/Kconfig b/crypto/Kconfig --- a/crypto/Kconfig 2004-08-25 22:01:56 -07:00 +++ b/crypto/Kconfig 2004-08-25 22:01:56 -07:00 @@ -67,6 +67,21 @@ This code also includes SHA-384, a 384 bit hash with 192 bits of security against collision attacks. +config CRYPTO_WHIRLPOOL + tristate "Whirlpool digest algorithm" + depends on CRYPTO + help + Whirlpool hash algorithm. + + Whirlpool is part of the NESSIE cryptographic primtives. + Whirlpool works on messages shorter than 2^256 bits and + produces a 512 bit hash. + + Whirlpool will be part of the ISO/IEC 10118-3:2003(E) standard + + See also: + http://planeta.terra.com.br/informatica/paulobarreto/WhirlpoolPage.html + config CRYPTO_DES tristate "DES and Triple DES EDE cipher algorithms" depends on CRYPTO diff -Nru a/crypto/Makefile b/crypto/Makefile --- a/crypto/Makefile 2004-08-25 22:01:56 -07:00 +++ b/crypto/Makefile 2004-08-25 22:01:56 -07:00 @@ -14,6 +14,7 @@ obj-$(CONFIG_CRYPTO_SHA1) += sha1.o obj-$(CONFIG_CRYPTO_SHA256) += sha256.o obj-$(CONFIG_CRYPTO_SHA512) += sha512.o +obj-$(CONFIG_CRYPTO_WHIRLPOOL) += whirlpool.o obj-$(CONFIG_CRYPTO_DES) += des.o obj-$(CONFIG_CRYPTO_BLOWFISH) += blowfish.o obj-$(CONFIG_CRYPTO_TWOFISH) += twofish.o diff -Nru a/crypto/tcrypt.c b/crypto/tcrypt.c --- a/crypto/tcrypt.c 2004-08-25 22:01:56 -07:00 +++ b/crypto/tcrypt.c 2004-08-25 22:01:56 -07:00 @@ -61,7 +61,8 @@ static char *check[] = { "des", "md5", "des3_ede", "rot13", "sha1", "sha256", "blowfish", "twofish", "serpent", "sha384", "sha512", "md4", "aes", "cast6", - "arc4", "michael_mic", "deflate", "crc32c", "tea", "xtea", NULL + "arc4", "michael_mic", "deflate", "crc32c", "tea", "xtea", + "whirlpool", NULL }; static void @@ -680,6 +681,7 @@ test_hash("sha384", sha384_tv_template, SHA384_TEST_VECTORS); test_hash("sha512", sha512_tv_template, SHA512_TEST_VECTORS); + test_hash("whirlpool", whirlpool_tv_template, WHIRLPOOL_TEST_VECTORS); test_deflate(); test_crc32c(); #ifdef CONFIG_CRYPTO_HMAC @@ -790,6 +792,11 @@ test_cipher ("khazad", MODE_ECB, ENCRYPT, khazad_enc_tv_template, KHAZAD_ENC_TEST_VECTORS); test_cipher ("khazad", MODE_ECB, DECRYPT, khazad_dec_tv_template, KHAZAD_DEC_TEST_VECTORS); break; + + case 22: + test_hash("whirlpool", whirlpool_tv_template, WHIRLPOOL_TEST_VECTORS); + break; + #ifdef CONFIG_CRYPTO_HMAC case 100: diff -Nru a/crypto/tcrypt.h b/crypto/tcrypt.h --- a/crypto/tcrypt.h 2004-08-25 22:01:56 -07:00 +++ b/crypto/tcrypt.h 2004-08-25 22:01:56 -07:00 @@ -301,6 +301,110 @@ }, }; + +/* + * WHIRLPOOL test vectors from Whirlpool package + * by Vincent Rijmen and Paulo S. L. M. Barreto as part of the NESSIE + * submission + */ +#define WHIRLPOOL_TEST_VECTORS 8 + +struct hash_testvec whirlpool_tv_template[] = { + { + .plaintext = "", + .psize = 0, + .digest = { 0x19, 0xFA, 0x61, 0xD7, 0x55, 0x22, 0xA4, 0x66, + 0x9B, 0x44, 0xE3, 0x9C, 0x1D, 0x2E, 0x17, 0x26, + 0xC5, 0x30, 0x23, 0x21, 0x30, 0xD4, 0x07, 0xF8, + 0x9A, 0xFE, 0xE0, 0x96, 0x49, 0x97, 0xF7, 0xA7, + 0x3E, 0x83, 0xBE, 0x69, 0x8B, 0x28, 0x8F, 0xEB, + 0xCF, 0x88, 0xE3, 0xE0, 0x3C, 0x4F, 0x07, 0x57, + 0xEA, 0x89, 0x64, 0xE5, 0x9B, 0x63, 0xD9, 0x37, + 0x08, 0xB1, 0x38, 0xCC, 0x42, 0xA6, 0x6E, 0xB3 }, + + + }, { + .plaintext = "a", + .psize = 1, + .digest = { 0x8A, 0xCA, 0x26, 0x02, 0x79, 0x2A, 0xEC, 0x6F, + 0x11, 0xA6, 0x72, 0x06, 0x53, 0x1F, 0xB7, 0xD7, + 0xF0, 0xDF, 0xF5, 0x94, 0x13, 0x14, 0x5E, 0x69, + 0x73, 0xC4, 0x50, 0x01, 0xD0, 0x08, 0x7B, 0x42, + 0xD1, 0x1B, 0xC6, 0x45, 0x41, 0x3A, 0xEF, 0xF6, + 0x3A, 0x42, 0x39, 0x1A, 0x39, 0x14, 0x5A, 0x59, + 0x1A, 0x92, 0x20, 0x0D, 0x56, 0x01, 0x95, 0xE5, + 0x3B, 0x47, 0x85, 0x84, 0xFD, 0xAE, 0x23, 0x1A }, + }, { + .plaintext = "abc", + .psize = 3, + .digest = { 0x4E, 0x24, 0x48, 0xA4, 0xC6, 0xF4, 0x86, 0xBB, + 0x16, 0xB6, 0x56, 0x2C, 0x73, 0xB4, 0x02, 0x0B, + 0xF3, 0x04, 0x3E, 0x3A, 0x73, 0x1B, 0xCE, 0x72, + 0x1A, 0xE1, 0xB3, 0x03, 0xD9, 0x7E, 0x6D, 0x4C, + 0x71, 0x81, 0xEE, 0xBD, 0xB6, 0xC5, 0x7E, 0x27, + 0x7D, 0x0E, 0x34, 0x95, 0x71, 0x14, 0xCB, 0xD6, + 0xC7, 0x97, 0xFC, 0x9D, 0x95, 0xD8, 0xB5, 0x82, + 0xD2, 0x25, 0x29, 0x20, 0x76, 0xD4, 0xEE, 0xF5 }, + }, { + .plaintext = "message digest", + .psize = 14, + .digest = { 0x37, 0x8C, 0x84, 0xA4, 0x12, 0x6E, 0x2D, 0xC6, + 0xE5, 0x6D, 0xCC, 0x74, 0x58, 0x37, 0x7A, 0xAC, + 0x83, 0x8D, 0x00, 0x03, 0x22, 0x30, 0xF5, 0x3C, + 0xE1, 0xF5, 0x70, 0x0C, 0x0F, 0xFB, 0x4D, 0x3B, + 0x84, 0x21, 0x55, 0x76, 0x59, 0xEF, 0x55, 0xC1, + 0x06, 0xB4, 0xB5, 0x2A, 0xC5, 0xA4, 0xAA, 0xA6, + 0x92, 0xED, 0x92, 0x00, 0x52, 0x83, 0x8F, 0x33, + 0x62, 0xE8, 0x6D, 0xBD, 0x37, 0xA8, 0x90, 0x3E }, + }, { + .plaintext = "abcdefghijklmnopqrstuvwxyz", + .psize = 26, + .digest = { 0xF1, 0xD7, 0x54, 0x66, 0x26, 0x36, 0xFF, 0xE9, + 0x2C, 0x82, 0xEB, 0xB9, 0x21, 0x2A, 0x48, 0x4A, + 0x8D, 0x38, 0x63, 0x1E, 0xAD, 0x42, 0x38, 0xF5, + 0x44, 0x2E, 0xE1, 0x3B, 0x80, 0x54, 0xE4, 0x1B, + 0x08, 0xBF, 0x2A, 0x92, 0x51, 0xC3, 0x0B, 0x6A, + 0x0B, 0x8A, 0xAE, 0x86, 0x17, 0x7A, 0xB4, 0xA6, + 0xF6, 0x8F, 0x67, 0x3E, 0x72, 0x07, 0x86, 0x5D, + 0x5D, 0x98, 0x19, 0xA3, 0xDB, 0xA4, 0xEB, 0x3B }, + }, { + .plaintext = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz0123456789", + .psize = 62, + .digest = { 0xDC, 0x37, 0xE0, 0x08, 0xCF, 0x9E, 0xE6, 0x9B, + 0xF1, 0x1F, 0x00, 0xED, 0x9A, 0xBA, 0x26, 0x90, + 0x1D, 0xD7, 0xC2, 0x8C, 0xDE, 0xC0, 0x66, 0xCC, + 0x6A, 0xF4, 0x2E, 0x40, 0xF8, 0x2F, 0x3A, 0x1E, + 0x08, 0xEB, 0xA2, 0x66, 0x29, 0x12, 0x9D, 0x8F, + 0xB7, 0xCB, 0x57, 0x21, 0x1B, 0x92, 0x81, 0xA6, + 0x55, 0x17, 0xCC, 0x87, 0x9D, 0x7B, 0x96, 0x21, + 0x42, 0xC6, 0x5F, 0x5A, 0x7A, 0xF0, 0x14, 0x67 }, + }, { + .plaintext = "1234567890123456789012345678901234567890" + "1234567890123456789012345678901234567890", + .psize = 80, + .digest = { 0x46, 0x6E, 0xF1, 0x8B, 0xAB, 0xB0, 0x15, 0x4D, + 0x25, 0xB9, 0xD3, 0x8A, 0x64, 0x14, 0xF5, 0xC0, + 0x87, 0x84, 0x37, 0x2B, 0xCC, 0xB2, 0x04, 0xD6, + 0x54, 0x9C, 0x4A, 0xFA, 0xDB, 0x60, 0x14, 0x29, + 0x4D, 0x5B, 0xD8, 0xDF, 0x2A, 0x6C, 0x44, 0xE5, + 0x38, 0xCD, 0x04, 0x7B, 0x26, 0x81, 0xA5, 0x1A, + 0x2C, 0x60, 0x48, 0x1E, 0x88, 0xC5, 0xA2, 0x0B, + 0x2C, 0x2A, 0x80, 0xCF, 0x3A, 0x9A, 0x08, 0x3B }, + }, { + .plaintext = "abcdbcdecdefdefgefghfghighijhijk", + .psize = 32, + .digest = { 0x2A, 0x98, 0x7E, 0xA4, 0x0F, 0x91, 0x70, 0x61, + 0xF5, 0xD6, 0xF0, 0xA0, 0xE4, 0x64, 0x4F, 0x48, + 0x8A, 0x7A, 0x5A, 0x52, 0xDE, 0xEE, 0x65, 0x62, + 0x07, 0xC5, 0x62, 0xF9, 0x88, 0xE9, 0x5C, 0x69, + 0x16, 0xBD, 0xC8, 0x03, 0x1B, 0xC5, 0xBE, 0x1B, + 0x7B, 0x94, 0x76, 0x39, 0xFE, 0x05, 0x0B, 0x56, + 0x93, 0x9B, 0xAA, 0xA0, 0xAD, 0xFF, 0x9A, 0xE6, + 0x74, 0x5B, 0x7B, 0x18, 0x1C, 0x3B, 0xE3, 0xFD }, + }, +}; + #ifdef CONFIG_CRYPTO_HMAC /* * HMAC-MD5 test vectors from RFC2202 diff -Nru a/crypto/whirlpool.c b/crypto/whirlpool.c --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/crypto/whirlpool.c 2004-08-25 22:01:56 -07:00 @@ -0,0 +1,1131 @@ +/* + * Cryptographic API. + * + * Whirlpool hashing Algorithm + * + * The Whirlpool algorithm was developed by Paulo S. L. M. Barreto and + * Vincent Rijmen. It has been selected as one of cryptographic + * primitives by the NESSIE project http://www.cryptonessie.org/ + * + * The original authors have disclaimed all copyright interest in this + * code and thus put it in the public domain. The subsequent authors + * have put this under the GNU General Public License. + * + * By Aaron Grothe ajgrothe@yahoo.com, August 23, 2004 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + */ +#include +#include +#include +#include +#include + +#define WHIRLPOOL_DIGEST_SIZE 64 +#define WHIRLPOOL_BLOCK_SIZE 64 +#define WHIRLPOOL_LENGTHBYTES 32 + +#define WHIRLPOOL_ROUNDS 10 + +struct whirlpool_ctx { + u8 bitLength[WHIRLPOOL_LENGTHBYTES]; + u8 buffer[WHIRLPOOL_BLOCK_SIZE]; + int bufferBits; + int bufferPos; + u64 hash[WHIRLPOOL_DIGEST_SIZE/8]; +}; + +/* + * Though Whirlpool is endianness-neutral, the encryption tables are listed + * in BIG-ENDIAN format, which is adopted throughout this implementation + * (but little-endian notation would be equally suitable if consistently + * employed). + */ + +static const u64 C0[256] = { + 0x18186018c07830d8ULL, 0x23238c2305af4626ULL, 0xc6c63fc67ef991b8ULL, + 0xe8e887e8136fcdfbULL, 0x878726874ca113cbULL, 0xb8b8dab8a9626d11ULL, + 0x0101040108050209ULL, 0x4f4f214f426e9e0dULL, 0x3636d836adee6c9bULL, + 0xa6a6a2a6590451ffULL, 0xd2d26fd2debdb90cULL, 0xf5f5f3f5fb06f70eULL, + 0x7979f979ef80f296ULL, 0x6f6fa16f5fcede30ULL, 0x91917e91fcef3f6dULL, + 0x52525552aa07a4f8ULL, 0x60609d6027fdc047ULL, 0xbcbccabc89766535ULL, + 0x9b9b569baccd2b37ULL, 0x8e8e028e048c018aULL, 0xa3a3b6a371155bd2ULL, + 0x0c0c300c603c186cULL, 0x7b7bf17bff8af684ULL, 0x3535d435b5e16a80ULL, + 0x1d1d741de8693af5ULL, 0xe0e0a7e05347ddb3ULL, 0xd7d77bd7f6acb321ULL, + 0xc2c22fc25eed999cULL, 0x2e2eb82e6d965c43ULL, 0x4b4b314b627a9629ULL, + 0xfefedffea321e15dULL, 0x575741578216aed5ULL, 0x15155415a8412abdULL, + 0x7777c1779fb6eee8ULL, 0x3737dc37a5eb6e92ULL, 0xe5e5b3e57b56d79eULL, + 0x9f9f469f8cd92313ULL, 0xf0f0e7f0d317fd23ULL, 0x4a4a354a6a7f9420ULL, + 0xdada4fda9e95a944ULL, 0x58587d58fa25b0a2ULL, 0xc9c903c906ca8fcfULL, + 0x2929a429558d527cULL, 0x0a0a280a5022145aULL, 0xb1b1feb1e14f7f50ULL, + 0xa0a0baa0691a5dc9ULL, 0x6b6bb16b7fdad614ULL, 0x85852e855cab17d9ULL, + 0xbdbdcebd8173673cULL, 0x5d5d695dd234ba8fULL, 0x1010401080502090ULL, + 0xf4f4f7f4f303f507ULL, 0xcbcb0bcb16c08bddULL, 0x3e3ef83eedc67cd3ULL, + 0x0505140528110a2dULL, 0x676781671fe6ce78ULL, 0xe4e4b7e47353d597ULL, + 0x27279c2725bb4e02ULL, 0x4141194132588273ULL, 0x8b8b168b2c9d0ba7ULL, + 0xa7a7a6a7510153f6ULL, 0x7d7de97dcf94fab2ULL, 0x95956e95dcfb3749ULL, + 0xd8d847d88e9fad56ULL, 0xfbfbcbfb8b30eb70ULL, 0xeeee9fee2371c1cdULL, + 0x7c7ced7cc791f8bbULL, 0x6666856617e3cc71ULL, 0xdddd53dda68ea77bULL, + 0x17175c17b84b2eafULL, 0x4747014702468e45ULL, 0x9e9e429e84dc211aULL, + 0xcaca0fca1ec589d4ULL, 0x2d2db42d75995a58ULL, 0xbfbfc6bf9179632eULL, + 0x07071c07381b0e3fULL, 0xadad8ead012347acULL, 0x5a5a755aea2fb4b0ULL, + 0x838336836cb51befULL, 0x3333cc3385ff66b6ULL, 0x636391633ff2c65cULL, + 0x02020802100a0412ULL, 0xaaaa92aa39384993ULL, 0x7171d971afa8e2deULL, + 0xc8c807c80ecf8dc6ULL, 0x19196419c87d32d1ULL, 0x494939497270923bULL, + 0xd9d943d9869aaf5fULL, 0xf2f2eff2c31df931ULL, 0xe3e3abe34b48dba8ULL, + 0x5b5b715be22ab6b9ULL, 0x88881a8834920dbcULL, 0x9a9a529aa4c8293eULL, + 0x262698262dbe4c0bULL, 0x3232c8328dfa64bfULL, 0xb0b0fab0e94a7d59ULL, + 0xe9e983e91b6acff2ULL, 0x0f0f3c0f78331e77ULL, 0xd5d573d5e6a6b733ULL, + 0x80803a8074ba1df4ULL, 0xbebec2be997c6127ULL, 0xcdcd13cd26de87ebULL, + 0x3434d034bde46889ULL, 0x48483d487a759032ULL, 0xffffdbffab24e354ULL, + 0x7a7af57af78ff48dULL, 0x90907a90f4ea3d64ULL, 0x5f5f615fc23ebe9dULL, + 0x202080201da0403dULL, 0x6868bd6867d5d00fULL, 0x1a1a681ad07234caULL, + 0xaeae82ae192c41b7ULL, 0xb4b4eab4c95e757dULL, 0x54544d549a19a8ceULL, + 0x93937693ece53b7fULL, 0x222288220daa442fULL, 0x64648d6407e9c863ULL, + 0xf1f1e3f1db12ff2aULL, 0x7373d173bfa2e6ccULL, 0x12124812905a2482ULL, + 0x40401d403a5d807aULL, 0x0808200840281048ULL, 0xc3c32bc356e89b95ULL, + 0xecec97ec337bc5dfULL, 0xdbdb4bdb9690ab4dULL, 0xa1a1bea1611f5fc0ULL, + 0x8d8d0e8d1c830791ULL, 0x3d3df43df5c97ac8ULL, 0x97976697ccf1335bULL, + 0x0000000000000000ULL, 0xcfcf1bcf36d483f9ULL, 0x2b2bac2b4587566eULL, + 0x7676c57697b3ece1ULL, 0x8282328264b019e6ULL, 0xd6d67fd6fea9b128ULL, + 0x1b1b6c1bd87736c3ULL, 0xb5b5eeb5c15b7774ULL, 0xafaf86af112943beULL, + 0x6a6ab56a77dfd41dULL, 0x50505d50ba0da0eaULL, 0x45450945124c8a57ULL, + 0xf3f3ebf3cb18fb38ULL, 0x3030c0309df060adULL, 0xefef9bef2b74c3c4ULL, + 0x3f3ffc3fe5c37edaULL, 0x55554955921caac7ULL, 0xa2a2b2a2791059dbULL, + 0xeaea8fea0365c9e9ULL, 0x656589650fecca6aULL, 0xbabad2bab9686903ULL, + 0x2f2fbc2f65935e4aULL, 0xc0c027c04ee79d8eULL, 0xdede5fdebe81a160ULL, + 0x1c1c701ce06c38fcULL, 0xfdfdd3fdbb2ee746ULL, 0x4d4d294d52649a1fULL, + 0x92927292e4e03976ULL, 0x7575c9758fbceafaULL, 0x06061806301e0c36ULL, + 0x8a8a128a249809aeULL, 0xb2b2f2b2f940794bULL, 0xe6e6bfe66359d185ULL, + 0x0e0e380e70361c7eULL, 0x1f1f7c1ff8633ee7ULL, 0x6262956237f7c455ULL, + 0xd4d477d4eea3b53aULL, 0xa8a89aa829324d81ULL, 0x96966296c4f43152ULL, + 0xf9f9c3f99b3aef62ULL, 0xc5c533c566f697a3ULL, 0x2525942535b14a10ULL, + 0x59597959f220b2abULL, 0x84842a8454ae15d0ULL, 0x7272d572b7a7e4c5ULL, + 0x3939e439d5dd72ecULL, 0x4c4c2d4c5a619816ULL, 0x5e5e655eca3bbc94ULL, + 0x7878fd78e785f09fULL, 0x3838e038ddd870e5ULL, 0x8c8c0a8c14860598ULL, + 0xd1d163d1c6b2bf17ULL, 0xa5a5aea5410b57e4ULL, 0xe2e2afe2434dd9a1ULL, + 0x616199612ff8c24eULL, 0xb3b3f6b3f1457b42ULL, 0x2121842115a54234ULL, + 0x9c9c4a9c94d62508ULL, 0x1e1e781ef0663ceeULL, 0x4343114322528661ULL, + 0xc7c73bc776fc93b1ULL, 0xfcfcd7fcb32be54fULL, 0x0404100420140824ULL, + 0x51515951b208a2e3ULL, 0x99995e99bcc72f25ULL, 0x6d6da96d4fc4da22ULL, + 0x0d0d340d68391a65ULL, 0xfafacffa8335e979ULL, 0xdfdf5bdfb684a369ULL, + 0x7e7ee57ed79bfca9ULL, 0x242490243db44819ULL, 0x3b3bec3bc5d776feULL, + 0xabab96ab313d4b9aULL, 0xcece1fce3ed181f0ULL, 0x1111441188552299ULL, + 0x8f8f068f0c890383ULL, 0x4e4e254e4a6b9c04ULL, 0xb7b7e6b7d1517366ULL, + 0xebeb8beb0b60cbe0ULL, 0x3c3cf03cfdcc78c1ULL, 0x81813e817cbf1ffdULL, + 0x94946a94d4fe3540ULL, 0xf7f7fbf7eb0cf31cULL, 0xb9b9deb9a1676f18ULL, + 0x13134c13985f268bULL, 0x2c2cb02c7d9c5851ULL, 0xd3d36bd3d6b8bb05ULL, + 0xe7e7bbe76b5cd38cULL, 0x6e6ea56e57cbdc39ULL, 0xc4c437c46ef395aaULL, + 0x03030c03180f061bULL, 0x565645568a13acdcULL, 0x44440d441a49885eULL, + 0x7f7fe17fdf9efea0ULL, 0xa9a99ea921374f88ULL, 0x2a2aa82a4d825467ULL, + 0xbbbbd6bbb16d6b0aULL, 0xc1c123c146e29f87ULL, 0x53535153a202a6f1ULL, + 0xdcdc57dcae8ba572ULL, 0x0b0b2c0b58271653ULL, 0x9d9d4e9d9cd32701ULL, + 0x6c6cad6c47c1d82bULL, 0x3131c43195f562a4ULL, 0x7474cd7487b9e8f3ULL, + 0xf6f6fff6e309f115ULL, 0x464605460a438c4cULL, 0xacac8aac092645a5ULL, + 0x89891e893c970fb5ULL, 0x14145014a04428b4ULL, 0xe1e1a3e15b42dfbaULL, + 0x16165816b04e2ca6ULL, 0x3a3ae83acdd274f7ULL, 0x6969b9696fd0d206ULL, + 0x09092409482d1241ULL, 0x7070dd70a7ade0d7ULL, 0xb6b6e2b6d954716fULL, + 0xd0d067d0ceb7bd1eULL, 0xeded93ed3b7ec7d6ULL, 0xcccc17cc2edb85e2ULL, + 0x424215422a578468ULL, 0x98985a98b4c22d2cULL, 0xa4a4aaa4490e55edULL, + 0x2828a0285d885075ULL, 0x5c5c6d5cda31b886ULL, 0xf8f8c7f8933fed6bULL, + 0x8686228644a411c2ULL, +}; + +static const u64 C1[256] = { + 0xd818186018c07830ULL, 0x2623238c2305af46ULL, 0xb8c6c63fc67ef991ULL, + 0xfbe8e887e8136fcdULL, 0xcb878726874ca113ULL, 0x11b8b8dab8a9626dULL, + 0x0901010401080502ULL, 0x0d4f4f214f426e9eULL, 0x9b3636d836adee6cULL, + 0xffa6a6a2a6590451ULL, 0x0cd2d26fd2debdb9ULL, 0x0ef5f5f3f5fb06f7ULL, + 0x967979f979ef80f2ULL, 0x306f6fa16f5fcedeULL, 0x6d91917e91fcef3fULL, + 0xf852525552aa07a4ULL, 0x4760609d6027fdc0ULL, 0x35bcbccabc897665ULL, + 0x379b9b569baccd2bULL, 0x8a8e8e028e048c01ULL, 0xd2a3a3b6a371155bULL, + 0x6c0c0c300c603c18ULL, 0x847b7bf17bff8af6ULL, 0x803535d435b5e16aULL, + 0xf51d1d741de8693aULL, 0xb3e0e0a7e05347ddULL, 0x21d7d77bd7f6acb3ULL, + 0x9cc2c22fc25eed99ULL, 0x432e2eb82e6d965cULL, 0x294b4b314b627a96ULL, + 0x5dfefedffea321e1ULL, 0xd5575741578216aeULL, 0xbd15155415a8412aULL, + 0xe87777c1779fb6eeULL, 0x923737dc37a5eb6eULL, 0x9ee5e5b3e57b56d7ULL, + 0x139f9f469f8cd923ULL, 0x23f0f0e7f0d317fdULL, 0x204a4a354a6a7f94ULL, + 0x44dada4fda9e95a9ULL, 0xa258587d58fa25b0ULL, 0xcfc9c903c906ca8fULL, + 0x7c2929a429558d52ULL, 0x5a0a0a280a502214ULL, 0x50b1b1feb1e14f7fULL, + 0xc9a0a0baa0691a5dULL, 0x146b6bb16b7fdad6ULL, 0xd985852e855cab17ULL, + 0x3cbdbdcebd817367ULL, 0x8f5d5d695dd234baULL, 0x9010104010805020ULL, + 0x07f4f4f7f4f303f5ULL, 0xddcbcb0bcb16c08bULL, 0xd33e3ef83eedc67cULL, + 0x2d0505140528110aULL, 0x78676781671fe6ceULL, 0x97e4e4b7e47353d5ULL, + 0x0227279c2725bb4eULL, 0x7341411941325882ULL, 0xa78b8b168b2c9d0bULL, + 0xf6a7a7a6a7510153ULL, 0xb27d7de97dcf94faULL, 0x4995956e95dcfb37ULL, + 0x56d8d847d88e9fadULL, 0x70fbfbcbfb8b30ebULL, 0xcdeeee9fee2371c1ULL, + 0xbb7c7ced7cc791f8ULL, 0x716666856617e3ccULL, 0x7bdddd53dda68ea7ULL, + 0xaf17175c17b84b2eULL, 0x454747014702468eULL, 0x1a9e9e429e84dc21ULL, + 0xd4caca0fca1ec589ULL, 0x582d2db42d75995aULL, 0x2ebfbfc6bf917963ULL, + 0x3f07071c07381b0eULL, 0xacadad8ead012347ULL, 0xb05a5a755aea2fb4ULL, + 0xef838336836cb51bULL, 0xb63333cc3385ff66ULL, 0x5c636391633ff2c6ULL, + 0x1202020802100a04ULL, 0x93aaaa92aa393849ULL, 0xde7171d971afa8e2ULL, + 0xc6c8c807c80ecf8dULL, 0xd119196419c87d32ULL, 0x3b49493949727092ULL, + 0x5fd9d943d9869aafULL, 0x31f2f2eff2c31df9ULL, 0xa8e3e3abe34b48dbULL, + 0xb95b5b715be22ab6ULL, 0xbc88881a8834920dULL, 0x3e9a9a529aa4c829ULL, + 0x0b262698262dbe4cULL, 0xbf3232c8328dfa64ULL, 0x59b0b0fab0e94a7dULL, + 0xf2e9e983e91b6acfULL, 0x770f0f3c0f78331eULL, 0x33d5d573d5e6a6b7ULL, + 0xf480803a8074ba1dULL, 0x27bebec2be997c61ULL, 0xebcdcd13cd26de87ULL, + 0x893434d034bde468ULL, 0x3248483d487a7590ULL, 0x54ffffdbffab24e3ULL, + 0x8d7a7af57af78ff4ULL, 0x6490907a90f4ea3dULL, 0x9d5f5f615fc23ebeULL, + 0x3d202080201da040ULL, 0x0f6868bd6867d5d0ULL, 0xca1a1a681ad07234ULL, + 0xb7aeae82ae192c41ULL, 0x7db4b4eab4c95e75ULL, 0xce54544d549a19a8ULL, + 0x7f93937693ece53bULL, 0x2f222288220daa44ULL, 0x6364648d6407e9c8ULL, + 0x2af1f1e3f1db12ffULL, 0xcc7373d173bfa2e6ULL, 0x8212124812905a24ULL, + 0x7a40401d403a5d80ULL, 0x4808082008402810ULL, 0x95c3c32bc356e89bULL, + 0xdfecec97ec337bc5ULL, 0x4ddbdb4bdb9690abULL, 0xc0a1a1bea1611f5fULL, + 0x918d8d0e8d1c8307ULL, 0xc83d3df43df5c97aULL, 0x5b97976697ccf133ULL, + 0x0000000000000000ULL, 0xf9cfcf1bcf36d483ULL, 0x6e2b2bac2b458756ULL, + 0xe17676c57697b3ecULL, 0xe68282328264b019ULL, 0x28d6d67fd6fea9b1ULL, + 0xc31b1b6c1bd87736ULL, 0x74b5b5eeb5c15b77ULL, 0xbeafaf86af112943ULL, + 0x1d6a6ab56a77dfd4ULL, 0xea50505d50ba0da0ULL, 0x5745450945124c8aULL, + 0x38f3f3ebf3cb18fbULL, 0xad3030c0309df060ULL, 0xc4efef9bef2b74c3ULL, + 0xda3f3ffc3fe5c37eULL, 0xc755554955921caaULL, 0xdba2a2b2a2791059ULL, + 0xe9eaea8fea0365c9ULL, 0x6a656589650feccaULL, 0x03babad2bab96869ULL, + 0x4a2f2fbc2f65935eULL, 0x8ec0c027c04ee79dULL, 0x60dede5fdebe81a1ULL, + 0xfc1c1c701ce06c38ULL, 0x46fdfdd3fdbb2ee7ULL, 0x1f4d4d294d52649aULL, + 0x7692927292e4e039ULL, 0xfa7575c9758fbceaULL, 0x3606061806301e0cULL, + 0xae8a8a128a249809ULL, 0x4bb2b2f2b2f94079ULL, 0x85e6e6bfe66359d1ULL, + 0x7e0e0e380e70361cULL, 0xe71f1f7c1ff8633eULL, 0x556262956237f7c4ULL, + 0x3ad4d477d4eea3b5ULL, 0x81a8a89aa829324dULL, 0x5296966296c4f431ULL, + 0x62f9f9c3f99b3aefULL, 0xa3c5c533c566f697ULL, 0x102525942535b14aULL, + 0xab59597959f220b2ULL, 0xd084842a8454ae15ULL, 0xc57272d572b7a7e4ULL, + 0xec3939e439d5dd72ULL, 0x164c4c2d4c5a6198ULL, 0x945e5e655eca3bbcULL, + 0x9f7878fd78e785f0ULL, 0xe53838e038ddd870ULL, 0x988c8c0a8c148605ULL, + 0x17d1d163d1c6b2bfULL, 0xe4a5a5aea5410b57ULL, 0xa1e2e2afe2434dd9ULL, + 0x4e616199612ff8c2ULL, 0x42b3b3f6b3f1457bULL, 0x342121842115a542ULL, + 0x089c9c4a9c94d625ULL, 0xee1e1e781ef0663cULL, 0x6143431143225286ULL, + 0xb1c7c73bc776fc93ULL, 0x4ffcfcd7fcb32be5ULL, 0x2404041004201408ULL, + 0xe351515951b208a2ULL, 0x2599995e99bcc72fULL, 0x226d6da96d4fc4daULL, + 0x650d0d340d68391aULL, 0x79fafacffa8335e9ULL, 0x69dfdf5bdfb684a3ULL, + 0xa97e7ee57ed79bfcULL, 0x19242490243db448ULL, 0xfe3b3bec3bc5d776ULL, + 0x9aabab96ab313d4bULL, 0xf0cece1fce3ed181ULL, 0x9911114411885522ULL, + 0x838f8f068f0c8903ULL, 0x044e4e254e4a6b9cULL, 0x66b7b7e6b7d15173ULL, + 0xe0ebeb8beb0b60cbULL, 0xc13c3cf03cfdcc78ULL, 0xfd81813e817cbf1fULL, + 0x4094946a94d4fe35ULL, 0x1cf7f7fbf7eb0cf3ULL, 0x18b9b9deb9a1676fULL, + 0x8b13134c13985f26ULL, 0x512c2cb02c7d9c58ULL, 0x05d3d36bd3d6b8bbULL, + 0x8ce7e7bbe76b5cd3ULL, 0x396e6ea56e57cbdcULL, 0xaac4c437c46ef395ULL, + 0x1b03030c03180f06ULL, 0xdc565645568a13acULL, 0x5e44440d441a4988ULL, + 0xa07f7fe17fdf9efeULL, 0x88a9a99ea921374fULL, 0x672a2aa82a4d8254ULL, + 0x0abbbbd6bbb16d6bULL, 0x87c1c123c146e29fULL, 0xf153535153a202a6ULL, + 0x72dcdc57dcae8ba5ULL, 0x530b0b2c0b582716ULL, 0x019d9d4e9d9cd327ULL, + 0x2b6c6cad6c47c1d8ULL, 0xa43131c43195f562ULL, 0xf37474cd7487b9e8ULL, + 0x15f6f6fff6e309f1ULL, 0x4c464605460a438cULL, 0xa5acac8aac092645ULL, + 0xb589891e893c970fULL, 0xb414145014a04428ULL, 0xbae1e1a3e15b42dfULL, + 0xa616165816b04e2cULL, 0xf73a3ae83acdd274ULL, 0x066969b9696fd0d2ULL, + 0x4109092409482d12ULL, 0xd77070dd70a7ade0ULL, 0x6fb6b6e2b6d95471ULL, + 0x1ed0d067d0ceb7bdULL, 0xd6eded93ed3b7ec7ULL, 0xe2cccc17cc2edb85ULL, + 0x68424215422a5784ULL, 0x2c98985a98b4c22dULL, 0xeda4a4aaa4490e55ULL, + 0x752828a0285d8850ULL, 0x865c5c6d5cda31b8ULL, 0x6bf8f8c7f8933fedULL, + 0xc28686228644a411ULL, +}; + +static const u64 C2[256] = { + 0x30d818186018c078ULL, 0x462623238c2305afULL, 0x91b8c6c63fc67ef9ULL, + 0xcdfbe8e887e8136fULL, 0x13cb878726874ca1ULL, 0x6d11b8b8dab8a962ULL, + 0x0209010104010805ULL, 0x9e0d4f4f214f426eULL, 0x6c9b3636d836adeeULL, + 0x51ffa6a6a2a65904ULL, 0xb90cd2d26fd2debdULL, 0xf70ef5f5f3f5fb06ULL, + 0xf2967979f979ef80ULL, 0xde306f6fa16f5fceULL, 0x3f6d91917e91fcefULL, + 0xa4f852525552aa07ULL, 0xc04760609d6027fdULL, 0x6535bcbccabc8976ULL, + 0x2b379b9b569baccdULL, 0x018a8e8e028e048cULL, 0x5bd2a3a3b6a37115ULL, + 0x186c0c0c300c603cULL, 0xf6847b7bf17bff8aULL, 0x6a803535d435b5e1ULL, + 0x3af51d1d741de869ULL, 0xddb3e0e0a7e05347ULL, 0xb321d7d77bd7f6acULL, + 0x999cc2c22fc25eedULL, 0x5c432e2eb82e6d96ULL, 0x96294b4b314b627aULL, + 0xe15dfefedffea321ULL, 0xaed5575741578216ULL, 0x2abd15155415a841ULL, + 0xeee87777c1779fb6ULL, 0x6e923737dc37a5ebULL, 0xd79ee5e5b3e57b56ULL, + 0x23139f9f469f8cd9ULL, 0xfd23f0f0e7f0d317ULL, 0x94204a4a354a6a7fULL, + 0xa944dada4fda9e95ULL, 0xb0a258587d58fa25ULL, 0x8fcfc9c903c906caULL, + 0x527c2929a429558dULL, 0x145a0a0a280a5022ULL, 0x7f50b1b1feb1e14fULL, + 0x5dc9a0a0baa0691aULL, 0xd6146b6bb16b7fdaULL, 0x17d985852e855cabULL, + 0x673cbdbdcebd8173ULL, 0xba8f5d5d695dd234ULL, 0x2090101040108050ULL, + 0xf507f4f4f7f4f303ULL, 0x8bddcbcb0bcb16c0ULL, 0x7cd33e3ef83eedc6ULL, + 0x0a2d050514052811ULL, 0xce78676781671fe6ULL, 0xd597e4e4b7e47353ULL, + 0x4e0227279c2725bbULL, 0x8273414119413258ULL, 0x0ba78b8b168b2c9dULL, + 0x53f6a7a7a6a75101ULL, 0xfab27d7de97dcf94ULL, 0x374995956e95dcfbULL, + 0xad56d8d847d88e9fULL, 0xeb70fbfbcbfb8b30ULL, 0xc1cdeeee9fee2371ULL, + 0xf8bb7c7ced7cc791ULL, 0xcc716666856617e3ULL, 0xa77bdddd53dda68eULL, + 0x2eaf17175c17b84bULL, 0x8e45474701470246ULL, 0x211a9e9e429e84dcULL, + 0x89d4caca0fca1ec5ULL, 0x5a582d2db42d7599ULL, 0x632ebfbfc6bf9179ULL, + 0x0e3f07071c07381bULL, 0x47acadad8ead0123ULL, 0xb4b05a5a755aea2fULL, + 0x1bef838336836cb5ULL, 0x66b63333cc3385ffULL, 0xc65c636391633ff2ULL, + 0x041202020802100aULL, 0x4993aaaa92aa3938ULL, 0xe2de7171d971afa8ULL, + 0x8dc6c8c807c80ecfULL, 0x32d119196419c87dULL, 0x923b494939497270ULL, + 0xaf5fd9d943d9869aULL, 0xf931f2f2eff2c31dULL, 0xdba8e3e3abe34b48ULL, + 0xb6b95b5b715be22aULL, 0x0dbc88881a883492ULL, 0x293e9a9a529aa4c8ULL, + 0x4c0b262698262dbeULL, 0x64bf3232c8328dfaULL, 0x7d59b0b0fab0e94aULL, + 0xcff2e9e983e91b6aULL, 0x1e770f0f3c0f7833ULL, 0xb733d5d573d5e6a6ULL, + 0x1df480803a8074baULL, 0x6127bebec2be997cULL, 0x87ebcdcd13cd26deULL, + 0x68893434d034bde4ULL, 0x903248483d487a75ULL, 0xe354ffffdbffab24ULL, + 0xf48d7a7af57af78fULL, 0x3d6490907a90f4eaULL, 0xbe9d5f5f615fc23eULL, + 0x403d202080201da0ULL, 0xd00f6868bd6867d5ULL, 0x34ca1a1a681ad072ULL, + 0x41b7aeae82ae192cULL, 0x757db4b4eab4c95eULL, 0xa8ce54544d549a19ULL, + 0x3b7f93937693ece5ULL, 0x442f222288220daaULL, 0xc86364648d6407e9ULL, + 0xff2af1f1e3f1db12ULL, 0xe6cc7373d173bfa2ULL, 0x248212124812905aULL, + 0x807a40401d403a5dULL, 0x1048080820084028ULL, 0x9b95c3c32bc356e8ULL, + 0xc5dfecec97ec337bULL, 0xab4ddbdb4bdb9690ULL, 0x5fc0a1a1bea1611fULL, + 0x07918d8d0e8d1c83ULL, 0x7ac83d3df43df5c9ULL, 0x335b97976697ccf1ULL, + 0x0000000000000000ULL, 0x83f9cfcf1bcf36d4ULL, 0x566e2b2bac2b4587ULL, + 0xece17676c57697b3ULL, 0x19e68282328264b0ULL, 0xb128d6d67fd6fea9ULL, + 0x36c31b1b6c1bd877ULL, 0x7774b5b5eeb5c15bULL, 0x43beafaf86af1129ULL, + 0xd41d6a6ab56a77dfULL, 0xa0ea50505d50ba0dULL, 0x8a5745450945124cULL, + 0xfb38f3f3ebf3cb18ULL, 0x60ad3030c0309df0ULL, 0xc3c4efef9bef2b74ULL, + 0x7eda3f3ffc3fe5c3ULL, 0xaac755554955921cULL, 0x59dba2a2b2a27910ULL, + 0xc9e9eaea8fea0365ULL, 0xca6a656589650fecULL, 0x6903babad2bab968ULL, + 0x5e4a2f2fbc2f6593ULL, 0x9d8ec0c027c04ee7ULL, 0xa160dede5fdebe81ULL, + 0x38fc1c1c701ce06cULL, 0xe746fdfdd3fdbb2eULL, 0x9a1f4d4d294d5264ULL, + 0x397692927292e4e0ULL, 0xeafa7575c9758fbcULL, 0x0c3606061806301eULL, + 0x09ae8a8a128a2498ULL, 0x794bb2b2f2b2f940ULL, 0xd185e6e6bfe66359ULL, + 0x1c7e0e0e380e7036ULL, 0x3ee71f1f7c1ff863ULL, 0xc4556262956237f7ULL, + 0xb53ad4d477d4eea3ULL, 0x4d81a8a89aa82932ULL, 0x315296966296c4f4ULL, + 0xef62f9f9c3f99b3aULL, 0x97a3c5c533c566f6ULL, 0x4a102525942535b1ULL, + 0xb2ab59597959f220ULL, 0x15d084842a8454aeULL, 0xe4c57272d572b7a7ULL, + 0x72ec3939e439d5ddULL, 0x98164c4c2d4c5a61ULL, 0xbc945e5e655eca3bULL, + 0xf09f7878fd78e785ULL, 0x70e53838e038ddd8ULL, 0x05988c8c0a8c1486ULL, + 0xbf17d1d163d1c6b2ULL, 0x57e4a5a5aea5410bULL, 0xd9a1e2e2afe2434dULL, + 0xc24e616199612ff8ULL, 0x7b42b3b3f6b3f145ULL, 0x42342121842115a5ULL, + 0x25089c9c4a9c94d6ULL, 0x3cee1e1e781ef066ULL, 0x8661434311432252ULL, + 0x93b1c7c73bc776fcULL, 0xe54ffcfcd7fcb32bULL, 0x0824040410042014ULL, + 0xa2e351515951b208ULL, 0x2f2599995e99bcc7ULL, 0xda226d6da96d4fc4ULL, + 0x1a650d0d340d6839ULL, 0xe979fafacffa8335ULL, 0xa369dfdf5bdfb684ULL, + 0xfca97e7ee57ed79bULL, 0x4819242490243db4ULL, 0x76fe3b3bec3bc5d7ULL, + 0x4b9aabab96ab313dULL, 0x81f0cece1fce3ed1ULL, 0x2299111144118855ULL, + 0x03838f8f068f0c89ULL, 0x9c044e4e254e4a6bULL, 0x7366b7b7e6b7d151ULL, + 0xcbe0ebeb8beb0b60ULL, 0x78c13c3cf03cfdccULL, 0x1ffd81813e817cbfULL, + 0x354094946a94d4feULL, 0xf31cf7f7fbf7eb0cULL, 0x6f18b9b9deb9a167ULL, + 0x268b13134c13985fULL, 0x58512c2cb02c7d9cULL, 0xbb05d3d36bd3d6b8ULL, + 0xd38ce7e7bbe76b5cULL, 0xdc396e6ea56e57cbULL, 0x95aac4c437c46ef3ULL, + 0x061b03030c03180fULL, 0xacdc565645568a13ULL, 0x885e44440d441a49ULL, + 0xfea07f7fe17fdf9eULL, 0x4f88a9a99ea92137ULL, 0x54672a2aa82a4d82ULL, + 0x6b0abbbbd6bbb16dULL, 0x9f87c1c123c146e2ULL, 0xa6f153535153a202ULL, + 0xa572dcdc57dcae8bULL, 0x16530b0b2c0b5827ULL, 0x27019d9d4e9d9cd3ULL, + 0xd82b6c6cad6c47c1ULL, 0x62a43131c43195f5ULL, 0xe8f37474cd7487b9ULL, + 0xf115f6f6fff6e309ULL, 0x8c4c464605460a43ULL, 0x45a5acac8aac0926ULL, + 0x0fb589891e893c97ULL, 0x28b414145014a044ULL, 0xdfbae1e1a3e15b42ULL, + 0x2ca616165816b04eULL, 0x74f73a3ae83acdd2ULL, 0xd2066969b9696fd0ULL, + 0x124109092409482dULL, 0xe0d77070dd70a7adULL, 0x716fb6b6e2b6d954ULL, + 0xbd1ed0d067d0ceb7ULL, 0xc7d6eded93ed3b7eULL, 0x85e2cccc17cc2edbULL, + 0x8468424215422a57ULL, 0x2d2c98985a98b4c2ULL, 0x55eda4a4aaa4490eULL, + 0x50752828a0285d88ULL, 0xb8865c5c6d5cda31ULL, 0xed6bf8f8c7f8933fULL, + 0x11c28686228644a4ULL, +}; + +static const u64 C3[256] = { + 0x7830d818186018c0ULL, 0xaf462623238c2305ULL, 0xf991b8c6c63fc67eULL, + 0x6fcdfbe8e887e813ULL, 0xa113cb878726874cULL, 0x626d11b8b8dab8a9ULL, + 0x0502090101040108ULL, 0x6e9e0d4f4f214f42ULL, 0xee6c9b3636d836adULL, + 0x0451ffa6a6a2a659ULL, 0xbdb90cd2d26fd2deULL, 0x06f70ef5f5f3f5fbULL, + 0x80f2967979f979efULL, 0xcede306f6fa16f5fULL, 0xef3f6d91917e91fcULL, + 0x07a4f852525552aaULL, 0xfdc04760609d6027ULL, 0x766535bcbccabc89ULL, + 0xcd2b379b9b569bacULL, 0x8c018a8e8e028e04ULL, 0x155bd2a3a3b6a371ULL, + 0x3c186c0c0c300c60ULL, 0x8af6847b7bf17bffULL, 0xe16a803535d435b5ULL, + 0x693af51d1d741de8ULL, 0x47ddb3e0e0a7e053ULL, 0xacb321d7d77bd7f6ULL, + 0xed999cc2c22fc25eULL, 0x965c432e2eb82e6dULL, 0x7a96294b4b314b62ULL, + 0x21e15dfefedffea3ULL, 0x16aed55757415782ULL, 0x412abd15155415a8ULL, + 0xb6eee87777c1779fULL, 0xeb6e923737dc37a5ULL, 0x56d79ee5e5b3e57bULL, + 0xd923139f9f469f8cULL, 0x17fd23f0f0e7f0d3ULL, 0x7f94204a4a354a6aULL, + 0x95a944dada4fda9eULL, 0x25b0a258587d58faULL, 0xca8fcfc9c903c906ULL, + 0x8d527c2929a42955ULL, 0x22145a0a0a280a50ULL, 0x4f7f50b1b1feb1e1ULL, + 0x1a5dc9a0a0baa069ULL, 0xdad6146b6bb16b7fULL, 0xab17d985852e855cULL, + 0x73673cbdbdcebd81ULL, 0x34ba8f5d5d695dd2ULL, 0x5020901010401080ULL, + 0x03f507f4f4f7f4f3ULL, 0xc08bddcbcb0bcb16ULL, 0xc67cd33e3ef83eedULL, + 0x110a2d0505140528ULL, 0xe6ce78676781671fULL, 0x53d597e4e4b7e473ULL, + 0xbb4e0227279c2725ULL, 0x5882734141194132ULL, 0x9d0ba78b8b168b2cULL, + 0x0153f6a7a7a6a751ULL, 0x94fab27d7de97dcfULL, 0xfb374995956e95dcULL, + 0x9fad56d8d847d88eULL, 0x30eb70fbfbcbfb8bULL, 0x71c1cdeeee9fee23ULL, + 0x91f8bb7c7ced7cc7ULL, 0xe3cc716666856617ULL, 0x8ea77bdddd53dda6ULL, + 0x4b2eaf17175c17b8ULL, 0x468e454747014702ULL, 0xdc211a9e9e429e84ULL, + 0xc589d4caca0fca1eULL, 0x995a582d2db42d75ULL, 0x79632ebfbfc6bf91ULL, + 0x1b0e3f07071c0738ULL, 0x2347acadad8ead01ULL, 0x2fb4b05a5a755aeaULL, + 0xb51bef838336836cULL, 0xff66b63333cc3385ULL, 0xf2c65c636391633fULL, + 0x0a04120202080210ULL, 0x384993aaaa92aa39ULL, 0xa8e2de7171d971afULL, + 0xcf8dc6c8c807c80eULL, 0x7d32d119196419c8ULL, 0x70923b4949394972ULL, + 0x9aaf5fd9d943d986ULL, 0x1df931f2f2eff2c3ULL, 0x48dba8e3e3abe34bULL, + 0x2ab6b95b5b715be2ULL, 0x920dbc88881a8834ULL, 0xc8293e9a9a529aa4ULL, + 0xbe4c0b262698262dULL, 0xfa64bf3232c8328dULL, 0x4a7d59b0b0fab0e9ULL, + 0x6acff2e9e983e91bULL, 0x331e770f0f3c0f78ULL, 0xa6b733d5d573d5e6ULL, + 0xba1df480803a8074ULL, 0x7c6127bebec2be99ULL, 0xde87ebcdcd13cd26ULL, + 0xe468893434d034bdULL, 0x75903248483d487aULL, 0x24e354ffffdbffabULL, + 0x8ff48d7a7af57af7ULL, 0xea3d6490907a90f4ULL, 0x3ebe9d5f5f615fc2ULL, + 0xa0403d202080201dULL, 0xd5d00f6868bd6867ULL, 0x7234ca1a1a681ad0ULL, + 0x2c41b7aeae82ae19ULL, 0x5e757db4b4eab4c9ULL, 0x19a8ce54544d549aULL, + 0xe53b7f93937693ecULL, 0xaa442f222288220dULL, 0xe9c86364648d6407ULL, + 0x12ff2af1f1e3f1dbULL, 0xa2e6cc7373d173bfULL, 0x5a24821212481290ULL, + 0x5d807a40401d403aULL, 0x2810480808200840ULL, 0xe89b95c3c32bc356ULL, + 0x7bc5dfecec97ec33ULL, 0x90ab4ddbdb4bdb96ULL, 0x1f5fc0a1a1bea161ULL, + 0x8307918d8d0e8d1cULL, 0xc97ac83d3df43df5ULL, 0xf1335b97976697ccULL, + 0x0000000000000000ULL, 0xd483f9cfcf1bcf36ULL, 0x87566e2b2bac2b45ULL, + 0xb3ece17676c57697ULL, 0xb019e68282328264ULL, 0xa9b128d6d67fd6feULL, + 0x7736c31b1b6c1bd8ULL, 0x5b7774b5b5eeb5c1ULL, 0x2943beafaf86af11ULL, + 0xdfd41d6a6ab56a77ULL, 0x0da0ea50505d50baULL, 0x4c8a574545094512ULL, + 0x18fb38f3f3ebf3cbULL, 0xf060ad3030c0309dULL, 0x74c3c4efef9bef2bULL, + 0xc37eda3f3ffc3fe5ULL, 0x1caac75555495592ULL, 0x1059dba2a2b2a279ULL, + 0x65c9e9eaea8fea03ULL, 0xecca6a656589650fULL, 0x686903babad2bab9ULL, + 0x935e4a2f2fbc2f65ULL, 0xe79d8ec0c027c04eULL, 0x81a160dede5fdebeULL, + 0x6c38fc1c1c701ce0ULL, 0x2ee746fdfdd3fdbbULL, 0x649a1f4d4d294d52ULL, + 0xe0397692927292e4ULL, 0xbceafa7575c9758fULL, 0x1e0c360606180630ULL, + 0x9809ae8a8a128a24ULL, 0x40794bb2b2f2b2f9ULL, 0x59d185e6e6bfe663ULL, + 0x361c7e0e0e380e70ULL, 0x633ee71f1f7c1ff8ULL, 0xf7c4556262956237ULL, + 0xa3b53ad4d477d4eeULL, 0x324d81a8a89aa829ULL, 0xf4315296966296c4ULL, + 0x3aef62f9f9c3f99bULL, 0xf697a3c5c533c566ULL, 0xb14a102525942535ULL, + 0x20b2ab59597959f2ULL, 0xae15d084842a8454ULL, 0xa7e4c57272d572b7ULL, + 0xdd72ec3939e439d5ULL, 0x6198164c4c2d4c5aULL, 0x3bbc945e5e655ecaULL, + 0x85f09f7878fd78e7ULL, 0xd870e53838e038ddULL, 0x8605988c8c0a8c14ULL, + 0xb2bf17d1d163d1c6ULL, 0x0b57e4a5a5aea541ULL, 0x4dd9a1e2e2afe243ULL, + 0xf8c24e616199612fULL, 0x457b42b3b3f6b3f1ULL, 0xa542342121842115ULL, + 0xd625089c9c4a9c94ULL, 0x663cee1e1e781ef0ULL, 0x5286614343114322ULL, + 0xfc93b1c7c73bc776ULL, 0x2be54ffcfcd7fcb3ULL, 0x1408240404100420ULL, + 0x08a2e351515951b2ULL, 0xc72f2599995e99bcULL, 0xc4da226d6da96d4fULL, + 0x391a650d0d340d68ULL, 0x35e979fafacffa83ULL, 0x84a369dfdf5bdfb6ULL, + 0x9bfca97e7ee57ed7ULL, 0xb44819242490243dULL, 0xd776fe3b3bec3bc5ULL, + 0x3d4b9aabab96ab31ULL, 0xd181f0cece1fce3eULL, 0x5522991111441188ULL, + 0x8903838f8f068f0cULL, 0x6b9c044e4e254e4aULL, 0x517366b7b7e6b7d1ULL, + 0x60cbe0ebeb8beb0bULL, 0xcc78c13c3cf03cfdULL, 0xbf1ffd81813e817cULL, + 0xfe354094946a94d4ULL, 0x0cf31cf7f7fbf7ebULL, 0x676f18b9b9deb9a1ULL, + 0x5f268b13134c1398ULL, 0x9c58512c2cb02c7dULL, 0xb8bb05d3d36bd3d6ULL, + 0x5cd38ce7e7bbe76bULL, 0xcbdc396e6ea56e57ULL, 0xf395aac4c437c46eULL, + 0x0f061b03030c0318ULL, 0x13acdc565645568aULL, 0x49885e44440d441aULL, + 0x9efea07f7fe17fdfULL, 0x374f88a9a99ea921ULL, 0x8254672a2aa82a4dULL, + 0x6d6b0abbbbd6bbb1ULL, 0xe29f87c1c123c146ULL, 0x02a6f153535153a2ULL, + 0x8ba572dcdc57dcaeULL, 0x2716530b0b2c0b58ULL, 0xd327019d9d4e9d9cULL, + 0xc1d82b6c6cad6c47ULL, 0xf562a43131c43195ULL, 0xb9e8f37474cd7487ULL, + 0x09f115f6f6fff6e3ULL, 0x438c4c464605460aULL, 0x2645a5acac8aac09ULL, + 0x970fb589891e893cULL, 0x4428b414145014a0ULL, 0x42dfbae1e1a3e15bULL, + 0x4e2ca616165816b0ULL, 0xd274f73a3ae83acdULL, 0xd0d2066969b9696fULL, + 0x2d12410909240948ULL, 0xade0d77070dd70a7ULL, 0x54716fb6b6e2b6d9ULL, + 0xb7bd1ed0d067d0ceULL, 0x7ec7d6eded93ed3bULL, 0xdb85e2cccc17cc2eULL, + 0x578468424215422aULL, 0xc22d2c98985a98b4ULL, 0x0e55eda4a4aaa449ULL, + 0x8850752828a0285dULL, 0x31b8865c5c6d5cdaULL, 0x3fed6bf8f8c7f893ULL, + 0xa411c28686228644ULL, +}; + +static const u64 C4[256] = { + 0xc07830d818186018ULL, 0x05af462623238c23ULL, 0x7ef991b8c6c63fc6ULL, + 0x136fcdfbe8e887e8ULL, 0x4ca113cb87872687ULL, 0xa9626d11b8b8dab8ULL, + 0x0805020901010401ULL, 0x426e9e0d4f4f214fULL, 0xadee6c9b3636d836ULL, + 0x590451ffa6a6a2a6ULL, 0xdebdb90cd2d26fd2ULL, 0xfb06f70ef5f5f3f5ULL, + 0xef80f2967979f979ULL, 0x5fcede306f6fa16fULL, 0xfcef3f6d91917e91ULL, + 0xaa07a4f852525552ULL, 0x27fdc04760609d60ULL, 0x89766535bcbccabcULL, + 0xaccd2b379b9b569bULL, 0x048c018a8e8e028eULL, 0x71155bd2a3a3b6a3ULL, + 0x603c186c0c0c300cULL, 0xff8af6847b7bf17bULL, 0xb5e16a803535d435ULL, + 0xe8693af51d1d741dULL, 0x5347ddb3e0e0a7e0ULL, 0xf6acb321d7d77bd7ULL, + 0x5eed999cc2c22fc2ULL, 0x6d965c432e2eb82eULL, 0x627a96294b4b314bULL, + 0xa321e15dfefedffeULL, 0x8216aed557574157ULL, 0xa8412abd15155415ULL, + 0x9fb6eee87777c177ULL, 0xa5eb6e923737dc37ULL, 0x7b56d79ee5e5b3e5ULL, + 0x8cd923139f9f469fULL, 0xd317fd23f0f0e7f0ULL, 0x6a7f94204a4a354aULL, + 0x9e95a944dada4fdaULL, 0xfa25b0a258587d58ULL, 0x06ca8fcfc9c903c9ULL, + 0x558d527c2929a429ULL, 0x5022145a0a0a280aULL, 0xe14f7f50b1b1feb1ULL, + 0x691a5dc9a0a0baa0ULL, 0x7fdad6146b6bb16bULL, 0x5cab17d985852e85ULL, + 0x8173673cbdbdcebdULL, 0xd234ba8f5d5d695dULL, 0x8050209010104010ULL, + 0xf303f507f4f4f7f4ULL, 0x16c08bddcbcb0bcbULL, 0xedc67cd33e3ef83eULL, + 0x28110a2d05051405ULL, 0x1fe6ce7867678167ULL, 0x7353d597e4e4b7e4ULL, + 0x25bb4e0227279c27ULL, 0x3258827341411941ULL, 0x2c9d0ba78b8b168bULL, + 0x510153f6a7a7a6a7ULL, 0xcf94fab27d7de97dULL, 0xdcfb374995956e95ULL, + 0x8e9fad56d8d847d8ULL, 0x8b30eb70fbfbcbfbULL, 0x2371c1cdeeee9feeULL, + 0xc791f8bb7c7ced7cULL, 0x17e3cc7166668566ULL, 0xa68ea77bdddd53ddULL, + 0xb84b2eaf17175c17ULL, 0x02468e4547470147ULL, 0x84dc211a9e9e429eULL, + 0x1ec589d4caca0fcaULL, 0x75995a582d2db42dULL, 0x9179632ebfbfc6bfULL, + 0x381b0e3f07071c07ULL, 0x012347acadad8eadULL, 0xea2fb4b05a5a755aULL, + 0x6cb51bef83833683ULL, 0x85ff66b63333cc33ULL, 0x3ff2c65c63639163ULL, + 0x100a041202020802ULL, 0x39384993aaaa92aaULL, 0xafa8e2de7171d971ULL, + 0x0ecf8dc6c8c807c8ULL, 0xc87d32d119196419ULL, 0x7270923b49493949ULL, + 0x869aaf5fd9d943d9ULL, 0xc31df931f2f2eff2ULL, 0x4b48dba8e3e3abe3ULL, + 0xe22ab6b95b5b715bULL, 0x34920dbc88881a88ULL, 0xa4c8293e9a9a529aULL, + 0x2dbe4c0b26269826ULL, 0x8dfa64bf3232c832ULL, 0xe94a7d59b0b0fab0ULL, + 0x1b6acff2e9e983e9ULL, 0x78331e770f0f3c0fULL, 0xe6a6b733d5d573d5ULL, + 0x74ba1df480803a80ULL, 0x997c6127bebec2beULL, 0x26de87ebcdcd13cdULL, + 0xbde468893434d034ULL, 0x7a75903248483d48ULL, 0xab24e354ffffdbffULL, + 0xf78ff48d7a7af57aULL, 0xf4ea3d6490907a90ULL, 0xc23ebe9d5f5f615fULL, + 0x1da0403d20208020ULL, 0x67d5d00f6868bd68ULL, 0xd07234ca1a1a681aULL, + 0x192c41b7aeae82aeULL, 0xc95e757db4b4eab4ULL, 0x9a19a8ce54544d54ULL, + 0xece53b7f93937693ULL, 0x0daa442f22228822ULL, 0x07e9c86364648d64ULL, + 0xdb12ff2af1f1e3f1ULL, 0xbfa2e6cc7373d173ULL, 0x905a248212124812ULL, + 0x3a5d807a40401d40ULL, 0x4028104808082008ULL, 0x56e89b95c3c32bc3ULL, + 0x337bc5dfecec97ecULL, 0x9690ab4ddbdb4bdbULL, 0x611f5fc0a1a1bea1ULL, + 0x1c8307918d8d0e8dULL, 0xf5c97ac83d3df43dULL, 0xccf1335b97976697ULL, + 0x0000000000000000ULL, 0x36d483f9cfcf1bcfULL, 0x4587566e2b2bac2bULL, + 0x97b3ece17676c576ULL, 0x64b019e682823282ULL, 0xfea9b128d6d67fd6ULL, + 0xd87736c31b1b6c1bULL, 0xc15b7774b5b5eeb5ULL, 0x112943beafaf86afULL, + 0x77dfd41d6a6ab56aULL, 0xba0da0ea50505d50ULL, 0x124c8a5745450945ULL, + 0xcb18fb38f3f3ebf3ULL, 0x9df060ad3030c030ULL, 0x2b74c3c4efef9befULL, + 0xe5c37eda3f3ffc3fULL, 0x921caac755554955ULL, 0x791059dba2a2b2a2ULL, + 0x0365c9e9eaea8feaULL, 0x0fecca6a65658965ULL, 0xb9686903babad2baULL, + 0x65935e4a2f2fbc2fULL, 0x4ee79d8ec0c027c0ULL, 0xbe81a160dede5fdeULL, + 0xe06c38fc1c1c701cULL, 0xbb2ee746fdfdd3fdULL, 0x52649a1f4d4d294dULL, + 0xe4e0397692927292ULL, 0x8fbceafa7575c975ULL, 0x301e0c3606061806ULL, + 0x249809ae8a8a128aULL, 0xf940794bb2b2f2b2ULL, 0x6359d185e6e6bfe6ULL, + 0x70361c7e0e0e380eULL, 0xf8633ee71f1f7c1fULL, 0x37f7c45562629562ULL, + 0xeea3b53ad4d477d4ULL, 0x29324d81a8a89aa8ULL, 0xc4f4315296966296ULL, + 0x9b3aef62f9f9c3f9ULL, 0x66f697a3c5c533c5ULL, 0x35b14a1025259425ULL, + 0xf220b2ab59597959ULL, 0x54ae15d084842a84ULL, 0xb7a7e4c57272d572ULL, + 0xd5dd72ec3939e439ULL, 0x5a6198164c4c2d4cULL, 0xca3bbc945e5e655eULL, + 0xe785f09f7878fd78ULL, 0xddd870e53838e038ULL, 0x148605988c8c0a8cULL, + 0xc6b2bf17d1d163d1ULL, 0x410b57e4a5a5aea5ULL, 0x434dd9a1e2e2afe2ULL, + 0x2ff8c24e61619961ULL, 0xf1457b42b3b3f6b3ULL, 0x15a5423421218421ULL, + 0x94d625089c9c4a9cULL, 0xf0663cee1e1e781eULL, 0x2252866143431143ULL, + 0x76fc93b1c7c73bc7ULL, 0xb32be54ffcfcd7fcULL, 0x2014082404041004ULL, + 0xb208a2e351515951ULL, 0xbcc72f2599995e99ULL, 0x4fc4da226d6da96dULL, + 0x68391a650d0d340dULL, 0x8335e979fafacffaULL, 0xb684a369dfdf5bdfULL, + 0xd79bfca97e7ee57eULL, 0x3db4481924249024ULL, 0xc5d776fe3b3bec3bULL, + 0x313d4b9aabab96abULL, 0x3ed181f0cece1fceULL, 0x8855229911114411ULL, + 0x0c8903838f8f068fULL, 0x4a6b9c044e4e254eULL, 0xd1517366b7b7e6b7ULL, + 0x0b60cbe0ebeb8bebULL, 0xfdcc78c13c3cf03cULL, 0x7cbf1ffd81813e81ULL, + 0xd4fe354094946a94ULL, 0xeb0cf31cf7f7fbf7ULL, 0xa1676f18b9b9deb9ULL, + 0x985f268b13134c13ULL, 0x7d9c58512c2cb02cULL, 0xd6b8bb05d3d36bd3ULL, + 0x6b5cd38ce7e7bbe7ULL, 0x57cbdc396e6ea56eULL, 0x6ef395aac4c437c4ULL, + 0x180f061b03030c03ULL, 0x8a13acdc56564556ULL, 0x1a49885e44440d44ULL, + 0xdf9efea07f7fe17fULL, 0x21374f88a9a99ea9ULL, 0x4d8254672a2aa82aULL, + 0xb16d6b0abbbbd6bbULL, 0x46e29f87c1c123c1ULL, 0xa202a6f153535153ULL, + 0xae8ba572dcdc57dcULL, 0x582716530b0b2c0bULL, 0x9cd327019d9d4e9dULL, + 0x47c1d82b6c6cad6cULL, 0x95f562a43131c431ULL, 0x87b9e8f37474cd74ULL, + 0xe309f115f6f6fff6ULL, 0x0a438c4c46460546ULL, 0x092645a5acac8aacULL, + 0x3c970fb589891e89ULL, 0xa04428b414145014ULL, 0x5b42dfbae1e1a3e1ULL, + 0xb04e2ca616165816ULL, 0xcdd274f73a3ae83aULL, 0x6fd0d2066969b969ULL, + 0x482d124109092409ULL, 0xa7ade0d77070dd70ULL, 0xd954716fb6b6e2b6ULL, + 0xceb7bd1ed0d067d0ULL, 0x3b7ec7d6eded93edULL, 0x2edb85e2cccc17ccULL, + 0x2a57846842421542ULL, 0xb4c22d2c98985a98ULL, 0x490e55eda4a4aaa4ULL, + 0x5d8850752828a028ULL, 0xda31b8865c5c6d5cULL, 0x933fed6bf8f8c7f8ULL, + 0x44a411c286862286ULL, +}; + +static const u64 C5[256] = { + 0x18c07830d8181860ULL, 0x2305af462623238cULL, 0xc67ef991b8c6c63fULL, + 0xe8136fcdfbe8e887ULL, 0x874ca113cb878726ULL, 0xb8a9626d11b8b8daULL, + 0x0108050209010104ULL, 0x4f426e9e0d4f4f21ULL, 0x36adee6c9b3636d8ULL, + 0xa6590451ffa6a6a2ULL, 0xd2debdb90cd2d26fULL, 0xf5fb06f70ef5f5f3ULL, + 0x79ef80f2967979f9ULL, 0x6f5fcede306f6fa1ULL, 0x91fcef3f6d91917eULL, + 0x52aa07a4f8525255ULL, 0x6027fdc04760609dULL, 0xbc89766535bcbccaULL, + 0x9baccd2b379b9b56ULL, 0x8e048c018a8e8e02ULL, 0xa371155bd2a3a3b6ULL, + 0x0c603c186c0c0c30ULL, 0x7bff8af6847b7bf1ULL, 0x35b5e16a803535d4ULL, + 0x1de8693af51d1d74ULL, 0xe05347ddb3e0e0a7ULL, 0xd7f6acb321d7d77bULL, + 0xc25eed999cc2c22fULL, 0x2e6d965c432e2eb8ULL, 0x4b627a96294b4b31ULL, + 0xfea321e15dfefedfULL, 0x578216aed5575741ULL, 0x15a8412abd151554ULL, + 0x779fb6eee87777c1ULL, 0x37a5eb6e923737dcULL, 0xe57b56d79ee5e5b3ULL, + 0x9f8cd923139f9f46ULL, 0xf0d317fd23f0f0e7ULL, 0x4a6a7f94204a4a35ULL, + 0xda9e95a944dada4fULL, 0x58fa25b0a258587dULL, 0xc906ca8fcfc9c903ULL, + 0x29558d527c2929a4ULL, 0x0a5022145a0a0a28ULL, 0xb1e14f7f50b1b1feULL, + 0xa0691a5dc9a0a0baULL, 0x6b7fdad6146b6bb1ULL, 0x855cab17d985852eULL, + 0xbd8173673cbdbdceULL, 0x5dd234ba8f5d5d69ULL, 0x1080502090101040ULL, + 0xf4f303f507f4f4f7ULL, 0xcb16c08bddcbcb0bULL, 0x3eedc67cd33e3ef8ULL, + 0x0528110a2d050514ULL, 0x671fe6ce78676781ULL, 0xe47353d597e4e4b7ULL, + 0x2725bb4e0227279cULL, 0x4132588273414119ULL, 0x8b2c9d0ba78b8b16ULL, + 0xa7510153f6a7a7a6ULL, 0x7dcf94fab27d7de9ULL, 0x95dcfb374995956eULL, + 0xd88e9fad56d8d847ULL, 0xfb8b30eb70fbfbcbULL, 0xee2371c1cdeeee9fULL, + 0x7cc791f8bb7c7cedULL, 0x6617e3cc71666685ULL, 0xdda68ea77bdddd53ULL, + 0x17b84b2eaf17175cULL, 0x4702468e45474701ULL, 0x9e84dc211a9e9e42ULL, + 0xca1ec589d4caca0fULL, 0x2d75995a582d2db4ULL, 0xbf9179632ebfbfc6ULL, + 0x07381b0e3f07071cULL, 0xad012347acadad8eULL, 0x5aea2fb4b05a5a75ULL, + 0x836cb51bef838336ULL, 0x3385ff66b63333ccULL, 0x633ff2c65c636391ULL, + 0x02100a0412020208ULL, 0xaa39384993aaaa92ULL, 0x71afa8e2de7171d9ULL, + 0xc80ecf8dc6c8c807ULL, 0x19c87d32d1191964ULL, 0x497270923b494939ULL, + 0xd9869aaf5fd9d943ULL, 0xf2c31df931f2f2efULL, 0xe34b48dba8e3e3abULL, + 0x5be22ab6b95b5b71ULL, 0x8834920dbc88881aULL, 0x9aa4c8293e9a9a52ULL, + 0x262dbe4c0b262698ULL, 0x328dfa64bf3232c8ULL, 0xb0e94a7d59b0b0faULL, + 0xe91b6acff2e9e983ULL, 0x0f78331e770f0f3cULL, 0xd5e6a6b733d5d573ULL, + 0x8074ba1df480803aULL, 0xbe997c6127bebec2ULL, 0xcd26de87ebcdcd13ULL, + 0x34bde468893434d0ULL, 0x487a75903248483dULL, 0xffab24e354ffffdbULL, + 0x7af78ff48d7a7af5ULL, 0x90f4ea3d6490907aULL, 0x5fc23ebe9d5f5f61ULL, + 0x201da0403d202080ULL, 0x6867d5d00f6868bdULL, 0x1ad07234ca1a1a68ULL, + 0xae192c41b7aeae82ULL, 0xb4c95e757db4b4eaULL, 0x549a19a8ce54544dULL, + 0x93ece53b7f939376ULL, 0x220daa442f222288ULL, 0x6407e9c86364648dULL, + 0xf1db12ff2af1f1e3ULL, 0x73bfa2e6cc7373d1ULL, 0x12905a2482121248ULL, + 0x403a5d807a40401dULL, 0x0840281048080820ULL, 0xc356e89b95c3c32bULL, + 0xec337bc5dfecec97ULL, 0xdb9690ab4ddbdb4bULL, 0xa1611f5fc0a1a1beULL, + 0x8d1c8307918d8d0eULL, 0x3df5c97ac83d3df4ULL, 0x97ccf1335b979766ULL, + 0x0000000000000000ULL, 0xcf36d483f9cfcf1bULL, 0x2b4587566e2b2bacULL, + 0x7697b3ece17676c5ULL, 0x8264b019e6828232ULL, 0xd6fea9b128d6d67fULL, + 0x1bd87736c31b1b6cULL, 0xb5c15b7774b5b5eeULL, 0xaf112943beafaf86ULL, + 0x6a77dfd41d6a6ab5ULL, 0x50ba0da0ea50505dULL, 0x45124c8a57454509ULL, + 0xf3cb18fb38f3f3ebULL, 0x309df060ad3030c0ULL, 0xef2b74c3c4efef9bULL, + 0x3fe5c37eda3f3ffcULL, 0x55921caac7555549ULL, 0xa2791059dba2a2b2ULL, + 0xea0365c9e9eaea8fULL, 0x650fecca6a656589ULL, 0xbab9686903babad2ULL, + 0x2f65935e4a2f2fbcULL, 0xc04ee79d8ec0c027ULL, 0xdebe81a160dede5fULL, + 0x1ce06c38fc1c1c70ULL, 0xfdbb2ee746fdfdd3ULL, 0x4d52649a1f4d4d29ULL, + 0x92e4e03976929272ULL, 0x758fbceafa7575c9ULL, 0x06301e0c36060618ULL, + 0x8a249809ae8a8a12ULL, 0xb2f940794bb2b2f2ULL, 0xe66359d185e6e6bfULL, + 0x0e70361c7e0e0e38ULL, 0x1ff8633ee71f1f7cULL, 0x6237f7c455626295ULL, + 0xd4eea3b53ad4d477ULL, 0xa829324d81a8a89aULL, 0x96c4f43152969662ULL, + 0xf99b3aef62f9f9c3ULL, 0xc566f697a3c5c533ULL, 0x2535b14a10252594ULL, + 0x59f220b2ab595979ULL, 0x8454ae15d084842aULL, 0x72b7a7e4c57272d5ULL, + 0x39d5dd72ec3939e4ULL, 0x4c5a6198164c4c2dULL, 0x5eca3bbc945e5e65ULL, + 0x78e785f09f7878fdULL, 0x38ddd870e53838e0ULL, 0x8c148605988c8c0aULL, + 0xd1c6b2bf17d1d163ULL, 0xa5410b57e4a5a5aeULL, 0xe2434dd9a1e2e2afULL, + 0x612ff8c24e616199ULL, 0xb3f1457b42b3b3f6ULL, 0x2115a54234212184ULL, + 0x9c94d625089c9c4aULL, 0x1ef0663cee1e1e78ULL, 0x4322528661434311ULL, + 0xc776fc93b1c7c73bULL, 0xfcb32be54ffcfcd7ULL, 0x0420140824040410ULL, + 0x51b208a2e3515159ULL, 0x99bcc72f2599995eULL, 0x6d4fc4da226d6da9ULL, + 0x0d68391a650d0d34ULL, 0xfa8335e979fafacfULL, 0xdfb684a369dfdf5bULL, + 0x7ed79bfca97e7ee5ULL, 0x243db44819242490ULL, 0x3bc5d776fe3b3becULL, + 0xab313d4b9aabab96ULL, 0xce3ed181f0cece1fULL, 0x1188552299111144ULL, + 0x8f0c8903838f8f06ULL, 0x4e4a6b9c044e4e25ULL, 0xb7d1517366b7b7e6ULL, + 0xeb0b60cbe0ebeb8bULL, 0x3cfdcc78c13c3cf0ULL, 0x817cbf1ffd81813eULL, + 0x94d4fe354094946aULL, 0xf7eb0cf31cf7f7fbULL, 0xb9a1676f18b9b9deULL, + 0x13985f268b13134cULL, 0x2c7d9c58512c2cb0ULL, 0xd3d6b8bb05d3d36bULL, + 0xe76b5cd38ce7e7bbULL, 0x6e57cbdc396e6ea5ULL, 0xc46ef395aac4c437ULL, + 0x03180f061b03030cULL, 0x568a13acdc565645ULL, 0x441a49885e44440dULL, + 0x7fdf9efea07f7fe1ULL, 0xa921374f88a9a99eULL, 0x2a4d8254672a2aa8ULL, + 0xbbb16d6b0abbbbd6ULL, 0xc146e29f87c1c123ULL, 0x53a202a6f1535351ULL, + 0xdcae8ba572dcdc57ULL, 0x0b582716530b0b2cULL, 0x9d9cd327019d9d4eULL, + 0x6c47c1d82b6c6cadULL, 0x3195f562a43131c4ULL, 0x7487b9e8f37474cdULL, + 0xf6e309f115f6f6ffULL, 0x460a438c4c464605ULL, 0xac092645a5acac8aULL, + 0x893c970fb589891eULL, 0x14a04428b4141450ULL, 0xe15b42dfbae1e1a3ULL, + 0x16b04e2ca6161658ULL, 0x3acdd274f73a3ae8ULL, 0x696fd0d2066969b9ULL, + 0x09482d1241090924ULL, 0x70a7ade0d77070ddULL, 0xb6d954716fb6b6e2ULL, + 0xd0ceb7bd1ed0d067ULL, 0xed3b7ec7d6eded93ULL, 0xcc2edb85e2cccc17ULL, + 0x422a578468424215ULL, 0x98b4c22d2c98985aULL, 0xa4490e55eda4a4aaULL, + 0x285d8850752828a0ULL, 0x5cda31b8865c5c6dULL, 0xf8933fed6bf8f8c7ULL, + 0x8644a411c2868622ULL, +}; + +static const u64 C6[256] = { + 0x6018c07830d81818ULL, 0x8c2305af46262323ULL, 0x3fc67ef991b8c6c6ULL, + 0x87e8136fcdfbe8e8ULL, 0x26874ca113cb8787ULL, 0xdab8a9626d11b8b8ULL, + 0x0401080502090101ULL, 0x214f426e9e0d4f4fULL, 0xd836adee6c9b3636ULL, + 0xa2a6590451ffa6a6ULL, 0x6fd2debdb90cd2d2ULL, 0xf3f5fb06f70ef5f5ULL, + 0xf979ef80f2967979ULL, 0xa16f5fcede306f6fULL, 0x7e91fcef3f6d9191ULL, + 0x5552aa07a4f85252ULL, 0x9d6027fdc0476060ULL, 0xcabc89766535bcbcULL, + 0x569baccd2b379b9bULL, 0x028e048c018a8e8eULL, 0xb6a371155bd2a3a3ULL, + 0x300c603c186c0c0cULL, 0xf17bff8af6847b7bULL, 0xd435b5e16a803535ULL, + 0x741de8693af51d1dULL, 0xa7e05347ddb3e0e0ULL, 0x7bd7f6acb321d7d7ULL, + 0x2fc25eed999cc2c2ULL, 0xb82e6d965c432e2eULL, 0x314b627a96294b4bULL, + 0xdffea321e15dfefeULL, 0x41578216aed55757ULL, 0x5415a8412abd1515ULL, + 0xc1779fb6eee87777ULL, 0xdc37a5eb6e923737ULL, 0xb3e57b56d79ee5e5ULL, + 0x469f8cd923139f9fULL, 0xe7f0d317fd23f0f0ULL, 0x354a6a7f94204a4aULL, + 0x4fda9e95a944dadaULL, 0x7d58fa25b0a25858ULL, 0x03c906ca8fcfc9c9ULL, + 0xa429558d527c2929ULL, 0x280a5022145a0a0aULL, 0xfeb1e14f7f50b1b1ULL, + 0xbaa0691a5dc9a0a0ULL, 0xb16b7fdad6146b6bULL, 0x2e855cab17d98585ULL, + 0xcebd8173673cbdbdULL, 0x695dd234ba8f5d5dULL, 0x4010805020901010ULL, + 0xf7f4f303f507f4f4ULL, 0x0bcb16c08bddcbcbULL, 0xf83eedc67cd33e3eULL, + 0x140528110a2d0505ULL, 0x81671fe6ce786767ULL, 0xb7e47353d597e4e4ULL, + 0x9c2725bb4e022727ULL, 0x1941325882734141ULL, 0x168b2c9d0ba78b8bULL, + 0xa6a7510153f6a7a7ULL, 0xe97dcf94fab27d7dULL, 0x6e95dcfb37499595ULL, + 0x47d88e9fad56d8d8ULL, 0xcbfb8b30eb70fbfbULL, 0x9fee2371c1cdeeeeULL, + 0xed7cc791f8bb7c7cULL, 0x856617e3cc716666ULL, 0x53dda68ea77bddddULL, + 0x5c17b84b2eaf1717ULL, 0x014702468e454747ULL, 0x429e84dc211a9e9eULL, + 0x0fca1ec589d4cacaULL, 0xb42d75995a582d2dULL, 0xc6bf9179632ebfbfULL, + 0x1c07381b0e3f0707ULL, 0x8ead012347acadadULL, 0x755aea2fb4b05a5aULL, + 0x36836cb51bef8383ULL, 0xcc3385ff66b63333ULL, 0x91633ff2c65c6363ULL, + 0x0802100a04120202ULL, 0x92aa39384993aaaaULL, 0xd971afa8e2de7171ULL, + 0x07c80ecf8dc6c8c8ULL, 0x6419c87d32d11919ULL, 0x39497270923b4949ULL, + 0x43d9869aaf5fd9d9ULL, 0xeff2c31df931f2f2ULL, 0xabe34b48dba8e3e3ULL, + 0x715be22ab6b95b5bULL, 0x1a8834920dbc8888ULL, 0x529aa4c8293e9a9aULL, + 0x98262dbe4c0b2626ULL, 0xc8328dfa64bf3232ULL, 0xfab0e94a7d59b0b0ULL, + 0x83e91b6acff2e9e9ULL, 0x3c0f78331e770f0fULL, 0x73d5e6a6b733d5d5ULL, + 0x3a8074ba1df48080ULL, 0xc2be997c6127bebeULL, 0x13cd26de87ebcdcdULL, + 0xd034bde468893434ULL, 0x3d487a7590324848ULL, 0xdbffab24e354ffffULL, + 0xf57af78ff48d7a7aULL, 0x7a90f4ea3d649090ULL, 0x615fc23ebe9d5f5fULL, + 0x80201da0403d2020ULL, 0xbd6867d5d00f6868ULL, 0x681ad07234ca1a1aULL, + 0x82ae192c41b7aeaeULL, 0xeab4c95e757db4b4ULL, 0x4d549a19a8ce5454ULL, + 0x7693ece53b7f9393ULL, 0x88220daa442f2222ULL, 0x8d6407e9c8636464ULL, + 0xe3f1db12ff2af1f1ULL, 0xd173bfa2e6cc7373ULL, 0x4812905a24821212ULL, + 0x1d403a5d807a4040ULL, 0x2008402810480808ULL, 0x2bc356e89b95c3c3ULL, + 0x97ec337bc5dfececULL, 0x4bdb9690ab4ddbdbULL, 0xbea1611f5fc0a1a1ULL, + 0x0e8d1c8307918d8dULL, 0xf43df5c97ac83d3dULL, 0x6697ccf1335b9797ULL, + 0x0000000000000000ULL, 0x1bcf36d483f9cfcfULL, 0xac2b4587566e2b2bULL, + 0xc57697b3ece17676ULL, 0x328264b019e68282ULL, 0x7fd6fea9b128d6d6ULL, + 0x6c1bd87736c31b1bULL, 0xeeb5c15b7774b5b5ULL, 0x86af112943beafafULL, + 0xb56a77dfd41d6a6aULL, 0x5d50ba0da0ea5050ULL, 0x0945124c8a574545ULL, + 0xebf3cb18fb38f3f3ULL, 0xc0309df060ad3030ULL, 0x9bef2b74c3c4efefULL, + 0xfc3fe5c37eda3f3fULL, 0x4955921caac75555ULL, 0xb2a2791059dba2a2ULL, + 0x8fea0365c9e9eaeaULL, 0x89650fecca6a6565ULL, 0xd2bab9686903babaULL, + 0xbc2f65935e4a2f2fULL, 0x27c04ee79d8ec0c0ULL, 0x5fdebe81a160dedeULL, + 0x701ce06c38fc1c1cULL, 0xd3fdbb2ee746fdfdULL, 0x294d52649a1f4d4dULL, + 0x7292e4e039769292ULL, 0xc9758fbceafa7575ULL, 0x1806301e0c360606ULL, + 0x128a249809ae8a8aULL, 0xf2b2f940794bb2b2ULL, 0xbfe66359d185e6e6ULL, + 0x380e70361c7e0e0eULL, 0x7c1ff8633ee71f1fULL, 0x956237f7c4556262ULL, + 0x77d4eea3b53ad4d4ULL, 0x9aa829324d81a8a8ULL, 0x6296c4f431529696ULL, + 0xc3f99b3aef62f9f9ULL, 0x33c566f697a3c5c5ULL, 0x942535b14a102525ULL, + 0x7959f220b2ab5959ULL, 0x2a8454ae15d08484ULL, 0xd572b7a7e4c57272ULL, + 0xe439d5dd72ec3939ULL, 0x2d4c5a6198164c4cULL, 0x655eca3bbc945e5eULL, + 0xfd78e785f09f7878ULL, 0xe038ddd870e53838ULL, 0x0a8c148605988c8cULL, + 0x63d1c6b2bf17d1d1ULL, 0xaea5410b57e4a5a5ULL, 0xafe2434dd9a1e2e2ULL, + 0x99612ff8c24e6161ULL, 0xf6b3f1457b42b3b3ULL, 0x842115a542342121ULL, + 0x4a9c94d625089c9cULL, 0x781ef0663cee1e1eULL, 0x1143225286614343ULL, + 0x3bc776fc93b1c7c7ULL, 0xd7fcb32be54ffcfcULL, 0x1004201408240404ULL, + 0x5951b208a2e35151ULL, 0x5e99bcc72f259999ULL, 0xa96d4fc4da226d6dULL, + 0x340d68391a650d0dULL, 0xcffa8335e979fafaULL, 0x5bdfb684a369dfdfULL, + 0xe57ed79bfca97e7eULL, 0x90243db448192424ULL, 0xec3bc5d776fe3b3bULL, + 0x96ab313d4b9aababULL, 0x1fce3ed181f0ceceULL, 0x4411885522991111ULL, + 0x068f0c8903838f8fULL, 0x254e4a6b9c044e4eULL, 0xe6b7d1517366b7b7ULL, + 0x8beb0b60cbe0ebebULL, 0xf03cfdcc78c13c3cULL, 0x3e817cbf1ffd8181ULL, + 0x6a94d4fe35409494ULL, 0xfbf7eb0cf31cf7f7ULL, 0xdeb9a1676f18b9b9ULL, + 0x4c13985f268b1313ULL, 0xb02c7d9c58512c2cULL, 0x6bd3d6b8bb05d3d3ULL, + 0xbbe76b5cd38ce7e7ULL, 0xa56e57cbdc396e6eULL, 0x37c46ef395aac4c4ULL, + 0x0c03180f061b0303ULL, 0x45568a13acdc5656ULL, 0x0d441a49885e4444ULL, + 0xe17fdf9efea07f7fULL, 0x9ea921374f88a9a9ULL, 0xa82a4d8254672a2aULL, + 0xd6bbb16d6b0abbbbULL, 0x23c146e29f87c1c1ULL, 0x5153a202a6f15353ULL, + 0x57dcae8ba572dcdcULL, 0x2c0b582716530b0bULL, 0x4e9d9cd327019d9dULL, + 0xad6c47c1d82b6c6cULL, 0xc43195f562a43131ULL, 0xcd7487b9e8f37474ULL, + 0xfff6e309f115f6f6ULL, 0x05460a438c4c4646ULL, 0x8aac092645a5acacULL, + 0x1e893c970fb58989ULL, 0x5014a04428b41414ULL, 0xa3e15b42dfbae1e1ULL, + 0x5816b04e2ca61616ULL, 0xe83acdd274f73a3aULL, 0xb9696fd0d2066969ULL, + 0x2409482d12410909ULL, 0xdd70a7ade0d77070ULL, 0xe2b6d954716fb6b6ULL, + 0x67d0ceb7bd1ed0d0ULL, 0x93ed3b7ec7d6ededULL, 0x17cc2edb85e2ccccULL, + 0x15422a5784684242ULL, 0x5a98b4c22d2c9898ULL, 0xaaa4490e55eda4a4ULL, + 0xa0285d8850752828ULL, 0x6d5cda31b8865c5cULL, 0xc7f8933fed6bf8f8ULL, + 0x228644a411c28686ULL, +}; + +static const u64 C7[256] = { + 0x186018c07830d818ULL, 0x238c2305af462623ULL, 0xc63fc67ef991b8c6ULL, + 0xe887e8136fcdfbe8ULL, 0x8726874ca113cb87ULL, 0xb8dab8a9626d11b8ULL, + 0x0104010805020901ULL, 0x4f214f426e9e0d4fULL, 0x36d836adee6c9b36ULL, + 0xa6a2a6590451ffa6ULL, 0xd26fd2debdb90cd2ULL, 0xf5f3f5fb06f70ef5ULL, + 0x79f979ef80f29679ULL, 0x6fa16f5fcede306fULL, 0x917e91fcef3f6d91ULL, + 0x525552aa07a4f852ULL, 0x609d6027fdc04760ULL, 0xbccabc89766535bcULL, + 0x9b569baccd2b379bULL, 0x8e028e048c018a8eULL, 0xa3b6a371155bd2a3ULL, + 0x0c300c603c186c0cULL, 0x7bf17bff8af6847bULL, 0x35d435b5e16a8035ULL, + 0x1d741de8693af51dULL, 0xe0a7e05347ddb3e0ULL, 0xd77bd7f6acb321d7ULL, + 0xc22fc25eed999cc2ULL, 0x2eb82e6d965c432eULL, 0x4b314b627a96294bULL, + 0xfedffea321e15dfeULL, 0x5741578216aed557ULL, 0x155415a8412abd15ULL, + 0x77c1779fb6eee877ULL, 0x37dc37a5eb6e9237ULL, 0xe5b3e57b56d79ee5ULL, + 0x9f469f8cd923139fULL, 0xf0e7f0d317fd23f0ULL, 0x4a354a6a7f94204aULL, + 0xda4fda9e95a944daULL, 0x587d58fa25b0a258ULL, 0xc903c906ca8fcfc9ULL, + 0x29a429558d527c29ULL, 0x0a280a5022145a0aULL, 0xb1feb1e14f7f50b1ULL, + 0xa0baa0691a5dc9a0ULL, 0x6bb16b7fdad6146bULL, 0x852e855cab17d985ULL, + 0xbdcebd8173673cbdULL, 0x5d695dd234ba8f5dULL, 0x1040108050209010ULL, + 0xf4f7f4f303f507f4ULL, 0xcb0bcb16c08bddcbULL, 0x3ef83eedc67cd33eULL, + 0x05140528110a2d05ULL, 0x6781671fe6ce7867ULL, 0xe4b7e47353d597e4ULL, + 0x279c2725bb4e0227ULL, 0x4119413258827341ULL, 0x8b168b2c9d0ba78bULL, + 0xa7a6a7510153f6a7ULL, 0x7de97dcf94fab27dULL, 0x956e95dcfb374995ULL, + 0xd847d88e9fad56d8ULL, 0xfbcbfb8b30eb70fbULL, 0xee9fee2371c1cdeeULL, + 0x7ced7cc791f8bb7cULL, 0x66856617e3cc7166ULL, 0xdd53dda68ea77bddULL, + 0x175c17b84b2eaf17ULL, 0x47014702468e4547ULL, 0x9e429e84dc211a9eULL, + 0xca0fca1ec589d4caULL, 0x2db42d75995a582dULL, 0xbfc6bf9179632ebfULL, + 0x071c07381b0e3f07ULL, 0xad8ead012347acadULL, 0x5a755aea2fb4b05aULL, + 0x8336836cb51bef83ULL, 0x33cc3385ff66b633ULL, 0x6391633ff2c65c63ULL, + 0x020802100a041202ULL, 0xaa92aa39384993aaULL, 0x71d971afa8e2de71ULL, + 0xc807c80ecf8dc6c8ULL, 0x196419c87d32d119ULL, 0x4939497270923b49ULL, + 0xd943d9869aaf5fd9ULL, 0xf2eff2c31df931f2ULL, 0xe3abe34b48dba8e3ULL, + 0x5b715be22ab6b95bULL, 0x881a8834920dbc88ULL, 0x9a529aa4c8293e9aULL, + 0x2698262dbe4c0b26ULL, 0x32c8328dfa64bf32ULL, 0xb0fab0e94a7d59b0ULL, + 0xe983e91b6acff2e9ULL, 0x0f3c0f78331e770fULL, 0xd573d5e6a6b733d5ULL, + 0x803a8074ba1df480ULL, 0xbec2be997c6127beULL, 0xcd13cd26de87ebcdULL, + 0x34d034bde4688934ULL, 0x483d487a75903248ULL, 0xffdbffab24e354ffULL, + 0x7af57af78ff48d7aULL, 0x907a90f4ea3d6490ULL, 0x5f615fc23ebe9d5fULL, + 0x2080201da0403d20ULL, 0x68bd6867d5d00f68ULL, 0x1a681ad07234ca1aULL, + 0xae82ae192c41b7aeULL, 0xb4eab4c95e757db4ULL, 0x544d549a19a8ce54ULL, + 0x937693ece53b7f93ULL, 0x2288220daa442f22ULL, 0x648d6407e9c86364ULL, + 0xf1e3f1db12ff2af1ULL, 0x73d173bfa2e6cc73ULL, 0x124812905a248212ULL, + 0x401d403a5d807a40ULL, 0x0820084028104808ULL, 0xc32bc356e89b95c3ULL, + 0xec97ec337bc5dfecULL, 0xdb4bdb9690ab4ddbULL, 0xa1bea1611f5fc0a1ULL, + 0x8d0e8d1c8307918dULL, 0x3df43df5c97ac83dULL, 0x976697ccf1335b97ULL, + 0x0000000000000000ULL, 0xcf1bcf36d483f9cfULL, 0x2bac2b4587566e2bULL, + 0x76c57697b3ece176ULL, 0x82328264b019e682ULL, 0xd67fd6fea9b128d6ULL, + 0x1b6c1bd87736c31bULL, 0xb5eeb5c15b7774b5ULL, 0xaf86af112943beafULL, + 0x6ab56a77dfd41d6aULL, 0x505d50ba0da0ea50ULL, 0x450945124c8a5745ULL, + 0xf3ebf3cb18fb38f3ULL, 0x30c0309df060ad30ULL, 0xef9bef2b74c3c4efULL, + 0x3ffc3fe5c37eda3fULL, 0x554955921caac755ULL, 0xa2b2a2791059dba2ULL, + 0xea8fea0365c9e9eaULL, 0x6589650fecca6a65ULL, 0xbad2bab9686903baULL, + 0x2fbc2f65935e4a2fULL, 0xc027c04ee79d8ec0ULL, 0xde5fdebe81a160deULL, + 0x1c701ce06c38fc1cULL, 0xfdd3fdbb2ee746fdULL, 0x4d294d52649a1f4dULL, + 0x927292e4e0397692ULL, 0x75c9758fbceafa75ULL, 0x061806301e0c3606ULL, + 0x8a128a249809ae8aULL, 0xb2f2b2f940794bb2ULL, 0xe6bfe66359d185e6ULL, + 0x0e380e70361c7e0eULL, 0x1f7c1ff8633ee71fULL, 0x62956237f7c45562ULL, + 0xd477d4eea3b53ad4ULL, 0xa89aa829324d81a8ULL, 0x966296c4f4315296ULL, + 0xf9c3f99b3aef62f9ULL, 0xc533c566f697a3c5ULL, 0x25942535b14a1025ULL, + 0x597959f220b2ab59ULL, 0x842a8454ae15d084ULL, 0x72d572b7a7e4c572ULL, + 0x39e439d5dd72ec39ULL, 0x4c2d4c5a6198164cULL, 0x5e655eca3bbc945eULL, + 0x78fd78e785f09f78ULL, 0x38e038ddd870e538ULL, 0x8c0a8c148605988cULL, + 0xd163d1c6b2bf17d1ULL, 0xa5aea5410b57e4a5ULL, 0xe2afe2434dd9a1e2ULL, + 0x6199612ff8c24e61ULL, 0xb3f6b3f1457b42b3ULL, 0x21842115a5423421ULL, + 0x9c4a9c94d625089cULL, 0x1e781ef0663cee1eULL, 0x4311432252866143ULL, + 0xc73bc776fc93b1c7ULL, 0xfcd7fcb32be54ffcULL, 0x0410042014082404ULL, + 0x515951b208a2e351ULL, 0x995e99bcc72f2599ULL, 0x6da96d4fc4da226dULL, + 0x0d340d68391a650dULL, 0xfacffa8335e979faULL, 0xdf5bdfb684a369dfULL, + 0x7ee57ed79bfca97eULL, 0x2490243db4481924ULL, 0x3bec3bc5d776fe3bULL, + 0xab96ab313d4b9aabULL, 0xce1fce3ed181f0ceULL, 0x1144118855229911ULL, + 0x8f068f0c8903838fULL, 0x4e254e4a6b9c044eULL, 0xb7e6b7d1517366b7ULL, + 0xeb8beb0b60cbe0ebULL, 0x3cf03cfdcc78c13cULL, 0x813e817cbf1ffd81ULL, + 0x946a94d4fe354094ULL, 0xf7fbf7eb0cf31cf7ULL, 0xb9deb9a1676f18b9ULL, + 0x134c13985f268b13ULL, 0x2cb02c7d9c58512cULL, 0xd36bd3d6b8bb05d3ULL, + 0xe7bbe76b5cd38ce7ULL, 0x6ea56e57cbdc396eULL, 0xc437c46ef395aac4ULL, + 0x030c03180f061b03ULL, 0x5645568a13acdc56ULL, 0x440d441a49885e44ULL, + 0x7fe17fdf9efea07fULL, 0xa99ea921374f88a9ULL, 0x2aa82a4d8254672aULL, + 0xbbd6bbb16d6b0abbULL, 0xc123c146e29f87c1ULL, 0x535153a202a6f153ULL, + 0xdc57dcae8ba572dcULL, 0x0b2c0b582716530bULL, 0x9d4e9d9cd327019dULL, + 0x6cad6c47c1d82b6cULL, 0x31c43195f562a431ULL, 0x74cd7487b9e8f374ULL, + 0xf6fff6e309f115f6ULL, 0x4605460a438c4c46ULL, 0xac8aac092645a5acULL, + 0x891e893c970fb589ULL, 0x145014a04428b414ULL, 0xe1a3e15b42dfbae1ULL, + 0x165816b04e2ca616ULL, 0x3ae83acdd274f73aULL, 0x69b9696fd0d20669ULL, + 0x092409482d124109ULL, 0x70dd70a7ade0d770ULL, 0xb6e2b6d954716fb6ULL, + 0xd067d0ceb7bd1ed0ULL, 0xed93ed3b7ec7d6edULL, 0xcc17cc2edb85e2ccULL, + 0x4215422a57846842ULL, 0x985a98b4c22d2c98ULL, 0xa4aaa4490e55eda4ULL, + 0x28a0285d88507528ULL, 0x5c6d5cda31b8865cULL, 0xf8c7f8933fed6bf8ULL, + 0x86228644a411c286ULL, +}; + +static const u64 rc[WHIRLPOOL_ROUNDS + 1] = { + 0x0000000000000000ULL, 0x1823c6e887b8014fULL, 0x36a6d2f5796f9152ULL, + 0x60bc9b8ea30c7b35ULL, 0x1de0d7c22e4bfe57ULL, 0x157737e59ff04adaULL, + 0x58c9290ab1a06b85ULL, 0xbd5d10f4cb3e0567ULL, 0xe427418ba77d95d8ULL, + 0xfbee7c66dd17479eULL, 0xca2dbf07ad5a8333ULL, +}; + +/** + * The core Whirlpool transform. + */ + +static void whirlpool_process_buffer(struct whirlpool_ctx *wctx) { + int i, r; + u64 K[8]; /* the round key */ + u64 block[8]; /* mu(buffer) */ + u64 state[8]; /* the cipher state */ + u64 L[8]; + u8 *buffer = wctx->buffer; + + for (i = 0; i < 8; i++, buffer += 8) { + block[i] = + (((u64)buffer[0] ) << 56) ^ + (((u64)buffer[1] & 0xffL) << 48) ^ + (((u64)buffer[2] & 0xffL) << 40) ^ + (((u64)buffer[3] & 0xffL) << 32) ^ + (((u64)buffer[4] & 0xffL) << 24) ^ + (((u64)buffer[5] & 0xffL) << 16) ^ + (((u64)buffer[6] & 0xffL) << 8) ^ + (((u64)buffer[7] & 0xffL) ); + } + + state[0] = block[0] ^ (K[0] = wctx->hash[0]); + state[1] = block[1] ^ (K[1] = wctx->hash[1]); + state[2] = block[2] ^ (K[2] = wctx->hash[2]); + state[3] = block[3] ^ (K[3] = wctx->hash[3]); + state[4] = block[4] ^ (K[4] = wctx->hash[4]); + state[5] = block[5] ^ (K[5] = wctx->hash[5]); + state[6] = block[6] ^ (K[6] = wctx->hash[6]); + state[7] = block[7] ^ (K[7] = wctx->hash[7]); + + for (r = 1; r <= WHIRLPOOL_ROUNDS; r++) { + + L[0] = C0[(int)(K[0] >> 56) ] ^ + C1[(int)(K[7] >> 48) & 0xff] ^ + C2[(int)(K[6] >> 40) & 0xff] ^ + C3[(int)(K[5] >> 32) & 0xff] ^ + C4[(int)(K[4] >> 24) & 0xff] ^ + C5[(int)(K[3] >> 16) & 0xff] ^ + C6[(int)(K[2] >> 8) & 0xff] ^ + C7[(int)(K[1] ) & 0xff] ^ + rc[r]; + + L[1] = C0[(int)(K[1] >> 56) ] ^ + C1[(int)(K[0] >> 48) & 0xff] ^ + C2[(int)(K[7] >> 40) & 0xff] ^ + C3[(int)(K[6] >> 32) & 0xff] ^ + C4[(int)(K[5] >> 24) & 0xff] ^ + C5[(int)(K[4] >> 16) & 0xff] ^ + C6[(int)(K[3] >> 8) & 0xff] ^ + C7[(int)(K[2] ) & 0xff]; + + L[2] = C0[(int)(K[2] >> 56) ] ^ + C1[(int)(K[1] >> 48) & 0xff] ^ + C2[(int)(K[0] >> 40) & 0xff] ^ + C3[(int)(K[7] >> 32) & 0xff] ^ + C4[(int)(K[6] >> 24) & 0xff] ^ + C5[(int)(K[5] >> 16) & 0xff] ^ + C6[(int)(K[4] >> 8) & 0xff] ^ + C7[(int)(K[3] ) & 0xff]; + + L[3] = C0[(int)(K[3] >> 56) ] ^ + C1[(int)(K[2] >> 48) & 0xff] ^ + C2[(int)(K[1] >> 40) & 0xff] ^ + C3[(int)(K[0] >> 32) & 0xff] ^ + C4[(int)(K[7] >> 24) & 0xff] ^ + C5[(int)(K[6] >> 16) & 0xff] ^ + C6[(int)(K[5] >> 8) & 0xff] ^ + C7[(int)(K[4] ) & 0xff]; + + L[4] = C0[(int)(K[4] >> 56) ] ^ + C1[(int)(K[3] >> 48) & 0xff] ^ + C2[(int)(K[2] >> 40) & 0xff] ^ + C3[(int)(K[1] >> 32) & 0xff] ^ + C4[(int)(K[0] >> 24) & 0xff] ^ + C5[(int)(K[7] >> 16) & 0xff] ^ + C6[(int)(K[6] >> 8) & 0xff] ^ + C7[(int)(K[5] ) & 0xff]; + + L[5] = C0[(int)(K[5] >> 56) ] ^ + C1[(int)(K[4] >> 48) & 0xff] ^ + C2[(int)(K[3] >> 40) & 0xff] ^ + C3[(int)(K[2] >> 32) & 0xff] ^ + C4[(int)(K[1] >> 24) & 0xff] ^ + C5[(int)(K[0] >> 16) & 0xff] ^ + C6[(int)(K[7] >> 8) & 0xff] ^ + C7[(int)(K[6] ) & 0xff]; + + L[6] = C0[(int)(K[6] >> 56) ] ^ + C1[(int)(K[5] >> 48) & 0xff] ^ + C2[(int)(K[4] >> 40) & 0xff] ^ + C3[(int)(K[3] >> 32) & 0xff] ^ + C4[(int)(K[2] >> 24) & 0xff] ^ + C5[(int)(K[1] >> 16) & 0xff] ^ + C6[(int)(K[0] >> 8) & 0xff] ^ + C7[(int)(K[7] ) & 0xff]; + + L[7] = C0[(int)(K[7] >> 56) ] ^ + C1[(int)(K[6] >> 48) & 0xff] ^ + C2[(int)(K[5] >> 40) & 0xff] ^ + C3[(int)(K[4] >> 32) & 0xff] ^ + C4[(int)(K[3] >> 24) & 0xff] ^ + C5[(int)(K[2] >> 16) & 0xff] ^ + C6[(int)(K[1] >> 8) & 0xff] ^ + C7[(int)(K[0] ) & 0xff]; + + K[0] = L[0]; + K[1] = L[1]; + K[2] = L[2]; + K[3] = L[3]; + K[4] = L[4]; + K[5] = L[5]; + K[6] = L[6]; + K[7] = L[7]; + + L[0] = C0[(int)(state[0] >> 56) ] ^ + C1[(int)(state[7] >> 48) & 0xff] ^ + C2[(int)(state[6] >> 40) & 0xff] ^ + C3[(int)(state[5] >> 32) & 0xff] ^ + C4[(int)(state[4] >> 24) & 0xff] ^ + C5[(int)(state[3] >> 16) & 0xff] ^ + C6[(int)(state[2] >> 8) & 0xff] ^ + C7[(int)(state[1] ) & 0xff] ^ + K[0]; + + L[1] = C0[(int)(state[1] >> 56) ] ^ + C1[(int)(state[0] >> 48) & 0xff] ^ + C2[(int)(state[7] >> 40) & 0xff] ^ + C3[(int)(state[6] >> 32) & 0xff] ^ + C4[(int)(state[5] >> 24) & 0xff] ^ + C5[(int)(state[4] >> 16) & 0xff] ^ + C6[(int)(state[3] >> 8) & 0xff] ^ + C7[(int)(state[2] ) & 0xff] ^ + K[1]; + + L[2] = C0[(int)(state[2] >> 56) ] ^ + C1[(int)(state[1] >> 48) & 0xff] ^ + C2[(int)(state[0] >> 40) & 0xff] ^ + C3[(int)(state[7] >> 32) & 0xff] ^ + C4[(int)(state[6] >> 24) & 0xff] ^ + C5[(int)(state[5] >> 16) & 0xff] ^ + C6[(int)(state[4] >> 8) & 0xff] ^ + C7[(int)(state[3] ) & 0xff] ^ + K[2]; + + L[3] = C0[(int)(state[3] >> 56) ] ^ + C1[(int)(state[2] >> 48) & 0xff] ^ + C2[(int)(state[1] >> 40) & 0xff] ^ + C3[(int)(state[0] >> 32) & 0xff] ^ + C4[(int)(state[7] >> 24) & 0xff] ^ + C5[(int)(state[6] >> 16) & 0xff] ^ + C6[(int)(state[5] >> 8) & 0xff] ^ + C7[(int)(state[4] ) & 0xff] ^ + K[3]; + + L[4] = C0[(int)(state[4] >> 56) ] ^ + C1[(int)(state[3] >> 48) & 0xff] ^ + C2[(int)(state[2] >> 40) & 0xff] ^ + C3[(int)(state[1] >> 32) & 0xff] ^ + C4[(int)(state[0] >> 24) & 0xff] ^ + C5[(int)(state[7] >> 16) & 0xff] ^ + C6[(int)(state[6] >> 8) & 0xff] ^ + C7[(int)(state[5] ) & 0xff] ^ + K[4]; + + L[5] = C0[(int)(state[5] >> 56) ] ^ + C1[(int)(state[4] >> 48) & 0xff] ^ + C2[(int)(state[3] >> 40) & 0xff] ^ + C3[(int)(state[2] >> 32) & 0xff] ^ + C4[(int)(state[1] >> 24) & 0xff] ^ + C5[(int)(state[0] >> 16) & 0xff] ^ + C6[(int)(state[7] >> 8) & 0xff] ^ + C7[(int)(state[6] ) & 0xff] ^ + K[5]; + + L[6] = C0[(int)(state[6] >> 56) ] ^ + C1[(int)(state[5] >> 48) & 0xff] ^ + C2[(int)(state[4] >> 40) & 0xff] ^ + C3[(int)(state[3] >> 32) & 0xff] ^ + C4[(int)(state[2] >> 24) & 0xff] ^ + C5[(int)(state[1] >> 16) & 0xff] ^ + C6[(int)(state[0] >> 8) & 0xff] ^ + C7[(int)(state[7] ) & 0xff] ^ + K[6]; + + L[7] = C0[(int)(state[7] >> 56) ] ^ + C1[(int)(state[6] >> 48) & 0xff] ^ + C2[(int)(state[5] >> 40) & 0xff] ^ + C3[(int)(state[4] >> 32) & 0xff] ^ + C4[(int)(state[3] >> 24) & 0xff] ^ + C5[(int)(state[2] >> 16) & 0xff] ^ + C6[(int)(state[1] >> 8) & 0xff] ^ + C7[(int)(state[0] ) & 0xff] ^ + K[7]; + + state[0] = L[0]; + state[1] = L[1]; + state[2] = L[2]; + state[3] = L[3]; + state[4] = L[4]; + state[5] = L[5]; + state[6] = L[6]; + state[7] = L[7]; + } + /* + * apply the Miyaguchi-Preneel compression function: + */ + wctx->hash[0] ^= state[0] ^ block[0]; + wctx->hash[1] ^= state[1] ^ block[1]; + wctx->hash[2] ^= state[2] ^ block[2]; + wctx->hash[3] ^= state[3] ^ block[3]; + wctx->hash[4] ^= state[4] ^ block[4]; + wctx->hash[5] ^= state[5] ^ block[5]; + wctx->hash[6] ^= state[6] ^ block[6]; + wctx->hash[7] ^= state[7] ^ block[7]; + +} + +static void whirlpool_init (void *ctx) { + int i; + struct whirlpool_ctx *wctx = ctx; + + memset(wctx->bitLength, 0, 32); + wctx->bufferBits = wctx->bufferPos = 0; + wctx->buffer[0] = 0; + for (i = 0; i < 8; i++) { + wctx->hash[i] = 0L; + } +} + +static void whirlpool_update(void *ctx, const u8 *source, unsigned int len) +{ + + struct whirlpool_ctx *wctx = ctx; + int sourcePos = 0; + unsigned int bits_len = len * 8; // convert to number of bits + int sourceGap = (8 - ((int)bits_len & 7)) & 7; + int bufferRem = wctx->bufferBits & 7; + int i; + u32 b, carry; + u8 *buffer = wctx->buffer; + u8 *bitLength = wctx->bitLength; + int bufferBits = wctx->bufferBits; + int bufferPos = wctx->bufferPos; + + u64 value = bits_len; + for (i = 31, carry = 0; i >= 0 && (carry != 0 || value != 0ULL); i--) { + carry += bitLength[i] + ((u32)value & 0xff); + bitLength[i] = (u8)carry; + carry >>= 8; + value >>= 8; + } + while (bits_len > 8) { + b = ((source[sourcePos] << sourceGap) & 0xff) | + ((source[sourcePos + 1] & 0xff) >> (8 - sourceGap)); + buffer[bufferPos++] |= (u8)(b >> bufferRem); + bufferBits += 8 - bufferRem; + if (bufferBits == WHIRLPOOL_DIGEST_SIZE * 8) { + whirlpool_process_buffer(wctx); + bufferBits = bufferPos = 0; + } + buffer[bufferPos] = b << (8 - bufferRem); + bufferBits += bufferRem; + bits_len -= 8; + sourcePos++; + } + if (bits_len > 0) { + b = (source[sourcePos] << sourceGap) & 0xff; + buffer[bufferPos] |= b >> bufferRem; + } else { + b = 0; + } + if (bufferRem + bits_len < 8) { + bufferBits += bits_len; + } else { + bufferPos++; + bufferBits += 8 - bufferRem; + bits_len -= 8 - bufferRem; + if (bufferBits == WHIRLPOOL_DIGEST_SIZE * 8) { + whirlpool_process_buffer(wctx); + bufferBits = bufferPos = 0; + } + buffer[bufferPos] = b << (8 - bufferRem); + bufferBits += (int)bits_len; + } + + wctx->bufferBits = bufferBits; + wctx->bufferPos = bufferPos; + +} + +static void whirlpool_final(void *ctx, u8 *out) +{ + struct whirlpool_ctx *wctx = ctx; + int i; + u8 *buffer = wctx->buffer; + u8 *bitLength = wctx->bitLength; + int bufferBits = wctx->bufferBits; + int bufferPos = wctx->bufferPos; + u8 *digest = out; + + buffer[bufferPos] |= 0x80U >> (bufferBits & 7); + bufferPos++; + if (bufferPos > WHIRLPOOL_BLOCK_SIZE - WHIRLPOOL_LENGTHBYTES) { + if (bufferPos < WHIRLPOOL_BLOCK_SIZE) { + memset(&buffer[bufferPos], 0, WHIRLPOOL_BLOCK_SIZE - bufferPos); + } + whirlpool_process_buffer(wctx); + bufferPos = 0; + } + if (bufferPos < WHIRLPOOL_BLOCK_SIZE - WHIRLPOOL_LENGTHBYTES) { + memset(&buffer[bufferPos], 0, + (WHIRLPOOL_BLOCK_SIZE - WHIRLPOOL_LENGTHBYTES) - bufferPos); + } + bufferPos = WHIRLPOOL_BLOCK_SIZE - WHIRLPOOL_LENGTHBYTES; + memcpy(&buffer[WHIRLPOOL_BLOCK_SIZE - WHIRLPOOL_LENGTHBYTES], + bitLength, WHIRLPOOL_LENGTHBYTES); + whirlpool_process_buffer(wctx); + for (i = 0; i < WHIRLPOOL_DIGEST_SIZE/8; i++) { + digest[0] = (u8)(wctx->hash[i] >> 56); + digest[1] = (u8)(wctx->hash[i] >> 48); + digest[2] = (u8)(wctx->hash[i] >> 40); + digest[3] = (u8)(wctx->hash[i] >> 32); + digest[4] = (u8)(wctx->hash[i] >> 24); + digest[5] = (u8)(wctx->hash[i] >> 16); + digest[6] = (u8)(wctx->hash[i] >> 8); + digest[7] = (u8)(wctx->hash[i] ); + digest += 8; + } + wctx->bufferBits = bufferBits; + wctx->bufferPos = bufferPos; +} + +static struct crypto_alg alg = { + .cra_name = "whirlpool", + .cra_flags = CRYPTO_ALG_TYPE_DIGEST, + .cra_blocksize = WHIRLPOOL_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct whirlpool_ctx), + .cra_module = THIS_MODULE, + .cra_list = LIST_HEAD_INIT(alg.cra_list), + .cra_u = { .digest = { + .dia_digestsize = WHIRLPOOL_DIGEST_SIZE, + .dia_init = whirlpool_init, + .dia_update = whirlpool_update, + .dia_final = whirlpool_final } } +}; + +static int __init init(void) +{ + return crypto_register_alg(&alg); +} + +static void __exit fini(void) +{ + crypto_unregister_alg(&alg); +} + +module_init(init); +module_exit(fini); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Whirlpool Message Digest Algorithm"); diff -Nru a/drivers/atm/idt77252.c b/drivers/atm/idt77252.c --- a/drivers/atm/idt77252.c 2004-08-25 22:01:55 -07:00 +++ b/drivers/atm/idt77252.c 2004-08-25 22:01:55 -07:00 @@ -3681,18 +3681,25 @@ struct idt77252_dev *card; struct atm_dev *dev; ushort revision = 0; - int i; + int i, err; + if (pci_enable_device(pcidev)) { + printk("idt77252: can't enable PCI device at %s\n", pci_name(pcidev)); + return -ENODEV; + } + if (pci_read_config_word(pcidev, PCI_REVISION_ID, &revision)) { printk("idt77252-%d: can't read PCI_REVISION_ID\n", index); - return -ENODEV; + err = -ENODEV; + goto err_out_disable_pdev; } card = kmalloc(sizeof(struct idt77252_dev), GFP_KERNEL); if (!card) { printk("idt77252-%d: can't allocate private data\n", index); - return -ENOMEM; + err = -ENOMEM; + goto err_out_disable_pdev; } memset(card, 0, sizeof(struct idt77252_dev)); @@ -3718,23 +3725,21 @@ card->membase = (unsigned long) ioremap(membase, 1024); if (!card->membase) { printk("%s: can't ioremap() membase\n", card->name); - kfree(card); - return -EIO; + err = -EIO; + goto err_out_free_card; } if (idt77252_preset(card)) { printk("%s: preset failed\n", card->name); - iounmap((void *) card->membase); - kfree(card); - return -EIO; + err = -EIO; + goto err_out_iounmap; } dev = atm_dev_register("idt77252", &idt77252_ops, -1, NULL); if (!dev) { printk("%s: can't register atm device\n", card->name); - iounmap((void *) card->membase); - kfree(card); - return -EIO; + err = -EIO; + goto err_out_iounmap; } dev->dev_data = card; card->atmdev = dev; @@ -3743,9 +3748,8 @@ suni_init(dev); if (!dev->phy) { printk("%s: can't init SUNI\n", card->name); - deinit_card(card); - kfree(card); - return -EIO; + err = -EIO; + goto err_out_deinit_card; } #endif /* CONFIG_ATM_IDT77252_USE_SUNI */ @@ -3756,9 +3760,8 @@ ioremap(srambase | 0x200000 | (i << 18), 4); if (!card->fbq[i]) { printk("%s: can't ioremap() FBQ%d\n", card->name, i); - deinit_card(card); - kfree(card); - return -EIO; + err = -EIO; + goto err_out_deinit_card; } } @@ -3769,9 +3772,8 @@ if (init_card(dev)) { printk("%s: init_card failed\n", card->name); - deinit_card(card); - kfree(card); - return -EIO; + err = -EIO; + goto err_out_deinit_card; } dev->ci_range.vpi_bits = card->vpibits; @@ -3783,12 +3785,8 @@ if (idt77252_dev_open(card)) { printk("%s: dev_open failed\n", card->name); - - if (dev->phy->stop) - dev->phy->stop(dev); - deinit_card(card); - kfree(card); - return -EIO; + err = -EIO; + goto err_out_stop; } *last = card; @@ -3796,6 +3794,23 @@ index++; return 0; + +err_out_stop: + if (dev->phy->stop) + dev->phy->stop(dev); + +err_out_deinit_card: + deinit_card(card); + +err_out_iounmap: + iounmap((void *) card->membase); + +err_out_free_card: + kfree(card); + +err_out_disable_pdev: + pci_disable_device(pcidev); + return err; } static struct pci_device_id idt77252_pci_tbl[] = @@ -3848,6 +3863,7 @@ if (dev->phy->stop) dev->phy->stop(dev); deinit_card(card); + pci_disable_device(card->pcidev); kfree(card); } diff -Nru a/drivers/base/class.c b/drivers/base/class.c --- a/drivers/base/class.c 2004-08-25 22:01:56 -07:00 +++ b/drivers/base/class.c 2004-08-25 22:01:56 -07:00 @@ -349,13 +349,18 @@ int class_device_add(struct class_device *class_dev) { - struct class * parent; + struct class * parent = NULL; struct class_interface * class_intf; int error; class_dev = class_device_get(class_dev); - if (!class_dev || !strlen(class_dev->class_id)) + if (!class_dev) return -EINVAL; + + if (!strlen(class_dev->class_id)) { + error = -EINVAL; + goto register_done; + } parent = class_get(class_dev->class); diff -Nru a/drivers/base/node.c b/drivers/base/node.c --- a/drivers/base/node.c 2004-08-25 22:01:54 -07:00 +++ b/drivers/base/node.c 2004-08-25 22:01:54 -07:00 @@ -19,7 +19,7 @@ static ssize_t node_read_cpumap(struct sys_device * dev, char * buf) { struct node *node_dev = to_node(dev); - cpumask_t mask = node_dev->cpumap; + cpumask_t mask = node_to_cpumask(node_dev->sysdev.id); int len; /* 2004/06/03: buf currently PAGE_SIZE, need > 1 char per 4 bits. */ @@ -38,11 +38,19 @@ int n; int nid = dev->id; struct sysinfo i; + unsigned long inactive; + unsigned long active; + unsigned long free; + si_meminfo_node(&i, nid); + __get_zone_counts(&active, &inactive, &free, NODE_DATA(nid)); + n = sprintf(buf, "\n" "Node %d MemTotal: %8lu kB\n" "Node %d MemFree: %8lu kB\n" "Node %d MemUsed: %8lu kB\n" + "Node %d Active: %8lu kB\n" + "Node %d Inactive: %8lu kB\n" "Node %d HighTotal: %8lu kB\n" "Node %d HighFree: %8lu kB\n" "Node %d LowTotal: %8lu kB\n" @@ -50,6 +58,8 @@ nid, K(i.totalram), nid, K(i.freeram), nid, K(i.totalram - i.freeram), + nid, K(active), + nid, K(inactive), nid, K(i.totalhigh), nid, K(i.freehigh), nid, K(i.totalram - i.totalhigh), @@ -111,7 +121,6 @@ { int error; - node->cpumap = node_to_cpumask(num); node->sysdev.id = num; node->sysdev.cls = &node_class; error = sysdev_register(&node->sysdev); diff -Nru a/drivers/block/rd.c b/drivers/block/rd.c --- a/drivers/block/rd.c 2004-08-25 22:01:55 -07:00 +++ b/drivers/block/rd.c 2004-08-25 22:01:55 -07:00 @@ -349,13 +349,17 @@ if (rd_bdev[unit] == NULL) { struct block_device *bdev = inode->i_bdev; struct address_space *mapping; + unsigned bsize; int gfp_mask; inode = igrab(bdev->bd_inode); rd_bdev[unit] = bdev; bdev->bd_openers++; - bdev->bd_block_size = rd_blocksize; - inode->i_size = get_capacity(rd_disks[unit])<<9; + bsize = bdev_hardsect_size(bdev); + bdev->bd_block_size = bsize; + inode->i_blkbits = blksize_bits(bsize); + inode->i_size = get_capacity(bdev->bd_disk)<<9; + mapping = inode->i_mapping; mapping->a_ops = &ramdisk_aops; mapping->backing_dev_info = &rd_backing_dev_info; @@ -449,6 +453,7 @@ goto out_queue; blk_queue_make_request(rd_queue[i], &rd_make_request); + blk_queue_hardsect_size(rd_queue[i], rd_blocksize); /* rd_size is given in kB */ disk->major = RAMDISK_MAJOR; diff -Nru a/drivers/block/scsi_ioctl.c b/drivers/block/scsi_ioctl.c --- a/drivers/block/scsi_ioctl.c 2004-08-25 22:01:56 -07:00 +++ b/drivers/block/scsi_ioctl.c 2004-08-25 22:01:56 -07:00 @@ -178,6 +178,7 @@ safe_for_write(GPCMD_SEND_EVENT), safe_for_write(GPCMD_SEND_KEY), safe_for_write(GPCMD_SEND_OPC), + safe_for_write(GPCMD_SEND_CUE_SHEET), safe_for_write(GPCMD_SET_SPEED), safe_for_write(GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL), safe_for_write(GPCMD_LOAD_UNLOAD), diff -Nru a/drivers/char/Makefile b/drivers/char/Makefile --- a/drivers/char/Makefile 2004-08-25 22:01:56 -07:00 +++ b/drivers/char/Makefile 2004-08-25 22:01:56 -07:00 @@ -7,8 +7,11 @@ # FONTMAPFILE = cp437.uni -obj-y += mem.o random.o tty_io.o n_tty.o tty_ioctl.o pty.o misc.o +obj-y += mem.o random.o tty_io.o n_tty.o tty_ioctl.o +obj-$(CONFIG_LEGACY_PTYS) += pty.o +obj-$(CONFIG_UNIX98_PTYS) += pty.o +obj-y += misc.o obj-$(CONFIG_VT) += vt_ioctl.o vc_screen.o consolemap.o \ consolemap_deftbl.o selection.o keyboard.o obj-$(CONFIG_HW_CONSOLE) += vt.o defkeymap.o diff -Nru a/drivers/char/amiserial.c b/drivers/char/amiserial.c --- a/drivers/char/amiserial.c 2004-08-25 22:01:56 -07:00 +++ b/drivers/char/amiserial.c 2004-08-25 22:01:56 -07:00 @@ -430,7 +430,7 @@ if ((info->flags & ASYNC_CHECK_CD) && (dstatus & SER_DCD)) { #if (defined(SERIAL_DEBUG_OPEN) || defined(SERIAL_DEBUG_INTR)) - printk("ttyS%02d CD now %s...", info->line, + printk("ttyS%d CD now %s...", info->line, (!(status & SER_DCD)) ? "on" : "off"); #endif if (!(status & SER_DCD)) @@ -2095,7 +2095,7 @@ continue; */ - printk(KERN_INFO "ttyS%02d is the amiga builtin serial port\n", + printk(KERN_INFO "ttyS%d is the amiga builtin serial port\n", state->line); /* Hardware set up */ diff -Nru a/drivers/char/ip2/ip2types.h b/drivers/char/ip2/ip2types.h --- a/drivers/char/ip2/ip2types.h 2004-08-25 22:01:56 -07:00 +++ b/drivers/char/ip2/ip2types.h 2004-08-25 22:01:56 -07:00 @@ -49,6 +49,9 @@ short irq[IP2_MAX_BOARDS]; unsigned short addr[IP2_MAX_BOARDS]; int type[IP2_MAX_BOARDS]; +#ifdef CONFIG_PCI + struct pci_dev *pci_dev[IP2_MAX_BOARDS]; +#endif } ip2config_t; #endif diff -Nru a/drivers/char/ip2main.c b/drivers/char/ip2main.c --- a/drivers/char/ip2main.c 2004-08-25 22:01:56 -07:00 +++ b/drivers/char/ip2main.c 2004-08-25 22:01:56 -07:00 @@ -440,6 +440,12 @@ // free memory for (i = 0; i < IP2_MAX_BOARDS; i++) { void *pB; +#ifdef CONFIG_PCI + if (ip2config.type[i] == PCI && ip2config.pci_dev[i]) { + pci_disable_device(ip2config.pci_dev[i]); + ip2config.pci_dev[i] = NULL; + } +#endif if ((pB = i2BoardPtrTable[i]) != 0 ) { kfree ( pB ); i2BoardPtrTable[i] = NULL; @@ -594,9 +600,14 @@ PCI_DEVICE_ID_COMPUTONE_IP2EX, pci_dev_i); if (pci_dev_i != NULL) { unsigned int addr; - unsigned char pci_irq; + if (pci_enable_device(pci_dev_i)) { + printk( KERN_ERR "IP2: can't enable PCI device at %s\n", + pci_name(pci_dev_i)); + break; + } ip2config.type[i] = PCI; + ip2config.pci_dev[i] = pci_dev_i; status = pci_read_config_dword(pci_dev_i, PCI_BASE_ADDRESS_1, &addr); if ( addr & 1 ) { @@ -604,8 +615,6 @@ } else { printk( KERN_ERR "IP2: PCI I/O address error\n"); } - status = - pci_read_config_byte(pci_dev_i, PCI_INTERRUPT_LINE, &pci_irq); // If the PCI BIOS assigned it, lets try and use it. If we // can't acquire it or it screws up, deal with it then. @@ -614,7 +623,7 @@ // printk( KERN_ERR "IP2: Bad PCI BIOS IRQ(%d)\n",pci_irq); // pci_irq = 0; // } - ip2config.irq[i] = pci_irq; + ip2config.irq[i] = pci_dev_i->irq; } else { // ann error ip2config.addr[i] = 0; if (status == PCIBIOS_DEVICE_NOT_FOUND) { diff -Nru a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c --- a/drivers/char/pcmcia/synclink_cs.c 2004-08-25 22:01:55 -07:00 +++ b/drivers/char/pcmcia/synclink_cs.c 2004-08-25 22:01:55 -07:00 @@ -1,7 +1,7 @@ /* * linux/drivers/char/pcmcia/synclink_cs.c * - * $Id: synclink_cs.c,v 4.22 2004/06/01 20:27:46 paulkf Exp $ + * $Id: synclink_cs.c,v 4.26 2004/08/11 19:30:02 paulkf Exp $ * * Device driver for Microgate SyncLink PC Card * multiprotocol serial adapter. @@ -68,6 +68,7 @@ #include #include #include +#include #include #include @@ -76,12 +77,8 @@ #include #include -#ifdef CONFIG_SYNCLINK_SYNCPPP_MODULE -#define CONFIG_SYNCLINK_SYNCPPP 1 -#endif - -#ifdef CONFIG_SYNCLINK_SYNCPPP -#include +#ifdef CONFIG_HDLC_MODULE +#define CONFIG_HDLC 1 #endif #define GET_USER(error,value,addr) error = get_user(value,addr) @@ -239,12 +236,11 @@ int netcount; int dosyncppp; spinlock_t netlock; -#ifdef CONFIG_SYNCLINK_SYNCPPP - struct ppp_device pppdev; - char netname[10]; + +#ifdef CONFIG_HDLC struct net_device *netdev; - struct net_device_stats netstats; #endif + } MGSLPC_INFO; #define MGSLPC_MAGIC 0x5402 @@ -262,7 +258,7 @@ * FIXME: PPC has PVR defined in asm/reg.h. For now we just undef it. */ #undef PVR - + #define RXFIFO 0 #define TXFIFO 0 #define STAR 0x20 @@ -398,18 +394,12 @@ static int ioctl_common(MGSLPC_INFO *info, unsigned int cmd, unsigned long arg); -#ifdef CONFIG_SYNCLINK_SYNCPPP -/* SPPP/HDLC stuff */ -static void mgslpc_sppp_init(MGSLPC_INFO *info); -static void mgslpc_sppp_delete(MGSLPC_INFO *info); -static int mgslpc_sppp_open(struct net_device *d); -static int mgslpc_sppp_close(struct net_device *d); -static void mgslpc_sppp_tx_timeout(struct net_device *d); -static int mgslpc_sppp_tx(struct sk_buff *skb, struct net_device *d); -static void mgslpc_sppp_rx_done(MGSLPC_INFO *info, char *buf, int size); -static void mgslpc_sppp_tx_done(MGSLPC_INFO *info); -static int mgslpc_sppp_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd); -struct net_device_stats *mgslpc_net_stats(struct net_device *dev); +#ifdef CONFIG_HDLC +#define dev_to_port(D) (dev_to_hdlc(D)->priv) +static void hdlcdev_tx_done(MGSLPC_INFO *info); +static void hdlcdev_rx(MGSLPC_INFO *info, char *buf, int size); +static int hdlcdev_init(MGSLPC_INFO *info); +static void hdlcdev_exit(MGSLPC_INFO *info); #endif static void trace_block(MGSLPC_INFO *info,const char* data, int count, int xmit); @@ -494,7 +484,7 @@ MODULE_LICENSE("GPL"); static char *driver_name = "SyncLink PC Card driver"; -static char *driver_version = "$Revision: 4.22 $"; +static char *driver_version = "$Revision: 4.26 $"; static struct tty_driver *serial_driver; @@ -1163,9 +1153,9 @@ info->drop_rts_on_tx_done = 0; } -#ifdef CONFIG_SYNCLINK_SYNCPPP +#ifdef CONFIG_HDLC if (info->netcount) - mgslpc_sppp_tx_done(info); + hdlcdev_tx_done(info); else #endif { @@ -1271,13 +1261,13 @@ info->icount.dcd++; if (info->serial_signals & SerialSignal_DCD) { info->input_signal_events.dcd_up++; -#ifdef CONFIG_SYNCLINK_SYNCPPP - if (info->netcount) - sppp_reopen(info->netdev); -#endif } else info->input_signal_events.dcd_down++; +#ifdef CONFIG_HDLC + if (info->netcount) + hdlc_set_carrier(info->serial_signals & SerialSignal_DCD, info->netdev); +#endif wake_up_interruptible(&info->status_event_wait_q); wake_up_interruptible(&info->event_wait_q); @@ -2876,7 +2866,7 @@ cleanup: if (retval) { if (tty->count == 1) - info->tty = NULL;/* tty layer will release tty struct */ + info->tty = NULL; /* tty layer will release tty struct */ if(info->count) info->count--; } @@ -2931,7 +2921,7 @@ if (info->icount.rxover) ret += sprintf(buf+ret, " rxover:%d", info->icount.rxover); if (info->icount.rxcrc) - ret += sprintf(buf+ret, " rxlong:%d", info->icount.rxcrc); + ret += sprintf(buf+ret, " rxcrc:%d", info->icount.rxcrc); } else { ret += sprintf(buf+ret, " ASYNC tx:%d rx:%d", info->icount.tx, info->icount.rx); @@ -3070,12 +3060,8 @@ printk( "SyncLink PC Card %s:IO=%04X IRQ=%d\n", info->device_name, info->io_base, info->irq_level); - -#ifdef CONFIG_SYNCLINK_SYNCPPP -#ifdef MODULE - if (info->dosyncppp) -#endif - mgslpc_sppp_init(info); +#ifdef CONFIG_HDLC + hdlcdev_init(info); #endif } @@ -3090,9 +3076,8 @@ last->next_device = info->next_device; else mgslpc_device_list = info->next_device; -#ifdef CONFIG_SYNCLINK_SYNCPPP - if (info->dosyncppp) - mgslpc_sppp_delete(info); +#ifdef CONFIG_HDLC + hdlcdev_exit(info); #endif release_resources(info); kfree(info); @@ -4021,9 +4006,12 @@ return_frame = 1; } framesize = 0; -#ifdef CONFIG_SYNCLINK_SYNCPPP - info->netstats.rx_errors++; - info->netstats.rx_frame_errors++; +#ifdef CONFIG_HDLC + { + struct net_device_stats *stats = hdlc_stats(info->netdev); + stats->rx_errors++; + stats->rx_frame_errors++; + } #endif } else return_frame = 1; @@ -4052,11 +4040,9 @@ ++framesize; } -#ifdef CONFIG_SYNCLINK_SYNCPPP - if (info->netcount) { - /* pass frame to syncppp device */ - mgslpc_sppp_rx_done(info, buf->data, framesize); - } +#ifdef CONFIG_HDLC + if (info->netcount) + hdlcdev_rx(info, buf->data, framesize); else #endif { @@ -4215,88 +4201,134 @@ spin_unlock_irqrestore(&info->lock,flags); -#ifdef CONFIG_SYNCLINK_SYNCPPP +#ifdef CONFIG_HDLC if (info->netcount) - mgslpc_sppp_tx_done(info); + hdlcdev_tx_done(info); else #endif bh_transmit(info); } -#ifdef CONFIG_SYNCLINK_SYNCPPP -/* syncppp net device routines +#ifdef CONFIG_HDLC + +/** + * called by generic HDLC layer when protocol selected (PPP, frame relay, etc.) + * set encoding and frame check sequence (FCS) options + * + * dev pointer to network device structure + * encoding serial encoding setting + * parity FCS setting + * + * returns 0 if success, otherwise error code */ - -static void mgslpc_setup(struct net_device *dev) +static int hdlcdev_attach(struct net_device *dev, unsigned short encoding, + unsigned short parity) { - dev->open = mgslpc_sppp_open; - dev->stop = mgslpc_sppp_close; - dev->hard_start_xmit = mgslpc_sppp_tx; - dev->do_ioctl = mgslpc_sppp_ioctl; - dev->get_stats = mgslpc_net_stats; - dev->tx_timeout = mgslpc_sppp_tx_timeout; - dev->watchdog_timeo = 10*HZ; -} + MGSLPC_INFO *info = dev_to_port(dev); + unsigned char new_encoding; + unsigned short new_crctype; -void mgslpc_sppp_init(MGSLPC_INFO *info) -{ - struct net_device *d; + /* return error if TTY interface open */ + if (info->count) + return -EBUSY; - sprintf(info->netname,"mgslp%d",info->line); - - d = alloc_netdev(0, info->netname, mgslpc_setup); - if (!d) { - printk(KERN_WARNING "%s: alloc_netdev failed.\n", - info->netname); - return; + switch (encoding) + { + case ENCODING_NRZ: new_encoding = HDLC_ENCODING_NRZ; break; + case ENCODING_NRZI: new_encoding = HDLC_ENCODING_NRZI_SPACE; break; + case ENCODING_FM_MARK: new_encoding = HDLC_ENCODING_BIPHASE_MARK; break; + case ENCODING_FM_SPACE: new_encoding = HDLC_ENCODING_BIPHASE_SPACE; break; + case ENCODING_MANCHESTER: new_encoding = HDLC_ENCODING_BIPHASE_LEVEL; break; + default: return -EINVAL; } - info->if_ptr = &info->pppdev; - info->netdev = info->pppdev.dev = d; - - d->base_addr = info->io_base; - d->irq = info->irq_level; - d->priv = info; - - sppp_attach(&info->pppdev); - mgslpc_setup(d); - - if (register_netdev(d)) { - printk(KERN_WARNING "%s: register_netdev failed.\n", d->name); - sppp_detach(info->netdev); - info->netdev = NULL; - info->pppdev.dev = NULL; - free_netdev(d); - return; + switch (parity) + { + case PARITY_NONE: new_crctype = HDLC_CRC_NONE; break; + case PARITY_CRC16_PR1_CCITT: new_crctype = HDLC_CRC_16_CCITT; break; + case PARITY_CRC32_PR1_CCITT: new_crctype = HDLC_CRC_32_CCITT; break; + default: return -EINVAL; } - if (debug_level >= DEBUG_LEVEL_INFO) - printk("mgslpc_sppp_init()\n"); + info->params.encoding = new_encoding; + info->params.crc_type = new_crctype;; + + /* if network interface up, reprogram hardware */ + if (info->netcount) + mgslpc_program_hw(info); + + return 0; } -void mgslpc_sppp_delete(MGSLPC_INFO *info) +/** + * called by generic HDLC layer to send frame + * + * skb socket buffer containing HDLC frame + * dev pointer to network device structure + * + * returns 0 if success, otherwise error code + */ +static int hdlcdev_xmit(struct sk_buff *skb, struct net_device *dev) { + MGSLPC_INFO *info = dev_to_port(dev); + struct net_device_stats *stats = hdlc_stats(dev); + unsigned long flags; + if (debug_level >= DEBUG_LEVEL_INFO) - printk("mgslpc_sppp_delete(%s)\n",info->netname); - unregister_netdev(info->netdev); - sppp_detach(info->netdev); - free_netdev(info->netdev); - info->netdev = NULL; - info->pppdev.dev = NULL; + printk(KERN_INFO "%s:hdlc_xmit(%s)\n",__FILE__,dev->name); + + /* stop sending until this frame completes */ + netif_stop_queue(dev); + + /* copy data to device buffers */ + memcpy(info->tx_buf, skb->data, skb->len); + info->tx_get = 0; + info->tx_put = info->tx_count = skb->len; + + /* update network statistics */ + stats->tx_packets++; + stats->tx_bytes += skb->len; + + /* done with socket buffer, so free it */ + dev_kfree_skb(skb); + + /* save start time for transmit timeout detection */ + dev->trans_start = jiffies; + + /* start hardware transmitter if necessary */ + spin_lock_irqsave(&info->lock,flags); + if (!info->tx_active) + tx_start(info); + spin_unlock_irqrestore(&info->lock,flags); + + return 0; } -int mgslpc_sppp_open(struct net_device *d) +/** + * called by network layer when interface enabled + * claim resources and initialize hardware + * + * dev pointer to network device structure + * + * returns 0 if success, otherwise error code + */ +static int hdlcdev_open(struct net_device *dev) { - MGSLPC_INFO *info = d->priv; - int err; + MGSLPC_INFO *info = dev_to_port(dev); + int rc; unsigned long flags; if (debug_level >= DEBUG_LEVEL_INFO) - printk("mgslpc_sppp_open(%s)\n",info->netname); + printk("%s:hdlcdev_open(%s)\n",__FILE__,dev->name); + + /* generic HDLC layer open processing */ + if ((rc = hdlc_open(dev))) + return rc; + /* arbitrate between network and tty opens */ spin_lock_irqsave(&info->netlock, flags); if (info->count != 0 || info->netcount != 0) { - printk(KERN_WARNING "%s: sppp_open returning busy\n", info->netname); + printk(KERN_WARNING "%s: hdlc_open returning busy\n", dev->name); spin_unlock_irqrestore(&info->netlock, flags); return -EBUSY; } @@ -4304,142 +4336,297 @@ spin_unlock_irqrestore(&info->netlock, flags); /* claim resources and init adapter */ - if ((err = startup(info)) != 0) - goto open_fail; - - /* allow syncppp module to do open processing */ - if ((err = sppp_open(d)) != 0) { - shutdown(info); - goto open_fail; + if ((rc = startup(info)) != 0) { + spin_lock_irqsave(&info->netlock, flags); + info->netcount=0; + spin_unlock_irqrestore(&info->netlock, flags); + return rc; } + /* assert DTR and RTS, apply hardware settings */ info->serial_signals |= SerialSignal_RTS + SerialSignal_DTR; mgslpc_program_hw(info); - d->trans_start = jiffies; - netif_start_queue(d); - return 0; + /* enable network layer transmit */ + dev->trans_start = jiffies; + netif_start_queue(dev); -open_fail: - spin_lock_irqsave(&info->netlock, flags); - info->netcount=0; - spin_unlock_irqrestore(&info->netlock, flags); - return err; + /* inform generic HDLC layer of current DCD status */ + spin_lock_irqsave(&info->lock, flags); + get_signals(info); + spin_unlock_irqrestore(&info->lock, flags); + hdlc_set_carrier(info->serial_signals & SerialSignal_DCD, dev); + + return 0; } -void mgslpc_sppp_tx_timeout(struct net_device *dev) +/** + * called by network layer when interface is disabled + * shutdown hardware and release resources + * + * dev pointer to network device structure + * + * returns 0 if success, otherwise error code + */ +static int hdlcdev_close(struct net_device *dev) { - MGSLPC_INFO *info = dev->priv; + MGSLPC_INFO *info = dev_to_port(dev); unsigned long flags; if (debug_level >= DEBUG_LEVEL_INFO) - printk("mgslpc_sppp_tx_timeout(%s)\n",info->netname); + printk("%s:hdlcdev_close(%s)\n",__FILE__,dev->name); - info->netstats.tx_errors++; - info->netstats.tx_aborted_errors++; + netif_stop_queue(dev); - spin_lock_irqsave(&info->lock,flags); - tx_stop(info); - spin_unlock_irqrestore(&info->lock,flags); + /* shutdown adapter and release resources */ + shutdown(info); - netif_wake_queue(dev); + hdlc_close(dev); + + spin_lock_irqsave(&info->netlock, flags); + info->netcount=0; + spin_unlock_irqrestore(&info->netlock, flags); + + return 0; } -int mgslpc_sppp_tx(struct sk_buff *skb, struct net_device *dev) +/** + * called by network layer to process IOCTL call to network device + * + * dev pointer to network device structure + * ifr pointer to network interface request structure + * cmd IOCTL command code + * + * returns 0 if success, otherwise error code + */ +static int hdlcdev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) { - MGSLPC_INFO *info = dev->priv; - unsigned long flags; + const size_t size = sizeof(sync_serial_settings); + sync_serial_settings new_line; + sync_serial_settings __user *line = ifr->ifr_settings.ifs_ifsu.sync; + MGSLPC_INFO *info = dev_to_port(dev); + unsigned int flags; if (debug_level >= DEBUG_LEVEL_INFO) - printk("mgslpc_sppp_tx(%s)\n",info->netname); + printk("%s:hdlcdev_ioctl(%s)\n",__FILE__,dev->name); - netif_stop_queue(dev); + /* return error if TTY interface open */ + if (info->count) + return -EBUSY; - info->tx_count = skb->len; + if (cmd != SIOCWANDEV) + return hdlc_ioctl(dev, ifr, cmd); - memcpy(info->tx_buf, skb->data, skb->len); - info->tx_get = 0; - info->tx_put = info->tx_count = skb->len; + switch(ifr->ifr_settings.type) { + case IF_GET_IFACE: /* return current sync_serial_settings */ - info->netstats.tx_packets++; - info->netstats.tx_bytes += skb->len; - dev_kfree_skb(skb); + ifr->ifr_settings.type = IF_IFACE_SYNC_SERIAL; + if (ifr->ifr_settings.size < size) { + ifr->ifr_settings.size = size; /* data size wanted */ + return -ENOBUFS; + } - dev->trans_start = jiffies; + flags = info->params.flags & (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_RXC_DPLL | + HDLC_FLAG_RXC_BRG | HDLC_FLAG_RXC_TXCPIN | + HDLC_FLAG_TXC_TXCPIN | HDLC_FLAG_TXC_DPLL | + HDLC_FLAG_TXC_BRG | HDLC_FLAG_TXC_RXCPIN); + + switch (flags){ + case (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_TXCPIN): new_line.clock_type = CLOCK_EXT; break; + case (HDLC_FLAG_RXC_BRG | HDLC_FLAG_TXC_BRG): new_line.clock_type = CLOCK_INT; break; + case (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_BRG): new_line.clock_type = CLOCK_TXINT; break; + case (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_RXCPIN): new_line.clock_type = CLOCK_TXFROMRX; break; + default: new_line.clock_type = CLOCK_DEFAULT; + } - spin_lock_irqsave(&info->lock,flags); - if (!info->tx_active) - tx_start(info); - spin_unlock_irqrestore(&info->lock,flags); + new_line.clock_rate = info->params.clock_speed; + new_line.loopback = info->params.loopback ? 1:0; - return 0; + if (copy_to_user(line, &new_line, size)) + return -EFAULT; + return 0; + + case IF_IFACE_SYNC_SERIAL: /* set sync_serial_settings */ + + if(!capable(CAP_NET_ADMIN)) + return -EPERM; + if (copy_from_user(&new_line, line, size)) + return -EFAULT; + + switch (new_line.clock_type) + { + case CLOCK_EXT: flags = HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_TXCPIN; break; + case CLOCK_TXFROMRX: flags = HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_RXCPIN; break; + case CLOCK_INT: flags = HDLC_FLAG_RXC_BRG | HDLC_FLAG_TXC_BRG; break; + case CLOCK_TXINT: flags = HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_BRG; break; + case CLOCK_DEFAULT: flags = info->params.flags & + (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_RXC_DPLL | + HDLC_FLAG_RXC_BRG | HDLC_FLAG_RXC_TXCPIN | + HDLC_FLAG_TXC_TXCPIN | HDLC_FLAG_TXC_DPLL | + HDLC_FLAG_TXC_BRG | HDLC_FLAG_TXC_RXCPIN); break; + default: return -EINVAL; + } + + if (new_line.loopback != 0 && new_line.loopback != 1) + return -EINVAL; + + info->params.flags &= ~(HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_RXC_DPLL | + HDLC_FLAG_RXC_BRG | HDLC_FLAG_RXC_TXCPIN | + HDLC_FLAG_TXC_TXCPIN | HDLC_FLAG_TXC_DPLL | + HDLC_FLAG_TXC_BRG | HDLC_FLAG_TXC_RXCPIN); + info->params.flags |= flags; + + info->params.loopback = new_line.loopback; + + if (flags & (HDLC_FLAG_RXC_BRG | HDLC_FLAG_TXC_BRG)) + info->params.clock_speed = new_line.clock_rate; + else + info->params.clock_speed = 0; + + /* if network interface up, reprogram hardware */ + if (info->netcount) + mgslpc_program_hw(info); + return 0; + + default: + return hdlc_ioctl(dev, ifr, cmd); + } } -int mgslpc_sppp_close(struct net_device *d) +/** + * called by network layer when transmit timeout is detected + * + * dev pointer to network device structure + */ +static void hdlcdev_tx_timeout(struct net_device *dev) { - MGSLPC_INFO *info = d->priv; + MGSLPC_INFO *info = dev_to_port(dev); + struct net_device_stats *stats = hdlc_stats(dev); unsigned long flags; if (debug_level >= DEBUG_LEVEL_INFO) - printk("mgslpc_sppp_close(%s)\n",info->netname); + printk("hdlcdev_tx_timeout(%s)\n",dev->name); - /* shutdown adapter and release resources */ - shutdown(info); + stats->tx_errors++; + stats->tx_aborted_errors++; - /* allow syncppp to do close processing */ - sppp_close(d); - netif_stop_queue(d); + spin_lock_irqsave(&info->lock,flags); + tx_stop(info); + spin_unlock_irqrestore(&info->lock,flags); - spin_lock_irqsave(&info->netlock, flags); - info->netcount=0; - spin_unlock_irqrestore(&info->netlock, flags); - return 0; + netif_wake_queue(dev); +} + +/** + * called by device driver when transmit completes + * reenable network layer transmit if stopped + * + * info pointer to device instance information + */ +static void hdlcdev_tx_done(MGSLPC_INFO *info) +{ + if (netif_queue_stopped(info->netdev)) + netif_wake_queue(info->netdev); } -void mgslpc_sppp_rx_done(MGSLPC_INFO *info, char *buf, int size) +/** + * called by device driver when frame received + * pass frame to network layer + * + * info pointer to device instance information + * buf pointer to buffer contianing frame data + * size count of data bytes in buf + */ +static void hdlcdev_rx(MGSLPC_INFO *info, char *buf, int size) { struct sk_buff *skb = dev_alloc_skb(size); + struct net_device *dev = info->netdev; + struct net_device_stats *stats = hdlc_stats(dev); + if (debug_level >= DEBUG_LEVEL_INFO) - printk("mgslpc_sppp_rx_done(%s)\n",info->netname); + printk("hdlcdev_rx(%s)\n",dev->name); + if (skb == NULL) { - printk(KERN_NOTICE "%s: can't alloc skb, dropping packet\n", - info->netname); - info->netstats.rx_dropped++; + printk(KERN_NOTICE "%s: can't alloc skb, dropping packet\n", dev->name); + stats->rx_dropped++; return; } memcpy(skb_put(skb, size),buf,size); - skb->protocol = htons(ETH_P_WAN_PPP); - skb->dev = info->netdev; - skb->mac.raw = skb->data; - info->netstats.rx_packets++; - info->netstats.rx_bytes += size; + skb->dev = info->netdev; + skb->mac.raw = skb->data; + skb->protocol = hdlc_type_trans(skb, skb->dev); + + stats->rx_packets++; + stats->rx_bytes += size; + netif_rx(skb); - info->netdev->trans_start = jiffies; -} -void mgslpc_sppp_tx_done(MGSLPC_INFO *info) -{ - if (netif_queue_stopped(info->netdev)) - netif_wake_queue(info->netdev); + info->netdev->last_rx = jiffies; } -struct net_device_stats *mgslpc_net_stats(struct net_device *dev) +/** + * called by device driver when adding device instance + * do generic HDLC initialization + * + * info pointer to device instance information + * + * returns 0 if success, otherwise error code + */ +static int hdlcdev_init(MGSLPC_INFO *info) { - MGSLPC_INFO *info = dev->priv; - if (debug_level >= DEBUG_LEVEL_INFO) - printk("mgslpc_net_stats(%s)\n",info->netname); - return &info->netstats; + int rc; + struct net_device *dev; + hdlc_device *hdlc; + + /* allocate and initialize network and HDLC layer objects */ + + if (!(dev = alloc_hdlcdev(info))) { + printk(KERN_ERR "%s:hdlc device allocation failure\n",__FILE__); + return -ENOMEM; + } + + /* for network layer reporting purposes only */ + dev->base_addr = info->io_base; + dev->irq = info->irq_level; + + /* network layer callbacks and settings */ + dev->do_ioctl = hdlcdev_ioctl; + dev->open = hdlcdev_open; + dev->stop = hdlcdev_close; + dev->tx_timeout = hdlcdev_tx_timeout; + dev->watchdog_timeo = 10*HZ; + dev->tx_queue_len = 50; + + /* generic HDLC layer callbacks and settings */ + hdlc = dev_to_hdlc(dev); + hdlc->attach = hdlcdev_attach; + hdlc->xmit = hdlcdev_xmit; + + /* register objects with HDLC layer */ + if ((rc = register_hdlc_device(dev))) { + printk(KERN_WARNING "%s:unable to register hdlc device\n",__FILE__); + free_netdev(dev); + return rc; + } + + info->netdev = dev; + return 0; } -int mgslpc_sppp_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) +/** + * called by device driver when removing device instance + * do generic HDLC cleanup + * + * info pointer to device instance information + */ +static void hdlcdev_exit(MGSLPC_INFO *info) { - MGSLPC_INFO *info = dev->priv; - if (debug_level >= DEBUG_LEVEL_INFO) - printk("%s(%d):mgslpc_ioctl %s cmd=%08X\n", __FILE__,__LINE__, - info->netname, cmd ); - return sppp_do_ioctl(dev, ifr, cmd); + unregister_hdlc_device(info->netdev); + free_netdev(info->netdev); + info->netdev = NULL; } -#endif /* ifdef CONFIG_SYNCLINK_SYNCPPP */ +#endif /* CONFIG_HDLC */ + diff -Nru a/drivers/char/pty.c b/drivers/char/pty.c --- a/drivers/char/pty.c 2004-08-25 22:01:55 -07:00 +++ b/drivers/char/pty.c 2004-08-25 22:01:55 -07:00 @@ -32,12 +32,6 @@ #include #include -#if defined(CONFIG_LEGACY_PTYS) || defined(CONFIG_UNIX98_PTYS) - -#ifdef CONFIG_LEGACY_PTYS -static struct tty_driver *pty_driver, *pty_slave_driver; -#endif - /* These are global because they are accessed in tty_io.c */ #ifdef CONFIG_UNIX98_PTYS struct tty_driver *ptm_driver; @@ -205,19 +199,6 @@ return ((count < N_TTY_BUF_SIZE/2) ? 0 : count); } -/* - * Return the device number of a Unix98 PTY (only!). This lets us open a - * master pty with the multi-headed ptmx device, then find out which - * one we got after it is open, with an ioctl. - */ -#ifdef CONFIG_UNIX98_PTYS -static int pty_get_device_number(struct tty_struct *tty, unsigned __user *value) -{ - unsigned int result = tty->index; - return put_user(result, value); -} -#endif - /* Set the lock flag on a pty */ static int pty_set_lock(struct tty_struct *tty, int __user * arg) { @@ -231,41 +212,6 @@ return 0; } -#ifdef CONFIG_LEGACY_PTYS -static int pty_bsd_ioctl(struct tty_struct *tty, struct file *file, - unsigned int cmd, unsigned long arg) -{ - if (!tty) { - printk("pty_ioctl called with NULL tty!\n"); - return -EIO; - } - switch(cmd) { - case TIOCSPTLCK: /* Set PT Lock (disallow slave open) */ - return pty_set_lock(tty, (int __user *) arg); - } - return -ENOIOCTLCMD; -} -#endif - -#ifdef CONFIG_UNIX98_PTYS -static int pty_unix98_ioctl(struct tty_struct *tty, struct file *file, - unsigned int cmd, unsigned long arg) -{ - if (!tty) { - printk("pty_unix98_ioctl called with NULL tty!\n"); - return -EIO; - } - switch(cmd) { - case TIOCSPTLCK: /* Set PT Lock (disallow slave open) */ - return pty_set_lock(tty, (int __user *)arg); - case TIOCGPTN: /* Get PT Number */ - return pty_get_device_number(tty, (unsigned int __user *)arg); - } - - return -ENOIOCTLCMD; -} -#endif - static void pty_flush_buffer(struct tty_struct *tty) { struct tty_struct *to = tty->link; @@ -322,42 +268,22 @@ .set_termios = pty_set_termios, }; -/* sysctl support for setting limits on the number of Unix98 ptys allocated. - Otherwise one can eat up all kernel memory by opening /dev/ptmx repeatedly. */ -#ifdef CONFIG_UNIX98_PTYS -int pty_limit = NR_UNIX98_PTY_DEFAULT; -static int pty_limit_min = 0; -static int pty_limit_max = NR_UNIX98_PTY_MAX; +/* Traditional BSD devices */ +#ifdef CONFIG_LEGACY_PTYS +static struct tty_driver *pty_driver, *pty_slave_driver; -ctl_table pty_table[] = { - { - .ctl_name = PTY_MAX, - .procname = "max", - .maxlen = sizeof(int), - .mode = 0644, - .data = &pty_limit, - .proc_handler = &proc_dointvec_minmax, - .strategy = &sysctl_intvec, - .extra1 = &pty_limit_min, - .extra2 = &pty_limit_max, - }, { - .ctl_name = PTY_NR, - .procname = "nr", - .maxlen = sizeof(int), - .mode = 0444, - .proc_handler = &proc_dointvec, - }, { - .ctl_name = 0 +static int pty_bsd_ioctl(struct tty_struct *tty, struct file *file, + unsigned int cmd, unsigned long arg) +{ + switch (cmd) { + case TIOCSPTLCK: /* Set PT Lock (disallow slave open) */ + return pty_set_lock(tty, (int __user *) arg); } -}; -#endif - -/* Initialization */ + return -ENOIOCTLCMD; +} -static int __init pty_init(void) +static void __init legacy_pty_init(void) { -#ifdef CONFIG_LEGACY_PTYS - /* Traditional BSD devices */ pty_driver = alloc_tty_driver(NR_PTYS); if (!pty_driver) @@ -404,11 +330,58 @@ panic("Couldn't register pty driver"); if (tty_register_driver(pty_slave_driver)) panic("Couldn't register pty slave driver"); +} +#else +static inline void legacy_pty_init(void) { } +#endif -#endif /* CONFIG_LEGACY_PTYS */ - +/* Unix98 devices */ #ifdef CONFIG_UNIX98_PTYS - /* Unix98 devices */ +/* + * sysctl support for setting limits on the number of Unix98 ptys allocated. + * Otherwise one can eat up all kernel memory by opening /dev/ptmx repeatedly. + */ +int pty_limit = NR_UNIX98_PTY_DEFAULT; +static int pty_limit_min = 0; +static int pty_limit_max = NR_UNIX98_PTY_MAX; + +ctl_table pty_table[] = { + { + .ctl_name = PTY_MAX, + .procname = "max", + .maxlen = sizeof(int), + .mode = 0644, + .data = &pty_limit, + .proc_handler = &proc_dointvec_minmax, + .strategy = &sysctl_intvec, + .extra1 = &pty_limit_min, + .extra2 = &pty_limit_max, + }, { + .ctl_name = PTY_NR, + .procname = "nr", + .maxlen = sizeof(int), + .mode = 0444, + .proc_handler = &proc_dointvec, + }, { + .ctl_name = 0 + } +}; + +static int pty_unix98_ioctl(struct tty_struct *tty, struct file *file, + unsigned int cmd, unsigned long arg) +{ + switch (cmd) { + case TIOCSPTLCK: /* Set PT Lock (disallow slave open) */ + return pty_set_lock(tty, (int __user *)arg); + case TIOCGPTN: /* Get PT Number */ + return put_user(tty->index, (unsigned int __user *)arg); + } + + return -ENOIOCTLCMD; +} + +static void __init unix98_pty_init(void) +{ devfs_mk_dir("pts"); ptm_driver = alloc_tty_driver(NR_UNIX98_PTY_MAX); if (!ptm_driver) @@ -455,10 +428,15 @@ panic("Couldn't register Unix98 pts driver"); pty_table[1].data = &ptm_driver->refcount; -#endif /* CONFIG_UNIX98_PTYS */ +} +#else +static inline void unix98_pty_init(void) { } +#endif +static int __init pty_init(void) +{ + legacy_pty_init(); + unix98_pty_init(); return 0; } module_init(pty_init); - -#endif /* CONFIG_LEGACY_PTYS || CONFIG_UNIX98_PTYS */ diff -Nru a/drivers/char/random.c b/drivers/char/random.c --- a/drivers/char/random.c 2004-08-25 22:01:54 -07:00 +++ b/drivers/char/random.c 2004-08-25 22:01:54 -07:00 @@ -401,6 +401,7 @@ */ static struct entropy_store *random_state; /* The default global store */ static struct entropy_store *sec_random_state; /* secondary store */ +static struct entropy_store *urandom_state; /* For urandom */ static DECLARE_WAIT_QUEUE_HEAD(random_read_wait); static DECLARE_WAIT_QUEUE_HEAD(random_write_wait); @@ -493,6 +494,7 @@ /* mostly-read data: */ struct poolinfo poolinfo; __u32 *pool; + const char *name; /* read-write data: */ spinlock_t lock ____cacheline_aligned_in_smp; @@ -507,7 +509,8 @@ * * Returns an negative error if there is a problem. */ -static int create_entropy_store(int size, struct entropy_store **ret_bucket) +static int create_entropy_store(int size, const char *name, + struct entropy_store **ret_bucket) { struct entropy_store *r; struct poolinfo *p; @@ -538,6 +541,7 @@ } memset(r->pool, 0, POOLBYTES); r->lock = SPIN_LOCK_UNLOCKED; + r->name = name; *ret_bucket = r; return 0; } @@ -643,12 +647,8 @@ } else { r->entropy_count += nbits; if (nbits) - DEBUG_ENT("%04d %04d : added %d bits to %s\n", - random_state->entropy_count, - sec_random_state->entropy_count, - nbits, - r == sec_random_state ? "secondary" : - r == random_state ? "primary" : "unknown"); + DEBUG_ENT("Added %d entropy credits to %s, now %d\n", + nbits, r->name, r->entropy_count); } spin_unlock_irqrestore(&r->lock, flags); @@ -1328,8 +1328,7 @@ "(%d of %d requested)\n", random_state->entropy_count, sec_random_state->entropy_count, - r == sec_random_state ? "secondary" : "unknown", - bytes * 8, nbytes * 8, r->entropy_count); + r->name, bytes * 8, nbytes * 8, r->entropy_count); bytes=extract_entropy(random_state, tmp, bytes, EXTRACT_ENTROPY_LIMIT); @@ -1373,9 +1372,7 @@ DEBUG_ENT("%04d %04d : trying to extract %d bits from %s\n", random_state->entropy_count, sec_random_state->entropy_count, - nbytes * 8, - r == sec_random_state ? "secondary" : - r == random_state ? "primary" : "unknown"); + nbytes * 8, r->name); if (flags & EXTRACT_ENTROPY_LIMIT && nbytes >= r->entropy_count / 8) nbytes = r->entropy_count / 8; @@ -1388,12 +1385,8 @@ if (r->entropy_count < random_write_wakeup_thresh) wake_up_interruptible(&random_write_wait); - DEBUG_ENT("%04d %04d : debiting %d bits from %s%s\n", - random_state->entropy_count, - sec_random_state->entropy_count, - nbytes * 8, - r == sec_random_state ? "secondary" : - r == random_state ? "primary" : "unknown", + DEBUG_ENT("Debiting %d entropy credits from %s%s\n", + nbytes * 8, r->name, flags & EXTRACT_ENTROPY_LIMIT ? "" : " (unlimited)"); spin_unlock_irqrestore(&r->lock, cpuflags); @@ -1482,14 +1475,21 @@ */ void get_random_bytes(void *buf, int nbytes) { - if (sec_random_state) - extract_entropy(sec_random_state, (char *) buf, nbytes, - EXTRACT_ENTROPY_SECONDARY); - else if (random_state) - extract_entropy(random_state, (char *) buf, nbytes, 0); - else + struct entropy_store *r = urandom_state; + int flags = EXTRACT_ENTROPY_SECONDARY; + + if (!r) + r = sec_random_state; + if (!r) { + r = random_state; + flags = 0; + } + if (!r) { printk(KERN_NOTICE "get_random_bytes called before " "random driver initialization\n"); + return; + } + extract_entropy(r, (char *) buf, nbytes, flags); } EXPORT_SYMBOL(get_random_bytes); @@ -1533,14 +1533,19 @@ { int i; - if (create_entropy_store(DEFAULT_POOL_SIZE, &random_state)) + if (create_entropy_store(DEFAULT_POOL_SIZE, "primary", &random_state)) goto err; if (batch_entropy_init(BATCH_ENTROPY_SIZE, random_state)) goto err; - if (create_entropy_store(SECONDARY_POOL_SIZE, &sec_random_state)) + if (create_entropy_store(SECONDARY_POOL_SIZE, "secondary", + &sec_random_state)) + goto err; + if (create_entropy_store(SECONDARY_POOL_SIZE, "urandom", + &urandom_state)) goto err; clear_entropy_store(random_state); clear_entropy_store(sec_random_state); + clear_entropy_store(urandom_state); init_std_data(random_state); init_std_data(sec_random_state); #ifdef CONFIG_SYSCTL @@ -1675,9 +1680,15 @@ urandom_read(struct file * file, char __user * buf, size_t nbytes, loff_t *ppos) { - return extract_entropy(sec_random_state, buf, nbytes, - EXTRACT_ENTROPY_USER | - EXTRACT_ENTROPY_SECONDARY); + int flags = EXTRACT_ENTROPY_USER; + unsigned long cpuflags; + + spin_lock_irqsave(&random_state->lock, cpuflags); + if (random_state->entropy_count > random_state->poolinfo.POOLBITS) + flags |= EXTRACT_ENTROPY_SECONDARY; + spin_unlock_irqrestore(&random_state->lock, cpuflags); + + return extract_entropy(urandom_state, buf, nbytes, flags); } static unsigned int @@ -1731,10 +1742,9 @@ random_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigned long arg) { - int *tmp, size, ent_count; + int size, ent_count; int __user *p = (int __user *)arg; int retval; - unsigned long flags; switch (cmd) { case RNDGETENTCNT: @@ -1755,40 +1765,6 @@ if (random_state->entropy_count >= random_read_wakeup_thresh) wake_up_interruptible(&random_read_wait); return 0; - case RNDGETPOOL: - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - if (get_user(size, p) || - put_user(random_state->poolinfo.poolwords, p++)) - return -EFAULT; - if (size < 0) - return -EFAULT; - if (size > random_state->poolinfo.poolwords) - size = random_state->poolinfo.poolwords; - - /* prepare to atomically snapshot pool */ - - tmp = kmalloc(size * sizeof(__u32), GFP_KERNEL); - - if (!tmp) - return -ENOMEM; - - spin_lock_irqsave(&random_state->lock, flags); - ent_count = random_state->entropy_count; - memcpy(tmp, random_state->pool, size * sizeof(__u32)); - spin_unlock_irqrestore(&random_state->lock, flags); - - if (!copy_to_user(p, tmp, size * sizeof(__u32))) { - kfree(tmp); - return -EFAULT; - } - - kfree(tmp); - - if(put_user(ent_count, p++)) - return -EFAULT; - - return 0; case RNDADDENTROPY: if (!capable(CAP_SYS_ADMIN)) return -EPERM; @@ -1885,7 +1861,8 @@ struct entropy_store *new_store, *old_store; int ret; - if ((ret = create_entropy_store(poolsize, &new_store))) + if ((ret = create_entropy_store(poolsize, random_state->name, + &new_store))) return ret; add_entropy_words(new_store, random_state->pool, @@ -2247,30 +2224,35 @@ static spinlock_t ip_lock = SPIN_LOCK_UNLOCKED; static unsigned int ip_cnt; -static struct keydata *__check_and_rekey(time_t time) +static void rekey_seq_generator(void *private_) { struct keydata *keyptr; + struct timeval tv; + + do_gettimeofday(&tv); + spin_lock_bh(&ip_lock); keyptr = &ip_keydata[ip_cnt&1]; - if (!keyptr->rekey_time || (time - keyptr->rekey_time) > REKEY_INTERVAL) { - keyptr = &ip_keydata[1^(ip_cnt&1)]; - keyptr->rekey_time = time; - get_random_bytes(keyptr->secret, sizeof(keyptr->secret)); - keyptr->count = (ip_cnt&COUNT_MASK)<rekey_time = tv.tv_sec; + get_random_bytes(keyptr->secret, sizeof(keyptr->secret)); + keyptr->count = (ip_cnt&COUNT_MASK)<rekey_time || (time - keyptr->rekey_time) > REKEY_INTERVAL) { - keyptr = __check_and_rekey(time); + schedule_work(&rekey_work); } return keyptr; diff -Nru a/drivers/char/rocket.c b/drivers/char/rocket.c --- a/drivers/char/rocket.c 2004-08-25 22:01:55 -07:00 +++ b/drivers/char/rocket.c 2004-08-25 22:01:55 -07:00 @@ -1283,11 +1283,7 @@ if (copy_from_user(&new_serial, new_info, sizeof (new_serial))) return -EFAULT; -#ifdef CAP_SYS_ADMIN if (!capable(CAP_SYS_ADMIN)) -#else - if (!suser()) -#endif { if ((new_serial.flags & ~ROCKET_USR_MASK) != (info->flags & ~ROCKET_USR_MASK)) return -EPERM; diff -Nru a/drivers/char/serial167.c b/drivers/char/serial167.c --- a/drivers/char/serial167.c 2004-08-25 22:01:55 -07:00 +++ b/drivers/char/serial167.c 2004-08-25 22:01:55 -07:00 @@ -2379,7 +2379,7 @@ | CyPARITY| CyFRAME| CyOVERRUN; /* info->timeout */ - printk("ttyS%1d ", info->line); + printk("ttyS%d ", info->line); port_num++;info++; if(!(port_num & 7)){ printk("\n "); diff -Nru a/drivers/char/sonypi.c b/drivers/char/sonypi.c --- a/drivers/char/sonypi.c 2004-08-25 22:01:56 -07:00 +++ b/drivers/char/sonypi.c 2004-08-25 22:01:56 -07:00 @@ -67,7 +67,7 @@ static inline void sonypi_initq(void) { sonypi_device.queue.head = sonypi_device.queue.tail = 0; sonypi_device.queue.len = 0; - sonypi_device.queue.s_lock = (spinlock_t)SPIN_LOCK_UNLOCKED; + sonypi_device.queue.s_lock = SPIN_LOCK_UNLOCKED; init_waitqueue_head(&sonypi_device.queue.proc_list); } diff -Nru a/drivers/char/synclink.c b/drivers/char/synclink.c --- a/drivers/char/synclink.c 2004-08-25 22:01:55 -07:00 +++ b/drivers/char/synclink.c 2004-08-25 22:01:55 -07:00 @@ -1,7 +1,7 @@ /* * linux/drivers/char/synclink.c * - * $Id: synclink.c,v 4.24 2004/06/03 14:50:09 paulkf Exp $ + * $Id: synclink.c,v 4.28 2004/08/11 19:30:01 paulkf Exp $ * * Device driver for Microgate SyncLink ISA and PCI * high speed multiprotocol serial adapters. @@ -100,13 +100,10 @@ #include #include #include +#include -#ifdef CONFIG_SYNCLINK_SYNCPPP_MODULE -#define CONFIG_SYNCLINK_SYNCPPP 1 -#endif - -#ifdef CONFIG_SYNCLINK_SYNCPPP -#include +#ifdef CONFIG_HDLC_MODULE +#define CONFIG_HDLC 1 #endif #define GET_USER(error,value,addr) error = get_user(value,addr) @@ -187,7 +184,6 @@ */ struct mgsl_struct { - void *if_ptr; /* General purpose pointer (used by SPPP) */ int magic; int flags; int count; /* count of opens */ @@ -318,15 +314,13 @@ struct _input_signal_events input_signal_events; - /* SPPP/Cisco HDLC device parts */ + /* generic HDLC device parts */ int netcount; int dosyncppp; spinlock_t netlock; -#ifdef CONFIG_SYNCLINK_SYNCPPP - struct ppp_device pppdev; - char netname[10]; + +#ifdef CONFIG_HDLC struct net_device *netdev; - struct net_device_stats netstats; #endif }; @@ -734,18 +728,12 @@ int mgsl_ioctl_common(struct mgsl_struct *info, unsigned int cmd, unsigned long arg); -#ifdef CONFIG_SYNCLINK_SYNCPPP -/* SPPP/HDLC stuff */ -static void mgsl_sppp_init(struct mgsl_struct *info); -static void mgsl_sppp_delete(struct mgsl_struct *info); -int mgsl_sppp_open(struct net_device *d); -int mgsl_sppp_close(struct net_device *d); -void mgsl_sppp_tx_timeout(struct net_device *d); -int mgsl_sppp_tx(struct sk_buff *skb, struct net_device *d); -void mgsl_sppp_rx_done(struct mgsl_struct *info, char *buf, int size); -void mgsl_sppp_tx_done(struct mgsl_struct *info); -int mgsl_sppp_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd); -struct net_device_stats *mgsl_net_stats(struct net_device *dev); +#ifdef CONFIG_HDLC +#define dev_to_port(D) (dev_to_hdlc(D)->priv) +static void hdlcdev_tx_done(struct mgsl_struct *info); +static void hdlcdev_rx(struct mgsl_struct *info, char *buf, int size); +static int hdlcdev_init(struct mgsl_struct *info); +static void hdlcdev_exit(struct mgsl_struct *info); #endif /* @@ -911,7 +899,7 @@ MODULE_PARM(txholdbufs,"1-" __MODULE_STRING(MAX_TOTAL_DEVICES) "i"); static char *driver_name = "SyncLink serial driver"; -static char *driver_version = "$Revision: 4.24 $"; +static char *driver_version = "$Revision: 4.28 $"; static int synclink_init_one (struct pci_dev *dev, const struct pci_device_id *ent); @@ -1289,9 +1277,9 @@ info->drop_rts_on_tx_done = 0; } -#ifdef CONFIG_SYNCLINK_SYNCPPP +#ifdef CONFIG_HDLC if (info->netcount) - mgsl_sppp_tx_done(info); + hdlcdev_tx_done(info); else #endif { @@ -1352,12 +1340,12 @@ icount->dcd++; if (status & MISCSTATUS_DCD) { info->input_signal_events.dcd_up++; -#ifdef CONFIG_SYNCLINK_SYNCPPP - if (info->netcount) - sppp_reopen(info->netdev); -#endif } else info->input_signal_events.dcd_down++; +#ifdef CONFIG_HDLC + if (info->netcount) + hdlc_set_carrier(status & MISCSTATUS_DCD, info->netdev); +#endif } if (status & MISCSTATUS_CTS_LATCHED) { @@ -3592,7 +3580,7 @@ cleanup: if (retval) { if (tty->count == 1) - info->tty = NULL;/* tty layer will release tty struct */ + info->tty = NULL; /* tty layer will release tty struct */ if(info->count) info->count--; } @@ -4415,12 +4403,10 @@ info->max_frame_size ); } -#ifdef CONFIG_SYNCLINK_SYNCPPP -#ifdef MODULE - if (info->dosyncppp) -#endif - mgsl_sppp_init(info); +#ifdef CONFIG_HDLC + hdlcdev_init(info); #endif + } /* end of mgsl_add_device() */ /* mgsl_allocate_device() @@ -4575,9 +4561,8 @@ info = mgsl_device_list; while(info) { -#ifdef CONFIG_SYNCLINK_SYNCPPP - if (info->dosyncppp) - mgsl_sppp_delete(info); +#ifdef CONFIG_HDLC + hdlcdev_exit(info); #endif mgsl_release_resources(info); tmp = info; @@ -6750,9 +6735,12 @@ return_frame = 1; } framesize = 0; -#ifdef CONFIG_SYNCLINK_SYNCPPP - info->netstats.rx_errors++; - info->netstats.rx_frame_errors++; +#ifdef CONFIG_HDLC + { + struct net_device_stats *stats = hdlc_stats(info->netdev); + stats->rx_errors++; + stats->rx_frame_errors++; + } #endif } else return_frame = 1; @@ -6823,11 +6811,9 @@ *ptmp); } -#ifdef CONFIG_SYNCLINK_SYNCPPP - if (info->netcount) { - /* pass frame to syncppp device */ - mgsl_sppp_rx_done(info,info->intermediate_rxbuffer,framesize); - } +#ifdef CONFIG_HDLC + if (info->netcount) + hdlcdev_rx(info,info->intermediate_rxbuffer,framesize); else #endif { @@ -7736,9 +7722,9 @@ spin_unlock_irqrestore(&info->irq_spinlock,flags); -#ifdef CONFIG_SYNCLINK_SYNCPPP +#ifdef CONFIG_HDLC if (info->netcount) - mgsl_sppp_tx_done(info); + hdlcdev_tx_done(info); else #endif mgsl_bh_transmit(info); @@ -7819,79 +7805,125 @@ return usc_InReg( info, CCSR ) & BIT6 ? 1 : 0 ; } -#ifdef CONFIG_SYNCLINK_SYNCPPP -/* syncppp net device routines +#ifdef CONFIG_HDLC + +/** + * called by generic HDLC layer when protocol selected (PPP, frame relay, etc.) + * set encoding and frame check sequence (FCS) options + * + * dev pointer to network device structure + * encoding serial encoding setting + * parity FCS setting + * + * returns 0 if success, otherwise error code */ -static void mgsl_setup(struct net_device *dev) +static int hdlcdev_attach(struct net_device *dev, unsigned short encoding, + unsigned short parity) { - dev->open = mgsl_sppp_open; - dev->stop = mgsl_sppp_close; - dev->hard_start_xmit = mgsl_sppp_tx; - dev->do_ioctl = mgsl_sppp_ioctl; - dev->get_stats = mgsl_net_stats; - dev->tx_timeout = mgsl_sppp_tx_timeout; - dev->watchdog_timeo = 10*HZ; -} + struct mgsl_struct *info = dev_to_port(dev); + unsigned char new_encoding; + unsigned short new_crctype; -static void mgsl_sppp_init(struct mgsl_struct *info) -{ - struct net_device *d; + /* return error if TTY interface open */ + if (info->count) + return -EBUSY; - sprintf(info->netname,"mgsl%d",info->line); + switch (encoding) + { + case ENCODING_NRZ: new_encoding = HDLC_ENCODING_NRZ; break; + case ENCODING_NRZI: new_encoding = HDLC_ENCODING_NRZI_SPACE; break; + case ENCODING_FM_MARK: new_encoding = HDLC_ENCODING_BIPHASE_MARK; break; + case ENCODING_FM_SPACE: new_encoding = HDLC_ENCODING_BIPHASE_SPACE; break; + case ENCODING_MANCHESTER: new_encoding = HDLC_ENCODING_BIPHASE_LEVEL; break; + default: return -EINVAL; + } - d = alloc_netdev(0, info->netname, mgsl_setup); - if (!d) { - printk(KERN_WARNING "%s: alloc_netdev failed.\n", - info->netname); - return; + switch (parity) + { + case PARITY_NONE: new_crctype = HDLC_CRC_NONE; break; + case PARITY_CRC16_PR1_CCITT: new_crctype = HDLC_CRC_16_CCITT; break; + case PARITY_CRC32_PR1_CCITT: new_crctype = HDLC_CRC_32_CCITT; break; + default: return -EINVAL; } - info->if_ptr = &info->pppdev; - info->netdev = info->pppdev.dev = d; + info->params.encoding = new_encoding; + info->params.crc_type = new_crctype;; - d->base_addr = info->io_base; - d->irq = info->irq_level; - d->dma = info->dma_level; - d->priv = info; - - sppp_attach(&info->pppdev); - mgsl_setup(d); - - if (register_netdev(d)) { - printk(KERN_WARNING "%s: register_netdev failed.\n", d->name); - sppp_detach(info->netdev); - info->netdev = NULL; - free_netdev(d); - return; - } + /* if network interface up, reprogram hardware */ + if (info->netcount) + mgsl_program_hw(info); - if (debug_level >= DEBUG_LEVEL_INFO) - printk("mgsl_sppp_init()\n"); + return 0; } -void mgsl_sppp_delete(struct mgsl_struct *info) +/** + * called by generic HDLC layer to send frame + * + * skb socket buffer containing HDLC frame + * dev pointer to network device structure + * + * returns 0 if success, otherwise error code + */ +static int hdlcdev_xmit(struct sk_buff *skb, struct net_device *dev) { + struct mgsl_struct *info = dev_to_port(dev); + struct net_device_stats *stats = hdlc_stats(dev); + unsigned long flags; + if (debug_level >= DEBUG_LEVEL_INFO) - printk("mgsl_sppp_delete(%s)\n",info->netname); - unregister_netdev(info->netdev); - sppp_detach(info->netdev); - free_netdev(info->netdev); - info->netdev = NULL; - info->pppdev.dev = NULL; + printk(KERN_INFO "%s:hdlc_xmit(%s)\n",__FILE__,dev->name); + + /* stop sending until this frame completes */ + netif_stop_queue(dev); + + /* copy data to device buffers */ + info->xmit_cnt = skb->len; + mgsl_load_tx_dma_buffer(info, skb->data, skb->len); + + /* update network statistics */ + stats->tx_packets++; + stats->tx_bytes += skb->len; + + /* done with socket buffer, so free it */ + dev_kfree_skb(skb); + + /* save start time for transmit timeout detection */ + dev->trans_start = jiffies; + + /* start hardware transmitter if necessary */ + spin_lock_irqsave(&info->irq_spinlock,flags); + if (!info->tx_active) + usc_start_transmitter(info); + spin_unlock_irqrestore(&info->irq_spinlock,flags); + + return 0; } -int mgsl_sppp_open(struct net_device *d) +/** + * called by network layer when interface enabled + * claim resources and initialize hardware + * + * dev pointer to network device structure + * + * returns 0 if success, otherwise error code + */ +static int hdlcdev_open(struct net_device *dev) { - struct mgsl_struct *info = d->priv; - int err; + struct mgsl_struct *info = dev_to_port(dev); + int rc; unsigned long flags; if (debug_level >= DEBUG_LEVEL_INFO) - printk("mgsl_sppp_open(%s)\n",info->netname); + printk("%s:hdlcdev_open(%s)\n",__FILE__,dev->name); + /* generic HDLC layer open processing */ + if ((rc = hdlc_open(dev))) + return rc; + + /* arbitrate between network and tty opens */ spin_lock_irqsave(&info->netlock, flags); if (info->count != 0 || info->netcount != 0) { - printk(KERN_WARNING "%s: sppp_open returning busy\n", info->netname); + printk(KERN_WARNING "%s: hdlc_open returning busy\n", dev->name); spin_unlock_irqrestore(&info->netlock, flags); return -EBUSY; } @@ -7899,141 +7931,301 @@ spin_unlock_irqrestore(&info->netlock, flags); /* claim resources and init adapter */ - if ((err = startup(info)) != 0) - goto open_fail; - - /* allow syncppp module to do open processing */ - if ((err = sppp_open(d)) != 0) { - shutdown(info); - goto open_fail; + if ((rc = startup(info)) != 0) { + spin_lock_irqsave(&info->netlock, flags); + info->netcount=0; + spin_unlock_irqrestore(&info->netlock, flags); + return rc; } + /* assert DTR and RTS, apply hardware settings */ info->serial_signals |= SerialSignal_RTS + SerialSignal_DTR; mgsl_program_hw(info); - d->trans_start = jiffies; - netif_start_queue(d); - return 0; + /* enable network layer transmit */ + dev->trans_start = jiffies; + netif_start_queue(dev); -open_fail: - spin_lock_irqsave(&info->netlock, flags); - info->netcount=0; - spin_unlock_irqrestore(&info->netlock, flags); - return err; + /* inform generic HDLC layer of current DCD status */ + spin_lock_irqsave(&info->irq_spinlock, flags); + usc_get_serial_signals(info); + spin_unlock_irqrestore(&info->irq_spinlock, flags); + hdlc_set_carrier(info->serial_signals & SerialSignal_DCD, dev); + + return 0; } -void mgsl_sppp_tx_timeout(struct net_device *dev) +/** + * called by network layer when interface is disabled + * shutdown hardware and release resources + * + * dev pointer to network device structure + * + * returns 0 if success, otherwise error code + */ +static int hdlcdev_close(struct net_device *dev) { - struct mgsl_struct *info = dev->priv; + struct mgsl_struct *info = dev_to_port(dev); unsigned long flags; if (debug_level >= DEBUG_LEVEL_INFO) - printk("mgsl_sppp_tx_timeout(%s)\n",info->netname); + printk("%s:hdlcdev_close(%s)\n",__FILE__,dev->name); - info->netstats.tx_errors++; - info->netstats.tx_aborted_errors++; + netif_stop_queue(dev); - spin_lock_irqsave(&info->irq_spinlock,flags); - usc_stop_transmitter(info); - spin_unlock_irqrestore(&info->irq_spinlock,flags); + /* shutdown adapter and release resources */ + shutdown(info); - netif_wake_queue(dev); + hdlc_close(dev); + + spin_lock_irqsave(&info->netlock, flags); + info->netcount=0; + spin_unlock_irqrestore(&info->netlock, flags); + + return 0; } -int mgsl_sppp_tx(struct sk_buff *skb, struct net_device *dev) +/** + * called by network layer to process IOCTL call to network device + * + * dev pointer to network device structure + * ifr pointer to network interface request structure + * cmd IOCTL command code + * + * returns 0 if success, otherwise error code + */ +static int hdlcdev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) { - struct mgsl_struct *info = dev->priv; - unsigned long flags; + const size_t size = sizeof(sync_serial_settings); + sync_serial_settings new_line; + sync_serial_settings __user *line = ifr->ifr_settings.ifs_ifsu.sync; + struct mgsl_struct *info = dev_to_port(dev); + unsigned int flags; if (debug_level >= DEBUG_LEVEL_INFO) - printk("mgsl_sppp_tx(%s)\n",info->netname); + printk("%s:hdlcdev_ioctl(%s)\n",__FILE__,dev->name); - netif_stop_queue(dev); + /* return error if TTY interface open */ + if (info->count) + return -EBUSY; - info->xmit_cnt = skb->len; - mgsl_load_tx_dma_buffer(info, skb->data, skb->len); - info->netstats.tx_packets++; - info->netstats.tx_bytes += skb->len; - dev_kfree_skb(skb); + if (cmd != SIOCWANDEV) + return hdlc_ioctl(dev, ifr, cmd); - dev->trans_start = jiffies; + switch(ifr->ifr_settings.type) { + case IF_GET_IFACE: /* return current sync_serial_settings */ - spin_lock_irqsave(&info->irq_spinlock,flags); - if (!info->tx_active) - usc_start_transmitter(info); - spin_unlock_irqrestore(&info->irq_spinlock,flags); + ifr->ifr_settings.type = IF_IFACE_SYNC_SERIAL; + if (ifr->ifr_settings.size < size) { + ifr->ifr_settings.size = size; /* data size wanted */ + return -ENOBUFS; + } - return 0; + flags = info->params.flags & (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_RXC_DPLL | + HDLC_FLAG_RXC_BRG | HDLC_FLAG_RXC_TXCPIN | + HDLC_FLAG_TXC_TXCPIN | HDLC_FLAG_TXC_DPLL | + HDLC_FLAG_TXC_BRG | HDLC_FLAG_TXC_RXCPIN); + + switch (flags){ + case (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_TXCPIN): new_line.clock_type = CLOCK_EXT; break; + case (HDLC_FLAG_RXC_BRG | HDLC_FLAG_TXC_BRG): new_line.clock_type = CLOCK_INT; break; + case (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_BRG): new_line.clock_type = CLOCK_TXINT; break; + case (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_RXCPIN): new_line.clock_type = CLOCK_TXFROMRX; break; + default: new_line.clock_type = CLOCK_DEFAULT; + } + + new_line.clock_rate = info->params.clock_speed; + new_line.loopback = info->params.loopback ? 1:0; + + if (copy_to_user(line, &new_line, size)) + return -EFAULT; + return 0; + + case IF_IFACE_SYNC_SERIAL: /* set sync_serial_settings */ + + if(!capable(CAP_NET_ADMIN)) + return -EPERM; + if (copy_from_user(&new_line, line, size)) + return -EFAULT; + + switch (new_line.clock_type) + { + case CLOCK_EXT: flags = HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_TXCPIN; break; + case CLOCK_TXFROMRX: flags = HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_RXCPIN; break; + case CLOCK_INT: flags = HDLC_FLAG_RXC_BRG | HDLC_FLAG_TXC_BRG; break; + case CLOCK_TXINT: flags = HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_BRG; break; + case CLOCK_DEFAULT: flags = info->params.flags & + (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_RXC_DPLL | + HDLC_FLAG_RXC_BRG | HDLC_FLAG_RXC_TXCPIN | + HDLC_FLAG_TXC_TXCPIN | HDLC_FLAG_TXC_DPLL | + HDLC_FLAG_TXC_BRG | HDLC_FLAG_TXC_RXCPIN); break; + default: return -EINVAL; + } + + if (new_line.loopback != 0 && new_line.loopback != 1) + return -EINVAL; + + info->params.flags &= ~(HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_RXC_DPLL | + HDLC_FLAG_RXC_BRG | HDLC_FLAG_RXC_TXCPIN | + HDLC_FLAG_TXC_TXCPIN | HDLC_FLAG_TXC_DPLL | + HDLC_FLAG_TXC_BRG | HDLC_FLAG_TXC_RXCPIN); + info->params.flags |= flags; + + info->params.loopback = new_line.loopback; + + if (flags & (HDLC_FLAG_RXC_BRG | HDLC_FLAG_TXC_BRG)) + info->params.clock_speed = new_line.clock_rate; + else + info->params.clock_speed = 0; + + /* if network interface up, reprogram hardware */ + if (info->netcount) + mgsl_program_hw(info); + return 0; + + default: + return hdlc_ioctl(dev, ifr, cmd); + } } -int mgsl_sppp_close(struct net_device *d) +/** + * called by network layer when transmit timeout is detected + * + * dev pointer to network device structure + */ +static void hdlcdev_tx_timeout(struct net_device *dev) { - struct mgsl_struct *info = d->priv; + struct mgsl_struct *info = dev_to_port(dev); + struct net_device_stats *stats = hdlc_stats(dev); unsigned long flags; if (debug_level >= DEBUG_LEVEL_INFO) - printk("mgsl_sppp_close(%s)\n",info->netname); + printk("hdlcdev_tx_timeout(%s)\n",dev->name); - /* shutdown adapter and release resources */ - shutdown(info); + stats->tx_errors++; + stats->tx_aborted_errors++; + + spin_lock_irqsave(&info->irq_spinlock,flags); + usc_stop_transmitter(info); + spin_unlock_irqrestore(&info->irq_spinlock,flags); - /* allow syncppp to do close processing */ - sppp_close(d); - netif_stop_queue(d); + netif_wake_queue(dev); +} - spin_lock_irqsave(&info->netlock, flags); - info->netcount=0; - spin_unlock_irqrestore(&info->netlock, flags); - return 0; +/** + * called by device driver when transmit completes + * reenable network layer transmit if stopped + * + * info pointer to device instance information + */ +static void hdlcdev_tx_done(struct mgsl_struct *info) +{ + if (netif_queue_stopped(info->netdev)) + netif_wake_queue(info->netdev); } -void mgsl_sppp_rx_done(struct mgsl_struct *info, char *buf, int size) +/** + * called by device driver when frame received + * pass frame to network layer + * + * info pointer to device instance information + * buf pointer to buffer contianing frame data + * size count of data bytes in buf + */ +static void hdlcdev_rx(struct mgsl_struct *info, char *buf, int size) { struct sk_buff *skb = dev_alloc_skb(size); + struct net_device *dev = info->netdev; + struct net_device_stats *stats = hdlc_stats(dev); + if (debug_level >= DEBUG_LEVEL_INFO) - printk("mgsl_sppp_rx_done(%s)\n",info->netname); + printk("hdlcdev_rx(%s)\n",dev->name); + if (skb == NULL) { - printk(KERN_NOTICE "%s: can't alloc skb, dropping packet\n", - info->netname); - info->netstats.rx_dropped++; + printk(KERN_NOTICE "%s: can't alloc skb, dropping packet\n", dev->name); + stats->rx_dropped++; return; } memcpy(skb_put(skb, size),buf,size); - skb->protocol = htons(ETH_P_WAN_PPP); - skb->dev = info->netdev; - skb->mac.raw = skb->data; - info->netstats.rx_packets++; - info->netstats.rx_bytes += size; + skb->dev = info->netdev; + skb->mac.raw = skb->data; + skb->protocol = hdlc_type_trans(skb, skb->dev); + + stats->rx_packets++; + stats->rx_bytes += size; + netif_rx(skb); - info->netdev->trans_start = jiffies; -} -void mgsl_sppp_tx_done(struct mgsl_struct *info) -{ - if (netif_queue_stopped(info->netdev)) - netif_wake_queue(info->netdev); + info->netdev->last_rx = jiffies; } -struct net_device_stats *mgsl_net_stats(struct net_device *dev) +/** + * called by device driver when adding device instance + * do generic HDLC initialization + * + * info pointer to device instance information + * + * returns 0 if success, otherwise error code + */ +static int hdlcdev_init(struct mgsl_struct *info) { - struct mgsl_struct *info = dev->priv; - if (debug_level >= DEBUG_LEVEL_INFO) - printk("mgsl_net_stats(%s)\n",info->netname); - return &info->netstats; + int rc; + struct net_device *dev; + hdlc_device *hdlc; + + /* allocate and initialize network and HDLC layer objects */ + + if (!(dev = alloc_hdlcdev(info))) { + printk(KERN_ERR "%s:hdlc device allocation failure\n",__FILE__); + return -ENOMEM; + } + + /* for network layer reporting purposes only */ + dev->base_addr = info->io_base; + dev->irq = info->irq_level; + dev->dma = info->dma_level; + + /* network layer callbacks and settings */ + dev->do_ioctl = hdlcdev_ioctl; + dev->open = hdlcdev_open; + dev->stop = hdlcdev_close; + dev->tx_timeout = hdlcdev_tx_timeout; + dev->watchdog_timeo = 10*HZ; + dev->tx_queue_len = 50; + + /* generic HDLC layer callbacks and settings */ + hdlc = dev_to_hdlc(dev); + hdlc->attach = hdlcdev_attach; + hdlc->xmit = hdlcdev_xmit; + + /* register objects with HDLC layer */ + if ((rc = register_hdlc_device(dev))) { + printk(KERN_WARNING "%s:unable to register hdlc device\n",__FILE__); + free_netdev(dev); + return rc; + } + + info->netdev = dev; + return 0; } -int mgsl_sppp_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) +/** + * called by device driver when removing device instance + * do generic HDLC cleanup + * + * info pointer to device instance information + */ +static void hdlcdev_exit(struct mgsl_struct *info) { - struct mgsl_struct *info = dev->priv; - if (debug_level >= DEBUG_LEVEL_INFO) - printk("%s(%d):mgsl_ioctl %s cmd=%08X\n", __FILE__,__LINE__, - info->netname, cmd ); - return sppp_do_ioctl(dev, ifr, cmd); + unregister_hdlc_device(info->netdev); + free_netdev(info->netdev); + info->netdev = NULL; } -#endif /* ifdef CONFIG_SYNCLINK_SYNCPPP */ +#endif /* CONFIG_HDLC */ + static int __devinit synclink_init_one (struct pci_dev *dev, const struct pci_device_id *ent) diff -Nru a/drivers/char/synclinkmp.c b/drivers/char/synclinkmp.c --- a/drivers/char/synclinkmp.c 2004-08-25 22:01:54 -07:00 +++ b/drivers/char/synclinkmp.c 2004-08-25 22:01:54 -07:00 @@ -1,5 +1,5 @@ /* - * $Id: synclinkmp.c,v 4.22 2004/06/03 14:50:10 paulkf Exp $ + * $Id: synclinkmp.c,v 4.26 2004/08/11 19:30:02 paulkf Exp $ * * Device driver for Microgate SyncLink Multiport * high speed multiprotocol serial adapter. @@ -67,13 +67,10 @@ #include #include #include +#include -#ifdef CONFIG_SYNCLINK_SYNCPPP_MODULE -#define CONFIG_SYNCLINK_SYNCPPP 1 -#endif - -#ifdef CONFIG_SYNCLINK_SYNCPPP -#include +#ifdef CONFIG_HDLC_MODULE +#define CONFIG_HDLC 1 #endif #define GET_USER(error,value,addr) error = get_user(value,addr) @@ -284,12 +281,11 @@ int netcount; int dosyncppp; spinlock_t netlock; -#ifdef CONFIG_SYNCLINK_SYNCPPP - struct ppp_device pppdev; - char netname[10]; + +#ifdef CONFIG_HDLC struct net_device *netdev; - struct net_device_stats netstats; #endif + } SLMP_INFO; #define MGSL_MAGIC 0x5401 @@ -361,12 +357,7 @@ #define TMCS 0x64 #define TEPR 0x65 -/* - * FIXME: DAR here clashed with asm-ppc/reg.h and asm-sh/.../dma.h - */ -#undef DAR /* DMA Controller Register macros */ -#define DAR 0x80 #define DARL 0x80 #define DARH 0x81 #define DARB 0x82 @@ -498,7 +489,7 @@ MODULE_PARM(dosyncppp,"1-" __MODULE_STRING(MAX_DEVICES) "i"); static char *driver_name = "SyncLink MultiPort driver"; -static char *driver_version = "$Revision: 4.22 $"; +static char *driver_version = "$Revision: 4.26 $"; static int synclinkmp_init_one(struct pci_dev *dev,const struct pci_device_id *ent); static void synclinkmp_remove_one(struct pci_dev *dev); @@ -553,20 +544,12 @@ static void unthrottle(struct tty_struct * tty); static void set_break(struct tty_struct *tty, int break_state); -/* sppp support and callbacks */ - -#ifdef CONFIG_SYNCLINK_SYNCPPP -static void sppp_init(SLMP_INFO *info); -static void sppp_delete(SLMP_INFO *info); -static void sppp_rx_done(SLMP_INFO *info, char *buf, int size); -static void sppp_tx_done(SLMP_INFO *info); - -static int sppp_cb_open(struct net_device *d); -static int sppp_cb_close(struct net_device *d); -static int sppp_cb_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd); -static int sppp_cb_tx(struct sk_buff *skb, struct net_device *dev); -static void sppp_cb_tx_timeout(struct net_device *dev); -static struct net_device_stats *sppp_cb_net_stats(struct net_device *dev); +#ifdef CONFIG_HDLC +#define dev_to_port(D) (dev_to_hdlc(D)->priv) +static void hdlcdev_tx_done(SLMP_INFO *info); +static void hdlcdev_rx(SLMP_INFO *info, char *buf, int size); +static int hdlcdev_init(SLMP_INFO *info); +static void hdlcdev_exit(SLMP_INFO *info); #endif /* ioctl handlers */ @@ -800,7 +783,7 @@ cleanup: if (retval) { if (tty->count == 1) - info->tty = NULL;/* tty layer will release tty struct */ + info->tty = NULL; /* tty layer will release tty struct */ if(info->count) info->count--; } @@ -1627,79 +1610,125 @@ spin_unlock_irqrestore(&info->lock,flags); } -#ifdef CONFIG_SYNCLINK_SYNCPPP - -/* syncppp support and callbacks */ - -static void cb_setup(struct net_device *dev) -{ - dev->open = sppp_cb_open; - dev->stop = sppp_cb_close; - dev->hard_start_xmit = sppp_cb_tx; - dev->do_ioctl = sppp_cb_ioctl; - dev->get_stats = sppp_cb_net_stats; - dev->tx_timeout = sppp_cb_tx_timeout; - dev->watchdog_timeo = 10*HZ; -} +#ifdef CONFIG_HDLC -static void sppp_init(SLMP_INFO *info) +/** + * called by generic HDLC layer when protocol selected (PPP, frame relay, etc.) + * set encoding and frame check sequence (FCS) options + * + * dev pointer to network device structure + * encoding serial encoding setting + * parity FCS setting + * + * returns 0 if success, otherwise error code + */ +static int hdlcdev_attach(struct net_device *dev, unsigned short encoding, + unsigned short parity) { - struct net_device *d; + SLMP_INFO *info = dev_to_port(dev); + unsigned char new_encoding; + unsigned short new_crctype; - sprintf(info->netname,"mgslm%dp%d",info->adapter_num,info->port_num); + /* return error if TTY interface open */ + if (info->count) + return -EBUSY; - d = alloc_netdev(0, info->netname, cb_setup); - if (!d) { - printk(KERN_WARNING "%s: alloc_netdev failed.\n", - info->netname); - return; + switch (encoding) + { + case ENCODING_NRZ: new_encoding = HDLC_ENCODING_NRZ; break; + case ENCODING_NRZI: new_encoding = HDLC_ENCODING_NRZI_SPACE; break; + case ENCODING_FM_MARK: new_encoding = HDLC_ENCODING_BIPHASE_MARK; break; + case ENCODING_FM_SPACE: new_encoding = HDLC_ENCODING_BIPHASE_SPACE; break; + case ENCODING_MANCHESTER: new_encoding = HDLC_ENCODING_BIPHASE_LEVEL; break; + default: return -EINVAL; } - info->if_ptr = &info->pppdev; - info->netdev = info->pppdev.dev = d; - - d->irq = info->irq_level; - d->priv = info; + switch (parity) + { + case PARITY_NONE: new_crctype = HDLC_CRC_NONE; break; + case PARITY_CRC16_PR1_CCITT: new_crctype = HDLC_CRC_16_CCITT; break; + case PARITY_CRC32_PR1_CCITT: new_crctype = HDLC_CRC_32_CCITT; break; + default: return -EINVAL; + } - sppp_attach(&info->pppdev); - cb_setup(d); + info->params.encoding = new_encoding; + info->params.crc_type = new_crctype;; - if (register_netdev(d)) { - printk(KERN_WARNING "%s: register_netdev failed.\n", d->name); - sppp_detach(info->netdev); - info->netdev = NULL; - info->pppdev.dev = NULL; - free_netdev(d); - return; - } + /* if network interface up, reprogram hardware */ + if (info->netcount) + program_hw(info); - if (debug_level >= DEBUG_LEVEL_INFO) - printk("sppp_init(%s)\n",info->netname); + return 0; } -static void sppp_delete(SLMP_INFO *info) +/** + * called by generic HDLC layer to send frame + * + * skb socket buffer containing HDLC frame + * dev pointer to network device structure + * + * returns 0 if success, otherwise error code + */ +static int hdlcdev_xmit(struct sk_buff *skb, struct net_device *dev) { + SLMP_INFO *info = dev_to_port(dev); + struct net_device_stats *stats = hdlc_stats(dev); + unsigned long flags; + if (debug_level >= DEBUG_LEVEL_INFO) - printk("sppp_delete(%s)\n",info->netname); - unregister_netdev(info->netdev); - sppp_detach(info->netdev); - free_netdev(info->netdev); - info->netdev = NULL; - info->pppdev.dev = NULL; + printk(KERN_INFO "%s:hdlc_xmit(%s)\n",__FILE__,dev->name); + + /* stop sending until this frame completes */ + netif_stop_queue(dev); + + /* copy data to device buffers */ + info->tx_count = skb->len; + tx_load_dma_buffer(info, skb->data, skb->len); + + /* update network statistics */ + stats->tx_packets++; + stats->tx_bytes += skb->len; + + /* done with socket buffer, so free it */ + dev_kfree_skb(skb); + + /* save start time for transmit timeout detection */ + dev->trans_start = jiffies; + + /* start hardware transmitter if necessary */ + spin_lock_irqsave(&info->lock,flags); + if (!info->tx_active) + tx_start(info); + spin_unlock_irqrestore(&info->lock,flags); + + return 0; } -static int sppp_cb_open(struct net_device *d) +/** + * called by network layer when interface enabled + * claim resources and initialize hardware + * + * dev pointer to network device structure + * + * returns 0 if success, otherwise error code + */ +static int hdlcdev_open(struct net_device *dev) { - SLMP_INFO *info = d->priv; - int err; + SLMP_INFO *info = dev_to_port(dev); + int rc; unsigned long flags; if (debug_level >= DEBUG_LEVEL_INFO) - printk("sppp_cb_open(%s)\n",info->netname); + printk("%s:hdlcdev_open(%s)\n",__FILE__,dev->name); + + /* generic HDLC layer open processing */ + if ((rc = hdlc_open(dev))) + return rc; + /* arbitrate between network and tty opens */ spin_lock_irqsave(&info->netlock, flags); if (info->count != 0 || info->netcount != 0) { - printk(KERN_WARNING "%s: sppp_cb_open returning busy\n", info->netname); + printk(KERN_WARNING "%s: hdlc_open returning busy\n", dev->name); spin_unlock_irqrestore(&info->netlock, flags); return -EBUSY; } @@ -1707,141 +1736,300 @@ spin_unlock_irqrestore(&info->netlock, flags); /* claim resources and init adapter */ - if ((err = startup(info)) != 0) - goto open_fail; - - /* allow syncppp module to do open processing */ - if ((err = sppp_open(d)) != 0) { - shutdown(info); - goto open_fail; + if ((rc = startup(info)) != 0) { + spin_lock_irqsave(&info->netlock, flags); + info->netcount=0; + spin_unlock_irqrestore(&info->netlock, flags); + return rc; } + /* assert DTR and RTS, apply hardware settings */ info->serial_signals |= SerialSignal_RTS + SerialSignal_DTR; program_hw(info); - d->trans_start = jiffies; - netif_start_queue(d); - return 0; + /* enable network layer transmit */ + dev->trans_start = jiffies; + netif_start_queue(dev); -open_fail: - spin_lock_irqsave(&info->netlock, flags); - info->netcount=0; - spin_unlock_irqrestore(&info->netlock, flags); - return err; + /* inform generic HDLC layer of current DCD status */ + spin_lock_irqsave(&info->lock, flags); + get_signals(info); + spin_unlock_irqrestore(&info->lock, flags); + hdlc_set_carrier(info->serial_signals & SerialSignal_DCD, dev); + + return 0; } -static void sppp_cb_tx_timeout(struct net_device *dev) +/** + * called by network layer when interface is disabled + * shutdown hardware and release resources + * + * dev pointer to network device structure + * + * returns 0 if success, otherwise error code + */ +static int hdlcdev_close(struct net_device *dev) { - SLMP_INFO *info = dev->priv; + SLMP_INFO *info = dev_to_port(dev); unsigned long flags; if (debug_level >= DEBUG_LEVEL_INFO) - printk("sppp_tx_timeout(%s)\n",info->netname); + printk("%s:hdlcdev_close(%s)\n",__FILE__,dev->name); - info->netstats.tx_errors++; - info->netstats.tx_aborted_errors++; + netif_stop_queue(dev); - spin_lock_irqsave(&info->lock,flags); - tx_stop(info); - spin_unlock_irqrestore(&info->lock,flags); + /* shutdown adapter and release resources */ + shutdown(info); - netif_wake_queue(dev); + hdlc_close(dev); + + spin_lock_irqsave(&info->netlock, flags); + info->netcount=0; + spin_unlock_irqrestore(&info->netlock, flags); + + return 0; } -static int sppp_cb_tx(struct sk_buff *skb, struct net_device *dev) +/** + * called by network layer to process IOCTL call to network device + * + * dev pointer to network device structure + * ifr pointer to network interface request structure + * cmd IOCTL command code + * + * returns 0 if success, otherwise error code + */ +static int hdlcdev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) { - SLMP_INFO *info = dev->priv; - unsigned long flags; + const size_t size = sizeof(sync_serial_settings); + sync_serial_settings new_line; + sync_serial_settings __user *line = ifr->ifr_settings.ifs_ifsu.sync; + SLMP_INFO *info = dev_to_port(dev); + unsigned int flags; if (debug_level >= DEBUG_LEVEL_INFO) - printk("sppp_tx(%s)\n",info->netname); + printk("%s:hdlcdev_ioctl(%s)\n",__FILE__,dev->name); - netif_stop_queue(dev); + /* return error if TTY interface open */ + if (info->count) + return -EBUSY; - info->tx_count = skb->len; - tx_load_dma_buffer(info, skb->data, skb->len); - info->netstats.tx_packets++; - info->netstats.tx_bytes += skb->len; - dev_kfree_skb(skb); + if (cmd != SIOCWANDEV) + return hdlc_ioctl(dev, ifr, cmd); - dev->trans_start = jiffies; + switch(ifr->ifr_settings.type) { + case IF_GET_IFACE: /* return current sync_serial_settings */ - spin_lock_irqsave(&info->lock,flags); - if (!info->tx_active) - tx_start(info); - spin_unlock_irqrestore(&info->lock,flags); + ifr->ifr_settings.type = IF_IFACE_SYNC_SERIAL; + if (ifr->ifr_settings.size < size) { + ifr->ifr_settings.size = size; /* data size wanted */ + return -ENOBUFS; + } - return 0; + flags = info->params.flags & (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_RXC_DPLL | + HDLC_FLAG_RXC_BRG | HDLC_FLAG_RXC_TXCPIN | + HDLC_FLAG_TXC_TXCPIN | HDLC_FLAG_TXC_DPLL | + HDLC_FLAG_TXC_BRG | HDLC_FLAG_TXC_RXCPIN); + + switch (flags){ + case (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_TXCPIN): new_line.clock_type = CLOCK_EXT; break; + case (HDLC_FLAG_RXC_BRG | HDLC_FLAG_TXC_BRG): new_line.clock_type = CLOCK_INT; break; + case (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_BRG): new_line.clock_type = CLOCK_TXINT; break; + case (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_RXCPIN): new_line.clock_type = CLOCK_TXFROMRX; break; + default: new_line.clock_type = CLOCK_DEFAULT; + } + + new_line.clock_rate = info->params.clock_speed; + new_line.loopback = info->params.loopback ? 1:0; + + if (copy_to_user(line, &new_line, size)) + return -EFAULT; + return 0; + + case IF_IFACE_SYNC_SERIAL: /* set sync_serial_settings */ + + if(!capable(CAP_NET_ADMIN)) + return -EPERM; + if (copy_from_user(&new_line, line, size)) + return -EFAULT; + + switch (new_line.clock_type) + { + case CLOCK_EXT: flags = HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_TXCPIN; break; + case CLOCK_TXFROMRX: flags = HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_RXCPIN; break; + case CLOCK_INT: flags = HDLC_FLAG_RXC_BRG | HDLC_FLAG_TXC_BRG; break; + case CLOCK_TXINT: flags = HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_BRG; break; + case CLOCK_DEFAULT: flags = info->params.flags & + (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_RXC_DPLL | + HDLC_FLAG_RXC_BRG | HDLC_FLAG_RXC_TXCPIN | + HDLC_FLAG_TXC_TXCPIN | HDLC_FLAG_TXC_DPLL | + HDLC_FLAG_TXC_BRG | HDLC_FLAG_TXC_RXCPIN); break; + default: return -EINVAL; + } + + if (new_line.loopback != 0 && new_line.loopback != 1) + return -EINVAL; + + info->params.flags &= ~(HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_RXC_DPLL | + HDLC_FLAG_RXC_BRG | HDLC_FLAG_RXC_TXCPIN | + HDLC_FLAG_TXC_TXCPIN | HDLC_FLAG_TXC_DPLL | + HDLC_FLAG_TXC_BRG | HDLC_FLAG_TXC_RXCPIN); + info->params.flags |= flags; + + info->params.loopback = new_line.loopback; + + if (flags & (HDLC_FLAG_RXC_BRG | HDLC_FLAG_TXC_BRG)) + info->params.clock_speed = new_line.clock_rate; + else + info->params.clock_speed = 0; + + /* if network interface up, reprogram hardware */ + if (info->netcount) + program_hw(info); + return 0; + + default: + return hdlc_ioctl(dev, ifr, cmd); + } } -static int sppp_cb_close(struct net_device *d) +/** + * called by network layer when transmit timeout is detected + * + * dev pointer to network device structure + */ +static void hdlcdev_tx_timeout(struct net_device *dev) { - SLMP_INFO *info = d->priv; + SLMP_INFO *info = dev_to_port(dev); + struct net_device_stats *stats = hdlc_stats(dev); unsigned long flags; if (debug_level >= DEBUG_LEVEL_INFO) - printk("sppp_cb_close(%s)\n",info->netname); + printk("hdlcdev_tx_timeout(%s)\n",dev->name); - /* shutdown adapter and release resources */ - shutdown(info); + stats->tx_errors++; + stats->tx_aborted_errors++; - /* allow syncppp to do close processing */ - sppp_close(d); - netif_stop_queue(d); + spin_lock_irqsave(&info->lock,flags); + tx_stop(info); + spin_unlock_irqrestore(&info->lock,flags); - spin_lock_irqsave(&info->netlock, flags); - info->netcount=0; - spin_unlock_irqrestore(&info->netlock, flags); - return 0; + netif_wake_queue(dev); } -static void sppp_rx_done(SLMP_INFO *info, char *buf, int size) +/** + * called by device driver when transmit completes + * reenable network layer transmit if stopped + * + * info pointer to device instance information + */ +static void hdlcdev_tx_done(SLMP_INFO *info) +{ + if (netif_queue_stopped(info->netdev)) + netif_wake_queue(info->netdev); +} + +/** + * called by device driver when frame received + * pass frame to network layer + * + * info pointer to device instance information + * buf pointer to buffer contianing frame data + * size count of data bytes in buf + */ +static void hdlcdev_rx(SLMP_INFO *info, char *buf, int size) { struct sk_buff *skb = dev_alloc_skb(size); + struct net_device *dev = info->netdev; + struct net_device_stats *stats = hdlc_stats(dev); + if (debug_level >= DEBUG_LEVEL_INFO) - printk("sppp_rx_done(%s)\n",info->netname); + printk("hdlcdev_rx(%s)\n",dev->name); + if (skb == NULL) { - printk(KERN_NOTICE "%s: can't alloc skb, dropping packet\n", - info->netname); - info->netstats.rx_dropped++; + printk(KERN_NOTICE "%s: can't alloc skb, dropping packet\n", dev->name); + stats->rx_dropped++; return; } memcpy(skb_put(skb, size),buf,size); - skb->protocol = htons(ETH_P_WAN_PPP); - skb->dev = info->netdev; - skb->mac.raw = skb->data; - info->netstats.rx_packets++; - info->netstats.rx_bytes += size; + skb->dev = info->netdev; + skb->mac.raw = skb->data; + skb->protocol = hdlc_type_trans(skb, skb->dev); + + stats->rx_packets++; + stats->rx_bytes += size; + netif_rx(skb); - info->netdev->trans_start = jiffies; -} -static void sppp_tx_done(SLMP_INFO *info) -{ - if (netif_queue_stopped(info->netdev)) - netif_wake_queue(info->netdev); + info->netdev->last_rx = jiffies; } -static struct net_device_stats *sppp_cb_net_stats(struct net_device *dev) +/** + * called by device driver when adding device instance + * do generic HDLC initialization + * + * info pointer to device instance information + * + * returns 0 if success, otherwise error code + */ +static int hdlcdev_init(SLMP_INFO *info) { - SLMP_INFO *info = dev->priv; - if (debug_level >= DEBUG_LEVEL_INFO) - printk("net_stats(%s)\n",info->netname); - return &info->netstats; + int rc; + struct net_device *dev; + hdlc_device *hdlc; + + /* allocate and initialize network and HDLC layer objects */ + + if (!(dev = alloc_hdlcdev(info))) { + printk(KERN_ERR "%s:hdlc device allocation failure\n",__FILE__); + return -ENOMEM; + } + + /* for network layer reporting purposes only */ + dev->mem_start = info->phys_sca_base; + dev->mem_end = info->phys_sca_base + SCA_BASE_SIZE - 1; + dev->irq = info->irq_level; + + /* network layer callbacks and settings */ + dev->do_ioctl = hdlcdev_ioctl; + dev->open = hdlcdev_open; + dev->stop = hdlcdev_close; + dev->tx_timeout = hdlcdev_tx_timeout; + dev->watchdog_timeo = 10*HZ; + dev->tx_queue_len = 50; + + /* generic HDLC layer callbacks and settings */ + hdlc = dev_to_hdlc(dev); + hdlc->attach = hdlcdev_attach; + hdlc->xmit = hdlcdev_xmit; + + /* register objects with HDLC layer */ + if ((rc = register_hdlc_device(dev))) { + printk(KERN_WARNING "%s:unable to register hdlc device\n",__FILE__); + free_netdev(dev); + return rc; + } + + info->netdev = dev; + return 0; } -static int sppp_cb_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) +/** + * called by device driver when removing device instance + * do generic HDLC cleanup + * + * info pointer to device instance information + */ +static void hdlcdev_exit(SLMP_INFO *info) { - SLMP_INFO *info = dev->priv; - if (debug_level >= DEBUG_LEVEL_INFO) - printk("%s(%d):ioctl %s cmd=%08X\n", __FILE__,__LINE__, - info->netname, cmd ); - return sppp_do_ioctl(dev, ifr, cmd); + unregister_hdlc_device(info->netdev); + free_netdev(info->netdev); + info->netdev = NULL; } -#endif /* ifdef CONFIG_SYNCLINK_SYNCPPP */ +#endif /* CONFIG_HDLC */ /* Return next bottom half action to perform. @@ -2168,9 +2356,9 @@ set_signals(info); } -#ifdef CONFIG_SYNCLINK_SYNCPPP +#ifdef CONFIG_HDLC if (info->netcount) - sppp_tx_done(info); + hdlcdev_tx_done(info); else #endif { @@ -2358,12 +2546,12 @@ icount->dcd++; if (status & SerialSignal_DCD) { info->input_signal_events.dcd_up++; -#ifdef CONFIG_SYNCLINK_SYNCPPP - if (info->netcount) - sppp_reopen(info->netdev); -#endif } else info->input_signal_events.dcd_down++; +#ifdef CONFIG_HDLC + if (info->netcount) + hdlc_set_carrier(status & SerialSignal_DCD, info->netdev); +#endif } if (status & MISCSTATUS_CTS_LATCHED) { @@ -3616,9 +3804,8 @@ info->irq_level, info->max_frame_size ); -#ifdef CONFIG_SYNCLINK_SYNCPPP - if (info->dosyncppp) - sppp_init(info); +#ifdef CONFIG_HDLC + hdlcdev_init(info); #endif } @@ -3804,9 +3991,8 @@ info = synclinkmp_device_list; while(info) { -#ifdef CONFIG_SYNCLINK_SYNCPPP - if (info->dosyncppp) - sppp_delete(info); +#ifdef CONFIG_HDLC + hdlcdev_exit(info); #endif reset_port(info); if ( info->port_num == 0 ) { @@ -4823,10 +5009,12 @@ info->icount.rxcrc++; framesize = 0; - -#ifdef CONFIG_SYNCLINK_SYNCPPP - info->netstats.rx_errors++; - info->netstats.rx_frame_errors++; +#ifdef CONFIG_HDLC + { + struct net_device_stats *stats = hdlc_stats(info->netdev); + stats->rx_errors++; + stats->rx_frame_errors++; + } #endif } @@ -4862,11 +5050,9 @@ index = 0; } -#ifdef CONFIG_SYNCLINK_SYNCPPP - if (info->netcount) { - /* pass frame to syncppp device */ - sppp_rx_done(info,info->tmp_rx_buf,framesize); - } +#ifdef CONFIG_HDLC + if (info->netcount) + hdlcdev_rx(info,info->tmp_rx_buf,framesize); else #endif { @@ -5384,9 +5570,9 @@ spin_unlock_irqrestore(&info->lock,flags); -#ifdef CONFIG_SYNCLINK_SYNCPPP +#ifdef CONFIG_HDLC if (info->netcount) - sppp_tx_done(info); + hdlcdev_tx_done(info); else #endif bh_transmit(info); diff -Nru a/drivers/char/tty_io.c b/drivers/char/tty_io.c --- a/drivers/char/tty_io.c 2004-08-25 22:01:55 -07:00 +++ b/drivers/char/tty_io.c 2004-08-25 22:01:55 -07:00 @@ -142,6 +142,7 @@ ssize_t redirected_tty_write(struct file *, const char __user *, size_t, loff_t *); static unsigned int tty_poll(struct file *, poll_table *); static int tty_open(struct inode *, struct file *); +static int ptmx_open(struct inode *, struct file *); static int tty_release(struct inode *, struct file *); int tty_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigned long arg); @@ -377,6 +378,19 @@ .fasync = tty_fasync, }; +#ifdef CONFIG_UNIX98_PTYS +static struct file_operations ptmx_fops = { + .llseek = no_llseek, + .read = tty_read, + .write = tty_write, + .poll = tty_poll, + .ioctl = tty_ioctl, + .open = ptmx_open, + .release = tty_release, + .fasync = tty_fasync, +}; +#endif + static struct file_operations console_fops = { .llseek = no_llseek, .read = tty_read, @@ -749,6 +763,17 @@ return tty_write(file, buf, count, ppos); } +static char ptychar[] = "pqrstuvwxyzabcde"; + +static inline void pty_line_name(struct tty_driver *driver, int index, char *p) +{ + int i = index + driver->name_base; + /* ->name is initialized to "ttyp", but "tty" is expected */ + sprintf(p, "%s%c%x", + driver->subtype == PTY_TYPE_SLAVE ? "tty" : driver->name, + ptychar[i >> 4 & 0xf], i & 0xf); +} + static inline void tty_line_name(struct tty_driver *driver, int index, char *p) { sprintf(p, "%s%d", driver->name, index + driver->name_base); @@ -1358,53 +1383,13 @@ return -ENODEV; } -#ifdef CONFIG_UNIX98_PTYS - if (device == MKDEV(TTYAUX_MAJOR,2)) { - int idr_ret; - - /* find a device that is not in use. */ - down(&allocated_ptys_lock); - if (!idr_pre_get(&allocated_ptys, GFP_KERNEL)) { - up(&allocated_ptys_lock); - return -ENOMEM; - } - idr_ret = idr_get_new(&allocated_ptys, NULL, &index); - if (idr_ret < 0) { - up(&allocated_ptys_lock); - if (idr_ret == -EAGAIN) - return -ENOMEM; - return -EIO; - } - if (index >= pty_limit) { - idr_remove(&allocated_ptys, index); - up(&allocated_ptys_lock); - return -EIO; - } - up(&allocated_ptys_lock); - - driver = ptm_driver; - retval = init_dev(driver, index, &tty); - if (retval) { - down(&allocated_ptys_lock); - idr_remove(&allocated_ptys, index); - up(&allocated_ptys_lock); - return retval; - } - - set_bit(TTY_PTY_LOCK, &tty->flags); /* LOCK THE SLAVE */ - if (devpts_pty_new(tty->link)) - retval = -ENOMEM; - } else -#endif - { - driver = get_tty_driver(device, &index); - if (!driver) - return -ENODEV; + driver = get_tty_driver(device, &index); + if (!driver) + return -ENODEV; got_driver: - retval = init_dev(driver, index, &tty); - if (retval) - return retval; - } + retval = init_dev(driver, index, &tty); + if (retval) + return retval; filp->private_data = tty; file_move(filp, &tty->tty_files); @@ -1431,15 +1416,6 @@ printk(KERN_DEBUG "error %d in opening %s...", retval, tty->name); #endif - -#ifdef CONFIG_UNIX98_PTYS - if (index != -1) { - down(&allocated_ptys_lock); - idr_remove(&allocated_ptys, index); - up(&allocated_ptys_lock); - } -#endif - release_dev(filp); if (retval != -ERESTARTSYS) return retval; @@ -1467,6 +1443,62 @@ return 0; } +#ifdef CONFIG_UNIX98_PTYS +static int ptmx_open(struct inode * inode, struct file * filp) +{ + struct tty_struct *tty; + int retval; + int index; + int idr_ret; + + nonseekable_open(inode, filp); + + /* find a device that is not in use. */ + down(&allocated_ptys_lock); + if (!idr_pre_get(&allocated_ptys, GFP_KERNEL)) { + up(&allocated_ptys_lock); + return -ENOMEM; + } + idr_ret = idr_get_new(&allocated_ptys, NULL, &index); + if (idr_ret < 0) { + up(&allocated_ptys_lock); + if (idr_ret == -EAGAIN) + return -ENOMEM; + return -EIO; + } + if (index >= pty_limit) { + idr_remove(&allocated_ptys, index); + up(&allocated_ptys_lock); + return -EIO; + } + up(&allocated_ptys_lock); + + retval = init_dev(ptm_driver, index, &tty); + if (retval) + goto out; + + set_bit(TTY_PTY_LOCK, &tty->flags); /* LOCK THE SLAVE */ + filp->private_data = tty; + file_move(filp, &tty->tty_files); + + retval = -ENOMEM; + if (devpts_pty_new(tty->link)) + goto out1; + + check_tty_count(tty, "tty_open"); + retval = ptm_driver->open(tty, filp); + if (!retval) + return 0; +out1: + release_dev(filp); +out: + down(&allocated_ptys_lock); + idr_remove(&allocated_ptys, index); + up(&allocated_ptys_lock); + return retval; +} +#endif + static int tty_release(struct inode * inode, struct file * filp) { lock_kernel(); @@ -2154,6 +2186,7 @@ void tty_register_device(struct tty_driver *driver, unsigned index, struct device *device) { + char name[64]; dev_t dev = MKDEV(driver->major, driver->minor_start) + index; if (index >= driver->num) { @@ -2165,13 +2198,11 @@ devfs_mk_cdev(dev, S_IFCHR | S_IRUSR | S_IWUSR, "%s%d", driver->devfs_name, index + driver->name_base); - /* we don't care about the ptys */ - /* how nice to hide this behind some crappy interface.. */ - if (driver->type != TTY_DRIVER_TYPE_PTY) { - char name[64]; + if (driver->type == TTY_DRIVER_TYPE_PTY) + pty_line_name(driver, index, name); + else tty_line_name(driver, index, name); - class_simple_device_add(tty_class, dev, device, name); - } + class_simple_device_add(tty_class, dev, device, name); } /** @@ -2441,7 +2472,7 @@ class_simple_device_add(tty_class, MKDEV(TTYAUX_MAJOR, 1), NULL, "console"); #ifdef CONFIG_UNIX98_PTYS - cdev_init(&ptmx_cdev, &tty_fops); + cdev_init(&ptmx_cdev, &ptmx_fops); if (cdev_add(&ptmx_cdev, MKDEV(TTYAUX_MAJOR, 2), 1) || register_chrdev_region(MKDEV(TTYAUX_MAJOR, 2), 1, "/dev/ptmx") < 0) panic("Couldn't register /dev/ptmx driver\n"); diff -Nru a/drivers/char/vt.c b/drivers/char/vt.c --- a/drivers/char/vt.c 2004-08-25 22:01:56 -07:00 +++ b/drivers/char/vt.c 2004-08-25 22:01:56 -07:00 @@ -1981,12 +1981,16 @@ hide_cursor(currcons); while (!tty->stopped && count) { - c = *buf; + int orig = *buf; + c = orig; buf++; n++; count--; - if (utf) { + /* Do no translation at all in control states */ + if (vc_state != ESnormal) { + tc = c; + } else if (utf) { /* Combine UTF-8 into Unicode */ /* Incomplete characters silently ignored */ if(c > 0x7f) { @@ -2086,7 +2090,7 @@ continue; } FLUSH - do_con_trol(tty, currcons, c); + do_con_trol(tty, currcons, orig); } FLUSH console_conditional_schedule(); diff -Nru a/drivers/char/watchdog/Kconfig b/drivers/char/watchdog/Kconfig --- a/drivers/char/watchdog/Kconfig 2004-08-25 22:01:55 -07:00 +++ b/drivers/char/watchdog/Kconfig 2004-08-25 22:01:55 -07:00 @@ -319,6 +319,12 @@ To compile this driver as a module, choose M here: the module will be called machzwd. +# PowerPC Architecture + +config 8xx_WDT + tristate "MPC8xx Watchdog Timer" + depends on WATCHDOG && 8xx + # MIPS Architecture config INDYDOG diff -Nru a/drivers/char/watchdog/Makefile b/drivers/char/watchdog/Makefile --- a/drivers/char/watchdog/Makefile 2004-08-25 22:01:56 -07:00 +++ b/drivers/char/watchdog/Makefile 2004-08-25 22:01:56 -07:00 @@ -37,3 +37,4 @@ obj-$(CONFIG_USBPCWATCHDOG) += pcwd_usb.o obj-$(CONFIG_IXP4XX_WATCHDOG) += ixp4xx_wdt.o obj-$(CONFIG_IXP2000_WATCHDOG) += ixp2000_wdt.o +obj-$(CONFIG_8xx_WDT) += mpc8xx_wdt.o diff -Nru a/drivers/char/watchdog/mpc8xx_wdt.c b/drivers/char/watchdog/mpc8xx_wdt.c --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/drivers/char/watchdog/mpc8xx_wdt.c 2004-08-25 22:01:56 -07:00 @@ -0,0 +1,164 @@ +/* + * mpc8xx_wdt.c - MPC8xx watchdog userspace interface + * + * Author: Florian Schirmer + * + * 2002 (c) Florian Schirmer This file is licensed under + * the terms of the GNU General Public License version 2. This program + * is licensed "as is" without any warranty of any kind, whether express + * or implied. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static unsigned long wdt_opened; +static int wdt_status; + +static void mpc8xx_wdt_handler_disable(void) +{ + volatile immap_t *imap = (volatile immap_t *)IMAP_ADDR; + + imap->im_sit.sit_piscr &= ~(PISCR_PIE | PISCR_PTE); + + printk(KERN_NOTICE "mpc8xx_wdt: keep-alive handler deactivated\n"); +} + +static void mpc8xx_wdt_handler_enable(void) +{ + volatile immap_t *imap = (volatile immap_t *)IMAP_ADDR; + + imap->im_sit.sit_piscr |= PISCR_PIE | PISCR_PTE; + + printk(KERN_NOTICE "mpc8xx_wdt: keep-alive handler activated\n"); +} + +static int mpc8xx_wdt_open(struct inode *inode, struct file *file) +{ + if (test_and_set_bit(0, &wdt_opened)) + return -EBUSY; + + m8xx_wdt_reset(); + mpc8xx_wdt_handler_disable(); + + return 0; +} + +static int mpc8xx_wdt_release(struct inode *inode, struct file *file) +{ + m8xx_wdt_reset(); + +#if !defined(CONFIG_WATCHDOG_NOWAYOUT) + mpc8xx_wdt_handler_enable(); +#endif + + clear_bit(0, &wdt_opened); + + return 0; +} + +static ssize_t mpc8xx_wdt_write(struct file *file, const char *data, size_t len, + loff_t * ppos) +{ + if (ppos != &file->f_pos) + return -ESPIPE; + + if (len) + m8xx_wdt_reset(); + + return len; +} + +static int mpc8xx_wdt_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + int timeout; + static struct watchdog_info info = { + .options = WDIOF_KEEPALIVEPING, + .firmware_version = 0, + .identity = "MPC8xx watchdog", + }; + + switch (cmd) { + case WDIOC_GETSUPPORT: + if (copy_to_user((void *)arg, &info, sizeof(info))) + return -EFAULT; + break; + + case WDIOC_GETSTATUS: + case WDIOC_GETBOOTSTATUS: + if (put_user(wdt_status, (int *)arg)) + return -EFAULT; + wdt_status &= ~WDIOF_KEEPALIVEPING; + break; + + case WDIOC_GETTEMP: + return -EOPNOTSUPP; + + case WDIOC_SETOPTIONS: + return -EOPNOTSUPP; + + case WDIOC_KEEPALIVE: + m8xx_wdt_reset(); + wdt_status |= WDIOF_KEEPALIVEPING; + break; + + case WDIOC_SETTIMEOUT: + return -EOPNOTSUPP; + + case WDIOC_GETTIMEOUT: + timeout = m8xx_wdt_get_timeout(); + if (put_user(timeout, (int *)arg)) + return -EFAULT; + break; + + default: + return -ENOIOCTLCMD; + } + + return 0; +} + +static struct file_operations mpc8xx_wdt_fops = { + .owner = THIS_MODULE, + .llseek = no_llseek, + .write = mpc8xx_wdt_write, + .ioctl = mpc8xx_wdt_ioctl, + .open = mpc8xx_wdt_open, + .release = mpc8xx_wdt_release, +}; + +static struct miscdevice mpc8xx_wdt_miscdev = { + .minor = WATCHDOG_MINOR, + .name = "watchdog", + .fops = &mpc8xx_wdt_fops, +}; + +static int __init mpc8xx_wdt_init(void) +{ + return misc_register(&mpc8xx_wdt_miscdev); +} + +static void __exit mpc8xx_wdt_exit(void) +{ + misc_deregister(&mpc8xx_wdt_miscdev); + + m8xx_wdt_reset(); + mpc8xx_wdt_handler_enable(); +} + +module_init(mpc8xx_wdt_init); +module_exit(mpc8xx_wdt_exit); + +MODULE_AUTHOR("Florian Schirmer "); +MODULE_DESCRIPTION("MPC8xx watchdog driver"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); diff -Nru a/drivers/char/watchdog/wdt_pci.c b/drivers/char/watchdog/wdt_pci.c --- a/drivers/char/watchdog/wdt_pci.c 2004-08-25 22:01:55 -07:00 +++ b/drivers/char/watchdog/wdt_pci.c 2004-08-25 22:01:55 -07:00 @@ -674,8 +674,8 @@ out_misc: #ifdef CONFIG_WDT_501_PCI misc_deregister(&temp_miscdev); -#endif /* CONFIG_WDT_501_PCI */ out_rbt: +#endif /* CONFIG_WDT_501_PCI */ unregister_reboot_notifier(&wdtpci_notifier); out_irq: free_irq(irq, &wdtpci_miscdev); diff -Nru a/drivers/cpufreq/Kconfig b/drivers/cpufreq/Kconfig --- a/drivers/cpufreq/Kconfig 2004-08-25 22:01:56 -07:00 +++ b/drivers/cpufreq/Kconfig 2004-08-25 22:01:56 -07:00 @@ -69,6 +69,21 @@ If in doubt, say Y. +config CPU_FREQ_GOV_ONDEMAND + tristate "'ondemand' cpufreq policy governor" + depends on CPU_FREQ + help + 'ondemand' - This driver adds a dynamic cpufreq policy governor. + The governor does a periodic polling and + changes frequency based on the CPU utilization. + The support for this governor depends on CPU capability to + do fast frequency switching (i.e, very low latency frequency + transitions). + + For details, take a look at linux/Documentation/cpu-freq. + + If in doubt, say N. + config CPU_FREQ_24_API bool "/proc/sys/cpu/ interface (2.4. / OLD)" depends on CPU_FREQ && SYSCTL && CPU_FREQ_GOV_USERSPACE diff -Nru a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile --- a/drivers/cpufreq/Makefile 2004-08-25 22:01:56 -07:00 +++ b/drivers/cpufreq/Makefile 2004-08-25 22:01:56 -07:00 @@ -5,6 +5,7 @@ obj-$(CONFIG_CPU_FREQ_GOV_PERFORMANCE) += cpufreq_performance.o obj-$(CONFIG_CPU_FREQ_GOV_POWERSAVE) += cpufreq_powersave.o obj-$(CONFIG_CPU_FREQ_GOV_USERSPACE) += cpufreq_userspace.o +obj-$(CONFIG_CPU_FREQ_GOV_ONDEMAND) += cpufreq_ondemand.o # CPUfreq cross-arch helpers obj-$(CONFIG_CPU_FREQ_TABLE) += freq_table.o diff -Nru a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/drivers/cpufreq/cpufreq_ondemand.c 2004-08-25 22:01:56 -07:00 @@ -0,0 +1,424 @@ +/* + * drivers/cpufreq/cpufreq_ondemand.c + * + * Copyright (C) 2001 Russell King + * (C) 2003 Venkatesh Pallipadi . + * Jun Nakajima + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * dbs is used in this file as a shortform for demandbased switching + * It helps to keep variable names smaller, simpler + */ + +#define DEF_FREQUENCY_UP_THRESHOLD (80) +#define MIN_FREQUENCY_UP_THRESHOLD (0) +#define MAX_FREQUENCY_UP_THRESHOLD (100) + +#define DEF_FREQUENCY_DOWN_THRESHOLD (20) +#define MIN_FREQUENCY_DOWN_THRESHOLD (0) +#define MAX_FREQUENCY_DOWN_THRESHOLD (100) + +/* + * The polling frequency of this governor depends on the capability of + * the processor. Default polling frequency is 1000 times the transition + * latency of the processor. The governor will work on any processor with + * transition latency <= 10mS, using appropriate sampling + * rate. + * For CPUs with transition latency > 10mS (mostly drivers with CPUFREQ_ETERNAL) + * this governor will not work. + * All times here are in uS. + */ +static unsigned int def_sampling_rate; +#define MIN_SAMPLING_RATE (def_sampling_rate / 2) +#define MAX_SAMPLING_RATE (500 * def_sampling_rate) +#define DEF_SAMPLING_RATE_LATENCY_MULTIPLIER (1000) +#define DEF_SAMPLING_DOWN_FACTOR (10) +#define TRANSITION_LATENCY_LIMIT (10 * 1000) +#define sampling_rate_in_HZ(x) ((x * HZ) / (1000 * 1000)) + +static void do_dbs_timer(void *data); + +struct cpu_dbs_info_s { + struct cpufreq_policy *cur_policy; + unsigned int prev_cpu_idle_up; + unsigned int prev_cpu_idle_down; + unsigned int enable; +}; +static DEFINE_PER_CPU(struct cpu_dbs_info_s, cpu_dbs_info); + +static unsigned int dbs_enable; /* number of CPUs using this policy */ + +static DECLARE_MUTEX (dbs_sem); +static DECLARE_WORK (dbs_work, do_dbs_timer, NULL); + +struct dbs_tuners { + unsigned int sampling_rate; + unsigned int sampling_down_factor; + unsigned int up_threshold; + unsigned int down_threshold; +}; + +struct dbs_tuners dbs_tuners_ins = { + .up_threshold = DEF_FREQUENCY_UP_THRESHOLD, + .down_threshold = DEF_FREQUENCY_DOWN_THRESHOLD, + .sampling_down_factor = DEF_SAMPLING_DOWN_FACTOR, +}; + +/************************** sysfs interface ************************/ +static ssize_t show_current_freq(struct cpufreq_policy *policy, char *buf) +{ + return sprintf (buf, "%u\n", policy->cur); +} + +static ssize_t show_sampling_rate_max(struct cpufreq_policy *policy, char *buf) +{ + return sprintf (buf, "%u\n", MAX_SAMPLING_RATE); +} + +static ssize_t show_sampling_rate_min(struct cpufreq_policy *policy, char *buf) +{ + return sprintf (buf, "%u\n", MIN_SAMPLING_RATE); +} + +#define define_one_ro(_name) \ +static struct freq_attr _name = { \ + .attr = { .name = __stringify(_name), .mode = 0444 }, \ + .show = show_##_name, \ +} + +define_one_ro(current_freq); +define_one_ro(sampling_rate_max); +define_one_ro(sampling_rate_min); + +/* cpufreq_ondemand Governor Tunables */ +#define show_one(file_name, object) \ +static ssize_t show_##file_name \ +(struct cpufreq_policy *unused, char *buf) \ +{ \ + return sprintf(buf, "%u\n", dbs_tuners_ins.object); \ +} +show_one(sampling_rate, sampling_rate); +show_one(sampling_down_factor, sampling_down_factor); +show_one(up_threshold, up_threshold); +show_one(down_threshold, down_threshold); + +static ssize_t store_sampling_down_factor(struct cpufreq_policy *unused, + const char *buf, size_t count) +{ + unsigned int input; + int ret; + ret = sscanf (buf, "%u", &input); + down(&dbs_sem); + if (ret != 1 ) + goto out; + + dbs_tuners_ins.sampling_down_factor = input; +out: + up(&dbs_sem); + return count; +} + +static ssize_t store_sampling_rate(struct cpufreq_policy *unused, + const char *buf, size_t count) +{ + unsigned int input; + int ret; + ret = sscanf (buf, "%u", &input); + down(&dbs_sem); + if (ret != 1 || input > MAX_SAMPLING_RATE || input < MIN_SAMPLING_RATE) + goto out; + + dbs_tuners_ins.sampling_rate = input; +out: + up(&dbs_sem); + return count; +} + +static ssize_t store_up_threshold(struct cpufreq_policy *unused, + const char *buf, size_t count) +{ + unsigned int input; + int ret; + ret = sscanf (buf, "%u", &input); + down(&dbs_sem); + if (ret != 1 || input > MAX_FREQUENCY_UP_THRESHOLD || + input < MIN_FREQUENCY_UP_THRESHOLD || + input <= dbs_tuners_ins.down_threshold) + goto out; + + dbs_tuners_ins.up_threshold = input; +out: + up(&dbs_sem); + return count; +} + +static ssize_t store_down_threshold(struct cpufreq_policy *unused, + const char *buf, size_t count) +{ + unsigned int input; + int ret; + ret = sscanf (buf, "%u", &input); + down(&dbs_sem); + if (ret != 1 || input > MAX_FREQUENCY_DOWN_THRESHOLD || + input < MIN_FREQUENCY_DOWN_THRESHOLD || + input >= dbs_tuners_ins.up_threshold) + goto out; + + dbs_tuners_ins.down_threshold = input; +out: + up(&dbs_sem); + return count; +} + +#define define_one_rw(_name) \ +static struct freq_attr _name = { \ + .attr = { .name = __stringify(_name), .mode = 0644 }, \ + .show = show_##_name, \ + .store = store_##_name, \ +} + +define_one_rw(sampling_rate); +define_one_rw(sampling_down_factor); +define_one_rw(up_threshold); +define_one_rw(down_threshold); + +static struct attribute * dbs_attributes[] = { + ¤t_freq.attr, + &sampling_rate_max.attr, + &sampling_rate_min.attr, + &sampling_rate.attr, + &sampling_down_factor.attr, + &up_threshold.attr, + &down_threshold.attr, + NULL +}; + +static struct attribute_group dbs_attr_group = { + .attrs = dbs_attributes, + .name = "ondemand", +}; + +/************************** sysfs end ************************/ + +static void dbs_check_cpu(int cpu) +{ + unsigned int idle_ticks, up_idle_ticks, down_idle_ticks; + unsigned int freq_down_step; + unsigned int freq_down_sampling_rate; + static int down_skip[NR_CPUS]; + struct cpu_dbs_info_s *this_dbs_info; + + this_dbs_info = &per_cpu(cpu_dbs_info, cpu); + if (!this_dbs_info->enable) + return; + + /* + * The default safe range is 20% to 80% + * Every sampling_rate, we check + * - If current idle time is less than 20%, then we try to + * increase frequency + * Every sampling_rate*sampling_down_factor, we check + * - If current idle time is more than 80%, then we try to + * decrease frequency + * + * Any frequency increase takes it to the maximum frequency. + * Frequency reduction happens at minimum steps of + * 5% of max_frequency + */ + /* Check for frequency increase */ + idle_ticks = kstat_cpu(cpu).cpustat.idle - + this_dbs_info->prev_cpu_idle_up; + this_dbs_info->prev_cpu_idle_up = kstat_cpu(cpu).cpustat.idle; + + up_idle_ticks = (100 - dbs_tuners_ins.up_threshold) * + sampling_rate_in_HZ(dbs_tuners_ins.sampling_rate) / 100; + + if (idle_ticks < up_idle_ticks) { + __cpufreq_driver_target(this_dbs_info->cur_policy, + this_dbs_info->cur_policy->max, + CPUFREQ_RELATION_H); + down_skip[cpu] = 0; + this_dbs_info->prev_cpu_idle_down = kstat_cpu(cpu).cpustat.idle; + return; + } + + /* Check for frequency decrease */ + down_skip[cpu]++; + if (down_skip[cpu] < dbs_tuners_ins.sampling_down_factor) + return; + + idle_ticks = kstat_cpu(cpu).cpustat.idle - + this_dbs_info->prev_cpu_idle_down; + down_skip[cpu] = 0; + this_dbs_info->prev_cpu_idle_down = kstat_cpu(cpu).cpustat.idle; + + freq_down_sampling_rate = dbs_tuners_ins.sampling_rate * + dbs_tuners_ins.sampling_down_factor; + down_idle_ticks = (100 - dbs_tuners_ins.down_threshold) * + sampling_rate_in_HZ(freq_down_sampling_rate) / 100; + + if (idle_ticks > down_idle_ticks ) { + freq_down_step = (5 * this_dbs_info->cur_policy->max) / 100; + __cpufreq_driver_target(this_dbs_info->cur_policy, + this_dbs_info->cur_policy->cur - freq_down_step, + CPUFREQ_RELATION_H); + return; + } +} + +static void do_dbs_timer(void *data) +{ + int i; + down(&dbs_sem); + for (i = 0; i < NR_CPUS; i++) + if (cpu_online(i)) + dbs_check_cpu(i); + schedule_delayed_work(&dbs_work, + sampling_rate_in_HZ(dbs_tuners_ins.sampling_rate)); + up(&dbs_sem); +} + +static inline void dbs_timer_init(void) +{ + INIT_WORK(&dbs_work, do_dbs_timer, NULL); + schedule_work(&dbs_work); + return; +} + +static inline void dbs_timer_exit(void) +{ + cancel_delayed_work(&dbs_work); + return; +} + +static int cpufreq_governor_dbs(struct cpufreq_policy *policy, + unsigned int event) +{ + unsigned int cpu = policy->cpu; + struct cpu_dbs_info_s *this_dbs_info; + + this_dbs_info = &per_cpu(cpu_dbs_info, cpu); + + switch (event) { + case CPUFREQ_GOV_START: + if ((!cpu_online(cpu)) || + (!policy->cur)) + return -EINVAL; + + if (policy->cpuinfo.transition_latency > + (TRANSITION_LATENCY_LIMIT * 1000)) + return -EINVAL; + if (this_dbs_info->enable) /* Already enabled */ + break; + + down(&dbs_sem); + this_dbs_info->cur_policy = policy; + + this_dbs_info->prev_cpu_idle_up = + kstat_cpu(cpu).cpustat.idle; + this_dbs_info->prev_cpu_idle_down = + kstat_cpu(cpu).cpustat.idle; + this_dbs_info->enable = 1; + sysfs_create_group(&policy->kobj, &dbs_attr_group); + dbs_enable++; + /* + * Start the timerschedule work, when this governor + * is used for first time + */ + if (dbs_enable == 1) { + /* policy latency is in nS. Convert it to uS first */ + def_sampling_rate = (policy->cpuinfo.transition_latency / 1000) * + DEF_SAMPLING_RATE_LATENCY_MULTIPLIER; + dbs_tuners_ins.sampling_rate = def_sampling_rate; + + dbs_timer_init(); + } + + up(&dbs_sem); + break; + + case CPUFREQ_GOV_STOP: + down(&dbs_sem); + this_dbs_info->enable = 0; + sysfs_remove_group(&policy->kobj, &dbs_attr_group); + dbs_enable--; + /* + * Stop the timerschedule work, when this governor + * is used for first time + */ + if (dbs_enable == 0) + dbs_timer_exit(); + + up(&dbs_sem); + + break; + + case CPUFREQ_GOV_LIMITS: + down(&dbs_sem); + if (policy->max < this_dbs_info->cur_policy->cur) + __cpufreq_driver_target( + this_dbs_info->cur_policy, + policy->max, CPUFREQ_RELATION_H); + else if (policy->min > this_dbs_info->cur_policy->cur) + __cpufreq_driver_target( + this_dbs_info->cur_policy, + policy->min, CPUFREQ_RELATION_L); + up(&dbs_sem); + break; + } + return 0; +} + +struct cpufreq_governor cpufreq_gov_dbs = { + .name = "ondemand", + .governor = cpufreq_governor_dbs, + .owner = THIS_MODULE, +}; +EXPORT_SYMBOL(cpufreq_gov_dbs); + +static int __init cpufreq_gov_dbs_init(void) +{ + return cpufreq_register_governor(&cpufreq_gov_dbs); +} + +static void __exit cpufreq_gov_dbs_exit(void) +{ + /* Make sure that the scheduled work is indeed not running */ + flush_scheduled_work(); + + cpufreq_unregister_governor(&cpufreq_gov_dbs); +} + + +MODULE_AUTHOR ("Venkatesh Pallipadi "); +MODULE_DESCRIPTION ("'cpufreq_ondemand' - A dynamic cpufreq governor for " + "Low Latency Frequency Transition capable processors"); +MODULE_LICENSE ("GPL"); + +module_init(cpufreq_gov_dbs_init); +module_exit(cpufreq_gov_dbs_exit); diff -Nru a/drivers/i2c/chips/asb100.c b/drivers/i2c/chips/asb100.c --- a/drivers/i2c/chips/asb100.c 2004-08-25 22:01:55 -07:00 +++ b/drivers/i2c/chips/asb100.c 2004-08-25 22:01:55 -07:00 @@ -520,9 +520,9 @@ return sprintf(buf, "%d\n", vid_from_reg(data->vid, data->vrm)); } -static DEVICE_ATTR(in0_ref, S_IRUGO, show_vid, NULL); +static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL); #define device_create_file_vid(client) \ -device_create_file(&client->dev, &dev_attr_in0_ref) +device_create_file(&client->dev, &dev_attr_cpu0_vid) /* VRM */ static ssize_t show_vrm(struct device *dev, char *buf) diff -Nru a/drivers/i2c/chips/it87.c b/drivers/i2c/chips/it87.c --- a/drivers/i2c/chips/it87.c 2004-08-25 22:01:56 -07:00 +++ b/drivers/i2c/chips/it87.c 2004-08-25 22:01:56 -07:00 @@ -571,9 +571,9 @@ struct it87_data *data = it87_update_device(dev); return sprintf(buf, "%ld\n", (long) vid_from_reg(data->vid, data->vrm)); } -static DEVICE_ATTR(in0_ref, S_IRUGO, show_vid_reg, NULL); +static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid_reg, NULL); #define device_create_file_vid(client) \ -device_create_file(&client->dev, &dev_attr_in0_ref) +device_create_file(&client->dev, &dev_attr_cpu0_vid) /* This function is called when: * it87_driver is inserted (when this module is loaded), for each diff -Nru a/drivers/i2c/chips/lm78.c b/drivers/i2c/chips/lm78.c --- a/drivers/i2c/chips/lm78.c 2004-08-25 22:01:56 -07:00 +++ b/drivers/i2c/chips/lm78.c 2004-08-25 22:01:56 -07:00 @@ -423,7 +423,7 @@ struct lm78_data *data = lm78_update_device(dev); return sprintf(buf, "%d\n", VID_FROM_REG(data->vid)); } -static DEVICE_ATTR(in0_ref, S_IRUGO, show_vid, NULL); +static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL); /* Alarms */ static ssize_t show_alarms(struct device *dev, char *buf) @@ -615,7 +615,7 @@ device_create_file(&new_client->dev, &dev_attr_fan3_min); device_create_file(&new_client->dev, &dev_attr_fan3_div); device_create_file(&new_client->dev, &dev_attr_alarms); - device_create_file(&new_client->dev, &dev_attr_in0_ref); + device_create_file(&new_client->dev, &dev_attr_cpu0_vid); return 0; diff -Nru a/drivers/i2c/chips/lm85.c b/drivers/i2c/chips/lm85.c --- a/drivers/i2c/chips/lm85.c 2004-08-25 22:01:55 -07:00 +++ b/drivers/i2c/chips/lm85.c 2004-08-25 22:01:55 -07:00 @@ -465,7 +465,7 @@ return sprintf(buf, "%ld\n", (long) vid_from_reg(data->vid, data->vrm)); } -static DEVICE_ATTR(in0_ref, S_IRUGO, show_vid_reg, NULL); +static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid_reg, NULL); static ssize_t show_vrm_reg(struct device *dev, char *buf) { @@ -874,7 +874,7 @@ device_create_file(&new_client->dev, &dev_attr_temp2_max); device_create_file(&new_client->dev, &dev_attr_temp3_max); device_create_file(&new_client->dev, &dev_attr_vrm); - device_create_file(&new_client->dev, &dev_attr_in0_ref); + device_create_file(&new_client->dev, &dev_attr_cpu0_vid); device_create_file(&new_client->dev, &dev_attr_alarms); return 0; diff -Nru a/drivers/i2c/chips/w83627hf.c b/drivers/i2c/chips/w83627hf.c --- a/drivers/i2c/chips/w83627hf.c 2004-08-25 22:01:56 -07:00 +++ b/drivers/i2c/chips/w83627hf.c 2004-08-25 22:01:56 -07:00 @@ -635,9 +635,9 @@ struct w83627hf_data *data = w83627hf_update_device(dev); return sprintf(buf, "%ld\n", (long) vid_from_reg(data->vid, data->vrm)); } -static DEVICE_ATTR(in0_ref, S_IRUGO, show_vid_reg, NULL); +static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid_reg, NULL); #define device_create_file_vid(client) \ -device_create_file(&client->dev, &dev_attr_in0_ref) +device_create_file(&client->dev, &dev_attr_cpu0_vid) static ssize_t show_vrm_reg(struct device *dev, char *buf) diff -Nru a/drivers/i2c/chips/w83781d.c b/drivers/i2c/chips/w83781d.c --- a/drivers/i2c/chips/w83781d.c 2004-08-25 22:01:54 -07:00 +++ b/drivers/i2c/chips/w83781d.c 2004-08-25 22:01:54 -07:00 @@ -503,9 +503,9 @@ } static -DEVICE_ATTR(in0_ref, S_IRUGO, show_vid_reg, NULL); +DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid_reg, NULL); #define device_create_file_vid(client) \ -device_create_file(&client->dev, &dev_attr_in0_ref); +device_create_file(&client->dev, &dev_attr_cpu0_vid); static ssize_t show_vrm_reg(struct device *dev, char *buf) { diff -Nru a/drivers/input/serio/gscps2.c b/drivers/input/serio/gscps2.c --- a/drivers/input/serio/gscps2.c 2004-08-25 22:01:56 -07:00 +++ b/drivers/input/serio/gscps2.c 2004-08-25 22:01:56 -07:00 @@ -6,7 +6,7 @@ * Copyright (c) 2002 Thibaut Varene * * Pieces of code based on linux-2.4's hp_mouse.c & hp_keyb.c - * Copyright (c) 1999 Alex deVries + * Copyright (c) 1999 Alex deVries * Copyright (c) 1999-2000 Philipp Rumpf * Copyright (c) 2000 Xavier Debacker * Copyright (c) 2000-2001 Thomas Marteau diff -Nru a/drivers/isdn/hisax/avm_pci.c b/drivers/isdn/hisax/avm_pci.c --- a/drivers/isdn/hisax/avm_pci.c 2004-08-25 22:01:55 -07:00 +++ b/drivers/isdn/hisax/avm_pci.c 2004-08-25 22:01:55 -07:00 @@ -752,70 +752,70 @@ cs->hw.avm.cfg_reg = card->para[1]; cs->irq = card->para[0]; cs->subtyp = AVM_FRITZ_PNP; - } else { + goto ready; + } #ifdef __ISAPNP__ - if (isapnp_present()) { - struct pnp_dev *pnp_avm_d = NULL; - if ((pnp_avm_c = pnp_find_card( + if (isapnp_present()) { + struct pnp_dev *pnp_avm_d = NULL; + if ((pnp_avm_c = pnp_find_card( + ISAPNP_VENDOR('A', 'V', 'M'), + ISAPNP_FUNCTION(0x0900), pnp_avm_c))) { + if ((pnp_avm_d = pnp_find_dev(pnp_avm_c, ISAPNP_VENDOR('A', 'V', 'M'), - ISAPNP_FUNCTION(0x0900), pnp_avm_c))) { - if ((pnp_avm_d = pnp_find_dev(pnp_avm_c, - ISAPNP_VENDOR('A', 'V', 'M'), - ISAPNP_FUNCTION(0x0900), pnp_avm_d))) { - int err; + ISAPNP_FUNCTION(0x0900), pnp_avm_d))) { + int err; - pnp_disable_dev(pnp_avm_d); - err = pnp_activate_dev(pnp_avm_d); - if (err<0) { - printk(KERN_WARNING "%s: pnp_activate_dev ret(%d)\n", - __FUNCTION__, err); - return(0); - } - cs->hw.avm.cfg_reg = - pnp_port_start(pnp_avm_d, 0); - cs->irq = pnp_irq(pnp_avm_d, 0); - if (!cs->irq) { - printk(KERN_ERR "FritzPnP:No IRQ\n"); - return(0); - } - if (!cs->hw.avm.cfg_reg) { - printk(KERN_ERR "FritzPnP:No IO address\n"); - return(0); - } - cs->subtyp = AVM_FRITZ_PNP; - goto ready; + pnp_disable_dev(pnp_avm_d); + err = pnp_activate_dev(pnp_avm_d); + if (err<0) { + printk(KERN_WARNING "%s: pnp_activate_dev ret(%d)\n", + __FUNCTION__, err); + return(0); + } + cs->hw.avm.cfg_reg = + pnp_port_start(pnp_avm_d, 0); + cs->irq = pnp_irq(pnp_avm_d, 0); + if (!cs->irq) { + printk(KERN_ERR "FritzPnP:No IRQ\n"); + return(0); + } + if (!cs->hw.avm.cfg_reg) { + printk(KERN_ERR "FritzPnP:No IO address\n"); + return(0); } + cs->subtyp = AVM_FRITZ_PNP; + goto ready; } - } else { - printk(KERN_INFO "FritzPnP: no ISA PnP present\n"); } + } else { + printk(KERN_INFO "FritzPnP: no ISA PnP present\n"); + } #endif #ifdef CONFIG_PCI - if ((dev_avm = pci_find_device(PCI_VENDOR_ID_AVM, - PCI_DEVICE_ID_AVM_A1, dev_avm))) { - cs->irq = dev_avm->irq; - if (!cs->irq) { - printk(KERN_ERR "FritzPCI: No IRQ for PCI card found\n"); - return(0); - } - if (pci_enable_device(dev_avm)) - return(0); - cs->hw.avm.cfg_reg = pci_resource_start(dev_avm, 1); - if (!cs->hw.avm.cfg_reg) { - printk(KERN_ERR "FritzPCI: No IO-Adr for PCI card found\n"); - return(0); - } - cs->subtyp = AVM_FRITZ_PCI; - } else { - printk(KERN_WARNING "FritzPCI: No PCI card found\n"); + if ((dev_avm = pci_find_device(PCI_VENDOR_ID_AVM, + PCI_DEVICE_ID_AVM_A1, dev_avm))) { + cs->irq = dev_avm->irq; + if (!cs->irq) { + printk(KERN_ERR "FritzPCI: No IRQ for PCI card found\n"); + return(0); + } + if (pci_enable_device(dev_avm)) + return(0); + cs->hw.avm.cfg_reg = pci_resource_start(dev_avm, 1); + if (!cs->hw.avm.cfg_reg) { + printk(KERN_ERR "FritzPCI: No IO-Adr for PCI card found\n"); return(0); } - cs->irq_flags |= SA_SHIRQ; + cs->subtyp = AVM_FRITZ_PCI; + } else { + printk(KERN_WARNING "FritzPCI: No PCI card found\n"); + return(0); + } + cs->irq_flags |= SA_SHIRQ; #else - printk(KERN_WARNING "FritzPCI: NO_PCI_BIOS\n"); - return (0); + printk(KERN_WARNING "FritzPCI: NO_PCI_BIOS\n"); + return (0); #endif /* CONFIG_PCI */ - } ready: cs->hw.avm.isac = cs->hw.avm.cfg_reg + 0x10; if (!request_region(cs->hw.avm.cfg_reg, 32, diff -Nru a/drivers/isdn/tpam/tpam_main.c b/drivers/isdn/tpam/tpam_main.c --- a/drivers/isdn/tpam/tpam_main.c 2004-08-25 22:01:56 -07:00 +++ b/drivers/isdn/tpam/tpam_main.c 2004-08-25 22:01:56 -07:00 @@ -23,7 +23,7 @@ /* Local functions prototypes */ static int __devinit tpam_probe(struct pci_dev *, const struct pci_device_id *); -static void __devexit tpam_unregister_card(tpam_card *); +static void __devexit tpam_unregister_card(struct pci_dev *, tpam_card *); static void __devexit tpam_remove(struct pci_dev *); static int __init tpam_init(void); static void __exit tpam_exit(void); @@ -86,13 +86,20 @@ */ static int __devinit tpam_probe(struct pci_dev *dev, const struct pci_device_id *pci_id) { tpam_card *card, *c; - int i; + int i, err; + + if (pci_enable_device(dev)) { + printk(KERN_ERR "TurboPAM: can't enable PCI device at %s\n", + pci_name(dev)); + return -ENODEV; + } /* allocate memory for the board structure */ if (!(card = (tpam_card *)kmalloc(sizeof(tpam_card), GFP_KERNEL))) { printk(KERN_ERR "TurboPAM: tpam_register_card: " "kmalloc failed!\n"); - return -ENOMEM; + err = -ENOMEM; + goto err_out_disable_dev; } memset((char *)card, 0, sizeof(tpam_card)); @@ -106,8 +113,8 @@ card->interface.id, card)) { printk(KERN_ERR "TurboPAM: tpam_register_card: " "could not request irq %d\n", card->irq); - kfree(card); - return -EIO; + err = -EIO; + goto err_out_free_card; } /* remap board memory */ @@ -115,9 +122,8 @@ 0x800000))) { printk(KERN_ERR "TurboPAM: tpam_register_card: " "unable to remap bar0\n"); - free_irq(card->irq, card); - kfree(card); - return -EIO; + err = -EIO; + goto err_out_free_irq; } /* reset the board */ @@ -150,10 +156,8 @@ if (!register_isdn(&card->interface)) { printk(KERN_ERR "TurboPAM: tpam_register_card: " "unable to register %s\n", card->interface.id); - free_irq(card->irq, card); - iounmap((void *)card->bar0); - kfree(card); - return -EIO; + err = -EIO; + goto err_out_iounmap; } card->id = card->interface.channels; @@ -195,6 +199,19 @@ pci_set_drvdata(dev, card); return 0; + +err_out_iounmap: + iounmap((void *)card->bar0); + +err_out_free_irq: + free_irq(card->irq, card); + +err_out_free_card: + kfree(card); + +err_out_disable_dev: + pci_disable_device(dev); + return err; } /* @@ -202,7 +219,7 @@ * * card: the board. */ -static void __devexit tpam_unregister_card(tpam_card *card) { +static void __devexit tpam_unregister_card(struct pci_dev *pcidev, tpam_card *card) { isdn_ctrl cmd; /* prevent the ISDN link layer that the driver will be unloaded */ @@ -215,6 +232,8 @@ /* release mapped memory */ iounmap((void *)card->bar0); + + pci_disable_device(pcidev); } /* @@ -235,7 +254,7 @@ } /* unregister each board */ - tpam_unregister_card(card); + tpam_unregister_card(pcidev, card); /* and free the board structure itself */ kfree(card); diff -Nru a/drivers/md/Kconfig b/drivers/md/Kconfig --- a/drivers/md/Kconfig 2004-08-25 22:01:54 -07:00 +++ b/drivers/md/Kconfig 2004-08-25 22:01:54 -07:00 @@ -85,6 +85,24 @@ If unsure, say Y. +config MD_RAID10 + tristate "RAID-10 (mirrored striping) mode (EXPERIMENTAL)" + depends on BLK_DEV_MD && EXPERIMENTAL + ---help--- + RAID-10 provides a combination of striping (RAID-0) and + mirroring (RAID-1) with easier configuration and more flexable + layout. + Unlike RAID-0, but like RAID-1, RAID-10 requires all devices to + be the same size (or atleast, only as much as the smallest device + will be used). + RAID-10 provides a variety of layouts that provide different levels + of redundancy and performance. + + RAID-10 requires mdadm-1.7.0 or later, available at: + + ftp://ftp.kernel.org/pub/linux/utils/raid/mdadm/ + + config MD_RAID5 tristate "RAID-4/RAID-5 mode" depends on BLK_DEV_MD diff -Nru a/drivers/md/Makefile b/drivers/md/Makefile --- a/drivers/md/Makefile 2004-08-25 22:01:55 -07:00 +++ b/drivers/md/Makefile 2004-08-25 22:01:55 -07:00 @@ -20,6 +20,7 @@ obj-$(CONFIG_MD_LINEAR) += linear.o obj-$(CONFIG_MD_RAID0) += raid0.o obj-$(CONFIG_MD_RAID1) += raid1.o +obj-$(CONFIG_MD_RAID10) += raid10.o obj-$(CONFIG_MD_RAID5) += raid5.o xor.o obj-$(CONFIG_MD_RAID6) += raid6.o xor.o obj-$(CONFIG_MD_MULTIPATH) += multipath.o diff -Nru a/drivers/md/md.c b/drivers/md/md.c --- a/drivers/md/md.c 2004-08-25 22:01:55 -07:00 +++ b/drivers/md/md.c 2004-08-25 22:01:55 -07:00 @@ -406,7 +406,7 @@ return 0; fail: - printk(KERN_ERR "md: disabled device %s, could not read superblock.\n", + printk(KERN_WARNING "md: disabled device %s, could not read superblock.\n", bdevname(rdev->bdev,b)); return -EINVAL; } @@ -1075,20 +1075,24 @@ /* * prevent the device from being mounted, repartitioned or * otherwise reused by a RAID array (or any other kernel - * subsystem), by opening the device. [simply getting an - * inode is not enough, the SCSI module usage code needs - * an explicit open() on the device] + * subsystem), by bd_claiming the device. */ static int lock_rdev(mdk_rdev_t *rdev, dev_t dev) { int err = 0; struct block_device *bdev; + char b[BDEVNAME_SIZE]; bdev = open_by_devnum(dev, FMODE_READ|FMODE_WRITE); - if (IS_ERR(bdev)) + if (IS_ERR(bdev)) { + printk(KERN_ERR "md: could not open %s.\n", + __bdevname(dev, b)); return PTR_ERR(bdev); + } err = bd_claim(bdev, rdev); if (err) { + printk(KERN_ERR "md: could not bd_claim %s.\n", + bdevname(bdev, b)); blkdev_put(bdev); return err; } @@ -1150,10 +1154,7 @@ static void print_desc(mdp_disk_t *desc) { - char b[BDEVNAME_SIZE]; - - printk(" DISK\n", desc->number, - __bdevname(MKDEV(desc->major, desc->minor), b), + printk(" DISK\n", desc->number, desc->major,desc->minor,desc->raid_disk,desc->state); } @@ -1345,8 +1346,7 @@ rdev = (mdk_rdev_t *) kmalloc(sizeof(*rdev), GFP_KERNEL); if (!rdev) { - printk(KERN_ERR "md: could not alloc mem for %s!\n", - __bdevname(newdev, b)); + printk(KERN_ERR "md: could not alloc mem for new device!\n"); return ERR_PTR(-ENOMEM); } memset(rdev, 0, sizeof(*rdev)); @@ -1355,11 +1355,9 @@ goto abort_free; err = lock_rdev(rdev, newdev); - if (err) { - printk(KERN_ERR "md: could not lock %s.\n", - __bdevname(newdev, b)); + if (err) goto abort_free; - } + rdev->desc_nr = -1; rdev->faulty = 0; rdev->in_sync = 0; @@ -1648,6 +1646,8 @@ mddev->pers = pers[pnum]; spin_unlock(&pers_lock); + mddev->resync_max_sectors = mddev->size << 1; /* may be over-ridden by personality */ + err = mddev->pers->run(mddev); if (err) { printk(KERN_ERR "md: pers->run() failed ...\n"); @@ -1915,11 +1915,9 @@ mdk_rdev_t *start_rdev = NULL, *rdev; start_rdev = md_import_device(startdev, 0, 0); - if (IS_ERR(start_rdev)) { - printk(KERN_WARNING "md: could not import %s!\n", - __bdevname(startdev, b)); + if (IS_ERR(start_rdev)) return err; - } + /* NOTE: this can only work for 0.90.0 superblocks */ sb = (mdp_super_t*)page_address(start_rdev->sb_page); @@ -1950,12 +1948,9 @@ if (MAJOR(dev) != desc->major || MINOR(dev) != desc->minor) continue; rdev = md_import_device(dev, 0, 0); - if (IS_ERR(rdev)) { - printk(KERN_WARNING "md: could not import %s," - " trying to run array nevertheless.\n", - __bdevname(dev, b)); + if (IS_ERR(rdev)) continue; - } + list_add(&rdev->same_set, &pending_raid_disks); } @@ -2187,42 +2182,6 @@ return 0; } -static int hot_generate_error(mddev_t * mddev, dev_t dev) -{ - char b[BDEVNAME_SIZE]; - struct request_queue *q; - mdk_rdev_t *rdev; - - if (!mddev->pers) - return -ENODEV; - - printk(KERN_INFO "md: trying to generate %s error in %s ... \n", - __bdevname(dev, b), mdname(mddev)); - - rdev = find_rdev(mddev, dev); - if (!rdev) { - /* MD_BUG(); */ /* like hell - it's not a driver bug */ - return -ENXIO; - } - - if (rdev->desc_nr == -1) { - MD_BUG(); - return -EINVAL; - } - if (!rdev->in_sync) - return -ENODEV; - - q = bdev_get_queue(rdev->bdev); - if (!q) { - MD_BUG(); - return -ENODEV; - } - printk(KERN_INFO "md: okay, generating error!\n"); -// q->oneshot_error = 1; // disabled for now - - return 0; -} - static int hot_remove_disk(mddev_t * mddev, dev_t dev) { char b[BDEVNAME_SIZE]; @@ -2231,9 +2190,6 @@ if (!mddev->pers) return -ENODEV; - printk(KERN_INFO "md: trying to remove %s from %s ... \n", - __bdevname(dev, b), mdname(mddev)); - rdev = find_rdev(mddev, dev); if (!rdev) return -ENXIO; @@ -2261,9 +2217,6 @@ if (!mddev->pers) return -ENODEV; - printk(KERN_INFO "md: trying to hot-add %s to %s ... \n", - __bdevname(dev, b), mdname(mddev)); - if (mddev->major_version != 0) { printk(KERN_WARNING "%s: HOT_ADD may only be used with" " version-0 superblocks.\n", @@ -2523,7 +2476,6 @@ static int md_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { - char b[BDEVNAME_SIZE]; int err = 0; void __user *argp = (void __user *)arg; struct hd_geometry __user *loc = argp; @@ -2582,8 +2534,7 @@ } err = autostart_array(new_decode_dev(arg)); if (err) { - printk(KERN_WARNING "md: autostart %s failed!\n", - __bdevname(arg, b)); + printk(KERN_WARNING "md: autostart failed!\n"); goto abort; } goto done; @@ -2724,9 +2675,7 @@ err = add_new_disk(mddev, &info); goto done_unlock; } - case HOT_GENERATE_ERROR: - err = hot_generate_error(mddev, new_decode_dev(arg)); - goto done_unlock; + case HOT_REMOVE_DISK: err = hot_remove_disk(mddev, new_decode_dev(arg)); goto done_unlock; @@ -2953,6 +2902,7 @@ if (!mddev->pers->error_handler) return; mddev->pers->error_handler(mddev,rdev); + set_bit(MD_RECOVERY_INTR, &mddev->recovery); set_bit(MD_RECOVERY_NEEDED, &mddev->recovery); md_wakeup_thread(mddev->thread); } @@ -2985,7 +2935,11 @@ unsigned long max_blocks, resync, res, dt, db, rt; resync = (mddev->curr_resync - atomic_read(&mddev->recovery_active))/2; - max_blocks = mddev->size; + + if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery)) + max_blocks = mddev->resync_max_sectors >> 1; + else + max_blocks = mddev->size; /* * Should not happen. @@ -3221,11 +3175,6 @@ return 0; } -void md_sync_acct(mdk_rdev_t *rdev, unsigned long nr_sectors) -{ - rdev->bdev->bd_contains->bd_disk->sync_io += nr_sectors; -} - static int is_mddev_idle(mddev_t *mddev) { mdk_rdev_t * rdev; @@ -3238,8 +3187,12 @@ struct gendisk *disk = rdev->bdev->bd_contains->bd_disk; curr_events = disk_stat_read(disk, read_sectors) + disk_stat_read(disk, write_sectors) - - disk->sync_io; - if ((curr_events - rdev->last_events) > 32) { + atomic_read(&disk->sync_io); + /* Allow some slack between valud of curr_events and last_events, + * as there are some uninteresting races. + * Note: the following is an unsigned comparison. + */ + if ((curr_events - rdev->last_events + 32) > 64) { rdev->last_events = curr_events; idle = 0; } @@ -3373,7 +3326,14 @@ } } while (mddev->curr_resync < 2); - max_sectors = mddev->size << 1; + if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery)) + /* resync follows the size requested by the personality, + * which default to physical size, but can be virtual size + */ + max_sectors = mddev->resync_max_sectors; + else + /* recovery follows the physical size of devices */ + max_sectors = mddev->size << 1; printk(KERN_INFO "md: syncing RAID array %s\n", mdname(mddev)); printk(KERN_INFO "md: minimum _guaranteed_ reconstruction speed:" @@ -3731,7 +3691,6 @@ static void autostart_arrays(int part) { - char b[BDEVNAME_SIZE]; mdk_rdev_t *rdev; int i; @@ -3741,11 +3700,9 @@ dev_t dev = detected_devices[i]; rdev = md_import_device(dev,0, 0); - if (IS_ERR(rdev)) { - printk(KERN_ALERT "md: could not import %s!\n", - __bdevname(dev, b)); + if (IS_ERR(rdev)) continue; - } + if (rdev->faulty) { MD_BUG(); continue; @@ -3796,7 +3753,6 @@ EXPORT_SYMBOL(register_md_personality); EXPORT_SYMBOL(unregister_md_personality); EXPORT_SYMBOL(md_error); -EXPORT_SYMBOL(md_sync_acct); EXPORT_SYMBOL(md_done_sync); EXPORT_SYMBOL(md_write_start); EXPORT_SYMBOL(md_write_end); diff -Nru a/drivers/md/raid1.c b/drivers/md/raid1.c --- a/drivers/md/raid1.c 2004-08-25 22:01:55 -07:00 +++ b/drivers/md/raid1.c 2004-08-25 22:01:55 -07:00 @@ -24,10 +24,6 @@ #include -#define MAJOR_NR MD_MAJOR -#define MD_DRIVER -#define MD_PERSONALITY - /* * Number of guaranteed r1bios in case of extreme VM load: */ @@ -44,13 +40,12 @@ { struct pool_info *pi = data; r1bio_t *r1_bio; + int size = offsetof(r1bio_t, bios[pi->raid_disks]); /* allocate a r1bio with room for raid_disks entries in the bios array */ - r1_bio = kmalloc(sizeof(r1bio_t) + sizeof(struct bio*)*pi->raid_disks, - gfp_flags); + r1_bio = kmalloc(size, gfp_flags); if (r1_bio) - memset(r1_bio, 0, sizeof(*r1_bio) + - sizeof(struct bio*) * pi->raid_disks); + memset(r1_bio, 0, size); else unplug_slaves(pi->mddev); @@ -104,7 +99,7 @@ bio->bi_io_vec[i].bv_page = page; } - r1_bio->master_bio = bio; + r1_bio->master_bio = NULL; return r1_bio; @@ -189,32 +184,6 @@ spin_unlock_irqrestore(&conf->resync_lock, flags); } -static int map(mddev_t *mddev, mdk_rdev_t **rdevp) -{ - conf_t *conf = mddev_to_conf(mddev); - int i, disks = conf->raid_disks; - - /* - * Later we do read balancing on the read side - * now we use the first available disk. - */ - - spin_lock_irq(&conf->device_lock); - for (i = 0; i < disks; i++) { - mdk_rdev_t *rdev = conf->mirrors[i].rdev; - if (rdev && rdev->in_sync) { - *rdevp = rdev; - atomic_inc(&rdev->nr_pending); - spin_unlock_irq(&conf->device_lock); - return i; - } - } - spin_unlock_irq(&conf->device_lock); - - printk(KERN_ERR "raid1_map(): huh, no more operational devices?\n"); - return -1; -} - static void reschedule_retry(r1bio_t *r1_bio) { unsigned long flags; @@ -292,8 +261,9 @@ * oops, read error: */ char b[BDEVNAME_SIZE]; - printk(KERN_ERR "raid1: %s: rescheduling sector %llu\n", - bdevname(conf->mirrors[mirror].rdev->bdev,b), (unsigned long long)r1_bio->sector); + if (printk_ratelimit()) + printk(KERN_ERR "raid1: %s: rescheduling sector %llu\n", + bdevname(conf->mirrors[mirror].rdev->bdev,b), (unsigned long long)r1_bio->sector); reschedule_retry(r1_bio); } @@ -363,11 +333,11 @@ * * The rdev for the device selected will have nr_pending incremented. */ -static int read_balance(conf_t *conf, struct bio *bio, r1bio_t *r1_bio) +static int read_balance(conf_t *conf, r1bio_t *r1_bio) { const unsigned long this_sector = r1_bio->sector; int new_disk = conf->last_used, disk = new_disk; - const int sectors = bio->bi_size >> 9; + const int sectors = r1_bio->sectors; sector_t new_distance, current_distance; spin_lock_irq(&conf->device_lock); @@ -378,14 +348,14 @@ */ if (conf->mddev->recovery_cp < MaxSector && (this_sector + sectors >= conf->next_resync)) { - /* make sure that disk is operational */ + /* Choose the first operation device, for consistancy */ new_disk = 0; while (!conf->mirrors[new_disk].rdev || !conf->mirrors[new_disk].rdev->in_sync) { new_disk++; if (new_disk == conf->raid_disks) { - new_disk = 0; + new_disk = -1; break; } } @@ -400,7 +370,7 @@ new_disk = conf->raid_disks; new_disk--; if (new_disk == disk) { - new_disk = conf->last_used; + new_disk = -1; goto rb_out; } } @@ -440,13 +410,13 @@ } while (disk != conf->last_used); rb_out: - r1_bio->read_disk = new_disk; - conf->next_seq_sect = this_sector + sectors; - conf->last_used = new_disk; - if (conf->mirrors[new_disk].rdev) + if (new_disk >= 0) { + conf->next_seq_sect = this_sector + sectors; + conf->last_used = new_disk; atomic_inc(&conf->mirrors[new_disk].rdev->nr_pending); + } spin_unlock_irq(&conf->device_lock); return new_disk; @@ -571,15 +541,26 @@ r1_bio->mddev = mddev; r1_bio->sector = bio->bi_sector; + r1_bio->state = 0; + if (bio_data_dir(bio) == READ) { /* * read balancing logic: */ - mirror = conf->mirrors + read_balance(conf, bio, r1_bio); + int rdisk = read_balance(conf, r1_bio); + + if (rdisk < 0) { + /* couldn't find anywhere to read from */ + raid_end_bio_io(r1_bio); + return 0; + } + mirror = conf->mirrors + rdisk; + + r1_bio->read_disk = rdisk; read_bio = bio_clone(bio, GFP_NOIO); - r1_bio->bios[r1_bio->read_disk] = read_bio; + r1_bio->bios[rdisk] = read_bio; read_bio->bi_sector = r1_bio->sector + mirror->rdev->data_offset; read_bio->bi_bdev = mirror->rdev->bdev; @@ -903,7 +884,7 @@ atomic_inc(&conf->mirrors[i].rdev->nr_pending); atomic_inc(&r1_bio->remaining); - md_sync_acct(conf->mirrors[i].rdev, wbio->bi_size >> 9); + md_sync_acct(conf->mirrors[i].rdev->bdev, wbio->bi_size >> 9); generic_make_request(wbio); } @@ -951,7 +932,7 @@ } else { int disk; bio = r1_bio->bios[r1_bio->read_disk]; - if ((disk=map(mddev, &rdev)) == -1) { + if ((disk=read_balance(conf, r1_bio)) == -1) { printk(KERN_ALERT "raid1: %s: unrecoverable I/O" " read error for block %llu\n", bdevname(bio->bi_bdev,b), @@ -961,10 +942,12 @@ r1_bio->bios[r1_bio->read_disk] = NULL; r1_bio->read_disk = disk; r1_bio->bios[r1_bio->read_disk] = bio; - printk(KERN_ERR "raid1: %s: redirecting sector %llu to" - " another mirror\n", - bdevname(rdev->bdev,b), - (unsigned long long)r1_bio->sector); + rdev = conf->mirrors[disk].rdev; + if (printk_ratelimit()) + printk(KERN_ERR "raid1: %s: redirecting sector %llu to" + " another mirror\n", + bdevname(rdev->bdev,b), + (unsigned long long)r1_bio->sector); bio->bi_bdev = rdev->bdev; bio->bi_sector = r1_bio->sector + rdev->data_offset; bio->bi_rw = READ; @@ -1143,7 +1126,7 @@ bio = r1_bio->bios[disk]; r1_bio->sectors = nr_sectors; - md_sync_acct(mirror->rdev, nr_sectors); + md_sync_acct(mirror->rdev->bdev, nr_sectors); generic_make_request(bio); diff -Nru a/drivers/md/raid10.c b/drivers/md/raid10.c --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/drivers/md/raid10.c 2004-08-25 22:01:56 -07:00 @@ -0,0 +1,1780 @@ +/* + * raid10.c : Multiple Devices driver for Linux + * + * Copyright (C) 2000-2004 Neil Brown + * + * RAID-10 support for md. + * + * Base on code in raid1.c. See raid1.c for futher copyright information. + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * You should have received a copy of the GNU General Public License + * (for example /usr/src/linux/COPYING); if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include + +/* + * RAID10 provides a combination of RAID0 and RAID1 functionality. + * The layout of data is defined by + * chunk_size + * raid_disks + * near_copies (stored in low byte of layout) + * far_copies (stored in second byte of layout) + * + * The data to be stored is divided into chunks using chunksize. + * Each device is divided into far_copies sections. + * In each section, chunks are laid out in a style similar to raid0, but + * near_copies copies of each chunk is stored (each on a different drive). + * The starting device for each section is offset near_copies from the starting + * device of the previous section. + * Thus there are (near_copies*far_copies) of each chunk, and each is on a different + * drive. + * near_copies and far_copies must be at least one, and there product is at most + * raid_disks. + */ + +/* + * Number of guaranteed r10bios in case of extreme VM load: + */ +#define NR_RAID10_BIOS 256 + +static void unplug_slaves(mddev_t *mddev); + +static void * r10bio_pool_alloc(int gfp_flags, void *data) +{ + conf_t *conf = data; + r10bio_t *r10_bio; + int size = offsetof(struct r10bio_s, devs[conf->copies]); + + /* allocate a r10bio with room for raid_disks entries in the bios array */ + r10_bio = kmalloc(size, gfp_flags); + if (r10_bio) + memset(r10_bio, 0, size); + else + unplug_slaves(conf->mddev); + + return r10_bio; +} + +static void r10bio_pool_free(void *r10_bio, void *data) +{ + kfree(r10_bio); +} + +#define RESYNC_BLOCK_SIZE (64*1024) +//#define RESYNC_BLOCK_SIZE PAGE_SIZE +#define RESYNC_SECTORS (RESYNC_BLOCK_SIZE >> 9) +#define RESYNC_PAGES ((RESYNC_BLOCK_SIZE + PAGE_SIZE-1) / PAGE_SIZE) +#define RESYNC_WINDOW (2048*1024) + +/* + * When performing a resync, we need to read and compare, so + * we need as many pages are there are copies. + * When performing a recovery, we need 2 bios, one for read, + * one for write (we recover only one drive per r10buf) + * + */ +static void * r10buf_pool_alloc(int gfp_flags, void *data) +{ + conf_t *conf = data; + struct page *page; + r10bio_t *r10_bio; + struct bio *bio; + int i, j; + int nalloc; + + r10_bio = r10bio_pool_alloc(gfp_flags, conf); + if (!r10_bio) { + unplug_slaves(conf->mddev); + return NULL; + } + + if (test_bit(MD_RECOVERY_SYNC, &conf->mddev->recovery)) + nalloc = conf->copies; /* resync */ + else + nalloc = 2; /* recovery */ + + /* + * Allocate bios. + */ + for (j = nalloc ; j-- ; ) { + bio = bio_alloc(gfp_flags, RESYNC_PAGES); + if (!bio) + goto out_free_bio; + r10_bio->devs[j].bio = bio; + } + /* + * Allocate RESYNC_PAGES data pages and attach them + * where needed. + */ + for (j = 0 ; j < nalloc; j++) { + bio = r10_bio->devs[j].bio; + for (i = 0; i < RESYNC_PAGES; i++) { + page = alloc_page(gfp_flags); + if (unlikely(!page)) + goto out_free_pages; + + bio->bi_io_vec[i].bv_page = page; + } + } + + return r10_bio; + +out_free_pages: + for ( ; i > 0 ; i--) + __free_page(bio->bi_io_vec[i-1].bv_page); + while (j--) + for (i = 0; i < RESYNC_PAGES ; i++) + __free_page(r10_bio->devs[j].bio->bi_io_vec[i].bv_page); + j = -1; +out_free_bio: + while ( ++j < nalloc ) + bio_put(r10_bio->devs[j].bio); + r10bio_pool_free(r10_bio, conf); + return NULL; +} + +static void r10buf_pool_free(void *__r10_bio, void *data) +{ + int i; + conf_t *conf = data; + r10bio_t *r10bio = __r10_bio; + int j; + + for (j=0; j < conf->copies; j++) { + struct bio *bio = r10bio->devs[j].bio; + if (bio) { + for (i = 0; i < RESYNC_PAGES; i++) { + __free_page(bio->bi_io_vec[i].bv_page); + bio->bi_io_vec[i].bv_page = NULL; + } + bio_put(bio); + } + } + r10bio_pool_free(r10bio, conf); +} + +static void put_all_bios(conf_t *conf, r10bio_t *r10_bio) +{ + int i; + + for (i = 0; i < conf->copies; i++) { + struct bio **bio = & r10_bio->devs[i].bio; + if (*bio) + bio_put(*bio); + *bio = NULL; + } +} + +static inline void free_r10bio(r10bio_t *r10_bio) +{ + unsigned long flags; + + conf_t *conf = mddev_to_conf(r10_bio->mddev); + + /* + * Wake up any possible resync thread that waits for the device + * to go idle. + */ + spin_lock_irqsave(&conf->resync_lock, flags); + if (!--conf->nr_pending) { + wake_up(&conf->wait_idle); + wake_up(&conf->wait_resume); + } + spin_unlock_irqrestore(&conf->resync_lock, flags); + + put_all_bios(conf, r10_bio); + mempool_free(r10_bio, conf->r10bio_pool); +} + +static inline void put_buf(r10bio_t *r10_bio) +{ + conf_t *conf = mddev_to_conf(r10_bio->mddev); + unsigned long flags; + + mempool_free(r10_bio, conf->r10buf_pool); + + spin_lock_irqsave(&conf->resync_lock, flags); + if (!conf->barrier) + BUG(); + --conf->barrier; + wake_up(&conf->wait_resume); + wake_up(&conf->wait_idle); + + if (!--conf->nr_pending) { + wake_up(&conf->wait_idle); + wake_up(&conf->wait_resume); + } + spin_unlock_irqrestore(&conf->resync_lock, flags); +} + +static void reschedule_retry(r10bio_t *r10_bio) +{ + unsigned long flags; + mddev_t *mddev = r10_bio->mddev; + conf_t *conf = mddev_to_conf(mddev); + + spin_lock_irqsave(&conf->device_lock, flags); + list_add(&r10_bio->retry_list, &conf->retry_list); + spin_unlock_irqrestore(&conf->device_lock, flags); + + md_wakeup_thread(mddev->thread); +} + +/* + * raid_end_bio_io() is called when we have finished servicing a mirrored + * operation and are ready to return a success/failure code to the buffer + * cache layer. + */ +static void raid_end_bio_io(r10bio_t *r10_bio) +{ + struct bio *bio = r10_bio->master_bio; + + bio_endio(bio, bio->bi_size, + test_bit(R10BIO_Uptodate, &r10_bio->state) ? 0 : -EIO); + free_r10bio(r10_bio); +} + +/* + * Update disk head position estimator based on IRQ completion info. + */ +static inline void update_head_pos(int slot, r10bio_t *r10_bio) +{ + conf_t *conf = mddev_to_conf(r10_bio->mddev); + + conf->mirrors[r10_bio->devs[slot].devnum].head_position = + r10_bio->devs[slot].addr + (r10_bio->sectors); +} + +static int raid10_end_read_request(struct bio *bio, unsigned int bytes_done, int error) +{ + int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags); + r10bio_t * r10_bio = (r10bio_t *)(bio->bi_private); + int slot, dev; + conf_t *conf = mddev_to_conf(r10_bio->mddev); + + if (bio->bi_size) + return 1; + + slot = r10_bio->read_slot; + dev = r10_bio->devs[slot].devnum; + /* + * this branch is our 'one mirror IO has finished' event handler: + */ + if (!uptodate) + md_error(r10_bio->mddev, conf->mirrors[dev].rdev); + else + /* + * Set R10BIO_Uptodate in our master bio, so that + * we will return a good error code to the higher + * levels even if IO on some other mirrored buffer fails. + * + * The 'master' represents the composite IO operation to + * user-side. So if something waits for IO, then it will + * wait for the 'master' bio. + */ + set_bit(R10BIO_Uptodate, &r10_bio->state); + + update_head_pos(slot, r10_bio); + + /* + * we have only one bio on the read side + */ + if (uptodate) + raid_end_bio_io(r10_bio); + else { + /* + * oops, read error: + */ + char b[BDEVNAME_SIZE]; + if (printk_ratelimit()) + printk(KERN_ERR "raid10: %s: rescheduling sector %llu\n", + bdevname(conf->mirrors[dev].rdev->bdev,b), (unsigned long long)r10_bio->sector); + reschedule_retry(r10_bio); + } + + rdev_dec_pending(conf->mirrors[dev].rdev, conf->mddev); + return 0; +} + +static int raid10_end_write_request(struct bio *bio, unsigned int bytes_done, int error) +{ + int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags); + r10bio_t * r10_bio = (r10bio_t *)(bio->bi_private); + int slot, dev; + conf_t *conf = mddev_to_conf(r10_bio->mddev); + + if (bio->bi_size) + return 1; + + for (slot = 0; slot < conf->copies; slot++) + if (r10_bio->devs[slot].bio == bio) + break; + dev = r10_bio->devs[slot].devnum; + + /* + * this branch is our 'one mirror IO has finished' event handler: + */ + if (!uptodate) + md_error(r10_bio->mddev, conf->mirrors[dev].rdev); + else + /* + * Set R10BIO_Uptodate in our master bio, so that + * we will return a good error code for to the higher + * levels even if IO on some other mirrored buffer fails. + * + * The 'master' represents the composite IO operation to + * user-side. So if something waits for IO, then it will + * wait for the 'master' bio. + */ + set_bit(R10BIO_Uptodate, &r10_bio->state); + + update_head_pos(slot, r10_bio); + + /* + * + * Let's see if all mirrored write operations have finished + * already. + */ + if (atomic_dec_and_test(&r10_bio->remaining)) { + md_write_end(r10_bio->mddev); + raid_end_bio_io(r10_bio); + } + + rdev_dec_pending(conf->mirrors[dev].rdev, conf->mddev); + return 0; +} + + +/* + * RAID10 layout manager + * Aswell as the chunksize and raid_disks count, there are two + * parameters: near_copies and far_copies. + * near_copies * far_copies must be <= raid_disks. + * Normally one of these will be 1. + * If both are 1, we get raid0. + * If near_copies == raid_disks, we get raid1. + * + * Chunks are layed out in raid0 style with near_copies copies of the + * first chunk, followed by near_copies copies of the next chunk and + * so on. + * If far_copies > 1, then after 1/far_copies of the array has been assigned + * as described above, we start again with a device offset of near_copies. + * So we effectively have another copy of the whole array further down all + * the drives, but with blocks on different drives. + * With this layout, and block is never stored twice on the one device. + * + * raid10_find_phys finds the sector offset of a given virtual sector + * on each device that it is on. If a block isn't on a device, + * that entry in the array is set to MaxSector. + * + * raid10_find_virt does the reverse mapping, from a device and a + * sector offset to a virtual address + */ + +static void raid10_find_phys(conf_t *conf, r10bio_t *r10bio) +{ + int n,f; + sector_t sector; + sector_t chunk; + sector_t stripe; + int dev; + + int slot = 0; + + /* now calculate first sector/dev */ + chunk = r10bio->sector >> conf->chunk_shift; + sector = r10bio->sector & conf->chunk_mask; + + chunk *= conf->near_copies; + stripe = chunk; + dev = sector_div(stripe, conf->raid_disks); + + sector += stripe << conf->chunk_shift; + + /* and calculate all the others */ + for (n=0; n < conf->near_copies; n++) { + int d = dev; + sector_t s = sector; + r10bio->devs[slot].addr = sector; + r10bio->devs[slot].devnum = d; + slot++; + + for (f = 1; f < conf->far_copies; f++) { + d += conf->near_copies; + if (d >= conf->raid_disks) + d -= conf->raid_disks; + s += conf->stride; + r10bio->devs[slot].devnum = d; + r10bio->devs[slot].addr = s; + slot++; + } + dev++; + if (dev >= conf->raid_disks) { + dev = 0; + sector += (conf->chunk_mask + 1); + } + } + BUG_ON(slot != conf->copies); +} + +static sector_t raid10_find_virt(conf_t *conf, sector_t sector, int dev) +{ + sector_t offset, chunk, vchunk; + + while (sector > conf->stride) { + sector -= conf->stride; + if (dev < conf->near_copies) + dev += conf->raid_disks - conf->near_copies; + else + dev -= conf->near_copies; + } + + offset = sector & conf->chunk_mask; + chunk = sector >> conf->chunk_shift; + vchunk = chunk * conf->raid_disks + dev; + sector_div(vchunk, conf->near_copies); + return (vchunk << conf->chunk_shift) + offset; +} + +/** + * raid10_mergeable_bvec -- tell bio layer if a two requests can be merged + * @q: request queue + * @bio: the buffer head that's been built up so far + * @biovec: the request that could be merged to it. + * + * Return amount of bytes we can accept at this offset + * If near_copies == raid_disk, there are no striping issues, + * but in that case, the function isn't called at all. + */ +static int raid10_mergeable_bvec(request_queue_t *q, struct bio *bio, + struct bio_vec *bio_vec) +{ + mddev_t *mddev = q->queuedata; + sector_t sector = bio->bi_sector + get_start_sect(bio->bi_bdev); + int max; + unsigned int chunk_sectors = mddev->chunk_size >> 9; + unsigned int bio_sectors = bio->bi_size >> 9; + + max = (chunk_sectors - ((sector & (chunk_sectors - 1)) + bio_sectors)) << 9; + if (max < 0) max = 0; /* bio_add cannot handle a negative return */ + if (max <= bio_vec->bv_len && bio_sectors == 0) + return bio_vec->bv_len; + else + return max; +} + +/* + * This routine returns the disk from which the requested read should + * be done. There is a per-array 'next expected sequential IO' sector + * number - if this matches on the next IO then we use the last disk. + * There is also a per-disk 'last know head position' sector that is + * maintained from IRQ contexts, both the normal and the resync IO + * completion handlers update this position correctly. If there is no + * perfect sequential match then we pick the disk whose head is closest. + * + * If there are 2 mirrors in the same 2 devices, performance degrades + * because position is mirror, not device based. + * + * The rdev for the device selected will have nr_pending incremented. + */ + +/* + * FIXME: possibly should rethink readbalancing and do it differently + * depending on near_copies / far_copies geometry. + */ +static int read_balance(conf_t *conf, r10bio_t *r10_bio) +{ + const unsigned long this_sector = r10_bio->sector; + int disk, slot, nslot; + const int sectors = r10_bio->sectors; + sector_t new_distance, current_distance; + + raid10_find_phys(conf, r10_bio); + spin_lock_irq(&conf->device_lock); + /* + * Check if we can balance. We can balance on the whole + * device if no resync is going on, or below the resync window. + * We take the first readable disk when above the resync window. + */ + if (conf->mddev->recovery_cp < MaxSector + && (this_sector + sectors >= conf->next_resync)) { + /* make sure that disk is operational */ + slot = 0; + disk = r10_bio->devs[slot].devnum; + + while (!conf->mirrors[disk].rdev || + !conf->mirrors[disk].rdev->in_sync) { + slot++; + if (slot == conf->copies) { + slot = 0; + disk = -1; + break; + } + disk = r10_bio->devs[slot].devnum; + } + goto rb_out; + } + + + /* make sure the disk is operational */ + slot = 0; + disk = r10_bio->devs[slot].devnum; + while (!conf->mirrors[disk].rdev || + !conf->mirrors[disk].rdev->in_sync) { + slot ++; + if (slot == conf->copies) { + disk = -1; + goto rb_out; + } + disk = r10_bio->devs[slot].devnum; + } + + + current_distance = abs(this_sector - conf->mirrors[disk].head_position); + + /* Find the disk whose head is closest */ + + for (nslot = slot; nslot < conf->copies; nslot++) { + int ndisk = r10_bio->devs[nslot].devnum; + + + if (!conf->mirrors[ndisk].rdev || + !conf->mirrors[ndisk].rdev->in_sync) + continue; + + if (!atomic_read(&conf->mirrors[ndisk].rdev->nr_pending)) { + disk = ndisk; + slot = nslot; + break; + } + new_distance = abs(r10_bio->devs[nslot].addr - + conf->mirrors[ndisk].head_position); + if (new_distance < current_distance) { + current_distance = new_distance; + disk = ndisk; + slot = nslot; + } + } + +rb_out: + r10_bio->read_slot = slot; +/* conf->next_seq_sect = this_sector + sectors;*/ + + if (disk >= 0 && conf->mirrors[disk].rdev) + atomic_inc(&conf->mirrors[disk].rdev->nr_pending); + spin_unlock_irq(&conf->device_lock); + + return disk; +} + +static void unplug_slaves(mddev_t *mddev) +{ + conf_t *conf = mddev_to_conf(mddev); + int i; + unsigned long flags; + + spin_lock_irqsave(&conf->device_lock, flags); + for (i=0; iraid_disks; i++) { + mdk_rdev_t *rdev = conf->mirrors[i].rdev; + if (rdev && atomic_read(&rdev->nr_pending)) { + request_queue_t *r_queue = bdev_get_queue(rdev->bdev); + + atomic_inc(&rdev->nr_pending); + spin_unlock_irqrestore(&conf->device_lock, flags); + + if (r_queue->unplug_fn) + r_queue->unplug_fn(r_queue); + + spin_lock_irqsave(&conf->device_lock, flags); + atomic_dec(&rdev->nr_pending); + } + } + spin_unlock_irqrestore(&conf->device_lock, flags); +} +static void raid10_unplug(request_queue_t *q) +{ + unplug_slaves(q->queuedata); +} + +static int raid10_issue_flush(request_queue_t *q, struct gendisk *disk, + sector_t *error_sector) +{ + mddev_t *mddev = q->queuedata; + conf_t *conf = mddev_to_conf(mddev); + unsigned long flags; + int i, ret = 0; + + spin_lock_irqsave(&conf->device_lock, flags); + for (i=0; iraid_disks; i++) { + mdk_rdev_t *rdev = conf->mirrors[i].rdev; + if (rdev && !rdev->faulty) { + struct block_device *bdev = rdev->bdev; + request_queue_t *r_queue = bdev_get_queue(bdev); + + if (r_queue->issue_flush_fn) { + ret = r_queue->issue_flush_fn(r_queue, bdev->bd_disk, error_sector); + if (ret) + break; + } + } + } + spin_unlock_irqrestore(&conf->device_lock, flags); + return ret; +} + +/* + * Throttle resync depth, so that we can both get proper overlapping of + * requests, but are still able to handle normal requests quickly. + */ +#define RESYNC_DEPTH 32 + +static void device_barrier(conf_t *conf, sector_t sect) +{ + spin_lock_irq(&conf->resync_lock); + wait_event_lock_irq(conf->wait_idle, !waitqueue_active(&conf->wait_resume), + conf->resync_lock, unplug_slaves(conf->mddev)); + + if (!conf->barrier++) { + wait_event_lock_irq(conf->wait_idle, !conf->nr_pending, + conf->resync_lock, unplug_slaves(conf->mddev)); + if (conf->nr_pending) + BUG(); + } + wait_event_lock_irq(conf->wait_resume, conf->barrier < RESYNC_DEPTH, + conf->resync_lock, unplug_slaves(conf->mddev)); + conf->next_resync = sect; + spin_unlock_irq(&conf->resync_lock); +} + +static int make_request(request_queue_t *q, struct bio * bio) +{ + mddev_t *mddev = q->queuedata; + conf_t *conf = mddev_to_conf(mddev); + mirror_info_t *mirror; + r10bio_t *r10_bio; + struct bio *read_bio; + int i; + int chunk_sects = conf->chunk_mask + 1; + + /* If this request crosses a chunk boundary, we need to + * split it. This will only happen for 1 PAGE (or less) requests. + */ + if (unlikely( (bio->bi_sector & conf->chunk_mask) + (bio->bi_size >> 9) + > chunk_sects && + conf->near_copies < conf->raid_disks)) { + struct bio_pair *bp; + /* Sanity check -- queue functions should prevent this happening */ + if (bio->bi_vcnt != 1 || + bio->bi_idx != 0) + goto bad_map; + /* This is a one page bio that upper layers + * refuse to split for us, so we need to split it. + */ + bp = bio_split(bio, bio_split_pool, + chunk_sects - (bio->bi_sector & (chunk_sects - 1)) ); + if (make_request(q, &bp->bio1)) + generic_make_request(&bp->bio1); + if (make_request(q, &bp->bio2)) + generic_make_request(&bp->bio2); + + bio_pair_release(bp); + return 0; + bad_map: + printk("raid10_make_request bug: can't convert block across chunks" + " or bigger than %dk %llu %d\n", chunk_sects/2, + (unsigned long long)bio->bi_sector, bio->bi_size >> 10); + + bio_io_error(bio, bio->bi_size); + return 0; + } + + /* + * Register the new request and wait if the reconstruction + * thread has put up a bar for new requests. + * Continue immediately if no resync is active currently. + */ + spin_lock_irq(&conf->resync_lock); + wait_event_lock_irq(conf->wait_resume, !conf->barrier, conf->resync_lock, ); + conf->nr_pending++; + spin_unlock_irq(&conf->resync_lock); + + if (bio_data_dir(bio)==WRITE) { + disk_stat_inc(mddev->gendisk, writes); + disk_stat_add(mddev->gendisk, write_sectors, bio_sectors(bio)); + } else { + disk_stat_inc(mddev->gendisk, reads); + disk_stat_add(mddev->gendisk, read_sectors, bio_sectors(bio)); + } + + r10_bio = mempool_alloc(conf->r10bio_pool, GFP_NOIO); + + r10_bio->master_bio = bio; + r10_bio->sectors = bio->bi_size >> 9; + + r10_bio->mddev = mddev; + r10_bio->sector = bio->bi_sector; + + if (bio_data_dir(bio) == READ) { + /* + * read balancing logic: + */ + int disk = read_balance(conf, r10_bio); + int slot = r10_bio->read_slot; + if (disk < 0) { + raid_end_bio_io(r10_bio); + return 0; + } + mirror = conf->mirrors + disk; + + read_bio = bio_clone(bio, GFP_NOIO); + + r10_bio->devs[slot].bio = read_bio; + + read_bio->bi_sector = r10_bio->devs[slot].addr + + mirror->rdev->data_offset; + read_bio->bi_bdev = mirror->rdev->bdev; + read_bio->bi_end_io = raid10_end_read_request; + read_bio->bi_rw = READ; + read_bio->bi_private = r10_bio; + + generic_make_request(read_bio); + return 0; + } + + /* + * WRITE: + */ + /* first select target devices under spinlock and + * inc refcount on their rdev. Record them by setting + * bios[x] to bio + */ + raid10_find_phys(conf, r10_bio); + spin_lock_irq(&conf->device_lock); + for (i = 0; i < conf->copies; i++) { + int d = r10_bio->devs[i].devnum; + if (conf->mirrors[d].rdev && + !conf->mirrors[d].rdev->faulty) { + atomic_inc(&conf->mirrors[d].rdev->nr_pending); + r10_bio->devs[i].bio = bio; + } else + r10_bio->devs[i].bio = NULL; + } + spin_unlock_irq(&conf->device_lock); + + atomic_set(&r10_bio->remaining, 1); + md_write_start(mddev); + for (i = 0; i < conf->copies; i++) { + struct bio *mbio; + int d = r10_bio->devs[i].devnum; + if (!r10_bio->devs[i].bio) + continue; + + mbio = bio_clone(bio, GFP_NOIO); + r10_bio->devs[i].bio = mbio; + + mbio->bi_sector = r10_bio->devs[i].addr+ + conf->mirrors[d].rdev->data_offset; + mbio->bi_bdev = conf->mirrors[d].rdev->bdev; + mbio->bi_end_io = raid10_end_write_request; + mbio->bi_rw = WRITE; + mbio->bi_private = r10_bio; + + atomic_inc(&r10_bio->remaining); + generic_make_request(mbio); + } + + if (atomic_dec_and_test(&r10_bio->remaining)) { + md_write_end(mddev); + raid_end_bio_io(r10_bio); + } + + return 0; +} + +static void status(struct seq_file *seq, mddev_t *mddev) +{ + conf_t *conf = mddev_to_conf(mddev); + int i; + + if (conf->near_copies < conf->raid_disks) + seq_printf(seq, " %dK chunks", mddev->chunk_size/1024); + if (conf->near_copies > 1) + seq_printf(seq, " %d near-copies", conf->near_copies); + if (conf->far_copies > 1) + seq_printf(seq, " %d far-copies", conf->far_copies); + + seq_printf(seq, " [%d/%d] [", conf->raid_disks, + conf->working_disks); + for (i = 0; i < conf->raid_disks; i++) + seq_printf(seq, "%s", + conf->mirrors[i].rdev && + conf->mirrors[i].rdev->in_sync ? "U" : "_"); + seq_printf(seq, "]"); +} + +static void error(mddev_t *mddev, mdk_rdev_t *rdev) +{ + char b[BDEVNAME_SIZE]; + conf_t *conf = mddev_to_conf(mddev); + + /* + * If it is not operational, then we have already marked it as dead + * else if it is the last working disks, ignore the error, let the + * next level up know. + * else mark the drive as failed + */ + if (rdev->in_sync + && conf->working_disks == 1) + /* + * Don't fail the drive, just return an IO error. + * The test should really be more sophisticated than + * "working_disks == 1", but it isn't critical, and + * can wait until we do more sophisticated "is the drive + * really dead" tests... + */ + return; + if (rdev->in_sync) { + mddev->degraded++; + conf->working_disks--; + /* + * if recovery is running, make sure it aborts. + */ + set_bit(MD_RECOVERY_ERR, &mddev->recovery); + } + rdev->in_sync = 0; + rdev->faulty = 1; + mddev->sb_dirty = 1; + printk(KERN_ALERT "raid10: Disk failure on %s, disabling device. \n" + " Operation continuing on %d devices\n", + bdevname(rdev->bdev,b), conf->working_disks); +} + +static void print_conf(conf_t *conf) +{ + int i; + mirror_info_t *tmp; + + printk("RAID10 conf printout:\n"); + if (!conf) { + printk("(!conf)\n"); + return; + } + printk(" --- wd:%d rd:%d\n", conf->working_disks, + conf->raid_disks); + + for (i = 0; i < conf->raid_disks; i++) { + char b[BDEVNAME_SIZE]; + tmp = conf->mirrors + i; + if (tmp->rdev) + printk(" disk %d, wo:%d, o:%d, dev:%s\n", + i, !tmp->rdev->in_sync, !tmp->rdev->faulty, + bdevname(tmp->rdev->bdev,b)); + } +} + +static void close_sync(conf_t *conf) +{ + spin_lock_irq(&conf->resync_lock); + wait_event_lock_irq(conf->wait_resume, !conf->barrier, + conf->resync_lock, unplug_slaves(conf->mddev)); + spin_unlock_irq(&conf->resync_lock); + + if (conf->barrier) BUG(); + if (waitqueue_active(&conf->wait_idle)) BUG(); + + mempool_destroy(conf->r10buf_pool); + conf->r10buf_pool = NULL; +} + +static int raid10_spare_active(mddev_t *mddev) +{ + int i; + conf_t *conf = mddev->private; + mirror_info_t *tmp; + + spin_lock_irq(&conf->device_lock); + /* + * Find all non-in_sync disks within the RAID10 configuration + * and mark them in_sync + */ + for (i = 0; i < conf->raid_disks; i++) { + tmp = conf->mirrors + i; + if (tmp->rdev + && !tmp->rdev->faulty + && !tmp->rdev->in_sync) { + conf->working_disks++; + mddev->degraded--; + tmp->rdev->in_sync = 1; + } + } + spin_unlock_irq(&conf->device_lock); + + print_conf(conf); + return 0; +} + + +static int raid10_add_disk(mddev_t *mddev, mdk_rdev_t *rdev) +{ + conf_t *conf = mddev->private; + int found = 0; + int mirror; + mirror_info_t *p; + + if (mddev->recovery_cp < MaxSector) + /* only hot-add to in-sync arrays, as recovery is + * very different from resync + */ + return 0; + spin_lock_irq(&conf->device_lock); + for (mirror=0; mirror < mddev->raid_disks; mirror++) + if ( !(p=conf->mirrors+mirror)->rdev) { + p->rdev = rdev; + + blk_queue_stack_limits(mddev->queue, + rdev->bdev->bd_disk->queue); + /* as we don't honour merge_bvec_fn, we must never risk + * violating it, so limit ->max_sector to one PAGE, as + * a one page request is never in violation. + */ + if (rdev->bdev->bd_disk->queue->merge_bvec_fn && + mddev->queue->max_sectors > (PAGE_SIZE>>9)) + mddev->queue->max_sectors = (PAGE_SIZE>>9); + + p->head_position = 0; + rdev->raid_disk = mirror; + found = 1; + break; + } + spin_unlock_irq(&conf->device_lock); + + print_conf(conf); + return found; +} + +static int raid10_remove_disk(mddev_t *mddev, int number) +{ + conf_t *conf = mddev->private; + int err = 1; + mirror_info_t *p = conf->mirrors+ number; + + print_conf(conf); + spin_lock_irq(&conf->device_lock); + if (p->rdev) { + if (p->rdev->in_sync || + atomic_read(&p->rdev->nr_pending)) { + err = -EBUSY; + goto abort; + } + p->rdev = NULL; + err = 0; + } + if (err) + MD_BUG(); +abort: + spin_unlock_irq(&conf->device_lock); + + print_conf(conf); + return err; +} + + +static int end_sync_read(struct bio *bio, unsigned int bytes_done, int error) +{ + int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags); + r10bio_t * r10_bio = (r10bio_t *)(bio->bi_private); + conf_t *conf = mddev_to_conf(r10_bio->mddev); + int i,d; + + if (bio->bi_size) + return 1; + + for (i=0; icopies; i++) + if (r10_bio->devs[i].bio == bio) + break; + if (i == conf->copies) + BUG(); + update_head_pos(i, r10_bio); + d = r10_bio->devs[i].devnum; + if (!uptodate) + md_error(r10_bio->mddev, + conf->mirrors[d].rdev); + + /* for reconstruct, we always reschedule after a read. + * for resync, only after all reads + */ + if (test_bit(R10BIO_IsRecover, &r10_bio->state) || + atomic_dec_and_test(&r10_bio->remaining)) { + /* we have read all the blocks, + * do the comparison in process context in raid10d + */ + reschedule_retry(r10_bio); + } + rdev_dec_pending(conf->mirrors[d].rdev, conf->mddev); + return 0; +} + +static int end_sync_write(struct bio *bio, unsigned int bytes_done, int error) +{ + int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags); + r10bio_t * r10_bio = (r10bio_t *)(bio->bi_private); + mddev_t *mddev = r10_bio->mddev; + conf_t *conf = mddev_to_conf(mddev); + int i,d; + + if (bio->bi_size) + return 1; + + for (i = 0; i < conf->copies; i++) + if (r10_bio->devs[i].bio == bio) + break; + d = r10_bio->devs[i].devnum; + + if (!uptodate) + md_error(mddev, conf->mirrors[d].rdev); + update_head_pos(i, r10_bio); + + while (atomic_dec_and_test(&r10_bio->remaining)) { + if (r10_bio->master_bio == NULL) { + /* the primary of several recovery bios */ + md_done_sync(mddev, r10_bio->sectors, 1); + put_buf(r10_bio); + break; + } else { + r10bio_t *r10_bio2 = (r10bio_t *)r10_bio->master_bio; + put_buf(r10_bio); + r10_bio = r10_bio2; + } + } + rdev_dec_pending(conf->mirrors[d].rdev, mddev); + return 0; +} + +/* + * Note: sync and recover and handled very differently for raid10 + * This code is for resync. + * For resync, we read through virtual addresses and read all blocks. + * If there is any error, we schedule a write. The lowest numbered + * drive is authoritative. + * However requests come for physical address, so we need to map. + * For every physical address there are raid_disks/copies virtual addresses, + * which is always are least one, but is not necessarly an integer. + * This means that a physical address can span multiple chunks, so we may + * have to submit multiple io requests for a single sync request. + */ +/* + * We check if all blocks are in-sync and only write to blocks that + * aren't in sync + */ +static void sync_request_write(mddev_t *mddev, r10bio_t *r10_bio) +{ + conf_t *conf = mddev_to_conf(mddev); + int i, first; + struct bio *tbio, *fbio; + + atomic_set(&r10_bio->remaining, 1); + + /* find the first device with a block */ + for (i=0; icopies; i++) + if (test_bit(BIO_UPTODATE, &r10_bio->devs[i].bio->bi_flags)) + break; + + if (i == conf->copies) + goto done; + + first = i; + fbio = r10_bio->devs[i].bio; + + /* now find blocks with errors */ + for (i=first+1 ; i < conf->copies ; i++) { + int vcnt, j, d; + + if (!test_bit(BIO_UPTODATE, &r10_bio->devs[i].bio->bi_flags)) + continue; + /* We know that the bi_io_vec layout is the same for + * both 'first' and 'i', so we just compare them. + * All vec entries are PAGE_SIZE; + */ + tbio = r10_bio->devs[i].bio; + vcnt = r10_bio->sectors >> (PAGE_SHIFT-9); + for (j = 0; j < vcnt; j++) + if (memcmp(page_address(fbio->bi_io_vec[j].bv_page), + page_address(tbio->bi_io_vec[j].bv_page), + PAGE_SIZE)) + break; + if (j == vcnt) + continue; + /* Ok, we need to write this bio + * First we need to fixup bv_offset, bv_len and + * bi_vecs, as the read request might have corrupted these + */ + tbio->bi_vcnt = vcnt; + tbio->bi_size = r10_bio->sectors << 9; + tbio->bi_idx = 0; + tbio->bi_phys_segments = 0; + tbio->bi_hw_segments = 0; + tbio->bi_hw_front_size = 0; + tbio->bi_hw_back_size = 0; + tbio->bi_flags &= ~(BIO_POOL_MASK - 1); + tbio->bi_flags |= 1 << BIO_UPTODATE; + tbio->bi_next = NULL; + tbio->bi_rw = WRITE; + tbio->bi_private = r10_bio; + tbio->bi_sector = r10_bio->devs[i].addr; + + for (j=0; j < vcnt ; j++) { + tbio->bi_io_vec[j].bv_offset = 0; + tbio->bi_io_vec[j].bv_len = PAGE_SIZE; + + memcpy(page_address(tbio->bi_io_vec[j].bv_page), + page_address(fbio->bi_io_vec[j].bv_page), + PAGE_SIZE); + } + tbio->bi_end_io = end_sync_write; + + d = r10_bio->devs[i].devnum; + atomic_inc(&conf->mirrors[d].rdev->nr_pending); + atomic_inc(&r10_bio->remaining); + md_sync_acct(conf->mirrors[d].rdev->bdev, tbio->bi_size >> 9); + + generic_make_request(tbio); + } + +done: + if (atomic_dec_and_test(&r10_bio->remaining)) { + md_done_sync(mddev, r10_bio->sectors, 1); + put_buf(r10_bio); + } +} + +/* + * Now for the recovery code. + * Recovery happens across physical sectors. + * We recover all non-is_sync drives by finding the virtual address of + * each, and then choose a working drive that also has that virt address. + * There is a separate r10_bio for each non-in_sync drive. + * Only the first two slots are in use. The first for reading, + * The second for writing. + * + */ + +static void recovery_request_write(mddev_t *mddev, r10bio_t *r10_bio) +{ + conf_t *conf = mddev_to_conf(mddev); + int i, d; + struct bio *bio, *wbio; + + + /* move the pages across to the second bio + * and submit the write request + */ + bio = r10_bio->devs[0].bio; + wbio = r10_bio->devs[1].bio; + for (i=0; i < wbio->bi_vcnt; i++) { + struct page *p = bio->bi_io_vec[i].bv_page; + bio->bi_io_vec[i].bv_page = wbio->bi_io_vec[i].bv_page; + wbio->bi_io_vec[i].bv_page = p; + } + d = r10_bio->devs[1].devnum; + + atomic_inc(&conf->mirrors[d].rdev->nr_pending); + md_sync_acct(conf->mirrors[d].rdev->bdev, wbio->bi_size >> 9); + generic_make_request(wbio); +} + + +/* + * This is a kernel thread which: + * + * 1. Retries failed read operations on working mirrors. + * 2. Updates the raid superblock when problems encounter. + * 3. Performs writes following reads for array syncronising. + */ + +static void raid10d(mddev_t *mddev) +{ + r10bio_t *r10_bio; + struct bio *bio; + unsigned long flags; + conf_t *conf = mddev_to_conf(mddev); + struct list_head *head = &conf->retry_list; + int unplug=0; + mdk_rdev_t *rdev; + + md_check_recovery(mddev); + md_handle_safemode(mddev); + + for (;;) { + char b[BDEVNAME_SIZE]; + spin_lock_irqsave(&conf->device_lock, flags); + if (list_empty(head)) + break; + r10_bio = list_entry(head->prev, r10bio_t, retry_list); + list_del(head->prev); + spin_unlock_irqrestore(&conf->device_lock, flags); + + mddev = r10_bio->mddev; + conf = mddev_to_conf(mddev); + if (test_bit(R10BIO_IsSync, &r10_bio->state)) { + sync_request_write(mddev, r10_bio); + unplug = 1; + } else if (test_bit(R10BIO_IsRecover, &r10_bio->state)) { + recovery_request_write(mddev, r10_bio); + unplug = 1; + } else { + int mirror; + bio = r10_bio->devs[r10_bio->read_slot].bio; + r10_bio->devs[r10_bio->read_slot].bio = NULL; + mirror = read_balance(conf, r10_bio); + r10_bio->devs[r10_bio->read_slot].bio = bio; + if (mirror == -1) { + printk(KERN_ALERT "raid10: %s: unrecoverable I/O" + " read error for block %llu\n", + bdevname(bio->bi_bdev,b), + (unsigned long long)r10_bio->sector); + raid_end_bio_io(r10_bio); + } else { + rdev = conf->mirrors[mirror].rdev; + if (printk_ratelimit()) + printk(KERN_ERR "raid10: %s: redirecting sector %llu to" + " another mirror\n", + bdevname(rdev->bdev,b), + (unsigned long long)r10_bio->sector); + bio->bi_bdev = rdev->bdev; + bio->bi_sector = r10_bio->devs[r10_bio->read_slot].addr + + rdev->data_offset; + bio->bi_next = NULL; + bio->bi_flags &= (1<bi_flags |= 1 << BIO_UPTODATE; + bio->bi_idx = 0; + bio->bi_size = r10_bio->sectors << 9; + bio->bi_rw = READ; + unplug = 1; + generic_make_request(bio); + } + } + } + spin_unlock_irqrestore(&conf->device_lock, flags); + if (unplug) + unplug_slaves(mddev); +} + + +static int init_resync(conf_t *conf) +{ + int buffs; + + buffs = RESYNC_WINDOW / RESYNC_BLOCK_SIZE; + if (conf->r10buf_pool) + BUG(); + conf->r10buf_pool = mempool_create(buffs, r10buf_pool_alloc, r10buf_pool_free, conf); + if (!conf->r10buf_pool) + return -ENOMEM; + conf->next_resync = 0; + return 0; +} + +/* + * perform a "sync" on one "block" + * + * We need to make sure that no normal I/O request - particularly write + * requests - conflict with active sync requests. + * + * This is achieved by tracking pending requests and a 'barrier' concept + * that can be installed to exclude normal IO requests. + * + * Resync and recovery are handled very differently. + * We differentiate by looking at MD_RECOVERY_SYNC in mddev->recovery. + * + * For resync, we iterate over virtual addresses, read all copies, + * and update if there are differences. If only one copy is live, + * skip it. + * For recovery, we iterate over physical addresses, read a good + * value for each non-in_sync drive, and over-write. + * + * So, for recovery we may have several outstanding complex requests for a + * given address, one for each out-of-sync device. We model this by allocating + * a number of r10_bio structures, one for each out-of-sync device. + * As we setup these structures, we collect all bio's together into a list + * which we then process collectively to add pages, and then process again + * to pass to generic_make_request. + * + * The r10_bio structures are linked using a borrowed master_bio pointer. + * This link is counted in ->remaining. When the r10_bio that points to NULL + * has its remaining count decremented to 0, the whole complex operation + * is complete. + * + */ + +static int sync_request(mddev_t *mddev, sector_t sector_nr, int go_faster) +{ + conf_t *conf = mddev_to_conf(mddev); + r10bio_t *r10_bio; + struct bio *biolist = NULL, *bio; + sector_t max_sector, nr_sectors; + int disk; + int i; + + sector_t sectors_skipped = 0; + int chunks_skipped = 0; + + if (!conf->r10buf_pool) + if (init_resync(conf)) + return -ENOMEM; + + skipped: + max_sector = mddev->size << 1; + if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery)) + max_sector = mddev->resync_max_sectors; + if (sector_nr >= max_sector) { + close_sync(conf); + return sectors_skipped; + } + if (chunks_skipped >= conf->raid_disks) { + /* if there has been nothing to do on any drive, + * then there is nothing to do at all.. + */ + sector_t sec = max_sector - sector_nr; + md_done_sync(mddev, sec, 1); + return sec + sectors_skipped; + } + + /* make sure whole request will fit in a chunk - if chunks + * are meaningful + */ + if (conf->near_copies < conf->raid_disks && + max_sector > (sector_nr | conf->chunk_mask)) + max_sector = (sector_nr | conf->chunk_mask) + 1; + /* + * If there is non-resync activity waiting for us then + * put in a delay to throttle resync. + */ + if (!go_faster && waitqueue_active(&conf->wait_resume)) + schedule_timeout(HZ); + device_barrier(conf, sector_nr + RESYNC_SECTORS); + + /* Again, very different code for resync and recovery. + * Both must result in an r10bio with a list of bios that + * have bi_end_io, bi_sector, bi_bdev set, + * and bi_private set to the r10bio. + * For recovery, we may actually create several r10bios + * with 2 bios in each, that correspond to the bios in the main one. + * In this case, the subordinate r10bios link back through a + * borrowed master_bio pointer, and the counter in the master + * includes a ref from each subordinate. + */ + /* First, we decide what to do and set ->bi_end_io + * To end_sync_read if we want to read, and + * end_sync_write if we will want to write. + */ + + if (!test_bit(MD_RECOVERY_SYNC, &mddev->recovery)) { + /* recovery... the complicated one */ + int i, j, k; + r10_bio = NULL; + + for (i=0 ; iraid_disks; i++) + if (conf->mirrors[i].rdev && + !conf->mirrors[i].rdev->in_sync) { + /* want to reconstruct this device */ + r10bio_t *rb2 = r10_bio; + + r10_bio = mempool_alloc(conf->r10buf_pool, GFP_NOIO); + spin_lock_irq(&conf->resync_lock); + conf->nr_pending++; + if (rb2) conf->barrier++; + spin_unlock_irq(&conf->resync_lock); + atomic_set(&r10_bio->remaining, 0); + + r10_bio->master_bio = (struct bio*)rb2; + if (rb2) + atomic_inc(&rb2->remaining); + r10_bio->mddev = mddev; + set_bit(R10BIO_IsRecover, &r10_bio->state); + r10_bio->sector = raid10_find_virt(conf, sector_nr, i); + raid10_find_phys(conf, r10_bio); + for (j=0; jcopies;j++) { + int d = r10_bio->devs[j].devnum; + if (conf->mirrors[d].rdev && + conf->mirrors[d].rdev->in_sync) { + /* This is where we read from */ + bio = r10_bio->devs[0].bio; + bio->bi_next = biolist; + biolist = bio; + bio->bi_private = r10_bio; + bio->bi_end_io = end_sync_read; + bio->bi_rw = 0; + bio->bi_sector = r10_bio->devs[j].addr + + conf->mirrors[d].rdev->data_offset; + bio->bi_bdev = conf->mirrors[d].rdev->bdev; + atomic_inc(&conf->mirrors[d].rdev->nr_pending); + atomic_inc(&r10_bio->remaining); + /* and we write to 'i' */ + + for (k=0; kcopies; k++) + if (r10_bio->devs[k].devnum == i) + break; + bio = r10_bio->devs[1].bio; + bio->bi_next = biolist; + biolist = bio; + bio->bi_private = r10_bio; + bio->bi_end_io = end_sync_write; + bio->bi_rw = 1; + bio->bi_sector = r10_bio->devs[k].addr + + conf->mirrors[i].rdev->data_offset; + bio->bi_bdev = conf->mirrors[i].rdev->bdev; + + r10_bio->devs[0].devnum = d; + r10_bio->devs[1].devnum = i; + + break; + } + } + if (j == conf->copies) { + BUG(); + } + } + if (biolist == NULL) { + while (r10_bio) { + r10bio_t *rb2 = r10_bio; + r10_bio = (r10bio_t*) rb2->master_bio; + rb2->master_bio = NULL; + put_buf(rb2); + } + goto giveup; + } + } else { + /* resync. Schedule a read for every block at this virt offset */ + int count = 0; + r10_bio = mempool_alloc(conf->r10buf_pool, GFP_NOIO); + + spin_lock_irq(&conf->resync_lock); + conf->nr_pending++; + spin_unlock_irq(&conf->resync_lock); + + r10_bio->mddev = mddev; + atomic_set(&r10_bio->remaining, 0); + + r10_bio->master_bio = NULL; + r10_bio->sector = sector_nr; + set_bit(R10BIO_IsSync, &r10_bio->state); + raid10_find_phys(conf, r10_bio); + r10_bio->sectors = (sector_nr | conf->chunk_mask) - sector_nr +1; + spin_lock_irq(&conf->device_lock); + for (i=0; icopies; i++) { + int d = r10_bio->devs[i].devnum; + bio = r10_bio->devs[i].bio; + bio->bi_end_io = NULL; + if (conf->mirrors[d].rdev == NULL || + conf->mirrors[d].rdev->faulty) + continue; + atomic_inc(&conf->mirrors[d].rdev->nr_pending); + atomic_inc(&r10_bio->remaining); + bio->bi_next = biolist; + biolist = bio; + bio->bi_private = r10_bio; + bio->bi_end_io = end_sync_read; + bio->bi_rw = 0; + bio->bi_sector = r10_bio->devs[i].addr + + conf->mirrors[d].rdev->data_offset; + bio->bi_bdev = conf->mirrors[d].rdev->bdev; + count++; + } + spin_unlock_irq(&conf->device_lock); + if (count < 2) { + for (i=0; icopies; i++) { + int d = r10_bio->devs[i].devnum; + if (r10_bio->devs[i].bio->bi_end_io) + atomic_dec(&conf->mirrors[d].rdev->nr_pending); + } + put_buf(r10_bio); + goto giveup; + } + } + + for (bio = biolist; bio ; bio=bio->bi_next) { + + bio->bi_flags &= ~(BIO_POOL_MASK - 1); + if (bio->bi_end_io) + bio->bi_flags |= 1 << BIO_UPTODATE; + bio->bi_vcnt = 0; + bio->bi_idx = 0; + bio->bi_phys_segments = 0; + bio->bi_hw_segments = 0; + bio->bi_size = 0; + } + + nr_sectors = 0; + do { + struct page *page; + int len = PAGE_SIZE; + disk = 0; + if (sector_nr + (len>>9) > max_sector) + len = (max_sector - sector_nr) << 9; + if (len == 0) + break; + for (bio= biolist ; bio ; bio=bio->bi_next) { + page = bio->bi_io_vec[bio->bi_vcnt].bv_page; + if (bio_add_page(bio, page, len, 0) == 0) { + /* stop here */ + struct bio *bio2; + bio->bi_io_vec[bio->bi_vcnt].bv_page = page; + for (bio2 = biolist; bio2 && bio2 != bio; bio2 = bio2->bi_next) { + /* remove last page from this bio */ + bio2->bi_vcnt--; + bio2->bi_size -= len; + bio2->bi_flags &= ~(1<< BIO_SEG_VALID); + } + goto bio_full; + } + disk = i; + } + nr_sectors += len>>9; + sector_nr += len>>9; + } while (biolist->bi_vcnt < RESYNC_PAGES); + bio_full: + r10_bio->sectors = nr_sectors; + + while (biolist) { + bio = biolist; + biolist = biolist->bi_next; + + bio->bi_next = NULL; + r10_bio = bio->bi_private; + r10_bio->sectors = nr_sectors; + + if (bio->bi_end_io == end_sync_read) { + md_sync_acct(bio->bi_bdev, nr_sectors); + generic_make_request(bio); + } + } + + return nr_sectors; + giveup: + /* There is nowhere to write, so all non-sync + * drives must be failed, so try the next chunk... + */ + { + int sec = max_sector - sector_nr; + sectors_skipped += sec; + chunks_skipped ++; + sector_nr = max_sector; + md_done_sync(mddev, sec, 1); + goto skipped; + } +} + +static int run(mddev_t *mddev) +{ + conf_t *conf; + int i, disk_idx; + mirror_info_t *disk; + mdk_rdev_t *rdev; + struct list_head *tmp; + int nc, fc; + sector_t stride, size; + + if (mddev->level != 10) { + printk(KERN_ERR "raid10: %s: raid level not set correctly... (%d)\n", + mdname(mddev), mddev->level); + goto out; + } + nc = mddev->layout & 255; + fc = (mddev->layout >> 8) & 255; + if ((nc*fc) <2 || (nc*fc) > mddev->raid_disks || + (mddev->layout >> 16)) { + printk(KERN_ERR "raid10: %s: unsupported raid10 layout: 0x%8x\n", + mdname(mddev), mddev->layout); + goto out; + } + /* + * copy the already verified devices into our private RAID10 + * bookkeeping area. [whatever we allocate in run(), + * should be freed in stop()] + */ + conf = kmalloc(sizeof(conf_t), GFP_KERNEL); + mddev->private = conf; + if (!conf) { + printk(KERN_ERR "raid10: couldn't allocate memory for %s\n", + mdname(mddev)); + goto out; + } + memset(conf, 0, sizeof(*conf)); + conf->mirrors = kmalloc(sizeof(struct mirror_info)*mddev->raid_disks, + GFP_KERNEL); + if (!conf->mirrors) { + printk(KERN_ERR "raid10: couldn't allocate memory for %s\n", + mdname(mddev)); + goto out_free_conf; + } + memset(conf->mirrors, 0, sizeof(struct mirror_info)*mddev->raid_disks); + + conf->near_copies = nc; + conf->far_copies = fc; + conf->copies = nc*fc; + conf->chunk_mask = (sector_t)(mddev->chunk_size>>9)-1; + conf->chunk_shift = ffz(~mddev->chunk_size) - 9; + stride = mddev->size >> (conf->chunk_shift-1); + sector_div(stride, fc); + conf->stride = stride << conf->chunk_shift; + + conf->r10bio_pool = mempool_create(NR_RAID10_BIOS, r10bio_pool_alloc, + r10bio_pool_free, conf); + if (!conf->r10bio_pool) { + printk(KERN_ERR "raid10: couldn't allocate memory for %s\n", + mdname(mddev)); + goto out_free_conf; + } + mddev->queue->unplug_fn = raid10_unplug; + + mddev->queue->issue_flush_fn = raid10_issue_flush; + + ITERATE_RDEV(mddev, rdev, tmp) { + disk_idx = rdev->raid_disk; + if (disk_idx >= mddev->raid_disks + || disk_idx < 0) + continue; + disk = conf->mirrors + disk_idx; + + disk->rdev = rdev; + + blk_queue_stack_limits(mddev->queue, + rdev->bdev->bd_disk->queue); + /* as we don't honour merge_bvec_fn, we must never risk + * violating it, so limit ->max_sector to one PAGE, as + * a one page request is never in violation. + */ + if (rdev->bdev->bd_disk->queue->merge_bvec_fn && + mddev->queue->max_sectors > (PAGE_SIZE>>9)) + mddev->queue->max_sectors = (PAGE_SIZE>>9); + + disk->head_position = 0; + if (!rdev->faulty && rdev->in_sync) + conf->working_disks++; + } + conf->raid_disks = mddev->raid_disks; + conf->mddev = mddev; + conf->device_lock = SPIN_LOCK_UNLOCKED; + INIT_LIST_HEAD(&conf->retry_list); + + conf->resync_lock = SPIN_LOCK_UNLOCKED; + init_waitqueue_head(&conf->wait_idle); + init_waitqueue_head(&conf->wait_resume); + + if (!conf->working_disks) { + printk(KERN_ERR "raid10: no operational mirrors for %s\n", + mdname(mddev)); + goto out_free_conf; + } + + mddev->degraded = 0; + for (i = 0; i < conf->raid_disks; i++) { + + disk = conf->mirrors + i; + + if (!disk->rdev) { + disk->head_position = 0; + mddev->degraded++; + } + } + + + mddev->thread = md_register_thread(raid10d, mddev, "%s_raid10"); + if (!mddev->thread) { + printk(KERN_ERR + "raid10: couldn't allocate thread for %s\n", + mdname(mddev)); + goto out_free_conf; + } + + printk(KERN_INFO + "raid10: raid set %s active with %d out of %d devices\n", + mdname(mddev), mddev->raid_disks - mddev->degraded, + mddev->raid_disks); + /* + * Ok, everything is just fine now + */ + size = conf->stride * conf->raid_disks; + sector_div(size, conf->near_copies); + mddev->array_size = size/2; + mddev->resync_max_sectors = size; + + /* Calculate max read-ahead size. + * We need to readahead at least twice a whole stripe.... + * maybe... + */ + { + int stripe = conf->raid_disks * mddev->chunk_size / PAGE_CACHE_SIZE; + stripe /= conf->near_copies; + if (mddev->queue->backing_dev_info.ra_pages < 2* stripe) + mddev->queue->backing_dev_info.ra_pages = 2* stripe; + } + + if (conf->near_copies < mddev->raid_disks) + blk_queue_merge_bvec(mddev->queue, raid10_mergeable_bvec); + return 0; + +out_free_conf: + if (conf->r10bio_pool) + mempool_destroy(conf->r10bio_pool); + if (conf->mirrors) + kfree(conf->mirrors); + kfree(conf); + mddev->private = NULL; +out: + return -EIO; +} + +static int stop(mddev_t *mddev) +{ + conf_t *conf = mddev_to_conf(mddev); + + md_unregister_thread(mddev->thread); + mddev->thread = NULL; + if (conf->r10bio_pool) + mempool_destroy(conf->r10bio_pool); + if (conf->mirrors) + kfree(conf->mirrors); + kfree(conf); + mddev->private = NULL; + return 0; +} + + +static mdk_personality_t raid10_personality = +{ + .name = "raid10", + .owner = THIS_MODULE, + .make_request = make_request, + .run = run, + .stop = stop, + .status = status, + .error_handler = error, + .hot_add_disk = raid10_add_disk, + .hot_remove_disk= raid10_remove_disk, + .spare_active = raid10_spare_active, + .sync_request = sync_request, +}; + +static int __init raid_init(void) +{ + return register_md_personality(RAID10, &raid10_personality); +} + +static void raid_exit(void) +{ + unregister_md_personality(RAID10); +} + +module_init(raid_init); +module_exit(raid_exit); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("md-personality-9"); /* RAID10 */ diff -Nru a/drivers/md/raid5.c b/drivers/md/raid5.c --- a/drivers/md/raid5.c 2004-08-25 22:01:54 -07:00 +++ b/drivers/md/raid5.c 2004-08-25 22:01:54 -07:00 @@ -1071,7 +1071,8 @@ PRINTK("Reading block %d (sync=%d)\n", i, syncing); if (syncing) - md_sync_acct(conf->disks[i].rdev, STRIPE_SECTORS); + md_sync_acct(conf->disks[i].rdev->bdev, + STRIPE_SECTORS); } } } @@ -1256,7 +1257,7 @@ if (rdev) { if (test_bit(R5_Syncio, &sh->dev[i].flags)) - md_sync_acct(rdev, STRIPE_SECTORS); + md_sync_acct(rdev->bdev, STRIPE_SECTORS); bi->bi_bdev = rdev->bdev; PRINTK("for %llu schedule op %ld on disc %d\n", diff -Nru a/drivers/md/raid6main.c b/drivers/md/raid6main.c --- a/drivers/md/raid6main.c 2004-08-25 22:01:54 -07:00 +++ b/drivers/md/raid6main.c 2004-08-25 22:01:54 -07:00 @@ -1208,7 +1208,8 @@ PRINTK("Reading block %d (sync=%d)\n", i, syncing); if (syncing) - md_sync_acct(conf->disks[i].rdev, STRIPE_SECTORS); + md_sync_acct(conf->disks[i].rdev->bdev, + STRIPE_SECTORS); } } } @@ -1418,7 +1419,7 @@ if (rdev) { if (test_bit(R5_Syncio, &sh->dev[i].flags)) - md_sync_acct(rdev, STRIPE_SECTORS); + md_sync_acct(rdev->bdev, STRIPE_SECTORS); bi->bi_bdev = rdev->bdev; PRINTK("for %llu schedule op %ld on disc %d\n", diff -Nru a/drivers/media/dvb/ttpci/Kconfig b/drivers/media/dvb/ttpci/Kconfig --- a/drivers/media/dvb/ttpci/Kconfig 2004-08-25 22:01:54 -07:00 +++ b/drivers/media/dvb/ttpci/Kconfig 2004-08-25 22:01:54 -07:00 @@ -1,6 +1,6 @@ config DVB_AV7110 tristate "AV7110 cards" - depends on DVB_CORE + depends on DVB_CORE && PCI select FW_LOADER select VIDEO_DEV select VIDEO_SAA7146_VV @@ -45,7 +45,7 @@ config DVB_BUDGET tristate "Budget cards" - depends on DVB_CORE + depends on DVB_CORE && PCI select VIDEO_SAA7146 help Support for simple SAA7146 based DVB cards @@ -59,7 +59,7 @@ config DVB_BUDGET_CI tristate "Budget cards with onboard CI connector" - depends on DVB_CORE + depends on DVB_CORE && PCI select VIDEO_SAA7146 help Support for simple SAA7146 based DVB cards @@ -76,7 +76,7 @@ config DVB_BUDGET_AV tristate "Budget cards with analog video inputs" - depends on DVB_CORE + depends on DVB_CORE && PCI select VIDEO_DEV select VIDEO_SAA7146_VV help diff -Nru a/drivers/media/video/meye.c b/drivers/media/video/meye.c --- a/drivers/media/video/meye.c 2004-08-25 22:01:55 -07:00 +++ b/drivers/media/video/meye.c 2004-08-25 22:01:55 -07:00 @@ -58,7 +58,7 @@ static inline void meye_initq(struct meye_queue *queue) { queue->head = queue->tail = 0; queue->len = 0; - queue->s_lock = (spinlock_t)SPIN_LOCK_UNLOCKED; + queue->s_lock = SPIN_LOCK_UNLOCKED; init_waitqueue_head(&queue->proc_list); } diff -Nru a/drivers/misc/ibmasm/module.c b/drivers/misc/ibmasm/module.c --- a/drivers/misc/ibmasm/module.c 2004-08-25 22:01:55 -07:00 +++ b/drivers/misc/ibmasm/module.c 2004-08-25 22:01:55 -07:00 @@ -62,10 +62,17 @@ int result = -ENOMEM; struct service_processor *sp; + if (pci_enable_device(pdev)) { + printk(KERN_ERR "%s: can't enable PCI device at %s\n", + DRIVER_NAME, pci_name(pdev)); + return -ENODEV; + } + sp = kmalloc(sizeof(struct service_processor), GFP_KERNEL); if (sp == NULL) { dev_err(&pdev->dev, "Failed to allocate memory\n"); - return result; + result = -ENOMEM; + goto error_kmalloc; } memset(sp, 0, sizeof(struct service_processor)); @@ -148,6 +155,8 @@ ibmasm_event_buffer_exit(sp); error_eventbuffer: kfree(sp); +error_kmalloc: + pci_disable_device(pdev); return result; } @@ -166,6 +175,7 @@ iounmap(sp->base_address); ibmasm_event_buffer_exit(sp); kfree(sp); + pci_disable_device(pdev); } static struct pci_device_id ibmasm_pci_table[] = diff -Nru a/drivers/mtd/chips/jedec_probe.c b/drivers/mtd/chips/jedec_probe.c --- a/drivers/mtd/chips/jedec_probe.c 2004-08-25 22:01:56 -07:00 +++ b/drivers/mtd/chips/jedec_probe.c 2004-08-25 22:01:56 -07:00 @@ -29,6 +29,7 @@ #define MANUFACTURER_AMD 0x0001 #define MANUFACTURER_ATMEL 0x001f #define MANUFACTURER_FUJITSU 0x0004 +#define MANUFACTURER_HYUNDAI 0x00AD #define MANUFACTURER_INTEL 0x0089 #define MANUFACTURER_MACRONIX 0x00C2 #define MANUFACTURER_PMC 0x009D @@ -56,6 +57,7 @@ #define AM29F040 0x00A4 #define AM29LV040B 0x004F #define AM29F032B 0x0041 +#define AM29F002T 0x00B0 /* Atmel */ #define AT49BV512 0x0003 @@ -77,6 +79,8 @@ #define MBM29LV400TC 0x22B9 #define MBM29LV400BC 0x22BA +/* Hyundai */ +#define HY29F002T 0x00B0 /* Intel */ #define I28F004B3T 0x00d4 @@ -106,6 +110,7 @@ #define MX29LV160T 0x22C4 #define MX29LV160B 0x2249 #define MX29F016 0x00AD +#define MX29F002T 0x00B0 #define MX29F004T 0x0045 #define MX29F004B 0x0046 @@ -507,6 +512,17 @@ ERASEINFO(0x10000,8), } }, { + mfr_id: MANUFACTURER_AMD, + dev_id: AM29F002T, + name: "AMD AM29F002T", + DevSize: SIZE_256KiB, + NumEraseRegions: 4, + regions: {ERASEINFO(0x10000,3), + ERASEINFO(0x08000,1), + ERASEINFO(0x02000,2), + ERASEINFO(0x04000,1) + } + }, { .mfr_id = MANUFACTURER_ATMEL, .dev_id = AT49BV512, .name = "Atmel AT49BV512", @@ -752,6 +768,17 @@ ERASEINFO(0x04000,1) } }, { + mfr_id: MANUFACTURER_HYUNDAI, + dev_id: HY29F002T, + name: "Hyundai HY29F002T", + DevSize: SIZE_256KiB, + NumEraseRegions: 4, + regions: {ERASEINFO(0x10000,3), + ERASEINFO(0x08000,1), + ERASEINFO(0x02000,2), + ERASEINFO(0x04000,1) + } + }, { .mfr_id = MANUFACTURER_INTEL, .dev_id = I28F004B3B, .name = "Intel 28F004B3B", @@ -1135,6 +1162,17 @@ ERASEINFO(0x10000,7), } }, { + mfr_id: MANUFACTURER_MACRONIX, + dev_id: MX29F002T, + name: "Macronix MX29F002T", + DevSize: SIZE_256KiB, + NumEraseRegions: 4, + regions: {ERASEINFO(0x10000,3), + ERASEINFO(0x08000,1), + ERASEINFO(0x02000,2), + ERASEINFO(0x04000,1) + } + }, { .mfr_id = MANUFACTURER_PMC, .dev_id = PM49FL002, .name = "PMC Pm49FL002", @@ -1570,7 +1608,7 @@ ERASEINFO(0x02000, 2), ERASEINFO(0x04000, 1), } - } + } }; diff -Nru a/drivers/net/8139too.c b/drivers/net/8139too.c --- a/drivers/net/8139too.c 2004-08-25 22:01:54 -07:00 +++ b/drivers/net/8139too.c 2004-08-25 22:01:54 -07:00 @@ -593,6 +593,7 @@ int time_to_die; struct mii_if_info mii; unsigned int regs_len; + unsigned long fifo_copy_timeout; }; MODULE_AUTHOR ("Jeff Garzik "); @@ -1927,6 +1928,24 @@ } #endif +static void rtl8139_isr_ack(struct rtl8139_private *tp) +{ + void *ioaddr = tp->mmio_addr; + u16 status; + + status = RTL_R16 (IntrStatus) & RxAckBits; + + /* Clear out errors and receive interrupts */ + if (likely(status != 0)) { + if (unlikely(status & (RxFIFOOver | RxOverflow))) { + tp->stats.rx_errors++; + if (status & RxFIFOOver) + tp->stats.rx_fifo_errors++; + } + RTL_W16_F (IntrStatus, RxAckBits); + } +} + static int rtl8139_rx(struct net_device *dev, struct rtl8139_private *tp, int budget) { @@ -1934,9 +1953,10 @@ int received = 0; unsigned char *rx_ring = tp->rx_ring; unsigned int cur_rx = tp->cur_rx; + unsigned int rx_size = 0; DPRINTK ("%s: In rtl8139_rx(), current %4.4x BufAddr %4.4x," - " free to %4.4x, Cmd %2.2x.\n", dev->name, cur_rx, + " free to %4.4x, Cmd %2.2x.\n", dev->name, (u16)cur_rx, RTL_R16 (RxBufAddr), RTL_R16 (RxBufPtr), RTL_R8 (ChipCmd)); @@ -1944,10 +1964,8 @@ && (RTL_R8 (ChipCmd) & RxBufEmpty) == 0) { u32 ring_offset = cur_rx % RX_BUF_LEN; u32 rx_status; - unsigned int rx_size; unsigned int pkt_size; struct sk_buff *skb; - u16 status; rmb(); @@ -1976,10 +1994,24 @@ * since EarlyRx is disabled. */ if (unlikely(rx_size == 0xfff0)) { + if (!tp->fifo_copy_timeout) + tp->fifo_copy_timeout = jiffies + 2; + else if (time_after(jiffies, tp->fifo_copy_timeout)) { + DPRINTK ("%s: hung FIFO. Reset.", dev->name); + rx_size = 0; + goto no_early_rx; + } + if (netif_msg_intr(tp)) { + printk(KERN_DEBUG "%s: fifo copy in progress.", + dev->name); + } tp->xstats.early_rx++; - goto done; + break; } +no_early_rx: + tp->fifo_copy_timeout = 0; + /* If Rx err or invalid rx_size/rx_status received * (which happens if we get lost in the ring), * Rx process gets reset, so we abort any further @@ -1989,7 +2021,8 @@ (rx_size < 8) || (!(rx_status & RxStatusOK)))) { rtl8139_rx_err (rx_status, dev, tp, ioaddr); - return -1; + received = -1; + goto out; } /* Malloc up new buffer, compatible with net-2e. */ @@ -2025,19 +2058,11 @@ cur_rx = (cur_rx + rx_size + 4 + 3) & ~3; RTL_W16 (RxBufPtr, (u16) (cur_rx - 16)); - /* Clear out errors and receive interrupts */ - status = RTL_R16 (IntrStatus) & RxAckBits; - if (likely(status != 0)) { - if (unlikely(status & (RxFIFOOver | RxOverflow))) { - tp->stats.rx_errors++; - if (status & RxFIFOOver) - tp->stats.rx_fifo_errors++; - } - RTL_W16_F (IntrStatus, RxAckBits); - } + rtl8139_isr_ack(tp); } - done: + if (unlikely(!received || rx_size == 0xfff0)) + rtl8139_isr_ack(tp); #if RTL8139_DEBUG > 1 DPRINTK ("%s: Done rtl8139_rx(), current %4.4x BufAddr %4.4x," @@ -2047,6 +2072,15 @@ #endif tp->cur_rx = cur_rx; + + /* + * The receive buffer should be mostly empty. + * Tell NAPI to reenable the Rx irq. + */ + if (tp->fifo_copy_timeout) + received = budget; + +out: return received; } diff -Nru a/drivers/net/Kconfig b/drivers/net/Kconfig --- a/drivers/net/Kconfig 2004-08-25 22:01:56 -07:00 +++ b/drivers/net/Kconfig 2004-08-25 22:01:56 -07:00 @@ -1752,7 +1752,7 @@ If you have a VIA "Velocity" based network card say Y here. To compile this driver as a module, choose M here. The module - will be called via-rhine. + will be called via-velocity. config LAN_SAA9730 bool "Philips SAA9730 Ethernet support (EXPERIMENTAL)" @@ -2046,8 +2046,20 @@ config R8169_NAPI bool "Use Rx and Tx Polling (NAPI) (EXPERIMENTAL)" - depends on R8169 && EXPERIMENTAL + depends on R8169 && EXPERIMENTAL + help + NAPI is a new driver API designed to reduce CPU and interrupt load + when the driver is receiving lots of packets from the card. It is + still somewhat experimental and thus not yet enabled by default. + + If your estimated Rx load is 10kpps or more, or if the card will be + deployed on potentially unfriendly networks (e.g. in a firewall), + then say Y here. + + See for more + information. + If in doubt, say N. config SK98LIN tristate "Marvell Yukon Chipset / SysKonnect SK-98xx Support" diff -Nru a/drivers/net/dl2k.h b/drivers/net/dl2k.h --- a/drivers/net/dl2k.h 2004-08-25 22:01:56 -07:00 +++ b/drivers/net/dl2k.h 2004-08-25 22:01:56 -07:00 @@ -92,7 +92,7 @@ EepromCtrl = 0x4a, ExpromAddr = 0x4c, Exprodata = 0x50, - WakeEvent0x51, + WakeEvent = 0x51, CountDown = 0x54, IntStatusAck = 0x5a, IntEnable = 0x5c, diff -Nru a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c --- a/drivers/net/e1000/e1000_main.c 2004-08-25 22:01:55 -07:00 +++ b/drivers/net/e1000/e1000_main.c 2004-08-25 22:01:55 -07:00 @@ -128,8 +128,8 @@ static struct net_device_stats * e1000_get_stats(struct net_device *netdev); static int e1000_change_mtu(struct net_device *netdev, int new_mtu); static int e1000_set_mac(struct net_device *netdev, void *p); -static inline void e1000_irq_disable(struct e1000_adapter *adapter); -static inline void e1000_irq_enable(struct e1000_adapter *adapter); +static void e1000_irq_disable(struct e1000_adapter *adapter); +static void e1000_irq_enable(struct e1000_adapter *adapter); static irqreturn_t e1000_intr(int irq, void *data, struct pt_regs *regs); static boolean_t e1000_clean_tx_irq(struct e1000_adapter *adapter); #ifdef CONFIG_E1000_NAPI @@ -146,9 +146,9 @@ void set_ethtool_ops(struct net_device *netdev); static void e1000_enter_82542_rst(struct e1000_adapter *adapter); static void e1000_leave_82542_rst(struct e1000_adapter *adapter); -static inline void e1000_rx_checksum(struct e1000_adapter *adapter, - struct e1000_rx_desc *rx_desc, - struct sk_buff *skb); +static void e1000_rx_checksum(struct e1000_adapter *adapter, + struct e1000_rx_desc *rx_desc, + struct sk_buff *skb); static void e1000_tx_timeout(struct net_device *dev); static void e1000_tx_timeout_task(struct net_device *dev); static void e1000_smartspeed(struct e1000_adapter *adapter); @@ -2077,7 +2077,7 @@ * @adapter: board private structure **/ -static inline void +static void e1000_irq_disable(struct e1000_adapter *adapter) { atomic_inc(&adapter->irq_sem); @@ -2091,7 +2091,7 @@ * @adapter: board private structure **/ -static inline void +static void e1000_irq_enable(struct e1000_adapter *adapter) { if(likely(atomic_dec_and_test(&adapter->irq_sem))) { @@ -2593,7 +2593,7 @@ * @sk_buff: socket buffer with received data **/ -static inline void +static void e1000_rx_checksum(struct e1000_adapter *adapter, struct e1000_rx_desc *rx_desc, struct sk_buff *skb) diff -Nru a/drivers/net/gianfar.c b/drivers/net/gianfar.c --- a/drivers/net/gianfar.c 2004-08-25 22:01:54 -07:00 +++ b/drivers/net/gianfar.c 2004-08-25 22:01:54 -07:00 @@ -307,8 +307,8 @@ /* Print out the device info */ printk(KERN_INFO DEVICE_NAME, dev->name); for (idx = 0; idx < 6; idx++) - printk(KERN_INFO "%2.2x%c", dev->dev_addr[idx], idx == 5 ? ' ' : ':'); - printk(KERN_INFO "\n"); + printk("%2.2x%c", dev->dev_addr[idx], idx == 5 ? ' ' : ':'); + printk("\n"); /* Even more device info helps when determining which kernel */ /* provided which set of benchmarks. Since this is global for all */ diff -Nru a/drivers/net/hamachi.c b/drivers/net/hamachi.c --- a/drivers/net/hamachi.c 2004-08-25 22:01:56 -07:00 +++ b/drivers/net/hamachi.c 2004-08-25 22:01:56 -07:00 @@ -559,7 +559,7 @@ static void hamachi_init_ring(struct net_device *dev); static int hamachi_start_xmit(struct sk_buff *skb, struct net_device *dev); static irqreturn_t hamachi_interrupt(int irq, void *dev_instance, struct pt_regs *regs); -static inline int hamachi_rx(struct net_device *dev); +static int hamachi_rx(struct net_device *dev); static inline int hamachi_tx(struct net_device *dev); static void hamachi_error(struct net_device *dev, int intr_status); static int hamachi_close(struct net_device *dev); diff -Nru a/drivers/net/hamradio/dmascc.c b/drivers/net/hamradio/dmascc.c --- a/drivers/net/hamradio/dmascc.c 2004-08-25 22:01:55 -07:00 +++ b/drivers/net/hamradio/dmascc.c 2004-08-25 22:01:55 -07:00 @@ -246,8 +246,14 @@ static struct net_device_stats *scc_get_stats(struct net_device *dev); static int scc_set_mac_address(struct net_device *dev, void *sa); -static irqreturn_t scc_isr(int irq, void *dev_id, struct pt_regs * regs); +static inline void tx_on(struct scc_priv *priv); +static inline void rx_on(struct scc_priv *priv); +static inline void rx_off(struct scc_priv *priv); +static void start_timer(struct scc_priv *priv, int t, int r15); +static inline unsigned char random(void); + static inline void z8530_isr(struct scc_info *info); +static irqreturn_t scc_isr(int irq, void *dev_id, struct pt_regs * regs); static void rx_isr(struct scc_priv *priv); static void special_condition(struct scc_priv *priv, int rc); static void rx_bh(void *arg); @@ -255,12 +261,6 @@ static void es_isr(struct scc_priv *priv); static void tm_isr(struct scc_priv *priv); -static inline void tx_on(struct scc_priv *priv); -static inline void rx_on(struct scc_priv *priv); -static inline void rx_off(struct scc_priv *priv); -static void start_timer(struct scc_priv *priv, int t, int r15); -static inline unsigned char random(void); - /* Initialization variables */ @@ -945,42 +945,115 @@ } -static irqreturn_t scc_isr(int irq, void *dev_id, struct pt_regs * regs) { - struct scc_info *info = dev_id; +static inline void tx_on(struct scc_priv *priv) { + int i, n; + unsigned long flags; - spin_lock(info->priv[0].register_lock); - /* At this point interrupts are enabled, and the interrupt under service - is already acknowledged, but masked off. + if (priv->param.dma >= 0) { + n = (priv->chip == Z85230) ? 3 : 1; + /* Program DMA controller */ + flags = claim_dma_lock(); + set_dma_mode(priv->param.dma, DMA_MODE_WRITE); + set_dma_addr(priv->param.dma, (int) priv->tx_buf[priv->tx_tail]+n); + set_dma_count(priv->param.dma, priv->tx_len[priv->tx_tail]-n); + release_dma_lock(flags); + /* Enable TX underrun interrupt */ + write_scc(priv, R15, TxUIE); + /* Configure DREQ */ + if (priv->type == TYPE_TWIN) + outb((priv->param.dma == 1) ? TWIN_DMA_HDX_T1 : TWIN_DMA_HDX_T3, + priv->card_base + TWIN_DMA_CFG); + else + write_scc(priv, R1, EXT_INT_ENAB | WT_FN_RDYFN | WT_RDY_ENAB); + /* Write first byte(s) */ + spin_lock_irqsave(priv->register_lock, flags); + for (i = 0; i < n; i++) + write_scc_data(priv, priv->tx_buf[priv->tx_tail][i], 1); + enable_dma(priv->param.dma); + spin_unlock_irqrestore(priv->register_lock, flags); + } else { + write_scc(priv, R15, TxUIE); + write_scc(priv, R1, EXT_INT_ENAB | WT_FN_RDYFN | TxINT_ENAB); + tx_isr(priv); + } + /* Reset EOM latch if we do not have the AUTOEOM feature */ + if (priv->chip == Z8530) write_scc(priv, R0, RES_EOM_L); +} - Interrupt processing: We loop until we know that the IRQ line is - low. If another positive edge occurs afterwards during the ISR, - another interrupt will be triggered by the interrupt controller - as soon as the IRQ level is enabled again (see asm/irq.h). - Bottom-half handlers will be processed after scc_isr(). This is - important, since we only have small ringbuffers and want new data - to be fetched/delivered immediately. */ +static inline void rx_on(struct scc_priv *priv) { + unsigned long flags; - if (info->priv[0].type == TYPE_TWIN) { - int is, card_base = info->priv[0].card_base; - while ((is = ~inb(card_base + TWIN_INT_REG)) & - TWIN_INT_MSK) { - if (is & TWIN_SCC_MSK) { - z8530_isr(info); - } else if (is & TWIN_TMR1_MSK) { - inb(card_base + TWIN_CLR_TMR1); - tm_isr(&info->priv[0]); - } else { - inb(card_base + TWIN_CLR_TMR2); - tm_isr(&info->priv[1]); - } + /* Clear RX FIFO */ + while (read_scc(priv, R0) & Rx_CH_AV) read_scc_data(priv); + priv->rx_over = 0; + if (priv->param.dma >= 0) { + /* Program DMA controller */ + flags = claim_dma_lock(); + set_dma_mode(priv->param.dma, DMA_MODE_READ); + set_dma_addr(priv->param.dma, (int) priv->rx_buf[priv->rx_head]); + set_dma_count(priv->param.dma, BUF_SIZE); + release_dma_lock(flags); + enable_dma(priv->param.dma); + /* Configure PackeTwin DMA */ + if (priv->type == TYPE_TWIN) { + outb((priv->param.dma == 1) ? TWIN_DMA_HDX_R1 : TWIN_DMA_HDX_R3, + priv->card_base + TWIN_DMA_CFG); } - } else z8530_isr(info); - spin_unlock(info->priv[0].register_lock); - return IRQ_HANDLED; + /* Sp. cond. intr. only, ext int enable, RX DMA enable */ + write_scc(priv, R1, EXT_INT_ENAB | INT_ERR_Rx | + WT_RDY_RT | WT_FN_RDYFN | WT_RDY_ENAB); + } else { + /* Reset current frame */ + priv->rx_ptr = 0; + /* Intr. on all Rx characters and Sp. cond., ext int enable */ + write_scc(priv, R1, EXT_INT_ENAB | INT_ALL_Rx | WT_RDY_RT | + WT_FN_RDYFN); + } + write_scc(priv, R0, ERR_RES); + write_scc(priv, R3, RxENABLE | Rx8 | RxCRC_ENAB); +} + + +static inline void rx_off(struct scc_priv *priv) { + /* Disable receiver */ + write_scc(priv, R3, Rx8); + /* Disable DREQ / RX interrupt */ + if (priv->param.dma >= 0 && priv->type == TYPE_TWIN) + outb(0, priv->card_base + TWIN_DMA_CFG); + else + write_scc(priv, R1, EXT_INT_ENAB | WT_FN_RDYFN); + /* Disable DMA */ + if (priv->param.dma >= 0) disable_dma(priv->param.dma); +} + + +static void start_timer(struct scc_priv *priv, int t, int r15) { + unsigned long flags; + + outb(priv->tmr_mode, priv->tmr_ctrl); + if (t == 0) { + tm_isr(priv); + } else if (t > 0) { + save_flags(flags); + cli(); + outb(t & 0xFF, priv->tmr_cnt); + outb((t >> 8) & 0xFF, priv->tmr_cnt); + if (priv->type != TYPE_TWIN) { + write_scc(priv, R15, r15 | CTSIE); + priv->rr0 |= CTS; + } + restore_flags(flags); + } } +static inline unsigned char random(void) { + /* See "Numerical Recipes in C", second edition, p. 284 */ + rand = rand * 1664525L + 1013904223L; + return (unsigned char) (rand >> 24); +} + static inline void z8530_isr(struct scc_info *info) { int is, i = 100; @@ -1009,6 +1082,42 @@ } +static irqreturn_t scc_isr(int irq, void *dev_id, struct pt_regs * regs) { + struct scc_info *info = dev_id; + + spin_lock(info->priv[0].register_lock); + /* At this point interrupts are enabled, and the interrupt under service + is already acknowledged, but masked off. + + Interrupt processing: We loop until we know that the IRQ line is + low. If another positive edge occurs afterwards during the ISR, + another interrupt will be triggered by the interrupt controller + as soon as the IRQ level is enabled again (see asm/irq.h). + + Bottom-half handlers will be processed after scc_isr(). This is + important, since we only have small ringbuffers and want new data + to be fetched/delivered immediately. */ + + if (info->priv[0].type == TYPE_TWIN) { + int is, card_base = info->priv[0].card_base; + while ((is = ~inb(card_base + TWIN_INT_REG)) & + TWIN_INT_MSK) { + if (is & TWIN_SCC_MSK) { + z8530_isr(info); + } else if (is & TWIN_TMR1_MSK) { + inb(card_base + TWIN_CLR_TMR1); + tm_isr(&info->priv[0]); + } else { + inb(card_base + TWIN_CLR_TMR2); + tm_isr(&info->priv[1]); + } + } + } else z8530_isr(info); + spin_unlock(info->priv[0].register_lock); + return IRQ_HANDLED; +} + + static void rx_isr(struct scc_priv *priv) { if (priv->param.dma >= 0) { /* Check special condition and perform error reset. See 2.4.7.5. */ @@ -1292,114 +1401,3 @@ break; } } - - -static inline void tx_on(struct scc_priv *priv) { - int i, n; - unsigned long flags; - - if (priv->param.dma >= 0) { - n = (priv->chip == Z85230) ? 3 : 1; - /* Program DMA controller */ - flags = claim_dma_lock(); - set_dma_mode(priv->param.dma, DMA_MODE_WRITE); - set_dma_addr(priv->param.dma, (int) priv->tx_buf[priv->tx_tail]+n); - set_dma_count(priv->param.dma, priv->tx_len[priv->tx_tail]-n); - release_dma_lock(flags); - /* Enable TX underrun interrupt */ - write_scc(priv, R15, TxUIE); - /* Configure DREQ */ - if (priv->type == TYPE_TWIN) - outb((priv->param.dma == 1) ? TWIN_DMA_HDX_T1 : TWIN_DMA_HDX_T3, - priv->card_base + TWIN_DMA_CFG); - else - write_scc(priv, R1, EXT_INT_ENAB | WT_FN_RDYFN | WT_RDY_ENAB); - /* Write first byte(s) */ - spin_lock_irqsave(priv->register_lock, flags); - for (i = 0; i < n; i++) - write_scc_data(priv, priv->tx_buf[priv->tx_tail][i], 1); - enable_dma(priv->param.dma); - spin_unlock_irqrestore(priv->register_lock, flags); - } else { - write_scc(priv, R15, TxUIE); - write_scc(priv, R1, EXT_INT_ENAB | WT_FN_RDYFN | TxINT_ENAB); - tx_isr(priv); - } - /* Reset EOM latch if we do not have the AUTOEOM feature */ - if (priv->chip == Z8530) write_scc(priv, R0, RES_EOM_L); -} - - -static inline void rx_on(struct scc_priv *priv) { - unsigned long flags; - - /* Clear RX FIFO */ - while (read_scc(priv, R0) & Rx_CH_AV) read_scc_data(priv); - priv->rx_over = 0; - if (priv->param.dma >= 0) { - /* Program DMA controller */ - flags = claim_dma_lock(); - set_dma_mode(priv->param.dma, DMA_MODE_READ); - set_dma_addr(priv->param.dma, (int) priv->rx_buf[priv->rx_head]); - set_dma_count(priv->param.dma, BUF_SIZE); - release_dma_lock(flags); - enable_dma(priv->param.dma); - /* Configure PackeTwin DMA */ - if (priv->type == TYPE_TWIN) { - outb((priv->param.dma == 1) ? TWIN_DMA_HDX_R1 : TWIN_DMA_HDX_R3, - priv->card_base + TWIN_DMA_CFG); - } - /* Sp. cond. intr. only, ext int enable, RX DMA enable */ - write_scc(priv, R1, EXT_INT_ENAB | INT_ERR_Rx | - WT_RDY_RT | WT_FN_RDYFN | WT_RDY_ENAB); - } else { - /* Reset current frame */ - priv->rx_ptr = 0; - /* Intr. on all Rx characters and Sp. cond., ext int enable */ - write_scc(priv, R1, EXT_INT_ENAB | INT_ALL_Rx | WT_RDY_RT | - WT_FN_RDYFN); - } - write_scc(priv, R0, ERR_RES); - write_scc(priv, R3, RxENABLE | Rx8 | RxCRC_ENAB); -} - - -static inline void rx_off(struct scc_priv *priv) { - /* Disable receiver */ - write_scc(priv, R3, Rx8); - /* Disable DREQ / RX interrupt */ - if (priv->param.dma >= 0 && priv->type == TYPE_TWIN) - outb(0, priv->card_base + TWIN_DMA_CFG); - else - write_scc(priv, R1, EXT_INT_ENAB | WT_FN_RDYFN); - /* Disable DMA */ - if (priv->param.dma >= 0) disable_dma(priv->param.dma); -} - - -static void start_timer(struct scc_priv *priv, int t, int r15) { - unsigned long flags; - - outb(priv->tmr_mode, priv->tmr_ctrl); - if (t == 0) { - tm_isr(priv); - } else if (t > 0) { - save_flags(flags); - cli(); - outb(t & 0xFF, priv->tmr_cnt); - outb((t >> 8) & 0xFF, priv->tmr_cnt); - if (priv->type != TYPE_TWIN) { - write_scc(priv, R15, r15 | CTSIE); - priv->rr0 |= CTS; - } - restore_flags(flags); - } -} - - -static inline unsigned char random(void) { - /* See "Numerical Recipes in C", second edition, p. 284 */ - rand = rand * 1664525L + 1013904223L; - return (unsigned char) (rand >> 24); -} - diff -Nru a/drivers/net/hp100.c b/drivers/net/hp100.c --- a/drivers/net/hp100.c 2004-08-25 22:01:55 -07:00 +++ b/drivers/net/hp100.c 2004-08-25 22:01:55 -07:00 @@ -2910,10 +2910,15 @@ int ioaddr = pci_resource_start(pdev, 0); u_short pci_command; int err; - + if (!dev) return -ENOMEM; + if (pci_enable_device(pdev)) { + err = -ENODEV; + goto out0; + } + SET_MODULE_OWNER(dev); SET_NETDEV_DEV(dev, &pdev->dev); @@ -2951,6 +2956,8 @@ release_region(dev->base_addr, HP100_REGION_SIZE); out1: free_netdev(dev); + pci_disable_device(pdev); + out0: return err; } @@ -2959,6 +2966,7 @@ struct net_device *dev = pci_get_drvdata(pdev); cleanup_dev(dev); + pci_disable_device(pdev); } diff -Nru a/drivers/net/ioc3-eth.c b/drivers/net/ioc3-eth.c --- a/drivers/net/ioc3-eth.c 2004-08-25 22:01:54 -07:00 +++ b/drivers/net/ioc3-eth.c 2004-08-25 22:01:54 -07:00 @@ -1172,9 +1172,14 @@ u32 vendor, model, rev; int err; + if (pci_enable_device(pdev)) + return -ENODEV; + dev = alloc_etherdev(sizeof(struct ioc3_private)); - if (!dev) - return -ENOMEM; + if (!dev) { + err = -ENOMEM; + goto out_disable; + } err = pci_request_regions(pdev, "ioc3"); if (err) @@ -1269,6 +1274,8 @@ pci_release_regions(pdev); out_free: free_netdev(dev); +out_disable: + pci_disable_device(pdev); return err; } @@ -1282,6 +1289,7 @@ iounmap(ioc3); pci_release_regions(pdev); free_netdev(dev); + pci_disable_device(pdev); } static struct pci_device_id ioc3_pci_tbl[] = { diff -Nru a/drivers/net/ixgb/ixgb_main.c b/drivers/net/ixgb/ixgb_main.c --- a/drivers/net/ixgb/ixgb_main.c 2004-08-25 22:01:54 -07:00 +++ b/drivers/net/ixgb/ixgb_main.c 2004-08-25 22:01:54 -07:00 @@ -55,6 +55,8 @@ /* Local Function Prototypes */ +static inline void ixgb_irq_disable(struct ixgb_adapter *adapter); +static inline void ixgb_irq_enable(struct ixgb_adapter *adapter); int ixgb_up(struct ixgb_adapter *adapter); void ixgb_down(struct ixgb_adapter *adapter, boolean_t kill_watchdog); void ixgb_reset(struct ixgb_adapter *adapter); @@ -82,10 +84,11 @@ static int ixgb_change_mtu(struct net_device *netdev, int new_mtu); static int ixgb_set_mac(struct net_device *netdev, void *p); static void ixgb_update_stats(struct ixgb_adapter *adapter); -static inline void ixgb_irq_disable(struct ixgb_adapter *adapter); -static inline void ixgb_irq_enable(struct ixgb_adapter *adapter); static irqreturn_t ixgb_intr(int irq, void *data, struct pt_regs *regs); static boolean_t ixgb_clean_tx_irq(struct ixgb_adapter *adapter); +static inline void ixgb_rx_checksum(struct ixgb_adapter *adapter, + struct ixgb_rx_desc *rx_desc, + struct sk_buff *skb); #ifdef CONFIG_IXGB_NAPI static int ixgb_clean(struct net_device *netdev, int *budget); static boolean_t ixgb_clean_rx_irq(struct ixgb_adapter *adapter, @@ -95,9 +98,6 @@ #endif static void ixgb_alloc_rx_buffers(struct ixgb_adapter *adapter); static int ixgb_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd); -static inline void ixgb_rx_checksum(struct ixgb_adapter *adapter, - struct ixgb_rx_desc *rx_desc, - struct sk_buff *skb); static void ixgb_tx_timeout(struct net_device *dev); static void ixgb_tx_timeout_task(struct net_device *dev); static void ixgb_vlan_rx_register(struct net_device *netdev, @@ -185,6 +185,34 @@ module_exit(ixgb_exit_module); +/** + * ixgb_irq_disable - Mask off interrupt generation on the NIC + * @adapter: board private structure + **/ + +static inline void ixgb_irq_disable(struct ixgb_adapter *adapter) +{ + atomic_inc(&adapter->irq_sem); + IXGB_WRITE_REG(&adapter->hw, IMC, ~0); + IXGB_WRITE_FLUSH(&adapter->hw); + synchronize_irq(adapter->pdev->irq); +} + +/** + * ixgb_irq_enable - Enable default interrupt generation settings + * @adapter: board private structure + **/ + +static inline void ixgb_irq_enable(struct ixgb_adapter *adapter) +{ + if (atomic_dec_and_test(&adapter->irq_sem)) { + IXGB_WRITE_REG(&adapter->hw, IMS, + IXGB_INT_RXT0 | IXGB_INT_RXDMT0 | IXGB_INT_TXDW | + IXGB_INT_RXO | IXGB_INT_LSC); + IXGB_WRITE_FLUSH(&adapter->hw); + } +} + int ixgb_up(struct ixgb_adapter *adapter) { struct net_device *netdev = adapter->netdev; @@ -1550,34 +1578,6 @@ adapter->net_stats.tx_window_errors = 0; } -/** - * ixgb_irq_disable - Mask off interrupt generation on the NIC - * @adapter: board private structure - **/ - -static inline void ixgb_irq_disable(struct ixgb_adapter *adapter) -{ - atomic_inc(&adapter->irq_sem); - IXGB_WRITE_REG(&adapter->hw, IMC, ~0); - IXGB_WRITE_FLUSH(&adapter->hw); - synchronize_irq(adapter->pdev->irq); -} - -/** - * ixgb_irq_enable - Enable default interrupt generation settings - * @adapter: board private structure - **/ - -static inline void ixgb_irq_enable(struct ixgb_adapter *adapter) -{ - if (atomic_dec_and_test(&adapter->irq_sem)) { - IXGB_WRITE_REG(&adapter->hw, IMS, - IXGB_INT_RXT0 | IXGB_INT_RXDMT0 | IXGB_INT_TXDW | - IXGB_INT_RXO | IXGB_INT_LSC); - IXGB_WRITE_FLUSH(&adapter->hw); - } -} - #define IXGB_MAX_INTR 10 /** * ixgb_intr - Interrupt Handler @@ -1730,6 +1730,39 @@ } /** + * ixgb_rx_checksum - Receive Checksum Offload for 82597. + * @adapter: board private structure + * @rx_desc: receive descriptor + * @sk_buff: socket buffer with received data + **/ + +static inline void +ixgb_rx_checksum(struct ixgb_adapter *adapter, + struct ixgb_rx_desc *rx_desc, struct sk_buff *skb) +{ + /* Ignore Checksum bit is set OR + * TCP Checksum has not been calculated + */ + if ((rx_desc->status & IXGB_RX_DESC_STATUS_IXSM) || + (!(rx_desc->status & IXGB_RX_DESC_STATUS_TCPCS))) { + skb->ip_summed = CHECKSUM_NONE; + return; + } + + /* At this point we know the hardware did the TCP checksum */ + /* now look at the TCP checksum error bit */ + if (rx_desc->errors & IXGB_RX_DESC_ERRORS_TCPE) { + /* let the stack verify checksum errors */ + skb->ip_summed = CHECKSUM_NONE; + adapter->hw_csum_rx_error++; + } else { + /* TCP checksum is good */ + skb->ip_summed = CHECKSUM_UNNECESSARY; + adapter->hw_csum_rx_good++; + } +} + +/** * ixgb_clean_rx_irq - Send received data up the network stack, * @adapter: board private structure **/ @@ -1953,39 +1986,6 @@ } return 0; -} - -/** - * ixgb_rx_checksum - Receive Checksum Offload for 82597. - * @adapter: board private structure - * @rx_desc: receive descriptor - * @sk_buff: socket buffer with received data - **/ - -static inline void -ixgb_rx_checksum(struct ixgb_adapter *adapter, - struct ixgb_rx_desc *rx_desc, struct sk_buff *skb) -{ - /* Ignore Checksum bit is set OR - * TCP Checksum has not been calculated - */ - if ((rx_desc->status & IXGB_RX_DESC_STATUS_IXSM) || - (!(rx_desc->status & IXGB_RX_DESC_STATUS_TCPCS))) { - skb->ip_summed = CHECKSUM_NONE; - return; - } - - /* At this point we know the hardware did the TCP checksum */ - /* now look at the TCP checksum error bit */ - if (rx_desc->errors & IXGB_RX_DESC_ERRORS_TCPE) { - /* let the stack verify checksum errors */ - skb->ip_summed = CHECKSUM_NONE; - adapter->hw_csum_rx_error++; - } else { - /* TCP checksum is good */ - skb->ip_summed = CHECKSUM_UNNECESSARY; - adapter->hw_csum_rx_good++; - } } /** diff -Nru a/drivers/net/rrunner.c b/drivers/net/rrunner.c --- a/drivers/net/rrunner.c 2004-08-25 22:01:54 -07:00 +++ b/drivers/net/rrunner.c 2004-08-25 22:01:54 -07:00 @@ -1139,6 +1139,49 @@ return IRQ_HANDLED; } +static inline void rr_raz_tx(struct rr_private *rrpriv, + struct net_device *dev) +{ + int i; + + for (i = 0; i < TX_RING_ENTRIES; i++) { + struct sk_buff *skb = rrpriv->tx_skbuff[i]; + + if (skb) { + struct tx_desc *desc = &(rrpriv->tx_ring[i]); + + pci_unmap_single(rrpriv->pci_dev, desc->addr.addrlo, + skb->len, PCI_DMA_TODEVICE); + desc->size = 0; + set_rraddr(&desc->addr, 0); + dev_kfree_skb(skb); + rrpriv->tx_skbuff[i] = NULL; + } + } +} + + +static inline void rr_raz_rx(struct rr_private *rrpriv, + struct net_device *dev) +{ + int i; + + for (i = 0; i < RX_RING_ENTRIES; i++) { + struct sk_buff *skb = rrpriv->rx_skbuff[i]; + + if (skb) { + struct rx_desc *desc = &(rrpriv->rx_ring[i]); + + pci_unmap_single(rrpriv->pci_dev, desc->addr.addrlo, + dev->mtu + HIPPI_HLEN, PCI_DMA_FROMDEVICE); + desc->size = 0; + set_rraddr(&desc->addr, 0); + dev_kfree_skb(skb); + rrpriv->rx_skbuff[i] = NULL; + } + } +} + static void rr_timer(unsigned long data) { struct net_device *dev = (struct net_device *)data; @@ -1253,49 +1296,6 @@ return ecode; } - -static inline void rr_raz_tx(struct rr_private *rrpriv, - struct net_device *dev) -{ - int i; - - for (i = 0; i < TX_RING_ENTRIES; i++) { - struct sk_buff *skb = rrpriv->tx_skbuff[i]; - - if (skb) { - struct tx_desc *desc = &(rrpriv->tx_ring[i]); - - pci_unmap_single(rrpriv->pci_dev, desc->addr.addrlo, - skb->len, PCI_DMA_TODEVICE); - desc->size = 0; - set_rraddr(&desc->addr, 0); - dev_kfree_skb(skb); - rrpriv->tx_skbuff[i] = NULL; - } - } -} - - -static inline void rr_raz_rx(struct rr_private *rrpriv, - struct net_device *dev) -{ - int i; - - for (i = 0; i < RX_RING_ENTRIES; i++) { - struct sk_buff *skb = rrpriv->rx_skbuff[i]; - - if (skb) { - struct rx_desc *desc = &(rrpriv->rx_ring[i]); - - pci_unmap_single(rrpriv->pci_dev, desc->addr.addrlo, - dev->mtu + HIPPI_HLEN, PCI_DMA_FROMDEVICE); - desc->size = 0; - set_rraddr(&desc->addr, 0); - dev_kfree_skb(skb); - rrpriv->rx_skbuff[i] = NULL; - } - } -} static void rr_dump(struct net_device *dev) { diff -Nru a/drivers/net/sk98lin/skge.c b/drivers/net/sk98lin/skge.c --- a/drivers/net/sk98lin/skge.c 2004-08-25 22:01:54 -07:00 +++ b/drivers/net/sk98lin/skge.c 2004-08-25 22:01:54 -07:00 @@ -110,10 +110,7 @@ #include #include - -#ifdef CONFIG_PROC_FS #include -#endif #include "h/skdrv1st.h" #include "h/skdrv2nd.h" @@ -5113,9 +5110,12 @@ if ((pAC->GIni.GIMacsFound == 2) && pAC->RlmtNets == 2) have_second_mac = 1; + remove_proc_entry(dev->name, pSkRootDir); unregister_netdev(dev); - if (have_second_mac) + if (have_second_mac) { + remove_proc_entry(pAC->dev[1]->name, pSkRootDir); unregister_netdev(pAC->dev[1]); + } SkGeYellowLED(pAC, pAC->IoBase, 0); @@ -5182,9 +5182,9 @@ { int error; +#ifdef CONFIG_PROC_FS memcpy(&SK_Root_Dir_entry, BOOT_STRING, sizeof(SK_Root_Dir_entry) - 1); -#ifdef CONFIG_PROC_FS pSkRootDir = proc_mkdir(SK_Root_Dir_entry, proc_net); if (!pSkRootDir) { printk(KERN_WARNING "Unable to create /proc/net/%s", diff -Nru a/drivers/net/smc9194.c b/drivers/net/smc9194.c --- a/drivers/net/smc9194.c 2004-08-25 22:01:56 -07:00 +++ b/drivers/net/smc9194.c 2004-08-25 22:01:56 -07:00 @@ -1191,133 +1191,6 @@ netif_wake_queue(dev); } -/*-------------------------------------------------------------------- - . - . This is the main routine of the driver, to handle the device when - . it needs some attention. - . - . So: - . first, save state of the chipset - . branch off into routines to handle each case, and acknowledge - . each to the interrupt register - . and finally restore state. - . - ---------------------------------------------------------------------*/ - -static irqreturn_t smc_interrupt(int irq, void * dev_id, struct pt_regs * regs) -{ - struct net_device *dev = dev_id; - int ioaddr = dev->base_addr; - struct smc_local *lp = netdev_priv(dev); - - byte status; - word card_stats; - byte mask; - int timeout; - /* state registers */ - word saved_bank; - word saved_pointer; - int handled = 0; - - - PRINTK3((CARDNAME": SMC interrupt started \n")); - - saved_bank = inw( ioaddr + BANK_SELECT ); - - SMC_SELECT_BANK(2); - saved_pointer = inw( ioaddr + POINTER ); - - mask = inb( ioaddr + INT_MASK ); - /* clear all interrupts */ - outb( 0, ioaddr + INT_MASK ); - - - /* set a timeout value, so I don't stay here forever */ - timeout = 4; - - PRINTK2((KERN_WARNING CARDNAME ": MASK IS %x \n", mask )); - do { - /* read the status flag, and mask it */ - status = inb( ioaddr + INTERRUPT ) & mask; - if (!status ) - break; - - handled = 1; - - PRINTK3((KERN_WARNING CARDNAME - ": Handling interrupt status %x \n", status )); - - if (status & IM_RCV_INT) { - /* Got a packet(s). */ - PRINTK2((KERN_WARNING CARDNAME - ": Receive Interrupt\n")); - smc_rcv(dev); - } else if (status & IM_TX_INT ) { - PRINTK2((KERN_WARNING CARDNAME - ": TX ERROR handled\n")); - smc_tx(dev); - outb(IM_TX_INT, ioaddr + INTERRUPT ); - } else if (status & IM_TX_EMPTY_INT ) { - /* update stats */ - SMC_SELECT_BANK( 0 ); - card_stats = inw( ioaddr + COUNTER ); - /* single collisions */ - lp->stats.collisions += card_stats & 0xF; - card_stats >>= 4; - /* multiple collisions */ - lp->stats.collisions += card_stats & 0xF; - - /* these are for when linux supports these statistics */ - - SMC_SELECT_BANK( 2 ); - PRINTK2((KERN_WARNING CARDNAME - ": TX_BUFFER_EMPTY handled\n")); - outb( IM_TX_EMPTY_INT, ioaddr + INTERRUPT ); - mask &= ~IM_TX_EMPTY_INT; - lp->stats.tx_packets += lp->packets_waiting; - lp->packets_waiting = 0; - - } else if (status & IM_ALLOC_INT ) { - PRINTK2((KERN_DEBUG CARDNAME - ": Allocation interrupt \n")); - /* clear this interrupt so it doesn't happen again */ - mask &= ~IM_ALLOC_INT; - - smc_hardware_send_packet( dev ); - - /* enable xmit interrupts based on this */ - mask |= ( IM_TX_EMPTY_INT | IM_TX_INT ); - - /* and let the card send more packets to me */ - netif_wake_queue(dev); - - PRINTK2((CARDNAME": Handoff done successfully.\n")); - } else if (status & IM_RX_OVRN_INT ) { - lp->stats.rx_errors++; - lp->stats.rx_fifo_errors++; - outb( IM_RX_OVRN_INT, ioaddr + INTERRUPT ); - } else if (status & IM_EPH_INT ) { - PRINTK((CARDNAME ": UNSUPPORTED: EPH INTERRUPT \n")); - } else if (status & IM_ERCV_INT ) { - PRINTK((CARDNAME ": UNSUPPORTED: ERCV INTERRUPT \n")); - outb( IM_ERCV_INT, ioaddr + INTERRUPT ); - } - } while ( timeout -- ); - - - /* restore state register */ - SMC_SELECT_BANK( 2 ); - outb( mask, ioaddr + INT_MASK ); - - PRINTK3(( KERN_WARNING CARDNAME ": MASK is now %x \n", mask )); - outw( saved_pointer, ioaddr + POINTER ); - - SMC_SELECT_BANK( saved_bank ); - - PRINTK3((CARDNAME ": Interrupt done\n")); - return IRQ_RETVAL(handled); -} - /*------------------------------------------------------------- . . smc_rcv - receive a packet from the card @@ -1508,6 +1381,134 @@ outb( saved_packet, ioaddr + PNR_ARR ); return; } + +/*-------------------------------------------------------------------- + . + . This is the main routine of the driver, to handle the device when + . it needs some attention. + . + . So: + . first, save state of the chipset + . branch off into routines to handle each case, and acknowledge + . each to the interrupt register + . and finally restore state. + . + ---------------------------------------------------------------------*/ + +static irqreturn_t smc_interrupt(int irq, void * dev_id, struct pt_regs * regs) +{ + struct net_device *dev = dev_id; + int ioaddr = dev->base_addr; + struct smc_local *lp = netdev_priv(dev); + + byte status; + word card_stats; + byte mask; + int timeout; + /* state registers */ + word saved_bank; + word saved_pointer; + int handled = 0; + + + PRINTK3((CARDNAME": SMC interrupt started \n")); + + saved_bank = inw( ioaddr + BANK_SELECT ); + + SMC_SELECT_BANK(2); + saved_pointer = inw( ioaddr + POINTER ); + + mask = inb( ioaddr + INT_MASK ); + /* clear all interrupts */ + outb( 0, ioaddr + INT_MASK ); + + + /* set a timeout value, so I don't stay here forever */ + timeout = 4; + + PRINTK2((KERN_WARNING CARDNAME ": MASK IS %x \n", mask )); + do { + /* read the status flag, and mask it */ + status = inb( ioaddr + INTERRUPT ) & mask; + if (!status ) + break; + + handled = 1; + + PRINTK3((KERN_WARNING CARDNAME + ": Handling interrupt status %x \n", status )); + + if (status & IM_RCV_INT) { + /* Got a packet(s). */ + PRINTK2((KERN_WARNING CARDNAME + ": Receive Interrupt\n")); + smc_rcv(dev); + } else if (status & IM_TX_INT ) { + PRINTK2((KERN_WARNING CARDNAME + ": TX ERROR handled\n")); + smc_tx(dev); + outb(IM_TX_INT, ioaddr + INTERRUPT ); + } else if (status & IM_TX_EMPTY_INT ) { + /* update stats */ + SMC_SELECT_BANK( 0 ); + card_stats = inw( ioaddr + COUNTER ); + /* single collisions */ + lp->stats.collisions += card_stats & 0xF; + card_stats >>= 4; + /* multiple collisions */ + lp->stats.collisions += card_stats & 0xF; + + /* these are for when linux supports these statistics */ + + SMC_SELECT_BANK( 2 ); + PRINTK2((KERN_WARNING CARDNAME + ": TX_BUFFER_EMPTY handled\n")); + outb( IM_TX_EMPTY_INT, ioaddr + INTERRUPT ); + mask &= ~IM_TX_EMPTY_INT; + lp->stats.tx_packets += lp->packets_waiting; + lp->packets_waiting = 0; + + } else if (status & IM_ALLOC_INT ) { + PRINTK2((KERN_DEBUG CARDNAME + ": Allocation interrupt \n")); + /* clear this interrupt so it doesn't happen again */ + mask &= ~IM_ALLOC_INT; + + smc_hardware_send_packet( dev ); + + /* enable xmit interrupts based on this */ + mask |= ( IM_TX_EMPTY_INT | IM_TX_INT ); + + /* and let the card send more packets to me */ + netif_wake_queue(dev); + + PRINTK2((CARDNAME": Handoff done successfully.\n")); + } else if (status & IM_RX_OVRN_INT ) { + lp->stats.rx_errors++; + lp->stats.rx_fifo_errors++; + outb( IM_RX_OVRN_INT, ioaddr + INTERRUPT ); + } else if (status & IM_EPH_INT ) { + PRINTK((CARDNAME ": UNSUPPORTED: EPH INTERRUPT \n")); + } else if (status & IM_ERCV_INT ) { + PRINTK((CARDNAME ": UNSUPPORTED: ERCV INTERRUPT \n")); + outb( IM_ERCV_INT, ioaddr + INTERRUPT ); + } + } while ( timeout -- ); + + + /* restore state register */ + SMC_SELECT_BANK( 2 ); + outb( mask, ioaddr + INT_MASK ); + + PRINTK3(( KERN_WARNING CARDNAME ": MASK is now %x \n", mask )); + outw( saved_pointer, ioaddr + POINTER ); + + SMC_SELECT_BANK( saved_bank ); + + PRINTK3((CARDNAME ": Interrupt done\n")); + return IRQ_RETVAL(handled); +} + /*---------------------------------------------------- . smc_close diff -Nru a/drivers/net/sundance.c b/drivers/net/sundance.c --- a/drivers/net/sundance.c 2004-08-25 22:01:55 -07:00 +++ b/drivers/net/sundance.c 2004-08-25 22:01:55 -07:00 @@ -879,7 +879,7 @@ if (dev->if_port == 0) dev->if_port = np->default_port; - np->mcastlock = (spinlock_t) SPIN_LOCK_UNLOCKED; + np->mcastlock = SPIN_LOCK_UNLOCKED; set_rx_mode(dev); writew(0, ioaddr + IntrEnable); diff -Nru a/drivers/net/tokenring/ibmtr.c b/drivers/net/tokenring/ibmtr.c --- a/drivers/net/tokenring/ibmtr.c 2004-08-25 22:01:55 -07:00 +++ b/drivers/net/tokenring/ibmtr.c 2004-08-25 22:01:55 -07:00 @@ -895,7 +895,7 @@ ti->sram_virt &= ~1; /* to reverse what we do in tok_close */ /* init the spinlock */ - ti->lock = (spinlock_t) SPIN_LOCK_UNLOCKED; + ti->lock = SPIN_LOCK_UNLOCKED; init_timer(&ti->tr_timer); i = tok_init_card(dev); diff -Nru a/drivers/net/tulip/de4x5.c b/drivers/net/tulip/de4x5.c --- a/drivers/net/tulip/de4x5.c 2004-08-25 22:01:54 -07:00 +++ b/drivers/net/tulip/de4x5.c 2004-08-25 22:01:54 -07:00 @@ -1141,7 +1141,7 @@ lp->asBitValid = TRUE; lp->timeout = -1; lp->gendev = gendev; - lp->lock = (spinlock_t) SPIN_LOCK_UNLOCKED; + lp->lock = SPIN_LOCK_UNLOCKED; init_timer(&lp->timer); de4x5_parse_params(dev); @@ -1316,7 +1316,7 @@ ** Re-initialize the DE4X5... */ status = de4x5_init(dev); - lp->lock = (spinlock_t) SPIN_LOCK_UNLOCKED; + lp->lock = SPIN_LOCK_UNLOCKED; lp->state = OPEN; de4x5_dbg_open(dev); @@ -2242,8 +2242,13 @@ return -ENODEV; /* Ok, the device seems to be for us. */ - if (!(dev = alloc_etherdev (sizeof (struct de4x5_private)))) - return -ENOMEM; + if (pci_enable_device (pdev)) + return -ENODEV; + + if (!(dev = alloc_etherdev (sizeof (struct de4x5_private)))) { + error = -ENOMEM; + goto disable_dev; + } lp = netdev_priv(dev); lp->bus = PCI; @@ -2327,6 +2332,8 @@ release_region (iobase, DE4X5_PCI_TOTAL_SIZE); free_dev: free_netdev (dev); + disable_dev: + pci_disable_device (pdev); return error; } @@ -2341,6 +2348,7 @@ unregister_netdev (dev); free_netdev (dev); release_region (iobase, DE4X5_PCI_TOTAL_SIZE); + pci_disable_device (pdev); } static struct pci_device_id de4x5_pci_tbl[] = { diff -Nru a/drivers/net/tulip/dmfe.c b/drivers/net/tulip/dmfe.c --- a/drivers/net/tulip/dmfe.c 2004-08-25 22:01:56 -07:00 +++ b/drivers/net/tulip/dmfe.c 2004-08-25 22:01:56 -07:00 @@ -314,13 +314,13 @@ static u8 dmfe_sense_speed(struct dmfe_board_info *); static void dmfe_process_mode(struct dmfe_board_info *); static void dmfe_timer(unsigned long); +static inline u32 cal_CRC(unsigned char *, unsigned int, u8); static void dmfe_rx_packet(struct DEVICE *, struct dmfe_board_info *); static void dmfe_free_tx_pkt(struct DEVICE *, struct dmfe_board_info *); static void dmfe_reuse_skb(struct dmfe_board_info *, struct sk_buff *); static void dmfe_dynamic_reset(struct DEVICE *); static void dmfe_free_rxbuffer(struct dmfe_board_info *); static void dmfe_init_dm910x(struct DEVICE *); -static inline u32 cal_CRC(unsigned char *, unsigned int, u8); static void dmfe_parse_srom(struct dmfe_board_info *); static void dmfe_program_DM9801(struct dmfe_board_info *, int); static void dmfe_program_DM9802(struct dmfe_board_info *); @@ -885,6 +885,20 @@ /* + * Calculate the CRC valude of the Rx packet + * flag = 1 : return the reverse CRC (for the received packet CRC) + * 0 : return the normal CRC (for Hash Table index) + */ + +static inline u32 cal_CRC(unsigned char * Data, unsigned int Len, u8 flag) +{ + u32 crc = crc32(~0, Data, Len); + if (flag) crc = ~crc; + return crc; +} + + +/* * Receive the come packet and pass to upper layer */ @@ -1770,20 +1784,6 @@ udelay(1); return phy_data; -} - - -/* - * Calculate the CRC valude of the Rx packet - * flag = 1 : return the reverse CRC (for the received packet CRC) - * 0 : return the normal CRC (for Hash Table index) - */ - -static inline u32 cal_CRC(unsigned char * Data, unsigned int Len, u8 flag) -{ - u32 crc = crc32(~0, Data, Len); - if (flag) crc = ~crc; - return crc; } diff -Nru a/drivers/net/via-rhine.c b/drivers/net/via-rhine.c --- a/drivers/net/via-rhine.c 2004-08-25 22:01:56 -07:00 +++ b/drivers/net/via-rhine.c 2004-08-25 22:01:56 -07:00 @@ -346,7 +346,7 @@ VT6105L = 0x8A, VT6107 = 0x8C, VTunknown2 = 0x8E, - VT6105M = 0x90, + VT6105M = 0x90, /* Management adapter */ }; enum rhine_quirks { @@ -485,6 +485,7 @@ dma_addr_t tx_bufs_dma; struct pci_dev *pdev; + long pioaddr; struct net_device_stats stats; spinlock_t lock; @@ -593,7 +594,7 @@ default: reason = "Unknown"; } - printk("%s: Woke system up. Reason: %s.\n", + printk(KERN_INFO "%s: Woke system up. Reason: %s.\n", DRV_NAME, reason); } } @@ -703,7 +704,7 @@ long memaddr; long ioaddr; int io_size, phy_id; - const char *name, *mname; + const char *name; /* when built into the kernel, we only print version if device is found */ #ifndef MODULE @@ -718,41 +719,24 @@ phy_id = 0; quirks = 0; name = "Rhine"; - mname = "unknown"; if (pci_rev < VTunknown0) { quirks = rqRhineI; io_size = 128; - mname = "VT86C100A"; } else if (pci_rev >= VT6102) { quirks = rqWOL | rqForceReset; if (pci_rev < VT6105) { name = "Rhine II"; quirks |= rqStatusWBRace; /* Rhine-II exclusive */ - if (pci_rev < VT8231) - mname = "VT6102"; - else if (pci_rev < VT8233) - mname = "VT8231"; - else if (pci_rev < VT8235) - mname = "VT8233"; - else if (pci_rev < VT8237) - mname = "VT8235"; - else if (pci_rev < VTunknown1) - mname = "VT8237"; } else { - name = "Rhine III"; phy_id = 1; /* Integrated PHY, phy_id fixed to 1 */ if (pci_rev >= VT6105_B0) quirks |= rq6patterns; - if (pci_rev < VT6105L) - mname = "VT6105"; - else if (pci_rev < VT6107) - mname = "VT6105L"; - else if (pci_rev < VT6105M) - mname = "VT6107"; - else if (pci_rev >= VT6105M) - mname = "Management Adapter VT6105M"; + if (pci_rev < VT6105M) + name = "Rhine III"; + else + name = "Rhine III (Management Adapter)"; } } @@ -790,6 +774,11 @@ SET_MODULE_OWNER(dev); SET_NETDEV_DEV(dev, &pdev->dev); + rp = netdev_priv(dev); + rp->quirks = quirks; + rp->pioaddr = pioaddr; + rp->pdev = pdev; + rc = pci_request_regions(pdev, DRV_NAME); if (rc) goto err_out_free_netdev; @@ -823,8 +812,6 @@ #endif /* USE_MMIO */ dev->base_addr = ioaddr; - rp = netdev_priv(dev); - rp->quirks = quirks; /* Get chip registers into a sane state */ rhine_power_init(dev); @@ -846,7 +833,6 @@ dev->irq = pdev->irq; spin_lock_init(&rp->lock); - rp->pdev = pdev; rp->mii_if.dev = dev; rp->mii_if.mdio_read = mdio_read; rp->mii_if.mdio_write = mdio_write; @@ -874,8 +860,8 @@ if (rc) goto err_out_unmap; - printk(KERN_INFO "%s: VIA %s (%s) at 0x%lx, ", - dev->name, name, mname, + printk(KERN_INFO "%s: VIA %s at 0x%lx, ", + dev->name, name, #ifdef USE_MMIO memaddr #else @@ -890,7 +876,10 @@ pci_set_drvdata(pdev, dev); { + u16 mii_cmd; int mii_status = mdio_read(dev, phy_id, 1); + mii_cmd = mdio_read(dev, phy_id, MII_BMCR) & ~BMCR_ISOLATE; + mdio_write(dev, phy_id, MII_BMCR, mii_cmd); if (mii_status != 0xffff && mii_status != 0x0000) { rp->mii_if.advertising = mdio_read(dev, phy_id, 4); printk(KERN_INFO "%s: MII PHY found at address " @@ -1172,7 +1161,7 @@ rhine_disable_linkmon(ioaddr, rp->quirks); - writeb(0, ioaddr + MIICmd); + /* rhine_disable_linkmon already cleared MIICmd */ writeb(phy_id, ioaddr + MIIPhyAddr); writeb(regnum, ioaddr + MIIRegAddr); writeb(0x40, ioaddr + MIICmd); /* Trigger read */ @@ -1190,7 +1179,7 @@ rhine_disable_linkmon(ioaddr, rp->quirks); - writeb(0, ioaddr + MIICmd); + /* rhine_disable_linkmon already cleared MIICmd */ writeb(phy_id, ioaddr + MIIPhyAddr); writeb(regnum, ioaddr + MIIRegAddr); writew(value, ioaddr + MIIData); @@ -1951,11 +1940,70 @@ } +#ifdef CONFIG_PM +static int rhine_suspend(struct pci_dev *pdev, u32 state) +{ + struct net_device *dev = pci_get_drvdata(pdev); + struct rhine_private *rp = netdev_priv(dev); + unsigned long flags; + + if (!netif_running(dev)) + return 0; + + netif_device_detach(dev); + pci_save_state(pdev, pdev->saved_config_space); + + spin_lock_irqsave(&rp->lock, flags); + rhine_shutdown(&pdev->dev); + spin_unlock_irqrestore(&rp->lock, flags); + + return 0; +} + +static int rhine_resume(struct pci_dev *pdev) +{ + struct net_device *dev = pci_get_drvdata(pdev); + struct rhine_private *rp = netdev_priv(dev); + unsigned long flags; + int ret; + + if (!netif_running(dev)) + return 0; + + ret = pci_set_power_state(pdev, 0); + if (debug > 1) + printk(KERN_INFO "%s: Entering power state D0 %s (%d).\n", + dev->name, ret ? "failed" : "succeeded", ret); + + pci_restore_state(pdev, pdev->saved_config_space); + + spin_lock_irqsave(&rp->lock, flags); +#ifdef USE_MMIO + enable_mmio(rp->pioaddr, rp->quirks); +#endif + rhine_power_init(dev); + free_tbufs(dev); + free_rbufs(dev); + alloc_tbufs(dev); + alloc_rbufs(dev); + init_registers(dev); + spin_unlock_irqrestore(&rp->lock, flags); + + netif_device_attach(dev); + + return 0; +} +#endif /* CONFIG_PM */ + static struct pci_driver rhine_driver = { .name = DRV_NAME, .id_table = rhine_pci_tbl, .probe = rhine_init_one, .remove = __devexit_p(rhine_remove_one), +#ifdef CONFIG_PM + .suspend = rhine_suspend, + .resume = rhine_resume, +#endif /* CONFIG_PM */ .driver = { .shutdown = rhine_shutdown, } diff -Nru a/drivers/net/via-velocity.c b/drivers/net/via-velocity.c --- a/drivers/net/via-velocity.c 2004-08-25 22:01:56 -07:00 +++ b/drivers/net/via-velocity.c 2004-08-25 22:01:56 -07:00 @@ -262,6 +262,7 @@ static int velocity_set_media_mode(struct velocity_info *vptr, u32 mii_status); #ifdef CONFIG_PM + static int velocity_suspend(struct pci_dev *pdev, u32 state); static int velocity_resume(struct pci_dev *pdev); @@ -270,9 +271,26 @@ static struct notifier_block velocity_inetaddr_notifier = { .notifier_call = velocity_netdev_event, }; -static int velocity_notifier_registered; -#endif /* CONFIG_PM */ +static spinlock_t velocity_dev_list_lock = SPIN_LOCK_UNLOCKED; +static LIST_HEAD(velocity_dev_list); + +static void velocity_register_notifier(void) +{ + register_inetaddr_notifier(&velocity_inetaddr_notifier); +} + +static void velocity_unregister_notifier(void) +{ + unregister_inetaddr_notifier(&velocity_inetaddr_notifier); +} + +#else /* CONFIG_PM */ + +#define velocity_register_notifier() do {} while (0) +#define velocity_unregister_notifier() do {} while (0) + +#endif /* !CONFIG_PM */ /* * Internal board variants. At the moment we have only one @@ -327,6 +345,14 @@ struct net_device *dev = pci_get_drvdata(pdev); struct velocity_info *vptr = dev->priv; +#ifdef CONFIG_PM + unsigned long flags; + + spin_lock_irqsave(&velocity_dev_list_lock, flags); + if (!list_empty(&velocity_dev_list)) + list_del(&vptr->list); + spin_unlock_irqrestore(&velocity_dev_list_lock, flags); +#endif unregister_netdev(dev); iounmap(vptr->mac_regs); pci_release_regions(pdev); @@ -782,13 +808,16 @@ /* and leave the chip powered down */ pci_set_power_state(pdev, 3); -out: #ifdef CONFIG_PM - if (ret == 0 && !velocity_notifier_registered) { - velocity_notifier_registered = 1; - register_inetaddr_notifier(&velocity_inetaddr_notifier); + { + unsigned long flags; + + spin_lock_irqsave(&velocity_dev_list_lock, flags); + list_add(&vptr->list, &velocity_dev_list); + spin_unlock_irqrestore(&velocity_dev_list_lock, flags); } #endif +out: return ret; err_iounmap: @@ -843,6 +872,8 @@ spin_lock_init(&vptr->lock); spin_lock_init(&vptr->xmit_lock); + + INIT_LIST_HEAD(&vptr->list); } /** @@ -2211,8 +2242,11 @@ static int __init velocity_init_module(void) { int ret; - ret = pci_module_init(&velocity_driver); + velocity_register_notifier(); + ret = pci_module_init(&velocity_driver); + if (ret < 0) + velocity_unregister_notifier(); return ret; } @@ -2227,12 +2261,7 @@ static void __exit velocity_cleanup_module(void) { -#ifdef CONFIG_PM - if (velocity_notifier_registered) { - unregister_inetaddr_notifier(&velocity_inetaddr_notifier); - velocity_notifier_registered = 0; - } -#endif + velocity_unregister_notifier(); pci_unregister_driver(&velocity_driver); } @@ -3252,13 +3281,20 @@ static int velocity_netdev_event(struct notifier_block *nb, unsigned long notification, void *ptr) { struct in_ifaddr *ifa = (struct in_ifaddr *) ptr; - struct net_device *dev; - struct velocity_info *vptr; if (ifa) { - dev = ifa->ifa_dev->dev; - vptr = dev->priv; - velocity_get_ip(vptr); + struct net_device *dev = ifa->ifa_dev->dev; + struct velocity_info *vptr; + unsigned long flags; + + spin_lock_irqsave(&velocity_dev_list_lock, flags); + list_for_each_entry(vptr, &velocity_dev_list, list) { + if (vptr->dev == dev) { + velocity_get_ip(vptr); + break; + } + } + spin_unlock_irqrestore(&velocity_dev_list_lock, flags); } return NOTIFY_DONE; } diff -Nru a/drivers/net/via-velocity.h b/drivers/net/via-velocity.h --- a/drivers/net/via-velocity.h 2004-08-25 22:01:56 -07:00 +++ b/drivers/net/via-velocity.h 2004-08-25 22:01:56 -07:00 @@ -1733,8 +1733,7 @@ }; struct velocity_info { - struct velocity_info *next; - struct velocity_info *prev; + struct list_head list; struct pci_dev *pdev; struct net_device *dev; diff -Nru a/drivers/net/wan/cycx_x25.c b/drivers/net/wan/cycx_x25.c --- a/drivers/net/wan/cycx_x25.c 2004-08-25 22:01:54 -07:00 +++ b/drivers/net/wan/cycx_x25.c 2004-08-25 22:01:54 -07:00 @@ -186,7 +186,7 @@ reset_timer(struct net_device *dev); static u8 bps_to_speed_code(u32 bps); -static u8 log2(u32 n); +static u8 cycx_log2(u32 n); static unsigned dec_to_uint(u8 *str, int len); @@ -263,7 +263,7 @@ else card->wandev.mtu = 64; - cfg.pktlen = log2(card->wandev.mtu); + cfg.pktlen = cycx_log2(card->wandev.mtu); if (conf->station == WANOPT_DTE) { cfg.locaddr = 3; /* DTE */ @@ -1513,7 +1513,7 @@ } /* log base 2 */ -static u8 log2(u32 n) +static u8 cycx_log2(u32 n) { u8 log = 0; diff -Nru a/drivers/parisc/lasi.c b/drivers/parisc/lasi.c --- a/drivers/parisc/lasi.c 2004-08-25 22:01:55 -07:00 +++ b/drivers/parisc/lasi.c 2004-08-25 22:01:55 -07:00 @@ -11,7 +11,7 @@ * (at your option) any later version. * * by Alan Cox and - * Alex deVries + * Alex deVries */ #include diff -Nru a/drivers/parisc/superio.c b/drivers/parisc/superio.c --- a/drivers/parisc/superio.c 2004-08-25 22:01:55 -07:00 +++ b/drivers/parisc/superio.c 2004-08-25 22:01:55 -07:00 @@ -8,7 +8,7 @@ * (C) Copyright 2000 Linuxcare, Inc. * (C) Copyright 2000 Linuxcare Canada, Inc. * (C) Copyright 2000 Martin K. Petersen - * (C) Copyright 2000 Alex deVries + * (C) Copyright 2000 Alex deVries * (C) Copyright 2001 John Marvin * (C) Copyright 2003 Grant Grundler * diff -Nru a/drivers/pci/hotplug/acpiphp_core.c b/drivers/pci/hotplug/acpiphp_core.c --- a/drivers/pci/hotplug/acpiphp_core.c 2004-08-25 22:01:55 -07:00 +++ b/drivers/pci/hotplug/acpiphp_core.c 2004-08-25 22:01:55 -07:00 @@ -61,7 +61,7 @@ MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); MODULE_PARM_DESC(debug, "Debugging mode enabled or not"); -module_param(debug, bool, 644); +module_param(debug, bool, 0644); /* export the attention callback registration methods */ EXPORT_SYMBOL_GPL(acpiphp_register_attention); diff -Nru a/drivers/pci/hotplug/cpcihp_zt5550.c b/drivers/pci/hotplug/cpcihp_zt5550.c --- a/drivers/pci/hotplug/cpcihp_zt5550.c 2004-08-25 22:01:55 -07:00 +++ b/drivers/pci/hotplug/cpcihp_zt5550.c 2004-08-25 22:01:55 -07:00 @@ -298,7 +298,7 @@ MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); -module_param(debug, bool, 644); +module_param(debug, bool, 0644); MODULE_PARM_DESC(debug, "Debugging mode enabled or not"); -module_param(poll, bool, 644); +module_param(poll, bool, 0644); MODULE_PARM_DESC(poll, "#ENUM polling mode enabled or not"); diff -Nru a/drivers/pci/hotplug/cpqphp_core.c b/drivers/pci/hotplug/cpqphp_core.c --- a/drivers/pci/hotplug/cpqphp_core.c 2004-08-25 22:01:54 -07:00 +++ b/drivers/pci/hotplug/cpqphp_core.c 2004-08-25 22:01:54 -07:00 @@ -69,10 +69,10 @@ MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); -module_param(power_mode, bool, 644); +module_param(power_mode, bool, 0644); MODULE_PARM_DESC(power_mode, "Power mode enabled or not"); -module_param(debug, bool, 644); +module_param(debug, bool, 0644); MODULE_PARM_DESC(debug, "Debugging mode enabled or not"); #define CPQHPC_MODULE_MINOR 208 diff -Nru a/drivers/pci/hotplug/pci_hotplug_core.c b/drivers/pci/hotplug/pci_hotplug_core.c --- a/drivers/pci/hotplug/pci_hotplug_core.c 2004-08-25 22:01:56 -07:00 +++ b/drivers/pci/hotplug/pci_hotplug_core.c 2004-08-25 22:01:56 -07:00 @@ -701,7 +701,7 @@ MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); -module_param(debug, bool, 644); +module_param(debug, bool, 0644); MODULE_PARM_DESC(debug, "Debugging mode enabled or not"); EXPORT_SYMBOL_GPL(pci_hotplug_slots_subsys); diff -Nru a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c --- a/drivers/pci/hotplug/pciehp_core.c 2004-08-25 22:01:54 -07:00 +++ b/drivers/pci/hotplug/pciehp_core.c 2004-08-25 22:01:54 -07:00 @@ -57,9 +57,9 @@ MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); -module_param(pciehp_debug, bool, 644); -module_param(pciehp_poll_mode, bool, 644); -module_param(pciehp_poll_time, int, 644); +module_param(pciehp_debug, bool, 0644); +module_param(pciehp_poll_mode, bool, 0644); +module_param(pciehp_poll_time, int, 0644); MODULE_PARM_DESC(pciehp_debug, "Debugging mode enabled or not"); MODULE_PARM_DESC(pciehp_poll_mode, "Using polling mechanism for hot-plug events or not"); MODULE_PARM_DESC(pciehp_poll_time, "Polling mechanism frequency, in seconds"); diff -Nru a/drivers/pci/hotplug/pcihp_skeleton.c b/drivers/pci/hotplug/pcihp_skeleton.c --- a/drivers/pci/hotplug/pcihp_skeleton.c 2004-08-25 22:01:55 -07:00 +++ b/drivers/pci/hotplug/pcihp_skeleton.c 2004-08-25 22:01:55 -07:00 @@ -70,7 +70,7 @@ MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); -module_param(debug, bool, 644); +module_param(debug, bool, 0644); MODULE_PARM_DESC(debug, "Debugging mode enabled or not"); static int enable_slot (struct hotplug_slot *slot); diff -Nru a/drivers/pci/hotplug/shpchp_core.c b/drivers/pci/hotplug/shpchp_core.c --- a/drivers/pci/hotplug/shpchp_core.c 2004-08-25 22:01:54 -07:00 +++ b/drivers/pci/hotplug/shpchp_core.c 2004-08-25 22:01:54 -07:00 @@ -57,9 +57,9 @@ MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); -module_param(shpchp_debug, bool, 644); -module_param(shpchp_poll_mode, bool, 644); -module_param(shpchp_poll_time, int, 644); +module_param(shpchp_debug, bool, 0644); +module_param(shpchp_poll_mode, bool, 0644); +module_param(shpchp_poll_time, int, 0644); MODULE_PARM_DESC(shpchp_debug, "Debugging mode enabled or not"); MODULE_PARM_DESC(shpchp_poll_mode, "Using polling mechanism for hot-plug events or not"); MODULE_PARM_DESC(shpchp_poll_time, "Polling mechanism frequency, in seconds"); diff -Nru a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c --- a/drivers/pci/pci-driver.c 2004-08-25 22:01:55 -07:00 +++ b/drivers/pci/pci-driver.c 2004-08-25 22:01:55 -07:00 @@ -390,10 +390,9 @@ * pci_register_driver - register a new pci driver * @drv: the driver structure to register * - * Adds the driver structure to the list of registered drivers - * Returns the number of pci devices which were claimed by the driver - * during registration. The driver remains registered even if the - * return value is zero. + * Adds the driver structure to the list of registered drivers. + * Returns a negative value on error. The driver remains registered + * even if no device was claimed during registration. */ int pci_register_driver(struct pci_driver *drv) diff -Nru a/drivers/pci/probe.c b/drivers/pci/probe.c --- a/drivers/pci/probe.c 2004-08-25 22:01:55 -07:00 +++ b/drivers/pci/probe.c 2004-08-25 22:01:55 -07:00 @@ -571,6 +571,11 @@ return PCI_CFG_SPACE_SIZE; } +static void pci_release_bus_bridge_dev(struct device *dev) +{ + kfree(dev); +} + /* * Read the config data for a PCI device, sanity-check it * and fill in the dev structure... @@ -772,6 +777,7 @@ memset(dev, 0, sizeof(*dev)); dev->parent = parent; + dev->release = pci_release_bus_bridge_dev; sprintf(dev->bus_id, "pci%04x:%02x", pci_domain_nr(b), bus); device_register(dev); b->bridge = get_device(dev); diff -Nru a/drivers/pci/remove.c b/drivers/pci/remove.c --- a/drivers/pci/remove.c 2004-08-25 22:01:54 -07:00 +++ b/drivers/pci/remove.c 2004-08-25 22:01:54 -07:00 @@ -59,6 +59,18 @@ } EXPORT_SYMBOL(pci_remove_device_safe); +void pci_remove_bus(struct pci_bus *b) +{ + pci_proc_detach_bus(b); + + spin_lock(&pci_bus_lock); + list_del(&b->node); + spin_unlock(&pci_bus_lock); + + class_device_unregister(&b->class_dev); +} +EXPORT_SYMBOL(pci_remove_bus); + /** * pci_remove_bus_device - remove a PCI device and any children * @dev: the device to remove @@ -77,13 +89,7 @@ struct pci_bus *b = dev->subordinate; pci_remove_behind_bridge(dev); - pci_proc_detach_bus(b); - - spin_lock(&pci_bus_lock); - list_del(&b->node); - spin_unlock(&pci_bus_lock); - - class_device_unregister(&b->class_dev); + pci_remove_bus(b); dev->subordinate = NULL; } diff -Nru a/drivers/pcmcia/au1000_generic.c b/drivers/pcmcia/au1000_generic.c --- a/drivers/pcmcia/au1000_generic.c 2004-08-25 22:01:55 -07:00 +++ b/drivers/pcmcia/au1000_generic.c 2004-08-25 22:01:55 -07:00 @@ -566,7 +566,6 @@ au1000_pcmcia_set_mem_map(unsigned int sock, struct pccard_mem_map *map) { unsigned int speed; - unsigned long start; u_long flags; if(map->map>=MAX_WIN){ @@ -588,25 +587,19 @@ } spin_lock_irqsave(&pcmcia_lock, flags); - start=map->sys_start; - - if(map->sys_stop==0) - map->sys_stop=MAP_SIZE-1; - if (map->flags & MAP_ATTRIB) { - map->sys_start = pcmcia_socket[sock].phys_attr + + map->static_start = pcmcia_socket[sock].phys_attr + map->card_start; } else { - map->sys_start = pcmcia_socket[sock].phys_mem + + map->static_start = pcmcia_socket[sock].phys_mem + map->card_start; } - map->sys_stop=map->sys_start+(map->sys_stop-start); pcmcia_socket[sock].mem_map[map->map]=*map; spin_unlock_irqrestore(&pcmcia_lock, flags); - debug(3, "set_mem_map %d start %x stop %x card_start %x\n", - map->map, map->sys_start, map->sys_stop, + debug(3, "set_mem_map %d start %x card_start %x\n", + map->map, map->static_start, map->card_start); return 0; diff -Nru a/drivers/pcmcia/cistpl.c b/drivers/pcmcia/cistpl.c --- a/drivers/pcmcia/cistpl.c 2004-08-25 22:01:55 -07:00 +++ b/drivers/pcmcia/cistpl.c 2004-08-25 22:01:55 -07:00 @@ -114,8 +114,6 @@ printk(KERN_NOTICE "cs: unable to map card memory!\n"); return NULL; } - mem->sys_start = mem->res->start; - mem->sys_stop = mem->res->end; s->cis_virt = ioremap(mem->res->start, s->map_size); } mem->card_start = card_offset; @@ -124,7 +122,7 @@ if (s->features & SS_CAP_STATIC_MAP) { if (s->cis_virt) iounmap(s->cis_virt); - s->cis_virt = ioremap(mem->sys_start, s->map_size); + s->cis_virt = ioremap(mem->static_start, s->map_size); } return s->cis_virt; } diff -Nru a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c --- a/drivers/pcmcia/cs.c 2004-08-25 22:01:54 -07:00 +++ b/drivers/pcmcia/cs.c 2004-08-25 22:01:54 -07:00 @@ -1886,11 +1886,6 @@ (*handle)->dev_info, s); if (!win->ctl.res) return CS_IN_USE; - win->ctl.sys_start = win->ctl.res->start; - win->ctl.sys_stop = win->ctl.res->end; - } else { - win->ctl.sys_start = req->Base; - win->ctl.sys_stop = req->Base + req->Size - 1; } (*handle)->state |= CLIENT_WIN_REQ(w); @@ -1912,7 +1907,11 @@ s->state |= SOCKET_WIN_REQ(w); /* Return window handle */ - req->Base = win->ctl.sys_start; + if (s->features & SS_CAP_STATIC_MAP) { + req->Base = win->ctl.static_start; + } else { + req->Base = win->ctl.res->start; + } *wh = win; return CS_SUCCESS; diff -Nru a/drivers/pcmcia/hd64465_ss.c b/drivers/pcmcia/hd64465_ss.c --- a/drivers/pcmcia/hd64465_ss.c 2004-08-25 22:01:55 -07:00 +++ b/drivers/pcmcia/hd64465_ss.c 2004-08-25 22:01:55 -07:00 @@ -636,19 +636,17 @@ hs_socket_t *sp = container_of(s, struct hs_socket_t, socket); struct pccard_mem_map *smem; int map = mem->map; - unsigned long paddr, size; + unsigned long paddr; #if 0 - DPRINTK("hs_set_mem_map(sock=%d, map=%d, flags=0x%x, sys_start=0x%08lx, sys_end=0x%08lx, card_start=0x%08x)\n", - sock, map, mem->flags, mem->sys_start, mem->sys_stop, mem->card_start); + DPRINTK("hs_set_mem_map(sock=%d, map=%d, flags=0x%x, card_start=0x%08x)\n", + sock, map, mem->flags, mem->card_start); #endif if (map >= MAX_WIN) return -EINVAL; smem = &sp->mem_maps[map]; - size = mem->sys_stop - mem->sys_start + 1; - paddr = sp->mem_base; /* base of Attribute mapping */ if (!(mem->flags & MAP_ATTRIB)) paddr += HD64465_PCC_WINDOW; /* base of Common mapping */ @@ -660,8 +658,7 @@ * queries our fixed mapping. I wish this fact had been * documented - Greg Banks. */ - mem->sys_start = paddr; - mem->sys_stop = paddr + size - 1; + mem->static_start = paddr; *smem = *mem; diff -Nru a/drivers/pcmcia/i82092.c b/drivers/pcmcia/i82092.c --- a/drivers/pcmcia/i82092.c 2004-08-25 22:01:56 -07:00 +++ b/drivers/pcmcia/i82092.c 2004-08-25 22:01:56 -07:00 @@ -422,7 +422,7 @@ int i; struct resource res = { .start = 0, .end = 0x0fff }; pccard_io_map io = { 0, 0, 0, 0, 1 }; - pccard_mem_map mem = { .res = &res, .sys_stop = 0x0fff, }; + pccard_mem_map mem = { .res = &res, }; enter("i82092aa_init"); @@ -706,11 +706,15 @@ static int i82092aa_set_mem_map(struct pcmcia_socket *socket, struct pccard_mem_map *mem) { - unsigned int sock = container_of(socket, struct socket_info, socket)->number; + struct socket_info *sock_info = container_of(socket, struct socket_info, socket); + unsigned int sock = sock_info->number; + struct pci_bus_region region; unsigned short base, i; unsigned char map; enter("i82092aa_set_mem_map"); + + pcibios_resource_to_bus(sock_info->dev, ®ion, mem->res); map = mem->map; if (map > 4) { @@ -719,10 +723,10 @@ } - if ( (mem->card_start > 0x3ffffff) || (mem->sys_start > mem->sys_stop) || + if ( (mem->card_start > 0x3ffffff) || (region.start > region.end) || (mem->speed > 1000) ) { leave("i82092aa_set_mem_map: invalid address / speed"); - printk("invalid mem map for socket %i : %lx to %lx with a start of %x \n",sock,mem->sys_start, mem->sys_stop, mem->card_start); + printk("invalid mem map for socket %i : %lx to %lx with a start of %x \n",sock,region.start, region.end, mem->card_start); return -EINVAL; } @@ -731,11 +735,11 @@ indirect_resetbit(sock, I365_ADDRWIN, I365_ENA_MEM(map)); -/* printk("set_mem_map: Setting map %i range to %x - %x on socket %i, speed is %i, active = %i \n",map, mem->sys_start,mem->sys_stop,sock,mem->speed,mem->flags & MAP_ACTIVE); */ +/* printk("set_mem_map: Setting map %i range to %x - %x on socket %i, speed is %i, active = %i \n",map, region.start,region.end,sock,mem->speed,mem->flags & MAP_ACTIVE); */ /* write the start address */ base = I365_MEM(map); - i = (mem->sys_start >> 12) & 0x0fff; + i = (region.start >> 12) & 0x0fff; if (mem->flags & MAP_16BIT) i |= I365_MEM_16BIT; if (mem->flags & MAP_0WS) @@ -744,7 +748,7 @@ /* write the stop address */ - i= (mem->sys_stop >> 12) & 0x0fff; + i= (region.end >> 12) & 0x0fff; switch (to_cycles(mem->speed)) { case 0: break; @@ -763,7 +767,7 @@ /* card start */ - i = ((mem->card_start - mem->sys_start) >> 12) & 0x3fff; + i = ((mem->card_start - region.start) >> 12) & 0x3fff; if (mem->flags & MAP_WRPROT) i |= I365_MEM_WRPROT; if (mem->flags & MAP_ATTRIB) { diff -Nru a/drivers/pcmcia/i82365.c b/drivers/pcmcia/i82365.c --- a/drivers/pcmcia/i82365.c 2004-08-25 22:01:56 -07:00 +++ b/drivers/pcmcia/i82365.c 2004-08-25 22:01:56 -07:00 @@ -1159,13 +1159,13 @@ debug(1, "SetMemMap(%d, %d, %#2.2x, %d ns, %#5.5lx-%#5.5" "lx, %#5.5x)\n", sock, mem->map, mem->flags, mem->speed, - mem->sys_start, mem->sys_stop, mem->card_start); + mem->res->start, mem->res->end, mem->card_start); map = mem->map; if ((map > 4) || (mem->card_start > 0x3ffffff) || - (mem->sys_start > mem->sys_stop) || (mem->speed > 1000)) + (mem->res->start > mem->res->end) || (mem->speed > 1000)) return -EINVAL; - if ((mem->sys_start > 0xffffff) || (mem->sys_stop > 0xffffff)) + if ((mem->res->start > 0xffffff) || (mem->res->end > 0xffffff)) return -EINVAL; /* Turn off the window before changing anything */ @@ -1173,12 +1173,12 @@ i365_bclr(sock, I365_ADDRWIN, I365_ENA_MEM(map)); base = I365_MEM(map); - i = (mem->sys_start >> 12) & 0x0fff; + i = (mem->res->start >> 12) & 0x0fff; if (mem->flags & MAP_16BIT) i |= I365_MEM_16BIT; if (mem->flags & MAP_0WS) i |= I365_MEM_0WS; i365_set_pair(sock, base+I365_W_START, i); - i = (mem->sys_stop >> 12) & 0x0fff; + i = (mem->res->end >> 12) & 0x0fff; switch (to_cycles(mem->speed)) { case 0: break; case 1: i |= I365_MEM_WS0; break; @@ -1187,7 +1187,7 @@ } i365_set_pair(sock, base+I365_W_STOP, i); - i = ((mem->card_start - mem->sys_start) >> 12) & 0x3fff; + i = ((mem->card_start - mem->res->start) >> 12) & 0x3fff; if (mem->flags & MAP_WRPROT) i |= I365_MEM_WRPROT; if (mem->flags & MAP_ATTRIB) i |= I365_MEM_REG; i365_set_pair(sock, base+I365_W_OFF, i); @@ -1309,7 +1309,7 @@ int i; struct resource res = { .start = 0, .end = 0x1000 }; pccard_io_map io = { 0, 0, 0, 0, 1 }; - pccard_mem_map mem = { .res = &res, .sys_stop = 0x1000, }; + pccard_mem_map mem = { .res = &res, }; for (i = 0; i < 2; i++) { io.map = i; diff -Nru a/drivers/pcmcia/pd6729.c b/drivers/pcmcia/pd6729.c --- a/drivers/pcmcia/pd6729.c 2004-08-25 22:01:56 -07:00 +++ b/drivers/pcmcia/pd6729.c 2004-08-25 22:01:56 -07:00 @@ -502,10 +502,10 @@ return -EINVAL; } - if ((mem->sys_start > mem->sys_stop) || (mem->speed > 1000)) { + if ((mem->res->start > mem->res->end) || (mem->speed > 1000)) { printk("pd6729_set_mem_map: invalid address / speed"); /* printk("invalid mem map for socket %i : %lx to %lx with a start of %x\n", - sock, mem->sys_start, mem->sys_stop, mem->card_start); */ + sock, mem->res->start, mem->res->end, mem->card_start); */ return -EINVAL; } @@ -515,7 +515,7 @@ /* write the start address */ base = I365_MEM(map); - i = (mem->sys_start >> 12) & 0x0fff; + i = (mem->res->start >> 12) & 0x0fff; if (mem->flags & MAP_16BIT) i |= I365_MEM_16BIT; if (mem->flags & MAP_0WS) @@ -524,7 +524,7 @@ /* write the stop address */ - i= (mem->sys_stop >> 12) & 0x0fff; + i= (mem->res->end >> 12) & 0x0fff; switch (to_cycles(mem->speed)) { case 0: break; @@ -543,11 +543,11 @@ /* Take care of high byte */ indirect_write(socket, PD67_EXT_INDEX, PD67_MEM_PAGE(map)); - indirect_write(socket, PD67_EXT_DATA, mem->sys_start >> 24); + indirect_write(socket, PD67_EXT_DATA, mem->res->start >> 24); /* card start */ - i = ((mem->card_start - mem->sys_start) >> 12) & 0x3fff; + i = ((mem->card_start - mem->res->start) >> 12) & 0x3fff; if (mem->flags & MAP_WRPROT) i |= I365_MEM_WRPROT; if (mem->flags & MAP_ATTRIB) { @@ -577,7 +577,7 @@ int i; struct resource res = { .end = 0x0fff }; pccard_io_map io = { 0, 0, 0, 0, 1 }; - pccard_mem_map mem = { .res = &res, .sys_stop = 0x0fff }; + pccard_mem_map mem = { .res = &res, }; pd6729_set_socket(sock, &dead_socket); for (i = 0; i < 2; i++) { diff -Nru a/drivers/pcmcia/rsrc_mgr.c b/drivers/pcmcia/rsrc_mgr.c --- a/drivers/pcmcia/rsrc_mgr.c 2004-08-25 22:01:55 -07:00 +++ b/drivers/pcmcia/rsrc_mgr.c 2004-08-25 22:01:55 -07:00 @@ -301,8 +301,6 @@ { int ret = -1; - s->cis_mem.sys_start = res->start; - s->cis_mem.sys_stop = res->end; s->cis_mem.res = res; s->cis_virt = ioremap(res->start, s->map_size); if (s->cis_virt) { @@ -312,8 +310,6 @@ s->cis_virt = NULL; destroy_cis_cache(s); } - s->cis_mem.sys_start = 0; - s->cis_mem.sys_stop = 0; s->cis_mem.res = NULL; if ((ret != 0) || (info->Chains == 0)) return 0; @@ -332,8 +328,6 @@ map.map = 0; map.flags = MAP_ACTIVE; map.speed = 0; - map.sys_start = res->start; - map.sys_stop = res->end; map.res = res; map.card_start = 0; s->ops->set_mem_map(s, &map); diff -Nru a/drivers/pcmcia/soc_common.c b/drivers/pcmcia/soc_common.c --- a/drivers/pcmcia/soc_common.c 2004-08-25 22:01:54 -07:00 +++ b/drivers/pcmcia/soc_common.c 2004-08-25 22:01:54 -07:00 @@ -448,9 +448,7 @@ skt->ops->set_timing(skt); - map->sys_stop -= map->sys_start; - map->sys_stop += res->start + map->card_start; - map->sys_start = res->start + map->card_start; + map->static_start = res->start + map->card_start; return 0; } @@ -662,6 +660,7 @@ int soc_common_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops, int first, int nr) { struct skt_dev_info *sinfo; + struct soc_pcmcia_socket *skt; int ret, i; down(&soc_pcmcia_sockets_lock); @@ -679,7 +678,7 @@ * Initialise the per-socket structure. */ for (i = 0; i < nr; i++) { - struct soc_pcmcia_socket *skt = &sinfo->skt[i]; + skt = &sinfo->skt[i]; skt->socket.ops = &soc_common_pcmcia_operations; skt->socket.owner = ops->owner; @@ -777,7 +776,7 @@ goto out; do { - struct soc_pcmcia_socket *skt = &sinfo->skt[i]; + skt = &sinfo->skt[i]; del_timer_sync(&skt->poll_timer); pcmcia_unregister_socket(&skt->socket); diff -Nru a/drivers/pcmcia/tcic.c b/drivers/pcmcia/tcic.c --- a/drivers/pcmcia/tcic.c 2004-08-25 22:01:55 -07:00 +++ b/drivers/pcmcia/tcic.c 2004-08-25 22:01:55 -07:00 @@ -829,15 +829,15 @@ debug(1, "SetMemMap(%d, %d, %#2.2x, %d ns, " "%#5.5lx-%#5.5lx, %#5.5x)\n", psock, mem->map, mem->flags, - mem->speed, mem->sys_start, mem->sys_stop, mem->card_start); + mem->speed, mem->res->start, mem->res->end, mem->card_start); if ((mem->map > 3) || (mem->card_start > 0x3ffffff) || - (mem->sys_start > 0xffffff) || (mem->sys_stop > 0xffffff) || - (mem->sys_start > mem->sys_stop) || (mem->speed > 1000)) + (mem->res->start > 0xffffff) || (mem->res->end > 0xffffff) || + (mem->res->start > mem->res->end) || (mem->speed > 1000)) return -EINVAL; tcic_setw(TCIC_ADDR+2, TCIC_ADR2_INDREG | (psock << TCIC_SS_SHFT)); addr = TCIC_MWIN(psock, mem->map); - base = mem->sys_start; len = mem->sys_stop - mem->sys_start; + base = mem->res->start; len = mem->res->end - mem->res->start; if ((len & (len+1)) || (base & len)) return -EINVAL; if (len == 0x0fff) base = (base >> TCIC_MBASE_HA_SHFT) | TCIC_MBASE_4K_BIT; @@ -846,7 +846,7 @@ tcic_setw(TCIC_ADDR, addr + TCIC_MBASE_X); tcic_setw(TCIC_DATA, base); - mmap = mem->card_start - mem->sys_start; + mmap = mem->card_start - mem->res->start; mmap = (mmap >> TCIC_MMAP_CA_SHFT) & TCIC_MMAP_CA_MASK; if (mem->flags & MAP_ATTRIB) mmap |= TCIC_MMAP_REG; tcic_setw(TCIC_ADDR, addr + TCIC_MMAP_X); @@ -870,7 +870,7 @@ int i; struct resource res = { .start = 0, .end = 0x1000 }; pccard_io_map io = { 0, 0, 0, 0, 1 }; - pccard_mem_map mem = { .res = &res, .sys_stop = 0x1000, }; + pccard_mem_map mem = { .res = &res, }; for (i = 0; i < 2; i++) { io.map = i; diff -Nru a/drivers/pcmcia/yenta_socket.c b/drivers/pcmcia/yenta_socket.c --- a/drivers/pcmcia/yenta_socket.c 2004-08-25 22:01:55 -07:00 +++ b/drivers/pcmcia/yenta_socket.c 2004-08-25 22:01:55 -07:00 @@ -343,14 +343,17 @@ static int yenta_set_mem_map(struct pcmcia_socket *sock, struct pccard_mem_map *mem) { struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket); + struct pci_bus_region region; int map; unsigned char addr, enable; unsigned int start, stop, card_start; unsigned short word; + pcibios_resource_to_bus(socket->dev, ®ion, mem->res); + map = mem->map; - start = mem->sys_start; - stop = mem->sys_stop; + start = region.start; + stop = region.end; card_start = mem->card_start; if (map > 4 || start > stop || ((start ^ stop) >> 24) || @@ -447,7 +450,7 @@ int i; struct resource res = { .start = 0, .end = 0x0fff }; pccard_io_map io = { 0, 0, 0, 0, 1 }; - pccard_mem_map mem = { .res = &res, .sys_stop = 0x0fff, }; + pccard_mem_map mem = { .res = &res, }; yenta_set_socket(&socket->socket, &dead_socket); for (i = 0; i < 2; i++) { diff -Nru a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c --- a/drivers/s390/scsi/zfcp_aux.c 2004-08-25 22:01:56 -07:00 +++ b/drivers/s390/scsi/zfcp_aux.c 2004-08-25 22:01:56 -07:00 @@ -29,7 +29,7 @@ */ /* this drivers version (do not edit !!! generated and updated by cvs) */ -#define ZFCP_AUX_REVISION "$Revision: 1.115 $" +#define ZFCP_AUX_REVISION "$Revision: 1.121 $" #include "zfcp_ext.h" @@ -48,10 +48,10 @@ static inline int zfcp_sg_list_alloc(struct zfcp_sg_list *, size_t); static inline int zfcp_sg_list_free(struct zfcp_sg_list *); -static inline int zfcp_sg_list_copy_from_user(struct zfcp_sg_list *, void *, - size_t); -static inline int zfcp_sg_list_copy_to_user(void *, struct zfcp_sg_list *, - size_t); +static inline int zfcp_sg_list_copy_from_user(struct zfcp_sg_list *, + void __user *, size_t); +static inline int zfcp_sg_list_copy_to_user(void __user *, + struct zfcp_sg_list *, size_t); static int zfcp_cfdc_dev_ioctl(struct inode *, struct file *, unsigned int, unsigned long); @@ -95,7 +95,7 @@ module_param(loglevel, uint, 0); MODULE_PARM_DESC(loglevel, "log levels, 8 nibbles: " - "(unassigned) ERP QDIO DIO Config FSF SCSI Other, " + "(unassigned) FC ERP QDIO CIO Config FSF SCSI Other, " "levels: 0=none 1=normal 2=devel 3=trace"); #ifdef ZFCP_PRINT_FLAGS @@ -382,7 +382,7 @@ zfcp_cfdc_dev_ioctl(struct inode *inode, struct file *file, unsigned int command, unsigned long buffer) { - struct zfcp_cfdc_sense_data sense_data, *sense_data_user; + struct zfcp_cfdc_sense_data sense_data, __user *sense_data_user; struct zfcp_adapter *adapter = NULL; struct zfcp_fsf_req *fsf_req = NULL; struct zfcp_sg_list *sg_list = NULL; @@ -403,7 +403,7 @@ goto out; } - if ((sense_data_user = (struct zfcp_cfdc_sense_data*)buffer) == NULL) { + if ((sense_data_user = (void __user *) buffer) == NULL) { ZFCP_LOG_INFO("sense data record is required\n"); retval = -EINVAL; goto out; @@ -520,6 +520,12 @@ wait_event(fsf_req->completion_wq, fsf_req->status & ZFCP_STATUS_FSFREQ_COMPLETED); + if ((fsf_req->qtcb->prefix.prot_status != FSF_PROT_GOOD) && + (fsf_req->qtcb->prefix.prot_status != FSF_PROT_FSF_STATUS_PRESENTED)) { + retval = -ENXIO; + goto out; + } + sense_data.fsf_status = fsf_req->qtcb->header.fsf_status; memcpy(&sense_data.fsf_status_qual, &fsf_req->qtcb->header.fsf_status_qual, @@ -637,7 +643,8 @@ * -EFAULT - Memory I/O operation fault */ static inline int -zfcp_sg_list_copy_from_user(struct zfcp_sg_list *sg_list, void *user_buffer, +zfcp_sg_list_copy_from_user(struct zfcp_sg_list *sg_list, + void __user *user_buffer, size_t size) { struct scatterlist *sg; @@ -671,7 +678,8 @@ * -EFAULT - Memory I/O operation fault */ static inline int -zfcp_sg_list_copy_to_user(void *user_buffer, struct zfcp_sg_list *sg_list, +zfcp_sg_list_copy_to_user(void __user *user_buffer, + struct zfcp_sg_list *sg_list, size_t size) { struct scatterlist *sg; @@ -1646,15 +1654,7 @@ ct_iu_req = zfcp_sg_to_address(ct->req); ct_iu_resp = zfcp_sg_to_address(ct->resp); - if (ct_iu_resp->header.revision != ZFCP_CT_REVISION) - goto failed; - if (ct_iu_resp->header.gs_type != ZFCP_CT_DIRECTORY_SERVICE) - goto failed; - if (ct_iu_resp->header.gs_subtype != ZFCP_CT_NAME_SERVER) - goto failed; - if (ct_iu_resp->header.options != ZFCP_CT_SYNCHRONOUS) - goto failed; - if (ct_iu_resp->header.cmd_rsp_code != ZFCP_CT_ACCEPT) { + if (zfcp_check_ct_response(&ct_iu_resp->header)) { /* FIXME: do we need some specific erp entry points */ atomic_set_mask(ZFCP_STATUS_PORT_INVALID_WWPN, &port->status); goto failed; @@ -1675,7 +1675,7 @@ zfcp_get_busid_by_port(port), port->wwpn, port->d_id); goto out; -failed: + failed: ZFCP_LOG_NORMAL("warning: failed gid_pn nameserver request for wwpn " "0x%016Lx for adapter %s\n", port->wwpn, zfcp_get_busid_by_port(port)); @@ -1688,6 +1688,171 @@ out: zfcp_gid_pn_buffers_free(gid_pn); return; +} + +/* reject CT_IU reason codes acc. to FC-GS-4 */ +static const struct zfcp_rc_entry zfcp_ct_rc[] = { + {0x01, "invalid command code"}, + {0x02, "invalid version level"}, + {0x03, "logical error"}, + {0x04, "invalid CT_IU size"}, + {0x05, "logical busy"}, + {0x07, "protocol error"}, + {0x09, "unable to perform command request"}, + {0x0b, "command not supported"}, + {0x0d, "server not available"}, + {0x0e, "session could not be established"}, + {0xff, "vendor specific error"}, + {0, NULL}, +}; + +/* LS_RJT reason codes acc. to FC-FS */ +static const struct zfcp_rc_entry zfcp_ls_rjt_rc[] = { + {0x01, "invalid LS_Command code"}, + {0x03, "logical error"}, + {0x05, "logical busy"}, + {0x07, "protocol error"}, + {0x09, "unable to perform command request"}, + {0x0b, "command not supported"}, + {0x0e, "command already in progress"}, + {0xff, "vendor specific error"}, + {0, NULL}, +}; + +/* reject reason codes according to FC-PH/FC-FS */ +static const struct zfcp_rc_entry zfcp_p_rjt_rc[] = { + {0x01, "invalid D_ID"}, + {0x02, "invalid S_ID"}, + {0x03, "Nx_Port not available, temporary"}, + {0x04, "Nx_Port not available, permament"}, + {0x05, "class not supported"}, + {0x06, "delimiter usage error"}, + {0x07, "TYPE not supported"}, + {0x08, "invalid Link_Control"}, + {0x09, "invalid R_CTL field"}, + {0x0a, "invalid F_CTL field"}, + {0x0b, "invalid OX_ID"}, + {0x0c, "invalid RX_ID"}, + {0x0d, "invalid SEQ_ID"}, + {0x0e, "invalid DF_CTL"}, + {0x0f, "invalid SEQ_CNT"}, + {0x10, "invalid parameter field"}, + {0x11, "exchange error"}, + {0x12, "protocol error"}, + {0x13, "incorrect length"}, + {0x14, "unsupported ACK"}, + {0x15, "class of service not supported by entity at FFFFFE"}, + {0x16, "login required"}, + {0x17, "excessive sequences attempted"}, + {0x18, "unable to establish exchange"}, + {0x1a, "fabric path not available"}, + {0x1b, "invalid VC_ID (class 4)"}, + {0x1c, "invalid CS_CTL field"}, + {0x1d, "insufficient resources for VC (class 4)"}, + {0x1f, "invalid class of service"}, + {0x20, "preemption request rejected"}, + {0x21, "preemption not enabled"}, + {0x22, "multicast error"}, + {0x23, "multicast error terminate"}, + {0x24, "process login required"}, + {0xff, "vendor specific reject"}, + {0, NULL}, +}; + +/** + * zfcp_rc_description - return description for given reaon code + * @code: reason code + * @rc_table: table of reason codes and descriptions + */ +static inline const char * +zfcp_rc_description(u8 code, const struct zfcp_rc_entry *rc_table) +{ + const char *descr = "unknown reason code"; + + do { + if (code == rc_table->code) { + descr = rc_table->description; + break; + } + rc_table++; + } while (rc_table->code && rc_table->description); + + return descr; +} + +/** + * zfcp_check_ct_response - evaluate reason code for CT_IU + * @rjt: response payload to an CT_IU request + * Return: 0 for accept CT_IU, 1 for reject CT_IU or invlid response code + */ +int +zfcp_check_ct_response(struct ct_hdr *rjt) +{ + if (rjt->cmd_rsp_code == ZFCP_CT_ACCEPT) + return 0; + + if (rjt->cmd_rsp_code != ZFCP_CT_REJECT) { + ZFCP_LOG_NORMAL("error: invalid Generic Service command/" + "response code (0x%04hx)\n", + rjt->cmd_rsp_code); + return 1; + } + + ZFCP_LOG_INFO("Generic Service command rejected\n"); + ZFCP_LOG_INFO("%s (0x%02x, 0x%02x, 0x%02x)\n", + zfcp_rc_description(rjt->reason_code, zfcp_ct_rc), + (u32) rjt->reason_code, (u32) rjt->reason_code_expl, + (u32) rjt->vendor_unique); + + return 1; +} + +/** + * zfcp_print_els_rjt - print reject parameter and description for ELS reject + * @rjt_par: reject parameter acc. to FC-PH/FC-FS + * @rc_table: table of reason codes and descriptions + */ +static inline void +zfcp_print_els_rjt(struct zfcp_ls_rjt_par *rjt_par, + const struct zfcp_rc_entry *rc_table) +{ + ZFCP_LOG_INFO("%s (%02x %02x %02x %02x)\n", + zfcp_rc_description(rjt_par->reason_code, rc_table), + (u32) rjt_par->action, (u32) rjt_par->reason_code, + (u32) rjt_par->reason_expl, (u32) rjt_par->vendor_unique); +} + +/** + * zfcp_fsf_handle_els_rjt - evaluate status qualifier/reason code on ELS reject + * @sq: status qualifier word + * @rjt_par: reject parameter as described in FC-PH and FC-FS + * Return: -EROMTEIO for LS_RJT, -EREMCHG for invalid D_ID, -EIO else + */ +int +zfcp_handle_els_rjt(u32 sq, struct zfcp_ls_rjt_par *rjt_par) +{ + int ret = -EIO; + + if (sq == FSF_IOSTAT_NPORT_RJT) { + ZFCP_LOG_INFO("ELS rejected (P_RJT)\n"); + zfcp_print_els_rjt(rjt_par, zfcp_p_rjt_rc); + /* invalid d_id */ + if (rjt_par->reason_code == 0x01) + ret = -EREMCHG; + } else if (sq == FSF_IOSTAT_FABRIC_RJT) { + ZFCP_LOG_INFO("ELS rejected (F_RJT)\n"); + zfcp_print_els_rjt(rjt_par, zfcp_p_rjt_rc); + /* invalid d_id */ + if (rjt_par->reason_code == 0x01) + ret = -EREMCHG; + } else if (sq == FSF_IOSTAT_LS_RJT) { + ZFCP_LOG_INFO("ELS rejected (LS_RJT)\n"); + zfcp_print_els_rjt(rjt_par, zfcp_ls_rjt_rc); + ret = -EREMOTEIO; + } else + ZFCP_LOG_INFO("unexpected SQ: 0x%02x\n", sq); + + return ret; } #undef ZFCP_LOG_AREA diff -Nru a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h --- a/drivers/s390/scsi/zfcp_def.h 2004-08-25 22:01:55 -07:00 +++ b/drivers/s390/scsi/zfcp_def.h 2004-08-25 22:01:55 -07:00 @@ -33,7 +33,7 @@ #define ZFCP_DEF_H /* this drivers version (do not edit !!! generated and updated by cvs) */ -#define ZFCP_DEF_REVISION "$Revision: 1.81 $" +#define ZFCP_DEF_REVISION "$Revision: 1.83 $" /*************************** INCLUDES *****************************************/ @@ -296,13 +296,11 @@ #define ZFCP_LS_RJT_COMMAND_NOT_SUPPORTED 0x0B #define ZFCP_LS_RJT_VENDOR_UNIQUE_ERROR 0xFF -struct zfcp_ls_rjt { - u8 code; - u8 field[3]; - u8 reserved; - u8 reason_code; - u8 reason_expl; - u8 vendor_unique; +struct zfcp_ls_rjt_par { + u8 action; + u8 reason_code; + u8 reason_expl; + u8 vendor_unique; } __attribute__ ((packed)); struct zfcp_ls_rtv { @@ -423,6 +421,11 @@ specific_id; } __attribute__((packed)); +struct zfcp_rc_entry { + u8 code; + const char *description; +}; + /* * FC-GS-2 stuff */ @@ -431,9 +434,9 @@ #define ZFCP_CT_NAME_SERVER 0x02 #define ZFCP_CT_SYNCHRONOUS 0x00 #define ZFCP_CT_GID_PN 0x0121 -#define ZFCP_CT_GA_NXT 0x0100 #define ZFCP_CT_MAX_SIZE 0x1020 #define ZFCP_CT_ACCEPT 0x8002 +#define ZFCP_CT_REJECT 0x8001 /* * FC-GS-4 stuff @@ -851,7 +854,7 @@ struct zfcp_port *port; }; -typedef int (*zfcp_send_els_handler_t)(unsigned long); +typedef void (*zfcp_send_els_handler_t)(unsigned long); /* used to pass parameters to zfcp_send_els() */ /* ToDo merge send_ct() and send_els() and corresponding structs */ diff -Nru a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c --- a/drivers/s390/scsi/zfcp_erp.c 2004-08-25 22:01:54 -07:00 +++ b/drivers/s390/scsi/zfcp_erp.c 2004-08-25 22:01:54 -07:00 @@ -31,12 +31,12 @@ #define ZFCP_LOG_AREA ZFCP_LOG_AREA_ERP /* this drivers version (do not edit !!! generated and updated by cvs) */ -#define ZFCP_ERP_REVISION "$Revision: 1.61 $" +#define ZFCP_ERP_REVISION "$Revision: 1.62 $" #include "zfcp_ext.h" static int zfcp_els(struct zfcp_port *, u8); -static int zfcp_els_handler(unsigned long); +static void zfcp_els_handler(unsigned long); static int zfcp_erp_adapter_reopen_internal(struct zfcp_adapter *, int); static int zfcp_erp_port_forced_reopen_internal(struct zfcp_port *, int); @@ -324,6 +324,7 @@ send_els->completion = NULL; req = zfcp_sg_to_address(send_els->req); + memset(req, 0, PAGE_SIZE); *(u32*)req = 0; *(u8*)req = ls_code; @@ -412,185 +413,99 @@ } -/* - * function: zfcp_els_handler - * - * purpose: Handler for all kind of ELSs - * - * returns: 0 - Operation completed successfuly - * -ENXIO - ELS has been rejected - * -EPERM - Port forced reopen failed +/** + * zfcp_els_handler - handler for ELS commands + * @data: pointer to struct zfcp_send_els + * If ELS failed (LS_RJT or timed out) forced reopen of the port is triggered. */ -int +void zfcp_els_handler(unsigned long data) { struct zfcp_send_els *send_els = (struct zfcp_send_els*)data; struct zfcp_port *port = send_els->port; - struct zfcp_ls_rjt *rjt; struct zfcp_ls_rtv_acc *rtv; struct zfcp_ls_rls_acc *rls; struct zfcp_ls_pdisc_acc *pdisc; struct zfcp_ls_adisc_acc *adisc; void *req, *resp; - u8 req_code, resp_code; - int retval = 0; + u8 req_code; + /* request rejected or timed out */ if (send_els->status != 0) { ZFCP_LOG_NORMAL("ELS request timed out, force physical port " "reopen of port 0x%016Lx on adapter %s\n", port->wwpn, zfcp_get_busid_by_port(port)); debug_text_event(port->adapter->erp_dbf, 3, "forcreop"); - retval = zfcp_erp_port_forced_reopen(port, 0); - if (retval != 0) { + if (zfcp_erp_port_forced_reopen(port, 0)) ZFCP_LOG_NORMAL("reopen of remote port 0x%016Lx " "on adapter %s failed\n", port->wwpn, zfcp_get_busid_by_port(port)); - retval = -EPERM; - } - goto skip_fsfstatus; + goto out; } - req = (void*)((page_to_pfn(send_els->req->page) << PAGE_SHIFT) + send_els->req->offset); - resp = (void*)((page_to_pfn(send_els->resp->page) << PAGE_SHIFT) + send_els->resp->offset); + req = zfcp_sg_to_address(send_els->req); + resp = zfcp_sg_to_address(send_els->resp); req_code = *(u8*)req; - resp_code = *(u8*)resp; - - switch (resp_code) { - - case ZFCP_LS_RJT: - rjt = (struct zfcp_ls_rjt*)resp; - switch (rjt->reason_code) { + switch (req_code) { - case ZFCP_LS_RJT_INVALID_COMMAND_CODE: - ZFCP_LOG_INFO("invalid LS command code " - "(wwpn=0x%016Lx, command=0x%02x)\n", - port->wwpn, req_code); - break; - - case ZFCP_LS_RJT_LOGICAL_ERROR: - ZFCP_LOG_INFO("logical error (wwpn=0x%016Lx, " - "reason_expl=0x%02x)\n", - port->wwpn, rjt->reason_expl); - break; - - case ZFCP_LS_RJT_LOGICAL_BUSY: - ZFCP_LOG_INFO("logical busy (wwpn=0x%016Lx, " - "reason_expl=0x%02x)\n", - port->wwpn, rjt->reason_expl); - break; - - case ZFCP_LS_RJT_PROTOCOL_ERROR: - ZFCP_LOG_INFO("protocol error (wwpn=0x%016Lx, " - "reason_expl=0x%02x)\n", - port->wwpn, rjt->reason_expl); - break; - - case ZFCP_LS_RJT_UNABLE_TO_PERFORM: - ZFCP_LOG_INFO("unable to perform command requested " - "(wwpn=0x%016Lx, reason_expl=0x%02x)\n", - port->wwpn, rjt->reason_expl); - break; - - case ZFCP_LS_RJT_COMMAND_NOT_SUPPORTED: - ZFCP_LOG_INFO("command not supported (wwpn=0x%016Lx, " - "command=0x%02x)\n", - port->wwpn, req_code); - break; - - case ZFCP_LS_RJT_VENDOR_UNIQUE_ERROR: - ZFCP_LOG_INFO("vendor specific error (wwpn=0x%016Lx, " - "vendor_unique=0x%02x)\n", - port->wwpn, rjt->vendor_unique); - break; - - default: - ZFCP_LOG_NORMAL("ELS rejected by remote port 0x%016Lx " - "on adapter %s (reason_code=0x%02x)\n", - port->wwpn, - zfcp_get_busid_by_port(port), - rjt->reason_code); - } - retval = -ENXIO; + case ZFCP_LS_RTV: + rtv = (struct zfcp_ls_rtv_acc*)resp; + ZFCP_LOG_INFO("RTV response from d_id 0x%08x to s_id " + "0x%08x (R_A_TOV=%ds E_D_TOV=%d%cs)\n", + port->d_id, port->adapter->s_id, + rtv->r_a_tov, rtv->e_d_tov, + rtv->qualifier & + ZFCP_LS_RTV_E_D_TOV_FLAG ? 'n' : 'm'); break; - case ZFCP_LS_ACC: - switch (req_code) { + case ZFCP_LS_RLS: + rls = (struct zfcp_ls_rls_acc*)resp; + ZFCP_LOG_INFO("RLS response from d_id 0x%08x to s_id " + "0x%08x (link_failure_count=%u, " + "loss_of_sync_count=%u, " + "loss_of_signal_count=%u, " + "primitive_sequence_protocol_error=%u, " + "invalid_transmition_word=%u, " + "invalid_crc_count=%u)\n", + port->d_id, port->adapter->s_id, + rls->link_failure_count, + rls->loss_of_sync_count, + rls->loss_of_signal_count, + rls->prim_seq_prot_error, + rls->invalid_transmition_word, + rls->invalid_crc_count); + break; - case ZFCP_LS_RTV: - rtv = (struct zfcp_ls_rtv_acc*)resp; - ZFCP_LOG_INFO("RTV response from d_id 0x%08x to s_id " - "0x%08x (R_A_TOV=%ds E_D_TOV=%d%cs)\n", - port->d_id, port->adapter->s_id, - rtv->r_a_tov, rtv->e_d_tov, - rtv->qualifier & - ZFCP_LS_RTV_E_D_TOV_FLAG ? 'n' : 'm'); - break; - - case ZFCP_LS_RLS: - rls = (struct zfcp_ls_rls_acc*)resp; - ZFCP_LOG_INFO("RLS response from d_id 0x%08x to s_id " - "0x%08x (link_failure_count=%u, " - "loss_of_sync_count=%u, " - "loss_of_signal_count=%u, " - "primitive_sequence_protocol_error=%u, " - "invalid_transmition_word=%u, " - "invalid_crc_count=%u)\n", - port->d_id, port->adapter->s_id, - rls->link_failure_count, - rls->loss_of_sync_count, - rls->loss_of_signal_count, - rls->prim_seq_prot_error, - rls->invalid_transmition_word, - rls->invalid_crc_count); - break; - - case ZFCP_LS_PDISC: - pdisc = (struct zfcp_ls_pdisc_acc*)resp; - ZFCP_LOG_INFO("PDISC response from d_id 0x%08x to s_id " - "0x%08x (wwpn=0x%016Lx, wwnn=0x%016Lx, " - "vendor='%-16s')\n", port->d_id, - port->adapter->s_id, pdisc->wwpn, - pdisc->wwnn, pdisc->vendor_version); - break; - - case ZFCP_LS_ADISC: - adisc = (struct zfcp_ls_adisc_acc*)resp; - ZFCP_LOG_INFO("ADISC response from d_id 0x%08x to s_id " - "0x%08x (wwpn=0x%016Lx, wwnn=0x%016Lx, " - "hard_nport_id=0x%08x, " - "nport_id=0x%08x)\n", port->d_id, - port->adapter->s_id, adisc->wwpn, - adisc->wwnn, adisc->hard_nport_id, - adisc->nport_id); - /* FIXME: set wwnn in during open port */ - if (port->wwnn == 0) - port->wwnn = adisc->wwnn; - break; - } + case ZFCP_LS_PDISC: + pdisc = (struct zfcp_ls_pdisc_acc*)resp; + ZFCP_LOG_INFO("PDISC response from d_id 0x%08x to s_id " + "0x%08x (wwpn=0x%016Lx, wwnn=0x%016Lx, " + "vendor='%-16s')\n", port->d_id, + port->adapter->s_id, pdisc->wwpn, + pdisc->wwnn, pdisc->vendor_version); break; - default: - ZFCP_LOG_NORMAL("unknown payload code 0x%02x received for " - "request 0x%02x to d_id 0x%08x, reopen needed " - "for port 0x%016Lx on adapter %s\n", resp_code, - req_code, port->d_id, port->wwpn, - zfcp_get_busid_by_port(port)); - retval = zfcp_erp_port_forced_reopen(port, 0); - if (retval != 0) { - ZFCP_LOG_NORMAL("reopen of remote port 0x%016Lx on " - "adapter %s failed\n", port->wwpn, - zfcp_get_busid_by_port(port)); - retval = -EPERM; - } + case ZFCP_LS_ADISC: + adisc = (struct zfcp_ls_adisc_acc*)resp; + ZFCP_LOG_INFO("ADISC response from d_id 0x%08x to s_id " + "0x%08x (wwpn=0x%016Lx, wwnn=0x%016Lx, " + "hard_nport_id=0x%08x, " + "nport_id=0x%08x)\n", port->d_id, + port->adapter->s_id, adisc->wwpn, + adisc->wwnn, adisc->hard_nport_id, + adisc->nport_id); + /* FIXME: set wwnn in during open port */ + if (port->wwnn == 0) + port->wwnn = adisc->wwnn; + break; } -skip_fsfstatus: + out: __free_pages(send_els->req->page, 0); kfree(send_els->req); kfree(send_els->resp); - - return retval; + kfree(send_els); } diff -Nru a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h --- a/drivers/s390/scsi/zfcp_ext.h 2004-08-25 22:01:54 -07:00 +++ b/drivers/s390/scsi/zfcp_ext.h 2004-08-25 22:01:54 -07:00 @@ -31,7 +31,7 @@ #ifndef ZFCP_EXT_H #define ZFCP_EXT_H /* this drivers version (do not edit !!! generated and updated by cvs) */ -#define ZFCP_EXT_REVISION "$Revision: 1.51 $" +#define ZFCP_EXT_REVISION "$Revision: 1.53 $" #include "zfcp_def.h" @@ -117,9 +117,11 @@ extern struct zfcp_fsf_req *zfcp_fsf_abort_fcp_command( unsigned long, struct zfcp_adapter *, struct zfcp_unit *, int); -/******************************** FCP ****************************************/ +/******************************* FC/FCP **************************************/ extern int zfcp_nameserver_enqueue(struct zfcp_adapter *); extern int zfcp_ns_gid_pn_request(struct zfcp_erp_action *); +extern int zfcp_check_ct_response(struct ct_hdr *); +extern int zfcp_handle_els_rjt(u32, struct zfcp_ls_rjt_par *); /******************************* SCSI ****************************************/ extern int zfcp_adapter_scsi_register(struct zfcp_adapter *); diff -Nru a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c --- a/drivers/s390/scsi/zfcp_fsf.c 2004-08-25 22:01:55 -07:00 +++ b/drivers/s390/scsi/zfcp_fsf.c 2004-08-25 22:01:55 -07:00 @@ -29,7 +29,7 @@ */ /* this drivers version (do not edit !!! generated and updated by cvs) */ -#define ZFCP_FSF_C_REVISION "$Revision: 1.55 $" +#define ZFCP_FSF_C_REVISION "$Revision: 1.59 $" #include "zfcp_ext.h" @@ -48,7 +48,7 @@ static int zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *); static int zfcp_fsf_send_els_handler(struct zfcp_fsf_req *); static int zfcp_fsf_control_file_handler(struct zfcp_fsf_req *); -static inline int zfcp_fsf_req_create_sbal_check( +static inline int zfcp_fsf_req_sbal_check( unsigned long *, struct zfcp_qdio_queue *, int); static inline int zfcp_use_one_sbal( struct scatterlist *, int, struct scatterlist *, int); @@ -79,10 +79,9 @@ }; static const char zfcp_act_subtable_type[5][8] = { - {"unknown"}, {"OS"}, {"WWPN"}, {"DID"}, {"LUN"} + "unknown", "OS", "WWPN", "DID", "LUN" }; - /****************************************************************/ /*************** FSF related Functions *************************/ /****************************************************************/ @@ -1863,6 +1862,10 @@ /* ERP strategy will escalate */ debug_text_event(adapter->erp_dbf, 1, "fsf_sq_ulp"); fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR; + retval = + zfcp_handle_els_rjt(header->fsf_status_qual.word[1], + (struct zfcp_ls_rjt_par *) + &header->fsf_status_qual.word[2]); break; case FSF_SQ_RETRY_IF_POSSIBLE: ZFCP_LOG_FLAGS(2, "FSF_SQ_RETRY_IF_POSSIBLE\n"); @@ -1971,8 +1974,6 @@ if (send_els->handler != 0) send_els->handler(send_els->handler_data); - kfree(send_els); - return retval; } @@ -4157,87 +4158,6 @@ } skip_fsfstatus: -#if 0 - /* - * This nasty chop at the problem is not working anymore - * as we do not adjust the retry count anylonger in order - * to have a number of retries that avoids I/O errors. - * The manipulation of the retry count has been removed - * in favour of a safe tape device handling. We must not - * sent SCSI commands more than once to a device if no - * retries are permitted by the high level driver. Generally - * speaking, it was a mess to change retry counts. So it is - * fine that this sort of workaround is gone. - * Then, we had to face a certain number of immediate retries in case of - * busy and queue full conditions (see below). - * This is not acceptable - * for the latter. Queue full conditions are used - * by devices to indicate to a host that the host can rely - * on the completion (or timeout) of at least one outstanding - * command as a suggested trigger for command retries. - * Busy conditions require a different trigger since - * no commands are outstanding for that initiator from the - * devices perspective. - * The drawback of mapping a queue full condition to a - * busy condition is the chance of wasting all retries prior - * to the time when the device indicates that a command - * rejected due to a queue full condition should be re-driven. - * This case would lead to unnecessary I/O errors that - * have to be considered fatal if for example ext3's - * journaling would be torpedoed by such an avoidable - * I/O error. - * So, what issues are there with not mapping a queue-full - * condition to a busy condition? - * Due to the 'exclusive LUN' - * policy enforced by the zSeries FCP channel, this - * Linux instance is the only initiator with regard to - * this adapter. It is safe to rely on the information - * 'don't disturb me now ... and btw. no other commands - * pending for you' (= queue full) sent by the LU, - * since no other Linux can use this LUN via this adapter - * at the same time. If there is a potential race - * introduced by the FCP channel by not inhibiting Linux A - * to give up a LU with commands pending while Linux B - * grabs this LU and sends commands - thus providing - * an exploit at the 'exclusive LUN' policy - then this - * issue has to be considered a hardware problem. It should - * be tracked as such if it really occurs. Even if the - * FCP Channel spec. begs exploiters to wait for the - * completion of all request sent to a LU prior to - * closing this LU connection. - * This spec. statement in conjunction with - * the 'exclusive LUN' policy is not consistent design. - * Another issue is how resource constraints for SCSI commands - * might be handled by the FCP channel (just guessing for now). - * If the FCP channel would always map resource constraints, - * e.g. no free FC exchange ID due to I/O stress caused by - * other sharing Linux instances, to faked queue-full - * conditions then this would be a misinterpretation and - * violation of SCSI standards. - * If there are SCSI stack races as indicated below - * then they need to be fixed just there. - * Providing all issue above are not applicable or will - * be fixed appropriately, removing the following hack - * is the right thing to do. - */ - - /* - * Note: This is a rather nasty chop at the problem. We cannot - * risk adding to the mlqueue however as this will block the - * device. If it is the last outstanding command for this host - * it will remain blocked indefinitely. This would be quite possible - * on the zSeries FCP adapter. - * Also, there exists a race with scsi_insert_special relying on - * scsi_request_fn to recalculate some command data which may not - * happen when q->plugged is true in scsi_request_fn - */ - if (status_byte(scpnt->result) == QUEUE_FULL) { - ZFCP_LOG_DEBUG("Changing QUEUE_FULL to BUSY....\n"); - scpnt->result &= ~(QUEUE_FULL << 1); - scpnt->result |= (BUSY << 1); - } -#endif - ZFCP_LOG_DEBUG("scpnt->result =0x%x\n", scpnt->result); zfcp_cmd_dbf_event_scsi("response", scpnt); @@ -4682,8 +4602,8 @@ } static inline int -zfcp_fsf_req_create_sbal_check(unsigned long *flags, - struct zfcp_qdio_queue *queue, int needed) +zfcp_fsf_req_sbal_check(unsigned long *flags, + struct zfcp_qdio_queue *queue, int needed) { write_lock_irqsave(&queue->queue_lock, *flags); if (likely(atomic_read(&queue->free_count) >= needed)) @@ -4713,29 +4633,24 @@ * @adapter: adapter for which request queue is examined * @req_flags: flags indicating whether to wait for needed SBAL or not * @lock_flags: lock_flags is queue_lock is taken - * - * locking: on success the queue_lock for the request queue of the adapter - * is held + * Return: 0 on success, otherwise -EIO, or -ERESTARTSYS + * Locks: lock adapter->request_queue->queue_lock on success */ static int zfcp_fsf_req_sbal_get(struct zfcp_adapter *adapter, int req_flags, unsigned long *lock_flags) { - int condition; + long ret; struct zfcp_qdio_queue *req_queue = &adapter->request_queue; if (unlikely(req_flags & ZFCP_WAIT_FOR_SBAL)) { - wait_event_interruptible_timeout(adapter->request_wq, - (condition = - zfcp_fsf_req_create_sbal_check - (lock_flags, req_queue, 1)), - ZFCP_SBAL_TIMEOUT); - if (!condition) { - return -EIO; - } - } else if (!zfcp_fsf_req_create_sbal_check(lock_flags, req_queue, 1)) { + ret = wait_event_interruptible_timeout(adapter->request_wq, + zfcp_fsf_req_sbal_check(lock_flags, req_queue, 1), + ZFCP_SBAL_TIMEOUT); + if (ret < 0) + return ret; + } else if (!zfcp_fsf_req_sbal_check(lock_flags, req_queue, 1)) return -EIO; - } return 0; } diff -Nru a/drivers/s390/scsi/zfcp_fsf.h b/drivers/s390/scsi/zfcp_fsf.h --- a/drivers/s390/scsi/zfcp_fsf.h 2004-08-25 22:01:56 -07:00 +++ b/drivers/s390/scsi/zfcp_fsf.h 2004-08-25 22:01:56 -07:00 @@ -227,6 +227,10 @@ #define FSF_HBA_PORTSTATE_LINKDOWN 0x00000006 #define FSF_HBA_PORTSTATE_ERROR 0x00000007 +/* IO states of adapter */ +#define FSF_IOSTAT_NPORT_RJT 0x00000004 +#define FSF_IOSTAT_FABRIC_RJT 0x00000005 +#define FSF_IOSTAT_LS_RJT 0x00000009 struct fsf_queue_designator; struct fsf_status_read_buffer; diff -Nru a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c --- a/drivers/s390/scsi/zfcp_scsi.c 2004-08-25 22:01:56 -07:00 +++ b/drivers/s390/scsi/zfcp_scsi.c 2004-08-25 22:01:56 -07:00 @@ -31,7 +31,7 @@ #define ZFCP_LOG_AREA ZFCP_LOG_AREA_SCSI /* this drivers version (do not edit !!! generated and updated by cvs) */ -#define ZFCP_SCSI_REVISION "$Revision: 1.65 $" +#define ZFCP_SCSI_REVISION "$Revision: 1.66 $" #include "zfcp_ext.h" @@ -430,7 +430,7 @@ u64 dbf_fsf_req = 0; u64 dbf_fsf_status = 0; u64 dbf_fsf_qual[2] = { 0, 0 }; - char dbf_result[ZFCP_ABORT_DBF_LENGTH] = { "##undef" }; + char dbf_result[ZFCP_ABORT_DBF_LENGTH] = "##undef"; memset(dbf_opcode, 0, ZFCP_ABORT_DBF_LENGTH); memcpy(dbf_opcode, diff -Nru a/drivers/s390/scsi/zfcp_sysfs_adapter.c b/drivers/s390/scsi/zfcp_sysfs_adapter.c --- a/drivers/s390/scsi/zfcp_sysfs_adapter.c 2004-08-25 22:01:54 -07:00 +++ b/drivers/s390/scsi/zfcp_sysfs_adapter.c 2004-08-25 22:01:54 -07:00 @@ -26,18 +26,18 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#define ZFCP_SYSFS_ADAPTER_C_REVISION "$Revision: 1.33 $" +#define ZFCP_SYSFS_ADAPTER_C_REVISION "$Revision: 1.36 $" #include "zfcp_ext.h" #define ZFCP_LOG_AREA ZFCP_LOG_AREA_CONFIG static const char fc_topologies[5][25] = { - {""}, - {"point-to-point"}, - {"fabric"}, - {"arbitrated loop"}, - {"fabric (virt. adapter)"} + "", + "point-to-point", + "fabric", + "arbitrated loop", + "fabric (virt. adapter)" }; /** @@ -74,29 +74,8 @@ adapter->hardware_version); ZFCP_DEFINE_ADAPTER_ATTR(serial_number, "%17s\n", adapter->serial_number); ZFCP_DEFINE_ADAPTER_ATTR(scsi_host_no, "0x%x\n", adapter->scsi_host_no); - -/** - * zfcp_sysfs_adapter_in_recovery_show - recovery state of adapter - * @dev: pointer to belonging device - * @buf: pointer to input buffer - * - * Show function of "in_recovery" attribute of adapter. Will be - * "0" if no error recovery is pending for adapter, otherwise "1". - */ -static ssize_t -zfcp_sysfs_adapter_in_recovery_show(struct device *dev, char *buf) -{ - struct zfcp_adapter *adapter; - - adapter = dev_get_drvdata(dev); - if (atomic_test_mask(ZFCP_STATUS_COMMON_ERP_INUSE, &adapter->status)) - return sprintf(buf, "1\n"); - else - return sprintf(buf, "0\n"); -} - -static DEVICE_ATTR(in_recovery, S_IRUGO, - zfcp_sysfs_adapter_in_recovery_show, NULL); +ZFCP_DEFINE_ADAPTER_ATTR(in_recovery, "%d\n", atomic_test_mask + (ZFCP_STATUS_COMMON_ERP_INUSE, &adapter->status)); /** * zfcp_sysfs_port_add_store - add a port to sysfs tree @@ -138,7 +117,7 @@ zfcp_port_put(port); out: up(&zfcp_data.config_sema); - return retval ? retval : count; + return retval ? retval : (ssize_t) count; } static DEVICE_ATTR(port_add, S_IWUSR, NULL, zfcp_sysfs_port_add_store); @@ -197,7 +176,7 @@ zfcp_port_dequeue(port); out: up(&zfcp_data.config_sema); - return retval ? retval : count; + return retval ? retval : (ssize_t) count; } static DEVICE_ATTR(port_remove, S_IWUSR, NULL, zfcp_sysfs_port_remove_store); @@ -241,7 +220,7 @@ zfcp_erp_wait(adapter); out: up(&zfcp_data.config_sema); - return retval ? retval : count; + return retval ? retval : (ssize_t) count; } /** diff -Nru a/drivers/s390/scsi/zfcp_sysfs_driver.c b/drivers/s390/scsi/zfcp_sysfs_driver.c --- a/drivers/s390/scsi/zfcp_sysfs_driver.c 2004-08-25 22:01:56 -07:00 +++ b/drivers/s390/scsi/zfcp_sysfs_driver.c 2004-08-25 22:01:56 -07:00 @@ -26,7 +26,7 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#define ZFCP_SYSFS_DRIVER_C_REVISION "$Revision: 1.14 $" +#define ZFCP_SYSFS_DRIVER_C_REVISION "$Revision: 1.15 $" #include "zfcp_ext.h" @@ -65,7 +65,7 @@ static ssize_t zfcp_sysfs_loglevel_##_name##_show(struct device_driver *dev, \ char *buf) \ { \ - return sprintf(buf,"%d\n", \ + return sprintf(buf,"%d\n", (unsigned int) \ ZFCP_GET_LOG_VALUE(ZFCP_LOG_AREA_##_define)); \ } \ \ diff -Nru a/drivers/s390/scsi/zfcp_sysfs_port.c b/drivers/s390/scsi/zfcp_sysfs_port.c --- a/drivers/s390/scsi/zfcp_sysfs_port.c 2004-08-25 22:01:56 -07:00 +++ b/drivers/s390/scsi/zfcp_sysfs_port.c 2004-08-25 22:01:56 -07:00 @@ -26,7 +26,7 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#define ZFCP_SYSFS_PORT_C_REVISION "$Revision: 1.41 $" +#define ZFCP_SYSFS_PORT_C_REVISION "$Revision: 1.43 $" #include "zfcp_ext.h" @@ -66,6 +66,8 @@ ZFCP_DEFINE_PORT_ATTR(wwnn, "0x%016llx\n", port->wwnn); ZFCP_DEFINE_PORT_ATTR(d_id, "0x%06x\n", port->d_id); ZFCP_DEFINE_PORT_ATTR(scsi_id, "0x%x\n", port->scsi_id); +ZFCP_DEFINE_PORT_ATTR(in_recovery, "%d\n", atomic_test_mask + (ZFCP_STATUS_COMMON_ERP_INUSE, &port->status)); /** * zfcp_sysfs_unit_add_store - add a unit to sysfs tree @@ -107,7 +109,7 @@ zfcp_unit_put(unit); out: up(&zfcp_data.config_sema); - return retval ? retval : count; + return retval ? retval : (ssize_t) count; } static DEVICE_ATTR(unit_add, S_IWUSR, NULL, zfcp_sysfs_unit_add_store); @@ -164,7 +166,7 @@ zfcp_unit_dequeue(unit); out: up(&zfcp_data.config_sema); - return retval ? retval : count; + return retval ? retval : (ssize_t) count; } static DEVICE_ATTR(unit_remove, S_IWUSR, NULL, zfcp_sysfs_unit_remove_store); @@ -206,7 +208,7 @@ zfcp_erp_wait(port->adapter); out: up(&zfcp_data.config_sema); - return retval ? retval : count; + return retval ? retval : (ssize_t) count; } /** @@ -231,29 +233,6 @@ static DEVICE_ATTR(failed, S_IWUSR | S_IRUGO, zfcp_sysfs_port_failed_show, zfcp_sysfs_port_failed_store); - -/** - * zfcp_sysfs_port_in_recovery_show - recovery state of port - * @dev: pointer to belonging device - * @buf: pointer to input buffer - * - * Show function of "in_recovery" attribute of port. Will be - * "0" if no error recovery is pending for port, otherwise "1". - */ -static ssize_t -zfcp_sysfs_port_in_recovery_show(struct device *dev, char *buf) -{ - struct zfcp_port *port; - - port = dev_get_drvdata(dev); - if (atomic_test_mask(ZFCP_STATUS_COMMON_ERP_INUSE, &port->status)) - return sprintf(buf, "1\n"); - else - return sprintf(buf, "0\n"); -} - -static DEVICE_ATTR(in_recovery, S_IRUGO, zfcp_sysfs_port_in_recovery_show, - NULL); /** * zfcp_port_common_attrs diff -Nru a/drivers/s390/scsi/zfcp_sysfs_unit.c b/drivers/s390/scsi/zfcp_sysfs_unit.c --- a/drivers/s390/scsi/zfcp_sysfs_unit.c 2004-08-25 22:01:56 -07:00 +++ b/drivers/s390/scsi/zfcp_sysfs_unit.c 2004-08-25 22:01:56 -07:00 @@ -26,7 +26,7 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#define ZFCP_SYSFS_UNIT_C_REVISION "$Revision: 1.25 $" +#define ZFCP_SYSFS_UNIT_C_REVISION "$Revision: 1.27 $" #include "zfcp_ext.h" @@ -64,6 +64,8 @@ ZFCP_DEFINE_UNIT_ATTR(status, "0x%08x\n", atomic_read(&unit->status)); ZFCP_DEFINE_UNIT_ATTR(scsi_lun, "0x%x\n", unit->scsi_lun); +ZFCP_DEFINE_UNIT_ATTR(in_recovery, "%d\n", atomic_test_mask + (ZFCP_STATUS_COMMON_ERP_INUSE, &unit->status)); /** * zfcp_sysfs_unit_failed_store - failed state of unit @@ -101,7 +103,7 @@ zfcp_erp_wait(unit->port->adapter); out: up(&zfcp_data.config_sema); - return retval ? retval : count; + return retval ? retval : (ssize_t) count; } /** @@ -126,29 +128,6 @@ static DEVICE_ATTR(failed, S_IWUSR | S_IRUGO, zfcp_sysfs_unit_failed_show, zfcp_sysfs_unit_failed_store); - -/** - * zfcp_sysfs_unit_in_recovery_show - recovery state of unit - * @dev: pointer to belonging device - * @buf: pointer to input buffer - * - * Show function of "in_recovery" attribute of unit. Will be - * "0" if no error recovery is pending for unit, otherwise "1". - */ -static ssize_t -zfcp_sysfs_unit_in_recovery_show(struct device *dev, char *buf) -{ - struct zfcp_unit *unit; - - unit = dev_get_drvdata(dev); - if (atomic_test_mask(ZFCP_STATUS_COMMON_ERP_INUSE, &unit->status)) - return sprintf(buf, "1\n"); - else - return sprintf(buf, "0\n"); -} - -static DEVICE_ATTR(in_recovery, S_IRUGO, zfcp_sysfs_unit_in_recovery_show, - NULL); static struct attribute *zfcp_unit_attrs[] = { &dev_attr_scsi_lun.attr, diff -Nru a/drivers/scsi/cpqfcTSinit.c b/drivers/scsi/cpqfcTSinit.c --- a/drivers/scsi/cpqfcTSinit.c 2004-08-25 22:01:54 -07:00 +++ b/drivers/scsi/cpqfcTSinit.c 2004-08-25 22:01:54 -07:00 @@ -302,10 +302,16 @@ cpqfc_boards[i].device_id, PciDev))) { + if (pci_enable_device(PciDev)) { + printk(KERN_ERR + "cpqfc: can't enable PCI device at %s\n", pci_name(PciDev)); + goto err_continue; + } + if (pci_set_dma_mask(PciDev, CPQFCTS_DMA_MASK) != 0) { printk(KERN_WARNING "cpqfc: HBA cannot support required DMA mask, skipping.\n"); - continue; + goto err_disable_dev; } // NOTE: (kernel 2.2.12-32) limits allocation to 128k bytes... @@ -314,8 +320,11 @@ HostAdapter = scsi_register( ScsiHostTemplate, sizeof( CPQFCHBA ) ); - if(HostAdapter == NULL) - continue; + if(HostAdapter == NULL) { + printk(KERN_WARNING + "cpqfc: can't register SCSI HBA, skipping.\n"); + goto err_disable_dev; + } DEBUG_PCI( printk(" HBA found!\n")); DEBUG_PCI( printk(" HostAdapter->PciDev->irq = %u\n", PciDev->irq) ); DEBUG_PCI(printk(" PciDev->baseaddress[0]= %lx\n", @@ -367,9 +376,8 @@ DEV_NAME, HostAdapter) ) { - printk(" IRQ %u already used\n", HostAdapter->irq); - scsi_unregister( HostAdapter); - continue; + printk(KERN_WARNING "cpqfc: IRQ %u already used\n", HostAdapter->irq); + goto err_unregister; } // Since we have two 256-byte I/O port ranges (upper @@ -377,22 +385,17 @@ if( !request_region( cpqfcHBAdata->fcChip.Registers.IOBaseU, 0xff, DEV_NAME ) ) { - printk(" cpqfcTS address in use: %x\n", + printk(KERN_WARNING "cpqfc: address in use: %x\n", cpqfcHBAdata->fcChip.Registers.IOBaseU); - free_irq( HostAdapter->irq, HostAdapter); - scsi_unregister( HostAdapter); - continue; + goto err_free_irq; } if( !request_region( cpqfcHBAdata->fcChip.Registers.IOBaseL, 0xff, DEV_NAME ) ) { - printk(" cpqfcTS address in use: %x\n", + printk(KERN_WARNING "cpqfc: address in use: %x\n", cpqfcHBAdata->fcChip.Registers.IOBaseL); - release_region( cpqfcHBAdata->fcChip.Registers.IOBaseU, 0xff ); - free_irq( HostAdapter->irq, HostAdapter); - scsi_unregister( HostAdapter); - continue; + goto err_release_region_U; } // OK, we have grabbed everything we need now. @@ -424,7 +427,7 @@ // now initialize our hardware... if (cpqfcHBAdata->fcChip.InitializeTachyon( cpqfcHBAdata, 1,1)) { printk(KERN_WARNING "cpqfc: initialization of HBA hardware failed.\n"); - // FIXME: might want to do something better than nothing here. + goto err_release_region_L; } cpqfcHBAdata->fcStatsTime = jiffies; // (for FC Statistics delta) @@ -455,6 +458,21 @@ spin_lock_irq(HostAdapter->host_lock); NumberOfAdapters++; spin_unlock_irq(HostAdapter->host_lock); + + continue; + +err_release_region_L: + release_region( cpqfcHBAdata->fcChip.Registers.IOBaseL, 0xff ); +err_release_region_U: + release_region( cpqfcHBAdata->fcChip.Registers.IOBaseU, 0xff ); +err_free_irq: + free_irq( HostAdapter->irq, HostAdapter); +err_unregister: + scsi_unregister( HostAdapter); +err_disable_dev: + pci_disable_device( PciDev ); +err_continue: + continue; } // end of while() } @@ -811,6 +829,7 @@ cpqfcHBAdata->fcChip.Registers.ReMapMemBase) vfree( cpqfcHBAdata->fcChip.Registers.ReMapMemBase); */ + pci_disable_device( cpqfcHBAdata->PciDev); LEAVE("cpqfcTS_release"); return 0; diff -Nru a/drivers/scsi/sd.c b/drivers/scsi/sd.c --- a/drivers/scsi/sd.c 2004-08-25 22:01:56 -07:00 +++ b/drivers/scsi/sd.c 2004-08-25 22:01:56 -07:00 @@ -182,16 +182,14 @@ if (disk->private_data == NULL) goto out; sdkp = scsi_disk(disk); - if (!kref_get(&sdkp->kref)) - goto out_sdkp; + kref_get(&sdkp->kref); if (scsi_device_get(sdkp->device)) goto out_put; up(&sd_ref_sem); return sdkp; out_put: - kref_put(&sdkp->kref); - out_sdkp: + kref_put(&sdkp->kref, scsi_disk_release); sdkp = NULL; out: up(&sd_ref_sem); @@ -202,7 +200,7 @@ { down(&sd_ref_sem); scsi_device_put(sdkp->device); - kref_put(&sdkp->kref); + kref_put(&sdkp->kref, scsi_disk_release); up(&sd_ref_sem); } @@ -1420,7 +1418,7 @@ goto out; memset (sdkp, 0, sizeof(*sdkp)); - kref_init(&sdkp->kref, scsi_disk_release); + kref_init(&sdkp->kref); /* Note: We can accomodate 64 partitions, but the genhd code * assumes partitions allocate consecutive minors, which they don't. @@ -1522,7 +1520,7 @@ del_gendisk(sdkp->disk); sd_shutdown(dev); down(&sd_ref_sem); - kref_put(&sdkp->kref); + kref_put(&sdkp->kref, scsi_disk_release); up(&sd_ref_sem); return 0; diff -Nru a/drivers/scsi/sr.c b/drivers/scsi/sr.c --- a/drivers/scsi/sr.c 2004-08-25 22:01:56 -07:00 +++ b/drivers/scsi/sr.c 2004-08-25 22:01:56 -07:00 @@ -140,15 +140,13 @@ if (disk->private_data == NULL) goto out; cd = scsi_cd(disk); - if (!kref_get(&cd->kref)) - goto out_null; + kref_get(&cd->kref); if (scsi_device_get(cd->device)) goto out_put; goto out; out_put: - kref_put(&cd->kref); - out_null: + kref_put(&cd->kref, sr_kref_release); cd = NULL; out: up(&sr_ref_sem); @@ -159,7 +157,7 @@ { down(&sr_ref_sem); scsi_device_put(cd->device); - kref_put(&cd->kref); + kref_put(&cd->kref, sr_kref_release); up(&sr_ref_sem); } @@ -576,7 +574,7 @@ goto fail; memset(cd, 0, sizeof(*cd)); - kref_init(&cd->kref, sr_kref_release); + kref_init(&cd->kref); disk = alloc_disk(1); if (!disk) @@ -937,7 +935,7 @@ del_gendisk(cd->disk); down(&sr_ref_sem); - kref_put(&cd->kref); + kref_put(&cd->kref, sr_kref_release); up(&sr_ref_sem); return 0; diff -Nru a/drivers/serial/68360serial.c b/drivers/serial/68360serial.c --- a/drivers/serial/68360serial.c 2004-08-25 22:01:56 -07:00 +++ b/drivers/serial/68360serial.c 2004-08-25 22:01:56 -07:00 @@ -2592,7 +2592,7 @@ state->icount.rx = state->icount.tx = 0; state->icount.frame = state->icount.parity = 0; state->icount.overrun = state->icount.brk = 0; - printk(KERN_INFO "ttyS%02d at irq 0x%02x is an %s\n", + printk(KERN_INFO "ttyS%d at irq 0x%02x is an %s\n", i, (unsigned int)(state->irq), (state->smc_scc_num & NUM_IS_SCC) ? "SCC" : "SMC"); diff -Nru a/drivers/serial/sn_console.c b/drivers/serial/sn_console.c --- a/drivers/serial/sn_console.c 2004-08-25 22:01:55 -07:00 +++ b/drivers/serial/sn_console.c 2004-08-25 22:01:55 -07:00 @@ -50,6 +50,7 @@ #include #include +#include #include #include #include @@ -1086,7 +1087,9 @@ spin_unlock_irqrestore(&port->sc_port.lock, flags); puts_raw_fixed(port->sc_ops->sal_puts_raw, s, count); +#if defined(CONFIG_SMP) || defined(CONFIG_PREEMPT) } +#endif } else { /* Not yet registered with serial core - simple case */ diff -Nru a/drivers/tc/zs.c b/drivers/tc/zs.c --- a/drivers/tc/zs.c 2004-08-25 22:01:56 -07:00 +++ b/drivers/tc/zs.c 2004-08-25 22:01:56 -07:00 @@ -706,7 +706,7 @@ save_flags(flags); cli(); #ifdef SERIAL_DEBUG_OPEN - printk("starting up ttyS%02d (irq %d)...", info->line, info->irq); + printk("starting up ttyS%d (irq %d)...", info->line, info->irq); #endif /* @@ -1356,7 +1356,7 @@ } #ifdef SERIAL_DEBUG_OPEN - printk("rs_close ttyS%02d, count = %d\n", info->line, info->count); + printk("rs_close ttyS%d, count = %d\n", info->line, info->count); #endif if ((tty->count == 1) && (info->count != 1)) { /* @@ -1371,7 +1371,7 @@ info->count = 1; } if (--info->count < 0) { - printk("rs_close: bad serial port count for ttyS%02d: %d\n", + printk("rs_close: bad serial port count for ttyS%d: %d\n", info->line, info->count); info->count = 0; } @@ -1531,7 +1531,7 @@ retval = 0; add_wait_queue(&info->open_wait, &wait); #ifdef SERIAL_DEBUG_OPEN - printk("block_til_ready before block: ttyS%02d, count = %d\n", + printk("block_til_ready before block: ttyS%d, count = %d\n", info->line, info->count); #endif cli(); @@ -1565,7 +1565,7 @@ break; } #ifdef SERIAL_DEBUG_OPEN - printk("block_til_ready blocking: ttyS%02d, count = %d\n", + printk("block_til_ready blocking: ttyS%d, count = %d\n", info->line, info->count); #endif schedule(); @@ -1576,7 +1576,7 @@ info->count++; info->blocked_open--; #ifdef SERIAL_DEBUG_OPEN - printk("block_til_ready after blocking: ttyS%02d, count = %d\n", + printk("block_til_ready after blocking: ttyS%d, count = %d\n", info->line, info->count); #endif if (retval) @@ -1896,7 +1896,7 @@ info->tqueue.data = info; init_waitqueue_head(&info->open_wait); init_waitqueue_head(&info->close_wait); - printk("ttyS%02d at 0x%08x (irq = %d)", info->line, + printk("ttyS%d at 0x%08x (irq = %d)", info->line, info->port, info->irq); printk(" is a Z85C30 SCC\n"); tty_register_device(serial_driver, info->line, NULL); diff -Nru a/drivers/telephony/ixj.c b/drivers/telephony/ixj.c --- a/drivers/telephony/ixj.c 2004-08-25 22:01:54 -07:00 +++ b/drivers/telephony/ixj.c 2004-08-25 22:01:54 -07:00 @@ -7718,6 +7718,23 @@ cleanup(); } +static IXJ *new_ixj(unsigned long port) +{ + IXJ *res; + if (!request_region(port, 16, "ixj DSP")) { + printk(KERN_INFO "ixj: can't get I/O address 0x%lx\n", port); + return NULL; + } + res = ixj_alloc(); + if (!res) { + release_region(port, 16); + printk(KERN_INFO "ixj: out of memory\n"); + return NULL; + } + res->DSPbase = port; + return res; +} + int __init ixj_probe_isapnp(int *cnt) { int probe = 0; @@ -7750,15 +7767,9 @@ return -ENODEV; } - result = check_region(pnp_port_start(dev, 0), 16); - if (result) { - printk(KERN_INFO "ixj: can't get I/O address 0x%lx\n", pnp_port_start(dev, 0)); + j = new_ixj(pnp_port_start(dev, 0)); + if (!j) break; - } - - j = ixj_alloc(); - j->DSPbase = pnp_port_start(dev,0); - request_region(j->DSPbase, 16, "ixj DSP"); if (func != 0x110) j->XILINXbase = pnp_port_start(dev, 1); /* get real port */ @@ -7806,22 +7817,15 @@ int __init ixj_probe_isa(int *cnt) { - int i, result, probe; + int i, probe; /* Use passed parameters for older kernels without PnP */ for (i = 0; i < IXJMAX; i++) { if (dspio[i]) { - IXJ *j; + IXJ *j = new_ixj(dspio[i]); - if ((result = check_region(ixj[*cnt].DSPbase, 16)) < 0) { - printk(KERN_INFO "ixj: can't get I/O address 0x%x\n", ixj[*cnt].DSPbase); + if (!j) break; - } - - j = ixj_alloc(); - - j->DSPbase = dspio[i]; - request_region(j->DSPbase, 16, "ixj DSP"); j->XILINXbase = xio[i]; j->cardtype = 0; @@ -7840,7 +7844,6 @@ struct pci_dev *pci = NULL; int i, probe = 0; IXJ *j = NULL; - int result; for (i = 0; i < IXJMAX - *cnt; i++) { pci = pci_find_device(0x15E2, 0x0500, pci); @@ -7849,20 +7852,12 @@ if (pci_enable_device(pci)) break; - if ((result = check_region(pci_resource_start(pci, 0), 16)) < 0) { - printk(KERN_INFO "ixj: can't get I/O address\n"); + j = new_ixj(pci_resource_start(pci, 0)); + if (!j) break; - } - /* Grab a device slot */ - j = ixj_alloc(); - if(j == NULL) - break; - - j->DSPbase = pci_resource_start(pci, 0); j->serial = (PCIEE_GetSerialNumber)pci_resource_start(pci, 2); j->XILINXbase = j->DSPbase + 0x10; - request_region(j->DSPbase, 16, "ixj DSP"); j->cardtype = QTI_PHONEJACK_PCI; j->board = *cnt; probe = ixj_selfprobe(j); diff -Nru a/drivers/telephony/ixj.h b/drivers/telephony/ixj.h --- a/drivers/telephony/ixj.h 2004-08-25 22:01:56 -07:00 +++ b/drivers/telephony/ixj.h 2004-08-25 22:01:56 -07:00 @@ -1188,12 +1188,12 @@ unsigned int cid_rec_codec; unsigned int cid_rec_volume; unsigned char cid_rec_flag; - char rec_mode; + signed char rec_mode; unsigned int play_codec; unsigned int cid_play_codec; unsigned int cid_play_volume; unsigned char cid_play_flag; - char play_mode; + signed char play_mode; IXJ_FLAGS flags; unsigned long busyflags; unsigned int rec_frame_size; diff -Nru a/drivers/usb/core/config.c b/drivers/usb/core/config.c --- a/drivers/usb/core/config.c 2004-08-25 22:01:54 -07:00 +++ b/drivers/usb/core/config.c 2004-08-25 22:01:54 -07:00 @@ -106,7 +106,7 @@ return buffer - buffer0 + i; } -static void usb_release_interface_cache(struct kref *ref) +void usb_release_interface_cache(struct kref *ref) { struct usb_interface_cache *intfc = ref_to_usb_interface_cache(ref); int j; @@ -356,7 +356,7 @@ if (!intfc) return -ENOMEM; memset(intfc, 0, len); - kref_init(&intfc->ref, usb_release_interface_cache); + kref_init(&intfc->ref); } /* Skip over any Class Specific or Vendor Specific descriptors; @@ -422,7 +422,8 @@ for (i = 0; i < cf->desc.bNumInterfaces; i++) { if (cf->intf_cache[i]) - kref_put(&cf->intf_cache[i]->ref); + kref_put(&cf->intf_cache[i]->ref, + usb_release_interface_cache); } } kfree(dev->config); diff -Nru a/drivers/usb/core/message.c b/drivers/usb/core/message.c --- a/drivers/usb/core/message.c 2004-08-25 22:01:54 -07:00 +++ b/drivers/usb/core/message.c 2004-08-25 22:01:54 -07:00 @@ -1196,7 +1196,7 @@ struct usb_interface_cache *intfc = altsetting_to_usb_interface_cache(intf->altsetting); - kref_put(&intfc->ref); + kref_put(&intfc->ref, usb_release_interface_cache); kfree(intf); } diff -Nru a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c --- a/drivers/usb/core/urb.c 2004-08-25 22:01:55 -07:00 +++ b/drivers/usb/core/urb.c 2004-08-25 22:01:55 -07:00 @@ -39,7 +39,7 @@ { if (urb) { memset(urb, 0, sizeof(*urb)); - kref_init(&urb->kref, urb_destroy); + kref_init(&urb->kref); spin_lock_init(&urb->lock); } } @@ -88,7 +88,7 @@ void usb_free_urb(struct urb *urb) { if (urb) - kref_put(&urb->kref); + kref_put(&urb->kref, urb_destroy); } /** diff -Nru a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h --- a/drivers/usb/core/usb.h 2004-08-25 22:01:54 -07:00 +++ b/drivers/usb/core/usb.h 2004-08-25 22:01:54 -07:00 @@ -10,6 +10,7 @@ extern void usb_disable_endpoint (struct usb_device *dev, unsigned int epaddr); extern void usb_disable_interface (struct usb_device *dev, struct usb_interface *intf); +extern void usb_release_interface_cache(struct kref *ref); extern void usb_disable_device (struct usb_device *dev, int skip_ep0); extern void usb_enable_endpoint (struct usb_device *dev, diff -Nru a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c --- a/drivers/usb/gadget/inode.c 2004-08-25 22:01:56 -07:00 +++ b/drivers/usb/gadget/inode.c 2004-08-25 22:01:56 -07:00 @@ -577,10 +577,10 @@ return value; } -static long ep_aio_read_retry(struct kiocb *iocb) +static ssize_t ep_aio_read_retry(struct kiocb *iocb) { struct kiocb_priv *priv = (void *) &iocb->private; - int status = priv->actual; + ssize_t status = priv->actual; /* we "retry" to get the right mm context for this: */ status = copy_to_user(priv->ubuf, priv->buf, priv->actual); diff -Nru a/drivers/usb/host/ehci-mem.c b/drivers/usb/host/ehci-mem.c --- a/drivers/usb/host/ehci-mem.c 2004-08-25 22:01:56 -07:00 +++ b/drivers/usb/host/ehci-mem.c 2004-08-25 22:01:56 -07:00 @@ -114,7 +114,7 @@ return qh; memset (qh, 0, sizeof *qh); - kref_init(&qh->kref, qh_destroy); + kref_init(&qh->kref); qh->ehci = ehci; qh->qh_dma = dma; // INIT_LIST_HEAD (&qh->qh_list); @@ -139,7 +139,7 @@ static inline void qh_put (struct ehci_qh *qh) { - kref_put(&qh->kref); + kref_put(&qh->kref, qh_destroy); } /*-------------------------------------------------------------------------*/ diff -Nru a/drivers/usb/input/ati_remote.c b/drivers/usb/input/ati_remote.c --- a/drivers/usb/input/ati_remote.c 2004-08-25 22:01:56 -07:00 +++ b/drivers/usb/input/ati_remote.c 2004-08-25 22:01:56 -07:00 @@ -112,11 +112,11 @@ #define ATI_INPUTNUM 1 /* Which input device to register as */ static unsigned long channel_mask = 0; -module_param(channel_mask, ulong, 444); +module_param(channel_mask, ulong, 0444); MODULE_PARM_DESC(channel_mask, "Bitmask of remote control channels to ignore"); static int debug = 0; -module_param(debug, int, 444); +module_param(debug, int, 0444); MODULE_PARM_DESC(debug, "Enable extra debug messages and information"); #define dbginfo(dev, format, arg...) do { if (debug) dev_info(dev , format , ## arg); } while (0) diff -Nru a/drivers/usb/misc/auerswald.c b/drivers/usb/misc/auerswald.c --- a/drivers/usb/misc/auerswald.c 2004-08-25 22:01:55 -07:00 +++ b/drivers/usb/misc/auerswald.c 2004-08-25 22:01:55 -07:00 @@ -1037,7 +1037,8 @@ /* now extract the information */ channelid = cp->intbufp[2]; - bytecount = le16_to_cpup (&cp->intbufp[3]); + bytecount = (unsigned char)cp->intbufp[3]; + bytecount |= (unsigned char)cp->intbufp[4] << 8; /* check the channel id */ if (channelid >= AUH_TYPESIZE) { @@ -1930,7 +1931,7 @@ struct usb_device *usbdev = interface_to_usbdev(intf); pauerswald_t cp = NULL; unsigned int u = 0; - char *pbuf; + u16 *pbuf; int ret; dbg ("probe: vendor id 0x%x, device id 0x%x", @@ -2002,7 +2003,7 @@ info("device is a %s", cp->dev_desc); /* get the maximum allowed control transfer length */ - pbuf = (char *) kmalloc (2, GFP_KERNEL); /* use an allocated buffer because of urb target */ + pbuf = (u16 *) kmalloc (2, GFP_KERNEL); /* use an allocated buffer because of urb target */ if (!pbuf) { err( "out of memory"); goto pfail; diff -Nru a/drivers/usb/net/rtl8150.c b/drivers/usb/net/rtl8150.c --- a/drivers/usb/net/rtl8150.c 2004-08-25 22:01:55 -07:00 +++ b/drivers/usb/net/rtl8150.c 2004-08-25 22:01:55 -07:00 @@ -265,7 +265,7 @@ if (i < MII_TIMEOUT) { get_registers(dev, PHYDAT, 2, data); - *reg = le16_to_cpup(data); + *reg = data[0] | (data[1] << 8); return 0; } else return 1; diff -Nru a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c --- a/drivers/usb/serial/usb-serial.c 2004-08-25 22:01:56 -07:00 +++ b/drivers/usb/serial/usb-serial.c 2004-08-25 22:01:56 -07:00 @@ -421,6 +421,63 @@ return; } +static void destroy_serial(struct kref *kref) +{ + struct usb_serial *serial; + struct usb_serial_port *port; + int i; + + serial = to_usb_serial(kref); + + dbg ("%s - %s", __FUNCTION__, serial->type->name); + + serial->type->shutdown(serial); + + /* return the minor range that this device had */ + return_serial(serial); + + for (i = 0; i < serial->num_ports; ++i) + serial->port[i]->open_count = 0; + + /* the ports are cleaned up and released in port_release() */ + for (i = 0; i < serial->num_ports; ++i) + if (serial->port[i]->dev.parent != NULL) { + device_unregister(&serial->port[i]->dev); + serial->port[i] = NULL; + } + + /* If this is a "fake" port, we have to clean it up here, as it will + * not get cleaned up in port_release() as it was never registered with + * the driver core */ + if (serial->num_ports < serial->num_port_pointers) { + for (i = serial->num_ports; i < serial->num_port_pointers; ++i) { + port = serial->port[i]; + if (!port) + continue; + if (port->read_urb) { + usb_unlink_urb(port->read_urb); + usb_free_urb(port->read_urb); + } + if (port->write_urb) { + usb_unlink_urb(port->write_urb); + usb_free_urb(port->write_urb); + } + if (port->interrupt_in_urb) { + usb_unlink_urb(port->interrupt_in_urb); + usb_free_urb(port->interrupt_in_urb); + } + kfree(port->bulk_in_buffer); + kfree(port->bulk_out_buffer); + kfree(port->interrupt_in_buffer); + } + } + + usb_put_dev(serial->dev); + + /* free up any memory that we allocated */ + kfree (serial); +} + /***************************************************************************** * Driver tty interface functions *****************************************************************************/ @@ -465,7 +522,7 @@ if (retval) { port->open_count = 0; module_put(serial->type->owner); - kref_put(&serial->kref); + kref_put(&serial->kref, destroy_serial); } } bailout: @@ -496,7 +553,7 @@ } module_put(port->serial->type->owner); - kref_put(&port->serial->kref); + kref_put(&port->serial->kref, destroy_serial); } static int serial_write (struct tty_struct * tty, int from_user, const unsigned char *buf, int count) @@ -654,13 +711,6 @@ ; } -static void serial_shutdown (struct usb_serial *serial) -{ - dbg ("%s", __FUNCTION__); - - serial->type->shutdown(serial); -} - static int serial_read_proc (char *page, char **start, off_t off, int count, int *eof, void *data) { struct usb_serial *serial; @@ -694,7 +744,7 @@ begin += length; length = 0; } - kref_put(&serial->kref); + kref_put(&serial->kref, destroy_serial); } *eof = 1; done: @@ -763,62 +813,6 @@ wake_up_interruptible(&tty->write_wait); } -static void destroy_serial(struct kref *kref) -{ - struct usb_serial *serial; - struct usb_serial_port *port; - int i; - - serial = to_usb_serial(kref); - - dbg ("%s - %s", __FUNCTION__, serial->type->name); - serial_shutdown (serial); - - /* return the minor range that this device had */ - return_serial(serial); - - for (i = 0; i < serial->num_ports; ++i) - serial->port[i]->open_count = 0; - - /* the ports are cleaned up and released in port_release() */ - for (i = 0; i < serial->num_ports; ++i) - if (serial->port[i]->dev.parent != NULL) { - device_unregister(&serial->port[i]->dev); - serial->port[i] = NULL; - } - - /* If this is a "fake" port, we have to clean it up here, as it will - * not get cleaned up in port_release() as it was never registered with - * the driver core */ - if (serial->num_ports < serial->num_port_pointers) { - for (i = serial->num_ports; i < serial->num_port_pointers; ++i) { - port = serial->port[i]; - if (!port) - continue; - if (port->read_urb) { - usb_unlink_urb(port->read_urb); - usb_free_urb(port->read_urb); - } - if (port->write_urb) { - usb_unlink_urb(port->write_urb); - usb_free_urb(port->write_urb); - } - if (port->interrupt_in_urb) { - usb_unlink_urb(port->interrupt_in_urb); - usb_free_urb(port->interrupt_in_urb); - } - kfree(port->bulk_in_buffer); - kfree(port->bulk_out_buffer); - kfree(port->interrupt_in_buffer); - } - } - - usb_put_dev(serial->dev); - - /* free up any memory that we allocated */ - kfree (serial); -} - static void port_release(struct device *dev) { struct usb_serial_port *port = to_usb_serial_port(dev); @@ -859,7 +853,7 @@ serial->interface = interface; serial->vendor = dev->descriptor.idVendor; serial->product = dev->descriptor.idProduct; - kref_init(&serial->kref, destroy_serial); + kref_init(&serial->kref); return serial; } @@ -1209,7 +1203,7 @@ if (serial) { /* let the last holder of this object * cause it to be cleaned up */ - kref_put(&serial->kref); + kref_put(&serial->kref, destroy_serial); } dev_info(dev, "device disconnected\n"); } diff -Nru a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig --- a/drivers/video/console/Kconfig 2004-08-25 22:01:54 -07:00 +++ b/drivers/video/console/Kconfig 2004-08-25 22:01:54 -07:00 @@ -43,7 +43,7 @@ about the Video mode selection support. If unsure, say N. config MDA_CONSOLE - depends on !M68K + depends on !M68K && ISA tristate "MDA text console (dual-headed) (EXPERIMENTAL)" ---help--- Say Y here if you have an old MDA or monochrome Hercules graphics diff -Nru a/fs/Makefile b/fs/Makefile --- a/fs/Makefile 2004-08-25 22:01:55 -07:00 +++ b/fs/Makefile 2004-08-25 22:01:55 -07:00 @@ -91,3 +91,5 @@ obj-$(CONFIG_XFS_FS) += xfs/ obj-$(CONFIG_AFS_FS) += afs/ obj-$(CONFIG_BEFS_FS) += befs/ +obj-$(CONFIG_HOSTFS) += hostfs/ +obj-$(CONFIG_HPPFS) += hppfs/ diff -Nru a/fs/adfs/super.c b/fs/adfs/super.c --- a/fs/adfs/super.c 2004-08-25 22:01:54 -07:00 +++ b/fs/adfs/super.c 2004-08-25 22:01:54 -07:00 @@ -241,7 +241,7 @@ { adfs_inode_cachep = kmem_cache_create("adfs_inode_cache", sizeof(struct adfs_inode_info), - 0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT, + 0, SLAB_RECLAIM_ACCOUNT, init_once, NULL); if (adfs_inode_cachep == NULL) return -ENOMEM; diff -Nru a/fs/affs/super.c b/fs/affs/super.c --- a/fs/affs/super.c 2004-08-25 22:01:55 -07:00 +++ b/fs/affs/super.c 2004-08-25 22:01:55 -07:00 @@ -115,7 +115,7 @@ { affs_inode_cachep = kmem_cache_create("affs_inode_cache", sizeof(struct affs_inode_info), - 0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT, + 0, SLAB_RECLAIM_ACCOUNT, init_once, NULL); if (affs_inode_cachep == NULL) return -ENOMEM; diff -Nru a/fs/aio.c b/fs/aio.c --- a/fs/aio.c 2004-08-25 22:01:55 -07:00 +++ b/fs/aio.c 2004-08-25 22:01:55 -07:00 @@ -39,6 +39,9 @@ #define dprintk(x...) do { ; } while (0) #endif +long aio_run = 0; /* for testing only */ +long aio_wakeups = 0; /* for testing only */ + /*------ sysctl variables----*/ atomic_t aio_nr = ATOMIC_INIT(0); /* current system wide number of aio requests */ unsigned aio_max_nr = 0x10000; /* system wide maximum number of aio requests */ @@ -277,6 +280,7 @@ struct kiocb *iocb = list_kiocb(pos); list_del_init(&iocb->ki_list); cancel = iocb->ki_cancel; + kiocbSetCancelled(iocb); if (cancel) { iocb->ki_users++; spin_unlock_irq(&ctx->ctx_lock); @@ -337,6 +341,11 @@ aio_cancel_all(ctx); wait_for_all_aios(ctx); + /* + * this is an overkill, but ensures we don't leave + * the ctx on the aio_wq + */ + flush_workqueue(aio_wq); if (1 != atomic_read(&ctx->users)) printk(KERN_DEBUG @@ -359,6 +368,8 @@ if (unlikely(ctx->reqs_active)) BUG(); + cancel_delayed_work(&ctx->wq); + flush_workqueue(aio_wq); aio_free_ring(ctx); mmdrop(ctx->mm); ctx->mm = NULL; @@ -398,6 +409,7 @@ req->ki_obj.user = NULL; req->ki_dtor = NULL; req->private = NULL; + INIT_LIST_HEAD(&req->ki_run_list); /* Check if the completion queue has enough free space to * accept an event from this io. @@ -543,85 +555,367 @@ return ioctx; } +/* + * use_mm + * Makes the calling kernel thread take on the specified + * mm context. + * Called by the retry thread execute retries within the + * iocb issuer's mm context, so that copy_from/to_user + * operations work seamlessly for aio. + * (Note: this routine is intended to be called only + * from a kernel thread context) + */ static void use_mm(struct mm_struct *mm) { struct mm_struct *active_mm; + struct task_struct *tsk = current; + task_lock(tsk); + active_mm = tsk->active_mm; atomic_inc(&mm->mm_count); - task_lock(current); - active_mm = current->active_mm; - current->mm = mm; - if (mm != active_mm) { - current->active_mm = mm; - activate_mm(active_mm, mm); - } - task_unlock(current); + tsk->mm = mm; + tsk->active_mm = mm; + activate_mm(active_mm, mm); + task_unlock(tsk); + mmdrop(active_mm); } -static void unuse_mm(struct mm_struct *mm) +/* + * unuse_mm + * Reverses the effect of use_mm, i.e. releases the + * specified mm context which was earlier taken on + * by the calling kernel thread + * (Note: this routine is intended to be called only + * from a kernel thread context) + * + * Comments: Called with ctx->ctx_lock held. This nests + * task_lock instead ctx_lock. + */ +void unuse_mm(struct mm_struct *mm) { - task_lock(current); - current->mm = NULL; - task_unlock(current); + struct task_struct *tsk = current; + + task_lock(tsk); + tsk->mm = NULL; /* active_mm is still 'mm' */ - enter_lazy_tlb(mm, current); + enter_lazy_tlb(mm, tsk); + task_unlock(tsk); } -/* Run on kevent's context. FIXME: needs to be per-cpu and warn if an - * operation blocks. +/* + * Queue up a kiocb to be retried. Assumes that the kiocb + * has already been marked as kicked, and places it on + * the retry run list for the corresponding ioctx, if it + * isn't already queued. Returns 1 if it actually queued + * the kiocb (to tell the caller to activate the work + * queue to process it), or 0, if it found that it was + * already queued. + * + * Should be called with the spin lock iocb->ki_ctx->ctx_lock + * held */ -static void aio_kick_handler(void *data) +static inline int __queue_kicked_iocb(struct kiocb *iocb) { - struct kioctx *ctx = data; + struct kioctx *ctx = iocb->ki_ctx; - use_mm(ctx->mm); + if (list_empty(&iocb->ki_run_list)) { + list_add_tail(&iocb->ki_run_list, + &ctx->run_list); + iocb->ki_queued++; + return 1; + } + return 0; +} - spin_lock_irq(&ctx->ctx_lock); - while (!list_empty(&ctx->run_list)) { - struct kiocb *iocb; - long ret; +/* aio_run_iocb + * This is the core aio execution routine. It is + * invoked both for initial i/o submission and + * subsequent retries via the aio_kick_handler. + * Expects to be invoked with iocb->ki_ctx->lock + * already held. The lock is released and reaquired + * as needed during processing. + * + * Calls the iocb retry method (already setup for the + * iocb on initial submission) for operation specific + * handling, but takes care of most of common retry + * execution details for a given iocb. The retry method + * needs to be non-blocking as far as possible, to avoid + * holding up other iocbs waiting to be serviced by the + * retry kernel thread. + * + * The trickier parts in this code have to do with + * ensuring that only one retry instance is in progress + * for a given iocb at any time. Providing that guarantee + * simplifies the coding of individual aio operations as + * it avoids various potential races. + */ +static ssize_t aio_run_iocb(struct kiocb *iocb) +{ + struct kioctx *ctx = iocb->ki_ctx; + ssize_t (*retry)(struct kiocb *); + ssize_t ret; - iocb = list_entry(ctx->run_list.next, struct kiocb, - ki_run_list); - list_del(&iocb->ki_run_list); - iocb->ki_users ++; - spin_unlock_irq(&ctx->ctx_lock); + if (iocb->ki_retried++ > 1024*1024) { + printk("Maximal retry count. Bytes done %Zd\n", + iocb->ki_nbytes - iocb->ki_left); + return -EAGAIN; + } + + if (!(iocb->ki_retried & 0xff)) { + pr_debug("%ld retry: %d of %d (kick %ld, Q %ld run %ld, wake %ld)\n", + iocb->ki_retried, + iocb->ki_nbytes - iocb->ki_left, iocb->ki_nbytes, + iocb->ki_kicked, iocb->ki_queued, aio_run, aio_wakeups); + } - kiocbClearKicked(iocb); - ret = iocb->ki_retry(iocb); - if (-EIOCBQUEUED != ret) { + if (!(retry = iocb->ki_retry)) { + printk("aio_run_iocb: iocb->ki_retry = NULL\n"); + return 0; + } + + /* + * We don't want the next retry iteration for this + * operation to start until this one has returned and + * updated the iocb state. However, wait_queue functions + * can trigger a kick_iocb from interrupt context in the + * meantime, indicating that data is available for the next + * iteration. We want to remember that and enable the + * next retry iteration _after_ we are through with + * this one. + * + * So, in order to be able to register a "kick", but + * prevent it from being queued now, we clear the kick + * flag, but make the kick code *think* that the iocb is + * still on the run list until we are actually done. + * When we are done with this iteration, we check if + * the iocb was kicked in the meantime and if so, queue + * it up afresh. + */ + + kiocbClearKicked(iocb); + + /* + * This is so that aio_complete knows it doesn't need to + * pull the iocb off the run list (We can't just call + * INIT_LIST_HEAD because we don't want a kick_iocb to + * queue this on the run list yet) + */ + iocb->ki_run_list.next = iocb->ki_run_list.prev = NULL; + spin_unlock_irq(&ctx->ctx_lock); + + /* Quit retrying if the i/o has been cancelled */ + if (kiocbIsCancelled(iocb)) { + ret = -EINTR; + aio_complete(iocb, ret, 0); + /* must not access the iocb after this */ + goto out; + } + + /* + * Now we are all set to call the retry method in async + * context. By setting this thread's io_wait context + * to point to the wait queue entry inside the currently + * running iocb for the duration of the retry, we ensure + * that async notification wakeups are queued by the + * operation instead of blocking waits, and when notified, + * cause the iocb to be kicked for continuation (through + * the aio_wake_function callback). + */ + BUG_ON(current->io_wait != NULL); + current->io_wait = &iocb->ki_wait; + ret = retry(iocb); + current->io_wait = NULL; + + if (-EIOCBRETRY != ret) { + if (-EIOCBQUEUED != ret) { + BUG_ON(!list_empty(&iocb->ki_wait.task_list)); aio_complete(iocb, ret, 0); - iocb = NULL; + /* must not access the iocb after this */ } + } else { + /* + * Issue an additional retry to avoid waiting forever if + * no waits were queued (e.g. in case of a short read). + */ + if (list_empty(&iocb->ki_wait.task_list)) + kiocbSetKicked(iocb); + } +out: + spin_lock_irq(&ctx->ctx_lock); - spin_lock_irq(&ctx->ctx_lock); - if (NULL != iocb) - __aio_put_req(ctx, iocb); + if (-EIOCBRETRY == ret) { + /* + * OK, now that we are done with this iteration + * and know that there is more left to go, + * this is where we let go so that a subsequent + * "kick" can start the next iteration + */ + + /* will make __queue_kicked_iocb succeed from here on */ + INIT_LIST_HEAD(&iocb->ki_run_list); + /* we must queue the next iteration ourselves, if it + * has already been kicked */ + if (kiocbIsKicked(iocb)) { + __queue_kicked_iocb(iocb); + } } + return ret; +} + +/* + * __aio_run_iocbs: + * Process all pending retries queued on the ioctx + * run list. + * Assumes it is operating within the aio issuer's mm + * context. Expects to be called with ctx->ctx_lock held + */ +static int __aio_run_iocbs(struct kioctx *ctx) +{ + struct kiocb *iocb; + int count = 0; + LIST_HEAD(run_list); + + list_splice_init(&ctx->run_list, &run_list); + while (!list_empty(&run_list)) { + iocb = list_entry(run_list.next, struct kiocb, + ki_run_list); + list_del(&iocb->ki_run_list); + /* + * Hold an extra reference while retrying i/o. + */ + iocb->ki_users++; /* grab extra reference */ + aio_run_iocb(iocb); + if (__aio_put_req(ctx, iocb)) /* drop extra ref */ + put_ioctx(ctx); + count++; + } + aio_run++; + if (!list_empty(&ctx->run_list)) + return 1; + return 0; +} + +static void aio_queue_work(struct kioctx * ctx) +{ + unsigned long timeout; + /* + * if someone is waiting, get the work started right + * away, otherwise, use a longer delay + */ + smp_mb(); + if (waitqueue_active(&ctx->wait)) + timeout = 1; + else + timeout = HZ/10; + queue_delayed_work(aio_wq, &ctx->wq, timeout); +} + + +/* + * aio_run_iocbs: + * Process all pending retries queued on the ioctx + * run list. + * Assumes it is operating within the aio issuer's mm + * context. + */ +static inline void aio_run_iocbs(struct kioctx *ctx) +{ + int requeue; + + spin_lock_irq(&ctx->ctx_lock); + + requeue = __aio_run_iocbs(ctx); spin_unlock_irq(&ctx->ctx_lock); + if (requeue) + aio_queue_work(ctx); +} - unuse_mm(ctx->mm); +/* + * just like aio_run_iocbs, but keeps running them until + * the list stays empty + */ +static inline void aio_run_all_iocbs(struct kioctx *ctx) +{ + spin_lock_irq(&ctx->ctx_lock); + while (__aio_run_iocbs(ctx)) + ; + spin_unlock_irq(&ctx->ctx_lock); } -void fastcall kick_iocb(struct kiocb *iocb) +/* + * aio_kick_handler: + * Work queue handler triggered to process pending + * retries on an ioctx. Takes on the aio issuer's + * mm context before running the iocbs, so that + * copy_xxx_user operates on the issuer's address + * space. + * Run on aiod's context. + */ +static void aio_kick_handler(void *data) { - struct kioctx *ctx = iocb->ki_ctx; + struct kioctx *ctx = data; + mm_segment_t oldfs = get_fs(); + int requeue; + set_fs(USER_DS); + use_mm(ctx->mm); + spin_lock_irq(&ctx->ctx_lock); + requeue =__aio_run_iocbs(ctx); + unuse_mm(ctx->mm); + spin_unlock_irq(&ctx->ctx_lock); + set_fs(oldfs); + /* + * we're in a worker thread already, don't use queue_delayed_work, + */ + if (requeue) + queue_work(aio_wq, &ctx->wq); +} + + +/* + * Called by kick_iocb to queue the kiocb for retry + * and if required activate the aio work queue to process + * it + */ +void queue_kicked_iocb(struct kiocb *iocb) +{ + struct kioctx *ctx = iocb->ki_ctx; + unsigned long flags; + int run = 0; + + WARN_ON((!list_empty(&iocb->ki_wait.task_list))); + + spin_lock_irqsave(&ctx->ctx_lock, flags); + run = __queue_kicked_iocb(iocb); + spin_unlock_irqrestore(&ctx->ctx_lock, flags); + if (run) { + aio_queue_work(ctx); + aio_wakeups++; + } +} + +/* + * kick_iocb: + * Called typically from a wait queue callback context + * (aio_wake_function) to trigger a retry of the iocb. + * The retry is usually executed by aio workqueue + * threads (See aio_kick_handler). + */ +void fastcall kick_iocb(struct kiocb *iocb) +{ /* sync iocbs are easy: they can only ever be executing from a * single context. */ if (is_sync_kiocb(iocb)) { kiocbSetKicked(iocb); - wake_up_process(iocb->ki_obj.tsk); + wake_up_process(iocb->ki_obj.tsk); return; } + iocb->ki_kicked++; + /* If its already kicked we shouldn't queue it again */ if (!kiocbTryKick(iocb)) { - unsigned long flags; - spin_lock_irqsave(&ctx->ctx_lock, flags); - list_add_tail(&iocb->ki_run_list, &ctx->run_list); - spin_unlock_irqrestore(&ctx->ctx_lock, flags); - queue_work(aio_wq, &ctx->wq); + queue_kicked_iocb(iocb); } } EXPORT_SYMBOL(kick_iocb); @@ -675,6 +969,16 @@ */ spin_lock_irqsave(&ctx->ctx_lock, flags); + if (iocb->ki_run_list.prev && !list_empty(&iocb->ki_run_list)) + list_del_init(&iocb->ki_run_list); + + /* + * cancelled requests don't get events, userland was given one + * when the event got cancelled. + */ + if (kiocbIsCancelled(iocb)) + goto put_rq; + ring = kmap_atomic(info->ring_pages[0], KM_IRQ1); tail = info->tail; @@ -703,6 +1007,11 @@ pr_debug("added to ring %p at [%lu]\n", iocb, tail); + pr_debug("%ld retries: %d of %d (kicked %ld, Q %ld run %ld wake %ld)\n", + iocb->ki_retried, + iocb->ki_nbytes - iocb->ki_left, iocb->ki_nbytes, + iocb->ki_kicked, iocb->ki_queued, aio_run, aio_wakeups); +put_rq: /* everything turned out well, dispose of the aiocb. */ ret = __aio_put_req(ctx, iocb); @@ -809,13 +1118,15 @@ int i = 0; struct io_event ent; struct aio_timeout to; + int event_loop = 0; /* testing only */ + int retry = 0; /* needed to zero any padding within an entry (there shouldn't be * any, but C is fun! */ memset(&ent, 0, sizeof(ent)); +retry: ret = 0; - while (likely(i < nr)) { ret = aio_read_evt(ctx, &ent); if (unlikely(ret <= 0)) @@ -844,6 +1155,13 @@ /* End fast path */ + /* racey check, but it gets redone */ + if (!retry && unlikely(!list_empty(&ctx->run_list))) { + retry = 1; + aio_run_all_iocbs(ctx); + goto retry; + } + init_timeout(&to); if (timeout) { struct timespec ts; @@ -858,7 +1176,6 @@ add_wait_queue_exclusive(&ctx->wait, &wait); do { set_task_state(tsk, TASK_INTERRUPTIBLE); - ret = aio_read_evt(ctx, &ent); if (ret) break; @@ -868,6 +1185,7 @@ if (to.timed_out) /* Only check after read evt */ break; schedule(); + event_loop++; if (signal_pending(tsk)) { ret = -EINTR; break; @@ -895,6 +1213,9 @@ if (timeout) clear_timeout(&to); out: + pr_debug("event loop executed %d times\n", event_loop); + pr_debug("aio_run %ld\n", aio_run); + pr_debug("aio_wakeups %ld\n", aio_wakeups); return i ? i : ret; } @@ -962,7 +1283,7 @@ ret = put_user(ioctx->user_id, ctxp); if (!ret) return 0; - get_ioctx(ioctx); + io_destroy(ioctx); } @@ -987,13 +1308,181 @@ return -EINVAL; } +/* + * Default retry method for aio_read (also used for first time submit) + * Responsible for updating iocb state as retries progress + */ +static ssize_t aio_pread(struct kiocb *iocb) +{ + struct file *file = iocb->ki_filp; + struct address_space *mapping = file->f_mapping; + struct inode *inode = mapping->host; + ssize_t ret = 0; + + ret = file->f_op->aio_read(iocb, iocb->ki_buf, + iocb->ki_left, iocb->ki_pos); + + /* + * Can't just depend on iocb->ki_left to determine + * whether we are done. This may have been a short read. + */ + if (ret > 0) { + iocb->ki_buf += ret; + iocb->ki_left -= ret; + /* + * For pipes and sockets we return once we have + * some data; for regular files we retry till we + * complete the entire read or find that we can't + * read any more data (e.g short reads). + */ + if (!S_ISFIFO(inode->i_mode) && !S_ISSOCK(inode->i_mode)) + ret = -EIOCBRETRY; + } + + /* This means we must have transferred all that we could */ + /* No need to retry anymore */ + if ((ret == 0) || (iocb->ki_left == 0)) + ret = iocb->ki_nbytes - iocb->ki_left; + + return ret; +} + +/* + * Default retry method for aio_write (also used for first time submit) + * Responsible for updating iocb state as retries progress + */ +static ssize_t aio_pwrite(struct kiocb *iocb) +{ + struct file *file = iocb->ki_filp; + ssize_t ret = 0; + + ret = file->f_op->aio_write(iocb, iocb->ki_buf, + iocb->ki_left, iocb->ki_pos); + + if (ret > 0) { + iocb->ki_buf += ret; + iocb->ki_left -= ret; + + ret = -EIOCBRETRY; + } + + /* This means we must have transferred all that we could */ + /* No need to retry anymore */ + if ((ret == 0) || (iocb->ki_left == 0)) + ret = iocb->ki_nbytes - iocb->ki_left; + + return ret; +} + +static ssize_t aio_fdsync(struct kiocb *iocb) +{ + struct file *file = iocb->ki_filp; + ssize_t ret = -EINVAL; + + if (file->f_op->aio_fsync) + ret = file->f_op->aio_fsync(iocb, 1); + return ret; +} + +static ssize_t aio_fsync(struct kiocb *iocb) +{ + struct file *file = iocb->ki_filp; + ssize_t ret = -EINVAL; + + if (file->f_op->aio_fsync) + ret = file->f_op->aio_fsync(iocb, 0); + return ret; +} + +/* + * aio_setup_iocb: + * Performs the initial checks and aio retry method + * setup for the kiocb at the time of io submission. + */ +ssize_t aio_setup_iocb(struct kiocb *kiocb) +{ + struct file *file = kiocb->ki_filp; + ssize_t ret = 0; + + switch (kiocb->ki_opcode) { + case IOCB_CMD_PREAD: + ret = -EBADF; + if (unlikely(!(file->f_mode & FMODE_READ))) + break; + ret = -EFAULT; + if (unlikely(!access_ok(VERIFY_WRITE, kiocb->ki_buf, + kiocb->ki_left))) + break; + ret = -EINVAL; + if (file->f_op->aio_read) + kiocb->ki_retry = aio_pread; + break; + case IOCB_CMD_PWRITE: + ret = -EBADF; + if (unlikely(!(file->f_mode & FMODE_WRITE))) + break; + ret = -EFAULT; + if (unlikely(!access_ok(VERIFY_READ, kiocb->ki_buf, + kiocb->ki_left))) + break; + ret = -EINVAL; + if (file->f_op->aio_write) + kiocb->ki_retry = aio_pwrite; + break; + case IOCB_CMD_FDSYNC: + ret = -EINVAL; + if (file->f_op->aio_fsync) + kiocb->ki_retry = aio_fdsync; + break; + case IOCB_CMD_FSYNC: + ret = -EINVAL; + if (file->f_op->aio_fsync) + kiocb->ki_retry = aio_fsync; + break; + default: + dprintk("EINVAL: io_submit: no operation provided\n"); + ret = -EINVAL; + } + + if (!kiocb->ki_retry) + return ret; + + return 0; +} + +/* + * aio_wake_function: + * wait queue callback function for aio notification, + * Simply triggers a retry of the operation via kick_iocb. + * + * This callback is specified in the wait queue entry in + * a kiocb (current->io_wait points to this wait queue + * entry when an aio operation executes; it is used + * instead of a synchronous wait when an i/o blocking + * condition is encountered during aio). + * + * Note: + * This routine is executed with the wait queue lock held. + * Since kick_iocb acquires iocb->ctx->ctx_lock, it nests + * the ioctx lock inside the wait queue lock. This is safe + * because this callback isn't used for wait queues which + * are nested inside ioctx lock (i.e. ctx->wait) + */ +int aio_wake_function(wait_queue_t *wait, unsigned mode, int sync, void *key) +{ + struct kiocb *iocb = container_of(wait, struct kiocb, ki_wait); + + list_del_init(&wait->task_list); + kick_iocb(iocb); + return 1; +} + int fastcall io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb, struct iocb *iocb) { struct kiocb *req; struct file *file; ssize_t ret; - char __user *buf; /* enforce forwards compatibility on users */ if (unlikely(iocb->aio_reserved1 || iocb->aio_reserved2 || @@ -1034,58 +1523,31 @@ req->ki_user_data = iocb->aio_data; req->ki_pos = iocb->aio_offset; - buf = (char __user *)(unsigned long)iocb->aio_buf; + req->ki_buf = (char __user *)(unsigned long)iocb->aio_buf; + req->ki_left = req->ki_nbytes = iocb->aio_nbytes; + req->ki_opcode = iocb->aio_lio_opcode; + init_waitqueue_func_entry(&req->ki_wait, aio_wake_function); + INIT_LIST_HEAD(&req->ki_wait.task_list); + req->ki_run_list.next = req->ki_run_list.prev = NULL; + req->ki_retry = NULL; + req->ki_retried = 0; + req->ki_kicked = 0; + req->ki_queued = 0; + aio_run = 0; + aio_wakeups = 0; - switch (iocb->aio_lio_opcode) { - case IOCB_CMD_PREAD: - ret = -EBADF; - if (unlikely(!(file->f_mode & FMODE_READ))) - goto out_put_req; - ret = -EFAULT; - if (unlikely(!access_ok(VERIFY_WRITE, buf, iocb->aio_nbytes))) - goto out_put_req; - ret = security_file_permission (file, MAY_READ); - if (ret) - goto out_put_req; - ret = -EINVAL; - if (file->f_op->aio_read) - ret = file->f_op->aio_read(req, buf, - iocb->aio_nbytes, req->ki_pos); - break; - case IOCB_CMD_PWRITE: - ret = -EBADF; - if (unlikely(!(file->f_mode & FMODE_WRITE))) - goto out_put_req; - ret = -EFAULT; - if (unlikely(!access_ok(VERIFY_READ, buf, iocb->aio_nbytes))) - goto out_put_req; - ret = security_file_permission (file, MAY_WRITE); - if (ret) - goto out_put_req; - ret = -EINVAL; - if (file->f_op->aio_write) - ret = file->f_op->aio_write(req, buf, - iocb->aio_nbytes, req->ki_pos); - break; - case IOCB_CMD_FDSYNC: - ret = -EINVAL; - if (file->f_op->aio_fsync) - ret = file->f_op->aio_fsync(req, 1); - break; - case IOCB_CMD_FSYNC: - ret = -EINVAL; - if (file->f_op->aio_fsync) - ret = file->f_op->aio_fsync(req, 0); - break; - default: - dprintk("EINVAL: io_submit: no operation provided\n"); - ret = -EINVAL; - } + ret = aio_setup_iocb(req); + if (ret) + goto out_put_req; + + spin_lock_irq(&ctx->ctx_lock); + list_add_tail(&req->ki_run_list, &ctx->run_list); + /* drain the run list */ + while (__aio_run_iocbs(ctx)) + ; + spin_unlock_irq(&ctx->ctx_lock); aio_put_req(req); /* drop extra ref to req */ - if (likely(-EIOCBQUEUED == ret)) - return 0; - aio_complete(req, ret, 0); /* will drop i/o ref to req */ return 0; out_put_req: @@ -1201,6 +1663,7 @@ if (kiocb && kiocb->ki_cancel) { cancel = kiocb->ki_cancel; kiocb->ki_users ++; + kiocbSetCancelled(kiocb); } else cancel = NULL; spin_unlock_irq(&ctx->ctx_lock); diff -Nru a/fs/befs/linuxvfs.c b/fs/befs/linuxvfs.c --- a/fs/befs/linuxvfs.c 2004-08-25 22:01:55 -07:00 +++ b/fs/befs/linuxvfs.c 2004-08-25 22:01:55 -07:00 @@ -433,7 +433,7 @@ { befs_inode_cachep = kmem_cache_create("befs_inode_cache", sizeof (struct befs_inode_info), - 0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT, + 0, SLAB_RECLAIM_ACCOUNT, init_once, NULL); if (befs_inode_cachep == NULL) { printk(KERN_ERR "befs_init_inodecache: " diff -Nru a/fs/bfs/inode.c b/fs/bfs/inode.c --- a/fs/bfs/inode.c 2004-08-25 22:01:55 -07:00 +++ b/fs/bfs/inode.c 2004-08-25 22:01:55 -07:00 @@ -245,7 +245,7 @@ { bfs_inode_cachep = kmem_cache_create("bfs_inode_cache", sizeof(struct bfs_inode_info), - 0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT, + 0, SLAB_RECLAIM_ACCOUNT, init_once, NULL); if (bfs_inode_cachep == NULL) return -ENOMEM; diff -Nru a/fs/binfmt_aout.c b/fs/binfmt_aout.c --- a/fs/binfmt_aout.c 2004-08-25 22:01:54 -07:00 +++ b/fs/binfmt_aout.c 2004-08-25 22:01:54 -07:00 @@ -307,7 +307,7 @@ (current->mm->start_data = N_DATADDR(ex)); current->mm->brk = ex.a_bss + (current->mm->start_brk = N_BSSADDR(ex)); - current->mm->free_area_cache = TASK_UNMAPPED_BASE; + current->mm->free_area_cache = current->mm->mmap_base; current->mm->rss = 0; current->mm->mmap = NULL; diff -Nru a/fs/binfmt_elf.c b/fs/binfmt_elf.c --- a/fs/binfmt_elf.c 2004-08-25 22:01:55 -07:00 +++ b/fs/binfmt_elf.c 2004-08-25 22:01:55 -07:00 @@ -703,10 +703,12 @@ if (elf_read_implies_exec(elf_ex, have_pt_gnu_stack)) current->personality |= READ_IMPLIES_EXEC; + arch_pick_mmap_layout(current->mm); + /* Do this so that we can load the interpreter, if need be. We will change some of these later */ current->mm->rss = 0; - current->mm->free_area_cache = TASK_UNMAPPED_BASE; + current->mm->free_area_cache = current->mm->mmap_base; retval = setup_arg_pages(bprm, executable_stack); if (retval < 0) { send_sig(SIGKILL, current, 0); diff -Nru a/fs/bio.c b/fs/bio.c --- a/fs/bio.c 2004-08-25 22:01:55 -07:00 +++ b/fs/bio.c 2004-08-25 22:01:55 -07:00 @@ -388,20 +388,17 @@ struct bio_vec *bvec; int i, ret = 0; - if (bio_data_dir(bio) == READ) { - char *uaddr = bio->bi_private; + char *uaddr = bio->bi_private; - __bio_for_each_segment(bvec, bio, i, 0) { - char *addr = page_address(bvec->bv_page); - - if (!ret && copy_to_user(uaddr, addr, bvec->bv_len)) - ret = -EFAULT; + __bio_for_each_segment(bvec, bio, i, 0) { + char *addr = page_address(bvec->bv_page); + if (bio_data_dir(bio) == READ && !ret && + copy_to_user(uaddr, addr, bvec->bv_len)) + ret = -EFAULT; - __free_page(bvec->bv_page); - uaddr += bvec->bv_len; - } + __free_page(bvec->bv_page); + uaddr += bvec->bv_len; } - bio_put(bio); return ret; } @@ -457,6 +454,7 @@ */ if (!ret) { if (!write_to_vm) { + unsigned long p = uaddr; bio->bi_rw |= (1 << BIO_RW); /* * for a write, copy in data to kernel pages @@ -465,8 +463,9 @@ bio_for_each_segment(bvec, bio, i) { char *addr = page_address(bvec->bv_page); - if (copy_from_user(addr, (char *) uaddr, bvec->bv_len)) + if (copy_from_user(addr, (char *) p, bvec->bv_len)) goto cleanup; + p += bvec->bv_len; } } diff -Nru a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c --- a/fs/cifs/cifsfs.c 2004-08-25 22:01:55 -07:00 +++ b/fs/cifs/cifsfs.c 2004-08-25 22:01:55 -07:00 @@ -561,7 +561,7 @@ { cifs_inode_cachep = kmem_cache_create("cifs_inode_cache", sizeof (struct cifsInodeInfo), - 0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT, + 0, SLAB_RECLAIM_ACCOUNT, cifs_init_once, NULL); if (cifs_inode_cachep == NULL) return -ENOMEM; diff -Nru a/fs/coda/inode.c b/fs/coda/inode.c --- a/fs/coda/inode.c 2004-08-25 22:01:55 -07:00 +++ b/fs/coda/inode.c 2004-08-25 22:01:55 -07:00 @@ -69,7 +69,7 @@ { coda_inode_cachep = kmem_cache_create("coda_inode_cache", sizeof(struct coda_inode_info), - 0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT, + 0, SLAB_RECLAIM_ACCOUNT, init_once, NULL); if (coda_inode_cachep == NULL) return -ENOMEM; diff -Nru a/fs/compat.c b/fs/compat.c --- a/fs/compat.c 2004-08-25 22:01:55 -07:00 +++ b/fs/compat.c 2004-08-25 22:01:55 -07:00 @@ -429,6 +429,8 @@ fn = d_path(filp->f_dentry, filp->f_vfsmnt, path, PAGE_SIZE); + if (IS_ERR(fn)) + fn = "?"; } sprintf(buf,"'%c'", (cmd>>24) & 0x3f); @@ -1373,14 +1375,14 @@ int retval; int i; - sched_balance_exec(); - file = open_exec(filename); retval = PTR_ERR(file); if (IS_ERR(file)) return retval; + sched_exec(); + bprm.p = PAGE_SIZE*MAX_ARG_PAGES-sizeof(void *); memset(bprm.page, 0, MAX_ARG_PAGES*sizeof(bprm.page[0])); @@ -1390,6 +1392,8 @@ bprm.sh_bang = 0; bprm.loader = 0; bprm.exec = 0; + bprm.interp_flags = 0; + bprm.interp_data = 0; bprm.security = NULL; bprm.mm = mm_alloc(); retval = -ENOMEM; diff -Nru a/fs/efs/super.c b/fs/efs/super.c --- a/fs/efs/super.c 2004-08-25 22:01:56 -07:00 +++ b/fs/efs/super.c 2004-08-25 22:01:56 -07:00 @@ -58,7 +58,7 @@ { efs_inode_cachep = kmem_cache_create("efs_inode_cache", sizeof(struct efs_inode_info), - 0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT, + 0, SLAB_RECLAIM_ACCOUNT, init_once, NULL); if (efs_inode_cachep == NULL) return -ENOMEM; diff -Nru a/fs/exec.c b/fs/exec.c --- a/fs/exec.c 2004-08-25 22:01:55 -07:00 +++ b/fs/exec.c 2004-08-25 22:01:55 -07:00 @@ -546,6 +546,7 @@ tsk->active_mm = mm; activate_mm(active_mm, mm); task_unlock(tsk); + arch_pick_mmap_layout(mm); if (old_mm) { if (active_mm != old_mm) BUG(); mmput(old_mm); @@ -1102,7 +1103,7 @@ if (IS_ERR(file)) return retval; - sched_balance_exec(); + sched_exec(); bprm.p = PAGE_SIZE*MAX_ARG_PAGES-sizeof(void *); memset(bprm.page, 0, MAX_ARG_PAGES*sizeof(bprm.page[0])); @@ -1210,7 +1211,7 @@ * name into corename, which must have space for at least * CORENAME_MAX_SIZE bytes plus one byte for the zero terminator. */ -void format_corename(char *corename, const char *pattern, long signr) +static void format_corename(char *corename, const char *pattern, long signr) { const char *pat_ptr = pattern; char *out_ptr = corename; @@ -1374,7 +1375,6 @@ struct file * file; int retval = 0; - lock_kernel(); binfmt = current->binfmt; if (!binfmt || !binfmt->core_dump) goto fail; @@ -1392,7 +1392,13 @@ if (current->rlim[RLIMIT_CORE].rlim_cur < binfmt->min_coredump) goto fail_unlock; - format_corename(corename, core_pattern, signr); + /* + * lock_kernel() because format_corename() is controlled by sysctl, which + * uses lock_kernel() + */ + lock_kernel(); + format_corename(corename, core_pattern, signr); + unlock_kernel(); file = filp_open(corename, O_CREAT | 2 | O_NOFOLLOW | O_LARGEFILE, 0600); if (IS_ERR(file)) goto fail_unlock; @@ -1419,6 +1425,5 @@ fail_unlock: complete_all(&mm->core_done); fail: - unlock_kernel(); return retval; } diff -Nru a/fs/ext2/super.c b/fs/ext2/super.c --- a/fs/ext2/super.c 2004-08-25 22:01:55 -07:00 +++ b/fs/ext2/super.c 2004-08-25 22:01:55 -07:00 @@ -190,7 +190,7 @@ { ext2_inode_cachep = kmem_cache_create("ext2_inode_cache", sizeof(struct ext2_inode_info), - 0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT, + 0, SLAB_RECLAIM_ACCOUNT, init_once, NULL); if (ext2_inode_cachep == NULL) return -ENOMEM; diff -Nru a/fs/ext3/super.c b/fs/ext3/super.c --- a/fs/ext3/super.c 2004-08-25 22:01:56 -07:00 +++ b/fs/ext3/super.c 2004-08-25 22:01:56 -07:00 @@ -477,7 +477,7 @@ { ext3_inode_cachep = kmem_cache_create("ext3_inode_cache", sizeof(struct ext3_inode_info), - 0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT, + 0, SLAB_RECLAIM_ACCOUNT, init_once, NULL); if (ext3_inode_cachep == NULL) return -ENOMEM; diff -Nru a/fs/fat/file.c b/fs/fat/file.c --- a/fs/fat/file.c 2004-08-25 22:01:54 -07:00 +++ b/fs/fat/file.c 2004-08-25 22:01:54 -07:00 @@ -90,12 +90,6 @@ const unsigned int cluster_size = sbi->cluster_size; int nr_clusters; - /* Why no return value? Surely the disk could fail... */ - if (IS_RDONLY (inode)) - return /* -EPERM */; - if (IS_IMMUTABLE(inode)) - return /* -EPERM */; - /* * This protects against truncating a file bigger than it was then * trying to write into the hole. diff -Nru a/fs/fat/inode.c b/fs/fat/inode.c --- a/fs/fat/inode.c 2004-08-25 22:01:55 -07:00 +++ b/fs/fat/inode.c 2004-08-25 22:01:55 -07:00 @@ -744,7 +744,7 @@ { fat_inode_cachep = kmem_cache_create("fat_inode_cache", sizeof(struct msdos_inode_info), - 0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT, + 0, SLAB_RECLAIM_ACCOUNT, init_once, NULL); if (fat_inode_cachep == NULL) return -ENOMEM; diff -Nru a/fs/hostfs/Makefile b/fs/hostfs/Makefile --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/fs/hostfs/Makefile 2004-08-25 22:01:56 -07:00 @@ -0,0 +1,26 @@ +# +# Copyright (C) 2000 Jeff Dike (jdike@karaya.com) +# Licensed under the GPL +# + +# struct stat64 changed the inode field name between 2.2 and 2.4 from st_ino +# to __st_ino. It stayed in the same place, so as long as the correct name +# is used, hostfs compiled on 2.2 should work on 2.4 and vice versa. + +STAT64_INO_FIELD := $(shell grep -q __st_ino /usr/include/bits/stat.h && \ + echo __)st_ino + +hostfs-objs := hostfs_kern.o hostfs_user.o + +obj-y = +obj-$(CONFIG_HOSTFS) += hostfs.o + +SINGLE_OBJS = $(foreach f,$(patsubst %.o,%,$(obj-y) $(obj-m)),$($(f)-objs)) + +USER_OBJS := $(filter %_user.o,$(obj-y) $(obj-m) $(SINGLE_OBJS)) +USER_OBJS := $(foreach file,$(USER_OBJS),$(obj)/$(file)) + +USER_CFLAGS += -DSTAT64_INO_FIELD=$(STAT64_INO_FIELD) + +$(USER_OBJS) : %.o: %.c + $(CC) $(CFLAGS_$(notdir $@)) $(USER_CFLAGS) -c -o $@ $< diff -Nru a/fs/hostfs/hostfs.h b/fs/hostfs/hostfs.h --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/fs/hostfs/hostfs.h 2004-08-25 22:01:56 -07:00 @@ -0,0 +1,79 @@ +#ifndef __UM_FS_HOSTFS +#define __UM_FS_HOSTFS + +#include "os.h" + +/* These are exactly the same definitions as in fs.h, but the names are + * changed so that this file can be included in both kernel and user files. + */ + +#define HOSTFS_ATTR_MODE 1 +#define HOSTFS_ATTR_UID 2 +#define HOSTFS_ATTR_GID 4 +#define HOSTFS_ATTR_SIZE 8 +#define HOSTFS_ATTR_ATIME 16 +#define HOSTFS_ATTR_MTIME 32 +#define HOSTFS_ATTR_CTIME 64 +#define HOSTFS_ATTR_ATIME_SET 128 +#define HOSTFS_ATTR_MTIME_SET 256 +#define HOSTFS_ATTR_FORCE 512 /* Not a change, but a change it */ +#define HOSTFS_ATTR_ATTR_FLAG 1024 + +struct hostfs_iattr { + unsigned int ia_valid; + mode_t ia_mode; + uid_t ia_uid; + gid_t ia_gid; + loff_t ia_size; + struct timespec ia_atime; + struct timespec ia_mtime; + struct timespec ia_ctime; + unsigned int ia_attr_flags; +}; + +extern int stat_file(const char *path, unsigned long long *inode_out, + int *mode_out, int *nlink_out, int *uid_out, int *gid_out, + unsigned long long *size_out, struct timespec *atime_out, + struct timespec *mtime_out, struct timespec *ctime_out, + int *blksize_out, unsigned long long *blocks_out); +extern int access_file(char *path, int r, int w, int x); +extern int open_file(char *path, int r, int w, int append); +extern int file_type(const char *path, int *rdev); +extern void *open_dir(char *path, int *err_out); +extern char *read_dir(void *stream, unsigned long long *pos, + unsigned long long *ino_out, int *len_out); +extern void close_file(void *stream); +extern void close_dir(void *stream); +extern int read_file(int fd, unsigned long long *offset, char *buf, int len); +extern int write_file(int fd, unsigned long long *offset, const char *buf, + int len); +extern int lseek_file(int fd, long long offset, int whence); +extern int file_create(char *name, int ur, int uw, int ux, int gr, + int gw, int gx, int or, int ow, int ox); +extern int set_attr(const char *file, struct hostfs_iattr *attrs); +extern int make_symlink(const char *from, const char *to); +extern int unlink_file(const char *file); +extern int do_mkdir(const char *file, int mode); +extern int do_rmdir(const char *file); +extern int do_mknod(const char *file, int mode, int dev); +extern int link_file(const char *from, const char *to); +extern int do_readlink(char *file, char *buf, int size); +extern int rename_file(char *from, char *to); +extern int do_statfs(char *root, long *bsize_out, long long *blocks_out, + long long *bfree_out, long long *bavail_out, + long long *files_out, long long *ffree_out, + void *fsid_out, int fsid_size, long *namelen_out, + long *spare_out); + +#endif + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff -Nru a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/fs/hostfs/hostfs_kern.c 2004-08-25 22:01:56 -07:00 @@ -0,0 +1,1024 @@ +/* + * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) + * Licensed under the GPL + * + * Ported the filesystem routines to 2.5. + * 2003-02-10 Petr Baudis + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "hostfs.h" +#include "kern_util.h" +#include "kern.h" +#include "user_util.h" +#include "2_5compat.h" +#include "init.h" + +struct hostfs_inode_info { + char *host_filename; + int fd; + int mode; + struct inode vfs_inode; +}; + +static inline struct hostfs_inode_info *HOSTFS_I(struct inode *inode) +{ + return(list_entry(inode, struct hostfs_inode_info, vfs_inode)); +} + +#define FILE_HOSTFS_I(file) HOSTFS_I((file)->f_dentry->d_inode) + +int hostfs_d_delete(struct dentry *dentry) +{ + return(1); +} + +struct dentry_operations hostfs_dentry_ops = { + .d_delete = hostfs_d_delete, +}; + +/* Changed in hostfs_args before the kernel starts running */ +static char *root_ino = "/"; +static int append = 0; + +#define HOSTFS_SUPER_MAGIC 0x00c0ffee + +static struct inode_operations hostfs_iops; +static struct inode_operations hostfs_dir_iops; +static struct address_space_operations hostfs_link_aops; + +#ifndef MODULE +static int __init hostfs_args(char *options, int *add) +{ + char *ptr; + + ptr = strchr(options, ','); + if(ptr != NULL) + *ptr++ = '\0'; + if(*options != '\0') + root_ino = options; + + options = ptr; + while(options){ + ptr = strchr(options, ','); + if(ptr != NULL) + *ptr++ = '\0'; + if(*options != '\0'){ + if(!strcmp(options, "append")) + append = 1; + else printf("hostfs_args - unsupported option - %s\n", + options); + } + options = ptr; + } + return(0); +} + +__uml_setup("hostfs=", hostfs_args, +"hostfs=,,...\n" +" This is used to set hostfs parameters. The root directory argument\n" +" is used to confine all hostfs mounts to within the specified directory\n" +" tree on the host. If this isn't specified, then a user inside UML can\n" +" mount anything on the host that's accessible to the user that's running\n" +" it.\n" +" The only flag currently supported is 'append', which specifies that all\n" +" files opened by hostfs will be opened in append mode.\n\n" +); +#endif + +static char *dentry_name(struct dentry *dentry, int extra) +{ + struct dentry *parent; + char *root, *name; + int len; + + len = 0; + parent = dentry; + while(parent->d_parent != parent){ + len += parent->d_name.len + 1; + parent = parent->d_parent; + } + + root = HOSTFS_I(parent->d_inode)->host_filename; + len += strlen(root); + name = kmalloc(len + extra + 1, GFP_KERNEL); + if(name == NULL) return(NULL); + + name[len] = '\0'; + parent = dentry; + while(parent->d_parent != parent){ + len -= parent->d_name.len + 1; + name[len] = '/'; + strncpy(&name[len + 1], parent->d_name.name, + parent->d_name.len); + parent = parent->d_parent; + } + strncpy(name, root, strlen(root)); + return(name); +} + +static char *inode_name(struct inode *ino, int extra) +{ + struct dentry *dentry; + + dentry = list_entry(ino->i_dentry.next, struct dentry, d_alias); + return(dentry_name(dentry, extra)); +} + +static int read_name(struct inode *ino, char *name) +{ + /* The non-int inode fields are copied into ints by stat_file and + * then copied into the inode because passing the actual pointers + * in and having them treated as int * breaks on big-endian machines + */ + int err; + int i_mode, i_nlink, i_blksize; + unsigned long long i_size; + unsigned long long i_ino; + unsigned long long i_blocks; + + err = stat_file(name, &i_ino, &i_mode, &i_nlink, &ino->i_uid, + &ino->i_gid, &i_size, &ino->i_atime, &ino->i_mtime, + &ino->i_ctime, &i_blksize, &i_blocks); + if(err) + return(err); + + ino->i_ino = i_ino; + ino->i_mode = i_mode; + ino->i_nlink = i_nlink; + ino->i_size = i_size; + ino->i_blksize = i_blksize; + ino->i_blocks = i_blocks; + if((ino->i_sb->s_dev == ROOT_DEV) && (ino->i_uid == getuid())) + ino->i_uid = 0; + return(0); +} + +static char *follow_link(char *link) +{ + int len, n; + char *name, *resolved, *end; + + len = 64; + while(1){ + n = -ENOMEM; + name = kmalloc(len, GFP_KERNEL); + if(name == NULL) + goto out; + + n = do_readlink(link, name, len); + if(n < len) + break; + len *= 2; + kfree(name); + } + if(n < 0) + goto out_free; + + if(*name == '/') + return(name); + + end = strrchr(link, '/'); + if(end == NULL) + return(name); + + *(end + 1) = '\0'; + len = strlen(link) + strlen(name) + 1; + + resolved = kmalloc(len, GFP_KERNEL); + if(resolved == NULL){ + n = -ENOMEM; + goto out_free; + } + + sprintf(resolved, "%s%s", link, name); + kfree(name); + kfree(link); + return(resolved); + + out_free: + kfree(name); + out: + return(ERR_PTR(n)); +} + +static int read_inode(struct inode *ino) +{ + char *name; + int err = 0; + + /* Unfortunately, we are called from iget() when we don't have a dentry + * allocated yet. + */ + if(list_empty(&ino->i_dentry)) + goto out; + + err = -ENOMEM; + name = inode_name(ino, 0); + if(name == NULL) + goto out; + + if(file_type(name, NULL) == OS_TYPE_SYMLINK){ + name = follow_link(name); + if(IS_ERR(name)){ + err = PTR_ERR(name); + goto out; + } + } + + err = read_name(ino, name); + kfree(name); + out: + return(err); +} + +int hostfs_statfs(struct super_block *sb, struct kstatfs *sf) +{ + /* do_statfs uses struct statfs64 internally, but the linux kernel + * struct statfs still has 32-bit versions for most of these fields, + * so we convert them here + */ + int err; + long long f_blocks; + long long f_bfree; + long long f_bavail; + long long f_files; + long long f_ffree; + + err = do_statfs(HOSTFS_I(sb->s_root->d_inode)->host_filename, + &sf->f_bsize, &f_blocks, &f_bfree, &f_bavail, &f_files, + &f_ffree, &sf->f_fsid, sizeof(sf->f_fsid), + &sf->f_namelen, sf->f_spare); + if(err) return(err); + sf->f_blocks = f_blocks; + sf->f_bfree = f_bfree; + sf->f_bavail = f_bavail; + sf->f_files = f_files; + sf->f_ffree = f_ffree; + sf->f_type = HOSTFS_SUPER_MAGIC; + return(0); +} + +static struct inode *hostfs_alloc_inode(struct super_block *sb) +{ + struct hostfs_inode_info *hi; + + hi = kmalloc(sizeof(*hi), GFP_KERNEL); + if(hi == NULL) + return(NULL); + + *hi = ((struct hostfs_inode_info) { .host_filename = NULL, + .fd = -1, + .mode = 0 }); + inode_init_once(&hi->vfs_inode); + return(&hi->vfs_inode); +} + +static void hostfs_delete_inode(struct inode *inode) +{ + if(HOSTFS_I(inode)->fd != -1) { + close_file(&HOSTFS_I(inode)->fd); + printk("Closing host fd in .delete_inode\n"); + HOSTFS_I(inode)->fd = -1; + } + clear_inode(inode); +} + +static void hostfs_destroy_inode(struct inode *inode) +{ + if(HOSTFS_I(inode)->host_filename) + kfree(HOSTFS_I(inode)->host_filename); + + if(HOSTFS_I(inode)->fd != -1) { + close_file(&HOSTFS_I(inode)->fd); + printk("Closing host fd in .destroy_inode\n"); + } + + kfree(HOSTFS_I(inode)); +} + +static void hostfs_read_inode(struct inode *inode) +{ + read_inode(inode); +} + +static struct super_operations hostfs_sbops = { + .alloc_inode = hostfs_alloc_inode, + .drop_inode = generic_delete_inode, + .delete_inode = hostfs_delete_inode, + .destroy_inode = hostfs_destroy_inode, + .read_inode = hostfs_read_inode, + .statfs = hostfs_statfs, +}; + +int hostfs_readdir(struct file *file, void *ent, filldir_t filldir) +{ + void *dir; + char *name; + unsigned long long next, ino; + int error, len; + + name = dentry_name(file->f_dentry, 0); + if(name == NULL) return(-ENOMEM); + dir = open_dir(name, &error); + kfree(name); + if(dir == NULL) return(-error); + next = file->f_pos; + while((name = read_dir(dir, &next, &ino, &len)) != NULL){ + error = (*filldir)(ent, name, len, file->f_pos, + ino, DT_UNKNOWN); + if(error) break; + file->f_pos = next; + } + close_dir(dir); + return(0); +} + +int hostfs_file_open(struct inode *ino, struct file *file) +{ + char *name; + int mode = 0, r = 0, w = 0, fd; + + mode = file->f_mode & (FMODE_READ | FMODE_WRITE); + if((mode & HOSTFS_I(ino)->mode) == mode) + return(0); + + /* The file may already have been opened, but with the wrong access, + * so this resets things and reopens the file with the new access. + */ + if(HOSTFS_I(ino)->fd != -1){ + close_file(&HOSTFS_I(ino)->fd); + HOSTFS_I(ino)->fd = -1; + } + + HOSTFS_I(ino)->mode |= mode; + if(HOSTFS_I(ino)->mode & FMODE_READ) + r = 1; + if(HOSTFS_I(ino)->mode & FMODE_WRITE) + w = 1; + if(w) + r = 1; + + name = dentry_name(file->f_dentry, 0); + if(name == NULL) + return(-ENOMEM); + + fd = open_file(name, r, w, append); + kfree(name); + if(fd < 0) return(fd); + FILE_HOSTFS_I(file)->fd = fd; + + return(0); +} + +int hostfs_fsync(struct file *file, struct dentry *dentry, int datasync) +{ + return(0); +} + +static struct file_operations hostfs_file_fops = { + .llseek = generic_file_llseek, + .read = generic_file_read, + .write = generic_file_write, + .mmap = generic_file_mmap, + .open = hostfs_file_open, + .release = NULL, + .fsync = hostfs_fsync, +}; + +static struct file_operations hostfs_dir_fops = { + .readdir = hostfs_readdir, + .read = generic_read_dir, +}; + +int hostfs_writepage(struct page *page, struct writeback_control *wbc) +{ + struct address_space *mapping = page->mapping; + struct inode *inode = mapping->host; + char *buffer; + unsigned long long base; + int count = PAGE_CACHE_SIZE; + int end_index = inode->i_size >> PAGE_CACHE_SHIFT; + int err; + + if (page->index >= end_index) + count = inode->i_size & (PAGE_CACHE_SIZE-1); + + buffer = kmap(page); + base = ((unsigned long long) page->index) << PAGE_CACHE_SHIFT; + + err = write_file(HOSTFS_I(inode)->fd, &base, buffer, count); + if(err != count){ + ClearPageUptodate(page); + goto out; + } + + if (base > inode->i_size) + inode->i_size = base; + + if (PageError(page)) + ClearPageError(page); + err = 0; + + out: + kunmap(page); + + unlock_page(page); + return err; +} + +int hostfs_readpage(struct file *file, struct page *page) +{ + char *buffer; + long long start; + int err = 0; + + start = (long long) page->index << PAGE_CACHE_SHIFT; + buffer = kmap(page); + err = read_file(FILE_HOSTFS_I(file)->fd, &start, buffer, + PAGE_CACHE_SIZE); + if(err < 0) goto out; + + memset(&buffer[err], 0, PAGE_CACHE_SIZE - err); + + flush_dcache_page(page); + SetPageUptodate(page); + if (PageError(page)) ClearPageError(page); + err = 0; + out: + kunmap(page); + unlock_page(page); + return(err); +} + +int hostfs_prepare_write(struct file *file, struct page *page, + unsigned int from, unsigned int to) +{ + char *buffer; + long long start, tmp; + int err; + + start = (long long) page->index << PAGE_CACHE_SHIFT; + buffer = kmap(page); + if(from != 0){ + tmp = start; + err = read_file(FILE_HOSTFS_I(file)->fd, &tmp, buffer, + from); + if(err < 0) goto out; + } + if(to != PAGE_CACHE_SIZE){ + start += to; + err = read_file(FILE_HOSTFS_I(file)->fd, &start, buffer + to, + PAGE_CACHE_SIZE - to); + if(err < 0) goto out; + } + err = 0; + out: + kunmap(page); + return(err); +} + +int hostfs_commit_write(struct file *file, struct page *page, unsigned from, + unsigned to) +{ + struct address_space *mapping = page->mapping; + struct inode *inode = mapping->host; + char *buffer; + long long start; + int err = 0; + + start = (long long) (page->index << PAGE_CACHE_SHIFT) + from; + buffer = kmap(page); + err = write_file(FILE_HOSTFS_I(file)->fd, &start, buffer + from, + to - from); + if(err > 0) err = 0; + if(!err && (start > inode->i_size)) + inode->i_size = start; + + kunmap(page); + return(err); +} + +static struct address_space_operations hostfs_aops = { + .writepage = hostfs_writepage, + .readpage = hostfs_readpage, +/* .set_page_dirty = __set_page_dirty_nobuffers, */ + .prepare_write = hostfs_prepare_write, + .commit_write = hostfs_commit_write +}; + +static int init_inode(struct inode *inode, struct dentry *dentry) +{ + char *name; + int type, err = -ENOMEM, rdev; + + if(dentry){ + name = dentry_name(dentry, 0); + if(name == NULL) + goto out; + type = file_type(name, &rdev); + kfree(name); + } + else type = OS_TYPE_DIR; + + err = 0; + if(type == OS_TYPE_SYMLINK) + inode->i_op = &page_symlink_inode_operations; + else if(type == OS_TYPE_DIR) + inode->i_op = &hostfs_dir_iops; + else inode->i_op = &hostfs_iops; + + if(type == OS_TYPE_DIR) inode->i_fop = &hostfs_dir_fops; + else inode->i_fop = &hostfs_file_fops; + + if(type == OS_TYPE_SYMLINK) + inode->i_mapping->a_ops = &hostfs_link_aops; + else inode->i_mapping->a_ops = &hostfs_aops; + + switch (type) { + case OS_TYPE_CHARDEV: + init_special_inode(inode, S_IFCHR, rdev); + break; + case OS_TYPE_BLOCKDEV: + init_special_inode(inode, S_IFBLK, rdev); + break; + case OS_TYPE_FIFO: + init_special_inode(inode, S_IFIFO, 0); + break; + case OS_TYPE_SOCK: + init_special_inode(inode, S_IFSOCK, 0); + break; + } + out: + return(err); +} + +int hostfs_create(struct inode *dir, struct dentry *dentry, int mode, + struct nameidata *nd) +{ + struct inode *inode; + char *name; + int error, fd; + + error = -ENOMEM; + inode = iget(dir->i_sb, 0); + if(inode == NULL) goto out; + + error = init_inode(inode, dentry); + if(error) + goto out_put; + + error = -ENOMEM; + name = dentry_name(dentry, 0); + if(name == NULL) + goto out_put; + + fd = file_create(name, + mode & S_IRUSR, mode & S_IWUSR, mode & S_IXUSR, + mode & S_IRGRP, mode & S_IWGRP, mode & S_IXGRP, + mode & S_IROTH, mode & S_IWOTH, mode & S_IXOTH); + if(fd < 0) + error = fd; + else error = read_name(inode, name); + + kfree(name); + if(error) + goto out_put; + + HOSTFS_I(inode)->fd = fd; + HOSTFS_I(inode)->mode = FMODE_READ | FMODE_WRITE; + d_instantiate(dentry, inode); + return(0); + + out_put: + iput(inode); + out: + return(error); +} + +struct dentry *hostfs_lookup(struct inode *ino, struct dentry *dentry, + struct nameidata *nd) +{ + struct inode *inode; + char *name; + int err; + + err = -ENOMEM; + inode = iget(ino->i_sb, 0); + if(inode == NULL) + goto out; + + err = init_inode(inode, dentry); + if(err) + goto out_put; + + err = -ENOMEM; + name = dentry_name(dentry, 0); + if(name == NULL) + goto out_put; + + err = read_name(inode, name); + kfree(name); + if(err == -ENOENT){ + iput(inode); + inode = NULL; + } + else if(err) + goto out_put; + + d_add(dentry, inode); + dentry->d_op = &hostfs_dentry_ops; + return(NULL); + + out_put: + iput(inode); + out: + return(ERR_PTR(err)); +} + +static char *inode_dentry_name(struct inode *ino, struct dentry *dentry) +{ + char *file; + int len; + + file = inode_name(ino, dentry->d_name.len + 1); + if(file == NULL) return(NULL); + strcat(file, "/"); + len = strlen(file); + strncat(file, dentry->d_name.name, dentry->d_name.len); + file[len + dentry->d_name.len] = '\0'; + return(file); +} + +int hostfs_link(struct dentry *to, struct inode *ino, struct dentry *from) +{ + char *from_name, *to_name; + int err; + + if((from_name = inode_dentry_name(ino, from)) == NULL) + return(-ENOMEM); + to_name = dentry_name(to, 0); + if(to_name == NULL){ + kfree(from_name); + return(-ENOMEM); + } + err = link_file(to_name, from_name); + kfree(from_name); + kfree(to_name); + return(err); +} + +int hostfs_unlink(struct inode *ino, struct dentry *dentry) +{ + char *file; + int err; + + if((file = inode_dentry_name(ino, dentry)) == NULL) return(-ENOMEM); + if(append) + return(-EPERM); + + err = unlink_file(file); + kfree(file); + return(err); +} + +int hostfs_symlink(struct inode *ino, struct dentry *dentry, const char *to) +{ + char *file; + int err; + + if((file = inode_dentry_name(ino, dentry)) == NULL) return(-ENOMEM); + err = make_symlink(file, to); + kfree(file); + return(err); +} + +int hostfs_mkdir(struct inode *ino, struct dentry *dentry, int mode) +{ + char *file; + int err; + + if((file = inode_dentry_name(ino, dentry)) == NULL) return(-ENOMEM); + err = do_mkdir(file, mode); + kfree(file); + return(err); +} + +int hostfs_rmdir(struct inode *ino, struct dentry *dentry) +{ + char *file; + int err; + + if((file = inode_dentry_name(ino, dentry)) == NULL) return(-ENOMEM); + err = do_rmdir(file); + kfree(file); + return(err); +} + +int hostfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev) +{ + struct inode *inode; + char *name; + int err = -ENOMEM; + + inode = iget(dir->i_sb, 0); + if(inode == NULL) + goto out; + + err = init_inode(inode, dentry); + if(err) + goto out_put; + + err = -ENOMEM; + name = dentry_name(dentry, 0); + if(name == NULL) + goto out_put; + + init_special_inode(inode, mode, dev); + err = do_mknod(name, mode, dev); + if(err) + goto out_free; + + err = read_name(inode, name); + kfree(name); + if(err) + goto out_put; + + d_instantiate(dentry, inode); + return(0); + + out_free: + kfree(name); + out_put: + iput(inode); + out: + return(err); +} + +int hostfs_rename(struct inode *from_ino, struct dentry *from, + struct inode *to_ino, struct dentry *to) +{ + char *from_name, *to_name; + int err; + + if((from_name = inode_dentry_name(from_ino, from)) == NULL) + return(-ENOMEM); + if((to_name = inode_dentry_name(to_ino, to)) == NULL){ + kfree(from_name); + return(-ENOMEM); + } + err = rename_file(from_name, to_name); + kfree(from_name); + kfree(to_name); + return(err); +} + +void hostfs_truncate(struct inode *ino) +{ + not_implemented(); +} + +int hostfs_permission(struct inode *ino, int desired, struct nameidata *nd) +{ + char *name; + int r = 0, w = 0, x = 0, err; + + if(desired & MAY_READ) r = 1; + if(desired & MAY_WRITE) w = 1; + if(desired & MAY_EXEC) x = 1; + name = inode_name(ino, 0); + if(name == NULL) return(-ENOMEM); + err = access_file(name, r, w, x); + kfree(name); + if(!err) err = vfs_permission(ino, desired); + return(err); +} + +int hostfs_setattr(struct dentry *dentry, struct iattr *attr) +{ + struct hostfs_iattr attrs; + char *name; + int err; + + if(append) + attr->ia_valid &= ~ATTR_SIZE; + + attrs.ia_valid = 0; + if(attr->ia_valid & ATTR_MODE){ + attrs.ia_valid |= HOSTFS_ATTR_MODE; + attrs.ia_mode = attr->ia_mode; + } + if(attr->ia_valid & ATTR_UID){ + if((dentry->d_inode->i_sb->s_dev == ROOT_DEV) && + (attr->ia_uid == 0)) + attr->ia_uid = getuid(); + attrs.ia_valid |= HOSTFS_ATTR_UID; + attrs.ia_uid = attr->ia_uid; + } + if(attr->ia_valid & ATTR_GID){ + if((dentry->d_inode->i_sb->s_dev == ROOT_DEV) && + (attr->ia_gid == 0)) + attr->ia_gid = getuid(); + attrs.ia_valid |= HOSTFS_ATTR_GID; + attrs.ia_gid = attr->ia_gid; + } + if(attr->ia_valid & ATTR_SIZE){ + attrs.ia_valid |= HOSTFS_ATTR_SIZE; + attrs.ia_size = attr->ia_size; + } + if(attr->ia_valid & ATTR_ATIME){ + attrs.ia_valid |= HOSTFS_ATTR_ATIME; + attrs.ia_atime = attr->ia_atime; + } + if(attr->ia_valid & ATTR_MTIME){ + attrs.ia_valid |= HOSTFS_ATTR_MTIME; + attrs.ia_mtime = attr->ia_mtime; + } + if(attr->ia_valid & ATTR_CTIME){ + attrs.ia_valid |= HOSTFS_ATTR_CTIME; + attrs.ia_ctime = attr->ia_ctime; + } + if(attr->ia_valid & ATTR_ATIME_SET){ + attrs.ia_valid |= HOSTFS_ATTR_ATIME_SET; + } + if(attr->ia_valid & ATTR_MTIME_SET){ + attrs.ia_valid |= HOSTFS_ATTR_MTIME_SET; + } + name = dentry_name(dentry, 0); + if(name == NULL) return(-ENOMEM); + err = set_attr(name, &attrs); + kfree(name); + if(err) + return(err); + + return(inode_setattr(dentry->d_inode, attr)); +} + +int hostfs_getattr(struct vfsmount *mnt, struct dentry *dentry, + struct kstat *stat) +{ + generic_fillattr(dentry->d_inode, stat); + return(0); +} + +static struct inode_operations hostfs_iops = { + .create = hostfs_create, + .link = hostfs_link, + .unlink = hostfs_unlink, + .symlink = hostfs_symlink, + .mkdir = hostfs_mkdir, + .rmdir = hostfs_rmdir, + .mknod = hostfs_mknod, + .rename = hostfs_rename, + .truncate = hostfs_truncate, + .permission = hostfs_permission, + .setattr = hostfs_setattr, + .getattr = hostfs_getattr, +}; + +static struct inode_operations hostfs_dir_iops = { + .create = hostfs_create, + .lookup = hostfs_lookup, + .link = hostfs_link, + .unlink = hostfs_unlink, + .symlink = hostfs_symlink, + .mkdir = hostfs_mkdir, + .rmdir = hostfs_rmdir, + .mknod = hostfs_mknod, + .rename = hostfs_rename, + .truncate = hostfs_truncate, + .permission = hostfs_permission, + .setattr = hostfs_setattr, + .getattr = hostfs_getattr, +}; + +int hostfs_link_readpage(struct file *file, struct page *page) +{ + char *buffer, *name; + long long start; + int err; + + start = page->index << PAGE_CACHE_SHIFT; + buffer = kmap(page); + name = inode_name(page->mapping->host, 0); + if(name == NULL) return(-ENOMEM); + err = do_readlink(name, buffer, PAGE_CACHE_SIZE); + kfree(name); + if(err == PAGE_CACHE_SIZE) + err = -E2BIG; + else if(err > 0){ + flush_dcache_page(page); + SetPageUptodate(page); + if (PageError(page)) ClearPageError(page); + err = 0; + } + kunmap(page); + unlock_page(page); + return(err); +} + +static struct address_space_operations hostfs_link_aops = { + .readpage = hostfs_link_readpage, +}; + +static int hostfs_fill_sb_common(struct super_block *sb, void *d, int silent) +{ + struct inode *root_inode; + char *name, *data = d; + int err; + + sb->s_blocksize = 1024; + sb->s_blocksize_bits = 10; + sb->s_magic = HOSTFS_SUPER_MAGIC; + sb->s_op = &hostfs_sbops; + + if((data == NULL) || (*data == '\0')) + data = root_ino; + + err = -ENOMEM; + name = kmalloc(strlen(data) + 1, GFP_KERNEL); + if(name == NULL) + goto out; + + strcpy(name, data); + + root_inode = iget(sb, 0); + if(root_inode == NULL) + goto out_free; + + err = init_inode(root_inode, NULL); + if(err) + goto out_put; + + HOSTFS_I(root_inode)->host_filename = name; + + err = -ENOMEM; + sb->s_root = d_alloc_root(root_inode); + if(sb->s_root == NULL) + goto out_put; + + err = read_inode(root_inode); + if(err) + goto out_put; + + return(0); + + out_put: + iput(root_inode); + out_free: + kfree(name); + out: + return(err); +} + +static struct super_block *hostfs_read_sb(struct file_system_type *type, + int flags, const char *dev_name, + void *data) +{ + return(get_sb_nodev(type, flags, data, hostfs_fill_sb_common)); +} + +static struct file_system_type hostfs_type = { + .owner = THIS_MODULE, + .name = "hostfs", + .get_sb = hostfs_read_sb, + .kill_sb = kill_anon_super, + .fs_flags = 0, +}; + +static int __init init_hostfs(void) +{ + return(register_filesystem(&hostfs_type)); +} + +static void __exit exit_hostfs(void) +{ + unregister_filesystem(&hostfs_type); +} + +module_init(init_hostfs) +module_exit(exit_hostfs) +MODULE_LICENSE("GPL"); + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff -Nru a/fs/hostfs/hostfs_user.c b/fs/hostfs/hostfs_user.c --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/fs/hostfs/hostfs_user.c 2004-08-25 22:01:56 -07:00 @@ -0,0 +1,361 @@ +/* + * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) + * Licensed under the GPL + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "hostfs.h" +#include "kern_util.h" +#include "user.h" + +int stat_file(const char *path, unsigned long long *inode_out, int *mode_out, + int *nlink_out, int *uid_out, int *gid_out, + unsigned long long *size_out, struct timespec *atime_out, + struct timespec *mtime_out, struct timespec *ctime_out, + int *blksize_out, unsigned long long *blocks_out) +{ + struct stat64 buf; + + if(lstat64(path, &buf) < 0) + return(-errno); + + /* See the Makefile for why STAT64_INO_FIELD is passed in + * by the build + */ + if(inode_out != NULL) *inode_out = buf.STAT64_INO_FIELD; + if(mode_out != NULL) *mode_out = buf.st_mode; + if(nlink_out != NULL) *nlink_out = buf.st_nlink; + if(uid_out != NULL) *uid_out = buf.st_uid; + if(gid_out != NULL) *gid_out = buf.st_gid; + if(size_out != NULL) *size_out = buf.st_size; + if(atime_out != NULL) { + atime_out->tv_sec = buf.st_atime; + atime_out->tv_nsec = 0; + } + if(mtime_out != NULL) { + mtime_out->tv_sec = buf.st_mtime; + mtime_out->tv_nsec = 0; + } + if(ctime_out != NULL) { + ctime_out->tv_sec = buf.st_ctime; + ctime_out->tv_nsec = 0; + } + if(blksize_out != NULL) *blksize_out = buf.st_blksize; + if(blocks_out != NULL) *blocks_out = buf.st_blocks; + return(0); +} + +int file_type(const char *path, int *rdev) +{ + struct stat64 buf; + + if(lstat64(path, &buf) < 0) + return(-errno); + if(rdev != NULL) + *rdev = buf.st_rdev; + + if(S_ISDIR(buf.st_mode)) return(OS_TYPE_DIR); + else if(S_ISLNK(buf.st_mode)) return(OS_TYPE_SYMLINK); + else if(S_ISCHR(buf.st_mode)) return(OS_TYPE_CHARDEV); + else if(S_ISBLK(buf.st_mode)) return(OS_TYPE_BLOCKDEV); + else if(S_ISFIFO(buf.st_mode))return(OS_TYPE_FIFO); + else if(S_ISSOCK(buf.st_mode))return(OS_TYPE_SOCK); + else return(OS_TYPE_FILE); +} + +int access_file(char *path, int r, int w, int x) +{ + int mode = 0; + + if(r) mode = R_OK; + if(w) mode |= W_OK; + if(x) mode |= X_OK; + if(access(path, mode) != 0) return(-errno); + else return(0); +} + +int open_file(char *path, int r, int w, int append) +{ + int mode = 0, fd; + + if(r && !w) + mode = O_RDONLY; + else if(!r && w) + mode = O_WRONLY; + else if(r && w) + mode = O_RDWR; + else panic("Impossible mode in open_file"); + + if(append) + mode |= O_APPEND; + fd = open64(path, mode); + if(fd < 0) return(-errno); + else return(fd); +} + +void *open_dir(char *path, int *err_out) +{ + DIR *dir; + + dir = opendir(path); + *err_out = errno; + if(dir == NULL) return(NULL); + return(dir); +} + +char *read_dir(void *stream, unsigned long long *pos, + unsigned long long *ino_out, int *len_out) +{ + DIR *dir = stream; + struct dirent *ent; + + seekdir(dir, *pos); + ent = readdir(dir); + if(ent == NULL) return(NULL); + *len_out = strlen(ent->d_name); + *ino_out = ent->d_ino; + *pos = telldir(dir); + return(ent->d_name); +} + +int read_file(int fd, unsigned long long *offset, char *buf, int len) +{ + int n; + + n = pread64(fd, buf, len, *offset); + if(n < 0) return(-errno); + *offset += n; + return(n); +} + +int write_file(int fd, unsigned long long *offset, const char *buf, int len) +{ + int n; + + n = pwrite64(fd, buf, len, *offset); + if(n < 0) return(-errno); + *offset += n; + return(n); +} + +int lseek_file(int fd, long long offset, int whence) +{ + int ret; + + ret = lseek64(fd, offset, whence); + if(ret < 0) return(-errno); + return(0); +} + +void close_file(void *stream) +{ + close(*((int *) stream)); +} + +void close_dir(void *stream) +{ + closedir(stream); +} + +int file_create(char *name, int ur, int uw, int ux, int gr, + int gw, int gx, int or, int ow, int ox) +{ + int mode, fd; + + mode = 0; + mode |= ur ? S_IRUSR : 0; + mode |= uw ? S_IWUSR : 0; + mode |= ux ? S_IXUSR : 0; + mode |= gr ? S_IRGRP : 0; + mode |= gw ? S_IWGRP : 0; + mode |= gx ? S_IXGRP : 0; + mode |= or ? S_IROTH : 0; + mode |= ow ? S_IWOTH : 0; + mode |= ox ? S_IXOTH : 0; + fd = open64(name, O_CREAT | O_RDWR, mode); + if(fd < 0) + return(-errno); + return(fd); +} + +int set_attr(const char *file, struct hostfs_iattr *attrs) +{ + struct utimbuf buf; + int err, ma; + + if(attrs->ia_valid & HOSTFS_ATTR_MODE){ + if(chmod(file, attrs->ia_mode) != 0) return(-errno); + } + if(attrs->ia_valid & HOSTFS_ATTR_UID){ + if(chown(file, attrs->ia_uid, -1)) return(-errno); + } + if(attrs->ia_valid & HOSTFS_ATTR_GID){ + if(chown(file, -1, attrs->ia_gid)) return(-errno); + } + if(attrs->ia_valid & HOSTFS_ATTR_SIZE){ + if(truncate(file, attrs->ia_size)) return(-errno); + } + ma = HOSTFS_ATTR_ATIME_SET | HOSTFS_ATTR_MTIME_SET; + if((attrs->ia_valid & ma) == ma){ + buf.actime = attrs->ia_atime.tv_sec; + buf.modtime = attrs->ia_mtime.tv_sec; + if(utime(file, &buf) != 0) return(-errno); + } + else { + struct timespec ts; + + if(attrs->ia_valid & HOSTFS_ATTR_ATIME_SET){ + err = stat_file(file, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, &ts, NULL, NULL, NULL); + if(err != 0) + return(err); + buf.actime = attrs->ia_atime.tv_sec; + buf.modtime = ts.tv_sec; + if(utime(file, &buf) != 0) + return(-errno); + } + if(attrs->ia_valid & HOSTFS_ATTR_MTIME_SET){ + err = stat_file(file, NULL, NULL, NULL, NULL, NULL, + NULL, &ts, NULL, NULL, NULL, NULL); + if(err != 0) + return(err); + buf.actime = ts.tv_sec; + buf.modtime = attrs->ia_mtime.tv_sec; + if(utime(file, &buf) != 0) + return(-errno); + } + } + if(attrs->ia_valid & HOSTFS_ATTR_CTIME) ; + if(attrs->ia_valid & (HOSTFS_ATTR_ATIME | HOSTFS_ATTR_MTIME)){ + err = stat_file(file, NULL, NULL, NULL, NULL, NULL, NULL, + &attrs->ia_atime, &attrs->ia_mtime, NULL, + NULL, NULL); + if(err != 0) return(err); + } + return(0); +} + +int make_symlink(const char *from, const char *to) +{ + int err; + + err = symlink(to, from); + if(err) return(-errno); + return(0); +} + +int unlink_file(const char *file) +{ + int err; + + err = unlink(file); + if(err) return(-errno); + return(0); +} + +int do_mkdir(const char *file, int mode) +{ + int err; + + err = mkdir(file, mode); + if(err) return(-errno); + return(0); +} + +int do_rmdir(const char *file) +{ + int err; + + err = rmdir(file); + if(err) return(-errno); + return(0); +} + +int do_mknod(const char *file, int mode, int dev) +{ + int err; + + err = mknod(file, mode, dev); + if(err) return(-errno); + return(0); +} + +int link_file(const char *to, const char *from) +{ + int err; + + err = link(to, from); + if(err) return(-errno); + return(0); +} + +int do_readlink(char *file, char *buf, int size) +{ + int n; + + n = readlink(file, buf, size); + if(n < 0) + return(-errno); + if(n < size) + buf[n] = '\0'; + return(n); +} + +int rename_file(char *from, char *to) +{ + int err; + + err = rename(from, to); + if(err < 0) return(-errno); + return(0); +} + +int do_statfs(char *root, long *bsize_out, long long *blocks_out, + long long *bfree_out, long long *bavail_out, + long long *files_out, long long *ffree_out, + void *fsid_out, int fsid_size, long *namelen_out, + long *spare_out) +{ + struct statfs64 buf; + int err; + + err = statfs64(root, &buf); + if(err < 0) return(-errno); + *bsize_out = buf.f_bsize; + *blocks_out = buf.f_blocks; + *bfree_out = buf.f_bfree; + *bavail_out = buf.f_bavail; + *files_out = buf.f_files; + *ffree_out = buf.f_ffree; + memcpy(fsid_out, &buf.f_fsid, + sizeof(buf.f_fsid) > fsid_size ? fsid_size : + sizeof(buf.f_fsid)); + *namelen_out = buf.f_namelen; + spare_out[0] = buf.f_spare[0]; + spare_out[1] = buf.f_spare[1]; + spare_out[2] = buf.f_spare[2]; + spare_out[3] = buf.f_spare[3]; + spare_out[4] = buf.f_spare[4]; + spare_out[5] = buf.f_spare[5]; + return(0); +} + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff -Nru a/fs/hpfs/super.c b/fs/hpfs/super.c --- a/fs/hpfs/super.c 2004-08-25 22:01:55 -07:00 +++ b/fs/hpfs/super.c 2004-08-25 22:01:55 -07:00 @@ -191,7 +191,7 @@ { hpfs_inode_cachep = kmem_cache_create("hpfs_inode_cache", sizeof(struct hpfs_inode_info), - 0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT, + 0, SLAB_RECLAIM_ACCOUNT, init_once, NULL); if (hpfs_inode_cachep == NULL) return -ENOMEM; diff -Nru a/fs/hppfs/Makefile b/fs/hppfs/Makefile --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/fs/hppfs/Makefile 2004-08-25 22:01:56 -07:00 @@ -0,0 +1,19 @@ +# +# Copyright (C) 2002, 2003 Jeff Dike (jdike@karaya.com) +# Licensed under the GPL +# + +hppfs-objs := hppfs_kern.o + +obj-y = +obj-$(CONFIG_HPPFS) += hppfs.o + +clean: + +modules: + +fastdep: + +dep: + +archmrproper: clean diff -Nru a/fs/hppfs/hppfs_kern.c b/fs/hppfs/hppfs_kern.c --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/fs/hppfs/hppfs_kern.c 2004-08-25 22:01:56 -07:00 @@ -0,0 +1,815 @@ +/* + * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) + * Licensed under the GPL + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "os.h" + +static int init_inode(struct inode *inode, struct dentry *dentry); + +struct hppfs_data { + struct list_head list; + char contents[PAGE_SIZE - sizeof(struct list_head)]; +}; + +struct hppfs_private { + struct file *proc_file; + int host_fd; + loff_t len; + struct hppfs_data *contents; +}; + +struct hppfs_inode_info { + struct dentry *proc_dentry; + struct inode vfs_inode; +}; + +static inline struct hppfs_inode_info *HPPFS_I(struct inode *inode) +{ + return(list_entry(inode, struct hppfs_inode_info, vfs_inode)); +} + +#define HPPFS_SUPER_MAGIC 0xb00000ee + +static struct super_operations hppfs_sbops; + +static int is_pid(struct dentry *dentry) +{ + struct super_block *sb; + int i; + + sb = dentry->d_sb; + if((sb->s_op != &hppfs_sbops) || (dentry->d_parent != sb->s_root)) + return(0); + + for(i = 0; i < dentry->d_name.len; i++){ + if(!isdigit(dentry->d_name.name[i])) + return(0); + } + return(1); +} + +static char *dentry_name(struct dentry *dentry, int extra) +{ + struct dentry *parent; + char *root, *name; + const char *seg_name; + int len, seg_len; + + len = 0; + parent = dentry; + while(parent->d_parent != parent){ + if(is_pid(parent)) + len += strlen("pid") + 1; + else len += parent->d_name.len + 1; + parent = parent->d_parent; + } + + root = "proc"; + len += strlen(root); + name = kmalloc(len + extra + 1, GFP_KERNEL); + if(name == NULL) return(NULL); + + name[len] = '\0'; + parent = dentry; + while(parent->d_parent != parent){ + if(is_pid(parent)){ + seg_name = "pid"; + seg_len = strlen("pid"); + } + else { + seg_name = parent->d_name.name; + seg_len = parent->d_name.len; + } + + len -= seg_len + 1; + name[len] = '/'; + strncpy(&name[len + 1], seg_name, seg_len); + parent = parent->d_parent; + } + strncpy(name, root, strlen(root)); + return(name); +} + +struct dentry_operations hppfs_dentry_ops = { +}; + +static int file_removed(struct dentry *dentry, const char *file) +{ + char *host_file; + int extra, fd; + + extra = 0; + if(file != NULL) extra += strlen(file) + 1; + + host_file = dentry_name(dentry, extra + strlen("/remove")); + if(host_file == NULL){ + printk("file_removed : allocation failed\n"); + return(-ENOMEM); + } + + if(file != NULL){ + strcat(host_file, "/"); + strcat(host_file, file); + } + strcat(host_file, "/remove"); + + fd = os_open_file(host_file, of_read(OPENFLAGS()), 0); + kfree(host_file); + if(fd > 0){ + os_close_file(fd); + return(1); + } + return(0); +} + +static void hppfs_read_inode(struct inode *ino) +{ + struct inode *proc_ino; + + if(HPPFS_I(ino)->proc_dentry == NULL) + return; + + proc_ino = HPPFS_I(ino)->proc_dentry->d_inode; + ino->i_uid = proc_ino->i_uid; + ino->i_gid = proc_ino->i_gid; + ino->i_atime = proc_ino->i_atime; + ino->i_mtime = proc_ino->i_mtime; + ino->i_ctime = proc_ino->i_ctime; + ino->i_ino = proc_ino->i_ino; + ino->i_mode = proc_ino->i_mode; + ino->i_nlink = proc_ino->i_nlink; + ino->i_size = proc_ino->i_size; + ino->i_blksize = proc_ino->i_blksize; + ino->i_blocks = proc_ino->i_blocks; +} + +static struct dentry *hppfs_lookup(struct inode *ino, struct dentry *dentry, + struct nameidata *nd) +{ + struct dentry *proc_dentry, *new, *parent; + struct inode *inode; + int err, deleted; + + deleted = file_removed(dentry, NULL); + if(deleted < 0) + return(ERR_PTR(deleted)); + else if(deleted) + return(ERR_PTR(-ENOENT)); + + err = -ENOMEM; + parent = HPPFS_I(ino)->proc_dentry; + down(&parent->d_inode->i_sem); + proc_dentry = d_lookup(parent, &dentry->d_name); + if(proc_dentry == NULL){ + proc_dentry = d_alloc(parent, &dentry->d_name); + if(proc_dentry == NULL){ + up(&parent->d_inode->i_sem); + goto out; + } + new = (*parent->d_inode->i_op->lookup)(parent->d_inode, + proc_dentry, NULL); + if(new){ + dput(proc_dentry); + proc_dentry = new; + } + } + up(&parent->d_inode->i_sem); + + if(IS_ERR(proc_dentry)) + return(proc_dentry); + + inode = iget(ino->i_sb, 0); + if(inode == NULL) + goto out_dput; + + err = init_inode(inode, proc_dentry); + if(err) + goto out_put; + + hppfs_read_inode(inode); + + d_add(dentry, inode); + dentry->d_op = &hppfs_dentry_ops; + return(NULL); + + out_put: + iput(inode); + out_dput: + dput(proc_dentry); + out: + return(ERR_PTR(err)); +} + +static struct inode_operations hppfs_file_iops = { +}; + +static ssize_t read_proc(struct file *file, char *buf, ssize_t count, + loff_t *ppos, int is_user) +{ + ssize_t (*read)(struct file *, char *, size_t, loff_t *); + ssize_t n; + + read = file->f_dentry->d_inode->i_fop->read; + + if(!is_user) + set_fs(KERNEL_DS); + + n = (*read)(file, buf, count, &file->f_pos); + + if(!is_user) + set_fs(USER_DS); + + if(ppos) *ppos = file->f_pos; + return(n); +} + +static ssize_t hppfs_read_file(int fd, char *buf, ssize_t count) +{ + ssize_t n; + int cur, err; + char *new_buf; + + n = -ENOMEM; + new_buf = kmalloc(PAGE_SIZE, GFP_KERNEL); + if(new_buf == NULL){ + printk("hppfs_read_file : kmalloc failed\n"); + goto out; + } + n = 0; + while(count > 0){ + cur = min_t(ssize_t, count, PAGE_SIZE); + err = os_read_file(fd, new_buf, cur); + if(err < 0){ + printk("hppfs_read : read failed, errno = %d\n", + count); + n = err; + goto out_free; + } + else if(err == 0) + break; + + if(copy_to_user(buf, new_buf, err)){ + n = -EFAULT; + goto out_free; + } + n += err; + count -= err; + } + out_free: + kfree(new_buf); + out: + return(n); +} + +static ssize_t hppfs_read(struct file *file, char *buf, size_t count, + loff_t *ppos) +{ + struct hppfs_private *hppfs = file->private_data; + struct hppfs_data *data; + loff_t off; + int err; + + if(hppfs->contents != NULL){ + if(*ppos >= hppfs->len) return(0); + + data = hppfs->contents; + off = *ppos; + while(off >= sizeof(data->contents)){ + data = list_entry(data->list.next, struct hppfs_data, + list); + off -= sizeof(data->contents); + } + + if(off + count > hppfs->len) + count = hppfs->len - off; + copy_to_user(buf, &data->contents[off], count); + *ppos += count; + } + else if(hppfs->host_fd != -1){ + err = os_seek_file(hppfs->host_fd, *ppos); + if(err){ + printk("hppfs_read : seek failed, errno = %d\n", err); + return(err); + } + count = hppfs_read_file(hppfs->host_fd, buf, count); + if(count > 0) + *ppos += count; + } + else count = read_proc(hppfs->proc_file, buf, count, ppos, 1); + + return(count); +} + +static ssize_t hppfs_write(struct file *file, const char *buf, size_t len, + loff_t *ppos) +{ + struct hppfs_private *data = file->private_data; + struct file *proc_file = data->proc_file; + ssize_t (*write)(struct file *, const char *, size_t, loff_t *); + int err; + + write = proc_file->f_dentry->d_inode->i_fop->write; + + proc_file->f_pos = file->f_pos; + err = (*write)(proc_file, buf, len, &proc_file->f_pos); + file->f_pos = proc_file->f_pos; + + return(err); +} + +static int open_host_sock(char *host_file, int *filter_out) +{ + char *end; + int fd; + + end = &host_file[strlen(host_file)]; + strcpy(end, "/rw"); + *filter_out = 1; + fd = os_connect_socket(host_file); + if(fd > 0) + return(fd); + + strcpy(end, "/r"); + *filter_out = 0; + fd = os_connect_socket(host_file); + return(fd); +} + +static void free_contents(struct hppfs_data *head) +{ + struct hppfs_data *data; + struct list_head *ele, *next; + + if(head == NULL) return; + + list_for_each_safe(ele, next, &head->list){ + data = list_entry(ele, struct hppfs_data, list); + kfree(data); + } + kfree(head); +} + +static struct hppfs_data *hppfs_get_data(int fd, int filter, + struct file *proc_file, + struct file *hppfs_file, + loff_t *size_out) +{ + struct hppfs_data *data, *new, *head; + int n, err; + + err = -ENOMEM; + data = kmalloc(sizeof(*data), GFP_KERNEL); + if(data == NULL){ + printk("hppfs_get_data : head allocation failed\n"); + goto failed; + } + + INIT_LIST_HEAD(&data->list); + + head = data; + *size_out = 0; + + if(filter){ + while((n = read_proc(proc_file, data->contents, + sizeof(data->contents), NULL, 0)) > 0) + os_write_file(fd, data->contents, n); + err = os_shutdown_socket(fd, 0, 1); + if(err){ + printk("hppfs_get_data : failed to shut down " + "socket\n"); + goto failed_free; + } + } + while(1){ + n = os_read_file(fd, data->contents, sizeof(data->contents)); + if(n < 0){ + err = n; + printk("hppfs_get_data : read failed, errno = %d\n", + err); + goto failed_free; + } + else if(n == 0) + break; + + *size_out += n; + + if(n < sizeof(data->contents)) + break; + + new = kmalloc(sizeof(*data), GFP_KERNEL); + if(new == 0){ + printk("hppfs_get_data : data allocation failed\n"); + err = -ENOMEM; + goto failed_free; + } + + INIT_LIST_HEAD(&new->list); + list_add(&new->list, &data->list); + data = new; + } + return(head); + + failed_free: + free_contents(head); + failed: + return(ERR_PTR(err)); +} + +static struct hppfs_private *hppfs_data(void) +{ + struct hppfs_private *data; + + data = kmalloc(sizeof(*data), GFP_KERNEL); + if(data == NULL) + return(data); + + *data = ((struct hppfs_private ) { .host_fd = -1, + .len = -1, + .contents = NULL } ); + return(data); +} + +static int file_mode(int fmode) +{ + if(fmode == (FMODE_READ | FMODE_WRITE)) + return(O_RDWR); + if(fmode == FMODE_READ) + return(O_RDONLY); + if(fmode == FMODE_WRITE) + return(O_WRONLY); + return(0); +} + +static int hppfs_open(struct inode *inode, struct file *file) +{ + struct hppfs_private *data; + struct dentry *proc_dentry; + char *host_file; + int err, fd, type, filter; + + err = -ENOMEM; + data = hppfs_data(); + if(data == NULL) + goto out; + + host_file = dentry_name(file->f_dentry, strlen("/rw")); + if(host_file == NULL) + goto out_free2; + + proc_dentry = HPPFS_I(inode)->proc_dentry; + + /* XXX This isn't closed anywhere */ + data->proc_file = dentry_open(dget(proc_dentry), NULL, + file_mode(file->f_mode)); + err = PTR_ERR(data->proc_file); + if(IS_ERR(data->proc_file)) + goto out_free1; + + type = os_file_type(host_file); + if(type == OS_TYPE_FILE){ + fd = os_open_file(host_file, of_read(OPENFLAGS()), 0); + if(fd >= 0) + data->host_fd = fd; + else printk("hppfs_open : failed to open '%s', errno = %d\n", + host_file, -fd); + + data->contents = NULL; + } + else if(type == OS_TYPE_DIR){ + fd = open_host_sock(host_file, &filter); + if(fd > 0){ + data->contents = hppfs_get_data(fd, filter, + &data->proc_file, + file, &data->len); + if(!IS_ERR(data->contents)) + data->host_fd = fd; + } + else printk("hppfs_open : failed to open a socket in " + "'%s', errno = %d\n", host_file, -fd); + } + kfree(host_file); + + file->private_data = data; + return(0); + + out_free1: + kfree(host_file); + out_free2: + free_contents(data->contents); + kfree(data); + out: + return(err); +} + +static int hppfs_dir_open(struct inode *inode, struct file *file) +{ + struct hppfs_private *data; + struct dentry *proc_dentry; + int err; + + err = -ENOMEM; + data = hppfs_data(); + if(data == NULL) + goto out; + + proc_dentry = HPPFS_I(inode)->proc_dentry; + data->proc_file = dentry_open(dget(proc_dentry), NULL, + file_mode(file->f_mode)); + err = PTR_ERR(data->proc_file); + if(IS_ERR(data->proc_file)) + goto out_free; + + file->private_data = data; + return(0); + + out_free: + kfree(data); + out: + return(err); +} + +static loff_t hppfs_llseek(struct file *file, loff_t off, int where) +{ + struct hppfs_private *data = file->private_data; + struct file *proc_file = &data->proc_file; + loff_t (*llseek)(struct file *, loff_t, int); + loff_t ret; + + llseek = proc_file->f_dentry->d_inode->i_fop->llseek; + if(llseek != NULL){ + ret = (*llseek)(proc_file, off, where); + if(ret < 0) + return(ret); + } + + return(default_llseek(file, off, where)); +} + +static struct file_operations hppfs_file_fops = { + .owner = NULL, + .llseek = hppfs_llseek, + .read = hppfs_read, + .write = hppfs_write, + .open = hppfs_open, +}; + +struct hppfs_dirent { + void *vfs_dirent; + filldir_t filldir; + struct dentry *dentry; +}; + +static int hppfs_filldir(void *d, const char *name, int size, + loff_t offset, ino_t inode, unsigned int type) +{ + struct hppfs_dirent *dirent = d; + + if(file_removed(dirent->dentry, name)) + return(0); + + return((*dirent->filldir)(dirent->vfs_dirent, name, size, offset, + inode, type)); +} + +static int hppfs_readdir(struct file *file, void *ent, filldir_t filldir) +{ + struct hppfs_private *data = file->private_data; + struct file *proc_file = &data->proc_file; + int (*readdir)(struct file *, void *, filldir_t); + struct hppfs_dirent dirent = ((struct hppfs_dirent) + { .vfs_dirent = ent, + .filldir = filldir, + .dentry = file->f_dentry } ); + int err; + + readdir = proc_file->f_dentry->d_inode->i_fop->readdir; + + proc_file->f_pos = file->f_pos; + err = (*readdir)(proc_file, &dirent, hppfs_filldir); + file->f_pos = proc_file->f_pos; + + return(err); +} + +static int hppfs_fsync(struct file *file, struct dentry *dentry, int datasync) +{ + return(0); +} + +static struct file_operations hppfs_dir_fops = { + .owner = NULL, + .readdir = hppfs_readdir, + .open = hppfs_dir_open, + .fsync = hppfs_fsync, +}; + +static int hppfs_statfs(struct super_block *sb, struct kstatfs *sf) +{ + sf->f_blocks = 0; + sf->f_bfree = 0; + sf->f_bavail = 0; + sf->f_files = 0; + sf->f_ffree = 0; + sf->f_type = HPPFS_SUPER_MAGIC; + return(0); +} + +static struct inode *hppfs_alloc_inode(struct super_block *sb) +{ + struct hppfs_inode_info *hi; + + hi = kmalloc(sizeof(*hi), GFP_KERNEL); + if(hi == NULL) + return(NULL); + + *hi = ((struct hppfs_inode_info) { .proc_dentry = NULL }); + inode_init_once(&hi->vfs_inode); + return(&hi->vfs_inode); +} + +void hppfs_delete_inode(struct inode *ino) +{ + clear_inode(ino); +} + +static void hppfs_destroy_inode(struct inode *inode) +{ + kfree(HPPFS_I(inode)); +} + +static struct super_operations hppfs_sbops = { + .alloc_inode = hppfs_alloc_inode, + .destroy_inode = hppfs_destroy_inode, + .read_inode = hppfs_read_inode, + .delete_inode = hppfs_delete_inode, + .statfs = hppfs_statfs, +}; + +static int hppfs_readlink(struct dentry *dentry, char *buffer, int buflen) +{ + struct file *proc_file; + struct dentry *proc_dentry; + int (*readlink)(struct dentry *, char *, int); + int err, n; + + proc_dentry = HPPFS_I(dentry->d_inode)->proc_dentry; + proc_file = dentry_open(dget(proc_dentry), NULL, O_RDONLY); + err = PTR_ERR(proc_dentry); + if(IS_ERR(proc_dentry)) + return(err); + + readlink = proc_dentry->d_inode->i_op->readlink; + n = (*readlink)(proc_dentry, buffer, buflen); + + fput(proc_file); + + return(n); +} + +static int hppfs_follow_link(struct dentry *dentry, struct nameidata *nd) +{ + struct file *proc_file; + struct dentry *proc_dentry; + int (*follow_link)(struct dentry *, struct nameidata *); + int err, n; + + proc_dentry = HPPFS_I(dentry->d_inode)->proc_dentry; + proc_file = dentry_open(dget(proc_dentry), NULL, O_RDONLY); + err = PTR_ERR(proc_dentry); + if(IS_ERR(proc_dentry)) + return(err); + + follow_link = proc_dentry->d_inode->i_op->follow_link; + n = (*follow_link)(proc_dentry, nd); + + fput(proc_file); + + return(n); +} + +static struct inode_operations hppfs_dir_iops = { + .lookup = hppfs_lookup, +}; + +static struct inode_operations hppfs_link_iops = { + .readlink = hppfs_readlink, + .follow_link = hppfs_follow_link, +}; + +static int init_inode(struct inode *inode, struct dentry *dentry) +{ + if(S_ISDIR(dentry->d_inode->i_mode)){ + inode->i_op = &hppfs_dir_iops; + inode->i_fop = &hppfs_dir_fops; + } + else if(S_ISLNK(dentry->d_inode->i_mode)){ + inode->i_op = &hppfs_link_iops; + inode->i_fop = &hppfs_file_fops; + } + else { + inode->i_op = &hppfs_file_iops; + inode->i_fop = &hppfs_file_fops; + } + + HPPFS_I(inode)->proc_dentry = dentry; + + return(0); +} + +static int hppfs_fill_super(struct super_block *sb, void *d, int silent) +{ + struct inode *root_inode; + struct file_system_type *procfs; + struct super_block *proc_sb; + int err; + + err = -ENOENT; + procfs = get_fs_type("proc"); + if(procfs == NULL) + goto out; + + if(list_empty(&procfs->fs_supers)) + goto out; + + proc_sb = list_entry(procfs->fs_supers.next, struct super_block, + s_instances); + + sb->s_blocksize = 1024; + sb->s_blocksize_bits = 10; + sb->s_magic = HPPFS_SUPER_MAGIC; + sb->s_op = &hppfs_sbops; + + root_inode = iget(sb, 0); + if(root_inode == NULL) + goto out; + + err = init_inode(root_inode, proc_sb->s_root); + if(err) + goto out_put; + + err = -ENOMEM; + sb->s_root = d_alloc_root(root_inode); + if(sb->s_root == NULL) + goto out_put; + + hppfs_read_inode(root_inode); + + return(0); + + out_put: + iput(root_inode); + out: + return(err); +} + +static struct super_block *hppfs_read_super(struct file_system_type *type, + int flags, const char *dev_name, + void *data) +{ + return(get_sb_nodev(type, flags, data, hppfs_fill_super)); +} + +static struct file_system_type hppfs_type = { + .owner = THIS_MODULE, + .name = "hppfs", + .get_sb = hppfs_read_super, + .kill_sb = kill_anon_super, + .fs_flags = 0, +}; + +static int __init init_hppfs(void) +{ + return(register_filesystem(&hppfs_type)); +} + +static void __exit exit_hppfs(void) +{ + unregister_filesystem(&hppfs_type); +} + +module_init(init_hppfs) +module_exit(exit_hppfs) +MODULE_LICENSE("GPL"); + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff -Nru a/fs/inode.c b/fs/inode.c --- a/fs/inode.c 2004-08-25 22:01:56 -07:00 +++ b/fs/inode.c 2004-08-25 22:01:56 -07:00 @@ -1373,8 +1373,7 @@ /* inode slab cache */ inode_cachep = kmem_cache_create("inode_cache", sizeof(struct inode), - 0, SLAB_HWCACHE_ALIGN|SLAB_PANIC, init_once, - NULL); + 0, SLAB_PANIC, init_once, NULL); set_shrinker(DEFAULT_SEEKS, shrink_icache_memory); } diff -Nru a/fs/isofs/inode.c b/fs/isofs/inode.c --- a/fs/isofs/inode.c 2004-08-25 22:01:56 -07:00 +++ b/fs/isofs/inode.c 2004-08-25 22:01:56 -07:00 @@ -108,7 +108,7 @@ { isofs_inode_cachep = kmem_cache_create("isofs_inode_cache", sizeof(struct iso_inode_info), - 0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT, + 0, SLAB_RECLAIM_ACCOUNT, init_once, NULL); if (isofs_inode_cachep == NULL) return -ENOMEM; @@ -715,6 +715,7 @@ } s->s_magic = ISOFS_SUPER_MAGIC; + s->s_maxbytes = 0xffffffff; /* We can handle files up to 4 GB */ /* The CDROM is read-only, has no nodes (devices) on it, and since all of the files appear to be owned by root, we really do not want diff -Nru a/fs/jffs2/super.c b/fs/jffs2/super.c --- a/fs/jffs2/super.c 2004-08-25 22:01:55 -07:00 +++ b/fs/jffs2/super.c 2004-08-25 22:01:55 -07:00 @@ -302,7 +302,7 @@ jffs2_inode_cachep = kmem_cache_create("jffs2_i", sizeof(struct jffs2_inode_info), - 0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT, + 0, SLAB_RECLAIM_ACCOUNT, jffs2_i_init_once, NULL); if (!jffs2_inode_cachep) { printk(KERN_ERR "JFFS2 error: Failed to initialise inode cache\n"); diff -Nru a/fs/jfs/super.c b/fs/jfs/super.c --- a/fs/jfs/super.c 2004-08-25 22:01:55 -07:00 +++ b/fs/jfs/super.c 2004-08-25 22:01:55 -07:00 @@ -58,7 +58,7 @@ #ifdef CONFIG_JFS_DEBUG int jfsloglevel = JFS_LOGLEVEL_WARN; -module_param(jfsloglevel, int, 644); +module_param(jfsloglevel, int, 0644); MODULE_PARM_DESC(jfsloglevel, "Specify JFS loglevel (0, 1 or 2)"); #endif diff -Nru a/fs/libfs.c b/fs/libfs.c --- a/fs/libfs.c 2004-08-25 22:01:54 -07:00 +++ b/fs/libfs.c 2004-08-25 22:01:54 -07:00 @@ -27,14 +27,27 @@ } /* - * Lookup the data. This is trivial - if the dentry didn't already - * exist, we know it is negative. + * Retaining negative dentries for an in-memory filesystem just wastes + * memory and lookup time: arrange for them to be deleted immediately. */ +static int simple_delete_dentry(struct dentry *dentry) +{ + return 1; +} +/* + * Lookup the data. This is trivial - if the dentry didn't already + * exist, we know it is negative. Set d_op to delete negative dentries. + */ struct dentry *simple_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd) { + static struct dentry_operations simple_dentry_operations = { + .d_delete = simple_delete_dentry, + }; + if (dentry->d_name.len > NAME_MAX) return ERR_PTR(-ENAMETOOLONG); + dentry->d_op = &simple_dentry_operations; d_add(dentry, NULL); return NULL; } @@ -456,6 +469,58 @@ return count; } +/* + * Transaction based IO. + * The file expects a single write which triggers the transaction, and then + * possibly a read which collects the result - which is stored in a + * file-local buffer. + */ +char *simple_transaction_get(struct file *file, const char __user *buf, size_t size) +{ + struct simple_transaction_argresp *ar; + static spinlock_t simple_transaction_lock = SPIN_LOCK_UNLOCKED; + + if (size > SIMPLE_TRANSACTION_LIMIT - 1) + return ERR_PTR(-EFBIG); + + ar = (struct simple_transaction_argresp *)get_zeroed_page(GFP_KERNEL); + if (!ar) + return ERR_PTR(-ENOMEM); + + spin_lock(&simple_transaction_lock); + + /* only one write allowed per open */ + if (file->private_data) { + spin_unlock(&simple_transaction_lock); + free_page((unsigned long)ar); + return ERR_PTR(-EBUSY); + } + + file->private_data = ar; + + spin_unlock(&simple_transaction_lock); + + if (copy_from_user(ar->data, buf, size)) + return ERR_PTR(-EFAULT); + + return ar->data; +} + +ssize_t simple_transaction_read(struct file *file, char __user *buf, size_t size, loff_t *pos) +{ + struct simple_transaction_argresp *ar = file->private_data; + + if (!ar) + return 0; + return simple_read_from_buffer(buf, size, pos, ar->data, ar->size); +} + +int simple_transaction_release(struct inode *inode, struct file *file) +{ + free_page((unsigned long)file->private_data); + return 0; +} + EXPORT_SYMBOL(dcache_dir_close); EXPORT_SYMBOL(dcache_dir_lseek); EXPORT_SYMBOL(dcache_dir_open); @@ -479,3 +544,6 @@ EXPORT_SYMBOL(simple_sync_file); EXPORT_SYMBOL(simple_unlink); EXPORT_SYMBOL(simple_read_from_buffer); +EXPORT_SYMBOL(simple_transaction_get); +EXPORT_SYMBOL(simple_transaction_read); +EXPORT_SYMBOL(simple_transaction_release); diff -Nru a/fs/lockd/svc.c b/fs/lockd/svc.c --- a/fs/lockd/svc.c 2004-08-25 22:01:55 -07:00 +++ b/fs/lockd/svc.c 2004-08-25 22:01:55 -07:00 @@ -409,13 +409,13 @@ MODULE_LICENSE("GPL"); module_param_call(nlm_grace_period, param_set_grace_period, param_get_ulong, - &nlm_grace_period, 644); + &nlm_grace_period, 0644); module_param_call(nlm_timeout, param_set_timeout, param_get_ulong, - &nlm_timeout, 644); + &nlm_timeout, 0644); module_param_call(nlm_udpport, param_set_port, param_get_int, - &nlm_udpport, 644); + &nlm_udpport, 0644); module_param_call(nlm_tcpport, param_set_port, param_get_int, - &nlm_tcpport, 644); + &nlm_tcpport, 0644); /* * Initialising and terminating the module. diff -Nru a/fs/locks.c b/fs/locks.c --- a/fs/locks.c 2004-08-25 22:01:56 -07:00 +++ b/fs/locks.c 2004-08-25 22:01:56 -07:00 @@ -2063,4 +2063,4 @@ return 0; } -module_init(filelock_init) +core_initcall(filelock_init); diff -Nru a/fs/minix/inode.c b/fs/minix/inode.c --- a/fs/minix/inode.c 2004-08-25 22:01:55 -07:00 +++ b/fs/minix/inode.c 2004-08-25 22:01:55 -07:00 @@ -79,7 +79,7 @@ { minix_inode_cachep = kmem_cache_create("minix_inode_cache", sizeof(struct minix_inode_info), - 0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT, + 0, SLAB_RECLAIM_ACCOUNT, init_once, NULL); if (minix_inode_cachep == NULL) return -ENOMEM; diff -Nru a/fs/mpage.c b/fs/mpage.c --- a/fs/mpage.c 2004-08-25 22:01:54 -07:00 +++ b/fs/mpage.c 2004-08-25 22:01:54 -07:00 @@ -290,7 +290,8 @@ alloc_new: if (bio == NULL) { bio = mpage_alloc(bdev, blocks[0] << (blkbits - 9), - nr_pages, GFP_KERNEL); + min_t(int, nr_pages, bio_get_nr_vecs(bdev)), + GFP_KERNEL); if (bio == NULL) goto confused; } diff -Nru a/fs/namei.c b/fs/namei.c --- a/fs/namei.c 2004-08-25 22:01:55 -07:00 +++ b/fs/namei.c 2004-08-25 22:01:55 -07:00 @@ -1094,8 +1094,12 @@ static inline int may_delete(struct inode *dir,struct dentry *victim,int isdir) { int error; - if (!victim->d_inode || victim->d_parent->d_inode != dir) + + if (!victim->d_inode) return -ENOENT; + + BUG_ON(victim->d_parent->d_inode != dir); + error = permission(dir,MAY_WRITE | MAY_EXEC, NULL); if (error) return error; diff -Nru a/fs/ncpfs/file.c b/fs/ncpfs/file.c --- a/fs/ncpfs/file.c 2004-08-25 22:01:54 -07:00 +++ b/fs/ncpfs/file.c 2004-08-25 22:01:54 -07:00 @@ -115,11 +115,6 @@ if (!ncp_conn_valid(NCP_SERVER(inode))) return -EIO; - if (!S_ISREG(inode->i_mode)) { - DPRINTK("ncp_file_read: read from non-file, mode %07o\n", - inode->i_mode); - return -EINVAL; - } pos = *ppos; @@ -175,10 +170,8 @@ *ppos = pos; - if (!IS_RDONLY(inode)) { - inode->i_atime = CURRENT_TIME; - } - + file_accessed(file); + DPRINTK("ncp_file_read: exit %s/%s\n", dentry->d_parent->d_name.name, dentry->d_name.name); outrel: @@ -201,11 +194,6 @@ dentry->d_parent->d_name.name, dentry->d_name.name); if (!ncp_conn_valid(NCP_SERVER(inode))) return -EIO; - if (!S_ISREG(inode->i_mode)) { - DPRINTK("ncp_file_write: write to non-file, mode %07o\n", - inode->i_mode); - return -EINVAL; - } if ((ssize_t) count < 0) return -EINVAL; pos = *ppos; @@ -273,8 +261,9 @@ } } vfree(bouncebuffer); - inode->i_mtime = inode->i_atime = CURRENT_TIME; - + + inode_update_time(inode, 1); + *ppos = pos; if (pos > inode->i_size) { diff -Nru a/fs/ncpfs/inode.c b/fs/ncpfs/inode.c --- a/fs/ncpfs/inode.c 2004-08-25 22:01:55 -07:00 +++ b/fs/ncpfs/inode.c 2004-08-25 22:01:55 -07:00 @@ -72,7 +72,7 @@ { ncp_inode_cachep = kmem_cache_create("ncp_inode_cache", sizeof(struct ncp_inode_info), - 0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT, + 0, SLAB_RECLAIM_ACCOUNT, init_once, NULL); if (ncp_inode_cachep == NULL) return -ENOMEM; diff -Nru a/fs/ncpfs/mmap.c b/fs/ncpfs/mmap.c --- a/fs/ncpfs/mmap.c 2004-08-25 22:01:55 -07:00 +++ b/fs/ncpfs/mmap.c 2004-08-25 22:01:55 -07:00 @@ -110,23 +110,19 @@ DPRINTK("ncp_mmap: called\n"); - if (!ncp_conn_valid(NCP_SERVER(inode))) { + if (!ncp_conn_valid(NCP_SERVER(inode))) return -EIO; - } + /* only PAGE_COW or read-only supported now */ if (vma->vm_flags & VM_SHARED) return -EINVAL; - if (!inode->i_sb || !S_ISREG(inode->i_mode)) - return -EACCES; /* we do not support files bigger than 4GB... We eventually supports just 4GB... */ if (((vma->vm_end - vma->vm_start) >> PAGE_SHIFT) + vma->vm_pgoff > (1U << (32 - PAGE_SHIFT))) return -EFBIG; - if (!IS_RDONLY(inode)) { - inode->i_atime = CURRENT_TIME; - } vma->vm_ops = &ncp_file_mmap; + file_accessed(file); return 0; } diff -Nru a/fs/nfs/inode.c b/fs/nfs/inode.c --- a/fs/nfs/inode.c 2004-08-25 22:01:56 -07:00 +++ b/fs/nfs/inode.c 2004-08-25 22:01:56 -07:00 @@ -1859,7 +1859,7 @@ { nfs_inode_cachep = kmem_cache_create("nfs_inode_cache", sizeof(struct nfs_inode), - 0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT, + 0, SLAB_RECLAIM_ACCOUNT, init_once, NULL); if (nfs_inode_cachep == NULL) return -ENOMEM; diff -Nru a/fs/nfs/nfsroot.c b/fs/nfs/nfsroot.c --- a/fs/nfs/nfsroot.c 2004-08-25 22:01:56 -07:00 +++ b/fs/nfs/nfsroot.c 2004-08-25 22:01:56 -07:00 @@ -495,8 +495,10 @@ if (status < 0) printk(KERN_ERR "Root-NFS: Server returned error %d " "while mounting %s\n", status, nfs_path); - else - nfs_copy_fh(nfs_data.root, fh); + else { + nfs_data.root.size = fh.size; + memcpy(nfs_data.root.data, fh.data, fh.size); + } return status; } diff -Nru a/fs/nfsd/export.c b/fs/nfsd/export.c --- a/fs/nfsd/export.c 2004-08-25 22:01:55 -07:00 +++ b/fs/nfsd/export.c 2004-08-25 22:01:55 -07:00 @@ -294,6 +294,11 @@ qword_add(bpp, blen, exp->ex_client->name); pth = d_path(exp->ex_dentry, exp->ex_mnt, *bpp, *blen); + if (IS_ERR(pth)) { + /* is this correct? */ + (*bpp)[0] = '\n'; + return; + } qword_add(bpp, blen, pth); (*bpp)[-1] = '\n'; } diff -Nru a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c --- a/fs/nfsd/nfsctl.c 2004-08-25 22:01:54 -07:00 +++ b/fs/nfsd/nfsctl.c 2004-08-25 22:01:54 -07:00 @@ -80,101 +80,31 @@ [NFSD_Leasetime] = write_leasetime, }; -/* an argresp is stored in an allocated page and holds the - * size of the argument or response, along with its content - */ -struct argresp { - ssize_t size; - char data[0]; -}; - -/* - * transaction based IO methods. - * The file expects a single write which triggers the transaction, and then - * possibly a read which collects the result - which is stored in a - * file-local buffer. - */ -static ssize_t TA_write(struct file *file, const char __user *buf, size_t size, loff_t *pos) +static ssize_t nfsctl_transaction_write(struct file *file, const char __user *buf, size_t size, loff_t *pos) { ino_t ino = file->f_dentry->d_inode->i_ino; - struct argresp *ar; - ssize_t rv = 0; + char *data; + ssize_t rv; if (ino >= sizeof(write_op)/sizeof(write_op[0]) || !write_op[ino]) return -EINVAL; - if (file->private_data) - return -EINVAL; /* only one write allowed per open */ - if (size > PAGE_SIZE - sizeof(struct argresp)) - return -EFBIG; - ar = kmalloc(PAGE_SIZE, GFP_KERNEL); - if (!ar) - return -ENOMEM; - ar->size = 0; - down(&file->f_dentry->d_inode->i_sem); - if (file->private_data) - rv = -EINVAL; - else - file->private_data = ar; - up(&file->f_dentry->d_inode->i_sem); - if (rv) { - kfree(ar); - return rv; - } - if (copy_from_user(ar->data, buf, size)) - return -EFAULT; - - rv = write_op[ino](file, ar->data, size); + data = simple_transaction_get(file, buf, size); + if (IS_ERR(data)) + return PTR_ERR(data); + + rv = write_op[ino](file, data, size); if (rv>0) { - ar->size = rv; + simple_transaction_set(file, rv); rv = size; } return rv; } - -static ssize_t TA_read(struct file *file, char __user *buf, size_t size, loff_t *pos) -{ - struct argresp *ar; - ssize_t rv = 0; - - if (file->private_data == NULL) - rv = TA_write(file, buf, 0, pos); - if (rv < 0) - return rv; - - ar = file->private_data; - if (!ar) - return 0; - if (*pos >= ar->size) - return 0; - if (*pos + size > ar->size) - size = ar->size - *pos; - if (copy_to_user(buf, ar->data + *pos, size)) - return -EFAULT; - *pos += size; - return size; -} - -static int TA_open(struct inode *inode, struct file *file) -{ - file->private_data = NULL; - return 0; -} - -static int TA_release(struct inode *inode, struct file *file) -{ - void *p = file->private_data; - file->private_data = NULL; - kfree(p); - return 0; -} - static struct file_operations transaction_ops = { - .write = TA_write, - .read = TA_read, - .open = TA_open, - .release = TA_release, + .write = nfsctl_transaction_write, + .read = simple_transaction_read, + .release = simple_transaction_release, }; extern struct seq_operations nfs_exports_op; @@ -366,7 +296,7 @@ if (len) return len; - mesg = buf; len = PAGE_SIZE-sizeof(struct argresp); + mesg = buf; len = SIMPLE_TRANSACTION_LIMIT; qword_addhex(&mesg, &len, (char*)&fh.fh_base, fh.fh_size); mesg[-1] = '\n'; return mesg - buf; diff -Nru a/fs/ntfs/super.c b/fs/ntfs/super.c --- a/fs/ntfs/super.c 2004-08-25 22:01:55 -07:00 +++ b/fs/ntfs/super.c 2004-08-25 22:01:55 -07:00 @@ -2638,7 +2638,7 @@ ntfs_inode_cache = kmem_cache_create(ntfs_inode_cache_name, sizeof(ntfs_inode), 0, - SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT, NULL, NULL); + SLAB_RECLAIM_ACCOUNT, NULL, NULL); if (!ntfs_inode_cache) { printk(KERN_CRIT "NTFS: Failed to create %s!\n", ntfs_inode_cache_name); diff -Nru a/fs/proc/array.c b/fs/proc/array.c --- a/fs/proc/array.c 2004-08-25 22:01:55 -07:00 +++ b/fs/proc/array.c 2004-08-25 22:01:55 -07:00 @@ -316,11 +316,7 @@ state = *get_task_state(task); vsize = eip = esp = 0; - task_lock(task); - mm = task->mm; - if(mm) - mm = mmgrab(mm); - task_unlock(task); + mm = get_task_mm(task); if (mm) { down_read(&mm->mmap_sem); vsize = task_vsize(mm); diff -Nru a/fs/proc/base.c b/fs/proc/base.c --- a/fs/proc/base.c 2004-08-25 22:01:55 -07:00 +++ b/fs/proc/base.c 2004-08-25 22:01:55 -07:00 @@ -60,6 +60,9 @@ PROC_TGID_MAPS, PROC_TGID_MOUNTS, PROC_TGID_WCHAN, +#ifdef CONFIG_SCHEDSTATS + PROC_TGID_SCHEDSTAT, +#endif #ifdef CONFIG_SECURITY PROC_TGID_ATTR, PROC_TGID_ATTR_CURRENT, @@ -83,6 +86,9 @@ PROC_TID_MAPS, PROC_TID_MOUNTS, PROC_TID_WCHAN, +#ifdef CONFIG_SCHEDSTATS + PROC_TID_SCHEDSTAT, +#endif #ifdef CONFIG_SECURITY PROC_TID_ATTR, PROC_TID_ATTR_CURRENT, @@ -123,6 +129,9 @@ #ifdef CONFIG_KALLSYMS E(PROC_TGID_WCHAN, "wchan", S_IFREG|S_IRUGO), #endif +#ifdef CONFIG_SCHEDSTATS + E(PROC_TGID_SCHEDSTAT, "schedstat", S_IFREG|S_IRUGO), +#endif {0,0,NULL,0} }; static struct pid_entry tid_base_stuff[] = { @@ -145,6 +154,9 @@ #ifdef CONFIG_KALLSYMS E(PROC_TID_WCHAN, "wchan", S_IFREG|S_IRUGO), #endif +#ifdef CONFIG_SCHEDSTATS + E(PROC_TID_SCHEDSTAT, "schedstat",S_IFREG|S_IRUGO), +#endif {0,0,NULL,0} }; @@ -340,7 +352,7 @@ // If the nul at the end of args has been overwritten, then // assume application is using setproctitle(3). - if (res > 0 && buffer[res-1] != '\0') { + if (res > 0 && buffer[res-1] != '\0' && len < PAGE_SIZE) { len = strnlen(buffer, res); if (len < res) { res = len; @@ -398,6 +410,19 @@ } #endif /* CONFIG_KALLSYMS */ +#ifdef CONFIG_SCHEDSTATS +/* + * Provides /proc/PID/schedstat + */ +static int proc_pid_schedstat(struct task_struct *task, char *buffer) +{ + return sprintf(buffer, "%lu %lu %lu\n", + task->sched_info.cpu_time, + task->sched_info.run_delay, + task->sched_info.pcnt); +} +#endif + /************************************************************************/ /* Here the fs part begins */ /************************************************************************/ @@ -518,7 +543,6 @@ struct inode * inode = file->f_dentry->d_inode; unsigned long page; ssize_t length; - ssize_t end; struct task_struct *task = proc_task(inode); if (count > PROC_BLOCK_SIZE) @@ -528,24 +552,10 @@ length = PROC_I(inode)->op.proc_read(task, (char*)page); - if (length < 0) { - free_page(page); - return length; - } - /* Static 4kB (or whatever) block capacity */ - if (*ppos >= length) { - free_page(page); - return 0; - } - if (count + *ppos > length) - count = length - *ppos; - end = count + *ppos; - if (copy_to_user(buf, (char *) page + *ppos, count)) - count = -EFAULT; - else - *ppos = end; + if (length >= 0) + length = simple_read_from_buffer(buf, count, ppos, (char *)page, length); free_page(page); - return count; + return length; } static struct file_operations proc_info_file_operations = { @@ -1169,7 +1179,6 @@ struct inode * inode = file->f_dentry->d_inode; unsigned long page; ssize_t length; - ssize_t end; struct task_struct *task = proc_task(inode); if (count > PAGE_SIZE) @@ -1180,24 +1189,10 @@ length = security_getprocattr(task, (char*)file->f_dentry->d_name.name, (void*)page, count); - if (length < 0) { - free_page(page); - return length; - } - /* Static 4kB (or whatever) block capacity */ - if (*ppos >= length) { - free_page(page); - return 0; - } - if (count + *ppos > length) - count = length - *ppos; - end = count + *ppos; - if (copy_to_user(buf, (char *) page + *ppos, count)) - count = -EFAULT; - else - *ppos = end; + if (length >= 0) + length = simple_read_from_buffer(buf, count, ppos, (char *)page, length); free_page(page); - return count; + return length; } static ssize_t proc_pid_attr_write(struct file * file, const char __user * buf, @@ -1374,6 +1369,13 @@ case PROC_TGID_WCHAN: inode->i_fop = &proc_info_file_operations; ei->op.proc_read = proc_pid_wchan; + break; +#endif +#ifdef CONFIG_SCHEDSTATS + case PROC_TID_SCHEDSTAT: + case PROC_TGID_SCHEDSTAT: + inode->i_fop = &proc_info_file_operations; + ei->op.proc_read = proc_pid_schedstat; break; #endif default: diff -Nru a/fs/proc/inode.c b/fs/proc/inode.c --- a/fs/proc/inode.c 2004-08-25 22:01:56 -07:00 +++ b/fs/proc/inode.c 2004-08-25 22:01:56 -07:00 @@ -120,7 +120,7 @@ { proc_inode_cachep = kmem_cache_create("proc_inode_cache", sizeof(struct proc_inode), - 0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT, + 0, SLAB_RECLAIM_ACCOUNT, init_once, NULL); if (proc_inode_cachep == NULL) return -ENOMEM; diff -Nru a/fs/proc/proc_misc.c b/fs/proc/proc_misc.c --- a/fs/proc/proc_misc.c 2004-08-25 22:01:54 -07:00 +++ b/fs/proc/proc_misc.c 2004-08-25 22:01:54 -07:00 @@ -681,6 +681,9 @@ #ifdef CONFIG_MODULES create_seq_entry("modules", 0, &proc_modules_operations); #endif +#ifdef CONFIG_SCHEDSTATS + create_seq_entry("schedstat", 0, &proc_schedstat_operations); +#endif #ifdef CONFIG_PROC_KCORE proc_root_kcore = create_proc_entry("kcore", S_IRUSR, NULL); if (proc_root_kcore) { diff -Nru a/fs/qnx4/inode.c b/fs/qnx4/inode.c --- a/fs/qnx4/inode.c 2004-08-25 22:01:56 -07:00 +++ b/fs/qnx4/inode.c 2004-08-25 22:01:56 -07:00 @@ -544,7 +544,7 @@ { qnx4_inode_cachep = kmem_cache_create("qnx4_inode_cache", sizeof(struct qnx4_inode_info), - 0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT, + 0, SLAB_RECLAIM_ACCOUNT, init_once, NULL); if (qnx4_inode_cachep == NULL) return -ENOMEM; diff -Nru a/fs/reiserfs/super.c b/fs/reiserfs/super.c --- a/fs/reiserfs/super.c 2004-08-25 22:01:55 -07:00 +++ b/fs/reiserfs/super.c 2004-08-25 22:01:55 -07:00 @@ -444,7 +444,7 @@ { reiserfs_inode_cachep = kmem_cache_create("reiser_inode_cache", sizeof(struct reiserfs_inode_info), - 0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT, + 0, SLAB_RECLAIM_ACCOUNT, init_once, NULL); if (reiserfs_inode_cachep == NULL) return -ENOMEM; diff -Nru a/fs/reiserfs/xattr.c b/fs/reiserfs/xattr.c --- a/fs/reiserfs/xattr.c 2004-08-25 22:01:56 -07:00 +++ b/fs/reiserfs/xattr.c 2004-08-25 22:01:56 -07:00 @@ -761,6 +761,11 @@ err = __reiserfs_xattr_del (dir, name, strlen (name)); dput (dir); + if (!err) { + inode->i_ctime = CURRENT_TIME; + mark_inode_dirty (inode); + } + out: return err; } @@ -1240,8 +1245,10 @@ name->hash == priv_root->d_name.hash && !memcmp (name->name, priv_root->d_name.name, name->len)) { return -ENOENT; - } - return 0; + } else if (q1->len == name->len && + !memcmp(q1->name, name->name, name->len)) + return 0; + return 1; } static struct dentry_operations xattr_lookup_poison_ops = { diff -Nru a/fs/reiserfs/xattr_acl.c b/fs/reiserfs/xattr_acl.c --- a/fs/reiserfs/xattr_acl.c 2004-08-25 22:01:56 -07:00 +++ b/fs/reiserfs/xattr_acl.c 2004-08-25 22:01:56 -07:00 @@ -289,8 +289,14 @@ error = reiserfs_xattr_set(inode, name, value, size, 0); } else { error = reiserfs_xattr_del (inode, name); - if (error == -ENODATA) + if (error == -ENODATA) { + /* This may seem odd here, but it means that the ACL was set + * with a value representable with mode bits. If there was + * an ACL before, reiserfs_xattr_del already dirtied the inode. + */ + mark_inode_dirty (inode); error = 0; + } } if (value) diff -Nru a/fs/romfs/inode.c b/fs/romfs/inode.c --- a/fs/romfs/inode.c 2004-08-25 22:01:55 -07:00 +++ b/fs/romfs/inode.c 2004-08-25 22:01:55 -07:00 @@ -579,7 +579,7 @@ { romfs_inode_cachep = kmem_cache_create("romfs_inode_cache", sizeof(struct romfs_inode_info), - 0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT, + 0, SLAB_RECLAIM_ACCOUNT, init_once, NULL); if (romfs_inode_cachep == NULL) return -ENOMEM; diff -Nru a/fs/smbfs/inode.c b/fs/smbfs/inode.c --- a/fs/smbfs/inode.c 2004-08-25 22:01:54 -07:00 +++ b/fs/smbfs/inode.c 2004-08-25 22:01:54 -07:00 @@ -80,7 +80,7 @@ { smb_inode_cachep = kmem_cache_create("smb_inode_cache", sizeof(struct smb_inode_info), - 0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT, + 0, SLAB_RECLAIM_ACCOUNT, init_once, NULL); if (smb_inode_cachep == NULL) return -ENOMEM; diff -Nru a/fs/sysv/inode.c b/fs/sysv/inode.c --- a/fs/sysv/inode.c 2004-08-25 22:01:54 -07:00 +++ b/fs/sysv/inode.c 2004-08-25 22:01:54 -07:00 @@ -340,7 +340,7 @@ { sysv_inode_cachep = kmem_cache_create("sysv_inode_cache", sizeof(struct sysv_inode_info), 0, - SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT, + SLAB_RECLAIM_ACCOUNT, init_once, NULL); if (!sysv_inode_cachep) return -ENOMEM; diff -Nru a/fs/udf/super.c b/fs/udf/super.c --- a/fs/udf/super.c 2004-08-25 22:01:55 -07:00 +++ b/fs/udf/super.c 2004-08-25 22:01:55 -07:00 @@ -145,7 +145,7 @@ { udf_inode_cachep = kmem_cache_create("udf_inode_cache", sizeof(struct udf_inode_info), - 0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT, + 0, SLAB_RECLAIM_ACCOUNT, init_once, NULL); if (udf_inode_cachep == NULL) return -ENOMEM; diff -Nru a/fs/ufs/super.c b/fs/ufs/super.c --- a/fs/ufs/super.c 2004-08-25 22:01:54 -07:00 +++ b/fs/ufs/super.c 2004-08-25 22:01:54 -07:00 @@ -1183,7 +1183,7 @@ { ufs_inode_cachep = kmem_cache_create("ufs_inode_cache", sizeof(struct ufs_inode_info), - 0, SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT, + 0, SLAB_RECLAIM_ACCOUNT, init_once, NULL); if (ufs_inode_cachep == NULL) return -ENOMEM; diff -Nru a/fs/xfs/linux-2.6/xfs_file.c b/fs/xfs/linux-2.6/xfs_file.c --- a/fs/xfs/linux-2.6/xfs_file.c 2004-08-25 22:01:55 -07:00 +++ b/fs/xfs/linux-2.6/xfs_file.c 2004-08-25 22:01:55 -07:00 @@ -259,7 +259,7 @@ loff_t *ppos, size_t count, read_actor_t actor, - void __user *target) + void *target) { vnode_t *vp = LINVFS_GET_VP(filp->f_dentry->d_inode); ssize_t rval; diff -Nru a/fs/xfs/linux-2.6/xfs_lrw.c b/fs/xfs/linux-2.6/xfs_lrw.c --- a/fs/xfs/linux-2.6/xfs_lrw.c 2004-08-25 22:01:54 -07:00 +++ b/fs/xfs/linux-2.6/xfs_lrw.c 2004-08-25 22:01:54 -07:00 @@ -366,7 +366,7 @@ int ioflags, size_t count, read_actor_t actor, - void __user *target, + void *target, cred_t *credp) { ssize_t ret; diff -Nru a/fs/xfs/linux-2.6/xfs_lrw.h b/fs/xfs/linux-2.6/xfs_lrw.h --- a/fs/xfs/linux-2.6/xfs_lrw.h 2004-08-25 22:01:54 -07:00 +++ b/fs/xfs/linux-2.6/xfs_lrw.h 2004-08-25 22:01:54 -07:00 @@ -104,7 +104,7 @@ loff_t *, int, struct cred *); extern ssize_t xfs_sendfile(struct bhv_desc *, struct file *, loff_t *, int, size_t, read_actor_t, - void __user *, struct cred *); + void *, struct cred *); extern int xfs_dev_is_read_only(struct xfs_mount *, char *); diff -Nru a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c --- a/fs/xfs/linux-2.6/xfs_super.c 2004-08-25 22:01:56 -07:00 +++ b/fs/xfs/linux-2.6/xfs_super.c 2004-08-25 22:01:56 -07:00 @@ -335,8 +335,7 @@ init_inodecache( void ) { linvfs_inode_zone = kmem_cache_create("linvfs_icache", - sizeof(vnode_t), 0, - SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT, + sizeof(vnode_t), 0, SLAB_RECLAIM_ACCOUNT, init_once, NULL); if (linvfs_inode_zone == NULL) diff -Nru a/fs/xfs/linux-2.6/xfs_vnode.h b/fs/xfs/linux-2.6/xfs_vnode.h --- a/fs/xfs/linux-2.6/xfs_vnode.h 2004-08-25 22:01:56 -07:00 +++ b/fs/xfs/linux-2.6/xfs_vnode.h 2004-08-25 22:01:56 -07:00 @@ -192,7 +192,7 @@ loff_t *, int, struct cred *); typedef ssize_t (*vop_sendfile_t)(bhv_desc_t *, struct file *, loff_t *, int, size_t, read_actor_t, - void __user *, struct cred *); + void *, struct cred *); typedef int (*vop_ioctl_t)(bhv_desc_t *, struct inode *, struct file *, int, unsigned int, void __user *); typedef int (*vop_getattr_t)(bhv_desc_t *, struct vattr *, int, diff -Nru a/include/asm-arm/hardirq.h b/include/asm-arm/hardirq.h --- a/include/asm-arm/hardirq.h 2004-08-25 22:01:55 -07:00 +++ b/include/asm-arm/hardirq.h 2004-08-25 22:01:55 -07:00 @@ -22,12 +22,20 @@ * * - bits 0-7 are the preemption count (max depth: 256) * - bits 8-15 are the softirq count (max # of softirqs: 256) - * - bits 16-23 are the hardirq count (max # of hardirqs: 256) + * - bits 16-24 are the hardirq count (max # of hardirqs: 512) * - bit 26 is the PREEMPT_ACTIVE flag + * + * We optimize HARDIRQ_BITS for immediate constant, and only + * increase it if really needed. */ #define PREEMPT_BITS 8 #define SOFTIRQ_BITS 8 + +#if NR_IRQS > 256 +#define HARDIRQ_BITS 9 +#else #define HARDIRQ_BITS 8 +#endif #define PREEMPT_SHIFT 0 #define SOFTIRQ_SHIFT (PREEMPT_SHIFT + PREEMPT_BITS) diff -Nru a/include/asm-arm/memory.h b/include/asm-arm/memory.h --- a/include/asm-arm/memory.h 2004-08-25 22:01:56 -07:00 +++ b/include/asm-arm/memory.h 2004-08-25 22:01:56 -07:00 @@ -186,8 +186,8 @@ */ #ifndef __arch_page_to_dma #define page_to_dma(dev, page) ((dma_addr_t)__virt_to_bus((unsigned long)page_address(page))) -#define dma_to_virt(dev, addr) (__bus_to_virt(addr)) -#define virt_to_dma(dev, addr) (__virt_to_bus((unsigned long)(addr))) +#define dma_to_virt(dev, addr) ((void *)__bus_to_virt(addr)) +#define virt_to_dma(dev, addr) ((dma_addr_t)__virt_to_bus((unsigned long)(addr))) #else #define page_to_dma(dev, page) (__arch_page_to_dma(dev, page)) #define dma_to_virt(dev, addr) (__arch_dma_to_virt(dev, addr)) diff -Nru a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h --- a/include/asm-generic/vmlinux.lds.h 2004-08-25 22:01:54 -07:00 +++ b/include/asm-generic/vmlinux.lds.h 2004-08-25 22:01:54 -07:00 @@ -57,6 +57,13 @@ /* Kernel symbol table: strings */ \ __ksymtab_strings : AT(ADDR(__ksymtab_strings) - LOAD_OFFSET) { \ *(__ksymtab_strings) \ + } \ + \ + /* Built-in module parameters. */ \ + __param : AT(ADDR(__param) - LOAD_OFFSET) { \ + VMLINUX_SYMBOL(__start___param) = .; \ + *(__param) \ + VMLINUX_SYMBOL(__stop___param) = .; \ } #define SECURITY_INIT \ diff -Nru a/include/asm-i386/bitops.h b/include/asm-i386/bitops.h --- a/include/asm-i386/bitops.h 2004-08-25 22:01:55 -07:00 +++ b/include/asm-i386/bitops.h 2004-08-25 22:01:55 -07:00 @@ -31,6 +31,11 @@ * * This function is atomic and may not be reordered. See __set_bit() * if you do not require the atomic guarantees. + * + * Note: there are no guarantees that this function will not be reordered + * on non x86 architectures, so if you are writting portable code, + * make sure not to rely on its reordering guarantees. + * * Note that @nr may be almost arbitrarily large; this function is not * restricted to acting on a single-word quantity. */ @@ -109,7 +114,8 @@ * @nr: Bit to change * @addr: Address to start counting from * - * change_bit() is atomic and may not be reordered. + * change_bit() is atomic and may not be reordered. It may be + * reordered on other architectures than x86. * Note that @nr may be almost arbitrarily large; this function is not * restricted to acting on a single-word quantity. */ @@ -127,6 +133,7 @@ * @addr: Address to count from * * This operation is atomic and cannot be reordered. + * It may be reordered on other architectures than x86. * It also implies a memory barrier. */ static inline int test_and_set_bit(int nr, volatile unsigned long * addr) @@ -165,7 +172,8 @@ * @nr: Bit to clear * @addr: Address to count from * - * This operation is atomic and cannot be reordered. + * This operation is atomic and cannot be reordered. + * It can be reorderdered on other architectures other than x86. * It also implies a memory barrier. */ static inline int test_and_clear_bit(int nr, volatile unsigned long * addr) diff -Nru a/include/asm-i386/cpufeature.h b/include/asm-i386/cpufeature.h --- a/include/asm-i386/cpufeature.h 2004-08-25 22:01:56 -07:00 +++ b/include/asm-i386/cpufeature.h 2004-08-25 22:01:56 -07:00 @@ -71,9 +71,13 @@ #define X86_FEATURE_P4 (3*32+ 7) /* P4 */ /* Intel-defined CPU features, CPUID level 0x00000001 (ecx), word 4 */ -#define X86_FEATURE_EST (4*32+ 7) /* Enhanced SpeedStep */ +#define X86_FEATURE_XMM3 (4*32+ 0) /* Streaming SIMD Extensions-3 */ #define X86_FEATURE_MWAIT (4*32+ 3) /* Monitor/Mwait support */ - +#define X86_FEATURE_DSCPL (4*32+ 4) /* CPL Qualified Debug Store */ +#define X86_FEATURE_EST (4*32+ 7) /* Enhanced SpeedStep */ +#define X86_FEATURE_TM2 (4*32+ 8) /* Thermal Monitor 2 */ +#define X86_FEATURE_CID (4*32+10) /* Context ID */ +#define X86_FEATURE_XTPR (4*32+14) /* Send Task Priority Messages */ /* VIA/Cyrix/Centaur-defined CPU features, CPUID level 0xC0000001, word 5 */ #define X86_FEATURE_XSTORE (5*32+ 2) /* on-CPU RNG present (xstore insn) */ @@ -92,13 +96,14 @@ #define cpu_has_tsc boot_cpu_has(X86_FEATURE_TSC) #define cpu_has_pae boot_cpu_has(X86_FEATURE_PAE) #define cpu_has_pge boot_cpu_has(X86_FEATURE_PGE) -#define cpu_has_sse2 boot_cpu_has(X86_FEATURE_XMM2) #define cpu_has_apic boot_cpu_has(X86_FEATURE_APIC) #define cpu_has_sep boot_cpu_has(X86_FEATURE_SEP) #define cpu_has_mtrr boot_cpu_has(X86_FEATURE_MTRR) #define cpu_has_mmx boot_cpu_has(X86_FEATURE_MMX) #define cpu_has_fxsr boot_cpu_has(X86_FEATURE_FXSR) #define cpu_has_xmm boot_cpu_has(X86_FEATURE_XMM) +#define cpu_has_xmm2 boot_cpu_has(X86_FEATURE_XMM2) +#define cpu_has_xmm3 boot_cpu_has(X86_FEATURE_XMM3) #define cpu_has_ht boot_cpu_has(X86_FEATURE_HT) #define cpu_has_mp boot_cpu_has(X86_FEATURE_MP) #define cpu_has_nx boot_cpu_has(X86_FEATURE_NX) @@ -106,7 +111,9 @@ #define cpu_has_cyrix_arr boot_cpu_has(X86_FEATURE_CYRIX_ARR) #define cpu_has_centaur_mcr boot_cpu_has(X86_FEATURE_CENTAUR_MCR) #define cpu_has_xstore boot_cpu_has(X86_FEATURE_XSTORE) +#define cpu_has_xstore_enabled boot_cpu_has(X86_FEATURE_XSTORE_EN) #define cpu_has_xcrypt boot_cpu_has(X86_FEATURE_XCRYPT) +#define cpu_has_xcrypt_enabled boot_cpu_has(X86_FEATURE_XCRYPT_EN) #endif /* __ASM_I386_CPUFEATURE_H */ diff -Nru a/include/asm-i386/fixmap.h b/include/asm-i386/fixmap.h --- a/include/asm-i386/fixmap.h 2004-08-25 22:01:54 -07:00 +++ b/include/asm-i386/fixmap.h 2004-08-25 22:01:54 -07:00 @@ -14,6 +14,15 @@ #define _ASM_FIXMAP_H #include + +/* used by vmalloc.c, vsyscall.lds.S. + * + * Leave one empty page between vmalloc'ed areas and + * the start of the fixmap. + */ +#define __FIXADDR_TOP 0xfffff000 + +#ifndef __ASSEMBLY__ #include #include #include @@ -97,13 +106,8 @@ #define clear_fixmap(idx) \ __set_fixmap(idx, 0, __pgprot(0)) -/* - * used by vmalloc.c. - * - * Leave one empty page between vmalloc'ed areas and - * the start of the fixmap. - */ -#define FIXADDR_TOP (0xfffff000UL) +#define FIXADDR_TOP ((unsigned long)__FIXADDR_TOP) + #define __FIXADDR_SIZE (__end_of_permanent_fixed_addresses << PAGE_SHIFT) #define FIXADDR_START (FIXADDR_TOP - __FIXADDR_SIZE) @@ -148,4 +152,5 @@ return __virt_to_fix(vaddr); } +#endif /* !__ASSEMBLY__ */ #endif diff -Nru a/include/asm-i386/mach-bigsmp/mach_ipi.h b/include/asm-i386/mach-bigsmp/mach_ipi.h --- a/include/asm-i386/mach-bigsmp/mach_ipi.h 2004-08-25 22:01:55 -07:00 +++ b/include/asm-i386/mach-bigsmp/mach_ipi.h 2004-08-25 22:01:55 -07:00 @@ -1,7 +1,7 @@ #ifndef __ASM_MACH_IPI_H #define __ASM_MACH_IPI_H -inline void send_IPI_mask_sequence(cpumask_t mask, int vector); +void send_IPI_mask_sequence(cpumask_t mask, int vector); static inline void send_IPI_mask(cpumask_t mask, int vector) { diff -Nru a/include/asm-i386/mach-es7000/mach_ipi.h b/include/asm-i386/mach-es7000/mach_ipi.h --- a/include/asm-i386/mach-es7000/mach_ipi.h 2004-08-25 22:01:55 -07:00 +++ b/include/asm-i386/mach-es7000/mach_ipi.h 2004-08-25 22:01:55 -07:00 @@ -1,7 +1,7 @@ #ifndef __ASM_MACH_IPI_H #define __ASM_MACH_IPI_H -inline void send_IPI_mask_sequence(cpumask_t mask, int vector); +void send_IPI_mask_sequence(cpumask_t mask, int vector); static inline void send_IPI_mask(cpumask_t mask, int vector) { diff -Nru a/include/asm-i386/mach-summit/mach_ipi.h b/include/asm-i386/mach-summit/mach_ipi.h --- a/include/asm-i386/mach-summit/mach_ipi.h 2004-08-25 22:01:54 -07:00 +++ b/include/asm-i386/mach-summit/mach_ipi.h 2004-08-25 22:01:54 -07:00 @@ -1,7 +1,7 @@ #ifndef __ASM_MACH_IPI_H #define __ASM_MACH_IPI_H -inline void send_IPI_mask_sequence(cpumask_t mask, int vector); +void send_IPI_mask_sequence(cpumask_t mask, int vector); static inline void send_IPI_mask(cpumask_t mask, int vector) { diff -Nru a/include/asm-i386/page.h b/include/asm-i386/page.h --- a/include/asm-i386/page.h 2004-08-25 22:01:54 -07:00 +++ b/include/asm-i386/page.h 2004-08-25 22:01:54 -07:00 @@ -116,6 +116,8 @@ return order; } +extern int sysctl_legacy_va_layout; + #endif /* __ASSEMBLY__ */ #ifdef __ASSEMBLY__ diff -Nru a/include/asm-i386/pgtable-2level.h b/include/asm-i386/pgtable-2level.h --- a/include/asm-i386/pgtable-2level.h 2004-08-25 22:01:55 -07:00 +++ b/include/asm-i386/pgtable-2level.h 2004-08-25 22:01:55 -07:00 @@ -75,4 +75,11 @@ #define pgoff_to_pte(off) \ ((pte_t) { (((off) & 0x1f) << 1) + (((off) >> 5) << 8) + _PAGE_FILE }) +/* Encode and de-code a swap entry */ +#define __swp_type(x) (((x).val >> 1) & 0x1f) +#define __swp_offset(x) ((x).val >> 8) +#define __swp_entry(type, offset) ((swp_entry_t) { ((type) << 1) | ((offset) << 8) }) +#define __pte_to_swp_entry(pte) ((swp_entry_t) { (pte).pte_low }) +#define __swp_entry_to_pte(x) ((pte_t) { (x).val }) + #endif /* _I386_PGTABLE_2LEVEL_H */ diff -Nru a/include/asm-i386/pgtable-3level.h b/include/asm-i386/pgtable-3level.h --- a/include/asm-i386/pgtable-3level.h 2004-08-25 22:01:56 -07:00 +++ b/include/asm-i386/pgtable-3level.h 2004-08-25 22:01:56 -07:00 @@ -134,4 +134,11 @@ #define pgoff_to_pte(off) ((pte_t) { _PAGE_FILE, (off) }) #define PTE_FILE_MAX_BITS 32 +/* Encode and de-code a swap entry */ +#define __swp_type(x) (((x).val) & 0x1f) +#define __swp_offset(x) ((x).val >> 5) +#define __swp_entry(type, offset) ((swp_entry_t){(type) | (offset) << 5}) +#define __pte_to_swp_entry(pte) ((swp_entry_t){ (pte).pte_high }) +#define __swp_entry_to_pte(x) ((pte_t){ 0, (x).val }) + #endif /* _I386_PGTABLE_3LEVEL_H */ diff -Nru a/include/asm-i386/pgtable.h b/include/asm-i386/pgtable.h --- a/include/asm-i386/pgtable.h 2004-08-25 22:01:56 -07:00 +++ b/include/asm-i386/pgtable.h 2004-08-25 22:01:56 -07:00 @@ -398,13 +398,6 @@ } \ } while (0) -/* Encode and de-code a swap entry */ -#define __swp_type(x) (((x).val >> 1) & 0x1f) -#define __swp_offset(x) ((x).val >> 8) -#define __swp_entry(type, offset) ((swp_entry_t) { ((type) << 1) | ((offset) << 8) }) -#define __pte_to_swp_entry(pte) ((swp_entry_t) { (pte).pte_low }) -#define __swp_entry_to_pte(x) ((pte_t) { (x).val }) - #endif /* !__ASSEMBLY__ */ #ifndef CONFIG_DISCONTIGMEM diff -Nru a/include/asm-i386/processor.h b/include/asm-i386/processor.h --- a/include/asm-i386/processor.h 2004-08-25 22:01:54 -07:00 +++ b/include/asm-i386/processor.h 2004-08-25 22:01:54 -07:00 @@ -297,6 +297,8 @@ */ #define TASK_UNMAPPED_BASE (PAGE_ALIGN(TASK_SIZE / 3)) +#define HAVE_ARCH_PICK_MMAP_LAYOUT + /* * Size of io_bitmap. */ @@ -646,10 +648,5 @@ extern void select_idle_routine(const struct cpuinfo_x86 *c); #define cache_line_size() (boot_cpu_data.x86_cache_alignment) - -#ifdef CONFIG_SCHED_SMT -#define ARCH_HAS_SCHED_DOMAIN -#define ARCH_HAS_SCHED_WAKE_IDLE -#endif #endif /* __ASM_I386_PROCESSOR_H */ diff -Nru a/include/asm-ia64/dma-mapping.h b/include/asm-ia64/dma-mapping.h --- a/include/asm-ia64/dma-mapping.h 2004-08-25 22:01:56 -07:00 +++ b/include/asm-ia64/dma-mapping.h 2004-08-25 22:01:56 -07:00 @@ -5,7 +5,8 @@ * Copyright (C) 2003-2004 Hewlett-Packard Co * David Mosberger-Tang */ - +#include +#include #include #define dma_alloc_coherent platform_dma_alloc_coherent diff -Nru a/include/asm-ia64/pgtable.h b/include/asm-ia64/pgtable.h --- a/include/asm-ia64/pgtable.h 2004-08-25 22:01:55 -07:00 +++ b/include/asm-ia64/pgtable.h 2004-08-25 22:01:55 -07:00 @@ -520,7 +520,7 @@ # ifdef CONFIG_VIRTUAL_MEM_MAP /* arch mem_map init routine is needed due to holes in a virtual mem_map */ # define __HAVE_ARCH_MEMMAP_INIT - extern void memmap_init (struct page *start, unsigned long size, int nid, unsigned long zone, + extern void memmap_init (unsigned long size, int nid, unsigned long zone, unsigned long start_pfn); # endif /* CONFIG_VIRTUAL_MEM_MAP */ # endif /* !__ASSEMBLY__ */ diff -Nru a/include/asm-ia64/processor.h b/include/asm-ia64/processor.h --- a/include/asm-ia64/processor.h 2004-08-25 22:01:55 -07:00 +++ b/include/asm-ia64/processor.h 2004-08-25 22:01:55 -07:00 @@ -334,6 +334,26 @@ /* Prepare to copy thread state - unlazy all lazy status */ #define prepare_to_copy(tsk) do { } while (0) +#ifdef CONFIG_NUMA +#define SD_NODE_INIT (struct sched_domain) { \ + .span = CPU_MASK_NONE, \ + .parent = NULL, \ + .groups = NULL, \ + .min_interval = 80, \ + .max_interval = 320, \ + .busy_factor = 320, \ + .imbalance_pct = 125, \ + .cache_hot_time = (10*1000000), \ + .cache_nice_tries = 1, \ + .per_cpu_gain = 100, \ + .flags = SD_BALANCE_EXEC \ + | SD_WAKE_BALANCE, \ + .last_balance = jiffies, \ + .balance_interval = 10, \ + .nr_balance_failed = 0, \ +} +#endif + /* * This is the mechanism for creating a new kernel thread. * diff -Nru a/include/asm-ppc/mpc8260.h b/include/asm-ppc/mpc8260.h --- a/include/asm-ppc/mpc8260.h 2004-08-25 22:01:54 -07:00 +++ b/include/asm-ppc/mpc8260.h 2004-08-25 22:01:54 -07:00 @@ -40,6 +40,10 @@ #include #endif +#ifdef CONFIG_PCI_8260 +#include +#endif + /* Make sure the memory translation stuff is there if PCI not used. */ #ifndef _IO_BASE diff -Nru a/include/asm-ppc/open_pic.h b/include/asm-ppc/open_pic.h --- a/include/asm-ppc/open_pic.h 2004-08-25 22:01:55 -07:00 +++ b/include/asm-ppc/open_pic.h 2004-08-25 22:01:55 -07:00 @@ -23,7 +23,7 @@ #define OPENPIC_VEC_TIMER 110 /* and up */ #define OPENPIC_VEC_IPI 118 /* and up */ -#define OPENPIC_VEC_SPURIOUS 127 +#define OPENPIC_VEC_SPURIOUS 239 /* OpenPIC IRQ controller structure */ extern struct hw_interrupt_type open_pic; diff -Nru a/include/asm-ppc/residual.h b/include/asm-ppc/residual.h --- a/include/asm-ppc/residual.h 2004-08-25 22:01:55 -07:00 +++ b/include/asm-ppc/residual.h 2004-08-25 22:01:55 -07:00 @@ -315,11 +315,20 @@ } RESIDUAL; +/* + * Forward declaration - we can't include because it + * breaks the boot loader + */ +struct pci_dev; + extern RESIDUAL *res; extern void print_residual_device_info(void); extern PPC_DEVICE *residual_find_device(unsigned long BusMask, unsigned char * DevID, int BaseType, int SubType, int Interface, int n); +extern int residual_pcidev_irq(struct pci_dev *dev); +extern void residual_irq_mask(char *irq_edge_mask_lo, char *irq_edge_mask_hi); +extern unsigned int residual_isapic_addr(void); extern PnP_TAG_PACKET *PnP_find_packet(unsigned char *p, unsigned packet_tag, int n); extern PnP_TAG_PACKET *PnP_find_small_vendor_packet(unsigned char *p, @@ -328,6 +337,13 @@ extern PnP_TAG_PACKET *PnP_find_large_vendor_packet(unsigned char *p, unsigned packet_type, int n); + +#ifdef CONFIG_PREP_RESIDUAL +#define have_residual_data (res && res->ResidualLength) +#else +#define have_residual_data 0 +#endif + #endif /* __ASSEMBLY__ */ #endif /* ndef _RESIDUAL_ */ diff -Nru a/include/asm-ppc/serial.h b/include/asm-ppc/serial.h --- a/include/asm-ppc/serial.h 2004-08-25 22:01:56 -07:00 +++ b/include/asm-ppc/serial.h 2004-08-25 22:01:56 -07:00 @@ -13,17 +13,17 @@ #elif defined(CONFIG_GEMINI) #include #elif defined(CONFIG_POWERPMC250) -#include +#include #elif defined(CONFIG_LOPEC) -#include +#include #elif defined(CONFIG_MCPN765) -#include +#include #elif defined(CONFIG_MVME5100) -#include +#include #elif defined(CONFIG_PRPMC750) -#include +#include #elif defined(CONFIG_PRPMC800) -#include +#include #elif defined(CONFIG_SANDPOINT) #include #elif defined(CONFIG_SPRUCE) diff -Nru a/include/asm-ppc64/processor.h b/include/asm-ppc64/processor.h --- a/include/asm-ppc64/processor.h 2004-08-25 22:01:54 -07:00 +++ b/include/asm-ppc64/processor.h 2004-08-25 22:01:54 -07:00 @@ -626,12 +626,9 @@ #define spin_lock_prefetch(x) prefetchw(x) -#ifdef CONFIG_SCHED_SMT -#define ARCH_HAS_SCHED_DOMAIN -#define ARCH_HAS_SCHED_WAKE_IDLE -#endif - #endif /* ASSEMBLY */ + +#define HAVE_ARCH_PICK_MMAP_LAYOUT /* * Number of entries in the SLB. If this ever changes we should handle diff -Nru a/include/asm-ppc64/smp.h b/include/asm-ppc64/smp.h --- a/include/asm-ppc64/smp.h 2004-08-25 22:01:54 -07:00 +++ b/include/asm-ppc64/smp.h 2004-08-25 22:01:54 -07:00 @@ -36,6 +36,8 @@ #define smp_processor_id() (get_paca()->paca_index) #define hard_smp_processor_id() (get_paca()->hw_cpu_id) +extern cpumask_t cpu_sibling_map[NR_CPUS]; + /* Since OpenPIC has only 4 IPIs, we use slightly different message numbers. * * Make sure this matches openpic_request_IPIs in open_pic.c, or what shows up diff -Nru a/include/asm-ppc64/system.h b/include/asm-ppc64/system.h --- a/include/asm-ppc64/system.h 2004-08-25 22:01:56 -07:00 +++ b/include/asm-ppc64/system.h 2004-08-25 22:01:56 -07:00 @@ -105,6 +105,7 @@ extern void bad_page_fault(struct pt_regs *regs, unsigned long address, int sig); extern void show_regs(struct pt_regs * regs); +extern void low_hash_fault(struct pt_regs *regs, unsigned long address); extern int die(const char *str, struct pt_regs *regs, long err); extern void flush_instruction_cache(void); diff -Nru a/include/asm-s390/processor.h b/include/asm-s390/processor.h --- a/include/asm-s390/processor.h 2004-08-25 22:01:55 -07:00 +++ b/include/asm-s390/processor.h 2004-08-25 22:01:55 -07:00 @@ -76,6 +76,8 @@ #define MM_VM_SIZE(mm) DEFAULT_TASK_SIZE +#define HAVE_ARCH_PICK_MMAP_LAYOUT + typedef struct { __u32 ar4; } mm_segment_t; diff -Nru a/include/asm-s390/timer.h b/include/asm-s390/timer.h --- a/include/asm-s390/timer.h 2004-08-25 22:01:54 -07:00 +++ b/include/asm-s390/timer.h 2004-08-25 22:01:54 -07:00 @@ -45,6 +45,4 @@ extern int mod_virt_timer(struct vtimer_list *timer, __u64 expires); extern int del_virt_timer(struct vtimer_list *timer); -int stop_timers(void); - #endif diff -Nru a/include/asm-um/archparam-i386.h b/include/asm-um/archparam-i386.h --- a/include/asm-um/archparam-i386.h 2004-08-25 22:01:56 -07:00 +++ b/include/asm-um/archparam-i386.h 2004-08-25 22:01:56 -07:00 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com) + * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com) * Licensed under the GPL */ @@ -55,6 +55,93 @@ pr_reg[15] = PT_REGS_SP(regs); \ pr_reg[16] = PT_REGS_SS(regs); \ } while(0); + +#if 0 /* Turn this back on when UML has VSYSCALL working */ +#define VSYSCALL_BASE (__fix_to_virt(FIX_VSYSCALL)) +#else +#define VSYSCALL_BASE 0 +#endif + +#define VSYSCALL_EHDR ((const struct elfhdr *) VSYSCALL_BASE) +#define VSYSCALL_ENTRY ((unsigned long) &__kernel_vsyscall) +extern void *__kernel_vsyscall; + +/* + * Architecture-neutral AT_ values in 0-17, leave some room + * for more of them, start the x86-specific ones at 32. + */ +#define AT_SYSINFO 32 +#define AT_SYSINFO_EHDR 33 + +#define ARCH_DLINFO \ +do { \ + NEW_AUX_ENT(AT_SYSINFO, VSYSCALL_ENTRY); \ + NEW_AUX_ENT(AT_SYSINFO_EHDR, VSYSCALL_BASE); \ +} while (0) + +/* + * These macros parameterize elf_core_dump in fs/binfmt_elf.c to write out + * extra segments containing the vsyscall DSO contents. Dumping its + * contents makes post-mortem fully interpretable later without matching up + * the same kernel and hardware config to see what PC values meant. + * Dumping its extra ELF program headers includes all the other information + * a debugger needs to easily find how the vsyscall DSO was being used. + */ +#if 0 +#define ELF_CORE_EXTRA_PHDRS (VSYSCALL_EHDR->e_phnum) +#endif + +#undef ELF_CORE_EXTRA_PHDRS + +#if 0 +#define ELF_CORE_WRITE_EXTRA_PHDRS \ +do { \ + const struct elf_phdr *const vsyscall_phdrs = \ + (const struct elf_phdr *) (VSYSCALL_BASE \ + + VSYSCALL_EHDR->e_phoff); \ + int i; \ + Elf32_Off ofs = 0; \ + for (i = 0; i < VSYSCALL_EHDR->e_phnum; ++i) { \ + struct elf_phdr phdr = vsyscall_phdrs[i]; \ + if (phdr.p_type == PT_LOAD) { \ + ofs = phdr.p_offset = offset; \ + offset += phdr.p_filesz; \ + } \ + else \ + phdr.p_offset += ofs; \ + phdr.p_paddr = 0; /* match other core phdrs */ \ + DUMP_WRITE(&phdr, sizeof(phdr)); \ + } \ +} while (0) +#define ELF_CORE_WRITE_EXTRA_DATA \ +do { \ + const struct elf_phdr *const vsyscall_phdrs = \ + (const struct elf_phdr *) (VSYSCALL_BASE \ + + VSYSCALL_EHDR->e_phoff); \ + int i; \ + for (i = 0; i < VSYSCALL_EHDR->e_phnum; ++i) { \ + if (vsyscall_phdrs[i].p_type == PT_LOAD) \ + DUMP_WRITE((void *) vsyscall_phdrs[i].p_vaddr, \ + vsyscall_phdrs[i].p_filesz); \ + } \ +} while (0) +#endif + +#undef ELF_CORE_WRITE_EXTRA_PHDRS +#undef ELF_CORE_WRITE_EXTRA_DATA + +#define R_386_NONE 0 +#define R_386_32 1 +#define R_386_PC32 2 +#define R_386_GOT32 3 +#define R_386_PLT32 4 +#define R_386_COPY 5 +#define R_386_GLOB_DAT 6 +#define R_386_JMP_SLOT 7 +#define R_386_RELATIVE 8 +#define R_386_GOTOFF 9 +#define R_386_GOTPC 10 +#define R_386_NUM 11 /********* Bits for asm-um/delay.h **********/ diff -Nru a/include/asm-um/common.lds.S b/include/asm-um/common.lds.S --- a/include/asm-um/common.lds.S 2004-08-25 22:01:54 -07:00 +++ b/include/asm-um/common.lds.S 2004-08-25 22:01:54 -07:00 @@ -1,3 +1,5 @@ +#include + .fini : { *(.fini) } =0x9090 _etext = .; PROVIDE (etext = .); @@ -13,18 +15,6 @@ RODATA - __start___ksymtab = .; /* Kernel symbol table */ - __ksymtab : { *(__ksymtab) } - __stop___ksymtab = .; - - __start___gpl_ksymtab = .; /* Kernel symbol table: GPL-only symbols */ - __gpl_ksymtab : { *(__gpl_ksymtab) } - __stop___gpl_ksymtab = .; - - __start___kallsyms = .; /* All kernel symbols */ - __kallsyms : { *(__kallsyms) } - __stop___kallsyms = .; - .unprotected : { *(.unprotected) } . = ALIGN(4096); PROVIDE (_unprotected_end = .); @@ -46,10 +36,6 @@ .init.setup : { *(.init.setup) } __setup_end = .; - __start___param = .; - __param : { *(__param) } - __stop___param = .; - . = ALIGN(32); __per_cpu_start = . ; .data.percpu : { *(.data.percpu) } @@ -67,11 +53,17 @@ } __initcall_end = .; + __con_initcall_start = .; + .con_initcall.init : { *(.con_initcall.init) } + __con_initcall_end = .; + __uml_initcall_start = .; .uml.initcall.init : { *(.uml.initcall.init) } __uml_initcall_end = .; __init_end = .; + SECURITY_INIT + __exitcall_begin = .; .exitcall : { *(.exitcall.exit) } __exitcall_end = .; @@ -80,7 +72,33 @@ .uml.exitcall : { *(.uml.exitcall.exit) } __uml_exitcall_end = .; - . = ALIGN(4096); + . = ALIGN(4); + __alt_instructions = .; + .altinstructions : { *(.altinstructions) } + __alt_instructions_end = .; + .altinstr_replacement : { *(.altinstr_replacement) } + /* .exit.text is discard at runtime, not link time, to deal with references + from .altinstructions and .eh_frame */ + .exit.text : { *(.exit.text) } + .exit.data : { *(.exit.data) } + + __preinit_array_start = .; + .preinit_array : { *(.preinit_array) } + __preinit_array_end = .; + __init_array_start = .; + .init_array : { *(.init_array) } + __init_array_end = .; + __fini_array_start = .; + .fini_array : { *(.fini_array) } + __fini_array_end = .; + + . = ALIGN(4096); __initramfs_start = .; .init.ramfs : { *(.init.ramfs) } __initramfs_end = .; + + /* Sections to be discarded */ + /DISCARD/ : { + *(.exitcall.exit) + } + diff -Nru a/include/asm-um/cpufeature.h b/include/asm-um/cpufeature.h --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/include/asm-um/cpufeature.h 2004-08-25 22:01:56 -07:00 @@ -0,0 +1,6 @@ +#ifndef __UM_CPUFEATURE_H +#define __UM_CPUFEATURE_H + +#include "asm/arch/cpufeature.h" + +#endif diff -Nru a/include/asm-um/current.h b/include/asm-um/current.h --- a/include/asm-um/current.h 2004-08-25 22:01:54 -07:00 +++ b/include/asm-um/current.h 2004-08-25 22:01:54 -07:00 @@ -16,8 +16,10 @@ #define CURRENT_THREAD(dummy) (((unsigned long) &dummy) & \ (PAGE_MASK << CONFIG_KERNEL_STACK_ORDER)) -#define current ({ int dummy; \ - ((struct thread_info *) CURRENT_THREAD(dummy))->task; }) +#define current_thread \ + ({ int dummy; ((struct thread_info *) CURRENT_THREAD(dummy)); }) + +#define current (current_thread->task) #endif /* __ASSEMBLY__ */ diff -Nru a/include/asm-um/dma-mapping.h b/include/asm-um/dma-mapping.h --- a/include/asm-um/dma-mapping.h 2004-08-25 22:01:54 -07:00 +++ b/include/asm-um/dma-mapping.h 2004-08-25 22:01:54 -07:00 @@ -1 +1,119 @@ -#include +#ifndef _ASM_DMA_MAPPING_H +#define _ASM_DMA_MAPPING_H + +static inline int +dma_supported(struct device *dev, u64 mask) +{ + BUG(); + return(0); +} + +static inline int +dma_set_mask(struct device *dev, u64 dma_mask) +{ + BUG(); + return(0); +} + +static inline void * +dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle, + int flag) +{ + BUG(); + return((void *) 0); +} + +static inline void +dma_free_coherent(struct device *dev, size_t size, void *cpu_addr, + dma_addr_t dma_handle) +{ + BUG(); +} + +static inline dma_addr_t +dma_map_single(struct device *dev, void *cpu_addr, size_t size, + enum dma_data_direction direction) +{ + BUG(); + return(0); +} + +static inline void +dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size, + enum dma_data_direction direction) +{ + BUG(); +} + +static inline dma_addr_t +dma_map_page(struct device *dev, struct page *page, + unsigned long offset, size_t size, + enum dma_data_direction direction) +{ + BUG(); + return(0); +} + +static inline void +dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size, + enum dma_data_direction direction) +{ + BUG(); +} + +static inline int +dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, + enum dma_data_direction direction) +{ + BUG(); + return(0); +} + +static inline void +dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries, + enum dma_data_direction direction) +{ + BUG(); +} + +static inline void +dma_sync_single(struct device *dev, dma_addr_t dma_handle, size_t size, + enum dma_data_direction direction) +{ + BUG(); +} + +static inline void +dma_sync_sg(struct device *dev, struct scatterlist *sg, int nelems, + enum dma_data_direction direction) +{ + BUG(); +} + +#define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f) +#define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h) +#define dma_is_consistent(d) (1) + +static inline int +dma_get_cache_alignment(void) +{ + BUG(); + return(0); +} + +static inline void +dma_sync_single_range(struct device *dev, dma_addr_t dma_handle, + unsigned long offset, size_t size, + enum dma_data_direction direction) +{ + BUG(); +} + +static inline void +dma_cache_sync(void *vaddr, size_t size, + enum dma_data_direction direction) +{ + BUG(); +} + +#endif diff -Nru a/include/asm-um/elf.h b/include/asm-um/elf.h --- a/include/asm-um/elf.h 2004-08-25 22:01:55 -07:00 +++ b/include/asm-um/elf.h 2004-08-25 22:01:55 -07:00 @@ -15,4 +15,17 @@ #define USE_ELF_CORE_DUMP +#define R_386_NONE 0 +#define R_386_32 1 +#define R_386_PC32 2 +#define R_386_GOT32 3 +#define R_386_PLT32 4 +#define R_386_COPY 5 +#define R_386_GLOB_DAT 6 +#define R_386_JMP_SLOT 7 +#define R_386_RELATIVE 8 +#define R_386_GOTOFF 9 +#define R_386_GOTPC 10 +#define R_386_NUM 11 + #endif diff -Nru a/include/asm-um/fixmap.h b/include/asm-um/fixmap.h --- a/include/asm-um/fixmap.h 2004-08-25 22:01:56 -07:00 +++ b/include/asm-um/fixmap.h 2004-08-25 22:01:56 -07:00 @@ -34,6 +34,7 @@ FIX_KMAP_BEGIN, /* reserved pte's for temporary kernel mappings */ FIX_KMAP_END = FIX_KMAP_BEGIN+(KM_TYPE_NR*NR_CPUS)-1, #endif + FIX_VSYSCALL, __end_of_fixed_addresses }; @@ -62,6 +63,13 @@ #define __fix_to_virt(x) (FIXADDR_TOP - ((x) << PAGE_SHIFT)) #define __virt_to_fix(x) ((FIXADDR_TOP - ((x)&PAGE_MASK)) >> PAGE_SHIFT) + +/* + * This is the range that is readable by user mode, and things + * acting like user mode such as get_user_pages. + */ +#define FIXADDR_USER_START (__fix_to_virt(FIX_VSYSCALL)) +#define FIXADDR_USER_END (FIXADDR_USER_START + PAGE_SIZE) extern void __this_fixmap_does_not_exist(void); diff -Nru a/include/asm-um/irq.h b/include/asm-um/irq.h --- a/include/asm-um/irq.h 2004-08-25 22:01:56 -07:00 +++ b/include/asm-um/irq.h 2004-08-25 22:01:56 -07:00 @@ -1,15 +1,6 @@ #ifndef __UM_IRQ_H #define __UM_IRQ_H -/* The i386 irq.h has a struct task_struct in a prototype without including - * sched.h. This forward declaration kills the resulting warning. - */ -struct task_struct; - -#include "asm/ptrace.h" - -#undef NR_IRQS - #define TIMER_IRQ 0 #define UMN_IRQ 1 #define CONSOLE_IRQ 2 @@ -27,14 +18,5 @@ #define LAST_IRQ XTERM_IRQ #define NR_IRQS (LAST_IRQ + 1) - -extern int um_request_irq(unsigned int irq, int fd, int type, - void (*handler)(int, void *, struct pt_regs *), - unsigned long irqflags, const char * devname, - void *dev_id); - -struct irqaction; -struct pt_regs; -int handle_IRQ_event(unsigned int, struct pt_regs *, struct irqaction *); #endif diff -Nru a/include/asm-um/local.h b/include/asm-um/local.h --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/include/asm-um/local.h 2004-08-25 22:01:56 -07:00 @@ -0,0 +1,6 @@ +#ifndef __UM_LOCAL_H +#define __UM_LOCAL_H + +#include "asm/arch/local.h" + +#endif diff -Nru a/include/asm-um/mmu_context.h b/include/asm-um/mmu_context.h --- a/include/asm-um/mmu_context.h 2004-08-25 22:01:55 -07:00 +++ b/include/asm-um/mmu_context.h 2004-08-25 22:01:55 -07:00 @@ -26,8 +26,8 @@ unsigned cpu = smp_processor_id(); if(prev != next){ - clear_bit(cpu, &prev->cpu_vm_mask); - set_bit(cpu, &next->cpu_vm_mask); + cpu_clear(cpu, prev->cpu_vm_mask); + cpu_set(cpu, next->cpu_vm_mask); if(next != &init_mm) CHOOSE_MODE((void) 0, switch_mm_skas(next->context.skas.mm_fd)); diff -Nru a/include/asm-um/module-generic.h b/include/asm-um/module-generic.h --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/include/asm-um/module-generic.h 2004-08-25 22:01:56 -07:00 @@ -0,0 +1,6 @@ +#ifndef __UM_MODULE_GENERIC_H +#define __UM_MODULE_GENERIC_H + +#include "asm/arch/module.h" + +#endif diff -Nru a/include/asm-um/module-i386.h b/include/asm-um/module-i386.h --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/include/asm-um/module-i386.h 2004-08-25 22:01:56 -07:00 @@ -0,0 +1,13 @@ +#ifndef __UM_MODULE_I386_H +#define __UM_MODULE_I386_H + +/* UML is simple */ +struct mod_arch_specific +{ +}; + +#define Elf_Shdr Elf32_Shdr +#define Elf_Sym Elf32_Sym +#define Elf_Ehdr Elf32_Ehdr + +#endif diff -Nru a/include/asm-um/module.h b/include/asm-um/module.h --- a/include/asm-um/module.h 2004-08-25 22:01:55 -07:00 +++ /dev/null Wed Dec 31 16:00:00 196900 @@ -1,13 +0,0 @@ -#ifndef __UM_MODULE_H -#define __UM_MODULE_H - -/* UML is simple */ -struct mod_arch_specific -{ -}; - -#define Elf_Shdr Elf32_Shdr -#define Elf_Sym Elf32_Sym -#define Elf_Ehdr Elf32_Ehdr - -#endif diff -Nru a/include/asm-um/page.h b/include/asm-um/page.h --- a/include/asm-um/page.h 2004-08-25 22:01:55 -07:00 +++ b/include/asm-um/page.h 2004-08-25 22:01:55 -07:00 @@ -1,10 +1,14 @@ +/* + * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com) + * Licensed under the GPL + */ + #ifndef __UM_PAGE_H #define __UM_PAGE_H struct page; #include "asm/arch/page.h" -#include "asm/bug.h" #undef __pa #undef __va @@ -24,25 +28,25 @@ #define __va_space (8*1024*1024) -extern unsigned long region_pa(void *virt); -extern void *region_va(unsigned long phys); - -#define __pa(virt) region_pa((void *) (virt)) -#define __va(phys) region_va((unsigned long) (phys)) - -extern unsigned long page_to_pfn(struct page *page); -extern struct page *pfn_to_page(unsigned long pfn); +extern unsigned long to_phys(void *virt); +extern void *to_virt(unsigned long phys); -extern struct page *phys_to_page(unsigned long phys); +#define __pa(virt) to_phys((void *) virt) +#define __va(phys) to_virt((unsigned long) phys) -#define virt_to_page(v) (phys_to_page(__pa(v))) +#define page_to_pfn(page) ((page) - mem_map) +#define pfn_to_page(pfn) (mem_map + (pfn)) -extern struct page *page_mem_map(struct page *page); - -#define pfn_valid(pfn) (page_mem_map(pfn_to_page(pfn)) != NULL) -#define virt_addr_valid(v) pfn_valid(__pa(v) >> PAGE_SHIFT) +#define phys_to_pfn(p) ((p) >> PAGE_SHIFT) +#define pfn_to_phys(pfn) ((pfn) << PAGE_SHIFT) +#define pfn_valid(pfn) ((pfn) < max_mapnr) +#define virt_addr_valid(v) pfn_valid(phys_to_pfn(__pa(v))) + extern struct page *arch_validate(struct page *page, int mask, int order); #define HAVE_ARCH_VALIDATE + +extern void arch_free_page(struct page *page, int order); +#define HAVE_ARCH_FREE_PAGE #endif diff -Nru a/include/asm-um/pgtable.h b/include/asm-um/pgtable.h --- a/include/asm-um/pgtable.h 2004-08-25 22:01:56 -07:00 +++ b/include/asm-um/pgtable.h 2004-08-25 22:01:56 -07:00 @@ -12,8 +12,6 @@ #include "asm/page.h" #include "asm/fixmap.h" -extern pgd_t swapper_pg_dir[1024]; - extern void *um_virt_to_phys(struct task_struct *task, unsigned long virt, pte_t *pte_out); @@ -49,6 +47,8 @@ #define pgd_ERROR(e) \ printk("%s:%d: bad pgd %08lx.\n", __FILE__, __LINE__, pgd_val(e)) +extern pgd_t swapper_pg_dir[PTRS_PER_PGD]; + /* * pgd entries used up by user/kernel: */ @@ -65,10 +65,10 @@ * area for the same reason. ;) */ -extern unsigned long high_physmem; +extern unsigned long end_iomem; #define VMALLOC_OFFSET (__va_space) -#define VMALLOC_START (((unsigned long) high_physmem + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1)) +#define VMALLOC_START ((end_iomem + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1)) #ifdef CONFIG_HIGHMEM # define VMALLOC_END (PKMAP_BASE-2*PAGE_SIZE) @@ -78,12 +78,13 @@ #define _PAGE_PRESENT 0x001 #define _PAGE_NEWPAGE 0x002 -#define _PAGE_PROTNONE 0x004 /* If not present */ -#define _PAGE_RW 0x008 -#define _PAGE_USER 0x010 -#define _PAGE_ACCESSED 0x020 -#define _PAGE_DIRTY 0x040 -#define _PAGE_NEWPROT 0x080 +#define _PAGE_NEWPROT 0x004 +#define _PAGE_FILE 0x008 /* set:pagecache unset:swap */ +#define _PAGE_PROTNONE 0x010 /* If not present */ +#define _PAGE_RW 0x020 +#define _PAGE_USER 0x040 +#define _PAGE_ACCESSED 0x080 +#define _PAGE_DIRTY 0x100 #define REGION_MASK 0xf0000000 #define REGION_SHIFT 28 @@ -143,7 +144,8 @@ #define BAD_PAGETABLE __bad_pagetable() #define BAD_PAGE __bad_page() -#define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page)) + +#define ZERO_PAGE(vaddr) virt_to_page(empty_zero_page) /* number of bits that fit into a memory pointer */ #define BITS_PER_PTR (8*sizeof(unsigned long)) @@ -164,9 +166,6 @@ #define pte_clear(xp) do { pte_val(*(xp)) = _PAGE_NEWPAGE; } while (0) -#define phys_region_index(x) (((x) & REGION_MASK) >> REGION_SHIFT) -#define pte_region_index(x) phys_region_index(pte_val(x)) - #define pmd_none(x) (!(pmd_val(x) & ~_PAGE_NEWPAGE)) #define pmd_bad(x) ((pmd_val(x) & (~PAGE_MASK & ~_PAGE_USER)) != _KERNPG_TABLE) #define pmd_present(x) (pmd_val(x) & _PAGE_PRESENT) @@ -188,19 +187,25 @@ #define pages_to_mb(x) ((x) >> (20-PAGE_SHIFT)) -extern struct page *pte_mem_map(pte_t pte); -extern struct page *phys_mem_map(unsigned long phys); -extern unsigned long phys_to_pfn(unsigned long p); -extern unsigned long pfn_to_phys(unsigned long pfn); - -#define pte_page(x) pfn_to_page(pte_pfn(x)) -#define pte_address(x) (__va(pte_val(x) & PAGE_MASK)) -#define mk_phys(a, r) ((a) + (r << REGION_SHIFT)) -#define phys_addr(p) ((p) & ~REGION_MASK) -#define phys_page(p) (phys_mem_map(p) + ((phys_addr(p)) >> PAGE_SHIFT)) +#define pte_page(pte) phys_to_page(pte_val(pte)) +#define pmd_page(pmd) phys_to_page(pmd_val(pmd) & PAGE_MASK) + #define pte_pfn(x) phys_to_pfn(pte_val(x)) #define pfn_pte(pfn, prot) __pte(pfn_to_phys(pfn) | pgprot_val(prot)) -#define pfn_pmd(pfn, prot) __pmd(pfn_to_phys(pfn) | pgprot_val(prot)) + +extern struct page *phys_to_page(const unsigned long phys); +extern struct page *__virt_to_page(const unsigned long virt); +#define virt_to_page(addr) __virt_to_page((const unsigned long) addr) + +/* + * Bits 0 through 3 are taken + */ +#define PTE_FILE_MAX_BITS 28 + +#define pte_to_pgoff(pte) ((pte).pte_low >> 4) + +#define pgoff_to_pte(off) \ + ((pte_t) { ((off) << 4) + _PAGE_FILE }) static inline pte_t pte_mknewprot(pte_t pte) { @@ -235,6 +240,12 @@ * The following only work if pte_present() is true. * Undefined behaviour if not.. */ +static inline int pte_user(pte_t pte) +{ + return((pte_val(pte) & _PAGE_USER) && + !(pte_val(pte) & _PAGE_PROTNONE)); +} + static inline int pte_read(pte_t pte) { return((pte_val(pte) & _PAGE_USER) && @@ -252,6 +263,14 @@ !(pte_val(pte) & _PAGE_PROTNONE)); } +/* + * The following only works if pte_present() is not true. + */ +static inline int pte_file(pte_t pte) +{ + return (pte).pte_low & _PAGE_FILE; +} + static inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_DIRTY; } static inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED; } static inline int pte_newpage(pte_t pte) { return pte_val(pte) & _PAGE_NEWPAGE; } @@ -334,14 +353,7 @@ * and a page entry and page directory to the page they refer to. */ -#define mk_pte(page, pgprot) \ -({ \ - pte_t __pte; \ - \ - pte_val(__pte) = page_to_phys(page) + pgprot_val(pgprot);\ - if(pte_present(__pte)) pte_mknewprot(pte_mknewpage(__pte)); \ - __pte; \ -}) +extern pte_t mk_pte(struct page *page, pgprot_t pgprot); static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) { @@ -351,17 +363,27 @@ } #define pmd_page_kernel(pmd) ((unsigned long) __va(pmd_val(pmd) & PAGE_MASK)) -#define pmd_page(pmd) (phys_mem_map(pmd_val(pmd) & PAGE_MASK) + \ - ((phys_addr(pmd_val(pmd)) >> PAGE_SHIFT))) -/* to find an entry in a page-table-directory. */ +/* + * the pgd page can be thought of an array like this: pgd_t[PTRS_PER_PGD] + * + * this macro returns the index of the entry in the pgd page which would + * control the given virtual address + */ #define pgd_index(address) ((address >> PGDIR_SHIFT) & (PTRS_PER_PGD-1)) -/* to find an entry in a page-table-directory */ +/* + * pgd_offset() returns a (pgd_t *) + * pgd_index() is used get the offset into the pgd page's array of pgd_t's; + */ #define pgd_offset(mm, address) \ ((mm)->pgd + ((address) >> PGDIR_SHIFT)) -/* to find an entry in a kernel page-table-directory */ + +/* + * a shortcut which implies the use of the kernel's pgd, instead + * of a process's + */ #define pgd_offset_k(address) pgd_offset(&init_mm, address) #define pmd_index(address) \ @@ -373,7 +395,12 @@ return (pmd_t *) dir; } -/* Find an entry in the third-level page table.. */ +/* + * the pte page can be thought of an array like this: pte_t[PTRS_PER_PTE] + * + * this macro returns the index of the entry in the pte page which would + * control the given virtual address + */ #define pte_index(address) (((address) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1)) #define pte_offset_kernel(dir, address) \ ((pte_t *) pmd_page_kernel(*(dir)) + pte_index(address)) @@ -387,11 +414,11 @@ #define update_mmu_cache(vma,address,pte) do ; while (0) /* Encode and de-code a swap entry */ -#define __swp_type(x) (((x).val >> 3) & 0x7f) -#define __swp_offset(x) ((x).val >> 10) +#define __swp_type(x) (((x).val >> 4) & 0x3f) +#define __swp_offset(x) ((x).val >> 11) #define __swp_entry(type, offset) \ - ((swp_entry_t) { ((type) << 3) | ((offset) << 10) }) + ((swp_entry_t) { ((type) << 4) | ((offset) << 11) }) #define __pte_to_swp_entry(pte) \ ((swp_entry_t) { pte_val(pte_mkuptodate(pte)) }) #define __swp_entry_to_pte(x) ((pte_t) { (x).val }) diff -Nru a/include/asm-um/processor-generic.h b/include/asm-um/processor-generic.h --- a/include/asm-um/processor-generic.h 2004-08-25 22:01:54 -07:00 +++ b/include/asm-um/processor-generic.h 2004-08-25 22:01:54 -07:00 @@ -11,33 +11,14 @@ struct task_struct; #include "linux/config.h" -#include "linux/signal.h" #include "asm/ptrace.h" -#include "asm/siginfo.h" #include "choose-mode.h" struct mm_struct; #define current_text_addr() ((void *) 0) -#define cpu_relax() do ; while (0) - -#ifdef CONFIG_MODE_TT -struct proc_tt_mode { - int extern_pid; - int tracing; - int switch_pipe[2]; - int singlestep_syscall; - int vm_seq; -}; -#endif - -#ifdef CONFIG_MODE_SKAS -struct proc_skas_mode { - void *switch_buf; - void *fork_buf; -}; -#endif +#define cpu_relax() barrier() struct thread_struct { int forking; @@ -46,6 +27,7 @@ struct pt_regs regs; unsigned long cr2; int err; + unsigned long trap_no; void *fault_addr; void *fault_catcher; struct task_struct *prev_sched; @@ -54,10 +36,20 @@ struct arch_thread arch; union { #ifdef CONFIG_MODE_TT - struct proc_tt_mode tt; + struct { + int extern_pid; + int tracing; + int switch_pipe[2]; + int singlestep_syscall; + int vm_seq; + } tt; #endif #ifdef CONFIG_MODE_SKAS - struct proc_skas_mode skas; + struct { + void *switch_buf; + void *fork_buf; + int mm_count; + } skas; #endif } mode; struct { @@ -99,13 +91,18 @@ } mm_segment_t; extern struct task_struct *alloc_task_struct(void); -extern void free_task_struct(struct task_struct *task); extern void release_thread(struct task_struct *); extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); extern void dump_thread(struct pt_regs *regs, struct user *u); +extern void prepare_to_copy(struct task_struct *tsk); extern unsigned long thread_saved_pc(struct task_struct *t); + +static inline void mm_copy_segments(struct mm_struct *from_mm, + struct mm_struct *new_mm) +{ +} #define init_stack (init_thread_union.stack) diff -Nru a/include/asm-um/processor-i386.h b/include/asm-um/processor-i386.h --- a/include/asm-um/processor-i386.h 2004-08-25 22:01:54 -07:00 +++ b/include/asm-um/processor-i386.h 2004-08-25 22:01:54 -07:00 @@ -6,8 +6,8 @@ #ifndef __UM_PROCESSOR_I386_H #define __UM_PROCESSOR_I386_H -extern int cpu_has_xmm; -extern int cpu_has_cmov; +extern int host_has_xmm; +extern int host_has_cmov; struct arch_thread { unsigned long debugregs[8]; diff -Nru a/include/asm-um/ptrace-generic.h b/include/asm-um/ptrace-generic.h --- a/include/asm-um/ptrace-generic.h 2004-08-25 22:01:56 -07:00 +++ b/include/asm-um/ptrace-generic.h 2004-08-25 22:01:56 -07:00 @@ -45,6 +45,8 @@ #define PT_REGS_SC(r) UPT_SC(&(r)->regs) +#define instruction_pointer(regs) PT_REGS_IP(regs) + struct task_struct; extern unsigned long getreg(struct task_struct *child, int regno); diff -Nru a/include/asm-um/sections.h b/include/asm-um/sections.h --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/include/asm-um/sections.h 2004-08-25 22:01:56 -07:00 @@ -0,0 +1,7 @@ +#ifndef _UM_SECTIONS_H +#define _UM_SECTIONS_H + +/* nothing to see, move along */ +#include + +#endif diff -Nru a/include/asm-um/smp.h b/include/asm-um/smp.h --- a/include/asm-um/smp.h 2004-08-25 22:01:54 -07:00 +++ b/include/asm-um/smp.h 2004-08-25 22:01:54 -07:00 @@ -10,7 +10,7 @@ extern cpumask_t cpu_online_map; -#define smp_processor_id() (current->thread_info->cpu) +#define smp_processor_id() (current_thread->cpu) #define cpu_logical_map(n) (n) #define cpu_number_map(n) (n) #define PROC_CHANGE_PENALTY 15 /* Pick a number, any number */ diff -Nru a/include/asm-um/smplock.h b/include/asm-um/smplock.h --- a/include/asm-um/smplock.h 2004-08-25 22:01:54 -07:00 +++ /dev/null Wed Dec 31 16:00:00 196900 @@ -1,6 +0,0 @@ -#ifndef __UM_SMPLOCK_H -#define __UM_SMPLOCK_H - -#include "asm/arch/smplock.h" - -#endif diff -Nru a/include/asm-um/spinlock.h b/include/asm-um/spinlock.h --- a/include/asm-um/spinlock.h 2004-08-25 22:01:56 -07:00 +++ /dev/null Wed Dec 31 16:00:00 196900 @@ -1,10 +0,0 @@ -#ifndef __UM_SPINLOCK_H -#define __UM_SPINLOCK_H - -#include "linux/config.h" - -#ifdef CONFIG_SMP -#include "asm/arch/spinlock.h" -#endif - -#endif diff -Nru a/include/asm-um/system-generic.h b/include/asm-um/system-generic.h --- a/include/asm-um/system-generic.h 2004-08-25 22:01:56 -07:00 +++ b/include/asm-um/system-generic.h 2004-08-25 22:01:56 -07:00 @@ -23,8 +23,10 @@ extern void block_signals(void); extern void unblock_signals(void); -#define local_save_flags(flags) do { (flags) = get_signals(); } while(0) -#define local_irq_restore(flags) do { set_signals(flags); } while(0) +#define local_save_flags(flags) do { typecheck(unsigned long, flags); \ + (flags) = get_signals(); } while(0) +#define local_irq_restore(flags) do { typecheck(unsigned long, flags); \ + set_signals(flags); } while(0) #define local_irq_save(flags) do { local_save_flags(flags); \ local_irq_disable(); } while(0) @@ -38,5 +40,8 @@ local_save_flags(flags); \ (flags == 0); \ }) + +extern void *_switch_to(void *prev, void *next, void *last); +#define switch_to(prev, next, last) prev = _switch_to(prev, next, last) #endif diff -Nru a/include/asm-um/system-i386.h b/include/asm-um/system-i386.h --- a/include/asm-um/system-i386.h 2004-08-25 22:01:55 -07:00 +++ b/include/asm-um/system-i386.h 2004-08-25 22:01:55 -07:00 @@ -2,36 +2,5 @@ #define __UM_SYSTEM_I386_H #include "asm/system-generic.h" - -static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old, - unsigned long new, int size) -{ - unsigned long prev; - switch (size) { - case 1: - __asm__ __volatile__(LOCK_PREFIX "cmpxchgb %b1,%2" - : "=a"(prev) - : "q"(new), "m"(*__xg(ptr)), "0"(old) - : "memory"); - return prev; - case 2: - __asm__ __volatile__(LOCK_PREFIX "cmpxchgw %w1,%2" - : "=a"(prev) - : "q"(new), "m"(*__xg(ptr)), "0"(old) - : "memory"); - return prev; - case 4: - __asm__ __volatile__(LOCK_PREFIX "cmpxchgl %1,%2" - : "=a"(prev) - : "q"(new), "m"(*__xg(ptr)), "0"(old) - : "memory"); - return prev; - } - return old; -} - -#define cmpxchg(ptr,o,n)\ - ((__typeof__(*(ptr)))__cmpxchg((ptr),(unsigned long)(o),\ - (unsigned long)(n),sizeof(*(ptr)))) #endif diff -Nru a/include/asm-um/thread_info.h b/include/asm-um/thread_info.h --- a/include/asm-um/thread_info.h 2004-08-25 22:01:55 -07:00 +++ b/include/asm-um/thread_info.h 2004-08-25 22:01:55 -07:00 @@ -9,6 +9,7 @@ #ifndef __ASSEMBLY__ #include +#include struct thread_info { struct task_struct *task; /* main task structure */ @@ -43,15 +44,18 @@ static inline struct thread_info *current_thread_info(void) { struct thread_info *ti; - __asm__("andl %%esp,%0; ":"=r" (ti) : "0" (~16383UL)); + unsigned long mask = PAGE_SIZE * + (1 << CONFIG_KERNEL_STACK_ORDER) - 1; + __asm__("andl %%esp,%0; ":"=r" (ti) : "0" (~mask)); return ti; } /* thread information allocation */ -#define THREAD_SIZE (4*PAGE_SIZE) -#define alloc_thread_info(tsk) ((struct thread_info *) \ - __get_free_pages(GFP_KERNEL,2)) -#define free_thread_info(ti) free_pages((unsigned long) (ti), 2) +#define THREAD_SIZE ((1 << CONFIG_KERNEL_STACK_ORDER) * PAGE_SIZE) +#define alloc_thread_info(tsk) \ + ((struct thread_info *) kmalloc(THREAD_SIZE, GFP_KERNEL)) +#define free_thread_info(ti) kfree(ti) + #define get_thread_info(ti) get_task_struct((ti)->task) #define put_thread_info(ti) put_task_struct((ti)->task) @@ -65,11 +69,13 @@ #define TIF_POLLING_NRFLAG 3 /* true if poll_idle() is polling * TIF_NEED_RESCHED */ +#define TIF_RESTART_BLOCK 4 #define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE) #define _TIF_SIGPENDING (1 << TIF_SIGPENDING) #define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED) #define _TIF_POLLING_NRFLAG (1 << TIF_POLLING_NRFLAG) +#define _TIF_RESTART_BLOCK (1 << TIF_RESTART_BLOCK) #endif diff -Nru a/include/asm-um/timex.h b/include/asm-um/timex.h --- a/include/asm-um/timex.h 2004-08-25 22:01:55 -07:00 +++ b/include/asm-um/timex.h 2004-08-25 22:01:55 -07:00 @@ -1,8 +1,6 @@ #ifndef __UM_TIMEX_H #define __UM_TIMEX_H -#include "linux/time.h" - typedef unsigned long cycles_t; #define cacheflush_time (0) diff -Nru a/include/asm-um/uaccess.h b/include/asm-um/uaccess.h --- a/include/asm-um/uaccess.h 2004-08-25 22:01:55 -07:00 +++ b/include/asm-um/uaccess.h 2004-08-25 22:01:55 -07:00 @@ -6,6 +6,8 @@ #ifndef __UM_UACCESS_H #define __UM_UACCESS_H +#include "linux/sched.h" + #define VERIFY_READ 0 #define VERIFY_WRITE 1 diff -Nru a/include/asm-um/unistd.h b/include/asm-um/unistd.h --- a/include/asm-um/unistd.h 2004-08-25 22:01:56 -07:00 +++ b/include/asm-um/unistd.h 2004-08-25 22:01:56 -07:00 @@ -48,7 +48,10 @@ set_fs(KERNEL_DS); \ ret = sys(args); \ set_fs(fs); \ - return ret; + if (ret >= 0) \ + return ret; \ + errno = -(long)ret; \ + return -1; static inline long open(const char *pathname, int flags, int mode) { diff -Nru a/include/asm-x86_64/acpi.h b/include/asm-x86_64/acpi.h --- a/include/asm-x86_64/acpi.h 2004-08-25 22:01:55 -07:00 +++ b/include/asm-x86_64/acpi.h 2004-08-25 22:01:55 -07:00 @@ -99,6 +99,11 @@ :"=r"(n_hi), "=r"(n_lo) \ :"0"(n_hi), "1"(n_lo)) +/* + * Refer Intel ACPI _PDC support document for bit definitions + */ +#define ACPI_PDC_EST_CAPABILITY_SMP 0xa +#define ACPI_PDC_EST_CAPABILITY_MSR 0x1 #ifdef CONFIG_ACPI_BOOT extern int acpi_lapic; diff -Nru a/include/asm-x86_64/bitops.h b/include/asm-x86_64/bitops.h --- a/include/asm-x86_64/bitops.h 2004-08-25 22:01:55 -07:00 +++ b/include/asm-x86_64/bitops.h 2004-08-25 22:01:55 -07:00 @@ -25,10 +25,10 @@ * Note that @nr may be almost arbitrarily large; this function is not * restricted to acting on a single-word quantity. */ -static __inline__ void set_bit(long nr, volatile void * addr) +static __inline__ void set_bit(int nr, volatile void * addr) { __asm__ __volatile__( LOCK_PREFIX - "btsq %1,%0" + "btsl %1,%0" :"=m" (ADDR) :"dIr" (nr) : "memory"); } @@ -254,128 +254,37 @@ #undef ADDR -/** - * find_first_zero_bit - find the first zero bit in a memory region - * @addr: The address to start the search at - * @size: The maximum size to search - * - * Returns the bit-number of the first zero bit, not the number of the byte - * containing a bit. - */ -static __inline__ int find_first_zero_bit(const unsigned long * addr, unsigned size) -{ - int d0, d1, d2; - int res; - - if (!size) - return 0; - __asm__ __volatile__( - "movl $-1,%%eax\n\t" - "xorl %%edx,%%edx\n\t" - "repe; scasl\n\t" - "je 1f\n\t" - "xorl -4(%%rdi),%%eax\n\t" - "subq $4,%%rdi\n\t" - "bsfl %%eax,%%edx\n" - "1:\tsubq %%rbx,%%rdi\n\t" - "shlq $3,%%rdi\n\t" - "addq %%rdi,%%rdx" - :"=d" (res), "=&c" (d0), "=&D" (d1), "=&a" (d2) - :"1" ((size + 31) >> 5), "2" (addr), "b" (addr) : "memory"); - return res; -} - -/** - * find_next_zero_bit - find the first zero bit in a memory region - * @addr: The address to base the search on - * @offset: The bitnumber to start searching at - * @size: The maximum size to search - */ -static __inline__ int find_next_zero_bit (const unsigned long * addr, int size, int offset) -{ - unsigned long * p = ((unsigned long *) addr) + (offset >> 6); - unsigned long set = 0; - unsigned long res, bit = offset&63; - - if (bit) { - /* - * Look for zero in first word - */ - __asm__("bsfq %1,%0\n\t" - "cmoveq %2,%0" - : "=r" (set) - : "r" (~(*p >> bit)), "r"(64L)); - if (set < (64 - bit)) - return set + offset; - set = 64 - bit; - p++; - } - /* - * No zero yet, search remaining full words for a zero - */ - res = find_first_zero_bit ((const unsigned long *)p, size - 64 * (p - (unsigned long *) addr)); - return (offset + set + res); -} - - -/** - * find_first_bit - find the first set bit in a memory region - * @addr: The address to start the search at - * @size: The maximum size to search - * - * Returns the bit-number of the first set bit, not the number of the byte - * containing a bit. - */ -static __inline__ int find_first_bit(const unsigned long * addr, unsigned size) -{ - int d0, d1; - int res; - - /* This looks at memory. Mark it volatile to tell gcc not to move it around */ - __asm__ __volatile__( - "xorl %%eax,%%eax\n\t" - "repe; scasl\n\t" - "jz 1f\n\t" - "leaq -4(%%rdi),%%rdi\n\t" - "bsfl (%%rdi),%%eax\n" - "1:\tsubq %%rbx,%%rdi\n\t" - "shll $3,%%edi\n\t" - "addl %%edi,%%eax" - :"=a" (res), "=&c" (d0), "=&D" (d1) - :"1" ((size + 31) >> 5), "2" (addr), "b" (addr) : "memory"); - return res; -} - -/** - * find_next_bit - find the first set bit in a memory region - * @addr: The address to base the search on - * @offset: The bitnumber to start searching at - * @size: The maximum size to search - */ -static __inline__ int find_next_bit(const unsigned long * addr, int size, int offset) -{ - const unsigned long * p = addr + (offset >> 6); - unsigned long set = 0, bit = offset & 63, res; +extern long find_first_zero_bit(const unsigned long * addr, unsigned long size); +extern long find_next_zero_bit (const unsigned long * addr, long size, long offset); +extern long find_first_bit(const unsigned long * addr, unsigned long size); +extern long find_next_bit(const unsigned long * addr, long size, long offset); + +/* return index of first bet set in val or max when no bit is set */ +static inline unsigned long __scanbit(unsigned long val, unsigned long max) +{ + asm("bsfq %1,%0 ; cmovz %2,%0" : "=&r" (val) : "r" (val), "r" (max)); + return val; +} + +#define find_first_bit(addr,size) \ +((__builtin_constant_p(size) && size <= BITS_PER_LONG ? \ + (__scanbit(*(unsigned long *)addr,(size))) : \ + find_first_bit(addr,size))) + +#define find_next_bit(addr,size,off) \ +((__builtin_constant_p(size) && size <= BITS_PER_LONG ? \ + ((off) + (__scanbit((*(unsigned long *)addr) >> (off),(size)-(off)))) : \ + find_next_bit(addr,size,off))) + +#define find_first_zero_bit(addr,size) \ +((__builtin_constant_p(size) && size <= BITS_PER_LONG ? \ + (__scanbit(~*(unsigned long *)addr,(size))) : \ + find_first_zero_bit(addr,size))) - if (bit) { - /* - * Look for nonzero in the first 64 bits: - */ - __asm__("bsfq %1,%0\n\t" - "cmoveq %2,%0\n\t" - : "=r" (set) - : "r" (*p >> bit), "r" (64L)); - if (set < (64 - bit)) - return set + offset; - set = 64 - bit; - p++; - } - /* - * No set bit yet, search remaining full words for a bit - */ - res = find_first_bit (p, size - 64 * (p - addr)); - return (offset + set + res); -} +#define find_next_zero_bit(addr,size,off) \ +((__builtin_constant_p(size) && size <= BITS_PER_LONG ? \ + ((off)+(__scanbit(~(((*(unsigned long *)addr)) >> (off)),(size)-(off)))) : \ + find_next_zero_bit(addr,size,off))) /* * Find string of zero bits in a bitmap. -1 when not found. diff -Nru a/include/asm-x86_64/cpufeature.h b/include/asm-x86_64/cpufeature.h --- a/include/asm-x86_64/cpufeature.h 2004-08-25 22:01:55 -07:00 +++ b/include/asm-x86_64/cpufeature.h 2004-08-25 22:01:55 -07:00 @@ -63,8 +63,14 @@ #define X86_FEATURE_K8_C (3*32+ 4) /* C stepping K8 */ /* Intel-defined CPU features, CPUID level 0x00000001 (ecx), word 4 */ -#define X86_FEATURE_EST (4*32+ 7) /* Enhanced SpeedStep */ +#define X86_FEATURE_XMM3 (4*32+ 0) /* Streaming SIMD Extensions-3 */ #define X86_FEATURE_MWAIT (4*32+ 3) /* Monitor/Mwait support */ +#define X86_FEATURE_DSCPL (4*32+ 4) /* CPL Qualified Debug Store */ +#define X86_FEATURE_EST (4*32+ 7) /* Enhanced SpeedStep */ +#define X86_FEATURE_TM2 (4*32+ 8) /* Thermal Monitor 2 */ +#define X86_FEATURE_CID (4*32+10) /* Context ID */ +#define X86_FEATURE_CX16 (4*32+13) /* CMPXCHG16B */ +#define X86_FEATURE_XTPR (4*32+14) /* Send Task Priority Messages */ #define cpu_has(c, bit) test_bit(bit, (c)->x86_capability) #define boot_cpu_has(bit) test_bit(bit, boot_cpu_data.x86_capability) @@ -81,6 +87,8 @@ #define cpu_has_mmx 1 #define cpu_has_fxsr 1 #define cpu_has_xmm 1 +#define cpu_has_xmm2 1 +#define cpu_has_xmm3 boot_cpu_has(X86_FEATURE_XMM3) #define cpu_has_ht boot_cpu_has(X86_FEATURE_HT) #define cpu_has_mp 1 /* XXX */ #define cpu_has_k6_mtrr 0 diff -Nru a/include/asm-x86_64/dma-mapping.h b/include/asm-x86_64/dma-mapping.h --- a/include/asm-x86_64/dma-mapping.h 2004-08-25 22:01:55 -07:00 +++ b/include/asm-x86_64/dma-mapping.h 2004-08-25 22:01:55 -07:00 @@ -1,6 +1,139 @@ #ifndef _X8664_DMA_MAPPING_H #define _X8664_DMA_MAPPING_H 1 -#include +/* + * IOMMU interface. See Documentation/DMA-mapping.txt and DMA-API.txt for + * documentation. + */ + +#include +#include + +#include +#include +#include + +extern dma_addr_t bad_dma_address; +#define dma_mapping_error(x) \ + (swiotlb ? swiotlb_dma_mapping_error(x) : ((x) == bad_dma_address)) + +void *dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle, + unsigned gfp); +void dma_free_coherent(struct device *dev, size_t size, void *vaddr, + dma_addr_t dma_handle); + +#ifdef CONFIG_GART_IOMMU + +extern dma_addr_t dma_map_single(struct device *hwdev, void *ptr, size_t size, + int direction); +extern void dma_unmap_single(struct device *dev, dma_addr_t addr,size_t size, + int direction); + +#else + +/* No IOMMU */ + +static inline dma_addr_t dma_map_single(struct device *hwdev, void *ptr, + size_t size, int direction) +{ + dma_addr_t addr; + + if (direction == DMA_NONE) + out_of_line_bug(); + addr = virt_to_bus(ptr); + + if ((addr+size) & ~*hwdev->dma_mask) + out_of_line_bug(); + return addr; +} + +static inline void dma_unmap_single(struct device *hwdev, dma_addr_t dma_addr, + size_t size, int direction) +{ + if (direction == DMA_NONE) + out_of_line_bug(); + /* Nothing to do */ +} + +#endif + +#define dma_map_page(dev,page,offset,size,dir) \ + dma_map_single((dev), page_address(page)+(offset), (size), (dir)) + +static inline void dma_sync_single_for_cpu(struct device *hwdev, + dma_addr_t dma_handle, + size_t size, int direction) +{ + if (direction == DMA_NONE) + out_of_line_bug(); + + if (swiotlb) + return swiotlb_sync_single_for_cpu(hwdev,dma_handle,size,direction); + + flush_write_buffers(); +} + +static inline void dma_sync_single_for_device(struct device *hwdev, + dma_addr_t dma_handle, + size_t size, int direction) +{ + if (direction == DMA_NONE) + out_of_line_bug(); + + if (swiotlb) + return swiotlb_sync_single_for_device(hwdev,dma_handle,size,direction); + + flush_write_buffers(); +} + +static inline void dma_sync_sg_for_cpu(struct device *hwdev, + struct scatterlist *sg, + int nelems, int direction) +{ + if (direction == DMA_NONE) + out_of_line_bug(); + + if (swiotlb) + return swiotlb_sync_sg_for_cpu(hwdev,sg,nelems,direction); + + flush_write_buffers(); +} + +static inline void dma_sync_sg_for_device(struct device *hwdev, + struct scatterlist *sg, + int nelems, int direction) +{ + if (direction == DMA_NONE) + out_of_line_bug(); + + if (swiotlb) + return swiotlb_sync_sg_for_device(hwdev,sg,nelems,direction); + + flush_write_buffers(); +} + +extern int dma_map_sg(struct device *hwdev, struct scatterlist *sg, + int nents, int direction); +extern void dma_unmap_sg(struct device *hwdev, struct scatterlist *sg, + int nents, int direction); + +#define dma_unmap_page dma_unmap_single + +extern int dma_supported(struct device *hwdev, u64 mask); +extern int dma_get_cache_alignment(void); +#define dma_is_consistent(h) 1 + +static inline int dma_set_mask(struct device *dev, u64 mask) +{ + if (!dev->dma_mask || !dma_supported(dev, mask)) + return -EIO; + *dev->dma_mask = mask; + return 0; +} + +static inline void dma_cache_sync(void *vaddr, size_t size, enum dma_data_direction dir) +{ + flush_write_buffers(); +} #endif diff -Nru a/include/asm-x86_64/i387.h b/include/asm-x86_64/i387.h --- a/include/asm-x86_64/i387.h 2004-08-25 22:01:55 -07:00 +++ b/include/asm-x86_64/i387.h 2004-08-25 22:01:55 -07:00 @@ -39,16 +39,25 @@ * FPU lazy state save handling... */ -#define kernel_fpu_end() stts() - #define unlazy_fpu(tsk) do { \ if ((tsk)->thread_info->status & TS_USEDFPU) \ save_init_fpu(tsk); \ } while (0) +/* Ignore delayed exceptions from user space */ +static inline void tolerant_fwait(void) +{ + asm volatile("1: fwait\n" + "2:\n" + " .section __ex_table,\"a\"\n" + " .align 8\n" + " .quad 1b,2b\n" + " .previous\n"); +} + #define clear_fpu(tsk) do { \ if ((tsk)->thread_info->status & TS_USEDFPU) { \ - asm volatile("fnclex ; fwait"); \ + tolerant_fwait(); \ (tsk)->thread_info->status &= ~TS_USEDFPU; \ stts(); \ } \ @@ -116,6 +125,7 @@ static inline void kernel_fpu_begin(void) { struct thread_info *me = current_thread_info(); + preempt_disable(); if (me->status & TS_USEDFPU) { asm volatile("rex64 ; fxsave %0 ; fnclex" : "=m" (me->task->thread.i387.fxsave)); @@ -125,9 +135,15 @@ clts(); } +static inline void kernel_fpu_end(void) +{ + stts(); + preempt_enable(); +} + static inline void save_init_fpu( struct task_struct *tsk ) { - asm volatile( "fxsave %0 ; fnclex" + asm volatile( "rex64 ; fxsave %0 ; fnclex" : "=m" (tsk->thread.i387.fxsave)); tsk->thread_info->status &= ~TS_USEDFPU; stts(); diff -Nru a/include/asm-x86_64/ia32.h b/include/asm-x86_64/ia32.h --- a/include/asm-x86_64/ia32.h 2004-08-25 22:01:56 -07:00 +++ b/include/asm-x86_64/ia32.h 2004-08-25 22:01:56 -07:00 @@ -78,12 +78,6 @@ unsigned long long st_ino; } __attribute__((packed)); - -typedef union sigval32 { - int sival_int; - unsigned int sival_ptr; -} sigval_t32; - typedef struct siginfo32 { int si_signo; int si_errno; @@ -102,7 +96,7 @@ struct { int _tid; /* timer id */ int _overrun; /* overrun count */ - sigval_t32 _sigval; /* same as below */ + compat_sigval_t _sigval; /* same as below */ int _sys_private; /* not to be passed to user */ int _overrun_incr; /* amount to add to overrun */ } _timer; @@ -111,7 +105,7 @@ struct { unsigned int _pid; /* sender's pid */ unsigned int _uid; /* sender's uid */ - sigval_t32 _sigval; + compat_sigval_t _sigval; } _rt; /* SIGCHLD */ diff -Nru a/include/asm-x86_64/io.h b/include/asm-x86_64/io.h --- a/include/asm-x86_64/io.h 2004-08-25 22:01:55 -07:00 +++ b/include/asm-x86_64/io.h 2004-08-25 22:01:55 -07:00 @@ -186,10 +186,30 @@ #define __raw_readl readl #define __raw_readq readq -#define writeb(b,addr) (*(volatile unsigned char *) (addr) = (b)) -#define writew(b,addr) (*(volatile unsigned short *) (addr) = (b)) +#ifdef CONFIG_UNORDERED_IO +static inline void __writel(u32 val, void *addr) +{ + volatile u32 *target = addr; + asm volatile("movnti %1,%0" + : "=m" (*target) + : "r" (val) : "memory"); +} + +static inline void __writeq(u64 val, void *addr) +{ + volatile u64 *target = addr; + asm volatile("movnti %1,%0" + : "=m" (*target) + : "r" (val) : "memory"); +} +#define writeq(val,addr) __writeq((val),(void *)(addr)) +#define writel(val,addr) __writel((val),(void *)(addr)) +#else #define writel(b,addr) (*(volatile unsigned int *) (addr) = (b)) #define writeq(b,addr) (*(volatile unsigned long *) (addr) = (b)) +#endif +#define writeb(b,addr) (*(volatile unsigned char *) (addr) = (b)) +#define writew(b,addr) (*(volatile unsigned short *) (addr) = (b)) #define __raw_writeb writeb #define __raw_writew writew #define __raw_writel writel @@ -299,11 +319,8 @@ #define flush_write_buffers() -/* Disable vmerge for now. Need to fix the block layer code - to check for non iommu addresses first. - When the IOMMU is force it is safe to enable. */ -extern int iommu_merge; -#define BIO_VMERGE_BOUNDARY (iommu_merge ? 4096 : 0) +extern int iommu_bio_merge; +#define BIO_VMERGE_BOUNDARY iommu_bio_merge #endif /* __KERNEL__ */ diff -Nru a/include/asm-x86_64/mpspec.h b/include/asm-x86_64/mpspec.h --- a/include/asm-x86_64/mpspec.h 2004-08-25 22:01:55 -07:00 +++ b/include/asm-x86_64/mpspec.h 2004-08-25 22:01:55 -07:00 @@ -166,7 +166,6 @@ }; extern unsigned char mp_bus_id_to_type [MAX_MP_BUSSES]; extern int mp_bus_id_to_pci_bus [MAX_MP_BUSSES]; -extern cpumask_t pci_bus_to_cpumask [256]; extern unsigned int boot_cpu_physical_apicid; extern int smp_found_config; diff -Nru a/include/asm-x86_64/mtrr.h b/include/asm-x86_64/mtrr.h --- a/include/asm-x86_64/mtrr.h 2004-08-25 22:01:54 -07:00 +++ b/include/asm-x86_64/mtrr.h 2004-08-25 22:01:54 -07:00 @@ -71,8 +71,6 @@ #ifdef __KERNEL__ -extern char *mtrr_strings[MTRR_NUM_TYPES]; - /* The following functions are for use by other drivers */ # ifdef CONFIG_MTRR extern int mtrr_add (unsigned long base, unsigned long size, diff -Nru a/include/asm-x86_64/pci.h b/include/asm-x86_64/pci.h --- a/include/asm-x86_64/pci.h 2004-08-25 22:01:55 -07:00 +++ b/include/asm-x86_64/pci.h 2004-08-25 22:01:55 -07:00 @@ -44,81 +44,25 @@ #include #include -struct pci_dev; - extern int iommu_setup(char *opt); -extern dma_addr_t bad_dma_address; -#define pci_dma_mapping_error(x) ((x) == bad_dma_address) - -/* Allocate and map kernel buffer using consistent mode DMA for a device. - * hwdev should be valid struct pci_dev pointer for PCI devices, - * NULL for PCI-like buses (ISA, EISA). - * Returns non-NULL cpu-view pointer to the buffer if successful and - * sets *dma_addrp to the pci side dma address as well, else *dma_addrp - * is undefined. - */ -extern void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size, - dma_addr_t *dma_handle); - -/* Free and unmap a consistent DMA buffer. - * cpu_addr is what was returned from pci_alloc_consistent, - * size must be the same as what as passed into pci_alloc_consistent, - * and likewise dma_addr must be the same as what *dma_addrp was set to. - * - * References to the memory and mappings associated with cpu_addr/dma_addr - * past this call are illegal. - */ -extern void pci_free_consistent(struct pci_dev *hwdev, size_t size, - void *vaddr, dma_addr_t dma_handle); - -#ifdef CONFIG_SWIOTLB -extern int swiotlb; -extern dma_addr_t swiotlb_map_single (struct device *hwdev, void *ptr, size_t size, - int dir); -extern void swiotlb_unmap_single (struct device *hwdev, dma_addr_t dev_addr, - size_t size, int dir); -extern void swiotlb_sync_single_for_cpu (struct device *hwdev, - dma_addr_t dev_addr, - size_t size, int dir); -extern void swiotlb_sync_single_for_device (struct device *hwdev, - dma_addr_t dev_addr, - size_t size, int dir); -extern void swiotlb_sync_sg_for_cpu (struct device *hwdev, - struct scatterlist *sg, int nelems, - int dir); -extern void swiotlb_sync_sg_for_device (struct device *hwdev, - struct scatterlist *sg, int nelems, - int dir); -extern int swiotlb_map_sg(struct device *hwdev, struct scatterlist *sg, - int nents, int direction); -extern void swiotlb_unmap_sg(struct device *hwdev, struct scatterlist *sg, - int nents, int direction); - -#endif - #ifdef CONFIG_GART_IOMMU - -/* Map a single buffer of the indicated size for DMA in streaming mode. - * The 32-bit bus address to use is returned. +/* The PCI address space does equal the physical memory + * address space. The networking and block device layers use + * this boolean for bounce buffer decisions * - * Once the device is given the dma address, the device owns this memory - * until either pci_unmap_single or pci_dma_sync_single_for_cpu is performed. + * On AMD64 it mostly equals, but we set it to zero to tell some subsystems + * that an IOMMU is available. */ -extern dma_addr_t pci_map_single(struct pci_dev *hwdev, void *ptr, size_t size, - int direction); - - -void pci_unmap_single(struct pci_dev *hwdev, dma_addr_t addr, - size_t size, int direction); +#define PCI_DMA_BUS_IS_PHYS (no_iommu ? 1 : 0) /* - * pci_{map,unmap}_single_page maps a kernel page to a dma_addr_t. identical - * to pci_map_single, but takes a struct page instead of a virtual address + * x86-64 always supports DAC, but sometimes it is useful to force + * devices through the IOMMU to get automatic sg list merging. + * Optional right now. */ - -#define pci_map_page(dev,page,offset,size,dir) \ - pci_map_single((dev), page_address(page)+(offset), (size), (dir)) +extern int iommu_sac_force; +#define pci_dac_dma_supported(pci_dev, mask) (!iommu_sac_force) #define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME) \ dma_addr_t ADDR_NAME; @@ -133,113 +77,12 @@ #define pci_unmap_len_set(PTR, LEN_NAME, VAL) \ (((PTR)->LEN_NAME) = (VAL)) -static inline void pci_dma_sync_single_for_cpu(struct pci_dev *hwdev, - dma_addr_t dma_handle, - size_t size, int direction) -{ - BUG_ON(direction == PCI_DMA_NONE); - -#ifdef CONFIG_SWIOTLB - if (swiotlb) - return swiotlb_sync_single_for_cpu(&hwdev->dev,dma_handle,size,direction); -#endif - - flush_write_buffers(); -} - -static inline void pci_dma_sync_single_for_device(struct pci_dev *hwdev, - dma_addr_t dma_handle, - size_t size, int direction) -{ - BUG_ON(direction == PCI_DMA_NONE); - -#ifdef CONFIG_SWIOTLB - if (swiotlb) - return swiotlb_sync_single_for_device(&hwdev->dev,dma_handle,size,direction); -#endif - - flush_write_buffers(); -} - -static inline void pci_dma_sync_sg_for_cpu(struct pci_dev *hwdev, - struct scatterlist *sg, - int nelems, int direction) -{ - BUG_ON(direction == PCI_DMA_NONE); - -#ifdef CONFIG_SWIOTLB - if (swiotlb) - return swiotlb_sync_sg_for_cpu(&hwdev->dev,sg,nelems,direction); -#endif - flush_write_buffers(); -} - -static inline void pci_dma_sync_sg_for_device(struct pci_dev *hwdev, - struct scatterlist *sg, - int nelems, int direction) -{ - BUG_ON(direction == PCI_DMA_NONE); - -#ifdef CONFIG_SWIOTLB - if (swiotlb) - return swiotlb_sync_sg_for_device(&hwdev->dev,sg,nelems,direction); -#endif - flush_write_buffers(); -} - -/* The PCI address space does equal the physical memory - * address space. The networking and block device layers use - * this boolean for bounce buffer decisions - * - * On AMD64 it mostly equals, but we set it to zero to tell some subsystems - * that an IOMMU is available. - */ -#define PCI_DMA_BUS_IS_PHYS (no_iommu ? 1 : 0) - -/* We lie slightly when the IOMMU is forced to get the device to - use SAC instead of DAC. */ -#define pci_dac_dma_supported(pci_dev, mask) (force_iommu ? 0 : 1) - #else -static inline dma_addr_t pci_map_single(struct pci_dev *hwdev, void *ptr, - size_t size, int direction) -{ - dma_addr_t addr; +/* No IOMMU */ - if (direction == PCI_DMA_NONE) - out_of_line_bug(); - addr = virt_to_bus(ptr); - - /* - * This is gross, but what should I do. - * Unfortunately drivers do not test the return value of this. - */ - if ((addr+size) & ~hwdev->dma_mask) - out_of_line_bug(); - return addr; -} - -static inline void pci_unmap_single(struct pci_dev *hwdev, dma_addr_t dma_addr, - size_t size, int direction) -{ - if (direction == PCI_DMA_NONE) - out_of_line_bug(); - /* Nothing to do */ -} - -static inline dma_addr_t pci_map_page(struct pci_dev *hwdev, struct page *page, - unsigned long offset, size_t size, int direction) -{ - dma_addr_t addr; - if (direction == PCI_DMA_NONE) - out_of_line_bug(); - addr = page_to_pfn(page) * PAGE_SIZE + offset; - if ((addr+size) & ~hwdev->dma_mask) - out_of_line_bug(); - return addr; -} +#define PCI_DMA_BUS_IS_PHYS 1 +#define pci_dac_dma_supported(pci_dev, mask) 1 -/* pci_unmap_{page,single} is a nop so... */ #define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME) #define DECLARE_PCI_UNMAP_LEN(LEN_NAME) #define pci_unmap_addr(PTR, ADDR_NAME) (0) @@ -247,74 +90,9 @@ #define pci_unmap_len(PTR, LEN_NAME) (0) #define pci_unmap_len_set(PTR, LEN_NAME, VAL) do { } while (0) -/* Make physical memory consistent for a single - * streaming mode DMA translation after a transfer. - * - * If you perform a pci_map_single() but wish to interrogate the - * buffer using the cpu, yet do not wish to teardown the PCI dma - * mapping, you must call this function before doing so. At the - * next point you give the PCI dma address back to the card, you - * must first perform a pci_dma_sync_for_device, and then the - * device again owns the buffer. - */ -static inline void pci_dma_sync_single_for_cpu(struct pci_dev *hwdev, - dma_addr_t dma_handle, - size_t size, int direction) -{ - if (direction == PCI_DMA_NONE) - out_of_line_bug(); -} - -static inline void pci_dma_sync_single_for_device(struct pci_dev *hwdev, - dma_addr_t dma_handle, - size_t size, int direction) -{ - if (direction == PCI_DMA_NONE) - out_of_line_bug(); - flush_write_buffers(); -} - -/* Make physical memory consistent for a set of streaming - * mode DMA translations after a transfer. - * - * The same as pci_dma_sync_single_* but for a scatter-gather list, - * same rules and usage. - */ -static inline void pci_dma_sync_sg_for_cpu(struct pci_dev *hwdev, - struct scatterlist *sg, - int nelems, int direction) -{ - if (direction == PCI_DMA_NONE) - out_of_line_bug(); -} - -static inline void pci_dma_sync_sg_for_device(struct pci_dev *hwdev, - struct scatterlist *sg, - int nelems, int direction) -{ - if (direction == PCI_DMA_NONE) - out_of_line_bug(); - flush_write_buffers(); -} - -#define PCI_DMA_BUS_IS_PHYS 1 - -#define pci_dac_dma_supported(pci_dev, mask) 1 #endif -extern int pci_map_sg(struct pci_dev *hwdev, struct scatterlist *sg, - int nents, int direction); -extern void pci_unmap_sg(struct pci_dev *hwdev, struct scatterlist *sg, - int nents, int direction); - -#define pci_unmap_page pci_unmap_single - -/* Return whether the given PCI device DMA address mask can - * be supported properly. For example, if your device can - * only drive the low 24-bits during PCI bus mastering, then - * you would pass 0x00ffffff as the mask to this function. - */ -extern int pci_dma_supported(struct pci_dev *hwdev, u64 mask); +#include static inline dma64_addr_t pci_dac_page_to_dma(struct pci_dev *pdev, struct page *page, unsigned long offset, int direction) @@ -359,7 +137,6 @@ /* generic pci stuff */ #ifdef CONFIG_PCI #include -#include #endif #endif /* __x8664_PCI_H */ diff -Nru a/include/asm-x86_64/processor.h b/include/asm-x86_64/processor.h --- a/include/asm-x86_64/processor.h 2004-08-25 22:01:56 -07:00 +++ b/include/asm-x86_64/processor.h 2004-08-25 22:01:56 -07:00 @@ -456,9 +456,4 @@ #define cache_line_size() (boot_cpu_data.x86_cache_alignment) -#ifdef CONFIG_SCHED_SMT -#define ARCH_HAS_SCHED_DOMAIN -#define ARCH_HAS_SCHED_WAKE_IDLE -#endif - #endif /* __ASM_X86_64_PROCESSOR_H */ diff -Nru a/include/asm-x86_64/proto.h b/include/asm-x86_64/proto.h --- a/include/asm-x86_64/proto.h 2004-08-25 22:01:56 -07:00 +++ b/include/asm-x86_64/proto.h 2004-08-25 22:01:56 -07:00 @@ -82,7 +82,6 @@ extern void select_idle_routine(const struct cpuinfo_x86 *c); extern void swiotlb_init(void); -extern int swiotlb; extern unsigned long max_mapnr; extern unsigned long end_pfn; @@ -103,6 +102,8 @@ extern int iommu_aperture; extern int iommu_aperture_disabled; extern int iommu_aperture_allowed; +extern int fix_aperture; +extern int force_iommu; extern void smp_local_timer_interrupt(struct pt_regs * regs); diff -Nru a/include/asm-x86_64/swiotlb.h b/include/asm-x86_64/swiotlb.h --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/include/asm-x86_64/swiotlb.h 2004-08-25 22:01:56 -07:00 @@ -0,0 +1,36 @@ +#ifndef _ASM_SWIOTLB_H +#define _ASM_SWTIOLB_H 1 + +#include + +/* SWIOTLB interface */ + +extern dma_addr_t swiotlb_map_single(struct device *hwdev, void *ptr, size_t size, + int dir); +extern void swiotlb_unmap_single(struct device *hwdev, dma_addr_t dev_addr, + size_t size, int dir); +extern void swiotlb_sync_single_for_cpu(struct device *hwdev, + dma_addr_t dev_addr, + size_t size, int dir); +extern void swiotlb_sync_single_for_device(struct device *hwdev, + dma_addr_t dev_addr, + size_t size, int dir); +extern void swiotlb_sync_sg_for_cpu(struct device *hwdev, + struct scatterlist *sg, int nelems, + int dir); +extern void swiotlb_sync_sg_for_device(struct device *hwdev, + struct scatterlist *sg, int nelems, + int dir); +extern int swiotlb_map_sg(struct device *hwdev, struct scatterlist *sg, + int nents, int direction); +extern void swiotlb_unmap_sg(struct device *hwdev, struct scatterlist *sg, + int nents, int direction); +extern int swiotlb_dma_mapping_error(dma_addr_t dma_addr); + +#ifdef CONFIG_SWIOTLB +extern int swiotlb; +#else +#define swiotlb 0 +#endif + +#endif diff -Nru a/include/asm-x86_64/system.h b/include/asm-x86_64/system.h --- a/include/asm-x86_64/system.h 2004-08-25 22:01:56 -07:00 +++ b/include/asm-x86_64/system.h 2004-08-25 22:01:56 -07:00 @@ -297,11 +297,11 @@ #define mb() asm volatile("mfence":::"memory") #define rmb() asm volatile("lfence":::"memory") -/* could use SFENCE here, but it would be only needed for unordered SSE - store instructions and we always do an explicit sfence with them currently. - the ordering of normal stores is serialized enough. Just make it a compile - barrier. */ +#ifdef CONFIG_UNORDERED_IO +#define wmb() asm volatile("sfence" ::: "memory") +#else #define wmb() asm volatile("" ::: "memory") +#endif #define read_barrier_depends() do {} while(0) #define set_mb(var, value) do { xchg(&var, value); } while (0) #define set_wmb(var, value) do { var = value; wmb(); } while (0) diff -Nru a/include/asm-x86_64/topology.h b/include/asm-x86_64/topology.h --- a/include/asm-x86_64/topology.h 2004-08-25 22:01:55 -07:00 +++ b/include/asm-x86_64/topology.h 2004-08-25 22:01:55 -07:00 @@ -14,18 +14,23 @@ extern unsigned char cpu_to_node[]; extern cpumask_t node_to_cpumask[]; +extern cpumask_t pci_bus_to_cpumask[]; #define cpu_to_node(cpu) (cpu_to_node[cpu]) #define parent_node(node) (node) #define node_to_first_cpu(node) (__ffs(node_to_cpumask[node])) #define node_to_cpumask(node) (node_to_cpumask[node]) -static inline cpumask_t pcibus_to_cpumask(int bus) +static inline cpumask_t __pcibus_to_cpumask(int bus) { + cpumask_t busmask = pci_bus_to_cpumask[bus]; + cpumask_t online = cpu_online_map; cpumask_t res; - cpus_and(res, pci_bus_to_cpumask[bus], cpu_online_map); + cpus_and(res, busmask, online); return res; } +/* broken generic file uses #ifndef later on this */ +#define pcibus_to_cpumask(bus) __pcibus_to_cpumask(bus) #define NODE_BALANCE_RATE 30 /* CHECKME */ diff -Nru a/include/linux/adfs_fs_i.h b/include/linux/adfs_fs_i.h --- a/include/linux/adfs_fs_i.h 2004-08-25 22:01:55 -07:00 +++ b/include/linux/adfs_fs_i.h 2004-08-25 22:01:55 -07:00 @@ -17,7 +17,7 @@ __u32 execaddr; /* RISC OS exec address */ unsigned int filetype; /* RISC OS file type */ unsigned int attr; /* RISC OS permissions */ - int stamped:1; /* RISC OS file has date/time */ + unsigned int stamped:1; /* RISC OS file has date/time */ struct inode vfs_inode; }; diff -Nru a/include/linux/aio.h b/include/linux/aio.h --- a/include/linux/aio.h 2004-08-25 22:01:56 -07:00 +++ b/include/linux/aio.h 2004-08-25 22:01:56 -07:00 @@ -52,7 +52,7 @@ struct file *ki_filp; struct kioctx *ki_ctx; /* may be NULL for sync ops */ int (*ki_cancel)(struct kiocb *, struct io_event *); - long (*ki_retry)(struct kiocb *); + ssize_t (*ki_retry)(struct kiocb *); void (*ki_dtor)(struct kiocb *); struct list_head ki_list; /* the aio core uses this @@ -64,6 +64,16 @@ } ki_obj; __u64 ki_user_data; /* user's data for completion */ loff_t ki_pos; + /* State that we remember to be able to restart/retry */ + unsigned short ki_opcode; + size_t ki_nbytes; /* copy of iocb->aio_nbytes */ + char __user *ki_buf; /* remaining iocb->aio_buf */ + size_t ki_left; /* remaining bytes */ + wait_queue_t ki_wait; + long ki_retried; /* just for testing */ + long ki_kicked; /* just for testing */ + long ki_queued; /* just for testing */ + void *private; }; @@ -79,6 +89,8 @@ (x)->ki_cancel = NULL; \ (x)->ki_dtor = NULL; \ (x)->ki_obj.tsk = tsk; \ + (x)->ki_user_data = 0; \ + init_wait((&(x)->ki_wait)); \ } while (0) #define AIO_RING_MAGIC 0xa10a10a1 @@ -160,6 +172,20 @@ #define get_ioctx(kioctx) do { if (unlikely(atomic_read(&(kioctx)->users) <= 0)) BUG(); atomic_inc(&(kioctx)->users); } while (0) #define put_ioctx(kioctx) do { if (unlikely(atomic_dec_and_test(&(kioctx)->users))) __put_ioctx(kioctx); else if (unlikely(atomic_read(&(kioctx)->users) < 0)) BUG(); } while (0) + +#define in_aio() !is_sync_wait(current->io_wait) +/* may be used for debugging */ +#define warn_if_async() \ +do { \ + if (in_aio()) { \ + printk(KERN_ERR "%s(%s:%d) called in async context!\n", \ + __FUNCTION__, __FILE__, __LINE__); \ + dump_stack(); \ + } \ +} while (0) + +#define io_wait_to_kiocb(wait) container_of(wait, struct kiocb, ki_wait) +#define is_retried_kiocb(iocb) ((iocb)->ki_retried > 1) #include diff -Nru a/include/linux/buffer_head.h b/include/linux/buffer_head.h --- a/include/linux/buffer_head.h 2004-08-25 22:01:54 -07:00 +++ b/include/linux/buffer_head.h 2004-08-25 22:01:54 -07:00 @@ -49,12 +49,12 @@ struct buffer_head { /* First cache line: */ unsigned long b_state; /* buffer state bitmap (see above) */ - atomic_t b_count; /* users using this block */ struct buffer_head *b_this_page;/* circular list of page's buffers */ struct page *b_page; /* the page this bh is mapped to */ + atomic_t b_count; /* users using this block */ + u32 b_size; /* block size */ sector_t b_blocknr; /* block number */ - u32 b_size; /* block size */ char *b_data; /* pointer to data block */ struct block_device *b_bdev; diff -Nru a/include/linux/cpumask.h b/include/linux/cpumask.h --- a/include/linux/cpumask.h 2004-08-25 22:01:55 -07:00 +++ b/include/linux/cpumask.h 2004-08-25 22:01:55 -07:00 @@ -73,6 +73,7 @@ * inside a macro, the way we do the other calls. */ +#include #include #include #include @@ -207,13 +208,13 @@ #define first_cpu(src) __first_cpu(&(src), NR_CPUS) static inline int __first_cpu(const cpumask_t *srcp, int nbits) { - return find_first_bit(srcp->bits, nbits); + return min_t(int, nbits, find_first_bit(srcp->bits, nbits)); } #define next_cpu(n, src) __next_cpu((n), &(src), NR_CPUS) static inline int __next_cpu(int n, const cpumask_t *srcp, int nbits) { - return find_next_bit(srcp->bits, nbits, n+1); + return min_t(int, nbits, find_next_bit(srcp->bits, nbits, n+1)); } #define cpumask_of_cpu(cpu) \ diff -Nru a/include/linux/dcache.h b/include/linux/dcache.h --- a/include/linux/dcache.h 2004-08-25 22:01:56 -07:00 +++ b/include/linux/dcache.h 2004-08-25 22:01:56 -07:00 @@ -33,8 +33,8 @@ */ struct qstr { unsigned int hash; - const unsigned char *name; unsigned int len; + const unsigned char *name; }; struct dentry_stat_t { @@ -101,11 +101,11 @@ unsigned long d_time; /* used by d_revalidate */ struct dentry_operations *d_op; struct super_block *d_sb; /* The root of the dentry tree */ - int d_mounted; void *d_fsdata; /* fs-specific data */ struct rcu_head d_rcu; struct dcookie_struct *d_cookie; /* cookie, if any */ struct hlist_node d_hash; /* lookup hash list */ + int d_mounted; unsigned char d_iname[DNAME_INLINE_LEN_MIN]; /* small names */ }; diff -Nru a/include/linux/device.h b/include/linux/device.h --- a/include/linux/device.h 2004-08-25 22:01:56 -07:00 +++ b/include/linux/device.h 2004-08-25 22:01:56 -07:00 @@ -59,7 +59,6 @@ struct driver_attribute * drv_attrs; int (*match)(struct device * dev, struct device_driver * drv); - struct device * (*add) (struct device * parent, char * bus_id); int (*hotplug) (struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size); int (*suspend)(struct device * dev, u32 state); diff -Nru a/include/linux/errno.h b/include/linux/errno.h --- a/include/linux/errno.h 2004-08-25 22:01:56 -07:00 +++ b/include/linux/errno.h 2004-08-25 22:01:56 -07:00 @@ -22,6 +22,7 @@ #define EBADTYPE 527 /* Type not supported by server */ #define EJUKEBOX 528 /* Request initiated, but will not complete before timeout */ #define EIOCBQUEUED 529 /* iocb queued, will get completion event */ +#define EIOCBRETRY 530 /* iocb queued, will trigger a retry */ #endif diff -Nru a/include/linux/fs.h b/include/linux/fs.h --- a/include/linux/fs.h 2004-08-25 22:01:54 -07:00 +++ b/include/linux/fs.h 2004-08-25 22:01:54 -07:00 @@ -1571,6 +1571,39 @@ /* kernel/fork.c */ extern int unshare_files(void); +/* Transaction based IO helpers */ + +/* + * An argresp is stored in an allocated page and holds the + * size of the argument or response, along with its content + */ +struct simple_transaction_argresp { + ssize_t size; + char data[0]; +}; + +#define SIMPLE_TRANSACTION_LIMIT (PAGE_SIZE - sizeof(struct simple_transaction_argresp)) + +char *simple_transaction_get(struct file *file, const char __user *buf, + size_t size); +ssize_t simple_transaction_read(struct file *file, char __user *buf, + size_t size, loff_t *pos); +int simple_transaction_release(struct inode *inode, struct file *file); + +static inline void simple_transaction_set(struct file *file, size_t n) +{ + struct simple_transaction_argresp *ar = file->private_data; + + BUG_ON(n > SIMPLE_TRANSACTION_LIMIT); + + /* + * The barrier ensures that ar->size will really remain zero until + * ar->data is ready for reading. + */ + smp_mb(); + ar->size = n; +} + #ifdef CONFIG_SECURITY static inline char *alloc_secdata(void) { diff -Nru a/include/linux/genhd.h b/include/linux/genhd.h --- a/include/linux/genhd.h 2004-08-25 22:01:54 -07:00 +++ b/include/linux/genhd.h 2004-08-25 22:01:54 -07:00 @@ -100,7 +100,7 @@ struct timer_rand_state *random; int policy; - unsigned sync_io; /* RAID */ + atomic_t sync_io; /* RAID */ unsigned long stamp, stamp_idle; int in_flight; #ifdef CONFIG_SMP diff -Nru a/include/linux/gfp.h b/include/linux/gfp.h --- a/include/linux/gfp.h 2004-08-25 22:01:54 -07:00 +++ b/include/linux/gfp.h 2004-08-25 22:01:54 -07:00 @@ -73,6 +73,11 @@ * For the normal case of non-DISCONTIGMEM systems the NODE_DATA() gets * optimized to &contig_page_data at compile-time. */ + +#ifndef HAVE_ARCH_FREE_PAGE +static inline void arch_free_page(struct page *page, int order) { } +#endif + extern struct page * FASTCALL(__alloc_pages(unsigned int, unsigned int, struct zonelist *)); diff -Nru a/include/linux/ghash.h b/include/linux/ghash.h --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/include/linux/ghash.h 2004-08-25 22:01:56 -07:00 @@ -0,0 +1,236 @@ +/* + * include/linux/ghash.h -- generic hashing with fuzzy retrieval + * + * (C) 1997 Thomas Schoebel-Theuer + * + * The algorithms implemented here seem to be a completely new invention, + * and I'll publish the fundamentals in a paper. + */ + +#ifndef _GHASH_H +#define _GHASH_H +/* HASHSIZE _must_ be a power of two!!! */ + + +#define DEF_HASH_FUZZY_STRUCTS(NAME,HASHSIZE,TYPE) \ +\ +struct NAME##_table {\ + TYPE * hashtable[HASHSIZE];\ + TYPE * sorted_list;\ + int nr_entries;\ +};\ +\ +struct NAME##_ptrs {\ + TYPE * next_hash;\ + TYPE * prev_hash;\ + TYPE * next_sorted;\ + TYPE * prev_sorted;\ +}; + +#define DEF_HASH_FUZZY(LINKAGE,NAME,HASHSIZE,TYPE,PTRS,KEYTYPE,KEY,KEYCMP,KEYEQ,HASHFN)\ +\ +LINKAGE void insert_##NAME##_hash(struct NAME##_table * tbl, TYPE * elem)\ +{\ + int ix = HASHFN(elem->KEY);\ + TYPE ** base = &tbl->hashtable[ix];\ + TYPE * ptr = *base;\ + TYPE * prev = NULL;\ +\ + tbl->nr_entries++;\ + while(ptr && KEYCMP(ptr->KEY, elem->KEY)) {\ + base = &ptr->PTRS.next_hash;\ + prev = ptr;\ + ptr = *base;\ + }\ + elem->PTRS.next_hash = ptr;\ + elem->PTRS.prev_hash = prev;\ + if(ptr) {\ + ptr->PTRS.prev_hash = elem;\ + }\ + *base = elem;\ +\ + ptr = prev;\ + if(!ptr) {\ + ptr = tbl->sorted_list;\ + prev = NULL;\ + } else {\ + prev = ptr->PTRS.prev_sorted;\ + }\ + while(ptr) {\ + TYPE * next = ptr->PTRS.next_hash;\ + if(next && KEYCMP(next->KEY, elem->KEY)) {\ + prev = ptr;\ + ptr = next;\ + } else if(KEYCMP(ptr->KEY, elem->KEY)) {\ + prev = ptr;\ + ptr = ptr->PTRS.next_sorted;\ + } else\ + break;\ + }\ + elem->PTRS.next_sorted = ptr;\ + elem->PTRS.prev_sorted = prev;\ + if(ptr) {\ + ptr->PTRS.prev_sorted = elem;\ + }\ + if(prev) {\ + prev->PTRS.next_sorted = elem;\ + } else {\ + tbl->sorted_list = elem;\ + }\ +}\ +\ +LINKAGE void remove_##NAME##_hash(struct NAME##_table * tbl, TYPE * elem)\ +{\ + TYPE * next = elem->PTRS.next_hash;\ + TYPE * prev = elem->PTRS.prev_hash;\ +\ + tbl->nr_entries--;\ + if(next)\ + next->PTRS.prev_hash = prev;\ + if(prev)\ + prev->PTRS.next_hash = next;\ + else {\ + int ix = HASHFN(elem->KEY);\ + tbl->hashtable[ix] = next;\ + }\ +\ + next = elem->PTRS.next_sorted;\ + prev = elem->PTRS.prev_sorted;\ + if(next)\ + next->PTRS.prev_sorted = prev;\ + if(prev)\ + prev->PTRS.next_sorted = next;\ + else\ + tbl->sorted_list = next;\ +}\ +\ +LINKAGE TYPE * find_##NAME##_hash(struct NAME##_table * tbl, KEYTYPE pos)\ +{\ + int ix = hashfn(pos);\ + TYPE * ptr = tbl->hashtable[ix];\ + while(ptr && KEYCMP(ptr->KEY, pos))\ + ptr = ptr->PTRS.next_hash;\ + if(ptr && !KEYEQ(ptr->KEY, pos))\ + ptr = NULL;\ + return ptr;\ +}\ +\ +LINKAGE TYPE * find_##NAME##_hash_fuzzy(struct NAME##_table * tbl, KEYTYPE pos)\ +{\ + int ix;\ + int offset;\ + TYPE * ptr;\ + TYPE * next;\ +\ + ptr = tbl->sorted_list;\ + if(!ptr || KEYCMP(pos, ptr->KEY))\ + return NULL;\ + ix = HASHFN(pos);\ + offset = HASHSIZE;\ + do {\ + offset >>= 1;\ + next = tbl->hashtable[(ix+offset) & ((HASHSIZE)-1)];\ + if(next && (KEYCMP(next->KEY, pos) || KEYEQ(next->KEY, pos))\ + && KEYCMP(ptr->KEY, next->KEY))\ + ptr = next;\ + } while(offset);\ +\ + for(;;) {\ + next = ptr->PTRS.next_hash;\ + if(next) {\ + if(KEYCMP(next->KEY, pos)) {\ + ptr = next;\ + continue;\ + }\ + }\ + next = ptr->PTRS.next_sorted;\ + if(next && KEYCMP(next->KEY, pos)) {\ + ptr = next;\ + continue;\ + }\ + return ptr;\ + }\ + return NULL;\ +} + +/* LINKAGE - empty or "static", depending on whether you want the definitions to + * be public or not + * NAME - a string to stick in names to make this hash table type distinct from + * any others + * HASHSIZE - number of buckets + * TYPE - type of data contained in the buckets - must be a structure, one + * field is of type NAME_ptrs, another is the hash key + * PTRS - TYPE must contain a field of type NAME_ptrs, PTRS is the name of that + * field + * KEYTYPE - type of the key field within TYPE + * KEY - name of the key field within TYPE + * KEYCMP - pointer to function that compares KEYTYPEs to each other - the + * prototype is int KEYCMP(KEYTYPE, KEYTYPE), it returns zero for equal, + * non-zero for not equal + * HASHFN - the hash function - the prototype is int HASHFN(KEYTYPE), + * it returns a number in the range 0 ... HASHSIZE - 1 + * Call DEF_HASH_STRUCTS, define your hash table as a NAME_table, then call + * DEF_HASH. + */ + +#define DEF_HASH_STRUCTS(NAME,HASHSIZE,TYPE) \ +\ +struct NAME##_table {\ + TYPE * hashtable[HASHSIZE];\ + int nr_entries;\ +};\ +\ +struct NAME##_ptrs {\ + TYPE * next_hash;\ + TYPE * prev_hash;\ +}; + +#define DEF_HASH(LINKAGE,NAME,TYPE,PTRS,KEYTYPE,KEY,KEYCMP,HASHFN)\ +\ +LINKAGE void insert_##NAME##_hash(struct NAME##_table * tbl, TYPE * elem)\ +{\ + int ix = HASHFN(elem->KEY);\ + TYPE ** base = &tbl->hashtable[ix];\ + TYPE * ptr = *base;\ + TYPE * prev = NULL;\ +\ + tbl->nr_entries++;\ + while(ptr && KEYCMP(ptr->KEY, elem->KEY)) {\ + base = &ptr->PTRS.next_hash;\ + prev = ptr;\ + ptr = *base;\ + }\ + elem->PTRS.next_hash = ptr;\ + elem->PTRS.prev_hash = prev;\ + if(ptr) {\ + ptr->PTRS.prev_hash = elem;\ + }\ + *base = elem;\ +}\ +\ +LINKAGE void remove_##NAME##_hash(struct NAME##_table * tbl, TYPE * elem)\ +{\ + TYPE * next = elem->PTRS.next_hash;\ + TYPE * prev = elem->PTRS.prev_hash;\ +\ + tbl->nr_entries--;\ + if(next)\ + next->PTRS.prev_hash = prev;\ + if(prev)\ + prev->PTRS.next_hash = next;\ + else {\ + int ix = HASHFN(elem->KEY);\ + tbl->hashtable[ix] = next;\ + }\ +}\ +\ +LINKAGE TYPE * find_##NAME##_hash(struct NAME##_table * tbl, KEYTYPE pos)\ +{\ + int ix = HASHFN(pos);\ + TYPE * ptr = tbl->hashtable[ix];\ + while(ptr && KEYCMP(ptr->KEY, pos))\ + ptr = ptr->PTRS.next_hash;\ + return ptr;\ +} + +#endif diff -Nru a/include/linux/highuid.h b/include/linux/highuid.h --- a/include/linux/highuid.h 2004-08-25 22:01:55 -07:00 +++ b/include/linux/highuid.h 2004-08-25 22:01:55 -07:00 @@ -44,8 +44,8 @@ #ifdef CONFIG_UID16 /* prevent uid mod 65536 effect by returning a default value for high UIDs */ -#define high2lowuid(uid) ((uid) > 65535 ? (old_uid_t)overflowuid : (old_uid_t)(uid)) -#define high2lowgid(gid) ((gid) > 65535 ? (old_gid_t)overflowgid : (old_gid_t)(gid)) +#define high2lowuid(uid) ((uid) & ~0xFFFF ? (old_uid_t)overflowuid : (old_uid_t)(uid)) +#define high2lowgid(gid) ((gid) & ~0xFFFF ? (old_gid_t)overflowgid : (old_gid_t)(gid)) /* * -1 is different in 16 bits than it is in 32 bits * these macros are used by chown(), setreuid(), ..., @@ -89,8 +89,8 @@ * Since these macros are used in architectures that only need limited * 16-bit UID back compatibility, we won't use old_uid_t and old_gid_t */ -#define fs_high2lowuid(uid) ((uid) > 65535 ? (uid16_t)fs_overflowuid : (uid16_t)(uid)) -#define fs_high2lowgid(gid) ((gid) > 65535 ? (gid16_t)fs_overflowgid : (gid16_t)(gid)) +#define fs_high2lowuid(uid) ((uid) & ~0xFFFF ? (uid16_t)fs_overflowuid : (uid16_t)(uid)) +#define fs_high2lowgid(gid) ((gid) & ~0xFFFF ? (gid16_t)fs_overflowgid : (gid16_t)(gid)) #define low_16_bits(x) ((x) & 0xFFFF) #define high_16_bits(x) (((x) & 0xFFFF0000) >> 16) diff -Nru a/include/linux/if_bridge.h b/include/linux/if_bridge.h --- a/include/linux/if_bridge.h 2004-08-25 22:01:55 -07:00 +++ b/include/linux/if_bridge.h 2004-08-25 22:01:55 -07:00 @@ -105,7 +105,7 @@ #include extern void brioctl_set(int (*ioctl_hook)(unsigned int, void __user *)); -extern int (*br_handle_frame_hook)(struct sk_buff *skb); +extern int (*br_handle_frame_hook)(struct net_bridge_port *p, struct sk_buff **pskb); extern int (*br_should_route_hook)(struct sk_buff **pskb); #endif diff -Nru a/include/linux/kobject.h b/include/linux/kobject.h --- a/include/linux/kobject.h 2004-08-25 22:01:54 -07:00 +++ b/include/linux/kobject.h 2004-08-25 22:01:54 -07:00 @@ -19,6 +19,7 @@ #include #include #include +#include #include #define KOBJ_NAME_LEN 20 @@ -26,7 +27,7 @@ struct kobject { char * k_name; char name[KOBJ_NAME_LEN]; - atomic_t refcount; + struct kref kref; struct list_head entry; struct kobject * parent; struct kset * kset; @@ -57,6 +58,8 @@ extern void kobject_put(struct kobject *); extern void kobject_hotplug(const char *action, struct kobject *); + +extern char * kobject_get_path(struct kset *, struct kobject *, int); struct kobj_type { void (*release)(struct kobject *); diff -Nru a/include/linux/kref.h b/include/linux/kref.h --- a/include/linux/kref.h 2004-08-25 22:01:54 -07:00 +++ b/include/linux/kref.h 2004-08-25 22:01:54 -07:00 @@ -18,15 +18,12 @@ #include #include - struct kref { atomic_t refcount; - void (*release)(struct kref *kref); }; -void kref_init(struct kref *kref, void (*release)(struct kref *)); -struct kref *kref_get(struct kref *kref); -void kref_put(struct kref *kref); - +void kref_init(struct kref *kref); +void kref_get(struct kref *kref); +void kref_put(struct kref *kref, void (*release) (struct kref *kref)); #endif /* _KREF_H_ */ diff -Nru a/include/linux/mm.h b/include/linux/mm.h --- a/include/linux/mm.h 2004-08-25 22:01:54 -07:00 +++ b/include/linux/mm.h 2004-08-25 22:01:54 -07:00 @@ -26,6 +26,12 @@ extern unsigned long vmalloc_earlyreserve; extern int page_cluster; +#ifdef CONFIG_SYSCTL +extern int sysctl_legacy_va_layout; +#else +#define sysctl_legacy_va_layout 0 +#endif + #include #include #include @@ -195,21 +201,21 @@ page_flags_t flags; /* Atomic flags, some possibly * updated asynchronously */ atomic_t _count; /* Usage count, see below. */ - unsigned int mapcount; /* Count of ptes mapped in mms, + atomic_t _mapcount; /* Count of ptes mapped in mms, * to show when page is mapped - * & limit reverse map searches, - * protected by PG_maplock. + * & limit reverse map searches. */ unsigned long private; /* Mapping-private opaque data: * usually used for buffer_heads * if PagePrivate set; used for * swp_entry_t if PageSwapCache */ - struct address_space *mapping; /* If PG_anon clear, points to + struct address_space *mapping; /* If low bit clear, points to * inode address_space, or NULL. * If page mapped as anonymous - * memory, PG_anon is set, and - * it points to anon_vma object. + * memory, low bit is set, and + * it points to anon_vma object: + * see PAGE_MAPPING_ANON below. */ pgoff_t index; /* Our offset within mapping. */ struct list_head lru; /* Pageout list, eg. active_list @@ -433,24 +439,32 @@ /* * On an anonymous page mapped into a user virtual memory area, - * page->mapping points to its anon_vma, not to a struct address_space. + * page->mapping points to its anon_vma, not to a struct address_space; + * with the PAGE_MAPPING_ANON bit set to distinguish it. * * Please note that, confusingly, "page_mapping" refers to the inode * address_space which maps the page from disk; whereas "page_mapped" * refers to user virtual address space into which the page is mapped. */ +#define PAGE_MAPPING_ANON 1 + extern struct address_space swapper_space; static inline struct address_space *page_mapping(struct page *page) { - struct address_space *mapping = NULL; + struct address_space *mapping = page->mapping; if (unlikely(PageSwapCache(page))) mapping = &swapper_space; - else if (likely(!PageAnon(page))) - mapping = page->mapping; + else if (unlikely((unsigned long)mapping & PAGE_MAPPING_ANON)) + mapping = NULL; return mapping; } +static inline int PageAnon(struct page *page) +{ + return ((unsigned long)page->mapping & PAGE_MAPPING_ANON) != 0; +} + /* * Return the pagecache index of the passed page. Regular pagecache pages * use ->index whereas swapcache pages use ->private @@ -463,11 +477,26 @@ } /* + * The atomic page->_mapcount, like _count, starts from -1: + * so that transitions both from it and to it can be tracked, + * using atomic_inc_and_test and atomic_add_negative(-1). + */ +static inline void reset_page_mapcount(struct page *page) +{ + atomic_set(&(page)->_mapcount, -1); +} + +static inline int page_mapcount(struct page *page) +{ + return atomic_read(&(page)->_mapcount) + 1; +} + +/* * Return true if this page is mapped into pagetables. */ static inline int page_mapped(struct page *page) { - return page->mapcount != 0; + return atomic_read(&(page)->_mapcount) >= 0; } /* @@ -599,11 +628,10 @@ } extern void free_area_init(unsigned long * zones_size); -extern void free_area_init_node(int nid, pg_data_t *pgdat, struct page *pmap, +extern void free_area_init_node(int nid, pg_data_t *pgdat, unsigned long * zones_size, unsigned long zone_start_pfn, unsigned long *zholes_size); -extern void memmap_init_zone(struct page *, unsigned long, int, - unsigned long, unsigned long); +extern void memmap_init_zone(unsigned long, int, unsigned long, unsigned long); extern void mem_init(void); extern void show_mem(void); extern void si_meminfo(struct sysinfo * val); diff -Nru a/include/linux/mmzone.h b/include/linux/mmzone.h --- a/include/linux/mmzone.h 2004-08-25 22:01:55 -07:00 +++ b/include/linux/mmzone.h 2004-08-25 22:01:55 -07:00 @@ -272,6 +272,8 @@ extern int numnodes; extern struct pglist_data *pgdat_list; +void __get_zone_counts(unsigned long *active, unsigned long *inactive, + unsigned long *free, struct pglist_data *pgdat); void get_zone_counts(unsigned long *active, unsigned long *inactive, unsigned long *free); void build_all_zonelists(void); diff -Nru a/include/linux/netfilter_ipv4/ip_nat_helper.h b/include/linux/netfilter_ipv4/ip_nat_helper.h --- a/include/linux/netfilter_ipv4/ip_nat_helper.h 2004-08-25 22:01:54 -07:00 +++ b/include/linux/netfilter_ipv4/ip_nat_helper.h 2004-08-25 22:01:54 -07:00 @@ -44,6 +44,9 @@ extern struct ip_nat_helper * ip_nat_find_helper(const struct ip_conntrack_tuple *tuple); +extern struct ip_nat_helper * +__ip_nat_find_helper(const struct ip_conntrack_tuple *tuple); + /* These return true or false. */ extern int ip_nat_mangle_tcp_packet(struct sk_buff **skb, struct ip_conntrack *ct, diff -Nru a/include/linux/node.h b/include/linux/node.h --- a/include/linux/node.h 2004-08-25 22:01:56 -07:00 +++ b/include/linux/node.h 2004-08-25 22:01:56 -07:00 @@ -23,7 +23,6 @@ #include struct node { - cpumask_t cpumap; /* Bitmap of CPUs on the Node */ struct sys_device sysdev; }; diff -Nru a/include/linux/page-flags.h b/include/linux/page-flags.h --- a/include/linux/page-flags.h 2004-08-25 22:01:55 -07:00 +++ b/include/linux/page-flags.h 2004-08-25 22:01:55 -07:00 @@ -69,14 +69,11 @@ #define PG_private 12 /* Has something at ->private */ #define PG_writeback 13 /* Page is under writeback */ #define PG_nosave 14 /* Used for system suspend/resume */ -#define PG_maplock 15 /* Lock bit for rmap to ptes */ +#define PG_compound 15 /* Part of a compound page */ #define PG_swapcache 16 /* Swap page: swp_entry_t in private */ #define PG_mappedtodisk 17 /* Has blocks allocated on-disk */ #define PG_reclaim 18 /* To be reclaimed asap */ -#define PG_compound 19 /* Part of a compound page */ - -#define PG_anon 20 /* Anonymous: anon_vma in mapping */ /* @@ -236,6 +233,7 @@ #define PageReserved(page) test_bit(PG_reserved, &(page)->flags) #define SetPageReserved(page) set_bit(PG_reserved, &(page)->flags) #define ClearPageReserved(page) clear_bit(PG_reserved, &(page)->flags) +#define __ClearPageReserved(page) __clear_bit(PG_reserved, &(page)->flags) #define SetPagePrivate(page) set_bit(PG_private, &(page)->flags) #define ClearPagePrivate(page) clear_bit(PG_private, &(page)->flags) @@ -291,10 +289,6 @@ #define PageCompound(page) test_bit(PG_compound, &(page)->flags) #define SetPageCompound(page) set_bit(PG_compound, &(page)->flags) #define ClearPageCompound(page) clear_bit(PG_compound, &(page)->flags) - -#define PageAnon(page) test_bit(PG_anon, &(page)->flags) -#define SetPageAnon(page) set_bit(PG_anon, &(page)->flags) -#define ClearPageAnon(page) clear_bit(PG_anon, &(page)->flags) #ifdef CONFIG_SWAP #define PageSwapCache(page) test_bit(PG_swapcache, &(page)->flags) diff -Nru a/include/linux/pci.h b/include/linux/pci.h --- a/include/linux/pci.h 2004-08-25 22:01:55 -07:00 +++ b/include/linux/pci.h 2004-08-25 22:01:55 -07:00 @@ -712,7 +712,7 @@ int pci_get_interrupt_pin(struct pci_dev *dev, struct pci_dev **bridge); extern struct pci_dev *pci_dev_get(struct pci_dev *dev); extern void pci_dev_put(struct pci_dev *dev); - +extern void pci_remove_bus(struct pci_bus *b); extern void pci_remove_bus_device(struct pci_dev *dev); /* Generic PCI functions exported to card drivers */ diff -Nru a/include/linux/personality.h b/include/linux/personality.h --- a/include/linux/personality.h 2004-08-25 22:01:55 -07:00 +++ b/include/linux/personality.h 2004-08-25 22:01:55 -07:00 @@ -30,6 +30,7 @@ */ enum { MMAP_PAGE_ZERO = 0x0100000, + ADDR_COMPAT_LAYOUT = 0x0200000, READ_IMPLIES_EXEC = 0x0400000, ADDR_LIMIT_32BIT = 0x0800000, SHORT_INODE = 0x1000000, diff -Nru a/include/linux/raid/md.h b/include/linux/raid/md.h --- a/include/linux/raid/md.h 2004-08-25 22:01:54 -07:00 +++ b/include/linux/raid/md.h 2004-08-25 22:01:54 -07:00 @@ -74,7 +74,6 @@ extern void md_write_end(mddev_t *mddev); extern void md_handle_safemode(mddev_t *mddev); extern void md_done_sync(mddev_t *mddev, int blocks, int ok); -extern void md_sync_acct(mdk_rdev_t *rdev, unsigned long nr_sectors); extern void md_error (mddev_t *mddev, mdk_rdev_t *rdev); extern void md_unplug_mddev(mddev_t *mddev); diff -Nru a/include/linux/raid/md_k.h b/include/linux/raid/md_k.h --- a/include/linux/raid/md_k.h 2004-08-25 22:01:54 -07:00 +++ b/include/linux/raid/md_k.h 2004-08-25 22:01:54 -07:00 @@ -24,7 +24,8 @@ #define HSM 6UL #define MULTIPATH 7UL #define RAID6 8UL -#define MAX_PERSONALITY 9UL +#define RAID10 9UL +#define MAX_PERSONALITY 10UL #define LEVEL_MULTIPATH (-4) #define LEVEL_LINEAR (-1) @@ -43,6 +44,7 @@ case RAID1: return 1; case RAID5: return 5; case RAID6: return 6; + case RAID10: return 10; } BUG(); return MD_RESERVED; @@ -60,6 +62,7 @@ case 4: case 5: return RAID5; case 6: return RAID6; + case 10: return RAID10; } return MD_RESERVED; } @@ -216,6 +219,7 @@ unsigned long resync_mark; /* a recent timestamp */ sector_t resync_mark_cnt;/* blocks written at resync_mark */ + sector_t resync_max_sectors; /* may be set by personality */ /* recovery/resync flags * NEEDED: we might need to start a resync/recover * RUNNING: a thread is running, or about to be started @@ -261,6 +265,11 @@ int faulty = rdev->faulty; if (atomic_dec_and_test(&rdev->nr_pending) && faulty) set_bit(MD_RECOVERY_NEEDED, &mddev->recovery); +} + +static inline void md_sync_acct(struct block_device *bdev, unsigned long nr_sectors) +{ + atomic_add(nr_sectors, &bdev->bd_contains->bd_disk->sync_io); } struct mdk_personality_s diff -Nru a/include/linux/raid/raid10.h b/include/linux/raid/raid10.h --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/include/linux/raid/raid10.h 2004-08-25 22:01:56 -07:00 @@ -0,0 +1,103 @@ +#ifndef _RAID10_H +#define _RAID10_H + +#include + +typedef struct mirror_info mirror_info_t; + +struct mirror_info { + mdk_rdev_t *rdev; + sector_t head_position; +}; + +typedef struct r10bio_s r10bio_t; + +struct r10_private_data_s { + mddev_t *mddev; + mirror_info_t *mirrors; + int raid_disks; + int working_disks; + spinlock_t device_lock; + + /* geometry */ + int near_copies; /* number of copies layed out raid0 style */ + int far_copies; /* number of copies layed out + * at large strides across drives + */ + int copies; /* near_copies * far_copies. + * must be <= raid_disks + */ + sector_t stride; /* distance between far copies. + * This is size / far_copies + */ + + int chunk_shift; /* shift from chunks to sectors */ + sector_t chunk_mask; + + struct list_head retry_list; + /* for use when syncing mirrors: */ + + spinlock_t resync_lock; + int nr_pending; + int barrier; + sector_t next_resync; + + wait_queue_head_t wait_idle; + wait_queue_head_t wait_resume; + + mempool_t *r10bio_pool; + mempool_t *r10buf_pool; +}; + +typedef struct r10_private_data_s conf_t; + +/* + * this is the only point in the RAID code where we violate + * C type safety. mddev->private is an 'opaque' pointer. + */ +#define mddev_to_conf(mddev) ((conf_t *) mddev->private) + +/* + * this is our 'private' RAID10 bio. + * + * it contains information about what kind of IO operations were started + * for this RAID10 operation, and about their status: + */ + +struct r10bio_s { + atomic_t remaining; /* 'have we finished' count, + * used from IRQ handlers + */ + sector_t sector; /* virtual sector number */ + int sectors; + unsigned long state; + mddev_t *mddev; + /* + * original bio going to /dev/mdx + */ + struct bio *master_bio; + /* + * if the IO is in READ direction, then this is where we read + */ + int read_slot; + + struct list_head retry_list; + /* + * if the IO is in WRITE direction, then multiple bios are used, + * one for each copy. + * When resyncing we also use one for each copy. + * When reconstructing, we use 2 bios, one for read, one for write. + * We choose the number when they are allocated. + */ + struct { + struct bio *bio; + sector_t addr; + int devnum; + } devs[0]; +}; + +/* bits for r10bio.state */ +#define R10BIO_Uptodate 0 +#define R10BIO_IsSync 1 +#define R10BIO_IsRecover 2 +#endif diff -Nru a/include/linux/rmap.h b/include/linux/rmap.h --- a/include/linux/rmap.h 2004-08-25 22:01:54 -07:00 +++ b/include/linux/rmap.h 2004-08-25 22:01:54 -07:00 @@ -9,11 +9,6 @@ #include #include -#define page_map_lock(page) \ - bit_spin_lock(PG_maplock, (unsigned long *)&(page)->flags) -#define page_map_unlock(page) \ - bit_spin_unlock(PG_maplock, (unsigned long *)&(page)->flags) - /* * The anon_vma heads a list of private "related" vmas, to scan if * an anonymous page pointing to this anon_vma needs to be unmapped: @@ -87,24 +82,27 @@ */ static inline void page_dup_rmap(struct page *page) { - page_map_lock(page); - page->mapcount++; - page_map_unlock(page); + atomic_inc(&page->_mapcount); } /* * Called from mm/vmscan.c to handle paging out */ -int page_referenced(struct page *); +int page_referenced(struct page *, int is_locked); int try_to_unmap(struct page *); +/* + * Used by swapoff to help locate where page is expected in vma. + */ +unsigned long page_address_in_vma(struct page *, struct vm_area_struct *); + #else /* !CONFIG_MMU */ #define anon_vma_init() do {} while (0) #define anon_vma_prepare(vma) (0) #define anon_vma_link(vma) do {} while (0) -#define page_referenced(page) TestClearPageReferenced(page) +#define page_referenced(page,l) TestClearPageReferenced(page) #define try_to_unmap(page) SWAP_FAIL #endif /* CONFIG_MMU */ diff -Nru a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h --- a/include/linux/rtnetlink.h 2004-08-25 22:01:56 -07:00 +++ b/include/linux/rtnetlink.h 2004-08-25 22:01:56 -07:00 @@ -561,6 +561,10 @@ #define IFLA_WIRELESS IFLA_WIRELESS IFLA_PROTINFO, /* Protocol specific information for a link */ #define IFLA_PROTINFO IFLA_PROTINFO + IFLA_TXQLEN, +#define IFLA_TXQLEN IFLA_TXQLEN + IFLA_MAP, +#define IFLA_MAP IFLA_MAP __IFLA_MAX }; diff -Nru a/include/linux/sched.h b/include/linux/sched.h --- a/include/linux/sched.h 2004-08-25 22:01:54 -07:00 +++ b/include/linux/sched.h 2004-08-25 22:01:54 -07:00 @@ -40,7 +40,6 @@ #define CLONE_FS 0x00000200 /* set if fs info shared between processes */ #define CLONE_FILES 0x00000400 /* set if open files shared between processes */ #define CLONE_SIGHAND 0x00000800 /* set if signal handlers and blocked signals shared */ -#define CLONE_IDLETASK 0x00001000 /* set if new pid should be 0 (kernel only)*/ #define CLONE_PTRACE 0x00002000 /* set if we want to let tracing continue on the child too */ #define CLONE_VFORK 0x00004000 /* set if the parent wants the child to wake it up on mm_release */ #define CLONE_PARENT 0x00008000 /* set if we want to have the same parent as the cloner */ @@ -189,10 +188,26 @@ #include +extern unsigned long +arch_get_unmapped_area(struct file *, unsigned long, unsigned long, + unsigned long, unsigned long); +extern unsigned long +arch_get_unmapped_area_topdown(struct file *filp, unsigned long addr, + unsigned long len, unsigned long pgoff, + unsigned long flags); +extern void arch_unmap_area(struct vm_area_struct *area); +extern void arch_unmap_area_topdown(struct vm_area_struct *area); + + struct mm_struct { struct vm_area_struct * mmap; /* list of VMAs */ struct rb_root mm_rb; struct vm_area_struct * mmap_cache; /* last find_vma result */ + unsigned long (*get_unmapped_area) (struct file *filp, + unsigned long addr, unsigned long len, + unsigned long pgoff, unsigned long flags); + void (*unmap_area) (struct vm_area_struct *area); + unsigned long mmap_base; /* base of mmap area */ unsigned long free_area_cache; /* first hole */ pgd_t * pgd; atomic_t mm_users; /* How many users with user space? */ @@ -304,7 +319,7 @@ #define MAX_PRIO (MAX_RT_PRIO + 40) -#define rt_task(p) ((p)->prio < MAX_RT_PRIO) +#define rt_task(p) (unlikely((p)->prio < MAX_RT_PRIO)) /* * Some day this will be a full-fledged user tracking system.. @@ -352,6 +367,20 @@ struct timespec wall_to_prev; /* wall_to_monotonic used when set */ }; +#ifdef CONFIG_SCHEDSTATS +struct sched_info { + /* cumulative counters */ + unsigned long cpu_time, /* time spent on the cpu */ + run_delay, /* time spent waiting on a runqueue */ + pcnt; /* # of timeslices run on this cpu */ + + /* timestamps */ + unsigned long last_arrival, /* when we last ran on a cpu */ + last_queued; /* when we were last queued to run */ +}; + +extern struct file_operations proc_schedstat_operations; +#endif struct io_context; /* See blkdev.h */ void exit_io_context(void); @@ -414,6 +443,10 @@ cpumask_t cpus_allowed; unsigned int time_slice, first_time_slice; +#ifdef CONFIG_SCHEDSTATS + struct sched_info sched_info; +#endif + struct list_head tasks; /* * ptrace_list/ptrace_children forms the list of my children @@ -527,7 +560,13 @@ unsigned long ptrace_message; siginfo_t *last_siginfo; /* For ptrace use. */ - +/* + * current io wait handle: wait queue entry to use for io waits + * If this thread is processing aio, this points at the waitqueue + * inside the currently handled kiocb. It may be NULL (i.e. default + * to a stack based synchronous wait) if its doing sync IO. + */ + wait_queue_t *io_wait; #ifdef CONFIG_NUMA struct mempolicy *mempolicy; short il_next; /* could be shared with used_math */ @@ -570,118 +609,6 @@ #define PF_SYNCWRITE 0x00200000 /* I am doing a sync write */ #ifdef CONFIG_SMP -#define SCHED_LOAD_SCALE 128UL /* increase resolution of load */ - -#define SD_BALANCE_NEWIDLE 1 /* Balance when about to become idle */ -#define SD_BALANCE_EXEC 2 /* Balance on exec */ -#define SD_BALANCE_CLONE 4 /* Balance on clone */ -#define SD_WAKE_IDLE 8 /* Wake to idle CPU on task wakeup */ -#define SD_WAKE_AFFINE 16 /* Wake task to waking CPU */ -#define SD_WAKE_BALANCE 32 /* Perform balancing at task wakeup */ -#define SD_SHARE_CPUPOWER 64 /* Domain members share cpu power */ - -struct sched_group { - struct sched_group *next; /* Must be a circular list */ - cpumask_t cpumask; - - /* - * CPU power of this group, SCHED_LOAD_SCALE being max power for a - * single CPU. This should be read only (except for setup). Although - * it will need to be written to at cpu hot(un)plug time, perhaps the - * cpucontrol semaphore will provide enough exclusion? - */ - unsigned long cpu_power; -}; - -struct sched_domain { - /* These fields must be setup */ - struct sched_domain *parent; /* top domain must be null terminated */ - struct sched_group *groups; /* the balancing groups of the domain */ - cpumask_t span; /* span of all CPUs in this domain */ - unsigned long min_interval; /* Minimum balance interval ms */ - unsigned long max_interval; /* Maximum balance interval ms */ - unsigned int busy_factor; /* less balancing by factor if busy */ - unsigned int imbalance_pct; /* No balance until over watermark */ - unsigned long long cache_hot_time; /* Task considered cache hot (ns) */ - unsigned int cache_nice_tries; /* Leave cache hot tasks for # tries */ - unsigned int per_cpu_gain; /* CPU % gained by adding domain cpus */ - int flags; /* See SD_* */ - - /* Runtime fields. */ - unsigned long last_balance; /* init to jiffies. units in jiffies */ - unsigned int balance_interval; /* initialise to 1. units in ms. */ - unsigned int nr_balance_failed; /* initialise to 0 */ -}; - -/* Common values for SMT siblings */ -#define SD_SIBLING_INIT (struct sched_domain) { \ - .span = CPU_MASK_NONE, \ - .parent = NULL, \ - .groups = NULL, \ - .min_interval = 1, \ - .max_interval = 2, \ - .busy_factor = 8, \ - .imbalance_pct = 110, \ - .cache_hot_time = 0, \ - .cache_nice_tries = 0, \ - .per_cpu_gain = 15, \ - .flags = SD_BALANCE_NEWIDLE \ - | SD_BALANCE_EXEC \ - | SD_BALANCE_CLONE \ - | SD_WAKE_AFFINE \ - | SD_WAKE_IDLE \ - | SD_SHARE_CPUPOWER, \ - .last_balance = jiffies, \ - .balance_interval = 1, \ - .nr_balance_failed = 0, \ -} - -/* Common values for CPUs */ -#define SD_CPU_INIT (struct sched_domain) { \ - .span = CPU_MASK_NONE, \ - .parent = NULL, \ - .groups = NULL, \ - .min_interval = 1, \ - .max_interval = 4, \ - .busy_factor = 64, \ - .imbalance_pct = 125, \ - .cache_hot_time = (5*1000000/2), \ - .cache_nice_tries = 1, \ - .per_cpu_gain = 100, \ - .flags = SD_BALANCE_NEWIDLE \ - | SD_BALANCE_EXEC \ - | SD_BALANCE_CLONE \ - | SD_WAKE_AFFINE \ - | SD_WAKE_BALANCE, \ - .last_balance = jiffies, \ - .balance_interval = 1, \ - .nr_balance_failed = 0, \ -} - -#ifdef CONFIG_NUMA -/* Common values for NUMA nodes */ -#define SD_NODE_INIT (struct sched_domain) { \ - .span = CPU_MASK_NONE, \ - .parent = NULL, \ - .groups = NULL, \ - .min_interval = 8, \ - .max_interval = 32, \ - .busy_factor = 32, \ - .imbalance_pct = 125, \ - .cache_hot_time = (10*1000000), \ - .cache_nice_tries = 1, \ - .per_cpu_gain = 100, \ - .flags = SD_BALANCE_EXEC \ - | SD_BALANCE_CLONE \ - | SD_WAKE_BALANCE, \ - .last_balance = jiffies, \ - .balance_interval = 1, \ - .nr_balance_failed = 0, \ -} -#endif - -extern void cpu_attach_domain(struct sched_domain *sd, int cpu); - extern int set_cpus_allowed(task_t *p, cpumask_t new_mask); #else static inline int set_cpus_allowed(task_t *p, cpumask_t new_mask) @@ -692,10 +619,11 @@ extern unsigned long long sched_clock(void); +/* sched_exec is called by processes performing an exec */ #ifdef CONFIG_SMP -extern void sched_balance_exec(void); +extern void sched_exec(void); #else -#define sched_balance_exec() {} +#define sched_exec() {} #endif extern void sched_idle_next(void); @@ -754,16 +682,12 @@ extern int FASTCALL(wake_up_state(struct task_struct * tsk, unsigned int state)); extern int FASTCALL(wake_up_process(struct task_struct * tsk)); -extern void FASTCALL(wake_up_forked_process(struct task_struct * tsk)); +extern void FASTCALL(wake_up_new_task(struct task_struct * tsk, + unsigned long clone_flags)); #ifdef CONFIG_SMP extern void kick_process(struct task_struct *tsk); - extern void FASTCALL(wake_up_forked_thread(struct task_struct * tsk)); #else static inline void kick_process(struct task_struct *tsk) { } - static inline void wake_up_forked_thread(struct task_struct * tsk) - { - wake_up_forked_process(tsk); - } #endif extern void FASTCALL(sched_fork(task_t * p)); extern void FASTCALL(sched_exit(task_t * p)); @@ -794,6 +718,7 @@ extern void release_task(struct task_struct * p); extern int send_sig_info(int, struct siginfo *, struct task_struct *); extern int send_group_sig_info(int, struct siginfo *, struct task_struct *); +extern int force_sigsegv(int, struct task_struct *); extern int force_sig_info(int, struct siginfo *, struct task_struct *); extern int __kill_pg_info(int sig, struct siginfo *info, pid_t pgrp); extern int kill_pg_info(int, struct siginfo *, pid_t); @@ -863,8 +788,8 @@ /* mmput gets rid of the mappings and all user-space */ extern void mmput(struct mm_struct *); -/* Grab a reference to the mm if its not already going away */ -extern struct mm_struct *mmgrab(struct mm_struct *); +/* Grab a reference to a task's mm, if it is not already going away */ +extern struct mm_struct *get_task_mm(struct task_struct *task); /* Remove the current tasks stale references to the old mm_struct */ extern void mm_release(struct task_struct *, struct mm_struct *); @@ -890,7 +815,7 @@ extern int do_execve(char *, char __user * __user *, char __user * __user *, struct pt_regs *); extern long do_fork(unsigned long, unsigned long, struct pt_regs *, unsigned long, int __user *, int __user *); -extern struct task_struct * copy_process(unsigned long, unsigned long, struct pt_regs *, unsigned long, int __user *, int __user *); +task_t *fork_idle(int); extern void set_task_comm(struct task_struct *tsk, char *from); extern void get_task_comm(char *to, struct task_struct *tsk); @@ -965,27 +890,7 @@ { spin_unlock(&p->alloc_lock); } - -/** - * get_task_mm - acquire a reference to the task's mm - * - * Returns %NULL if the task has no mm. User must release - * the mm via mmput() after use. - */ -static inline struct mm_struct * get_task_mm(struct task_struct * task) -{ - struct mm_struct * mm; - - task_lock(task); - mm = task->mm; - if (mm) - mm = mmgrab(mm); - task_unlock(task); - return mm; -} - - /* set thread flags in other task's structures * - see asm/thread_info.h for TIF_xxxx flags available */ @@ -1095,6 +1000,17 @@ } #endif /* CONFIG_SMP */ + +#ifdef HAVE_ARCH_PICK_MMAP_LAYOUT +extern void arch_pick_mmap_layout(struct mm_struct *mm); +#else +static inline void arch_pick_mmap_layout(struct mm_struct *mm) +{ + mm->mmap_base = TASK_UNMAPPED_BASE; + mm->get_unmapped_area = arch_get_unmapped_area; + mm->unmap_area = arch_unmap_area; +} +#endif #endif /* __KERNEL__ */ diff -Nru a/include/linux/shm.h b/include/linux/shm.h --- a/include/linux/shm.h 2004-08-25 22:01:56 -07:00 +++ b/include/linux/shm.h 2004-08-25 22:01:56 -07:00 @@ -44,6 +44,7 @@ #define SHM_RDONLY 010000 /* read-only access */ #define SHM_RND 020000 /* round attach address to SHMLBA boundary */ #define SHM_REMAP 040000 /* take-over region on attach */ +#define SHM_EXEC 0100000 /* execution access */ /* super user shmctl commands */ #define SHM_LOCK 11 diff -Nru a/include/linux/signal.h b/include/linux/signal.h --- a/include/linux/signal.h 2004-08-25 22:01:54 -07:00 +++ b/include/linux/signal.h 2004-08-25 22:01:54 -07:00 @@ -217,7 +217,7 @@ #ifndef HAVE_ARCH_GET_SIGNAL_TO_DELIVER struct pt_regs; -extern int get_signal_to_deliver(siginfo_t *info, struct pt_regs *regs, void *cookie); +extern int get_signal_to_deliver(siginfo_t *info, struct k_sigaction *return_ka, struct pt_regs *regs, void *cookie); #endif #endif /* __KERNEL__ */ diff -Nru a/include/linux/slab.h b/include/linux/slab.h --- a/include/linux/slab.h 2004-08-25 22:01:56 -07:00 +++ b/include/linux/slab.h 2004-08-25 22:01:56 -07:00 @@ -45,6 +45,7 @@ #define SLAB_RECLAIM_ACCOUNT 0x00020000UL /* track pages allocated to indicate what is reclaimable later*/ #define SLAB_PANIC 0x00040000UL /* panic if kmem_cache_create() fails */ +#define SLAB_DESTROY_BY_RCU 0x00080000UL /* defer freeing pages to RCU */ /* flags passed to a constructor func */ #define SLAB_CTOR_CONSTRUCTOR 0x001UL /* if not set, then deconstructor */ diff -Nru a/include/linux/sysctl.h b/include/linux/sysctl.h --- a/include/linux/sysctl.h 2004-08-25 22:01:55 -07:00 +++ b/include/linux/sysctl.h 2004-08-25 22:01:55 -07:00 @@ -166,6 +166,7 @@ VM_BLOCK_DUMP=24, /* block dump mode */ VM_HUGETLB_GROUP=25, /* permitted hugetlb group */ VM_VFS_CACHE_PRESSURE=26, /* dcache/icache reclaim pressure */ + VM_LEGACY_VA_LAYOUT=27, /* legacy/compatibility virtual address space layout */ }; diff -Nru a/include/linux/time.h b/include/linux/time.h --- a/include/linux/time.h 2004-08-25 22:01:55 -07:00 +++ b/include/linux/time.h 2004-08-25 22:01:55 -07:00 @@ -41,7 +41,7 @@ * Have the 32 bit jiffies value wrap 5 minutes after boot * so jiffies wrap bugs show up earlier. */ -#define INITIAL_JIFFIES ((unsigned long)(unsigned int) (-300*HZ)) +#define INITIAL_JIFFIES ((unsigned long)(0)) /* * Change timeval to jiffies, trying to avoid the diff -Nru a/include/linux/wait.h b/include/linux/wait.h --- a/include/linux/wait.h 2004-08-25 22:01:55 -07:00 +++ b/include/linux/wait.h 2004-08-25 22:01:55 -07:00 @@ -80,6 +80,15 @@ return !list_empty(&q->task_list); } +/* + * Used to distinguish between sync and async io wait context: + * sync i/o typically specifies a NULL wait queue entry or a wait + * queue entry bound to a task (current task) to wake up. + * aio specifies a wait queue entry with an async notification + * callback routine, not associated with any task. + */ +#define is_sync_wait(wait) (!(wait) || ((wait)->task)) + extern void FASTCALL(add_wait_queue(wait_queue_head_t *q, wait_queue_t * wait)); extern void FASTCALL(add_wait_queue_exclusive(wait_queue_head_t *q, wait_queue_t * wait)); extern void FASTCALL(remove_wait_queue(wait_queue_head_t *q, wait_queue_t * wait)); diff -Nru a/include/net/xfrm.h b/include/net/xfrm.h --- a/include/net/xfrm.h 2004-08-25 22:01:56 -07:00 +++ b/include/net/xfrm.h 2004-08-25 22:01:56 -07:00 @@ -428,6 +428,7 @@ switch(fl->proto) { case IPPROTO_TCP: case IPPROTO_UDP: + case IPPROTO_SCTP: port = fl->fl_ip_sport; break; case IPPROTO_ICMP: @@ -447,6 +448,7 @@ switch(fl->proto) { case IPPROTO_TCP: case IPPROTO_UDP: + case IPPROTO_SCTP: port = fl->fl_ip_dport; break; case IPPROTO_ICMP: diff -Nru a/include/pcmcia/ss.h b/include/pcmcia/ss.h --- a/include/pcmcia/ss.h 2004-08-25 22:01:56 -07:00 +++ b/include/pcmcia/ss.h 2004-08-25 22:01:56 -07:00 @@ -103,7 +103,7 @@ u_char map; u_char flags; u_short speed; - u_long sys_start, sys_stop; + u_long static_start; u_int card_start; struct resource *res; } pccard_mem_map; diff -Nru a/init/Kconfig b/init/Kconfig --- a/init/Kconfig 2004-08-25 22:01:56 -07:00 +++ b/init/Kconfig 2004-08-25 22:01:56 -07:00 @@ -121,7 +121,7 @@ process and it's parent. Note that this file format is incompatible with previous v0/v1/v2 file formats, so you will need updated tools for processing it. A preliminary version of these tools is available - at . + at . config SYSCTL bool "Sysctl support" diff -Nru a/init/do_mounts_rd.c b/init/do_mounts_rd.c --- a/init/do_mounts_rd.c 2004-08-25 22:01:56 -07:00 +++ b/init/do_mounts_rd.c 2004-08-25 22:01:56 -07:00 @@ -122,7 +122,8 @@ printk(KERN_NOTICE "RAMDISK: ext2 filesystem found at block %d\n", start_block); - nblocks = le32_to_cpu(ext2sb->s_blocks_count); + nblocks = le32_to_cpu(ext2sb->s_blocks_count) << + le32_to_cpu(ext2sb->s_log_block_size); goto done; } @@ -173,10 +174,15 @@ } /* - * NOTE NOTE: nblocks suppose that the blocksize is BLOCK_SIZE, so - * rd_load_image will work only with filesystem BLOCK_SIZE wide! - * So make sure to use 1k blocksize while generating ext2fs - * ramdisk-images. + * NOTE NOTE: nblocks is not actually blocks but + * the number of kibibytes of data to load into a ramdisk. + * So any ramdisk block size that is a multiple of 1KiB should + * work when the appropriate ramdisk_blocksize is specified + * on the command line. + * + * The default ramdisk_blocksize is 1KiB and it is generally + * silly to use anything else, so make sure to use 1KiB + * blocksize while generating ext2fs ramdisk-images. */ if (sys_ioctl(out_fd, BLKGETSIZE, (unsigned long)&rd_blocks) < 0) rd_blocks = 0; @@ -184,7 +190,7 @@ rd_blocks >>= 1; if (nblocks > rd_blocks) { - printk("RAMDISK: image too big! (%d/%ld blocks)\n", + printk("RAMDISK: image too big! (%dKiB/%ldKiB)\n", nblocks, rd_blocks); goto done; } @@ -211,7 +217,7 @@ goto done; } - printk(KERN_NOTICE "RAMDISK: Loading %d blocks [%ld disk%s] into ram disk... ", + printk(KERN_NOTICE "RAMDISK: Loading %dKiB [%ld disk%s] into ram disk... ", nblocks, ((nblocks-1)/devblocks)+1, nblocks>devblocks ? "s" : ""); for (i = 0, disk = 1; i < nblocks; i++) { if (i && (i % devblocks == 0)) { diff -Nru a/init/main.c b/init/main.c --- a/init/main.c 2004-08-25 22:01:54 -07:00 +++ b/init/main.c 2004-08-25 22:01:54 -07:00 @@ -110,8 +110,8 @@ /* * Boot command-line arguments */ -#define MAX_INIT_ARGS 8 -#define MAX_INIT_ENVS 8 +#define MAX_INIT_ARGS 32 +#define MAX_INIT_ENVS 32 extern void time_init(void); /* Default late time init is NULL. archs can override this later. */ @@ -184,15 +184,28 @@ return 0; } -/* this should be approx 2 Bo*oMips to start (note initial shift), and will - still work even if initially too large, it will just take slightly longer */ +static unsigned long preset_lpj; +static int __init lpj_setup(char *str) +{ + preset_lpj = simple_strtoul(str,NULL,0); + return 1; +} + +__setup("lpj=", lpj_setup); + +/* + * This should be approx 2 Bo*oMips to start (note initial shift), and will + * still work even if initially too large, it will just take slightly longer + */ unsigned long loops_per_jiffy = (1<<12); EXPORT_SYMBOL(loops_per_jiffy); -/* This is the number of bits of precision for the loops_per_jiffy. Each - bit takes on average 1.5/HZ seconds. This (like the original) is a little - better than 1% */ +/* + * This is the number of bits of precision for the loops_per_jiffy. Each + * bit takes on average 1.5/HZ seconds. This (like the original) is a little + * better than 1% + */ #define LPS_PREC 8 void __devinit calibrate_delay(void) @@ -200,40 +213,53 @@ unsigned long ticks, loopbit; int lps_precision = LPS_PREC; - loops_per_jiffy = (1<<12); + if (preset_lpj) { + loops_per_jiffy = preset_lpj; + printk("Calibrating delay loop (skipped)... " + "%lu.%02lu BogoMIPS preset\n", + loops_per_jiffy/(500000/HZ), + (loops_per_jiffy/(5000/HZ)) % 100); + } else { + loops_per_jiffy = (1<<12); - printk("Calibrating delay loop... "); - while ((loops_per_jiffy <<= 1) != 0) { - /* wait for "start of" clock tick */ - ticks = jiffies; - while (ticks == jiffies) - /* nothing */; - /* Go .. */ - ticks = jiffies; - __delay(loops_per_jiffy); - ticks = jiffies - ticks; - if (ticks) - break; - } + printk(KERN_DEBUG "Calibrating delay loop... "); + while ((loops_per_jiffy <<= 1) != 0) { + /* wait for "start of" clock tick */ + ticks = jiffies; + while (ticks == jiffies) + /* nothing */; + /* Go .. */ + ticks = jiffies; + __delay(loops_per_jiffy); + ticks = jiffies - ticks; + if (ticks) + break; + } + + /* + * Do a binary approximation to get loops_per_jiffy set to + * equal one clock (up to lps_precision bits) + */ + loops_per_jiffy >>= 1; + loopbit = loops_per_jiffy; + while (lps_precision-- && (loopbit >>= 1)) { + loops_per_jiffy |= loopbit; + ticks = jiffies; + while (ticks == jiffies) + /* nothing */; + ticks = jiffies; + __delay(loops_per_jiffy); + if (jiffies != ticks) /* longer than 1 tick */ + loops_per_jiffy &= ~loopbit; + } -/* Do a binary approximation to get loops_per_jiffy set to equal one clock - (up to lps_precision bits) */ - loops_per_jiffy >>= 1; - loopbit = loops_per_jiffy; - while ( lps_precision-- && (loopbit >>= 1) ) { - loops_per_jiffy |= loopbit; - ticks = jiffies; - while (ticks == jiffies); - ticks = jiffies; - __delay(loops_per_jiffy); - if (jiffies != ticks) /* longer than 1 tick */ - loops_per_jiffy &= ~loopbit; + /* Round the value and print it */ + printk("%lu.%02lu BogoMIPS (lpj=%lu)\n", + loops_per_jiffy/(500000/HZ), + (loops_per_jiffy/(5000/HZ)) % 100, + loops_per_jiffy); } -/* Round the value and print it */ - printk("%lu.%02lu BogoMIPS\n", - loops_per_jiffy/(500000/HZ), - (loops_per_jiffy/(5000/HZ)) % 100); } static int __init debug_kernel(char *str) @@ -255,8 +281,10 @@ __setup("debug", debug_kernel); __setup("quiet", quiet_kernel); -/* Unknown boot options get handed to init, unless they look like - failed parameters */ +/* + * Unknown boot options get handed to init, unless they look like + * failed parameters + */ static int __init unknown_bootoption(char *param, char *val) { /* Change NUL term back to "=", to make "param" the whole string. */ @@ -267,8 +295,10 @@ if (obsolete_checksetup(param)) return 0; - /* Preemptive maintenance for "why didn't my mispelled command - line work?" */ + /* + * Preemptive maintenance for "why didn't my mispelled command + * line work?" + */ if (strchr(param, '.') && (!val || strchr(param, '.') < val)) { printk(KERN_ERR "Unknown boot option `%s': ignoring\n", param); return 0; @@ -308,7 +338,8 @@ unsigned int i; execute_command = str; - /* In case LILO is going to boot us with default command line, + /* + * In case LILO is going to boot us with default command line, * it prepends "auto" before the whole cmdline which makes * the shell think it should execute a script with such name. * So we ignore all arguments entered _before_ init=... [MJ] @@ -471,7 +502,6 @@ * time - but meanwhile we still have a functioning scheduler. */ sched_init(); - build_all_zonelists(); page_alloc_init(); printk("Kernel command line: %s\n", saved_command_line); @@ -537,13 +567,6 @@ check_bugs(); acpi_early_init(); /* before LAPIC and SMP init */ - - /* - * We count on the initial thread going ok - * Like idlers init is an unlocked kernel thread, which will - * make syscalls (and thus be locked). - */ - init_idle(current, smp_processor_id()); /* Do the rest non-__init'ed, we're now alive */ rest_init(); diff -Nru a/ipc/shm.c b/ipc/shm.c --- a/ipc/shm.c 2004-08-25 22:01:55 -07:00 +++ b/ipc/shm.c 2004-08-25 22:01:55 -07:00 @@ -78,7 +78,7 @@ static inline int shm_addid(struct shmid_kernel *shp) { - return ipc_addid(&shm_ids, &shp->shm_perm, shm_ctlmni+1); + return ipc_addid(&shm_ids, &shp->shm_perm, shm_ctlmni); } @@ -687,6 +687,10 @@ prot = PROT_READ | PROT_WRITE; o_flags = O_RDWR; acc_mode = S_IRUGO | S_IWUGO; + } + if (shmflg & SHM_EXEC) { + prot |= PROT_EXEC; + acc_mode |= S_IXUGO; } /* diff -Nru a/kernel/audit.c b/kernel/audit.c --- a/kernel/audit.c 2004-08-25 22:01:56 -07:00 +++ b/kernel/audit.c 2004-08-25 22:01:56 -07:00 @@ -708,7 +708,7 @@ audit_log_move(ab); avail = sizeof(ab->tmp) - ab->len; p = d_path(dentry, vfsmnt, ab->tmp + ab->len, avail); - if (p == ERR_PTR(-ENAMETOOLONG)) { + if (IS_ERR(p)) { /* FIXME: can we save some information here? */ audit_log_format(ab, ""); } else { diff -Nru a/kernel/exit.c b/kernel/exit.c --- a/kernel/exit.c 2004-08-25 22:01:56 -07:00 +++ b/kernel/exit.c 2004-08-25 22:01:56 -07:00 @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -56,8 +57,6 @@ struct dentry *proc_dentry; repeat: - BUG_ON(p->state < TASK_ZOMBIE); - atomic_dec(&p->user->processes); spin_lock(&p->proc_lock); proc_dentry = proc_pid_unhash(p); @@ -755,9 +754,8 @@ state = TASK_ZOMBIE; if (tsk->exit_signal == -1 && tsk->ptrace == 0) state = TASK_DEAD; - tsk->state = state; - tsk->flags |= PF_DEAD; - + else + tsk->state = state; /* * Clear these here so that update_process_times() won't try to deliver * itimer, profile or rlimit signals to this task while it is in late exit. @@ -767,19 +765,14 @@ tsk->rlim[RLIMIT_CPU].rlim_cur = RLIM_INFINITY; /* - * In the preemption case it must be impossible for the task - * to get runnable again, so use "_raw_" unlock to keep - * preempt_count elevated until we schedule(). - * - * To avoid deadlock on SMP, interrupts must be unmasked. If we - * don't, subsequently called functions (e.g, wait_task_inactive() - * via release_task()) will spin, with interrupt flags - * unwittingly blocked, until the other task sleeps. That task - * may itself be waiting for smp_call_function() to answer and - * complete, and with interrupts blocked that will never happen. + * Get a reference to it so that we can set the state + * as the last step. The state-setting only matters if the + * current task is releasing itself, to trigger the final + * put_task_struct() in finish_task_switch(). (thread self-reap) */ - _raw_write_unlock(&tasklist_lock); - local_irq_enable(); + get_task_struct(tsk); + + write_unlock_irq(&tasklist_lock); list_for_each_safe(_p, _n, &ptrace_dead) { list_del_init(_p); @@ -788,9 +781,23 @@ } /* If the process is dead, release it - nobody will wait for it */ - if (state == TASK_DEAD) + if (state == TASK_DEAD) { + lock_cpu_hotplug(); release_task(tsk); + write_lock_irq(&tasklist_lock); + /* + * No preemption may happen from this point on, + * or CPU hotplug (and task exit) breaks: + */ + unlock_cpu_hotplug(); + tsk->state = state; + _raw_write_unlock(&tasklist_lock); + local_irq_enable(); + } else + preempt_disable(); + tsk->flags |= PF_DEAD; + put_task_struct(tsk); } asmlinkage NORET_TYPE void do_exit(long code) diff -Nru a/kernel/fork.c b/kernel/fork.c --- a/kernel/fork.c 2004-08-25 22:01:54 -07:00 +++ b/kernel/fork.c 2004-08-25 22:01:54 -07:00 @@ -152,7 +152,12 @@ spin_lock_irqsave(&q->lock, flags); if (list_empty(&wait->task_list)) __add_wait_queue(q, wait); - set_current_state(state); + /* + * don't alter the task state if this is just going to + * queue an async wait queue callback + */ + if (is_sync_wait(wait)) + set_current_state(state); spin_unlock_irqrestore(&q->lock, flags); } @@ -167,7 +172,12 @@ spin_lock_irqsave(&q->lock, flags); if (list_empty(&wait->task_list)) __add_wait_queue_tail(q, wait); - set_current_state(state); + /* + * don't alter the task state if this is just going to + * queue an async wait queue callback + */ + if (is_sync_wait(wait)) + set_current_state(state); spin_unlock_irqrestore(&q->lock, flags); } @@ -280,7 +290,7 @@ mm->locked_vm = 0; mm->mmap = NULL; mm->mmap_cache = NULL; - mm->free_area_cache = TASK_UNMAPPED_BASE; + mm->free_area_cache = oldmm->mmap_base; mm->map_count = 0; mm->rss = 0; cpus_clear(mm->cpu_vm_mask); @@ -467,20 +477,34 @@ } } -/* - * Checks if the use count of an mm is non-zero and if so - * returns a reference to it after bumping up the use count. - * If the use count is zero, it means this mm is going away, - * so return NULL. +/** + * get_task_mm - acquire a reference to the task's mm + * + * Returns %NULL if the task has no mm. Checks if the use count + * of the mm is non-zero and if so returns a reference to it, after + * bumping up the use count. User must release the mm via mmput() + * after use. Typically used by /proc and ptrace. + * + * If the use count is zero, it means that this mm is going away, + * so return %NULL. This only happens in the case of an AIO daemon + * which has temporarily adopted an mm (see use_mm), in the course + * of its final mmput, before exit_aio has completed. */ -struct mm_struct *mmgrab(struct mm_struct *mm) +struct mm_struct *get_task_mm(struct task_struct *task) { - spin_lock(&mmlist_lock); - if (!atomic_read(&mm->mm_users)) - mm = NULL; - else - atomic_inc(&mm->mm_users); - spin_unlock(&mmlist_lock); + struct mm_struct *mm; + + task_lock(task); + mm = task->mm; + if (mm) { + spin_lock(&mmlist_lock); + if (!atomic_read(&mm->mm_users)) + mm = NULL; + else + atomic_inc(&mm->mm_users); + spin_unlock(&mmlist_lock); + } + task_unlock(task); return mm; } @@ -865,12 +889,13 @@ * parts of the process environment (as per the clone * flags). The actual kick-off is left to the caller. */ -struct task_struct *copy_process(unsigned long clone_flags, +static task_t *copy_process(unsigned long clone_flags, unsigned long stack_start, struct pt_regs *regs, unsigned long stack_size, int __user *parent_tidptr, - int __user *child_tidptr) + int __user *child_tidptr, + int pid) { int retval; struct task_struct *p = NULL; @@ -930,13 +955,7 @@ p->did_exec = 0; copy_flags(clone_flags, p); - if (clone_flags & CLONE_IDLETASK) - p->pid = 0; - else { - p->pid = alloc_pidmap(); - if (p->pid == -1) - goto bad_fork_cleanup; - } + p->pid = pid; retval = -EFAULT; if (clone_flags & CLONE_PARENT_SETTID) if (put_user(p->pid, parent_tidptr)) @@ -965,6 +984,7 @@ p->start_time = get_jiffies_64(); p->security = NULL; p->io_context = NULL; + p->io_wait = NULL; p->audit_context = NULL; #ifdef CONFIG_NUMA p->mempolicy = mpol_copy(p->mempolicy); @@ -1033,6 +1053,17 @@ /* Need tasklist lock for parent etc handling! */ write_lock_irq(&tasklist_lock); + + /* + * The task hasn't been attached yet, so cpus_allowed mask cannot + * have changed. The cpus_allowed mask of the parent may have + * changed after it was copied first time, and it may then move to + * another CPU - so we re-copy it here and set the child's CPU to + * the parent's CPU. This avoids alot of nasty races. + */ + p->cpus_allowed = current->cpus_allowed; + set_task_cpu(p, smp_processor_id()); + /* * Check for pending SIGKILL! The new thread should not be allowed * to slip out of an OOM kill. (or normal SIGKILL.) @@ -1127,8 +1158,6 @@ mpol_free(p->mempolicy); #endif bad_fork_cleanup: - if (p->pid > 0) - free_pidmap(p->pid); if (p->binfmt) module_put(p->binfmt->module); bad_fork_cleanup_put_domain: @@ -1142,9 +1171,28 @@ goto fork_out; } +struct pt_regs * __init __attribute__((weak)) idle_regs(struct pt_regs *regs) +{ + memset(regs, 0, sizeof(struct pt_regs)); + return regs; +} + +task_t * __init fork_idle(int cpu) +{ + task_t *task; + struct pt_regs regs; + + task = copy_process(CLONE_VM, 0, idle_regs(®s), 0, NULL, NULL, 0); + if (!task) + return ERR_PTR(-ENOMEM); + init_idle(task, cpu); + unhash_process(task); + return task; +} + static inline int fork_traceflag (unsigned clone_flags) { - if (clone_flags & (CLONE_UNTRACED | CLONE_IDLETASK)) + if (clone_flags & CLONE_UNTRACED) return 0; else if (clone_flags & CLONE_VFORK) { if (current->ptrace & PT_TRACE_VFORK) @@ -1173,21 +1221,21 @@ { struct task_struct *p; int trace = 0; - long pid; + long pid = alloc_pidmap(); + if (pid < 0) + return -EAGAIN; if (unlikely(current->ptrace)) { trace = fork_traceflag (clone_flags); if (trace) clone_flags |= CLONE_PTRACE; } - p = copy_process(clone_flags, stack_start, regs, stack_size, parent_tidptr, child_tidptr); + p = copy_process(clone_flags, stack_start, regs, stack_size, parent_tidptr, child_tidptr, pid); /* * Do this prior waking up the new thread - the thread pointer * might get invalid after that point, if the thread exits quickly. */ - pid = IS_ERR(p) ? PTR_ERR(p) : p->pid; - if (!IS_ERR(p)) { struct completion vfork; @@ -1204,31 +1252,10 @@ set_tsk_thread_flag(p, TIF_SIGPENDING); } - if (!(clone_flags & CLONE_STOPPED)) { - /* - * Do the wakeup last. On SMP we treat fork() and - * CLONE_VM separately, because fork() has already - * created cache footprint on this CPU (due to - * copying the pagetables), hence migration would - * probably be costy. Threads on the other hand - * have less traction to the current CPU, and if - * there's an imbalance then the scheduler can - * migrate this fresh thread now, before it - * accumulates a larger cache footprint: - */ - if (clone_flags & CLONE_VM) - wake_up_forked_thread(p); - else - wake_up_forked_process(p); - } else { - int cpu = get_cpu(); - + if (!(clone_flags & CLONE_STOPPED)) + wake_up_new_task(p, clone_flags); + else p->state = TASK_STOPPED; - if (cpu_is_offline(task_cpu(p))) - set_task_cpu(p, cpu); - - put_cpu(); - } ++total_forks; if (unlikely (trace)) { @@ -1240,12 +1267,10 @@ wait_for_completion(&vfork); if (unlikely (current->ptrace & PT_TRACE_VFORK_DONE)) ptrace_notify ((PTRACE_EVENT_VFORK_DONE << 8) | SIGTRAP); - } else - /* - * Let the child process run first, to avoid most of the - * COW overhead when the child exec()s afterwards. - */ - set_need_resched(); + } + } else { + free_pidmap(pid); + pid = PTR_ERR(p); } return pid; } diff -Nru a/kernel/sched.c b/kernel/sched.c --- a/kernel/sched.c 2004-08-25 22:01:56 -07:00 +++ b/kernel/sched.c 2004-08-25 22:01:56 -07:00 @@ -40,6 +40,8 @@ #include #include #include +#include +#include #include #include @@ -67,8 +69,6 @@ #define USER_PRIO(p) ((p)-MAX_RT_PRIO) #define TASK_USER_PRIO(p) USER_PRIO((p)->static_prio) #define MAX_USER_PRIO (USER_PRIO(MAX_PRIO)) -#define AVG_TIMESLICE (MIN_TIMESLICE + ((MAX_TIMESLICE - MIN_TIMESLICE) *\ - (MAX_PRIO-1-NICE_TO_PRIO(0))/(MAX_USER_PRIO - 1))) /* * Some helpers for converting nanosecond timing to jiffy resolution @@ -79,12 +79,12 @@ /* * These are the 'tuning knobs' of the scheduler: * - * Minimum timeslice is 10 msecs, default timeslice is 100 msecs, - * maximum timeslice is 200 msecs. Timeslices get refilled after - * they expire. + * Minimum timeslice is 5 msecs (or 1 jiffy, whichever is larger), + * default timeslice is 100 msecs, maximum timeslice is 800 msecs. + * Timeslices get refilled after they expire. */ -#define MIN_TIMESLICE ( 10 * HZ / 1000) -#define MAX_TIMESLICE (200 * HZ / 1000) +#define MIN_TIMESLICE max(5 * HZ / 1000, 1) +#define DEF_TIMESLICE (100 * HZ / 1000) #define ON_RUNQUEUE_WEIGHT 30 #define CHILD_PENALTY 95 #define PARENT_PENALTY 100 @@ -92,7 +92,7 @@ #define PRIO_BONUS_RATIO 25 #define MAX_BONUS (MAX_USER_PRIO * PRIO_BONUS_RATIO / 100) #define INTERACTIVE_DELTA 2 -#define MAX_SLEEP_AVG (AVG_TIMESLICE * MAX_BONUS) +#define MAX_SLEEP_AVG (DEF_TIMESLICE * MAX_BONUS) #define STARVATION_LIMIT (MAX_SLEEP_AVG) #define NS_MAX_SLEEP_AVG (JIFFIES_TO_NS(MAX_SLEEP_AVG)) #define CREDIT_LIMIT 100 @@ -161,27 +161,36 @@ ((p)->prio < (rq)->curr->prio) /* - * BASE_TIMESLICE scales user-nice values [ -20 ... 19 ] - * to time slice values. + * task_timeslice() scales user-nice values [ -20 ... 0 ... 19 ] + * to time slice values: [800ms ... 100ms ... 5ms] * * The higher a thread's priority, the bigger timeslices * it gets during one round of execution. But even the lowest * priority thread gets MIN_TIMESLICE worth of execution time. - * - * task_timeslice() is the interface that is used by the scheduler. */ -#define BASE_TIMESLICE(p) (MIN_TIMESLICE + \ - ((MAX_TIMESLICE - MIN_TIMESLICE) * \ - (MAX_PRIO-1 - (p)->static_prio) / (MAX_USER_PRIO-1))) +#define SCALE_PRIO(x, prio) \ + max(x * (MAX_PRIO - prio) / (MAX_USER_PRIO/2), MIN_TIMESLICE) static unsigned int task_timeslice(task_t *p) { - return BASE_TIMESLICE(p); + if (p->static_prio < NICE_TO_PRIO(0)) + return SCALE_PRIO(DEF_TIMESLICE*4, p->static_prio); + else + return SCALE_PRIO(DEF_TIMESLICE, p->static_prio); } - #define task_hot(p, now, sd) ((now) - (p)->timestamp < (sd)->cache_hot_time) +enum idle_type +{ + IDLE, + NOT_IDLE, + NEWLY_IDLE, + MAX_IDLE_TYPES +}; + +struct sched_domain; + /* * These are the runqueue data structures: */ @@ -233,10 +242,186 @@ task_t *migration_thread; struct list_head migration_queue; #endif + +#ifdef CONFIG_SCHEDSTATS + /* latency stats */ + struct sched_info rq_sched_info; + + /* sys_sched_yield() stats */ + unsigned long yld_exp_empty; + unsigned long yld_act_empty; + unsigned long yld_both_empty; + unsigned long yld_cnt; + + /* schedule() stats */ + unsigned long sched_noswitch; + unsigned long sched_switch; + unsigned long sched_cnt; + unsigned long sched_goidle; + + /* pull_task() stats */ + unsigned long pt_gained[MAX_IDLE_TYPES]; + unsigned long pt_lost[MAX_IDLE_TYPES]; + + /* active_load_balance() stats */ + unsigned long alb_cnt; + unsigned long alb_lost; + unsigned long alb_gained; + unsigned long alb_failed; + + /* try_to_wake_up() stats */ + unsigned long ttwu_cnt; + unsigned long ttwu_attempts; + unsigned long ttwu_moved; + + /* wake_up_new_task() stats */ + unsigned long wunt_cnt; + unsigned long wunt_moved; + + /* sched_migrate_task() stats */ + unsigned long smt_cnt; + + /* sched_balance_exec() stats */ + unsigned long sbe_cnt; +#endif }; static DEFINE_PER_CPU(struct runqueue, runqueues); +/* + * sched-domains (multiprocessor balancing) declarations: + */ +#ifdef CONFIG_SMP +#define SCHED_LOAD_SCALE 128UL /* increase resolution of load */ + +#define SD_BALANCE_NEWIDLE 1 /* Balance when about to become idle */ +#define SD_BALANCE_EXEC 2 /* Balance on exec */ +#define SD_WAKE_IDLE 4 /* Wake to idle CPU on task wakeup */ +#define SD_WAKE_AFFINE 8 /* Wake task to waking CPU */ +#define SD_WAKE_BALANCE 16 /* Perform balancing at task wakeup */ +#define SD_SHARE_CPUPOWER 32 /* Domain members share cpu power */ + +struct sched_group { + struct sched_group *next; /* Must be a circular list */ + cpumask_t cpumask; + + /* + * CPU power of this group, SCHED_LOAD_SCALE being max power for a + * single CPU. This should be read only (except for setup). Although + * it will need to be written to at cpu hot(un)plug time, perhaps the + * cpucontrol semaphore will provide enough exclusion? + */ + unsigned long cpu_power; +}; + +struct sched_domain { + /* These fields must be setup */ + struct sched_domain *parent; /* top domain must be null terminated */ + struct sched_group *groups; /* the balancing groups of the domain */ + cpumask_t span; /* span of all CPUs in this domain */ + unsigned long min_interval; /* Minimum balance interval ms */ + unsigned long max_interval; /* Maximum balance interval ms */ + unsigned int busy_factor; /* less balancing by factor if busy */ + unsigned int imbalance_pct; /* No balance until over watermark */ + unsigned long long cache_hot_time; /* Task considered cache hot (ns) */ + unsigned int cache_nice_tries; /* Leave cache hot tasks for # tries */ + unsigned int per_cpu_gain; /* CPU % gained by adding domain cpus */ + int flags; /* See SD_* */ + + /* Runtime fields. */ + unsigned long last_balance; /* init to jiffies. units in jiffies */ + unsigned int balance_interval; /* initialise to 1. units in ms. */ + unsigned int nr_balance_failed; /* initialise to 0 */ + +#ifdef CONFIG_SCHEDSTATS + /* load_balance() stats */ + unsigned long lb_cnt[MAX_IDLE_TYPES]; + unsigned long lb_failed[MAX_IDLE_TYPES]; + unsigned long lb_imbalance[MAX_IDLE_TYPES]; + unsigned long lb_nobusyg[MAX_IDLE_TYPES]; + unsigned long lb_nobusyq[MAX_IDLE_TYPES]; + + /* sched_balance_exec() stats */ + unsigned long sbe_attempts; + unsigned long sbe_pushed; + + /* try_to_wake_up() stats */ + unsigned long ttwu_wake_affine; + unsigned long ttwu_wake_balance; +#endif +}; + +#ifndef ARCH_HAS_SCHED_TUNE +#ifdef CONFIG_SCHED_SMT +#define ARCH_HAS_SCHED_WAKE_IDLE +/* Common values for SMT siblings */ +#define SD_SIBLING_INIT (struct sched_domain) { \ + .span = CPU_MASK_NONE, \ + .parent = NULL, \ + .groups = NULL, \ + .min_interval = 1, \ + .max_interval = 2, \ + .busy_factor = 8, \ + .imbalance_pct = 110, \ + .cache_hot_time = 0, \ + .cache_nice_tries = 0, \ + .per_cpu_gain = 25, \ + .flags = SD_BALANCE_NEWIDLE \ + | SD_BALANCE_EXEC \ + | SD_WAKE_AFFINE \ + | SD_WAKE_IDLE \ + | SD_SHARE_CPUPOWER, \ + .last_balance = jiffies, \ + .balance_interval = 1, \ + .nr_balance_failed = 0, \ +} +#endif + +/* Common values for CPUs */ +#define SD_CPU_INIT (struct sched_domain) { \ + .span = CPU_MASK_NONE, \ + .parent = NULL, \ + .groups = NULL, \ + .min_interval = 1, \ + .max_interval = 4, \ + .busy_factor = 64, \ + .imbalance_pct = 125, \ + .cache_hot_time = (5*1000000/2), \ + .cache_nice_tries = 1, \ + .per_cpu_gain = 100, \ + .flags = SD_BALANCE_NEWIDLE \ + | SD_BALANCE_EXEC \ + | SD_WAKE_AFFINE \ + | SD_WAKE_BALANCE, \ + .last_balance = jiffies, \ + .balance_interval = 1, \ + .nr_balance_failed = 0, \ +} + +/* Arch can override this macro in processor.h */ +#if defined(CONFIG_NUMA) && !defined(SD_NODE_INIT) +#define SD_NODE_INIT (struct sched_domain) { \ + .span = CPU_MASK_NONE, \ + .parent = NULL, \ + .groups = NULL, \ + .min_interval = 8, \ + .max_interval = 32, \ + .busy_factor = 32, \ + .imbalance_pct = 125, \ + .cache_hot_time = (10*1000000), \ + .cache_nice_tries = 1, \ + .per_cpu_gain = 100, \ + .flags = SD_BALANCE_EXEC \ + | SD_WAKE_BALANCE, \ + .last_balance = jiffies, \ + .balance_interval = 1, \ + .nr_balance_failed = 0, \ +} +#endif +#endif /* ARCH_HAS_SCHED_TUNE */ +#endif + + #define for_each_domain(cpu, domain) \ for (domain = cpu_rq(cpu)->sd; domain; domain = domain->parent) @@ -279,6 +464,104 @@ spin_unlock_irqrestore(&rq->lock, *flags); } +#ifdef CONFIG_SCHEDSTATS +/* + * bump this up when changing the output format or the meaning of an existing + * format, so that tools can adapt (or abort) + */ +#define SCHEDSTAT_VERSION 10 + +static int show_schedstat(struct seq_file *seq, void *v) +{ + int cpu; + enum idle_type itype; + + seq_printf(seq, "version %d\n", SCHEDSTAT_VERSION); + seq_printf(seq, "timestamp %lu\n", jiffies); + for_each_online_cpu(cpu) { + runqueue_t *rq = cpu_rq(cpu); +#ifdef CONFIG_SMP + struct sched_domain *sd; + int dcnt = 0; +#endif + + /* runqueue-specific stats */ + seq_printf(seq, + "cpu%d %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu " + "%lu %lu %lu %lu %lu %lu %lu %lu %lu %lu", + cpu, rq->yld_both_empty, + rq->yld_act_empty, rq->yld_exp_empty, + rq->yld_cnt, rq->sched_noswitch, + rq->sched_switch, rq->sched_cnt, rq->sched_goidle, + rq->alb_cnt, rq->alb_gained, rq->alb_lost, + rq->alb_failed, + rq->ttwu_cnt, rq->ttwu_moved, rq->ttwu_attempts, + rq->wunt_cnt, rq->wunt_moved, + rq->smt_cnt, rq->sbe_cnt, rq->rq_sched_info.cpu_time, + rq->rq_sched_info.run_delay, rq->rq_sched_info.pcnt); + + for (itype = IDLE; itype < MAX_IDLE_TYPES; itype++) + seq_printf(seq, " %lu %lu", rq->pt_gained[itype], + rq->pt_lost[itype]); + seq_printf(seq, "\n"); + +#ifdef CONFIG_SMP + /* domain-specific stats */ + for_each_domain(cpu, sd) { + char mask_str[NR_CPUS]; + + cpumask_scnprintf(mask_str, NR_CPUS, sd->span); + seq_printf(seq, "domain%d %s", dcnt++, mask_str); + for (itype = IDLE; itype < MAX_IDLE_TYPES; itype++) { + seq_printf(seq, " %lu %lu %lu %lu %lu", + sd->lb_cnt[itype], + sd->lb_failed[itype], + sd->lb_imbalance[itype], + sd->lb_nobusyq[itype], + sd->lb_nobusyg[itype]); + } + seq_printf(seq, " %lu %lu %lu %lu\n", + sd->sbe_pushed, sd->sbe_attempts, + sd->ttwu_wake_affine, sd->ttwu_wake_balance); + } +#endif + } + return 0; +} + +static int schedstat_open(struct inode *inode, struct file *file) +{ + unsigned int size = PAGE_SIZE * (1 + num_online_cpus() / 32); + char *buf = kmalloc(size, GFP_KERNEL); + struct seq_file *m; + int res; + + if (!buf) + return -ENOMEM; + res = single_open(file, show_schedstat, NULL); + if (!res) { + m = file->private_data; + m->buf = buf; + m->size = size; + } else + kfree(buf); + return res; +} + +struct file_operations proc_schedstat_operations = { + .open = schedstat_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +# define schedstat_inc(rq, field) rq->field++; +# define schedstat_add(rq, field, amt) rq->field += amt; +#else /* !CONFIG_SCHEDSTATS */ +# define schedstat_inc(rq, field) do { } while (0); +# define schedstat_add(rq, field, amt) do { } while (0); +#endif + /* * rq_lock - lock a given runqueue and disable interrupts. */ @@ -298,6 +581,112 @@ spin_unlock_irq(&rq->lock); } +#ifdef CONFIG_SCHEDSTATS +/* + * Called when a process is dequeued from the active array and given + * the cpu. We should note that with the exception of interactive + * tasks, the expired queue will become the active queue after the active + * queue is empty, without explicitly dequeuing and requeuing tasks in the + * expired queue. (Interactive tasks may be requeued directly to the + * active queue, thus delaying tasks in the expired queue from running; + * see scheduler_tick()). + * + * This function is only called from sched_info_arrive(), rather than + * dequeue_task(). Even though a task may be queued and dequeued multiple + * times as it is shuffled about, we're really interested in knowing how + * long it was from the *first* time it was queued to the time that it + * finally hit a cpu. + */ +static inline void sched_info_dequeued(task_t *t) +{ + t->sched_info.last_queued = 0; +} + +/* + * Called when a task finally hits the cpu. We can now calculate how + * long it was waiting to run. We also note when it began so that we + * can keep stats on how long its timeslice is. + */ +static inline void sched_info_arrive(task_t *t) +{ + unsigned long now = jiffies, diff = 0; + struct runqueue *rq = task_rq(t); + + if (t->sched_info.last_queued) + diff = now - t->sched_info.last_queued; + sched_info_dequeued(t); + t->sched_info.run_delay += diff; + t->sched_info.last_arrival = now; + t->sched_info.pcnt++; + + if (!rq) + return; + + rq->rq_sched_info.run_delay += diff; + rq->rq_sched_info.pcnt++; +} + +/* + * Called when a process is queued into either the active or expired + * array. The time is noted and later used to determine how long we + * had to wait for us to reach the cpu. Since the expired queue will + * become the active queue after active queue is empty, without dequeuing + * and requeuing any tasks, we are interested in queuing to either. It + * is unusual but not impossible for tasks to be dequeued and immediately + * requeued in the same or another array: this can happen in sched_yield(), + * set_user_nice(), and even load_balance() as it moves tasks from runqueue + * to runqueue. + * + * This function is only called from enqueue_task(), but also only updates + * the timestamp if it is already not set. It's assumed that + * sched_info_dequeued() will clear that stamp when appropriate. + */ +static inline void sched_info_queued(task_t *t) +{ + if (!t->sched_info.last_queued) + t->sched_info.last_queued = jiffies; +} + +/* + * Called when a process ceases being the active-running process, either + * voluntarily or involuntarily. Now we can calculate how long we ran. + */ +static inline void sched_info_depart(task_t *t) +{ + struct runqueue *rq = task_rq(t); + unsigned long diff = jiffies - t->sched_info.last_arrival; + + t->sched_info.cpu_time += diff; + + if (rq) + rq->rq_sched_info.cpu_time += diff; +} + +/* + * Called when tasks are switched involuntarily due, typically, to expiring + * their time slice. (This may also be called when switching to or from + * the idle task.) We are only called when prev != next. + */ +static inline void sched_info_switch(task_t *prev, task_t *next) +{ + struct runqueue *rq = task_rq(prev); + + /* + * prev now departs the cpu. It's not interesting to record + * stats about how efficient we were at scheduling the idle + * process, however. + */ + if (prev != rq->idle) + sched_info_depart(prev); + + if (next != rq->idle) + sched_info_arrive(next); +} +#else +#define sched_info_queued(t) do { } while (0) +#define sched_info_switch(t, next) do { } while (0) +#endif /* CONFIG_SCHEDSTATS */ + /* * Adding/removing a task to/from a priority array: */ @@ -311,6 +700,7 @@ static void enqueue_task(struct task_struct *p, prio_array_t *array) { + sched_info_queued(p); list_add_tail(&p->run_list, array->queue + p->prio); __set_bit(p->prio, array->bitmap); array->nr_active++; @@ -399,7 +789,7 @@ if (p->mm && p->activated != -1 && sleep_time > INTERACTIVE_SLEEP(p)) { p->sleep_avg = JIFFIES_TO_NS(MAX_SLEEP_AVG - - AVG_TIMESLICE); + DEF_TIMESLICE); if (!HIGH_CREDIT(p)) p->interactive_credit++; } else { @@ -526,7 +916,8 @@ { int need_resched, nrpolling; - preempt_disable(); + BUG_ON(!spin_is_locked(&task_rq(p)->lock)); + /* minimise the chance of sending an interrupt to poll_idle() */ nrpolling = test_tsk_thread_flag(p,TIF_POLLING_NRFLAG); need_resched = test_and_set_tsk_thread_flag(p,TIF_NEED_RESCHED); @@ -534,7 +925,6 @@ if (!need_resched && !nrpolling && (task_cpu(p) != smp_processor_id())) smp_send_reschedule(task_cpu(p)); - preempt_enable(); } #else static inline void resched_task(task_t *p) @@ -740,6 +1130,7 @@ #endif rq = task_rq_lock(p, &flags); + schedstat_inc(rq, ttwu_cnt); old_state = p->state; if (!(old_state & state)) goto out; @@ -787,23 +1178,35 @@ */ imbalance = sd->imbalance_pct + (sd->imbalance_pct - 100) / 2; - if ( ((sd->flags & SD_WAKE_AFFINE) && - !task_hot(p, rq->timestamp_last_tick, sd)) - || ((sd->flags & SD_WAKE_BALANCE) && - imbalance*this_load <= 100*load) ) { + if ((sd->flags & SD_WAKE_AFFINE) && + !task_hot(p, rq->timestamp_last_tick, sd)) { + /* + * This domain has SD_WAKE_AFFINE and p is cache cold + * in this domain. + */ + if (cpu_isset(cpu, sd->span)) { + schedstat_inc(sd, ttwu_wake_affine); + goto out_set_cpu; + } + } else if ((sd->flags & SD_WAKE_BALANCE) && + imbalance*this_load <= 100*load) { /* - * Now sd has SD_WAKE_AFFINE and p is cache cold in sd - * or sd has SD_WAKE_BALANCE and there is an imbalance + * This domain has SD_WAKE_BALANCE and there is + * an imbalance. */ - if (cpu_isset(cpu, sd->span)) + if (cpu_isset(cpu, sd->span)) { + schedstat_inc(sd, ttwu_wake_balance); goto out_set_cpu; + } } } new_cpu = cpu; /* Could not wake to this_cpu. Wake to cpu instead */ out_set_cpu: + schedstat_inc(rq, ttwu_attempts); new_cpu = wake_idle(new_cpu, p); if (new_cpu != cpu && cpu_isset(new_cpu, p->cpus_allowed)) { + schedstat_inc(rq, ttwu_moved); set_task_cpu(p, new_cpu); task_rq_unlock(rq, &flags); /* might preempt at this point */ @@ -865,6 +1268,11 @@ return try_to_wake_up(p, state, 0); } +#ifdef CONFIG_SMP +static int find_idlest_cpu(struct task_struct *p, int this_cpu, + struct sched_domain *sd); +#endif + /* * Perform scheduler related setup for a newly forked process p. * p is forked by current. @@ -881,6 +1289,9 @@ INIT_LIST_HEAD(&p->run_list); p->array = NULL; spin_lock_init(&p->switch_lock); +#ifdef CONFIG_SCHEDSTATS + memset(&p->sched_info, 0, sizeof(p->sched_info)); +#endif #ifdef CONFIG_PREEMPT /* * During context-switch we hold precisely one spinlock, which @@ -904,7 +1315,7 @@ p->first_time_slice = 1; current->time_slice >>= 1; p->timestamp = sched_clock(); - if (!current->time_slice) { + if (unlikely(!current->time_slice)) { /* * This case is rare, it happens when the parent has only * a single jiffy left from its timeslice. Taking the @@ -920,44 +1331,89 @@ } /* - * wake_up_forked_process - wake up a freshly forked process. + * wake_up_new_task - wake up a newly created task for the first time. * * This function will do some initial scheduler statistics housekeeping - * that must be done for every newly created process. + * that must be done for every newly created context, then puts the task + * on the runqueue and wakes it. */ -void fastcall wake_up_forked_process(task_t * p) +void fastcall wake_up_new_task(task_t * p, unsigned long clone_flags) { unsigned long flags; - runqueue_t *rq = task_rq_lock(current, &flags); + int this_cpu, cpu; + runqueue_t *rq, *this_rq; + + rq = task_rq_lock(p, &flags); + cpu = task_cpu(p); + this_cpu = smp_processor_id(); BUG_ON(p->state != TASK_RUNNING); + schedstat_inc(rq, wunt_cnt); /* * We decrease the sleep average of forking parents * and children as well, to keep max-interactive tasks - * from forking tasks that are max-interactive. + * from forking tasks that are max-interactive. The parent + * (current) is done further down, under its lock. */ - current->sleep_avg = JIFFIES_TO_NS(CURRENT_BONUS(current) * - PARENT_PENALTY / 100 * MAX_SLEEP_AVG / MAX_BONUS); - p->sleep_avg = JIFFIES_TO_NS(CURRENT_BONUS(p) * CHILD_PENALTY / 100 * MAX_SLEEP_AVG / MAX_BONUS); p->interactive_credit = 0; p->prio = effective_prio(p); - set_task_cpu(p, smp_processor_id()); - if (unlikely(!current->array)) + if (likely(cpu == this_cpu)) { + if (!(clone_flags & CLONE_VM)) { + /* + * The VM isn't cloned, so we're in a good position to + * do child-runs-first in anticipation of an exec. This + * usually avoids a lot of COW overhead. + */ + if (unlikely(!current->array)) + __activate_task(p, rq); + else { + p->prio = current->prio; + list_add_tail(&p->run_list, ¤t->run_list); + p->array = current->array; + p->array->nr_active++; + rq->nr_running++; + } + set_need_resched(); + } else + /* Run child last */ + __activate_task(p, rq); + /* + * We skip the following code due to cpu == this_cpu + * + * task_rq_unlock(rq, &flags); + * this_rq = task_rq_lock(current, &flags); + */ + this_rq = rq; + } else { + this_rq = cpu_rq(this_cpu); + + /* + * Not the local CPU - must adjust timestamp. This should + * get optimised away in the !CONFIG_SMP case. + */ + p->timestamp = (p->timestamp - this_rq->timestamp_last_tick) + + rq->timestamp_last_tick; __activate_task(p, rq); - else { - p->prio = current->prio; - list_add_tail(&p->run_list, ¤t->run_list); - p->array = current->array; - p->array->nr_active++; - rq->nr_running++; + if (TASK_PREEMPTS_CURR(p, rq)) + resched_task(rq->curr); + + schedstat_inc(rq, wunt_moved); + /* + * Parent and child are on different CPUs, now get the + * parent runqueue to update the parent's ->sleep_avg: + */ + task_rq_unlock(rq, &flags); + this_rq = task_rq_lock(current, &flags); } - task_rq_unlock(rq, &flags); + current->sleep_avg = JIFFIES_TO_NS(CURRENT_BONUS(current) * + PARENT_PENALTY / 100 * MAX_SLEEP_AVG / MAX_BONUS); + task_rq_unlock(this_rq, &flags); } /* @@ -974,18 +1430,16 @@ unsigned long flags; runqueue_t *rq; - local_irq_save(flags); - if (p->first_time_slice) { - p->parent->time_slice += p->time_slice; - if (unlikely(p->parent->time_slice > MAX_TIMESLICE)) - p->parent->time_slice = MAX_TIMESLICE; - } - local_irq_restore(flags); /* * If the child was a (relative-) CPU hog then decrease * the sleep_avg of the parent as well. */ rq = task_rq_lock(p->parent, &flags); + if (p->first_time_slice) { + p->parent->time_slice += p->time_slice; + if (unlikely(p->parent->time_slice > task_timeslice(p))) + p->parent->time_slice = task_timeslice(p); + } if (p->sleep_avg < p->parent->sleep_avg) p->parent->sleep_avg = p->parent->sleep_avg / (EXIT_WEIGHT + 1) * EXIT_WEIGHT + p->sleep_avg / @@ -1085,7 +1539,7 @@ { unsigned long i, sum = 0; - for_each_cpu(i) + for_each_online_cpu(i) sum += cpu_rq(i)->nr_running; return sum; @@ -1121,6 +1575,8 @@ return sum; } +#ifdef CONFIG_SMP + /* * double_rq_lock - safely lock two runqueues * @@ -1155,14 +1611,20 @@ spin_unlock(&rq2->lock); } -enum idle_type +/* + * double_lock_balance - lock the busiest runqueue, this_rq is locked already. + */ +static void double_lock_balance(runqueue_t *this_rq, runqueue_t *busiest) { - IDLE, - NOT_IDLE, - NEWLY_IDLE, -}; - -#ifdef CONFIG_SMP + if (unlikely(!spin_trylock(&busiest->lock))) { + if (busiest < this_rq) { + spin_unlock(&this_rq->lock); + spin_lock(&busiest->lock); + spin_lock(&this_rq->lock); + } else + spin_lock(&busiest->lock); + } +} /* * find_idlest_cpu - find the least busy runqueue. @@ -1211,89 +1673,6 @@ } /* - * wake_up_forked_thread - wake up a freshly forked thread. - * - * This function will do some initial scheduler statistics housekeeping - * that must be done for every newly created context, and it also does - * runqueue balancing. - */ -void fastcall wake_up_forked_thread(task_t * p) -{ - unsigned long flags; - int this_cpu = get_cpu(), cpu; - struct sched_domain *tmp, *sd = NULL; - runqueue_t *this_rq = cpu_rq(this_cpu), *rq; - - /* - * Find the largest domain that this CPU is part of that - * is willing to balance on clone: - */ - for_each_domain(this_cpu, tmp) - if (tmp->flags & SD_BALANCE_CLONE) - sd = tmp; - if (sd) - cpu = find_idlest_cpu(p, this_cpu, sd); - else - cpu = this_cpu; - - local_irq_save(flags); -lock_again: - rq = cpu_rq(cpu); - double_rq_lock(this_rq, rq); - - BUG_ON(p->state != TASK_RUNNING); - - /* - * We did find_idlest_cpu() unlocked, so in theory - * the mask could have changed - just dont migrate - * in this case: - */ - if (unlikely(!cpu_isset(cpu, p->cpus_allowed))) { - cpu = this_cpu; - double_rq_unlock(this_rq, rq); - goto lock_again; - } - /* - * We decrease the sleep average of forking parents - * and children as well, to keep max-interactive tasks - * from forking tasks that are max-interactive. - */ - current->sleep_avg = JIFFIES_TO_NS(CURRENT_BONUS(current) * - PARENT_PENALTY / 100 * MAX_SLEEP_AVG / MAX_BONUS); - - p->sleep_avg = JIFFIES_TO_NS(CURRENT_BONUS(p) * - CHILD_PENALTY / 100 * MAX_SLEEP_AVG / MAX_BONUS); - - p->interactive_credit = 0; - - p->prio = effective_prio(p); - set_task_cpu(p, cpu); - - if (cpu == this_cpu) { - if (unlikely(!current->array)) - __activate_task(p, rq); - else { - p->prio = current->prio; - list_add_tail(&p->run_list, ¤t->run_list); - p->array = current->array; - p->array->nr_active++; - rq->nr_running++; - } - } else { - /* Not the local CPU - must adjust timestamp */ - p->timestamp = (p->timestamp - this_rq->timestamp_last_tick) - + rq->timestamp_last_tick; - __activate_task(p, rq); - if (TASK_PREEMPTS_CURR(p, rq)) - resched_task(rq->curr); - } - - double_rq_unlock(this_rq, rq); - local_irq_restore(flags); - put_cpu(); -} - -/* * If dest_cpu is allowed for this process, migrate the task to it. * This is accomplished by forcing the cpu_allowed mask to only * allow dest_cpu, which will force the cpu onto dest_cpu. Then @@ -1310,6 +1689,7 @@ || unlikely(cpu_is_offline(dest_cpu))) goto out; + schedstat_inc(rq, smt_cnt); /* force the process onto the specified CPU */ if (migrate_task(p, dest_cpu, &req)) { /* Need to wait for migration thread (might exit: take ref). */ @@ -1326,17 +1706,18 @@ } /* - * sched_balance_exec(): find the highest-level, exec-balance-capable + * sched_exec(): find the highest-level, exec-balance-capable * domain and try to migrate the task to the least loaded CPU. * * execve() is a valuable balancing opportunity, because at this point * the task has the smallest effective memory and cache footprint. */ -void sched_balance_exec(void) +void sched_exec(void) { struct sched_domain *tmp, *sd = NULL; int new_cpu, this_cpu = get_cpu(); + schedstat_inc(this_rq(), sbe_cnt); /* Prefer the current CPU if there's only this task running */ if (this_rq()->nr_running <= 1) goto out; @@ -1345,9 +1726,11 @@ if (tmp->flags & SD_BALANCE_EXEC) sd = tmp; + schedstat_inc(sd, sbe_attempts); if (sd) { new_cpu = find_idlest_cpu(current, this_cpu, sd); if (new_cpu != this_cpu) { + schedstat_inc(sd, sbe_pushed); put_cpu(); sched_migrate_task(current, new_cpu); return; @@ -1358,21 +1741,6 @@ } /* - * double_lock_balance - lock the busiest runqueue, this_rq is locked already. - */ -static void double_lock_balance(runqueue_t *this_rq, runqueue_t *busiest) -{ - if (unlikely(!spin_trylock(&busiest->lock))) { - if (busiest < this_rq) { - spin_unlock(&this_rq->lock); - spin_lock(&busiest->lock); - spin_lock(&this_rq->lock); - } else - spin_lock(&busiest->lock); - } -} - -/* * pull_task - move a task from a remote runqueue to the local runqueue. * Both runqueues must be locked. */ @@ -1486,6 +1854,15 @@ idx++; goto skip_bitmap; } + + /* + * Right now, this is the only place pull_task() is called, + * so we can safely collect pull_task() stats here rather than + * inside pull_task(). + */ + schedstat_inc(this_rq, pt_gained[idle]); + schedstat_inc(busiest, pt_lost[idle]); + pull_task(busiest, array, tmp, this_rq, dst_array, this_cpu); pulled++; @@ -1680,14 +2057,20 @@ int nr_moved; spin_lock(&this_rq->lock); + schedstat_inc(sd, lb_cnt[idle]); group = find_busiest_group(sd, this_cpu, &imbalance, idle); - if (!group) + if (!group) { + schedstat_inc(sd, lb_nobusyg[idle]); goto out_balanced; + } busiest = find_busiest_queue(group); - if (!busiest) + if (!busiest) { + schedstat_inc(sd, lb_nobusyq[idle]); goto out_balanced; + } + /* * This should be "impossible", but since load * balancing is inherently racy and statistical, @@ -1698,6 +2081,8 @@ goto out_balanced; } + schedstat_add(sd, lb_imbalance[idle], imbalance); + nr_moved = 0; if (busiest->nr_running > 1) { /* @@ -1714,6 +2099,7 @@ spin_unlock(&this_rq->lock); if (!nr_moved) { + schedstat_inc(sd, lb_failed[idle]); sd->nr_balance_failed++; if (unlikely(sd->nr_balance_failed > sd->cache_nice_tries+2)) { @@ -1768,19 +2154,27 @@ unsigned long imbalance; int nr_moved = 0; + schedstat_inc(sd, lb_cnt[NEWLY_IDLE]); group = find_busiest_group(sd, this_cpu, &imbalance, NEWLY_IDLE); - if (!group) + if (!group) { + schedstat_inc(sd, lb_nobusyg[NEWLY_IDLE]); goto out; + } busiest = find_busiest_queue(group); - if (!busiest || busiest == this_rq) + if (!busiest || busiest == this_rq) { + schedstat_inc(sd, lb_nobusyq[NEWLY_IDLE]); goto out; + } /* Attempt to move tasks */ double_lock_balance(this_rq, busiest); + schedstat_add(sd, lb_imbalance[NEWLY_IDLE], imbalance); nr_moved = move_tasks(this_rq, this_cpu, busiest, imbalance, sd, NEWLY_IDLE); + if (!nr_moved) + schedstat_inc(sd, lb_failed[NEWLY_IDLE]); spin_unlock(&busiest->lock); @@ -1820,40 +2214,39 @@ struct sched_group *group, *busy_group; int i; + schedstat_inc(busiest, alb_cnt); if (busiest->nr_running <= 1) return; for_each_domain(busiest_cpu, sd) if (cpu_isset(busiest->push_cpu, sd->span)) break; - if (!sd) { - WARN_ON(1); + if (!sd) return; - } - group = sd->groups; + group = sd->groups; while (!cpu_isset(busiest_cpu, group->cpumask)) - group = group->next; - busy_group = group; + group = group->next; + busy_group = group; - group = sd->groups; - do { + group = sd->groups; + do { cpumask_t tmp; runqueue_t *rq; int push_cpu = 0; - if (group == busy_group) - goto next_group; + if (group == busy_group) + goto next_group; cpus_and(tmp, group->cpumask, cpu_online_map); if (!cpus_weight(tmp)) goto next_group; - for_each_cpu_mask(i, tmp) { + for_each_cpu_mask(i, tmp) { if (!idle_cpu(i)) goto next_group; - push_cpu = i; - } + push_cpu = i; + } rq = cpu_rq(push_cpu); @@ -1866,7 +2259,12 @@ if (unlikely(busiest == rq)) goto next_group; double_lock_balance(busiest, rq); - move_tasks(rq, push_cpu, busiest, 1, sd, IDLE); + if (move_tasks(rq, push_cpu, busiest, 1, sd, IDLE)) { + schedstat_inc(busiest, alb_lost); + schedstat_inc(rq, alb_gained); + } else { + schedstat_inc(busiest, alb_failed); + } spin_unlock(&rq->lock); next_group: group = group->next; @@ -1938,17 +2336,20 @@ static inline int wake_priority_sleeper(runqueue_t *rq) { + int ret = 0; #ifdef CONFIG_SCHED_SMT + spin_lock(&rq->lock); /* * If an SMT sibling task has been put to sleep for priority * reasons reschedule the idle task to see if it can now run. */ if (rq->nr_running) { resched_task(rq->idle); - return 1; + ret = 1; } + spin_unlock(&rq->lock); #endif - return 0; + return ret; } DEFINE_PER_CPU(struct kernel_stat, kstat); @@ -2028,7 +2429,7 @@ * timeslice. This makes it possible for interactive tasks * to use up their timeslices at their highest priority levels. */ - if (unlikely(rt_task(p))) { + if (rt_task(p)) { /* * RR tasks need a special form of timeslice management. * FIFO tasks have no timeslices. @@ -2094,23 +2495,34 @@ } #ifdef CONFIG_SCHED_SMT -static inline void wake_sleeping_dependent(int cpu, runqueue_t *rq) +static inline void wake_sleeping_dependent(int this_cpu, runqueue_t *this_rq) { - int i; - struct sched_domain *sd = rq->sd; + struct sched_domain *sd = this_rq->sd; cpumask_t sibling_map; + int i; if (!(sd->flags & SD_SHARE_CPUPOWER)) return; + /* + * Unlock the current runqueue because we have to lock in + * CPU order to avoid deadlocks. Caller knows that we might + * unlock. We keep IRQs disabled. + */ + spin_unlock(&this_rq->lock); + cpus_and(sibling_map, sd->span, cpu_online_map); - for_each_cpu_mask(i, sibling_map) { - runqueue_t *smt_rq; - if (i == cpu) - continue; + for_each_cpu_mask(i, sibling_map) + spin_lock(&cpu_rq(i)->lock); + /* + * We clear this CPU from the mask. This both simplifies the + * inner loop and keps this_rq locked when we exit: + */ + cpu_clear(this_cpu, sibling_map); - smt_rq = cpu_rq(i); + for_each_cpu_mask(i, sibling_map) { + runqueue_t *smt_rq = cpu_rq(i); /* * If an SMT sibling task is sleeping due to priority @@ -2119,27 +2531,53 @@ if (smt_rq->curr == smt_rq->idle && smt_rq->nr_running) resched_task(smt_rq->idle); } + + for_each_cpu_mask(i, sibling_map) + spin_unlock(&cpu_rq(i)->lock); + /* + * We exit with this_cpu's rq still held and IRQs + * still disabled: + */ } -static inline int dependent_sleeper(int cpu, runqueue_t *rq, task_t *p) +static inline int dependent_sleeper(int this_cpu, runqueue_t *this_rq) { - struct sched_domain *sd = rq->sd; + struct sched_domain *sd = this_rq->sd; cpumask_t sibling_map; + prio_array_t *array; int ret = 0, i; + task_t *p; if (!(sd->flags & SD_SHARE_CPUPOWER)) return 0; + /* + * The same locking rules and details apply as for + * wake_sleeping_dependent(): + */ + spin_unlock(&this_rq->lock); cpus_and(sibling_map, sd->span, cpu_online_map); - for_each_cpu_mask(i, sibling_map) { - runqueue_t *smt_rq; - task_t *smt_curr; + for_each_cpu_mask(i, sibling_map) + spin_lock(&cpu_rq(i)->lock); + cpu_clear(this_cpu, sibling_map); - if (i == cpu) - continue; + /* + * Establish next task to be run - it might have gone away because + * we released the runqueue lock above: + */ + if (!this_rq->nr_running) + goto out_unlock; + array = this_rq->active; + if (!array->nr_active) + array = this_rq->expired; + BUG_ON(!array->nr_active); - smt_rq = cpu_rq(i); - smt_curr = smt_rq->curr; + p = list_entry(array->queue[sched_find_first_bit(array->bitmap)].next, + task_t, run_list); + + for_each_cpu_mask(i, sibling_map) { + runqueue_t *smt_rq = cpu_rq(i); + task_t *smt_curr = smt_rq->curr; /* * If a user task with lower static priority than the @@ -2165,14 +2603,17 @@ (smt_curr == smt_rq->idle && smt_rq->nr_running)) resched_task(smt_curr); } +out_unlock: + for_each_cpu_mask(i, sibling_map) + spin_unlock(&cpu_rq(i)->lock); return ret; } #else -static inline void wake_sleeping_dependent(int cpu, runqueue_t *rq) +static inline void wake_sleeping_dependent(int this_cpu, runqueue_t *this_rq) { } -static inline int dependent_sleeper(int cpu, runqueue_t *rq, task_t *p) +static inline int dependent_sleeper(int this_cpu, runqueue_t *this_rq) { return 0; } @@ -2209,7 +2650,17 @@ prev = current; rq = this_rq(); + /* + * The idle thread is not allowed to schedule! + * Remove this check after it has been exercised a bit. + */ + if (unlikely(current == rq->idle) && current->state != TASK_RUNNING) { + printk(KERN_ERR "bad: scheduling from the idle thread!\n"); + dump_stack(); + } + release_kernel_lock(prev); + schedstat_inc(rq, sched_cnt); now = sched_clock(); if (likely(now - prev->timestamp < NS_MAX_SLEEP_AVG)) run_time = now - prev->timestamp; @@ -2242,13 +2693,33 @@ cpu = smp_processor_id(); if (unlikely(!rq->nr_running)) { +go_idle: idle_balance(cpu, rq); if (!rq->nr_running) { next = rq->idle; rq->expired_timestamp = 0; wake_sleeping_dependent(cpu, rq); + /* + * wake_sleeping_dependent() might have released + * the runqueue, so break out if we got new + * tasks meanwhile: + */ + if (!rq->nr_running) + goto switch_tasks; + } + } else { + if (dependent_sleeper(cpu, rq)) { + schedstat_inc(rq, sched_goidle); + next = rq->idle; goto switch_tasks; } + /* + * dependent_sleeper() releases and reacquires the runqueue + * lock, hence go into the idle loop if the rq went + * empty meanwhile: + */ + if (unlikely(!rq->nr_running)) + goto go_idle; } array = rq->active; @@ -2256,22 +2727,19 @@ /* * Switch the active and expired arrays. */ + schedstat_inc(rq, sched_switch); rq->active = rq->expired; rq->expired = array; array = rq->active; rq->expired_timestamp = 0; rq->best_expired_prio = MAX_PRIO; - } + } else + schedstat_inc(rq, sched_noswitch); idx = sched_find_first_bit(array->bitmap); queue = array->queue + idx; next = list_entry(queue->next, task_t, run_list); - if (dependent_sleeper(cpu, rq, next)) { - next = rq->idle; - goto switch_tasks; - } - if (!rt_task(next) && next->activated > 0) { unsigned long long delta = now - next->timestamp; @@ -2297,6 +2765,7 @@ } prev->timestamp = now; + sched_info_switch(prev, next); if (likely(prev != next)) { next->timestamp = now; rq->nr_switches++; @@ -2313,7 +2782,7 @@ reacquire_kernel_lock(current); preempt_enable_no_resched(); - if (test_thread_flag(TIF_NEED_RESCHED)) + if (unlikely(test_thread_flag(TIF_NEED_RESCHED))) goto need_resched; } @@ -3008,6 +3477,7 @@ prio_array_t *array = current->array; prio_array_t *target = rq->expired; + schedstat_inc(rq, yld_cnt); /* * We implement yielding by moving the task into the expired * queue. @@ -3015,9 +3485,16 @@ * (special rule: RT tasks will just roundrobin in the active * array.) */ - if (unlikely(rt_task(current))) + if (rt_task(current)) target = rq->active; + if (current->array->nr_active == 1) { + schedstat_inc(rq, yld_act_empty); + if (!rq->expired->nr_active) + schedstat_inc(rq, yld_both_empty); + } else if (!rq->expired->nr_active) + schedstat_inc(rq, yld_exp_empty); + dequeue_task(current, array); enqueue_task(current, target); @@ -3268,21 +3745,20 @@ void __devinit init_idle(task_t *idle, int cpu) { - runqueue_t *idle_rq = cpu_rq(cpu), *rq = cpu_rq(task_cpu(idle)); + runqueue_t *rq = cpu_rq(cpu); unsigned long flags; - local_irq_save(flags); - double_rq_lock(idle_rq, rq); - - idle_rq->curr = idle_rq->idle = idle; - deactivate_task(idle, rq); + idle->sleep_avg = 0; + idle->interactive_credit = 0; idle->array = NULL; idle->prio = MAX_PRIO; idle->state = TASK_RUNNING; set_task_cpu(idle, cpu); - double_rq_unlock(idle_rq, rq); + + spin_lock_irqsave(&rq->lock, flags); + rq->curr = rq->idle = idle; set_tsk_need_resched(idle); - local_irq_restore(flags); + spin_unlock_irqrestore(&rq->lock, flags); /* Set the preempt count _outside_ the spinlocks! */ #ifdef CONFIG_PREEMPT @@ -3364,7 +3840,7 @@ * Move (not current) task off this cpu, onto dest cpu. We're doing * this because either it can't run here any more (set_cpus_allowed() * away from this CPU, or CPU going down), or because we're - * attempting to rebalance this task on exec (sched_balance_exec). + * attempting to rebalance this task on exec (sched_exec). * * So we race with normal scheduler movements, but that's OK, as long * as the task is no longer on this CPU. @@ -3376,7 +3852,7 @@ if (unlikely(cpu_is_offline(dest_cpu))) return; - rq_src = cpu_rq(src_cpu); + rq_src = cpu_rq(src_cpu); rq_dest = cpu_rq(dest_cpu); double_rq_lock(rq_src, rq_dest); @@ -3481,7 +3957,7 @@ } #ifdef CONFIG_HOTPLUG_CPU -/* migrate_all_tasks - function to migrate all tasks from the dead cpu. */ +/* migrate_all_tasks - function to migrate all tasks from the dead cpu. */ static void migrate_all_tasks(int src_cpu) { struct task_struct *tsk, *t; @@ -3514,15 +3990,16 @@ cpus_setall(tsk->cpus_allowed); dest_cpu = any_online_cpu(tsk->cpus_allowed); - /* Don't tell them about moving exiting tasks - or kernel threads (both mm NULL), since - they never leave kernel. */ + /* + * Don't tell them about moving exiting tasks + * or kernel threads (both mm NULL), since + * they never leave kernel. + */ if (tsk->mm && printk_ratelimit()) printk(KERN_INFO "process %d (%s) no " "longer affine to cpu%d\n", tsk->pid, tsk->comm, src_cpu); } - __migrate_task(tsk, src_cpu, dest_cpu); } while_each_thread(t, tsk); @@ -3603,7 +4080,7 @@ rq->idle->static_prio = MAX_PRIO; __setscheduler(rq->idle, SCHED_NORMAL, 0); task_rq_unlock(rq, &flags); - BUG_ON(rq->nr_running != 0); + BUG_ON(rq->nr_running != 0); /* No need to migrate the tasks: it was best-effort if * they didn't do lock_cpu_hotplug(). Just wake up @@ -3618,7 +4095,7 @@ complete(&req->done); } spin_unlock_irq(&rq->lock); - break; + break; #endif } return NOTIFY_OK; @@ -3660,7 +4137,7 @@ #ifdef CONFIG_SMP /* Attach the domain 'sd' to 'cpu' as its base domain */ -void cpu_attach_domain(struct sched_domain *sd, int cpu) +static void cpu_attach_domain(struct sched_domain *sd, int cpu) { migration_req_t req; unsigned long flags; @@ -3691,123 +4168,326 @@ unlock_cpu_hotplug(); } -#ifdef ARCH_HAS_SCHED_DOMAIN -extern void __init arch_init_sched_domains(void); -#else -static struct sched_group sched_group_cpus[NR_CPUS]; -static DEFINE_PER_CPU(struct sched_domain, cpu_domains); #ifdef CONFIG_NUMA -static struct sched_group sched_group_nodes[MAX_NUMNODES]; -static DEFINE_PER_CPU(struct sched_domain, node_domains); -static void __init arch_init_sched_domains(void) +/** + * find_next_best_node - find the next node to include in a sched_domain + * @node: node whose sched_domain we're building + * @used_nodes: nodes already in the sched_domain + * + * Find the next node to include in a given scheduling domain. Simply + * finds the closest node not already in the @used_nodes map. + * + * Should use nodemask_t. + */ +static int __init find_next_best_node(int node, unsigned long *used_nodes) +{ + int i, n, val, min_val, best_node = 0; + + min_val = INT_MAX; + + for (i = 0; i < numnodes; i++) { + /* Start at @node */ + n = (node + i) % numnodes; + + /* Skip already used nodes */ + if (test_bit(n, used_nodes)) + continue; + + /* Simple min distance search */ + val = node_distance(node, i); + + if (val < min_val) { + min_val = val; + best_node = n; + } + } + + set_bit(best_node, used_nodes); + return best_node; +} + +/** + * sched_domain_node_span - get a cpumask for a node's sched_domain + * @node: node whose cpumask we're constructing + * @size: number of nodes to include in this span + * + * Given a node, construct a good cpumask for its sched_domain to span. It + * should be one that prevents unnecessary balancing, but also spreads tasks + * out optimally. + */ +cpumask_t __init sched_domain_node_span(int node, int size) { int i; - struct sched_group *first_node = NULL, *last_node = NULL; + cpumask_t span; + DECLARE_BITMAP(used_nodes, MAX_NUMNODES); - /* Set up domains */ - for_each_cpu(i) { - int node = cpu_to_node(i); - cpumask_t nodemask = node_to_cpumask(node); - struct sched_domain *node_sd = &per_cpu(node_domains, i); - struct sched_domain *cpu_sd = &per_cpu(cpu_domains, i); - - *node_sd = SD_NODE_INIT; - node_sd->span = cpu_possible_map; - node_sd->groups = &sched_group_nodes[cpu_to_node(i)]; - - *cpu_sd = SD_CPU_INIT; - cpus_and(cpu_sd->span, nodemask, cpu_possible_map); - cpu_sd->groups = &sched_group_cpus[i]; - cpu_sd->parent = node_sd; + cpus_clear(span); + bitmap_zero(used_nodes, MAX_NUMNODES); + + for (i = 0; i < size; i++) { + int next_node = find_next_best_node(node, used_nodes); + cpumask_t nodemask; + + nodemask = node_to_cpumask(next_node); + cpus_or(span, span, nodemask); } - /* Set up groups */ - for (i = 0; i < MAX_NUMNODES; i++) { - cpumask_t tmp = node_to_cpumask(i); - cpumask_t nodemask; - struct sched_group *first_cpu = NULL, *last_cpu = NULL; - struct sched_group *node = &sched_group_nodes[i]; - int j; + return span; +} +#endif /* CONFIG_NUMA */ + +#ifdef CONFIG_SCHED_SMT +static DEFINE_PER_CPU(struct sched_domain, cpu_domains); +static struct sched_group sched_group_cpus[NR_CPUS]; +__init static int cpu_to_cpu_group(int cpu) +{ + return cpu; +} +#endif + +static DEFINE_PER_CPU(struct sched_domain, phys_domains); +static struct sched_group sched_group_phys[NR_CPUS]; +__init static int cpu_to_phys_group(int cpu) +{ +#ifdef CONFIG_SCHED_SMT + return first_cpu(cpu_sibling_map[cpu]); +#else + return cpu; +#endif +} - cpus_and(nodemask, tmp, cpu_possible_map); +#ifdef CONFIG_NUMA - if (cpus_empty(nodemask)) - continue; +/* Number of nearby nodes in a node's scheduling domain */ +#define SD_NODES_PER_DOMAIN 4 + +static DEFINE_PER_CPU(struct sched_domain, node_domains); +static struct sched_group sched_group_nodes[MAX_NUMNODES]; +__init static int cpu_to_node_group(int cpu) +{ + return cpu_to_node(cpu); +} +#endif - node->cpumask = nodemask; - node->cpu_power = SCHED_LOAD_SCALE * cpus_weight(node->cpumask); +/* Groups for isolated scheduling domains */ +static struct sched_group sched_group_isolated[NR_CPUS]; - for_each_cpu_mask(j, node->cpumask) { - struct sched_group *cpu = &sched_group_cpus[j]; +/* cpus with isolated domains */ +cpumask_t __initdata cpu_isolated_map = CPU_MASK_NONE; + +__init static int cpu_to_isolated_group(int cpu) +{ + return cpu; +} - cpus_clear(cpu->cpumask); - cpu_set(j, cpu->cpumask); - cpu->cpu_power = SCHED_LOAD_SCALE; +/* Setup the mask of cpus configured for isolated domains */ +static int __init isolated_cpu_setup(char *str) +{ + int ints[NR_CPUS], i; - if (!first_cpu) - first_cpu = cpu; - if (last_cpu) - last_cpu->next = cpu; - last_cpu = cpu; - } - last_cpu->next = first_cpu; + str = get_options(str, ARRAY_SIZE(ints), ints); + cpus_clear(cpu_isolated_map); + for (i = 1; i <= ints[0]; i++) + cpu_set(ints[i], cpu_isolated_map); + return 1; +} - if (!first_node) - first_node = node; - if (last_node) - last_node->next = node; - last_node = node; - } - last_node->next = first_node; +__setup ("isolcpus=", isolated_cpu_setup); - mb(); - for_each_cpu(i) { - struct sched_domain *cpu_sd = &per_cpu(cpu_domains, i); - cpu_attach_domain(cpu_sd, i); +/* + * init_sched_build_groups takes an array of groups, the cpumask we wish + * to span, and a pointer to a function which identifies what group a CPU + * belongs to. The return value of group_fn must be a valid index into the + * groups[] array, and must be >= 0 and < NR_CPUS (due to the fact that we + * keep track of groups covered with a cpumask_t). + * + * init_sched_build_groups will build a circular linked list of the groups + * covered by the given span, and will set each group's ->cpumask correctly, + * and ->cpu_power to 0. + */ +__init static void init_sched_build_groups(struct sched_group groups[], + cpumask_t span, int (*group_fn)(int cpu)) +{ + struct sched_group *first = NULL, *last = NULL; + cpumask_t covered = CPU_MASK_NONE; + int i; + + for_each_cpu_mask(i, span) { + int group = group_fn(i); + struct sched_group *sg = &groups[group]; + int j; + + if (cpu_isset(i, covered)) + continue; + + sg->cpumask = CPU_MASK_NONE; + sg->cpu_power = 0; + + for_each_cpu_mask(j, span) { + if (group_fn(j) != group) + continue; + + cpu_set(j, covered); + cpu_set(j, sg->cpumask); + } + if (!first) + first = sg; + if (last) + last->next = sg; + last = sg; } + last->next = first; } -#else /* !CONFIG_NUMA */ -static void __init arch_init_sched_domains(void) +__init static void arch_init_sched_domains(void) { int i; - struct sched_group *first_cpu = NULL, *last_cpu = NULL; + cpumask_t cpu_default_map; + + /* + * Setup mask for cpus without special case scheduling requirements. + * For now this just excludes isolated cpus, but could be used to + * exclude other special cases in the future. + */ + cpus_complement(cpu_default_map, cpu_isolated_map); + cpus_and(cpu_default_map, cpu_default_map, cpu_possible_map); /* Set up domains */ for_each_cpu(i) { - struct sched_domain *cpu_sd = &per_cpu(cpu_domains, i); + int group; + struct sched_domain *sd = NULL, *p; + cpumask_t nodemask = node_to_cpumask(cpu_to_node(i)); + + cpus_and(nodemask, nodemask, cpu_default_map); + + /* + * Set up isolated domains. + * Unlike those of other cpus, the domains and groups are + * single level, and span a single cpu. + */ + if (cpu_isset(i, cpu_isolated_map)) { +#ifdef CONFIG_SCHED_SMT + sd = &per_cpu(cpu_domains, i); +#else + sd = &per_cpu(phys_domains, i); +#endif + group = cpu_to_isolated_group(i); + *sd = SD_CPU_INIT; + cpu_set(i, sd->span); + sd->balance_interval = INT_MAX; /* Don't balance */ + sd->flags = 0; /* Avoid WAKE_ */ + sd->groups = &sched_group_isolated[group]; + printk(KERN_INFO "Setting up cpu %d isolated.\n", i); + /* Single level, so continue with next cpu */ + continue; + } + +#ifdef CONFIG_NUMA + sd = &per_cpu(node_domains, i); + group = cpu_to_node_group(i); + *sd = SD_NODE_INIT; + /* FIXME: should be multilevel, in arch code */ + sd->span = sched_domain_node_span(i, SD_NODES_PER_DOMAIN); + cpus_and(sd->span, sd->span, cpu_default_map); + sd->groups = &sched_group_nodes[group]; +#endif - *cpu_sd = SD_CPU_INIT; - cpu_sd->span = cpu_possible_map; - cpu_sd->groups = &sched_group_cpus[i]; + p = sd; + sd = &per_cpu(phys_domains, i); + group = cpu_to_phys_group(i); + *sd = SD_CPU_INIT; + sd->span = nodemask; + sd->parent = p; + sd->groups = &sched_group_phys[group]; + +#ifdef CONFIG_SCHED_SMT + p = sd; + sd = &per_cpu(cpu_domains, i); + group = cpu_to_cpu_group(i); + *sd = SD_SIBLING_INIT; + sd->span = cpu_sibling_map[i]; + cpus_and(sd->span, sd->span, cpu_default_map); + sd->parent = p; + sd->groups = &sched_group_cpus[group]; +#endif } - /* Set up CPU groups */ - for_each_cpu_mask(i, cpu_possible_map) { - struct sched_group *cpu = &sched_group_cpus[i]; +#ifdef CONFIG_SCHED_SMT + /* Set up CPU (sibling) groups */ + for_each_cpu(i) { + cpumask_t this_sibling_map = cpu_sibling_map[i]; + cpus_and(this_sibling_map, this_sibling_map, cpu_default_map); + if (i != first_cpu(this_sibling_map)) + continue; - cpus_clear(cpu->cpumask); - cpu_set(i, cpu->cpumask); - cpu->cpu_power = SCHED_LOAD_SCALE; + init_sched_build_groups(sched_group_cpus, this_sibling_map, + &cpu_to_cpu_group); + } +#endif - if (!first_cpu) - first_cpu = cpu; - if (last_cpu) - last_cpu->next = cpu; - last_cpu = cpu; + /* Set up isolated groups */ + for_each_cpu_mask(i, cpu_isolated_map) { + cpumask_t mask; + cpus_clear(mask); + cpu_set(i, mask); + init_sched_build_groups(sched_group_isolated, mask, + &cpu_to_isolated_group); } - last_cpu->next = first_cpu; - mb(); /* domains were modified outside the lock */ + /* Set up physical groups */ + for (i = 0; i < MAX_NUMNODES; i++) { + cpumask_t nodemask = node_to_cpumask(i); + + cpus_and(nodemask, nodemask, cpu_default_map); + if (cpus_empty(nodemask)) + continue; + + init_sched_build_groups(sched_group_phys, nodemask, + &cpu_to_phys_group); + } + +#ifdef CONFIG_NUMA + /* Set up node groups */ + init_sched_build_groups(sched_group_nodes, cpu_default_map, + &cpu_to_node_group); +#endif + + /* Calculate CPU power for physical packages and nodes */ + for_each_cpu_mask(i, cpu_default_map) { + int power; + struct sched_domain *sd; +#ifdef CONFIG_SCHED_SMT + sd = &per_cpu(cpu_domains, i); + power = SCHED_LOAD_SCALE; + sd->groups->cpu_power = power; +#endif + + sd = &per_cpu(phys_domains, i); + power = SCHED_LOAD_SCALE + SCHED_LOAD_SCALE * + (cpus_weight(sd->groups->cpumask)-1) / 10; + sd->groups->cpu_power = power; + +#ifdef CONFIG_NUMA + if (i == first_cpu(sd->groups->cpumask)) { + /* Only add "power" once for each physical package. */ + sd = &per_cpu(node_domains, i); + sd->groups->cpu_power += power; + } +#endif + } + + /* Attach the domains */ for_each_cpu(i) { - struct sched_domain *cpu_sd = &per_cpu(cpu_domains, i); - cpu_attach_domain(cpu_sd, i); + struct sched_domain *sd; +#ifdef CONFIG_SCHED_SMT + sd = &per_cpu(cpu_domains, i); +#else + sd = &per_cpu(phys_domains, i); +#endif + cpu_attach_domain(sd, i); } } -#endif /* CONFIG_NUMA */ -#endif /* ARCH_HAS_SCHED_DOMAIN */ - #define SCHED_DOMAIN_DEBUG #ifdef SCHED_DOMAIN_DEBUG void sched_domain_debug(void) @@ -3959,21 +4639,20 @@ __set_bit(MAX_PRIO, array->bitmap); } } - /* - * We have to do a little magic to get the first - * thread right in SMP mode. - */ - rq = this_rq(); - rq->curr = current; - rq->idle = current; - set_task_cpu(current, smp_processor_id()); - wake_up_forked_process(current); /* * The boot idle thread does lazy MMU switching as well: */ atomic_inc(&init_mm.mm_count); enter_lazy_tlb(&init_mm, current); + + /* + * Make us the idle thread. Technically, schedule() should not be + * called from this thread, however somewhere below it might be, + * but because we are the idle thread, we just pick up running again + * when this runqueue becomes "idle". + */ + init_idle(current, smp_processor_id()); } #ifdef CONFIG_DEBUG_SPINLOCK_SLEEP diff -Nru a/kernel/signal.c b/kernel/signal.c --- a/kernel/signal.c 2004-08-25 22:01:55 -07:00 +++ b/kernel/signal.c 2004-08-25 22:01:55 -07:00 @@ -1243,6 +1243,25 @@ force_sig_info(sig, (void*)1L, p); } +/* + * When things go south during signal handling, we + * will force a SIGSEGV. And if the signal that caused + * the problem was already a SIGSEGV, we'll want to + * make sure we don't even try to deliver the signal.. + */ +int +force_sigsegv(int sig, struct task_struct *p) +{ + if (sig == SIGSEGV) { + unsigned long flags; + spin_lock_irqsave(&p->sighand->siglock, flags); + p->sighand->action[sig - 1].sa.sa_handler = SIG_DFL; + spin_unlock_irqrestore(&p->sighand->siglock, flags); + } + force_sig(SIGSEGV, p); + return 0; +} + int kill_pg(pid_t pgrp, int sig, int priv) { @@ -1724,7 +1743,8 @@ return 1; } -int get_signal_to_deliver(siginfo_t *info, struct pt_regs *regs, void *cookie) +int get_signal_to_deliver(siginfo_t *info, struct k_sigaction *return_ka, + struct pt_regs *regs, void *cookie) { sigset_t *mask = ¤t->blocked; int signr = 0; @@ -1793,8 +1813,15 @@ ka = ¤t->sighand->action[signr-1]; if (ka->sa.sa_handler == SIG_IGN) /* Do nothing. */ continue; - if (ka->sa.sa_handler != SIG_DFL) /* Run the handler. */ + if (ka->sa.sa_handler != SIG_DFL) { + /* Run the handler. */ + *return_ka = *ka; + + if (ka->sa.sa_flags & SA_ONESHOT) + ka->sa.sa_handler = SIG_DFL; + break; /* will return non-zero "signr" value */ + } /* * Now we are doing the default action for this signal. diff -Nru a/kernel/sysctl.c b/kernel/sysctl.c --- a/kernel/sysctl.c 2004-08-25 22:01:54 -07:00 +++ b/kernel/sysctl.c 2004-08-25 22:01:54 -07:00 @@ -42,6 +42,7 @@ #include #include +#include #ifdef CONFIG_ROOT_NFS #include @@ -116,12 +117,6 @@ extern int sysctl_hz_timer; -#if defined(CONFIG_PPC32) && defined(CONFIG_6xx) -extern unsigned long powersave_nap; -int proc_dol2crvec(ctl_table *table, int write, struct file *filp, - void __user *buffer, size_t *lenp, loff_t *ppos); -#endif - #ifdef CONFIG_BSD_PROCESS_ACCT extern int acct_parm[]; #endif @@ -149,6 +144,10 @@ extern ctl_table pty_table[]; #endif +#ifdef HAVE_ARCH_PICK_MMAP_LAYOUT +int sysctl_legacy_va_layout; +#endif + /* /proc declarations: */ #ifdef CONFIG_PROC_FS @@ -295,7 +294,7 @@ .procname = "tainted", .data = &tainted, .maxlen = sizeof(int), - .mode = 0644, + .mode = 0444, .proc_handler = &proc_dointvec, }, { @@ -361,22 +360,6 @@ .proc_handler = &proc_dointvec, }, #endif -#if defined(CONFIG_PPC32) && defined(CONFIG_6xx) - { - .ctl_name = KERN_PPC_POWERSAVE_NAP, - .procname = "powersave-nap", - .data = &powersave_nap, - .maxlen = sizeof(int), - .mode = 0644, - .proc_handler = &proc_dointvec, - }, - { - .ctl_name = KERN_PPC_L2CR, - .procname = "l2cr", - .mode = 0644, - .proc_handler = &proc_dol2crvec, - }, -#endif { .ctl_name = KERN_CTLALTDEL, .procname = "ctrl-alt-del", @@ -805,6 +788,18 @@ .strategy = &sysctl_intvec, .extra1 = &zero, }, +#ifdef HAVE_ARCH_PICK_MMAP_LAYOUT + { + .ctl_name = VM_LEGACY_VA_LAYOUT, + .procname = "legacy_va_layout", + .data = &sysctl_legacy_va_layout, + .maxlen = sizeof(sysctl_legacy_va_layout), + .mode = 0644, + .proc_handler = &proc_dointvec, + .strategy = &sysctl_intvec, + .extra1 = &zero, + }, +#endif { .ctl_name = 0 } }; diff -Nru a/lib/Makefile b/lib/Makefile --- a/lib/Makefile 2004-08-25 22:01:54 -07:00 +++ b/lib/Makefile 2004-08-25 22:01:54 -07:00 @@ -5,11 +5,8 @@ lib-y := errno.o ctype.o string.o vsprintf.o cmdline.o \ bust_spinlocks.o rbtree.o radix-tree.o dump_stack.o \ - kobject.o idr.o div64.o parser.o int_sqrt.o \ + kobject.o kref.o idr.o div64.o parser.o int_sqrt.o \ bitmap.o extable.o - -# hack for now till some static code uses krefs, then it can move up above... -obj-y += kref.o lib-$(CONFIG_RWSEM_GENERIC_SPINLOCK) += rwsem-spinlock.o lib-$(CONFIG_RWSEM_XCHGADD_ALGORITHM) += rwsem.o diff -Nru a/lib/kobject.c b/lib/kobject.c --- a/lib/kobject.c 2004-08-25 22:01:56 -07:00 +++ b/lib/kobject.c 2004-08-25 22:01:56 -07:00 @@ -58,14 +58,11 @@ return error; } - static inline struct kobject * to_kobj(struct list_head * entry) { return container_of(entry,struct kobject,entry); } - -#ifdef CONFIG_HOTPLUG static int get_kobj_path_length(struct kset *kset, struct kobject *kobj) { int length = 1; @@ -98,6 +95,31 @@ pr_debug("%s: path = '%s'\n",__FUNCTION__,path); } +/** + * kobject_get_path - generate and return the path associated with a given kobj + * and kset pair. The result must be freed by the caller with kfree(). + * + * @kset: kset in question, with which to build the path + * @kobj: kobject in question, with which to build the path + * @gfp_mask: the allocation type used to allocate the path + */ +char * kobject_get_path(struct kset *kset, struct kobject *kobj, int gfp_mask) +{ + char *path; + int len; + + len = get_kobj_path_length(kset, kobj); + path = kmalloc(len, gfp_mask); + if (!path) + return NULL; + memset(path, 0x00, len); + fill_kobj_path(kset, kobj, path, len); + + return path; +} + +#ifdef CONFIG_HOTPLUG + #define BUFFER_SIZE 1024 /* should be enough memory for the env */ #define NUM_ENVP 32 /* number of env pointers */ static unsigned long sequence_num; @@ -112,7 +134,6 @@ char *scratch; int i = 0; int retval; - int kobj_path_length; char *kobj_path = NULL; char *name = NULL; unsigned long seq; @@ -163,12 +184,9 @@ envp [i++] = scratch; scratch += sprintf(scratch, "SEQNUM=%ld", seq) + 1; - kobj_path_length = get_kobj_path_length (kset, kobj); - kobj_path = kmalloc (kobj_path_length, GFP_KERNEL); + kobj_path = kobject_get_path(kset, kobj, GFP_KERNEL); if (!kobj_path) goto exit; - memset (kobj_path, 0x00, kobj_path_length); - fill_kobj_path (kset, kobj, kobj_path, kobj_path_length); envp [i++] = scratch; scratch += sprintf (scratch, "DEVPATH=%s", kobj_path) + 1; @@ -225,10 +243,9 @@ * kobject_init - initialize object. * @kobj: object in question. */ - void kobject_init(struct kobject * kobj) { - atomic_set(&kobj->refcount,1); + kref_init(&kobj->kref); INIT_LIST_HEAD(&kobj->entry); kobj->kset = kset_get(kobj->kset); } @@ -325,7 +342,7 @@ * @kobj: object. * @name: name. * - * If strlen(name) < KOBJ_NAME_LEN, then use a dynamically allocated + * If strlen(name) >= KOBJ_NAME_LEN, then use a dynamically allocated * string that @kobj->k_name points to. Otherwise, use the static * @kobj->name array. */ @@ -429,10 +446,8 @@ struct kobject * kobject_get(struct kobject * kobj) { - if (kobj) { - WARN_ON(!atomic_read(&kobj->refcount)); - atomic_inc(&kobj->refcount); - } + if (kobj) + kref_get(&kobj->kref); return kobj; } @@ -459,17 +474,21 @@ kobject_put(parent); } +static void kobject_release(struct kref *kref) +{ + kobject_cleanup(container_of(kref, struct kobject, kref)); +} + /** * kobject_put - decrement refcount for object. * @kobj: object. * * Decrement the refcount, and if 0, call kobject_cleanup(). */ - void kobject_put(struct kobject * kobj) { - if (atomic_dec_and_test(&kobj->refcount)) - kobject_cleanup(kobj); + if (kobj) + kref_put(&kobj->kref, kobject_release); } @@ -626,7 +645,7 @@ } } - +EXPORT_SYMBOL(kobject_get_path); EXPORT_SYMBOL(kobject_init); EXPORT_SYMBOL(kobject_register); EXPORT_SYMBOL(kobject_unregister); diff -Nru a/lib/kref.c b/lib/kref.c --- a/lib/kref.c 2004-08-25 22:01:56 -07:00 +++ b/lib/kref.c 2004-08-25 22:01:56 -07:00 @@ -11,48 +11,45 @@ * */ -/* #define DEBUG */ - #include #include /** * kref_init - initialize object. * @kref: object in question. - * @release: pointer to a function that will clean up the object - * when the last reference to the object is released. - * This pointer is required. */ -void kref_init(struct kref *kref, void (*release)(struct kref *kref)) +void kref_init(struct kref *kref) { - WARN_ON(release == NULL); atomic_set(&kref->refcount,1); - kref->release = release; } /** * kref_get - increment refcount for object. * @kref: object. */ -struct kref *kref_get(struct kref *kref) +void kref_get(struct kref *kref) { WARN_ON(!atomic_read(&kref->refcount)); atomic_inc(&kref->refcount); - return kref; } /** * kref_put - decrement refcount for object. * @kref: object. + * @release: pointer to the function that will clean up the object when the + * last reference to the object is released. + * This pointer is required, and it is not acceptable to pass kfree + * in as this function. * - * Decrement the refcount, and if 0, call kref->release(). + * Decrement the refcount, and if 0, call release(). */ -void kref_put(struct kref *kref) +void kref_put(struct kref *kref, void (*release) (struct kref *kref)) { - if (atomic_dec_and_test(&kref->refcount)) { - pr_debug("kref cleaning up\n"); - kref->release(kref); - } + WARN_ON(release == NULL); + WARN_ON(release == (void (*)(struct kref *))kfree); + + if (atomic_dec_and_test(&kref->refcount)) + release(kref); } EXPORT_SYMBOL(kref_init); diff -Nru a/mm/bootmem.c b/mm/bootmem.c --- a/mm/bootmem.c 2004-08-25 22:01:55 -07:00 +++ b/mm/bootmem.c 2004-08-25 22:01:55 -07:00 @@ -259,6 +259,7 @@ unsigned long i, count, total = 0; unsigned long idx; unsigned long *map; + int gofast = 0; BUG_ON(!bdata->node_bootmem_map); @@ -267,14 +268,32 @@ page = virt_to_page(phys_to_virt(bdata->node_boot_start)); idx = bdata->node_low_pfn - (bdata->node_boot_start >> PAGE_SHIFT); map = bdata->node_bootmem_map; + /* Check physaddr is O(LOG2(BITS_PER_LONG)) page aligned */ + if (bdata->node_boot_start == 0 || + ffs(bdata->node_boot_start) - PAGE_SHIFT > ffs(BITS_PER_LONG)) + gofast = 1; for (i = 0; i < idx; ) { unsigned long v = ~map[i / BITS_PER_LONG]; - if (v) { + if (gofast && v == ~0UL) { + int j; + + count += BITS_PER_LONG; + __ClearPageReserved(page); + set_page_count(page, 1); + for (j = 1; j < BITS_PER_LONG; j++) { + if (j + 16 < BITS_PER_LONG) + prefetchw(page + j + 16); + __ClearPageReserved(page + j); + } + __free_pages(page, ffs(BITS_PER_LONG)-1); + i += BITS_PER_LONG; + page += BITS_PER_LONG; + } else if (v) { unsigned long m; for (m = 1; m && i < idx; m<<=1, page++, i++) { if (v & m) { count++; - ClearPageReserved(page); + __ClearPageReserved(page); set_page_count(page, 1); __free_page(page); } @@ -294,7 +313,7 @@ count = 0; for (i = 0; i < ((bdata->node_low_pfn-(bdata->node_boot_start >> PAGE_SHIFT))/8 + PAGE_SIZE-1)/PAGE_SIZE; i++,page++) { count++; - ClearPageReserved(page); + __ClearPageReserved(page); set_page_count(page, 1); __free_page(page); } diff -Nru a/mm/filemap.c b/mm/filemap.c --- a/mm/filemap.c 2004-08-25 22:01:56 -07:00 +++ b/mm/filemap.c 2004-08-25 22:01:56 -07:00 @@ -60,7 +60,6 @@ * ->swap_list_lock * ->swap_device_lock (exclusive_swap_page, others) * ->mapping->tree_lock - * ->page_map_lock() (try_to_unmap_file) * * ->i_sem * ->i_mmap_lock (truncate->unmap_mapping_range) @@ -83,16 +82,20 @@ * ->sb_lock (fs/fs-writeback.c) * ->mapping->tree_lock (__sync_single_inode) * + * ->i_mmap_lock + * ->anon_vma.lock (vma_adjust) + * + * ->anon_vma.lock + * ->page_table_lock (anon_vma_prepare and various) + * * ->page_table_lock * ->swap_device_lock (try_to_unmap_one) * ->private_lock (try_to_unmap_one) * ->tree_lock (try_to_unmap_one) * ->zone.lru_lock (follow_page->mark_page_accessed) - * ->page_map_lock() (page_add_anon_rmap) - * ->tree_lock (page_remove_rmap->set_page_dirty) - * ->private_lock (page_remove_rmap->set_page_dirty) - * ->inode_lock (page_remove_rmap->set_page_dirty) - * ->anon_vma.lock (anon_vma_prepare) + * ->private_lock (page_remove_rmap->set_page_dirty) + * ->tree_lock (page_remove_rmap->set_page_dirty) + * ->inode_lock (page_remove_rmap->set_page_dirty) * ->inode_lock (zap_pte_range->set_page_dirty) * ->private_lock (zap_pte_range->__set_page_dirty_buffers) * diff -Nru a/mm/hugetlb.c b/mm/hugetlb.c --- a/mm/hugetlb.c 2004-08-25 22:01:55 -07:00 +++ b/mm/hugetlb.c 2004-08-25 22:01:55 -07:00 @@ -123,6 +123,7 @@ } __setup("hugepages=", hugetlb_setup); +#ifdef CONFIG_SYSCTL static void update_and_free_page(struct page *page) { int i; @@ -188,7 +189,6 @@ return nr_huge_pages; } -#ifdef CONFIG_SYSCTL int hugetlb_sysctl_handler(struct ctl_table *table, int write, struct file *file, void __user *buffer, size_t *length, loff_t *ppos) diff -Nru a/mm/mempolicy.c b/mm/mempolicy.c --- a/mm/mempolicy.c 2004-08-25 22:01:56 -07:00 +++ b/mm/mempolicy.c 2004-08-25 22:01:56 -07:00 @@ -132,7 +132,6 @@ unsigned long nlongs; unsigned long endmask; - --maxnode; bitmap_zero(nodes, MAX_NUMNODES); if (maxnode == 0 || !nmask) return 0; diff -Nru a/mm/mmap.c b/mm/mmap.c --- a/mm/mmap.c 2004-08-25 22:01:55 -07:00 +++ b/mm/mmap.c 2004-08-25 22:01:55 -07:00 @@ -1018,7 +1018,7 @@ * This function "knows" that -ENOMEM has the bits set. */ #ifndef HAVE_ARCH_UNMAPPED_AREA -static inline unsigned long +unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsigned long len, unsigned long pgoff, unsigned long flags) { @@ -1062,12 +1062,116 @@ addr = vma->vm_end; } } -#else -extern unsigned long -arch_get_unmapped_area(struct file *, unsigned long, unsigned long, - unsigned long, unsigned long); #endif +void arch_unmap_area(struct vm_area_struct *area) +{ + /* + * Is this a new hole at the lowest possible address? + */ + if (area->vm_start >= TASK_UNMAPPED_BASE && + area->vm_start < area->vm_mm->free_area_cache) + area->vm_mm->free_area_cache = area->vm_start; +} + +/* + * This mmap-allocator allocates new areas top-down from below the + * stack's low limit (the base): + */ +unsigned long +arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, + const unsigned long len, const unsigned long pgoff, + const unsigned long flags) +{ + struct vm_area_struct *vma, *prev_vma; + struct mm_struct *mm = current->mm; + unsigned long base = mm->mmap_base, addr = addr0; + int first_time = 1; + + /* requested length too big for entire address space */ + if (len > TASK_SIZE) + return -ENOMEM; + + /* dont allow allocations above current base */ + if (mm->free_area_cache > base) + mm->free_area_cache = base; + + /* requesting a specific address */ + if (addr) { + addr = PAGE_ALIGN(addr); + vma = find_vma(mm, addr); + if (TASK_SIZE - len >= addr && + (!vma || addr + len <= vma->vm_start)) + return addr; + } + +try_again: + /* make sure it can fit in the remaining address space */ + if (mm->free_area_cache < len) + goto fail; + + /* either no address requested or cant fit in requested address hole */ + addr = (mm->free_area_cache - len) & PAGE_MASK; + do { + /* + * Lookup failure means no vma is above this address, + * i.e. return with success: + */ + if (!(vma = find_vma_prev(mm, addr, &prev_vma))) + return addr; + + /* + * new region fits between prev_vma->vm_end and + * vma->vm_start, use it: + */ + if (addr+len <= vma->vm_start && + (!prev_vma || (addr >= prev_vma->vm_end))) + /* remember the address as a hint for next time */ + return (mm->free_area_cache = addr); + else + /* pull free_area_cache down to the first hole */ + if (mm->free_area_cache == vma->vm_end) + mm->free_area_cache = vma->vm_start; + + /* try just below the current vma->vm_start */ + addr = vma->vm_start-len; + } while (len <= vma->vm_start); + +fail: + /* + * if hint left us with no space for the requested + * mapping then try again: + */ + if (first_time) { + mm->free_area_cache = base; + first_time = 0; + goto try_again; + } + /* + * A failed mmap() very likely causes application failure, + * so fall back to the bottom-up function here. This scenario + * can happen with large stack limits and large mmap() + * allocations. + */ + mm->free_area_cache = TASK_UNMAPPED_BASE; + addr = arch_get_unmapped_area(filp, addr0, len, pgoff, flags); + /* + * Restore the topdown base: + */ + mm->free_area_cache = base; + + return addr; +} + +void arch_unmap_area_topdown(struct vm_area_struct *area) +{ + /* + * Is this a new hole at the highest possible address? + */ + if (area->vm_end > area->vm_mm->free_area_cache) + area->vm_mm->free_area_cache = area->vm_end; +} + unsigned long get_unmapped_area(struct file *file, unsigned long addr, unsigned long len, unsigned long pgoff, unsigned long flags) @@ -1102,7 +1206,7 @@ return file->f_op->get_unmapped_area(file, addr, len, pgoff, flags); - return arch_get_unmapped_area(file, addr, len, pgoff, flags); + return current->mm->get_unmapped_area(file, addr, len, pgoff, flags); } EXPORT_SYMBOL(get_unmapped_area); @@ -1392,13 +1496,7 @@ area->vm_mm->total_vm -= len >> PAGE_SHIFT; if (area->vm_flags & VM_LOCKED) area->vm_mm->locked_vm -= len >> PAGE_SHIFT; - /* - * Is this a new hole at the lowest possible address? - */ - if (area->vm_start >= TASK_UNMAPPED_BASE && - area->vm_start < area->vm_mm->free_area_cache) - area->vm_mm->free_area_cache = area->vm_start; - + area->vm_mm->unmap_area(area); remove_vm_struct(area); } diff -Nru a/mm/page-writeback.c b/mm/page-writeback.c --- a/mm/page-writeback.c 2004-08-25 22:01:55 -07:00 +++ b/mm/page-writeback.c 2004-08-25 22:01:55 -07:00 @@ -153,9 +153,11 @@ if (dirty_ratio < 5) dirty_ratio = 5; - background_ratio = dirty_background_ratio; - if (background_ratio >= dirty_ratio) - background_ratio = dirty_ratio / 2; + /* + * Keep the ratio between dirty_ratio and background_ratio roughly + * what the sysctls are after dirty_ratio has been scaled (above). + */ + background_ratio = dirty_background_ratio * dirty_ratio/vm_dirty_ratio; background = (background_ratio * total_pages) / 100; dirty = (dirty_ratio * total_pages) / 100; diff -Nru a/mm/page_alloc.c b/mm/page_alloc.c --- a/mm/page_alloc.c 2004-08-25 22:01:54 -07:00 +++ b/mm/page_alloc.c 2004-08-25 22:01:54 -07:00 @@ -78,7 +78,7 @@ function, current->comm, page); printk(KERN_EMERG "flags:0x%08lx mapping:%p mapcount:%d count:%d\n", (unsigned long)page->flags, page->mapping, - (int)page->mapcount, page_count(page)); + page_mapcount(page), page_count(page)); printk(KERN_EMERG "Backtrace:\n"); dump_stack(); printk(KERN_EMERG "Trying to fix it up, but a reboot is needed\n"); @@ -87,13 +87,11 @@ 1 << PG_lru | 1 << PG_active | 1 << PG_dirty | - 1 << PG_maplock | - 1 << PG_anon | 1 << PG_swapcache | 1 << PG_writeback); set_page_count(page, 0); + reset_page_mapcount(page); page->mapping = NULL; - page->mapcount = 0; } #ifndef CONFIG_HUGETLB_PAGE @@ -229,8 +227,6 @@ 1 << PG_active | 1 << PG_reclaim | 1 << PG_slab | - 1 << PG_maplock | - 1 << PG_anon | 1 << PG_swapcache | 1 << PG_writeback ))) bad_page(function, page); @@ -279,6 +275,8 @@ LIST_HEAD(list); int i; + arch_free_page(page, order); + mod_page_state(pgfree, 1 << order); for (i = 0 ; i < (1 << order) ; ++i) free_pages_check(__FUNCTION__, page + i); @@ -350,8 +348,6 @@ 1 << PG_active | 1 << PG_dirty | 1 << PG_reclaim | - 1 << PG_maplock | - 1 << PG_anon | 1 << PG_swapcache | 1 << PG_writeback ))) bad_page(__FUNCTION__, page); @@ -509,8 +505,12 @@ struct per_cpu_pages *pcp; unsigned long flags; + arch_free_page(page, 0); + kernel_map_pages(page, 1, 0); inc_page_state(pgfree); + if (PageAnon(page)) + page->mapping = NULL; free_pages_check(__FUNCTION__, page); pcp = &zone->pageset[get_cpu()].pcp[cold]; local_irq_save(flags); @@ -600,83 +600,75 @@ { const int wait = gfp_mask & __GFP_WAIT; unsigned long min; - struct zone **zones; + struct zone **zones, *z; struct page *page; struct reclaim_state reclaim_state; struct task_struct *p = current; int i; int alloc_type; int do_retry; + int can_try_harder; might_sleep_if(wait); + /* + * The caller may dip into page reserves a bit more if the caller + * cannot run direct reclaim, or is the caller has realtime scheduling + * policy + */ + can_try_harder = (unlikely(rt_task(p)) && !in_interrupt()) || !wait; + zones = zonelist->zones; /* the list of zones suitable for gfp_mask */ - if (zones[0] == NULL) /* no zones in the zonelist */ + + if (unlikely(zones[0] == NULL)) { + /* Should this ever happen?? */ return NULL; + } alloc_type = zone_idx(zones[0]); /* Go through the zonelist once, looking for a zone with enough free */ - for (i = 0; zones[i] != NULL; i++) { - struct zone *z = zones[i]; - - min = (1<protection[alloc_type]; + for (i = 0; (z = zones[i]) != NULL; i++) { + min = z->pages_low + (1<protection[alloc_type]; - /* - * We let real-time tasks dip their real-time paws a little - * deeper into reserves. - */ - if (rt_task(p)) - min -= z->pages_low >> 1; + if (z->free_pages < min) + continue; - if (z->free_pages >= min || - (!wait && z->free_pages >= z->pages_high)) { - page = buffered_rmqueue(z, order, gfp_mask); - if (page) { - zone_statistics(zonelist, z); - goto got_pg; - } - } + page = buffered_rmqueue(z, order, gfp_mask); + if (page) + goto got_pg; } - /* we're somewhat low on memory, failed to find what we needed */ - for (i = 0; zones[i] != NULL; i++) - wakeup_kswapd(zones[i]); - - /* Go through the zonelist again, taking __GFP_HIGH into account */ - for (i = 0; zones[i] != NULL; i++) { - struct zone *z = zones[i]; - - min = (1<protection[alloc_type]; + for (i = 0; (z = zones[i]) != NULL; i++) + wakeup_kswapd(z); + /* + * Go through the zonelist again. Let __GFP_HIGH and allocations + * coming from realtime tasks to go deeper into reserves + */ + for (i = 0; (z = zones[i]) != NULL; i++) { + min = z->pages_min; if (gfp_mask & __GFP_HIGH) - min -= z->pages_low >> 2; - if (rt_task(p)) - min -= z->pages_low >> 1; + min /= 2; + if (can_try_harder) + min -= min / 4; + min += (1<protection[alloc_type]; - if (z->free_pages >= min || - (!wait && z->free_pages >= z->pages_high)) { - page = buffered_rmqueue(z, order, gfp_mask); - if (page) { - zone_statistics(zonelist, z); - goto got_pg; - } - } - } + if (z->free_pages < min) + continue; - /* here we're in the low on memory slow path */ + page = buffered_rmqueue(z, order, gfp_mask); + if (page) + goto got_pg; + } -rebalance: + /* This allocation should allow future memory freeing. */ if ((p->flags & (PF_MEMALLOC | PF_MEMDIE)) && !in_interrupt()) { /* go through the zonelist yet again, ignoring mins */ - for (i = 0; zones[i] != NULL; i++) { - struct zone *z = zones[i]; - + for (i = 0; (z = zones[i]) != NULL; i++) { page = buffered_rmqueue(z, order, gfp_mask); - if (page) { - zone_statistics(zonelist, z); + if (page) goto got_pg; - } } goto nopage; } @@ -685,6 +677,8 @@ if (!wait) goto nopage; +rebalance: + /* We now go into synchronous reclaim */ p->flags |= PF_MEMALLOC; reclaim_state.reclaimed_slab = 0; p->reclaim_state = &reclaim_state; @@ -695,27 +689,28 @@ p->flags &= ~PF_MEMALLOC; /* go through the zonelist yet one more time */ - for (i = 0; zones[i] != NULL; i++) { - struct zone *z = zones[i]; + for (i = 0; (z = zones[i]) != NULL; i++) { + min = z->pages_min; + if (gfp_mask & __GFP_HIGH) + min /= 2; + if (can_try_harder) + min -= min / 4; + min += (1<protection[alloc_type]; - min = (1UL << order) + z->protection[alloc_type]; + if (z->free_pages < min) + continue; - if (z->free_pages >= min || - (!wait && z->free_pages >= z->pages_high)) { - page = buffered_rmqueue(z, order, gfp_mask); - if (page) { - zone_statistics(zonelist, z); - goto got_pg; - } - } + page = buffered_rmqueue(z, order, gfp_mask); + if (page) + goto got_pg; } /* * Don't let big-order allocations loop unless the caller explicitly * requests that. Wait for some write requests to complete then retry. * - * In this implementation, __GFP_REPEAT means __GFP_NOFAIL, but that - * may not be true in other implementations. + * In this implementation, __GFP_REPEAT means __GFP_NOFAIL for order + * <= 3, but that may not be true in other implementations. */ do_retry = 0; if (!(gfp_mask & __GFP_NORETRY)) { @@ -738,6 +733,7 @@ } return NULL; got_pg: + zone_statistics(zonelist, z); kernel_map_pages(page, 1 << order, 1); return page; } @@ -965,18 +961,36 @@ return ret; } +void __get_zone_counts(unsigned long *active, unsigned long *inactive, + unsigned long *free, struct pglist_data *pgdat) +{ + struct zone *zones = pgdat->node_zones; + int i; + + *active = 0; + *inactive = 0; + *free = 0; + for (i = 0; i < MAX_NR_ZONES; i++) { + *active += zones[i].nr_active; + *inactive += zones[i].nr_inactive; + *free += zones[i].free_pages; + } +} + void get_zone_counts(unsigned long *active, unsigned long *inactive, unsigned long *free) { - struct zone *zone; + struct pglist_data *pgdat; *active = 0; *inactive = 0; *free = 0; - for_each_zone(zone) { - *active += zone->nr_active; - *inactive += zone->nr_inactive; - *free += zone->free_pages; + for_each_pgdat(pgdat) { + unsigned long l, m, n; + __get_zone_counts(&l, &m, &n, pgdat); + *active += l; + *inactive += m; + *free += n; } } @@ -1379,14 +1393,16 @@ * up by free_all_bootmem() once the early boot process is * done. Non-atomic initialization, single-pass. */ -void __init memmap_init_zone(struct page *start, unsigned long size, int nid, - unsigned long zone, unsigned long start_pfn) +void __init memmap_init_zone(unsigned long size, int nid, unsigned long zone, + unsigned long start_pfn) { + struct page *start = pfn_to_page(start_pfn); struct page *page; for (page = start; page < (start + size); page++) { set_page_zone(page, NODEZONE(nid, zone)); set_page_count(page, 0); + reset_page_mapcount(page); SetPageReserved(page); INIT_LIST_HEAD(&page->lru); #ifdef WANT_PAGE_VIRTUAL @@ -1445,8 +1461,8 @@ } #ifndef __HAVE_ARCH_MEMMAP_INIT -#define memmap_init(start, size, nid, zone, start_pfn) \ - memmap_init_zone((start), (size), (nid), (zone), (start_pfn)) +#define memmap_init(size, nid, zone, start_pfn) \ + memmap_init_zone((size), (nid), (zone), (start_pfn)) #endif /* @@ -1461,7 +1477,6 @@ unsigned long i, j; const unsigned long zone_required_alignment = 1UL << (MAX_ORDER-1); int cpu, nid = pgdat->node_id; - struct page *lmem_map = pgdat->node_mem_map; unsigned long zone_start_pfn = pgdat->node_start_pfn; pgdat->nr_zones = 0; @@ -1549,35 +1564,41 @@ pgdat->nr_zones = j+1; - zone->zone_mem_map = lmem_map; + zone->zone_mem_map = pfn_to_page(zone_start_pfn); zone->zone_start_pfn = zone_start_pfn; if ((zone_start_pfn) & (zone_required_alignment-1)) printk("BUG: wrong zone alignment, it will crash\n"); - memmap_init(lmem_map, size, nid, j, zone_start_pfn); + memmap_init(size, nid, j, zone_start_pfn); zone_start_pfn += size; - lmem_map += size; zone_init_free_lists(pgdat, zone, zone->spanned_pages); } } -void __init free_area_init_node(int nid, struct pglist_data *pgdat, - struct page *node_mem_map, unsigned long *zones_size, - unsigned long node_start_pfn, unsigned long *zholes_size) +void __init node_alloc_mem_map(struct pglist_data *pgdat) { unsigned long size; + size = (pgdat->node_spanned_pages + 1) * sizeof(struct page); + pgdat->node_mem_map = alloc_bootmem_node(pgdat, size); +#ifndef CONFIG_DISCONTIGMEM + mem_map = contig_page_data.node_mem_map; +#endif +} + +void __init free_area_init_node(int nid, struct pglist_data *pgdat, + unsigned long *zones_size, unsigned long node_start_pfn, + unsigned long *zholes_size) +{ pgdat->node_id = nid; pgdat->node_start_pfn = node_start_pfn; calculate_zone_totalpages(pgdat, zones_size, zholes_size); - if (!node_mem_map) { - size = (pgdat->node_spanned_pages + 1) * sizeof(struct page); - node_mem_map = alloc_bootmem_node(pgdat, size); - } - pgdat->node_mem_map = node_mem_map; + + if (!pfn_to_page(node_start_pfn)) + node_alloc_mem_map(pgdat); free_area_init_core(pgdat, zones_size, zholes_size); } @@ -1590,9 +1611,8 @@ void __init free_area_init(unsigned long *zones_size) { - free_area_init_node(0, &contig_page_data, NULL, zones_size, + free_area_init_node(0, &contig_page_data, zones_size, __pa(PAGE_OFFSET) >> PAGE_SHIFT, NULL); - mem_map = contig_page_data.node_mem_map; } #endif @@ -1851,11 +1871,11 @@ * We never protect zones that don't have memory * in them (j>max_zone) or zones that aren't in * the zonelists for a certain type of - * allocation (j>i). We have to assign these to - * zero because the lower zones take + * allocation (j>=i). We have to assign these + * to zero because the lower zones take * contributions from the higher zones. */ - if (j > max_zone || j > i) { + if (j > max_zone || j >= i) { zone->protection[i] = 0; continue; } @@ -1864,7 +1884,6 @@ */ zone->protection[i] = higherzone_val(zone, max_zone, i); - zone->protection[i] += zone->pages_low; } } } diff -Nru a/mm/readahead.c b/mm/readahead.c --- a/mm/readahead.c 2004-08-25 22:01:54 -07:00 +++ b/mm/readahead.c 2004-08-25 22:01:54 -07:00 @@ -28,16 +28,15 @@ EXPORT_SYMBOL_GPL(default_backing_dev_info); /* - * Initialise a struct file's readahead state + * Initialise a struct file's readahead state. Assumes that the caller has + * memset *ra to zero. */ void file_ra_state_init(struct file_ra_state *ra, struct address_space *mapping) { - memset(ra, 0, sizeof(*ra)); ra->ra_pages = mapping->backing_dev_info->ra_pages; ra->average = ra->ra_pages / 2; } -EXPORT_SYMBOL(file_ra_state_init); /* * Return max readahead size for this inode in number-of-pages. @@ -572,6 +571,6 @@ unsigned long inactive; unsigned long free; - get_zone_counts(&active, &inactive, &free); + __get_zone_counts(&active, &inactive, &free, NODE_DATA(numa_node_id())); return min(nr, (inactive + free) / 2); } diff -Nru a/mm/rmap.c b/mm/rmap.c --- a/mm/rmap.c 2004-08-25 22:01:56 -07:00 +++ b/mm/rmap.c 2004-08-25 22:01:56 -07:00 @@ -18,9 +18,30 @@ */ /* - * Locking: see "Lock ordering" summary in filemap.c. - * In swapout, page_map_lock is held on entry to page_referenced and - * try_to_unmap, so they trylock for i_mmap_lock and page_table_lock. + * Lock ordering in mm: + * + * inode->i_sem (while writing or truncating, not reading or faulting) + * inode->i_alloc_sem + * + * When a page fault occurs in writing from user to file, down_read + * of mmap_sem nests within i_sem; in sys_msync, i_sem nests within + * down_read of mmap_sem; i_sem and down_write of mmap_sem are never + * taken together; in truncation, i_sem is taken outermost. + * + * mm->mmap_sem + * page->flags PG_locked (lock_page) + * mapping->i_mmap_lock + * anon_vma->lock + * mm->page_table_lock + * zone->lru_lock (in mark_page_accessed) + * swap_list_lock (in swap_free etc's swap_info_get) + * swap_device_lock (in swap_duplicate, swap_info_get) + * mapping->private_lock (in __set_page_dirty_buffers) + * inode_lock (in set_page_dirty's __mark_inode_dirty) + * sb_lock (within inode_lock in fs/fs-writeback.c) + * mapping->tree_lock (widely used, in set_page_dirty, + * in arch-dependent flush_dcache_mmap_lock, + * within inode_lock in __sync_single_inode) */ #include @@ -30,6 +51,7 @@ #include #include #include +#include #include @@ -63,28 +85,32 @@ might_sleep(); if (unlikely(!anon_vma)) { struct mm_struct *mm = vma->vm_mm; - struct anon_vma *allocated = NULL; + struct anon_vma *allocated, *locked; anon_vma = find_mergeable_anon_vma(vma); - if (!anon_vma) { + if (anon_vma) { + allocated = NULL; + locked = anon_vma; + spin_lock(&locked->lock); + } else { anon_vma = anon_vma_alloc(); if (unlikely(!anon_vma)) return -ENOMEM; allocated = anon_vma; + locked = NULL; } /* page_table_lock to protect against threads */ spin_lock(&mm->page_table_lock); if (likely(!vma->anon_vma)) { - if (!allocated) - spin_lock(&anon_vma->lock); vma->anon_vma = anon_vma; list_add(&vma->anon_vma_node, &anon_vma->head); - if (!allocated) - spin_unlock(&anon_vma->lock); allocated = NULL; } spin_unlock(&mm->page_table_lock); + + if (locked) + spin_unlock(&locked->lock); if (unlikely(allocated)) anon_vma_free(allocated); } @@ -159,16 +185,31 @@ void __init anon_vma_init(void) { - anon_vma_cachep = kmem_cache_create("anon_vma", - sizeof(struct anon_vma), 0, SLAB_PANIC, anon_vma_ctor, NULL); + anon_vma_cachep = kmem_cache_create("anon_vma", sizeof(struct anon_vma), + 0, SLAB_DESTROY_BY_RCU|SLAB_PANIC, anon_vma_ctor, NULL); } -/* this needs the page->flags PG_maplock held */ -static inline void clear_page_anon(struct page *page) +/* + * Getting a lock on a stable anon_vma from a page off the LRU is + * tricky: page_lock_anon_vma rely on RCU to guard against the races. + */ +static struct anon_vma *page_lock_anon_vma(struct page *page) { - BUG_ON(!page->mapping); - page->mapping = NULL; - ClearPageAnon(page); + struct anon_vma *anon_vma = NULL; + unsigned long anon_mapping; + + rcu_read_lock(); + anon_mapping = (unsigned long) page->mapping; + if (!(anon_mapping & PAGE_MAPPING_ANON)) + goto out; + if (!page_mapped(page)) + goto out; + + anon_vma = (struct anon_vma *) (anon_mapping - PAGE_MAPPING_ANON); + spin_lock(&anon_vma->lock); +out: + rcu_read_unlock(); + return anon_vma; } /* @@ -190,6 +231,24 @@ } /* + * At what user virtual address is page expected in vma? checking that the + * page matches the vma: currently only used by unuse_process, on anon pages. + */ +unsigned long page_address_in_vma(struct page *page, struct vm_area_struct *vma) +{ + if (PageAnon(page)) { + if ((void *)vma->anon_vma != + (void *)page->mapping - PAGE_MAPPING_ANON) + return -EFAULT; + } else if (page->mapping && !(vma->vm_flags & VM_NONLINEAR)) { + if (vma->vm_file->f_mapping != page->mapping) + return -EFAULT; + } else + return -EFAULT; + return vma_address(page, vma); +} + +/* * Subfunctions of page_referenced: page_referenced_one called * repeatedly from either page_referenced_anon or page_referenced_file. */ @@ -209,8 +268,7 @@ if (address == -EFAULT) goto out; - if (!spin_trylock(&mm->page_table_lock)) - goto out; + spin_lock(&mm->page_table_lock); pgd = pgd_offset(mm, address); if (!pgd_present(*pgd)) @@ -243,15 +301,18 @@ return referenced; } -static inline int page_referenced_anon(struct page *page) +static int page_referenced_anon(struct page *page) { - unsigned int mapcount = page->mapcount; - struct anon_vma *anon_vma = (struct anon_vma *) page->mapping; + unsigned int mapcount; + struct anon_vma *anon_vma; struct vm_area_struct *vma; int referenced = 0; - spin_lock(&anon_vma->lock); - BUG_ON(list_empty(&anon_vma->head)); + anon_vma = page_lock_anon_vma(page); + if (!anon_vma) + return referenced; + + mapcount = page_mapcount(page); list_for_each_entry(vma, &anon_vma->head, anon_vma_node) { referenced += page_referenced_one(page, vma, &mapcount); if (!mapcount) @@ -271,21 +332,38 @@ * of references it found. * * This function is only called from page_referenced for object-based pages. - * - * The spinlock address_space->i_mmap_lock is tried. If it can't be gotten, - * assume a reference count of 0, so try_to_unmap will then have a go. */ -static inline int page_referenced_file(struct page *page) +static int page_referenced_file(struct page *page) { - unsigned int mapcount = page->mapcount; + unsigned int mapcount; struct address_space *mapping = page->mapping; pgoff_t pgoff = page->index << (PAGE_CACHE_SHIFT - PAGE_SHIFT); struct vm_area_struct *vma; struct prio_tree_iter iter; int referenced = 0; - if (!spin_trylock(&mapping->i_mmap_lock)) - return 0; + /* + * The caller's checks on page->mapping and !PageAnon have made + * sure that this is a file page: the check for page->mapping + * excludes the case just before it gets set on an anon page. + */ + BUG_ON(PageAnon(page)); + + /* + * The page lock not only makes sure that page->mapping cannot + * suddenly be NULLified by truncation, it makes sure that the + * structure at mapping cannot be freed and reused yet, + * so we can safely take mapping->i_mmap_lock. + */ + BUG_ON(!PageLocked(page)); + + spin_lock(&mapping->i_mmap_lock); + + /* + * i_mmap_lock does not stabilize mapcount at all, but mapcount + * is more likely to be accurate if we note it after spinning. + */ + mapcount = page_mapcount(page); vma_prio_tree_foreach(vma, &iter, &mapping->i_mmap, pgoff, pgoff) { if ((vma->vm_flags & (VM_LOCKED|VM_MAYSHARE)) @@ -305,12 +383,12 @@ /** * page_referenced - test if the page was referenced * @page: the page to test + * @is_locked: caller holds lock on the page * * Quick test_and_clear_referenced for all mappings to a page, * returns the number of ptes which referenced the page. - * Caller needs to hold the rmap lock. */ -int page_referenced(struct page *page) +int page_referenced(struct page *page, int is_locked) { int referenced = 0; @@ -320,11 +398,17 @@ if (TestClearPageReferenced(page)) referenced++; - if (page->mapcount && page->mapping) { + if (page_mapped(page) && page->mapping) { if (PageAnon(page)) referenced += page_referenced_anon(page); - else + else if (is_locked) + referenced += page_referenced_file(page); + else if (TestSetPageLocked(page)) + referenced++; + else if (page->mapping) { referenced += page_referenced_file(page); + unlock_page(page); + } } return referenced; } @@ -346,36 +430,17 @@ BUG_ON(PageReserved(page)); BUG_ON(!anon_vma); + anon_vma = (void *) anon_vma + PAGE_MAPPING_ANON; index = (address - vma->vm_start) >> PAGE_SHIFT; index += vma->vm_pgoff; index >>= PAGE_CACHE_SHIFT - PAGE_SHIFT; - /* - * Setting and clearing PG_anon must always happen inside - * page_map_lock to avoid races between mapping and - * unmapping on different processes of the same - * shared cow swapcache page. And while we take the - * page_map_lock PG_anon cannot change from under us. - * Actually PG_anon cannot change under fork either - * since fork holds a reference on the page so it cannot - * be unmapped under fork and in turn copy_page_range is - * allowed to read PG_anon outside the page_map_lock. - */ - page_map_lock(page); - if (!page->mapcount) { - BUG_ON(PageAnon(page)); - BUG_ON(page->mapping); - SetPageAnon(page); + if (atomic_inc_and_test(&page->_mapcount)) { page->index = index; page->mapping = (struct address_space *) anon_vma; inc_page_state(nr_mapped); - } else { - BUG_ON(!PageAnon(page)); - BUG_ON(page->index != index); - BUG_ON(page->mapping != (struct address_space *) anon_vma); } - page->mapcount++; - page_map_unlock(page); + /* else checking page index and mapping is racy */ } /** @@ -390,11 +455,8 @@ if (!pfn_valid(page_to_pfn(page)) || PageReserved(page)) return; - page_map_lock(page); - if (!page->mapcount) + if (atomic_inc_and_test(&page->_mapcount)) inc_page_state(nr_mapped); - page->mapcount++; - page_map_unlock(page); } /** @@ -406,18 +468,22 @@ void page_remove_rmap(struct page *page) { BUG_ON(PageReserved(page)); - BUG_ON(!page->mapcount); - page_map_lock(page); - page->mapcount--; - if (!page->mapcount) { + if (atomic_add_negative(-1, &page->_mapcount)) { + BUG_ON(page_mapcount(page) < 0); + /* + * It would be tidy to reset the PageAnon mapping here, + * but that might overwrite a racing page_add_anon_rmap + * which increments mapcount after us but sets mapping + * before us: so leave the reset to free_hot_cold_page, + * and remember that it's only reliable while mapped. + * Leaving it set also helps swapoff to reinstate ptes + * faster for those pages still in swapcache. + */ if (page_test_and_clear_dirty(page)) set_page_dirty(page); - if (PageAnon(page)) - clear_page_anon(page); dec_page_state(nr_mapped); } - page_map_unlock(page); } /* @@ -444,8 +510,7 @@ * We need the page_table_lock to protect us from page faults, * munmap, fork, etc... */ - if (!spin_trylock(&mm->page_table_lock)) - goto out; + spin_lock(&mm->page_table_lock); pgd = pgd_offset(mm, address); if (!pgd_present(*pgd)) @@ -489,7 +554,7 @@ * ptes from being unmapped, so swapoff can make progress. */ if (PageSwapCache(page) && - page_count(page) != page->mapcount + 2) { + page_count(page) != page_mapcount(page) + 2) { ret = SWAP_FAIL; goto out_unmap; } @@ -515,8 +580,7 @@ } mm->rss--; - BUG_ON(!page->mapcount); - page->mapcount--; + page_remove_rmap(page); page_cache_release(page); out_unmap: @@ -549,7 +613,7 @@ #define CLUSTER_SIZE min(32*PAGE_SIZE, PMD_SIZE) #define CLUSTER_MASK (~(CLUSTER_SIZE - 1)) -static int try_to_unmap_cluster(unsigned long cursor, +static void try_to_unmap_cluster(unsigned long cursor, unsigned int *mapcount, struct vm_area_struct *vma) { struct mm_struct *mm = vma->vm_mm; @@ -566,8 +630,7 @@ * We need the page_table_lock to protect us from page faults, * munmap, fork, etc... */ - if (!spin_trylock(&mm->page_table_lock)) - return SWAP_FAIL; + spin_lock(&mm->page_table_lock); address = (vma->vm_start + cursor) & CLUSTER_MASK; end = address + CLUSTER_SIZE; @@ -624,20 +687,21 @@ out_unlock: spin_unlock(&mm->page_table_lock); - return SWAP_AGAIN; } -static inline int try_to_unmap_anon(struct page *page) +static int try_to_unmap_anon(struct page *page) { - struct anon_vma *anon_vma = (struct anon_vma *) page->mapping; + struct anon_vma *anon_vma; struct vm_area_struct *vma; int ret = SWAP_AGAIN; - spin_lock(&anon_vma->lock); - BUG_ON(list_empty(&anon_vma->head)); + anon_vma = page_lock_anon_vma(page); + if (!anon_vma) + return ret; + list_for_each_entry(vma, &anon_vma->head, anon_vma_node) { ret = try_to_unmap_one(page, vma); - if (ret == SWAP_FAIL || !page->mapcount) + if (ret == SWAP_FAIL || !page_mapped(page)) break; } spin_unlock(&anon_vma->lock); @@ -652,11 +716,8 @@ * contained in the address_space struct it points to. * * This function is only called from try_to_unmap for object-based pages. - * - * The spinlock address_space->i_mmap_lock is tried. If it can't be gotten, - * return a temporary error. */ -static inline int try_to_unmap_file(struct page *page) +static int try_to_unmap_file(struct page *page) { struct address_space *mapping = page->mapping; pgoff_t pgoff = page->index << (PAGE_CACHE_SHIFT - PAGE_SHIFT); @@ -668,12 +729,10 @@ unsigned long max_nl_size = 0; unsigned int mapcount; - if (!spin_trylock(&mapping->i_mmap_lock)) - return ret; - + spin_lock(&mapping->i_mmap_lock); vma_prio_tree_foreach(vma, &iter, &mapping->i_mmap, pgoff, pgoff) { ret = try_to_unmap_one(page, vma); - if (ret == SWAP_FAIL || !page->mapcount) + if (ret == SWAP_FAIL || !page_mapped(page)) goto out; } @@ -692,8 +751,10 @@ max_nl_size = cursor; } - if (max_nl_size == 0) /* any nonlinears locked or reserved */ + if (max_nl_size == 0) { /* any nonlinears locked or reserved */ + ret = SWAP_FAIL; goto out; + } /* * We don't try to search for this page in the nonlinear vmas, @@ -702,8 +763,9 @@ * The mapcount of the page we came in with is irrelevant, * but even so use it as a guide to how hard we should try? */ - mapcount = page->mapcount; - page_map_unlock(page); + mapcount = page_mapcount(page); + if (!mapcount) + goto out; cond_resched_lock(&mapping->i_mmap_lock); max_nl_size = (max_nl_size + CLUSTER_SIZE - 1) & CLUSTER_MASK; @@ -719,19 +781,13 @@ while (vma->vm_mm->rss && cursor < max_nl_cursor && cursor < vma->vm_end - vma->vm_start) { - ret = try_to_unmap_cluster( - cursor, &mapcount, vma); - if (ret == SWAP_FAIL) - break; + try_to_unmap_cluster(cursor, &mapcount, vma); cursor += CLUSTER_SIZE; vma->vm_private_data = (void *) cursor; if ((int)mapcount <= 0) - goto relock; + goto out; } - if (ret != SWAP_FAIL) - vma->vm_private_data = - (void *) max_nl_cursor; - ret = SWAP_AGAIN; + vma->vm_private_data = (void *) max_nl_cursor; } cond_resched_lock(&mapping->i_mmap_lock); max_nl_cursor += CLUSTER_SIZE; @@ -747,8 +803,6 @@ if (!(vma->vm_flags & VM_RESERVED)) vma->vm_private_data = NULL; } -relock: - page_map_lock(page); out: spin_unlock(&mapping->i_mmap_lock); return ret; @@ -759,11 +813,11 @@ * @page: the page to get unmapped * * Tries to remove all the page table entries which are mapping this - * page, used in the pageout path. Caller must hold the page lock - * and its rmap lock. Return values are: + * page, used in the pageout path. Caller must hold the page lock. + * Return values are: * * SWAP_SUCCESS - we succeeded in removing all mappings - * SWAP_AGAIN - we missed a trylock, try again later + * SWAP_AGAIN - we missed a mapping, try again later * SWAP_FAIL - the page is unswappable */ int try_to_unmap(struct page *page) @@ -772,20 +826,13 @@ BUG_ON(PageReserved(page)); BUG_ON(!PageLocked(page)); - BUG_ON(!page->mapcount); if (PageAnon(page)) ret = try_to_unmap_anon(page); else ret = try_to_unmap_file(page); - if (!page->mapcount) { - if (page_test_and_clear_dirty(page)) - set_page_dirty(page); - if (PageAnon(page)) - clear_page_anon(page); - dec_page_state(nr_mapped); + if (!page_mapped(page)) ret = SWAP_SUCCESS; - } return ret; } diff -Nru a/mm/slab.c b/mm/slab.c --- a/mm/slab.c 2004-08-25 22:01:56 -07:00 +++ b/mm/slab.c 2004-08-25 22:01:56 -07:00 @@ -91,6 +91,7 @@ #include #include #include +#include #include #include @@ -139,11 +140,13 @@ SLAB_POISON | SLAB_HWCACHE_ALIGN | \ SLAB_NO_REAP | SLAB_CACHE_DMA | \ SLAB_MUST_HWCACHE_ALIGN | SLAB_STORE_USER | \ - SLAB_RECLAIM_ACCOUNT | SLAB_PANIC) + SLAB_RECLAIM_ACCOUNT | SLAB_PANIC | \ + SLAB_DESTROY_BY_RCU) #else # define CREATE_MASK (SLAB_HWCACHE_ALIGN | SLAB_NO_REAP | \ SLAB_CACHE_DMA | SLAB_MUST_HWCACHE_ALIGN | \ - SLAB_RECLAIM_ACCOUNT | SLAB_PANIC) + SLAB_RECLAIM_ACCOUNT | SLAB_PANIC | \ + SLAB_DESTROY_BY_RCU) #endif /* @@ -190,6 +193,28 @@ }; /* + * struct slab_rcu + * + * slab_destroy on a SLAB_DESTROY_BY_RCU cache uses this structure to + * arrange for kmem_freepages to be called via RCU. This is useful if + * we need to approach a kernel structure obliquely, from its address + * obtained without the usual locking. We can lock the structure to + * stabilize it and check it's still at the given address, only if we + * can be sure that the memory has not been meanwhile reused for some + * other kind of object (which our subsystem's lock might corrupt). + * + * rcu_read_lock before reading the address, then rcu_read_unlock after + * taking the spinlock within the structure expected at that address. + * + * We assume struct slab_rcu can overlay struct slab when destroying. + */ +struct slab_rcu { + struct rcu_head head; + kmem_cache_t *cachep; + void *addr; +}; + +/* * struct array_cache * * Per cpu structures @@ -873,6 +898,16 @@ atomic_sub(1<gfporder, &slab_reclaim_pages); } +static void kmem_rcu_free(struct rcu_head *head) +{ + struct slab_rcu *slab_rcu = (struct slab_rcu *) head; + kmem_cache_t *cachep = slab_rcu->cachep; + + kmem_freepages(cachep, slab_rcu->addr); + if (OFF_SLAB(cachep)) + kmem_cache_free(cachep->slabp_cache, slab_rcu); +} + #if DEBUG #ifdef CONFIG_DEBUG_PAGEALLOC @@ -1026,6 +1061,8 @@ */ static void slab_destroy (kmem_cache_t *cachep, struct slab *slabp) { + void *addr = slabp->s_mem - slabp->colouroff; + #if DEBUG int i; for (i = 0; i < cachep->num; i++) { @@ -1061,10 +1098,19 @@ } } #endif - - kmem_freepages(cachep, slabp->s_mem-slabp->colouroff); - if (OFF_SLAB(cachep)) - kmem_cache_free(cachep->slabp_cache, slabp); + + if (unlikely(cachep->flags & SLAB_DESTROY_BY_RCU)) { + struct slab_rcu *slab_rcu; + + slab_rcu = (struct slab_rcu *) slabp; + slab_rcu->cachep = cachep; + slab_rcu->addr = addr; + call_rcu(&slab_rcu->head, kmem_rcu_free); + } else { + kmem_freepages(cachep, addr); + if (OFF_SLAB(cachep)) + kmem_cache_free(cachep->slabp_cache, slabp); + } } /** @@ -1139,9 +1185,15 @@ */ if ((size < 4096 || fls(size-1) == fls(size-1+3*BYTES_PER_WORD))) flags |= SLAB_RED_ZONE|SLAB_STORE_USER; - flags |= SLAB_POISON; + if (!(flags & SLAB_DESTROY_BY_RCU)) + flags |= SLAB_POISON; #endif + if (flags & SLAB_DESTROY_BY_RCU) + BUG_ON(flags & SLAB_POISON); #endif + if (flags & SLAB_DESTROY_BY_RCU) + BUG_ON(dtor); + /* * Always checks flags, a caller might be expecting debug * support which isn't available. @@ -1552,6 +1604,9 @@ unlock_cpu_hotplug(); return 1; } + + if (unlikely(cachep->flags & SLAB_DESTROY_BY_RCU)) + synchronize_kernel(); /* no cpu_online check required here since we clear the percpu * array on cpu offline and set this to NULL. diff -Nru a/mm/swapfile.c b/mm/swapfile.c --- a/mm/swapfile.c 2004-08-25 22:01:54 -07:00 +++ b/mm/swapfile.c 2004-08-25 22:01:54 -07:00 @@ -520,14 +520,24 @@ } /* vma->vm_mm->page_table_lock is held */ -static unsigned long unuse_vma(struct vm_area_struct * vma, pgd_t *pgdir, +static unsigned long unuse_vma(struct vm_area_struct * vma, swp_entry_t entry, struct page *page) { - unsigned long start = vma->vm_start, end = vma->vm_end; + pgd_t *pgdir; + unsigned long start, end; unsigned long foundaddr; - if (start >= end) - BUG(); + if (page->mapping) { + start = page_address_in_vma(page, vma); + if (start == -EFAULT) + return 0; + else + end = start + PAGE_SIZE; + } else { + start = vma->vm_start; + end = vma->vm_end; + } + pgdir = pgd_offset(vma->vm_mm, start); do { foundaddr = unuse_pgd(vma, pgdir, start, end - start, entry, page); @@ -559,9 +569,8 @@ } spin_lock(&mm->page_table_lock); for (vma = mm->mmap; vma; vma = vma->vm_next) { - if (!is_vm_hugetlb_page(vma)) { - pgd_t * pgd = pgd_offset(mm, vma->vm_start); - foundaddr = unuse_vma(vma, pgd, entry, page); + if (vma->anon_vma) { + foundaddr = unuse_vma(vma, entry, page); if (foundaddr) break; } diff -Nru a/mm/vmscan.c b/mm/vmscan.c --- a/mm/vmscan.c 2004-08-25 22:01:54 -07:00 +++ b/mm/vmscan.c 2004-08-25 22:01:54 -07:00 @@ -219,7 +219,7 @@ return 0; } -/* Must be called with page's rmap lock held. */ +/* Called without lock on whether page is mapped, so answer is unstable */ static inline int page_mapping_inuse(struct page *page) { struct address_space *mapping; @@ -377,26 +377,19 @@ if (page_mapped(page) || PageSwapCache(page)) sc->nr_scanned++; - page_map_lock(page); - referenced = page_referenced(page); - if (referenced && page_mapping_inuse(page)) { - /* In active use or really unfreeable. Activate it. */ - page_map_unlock(page); + referenced = page_referenced(page, 1); + /* In active use or really unfreeable? Activate it. */ + if (referenced && page_mapping_inuse(page)) goto activate_locked; - } #ifdef CONFIG_SWAP /* * Anonymous process memory has backing store? * Try to allocate it some swap space here. - * - * XXX: implement swap clustering ? */ if (PageAnon(page) && !PageSwapCache(page)) { - page_map_unlock(page); if (!add_to_swap(page)) goto activate_locked; - page_map_lock(page); } #endif /* CONFIG_SWAP */ @@ -411,16 +404,13 @@ if (page_mapped(page) && mapping) { switch (try_to_unmap(page)) { case SWAP_FAIL: - page_map_unlock(page); goto activate_locked; case SWAP_AGAIN: - page_map_unlock(page); goto keep_locked; case SWAP_SUCCESS: ; /* try to free the page below */ } } - page_map_unlock(page); if (PageDirty(page)) { if (referenced) @@ -723,25 +713,12 @@ page = lru_to_page(&l_hold); list_del(&page->lru); if (page_mapped(page)) { - if (!reclaim_mapped) { - list_add(&page->lru, &l_active); - continue; - } - page_map_lock(page); - if (page_referenced(page)) { - page_map_unlock(page); + if (!reclaim_mapped || + (total_swap_pages == 0 && PageAnon(page)) || + page_referenced(page, 0)) { list_add(&page->lru, &l_active); continue; } - page_map_unlock(page); - } - /* - * FIXME: need to consider page_count(page) here if/when we - * reap orphaned pages via the LRU (Daniel's locking stuff) - */ - if (total_swap_pages == 0 && PageAnon(page)) { - list_add(&page->lru, &l_active); - continue; } list_add(&page->lru, &l_inactive); } diff -Nru a/net/bridge/br_input.c b/net/bridge/br_input.c --- a/net/bridge/br_input.c 2004-08-25 22:01:54 -07:00 +++ b/net/bridge/br_input.c 2004-08-25 22:01:54 -07:00 @@ -45,26 +45,15 @@ br_pass_frame_up_finish); } +/* note: already called with rcu_read_lock (preempt_disabled) */ int br_handle_frame_finish(struct sk_buff *skb) { - struct net_bridge *br; - unsigned char *dest; + const unsigned char *dest = skb->mac.ethernet->h_dest; + struct net_bridge_port *p = skb->dev->br_port; + struct net_bridge *br = p->br; struct net_bridge_fdb_entry *dst; - struct net_bridge_port *p; - int passedup; + int passedup = 0; - dest = skb->mac.ethernet->h_dest; - - rcu_read_lock(); - p = rcu_dereference(skb->dev->br_port); - - if (p == NULL || p->state == BR_STATE_DISABLED) { - kfree_skb(skb); - goto out; - } - - br = p->br; - passedup = 0; if (br->dev->flags & IFF_PROMISC) { struct sk_buff *skb2; @@ -99,20 +88,21 @@ br_flood_forward(br, skb, 0); out: - rcu_read_unlock(); return 0; } -int br_handle_frame(struct sk_buff *skb) +/* + * Called via br_handle_frame_hook. + * Return 0 if *pskb should be processed furthur + * 1 if *pskb is handled + * note: already called with rcu_read_lock (preempt_disabled) + */ +int br_handle_frame(struct net_bridge_port *p, struct sk_buff **pskb) { - unsigned char *dest; - struct net_bridge_port *p; - - dest = skb->mac.ethernet->h_dest; + struct sk_buff *skb = *pskb; + const unsigned char *dest = skb->mac.ethernet->h_dest; - rcu_read_lock(); - p = skb->dev->br_port; - if (p == NULL || p->state == BR_STATE_DISABLED) + if (p->state == BR_STATE_DISABLED) goto err; if (skb->mac.ethernet->h_source[0] & 1) @@ -128,15 +118,16 @@ if (!dest[5]) { NF_HOOK(PF_BRIDGE, NF_BR_LOCAL_IN, skb, skb->dev, NULL, br_stp_handle_bpdu); - rcu_read_unlock(); - return 0; + return 1; } } else if (p->state == BR_STATE_FORWARDING) { - if (br_should_route_hook && br_should_route_hook(&skb)) { - rcu_read_unlock(); - return -1; + if (br_should_route_hook) { + if (br_should_route_hook(pskb)) + return 0; + skb = *pskb; + dest = skb->mac.ethernet->h_dest; } if (!memcmp(p->br->dev->dev_addr, dest, ETH_ALEN)) @@ -144,12 +135,10 @@ NF_HOOK(PF_BRIDGE, NF_BR_PRE_ROUTING, skb, skb->dev, NULL, br_handle_frame_finish); - rcu_read_unlock(); - return 0; + return 1; } err: - rcu_read_unlock(); kfree_skb(skb); - return 0; + return 1; } diff -Nru a/net/bridge/br_private.h b/net/bridge/br_private.h --- a/net/bridge/br_private.h 2004-08-25 22:01:54 -07:00 +++ b/net/bridge/br_private.h 2004-08-25 22:01:54 -07:00 @@ -177,7 +177,7 @@ /* br_input.c */ extern int br_handle_frame_finish(struct sk_buff *skb); -extern int br_handle_frame(struct sk_buff *skb); +extern int br_handle_frame(struct net_bridge_port *p, struct sk_buff **pskb); /* br_ioctl.c */ extern int br_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); diff -Nru a/net/core/dev.c b/net/core/dev.c --- a/net/core/dev.c 2004-08-25 22:01:55 -07:00 +++ b/net/core/dev.c 2004-08-25 22:01:55 -07:00 @@ -1144,16 +1144,10 @@ goto out; } - if (skb_shared(*pskb) || skb_cloned(*pskb)) { - struct sk_buff *newskb = skb_copy(*pskb, GFP_ATOMIC); - if (!newskb) { - ret = -ENOMEM; + if (skb_cloned(*pskb)) { + ret = pskb_expand_head(*pskb, 0, 0, GFP_ATOMIC); + if (ret) goto out; - } - if ((*pskb)->sk) - skb_set_owner_w(newskb, (*pskb)->sk); - kfree_skb(*pskb); - *pskb = newskb; } if (offset > (int)(*pskb)->len) @@ -1676,43 +1670,34 @@ } static __inline__ int deliver_skb(struct sk_buff *skb, - struct packet_type *pt_prev, int last) + struct packet_type *pt_prev) { atomic_inc(&skb->users); return pt_prev->func(skb, skb->dev, pt_prev); } - #if defined(CONFIG_BRIDGE) || defined (CONFIG_BRIDGE_MODULE) -int (*br_handle_frame_hook)(struct sk_buff *skb); +int (*br_handle_frame_hook)(struct net_bridge_port *p, struct sk_buff **pskb); -static __inline__ int handle_bridge(struct sk_buff *skb, - struct packet_type *pt_prev) +static __inline__ int handle_bridge(struct sk_buff **pskb, + struct packet_type **pt_prev, int *ret) { - int ret = NET_RX_DROP; - if (pt_prev) - ret = deliver_skb(skb, pt_prev, 0); - - return ret; -} + struct net_bridge_port *port; -#endif - -static inline int __handle_bridge(struct sk_buff *skb, - struct packet_type **pt_prev, int *ret) -{ -#if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) - if (skb->dev->br_port && skb->pkt_type != PACKET_LOOPBACK) { - *ret = handle_bridge(skb, *pt_prev); - if (br_handle_frame_hook(skb) == 0) - return 1; + if ((*pskb)->pkt_type == PACKET_LOOPBACK || + (port = rcu_dereference((*pskb)->dev->br_port)) == NULL) + return 0; + if (*pt_prev) { + *ret = deliver_skb(*pskb, *pt_prev); *pt_prev = NULL; - } -#endif - return 0; + } + + return br_handle_frame_hook(port, pskb); } - +#else +#define handle_bridge(skb, pt_prev, ret) (0) +#endif #ifdef CONFIG_NET_CLS_ACT /* TODO: Maybe we should just force sch_ingress to be compiled in @@ -1779,27 +1764,27 @@ skb->mac_len = skb->nh.raw - skb->mac.raw; pt_prev = NULL; + + rcu_read_lock(); + #ifdef CONFIG_NET_CLS_ACT if (skb->tc_verd & TC_NCLS) { skb->tc_verd = CLR_TC_NCLS(skb->tc_verd); - rcu_read_lock(); goto ncls; } - #endif +#endif - rcu_read_lock(); list_for_each_entry_rcu(ptype, &ptype_all, list) { if (!ptype->dev || ptype->dev == skb->dev) { if (pt_prev) - ret = deliver_skb(skb, pt_prev, 0); + ret = deliver_skb(skb, pt_prev); pt_prev = ptype; } } #ifdef CONFIG_NET_CLS_ACT if (pt_prev) { - atomic_inc(&skb->users); - ret = pt_prev->func(skb, skb->dev, pt_prev); + ret = deliver_skb(skb, pt_prev); pt_prev = NULL; /* noone else should process this after*/ } else { skb->tc_verd = SET_TC_OK2MUNGE(skb->tc_verd); @@ -1818,7 +1803,7 @@ handle_diverter(skb); - if (__handle_bridge(skb, &pt_prev, &ret)) + if (handle_bridge(&skb, &pt_prev, &ret)) goto out; type = skb->protocol; @@ -1826,7 +1811,7 @@ if (ptype->type == type && (!ptype->dev || ptype->dev == skb->dev)) { if (pt_prev) - ret = deliver_skb(skb, pt_prev, 0); + ret = deliver_skb(skb, pt_prev); pt_prev = ptype; } } diff -Nru a/net/core/rtnetlink.c b/net/core/rtnetlink.c --- a/net/core/rtnetlink.c 2004-08-25 22:01:56 -07:00 +++ b/net/core/rtnetlink.c 2004-08-25 22:01:56 -07:00 @@ -166,31 +166,53 @@ r->ifi_family = AF_UNSPEC; r->ifi_type = dev->type; r->ifi_index = dev->ifindex; - r->ifi_flags = dev->flags; + r->ifi_flags = dev_get_flags(dev); r->ifi_change = change; - if (!netif_running(dev) || !netif_carrier_ok(dev)) - r->ifi_flags &= ~IFF_RUNNING; - else - r->ifi_flags |= IFF_RUNNING; - RTA_PUT(skb, IFLA_IFNAME, strlen(dev->name)+1, dev->name); + + if (1) { + u32 txqlen = dev->tx_queue_len; + RTA_PUT(skb, IFLA_TXQLEN, sizeof(txqlen), &txqlen); + } + + if (1) { + struct ifmap map = { + .mem_start = dev->mem_start, + .mem_end = dev->mem_end, + .base_addr = dev->base_addr, + .irq = dev->irq, + .dma = dev->dma, + .port = dev->if_port, + }; + RTA_PUT(skb, IFLA_MAP, sizeof(map), &map); + } + if (dev->addr_len) { RTA_PUT(skb, IFLA_ADDRESS, dev->addr_len, dev->dev_addr); RTA_PUT(skb, IFLA_BROADCAST, dev->addr_len, dev->broadcast); } + if (1) { - unsigned mtu = dev->mtu; + u32 mtu = dev->mtu; RTA_PUT(skb, IFLA_MTU, sizeof(mtu), &mtu); } - if (dev->ifindex != dev->iflink) - RTA_PUT(skb, IFLA_LINK, sizeof(int), &dev->iflink); + + if (dev->ifindex != dev->iflink) { + u32 iflink = dev->iflink; + RTA_PUT(skb, IFLA_LINK, sizeof(iflink), &iflink); + } + if (dev->qdisc_sleeping) RTA_PUT(skb, IFLA_QDISC, strlen(dev->qdisc_sleeping->ops->id) + 1, dev->qdisc_sleeping->ops->id); - if (dev->master) - RTA_PUT(skb, IFLA_MASTER, sizeof(int), &dev->master->ifindex); + + if (dev->master) { + u32 master = dev->master->ifindex; + RTA_PUT(skb, IFLA_MASTER, sizeof(master), &master); + } + if (dev->get_stats) { unsigned long *stats = (unsigned long*)dev->get_stats(dev); if (stats) { @@ -246,6 +268,30 @@ err = -EINVAL; + if (ifm->ifi_flags) + dev_change_flags(dev, ifm->ifi_flags); + + if (ida[IFLA_MAP - 1]) { + if (!dev->set_config) { + err = -EOPNOTSUPP; + goto out; + } + + if (!netif_device_present(dev)) { + err = -ENODEV; + goto out; + } + + if (ida[IFLA_MAP - 1]->rta_len != RTA_LENGTH(sizeof(struct ifmap))) + goto out; + + err = dev->set_config(dev, (struct ifmap *) + RTA_DATA(ida[IFLA_MAP - 1])); + + if (err) + goto out; + } + if (ida[IFLA_ADDRESS - 1]) { if (!dev->set_mac_address) { err = -EOPNOTSUPP; @@ -268,6 +314,23 @@ goto out; memcpy(dev->broadcast, RTA_DATA(ida[IFLA_BROADCAST - 1]), dev->addr_len); + } + + if (ida[IFLA_MTU - 1]) { + if (ida[IFLA_MTU - 1]->rta_len != RTA_LENGTH(sizeof(u32))) + goto out; + err = dev_set_mtu(dev, *((u32 *) RTA_DATA(ida[IFLA_MTU - 1]))); + + if (err) + goto out; + + } + + if (ida[IFLA_TXQLEN - 1]) { + if (ida[IFLA_TXQLEN - 1]->rta_len != RTA_LENGTH(sizeof(u32))) + goto out; + + dev->tx_queue_len = *((u32 *) RTA_DATA(ida[IFLA_TXQLEN - 1])); } err = 0; diff -Nru a/net/ipv4/netfilter/ip_conntrack_proto_icmp.c b/net/ipv4/netfilter/ip_conntrack_proto_icmp.c --- a/net/ipv4/netfilter/ip_conntrack_proto_icmp.c 2004-08-25 22:01:54 -07:00 +++ b/net/ipv4/netfilter/ip_conntrack_proto_icmp.c 2004-08-25 22:01:54 -07:00 @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include diff -Nru a/net/ipv4/netfilter/ip_conntrack_proto_tcp.c b/net/ipv4/netfilter/ip_conntrack_proto_tcp.c --- a/net/ipv4/netfilter/ip_conntrack_proto_tcp.c 2004-08-25 22:01:56 -07:00 +++ b/net/ipv4/netfilter/ip_conntrack_proto_tcp.c 2004-08-25 22:01:56 -07:00 @@ -33,6 +33,7 @@ #include #include +#include #include #include #include diff -Nru a/net/ipv4/netfilter/ip_conntrack_proto_udp.c b/net/ipv4/netfilter/ip_conntrack_proto_udp.c --- a/net/ipv4/netfilter/ip_conntrack_proto_udp.c 2004-08-25 22:01:54 -07:00 +++ b/net/ipv4/netfilter/ip_conntrack_proto_udp.c 2004-08-25 22:01:54 -07:00 @@ -14,6 +14,7 @@ #include #include #include +#include #include unsigned long ip_ct_udp_timeout = 30*HZ; diff -Nru a/net/ipv4/netfilter/ip_nat_core.c b/net/ipv4/netfilter/ip_nat_core.c --- a/net/ipv4/netfilter/ip_nat_core.c 2004-08-25 22:01:54 -07:00 +++ b/net/ipv4/netfilter/ip_nat_core.c 2004-08-25 22:01:54 -07:00 @@ -635,7 +635,7 @@ /* If there's a helper, assign it; based on new tuple. */ if (!conntrack->master) - info->helper = ip_nat_find_helper(&reply); + info->helper = __ip_nat_find_helper(&reply); /* It's done. */ info->initialized |= (1 << HOOK2MANIP(hooknum)); diff -Nru a/net/ipv4/netfilter/ip_nat_helper.c b/net/ipv4/netfilter/ip_nat_helper.c --- a/net/ipv4/netfilter/ip_nat_helper.c 2004-08-25 22:01:54 -07:00 +++ b/net/ipv4/netfilter/ip_nat_helper.c 2004-08-25 22:01:54 -07:00 @@ -421,12 +421,18 @@ } struct ip_nat_helper * +__ip_nat_find_helper(const struct ip_conntrack_tuple *tuple) +{ + return LIST_FIND(&helpers, helper_cmp, struct ip_nat_helper *, tuple); +} + +struct ip_nat_helper * ip_nat_find_helper(const struct ip_conntrack_tuple *tuple) { struct ip_nat_helper *h; READ_LOCK(&ip_nat_lock); - h = LIST_FIND(&helpers, helper_cmp, struct ip_nat_helper *, tuple); + h = __ip_nat_find_helper(tuple); READ_UNLOCK(&ip_nat_lock); return h; diff -Nru a/net/ipv4/netfilter/ip_nat_standalone.c b/net/ipv4/netfilter/ip_nat_standalone.c --- a/net/ipv4/netfilter/ip_nat_standalone.c 2004-08-25 22:01:56 -07:00 +++ b/net/ipv4/netfilter/ip_nat_standalone.c 2004-08-25 22:01:56 -07:00 @@ -394,4 +394,6 @@ EXPORT_SYMBOL(ip_nat_mangle_tcp_packet); EXPORT_SYMBOL(ip_nat_mangle_udp_packet); EXPORT_SYMBOL(ip_nat_used_tuple); +EXPORT_SYMBOL(ip_nat_find_helper); +EXPORT_SYMBOL(__ip_nat_find_helper); MODULE_LICENSE("GPL"); diff -Nru a/net/ipv4/xfrm4_output.c b/net/ipv4/xfrm4_output.c --- a/net/ipv4/xfrm4_output.c 2004-08-25 22:01:54 -07:00 +++ b/net/ipv4/xfrm4_output.c 2004-08-25 22:01:54 -07:00 @@ -58,8 +58,7 @@ if (!top_iph->frag_off) __ip_select_ident(top_iph, dst, 0); - /* TTL disclosed */ - top_iph->ttl = iph->ttl; + top_iph->ttl = dst_path_metric(dst, RTAX_HOPLIMIT); top_iph->saddr = x->props.saddr.a4; top_iph->daddr = x->id.daddr.a4; diff -Nru a/net/ipv6/route.c b/net/ipv6/route.c --- a/net/ipv6/route.c 2004-08-25 22:01:56 -07:00 +++ b/net/ipv6/route.c 2004-08-25 22:01:56 -07:00 @@ -820,9 +820,12 @@ */ if ((rtmsg->rtmsg_flags&RTF_REJECT) || (dev && (dev->flags&IFF_LOOPBACK) && !(addr_type&IPV6_ADDR_LOOPBACK))) { - if (dev && dev != &loopback_dev) { - dev_put(dev); - in6_dev_put(idev); + /* hold loopback dev/idev if we haven't done so. */ + if (dev != &loopback_dev) { + if (dev) { + dev_put(dev); + in6_dev_put(idev); + } dev = &loopback_dev; dev_hold(dev); idev = in6_dev_get(dev); diff -Nru a/net/ipv6/xfrm6_output.c b/net/ipv6/xfrm6_output.c --- a/net/ipv6/xfrm6_output.c 2004-08-25 22:01:56 -07:00 +++ b/net/ipv6/xfrm6_output.c 2004-08-25 22:01:56 -07:00 @@ -64,7 +64,7 @@ top_iph->flow_lbl[1] = iph->flow_lbl[1]; top_iph->flow_lbl[2] = iph->flow_lbl[2]; top_iph->nexthdr = IPPROTO_IPV6; - top_iph->hop_limit = iph->hop_limit; + top_iph->hop_limit = dst_path_metric(dst, RTAX_HOPLIMIT); ipv6_addr_copy(&top_iph->saddr, (struct in6_addr *)&x->props.saddr); ipv6_addr_copy(&top_iph->daddr, (struct in6_addr *)&x->id.daddr); } diff -Nru a/scripts/basic/fixdep.c b/scripts/basic/fixdep.c --- a/scripts/basic/fixdep.c 2004-08-25 22:01:55 -07:00 +++ b/scripts/basic/fixdep.c 2004-08-25 22:01:55 -07:00 @@ -93,6 +93,14 @@ * (Note: it'd be easy to port over the complete mkdep state machine, * but I don't think the added complexity is worth it) */ +/* + * Note 2: if somebody writes HELLO_CONFIG_BOOM in a file, it will depend onto + * CONFIG_BOOM. This could seem a bug (not too hard to fix), but please do not + * fix it! Some UserModeLinux files (look at arch/um/) call CONFIG_BOOM as + * UML_CONFIG_BOOM, to avoid conflicts with /usr/include/linux/autoconf.h, + * through arch/um/include/uml-config.h; this fixdep "bug" makes sure that + * those files will have correct dependencies. + */ #include #include @@ -310,6 +318,7 @@ } memcpy(s, m, p-m); s[p-m] = 0; if (strrcmp(s, "include/linux/autoconf.h") && + strrcmp(s, "arch/um/include/uml-config.h") && strrcmp(s, ".ver")) { printf(" %s \\\n", s); do_config_file(s); diff -Nru a/scripts/mod/sumversion.c b/scripts/mod/sumversion.c --- a/scripts/mod/sumversion.c 2004-08-25 22:01:56 -07:00 +++ b/scripts/mod/sumversion.c 2004-08-25 22:01:56 -07:00 @@ -1,4 +1,4 @@ -#include +#include #include #include #include diff -Nru a/security/Kconfig b/security/Kconfig --- a/security/Kconfig 2004-08-25 22:01:55 -07:00 +++ b/security/Kconfig 2004-08-25 22:01:55 -07:00 @@ -26,14 +26,14 @@ config SECURITY_CAPABILITIES tristate "Default Linux Capabilities" - depends on SECURITY!=n + depends on SECURITY help This enables the "default" Linux capabilities functionality. If you are unsure how to answer this question, answer Y. config SECURITY_ROOTPLUG tristate "Root Plug Support" - depends on USB && SECURITY!=n + depends on USB && SECURITY help This is a sample LSM module that should only be used as such. It prevents any programs running with egid == 0 if a specific diff -Nru a/security/security.c b/security/security.c --- a/security/security.c 2004-08-25 22:01:54 -07:00 +++ b/security/security.c 2004-08-25 22:01:54 -07:00 @@ -49,7 +49,7 @@ } /** - * security_scaffolding_startup - initialzes the security scaffolding framework + * security_scaffolding_startup - initializes the security scaffolding framework * * This should be called early in the kernel initialization sequence. */ @@ -183,7 +183,7 @@ * capable - calls the currently loaded security module's capable() function with the specified capability * @cap: the requested capability level. * - * This function calls the currently loaded security module's cabable() + * This function calls the currently loaded security module's capable() * function with a pointer to the current task and the specified @cap value. * * This allows the security module to implement the capable function call diff -Nru a/security/selinux/Kconfig b/security/selinux/Kconfig --- a/security/selinux/Kconfig 2004-08-25 22:01:54 -07:00 +++ b/security/selinux/Kconfig 2004-08-25 22:01:54 -07:00 @@ -24,6 +24,21 @@ If you are unsure how to answer this question, answer N. +config SECURITY_SELINUX_BOOTPARAM_VALUE + int "NSA SELinux boot parameter default value" + depends on SECURITY_SELINUX_BOOTPARAM + range 0 1 + default 1 + help + This option sets the default value for the kernel parameter + 'selinux', which allows SELinux to be disabled at boot. If this + option is set to 0 (zero), the SELinux kernel parameter will + default to 0, disabling SELinux at bootup. If this option is + set to 1 (one), the SELinux kernel paramater will default to 1, + enabling SELinux at bootup. + + If you are unsure how to answer this question, answer 1. + config SECURITY_SELINUX_DISABLE bool "NSA SELinux runtime disable" depends on SECURITY_SELINUX diff -Nru a/security/selinux/hooks.c b/security/selinux/hooks.c --- a/security/selinux/hooks.c 2004-08-25 22:01:56 -07:00 +++ b/security/selinux/hooks.c 2004-08-25 22:01:56 -07:00 @@ -43,6 +43,7 @@ #include #include #include +#include #include #include /* for sysctl_local_port_range[] */ #include /* struct or_callable used in sock_rcv_skb */ @@ -62,7 +63,6 @@ #include #include #include -#include #include #include "avc.h" @@ -87,7 +87,7 @@ #endif #ifdef CONFIG_SECURITY_SELINUX_BOOTPARAM -int selinux_enabled = 1; +int selinux_enabled = CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE; static int __init selinux_enabled_setup(char *str) { @@ -1266,6 +1266,12 @@ int inode_security_set_sid(struct inode *inode, u32 sid) { struct inode_security_struct *isec = inode->i_security; + struct superblock_security_struct *sbsec = inode->i_sb->s_security; + + if (!sbsec->initialized) { + /* Defer initialization to selinux_complete_init. */ + return 0; + } down(&isec->sem); isec->sclass = inode_mode_to_security_class(inode->i_mode); @@ -1726,72 +1732,40 @@ kfree(bsec); } -/* Create an open file that refers to the null device. - Derived from the OpenWall LSM. */ -struct file *open_devnull(void) -{ - struct inode *inode; - struct dentry *dentry; - struct file *file = NULL; - struct inode_security_struct *isec; - dev_t dev; - - inode = new_inode(current->fs->rootmnt->mnt_sb); - if (!inode) - goto out; - - dentry = dget(d_alloc_root(inode)); - if (!dentry) - goto out_iput; - - file = get_empty_filp(); - if (!file) - goto out_dput; - - dev = MKDEV(MEM_MAJOR, 3); /* null device */ - - inode->i_uid = current->fsuid; - inode->i_gid = current->fsgid; - inode->i_blksize = PAGE_SIZE; - inode->i_blocks = 0; - inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; - inode->i_state = I_DIRTY; /* so that mark_inode_dirty won't touch us */ - - isec = inode->i_security; - isec->sid = SECINITSID_DEVNULL; - isec->sclass = SECCLASS_CHR_FILE; - isec->initialized = 1; - - file->f_flags = O_RDWR; - file->f_mode = FMODE_READ | FMODE_WRITE; - file->f_dentry = dentry; - file->f_vfsmnt = mntget(current->fs->rootmnt); - file->f_pos = 0; - - init_special_inode(inode, S_IFCHR | S_IRUGO | S_IWUGO, dev); - if (inode->i_fop->open(inode, file)) - goto out_fput; - -out: - return file; -out_fput: - mntput(file->f_vfsmnt); - put_filp(file); -out_dput: - dput(dentry); -out_iput: - iput(inode); - file = NULL; - goto out; -} +extern struct vfsmount *selinuxfs_mount; +extern struct dentry *selinux_null; /* Derived from fs/exec.c:flush_old_files. */ static inline void flush_unauthorized_files(struct files_struct * files) { struct avc_audit_data ad; struct file *file, *devnull = NULL; + struct tty_struct *tty = current->signal->tty; long j = -1; + if (tty) { + file_list_lock(); + file = list_entry(tty->tty_files.next, typeof(*file), f_list); + if (file) { + /* Revalidate access to controlling tty. + Use inode_has_perm on the tty inode directly rather + than using file_has_perm, as this particular open + file may belong to another process and we are only + interested in the inode-based check here. */ + struct inode *inode = file->f_dentry->d_inode; + if (inode_has_perm(current, inode, + FILE__READ | FILE__WRITE, + NULL, NULL)) { + /* Reset controlling tty. */ + current->signal->tty = NULL; + current->signal->tty_old_pgrp = 0; + } + } + file_list_unlock(); + } + + /* Revalidate access to inherited open files. */ + AVC_AUDIT_DATA_INIT(&ad,FS); spin_lock(&files->file_lock); @@ -1826,7 +1800,7 @@ if (devnull) { atomic_inc(&devnull->f_count); } else { - devnull = open_devnull(); + devnull = dentry_open(dget(selinux_null), mntget(selinuxfs_mount), O_RDWR); if (!devnull) { put_unused_fd(fd); fput(file); @@ -2822,7 +2796,7 @@ /* Returns error only if unable to parse addresses */ static int selinux_parse_skb_ipv4(struct sk_buff *skb, struct avc_audit_data *ad) { - int offset, ihlen, ret; + int offset, ihlen, ret = -EINVAL; struct iphdr _iph, *ih; offset = skb->nh.raw - skb->data; @@ -2836,6 +2810,7 @@ ad->u.net.v4info.saddr = ih->saddr; ad->u.net.v4info.daddr = ih->daddr; + ret = 0; switch (ih->protocol) { case IPPROTO_TCP: { @@ -2883,7 +2858,7 @@ static int selinux_parse_skb_ipv6(struct sk_buff *skb, struct avc_audit_data *ad) { u8 nexthdr; - int ret, offset; + int ret = -EINVAL, offset; struct ipv6hdr _ipv6h, *ip6; offset = skb->nh.raw - skb->data; @@ -2893,6 +2868,7 @@ ipv6_addr_copy(&ad->u.net.v6info.saddr, &ip6->saddr); ipv6_addr_copy(&ad->u.net.v6info.daddr, &ip6->daddr); + ret = 0; nexthdr = ip6->nexthdr; offset += sizeof(_ipv6h); @@ -3082,6 +3058,7 @@ goto out; AVC_AUDIT_DATA_INIT(&ad,NET); ad.u.net.sport = htons(snum); + ad.u.net.family = family; err = avc_has_perm(isec->sid, sid, isec->sclass, SOCKET__NAME_BIND, NULL, &ad); diff -Nru a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c --- a/security/selinux/selinuxfs.c 2004-08-25 22:01:56 -07:00 +++ b/security/selinux/selinuxfs.c 2004-08-25 22:01:56 -07:00 @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -68,40 +69,15 @@ SEL_DISABLE /* disable SELinux until next reboot */ }; +#define TMPBUFLEN 12 static ssize_t sel_read_enforce(struct file *filp, char __user *buf, size_t count, loff_t *ppos) { - char *page; + char tmpbuf[TMPBUFLEN]; ssize_t length; - ssize_t end; - - if (count < 0 || count > PAGE_SIZE) - return -EINVAL; - if (!(page = (char*)__get_free_page(GFP_KERNEL))) - return -ENOMEM; - memset(page, 0, PAGE_SIZE); - length = scnprintf(page, PAGE_SIZE, "%d", selinux_enforcing); - if (length < 0) { - free_page((unsigned long)page); - return length; - } - - if (*ppos >= length) { - free_page((unsigned long)page); - return 0; - } - if (count + *ppos > length) - count = length - *ppos; - end = count + *ppos; - if (copy_to_user(buf, (char *) page + *ppos, count)) { - count = -EFAULT; - goto out; - } - *ppos = end; -out: - free_page((unsigned long)page); - return count; + length = scnprintf(tmpbuf, TMPBUFLEN, "%d", selinux_enforcing); + return simple_read_from_buffer(buf, count, ppos, tmpbuf, length); } #ifdef CONFIG_SECURITY_SELINUX_DEVELOP @@ -119,10 +95,9 @@ /* No partial writes. */ return -EINVAL; } - page = (char*)__get_free_page(GFP_KERNEL); + page = (char*)get_zeroed_page(GFP_KERNEL); if (!page) return -ENOMEM; - memset(page, 0, PAGE_SIZE); length = -EFAULT; if (copy_from_user(page, buf, count)) goto out; @@ -170,10 +145,9 @@ /* No partial writes. */ return -EINVAL; } - page = (char*)__get_free_page(GFP_KERNEL); + page = (char*)get_zeroed_page(GFP_KERNEL); if (!page) return -ENOMEM; - memset(page, 0, PAGE_SIZE); length = -EFAULT; if (copy_from_user(page, buf, count)) goto out; @@ -204,37 +178,11 @@ static ssize_t sel_read_policyvers(struct file *filp, char __user *buf, size_t count, loff_t *ppos) { - char *page; + char tmpbuf[TMPBUFLEN]; ssize_t length; - ssize_t end; - if (count < 0 || count > PAGE_SIZE) - return -EINVAL; - if (!(page = (char*)__get_free_page(GFP_KERNEL))) - return -ENOMEM; - memset(page, 0, PAGE_SIZE); - - length = scnprintf(page, PAGE_SIZE, "%u", POLICYDB_VERSION_MAX); - if (length < 0) { - free_page((unsigned long)page); - return length; - } - - if (*ppos >= length) { - free_page((unsigned long)page); - return 0; - } - if (count + *ppos > length) - count = length - *ppos; - end = count + *ppos; - if (copy_to_user(buf, (char *) page + *ppos, count)) { - count = -EFAULT; - goto out; - } - *ppos = end; -out: - free_page((unsigned long)page); - return count; + length = scnprintf(tmpbuf, TMPBUFLEN, "%u", POLICYDB_VERSION_MAX); + return simple_read_from_buffer(buf, count, ppos, tmpbuf, length); } static struct file_operations sel_policyvers_ops = { @@ -247,37 +195,11 @@ static ssize_t sel_read_mls(struct file *filp, char __user *buf, size_t count, loff_t *ppos) { - char *page; + char tmpbuf[TMPBUFLEN]; ssize_t length; - ssize_t end; - - if (count < 0 || count > PAGE_SIZE) - return -EINVAL; - if (!(page = (char*)__get_free_page(GFP_KERNEL))) - return -ENOMEM; - memset(page, 0, PAGE_SIZE); - length = scnprintf(page, PAGE_SIZE, "%d", selinux_mls_enabled); - if (length < 0) { - free_page((unsigned long)page); - return length; - } - - if (*ppos >= length) { - free_page((unsigned long)page); - return 0; - } - if (count + *ppos > length) - count = length - *ppos; - end = count + *ppos; - if (copy_to_user(buf, (char *) page + *ppos, count)) { - count = -EFAULT; - goto out; - } - *ppos = end; -out: - free_page((unsigned long)page); - return count; + length = scnprintf(tmpbuf, TMPBUFLEN, "%d", selinux_mls_enabled); + return simple_read_from_buffer(buf, count, ppos, tmpbuf, length); } static struct file_operations sel_mls_ops = { @@ -352,10 +274,9 @@ /* No partial writes. */ return -EINVAL; } - page = (char*)__get_free_page(GFP_KERNEL); + page = (char*)get_zeroed_page(GFP_KERNEL); if (!page) return -ENOMEM; - memset(page, 0, PAGE_SIZE); length = -EFAULT; if (copy_from_user(page, buf, count)) goto out; @@ -390,103 +311,31 @@ [SEL_USER] = sel_write_user, }; -/* an argresp is stored in an allocated page and holds the - * size of the argument or response, along with its content - */ -struct argresp { - ssize_t size; - char data[0]; -}; - -#define PAYLOAD_SIZE (PAGE_SIZE - sizeof(struct argresp)) - -/* - * transaction based IO methods. - * The file expects a single write which triggers the transaction, and then - * possibly a read which collects the result - which is stored in a - * file-local buffer. - */ -static ssize_t TA_write(struct file *file, const char __user *buf, size_t size, loff_t *pos) +static ssize_t selinux_transaction_write(struct file *file, const char __user *buf, size_t size, loff_t *pos) { ino_t ino = file->f_dentry->d_inode->i_ino; - struct argresp *ar; - ssize_t rv = 0; + char *data; + ssize_t rv; if (ino >= sizeof(write_op)/sizeof(write_op[0]) || !write_op[ino]) return -EINVAL; - if (file->private_data) - return -EINVAL; /* only one write allowed per open */ - if (size > PAYLOAD_SIZE - 1) /* allow one byte for null terminator */ - return -EFBIG; - ar = kmalloc(PAGE_SIZE, GFP_KERNEL); - if (!ar) - return -ENOMEM; - memset(ar, 0, PAGE_SIZE); /* clear buffer, particularly last byte */ - ar->size = 0; - down(&file->f_dentry->d_inode->i_sem); - if (file->private_data) - rv = -EINVAL; - else - file->private_data = ar; - up(&file->f_dentry->d_inode->i_sem); - if (rv) { - kfree(ar); - return rv; - } - if (copy_from_user(ar->data, buf, size)) - return -EFAULT; + data = simple_transaction_get(file, buf, size); + if (IS_ERR(data)) + return PTR_ERR(data); - rv = write_op[ino](file, ar->data, size); + rv = write_op[ino](file, data, size); if (rv>0) { - ar->size = rv; + simple_transaction_set(file, rv); rv = size; } return rv; } -static ssize_t TA_read(struct file *file, char __user *buf, size_t size, loff_t *pos) -{ - struct argresp *ar; - ssize_t rv = 0; - - if (file->private_data == NULL) - rv = TA_write(file, buf, 0, pos); - if (rv < 0) - return rv; - - ar = file->private_data; - if (!ar) - return 0; - if (*pos >= ar->size) - return 0; - if (*pos + size > ar->size) - size = ar->size - *pos; - if (copy_to_user(buf, ar->data + *pos, size)) - return -EFAULT; - *pos += size; - return size; -} - -static int TA_open(struct inode *inode, struct file *file) -{ - file->private_data = NULL; - return 0; -} - -static int TA_release(struct inode *inode, struct file *file) -{ - void *p = file->private_data; - file->private_data = NULL; - kfree(p); - return 0; -} - static struct file_operations transaction_ops = { - .write = TA_write, - .read = TA_read, - .open = TA_open, - .release = TA_release, + .write = selinux_transaction_write, + .read = simple_transaction_read, + .release = simple_transaction_release, }; /* @@ -534,7 +383,8 @@ if (length < 0) goto out2; - length = scnprintf(buf, PAYLOAD_SIZE, "%x %x %x %x %u", + length = scnprintf(buf, SIMPLE_TRANSACTION_LIMIT, + "%x %x %x %x %u", avd.allowed, avd.decided, avd.auditallow, avd.auditdeny, avd.seqno); @@ -588,7 +438,7 @@ if (length < 0) goto out2; - if (len > PAYLOAD_SIZE) { + if (len > SIMPLE_TRANSACTION_LIMIT) { printk(KERN_ERR "%s: context size (%u) exceeds payload " "max\n", __FUNCTION__, len); length = -ERANGE; @@ -649,7 +499,7 @@ if (length < 0) goto out2; - if (len > PAYLOAD_SIZE) { + if (len > SIMPLE_TRANSACTION_LIMIT) { length = -ERANGE; goto out3; } @@ -709,7 +559,7 @@ length = rc; goto out3; } - if ((length + len) >= PAYLOAD_SIZE) { + if ((length + len) >= SIMPLE_TRANSACTION_LIMIT) { kfree(newcon); length = -ERANGE; goto out3; @@ -766,11 +616,10 @@ ret = -EINVAL; goto out; } - if (!(page = (char*)__get_free_page(GFP_KERNEL))) { + if (!(page = (char*)get_zeroed_page(GFP_KERNEL))) { ret = -ENOMEM; goto out; } - memset(page, 0, PAGE_SIZE); inode = filep->f_dentry->d_inode; cur_enforcing = security_get_bool_value(inode->i_ino - BOOL_INO_OFFSET); @@ -832,12 +681,11 @@ /* No partial writes. */ goto out; } - page = (char*)__get_free_page(GFP_KERNEL); + page = (char*)get_zeroed_page(GFP_KERNEL); if (!page) { length = -ENOMEM; goto out; } - memset(page, 0, PAGE_SIZE); if (copy_from_user(page, buf, count)) goto out; @@ -891,14 +739,12 @@ /* No partial writes. */ goto out; } - page = (char*)__get_free_page(GFP_KERNEL); + page = (char*)get_zeroed_page(GFP_KERNEL); if (!page) { length = -ENOMEM; goto out; } - memset(page, 0, PAGE_SIZE); - if (copy_from_user(page, buf, count)) goto out; @@ -984,9 +830,8 @@ sel_remove_bools(dir); - if (!(page = (char*)__get_free_page(GFP_KERNEL))) + if (!(page = (char*)get_zeroed_page(GFP_KERNEL))) return -ENOMEM; - memset(page, 0, PAGE_SIZE); ret = security_get_bools(&num, &names, &values); if (ret != 0) @@ -1042,12 +887,17 @@ goto out; } +#define NULL_FILE_NAME "null" + +struct dentry *selinux_null = NULL; + static int sel_fill_super(struct super_block * sb, void * data, int silent) { int ret; struct dentry *dentry; struct inode *inode; struct qstr qname; + struct inode_security_struct *isec; static struct tree_descr selinux_files[] = { [SEL_LOAD] = {"load", &sel_load_ops, S_IRUSR|S_IWUSR}, @@ -1085,10 +935,29 @@ if (ret) goto out; + qname.name = NULL_FILE_NAME; + qname.len = strlen(qname.name); + qname.hash = full_name_hash(qname.name, qname.len); + dentry = d_alloc(sb->s_root, &qname); + if (!dentry) + return -ENOMEM; + + inode = sel_make_inode(sb, S_IFCHR | S_IRUGO | S_IWUGO); + if (!inode) + goto out; + isec = (struct inode_security_struct*)inode->i_security; + isec->sid = SECINITSID_DEVNULL; + isec->sclass = SECCLASS_CHR_FILE; + isec->initialized = 1; + + init_special_inode(inode, S_IFCHR | S_IRUGO | S_IWUGO, MKDEV(MEM_MAJOR, 3)); + d_add(dentry, inode); + selinux_null = dentry; + return 0; out: dput(dentry); - printk(KERN_ERR "security: error creating conditional out_dput\n"); + printk(KERN_ERR "%s: failed while creating inodes\n", __FUNCTION__); return -ENOMEM; } @@ -1104,9 +973,24 @@ .kill_sb = kill_litter_super, }; +struct vfsmount *selinuxfs_mount; + static int __init init_sel_fs(void) { - return selinux_enabled ? register_filesystem(&sel_fs_type) : 0; + int err; + + if (!selinux_enabled) + return 0; + err = register_filesystem(&sel_fs_type); + if (!err) { + selinuxfs_mount = kern_mount(&sel_fs_type); + if (IS_ERR(selinuxfs_mount)) { + printk(KERN_ERR "selinuxfs: could not mount!\n"); + err = PTR_ERR(selinuxfs_mount); + selinuxfs_mount = NULL; + } + } + return err; } __initcall(init_sel_fs); diff -Nru a/security/selinux/ss/avtab.c b/security/selinux/ss/avtab.c --- a/security/selinux/ss/avtab.c 2004-08-25 22:01:56 -07:00 +++ b/security/selinux/ss/avtab.c 2004-08-25 22:01:56 -07:00 @@ -28,12 +28,14 @@ (keyp->source_type << 9)) & \ AVTAB_HASH_MASK) +static kmem_cache_t *avtab_node_cachep; + static struct avtab_node* avtab_insert_node(struct avtab *h, int hvalue, struct avtab_node * prev, struct avtab_node * cur, struct avtab_key *key, struct avtab_datum *datum) { struct avtab_node * newnode; - newnode = (struct avtab_node *) kmalloc(sizeof(struct avtab_node),GFP_KERNEL); + newnode = kmem_cache_alloc(avtab_node_cachep, SLAB_KERNEL); if (newnode == NULL) return NULL; memset(newnode, 0, sizeof(struct avtab_node)); @@ -226,7 +228,7 @@ while (cur != NULL) { temp = cur; cur = cur->next; - kfree(temp); + kmem_cache_free(avtab_node_cachep, temp); } h->htable[i] = NULL; } @@ -399,3 +401,9 @@ goto out; } +void avtab_cache_init(void) +{ + avtab_node_cachep = kmem_cache_create("avtab_node", + sizeof(struct avtab_node), + 0, SLAB_PANIC, NULL, NULL); +} diff -Nru a/security/selinux/ss/avtab.h b/security/selinux/ss/avtab.h --- a/security/selinux/ss/avtab.h 2004-08-25 22:01:55 -07:00 +++ b/security/selinux/ss/avtab.h 2004-08-25 22:01:55 -07:00 @@ -78,6 +78,8 @@ struct avtab_node *avtab_search_node_next(struct avtab_node *node, int specified); +void avtab_cache_init(void); + #define AVTAB_HASH_BITS 15 #define AVTAB_HASH_BUCKETS (1 << AVTAB_HASH_BITS) #define AVTAB_HASH_MASK (AVTAB_HASH_BUCKETS-1) diff -Nru a/security/selinux/ss/services.c b/security/selinux/ss/services.c --- a/security/selinux/ss/services.c 2004-08-25 22:01:56 -07:00 +++ b/security/selinux/ss/services.c 2004-08-25 22:01:56 -07:00 @@ -1034,6 +1034,7 @@ LOAD_LOCK; if (!ss_initialized) { + avtab_cache_init(); if (policydb_read(&policydb, fp)) { LOAD_UNLOCK; return -EINVAL; diff -Nru a/sound/oss/harmony.c b/sound/oss/harmony.c --- a/sound/oss/harmony.c 2004-08-25 22:01:56 -07:00 +++ b/sound/oss/harmony.c 2004-08-25 22:01:56 -07:00 @@ -8,7 +8,7 @@ On older 715 machines you'll find the technically identical chip called 'Vivace'. Both Harmony and Vicace are supported by this driver. - Copyright 2000 (c) Linuxcare Canada, Alex deVries + Copyright 2000 (c) Linuxcare Canada, Alex deVries Copyright 2000-2003 (c) Helge Deller Copyright 2001 (c) Matthieu Delahaye Copyright 2001 (c) Jean-Christophe Vaugeois @@ -1321,7 +1321,7 @@ } -MODULE_AUTHOR("Alex DeVries "); +MODULE_AUTHOR("Alex DeVries "); MODULE_DESCRIPTION("Harmony sound driver"); MODULE_LICENSE("GPL");