]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
Merge branch 'e1000-7.0.38-k2-fixes' of git://63.64.152.142/~ahkok/git/netdev-2.6
authorJeff Garzik <jeff@garzik.org>
Thu, 20 Apr 2006 21:30:41 +0000 (17:30 -0400)
committerJeff Garzik <jeff@garzik.org>
Thu, 20 Apr 2006 21:30:41 +0000 (17:30 -0400)
396 files changed:
Documentation/block/switching-sched.txt [new file with mode: 0644]
Documentation/cpu-freq/index.txt
Documentation/feature-removal-schedule.txt
Documentation/serial/driver
Documentation/vm/hugetlbpage.txt
MAINTAINERS
Makefile
README
arch/arm/common/scoop.c
arch/arm/mach-at91rm9200/devices.c
arch/arm/mach-pxa/corgi_ssp.c
arch/arm/mach-s3c2410/common-smdk.c
arch/arm/mach-s3c2410/s3c2440-clock.c
arch/i386/Kconfig.debug
arch/i386/kernel/acpi/boot.c
arch/i386/kernel/apm.c
arch/i386/kernel/cpu/amd.c
arch/i386/kernel/cpu/cpufreq/powernow-k8.c
arch/i386/kernel/cpuid.c
arch/i386/kernel/kprobes.c
arch/i386/kernel/msr.c
arch/i386/mach-voyager/voyager_cat.c
arch/ia64/kernel/kprobes.c
arch/m32r/kernel/entry.S
arch/m32r/kernel/process.c
arch/m32r/kernel/signal.c
arch/mips/Kconfig
arch/mips/Makefile
arch/mips/au1000/common/Makefile
arch/mips/au1000/common/int-handler.S [deleted file]
arch/mips/au1000/common/irq.c
arch/mips/cobalt/Makefile
arch/mips/cobalt/int-handler.S [deleted file]
arch/mips/cobalt/irq.c
arch/mips/configs/tb0287_defconfig [new file with mode: 0644]
arch/mips/ddb5xxx/ddb5074/Makefile
arch/mips/ddb5xxx/ddb5074/int-handler.S [deleted file]
arch/mips/ddb5xxx/ddb5074/irq.c
arch/mips/ddb5xxx/ddb5476/Makefile
arch/mips/ddb5xxx/ddb5476/int-handler.S [deleted file]
arch/mips/ddb5xxx/ddb5476/irq.c
arch/mips/ddb5xxx/ddb5476/vrc5476_irq.c
arch/mips/ddb5xxx/ddb5477/Makefile
arch/mips/ddb5xxx/ddb5477/int-handler.S [deleted file]
arch/mips/ddb5xxx/ddb5477/irq.c
arch/mips/dec/boot/decstation.c
arch/mips/dec/int-handler.S
arch/mips/dec/setup.c
arch/mips/galileo-boards/ev96100/Makefile
arch/mips/galileo-boards/ev96100/int-handler.S [deleted file]
arch/mips/galileo-boards/ev96100/irq.c
arch/mips/gt64120/ev64120/Makefile
arch/mips/gt64120/ev64120/int-handler.S [deleted file]
arch/mips/gt64120/ev64120/irq.c
arch/mips/gt64120/momenco_ocelot/Makefile
arch/mips/gt64120/momenco_ocelot/int-handler.S [deleted file]
arch/mips/gt64120/momenco_ocelot/irq.c
arch/mips/ite-boards/generic/Makefile
arch/mips/ite-boards/generic/int-handler.S [deleted file]
arch/mips/ite-boards/generic/irq.c
arch/mips/ite-boards/generic/time.c
arch/mips/ite-boards/ivr/init.c
arch/mips/ite-boards/qed-4n-s01b/init.c
arch/mips/jazz/Makefile
arch/mips/jazz/int-handler.S [deleted file]
arch/mips/jazz/irq.c
arch/mips/jmr3927/common/rtc_ds1742.c
arch/mips/jmr3927/rbhma3100/Makefile
arch/mips/jmr3927/rbhma3100/int-handler.S [deleted file]
arch/mips/jmr3927/rbhma3100/irq.c
arch/mips/kernel/Makefile
arch/mips/kernel/asm-offsets.c
arch/mips/kernel/entry.S
arch/mips/kernel/gdb-low.S
arch/mips/kernel/gdb-stub.c
arch/mips/kernel/genex.S
arch/mips/kernel/head.S
arch/mips/kernel/i8259.c
arch/mips/kernel/irq-msc01.c
arch/mips/kernel/irq.c
arch/mips/kernel/kspd.c [new file with mode: 0644]
arch/mips/kernel/linux32.c
arch/mips/kernel/mips-mt.c [new file with mode: 0644]
arch/mips/kernel/mips_ksyms.c
arch/mips/kernel/process.c
arch/mips/kernel/ptrace.c
arch/mips/kernel/ptrace32.c
arch/mips/kernel/r4k_switch.S
arch/mips/kernel/rtlx.c
arch/mips/kernel/scall32-o32.S
arch/mips/kernel/scall64-64.S
arch/mips/kernel/scall64-n32.S
arch/mips/kernel/scall64-o32.S
arch/mips/kernel/setup.c
arch/mips/kernel/smp-mt.c [moved from arch/mips/kernel/smp_mt.c with 88% similarity]
arch/mips/kernel/smp.c
arch/mips/kernel/smtc-asm.S [new file with mode: 0644]
arch/mips/kernel/smtc-proc.c [new file with mode: 0644]
arch/mips/kernel/smtc.c [new file with mode: 0644]
arch/mips/kernel/time.c
arch/mips/kernel/traps.c
arch/mips/kernel/vmlinux.lds.S
arch/mips/kernel/vpe.c
arch/mips/lasat/Makefile
arch/mips/lasat/interrupt.c
arch/mips/lasat/lasatIRQ.S [deleted file]
arch/mips/mips-boards/atlas/atlas_int.c
arch/mips/mips-boards/generic/Makefile
arch/mips/mips-boards/generic/gdb_hook.c
arch/mips/mips-boards/generic/init.c
arch/mips/mips-boards/generic/memory.c
arch/mips/mips-boards/generic/mipsIRQ.S [deleted file]
arch/mips/mips-boards/generic/time.c
arch/mips/mips-boards/malta/Makefile
arch/mips/mips-boards/malta/malta_int.c
arch/mips/mips-boards/malta/malta_smp.c [new file with mode: 0644]
arch/mips/mips-boards/sead/sead_int.c
arch/mips/mips-boards/sim/cmdline.c [deleted file]
arch/mips/mips-boards/sim/sim_cmdline.c
arch/mips/mips-boards/sim/sim_int.c
arch/mips/mips-boards/sim/sim_irq.S
arch/mips/mips-boards/sim/sim_mem.c
arch/mips/mips-boards/sim/sim_smp.c
arch/mips/mm/c-r3k.c
arch/mips/mm/c-r4k.c
arch/mips/mm/c-sb1.c
arch/mips/mm/c-tx39.c
arch/mips/mm/cache.c
arch/mips/mm/fault.c
arch/mips/mm/highmem.c
arch/mips/mm/init.c
arch/mips/mm/sc-rm7k.c
arch/mips/mm/tlb-r4k.c
arch/mips/mm/tlbex.c
arch/mips/momentum/jaguar_atx/Makefile
arch/mips/momentum/jaguar_atx/int-handler.S [deleted file]
arch/mips/momentum/jaguar_atx/irq.c
arch/mips/momentum/jaguar_atx/setup.c
arch/mips/momentum/ocelot_3/Makefile
arch/mips/momentum/ocelot_3/int-handler.S [deleted file]
arch/mips/momentum/ocelot_3/irq.c
arch/mips/momentum/ocelot_3/setup.c
arch/mips/momentum/ocelot_c/Makefile
arch/mips/momentum/ocelot_c/int-handler.S [deleted file]
arch/mips/momentum/ocelot_c/irq.c
arch/mips/momentum/ocelot_g/Makefile
arch/mips/momentum/ocelot_g/int-handler.S [deleted file]
arch/mips/momentum/ocelot_g/irq.c
arch/mips/philips/pnx8550/common/Makefile
arch/mips/philips/pnx8550/common/int.c
arch/mips/philips/pnx8550/common/mipsIRQ.S [deleted file]
arch/mips/philips/pnx8550/common/platform.c
arch/mips/pmc-sierra/yosemite/Makefile
arch/mips/pmc-sierra/yosemite/irq-handler.S [deleted file]
arch/mips/pmc-sierra/yosemite/irq.c
arch/mips/qemu/Makefile
arch/mips/qemu/q-int.S [deleted file]
arch/mips/qemu/q-irq.c
arch/mips/sgi-ip22/Makefile
arch/mips/sgi-ip22/ip22-int.c
arch/mips/sgi-ip22/ip22-irq.S [deleted file]
arch/mips/sgi-ip27/Makefile
arch/mips/sgi-ip27/TODO
arch/mips/sgi-ip27/ip27-irq-glue.S [deleted file]
arch/mips/sgi-ip27/ip27-irq.c
arch/mips/sgi-ip32/Makefile
arch/mips/sgi-ip32/ip32-irq-glue.S [deleted file]
arch/mips/sgi-ip32/ip32-irq.c
arch/mips/sibyte/bcm1480/Makefile
arch/mips/sibyte/bcm1480/irq.c
arch/mips/sibyte/bcm1480/irq_handler.S [deleted file]
arch/mips/sibyte/sb1250/Makefile
arch/mips/sibyte/sb1250/irq.c
arch/mips/sibyte/sb1250/irq_handler.S [deleted file]
arch/mips/sni/Makefile
arch/mips/sni/int-handler.S [deleted file]
arch/mips/sni/irq.c
arch/mips/tx4927/common/Makefile
arch/mips/tx4927/common/tx4927_irq.c
arch/mips/tx4927/common/tx4927_irq_handler.S [deleted file]
arch/mips/tx4938/common/Makefile
arch/mips/tx4938/common/irq.c
arch/mips/tx4938/common/irq_handler.S [deleted file]
arch/mips/vr41xx/Kconfig
arch/mips/vr41xx/common/Makefile
arch/mips/vr41xx/common/int-handler.S [deleted file]
arch/mips/vr41xx/common/irq.c
arch/powerpc/Kconfig
arch/powerpc/Makefile
arch/powerpc/kernel/Makefile
arch/powerpc/kernel/asm-offsets.c
arch/powerpc/kernel/entry_32.S
arch/powerpc/kernel/head_64.S
arch/powerpc/kernel/idle.c
arch/powerpc/kernel/idle_6xx.S
arch/powerpc/kernel/idle_power4.S
arch/powerpc/kernel/irq.c
arch/powerpc/kernel/kprobes.c
arch/powerpc/kernel/prom_init.c
arch/powerpc/kernel/rtas-proc.c
arch/powerpc/platforms/cell/spufs/switch.c
arch/powerpc/platforms/chrp/chrp.h
arch/powerpc/platforms/chrp/pci.c
arch/powerpc/platforms/chrp/setup.c
arch/powerpc/platforms/iseries/setup.c
arch/powerpc/platforms/pseries/eeh.c
arch/powerpc/platforms/pseries/rtasd.c
arch/ppc/syslib/ppc_sys.c
arch/sparc64/Kconfig
arch/sparc64/kernel/kprobes.c
arch/sparc64/kernel/pci.c
arch/um/drivers/cow_user.c
arch/um/include/longjmp.h
arch/um/include/sysdep-i386/kernel-offsets.h
arch/um/include/sysdep-x86_64/kernel-offsets.h
arch/um/os-Linux/mem.c
arch/um/os-Linux/process.c
arch/um/os-Linux/skas/process.c
arch/um/os-Linux/start_up.c
arch/um/os-Linux/trap.c
arch/um/os-Linux/uaccess.c
arch/um/os-Linux/util.c
arch/um/sys-i386/signal.c
arch/um/sys-i386/stub_segv.c
arch/um/sys-x86_64/stub_segv.c
arch/x86_64/defconfig
arch/x86_64/ia32/ia32entry.S
arch/x86_64/kernel/kprobes.c
arch/x86_64/kernel/process.c
arch/x86_64/kernel/setup.c
arch/x86_64/kernel/traps.c
block/as-iosched.c
block/cfq-iosched.c
block/elevator.c
block/ll_rw_blk.c
drivers/block/cciss.c
drivers/char/cs5535_gpio.c
drivers/char/drm/drmP.h
drivers/char/drm/drm_drv.c
drivers/char/drm/drm_memory.c
drivers/char/drm/drm_memory.h
drivers/char/drm/drm_memory_debug.h
drivers/char/drm/drm_pci.c
drivers/char/drm/via_irq.c
drivers/char/ipmi/ipmi_bt_sm.c
drivers/char/ipmi/ipmi_si_intf.c
drivers/char/sonypi.c
drivers/char/tty_io.c
drivers/cpufreq/Kconfig
drivers/cpufreq/cpufreq.c
drivers/cpufreq/cpufreq_conservative.c
drivers/i2c/busses/i2c-i801.c
drivers/i2c/chips/m41t00.c
drivers/ide/pci/alim15x3.c
drivers/ide/pci/atiixp.c
drivers/ide/pci/pdc202xx_old.c
drivers/ide/setup-pci.c
drivers/infiniband/core/mad.c
drivers/infiniband/hw/ipath/ipath_diag.c
drivers/infiniband/hw/ipath/ipath_driver.c
drivers/infiniband/hw/ipath/ipath_intr.c
drivers/infiniband/hw/ipath/ipath_kernel.h
drivers/infiniband/hw/ipath/ipath_layer.c
drivers/infiniband/hw/ipath/ipath_pe800.c
drivers/infiniband/hw/ipath/ipath_qp.c
drivers/infiniband/hw/ipath/ipath_ud.c
drivers/infiniband/hw/ipath/ipath_verbs.c
drivers/infiniband/hw/ipath/ipath_verbs.h
drivers/infiniband/hw/mthca/mthca_mad.c
drivers/infiniband/ulp/srp/ib_srp.c
drivers/md/md.c
drivers/net/sis900.c
drivers/net/sis900.h
drivers/parport/parport_pc.c
drivers/pci/quirks.c
drivers/pcmcia/at91_cf.c
drivers/pcmcia/pxa2xx_sharpsl.c
drivers/pnp/manager.c
drivers/s390/net/Makefile
drivers/s390/net/ctcmain.c
drivers/s390/net/ctcmain.h
drivers/s390/net/ctctty.c [deleted file]
drivers/s390/net/ctctty.h [deleted file]
drivers/serial/m32r_sio.c
drivers/usb/storage/Kconfig
drivers/video/aty/radeon_base.c
drivers/video/fbmem.c
drivers/video/pm2fb.c
drivers/video/savage/savagefb_driver.c
fs/Kconfig
fs/exec.c
fs/ext3/resize.c
fs/lockd/svclock.c
fs/locks.c
fs/nfs/dir.c
fs/nfs/direct.c
fs/nfs/file.c
fs/nfs/inode.c
fs/nfs/nfs4proc.c
fs/open.c
fs/partitions/check.c
fs/proc/base.c
fs/splice.c
include/asm-arm/unistd.h
include/asm-i386/atomic.h
include/asm-i386/cpufeature.h
include/asm-i386/i387.h
include/asm-m32r/assembler.h
include/asm-m32r/mappi3/mappi3_pld.h
include/asm-m32r/ptrace.h
include/asm-m32r/semaphore.h
include/asm-m32r/sigcontext.h
include/asm-m32r/system.h
include/asm-mips/asmmacro.h
include/asm-mips/cacheflush.h
include/asm-mips/cpu-features.h
include/asm-mips/cpu-info.h
include/asm-mips/ds1742.h [new file with mode: 0644]
include/asm-mips/elf.h
include/asm-mips/fpu.h
include/asm-mips/hazards.h
include/asm-mips/interrupt.h
include/asm-mips/irq.h
include/asm-mips/kspd.h [new file with mode: 0644]
include/asm-mips/mach-generic/ide.h
include/asm-mips/mach-jmr3927/ds1742.h
include/asm-mips/mach-mips/param.h [new file with mode: 0644]
include/asm-mips/marvell.h
include/asm-mips/mips-boards/atlas.h
include/asm-mips/mips-boards/atlasint.h
include/asm-mips/mips_mt.h [new file with mode: 0644]
include/asm-mips/mipsmtregs.h
include/asm-mips/mipsregs.h
include/asm-mips/mmu_context.h
include/asm-mips/processor.h
include/asm-mips/ptrace.h
include/asm-mips/r4kcache.h
include/asm-mips/rtc.h
include/asm-mips/rtlx.h
include/asm-mips/serial.h
include/asm-mips/smtc.h [new file with mode: 0644]
include/asm-mips/smtc_ipi.h [new file with mode: 0644]
include/asm-mips/smtc_proc.h [new file with mode: 0644]
include/asm-mips/stackframe.h
include/asm-mips/system.h
include/asm-mips/unistd.h
include/asm-mips/vpe.h [new file with mode: 0644]
include/asm-powerpc/irq.h
include/asm-powerpc/thread_info.h
include/asm-sparc/unistd.h
include/asm-sparc64/unistd.h
include/asm-x86_64/cache.h
include/asm-x86_64/cpufeature.h
include/asm-x86_64/i387.h
include/asm-x86_64/mmzone.h
include/asm-x86_64/percpu.h
include/asm-x86_64/unistd.h
include/asm-xtensa/ioctls.h
include/linux/ide.h
include/linux/memory_hotplug.h
include/linux/mv643xx.h
include/linux/pci_ids.h
include/linux/sched.h
include/linux/sunrpc/metrics.h
include/linux/sunrpc/xprt.h
include/net/ipv6.h
init/Kconfig
ipc/shm.c
ipc/util.c
kernel/exit.c
kernel/fork.c
kernel/kprobes.c
kernel/power/snapshot.c
kernel/uid16.c
lib/Kconfig.debug
mm/madvise.c
mm/mempolicy.c
mm/oom_kill.c
mm/page_alloc.c
mm/slob.c
net/core/filter.c
net/ipv4/ipcomp.c
net/ipv4/route.c
net/ipv4/tcp_output.c
net/ipv6/exthdrs.c
net/ipv6/ip6_input.c
net/ipv6/xfrm6_policy.c
net/sunrpc/auth_gss/auth_gss.c
net/sunrpc/auth_gss/gss_krb5_crypto.c
net/sunrpc/stats.c
net/tipc/name_distr.c
scripts/kconfig/conf.c
security/selinux/ss/mls.c
sound/drivers/mpu401/mpu401_uart.c
sound/oss/Kconfig
usr/gen_init_cpio.c

diff --git a/Documentation/block/switching-sched.txt b/Documentation/block/switching-sched.txt
new file mode 100644 (file)
index 0000000..5fa130a
--- /dev/null
@@ -0,0 +1,22 @@
+As of the Linux 2.6.10 kernel, it is now possible to change the
+IO scheduler for a given block device on the fly (thus making it possible,
+for instance, to set the CFQ scheduler for the system default, but
+set a specific device to use the anticipatory or noop schedulers - which
+can improve that device's throughput).
+
+To set a specific scheduler, simply do this:
+
+echo SCHEDNAME > /sys/block/DEV/queue/scheduler
+
+where SCHEDNAME is the name of a defined IO scheduler, and DEV is the
+device name (hda, hdb, sga, or whatever you happen to have).
+
+The list of defined schedulers can be found by simply doing
+a "cat /sys/block/DEV/queue/scheduler" - the list of valid names
+will be displayed, with the currently selected scheduler in brackets:
+
+# cat /sys/block/hda/queue/scheduler
+noop anticipatory deadline [cfq]
+# echo anticipatory > /sys/block/hda/queue/scheduler
+# cat /sys/block/hda/queue/scheduler
+noop [anticipatory] deadline cfq
index 5009805f9378b6b60a566da9e9644be0dc34acfc..ffdb5323df378b84963e4f91cd1470ff17865b6d 100644 (file)
@@ -53,4 +53,4 @@ the CPUFreq Mailing list:
 * http://lists.linux.org.uk/mailman/listinfo/cpufreq
 
 Clock and voltage scaling for the SA-1100:
-* http://www.lart.tudelft.nl/projects/scaling
+* http://www.lartmaker.nl/projects/scaling
index 293fed113dff3fe08dbffb4db235ca62612ea7fc..421bcfff6ad21be680fcf819243ca9d750fa8ab2 100644 (file)
@@ -25,8 +25,9 @@ Who:  Adrian Bunk <bunk@stusta.de>
 
 ---------------------------
 
-What:  drivers depending on OBSOLETE_OSS_DRIVER
-When:  January 2006
+What:  drivers that were depending on OBSOLETE_OSS_DRIVER
+        (config options already removed)
+When:  before 2.6.19
 Why:   OSS drivers with ALSA replacements
 Who:   Adrian Bunk <bunk@stusta.de>
 
index 42ef9970bc86b1ad762a5928942f63085be0019d..df82116a9f261c35998c3bb5a69eb1a38c8d83d1 100644 (file)
@@ -3,14 +3,11 @@
                        --------------------
 
 
-   $Id: driver,v 1.10 2002/07/22 15:27:30 rmk Exp $
-
-
 This document is meant as a brief overview of some aspects of the new serial
 driver.  It is not complete, any questions you have should be directed to
 <rmk@arm.linux.org.uk>
 
-The reference implementation is contained within serial_amba.c.
+The reference implementation is contained within amba_pl011.c.
 
 
 
@@ -31,6 +28,11 @@ The serial core provides a few helper functions.  This includes identifing
 the correct port structure (via uart_get_console) and decoding command line
 arguments (uart_parse_options).
 
+There is also a helper function (uart_write_console) which performs a
+character by character write, translating newlines to CRLF sequences.
+Driver writers are recommended to use this function rather than implementing
+their own version.
+
 
 Locking
 -------
@@ -86,6 +88,7 @@ hardware.
                - TIOCM_DTR     DTR signal.
                - TIOCM_OUT1    OUT1 signal.
                - TIOCM_OUT2    OUT2 signal.
+               - TIOCM_LOOP    Set the port into loopback mode.
        If the appropriate bit is set, the signal should be driven
        active.  If the bit is clear, the signal should be driven
        inactive.
@@ -141,6 +144,10 @@ hardware.
   enable_ms(port)
        Enable the modem status interrupts.
 
+       This method may be called multiple times.  Modem status
+       interrupts should be disabled when the shutdown method is
+       called.
+
        Locking: port->lock taken.
        Interrupts: locally disabled.
        This call must not sleep
@@ -160,6 +167,8 @@ hardware.
        state.  Enable the port for reception.  It should not activate
        RTS nor DTR; this will be done via a separate call to set_mctrl.
 
+       This method will only be called when the port is initially opened.
+
        Locking: port_sem taken.
        Interrupts: globally disabled.
 
@@ -169,6 +178,11 @@ hardware.
        RTS nor DTR; this will have already been done via a separate
        call to set_mctrl.
 
+       Drivers must not access port->info once this call has completed.
+
+       This method will only be called when there are no more users of
+       this port.
+
        Locking: port_sem taken.
        Interrupts: caller dependent.
 
index 2803f63c1a27622a3e3f3680d6c2a6398c993c7e..687104bfd09a79eef794b8dbe1357c33864d028c 100644 (file)
@@ -32,7 +32,16 @@ The output of "cat /proc/meminfo" will have lines like:
 .....
 HugePages_Total: xxx
 HugePages_Free:  yyy
-Hugepagesize:    zzz KB
+HugePages_Rsvd:  www
+Hugepagesize:    zzz kB
+
+where:
+HugePages_Total is the size of the pool of hugepages.
+HugePages_Free is the number of hugepages in the pool that are not yet
+allocated.
+HugePages_Rsvd is short for "reserved," and is the number of hugepages
+for which a commitment to allocate from the pool has been made, but no
+allocation has yet been made. It's vaguely analogous to overcommit.
 
 /proc/filesystems should also show a filesystem of type "hugetlbfs" configured
 in the kernel.
index b6dc07f1d63d92d59109be18e7cde49bfd19bed1..4d442eae377a0df8870fa9540cd4902741adf999 100644 (file)
@@ -411,6 +411,7 @@ AX.25 NETWORK LAYER
 P:     Ralf Baechle
 M:     ralf@linux-mips.org
 L:     linux-hams@vger.kernel.org
+W:     http://www.linux-ax25.org/
 S:     Maintained
 
 BAYCOM/HDLCDRV DRIVERS FOR AX.25
@@ -1463,6 +1464,13 @@ M:       support@pathscale.com
 L:     openib-general@openib.org
 S:     Supported
 
+IPMI SUBSYSTEM
+P:     Corey Minyard
+M:     minyard@acm.org
+L:     openipmi-developer@lists.sourceforge.net
+W:     http://openipmi.sourceforge.net/
+S:     Supported
+
 IPX NETWORK LAYER
 P:     Arnaldo Carvalho de Melo
 M:     acme@conectiva.com.br
@@ -1875,6 +1883,7 @@ NETROM NETWORK LAYER
 P:     Ralf Baechle
 M:     ralf@linux-mips.org
 L:     linux-hams@vger.kernel.org
+W:     http://www.linux-ax25.org/
 S:     Maintained
 
 NETWORK BLOCK DEVICE
@@ -2266,6 +2275,7 @@ ROSE NETWORK LAYER
 P:     Ralf Baechle
 M:     ralf@linux-mips.org
 L:     linux-hams@vger.kernel.org
+W:     http://www.linux-ax25.org/
 S:     Maintained
 
 RISCOM8 DRIVER
index fc8e08c419f09e81252f3aa41cb7f47524c0af60..a940eaefe1c4d7859a8a2aa6b5baa7808704a1c1 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 6
 SUBLEVEL = 17
-EXTRAVERSION =-rc1
+EXTRAVERSION =-rc2
 NAME=Sliding Snow Leopard
 
 # *DOCUMENTATION*
diff --git a/README b/README
index 05e055530bbb687599dd732d6753c77ffa281ae5..3e264723b863add275e6f32c44762f8d09cfe0a0 100644 (file)
--- a/README
+++ b/README
@@ -165,10 +165,31 @@ CONFIGURING the kernel:
        "make xconfig"     X windows (Qt) based configuration tool.
        "make gconfig"     X windows (Gtk) based configuration tool.
        "make oldconfig"   Default all questions based on the contents of
-                          your existing ./.config file.
+                          your existing ./.config file and asking about
+                          new config symbols.
        "make silentoldconfig"
                           Like above, but avoids cluttering the screen
                           with questions already answered.
+       "make defconfig"   Create a ./.config file by using the default
+                          symbol values from arch/$ARCH/defconfig.
+       "make allyesconfig"
+                          Create a ./.config file by setting symbol
+                          values to 'y' as much as possible.
+       "make allmodconfig"
+                          Create a ./.config file by setting symbol
+                          values to 'm' as much as possible.
+       "make allnoconfig" Create a ./.config file by setting symbol
+                          values to 'n' as much as possible.
+       "make randconfig"  Create a ./.config file by setting symbol
+                          values to random values.
+
+   The allyesconfig/allmodconfig/allnoconfig/randconfig variants can
+   also use the environment variable KCONFIG_ALLCONFIG to specify a
+   filename that contains config options that the user requires to be
+   set to a specific value.  If KCONFIG_ALLCONFIG=filename is not used,
+   "make *config" checks for a file named "all{yes/mod/no/random}.config"
+   for symbol values that are to be forced.  If this file is not found,
+   it checks for a file named "all.config" to contain forced values.
    
        NOTES on "make config":
        - having unnecessary drivers will make the kernel bigger, and can
index 5e830f444c6c6b9d8148b7cd34a505f30bdbf294..314ebd3a1d718c60f2d7f16f2f8a5dcb98239681 100644 (file)
 #include <asm/io.h>
 #include <asm/hardware/scoop.h>
 
+/* PCMCIA to Scoop linkage
+
+   There is no easy way to link multiple scoop devices into one
+   single entity for the pxa2xx_pcmcia device so this structure
+   is used which is setup by the platform code.
+
+   This file is never modular so this symbol is always
+   accessile to the board support files.
+*/
+struct scoop_pcmcia_config *platform_scoop_config;
+EXPORT_SYMBOL(platform_scoop_config);
+
 #define SCOOP_REG(d,adr) (*(volatile unsigned short*)(d +(adr)))
 
 struct  scoop_dev {
index 1781b8f342c4d1b43e53d7f1c5009c987c1d2cfb..bfe47bd6e50c595682322cdc909386ea73ded909 100644 (file)
@@ -194,13 +194,23 @@ void __init at91_add_device_eth(struct at91_eth_data *data) {}
 #if defined(CONFIG_AT91_CF) || defined(CONFIG_AT91_CF_MODULE)
 static struct at91_cf_data cf_data;
 
+static struct resource at91_cf_resources[] = {
+       [0] = {
+               .start  = AT91_CF_BASE,
+               /* ties up CS4, CS5, and CS6 */
+               .end    = AT91_CF_BASE + (0x30000000 - 1),
+               .flags  = IORESOURCE_MEM | IORESOURCE_MEM_8AND16BIT,
+       },
+};
+
 static struct platform_device at91rm9200_cf_device = {
        .name           = "at91_cf",
        .id             = -1,
        .dev            = {
                                .platform_data          = &cf_data,
        },
-       .num_resources  = 0,
+       .resource       = at91_cf_resources,
+       .num_resources  = ARRAY_SIZE(at91_cf_resources),
 };
 
 void __init at91_add_device_cf(struct at91_cf_data *data)
index b371d723635f38062d907059d5b9622604148f6b..8a25a1c8019f9bf7685f92561f04b1523a851c1a 100644 (file)
@@ -196,12 +196,9 @@ static int __init corgi_ssp_probe(struct platform_device *dev)
        int ret;
 
        /* Chip Select - Disable All */
-       GPDR(ssp_machinfo->cs_lcdcon) |= GPIO_bit(ssp_machinfo->cs_lcdcon); /* output */
-       GPSR(ssp_machinfo->cs_lcdcon) = GPIO_bit(ssp_machinfo->cs_lcdcon);  /* High - Disable LCD Control/Timing Gen */
-       GPDR(ssp_machinfo->cs_max1111) |= GPIO_bit(ssp_machinfo->cs_max1111); /* output */
-       GPSR(ssp_machinfo->cs_max1111) = GPIO_bit(ssp_machinfo->cs_max1111);  /* High - Disable MAX1111*/
-       GPDR(ssp_machinfo->cs_ads7846) |= GPIO_bit(ssp_machinfo->cs_ads7846);  /* output */
-       GPSR(ssp_machinfo->cs_ads7846) = GPIO_bit(ssp_machinfo->cs_ads7846);   /* High - Disable ADS7846*/
+       pxa_gpio_mode(ssp_machinfo->cs_lcdcon  | GPIO_OUT | GPIO_DFLT_HIGH);
+        pxa_gpio_mode(ssp_machinfo->cs_max1111 | GPIO_OUT | GPIO_DFLT_HIGH);
+        pxa_gpio_mode(ssp_machinfo->cs_ads7846 | GPIO_OUT | GPIO_DFLT_HIGH);
 
        ret = ssp_init(&corgi_ssp_dev, ssp_machinfo->port, 0);
 
index f372fbda124e14e68663ac5207374b04ae381a63..c940890f621f1902fe761773acd2aa9b999b8188 100644 (file)
@@ -50,7 +50,7 @@ static struct mtd_partition smdk_default_nand_part[] = {
                .offset = 0,
        },
        [1] = {
-               .name   = "S3C2410 flash parition 1",
+               .name   = "S3C2410 flash partition 1",
                .offset = 0,
                .size   = SZ_2M,
        },
index 57a15974d4b50aaded6667882e4004b459cca878..d7a30ed6c327eb57d2f3c4ff454939a70f6129fd 100644 (file)
@@ -139,7 +139,7 @@ static int s3c2440_clk_add(struct sys_device *sysdev)
 
                clkdivn = __raw_readl(S3C2410_CLKDIVN);
                clkdivn |= S3C2440_CLKDIVN_UCLK;
-               __raw_writel(camdivn, S3C2410_CLKDIVN);
+               __raw_writel(clkdivn, S3C2410_CLKDIVN);
 
                mutex_unlock(&clocks_mutex);
        }
index 6e97df6979e859cd9e82b4c47d40a13f0af197d0..c92191b1fb672935527bccbadfdd129065306edb 100644 (file)
@@ -81,4 +81,13 @@ config X86_MPPARSE
        depends on X86_LOCAL_APIC && !X86_VISWS
        default y
 
+config DOUBLEFAULT
+       default y
+       bool "Enable doublefault exception handler" if EMBEDDED
+       help
+          This option allows trapping of rare doublefault exceptions that
+          would otherwise cause a system to silently reboot. Disabling this
+          option saves about 4k and might cause you much additional grey
+          hair.
+
 endmenu
index 030a0007a4e075a5cf28408c18056088ab8d6f89..049a25583793a26cd85201a0e69a190880fa24c7 100644 (file)
@@ -168,7 +168,7 @@ int __init acpi_parse_mcfg(unsigned long phys_addr, unsigned long size)
        unsigned long i;
        int config_size;
 
-       if (!phys_addr || !size || !cpu_has_apic)
+       if (!phys_addr || !size)
                return -EINVAL;
 
        mcfg = (struct acpi_table_mcfg *)__acpi_map_table(phys_addr, size);
@@ -1102,6 +1102,9 @@ int __init acpi_boot_table_init(void)
        dmi_check_system(acpi_dmi_table);
 #endif
 
+       if (!cpu_has_apic)
+               return -ENODEV;
+
        /*
         * If acpi_disabled, bail out
         * One exception: acpi=ht continues far enough to enumerate LAPICs
index da30a374dd4efba117ecf8de4b10a4fdfb59f920..df0e1745f189764174a70bb3d5430e36a290a0f1 100644 (file)
@@ -1079,7 +1079,7 @@ static int apm_console_blank(int blank)
                        break;
        }
 
-       if (error == APM_NOT_ENGAGED && state != APM_STATE_READY) {
+       if (error == APM_NOT_ENGAGED) {
                static int tried;
                int eng_error;
                if (tried++ == 0) {
index ff2b2154ac1b6c8a0e4bddec0d27319575f47933..786d1a57048b9156396a7f7d5739306097420c60 100644 (file)
@@ -207,6 +207,8 @@ static void __init init_amd(struct cpuinfo_x86 *c)
                set_bit(X86_FEATURE_K7, c->x86_capability); 
                break;
        }
+       if (c->x86 >= 6)
+               set_bit(X86_FEATURE_FXSAVE_LEAK, c->x86_capability);
 
        display_cacheinfo(c);
 
index 7c0e160a214503e44a8209fc000900e23b5b9010..71fffa17442530949dccf45aa210c2e371188a59 100644 (file)
@@ -905,14 +905,17 @@ static int powernowk8_target(struct cpufreq_policy *pol, unsigned targfreq, unsi
 {
        cpumask_t oldmask = CPU_MASK_ALL;
        struct powernow_k8_data *data = powernow_data[pol->cpu];
-       u32 checkfid = data->currfid;
-       u32 checkvid = data->currvid;
+       u32 checkfid;
+       u32 checkvid;
        unsigned int newstate;
        int ret = -EIO;
 
        if (!data)
                return -EINVAL;
 
+       checkfid = data->currfid;
+       checkvid = data->currvid;
+
        /* only run on specific CPU from here on */
        oldmask = current->cpus_allowed;
        set_cpus_allowed(current, cpumask_of_cpu(pol->cpu));
@@ -1106,9 +1109,6 @@ static unsigned int powernowk8_get (unsigned int cpu)
 
        data = powernow_data[first_cpu(cpu_core_map[cpu])];
 
-       if (!data)
-               return -EINVAL;
-
        if (!data)
                return -EINVAL;
 
index 006141d1c12a080f2d3fe39464db9da8a7a7bdf7..1d9a4abcdfc71f034c1c822853049280b32de0a2 100644 (file)
@@ -168,7 +168,7 @@ static int cpuid_class_device_create(int i)
        return err;
 }
 
-static int __devinit cpuid_class_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu)
+static int cpuid_class_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu)
 {
        unsigned int cpu = (unsigned long)hcpu;
 
index f19768789e8a607203023d7ba3788efbc7bc3c1b..043f5292e70a203eda9ed4051331227adc6bffa5 100644 (file)
@@ -43,7 +43,7 @@ DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL;
 DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk);
 
 /* insert a jmp code */
-static inline void set_jmp_op(void *from, void *to)
+static __always_inline void set_jmp_op(void *from, void *to)
 {
        struct __arch_jmp_op {
                char op;
@@ -57,7 +57,7 @@ static inline void set_jmp_op(void *from, void *to)
 /*
  * returns non-zero if opcodes can be boosted.
  */
-static inline int can_boost(kprobe_opcode_t opcode)
+static __always_inline int can_boost(kprobe_opcode_t opcode)
 {
        switch (opcode & 0xf0 ) {
        case 0x70:
@@ -88,7 +88,7 @@ static inline int can_boost(kprobe_opcode_t opcode)
 /*
  * returns non-zero if opcode modifies the interrupt flag.
  */
-static inline int is_IF_modifier(kprobe_opcode_t opcode)
+static int __kprobes is_IF_modifier(kprobe_opcode_t opcode)
 {
        switch (opcode) {
        case 0xfa:              /* cli */
@@ -138,7 +138,7 @@ void __kprobes arch_remove_kprobe(struct kprobe *p)
        mutex_unlock(&kprobe_mutex);
 }
 
-static inline void save_previous_kprobe(struct kprobe_ctlblk *kcb)
+static void __kprobes save_previous_kprobe(struct kprobe_ctlblk *kcb)
 {
        kcb->prev_kprobe.kp = kprobe_running();
        kcb->prev_kprobe.status = kcb->kprobe_status;
@@ -146,7 +146,7 @@ static inline void save_previous_kprobe(struct kprobe_ctlblk *kcb)
        kcb->prev_kprobe.saved_eflags = kcb->kprobe_saved_eflags;
 }
 
-static inline void restore_previous_kprobe(struct kprobe_ctlblk *kcb)
+static void __kprobes restore_previous_kprobe(struct kprobe_ctlblk *kcb)
 {
        __get_cpu_var(current_kprobe) = kcb->prev_kprobe.kp;
        kcb->kprobe_status = kcb->prev_kprobe.status;
@@ -154,7 +154,7 @@ static inline void restore_previous_kprobe(struct kprobe_ctlblk *kcb)
        kcb->kprobe_saved_eflags = kcb->prev_kprobe.saved_eflags;
 }
 
-static inline void set_current_kprobe(struct kprobe *p, struct pt_regs *regs,
+static void __kprobes set_current_kprobe(struct kprobe *p, struct pt_regs *regs,
                                struct kprobe_ctlblk *kcb)
 {
        __get_cpu_var(current_kprobe) = p;
@@ -164,7 +164,7 @@ static inline void set_current_kprobe(struct kprobe *p, struct pt_regs *regs,
                kcb->kprobe_saved_eflags &= ~IF_MASK;
 }
 
-static inline void prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
+static void __kprobes prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
 {
        regs->eflags |= TF_MASK;
        regs->eflags &= ~IF_MASK;
@@ -507,7 +507,7 @@ no_change:
  * Interrupts are disabled on entry as trap1 is an interrupt gate and they
  * remain disabled thoroughout this function.
  */
-static inline int post_kprobe_handler(struct pt_regs *regs)
+static int __kprobes post_kprobe_handler(struct pt_regs *regs)
 {
        struct kprobe *cur = kprobe_running();
        struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
@@ -543,7 +543,7 @@ out:
        return 1;
 }
 
-static inline int kprobe_fault_handler(struct pt_regs *regs, int trapnr)
+static int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr)
 {
        struct kprobe *cur = kprobe_running();
        struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
index 1d0a55e687602ff49be8aed13771e76a1c43c3d2..7a328230e540f8b073e5d0306f457a1a9bffbc28 100644 (file)
@@ -251,7 +251,7 @@ static int msr_class_device_create(int i)
        return err;
 }
 
-static int __devinit msr_class_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu)
+static int msr_class_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu)
 {
        unsigned int cpu = (unsigned long)hcpu;
 
index 3039539de51e548a2a92eb83033278fc5daf38df..10d21df1453143c5c8d6c33c629a6267985f2385 100644 (file)
@@ -120,7 +120,6 @@ static struct resource qic_res = {
  * It writes num_bits of the data buffer in msg starting at start_bit.
  * Note: This function assumes that any unused bit in the data stream
  * is set to zero so that the ors will work correctly */
-#define BITS_PER_BYTE 8
 static void
 cat_pack(__u8 *msg, const __u16 start_bit, __u8 *data, const __u16 num_bits)
 {
index 789881ca83d43606e389b65b481a8fc99083fb54..f9039f88d01dfbcefb9174c0f59bb968fa92f5bd 100644 (file)
@@ -251,7 +251,7 @@ static void __kprobes prepare_break_inst(uint template, uint  slot,
        update_kprobe_inst_flag(template, slot, major_opcode, kprobe_inst, p);
 }
 
-static inline void get_kprobe_inst(bundle_t *bundle, uint slot,
+static void __kprobes get_kprobe_inst(bundle_t *bundle, uint slot,
                unsigned long *kprobe_inst, uint *major_opcode)
 {
        unsigned long kprobe_inst_p0, kprobe_inst_p1;
@@ -278,7 +278,7 @@ static inline void get_kprobe_inst(bundle_t *bundle, uint slot,
 }
 
 /* Returns non-zero if the addr is in the Interrupt Vector Table */
-static inline int in_ivt_functions(unsigned long addr)
+static int __kprobes in_ivt_functions(unsigned long addr)
 {
        return (addr >= (unsigned long)__start_ivt_text
                && addr < (unsigned long)__end_ivt_text);
@@ -308,19 +308,19 @@ static int __kprobes valid_kprobe_addr(int template, int slot,
        return 0;
 }
 
-static inline void save_previous_kprobe(struct kprobe_ctlblk *kcb)
+static void __kprobes save_previous_kprobe(struct kprobe_ctlblk *kcb)
 {
        kcb->prev_kprobe.kp = kprobe_running();
        kcb->prev_kprobe.status = kcb->kprobe_status;
 }
 
-static inline void restore_previous_kprobe(struct kprobe_ctlblk *kcb)
+static void __kprobes restore_previous_kprobe(struct kprobe_ctlblk *kcb)
 {
        __get_cpu_var(current_kprobe) = kcb->prev_kprobe.kp;
        kcb->kprobe_status = kcb->prev_kprobe.status;
 }
 
-static inline void set_current_kprobe(struct kprobe *p,
+static void __kprobes set_current_kprobe(struct kprobe *p,
                        struct kprobe_ctlblk *kcb)
 {
        __get_cpu_var(current_kprobe) = p;
index 3871b65f0c827966eede1b0cac8d1d07464198ff..920bb742b7a2a90394c133998809917f0bb33f56 100644 (file)
@@ -20,7 +20,7 @@
  * Stack layout in 'ret_from_system_call':
  *     ptrace needs to have all regs on the stack.
  *     if the order here is changed, it needs to be
- *     updated in fork.c:copy_process, signal.c:do_signal,
+ *     updated in fork.c:copy_thread, signal.c:do_signal,
  *     ptrace.c and ptrace.h
  *
  * M32Rx/M32R2                         M32R
  *       @(0x38,sp) - syscall_nr       ditto
  *       @(0x3c,sp) - acc0h            @(0x3c,sp) - acch
  *       @(0x40,sp) - acc0l            @(0x40,sp) - accl
- *       @(0x44,sp) - acc1h            @(0x44,sp) - psw
- *       @(0x48,sp) - acc1l            @(0x48,sp) - bpc
- *       @(0x4c,sp) - psw              @(0x4c,sp) - bbpsw
- *       @(0x50,sp) - bpc              @(0x50,sp) - bbpc
- *       @(0x54,sp) - bbpsw            @(0x54,sp) - spu (cr3)
- *       @(0x58,sp) - bbpc             @(0x58,sp) - fp (r13)
- *       @(0x5c,sp) - spu (cr3)                @(0x5c,sp) - lr (r14)
- *       @(0x60,sp) - fp (r13)         @(0x60,sp) - spi (cr12)
- *       @(0x64,sp) - lr (r14)         @(0x64,sp) - orig_r0
- *       @(0x68,sp) - spi (cr2)
- *       @(0x6c,sp) - orig_r0
- *
+ *       @(0x44,sp) - acc1h            @(0x44,sp) - dummy_acc1h
+ *       @(0x48,sp) - acc1l            @(0x48,sp) - dummy_acc1l
+ *       @(0x4c,sp) - psw              ditto
+ *       @(0x50,sp) - bpc              ditto
+ *       @(0x54,sp) - bbpsw            ditto
+ *       @(0x58,sp) - bbpc             ditto
+ *       @(0x5c,sp) - spu (cr3)                ditto
+ *       @(0x60,sp) - fp (r13)         ditto
+ *       @(0x64,sp) - lr (r14)         ditto
+ *       @(0x68,sp) - spi (cr2)                ditto
+ *       @(0x6c,sp) - orig_r0          ditto
  */
 
 #include <linux/config.h>
 #define ACC0L(reg)             @(0x40,reg)
 #define ACC1H(reg)             @(0x44,reg)
 #define ACC1L(reg)             @(0x48,reg)
+#elif defined(CONFIG_ISA_M32R2) || defined(CONFIG_ISA_M32R)
+#define ACCH(reg)              @(0x3C,reg)
+#define ACCL(reg)              @(0x40,reg)
+#else
+#error unknown isa configuration
+#endif
 #define PSW(reg)               @(0x4C,reg)
 #define BPC(reg)               @(0x50,reg)
 #define BBPSW(reg)             @(0x54,reg)
 #define LR(reg)                        @(0x64,reg)
 #define SP(reg)                        @(0x68,reg)
 #define ORIG_R0(reg)           @(0x6C,reg)
-#elif defined(CONFIG_ISA_M32R2) || defined(CONFIG_ISA_M32R)
-#define ACCH(reg)              @(0x3C,reg)
-#define ACCL(reg)              @(0x40,reg)
-#define PSW(reg)               @(0x44,reg)
-#define BPC(reg)               @(0x48,reg)
-#define BBPSW(reg)             @(0x4C,reg)
-#define BBPC(reg)              @(0x50,reg)
-#define SPU(reg)               @(0x54,reg)
-#define FP(reg)                        @(0x58,reg)  /* FP = R13 */
-#define LR(reg)                        @(0x5C,reg)
-#define SP(reg)                        @(0x60,reg)
-#define ORIG_R0(reg)           @(0x64,reg)
-#else
-#error unknown isa configuration
-#endif
 
 CF_MASK                = 0x00000001
 TF_MASK                = 0x00000100
@@ -142,7 +132,7 @@ VM_MASK             = 0x00020000
 #endif
 
 ENTRY(ret_from_fork)
-       ld      r0, @sp+
+       pop     r0
        bl      schedule_tail
        GET_THREAD_INFO(r8)
        bra     syscall_exit
@@ -231,7 +221,7 @@ restore_all:
        RESTORE_ALL
 
        # perform work that needs to be done immediately before resumption
-       # r9 : frags
+       # r9 : flags
        ALIGN
 work_pending:
        and3    r4, r9, #_TIF_NEED_RESCHED
@@ -320,7 +310,7 @@ ENTRY(ei_handler)
 ;    GET_ICU_STATUS;
        seth    r0, #shigh(M32R_ICU_ISTS_ADDR)
        ld      r0, @(low(M32R_ICU_ISTS_ADDR),r0)
-       st      r0, @-sp
+       push    r0
 #if defined(CONFIG_SMP)
        /*
         * If IRQ == 0      --> Nothing to do,  Not write IMASK
@@ -557,7 +547,7 @@ check_end:
 #endif  /* CONFIG_PLAT_M32104UT */
        bl      do_IRQ
 #endif  /* CONFIG_SMP */
-       ld      r14, @sp+
+       pop     r14
        seth    r0, #shigh(M32R_ICU_IMASK_ADDR)
        st      r14, @(low(M32R_ICU_IMASK_ADDR),r0)
 #else
@@ -1015,4 +1005,3 @@ ENTRY(sys_call_table)
        .long sys_waitid
 
 syscall_table_size=(.-sys_call_table)
-
index 5dfc7ea45cf7a9b19887f7de1049a7d337e5833e..065f5e7190587cf4e6a8122a34c64617523ab1cc 100644 (file)
@@ -116,6 +116,10 @@ void cpu_idle (void)
 
 void machine_restart(char *__unused)
 {
+#if defined(CONFIG_PLAT_MAPPI3)
+       outw(1, (unsigned long)PLD_REBOOT);
+#endif
+
        printk("Please push reset button!\n");
        while (1)
                cpu_relax();
index cb33097fefc4453475451d31443b2e380b97f0d5..6498ee70bb738d4c6aedf927b2b45d7de17215fe 100644 (file)
@@ -118,6 +118,8 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc,
 #elif defined(CONFIG_ISA_M32R2) || defined(CONFIG_ISA_M32R)
        COPY(acch);
        COPY(accl);
+       COPY(dummy_acc1h);
+       COPY(dummy_acc1l);
 #else
 #error unknown isa configuration
 #endif
@@ -203,6 +205,8 @@ setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs,
 #elif defined(CONFIG_ISA_M32R2) || defined(CONFIG_ISA_M32R)
        COPY(acch);
        COPY(accl);
+       COPY(dummy_acc1h);
+       COPY(dummy_acc1l);
 #else
 #error unknown isa configuration
 #endif
index 7aec60d4042091b1648b3f491194477cd266f909..87f0b79c6b1590b0875721d9ce16ca5c0d82a194 100644 (file)
@@ -816,6 +816,10 @@ config GENERIC_CALIBRATE_DELAY
        bool
        default y
 
+config SCHED_NO_NO_OMIT_FRAME_POINTER
+       bool
+       default y
+
 #
 # Select some configuration options automatically based on user selections.
 #
@@ -1443,6 +1447,10 @@ choice
        prompt "MIPS MT options"
        depends on MIPS_MT
 
+config MIPS_MT_SMTC
+       bool "SMTC: Use all TCs on all VPEs for SMP"
+       select SMP
+
 config MIPS_MT_SMP
        bool "Use 1 TC on each available VPE for SMP"
        select SMP
@@ -1456,6 +1464,11 @@ config MIPS_VPE_LOADER
 
 endchoice
 
+config MIPS_MT_FPAFF
+       bool "Dynamic FPU affinity for FP-intensive threads"
+       depends on MIPS_MT
+       default y
+
 config MIPS_VPE_LOADER_TOM
        bool "Load VPE program into memory hidden from linux"
        depends on MIPS_VPE_LOADER
@@ -1472,6 +1485,16 @@ config MIPS_VPE_APSP_API
        depends on MIPS_VPE_LOADER
        help
 
+config MIPS_APSP_KSPD
+       bool "Enable KSPD"
+       depends on MIPS_VPE_APSP_API
+       default y
+       help
+         KSPD is a kernel daemon that accepts syscall requests from the SP
+         side, actions them and returns the results. It also handles the
+         "exit" syscall notifying other kernel modules the SP program is
+         exiting.  You probably want to say yes here.
+
 config SB1_PASS_1_WORKAROUNDS
        bool
        depends on CPU_SB1_PASS_1
@@ -1599,7 +1622,7 @@ source "mm/Kconfig"
 
 config SMP
        bool "Multi-Processing support"
-       depends on CPU_RM9000 || ((SIBYTE_BCM1x80 || SIBYTE_BCM1x55 || SIBYTE_SB1250 || QEMU) && !SIBYTE_STANDALONE) || SGI_IP27 || MIPS_MT_SMP
+       depends on CPU_RM9000 || ((SIBYTE_BCM1x80 || SIBYTE_BCM1x55 || SIBYTE_SB1250 || QEMU) && !SIBYTE_STANDALONE) || SGI_IP27 || MIPS_MT_SMP || MIPS_MT_SMTC
        ---help---
          This enables support for systems with more than one CPU. If you have
          a system with only one CPU, like most personal computers, say N. If
index 9a69e0f0ab765db60737334d34e3793c03ffb441..69b9c1b8fafc6f72bb9dc010b1a4422c20ce6c3e 100644 (file)
@@ -105,18 +105,18 @@ cflags-$(CONFIG_CPU_R4300)        += -march=r4300 -Wa,--trap
 cflags-$(CONFIG_CPU_VR41XX)    += -march=r4100 -Wa,--trap
 cflags-$(CONFIG_CPU_R4X00)     += -march=r4600 -Wa,--trap
 cflags-$(CONFIG_CPU_TX49XX)    += -march=r4600 -Wa,--trap
-cflags-$(CONFIG_CPU_MIPS32_R1) += $(call cc-option,-march=mips32,-mips2 -mtune=r4600) \
+cflags-$(CONFIG_CPU_MIPS32_R1) += $(call cc-option,-march=mips32,-mips32 -U_MIPS_ISA -D_MIPS_ISA=_MIPS_ISA_MIPS32) \
                        -Wa,-mips32 -Wa,--trap
-cflags-$(CONFIG_CPU_MIPS32_R2) += $(call cc-option,-march=mips32r2,-mips2 -mtune=r4600) \
+cflags-$(CONFIG_CPU_MIPS32_R2) += $(call cc-option,-march=mips32r2,-mips32r2 -U_MIPS_ISA -D_MIPS_ISA=_MIPS_ISA_MIPS32) \
                        -Wa,-mips32r2 -Wa,--trap
-cflags-$(CONFIG_CPU_MIPS64_R1) += $(call cc-option,-march=mips64,-mips2 -mtune=r4600) \
+cflags-$(CONFIG_CPU_MIPS64_R1) += $(call cc-option,-march=mips64,-mips64 -U_MIPS_ISA -D_MIPS_ISA=_MIPS_ISA_MIPS64) \
                        -Wa,-mips64 -Wa,--trap
-cflags-$(CONFIG_CPU_MIPS64_R2) += $(call cc-option,-march=mips64r2,-mips2 -mtune=r4600 ) \
+cflags-$(CONFIG_CPU_MIPS64_R2) += $(call cc-option,-march=mips64r2,-mips64r2 -U_MIPS_ISA -D_MIPS_ISA=_MIPS_ISA_MIPS64) \
                        -Wa,-mips64r2 -Wa,--trap
 cflags-$(CONFIG_CPU_R5000)     += -march=r5000 -Wa,--trap
-cflags-$(CONFIG_CPU_R5432)     += $(call cc-options,-march=r5400,-march=r5000) \
+cflags-$(CONFIG_CPU_R5432)     += $(call cc-option,-march=r5400,-march=r5000) \
                        -Wa,--trap
-cflags-$(CONFIG_CPU_NEVADA)    += $(call cc-options,-march=rm5200,-march=r5000) \
+cflags-$(CONFIG_CPU_NEVADA)    += $(call cc-option,-march=rm5200,-march=r5000) \
                        -Wa,--trap
 cflags-$(CONFIG_CPU_RM7000)    += $(call cc-option,-march=rm7000,-march=r5000) \
                        -Wa,--trap
index a1edfd1f643c4f53a7ec3b0889a6db0b1441197c..bf682f50b8598b18f8dc29a6c3698fa2c96fd778 100644 (file)
@@ -6,7 +6,7 @@
 # Makefile for the Alchemy Au1000 CPU, generic files.
 #
 
-obj-y += prom.o int-handler.o irq.o puts.o time.o reset.o \
+obj-y += prom.o irq.o puts.o time.o reset.o \
        au1xxx_irqmap.o clocks.o platform.o power.o setup.o \
        sleeper.o cputable.o dma.o dbdma.o gpio.o
 
diff --git a/arch/mips/au1000/common/int-handler.S b/arch/mips/au1000/common/int-handler.S
deleted file mode 100644 (file)
index 1c4ca88..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright 2001 MontaVista Software Inc.
- * Author: ppopov@mvista.com
- *
- * Interrupt dispatcher for Au1000 boards.
- *
- * 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 <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/addrspace.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-
-       .text
-       .set    macro
-       .set    noat
-       .align  5
-
-NESTED(au1000_IRQ, PT_SIZE, sp)
-       SAVE_ALL
-       CLI                             # Important: mark KERNEL mode !
-
-       mfc0    t0,CP0_CAUSE            # get pending interrupts
-       mfc0    t1,CP0_STATUS           # get enabled interrupts
-       and     t0,t1                   # isolate allowed ones
-
-       andi    t0,0xff00               # isolate pending bits
-       beqz    t0, 3f                  # spurious interrupt
-
-       andi    a0, t0, CAUSEF_IP7
-       beq     a0, zero, 1f
-       move    a0, sp
-       jal     mips_timer_interrupt
-       j       ret_from_irq
-
-1:
-       andi    a0, t0, CAUSEF_IP2      # Interrupt Controller 0, Request 0
-       beq     a0, zero, 2f
-       move    a0,sp
-       jal     intc0_req0_irqdispatch
-       j       ret_from_irq
-2:
-       andi    a0, t0, CAUSEF_IP3      # Interrupt Controller 0, Request 1
-       beq     a0, zero, 3f
-       move    a0,sp
-       jal     intc0_req1_irqdispatch
-       j       ret_from_irq
-3:
-       andi    a0, t0, CAUSEF_IP4      # Interrupt Controller 1, Request 0
-       beq     a0, zero, 4f
-       move    a0,sp
-       jal     intc1_req0_irqdispatch
-       j       ret_from_irq
-4:
-       andi    a0, t0, CAUSEF_IP5      # Interrupt Controller 1, Request 1
-       beq     a0, zero, 5f
-       move    a0, sp
-       jal     intc1_req1_irqdispatch
-       j       ret_from_irq
-
-5:
-       move    a0, sp
-       j       spurious_interrupt
-END(au1000_IRQ)
index 1339a0979f66d61be72c1e65fdce3856ff558149..da61de7761549d89c3e5bc08204ebbdfdea5cd2a 100644 (file)
@@ -66,7 +66,6 @@
 #define EXT_INTC1_REQ1 5 /* IP 5 */
 #define MIPS_TIMER_IP  7 /* IP 7 */
 
-extern asmlinkage void au1000_IRQ(void);
 extern void set_debug_traps(void);
 extern irq_cpustat_t irq_stat [NR_CPUS];
 
@@ -446,7 +445,6 @@ void __init arch_init_irq(void)
        extern int au1xxx_ic0_nr_irqs;
 
        cp0_status = read_c0_status();
-       set_except_vector(0, au1000_IRQ);
 
        /* Initialize interrupt controllers to a safe state.
        */
@@ -661,3 +659,21 @@ restore_au1xxx_intctl(void)
        au_writel(sleep_intctl_mask[0], IC0_MASKSET); au_sync();
 }
 #endif /* CONFIG_PM */
+
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+       unsigned int pending = read_c0_status() & read_c0_cause() & ST0_IM;
+
+       if (pending & CAUSEF_IP7)
+               mips_timer_interrupt(regs);
+       else if (pending & CAUSEF_IP2)
+               intc0_req0_irqdispatch(regs);
+       else if (pending & CAUSEF_IP3)
+               intc0_req1_irqdispatch(regs);
+       else if (pending & CAUSEF_IP4)
+               intc1_req0_irqdispatch(regs);
+       else if (pending  & CAUSEF_IP5)
+               intc1_req1_irqdispatch(regs);
+       else
+               spurious_interrupt(regs);
+}
index 720e757b2b6413cded55f094fc802bd565671412..225ac8f34ccd574cb3dd6f9d68d9d569c4782ada 100644 (file)
@@ -2,7 +2,7 @@
 # Makefile for the Cobalt micro systems family specific parts of the kernel
 #
 
-obj-y   := irq.o int-handler.o reset.o setup.o
+obj-y   := irq.o reset.o setup.o
 
 obj-$(CONFIG_EARLY_PRINTK)     += console.o
 
diff --git a/arch/mips/cobalt/int-handler.S b/arch/mips/cobalt/int-handler.S
deleted file mode 100644 (file)
index e75d5e3..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 1995, 1996, 1997, 2003 by Ralf Baechle
- * Copyright (C) 2001, 2002, 2003 by Liam Davies (ldavies@agile.tv)
- */
-#include <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/mach-cobalt/cobalt.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-
-               .text
-               .align  5
-               NESTED(cobalt_handle_int, PT_SIZE, sp)
-               SAVE_ALL
-               CLI
-
-               PTR_LA  ra, ret_from_irq
-               move    a0, sp
-               j       cobalt_irq
-
-               END(cobalt_handle_int)
index f9a108820d6e2d1245eb64ac942df5418fba03e0..0b75f4fb719570ef4a8f29be227e8c1f3d5d00d0 100644 (file)
@@ -20,8 +20,6 @@
 
 #include <asm/mach-cobalt/cobalt.h>
 
-extern void cobalt_handle_int(void);
-
 /*
  * We have two types of interrupts that we handle, ones that come in through
  * the CPU interrupt lines, and ones that come in on the via chip. The CPU
@@ -79,7 +77,7 @@ static inline void via_pic_irq(struct pt_regs *regs)
                do_IRQ(irq, regs);
 }
 
-asmlinkage void cobalt_irq(struct pt_regs *regs)
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
 {
        unsigned pending;
 
@@ -122,8 +120,6 @@ void __init arch_init_irq(void)
         */
        GALILEO_OUTL(0, GT_INTRMASK_OFS);
 
-       set_except_vector(0, cobalt_handle_int);
-
        init_i8259_irqs();                              /*  0 ... 15 */
        mips_cpu_irq_init(COBALT_CPU_IRQ);              /* 16 ... 23 */
 
diff --git a/arch/mips/configs/tb0287_defconfig b/arch/mips/configs/tb0287_defconfig
new file mode 100644 (file)
index 0000000..8a1e3ac
--- /dev/null
@@ -0,0 +1,1096 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.16
+# Wed Mar 22 11:07:34 2006
+#
+CONFIG_MIPS=y
+
+#
+# Machine selection
+#
+# CONFIG_MIPS_MTX1 is not set
+# CONFIG_MIPS_BOSPORUS is not set
+# CONFIG_MIPS_PB1000 is not set
+# CONFIG_MIPS_PB1100 is not set
+# CONFIG_MIPS_PB1500 is not set
+# CONFIG_MIPS_PB1550 is not set
+# CONFIG_MIPS_PB1200 is not set
+# CONFIG_MIPS_DB1000 is not set
+# CONFIG_MIPS_DB1100 is not set
+# CONFIG_MIPS_DB1500 is not set
+# CONFIG_MIPS_DB1550 is not set
+# CONFIG_MIPS_DB1200 is not set
+# CONFIG_MIPS_MIRAGE is not set
+# CONFIG_MIPS_COBALT is not set
+# CONFIG_MACH_DECSTATION is not set
+# CONFIG_MIPS_EV64120 is not set
+# CONFIG_MIPS_EV96100 is not set
+# CONFIG_MIPS_IVR is not set
+# CONFIG_MIPS_ITE8172 is not set
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_LASAT is not set
+# CONFIG_MIPS_ATLAS is not set
+# CONFIG_MIPS_MALTA is not set
+# CONFIG_MIPS_SEAD is not set
+# CONFIG_MIPS_SIM is not set
+# CONFIG_MOMENCO_JAGUAR_ATX is not set
+# CONFIG_MOMENCO_OCELOT is not set
+# CONFIG_MOMENCO_OCELOT_3 is not set
+# CONFIG_MOMENCO_OCELOT_C is not set
+# CONFIG_MOMENCO_OCELOT_G is not set
+# CONFIG_MIPS_XXS1500 is not set
+# CONFIG_PNX8550_V2PCI is not set
+# CONFIG_PNX8550_JBS is not set
+# CONFIG_DDB5074 is not set
+# CONFIG_DDB5476 is not set
+# CONFIG_DDB5477 is not set
+CONFIG_MACH_VR41XX=y
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_QEMU is not set
+# CONFIG_SGI_IP22 is not set
+# CONFIG_SGI_IP27 is not set
+# CONFIG_SGI_IP32 is not set
+# CONFIG_SIBYTE_BIGSUR is not set
+# CONFIG_SIBYTE_SWARM is not set
+# CONFIG_SIBYTE_SENTOSA is not set
+# CONFIG_SIBYTE_RHONE is not set
+# CONFIG_SIBYTE_CARMEL is not set
+# CONFIG_SIBYTE_PTSWARM is not set
+# CONFIG_SIBYTE_LITTLESUR is not set
+# CONFIG_SIBYTE_CRHINE is not set
+# CONFIG_SIBYTE_CRHONE is not set
+# CONFIG_SNI_RM200_PCI is not set
+# CONFIG_TOSHIBA_JMR3927 is not set
+# CONFIG_TOSHIBA_RBTX4927 is not set
+# CONFIG_TOSHIBA_RBTX4938 is not set
+# CONFIG_CASIO_E55 is not set
+# CONFIG_IBM_WORKPAD is not set
+# CONFIG_NEC_CMBVR4133 is not set
+CONFIG_TANBAC_TB022X=y
+# CONFIG_TANBAC_TB0226 is not set
+CONFIG_TANBAC_TB0287=y
+# CONFIG_VICTOR_MPC30X is not set
+# CONFIG_ZAO_CAPCELLA is not set
+CONFIG_PCI_VR41XX=y
+# CONFIG_VRC4173 is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_DMA_NONCOHERENT=y
+CONFIG_DMA_NEED_PCI_MAP_STATE=y
+# CONFIG_CPU_BIG_ENDIAN is not set
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y
+CONFIG_IRQ_CPU=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+
+#
+# CPU selection
+#
+# CONFIG_CPU_MIPS32_R1 is not set
+# CONFIG_CPU_MIPS32_R2 is not set
+# CONFIG_CPU_MIPS64_R1 is not set
+# CONFIG_CPU_MIPS64_R2 is not set
+# CONFIG_CPU_R3000 is not set
+# CONFIG_CPU_TX39XX is not set
+CONFIG_CPU_VR41XX=y
+# CONFIG_CPU_R4300 is not set
+# CONFIG_CPU_R4X00 is not set
+# CONFIG_CPU_TX49XX is not set
+# CONFIG_CPU_R5000 is not set
+# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R6000 is not set
+# CONFIG_CPU_NEVADA is not set
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_R10000 is not set
+# CONFIG_CPU_RM7000 is not set
+# CONFIG_CPU_RM9000 is not set
+# CONFIG_CPU_SB1 is not set
+CONFIG_SYS_HAS_CPU_VR41XX=y
+CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
+CONFIG_SYS_SUPPORTS_64BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y
+
+#
+# Kernel type
+#
+CONFIG_32BIT=y
+# CONFIG_64BIT is not set
+CONFIG_PAGE_SIZE_4KB=y
+# CONFIG_PAGE_SIZE_8KB is not set
+# CONFIG_PAGE_SIZE_16KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
+# CONFIG_MIPS_MT is not set
+# CONFIG_CPU_ADVANCED is not set
+CONFIG_CPU_HAS_SYNC=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+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_IKCONFIG is not set
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+# CONFIG_HOTPLUG is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+CONFIG_SLAB=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_KMOD=y
+
+#
+# Block layer
+#
+# CONFIG_LBD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+CONFIG_HW_HAS_PCI=y
+CONFIG_PCI=y
+# CONFIG_PCI_LEGACY_PROC is not set
+CONFIG_MMU=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PCI Hotplug Support
+#
+# CONFIG_HOTPLUG_PCI is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_TRAD_SIGNALS=y
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+CONFIG_XFRM_USER=m
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_ASK_IP_FIB_HASH=y
+# CONFIG_IP_FIB_TRIE is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+# CONFIG_IP_ROUTE_MULTIPATH_CACHED is not set
+CONFIG_IP_ROUTE_VERBOSE=y
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+CONFIG_NET_IPIP=m
+CONFIG_NET_IPGRE=m
+# CONFIG_NET_IPGRE_BROADCAST is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+CONFIG_INET_TUNNEL=m
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+CONFIG_TCP_CONG_ADVANCED=y
+
+#
+# TCP congestion control
+#
+CONFIG_TCP_CONG_BIC=y
+CONFIG_TCP_CONG_CUBIC=m
+CONFIG_TCP_CONG_WESTWOOD=m
+CONFIG_TCP_CONG_HTCP=m
+# CONFIG_TCP_CONG_HSTCP is not set
+# CONFIG_TCP_CONG_HYBLA is not set
+# CONFIG_TCP_CONG_VEGAS is not set
+# CONFIG_TCP_CONG_SCALABLE is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET 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
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=m
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+CONFIG_BLK_DEV_NBD=m
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE 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
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+CONFIG_BLK_DEV_IDEPCI=y
+# CONFIG_IDEPCI_SHARE_IRQ is not set
+# CONFIG_BLK_DEV_OFFBOARD is not set
+# CONFIG_BLK_DEV_GENERIC is not set
+# CONFIG_BLK_DEV_OPTI621 is not set
+CONFIG_BLK_DEV_IDEDMA_PCI=y
+# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
+# CONFIG_IDEDMA_PCI_AUTO is not set
+# CONFIG_BLK_DEV_AEC62XX is not set
+# CONFIG_BLK_DEV_ALI15X3 is not set
+# CONFIG_BLK_DEV_AMD74XX is not set
+# CONFIG_BLK_DEV_CMD64X is not set
+# CONFIG_BLK_DEV_TRIFLEX is not set
+# CONFIG_BLK_DEV_CY82C693 is not set
+# CONFIG_BLK_DEV_CS5520 is not set
+# CONFIG_BLK_DEV_CS5530 is not set
+# CONFIG_BLK_DEV_HPT34X is not set
+# CONFIG_BLK_DEV_HPT366 is not set
+# CONFIG_BLK_DEV_SC1200 is not set
+# CONFIG_BLK_DEV_PIIX is not set
+# CONFIG_BLK_DEV_IT821X is not set
+# CONFIG_BLK_DEV_NS87415 is not set
+# CONFIG_BLK_DEV_PDC202XX_OLD is not set
+# CONFIG_BLK_DEV_PDC202XX_NEW is not set
+# CONFIG_BLK_DEV_SVWKS is not set
+CONFIG_BLK_DEV_SIIMAGE=y
+# CONFIG_BLK_DEV_SLC90E66 is not set
+# CONFIG_BLK_DEV_TRM290 is not set
+# CONFIG_BLK_DEV_VIA82CXXX is not set
+# CONFIG_IDE_ARM is not set
+CONFIG_BLK_DEV_IDEDMA=y
+# CONFIG_IDEDMA_IVB is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+# CONFIG_CHR_DEV_SG is not set
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI Transport Attributes
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_ISCSI_TCP is not set
+# 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_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_MEGARAID_SAS is not set
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+# CONFIG_SCSI_IPR is not set
+# CONFIG_SCSI_QLOGIC_FC is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+# CONFIG_SCSI_QLA_FC is not set
+# CONFIG_SCSI_LPFC is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T 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
+# CONFIG_FUSION_SPI is not set
+# CONFIG_FUSION_FC is not set
+# CONFIG_FUSION_SAS is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+CONFIG_IEEE1394=m
+
+#
+# Subsystem Options
+#
+# CONFIG_IEEE1394_VERBOSEDEBUG is not set
+# CONFIG_IEEE1394_OUI_DB is not set
+CONFIG_IEEE1394_EXTRA_CONFIG_ROMS=y
+CONFIG_IEEE1394_CONFIG_ROM_IP1394=y
+# CONFIG_IEEE1394_EXPORT_FULL_API is not set
+
+#
+# Device Drivers
+#
+
+#
+# Texas Instruments PCILynx requires I2C
+#
+CONFIG_IEEE1394_OHCI1394=m
+
+#
+# Protocol Drivers
+#
+CONFIG_IEEE1394_VIDEO1394=m
+CONFIG_IEEE1394_SBP2=m
+# CONFIG_IEEE1394_SBP2_PHYS_DMA is not set
+CONFIG_IEEE1394_ETH1394=m
+CONFIG_IEEE1394_DV1394=m
+CONFIG_IEEE1394_RAWIO=m
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+CONFIG_DUMMY=m
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_CASSINI is not set
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_DM9000 is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+# CONFIG_NET_PCI is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+CONFIG_R8169=y
+# CONFIG_R8169_NAPI is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SKGE is not set
+# CONFIG_SKY2 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_CHELSIO_T1 is not set
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN 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
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# 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 Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_SERIAL_VR41XX=y
+CONFIG_SERIAL_VR41XX_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_RTC_VR41XX is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+# CONFIG_TANBAC_TB0219 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_DRM is not set
+CONFIG_GPIO_VR41XX=y
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Hardware Monitoring support
+#
+# CONFIG_HWMON is not set
+# CONFIG_HWMON_VID is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia Capabilities Port drivers
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB=m
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+# CONFIG_USB_DEVICEFS is not set
+# CONFIG_USB_BANDWIDTH is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+CONFIG_USB_EHCI_HCD=m
+# CONFIG_USB_EHCI_SPLIT_ISO is not set
+# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
+# CONFIG_USB_ISP116X_HCD is not set
+CONFIG_USB_OHCI_HCD=m
+# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+# CONFIG_USB_UHCI_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# may also be needed; see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=m
+# 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_USBAT 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_STORAGE_ALAUDA is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=m
+CONFIG_USB_HIDINPUT=y
+# CONFIG_USB_HIDINPUT_POWERBOOK is not set
+# CONFIG_HID_FF is not set
+# CONFIG_USB_HIDDEV is not set
+
+#
+# USB HID Boot Protocol drivers
+#
+# CONFIG_USB_KBD is not set
+# CONFIG_USB_MOUSE is not set
+# CONFIG_USB_AIPTEK is not set
+# CONFIG_USB_WACOM is not set
+# CONFIG_USB_ACECAD is not set
+# CONFIG_USB_KBTAB is not set
+# CONFIG_USB_POWERMATE is not set
+# CONFIG_USB_MTOUCH is not set
+# CONFIG_USB_ITMTOUCH is not set
+# CONFIG_USB_EGALAX is not set
+# CONFIG_USB_YEALINK is not set
+# CONFIG_USB_XPAD is not set
+# CONFIG_USB_ATI_REMOTE is not set
+# CONFIG_USB_ATI_REMOTE2 is not set
+# CONFIG_USB_KEYSPAN_REMOTE is not set
+# CONFIG_USB_APPLETOUCH is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB Multimedia devices
+#
+# CONFIG_USB_DABUSB is not set
+
+#
+# Video4Linux support is needed for USB Multimedia device support
+#
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET is not set
+CONFIG_USB_MON=y
+
+#
+# USB port drivers
+#
+
+#
+# USB Serial Converter support
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGETKIT is not set
+# CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_SISUSBVGA is not set
+# CONFIG_USB_LD is not set
+
+#
+# USB DSL modem support
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+CONFIG_XFS_FS=y
+CONFIG_XFS_QUOTA=y
+# CONFIG_XFS_SECURITY is not set
+CONFIG_XFS_POSIX_ACL=y
+# CONFIG_XFS_RT is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+CONFIG_ROMFS_FS=m
+CONFIG_INOTIFY=y
+# CONFIG_QUOTA is not set
+CONFIG_QUOTACTL=y
+# CONFIG_DNOTIFY is not set
+# CONFIG_AUTOFS_FS is not set
+CONFIG_AUTOFS4_FS=y
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# 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_TMPFS=y
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_RELAYFS_FS is not set
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# 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_EFS_FS is not set
+CONFIG_CRAMFS=m
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# 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_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 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
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_CROSSCOMPILE=y
+CONFIG_CMDLINE="mem=64M console=ttyVR0,115200 ip=any root=/dev/nfs"
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+CONFIG_KEYS_DEBUG_PROC_KEYS=y
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=m
index 488206b8d94e7459ada11008325683a9ba95256f..304c02107b468169ac429f5fe0c27988b12f973f 100644 (file)
@@ -3,6 +3,6 @@
 # under Linux.
 #
 
-obj-y                  += setup.o irq.o int-handler.o nile4_pic.o
+obj-y                  += setup.o irq.o nile4_pic.o
 
 EXTRA_AFLAGS := $(CFLAGS)
diff --git a/arch/mips/ddb5xxx/ddb5074/int-handler.S b/arch/mips/ddb5xxx/ddb5074/int-handler.S
deleted file mode 100644 (file)
index a786441..0000000
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- *  arch/mips/ddb5074/int-handler.S -- NEC DDB Vrc-5074 interrupt handler
- *
- *  Based on arch/mips/sgi/kernel/indyIRQ.S
- *
- *  Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
- *
- *  Copyright (C) 2000 Geert Uytterhoeven <geert@sonycom.com>
- *                     Sony Software Development Center Europe (SDCE), Brussels
- */
-#include <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-
-/* A lot of complication here is taken away because:
- *
- * 1) We handle one interrupt and return, sitting in a loop and moving across
- *    all the pending IRQ bits in the cause register is _NOT_ the answer, the
- *    common case is one pending IRQ so optimize in that direction.
- *
- * 2) We need not check against bits in the status register IRQ mask, that
- *    would make this routine slow as hell.
- *
- * 3) Linux only thinks in terms of all IRQs on or all IRQs off, nothing in
- *    between like BSD spl() brain-damage.
- *
- * Furthermore, the IRQs on the INDY look basically (barring software IRQs
- * which we don't use at all) like:
- *
- *     MIPS IRQ        Source
- *      --------        ------
- *             0       Software (ignored)
- *             1        Software (ignored)
- *             2        Local IRQ level zero
- *             3        Local IRQ level one
- *             4        8254 Timer zero
- *             5        8254 Timer one
- *             6        Bus Error
- *             7        R4k timer (what we use)
- *
- * We handle the IRQ according to _our_ priority which is:
- *
- * Highest ----     R4k Timer
- *                  Local IRQ zero
- *                  Local IRQ one
- *                  Bus Error
- *                  8254 Timer zero
- * Lowest  ----     8254 Timer one
- *
- * then we just return, if multiple IRQs are pending then we will just take
- * another exception, big deal.
- */
-
-       .text
-       .set    noreorder
-       .set    noat
-       .align  5
-       NESTED(ddbIRQ, PT_SIZE, sp)
-       SAVE_ALL
-       CLI
-       .set    at
-       mfc0    s0, CP0_CAUSE           # get irq mask
-
-#if 1
-       mfc0    t2,CP0_STATUS           # get enabled interrupts
-       and     s0,t2                   # isolate allowed ones
-#endif
-       /* First we check for r4k counter/timer IRQ. */
-       andi    a0, s0, CAUSEF_IP2      # delay slot, check local level zero
-       beq     a0, zero, 1f
-        andi   a0, s0, CAUSEF_IP3      # delay slot, check local level one
-
-       /* Wheee, local level zero interrupt. */
-       jal     ddb_local0_irqdispatch
-        move   a0, sp                  # delay slot
-
-       j       ret_from_irq
-        nop                            # delay slot
-
-1:
-       beq     a0, zero, 1f
-        andi   a0, s0, CAUSEF_IP6      # delay slot, check bus error
-
-       /* Wheee, local level one interrupt. */
-       move    a0, sp
-       jal     ddb_local1_irqdispatch
-        nop
-
-       j       ret_from_irq
-        nop
-
-1:
-       beq     a0, zero, 1f
-        nop
-
-       /* Wheee, an asynchronous bus error... */
-       move    a0, sp
-       jal     ddb_buserror_irq
-        nop
-
-       j       ret_from_irq
-        nop
-
-1:
-       /* Here by mistake?  This is possible, what can happen
-        * is that by the time we take the exception the IRQ
-        * pin goes low, so just leave if this is the case.
-        */
-       andi    a0, s0, (CAUSEF_IP4 | CAUSEF_IP5)
-       beq     a0, zero, 1f
-
-       /* Must be one of the 8254 timers... */
-       move    a0, sp
-       jal     ddb_8254timer_irq
-        nop
-1:
-       j       ret_from_irq
-        nop
-       END(ddbIRQ)
index 45088a1be4142a39c9cb2a8e5be63173778b63bf..60c087b7738c3c360214a788aa0528537b0b3852 100644 (file)
@@ -21,8 +21,6 @@
 #include <asm/ddb5xxx/ddb5074.h>
 
 
-extern asmlinkage void ddbIRQ(void);
-
 static struct irqaction irq_cascade = { no_action, 0, CPU_MASK_NONE, "cascade", NULL, NULL };
 
 #define M1543_PNP_CONFIG       0x03f0  /* PnP Config Port */
@@ -90,7 +88,7 @@ static void m1543_irq_setup(void)
 
 }
 
-void ddb_local0_irqdispatch(struct pt_regs *regs)
+static void ddb_local0_irqdispatch(struct pt_regs *regs)
 {
        u32 mask;
        int nile4_irq;
@@ -118,29 +116,41 @@ void ddb_local0_irqdispatch(struct pt_regs *regs)
                }
 }
 
-void ddb_local1_irqdispatch(void)
+static void ddb_local1_irqdispatch(void)
 {
        printk("ddb_local1_irqdispatch called\n");
 }
 
-void ddb_buserror_irq(void)
+static void ddb_buserror_irq(void)
 {
        printk("ddb_buserror_irq called\n");
 }
 
-void ddb_8254timer_irq(void)
+static void ddb_8254timer_irq(void)
 {
        printk("ddb_8254timer_irq called\n");
 }
 
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+       unsigned int pending = read_c0_cause() & read_c0_status();
+
+       if (pending & CAUSEF_IP2)
+               ddb_local0_irqdispatch(regs);
+       else if (pending & CAUSEF_IP3)
+               ddb_local1_irqdispatch();
+       else if (pending & CAUSEF_IP6)
+               ddb_buserror_irq();
+       else if (pending & (CAUSEF_IP4 | CAUSEF_IP5))
+               ddb_8254timer_irq();
+}
+
 void __init arch_init_irq(void)
 {
        /* setup cascade interrupts */
        setup_irq(NILE4_IRQ_BASE  + NILE4_INT_INTE, &irq_cascade);
        setup_irq(CPU_IRQ_BASE + CPU_NILE4_CASCADE, &irq_cascade);
 
-       set_except_vector(0, ddbIRQ);
-
        nile4_irq_setup(NILE4_IRQ_BASE);
        m1543_irq_setup();
        init_i8259_irqs();
index 61eec363cb02593b5c706e80d12276319acaa664..ab0312cb47b4552c6578720fa62763f386ed7d7a 100644 (file)
@@ -3,7 +3,7 @@
 # under Linux.
 #
 
-obj-y                  += setup.o irq.o int-handler.o nile4_pic.o vrc5476_irq.o
+obj-y                  += setup.o irq.o nile4_pic.o vrc5476_irq.o
 obj-$(CONFIG_KGDB)     += dbg_io.o
 
 EXTRA_AFLAGS := $(CFLAGS)
diff --git a/arch/mips/ddb5xxx/ddb5476/int-handler.S b/arch/mips/ddb5xxx/ddb5476/int-handler.S
deleted file mode 100644 (file)
index 12c292e..0000000
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Copyright 2001 MontaVista Software Inc.
- * Author: jsun@mvista.com or jsun@junsun.net
- *
- * First-level interrupt dispatcher for ddb5476
- *
- * 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 <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/addrspace.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-
-#include <asm/ddb5xxx/ddb5476.h>
-
-/*
- * first level interrupt dispatcher for ocelot board -
- * We check for the timer first, then check PCI ints A and D.
- * Then check for serial IRQ and fall through.
- */
-       .align  5
-       NESTED(ddb5476_handle_int, PT_SIZE, sp)
-       SAVE_ALL
-       CLI
-       .set    at
-       .set    noreorder
-       mfc0    t0, CP0_CAUSE
-       mfc0    t2, CP0_STATUS
-
-       and     t0, t2
-
-        andi    t1, t0, STATUSF_IP7     /* cpu timer */
-        bnez    t1, ll_cpu_ip7
-        andi    t1, t0, STATUSF_IP2    /* vrc5476 & i8259 */
-        bnez    t1, ll_cpu_ip2
-        andi    t1, t0, STATUSF_IP3
-        bnez    t1, ll_cpu_ip3
-        andi    t1, t0, STATUSF_IP4
-        bnez    t1, ll_cpu_ip4
-        andi    t1, t0, STATUSF_IP5
-        bnez    t1, ll_cpu_ip5
-        andi    t1, t0, STATUSF_IP6
-        bnez    t1, ll_cpu_ip6
-        andi    t1, t0, STATUSF_IP0     /* software int 0 */
-        bnez    t1, ll_cpu_ip0
-        andi    t1, t0, STATUSF_IP1     /* software int 1 */
-        bnez    t1, ll_cpu_ip1
-        nop
-
-       .set    reorder
-
-       /* wrong alarm or masked ... */
-       // j    spurious_interrupt
-       move    a0, sp
-       jal     vrc5476_irq_dispatch
-       j       ret_from_irq
-       nop
-
-       .align  5
-
-ll_cpu_ip0:
-       li      a0, CPU_IRQ_BASE + 0
-       move    a1, sp
-       jal     do_IRQ
-       j       ret_from_irq
-
-ll_cpu_ip1:
-       li      a0, CPU_IRQ_BASE + 1
-       move    a1, sp
-       jal     do_IRQ
-       j       ret_from_irq
-
-ll_cpu_ip2:            /* jump to second-level dispatching */
-       move    a0, sp
-       jal     vrc5476_irq_dispatch
-       j       ret_from_irq
-
-ll_cpu_ip3:
-       li      a0, CPU_IRQ_BASE + 3
-       move    a1, sp
-       jal     do_IRQ
-       j       ret_from_irq
-
-ll_cpu_ip4:
-       li      a0, CPU_IRQ_BASE + 4
-       move    a1, sp
-       jal     do_IRQ
-       j       ret_from_irq
-
-ll_cpu_ip5:
-       li      a0, CPU_IRQ_BASE + 5
-       move    a1, sp
-       jal     do_IRQ
-       j       ret_from_irq
-
-ll_cpu_ip6:
-       li      a0, CPU_IRQ_BASE + 6
-       move    a1, sp
-       jal     do_IRQ
-       j       ret_from_irq
-
-ll_cpu_ip7:
-       li      a0, CPU_IRQ_BASE + 7
-       move    a1, sp
-       jal     do_IRQ
-       j       ret_from_irq
-
-       END(ddb5476_handle_int)
index 5388b5868c4a6b31ab5bb126bbde379f88d125f6..7583a1f307118e483707ee9e30415521bce27efe 100644 (file)
@@ -110,11 +110,36 @@ static void nile4_irq_setup(void)
 static struct irqaction irq_cascade = { no_action, 0, CPU_MASK_NONE, "cascade", NULL, NULL };
 static struct irqaction irq_error = { no_action, 0, CPU_MASK_NONE, "error", NULL, NULL };
 
-extern asmlinkage void ddb5476_handle_int(void);
 extern int setup_irq(unsigned int irq, struct irqaction *irqaction);
 extern void mips_cpu_irq_init(u32 irq_base);
 extern void vrc5476_irq_init(u32 irq_base);
 
+extern void vrc5476_irq_dispatch(struct pt_regs *regs);
+
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+       unsigned int pending = read_c0_cause() & read_c0_status();
+
+       if (pending & STATUSF_IP7)
+               do_IRQ(CPU_IRQ_BASE + 7, regs);
+       else if (pending & STATUSF_IP2)
+               vrc5476_irq_dispatch(regs);
+       else if (pending & STATUSF_IP3)
+               do_IRQ(CPU_IRQ_BASE + 3, regs);
+       else if (pending & STATUSF_IP4)
+               do_IRQ(CPU_IRQ_BASE + 4, regs);
+       else if (pending & STATUSF_IP5)
+               do_IRQ(CPU_IRQ_BASE + 5, regs);
+       else if (pending & STATUSF_IP6)
+               do_IRQ(CPU_IRQ_BASE + 6, regs);
+       else if (pending & STATUSF_IP0)
+               do_IRQ(CPU_IRQ_BASE, regs);
+       else if (pending & STATUSF_IP1)
+               do_IRQ(CPU_IRQ_BASE + 1, regs);
+
+       vrc5476_irq_dispatch(regs);
+}
+
 void __init arch_init_irq(void)
 {
        /* hardware initialization */
@@ -137,7 +162,4 @@ void __init arch_init_irq(void)
        setup_irq(VRC5476_IRQ_BASE + VRC5476_IRQ_LBRT, &irq_error);
        setup_irq(VRC5476_IRQ_BASE + VRC5476_IRQ_PCIS, &irq_error);
        setup_irq(VRC5476_IRQ_BASE + VRC5476_IRQ_PCI, &irq_error);
-
-       /* setup the grandpa intr vector */
-       set_except_vector(0, ddb5476_handle_int);
 }
index f66fe5b5863660b4014c953ba8726f8b1fe6c87e..a3c5e7b18018015e89df25a5613f2dc5bccba9bb 100644 (file)
@@ -77,11 +77,9 @@ vrc5476_irq_init(u32 base)
 }
 
 
-asmlinkage void
+void
 vrc5476_irq_dispatch(struct pt_regs *regs)
 {
-       extern void spurious_interrupt(void);
-
        u32 mask;
        int nile4_irq;
 
@@ -107,5 +105,5 @@ vrc5476_irq_dispatch(struct pt_regs *regs)
                        return;
                }
        }
-       spurious_interrupt();
+       spurious_interrupt(regs);
 }
index b79b43c9f93b399775d4c769d0d56a1ecc0f9b91..ea68815ad17ae5be6542f0bba36107c5f4fd6b62 100644 (file)
@@ -2,7 +2,7 @@
 # Makefile for NEC DDB-Vrc5477 board
 #
 
-obj-y                  += int-handler.o irq.o irq_5477.o setup.o lcd44780.o
+obj-y                  += irq.o irq_5477.o setup.o lcd44780.o
 
 obj-$(CONFIG_RUNTIME_DEBUG)    += debug.o
 obj-$(CONFIG_KGDB)             += kgdb_io.o
diff --git a/arch/mips/ddb5xxx/ddb5477/int-handler.S b/arch/mips/ddb5xxx/ddb5477/int-handler.S
deleted file mode 100644 (file)
index a2502a1..0000000
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright 2001 MontaVista Software Inc.
- * Author: jsun@mvista.com or jsun@junsun.net
- *
- * First-level interrupt dispatcher for ddb5477
- *
- * 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 <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/addrspace.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-#include <asm/ddb5xxx/ddb5477.h>
-
-/*
- * first level interrupt dispatcher for ocelot board -
- * We check for the timer first, then check PCI ints A and D.
- * Then check for serial IRQ and fall through.
- */
-       .align  5
-       NESTED(ddb5477_handle_int, PT_SIZE, sp)
-       SAVE_ALL
-       CLI
-       .set    at
-       .set    noreorder
-       mfc0    t0, CP0_CAUSE
-       mfc0    t2, CP0_STATUS
-
-       and     t0, t2
-
-       andi    t1, t0, STATUSF_IP7     /* cpu timer */
-       bnez    t1, ll_cputimer_irq
-       andi    t1, t0, (STATUSF_IP2 | STATUSF_IP3 | STATUSF_IP4 | STATUSF_IP5 | STATUSF_IP6 )
-       bnez    t1, ll_vrc5477_irq
-       andi    t1, t0, STATUSF_IP0     /* software int 0 */
-       bnez    t1, ll_cpu_ip0
-       andi    t1, t0, STATUSF_IP1     /* software int 1 */
-       bnez    t1, ll_cpu_ip1
-       nop
-       .set    reorder
-
-       /* wrong alarm or masked ... */
-       j       spurious_interrupt
-       nop
-       END(ddb5477_handle_int)
-
-       .align  5
-
-ll_vrc5477_irq:
-       move    a0, sp
-       jal     vrc5477_irq_dispatch
-       j       ret_from_irq
-
-ll_cputimer_irq:
-       li      a0, CPU_IRQ_BASE + 7
-       move    a1, sp
-       jal     do_IRQ
-       j       ret_from_irq
-
-
-ll_cpu_ip0:
-       li      a0, CPU_IRQ_BASE + 0
-       move    a1, sp
-       jal     do_IRQ
-       j       ret_from_irq
-
-ll_cpu_ip1:
-       li      a0, CPU_IRQ_BASE + 1
-       move    a1, sp
-       jal     do_IRQ
-       j       ret_from_irq
index 9ffe1a9142caef3e86c19faa03a4dd9906e94e6b..de433cf9fb5013b7c934e0b0bafef9038842e21e 100644 (file)
@@ -75,7 +75,6 @@ set_pci_int_attr(u32 pci, u32 intn, u32 active, u32 trigger)
 
 extern void vrc5477_irq_init(u32 base);
 extern void mips_cpu_irq_init(u32 base);
-extern asmlinkage void ddb5477_handle_int(void);
 extern int setup_irq(unsigned int irq, struct irqaction *irqaction);
 static struct irqaction irq_cascade = { no_action, 0, CPU_MASK_NONE, "cascade", NULL, NULL };
 
@@ -135,9 +134,6 @@ void __init arch_init_irq(void)
        /* setup cascade interrupts */
        setup_irq(VRC5477_IRQ_BASE + VRC5477_I8259_CASCADE, &irq_cascade);
        setup_irq(CPU_IRQ_BASE + CPU_VRC5477_CASCADE, &irq_cascade);
-
-       /* hook up the first-level interrupt handler */
-       set_except_vector(0, ddb5477_handle_int);
 }
 
 u8 i8259_interrupt_ack(void)
@@ -159,7 +155,7 @@ u8 i8259_interrupt_ack(void)
  * the first level int-handler will jump here if it is a vrc5477 irq
  */
 #define        NUM_5477_IRQS   32
-asmlinkage void
+static void
 vrc5477_irq_dispatch(struct pt_regs *regs)
 {
        u32 intStatus;
@@ -197,3 +193,21 @@ vrc5477_irq_dispatch(struct pt_regs *regs)
                }
        }
 }
+
+#define VR5477INTS (STATUSF_IP2|STATUSF_IP3|STATUSF_IP4|STATUSF_IP5|STATUSF_IP6)
+
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+       unsigned int pending = read_c0_cause() & read_c0_status();
+
+       if (pending & STATUSF_IP7)
+               do_IRQ(CPU_IRQ_BASE + 7, regs);
+       else if (pending & VR5477INTS)
+               vrc5477_irq_dispatch(regs);
+       else if (pending & STATUSF_IP0)
+               do_IRQ(CPU_IRQ_BASE, regs);
+       else if (pending & STATUSF_IP1)
+               do_IRQ(CPU_IRQ_BASE + 1, regs);
+       else
+               spurious_interrupt(regs);
+}
index 56fd4277555e6064f63c629f4557c32424ec8f4d..4db8bacaf22d51398f1f5f4ac414c44c5c0be923 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * arch/mips/dec/decstation.c
  */
+#include <asm/sections.h>
 
 #define RELOC
 #define INITRD
@@ -24,7 +25,7 @@
 #define INITRD_START (*(unsigned long *) (PARAM+0x218))
 #define INITRD_SIZE (*(unsigned long *) (PARAM+0x21c))
 
-extern int _ftext, _end;               /* begin and end of kernel image */
+extern int _ftext;                     /* begin and end of kernel image */
 extern void kernel_entry(int, char **, unsigned long, int *);
 
 void * memcpy(void * dest, const void *src, unsigned int count)
index 41fa372007bf07889f2facffc6edfd76f8287ff9..e8ec93e33fe60cc05eb0c7503992cbca38581d7b 100644 (file)
@@ -36,7 +36,7 @@
                .text
                .set    noreorder
 /*
- * decstation_handle_int: Interrupt handler for DECstations
+ * plat_irq_dispatch: Interrupt handler for DECstations
  *
  * We follow the model in the Indy interrupt code by David Miller, where he
  * says: a lot of complication here is taken away because:
  * just take another exception, big deal.
  */
                .align  5
-               NESTED(decstation_handle_int, PT_SIZE, ra)
-               .set    noat
-               SAVE_ALL
-               CLI                             # TEST: interrupts should be off
-               .set    at
+               NESTED(plat_irq_dispatch, PT_SIZE, ra)
                .set    noreorder
 
                /*
@@ -282,9 +278,11 @@ fpu:
 #endif
 
 spurious:
-               j       spurious_interrupt
+               jal     spurious_interrupt
                 nop
-               END(decstation_handle_int)
+               j       ret_from_irq
+                nop
+               END(plat_irq_dispatch)
 
 /*
  * Generic unimplemented interrupt routines -- cpu_mask_nr_tbl
index 7c1ca8f6330e0e33a69f6de58758effbe017be69..ad5d436d80c19bae206c86a6623b3aaa8e486263 100644 (file)
@@ -48,8 +48,6 @@ extern void dec_machine_halt(void);
 extern void dec_machine_power_off(void);
 extern irqreturn_t dec_intr_halt(int irq, void *dev_id, struct pt_regs *regs);
 
-extern asmlinkage void decstation_handle_int(void);
-
 unsigned long dec_kn_slot_base, dec_kn_slot_size;
 
 EXPORT_SYMBOL(dec_kn_slot_base);
@@ -744,7 +742,6 @@ void __init arch_init_irq(void)
                panic("Don't know how to set this up!");
                break;
        }
-       set_except_vector(0, decstation_handle_int);
 
        /* Free the FPU interrupt if the exception is present. */
        if (!cpu_has_nofpuex) {
index 58c02f9db69d86dfb20033a70573b3ad8118f719..cd868ec78cbc9e51d8850d2ec618393ea6e4724c 100644 (file)
@@ -6,4 +6,4 @@
 # Makefile for the Galileo EV96100 board.
 #
 
-obj-y          += init.o irq.o puts.o reset.o time.o int-handler.o setup.o
+obj-y          += init.o irq.o puts.o reset.o time.o setup.o
diff --git a/arch/mips/galileo-boards/ev96100/int-handler.S b/arch/mips/galileo-boards/ev96100/int-handler.S
deleted file mode 100644 (file)
index ff4d10a..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-#include <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-
-       .set    noat
-       .align  5
-
-NESTED(ev96100IRQ, PT_SIZE, sp)
-       SAVE_ALL
-       CLI                             # Important: mark KERNEL mode !
-
-       mfc0    t0, CP0_CAUSE           # get pending interrupts
-       mfc0    t1, CP0_STATUS          # get enabled interrupts
-       and     t0, t1                  # isolate allowed ones
-
-       # FIX ME add R7000 extensions
-       andi    t0,0xff00               # isolate pending bits
-       andi    a0, t0, CAUSEF_IP7
-       beq     a0, zero, 1f
-       move    a0, sp
-       jal     mips_timer_interrupt
-       j       ret_from_irq
-
-1:     beqz    t0, 3f                  # spurious interrupt
-
-       move    a0, t0
-       move    a1, sp
-       jal     ev96100_cpu_irq
-       j       ret_from_irq
-
-3:     j       spurious_interrupt
-       END(ev96100IRQ)
index 97bf094da4fe07f2af22c77aed110a003f5e7b1c..ee5d6720f23bf614c8a6ea18ae985a5386e4f894 100644 (file)
@@ -40,8 +40,6 @@
 #include <linux/interrupt.h>
 #include <asm/irq_cpu.h>
 
-extern asmlinkage void ev96100IRQ(void);
-
 static inline unsigned int ffz8(unsigned int word)
 {
        unsigned long k;
@@ -54,13 +52,26 @@ static inline unsigned int ffz8(unsigned int word)
        return k;
 }
 
-asmlinkage void ev96100_cpu_irq(unsigned int pendin)
+extern void mips_timer_interrupt(struct pt_regs *regs);
+
+asmlinkage void ev96100_cpu_irq(unsigned int pending, struct pt_regs *regs)
 {
        do_IRQ(ffz8(pending >> 8), regs);
 }
 
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+       unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM;
+
+       if (pending & CAUSEF_IP7)
+               mips_timer_interrupt(regs);
+       else if (pending)
+               ev96100_cpu_irq(pending, regs);
+       else
+               spurious_interrupt(regs);
+}
+
 void __init arch_init_irq(void)
 {
-       set_except_vector(0, ev96100IRQ);
        mips_cpu_irq_init(0);
 }
index ebe91c57e17345f1205a12cda20df5fda191cf3f..b2c53a8f8718a71476006fcdff36e76fa07c6318 100644 (file)
@@ -6,6 +6,6 @@
 # Makefile for the Galileo EV64120 board.
 #
 
-obj-y  += int-handler.o irq.o promcon.o reset.o serialGT.o setup.o
+obj-y  += irq.o promcon.o reset.o serialGT.o setup.o
 
 EXTRA_AFLAGS := $(CFLAGS)
diff --git a/arch/mips/gt64120/ev64120/int-handler.S b/arch/mips/gt64120/ev64120/int-handler.S
deleted file mode 100644 (file)
index 752435f..0000000
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * int-handler.S
- *
- * Based on the cobalt handler.
- */
-#include <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/addrspace.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-
-/*
- * galileo_handle_int -
- *      We check for the timer first, then check PCI ints A and D.
- *      Then check for serial IRQ and fall through.
- */
-               .align  5
-               .set    reorder
-               .set    noat
-               NESTED(galileo_handle_int, PT_SIZE, sp)
-               SAVE_ALL
-               CLI
-               .set    at
-               mfc0    t0,CP0_CAUSE
-               mfc0    t2,CP0_STATUS
-
-               and     t0,t2
-
-               andi    t1,t0,STATUSF_IP4 /* int2 hardware line (timer) */
-               bnez    t1,ll_gt64120_irq
-               andi    t1,t0,STATUSF_IP2 /* int0 hardware line */
-               bnez    t1,ll_pci_intA
-               andi    t1,t0,STATUSF_IP5 /* int3 hardware line */
-               bnez    t1,ll_pci_intD
-               andi    t1,t0,STATUSF_IP6 /* int4 hardware line */
-               bnez    t1,ll_serial_irq
-               andi    t1,t0,STATUSF_IP7 /* compare int */
-               bnez    t1,ll_compare_irq
-               nop
-
-    /* wrong alarm or masked ... */
-               j       spurious_interrupt
-               nop
-               END(galileo_handle_int)
-
-
-               .align  5
-               .set    reorder
-ll_gt64120_irq:
-               li      a0,4
-               move    a1,sp
-               jal     do_IRQ
-               nop
-               j       ret_from_irq
-               nop
-
-               .align  5
-               .set    reorder
-ll_compare_irq:
-               li      a0,7
-               move    a1,sp
-               jal     do_IRQ
-               nop
-               j       ret_from_irq
-               nop
-
-               .align  5
-               .set    reorder
-ll_pci_intA:
-               move    a0,sp
-               jal     pci_intA
-               nop
-               j       ret_from_irq
-               nop
-
-#if 0
-               .align  5
-               .set    reorder
-ll_pci_intB:
-               move    a0,sp
-               jal     pci_intB
-               nop
-               j       ret_from_irq
-               nop
-
-               .align  5
-               .set    reorder
-ll_pci_intC:
-               move    a0,sp
-               jal     pci_intC
-               nop
-               j       ret_from_irq
-               nop
-#endif
-
-               .align  5
-               .set    reorder
-ll_pci_intD:
-               move    a0,sp
-               jal     pci_intD
-               nop
-               j       ret_from_irq
-               nop
-
-               .align  5
-               .set    reorder
-ll_serial_irq:
-               li      a0,6
-               move    a1,sp
-               jal     do_IRQ
-               nop
-               j       ret_from_irq
-               nop
index 3b186159b21a17b9a1763736d736f550e1e0918f..46c468b26b30879c72b82e01e52a271b32e61d2a 100644 (file)
 #include <asm/system.h>
 #include <asm/gt64120.h>
 
-asmlinkage inline void pci_intA(struct pt_regs *regs)
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
 {
-       do_IRQ(GT_INTA, regs);
-}
-
-asmlinkage inline void pci_intD(struct pt_regs *regs)
-{
-       do_IRQ(GT_INTD, regs);
+       unsigned int pending = read_c0_status() & read_c0_cause();
+
+       if (pending & STATUSF_IP4)              /* int2 hardware line (timer) */
+               do_IRQ(4, regs);
+       else if (pending & STATUSF_IP2)         /* int0 hardware line */
+               do_IRQ(GT_INTA, regs);
+       else if (pending & STATUSF_IP5)         /* int3 hardware line */
+               do_IRQ(GT_INTD, regs);
+       else if (pending & STATUSF_IP6)         /* int4 hardware line */
+               do_IRQ(6, regs);
+       else if (pending & STATUSF_IP7)         /* compare int */
+               do_IRQ(7, regs);
+       else
+               spurious_interrupt(regs);
 }
 
 static void disable_ev64120_irq(unsigned int irq_nr)
@@ -109,16 +117,11 @@ static struct hw_interrupt_type ev64120_irq_type = {
 
 void gt64120_irq_setup(void)
 {
-       extern asmlinkage void galileo_handle_int(void);
-
        /*
         * Clear all of the interrupts while we change the able around a bit.
         */
        clear_c0_status(ST0_IM);
 
-       /* Sets the exception_handler array. */
-       set_except_vector(0, galileo_handle_int);
-
        local_irq_disable();
 
        /*
index 7b59c6567c79437abcf80513dc2068c17c6fa8d2..6f708df8373be147689ee6b88f55189137ab77a2 100644 (file)
@@ -2,7 +2,7 @@
 # Makefile for Momentum's Ocelot board.
 #
 
-obj-y                  += int-handler.o irq.o prom.o reset.o setup.o
+obj-y                  += irq.o prom.o reset.o setup.o
 
 obj-$(CONFIG_KGDB)     += dbg_io.o
 
diff --git a/arch/mips/gt64120/momenco_ocelot/int-handler.S b/arch/mips/gt64120/momenco_ocelot/int-handler.S
deleted file mode 100644 (file)
index 808acef..0000000
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * Copyright 2001 MontaVista Software Inc.
- * Author: jsun@mvista.com or jsun@junsun.net
- *
- * First-level interrupt dispatcher for ocelot board.
- *
- * 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 <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/addrspace.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-
-/*
- * first level interrupt dispatcher for ocelot board -
- * We check for the timer first, then check PCI ints A and D.
- * Then check for serial IRQ and fall through.
- */
-               .align  5
-               NESTED(ocelot_handle_int, PT_SIZE, sp)
-               SAVE_ALL
-               CLI
-               .set    at
-               mfc0    t0, CP0_CAUSE
-               mfc0    t2, CP0_STATUS
-
-               and     t0, t2
-
-                andi   t1, t0, STATUSF_IP2     /* int0 hardware line */
-               bnez    t1, ll_pri_enet_irq
-                andi   t1, t0, STATUSF_IP3     /* int1 hardware line */
-               bnez    t1, ll_sec_enet_irq
-                andi   t1, t0, STATUSF_IP4     /* int2 hardware line */
-               bnez    t1, ll_uart1_irq
-                andi   t1, t0, STATUSF_IP5     /* int3 hardware line */
-               bnez    t1, ll_cpci_irq
-                andi   t1, t0, STATUSF_IP6     /* int4 hardware line */
-               bnez    t1, ll_galileo_irq
-                andi   t1, t0, STATUSF_IP7     /* cpu timer */
-               bnez    t1, ll_cputimer_irq
-
-                /* now look at the extended interrupts */
-               mfc0    t0, CP0_CAUSE
-               cfc0    t1, CP0_S1_INTCONTROL
-
-               /* shift the mask 8 bits left to line up the bits */
-                sll    t2, t1, 8
-
-                and    t0, t2
-                srl    t0, t0, 16
-
-                andi   t1, t0, STATUSF_IP8     /* int6 hardware line */
-               bnez    t1, ll_pmc1_irq
-                andi   t1, t0, STATUSF_IP9     /* int7 hardware line */
-               bnez    t1, ll_pmc2_irq
-                andi   t1, t0, STATUSF_IP10    /* int8 hardware line */
-               bnez    t1, ll_cpci_abcd_irq
-                andi   t1, t0, STATUSF_IP11    /* int9 hardware line */
-               bnez    t1, ll_uart2_irq
-
-               .set    reorder
-
-               /* wrong alarm or masked ... */
-               j       spurious_interrupt
-               nop
-               END(ocelot_handle_int)
-
-               .align  5
-ll_pri_enet_irq:
-               li      a0, 2
-               move    a1, sp
-               jal     do_IRQ
-               j       ret_from_irq
-
-ll_sec_enet_irq:
-               li      a0, 3
-               move    a1, sp
-               jal     do_IRQ
-               j       ret_from_irq
-
-ll_uart1_irq:
-               li      a0, 4
-               move    a1, sp
-               jal     do_IRQ
-               j       ret_from_irq
-
-ll_cpci_irq:
-               li      a0, 5
-               move    a1, sp
-               jal     do_IRQ
-               j       ret_from_irq
-
-ll_galileo_irq:
-               li      a0, 6
-               move    a1, sp
-               jal     do_IRQ
-               j       ret_from_irq
-
-ll_cputimer_irq:
-               li      a0, 7
-               move    a1, sp
-               jal     do_IRQ
-               j       ret_from_irq
-
-ll_pmc1_irq:
-               li      a0, 8
-               move    a1, sp
-               jal     do_IRQ
-               j       ret_from_irq
-
-ll_pmc2_irq:
-               li      a0, 9
-               move    a1, sp
-               jal     do_IRQ
-               j       ret_from_irq
-
-ll_cpci_abcd_irq:
-               li      a0, 10
-               move    a1, sp
-               jal     do_IRQ
-               j       ret_from_irq
-
-ll_uart2_irq:
-               li      a0, 11
-               move    a1, sp
-               jal     do_IRQ
-               j       ret_from_irq
index 4f108da71b2355d02b4185ac7ed409992c959347..885f67f32ea3dfa501916f5ed8e194984063c3a1 100644 (file)
 #include <asm/mipsregs.h>
 #include <asm/system.h>
 
-extern asmlinkage void ocelot_handle_int(void);
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+       unsigned int pending = read_c0_status() & read_c0_cause();
+
+       if (pending & STATUSF_IP2)              /* int0 hardware line */
+               do_IRQ(2, regs);
+       else if (pending & STATUSF_IP3)         /* int1 hardware line */
+               do_IRQ(3, regs);
+       else if (pending & STATUSF_IP4)         /* int2 hardware line */
+               do_IRQ(4, regs);
+       else if (pending & STATUSF_IP5)         /* int3 hardware line */
+               do_IRQ(5, regs);
+       else if (pending & STATUSF_IP6)         /* int4 hardware line */
+               do_IRQ(6, regs);
+       else if (pending & STATUSF_IP7)         /* cpu timer */
+               do_IRQ(7, regs);
+       else {
+               /*
+                * Now look at the extended interrupts
+                */
+               pending = (read_c0_cause() & (read_c0_intcontrol() << 8)) >> 16;
+
+               if (pending & STATUSF_IP8)              /* int6 hardware line */
+                       do_IRQ(8, regs);
+               else if (pending & STATUSF_IP9)         /* int7 hardware line */
+                       do_IRQ(9, regs);
+               else if (pending & STATUSF_IP10)        /* int8 hardware line */
+                       do_IRQ(10, regs);
+               else if (pending & STATUSF_IP11)        /* int9 hardware line */
+                       do_IRQ(11, regs);
+       }
+}
 
 void __init arch_init_irq(void)
 {
@@ -59,9 +90,6 @@ void __init arch_init_irq(void)
        clear_c0_status(ST0_IM);
        local_irq_disable();
 
-       /* Sets the first-level interrupt dispatcher. */
-       set_except_vector(0, ocelot_handle_int);
-
        mips_cpu_irq_init(0);
        rm7k_cpu_irq_init(8);
 }
index 0e7853f43983f7725f712167738775be4f80a221..63431538d0ec81ad92a1771ec53c15a72474968c 100644 (file)
@@ -6,7 +6,7 @@
 # Makefile for the ITE 8172 (qed-4n-s01b) board, generic files.
 #
 
-obj-y                  += it8172_setup.o irq.o int-handler.o pmon_prom.o \
+obj-y                  += it8172_setup.o irq.o pmon_prom.o \
                           time.o lpc.o puts.o reset.o
 
 obj-$(CONFIG_IT8172_CIR)+= it8172_cir.o
diff --git a/arch/mips/ite-boards/generic/int-handler.S b/arch/mips/ite-boards/generic/int-handler.S
deleted file mode 100644 (file)
index d190d8a..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-#include <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-
-       .text
-       .set    macro
-       .set    noat
-       .align  5
-
-NESTED(it8172_IRQ, PT_SIZE, sp)
-       SAVE_ALL
-       CLI                             # Important: mark KERNEL mode !
-
-        /* We're working with 'reorder' set at this point. */
-       /*
-        * Get pending interrupts
-        */
-
-       mfc0    t0,CP0_CAUSE            # get pending interrupts
-       mfc0    t1,CP0_STATUS           # get enabled interrupts
-       and     t0,t1                   # isolate allowed ones
-
-       andi    t0,0xff00               # isolate pending bits
-        beqz    t0, 3f                  # spurious interrupt
-
-        andi    a0, t0, CAUSEF_IP7
-        beq     a0, zero, 1f
-
-        li     a0, 127                 # MIPS_CPU_TIMER_IRQ = (NR_IRQS-1)
-        move    a1, sp
-        jal     ll_timer_interrupt
-       j       ret_from_irq
-        nop
-
-1:
-        andi    a0, t0, CAUSEF_IP2      # the only int we expect at this time
-        beq     a0, zero, 3f
-       move    a0,sp
-       jal     it8172_hw0_irqdispatch
-
-       mfc0    t0,CP0_STATUS           # disable interrupts
-       ori     t0,1
-       xori    t0,1
-       mtc0    t0,CP0_STATUS
-        nop
-        nop
-        nop
-
-       la      a1, ret_from_irq
-       jr      a1
-        nop
-
-3:
-       move a0, sp
-       jal     mips_spurious_interrupt
-        nop
-       la      a1, ret_from_irq
-       jr      a1
-        nop
-
-END(it8172_IRQ)
-
index e67f96129491009074f28187a7ee72edd9b864c9..77be7216bdd091430735ccb89c1e356144a779fd 100644 (file)
 
 #define ALLINTS_NOTIMER (IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4)
 
-void disable_it8172_irq(unsigned int irq_nr);
-void enable_it8172_irq(unsigned int irq_nr);
-
 extern void set_debug_traps(void);
 extern void mips_timer_interrupt(int irq, struct pt_regs *regs);
-extern asmlinkage void it8172_IRQ(void);
 
 struct it8172_intc_regs volatile *it8172_hw0_icregs =
        (struct it8172_intc_regs volatile *)(KSEG1ADDR(IT8172_PCI_IO_BASE + IT_INTC_BASE));
@@ -181,8 +177,6 @@ void __init arch_init_irq(void)
        int i;
         unsigned long flags;
 
-        set_except_vector(0, it8172_IRQ);
-
        /* mask all interrupts */
        it8172_hw0_icregs->lb_mask  = 0xffff;
        it8172_hw0_icregs->lpc_mask = 0xffff;
@@ -282,6 +276,18 @@ void it8172_hw0_irqdispatch(struct pt_regs *regs)
        do_IRQ(irq, regs);
 }
 
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+       unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM;
+
+       if (!pending)
+               mips_spurious_interrupt(regs);
+       else if (pending & CAUSEF_IP7)
+               ll_timer_interrupt(127, regs);
+       else if (pending & CAUSEF_IP2)
+               it8172_hw0_irqdispatch(regs);
+}
+
 void show_pending_irqs(void)
 {
        fputs("intstatus:  ");
index b79817bb6cceb777e79ce8f5a315e1811c6a20e5..dee497a91807b163a97392e4663463b6cd994869 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/sched.h>
 #include <linux/time.h>
 #include <linux/spinlock.h>
+#include <linux/mc146818rtc.h>
 
 #include <asm/time.h>
 #include <asm/mipsregs.h>
index b774db035b3132c69769d37dae693e3889fd1a53..05cf9218c43279b1c8a25e6a5c6ea1ce2072c0cb 100644 (file)
 #include <asm/bootinfo.h>
 #include <linux/string.h>
 #include <linux/kernel.h>
+#include <asm/sections.h>
 #include <asm/it8172/it8172.h>
 #include <asm/it8172/it8172_dbg.h>
 
 int prom_argc;
 char **prom_argv, **prom_envp;
 
-extern char _end;
 extern void  __init prom_init_cmdline(void);
 extern unsigned long __init prom_get_memsize(void);
 extern void __init it8172_init_ram_resource(unsigned long memsize);
index e8ec8be66a80b9d630948312f38654d993273cfb..ea2a754cafe582ef0d6b10dccb76bc7dd71b6edb 100644 (file)
 #include <asm/bootinfo.h>
 #include <linux/string.h>
 #include <linux/kernel.h>
+#include <asm/sections.h>
 #include <asm/it8172/it8172.h>
 #include <asm/it8172/it8172_dbg.h>
 
 int prom_argc;
 char **prom_argv, **prom_envp;
 
-extern char _end;
 extern void  __init prom_init_cmdline(void);
 extern unsigned long __init prom_get_memsize(void);
 extern void __init it8172_init_ram_resource(unsigned long memsize);
index 85749246a671481ead67aae3147198650cc9c6f7..02bd39add891c042a90295a0bd2abd2e2729df99 100644 (file)
@@ -2,6 +2,6 @@
 # Makefile for the Jazz family specific parts of the kernel
 #
 
-obj-y          := int-handler.o irq.o jazzdma.o reset.o setup.o
+obj-y          := irq.o jazzdma.o reset.o setup.o
 
 EXTRA_AFLAGS := $(CFLAGS)
diff --git a/arch/mips/jazz/int-handler.S b/arch/mips/jazz/int-handler.S
deleted file mode 100644 (file)
index dc752c6..0000000
+++ /dev/null
@@ -1,282 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 1995, 1996, 1997, 1998 by Ralf Baechle and Andreas Busse
- *
- * Jazz family specific interrupt stuff
- *
- * To do: On Jazz machines we remap some non-ISA interrupts to ISA
- *        interrupts.  These interrupts should use their own vectors.
- *        Squeeze the last cycles out of the handlers.  Only a dead
- *        cycle is a good cycle.
- */
-#include <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/jazz.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-
-/*
- * jazz_handle_int: Interrupt handler for the ACER Pica-61 boards
- */
-               .set    noreorder
-
-               NESTED(jazz_handle_int, PT_SIZE, ra)
-               .set    noat
-               SAVE_ALL
-               CLI
-               .set    at
-
-               /*
-                * Get pending interrupts
-                */
-               mfc0    t0,CP0_CAUSE            # get pending interrupts
-               mfc0    t1,CP0_STATUS           # get enabled interrupts
-               and     t0,t1                   # isolate allowed ones
-               andi    t0,0xff00               # isolate pending bits
-               beqz    t0,3f
-               sll     t0,16                   # delay slot
-
-               /*
-                * Find irq with highest priority
-                * FIXME: This is slow - use binary search
-                */
-               la      t1,ll_vectors
-1:             bltz    t0,2f                   # found pending irq
-               sll     t0,1
-               b       1b
-               subu    t1,PTRSIZE              # delay slot
-
-               /*
-                * Do the low-level stuff
-                */
-2:             lw      t0,(t1)
-               jr      t0
-               nop                             # delay slot
-               END(jazz_handle_int)
-
-ll_sw0:                li      s1,~IE_SW0
-               mfc0    t0,CP0_CAUSE
-               and     t0,s1
-               mtc0    t0,CP0_CAUSE
-               PANIC("Unimplemented sw0 handler")
-
-ll_sw1:                li      s1,~IE_SW1
-               mfc0    t0,CP0_CAUSE
-               and     t0,s1
-               mtc0    t0,CP0_CAUSE
-               PANIC("Unimplemented sw1 handler")
-
-ll_local_dma:  li      s1,~IE_IRQ0
-               PANIC("Unimplemented local_dma handler")
-
-ll_local_dev:  lbu     t0,JAZZ_IO_IRQ_SOURCE
-#if PTRSIZE == 8       /* True 64 bit kernel */
-               dsll    t0,1
-#endif
-               .set    reorder
-               LONG_L  t0,local_vector(t0)
-               jr      t0
-               .set    noreorder
-
-/*
- * The braindead PICA hardware gives us no way to distinguish if we really
- * received interrupt 7 from the (E)ISA bus or if we just received an
- * interrupt with no findable cause.  This sometimes happens with braindead
- * cards.  Oh well - for all the Jazz boxes slots are more or less just
- * whistles and bells and we're aware of the problem.
- */
-ll_isa_irq:    lw      a0, JAZZ_EISA_IRQ_ACK
-
-               jal     do_IRQ
-                move   a1,sp
-
-               j       ret_from_irq
-               nop
-
-/*
- * Hmm...  This is not just a plain PC clone so the question is
- * which devices on Jazz machines can generate an (E)ISA NMI?
- * (Writing to nonexistent memory?)
- */
-ll_isa_nmi:    li      s1,~IE_IRQ3
-               PANIC("Unimplemented isa_nmi handler")
-
-/*
- * Timer IRQ - remapped to be more similar to an IBM compatible.
- *
- * The timer interrupt is handled specially to ensure that the jiffies
- * variable is updated at all times.  Specifically, the timer interrupt is
- * just like the complete handlers except that it is invoked with interrupts
- * disabled and should never re-enable them.  If other interrupts were
- * allowed to be processed while the timer interrupt is active, then the
- * other interrupts would have to avoid using the jiffies variable for delay
- * and interval timing operations to avoid hanging the system.
- */
-ll_timer:      lw      zero,JAZZ_TIMER_REGISTER # timer irq cleared on read
-               li      s1,~IE_IRQ4
-
-               li      a0, JAZZ_TIMER_IRQ
-               jal     do_IRQ
-                move   a1,sp
-
-               mfc0    t0,CP0_STATUS           # disable interrupts again
-               ori     t0,1
-               xori    t0,1
-               mtc0    t0,CP0_STATUS
-
-               j       ret_from_irq
-                nop
-
-/*
- * CPU count/compare IRQ (unused)
- */
-ll_count:      j       ret_from_irq
-                mtc0   zero,CP0_COMPARE
-
-#if 0
-/*
- * Call the handler for the interrupt
- * (Currently unused)
- */
-call_real:     /*
-                * temporarily disable interrupt
-                */
-               mfc0    t2,CP0_STATUS
-               and     t2,s1
-               mtc0    t2,CP0_STATUS
-               nor     s1,zero,s1
-               jal     do_IRQ
-
-               /*
-                * reenable interrupt
-                */
-               mfc0    t2,CP0_STATUS
-               or      t2,s1
-               mtc0    t2,CP0_STATUS
-               j       ret_from_irq
-#endif
-
-               .data
-               PTR     ll_sw0                  # SW0
-               PTR     ll_sw1                  # SW1
-               PTR     ll_local_dma            # Local DMA
-               PTR     ll_local_dev            # Local devices
-               PTR     ll_isa_irq              # ISA IRQ
-               PTR     ll_isa_nmi              # ISA NMI
-               PTR     ll_timer                # Timer
-ll_vectors:    PTR     ll_count                # Count/Compare IRQ
-
-               /*
-                * Interrupt handlers for local devices.
-                */
-               .text
-               .set    reorder
-loc_no_irq:    PANIC("Unimplemented loc_no_irq handler")
-/*
- * Parallel port IRQ
- */
-loc_parallel:  li      s1,~JAZZ_IE_PARALLEL
-               li      a0,JAZZ_PARALLEL_IRQ
-               b       loc_call
-
-/*
- * Floppy IRQ
- */
-loc_floppy:    li      s1,~JAZZ_IE_FLOPPY
-               li      a0,JAZZ_FLOPPY_IRQ
-               b       loc_call
-
-/*
- * Sound IRQ
- */
-loc_sound:     PANIC("Unimplemented loc_sound handler")
-loc_video:     PANIC("Unimplemented loc_video handler")
-
-/*
- * Ethernet interrupt handler
- */
-loc_ethernet:  li      s1,~JAZZ_IE_ETHERNET
-               li      a0,JAZZ_ETHERNET_IRQ
-               b       loc_call
-
-/*
- * SCSI interrupt handler
- */
-loc_scsi:      li      s1,~JAZZ_IE_SCSI
-               li      a0,JAZZ_SCSI_IRQ
-               b       loc_call
-
-/*
- * Keyboard interrupt handler
- */
-loc_keyboard:  li      s1,~JAZZ_IE_KEYBOARD
-               li      a0,JAZZ_KEYBOARD_IRQ
-               b       loc_call
-
-/*
- * Mouse interrupt handler
- */
-loc_mouse:     li      s1,~JAZZ_IE_MOUSE
-               li      a0,JAZZ_MOUSE_IRQ
-               b       loc_call
-
-/*
- * Serial port 1 IRQ
- */
-loc_serial1:   li      s1,~JAZZ_IE_SERIAL1
-               li      a0,JAZZ_SERIAL1_IRQ
-               b       loc_call
-
-/*
- * Serial port 2 IRQ
- */
-loc_serial2:   li      s1,~JAZZ_IE_SERIAL2
-               li      a0,JAZZ_SERIAL2_IRQ
-               b       loc_call
-
-/*
- * Call the interrupt handler for an interrupt generated by a
- * local device.
- */
-loc_call:      /*
-                * Temporarily disable interrupt source
-                */
-               lhu     t2,JAZZ_IO_IRQ_ENABLE
-               and     t2,s1
-               sh      t2,JAZZ_IO_IRQ_ENABLE
-
-               nor     s1,zero,s1
-               jal     do_IRQ
-
-               /*
-                * Reenable interrupt
-                */
-               lhu     t2,JAZZ_IO_IRQ_ENABLE
-               or      t2,s1
-               sh      t2,JAZZ_IO_IRQ_ENABLE
-
-               j       ret_from_irq
-
-/*
- * "Jump extender" to reach spurious_interrupt
- */
-3:             j       spurious_interrupt
-
-/*
- * Vectors for interrupts generated by local devices
- */
-               .data
-local_vector:  PTR     loc_no_irq
-               PTR     loc_parallel
-               PTR     loc_floppy
-               PTR     loc_sound
-               PTR     loc_video
-               PTR     loc_ethernet
-               PTR     loc_scsi
-               PTR     loc_keyboard
-               PTR     loc_mouse
-               PTR     loc_serial1
-               PTR     loc_serial2
index b309b1bcf2e87926117e1de16ea2b835107b96c2..becc9accd49573e5d24e052a8e3d8e2e40699339 100644 (file)
@@ -15,8 +15,6 @@
 #include <asm/io.h>
 #include <asm/jazz.h>
 
-extern asmlinkage void jazz_handle_int(void);
-
 static DEFINE_SPINLOCK(r4030_lock);
 
 static void enable_r4030_irq(unsigned int irq)
@@ -90,10 +88,82 @@ void __init init_r4030_ints(void)
  */
 void __init arch_init_irq(void)
 {
-       set_except_vector(0, jazz_handle_int);
-
        init_i8259_irqs();                      /* Integrated i8259  */
        init_r4030_ints();
 
        change_c0_status(ST0_IM, IE_IRQ4 | IE_IRQ3 | IE_IRQ2 | IE_IRQ1);
 }
+
+static void loc_call(unsigned int irq, struct pt_regs *regs, unsigned int mask)
+{
+       r4030_write_reg16(JAZZ_IO_IRQ_ENABLE,
+                         r4030_read_reg16(JAZZ_IO_IRQ_ENABLE) & mask);
+       do_IRQ(irq, regs);
+       r4030_write_reg16(JAZZ_IO_IRQ_ENABLE,
+                         r4030_read_reg16(JAZZ_IO_IRQ_ENABLE) | mask);
+}
+
+static void ll_local_dev(struct pt_regs *regs)
+{
+       switch (r4030_read_reg32(JAZZ_IO_IRQ_SOURCE)) {
+       case 0:
+               panic("Unimplemented loc_no_irq handler");
+               break;
+       case 4:
+               loc_call(JAZZ_PARALLEL_IRQ, regs, JAZZ_IE_PARALLEL);
+               break;
+       case 8:
+               loc_call(JAZZ_PARALLEL_IRQ, regs, JAZZ_IE_FLOPPY);
+               break;
+       case 12:
+               panic("Unimplemented loc_sound handler");
+               break;
+       case 16:
+               panic("Unimplemented loc_video handler");
+               break;
+       case 20:
+               loc_call(JAZZ_ETHERNET_IRQ, regs, JAZZ_IE_ETHERNET);
+               break;
+       case 24:
+               loc_call(JAZZ_SCSI_IRQ, regs, JAZZ_IE_SCSI);
+               break;
+       case 28:
+               loc_call(JAZZ_KEYBOARD_IRQ, regs, JAZZ_IE_KEYBOARD);
+               break;
+       case 32:
+               loc_call(JAZZ_MOUSE_IRQ, regs, JAZZ_IE_MOUSE);
+               break;
+       case 36:
+               loc_call(JAZZ_SERIAL1_IRQ, regs, JAZZ_IE_SERIAL1);
+               break;
+       case 40:
+               loc_call(JAZZ_SERIAL2_IRQ, regs, JAZZ_IE_SERIAL2);
+               break;
+       }
+}
+
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+       unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM;
+
+       if (pending & IE_IRQ5)
+               write_c0_compare(0);
+       else if (pending & IE_IRQ4) {
+               r4030_read_reg32(JAZZ_TIMER_REGISTER);
+               do_IRQ(JAZZ_TIMER_IRQ, regs);
+       } else if (pending & IE_IRQ3)
+               panic("Unimplemented ISA NMI handler");
+       else if (pending & IE_IRQ2)
+               do_IRQ(r4030_read_reg32(JAZZ_EISA_IRQ_ACK), regs);
+       else if (pending & IE_IRQ1) {
+               ll_local_dev(regs);
+       } else if (unlikely(pending & IE_IRQ0))
+               panic("Unimplemented local_dma handler");
+       else if (pending & IE_SW1) {
+               clear_c0_cause(IE_SW1);
+               panic("Unimplemented sw1 handler");
+       } else if (pending & IE_SW0) {
+               clear_c0_cause(IE_SW0);
+               panic("Unimplemented sw0 handler");
+       }
+}
index a6bd3f4d3049d56c9790a1ffb450edeb29062d16..e6561345d12a345cec239a4daec921b98bf3dce5 100644 (file)
@@ -60,15 +60,15 @@ rtc_ds1742_get_time(void)
        unsigned long flags;
 
        spin_lock_irqsave(&rtc_lock, flags);
-       CMOS_WRITE(RTC_READ, RTC_CONTROL);
-       second = BCD2BIN(CMOS_READ(RTC_SECONDS) & RTC_SECONDS_MASK);
-       minute = BCD2BIN(CMOS_READ(RTC_MINUTES));
-       hour = BCD2BIN(CMOS_READ(RTC_HOURS));
-       day = BCD2BIN(CMOS_READ(RTC_DATE));
-       month = BCD2BIN(CMOS_READ(RTC_MONTH));
-       year = BCD2BIN(CMOS_READ(RTC_YEAR));
-       century = BCD2BIN(CMOS_READ(RTC_CENTURY) & RTC_CENTURY_MASK);
-       CMOS_WRITE(0, RTC_CONTROL);
+       rtc_write(RTC_READ, RTC_CONTROL);
+       second = BCD2BIN(rtc_read(RTC_SECONDS) & RTC_SECONDS_MASK);
+       minute = BCD2BIN(rtc_read(RTC_MINUTES));
+       hour = BCD2BIN(rtc_read(RTC_HOURS));
+       day = BCD2BIN(rtc_read(RTC_DATE));
+       month = BCD2BIN(rtc_read(RTC_MONTH));
+       year = BCD2BIN(rtc_read(RTC_YEAR));
+       century = BCD2BIN(rtc_read(RTC_CENTURY) & RTC_CENTURY_MASK);
+       rtc_write(0, RTC_CONTROL);
        spin_unlock_irqrestore(&rtc_lock, flags);
 
        year += century * 100;
@@ -87,16 +87,16 @@ rtc_ds1742_set_time(unsigned long t)
        unsigned long flags;
 
        spin_lock_irqsave(&rtc_lock, flags);
-       CMOS_WRITE(RTC_READ, RTC_CONTROL);
-       cmos_second = (u8)(CMOS_READ(RTC_SECONDS) & RTC_SECONDS_MASK);
-       cmos_minute = (u8)CMOS_READ(RTC_MINUTES);
-       cmos_hour = (u8)CMOS_READ(RTC_HOURS);
-       cmos_day = (u8)CMOS_READ(RTC_DATE);
-       cmos_month = (u8)CMOS_READ(RTC_MONTH);
-       cmos_year = (u8)CMOS_READ(RTC_YEAR);
-       cmos_century = CMOS_READ(RTC_CENTURY) & RTC_CENTURY_MASK;
+       rtc_write(RTC_READ, RTC_CONTROL);
+       cmos_second = (u8)(rtc_read(RTC_SECONDS) & RTC_SECONDS_MASK);
+       cmos_minute = (u8)rtc_read(RTC_MINUTES);
+       cmos_hour = (u8)rtc_read(RTC_HOURS);
+       cmos_day = (u8)rtc_read(RTC_DATE);
+       cmos_month = (u8)rtc_read(RTC_MONTH);
+       cmos_year = (u8)rtc_read(RTC_YEAR);
+       cmos_century = rtc_read(RTC_CENTURY) & RTC_CENTURY_MASK;
 
-       CMOS_WRITE(RTC_WRITE, RTC_CONTROL);
+       rtc_write(RTC_WRITE, RTC_CONTROL);
 
        /* convert */
        to_tm(t, &tm);
@@ -104,18 +104,18 @@ rtc_ds1742_set_time(unsigned long t)
        /* check each field one by one */
        year = BIN2BCD(tm.tm_year - EPOCH);
        if (year != cmos_year) {
-               CMOS_WRITE(year,RTC_YEAR);
+               rtc_write(year,RTC_YEAR);
        }
 
        month = BIN2BCD(tm.tm_mon);
        if (month != (cmos_month & 0x1f)) {
-               CMOS_WRITE((month & 0x1f) | (cmos_month & ~0x1f),RTC_MONTH);
+               rtc_write((month & 0x1f) | (cmos_month & ~0x1f),RTC_MONTH);
        }
 
        day = BIN2BCD(tm.tm_mday);
        if (day != cmos_day) {
 
-               CMOS_WRITE(day, RTC_DATE);
+               rtc_write(day, RTC_DATE);
        }
 
        if (cmos_hour & 0x40) {
@@ -130,20 +130,20 @@ rtc_ds1742_set_time(unsigned long t)
                /* 24 hour format */
                hour = BIN2BCD(tm.tm_hour) & 0x3f;
        }
-       if (hour != cmos_hour) CMOS_WRITE(hour, RTC_HOURS);
+       if (hour != cmos_hour) rtc_write(hour, RTC_HOURS);
 
        minute = BIN2BCD(tm.tm_min);
        if (minute !=  cmos_minute) {
-               CMOS_WRITE(minute, RTC_MINUTES);
+               rtc_write(minute, RTC_MINUTES);
        }
 
        second = BIN2BCD(tm.tm_sec);
        if (second !=  cmos_second) {
-               CMOS_WRITE(second & RTC_SECONDS_MASK,RTC_SECONDS);
+               rtc_write(second & RTC_SECONDS_MASK,RTC_SECONDS);
        }
 
        /* RTC_CENTURY and RTC_CONTROL share same address... */
-       CMOS_WRITE(cmos_century, RTC_CONTROL);
+       rtc_write(cmos_century, RTC_CONTROL);
        spin_unlock_irqrestore(&rtc_lock, flags);
 
        return 0;
@@ -163,9 +163,9 @@ rtc_ds1742_init(unsigned long base)
        rtc_mips_set_time = rtc_ds1742_set_time;
 
        /* clear oscillator stop bit */
-       CMOS_WRITE(RTC_READ, RTC_CONTROL);
-       cmos_second = (u8)(CMOS_READ(RTC_SECONDS) & RTC_SECONDS_MASK);
-       CMOS_WRITE(RTC_WRITE, RTC_CONTROL);
-       CMOS_WRITE(cmos_second, RTC_SECONDS); /* clear msb */
-       CMOS_WRITE(0, RTC_CONTROL);
+       rtc_write(RTC_READ, RTC_CONTROL);
+       cmos_second = (u8)(rtc_read(RTC_SECONDS) & RTC_SECONDS_MASK);
+       rtc_write(RTC_WRITE, RTC_CONTROL);
+       rtc_write(cmos_second, RTC_SECONDS); /* clear msb */
+       rtc_write(0, RTC_CONTROL);
 }
index 75bf418b94c0cf8a2192e14d165b3f5ebc2c1151..baf5077813c1ac2489be2ff0488c9aa6e42b679f 100644 (file)
@@ -2,7 +2,7 @@
 # Makefile for TOSHIBA JMR-TX3927 board
 #
 
-obj-y                          += init.o int-handler.o irq.o setup.o
+obj-y                          += init.o irq.o setup.o
 obj-$(CONFIG_RUNTIME_DEBUG)    += debug.o
 obj-$(CONFIG_KGDB)             += kgdb_io.o
 
diff --git a/arch/mips/jmr3927/rbhma3100/int-handler.S b/arch/mips/jmr3927/rbhma3100/int-handler.S
deleted file mode 100644 (file)
index f85bbf4..0000000
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright 2001 MontaVista Software Inc.
- * Author: MontaVista Software, Inc.
- *              ahennessy@mvista.com
- *
- * Based on arch/mips/tsdb/kernel/int-handler.S
- *
- * Copyright (C) 2000-2001 Toshiba Corporation
- *
- *  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  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
- *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
- *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
- *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
- *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *  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.,
- *  675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-#include <asm/jmr3927/jmr3927.h>
-
-       /* A lot of complication here is taken away because:
-        *
-        * 1) We handle one interrupt and return, sitting in a loop
-        *    and moving across all the pending IRQ bits in the cause
-        *    register is _NOT_ the answer, the common case is one
-        *    pending IRQ so optimize in that direction.
-        *
-        * 2) We need not check against bits in the status register
-        *    IRQ mask, that would make this routine slow as hell.
-        *
-        * 3) Linux only thinks in terms of all IRQs on or all IRQs
-        *    off, nothing in between like BSD spl() brain-damage.
-        *
-        */
-
-/* Flush write buffer (needed?)
- * NOTE: TX39xx performs "non-blocking load", so explicitly use the target
- * register of LBU to flush immediately.
- */
-#define FLUSH_WB(tmp)  \
-       la      tmp, JMR3927_IOC_REV_ADDR; \
-       lbu     tmp, (tmp); \
-       move    tmp, zero;
-
-       .text
-       .set    noreorder
-       .set    noat
-       .align  5
-       NESTED(jmr3927_IRQ, PT_SIZE, sp)
-       SAVE_ALL
-       CLI
-       .set    at
-       jal     jmr3927_irc_irqdispatch
-        move   a0, sp
-       FLUSH_WB(t0)
-       j       ret_from_irq
-        nop
-       END(jmr3927_IRQ)
index 2810727f1d4e64312708827e6f8c88c4f5fab4e6..11304d1354f45b0d47afc511e9a7811fa9383ca6 100644 (file)
@@ -77,8 +77,6 @@ static int jmr3927_gen_iack(void)
 }
 #endif
 
-extern asmlinkage void jmr3927_IRQ(void);
-
 #define irc_dlevel     0
 #define irc_elevel     1
 
@@ -262,7 +260,7 @@ void jmr3927_spurious(struct pt_regs *regs)
               regs->cp0_cause, regs->cp0_epc, regs->regs[31]);
 }
 
-void jmr3927_irc_irqdispatch(struct pt_regs *regs)
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
 {
        int irq;
 
@@ -398,8 +396,6 @@ void __init arch_init_irq(void)
 
        jmr3927_irq_init(NR_ISA_IRQS);
 
-       set_except_vector(0, jmr3927_IRQ);
-
        /* setup irq space */
        add_tb_irq_space(&jmr3927_isac_irqspace);
        add_tb_irq_space(&jmr3927_ioc_irqspace);
index 309d54cceda3c66eb93d4c48eb655aaa6238d72c..34e8a256765c3f2a811e6c6edc701ccb6544b032 100644 (file)
@@ -34,8 +34,11 @@ obj-$(CONFIG_CPU_R6000)              += r6000_fpu.o r4k_switch.o
 
 obj-$(CONFIG_SMP)              += smp.o
 
-obj-$(CONFIG_MIPS_MT_SMP)      += smp_mt.o
+obj-$(CONFIG_MIPS_MT)          += mips-mt.o
+obj-$(CONFIG_MIPS_MT_SMTC)     += smtc.o smtc-asm.o smtc-proc.o
+obj-$(CONFIG_MIPS_MT_SMP)      += smp-mt.o
 
+obj-$(CONFIG_MIPS_APSP_KSPD)   += kspd.o
 obj-$(CONFIG_MIPS_VPE_LOADER)  += vpe.o
 obj-$(CONFIG_MIPS_VPE_APSP_API)        += rtlx.o
 
index ca6b03c773be3b2d7da5578b2d8da7838a7c19b0..92b28b674d6f615be8ab8894ea117e06018f44d1 100644 (file)
@@ -69,6 +69,9 @@ void output_ptreg_defines(void)
        offset("#define PT_BVADDR ", struct pt_regs, cp0_badvaddr);
        offset("#define PT_STATUS ", struct pt_regs, cp0_status);
        offset("#define PT_CAUSE  ", struct pt_regs, cp0_cause);
+#ifdef CONFIG_MIPS_MT_SMTC
+       offset("#define PT_TCSTATUS  ", struct pt_regs, cp0_tcstatus);
+#endif /* CONFIG_MIPS_MT_SMTC */
        size("#define PT_SIZE   ", struct pt_regs);
        linefeed;
 }
index 83c87fe4ee4f0b631cb5be82dfd9783d15c3541d..d101d2fb24caab6f8283647a20a5c37768f30c05 100644 (file)
@@ -17,6 +17,9 @@
 #include <asm/isadep.h>
 #include <asm/thread_info.h>
 #include <asm/war.h>
+#ifdef CONFIG_MIPS_MT_SMTC
+#include <asm/mipsmtregs.h>
+#endif
 
 #ifdef CONFIG_PREEMPT
        .macro  preempt_stop
@@ -75,6 +78,37 @@ FEXPORT(syscall_exit)
        bnez    t0, syscall_exit_work
 
 FEXPORT(restore_all)                   # restore full frame
+#ifdef CONFIG_MIPS_MT_SMTC
+/* Detect and execute deferred IPI "interrupts" */
+       move    a0,sp
+       jal     deferred_smtc_ipi
+/* Re-arm any temporarily masked interrupts not explicitly "acked" */
+       mfc0    v0, CP0_TCSTATUS
+       ori     v1, v0, TCSTATUS_IXMT
+       mtc0    v1, CP0_TCSTATUS
+       andi    v0, TCSTATUS_IXMT
+       ehb
+       mfc0    t0, CP0_TCCONTEXT
+       DMT     9                               # dmt t1
+       jal     mips_ihb
+       mfc0    t2, CP0_STATUS
+       andi    t3, t0, 0xff00
+       or      t2, t2, t3
+       mtc0    t2, CP0_STATUS
+       ehb
+       andi    t1, t1, VPECONTROL_TE
+       beqz    t1, 1f
+       EMT
+1:
+       mfc0    v1, CP0_TCSTATUS
+       /* We set IXMT above, XOR should cler it here */
+       xori    v1, v1, TCSTATUS_IXMT
+       or      v1, v0, v1
+       mtc0    v1, CP0_TCSTATUS
+       ehb
+       xor     t0, t0, t3
+       mtc0    t0, CP0_TCCONTEXT
+#endif /* CONFIG_MIPS_MT_SMTC */
        .set    noat
        RESTORE_TEMP
        RESTORE_AT
@@ -120,28 +154,17 @@ syscall_exit_work:
        jal     do_syscall_trace
        b       resume_userspace
 
+#if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_MIPS_MT)
+
 /*
- * Common spurious interrupt handler.
+ * MIPS32R2 Instruction Hazard Barrier - must be called
+ *
+ * For C code use the inline version named instruction_hazard().
  */
-LEAF(spurious_interrupt)
-       /*
-        * Someone tried to fool us by sending an interrupt but we
-        * couldn't find a cause for it.
-        */
-       PTR_LA  t1, irq_err_count
-#ifdef CONFIG_SMP
-1:     ll      t0, (t1)
-       addiu   t0, 1
-       sc      t0, (t1)
-#if R10000_LLSC_WAR
-       beqzl   t0, 1b
-#else
-       beqz    t0, 1b
-#endif
-#else
-       lw      t0, (t1)
-       addiu   t0, 1
-       sw      t0, (t1)
-#endif
-       j       ret_from_irq
-       END(spurious_interrupt)
+LEAF(mips_ihb)
+       .set    mips32r2
+       jr.hb   ra
+       nop
+       END(mips_ihb)
+
+#endif /* CONFIG_CPU_MIPSR2 or CONFIG_MIPS_MT */
index 235ad9f6bd350595318335171a2ab4e2db5b72d5..10f28fb9f008a92fc89b68c89734233297e8472b 100644 (file)
  */
 
 3:
+#ifdef CONFIG_MIPS_MT_SMTC
+               /* Read-modify write of Status must be atomic */
+               mfc0    t2, CP0_TCSTATUS
+               ori     t1, t2, TCSTATUS_IXMT
+               mtc0    t1, CP0_TCSTATUS
+               andi    t2, t2, TCSTATUS_IXMT
+               ehb
+               DMT     9                               # dmt   t1
+               jal     mips_ihb
+               nop
+#endif /* CONFIG_MIPS_MT_SMTC */
                mfc0    t0, CP0_STATUS
                ori     t0, 0x1f
                xori    t0, 0x1f
                mtc0    t0, CP0_STATUS
-
+#ifdef CONFIG_MIPS_MT_SMTC
+               andi    t1, t1, VPECONTROL_TE
+               beqz    t1, 9f
+               nop
+               EMT                                     # emt
+9:
+               mfc0    t1, CP0_TCSTATUS
+               xori    t1, t1, TCSTATUS_IXMT
+               or      t1, t1, t2
+               mtc0    t1, CP0_TCSTATUS
+               ehb
+#endif /* CONFIG_MIPS_MT_SMTC */
                LONG_L  v0, GDB_FR_STATUS(sp)
                LONG_L  v1, GDB_FR_EPC(sp)
                mtc0    v0, CP0_STATUS
index d4f88e0af24c04fcb51271d50414242418f96ded..6ecbdc1fefd13acdd930998a07c19e633aaab354 100644 (file)
 #include <asm/system.h>
 #include <asm/gdb-stub.h>
 #include <asm/inst.h>
+#include <asm/smp.h>
 
 /*
  * external low-level support routines
@@ -669,6 +670,64 @@ static void kgdb_wait(void *arg)
        local_irq_restore(flags);
 }
 
+/*
+ * GDB stub needs to call kgdb_wait on all processor with interrupts
+ * disabled, so it uses it's own special variant.
+ */
+static int kgdb_smp_call_kgdb_wait(void)
+{
+#ifdef CONFIG_SMP
+       struct call_data_struct data;
+       int i, cpus = num_online_cpus() - 1;
+       int cpu = smp_processor_id();
+
+       /*
+        * Can die spectacularly if this CPU isn't yet marked online
+        */
+       BUG_ON(!cpu_online(cpu));
+
+       if (!cpus)
+               return 0;
+
+       if (spin_is_locked(&smp_call_lock)) {
+               /*
+                * Some other processor is trying to make us do something
+                * but we're not going to respond... give up
+                */
+               return -1;
+               }
+
+       /*
+        * We will continue here, accepting the fact that
+        * the kernel may deadlock if another CPU attempts
+        * to call smp_call_function now...
+        */
+
+       data.func = kgdb_wait;
+       data.info = NULL;
+       atomic_set(&data.started, 0);
+       data.wait = 0;
+
+       spin_lock(&smp_call_lock);
+       call_data = &data;
+       mb();
+
+       /* Send a message to all other CPUs and wait for them to respond */
+       for (i = 0; i < NR_CPUS; i++)
+               if (cpu_online(i) && i != cpu)
+                       core_send_ipi(i, SMP_CALL_FUNCTION);
+
+       /* Wait for response */
+       /* FIXME: lock-up detection, backtrace on lock-up */
+       while (atomic_read(&data.started) != cpus)
+               barrier();
+
+       call_data = NULL;
+       spin_unlock(&smp_call_lock);
+#endif
+
+       return 0;
+}
 
 /*
  * This function does all command processing for interfacing to gdb.  It
@@ -718,7 +777,7 @@ void handle_exception (struct gdb_regs *regs)
        /*
         * force other cpus to enter kgdb
         */
-       smp_call_function(kgdb_wait, NULL, 0, 0);
+       kgdb_smp_call_kgdb_wait();
 
        /*
         * If we're in breakpoint() increment the PC
index 13f22d1d0e8b7fe119ca0294e257567bf693359a..ff7af369f2862eedd4e8fbf08eb6eb3adf263010 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/init.h>
 
 #include <asm/asm.h>
+#include <asm/asmmacro.h>
 #include <asm/cacheops.h>
 #include <asm/regdef.h>
 #include <asm/fpregdef.h>
@@ -122,6 +123,20 @@ handle_vcei:
        .set    pop
        END(except_vec3_r4000)
 
+       __FINIT
+
+       .align  5
+NESTED(handle_int, PT_SIZE, sp)
+       SAVE_ALL
+       CLI
+
+       PTR_LA  ra, ret_from_irq
+       move    a0, sp
+       j       plat_irq_dispatch
+       END(handle_int)
+
+       __INIT
+
 /*
  * Special interrupt vector for MIPS64 ISA & embedded MIPS processors.
  * This is a dedicated interrupt exception vector which reduces the
@@ -157,6 +172,15 @@ NESTED(except_vec_vi, 0, sp)
        SAVE_AT
        .set    push
        .set    noreorder
+#ifdef CONFIG_MIPS_MT_SMTC
+       /*
+        * To keep from blindly blocking *all* interrupts
+        * during service by SMTC kernel, we also want to
+        * pass the IM value to be cleared.
+        */
+EXPORT(except_vec_vi_mori)
+       ori     a0, $0, 0
+#endif /* CONFIG_MIPS_MT_SMTC */
 EXPORT(except_vec_vi_lui)
        lui     v0, 0           /* Patched */
        j       except_vec_vi_handler
@@ -173,6 +197,25 @@ EXPORT(except_vec_vi_end)
 NESTED(except_vec_vi_handler, 0, sp)
        SAVE_TEMP
        SAVE_STATIC
+#ifdef CONFIG_MIPS_MT_SMTC
+       /*
+        * SMTC has an interesting problem that interrupts are level-triggered,
+        * and the CLI macro will clear EXL, potentially causing a duplicate
+        * interrupt service invocation. So we need to clear the associated
+        * IM bit of Status prior to doing CLI, and restore it after the
+        * service routine has been invoked - we must assume that the
+        * service routine will have cleared the state, and any active
+        * level represents a new or otherwised unserviced event...
+        */
+       mfc0    t1, CP0_STATUS
+       and     t0, a0, t1
+       mfc0    t2, CP0_TCCONTEXT
+       or      t0, t0, t2
+       mtc0    t0, CP0_TCCONTEXT
+       xor     t1, t1, t0
+       mtc0    t1, CP0_STATUS
+       ehb
+#endif /* CONFIG_MIPS_MT_SMTC */
        CLI
        move    a0, sp
        jalr    v0
index 2e9122a4213a2215480637903b0948910ef6128c..bdf6f6eff721262d1c98a9dc48adba2b569adba9 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/threads.h>
 
 #include <asm/asm.h>
+#include <asm/asmmacro.h>
 #include <asm/regdef.h>
 #include <asm/page.h>
 #include <asm/mipsregs.h>
         */
        .macro  setup_c0_status set clr
        .set    push
+#ifdef CONFIG_MIPS_MT_SMTC
+       /*
+        * For SMTC, we need to set privilege and disable interrupts only for
+        * the current TC, using the TCStatus register.
+        */
+       mfc0    t0, CP0_TCSTATUS
+       /* Fortunately CU 0 is in the same place in both registers */
+       /* Set TCU0, TMX, TKSU (for later inversion) and IXMT */
+       li      t1, ST0_CU0 | 0x08001c00
+       or      t0, t1
+       /* Clear TKSU, leave IXMT */
+       xori    t0, 0x00001800
+       mtc0    t0, CP0_TCSTATUS
+       ehb
+       /* We need to leave the global IE bit set, but clear EXL...*/
+       mfc0    t0, CP0_STATUS
+       or      t0, ST0_CU0 | ST0_EXL | ST0_ERL | \set | \clr
+       xor     t0, ST0_EXL | ST0_ERL | \clr
+       mtc0    t0, CP0_STATUS
+#else
        mfc0    t0, CP0_STATUS
        or      t0, ST0_CU0|\set|0x1f|\clr
        xor     t0, 0x1f|\clr
        mtc0    t0, CP0_STATUS
        .set    noreorder
        sll     zero,3                          # ehb
+#endif
        .set    pop
        .endm
 
@@ -134,6 +156,24 @@ NESTED(kernel_entry, 16, sp)                       # kernel entry point
 
        ARC64_TWIDDLE_PC
 
+#ifdef CONFIG_MIPS_MT_SMTC
+       /*
+        * In SMTC kernel, "CLI" is thread-specific, in TCStatus.
+        * We still need to enable interrupts globally in Status,
+        * and clear EXL/ERL.
+        *
+        * TCContext is used to track interrupt levels under
+        * service in SMTC kernel. Clear for boot TC before
+        * allowing any interrupts.
+        */
+       mtc0    zero, CP0_TCCONTEXT
+
+       mfc0    t0, CP0_STATUS
+       ori     t0, t0, 0xff1f
+       xori    t0, t0, 0x001e
+       mtc0    t0, CP0_STATUS
+#endif /* CONFIG_MIPS_MT_SMTC */
+
        PTR_LA          t0, __bss_start         # clear .bss
        LONG_S          zero, (t0)
        PTR_LA          t1, __bss_stop - LONGSIZE
@@ -166,8 +206,25 @@ NESTED(kernel_entry, 16, sp)                       # kernel entry point
  * function after setting up the stack and gp registers.
  */
 NESTED(smp_bootstrap, 16, sp)
+#ifdef CONFIG_MIPS_MT_SMTC
+       /*
+        * Read-modify-writes of Status must be atomic, and this
+        * is one case where CLI is invoked without EXL being
+        * necessarily set. The CLI and setup_c0_status will
+        * in fact be redundant for all but the first TC of
+        * each VPE being booted.
+        */
+       DMT     10      # dmt t2 /* t0, t1 are used by CLI and setup_c0_status() */
+       jal     mips_ihb
+#endif /* CONFIG_MIPS_MT_SMTC */
        setup_c0_status_sec
        smp_slave_setup
+#ifdef CONFIG_MIPS_MT_SMTC
+       andi    t2, t2, VPECONTROL_TE
+       beqz    t2, 2f
+       EMT             # emt
+2:
+#endif /* CONFIG_MIPS_MT_SMTC */
        j       start_secondary
        END(smp_bootstrap)
 #endif /* CONFIG_SMP */
index b974ac9057f616e5f3eb07882da80c3712762842..2125ba5f1d9b20b2d2e0fe282e6513b399546478 100644 (file)
@@ -187,6 +187,10 @@ handle_real_irq:
                outb(cached_21,0x21);
                outb(0x60+irq,0x20);    /* 'Specific EOI' to master */
        }
+#ifdef CONFIG_MIPS_MT_SMTC
+        if (irq_hwmask[irq] & ST0_IM)
+               set_c0_status(irq_hwmask[irq] & ST0_IM);
+#endif /* CONFIG_MIPS_MT_SMTC */
        spin_unlock_irqrestore(&i8259A_lock, flags);
        return;
 
index 3f653c7cfbf3d58eba3dbb300d96a13152a10aea..97ebdc754b9e6e8a59a1edf02611819872e606fb 100644 (file)
@@ -76,6 +76,11 @@ static void level_mask_and_ack_msc_irq(unsigned int irq)
        mask_msc_irq(irq);
        if (!cpu_has_veic)
                MSCIC_WRITE(MSC01_IC_EOI, 0);
+#ifdef CONFIG_MIPS_MT_SMTC
+       /* This actually needs to be a call into platform code */
+       if (irq_hwmask[irq] & ST0_IM)
+               set_c0_status(irq_hwmask[irq] & ST0_IM);
+#endif /* CONFIG_MIPS_MT_SMTC */
 }
 
 /*
@@ -92,6 +97,10 @@ static void edge_mask_and_ack_msc_irq(unsigned int irq)
                MSCIC_WRITE(MSC01_IC_SUP+irq*8, r | ~MSC01_IC_SUP_EDGE_BIT);
                MSCIC_WRITE(MSC01_IC_SUP+irq*8, r);
        }
+#ifdef CONFIG_MIPS_MT_SMTC
+       if (irq_hwmask[irq] & ST0_IM)
+               set_c0_status(irq_hwmask[irq] & ST0_IM);
+#endif /* CONFIG_MIPS_MT_SMTC */
 }
 
 /*
index 3dd76b3d296778c1f81596a8888da5bf96fc4ab3..3dce742e716fd3df1b36920dc3606d2e91fb056b 100644 (file)
@@ -38,6 +38,15 @@ void ack_bad_irq(unsigned int irq)
 
 atomic_t irq_err_count;
 
+#ifdef CONFIG_MIPS_MT_SMTC
+/*
+ * SMTC Kernel needs to manipulate low-level CPU interrupt mask
+ * in do_IRQ. These are passed in setup_irq_smtc() and stored
+ * in this table.
+ */
+unsigned long irq_hwmask[NR_IRQS];
+#endif /* CONFIG_MIPS_MT_SMTC */
+
 #undef do_IRQ
 
 /*
@@ -49,6 +58,7 @@ asmlinkage unsigned int do_IRQ(unsigned int irq, struct pt_regs *regs)
 {
        irq_enter();
 
+       __DO_IRQ_SMTC_HOOK();
        __do_IRQ(irq, regs);
 
        irq_exit();
@@ -101,6 +111,11 @@ skip:
        return 0;
 }
 
+asmlinkage void spurious_interrupt(struct pt_regs *regs)
+{
+       atomic_inc(&irq_err_count);
+}
+
 #ifdef CONFIG_KGDB
 extern void breakpoint(void);
 extern void set_debug_traps(void);
@@ -124,6 +139,9 @@ void __init init_IRQ(void)
                irq_desc[i].depth   = 1;
                irq_desc[i].handler = &no_irq_type;
                spin_lock_init(&irq_desc[i].lock);
+#ifdef CONFIG_MIPS_MT_SMTC
+               irq_hwmask[i] = 0;
+#endif /* CONFIG_MIPS_MT_SMTC */
        }
 
        arch_init_irq();
diff --git a/arch/mips/kernel/kspd.c b/arch/mips/kernel/kspd.c
new file mode 100644 (file)
index 0000000..f06a144
--- /dev/null
@@ -0,0 +1,398 @@
+/*
+ * Copyright (C) 2005 MIPS Technologies, Inc.  All rights reserved.
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope 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.
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/unistd.h>
+#include <linux/file.h>
+#include <linux/fs.h>
+#include <linux/syscalls.h>
+#include <linux/workqueue.h>
+#include <linux/errno.h>
+#include <linux/list.h>
+
+#include <asm/vpe.h>
+#include <asm/rtlx.h>
+#include <asm/kspd.h>
+
+static struct workqueue_struct *workqueue = NULL;
+static struct work_struct work;
+
+extern unsigned long cpu_khz;
+
+struct mtsp_syscall {
+       int cmd;
+       unsigned char abi;
+       unsigned char size;
+};
+
+struct mtsp_syscall_ret {
+       int retval;
+       int errno;
+};
+
+struct mtsp_syscall_generic {
+       int arg0;
+       int arg1;
+       int arg2;
+       int arg3;
+       int arg4;
+       int arg5;
+       int arg6;
+};
+
+static struct list_head kspd_notifylist;
+static int sp_stopping = 0;
+
+/* these should match with those in the SDE kit */
+#define MTSP_SYSCALL_BASE      0
+#define MTSP_SYSCALL_EXIT      (MTSP_SYSCALL_BASE + 0)
+#define MTSP_SYSCALL_OPEN      (MTSP_SYSCALL_BASE + 1)
+#define MTSP_SYSCALL_READ      (MTSP_SYSCALL_BASE + 2)
+#define MTSP_SYSCALL_WRITE     (MTSP_SYSCALL_BASE + 3)
+#define MTSP_SYSCALL_CLOSE     (MTSP_SYSCALL_BASE + 4)
+#define MTSP_SYSCALL_LSEEK32   (MTSP_SYSCALL_BASE + 5)
+#define MTSP_SYSCALL_ISATTY    (MTSP_SYSCALL_BASE + 6)
+#define MTSP_SYSCALL_GETTIME   (MTSP_SYSCALL_BASE + 7)
+#define MTSP_SYSCALL_PIPEFREQ  (MTSP_SYSCALL_BASE + 8)
+#define MTSP_SYSCALL_GETTOD    (MTSP_SYSCALL_BASE + 9)
+
+#define MTSP_O_RDONLY          0x0000
+#define MTSP_O_WRONLY          0x0001
+#define MTSP_O_RDWR            0x0002
+#define MTSP_O_NONBLOCK                0x0004
+#define MTSP_O_APPEND          0x0008
+#define MTSP_O_SHLOCK          0x0010
+#define MTSP_O_EXLOCK          0x0020
+#define MTSP_O_ASYNC           0x0040
+#define MTSP_O_FSYNC           O_SYNC
+#define MTSP_O_NOFOLLOW                0x0100
+#define MTSP_O_SYNC            0x0080
+#define MTSP_O_CREAT           0x0200
+#define MTSP_O_TRUNC           0x0400
+#define MTSP_O_EXCL            0x0800
+#define MTSP_O_BINARY          0x8000
+
+#define SP_VPE 1
+
+struct apsp_table  {
+       int sp;
+       int ap;
+};
+
+/* we might want to do the mode flags too */
+struct apsp_table open_flags_table[] = {
+       { MTSP_O_RDWR, O_RDWR },
+       { MTSP_O_WRONLY, O_WRONLY },
+       { MTSP_O_CREAT, O_CREAT },
+       { MTSP_O_TRUNC, O_TRUNC },
+       { MTSP_O_NONBLOCK, O_NONBLOCK },
+       { MTSP_O_APPEND, O_APPEND },
+       { MTSP_O_NOFOLLOW, O_NOFOLLOW }
+};
+
+struct apsp_table syscall_command_table[] = {
+       { MTSP_SYSCALL_OPEN, __NR_open },
+       { MTSP_SYSCALL_CLOSE, __NR_close },
+       { MTSP_SYSCALL_READ, __NR_read },
+       { MTSP_SYSCALL_WRITE, __NR_write },
+       { MTSP_SYSCALL_LSEEK32, __NR_lseek }
+};
+
+static int sp_syscall(int num, int arg0, int arg1, int arg2, int arg3)
+{
+       register long int _num  __asm__ ("$2") = num;
+       register long int _arg0  __asm__ ("$4") = arg0;
+       register long int _arg1  __asm__ ("$5") = arg1;
+       register long int _arg2  __asm__ ("$6") = arg2;
+       register long int _arg3  __asm__ ("$7") = arg3;
+
+       mm_segment_t old_fs;
+
+       old_fs = get_fs();
+       set_fs(KERNEL_DS);
+
+       __asm__ __volatile__ (
+       "       syscall                                 \n"
+       : "=r" (_num), "=r" (_arg3)
+       : "r" (_num), "r" (_arg0), "r" (_arg1), "r" (_arg2), "r" (_arg3));
+
+       set_fs(old_fs);
+
+       /* $a3 is error flag */
+       if (_arg3)
+               return -_num;
+
+       return _num;
+}
+
+static int translate_syscall_command(int cmd)
+{
+       int i;
+       int ret = -1;
+
+       for (i = 0; i < ARRAY_SIZE(syscall_command_table); i++) {
+               if ((cmd == syscall_command_table[i].sp))
+                       return syscall_command_table[i].ap;
+       }
+
+       return ret;
+}
+
+static unsigned int translate_open_flags(int flags)
+{
+       int i;
+       unsigned int ret = 0;
+
+       for (i = 0; i < (sizeof(open_flags_table) / sizeof(struct apsp_table));
+            i++) {
+               if( (flags & open_flags_table[i].sp) ) {
+                       ret |= open_flags_table[i].ap;
+               }
+       }
+
+       return ret;
+}
+
+
+static void sp_setfsuidgid( uid_t uid, gid_t gid)
+{
+       current->fsuid = uid;
+       current->fsgid = gid;
+
+       key_fsuid_changed(current);
+       key_fsgid_changed(current);
+}
+
+/*
+ * Expects a request to be on the sysio channel. Reads it.  Decides whether
+ * its a linux syscall and runs it, or whatever.  Puts the return code back
+ * into the request and sends the whole thing back.
+ */
+void sp_work_handle_request(void)
+{
+       struct mtsp_syscall sc;
+       struct mtsp_syscall_generic generic;
+       struct mtsp_syscall_ret ret;
+       struct kspd_notifications *n;
+       struct timeval tv;
+       struct timezone tz;
+       int cmd;
+
+       char *vcwd;
+       mm_segment_t old_fs;
+       int size;
+
+       ret.retval = -1;
+
+       if (!rtlx_read(RTLX_CHANNEL_SYSIO, &sc, sizeof(struct mtsp_syscall), 0)) {
+               printk(KERN_ERR "Expected request but nothing to read\n");
+               return;
+       }
+
+       size = sc.size;
+
+       if (size) {
+               if (!rtlx_read(RTLX_CHANNEL_SYSIO, &generic, size, 0)) {
+                       printk(KERN_ERR "Expected request but nothing to read\n");
+                       return;
+               }
+       }
+
+       /* Run the syscall at the priviledge of the user who loaded the
+          SP program */
+
+       if (vpe_getuid(SP_VPE))
+               sp_setfsuidgid( vpe_getuid(SP_VPE), vpe_getgid(SP_VPE));
+
+       switch (sc.cmd) {
+       /* needs the flags argument translating from SDE kit to
+          linux */
+       case MTSP_SYSCALL_PIPEFREQ:
+               ret.retval = cpu_khz * 1000;
+               ret.errno = 0;
+               break;
+
+       case MTSP_SYSCALL_GETTOD:
+               memset(&tz, 0, sizeof(tz));
+               if ((ret.retval = sp_syscall(__NR_gettimeofday, (int)&tv,
+                                            (int)&tz, 0,0)) == 0)
+               ret.retval = tv.tv_sec;
+
+               ret.errno = errno;
+               break;
+
+       case MTSP_SYSCALL_EXIT:
+               list_for_each_entry(n, &kspd_notifylist, list)
+                       n->kspd_sp_exit(SP_VPE);
+               sp_stopping = 1;
+
+               printk(KERN_DEBUG "KSPD got exit syscall from SP exitcode %d\n",
+                      generic.arg0);
+               break;
+
+       case MTSP_SYSCALL_OPEN:
+               generic.arg1 = translate_open_flags(generic.arg1);
+
+               vcwd = vpe_getcwd(SP_VPE);
+
+               /* change to the cwd of the process that loaded the SP program */
+               old_fs = get_fs();
+               set_fs(KERNEL_DS);
+               sys_chdir(vcwd);
+               set_fs(old_fs);
+
+               sc.cmd = __NR_open;
+
+               /* fall through */
+
+       default:
+               if ((sc.cmd >= __NR_Linux) &&
+                   (sc.cmd <= (__NR_Linux +  __NR_Linux_syscalls)) )
+                       cmd = sc.cmd;
+               else
+                       cmd = translate_syscall_command(sc.cmd);
+
+               if (cmd >= 0) {
+                       ret.retval = sp_syscall(cmd, generic.arg0, generic.arg1,
+                                               generic.arg2, generic.arg3);
+                       ret.errno = errno;
+               } else
+                       printk(KERN_WARNING
+                              "KSPD: Unknown SP syscall number %d\n", sc.cmd);
+               break;
+       } /* switch */
+
+       if (vpe_getuid(SP_VPE))
+               sp_setfsuidgid( 0, 0);
+
+       if ((rtlx_write(RTLX_CHANNEL_SYSIO, &ret, sizeof(struct mtsp_syscall_ret), 0))
+           < sizeof(struct mtsp_syscall_ret))
+               printk("KSPD: sp_work_handle_request failed to send to SP\n");
+}
+
+static void sp_cleanup(void)
+{
+       struct files_struct *files = current->files;
+       int i, j;
+       struct fdtable *fdt;
+
+       j = 0;
+
+       /*
+        * It is safe to dereference the fd table without RCU or
+        * ->file_lock
+        */
+       fdt = files_fdtable(files);
+       for (;;) {
+               unsigned long set;
+               i = j * __NFDBITS;
+               if (i >= fdt->max_fdset || i >= fdt->max_fds)
+                       break;
+               set = fdt->open_fds->fds_bits[j++];
+               while (set) {
+                       if (set & 1) {
+                               struct file * file = xchg(&fdt->fd[i], NULL);
+                               if (file)
+                                       filp_close(file, files);
+                       }
+                       i++;
+                       set >>= 1;
+               }
+       }
+}
+
+static int channel_open = 0;
+
+/* the work handler */
+static void sp_work(void *data)
+{
+       if (!channel_open) {
+               if( rtlx_open(RTLX_CHANNEL_SYSIO, 1) != 0) {
+                       printk("KSPD: unable to open sp channel\n");
+                       sp_stopping = 1;
+               } else {
+                       channel_open++;
+                       printk(KERN_DEBUG "KSPD: SP channel opened\n");
+               }
+       } else {
+               /* wait for some data, allow it to sleep */
+               rtlx_read_poll(RTLX_CHANNEL_SYSIO, 1);
+
+               /* Check we haven't been woken because we are stopping */
+               if (!sp_stopping)
+                       sp_work_handle_request();
+       }
+
+       if (!sp_stopping)
+               queue_work(workqueue, &work);
+       else
+               sp_cleanup();
+}
+
+static void startwork(int vpe)
+{
+       sp_stopping = channel_open = 0;
+
+       if (workqueue == NULL) {
+               if ((workqueue = create_singlethread_workqueue("kspd")) == NULL) {
+                       printk(KERN_ERR "unable to start kspd\n");
+                       return;
+               }
+
+               INIT_WORK(&work, sp_work, NULL);
+               queue_work(workqueue, &work);
+       } else
+               queue_work(workqueue, &work);
+
+}
+
+static void stopwork(int vpe)
+{
+       sp_stopping = 1;
+
+       printk(KERN_DEBUG "KSPD: SP stopping\n");
+}
+
+void kspd_notify(struct kspd_notifications *notify)
+{
+       list_add(&notify->list, &kspd_notifylist);
+}
+
+static struct vpe_notifications notify;
+static int kspd_module_init(void)
+{
+       INIT_LIST_HEAD(&kspd_notifylist);
+
+       notify.start = startwork;
+       notify.stop = stopwork;
+       vpe_notify(SP_VPE, &notify);
+
+       return 0;
+}
+
+static void kspd_module_exit(void)
+{
+
+}
+
+module_init(kspd_module_init);
+module_exit(kspd_module_exit);
+
+MODULE_DESCRIPTION("MIPS KSPD");
+MODULE_AUTHOR("Elizabeth Oldham, MIPS Technologies, Inc.");
+MODULE_LICENSE("GPL");
index 3f40c37a9ee670252a56abf6066ad3b0cbfaec0d..7c953bcc5f6a076413ab740ec53cc925a723b5bc 100644 (file)
@@ -1182,6 +1182,16 @@ asmlinkage ssize_t sys32_readahead(int fd, u32 pad0, u64 a2, u64 a3,
        return sys_readahead(fd, merge_64(a2, a3), count);
 }
 
+asmlinkage long sys32_sync_file_range(int fd, int __pad,
+       unsigned long a2, unsigned long a3,
+       unsigned long a4, unsigned long a5,
+       int flags)
+{
+       return sys_sync_file_range(fd,
+                       merge_64(a2, a3), merge_64(a4, a5),
+                       flags);
+}
+
 /* Argument list sizes for sys_socketcall */
 #define AL(x) ((x) * sizeof(unsigned int))
 static unsigned char socketcall_nargs[18]={AL(0),AL(3),AL(3),AL(3),AL(2),AL(3),
diff --git a/arch/mips/kernel/mips-mt.c b/arch/mips/kernel/mips-mt.c
new file mode 100644 (file)
index 0000000..02237a6
--- /dev/null
@@ -0,0 +1,449 @@
+/*
+ * General MIPS MT support routines, usable in AP/SP, SMVP, or SMTC kernels
+ * Copyright (C) 2005 Mips Technologies, Inc
+ */
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/cpumask.h>
+#include <linux/interrupt.h>
+
+#include <asm/cpu.h>
+#include <asm/processor.h>
+#include <asm/atomic.h>
+#include <asm/system.h>
+#include <asm/hardirq.h>
+#include <asm/mmu_context.h>
+#include <asm/smp.h>
+#include <asm/mipsmtregs.h>
+#include <asm/r4kcache.h>
+#include <asm/cacheflush.h>
+
+/*
+ * CPU mask used to set process affinity for MT VPEs/TCs with FPUs
+ */
+
+cpumask_t mt_fpu_cpumask;
+
+#ifdef CONFIG_MIPS_MT_FPAFF
+
+#include <linux/cpu.h>
+#include <linux/delay.h>
+#include <asm/uaccess.h>
+
+unsigned long mt_fpemul_threshold = 0;
+
+/*
+ * Replacement functions for the sys_sched_setaffinity() and
+ * sys_sched_getaffinity() system calls, so that we can integrate
+ * FPU affinity with the user's requested processor affinity.
+ * This code is 98% identical with the sys_sched_setaffinity()
+ * and sys_sched_getaffinity() system calls, and should be
+ * updated when kernel/sched.c changes.
+ */
+
+/*
+ * find_process_by_pid - find a process with a matching PID value.
+ * used in sys_sched_set/getaffinity() in kernel/sched.c, so
+ * cloned here.
+ */
+static inline task_t *find_process_by_pid(pid_t pid)
+{
+       return pid ? find_task_by_pid(pid) : current;
+}
+
+
+/*
+ * mipsmt_sys_sched_setaffinity - set the cpu affinity of a process
+ */
+asmlinkage long mipsmt_sys_sched_setaffinity(pid_t pid, unsigned int len,
+                                     unsigned long __user *user_mask_ptr)
+{
+       cpumask_t new_mask;
+       cpumask_t effective_mask;
+       int retval;
+       task_t *p;
+
+       if (len < sizeof(new_mask))
+               return -EINVAL;
+
+       if (copy_from_user(&new_mask, user_mask_ptr, sizeof(new_mask)))
+               return -EFAULT;
+
+       lock_cpu_hotplug();
+       read_lock(&tasklist_lock);
+
+       p = find_process_by_pid(pid);
+       if (!p) {
+               read_unlock(&tasklist_lock);
+               unlock_cpu_hotplug();
+               return -ESRCH;
+       }
+
+       /*
+        * It is not safe to call set_cpus_allowed with the
+        * tasklist_lock held.  We will bump the task_struct's
+        * usage count and drop tasklist_lock before invoking
+        * set_cpus_allowed.
+        */
+       get_task_struct(p);
+
+       retval = -EPERM;
+       if ((current->euid != p->euid) && (current->euid != p->uid) &&
+                       !capable(CAP_SYS_NICE)) {
+               read_unlock(&tasklist_lock);
+               goto out_unlock;
+       }
+
+       /* Record new user-specified CPU set for future reference */
+       p->thread.user_cpus_allowed = new_mask;
+
+       /* Unlock the task list */
+       read_unlock(&tasklist_lock);
+
+       /* Compute new global allowed CPU set if necessary */
+       if( (p->thread.mflags & MF_FPUBOUND)
+       && cpus_intersects(new_mask, mt_fpu_cpumask)) {
+               cpus_and(effective_mask, new_mask, mt_fpu_cpumask);
+               retval = set_cpus_allowed(p, effective_mask);
+       } else {
+               p->thread.mflags &= ~MF_FPUBOUND;
+               retval = set_cpus_allowed(p, new_mask);
+       }
+
+
+out_unlock:
+       put_task_struct(p);
+       unlock_cpu_hotplug();
+       return retval;
+}
+
+/*
+ * mipsmt_sys_sched_getaffinity - get the cpu affinity of a process
+ */
+asmlinkage long mipsmt_sys_sched_getaffinity(pid_t pid, unsigned int len,
+                                     unsigned long __user *user_mask_ptr)
+{
+       unsigned int real_len;
+       cpumask_t mask;
+       int retval;
+       task_t *p;
+
+       real_len = sizeof(mask);
+       if (len < real_len)
+               return -EINVAL;
+
+       lock_cpu_hotplug();
+       read_lock(&tasklist_lock);
+
+       retval = -ESRCH;
+       p = find_process_by_pid(pid);
+       if (!p)
+               goto out_unlock;
+
+       retval = 0;
+
+       cpus_and(mask, p->thread.user_cpus_allowed, cpu_possible_map);
+
+out_unlock:
+       read_unlock(&tasklist_lock);
+       unlock_cpu_hotplug();
+       if (retval)
+               return retval;
+       if (copy_to_user(user_mask_ptr, &mask, real_len))
+               return -EFAULT;
+       return real_len;
+}
+
+#endif /* CONFIG_MIPS_MT_FPAFF */
+
+/*
+ * Dump new MIPS MT state for the core. Does not leave TCs halted.
+ * Takes an argument which taken to be a pre-call MVPControl value.
+ */
+
+void mips_mt_regdump(unsigned long mvpctl)
+{
+       unsigned long flags;
+       unsigned long vpflags;
+       unsigned long mvpconf0;
+       int nvpe;
+       int ntc;
+       int i;
+       int tc;
+       unsigned long haltval;
+       unsigned long tcstatval;
+#ifdef CONFIG_MIPS_MT_SMTC
+       void smtc_soft_dump(void);
+#endif /* CONFIG_MIPT_MT_SMTC */
+
+       local_irq_save(flags);
+       vpflags = dvpe();
+       printk("=== MIPS MT State Dump ===\n");
+       printk("-- Global State --\n");
+       printk("   MVPControl Passed: %08lx\n", mvpctl);
+       printk("   MVPControl Read: %08lx\n", vpflags);
+       printk("   MVPConf0 : %08lx\n", (mvpconf0 = read_c0_mvpconf0()));
+       nvpe = ((mvpconf0 & MVPCONF0_PVPE) >> MVPCONF0_PVPE_SHIFT) + 1;
+       ntc = ((mvpconf0 & MVPCONF0_PTC) >> MVPCONF0_PTC_SHIFT) + 1;
+       printk("-- per-VPE State --\n");
+       for(i = 0; i < nvpe; i++) {
+           for(tc = 0; tc < ntc; tc++) {
+                       settc(tc);
+               if((read_tc_c0_tcbind() & TCBIND_CURVPE) == i) {
+                   printk("  VPE %d\n", i);
+                   printk("   VPEControl : %08lx\n", read_vpe_c0_vpecontrol());
+                   printk("   VPEConf0 : %08lx\n", read_vpe_c0_vpeconf0());
+                   printk("   VPE%d.Status : %08lx\n",
+                               i, read_vpe_c0_status());
+                   printk("   VPE%d.EPC : %08lx\n", i, read_vpe_c0_epc());
+                   printk("   VPE%d.Cause : %08lx\n", i, read_vpe_c0_cause());
+                   printk("   VPE%d.Config7 : %08lx\n",
+                               i, read_vpe_c0_config7());
+                   break; /* Next VPE */
+               }
+           }
+       }
+       printk("-- per-TC State --\n");
+       for(tc = 0; tc < ntc; tc++) {
+               settc(tc);
+               if(read_tc_c0_tcbind() == read_c0_tcbind()) {
+                       /* Are we dumping ourself?  */
+                       haltval = 0; /* Then we're not halted, and mustn't be */
+                       tcstatval = flags; /* And pre-dump TCStatus is flags */
+                       printk("  TC %d (current TC with VPE EPC above)\n", tc);
+               } else {
+                       haltval = read_tc_c0_tchalt();
+                       write_tc_c0_tchalt(1);
+                       tcstatval = read_tc_c0_tcstatus();
+                       printk("  TC %d\n", tc);
+               }
+               printk("   TCStatus : %08lx\n", tcstatval);
+               printk("   TCBind : %08lx\n", read_tc_c0_tcbind());
+               printk("   TCRestart : %08lx\n", read_tc_c0_tcrestart());
+               printk("   TCHalt : %08lx\n", haltval);
+               printk("   TCContext : %08lx\n", read_tc_c0_tccontext());
+               if (!haltval)
+                       write_tc_c0_tchalt(0);
+       }
+#ifdef CONFIG_MIPS_MT_SMTC
+       smtc_soft_dump();
+#endif /* CONFIG_MIPT_MT_SMTC */
+       printk("===========================\n");
+       evpe(vpflags);
+       local_irq_restore(flags);
+}
+
+static int mt_opt_norps = 0;
+static int mt_opt_rpsctl = -1;
+static int mt_opt_nblsu = -1;
+static int mt_opt_forceconfig7 = 0;
+static int mt_opt_config7 = -1;
+
+static int __init rps_disable(char *s)
+{
+       mt_opt_norps = 1;
+       return 1;
+}
+__setup("norps", rps_disable);
+
+static int __init rpsctl_set(char *str)
+{
+       get_option(&str, &mt_opt_rpsctl);
+       return 1;
+}
+__setup("rpsctl=", rpsctl_set);
+
+static int __init nblsu_set(char *str)
+{
+       get_option(&str, &mt_opt_nblsu);
+       return 1;
+}
+__setup("nblsu=", nblsu_set);
+
+static int __init config7_set(char *str)
+{
+       get_option(&str, &mt_opt_config7);
+       mt_opt_forceconfig7 = 1;
+       return 1;
+}
+__setup("config7=", config7_set);
+
+/* Experimental cache flush control parameters that should go away some day */
+int mt_protiflush = 0;
+int mt_protdflush = 0;
+int mt_n_iflushes = 1;
+int mt_n_dflushes = 1;
+
+static int __init set_protiflush(char *s)
+{
+       mt_protiflush = 1;
+       return 1;
+}
+__setup("protiflush", set_protiflush);
+
+static int __init set_protdflush(char *s)
+{
+       mt_protdflush = 1;
+       return 1;
+}
+__setup("protdflush", set_protdflush);
+
+static int __init niflush(char *s)
+{
+       get_option(&s, &mt_n_iflushes);
+       return 1;
+}
+__setup("niflush=", niflush);
+
+static int __init ndflush(char *s)
+{
+       get_option(&s, &mt_n_dflushes);
+       return 1;
+}
+__setup("ndflush=", ndflush);
+#ifdef CONFIG_MIPS_MT_FPAFF
+static int fpaff_threshold = -1;
+
+static int __init fpaff_thresh(char *str)
+{
+       get_option(&str, &fpaff_threshold);
+       return 1;
+}
+
+__setup("fpaff=", fpaff_thresh);
+#endif /* CONFIG_MIPS_MT_FPAFF */
+
+static unsigned int itc_base = 0;
+
+static int __init set_itc_base(char *str)
+{
+       get_option(&str, &itc_base);
+       return 1;
+}
+
+__setup("itcbase=", set_itc_base);
+
+void mips_mt_set_cpuoptions(void)
+{
+       unsigned int oconfig7 = read_c0_config7();
+       unsigned int nconfig7 = oconfig7;
+
+       if (mt_opt_norps) {
+               printk("\"norps\" option deprectated: use \"rpsctl=\"\n");
+       }
+       if (mt_opt_rpsctl >= 0) {
+               printk("34K return prediction stack override set to %d.\n",
+                       mt_opt_rpsctl);
+               if (mt_opt_rpsctl)
+                       nconfig7 |= (1 << 2);
+               else
+                       nconfig7 &= ~(1 << 2);
+       }
+       if (mt_opt_nblsu >= 0) {
+               printk("34K ALU/LSU sync override set to %d.\n", mt_opt_nblsu);
+               if (mt_opt_nblsu)
+                       nconfig7 |= (1 << 5);
+               else
+                       nconfig7 &= ~(1 << 5);
+       }
+       if (mt_opt_forceconfig7) {
+               printk("CP0.Config7 forced to 0x%08x.\n", mt_opt_config7);
+               nconfig7 = mt_opt_config7;
+       }
+       if (oconfig7 != nconfig7) {
+               __asm__ __volatile("sync");
+               write_c0_config7(nconfig7);
+               ehb ();
+               printk("Config7: 0x%08x\n", read_c0_config7());
+       }
+
+       /* Report Cache management debug options */
+       if (mt_protiflush)
+               printk("I-cache flushes single-threaded\n");
+       if (mt_protdflush)
+               printk("D-cache flushes single-threaded\n");
+       if (mt_n_iflushes != 1)
+               printk("I-Cache Flushes Repeated %d times\n", mt_n_iflushes);
+       if (mt_n_dflushes != 1)
+               printk("D-Cache Flushes Repeated %d times\n", mt_n_dflushes);
+
+#ifdef CONFIG_MIPS_MT_FPAFF
+       /* FPU Use Factor empirically derived from experiments on 34K */
+#define FPUSEFACTOR 333
+
+       if (fpaff_threshold >= 0) {
+               mt_fpemul_threshold = fpaff_threshold;
+       } else {
+               mt_fpemul_threshold =
+                       (FPUSEFACTOR * (loops_per_jiffy/(500000/HZ))) / HZ;
+       }
+       printk("FPU Affinity set after %ld emulations\n",
+                       mt_fpemul_threshold);
+#endif /* CONFIG_MIPS_MT_FPAFF */
+
+       if (itc_base != 0) {
+               /*
+                * Configure ITC mapping.  This code is very
+                * specific to the 34K core family, which uses
+                * a special mode bit ("ITC") in the ErrCtl
+                * register to enable access to ITC control
+                * registers via cache "tag" operations.
+                */
+               unsigned long ectlval;
+               unsigned long itcblkgrn;
+
+               /* ErrCtl register is known as "ecc" to Linux */
+               ectlval = read_c0_ecc();
+               write_c0_ecc(ectlval | (0x1 << 26));
+               ehb();
+#define INDEX_0 (0x80000000)
+#define INDEX_8 (0x80000008)
+               /* Read "cache tag" for Dcache pseudo-index 8 */
+               cache_op(Index_Load_Tag_D, INDEX_8);
+               ehb();
+               itcblkgrn = read_c0_dtaglo();
+               itcblkgrn &= 0xfffe0000;
+               /* Set for 128 byte pitch of ITC cells */
+               itcblkgrn |= 0x00000c00;
+               /* Stage in Tag register */
+               write_c0_dtaglo(itcblkgrn);
+               ehb();
+               /* Write out to ITU with CACHE op */
+               cache_op(Index_Store_Tag_D, INDEX_8);
+               /* Now set base address, and turn ITC on with 0x1 bit */
+               write_c0_dtaglo((itc_base & 0xfffffc00) | 0x1 );
+               ehb();
+               /* Write out to ITU with CACHE op */
+               cache_op(Index_Store_Tag_D, INDEX_0);
+               write_c0_ecc(ectlval);
+               ehb();
+               printk("Mapped %ld ITC cells starting at 0x%08x\n",
+                       ((itcblkgrn & 0x7fe00000) >> 20), itc_base);
+       }
+}
+
+/*
+ * Function to protect cache flushes from concurrent execution
+ * depends on MP software model chosen.
+ */
+
+void mt_cflush_lockdown(void)
+{
+#ifdef CONFIG_MIPS_MT_SMTC
+       void smtc_cflush_lockdown(void);
+
+       smtc_cflush_lockdown();
+#endif /* CONFIG_MIPS_MT_SMTC */
+       /* FILL IN VSMP and AP/SP VERSIONS HERE */
+}
+
+void mt_cflush_release(void)
+{
+#ifdef CONFIG_MIPS_MT_SMTC
+       void smtc_cflush_release(void);
+
+       smtc_cflush_release();
+#endif /* CONFIG_MIPS_MT_SMTC */
+       /* FILL IN VSMP and AP/SP VERSIONS HERE */
+}
index e042f9d2ba31fb58b2960b4ed6cafc84c88823fc..0a71a4c337161c5304e86730769c82fffcb1e2cf 100644 (file)
@@ -28,21 +28,9 @@ extern long __strnlen_user_asm(const char *s);
 /*
  * String functions
  */
-EXPORT_SYMBOL(memchr);
-EXPORT_SYMBOL(memcmp);
 EXPORT_SYMBOL(memset);
 EXPORT_SYMBOL(memcpy);
 EXPORT_SYMBOL(memmove);
-EXPORT_SYMBOL(strcat);
-EXPORT_SYMBOL(strchr);
-#ifdef CONFIG_64BIT
-EXPORT_SYMBOL(strncmp);
-#endif
-EXPORT_SYMBOL(strlen);
-EXPORT_SYMBOL(strncat);
-EXPORT_SYMBOL(strnlen);
-EXPORT_SYMBOL(strrchr);
-EXPORT_SYMBOL(strstr);
 
 EXPORT_SYMBOL(kernel_thread);
 
@@ -61,6 +49,3 @@ EXPORT_SYMBOL(__strnlen_user_asm);
 EXPORT_SYMBOL(csum_partial);
 
 EXPORT_SYMBOL(invalid_pte_table);
-#ifdef CONFIG_GENERIC_IRQ_PROBE
-EXPORT_SYMBOL(probe_irq_mask);
-#endif
index c66db5e5ab624f9c2b0d3e7256539c6f0932cb97..199a06e873c6ab2e06166234a82d42fa1d3747e7 100644 (file)
 #include <asm/elf.h>
 #include <asm/isadep.h>
 #include <asm/inst.h>
+#ifdef CONFIG_MIPS_MT_SMTC
+#include <asm/mipsmtregs.h>
+extern void smtc_idle_loop_hook(void);
+#endif /* CONFIG_MIPS_MT_SMTC */
 
 /*
  * The idle thread. There's no useful work to be done, so just try to conserve
@@ -51,9 +55,13 @@ ATTRIB_NORET void cpu_idle(void)
 {
        /* endless idle loop with no priority at all */
        while (1) {
-               while (!need_resched())
+               while (!need_resched()) {
+#ifdef CONFIG_MIPS_MT_SMTC
+                       smtc_idle_loop_hook();
+#endif /* CONFIG_MIPS_MT_SMTC */
                        if (cpu_wait)
                                (*cpu_wait)();
+               }
                preempt_enable_no_resched();
                schedule();
                preempt_disable();
@@ -177,6 +185,17 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
        childregs->cp0_status &= ~(ST0_CU2|ST0_CU1);
        clear_tsk_thread_flag(p, TIF_USEDFPU);
 
+#ifdef CONFIG_MIPS_MT_FPAFF
+       /*
+        * FPU affinity support is cleaner if we track the
+        * user-visible CPU affinity from the very beginning.
+        * The generic cpus_allowed mask will already have
+        * been copied from the parent before copy_thread
+        * is invoked.
+        */
+       p->thread.user_cpus_allowed = p->cpus_allowed;
+#endif /* CONFIG_MIPS_MT_FPAFF */
+
        if (clone_flags & CLONE_SETTLS)
                ti->tp_value = regs->regs[7];
 
index f838b36cc765bcbc9ad544701aec14e2ff29c278..f3106d0771b0707ba21a767c32ed852530bc78d9 100644 (file)
@@ -248,10 +248,20 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
                        break;
                case FPC_EIR: { /* implementation / version register */
                        unsigned int flags;
+#ifdef CONFIG_MIPS_MT_SMTC
+                       unsigned int irqflags;
+                       unsigned int mtflags;
+#endif /* CONFIG_MIPS_MT_SMTC */
 
                        if (!cpu_has_fpu)
                                break;
 
+#ifdef CONFIG_MIPS_MT_SMTC
+                       /* Read-modify-write of Status must be atomic */
+                       local_irq_save(irqflags);
+                       mtflags = dmt();
+#endif /* CONFIG_MIPS_MT_SMTC */
+
                        preempt_disable();
                        if (cpu_has_mipsmt) {
                                unsigned int vpflags = dvpe();
@@ -266,6 +276,10 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
                                __asm__ __volatile__("cfc1\t%0,$0": "=r" (tmp));
                                write_c0_status(flags);
                        }
+#ifdef CONFIG_MIPS_MT_SMTC
+                       emt(mtflags);
+                       local_irq_restore(irqflags);
+#endif /* CONFIG_MIPS_MT_SMTC */
                        preempt_enable();
                        break;
                }
index 0d5cf97af727e3c39fd6c3e3fa965979c2a517bf..8704dc0496ea7f2427b4fd111dbbb54397955b0f 100644 (file)
@@ -173,12 +173,22 @@ asmlinkage int sys32_ptrace(int request, int pid, int addr, int data)
                        break;
                case FPC_EIR: { /* implementation / version register */
                        unsigned int flags;
+#ifdef CONFIG_MIPS_MT_SMTC
+                       unsigned int irqflags;
+                       unsigned int mtflags;
+#endif /* CONFIG_MIPS_MT_SMTC */
 
                        if (!cpu_has_fpu) {
                                tmp = 0;
                                break;
                        }
 
+#ifdef CONFIG_MIPS_MT_SMTC
+                       /* Read-modify-write of Status must be atomic */
+                       local_irq_save(irqflags);
+                       mtflags = dmt();
+#endif /* CONFIG_MIPS_MT_SMTC */
+
                        preempt_disable();
                        if (cpu_has_mipsmt) {
                                unsigned int vpflags = dvpe();
@@ -193,6 +203,10 @@ asmlinkage int sys32_ptrace(int request, int pid, int addr, int data)
                                __asm__ __volatile__("cfc1\t%0,$0": "=r" (tmp));
                                write_c0_status(flags);
                        }
+#ifdef CONFIG_MIPS_MT_SMTC
+                       emt(mtflags);
+                       local_irq_restore(irqflags);
+#endif /* CONFIG_MIPS_MT_SMTC */
                        preempt_enable();
                        break;
                }
index d2afbd19a9c8a0c013b4170008d55a18d701e61c..0b1b54acee9ffeb538a6667da285ee6c82a54777 100644 (file)
 
        PTR_ADDIU       t0, $28, _THREAD_SIZE - 32
        set_saved_sp    t0, t1, t2
-
+#ifdef CONFIG_MIPS_MT_SMTC
+       /* Read-modify-writes of Status must be atomic on a VPE */
+       mfc0    t2, CP0_TCSTATUS
+       ori     t1, t2, TCSTATUS_IXMT
+       mtc0    t1, CP0_TCSTATUS
+       andi    t2, t2, TCSTATUS_IXMT
+       ehb
+       DMT     8                               # dmt   t0
+       move    t1,ra
+       jal     mips_ihb
+       move    ra,t1
+#endif /* CONFIG_MIPS_MT_SMTC */
        mfc0    t1, CP0_STATUS          /* Do we really need this? */
        li      a3, 0xff01
        and     t1, a3
        and     a2, a3
        or      a2, t1
        mtc0    a2, CP0_STATUS
+#ifdef CONFIG_MIPS_MT_SMTC
+       ehb
+       andi    t0, t0, VPECONTROL_TE
+       beqz    t0, 1f
+       emt
+1:
+       mfc0    t1, CP0_TCSTATUS
+       xori    t1, t1, TCSTATUS_IXMT
+       or      t1, t1, t2
+       mtc0    t1, CP0_TCSTATUS
+       ehb
+#endif /* CONFIG_MIPS_MT_SMTC */
        move    v0, a0
        jr      ra
        END(resume)
@@ -131,10 +154,19 @@ LEAF(_restore_fp)
 #define FPU_DEFAULT  0x00000000
 
 LEAF(_init_fpu)
+#ifdef CONFIG_MIPS_MT_SMTC
+       /* Rather than manipulate per-VPE Status, set per-TC bit in TCStatus */
+       mfc0    t0, CP0_TCSTATUS
+       /* Bit position is the same for Status, TCStatus */
+       li      t1, ST0_CU1
+       or      t0, t1
+       mtc0    t0, CP0_TCSTATUS
+#else /* Normal MIPS CU1 enable */
        mfc0    t0, CP0_STATUS
        li      t1, ST0_CU1
        or      t0, t1
        mtc0    t0, CP0_STATUS
+#endif /* CONFIG_MIPS_MT_SMTC */
        fpu_enable_hazard
 
        li      t1, FPU_DEFAULT
index 986a9cf230673010e6f9ae678798d74de0a51474..6179805af9f06954a26786273634aedd2b67277d 100644 (file)
 #include <linux/module.h>
 #include <linux/fs.h>
 #include <linux/init.h>
+#include <asm/uaccess.h>
+#include <linux/slab.h>
+#include <linux/list.h>
+#include <linux/vmalloc.h>
+#include <linux/elf.h>
+#include <linux/seq_file.h>
+#include <linux/syscalls.h>
+#include <linux/moduleloader.h>
 #include <linux/interrupt.h>
-#include <linux/irq.h>
 #include <linux/poll.h>
 #include <linux/sched.h>
 #include <linux/wait.h>
-
 #include <asm/mipsmtregs.h>
-#include <asm/bitops.h>
+#include <asm/cacheflush.h>
+#include <asm/atomic.h>
 #include <asm/cpu.h>
 #include <asm/processor.h>
+#include <asm/system.h>
+#include <asm/vpe.h>
 #include <asm/rtlx.h>
-#include <asm/uaccess.h>
 
 #define RTLX_TARG_VPE 1
 
 static struct rtlx_info *rtlx;
 static int major;
 static char module_name[] = "rtlx";
-static struct irqaction irq;
-static int irq_num;
-
-static inline int spacefree(int read, int write, int size)
-{
-       if (read == write) {
-               /*
-                * never fill the buffer completely, so indexes are always
-                * equal if empty and only empty, or !equal if data available
-                */
-               return size - 1;
-       }
-
-       return ((read + size - write) % size) - 1;
-}
 
 static struct chan_waitqueues {
        wait_queue_head_t rt_queue;
        wait_queue_head_t lx_queue;
+       int in_open;
 } channel_wqs[RTLX_CHANNELS];
 
+static struct irqaction irq;
+static int irq_num;
+static struct vpe_notifications notify;
+static int sp_stopping = 0;
+
 extern void *vpe_get_shared(int index);
 
 static void rtlx_dispatch(struct pt_regs *regs)
@@ -67,174 +66,298 @@ static void rtlx_dispatch(struct pt_regs *regs)
        do_IRQ(MIPSCPU_INT_BASE + MIPS_CPU_RTLX_IRQ, regs);
 }
 
+
+/* Interrupt handler may be called before rtlx_init has otherwise had
+   a chance to run.
+*/
 static irqreturn_t rtlx_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
        int i;
 
        for (i = 0; i < RTLX_CHANNELS; i++) {
-               struct rtlx_channel *chan = &rtlx->channel[i];
-
-               if (chan->lx_read != chan->lx_write)
-                       wake_up_interruptible(&channel_wqs[i].lx_queue);
+                       wake_up(&channel_wqs[i].lx_queue);
+                       wake_up(&channel_wqs[i].rt_queue);
        }
 
        return IRQ_HANDLED;
 }
 
-/* call when we have the address of the shared structure from the SP side. */
-static int rtlx_init(struct rtlx_info *rtlxi)
+static __attribute_used__ void dump_rtlx(void)
 {
        int i;
 
-       if (rtlxi->id != RTLX_ID) {
-               printk(KERN_WARNING "no valid RTLX id at 0x%p\n", rtlxi);
-               return -ENOEXEC;
-       }
+       printk("id 0x%lx state %d\n", rtlx->id, rtlx->state);
 
-       /* initialise the wait queues */
        for (i = 0; i < RTLX_CHANNELS; i++) {
-               init_waitqueue_head(&channel_wqs[i].rt_queue);
-               init_waitqueue_head(&channel_wqs[i].lx_queue);
-       }
+               struct rtlx_channel *chan = &rtlx->channel[i];
 
-       /* set up for interrupt handling */
-       memset(&irq, 0, sizeof(struct irqaction));
+               printk(" rt_state %d lx_state %d buffer_size %d\n",
+                      chan->rt_state, chan->lx_state, chan->buffer_size);
 
-       if (cpu_has_vint)
-               set_vi_handler(MIPS_CPU_RTLX_IRQ, rtlx_dispatch);
+               printk(" rt_read %d rt_write %d\n",
+                      chan->rt_read, chan->rt_write);
 
-       irq_num = MIPSCPU_INT_BASE + MIPS_CPU_RTLX_IRQ;
-       irq.handler = rtlx_interrupt;
-       irq.flags = SA_INTERRUPT;
-       irq.name = "RTLX";
-       irq.dev_id = rtlx;
-       setup_irq(irq_num, &irq);
+               printk(" lx_read %d lx_write %d\n",
+                      chan->lx_read, chan->lx_write);
+
+               printk(" rt_buffer <%s>\n", chan->rt_buffer);
+               printk(" lx_buffer <%s>\n", chan->lx_buffer);
+       }
+}
+
+/* call when we have the address of the shared structure from the SP side. */
+static int rtlx_init(struct rtlx_info *rtlxi)
+{
+       if (rtlxi->id != RTLX_ID) {
+               printk(KERN_ERR "no valid RTLX id at 0x%p 0x%x\n", rtlxi, rtlxi->id);
+               return -ENOEXEC;
+       }
 
        rtlx = rtlxi;
 
        return 0;
 }
 
-/* only allow one open process at a time to open each channel */
-static int rtlx_open(struct inode *inode, struct file *filp)
+/* notifications */
+static void starting(int vpe)
 {
-       int minor, ret;
+       int i;
+       sp_stopping = 0;
+
+       /* force a reload of rtlx */
+       rtlx=NULL;
+
+       /* wake up any sleeping rtlx_open's */
+       for (i = 0; i < RTLX_CHANNELS; i++)
+               wake_up_interruptible(&channel_wqs[i].lx_queue);
+}
+
+static void stopping(int vpe)
+{
+       int i;
+
+       sp_stopping = 1;
+       for (i = 0; i < RTLX_CHANNELS; i++)
+               wake_up_interruptible(&channel_wqs[i].lx_queue);
+}
+
+
+int rtlx_open(int index, int can_sleep)
+{
+       int ret;
        struct rtlx_channel *chan;
+       volatile struct rtlx_info **p;
 
-       /* assume only 1 device at the mo. */
-       minor = MINOR(inode->i_rdev);
+       if (index >= RTLX_CHANNELS) {
+               printk(KERN_DEBUG "rtlx_open index out of range\n");
+               return -ENOSYS;
+       }
+
+       if (channel_wqs[index].in_open) {
+               printk(KERN_DEBUG "rtlx_open channel %d already opened\n", index);
+               return -EBUSY;
+       }
+
+       channel_wqs[index].in_open++;
 
        if (rtlx == NULL) {
-               struct rtlx_info **p;
                if( (p = vpe_get_shared(RTLX_TARG_VPE)) == NULL) {
-                       printk(KERN_ERR "vpe_get_shared is NULL. "
-                              "Has an SP program been loaded?\n");
-                       return -EFAULT;
+                       if (can_sleep) {
+                               DECLARE_WAITQUEUE(wait, current);
+
+                               /* go to sleep */
+                               add_wait_queue(&channel_wqs[index].lx_queue, &wait);
+
+                               set_current_state(TASK_INTERRUPTIBLE);
+                               while ((p = vpe_get_shared(RTLX_TARG_VPE)) == NULL) {
+                                       schedule();
+                                       set_current_state(TASK_INTERRUPTIBLE);
+                               }
+
+                               set_current_state(TASK_RUNNING);
+                               remove_wait_queue(&channel_wqs[index].lx_queue, &wait);
+
+                               /* back running */
+                       } else {
+                               printk( KERN_DEBUG "No SP program loaded, and device "
+                                       "opened with O_NONBLOCK\n");
+                               channel_wqs[index].in_open = 0;
+                               return -ENOSYS;
+                       }
                }
 
                if (*p == NULL) {
-                       printk(KERN_ERR "vpe_shared %p %p\n", p, *p);
-                       return -EFAULT;
+                       if (can_sleep) {
+                               DECLARE_WAITQUEUE(wait, current);
+
+                               /* go to sleep */
+                               add_wait_queue(&channel_wqs[index].lx_queue, &wait);
+
+                               set_current_state(TASK_INTERRUPTIBLE);
+                               while (*p == NULL) {
+                                       schedule();
+
+                                       /* reset task state to interruptable otherwise
+                                          we'll whizz round here like a very fast loopy
+                                          thing. schedule() appears to return with state
+                                          set to TASK_RUNNING.
+
+                                          If the loaded SP program, for whatever reason,
+                                          doesn't set up the shared structure *p will never
+                                          become true. So whoever connected to either /dev/rt?
+                                          or if it was kspd, will then take up rather a lot of
+                                          processor cycles.
+                                       */
+
+                                       set_current_state(TASK_INTERRUPTIBLE);
+                               }
+
+                               set_current_state(TASK_RUNNING);
+                               remove_wait_queue(&channel_wqs[index].lx_queue, &wait);
+
+                               /* back running */
+                       }
+                       else {
+                               printk(" *vpe_get_shared is NULL. "
+                                      "Has an SP program been loaded?\n");
+                               channel_wqs[index].in_open = 0;
+                               return -ENOSYS;
+                       }
+               }
+
+               if ((unsigned int)*p < KSEG0) {
+                       printk(KERN_WARNING "vpe_get_shared returned an invalid pointer "
+                              "maybe an error code %d\n", (int)*p);
+                       channel_wqs[index].in_open = 0;
+                       return -ENOSYS;
                }
 
-               if ((ret = rtlx_init(*p)) < 0)
-                       return ret;
+               if ((ret = rtlx_init(*p)) < 0) {
+                       channel_wqs[index].in_open = 0;
+                       return ret;
+               }
        }
 
-       chan = &rtlx->channel[minor];
+       chan = &rtlx->channel[index];
 
-       if (test_and_set_bit(RTLX_STATE_OPENED, &chan->lx_state))
-               return -EBUSY;
+       if (chan->lx_state == RTLX_STATE_OPENED) {
+               channel_wqs[index].in_open = 0;
+               return -EBUSY;
+       }
 
+       chan->lx_state = RTLX_STATE_OPENED;
+       channel_wqs[index].in_open = 0;
        return 0;
 }
 
-static int rtlx_release(struct inode *inode, struct file *filp)
+int rtlx_release(int index)
 {
-       int minor = MINOR(inode->i_rdev);
-
-       clear_bit(RTLX_STATE_OPENED, &rtlx->channel[minor].lx_state);
-       smp_mb__after_clear_bit();
-
+       rtlx->channel[index].lx_state = RTLX_STATE_UNUSED;
        return 0;
 }
 
-static unsigned int rtlx_poll(struct file *file, poll_table * wait)
+unsigned int rtlx_read_poll(int index, int can_sleep)
 {
-       int minor;
-       unsigned int mask = 0;
-       struct rtlx_channel *chan;
+       struct rtlx_channel *chan;
 
-       minor = MINOR(file->f_dentry->d_inode->i_rdev);
-       chan = &rtlx->channel[minor];
+       if (rtlx == NULL)
+               return 0;
 
-       poll_wait(file, &channel_wqs[minor].rt_queue, wait);
-       poll_wait(file, &channel_wqs[minor].lx_queue, wait);
+       chan = &rtlx->channel[index];
 
        /* data available to read? */
-       if (chan->lx_read != chan->lx_write)
-               mask |= POLLIN | POLLRDNORM;
+       if (chan->lx_read == chan->lx_write) {
+               if (can_sleep) {
+                       DECLARE_WAITQUEUE(wait, current);
 
-       /* space to write */
-       if (spacefree(chan->rt_read, chan->rt_write, chan->buffer_size))
-               mask |= POLLOUT | POLLWRNORM;
+                       /* go to sleep */
+                       add_wait_queue(&channel_wqs[index].lx_queue, &wait);
 
-       return mask;
+                       set_current_state(TASK_INTERRUPTIBLE);
+                       while (chan->lx_read == chan->lx_write) {
+                               schedule();
+
+                               set_current_state(TASK_INTERRUPTIBLE);
+
+                               if (sp_stopping) {
+                                       set_current_state(TASK_RUNNING);
+                                       remove_wait_queue(&channel_wqs[index].lx_queue, &wait);
+                                       return 0;
+                               }
+                       }
+
+                       set_current_state(TASK_RUNNING);
+                       remove_wait_queue(&channel_wqs[index].lx_queue, &wait);
+
+                       /* back running */
+               }
+               else
+                       return 0;
+       }
+
+       return (chan->lx_write + chan->buffer_size - chan->lx_read)
+              % chan->buffer_size;
 }
 
-static ssize_t rtlx_read(struct file *file, char __user * buffer, size_t count,
-                        loff_t * ppos)
+static inline int write_spacefree(int read, int write, int size)
 {
-       unsigned long failed;
-       size_t fl = 0L;
-       int minor;
-       struct rtlx_channel *lx;
-       DECLARE_WAITQUEUE(wait, current);
+       if (read == write) {
+               /*
+                * Never fill the buffer completely, so indexes are always
+                * equal if empty and only empty, or !equal if data available
+                */
+               return size - 1;
+       }
 
-       minor = MINOR(file->f_dentry->d_inode->i_rdev);
-       lx = &rtlx->channel[minor];
+       return ((read + size - write) % size) - 1;
+}
 
-       /* data available? */
-       if (lx->lx_write == lx->lx_read) {
-               if (file->f_flags & O_NONBLOCK)
-                       return 0;       /* -EAGAIN makes cat whinge */
+unsigned int rtlx_write_poll(int index)
+{
+       struct rtlx_channel *chan = &rtlx->channel[index];
+       return write_spacefree(chan->rt_read, chan->rt_write, chan->buffer_size);
+}
 
-               /* go to sleep */
-               add_wait_queue(&channel_wqs[minor].lx_queue, &wait);
-               set_current_state(TASK_INTERRUPTIBLE);
+static inline void copy_to(void *dst, void *src, size_t count, int user)
+{
+       if (user)
+               copy_to_user(dst, src, count);
+       else
+               memcpy(dst, src, count);
+}
 
-               while (lx->lx_write == lx->lx_read)
-                       schedule();
+static inline void copy_from(void *dst, void *src, size_t count, int user)
+{
+       if (user)
+               copy_from_user(dst, src, count);
+       else
+               memcpy(dst, src, count);
+}
 
-               set_current_state(TASK_RUNNING);
-               remove_wait_queue(&channel_wqs[minor].lx_queue, &wait);
+ssize_t rtlx_read(int index, void *buff, size_t count, int user)
+{
+       size_t fl = 0L;
+       struct rtlx_channel *lx;
 
-               /* back running */
-       }
+       if (rtlx == NULL)
+               return -ENOSYS;
+
+       lx = &rtlx->channel[index];
 
        /* find out how much in total */
        count = min(count,
-                   (size_t)(lx->lx_write + lx->buffer_size - lx->lx_read) % lx->buffer_size);
+                    (size_t)(lx->lx_write + lx->buffer_size - lx->lx_read)
+                    % lx->buffer_size);
 
        /* then how much from the read pointer onwards */
-       fl = min(count, (size_t)lx->buffer_size - lx->lx_read);
+       fl = min( count, (size_t)lx->buffer_size - lx->lx_read);
 
-       failed = copy_to_user (buffer, &lx->lx_buffer[lx->lx_read], fl);
-       if (failed) {
-               count = fl - failed;
-               goto out;
-       }
+       copy_to(buff, &lx->lx_buffer[lx->lx_read], fl, user);
 
        /* and if there is anything left at the beginning of the buffer */
-       if (count - fl) {
-               failed = copy_to_user (buffer + fl, lx->lx_buffer, count - fl);
-               if (failed) {
-                       count -= failed;
-                       goto out;
-               }
-       }
+       if ( count - fl )
+               copy_to (buff + fl, lx->lx_buffer, count - fl, user);
 
-out:
        /* update the index */
        lx->lx_read += count;
        lx->lx_read %= lx->buffer_size;
@@ -242,20 +365,101 @@ out:
        return count;
 }
 
-static ssize_t rtlx_write(struct file *file, const char __user * buffer,
+ssize_t rtlx_write(int index, void *buffer, size_t count, int user)
+{
+       struct rtlx_channel *rt;
+       size_t fl;
+
+       if (rtlx == NULL)
+               return(-ENOSYS);
+
+       rt = &rtlx->channel[index];
+
+       /* total number of bytes to copy */
+       count = min(count,
+                   (size_t)write_spacefree(rt->rt_read, rt->rt_write,
+                                           rt->buffer_size));
+
+       /* first bit from write pointer to the end of the buffer, or count */
+       fl = min(count, (size_t) rt->buffer_size - rt->rt_write);
+
+       copy_from (&rt->rt_buffer[rt->rt_write], buffer, fl, user);
+
+       /* if there's any left copy to the beginning of the buffer */
+       if( count - fl )
+               copy_from (rt->rt_buffer, buffer + fl, count - fl, user);
+
+       rt->rt_write += count;
+       rt->rt_write %= rt->buffer_size;
+
+       return(count);
+}
+
+
+static int file_open(struct inode *inode, struct file *filp)
+{
+       int minor = MINOR(inode->i_rdev);
+
+       return rtlx_open(minor, (filp->f_flags & O_NONBLOCK) ? 0 : 1);
+}
+
+static int file_release(struct inode *inode, struct file *filp)
+{
+       int minor;
+       minor = MINOR(inode->i_rdev);
+
+       return rtlx_release(minor);
+}
+
+static unsigned int file_poll(struct file *file, poll_table * wait)
+{
+       int minor;
+       unsigned int mask = 0;
+
+       minor = MINOR(file->f_dentry->d_inode->i_rdev);
+
+       poll_wait(file, &channel_wqs[minor].rt_queue, wait);
+       poll_wait(file, &channel_wqs[minor].lx_queue, wait);
+
+       if (rtlx == NULL)
+               return 0;
+
+       /* data available to read? */
+       if (rtlx_read_poll(minor, 0))
+               mask |= POLLIN | POLLRDNORM;
+
+       /* space to write */
+       if (rtlx_write_poll(minor))
+               mask |= POLLOUT | POLLWRNORM;
+
+       return mask;
+}
+
+static ssize_t file_read(struct file *file, char __user * buffer, size_t count,
+                        loff_t * ppos)
+{
+       int minor = MINOR(file->f_dentry->d_inode->i_rdev);
+
+       /* data available? */
+       if (!rtlx_read_poll(minor, (file->f_flags & O_NONBLOCK) ? 0 : 1)) {
+               return 0;       // -EAGAIN makes cat whinge
+       }
+
+       return rtlx_read(minor, buffer, count, 1);
+}
+
+static ssize_t file_write(struct file *file, const char __user * buffer,
                          size_t count, loff_t * ppos)
 {
-       unsigned long failed;
        int minor;
        struct rtlx_channel *rt;
-       size_t fl;
        DECLARE_WAITQUEUE(wait, current);
 
        minor = MINOR(file->f_dentry->d_inode->i_rdev);
        rt = &rtlx->channel[minor];
 
        /* any space left... */
-       if (!spacefree(rt->rt_read, rt->rt_write, rt->buffer_size)) {
+       if (!rtlx_write_poll(minor)) {
 
                if (file->f_flags & O_NONBLOCK)
                        return -EAGAIN;
@@ -263,61 +467,64 @@ static ssize_t rtlx_write(struct file *file, const char __user * buffer,
                add_wait_queue(&channel_wqs[minor].rt_queue, &wait);
                set_current_state(TASK_INTERRUPTIBLE);
 
-               while (!spacefree(rt->rt_read, rt->rt_write, rt->buffer_size))
+               while (!rtlx_write_poll(minor))
                        schedule();
 
                set_current_state(TASK_RUNNING);
                remove_wait_queue(&channel_wqs[minor].rt_queue, &wait);
        }
 
-       /* total number of bytes to copy */
-       count = min(count, (size_t)spacefree(rt->rt_read, rt->rt_write, rt->buffer_size) );
-
-       /* first bit from write pointer to the end of the buffer, or count */
-       fl = min(count, (size_t) rt->buffer_size - rt->rt_write);
-
-       failed = copy_from_user(&rt->rt_buffer[rt->rt_write], buffer, fl);
-       if (failed) {
-               count = fl - failed;
-               goto out;
-       }
-
-       /* if there's any left copy to the beginning of the buffer */
-       if (count - fl) {
-               failed = copy_from_user(rt->rt_buffer, buffer + fl, count - fl);
-               if (failed) {
-                       count -= failed;
-                       goto out;
-               }
-       }
-
-out:
-       rt->rt_write += count;
-       rt->rt_write %= rt->buffer_size;
-
-       return count;
+       return rtlx_write(minor, (void *)buffer, count, 1);
 }
 
 static struct file_operations rtlx_fops = {
-       .owner          = THIS_MODULE,
-       .open           = rtlx_open,
-       .release        = rtlx_release,
-       .write          = rtlx_write,
-       .read           = rtlx_read,
-       .poll           = rtlx_poll
+       .owner =   THIS_MODULE,
+       .open =    file_open,
+       .release = file_release,
+       .write =   file_write,
+       .read =    file_read,
+       .poll =    file_poll
 };
 
+static struct irqaction rtlx_irq = {
+       .handler        = rtlx_interrupt,
+       .flags          = SA_INTERRUPT,
+       .name           = "RTLX",
+};
+
+static int rtlx_irq_num = MIPSCPU_INT_BASE + MIPS_CPU_RTLX_IRQ;
+
 static char register_chrdev_failed[] __initdata =
        KERN_ERR "rtlx_module_init: unable to register device\n";
 
-static int __init rtlx_module_init(void)
+static int rtlx_module_init(void)
 {
+       int i;
+
        major = register_chrdev(0, module_name, &rtlx_fops);
        if (major < 0) {
                printk(register_chrdev_failed);
                return major;
        }
 
+       /* initialise the wait queues */
+       for (i = 0; i < RTLX_CHANNELS; i++) {
+               init_waitqueue_head(&channel_wqs[i].rt_queue);
+               init_waitqueue_head(&channel_wqs[i].lx_queue);
+               channel_wqs[i].in_open = 0;
+       }
+
+       /* set up notifiers */
+       notify.start = starting;
+       notify.stop = stopping;
+       vpe_notify(RTLX_TARG_VPE, &notify);
+
+       if (cpu_has_vint)
+               set_vi_handler(MIPS_CPU_RTLX_IRQ, rtlx_dispatch);
+
+       rtlx_irq.dev_id = rtlx;
+       setup_irq(rtlx_irq_num, &rtlx_irq);
+
        return 0;
 }
 
@@ -330,5 +537,5 @@ module_init(rtlx_module_init);
 module_exit(rtlx_module_exit);
 
 MODULE_DESCRIPTION("MIPS RTLX");
-MODULE_AUTHOR("Elizabeth Clarke, MIPS Technologies, Inc.");
+MODULE_AUTHOR("Elizabeth Oldham, MIPS Technologies, Inc.");
 MODULE_LICENSE("GPL");
index 2f2dc54b2e267bce6ed09d31a0d1cc8738f81491..a0ac0e5f61ad67d2d9ef9b8cb734e9db416431bd 100644 (file)
@@ -569,8 +569,19 @@ einval:    li      v0, -EINVAL
        sys     sys_tkill               2
        sys     sys_sendfile64          5
        sys     sys_futex               6
+#ifdef CONFIG_MIPS_MT_FPAFF
+       /*
+        * For FPU affinity scheduling on MIPS MT processors, we need to
+        * intercept sys_sched_xxxaffinity() calls until we get a proper hook
+        * in kernel/sched.c.  Considered only temporary we only support these
+        * hooks for the 32-bit kernel - there is no MIPS64 MT processor atm.
+        */
+       sys     mipsmt_sys_sched_setaffinity    3
+       sys     mipsmt_sys_sched_getaffinity    3
+#else
        sys     sys_sched_setaffinity   3
        sys     sys_sched_getaffinity   3       /* 4240 */
+#endif /* CONFIG_MIPS_MT_FPAFF */
        sys     sys_io_setup            2
        sys     sys_io_destroy          1
        sys     sys_io_getevents        5
@@ -634,6 +645,8 @@ einval:     li      v0, -EINVAL
        sys     sys_pselect6            6
        sys     sys_ppoll               5
        sys     sys_unshare             1
+       sys     sys_splice              4
+       sys     sys_sync_file_range     7       /* 4305 */
        .endm
 
        /* We pre-compute the number of _instruction_ bytes needed to
index 98bf25df56f39f28d0b55c9192bf33b6761a952e..9ba750887377a23ce2ce10b9374862b8e8fc7fe6 100644 (file)
@@ -460,3 +460,5 @@ sys_call_table:
        PTR     sys_pselect6                    /* 5260 */
        PTR     sys_ppoll
        PTR     sys_unshare
+       PTR     sys_splice
+       PTR     sys_sync_file_range
index 05a2c0567daedd953d3a62cb82cc54c356fc2b8b..942aca26f9c422854c58a124abfec6ee2dd514a9 100644 (file)
@@ -386,3 +386,5 @@ EXPORT(sysn32_call_table)
        PTR     sys_pselect6
        PTR     sys_ppoll                       /* 6265 */
        PTR     sys_unshare
+       PTR     sys_splice
+       PTR     sys_sync_file_range
index 19c4ca481b02c3ee1ccc6560a1748d2807959ebf..b53a9207f530a9db07d58c19b556b9d1cc379594 100644 (file)
@@ -508,4 +508,6 @@ sys_call_table:
        PTR     sys_pselect6
        PTR     sys_ppoll
        PTR     sys_unshare
+       PTR     sys_splice
+       PTR     sys32_sync_file_range           /* 4305 */
        .size   sys_call_table,.-sys_call_table
index dcbfd27071f043c82f4b14710042d4fe8df2415b..bcf1b10e518f8be4b4302e13bb3186d1e1773438 100644 (file)
@@ -529,7 +529,10 @@ void __init setup_arch(char **cmdline_p)
 
 int __init fpu_disable(char *s)
 {
-       cpu_data[0].options &= ~MIPS_CPU_FPU;
+       int i;
+
+       for (i = 0; i < NR_CPUS; i++)
+               cpu_data[i].options &= ~MIPS_CPU_FPU;
 
        return 1;
 }
similarity index 88%
rename from arch/mips/kernel/smp_mt.c
rename to arch/mips/kernel/smp-mt.c
index 993b8bf56aaf3d58f2257dc7fd68087b0301b5aa..57770902b9aeaa15542281c98611cb0e439882ca 100644 (file)
@@ -1,8 +1,4 @@
 /*
- * Copyright (C) 2004, 2005 MIPS Technologies, Inc.  All rights reserved.
- *
- *  Elizabeth Clarke (beth@mips.com)
- *
  *  This program is free software; you can distribute it and/or modify it
  *  under the terms of the GNU General Public License (Version 2) as
  *  published by the Free Software Foundation.
  *  with this program; if not, write to the Free Software Foundation, Inc.,
  *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
  *
+ * Copyright (C) 2004, 05, 06 MIPS Technologies, Inc.
+ *    Elizabeth Clarke (beth@mips.com)
+ *    Ralf Baechle (ralf@linux-mips.org)
+ * Copyright (C) 2006 Ralf Baechle (ralf@linux-mips.org)
  */
 #include <linux/kernel.h>
 #include <linux/sched.h>
@@ -24,6 +24,7 @@
 #include <linux/compiler.h>
 
 #include <asm/atomic.h>
+#include <asm/cacheflush.h>
 #include <asm/cpu.h>
 #include <asm/processor.h>
 #include <asm/system.h>
@@ -33,8 +34,8 @@
 #include <asm/time.h>
 #include <asm/mipsregs.h>
 #include <asm/mipsmtregs.h>
-#include <asm/cacheflush.h>
-#include <asm/mips-boards/maltaint.h>
+#include <asm/mips_mt.h>
+#include <asm/mips-boards/maltaint.h>  /* This is f*cking wrong */
 
 #define MIPS_CPU_IPI_RESCHED_IRQ 0
 #define MIPS_CPU_IPI_CALL_IRQ 1
@@ -66,6 +67,7 @@ void __init sanitize_tlb_entries(void)
        if (!cpu_has_mipsmt)
                return;
 
+       /* Enable VPC */
        set_c0_mvpcontrol(MVPCONTROL_VPC);
 
        back_to_back_c0_hazard();
@@ -106,12 +108,12 @@ void __init sanitize_tlb_entries(void)
 
 static void ipi_resched_dispatch (struct pt_regs *regs)
 {
-       do_IRQ(MIPS_CPU_IPI_RESCHED_IRQ, regs);
+       do_IRQ(MIPSCPU_INT_BASE + MIPS_CPU_IPI_RESCHED_IRQ, regs);
 }
 
 static void ipi_call_dispatch (struct pt_regs *regs)
 {
-       do_IRQ(MIPS_CPU_IPI_CALL_IRQ, regs);
+       do_IRQ(MIPSCPU_INT_BASE + MIPS_CPU_IPI_CALL_IRQ, regs);
 }
 
 irqreturn_t ipi_resched_interrupt(int irq, void *dev_id, struct pt_regs *regs)
@@ -148,6 +150,11 @@ void plat_smp_setup(void)
        unsigned long val;
        int i, num;
 
+#ifdef CONFIG_MIPS_MT_FPAFF
+       /* If we have an FPU, enroll ourselves in the FPU-full mask */
+       if (cpu_has_fpu)
+               cpu_set(0, mt_fpu_cpumask);
+#endif /* CONFIG_MIPS_MT_FPAFF */
        if (!cpu_has_mipsmt)
                return;
 
@@ -155,6 +162,8 @@ void plat_smp_setup(void)
        dvpe();
        dmt();
 
+       mips_mt_set_cpuoptions();
+
        /* Put MVPE's into 'configuration state' */
        set_c0_mvpcontrol(MVPCONTROL_VPC);
 
@@ -189,11 +198,13 @@ void plat_smp_setup(void)
 
                        if (i != 0) {
                                write_vpe_c0_status((read_c0_status() & ~(ST0_IM | ST0_IE | ST0_KSU)) | ST0_CU0);
-                               write_vpe_c0_cause(read_vpe_c0_cause() & ~CAUSEF_IP);
 
                                /* set config to be the same as vpe0, particularly kseg0 coherency alg */
                                write_vpe_c0_config( read_c0_config());
 
+                               /* make sure there are no software interrupts pending */
+                               write_vpe_c0_cause(read_vpe_c0_cause() & ~(C_SW1|C_SW0));
+
                                /* Propagate Config7 */
                                write_vpe_c0_config7(read_c0_config7());
                        }
@@ -233,16 +244,16 @@ void plat_smp_setup(void)
        /* We'll wait until starting the secondaries before starting MVPE */
 
        printk(KERN_INFO "Detected %i available secondary CPU(s)\n", num);
+}
 
+void __init plat_prepare_cpus(unsigned int max_cpus)
+{
        /* set up ipi interrupts */
        if (cpu_has_vint) {
                set_vi_handler (MIPS_CPU_IPI_RESCHED_IRQ, ipi_resched_dispatch);
                set_vi_handler (MIPS_CPU_IPI_CALL_IRQ, ipi_call_dispatch);
        }
-}
 
-void __init plat_prepare_cpus(unsigned int max_cpus)
-{
        cpu_ipi_resched_irq = MIPSCPU_INT_BASE + MIPS_CPU_IPI_RESCHED_IRQ;
        cpu_ipi_call_irq = MIPSCPU_INT_BASE + MIPS_CPU_IPI_CALL_IRQ;
 
@@ -287,7 +298,8 @@ void prom_boot_secondary(int cpu, struct task_struct *idle)
        /* global pointer */
        write_tc_gpr_gp((unsigned long)gp);
 
-       flush_icache_range((unsigned long)gp, (unsigned long)(gp + 1));
+       flush_icache_range((unsigned long)gp,
+                          (unsigned long)(gp + sizeof(struct thread_info)));
 
        /* finally out of configuration and into chaos */
        clear_c0_mvpcontrol(MVPCONTROL_VPC);
@@ -305,6 +317,12 @@ void prom_smp_finish(void)
 {
        write_c0_compare(read_c0_count() + (8* mips_hpt_frequency/HZ));
 
+#ifdef CONFIG_MIPS_MT_FPAFF
+       /* If we have an FPU, enroll ourselves in the FPU-full mask */
+       if (cpu_has_fpu)
+               cpu_set(smp_processor_id(), mt_fpu_cpumask);
+#endif /* CONFIG_MIPS_MT_FPAFF */
+
        local_irq_enable();
 }
 
index 78d171bfa331cbbbdd024746ba49c8e61267e846..d42f358754ad829129663f01350d7c0757f8f078 100644 (file)
 #include <asm/mmu_context.h>
 #include <asm/smp.h>
 
+#ifdef CONFIG_MIPS_MT_SMTC
+#include <asm/mipsmtregs.h>
+#endif /* CONFIG_MIPS_MT_SMTC */
+
 cpumask_t phys_cpu_present_map;                /* Bitmask of available CPUs */
 volatile cpumask_t cpu_callin_map;     /* Bitmask of started secondaries */
 cpumask_t cpu_online_map;              /* Bitmask of currently online CPUs */
@@ -85,6 +89,10 @@ asmlinkage void start_secondary(void)
 {
        unsigned int cpu;
 
+#ifdef CONFIG_MIPS_MT_SMTC
+       /* Only do cpu_probe for first TC of CPU */
+       if ((read_c0_tcbind() & TCBIND_CURTC) == 0)
+#endif /* CONFIG_MIPS_MT_SMTC */
        cpu_probe();
        cpu_report();
        per_cpu_trap_init();
@@ -179,11 +187,13 @@ int smp_call_function (void (*func) (void *info), void *info, int retry,
        if (wait)
                while (atomic_read(&data.finished) != cpus)
                        barrier();
+       call_data = NULL;
        spin_unlock(&smp_call_lock);
 
        return 0;
 }
 
+
 void smp_call_function_interrupt(void)
 {
        void (*func) (void *info) = call_data->func;
@@ -446,5 +456,3 @@ subsys_initcall(topology_init);
 
 EXPORT_SYMBOL(flush_tlb_page);
 EXPORT_SYMBOL(flush_tlb_one);
-EXPORT_SYMBOL(cpu_data);
-EXPORT_SYMBOL(synchronize_irq);
diff --git a/arch/mips/kernel/smtc-asm.S b/arch/mips/kernel/smtc-asm.S
new file mode 100644 (file)
index 0000000..c9d6519
--- /dev/null
@@ -0,0 +1,130 @@
+/*
+ * Assembly Language Functions for MIPS MT SMTC support
+ */
+
+/*
+ * This file should be built into the kernel only if CONFIG_MIPS_MT_SMTC is set. */
+
+#include <asm/regdef.h>
+#include <asm/asmmacro.h>
+#include <asm/stackframe.h>
+#include <asm/stackframe.h>
+
+/*
+ * "Software Interrupt" linkage.
+ *
+ * This is invoked when an "Interrupt" is sent from one TC to another,
+ * where the TC to be interrupted is halted, has it's Restart address
+ * and Status values saved by the "remote control" thread, then modified
+ * to cause execution to begin here, in kenel mode. This code then
+ * disguises the TC state as that of an exception and transfers
+ * control to the general exception or vectored interrupt handler.
+ */
+       .set noreorder
+
+/*
+The __smtc_ipi_vector would use k0 and k1 as temporaries and
+1) Set EXL (this is per-VPE, so this can't be done by proxy!)
+2) Restore the K/CU and IXMT bits to the pre "exception" state
+   (EXL means no interrupts and access to the kernel map).
+3) Set EPC to be the saved value of TCRestart.
+4) Jump to the exception handler entry point passed by the sender.
+
+CAN WE PROVE THAT WE WON'T DO THIS IF INTS DISABLED??
+*/
+
+/*
+ * Reviled and slandered vision: Set EXL and restore K/CU/IXMT
+ * state of pre-halt thread, then save everything and call
+ * thought some function pointer to imaginary_exception, which
+ * will parse a register value or memory message queue to
+ * deliver things like interprocessor interrupts. On return
+ * from that function, jump to the global ret_from_irq code
+ * to invoke the scheduler and return as appropriate.
+ */
+
+#define PT_PADSLOT4 (PT_R0-8)
+#define PT_PADSLOT5 (PT_R0-4)
+
+       .text
+       .align 5
+FEXPORT(__smtc_ipi_vector)
+       .set    noat
+       /* Disable thread scheduling to make Status update atomic */
+       DMT     27                                      # dmt   k1
+       ehb
+       /* Set EXL */
+       mfc0    k0,CP0_STATUS
+       ori     k0,k0,ST0_EXL
+       mtc0    k0,CP0_STATUS
+       ehb
+       /* Thread scheduling now inhibited by EXL. Restore TE state. */
+       andi    k1,k1,VPECONTROL_TE
+       beqz    k1,1f
+       emt
+1:
+       /*
+        * The IPI sender has put some information on the anticipated
+        * kernel stack frame.  If we were in user mode, this will be
+        * built above the saved kernel SP.  If we were already in the
+        * kernel, it will be built above the current CPU SP.
+        *
+        * Were we in kernel mode, as indicated by CU0?
+        */
+       sll     k1,k0,3
+       .set noreorder
+       bltz    k1,2f
+       move    k1,sp
+       .set reorder
+       /*
+        * If previously in user mode, set CU0 and use kernel stack.
+        */
+       li      k1,ST0_CU0
+       or      k1,k1,k0
+       mtc0    k1,CP0_STATUS
+       ehb
+       get_saved_sp
+       /* Interrupting TC will have pre-set values in slots in the new frame */
+2:     subu    k1,k1,PT_SIZE
+       /* Load TCStatus Value */
+       lw      k0,PT_TCSTATUS(k1)
+       /* Write it to TCStatus to restore CU/KSU/IXMT state */
+       mtc0    k0,$2,1
+       ehb
+       lw      k0,PT_EPC(k1)
+       mtc0    k0,CP0_EPC
+       /* Save all will redundantly recompute the SP, but use it for now */
+       SAVE_ALL
+       CLI
+       move    a0,sp
+       /* Function to be invoked passed stack pad slot 5 */
+       lw      t0,PT_PADSLOT5(sp)
+       /* Argument from sender passed in stack pad slot 4 */
+       lw      a1,PT_PADSLOT4(sp)
+       jalr    t0
+       nop
+       j       ret_from_irq
+       nop
+
+/*
+ * Called from idle loop to provoke processing of queued IPIs
+ * First IPI message in queue passed as argument.
+ */
+
+LEAF(self_ipi)
+       /* Before anything else, block interrupts */
+       mfc0    t0,CP0_TCSTATUS
+       ori     t1,t0,TCSTATUS_IXMT
+       mtc0    t1,CP0_TCSTATUS
+       ehb
+       /* We know we're in kernel mode, so prepare stack frame */
+       subu    t1,sp,PT_SIZE
+       sw      ra,PT_EPC(t1)
+       sw      a0,PT_PADSLOT4(t1)
+       la      t2,ipi_decode
+       sw      t2,PT_PADSLOT5(t1)
+       /* Save pre-disable value of TCStatus */
+       sw      t0,PT_TCSTATUS(t1)
+       j       __smtc_ipi_vector
+       nop
+END(self_ipi)
diff --git a/arch/mips/kernel/smtc-proc.c b/arch/mips/kernel/smtc-proc.c
new file mode 100644 (file)
index 0000000..6f37099
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * /proc hooks for SMTC kernel
+ * Copyright (C) 2005 Mips Technologies, Inc
+ */
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/cpumask.h>
+#include <linux/interrupt.h>
+
+#include <asm/cpu.h>
+#include <asm/processor.h>
+#include <asm/atomic.h>
+#include <asm/system.h>
+#include <asm/hardirq.h>
+#include <asm/mmu_context.h>
+#include <asm/smp.h>
+#include <asm/mipsregs.h>
+#include <asm/cacheflush.h>
+#include <linux/proc_fs.h>
+
+#include <asm/smtc_proc.h>
+
+/*
+ * /proc diagnostic and statistics hooks
+ */
+
+/*
+ * Statistics gathered
+ */
+unsigned long selfipis[NR_CPUS];
+
+struct smtc_cpu_proc smtc_cpu_stats[NR_CPUS];
+
+static struct proc_dir_entry *smtc_stats;
+
+atomic_t smtc_fpu_recoveries;
+
+static int proc_read_smtc(char *page, char **start, off_t off,
+                          int count, int *eof, void *data)
+{
+       int totalen = 0;
+       int len;
+       int i;
+       extern unsigned long ebase;
+
+       len = sprintf(page, "SMTC Status Word: 0x%08x\n", smtc_status);
+       totalen += len;
+       page += len;
+       len = sprintf(page, "Config7: 0x%08x\n", read_c0_config7());
+       totalen += len;
+       page += len;
+       len = sprintf(page, "EBASE: 0x%08lx\n", ebase);
+       totalen += len;
+       page += len;
+       len = sprintf(page, "Counter Interrupts taken per CPU (TC)\n");
+       totalen += len;
+       page += len;
+       for (i=0; i < NR_CPUS; i++) {
+               len = sprintf(page, "%d: %ld\n", i, smtc_cpu_stats[i].timerints);
+               totalen += len;
+               page += len;
+       }
+       len = sprintf(page, "Self-IPIs by CPU:\n");
+       totalen += len;
+       page += len;
+       for(i = 0; i < NR_CPUS; i++) {
+               len = sprintf(page, "%d: %ld\n", i, smtc_cpu_stats[i].selfipis);
+               totalen += len;
+               page += len;
+       }
+       len = sprintf(page, "%d Recoveries of \"stolen\" FPU\n",
+                     atomic_read(&smtc_fpu_recoveries));
+       totalen += len;
+       page += len;
+
+       return totalen;
+}
+
+void init_smtc_stats(void)
+{
+       int i;
+
+       for (i=0; i<NR_CPUS; i++) {
+               smtc_cpu_stats[i].timerints = 0;
+               smtc_cpu_stats[i].selfipis = 0;
+       }
+
+       atomic_set(&smtc_fpu_recoveries, 0);
+
+       smtc_stats = create_proc_read_entry("smtc", 0444, NULL,
+                                           proc_read_smtc, NULL);
+}
diff --git a/arch/mips/kernel/smtc.c b/arch/mips/kernel/smtc.c
new file mode 100644 (file)
index 0000000..2e8e52c
--- /dev/null
@@ -0,0 +1,1322 @@
+/* Copyright (C) 2004 Mips Technologies, Inc */
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/cpumask.h>
+#include <linux/interrupt.h>
+
+#include <asm/cpu.h>
+#include <asm/processor.h>
+#include <asm/atomic.h>
+#include <asm/system.h>
+#include <asm/hardirq.h>
+#include <asm/hazards.h>
+#include <asm/mmu_context.h>
+#include <asm/smp.h>
+#include <asm/mipsregs.h>
+#include <asm/cacheflush.h>
+#include <asm/time.h>
+#include <asm/addrspace.h>
+#include <asm/smtc.h>
+#include <asm/smtc_ipi.h>
+#include <asm/smtc_proc.h>
+
+/*
+ * This file should be built into the kernel only if CONFIG_MIPS_MT_SMTC is set.
+ */
+
+/*
+ * MIPSCPU_INT_BASE is identically defined in both
+ * asm-mips/mips-boards/maltaint.h and asm-mips/mips-boards/simint.h,
+ * but as yet there's no properly organized include structure that
+ * will ensure that the right *int.h file will be included for a
+ * given platform build.
+ */
+
+#define MIPSCPU_INT_BASE       16
+
+#define MIPS_CPU_IPI_IRQ       1
+
+#define LOCK_MT_PRA() \
+       local_irq_save(flags); \
+       mtflags = dmt()
+
+#define UNLOCK_MT_PRA() \
+       emt(mtflags); \
+       local_irq_restore(flags)
+
+#define LOCK_CORE_PRA() \
+       local_irq_save(flags); \
+       mtflags = dvpe()
+
+#define UNLOCK_CORE_PRA() \
+       evpe(mtflags); \
+       local_irq_restore(flags)
+
+/*
+ * Data structures purely associated with SMTC parallelism
+ */
+
+
+/*
+ * Table for tracking ASIDs whose lifetime is prolonged.
+ */
+
+asiduse smtc_live_asid[MAX_SMTC_TLBS][MAX_SMTC_ASIDS];
+
+/*
+ * Clock interrupt "latch" buffers, per "CPU"
+ */
+
+unsigned int ipi_timer_latch[NR_CPUS];
+
+/*
+ * Number of InterProcessor Interupt (IPI) message buffers to allocate
+ */
+
+#define IPIBUF_PER_CPU 4
+
+struct smtc_ipi_q IPIQ[NR_CPUS];
+struct smtc_ipi_q freeIPIq;
+
+
+/* Forward declarations */
+
+void ipi_decode(struct pt_regs *, struct smtc_ipi *);
+void post_direct_ipi(int cpu, struct smtc_ipi *pipi);
+void setup_cross_vpe_interrupts(void);
+void init_smtc_stats(void);
+
+/* Global SMTC Status */
+
+unsigned int smtc_status = 0;
+
+/* Boot command line configuration overrides */
+
+static int vpelimit = 0;
+static int tclimit = 0;
+static int ipibuffers = 0;
+static int nostlb = 0;
+static int asidmask = 0;
+unsigned long smtc_asid_mask = 0xff;
+
+static int __init maxvpes(char *str)
+{
+       get_option(&str, &vpelimit);
+       return 1;
+}
+
+static int __init maxtcs(char *str)
+{
+       get_option(&str, &tclimit);
+       return 1;
+}
+
+static int __init ipibufs(char *str)
+{
+       get_option(&str, &ipibuffers);
+       return 1;
+}
+
+static int __init stlb_disable(char *s)
+{
+       nostlb = 1;
+       return 1;
+}
+
+static int __init asidmask_set(char *str)
+{
+       get_option(&str, &asidmask);
+       switch(asidmask) {
+       case 0x1:
+       case 0x3:
+       case 0x7:
+       case 0xf:
+       case 0x1f:
+       case 0x3f:
+       case 0x7f:
+       case 0xff:
+               smtc_asid_mask = (unsigned long)asidmask;
+               break;
+       default:
+               printk("ILLEGAL ASID mask 0x%x from command line\n", asidmask);
+       }
+       return 1;
+}
+
+__setup("maxvpes=", maxvpes);
+__setup("maxtcs=", maxtcs);
+__setup("ipibufs=", ipibufs);
+__setup("nostlb", stlb_disable);
+__setup("asidmask=", asidmask_set);
+
+/* Enable additional debug checks before going into CPU idle loop */
+#define SMTC_IDLE_HOOK_DEBUG
+
+#ifdef SMTC_IDLE_HOOK_DEBUG
+
+static int hang_trig = 0;
+
+static int __init hangtrig_enable(char *s)
+{
+       hang_trig = 1;
+       return 1;
+}
+
+
+__setup("hangtrig", hangtrig_enable);
+
+#define DEFAULT_BLOCKED_IPI_LIMIT 32
+
+static int timerq_limit = DEFAULT_BLOCKED_IPI_LIMIT;
+
+static int __init tintq(char *str)
+{
+       get_option(&str, &timerq_limit);
+       return 1;
+}
+
+__setup("tintq=", tintq);
+
+int imstuckcount[2][8];
+/* vpemask represents IM/IE bits of per-VPE Status registers, low-to-high */
+int vpemask[2][8] = {{0,1,1,0,0,0,0,1},{0,1,0,0,0,0,0,1}};
+int tcnoprog[NR_CPUS];
+static atomic_t idle_hook_initialized = {0};
+static int clock_hang_reported[NR_CPUS];
+
+#endif /* SMTC_IDLE_HOOK_DEBUG */
+
+/* Initialize shared TLB - the should probably migrate to smtc_setup_cpus() */
+
+void __init sanitize_tlb_entries(void)
+{
+       printk("Deprecated sanitize_tlb_entries() invoked\n");
+}
+
+
+/*
+ * Configure shared TLB - VPC configuration bit must be set by caller
+ */
+
+void smtc_configure_tlb(void)
+{
+       int i,tlbsiz,vpes;
+       unsigned long mvpconf0;
+       unsigned long config1val;
+
+       /* Set up ASID preservation table */
+       for (vpes=0; vpes<MAX_SMTC_TLBS; vpes++) {
+           for(i = 0; i < MAX_SMTC_ASIDS; i++) {
+               smtc_live_asid[vpes][i] = 0;
+           }
+       }
+       mvpconf0 = read_c0_mvpconf0();
+
+       if ((vpes = ((mvpconf0 & MVPCONF0_PVPE)
+                       >> MVPCONF0_PVPE_SHIFT) + 1) > 1) {
+           /* If we have multiple VPEs, try to share the TLB */
+           if ((mvpconf0 & MVPCONF0_TLBS) && !nostlb) {
+               /*
+                * If TLB sizing is programmable, shared TLB
+                * size is the total available complement.
+                * Otherwise, we have to take the sum of all
+                * static VPE TLB entries.
+                */
+               if ((tlbsiz = ((mvpconf0 & MVPCONF0_PTLBE)
+                               >> MVPCONF0_PTLBE_SHIFT)) == 0) {
+                   /*
+                    * If there's more than one VPE, there had better
+                    * be more than one TC, because we need one to bind
+                    * to each VPE in turn to be able to read
+                    * its configuration state!
+                    */
+                   settc(1);
+                   /* Stop the TC from doing anything foolish */
+                   write_tc_c0_tchalt(TCHALT_H);
+                   mips_ihb();
+                   /* No need to un-Halt - that happens later anyway */
+                   for (i=0; i < vpes; i++) {
+                       write_tc_c0_tcbind(i);
+                       /*
+                        * To be 100% sure we're really getting the right
+                        * information, we exit the configuration state
+                        * and do an IHB after each rebinding.
+                        */
+                       write_c0_mvpcontrol(
+                               read_c0_mvpcontrol() & ~ MVPCONTROL_VPC );
+                       mips_ihb();
+                       /*
+                        * Only count if the MMU Type indicated is TLB
+                        */
+                       if(((read_vpe_c0_config() & MIPS_CONF_MT) >> 7) == 1) {
+                               config1val = read_vpe_c0_config1();
+                               tlbsiz += ((config1val >> 25) & 0x3f) + 1;
+                       }
+
+                       /* Put core back in configuration state */
+                       write_c0_mvpcontrol(
+                               read_c0_mvpcontrol() | MVPCONTROL_VPC );
+                       mips_ihb();
+                   }
+               }
+               write_c0_mvpcontrol(read_c0_mvpcontrol() | MVPCONTROL_STLB);
+
+               /*
+                * Setup kernel data structures to use software total,
+                * rather than read the per-VPE Config1 value. The values
+                * for "CPU 0" gets copied to all the other CPUs as part
+                * of their initialization in smtc_cpu_setup().
+                */
+
+               tlbsiz = tlbsiz & 0x3f; /* MIPS32 limits TLB indices to 64 */
+               cpu_data[0].tlbsize = tlbsiz;
+               smtc_status |= SMTC_TLB_SHARED;
+
+               printk("TLB of %d entry pairs shared by %d VPEs\n",
+                       tlbsiz, vpes);
+           } else {
+               printk("WARNING: TLB Not Sharable on SMTC Boot!\n");
+           }
+       }
+}
+
+
+/*
+ * Incrementally build the CPU map out of constituent MIPS MT cores,
+ * using the specified available VPEs and TCs.  Plaform code needs
+ * to ensure that each MIPS MT core invokes this routine on reset,
+ * one at a time(!).
+ *
+ * This version of the build_cpu_map and prepare_cpus routines assumes
+ * that *all* TCs of a MIPS MT core will be used for Linux, and that
+ * they will be spread across *all* available VPEs (to minimise the
+ * loss of efficiency due to exception service serialization).
+ * An improved version would pick up configuration information and
+ * possibly leave some TCs/VPEs as "slave" processors.
+ *
+ * Use c0_MVPConf0 to find out how many TCs are available, setting up
+ * phys_cpu_present_map and the logical/physical mappings.
+ */
+
+int __init mipsmt_build_cpu_map(int start_cpu_slot)
+{
+       int i, ntcs;
+
+       /*
+        * The CPU map isn't actually used for anything at this point,
+        * so it's not clear what else we should do apart from set
+        * everything up so that "logical" = "physical".
+        */
+       ntcs = ((read_c0_mvpconf0() & MVPCONF0_PTC) >> MVPCONF0_PTC_SHIFT) + 1;
+       for (i=start_cpu_slot; i<NR_CPUS && i<ntcs; i++) {
+               cpu_set(i, phys_cpu_present_map);
+               __cpu_number_map[i] = i;
+               __cpu_logical_map[i] = i;
+       }
+       /* Initialize map of CPUs with FPUs */
+       cpus_clear(mt_fpu_cpumask);
+
+       /* One of those TC's is the one booting, and not a secondary... */
+       printk("%i available secondary CPU TC(s)\n", i - 1);
+
+       return i;
+}
+
+/*
+ * Common setup before any secondaries are started
+ * Make sure all CPU's are in a sensible state before we boot any of the
+ * secondaries.
+ *
+ * For MIPS MT "SMTC" operation, we set up all TCs, spread as evenly
+ * as possible across the available VPEs.
+ */
+
+static void smtc_tc_setup(int vpe, int tc, int cpu)
+{
+       settc(tc);
+       write_tc_c0_tchalt(TCHALT_H);
+       mips_ihb();
+       write_tc_c0_tcstatus((read_tc_c0_tcstatus()
+                       & ~(TCSTATUS_TKSU | TCSTATUS_DA | TCSTATUS_IXMT))
+                       | TCSTATUS_A);
+       write_tc_c0_tccontext(0);
+       /* Bind tc to vpe */
+       write_tc_c0_tcbind(vpe);
+       /* In general, all TCs should have the same cpu_data indications */
+       memcpy(&cpu_data[cpu], &cpu_data[0], sizeof(struct cpuinfo_mips));
+       /* For 34Kf, start with TC/CPU 0 as sole owner of single FPU context */
+       if (cpu_data[0].cputype == CPU_34K)
+               cpu_data[cpu].options &= ~MIPS_CPU_FPU;
+       cpu_data[cpu].vpe_id = vpe;
+       cpu_data[cpu].tc_id = tc;
+}
+
+
+void mipsmt_prepare_cpus(void)
+{
+       int i, vpe, tc, ntc, nvpe, tcpervpe, slop, cpu;
+       unsigned long flags;
+       unsigned long val;
+       int nipi;
+       struct smtc_ipi *pipi;
+
+       /* disable interrupts so we can disable MT */
+       local_irq_save(flags);
+       /* disable MT so we can configure */
+       dvpe();
+       dmt();
+
+       freeIPIq.lock = SPIN_LOCK_UNLOCKED;
+
+       /*
+        * We probably don't have as many VPEs as we do SMP "CPUs",
+        * but it's possible - and in any case we'll never use more!
+        */
+       for (i=0; i<NR_CPUS; i++) {
+               IPIQ[i].head = IPIQ[i].tail = NULL;
+               IPIQ[i].lock = SPIN_LOCK_UNLOCKED;
+               IPIQ[i].depth = 0;
+               ipi_timer_latch[i] = 0;
+       }
+
+       /* cpu_data index starts at zero */
+       cpu = 0;
+       cpu_data[cpu].vpe_id = 0;
+       cpu_data[cpu].tc_id = 0;
+       cpu++;
+
+       /* Report on boot-time options */
+       mips_mt_set_cpuoptions ();
+       if (vpelimit > 0)
+               printk("Limit of %d VPEs set\n", vpelimit);
+       if (tclimit > 0)
+               printk("Limit of %d TCs set\n", tclimit);
+       if (nostlb) {
+               printk("Shared TLB Use Inhibited - UNSAFE for Multi-VPE Operation\n");
+       }
+       if (asidmask)
+               printk("ASID mask value override to 0x%x\n", asidmask);
+
+       /* Temporary */
+#ifdef SMTC_IDLE_HOOK_DEBUG
+       if (hang_trig)
+               printk("Logic Analyser Trigger on suspected TC hang\n");
+#endif /* SMTC_IDLE_HOOK_DEBUG */
+
+       /* Put MVPE's into 'configuration state' */
+       write_c0_mvpcontrol( read_c0_mvpcontrol() | MVPCONTROL_VPC );
+
+       val = read_c0_mvpconf0();
+       nvpe = ((val & MVPCONF0_PVPE) >> MVPCONF0_PVPE_SHIFT) + 1;
+       if (vpelimit > 0 && nvpe > vpelimit)
+               nvpe = vpelimit;
+       ntc = ((val & MVPCONF0_PTC) >> MVPCONF0_PTC_SHIFT) + 1;
+       if (ntc > NR_CPUS)
+               ntc = NR_CPUS;
+       if (tclimit > 0 && ntc > tclimit)
+               ntc = tclimit;
+       tcpervpe = ntc / nvpe;
+       slop = ntc % nvpe;      /* Residual TCs, < NVPE */
+
+       /* Set up shared TLB */
+       smtc_configure_tlb();
+
+       for (tc = 0, vpe = 0 ; (vpe < nvpe) && (tc < ntc) ; vpe++) {
+               /*
+                * Set the MVP bits.
+                */
+               settc(tc);
+               write_vpe_c0_vpeconf0(read_vpe_c0_vpeconf0() | VPECONF0_MVP);
+               if (vpe != 0)
+                       printk(", ");
+               printk("VPE %d: TC", vpe);
+               for (i = 0; i < tcpervpe; i++) {
+                       /*
+                        * TC 0 is bound to VPE 0 at reset,
+                        * and is presumably executing this
+                        * code.  Leave it alone!
+                        */
+                       if (tc != 0) {
+                               smtc_tc_setup(vpe,tc, cpu);
+                               cpu++;
+                       }
+                       printk(" %d", tc);
+                       tc++;
+               }
+               if (slop) {
+                       if (tc != 0) {
+                               smtc_tc_setup(vpe,tc, cpu);
+                               cpu++;
+                       }
+                       printk(" %d", tc);
+                       tc++;
+                       slop--;
+               }
+               if (vpe != 0) {
+                       /*
+                        * Clear any stale software interrupts from VPE's Cause
+                        */
+                       write_vpe_c0_cause(0);
+
+                       /*
+                        * Clear ERL/EXL of VPEs other than 0
+                        * and set restricted interrupt enable/mask.
+                        */
+                       write_vpe_c0_status((read_vpe_c0_status()
+                               & ~(ST0_BEV | ST0_ERL | ST0_EXL | ST0_IM))
+                               | (STATUSF_IP0 | STATUSF_IP1 | STATUSF_IP7
+                               | ST0_IE));
+                       /*
+                        * set config to be the same as vpe0,
+                        *  particularly kseg0 coherency alg
+                        */
+                       write_vpe_c0_config(read_c0_config());
+                       /* Clear any pending timer interrupt */
+                       write_vpe_c0_compare(0);
+                       /* Propagate Config7 */
+                       write_vpe_c0_config7(read_c0_config7());
+               }
+               /* enable multi-threading within VPE */
+               write_vpe_c0_vpecontrol(read_vpe_c0_vpecontrol() | VPECONTROL_TE);
+               /* enable the VPE */
+               write_vpe_c0_vpeconf0(read_vpe_c0_vpeconf0() | VPECONF0_VPA);
+       }
+
+       /*
+        * Pull any physically present but unused TCs out of circulation.
+        */
+       while (tc < (((val & MVPCONF0_PTC) >> MVPCONF0_PTC_SHIFT) + 1)) {
+               cpu_clear(tc, phys_cpu_present_map);
+               cpu_clear(tc, cpu_present_map);
+               tc++;
+       }
+
+       /* release config state */
+       write_c0_mvpcontrol( read_c0_mvpcontrol() & ~ MVPCONTROL_VPC );
+
+       printk("\n");
+
+       /* Set up coprocessor affinity CPU mask(s) */
+
+       for (tc = 0; tc < ntc; tc++) {
+               if(cpu_data[tc].options & MIPS_CPU_FPU)
+                       cpu_set(tc, mt_fpu_cpumask);
+       }
+
+       /* set up ipi interrupts... */
+
+       /* If we have multiple VPEs running, set up the cross-VPE interrupt */
+
+       if (nvpe > 1)
+               setup_cross_vpe_interrupts();
+
+       /* Set up queue of free IPI "messages". */
+       nipi = NR_CPUS * IPIBUF_PER_CPU;
+       if (ipibuffers > 0)
+               nipi = ipibuffers;
+
+       pipi = kmalloc(nipi *sizeof(struct smtc_ipi), GFP_KERNEL);
+       if (pipi == NULL)
+               panic("kmalloc of IPI message buffers failed\n");
+       else
+               printk("IPI buffer pool of %d buffers\n", nipi);
+       for (i = 0; i < nipi; i++) {
+               smtc_ipi_nq(&freeIPIq, pipi);
+               pipi++;
+       }
+
+       /* Arm multithreading and enable other VPEs - but all TCs are Halted */
+       emt(EMT_ENABLE);
+       evpe(EVPE_ENABLE);
+       local_irq_restore(flags);
+       /* Initialize SMTC /proc statistics/diagnostics */
+       init_smtc_stats();
+}
+
+
+/*
+ * Setup the PC, SP, and GP of a secondary processor and start it
+ * running!
+ * smp_bootstrap is the place to resume from
+ * __KSTK_TOS(idle) is apparently the stack pointer
+ * (unsigned long)idle->thread_info the gp
+ *
+ */
+void smtc_boot_secondary(int cpu, struct task_struct *idle)
+{
+       extern u32 kernelsp[NR_CPUS];
+       long flags;
+       int mtflags;
+
+       LOCK_MT_PRA();
+       if (cpu_data[cpu].vpe_id != cpu_data[smp_processor_id()].vpe_id) {
+               dvpe();
+       }
+       settc(cpu_data[cpu].tc_id);
+
+       /* pc */
+       write_tc_c0_tcrestart((unsigned long)&smp_bootstrap);
+
+       /* stack pointer */
+       kernelsp[cpu] = __KSTK_TOS(idle);
+       write_tc_gpr_sp(__KSTK_TOS(idle));
+
+       /* global pointer */
+       write_tc_gpr_gp((unsigned long)idle->thread_info);
+
+       smtc_status |= SMTC_MTC_ACTIVE;
+       write_tc_c0_tchalt(0);
+       if (cpu_data[cpu].vpe_id != cpu_data[smp_processor_id()].vpe_id) {
+               evpe(EVPE_ENABLE);
+       }
+       UNLOCK_MT_PRA();
+}
+
+void smtc_init_secondary(void)
+{
+       /*
+        * Start timer on secondary VPEs if necessary.
+        * mips_timer_setup should already have been invoked by init/main
+        * on "boot" TC.  Like per_cpu_trap_init() hack, this assumes that
+        * SMTC init code assigns TCs consdecutively and in ascending order
+        * to across available VPEs.
+        */
+       if(((read_c0_tcbind() & TCBIND_CURTC) != 0)
+       && ((read_c0_tcbind() & TCBIND_CURVPE)
+           != cpu_data[smp_processor_id() - 1].vpe_id)){
+               write_c0_compare (read_c0_count() + mips_hpt_frequency/HZ);
+       }
+
+       local_irq_enable();
+}
+
+void smtc_smp_finish(void)
+{
+       printk("TC %d going on-line as CPU %d\n",
+               cpu_data[smp_processor_id()].tc_id, smp_processor_id());
+}
+
+void smtc_cpus_done(void)
+{
+}
+
+/*
+ * Support for SMTC-optimized driver IRQ registration
+ */
+
+/*
+ * SMTC Kernel needs to manipulate low-level CPU interrupt mask
+ * in do_IRQ. These are passed in setup_irq_smtc() and stored
+ * in this table.
+ */
+
+int setup_irq_smtc(unsigned int irq, struct irqaction * new,
+                       unsigned long hwmask)
+{
+       irq_hwmask[irq] = hwmask;
+
+       return setup_irq(irq, new);
+}
+
+/*
+ * IPI model for SMTC is tricky, because interrupts aren't TC-specific.
+ * Within a VPE one TC can interrupt another by different approaches.
+ * The easiest to get right would probably be to make all TCs except
+ * the target IXMT and set a software interrupt, but an IXMT-based
+ * scheme requires that a handler must run before a new IPI could
+ * be sent, which would break the "broadcast" loops in MIPS MT.
+ * A more gonzo approach within a VPE is to halt the TC, extract
+ * its Restart, Status, and a couple of GPRs, and program the Restart
+ * address to emulate an interrupt.
+ *
+ * Within a VPE, one can be confident that the target TC isn't in
+ * a critical EXL state when halted, since the write to the Halt
+ * register could not have issued on the writing thread if the
+ * halting thread had EXL set. So k0 and k1 of the target TC
+ * can be used by the injection code.  Across VPEs, one can't
+ * be certain that the target TC isn't in a critical exception
+ * state. So we try a two-step process of sending a software
+ * interrupt to the target VPE, which either handles the event
+ * itself (if it was the target) or injects the event within
+ * the VPE.
+ */
+
+void smtc_ipi_qdump(void)
+{
+       int i;
+
+       for (i = 0; i < NR_CPUS ;i++) {
+               printk("IPIQ[%d]: head = 0x%x, tail = 0x%x, depth = %d\n",
+                       i, (unsigned)IPIQ[i].head, (unsigned)IPIQ[i].tail,
+                       IPIQ[i].depth);
+       }
+}
+
+/*
+ * The standard atomic.h primitives don't quite do what we want
+ * here: We need an atomic add-and-return-previous-value (which
+ * could be done with atomic_add_return and a decrement) and an
+ * atomic set/zero-and-return-previous-value (which can't really
+ * be done with the atomic.h primitives). And since this is
+ * MIPS MT, we can assume that we have LL/SC.
+ */
+static __inline__ int atomic_postincrement(unsigned int *pv)
+{
+       unsigned long result;
+
+       unsigned long temp;
+
+       __asm__ __volatile__(
+       "1:     ll      %0, %2                                  \n"
+       "       addu    %1, %0, 1                               \n"
+       "       sc      %1, %2                                  \n"
+       "       beqz    %1, 1b                                  \n"
+       "       sync                                            \n"
+       : "=&r" (result), "=&r" (temp), "=m" (*pv)
+       : "m" (*pv)
+       : "memory");
+
+       return result;
+}
+
+/* No longer used in IPI dispatch, but retained for future recycling */
+
+static __inline__ int atomic_postclear(unsigned int *pv)
+{
+       unsigned long result;
+
+       unsigned long temp;
+
+       __asm__ __volatile__(
+       "1:     ll      %0, %2                                  \n"
+       "       or      %1, $0, $0                              \n"
+       "       sc      %1, %2                                  \n"
+       "       beqz    %1, 1b                                  \n"
+       "       sync                                            \n"
+       : "=&r" (result), "=&r" (temp), "=m" (*pv)
+       : "m" (*pv)
+       : "memory");
+
+       return result;
+}
+
+
+void smtc_send_ipi(int cpu, int type, unsigned int action)
+{
+       int tcstatus;
+       struct smtc_ipi *pipi;
+       long flags;
+       int mtflags;
+
+       if (cpu == smp_processor_id()) {
+               printk("Cannot Send IPI to self!\n");
+               return;
+       }
+       /* Set up a descriptor, to be delivered either promptly or queued */
+       pipi = smtc_ipi_dq(&freeIPIq);
+       if (pipi == NULL) {
+               bust_spinlocks(1);
+               mips_mt_regdump(dvpe());
+               panic("IPI Msg. Buffers Depleted\n");
+       }
+       pipi->type = type;
+       pipi->arg = (void *)action;
+       pipi->dest = cpu;
+       if (cpu_data[cpu].vpe_id != cpu_data[smp_processor_id()].vpe_id) {
+               /* If not on same VPE, enqueue and send cross-VPE interupt */
+               smtc_ipi_nq(&IPIQ[cpu], pipi);
+               LOCK_CORE_PRA();
+               settc(cpu_data[cpu].tc_id);
+               write_vpe_c0_cause(read_vpe_c0_cause() | C_SW1);
+               UNLOCK_CORE_PRA();
+       } else {
+               /*
+                * Not sufficient to do a LOCK_MT_PRA (dmt) here,
+                * since ASID shootdown on the other VPE may
+                * collide with this operation.
+                */
+               LOCK_CORE_PRA();
+               settc(cpu_data[cpu].tc_id);
+               /* Halt the targeted TC */
+               write_tc_c0_tchalt(TCHALT_H);
+               mips_ihb();
+
+               /*
+                * Inspect TCStatus - if IXMT is set, we have to queue
+                * a message. Otherwise, we set up the "interrupt"
+                * of the other TC
+                */
+               tcstatus = read_tc_c0_tcstatus();
+
+               if ((tcstatus & TCSTATUS_IXMT) != 0) {
+                       /*
+                        * Spin-waiting here can deadlock,
+                        * so we queue the message for the target TC.
+                        */
+                       write_tc_c0_tchalt(0);
+                       UNLOCK_CORE_PRA();
+                       /* Try to reduce redundant timer interrupt messages */
+                       if(type == SMTC_CLOCK_TICK) {
+                           if(atomic_postincrement(&ipi_timer_latch[cpu])!=0) {
+                               smtc_ipi_nq(&freeIPIq, pipi);
+                               return;
+                           }
+                       }
+                       smtc_ipi_nq(&IPIQ[cpu], pipi);
+               } else {
+                       post_direct_ipi(cpu, pipi);
+                       write_tc_c0_tchalt(0);
+                       UNLOCK_CORE_PRA();
+               }
+       }
+}
+
+/*
+ * Send IPI message to Halted TC, TargTC/TargVPE already having been set
+ */
+void post_direct_ipi(int cpu, struct smtc_ipi *pipi)
+{
+       struct pt_regs *kstack;
+       unsigned long tcstatus;
+       unsigned long tcrestart;
+       extern u32 kernelsp[NR_CPUS];
+       extern void __smtc_ipi_vector(void);
+
+       /* Extract Status, EPC from halted TC */
+       tcstatus = read_tc_c0_tcstatus();
+       tcrestart = read_tc_c0_tcrestart();
+       /* If TCRestart indicates a WAIT instruction, advance the PC */
+       if ((tcrestart & 0x80000000)
+           && ((*(unsigned int *)tcrestart & 0xfe00003f) == 0x42000020)) {
+               tcrestart += 4;
+       }
+       /*
+        * Save on TC's future kernel stack
+        *
+        * CU bit of Status is indicator that TC was
+        * already running on a kernel stack...
+        */
+       if(tcstatus & ST0_CU0)  {
+               /* Note that this "- 1" is pointer arithmetic */
+               kstack = ((struct pt_regs *)read_tc_gpr_sp()) - 1;
+       } else {
+               kstack = ((struct pt_regs *)kernelsp[cpu]) - 1;
+       }
+
+       kstack->cp0_epc = (long)tcrestart;
+       /* Save TCStatus */
+       kstack->cp0_tcstatus = tcstatus;
+       /* Pass token of operation to be performed kernel stack pad area */
+       kstack->pad0[4] = (unsigned long)pipi;
+       /* Pass address of function to be called likewise */
+       kstack->pad0[5] = (unsigned long)&ipi_decode;
+       /* Set interrupt exempt and kernel mode */
+       tcstatus |= TCSTATUS_IXMT;
+       tcstatus &= ~TCSTATUS_TKSU;
+       write_tc_c0_tcstatus(tcstatus);
+       ehb();
+       /* Set TC Restart address to be SMTC IPI vector */
+       write_tc_c0_tcrestart(__smtc_ipi_vector);
+}
+
+void ipi_resched_interrupt(struct pt_regs *regs)
+{
+       /* Return from interrupt should be enough to cause scheduler check */
+}
+
+
+void ipi_call_interrupt(struct pt_regs *regs)
+{
+       /* Invoke generic function invocation code in smp.c */
+       smp_call_function_interrupt();
+}
+
+void ipi_decode(struct pt_regs *regs, struct smtc_ipi *pipi)
+{
+       void *arg_copy = pipi->arg;
+       int type_copy = pipi->type;
+       int dest_copy = pipi->dest;
+
+       smtc_ipi_nq(&freeIPIq, pipi);
+       switch (type_copy) {
+               case SMTC_CLOCK_TICK:
+                       /* Invoke Clock "Interrupt" */
+                       ipi_timer_latch[dest_copy] = 0;
+#ifdef SMTC_IDLE_HOOK_DEBUG
+                       clock_hang_reported[dest_copy] = 0;
+#endif /* SMTC_IDLE_HOOK_DEBUG */
+                       local_timer_interrupt(0, NULL, regs);
+                       break;
+               case LINUX_SMP_IPI:
+                       switch ((int)arg_copy) {
+                       case SMP_RESCHEDULE_YOURSELF:
+                               ipi_resched_interrupt(regs);
+                               break;
+                       case SMP_CALL_FUNCTION:
+                               ipi_call_interrupt(regs);
+                               break;
+                       default:
+                               printk("Impossible SMTC IPI Argument 0x%x\n",
+                                       (int)arg_copy);
+                               break;
+                       }
+                       break;
+               default:
+                       printk("Impossible SMTC IPI Type 0x%x\n", type_copy);
+                       break;
+       }
+}
+
+void deferred_smtc_ipi(struct pt_regs *regs)
+{
+       struct smtc_ipi *pipi;
+       unsigned long flags;
+/* DEBUG */
+       int q = smp_processor_id();
+
+       /*
+        * Test is not atomic, but much faster than a dequeue,
+        * and the vast majority of invocations will have a null queue.
+        */
+       if(IPIQ[q].head != NULL) {
+               while((pipi = smtc_ipi_dq(&IPIQ[q])) != NULL) {
+                       /* ipi_decode() should be called with interrupts off */
+                       local_irq_save(flags);
+                       ipi_decode(regs, pipi);
+                       local_irq_restore(flags);
+               }
+       }
+}
+
+/*
+ * Send clock tick to all TCs except the one executing the funtion
+ */
+
+void smtc_timer_broadcast(int vpe)
+{
+       int cpu;
+       int myTC = cpu_data[smp_processor_id()].tc_id;
+       int myVPE = cpu_data[smp_processor_id()].vpe_id;
+
+       smtc_cpu_stats[smp_processor_id()].timerints++;
+
+       for_each_online_cpu(cpu) {
+               if (cpu_data[cpu].vpe_id == myVPE &&
+                   cpu_data[cpu].tc_id != myTC)
+                       smtc_send_ipi(cpu, SMTC_CLOCK_TICK, 0);
+       }
+}
+
+/*
+ * Cross-VPE interrupts in the SMTC prototype use "software interrupts"
+ * set via cross-VPE MTTR manipulation of the Cause register. It would be
+ * in some regards preferable to have external logic for "doorbell" hardware
+ * interrupts.
+ */
+
+static int cpu_ipi_irq = MIPSCPU_INT_BASE + MIPS_CPU_IPI_IRQ;
+
+static irqreturn_t ipi_interrupt(int irq, void *dev_idm, struct pt_regs *regs)
+{
+       int my_vpe = cpu_data[smp_processor_id()].vpe_id;
+       int my_tc = cpu_data[smp_processor_id()].tc_id;
+       int cpu;
+       struct smtc_ipi *pipi;
+       unsigned long tcstatus;
+       int sent;
+       long flags;
+       unsigned int mtflags;
+       unsigned int vpflags;
+
+       /*
+        * So long as cross-VPE interrupts are done via
+        * MFTR/MTTR read-modify-writes of Cause, we need
+        * to stop other VPEs whenever the local VPE does
+        * anything similar.
+        */
+       local_irq_save(flags);
+       vpflags = dvpe();
+       clear_c0_cause(0x100 << MIPS_CPU_IPI_IRQ);
+       set_c0_status(0x100 << MIPS_CPU_IPI_IRQ);
+       irq_enable_hazard();
+       evpe(vpflags);
+       local_irq_restore(flags);
+
+       /*
+        * Cross-VPE Interrupt handler: Try to directly deliver IPIs
+        * queued for TCs on this VPE other than the current one.
+        * Return-from-interrupt should cause us to drain the queue
+        * for the current TC, so we ought not to have to do it explicitly here.
+        */
+
+       for_each_online_cpu(cpu) {
+               if (cpu_data[cpu].vpe_id != my_vpe)
+                       continue;
+
+               pipi = smtc_ipi_dq(&IPIQ[cpu]);
+               if (pipi != NULL) {
+                       if (cpu_data[cpu].tc_id != my_tc) {
+                               sent = 0;
+                               LOCK_MT_PRA();
+                               settc(cpu_data[cpu].tc_id);
+                               write_tc_c0_tchalt(TCHALT_H);
+                               mips_ihb();
+                               tcstatus = read_tc_c0_tcstatus();
+                               if ((tcstatus & TCSTATUS_IXMT) == 0) {
+                                       post_direct_ipi(cpu, pipi);
+                                       sent = 1;
+                               }
+                               write_tc_c0_tchalt(0);
+                               UNLOCK_MT_PRA();
+                               if (!sent) {
+                                       smtc_ipi_req(&IPIQ[cpu], pipi);
+                               }
+                       } else {
+                               /*
+                                * ipi_decode() should be called
+                                * with interrupts off
+                                */
+                               local_irq_save(flags);
+                               ipi_decode(regs, pipi);
+                               local_irq_restore(flags);
+                       }
+               }
+       }
+
+       return IRQ_HANDLED;
+}
+
+static void ipi_irq_dispatch(struct pt_regs *regs)
+{
+       do_IRQ(cpu_ipi_irq, regs);
+}
+
+static struct irqaction irq_ipi;
+
+void setup_cross_vpe_interrupts(void)
+{
+       if (!cpu_has_vint)
+               panic("SMTC Kernel requires Vectored Interupt support");
+
+       set_vi_handler(MIPS_CPU_IPI_IRQ, ipi_irq_dispatch);
+
+       irq_ipi.handler = ipi_interrupt;
+       irq_ipi.flags = SA_INTERRUPT;
+       irq_ipi.name = "SMTC_IPI";
+
+       setup_irq_smtc(cpu_ipi_irq, &irq_ipi, (0x100 << MIPS_CPU_IPI_IRQ));
+
+       irq_desc[cpu_ipi_irq].status |= IRQ_PER_CPU;
+}
+
+/*
+ * SMTC-specific hacks invoked from elsewhere in the kernel.
+ */
+
+void smtc_idle_loop_hook(void)
+{
+#ifdef SMTC_IDLE_HOOK_DEBUG
+       int im;
+       int flags;
+       int mtflags;
+       int bit;
+       int vpe;
+       int tc;
+       int hook_ntcs;
+       /*
+        * printk within DMT-protected regions can deadlock,
+        * so buffer diagnostic messages for later output.
+        */
+       char *pdb_msg;
+       char id_ho_db_msg[768]; /* worst-case use should be less than 700 */
+
+       if (atomic_read(&idle_hook_initialized) == 0) { /* fast test */
+               if (atomic_add_return(1, &idle_hook_initialized) == 1) {
+                       int mvpconf0;
+                       /* Tedious stuff to just do once */
+                       mvpconf0 = read_c0_mvpconf0();
+                       hook_ntcs = ((mvpconf0 & MVPCONF0_PTC) >> MVPCONF0_PTC_SHIFT) + 1;
+                       if (hook_ntcs > NR_CPUS)
+                               hook_ntcs = NR_CPUS;
+                       for (tc = 0; tc < hook_ntcs; tc++) {
+                               tcnoprog[tc] = 0;
+                               clock_hang_reported[tc] = 0;
+                       }
+                       for (vpe = 0; vpe < 2; vpe++)
+                               for (im = 0; im < 8; im++)
+                                       imstuckcount[vpe][im] = 0;
+                       printk("Idle loop test hook initialized for %d TCs\n", hook_ntcs);
+                       atomic_set(&idle_hook_initialized, 1000);
+               } else {
+                       /* Someone else is initializing in parallel - let 'em finish */
+                       while (atomic_read(&idle_hook_initialized) < 1000)
+                               ;
+               }
+       }
+
+       /* Have we stupidly left IXMT set somewhere? */
+       if (read_c0_tcstatus() & 0x400) {
+               write_c0_tcstatus(read_c0_tcstatus() & ~0x400);
+               ehb();
+               printk("Dangling IXMT in cpu_idle()\n");
+       }
+
+       /* Have we stupidly left an IM bit turned off? */
+#define IM_LIMIT 2000
+       local_irq_save(flags);
+       mtflags = dmt();
+       pdb_msg = &id_ho_db_msg[0];
+       im = read_c0_status();
+       vpe = cpu_data[smp_processor_id()].vpe_id;
+       for (bit = 0; bit < 8; bit++) {
+               /*
+                * In current prototype, I/O interrupts
+                * are masked for VPE > 0
+                */
+               if (vpemask[vpe][bit]) {
+                       if (!(im & (0x100 << bit)))
+                               imstuckcount[vpe][bit]++;
+                       else
+                               imstuckcount[vpe][bit] = 0;
+                       if (imstuckcount[vpe][bit] > IM_LIMIT) {
+                               set_c0_status(0x100 << bit);
+                               ehb();
+                               imstuckcount[vpe][bit] = 0;
+                               pdb_msg += sprintf(pdb_msg,
+                                       "Dangling IM %d fixed for VPE %d\n", bit,
+                                       vpe);
+                       }
+               }
+       }
+
+       /*
+        * Now that we limit outstanding timer IPIs, check for hung TC
+        */
+       for (tc = 0; tc < NR_CPUS; tc++) {
+               /* Don't check ourself - we'll dequeue IPIs just below */
+               if ((tc != smp_processor_id()) &&
+                   ipi_timer_latch[tc] > timerq_limit) {
+                   if (clock_hang_reported[tc] == 0) {
+                       pdb_msg += sprintf(pdb_msg,
+                               "TC %d looks hung with timer latch at %d\n",
+                               tc, ipi_timer_latch[tc]);
+                       clock_hang_reported[tc]++;
+                       }
+               }
+       }
+       emt(mtflags);
+       local_irq_restore(flags);
+       if (pdb_msg != &id_ho_db_msg[0])
+               printk("CPU%d: %s", smp_processor_id(), id_ho_db_msg);
+#endif /* SMTC_IDLE_HOOK_DEBUG */
+       /*
+        * To the extent that we've ever turned interrupts off,
+        * we may have accumulated deferred IPIs.  This is subtle.
+        * If we use the smtc_ipi_qdepth() macro, we'll get an
+        * exact number - but we'll also disable interrupts
+        * and create a window of failure where a new IPI gets
+        * queued after we test the depth but before we re-enable
+        * interrupts. So long as IXMT never gets set, however,
+        * we should be OK:  If we pick up something and dispatch
+        * it here, that's great. If we see nothing, but concurrent
+        * with this operation, another TC sends us an IPI, IXMT
+        * is clear, and we'll handle it as a real pseudo-interrupt
+        * and not a pseudo-pseudo interrupt.
+        */
+       if (IPIQ[smp_processor_id()].depth > 0) {
+               struct smtc_ipi *pipi;
+               extern void self_ipi(struct smtc_ipi *);
+
+               if ((pipi = smtc_ipi_dq(&IPIQ[smp_processor_id()])) != NULL) {
+                       self_ipi(pipi);
+                       smtc_cpu_stats[smp_processor_id()].selfipis++;
+               }
+       }
+}
+
+void smtc_soft_dump(void)
+{
+       int i;
+
+       printk("Counter Interrupts taken per CPU (TC)\n");
+       for (i=0; i < NR_CPUS; i++) {
+               printk("%d: %ld\n", i, smtc_cpu_stats[i].timerints);
+       }
+       printk("Self-IPI invocations:\n");
+       for (i=0; i < NR_CPUS; i++) {
+               printk("%d: %ld\n", i, smtc_cpu_stats[i].selfipis);
+       }
+       smtc_ipi_qdump();
+       printk("Timer IPI Backlogs:\n");
+       for (i=0; i < NR_CPUS; i++) {
+               printk("%d: %d\n", i, ipi_timer_latch[i]);
+       }
+       printk("%d Recoveries of \"stolen\" FPU\n",
+              atomic_read(&smtc_fpu_recoveries));
+}
+
+
+/*
+ * TLB management routines special to SMTC
+ */
+
+void smtc_get_new_mmu_context(struct mm_struct *mm, unsigned long cpu)
+{
+       unsigned long flags, mtflags, tcstat, prevhalt, asid;
+       int tlb, i;
+
+       /*
+        * It would be nice to be able to use a spinlock here,
+        * but this is invoked from within TLB flush routines
+        * that protect themselves with DVPE, so if a lock is
+         * held by another TC, it'll never be freed.
+        *
+        * DVPE/DMT must not be done with interrupts enabled,
+        * so even so most callers will already have disabled
+        * them, let's be really careful...
+        */
+
+       local_irq_save(flags);
+       if (smtc_status & SMTC_TLB_SHARED) {
+               mtflags = dvpe();
+               tlb = 0;
+       } else {
+               mtflags = dmt();
+               tlb = cpu_data[cpu].vpe_id;
+       }
+       asid = asid_cache(cpu);
+
+       do {
+               if (!((asid += ASID_INC) & ASID_MASK) ) {
+                       if (cpu_has_vtag_icache)
+                               flush_icache_all();
+                       /* Traverse all online CPUs (hack requires contigous range) */
+                       for (i = 0; i < num_online_cpus(); i++) {
+                               /*
+                                * We don't need to worry about our own CPU, nor those of
+                                * CPUs who don't share our TLB.
+                                */
+                               if ((i != smp_processor_id()) &&
+                                   ((smtc_status & SMTC_TLB_SHARED) ||
+                                    (cpu_data[i].vpe_id == cpu_data[cpu].vpe_id))) {
+                                       settc(cpu_data[i].tc_id);
+                                       prevhalt = read_tc_c0_tchalt() & TCHALT_H;
+                                       if (!prevhalt) {
+                                               write_tc_c0_tchalt(TCHALT_H);
+                                               mips_ihb();
+                                       }
+                                       tcstat = read_tc_c0_tcstatus();
+                                       smtc_live_asid[tlb][(tcstat & ASID_MASK)] |= (asiduse)(0x1 << i);
+                                       if (!prevhalt)
+                                               write_tc_c0_tchalt(0);
+                               }
+                       }
+                       if (!asid)              /* fix version if needed */
+                               asid = ASID_FIRST_VERSION;
+                       local_flush_tlb_all();  /* start new asid cycle */
+               }
+       } while (smtc_live_asid[tlb][(asid & ASID_MASK)]);
+
+       /*
+        * SMTC shares the TLB within VPEs and possibly across all VPEs.
+        */
+       for (i = 0; i < num_online_cpus(); i++) {
+               if ((smtc_status & SMTC_TLB_SHARED) ||
+                   (cpu_data[i].vpe_id == cpu_data[cpu].vpe_id))
+                       cpu_context(i, mm) = asid_cache(i) = asid;
+       }
+
+       if (smtc_status & SMTC_TLB_SHARED)
+               evpe(mtflags);
+       else
+               emt(mtflags);
+       local_irq_restore(flags);
+}
+
+/*
+ * Invoked from macros defined in mmu_context.h
+ * which must already have disabled interrupts
+ * and done a DVPE or DMT as appropriate.
+ */
+
+void smtc_flush_tlb_asid(unsigned long asid)
+{
+       int entry;
+       unsigned long ehi;
+
+       entry = read_c0_wired();
+
+       /* Traverse all non-wired entries */
+       while (entry < current_cpu_data.tlbsize) {
+               write_c0_index(entry);
+               ehb();
+               tlb_read();
+               ehb();
+               ehi = read_c0_entryhi();
+               if((ehi & ASID_MASK) == asid) {
+                   /*
+                    * Invalidate only entries with specified ASID,
+                    * makiing sure all entries differ.
+                    */
+                   write_c0_entryhi(CKSEG0 + (entry << (PAGE_SHIFT + 1)));
+                   write_c0_entrylo0(0);
+                   write_c0_entrylo1(0);
+                   mtc0_tlbw_hazard();
+                   tlb_write_indexed();
+               }
+               entry++;
+       }
+       write_c0_index(PARKED_INDEX);
+       tlbw_use_hazard();
+}
+
+/*
+ * Support for single-threading cache flush operations.
+ */
+
+int halt_state_save[NR_CPUS];
+
+/*
+ * To really, really be sure that nothing is being done
+ * by other TCs, halt them all.  This code assumes that
+ * a DVPE has already been done, so while their Halted
+ * state is theoretically architecturally unstable, in
+ * practice, it's not going to change while we're looking
+ * at it.
+ */
+
+void smtc_cflush_lockdown(void)
+{
+       int cpu;
+
+       for_each_online_cpu(cpu) {
+               if (cpu != smp_processor_id()) {
+                       settc(cpu_data[cpu].tc_id);
+                       halt_state_save[cpu] = read_tc_c0_tchalt();
+                       write_tc_c0_tchalt(TCHALT_H);
+               }
+       }
+       mips_ihb();
+}
+
+/* It would be cheating to change the cpu_online states during a flush! */
+
+void smtc_cflush_release(void)
+{
+       int cpu;
+
+       /*
+        * Start with a hazard barrier to ensure
+        * that all CACHE ops have played through.
+        */
+       mips_ihb();
+
+       for_each_online_cpu(cpu) {
+               if (cpu != smp_processor_id()) {
+                       settc(cpu_data[cpu].tc_id);
+                       write_tc_c0_tchalt(halt_state_save[cpu]);
+               }
+       }
+       mips_ihb();
+}
index 5e51a2d8f3f0712072e59a2a53f01a46b9880453..13ff4da598cdfbcff3b2d34677c0e89cd3b55e28 100644 (file)
@@ -116,8 +116,7 @@ static void c0_timer_ack(void)
        write_c0_compare(expirelo);
 
        /* Check to see if we have missed any timer interrupts.  */
-       count = read_c0_count();
-       if ((count - expirelo) < 0x7fffffff) {
+       while (((count = read_c0_count()) - expirelo) < 0x7fffffff) {
                /* missed_timer_count++; */
                expirelo = count + cycles_per_jiffy;
                write_c0_compare(expirelo);
index bed0eb6cf55d58f7178ecf0f550e05c8a7ac6c47..4901f0a37fca2b3ddb2de93dcf998873b10e6643 100644 (file)
@@ -42,6 +42,7 @@
 #include <asm/watch.h>
 #include <asm/types.h>
 
+extern asmlinkage void handle_int(void);
 extern asmlinkage void handle_tlbm(void);
 extern asmlinkage void handle_tlbl(void);
 extern asmlinkage void handle_tlbs(void);
@@ -279,9 +280,16 @@ static DEFINE_SPINLOCK(die_lock);
 NORET_TYPE void ATTRIB_NORET die(const char * str, struct pt_regs * regs)
 {
        static int die_counter;
+#ifdef CONFIG_MIPS_MT_SMTC
+       unsigned long dvpret = dvpe();
+#endif /* CONFIG_MIPS_MT_SMTC */
 
        console_verbose();
        spin_lock_irq(&die_lock);
+       bust_spinlocks(1);
+#ifdef CONFIG_MIPS_MT_SMTC
+       mips_mt_regdump(dvpret);
+#endif /* CONFIG_MIPS_MT_SMTC */
        printk("%s[#%d]:\n", str, ++die_counter);
        show_registers(regs);
        spin_unlock_irq(&die_lock);
@@ -750,12 +758,43 @@ asmlinkage void do_cpu(struct pt_regs *regs)
                                                &current->thread.fpu.soft);
                        if (sig)
                                force_sig(sig, current);
+#ifdef CONFIG_MIPS_MT_FPAFF
+                       else {
+                       /*
+                        * MIPS MT processors may have fewer FPU contexts
+                        * than CPU threads. If we've emulated more than
+                        * some threshold number of instructions, force
+                        * migration to a "CPU" that has FP support.
+                        */
+                        if(mt_fpemul_threshold > 0
+                        && ((current->thread.emulated_fp++
+                           > mt_fpemul_threshold))) {
+                         /*
+                          * If there's no FPU present, or if the
+                          * application has already restricted
+                          * the allowed set to exclude any CPUs
+                          * with FPUs, we'll skip the procedure.
+                          */
+                         if (cpus_intersects(current->cpus_allowed,
+                                               mt_fpu_cpumask)) {
+                           cpumask_t tmask;
+
+                           cpus_and(tmask,
+                                       current->thread.user_cpus_allowed,
+                                       mt_fpu_cpumask);
+                           set_cpus_allowed(current, tmask);
+                           current->thread.mflags |= MF_FPUBOUND;
+                         }
+                        }
+                       }
+#endif /* CONFIG_MIPS_MT_FPAFF */
                }
 
                return;
 
        case 2:
        case 3:
+               die_if_kernel("do_cpu invoked from kernel context!", regs);
                break;
        }
 
@@ -793,6 +832,36 @@ asmlinkage void do_mcheck(struct pt_regs *regs)
 
 asmlinkage void do_mt(struct pt_regs *regs)
 {
+       int subcode;
+
+       die_if_kernel("MIPS MT Thread exception in kernel", regs);
+
+       subcode = (read_vpe_c0_vpecontrol() & VPECONTROL_EXCPT)
+                       >> VPECONTROL_EXCPT_SHIFT;
+       switch (subcode) {
+       case 0:
+               printk(KERN_ERR "Thread Underflow\n");
+               break;
+       case 1:
+               printk(KERN_ERR "Thread Overflow\n");
+               break;
+       case 2:
+               printk(KERN_ERR "Invalid YIELD Qualifier\n");
+               break;
+       case 3:
+               printk(KERN_ERR "Gating Storage Exception\n");
+               break;
+       case 4:
+               printk(KERN_ERR "YIELD Scheduler Exception\n");
+               break;
+       case 5:
+               printk(KERN_ERR "Gating Storage Schedulier Exception\n");
+               break;
+       default:
+               printk(KERN_ERR "*** UNKNOWN THREAD EXCEPTION %d ***\n",
+                       subcode);
+               break;
+       }
        die_if_kernel("MIPS MT Thread exception in kernel", regs);
 
        force_sig(SIGILL, current);
@@ -928,7 +997,15 @@ void ejtag_exception_handler(struct pt_regs *regs)
  */
 void nmi_exception_handler(struct pt_regs *regs)
 {
+#ifdef CONFIG_MIPS_MT_SMTC
+       unsigned long dvpret = dvpe();
+       bust_spinlocks(1);
+       printk("NMI taken!!!!\n");
+       mips_mt_regdump(dvpret);
+#else
+       bust_spinlocks(1);
        printk("NMI taken!!!!\n");
+#endif /* CONFIG_MIPS_MT_SMTC */
        die("NMI", regs);
        while(1) ;
 }
@@ -960,27 +1037,29 @@ void *set_except_vector(int n, void *addr)
 
 #ifdef CONFIG_CPU_MIPSR2
 /*
- * Shadow register allocation
+ * MIPSR2 shadow register set allocation
  * FIXME: SMP...
  */
 
-/* MIPSR2 shadow register sets */
-struct shadow_registers {
-       spinlock_t sr_lock;     /*  */
-       int sr_supported;       /* Number of shadow register sets supported */
-       int sr_allocated;       /* Bitmap of allocated shadow registers */
+static struct shadow_registers {
+       /*
+        * Number of shadow register sets supported
+        */
+       unsigned long sr_supported;
+       /*
+        * Bitmap of allocated shadow registers
+        */
+       unsigned long sr_allocated;
 } shadow_registers;
 
-void mips_srs_init(void)
+static void mips_srs_init(void)
 {
 #ifdef CONFIG_CPU_MIPSR2_SRS
        shadow_registers.sr_supported = ((read_c0_srsctl() >> 26) & 0x0f) + 1;
-       printk ("%d MIPSR2 register sets available\n", shadow_registers.sr_supported);
-#else
-       shadow_registers.sr_supported = 1;
+       printk(KERN_INFO "%d MIPSR2 register sets available\n",
+              shadow_registers.sr_supported);
 #endif
        shadow_registers.sr_allocated = 1;      /* Set 0 used by kernel */
-       spin_lock_init(&shadow_registers.sr_lock);
 }
 
 int mips_srs_max(void)
@@ -988,38 +1067,30 @@ int mips_srs_max(void)
        return shadow_registers.sr_supported;
 }
 
-int mips_srs_alloc (void)
+int mips_srs_alloc(void)
 {
        struct shadow_registers *sr = &shadow_registers;
-       unsigned long flags;
        int set;
 
-       spin_lock_irqsave(&sr->sr_lock, flags);
+again:
+       set = find_first_zero_bit(&sr->sr_allocated, sr->sr_supported);
+       if (set >= sr->sr_supported)
+               return -1;
 
-       for (set = 0; set < sr->sr_supported; set++) {
-               if ((sr->sr_allocated & (1 << set)) == 0) {
-                       sr->sr_allocated |= 1 << set;
-                       spin_unlock_irqrestore(&sr->sr_lock, flags);
-                       return set;
-               }
-       }
+       if (test_and_set_bit(set, &sr->sr_allocated))
+               goto again;
 
-       /* None available */
-       spin_unlock_irqrestore(&sr->sr_lock, flags);
-       return -1;
+       return set;
 }
 
-void mips_srs_free (int set)
+void mips_srs_free(int set)
 {
        struct shadow_registers *sr = &shadow_registers;
-       unsigned long flags;
 
-       spin_lock_irqsave(&sr->sr_lock, flags);
-       sr->sr_allocated &= ~(1 << set);
-       spin_unlock_irqrestore(&sr->sr_lock, flags);
+       clear_bit(set, &sr->sr_allocated);
 }
 
-void *set_vi_srs_handler (int n, void *addr, int srs)
+static void *set_vi_srs_handler(int n, void *addr, int srs)
 {
        unsigned long handler;
        unsigned long old_handler = vi_handlers[n];
@@ -1032,8 +1103,7 @@ void *set_vi_srs_handler (int n, void *addr, int srs)
        if (addr == NULL) {
                handler = (unsigned long) do_default_vi;
                srs = 0;
-       }
-       else
+       } else
                handler = (unsigned long) addr;
        vi_handlers[n] = (unsigned long) addr;
 
@@ -1045,8 +1115,7 @@ void *set_vi_srs_handler (int n, void *addr, int srs)
        if (cpu_has_veic) {
                if (board_bind_eic_interrupt)
                        board_bind_eic_interrupt (n, srs);
-       }
-       else if (cpu_has_vint) {
+       } else if (cpu_has_vint) {
                /* SRSMap is only defined if shadow sets are implemented */
                if (mips_srs_max() > 1)
                        change_c0_srsmap (0xf << n*4, srs << n*4);
@@ -1060,6 +1129,15 @@ void *set_vi_srs_handler (int n, void *addr, int srs)
 
                extern char except_vec_vi, except_vec_vi_lui;
                extern char except_vec_vi_ori, except_vec_vi_end;
+#ifdef CONFIG_MIPS_MT_SMTC
+               /*
+                * We need to provide the SMTC vectored interrupt handler
+                * not only with the address of the handler, but with the
+                * Status.IM bit to be masked before going there.
+                */
+               extern char except_vec_vi_mori;
+               const int mori_offset = &except_vec_vi_mori - &except_vec_vi;
+#endif /* CONFIG_MIPS_MT_SMTC */
                const int handler_len = &except_vec_vi_end - &except_vec_vi;
                const int lui_offset = &except_vec_vi_lui - &except_vec_vi;
                const int ori_offset = &except_vec_vi_ori - &except_vec_vi;
@@ -1073,6 +1151,12 @@ void *set_vi_srs_handler (int n, void *addr, int srs)
                }
 
                memcpy (b, &except_vec_vi, handler_len);
+#ifdef CONFIG_MIPS_MT_SMTC
+               if (n > 7)
+                       printk("Vector index %d exceeds SMTC maximum\n", n);
+               w = (u32 *)(b + mori_offset);
+               *w = (*w & 0xffff0000) | (0x100 << n);
+#endif /* CONFIG_MIPS_MT_SMTC */
                w = (u32 *)(b + lui_offset);
                *w = (*w & 0xffff0000) | (((u32)handler >> 16) & 0xffff);
                w = (u32 *)(b + ori_offset);
@@ -1095,9 +1179,9 @@ void *set_vi_srs_handler (int n, void *addr, int srs)
        return (void *)old_handler;
 }
 
-void *set_vi_handler (int n, void *addr)
+void *set_vi_handler(int n, void *addr)
 {
-       return set_vi_srs_handler (n, addr, 0);
+       return set_vi_srs_handler(n, addr, 0);
 }
 #endif
 
@@ -1113,8 +1197,29 @@ extern asmlinkage int _restore_fp_context(struct sigcontext *sc);
 extern asmlinkage int fpu_emulator_save_context(struct sigcontext *sc);
 extern asmlinkage int fpu_emulator_restore_context(struct sigcontext *sc);
 
+#ifdef CONFIG_SMP
+static int smp_save_fp_context(struct sigcontext *sc)
+{
+       return cpu_has_fpu
+              ? _save_fp_context(sc)
+              : fpu_emulator_save_context(sc);
+}
+
+static int smp_restore_fp_context(struct sigcontext *sc)
+{
+       return cpu_has_fpu
+              ? _restore_fp_context(sc)
+              : fpu_emulator_restore_context(sc);
+}
+#endif
+
 static inline void signal_init(void)
 {
+#ifdef CONFIG_SMP
+       /* For now just do the cpu_has_fpu check when the functions are invoked */
+       save_fp_context = smp_save_fp_context;
+       restore_fp_context = smp_restore_fp_context;
+#else
        if (cpu_has_fpu) {
                save_fp_context = _save_fp_context;
                restore_fp_context = _restore_fp_context;
@@ -1122,6 +1227,7 @@ static inline void signal_init(void)
                save_fp_context = fpu_emulator_save_context;
                restore_fp_context = fpu_emulator_restore_context;
        }
+#endif
 }
 
 #ifdef CONFIG_MIPS32_COMPAT
@@ -1158,6 +1264,20 @@ void __init per_cpu_trap_init(void)
 {
        unsigned int cpu = smp_processor_id();
        unsigned int status_set = ST0_CU0;
+#ifdef CONFIG_MIPS_MT_SMTC
+       int secondaryTC = 0;
+       int bootTC = (cpu == 0);
+
+       /*
+        * Only do per_cpu_trap_init() for first TC of Each VPE.
+        * Note that this hack assumes that the SMTC init code
+        * assigns TCs consecutively and in ascending order.
+        */
+
+       if (((read_c0_tcbind() & TCBIND_CURTC) != 0) &&
+           ((read_c0_tcbind() & TCBIND_CURVPE) == cpu_data[cpu - 1].vpe_id))
+               secondaryTC = 1;
+#endif /* CONFIG_MIPS_MT_SMTC */
 
        /*
         * Disable coprocessors and select 32-bit or 64-bit addressing
@@ -1180,6 +1300,10 @@ void __init per_cpu_trap_init(void)
        write_c0_hwrena (0x0000000f); /* Allow rdhwr to all registers */
 #endif
 
+#ifdef CONFIG_MIPS_MT_SMTC
+       if (!secondaryTC) {
+#endif /* CONFIG_MIPS_MT_SMTC */
+
        /*
         * Interrupt handling.
         */
@@ -1196,6 +1320,9 @@ void __init per_cpu_trap_init(void)
                } else
                        set_c0_cause(CAUSEF_IV);
        }
+#ifdef CONFIG_MIPS_MT_SMTC
+       }
+#endif /* CONFIG_MIPS_MT_SMTC */
 
        cpu_data[cpu].asid_cache = ASID_FIRST_VERSION;
        TLBMISS_HANDLER_SETUP();
@@ -1205,8 +1332,14 @@ void __init per_cpu_trap_init(void)
        BUG_ON(current->mm);
        enter_lazy_tlb(&init_mm, current);
 
-       cpu_cache_init();
-       tlb_init();
+#ifdef CONFIG_MIPS_MT_SMTC
+       if (bootTC) {
+#endif /* CONFIG_MIPS_MT_SMTC */
+               cpu_cache_init();
+               tlb_init();
+#ifdef CONFIG_MIPS_MT_SMTC
+       }
+#endif /* CONFIG_MIPS_MT_SMTC */
 }
 
 /* Install CPU exception handler */
@@ -1278,7 +1411,7 @@ void __init trap_init(void)
        if (cpu_has_veic || cpu_has_vint) {
                int nvec = cpu_has_veic ? 64 : 8;
                for (i = 0; i < nvec; i++)
-                       set_vi_handler (i, NULL);
+                       set_vi_handler(i, NULL);
        }
        else if (cpu_has_divec)
                set_handler(0x200, &except_vec4, 0x8);
@@ -1297,6 +1430,7 @@ void __init trap_init(void)
        if (board_be_init)
                board_be_init();
 
+       set_except_vector(0, handle_int);
        set_except_vector(1, handle_tlbm);
        set_except_vector(2, handle_tlbl);
        set_except_vector(3, handle_tlbs);
index 2ad0cedf29fee2236c32d7e1ec1cd3ac34b0b0ad..14fa00e3cdfa6007332e58fbd84fc9eba3c4d1ac 100644 (file)
@@ -2,7 +2,7 @@
 #include <asm/asm-offsets.h>
 #include <asm-generic/vmlinux.lds.h>
 
-#undef mips            /* CPP really sucks for this job  */
+#undef mips
 #define mips mips
 OUTPUT_ARCH(mips)
 ENTRY(kernel_entry)
index ae83b755cf4aae68c24fe36b80f339665f9d42fd..80ffaa6d50ad0fc9b9d62474bbc62743dc9158f6 100644 (file)
@@ -13,7 +13,6 @@
  *  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.
- *
  */
 
 /*
  *
  * To load and run, simply cat a SP 'program file' to /dev/vpe1.
  * i.e cat spapp >/dev/vpe1.
- *
- * You'll need to have the following device files.
- * mknod /dev/vpe0 c 63 0
- * mknod /dev/vpe1 c 63 1
  */
+
 #include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
@@ -55,6 +51,8 @@
 #include <asm/cpu.h>
 #include <asm/processor.h>
 #include <asm/system.h>
+#include <asm/vpe.h>
+#include <asm/kspd.h>
 
 typedef void *vpe_handle;
 
@@ -68,6 +66,11 @@ typedef void *vpe_handle;
 static char module_name[] = "vpe";
 static int major;
 
+#ifdef CONFIG_MIPS_APSP_KSPD
+ static struct kspd_notifications kspd_events;
+static int kspd_events_reqd = 0;
+#endif
+
 /* grab the likely amount of memory we will need. */
 #ifdef CONFIG_MIPS_VPE_LOADER_TOM
 #define P_SIZE (2 * 1024 * 1024)
@@ -76,7 +79,10 @@ static int major;
 #define P_SIZE (256 * 1024)
 #endif
 
+extern unsigned long physical_memsize;
+
 #define MAX_VPES 16
+#define VPE_PATH_MAX 256
 
 enum vpe_state {
        VPE_STATE_UNUSED = 0,
@@ -102,6 +108,8 @@ struct vpe {
        unsigned long len;
        char *pbuffer;
        unsigned long plen;
+       unsigned int uid, gid;
+       char cwd[VPE_PATH_MAX];
 
        unsigned long __start;
 
@@ -113,6 +121,9 @@ struct vpe {
 
        /* shared symbol address */
        void *shared_ptr;
+
+       /* the list of who wants to know when something major happens */
+       struct list_head notify;
 };
 
 struct tc {
@@ -138,7 +149,7 @@ struct vpecontrol_ {
 } vpecontrol;
 
 static void release_progmem(void *ptr);
-static void dump_vpe(struct vpe * v);
+/* static __attribute_used__ void dump_vpe(struct vpe * v); */
 extern void save_gp_address(unsigned int secbase, unsigned int rel);
 
 /* get the vpe associated with this minor */
@@ -146,12 +157,14 @@ struct vpe *get_vpe(int minor)
 {
        struct vpe *v;
 
+       if (!cpu_has_mipsmt)
+               return NULL;
+
        list_for_each_entry(v, &vpecontrol.vpe_list, list) {
                if (v->minor == minor)
                        return v;
        }
 
-       printk(KERN_DEBUG "VPE: get_vpe minor %d not found\n", minor);
        return NULL;
 }
 
@@ -165,8 +178,6 @@ struct tc *get_tc(int index)
                        return t;
        }
 
-       printk(KERN_DEBUG "VPE: get_tc index %d not found\n", index);
-
        return NULL;
 }
 
@@ -179,8 +190,6 @@ struct tc *get_tc_unused(void)
                        return t;
        }
 
-       printk(KERN_DEBUG "VPE: All TC's are in use\n");
-
        return NULL;
 }
 
@@ -190,13 +199,13 @@ struct vpe *alloc_vpe(int minor)
        struct vpe *v;
 
        if ((v = kzalloc(sizeof(struct vpe), GFP_KERNEL)) == NULL) {
-               printk(KERN_WARNING "VPE: alloc_vpe no mem\n");
                return NULL;
        }
 
        INIT_LIST_HEAD(&v->tc);
        list_add_tail(&v->list, &vpecontrol.vpe_list);
 
+       INIT_LIST_HEAD(&v->notify);
        v->minor = minor;
        return v;
 }
@@ -207,7 +216,6 @@ struct tc *alloc_tc(int index)
        struct tc *t;
 
        if ((t = kzalloc(sizeof(struct tc), GFP_KERNEL)) == NULL) {
-               printk(KERN_WARNING "VPE: alloc_tc no mem\n");
                return NULL;
        }
 
@@ -236,20 +244,16 @@ void dump_mtregs(void)
        printk("config3 0x%lx MT %ld\n", val,
               (val & CONFIG3_MT) >> CONFIG3_MT_SHIFT);
 
-       val = read_c0_mvpconf0();
-       printk("mvpconf0 0x%lx, PVPE %ld PTC %ld M %ld\n", val,
-              (val & MVPCONF0_PVPE) >> MVPCONF0_PVPE_SHIFT,
-              val & MVPCONF0_PTC, (val & MVPCONF0_M) >> MVPCONF0_M_SHIFT);
-
        val = read_c0_mvpcontrol();
        printk("MVPControl 0x%lx, STLB %ld VPC %ld EVP %ld\n", val,
               (val & MVPCONTROL_STLB) >> MVPCONTROL_STLB_SHIFT,
               (val & MVPCONTROL_VPC) >> MVPCONTROL_VPC_SHIFT,
               (val & MVPCONTROL_EVP));
 
-       val = read_c0_vpeconf0();
-       printk("VPEConf0 0x%lx MVP %ld\n", val,
-              (val & VPECONF0_MVP) >> VPECONF0_MVP_SHIFT);
+       val = read_c0_mvpconf0();
+       printk("mvpconf0 0x%lx, PVPE %ld PTC %ld M %ld\n", val,
+              (val & MVPCONF0_PVPE) >> MVPCONF0_PVPE_SHIFT,
+              val & MVPCONF0_PTC, (val & MVPCONF0_M) >> MVPCONF0_M_SHIFT);
 }
 
 /* Find some VPE program space  */
@@ -354,9 +358,9 @@ static int apply_r_mips_gprel16(struct module *me, uint32_t *location,
        }
 
        if( (rel > 32768) || (rel < -32768) ) {
-               printk(KERN_ERR
-                      "apply_r_mips_gprel16: relative address out of range 0x%x %d\n",
-                      rel, rel);
+               printk(KERN_DEBUG "VPE loader: apply_r_mips_gprel16: "
+                      "relative address 0x%x out of range of gp register\n",
+                      rel);
                return -ENOEXEC;
        }
 
@@ -374,8 +378,8 @@ static int apply_r_mips_pc16(struct module *me, uint32_t *location,
        rel -= 1;               // and one instruction less due to the branch delay slot.
 
        if( (rel > 32768) || (rel < -32768) ) {
-               printk(KERN_ERR
-                      "apply_r_mips_pc16: relative address out of range 0x%x\n", rel);
+               printk(KERN_DEBUG "VPE loader: "
+                      "apply_r_mips_pc16: relative address out of range 0x%x\n", rel);
                return -ENOEXEC;
        }
 
@@ -396,7 +400,8 @@ static int apply_r_mips_26(struct module *me, uint32_t *location,
                           Elf32_Addr v)
 {
        if (v % 4) {
-               printk(KERN_ERR "module %s: dangerous relocation mod4\n", me->name);
+               printk(KERN_DEBUG "VPE loader: apply_r_mips_26 "
+                      " unaligned relocation\n");
                return -ENOEXEC;
        }
 
@@ -459,12 +464,13 @@ static int apply_r_mips_lo16(struct module *me, uint32_t *location,
                        /*
                         * The value for the HI16 had best be the same.
                         */
-                       if (v != l->value) {
-                               printk("%d != %d\n", v, l->value);
-                               goto out_danger;
+                       if (v != l->value) {
+                               printk(KERN_DEBUG "VPE loader: "
+                                      "apply_r_mips_lo16/hi16:         "
+                                      "inconsistent value information\n");
+                               return -ENOEXEC;
                        }
 
-
                        /*
                         * Do the HI16 relocation.  Note that we actually don't
                         * need to know anything about the LO16 itself, except
@@ -500,11 +506,6 @@ static int apply_r_mips_lo16(struct module *me, uint32_t *location,
        *location = insnlo;
 
        return 0;
-
-out_danger:
-       printk(KERN_ERR "module %s: dangerous " "relocation\n", me->name);
-
-       return -ENOEXEC;
 }
 
 static int (*reloc_handlers[]) (struct module *me, uint32_t *location,
@@ -518,6 +519,15 @@ static int (*reloc_handlers[]) (struct module *me, uint32_t *location,
        [R_MIPS_PC16] = apply_r_mips_pc16
 };
 
+static char *rstrs[] = {
+       [R_MIPS_NONE]   = "MIPS_NONE",
+       [R_MIPS_32]     = "MIPS_32",
+       [R_MIPS_26]     = "MIPS_26",
+       [R_MIPS_HI16]   = "MIPS_HI16",
+       [R_MIPS_LO16]   = "MIPS_LO16",
+       [R_MIPS_GPREL16] = "MIPS_GPREL16",
+       [R_MIPS_PC16] = "MIPS_PC16"
+};
 
 int apply_relocations(Elf32_Shdr *sechdrs,
                      const char *strtab,
@@ -552,15 +562,13 @@ int apply_relocations(Elf32_Shdr *sechdrs,
 
                res = reloc_handlers[ELF32_R_TYPE(r_info)](me, location, v);
                if( res ) {
-                       printk(KERN_DEBUG
-                              "relocation error 0x%x sym refer <%s> value 0x%x "
-                              "type 0x%x r_info 0x%x\n",
-                              (unsigned int)location, strtab + sym->st_name, v,
-                              r_info, ELF32_R_TYPE(r_info));
-               }
-
-               if (res)
+                       char *r = rstrs[ELF32_R_TYPE(r_info)];
+                       printk(KERN_WARNING "VPE loader: .text+0x%x "
+                              "relocation type %s for symbol \"%s\" failed\n",
+                              rel[i].r_offset, r ? r : "UNKNOWN",
+                              strtab + sym->st_name);
                        return res;
+               }
        }
 
        return 0;
@@ -576,7 +584,7 @@ void save_gp_address(unsigned int secbase, unsigned int rel)
 
 
 /* Change all symbols so that sh_value encodes the pointer directly. */
-static int simplify_symbols(Elf_Shdr * sechdrs,
+static void simplify_symbols(Elf_Shdr * sechdrs,
                            unsigned int symindex,
                            const char *strtab,
                            const char *secstrings,
@@ -585,18 +593,21 @@ static int simplify_symbols(Elf_Shdr * sechdrs,
        Elf_Sym *sym = (void *)sechdrs[symindex].sh_addr;
        unsigned long secbase, bssbase = 0;
        unsigned int i, n = sechdrs[symindex].sh_size / sizeof(Elf_Sym);
-       int ret = 0, size;
+       int size;
 
        /* find the .bss section for COMMON symbols */
        for (i = 0; i < nsecs; i++) {
-               if (strncmp(secstrings + sechdrs[i].sh_name, ".bss", 4) == 0)
+               if (strncmp(secstrings + sechdrs[i].sh_name, ".bss", 4) == 0) {
                        bssbase = sechdrs[i].sh_addr;
+                       break;
+               }
        }
 
        for (i = 1; i < n; i++) {
                switch (sym[i].st_shndx) {
                case SHN_COMMON:
-                       /* Allocate space for the symbol in the .bss section. st_value is currently size.
+                       /* Allocate space for the symbol in the .bss section.
+                          st_value is currently size.
                           We want it to have the address of the symbol. */
 
                        size = sym[i].st_value;
@@ -614,11 +625,9 @@ static int simplify_symbols(Elf_Shdr * sechdrs,
                        break;
 
                case SHN_MIPS_SCOMMON:
-
-                       printk(KERN_DEBUG
-                              "simplify_symbols: ignoring SHN_MIPS_SCOMMON symbol <%s> st_shndx %d\n",
-                              strtab + sym[i].st_name, sym[i].st_shndx);
-
+                       printk(KERN_DEBUG "simplify_symbols: ignoring SHN_MIPS_SCOMMON"
+                              "symbol <%s> st_shndx %d\n", strtab + sym[i].st_name,
+                              sym[i].st_shndx);
                        // .sbss section
                        break;
 
@@ -632,10 +641,7 @@ static int simplify_symbols(Elf_Shdr * sechdrs,
                        sym[i].st_value += secbase;
                        break;
                }
-
        }
-
-       return ret;
 }
 
 #ifdef DEBUG_ELFLOADER
@@ -655,9 +661,26 @@ static void dump_elfsymbols(Elf_Shdr * sechdrs, unsigned int symindex,
 
 static void dump_tc(struct tc *t)
 {
-       printk(KERN_WARNING "VPE: TC index %d TCStatus 0x%lx halt 0x%lx\n",
-              t->index, read_tc_c0_tcstatus(), read_tc_c0_tchalt());
-       printk(KERN_WARNING "VPE: tcrestart 0x%lx\n", read_tc_c0_tcrestart());
+       unsigned long val;
+
+       settc(t->index);
+       printk(KERN_DEBUG "VPE loader: TC index %d targtc %ld "
+              "TCStatus 0x%lx halt 0x%lx\n",
+              t->index, read_c0_vpecontrol() & VPECONTROL_TARGTC,
+              read_tc_c0_tcstatus(), read_tc_c0_tchalt());
+
+       printk(KERN_DEBUG " tcrestart 0x%lx\n", read_tc_c0_tcrestart());
+       printk(KERN_DEBUG " tcbind 0x%lx\n", read_tc_c0_tcbind());
+
+       val = read_c0_vpeconf0();
+       printk(KERN_DEBUG " VPEConf0 0x%lx MVP %ld\n", val,
+              (val & VPECONF0_MVP) >> VPECONF0_MVP_SHIFT);
+
+       printk(KERN_DEBUG " c0 status 0x%lx\n", read_vpe_c0_status());
+       printk(KERN_DEBUG " c0 cause 0x%lx\n", read_vpe_c0_cause());
+
+       printk(KERN_DEBUG " c0 badvaddr 0x%lx\n", read_vpe_c0_badvaddr());
+       printk(KERN_DEBUG " c0 epc 0x%lx\n", read_vpe_c0_epc());
 }
 
 static void dump_tclist(void)
@@ -672,96 +695,108 @@ static void dump_tclist(void)
 /* We are prepared so configure and start the VPE... */
 int vpe_run(struct vpe * v)
 {
-       unsigned long val;
+       struct vpe_notifications *n;
+       unsigned long val, dmt_flag;
        struct tc *t;
 
        /* check we are the Master VPE */
        val = read_c0_vpeconf0();
        if (!(val & VPECONF0_MVP)) {
                printk(KERN_WARNING
-                      "VPE: only Master VPE's are allowed to configure MT\n");
+                      "VPE loader: only Master VPE's are allowed to configure MT\n");
                return -1;
        }
 
        /* disable MT (using dvpe) */
        dvpe();
 
+       if (!list_empty(&v->tc)) {
+                if ((t = list_entry(v->tc.next, struct tc, tc)) == NULL) {
+                        printk(KERN_WARNING "VPE loader: TC %d is already in use.\n",
+                               t->index);
+                        return -ENOEXEC;
+                }
+        } else {
+                printk(KERN_WARNING "VPE loader: No TC's associated with VPE %d\n",
+                       v->minor);
+                return -ENOEXEC;
+        }
+
        /* Put MVPE's into 'configuration state' */
        set_c0_mvpcontrol(MVPCONTROL_VPC);
 
-       if (!list_empty(&v->tc)) {
-               if ((t = list_entry(v->tc.next, struct tc, tc)) == NULL) {
-                       printk(KERN_WARNING "VPE: TC %d is already in use.\n",
-                              t->index);
-                       return -ENOEXEC;
-               }
-       } else {
-               printk(KERN_WARNING "VPE: No TC's associated with VPE %d\n",
-                      v->minor);
-               return -ENOEXEC;
-       }
-
        settc(t->index);
 
-       val = read_vpe_c0_vpeconf0();
-
        /* should check it is halted, and not activated */
        if ((read_tc_c0_tcstatus() & TCSTATUS_A) || !(read_tc_c0_tchalt() & TCHALT_H)) {
-               printk(KERN_WARNING "VPE: TC %d is already doing something!\n",
+               printk(KERN_WARNING "VPE loader: TC %d is already doing something!\n",
                       t->index);
-
                dump_tclist();
                return -ENOEXEC;
        }
 
+       /*
+        * Disable multi-threaded execution whilst we activate, clear the
+        * halt bit and bound the tc to the other VPE...
+        */
+       dmt_flag = dmt();
+
        /* Write the address we want it to start running from in the TCPC register. */
        write_tc_c0_tcrestart((unsigned long)v->__start);
-
-       /* write the sivc_info address to tccontext */
        write_tc_c0_tccontext((unsigned long)0);
-
-       /* Set up the XTC bit in vpeconf0 to point at our tc */
-       write_vpe_c0_vpeconf0(read_vpe_c0_vpeconf0() | (t->index << VPECONF0_XTC_SHIFT));
-
-       /* mark the TC as activated, not interrupt exempt and not dynamically allocatable */
+       /*
+        * Mark the TC as activated, not interrupt exempt and not dynamically
+        * allocatable
+        */
        val = read_tc_c0_tcstatus();
        val = (val & ~(TCSTATUS_DA | TCSTATUS_IXMT)) | TCSTATUS_A;
        write_tc_c0_tcstatus(val);
 
        write_tc_c0_tchalt(read_tc_c0_tchalt() & ~TCHALT_H);
 
-       /* set up VPE1 */
-       write_vpe_c0_vpecontrol(read_vpe_c0_vpecontrol() & ~VPECONTROL_TE);     // no multiple TC's
-       write_vpe_c0_vpeconf0(read_vpe_c0_vpeconf0() | VPECONF0_VPA);   // enable this VPE
-
        /*
         * The sde-kit passes 'memsize' to __start in $a3, so set something
-        * here...
-        * Or set $a3 (register 7) to zero and define DFLT_STACK_SIZE and
+        * here...  Or set $a3 to zero and define DFLT_STACK_SIZE and
         * DFLT_HEAP_SIZE when you compile your program
         */
+       mttgpr(7, physical_memsize);
+
+
+       /* set up VPE1 */
+       /*
+        * bind the TC to VPE 1 as late as possible so we only have the final
+        * VPE registers to set up, and so an EJTAG probe can trigger on it
+        */
+       write_tc_c0_tcbind((read_tc_c0_tcbind() & ~TCBIND_CURVPE) | v->minor);
 
-       mttgpr(7, 0);
+        /* Set up the XTC bit in vpeconf0 to point at our tc */
+        write_vpe_c0_vpeconf0( (read_vpe_c0_vpeconf0() & ~(VPECONF0_XTC))
+                               | (t->index << VPECONF0_XTC_SHIFT));
 
-       /* set config to be the same as vpe0, particularly kseg0 coherency alg */
-       write_vpe_c0_config(read_c0_config());
+        /* enable this VPE */
+        write_vpe_c0_vpeconf0(read_vpe_c0_vpeconf0() | VPECONF0_VPA);
 
        /* clear out any left overs from a previous program */
+       write_vpe_c0_status(0);
        write_vpe_c0_cause(0);
 
        /* take system out of configuration state */
        clear_c0_mvpcontrol(MVPCONTROL_VPC);
 
-       /* clear interrupts enabled IE, ERL, EXL, and KSU from c0 status */
-       write_vpe_c0_status(read_vpe_c0_status() & ~(ST0_ERL | ST0_KSU | ST0_IE | ST0_EXL));
+       /* now safe to re-enable multi-threading */
+       emt(dmt_flag);
 
        /* set it running */
        evpe(EVPE_ENABLE);
 
+       list_for_each_entry(n, &v->notify, list) {
+               n->start(v->minor);
+       }
+
        return 0;
 }
 
-static unsigned long find_vpe_symbols(struct vpe * v, Elf_Shdr * sechdrs,
+static int find_vpe_symbols(struct vpe * v, Elf_Shdr * sechdrs,
                                      unsigned int symindex, const char *strtab,
                                      struct module *mod)
 {
@@ -778,26 +813,28 @@ static unsigned long find_vpe_symbols(struct vpe * v, Elf_Shdr * sechdrs,
                }
        }
 
+       if ( (v->__start == 0) || (v->shared_ptr == NULL))
+               return -1;
+
        return 0;
 }
 
 /*
- * Allocates a VPE with some program code space(the load address), copies
- * the contents of the program (p)buffer performing relocatations/etc,
- * free's it when finished.
-*/
+ * Allocates a VPE with some program code space(the load address), copies the
+ * contents of the program (p)buffer performing relocatations/etc, free's it
+ * when finished.
+ */
 int vpe_elfload(struct vpe * v)
 {
        Elf_Ehdr *hdr;
        Elf_Shdr *sechdrs;
        long err = 0;
        char *secstrings, *strtab = NULL;
-       unsigned int len, i, symindex = 0, strindex = 0;
-
+       unsigned int len, i, symindex = 0, strindex = 0, relocate = 0;
        struct module mod;      // so we can re-use the relocations code
 
        memset(&mod, 0, sizeof(struct module));
-       strcpy(mod.name, "VPE dummy prog module");
+       strcpy(mod.name, "VPE loader");
 
        hdr = (Elf_Ehdr *) v->pbuffer;
        len = v->plen;
@@ -805,16 +842,22 @@ int vpe_elfload(struct vpe * v)
        /* Sanity checks against insmoding binaries or wrong arch,
           weird elf version */
        if (memcmp(hdr->e_ident, ELFMAG, 4) != 0
-           || hdr->e_type != ET_REL || !elf_check_arch(hdr)
+           || (hdr->e_type != ET_REL && hdr->e_type != ET_EXEC)
+           || !elf_check_arch(hdr)
            || hdr->e_shentsize != sizeof(*sechdrs)) {
                printk(KERN_WARNING
-                      "VPE program, wrong arch or weird elf version\n");
+                      "VPE loader: program wrong arch or weird elf version\n");
 
                return -ENOEXEC;
        }
 
+       if (hdr->e_type == ET_REL)
+               relocate = 1;
+
        if (len < hdr->e_shoff + hdr->e_shnum * sizeof(Elf_Shdr)) {
-               printk(KERN_ERR "VPE program length %u truncated\n", len);
+               printk(KERN_ERR "VPE loader: program length %u truncated\n",
+                      len);
+
                return -ENOEXEC;
        }
 
@@ -826,82 +869,126 @@ int vpe_elfload(struct vpe * v)
        /* And these should exist, but gcc whinges if we don't init them */
        symindex = strindex = 0;
 
-       for (i = 1; i < hdr->e_shnum; i++) {
-
-               if (sechdrs[i].sh_type != SHT_NOBITS
-                   && len < sechdrs[i].sh_offset + sechdrs[i].sh_size) {
-                       printk(KERN_ERR "VPE program length %u truncated\n",
-                              len);
-                       return -ENOEXEC;
-               }
+       if (relocate) {
+               for (i = 1; i < hdr->e_shnum; i++) {
+                       if (sechdrs[i].sh_type != SHT_NOBITS
+                           && len < sechdrs[i].sh_offset + sechdrs[i].sh_size) {
+                               printk(KERN_ERR "VPE program length %u truncated\n",
+                                      len);
+                               return -ENOEXEC;
+                       }
 
-               /* Mark all sections sh_addr with their address in the
-                  temporary image. */
-               sechdrs[i].sh_addr = (size_t) hdr + sechdrs[i].sh_offset;
+                       /* Mark all sections sh_addr with their address in the
+                          temporary image. */
+                       sechdrs[i].sh_addr = (size_t) hdr + sechdrs[i].sh_offset;
 
-               /* Internal symbols and strings. */
-               if (sechdrs[i].sh_type == SHT_SYMTAB) {
-                       symindex = i;
-                       strindex = sechdrs[i].sh_link;
-                       strtab = (char *)hdr + sechdrs[strindex].sh_offset;
+                       /* Internal symbols and strings. */
+                       if (sechdrs[i].sh_type == SHT_SYMTAB) {
+                               symindex = i;
+                               strindex = sechdrs[i].sh_link;
+                               strtab = (char *)hdr + sechdrs[strindex].sh_offset;
+                       }
                }
+               layout_sections(&mod, hdr, sechdrs, secstrings);
        }
 
-       layout_sections(&mod, hdr, sechdrs, secstrings);
-
        v->load_addr = alloc_progmem(mod.core_size);
        memset(v->load_addr, 0, mod.core_size);
 
-       printk("VPE elf_loader: loading to %p\n", v->load_addr);
+       printk("VPE loader: loading to %p\n", v->load_addr);
 
-       for (i = 0; i < hdr->e_shnum; i++) {
-               void *dest;
+       if (relocate) {
+               for (i = 0; i < hdr->e_shnum; i++) {
+                       void *dest;
 
-               if (!(sechdrs[i].sh_flags & SHF_ALLOC))
-                       continue;
+                       if (!(sechdrs[i].sh_flags & SHF_ALLOC))
+                               continue;
 
-               dest = v->load_addr + sechdrs[i].sh_entsize;
+                       dest = v->load_addr + sechdrs[i].sh_entsize;
 
-               if (sechdrs[i].sh_type != SHT_NOBITS)
-                       memcpy(dest, (void *)sechdrs[i].sh_addr,
-                              sechdrs[i].sh_size);
-               /* Update sh_addr to point to copy in image. */
-               sechdrs[i].sh_addr = (unsigned long)dest;
-       }
+                       if (sechdrs[i].sh_type != SHT_NOBITS)
+                               memcpy(dest, (void *)sechdrs[i].sh_addr,
+                                      sechdrs[i].sh_size);
+                       /* Update sh_addr to point to copy in image. */
+                       sechdrs[i].sh_addr = (unsigned long)dest;
 
-       /* Fix up syms, so that st_value is a pointer to location. */
-       err =
-               simplify_symbols(sechdrs, symindex, strtab, secstrings,
-                                hdr->e_shnum, &mod);
-       if (err < 0) {
-               printk(KERN_WARNING "VPE: unable to simplify symbols\n");
-               goto cleanup;
-       }
+                       printk(KERN_DEBUG " section sh_name %s sh_addr 0x%x\n",
+                              secstrings + sechdrs[i].sh_name, sechdrs[i].sh_addr);
+               }
 
-       /* Now do relocations. */
-       for (i = 1; i < hdr->e_shnum; i++) {
-               const char *strtab = (char *)sechdrs[strindex].sh_addr;
-               unsigned int info = sechdrs[i].sh_info;
-
-               /* Not a valid relocation section? */
-               if (info >= hdr->e_shnum)
-                       continue;
-
-               /* Don't bother with non-allocated sections */
-               if (!(sechdrs[info].sh_flags & SHF_ALLOC))
-                       continue;
-
-               if (sechdrs[i].sh_type == SHT_REL)
-                       err =
-                               apply_relocations(sechdrs, strtab, symindex, i, &mod);
-               else if (sechdrs[i].sh_type == SHT_RELA)
-                       err = apply_relocate_add(sechdrs, strtab, symindex, i,
-                                                &mod);
-               if (err < 0) {
-                       printk(KERN_WARNING
-                              "vpe_elfload: error in relocations err %ld\n",
-                              err);
-                       goto cleanup;
+               /* Fix up syms, so that st_value is a pointer to location. */
+               simplify_symbols(sechdrs, symindex, strtab, secstrings,
+                                hdr->e_shnum, &mod);
+
+               /* Now do relocations. */
+               for (i = 1; i < hdr->e_shnum; i++) {
+                       const char *strtab = (char *)sechdrs[strindex].sh_addr;
+                       unsigned int info = sechdrs[i].sh_info;
+
+                       /* Not a valid relocation section? */
+                       if (info >= hdr->e_shnum)
+                               continue;
+
+                       /* Don't bother with non-allocated sections */
+                       if (!(sechdrs[info].sh_flags & SHF_ALLOC))
+                               continue;
+
+                       if (sechdrs[i].sh_type == SHT_REL)
+                               err = apply_relocations(sechdrs, strtab, symindex, i,
+                                                       &mod);
+                       else if (sechdrs[i].sh_type == SHT_RELA)
+                               err = apply_relocate_add(sechdrs, strtab, symindex, i,
+                                                        &mod);
+                       if (err < 0)
+                               return err;
+
+               }
+       } else {
+               for (i = 0; i < hdr->e_shnum; i++) {
+
+                       /* Internal symbols and strings. */
+                       if (sechdrs[i].sh_type == SHT_SYMTAB) {
+                               symindex = i;
+                               strindex = sechdrs[i].sh_link;
+                               strtab = (char *)hdr + sechdrs[strindex].sh_offset;
+
+                               /* mark the symtab's address for when we try to find the
+                                  magic symbols */
+                               sechdrs[i].sh_addr = (size_t) hdr + sechdrs[i].sh_offset;
+                       }
+
+                       /* filter sections we dont want in the final image */
+                       if (!(sechdrs[i].sh_flags & SHF_ALLOC) ||
+                           (sechdrs[i].sh_type == SHT_MIPS_REGINFO)) {
+                               printk( KERN_DEBUG " ignoring section, "
+                                       "name %s type %x address 0x%x \n",
+                                       secstrings + sechdrs[i].sh_name,
+                                       sechdrs[i].sh_type, sechdrs[i].sh_addr);
+                               continue;
+                       }
+
+                       if (sechdrs[i].sh_addr < (unsigned int)v->load_addr) {
+                               printk( KERN_WARNING "VPE loader: "
+                                       "fully linked image has invalid section, "
+                                       "name %s type %x address 0x%x, before load "
+                                       "address of 0x%x\n",
+                                       secstrings + sechdrs[i].sh_name,
+                                       sechdrs[i].sh_type, sechdrs[i].sh_addr,
+                                       (unsigned int)v->load_addr);
+                               return -ENOEXEC;
+                       }
+
+                       printk(KERN_DEBUG " copying section sh_name %s, sh_addr 0x%x "
+                              "size 0x%x0 from x%p\n",
+                              secstrings + sechdrs[i].sh_name, sechdrs[i].sh_addr,
+                              sechdrs[i].sh_size, hdr + sechdrs[i].sh_offset);
+
+                       if (sechdrs[i].sh_type != SHT_NOBITS)
+                               memcpy((void *)sechdrs[i].sh_addr,
+                                      (char *)hdr + sechdrs[i].sh_offset,
+                                      sechdrs[i].sh_size);
+                       else
+                               memset((void *)sechdrs[i].sh_addr, 0, sechdrs[i].sh_size);
                }
        }
 
@@ -910,71 +997,104 @@ int vpe_elfload(struct vpe * v)
                           (unsigned long)v->load_addr + v->len);
 
        if ((find_vpe_symbols(v, sechdrs, symindex, strtab, &mod)) < 0) {
+               if (v->__start == 0) {
+                       printk(KERN_WARNING "VPE loader: program does not contain "
+                              "a __start symbol\n");
+                       return -ENOEXEC;
+               }
 
-               printk(KERN_WARNING
-                      "VPE: program doesn't contain __start or vpe_shared symbols\n");
-               err = -ENOEXEC;
+               if (v->shared_ptr == NULL)
+                       printk(KERN_WARNING "VPE loader: "
+                              "program does not contain vpe_shared symbol.\n"
+                              " Unable to use AMVP (AP/SP) facilities.\n");
        }
 
        printk(" elf loaded\n");
-
-cleanup:
-       return err;
+       return 0;
 }
 
-static void dump_vpe(struct vpe * v)
+__attribute_used__ void dump_vpe(struct vpe * v)
 {
        struct tc *t;
 
+       settc(v->minor);
+
        printk(KERN_DEBUG "VPEControl 0x%lx\n", read_vpe_c0_vpecontrol());
        printk(KERN_DEBUG "VPEConf0 0x%lx\n", read_vpe_c0_vpeconf0());
 
-       list_for_each_entry(t, &vpecontrol.tc_list, list) {
+       list_for_each_entry(t, &vpecontrol.tc_list, list)
                dump_tc(t);
-       }
 }
 
-/* checks for VPE is unused and gets ready to load program      */
+static void cleanup_tc(struct tc *tc)
+{
+       int tmp;
+
+       /* Put MVPE's into 'configuration state' */
+       set_c0_mvpcontrol(MVPCONTROL_VPC);
+
+       settc(tc->index);
+       tmp = read_tc_c0_tcstatus();
+
+       /* mark not allocated and not dynamically allocatable */
+       tmp &= ~(TCSTATUS_A | TCSTATUS_DA);
+       tmp |= TCSTATUS_IXMT;   /* interrupt exempt */
+       write_tc_c0_tcstatus(tmp);
+
+       write_tc_c0_tchalt(TCHALT_H);
+
+       /* bind it to anything other than VPE1 */
+       write_tc_c0_tcbind(read_tc_c0_tcbind() & ~TCBIND_CURVPE); // | TCBIND_CURVPE
+
+       clear_c0_mvpcontrol(MVPCONTROL_VPC);
+}
+
+static int getcwd(char *buff, int size)
+{
+       mm_segment_t old_fs;
+       int ret;
+
+       old_fs = get_fs();
+       set_fs(KERNEL_DS);
+
+       ret = sys_getcwd(buff,size);
+
+       set_fs(old_fs);
+
+       return ret;
+}
+
+/* checks VPE is unused and gets ready to load program  */
 static int vpe_open(struct inode *inode, struct file *filp)
 {
-       int minor;
+       int minor, ret;
        struct vpe *v;
+       struct vpe_notifications *not;
 
        /* assume only 1 device at the mo. */
        if ((minor = MINOR(inode->i_rdev)) != 1) {
-               printk(KERN_WARNING "VPE: only vpe1 is supported\n");
+               printk(KERN_WARNING "VPE loader: only vpe1 is supported\n");
                return -ENODEV;
        }
 
        if ((v = get_vpe(minor)) == NULL) {
-               printk(KERN_WARNING "VPE: unable to get vpe\n");
+               printk(KERN_WARNING "VPE loader: unable to get vpe\n");
                return -ENODEV;
        }
 
        if (v->state != VPE_STATE_UNUSED) {
-               unsigned long tmp;
-               struct tc *t;
-
-               printk(KERN_WARNING "VPE: device %d already in use\n", minor);
-
                dvpe();
-               dump_vpe(v);
-
-               printk(KERN_WARNING "VPE: re-initialising %d\n", minor);
-
-               release_progmem(v->load_addr);
 
-               t = get_tc(minor);
-               settc(minor);
-               tmp = read_tc_c0_tcstatus();
+               printk(KERN_DEBUG "VPE loader: tc in use dumping regs\n");
 
-               /* mark not allocated and not dynamically allocatable */
-               tmp &= ~(TCSTATUS_A | TCSTATUS_DA);
-               tmp |= TCSTATUS_IXMT;   /* interrupt exempt */
-               write_tc_c0_tcstatus(tmp);
+               dump_tc(get_tc(minor));
 
-               write_tc_c0_tchalt(TCHALT_H);
+               list_for_each_entry(not, &v->notify, list) {
+                       not->stop(minor);
+               }
 
+               release_progmem(v->load_addr);
+               cleanup_tc(get_tc(minor));
        }
 
        // allocate it so when we get write ops we know it's expected.
@@ -986,6 +1106,24 @@ static int vpe_open(struct inode *inode, struct file *filp)
        v->load_addr = NULL;
        v->len = 0;
 
+       v->uid = filp->f_uid;
+       v->gid = filp->f_gid;
+
+#ifdef CONFIG_MIPS_APSP_KSPD
+       /* get kspd to tell us when a syscall_exit happens */
+       if (!kspd_events_reqd) {
+               kspd_notify(&kspd_events);
+               kspd_events_reqd++;
+       }
+#endif
+
+       v->cwd[0] = 0;
+       ret = getcwd(v->cwd, VPE_PATH_MAX);
+       if (ret < 0)
+               printk(KERN_WARNING "VPE loader: open, getcwd returned %d\n", ret);
+
+       v->shared_ptr = NULL;
+       v->__start = 0;
        return 0;
 }
 
@@ -1006,14 +1144,22 @@ static int vpe_release(struct inode *inode, struct file *filp)
                if (vpe_elfload(v) >= 0)
                        vpe_run(v);
                else {
-                       printk(KERN_WARNING "VPE: ELF load failed.\n");
+                       printk(KERN_WARNING "VPE loader: ELF load failed.\n");
                        ret = -ENOEXEC;
                }
        } else {
-               printk(KERN_WARNING "VPE: only elf files are supported\n");
+               printk(KERN_WARNING "VPE loader: only elf files are supported\n");
                ret = -ENOEXEC;
        }
 
+       /* It's good to be able to run the SP and if it chokes have a look at
+          the /dev/rt?. But if we reset the pointer to the shared struct we
+          loose what has happened. So perhaps if garbage is sent to the vpe
+          device, use it as a trigger for the reset. Hopefully a nice
+          executable will be along shortly. */
+       if (ret < 0)
+               v->shared_ptr = NULL;
+
        // cleanup any temp buffers
        if (v->pbuffer)
                vfree(v->pbuffer);
@@ -1033,21 +1179,19 @@ static ssize_t vpe_write(struct file *file, const char __user * buffer,
                return -ENODEV;
 
        if (v->pbuffer == NULL) {
-               printk(KERN_ERR "vpe_write: no pbuffer\n");
+               printk(KERN_ERR "VPE loader: no buffer for program\n");
                return -ENOMEM;
        }
 
        if ((count + v->len) > v->plen) {
                printk(KERN_WARNING
-                      "VPE Loader: elf size too big. Perhaps strip uneeded symbols\n");
+                      "VPE loader: elf size too big. Perhaps strip uneeded symbols\n");
                return -ENOMEM;
        }
 
        count -= copy_from_user(v->pbuffer + v->len, buffer, count);
-       if (!count) {
-               printk("vpe_write: copy_to_user failed\n");
+       if (!count)
                return -EFAULT;
-       }
 
        v->len += count;
        return ret;
@@ -1149,16 +1293,70 @@ void *vpe_get_shared(int index)
 {
        struct vpe *v;
 
-       if ((v = get_vpe(index)) == NULL) {
-               printk(KERN_WARNING "vpe: invalid vpe index %d\n", index);
+       if ((v = get_vpe(index)) == NULL)
                return NULL;
-       }
 
        return v->shared_ptr;
 }
 
 EXPORT_SYMBOL(vpe_get_shared);
 
+int vpe_getuid(int index)
+{
+       struct vpe *v;
+
+       if ((v = get_vpe(index)) == NULL)
+               return -1;
+
+       return v->uid;
+}
+
+EXPORT_SYMBOL(vpe_getuid);
+
+int vpe_getgid(int index)
+{
+       struct vpe *v;
+
+       if ((v = get_vpe(index)) == NULL)
+               return -1;
+
+       return v->gid;
+}
+
+EXPORT_SYMBOL(vpe_getgid);
+
+int vpe_notify(int index, struct vpe_notifications *notify)
+{
+       struct vpe *v;
+
+       if ((v = get_vpe(index)) == NULL)
+               return -1;
+
+       list_add(&notify->list, &v->notify);
+       return 0;
+}
+
+EXPORT_SYMBOL(vpe_notify);
+
+char *vpe_getcwd(int index)
+{
+       struct vpe *v;
+
+       if ((v = get_vpe(index)) == NULL)
+               return NULL;
+
+       return v->cwd;
+}
+
+EXPORT_SYMBOL(vpe_getcwd);
+
+#ifdef CONFIG_MIPS_APSP_KSPD
+static void kspd_sp_exit( int sp_id)
+{
+       cleanup_tc(get_tc(sp_id));
+}
+#endif
+
 static int __init vpe_module_init(void)
 {
        struct vpe *v = NULL;
@@ -1201,7 +1399,8 @@ static int __init vpe_module_init(void)
                                return -ENODEV;
                        }
 
-                       list_add(&t->tc, &v->tc);       /* add the tc to the list of this vpe's tc's. */
+                       /* add the tc to the list of this vpe's tc's. */
+                       list_add(&t->tc, &v->tc);
 
                        /* deactivate all but vpe0 */
                        if (i != 0) {
@@ -1222,10 +1421,12 @@ static int __init vpe_module_init(void)
                                                     ~(ST0_IM | ST0_IE | ST0_KSU))
                                                    | ST0_CU0);
 
-                               /* set config to be the same as vpe0, particularly kseg0 coherency alg */
+                               /*
+                                * Set config to be the same as vpe0,
+                                * particularly kseg0 coherency alg
+                                */
                                write_vpe_c0_config(read_c0_config());
                        }
-
                }
 
                /* TC's */
@@ -1234,23 +1435,28 @@ static int __init vpe_module_init(void)
                if (i != 0) {
                        unsigned long tmp;
 
-                       /* tc 0 will of course be running.... */
-                       if (i == 0)
-                               t->state = TC_STATE_RUNNING;
-
                        settc(i);
 
-                       /* bind a TC to each VPE, May as well put all excess TC's
-                          on the last VPE */
-                       if (i >= (((val & MVPCONF0_PVPE) >> MVPCONF0_PVPE_SHIFT) + 1))
-                               write_tc_c0_tcbind(read_tc_c0_tcbind() |
-                                                  ((val & MVPCONF0_PVPE) >> MVPCONF0_PVPE_SHIFT));
-                       else
-                               write_tc_c0_tcbind(read_tc_c0_tcbind() | i);
+                       /* Any TC that is bound to VPE0 gets left as is - in case
+                          we are running SMTC on VPE0. A TC that is bound to any
+                          other VPE gets bound to VPE0, ideally I'd like to make
+                          it homeless but it doesn't appear to let me bind a TC
+                          to a non-existent VPE. Which is perfectly reasonable.
+
+                          The (un)bound state is visible to an EJTAG probe so may
+                          notify GDB...
+                       */
+
+                       if (((tmp = read_tc_c0_tcbind()) & TCBIND_CURVPE)) {
+                               /* tc is bound >vpe0 */
+                               write_tc_c0_tcbind(tmp & ~TCBIND_CURVPE);
+
+                               t->pvpe = get_vpe(0);   /* set the parent vpe */
+                       }
 
                        tmp = read_tc_c0_tcstatus();
 
-                       /* mark not allocated and not dynamically allocatable */
+                       /* mark not activated and not dynamically allocatable */
                        tmp &= ~(TCSTATUS_A | TCSTATUS_DA);
                        tmp |= TCSTATUS_IXMT;   /* interrupt exempt */
                        write_tc_c0_tcstatus(tmp);
@@ -1262,6 +1468,9 @@ static int __init vpe_module_init(void)
        /* release config state */
        clear_c0_mvpcontrol(MVPCONTROL_VPC);
 
+#ifdef CONFIG_MIPS_APSP_KSPD
+       kspd_events.kspd_sp_exit = kspd_sp_exit;
+#endif
        return 0;
 }
 
@@ -1281,5 +1490,5 @@ static void __exit vpe_module_exit(void)
 module_init(vpe_module_init);
 module_exit(vpe_module_exit);
 MODULE_DESCRIPTION("MIPS VPE Loader");
-MODULE_AUTHOR("Elizabeth Clarke, MIPS Technologies, Inc");
+MODULE_AUTHOR("Elizabeth Oldham, MIPS Technologies, Inc.");
 MODULE_LICENSE("GPL");
index 0d5aec436725678eb99212db7c848c907ccb9e45..99f5046fdf4938bdc5558920feaaf67a5d43bc10 100644 (file)
@@ -3,7 +3,7 @@
 #
 
 obj-y                          += reset.o setup.o prom.o lasat_board.o \
-                                  at93c.o interrupt.o lasatIRQ.o
+                                  at93c.o interrupt.o
 
 obj-$(CONFIG_LASAT_SYSCTL)     += sysctl.o
 obj-$(CONFIG_DS1603)           += ds1603.o
index 852a41901a5e623eae2eb1b1eadec7e7699182b6..2d3472b21ebbe3ad62b98ff3046380b0039107a3 100644 (file)
 #include <asm/bootinfo.h>
 #include <asm/irq.h>
 #include <asm/lasat/lasatint.h>
+#include <asm/time.h>
 #include <asm/gdb-stub.h>
 
 static volatile int *lasat_int_status = NULL;
 static volatile int *lasat_int_mask = NULL;
 static volatile int lasat_int_mask_shift;
 
-extern asmlinkage void lasatIRQ(void);
-
 void disable_lasat_irq(unsigned int irq_nr)
 {
        unsigned long flags;
@@ -109,11 +108,17 @@ static unsigned long get_int_status_200(void)
        return int_status;
 }
 
-void lasat_hw0_irqdispatch(struct pt_regs *regs)
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
 {
        unsigned long int_status;
+       unsigned int cause = read_c0_cause();
        int irq;
 
+       if (cause & CAUSEF_IP7) {       /* R4000 count / compare IRQ */
+               ll_timer_interrupt(7, regs);
+               return;
+       }
+
        int_status = get_int_status();
 
        /* if int_status == 0, then the interrupt has already been cleared */
@@ -147,9 +152,6 @@ void __init arch_init_irq(void)
                panic("arch_init_irq: mips_machtype incorrect");
        }
 
-       /* Now safe to set the exception vector. */
-       set_except_vector(0, lasatIRQ);
-
        for (i = 0; i <= LASATINT_END; i++) {
                irq_desc[i].status      = IRQ_DISABLED;
                irq_desc[i].action      = 0;
diff --git a/arch/mips/lasat/lasatIRQ.S b/arch/mips/lasat/lasatIRQ.S
deleted file mode 100644 (file)
index 2a2b0d0..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Carsten Langgaard, carstenl@mips.com
- * Copyright (C) 1999, 2000 MIPS Technologies, Inc.  All rights reserved.
- *
- *  This program is free software; you can distribute it and/or modify it
- *  under the terms of the GNU General Public License (Version 2) as
- *  published by the Free Software Foundation.
- *
- *  This program is distributed in the hope 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.
- *
- * Interrupt exception dispatch code.
- */
-#include <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-
-       .text
-       .set    noreorder
-       .align  5
-       NESTED(lasatIRQ, PT_SIZE, sp)
-       .set    noat
-       SAVE_ALL
-       CLI
-       .set    at
-       .set    noreorder
-
-       mfc0    s0, CP0_CAUSE           # get irq mask
-
-       /* First we check for r4k counter/timer IRQ. */
-       andi    a0, s0, CAUSEF_IP7
-       beq     a0, zero, 1f
-        andi   a0, s0, CAUSEF_IP2      # delay slot, check hw0 interrupt
-
-       /* Wheee, a timer interrupt. */
-       li      a0, 7
-       jal     ll_timer_interrupt
-        move   a1, sp
-
-       j       ret_from_irq
-        nop
-
-1:
-       /* Wheee, combined hardware level zero interrupt. */
-       jal     lasat_hw0_irqdispatch
-        move   a0, sp                  # delay slot
-
-       j       ret_from_irq
-        nop                            # delay slot
-
-1:
-       /*
-        * Here by mistake?  This is possible, what can happen is that by the
-        * time we take the exception the IRQ pin goes low, so just leave if
-        * this is the case.
-        */
-       move    a1,s0
-       mfc0    a1, CP0_EPC
-
-       j       ret_from_irq
-        nop
-       END(lasatIRQ)
index bc0ebc69bfb3f4b9a2078bbb31c71a437f1558f0..db53950b7cfbae7bd9e8936ede6fd6f6f5c64882 100644 (file)
@@ -39,8 +39,6 @@
 
 static struct atlas_ictrl_regs *atlas_hw0_icregs;
 
-extern asmlinkage void mipsIRQ(void);
-
 #if 0
 #define DEBUG_INT(x...) printk(x)
 #else
@@ -98,7 +96,7 @@ static inline int ls1bit32(unsigned int x)
        return b;
 }
 
-void atlas_hw0_irqdispatch(struct pt_regs *regs)
+static inline void atlas_hw0_irqdispatch(struct pt_regs *regs)
 {
        unsigned long int_status;
        int irq;
@@ -116,6 +114,91 @@ void atlas_hw0_irqdispatch(struct pt_regs *regs)
        do_IRQ(irq, regs);
 }
 
+static inline int clz(unsigned long x)
+{
+       __asm__ (
+       "       .set    push                                    \n"
+       "       .set    mips32                                  \n"
+       "       clz     %0, %1                                  \n"
+       "       .set    pop                                     \n"
+       : "=r" (x)
+       : "r" (x));
+
+       return x;
+}
+
+/*
+ * Version of ffs that only looks at bits 12..15.
+ */
+static inline unsigned int irq_ffs(unsigned int pending)
+{
+#if defined(CONFIG_CPU_MIPS32) || defined(CONFIG_CPU_MIPS64)
+       return -clz(pending) + 31 - CAUSEB_IP;
+#else
+       unsigned int a0 = 7;
+       unsigned int t0;
+
+       t0 = s0 & 0xf000;
+       t0 = t0 < 1;
+       t0 = t0 << 2;
+       a0 = a0 - t0;
+       s0 = s0 << t0;
+
+       t0 = s0 & 0xc000;
+       t0 = t0 < 1;
+       t0 = t0 << 1;
+       a0 = a0 - t0;
+       s0 = s0 << t0;
+
+       t0 = s0 & 0x8000;
+       t0 = t0 < 1;
+       //t0 = t0 << 2;
+       a0 = a0 - t0;
+       //s0 = s0 << t0;
+
+       return a0;
+#endif
+}
+
+/*
+ * IRQs on the Atlas board look basically (barring software IRQs which we
+ * don't use at all and all external interrupt sources are combined together
+ * on hardware interrupt 0 (MIPS IRQ 2)) like:
+ *
+ *     MIPS IRQ        Source
+ *      --------        ------
+ *             0       Software (ignored)
+ *             1        Software (ignored)
+ *             2        Combined hardware interrupt (hw0)
+ *             3        Hardware (ignored)
+ *             4        Hardware (ignored)
+ *             5        Hardware (ignored)
+ *             6        Hardware (ignored)
+ *             7        R4k timer (what we use)
+ *
+ * We handle the IRQ according to _our_ priority which is:
+ *
+ * Highest ----     R4k Timer
+ * Lowest  ----     Combined hardware interrupt
+ *
+ * then we just return, if multiple IRQs are pending then we will just take
+ * another exception, big deal.
+ */
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+       unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM;
+       int irq;
+
+       irq = irq_ffs(pending);
+
+       if (irq == MIPSCPU_INT_ATLAS)
+               atlas_hw0_irqdispatch(regs);
+       else if (irq > 0)
+               do_IRQ(MIPSCPU_INT_BASE + irq, regs);
+       else
+               spurious_interrupt(regs);
+}
+
 void __init arch_init_irq(void)
 {
        int i;
@@ -128,9 +211,6 @@ void __init arch_init_irq(void)
         */
        atlas_hw0_icregs->intrsten = 0xffffffff;
 
-       /* Now safe to set the exception vector. */
-       set_except_vector(0, mipsIRQ);
-
        for (i = ATLASINT_BASE; i <= ATLASINT_END; i++) {
                irq_desc[i].status      = IRQ_DISABLED;
                irq_desc[i].action      = 0;
index b21bc6887fa8f45c7ea298a7898dae1cdba14d01..be47c1c2bc8020f33726c620749a28ac2e48315f 100644 (file)
@@ -18,8 +18,8 @@
 # Makefile for the MIPS boards generic routines under Linux.
 #
 
-obj-y                          := mipsIRQ.o reset.o display.o init.o memory.o \
-                                  printf.o cmdline.o time.o
+obj-y                          := reset.o display.o init.o memory.o printf.o \
+                                  cmdline.o time.o
 obj-$(CONFIG_PCI)              += pci.o
 obj-$(CONFIG_KGDB)             += gdb_hook.o
 
index 91a2ccbe3730e3cfafd15908f0b8e1d766755b6d..6a1854de45799e40d91efa03f8385eecdbdb617b 100644 (file)
@@ -25,7 +25,7 @@
 #include <asm/serial.h>
 #include <asm/io.h>
 
-static struct serial_state rs_table[RS_TABLE_SIZE] = {
+static struct serial_state rs_table[] = {
        SERIAL_PORT_DFNS        /* Defined in serial.h */
 };
 
index eab5a705e9892732635938f393690ed1c514eda1..17dfe6a8cab9b38b9b3620217953c57c6a118406 100644 (file)
@@ -220,7 +220,6 @@ void __init kgdb_config (void)
                                generic_putDebugChar (*s++);
                }
 
-               kgdb_enabled = 1;
                /* Breakpoint is invoked after interrupts are initialised */
        }
 }
index 32c9210373ac864e5faab2c8789dff848f3c5322..bc4d093685bbec8725ab448723700f691b8d3ac8 100644 (file)
 #include <linux/init.h>
 #include <linux/mm.h>
 #include <linux/bootmem.h>
+#include <linux/pfn.h>
 #include <linux/string.h>
 
 #include <asm/bootinfo.h>
 #include <asm/page.h>
+#include <asm/sections.h>
 
 #include <asm/mips-boards/prom.h>
 
@@ -46,9 +48,6 @@ static char *mtypes[3] = {
 };
 #endif
 
-/* References to section boundaries */
-extern char _end;
-
 struct prom_pmemblock * __init prom_getmdesc(void)
 {
        char *memsize_str;
@@ -106,10 +105,10 @@ struct prom_pmemblock * __init prom_getmdesc(void)
 
        mdesc[3].type = yamon_dontuse;
        mdesc[3].base = 0x00100000;
-       mdesc[3].size = CPHYSADDR(PAGE_ALIGN(&_end)) - mdesc[3].base;
+       mdesc[3].size = CPHYSADDR(PFN_ALIGN((unsigned long)&_end)) - mdesc[3].base;
 
        mdesc[4].type = yamon_free;
-       mdesc[4].base = CPHYSADDR(PAGE_ALIGN(&_end));
+       mdesc[4].base = CPHYSADDR(PFN_ALIGN(&_end));
        mdesc[4].size = memsize - mdesc[4].base;
 
        return &mdesc[0];
diff --git a/arch/mips/mips-boards/generic/mipsIRQ.S b/arch/mips/mips-boards/generic/mipsIRQ.S
deleted file mode 100644 (file)
index ddd5c73..0000000
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * Carsten Langgaard, carstenl@mips.com
- * Copyright (C) 1999, 2000 MIPS Technologies, Inc.  All rights reserved.
- *
- * ########################################################################
- *
- *  This program is free software; you can distribute it and/or modify it
- *  under the terms of the GNU General Public License (Version 2) as
- *  published by the Free Software Foundation.
- *
- *  This program is distributed in the hope 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.
- *
- * ########################################################################
- *
- * Interrupt exception dispatch code.
- *
- */
-#include <linux/config.h>
-
-#include <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-
-#ifdef CONFIG_MIPS_ATLAS
-#include <asm/mips-boards/atlasint.h>
-#define CASCADE_IRQ            MIPSCPU_INT_ATLAS
-#define CASCADE_DISPATCH       atlas_hw0_irqdispatch
-#endif
-#ifdef CONFIG_MIPS_MALTA
-#include <asm/mips-boards/maltaint.h>
-#define CASCADE_IRQ            MIPSCPU_INT_I8259A
-#define CASCADE_DISPATCH       malta_hw0_irqdispatch
-#endif
-#ifdef CONFIG_MIPS_SEAD
-#include <asm/mips-boards/seadint.h>
-#endif
-
-/* A lot of complication here is taken away because:
- *
- * 1) We handle one interrupt and return, sitting in a loop and moving across
- *    all the pending IRQ bits in the cause register is _NOT_ the answer, the
- *    common case is one pending IRQ so optimize in that direction.
- *
- * 2) We need not check against bits in the status register IRQ mask, that
- *    would make this routine slow as hell.
- *
- * 3) Linux only thinks in terms of all IRQs on or all IRQs off, nothing in
- *    between like BSD spl() brain-damage.
- *
- * Furthermore, the IRQs on the MIPS board look basically (barring software
- * IRQs which we don't use at all and all external interrupt sources are
- * combined together on hardware interrupt 0 (MIPS IRQ 2)) like:
- *
- *     MIPS IRQ        Source
- *      --------        ------
- *             0       Software (ignored)
- *             1        Software (ignored)
- *             2        Combined hardware interrupt (hw0)
- *             3        Hardware (ignored)
- *             4        Hardware (ignored)
- *             5        Hardware (ignored)
- *             6        Hardware (ignored)
- *             7        R4k timer (what we use)
- *
- * Note: On the SEAD board thing are a little bit different.
- *       Here IRQ 2 (hw0) is wired to the UART0 and IRQ 3 (hw1) is wired
- *       wired to UART1.
- *
- * We handle the IRQ according to _our_ priority which is:
- *
- * Highest ----     R4k Timer
- * Lowest  ----     Combined hardware interrupt
- *
- * then we just return, if multiple IRQs are pending then we will just take
- * another exception, big deal.
- */
-
-       .text
-       .set    noreorder
-       .set    noat
-       .align  5
-       NESTED(mipsIRQ, PT_SIZE, sp)
-       SAVE_ALL
-       CLI
-       .set    at
-
-       mfc0    s0, CP0_CAUSE           # get irq bits
-       mfc0    s1, CP0_STATUS          # get irq mask
-       andi    s0, ST0_IM              # CAUSE.CE may be non-zero!
-       and     s0, s1
-
-#if defined(CONFIG_CPU_MIPS32) || defined(CONFIG_CPU_MIPS64)
-       .set    mips32
-       clz     a0, s0
-       .set    mips0
-       negu    a0
-       addu    a0, 31-CAUSEB_IP
-       bltz    a0, spurious
-#else
-       beqz    s0, spurious
-        li     a0, 7
-
-       and     t0, s0, 0xf000
-       sltiu   t0, t0, 1
-       sll     t0, 2
-       subu    a0, t0
-       sll     s0, t0
-
-       and     t0, s0, 0xc000
-       sltiu   t0, t0, 1
-       sll     t0, 1
-       subu    a0, t0
-       sll     s0, t0
-
-       and     t0, s0, 0x8000
-       sltiu   t0, t0, 1
-       # sll   t0, 0
-       subu    a0, t0
-       # sll   s0, t0
-#endif
-
-#ifdef CASCADE_IRQ
-        li     a1, CASCADE_IRQ
-       bne     a0, a1, 1f
-        addu   a0, MIPSCPU_INT_BASE
-
-       jal     CASCADE_DISPATCH
-        move    a0, sp
-
-       j       ret_from_irq
-        nop
-1:
-#else
-        addu   a0, MIPSCPU_INT_BASE
-#endif
-
-       jal     do_IRQ
-        move   a1, sp
-
-       j       ret_from_irq
-        nop
-
-
-spurious:
-       j       spurious_interrupt
-        nop
-       END(mipsIRQ)
index 93f3bf2c2b22364217e4fe9ae925b1e36b8470e0..a9f6124b3a227ee722288a5b239ddbfff3f821dc 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/mc146818rtc.h>
 
 #include <asm/mipsregs.h>
+#include <asm/mipsmtregs.h>
 #include <asm/ptrace.h>
 #include <asm/hardirq.h>
 #include <asm/irq.h>
@@ -50,16 +51,23 @@ unsigned long cpu_khz;
 static char display_string[] = "        LINUX ON ATLAS       ";
 #endif
 #if defined(CONFIG_MIPS_MALTA)
+#if defined(CONFIG_MIPS_MT_SMTC)
+static char display_string[] = "       SMTC LINUX ON MALTA       ";
+#else
 static char display_string[] = "        LINUX ON MALTA       ";
+#endif /* CONFIG_MIPS_MT_SMTC */
 #endif
 #if defined(CONFIG_MIPS_SEAD)
 static char display_string[] = "        LINUX ON SEAD       ";
 #endif
-static unsigned int display_count = 0;
+static unsigned int display_count;
 #define MAX_DISPLAY_COUNT (sizeof(display_string) - 8)
 
-static unsigned int timer_tick_count=0;
+#define CPUCTR_IMASKBIT (0x100 << MIPSCPU_INT_CPUCTR)
+
+static unsigned int timer_tick_count;
 static int mips_cpu_timer_irq;
+extern void smtc_timer_broadcast(int);
 
 static inline void scroll_display_message(void)
 {
@@ -75,15 +83,55 @@ static void mips_timer_dispatch (struct pt_regs *regs)
        do_IRQ (mips_cpu_timer_irq, regs);
 }
 
+/*
+ * Redeclare until I get around mopping the timer code insanity on MIPS.
+ */
 extern int null_perf_irq(struct pt_regs *regs);
 
 extern int (*perf_irq)(struct pt_regs *regs);
 
 irqreturn_t mips_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-       int r2 = cpu_has_mips_r2;
        int cpu = smp_processor_id();
+       int r2 = cpu_has_mips_r2;
+
+#ifdef CONFIG_MIPS_MT_SMTC
+        /*
+        *  In an SMTC system, one Count/Compare set exists per VPE.
+        *  Which TC within a VPE gets the interrupt is essentially
+        *  random - we only know that it shouldn't be one with
+        *  IXMT set. Whichever TC gets the interrupt needs to
+        *  send special interprocessor interrupts to the other
+        *  TCs to make sure that they schedule, etc.
+        *
+        *  That code is specific to the SMTC kernel, not to
+        *  the a particular platform, so it's invoked from
+        *  the general MIPS timer_interrupt routine.
+        */
+
+       /*
+        * DVPE is necessary so long as cross-VPE interrupts
+        * are done via read-modify-write of Cause register.
+        */
+       int vpflags = dvpe();
+       write_c0_compare (read_c0_count() - 1);
+       clear_c0_cause(CPUCTR_IMASKBIT);
+       evpe(vpflags);
+
+       if (cpu_data[cpu].vpe_id == 0) {
+               timer_interrupt(irq, dev_id, regs);
+               scroll_display_message();
+       } else
+               write_c0_compare (read_c0_count() + ( mips_hpt_frequency/HZ));
+       smtc_timer_broadcast(cpu_data[cpu].vpe_id);
 
+       if (cpu != 0)
+               /*
+                * Other CPUs should do profiling and process accounting
+                */
+               local_timer_interrupt(irq, dev_id, regs);
+
+#else /* CONFIG_MIPS_MT_SMTC */
        if (cpu == 0) {
                /*
                 * CPU 0 handles the global timer interrupt job and process
@@ -107,12 +155,14 @@ irqreturn_t mips_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
                 * More support needs to be added to kernel/time for
                 * counter/timer interrupts on multiple CPU's
                 */
-               write_c0_compare (read_c0_count() + (mips_hpt_frequency/HZ));
+               write_c0_compare(read_c0_count() + (mips_hpt_frequency/HZ));
+
                /*
-                * other CPUs should do profiling and process accounting
+                * Other CPUs should do profiling and process accounting
                 */
-               local_timer_interrupt (irq, dev_id, regs);
+               local_timer_interrupt(irq, dev_id, regs);
        }
+#endif /* CONFIG_MIPS_MT_SMTC */
 
 out:
        return IRQ_HANDLED;
@@ -126,7 +176,7 @@ static unsigned int __init estimate_cpu_frequency(void)
        unsigned int prid = read_c0_prid() & 0xffff00;
        unsigned int count;
 
-#ifdef CONFIG_MIPS_SEAD
+#if defined(CONFIG_MIPS_SEAD) || defined(CONFIG_MIPS_SIM)
        /*
         * The SEAD board doesn't have a real time clock, so we can't
         * really calculate the timer frequency
@@ -211,7 +261,11 @@ void __init mips_timer_setup(struct irqaction *irq)
 
        /* we are using the cpu counter for timer interrupts */
        irq->handler = mips_timer_interrupt;    /* we use our own handler */
+#ifdef CONFIG_MIPS_MT_SMTC
+       setup_irq_smtc(mips_cpu_timer_irq, irq, CPUCTR_IMASKBIT);
+#else
        setup_irq(mips_cpu_timer_irq, irq);
+#endif /* CONFIG_MIPS_MT_SMTC */
 
 #ifdef CONFIG_SMP
        /* irq_desc(riptor) is a global resource, when the interrupt overlaps
index fd4c143c0e2f712cf0cf8c68e0b70a0fed93a53b..77ee5c6d33c119964da2619f5484cf83772e3b49 100644 (file)
@@ -20,3 +20,4 @@
 #
 
 obj-y := malta_int.o malta_setup.o
+obj-$(CONFIG_SMP) += malta_smp.o
index d06dc5ad6c9e55edd2284540ea01e729f2678d55..64db07d4dbe500d5c3a66355ff1f19c9f6e9ec34 100644 (file)
@@ -40,7 +40,6 @@
 #include <asm/mips-boards/msc01_pci.h>
 #include <asm/msc01_ic.h>
 
-extern asmlinkage void mipsIRQ(void);
 extern void mips_timer_interrupt(void);
 
 static DEFINE_SPINLOCK(mips_irq_lock);
@@ -114,13 +113,14 @@ static inline int get_int(void)
        return irq;
 }
 
-void malta_hw0_irqdispatch(struct pt_regs *regs)
+static void malta_hw0_irqdispatch(struct pt_regs *regs)
 {
        int irq;
 
        irq = get_int();
-       if (irq < 0)
+       if (irq < 0) {
                return;  /* interrupt has already been cleared */
+       }
 
        do_IRQ(MALTA_INT_BASE+irq, regs);
 }
@@ -182,6 +182,92 @@ void corehi_irqdispatch(struct pt_regs *regs)
         die("CoreHi interrupt", regs);
 }
 
+static inline int clz(unsigned long x)
+{
+       __asm__ (
+       "       .set    push                                    \n"
+       "       .set    mips32                                  \n"
+       "       clz     %0, %1                                  \n"
+       "       .set    pop                                     \n"
+       : "=r" (x)
+       : "r" (x));
+
+       return x;
+}
+
+/*
+ * Version of ffs that only looks at bits 12..15.
+ */
+static inline unsigned int irq_ffs(unsigned int pending)
+{
+#if defined(CONFIG_CPU_MIPS32) || defined(CONFIG_CPU_MIPS64)
+       return -clz(pending) + 31 - CAUSEB_IP;
+#else
+       unsigned int a0 = 7;
+       unsigned int t0;
+
+       t0 = s0 & 0xf000;
+       t0 = t0 < 1;
+       t0 = t0 << 2;
+       a0 = a0 - t0;
+       s0 = s0 << t0;
+
+       t0 = s0 & 0xc000;
+       t0 = t0 < 1;
+       t0 = t0 << 1;
+       a0 = a0 - t0;
+       s0 = s0 << t0;
+
+       t0 = s0 & 0x8000;
+       t0 = t0 < 1;
+       //t0 = t0 << 2;
+       a0 = a0 - t0;
+       //s0 = s0 << t0;
+
+       return a0;
+#endif
+}
+
+/*
+ * IRQs on the Malta board look basically (barring software IRQs which we
+ * don't use at all and all external interrupt sources are combined together
+ * on hardware interrupt 0 (MIPS IRQ 2)) like:
+ *
+ *     MIPS IRQ        Source
+ *      --------        ------
+ *             0       Software (ignored)
+ *             1        Software (ignored)
+ *             2        Combined hardware interrupt (hw0)
+ *             3        Hardware (ignored)
+ *             4        Hardware (ignored)
+ *             5        Hardware (ignored)
+ *             6        Hardware (ignored)
+ *             7        R4k timer (what we use)
+ *
+ * We handle the IRQ according to _our_ priority which is:
+ *
+ * Highest ----     R4k Timer
+ * Lowest  ----     Combined hardware interrupt
+ *
+ * then we just return, if multiple IRQs are pending then we will just take
+ * another exception, big deal.
+ */
+
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+       unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM;
+       int irq;
+
+       irq = irq_ffs(pending);
+
+       if (irq == MIPSCPU_INT_I8259A)
+               malta_hw0_irqdispatch(regs);
+       else if (irq > 0)
+               do_IRQ(MIPSCPU_INT_BASE + irq, regs);
+       else
+               spurious_interrupt(regs);
+}
+
 static struct irqaction i8259irq = {
        .handler = no_action,
        .name = "XT-PIC cascade"
@@ -214,7 +300,6 @@ int __initdata msc_nr_eicirqs = sizeof(msc_eicirqmap)/sizeof(msc_irqmap_t);
 
 void __init arch_init_irq(void)
 {
-       set_except_vector(0, mipsIRQ);
        init_i8259_irqs();
 
        if (!cpu_has_veic)
@@ -240,12 +325,17 @@ void __init arch_init_irq(void)
        else if (cpu_has_vint) {
                set_vi_handler (MIPSCPU_INT_I8259A, malta_hw0_irqdispatch);
                set_vi_handler (MIPSCPU_INT_COREHI, corehi_irqdispatch);
-
+#ifdef CONFIG_MIPS_MT_SMTC
+               setup_irq_smtc (MIPSCPU_INT_BASE+MIPSCPU_INT_I8259A, &i8259irq,
+                       (0x100 << MIPSCPU_INT_I8259A));
+               setup_irq_smtc (MIPSCPU_INT_BASE+MIPSCPU_INT_COREHI,
+                       &corehi_irqaction, (0x100 << MIPSCPU_INT_COREHI));
+#else /* Not SMTC */
                setup_irq (MIPSCPU_INT_BASE+MIPSCPU_INT_I8259A, &i8259irq);
                setup_irq (MIPSCPU_INT_BASE+MIPSCPU_INT_COREHI, &corehi_irqaction);
+#endif /* CONFIG_MIPS_MT_SMTC */
        }
        else {
-               set_except_vector(0, mipsIRQ);
                setup_irq (MIPSCPU_INT_BASE+MIPSCPU_INT_I8259A, &i8259irq);
                setup_irq (MIPSCPU_INT_BASE+MIPSCPU_INT_COREHI, &corehi_irqaction);
        }
diff --git a/arch/mips/mips-boards/malta/malta_smp.c b/arch/mips/mips-boards/malta/malta_smp.c
new file mode 100644 (file)
index 0000000..6c6c8ee
--- /dev/null
@@ -0,0 +1,128 @@
+/*
+ * Malta Platform-specific hooks for SMP operation
+ */
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/cpumask.h>
+#include <linux/interrupt.h>
+
+#include <asm/atomic.h>
+#include <asm/cpu.h>
+#include <asm/processor.h>
+#include <asm/system.h>
+#include <asm/hardirq.h>
+#include <asm/mmu_context.h>
+#include <asm/smp.h>
+#ifdef CONFIG_MIPS_MT_SMTC
+#include <asm/smtc_ipi.h>
+#endif /* CONFIG_MIPS_MT_SMTC */
+
+/* VPE/SMP Prototype implements platform interfaces directly */
+#if !defined(CONFIG_MIPS_MT_SMP)
+
+/*
+ * Cause the specified action to be performed on a targeted "CPU"
+ */
+
+void core_send_ipi(int cpu, unsigned int action)
+{
+/* "CPU" may be TC of same VPE, VPE of same CPU, or different CPU */
+#ifdef CONFIG_MIPS_MT_SMTC
+       smtc_send_ipi(cpu, LINUX_SMP_IPI, action);
+#endif /* CONFIG_MIPS_MT_SMTC */
+}
+
+/*
+ * Detect available CPUs/VPEs/TCs and populate phys_cpu_present_map
+ */
+
+void __init prom_build_cpu_map(void)
+{
+       int nextslot;
+
+       /*
+        * As of November, 2004, MIPSsim only simulates one core
+        * at a time.  However, that core may be a MIPS MT core
+        * with multiple virtual processors and thread contexts.
+        */
+
+       if (read_c0_config3() & (1<<2)) {
+               nextslot = mipsmt_build_cpu_map(1);
+       }
+}
+
+/*
+ * Platform "CPU" startup hook
+ */
+
+void prom_boot_secondary(int cpu, struct task_struct *idle)
+{
+#ifdef CONFIG_MIPS_MT_SMTC
+       smtc_boot_secondary(cpu, idle);
+#endif /* CONFIG_MIPS_MT_SMTC */
+}
+
+/*
+ * Post-config but pre-boot cleanup entry point
+ */
+
+void prom_init_secondary(void)
+{
+#ifdef CONFIG_MIPS_MT_SMTC
+        void smtc_init_secondary(void);
+       int myvpe;
+
+       /* Don't enable Malta I/O interrupts (IP2) for secondary VPEs */
+       myvpe = read_c0_tcbind() & TCBIND_CURVPE;
+       if (myvpe != 0) {
+               /* Ideally, this should be done only once per VPE, but... */
+               clear_c0_status(STATUSF_IP2);
+               set_c0_status(STATUSF_IP0 | STATUSF_IP1 | STATUSF_IP3
+                               | STATUSF_IP4 | STATUSF_IP5 | STATUSF_IP6
+                               | STATUSF_IP7);
+       }
+
+        smtc_init_secondary();
+#endif /* CONFIG_MIPS_MT_SMTC */
+}
+
+/*
+ * Platform SMP pre-initialization
+ *
+ * As noted above, we can assume a single CPU for now
+ * but it may be multithreaded.
+ */
+
+void plat_smp_setup(void)
+{
+       if (read_c0_config3() & (1<<2))
+               mipsmt_build_cpu_map(0);
+}
+
+void __init plat_prepare_cpus(unsigned int max_cpus)
+{
+       if (read_c0_config3() & (1<<2))
+               mipsmt_prepare_cpus();
+}
+
+/*
+ * SMP initialization finalization entry point
+ */
+
+void prom_smp_finish(void)
+{
+#ifdef CONFIG_MIPS_MT_SMTC
+       smtc_smp_finish();
+#endif /* CONFIG_MIPS_MT_SMTC */
+}
+
+/*
+ * Hook for after all CPUs are online
+ */
+
+void prom_cpus_done(void)
+{
+}
+
+#endif /* CONFIG_MIPS32R2_MT_SMP */
index 90fda0d9915f6464718c296df52d2111588b2c2c..9168d934c661477d421c784f4569c0cbffc668d3 100644 (file)
 #include <linux/irq.h>
 
 #include <asm/irq_cpu.h>
+#include <asm/mipsregs.h>
 #include <asm/system.h>
 
 #include <asm/mips-boards/seadint.h>
 
-extern asmlinkage void mipsIRQ(void);
+static inline int clz(unsigned long x)
+{
+       __asm__ (
+       "       .set    push                                    \n"
+       "       .set    mips32                                  \n"
+       "       clz     %0, %1                                  \n"
+       "       .set    pop                                     \n"
+       : "=r" (x)
+       : "r" (x));
+
+       return x;
+}
+
+/*
+ * Version of ffs that only looks at bits 12..15.
+ */
+static inline unsigned int irq_ffs(unsigned int pending)
+{
+#if defined(CONFIG_CPU_MIPS32) || defined(CONFIG_CPU_MIPS64)
+       return -clz(pending) + 31 - CAUSEB_IP;
+#else
+       unsigned int a0 = 7;
+       unsigned int t0;
+
+       t0 = s0 & 0xf000;
+       t0 = t0 < 1;
+       t0 = t0 << 2;
+       a0 = a0 - t0;
+       s0 = s0 << t0;
+
+       t0 = s0 & 0xc000;
+       t0 = t0 < 1;
+       t0 = t0 << 1;
+       a0 = a0 - t0;
+       s0 = s0 << t0;
+
+       t0 = s0 & 0x8000;
+       t0 = t0 < 1;
+       //t0 = t0 << 2;
+       a0 = a0 - t0;
+       //s0 = s0 << t0;
+
+       return a0;
+#endif
+}
+
+/*
+ * IRQs on the SEAD board look basically are combined together on hardware
+ * interrupt 0 (MIPS IRQ 2)) like:
+ *
+ *     MIPS IRQ        Source
+ *      --------        ------
+ *             0       Software (ignored)
+ *             1        Software (ignored)
+ *             2        UART0 (hw0)
+ *             3        UART1 (hw1)
+ *             4        Hardware (ignored)
+ *             5        Hardware (ignored)
+ *             6        Hardware (ignored)
+ *             7        R4k timer (what we use)
+ *
+ * We handle the IRQ according to _our_ priority which is:
+ *
+ * Highest ----     R4k Timer
+ * Lowest  ----     Combined hardware interrupt
+ *
+ * then we just return, if multiple IRQs are pending then we will just take
+ * another exception, big deal.
+ */
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+       unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM;
+       int irq;
+
+       irq = irq_ffs(pending);
+
+       if (irq >= 0)
+               do_IRQ(MIPSCPU_INT_BASE + irq, regs);
+       else
+               spurious_interrupt(regs);
+}
 
 void __init arch_init_irq(void)
 {
        mips_cpu_irq_init(MIPSCPU_INT_BASE);
-
-       /* Now safe to set the exception vector. */
-       set_except_vector(0, mipsIRQ);
 }
diff --git a/arch/mips/mips-boards/sim/cmdline.c b/arch/mips/mips-boards/sim/cmdline.c
deleted file mode 100644 (file)
index fef9fbd..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Carsten Langgaard, carstenl@mips.com
- * Copyright (C) 1999,2000 MIPS Technologies, Inc.  All rights reserved.
- *
- * This program is free software; you can distribute it and/or modify it
- * under the terms of the GNU General Public License (Version 2) as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope 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.
- *
- * Kernel command line creation using the prom monitor (YAMON) argc/argv.
- */
-#include <linux/init.h>
-#include <linux/string.h>
-
-#include <asm/bootinfo.h>
-
-extern int prom_argc;
-extern int *_prom_argv;
-
-/*
- * YAMON (32-bit PROM) pass arguments and environment as 32-bit pointer.
- * This macro take care of sign extension.
- */
-#define prom_argv(index) ((char *)(((int *)(int)_prom_argv)[(index)]))
-
-char arcs_cmdline[CL_SIZE];
-
-char * __init prom_getcmdline(void)
-{
-       return &(arcs_cmdline[0]);
-}
-
-
-void  __init prom_init_cmdline(void)
-{
-       char *cp;
-       int actr;
-
-       actr = 1; /* Always ignore argv[0] */
-
-       cp = &(arcs_cmdline[0]);
-       while(actr < prom_argc) {
-               strcpy(cp, prom_argv(actr));
-               cp += strlen(prom_argv(actr));
-               *cp++ = ' ';
-               actr++;
-       }
-       if (cp != &(arcs_cmdline[0])) /* get rid of trailing space */
-               --cp;
-       *cp = '\0';
-}
index 9df37c6fca36ac5815c02d2017ad9566b1515675..c63021a5dc6c8928f216a8c35911ca90f0ec48b9 100644 (file)
@@ -26,8 +26,10 @@ char * __init prom_getcmdline(void)
        return arcs_cmdline;
 }
 
-
 void  __init prom_init_cmdline(void)
 {
-    /* nothing to do */
+       char *cp;
+       cp = arcs_cmdline;
+       /* Get boot line from environment? */
+       *cp = '\0';
 }
index a4d0a2c05031ed5ff5d37136200eb8e367108067..2c15c8efec4e30c8e0bdc27df5e5327c644117b5 100644 (file)
 
 extern void mips_cpu_irq_init(int);
 
-extern asmlinkage void simIRQ(void);
+static inline int clz(unsigned long x)
+{
+       __asm__ (
+       "       .set    push                                    \n"
+       "       .set    mips32                                  \n"
+       "       clz     %0, %1                                  \n"
+       "       .set    pop                                     \n"
+       : "=r" (x)
+       : "r" (x));
+
+       return x;
+}
+
+/*
+ * Version of ffs that only looks at bits 12..15.
+ */
+static inline unsigned int irq_ffs(unsigned int pending)
+{
+#if defined(CONFIG_CPU_MIPS32) || defined(CONFIG_CPU_MIPS64)
+       return -clz(pending) + 31 - CAUSEB_IP;
+#else
+       unsigned int a0 = 7;
+       unsigned int t0;
+
+       t0 = s0 & 0xf000;
+       t0 = t0 < 1;
+       t0 = t0 << 2;
+       a0 = a0 - t0;
+       s0 = s0 << t0;
+
+       t0 = s0 & 0xc000;
+       t0 = t0 < 1;
+       t0 = t0 << 1;
+       a0 = a0 - t0;
+       s0 = s0 << t0;
 
-asmlinkage void sim_hw0_irqdispatch(struct pt_regs *regs)
+       t0 = s0 & 0x8000;
+       t0 = t0 < 1;
+       //t0 = t0 << 2;
+       a0 = a0 - t0;
+       //s0 = s0 << t0;
+
+       return a0;
+#endif
+}
+
+static inline void sim_hw0_irqdispatch(struct pt_regs *regs)
 {
        do_IRQ(2, regs);
 }
 
-void __init arch_init_irq(void)
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
 {
-       /* Now safe to set the exception vector. */
-       set_except_vector(0, simIRQ);
+       unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM;
+       int irq;
+
+       irq = irq_ffs(pending);
 
+       if (irq > 0)
+               do_IRQ(MIPSCPU_INT_BASE + irq, regs);
+       else
+               spurious_interrupt(regs);
+}
+
+void __init arch_init_irq(void)
+{
        mips_cpu_irq_init(MIPSCPU_INT_BASE);
 }
index da52297a221635b839b9537c8ef6a5ad4c8d70c6..d16cf38220763f34f7ef1a52da91cc4be21076b7 100644 (file)
@@ -94,6 +94,8 @@
 
 
 spurious:
-       j       spurious_interrupt
+       jal     spurious_interrupt
+        nop
+       j       ret_from_irq
         nop
        END(simIRQ)
index e57f737bab10265aeb1b46866336ad57651e24ba..f7ce769833283b38c6af2ecc8c3c24dd1db6c352 100644 (file)
 #include <linux/init.h>
 #include <linux/mm.h>
 #include <linux/bootmem.h>
+#include <linux/pfn.h>
 
 #include <asm/bootinfo.h>
 #include <asm/page.h>
+#include <asm/sections.h>
 
 #include <asm/mips-boards/prom.h>
 
@@ -39,9 +41,6 @@ static char *mtypes[3] = {
 };
 #endif
 
-/* References to section boundaries */
-extern char _end;
-
 struct prom_pmemblock * __init prom_getmdesc(void)
 {
        unsigned int memsize;
@@ -61,10 +60,10 @@ struct prom_pmemblock * __init prom_getmdesc(void)
 
        mdesc[2].type = simmem_reserved;
        mdesc[2].base = 0x00100000;
-       mdesc[2].size = CPHYSADDR(PAGE_ALIGN(&_end)) - mdesc[2].base;
+       mdesc[2].size = CPHYSADDR(PFN_ALIGN(&_end)) - mdesc[2].base;
 
        mdesc[3].type = simmem_free;
-       mdesc[3].base = CPHYSADDR(PAGE_ALIGN(&_end));
+       mdesc[3].base = CPHYSADDR(PFN_ALIGN(&_end));
        mdesc[3].size = memsize - mdesc[3].base;
 
        return &mdesc[0];
index a9f0c2bfe4ad7b4ee63480d6ec4b88b919a80c17..b7084e7c4bf9b7c4bce0ee742301ddfe198e85d5 100644 (file)
@@ -44,8 +44,6 @@
 void core_send_ipi(int cpu, unsigned int action)
 {
 #ifdef CONFIG_MIPS_MT_SMTC
-       void smtc_send_ipi(int, int, unsigned int);
-
        smtc_send_ipi(cpu, LINUX_SMP_IPI, action);
 #endif /* CONFIG_MIPS_MT_SMTC */
 /* "CPU" may be TC of same VPE, VPE of same CPU, or different CPU */
@@ -59,15 +57,8 @@ void core_send_ipi(int cpu, unsigned int action)
 void __init prom_build_cpu_map(void)
 {
 #ifdef CONFIG_MIPS_MT_SMTC
-       extern int mipsmt_build_cpu_map(int startslot);
        int nextslot;
 
-       cpus_clear(phys_cpu_present_map);
-
-       /* Register the boot CPU */
-
-       smp_prepare_boot_cpu();
-
        /*
         * As of November, 2004, MIPSsim only simulates one core
         * at a time.  However, that core may be a MIPS MT core
@@ -87,8 +78,6 @@ void __init prom_build_cpu_map(void)
 void prom_boot_secondary(int cpu, struct task_struct *idle)
 {
 #ifdef CONFIG_MIPS_MT_SMTC
-       extern void smtc_boot_secondary(int cpu, struct task_struct *t);
-
        smtc_boot_secondary(cpu, idle);
 #endif /* CONFIG_MIPS_MT_SMTC */
 }
@@ -113,7 +102,6 @@ void prom_init_secondary(void)
 void prom_prepare_cpus(unsigned int max_cpus)
 {
 #ifdef CONFIG_MIPS_MT_SMTC
-       void mipsmt_prepare_cpus(int c);
        /*
         * As noted above, we can assume a single CPU for now
         * but it may be multithreaded.
@@ -132,8 +120,6 @@ void prom_prepare_cpus(unsigned int max_cpus)
 void prom_smp_finish(void)
 {
 #ifdef CONFIG_MIPS_MT_SMTC
-       void smtc_smp_finish(void);
-
        smtc_smp_finish();
 #endif /* CONFIG_MIPS_MT_SMTC */
 }
index 9dd1352d57484a0b015b992c8759089ab5b483ab..bb041a22f20a55dd35f9eb28ffb3e5073abff1e8 100644 (file)
@@ -260,6 +260,10 @@ static void r3k_flush_cache_page(struct vm_area_struct *vma, unsigned long page,
 {
 }
 
+static void local_r3k_flush_data_cache_page(unsigned long addr)
+{
+}
+
 static void r3k_flush_data_cache_page(unsigned long addr)
 {
 }
@@ -335,6 +339,7 @@ void __init r3k_cache_init(void)
        flush_icache_range = r3k_flush_icache_range;
 
        flush_cache_sigtramp = r3k_flush_cache_sigtramp;
+       local_flush_data_cache_page = local_r3k_flush_data_cache_page;
        flush_data_cache_page = r3k_flush_data_cache_page;
 
        _dma_cache_wback_inv = r3k_dma_cache_wback_inv;
index 32b7f6aeb983271201702594c9d3a2da3e32ce5b..4182e1176faeaeb1181af9fe7d12094b42db1fc4 100644 (file)
@@ -154,7 +154,8 @@ static inline void blast_icache32_r4600_v1_page_indexed(unsigned long page)
 
 static inline void tx49_blast_icache32_page_indexed(unsigned long page)
 {
-       unsigned long start = page;
+       unsigned long indexmask = current_cpu_data.icache.waysize - 1;
+       unsigned long start = INDEX_BASE + (page & indexmask);
        unsigned long end = start + PAGE_SIZE;
        unsigned long ws_inc = 1UL << current_cpu_data.icache.waybit;
        unsigned long ws_end = current_cpu_data.icache.ways <<
@@ -749,12 +750,12 @@ static void __init probe_pcache(void)
                icache_size = 1 << (12 + ((config & CONF_IC) >> 9));
                c->icache.linesz = 16 << ((config & CONF_IB) >> 5);
                c->icache.ways = 2;
-               c->icache.waybit = ffs(icache_size/2) - 1;
+               c->icache.waybit = __ffs(icache_size/2);
 
                dcache_size = 1 << (12 + ((config & CONF_DC) >> 6));
                c->dcache.linesz = 16 << ((config & CONF_DB) >> 4);
                c->dcache.ways = 2;
-               c->dcache.waybit= ffs(dcache_size/2) - 1;
+               c->dcache.waybit= __ffs(dcache_size/2);
 
                c->options |= MIPS_CPU_CACHE_CDEX_P;
                break;
@@ -837,12 +838,12 @@ static void __init probe_pcache(void)
                icache_size = 1 << (10 + ((config & CONF_IC) >> 9));
                c->icache.linesz = 16 << ((config & CONF_IB) >> 5);
                c->icache.ways = 2;
-               c->icache.waybit = ffs(icache_size/2) - 1;
+               c->icache.waybit = __ffs(icache_size/2);
 
                dcache_size = 1 << (10 + ((config & CONF_DC) >> 6));
                c->dcache.linesz = 16 << ((config & CONF_DB) >> 4);
                c->dcache.ways = 2;
-               c->dcache.waybit = ffs(dcache_size/2) - 1;
+               c->dcache.waybit = __ffs(dcache_size/2);
 
                c->options |= MIPS_CPU_CACHE_CDEX_P;
                break;
@@ -873,12 +874,12 @@ static void __init probe_pcache(void)
                icache_size = 1 << (12 + ((config & CONF_IC) >> 9));
                c->icache.linesz = 16 << ((config & CONF_IB) >> 5);
                c->icache.ways = 4;
-               c->icache.waybit = ffs(icache_size / c->icache.ways) - 1;
+               c->icache.waybit = __ffs(icache_size / c->icache.ways);
 
                dcache_size = 1 << (12 + ((config & CONF_DC) >> 6));
                c->dcache.linesz = 16 << ((config & CONF_DB) >> 4);
                c->dcache.ways = 4;
-               c->dcache.waybit = ffs(dcache_size / c->dcache.ways) - 1;
+               c->dcache.waybit = __ffs(dcache_size / c->dcache.ways);
 
 #if !defined(CONFIG_SMP) || !defined(RM9000_CDEX_SMP_WAR)
                c->options |= MIPS_CPU_CACHE_CDEX_P;
@@ -906,7 +907,7 @@ static void __init probe_pcache(void)
                icache_size = c->icache.sets *
                              c->icache.ways *
                              c->icache.linesz;
-               c->icache.waybit = ffs(icache_size/c->icache.ways) - 1;
+               c->icache.waybit = __ffs(icache_size/c->icache.ways);
 
                if (config & 0x8)               /* VI bit */
                        c->icache.flags |= MIPS_CACHE_VTAG;
@@ -926,7 +927,7 @@ static void __init probe_pcache(void)
                dcache_size = c->dcache.sets *
                              c->dcache.ways *
                              c->dcache.linesz;
-               c->dcache.waybit = ffs(dcache_size/c->dcache.ways) - 1;
+               c->dcache.waybit = __ffs(dcache_size/c->dcache.ways);
 
                c->options |= MIPS_CPU_PREFETCH;
                break;
@@ -1198,6 +1199,7 @@ void __init r4k_cache_init(void)
 
        flush_cache_sigtramp    = r4k_flush_cache_sigtramp;
        flush_icache_all        = r4k_flush_icache_all;
+       local_flush_data_cache_page     = local_r4k_flush_data_cache_page;
        flush_data_cache_page   = r4k_flush_data_cache_page;
        flush_icache_range      = r4k_flush_icache_range;
 
index 2f08b535f20e8e9e6adc8a287398277598b36a5d..f9b129491b1e4e038019d715e0d4d63ae4b34629 100644 (file)
@@ -528,6 +528,7 @@ void sb1_cache_init(void)
        flush_cache_page = sb1_flush_cache_page;
 
        flush_cache_sigtramp = sb1_flush_cache_sigtramp;
+       local_flush_data_cache_page = (void *) sb1_nop;
        flush_data_cache_page = (void *) sb1_nop;
 
        /* Full flush */
index fe232e3988e39ade564b1141cf2a97870fca5952..5dfc9b1901f6537554bc7e34a1820b8cc8d5a6c0 100644 (file)
@@ -216,6 +216,11 @@ static void tx39_flush_cache_page(struct vm_area_struct *vma, unsigned long page
                tx39_blast_icache_page_indexed(page);
 }
 
+static void local_tx39_flush_data_cache_page(void * addr)
+{
+       tx39_blast_dcache_page(addr);
+}
+
 static void tx39_flush_data_cache_page(unsigned long addr)
 {
        tx39_blast_dcache_page(addr);
@@ -381,6 +386,7 @@ void __init tx39_cache_init(void)
                flush_icache_range      = (void *) tx39h_flush_icache_all;
 
                flush_cache_sigtramp    = (void *) tx39h_flush_icache_all;
+               local_flush_data_cache_page     = (void *) tx39h_flush_icache_all;
                flush_data_cache_page   = (void *) tx39h_flush_icache_all;
 
                _dma_cache_wback_inv    = tx39h_dma_cache_wback_inv;
@@ -406,6 +412,7 @@ void __init tx39_cache_init(void)
                flush_icache_range = tx39_flush_icache_range;
 
                flush_cache_sigtramp = tx39_flush_cache_sigtramp;
+               local_flush_data_cache_page = local_tx39_flush_data_cache_page;
                flush_data_cache_page = tx39_flush_data_cache_page;
 
                _dma_cache_wback_inv = tx39_dma_cache_wback_inv;
index 591c22b080e427edc681248508b86ffc3a3fecb7..83a56296be86d063c08296b6e39bb1df9ccaef85 100644 (file)
@@ -30,6 +30,7 @@ void (*flush_icache_page)(struct vm_area_struct *vma, struct page *page);
 
 /* MIPS specific cache operations */
 void (*flush_cache_sigtramp)(unsigned long addr);
+void (*local_flush_data_cache_page)(void * addr);
 void (*flush_data_cache_page)(unsigned long addr);
 void (*flush_icache_all)(void);
 
index 2d9624fd10ecb4ad61cc33f55901f2109d6a4137..e3a617224868f04643719e68c9020d9941688efc 100644 (file)
@@ -157,7 +157,6 @@ no_context:
         * Oops. The kernel tried to access some bad page. We'll have to
         * terminate things with extreme prejudice.
         */
-
        bust_spinlocks(1);
 
        printk(KERN_ALERT "CPU %d Unable to handle kernel paging request at "
@@ -188,11 +187,20 @@ do_sigbus:
        /* Kernel mode? Handle exceptions or die */
        if (!user_mode(regs))
                goto no_context;
-
+       else
        /*
         * Send a sigbus, regardless of whether we were in kernel
         * or user mode.
         */
+#if 0
+               printk("do_page_fault() #3: sending SIGBUS to %s for "
+                      "invalid %s\n%0*lx (epc == %0*lx, ra == %0*lx)\n",
+                      tsk->comm,
+                      write ? "write access to" : "read access from",
+                      field, address,
+                      field, (unsigned long) regs->cp0_epc,
+                      field, (unsigned long) regs->regs[31]);
+#endif
        tsk->thread.cp0_badvaddr = address;
        info.si_signo = SIGBUS;
        info.si_errno = 0;
@@ -201,7 +209,6 @@ do_sigbus:
        force_sig_info(SIGBUS, &info, tsk);
 
        return;
-
 vmalloc_fault:
        {
                /*
index 1f7b37b38f5c740839208cf7f6728e3335fde7f0..0c544375b856be81235c121c0fca81f0290deeb0 100644 (file)
@@ -83,6 +83,7 @@ void __kunmap_atomic(void *kvaddr, enum km_type type)
        preempt_check_resched();
 }
 
+#ifndef CONFIG_LIMITED_DMA
 /*
  * This is the same as kmap_atomic() but can map memory that doesn't
  * have a struct page associated with it.
@@ -101,6 +102,7 @@ void *kmap_atomic_pfn(unsigned long pfn, enum km_type type)
 
        return (void*) vaddr;
 }
+#endif /* CONFIG_LIMITED_DMA */
 
 struct page *__kmap_atomic_to_page(void *ptr)
 {
index ad89c442f2998918d52fdac6ad7a98c193fcdfa2..c22308b93ff05ce04aee860042733a63dc2bf713 100644 (file)
@@ -276,6 +276,20 @@ void __init mem_init(void)
 }
 #endif /* !CONFIG_NEED_MULTIPLE_NODES */
 
+void free_init_pages(char *what, unsigned long begin, unsigned long end)
+{
+       unsigned long addr;
+
+       for (addr = begin; addr < end; addr += PAGE_SIZE) {
+               ClearPageReserved(virt_to_page(addr));
+               init_page_count(virt_to_page(addr));
+               memset((void *)addr, 0xcc, PAGE_SIZE);
+               free_page(addr);
+               totalram_pages++;
+       }
+       printk(KERN_INFO "Freeing %s: %ldk freed\n", what, (end - begin) >> 10);
+}
+
 #ifdef CONFIG_BLK_DEV_INITRD
 void free_initrd_mem(unsigned long start, unsigned long end)
 {
@@ -284,16 +298,7 @@ void free_initrd_mem(unsigned long start, unsigned long end)
        start = (unsigned long)phys_to_virt(CPHYSADDR(start));
        end = (unsigned long)phys_to_virt(CPHYSADDR(end));
 #endif
-       if (start < end)
-               printk(KERN_INFO "Freeing initrd memory: %ldk freed\n",
-                      (end - start) >> 10);
-
-       for (; start < end; start += PAGE_SIZE) {
-               ClearPageReserved(virt_to_page(start));
-               init_page_count(virt_to_page(start));
-               free_page(start);
-               totalram_pages++;
-       }
+       free_init_pages("initrd memory", start, end);
 }
 #endif
 
@@ -301,24 +306,17 @@ extern unsigned long prom_free_prom_memory(void);
 
 void free_initmem(void)
 {
-       unsigned long addr, page, freed;
+       unsigned long start, end, freed;
 
        freed = prom_free_prom_memory();
+       if (freed)
+               printk(KERN_INFO "Freeing firmware memory: %ldk freed\n",freed);
 
-       addr = (unsigned long) &__init_begin;
-       while (addr < (unsigned long) &__init_end) {
+       start = (unsigned long)(&__init_begin);
+       end = (unsigned long)(&__init_end);
 #ifdef CONFIG_64BIT
-               page = PAGE_OFFSET | CPHYSADDR(addr);
-#else
-               page = addr;
+       start = PAGE_OFFSET | CPHYSADDR(start);
+       end = PAGE_OFFSET | CPHYSADDR(end);
 #endif
-               ClearPageReserved(virt_to_page(page));
-               init_page_count(virt_to_page(page));
-               free_page(page);
-               totalram_pages++;
-               freed += PAGE_SIZE;
-               addr += PAGE_SIZE;
-       }
-       printk(KERN_INFO "Freeing unused kernel memory: %ldk freed\n",
-              freed >> 10);
+       free_init_pages("unused kernel memory", start, end);
 }
index 3b6cc9ba1b052651b0c9b77fcb379e39668d0784..31ec730524239dcc9de7c22dd2cda845daa8b963 100644 (file)
@@ -138,7 +138,7 @@ void __init rm7k_sc_init(void)
 
        c->scache.linesz = sc_lsize;
        c->scache.ways = 4;
-       c->scache.waybit= ffs(scache_size / c->scache.ways) - 1;
+       c->scache.waybit= __ffs(scache_size / c->scache.ways);
        c->scache.waysize = scache_size / c->scache.ways;
        c->scache.sets = scache_size / (c->scache.linesz * c->scache.ways);
        printk(KERN_INFO "Secondary cache size %dK, linesize %d bytes.\n",
index a865f2394cb0d1de5d44acfdbbb1ee45b83beb28..9dca099ba16b01b907568d9f387f5ea9d693d665 100644 (file)
@@ -32,13 +32,35 @@ extern void build_tlb_refill_handler(void);
                                     "nop; nop; nop; nop; nop; nop;\n\t" \
                                     ".set reorder\n\t")
 
+/* Atomicity and interruptability */
+#ifdef CONFIG_MIPS_MT_SMTC
+
+#include <asm/smtc.h>
+#include <asm/mipsmtregs.h>
+
+#define ENTER_CRITICAL(flags) \
+       { \
+       unsigned int mvpflags; \
+       local_irq_save(flags);\
+       mvpflags = dvpe()
+#define EXIT_CRITICAL(flags) \
+       evpe(mvpflags); \
+       local_irq_restore(flags); \
+       }
+#else
+
+#define ENTER_CRITICAL(flags) local_irq_save(flags)
+#define EXIT_CRITICAL(flags) local_irq_restore(flags)
+
+#endif /* CONFIG_MIPS_MT_SMTC */
+
 void local_flush_tlb_all(void)
 {
        unsigned long flags;
        unsigned long old_ctx;
        int entry;
 
-       local_irq_save(flags);
+       ENTER_CRITICAL(flags);
        /* Save old context and create impossible VPN2 value */
        old_ctx = read_c0_entryhi();
        write_c0_entrylo0(0);
@@ -57,7 +79,7 @@ void local_flush_tlb_all(void)
        }
        tlbw_use_hazard();
        write_c0_entryhi(old_ctx);
-       local_irq_restore(flags);
+       EXIT_CRITICAL(flags);
 }
 
 /* All entries common to a mm share an asid.  To effectively flush
@@ -87,6 +109,7 @@ void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
                unsigned long flags;
                int size;
 
+               ENTER_CRITICAL(flags);
                size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
                size = (size + 1) >> 1;
                local_irq_save(flags);
@@ -120,7 +143,7 @@ void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
                } else {
                        drop_mmu_context(mm, cpu);
                }
-               local_irq_restore(flags);
+               EXIT_CRITICAL(flags);
        }
 }
 
@@ -129,9 +152,9 @@ void local_flush_tlb_kernel_range(unsigned long start, unsigned long end)
        unsigned long flags;
        int size;
 
+       ENTER_CRITICAL(flags);
        size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
        size = (size + 1) >> 1;
-       local_irq_save(flags);
        if (size <= current_cpu_data.tlbsize / 2) {
                int pid = read_c0_entryhi();
 
@@ -162,7 +185,7 @@ void local_flush_tlb_kernel_range(unsigned long start, unsigned long end)
        } else {
                local_flush_tlb_all();
        }
-       local_irq_restore(flags);
+       EXIT_CRITICAL(flags);
 }
 
 void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
@@ -175,7 +198,7 @@ void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
 
                newpid = cpu_asid(cpu, vma->vm_mm);
                page &= (PAGE_MASK << 1);
-               local_irq_save(flags);
+               ENTER_CRITICAL(flags);
                oldpid = read_c0_entryhi();
                write_c0_entryhi(page | newpid);
                mtc0_tlbw_hazard();
@@ -194,7 +217,7 @@ void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
 
        finish:
                write_c0_entryhi(oldpid);
-               local_irq_restore(flags);
+               EXIT_CRITICAL(flags);
        }
 }
 
@@ -207,7 +230,7 @@ void local_flush_tlb_one(unsigned long page)
        unsigned long flags;
        int oldpid, idx;
 
-       local_irq_save(flags);
+       ENTER_CRITICAL(flags);
        oldpid = read_c0_entryhi();
        page &= (PAGE_MASK << 1);
        write_c0_entryhi(page);
@@ -226,7 +249,7 @@ void local_flush_tlb_one(unsigned long page)
        }
        write_c0_entryhi(oldpid);
 
-       local_irq_restore(flags);
+       EXIT_CRITICAL(flags);
 }
 
 /*
@@ -249,7 +272,7 @@ void __update_tlb(struct vm_area_struct * vma, unsigned long address, pte_t pte)
        if (current->active_mm != vma->vm_mm)
                return;
 
-       local_irq_save(flags);
+       ENTER_CRITICAL(flags);
 
        pid = read_c0_entryhi() & ASID_MASK;
        address &= (PAGE_MASK << 1);
@@ -277,7 +300,7 @@ void __update_tlb(struct vm_area_struct * vma, unsigned long address, pte_t pte)
        else
                tlb_write_indexed();
        tlbw_use_hazard();
-       local_irq_restore(flags);
+       EXIT_CRITICAL(flags);
 }
 
 #if 0
@@ -291,7 +314,7 @@ static void r4k_update_mmu_cache_hwbug(struct vm_area_struct * vma,
        pte_t *ptep;
        int idx;
 
-       local_irq_save(flags);
+       ENTER_CRITICAL(flags);
        address &= (PAGE_MASK << 1);
        asid = read_c0_entryhi() & ASID_MASK;
        write_c0_entryhi(address | asid);
@@ -310,7 +333,7 @@ static void r4k_update_mmu_cache_hwbug(struct vm_area_struct * vma,
        else
                tlb_write_indexed();
        tlbw_use_hazard();
-       local_irq_restore(flags);
+       EXIT_CRITICAL(flags);
 }
 #endif
 
@@ -322,7 +345,7 @@ void __init add_wired_entry(unsigned long entrylo0, unsigned long entrylo1,
        unsigned long old_pagemask;
        unsigned long old_ctx;
 
-       local_irq_save(flags);
+       ENTER_CRITICAL(flags);
        /* Save old context and create impossible VPN2 value */
        old_ctx = read_c0_entryhi();
        old_pagemask = read_c0_pagemask();
@@ -342,7 +365,7 @@ void __init add_wired_entry(unsigned long entrylo0, unsigned long entrylo1,
        BARRIER;
        write_c0_pagemask(old_pagemask);
        local_flush_tlb_all();
-       local_irq_restore(flags);
+       EXIT_CRITICAL(flags);
 }
 
 /*
@@ -362,7 +385,7 @@ __init int add_temporary_entry(unsigned long entrylo0, unsigned long entrylo1,
        unsigned long old_pagemask;
        unsigned long old_ctx;
 
-       local_irq_save(flags);
+       ENTER_CRITICAL(flags);
        /* Save old context and create impossible VPN2 value */
        old_ctx = read_c0_entryhi();
        old_pagemask = read_c0_pagemask();
@@ -386,10 +409,11 @@ __init int add_temporary_entry(unsigned long entrylo0, unsigned long entrylo1,
        write_c0_entryhi(old_ctx);
        write_c0_pagemask(old_pagemask);
 out:
-       local_irq_restore(flags);
+       EXIT_CRITICAL(flags);
        return ret;
 }
 
+extern void __init sanitize_tlb_entries(void);
 static void __init probe_tlb(unsigned long config)
 {
        struct cpuinfo_mips *c = &current_cpu_data;
@@ -402,6 +426,14 @@ static void __init probe_tlb(unsigned long config)
         */
        if ((c->processor_id & 0xff0000) == PRID_COMP_LEGACY)
                return;
+#ifdef CONFIG_MIPS_MT_SMTC
+       /*
+        * If TLB is shared in SMTC system, total size already
+        * has been calculated and written into cpu_data tlbsize
+        */
+       if((smtc_status & SMTC_TLB_SHARED) == SMTC_TLB_SHARED)
+               return;
+#endif /* CONFIG_MIPS_MT_SMTC */
 
        reg = read_c0_config1();
        if (!((config >> 7) & 3))
@@ -410,6 +442,15 @@ static void __init probe_tlb(unsigned long config)
        c->tlbsize = ((reg >> 25) & 0x3f) + 1;
 }
 
+static int __initdata ntlb = 0;
+static int __init set_ntlb(char *str)
+{
+       get_option(&str, &ntlb);
+       return 1;
+}
+
+__setup("ntlb=", set_ntlb);
+
 void __init tlb_init(void)
 {
        unsigned int config = read_c0_config();
@@ -432,5 +473,15 @@ void __init tlb_init(void)
 
        /* Did I tell you that ARC SUCKS?  */
 
+       if (ntlb) {
+               if (ntlb > 1 && ntlb <= current_cpu_data.tlbsize) {
+                       int wired = current_cpu_data.tlbsize - ntlb;
+                       write_c0_wired(wired);
+                       write_c0_index(wired-1);
+                       printk ("Restricting TLB to %d entries\n", ntlb);
+               } else
+                       printk("Ignoring invalid argument ntlb=%d\n", ntlb);
+       }
+
        build_tlb_refill_handler();
 }
index 599b3c297186d360e3ce05cfd8f5135a827d021a..053dbacac56bdf4d5a797b0d115ddb1951297aa0 100644 (file)
@@ -7,6 +7,16 @@
  *
  * Copyright (C) 2004,2005 by Thiemo Seufer
  * Copyright (C) 2005  Maciej W. Rozycki
+ * Copyright (C) 2006  Ralf Baechle (ralf@linux-mips.org)
+ *
+ * ... and the days got worse and worse and now you see
+ * I've gone completly out of my mind.
+ *
+ * They're coming to take me a away haha
+ * they're coming to take me a away hoho hihi haha
+ * to the funny farm where code is beautiful all the time ...
+ *
+ * (Condolences to Napoleon XIV)
  */
 
 #include <stdarg.h>
@@ -68,6 +78,7 @@ enum fields
        BIMM = 0x040,
        JIMM = 0x080,
        FUNC = 0x100,
+       SET = 0x200
 };
 
 #define OP_MASK                0x2f
@@ -86,6 +97,8 @@ enum fields
 #define JIMM_SH                0
 #define FUNC_MASK      0x2f
 #define FUNC_SH                0
+#define SET_MASK       0x7
+#define SET_SH         0
 
 enum opcode {
        insn_invalid,
@@ -129,8 +142,8 @@ static __initdata struct insn insn_table[] = {
        { insn_bne, M(bne_op,0,0,0,0,0), RS | RT | BIMM },
        { insn_daddiu, M(daddiu_op,0,0,0,0,0), RS | RT | SIMM },
        { insn_daddu, M(spec_op,0,0,0,0,daddu_op), RS | RT | RD },
-       { insn_dmfc0, M(cop0_op,dmfc_op,0,0,0,0), RT | RD },
-       { insn_dmtc0, M(cop0_op,dmtc_op,0,0,0,0), RT | RD },
+       { insn_dmfc0, M(cop0_op,dmfc_op,0,0,0,0), RT | RD | SET},
+       { insn_dmtc0, M(cop0_op,dmtc_op,0,0,0,0), RT | RD | SET},
        { insn_dsll, M(spec_op,0,0,0,0,dsll_op), RT | RD | RE },
        { insn_dsll32, M(spec_op,0,0,0,0,dsll32_op), RT | RD | RE },
        { insn_dsra, M(spec_op,0,0,0,0,dsra_op), RT | RD | RE },
@@ -145,8 +158,8 @@ static __initdata struct insn insn_table[] = {
        { insn_lld, M(lld_op,0,0,0,0,0), RS | RT | SIMM },
        { insn_lui, M(lui_op,0,0,0,0,0), RT | SIMM },
        { insn_lw, M(lw_op,0,0,0,0,0), RS | RT | SIMM },
-       { insn_mfc0, M(cop0_op,mfc_op,0,0,0,0), RT | RD },
-       { insn_mtc0, M(cop0_op,mtc_op,0,0,0,0), RT | RD },
+       { insn_mfc0, M(cop0_op,mfc_op,0,0,0,0), RT | RD | SET},
+       { insn_mtc0, M(cop0_op,mtc_op,0,0,0,0), RT | RD | SET},
        { insn_ori, M(ori_op,0,0,0,0,0), RS | RT | UIMM },
        { insn_rfe, M(cop0_op,cop_op,0,0,0,rfe_op), 0 },
        { insn_sc, M(sc_op,0,0,0,0,0), RS | RT | SIMM },
@@ -242,6 +255,14 @@ static __init u32 build_func(u32 arg)
        return arg & FUNC_MASK;
 }
 
+static __init u32 build_set(u32 arg)
+{
+       if (arg & ~SET_MASK)
+               printk(KERN_WARNING "TLB synthesizer field overflow\n");
+
+       return arg & SET_MASK;
+}
+
 /*
  * The order of opcode arguments is implicitly left to right,
  * starting with RS and ending with FUNC or IMM.
@@ -273,6 +294,7 @@ static void __init build_insn(u32 **buf, enum opcode opc, ...)
        if (ip->fields & BIMM) op |= build_bimm(va_arg(ap, s32));
        if (ip->fields & JIMM) op |= build_jimm(va_arg(ap, u32));
        if (ip->fields & FUNC) op |= build_func(va_arg(ap, u32));
+       if (ip->fields & SET) op |= build_set(va_arg(ap, u32));
        va_end(ap);
 
        **buf = op;
@@ -358,8 +380,8 @@ I_u1s2(_bgezl);
 I_u1s2(_bltz);
 I_u1s2(_bltzl);
 I_u1u2s3(_bne);
-I_u1u2(_dmfc0);
-I_u1u2(_dmtc0);
+I_u1u2u3(_dmfc0);
+I_u1u2u3(_dmtc0);
 I_u2u1s3(_daddiu);
 I_u3u1u2(_daddu);
 I_u2u1u3(_dsll);
@@ -376,8 +398,8 @@ I_u2s3u1(_ll);
 I_u2s3u1(_lld);
 I_u1s2(_lui);
 I_u2s3u1(_lw);
-I_u1u2(_mfc0);
-I_u1u2(_mtc0);
+I_u1u2u3(_mfc0);
+I_u1u2u3(_mtc0);
 I_u2u1u3(_ori);
 I_0(_rfe);
 I_u2s3u1(_sc);
@@ -451,8 +473,8 @@ L_LA(_r3000_write_probe_fail)
 # define i_SLL(buf, rs, rt, sh) i_dsll(buf, rs, rt, sh)
 # define i_SRA(buf, rs, rt, sh) i_dsra(buf, rs, rt, sh)
 # define i_SRL(buf, rs, rt, sh) i_dsrl(buf, rs, rt, sh)
-# define i_MFC0(buf, rt, rd) i_dmfc0(buf, rt, rd)
-# define i_MTC0(buf, rt, rd) i_dmtc0(buf, rt, rd)
+# define i_MFC0(buf, rt, rd...) i_dmfc0(buf, rt, rd)
+# define i_MTC0(buf, rt, rd...) i_dmtc0(buf, rt, rd)
 # define i_ADDIU(buf, rs, rt, val) i_daddiu(buf, rs, rt, val)
 # define i_ADDU(buf, rs, rt, rd) i_daddu(buf, rs, rt, rd)
 # define i_SUBU(buf, rs, rt, rd) i_dsubu(buf, rs, rt, rd)
@@ -464,8 +486,8 @@ L_LA(_r3000_write_probe_fail)
 # define i_SLL(buf, rs, rt, sh) i_sll(buf, rs, rt, sh)
 # define i_SRA(buf, rs, rt, sh) i_sra(buf, rs, rt, sh)
 # define i_SRL(buf, rs, rt, sh) i_srl(buf, rs, rt, sh)
-# define i_MFC0(buf, rt, rd) i_mfc0(buf, rt, rd)
-# define i_MTC0(buf, rt, rd) i_mtc0(buf, rt, rd)
+# define i_MFC0(buf, rt, rd...) i_mfc0(buf, rt, rd)
+# define i_MTC0(buf, rt, rd...) i_mtc0(buf, rt, rd)
 # define i_ADDIU(buf, rs, rt, val) i_addiu(buf, rs, rt, val)
 # define i_ADDU(buf, rs, rt, rd) i_addu(buf, rs, rt, rd)
 # define i_SUBU(buf, rs, rt, rd) i_subu(buf, rs, rt, rd)
@@ -670,14 +692,15 @@ static void __init il_bgezl(u32 **p, struct reloc **r, unsigned int reg,
 #define K1             27
 
 /* Some CP0 registers */
-#define C0_INDEX       0
-#define C0_ENTRYLO0    2
-#define C0_ENTRYLO1    3
-#define C0_CONTEXT     4
-#define C0_BADVADDR    8
-#define C0_ENTRYHI     10
-#define C0_EPC         14
-#define C0_XCONTEXT    20
+#define C0_INDEX       0, 0
+#define C0_ENTRYLO0    2, 0
+#define C0_TCBIND      2, 2
+#define C0_ENTRYLO1    3, 0
+#define C0_CONTEXT     4, 0
+#define C0_BADVADDR    8, 0
+#define C0_ENTRYHI     10, 0
+#define C0_EPC         14, 0
+#define C0_XCONTEXT    20, 0
 
 #ifdef CONFIG_64BIT
 # define GET_CONTEXT(buf, reg) i_MFC0(buf, reg, C0_XCONTEXT)
@@ -742,7 +765,7 @@ static void __init build_r3000_tlb_refill_handler(void)
        }
 #endif
 
-       memcpy((void *)CAC_BASE, tlb_handler, 0x80);
+       memcpy((void *)ebase, tlb_handler, 0x80);
 }
 
 /*
@@ -951,12 +974,20 @@ build_get_pmde64(u32 **p, struct label **l, struct reloc **r,
        /* No i_nop needed here, since the next insn doesn't touch TMP. */
 
 #ifdef CONFIG_SMP
+# ifdef  CONFIG_MIPS_MT_SMTC
+       /*
+        * SMTC uses TCBind value as "CPU" index
+        */
+       i_mfc0(p, ptr, C0_TCBIND);
+       i_dsrl(p, ptr, ptr, 19);
+# else
        /*
         * 64 bit SMP running in XKPHYS has smp_processor_id() << 3
         * stored in CONTEXT.
         */
        i_dmfc0(p, ptr, C0_CONTEXT);
        i_dsrl(p, ptr, ptr, 23);
+#endif
        i_LA_mostly(p, tmp, pgdc);
        i_daddu(p, ptr, ptr, tmp);
        i_dmfc0(p, tmp, C0_BADVADDR);
@@ -1014,9 +1045,21 @@ build_get_pgde32(u32 **p, unsigned int tmp, unsigned int ptr)
 
        /* 32 bit SMP has smp_processor_id() stored in CONTEXT. */
 #ifdef CONFIG_SMP
+#ifdef  CONFIG_MIPS_MT_SMTC
+       /*
+        * SMTC uses TCBind value as "CPU" index
+        */
+       i_mfc0(p, ptr, C0_TCBIND);
+       i_LA_mostly(p, tmp, pgdc);
+       i_srl(p, ptr, ptr, 19);
+#else
+       /*
+        * smp_processor_id() << 3 is stored in CONTEXT.
+         */
        i_mfc0(p, ptr, C0_CONTEXT);
        i_LA_mostly(p, tmp, pgdc);
        i_srl(p, ptr, ptr, 23);
+#endif
        i_addu(p, ptr, tmp, ptr);
 #else
        i_LA_mostly(p, ptr, pgdc);
@@ -1247,7 +1290,7 @@ static void __init build_r4000_tlb_refill_handler(void)
        }
 #endif
 
-       memcpy((void *)CAC_BASE, final_handler, 0x100);
+       memcpy((void *)ebase, final_handler, 0x100);
 }
 
 /*
index 20bbd3ea44a8a1cc425241220583deda06fc53f6..67372f3f9654a3105e0b9d041d6c2650f848e240 100644 (file)
@@ -6,7 +6,7 @@
 # unless it's something special (ie not a .c file).
 #
 
-obj-y += int-handler.o irq.o prom.o reset.o setup.o
+obj-y += irq.o prom.o reset.o setup.o
 
 obj-$(CONFIG_SERIAL_8250_CONSOLE) += ja-console.o
 obj-$(CONFIG_REMOTE_DEBUG) += dbg_io.o
diff --git a/arch/mips/momentum/jaguar_atx/int-handler.S b/arch/mips/momentum/jaguar_atx/int-handler.S
deleted file mode 100644 (file)
index 55bc789..0000000
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * Copyright 2002 Momentum Computer Inc.
- * Author: Matthew Dharm <mdharm@momenco.com>
- *
- * Based on work:
- *   Copyright 2001 MontaVista Software Inc.
- *   Author: jsun@mvista.com or jsun@junsun.net
- *
- * First-level interrupt dispatcher for Jaguar-ATX board.
- *
- * 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 <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/addrspace.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-
-/*
- * First level interrupt dispatcher for Ocelot-CS board
- */
-               .align  5
-               NESTED(jaguar_handle_int, PT_SIZE, sp)
-               SAVE_ALL
-               CLI
-               .set    at
-               mfc0    t0, CP0_CAUSE
-               mfc0    t2, CP0_STATUS
-
-               and     t0, t2
-
-               andi    t1, t0, STATUSF_IP0     /* sw0 software interrupt */
-               bnez    t1, ll_sw0_irq
-               andi    t1, t0, STATUSF_IP1     /* sw1 software interrupt */
-               bnez    t1, ll_sw1_irq
-               andi    t1, t0, STATUSF_IP2     /* int0 hardware line */
-               bnez    t1, ll_pcixa_irq
-               andi    t1, t0, STATUSF_IP3     /* int1 hardware line */
-               bnez    t1, ll_pcixb_irq
-               andi    t1, t0, STATUSF_IP4     /* int2 hardware line */
-               bnez    t1, ll_pcia_irq
-               andi    t1, t0, STATUSF_IP5     /* int3 hardware line */
-               bnez    t1, ll_pcib_irq
-               andi    t1, t0, STATUSF_IP6     /* int4 hardware line */
-               bnez    t1, ll_uart_irq
-               andi    t1, t0, STATUSF_IP7     /* cpu timer */
-               bnez    t1, ll_cputimer_irq
-
-               nop
-               nop
-
-               /* now look at extended interrupts */
-               mfc0    t0, CP0_CAUSE
-               cfc0    t1, CP0_S1_INTCONTROL
-
-               /* shift the mask 8 bits left to line up the bits */
-               sll     t2, t1, 8
-
-               and     t0, t2
-               srl     t0, t0, 16
-
-               andi    t1, t0, STATUSF_IP8     /* int6 hardware line */
-               bnez    t1, ll_mv64340_decode_irq
-
-               nop
-               nop
-
-               .set    reorder
-
-               /* wrong alarm or masked ... */
-               j       spurious_interrupt
-               nop
-               END(jaguar_handle_int)
-
-               .align  5
-ll_sw0_irq:
-               li      a0, 0
-               move    a1, sp
-               jal     do_IRQ
-               j       ret_from_irq
-ll_sw1_irq:
-               li      a0, 1
-               move    a1, sp
-               jal     do_IRQ
-               j       ret_from_irq
-ll_pcixa_irq:
-               li      a0, 2
-               move    a1, sp
-               jal     do_IRQ
-               j       ret_from_irq
-
-ll_pcixb_irq:
-               li      a0, 3
-               move    a1, sp
-               jal     do_IRQ
-               j       ret_from_irq
-
-ll_pcia_irq:
-               li      a0, 4
-               move    a1, sp
-               jal     do_IRQ
-               j       ret_from_irq
-
-ll_pcib_irq:
-               li      a0, 5
-               move    a1, sp
-               jal     do_IRQ
-               j       ret_from_irq
-
-ll_uart_irq:
-               li      a0, 6
-               move    a1, sp
-               jal     do_IRQ
-               j       ret_from_irq
-
-ll_cputimer_irq:
-               li      a0, 7
-               move    a1, sp
-               jal     ll_timer_interrupt
-               j       ret_from_irq
-
-ll_mv64340_decode_irq:
-               move    a0, sp
-               jal     ll_mv64340_irq
-               j       ret_from_irq
index 15588f91ace2dd9499ae51506d8cdc8c3cef6899..ec4032b38f19230e26c169f57dceee4867bbf54f 100644 (file)
@@ -10,7 +10,7 @@
  *   Copyright 2001 MontaVista Software Inc.
  *   Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
  *
- *   Copyright (C) 2000, 2001 Ralf Baechle (ralf@gnu.org)
+ *   Copyright (C) 2000, 01, 06 Ralf Baechle (ralf@linux-mips.org)
  *
  *  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
 #include <linux/types.h>
 #include <asm/irq_cpu.h>
 #include <asm/mipsregs.h>
+#include <asm/time.h>
 
-extern asmlinkage void jaguar_handle_int(void);
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+       unsigned int pending = read_c0_cause() & read_c0_status();
+
+       if (pending & STATUSF_IP0)
+               do_IRQ(0, regs);
+       else if (pending & STATUSF_IP1)
+               do_IRQ(1, regs);
+       else if (pending & STATUSF_IP2)
+               do_IRQ(2, regs);
+       else if (pending & STATUSF_IP3)
+               do_IRQ(3, regs);
+       else if (pending & STATUSF_IP4)
+               do_IRQ(4, regs);
+       else if (pending & STATUSF_IP5)
+               do_IRQ(5, regs);
+       else if (pending & STATUSF_IP6)
+               do_IRQ(6, regs);
+       else if (pending & STATUSF_IP7)
+               ll_timer_interrupt(7, regs);
+       else {
+               /*
+                * Now look at the extended interrupts
+                */
+               pending = (read_c0_cause() & (read_c0_intcontrol() << 8)) >> 16;
+               if (pending & STATUSF_IP8)
+                       ll_mv64340_irq(regs);
+       }
+}
 
 static struct irqaction cascade_mv64340 = {
        no_action, SA_INTERRUPT, CPU_MASK_NONE, "MV64340-Cascade", NULL, NULL
@@ -53,8 +82,6 @@ void __init arch_init_irq(void)
         */
        clear_c0_status(ST0_IM);
 
-       /* Sets the first-level interrupt dispatcher. */
-       set_except_vector(0, jaguar_handle_int);
        mips_cpu_irq_init(0);
        rm7k_cpu_irq_init(8);
 
index 91d9637143d7fe24690e063f16be9f887d4e909c..1379c76845dc6619436c064400f46226777130c1 100644 (file)
@@ -381,24 +381,24 @@ void __init plat_setup(void)
         * shut down ethernet ports, just to be sure our memory doesn't get
         * corrupted by random ethernet traffic.
         */
-       MV_WRITE(MV64340_ETH_TRANSMIT_QUEUE_COMMAND_REG(0), 0xff << 8);
-       MV_WRITE(MV64340_ETH_TRANSMIT_QUEUE_COMMAND_REG(1), 0xff << 8);
-       MV_WRITE(MV64340_ETH_TRANSMIT_QUEUE_COMMAND_REG(2), 0xff << 8);
-       MV_WRITE(MV64340_ETH_RECEIVE_QUEUE_COMMAND_REG(0), 0xff << 8);
-       MV_WRITE(MV64340_ETH_RECEIVE_QUEUE_COMMAND_REG(1), 0xff << 8);
-       MV_WRITE(MV64340_ETH_RECEIVE_QUEUE_COMMAND_REG(2), 0xff << 8);
-       while (MV_READ(MV64340_ETH_RECEIVE_QUEUE_COMMAND_REG(0)) & 0xff);
-       while (MV_READ(MV64340_ETH_RECEIVE_QUEUE_COMMAND_REG(1)) & 0xff);
-       while (MV_READ(MV64340_ETH_RECEIVE_QUEUE_COMMAND_REG(2)) & 0xff);
-       while (MV_READ(MV64340_ETH_TRANSMIT_QUEUE_COMMAND_REG(0)) & 0xff);
-       while (MV_READ(MV64340_ETH_TRANSMIT_QUEUE_COMMAND_REG(1)) & 0xff);
-       while (MV_READ(MV64340_ETH_TRANSMIT_QUEUE_COMMAND_REG(2)) & 0xff);
-       MV_WRITE(MV64340_ETH_PORT_SERIAL_CONTROL_REG(0),
-                MV_READ(MV64340_ETH_PORT_SERIAL_CONTROL_REG(0)) & ~1);
-       MV_WRITE(MV64340_ETH_PORT_SERIAL_CONTROL_REG(1),
-                MV_READ(MV64340_ETH_PORT_SERIAL_CONTROL_REG(1)) & ~1);
-       MV_WRITE(MV64340_ETH_PORT_SERIAL_CONTROL_REG(2),
-                MV_READ(MV64340_ETH_PORT_SERIAL_CONTROL_REG(2)) & ~1);
+       MV_WRITE(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(0), 0xff << 8);
+       MV_WRITE(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(1), 0xff << 8);
+       MV_WRITE(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(2), 0xff << 8);
+       MV_WRITE(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(0), 0xff << 8);
+       MV_WRITE(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(1), 0xff << 8);
+       MV_WRITE(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(2), 0xff << 8);
+       while (MV_READ(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(0)) & 0xff);
+       while (MV_READ(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(1)) & 0xff);
+       while (MV_READ(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(2)) & 0xff);
+       while (MV_READ(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(0)) & 0xff);
+       while (MV_READ(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(1)) & 0xff);
+       while (MV_READ(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(2)) & 0xff);
+       MV_WRITE(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(0),
+                MV_READ(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(0)) & ~1);
+       MV_WRITE(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(1),
+                MV_READ(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(1)) & ~1);
+       MV_WRITE(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(2),
+                MV_READ(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(2)) & ~1);
 
        /* Turn off the Bit-Error LED */
        JAGUAR_FPGA_WRITE(0x80, CLR);
index aab8fd89f830bd18062ecaa2731ae0c957cb1221..8bcea64dd27b90a5500dac81b10cf5c6e5f869f3 100644 (file)
@@ -5,4 +5,4 @@
 # removes any old dependencies. DON'T put your own dependencies here
 # unless it's something special (ie not a .c file).
 #
-obj-y   += int-handler.o irq.o prom.o reset.o setup.o
+obj-y   += irq.o prom.o reset.o setup.o
diff --git a/arch/mips/momentum/ocelot_3/int-handler.S b/arch/mips/momentum/ocelot_3/int-handler.S
deleted file mode 100644 (file)
index 4522f09..0000000
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * Copyright 2002 Momentum Computer Inc.
- * Author: Matthew Dharm <mdharm@momenco.com>
- *
- * Copyright 2001 MontaVista Software Inc.
- * Author: jsun@mvista.com or jsun@junsun.net
- *
- * Copyright 2004 PMC-Sierra
- * Author: Manish Lachwani (lachwani@pmc-sierra.com)
- *
- * Copyright (C) 2004 MontaVista Software Inc.
- * Author: Manish Lachwani, mlachwani@mvista.com
- *
- * First-level interrupt dispatcher for Ocelot-3 board.
- *
- * 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 <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/addrspace.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-
-/*
- * First level interrupt dispatcher for Ocelot-3 board
- */
-               .align  5
-               NESTED(ocelot3_handle_int, PT_SIZE, sp)
-               SAVE_ALL
-               CLI
-               .set    at
-
-               mfc0    t0, CP0_CAUSE
-               mfc0    t2, CP0_STATUS
-
-               and     t0, t2
-
-               andi    t1, t0, STATUSF_IP0     /* sw0 software interrupt (IRQ0) */
-               bnez    t1, ll_sw0_irq
-
-               andi    t1, t0, STATUSF_IP1     /* sw1 software interrupt (IRQ1) */
-               bnez    t1, ll_sw1_irq
-
-               andi    t1, t0, STATUSF_IP2     /* int0 hardware line (IRQ2) */
-               bnez    t1, ll_pci0slot1_irq
-
-               andi    t1, t0, STATUSF_IP3     /* int1 hardware line (IRQ3) */
-               bnez    t1, ll_pci0slot2_irq
-
-               andi    t1, t0, STATUSF_IP4     /* int2 hardware line (IRQ4) */
-               bnez    t1, ll_pci1slot1_irq
-
-               andi    t1, t0, STATUSF_IP5     /* int3 hardware line (IRQ5) */
-               bnez    t1, ll_pci1slot2_irq
-
-               andi    t1, t0, STATUSF_IP6     /* int4 hardware line (IRQ6) */
-               bnez    t1, ll_uart_irq
-
-               andi    t1, t0, STATUSF_IP7     /* cpu timer (IRQ7) */
-               bnez    t1, ll_cputimer_irq
-
-                /* now look at extended interrupts */
-                mfc0    t0, CP0_CAUSE
-                cfc0    t1, CP0_S1_INTCONTROL
-
-                /* shift the mask 8 bits left to line up the bits */
-                sll     t2, t1, 8
-
-                and     t0, t2
-                srl     t0, t0, 16
-
-                andi    t1, t0, STATUSF_IP8     /* int6 hardware line (IRQ9) */
-                bnez    t1, ll_mv64340_decode_irq
-
-               .set    reorder
-
-               /* wrong alarm or masked ... */
-               j       spurious_interrupt
-               nop
-               END(ocelot3_handle_int)
-
-               .align  5
-ll_sw0_irq:
-               li      a0, 0           /* IRQ 1 */
-               move    a1, sp
-               jal     do_IRQ
-               j       ret_from_irq
-ll_sw1_irq:
-               li      a0, 1           /* IRQ 2 */
-               move    a1, sp
-               jal     do_IRQ
-               j       ret_from_irq
-
-ll_pci0slot1_irq:
-               li      a0, 2           /* IRQ 3 */
-               move    a1, sp
-               jal     do_IRQ
-               j       ret_from_irq
-
-ll_pci0slot2_irq:
-               li      a0, 3           /* IRQ 4 */
-               move    a1, sp
-               jal     do_IRQ
-               j       ret_from_irq
-
-ll_pci1slot1_irq:
-               li      a0, 4           /* IRQ 5 */
-               move    a1, sp
-               jal     do_IRQ
-               j       ret_from_irq
-
-ll_pci1slot2_irq:
-               li      a0, 5           /* IRQ 6 */
-               move    a1, sp
-               jal     do_IRQ
-               j       ret_from_irq
-
-ll_uart_irq:
-               li      a0, 6           /* IRQ 7 */
-               move    a1, sp
-               jal     do_IRQ
-               j       ret_from_irq
-
-ll_cputimer_irq:
-               li      a0, 7           /* IRQ 8 */
-               move    a1, sp
-               jal     do_IRQ
-               j       ret_from_irq
-
-ll_mv64340_decode_irq:
-               move    a0, sp
-               jal     ll_mv64340_irq
-               j       ret_from_irq
-
index 42464dbd4ad24d50fe07bab2dacda8ca0150fc0c..87c63c340ae3f4124f50887a07aa644b07efa414 100644 (file)
@@ -53,8 +53,6 @@
 #include <asm/mipsregs.h>
 #include <asm/system.h>
 
-extern asmlinkage void ocelot3_handle_int(void);
-
 static struct irqaction cascade_mv64340 = {
        no_action, SA_INTERRUPT, CPU_MASK_NONE, "MV64340-Cascade", NULL, NULL
 };
@@ -67,9 +65,6 @@ void __init arch_init_irq(void)
         */
        clear_c0_status(ST0_IM | ST0_BEV);
 
-       /* Sets the first-level interrupt dispatcher. */
-       set_except_vector(0, ocelot3_handle_int);
-       mips_cpu_irq_init(0);
        rm7k_cpu_irq_init(8);
 
        /* set up the cascading interrupts */
@@ -79,3 +74,36 @@ void __init arch_init_irq(void)
        set_c0_status(ST0_IM); /* IE in the status register */
 
 }
+
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+       unsigned int pending = read_c0_cause() & read_c0_status();
+
+       if (pending & STATUSF_IP0)
+               do_IRQ(0, regs);
+       else if (pending & STATUSF_IP1)
+               do_IRQ(1, regs);
+       else if (pending & STATUSF_IP2)
+               do_IRQ(2, regs);
+       else if (pending & STATUSF_IP3)
+               do_IRQ(3, regs);
+       else if (pending & STATUSF_IP4)
+               do_IRQ(4, regs);
+       else if (pending & STATUSF_IP5)
+               do_IRQ(5, regs);
+       else if (pending & STATUSF_IP6)
+               do_IRQ(6, regs);
+       else if (pending & STATUSF_IP7)
+               do_IRQ(7, regs);
+       else {
+               /*
+                * Now look at the extended interrupts
+                */
+               pending = (read_c0_cause() & (read_c0_intcontrol() << 8)) >> 16;
+
+               if (pending & STATUSF_IP8)
+                       ll_mv64340_irq(regs);
+               else
+                       spurious_interrupt(regs);
+       }
+}
index 370e75d0e75cdf2d4897806a0c47d59a6ff3df0e..c69195234309687d3f03d52aa6a3fbace55fefbb 100644 (file)
@@ -329,22 +329,22 @@ void __init plat_setup(void)
        /* shut down ethernet ports, just to be sure our memory doesn't get
         * corrupted by random ethernet traffic.
         */
-       MV_WRITE(MV64340_ETH_TRANSMIT_QUEUE_COMMAND_REG(0), 0xff << 8);
-       MV_WRITE(MV64340_ETH_TRANSMIT_QUEUE_COMMAND_REG(1), 0xff << 8);
-       MV_WRITE(MV64340_ETH_RECEIVE_QUEUE_COMMAND_REG(0), 0xff << 8);
-       MV_WRITE(MV64340_ETH_RECEIVE_QUEUE_COMMAND_REG(1), 0xff << 8);
+       MV_WRITE(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(0), 0xff << 8);
+       MV_WRITE(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(1), 0xff << 8);
+       MV_WRITE(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(0), 0xff << 8);
+       MV_WRITE(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(1), 0xff << 8);
        do {}
-         while (MV_READ(MV64340_ETH_RECEIVE_QUEUE_COMMAND_REG(0)) & 0xff);
+         while (MV_READ(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(0)) & 0xff);
        do {}
-         while (MV_READ(MV64340_ETH_RECEIVE_QUEUE_COMMAND_REG(1)) & 0xff);
+         while (MV_READ(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(1)) & 0xff);
        do {}
-         while (MV_READ(MV64340_ETH_TRANSMIT_QUEUE_COMMAND_REG(0)) & 0xff);
+         while (MV_READ(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(0)) & 0xff);
        do {}
-         while (MV_READ(MV64340_ETH_TRANSMIT_QUEUE_COMMAND_REG(1)) & 0xff);
-       MV_WRITE(MV64340_ETH_PORT_SERIAL_CONTROL_REG(0),
-                MV_READ(MV64340_ETH_PORT_SERIAL_CONTROL_REG(0)) & ~1);
-       MV_WRITE(MV64340_ETH_PORT_SERIAL_CONTROL_REG(1),
-                MV_READ(MV64340_ETH_PORT_SERIAL_CONTROL_REG(1)) & ~1);
+         while (MV_READ(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(1)) & 0xff);
+       MV_WRITE(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(0),
+                MV_READ(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(0)) & ~1);
+       MV_WRITE(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(1),
+                MV_READ(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(1)) & ~1);
 
        /* Turn off the Bit-Error LED */
        OCELOT_FPGA_WRITE(0x80, CLR);
index 91240777f978703fa9abf465575baeaa7d0c6c49..94802b4db472848545361ed68ed25da0b3544cf3 100644 (file)
@@ -2,7 +2,7 @@
 # Makefile for Momentum Computer's Ocelot-C and -CS boards.
 #
 
-obj-y                  += cpci-irq.o int-handler.o irq.o prom.o reset.o \
+obj-y                  += cpci-irq.o irq.o prom.o reset.o \
                           setup.o uart-irq.o
 
 obj-$(CONFIG_KGDB)     += dbg_io.o
diff --git a/arch/mips/momentum/ocelot_c/int-handler.S b/arch/mips/momentum/ocelot_c/int-handler.S
deleted file mode 100644 (file)
index 52349d9..0000000
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Copyright 2002 Momentum Computer Inc.
- * Author: Matthew Dharm <mdharm@momenco.com>
- *
- * Copyright 2001 MontaVista Software Inc.
- * Author: jsun@mvista.com or jsun@junsun.net
- *
- * First-level interrupt dispatcher for Ocelot-CS board.
- *
- * 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 <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/addrspace.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-#include "ocelot_c_fpga.h"
-
-/*
- * First level interrupt dispatcher for Ocelot-CS board
- */
-               .align  5
-               NESTED(ocelot_handle_int, PT_SIZE, sp)
-               SAVE_ALL
-               CLI
-               .set    at
-               mfc0    t0, CP0_CAUSE
-               mfc0    t2, CP0_STATUS
-
-               and     t0, t2
-
-               andi    t1, t0, STATUSF_IP0     /* sw0 software interrupt */
-               bnez    t1, ll_sw0_irq
-               andi    t1, t0, STATUSF_IP1     /* sw1 software interrupt */
-               bnez    t1, ll_sw1_irq
-               andi    t1, t0, STATUSF_IP2     /* int0 hardware line */
-               bnez    t1, ll_scsi_irq
-               andi    t1, t0, STATUSF_IP3     /* int1 hardware line */
-               bnez    t1, ll_uart_decode_irq
-               andi    t1, t0, STATUSF_IP4     /* int2 hardware line */
-               bnez    t1, ll_pmc_irq
-               andi    t1, t0, STATUSF_IP5     /* int3 hardware line */
-               bnez    t1, ll_cpci_decode_irq
-               andi    t1, t0, STATUSF_IP6     /* int4 hardware line */
-               bnez    t1, ll_mv64340_decode_irq
-               andi    t1, t0, STATUSF_IP7     /* cpu timer */
-               bnez    t1, ll_cputimer_irq
-
-               .set    reorder
-
-               /* wrong alarm or masked ... */
-               j       spurious_interrupt
-               nop
-               END(ocelot_handle_int)
-
-               .align  5
-ll_sw0_irq:
-               li      a0, 0
-               move    a1, sp
-               jal     do_IRQ
-               j       ret_from_irq
-ll_sw1_irq:
-               li      a0, 1
-               move    a1, sp
-               jal     do_IRQ
-               j       ret_from_irq
-ll_scsi_irq:
-               li      a0, 2
-               move    a1, sp
-               jal     do_IRQ
-               j       ret_from_irq
-
-ll_uart_decode_irq:
-               move    a0, sp
-               jal     ll_uart_irq
-               j       ret_from_irq
-
-ll_pmc_irq:
-               li      a0, 4
-               move    a1, sp
-               jal     do_IRQ
-               j       ret_from_irq
-
-ll_cpci_decode_irq:
-               move    a0, sp
-               jal     ll_cpci_irq
-               j       ret_from_irq
-
-ll_mv64340_decode_irq:
-               move    a0, sp
-               jal     ll_mv64340_irq
-               j       ret_from_irq
-
-ll_cputimer_irq:
-               li      a0, 7
-               move    a1, sp
-               jal     do_IRQ
-               j       ret_from_irq
-
index a5764bc20e36593df6d96ff6b25c1407106d9c53..86f61ce59e53b33d205040f14a903e6e44f37882 100644 (file)
@@ -48,7 +48,6 @@
 #include <asm/mipsregs.h>
 #include <asm/system.h>
 
-extern asmlinkage void ocelot_handle_int(void);
 extern void uart_irq_init(void);
 extern void cpci_irq_init(void);
 
@@ -60,6 +59,33 @@ static struct irqaction cascade_mv64340 = {
        no_action, SA_INTERRUPT, CPU_MASK_NONE, "cascade via MV64340", NULL, NULL
 };
 
+extern void ll_uart_irq(struct pt_regs *regs);
+extern void ll_cpci_irq(struct pt_regs *regs);
+
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+       unsigned int pending = read_c0_cause() & read_c0_status();
+
+       if (pending & STATUSF_IP0)
+               do_IRQ(0, regs);
+       else if (pending & STATUSF_IP1)
+               do_IRQ(1, regs);
+       else if (pending & STATUSF_IP2)
+               do_IRQ(2, regs);
+       else if (pending & STATUSF_IP3)
+               ll_uart_irq(regs);
+       else if (pending & STATUSF_IP4)
+               do_IRQ(4, regs);
+       else if (pending & STATUSF_IP5)
+               ll_cpci_irq(regs);
+       else if (pending & STATUSF_IP6)
+               ll_mv64340_irq(regs);
+       else if (pending & STATUSF_IP7)
+               do_IRQ(7, regs);
+       else
+               spurious_interrupt(regs);
+}
+
 void __init arch_init_irq(void)
 {
        /*
@@ -68,8 +94,6 @@ void __init arch_init_irq(void)
         */
        clear_c0_status(ST0_IM);
 
-       /* Sets the first-level interrupt dispatcher. */
-       set_except_vector(0, ocelot_handle_int);
        mips_cpu_irq_init(0);
 
        /* set up the cascading interrupts */
index e5f1cb08697324ad3d7d3824a49989baad9bf022..adb5665d40a950cf19f3f6ace46dba092ffc4e44 100644 (file)
@@ -2,7 +2,7 @@
 # Makefile for Momentum Computer's Ocelot-G board.
 #
 
-obj-y                  += int-handler.o irq.o gt-irq.o prom.o reset.o setup.o
+obj-y                  += irq.o gt-irq.o prom.o reset.o setup.o
 obj-$(CONFIG_KGDB)     += dbg_io.o
 
 EXTRA_AFLAGS := $(CFLAGS)
diff --git a/arch/mips/momentum/ocelot_g/int-handler.S b/arch/mips/momentum/ocelot_g/int-handler.S
deleted file mode 100644 (file)
index 772e8f7..0000000
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * Copyright 2001 MontaVista Software Inc.
- * Author: jsun@mvista.com or jsun@junsun.net
- *
- * First-level interrupt dispatcher for ocelot board.
- *
- * 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 <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/addrspace.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-
-/*
- * first level interrupt dispatcher for ocelot board -
- * We check for the timer first, then check PCI ints A and D.
- * Then check for serial IRQ and fall through.
- */
-               .align  5
-               NESTED(ocelot_handle_int, PT_SIZE, sp)
-               SAVE_ALL
-               CLI
-               .set    at
-               mfc0    t0, CP0_CAUSE
-               mfc0    t2, CP0_STATUS
-
-               and     t0, t2
-
-                andi   t1, t0, STATUSF_IP2     /* int0 hardware line */
-               bnez    t1, ll_pri_enet_irq
-                andi   t1, t0, STATUSF_IP3     /* int1 hardware line */
-               bnez    t1, ll_sec_enet_irq
-                andi   t1, t0, STATUSF_IP4     /* int2 hardware line */
-               bnez    t1, ll_uart_irq
-                andi   t1, t0, STATUSF_IP5     /* int3 hardware line */
-               bnez    t1, ll_cpci_irq
-                andi   t1, t0, STATUSF_IP6     /* int4 hardware line */
-               bnez    t1, ll_galileo_p0_irq
-                andi   t1, t0, STATUSF_IP7     /* cpu timer */
-               bnez    t1, ll_cputimer_irq
-
-                /* now look at the extended interrupts */
-               mfc0    t0, CP0_CAUSE
-               cfc0    t1, CP0_S1_INTCONTROL
-
-               /* shift the mask 8 bits left to line up the bits */
-                sll    t2, t1, 8
-
-                and    t0, t2
-                srl    t0, t0, 16
-
-                andi   t1, t0, STATUSF_IP8     /* int6 hardware line */
-               bnez    t1, ll_galileo_p1_irq
-                andi   t1, t0, STATUSF_IP9     /* int7 hardware line */
-               bnez    t1, ll_pmc_irq
-                andi   t1, t0, STATUSF_IP10    /* int8 hardware line */
-               bnez    t1, ll_cpci_abcd_irq
-                andi   t1, t0, STATUSF_IP11    /* int9 hardware line */
-               bnez    t1, ll_testpoint_irq
-
-               .set    reorder
-
-               /* wrong alarm or masked ... */
-               j       spurious_interrupt
-               nop
-               END(ocelot_handle_int)
-
-               .align  5
-ll_pri_enet_irq:
-               li      a0, 2
-               move    a1, sp
-               jal     do_IRQ
-               j       ret_from_irq
-
-ll_sec_enet_irq:
-               li      a0, 3
-               move    a1, sp
-               jal     do_IRQ
-               j       ret_from_irq
-
-ll_uart_irq:
-               li      a0, 4
-               move    a1, sp
-               jal     do_IRQ
-               j       ret_from_irq
-
-ll_cpci_irq:
-               li      a0, 5
-               move    a1, sp
-               jal     do_IRQ
-               j       ret_from_irq
-
-ll_galileo_p0_irq:
-               li      a0, 6
-               move    a1, sp
-               jal     do_IRQ
-               j       ret_from_irq
-
-ll_cputimer_irq:
-               li      a0, 7
-               move    a1, sp
-               jal     do_IRQ
-               j       ret_from_irq
-
-ll_galileo_p1_irq:
-               li      a0, 8
-               move    a1, sp
-               jal     do_IRQ
-               j       ret_from_irq
-
-ll_pmc_irq:
-               li      a0, 9
-               move    a1, sp
-               jal     do_IRQ
-               j       ret_from_irq
-
-ll_cpci_abcd_irq:
-               li      a0, 10
-               move    a1, sp
-               jal     do_IRQ
-               j       ret_from_irq
-
-ll_testpoint_irq:
-               li      a0, 11
-               move    a1, sp
-               jal     do_IRQ
-               j       ret_from_irq
index 5eb85b1642051b3f9cf036d76d7d79847716c6aa..7a4a419804f19f0c202f6dcc6c3ea91d9d100231 100644 (file)
 #include <asm/mipsregs.h>
 #include <asm/system.h>
 
-extern asmlinkage void ocelot_handle_int(void);
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+       unsigned int pending = read_c0_cause() & read_c0_status();
+
+       if (pending & STATUSF_IP2)
+               do_IRQ(2, regs);
+       else if (pending & STATUSF_IP3)
+               do_IRQ(3, regs);
+       else if (pending & STATUSF_IP4)
+               do_IRQ(4, regs);
+       else if (pending & STATUSF_IP5)
+               do_IRQ(5, regs);
+       else if (pending & STATUSF_IP6)
+               do_IRQ(6, regs);
+       else if (pending & STATUSF_IP7)
+               do_IRQ(7, regs);
+       else {
+               /*
+                * Now look at the extended interrupts
+                */
+               pending = (read_c0_cause() & (read_c0_intcontrol() << 8)) >> 16;
+
+               if (pending & STATUSF_IP8)
+                       do_IRQ(8, regs);
+               else if (pending & STATUSF_IP9)
+                       do_IRQ(9, regs);
+               else if (pending & STATUSF_IP10)
+                       do_IRQ(10, regs);
+               else if (pending & STATUSF_IP11)
+                       do_IRQ(11, regs);
+               else
+                       spurious_interrupt(regs);
+       }
+}
+
 extern void gt64240_irq_init(void);
 
 void __init arch_init_irq(void)
@@ -60,8 +94,6 @@ void __init arch_init_irq(void)
        clear_c0_status(ST0_IM);
        local_irq_disable();
 
-       /* Sets the first-level interrupt dispatcher. */
-       set_except_vector(0, ocelot_handle_int);
        mips_cpu_irq_init(0);
        rm7k_cpu_irq_init(8);
 
index 6e38f3bc443c6a590ef7e41665c9e54b7180676b..b7c638166e9f3a9927239f495e67a8429223c569 100644 (file)
@@ -22,6 +22,6 @@
 # under Linux.
 #
 
-obj-y := setup.o prom.o mipsIRQ.o int.o reset.o time.o proc.o platform.o
+obj-y := setup.o prom.o int.o reset.o time.o proc.o platform.o
 obj-$(CONFIG_PCI) += pci.o
 obj-$(CONFIG_KGDB) += gdb_hook.o
index c500e2d41f2c5f8d6c30ee843a98ca50f3576233..39ee6314f62757279e12118448a04b70713fb2a7 100644 (file)
@@ -38,8 +38,6 @@
 #include <int.h>
 #include <uart.h>
 
-extern asmlinkage void cp0_irqdispatch(void);
-
 static DEFINE_SPINLOCK(irq_lock);
 
 /* default prio for interrupts */
@@ -55,7 +53,7 @@ static char gic_prio[PNX8550_INT_GIC_TOTINT] = {
        1                       //  70
 };
 
-void hw0_irqdispatch(int irq, struct pt_regs *regs)
+static void hw0_irqdispatch(int irq, struct pt_regs *regs)
 {
        /* find out which interrupt */
        irq = PNX8550_GIC_VECTOR_0 >> 3;
@@ -68,7 +66,7 @@ void hw0_irqdispatch(int irq, struct pt_regs *regs)
 }
 
 
-void timer_irqdispatch(int irq, struct pt_regs *regs)
+static void timer_irqdispatch(int irq, struct pt_regs *regs)
 {
        irq = (0x01c0 & read_c0_config7()) >> 6;
 
@@ -88,6 +86,20 @@ void timer_irqdispatch(int irq, struct pt_regs *regs)
        }
 }
 
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+       unsigned int pending = read_c0_status() & read_c0_cause();
+
+       if (pending & STATUSF_IP2)
+               do_IRQ(2, regs);
+       else if (pending & STATUSF_IP7) {
+               if (read_c0_config7() & 0x01c0)
+                       timer_irqdispatch(7, regs);
+       }
+
+       spurious_interrupt(regs);
+}
+
 static inline void modify_cp0_intmask(unsigned clr_mask, unsigned set_mask)
 {
        unsigned long status = read_c0_status();
@@ -223,9 +235,6 @@ void __init arch_init_irq(void)
        int i;
        int configPR;
 
-       /* init of cp0 interrupts */
-       set_except_vector(0, cp0_irqdispatch);
-
        for (i = 0; i < PNX8550_INT_CP0_TOTINT; i++) {
                irq_desc[i].handler = &level_irq_type;
                pnx8550_ack(i); /* mask the irq just in case  */
diff --git a/arch/mips/philips/pnx8550/common/mipsIRQ.S b/arch/mips/philips/pnx8550/common/mipsIRQ.S
deleted file mode 100644 (file)
index 338bffd..0000000
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright (c) 2002 Philips, Inc. All rights.
- * Copyright (c) 2002 Red Hat, Inc. All rights.
- *
- * This software may be freely redistributed under the terms of the
- * GNU General Public License.
- *
- * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Based upon arch/mips/galileo-boards/ev64240/int-handler.S
- *
- */
-#include <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/addrspace.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-
-/*
- * cp0_irqdispatch
- *
- *    Code to handle in-core interrupt exception.
- */
-
-               .align  5
-               .set    reorder
-               .set    noat
-               NESTED(cp0_irqdispatch, PT_SIZE, sp)
-               SAVE_ALL
-               CLI
-               .set    at
-               mfc0    t0,CP0_CAUSE
-               mfc0    t2,CP0_STATUS
-
-               and     t0,t2
-
-               andi    t1,t0,STATUSF_IP2 /* int0 hardware line */
-               bnez    t1,ll_hw0_irq
-               nop
-
-               andi    t1,t0,STATUSF_IP7 /* int5 hardware line */
-               bnez    t1,ll_timer_irq
-               nop
-
-               /* wrong alarm or masked ... */
-
-               j       spurious_interrupt
-               nop
-               END(cp0_irqdispatch)
-
-               .align  5
-               .set    reorder
-ll_hw0_irq:
-               li      a0,2
-               move    a1,sp
-               jal     hw0_irqdispatch
-               nop
-               j       ret_from_irq
-               nop
-
-               .align  5
-               .set    reorder
-ll_timer_irq:
-               mfc0    t3,CP0_CONFIG,7
-               andi    t4,t3,0x01c0
-               beqz    t4,ll_timer_out
-               nop
-               li      a0,7
-               move    a1,sp
-               jal     timer_irqdispatch
-               nop
-
-ll_timer_out:  j       ret_from_irq
-               nop
index a592260fd6735b8a902e6939ddbd7826dcd0dec1..5436b4b97455f8ce95fffed943685d7eee5fda48 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/resource.h>
 #include <linux/serial.h>
 #include <linux/serial_ip3106.h>
+#include <linux/platform_device.h>
 
 #include <int.h>
 #include <usb.h>
index ae96a71a3089612e50c529bc8cf582315e01d1e2..e931e0d44229eee58b16b2cdc17c33965d9665ed 100644 (file)
@@ -2,7 +2,7 @@
 # Makefile for the PMC-Sierra Titan
 #
 
-obj-y    += irq-handler.o irq.o i2c-yosemite.o prom.o py-console.o setup.o
+obj-y    += irq.o i2c-yosemite.o prom.o py-console.o setup.o
 
 obj-$(CONFIG_KGDB)             += dbg_io.o
 obj-$(CONFIG_SMP)              += smp.o
diff --git a/arch/mips/pmc-sierra/yosemite/irq-handler.S b/arch/mips/pmc-sierra/yosemite/irq-handler.S
deleted file mode 100644 (file)
index 33b9c40..0000000
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Copyright 2003, 04 PMC-Sierra Inc.
- * Author: Manish Lachwani (lachwani@pmc-sierra.com
- * Copyright 2004 Ralf Baechle (ralf@linux-mips.org)
- *
- * First-level interrupt router for the PMC-Sierra Titan board
- *
- * 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.
- *
- * Titan supports Hypertransport or PCI but not both. Hence, one interrupt
- * line is shared between the PCI slot A and Hypertransport. This is the
- * Processor INTB #0.
- */
-
-#include <linux/config.h>
-#include <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/addrspace.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-
-               .align  5
-               NESTED(titan_handle_int, PT_SIZE, sp)
-               SAVE_ALL
-               CLI
-               .set    at
-               .set    noreorder
-               la      ra, ret_from_irq
-               mfc0    t0, CP0_CAUSE
-               mfc0    t2, CP0_STATUS
-
-               and     t0, t2
-
-               andi    t2, t0, STATUSF_IP7     /* INTB5 hardware line */
-               bnez    t2, ll_timer_irq        /* Timer */
-               andi    t1, t0, STATUSF_IP2     /* INTB0 hardware line */
-               bnez    t1, ll_pcia_irq         /* 64-bit PCI */
-               andi    t2, t0, STATUSF_IP3     /* INTB1 hardware line */
-               bnez    t2, ll_pcib_irq         /* second 64-bit PCI slot */
-               andi    t1, t0, STATUSF_IP4     /* INTB2 hardware line */
-               bnez    t1, ll_duart_irq        /* UART */
-               andi    t2, t0, STATUSF_IP5     /* SMP inter-core interrupts */
-               bnez    t2, ll_smp_irq
-               andi    t1, t0, STATUSF_IP6
-               bnez    t1, ll_ht_irq           /* Hypertransport */
-
-               move    a0, sp
-               j       do_extended_irq
-               END(titan_handle_int)
-
-               .set    reorder
-               .align  5
-
-ll_pcia_irq:
-               li      a0, 2
-               move    a1, sp
-#ifdef CONFIG_HYPERTRANSPORT
-               j       ll_ht_smp_irq_handler
-#else
-               j       do_IRQ
-#endif
-
-ll_pcib_irq:
-               li      a0, 3
-               move    a1, sp
-               j       do_IRQ
-
-ll_duart_irq:
-               li      a0, 4
-               move    a1, sp
-               j       do_IRQ
-
-ll_smp_irq:
-               li      a0, 5
-               move    a1, sp
-#ifdef CONFIG_SMP
-               j       titan_mailbox_irq
-#else
-               j       do_IRQ
-#endif
-
-ll_ht_irq:
-               li      a0, 6
-               move    a1, sp
-               j       ll_ht_smp_irq_handler
-
-ll_timer_irq:
-               li      a0, 7
-               move    a1, sp
-               j       do_IRQ
index f4e2897d9bf73af83623a4fdefb94012b0da3bcf..a1f524fc4c107feb18ba11024c35fa0f7b49b963 100644 (file)
@@ -2,6 +2,8 @@
  * Copyright (C) 2003 PMC-Sierra Inc.
  * Author: Manish Lachwani (lachwani@pmc-sierra.com)
  *
+ * Copyright (C) 2006 Ralf Baechle (ralf@linux-mips.org)
+ *
  *  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
@@ -55,7 +57,6 @@
 #define HYPERTRANSPORT_INTC     0x7a           /* INTC# */
 #define HYPERTRANSPORT_INTD     0x7b           /* INTD# */
 
-extern asmlinkage void titan_handle_int(void);
 extern void jaguar_mailbox_irq(struct pt_regs *);
 
 /*
@@ -125,6 +126,35 @@ asmlinkage void do_extended_irq(struct pt_regs *regs)
 
 }
 
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+       unsigned int cause = read_c0_cause();
+       unsigned int status = read_c0_status();
+       unsigned int pending = cause & status;
+
+       if (pending & STATUSF_IP7) {
+               do_IRQ(7, regs);
+       } else if (pending & STATUSF_IP2) {
+#ifdef CONFIG_HYPERTRANSPORT
+               ll_ht_smp_irq_handler(2, regs);
+#else
+               do_IRQ(2, regs);
+#endif
+       } else if (pending & STATUSF_IP3) {
+               do_IRQ(3, regs);
+       } else if (pending & STATUSF_IP4) {
+               do_IRQ(4, regs);
+       } else if (pending & STATUSF_IP5) {
+#ifdef CONFIG_SMP
+               titan_mailbox_irq(regs);
+#else
+               do_IRQ(5, regs);
+#endif
+       } else if (pending & STATUSF_IP6) {
+               do_IRQ(4, regs);
+       }
+}
+
 #ifdef CONFIG_KGDB
 extern void init_second_port(void);
 #endif
@@ -136,7 +166,6 @@ void __init arch_init_irq(void)
 {
        clear_c0_status(ST0_IM);
 
-       set_except_vector(0, titan_handle_int);
        mips_cpu_irq_init(0);
        rm7k_cpu_irq_init(8);
        rm9k_cpu_irq_init(12);
index 6a8e8bcef5528181dec4943c60f2d3635a150201..730f459f3e9920e0efeaa257ad88063eb8ed0265 100644 (file)
@@ -2,6 +2,6 @@
 # Makefile for Qemu specific kernel interface routines under Linux.
 #
 
-obj-y          = q-firmware.o q-int.o q-irq.o q-mem.o q-setup.o
+obj-y          = q-firmware.o q-irq.o q-mem.o q-setup.o
 
 obj-$(CONFIG_SMP) += q-smp.o
diff --git a/arch/mips/qemu/q-int.S b/arch/mips/qemu/q-int.S
deleted file mode 100644 (file)
index 6e3dfe5..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- * Qemu interrupt handler code.
- *
- * Copyright (C) 2005 by Ralf Baechle
- */
-#include <asm/asm.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-
-       .align  5
-       NESTED(qemu_handle_int, PT_SIZE, sp)
-       SAVE_ALL
-       CLI
-       move    a0, sp
-       PTR_LA  ra, ret_from_irq
-       j       do_qemu_int
-       END(qemu_handle_int)
index 2c4e0704ff10d4b6f90bdd62b053dae468088ac4..3352374c4c7d2ed9bd2e21249fe8276b4ef8c445 100644 (file)
@@ -9,7 +9,7 @@
 
 extern asmlinkage void qemu_handle_int(void);
 
-asmlinkage void do_qemu_int(struct pt_regs *regs)
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
 {
        unsigned int pending = read_c0_status() & read_c0_cause();
 
@@ -29,7 +29,6 @@ asmlinkage void do_qemu_int(struct pt_regs *regs)
 
 void __init arch_init_irq(void)
 {
-       set_except_vector(0, qemu_handle_int);
        mips_hpt_frequency = QEMU_C0_COUNTER_CLOCK;             /* 100MHz */
 
        init_i8259_irqs();
index eb0820fe50bd4e33b390c2df3eddc5b805ef728d..6aa4c0cd169ce513eba9dcafadd98faf2f797cb6 100644 (file)
@@ -3,7 +3,7 @@
 # under Linux.
 #
 
-obj-y  += ip22-mc.o ip22-hpc.o ip22-int.o ip22-irq.o ip22-berr.o \
+obj-y  += ip22-mc.o ip22-hpc.o ip22-int.o ip22-berr.o \
           ip22-time.o ip22-nvram.o ip22-reset.o ip22-setup.o
 
 obj-$(CONFIG_EISA)     += ip22-eisa.o
index d16fb43b1a93ba745f2a9838247f7bd1f845f932..fc6a7e2b189ccd90224c54dbf6ac4ae62ba99b68 100644 (file)
@@ -37,7 +37,6 @@ static char lc1msk_to_irqnr[256];
 static char lc2msk_to_irqnr[256];
 static char lc3msk_to_irqnr[256];
 
-extern asmlinkage void indyIRQ(void);
 extern int ip22_eisa_init(void);
 
 static void enable_local0_irq(unsigned int irq)
@@ -224,7 +223,7 @@ static struct hw_interrupt_type ip22_local3_irq_type = {
        .end            = end_local3_irq,
 };
 
-void indy_local0_irqdispatch(struct pt_regs *regs)
+static void indy_local0_irqdispatch(struct pt_regs *regs)
 {
        u8 mask = sgint->istat0 & sgint->imask0;
        u8 mask2;
@@ -242,7 +241,7 @@ void indy_local0_irqdispatch(struct pt_regs *regs)
        return;
 }
 
-void indy_local1_irqdispatch(struct pt_regs *regs)
+static void indy_local1_irqdispatch(struct pt_regs *regs)
 {
        u8 mask = sgint->istat1 & sgint->imask1;
        u8 mask2;
@@ -262,7 +261,7 @@ void indy_local1_irqdispatch(struct pt_regs *regs)
 
 extern void ip22_be_interrupt(int irq, struct pt_regs *regs);
 
-void indy_buserror_irq(struct pt_regs *regs)
+static void indy_buserror_irq(struct pt_regs *regs)
 {
        int irq = SGI_BUSERR_IRQ;
 
@@ -307,6 +306,56 @@ static struct irqaction map1_cascade = {
 #define SGI_INTERRUPTS SGINT_LOCAL3
 #endif
 
+extern void indy_r4k_timer_interrupt(struct pt_regs *regs);
+extern void indy_8254timer_irq(struct pt_regs *regs);
+
+/*
+ * IRQs on the INDY look basically (barring software IRQs which we don't use
+ * at all) like:
+ *
+ *     MIPS IRQ        Source
+ *      --------        ------
+ *             0       Software (ignored)
+ *             1        Software (ignored)
+ *             2        Local IRQ level zero
+ *             3        Local IRQ level one
+ *             4        8254 Timer zero
+ *             5        8254 Timer one
+ *             6        Bus Error
+ *             7        R4k timer (what we use)
+ *
+ * We handle the IRQ according to _our_ priority which is:
+ *
+ * Highest ----     R4k Timer
+ *                  Local IRQ zero
+ *                  Local IRQ one
+ *                  Bus Error
+ *                  8254 Timer zero
+ * Lowest  ----     8254 Timer one
+ *
+ * then we just return, if multiple IRQs are pending then we will just take
+ * another exception, big deal.
+ */
+
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+       unsigned int pending = read_c0_cause();
+
+       /*
+        * First we check for r4k counter/timer IRQ.
+        */
+       if (pending & CAUSEF_IP7)
+               indy_r4k_timer_interrupt(regs);
+       else if (pending & CAUSEF_IP2)
+               indy_local0_irqdispatch(regs);
+       else if (pending & CAUSEF_IP3)
+               indy_local1_irqdispatch(regs);
+       else if (pending & CAUSEF_IP6)
+               indy_buserror_irq(regs);
+       else if (pending & (CAUSEF_IP4 | CAUSEF_IP5))
+               indy_8254timer_irq(regs);
+}
+
 extern void mips_cpu_irq_init(unsigned int irq_base);
 
 void __init arch_init_irq(void)
@@ -369,8 +418,6 @@ void __init arch_init_irq(void)
        sgint->cmeimask0 = 0;
        sgint->cmeimask1 = 0;
 
-       set_except_vector(0, indyIRQ);
-
        /* init CPU irqs */
        mips_cpu_irq_init(SGINT_CPU);
 
diff --git a/arch/mips/sgi-ip22/ip22-irq.S b/arch/mips/sgi-ip22/ip22-irq.S
deleted file mode 100644 (file)
index 6ccbd9e..0000000
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * ip22-irq.S: Interrupt exception dispatch code for FullHouse and
- *             Guiness.
- *
- * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
- */
-
-#include <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-
-/* A lot of complication here is taken away because:
- *
- * 1) We handle one interrupt and return, sitting in a loop and moving across
- *    all the pending IRQ bits in the cause register is _NOT_ the answer, the
- *    common case is one pending IRQ so optimize in that direction.
- *
- * 2) We need not check against bits in the status register IRQ mask, that
- *    would make this routine slow as hell.
- *
- * 3) Linux only thinks in terms of all IRQs on or all IRQs off, nothing in
- *    between like BSD spl() brain-damage.
- *
- * Furthermore, the IRQs on the INDY look basically (barring software IRQs
- * which we don't use at all) like:
- *
- *     MIPS IRQ        Source
- *      --------        ------
- *             0       Software (ignored)
- *             1        Software (ignored)
- *             2        Local IRQ level zero
- *             3        Local IRQ level one
- *             4        8254 Timer zero
- *             5        8254 Timer one
- *             6        Bus Error
- *             7        R4k timer (what we use)
- *
- * We handle the IRQ according to _our_ priority which is:
- *
- * Highest ----     R4k Timer
- *                  Local IRQ zero
- *                  Local IRQ one
- *                  Bus Error
- *                  8254 Timer zero
- * Lowest  ----     8254 Timer one
- *
- * then we just return, if multiple IRQs are pending then we will just take
- * another exception, big deal.
- */
-
-       .text
-       .set    noreorder
-       .set    noat
-       .align  5
-       NESTED(indyIRQ, PT_SIZE, sp)
-       SAVE_ALL
-       CLI
-       .set    at
-       mfc0    s0, CP0_CAUSE           # get irq mask
-
-       /* First we check for r4k counter/timer IRQ. */
-       andi    a0, s0, CAUSEF_IP7
-       beq     a0, zero, 1f
-        andi   a0, s0, CAUSEF_IP2      # delay slot, check local level zero
-
-       /* Wheee, a timer interrupt. */
-       jal     indy_r4k_timer_interrupt
-        move   a0, sp                  # delay slot
-       j       ret_from_irq
-        nop                            # delay slot
-
-1:
-       beq     a0, zero, 1f
-        andi   a0, s0, CAUSEF_IP3      # delay slot, check local level one
-
-       /* Wheee, local level zero interrupt. */
-       jal     indy_local0_irqdispatch
-        move   a0, sp                  # delay slot
-
-       j       ret_from_irq
-        nop                            # delay slot
-
-1:
-       beq     a0, zero, 1f
-        andi   a0, s0, CAUSEF_IP6      # delay slot, check bus error
-
-       /* Wheee, local level one interrupt. */
-       jal     indy_local1_irqdispatch
-        move   a0, sp                  # delay slot
-       j       ret_from_irq
-        nop                            # delay slot
-
-1:
-       beq     a0, zero, 1f
-        andi   a0, s0, (CAUSEF_IP4 | CAUSEF_IP5)       # delay slot
-
-       /* Wheee, an asynchronous bus error... */
-       jal     indy_buserror_irq
-        move   a0, sp                  # delay slot
-       j       ret_from_irq
-        nop                            # delay slot
-
-1:
-       /* Here by mistake? It is possible, that by the time we take
-        * the exception the IRQ pin goes low, so just leave if this
-        * is the case.
-        */
-       beq     a0, zero, 1f
-        nop                            # delay slot
-
-       /* Must be one of the 8254 timers... */
-       jal     indy_8254timer_irq
-        move   a0, sp                  # delay slot
-1:
-       j       ret_from_irq
-        nop                            # delay slot
-       END(indyIRQ)
index 4ba340780c351bbce9d67a7cc0dc0652b935c78b..686ba14e2882495039bc73fc256fa73840f0b2b4 100644 (file)
@@ -2,7 +2,7 @@
 # Makefile for the IP27 specific kernel interface routines under Linux.
 #
 
-obj-y  := ip27-berr.o ip27-console.o ip27-irq.o ip27-init.o ip27-irq-glue.o \
+obj-y  := ip27-berr.o ip27-console.o ip27-irq.o ip27-init.o \
           ip27-klconfig.o ip27-klnuma.o ip27-memory.o ip27-nmi.o ip27-reset.o \
           ip27-timer.o ip27-hubio.o ip27-xtalk.o
 
index 32106131b0d08ded043f432a414115f97419cbcf..19f1512c8f2e3934a649d48d80e0630f93e96a48 100644 (file)
@@ -9,10 +9,6 @@ ip27-init.c:find_lbaord_real. DONE
 in irix?
 6. Investigate why things do not work without the setup_test() call
 being invoked on all nodes in ip27-memory.c.
-7. Too many CLIs in the locore handlers :
-For the low level handlers set up by set_except_vector(),
-__tlb_refill_debug_tramp, __xtlb_refill_debug_tramp and cacheerror,
-investigate whether the code should do CLI, STI or KMODE.
 8. Too many do_page_faults invoked - investigate.
 9. start_thread must turn off UX64 ... and define tlb_refill_debug.
 10. Need a bad pmd table, bad pte table. __bad_pmd_table/__bad_pagetable
diff --git a/arch/mips/sgi-ip27/ip27-irq-glue.S b/arch/mips/sgi-ip27/ip27-irq-glue.S
deleted file mode 100644 (file)
index c304df7..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 1999 Ralf Baechle
- * Copyright (C) 1999 Silicon Graphics, Inc.
- */
-#include <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-
-       .text
-       .align  5
-NESTED(ip27_irq, PT_SIZE, sp)
-       SAVE_ALL
-       CLI
-
-       mfc0    s0, CP0_CAUSE
-       mfc0    t0, CP0_STATUS
-       and     s0, t0
-       move    a0, sp
-       PTR_LA  ra, ret_from_irq
-
-       /* First check for RT interrupt.  */
-       andi    t0, s0, CAUSEF_IP4
-       bnez    t0, ip4
-       andi    t0, s0, CAUSEF_IP2
-       bnez    t0, ip2
-       andi    t0, s0, CAUSEF_IP3
-       bnez    t0, ip3
-       andi    t0, s0, CAUSEF_IP5
-       bnez    t0, ip5
-       andi    t0, s0, CAUSEF_IP6
-       bnez    t0, ip6
-       j       ra
-
-ip2:   j       ip27_do_irq_mask0       # PI_INT_PEND_0 or CC_PEND_{A|B}
-ip3:   j       ip27_do_irq_mask1       # PI_INT_PEND_1
-ip4:   j       ip27_rt_timer_interrupt
-ip5:   j       ip27_prof_timer
-ip6:   j       ip27_hub_error
-
-       END(ip27_irq)
index 2854ac4c9be13e0d75430de1f99eaef2ff070edb..2e643d2f51cbb7b909e859c5f4aae0cfbae1dde7 100644 (file)
@@ -130,7 +130,7 @@ static int ms1bit(unsigned long x)
  * Kanoj 05.13.00
  */
 
-void ip27_do_irq_mask0(struct pt_regs *regs)
+static void ip27_do_irq_mask0(struct pt_regs *regs)
 {
        int irq, swlevel;
        hubreg_t pend0, mask0;
@@ -171,7 +171,7 @@ void ip27_do_irq_mask0(struct pt_regs *regs)
        LOCAL_HUB_L(PI_INT_PEND0);
 }
 
-void ip27_do_irq_mask1(struct pt_regs *regs)
+static void ip27_do_irq_mask1(struct pt_regs *regs)
 {
        int irq, swlevel;
        hubreg_t pend1, mask1;
@@ -196,12 +196,12 @@ void ip27_do_irq_mask1(struct pt_regs *regs)
        LOCAL_HUB_L(PI_INT_PEND1);
 }
 
-void ip27_prof_timer(struct pt_regs *regs)
+static void ip27_prof_timer(struct pt_regs *regs)
 {
        panic("CPU %d got a profiling interrupt", smp_processor_id());
 }
 
-void ip27_hub_error(struct pt_regs *regs)
+static void ip27_hub_error(struct pt_regs *regs)
 {
        panic("CPU %d got a hub error interrupt", smp_processor_id());
 }
@@ -421,9 +421,26 @@ int __devinit request_bridge_irq(struct bridge_controller *bc)
        return irq;
 }
 
+extern void ip27_rt_timer_interrupt(struct pt_regs *regs);
+
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+       unsigned long pending = read_c0_cause() & read_c0_status();
+
+       if (pending & CAUSEF_IP4)
+               ip27_rt_timer_interrupt(regs);
+       else if (pending & CAUSEF_IP2)  /* PI_INT_PEND_0 or CC_PEND_{A|B} */
+               ip27_do_irq_mask0(regs);
+       else if (pending & CAUSEF_IP3)  /* PI_INT_PEND_1 */
+               ip27_do_irq_mask1(regs);
+       else if (pending & CAUSEF_IP5)
+               ip27_prof_timer(regs);
+       else if (pending & CAUSEF_IP6)
+               ip27_hub_error(regs);
+}
+
 void __init arch_init_irq(void)
 {
-       set_except_vector(0, ip27_irq);
 }
 
 void install_ipi(void)
index 470898f4afe15c4b855e55082ab938bd650dea46..530bf848c3d065fae9442b1175d3f4f5e6cceabb 100644 (file)
@@ -3,7 +3,7 @@
 # under Linux.
 #
 
-obj-y  += ip32-berr.o ip32-irq.o ip32-irq-glue.o ip32-setup.o ip32-reset.o \
+obj-y  += ip32-berr.o ip32-irq.o ip32-setup.o ip32-reset.o \
           crime.o ip32-memory.o
 
 EXTRA_AFLAGS := $(CFLAGS)
diff --git a/arch/mips/sgi-ip32/ip32-irq-glue.S b/arch/mips/sgi-ip32/ip32-irq-glue.S
deleted file mode 100644 (file)
index 200924e..0000000
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Low level interrupt handler for the SGI O2 aka IP32 aka Moosehead
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2000 Harald Koerfgen
- * Copyright (C) 2001 Keith M Wesolowski
- */
-#include <asm/asm.h>
-#include <asm/regdef.h>
-#include <asm/mipsregs.h>
-#include <asm/stackframe.h>
-#include <asm/addrspace.h>
-
-               .text
-               .set    noreorder
-               .set    noat
-               .align  5
-               NESTED(ip32_handle_int, PT_SIZE, ra)
-               .set    noat
-               SAVE_ALL
-               CLI                     # TEST: interrupts should be off
-               .set    at
-               .set    noreorder
-
-               mfc0    s0,CP0_CAUSE
-
-               andi    t1, s0, IE_IRQ0
-               bnez    t1, handle_irq0
-                andi   t1, s0, IE_IRQ1
-               bnez    t1, handle_irq1
-                andi   t1, s0, IE_IRQ2
-               bnez    t1, handle_irq2
-                andi   t1, s0, IE_IRQ3
-               bnez    t1, handle_irq3
-                andi   t1, s0, IE_IRQ4
-               bnez    t1, handle_irq4
-                andi   t1, s0, IE_IRQ5
-               bnez    t1, handle_irq5
-                nop
-
-               /* Either someone has triggered the "software interrupts"
-                * or we lost an interrupt somehow.  Ignore it.
-                */
-               j       ret_from_irq
-                nop
-
-handle_irq0:
-               jal     ip32_irq0
-                move   a0, sp
-               j       ret_from_irq
-                nop
-
-handle_irq1:
-               jal     ip32_irq1
-                move   a0, sp
-               j       ret_from_irq
-                nop
-
-handle_irq2:
-               jal     ip32_irq2
-                move   a0, sp
-               j       ret_from_irq
-                nop
-
-handle_irq3:
-               jal     ip32_irq3
-                move   a0, sp
-               j       ret_from_irq
-                nop
-
-handle_irq4:
-               jal     ip32_irq4
-                move   a0, sp
-               j       ret_from_irq
-                nop
-
-handle_irq5:
-               jal     ip32_irq5
-               move    a0, sp
-               j       ret_from_irq
-                nop
-
-               END(ip32_handle_int)
index 2eb22d692ed9bef6293f5345b68cdd0c6ba6e3c5..22a6df94b4a1e0ea81ae5602b710820b54014161 100644 (file)
@@ -130,8 +130,6 @@ struct irqaction memerr_irq = { crime_memerr_intr, SA_INTERRUPT,
 struct irqaction cpuerr_irq = { crime_cpuerr_intr, SA_INTERRUPT,
                        CPU_MASK_NONE, "CRIME CPU error", NULL, NULL };
 
-extern void ip32_handle_int(void);
-
 /*
  * For interrupts wired from a single device to the CPU.  Only the clock
  * uses this it seems, which is IRQ 0 and IP7.
@@ -503,7 +501,7 @@ static void ip32_unknown_interrupt(struct pt_regs *regs)
 
 /* CRIME 1.1 appears to deliver all interrupts to this one pin. */
 /* change this to loop over all edge-triggered irqs, exception masked out ones */
-void ip32_irq0(struct pt_regs *regs)
+static void ip32_irq0(struct pt_regs *regs)
 {
        uint64_t crime_int;
        int irq = 0;
@@ -520,31 +518,49 @@ void ip32_irq0(struct pt_regs *regs)
        do_IRQ(irq, regs);
 }
 
-void ip32_irq1(struct pt_regs *regs)
+static void ip32_irq1(struct pt_regs *regs)
 {
        ip32_unknown_interrupt(regs);
 }
 
-void ip32_irq2(struct pt_regs *regs)
+static void ip32_irq2(struct pt_regs *regs)
 {
        ip32_unknown_interrupt(regs);
 }
 
-void ip32_irq3(struct pt_regs *regs)
+static void ip32_irq3(struct pt_regs *regs)
 {
        ip32_unknown_interrupt(regs);
 }
 
-void ip32_irq4(struct pt_regs *regs)
+static void ip32_irq4(struct pt_regs *regs)
 {
        ip32_unknown_interrupt(regs);
 }
 
-void ip32_irq5(struct pt_regs *regs)
+static void ip32_irq5(struct pt_regs *regs)
 {
        ll_timer_interrupt(IP32_R4K_TIMER_IRQ, regs);
 }
 
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+       unsigned int pending = read_c0_cause();
+
+       if (likely(pending & IE_IRQ0))
+               ip32_irq0(regs);
+       else if (unlikely(pending & IE_IRQ1))
+               ip32_irq1(regs);
+       else if (unlikely(pending & IE_IRQ2))
+               ip32_irq2(regs);
+       else if (unlikely(pending & IE_IRQ3))
+               ip32_irq3(regs);
+       else if (unlikely(pending & IE_IRQ4))
+               ip32_irq4(regs);
+       else if (likely(pending & IE_IRQ5))
+               ip32_irq5(regs);
+}
+
 void __init arch_init_irq(void)
 {
        unsigned int irq;
@@ -556,7 +572,6 @@ void __init arch_init_irq(void)
        crime->soft_int = 0;
        mace->perif.ctrl.istat = 0;
        mace->perif.ctrl.imask = 0;
-       set_except_vector(0, ip32_handle_int);
 
        for (irq = 0; irq <= IP32_IRQ_MAX; irq++) {
                hw_irq_controller *controller;
index 538d5a51ae94fb515db922290bcc541a722d4b50..7b36ff3873b7f75d0dccf86875ae8854d54f6310 100644 (file)
@@ -1,4 +1,4 @@
-obj-y := setup.o irq.o irq_handler.o time.o
+obj-y := setup.o irq.o time.o
 
 obj-$(CONFIG_SMP)                      += smp.o
 
index 9cf7d713b13ccbaccf782db784cbe82f0c395167..e61760b14d99ec208d741e85f121f99cfb189838 100644 (file)
@@ -187,9 +187,6 @@ static void bcm1480_set_affinity(unsigned int irq, cpumask_t mask)
 #endif
 
 
-/* Defined in arch/mips/sibyte/bcm1480/irq_handler.S */
-extern void bcm1480_irq_handler(void);
-
 /*****************************************************************************/
 
 static unsigned int startup_bcm1480_irq(unsigned int irq)
@@ -422,7 +419,6 @@ void __init arch_init_irq(void)
 #endif
        /* Enable necessary IPs, disable the rest */
        change_c0_status(ST0_IM, imask);
-       set_except_vector(0, bcm1480_irq_handler);
 
 #ifdef CONFIG_KGDB
        if (kgdb_flag) {
@@ -473,3 +469,76 @@ void bcm1480_kgdb_interrupt(struct pt_regs *regs)
 }
 
 #endif         /* CONFIG_KGDB */
+
+static inline int dclz(unsigned long long x)
+{
+       int lz;
+
+       __asm__ (
+       "       .set    push                                            \n"
+       "       .set    mips64                                          \n"
+       "       dclz    %0, %1                                          \n"
+       "       .set    pop                                             \n"
+       : "=r" (lz)
+       : "r" (x));
+
+       return lz;
+}
+
+extern void bcm1480_timer_interrupt(struct pt_regs *regs);
+extern void bcm1480_mailbox_interrupt(struct pt_regs *regs);
+extern void bcm1480_kgdb_interrupt(struct pt_regs *regs);
+
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+       unsigned int pending;
+
+#ifdef CONFIG_SIBYTE_BCM1480_PROF
+       /* Set compare to count to silence count/compare timer interrupts */
+       write_c0_compare(read_c0_count());
+#endif
+
+       pending = read_c0_cause();
+
+#ifdef CONFIG_SIBYTE_BCM1480_PROF
+       if (pending & CAUSEF_IP7)       /* Cpu performance counter interrupt */
+               sbprof_cpu_intr(exception_epc(regs));
+#endif
+
+       if (pending & CAUSEF_IP4)
+               bcm1480_timer_interrupt(regs);
+
+#ifdef CONFIG_SMP
+       if (pending & CAUSEF_IP3)
+               bcm1480_mailbox_interrupt(regs);
+#endif
+
+#ifdef CONFIG_KGDB
+       if (pending & CAUSEF_IP6)
+               bcm1480_kgdb_interrupt(regs);           /* KGDB (uart 1) */
+#endif
+
+       if (pending & CAUSEF_IP2) {
+               unsigned long long mask_h, mask_l;
+               unsigned long base;
+
+               /*
+                * Default...we've hit an IP[2] interrupt, which means we've
+                * got to check the 1480 interrupt registers to figure out what
+                * to do.  Need to detect which CPU we're on, now that
+                * smp_affinity is supported.
+                */
+               base = A_BCM1480_IMR_MAPPER(smp_processor_id());
+               mask_h = __raw_readq(
+                       IOADDR(base + R_BCM1480_IMR_INTERRUPT_STATUS_BASE_H));
+               mask_l = __raw_readq(
+                       IOADDR(base + R_BCM1480_IMR_INTERRUPT_STATUS_BASE_L));
+
+               if (!mask_h) {
+                       if (mask_h ^ 1)
+                               do_IRQ(63 - dclz(mask_h), regs);
+                       else
+                               do_IRQ(127 - dclz(mask_l), regs);
+               }
+       }
+}
diff --git a/arch/mips/sibyte/bcm1480/irq_handler.S b/arch/mips/sibyte/bcm1480/irq_handler.S
deleted file mode 100644 (file)
index 408db88..0000000
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- * Copyright (C) 2000,2001,2002,2003,2004 Broadcom Corporation
- *
- * 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.
- */
-
-/*
- * bcm1480_irq_handler() is the routine that is actually called when an
- * interrupt occurs.  It is installed as the exception vector handler in
- * init_IRQ() in arch/mips/sibyte/bcm1480/irq.c
- *
- * In the handle we figure out which interrupts need handling, and use that
- * to call the dispatcher, which will take care of actually calling
- * registered handlers
- *
- * Note that we take care of all raised interrupts in one go at the handler.
- * This is more BSDish than the Indy code, and also, IMHO, more sane.
- */
-#include <linux/config.h>
-
-#include <asm/addrspace.h>
-#include <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-#include <asm/sibyte/sb1250_defs.h>
-#include <asm/sibyte/bcm1480_regs.h>
-#include <asm/sibyte/bcm1480_int.h>
-
-/*
- * What a pain. We have to be really careful saving the upper 32 bits of any
- * register across function calls if we don't want them trashed--since were
- * running in -o32, the calling routing never saves the full 64 bits of a
- * register across a function call.  Being the interrupt handler, we're
- * guaranteed that interrupts are disabled during this code so we don't have
- * to worry about random interrupts blasting the high 32 bits.
- */
-
-       .text
-       .set    push
-       .set    noreorder
-       .set    noat
-       .set    mips64
-       #.set   mips4
-       .align  5
-       NESTED(bcm1480_irq_handler, PT_SIZE, sp)
-       SAVE_ALL
-       CLI
-
-#ifdef CONFIG_SIBYTE_BCM1480_PROF
-       /* Set compare to count to silence count/compare timer interrupts */
-       mfc0    t1, CP0_COUNT
-       mtc0    t1, CP0_COMPARE /* pause to clear IP[7] bit of cause ? */
-#endif
-       /* Read cause */
-       mfc0    s0, CP0_CAUSE
-
-#ifdef CONFIG_SIBYTE_BCM1480_PROF
-       /* Cpu performance counter interrupt is routed to IP[7] */
-       andi    t1, s0, CAUSEF_IP7
-       beqz    t1, 0f
-        srl    t1, s0, (CAUSEB_BD-2)   /* Shift BD bit to bit 2 */
-       and     t1, t1, 0x4             /* mask to get just BD bit */
-#ifdef CONFIG_MIPS64
-       dmfc0   a0, CP0_EPC
-       daddu   a0, a0, t1              /* a0 = EPC + (BD ? 4 : 0) */
-#else
-       mfc0    a0, CP0_EPC
-       addu    a0, a0, t1              /* a0 = EPC + (BD ? 4 : 0) */
-#endif
-       jal     sbprof_cpu_intr
-        nop
-       j       ret_from_irq
-        nop
-0:
-#endif
-
-       /* Timer interrupt is routed to IP[4] */
-       andi    t1, s0, CAUSEF_IP4
-       beqz    t1, 1f
-        nop
-       jal     bcm1480_timer_interrupt
-        move   a0, sp                  /* Pass the registers along */
-       j       ret_from_irq
-        nop                            /* delay slot  */
-1:
-
-#ifdef CONFIG_SMP
-       /* Mailbox interrupt is routed to IP[3] */
-       andi     t1, s0, CAUSEF_IP3
-       beqz     t1, 2f
-        nop
-       jal      bcm1480_mailbox_interrupt
-        move    a0, sp
-       j        ret_from_irq
-        nop                            /* delay slot  */
-2:
-#endif
-
-#ifdef CONFIG_KGDB
-       /* KGDB (uart 1) interrupt is routed to IP[6] */
-       andi     t1, s0, CAUSEF_IP6
-       beqz     t1, 3f
-        nop                            /* delay slot  */
-       jal      bcm1480_kgdb_interrupt
-        move    a0, sp
-       j        ret_from_irq
-        nop                            /* delay slot  */
-3:
-#endif
-
-       and      t1, s0, CAUSEF_IP2
-       beqz     t1, 9f
-        nop
-
-       /*
-        * Default...we've hit an IP[2] interrupt, which means we've got
-        * to check the 1480 interrupt registers to figure out what to do
-        * Need to detect which CPU we're on, now that smp_affinity is
-        * supported.
-        */
-       PTR_LA   v0, CKSEG1 + A_BCM1480_IMR_CPU0_BASE
-#ifdef CONFIG_SMP
-       lw       t1, TI_CPU($28)
-       sll      t1, t1, BCM1480_IMR_REGISTER_SPACING_SHIFT
-       addu     v0, v0, t1
-#endif
-
-       /* Read IP[2] status (get both high and low halves of status) */
-       ld       s0, R_BCM1480_IMR_INTERRUPT_STATUS_BASE_H(v0)
-       ld       s1, R_BCM1480_IMR_INTERRUPT_STATUS_BASE_L(v0)
-
-       move     s2, zero       /* intr number  */
-       li       s3, 64
-
-       beqz     s0, 9f         /* No interrupts.  Return.  */
-        move    a1, sp
-
-       xori     s4, s0, 1      /* if s0 (_H) == 1, it's a low intr, so...  */
-       movz     s2, s3, s4     /* start the intr number at 64, and  */
-       movz     s0, s1, s4     /* look at the low status value.  */
-
-       dclz     s1, s0         /* Find the next interrupt.  */
-       dsubu    a0, zero, s1
-       daddiu   a0, a0, 63
-       jal      do_IRQ
-        daddu   a0, a0, s2
-
-9:     j        ret_from_irq
-        nop
-
-       .set pop
-       END(bcm1480_irq_handler)
index a8af846975884c6e97c57bcf6adfc38fcf4294d1..a2fdbd62f8ac0f78852f92b3870a5c2f721dd9ea 100644 (file)
@@ -1,4 +1,4 @@
-obj-y := setup.o irq.o irq_handler.o time.o
+obj-y := setup.o irq.o time.o
 
 obj-$(CONFIG_SMP)                      += smp.o
 obj-$(CONFIG_SIBYTE_TBPROF)            += bcm1250_tbprof.o
index 589537bfcc3d11b3cc66cc26db44e450492b0734..0f6e54db4888869c35d639fdc9963a602e62ad8c 100644 (file)
@@ -163,10 +163,6 @@ static void sb1250_set_affinity(unsigned int irq, cpumask_t mask)
 }
 #endif
 
-
-/* Defined in arch/mips/sibyte/sb1250/irq_handler.S */
-extern void sb1250_irq_handler(void);
-
 /*****************************************************************************/
 
 static unsigned int startup_sb1250_irq(unsigned int irq)
@@ -379,7 +375,6 @@ void __init arch_init_irq(void)
 #endif
        /* Enable necessary IPs, disable the rest */
        change_c0_status(ST0_IM, imask);
-       set_except_vector(0, sb1250_irq_handler);
 
 #ifdef CONFIG_KGDB
        if (kgdb_flag) {
@@ -409,7 +404,7 @@ void __init arch_init_irq(void)
 #define duart_out(reg, val)     csr_out32(val, IOADDR(A_DUART_CHANREG(kgdb_port,reg)))
 #define duart_in(reg)           csr_in32(IOADDR(A_DUART_CHANREG(kgdb_port,reg)))
 
-void sb1250_kgdb_interrupt(struct pt_regs *regs)
+static void sb1250_kgdb_interrupt(struct pt_regs *regs)
 {
        /*
         * Clear break-change status (allow some time for the remote
@@ -424,3 +419,74 @@ void sb1250_kgdb_interrupt(struct pt_regs *regs)
 }
 
 #endif         /* CONFIG_KGDB */
+
+static inline int dclz(unsigned long long x)
+{
+       int lz;
+
+       __asm__ (
+       "       .set    push                                            \n"
+       "       .set    mips64                                          \n"
+       "       dclz    %0, %1                                          \n"
+       "       .set    pop                                             \n"
+       : "=r" (lz)
+       : "r" (x));
+
+       return lz;
+}
+
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+       unsigned int pending;
+
+#ifdef CONFIG_SIBYTE_SB1250_PROF
+       /* Set compare to count to silence count/compare timer interrupts */
+       write_c0_count(read_c0_count());
+#endif
+
+       /*
+        * What a pain. We have to be really careful saving the upper 32 bits
+        * of any * register across function calls if we don't want them
+        * trashed--since were running in -o32, the calling routing never saves
+        * the full 64 bits of a register across a function call.  Being the
+        * interrupt handler, we're guaranteed that interrupts are disabled
+        * during this code so we don't have to worry about random interrupts
+        * blasting the high 32 bits.
+        */
+
+       pending = read_c0_cause();
+
+#ifdef CONFIG_SIBYTE_SB1250_PROF
+       if (pending & CAUSEF_IP7) { /* Cpu performance counter interrupt */
+               sbprof_cpu_intr(exception_epc(regs));
+       }
+#endif
+
+       if (pending & CAUSEF_IP4)
+               sb1250_timer_interrupt(regs);
+
+#ifdef CONFIG_SMP
+       if (pending & CAUSEF_IP3)
+               sb1250_mailbox_interrupt(regs);
+#endif
+
+#ifdef CONFIG_KGDB
+       if (pending & CAUSEF_IP6)                       /* KGDB (uart 1) */
+               sb1250_kgdb_interrupt(regs);
+#endif
+
+       if (pending & CAUSEF_IP2) {
+               unsigned long long mask;
+
+               /*
+                * Default...we've hit an IP[2] interrupt, which means we've
+                * got to check the 1250 interrupt registers to figure out what
+                * to do.  Need to detect which CPU we're on, now that
+                ~ smp_affinity is supported.
+                */
+               mask = __raw_readq(IOADDR(A_IMR_REGISTER(smp_processor_id(),
+                                             R_IMR_INTERRUPT_STATUS_BASE)));
+               if (mask)
+                       do_IRQ(63 - dclz(mask), regs);
+       }
+}
diff --git a/arch/mips/sibyte/sb1250/irq_handler.S b/arch/mips/sibyte/sb1250/irq_handler.S
deleted file mode 100644 (file)
index 60edc8f..0000000
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * Copyright (C) 2000, 2001, 2002, 2003 Broadcom Corporation
- *
- * 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.
- */
-
-/*
- * sb1250_handle_int() is the routine that is actually called when an interrupt
- * occurs.  It is installed as the exception vector handler in arch_init_irq()
- * in arch/mips/sibyte/sb1250/irq.c
- *
- * In the handle we figure out which interrupts need handling, and use that to
- * call the dispatcher, which will take care of actually calling registered
- * handlers
- *
- * Note that we take care of all raised interrupts in one go at the handler.
- * This is more BSDish than the Indy code, and also, IMHO, more sane.
- */
-#include <linux/config.h>
-
-#include <asm/addrspace.h>
-#include <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-#include <asm/sibyte/sb1250_defs.h>
-#include <asm/sibyte/sb1250_regs.h>
-#include <asm/sibyte/sb1250_int.h>
-
-/*
- * What a pain. We have to be really careful saving the upper 32 bits of any
- * register across function calls if we don't want them trashed--since were
- * running in -o32, the calling routing never saves the full 64 bits of a
- * register across a function call.  Being the interrupt handler, we're
- * guaranteed that interrupts are disabled during this code so we don't have
- * to worry about random interrupts blasting the high 32 bits.
- */
-
-       .text
-       .set    push
-       .set    noreorder
-       .set    noat
-       .set    mips64
-       .align  5
-       NESTED(sb1250_irq_handler, PT_SIZE, sp)
-       SAVE_ALL
-       CLI
-
-#ifdef CONFIG_SIBYTE_SB1250_PROF
-       /* Set compare to count to silence count/compare timer interrupts */
-       mfc0    t1, CP0_COUNT
-       mtc0    t1, CP0_COMPARE /* pause to clear IP[7] bit of cause ? */
-#endif
-       /* Read cause */
-       mfc0    s0, CP0_CAUSE
-
-#ifdef CONFIG_SIBYTE_SB1250_PROF
-       /* Cpu performance counter interrupt is routed to IP[7] */
-       andi    t1, s0, CAUSEF_IP7
-       beqz    t1, 0f
-        srl    t1, s0, (CAUSEB_BD-2)  /* Shift BD bit to bit 2 */
-       and     t1, t1, 0x4             /* mask to get just BD bit */
-       mfc0    a0, CP0_EPC
-       jal     sbprof_cpu_intr
-        addu   a0, a0, t1              /* a0 = EPC + (BD ? 4 : 0) */
-       j       ret_from_irq
-        nop
-0:
-#endif
-
-       /* Timer interrupt is routed to IP[4] */
-       andi    t1, s0, CAUSEF_IP4
-       beqz    t1, 1f
-        nop
-       jal     sb1250_timer_interrupt
-        move   a0, sp                  /* Pass the registers along */
-       j       ret_from_irq
-        nop                            # delay slot
-1:
-
-#ifdef CONFIG_SMP
-       /* Mailbox interrupt is routed to IP[3] */
-       andi     t1, s0, CAUSEF_IP3
-       beqz     t1, 2f
-        nop
-       jal      sb1250_mailbox_interrupt
-        move    a0, sp
-       j       ret_from_irq
-        nop                            # delay slot
-2:
-#endif
-
-#ifdef CONFIG_KGDB
-       /* KGDB (uart 1) interrupt is routed to IP[6] */
-       andi    t1, s0, CAUSEF_IP6
-       beqz    t1, 1f
-       nop                            # delay slot
-       jal     sb1250_kgdb_interrupt
-         move  a0, sp
-       j       ret_from_irq
-       nop                            # delay slot
-1:
-#endif
-
-       and      t1, s0, CAUSEF_IP2
-       beqz     t1, 4f
-        nop
-
-       /*
-        * Default...we've hit an IP[2] interrupt, which means we've got to
-        * check the 1250 interrupt registers to figure out what to do
-        * Need to detect which CPU we're on, now that smp_affinity is supported.
-        */
-       PTR_LA  v0, CKSEG1 + A_IMR_CPU0_BASE
-#ifdef CONFIG_SMP
-       lw      t1, TI_CPU($28)
-       sll     t1, IMR_REGISTER_SPACING_SHIFT
-       addu    v0, t1
-#endif
-       ld      s0, R_IMR_INTERRUPT_STATUS_BASE(v0)     /* read IP[2] status */
-
-       beqz    s0, 4f          /* No interrupts.  Return */
-        move   a1, sp
-
-3:     dclz    s1, s0          /* Find the next interrupt */
-       dsubu   a0, zero, s1
-       daddiu  a0, a0, 63
-       jal      do_IRQ
-        nop
-
-4:     j        ret_from_irq
-        nop
-
-       .set pop
-       END(sb1250_irq_handler)
index 1e5676e4be86080ec9f3df73a5afa9a9ef1bc55f..9c7eaa5fb2106ad5d63ce41bfb8fa63861f440b0 100644 (file)
@@ -2,6 +2,6 @@
 # Makefile for the SNI specific part of the kernel
 #
 
-obj-y          += int-handler.o irq.o pcimt_scache.o reset.o setup.o
+obj-y          += irq.o pcimt_scache.o reset.o setup.o
 
 EXTRA_AFLAGS := $(CFLAGS)
diff --git a/arch/mips/sni/int-handler.S b/arch/mips/sni/int-handler.S
deleted file mode 100644 (file)
index 2cdc09f..0000000
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * SNI RM200 PCI specific interrupt handler code.
- *
- * Copyright (C) 1994, 95, 96, 97, 98, 1999, 2000, 01 by Ralf Baechle
- */
-#include <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/regdef.h>
-#include <asm/sni.h>
-#include <asm/stackframe.h>
-
-/*
- * The PCI ASIC has the nasty property that it may delay writes if it is busy.
- * As a consequence from writes that have not graduated when we exit from the
- * interrupt handler we might catch a spurious interrupt.  To avoid this we
- * force the PCI ASIC to graduate all writes by executing a read from the
- * PCI bus.
- */
-               .set    noreorder
-               .set    noat
-               .align  5
-               NESTED(sni_rm200_pci_handle_int, PT_SIZE, sp)
-               SAVE_ALL
-               CLI
-               .set    at
-
-               /* Blinken light ...  */
-               lb      t0, led_cache
-               addiu   t0, 1
-               sb      t0, led_cache
-               sb      t0, PCIMT_CSLED                 # write only register
-               .data
-led_cache:     .byte   0
-               .text
-
-               mfc0    t0, CP0_STATUS
-               mfc0    t1, CP0_CAUSE
-               and     t0, t1
-
-                andi   t1, t0, 0x0800                  # hardware interrupt 1
-               bnez    t1, _hwint1
-                andi   t1, t0, 0x4000                  # hardware interrupt 4
-               bnez    t1, _hwint4
-                andi   t1, t0, 0x2000                  # hardware interrupt 3
-               bnez    t1, _hwint3
-                andi   t1, t0, 0x1000                  # hardware interrupt 2
-               bnez    t1, _hwint2
-                andi   t1, t0, 0x8000                  # hardware interrupt 5
-               bnez    t1, _hwint5
-                andi   t1, t0, 0x0400                  # hardware interrupt 0
-               bnez    t1, _hwint0
-                nop
-
-               j       restore_all                     # spurious interrupt
-                nop
-
- ##############################################################################
-
-/* hwint0 should deal with MP agent, ASIC PCI, EISA NMI and debug
-   button interrupts.  */
-_hwint0:       jal     pciasic_hwint0
-                move   a0, sp
-               j       ret_from_irq
-                nop
-
-/*
- * hwint 1 deals with EISA and SCSI interrupts
- */
-_hwint1:       jal     pciasic_hwint1
-                move   a0, sp
-               j       ret_from_irq
-                nop
-
-
-/*
- * This interrupt was used for the com1 console on the first prototypes;
- * it's unsed otherwise
- */
-_hwint2:       jal     pciasic_hwint2
-                move   a0, sp
-               j       ret_from_irq
-                nop
-
-/*
- * hwint 3 are the PCI interrupts A - D
- */
-_hwint3:       jal     pciasic_hwint3
-                move   a0, sp
-               j       ret_from_irq
-                nop
-
-/*
- * hwint 4 is used for only the onboard PCnet 32.
- */
-_hwint4:       jal     pciasic_hwint4
-                move   a0, sp
-               j       ret_from_irq
-                nop
-
-/* hwint5 is the r4k count / compare interrupt  */
-_hwint5:       jal     pciasic_hwint5
-                move   a0, sp
-               j       ret_from_irq
-                nop
-
-               END(sni_rm200_pci_handle_int)
index 952038aa4b90d7c0a5d8ad6a96bcf233ddb6cd85..7365b4853ddb212a0d6073d49d60460838819f1f 100644 (file)
@@ -19,8 +19,6 @@
 
 DEFINE_SPINLOCK(pciasic_lock);
 
-extern asmlinkage void sni_rm200_pci_handle_int(void);
-
 static void enable_pciasic_irq(unsigned int irq)
 {
        unsigned int mask = 1 << (irq - PCIMT_IRQ_INT2);
@@ -71,20 +69,20 @@ static struct hw_interrupt_type pciasic_irq_type = {
  * hwint0 should deal with MP agent, ASIC PCI, EISA NMI and debug
  * button interrupts.  Later ...
  */
-void pciasic_hwint0(struct pt_regs *regs)
+static void pciasic_hwint0(struct pt_regs *regs)
 {
        panic("Received int0 but no handler yet ...");
 }
 
 /* This interrupt was used for the com1 console on the first prototypes.  */
-void pciasic_hwint2(struct pt_regs *regs)
+static void pciasic_hwint2(struct pt_regs *regs)
 {
        /* I think this shouldn't happen on production machines.  */
        panic("hwint2 and no handler yet");
 }
 
 /* hwint5 is the r4k count / compare interrupt  */
-void pciasic_hwint5(struct pt_regs *regs)
+static void pciasic_hwint5(struct pt_regs *regs)
 {
        panic("hwint5 and no handler yet");
 }
@@ -105,7 +103,7 @@ static unsigned int ls1bit8(unsigned int x)
  *
  * The EISA_INT bit in CSITPEND is high active, all others are low active.
  */
-void pciasic_hwint1(struct pt_regs *regs)
+static void pciasic_hwint1(struct pt_regs *regs)
 {
        u8 pend = *(volatile char *)PCIMT_CSITPEND;
        unsigned long flags;
@@ -135,7 +133,7 @@ void pciasic_hwint1(struct pt_regs *regs)
 /*
  * hwint 3 should deal with the PCI A - D interrupts,
  */
-void pciasic_hwint3(struct pt_regs *regs)
+static void pciasic_hwint3(struct pt_regs *regs)
 {
        u8 pend = *(volatile char *)PCIMT_CSITPEND;
        int irq;
@@ -150,13 +148,34 @@ void pciasic_hwint3(struct pt_regs *regs)
 /*
  * hwint 4 is used for only the onboard PCnet 32.
  */
-void pciasic_hwint4(struct pt_regs *regs)
+static void pciasic_hwint4(struct pt_regs *regs)
 {
        clear_c0_status(IE_IRQ4);
        do_IRQ(PCIMT_IRQ_ETHERNET, regs);
        set_c0_status(IE_IRQ4);
 }
 
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+       unsigned int pending = read_c0_status() & read_c0_cause();
+       static unsigned char led_cache;
+
+       *(volatile unsigned char *) PCIMT_CSLED = ++led_cache;
+
+       if (pending & 0x0800)
+               pciasic_hwint1(regs);
+       else if (pending & 0x4000)
+               pciasic_hwint4(regs);
+       else if (pending & 0x2000)
+               pciasic_hwint3(regs);
+       else if (pending & 0x1000)
+               pciasic_hwint2(regs);
+       else if (pending & 0x8000)
+               pciasic_hwint5(regs);
+       else if (pending & 0x0400)
+               pciasic_hwint0(regs);
+}
+
 void __init init_pciasic(void)
 {
        unsigned long flags;
@@ -176,8 +195,6 @@ void __init arch_init_irq(void)
 {
        int i;
 
-       set_except_vector(0, sni_rm200_pci_handle_int);
-
        init_i8259_irqs();                      /* Integrated i8259  */
        init_pciasic();
 
index 8fa126b296e1f2ddde15c504e1b4ab4f014966f2..9cb9535ebacba6e9ad6b3c65113cde36b25444e8 100644 (file)
@@ -6,7 +6,7 @@
 # unless it's something special (ie not a .c file).
 #
 
-obj-y  += tx4927_prom.o tx4927_setup.o tx4927_irq.o tx4927_irq_handler.o
+obj-y  += tx4927_prom.o tx4927_setup.o tx4927_irq.o
 
 obj-$(CONFIG_TOSHIBA_FPCIB0)      += smsc_fdc37m81x.o
 obj-$(CONFIG_KGDB)                 += tx4927_dbgio.o
index 5ab2e2b7601817c36cce5898eda21aa55f911bfe..8ca68015cf40ffd9456a17febfa107187eb8b18d 100644 (file)
@@ -525,8 +525,6 @@ static void tx4927_irq_pic_end(unsigned int irq)
  */
 void __init tx4927_irq_init(void)
 {
-       extern asmlinkage void tx4927_irq_handler(void);
-
        TX4927_IRQ_DPRINTK(TX4927_IRQ_INIT, "-\n");
 
        TX4927_IRQ_DPRINTK(TX4927_IRQ_INIT, "=Calling tx4927_irq_cp0_init()\n");
@@ -535,16 +533,12 @@ void __init tx4927_irq_init(void)
        TX4927_IRQ_DPRINTK(TX4927_IRQ_INIT, "=Calling tx4927_irq_pic_init()\n");
        tx4927_irq_pic_init();
 
-       TX4927_IRQ_DPRINTK(TX4927_IRQ_INIT,
-                          "=Calling set_except_vector(tx4927_irq_handler)\n");
-       set_except_vector(0, tx4927_irq_handler);
-
        TX4927_IRQ_DPRINTK(TX4927_IRQ_INIT, "+\n");
 
        return;
 }
 
-int tx4927_irq_nested(void)
+static int tx4927_irq_nested(void)
 {
        int sw_irq = 0;
        u32 level2;
@@ -582,3 +576,25 @@ int tx4927_irq_nested(void)
 
        return (sw_irq);
 }
+
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+       unsigned int pending = read_c0_status() & read_c0_cause();
+
+       if (pending & STATUSF_IP7)                      /* cpu timer */
+               do_IRQ(TX4927_IRQ_CPU_TIMER, regs);
+       else if (pending & STATUSF_IP2) {               /* tx4927 pic */
+               unsigned int irq = tx4927_irq_nested();
+
+               if (unlikely(irq == 0)) {
+                       spurious_interrupt(regs);
+                       return;
+               }
+               do_IRQ(irq, regs);
+       } else if (pending & STATUSF_IP0)               /* user line 0 */
+               do_IRQ(TX4927_IRQ_USER0, regs);
+       else if (pending & STATUSF_IP1)                 /* user line 1 */
+               do_IRQ(TX4927_IRQ_USER1, regs);
+       else
+               spurious_interrupt(regs);
+}
diff --git a/arch/mips/tx4927/common/tx4927_irq_handler.S b/arch/mips/tx4927/common/tx4927_irq_handler.S
deleted file mode 100644 (file)
index dd3ceda..0000000
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * linux/arch/mips/tx4927/common/tx4927_irq_handler.S
- *
- * Primary interrupt handler for tx4927 based systems
- *
- * Author: MontaVista Software, Inc.
- * Author: jsun@mvista.com or jsun@junsun.net
- *         source@mvista.com
- *
- * Copyright 2001-2002 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.
- *
- *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- *  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- *  OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- *  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
- *  TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
- *  USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *  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.,
- *  675 Mass Ave, Cambridge, MA 02139, USA.
- */
-#include <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/addrspace.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-#include <asm/tx4927/tx4927.h>
-
-               .align  5
-               NESTED(tx4927_irq_handler, PT_SIZE, sp)
-               SAVE_ALL
-               CLI
-               .set    at
-
-               mfc0    t0, CP0_CAUSE
-               mfc0    t1, CP0_STATUS
-               and     t0, t1
-
-               andi    t1, t0, STATUSF_IP7     /* cpu timer */
-               bnez    t1, ll_ip7
-
-               /* IP6..IP3 multiplexed -- do not use */
-
-               andi    t1, t0, STATUSF_IP2     /* tx4927 pic */
-               bnez    t1, ll_ip2
-
-               andi    t1, t0, STATUSF_IP0     /* user line 0 */
-               bnez    t1, ll_ip0
-
-               andi    t1, t0, STATUSF_IP1     /* user line 1 */
-               bnez    t1, ll_ip1
-
-               .set    reorder
-
-               /* wrong alarm or masked ... */
-               j       spurious_interrupt
-               nop
-               END(tx4927_irq_handler)
-
-               .align  5
-
-
-ll_ip7:
-               li      a0, TX4927_IRQ_CPU_TIMER
-               move    a1, sp
-               jal     do_IRQ
-               j       ret_from_irq
-
-ll_ip2:
-               jal     tx4927_irq_nested
-               nop
-               beqz    v0, goto_spurious_interrupt
-               nop
-               move    a0, v0
-               move    a1, sp
-               jal     do_IRQ
-               j       ret_from_irq
-
-goto_spurious_interrupt:
-       j spurious_interrupt
-       nop
-
-ll_ip1:
-               li      a0, TX4927_IRQ_USER1
-               move    a1, sp
-               jal     do_IRQ
-               j       ret_from_irq
-
-ll_ip0:
-               li      a0, TX4927_IRQ_USER0
-               move    a1, sp
-               jal     do_IRQ
-               j       ret_from_irq
index 74c95c5bcdbff3d514a12e0d4ed2e5589a065257..2033ae77f6321c305489294d7a4aba939e4a835d 100644 (file)
@@ -6,6 +6,6 @@
 # unless it's something special (ie not a .c file).
 #
 
-obj-y  += prom.o setup.o irq.o irq_handler.o rtc_rx5c348.o
+obj-y  += prom.o setup.o irq.o rtc_rx5c348.o
 obj-$(CONFIG_KGDB) += dbgio.o
 
index 4f90d7faf634e72011224f4c031d53de5b5fb1e4..873805178d8e993b09402aad77ce8a9524f9bf83 100644 (file)
@@ -392,11 +392,8 @@ tx4938_irq_pic_end(unsigned int irq)
 void __init
 tx4938_irq_init(void)
 {
-       extern asmlinkage void tx4938_irq_handler(void);
-
        tx4938_irq_cp0_init();
        tx4938_irq_pic_init();
-       set_except_vector(0, tx4938_irq_handler);
 
        return;
 }
@@ -422,3 +419,21 @@ tx4938_irq_nested(void)
        wbflush();
        return (sw_irq);
 }
+
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+       unsigned int pending = read_c0_cause() & read_c0_status();
+
+       if (pending & STATUSF_IP7)
+               do_IRQ(TX4938_IRQ_CPU_TIMER, regs);
+       else if (pending & STATUSF_IP2) {
+               int irq = tx4938_irq_nested();
+               if (irq)
+                       do_IRQ(irq, regs);
+               else
+                       spurious_interrupt(regs);
+       } else if (pending & STATUSF_IP1)
+               do_IRQ(TX4938_IRQ_USER1, regs);
+       else if (pending & STATUSF_IP0)
+               do_IRQ(TX4938_IRQ_USER0, regs);
+}
diff --git a/arch/mips/tx4938/common/irq_handler.S b/arch/mips/tx4938/common/irq_handler.S
deleted file mode 100644 (file)
index 1b2f72b..0000000
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * linux/arch/mips/tx4938/common/handler.S
- *
- * Primary interrupt handler for tx4938 based systems
- * Copyright (C) 2000-2001 Toshiba Corporation
- *
- * 2003-2005 (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.
- *
- * Support for TX4938 in 2.6 - Manish Lachwani (mlachwani@mvista.com)
- */
-#include <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/addrspace.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-#include <asm/tx4938/rbtx4938.h>
-
-
-               .align  5
-               NESTED(tx4938_irq_handler, PT_SIZE, sp)
-               SAVE_ALL
-               CLI
-               .set    at
-
-               mfc0    t0, CP0_CAUSE
-               mfc0    t1, CP0_STATUS
-               and     t0, t1
-
-               andi    t1, t0, STATUSF_IP7     /* cpu timer */
-               bnez    t1, ll_ip7
-
-               /* IP6..IP3 multiplexed -- do not use */
-
-               andi    t1, t0, STATUSF_IP2     /* tx4938 pic */
-               bnez    t1, ll_ip2
-
-               andi    t1, t0, STATUSF_IP1     /* user line 1 */
-               bnez    t1, ll_ip1
-
-               andi    t1, t0, STATUSF_IP0     /* user line 0 */
-               bnez    t1, ll_ip0
-
-               .set    reorder
-
-               nop
-               END(tx4938_irq_handler)
-
-               .align  5
-
-
-ll_ip7:
-               li      a0, TX4938_IRQ_CPU_TIMER
-               move    a1, sp
-               jal     do_IRQ
-               j       ret_from_irq
-
-
-ll_ip2:
-               jal     tx4938_irq_nested
-               nop
-               beqz    v0, goto_spurious_interrupt
-               nop
-               move    a0, v0
-               move    a1, sp
-               jal     do_IRQ
-               j       ret_from_irq
-
-goto_spurious_interrupt:
-               j       ret_from_irq
-
-ll_ip1:
-               li      a0, TX4938_IRQ_USER1
-               move    a1, sp
-               jal     do_IRQ
-               j       ret_from_irq
-
-ll_ip0:
-               li      a0, TX4938_IRQ_USER0
-               move    a1, sp
-               jal     do_IRQ
-               j       ret_from_irq
index a7add16c9aa49f5c5879a6cfb80fbf2059c97ac3..055a2cdfc841f080b5cadb277a46e5155d05a89d 100644 (file)
@@ -4,6 +4,8 @@ config CASIO_E55
        select DMA_NONCOHERENT
        select IRQ_CPU
        select ISA
+       select SYS_HAS_CPU_VR41XX
+       select SYS_SUPPORTS_32BIT_KERNEL
        select SYS_SUPPORTS_LITTLE_ENDIAN
 
 config IBM_WORKPAD
@@ -12,6 +14,8 @@ config IBM_WORKPAD
        select DMA_NONCOHERENT
        select IRQ_CPU
        select ISA
+       select SYS_HAS_CPU_VR41XX
+       select SYS_SUPPORTS_32BIT_KERNEL
        select SYS_SUPPORTS_LITTLE_ENDIAN
 
 config NEC_CMBVR4133
@@ -21,6 +25,9 @@ config NEC_CMBVR4133
        select DMA_NONCOHERENT
        select IRQ_CPU
        select HW_HAS_PCI
+       select SYS_HAS_CPU_VR41XX
+       select SYS_SUPPORTS_32BIT_KERNEL
+       select SYS_SUPPORTS_LITTLE_ENDIAN
 
 config ROCKHOPPER
        bool "Support for Rockhopper baseboard"
@@ -34,6 +41,8 @@ config TANBAC_TB022X
        select DMA_NONCOHERENT
        select HW_HAS_PCI
        select IRQ_CPU
+       select SYS_HAS_CPU_VR41XX
+       select SYS_SUPPORTS_32BIT_KERNEL
        select SYS_SUPPORTS_LITTLE_ENDIAN
        help
          The TANBAC VR4131 multichip module(TB0225) and
@@ -65,6 +74,8 @@ config VICTOR_MPC30X
        select DMA_NONCOHERENT
        select HW_HAS_PCI
        select IRQ_CPU
+       select SYS_HAS_CPU_VR41XX
+       select SYS_SUPPORTS_32BIT_KERNEL
        select SYS_SUPPORTS_LITTLE_ENDIAN
 
 config ZAO_CAPCELLA
@@ -73,6 +84,8 @@ config ZAO_CAPCELLA
        select DMA_NONCOHERENT
        select HW_HAS_PCI
        select IRQ_CPU
+       select SYS_HAS_CPU_VR41XX
+       select SYS_SUPPORTS_32BIT_KERNEL
        select SYS_SUPPORTS_LITTLE_ENDIAN
 
 config PCI_VR41XX
index 9096302a7ecc1e79fed3a3a73f71d67241c07fce..aa373974c80f44111230a81f31c560eed7683632 100644 (file)
@@ -2,7 +2,7 @@
 # Makefile for common code of the NEC VR4100 series.
 #
 
-obj-y                          += bcu.o cmu.o icu.o init.o int-handler.o irq.o pmu.o type.o
+obj-y                          += bcu.o cmu.o icu.o init.o irq.o pmu.o type.o
 obj-$(CONFIG_VRC4173)          += vrc4173.o
 
 EXTRA_AFLAGS := $(CFLAGS)
diff --git a/arch/mips/vr41xx/common/int-handler.S b/arch/mips/vr41xx/common/int-handler.S
deleted file mode 100644 (file)
index 2b6043f..0000000
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * FILE NAME
- *     arch/mips/vr41xx/common/int-handler.S
- *
- * BRIEF MODULE DESCRIPTION
- *     Interrupt dispatcher for the NEC VR4100 series.
- *
- * Author: Yoichi Yuasa
- *         yyuasa@mvista.com or source@mvista.com
- *
- * 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.
- *
- *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- *  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- *  OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- *  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
- *  TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
- *  USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *  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.,
- *  675 Mass Ave, Cambridge, MA 02139, USA.
- */
-/*
- * Changes:
- *  MontaVista Software Inc. <yyuasa@mvista.com> or <source@mvista.com>
- *  - New creation, NEC VR4100 series are supported.
- *
- *  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
- *  - Coped with INTASSIGN of NEC VR4133.
- */
-#include <asm/asm.h>
-#include <asm/regdef.h>
-#include <asm/mipsregs.h>
-#include <asm/stackframe.h>
-
-               .text
-               .set    noreorder
-
-               .align  5
-               NESTED(vr41xx_handle_interrupt, PT_SIZE, ra)
-               .set    noat
-               SAVE_ALL
-               CLI
-               .set    at
-               .set    noreorder
-
-               /*
-                * Get the pending interrupts
-                */
-               mfc0    t0, CP0_CAUSE
-               mfc0    t1, CP0_STATUS
-               andi    t0, 0xff00
-               and     t0, t0, t1
-
-               andi    t1, t0, CAUSEF_IP7      # MIPS timer interrupt
-               bnez    t1, handle_irq
-               li      a0, 7
-
-               andi    t1, t0, 0x7800          # check for Int1-4
-               beqz    t1, 1f
-
-               andi    t1, t0, CAUSEF_IP3      # check for Int1
-               bnez    t1, handle_int
-               li      a0, 3
-
-               andi    t1, t0, CAUSEF_IP4      # check for Int2
-               bnez    t1, handle_int
-               li      a0, 4
-
-               andi    t1, t0, CAUSEF_IP5      # check for Int3
-               bnez    t1, handle_int
-               li      a0, 5
-
-               andi    t1, t0, CAUSEF_IP6      # check for Int4
-               bnez    t1, handle_int
-               li      a0, 6
-
-1:
-               andi    t1, t0, CAUSEF_IP2      # check for Int0
-               bnez    t1, handle_int
-               li      a0, 2
-
-               andi    t1, t0, CAUSEF_IP0      # check for IP0
-               bnez    t1, handle_irq
-               li      a0, 0
-
-               andi    t1, t0, CAUSEF_IP1      # check for IP1
-               bnez    t1, handle_irq
-               li      a0, 1
-
-               j       spurious_interrupt
-               nop
-
-handle_int:
-               jal     irq_dispatch
-               move    a1, sp
-               j       ret_from_irq
-               nop
-
-handle_irq:
-               jal     do_IRQ
-               move    a1, sp
-               j       ret_from_irq
-               END(vr41xx_handle_interrupt)
index 61aa264275ff2883d0f1fbec5871645a307a5287..86796bb63c3c7e3d6b3aaa41626a52a43b8eca35 100644 (file)
@@ -59,7 +59,7 @@ int cascade_irq(unsigned int irq, int (*get_irq)(unsigned int, struct pt_regs *)
 
 EXPORT_SYMBOL_GPL(cascade_irq);
 
-asmlinkage void irq_dispatch(unsigned int irq, struct pt_regs *regs)
+static void irq_dispatch(unsigned int irq, struct pt_regs *regs)
 {
        irq_cascade_t *cascade;
        irq_desc_t *desc;
@@ -84,11 +84,32 @@ asmlinkage void irq_dispatch(unsigned int irq, struct pt_regs *regs)
                do_IRQ(irq, regs);
 }
 
-extern asmlinkage void vr41xx_handle_interrupt(void);
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+       unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM;
+
+       if (pending & CAUSEF_IP7)
+               do_IRQ(7, regs);
+       else if (pending & 0x7800) {
+               if (pending & CAUSEF_IP3)
+                       irq_dispatch(3, regs);
+               else if (pending & CAUSEF_IP4)
+                       irq_dispatch(4, regs);
+               else if (pending & CAUSEF_IP5)
+                       irq_dispatch(5, regs);
+               else if (pending & CAUSEF_IP6)
+                       irq_dispatch(6, regs);
+       } else if (pending & CAUSEF_IP2)
+               irq_dispatch(2, regs);
+       else if (pending & CAUSEF_IP0)
+               do_IRQ(0, regs);
+       else if (pending & CAUSEF_IP1)
+               do_IRQ(1, regs);
+       else
+               spurious_interrupt(regs);
+}
 
 void __init arch_init_irq(void)
 {
        mips_cpu_irq_init(MIPS_CPU_IRQ_BASE);
-
-       set_except_vector(0, vr41xx_handle_interrupt);
 }
index 167e70e95556c0a7f6a281a96114773e46418fe9..6729c98b66f969fb16566bcc949039c776370a24 100644 (file)
@@ -366,6 +366,7 @@ config PPC_PMAC64
        select U3_DART
        select MPIC_BROKEN_U3
        select GENERIC_TBSYNC
+       select PPC_970_NAP
        default y
 
 config PPC_PREP
@@ -383,6 +384,7 @@ config PPC_MAPLE
        select MPIC_BROKEN_U3
        select GENERIC_TBSYNC
        select PPC_UDBG_16550
+       select PPC_970_NAP
        default n
        help
           This option enables support for the Maple 970FX Evaluation Board.
@@ -457,6 +459,10 @@ config PPC_MPC106
        bool
        default n
 
+config PPC_970_NAP
+       bool
+       default n
+
 source "drivers/cpufreq/Kconfig"
 
 config CPU_FREQ_PMAC
index 6ec84d37a3378dbaa321fe217091eb149a01b58c..ed5b26aa8be36e914967c6b5e3530d639ed6b861 100644 (file)
@@ -104,6 +104,10 @@ ifndef CONFIG_FSL_BOOKE
 CFLAGS         += -mstring
 endif
 
+ifeq ($(CONFIG_6xx),y)
+CFLAGS         += -mcpu=powerpc
+endif
+
 cpu-as-$(CONFIG_PPC64BRIDGE)   += -Wa,-mppc64bridge
 cpu-as-$(CONFIG_4xx)           += -Wa,-m405
 cpu-as-$(CONFIG_6xx)           += -Wa,-maltivec
index 0cc0995b81b07ec355413ba07ce8bfff08c58b98..803858e8616031054c62fbb04021e0d6a3f13052 100644 (file)
@@ -20,7 +20,7 @@ obj-$(CONFIG_PPC64)           += setup_64.o binfmt_elf32.o sys_ppc32.o \
                                   firmware.o sysfs.o
 obj-$(CONFIG_PPC64)            += vdso64/
 obj-$(CONFIG_ALTIVEC)          += vecemu.o vector.o
-obj-$(CONFIG_POWER4)           += idle_power4.o
+obj-$(CONFIG_PPC_970_NAP)      += idle_power4.o
 obj-$(CONFIG_PPC_OF)           += of_device.o prom_parse.o
 procfs-$(CONFIG_PPC64)         := proc_ppc64.o
 obj-$(CONFIG_PROC_FS)          += $(procfs-y)
index 54b48f3300515eb082eed331267e0373ca575507..8f85c5e8a55a438e927d6ca729e67066199f63c4 100644 (file)
@@ -91,6 +91,7 @@ int main(void)
 #endif /* CONFIG_PPC64 */
 
        DEFINE(TI_FLAGS, offsetof(struct thread_info, flags));
+       DEFINE(TI_LOCAL_FLAGS, offsetof(struct thread_info, local_flags));
        DEFINE(TI_PREEMPT, offsetof(struct thread_info, preempt_count));
        DEFINE(TI_TASK, offsetof(struct thread_info, task));
 #ifdef CONFIG_PPC32
index b3a9794672250c4ba98c3710e4bef8b691a6a82e..8866fd26c6b97048dfb3c8142c95dcf4c43c3bcc 100644 (file)
@@ -128,37 +128,36 @@ transfer_to_handler:
        stw     r12,4(r11)
 #endif
        b       3f
+
 2:     /* if from kernel, check interrupted DOZE/NAP mode and
          * check for stack overflow
          */
+       lwz     r9,THREAD_INFO-THREAD(r12)
+       cmplw   r1,r9                   /* if r1 <= current->thread_info */
+       ble-    stack_ovf               /* then the kernel stack overflowed */
+5:
 #ifdef CONFIG_6xx
-       mfspr   r11,SPRN_HID0
-       mtcr    r11
-BEGIN_FTR_SECTION
-       bt-     8,4f                    /* Check DOZE */
-END_FTR_SECTION_IFSET(CPU_FTR_CAN_DOZE)
-BEGIN_FTR_SECTION
-       bt-     9,4f                    /* Check NAP */
-END_FTR_SECTION_IFSET(CPU_FTR_CAN_NAP)
+       tophys(r9,r9)                   /* check local flags */
+       lwz     r12,TI_LOCAL_FLAGS(r9)
+       mtcrf   0x01,r12
+       bt-     31-TLF_NAPPING,4f
 #endif /* CONFIG_6xx */
        .globl transfer_to_handler_cont
 transfer_to_handler_cont:
-       lwz     r11,THREAD_INFO-THREAD(r12)
-       cmplw   r1,r11                  /* if r1 <= current->thread_info */
-       ble-    stack_ovf               /* then the kernel stack overflowed */
 3:
        mflr    r9
        lwz     r11,0(r9)               /* virtual address of handler */
        lwz     r9,4(r9)                /* where to go when done */
-       FIX_SRR1(r10,r12)
        mtspr   SPRN_SRR0,r11
        mtspr   SPRN_SRR1,r10
        mtlr    r9
        SYNC
        RFI                             /* jump to handler, enable MMU */
 
-#ifdef CONFIG_6xx      
-4:     b       power_save_6xx_restore
+#ifdef CONFIG_6xx
+4:     rlwinm  r12,r12,0,~_TLF_NAPPING
+       stw     r12,TI_LOCAL_FLAGS(r9)
+       b       power_save_6xx_restore
 #endif
 
 /*
@@ -167,10 +166,10 @@ transfer_to_handler_cont:
  */
 stack_ovf:
        /* sometimes we use a statically-allocated stack, which is OK. */
-       lis     r11,_end@h
-       ori     r11,r11,_end@l
-       cmplw   r1,r11
-       ble     3b                      /* r1 <= &_end is OK */
+       lis     r12,_end@h
+       ori     r12,r12,_end@l
+       cmplw   r1,r12
+       ble     5b                      /* r1 <= &_end is OK */
        SAVE_NVGPRS(r11)
        addi    r3,r1,STACK_FRAME_OVERHEAD
        lis     r1,init_thread_union@ha
index a5ae04a57c784371c57b1a1e0dcaa6ab20fdac7d..b7d140430a41e4a4fc625161ad417211984a5570 100644 (file)
@@ -376,17 +376,53 @@ label##_common:                                           \
        bl      hdlr;                                   \
        b       .ret_from_except
 
+/*
+ * Like STD_EXCEPTION_COMMON, but for exceptions that can occur
+ * in the idle task and therefore need the special idle handling.
+ */
+#define STD_EXCEPTION_COMMON_IDLE(trap, label, hdlr)   \
+       .align  7;                                      \
+       .globl label##_common;                          \
+label##_common:                                                \
+       EXCEPTION_PROLOG_COMMON(trap, PACA_EXGEN);      \
+       FINISH_NAP;                                     \
+       DISABLE_INTS;                                   \
+       bl      .save_nvgprs;                           \
+       addi    r3,r1,STACK_FRAME_OVERHEAD;             \
+       bl      hdlr;                                   \
+       b       .ret_from_except
+
 #define STD_EXCEPTION_COMMON_LITE(trap, label, hdlr)   \
        .align  7;                                      \
        .globl label##_common;                          \
 label##_common:                                                \
        EXCEPTION_PROLOG_COMMON(trap, PACA_EXGEN);      \
+       FINISH_NAP;                                     \
        DISABLE_INTS;                                   \
        bl      .ppc64_runlatch_on;                     \
        addi    r3,r1,STACK_FRAME_OVERHEAD;             \
        bl      hdlr;                                   \
        b       .ret_from_except_lite
 
+/*
+ * When the idle code in power4_idle puts the CPU into NAP mode,
+ * it has to do so in a loop, and relies on the external interrupt
+ * and decrementer interrupt entry code to get it out of the loop.
+ * It sets the _TLF_NAPPING bit in current_thread_info()->local_flags
+ * to signal that it is in the loop and needs help to get out.
+ */
+#ifdef CONFIG_PPC_970_NAP
+#define FINISH_NAP                             \
+BEGIN_FTR_SECTION                              \
+       clrrdi  r11,r1,THREAD_SHIFT;            \
+       ld      r9,TI_LOCAL_FLAGS(r11);         \
+       andi.   r10,r9,_TLF_NAPPING;            \
+       bnel    power4_fixup_nap;               \
+END_FTR_SECTION_IFSET(CPU_FTR_CAN_NAP)
+#else
+#define FINISH_NAP
+#endif
+
 /*
  * Start of pSeries system interrupt routines
  */
@@ -772,6 +808,7 @@ hardware_interrupt_iSeries_masked:
        .globl machine_check_common
 machine_check_common:
        EXCEPTION_PROLOG_COMMON(0x200, PACA_EXMC)
+       FINISH_NAP
        DISABLE_INTS
        bl      .save_nvgprs
        addi    r3,r1,STACK_FRAME_OVERHEAD
@@ -783,7 +820,7 @@ machine_check_common:
        STD_EXCEPTION_COMMON(0xb00, trap_0b, .unknown_exception)
        STD_EXCEPTION_COMMON(0xd00, single_step, .single_step_exception)
        STD_EXCEPTION_COMMON(0xe00, trap_0e, .unknown_exception)
-       STD_EXCEPTION_COMMON(0xf00, performance_monitor, .performance_monitor_exception)
+       STD_EXCEPTION_COMMON_IDLE(0xf00, performance_monitor, .performance_monitor_exception)
        STD_EXCEPTION_COMMON(0x1300, instruction_breakpoint, .instruction_breakpoint_exception)
 #ifdef CONFIG_ALTIVEC
        STD_EXCEPTION_COMMON(0x1700, altivec_assist, .altivec_assist_exception)
@@ -1034,6 +1071,7 @@ unrecov_slb:
        .globl hardware_interrupt_entry
 hardware_interrupt_common:
        EXCEPTION_PROLOG_COMMON(0x500, PACA_EXGEN)
+       FINISH_NAP
 hardware_interrupt_entry:
        DISABLE_INTS
        bl      .ppc64_runlatch_on
@@ -1041,6 +1079,15 @@ hardware_interrupt_entry:
        bl      .do_IRQ
        b       .ret_from_except_lite
 
+#ifdef CONFIG_PPC_970_NAP
+power4_fixup_nap:
+       andc    r9,r9,r10
+       std     r9,TI_LOCAL_FLAGS(r11)
+       ld      r10,_LINK(r1)           /* make idle task do the */
+       std     r10,_NIP(r1)            /* equivalent of a blr */
+       blr
+#endif
+
        .align  7
        .globl alignment_common
 alignment_common:
index e9f321d74d85293323714af7b2bffa950e8760e6..d491052c8e0c5d3ab8c5ee1cfb70d7c1a93d45c5 100644 (file)
@@ -50,9 +50,9 @@ void cpu_idle(void)
 
        set_thread_flag(TIF_POLLING_NRFLAG);
        while (1) {
-               ppc64_runlatch_off();
-
                while (!need_resched() && !cpu_should_die()) {
+                       ppc64_runlatch_off();
+
                        if (ppc_md.power_save) {
                                clear_thread_flag(TIF_POLLING_NRFLAG);
                                /*
index 12a4efbaa08f41a684bfe00cd5ab410037548288..b45fa0e37212526614c88f5e384a5f5d7a59e1c6 100644 (file)
@@ -22,8 +22,6 @@
 #include <asm/ppc_asm.h>
 #include <asm/asm-offsets.h>
 
-#undef DEBUG
-
        .text
 
 /*
@@ -109,12 +107,6 @@ BEGIN_FTR_SECTION
        dcbf    0,r4
        dcbf    0,r4
 END_FTR_SECTION_IFSET(CPU_FTR_NAP_DISABLE_L2_PR)
-#ifdef DEBUG
-       lis     r6,nap_enter_count@ha
-       lwz     r4,nap_enter_count@l(r6)
-       addi    r4,r4,1
-       stw     r4,nap_enter_count@l(r6)
-#endif 
 2:
 BEGIN_FTR_SECTION
        /* Go to low speed mode on some 750FX */
@@ -144,48 +136,42 @@ BEGIN_FTR_SECTION
        DSSALL
        sync
 END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
+       rlwinm  r9,r1,0,0,31-THREAD_SHIFT       /* current thread_info */
+       lwz     r8,TI_LOCAL_FLAGS(r9)   /* set napping bit */
+       ori     r8,r8,_TLF_NAPPING      /* so when we take an exception */
+       stw     r8,TI_LOCAL_FLAGS(r9)   /* it will return to our caller */
        mfmsr   r7
        ori     r7,r7,MSR_EE
        oris    r7,r7,MSR_POW@h
-       sync
-       isync
+1:     sync
        mtmsr   r7
        isync
-       sync
-       blr
-       
+       b       1b
+
 /*
  * Return from NAP/DOZE mode, restore some CPU specific registers,
  * we are called with DR/IR still off and r2 containing physical
- * address of current.
+ * address of current.  R11 points to the exception frame (physical
+ * address).  We have to preserve r10.
  */
 _GLOBAL(power_save_6xx_restore)
-       mfspr   r11,SPRN_HID0
-       rlwinm. r11,r11,0,10,8  /* Clear NAP & copy NAP bit !state to cr1 EQ */
-       cror    4*cr1+eq,4*cr0+eq,4*cr0+eq
-BEGIN_FTR_SECTION
-       rlwinm  r11,r11,0,9,7   /* Clear DOZE */
-END_FTR_SECTION_IFSET(CPU_FTR_CAN_DOZE)
-       mtspr   SPRN_HID0, r11
+       lwz     r9,_LINK(r11)           /* interrupted in ppc6xx_idle: */
+       stw     r9,_NIP(r11)            /* make it do a blr */
 
-#ifdef DEBUG
-       beq     cr1,1f
-       lis     r11,(nap_return_count-KERNELBASE)@ha
-       lwz     r9,nap_return_count@l(r11)
-       addi    r9,r9,1
-       stw     r9,nap_return_count@l(r11)
-1:
-#endif
-       
-       rlwinm  r9,r1,0,0,18
-       tophys(r9,r9)
-       lwz     r11,TI_CPU(r9)
+#ifdef CONFIG_SMP
+       mfspr   r12,SPRN_SPRG3
+       lwz     r11,TI_CPU(r12)         /* get cpu number * 4 */
        slwi    r11,r11,2
+#else
+       li      r11,0
+#endif
        /* Todo make sure all these are in the same page
-        * and load r22 (@ha part + CPU offset) only once
+        * and load r11 (@ha part + CPU offset) only once
         */
 BEGIN_FTR_SECTION
-       beq     cr1,1f
+       mfspr   r9,SPRN_HID0
+       andis.  r9,r9,HID0_NAP@h
+       beq     1f
        addis   r9,r11,(nap_save_msscr0-KERNELBASE)@ha
        lwz     r9,nap_save_msscr0@l(r9)
        mtspr   SPRN_MSSCR0, r9
@@ -210,10 +196,3 @@ _GLOBAL(nap_save_hid1)
 
 _GLOBAL(powersave_lowspeed)
        .long   0
-
-#ifdef DEBUG
-_GLOBAL(nap_enter_count)
-       .space  4
-_GLOBAL(nap_return_count)
-       .space  4
-#endif
index 6dad1c02496e723ee794f582216ea3077bf8f882..d85c7c938eed37f075c4eca9c95c0510b739d1aa 100644 (file)
@@ -35,12 +35,16 @@ BEGIN_FTR_SECTION
        DSSALL
        sync
 END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
+       clrrdi  r9,r1,THREAD_SHIFT      /* current thread_info */
+       ld      r8,TI_LOCAL_FLAGS(r9)   /* set napping bit */
+       ori     r8,r8,_TLF_NAPPING      /* so when we take an exception */
+       std     r8,TI_LOCAL_FLAGS(r9)   /* it will return to our caller */
        mfmsr   r7
        ori     r7,r7,MSR_EE
        oris    r7,r7,MSR_POW@h
-       sync
+1:     sync
        isync
        mtmsrd  r7
        isync
-       sync
-       blr
+       b       1b
+
index bb5c9501234c8364c855cf11d7e363983603ef61..57d560c68897b08bcd85003eaefbf1c4442ad0ac 100644 (file)
@@ -272,18 +272,26 @@ unsigned int virt_irq_to_real_map[NR_IRQS];
  * Don't use virtual irqs 0, 1, 2 for devices.
  * The pcnet32 driver considers interrupt numbers < 2 to be invalid,
  * and 2 is the XICS IPI interrupt.
- * We limit virtual irqs to 17 less than NR_IRQS so that when we
- * offset them by 16 (to reserve the first 16 for ISA interrupts)
- * we don't end up with an interrupt number >= NR_IRQS.
+ * We limit virtual irqs to __irq_offet_value less than virt_irq_max so
+ * that when we offset them we don't end up with an interrupt
+ * number >= virt_irq_max.
  */
 #define MIN_VIRT_IRQ   3
-#define MAX_VIRT_IRQ   (NR_IRQS - NUM_ISA_INTERRUPTS - 1)
-#define NR_VIRT_IRQS   (MAX_VIRT_IRQ - MIN_VIRT_IRQ + 1)
+
+unsigned int virt_irq_max;
+static unsigned int max_virt_irq;
+static unsigned int nr_virt_irqs;
 
 void
 virt_irq_init(void)
 {
        int i;
+
+       if ((virt_irq_max == 0) || (virt_irq_max > (NR_IRQS - 1)))
+               virt_irq_max = NR_IRQS - 1;
+       max_virt_irq = virt_irq_max - __irq_offset_value;
+       nr_virt_irqs = max_virt_irq - MIN_VIRT_IRQ + 1;
+
        for (i = 0; i < NR_IRQS; i++)
                virt_irq_to_real_map[i] = UNDEFINED_IRQ;
 }
@@ -308,17 +316,17 @@ int virt_irq_create_mapping(unsigned int real_irq)
                return real_irq;
        }
 
-       /* map to a number between MIN_VIRT_IRQ and MAX_VIRT_IRQ */
+       /* map to a number between MIN_VIRT_IRQ and max_virt_irq */
        virq = real_irq;
-       if (virq > MAX_VIRT_IRQ)
-               virq = (virq % NR_VIRT_IRQS) + MIN_VIRT_IRQ;
+       if (virq > max_virt_irq)
+               virq = (virq % nr_virt_irqs) + MIN_VIRT_IRQ;
 
        /* search for this number or a free slot */
        first_virq = virq;
        while (virt_irq_to_real_map[virq] != UNDEFINED_IRQ) {
                if (virt_irq_to_real_map[virq] == real_irq)
                        return virq;
-               if (++virq > MAX_VIRT_IRQ)
+               if (++virq > max_virt_irq)
                        virq = MIN_VIRT_IRQ;
                if (virq == first_virq)
                        goto nospace;   /* oops, no free slots */
@@ -330,8 +338,8 @@ int virt_irq_create_mapping(unsigned int real_irq)
  nospace:
        if (!warned) {
                printk(KERN_CRIT "Interrupt table is full\n");
-               printk(KERN_CRIT "Increase NR_IRQS (currently %d) "
-                      "in your kernel sources and rebuild.\n", NR_IRQS);
+               printk(KERN_CRIT "Increase virt_irq_max (currently %d) "
+                      "in your kernel sources and rebuild.\n", virt_irq_max);
                warned = 1;
        }
        return NO_IRQ;
@@ -349,8 +357,8 @@ unsigned int real_irq_to_virt_slowpath(unsigned int real_irq)
 
        virq = real_irq;
 
-       if (virq > MAX_VIRT_IRQ)
-               virq = (virq % NR_VIRT_IRQS) + MIN_VIRT_IRQ;
+       if (virq > max_virt_irq)
+               virq = (virq % nr_virt_irqs) + MIN_VIRT_IRQ;
 
        first_virq = virq;
 
@@ -360,7 +368,7 @@ unsigned int real_irq_to_virt_slowpath(unsigned int real_irq)
 
                virq++;
 
-               if (virq >= MAX_VIRT_IRQ)
+               if (virq >= max_virt_irq)
                        virq = 0;
 
        } while (first_virq != virq);
index ad7a90212204ee68eea83075b51fbadf5a62ef4b..856ef1a832b9466031309cd9b20f4dda31242396 100644 (file)
@@ -88,7 +88,7 @@ void __kprobes arch_remove_kprobe(struct kprobe *p)
        mutex_unlock(&kprobe_mutex);
 }
 
-static inline void prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
+static void __kprobes prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
 {
        kprobe_opcode_t insn = *p->ainsn.insn;
 
@@ -101,21 +101,21 @@ static inline void prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
                regs->nip = (unsigned long)p->ainsn.insn;
 }
 
-static inline void save_previous_kprobe(struct kprobe_ctlblk *kcb)
+static void __kprobes save_previous_kprobe(struct kprobe_ctlblk *kcb)
 {
        kcb->prev_kprobe.kp = kprobe_running();
        kcb->prev_kprobe.status = kcb->kprobe_status;
        kcb->prev_kprobe.saved_msr = kcb->kprobe_saved_msr;
 }
 
-static inline void restore_previous_kprobe(struct kprobe_ctlblk *kcb)
+static void __kprobes restore_previous_kprobe(struct kprobe_ctlblk *kcb)
 {
        __get_cpu_var(current_kprobe) = kcb->prev_kprobe.kp;
        kcb->kprobe_status = kcb->prev_kprobe.status;
        kcb->kprobe_saved_msr = kcb->prev_kprobe.saved_msr;
 }
 
-static inline void set_current_kprobe(struct kprobe *p, struct pt_regs *regs,
+static void __kprobes set_current_kprobe(struct kprobe *p, struct pt_regs *regs,
                                struct kprobe_ctlblk *kcb)
 {
        __get_cpu_var(current_kprobe) = p;
@@ -141,7 +141,7 @@ void __kprobes arch_prepare_kretprobe(struct kretprobe *rp,
        }
 }
 
-static inline int kprobe_handler(struct pt_regs *regs)
+static int __kprobes kprobe_handler(struct pt_regs *regs)
 {
        struct kprobe *p;
        int ret = 0;
@@ -334,7 +334,7 @@ static void __kprobes resume_execution(struct kprobe *p, struct pt_regs *regs)
                regs->nip = (unsigned long)p->addr + 4;
 }
 
-static inline int post_kprobe_handler(struct pt_regs *regs)
+static int __kprobes post_kprobe_handler(struct pt_regs *regs)
 {
        struct kprobe *cur = kprobe_running();
        struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
@@ -370,7 +370,7 @@ out:
        return 1;
 }
 
-static inline int kprobe_fault_handler(struct pt_regs *regs, int trapnr)
+static int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr)
 {
        struct kprobe *cur = kprobe_running();
        struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
index d66c5e77fcff35c9c5eb921339bd016b0c9c9978..7e4d54821a079411499dd2958f26bec980b1300b 100644 (file)
@@ -1528,12 +1528,11 @@ static int __init prom_find_machine_type(void)
         *    non-IBM designs !
         *  - it has /rtas
         */
-       len = prom_getprop(_prom->root, "model",
+       len = prom_getprop(_prom->root, "device_type",
                           compat, sizeof(compat)-1);
        if (len <= 0)
                return PLATFORM_GENERIC;
-       compat[len] = 0;
-       if (strcmp(compat, "chrp"))
+       if (strncmp(compat, RELOC("chrp"), 4))
                return PLATFORM_GENERIC;
 
        /* Default to pSeries. We need to know if we are running LPAR */
index 456286cf1d143cd8f6ca3ee9bf12af459620c1ce..9c9ad1fa9cce90748c7362d5dea5d744cdd84f08 100644 (file)
@@ -258,11 +258,11 @@ static int __init proc_rtas_init(void)
        struct proc_dir_entry *entry;
 
        if (!machine_is(pseries))
-               return 1;
+               return -ENODEV;
 
        rtas_node = of_find_node_by_name(NULL, "rtas");
        if (rtas_node == NULL)
-               return 1;
+               return -ENODEV;
 
        entry = create_proc_entry("ppc64/rtas/progress", S_IRUGO|S_IWUSR, NULL);
        if (entry)
index 97898d5d34e5c0539d942d4a7373c73eb6c3ff04..1726bfe38ee08f5dcd1aa3a198f43c7e086a2129 100644 (file)
@@ -1297,7 +1297,7 @@ static inline void setup_decr(struct spu_state *csa, struct spu *spu)
                cycles_t resume_time = get_cycles();
                cycles_t delta_time = resume_time - csa->suspend_time;
 
-               csa->lscsa->decr.slot[0] = delta_time;
+               csa->lscsa->decr.slot[0] -= delta_time;
        }
 }
 
index 63f0aee4c158e97df652e49b43d00551aaa21e03..996c28744e96a6d206a5f778dd562b5f30b3cf44 100644 (file)
@@ -9,3 +9,4 @@ extern long chrp_time_init(void);
 
 extern void chrp_find_bridges(void);
 extern void chrp_event_scan(unsigned long);
+extern void chrp_pcibios_fixup(void);
index 8ef279ad36ad15ddbd5500835b1580fb04134955..ac224876ce5943f999a0def0007f7214cd35ff9a 100644 (file)
@@ -23,6 +23,8 @@
 #include <asm/grackle.h>
 #include <asm/rtas.h>
 
+#include "chrp.h"
+
 /* LongTrail */
 void __iomem *gg2_pci_config_base;
 
@@ -314,6 +316,6 @@ chrp_find_bridges(void)
        }
 
        /* Do not fixup interrupts from OF tree on pegasos */
-       if (is_pegasos == 0)
-               ppc_md.pcibios_fixup = chrp_pcibios_fixup;
+       if (is_pegasos)
+               ppc_md.pcibios_fixup = NULL;
 }
index 23a2017187049d721dcac2f3b49efe82b1f221f1..18d89f38796b458d9953b93672893c528b537acf 100644 (file)
@@ -440,8 +440,6 @@ void __init chrp_init_IRQ(void)
 
        if (_chrp_type == _CHRP_Pegasos)
                ppc_md.get_irq        = i8259_irq;
-       else
-               ppc_md.get_irq        = mpic_get_irq;
 
 #if defined(CONFIG_VT) && defined(CONFIG_INPUT_ADBHID) && defined(XMON)
        /* see if there is a keyboard in the device tree
@@ -528,26 +526,24 @@ static int __init chrp_probe(void)
        /* Assume we have an 8259... */
        __irq_offset_value = NUM_ISA_INTERRUPTS;
 
-       ppc_md.setup_arch     = chrp_setup_arch;
-       ppc_md.show_cpuinfo   = chrp_show_cpuinfo;
-
-       ppc_md.init_IRQ       = chrp_init_IRQ;
-       ppc_md.init           = chrp_init2;
-
-       ppc_md.phys_mem_access_prot = pci_phys_mem_access_prot;
-
-       ppc_md.restart        = rtas_restart;
-       ppc_md.power_off      = rtas_power_off;
-       ppc_md.halt           = rtas_halt;
-
-       ppc_md.time_init      = chrp_time_init;
-       ppc_md.calibrate_decr = generic_calibrate_decr;
-
-       /* this may get overridden with rtas routines later... */
-       ppc_md.set_rtc_time   = chrp_set_rtc_time;
-       ppc_md.get_rtc_time   = chrp_get_rtc_time;
-
-#ifdef CONFIG_SMP
-       smp_ops = &chrp_smp_ops;
-#endif /* CONFIG_SMP */
+       return 1;
 }
+
+define_machine(chrp) {
+       .name                   = "CHRP",
+       .probe                  = chrp_probe,
+       .setup_arch             = chrp_setup_arch,
+       .init                   = chrp_init2,
+       .show_cpuinfo           = chrp_show_cpuinfo,
+       .init_IRQ               = chrp_init_IRQ,
+       .get_irq                = mpic_get_irq,
+       .pcibios_fixup          = chrp_pcibios_fixup,
+       .restart                = rtas_restart,
+       .power_off              = rtas_power_off,
+       .halt                   = rtas_halt,
+       .time_init              = chrp_time_init,
+       .set_rtc_time           = chrp_set_rtc_time,
+       .get_rtc_time           = chrp_get_rtc_time,
+       .calibrate_decr         = generic_calibrate_decr,
+       .phys_mem_access_prot   = pci_phys_mem_access_prot,
+};
index 6ce8a404ba6b2b9cd8f5ccbccbb1888b441df1ba..a6fd9bedb0741b533fc207650a128ef1c35070ec 100644 (file)
@@ -54,6 +54,7 @@
 #include <asm/iseries/hv_lp_event.h>
 #include <asm/iseries/lpar_map.h>
 #include <asm/udbg.h>
+#include <asm/irq.h>
 
 #include "naca.h"
 #include "setup.h"
@@ -684,6 +685,12 @@ static int __init iseries_probe(void)
        powerpc_firmware_features |= FW_FEATURE_ISERIES;
        powerpc_firmware_features |= FW_FEATURE_LPAR;
 
+       /*
+        * The Hypervisor only allows us up to 256 interrupt
+        * sources (the irq number is passed in a u8).
+        */
+       virt_irq_max = 255;
+
        return 1;
 }
 
index 780fb27a0099e24ca66b3fee2fbb9a5f7a258f1b..32eaddfa5470a635741228ada3365e4b9f20b5de 100644 (file)
@@ -957,8 +957,10 @@ static void eeh_remove_device(struct pci_dev *dev)
        pci_addr_cache_remove_device(dev);
 
        dn = pci_device_to_OF_node(dev);
-       PCI_DN(dn)->pcidev = NULL;
-       pci_dev_put (dev);
+       if (PCI_DN(dn)->pcidev) {
+               PCI_DN(dn)->pcidev = NULL;
+               pci_dev_put (dev);
+       }
 }
 
 void eeh_remove_bus_device(struct pci_dev *dev)
index fcc4d561a23653a659775efd27f9f8c4ccd75d4b..e0000ce769e51831db5df3fe82f25d57384c1e16 100644 (file)
@@ -488,7 +488,7 @@ static int __init rtas_init(void)
        /* No RTAS */
        if (rtas_token("event-scan") == RTAS_UNKNOWN_SERVICE) {
                printk(KERN_INFO "rtasd: no event-scan on system\n");
-               return 1;
+               return -ENODEV;
        }
 
        entry = create_proc_entry("ppc64/rtas/error_log", S_IRUSR, NULL);
index 60c724e1158499e6c136542447c96f9a13ddce96..7662c4e6e7d6070786ce144cb97ea20e6d4bd3a9 100644 (file)
@@ -156,12 +156,13 @@ void platform_notify_map(const struct platform_notify_dev_map *map,
        while (map->bus_id != NULL) {
                idx = -1;
                s = strrchr(dev->bus_id, '.');
-               if (s != NULL)
+               if (s != NULL) {
                        idx = (int)simple_strtol(s + 1, NULL, 10);
-               else
+                       len = s - dev->bus_id;
+               } else {
                        s = dev->bus_id;
-
-               len = s - dev->bus_id;
+                       len = strlen(dev->bus_id);
+               }
 
                if (!strncmp(dev->bus_id, map->bus_id, len)) {
                        pdev = container_of(dev, struct platform_device, dev);
index 648047a0bce34ed91d7eace9f05b9d4dfedb9e5b..43a66f5407f45b2b5d04666f0f765f2cd287778b 100644 (file)
@@ -187,7 +187,7 @@ config HUGETLB_PAGE_SIZE_512K
        bool "512K"
 
 config HUGETLB_PAGE_SIZE_64K
-       depends on !SPARC64_PAGE_SIZE_4MB && !SPARC64_PAGE_SIZE_512KB && !SPARC64_PAGE_SIZE_64K
+       depends on !SPARC64_PAGE_SIZE_4MB && !SPARC64_PAGE_SIZE_512KB && !SPARC64_PAGE_SIZE_64KB
        bool "64K"
 
 endchoice
index ffc7309e9f22d51e640f77b95aab4028e57c841f..2e1c824c1cc9512356460ea3a09f2fd74c11dfe2 100644 (file)
@@ -63,7 +63,7 @@ void __kprobes arch_disarm_kprobe(struct kprobe *p)
        flushi(p->addr);
 }
 
-static inline void save_previous_kprobe(struct kprobe_ctlblk *kcb)
+static void __kprobes save_previous_kprobe(struct kprobe_ctlblk *kcb)
 {
        kcb->prev_kprobe.kp = kprobe_running();
        kcb->prev_kprobe.status = kcb->kprobe_status;
@@ -71,7 +71,7 @@ static inline void save_previous_kprobe(struct kprobe_ctlblk *kcb)
        kcb->prev_kprobe.orig_tstate_pil = kcb->kprobe_orig_tstate_pil;
 }
 
-static inline void restore_previous_kprobe(struct kprobe_ctlblk *kcb)
+static void __kprobes restore_previous_kprobe(struct kprobe_ctlblk *kcb)
 {
        __get_cpu_var(current_kprobe) = kcb->prev_kprobe.kp;
        kcb->kprobe_status = kcb->prev_kprobe.status;
@@ -79,7 +79,7 @@ static inline void restore_previous_kprobe(struct kprobe_ctlblk *kcb)
        kcb->kprobe_orig_tstate_pil = kcb->prev_kprobe.orig_tstate_pil;
 }
 
-static inline void set_current_kprobe(struct kprobe *p, struct pt_regs *regs,
+static void __kprobes set_current_kprobe(struct kprobe *p, struct pt_regs *regs,
                                struct kprobe_ctlblk *kcb)
 {
        __get_cpu_var(current_kprobe) = p;
@@ -87,7 +87,7 @@ static inline void set_current_kprobe(struct kprobe *p, struct pt_regs *regs,
        kcb->kprobe_orig_tstate_pil = (regs->tstate & TSTATE_PIL);
 }
 
-static inline void prepare_singlestep(struct kprobe *p, struct pt_regs *regs,
+static void __kprobes prepare_singlestep(struct kprobe *p, struct pt_regs *regs,
                        struct kprobe_ctlblk *kcb)
 {
        regs->tstate |= TSTATE_PIL;
@@ -273,7 +273,7 @@ static void __kprobes resume_execution(struct kprobe *p,
                        kcb->kprobe_orig_tstate_pil);
 }
 
-static inline int post_kprobe_handler(struct pt_regs *regs)
+static int __kprobes post_kprobe_handler(struct pt_regs *regs)
 {
        struct kprobe *cur = kprobe_running();
        struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
@@ -300,7 +300,7 @@ out:
        return 1;
 }
 
-static inline int kprobe_fault_handler(struct pt_regs *regs, int trapnr)
+static int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr)
 {
        struct kprobe *cur = kprobe_running();
        struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
index dfccff29e182c1b2c68876debad304b6bf52ed11..f97ddeb105ac492b6b66cc1b87642b88dd2afe2e 100644 (file)
@@ -419,6 +419,7 @@ void pcibios_resource_to_bus(struct pci_dev *pdev, struct pci_bus_region *region
        region->start = res->start - zero_res.start;
        region->end = res->end - zero_res.start;
 }
+EXPORT_SYMBOL(pcibios_resource_to_bus);
 
 void pcibios_bus_to_resource(struct pci_dev *pdev, struct resource *res,
                             struct pci_bus_region *region)
index 0ec4052db9c5bbb183714a44012ef07fc388b026..6ab852bfcd3ac62cb66b18a02433d6b3feaadfcb 100644 (file)
@@ -100,7 +100,7 @@ struct cow_header_v3_broken {
        __u32 alignment;
        __u32 cow_format;
        char backing_file[PATH_LEN_V3];
-};
+} __attribute__((packed));
 
 /* COW format definitions - for now, we have only the usual COW bitmap */
 #define COW_BITMAP 0
index 018b3819ab0bf3ea4fc3007a8240b6b7f99c8dca..8e7053013f7b7d11d218603487abf8c9dcd96294 100644 (file)
@@ -4,11 +4,11 @@
 #include <setjmp.h>
 #include "os.h"
 
-#define UML_SIGLONGJMP(buf, val) do { \
+#define UML_LONGJMP(buf, val) do { \
        longjmp(*buf, val);     \
 } while(0)
 
-#define UML_SIGSETJMP(buf, enable) ({ \
+#define UML_SETJMP(buf, enable) ({ \
        int n; \
        enable = get_signals(); \
        n = setjmp(*buf); \
index 82f96c574144cbc327daa8b5c82624014bb9cf83..2c13de321f2fb330eb5dc162fe53bffca57f3bad 100644 (file)
@@ -1,6 +1,7 @@
 #include <linux/stddef.h>
 #include <linux/sched.h>
 #include <linux/elf.h>
+#include <asm/mman.h>
 
 #define DEFINE(sym, val) \
        asm volatile("\n->" #sym " %0 " #val : : "i" (val))
@@ -16,6 +17,7 @@
 void foo(void)
 {
        OFFSET(HOST_TASK_DEBUGREGS, task_struct, thread.arch.debugregs);
+       DEFINE(KERNEL_MADV_REMOVE, MADV_REMOVE);
 #ifdef CONFIG_MODE_TT
        OFFSET(HOST_TASK_EXTERN_PID, task_struct, thread.mode.tt.extern_pid);
 #endif
index 5ce93abd0b54fd79f95dea8df40cf3a756366bc0..939cc475757a583e7b38977f02c6f095de004465 100644 (file)
@@ -4,6 +4,7 @@
 #include <linux/time.h>
 #include <linux/elf.h>
 #include <asm/page.h>
+#include <asm/mman.h>
 
 #define DEFINE(sym, val) \
        asm volatile("\n->" #sym " %0 " #val : : "i" (val))
@@ -18,6 +19,7 @@
 
 void foo(void)
 {
+       DEFINE(KERNEL_MADV_REMOVE, MADV_REMOVE);
 #ifdef CONFIG_MODE_TT
        OFFSET(HOST_TASK_EXTERN_PID, task_struct, thread.mode.tt.extern_pid);
 #endif
index 71bb90a7606d0ebf8dab332fd874aa0e0f6d707b..c6432e7292411de1ea2006aabf97a13c3a7fa4eb 100644 (file)
@@ -8,6 +8,7 @@
 #include <fcntl.h>
 #include <sys/types.h>
 #include <sys/mman.h>
+#include <sys/statfs.h>
 #include "kern_util.h"
 #include "user.h"
 #include "user_util.h"
@@ -19,6 +20,7 @@
 
 #include <sys/param.h>
 
+static char *default_tmpdir = "/tmp";
 static char *tempdir = NULL;
 
 static void __init find_tempdir(void)
@@ -34,7 +36,7 @@ static void __init find_tempdir(void)
                        break;
        }
        if((dir == NULL) || (*dir == '\0'))
-               dir = "/tmp";
+               dir = default_tmpdir;
 
        tempdir = malloc(strlen(dir) + 2);
        if(tempdir == NULL){
@@ -46,6 +48,96 @@ static void __init find_tempdir(void)
        strcat(tempdir, "/");
 }
 
+/* This will return 1, with the first character in buf being the
+ * character following the next instance of c in the file.  This will
+ * read the file as needed.  If there's an error, -errno is returned;
+ * if the end of the file is reached, 0 is returned.
+ */
+static int next(int fd, char *buf, int size, char c)
+{
+       int n;
+       char *ptr;
+
+       while((ptr = strchr(buf, c)) == NULL){
+               n = read(fd, buf, size - 1);
+               if(n == 0)
+                       return 0;
+               else if(n < 0)
+                       return -errno;
+
+               buf[n] = '\0';
+       }
+
+       ptr++;
+       memmove(buf, ptr, strlen(ptr) + 1);
+       return 1;
+}
+
+static int checked_tmpdir = 0;
+
+/* Look for a tmpfs mounted at /dev/shm.  I couldn't find a cleaner
+ * way to do this than to parse /proc/mounts.  statfs will return the
+ * same filesystem magic number and fs id for both /dev and /dev/shm
+ * when they are both tmpfs, so you can't tell if they are different
+ * filesystems.  Also, there seems to be no other way of finding the
+ * mount point of a filesystem from within it.
+ *
+ * If a /dev/shm tmpfs entry is found, then we switch to using it.
+ * Otherwise, we stay with the default /tmp.
+ */
+static void which_tmpdir(void)
+{
+       int fd, found;
+       char buf[128] = { '\0' };
+
+       if(checked_tmpdir)
+               return;
+
+       checked_tmpdir = 1;
+
+       printf("Checking for tmpfs mount on /dev/shm...");
+
+       fd = open("/proc/mounts", O_RDONLY);
+       if(fd < 0){
+               printf("failed to open /proc/mounts, errno = %d\n", errno);
+               return;
+       }
+
+       while(1){
+               found = next(fd, buf, sizeof(buf) / sizeof(buf[0]), ' ');
+               if(found != 1)
+                       break;
+
+               if(!strncmp(buf, "/dev/shm", strlen("/dev/shm")))
+                       goto found;
+
+               found = next(fd, buf, sizeof(buf) / sizeof(buf[0]), '\n');
+               if(found != 1)
+                       break;
+       }
+
+err:
+       if(found == 0)
+               printf("nothing mounted on /dev/shm\n");
+       else if(found < 0)
+               printf("read returned errno %d\n", -found);
+
+       return;
+
+found:
+       found = next(fd, buf, sizeof(buf) / sizeof(buf[0]), ' ');
+       if(found != 1)
+               goto err;
+
+       if(strncmp(buf, "tmpfs", strlen("tmpfs"))){
+               printf("not tmpfs\n");
+               return;
+       }
+
+       printf("OK\n");
+       default_tmpdir = "/dev/shm";
+}
+
 /*
  * This proc still used in tt-mode
  * (file: kernel/tt/ptproxy/proxy.c, proc: start_debugger).
@@ -56,6 +148,7 @@ int make_tempfile(const char *template, char **out_tempname, int do_unlink)
        char *tempname;
        int fd;
 
+       which_tmpdir();
        tempname = malloc(MAXPATHLEN);
 
        find_tempdir();
@@ -137,3 +230,26 @@ int create_mem_file(unsigned long long len)
        }
        return(fd);
 }
+
+
+void check_tmpexec(void)
+{
+       void *addr;
+       int err, fd = create_tmp_file(UM_KERN_PAGE_SIZE);
+
+       addr = mmap(NULL, UM_KERN_PAGE_SIZE,
+                   PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE, fd, 0);
+       printf("Checking PROT_EXEC mmap in %s...",tempdir);
+       fflush(stdout);
+       if(addr == MAP_FAILED){
+               err = errno;
+               perror("failed");
+               if(err == EPERM)
+                       printf("%s must be not mounted noexec\n",tempdir);
+               exit(1);
+       }
+       printf("OK\n");
+       munmap(addr, UM_KERN_PAGE_SIZE);
+
+       close(fd);
+}
index 8176b0b52047061ae681e19d51583f4e683cad97..3505f44f8a25b4d2687327f4844ee61c468752e7 100644 (file)
@@ -190,7 +190,7 @@ int os_unmap_memory(void *addr, int len)
 }
 
 #ifndef MADV_REMOVE
-#define MADV_REMOVE    0x5             /* remove these pages & resources */
+#define MADV_REMOVE KERNEL_MADV_REMOVE
 #endif
 
 int os_drop_memory(void *addr, int length)
@@ -216,7 +216,7 @@ int can_drop_memory(void)
        }
 
        addr = mmap64(NULL, UM_KERN_PAGE_SIZE, PROT_READ | PROT_WRITE,
-                     MAP_PRIVATE, fd, 0);
+                     MAP_SHARED, fd, 0);
        if(addr == MAP_FAILED){
                printk("Mapping test memory file failed, err = %d\n", -errno);
                return 0;
@@ -266,11 +266,11 @@ void init_new_thread_signals(int altstack)
 
 int run_kernel_thread(int (*fn)(void *), void *arg, void **jmp_ptr)
 {
-       sigjmp_buf buf;
+       jmp_buf buf;
        int n, enable;
 
        *jmp_ptr = &buf;
-       n = UML_SIGSETJMP(&buf, enable);
+       n = UML_SETJMP(&buf, enable);
        if(n != 0)
                return(n);
        (*fn)(arg);
index 045ae0037456a3a723e5d58fdb9858af64349a61..0776bc18ca85ebeab95d1f579e244a7b2fe988e8 100644 (file)
@@ -434,7 +434,7 @@ void new_thread(void *stack, void **switch_buf_ptr, void **fork_buf_ptr,
                void (*handler)(int))
 {
        unsigned long flags;
-       sigjmp_buf switch_buf, fork_buf;
+       jmp_buf switch_buf, fork_buf;
        int enable;
 
        *switch_buf_ptr = &switch_buf;
@@ -450,7 +450,7 @@ void new_thread(void *stack, void **switch_buf_ptr, void **fork_buf_ptr,
         */
        flags = get_signals();
        block_signals();
-       if(UML_SIGSETJMP(&fork_buf, enable) == 0)
+       if(UML_SETJMP(&fork_buf, enable) == 0)
                new_thread_proc(stack, handler);
 
        remove_sigstack();
@@ -466,35 +466,35 @@ void new_thread(void *stack, void **switch_buf_ptr, void **fork_buf_ptr,
 
 void thread_wait(void *sw, void *fb)
 {
-       sigjmp_buf buf, **switch_buf = sw, *fork_buf;
+       jmp_buf buf, **switch_buf = sw, *fork_buf;
        int enable;
 
        *switch_buf = &buf;
        fork_buf = fb;
-       if(UML_SIGSETJMP(&buf, enable) == 0)
+       if(UML_SETJMP(&buf, enable) == 0)
                siglongjmp(*fork_buf, INIT_JMP_REMOVE_SIGSTACK);
 }
 
 void switch_threads(void *me, void *next)
 {
-       sigjmp_buf my_buf, **me_ptr = me, *next_buf = next;
+       jmp_buf my_buf, **me_ptr = me, *next_buf = next;
        int enable;
 
        *me_ptr = &my_buf;
-       if(UML_SIGSETJMP(&my_buf, enable) == 0)
-               UML_SIGLONGJMP(next_buf, 1);
+       if(UML_SETJMP(&my_buf, enable) == 0)
+               UML_LONGJMP(next_buf, 1);
 }
 
-static sigjmp_buf initial_jmpbuf;
+static jmp_buf initial_jmpbuf;
 
 /* XXX Make these percpu */
 static void (*cb_proc)(void *arg);
 static void *cb_arg;
-static sigjmp_buf *cb_back;
+static jmp_buf *cb_back;
 
 int start_idle_thread(void *stack, void *switch_buf_ptr, void **fork_buf_ptr)
 {
-       sigjmp_buf **switch_buf = switch_buf_ptr;
+       jmp_buf **switch_buf = switch_buf_ptr;
        int n, enable;
 
        set_handler(SIGWINCH, (__sighandler_t) sig_handler,
@@ -502,7 +502,7 @@ int start_idle_thread(void *stack, void *switch_buf_ptr, void **fork_buf_ptr)
                    SIGVTALRM, -1);
 
        *fork_buf_ptr = &initial_jmpbuf;
-       n = UML_SIGSETJMP(&initial_jmpbuf, enable);
+       n = UML_SETJMP(&initial_jmpbuf, enable);
        switch(n){
        case INIT_JMP_NEW_THREAD:
                new_thread_proc((void *) stack, new_thread_handler);
@@ -512,7 +512,7 @@ int start_idle_thread(void *stack, void *switch_buf_ptr, void **fork_buf_ptr)
                break;
        case INIT_JMP_CALLBACK:
                (*cb_proc)(cb_arg);
-               UML_SIGLONGJMP(cb_back, 1);
+               UML_LONGJMP(cb_back, 1);
                break;
        case INIT_JMP_HALT:
                kmalloc_ok = 0;
@@ -523,12 +523,12 @@ int start_idle_thread(void *stack, void *switch_buf_ptr, void **fork_buf_ptr)
        default:
                panic("Bad sigsetjmp return in start_idle_thread - %d\n", n);
        }
-       UML_SIGLONGJMP(*switch_buf, 1);
+       UML_LONGJMP(*switch_buf, 1);
 }
 
 void initial_thread_cb_skas(void (*proc)(void *), void *arg)
 {
-       sigjmp_buf here;
+       jmp_buf here;
        int enable;
 
        cb_proc = proc;
@@ -536,8 +536,8 @@ void initial_thread_cb_skas(void (*proc)(void *), void *arg)
        cb_back = &here;
 
        block_signals();
-       if(UML_SIGSETJMP(&here, enable) == 0)
-               UML_SIGLONGJMP(&initial_jmpbuf, INIT_JMP_CALLBACK);
+       if(UML_SETJMP(&here, enable) == 0)
+               UML_LONGJMP(&initial_jmpbuf, INIT_JMP_CALLBACK);
        unblock_signals();
 
        cb_proc = NULL;
@@ -548,13 +548,13 @@ void initial_thread_cb_skas(void (*proc)(void *), void *arg)
 void halt_skas(void)
 {
        block_signals();
-       UML_SIGLONGJMP(&initial_jmpbuf, INIT_JMP_HALT);
+       UML_LONGJMP(&initial_jmpbuf, INIT_JMP_HALT);
 }
 
 void reboot_skas(void)
 {
        block_signals();
-       UML_SIGLONGJMP(&initial_jmpbuf, INIT_JMP_REBOOT);
+       UML_LONGJMP(&initial_jmpbuf, INIT_JMP_REBOOT);
 }
 
 void switch_mm_skas(struct mm_id *mm_idp)
index 387e26af301a57c6ca0a861c654727af7a5b3696..5031485040090bfc07ba71eca0a41564c0cc8b03 100644 (file)
@@ -296,29 +296,7 @@ static void __init check_ptrace(void)
        check_sysemu();
 }
 
-extern int create_tmp_file(unsigned long long len);
-
-static void check_tmpexec(void)
-{
-       void *addr;
-       int err, fd = create_tmp_file(UM_KERN_PAGE_SIZE);
-
-       addr = mmap(NULL, UM_KERN_PAGE_SIZE,
-                   PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE, fd, 0);
-       printf("Checking PROT_EXEC mmap in /tmp...");
-       fflush(stdout);
-       if(addr == MAP_FAILED){
-               err = errno;
-               perror("failed");
-               if(err == EPERM)
-                       printf("/tmp must be not mounted noexec\n");
-               exit(1);
-       }
-       printf("OK\n");
-       munmap(addr, UM_KERN_PAGE_SIZE);
-
-       close(fd);
-}
+extern void check_tmpexec(void);
 
 void os_early_checks(void)
 {
index a9f6b26f9828f8f4c0a99bc6a2f8449054be8bb8..90b29ae9af46158ed52154d7e77ce1c4b100f83f 100644 (file)
@@ -35,7 +35,7 @@ void os_fill_handlinfo(struct kern_handlers h)
 
 void do_longjmp(void *b, int val)
 {
-       sigjmp_buf *buf = b;
+       jmp_buf *buf = b;
 
-       UML_SIGLONGJMP(buf, val);
+       UML_LONGJMP(buf, val);
 }
index 166fb66995df87e58793c6f99a33334324eaddce..e523719330b27cb2b0a29bd1dacbf15bc8b1ca05 100644 (file)
@@ -16,9 +16,9 @@ unsigned long __do_user_copy(void *to, const void *from, int n,
        unsigned long *faddrp = (unsigned long *) fault_addr, ret;
        int enable;
 
-       sigjmp_buf jbuf;
+       jmp_buf jbuf;
        *fault_catcher = &jbuf;
-       if(UML_SIGSETJMP(&jbuf, enable) == 0){
+       if(UML_SETJMP(&jbuf, enable) == 0){
                (*op)(to, from, n);
                ret = 0;
                *faulted_out = 0;
index e32065e2fdc80d7203a817d8708e3d3cbed845be..c47a2a7ce70e75614e425e7270b2e1364188b67d 100644 (file)
@@ -104,7 +104,7 @@ void setup_hostinfo(void)
 int setjmp_wrapper(void (*proc)(void *, void *), ...)
 {
        va_list args;
-       sigjmp_buf buf;
+       jmp_buf buf;
        int n;
 
        n = sigsetjmp(buf, 1);
index 618fd8594643b147ec6c878f696ab28a02ce0aeb..0709fc6670c287ab4b3bf2323792ebc19e4a0873 100644 (file)
@@ -57,7 +57,7 @@ static int copy_sc_from_user_skas(struct pt_regs *regs,
        return(0);
 }
 
-int copy_sc_to_user_skas(struct sigcontext *to, struct _fpstate __user *to_fp,
+int copy_sc_to_user_skas(struct sigcontext __user *to, struct _fpstate __user *to_fp,
                          struct pt_regs *regs, unsigned long sp)
 {
        struct sigcontext sc;
@@ -132,7 +132,7 @@ int copy_sc_from_user_tt(struct sigcontext *to, struct sigcontext __user *from,
        return(err);
 }
 
-int copy_sc_to_user_tt(struct sigcontext *to, struct _fpstate __user *fp,
+int copy_sc_to_user_tt(struct sigcontext __user *to, struct _fpstate __user *fp,
                       struct sigcontext *from, int fpsize, unsigned long sp)
 {
        struct _fpstate __user *to_fp;
@@ -167,7 +167,7 @@ static int copy_sc_from_user(struct pt_regs *to, void __user *from)
        return(ret);
 }
 
-static int copy_sc_to_user(struct sigcontext *to, struct _fpstate __user *fp,
+static int copy_sc_to_user(struct sigcontext __user *to, struct _fpstate __user *fp,
                           struct pt_regs *from, unsigned long sp)
 {
        return(CHOOSE_MODE(copy_sc_to_user_tt(to, fp, UPT_SC(&from->regs),
index a37f672ec964e3815c4f2de247b82d7d09dc1e30..2355dc19c46c544db5627b4e6f678903a23a5a0c 100644 (file)
@@ -27,6 +27,6 @@ stub_segv_handler(int sig)
         * the stack in its original form when we do the sigreturn here, by
         * hand.
         */
-       __asm__("mov %0,%%esp ; movl %1, %%eax ; "
-               "int $0x80" : : "a" (sc), "g" (__NR_sigreturn));
+       __asm__ __volatile__("mov %0,%%esp ; movl %1, %%eax ; "
+                            "int $0x80" : : "a" (sc), "g" (__NR_sigreturn));
 }
index a27099533198573d223f54a94134b84f8b7b7674..1c967026c957dd08e4b81406a82712b60ada8ee6 100644 (file)
@@ -33,7 +33,7 @@ stub_segv_handler(int sig)
        struct ucontext *uc;
         int pid;
 
-       __asm__("movq %%rdx, %0" : "=g" (uc) :);
+       __asm__ __volatile__("movq %%rdx, %0" : "=g" (uc) :);
        GET_FAULTINFO_FROM_SC(*((struct faultinfo *) UML_CONFIG_STUB_DATA),
                              &uc->uc_mcontext);
 
@@ -44,8 +44,8 @@ stub_segv_handler(int sig)
         * the signal frame.  So, we use the ucontext pointer, which we know
         * already, to get the signal frame pointer, and add 8 to that.
         */
-       __asm__("movq %0, %%rsp; movq %1, %%rax ; syscall": :
-               "g" ((unsigned long) container_of(uc, struct rt_sigframe, 
-                                                 uc) + 8),
-                "g" (__NR_rt_sigreturn));
+       __asm__ __volatile__("movq %0, %%rsp; movq %1, %%rax ; syscall": :
+                             "g" ((unsigned long)
+                                  container_of(uc, struct rt_sigframe, uc) + 8),
+                             "g" (__NR_rt_sigreturn));
 }
index 3c45ec22b3fea277de939d7c186b15891461d460..69db0c0721d1c4835ff02fed98ff662c0db1665c 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.17-rc1
-# Mon Apr  3 16:11:14 2006
+# Linux kernel version: 2.6.17-rc1-git11
+# Sun Apr 16 07:22:36 2006
 #
 CONFIG_X86_64=y
 CONFIG_64BIT=y
@@ -57,6 +57,7 @@ CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
 CONFIG_SLAB=y
+CONFIG_DOUBLEFAULT=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
 # CONFIG_SLOB is not set
@@ -121,6 +122,7 @@ CONFIG_PREEMPT_VOLUNTARY=y
 CONFIG_PREEMPT_BKL=y
 CONFIG_NUMA=y
 CONFIG_K8_NUMA=y
+CONFIG_NODES_SHIFT=6
 CONFIG_X86_64_ACPI_NUMA=y
 CONFIG_NUMA_EMU=y
 CONFIG_ARCH_DISCONTIGMEM_ENABLE=y
@@ -544,7 +546,6 @@ CONFIG_SCSI_SATA_INTEL_COMBINED=y
 # CONFIG_SCSI_INIA100 is not set
 # CONFIG_SCSI_SYM53C8XX_2 is not set
 # CONFIG_SCSI_IPR is not set
-# CONFIG_SCSI_QLOGIC_FC is not set
 # CONFIG_SCSI_QLOGIC_1280 is not set
 # CONFIG_SCSI_QLA_FC is not set
 # CONFIG_SCSI_LPFC is not set
@@ -1045,9 +1046,7 @@ CONFIG_USB_HIDINPUT=y
 # CONFIG_USB_ACECAD is not set
 # CONFIG_USB_KBTAB is not set
 # CONFIG_USB_POWERMATE is not set
-# CONFIG_USB_MTOUCH is not set
-# CONFIG_USB_ITMTOUCH is not set
-# CONFIG_USB_EGALAX is not set
+# CONFIG_USB_TOUCHSCREEN is not set
 # CONFIG_USB_YEALINK is not set
 # CONFIG_USB_XPAD is not set
 # CONFIG_USB_ATI_REMOTE is not set
@@ -1117,6 +1116,14 @@ CONFIG_USB_MON=y
 #
 # CONFIG_NEW_LEDS is not set
 
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
 #
 # InfiniBand support
 #
index 5a9802676689ec79d618b3733eaa7aec26363311..57fc37e0fb9c16d044156749c31157ef85a6302b 100644 (file)
@@ -694,4 +694,5 @@ ia32_sys_call_table:
        .quad compat_sys_get_robust_list
        .quad sys_splice
        .quad sys_sync_file_range
+       .quad sys_tee
 ia32_syscall_end:              
index accbff3fec491826071ad572c19d0207413a1bca..1eaa5dae6174ff57b514a56828f07e6f8ed0a149 100644 (file)
@@ -53,7 +53,7 @@ DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk);
 /*
  * returns non-zero if opcode modifies the interrupt flag.
  */
-static inline int is_IF_modifier(kprobe_opcode_t *insn)
+static __always_inline int is_IF_modifier(kprobe_opcode_t *insn)
 {
        switch (*insn) {
        case 0xfa:              /* cli */
@@ -84,7 +84,7 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p)
  * If it does, return the address of the 32-bit displacement word.
  * If not, return null.
  */
-static inline s32 *is_riprel(u8 *insn)
+static s32 __kprobes *is_riprel(u8 *insn)
 {
 #define W(row,b0,b1,b2,b3,b4,b5,b6,b7,b8,b9,ba,bb,bc,bd,be,bf)               \
        (((b0##UL << 0x0)|(b1##UL << 0x1)|(b2##UL << 0x2)|(b3##UL << 0x3) |   \
@@ -229,7 +229,7 @@ void __kprobes arch_remove_kprobe(struct kprobe *p)
        mutex_unlock(&kprobe_mutex);
 }
 
-static inline void save_previous_kprobe(struct kprobe_ctlblk *kcb)
+static void __kprobes save_previous_kprobe(struct kprobe_ctlblk *kcb)
 {
        kcb->prev_kprobe.kp = kprobe_running();
        kcb->prev_kprobe.status = kcb->kprobe_status;
@@ -237,7 +237,7 @@ static inline void save_previous_kprobe(struct kprobe_ctlblk *kcb)
        kcb->prev_kprobe.saved_rflags = kcb->kprobe_saved_rflags;
 }
 
-static inline void restore_previous_kprobe(struct kprobe_ctlblk *kcb)
+static void __kprobes restore_previous_kprobe(struct kprobe_ctlblk *kcb)
 {
        __get_cpu_var(current_kprobe) = kcb->prev_kprobe.kp;
        kcb->kprobe_status = kcb->prev_kprobe.status;
@@ -245,7 +245,7 @@ static inline void restore_previous_kprobe(struct kprobe_ctlblk *kcb)
        kcb->kprobe_saved_rflags = kcb->prev_kprobe.saved_rflags;
 }
 
-static inline void set_current_kprobe(struct kprobe *p, struct pt_regs *regs,
+static void __kprobes set_current_kprobe(struct kprobe *p, struct pt_regs *regs,
                                struct kprobe_ctlblk *kcb)
 {
        __get_cpu_var(current_kprobe) = p;
index 1c44b53cb15bb48391cf4300dbb93fd5fac34835..fb903e65e079a26034f76a30ef6f54b40613453d 100644 (file)
@@ -575,8 +575,10 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
        prev->userrsp = read_pda(oldrsp); 
        write_pda(oldrsp, next->userrsp); 
        write_pda(pcurrent, next_p); 
+
        /* This must be here to ensure both math_state_restore() and
-          kernel_fpu_begin() work consistently. */
+          kernel_fpu_begin() work consistently. 
+          And the AMD workaround requires it to be after DS reload. */
        unlazy_fpu(prev_p);
        write_pda(kernelstack,
                  task_stack_page(next_p) + THREAD_SIZE - PDA_STACKOFFSET);
index c50b06765a80ddc16d0d17a59055a8cd42044cea..759070c827511bb482c3b770ff0f35407746936c 100644 (file)
@@ -930,6 +930,10 @@ static int __init init_amd(struct cpuinfo_x86 *c)
        if (c->x86 == 15 && ((level >= 0x0f48 && level < 0x0f50) || level >= 0x0f58))
                set_bit(X86_FEATURE_REP_GOOD, &c->x86_capability);
 
+       /* Enable workaround for FXSAVE leak */
+       if (c->x86 >= 6)
+               set_bit(X86_FEATURE_FXSAVE_LEAK, &c->x86_capability);
+
        r = get_model_name(c);
        if (!r) { 
                switch (c->x86) { 
index 6bda322d3cafe30f64c03ed426f03c80dc42890b..2700b1375c1fe27c864d60ec41e15258d7c90cd6 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/moduleparam.h>
 #include <linux/nmi.h>
 #include <linux/kprobes.h>
+#include <linux/kexec.h>
 
 #include <asm/system.h>
 #include <asm/uaccess.h>
@@ -433,6 +434,8 @@ void __kprobes __die(const char * str, struct pt_regs * regs, long err)
        printk(KERN_ALERT "RIP ");
        printk_address(regs->rip); 
        printk(" RSP <%016lx>\n", regs->rsp); 
+       if (kexec_should_crash(current))
+               crash_kexec(regs);
 }
 
 void die(const char * str, struct pt_regs * regs, long err)
@@ -455,6 +458,8 @@ void __kprobes die_nmi(char *str, struct pt_regs *regs)
         */
        printk(str, safe_smp_processor_id());
        show_registers(regs);
+       if (kexec_should_crash(current))
+               crash_kexec(regs);
        if (panic_on_timeout || panic_on_oops)
                panic("nmi watchdog");
        printk("console shuts up ...\n");
index 296708ceceb2d62a8bacd8a954efeb1108d5547e..e25a5d79ab2715b2f3a07ce3331e46cd45ab86f1 100644 (file)
@@ -1844,9 +1844,10 @@ static void __exit as_exit(void)
        DECLARE_COMPLETION(all_gone);
        elv_unregister(&iosched_as);
        ioc_gone = &all_gone;
-       barrier();
+       /* ioc_gone's update must be visible before reading ioc_count */
+       smp_wmb();
        if (atomic_read(&ioc_count))
-               complete(ioc_gone);
+               wait_for_completion(ioc_gone);
        synchronize_rcu();
        kmem_cache_destroy(arq_pool);
 }
index 67d446de0227a3ac71aaa1563728717a21af5eb9..2540dfaa3e385def27a44284bf3e552f986ee15d 100644 (file)
@@ -1472,19 +1472,37 @@ out:
        return cfqq;
 }
 
+static void
+cfq_drop_dead_cic(struct io_context *ioc, struct cfq_io_context *cic)
+{
+       read_lock(&cfq_exit_lock);
+       rb_erase(&cic->rb_node, &ioc->cic_root);
+       read_unlock(&cfq_exit_lock);
+       kmem_cache_free(cfq_ioc_pool, cic);
+       atomic_dec(&ioc_count);
+}
+
 static struct cfq_io_context *
 cfq_cic_rb_lookup(struct cfq_data *cfqd, struct io_context *ioc)
 {
-       struct rb_node *n = ioc->cic_root.rb_node;
+       struct rb_node *n;
        struct cfq_io_context *cic;
-       void *key = cfqd;
+       void *k, *key = cfqd;
 
+restart:
+       n = ioc->cic_root.rb_node;
        while (n) {
                cic = rb_entry(n, struct cfq_io_context, rb_node);
+               /* ->key must be copied to avoid race with cfq_exit_queue() */
+               k = cic->key;
+               if (unlikely(!k)) {
+                       cfq_drop_dead_cic(ioc, cic);
+                       goto restart;
+               }
 
-               if (key < cic->key)
+               if (key < k)
                        n = n->rb_left;
-               else if (key > cic->key)
+               else if (key > k)
                        n = n->rb_right;
                else
                        return cic;
@@ -1497,29 +1515,37 @@ static inline void
 cfq_cic_link(struct cfq_data *cfqd, struct io_context *ioc,
             struct cfq_io_context *cic)
 {
-       struct rb_node **p = &ioc->cic_root.rb_node;
-       struct rb_node *parent = NULL;
+       struct rb_node **p;
+       struct rb_node *parent;
        struct cfq_io_context *__cic;
-
-       read_lock(&cfq_exit_lock);
+       void *k;
 
        cic->ioc = ioc;
        cic->key = cfqd;
 
        ioc->set_ioprio = cfq_ioc_set_ioprio;
-
+restart:
+       parent = NULL;
+       p = &ioc->cic_root.rb_node;
        while (*p) {
                parent = *p;
                __cic = rb_entry(parent, struct cfq_io_context, rb_node);
+               /* ->key must be copied to avoid race with cfq_exit_queue() */
+               k = __cic->key;
+               if (unlikely(!k)) {
+                       cfq_drop_dead_cic(ioc, cic);
+                       goto restart;
+               }
 
-               if (cic->key < __cic->key)
+               if (cic->key < k)
                        p = &(*p)->rb_left;
-               else if (cic->key > __cic->key)
+               else if (cic->key > k)
                        p = &(*p)->rb_right;
                else
                        BUG();
        }
 
+       read_lock(&cfq_exit_lock);
        rb_link_node(&cic->rb_node, parent, p);
        rb_insert_color(&cic->rb_node, &ioc->cic_root);
        list_add(&cic->queue_list, &cfqd->cic_list);
@@ -2439,9 +2465,10 @@ static void __exit cfq_exit(void)
        DECLARE_COMPLETION(all_gone);
        elv_unregister(&iosched_cfq);
        ioc_gone = &all_gone;
-       barrier();
+       /* ioc_gone's update must be visible before reading ioc_count */
+       smp_wmb();
        if (atomic_read(&ioc_count))
-               complete(ioc_gone);
+               wait_for_completion(ioc_gone);
        synchronize_rcu();
        cfq_slab_kill();
 }
index 0d6be03d929ea348423f8abf4a222f7c699d4e3b..29825792cbd5305cfbea9c1f6063710ec4b46be8 100644 (file)
@@ -895,10 +895,8 @@ ssize_t elv_iosched_show(request_queue_t *q, char *name)
 EXPORT_SYMBOL(elv_dispatch_sort);
 EXPORT_SYMBOL(elv_add_request);
 EXPORT_SYMBOL(__elv_add_request);
-EXPORT_SYMBOL(elv_requeue_request);
 EXPORT_SYMBOL(elv_next_request);
 EXPORT_SYMBOL(elv_dequeue_request);
 EXPORT_SYMBOL(elv_queue_empty);
-EXPORT_SYMBOL(elv_completed_request);
 EXPORT_SYMBOL(elevator_exit);
 EXPORT_SYMBOL(elevator_init);
index e112d1a5dab6b8c2dcae45e2a6b18bbfc4529760..1755c053fd68ce648ba90bcbc3c7132ac23d8ad1 100644 (file)
@@ -1554,7 +1554,7 @@ void blk_plug_device(request_queue_t *q)
         * don't plug a stopped queue, it must be paired with blk_start_queue()
         * which will restart the queueing
         */
-       if (test_bit(QUEUE_FLAG_STOPPED, &q->queue_flags))
+       if (blk_queue_stopped(q))
                return;
 
        if (!test_and_set_bit(QUEUE_FLAG_PLUGGED, &q->queue_flags)) {
@@ -1587,7 +1587,7 @@ EXPORT_SYMBOL(blk_remove_plug);
  */
 void __generic_unplug_device(request_queue_t *q)
 {
-       if (unlikely(test_bit(QUEUE_FLAG_STOPPED, &q->queue_flags)))
+       if (unlikely(blk_queue_stopped(q)))
                return;
 
        if (!blk_remove_plug(q))
index 1b0fd31c57c3dcd269dd60b528ccb2f3d68fa6a5..1319d8f20640505b69ebc6a37c3f9b435910ee0e 100644 (file)
@@ -1180,6 +1180,53 @@ static int revalidate_allvol(ctlr_info_t *host)
         return 0;
 }
 
+static inline void complete_buffers(struct bio *bio, int status)
+{
+       while (bio) {
+               struct bio *xbh = bio->bi_next;
+               int nr_sectors = bio_sectors(bio);
+
+               bio->bi_next = NULL;
+               blk_finished_io(len);
+               bio_endio(bio, nr_sectors << 9, status ? 0 : -EIO);
+               bio = xbh;
+       }
+
+}
+
+static void cciss_softirq_done(struct request *rq)
+{
+       CommandList_struct *cmd = rq->completion_data;
+       ctlr_info_t *h = hba[cmd->ctlr];
+       unsigned long flags;
+       u64bit temp64;
+       int i, ddir;
+
+       if (cmd->Request.Type.Direction == XFER_READ)
+               ddir = PCI_DMA_FROMDEVICE;
+       else
+               ddir = PCI_DMA_TODEVICE;
+
+       /* command did not need to be retried */
+       /* unmap the DMA mapping for all the scatter gather elements */
+       for(i=0; i<cmd->Header.SGList; i++) {
+               temp64.val32.lower = cmd->SG[i].Addr.lower;
+               temp64.val32.upper = cmd->SG[i].Addr.upper;
+               pci_unmap_page(h->pdev, temp64.val, cmd->SG[i].Len, ddir);
+       }
+
+       complete_buffers(rq->bio, rq->errors);
+
+#ifdef CCISS_DEBUG
+       printk("Done with %p\n", rq);
+#endif /* CCISS_DEBUG */
+
+       spin_lock_irqsave(&h->lock, flags);
+       end_that_request_last(rq, rq->errors);
+       cmd_free(h, cmd,1);
+       spin_unlock_irqrestore(&h->lock, flags);
+}
+
 /* This function will check the usage_count of the drive to be updated/added.
  * If the usage_count is zero then the drive information will be updated and
  * the disk will be re-registered with the kernel.  If not then it will be
@@ -1248,6 +1295,8 @@ static void cciss_update_drive_info(int ctlr, int drv_index)
 
                blk_queue_max_sectors(disk->queue, 512);
 
+               blk_queue_softirq_done(disk->queue, cciss_softirq_done);
+
                disk->queue->queuedata = hba[ctlr];
 
                blk_queue_hardsect_size(disk->queue,
@@ -2147,20 +2196,6 @@ static void start_io( ctlr_info_t *h)
                addQ (&(h->cmpQ), c); 
        }
 }
-
-static inline void complete_buffers(struct bio *bio, int status)
-{
-       while (bio) {
-               struct bio *xbh = bio->bi_next; 
-               int nr_sectors = bio_sectors(bio);
-
-               bio->bi_next = NULL; 
-               blk_finished_io(len);
-               bio_endio(bio, nr_sectors << 9, status ? 0 : -EIO);
-               bio = xbh;
-       }
-
-} 
 /* Assumes that CCISS_LOCK(h->ctlr) is held. */
 /* Zeros out the error record and then resends the command back */
 /* to the controller */
@@ -2178,39 +2213,6 @@ static inline void resend_cciss_cmd( ctlr_info_t *h, CommandList_struct *c)
        start_io(h);
 }
 
-static void cciss_softirq_done(struct request *rq)
-{
-       CommandList_struct *cmd = rq->completion_data;
-       ctlr_info_t *h = hba[cmd->ctlr];
-       unsigned long flags;
-       u64bit temp64;
-       int i, ddir;
-
-       if (cmd->Request.Type.Direction == XFER_READ)
-               ddir = PCI_DMA_FROMDEVICE;
-       else
-               ddir = PCI_DMA_TODEVICE;
-
-       /* command did not need to be retried */
-       /* unmap the DMA mapping for all the scatter gather elements */
-       for(i=0; i<cmd->Header.SGList; i++) {
-               temp64.val32.lower = cmd->SG[i].Addr.lower;
-               temp64.val32.upper = cmd->SG[i].Addr.upper;
-               pci_unmap_page(h->pdev, temp64.val, cmd->SG[i].Len, ddir);
-       }
-
-       complete_buffers(rq->bio, rq->errors);
-
-#ifdef CCISS_DEBUG
-       printk("Done with %p\n", rq);
-#endif /* CCISS_DEBUG */ 
-
-       spin_lock_irqsave(&h->lock, flags);
-       end_that_request_last(rq, rq->errors);
-       cmd_free(h, cmd,1);
-       spin_unlock_irqrestore(&h->lock, flags);
-}
-
 /* checks the status of the job and calls complete buffers to mark all 
  * buffers for the completed job. Note that this function does not need
  * to hold the hba/queue lock.
index 5d72f50de1ac97c6e377fb6c5e0d0d4192016983..46d66037b917c5851222b56af77f4b158ce793aa 100644 (file)
@@ -241,9 +241,10 @@ static int __init cs5535_gpio_init(void)
 static void __exit cs5535_gpio_cleanup(void)
 {
        dev_t dev_id = MKDEV(major, 0);
+
+       cdev_del(&cs5535_gpio_cdev);
        unregister_chrdev_region(dev_id, CS5535_GPIO_COUNT);
-       if (gpio_base != 0)
-               release_region(gpio_base, CS5535_GPIO_SIZE);
+       release_region(gpio_base, CS5535_GPIO_SIZE);
 }
 
 module_init(cs5535_gpio_init);
index edc72a6348a72301ceb2cf4f1b33816a8ee0e91b..e1aadae006232bc8762ae69e4a11bfac7e384ddc 100644 (file)
@@ -815,8 +815,6 @@ extern int drm_mem_info(char *buf, char **start, off_t offset,
 extern void *drm_realloc(void *oldpt, size_t oldsize, size_t size, int area);
 extern void *drm_ioremap(unsigned long offset, unsigned long size,
                         drm_device_t * dev);
-extern void *drm_ioremap_nocache(unsigned long offset, unsigned long size,
-                                drm_device_t * dev);
 extern void drm_ioremapfree(void *pt, unsigned long size, drm_device_t * dev);
 
 extern DRM_AGP_MEM *drm_alloc_agp(drm_device_t * dev, int pages, u32 type);
@@ -1022,11 +1020,13 @@ static __inline__ void drm_core_ioremap(struct drm_map *map,
        map->handle = drm_ioremap(map->offset, map->size, dev);
 }
 
+#if 0
 static __inline__ void drm_core_ioremap_nocache(struct drm_map *map,
                                                struct drm_device *dev)
 {
        map->handle = drm_ioremap_nocache(map->offset, map->size, dev);
 }
+#endif  /*  0  */
 
 static __inline__ void drm_core_ioremapfree(struct drm_map *map,
                                            struct drm_device *dev)
index dc6bbe8a18dc762e158ed8084071ddbaf4eb6ce6..3c0b882a8e72843a2074b2b495ffa2f2ebf266ab 100644 (file)
@@ -75,8 +75,8 @@ static drm_ioctl_desc_t drm_ioctls[] = {
        [DRM_IOCTL_NR(DRM_IOCTL_SET_SAREA_CTX)] = {drm_setsareactx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
        [DRM_IOCTL_NR(DRM_IOCTL_GET_SAREA_CTX)] = {drm_getsareactx, DRM_AUTH},
 
-       [DRM_IOCTL_NR(DRM_IOCTL_ADD_CTX)] = {drm_addctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
-       [DRM_IOCTL_NR(DRM_IOCTL_RM_CTX)] = {drm_rmctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
+       [DRM_IOCTL_NR(DRM_IOCTL_ADD_CTX)] = {drm_addctx, DRM_AUTH|DRM_ROOT_ONLY},
+       [DRM_IOCTL_NR(DRM_IOCTL_RM_CTX)] = {drm_rmctx, DRM_AUTH|DRM_ROOT_ONLY},
        [DRM_IOCTL_NR(DRM_IOCTL_MOD_CTX)] = {drm_modctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
        [DRM_IOCTL_NR(DRM_IOCTL_GET_CTX)] = {drm_getctx, DRM_AUTH},
        [DRM_IOCTL_NR(DRM_IOCTL_SWITCH_CTX)] = {drm_switchctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
index dddf8de661433cc21758fc5f1b98d25c775f483c..7e3318e1d1c655c2d93682ffbf910cc5aa78d8f0 100644 (file)
@@ -80,6 +80,71 @@ void *drm_realloc(void *oldpt, size_t oldsize, size_t size, int area)
 }
 
 #if __OS_HAS_AGP
+/*
+ * Find the drm_map that covers the range [offset, offset+size).
+ */
+static drm_map_t *drm_lookup_map(unsigned long offset,
+                                unsigned long size, drm_device_t * dev)
+{
+       struct list_head *list;
+       drm_map_list_t *r_list;
+       drm_map_t *map;
+
+       list_for_each(list, &dev->maplist->head) {
+               r_list = (drm_map_list_t *) list;
+               map = r_list->map;
+               if (!map)
+                       continue;
+               if (map->offset <= offset
+                   && (offset + size) <= (map->offset + map->size))
+                       return map;
+       }
+       return NULL;
+}
+
+static void *agp_remap(unsigned long offset, unsigned long size,
+                      drm_device_t * dev)
+{
+       unsigned long *phys_addr_map, i, num_pages =
+           PAGE_ALIGN(size) / PAGE_SIZE;
+       struct drm_agp_mem *agpmem;
+       struct page **page_map;
+       void *addr;
+
+       size = PAGE_ALIGN(size);
+
+#ifdef __alpha__
+       offset -= dev->hose->mem_space->start;
+#endif
+
+       for (agpmem = dev->agp->memory; agpmem; agpmem = agpmem->next)
+               if (agpmem->bound <= offset
+                   && (agpmem->bound + (agpmem->pages << PAGE_SHIFT)) >=
+                   (offset + size))
+                       break;
+       if (!agpmem)
+               return NULL;
+
+       /*
+        * OK, we're mapping AGP space on a chipset/platform on which memory accesses by
+        * the CPU do not get remapped by the GART.  We fix this by using the kernel's
+        * page-table instead (that's probably faster anyhow...).
+        */
+       /* note: use vmalloc() because num_pages could be large... */
+       page_map = vmalloc(num_pages * sizeof(struct page *));
+       if (!page_map)
+               return NULL;
+
+       phys_addr_map =
+           agpmem->memory->memory + (offset - agpmem->bound) / PAGE_SIZE;
+       for (i = 0; i < num_pages; ++i)
+               page_map[i] = pfn_to_page(phys_addr_map[i] >> PAGE_SHIFT);
+       addr = vmap(page_map, num_pages, VM_IOREMAP, PAGE_AGP);
+       vfree(page_map);
+
+       return addr;
+}
+
 /** Wrapper around agp_allocate_memory() */
 DRM_AGP_MEM *drm_alloc_agp(drm_device_t * dev, int pages, u32 type)
 {
@@ -103,5 +168,74 @@ int drm_unbind_agp(DRM_AGP_MEM * handle)
 {
        return drm_agp_unbind_memory(handle);
 }
+
+#else  /*  __OS_HAS_AGP  */
+
+static inline drm_map_t *drm_lookup_map(unsigned long offset,
+                                       unsigned long size, drm_device_t * dev)
+{
+       return NULL;
+}
+
+static inline void *agp_remap(unsigned long offset, unsigned long size,
+                             drm_device_t * dev)
+{
+       return NULL;
+}
+
 #endif                         /* agp */
+
+void *drm_ioremap(unsigned long offset, unsigned long size,
+                               drm_device_t * dev)
+{
+       if (drm_core_has_AGP(dev) && dev->agp && dev->agp->cant_use_aperture) {
+               drm_map_t *map = drm_lookup_map(offset, size, dev);
+
+               if (map && map->type == _DRM_AGP)
+                       return agp_remap(offset, size, dev);
+       }
+       return ioremap(offset, size);
+}
+EXPORT_SYMBOL(drm_ioremap);
+
+#if 0
+void *drm_ioremap_nocache(unsigned long offset,
+                                       unsigned long size, drm_device_t * dev)
+{
+       if (drm_core_has_AGP(dev) && dev->agp && dev->agp->cant_use_aperture) {
+               drm_map_t *map = drm_lookup_map(offset, size, dev);
+
+               if (map && map->type == _DRM_AGP)
+                       return agp_remap(offset, size, dev);
+       }
+       return ioremap_nocache(offset, size);
+}
+#endif  /*  0  */
+
+void drm_ioremapfree(void *pt, unsigned long size,
+                                  drm_device_t * dev)
+{
+       /*
+        * This is a bit ugly.  It would be much cleaner if the DRM API would use separate
+        * routines for handling mappings in the AGP space.  Hopefully this can be done in
+        * a future revision of the interface...
+        */
+       if (drm_core_has_AGP(dev) && dev->agp && dev->agp->cant_use_aperture
+           && ((unsigned long)pt >= VMALLOC_START
+               && (unsigned long)pt < VMALLOC_END)) {
+               unsigned long offset;
+               drm_map_t *map;
+
+               offset = drm_follow_page(pt) | ((unsigned long)pt & ~PAGE_MASK);
+               map = drm_lookup_map(offset, size, dev);
+               if (map && map->type == _DRM_AGP) {
+                       vunmap(pt);
+                       return;
+               }
+       }
+
+       iounmap(pt);
+}
+EXPORT_SYMBOL(drm_ioremapfree);
+
 #endif                         /* debug_memory */
index 3732a61c3762840553fd3e4470d71f050f9aaf26..714d9aedcff5dd38200eaf18dfcf029f1a36722c 100644 (file)
 # endif
 #endif
 
-/*
- * Find the drm_map that covers the range [offset, offset+size).
- */
-static inline drm_map_t *drm_lookup_map(unsigned long offset,
-                                       unsigned long size, drm_device_t * dev)
-{
-       struct list_head *list;
-       drm_map_list_t *r_list;
-       drm_map_t *map;
-
-       list_for_each(list, &dev->maplist->head) {
-               r_list = (drm_map_list_t *) list;
-               map = r_list->map;
-               if (!map)
-                       continue;
-               if (map->offset <= offset
-                   && (offset + size) <= (map->offset + map->size))
-                       return map;
-       }
-       return NULL;
-}
-
-static inline void *agp_remap(unsigned long offset, unsigned long size,
-                             drm_device_t * dev)
-{
-       unsigned long *phys_addr_map, i, num_pages =
-           PAGE_ALIGN(size) / PAGE_SIZE;
-       struct drm_agp_mem *agpmem;
-       struct page **page_map;
-       void *addr;
-
-       size = PAGE_ALIGN(size);
-
-#ifdef __alpha__
-       offset -= dev->hose->mem_space->start;
-#endif
-
-       for (agpmem = dev->agp->memory; agpmem; agpmem = agpmem->next)
-               if (agpmem->bound <= offset
-                   && (agpmem->bound + (agpmem->pages << PAGE_SHIFT)) >=
-                   (offset + size))
-                       break;
-       if (!agpmem)
-               return NULL;
-
-       /*
-        * OK, we're mapping AGP space on a chipset/platform on which memory accesses by
-        * the CPU do not get remapped by the GART.  We fix this by using the kernel's
-        * page-table instead (that's probably faster anyhow...).
-        */
-       /* note: use vmalloc() because num_pages could be large... */
-       page_map = vmalloc(num_pages * sizeof(struct page *));
-       if (!page_map)
-               return NULL;
-
-       phys_addr_map =
-           agpmem->memory->memory + (offset - agpmem->bound) / PAGE_SIZE;
-       for (i = 0; i < num_pages; ++i)
-               page_map[i] = pfn_to_page(phys_addr_map[i] >> PAGE_SHIFT);
-       addr = vmap(page_map, num_pages, VM_IOREMAP, PAGE_AGP);
-       vfree(page_map);
-
-       return addr;
-}
-
 static inline unsigned long drm_follow_page(void *vaddr)
 {
        pgd_t *pgd = pgd_offset_k((unsigned long)vaddr);
@@ -133,18 +68,6 @@ static inline unsigned long drm_follow_page(void *vaddr)
 
 #else                          /* __OS_HAS_AGP */
 
-static inline drm_map_t *drm_lookup_map(unsigned long offset,
-                                       unsigned long size, drm_device_t * dev)
-{
-       return NULL;
-}
-
-static inline void *agp_remap(unsigned long offset, unsigned long size,
-                             drm_device_t * dev)
-{
-       return NULL;
-}
-
 static inline unsigned long drm_follow_page(void *vaddr)
 {
        return 0;
@@ -152,51 +75,8 @@ static inline unsigned long drm_follow_page(void *vaddr)
 
 #endif
 
-static inline void *drm_ioremap(unsigned long offset, unsigned long size,
-                               drm_device_t * dev)
-{
-       if (drm_core_has_AGP(dev) && dev->agp && dev->agp->cant_use_aperture) {
-               drm_map_t *map = drm_lookup_map(offset, size, dev);
-
-               if (map && map->type == _DRM_AGP)
-                       return agp_remap(offset, size, dev);
-       }
-       return ioremap(offset, size);
-}
-
-static inline void *drm_ioremap_nocache(unsigned long offset,
-                                       unsigned long size, drm_device_t * dev)
-{
-       if (drm_core_has_AGP(dev) && dev->agp && dev->agp->cant_use_aperture) {
-               drm_map_t *map = drm_lookup_map(offset, size, dev);
-
-               if (map && map->type == _DRM_AGP)
-                       return agp_remap(offset, size, dev);
-       }
-       return ioremap_nocache(offset, size);
-}
-
-static inline void drm_ioremapfree(void *pt, unsigned long size,
-                                  drm_device_t * dev)
-{
-       /*
-        * This is a bit ugly.  It would be much cleaner if the DRM API would use separate
-        * routines for handling mappings in the AGP space.  Hopefully this can be done in
-        * a future revision of the interface...
-        */
-       if (drm_core_has_AGP(dev) && dev->agp && dev->agp->cant_use_aperture
-           && ((unsigned long)pt >= VMALLOC_START
-               && (unsigned long)pt < VMALLOC_END)) {
-               unsigned long offset;
-               drm_map_t *map;
-
-               offset = drm_follow_page(pt) | ((unsigned long)pt & ~PAGE_MASK);
-               map = drm_lookup_map(offset, size, dev);
-               if (map && map->type == _DRM_AGP) {
-                       vunmap(pt);
-                       return;
-               }
-       }
+void *drm_ioremap(unsigned long offset, unsigned long size,
+                               drm_device_t * dev);
 
-       iounmap(pt);
-}
+void drm_ioremapfree(void *pt, unsigned long size,
+                                  drm_device_t * dev);
index 7868341817da2f538f55764eb14055d096ff4df8..6543b9a14c42e677038bd001309e35143c5a10a1 100644 (file)
@@ -229,6 +229,7 @@ void *drm_ioremap (unsigned long offset, unsigned long size,
        return pt;
 }
 
+#if 0
 void *drm_ioremap_nocache (unsigned long offset, unsigned long size,
                            drm_device_t * dev) {
        void *pt;
@@ -251,6 +252,7 @@ void *drm_ioremap_nocache (unsigned long offset, unsigned long size,
        spin_unlock(&drm_mem_lock);
        return pt;
 }
+#endif  /*  0  */
 
 void drm_ioremapfree (void *pt, unsigned long size, drm_device_t * dev) {
        int alloc_count;
index b28ca9cea8a2a73c4f2c463fb762dc5fd94bae34..86a0f1c2209111075eb096d971271e08082f9e76 100644 (file)
@@ -37,6 +37,7 @@
  */
 
 #include <linux/pci.h>
+#include <linux/dma-mapping.h>
 #include "drmP.h"
 
 /**********************************************************************/
index 6152415644e9b4a327549841df072edd0c45f8e5..c33d068cde19f459b712147f0261829a59708804 100644 (file)
@@ -196,9 +196,9 @@ via_driver_irq_wait(drm_device_t * dev, unsigned int irq, int force_sequence,
 {
        drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
        unsigned int cur_irq_sequence;
-       drm_via_irq_t *cur_irq = dev_priv->via_irqs;
+       drm_via_irq_t *cur_irq;
        int ret = 0;
-       maskarray_t *masks = dev_priv->irq_masks;
+       maskarray_t *masks;
        int real_irq;
 
        DRM_DEBUG("%s\n", __FUNCTION__);
@@ -221,8 +221,9 @@ via_driver_irq_wait(drm_device_t * dev, unsigned int irq, int force_sequence,
                          __FUNCTION__, irq);
                return DRM_ERR(EINVAL);
        }
-       
-       cur_irq += real_irq;
+
+       masks = dev_priv->irq_masks;
+       cur_irq = dev_priv->via_irqs + real_irq;
 
        if (masks[real_irq][2] && !force_sequence) {
                DRM_WAIT_ON(ret, cur_irq->irq_queue, 3 * DRM_HZ,
@@ -247,11 +248,12 @@ void via_driver_irq_preinstall(drm_device_t * dev)
 {
        drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
        u32 status;
-       drm_via_irq_t *cur_irq = dev_priv->via_irqs;
+       drm_via_irq_t *cur_irq;
        int i;
 
        DRM_DEBUG("driver_irq_preinstall: dev_priv: %p\n", dev_priv);
        if (dev_priv) {
+               cur_irq = dev_priv->via_irqs;
 
                dev_priv->irq_enable_mask = VIA_IRQ_VBLANK_ENABLE;
                dev_priv->irq_pending_mask = VIA_IRQ_VBLANK_PENDING;
index 58dcdee1cd719ab3d165907fb76f53c6e55c5db6..0030cd8e2e956cb436ae781c854ba41df23058a9 100644 (file)
@@ -165,7 +165,7 @@ static int bt_start_transaction(struct si_sm_data *bt,
 {
        unsigned int i;
 
-       if ((size < 2) || (size > IPMI_MAX_MSG_LENGTH))
+       if ((size < 2) || (size > (IPMI_MAX_MSG_LENGTH - 2)))
               return -1;
 
        if ((bt->state != BT_STATE_IDLE) && (bt->state != BT_STATE_HOSED))
index a86c0f29953e7c1e2fa5921af10bb7ba88ebe062..b36eef0e9d199ff2751ddba5b77d812bacf489cb 100644 (file)
@@ -2198,11 +2198,11 @@ static inline void wait_for_timer_and_thread(struct smi_info *smi_info)
        }
 }
 
-static struct ipmi_default_vals
+static __devinitdata struct ipmi_default_vals
 {
        int type;
        int port;
-} __devinit ipmi_defaults[] =
+} ipmi_defaults[] =
 {
        { .type = SI_KCS, .port = 0xca2 },
        { .type = SI_SMIC, .port = 0xca9 },
index f8dd8527c6aa9d8e30d17a26b64ed5b5dcccb2f7..a90f5d97df35dc8c262145efe0187085a6bd2009 100644 (file)
@@ -1341,6 +1341,9 @@ static int __devinit sonypi_probe(struct platform_device *dev)
        else if ((pcidev = pci_get_device(PCI_VENDOR_ID_INTEL,
                                          PCI_DEVICE_ID_INTEL_ICH6_1, NULL)))
                sonypi_device.model = SONYPI_DEVICE_MODEL_TYPE3;
+       else if ((pcidev = pci_get_device(PCI_VENDOR_ID_INTEL,
+                                         PCI_DEVICE_ID_INTEL_ICH7_1, NULL)))
+               sonypi_device.model = SONYPI_DEVICE_MODEL_TYPE3;
        else
                sonypi_device.model = SONYPI_DEVICE_MODEL_TYPE2;
 
index 841f0bd3eaaf8426194c8cd838c1a0dfb67f37cc..f07637a8f88fd038bac53f44c7181ea901c2ec51 100644 (file)
@@ -2723,7 +2723,11 @@ static void __do_SAK(void *arg)
                }
                task_lock(p);
                if (p->files) {
-                       rcu_read_lock();
+                       /*
+                        * We don't take a ref to the file, so we must
+                        * hold ->file_lock instead.
+                        */
+                       spin_lock(&p->files->file_lock);
                        fdt = files_fdtable(p->files);
                        for (i=0; i < fdt->max_fds; i++) {
                                filp = fcheck_files(p->files, i);
@@ -2738,7 +2742,7 @@ static void __do_SAK(void *arg)
                                        break;
                                }
                        }
-                       rcu_read_unlock();
+                       spin_unlock(&p->files->file_lock);
                }
                task_unlock(p);
        } while_each_thread(g, p);
index 60c9be99c6d91244f311dccd2837f49e00b14e87..2cc71b66231ec07e81d7221578f040c6fdcaeed0 100644 (file)
@@ -99,7 +99,7 @@ config CPU_FREQ_GOV_USERSPACE
          Enable this cpufreq governor when you either want to set the
          CPU frequency manually or when an userspace program shall
          be able to set the CPU dynamically, like on LART 
-         <http://www.lart.tudelft.nl/>
+         <http://www.lartmaker.nl/>.
 
          For details, take a look at <file:Documentation/cpu-freq/>.
 
index 9b6ae7dc8b8a3a736666568fad41c3b8b567210d..9759d05b1972742b839b4188d0f8fcaf039859a9 100644 (file)
@@ -319,7 +319,6 @@ out:
        }
        return -EINVAL;
 }
-EXPORT_SYMBOL_GPL(cpufreq_parse_governor);
 
 
 /* drivers/base/cpu.c */
@@ -346,6 +345,8 @@ show_one(scaling_min_freq, min);
 show_one(scaling_max_freq, max);
 show_one(scaling_cur_freq, cur);
 
+static int __cpufreq_set_policy(struct cpufreq_policy *data, struct cpufreq_policy *policy);
+
 /**
  * cpufreq_per_cpu_attr_write() / store_##file_name() - sysfs write access
  */
@@ -364,7 +365,10 @@ static ssize_t store_##file_name                                   \
        if (ret != 1)                                                   \
                return -EINVAL;                                         \
                                                                        \
-       ret = cpufreq_set_policy(&new_policy);                          \
+       mutex_lock(&policy->lock);                                      \
+       ret = __cpufreq_set_policy(policy, &new_policy);                \
+       policy->user_policy.object = policy->object;                    \
+       mutex_unlock(&policy->lock);                                    \
                                                                        \
        return ret ? ret : count;                                       \
 }
@@ -420,7 +424,15 @@ static ssize_t store_scaling_governor (struct cpufreq_policy * policy,
        if (cpufreq_parse_governor(str_governor, &new_policy.policy, &new_policy.governor))
                return -EINVAL;
 
-       ret = cpufreq_set_policy(&new_policy);
+       /* Do not use cpufreq_set_policy here or the user_policy.max
+          will be wrongly overridden */
+       mutex_lock(&policy->lock);
+       ret = __cpufreq_set_policy(policy, &new_policy);
+
+       policy->user_policy.policy = policy->policy;
+       policy->user_policy.governor = policy->governor;
+       mutex_unlock(&policy->lock);
+
        return ret ? ret : count;
 }
 
@@ -685,7 +697,7 @@ static int cpufreq_add_dev (struct sys_device * sys_dev)
                if (!cpu_online(j))
                        continue;
 
-               dprintk("CPU already managed, adding link\n");
+               dprintk("CPU %u already managed, adding link\n", j);
                cpufreq_cpu_get(cpu);
                cpu_sys_dev = get_cpu_sysdev(j);
                sysfs_create_link(&cpu_sys_dev->kobj, &policy->kobj,
@@ -695,9 +707,8 @@ static int cpufreq_add_dev (struct sys_device * sys_dev)
        policy->governor = NULL; /* to assure that the starting sequence is
                                  * run in cpufreq_set_policy */
        mutex_unlock(&policy->lock);
-       
+
        /* set default policy */
-       
        ret = cpufreq_set_policy(&new_policy);
        if (ret) {
                dprintk("setting policy failed\n");
@@ -707,7 +718,7 @@ static int cpufreq_add_dev (struct sys_device * sys_dev)
        module_put(cpufreq_driver->owner);
        dprintk("initialization complete\n");
        cpufreq_debug_enable_ratelimit();
-       
+
        return 0;
 
 
index 037f6bf4543c3c29b98e6401d8cb242b85a2f993..e07a35487bde7cf5b713c0c203a4819a537ae901 100644 (file)
@@ -176,8 +176,7 @@ static ssize_t store_up_threshold(struct cpufreq_policy *unused,
        ret = sscanf (buf, "%u", &input);
 
        mutex_lock(&dbs_mutex);
-       if (ret != 1 || input > 100 || input < 0 ||
-                       input <= dbs_tuners_ins.down_threshold) {
+       if (ret != 1 || input > 100 || input <= dbs_tuners_ins.down_threshold) {
                mutex_unlock(&dbs_mutex);
                return -EINVAL;
        }
@@ -196,8 +195,7 @@ static ssize_t store_down_threshold(struct cpufreq_policy *unused,
        ret = sscanf (buf, "%u", &input);
 
        mutex_lock(&dbs_mutex);
-       if (ret != 1 || input > 100 || input < 0 ||
-                       input >= dbs_tuners_ins.up_threshold) {
+       if (ret != 1 || input > 100 || input >= dbs_tuners_ins.up_threshold) {
                mutex_unlock(&dbs_mutex);
                return -EINVAL;
        }
index 8e0f3158215f6bc191864ef5f0a87f49ecc67bbd..dfca74933625e0c1c629778f0af1f9f8f00351b3 100644 (file)
@@ -478,6 +478,11 @@ static s32 i801_access(struct i2c_adapter * adap, u16 addr,
                ret = i801_transaction();
        }
 
+       /* Some BIOSes don't like it when PEC is enabled at reboot or resume
+          time, so we forcibly disable it after every transaction. */
+       if (hwpec)
+               outb_p(0, SMBAUXCTL);
+
        if(block)
                return ret;
        if(ret)
index 27fc9ff2961a6dd9abff1f1ed9db358f4adb29ac..99ab4ec343902e8d5f3054fba8ffd301cfa2f168 100644 (file)
@@ -131,13 +131,13 @@ m41t00_set(void *arg)
        if ((i2c_smbus_write_byte_data(save_client, 0, tm.tm_sec & 0x7f) < 0)
                || (i2c_smbus_write_byte_data(save_client, 1, tm.tm_min & 0x7f)
                        < 0)
-               || (i2c_smbus_write_byte_data(save_client, 2, tm.tm_hour & 0x7f)
+               || (i2c_smbus_write_byte_data(save_client, 2, tm.tm_hour & 0x3f)
                        < 0)
-               || (i2c_smbus_write_byte_data(save_client, 4, tm.tm_mday & 0x7f)
+               || (i2c_smbus_write_byte_data(save_client, 4, tm.tm_mday & 0x3f)
                        < 0)
-               || (i2c_smbus_write_byte_data(save_client, 5, tm.tm_mon & 0x7f)
+               || (i2c_smbus_write_byte_data(save_client, 5, tm.tm_mon & 0x1f)
                        < 0)
-               || (i2c_smbus_write_byte_data(save_client, 6, tm.tm_year & 0x7f)
+               || (i2c_smbus_write_byte_data(save_client, 6, tm.tm_year & 0xff)
                        < 0))
 
                dev_warn(&save_client->dev,"m41t00: can't write to rtc chip\n");
index cf84350efc550b3dc804dd9a5cb03d8978dc9002..8b24b4f2a839a0abe424cf5e75eebd2bf5a9434b 100644 (file)
@@ -731,6 +731,8 @@ static unsigned int __devinit ata66_ali15x3 (ide_hwif_t *hwif)
        
        if(m5229_revision <= 0x20)
                tmpbyte = (tmpbyte & (~0x02)) | 0x01;
+       else if (m5229_revision == 0xc7)
+               tmpbyte |= 0x03;
        else
                tmpbyte |= 0x01;
 
index df9ee9a784350c2d63ab3ba345d90bd2da25c9cb..900efd1da587d782a0afd369579c62713935280b 100644 (file)
@@ -348,6 +348,7 @@ static struct pci_device_id atiixp_pci_tbl[] = {
        { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP200_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
        { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP300_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
        { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP400_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+       { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP600_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
        { 0, },
 };
 MODULE_DEVICE_TABLE(pci, atiixp_pci_tbl);
index 6f8f8645b02c5666ad4cc336b0a93d8ba6aa7447..7ce5bf7836882b32ed8da8587706eee826a543b9 100644 (file)
@@ -798,7 +798,6 @@ static ide_pci_device_t pdc202xx_chipsets[] __devinitdata = {
                .autodma        = AUTODMA,
                .bootable       = OFF_BOARD,
                .extra          = 48,
-               .flags          = IDEPCI_FLAG_FORCE_PDC,
        },{     /* 2 */
                .name           = "PDC20263",
                .init_setup     = init_setup_pdc202ata4,
@@ -819,7 +818,6 @@ static ide_pci_device_t pdc202xx_chipsets[] __devinitdata = {
                .autodma        = AUTODMA,
                .bootable       = OFF_BOARD,
                .extra          = 48,
-               .flags          = IDEPCI_FLAG_FORCE_PDC,
        },{     /* 4 */
                .name           = "PDC20267",
                .init_setup     = init_setup_pdc202xx,
index 7ebf992e8c2f40f2050060ea2e3f8cd53d188436..462ed3006c3082124a0a9622dfa9e7448116cc09 100644 (file)
@@ -580,7 +580,6 @@ void ide_pci_setup_ports(struct pci_dev *dev, ide_pci_device_t *d, int pciirq, a
        int port;
        int at_least_one_hwif_enabled = 0;
        ide_hwif_t *hwif, *mate = NULL;
-       static int secondpdc = 0;
        u8 tmp;
 
        index->all = 0xf0f0;
@@ -592,21 +591,9 @@ void ide_pci_setup_ports(struct pci_dev *dev, ide_pci_device_t *d, int pciirq, a
        for (port = 0; port <= 1; ++port) {
                ide_pci_enablebit_t *e = &(d->enablebits[port]);
        
-               /* 
-                * If this is a Promise FakeRaid controller,
-                * the 2nd controller will be marked as 
-                * disabled while it is actually there and enabled
-                * by the bios for raid purposes. 
-                * Skip the normal "is it enabled" test for those.
-                */
-               if ((d->flags & IDEPCI_FLAG_FORCE_PDC) &&
-                   (secondpdc++==1) && (port==1))
-                       goto controller_ok;
-                       
                if (e->reg && (pci_read_config_byte(dev, e->reg, &tmp) ||
                    (tmp & e->mask) != e->val))
                        continue;       /* port not enabled */
-controller_ok:
 
                if (d->channels <= port)
                        break;
index 3a702da83e41bc595263aa29438fadc0ed3df3d3..469b6923a2e2e0a2c59b388d8f93fedc2e961fac 100644 (file)
@@ -228,10 +228,7 @@ struct ib_mad_agent *ib_register_mad_agent(struct ib_device *device,
                                goto error1;
                }
                /* Make sure class supplied is consistent with RMPP */
-               if (ib_is_mad_class_rmpp(mad_reg_req->mgmt_class)) {
-                       if (!rmpp_version)
-                               goto error1;
-               } else {
+               if (!ib_is_mad_class_rmpp(mad_reg_req->mgmt_class)) {
                        if (rmpp_version)
                                goto error1;
                }
index cd533cf951c26b5a7cc25b3dcad22386065ca092..7d3fb6996b41d6fb6aecf589b2ef2bcddbe5588e 100644 (file)
@@ -365,15 +365,3 @@ static ssize_t ipath_diag_write(struct file *fp, const char __user *data,
 bail:
        return ret;
 }
-
-void ipath_diag_bringup_link(struct ipath_devdata *dd)
-{
-       if (diag_set_link || (dd->ipath_flags & IPATH_LINKACTIVE))
-               return;
-
-       diag_set_link = 1;
-       ipath_cdbg(VERBOSE, "Trying to set to set link active for "
-                  "diag pkt\n");
-       ipath_layer_set_linkstate(dd, IPATH_IB_LINKARM);
-       ipath_layer_set_linkstate(dd, IPATH_IB_LINKACTIVE);
-}
index 58a94efb0070bb14d658ae1e32f90b2e17b9f3c0..e7617c3982ea6c18641d9a6be9aee2120e566d6b 100644 (file)
@@ -1729,7 +1729,7 @@ void ipath_free_pddata(struct ipath_devdata *dd, u32 port, int freehdrq)
        }
 }
 
-int __init infinipath_init(void)
+static int __init infinipath_init(void)
 {
        int ret;
 
index 60f5f4108069253e20c84d2c06eded189b2e0865..0bcb428041f32eb7fb2990ee9ae0610390fe201e 100644 (file)
@@ -172,8 +172,8 @@ static void handle_e_ibstatuschanged(struct ipath_devdata *dd,
                                   "was %s\n", dd->ipath_unit,
                                   ib_linkstate(lstate),
                                   ib_linkstate((unsigned)
-                                               dd->ipath_lastibcstat
-                                               & IPATH_IBSTATE_MASK));
+                                               dd->ipath_lastibcstat
+                                               & IPATH_IBSTATE_MASK));
        }
        else {
                lstate = dd->ipath_lastibcstat & IPATH_IBSTATE_MASK;
index 159d0aed31a5b0b792e69b28f1b6ef32dd2596b1..0ce5f19c9d62ac5f2bd07356f1bcc8ce9f31fee1 100644 (file)
@@ -528,7 +528,6 @@ extern spinlock_t ipath_devs_lock;
 extern struct ipath_devdata *ipath_lookup(int unit);
 
 extern u16 ipath_layer_rcv_opcode;
-extern int ipath_verbs_registered;
 extern int __ipath_layer_intr(struct ipath_devdata *, u32);
 extern int ipath_layer_intr(struct ipath_devdata *, u32);
 extern int __ipath_layer_rcv(struct ipath_devdata *, void *,
index 2cabf634057212f3ca8f2b8410b07b61ab6cecdc..69ed1100701af5db8ff1cbc226b8076b03979f15 100644 (file)
@@ -52,7 +52,7 @@ static int (*layer_rcv)(void *, void *, struct sk_buff *);
 static int (*layer_rcv_lid)(void *, void *);
 static int (*verbs_piobufavail)(void *);
 static void (*verbs_rcv)(void *, void *, void *, u32);
-int ipath_verbs_registered;
+static int ipath_verbs_registered;
 
 static void *(*layer_add_one)(int, struct ipath_devdata *);
 static void (*layer_remove_one)(void *);
index e693a7a8266703996f99e5fe58f5e30fe1a244b3..e1dc4f757062a5ac8f9595fc197de26c20e7dda7 100644 (file)
@@ -305,8 +305,8 @@ static const struct ipath_cregs ipath_pe_cregs = {
  * we'll print them and continue.  We reuse the same message buffer as
  * ipath_handle_errors() to avoid excessive stack usage.
  */
-void ipath_pe_handle_hwerrors(struct ipath_devdata *dd, char *msg,
-       size_t msgl)
+static void ipath_pe_handle_hwerrors(struct ipath_devdata *dd, char *msg,
+                                    size_t msgl)
 {
        ipath_err_t hwerrs;
        u32 bits, ctrl;
@@ -552,7 +552,7 @@ static int ipath_pe_boardname(struct ipath_devdata *dd, char *name,
  * freeze mode), and enable hardware errors as errors (along with
  * everything else) in errormask
  */
-void ipath_pe_init_hwerrors(struct ipath_devdata *dd)
+static void ipath_pe_init_hwerrors(struct ipath_devdata *dd)
 {
        ipath_err_t val;
        u64 extsval;
@@ -577,7 +577,7 @@ void ipath_pe_init_hwerrors(struct ipath_devdata *dd)
  * ipath_pe_bringup_serdes - bring up the serdes
  * @dd: the infinipath device
  */
-int ipath_pe_bringup_serdes(struct ipath_devdata *dd)
+static int ipath_pe_bringup_serdes(struct ipath_devdata *dd)
 {
        u64 val, tmp, config1;
        int ret = 0, change = 0;
@@ -694,7 +694,7 @@ int ipath_pe_bringup_serdes(struct ipath_devdata *dd)
  * @dd: the infinipath device
  * Called when driver is being unloaded
  */
-void ipath_pe_quiet_serdes(struct ipath_devdata *dd)
+static void ipath_pe_quiet_serdes(struct ipath_devdata *dd)
 {
        u64 val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_serdesconfig0);
 
index 6058d70d7577bb349ab7e5db759e1e3d37db4fc3..18890716db1ed3bf5812968d8945f71905cdfd3a 100644 (file)
@@ -188,8 +188,8 @@ static void free_qpn(struct ipath_qp_table *qpt, u32 qpn)
  * Allocate the next available QPN and put the QP into the hash table.
  * The hash table holds a reference to the QP.
  */
-int ipath_alloc_qpn(struct ipath_qp_table *qpt, struct ipath_qp *qp,
-                   enum ib_qp_type type)
+static int ipath_alloc_qpn(struct ipath_qp_table *qpt, struct ipath_qp *qp,
+                          enum ib_qp_type type)
 {
        unsigned long flags;
        u32 qpn;
@@ -232,7 +232,7 @@ bail:
  * Remove the QP from the table so it can't be found asynchronously by
  * the receive interrupt routine.
  */
-void ipath_free_qp(struct ipath_qp_table *qpt, struct ipath_qp *qp)
+static void ipath_free_qp(struct ipath_qp_table *qpt, struct ipath_qp *qp)
 {
        struct ipath_qp *q, **qpp;
        unsigned long flags;
@@ -357,6 +357,65 @@ static void ipath_reset_qp(struct ipath_qp *qp)
        qp->r_reuse_sge = 0;
 }
 
+/**
+ * ipath_error_qp - put a QP into an error state
+ * @qp: the QP to put into an error state
+ *
+ * Flushes both send and receive work queues.
+ * QP r_rq.lock and s_lock should be held.
+ */
+
+static void ipath_error_qp(struct ipath_qp *qp)
+{
+       struct ipath_ibdev *dev = to_idev(qp->ibqp.device);
+       struct ib_wc wc;
+
+       _VERBS_INFO("QP%d/%d in error state\n",
+                   qp->ibqp.qp_num, qp->remote_qpn);
+
+       spin_lock(&dev->pending_lock);
+       /* XXX What if its already removed by the timeout code? */
+       if (qp->timerwait.next != LIST_POISON1)
+               list_del(&qp->timerwait);
+       if (qp->piowait.next != LIST_POISON1)
+               list_del(&qp->piowait);
+       spin_unlock(&dev->pending_lock);
+
+       wc.status = IB_WC_WR_FLUSH_ERR;
+       wc.vendor_err = 0;
+       wc.byte_len = 0;
+       wc.imm_data = 0;
+       wc.qp_num = qp->ibqp.qp_num;
+       wc.src_qp = 0;
+       wc.wc_flags = 0;
+       wc.pkey_index = 0;
+       wc.slid = 0;
+       wc.sl = 0;
+       wc.dlid_path_bits = 0;
+       wc.port_num = 0;
+
+       while (qp->s_last != qp->s_head) {
+               struct ipath_swqe *wqe = get_swqe_ptr(qp, qp->s_last);
+
+               wc.wr_id = wqe->wr.wr_id;
+               wc.opcode = ib_ipath_wc_opcode[wqe->wr.opcode];
+               if (++qp->s_last >= qp->s_size)
+                       qp->s_last = 0;
+               ipath_cq_enter(to_icq(qp->ibqp.send_cq), &wc, 1);
+       }
+       qp->s_cur = qp->s_tail = qp->s_head;
+       qp->s_hdrwords = 0;
+       qp->s_ack_state = IB_OPCODE_RC_ACKNOWLEDGE;
+
+       wc.opcode = IB_WC_RECV;
+       while (qp->r_rq.tail != qp->r_rq.head) {
+               wc.wr_id = get_rwqe_ptr(&qp->r_rq, qp->r_rq.tail)->wr_id;
+               if (++qp->r_rq.tail >= qp->r_rq.size)
+                       qp->r_rq.tail = 0;
+               ipath_cq_enter(to_icq(qp->ibqp.recv_cq), &wc, 1);
+       }
+}
+
 /**
  * ipath_modify_qp - modify the attributes of a queue pair
  * @ibqp: the queue pair who's attributes we're modifying
@@ -820,65 +879,6 @@ void ipath_sqerror_qp(struct ipath_qp *qp, struct ib_wc *wc)
        qp->state = IB_QPS_SQE;
 }
 
-/**
- * ipath_error_qp - put a QP into an error state
- * @qp: the QP to put into an error state
- *
- * Flushes both send and receive work queues.
- * QP r_rq.lock and s_lock should be held.
- */
-
-void ipath_error_qp(struct ipath_qp *qp)
-{
-       struct ipath_ibdev *dev = to_idev(qp->ibqp.device);
-       struct ib_wc wc;
-
-       _VERBS_INFO("QP%d/%d in error state\n",
-                   qp->ibqp.qp_num, qp->remote_qpn);
-
-       spin_lock(&dev->pending_lock);
-       /* XXX What if its already removed by the timeout code? */
-       if (qp->timerwait.next != LIST_POISON1)
-               list_del(&qp->timerwait);
-       if (qp->piowait.next != LIST_POISON1)
-               list_del(&qp->piowait);
-       spin_unlock(&dev->pending_lock);
-
-       wc.status = IB_WC_WR_FLUSH_ERR;
-       wc.vendor_err = 0;
-       wc.byte_len = 0;
-       wc.imm_data = 0;
-       wc.qp_num = qp->ibqp.qp_num;
-       wc.src_qp = 0;
-       wc.wc_flags = 0;
-       wc.pkey_index = 0;
-       wc.slid = 0;
-       wc.sl = 0;
-       wc.dlid_path_bits = 0;
-       wc.port_num = 0;
-
-       while (qp->s_last != qp->s_head) {
-               struct ipath_swqe *wqe = get_swqe_ptr(qp, qp->s_last);
-
-               wc.wr_id = wqe->wr.wr_id;
-               wc.opcode = ib_ipath_wc_opcode[wqe->wr.opcode];
-               if (++qp->s_last >= qp->s_size)
-                       qp->s_last = 0;
-               ipath_cq_enter(to_icq(qp->ibqp.send_cq), &wc, 1);
-       }
-       qp->s_cur = qp->s_tail = qp->s_head;
-       qp->s_hdrwords = 0;
-       qp->s_ack_state = IB_OPCODE_RC_ACKNOWLEDGE;
-
-       wc.opcode = IB_WC_RECV;
-       while (qp->r_rq.tail != qp->r_rq.head) {
-               wc.wr_id = get_rwqe_ptr(&qp->r_rq, qp->r_rq.tail)->wr_id;
-               if (++qp->r_rq.tail >= qp->r_rq.size)
-                       qp->r_rq.tail = 0;
-               ipath_cq_enter(to_icq(qp->ibqp.recv_cq), &wc, 1);
-       }
-}
-
 /**
  * ipath_get_credit - flush the send work queue of a QP
  * @qp: the qp who's send work queue to flush
index 5ff3de6128b2fd21b9f79f8dfb64704f65aa643e..01cfb30ee16040f31ee06a01527227ece95176ba 100644 (file)
@@ -46,8 +46,8 @@
  * This is called from ipath_post_ud_send() to forward a WQE addressed
  * to the same HCA.
  */
-void ipath_ud_loopback(struct ipath_qp *sqp, struct ipath_sge_state *ss,
-                      u32 length, struct ib_send_wr *wr, struct ib_wc *wc)
+static void ipath_ud_loopback(struct ipath_qp *sqp, struct ipath_sge_state *ss,
+                             u32 length, struct ib_send_wr *wr, struct ib_wc *wc)
 {
        struct ipath_ibdev *dev = to_idev(sqp->ibqp.device);
        struct ipath_qp *qp;
index 9f27fd35cdbb7e5500c4f5b7e17e8b5418b78221..8d2558a01f35e5a599d1fb0a0827987934fbdc75 100644 (file)
@@ -41,7 +41,7 @@
 /* Not static, because we don't want the compiler removing it */
 const char ipath_verbs_version[] = "ipath_verbs " IPATH_IDSTR;
 
-unsigned int ib_ipath_qp_table_size = 251;
+static unsigned int ib_ipath_qp_table_size = 251;
 module_param_named(qp_table_size, ib_ipath_qp_table_size, uint, S_IRUGO);
 MODULE_PARM_DESC(qp_table_size, "QP table size");
 
@@ -87,7 +87,7 @@ const enum ib_wc_opcode ib_ipath_wc_opcode[] = {
 /*
  * System image GUID.
  */
-__be64 sys_image_guid;
+static __be64 sys_image_guid;
 
 /**
  * ipath_copy_sge - copy data to SGE memory
@@ -1110,7 +1110,7 @@ static void ipath_unregister_ib_device(void *arg)
        ib_dealloc_device(ibdev);
 }
 
-int __init ipath_verbs_init(void)
+static int __init ipath_verbs_init(void)
 {
        return ipath_verbs_register(ipath_register_ib_device,
                                    ipath_unregister_ib_device,
@@ -1118,33 +1118,33 @@ int __init ipath_verbs_init(void)
                                    ipath_ib_timer);
 }
 
-void __exit ipath_verbs_cleanup(void)
+static void __exit ipath_verbs_cleanup(void)
 {
        ipath_verbs_unregister();
 }
 
 static ssize_t show_rev(struct class_device *cdev, char *buf)
 {
-        struct ipath_ibdev *dev =
-                container_of(cdev, struct ipath_ibdev, ibdev.class_dev);
-        int vendor, boardrev, majrev, minrev;
+       struct ipath_ibdev *dev =
+               container_of(cdev, struct ipath_ibdev, ibdev.class_dev);
+       int vendor, boardrev, majrev, minrev;
 
-        ipath_layer_query_device(dev->dd, &vendor, &boardrev,
-                                 &majrev, &minrev);
-        return sprintf(buf, "%d.%d\n", majrev, minrev);
+       ipath_layer_query_device(dev->dd, &vendor, &boardrev,
+                                &majrev, &minrev);
+       return sprintf(buf, "%d.%d\n", majrev, minrev);
 }
 
 static ssize_t show_hca(struct class_device *cdev, char *buf)
 {
-        struct ipath_ibdev *dev =
-                container_of(cdev, struct ipath_ibdev, ibdev.class_dev);
-        int ret;
+       struct ipath_ibdev *dev =
+               container_of(cdev, struct ipath_ibdev, ibdev.class_dev);
+       int ret;
 
-        ret = ipath_layer_get_boardname(dev->dd, buf, 128);
-        if (ret < 0)
-                goto bail;
-        strcat(buf, "\n");
-        ret = strlen(buf);
+       ret = ipath_layer_get_boardname(dev->dd, buf, 128);
+       if (ret < 0)
+               goto bail;
+       strcat(buf, "\n");
+       ret = strlen(buf);
 
 bail:
        return ret;
@@ -1152,40 +1152,40 @@ bail:
 
 static ssize_t show_stats(struct class_device *cdev, char *buf)
 {
-        struct ipath_ibdev *dev =
-                container_of(cdev, struct ipath_ibdev, ibdev.class_dev);
-        int i;
-        int len;
-
-        len = sprintf(buf,
-                      "RC resends  %d\n"
-                      "RC QACKs    %d\n"
-                      "RC ACKs     %d\n"
-                      "RC SEQ NAKs %d\n"
-                      "RC RDMA seq %d\n"
-                      "RC RNR NAKs %d\n"
-                      "RC OTH NAKs %d\n"
-                      "RC timeouts %d\n"
-                      "RC RDMA dup %d\n"
-                      "piobuf wait %d\n"
-                      "no piobuf   %d\n"
-                      "PKT drops   %d\n"
-                      "WQE errs    %d\n",
-                      dev->n_rc_resends, dev->n_rc_qacks, dev->n_rc_acks,
-                      dev->n_seq_naks, dev->n_rdma_seq, dev->n_rnr_naks,
-                      dev->n_other_naks, dev->n_timeouts,
-                      dev->n_rdma_dup_busy, dev->n_piowait,
-                      dev->n_no_piobuf, dev->n_pkt_drops, dev->n_wqe_errs);
-        for (i = 0; i < ARRAY_SIZE(dev->opstats); i++) {
+       struct ipath_ibdev *dev =
+               container_of(cdev, struct ipath_ibdev, ibdev.class_dev);
+       int i;
+       int len;
+
+       len = sprintf(buf,
+                     "RC resends  %d\n"
+                     "RC QACKs    %d\n"
+                     "RC ACKs     %d\n"
+                     "RC SEQ NAKs %d\n"
+                     "RC RDMA seq %d\n"
+                     "RC RNR NAKs %d\n"
+                     "RC OTH NAKs %d\n"
+                     "RC timeouts %d\n"
+                     "RC RDMA dup %d\n"
+                     "piobuf wait %d\n"
+                     "no piobuf   %d\n"
+                     "PKT drops   %d\n"
+                     "WQE errs    %d\n",
+                     dev->n_rc_resends, dev->n_rc_qacks, dev->n_rc_acks,
+                     dev->n_seq_naks, dev->n_rdma_seq, dev->n_rnr_naks,
+                     dev->n_other_naks, dev->n_timeouts,
+                     dev->n_rdma_dup_busy, dev->n_piowait,
+                     dev->n_no_piobuf, dev->n_pkt_drops, dev->n_wqe_errs);
+       for (i = 0; i < ARRAY_SIZE(dev->opstats); i++) {
                const struct ipath_opcode_stats *si = &dev->opstats[i];
 
-                if (!si->n_packets && !si->n_bytes)
-                        continue;
-                len += sprintf(buf + len, "%02x %llu/%llu\n", i,
+               if (!si->n_packets && !si->n_bytes)
+                       continue;
+               len += sprintf(buf + len, "%02x %llu/%llu\n", i,
                               (unsigned long long) si->n_packets,
-                               (unsigned long long) si->n_bytes);
-        }
-        return len;
+                              (unsigned long long) si->n_bytes);
+       }
+       return len;
 }
 
 static CLASS_DEVICE_ATTR(hw_rev, S_IRUGO, show_rev, NULL);
@@ -1194,25 +1194,25 @@ static CLASS_DEVICE_ATTR(board_id, S_IRUGO, show_hca, NULL);
 static CLASS_DEVICE_ATTR(stats, S_IRUGO, show_stats, NULL);
 
 static struct class_device_attribute *ipath_class_attributes[] = {
-        &class_device_attr_hw_rev,
-        &class_device_attr_hca_type,
-        &class_device_attr_board_id,
-        &class_device_attr_stats
+       &class_device_attr_hw_rev,
+       &class_device_attr_hca_type,
+       &class_device_attr_board_id,
+       &class_device_attr_stats
 };
 
 static int ipath_verbs_register_sysfs(struct ib_device *dev)
 {
-        int i;
+       int i;
        int ret;
 
-        for (i = 0; i < ARRAY_SIZE(ipath_class_attributes); ++i)
-                if (class_device_create_file(&dev->class_dev,
-                                             ipath_class_attributes[i])) {
-                        ret = 1;
+       for (i = 0; i < ARRAY_SIZE(ipath_class_attributes); ++i)
+               if (class_device_create_file(&dev->class_dev,
+                                            ipath_class_attributes[i])) {
+                       ret = 1;
                        goto bail;
                }
 
-        ret = 0;
+       ret = 0;
 
 bail:
        return ret;
index b824632b2a8c4f35809bcdb3ddc60c00cbece7c7..fcafbc7c9e71053002d9cd9b1a93bff2490ff545 100644 (file)
@@ -577,8 +577,6 @@ int ipath_init_qp_table(struct ipath_ibdev *idev, int size);
 
 void ipath_sqerror_qp(struct ipath_qp *qp, struct ib_wc *wc);
 
-void ipath_error_qp(struct ipath_qp *qp);
-
 void ipath_get_credit(struct ipath_qp *qp, u32 aeth);
 
 void ipath_do_rc_send(unsigned long data);
@@ -607,9 +605,6 @@ void ipath_rc_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr,
 
 void ipath_restart_rc(struct ipath_qp *qp, u32 psn, struct ib_wc *wc);
 
-void ipath_ud_loopback(struct ipath_qp *sqp, struct ipath_sge_state *ss,
-                      u32 length, struct ib_send_wr *wr, struct ib_wc *wc);
-
 int ipath_post_ud_send(struct ipath_qp *qp, struct ib_send_wr *wr);
 
 void ipath_ud_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr,
index f235c7ea42f07d7ed4e6d5aee255e834d7fdc2a6..4730863ece9a398c89e62c366d2f112d81b509f4 100644 (file)
@@ -49,7 +49,7 @@ enum {
        MTHCA_VENDOR_CLASS2 = 0xa
 };
 
-int mthca_update_rate(struct mthca_dev *dev, u8 port_num)
+static int mthca_update_rate(struct mthca_dev *dev, u8 port_num)
 {
        struct ib_port_attr *tprops = NULL;
        int                  ret;
index 5f2b3f6e4c4777c5a775627ba703669e66e5828c..5bb55742ada68d34249d11ae9390150b30e078f5 100644 (file)
@@ -617,6 +617,14 @@ static void srp_unmap_data(struct scsi_cmnd *scmnd,
                     scmnd->sc_data_direction);
 }
 
+static void srp_remove_req(struct srp_target_port *target, struct srp_request *req,
+                          int index)
+{
+       list_del(&req->list);
+       req->next = target->req_head;
+       target->req_head = index;
+}
+
 static void srp_process_rsp(struct srp_target_port *target, struct srp_rsp *rsp)
 {
        struct srp_request *req;
@@ -664,9 +672,7 @@ static void srp_process_rsp(struct srp_target_port *target, struct srp_rsp *rsp)
                        scmnd->host_scribble = (void *) -1L;
                        scmnd->scsi_done(scmnd);
 
-                       list_del(&req->list);
-                       req->next = target->req_head;
-                       target->req_head = rsp->tag & ~SRP_TAG_TSK_MGMT;
+                       srp_remove_req(target, req, rsp->tag & ~SRP_TAG_TSK_MGMT);
                } else
                        req->cmd_done = 1;
        }
@@ -1188,12 +1194,10 @@ static int srp_send_tsk_mgmt(struct scsi_cmnd *scmnd, u8 func)
        spin_lock_irq(target->scsi_host->host_lock);
 
        if (req->cmd_done) {
-               list_del(&req->list);
-               req->next = target->req_head;
-               target->req_head = req_index;
-
+               srp_remove_req(target, req, req_index);
                scmnd->scsi_done(scmnd);
        } else if (!req->tsk_status) {
+               srp_remove_req(target, req, req_index);
                scmnd->result = DID_ABORT << 16;
                ret = SUCCESS;
        }
index 434ca39d19c1d7b7dfb40c1163cb8281a52aeefb..d7316b829a62687a4c29372a893d2684121fb3a3 100644 (file)
@@ -279,11 +279,6 @@ static inline int mddev_lock(mddev_t * mddev)
        return mutex_lock_interruptible(&mddev->reconfig_mutex);
 }
 
-static inline void mddev_lock_uninterruptible(mddev_t * mddev)
-{
-       mutex_lock(&mddev->reconfig_mutex);
-}
-
 static inline int mddev_trylock(mddev_t * mddev)
 {
        return mutex_trylock(&mddev->reconfig_mutex);
@@ -2458,9 +2453,11 @@ md_attr_show(struct kobject *kobj, struct attribute *attr, char *page)
 
        if (!entry->show)
                return -EIO;
-       mddev_lock(mddev);
-       rv = entry->show(mddev, page);
-       mddev_unlock(mddev);
+       rv = mddev_lock(mddev);
+       if (!rv) {
+               rv = entry->show(mddev, page);
+               mddev_unlock(mddev);
+       }
        return rv;
 }
 
@@ -2474,9 +2471,11 @@ md_attr_store(struct kobject *kobj, struct attribute *attr,
 
        if (!entry->store)
                return -EIO;
-       mddev_lock(mddev);
-       rv = entry->store(mddev, page, length);
-       mddev_unlock(mddev);
+       rv = mddev_lock(mddev);
+       if (!rv) {
+               rv = entry->store(mddev, page, length);
+               mddev_unlock(mddev);
+       }
        return rv;
 }
 
@@ -4341,8 +4340,9 @@ static int md_seq_show(struct seq_file *seq, void *v)
                return 0;
        }
 
-       if (mddev_lock(mddev)!=0) 
+       if (mddev_lock(mddev) < 0)
                return -EINTR;
+
        if (mddev->pers || mddev->raid_disks || !list_empty(&mddev->disks)) {
                seq_printf(seq, "%s : %sactive", mdname(mddev),
                                                mddev->pers ? "" : "in");
index b82191d2bee127415d14b3e65075af0d7f702421..3b3e1046d0a47077a4a5c9b98dde97c13a369d23 100644 (file)
@@ -1,6 +1,6 @@
 /* sis900.c: A SiS 900/7016 PCI Fast Ethernet driver for Linux.
    Copyright 1999 Silicon Integrated System Corporation 
-   Revision:   1.08.09 Sep. 19 2005
+   Revision:   1.08.10 Apr. 2 2006
    
    Modified from the driver which is originally written by Donald Becker.
    
    SiS 7014 Single Chip 100BASE-TX/10BASE-T Physical Layer Solution,
    preliminary Rev. 1.0 Jan. 18, 1998
 
+   Rev 1.08.10 Apr.  2 2006 Daniele Venzano add vlan (jumbo packets) support
    Rev 1.08.09 Sep. 19 2005 Daniele Venzano add Wake on LAN support
    Rev 1.08.08 Jan. 22 2005 Daniele Venzano use netif_msg for debugging messages
-   Rev 1.08.07 Nov.  2 2003 Daniele Venzano <webvenza@libero.it> add suspend/resume support
+   Rev 1.08.07 Nov.  2 2003 Daniele Venzano <venza@brownhat.org> add suspend/resume support
    Rev 1.08.06 Sep. 24 2002 Mufasa Yang bug fix for Tx timeout & add SiS963 support
    Rev 1.08.05 Jun.  6 2002 Mufasa Yang bug fix for read_eeprom & Tx descriptor over-boundary
    Rev 1.08.04 Apr. 25 2002 Mufasa Yang <mufasa@sis.com.tw> added SiS962 support
@@ -77,7 +78,7 @@
 #include "sis900.h"
 
 #define SIS900_MODULE_NAME "sis900"
-#define SIS900_DRV_VERSION "v1.08.09 Sep. 19 2005"
+#define SIS900_DRV_VERSION "v1.08.10 Apr. 2 2006"
 
 static char version[] __devinitdata =
 KERN_INFO "sis900.c: " SIS900_DRV_VERSION "\n";
@@ -1401,6 +1402,11 @@ static void sis900_set_mode (long ioaddr, int speed, int duplex)
                rx_flags |= RxATX;
        }
 
+#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
+       /* Can accept Jumbo packet */
+       rx_flags |= RxAJAB;
+#endif
+
        outl (tx_flags, ioaddr + txcfg);
        outl (rx_flags, ioaddr + rxcfg);
 }
@@ -1713,18 +1719,26 @@ static int sis900_rx(struct net_device *net_dev)
 
        while (rx_status & OWN) {
                unsigned int rx_size;
+               unsigned int data_size;
 
                if (--rx_work_limit < 0)
                        break;
 
-               rx_size = (rx_status & DSIZE) - CRC_SIZE;
+               data_size = rx_status & DSIZE;
+               rx_size = data_size - CRC_SIZE;
+
+#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
+               /* ``TOOLONG'' flag means jumbo packet recived. */
+               if ((rx_status & TOOLONG) && data_size <= MAX_FRAME_SIZE)
+                       rx_status &= (~ ((unsigned int)TOOLONG));
+#endif
 
                if (rx_status & (ABORT|OVERRUN|TOOLONG|RUNT|RXISERR|CRCERR|FAERR)) {
                        /* corrupted packet received */
                        if (netif_msg_rx_err(sis_priv))
                                printk(KERN_DEBUG "%s: Corrupted packet "
-                                      "received, buffer status = 0x%8.8x.\n",
-                                      net_dev->name, rx_status);
+                                      "received, buffer status = 0x%8.8x/%d.\n",
+                                      net_dev->name, rx_status, data_size);
                        sis_priv->stats.rx_errors++;
                        if (rx_status & OVERRUN)
                                sis_priv->stats.rx_over_errors++;
index 50323941e3c0dea55d8c7357a63bc35631cae6db..4834e3a156948bc001c68ddf01735351edb6330c 100644 (file)
@@ -310,8 +310,14 @@ enum sis630_revision_id {
 #define CRC_SIZE                4
 #define MAC_HEADER_SIZE         14
 
-#define TX_BUF_SIZE     1536
-#define RX_BUF_SIZE     1536
+#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
+#define MAX_FRAME_SIZE  (1518 + 4)
+#else
+#define MAX_FRAME_SIZE  1518
+#endif /* CONFIG_VLAN_802_1Q */
+
+#define TX_BUF_SIZE     (MAX_FRAME_SIZE+18)
+#define RX_BUF_SIZE     (MAX_FRAME_SIZE+18)
 
 #define NUM_TX_DESC     16             /* Number of Tx descriptor registers. */
 #define NUM_RX_DESC     16             /* Number of Rx descriptor registers. */
index d5890027f8af86b0c11f5bf5222eba4fd8f01b05..48bbf32fd9802cb76e72eb1c8d8707e3d24d2357 100644 (file)
@@ -97,7 +97,7 @@ static struct superio_struct {        /* For Super-IO chips autodetection */
        int io;
        int irq;
        int dma;
-} superios[NR_SUPERIOS] __devinitdata = { {0,},};
+} superios[NR_SUPERIOS] = { {0,},};
 
 static int user_specified;
 #if defined(CONFIG_PARPORT_PC_SUPERIO) || \
@@ -1557,7 +1557,7 @@ static int __devinit get_superio_dma (struct parport *p)
        return PARPORT_DMA_NONE;
 }
 
-static int __devinit get_superio_irq (struct parport *p)
+static int get_superio_irq (struct parport *p)
 {
        int i=0;
         while( (superios[i].io != p->base) && (i<NR_SUPERIOS))
@@ -1579,7 +1579,7 @@ static int __devinit get_superio_irq (struct parport *p)
  *                         this shall always be the case!)
  *
  */
-static int __devinit parport_SPP_supported(struct parport *pb)
+static int parport_SPP_supported(struct parport *pb)
 {
        unsigned char r, w;
 
@@ -1660,7 +1660,7 @@ static int __devinit parport_SPP_supported(struct parport *pb)
  * two bits of ECR aren't writable, so we check by writing ECR and
  * reading it back to see if it's what we expect.
  */
-static int __devinit parport_ECR_present(struct parport *pb)
+static int parport_ECR_present(struct parport *pb)
 {
        struct parport_pc_private *priv = pb->private_data;
        unsigned char r = 0xc;
@@ -1712,7 +1712,7 @@ static int __devinit parport_ECR_present(struct parport *pb)
  * be misdetected here is rather academic. 
  */
 
-static int __devinit parport_PS2_supported(struct parport *pb)
+static int parport_PS2_supported(struct parport *pb)
 {
        int ok = 0;
   
@@ -1868,7 +1868,7 @@ static int __devinit parport_ECP_supported(struct parport *pb)
 }
 #endif
 
-static int __devinit parport_ECPPS2_supported(struct parport *pb)
+static int parport_ECPPS2_supported(struct parport *pb)
 {
        const struct parport_pc_private *priv = pb->private_data;
        int result;
@@ -1886,7 +1886,7 @@ static int __devinit parport_ECPPS2_supported(struct parport *pb)
 
 /* EPP mode detection  */
 
-static int __devinit parport_EPP_supported(struct parport *pb)
+static int parport_EPP_supported(struct parport *pb)
 {
        const struct parport_pc_private *priv = pb->private_data;
 
@@ -1931,7 +1931,7 @@ static int __devinit parport_EPP_supported(struct parport *pb)
        return 1;
 }
 
-static int __devinit parport_ECPEPP_supported(struct parport *pb)
+static int parport_ECPEPP_supported(struct parport *pb)
 {
        struct parport_pc_private *priv = pb->private_data;
        int result;
@@ -2073,7 +2073,7 @@ static int __devinit irq_probe_SPP(struct parport *pb)
  * When ECP is available we can autoprobe for IRQs.
  * NOTE: If we can autoprobe it, we can register the IRQ.
  */
-static int __devinit parport_irq_probe(struct parport *pb)
+static int parport_irq_probe(struct parport *pb)
 {
        struct parport_pc_private *priv = pb->private_data;
 
@@ -2779,7 +2779,7 @@ static struct parport_pc_pci {
        /* If set, this is called after probing for ports.  If 'failed'
         * is non-zero we couldn't use any of the ports. */
        void (*postinit_hook) (struct pci_dev *pdev, int failed);
-} cards[] __devinitdata = {
+} cards[] = {
        /* siig_1p_10x */               { 1, { { 2, 3 }, } },
        /* siig_2p_10x */               { 2, { { 2, 3 }, { 4, 5 }, } },
        /* siig_1p_20x */               { 1, { { 0, 1 }, } },
index 827550d25c9e3cfb058c8ef3d579fa09da1164d1..c42ae2cf8d64a262036381bd07ebb66b5d1b1cf8 100644 (file)
@@ -864,6 +864,35 @@ static void __init quirk_eisa_bridge(struct pci_dev *dev)
 }
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,  PCI_DEVICE_ID_INTEL_82375,      quirk_eisa_bridge );
 
+/*
+ * On the MSI-K8T-Neo2Fir Board, the internal Soundcard is disabled
+ * when a PCI-Soundcard is added. The BIOS only gives Options
+ * "Disabled" and "AUTO". This Quirk Sets the corresponding
+ * Register-Value to enable the Soundcard.
+ */
+static void __init k8t_sound_hostbridge(struct pci_dev *dev)
+{
+       unsigned char val;
+
+       printk(KERN_INFO "PCI: Quirk-MSI-K8T Soundcard On\n");
+       pci_read_config_byte(dev, 0x50, &val);
+       if (val == 0x88 || val == 0xc8) {
+               pci_write_config_byte(dev, 0x50, val & (~0x40));
+
+               /* Verify the Change for Status output */
+               pci_read_config_byte(dev, 0x50, &val);
+               if (val & 0x40)
+                       printk(KERN_INFO "PCI: MSI-K8T soundcard still off\n");
+               else
+                       printk(KERN_INFO "PCI: MSI-K8T soundcard on\n");
+       } else {
+               printk(KERN_INFO "PCI: Unexpected Value in PCI-Register: "
+                                       "no Change!\n");
+       }
+
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237, k8t_sound_hostbridge);
+
 /*
  * On ASUS P4B boards, the SMBus PCI Device within the ICH2/4 southbridge
  * is not activated. The myth is that Asus said that they do not want the
index 67cc5f7d0c90634c42726f9157f4c1460dfb4d71..a4d50940ebebf0f652de3163077d312e30e39269 100644 (file)
@@ -28,8 +28,6 @@
 #include <asm/arch/gpio.h>
 
 
-#define        CF_SIZE         0x30000000      /* CS5+CS6: unavailable */
-
 /*
  * A0..A10 work in each range; A23 indicates I/O space;  A25 is CFRNW;
  * some other bit in {A24,A22..A11} is nREG to flag memory access
@@ -76,7 +74,8 @@ static irqreturn_t at91_cf_irq(int irq, void *_cf, struct pt_regs *r)
                /* kick pccard as needed */
                if (present != cf->present) {
                        cf->present = present;
-                       pr_debug("%s: card %s\n", driver_name, present ? "present" : "gone");
+                       pr_debug("%s: card %s\n", driver_name,
+                                       present ? "present" : "gone");
                        pcmcia_parse_events(&cf->socket, SS_DETECT);
                }
        }
@@ -93,7 +92,7 @@ static int at91_cf_get_status(struct pcmcia_socket *s, u_int *sp)
 
        cf = container_of(s, struct at91_cf_socket, socket);
 
-       /* NOTE: we assume 3VCARD, not XVCARD...  */
+       /* NOTE: CF is always 3VCARD */
        if (at91_cf_present(cf)) {
                int rdy = cf->board->irq_pin;   /* RDY/nIRQ */
                int vcc = cf->board->vcc_pin;
@@ -109,7 +108,8 @@ static int at91_cf_get_status(struct pcmcia_socket *s, u_int *sp)
        return 0;
 }
 
-static int at91_cf_set_socket(struct pcmcia_socket *sock, struct socket_state_t *s)
+static int
+at91_cf_set_socket(struct pcmcia_socket *sock, struct socket_state_t *s)
 {
        struct at91_cf_socket   *cf;
 
@@ -184,7 +184,8 @@ static int at91_cf_set_io_map(struct pcmcia_socket *s, struct pccard_io_map *io)
 }
 
 /* pcmcia layer maps/unmaps mem regions */
-static int at91_cf_set_mem_map(struct pcmcia_socket *s, struct pccard_mem_map *map)
+static int
+at91_cf_set_mem_map(struct pcmcia_socket *s, struct pccard_mem_map *map)
 {
        struct at91_cf_socket   *cf;
 
@@ -218,12 +219,17 @@ static int __init at91_cf_probe(struct device *dev)
        struct at91_cf_socket   *cf;
        struct at91_cf_data     *board = dev->platform_data;
        struct platform_device  *pdev = to_platform_device(dev);
+       struct resource         *io;
        unsigned int            csa;
        int                     status;
 
        if (!board || !board->det_pin || !board->rst_pin)
                return -ENODEV;
 
+       io = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!io)
+               return -ENODEV;
+
        cf = kcalloc(1, sizeof *cf, GFP_KERNEL);
        if (!cf)
                return -ENOMEM;
@@ -250,10 +256,14 @@ static int __init at91_cf_probe(struct device *dev)
         * REVISIT:  these timings are in terms of MCK cycles, so
         * when MCK changes (cpufreq etc) so must these values...
         */
-       at91_sys_write(AT91_SMC_CSR(4), AT91_SMC_ACSS_STD | AT91_SMC_DBW_16 | AT91_SMC_BAT | AT91_SMC_WSEN
-                               | AT91_SMC_NWS_(32)             /* wait states */
-                               | AT91_SMC_RWSETUP_(6)          /* setup time */
-                               | AT91_SMC_RWHOLD_(4)           /* hold time */
+       at91_sys_write(AT91_SMC_CSR(4),
+                                 AT91_SMC_ACSS_STD
+                               | AT91_SMC_DBW_16
+                               | AT91_SMC_BAT
+                               | AT91_SMC_WSEN
+                               | AT91_SMC_NWS_(32)     /* wait states */
+                               | AT91_SMC_RWSETUP_(6)  /* setup time */
+                               | AT91_SMC_RWHOLD_(4)   /* hold time */
        );
 
        /* must be a GPIO; ergo must trigger on both edges */
@@ -274,8 +284,7 @@ static int __init at91_cf_probe(struct device *dev)
                if (status < 0)
                        goto fail0a;
                cf->socket.pci_irq = board->irq_pin;
-       }
-       else
+       } else
                cf->socket.pci_irq = NR_IRQS + 1;
 
        /* pcmcia layer only remaps "real" memory not iospace */
@@ -284,7 +293,8 @@ static int __init at91_cf_probe(struct device *dev)
                goto fail1;
 
        /* reserve CS4, CS5, and CS6 regions; but use just CS4 */
-       if (!request_mem_region(AT91_CF_BASE, CF_SIZE, driver_name))
+       if (!request_mem_region(io->start, io->end + 1 - io->start,
+                               driver_name))
                goto fail1;
 
        pr_info("%s: irqs det #%d, io #%d\n", driver_name,
@@ -297,7 +307,7 @@ static int __init at91_cf_probe(struct device *dev)
        cf->socket.features = SS_CAP_PCCARD | SS_CAP_STATIC_MAP
                                | SS_CAP_MEM_ALIGN;
        cf->socket.map_size = SZ_2K;
-       cf->socket.io[0].NumPorts = SZ_2K;
+       cf->socket.io[0].res = io;
 
        status = pcmcia_register_socket(&cf->socket);
        if (status < 0)
@@ -307,7 +317,7 @@ static int __init at91_cf_probe(struct device *dev)
 
 fail2:
        iounmap((void __iomem *) cf->socket.io_offset);
-       release_mem_region(AT91_CF_BASE, CF_SIZE);
+       release_mem_region(io->start, io->end + 1 - io->start);
 fail1:
        if (board->irq_pin)
                free_irq(board->irq_pin, cf);
@@ -321,14 +331,15 @@ fail0:
 
 static int __exit at91_cf_remove(struct device *dev)
 {
-       struct at91_cf_socket *cf = dev_get_drvdata(dev);
-       unsigned int csa;
+       struct at91_cf_socket   *cf = dev_get_drvdata(dev);
+       struct resource         *io = cf->socket.io[0].res;
+       unsigned int            csa;
 
        pcmcia_unregister_socket(&cf->socket);
        free_irq(cf->board->irq_pin, cf);
        free_irq(cf->board->det_pin, cf);
        iounmap((void __iomem *) cf->socket.io_offset);
-       release_mem_region(AT91_CF_BASE, CF_SIZE);
+       release_mem_region(io->start, io->end + 1 - io->start);
 
        csa = at91_sys_read(AT91_EBI_CSA);
        at91_sys_write(AT91_EBI_CSA, csa & ~AT91_EBI_CS4A);
@@ -342,8 +353,8 @@ static struct device_driver at91_cf_driver = {
        .bus            = &platform_bus_type,
        .probe          = at91_cf_probe,
        .remove         = __exit_p(at91_cf_remove),
-       .suspend        = pcmcia_socket_dev_suspend,
-       .resume         = pcmcia_socket_dev_resume,
+       .suspend        = pcmcia_socket_dev_suspend,
+       .resume         = pcmcia_socket_dev_resume,
 };
 
 /*--------------------------------------------------------------------------*/
index fd3647368955f1f68aa8dad0f99ed25994b8ed15..b7b9e149c5b9c73278b095ca99a368af8e8eac51 100644 (file)
 #include "soc_common.h"
 
 #define        NO_KEEP_VS 0x0001
-
-/* PCMCIA to Scoop linkage
-
-   There is no easy way to link multiple scoop devices into one
-   single entity for the pxa2xx_pcmcia device so this structure
-   is used which is setup by the platform code
-*/
-struct scoop_pcmcia_config *platform_scoop_config;
 #define SCOOP_DEV platform_scoop_config->devs
 
 static void sharpsl_pcmcia_init_reset(struct soc_pcmcia_socket *skt)
index c4256aa32bcb0cc296624301cc8087aabfdac350..6fff109bdab606e98eb188f70a4b4a1dcafe6415 100644 (file)
@@ -479,7 +479,7 @@ int pnp_auto_config_dev(struct pnp_dev *dev)
 int pnp_start_dev(struct pnp_dev *dev)
 {
        if (!pnp_can_write(dev)) {
-               pnp_info("Device %s does not supported activation.", dev->dev.bus_id);
+               pnp_info("Device %s does not support activation.", dev->dev.bus_id);
                return -EINVAL;
        }
 
@@ -503,7 +503,7 @@ int pnp_start_dev(struct pnp_dev *dev)
 int pnp_stop_dev(struct pnp_dev *dev)
 {
        if (!pnp_can_disable(dev)) {
-               pnp_info("Device %s does not supported disabling.", dev->dev.bus_id);
+               pnp_info("Device %s does not support disabling.", dev->dev.bus_id);
                return -EINVAL;
        }
        if (dev->protocol->disable(dev)<0) {
index 90d4d0ef3dd4d54f5b6563e24c68118c654aa74f..6775a837d6461b1be0e2e537e660b3e9f833b3b9 100644 (file)
@@ -2,7 +2,7 @@
 # S/390 network devices
 #
 
-ctc-objs := ctcmain.o ctctty.o ctcdbug.o
+ctc-objs := ctcmain.o ctcdbug.o
 
 obj-$(CONFIG_IUCV) += iucv.o
 obj-$(CONFIG_NETIUCV) += netiucv.o fsm.o
@@ -10,6 +10,7 @@ obj-$(CONFIG_SMSGIUCV) += smsgiucv.o
 obj-$(CONFIG_CTC) += ctc.o fsm.o cu3088.o
 obj-$(CONFIG_LCS) += lcs.o cu3088.o
 obj-$(CONFIG_CLAW) += claw.o cu3088.o
+obj-$(CONFIG_MPC) += ctcmpc.o fsm.o cu3088.o
 qeth-y := qeth_main.o qeth_mpc.o qeth_sys.o qeth_eddp.o 
 qeth-$(CONFIG_PROC_FS) += qeth_proc.o
 obj-$(CONFIG_QETH) += qeth.o
index af9f212314b3a3c00cf5e298daba5f95d9b1acce..e2ccaf55961cc2a5a2639c1302aed1aa59522b6d 100644 (file)
@@ -6,7 +6,7 @@
  * Fixes by : Jochen Röhrig (roehrig@de.ibm.com)
  *            Arnaldo Carvalho de Melo <acme@conectiva.com.br>
              Peter Tiedemann (ptiedem@de.ibm.com)
- * Driver Model stuff by : Cornelia Huck <huckc@de.ibm.com>
+ * Driver Model stuff by : Cornelia Huck <cornelia.huck@de.ibm.com>
  *
  * Documentation used:
  *  - Principles of Operation (IBM doc#: SA22-7201-06)
@@ -65,7 +65,6 @@
 
 #include <asm/idals.h>
 
-#include "ctctty.h"
 #include "fsm.h"
 #include "cu3088.h"
 
@@ -479,10 +478,7 @@ ctc_unpack_skb(struct channel *ch, struct sk_buff *pskb)
                skb->dev = pskb->dev;
                skb->protocol = pskb->protocol;
                pskb->ip_summed = CHECKSUM_UNNECESSARY;
-               if (ch->protocol == CTC_PROTO_LINUX_TTY)
-                       ctc_tty_netif_rx(skb);
-               else
-                       netif_rx_ni(skb);
+               netif_rx_ni(skb);
                /**
                 * Successful rx; reset logflags
                 */
@@ -557,8 +553,7 @@ ccw_unit_check(struct channel *ch, unsigned char sense)
        DBF_TEXT(trace, 5, __FUNCTION__);
        if (sense & SNS0_INTERVENTION_REQ) {
                if (sense & 0x01) {
-                       if (ch->protocol != CTC_PROTO_LINUX_TTY)
-                               ctc_pr_debug("%s: Interface disc. or Sel. reset "
+                       ctc_pr_debug("%s: Interface disc. or Sel. reset "
                                        "(remote)\n", ch->id);
                        fsm_event(ch->fsm, CH_EVENT_UC_RCRESET, ch);
                } else {
@@ -2034,7 +2029,6 @@ static void
 dev_action_chup(fsm_instance * fi, int event, void *arg)
 {
        struct net_device *dev = (struct net_device *) arg;
-       struct ctc_priv *privptr = dev->priv;
 
        DBF_TEXT(trace, 3, __FUNCTION__);
        switch (fsm_getstate(fi)) {
@@ -2049,8 +2043,6 @@ dev_action_chup(fsm_instance * fi, int event, void *arg)
                                fsm_newstate(fi, DEV_STATE_RUNNING);
                                ctc_pr_info("%s: connected with remote side\n",
                                            dev->name);
-                               if (privptr->protocol == CTC_PROTO_LINUX_TTY)
-                                       ctc_tty_setcarrier(dev, 1);
                                ctc_clear_busy(dev);
                        }
                        break;
@@ -2059,8 +2051,6 @@ dev_action_chup(fsm_instance * fi, int event, void *arg)
                                fsm_newstate(fi, DEV_STATE_RUNNING);
                                ctc_pr_info("%s: connected with remote side\n",
                                            dev->name);
-                               if (privptr->protocol == CTC_PROTO_LINUX_TTY)
-                                       ctc_tty_setcarrier(dev, 1);
                                ctc_clear_busy(dev);
                        }
                        break;
@@ -2086,14 +2076,10 @@ dev_action_chup(fsm_instance * fi, int event, void *arg)
 static void
 dev_action_chdown(fsm_instance * fi, int event, void *arg)
 {
-       struct net_device *dev = (struct net_device *) arg;
-       struct ctc_priv *privptr = dev->priv;
 
        DBF_TEXT(trace, 3, __FUNCTION__);
        switch (fsm_getstate(fi)) {
                case DEV_STATE_RUNNING:
-                       if (privptr->protocol == CTC_PROTO_LINUX_TTY)
-                               ctc_tty_setcarrier(dev, 0);
                        if (event == DEV_EVENT_TXDOWN)
                                fsm_newstate(fi, DEV_STATE_STARTWAIT_TX);
                        else
@@ -2397,8 +2383,6 @@ ctc_tx(struct sk_buff *skb, struct net_device * dev)
         */
        if (fsm_getstate(privptr->fsm) != DEV_STATE_RUNNING) {
                fsm_event(privptr->fsm, DEV_EVENT_START, dev);
-               if (privptr->protocol == CTC_PROTO_LINUX_TTY)
-                       return -EBUSY;
                dev_kfree_skb(skb);
                privptr->stats.tx_dropped++;
                privptr->stats.tx_errors++;
@@ -2608,20 +2592,13 @@ ctc_netdev_unregister(struct net_device * dev)
        if (!dev)
                return;
        privptr = (struct ctc_priv *) dev->priv;
-       if (privptr->protocol != CTC_PROTO_LINUX_TTY)
-               unregister_netdev(dev);
-       else
-               ctc_tty_unregister_netdev(dev);
+       unregister_netdev(dev);
 }
 
 static int
 ctc_netdev_register(struct net_device * dev)
 {
-       struct ctc_priv *privptr = (struct ctc_priv *) dev->priv;
-       if (privptr->protocol != CTC_PROTO_LINUX_TTY)
-               return register_netdev(dev);
-       else
-               return ctc_tty_register_netdev(dev);
+       return register_netdev(dev);
 }
 
 static void
@@ -2667,7 +2644,9 @@ ctc_proto_store(struct device *dev, struct device_attribute *attr, const char *b
        if (!priv)
                return -ENODEV;
        sscanf(buf, "%u", &value);
-       if ((value < 0) || (value > CTC_PROTO_MAX))
+       if (!((value == CTC_PROTO_S390)  ||
+             (value == CTC_PROTO_LINUX) ||
+             (value == CTC_PROTO_OS390)))
                return -EINVAL;
        priv->protocol = value;
 
@@ -2897,10 +2876,7 @@ ctc_new_device(struct ccwgroup_device *cgdev)
                goto out;
        }
 
-       if (privptr->protocol == CTC_PROTO_LINUX_TTY)
-               strlcpy(dev->name, "ctctty%d", IFNAMSIZ);
-       else
-               strlcpy(dev->name, "ctc%d", IFNAMSIZ);
+       strlcpy(dev->name, "ctc%d", IFNAMSIZ);
 
        for (direction = READ; direction <= WRITE; direction++) {
                privptr->channel[direction] =
@@ -3046,7 +3022,6 @@ ctc_exit(void)
 {
        DBF_TEXT(setup, 3, __FUNCTION__);
        unregister_cu3088_discipline(&ctc_group_driver);
-       ctc_tty_cleanup();
        ctc_unregister_dbf_views();
        ctc_pr_info("CTC driver unloaded\n");
 }
@@ -3073,10 +3048,8 @@ ctc_init(void)
                ctc_pr_crit("ctc_init failed with ctc_register_dbf_views rc = %d\n", ret);
                return ret;
        }
-       ctc_tty_init();
        ret = register_cu3088_discipline(&ctc_group_driver);
        if (ret) {
-               ctc_tty_cleanup();
                ctc_unregister_dbf_views();
        }
        return ret;
index d2e835c0c1344296de249deeb11e804c691534c1..7f305d119f3d4b0a085dd9b08faf3593df6ffa09 100644 (file)
@@ -35,7 +35,9 @@
 #include <asm/ccwdev.h>
 #include <asm/ccwgroup.h>
 
-#include "ctctty.h"
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+
 #include "fsm.h"
 #include "cu3088.h"
 
@@ -50,9 +52,7 @@
 
 #define CTC_PROTO_S390          0
 #define CTC_PROTO_LINUX         1
-#define CTC_PROTO_LINUX_TTY     2
 #define CTC_PROTO_OS390         3
-#define CTC_PROTO_MAX           3
 
 #define CTC_BUFSIZE_LIMIT       65535
 #define CTC_BUFSIZE_DEFAULT     32768
@@ -257,15 +257,13 @@ static __inline__ void
 ctc_clear_busy(struct net_device * dev)
 {
        clear_bit(0, &(((struct ctc_priv *) dev->priv)->tbusy));
-       if (((struct ctc_priv *)dev->priv)->protocol != CTC_PROTO_LINUX_TTY)
-               netif_wake_queue(dev);
+       netif_wake_queue(dev);
 }
 
 static __inline__ int
 ctc_test_and_set_busy(struct net_device * dev)
 {
-       if (((struct ctc_priv *)dev->priv)->protocol != CTC_PROTO_LINUX_TTY)
-               netif_stop_queue(dev);
+       netif_stop_queue(dev);
        return test_and_set_bit(0, &((struct ctc_priv *) dev->priv)->tbusy);
 }
 
diff --git a/drivers/s390/net/ctctty.c b/drivers/s390/net/ctctty.c
deleted file mode 100644 (file)
index 5cdcdbf..0000000
+++ /dev/null
@@ -1,1259 +0,0 @@
-/*
- * CTC / ESCON network driver, tty interface.
- *
- * Copyright (C) 2001 IBM Deutschland Entwicklung GmbH, IBM Corporation
- * Author(s): Fritz Elfert (elfert@de.ibm.com, felfert@millenux.com)
- *
- * 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.
- *
- * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/serial_reg.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-#include <asm/uaccess.h>
-#include <linux/devfs_fs_kernel.h>
-#include "ctctty.h"
-#include "ctcdbug.h"
-
-#define CTC_TTY_MAJOR       43
-#define CTC_TTY_MAX_DEVICES 64
-
-#define CTC_ASYNC_MAGIC          0x49344C01 /* for paranoia-checking        */
-#define CTC_ASYNC_INITIALIZED    0x80000000 /* port was initialized         */
-#define CTC_ASYNC_NORMAL_ACTIVE  0x20000000 /* Normal device active         */
-#define CTC_ASYNC_CLOSING        0x08000000 /* Serial port is closing       */
-#define CTC_ASYNC_CTS_FLOW       0x04000000 /* Do CTS flow control          */
-#define CTC_ASYNC_CHECK_CD       0x02000000 /* i.e., CLOCAL                 */
-#define CTC_ASYNC_HUP_NOTIFY         0x0001 /* Notify tty on hangups/closes */
-#define CTC_ASYNC_NETDEV_OPEN        0x0002 /* Underlying netdev is open    */
-#define CTC_ASYNC_TX_LINESTAT        0x0004 /* Must send line status        */
-#define CTC_ASYNC_SPLIT_TERMIOS      0x0008 /* Sep. termios for dialin/out  */
-#define CTC_TTY_XMIT_SIZE              1024 /* Default bufsize for write    */
-#define CTC_SERIAL_XMIT_MAX            4000 /* Maximum bufsize for write    */
-
-/* Private data (similar to async_struct in <linux/serial.h>) */
-typedef struct {
-  int                  magic;
-  int                  flags;           /* defined in tty.h               */
-  int                  mcr;             /* Modem control register         */
-  int                   msr;             /* Modem status register          */
-  int                   lsr;             /* Line status register           */
-  int                  line;
-  int                  count;           /* # of fd on device              */
-  int                  blocked_open;    /* # of blocked opens             */
-  struct net_device     *netdev;
-  struct sk_buff_head   tx_queue;        /* transmit queue                 */
-  struct sk_buff_head   rx_queue;        /* receive queue                  */
-  struct tty_struct    *tty;            /* Pointer to corresponding tty   */
-  wait_queue_head_t    open_wait;
-  wait_queue_head_t    close_wait;
-  struct semaphore      write_sem;
-  struct tasklet_struct tasklet;
-  struct timer_list     stoptimer;
-} ctc_tty_info;
-
-/* Description of one CTC-tty */
-typedef struct {
-  struct tty_driver  *ctc_tty_device;             /* tty-device             */
-  ctc_tty_info       info[CTC_TTY_MAX_DEVICES];           /* Private data           */
-} ctc_tty_driver;
-
-static ctc_tty_driver *driver;
-
-/* Leave this unchanged unless you know what you do! */
-#define MODEM_PARANOIA_CHECK
-#define MODEM_DO_RESTART
-
-#define CTC_TTY_NAME "ctctty"
-
-static __u32 ctc_tty_magic = CTC_ASYNC_MAGIC;
-static int ctc_tty_shuttingdown = 0;
-
-static spinlock_t ctc_tty_lock;
-
-/* ctc_tty_try_read() is called from within ctc_tty_rcv_skb()
- * to stuff incoming data directly into a tty's flip-buffer. If the
- * flip buffer is full, the packet gets queued up.
- *
- * Return:
- *  1 = Success
- *  0 = Failure, data has to be buffered and later processed by
- *      ctc_tty_readmodem().
- */
-static int
-ctc_tty_try_read(ctc_tty_info * info, struct sk_buff *skb)
-{
-       int len;
-       struct tty_struct *tty;
-
-       DBF_TEXT(trace, 5, __FUNCTION__);
-       if ((tty = info->tty)) {
-               if (info->mcr & UART_MCR_RTS) {
-                       len = skb->len;
-                       tty_insert_flip_string(tty, skb->data, len);
-                       tty_flip_buffer_push(tty);
-                       kfree_skb(skb);
-                       return 1;
-               }
-       }
-       return 0;
-}
-
-/* ctc_tty_readmodem() is called periodically from within timer-interrupt.
- * It tries getting received data from the receive queue an stuff it into
- * the tty's flip-buffer.
- */
-static int
-ctc_tty_readmodem(ctc_tty_info *info)
-{
-       int ret = 1;
-       struct tty_struct *tty;
-
-       DBF_TEXT(trace, 5, __FUNCTION__);
-       if ((tty = info->tty)) {
-               if (info->mcr & UART_MCR_RTS) {
-                       struct sk_buff *skb;
-                       
-                       if ((skb = skb_dequeue(&info->rx_queue))) {
-                               int len = skb->len;
-                               tty_insert_flip_string(tty, skb->data, len);
-                               skb_pull(skb, len);
-                               tty_flip_buffer_push(tty);
-                               if (skb->len > 0)
-                                       skb_queue_head(&info->rx_queue, skb);
-                               else {
-                                       kfree_skb(skb);
-                                       ret = !skb_queue_empty(&info->rx_queue);
-                               }
-                       }
-               }
-       }
-       return ret;
-}
-
-void
-ctc_tty_setcarrier(struct net_device *netdev, int on)
-{
-       int i;
-
-       DBF_TEXT(trace, 4, __FUNCTION__);
-       if ((!driver) || ctc_tty_shuttingdown)
-               return;
-       for (i = 0; i < CTC_TTY_MAX_DEVICES; i++)
-               if (driver->info[i].netdev == netdev) {
-                       ctc_tty_info *info = &driver->info[i];
-                       if (on)
-                               info->msr |= UART_MSR_DCD;
-                       else
-                               info->msr &= ~UART_MSR_DCD;
-                       if ((info->flags & CTC_ASYNC_CHECK_CD) && (!on))
-                               tty_hangup(info->tty);
-               }
-}
-
-void
-ctc_tty_netif_rx(struct sk_buff *skb)
-{
-       int i;
-       ctc_tty_info *info = NULL;
-
-       DBF_TEXT(trace, 5, __FUNCTION__);
-       if (!skb)
-               return;
-       if ((!skb->dev) || (!driver) || ctc_tty_shuttingdown) {
-               dev_kfree_skb(skb);
-               return;
-       }
-       for (i = 0; i < CTC_TTY_MAX_DEVICES; i++)
-               if (driver->info[i].netdev == skb->dev) {
-                       info = &driver->info[i];
-                       break;
-               }
-       if (!info) {
-               dev_kfree_skb(skb);
-               return;
-       }
-       if (skb->len < 6) {
-               dev_kfree_skb(skb);
-               return;
-       }
-       if (memcmp(skb->data, &ctc_tty_magic, sizeof(__u32))) {
-               dev_kfree_skb(skb);
-               return;
-       }
-       skb_pull(skb, sizeof(__u32));
-
-       i = *((int *)skb->data);
-       skb_pull(skb, sizeof(info->mcr));
-       if (i & UART_MCR_RTS) {
-               info->msr |= UART_MSR_CTS;
-               if (info->flags & CTC_ASYNC_CTS_FLOW)
-                       info->tty->hw_stopped = 0;
-       } else {
-               info->msr &= ~UART_MSR_CTS;
-               if (info->flags & CTC_ASYNC_CTS_FLOW)
-                       info->tty->hw_stopped = 1;
-       }
-       if (i & UART_MCR_DTR)
-               info->msr |= UART_MSR_DSR;
-       else
-               info->msr &= ~UART_MSR_DSR;
-       if (skb->len <= 0) {
-               kfree_skb(skb);
-               return;
-       }
-       /* Try to deliver directly via tty-flip-buf if queue is empty */
-       if (skb_queue_empty(&info->rx_queue))
-               if (ctc_tty_try_read(info, skb))
-                       return;
-       /* Direct deliver failed or queue wasn't empty.
-        * Queue up for later dequeueing via timer-irq.
-        */
-       skb_queue_tail(&info->rx_queue, skb);
-       /* Schedule dequeuing */
-       tasklet_schedule(&info->tasklet);
-}
-
-static int
-ctc_tty_tint(ctc_tty_info * info)
-{
-       struct sk_buff *skb = skb_dequeue(&info->tx_queue);
-       int stopped = (info->tty->hw_stopped || info->tty->stopped);
-       int wake = 1;
-       int rc;
-
-       DBF_TEXT(trace, 4, __FUNCTION__);
-       if (!info->netdev) {
-               if (skb)
-                       kfree_skb(skb);
-               return 0;
-       }
-       if (info->flags & CTC_ASYNC_TX_LINESTAT) {
-               int skb_res = info->netdev->hard_header_len +
-                       sizeof(info->mcr) + sizeof(__u32);
-               /* If we must update line status,
-                * create an empty dummy skb and insert it.
-                */
-               if (skb)
-                       skb_queue_head(&info->tx_queue, skb);
-
-               skb = dev_alloc_skb(skb_res);
-               if (!skb) {
-                       printk(KERN_WARNING
-                              "ctc_tty: Out of memory in %s%d tint\n",
-                              CTC_TTY_NAME, info->line);
-                       return 1;
-               }
-               skb_reserve(skb, skb_res);
-               stopped = 0;
-               wake = 0;
-       }
-       if (!skb)
-               return 0;
-       if (stopped) {
-               skb_queue_head(&info->tx_queue, skb);
-               return 1;
-       }
-#if 0
-       if (skb->len > 0)
-               printk(KERN_DEBUG "tint: %d %02x\n", skb->len, *(skb->data));
-       else
-               printk(KERN_DEBUG "tint: %d STAT\n", skb->len);
-#endif
-       memcpy(skb_push(skb, sizeof(info->mcr)), &info->mcr, sizeof(info->mcr));
-       memcpy(skb_push(skb, sizeof(__u32)), &ctc_tty_magic, sizeof(__u32));
-       rc = info->netdev->hard_start_xmit(skb, info->netdev);
-       if (rc) {
-               skb_pull(skb, sizeof(info->mcr) + sizeof(__u32));
-               if (skb->len > 0)
-                       skb_queue_head(&info->tx_queue, skb);
-               else
-                       kfree_skb(skb);
-       } else {
-               struct tty_struct *tty = info->tty;
-
-               info->flags &= ~CTC_ASYNC_TX_LINESTAT;
-               if (tty) {
-                       tty_wakeup(tty);
-               }
-       }
-       return (skb_queue_empty(&info->tx_queue) ? 0 : 1);
-}
-
-/************************************************************
- *
- * Modem-functions
- *
- * mostly "stolen" from original Linux-serial.c and friends.
- *
- ************************************************************/
-
-static inline int
-ctc_tty_paranoia_check(ctc_tty_info * info, char *name, const char *routine)
-{
-#ifdef MODEM_PARANOIA_CHECK
-       if (!info) {
-               printk(KERN_WARNING "ctc_tty: null info_struct for %s in %s\n",
-                      name, routine);
-               return 1;
-       }
-       if (info->magic != CTC_ASYNC_MAGIC) {
-               printk(KERN_WARNING "ctc_tty: bad magic for info struct %s in %s\n",
-                      name, routine);
-               return 1;
-       }
-#endif
-       return 0;
-}
-
-static void
-ctc_tty_inject(ctc_tty_info *info, char c)
-{
-       int skb_res;
-       struct sk_buff *skb;
-       
-       DBF_TEXT(trace, 4, __FUNCTION__);
-       if (ctc_tty_shuttingdown)
-               return;
-       skb_res = info->netdev->hard_header_len + sizeof(info->mcr) +
-               sizeof(__u32) + 1;
-       skb = dev_alloc_skb(skb_res);
-       if (!skb) {
-               printk(KERN_WARNING
-                      "ctc_tty: Out of memory in %s%d tx_inject\n",
-                      CTC_TTY_NAME, info->line);
-               return;
-       }
-       skb_reserve(skb, skb_res);
-       *(skb_put(skb, 1)) = c;
-       skb_queue_head(&info->tx_queue, skb);
-       tasklet_schedule(&info->tasklet);
-}
-
-static void
-ctc_tty_transmit_status(ctc_tty_info *info)
-{
-       DBF_TEXT(trace, 5, __FUNCTION__);
-       if (ctc_tty_shuttingdown)
-               return;
-       info->flags |= CTC_ASYNC_TX_LINESTAT;
-       tasklet_schedule(&info->tasklet);
-}
-
-static void
-ctc_tty_change_speed(ctc_tty_info * info)
-{
-       unsigned int cflag;
-       unsigned int quot;
-       int i;
-
-       DBF_TEXT(trace, 3, __FUNCTION__);
-       if (!info->tty || !info->tty->termios)
-               return;
-       cflag = info->tty->termios->c_cflag;
-
-       quot = i = cflag & CBAUD;
-       if (i & CBAUDEX) {
-               i &= ~CBAUDEX;
-               if (i < 1 || i > 2)
-                       info->tty->termios->c_cflag &= ~CBAUDEX;
-               else
-                       i += 15;
-       }
-       if (quot) {
-               info->mcr |= UART_MCR_DTR;
-               info->mcr |= UART_MCR_RTS;
-               ctc_tty_transmit_status(info);
-       } else {
-               info->mcr &= ~UART_MCR_DTR;
-               info->mcr &= ~UART_MCR_RTS;
-               ctc_tty_transmit_status(info);
-               return;
-       }
-
-       /* CTS flow control flag and modem status interrupts */
-       if (cflag & CRTSCTS) {
-               info->flags |= CTC_ASYNC_CTS_FLOW;
-       } else
-               info->flags &= ~CTC_ASYNC_CTS_FLOW;
-       if (cflag & CLOCAL)
-               info->flags &= ~CTC_ASYNC_CHECK_CD;
-       else {
-               info->flags |= CTC_ASYNC_CHECK_CD;
-       }
-}
-
-static int
-ctc_tty_startup(ctc_tty_info * info)
-{
-       DBF_TEXT(trace, 3, __FUNCTION__);
-       if (info->flags & CTC_ASYNC_INITIALIZED)
-               return 0;
-#ifdef CTC_DEBUG_MODEM_OPEN
-       printk(KERN_DEBUG "starting up %s%d ...\n", CTC_TTY_NAME, info->line);
-#endif
-       /*
-        * Now, initialize the UART
-        */
-       info->mcr = UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2;
-       if (info->tty)
-               clear_bit(TTY_IO_ERROR, &info->tty->flags);
-       /*
-        * and set the speed of the serial port
-        */
-       ctc_tty_change_speed(info);
-
-       info->flags |= CTC_ASYNC_INITIALIZED;
-       if (!(info->flags & CTC_ASYNC_NETDEV_OPEN))
-               info->netdev->open(info->netdev);
-       info->flags |= CTC_ASYNC_NETDEV_OPEN;
-       return 0;
-}
-
-static void
-ctc_tty_stopdev(unsigned long data)
-{
-       ctc_tty_info *info = (ctc_tty_info *)data;
-
-       if ((!info) || (!info->netdev) ||
-           (info->flags & CTC_ASYNC_INITIALIZED))
-               return;
-       info->netdev->stop(info->netdev);
-       info->flags &= ~CTC_ASYNC_NETDEV_OPEN;
-}
-
-/*
- * This routine will shutdown a serial port; interrupts are disabled, and
- * DTR is dropped if the hangup on close termio flag is on.
- */
-static void
-ctc_tty_shutdown(ctc_tty_info * info)
-{
-       DBF_TEXT(trace, 3, __FUNCTION__);
-       if (!(info->flags & CTC_ASYNC_INITIALIZED))
-               return;
-#ifdef CTC_DEBUG_MODEM_OPEN
-       printk(KERN_DEBUG "Shutting down %s%d ....\n", CTC_TTY_NAME, info->line);
-#endif
-       info->msr &= ~UART_MSR_RI;
-       if (!info->tty || (info->tty->termios->c_cflag & HUPCL))
-               info->mcr &= ~(UART_MCR_DTR | UART_MCR_RTS);
-       if (info->tty)
-               set_bit(TTY_IO_ERROR, &info->tty->flags);
-       mod_timer(&info->stoptimer, jiffies + (10 * HZ));
-       skb_queue_purge(&info->tx_queue);
-       skb_queue_purge(&info->rx_queue);
-       info->flags &= ~CTC_ASYNC_INITIALIZED;
-}
-
-/* ctc_tty_write() is the main send-routine. It is called from the upper
- * levels within the kernel to perform sending data. Depending on the
- * online-flag it either directs output to the at-command-interpreter or
- * to the lower level. Additional tasks done here:
- *  - If online, check for escape-sequence (+++)
- *  - If sending audio-data, call ctc_tty_DLEdown() to parse DLE-codes.
- *  - If receiving audio-data, call ctc_tty_end_vrx() to abort if needed.
- *  - If dialing, abort dial.
- */
-static int
-ctc_tty_write(struct tty_struct *tty, const u_char * buf, int count)
-{
-       int c;
-       int total = 0;
-       ctc_tty_info *info = (ctc_tty_info *) tty->driver_data;
-
-       DBF_TEXT(trace, 5, __FUNCTION__);
-       if (ctc_tty_shuttingdown)
-               goto ex;
-       if (ctc_tty_paranoia_check(info, tty->name, "ctc_tty_write"))
-               goto ex;
-       if (!tty)
-               goto ex;
-       if (!info->netdev) {
-               total = -ENODEV;
-               goto ex;
-       }
-       while (1) {
-               struct sk_buff *skb;
-               int skb_res;
-
-               c = (count < CTC_TTY_XMIT_SIZE) ? count : CTC_TTY_XMIT_SIZE;
-               if (c <= 0)
-                       break;
-               
-               skb_res = info->netdev->hard_header_len + sizeof(info->mcr) +
-                       + sizeof(__u32);
-               skb = dev_alloc_skb(skb_res + c);
-               if (!skb) {
-                       printk(KERN_WARNING
-                              "ctc_tty: Out of memory in %s%d write\n",
-                              CTC_TTY_NAME, info->line);
-                       break;
-               }
-               skb_reserve(skb, skb_res);
-               memcpy(skb_put(skb, c), buf, c);
-               skb_queue_tail(&info->tx_queue, skb);
-               buf += c;
-               total += c;
-               count -= c;
-       }
-       if (!skb_queue_empty(&info->tx_queue)) {
-               info->lsr &= ~UART_LSR_TEMT;
-               tasklet_schedule(&info->tasklet);
-       }
-ex:
-       DBF_TEXT(trace, 6, __FUNCTION__);
-       return total;
-}
-
-static int
-ctc_tty_write_room(struct tty_struct *tty)
-{
-       ctc_tty_info *info = (ctc_tty_info *) tty->driver_data;
-
-       if (ctc_tty_paranoia_check(info, tty->name, "ctc_tty_write_room"))
-               return 0;
-       return CTC_TTY_XMIT_SIZE;
-}
-
-static int
-ctc_tty_chars_in_buffer(struct tty_struct *tty)
-{
-       ctc_tty_info *info = (ctc_tty_info *) tty->driver_data;
-
-       if (ctc_tty_paranoia_check(info, tty->name, "ctc_tty_chars_in_buffer"))
-               return 0;
-       return 0;
-}
-
-static void
-ctc_tty_flush_buffer(struct tty_struct *tty)
-{
-       ctc_tty_info *info;
-       unsigned long flags;
-
-       DBF_TEXT(trace, 4, __FUNCTION__);
-       if (!tty)
-               goto ex;
-       spin_lock_irqsave(&ctc_tty_lock, flags);
-       info = (ctc_tty_info *) tty->driver_data;
-       if (ctc_tty_paranoia_check(info, tty->name, "ctc_tty_flush_buffer")) {
-               spin_unlock_irqrestore(&ctc_tty_lock, flags);
-               goto ex;
-       }
-       skb_queue_purge(&info->tx_queue);
-       info->lsr |= UART_LSR_TEMT;
-       spin_unlock_irqrestore(&ctc_tty_lock, flags);
-       wake_up_interruptible(&tty->write_wait);
-       tty_wakeup(tty);
-ex:
-       DBF_TEXT_(trace, 2, "ex: %s ", __FUNCTION__);
-       return;
-}
-
-static void
-ctc_tty_flush_chars(struct tty_struct *tty)
-{
-       ctc_tty_info *info = (ctc_tty_info *) tty->driver_data;
-
-       DBF_TEXT(trace, 4, __FUNCTION__);
-       if (ctc_tty_shuttingdown)
-               return;
-       if (ctc_tty_paranoia_check(info, tty->name, "ctc_tty_flush_chars"))
-               return;
-       if (tty->stopped || tty->hw_stopped || skb_queue_empty(&info->tx_queue))
-               return;
-       tasklet_schedule(&info->tasklet);
-}
-
-/*
- * ------------------------------------------------------------
- * ctc_tty_throttle()
- *
- * This routine is called by the upper-layer tty layer to signal that
- * incoming characters should be throttled.
- * ------------------------------------------------------------
- */
-static void
-ctc_tty_throttle(struct tty_struct *tty)
-{
-       ctc_tty_info *info = (ctc_tty_info *) tty->driver_data;
-
-       DBF_TEXT(trace, 4, __FUNCTION__);
-       if (ctc_tty_paranoia_check(info, tty->name, "ctc_tty_throttle"))
-               return;
-       info->mcr &= ~UART_MCR_RTS;
-       if (I_IXOFF(tty))
-               ctc_tty_inject(info, STOP_CHAR(tty));
-       ctc_tty_transmit_status(info);
-}
-
-static void
-ctc_tty_unthrottle(struct tty_struct *tty)
-{
-       ctc_tty_info *info = (ctc_tty_info *) tty->driver_data;
-
-       DBF_TEXT(trace, 4, __FUNCTION__);
-       if (ctc_tty_paranoia_check(info, tty->name, "ctc_tty_unthrottle"))
-               return;
-       info->mcr |= UART_MCR_RTS;
-       if (I_IXOFF(tty))
-               ctc_tty_inject(info, START_CHAR(tty));
-       ctc_tty_transmit_status(info);
-}
-
-/*
- * ------------------------------------------------------------
- * ctc_tty_ioctl() and friends
- * ------------------------------------------------------------
- */
-
-/*
- * ctc_tty_get_lsr_info - get line status register info
- *
- * Purpose: Let user call ioctl() to get info when the UART physically
- *          is emptied.  On bus types like RS485, the transmitter must
- *          release the bus after transmitting. This must be done when
- *          the transmit shift register is empty, not be done when the
- *          transmit holding register is empty.  This functionality
- *          allows RS485 driver to be written in user space.
- */
-static int
-ctc_tty_get_lsr_info(ctc_tty_info * info, uint __user *value)
-{
-       u_char status;
-       uint result;
-       ulong flags;
-
-       DBF_TEXT(trace, 4, __FUNCTION__);
-       spin_lock_irqsave(&ctc_tty_lock, flags);
-       status = info->lsr;
-       spin_unlock_irqrestore(&ctc_tty_lock, flags);
-       result = ((status & UART_LSR_TEMT) ? TIOCSER_TEMT : 0);
-       put_user(result, value);
-       return 0;
-}
-
-
-static int ctc_tty_tiocmget(struct tty_struct *tty, struct file *file)
-{
-       ctc_tty_info *info = (ctc_tty_info *) tty->driver_data;
-       u_char control,
-        status;
-       uint result;
-       ulong flags;
-
-       DBF_TEXT(trace, 4, __FUNCTION__);
-       if (ctc_tty_paranoia_check(info, tty->name, "ctc_tty_ioctl"))
-               return -ENODEV;
-       if (tty->flags & (1 << TTY_IO_ERROR))
-               return -EIO;
-
-       control = info->mcr;
-       spin_lock_irqsave(&ctc_tty_lock, flags);
-       status = info->msr;
-       spin_unlock_irqrestore(&ctc_tty_lock, flags);
-       result = ((control & UART_MCR_RTS) ? TIOCM_RTS : 0)
-           | ((control & UART_MCR_DTR) ? TIOCM_DTR : 0)
-           | ((status & UART_MSR_DCD) ? TIOCM_CAR : 0)
-           | ((status & UART_MSR_RI) ? TIOCM_RNG : 0)
-           | ((status & UART_MSR_DSR) ? TIOCM_DSR : 0)
-           | ((status & UART_MSR_CTS) ? TIOCM_CTS : 0);
-       return result;
-}
-
-static int
-ctc_tty_tiocmset(struct tty_struct *tty, struct file *file,
-                unsigned int set, unsigned int clear)
-{
-       ctc_tty_info *info = (ctc_tty_info *) tty->driver_data;
-
-       DBF_TEXT(trace, 4, __FUNCTION__);
-       if (ctc_tty_paranoia_check(info, tty->name, "ctc_tty_ioctl"))
-               return -ENODEV;
-       if (tty->flags & (1 << TTY_IO_ERROR))
-               return -EIO;
-
-       if (set & TIOCM_RTS)
-               info->mcr |= UART_MCR_RTS;
-       if (set & TIOCM_DTR)
-               info->mcr |= UART_MCR_DTR;
-
-       if (clear & TIOCM_RTS)
-               info->mcr &= ~UART_MCR_RTS;
-       if (clear & TIOCM_DTR)
-               info->mcr &= ~UART_MCR_DTR;
-
-       if ((set | clear) & (TIOCM_RTS|TIOCM_DTR))
-               ctc_tty_transmit_status(info);
-       return 0;
-}
-
-static int
-ctc_tty_ioctl(struct tty_struct *tty, struct file *file,
-              uint cmd, ulong arg)
-{
-       ctc_tty_info *info = (ctc_tty_info *) tty->driver_data;
-       int error;
-       int retval;
-
-       DBF_TEXT(trace, 4, __FUNCTION__);
-       if (ctc_tty_paranoia_check(info, tty->name, "ctc_tty_ioctl"))
-               return -ENODEV;
-       if (tty->flags & (1 << TTY_IO_ERROR))
-               return -EIO;
-       switch (cmd) {
-               case TCSBRK:   /* SVID version: non-zero arg --> no break */
-#ifdef CTC_DEBUG_MODEM_IOCTL
-                       printk(KERN_DEBUG "%s%d ioctl TCSBRK\n", CTC_TTY_NAME, info->line);
-#endif
-                       retval = tty_check_change(tty);
-                       if (retval)
-                               return retval;
-                       tty_wait_until_sent(tty, 0);
-                       return 0;
-               case TCSBRKP:  /* support for POSIX tcsendbreak() */
-#ifdef CTC_DEBUG_MODEM_IOCTL
-                       printk(KERN_DEBUG "%s%d ioctl TCSBRKP\n", CTC_TTY_NAME, info->line);
-#endif
-                       retval = tty_check_change(tty);
-                       if (retval)
-                               return retval;
-                       tty_wait_until_sent(tty, 0);
-                       return 0;
-               case TIOCGSOFTCAR:
-#ifdef CTC_DEBUG_MODEM_IOCTL
-                       printk(KERN_DEBUG "%s%d ioctl TIOCGSOFTCAR\n", CTC_TTY_NAME,
-                              info->line);
-#endif
-                       error = put_user(C_CLOCAL(tty) ? 1 : 0, (ulong __user *) arg);
-                       return error;
-               case TIOCSSOFTCAR:
-#ifdef CTC_DEBUG_MODEM_IOCTL
-                       printk(KERN_DEBUG "%s%d ioctl TIOCSSOFTCAR\n", CTC_TTY_NAME,
-                              info->line);
-#endif
-                       error = get_user(arg, (ulong __user *) arg);
-                       if (error)
-                               return error;
-                       tty->termios->c_cflag =
-                           ((tty->termios->c_cflag & ~CLOCAL) |
-                            (arg ? CLOCAL : 0));
-                       return 0;
-               case TIOCSERGETLSR:     /* Get line status register */
-#ifdef CTC_DEBUG_MODEM_IOCTL
-                       printk(KERN_DEBUG "%s%d ioctl TIOCSERGETLSR\n", CTC_TTY_NAME,
-                              info->line);
-#endif
-                       if (access_ok(VERIFY_WRITE, (void __user *) arg, sizeof(uint)))
-                               return ctc_tty_get_lsr_info(info, (uint __user *) arg);
-                       else
-                               return -EFAULT;
-               default:
-#ifdef CTC_DEBUG_MODEM_IOCTL
-                       printk(KERN_DEBUG "UNKNOWN ioctl 0x%08x on %s%d\n", cmd,
-                              CTC_TTY_NAME, info->line);
-#endif
-                       return -ENOIOCTLCMD;
-       }
-       return 0;
-}
-
-static void
-ctc_tty_set_termios(struct tty_struct *tty, struct termios *old_termios)
-{
-       ctc_tty_info *info = (ctc_tty_info *) tty->driver_data;
-       unsigned int cflag = tty->termios->c_cflag;
-
-       DBF_TEXT(trace, 4, __FUNCTION__);
-       ctc_tty_change_speed(info);
-
-       /* Handle transition to B0 */
-       if ((old_termios->c_cflag & CBAUD) && !(cflag & CBAUD)) {
-               info->mcr &= ~(UART_MCR_DTR|UART_MCR_RTS);
-               ctc_tty_transmit_status(info);
-       }
-
-       /* Handle transition from B0 to other */
-       if (!(old_termios->c_cflag & CBAUD) && (cflag & CBAUD)) {
-               info->mcr |= UART_MCR_DTR;
-               if (!(tty->termios->c_cflag & CRTSCTS) ||
-                    !test_bit(TTY_THROTTLED, &tty->flags)) {
-                        info->mcr |= UART_MCR_RTS;
-                }
-               ctc_tty_transmit_status(info);
-       }
-
-       /* Handle turning off CRTSCTS */
-       if ((old_termios->c_cflag & CRTSCTS) &&
-            !(tty->termios->c_cflag & CRTSCTS))
-                tty->hw_stopped = 0;
-}
-
-/*
- * ------------------------------------------------------------
- * ctc_tty_open() and friends
- * ------------------------------------------------------------
- */
-static int
-ctc_tty_block_til_ready(struct tty_struct *tty, struct file *filp, ctc_tty_info *info)
-{
-       DECLARE_WAITQUEUE(wait, NULL);
-       int do_clocal = 0;
-       unsigned long flags;
-       int retval;
-
-       DBF_TEXT(trace, 4, __FUNCTION__);
-       /*
-        * If the device is in the middle of being closed, then block
-        * until it's done, and then try again.
-        */
-       if (tty_hung_up_p(filp) ||
-           (info->flags & CTC_ASYNC_CLOSING)) {
-               if (info->flags & CTC_ASYNC_CLOSING)
-                       wait_event(info->close_wait, 
-                                  !(info->flags & CTC_ASYNC_CLOSING));
-#ifdef MODEM_DO_RESTART
-               if (info->flags & CTC_ASYNC_HUP_NOTIFY)
-                       return -EAGAIN;
-               else
-                       return -ERESTARTSYS;
-#else
-               return -EAGAIN;
-#endif
-       }
-       /*
-        * If non-blocking mode is set, then make the check up front
-        * and then exit.
-        */
-       if ((filp->f_flags & O_NONBLOCK) ||
-           (tty->flags & (1 << TTY_IO_ERROR))) {
-               info->flags |= CTC_ASYNC_NORMAL_ACTIVE;
-               return 0;
-       }
-       if (tty->termios->c_cflag & CLOCAL)
-               do_clocal = 1;
-       /*
-        * Block waiting for the carrier detect and the line to become
-        * free (i.e., not in use by the callout).  While we are in
-        * this loop, info->count is dropped by one, so that
-        * ctc_tty_close() knows when to free things.  We restore it upon
-        * exit, either normal or abnormal.
-        */
-       retval = 0;
-       add_wait_queue(&info->open_wait, &wait);
-#ifdef CTC_DEBUG_MODEM_OPEN
-       printk(KERN_DEBUG "ctc_tty_block_til_ready before block: %s%d, count = %d\n",
-              CTC_TTY_NAME, info->line, info->count);
-#endif
-       spin_lock_irqsave(&ctc_tty_lock, flags);
-       if (!(tty_hung_up_p(filp)))
-               info->count--;
-       spin_unlock_irqrestore(&ctc_tty_lock, flags);
-       info->blocked_open++;
-       while (1) {
-               set_current_state(TASK_INTERRUPTIBLE);
-               if (tty_hung_up_p(filp) ||
-                   !(info->flags & CTC_ASYNC_INITIALIZED)) {
-#ifdef MODEM_DO_RESTART
-                       if (info->flags & CTC_ASYNC_HUP_NOTIFY)
-                               retval = -EAGAIN;
-                       else
-                               retval = -ERESTARTSYS;
-#else
-                       retval = -EAGAIN;
-#endif
-                       break;
-               }
-               if (!(info->flags & CTC_ASYNC_CLOSING) &&
-                   (do_clocal || (info->msr & UART_MSR_DCD))) {
-                       break;
-               }
-               if (signal_pending(current)) {
-                       retval = -ERESTARTSYS;
-                       break;
-               }
-#ifdef CTC_DEBUG_MODEM_OPEN
-               printk(KERN_DEBUG "ctc_tty_block_til_ready blocking: %s%d, count = %d\n",
-                      CTC_TTY_NAME, info->line, info->count);
-#endif
-               schedule();
-       }
-       current->state = TASK_RUNNING;
-       remove_wait_queue(&info->open_wait, &wait);
-       if (!tty_hung_up_p(filp))
-               info->count++;
-       info->blocked_open--;
-#ifdef CTC_DEBUG_MODEM_OPEN
-       printk(KERN_DEBUG "ctc_tty_block_til_ready after blocking: %s%d, count = %d\n",
-              CTC_TTY_NAME, info->line, info->count);
-#endif
-       if (retval)
-               return retval;
-       info->flags |= CTC_ASYNC_NORMAL_ACTIVE;
-       return 0;
-}
-
-/*
- * This routine is called whenever a serial port is opened.  It
- * enables interrupts for a serial port, linking in its async structure into
- * the IRQ chain.   It also performs the serial-specific
- * initialization for the tty structure.
- */
-static int
-ctc_tty_open(struct tty_struct *tty, struct file *filp)
-{
-       ctc_tty_info *info;
-       unsigned long saveflags;
-       int retval,
-        line;
-
-       DBF_TEXT(trace, 3, __FUNCTION__);
-       line = tty->index;
-       if (line < 0 || line > CTC_TTY_MAX_DEVICES)
-               return -ENODEV;
-       info = &driver->info[line];
-       if (ctc_tty_paranoia_check(info, tty->name, "ctc_tty_open"))
-               return -ENODEV;
-       if (!info->netdev)
-               return -ENODEV;
-#ifdef CTC_DEBUG_MODEM_OPEN
-       printk(KERN_DEBUG "ctc_tty_open %s, count = %d\n", tty->name,
-              info->count);
-#endif
-       spin_lock_irqsave(&ctc_tty_lock, saveflags);
-       info->count++;
-       tty->driver_data = info;
-       info->tty = tty;
-       spin_unlock_irqrestore(&ctc_tty_lock, saveflags);
-       /*
-        * Start up serial port
-        */
-       retval = ctc_tty_startup(info);
-       if (retval) {
-#ifdef CTC_DEBUG_MODEM_OPEN
-               printk(KERN_DEBUG "ctc_tty_open return after startup\n");
-#endif
-               return retval;
-       }
-       retval = ctc_tty_block_til_ready(tty, filp, info);
-       if (retval) {
-#ifdef CTC_DEBUG_MODEM_OPEN
-               printk(KERN_DEBUG "ctc_tty_open return after ctc_tty_block_til_ready \n");
-#endif
-               return retval;
-       }
-#ifdef CTC_DEBUG_MODEM_OPEN
-       printk(KERN_DEBUG "ctc_tty_open %s successful...\n", tty->name);
-#endif
-       return 0;
-}
-
-static void
-ctc_tty_close(struct tty_struct *tty, struct file *filp)
-{
-       ctc_tty_info *info = (ctc_tty_info *) tty->driver_data;
-       ulong flags;
-       ulong timeout;
-       DBF_TEXT(trace, 3, __FUNCTION__);
-       if (!info || ctc_tty_paranoia_check(info, tty->name, "ctc_tty_close"))
-               return;
-       spin_lock_irqsave(&ctc_tty_lock, flags);
-       if (tty_hung_up_p(filp)) {
-               spin_unlock_irqrestore(&ctc_tty_lock, flags);
-#ifdef CTC_DEBUG_MODEM_OPEN
-               printk(KERN_DEBUG "ctc_tty_close return after tty_hung_up_p\n");
-#endif
-               return;
-       }
-       if ((tty->count == 1) && (info->count != 1)) {
-               /*
-                * Uh, oh.  tty->count is 1, which means that the tty
-                * structure will be freed.  Info->count should always
-                * be one in these conditions.  If it's greater than
-                * one, we've got real problems, since it means the
-                * serial port won't be shutdown.
-                */
-               printk(KERN_ERR "ctc_tty_close: bad port count; tty->count is 1, "
-                      "info->count is %d\n", info->count);
-               info->count = 1;
-       }
-       if (--info->count < 0) {
-               printk(KERN_ERR "ctc_tty_close: bad port count for %s%d: %d\n",
-                      CTC_TTY_NAME, info->line, info->count);
-               info->count = 0;
-       }
-       if (info->count) {
-               local_irq_restore(flags);
-#ifdef CTC_DEBUG_MODEM_OPEN
-               printk(KERN_DEBUG "ctc_tty_close after info->count != 0\n");
-#endif
-               return;
-       }
-       info->flags |= CTC_ASYNC_CLOSING;
-       tty->closing = 1;
-       /*
-        * At this point we stop accepting input.  To do this, we
-        * disable the receive line status interrupts, and tell the
-        * interrupt driver to stop checking the data ready bit in the
-        * line status register.
-        */
-       if (info->flags & CTC_ASYNC_INITIALIZED) {
-               tty_wait_until_sent(tty, 30*HZ); /* 30 seconds timeout */
-               /*
-                * Before we drop DTR, make sure the UART transmitter
-                * has completely drained; this is especially
-                * important if there is a transmit FIFO!
-                */
-               timeout = jiffies + HZ;
-               while (!(info->lsr & UART_LSR_TEMT)) {
-                       spin_unlock_irqrestore(&ctc_tty_lock, flags);
-                       msleep(500);
-                       spin_lock_irqsave(&ctc_tty_lock, flags);
-                       if (time_after(jiffies,timeout))
-                               break;
-               }
-       }
-       ctc_tty_shutdown(info);
-       if (tty->driver->flush_buffer) {
-               skb_queue_purge(&info->tx_queue);
-               info->lsr |= UART_LSR_TEMT;
-       }
-       tty_ldisc_flush(tty);
-       info->tty = 0;
-       tty->closing = 0;
-       if (info->blocked_open) {
-               msleep_interruptible(500);
-               wake_up_interruptible(&info->open_wait);
-       }
-       info->flags &= ~(CTC_ASYNC_NORMAL_ACTIVE | CTC_ASYNC_CLOSING);
-       wake_up_interruptible(&info->close_wait);
-       spin_unlock_irqrestore(&ctc_tty_lock, flags);
-#ifdef CTC_DEBUG_MODEM_OPEN
-       printk(KERN_DEBUG "ctc_tty_close normal exit\n");
-#endif
-}
-
-/*
- * ctc_tty_hangup() --- called by tty_hangup() when a hangup is signaled.
- */
-static void
-ctc_tty_hangup(struct tty_struct *tty)
-{
-       ctc_tty_info *info = (ctc_tty_info *)tty->driver_data;
-       unsigned long saveflags;
-       DBF_TEXT(trace, 3, __FUNCTION__);
-       if (ctc_tty_paranoia_check(info, tty->name, "ctc_tty_hangup"))
-               return;
-       ctc_tty_shutdown(info);
-       info->count = 0;
-       info->flags &= ~CTC_ASYNC_NORMAL_ACTIVE;
-       spin_lock_irqsave(&ctc_tty_lock, saveflags);
-       info->tty = 0;
-       spin_unlock_irqrestore(&ctc_tty_lock, saveflags);
-       wake_up_interruptible(&info->open_wait);
-}
-
-
-/*
- * For all online tty's, try sending data to
- * the lower levels.
- */
-static void
-ctc_tty_task(unsigned long arg)
-{
-       ctc_tty_info *info = (void *)arg;
-       unsigned long saveflags;
-       int again;
-
-       DBF_TEXT(trace, 3, __FUNCTION__);
-       spin_lock_irqsave(&ctc_tty_lock, saveflags);
-       if ((!ctc_tty_shuttingdown) && info) {
-               again = ctc_tty_tint(info);
-               if (!again)
-                       info->lsr |= UART_LSR_TEMT;
-               again |= ctc_tty_readmodem(info);
-               if (again) {
-                       tasklet_schedule(&info->tasklet);
-               }
-       }
-       spin_unlock_irqrestore(&ctc_tty_lock, saveflags);
-}
-
-static struct tty_operations ctc_ops = {
-       .open = ctc_tty_open,
-       .close = ctc_tty_close,
-       .write = ctc_tty_write,
-       .flush_chars = ctc_tty_flush_chars,
-       .write_room = ctc_tty_write_room,
-       .chars_in_buffer = ctc_tty_chars_in_buffer,
-       .flush_buffer = ctc_tty_flush_buffer,
-       .ioctl = ctc_tty_ioctl,
-       .throttle = ctc_tty_throttle,
-       .unthrottle = ctc_tty_unthrottle,
-       .set_termios = ctc_tty_set_termios,
-       .hangup = ctc_tty_hangup,
-       .tiocmget = ctc_tty_tiocmget,
-       .tiocmset = ctc_tty_tiocmset,
-};
-
-int
-ctc_tty_init(void)
-{
-       int i;
-       ctc_tty_info *info;
-       struct tty_driver *device;
-
-       DBF_TEXT(trace, 2, __FUNCTION__);
-       driver = kmalloc(sizeof(ctc_tty_driver), GFP_KERNEL);
-       if (driver == NULL) {
-               printk(KERN_WARNING "Out of memory in ctc_tty_modem_init\n");
-               return -ENOMEM;
-       }
-       memset(driver, 0, sizeof(ctc_tty_driver));
-       device = alloc_tty_driver(CTC_TTY_MAX_DEVICES);
-       if (!device) {
-               kfree(driver);
-               printk(KERN_WARNING "Out of memory in ctc_tty_modem_init\n");
-               return -ENOMEM;
-       }
-
-       device->devfs_name = "ctc/" CTC_TTY_NAME;
-       device->name = CTC_TTY_NAME;
-       device->major = CTC_TTY_MAJOR;
-       device->minor_start = 0;
-       device->type = TTY_DRIVER_TYPE_SERIAL;
-       device->subtype = SERIAL_TYPE_NORMAL;
-       device->init_termios = tty_std_termios;
-       device->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
-       device->flags = TTY_DRIVER_REAL_RAW;
-       device->driver_name = "ctc_tty",
-       tty_set_operations(device, &ctc_ops);
-       if (tty_register_driver(device)) {
-               printk(KERN_WARNING "ctc_tty: Couldn't register serial-device\n");
-               put_tty_driver(device);
-               kfree(driver);
-               return -1;
-       }
-       driver->ctc_tty_device = device;
-       for (i = 0; i < CTC_TTY_MAX_DEVICES; i++) {
-               info = &driver->info[i];
-               init_MUTEX(&info->write_sem);
-               tasklet_init(&info->tasklet, ctc_tty_task,
-                               (unsigned long) info);
-               info->magic = CTC_ASYNC_MAGIC;
-               info->line = i;
-               info->tty = 0;
-               info->count = 0;
-               info->blocked_open = 0;
-               init_waitqueue_head(&info->open_wait);
-               init_waitqueue_head(&info->close_wait);
-               skb_queue_head_init(&info->tx_queue);
-               skb_queue_head_init(&info->rx_queue);
-               init_timer(&info->stoptimer);
-               info->stoptimer.function = ctc_tty_stopdev;
-               info->stoptimer.data = (unsigned long)info;
-               info->mcr = UART_MCR_RTS;
-       }
-       return 0;
-}
-
-int
-ctc_tty_register_netdev(struct net_device *dev) {
-       int ttynum;
-       char *err;
-       char *p;
-
-       DBF_TEXT(trace, 2, __FUNCTION__);
-       if ((!dev) || (!dev->name)) {
-               printk(KERN_WARNING
-                      "ctc_tty_register_netdev called "
-                      "with NULL dev or NULL dev-name\n");
-               return -1;
-       }
-
-       /*
-        *      If the name is a format string the caller wants us to
-        *      do a name allocation : format string must end with %d
-        */
-       if (strchr(dev->name, '%'))
-       {
-               int err = dev_alloc_name(dev, dev->name);       // dev->name is changed by this
-               if (err < 0) {
-                       printk(KERN_DEBUG "dev_alloc returned error %d\n", err);
-                       return err;
-               }
-
-       }
-
-       for (p = dev->name; p && ((*p < '0') || (*p > '9')); p++);
-       ttynum = simple_strtoul(p, &err, 0);
-       if ((ttynum < 0) || (ttynum >= CTC_TTY_MAX_DEVICES) ||
-           (err && *err)) {
-               printk(KERN_WARNING
-                      "ctc_tty_register_netdev called "
-                      "with number in name '%s'\n", dev->name);
-               return -1;
-       }
-       if (driver->info[ttynum].netdev) {
-               printk(KERN_WARNING
-                      "ctc_tty_register_netdev called "
-                      "for already registered device '%s'\n",
-                      dev->name);
-               return -1;
-       }
-       driver->info[ttynum].netdev = dev;
-       return 0;
-}
-
-void
-ctc_tty_unregister_netdev(struct net_device *dev) {
-       int i;
-       unsigned long saveflags;
-       ctc_tty_info *info = NULL;
-
-       DBF_TEXT(trace, 2, __FUNCTION__);
-       spin_lock_irqsave(&ctc_tty_lock, saveflags);
-       for (i = 0; i < CTC_TTY_MAX_DEVICES; i++)
-               if (driver->info[i].netdev == dev) {
-                       info = &driver->info[i];
-                       break;
-               }
-       if (info) {
-               info->netdev = NULL;
-               skb_queue_purge(&info->tx_queue);
-               skb_queue_purge(&info->rx_queue);
-       }
-       spin_unlock_irqrestore(&ctc_tty_lock, saveflags);
-}
-
-void
-ctc_tty_cleanup(void) {
-       unsigned long saveflags;
-       
-       DBF_TEXT(trace, 2, __FUNCTION__);
-       spin_lock_irqsave(&ctc_tty_lock, saveflags);
-       ctc_tty_shuttingdown = 1;
-       spin_unlock_irqrestore(&ctc_tty_lock, saveflags);
-       tty_unregister_driver(driver->ctc_tty_device);
-       put_tty_driver(driver->ctc_tty_device);
-       kfree(driver);
-       driver = NULL;
-}
diff --git a/drivers/s390/net/ctctty.h b/drivers/s390/net/ctctty.h
deleted file mode 100644 (file)
index 7254dc0..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * CTC / ESCON network driver, tty interface.
- *
- * Copyright (C) 2001 IBM Deutschland Entwicklung GmbH, IBM Corporation
- * Author(s): Fritz Elfert (elfert@de.ibm.com, felfert@millenux.com)
- *
- * 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.
- *
- * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#ifndef _CTCTTY_H_
-#define _CTCTTY_H_
-
-#include <linux/skbuff.h>
-#include <linux/netdevice.h>
-
-extern int  ctc_tty_register_netdev(struct net_device *);
-extern void ctc_tty_unregister_netdev(struct net_device *);
-extern void ctc_tty_netif_rx(struct sk_buff *);
-extern int  ctc_tty_init(void);
-extern void ctc_tty_cleanup(void);
-extern void ctc_tty_setcarrier(struct net_device *, int);
-
-#endif
index e9c10c0a30fc057c9c47c49caadd3e557bbbd6a9..321a40f33b5042c93db4baac5ef6300c1f7f1f68 100644 (file)
@@ -1057,7 +1057,6 @@ static void m32r_sio_console_write(struct console *co, const char *s,
 {
        struct uart_sio_port *up = &m32r_sio_ports[co->index];
        unsigned int ier;
-       int i;
 
        /*
         *      First save the UER then disable the interrupts
index 92be101feba70882baea621b27adde4df0f153b5..be9eec2257436c2152aecd9e0d20462f69902b2e 100644 (file)
@@ -48,7 +48,8 @@ config USB_STORAGE_FREECOM
 
 config USB_STORAGE_ISD200
        bool "ISD-200 USB/ATA Bridge support"
-       depends on USB_STORAGE && BLK_DEV_IDE
+       depends on USB_STORAGE
+       depends on BLK_DEV_IDE=y || BLK_DEV_IDE=USB_STORAGE
        ---help---
          Say Y here if you want to use USB Mass Store devices based
          on the In-Systems Design ISD-200 USB/ATA bridge.
index 9a6b5b39b88ebed5807771037e7aeba34228258f..387a18a47ac24b533037368e0928f874500658af 100644 (file)
@@ -2265,7 +2265,7 @@ static struct bin_attribute edid2_attr = {
 };
 
 
-static int radeonfb_pci_register (struct pci_dev *pdev,
+static int __devinit radeonfb_pci_register (struct pci_dev *pdev,
                                  const struct pci_device_id *ent)
 {
        struct fb_info *info;
index 8d8eadb648530add752890c8a38a6b6bcd74d62b..372aa177682798bc2544ad3f04032ad6a36dc7c9 100644 (file)
@@ -674,13 +674,19 @@ fb_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
                total_size = info->fix.smem_len;
 
        if (p > total_size)
-               return 0;
+               return -EFBIG;
 
-       if (count >= total_size)
+       if (count > total_size) {
+               err = -EFBIG;
                count = total_size;
+       }
+
+       if (count + p > total_size) {
+               if (!err)
+                       err = -ENOSPC;
 
-       if (count + p > total_size)
                count = total_size - p;
+       }
 
        buffer = kmalloc((count > PAGE_SIZE) ? PAGE_SIZE : count,
                         GFP_KERNEL);
@@ -722,7 +728,7 @@ fb_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
 
        kfree(buffer);
 
-       return (err) ? err : cnt;
+       return (cnt) ? cnt : err;
 }
 
 #ifdef CONFIG_KMOD
index 5fe197943deb4a1c1deea3fa3b71e716a93265b0..4e963930b50ae40ee358e19e999e12dc5b3db368 100644 (file)
@@ -73,8 +73,8 @@ static char *mode __devinitdata = NULL;
  * these flags allow the user to specify that requests for +ve sync
  * should be silently turned in -ve sync.
  */
-static int lowhsync __devinitdata = 0;
-static int lowvsync __devinitdata = 0;
+static int lowhsync;
+static int lowvsync;
 
 /*
  * The hardware state of the graphics card that isn't part of the
index 10e6b3aab9eaf18f7bd11824cfa63c12b88ba86e..0da624e6524f5e3be9c7c1406f5c9248613f7eaa 100644 (file)
@@ -73,7 +73,7 @@
 /* --------------------------------------------------------------------- */
 
 
-static char *mode_option __initdata = NULL;
+static char *mode_option __devinitdata = NULL;
 
 #ifdef MODULE
 
@@ -1545,7 +1545,7 @@ static int __devinit savage_map_mmio (struct fb_info *info)
        return 0;
 }
 
-static void __devinit savage_unmap_mmio (struct fb_info *info)
+static void savage_unmap_mmio (struct fb_info *info)
 {
        struct savagefb_par *par = info->par;
        DBG ("savage_unmap_mmio");
@@ -1597,7 +1597,7 @@ static int __devinit savage_map_video (struct fb_info *info,
        return 0;
 }
 
-static void __devinit savage_unmap_video (struct fb_info *info)
+static void savage_unmap_video (struct fb_info *info)
 {
        struct savagefb_par *par = info->par;
 
@@ -1614,7 +1614,7 @@ static void __devinit savage_unmap_video (struct fb_info *info)
        }
 }
 
-static int __devinit savage_init_hw (struct savagefb_par *par)
+static int savage_init_hw (struct savagefb_par *par)
 {
        unsigned char config1, m, n, n1, n2, sr8, cr3f, cr66 = 0, tmp;
 
index 2524629dc8350558a608e6eca0f67cf8f5b7c8b0..f9b5842c8d2de67e6f9258f65fad1fc6207b9242 100644 (file)
@@ -842,6 +842,12 @@ config TMPFS
 config HUGETLBFS
        bool "HugeTLB file system support"
        depends X86 || IA64 || PPC64 || SPARC64 || SUPERH || BROKEN
+       help
+         hugetlbfs is a filesystem backing for HugeTLB pages, based on
+         ramfs. For architectures that support it, say Y here and read
+         <file:Documentation/vm/hugetlbpage.txt> for details.
+
+         If unsure, say N.
 
 config HUGETLB_PAGE
        def_bool HUGETLBFS
index 4121bb55973933b8a407c6969edba4094dad8022..3a79d97ac234422c353ad6c37ab973d3363471bd 100644 (file)
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -712,7 +712,7 @@ static int de_thread(struct task_struct *tsk)
                attach_pid(current, PIDTYPE_PID,  current->pid);
                attach_pid(current, PIDTYPE_PGID, current->signal->pgrp);
                attach_pid(current, PIDTYPE_SID,  current->signal->session);
-               list_add_tail(&current->tasks, &init_task.tasks);
+               list_add_tail_rcu(&current->tasks, &init_task.tasks);
 
                current->group_leader = current;
                leader->group_leader = current;
index 14f5f6ea3e7230fb2621a620a3639ff136f1996d..c5ffa852396802d2f58cfae2474f500c4aeb002f 100644 (file)
@@ -767,6 +767,7 @@ int ext3_group_add(struct super_block *sb, struct ext3_new_group_data *input)
        if (input->group != sbi->s_groups_count) {
                ext3_warning(sb, __FUNCTION__,
                             "multiple resizers run on filesystem!");
+               unlock_super(sb);
                err = -EBUSY;
                goto exit_journal;
        }
index d2b66bad7d50458a9725d9aa5eabb47b017932b0..3ef739120dff32b1a772514be25167e546b7d3af 100644 (file)
@@ -650,7 +650,7 @@ static void nlmsvc_grant_callback(struct rpc_task *task, void *data)
        svc_wake_up(block->b_daemon);
 }
 
-void nlmsvc_grant_release(void *data)
+static void nlmsvc_grant_release(void *data)
 {
        struct nlm_rqst         *call = data;
 
index dda83d6cd48b17934797de3f6c9f65c52662f859..efad798824dc19913b7aace09dbee47b8c6ca6a7 100644 (file)
@@ -2230,7 +2230,12 @@ void steal_locks(fl_owner_t from)
 
        lock_kernel();
        j = 0;
-       rcu_read_lock();
+
+       /*
+        * We are not taking a ref to the file structures, so
+        * we need to acquire ->file_lock.
+        */
+       spin_lock(&files->file_lock);
        fdt = files_fdtable(files);
        for (;;) {
                unsigned long set;
@@ -2248,7 +2253,7 @@ void steal_locks(fl_owner_t from)
                        set >>= 1;
                }
        }
-       rcu_read_unlock();
+       spin_unlock(&files->file_lock);
        unlock_kernel();
 }
 EXPORT_SYMBOL(steal_locks);
index a23f3489416709288655f80603337f91ea94e398..cae74dd4c7f51f6bd674c5e61bad36c415cb4460 100644 (file)
@@ -128,15 +128,14 @@ struct inode_operations nfs4_dir_inode_operations = {
 static int
 nfs_opendir(struct inode *inode, struct file *filp)
 {
-       int res = 0;
+       int res;
 
        dfprintk(VFS, "NFS: opendir(%s/%ld)\n",
                        inode->i_sb->s_id, inode->i_ino);
 
        lock_kernel();
        /* Call generic open code in order to cache credentials */
-       if (!res)
-               res = nfs_open(inode, filp);
+       res = nfs_open(inode, filp);
        unlock_kernel();
        return res;
 }
index 0f583cb16ddbc4bad0b48787a41160a6a5b8c148..3c72b0c072839383950c59955da28c6c098897bf 100644 (file)
@@ -112,10 +112,9 @@ static void nfs_direct_write_complete(struct nfs_direct_req *dreq, struct inode
  */
 ssize_t nfs_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov, loff_t pos, unsigned long nr_segs)
 {
-       struct dentry *dentry = iocb->ki_filp->f_dentry;
-
        dprintk("NFS: nfs_direct_IO (%s) off/no(%Ld/%lu) EINVAL\n",
-                       dentry->d_name.name, (long long) pos, nr_segs);
+                       iocb->ki_filp->f_dentry->d_name.name,
+                       (long long) pos, nr_segs);
 
        return -EINVAL;
 }
@@ -468,7 +467,6 @@ static const struct rpc_call_ops nfs_commit_direct_ops = {
 static void nfs_direct_commit_schedule(struct nfs_direct_req *dreq)
 {
        struct nfs_write_data *data = dreq->commit_data;
-       struct rpc_task *task = &data->task;
 
        data->inode = dreq->inode;
        data->cred = dreq->ctx->cred;
@@ -489,7 +487,7 @@ static void nfs_direct_commit_schedule(struct nfs_direct_req *dreq)
        /* Note: task.tk_ops->rpc_release will free dreq->commit_data */
        dreq->commit_data = NULL;
 
-       dprintk("NFS: %5u initiated commit call\n", task->tk_pid);
+       dprintk("NFS: %5u initiated commit call\n", data->task.tk_pid);
 
        lock_kernel();
        rpc_execute(&data->task);
index f1df2c8d92591e4fa1474d66ecda7f887868fd86..fade02c15e6ef11a8575e6381b6f10445a1de375 100644 (file)
@@ -534,10 +534,9 @@ static int nfs_lock(struct file *filp, int cmd, struct file_lock *fl)
  */
 static int nfs_flock(struct file *filp, int cmd, struct file_lock *fl)
 {
-       struct inode * inode = filp->f_mapping->host;
-
        dprintk("NFS: nfs_flock(f=%s/%ld, t=%x, fl=%x)\n",
-                       inode->i_sb->s_id, inode->i_ino,
+                       filp->f_dentry->d_inode->i_sb->s_id,
+                       filp->f_dentry->d_inode->i_ino,
                        fl->fl_type, fl->fl_flags);
 
        /*
index 2f7656b911b66df6f03a96561c2f03534ffa4241..d0b991a92327f32941a454865c6aed187523d52e 100644 (file)
@@ -700,12 +700,9 @@ static int nfs_show_stats(struct seq_file *m, struct vfsmount *mnt)
        /*
         * Display superblock I/O counters
         */
-       for (cpu = 0; cpu < NR_CPUS; cpu++) {
+       for_each_possible_cpu(cpu) {
                struct nfs_iostats *stats;
 
-               if (!cpu_possible(cpu))
-                       continue;
-
                preempt_disable();
                stats = per_cpu_ptr(nfss->io_stats, cpu);
 
index 47ece1dd3c6705fa12282b31354c5d1558228319..d86c0db7b1e82a03bd003bc54aca52385e2c1bb7 100644 (file)
@@ -1218,7 +1218,7 @@ out:
        return status;
 }
 
-static void nfs4_intent_set_file(struct nameidata *nd, struct dentry *dentry, struct nfs4_state *state)
+static int nfs4_intent_set_file(struct nameidata *nd, struct dentry *dentry, struct nfs4_state *state)
 {
        struct file *filp;
 
@@ -1227,8 +1227,10 @@ static void nfs4_intent_set_file(struct nameidata *nd, struct dentry *dentry, st
                struct nfs_open_context *ctx;
                ctx = (struct nfs_open_context *)filp->private_data;
                ctx->state = state;
-       } else
-               nfs4_close_state(state, nd->intent.open.flags);
+               return 0;
+       }
+       nfs4_close_state(state, nd->intent.open.flags);
+       return PTR_ERR(filp);
 }
 
 struct dentry *
@@ -1835,7 +1837,7 @@ nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
                        nfs_setattr_update_inode(state->inode, sattr);
        }
        if (status == 0 && nd != NULL && (nd->flags & LOOKUP_OPEN))
-               nfs4_intent_set_file(nd, dentry, state);
+               status = nfs4_intent_set_file(nd, dentry, state);
        else
                nfs4_close_state(state, flags);
 out:
index c32c89d6d8dbed71f831e94f8aa0c67eade8cfc1..53ec28c367770d5704ecdb24f7549470cb0ccf6a 100644 (file)
--- a/fs/open.c
+++ b/fs/open.c
@@ -331,7 +331,10 @@ out:
 
 asmlinkage long sys_ftruncate(unsigned int fd, unsigned long length)
 {
-       return do_sys_ftruncate(fd, length, 1);
+       long ret = do_sys_ftruncate(fd, length, 1);
+       /* avoid REGPARM breakage on x86: */
+       prevent_tail_call(ret);
+       return ret;
 }
 
 /* LFS versions of truncate are only needed on 32 bit machines */
@@ -343,7 +346,10 @@ asmlinkage long sys_truncate64(const char __user * path, loff_t length)
 
 asmlinkage long sys_ftruncate64(unsigned int fd, loff_t length)
 {
-       return do_sys_ftruncate(fd, length, 0);
+       long ret = do_sys_ftruncate(fd, length, 0);
+       /* avoid REGPARM breakage on x86: */
+       prevent_tail_call(ret);
+       return ret;
 }
 #endif
 
@@ -1093,20 +1099,30 @@ long do_sys_open(int dfd, const char __user *filename, int flags, int mode)
 
 asmlinkage long sys_open(const char __user *filename, int flags, int mode)
 {
+       long ret;
+
        if (force_o_largefile())
                flags |= O_LARGEFILE;
 
-       return do_sys_open(AT_FDCWD, filename, flags, mode);
+       ret = do_sys_open(AT_FDCWD, filename, flags, mode);
+       /* avoid REGPARM breakage on x86: */
+       prevent_tail_call(ret);
+       return ret;
 }
 EXPORT_SYMBOL_GPL(sys_open);
 
 asmlinkage long sys_openat(int dfd, const char __user *filename, int flags,
                           int mode)
 {
+       long ret;
+
        if (force_o_largefile())
                flags |= O_LARGEFILE;
 
-       return do_sys_open(dfd, filename, flags, mode);
+       ret = do_sys_open(dfd, filename, flags, mode);
+       /* avoid REGPARM breakage on x86: */
+       prevent_tail_call(ret);
+       return ret;
 }
 EXPORT_SYMBOL_GPL(sys_openat);
 
index f3b6af071722e8aca189d1aa5d2a82dff95dc378..45ae7dd3c650399baafe5c8d20cc3b6734181d7a 100644 (file)
@@ -372,6 +372,7 @@ static char *make_block_name(struct gendisk *disk)
        char *name;
        static char *block_str = "block:";
        int size;
+       char *s;
 
        size = strlen(block_str) + strlen(disk->disk_name) + 1;
        name = kmalloc(size, GFP_KERNEL);
@@ -379,6 +380,10 @@ static char *make_block_name(struct gendisk *disk)
                return NULL;
        strcpy(name, block_str);
        strcat(name, disk->disk_name);
+       /* ewww... some of these buggers have / in name... */
+       s = strchr(name, '/');
+       if (s)
+               *s = '!';
        return name;
 }
 
index a3a3eecef68946110f8f2641959af78eff7be428..6cc77dc3f3ff79c49fa7d4ce89360b595995d839 100644 (file)
@@ -297,16 +297,20 @@ static int proc_fd_link(struct inode *inode, struct dentry **dentry, struct vfsm
 
        files = get_files_struct(task);
        if (files) {
-               rcu_read_lock();
+               /*
+                * We are not taking a ref to the file structure, so we must
+                * hold ->file_lock.
+                */
+               spin_lock(&files->file_lock);
                file = fcheck_files(files, fd);
                if (file) {
                        *mnt = mntget(file->f_vfsmnt);
                        *dentry = dget(file->f_dentry);
-                       rcu_read_unlock();
+                       spin_unlock(&files->file_lock);
                        put_files_struct(files);
                        return 0;
                }
-               rcu_read_unlock();
+               spin_unlock(&files->file_lock);
                put_files_struct(files);
        }
        return -ENOENT;
@@ -1523,7 +1527,12 @@ static struct dentry *proc_lookupfd(struct inode * dir, struct dentry * dentry,
        if (!files)
                goto out_unlock;
        inode->i_mode = S_IFLNK;
-       rcu_read_lock();
+
+       /*
+        * We are not taking a ref to the file structure, so we must
+        * hold ->file_lock.
+        */
+       spin_lock(&files->file_lock);
        file = fcheck_files(files, fd);
        if (!file)
                goto out_unlock2;
@@ -1531,7 +1540,7 @@ static struct dentry *proc_lookupfd(struct inode * dir, struct dentry * dentry,
                inode->i_mode |= S_IRUSR | S_IXUSR;
        if (file->f_mode & 2)
                inode->i_mode |= S_IWUSR | S_IXUSR;
-       rcu_read_unlock();
+       spin_unlock(&files->file_lock);
        put_files_struct(files);
        inode->i_op = &proc_pid_link_inode_operations;
        inode->i_size = 64;
@@ -1541,7 +1550,7 @@ static struct dentry *proc_lookupfd(struct inode * dir, struct dentry * dentry,
        return NULL;
 
 out_unlock2:
-       rcu_read_unlock();
+       spin_unlock(&files->file_lock);
        put_files_struct(files);
 out_unlock:
        iput(inode);
index 8d57e89924a68990efa6a72d279dd35efa0fc7a7..0559e7577a04164ececffdcdbd57089d980dd586 100644 (file)
@@ -50,7 +50,8 @@ static int page_cache_pipe_buf_steal(struct pipe_inode_info *info,
        struct page *page = buf->page;
        struct address_space *mapping = page_mapping(page);
 
-       WARN_ON(!PageLocked(page));
+       lock_page(page);
+
        WARN_ON(!PageUptodate(page));
 
        /*
@@ -65,8 +66,10 @@ static int page_cache_pipe_buf_steal(struct pipe_inode_info *info,
        if (PagePrivate(page))
                try_to_release_page(page, mapping_gfp_mask(mapping));
 
-       if (!remove_mapping(mapping, page))
+       if (!remove_mapping(mapping, page)) {
+               unlock_page(page);
                return 1;
+       }
 
        buf->flags |= PIPE_BUF_FLAG_STOLEN | PIPE_BUF_FLAG_LRU;
        return 0;
@@ -145,8 +148,8 @@ static struct pipe_buf_operations page_cache_pipe_buf_ops = {
  * pipe buffer operations. Otherwise very similar to the regular pipe_writev().
  */
 static ssize_t move_to_pipe(struct pipe_inode_info *pipe, struct page **pages,
-                           int nr_pages, unsigned long offset,
-                           unsigned long len, unsigned int flags)
+                           int nr_pages, unsigned long len,
+                           unsigned int offset, unsigned int flags)
 {
        int ret, do_wakeup, i;
 
@@ -243,14 +246,16 @@ __generic_file_splice_read(struct file *in, loff_t *ppos,
                           unsigned int flags)
 {
        struct address_space *mapping = in->f_mapping;
-       unsigned int offset, nr_pages;
+       unsigned int loff, offset, nr_pages;
        struct page *pages[PIPE_BUFFERS];
        struct page *page;
-       pgoff_t index;
+       pgoff_t index, end_index;
+       loff_t isize;
+       size_t bytes;
        int i, error;
 
        index = *ppos >> PAGE_CACHE_SHIFT;
-       offset = *ppos & ~PAGE_CACHE_MASK;
+       loff = offset = *ppos & ~PAGE_CACHE_MASK;
        nr_pages = (len + offset + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
 
        if (nr_pages > PIPE_BUFFERS)
@@ -268,21 +273,23 @@ __generic_file_splice_read(struct file *in, loff_t *ppos,
         * Now fill in the holes:
         */
        error = 0;
+       bytes = 0;
        for (i = 0; i < nr_pages; i++, index++) {
+               unsigned int this_len;
+
+               if (!len)
+                       break;
+
+               /*
+                * this_len is the max we'll use from this page
+                */
+               this_len = min(len, PAGE_CACHE_SIZE - loff);
 find_page:
                /*
                 * lookup the page for this index
                 */
                page = find_get_page(mapping, index);
                if (!page) {
-                       /*
-                        * If in nonblock mode then dont block on
-                        * readpage (we've kicked readahead so there
-                        * will be asynchronous progress):
-                        */
-                       if (flags & SPLICE_F_NONBLOCK)
-                               break;
-
                        /*
                         * page didn't exist, allocate one
                         */
@@ -304,6 +311,13 @@ find_page:
                 * If the page isn't uptodate, we may need to start io on it
                 */
                if (!PageUptodate(page)) {
+                       /*
+                        * If in nonblock mode then dont block on waiting
+                        * for an in-flight io page
+                        */
+                       if (flags & SPLICE_F_NONBLOCK)
+                               break;
+
                        lock_page(page);
 
                        /*
@@ -336,13 +350,43 @@ readpage:
                                        goto find_page;
                                break;
                        }
+
+                       /*
+                        * i_size must be checked after ->readpage().
+                        */
+                       isize = i_size_read(mapping->host);
+                       end_index = (isize - 1) >> PAGE_CACHE_SHIFT;
+                       if (unlikely(!isize || index > end_index)) {
+                               page_cache_release(page);
+                               break;
+                       }
+
+                       /*
+                        * if this is the last page, see if we need to shrink
+                        * the length and stop
+                        */
+                       if (end_index == index) {
+                               loff = PAGE_CACHE_SIZE - (isize & ~PAGE_CACHE_MASK);
+                               if (bytes + loff > isize) {
+                                       page_cache_release(page);
+                                       break;
+                               }
+                               /*
+                                * force quit after adding this page
+                                */
+                               nr_pages = i;
+                               this_len = min(this_len, loff);
+                       }
                }
 fill_it:
                pages[i] = page;
+               bytes += this_len;
+               len -= this_len;
+               loff = 0;
        }
 
        if (i)
-               return move_to_pipe(pipe, pages, i, offset, len, flags);
+               return move_to_pipe(pipe, pages, i, bytes, offset, flags);
 
        return error;
 }
@@ -369,17 +413,20 @@ ssize_t generic_file_splice_read(struct file *in, loff_t *ppos,
        while (len) {
                ret = __generic_file_splice_read(in, ppos, pipe, len, flags);
 
-               if (ret <= 0)
+               if (ret < 0)
                        break;
+               else if (!ret) {
+                       if (spliced)
+                               break;
+                       if (flags & SPLICE_F_NONBLOCK) {
+                               ret = -EAGAIN;
+                               break;
+                       }
+               }
 
                *ppos += ret;
                len -= ret;
                spliced += ret;
-
-               if (!(flags & SPLICE_F_NONBLOCK))
-                       continue;
-               ret = -EAGAIN;
-               break;
        }
 
        if (spliced)
@@ -474,14 +521,12 @@ static int pipe_to_file(struct pipe_inode_info *info, struct pipe_buffer *buf,
        if (sd->flags & SPLICE_F_MOVE) {
                /*
                 * If steal succeeds, buf->page is now pruned from the vm
-                * side (LRU and page cache) and we can reuse it.
+                * side (LRU and page cache) and we can reuse it. The page
+                * will also be looked on successful return.
                 */
                if (buf->ops->steal(info, buf))
                        goto find_page;
 
-               /*
-                * this will also set the page locked
-                */
                page = buf->page;
                if (add_to_page_cache(page, mapping, index, gfp_mask))
                        goto find_page;
@@ -490,15 +535,27 @@ static int pipe_to_file(struct pipe_inode_info *info, struct pipe_buffer *buf,
                        lru_cache_add(page);
        } else {
 find_page:
-               ret = -ENOMEM;
-               page = find_or_create_page(mapping, index, gfp_mask);
-               if (!page)
-                       goto out_nomem;
+               page = find_lock_page(mapping, index);
+               if (!page) {
+                       ret = -ENOMEM;
+                       page = page_cache_alloc_cold(mapping);
+                       if (unlikely(!page))
+                               goto out_nomem;
+
+                       /*
+                        * This will also lock the page
+                        */
+                       ret = add_to_page_cache_lru(page, mapping, index,
+                                                   gfp_mask);
+                       if (unlikely(ret))
+                               goto out;
+               }
 
                /*
-                * If the page is uptodate, it is also locked. If it isn't
-                * uptodate, we can mark it uptodate if we are filling the
-                * full page. Otherwise we need to read it in first...
+                * We get here with the page locked. If the page is also
+                * uptodate, we don't need to do more. If it isn't, we
+                * may need to bring it in if we are not going to overwrite
+                * the full page.
                 */
                if (!PageUptodate(page)) {
                        if (sd->len < PAGE_CACHE_SIZE) {
@@ -520,10 +577,8 @@ find_page:
                                        ret = -EIO;
                                        goto out;
                                }
-                       } else {
-                               WARN_ON(!PageLocked(page));
+                       } else
                                SetPageUptodate(page);
-                       }
                }
        }
 
@@ -552,10 +607,10 @@ find_page:
        mark_page_accessed(page);
        balance_dirty_pages_ratelimited(mapping);
 out:
-       if (!(buf->flags & PIPE_BUF_FLAG_STOLEN)) {
+       if (!(buf->flags & PIPE_BUF_FLAG_STOLEN))
                page_cache_release(page);
-               unlock_page(page);
-       }
+
+       unlock_page(page);
 out_nomem:
        buf->ops->unmap(info, buf);
        return ret;
@@ -687,22 +742,26 @@ generic_file_splice_write(struct pipe_inode_info *pipe, struct file *out,
        ssize_t ret;
 
        ret = move_from_pipe(pipe, out, ppos, len, flags, pipe_to_file);
-
-       /*
-        * If file or inode is SYNC and we actually wrote some data, sync it.
-        */
-       if (unlikely((out->f_flags & O_SYNC) || IS_SYNC(mapping->host))
-           && ret > 0) {
+       if (ret > 0) {
                struct inode *inode = mapping->host;
-               int err;
 
-               mutex_lock(&inode->i_mutex);
-               err = generic_osync_inode(mapping->host, mapping,
-                                         OSYNC_METADATA|OSYNC_DATA);
-               mutex_unlock(&inode->i_mutex);
+               *ppos += ret;
+
+               /*
+                * If file or inode is SYNC and we actually wrote some data,
+                * sync it.
+                */
+               if (unlikely((out->f_flags & O_SYNC) || IS_SYNC(inode))) {
+                       int err;
+
+                       mutex_lock(&inode->i_mutex);
+                       err = generic_osync_inode(inode, mapping,
+                                                 OSYNC_METADATA|OSYNC_DATA);
+                       mutex_unlock(&inode->i_mutex);
 
-               if (err)
-                       ret = err;
+                       if (err)
+                               ret = err;
+               }
        }
 
        return ret;
@@ -904,6 +963,7 @@ static long do_splice(struct file *in, loff_t __user *off_in,
 {
        struct pipe_inode_info *pipe;
        loff_t offset, *off;
+       long ret;
 
        pipe = in->f_dentry->d_inode->i_pipe;
        if (pipe) {
@@ -918,7 +978,12 @@ static long do_splice(struct file *in, loff_t __user *off_in,
                } else
                        off = &out->f_pos;
 
-               return do_splice_from(pipe, out, off, len, flags);
+               ret = do_splice_from(pipe, out, off, len, flags);
+
+               if (off_out && copy_to_user(off_out, off, sizeof(loff_t)))
+                       ret = -EFAULT;
+
+               return ret;
        }
 
        pipe = out->f_dentry->d_inode->i_pipe;
@@ -934,7 +999,12 @@ static long do_splice(struct file *in, loff_t __user *off_in,
                } else
                        off = &in->f_pos;
 
-               return do_splice_to(in, off, pipe, len, flags);
+               ret = do_splice_to(in, off, pipe, len, flags);
+
+               if (off_in && copy_to_user(off_in, off, sizeof(loff_t)))
+                       ret = -EFAULT;
+
+               return ret;
        }
 
        return -EINVAL;
@@ -979,7 +1049,9 @@ static int link_pipe(struct pipe_inode_info *ipipe,
                     size_t len, unsigned int flags)
 {
        struct pipe_buffer *ibuf, *obuf;
-       int ret = 0, do_wakeup = 0, i;
+       int ret, do_wakeup, i, ipipe_first;
+
+       ret = do_wakeup = ipipe_first = 0;
 
        /*
         * Potential ABBA deadlock, work around it by ordering lock
@@ -987,6 +1059,7 @@ static int link_pipe(struct pipe_inode_info *ipipe,
         * could deadlock (one doing tee from A -> B, the other from B -> A).
         */
        if (ipipe->inode < opipe->inode) {
+               ipipe_first = 1;
                mutex_lock(&ipipe->inode->i_mutex);
                mutex_lock(&opipe->inode->i_mutex);
        } else {
@@ -1035,9 +1108,11 @@ static int link_pipe(struct pipe_inode_info *ipipe,
 
                        /*
                         * We have input available, but no output room.
-                        * If we already copied data, return that.
+                        * If we already copied data, return that. If we
+                        * need to drop the opipe lock, it must be ordered
+                        * last to avoid deadlocks.
                         */
-                       if (flags & SPLICE_F_NONBLOCK) {
+                       if ((flags & SPLICE_F_NONBLOCK) || !ipipe_first) {
                                if (!ret)
                                        ret = -EAGAIN;
                                break;
@@ -1071,7 +1146,12 @@ static int link_pipe(struct pipe_inode_info *ipipe,
                        if (ret)
                                break;
                }
-               if (flags & SPLICE_F_NONBLOCK) {
+               /*
+                * pipe_wait() drops the ipipe mutex. To avoid deadlocks
+                * with another process, we can only safely do that if
+                * the ipipe lock is ordered last.
+                */
+               if ((flags & SPLICE_F_NONBLOCK) || ipipe_first) {
                        if (!ret)
                                ret = -EAGAIN;
                        break;
index 65ac305c2d457fae139048b71093bc34972e8b4c..ee8dfea549bc324239b1e60f0cdd9ef984e75dfb 100644 (file)
 #define __ARM_NR_usr32                 (__ARM_NR_BASE+4)
 #define __ARM_NR_set_tls               (__ARM_NR_BASE+5)
 
+/*
+ * The following syscalls are obsolete and no longer available for EABI.
+ */
+#if defined(__ARM_EABI__)
+#undef __NR_time
+#undef __NR_umount
+#undef __NR_stime
+#undef __NR_alarm
+#undef __NR_utime
+#undef __NR_getrlimit
+#undef __NR_select
+#undef __NR_readdir
+#undef __NR_mmap
+#undef __NR_socketcall
+#undef __NR_syscall
+#undef __NR_ipc
+#endif
+
 #define __sys2(x) #x
 #define __sys1(x) __sys2(x)
 
index 22d80ece95cb48de54ed1dea6e0c9475d10935ba..4ddce5296a788a2b6442700f4126bb636cd14df9 100644 (file)
@@ -183,6 +183,7 @@ static __inline__ int atomic_add_return(int i, atomic_t *v)
 {
        int __i;
 #ifdef CONFIG_M386
+       unsigned long flags;
        if(unlikely(boot_cpu_data.x86==3))
                goto no_xadd;
 #endif
@@ -196,10 +197,10 @@ static __inline__ int atomic_add_return(int i, atomic_t *v)
 
 #ifdef CONFIG_M386
 no_xadd: /* Legacy 386 processor */
-       local_irq_disable();
+       local_irq_save(flags);
        __i = atomic_read(v);
        atomic_set(v, i + __i);
-       local_irq_enable();
+       local_irq_restore(flags);
        return i + __i;
 #endif
 }
index 5c0b5876b9318cf7e41af251c367597776330569..b44bfc6239cb51debea374b173e58b5469f8ff1c 100644 (file)
@@ -71,6 +71,7 @@
 #define X86_FEATURE_P4         (3*32+ 7) /* P4 */
 #define X86_FEATURE_CONSTANT_TSC (3*32+ 8) /* TSC ticks at a constant rate */
 #define X86_FEATURE_UP         (3*32+ 9) /* smp kernel running on up */
+#define X86_FEATURE_FXSAVE_LEAK (3*32+10) /* FXSAVE leaks FOP/FIP/FOP */
 
 /* Intel-defined CPU features, CPUID level 0x00000001 (ecx), word 4 */
 #define X86_FEATURE_XMM3       (4*32+ 0) /* Streaming SIMD Extensions-3 */
index 152d0baa576a675b39bfa408a6b69f670e8ad118..7b1f01191e7063df3ab056dfdb17e6de0bcd828f 100644 (file)
@@ -13,6 +13,7 @@
 
 #include <linux/sched.h>
 #include <linux/init.h>
+#include <linux/kernel_stat.h>
 #include <asm/processor.h>
 #include <asm/sigcontext.h>
 #include <asm/user.h>
@@ -38,17 +39,38 @@ extern void init_fpu(struct task_struct *);
 extern void kernel_fpu_begin(void);
 #define kernel_fpu_end() do { stts(); preempt_enable(); } while(0)
 
+/* We need a safe address that is cheap to find and that is already
+   in L1 during context switch. The best choices are unfortunately
+   different for UP and SMP */
+#ifdef CONFIG_SMP
+#define safe_address (__per_cpu_offset[0])
+#else
+#define safe_address (kstat_cpu(0).cpustat.user)
+#endif
+
 /*
  * These must be called with preempt disabled
  */
 static inline void __save_init_fpu( struct task_struct *tsk )
 {
+       /* Use more nops than strictly needed in case the compiler
+          varies code */
        alternative_input(
-               "fnsave %1 ; fwait ;" GENERIC_NOP2,
-               "fxsave %1 ; fnclex",
+               "fnsave %[fx] ;fwait;" GENERIC_NOP8 GENERIC_NOP4,
+               "fxsave %[fx]\n"
+               "bt $7,%[fsw] ; jc 1f ; fnclex\n1:",
                X86_FEATURE_FXSR,
-               "m" (tsk->thread.i387.fxsave)
-               :"memory");
+               [fx] "m" (tsk->thread.i387.fxsave),
+               [fsw] "m" (tsk->thread.i387.fxsave.swd) : "memory");
+       /* AMD K7/K8 CPUs don't save/restore FDP/FIP/FOP unless an exception
+          is pending.  Clear the x87 state here by setting it to fixed
+          values. __per_cpu_offset[0] is a random variable that should be in L1 */
+       alternative_input(
+               GENERIC_NOP8 GENERIC_NOP2,
+               "emms\n\t"              /* clear stack tags */
+               "fildl %[addr]",        /* set F?P to defined value */
+               X86_FEATURE_FXSAVE_LEAK,
+               [addr] "m" (safe_address));
        task_thread_info(tsk)->status &= ~TS_USEDFPU;
 }
 
index b7f4d8aaeb469b0409103dd8057e3b6f80c2cc8f..1a1aa17edd33fe737d1035676d756421b93a1fe8 100644 (file)
        push    r13
        mvfachi r13
        push    r13
+       ldi     r13, #0
+       push    r13             ; dummy push acc1h
+       push    r13             ; dummy push acc1l
 #else
 #error unknown isa configuration
 #endif
        pop     r13
        mvtaclo r13, a1
 #elif defined(CONFIG_ISA_M32R2) || defined(CONFIG_ISA_M32R)
+       pop     r13             ; dummy pop acc1h
+       pop     r13             ; dummy pop acc1l
        pop     r13
        mvtachi r13
        pop     r13
index 1d3c25d61bcb2399e6f4def20b7ac16b2a911fd0..031369a7afc85ed732613f483906b826707afecb 100644 (file)
 /* Power Control of MMC and CF */
 #define PLD_CPCR               __reg16(PLD_BASE + 0x14000)
 
-
-/*==== ICU ====*/
-#define  M32R_IRQ_PC104        (5)   /* INT4(PC/104) */
-#define  M32R_IRQ_I2C          (28)  /* I2C-BUS     */
-#define  PLD_IRQ_CFIREQ       (6)  /* INT5 CFC Card Interrupt */
-#define  PLD_IRQ_CFC_INSERT   (7)  /* INT6 CFC Card Insert */
-#define  PLD_IRQ_IDEIREQ      (8)  /* INT7 IDE Interrupt   */
-#define  PLD_IRQ_MMCCARD      (43)  /* MMC Card Insert */
-#define  PLD_IRQ_MMCIRQ       (44)  /* MMC Transfer Done */
-
+/* ICU */
+#define M32R_IRQ_PC104         (5)     /* INT4(PC/104) */
+#define M32R_IRQ_I2C           (28)    /* I2C-BUS */
+#define PLD_IRQ_CFIREQ         (6)     /* INT5 CFC Card Interrupt */
+#define PLD_IRQ_CFC_INSERT     (7)     /* INT6 CFC Card Insert & Eject */
+#define PLD_IRQ_IDEIREQ                (8)     /* INT7 IDE Interrupt */
+#define PLD_IRQ_MMCCARD                (43)    /* MMC Card Insert */
+#define PLD_IRQ_MMCIRQ         (44)    /* MMC Transfer Done */
 
 #if 0
 /* LED Control
@@ -97,7 +95,6 @@
 #define PLD_CRC16ADATA         __reg16(PLD_BASE + 0x18008)
 #define PLD_CRC16AINDATA       __reg16(PLD_BASE + 0x1800a)
 
-
 #if 0
 /* RTC */
 #define PLD_RTCCR              __reg16(PLD_BASE + 0x1c000)
 
 #endif
 
+/* Reset Control */
+#define PLD_REBOOT             __reg16(PLD_BASE + 0x38000)
+
 #endif /* _MAPPI3_PLD.H */
index 0d058b2d844e468ac6d6ac448a553dfa1d752528..53c792452dfc0c036538230f69fce24406d119f9 100644 (file)
 #define PT_ACC1L       18
 #define PT_ACCH                PT_ACC0H
 #define PT_ACCL                PT_ACC0L
+#elif defined(CONFIG_ISA_M32R2) || defined(CONFIG_ISA_M32R)
+#define PT_ACCH                15
+#define PT_ACCL                16
+#define PT_DUMMY_ACC1H 17
+#define PT_DUMMY_ACC1L 18
+#else
+#error unknown isa conifiguration
+#endif
 #define PT_PSW         19
 #define PT_BPC         20
 #define PT_BBPSW       21
 #define PT_LR          25
 #define PT_SPI         26
 #define PT_ORIGR0      27
-#elif defined(CONFIG_ISA_M32R2) || defined(CONFIG_ISA_M32R)
-#define PT_ACCH                15
-#define PT_ACCL                16
-#define PT_PSW         17
-#define PT_BPC         18
-#define PT_BBPSW       19
-#define PT_BBPC                20
-#define PT_SPU         21
-#define PT_FP          22
-#define PT_LR          23
-#define PT_SPI         24
-#define PT_ORIGR0      25
-#else
-#error unknown isa conifiguration
-#endif
 
 /* virtual pt_reg entry for gdb */
 #define PT_PC          30
@@ -121,6 +114,8 @@ struct pt_regs {
 #elif defined(CONFIG_ISA_M32R2) || defined(CONFIG_ISA_M32R)
        unsigned long acch;
        unsigned long accl;
+       unsigned long dummy_acc1h;
+       unsigned long dummy_acc1l;
 #else
 #error unknown isa configuration
 #endif
index bf447c52a0a126c8a26719885d5e081f73c3c728..81750edc8916267e035dcf47484afe001910c74a 100644 (file)
@@ -9,7 +9,7 @@
  * SMP- and interrupt-safe semaphores..
  *
  * Copyright (C) 1996  Linus Torvalds
- * Copyright (C) 2004  Hirokazu Takata <takata at linux-m32r.org>
+ * Copyright (C) 2004, 2006  Hirokazu Takata <takata at linux-m32r.org>
  */
 
 #include <linux/config.h>
@@ -77,27 +77,8 @@ asmlinkage void __up(struct semaphore * sem);
  */
 static inline void down(struct semaphore * sem)
 {
-       unsigned long flags;
-       long count;
-
        might_sleep();
-       local_irq_save(flags);
-       __asm__ __volatile__ (
-               "# down                         \n\t"
-               DCACHE_CLEAR("%0", "r4", "%1")
-               M32R_LOCK" %0, @%1;             \n\t"
-               "addi   %0, #-1;                \n\t"
-               M32R_UNLOCK" %0, @%1;           \n\t"
-               : "=&r" (count)
-               : "r" (&sem->count)
-               : "memory"
-#ifdef CONFIG_CHIP_M32700_TS1
-               , "r4"
-#endif /* CONFIG_CHIP_M32700_TS1 */
-       );
-       local_irq_restore(flags);
-
-       if (unlikely(count < 0))
+       if (unlikely(atomic_dec_return(&sem->count) < 0))
                __down(sem);
 }
 
@@ -107,28 +88,10 @@ static inline void down(struct semaphore * sem)
  */
 static inline int down_interruptible(struct semaphore * sem)
 {
-       unsigned long flags;
-       long count;
        int result = 0;
 
        might_sleep();
-       local_irq_save(flags);
-       __asm__ __volatile__ (
-               "# down_interruptible           \n\t"
-               DCACHE_CLEAR("%0", "r4", "%1")
-               M32R_LOCK" %0, @%1;             \n\t"
-               "addi   %0, #-1;                \n\t"
-               M32R_UNLOCK" %0, @%1;           \n\t"
-               : "=&r" (count)
-               : "r" (&sem->count)
-               : "memory"
-#ifdef CONFIG_CHIP_M32700_TS1
-               , "r4"
-#endif /* CONFIG_CHIP_M32700_TS1 */
-       );
-       local_irq_restore(flags);
-
-       if (unlikely(count < 0))
+       if (unlikely(atomic_dec_return(&sem->count) < 0))
                result = __down_interruptible(sem);
 
        return result;
@@ -174,26 +137,7 @@ static inline int down_trylock(struct semaphore * sem)
  */
 static inline void up(struct semaphore * sem)
 {
-       unsigned long flags;
-       long count;
-
-       local_irq_save(flags);
-       __asm__ __volatile__ (
-               "# up                           \n\t"
-               DCACHE_CLEAR("%0", "r4", "%1")
-               M32R_LOCK" %0, @%1;             \n\t"
-               "addi   %0, #1;                 \n\t"
-               M32R_UNLOCK" %0, @%1;           \n\t"
-               : "=&r" (count)
-               : "r" (&sem->count)
-               : "memory"
-#ifdef CONFIG_CHIP_M32700_TS1
-               , "r4"
-#endif /* CONFIG_CHIP_M32700_TS1 */
-       );
-       local_irq_restore(flags);
-
-       if (unlikely(count <= 0))
+       if (unlikely(atomic_inc_return(&sem->count) <= 0))
                __up(sem);
 }
 
index c233e2def2a3d198fd881c7e5f2e153b8763a0a3..942b8a30937df79deb9ac1dc76bb8cd27862afd9 100644 (file)
@@ -32,6 +32,8 @@ struct sigcontext {
 #elif defined(CONFIG_ISA_M32R2) || defined(CONFIG_ISA_M32R)
        unsigned long sc_acch;
        unsigned long sc_accl;
+       unsigned long sc_dummy_acc1h;
+       unsigned long sc_dummy_acc1l;
 #else
 #error unknown isa configuration
 #endif
index c5ab5da56d21acb42dfb4c18e5bbdd8151aa58f8..e55013f378e582357df670aee5638e62e8e5a2af 100644 (file)
@@ -6,8 +6,8 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 2001  by Hiroyuki Kondo, Hirokazu Takata, and Hitoshi Yamamoto
- * Copyright (C) 2004  Hirokazu Takata <takata at linux-m32r.org>
+ * Copyright (C) 2001  Hiroyuki Kondo, Hirokazu Takata, and Hitoshi Yamamoto
+ * Copyright (C) 2004, 2006  Hirokazu Takata <takata at linux-m32r.org>
  */
 
 #include <linux/config.h>
  * switch_to(prev, next) should switch from task `prev' to `next'
  * `prev' will never be the same as `next'.
  *
- * `next' and `prev' should be struct task_struct, but it isn't always defined
+ * `next' and `prev' should be task_t, but it isn't always defined
  */
 
 #define switch_to(prev, next, last)  do { \
-       register unsigned long  arg0 __asm__ ("r0") = (unsigned long)prev; \
-       register unsigned long  arg1 __asm__ ("r1") = (unsigned long)next; \
-       register unsigned long  *oldsp __asm__ ("r2") = &(prev->thread.sp); \
-       register unsigned long  *newsp __asm__ ("r3") = &(next->thread.sp); \
-       register unsigned long  *oldlr __asm__ ("r4") = &(prev->thread.lr); \
-       register unsigned long  *newlr __asm__ ("r5") = &(next->thread.lr); \
-       register struct task_struct  *__last __asm__ ("r6"); \
        __asm__ __volatile__ ( \
-               "st     r8, @-r15                                 \n\t" \
-               "st     r9, @-r15                                 \n\t" \
-               "st    r10, @-r15                                 \n\t" \
-               "st    r11, @-r15                                 \n\t" \
-               "st    r12, @-r15                                 \n\t" \
-               "st    r13, @-r15                                 \n\t" \
-               "st    r14, @-r15                                 \n\t" \
-               "seth  r14, #high(1f)                             \n\t" \
-               "or3   r14, r14, #low(1f)                         \n\t" \
-               "st    r14, @r4    ; store old LR                 \n\t" \
-               "st    r15, @r2    ; store old SP                 \n\t" \
-               "ld    r15, @r3    ; load new SP                  \n\t" \
-               "st     r0, @-r15  ; store 'prev' onto new stack  \n\t" \
-               "ld    r14, @r5    ; load new LR                  \n\t" \
-               "jmp   r14                                        \n\t" \
-               ".fillinsn                                        \n  " \
-               "1:                                               \n\t" \
-               "ld     r6, @r15+  ; load 'prev' from new stack   \n\t" \
-               "ld    r14, @r15+                                 \n\t" \
-               "ld    r13, @r15+                                 \n\t" \
-               "ld    r12, @r15+                                 \n\t" \
-               "ld    r11, @r15+                                 \n\t" \
-               "ld    r10, @r15+                                 \n\t" \
-               "ld     r9, @r15+                                 \n\t" \
-               "ld     r8, @r15+                                 \n\t" \
-               : "=&r" (__last) \
-               : "r" (arg0), "r" (arg1), "r" (oldsp), "r" (newsp), \
-                 "r" (oldlr), "r" (newlr) \
-               : "memory" \
+               "       seth    lr, #high(1f)                           \n" \
+               "       or3     lr, lr, #low(1f)                        \n" \
+               "       st      lr, @%4  ; store old LR                 \n" \
+               "       ld      lr, @%5  ; load new LR                  \n" \
+               "       st      sp, @%2  ; store old SP                 \n" \
+               "       ld      sp, @%3  ; load new SP                  \n" \
+               "       push    %1  ; store `prev' on new stack         \n" \
+               "       jmp     lr                                      \n" \
+               "       .fillinsn                                       \n" \
+               "1:                                                     \n" \
+               "       pop     %0  ; restore `__last' from new stack   \n" \
+               : "=r" (last) \
+               : "0" (prev), \
+                 "r" (&(prev->thread.sp)), "r" (&(next->thread.sp)), \
+                 "r" (&(prev->thread.lr)), "r" (&(next->thread.lr)) \
+               : "memory", "lr" \
        ); \
-       last = __last; \
 } while(0)
 
 /*
@@ -167,8 +146,8 @@ extern void  __xchg_called_with_bad_pointer(void);
 #define DCACHE_CLEAR(reg0, reg1, addr)
 #endif /* CONFIG_CHIP_M32700_TS1 */
 
-static __inline__ unsigned long __xchg(unsigned long x, volatile void * ptr,
-       int size)
+static inline unsigned long
+__xchg(unsigned long x, volatile void * ptr, int size)
 {
        unsigned long flags;
        unsigned long tmp = 0;
@@ -220,7 +199,7 @@ static __inline__ unsigned long __xchg(unsigned long x, volatile void * ptr,
 
 #define __HAVE_ARCH_CMPXCHG    1
 
-static __inline__ unsigned long
+static inline unsigned long
 __cmpxchg_u32(volatile unsigned int *p, unsigned int old, unsigned int new)
 {
        unsigned long flags;
@@ -254,7 +233,7 @@ __cmpxchg_u32(volatile unsigned int *p, unsigned int old, unsigned int new)
    if something tries to do an invalid cmpxchg().  */
 extern void __cmpxchg_called_with_bad_pointer(void);
 
-static __inline__ unsigned long
+static inline unsigned long
 __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size)
 {
        switch (size) {
index 30b18ea6cb1116fd12e86094788c5917fe9f7e99..f54aa147ec19066ac6aa9f729f72e78f35958153 100644 (file)
 #ifdef CONFIG_64BIT
 #include <asm/asmmacro-64.h>
 #endif
+#ifdef CONFIG_MIPS_MT_SMTC
+#include <asm/mipsmtregs.h>
+#endif
 
+#ifdef CONFIG_MIPS_MT_SMTC
+       .macro  local_irq_enable reg=t0
+       mfc0    \reg, CP0_TCSTATUS
+       ori     \reg, \reg, TCSTATUS_IXMT
+       xori    \reg, \reg, TCSTATUS_IXMT
+       mtc0    \reg, CP0_TCSTATUS
+       ehb
+       .endm
+
+       .macro  local_irq_disable reg=t0
+       mfc0    \reg, CP0_TCSTATUS
+       ori     \reg, \reg, TCSTATUS_IXMT
+       mtc0    \reg, CP0_TCSTATUS
+       ehb
+       .endm
+#else
        .macro  local_irq_enable reg=t0
        mfc0    \reg, CP0_STATUS
        ori     \reg, \reg, 1
@@ -32,6 +51,7 @@
        mtc0    \reg, CP0_STATUS
        irq_disable_hazard
        .endm
+#endif /* CONFIG_MIPS_MT_SMTC */
 
 #ifdef CONFIG_CPU_SB1
        .macro  fpu_enable_hazard
        .endm
 #endif
 
+/*
+ * Temporary until all gas have MT ASE support
+ */
+       .macro  DMT     reg=0
+       .word   (0x41600bc1 | (\reg << 16))
+       .endm
+
+       .macro  EMT     reg=0
+       .word   (0x41600be1 | (\reg << 16))
+       .endm
+
+       .macro  DVPE    reg=0
+       .word   (0x41600001 | (\reg << 16))
+       .endm
+
+       .macro  EVPE    reg=0
+       .word   (0x41600021 | (\reg << 16))
+       .endm
+
+       .macro  MFTR    rt=0, rd=0, u=0, sel=0
+        .word  (0x41000000 | (\rt << 16) | (\rd << 11) | (\u << 5) | (\sel))
+       .endm
+
+       .macro  MTTR    rt=0, rd=0, u=0, sel=0
+        .word  (0x41800000 | (\rt << 16) | (\rd << 11) | (\u << 5) | (\sel))
+       .endm
+
 #endif /* _ASM_ASMMACRO_H */
index aeae9fabf4a9be581937ce767a2eb4af1c6c3979..47bc8f6c20d2e2795211335e37cbb4e01489e0c2 100644 (file)
@@ -74,6 +74,7 @@ static inline void copy_from_user_page(struct vm_area_struct *vma,
 
 extern void (*flush_cache_sigtramp)(unsigned long addr);
 extern void (*flush_icache_all)(void);
+extern void (*local_flush_data_cache_page)(void * addr);
 extern void (*flush_data_cache_page)(unsigned long addr);
 
 /*
index 3f2b6d9ac45e73a5a770f878eab547cc33641785..254e11ed247b04cc4085782a51bd067f21db9e1b 100644 (file)
@@ -40,7 +40,7 @@
 #define cpu_has_sb1_cache      (cpu_data[0].options & MIPS_CPU_SB1_CACHE)
 #endif
 #ifndef cpu_has_fpu
-#define cpu_has_fpu            (cpu_data[0].options & MIPS_CPU_FPU)
+#define cpu_has_fpu            (current_cpu_data.options & MIPS_CPU_FPU)
 #endif
 #ifndef cpu_has_32fpr
 #define cpu_has_32fpr          (cpu_data[0].options & MIPS_CPU_32FPR)
index 140be1c67da7c734d38471df1ebe0ebf80ad9e1c..6572ac703662068da6de5ad81c8b952aec4ee591 100644 (file)
@@ -73,6 +73,16 @@ struct cpuinfo_mips {
        struct cache_desc       dcache; /* Primary D or combined I/D cache */
        struct cache_desc       scache; /* Secondary cache */
        struct cache_desc       tcache; /* Tertiary/split secondary cache */
+#if defined(CONFIG_MIPS_MT_SMTC)
+       /*
+        * In the MIPS MT "SMTC" model, each TC is considered
+        * to be a "CPU" for the purposes of scheduling, but
+        * exception resources, ASID spaces, etc, are common
+        * to all TCs within the same VPE.
+        */
+       int                     vpe_id;  /* Virtual Processor number */
+       int                     tc_id;   /* Thread Context number */
+#endif /* CONFIG_MIPS_MT */
        void                    *data;  /* Additional data */
 } __attribute__((aligned(SMP_CACHE_BYTES)));
 
diff --git a/include/asm-mips/ds1742.h b/include/asm-mips/ds1742.h
new file mode 100644 (file)
index 0000000..c2f2c32
--- /dev/null
@@ -0,0 +1,13 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2006 by Ralf Baechle (ralf@linux-mips.org)
+ */
+#ifndef _ASM_DS1742_H
+#define _ASM_DS1742_H
+
+#include <ds1742.h>
+
+#endif /* _ASM_DS1742_H */
index 851f013adad34a4541dad2cfce71f1823cfd15bb..bdc9de2df1ef28d52644252ab060de9969f6ab2c 100644 (file)
 #define SHT_MIPS_CONFLICT      0x70000002
 #define SHT_MIPS_GPTAB         0x70000003
 #define SHT_MIPS_UCODE         0x70000004
-
-#define SHF_MIPS_GPREL 0x10000000
+#define SHT_MIPS_DEBUG         0x70000005
+#define SHT_MIPS_REGINFO       0x70000006
+#define SHT_MIPS_PACKAGE       0x70000007
+#define SHT_MIPS_PACKSYM       0x70000008
+#define SHT_MIPS_RELD          0x70000009
+#define SHT_MIPS_IFACE         0x7000000b
+#define SHT_MIPS_CONTENT       0x7000000c
+#define SHT_MIPS_OPTIONS       0x7000000d
+#define SHT_MIPS_SHDR          0x70000010
+#define SHT_MIPS_FDESC         0x70000011
+#define SHT_MIPS_EXTSYM                0x70000012
+#define SHT_MIPS_DENSE         0x70000013
+#define SHT_MIPS_PDESC         0x70000014
+#define SHT_MIPS_LOCSYM                0x70000015
+#define SHT_MIPS_AUXSYM                0x70000016
+#define SHT_MIPS_OPTSYM                0x70000017
+#define SHT_MIPS_LOCSTR                0x70000018
+#define SHT_MIPS_LINE          0x70000019
+#define SHT_MIPS_RFDESC                0x7000001a
+#define SHT_MIPS_DELTASYM      0x7000001b
+#define SHT_MIPS_DELTAINST     0x7000001c
+#define SHT_MIPS_DELTACLASS    0x7000001d
+#define SHT_MIPS_DWARF         0x7000001e
+#define SHT_MIPS_DELTADECL     0x7000001f
+#define SHT_MIPS_SYMBOL_LIB    0x70000020
+#define SHT_MIPS_EVENTS                0x70000021
+#define SHT_MIPS_TRANSLATE     0x70000022
+#define SHT_MIPS_PIXIE         0x70000023
+#define SHT_MIPS_XLATE         0x70000024
+#define SHT_MIPS_XLATE_DEBUG   0x70000025
+#define SHT_MIPS_WHIRL         0x70000026
+#define SHT_MIPS_EH_REGION     0x70000027
+#define SHT_MIPS_XLATE_OLD     0x70000028
+#define SHT_MIPS_PDR_EXCEPTION 0x70000029
+
+#define SHF_MIPS_GPREL         0x10000000
+#define SHF_MIPS_MERGE         0x20000000
+#define SHF_MIPS_ADDR          0x40000000
+#define SHF_MIPS_STRING                0x80000000
+#define SHF_MIPS_NOSTRIP       0x08000000
+#define SHF_MIPS_LOCAL         0x04000000
+#define SHF_MIPS_NAMES         0x02000000
+#define SHF_MIPS_NODUPES       0x01000000
 
 #ifndef ELF_ARCH
 /* ELF register definitions */
index 9c828b1f821875e273bdd3da8f9a6b3fcf98e27b..b0f50015e25253688fd24e6154f48d70710d5fa3 100644 (file)
 #include <asm/processor.h>
 #include <asm/current.h>
 
+#ifdef CONFIG_MIPS_MT_FPAFF
+#include <asm/mips_mt.h>
+#endif
+
 struct sigcontext;
 struct sigcontext32;
 
index feb29a79388869199d0331fae77273a1d0473873..dadc05188db717c288ab9ecd6a86d483e4731119 100644 (file)
@@ -284,6 +284,8 @@ do {                                                                        \
 #define instruction_hazard() do { } while (0)
 #endif
 
+extern void mips_ihb(void);
+
 #endif /* __ASSEMBLY__ */
 
 #endif /* _ASM_HAZARDS_H */
index 774348734fa0b38a8fbe916972a966a59302be17..4bb9c06f44107006f4c6330df7f0aedb23bc96a2 100644 (file)
@@ -19,7 +19,12 @@ __asm__ (
        "       .set    push                                            \n"
        "       .set    reorder                                         \n"
        "       .set    noat                                            \n"
-#ifdef CONFIG_CPU_MIPSR2
+#ifdef CONFIG_MIPS_MT_SMTC
+       "       mfc0    $1, $2, 1       # SMTC - clear TCStatus.IXMT    \n"
+       "       ori     $1, 0x400                                       \n"
+       "       xori    $1, 0x400                                       \n"
+       "       mtc0    $1, $2, 1                                       \n"
+#elif defined(CONFIG_CPU_MIPSR2)
        "       ei                                                      \n"
 #else
        "       mfc0    $1,$12                                          \n"
@@ -62,7 +67,12 @@ __asm__ (
        "       .macro  local_irq_disable\n"
        "       .set    push                                            \n"
        "       .set    noat                                            \n"
-#ifdef CONFIG_CPU_MIPSR2
+#ifdef CONFIG_MIPS_MT_SMTC
+       "       mfc0    $1, $2, 1                                       \n"
+       "       ori     $1, 0x400                                       \n"
+       "       .set    noreorder                                       \n"
+       "       mtc0    $1, $2, 1                                       \n"
+#elif defined(CONFIG_CPU_MIPSR2)
        "       di                                                      \n"
 #else
        "       mfc0    $1,$12                                          \n"
@@ -88,7 +98,11 @@ __asm__ (
        "       .macro  local_save_flags flags                          \n"
        "       .set    push                                            \n"
        "       .set    reorder                                         \n"
+#ifdef CONFIG_MIPS_MT_SMTC
+       "       mfc0    \\flags, $2, 1                                  \n"
+#else
        "       mfc0    \\flags, $12                                    \n"
+#endif
        "       .set    pop                                             \n"
        "       .endm                                                   \n");
 
@@ -102,7 +116,13 @@ __asm__ (
        "       .set    push                                            \n"
        "       .set    reorder                                         \n"
        "       .set    noat                                            \n"
-#ifdef CONFIG_CPU_MIPSR2
+#ifdef CONFIG_MIPS_MT_SMTC
+       "       mfc0    \\result, $2, 1                                 \n"
+       "       ori     $1, \\result, 0x400                             \n"
+       "       .set    noreorder                                       \n"
+       "       mtc0    $1, $2, 1                                       \n"
+       "       andi    \\result, \\result, 0x400                       \n"
+#elif defined(CONFIG_CPU_MIPSR2)
        "       di      \\result                                        \n"
        "       andi    \\result, 1                                     \n"
 #else
@@ -128,7 +148,14 @@ __asm__ (
        "       .set    push                                            \n"
        "       .set    noreorder                                       \n"
        "       .set    noat                                            \n"
-#if defined(CONFIG_CPU_MIPSR2) && defined(CONFIG_IRQ_CPU)
+#ifdef CONFIG_MIPS_MT_SMTC
+       "mfc0   $1, $2, 1                                               \n"
+       "andi   \\flags, 0x400                                          \n"
+       "ori    $1, 0x400                                               \n"
+       "xori   $1, 0x400                                               \n"
+       "or     \\flags, $1                                             \n"
+       "mtc0   \\flags, $2, 1                                          \n"
+#elif defined(CONFIG_CPU_MIPSR2) && defined(CONFIG_IRQ_CPU)
        /*
         * Slow, but doesn't suffer from a relativly unlikely race
         * condition we're having since days 1.
@@ -167,11 +194,29 @@ do {                                                                      \
                : "memory");                                            \
 } while(0)
 
-#define irqs_disabled()                                                        \
-({                                                                     \
-       unsigned long flags;                                            \
-       local_save_flags(flags);                                        \
-       !(flags & 1);                                                   \
-})
+static inline int irqs_disabled(void)
+{
+#ifdef CONFIG_MIPS_MT_SMTC
+       /*
+        * SMTC model uses TCStatus.IXMT to disable interrupts for a thread/CPU
+        */
+       unsigned long __result;
+
+       __asm__ __volatile__(
+       "       .set    noreorder                                       \n"
+       "       mfc0    %0, $2, 1                                       \n"
+       "       andi    %0, 0x400                                       \n"
+       "       slt     %0, $0, %0                                      \n"
+       "       .set    reorder                                         \n"
+       : "=r" (__result));
+
+       return __result;
+#else
+       unsigned long flags;
+       local_save_flags(flags);
+
+       return !(flags & 1);
+#endif
+}
 
 #endif /* _ASM_INTERRUPT_H */
index 8a342ccb34a80e34c3c52835759d675744162142..dde677f02bc015e1129d3b30a550f707f3b8f61d 100644 (file)
@@ -11,6 +11,9 @@
 
 #include <linux/config.h>
 #include <linux/linkage.h>
+
+#include <asm/mipsmtregs.h>
+
 #include <irq.h>
 
 #ifdef CONFIG_I8259
@@ -26,6 +29,23 @@ struct pt_regs;
 
 extern asmlinkage unsigned int do_IRQ(unsigned int irq, struct pt_regs *regs);
 
+#ifdef CONFIG_MIPS_MT_SMTC
+/*
+ * Clear interrupt mask handling "backstop" if irq_hwmask
+ * entry so indicates. This implies that the ack() or end()
+ * functions will take over re-enabling the low-level mask.
+ * Otherwise it will be done on return from exception.
+ */
+#define __DO_IRQ_SMTC_HOOK()                                           \
+do {                                                                   \
+       if (irq_hwmask[irq] & 0x0000ff00)                               \
+               write_c0_tccontext(read_c0_tccontext() &                \
+                                  ~(irq_hwmask[irq] & 0x0000ff00));    \
+} while (0)
+#else
+#define __DO_IRQ_SMTC_HOOK() do { } while (0)
+#endif
+
 #ifdef CONFIG_PREEMPT
 
 /*
@@ -39,6 +59,7 @@ extern asmlinkage unsigned int do_IRQ(unsigned int irq, struct pt_regs *regs);
 #define do_IRQ(irq, regs)                                              \
 do {                                                                   \
        irq_enter();                                                    \
+       __DO_IRQ_SMTC_HOOK();                                           \
        __do_IRQ((irq), (regs));                                        \
        irq_exit();                                                     \
 } while (0)
@@ -46,5 +67,14 @@ do {                                                                 \
 #endif
 
 extern void arch_init_irq(void);
+extern void spurious_interrupt(struct pt_regs *regs);
+
+#ifdef CONFIG_MIPS_MT_SMTC
+struct irqaction;
+
+extern unsigned long irq_hwmask[];
+extern int setup_irq_smtc(unsigned int irq, struct irqaction * new,
+                          unsigned long hwmask);
+#endif /* CONFIG_MIPS_MT_SMTC */
 
 #endif /* _ASM_IRQ_H */
diff --git a/include/asm-mips/kspd.h b/include/asm-mips/kspd.h
new file mode 100644 (file)
index 0000000..4e9e724
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2005 MIPS Technologies, Inc.  All rights reserved.
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope 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.
+ *
+ */
+
+#ifndef _ASM_KSPD_H
+#define _ASM_KSPD_H
+
+struct kspd_notifications {
+       void (*kspd_sp_exit)(int sp_id);
+
+       struct list_head list;
+};
+
+#ifdef CONFIG_MIPS_APSP_KSPD
+extern void kspd_notify(struct kspd_notifications *notify);
+#else
+static inline void kspd_notify(struct kspd_notifications *notify)
+{
+}
+#endif
+
+#endif
index 550979a9ea9d21432fe0a8570f73d9cf294df4be..e3315359500abba1617bb13f4abd17be79dc2f66 100644 (file)
@@ -104,65 +104,107 @@ static __inline__ unsigned long ide_default_io_base(int index)
 #endif
 
 /* MIPS port and memory-mapped I/O string operations.  */
+static inline void __ide_flush_prologue(void)
+{
+#ifdef CONFIG_SMP
+       if (cpu_has_dc_aliases)
+               preempt_disable();
+#endif
+}
+
+static inline void __ide_flush_epilogue(void)
+{
+#ifdef CONFIG_SMP
+       if (cpu_has_dc_aliases)
+               preempt_enable();
+#endif
+}
 
 static inline void __ide_flush_dcache_range(unsigned long addr, unsigned long size)
 {
        if (cpu_has_dc_aliases) {
                unsigned long end = addr + size;
-               for (; addr < end; addr += PAGE_SIZE)
-                       flush_dcache_page(virt_to_page(addr));
+
+               while (addr < end) {
+                       local_flush_data_cache_page((void *)addr);
+                       addr += PAGE_SIZE;
+               }
        }
 }
 
+/*
+ * insw() and gang might be called with interrupts disabled, so we can't
+ * send IPIs for flushing due to the potencial of deadlocks, see the comment
+ * above smp_call_function() in arch/mips/kernel/smp.c.  We work around the
+ * problem by disabling preemption so we know we actually perform the flush
+ * on the processor that actually has the lines to be flushed which hopefully
+ * is even better for performance anyway.
+ */
 static inline void __ide_insw(unsigned long port, void *addr,
        unsigned int count)
 {
+       __ide_flush_prologue();
        insw(port, addr, count);
        __ide_flush_dcache_range((unsigned long)addr, count * 2);
+       __ide_flush_epilogue();
 }
 
 static inline void __ide_insl(unsigned long port, void *addr, unsigned int count)
 {
+       __ide_flush_prologue();
        insl(port, addr, count);
        __ide_flush_dcache_range((unsigned long)addr, count * 4);
+       __ide_flush_epilogue();
 }
 
 static inline void __ide_outsw(unsigned long port, const void *addr,
        unsigned long count)
 {
+       __ide_flush_prologue();
        outsw(port, addr, count);
        __ide_flush_dcache_range((unsigned long)addr, count * 2);
+       __ide_flush_epilogue();
 }
 
 static inline void __ide_outsl(unsigned long port, const void *addr,
        unsigned long count)
 {
+       __ide_flush_prologue();
        outsl(port, addr, count);
        __ide_flush_dcache_range((unsigned long)addr, count * 4);
+       __ide_flush_epilogue();
 }
 
 static inline void __ide_mm_insw(void __iomem *port, void *addr, u32 count)
 {
+       __ide_flush_prologue();
        readsw(port, addr, count);
        __ide_flush_dcache_range((unsigned long)addr, count * 2);
+       __ide_flush_epilogue();
 }
 
 static inline void __ide_mm_insl(void __iomem *port, void *addr, u32 count)
 {
+       __ide_flush_prologue();
        readsl(port, addr, count);
        __ide_flush_dcache_range((unsigned long)addr, count * 4);
+       __ide_flush_epilogue();
 }
 
 static inline void __ide_mm_outsw(void __iomem *port, void *addr, u32 count)
 {
+       __ide_flush_prologue();
        writesw(port, addr, count);
        __ide_flush_dcache_range((unsigned long)addr, count * 2);
+       __ide_flush_epilogue();
 }
 
 static inline void __ide_mm_outsl(void __iomem * port, void *addr, u32 count)
 {
+       __ide_flush_prologue();
        writesl(port, addr, count);
        __ide_flush_dcache_range((unsigned long)addr, count * 4);
+       __ide_flush_epilogue();
 }
 
 /* ide_insw calls insw, not __ide_insw.  Why? */
index cff6192d4bdbd820ab659c5cf8d449413ea7b697..8a8fef6d07fad7608a14404e496fd99bcba54861 100644 (file)
@@ -3,14 +3,14 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 2003 by Ralf Baechle
+ * Copyright (C) 2003, 06 by Ralf Baechle
  */
 #ifndef __ASM_MACH_JMR3927_DS1742_H
 #define __ASM_MACH_JMR3927_DS1742_H
 
 #include <asm/jmr3927/jmr3927.h>
 
-#define rtc_read(reg)          (jmr3927_nvram_in(addr))
+#define rtc_read(reg)          (jmr3927_nvram_in(reg))
 #define rtc_write(data, reg)   (jmr3927_nvram_out((data),(reg)))
 
 #endif /* __ASM_MACH_JMR3927_DS1742_H */
diff --git a/include/asm-mips/mach-mips/param.h b/include/asm-mips/mach-mips/param.h
new file mode 100644 (file)
index 0000000..805ef6d
--- /dev/null
@@ -0,0 +1,13 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2003 by Ralf Baechle
+ */
+#ifndef __ASM_MACH_MIPS_PARAM_H
+#define __ASM_MACH_MIPS_PARAM_H
+
+#define HZ             100             /* Internal kernel timer frequency */
+
+#endif /* __ASM_MACH_MIPS_PARAM_H */
index 9225b3397a4fb4d126cce26b4a37602696c0cd6d..6bb2125bb0538b1a8d148d4df9462ae3ab8e89c9 100644 (file)
@@ -53,4 +53,6 @@ struct mv_pci_controller {
        unsigned long   config_vreg;
 };
 
+extern void ll_mv64340_irq(struct pt_regs *regs);
+
 #endif /* __ASM_MIPS_MARVELL_H */
index 0998151fb3a12e68b28960082ff810cc5fd78c7c..a8ae12d120eecad17db01c7074d277e5919aa482 100644 (file)
 #define ATLAS_RTC_ADR_REG       0x1f000800
 #define ATLAS_RTC_DAT_REG       0x1f000808
 
-
 /*
  * Atlas interrupt controller register base.
  */
 #define ATLAS_ICTRL_REGS_BASE   0x1f000000
 
+/*
+ * Atlas registers are memory mapped on 64-bit aligned boundaries and
+ * only word access are allowed.
+ */
+struct atlas_ictrl_regs {
+       volatile unsigned int intraw;
+       int dummy1;
+       volatile unsigned int intseten;
+       int dummy2;
+       volatile unsigned int intrsten;
+       int dummy3;
+       volatile unsigned int intenable;
+       int dummy4;
+       volatile unsigned int intstatus;
+       int dummy5;
+};
+
 /*
  * Atlas UART register base.
  */
index bba35c183d087dd77747a4b1dfe527b2d8afc824..fd7ebc54fa901ff7384df77024dca98abf6e257e 100644 (file)
 #define ATLASINT_RES31         (ATLASINT_BASE+31)
 #define ATLASINT_END           (ATLASINT_BASE+31)
 
-/*
- * Atlas registers are memory mapped on 64-bit aligned boundaries and
- * only word access are allowed.
- */
-struct atlas_ictrl_regs {
-        volatile unsigned int intraw;
-        int dummy1;
-        volatile unsigned int intseten;
-        int dummy2;
-        volatile unsigned int intrsten;
-        int dummy3;
-        volatile unsigned int intenable;
-        int dummy4;
-        volatile unsigned int intstatus;
-        int dummy5;
-};
-
-extern void atlasint_init(void);
-
 #endif /* !(_MIPS_ATLASINT_H) */
diff --git a/include/asm-mips/mips_mt.h b/include/asm-mips/mips_mt.h
new file mode 100644 (file)
index 0000000..c31a312
--- /dev/null
@@ -0,0 +1,15 @@
+/*
+ * Definitions and decalrations for MIPS MT support
+ * that are common between SMTC, VSMP, and/or AP/SP
+ * kernel models.
+ */
+#ifndef __ASM_MIPS_MT_H
+#define __ASM_MIPS_MT_H
+
+extern cpumask_t mt_fpu_cpumask;
+extern unsigned long mt_fpemul_threshold;
+
+extern void mips_mt_regdump(unsigned long previous_mvpcontrol_value);
+extern void mips_mt_set_cpuoptions(void);
+
+#endif /* __ASM_MIPS_MT_H */
index a669c0702c66705fc7440b1056d9727ad03bc8b9..f637ce70758fb363b930f18615726c6205d060d7 100644 (file)
 
 #ifndef __ASSEMBLY__
 
-extern void mips_mt_regdump(void);
+extern void mips_mt_regdump(unsigned long previous_mvpcontrol_value);
 
 static inline unsigned int dvpe(void)
 {
@@ -234,7 +234,7 @@ static inline void __raw_emt(void)
        __asm__ __volatile__(
        "       .set    noreorder                                       \n"
        "       .set    mips32r2                                        \n"
-       "       emt                                                     \n"
+       "       .word   0x41600be1                      # emt           \n"
        "       ehb                                                     \n"
        "       .set    mips0                                           \n"
        "       .set    reorder");
@@ -282,8 +282,11 @@ static inline void ehb(void)
                                                                        \
        __asm__ __volatile__(                                           \
        "       .set    push                                    \n"     \
+       "       .set    noat                                    \n"     \
        "       .set    mips32r2                                \n"     \
-       "       mftgpr  %0," #rt "                              \n"     \
+       "       # mftgpr $1," #rt "                             \n"     \
+       "       .word   0x41000820 | (" #rt " << 16)            \n"     \
+       "       move    %0, $1                                  \n"     \
        "       .set    pop                                     \n"     \
        : "=r" (__res));                                                \
                                                                        \
@@ -295,9 +298,7 @@ static inline void ehb(void)
        unsigned long __res;                                            \
                                                                        \
        __asm__ __volatile__(                                           \
-       ".set noat\n\t"                                                 \
-       "mftr\t%0, " #rt ", " #u ", " #sel "\n\t"                       \
-       ".set at\n\t"                                                   \
+       "       mftr    %0, " #rt ", " #u ", " #sel "           \n"     \
        : "=r" (__res));                                                \
                                                                        \
        __res;                                                          \
@@ -364,6 +365,9 @@ do {                                                                        \
 #define read_vpe_c0_ebase()            mftc0(15,1)
 #define write_vpe_c0_ebase(val)                mttc0(15, 1, val)
 #define write_vpe_c0_compare(val)      mttc0(11, 0, val)
+#define read_vpe_c0_badvaddr()         mftc0(8, 0)
+#define read_vpe_c0_epc()              mftc0(14, 0)
+#define write_vpe_c0_epc(val)          mttc0(14, 0, val)
 
 
 /* TC */
index 035ba0a9b0dfe3c62d1f80a510246e82b6e5ce35..a2ef579f6b1a26d8e87d3b5c19b405629dfe0b29 100644 (file)
@@ -836,6 +836,9 @@ do {                                                                        \
 #define read_c0_cache()                __read_32bit_c0_register($7, 0) /* TX39xx */
 #define write_c0_cache(val)    __write_32bit_c0_register($7, 0, val)
 
+#define read_c0_badvaddr()     __read_ulong_c0_register($8, 0)
+#define write_c0_badvaddr(val) __write_ulong_c0_register($8, 0, val)
+
 #define read_c0_count()                __read_32bit_c0_register($9, 0)
 #define write_c0_count(val)    __write_32bit_c0_register($9, 0, val)
 
@@ -858,7 +861,19 @@ do {                                                                       \
 #define write_c0_compare3(val) __write_32bit_c0_register($11, 7, val)
 
 #define read_c0_status()       __read_32bit_c0_register($12, 0)
+#ifdef CONFIG_MIPS_MT_SMTC
+#define write_c0_status(val)                                           \
+do {                                                                   \
+       __write_32bit_c0_register($12, 0, val);                         \
+       __ehb();                                                        \
+} while (0)
+#else
+/*
+ * Legacy non-SMTC code, which may be hazardous
+ * but which might not support EHB
+ */
 #define write_c0_status(val)   __write_32bit_c0_register($12, 0, val)
+#endif /* CONFIG_MIPS_MT_SMTC */
 
 #define read_c0_cause()                __read_32bit_c0_register($13, 0)
 #define write_c0_cause(val)    __write_32bit_c0_register($13, 0, val)
@@ -1001,6 +1016,9 @@ do {                                                                      \
 #define read_c0_taglo()                __read_32bit_c0_register($28, 0)
 #define write_c0_taglo(val)    __write_32bit_c0_register($28, 0, val)
 
+#define read_c0_dtaglo()       __read_32bit_c0_register($28, 2)
+#define write_c0_dtaglo(val)   __write_32bit_c0_register($28, 2, val)
+
 #define read_c0_taghi()                __read_32bit_c0_register($29, 0)
 #define write_c0_taghi(val)    __write_32bit_c0_register($29, 0, val)
 
@@ -1354,15 +1372,119 @@ static inline void tlb_write_random(void)
 /*
  * Manipulate bits in a c0 register.
  */
+#ifndef CONFIG_MIPS_MT_SMTC
+/*
+ * SMTC Linux requires shutting-down microthread scheduling
+ * during CP0 register read-modify-write sequences.
+ */
+#define __BUILD_SET_C0(name)                                   \
+static inline unsigned int                                     \
+set_c0_##name(unsigned int set)                                        \
+{                                                              \
+       unsigned int res;                                       \
+                                                               \
+       res = read_c0_##name();                                 \
+       res |= set;                                             \
+       write_c0_##name(res);                                   \
+                                                               \
+       return res;                                             \
+}                                                              \
+                                                               \
+static inline unsigned int                                     \
+clear_c0_##name(unsigned int clear)                            \
+{                                                              \
+       unsigned int res;                                       \
+                                                               \
+       res = read_c0_##name();                                 \
+       res &= ~clear;                                          \
+       write_c0_##name(res);                                   \
+                                                               \
+       return res;                                             \
+}                                                              \
+                                                               \
+static inline unsigned int                                     \
+change_c0_##name(unsigned int change, unsigned int new)                \
+{                                                              \
+       unsigned int res;                                       \
+                                                               \
+       res = read_c0_##name();                                 \
+       res &= ~change;                                         \
+       res |= (new & change);                                  \
+       write_c0_##name(res);                                   \
+                                                               \
+       return res;                                             \
+}
+
+#else /* SMTC versions that manage MT scheduling */
+
+#include <asm/interrupt.h>
+
+/*
+ * This is a duplicate of dmt() in mipsmtregs.h to avoid problems with
+ * header file recursion.
+ */
+static inline unsigned int __dmt(void)
+{
+       int res;
+
+       __asm__ __volatile__(
+       "       .set    push                                            \n"
+       "       .set    mips32r2                                        \n"
+       "       .set    noat                                            \n"
+       "       .word   0x41610BC1                      # dmt $1        \n"
+       "       ehb                                                     \n"
+       "       move    %0, $1                                          \n"
+       "       .set    pop                                             \n"
+       : "=r" (res));
+
+       instruction_hazard();
+
+       return res;
+}
+
+#define __VPECONTROL_TE_SHIFT  15
+#define __VPECONTROL_TE                (1UL << __VPECONTROL_TE_SHIFT)
+
+#define __EMT_ENABLE           __VPECONTROL_TE
+
+static inline void __emt(unsigned int previous)
+{
+       if ((previous & __EMT_ENABLE))
+               __asm__ __volatile__(
+               "       .set    noreorder                               \n"
+               "       .set    mips32r2                                \n"
+               "       .word   0x41600be1              # emt           \n"
+               "       ehb                                             \n"
+               "       .set    mips0                                   \n"
+               "       .set    reorder                                 \n");
+}
+
+static inline void __ehb(void)
+{
+       __asm__ __volatile__(
+       "       ehb                                                     \n");
+}
+
+/*
+ * Note that local_irq_save/restore affect TC-specific IXMT state,
+ * not Status.IE as in non-SMTC kernel.
+ */
+
 #define __BUILD_SET_C0(name)                                   \
 static inline unsigned int                                     \
 set_c0_##name(unsigned int set)                                        \
 {                                                              \
        unsigned int res;                                       \
+       unsigned int omt;                                       \
+       unsigned int flags;                                     \
                                                                \
+       local_irq_save(flags);                                  \
+       omt = __dmt();                                          \
        res = read_c0_##name();                                 \
        res |= set;                                             \
        write_c0_##name(res);                                   \
+       __emt(omt);                                             \
+       local_irq_restore(flags);                               \
                                                                \
        return res;                                             \
 }                                                              \
@@ -1371,10 +1493,16 @@ static inline unsigned int                                      \
 clear_c0_##name(unsigned int clear)                            \
 {                                                              \
        unsigned int res;                                       \
+       unsigned int omt;                                       \
+       unsigned int flags;                                     \
                                                                \
+       local_irq_save(flags);                                  \
+       omt = __dmt();                                          \
        res = read_c0_##name();                                 \
        res &= ~clear;                                          \
        write_c0_##name(res);                                   \
+       __emt(omt);                                             \
+       local_irq_restore(flags);                               \
                                                                \
        return res;                                             \
 }                                                              \
@@ -1383,14 +1511,22 @@ static inline unsigned int                                      \
 change_c0_##name(unsigned int change, unsigned int new)                \
 {                                                              \
        unsigned int res;                                       \
+       unsigned int omt;                                       \
+       unsigned int flags;                                     \
                                                                \
+       local_irq_save(flags);                                  \
+                                                               \
+       omt = __dmt();                                          \
        res = read_c0_##name();                                 \
        res &= ~change;                                         \
        res |= (new & change);                                  \
        write_c0_##name(res);                                   \
+       __emt(omt);                                             \
+       local_irq_restore(flags);                               \
                                                                \
        return res;                                             \
 }
+#endif
 
 __BUILD_SET_C0(status)
 __BUILD_SET_C0(cause)
index 61cf22588137a3505c3d469c0da618734fbea190..6e09f4c87211017602fe9adba197855294e5dc77 100644 (file)
 #include <linux/slab.h>
 #include <asm/cacheflush.h>
 #include <asm/tlbflush.h>
+#ifdef CONFIG_MIPS_MT_SMTC
+#include <asm/mipsmtregs.h>
+#include <asm/smtc.h>
+#endif /* SMTC */
 
 /*
  * For the fast tlb miss handlers, we keep a per cpu array of pointers
@@ -54,6 +58,14 @@ extern unsigned long pgd_current[];
 #define ASID_INC       0x1
 #define ASID_MASK      0xfff
 
+/* SMTC/34K debug hack - but maybe we'll keep it */
+#elif defined(CONFIG_MIPS_MT_SMTC)
+
+#define ASID_INC       0x1
+extern unsigned long smtc_asid_mask;
+#define ASID_MASK      (smtc_asid_mask)
+#define        HW_ASID_MASK    0xff
+/* End SMTC/34K debug hack */
 #else /* FIXME: not correct for R6000 */
 
 #define ASID_INC       0x1
@@ -76,6 +88,8 @@ static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
 #define ASID_VERSION_MASK  ((unsigned long)~(ASID_MASK|(ASID_MASK-1)))
 #define ASID_FIRST_VERSION ((unsigned long)(~ASID_VERSION_MASK) + 1)
 
+#ifndef CONFIG_MIPS_MT_SMTC
+/* Normal, classic MIPS get_new_mmu_context */
 static inline void
 get_new_mmu_context(struct mm_struct *mm, unsigned long cpu)
 {
@@ -91,6 +105,12 @@ get_new_mmu_context(struct mm_struct *mm, unsigned long cpu)
        cpu_context(cpu, mm) = asid_cache(cpu) = asid;
 }
 
+#else /* CONFIG_MIPS_MT_SMTC */
+
+#define get_new_mmu_context(mm,cpu) smtc_get_new_mmu_context((mm),(cpu))
+
+#endif /* CONFIG_MIPS_MT_SMTC */
+
 /*
  * Initialize the context related info for a new mm_struct
  * instance.
@@ -111,14 +131,46 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
 {
        unsigned int cpu = smp_processor_id();
        unsigned long flags;
-
+#ifdef CONFIG_MIPS_MT_SMTC
+       unsigned long oldasid;
+       unsigned long mtflags;
+       int mytlb = (smtc_status & SMTC_TLB_SHARED) ? 0 : cpu_data[cpu].vpe_id;
        local_irq_save(flags);
+       mtflags = dvpe();
+#else /* Not SMTC */
+       local_irq_save(flags);
+#endif /* CONFIG_MIPS_MT_SMTC */
 
        /* Check if our ASID is of an older version and thus invalid */
        if ((cpu_context(cpu, next) ^ asid_cache(cpu)) & ASID_VERSION_MASK)
                get_new_mmu_context(next, cpu);
-
+#ifdef CONFIG_MIPS_MT_SMTC
+       /*
+        * If the EntryHi ASID being replaced happens to be
+        * the value flagged at ASID recycling time as having
+        * an extended life, clear the bit showing it being
+        * in use by this "CPU", and if that's the last bit,
+        * free up the ASID value for use and flush any old
+        * instances of it from the TLB.
+        */
+       oldasid = (read_c0_entryhi() & ASID_MASK);
+       if(smtc_live_asid[mytlb][oldasid]) {
+               smtc_live_asid[mytlb][oldasid] &= ~(0x1 << cpu);
+               if(smtc_live_asid[mytlb][oldasid] == 0)
+                       smtc_flush_tlb_asid(oldasid);
+       }
+       /*
+        * Tread softly on EntryHi, and so long as we support
+        * having ASID_MASK smaller than the hardware maximum,
+        * make sure no "soft" bits become "hard"...
+        */
+       write_c0_entryhi((read_c0_entryhi() & ~HW_ASID_MASK)
+                       | (cpu_context(cpu, next) & ASID_MASK));
+       ehb(); /* Make sure it propagates to TCStatus */
+       evpe(mtflags);
+#else
        write_c0_entryhi(cpu_context(cpu, next));
+#endif /* CONFIG_MIPS_MT_SMTC */
        TLBMISS_HANDLER_SETUP_PGD(next->pgd);
 
        /*
@@ -151,12 +203,34 @@ activate_mm(struct mm_struct *prev, struct mm_struct *next)
        unsigned long flags;
        unsigned int cpu = smp_processor_id();
 
+#ifdef CONFIG_MIPS_MT_SMTC
+       unsigned long oldasid;
+       unsigned long mtflags;
+       int mytlb = (smtc_status & SMTC_TLB_SHARED) ? 0 : cpu_data[cpu].vpe_id;
+#endif /* CONFIG_MIPS_MT_SMTC */
+
        local_irq_save(flags);
 
        /* Unconditionally get a new ASID.  */
        get_new_mmu_context(next, cpu);
 
+#ifdef CONFIG_MIPS_MT_SMTC
+       /* See comments for similar code above */
+       mtflags = dvpe();
+       oldasid = read_c0_entryhi() & ASID_MASK;
+       if(smtc_live_asid[mytlb][oldasid]) {
+               smtc_live_asid[mytlb][oldasid] &= ~(0x1 << cpu);
+                       if(smtc_live_asid[mytlb][oldasid] == 0)
+                                smtc_flush_tlb_asid(oldasid);
+       }
+       /* See comments for similar code above */
+       write_c0_entryhi((read_c0_entryhi() & ~HW_ASID_MASK) |
+                        (cpu_context(cpu, next) & ASID_MASK));
+       ehb(); /* Make sure it propagates to TCStatus */
+       evpe(mtflags);
+#else
        write_c0_entryhi(cpu_context(cpu, next));
+#endif /* CONFIG_MIPS_MT_SMTC */
        TLBMISS_HANDLER_SETUP_PGD(next->pgd);
 
        /* mark mmu ownership change */
@@ -174,17 +248,49 @@ static inline void
 drop_mmu_context(struct mm_struct *mm, unsigned cpu)
 {
        unsigned long flags;
+#ifdef CONFIG_MIPS_MT_SMTC
+       unsigned long oldasid;
+       /* Can't use spinlock because called from TLB flush within DVPE */
+       unsigned int prevvpe;
+       int mytlb = (smtc_status & SMTC_TLB_SHARED) ? 0 : cpu_data[cpu].vpe_id;
+#endif /* CONFIG_MIPS_MT_SMTC */
 
        local_irq_save(flags);
 
        if (cpu_isset(cpu, mm->cpu_vm_mask))  {
                get_new_mmu_context(mm, cpu);
+#ifdef CONFIG_MIPS_MT_SMTC
+               /* See comments for similar code above */
+               prevvpe = dvpe();
+               oldasid = (read_c0_entryhi() & ASID_MASK);
+               if(smtc_live_asid[mytlb][oldasid]) {
+                 smtc_live_asid[mytlb][oldasid] &= ~(0x1 << cpu);
+                 if(smtc_live_asid[mytlb][oldasid] == 0)
+                       smtc_flush_tlb_asid(oldasid);
+               }
+               /* See comments for similar code above */
+               write_c0_entryhi((read_c0_entryhi() & ~HW_ASID_MASK)
+                               | cpu_asid(cpu, mm));
+               ehb(); /* Make sure it propagates to TCStatus */
+               evpe(prevvpe);
+#else /* not CONFIG_MIPS_MT_SMTC */
                write_c0_entryhi(cpu_asid(cpu, mm));
+#endif /* CONFIG_MIPS_MT_SMTC */
        } else {
                /* will get a new context next time */
+#ifndef CONFIG_MIPS_MT_SMTC
                cpu_context(cpu, mm) = 0;
+#else /* SMTC */
+               int i;
+
+               /* SMTC shares the TLB (and ASIDs) across VPEs */
+               for (i = 0; i < num_online_cpus(); i++) {
+                   if((smtc_status & SMTC_TLB_SHARED)
+                   || (cpu_data[i].vpe_id == cpu_data[cpu].vpe_id))
+                       cpu_context(i, mm) = 0;
+               }
+#endif /* CONFIG_MIPS_MT_SMTC */
        }
-
        local_irq_restore(flags);
 }
 
index 39d2bd50fecede26d52090657e08b5fe71e29f39..0fb75f0762e0b6934dbe03b18f3aace575ba5f96 100644 (file)
@@ -12,6 +12,7 @@
 #define _ASM_PROCESSOR_H
 
 #include <linux/config.h>
+#include <linux/cpumask.h>
 #include <linux/threads.h>
 
 #include <asm/cachectl.h>
@@ -107,6 +108,10 @@ struct mips_dsp_state {
 
 #define INIT_DSP {{0,},}
 
+#define INIT_CPUMASK { \
+       {0,} \
+}
+
 typedef struct {
        unsigned long seg;
 } mm_segment_t;
@@ -129,6 +134,12 @@ struct thread_struct {
 
        /* Saved fpu/fpu emulator stuff. */
        union mips_fpu_union fpu;
+#ifdef CONFIG_MIPS_MT_FPAFF
+       /* Emulated instruction count */
+       unsigned long emulated_fp;
+       /* Saved per-thread scheduler affinity mask */
+       cpumask_t user_cpus_allowed;
+#endif /* CONFIG_MIPS_MT_FPAFF */
 
        /* Saved state of the DSP ASE, if available. */
        struct mips_dsp_state dsp;
@@ -142,6 +153,7 @@ struct thread_struct {
 #define MF_LOGADE      2               /* Log address errors to syslog */
 #define MF_32BIT_REGS  4               /* also implies 16/32 fprs */
 #define MF_32BIT_ADDR  8               /* 32-bit address space (o32/n32) */
+#define MF_FPUBOUND    0x10            /* thread bound to FPU-full CPU set */
        unsigned long mflags;
        unsigned long irix_trampoline;  /* Wheee... */
        unsigned long irix_oldctx;
@@ -153,6 +165,12 @@ struct thread_struct {
 #define MF_N32         MF_32BIT_ADDR
 #define MF_N64         0
 
+#ifdef CONFIG_MIPS_MT_FPAFF
+#define FPAFF_INIT 0, INIT_CPUMASK,
+#else
+#define FPAFF_INIT
+#endif /* CONFIG_MIPS_MT_FPAFF */
+
 #define INIT_THREAD  { \
         /* \
          * saved main processor registers \
@@ -167,6 +185,10 @@ struct thread_struct {
         * saved fpu/fpu emulator stuff \
         */ \
        INIT_FPU, \
+       /* \
+        * fpu affinity state (null if not FPAFF) \
+        */ \
+       FPAFF_INIT \
        /* \
         * saved dsp/dsp emulator stuff \
         */ \
index 95c5839ac4657dac29ebc30c03d05774ea677c8b..fa9d8713c12a2615ac0e1c89ff3b22f9be683797 100644 (file)
@@ -45,6 +45,10 @@ struct pt_regs {
        unsigned long cp0_badvaddr;
        unsigned long cp0_cause;
        unsigned long cp0_epc;
+#ifdef CONFIG_MIPS_MT_SMTC
+       unsigned long cp0_tcstatus;
+       unsigned long smtc_pad;
+#endif /* CONFIG_MIPS_MT_SMTC */
 };
 
 /* Arbitrarily choose the same ptrace numbers as used by the Sparc code. */
index 90c374700977cc87091663ac5d9ac71012ce600d..3c8e3c8d1a9a5da1a3aab928ceb3bc92a4685cf8 100644 (file)
@@ -15,6 +15,7 @@
 #include <asm/asm.h>
 #include <asm/cacheops.h>
 #include <asm/cpu-features.h>
+#include <asm/mipsmtregs.h>
 
 /*
  * This macro return a properly sign-extended address suitable as base address
        "       cache   %0, %1                                  \n"     \
        "       .set    pop                                     \n"     \
        :                                                               \
-       : "i" (op), "m" (*(unsigned char *)(addr)))
+       : "i" (op), "R" (*(unsigned char *)(addr)))
+
+#ifdef CONFIG_MIPS_MT
+/*
+ * Temporary hacks for SMTC debug. Optionally force single-threaded
+ * execution during I-cache flushes.
+ */
+
+#define PROTECT_CACHE_FLUSHES 1
+
+#ifdef PROTECT_CACHE_FLUSHES
+
+extern int mt_protiflush;
+extern int mt_protdflush;
+extern void mt_cflush_lockdown(void);
+extern void mt_cflush_release(void);
+
+#define BEGIN_MT_IPROT \
+       unsigned long flags = 0;                        \
+       unsigned long mtflags = 0;                      \
+       if(mt_protiflush) {                             \
+               local_irq_save(flags);                  \
+               ehb();                                  \
+               mtflags = dvpe();                       \
+               mt_cflush_lockdown();                   \
+       }
+
+#define END_MT_IPROT \
+       if(mt_protiflush) {                             \
+               mt_cflush_release();                    \
+               evpe(mtflags);                          \
+               local_irq_restore(flags);               \
+       }
+
+#define BEGIN_MT_DPROT \
+       unsigned long flags = 0;                        \
+       unsigned long mtflags = 0;                      \
+       if(mt_protdflush) {                             \
+               local_irq_save(flags);                  \
+               ehb();                                  \
+               mtflags = dvpe();                       \
+               mt_cflush_lockdown();                   \
+       }
+
+#define END_MT_DPROT \
+       if(mt_protdflush) {                             \
+               mt_cflush_release();                    \
+               evpe(mtflags);                          \
+               local_irq_restore(flags);               \
+       }
+
+#else
+
+#define BEGIN_MT_IPROT
+#define BEGIN_MT_DPROT
+#define END_MT_IPROT
+#define END_MT_DPROT
+
+#endif /* PROTECT_CACHE_FLUSHES */
+
+#define __iflush_prologue                                              \
+       unsigned long redundance;                                       \
+       extern int mt_n_iflushes;                                       \
+       BEGIN_MT_IPROT                                                  \
+       for (redundance = 0; redundance < mt_n_iflushes; redundance++) {
+
+#define __iflush_epilogue                                              \
+       END_MT_IPROT                                                    \
+       }
+
+#define __dflush_prologue                                              \
+       unsigned long redundance;                                       \
+       extern int mt_n_dflushes;                                       \
+       BEGIN_MT_DPROT                                                  \
+       for (redundance = 0; redundance < mt_n_dflushes; redundance++) {
+
+#define __dflush_epilogue \
+       END_MT_DPROT     \
+       }
+
+#define __inv_dflush_prologue __dflush_prologue
+#define __inv_dflush_epilogue __dflush_epilogue
+#define __sflush_prologue {
+#define __sflush_epilogue }
+#define __inv_sflush_prologue __sflush_prologue
+#define __inv_sflush_epilogue __sflush_epilogue
+
+#else /* CONFIG_MIPS_MT */
+
+#define __iflush_prologue {
+#define __iflush_epilogue }
+#define __dflush_prologue {
+#define __dflush_epilogue }
+#define __inv_dflush_prologue {
+#define __inv_dflush_epilogue }
+#define __sflush_prologue {
+#define __sflush_epilogue }
+#define __inv_sflush_prologue {
+#define __inv_sflush_epilogue }
+
+#endif /* CONFIG_MIPS_MT */
 
 static inline void flush_icache_line_indexed(unsigned long addr)
 {
+       __iflush_prologue
        cache_op(Index_Invalidate_I, addr);
+       __iflush_epilogue
 }
 
 static inline void flush_dcache_line_indexed(unsigned long addr)
 {
+       __dflush_prologue
        cache_op(Index_Writeback_Inv_D, addr);
+       __dflush_epilogue
 }
 
 static inline void flush_scache_line_indexed(unsigned long addr)
@@ -56,17 +161,23 @@ static inline void flush_scache_line_indexed(unsigned long addr)
 
 static inline void flush_icache_line(unsigned long addr)
 {
+       __iflush_prologue
        cache_op(Hit_Invalidate_I, addr);
+       __iflush_epilogue
 }
 
 static inline void flush_dcache_line(unsigned long addr)
 {
+       __dflush_prologue
        cache_op(Hit_Writeback_Inv_D, addr);
+       __dflush_epilogue
 }
 
 static inline void invalidate_dcache_line(unsigned long addr)
 {
+       __dflush_prologue
        cache_op(Hit_Invalidate_D, addr);
+       __dflush_epilogue
 }
 
 static inline void invalidate_scache_line(unsigned long addr)
@@ -239,9 +350,13 @@ static inline void blast_##pfx##cache##lsize(void)                 \
                               current_cpu_data.desc.waybit;            \
        unsigned long ws, addr;                                         \
                                                                        \
+       __##pfx##flush_prologue                                         \
+                                                                       \
        for (ws = 0; ws < ws_end; ws += ws_inc)                         \
                for (addr = start; addr < end; addr += lsize * 32)      \
                        cache##lsize##_unroll32(addr|ws,indexop);       \
+                                                                       \
+       __##pfx##flush_epilogue                                         \
 }                                                                      \
                                                                        \
 static inline void blast_##pfx##cache##lsize##_page(unsigned long page)        \
@@ -249,10 +364,14 @@ static inline void blast_##pfx##cache##lsize##_page(unsigned long page)   \
        unsigned long start = page;                                     \
        unsigned long end = page + PAGE_SIZE;                           \
                                                                        \
+       __##pfx##flush_prologue                                         \
+                                                                       \
        do {                                                            \
                cache##lsize##_unroll32(start,hitop);                   \
                start += lsize * 32;                                    \
        } while (start < end);                                          \
+                                                                       \
+       __##pfx##flush_epilogue                                         \
 }                                                                      \
                                                                        \
 static inline void blast_##pfx##cache##lsize##_page_indexed(unsigned long page) \
@@ -265,9 +384,13 @@ static inline void blast_##pfx##cache##lsize##_page_indexed(unsigned long page)
                               current_cpu_data.desc.waybit;            \
        unsigned long ws, addr;                                         \
                                                                        \
+       __##pfx##flush_prologue                                         \
+                                                                       \
        for (ws = 0; ws < ws_end; ws += ws_inc)                         \
                for (addr = start; addr < end; addr += lsize * 32)      \
                        cache##lsize##_unroll32(addr|ws,indexop);       \
+                                                                       \
+       __##pfx##flush_epilogue                                         \
 }
 
 __BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 16)
@@ -288,12 +411,17 @@ static inline void prot##blast_##pfx##cache##_range(unsigned long start, \
        unsigned long lsize = cpu_##desc##_line_size();                 \
        unsigned long addr = start & ~(lsize - 1);                      \
        unsigned long aend = (end - 1) & ~(lsize - 1);                  \
+                                                                       \
+       __##pfx##flush_prologue                                         \
+                                                                       \
        while (1) {                                                     \
                prot##cache_op(hitop, addr);                            \
                if (addr == aend)                                       \
                        break;                                          \
                addr += lsize;                                          \
        }                                                               \
+                                                                       \
+       __##pfx##flush_epilogue                                         \
 }
 
 __BUILD_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D, protected_)
index a2abc4572b638e5bf33cd59f3bdcb121c1d42865..82ad401c7dcae6839d5ea6b0e7181ce6fca84822 100644 (file)
@@ -32,7 +32,7 @@ static inline unsigned int get_rtc_time(struct rtc_time *time)
 {
        unsigned long nowtime;
 
-       nowtime = rtc_get_time();
+       nowtime = rtc_mips_get_time();
        to_tm(nowtime, time);
        time->tm_year -= 1900;
 
@@ -47,7 +47,7 @@ static inline int set_rtc_time(struct rtc_time *time)
        nowtime = mktime(time->tm_year+1900, time->tm_mon+1,
                        time->tm_mday, time->tm_hour, time->tm_min,
                        time->tm_sec);
-       ret = rtc_set_time(nowtime);
+       ret = rtc_mips_set_time(nowtime);
 
        return ret;
 }
index 1298c3fdf6c99b393dbaf118dd429d22672e4cb3..76cd51c6be397979beb615f70914b413f9ccfef1 100644 (file)
@@ -3,32 +3,46 @@
  *
  */
 
-#ifndef _RTLX_H
-#define _RTLX_H_
+#ifndef __ASM_RTLX_H
+#define __ASM_RTLX_H_
 
 #define LX_NODE_BASE 10
 
 #define MIPSCPU_INT_BASE       16
 #define MIPS_CPU_RTLX_IRQ 0
 
-#define RTLX_VERSION 1
+#define RTLX_VERSION 2
 #define RTLX_xID 0x12345600
 #define RTLX_ID (RTLX_xID | RTLX_VERSION)
 #define RTLX_CHANNELS 8
 
-#define RTLX_BUFFER_SIZE 1024
+#define RTLX_CHANNEL_STDIO     0
+#define RTLX_CHANNEL_DBG       1
+#define RTLX_CHANNEL_SYSIO     2
 
-/*
- * lx_state bits
- */
-#define RTLX_STATE_OPENED 1UL
+extern int rtlx_open(int index, int can_sleep);
+extern int rtlx_release(int index);
+extern ssize_t rtlx_read(int index, void *buff, size_t count, int user);
+extern ssize_t rtlx_write(int index, void *buffer, size_t count, int user);
+extern unsigned int rtlx_read_poll(int index, int can_sleep);
+extern unsigned int rtlx_write_poll(int index);
+
+enum rtlx_state {
+       RTLX_STATE_UNUSED,
+       RTLX_STATE_INITIALISED,
+       RTLX_STATE_REMOTE_READY,
+       RTLX_STATE_OPENED
+};
+
+#define RTLX_BUFFER_SIZE 1024
 
 /* each channel supports read and write.
    linux (vpe0) reads lx_buffer  and writes rt_buffer
    SP (vpe1) reads rt_buffer and writes lx_buffer
 */
 struct rtlx_channel {
-       unsigned long lx_state;
+       enum rtlx_state rt_state;
+       enum rtlx_state lx_state;
 
        int buffer_size;
 
@@ -38,15 +52,13 @@ struct rtlx_channel {
 
        int lx_write, lx_read;
        char *lx_buffer;
-
-       void *queues;
-
 };
 
 struct rtlx_info {
        unsigned long id;
+       enum rtlx_state state;
 
        struct rtlx_channel channel[RTLX_CHANNELS];
 };
 
-#endif /* _RTLX_H_ */
+#endif /* __ASM_RTLX_H_ */
index 7b236641220381122fe44c79385c3282b57d647e..7196ceb0e94821988a2bea67bff64e90568b5c32 100644 (file)
 #include <asm/it8712.h>
 #define ITE_SERIAL_PORT_DEFNS                                  \
     { .baud_base = BASE_BAUD, .port = (IT8172_PCI_IO_BASE + IT_UART_BASE), \
-      .irq = IT8172_UART_IRQ, .flags = STD_COM_FLAGS, .type = 0x3 }, \
+      .irq = IT8172_UART_IRQ, .flags = STD_COM_FLAGS, .port = PORT_16550 }, \
     { .baud_base = (24000000/(16*13)), .port = (IT8172_PCI_IO_BASE + IT8712_UART1_PORT), \
-      .irq = IT8172_SERIRQ_4, .flags = STD_COM_FLAGS, .type = 0x3 }, \
+      .irq = IT8172_SERIRQ_4, .flags = STD_COM_FLAGS, .port = PORT_16550 }, \
     /* Smart Card Reader 0 */ \
     { .baud_base = BASE_BAUD, .port = (IT8172_PCI_IO_BASE + IT_SCR0_BASE), \
-      .irq = IT8172_SCR0_IRQ, .flags = STD_COM_FLAGS, .type = 0x3 }, \
+      .irq = IT8172_SCR0_IRQ, .flags = STD_COM_FLAGS, .port = PORT_16550 }, \
     /* Smart Card Reader 1 */ \
     { .baud_base = BASE_BAUD, .port = (IT8172_PCI_IO_BASE + IT_SCR1_BASE), \
-      .irq = IT8172_SCR1_IRQ, .flags = STD_COM_FLAGS, .type = 0x3 },
+      .irq = IT8172_SCR1_IRQ, .flags = STD_COM_FLAGS, .port = PORT_16550 },
 #else
 #define ITE_SERIAL_PORT_DEFNS
 #endif
 #include <asm/it8172/it8172_int.h>
 #define IVR_SERIAL_PORT_DEFNS                                  \
     { .baud_base = BASE_BAUD, .port = (IT8172_PCI_IO_BASE + IT_UART_BASE), \
-      .irq = IT8172_UART_IRQ, .flags = STD_COM_FLAGS, .type = 0x3 },         \
+      .irq = IT8172_UART_IRQ, .flags = STD_COM_FLAGS, .port = PORT_16550 },         \
     /* Smart Card Reader 1 */ \
     { .baud_base = BASE_BAUD, .port = (IT8172_PCI_IO_BASE + IT_SCR1_BASE), \
-      .irq = IT8172_SCR1_IRQ, .flags = STD_COM_FLAGS, .type = 0x3 },
+      .irq = IT8172_SCR1_IRQ, .flags = STD_COM_FLAGS, .port = PORT_16550 },
 #else
 #define IVR_SERIAL_PORT_DEFNS
 #endif
diff --git a/include/asm-mips/smtc.h b/include/asm-mips/smtc.h
new file mode 100644 (file)
index 0000000..e1941d1
--- /dev/null
@@ -0,0 +1,55 @@
+#ifndef _ASM_SMTC_MT_H
+#define _ASM_SMTC_MT_H
+
+/*
+ * Definitions for SMTC multitasking on MIPS MT cores
+ */
+
+#include <asm/mips_mt.h>
+
+/*
+ * System-wide SMTC status information
+ */
+
+extern unsigned int smtc_status;
+
+#define SMTC_TLB_SHARED        0x00000001
+#define SMTC_MTC_ACTIVE        0x00000002
+
+/*
+ * TLB/ASID Management information
+ */
+
+#define MAX_SMTC_TLBS 2
+#define MAX_SMTC_ASIDS 256
+#if NR_CPUS <= 8
+typedef char asiduse;
+#else
+#if NR_CPUS <= 16
+typedef short asiduse;
+#else
+typedef long asiduse;
+#endif
+#endif
+
+extern asiduse smtc_live_asid[MAX_SMTC_TLBS][MAX_SMTC_ASIDS];
+
+void smtc_get_new_mmu_context(struct mm_struct *mm, unsigned long cpu);
+
+void smtc_flush_tlb_asid(unsigned long asid);
+extern int mipsmt_build_cpu_map(int startslot);
+extern void mipsmt_prepare_cpus(void);
+extern void smtc_smp_finish(void);
+extern void smtc_boot_secondary(int cpu, struct task_struct *t);
+
+/*
+ * Sharing the TLB between multiple VPEs means that the
+ * "random" index selection function is not allowed to
+ * select the current value of the Index register. To
+ * avoid additional TLB pressure, the Index registers
+ * are "parked" with an non-Valid value.
+ */
+
+#define PARKED_INDEX   ((unsigned int)0x80000000)
+
+#endif /*  _ASM_SMTC_MT_H */
diff --git a/include/asm-mips/smtc_ipi.h b/include/asm-mips/smtc_ipi.h
new file mode 100644 (file)
index 0000000..f22c3e2
--- /dev/null
@@ -0,0 +1,118 @@
+/*
+ * Definitions used in MIPS MT SMTC "Interprocessor Interrupt" code.
+ */
+#ifndef __ASM_SMTC_IPI_H
+#define __ASM_SMTC_IPI_H
+
+//#define SMTC_IPI_DEBUG
+
+#ifdef SMTC_IPI_DEBUG
+#include <asm/mipsregs.h>
+#include <asm/mipsmtregs.h>
+#endif /* SMTC_IPI_DEBUG */
+
+/*
+ * An IPI "message"
+ */
+
+struct smtc_ipi {
+       struct smtc_ipi *flink;
+       int type;
+       void *arg;
+       int dest;
+#ifdef SMTC_IPI_DEBUG
+       int sender;
+       long stamp;
+#endif /* SMTC_IPI_DEBUG */
+};
+
+/*
+ * Defined IPI Types
+ */
+
+#define LINUX_SMP_IPI 1
+#define SMTC_CLOCK_TICK 2
+
+/*
+ * A queue of IPI messages
+ */
+
+struct smtc_ipi_q {
+       struct smtc_ipi *head;
+       spinlock_t lock;
+       struct smtc_ipi *tail;
+       int depth;
+};
+
+extern struct smtc_ipi_q IPIQ[NR_CPUS];
+extern struct smtc_ipi_q freeIPIq;
+
+static inline void smtc_ipi_nq(struct smtc_ipi_q *q, struct smtc_ipi *p)
+{
+       long flags;
+
+       spin_lock_irqsave(&q->lock, flags);
+       if (q->head == NULL)
+               q->head = q->tail = p;
+       else
+               q->tail->flink = p;
+       p->flink = NULL;
+       q->tail = p;
+       q->depth++;
+#ifdef SMTC_IPI_DEBUG
+       p->sender = read_c0_tcbind();
+       p->stamp = read_c0_count();
+#endif /* SMTC_IPI_DEBUG */
+       spin_unlock_irqrestore(&q->lock, flags);
+}
+
+static inline struct smtc_ipi *smtc_ipi_dq(struct smtc_ipi_q *q)
+{
+       struct smtc_ipi *p;
+       long flags;
+
+       spin_lock_irqsave(&q->lock, flags);
+       if (q->head == NULL)
+               p = NULL;
+       else {
+               p = q->head;
+               q->head = q->head->flink;
+               q->depth--;
+               /* Arguably unnecessary, but leaves queue cleaner */
+               if (q->head == NULL)
+                       q->tail = NULL;
+       }
+       spin_unlock_irqrestore(&q->lock, flags);
+       return p;
+}
+
+static inline void smtc_ipi_req(struct smtc_ipi_q *q, struct smtc_ipi *p)
+{
+       long flags;
+
+       spin_lock_irqsave(&q->lock, flags);
+       if (q->head == NULL) {
+               q->head = q->tail = p;
+               p->flink = NULL;
+       } else {
+               p->flink = q->head;
+               q->head = p;
+       }
+       q->depth++;
+       spin_unlock_irqrestore(&q->lock, flags);
+}
+
+static inline int smtc_ipi_qdepth(struct smtc_ipi_q *q)
+{
+       long flags;
+       int retval;
+
+       spin_lock_irqsave(&q->lock, flags);
+       retval = q->depth;
+       spin_unlock_irqrestore(&q->lock, flags);
+       return retval;
+}
+
+extern void smtc_send_ipi(int cpu, int type, unsigned int action);
+
+#endif /* __ASM_SMTC_IPI_H */
diff --git a/include/asm-mips/smtc_proc.h b/include/asm-mips/smtc_proc.h
new file mode 100644 (file)
index 0000000..25da651
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * Definitions for SMTC /proc entries
+ * Copyright(C) 2005 MIPS Technologies Inc.
+ */
+#ifndef __ASM_SMTC_PROC_H
+#define __ASM_SMTC_PROC_H
+
+/*
+ * per-"CPU" statistics
+ */
+
+struct smtc_cpu_proc {
+       unsigned long timerints;
+       unsigned long selfipis;
+};
+
+extern struct smtc_cpu_proc smtc_cpu_stats[NR_CPUS];
+
+/* Count of number of recoveries of "stolen" FPU access rights on 34K */
+
+extern atomic_t smtc_fpu_recoveries;
+
+#endif /* __ASM_SMTC_PROC_H */
index 2acf3e844f0001951dcad3ed848eccdde9cba824..c4856a874965f3ad851808c9ec7886fd45bcd2a7 100644 (file)
 #include <linux/threads.h>
 
 #include <asm/asm.h>
+#include <asm/asmmacro.h>
 #include <asm/mipsregs.h>
 #include <asm/asm-offsets.h>
 
+#ifdef CONFIG_MIPS_MT_SMTC
+#include <asm/mipsmtregs.h>
+#endif /* CONFIG_MIPS_MT_SMTC */
+
                .macro  SAVE_AT
                .set    push
                .set    noat
 #ifdef CONFIG_SMP
                .macro  get_saved_sp    /* SMP variation */
 #ifdef CONFIG_32BIT
+#ifdef CONFIG_MIPS_MT_SMTC
+               .set    mips32
+               mfc0    k0, CP0_TCBIND;
+               .set    mips0
+               lui     k1, %hi(kernelsp)
+               srl     k0, k0, 19
+               /* No need to shift down and up to clear bits 0-1 */
+#else
                mfc0    k0, CP0_CONTEXT
                lui     k1, %hi(kernelsp)
                srl     k0, k0, 23
+#endif
                addu    k1, k0
                LONG_L  k1, %lo(kernelsp)(k1)
 #endif
 #ifdef CONFIG_64BIT
+#ifdef CONFIG_MIPS_MT_SMTC
+               .set    mips64
+               mfc0    k0, CP0_TCBIND;
+               .set    mips0
+               lui     k0, %highest(kernelsp)
+               dsrl    k1, 19
+               /* No need to shift down and up to clear bits 0-2 */
+#else
                MFC0    k1, CP0_CONTEXT
                lui     k0, %highest(kernelsp)
                dsrl    k1, 23
                dsll    k0, k0, 16
                daddiu  k0, %hi(kernelsp)
                dsll    k0, k0, 16
+#endif /* CONFIG_MIPS_MT_SMTC */
                daddu   k1, k1, k0
                LONG_L  k1, %lo(kernelsp)(k1)
-#endif
+#endif /* CONFIG_64BIT */
                .endm
 
                .macro  set_saved_sp stackp temp temp2
 #ifdef CONFIG_32BIT
+#ifdef CONFIG_MIPS_MT_SMTC
+               mfc0    \temp, CP0_TCBIND
+               srl     \temp, 19
+#else
                mfc0    \temp, CP0_CONTEXT
                srl     \temp, 23
 #endif
+#endif
 #ifdef CONFIG_64BIT
+#ifdef CONFIG_MIPS_MT_SMTC
+               mfc0    \temp, CP0_TCBIND
+               dsrl    \temp, 19
+#else
                MFC0    \temp, CP0_CONTEXT
                dsrl    \temp, 23
+#endif
 #endif
                LONG_S  \stackp, kernelsp(\temp)
                .endm
                PTR_SUBU sp, k1, PT_SIZE
                LONG_S  k0, PT_R29(sp)
                LONG_S  $3, PT_R3(sp)
+               /*
+                * You might think that you don't need to save $0,
+                * but the FPU emulator and gdb remote debug stub
+                * need it to operate correctly
+                */
                LONG_S  $0, PT_R0(sp)
                mfc0    v1, CP0_STATUS
                LONG_S  $2, PT_R2(sp)
                LONG_S  v1, PT_STATUS(sp)
+#ifdef CONFIG_MIPS_MT_SMTC
+               /*
+                * Ideally, these instructions would be shuffled in
+                * to cover the pipeline delay.
+                */
+               .set    mips32
+               mfc0    v1, CP0_TCSTATUS
+               .set    mips0
+               LONG_S  v1, PT_TCSTATUS(sp)
+#endif /* CONFIG_MIPS_MT_SMTC */
                LONG_S  $4, PT_R4(sp)
                mfc0    v1, CP0_CAUSE
                LONG_S  $5, PT_R5(sp)
                .endm
 
 #else
+/*
+ * For SMTC kernel, global IE should be left set, and interrupts
+ * controlled exclusively via IXMT.
+ */
 
+#ifdef CONFIG_MIPS_MT_SMTC
+#define STATMASK 0x1e
+#else
+#define STATMASK 0x1f
+#endif
                .macro  RESTORE_SOME
                .set    push
                .set    reorder
                .set    noat
+#ifdef CONFIG_MIPS_MT_SMTC
+               .set    mips32r2
+               /*
+                * This may not really be necessary if ints are already
+                * inhibited here.
+                */
+               mfc0    v0, CP0_TCSTATUS
+               ori     v0, TCSTATUS_IXMT
+               mtc0    v0, CP0_TCSTATUS
+               ehb
+               DMT     5                               # dmt a1
+               jal     mips_ihb
+#endif /* CONFIG_MIPS_MT_SMTC */
                mfc0    a0, CP0_STATUS
-               ori     a0, 0x1f
-               xori    a0, 0x1f
+               ori     a0, STATMASK
+               xori    a0, STATMASK
                mtc0    a0, CP0_STATUS
                li      v1, 0xff00
                and     a0, v1
                and     v0, v1
                or      v0, a0
                mtc0    v0, CP0_STATUS
+#ifdef CONFIG_MIPS_MT_SMTC
+/*
+ * Only after EXL/ERL have been restored to status can we
+ * restore TCStatus.IXMT.
+ */
+               LONG_L  v1, PT_TCSTATUS(sp)
+               ehb
+               mfc0    v0, CP0_TCSTATUS
+               andi    v1, TCSTATUS_IXMT
+               /* We know that TCStatua.IXMT should be set from above */
+               xori    v0, v0, TCSTATUS_IXMT
+               or      v0, v0, v1
+               mtc0    v0, CP0_TCSTATUS
+               ehb
+               andi    a1, a1, VPECONTROL_TE
+               beqz    a1, 1f
+               emt
+1:
+               .set    mips0
+#endif /* CONFIG_MIPS_MT_SMTC */
                LONG_L  v1, PT_EPC(sp)
                MTC0    v1, CP0_EPC
                LONG_L  $31, PT_R31(sp)
  * Set cp0 enable bit as sign that we're running on the kernel stack
  */
                .macro  CLI
+#if !defined(CONFIG_MIPS_MT_SMTC)
                mfc0    t0, CP0_STATUS
                li      t1, ST0_CU0 | 0x1f
                or      t0, t1
                xori    t0, 0x1f
                mtc0    t0, CP0_STATUS
+#else /* CONFIG_MIPS_MT_SMTC */
+               /*
+                * For SMTC, we need to set privilege
+                * and disable interrupts only for the
+                * current TC, using the TCStatus register.
+                */
+               mfc0    t0,CP0_TCSTATUS
+               /* Fortunately CU 0 is in the same place in both registers */
+               /* Set TCU0, TMX, TKSU (for later inversion) and IXMT */
+               li      t1, ST0_CU0 | 0x08001c00
+               or      t0,t1
+               /* Clear TKSU, leave IXMT */
+               xori    t0, 0x00001800
+               mtc0    t0, CP0_TCSTATUS
+               ehb
+               /* We need to leave the global IE bit set, but clear EXL...*/
+               mfc0    t0, CP0_STATUS
+               ori     t0, ST0_EXL | ST0_ERL
+               xori    t0, ST0_EXL | ST0_ERL
+               mtc0    t0, CP0_STATUS
+#endif /* CONFIG_MIPS_MT_SMTC */
                irq_disable_hazard
                .endm
 
  * Set cp0 enable bit as sign that we're running on the kernel stack
  */
                .macro  STI
+#if !defined(CONFIG_MIPS_MT_SMTC)
                mfc0    t0, CP0_STATUS
                li      t1, ST0_CU0 | 0x1f
                or      t0, t1
                xori    t0, 0x1e
                mtc0    t0, CP0_STATUS
+#else /* CONFIG_MIPS_MT_SMTC */
+               /*
+                * For SMTC, we need to set privilege
+                * and enable interrupts only for the
+                * current TC, using the TCStatus register.
+                */
+               ehb
+               mfc0    t0,CP0_TCSTATUS
+               /* Fortunately CU 0 is in the same place in both registers */
+               /* Set TCU0, TKSU (for later inversion) and IXMT */
+               li      t1, ST0_CU0 | 0x08001c00
+               or      t0,t1
+               /* Clear TKSU *and* IXMT */
+               xori    t0, 0x00001c00
+               mtc0    t0, CP0_TCSTATUS
+               ehb
+               /* We need to leave the global IE bit set, but clear EXL...*/
+               mfc0    t0, CP0_STATUS
+               ori     t0, ST0_EXL
+               xori    t0, ST0_EXL
+               mtc0    t0, CP0_STATUS
+               /* irq_enable_hazard below should expand to EHB for 24K/34K cpus */
+#endif /* CONFIG_MIPS_MT_SMTC */
                irq_enable_hazard
                .endm
 
  * Set cp0 enable bit as sign that we're running on the kernel stack
  */
                .macro  KMODE
+#ifdef CONFIG_MIPS_MT_SMTC
+               /*
+                * This gets baroque in SMTC.  We want to
+                * protect the non-atomic clearing of EXL
+                * with DMT/EMT, but we don't want to take
+                * an interrupt while DMT is still in effect.
+                */
+
+               /* KMODE gets invoked from both reorder and noreorder code */
+               .set    push
+               .set    mips32r2
+               .set    noreorder
+               mfc0    v0, CP0_TCSTATUS
+               andi    v1, v0, TCSTATUS_IXMT
+               ori     v0, TCSTATUS_IXMT
+               mtc0    v0, CP0_TCSTATUS
+               ehb
+               DMT     2                               # dmt   v0
+               /*
+                * We don't know a priori if ra is "live"
+                */
+               move    t0, ra
+               jal     mips_ihb
+               nop     /* delay slot */
+               move    ra, t0
+#endif /* CONFIG_MIPS_MT_SMTC */
                mfc0    t0, CP0_STATUS
                li      t1, ST0_CU0 | 0x1e
                or      t0, t1
                xori    t0, 0x1e
                mtc0    t0, CP0_STATUS
+#ifdef CONFIG_MIPS_MT_SMTC
+               ehb
+               andi    v0, v0, VPECONTROL_TE
+               beqz    v0, 2f
+               nop     /* delay slot */
+               emt
+2:
+               mfc0    v0, CP0_TCSTATUS
+               /* Clear IXMT, then OR in previous value */
+               ori     v0, TCSTATUS_IXMT
+               xori    v0, TCSTATUS_IXMT
+               or      v0, v1, v0
+               mtc0    v0, CP0_TCSTATUS
+               /*
+                * irq_disable_hazard below should expand to EHB
+                * on 24K/34K CPUS
+                */
+               .set pop
+#endif /* CONFIG_MIPS_MT_SMTC */
                irq_disable_hazard
                .endm
 
index 4097fac5ac3cf66874a248b18ae0cba66adffe16..261f71d16a074f4dd4b3ab2fc2d42ba2c583d2e9 100644 (file)
@@ -155,6 +155,37 @@ extern asmlinkage void *resume(void *last, void *next, void *next_ti);
 
 struct task_struct;
 
+#ifdef CONFIG_MIPS_MT_FPAFF
+
+/*
+ * Handle the scheduler resume end of FPU affinity management.  We do this
+ * inline to try to keep the overhead down. If we have been forced to run on
+ * a "CPU" with an FPU because of a previous high level of FP computation,
+ * but did not actually use the FPU during the most recent time-slice (CU1
+ * isn't set), we undo the restriction on cpus_allowed.
+ *
+ * We're not calling set_cpus_allowed() here, because we have no need to
+ * force prompt migration - we're already switching the current CPU to a
+ * different thread.
+ */
+
+#define switch_to(prev,next,last)                                      \
+do {                                                                   \
+       if (cpu_has_fpu &&                                              \
+           (prev->thread.mflags & MF_FPUBOUND) &&                      \
+            (!(KSTK_STATUS(prev) & ST0_CU1))) {                        \
+               prev->thread.mflags &= ~MF_FPUBOUND;                    \
+               prev->cpus_allowed = prev->thread.user_cpus_allowed;    \
+       }                                                               \
+       if (cpu_has_dsp)                                                \
+               __save_dsp(prev);                                       \
+       next->thread.emulated_fp = 0;                                   \
+       (last) = resume(prev, next, next->thread_info);                 \
+       if (cpu_has_dsp)                                                \
+               __restore_dsp(current);                                 \
+} while(0)
+
+#else
 #define switch_to(prev,next,last)                                      \
 do {                                                                   \
        if (cpu_has_dsp)                                                \
@@ -163,6 +194,7 @@ do {                                                                        \
        if (cpu_has_dsp)                                                \
                __restore_dsp(current);                                 \
 } while(0)
+#endif
 
 /*
  * On SMP systems, when the scheduler does migration-cost autodetection,
@@ -440,8 +472,8 @@ static inline unsigned long __cmpxchg(volatile void * ptr, unsigned long old,
 extern void set_handler (unsigned long offset, void *addr, unsigned long len);
 extern void set_uncached_handler (unsigned long offset, void *addr, unsigned long len);
 extern void *set_vi_handler (int n, void *addr);
-extern void *set_vi_srs_handler (int n, void *addr, int regset);
 extern void *set_except_vector(int n, void *addr);
+extern unsigned long ebase;
 extern void per_cpu_trap_init(void);
 
 extern NORET_TYPE void die(const char *, struct pt_regs *);
index b5c78a4a019210cdfd9e140a2c74c3c3fd43158b..1068fe9a0a583cff6f272357733f1f664833a7f7 100644 (file)
 #define __NR_pselect6                  (__NR_Linux + 301)
 #define __NR_ppoll                     (__NR_Linux + 302)
 #define __NR_unshare                   (__NR_Linux + 303)
+#define __NR_splice                    (__NR_Linux + 304)
+#define __NR_sync_file_range           (__NR_Linux + 305)
 
 /*
  * Offset of the last Linux o32 flavoured syscall
  */
-#define __NR_Linux_syscalls            303
+#define __NR_Linux_syscalls            305
 
 #endif /* _MIPS_SIM == _MIPS_SIM_ABI32 */
 
 #define __NR_O32_Linux                 4000
-#define __NR_O32_Linux_syscalls                303
+#define __NR_O32_Linux_syscalls                305
 
 #if _MIPS_SIM == _MIPS_SIM_ABI64
 
 #define __NR_pselect6                  (__NR_Linux + 260)
 #define __NR_ppoll                     (__NR_Linux + 261)
 #define __NR_unshare                   (__NR_Linux + 262)
+#define __NR_splice                    (__NR_Linux + 263)
+#define __NR_sync_file_range           (__NR_Linux + 264)
 
 /*
  * Offset of the last Linux 64-bit flavoured syscall
  */
-#define __NR_Linux_syscalls            262
+#define __NR_Linux_syscalls            264
 
 #endif /* _MIPS_SIM == _MIPS_SIM_ABI64 */
 
 #define __NR_64_Linux                  5000
-#define __NR_64_Linux_syscalls         262
+#define __NR_64_Linux_syscalls         264
 
 #if _MIPS_SIM == _MIPS_SIM_NABI32
 
 #define __NR_pselect6                  (__NR_Linux + 264)
 #define __NR_ppoll                     (__NR_Linux + 265)
 #define __NR_unshare                   (__NR_Linux + 266)
+#define __NR_splice                    (__NR_Linux + 267)
+#define __NR_sync_file_range           (__NR_Linux + 268)
 
 /*
  * Offset of the last N32 flavoured syscall
  */
-#define __NR_Linux_syscalls            266
+#define __NR_Linux_syscalls            268
 
 #endif /* _MIPS_SIM == _MIPS_SIM_NABI32 */
 
 #define __NR_N32_Linux                 6000
-#define __NR_N32_Linux_syscalls                266
+#define __NR_N32_Linux_syscalls                268
 
 #ifndef __ASSEMBLY__
 
diff --git a/include/asm-mips/vpe.h b/include/asm-mips/vpe.h
new file mode 100644 (file)
index 0000000..c6e1b96
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2005 MIPS Technologies, Inc.  All rights reserved.
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope 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.
+ *
+ */
+
+#ifndef _ASM_VPE_H
+#define _ASM_VPE_H
+
+struct vpe_notifications {
+       void (*start)(int vpe);
+       void (*stop)(int vpe);
+
+       struct list_head list;
+};
+
+
+extern int vpe_notify(int index, struct vpe_notifications *notify);
+
+extern void *vpe_get_shared(int index);
+extern int vpe_getuid(int index);
+extern int vpe_getgid(int index);
+extern char *vpe_getcwd(int index);
+
+#endif /* _ASM_VPE_H */
index 51f87d9993b6d09e2833f2ff403a58783c61d7bf..7bc6d73b2823c5032852d3b1ae57b8db569795e8 100644 (file)
  */
 extern unsigned int virt_irq_to_real_map[NR_IRQS];
 
+/* The maximum virtual IRQ number that we support.  This
+ * can be set by the platform and will be reduced by the
+ * value of __irq_offset_value.  It defaults to and is
+ * capped by (NR_IRQS - 1).
+ */
+extern unsigned int virt_irq_max;
+
 /* Create a mapping for a real_irq if it doesn't already exist.
  * Return the virtual irq as a convenience.
  */
index ffc7462d77ba752f1d803a73326a09a48531f026..88b553c6b26c9b461660b8de1f31c98c87c86a68 100644 (file)
@@ -37,6 +37,8 @@ struct thread_info {
        int             preempt_count;          /* 0 => preemptable,
                                                   <0 => BUG */
        struct restart_block restart_block;
+       unsigned long   local_flags;            /* private flags for thread */
+
        /* low level flags - has atomic operations done on it */
        unsigned long   flags ____cacheline_aligned_in_smp;
 };
@@ -143,6 +145,12 @@ static inline struct thread_info *current_thread_info(void)
                                 _TIF_NEED_RESCHED | _TIF_RESTORE_SIGMASK)
 #define _TIF_PERSYSCALL_MASK   (_TIF_RESTOREALL|_TIF_NOERROR)
 
+/* Bits in local_flags */
+/* Don't move TLF_NAPPING without adjusting the code in entry_32.S */
+#define TLF_NAPPING            0       /* idle thread enabled NAP mode */
+
+#define _TLF_NAPPING           (1 << TLF_NAPPING)
+
 #endif /* __KERNEL__ */
 
 #endif /* _ASM_POWERPC_THREAD_INFO_H */
index 2a911aa4cae9f8578d2410a2d26fe07f8c868540..45feff893b8e0f9df1d5c60b6bd4ec423a150058 100644 (file)
 #define __NR_setfsgid           229 /* Linux Specific                              */
 #define __NR__newselect         230 /* Linux Specific                              */
 #define __NR_time               231 /* Linux Specific                              */
-#define __NR_sys_splice         232 /* Linux Specific                              */
+#define __NR_splice             232 /* Linux Specific                              */
 #define __NR_stime              233 /* Linux Specific                              */
 #define __NR_statfs64           234 /* Linux Specific                              */
 #define __NR_fstatfs64          235 /* Linux Specific                              */
index 6ada6a871cc8b60b3eaf4deb9b1ca158660c3894..597f6923a46eec7665cb887a0c2b7e9b51404f1c 100644 (file)
 #ifdef __KERNEL__
 #define __NR_time              231 /* Linux sparc32                               */
 #endif
-#define __NR_sys_splice         232 /* Linux Specific                              */
+#define __NR_splice             232 /* Linux Specific                              */
 #define __NR_stime              233 /* Linux Specific                              */
 #define __NR_statfs64           234 /* Linux Specific                              */
 #define __NR_fstatfs64          235 /* Linux Specific                              */
index c8043a16152e31fc52d3a48c32ae94ec2155eed9..f8dff1c67538b75381964b6c5c7b4dd3dcc9b37d 100644 (file)
@@ -20,8 +20,8 @@
        __attribute__((__section__(".data.page_aligned")))
 #endif
 
-#define __read_mostly __attribute__((__section__(".data.read_mostly")))
-
 #endif
 
+#define __read_mostly __attribute__((__section__(".data.read_mostly")))
+
 #endif
index 76bb6193ae9107a380ac6b754d5dd498869eef5f..662964b74e348f228fbb9c874567c574d6339175 100644 (file)
@@ -64,6 +64,7 @@
 #define X86_FEATURE_REP_GOOD   (3*32+ 4) /* rep microcode works well on this CPU */
 #define X86_FEATURE_CONSTANT_TSC (3*32+5) /* TSC runs at constant rate */
 #define X86_FEATURE_SYNC_RDTSC  (3*32+6)  /* RDTSC syncs CPU core */
+#define X86_FEATURE_FXSAVE_LEAK (3*32+7)  /* FIP/FOP/FDP leaks through FXSAVE */
 
 /* Intel-defined CPU features, CPUID level 0x00000001 (ecx), word 4 */
 #define X86_FEATURE_XMM3       (4*32+ 0) /* Streaming SIMD Extensions-3 */
index 876eb9a2fe7868a7c7ce01ef694403b3150f4601..cba8a3b0cded5a77191d9528710b04c85bc13c5b 100644 (file)
@@ -72,6 +72,23 @@ extern int set_fpregs(struct task_struct *tsk,
 #define set_fpu_swd(t,val) ((t)->thread.i387.fxsave.swd = (val))
 #define set_fpu_fxsr_twd(t,val) ((t)->thread.i387.fxsave.twd = (val))
 
+#define X87_FSW_ES (1 << 7)    /* Exception Summary */
+
+/* AMD CPUs don't save/restore FDP/FIP/FOP unless an exception
+   is pending. Clear the x87 state here by setting it to fixed
+   values. The kernel data segment can be sometimes 0 and sometimes
+   new user value. Both should be ok.
+   Use the PDA as safe address because it should be already in L1. */
+static inline void clear_fpu_state(struct i387_fxsave_struct *fx)
+{
+       if (unlikely(fx->swd & X87_FSW_ES))
+                asm volatile("fnclex");
+       alternative_input(ASM_NOP8 ASM_NOP2,
+                    "    emms\n"               /* clear stack tags */
+                    "    fildl %%gs:0",        /* load to clear state */
+                    X86_FEATURE_FXSAVE_LEAK);
+}
+
 static inline int restore_fpu_checking(struct i387_fxsave_struct *fx) 
 { 
        int err;
@@ -119,6 +136,7 @@ static inline int save_i387_checking(struct i387_fxsave_struct __user *fx)
 #endif
        if (unlikely(err))
                __clear_user(fx, sizeof(struct i387_fxsave_struct));
+       /* No need to clear here because the caller clears USED_MATH */
        return err;
 } 
 
@@ -149,7 +167,7 @@ static inline void __fxsave_clear(struct task_struct *tsk)
                                "i" (offsetof(__typeof__(*tsk),
                                              thread.i387.fxsave)));
 #endif
-       __asm__ __volatile__("fnclex");
+       clear_fpu_state(&tsk->thread.i387.fxsave);
 }
 
 static inline void kernel_fpu_begin(void)
index 6b18cd8f293d731d4908e52799131e1ff3bcc645..6944e7122df5194c767217444a993a90db3d6ede 100644 (file)
@@ -12,7 +12,8 @@
 
 #include <asm/smp.h>
 
-#define NODEMAPSIZE 0xfff
+/* Should really switch to dynamic allocation at some point */
+#define NODEMAPSIZE 0x4fff
 
 /* Simple perfect hash to map physical addresses to node numbers */
 struct memnode {
index 4405b4adeabad5e09a0d014f578dd8f618433740..7f33aaf9f7b1870c1b58d9de974712c004809182 100644 (file)
@@ -26,7 +26,7 @@
 #define percpu_modcopy(pcpudst, src, size)                     \
 do {                                                           \
        unsigned int __i;                                       \
-       for_each_cpu(__i)                                       \
+       for_each_possible_cpu(__i)                              \
                memcpy((pcpudst)+__per_cpu_offset(__i),         \
                       (src), (size));                          \
 } while (0)
index d86494e23b638460557133d1f388f5c18030b17b..98c36eae567c0fc0d593d0af3974a71492f62b72 100644 (file)
@@ -613,8 +613,10 @@ __SYSCALL(__NR_get_robust_list, sys_get_robust_list)
 __SYSCALL(__NR_splice, sys_splice)
 #define __NR_tee               276
 __SYSCALL(__NR_tee, sys_tee)
+#define __NR_sync_file_range   277
+__SYSCALL(__NR_sync_file_range, sys_sync_file_range)
 
-#define __NR_syscall_max __NR_tee
+#define __NR_syscall_max __NR_sync_file_range
 
 #ifndef __NO_STUBS
 
index 10c443435c117084abfbf10b204c7254eff26970..3b89a772d0a0b954e5cec7647cdf0890f0db68c5 100644 (file)
 #define TIOCSERSETMULTI _IOW('T', 91, struct serial_multiport_struct) /* Set multiport config */
 
 #define TIOCMIWAIT     _IO('T', 92) /* wait for a change on serial input line(s) */
-#define TIOCGICOUNT    _IOR('T', 93, struct async_icount) /* read serial port inline interrupt counts */
+#define TIOCGICOUNT    0x545D  /* read serial port inline interrupt counts */
 
 #endif /* _XTENSA_IOCTLS_H */
index 8d2db412ba9ca2f46f9161642b70705d68f7fe03..a8bef1d1371cc999ce6882d355c7554ca7738173 100644 (file)
@@ -1220,7 +1220,6 @@ typedef struct ide_pci_enablebit_s {
 enum {
        /* Uses ISA control ports not PCI ones. */
        IDEPCI_FLAG_ISA_PORTS           = (1 << 0),
-       IDEPCI_FLAG_FORCE_PDC           = (1 << 1),
 };
 
 typedef struct ide_pci_device_s {
index 4ca3e6ad03ec4c2b7838fec75386262dac583199..911206386171ccedc51397d9e36a7c424de9642c 100644 (file)
@@ -99,10 +99,7 @@ static inline int __remove_pages(struct zone *zone, unsigned long start_pfn,
        return -ENOSYS;
 }
 
-#if defined(CONFIG_MEMORY_HOTPLUG) || defined(CONFIG_ACPI_HOTPLUG_MEMORY) \
-       || defined(CONFIG_ACPI_HOTPLUG_MEMORY_MODULE)
 extern int add_memory(u64 start, u64 size);
 extern int remove_memory(u64 start, u64 size);
-#endif
 
 #endif /* __LINUX_MEMORY_HOTPLUG_H */
index 955d3069d7271dd0dfc65a26f9e122b7b7b502af..edfa012fad3a93dd1e25b0f84d9bf166a225221e 100644 (file)
@@ -13,7 +13,7 @@
 #ifndef __ASM_MV643XX_H
 #define __ASM_MV643XX_H
 
-#ifdef __MIPS__
+#ifdef __mips__
 #include <asm/addrspace.h>
 #include <asm/marvell.h>
 #endif
index 9dfb4b2b16c904ebadb01002ddef0f0c78efc8e7..563eeadbea46441a8b8196b35c6fa1f080e6ff79 100644 (file)
 #define PCI_DEVICE_ID_ATI_IXP300_SATA   0x436e
 #define PCI_DEVICE_ID_ATI_IXP400_IDE   0x4376
 #define PCI_DEVICE_ID_ATI_IXP400_SATA   0x4379
+#define PCI_DEVICE_ID_ATI_IXP400_SATA2 0x437a
+#define PCI_DEVICE_ID_ATI_IXP600_SATA  0x4380
+#define PCI_DEVICE_ID_ATI_IXP600_SRAID 0x4381
+#define PCI_DEVICE_ID_ATI_IXP600_IDE   0x438c
 
 #define PCI_VENDOR_ID_VLSI             0x1004
 #define PCI_DEVICE_ID_VLSI_82C592      0x0005
index b7d31e2e1729027ada80a4759eb2eb7618d482ae..29b7d4f87d207a69a1b8a2c0167416f1332f030d 100644 (file)
@@ -1192,8 +1192,7 @@ extern void wait_task_inactive(task_t * p);
 #define remove_parent(p)       list_del_init(&(p)->sibling)
 #define add_parent(p)          list_add_tail(&(p)->sibling,&(p)->parent->children)
 
-#define next_task(p)   list_entry((p)->tasks.next, struct task_struct, tasks)
-#define prev_task(p)   list_entry((p)->tasks.prev, struct task_struct, tasks)
+#define next_task(p)   list_entry(rcu_dereference((p)->tasks.next), struct task_struct, tasks)
 
 #define for_each_process(p) \
        for (p = &init_task ; (p = next_task(p)) != &init_task ; )
index 8f96e9dc369abebb5cbef5f8a8cfed63398efb65..77f78e56c4814606066669b2ba45104fafb45b91 100644 (file)
@@ -69,9 +69,21 @@ struct rpc_clnt;
 /*
  * EXPORTed functions for managing rpc_iostats structures
  */
+
+#ifdef CONFIG_PROC_FS
+
 struct rpc_iostats *   rpc_alloc_iostats(struct rpc_clnt *);
 void                   rpc_count_iostats(struct rpc_task *);
 void                   rpc_print_iostats(struct seq_file *, struct rpc_clnt *);
 void                   rpc_free_iostats(struct rpc_iostats *);
 
+#else  /*  CONFIG_PROC_FS  */
+
+static inline struct rpc_iostats *rpc_alloc_iostats(struct rpc_clnt *clnt) { return NULL; }
+static inline void rpc_count_iostats(struct rpc_task *task) {}
+static inline void rpc_print_iostats(struct seq_file *seq, struct rpc_clnt *clnt) {}
+static inline void rpc_free_iostats(struct rpc_iostats *stats) {}
+
+#endif  /*  CONFIG_PROC_FS  */
+
 #endif /* _LINUX_SUNRPC_METRICS_H */
index 7eebbab7160bf1900b5bec67374c271e6a4d9539..e8bbe8118de8118dc6f5fd1b7e21cacafa8afef4 100644 (file)
@@ -53,6 +53,7 @@ struct rpc_timeout {
 
 struct rpc_task;
 struct rpc_xprt;
+struct seq_file;
 
 /*
  * This describes a complete RPC request
index 6d6f0634ae41294299324005be723d0ac86a1bf0..4abedb8eaece67a43e4a091cca197477c025cc7a 100644 (file)
@@ -230,7 +230,7 @@ extern int                  ip6_ra_control(struct sock *sk, int sel,
                                               void (*destructor)(struct sock *));
 
 
-extern int                     ipv6_parse_hopopts(struct sk_buff *skb, int);
+extern int                     ipv6_parse_hopopts(struct sk_buff *skb);
 
 extern struct ipv6_txoptions *  ipv6_dup_options(struct sock *sk, struct ipv6_txoptions *opt);
 extern struct ipv6_txoptions * ipv6_renew_options(struct sock *sk, struct ipv6_txoptions *opt,
index f1bc2f0e94e5996eeaf520132823f7e171d3bb86..3b36a1d536564e742d9d0b8d93f6db11d5a19c83 100644 (file)
@@ -374,15 +374,6 @@ config SLAB
          SLOB is more space efficient but does not scale well and is
          more susceptible to fragmentation.
 
-config DOUBLEFAULT
-       default y
-       bool "Enable doublefault exception handler" if EMBEDDED && X86_32
-       help
-          This option allows trapping of rare doublefault exceptions that
-          would otherwise cause a system to silently reboot. Disabling this
-          option saves about 4k and might cause you much additional grey
-          hair.
-
 endmenu                # General setup
 
 config TINY_SHMEM
index 6b0c9af5bbf7c4a2569cf982ea4eba3821e9634b..1c2faf62bc7301a823b26cee9ae738069e93aaa6 100644 (file)
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -162,6 +162,8 @@ static int shm_mmap(struct file * file, struct vm_area_struct * vma)
        ret = shmem_mmap(file, vma);
        if (ret == 0) {
                vma->vm_ops = &shm_vm_ops;
+               if (!(vma->vm_flags & VM_WRITE))
+                       vma->vm_flags &= ~VM_MAYWRITE;
                shm_inc(file->f_dentry->d_inode->i_ino);
        }
 
index 5e785a29e1e63349ff35f8a1b3282f468fd24277..b3dcfad3b4f72075b7c338dc182eeb0c2403d482 100644 (file)
@@ -183,8 +183,7 @@ static int grow_ary(struct ipc_ids* ids, int newsize)
        if(new == NULL)
                return size;
        new->size = newsize;
-       memcpy(new->p, ids->entries->p, sizeof(struct kern_ipc_perm *)*size +
-                                       sizeof(struct ipc_id_ary));
+       memcpy(new->p, ids->entries->p, sizeof(struct kern_ipc_perm *)*size);
        for(i=size;i<newsize;i++) {
                new->p[i] = NULL;
        }
index 1a9787ac61733abbc793c10c515347904a678bff..f86434d7b3d1811b689bfedcfc1bc40079950a34 100644 (file)
@@ -56,7 +56,7 @@ static void __unhash_process(struct task_struct *p)
                detach_pid(p, PIDTYPE_PGID);
                detach_pid(p, PIDTYPE_SID);
 
-               list_del_init(&p->tasks);
+               list_del_rcu(&p->tasks);
                __get_cpu_var(process_counts)--;
        }
        list_del_rcu(&p->thread_group);
index 54b15f8cda538b3a721c03704c04390a369ae65c..d2fa57d480d4af9c868c2e7a5602f50b6e164795 100644 (file)
@@ -180,6 +180,7 @@ static struct task_struct *dup_task_struct(struct task_struct *orig)
        atomic_set(&tsk->usage,2);
        atomic_set(&tsk->fs_excl, 0);
        tsk->btrace_seq = 0;
+       tsk->splice_pipe = NULL;
        return tsk;
 }
 
@@ -1204,7 +1205,7 @@ static task_t *copy_process(unsigned long clone_flags,
                        attach_pid(p, PIDTYPE_PGID, process_group(p));
                        attach_pid(p, PIDTYPE_SID, p->signal->session);
 
-                       list_add_tail(&p->tasks, &init_task.tasks);
+                       list_add_tail_rcu(&p->tasks, &init_task.tasks);
                        __get_cpu_var(process_counts)++;
                }
                attach_pid(p, PIDTYPE_PID, p->pid);
index 1156eb0977d04db06b1daeb926d776e87c34a5b7..1fbf466a29aab6ca0dfe1cf6e5d6ac16fba546d8 100644 (file)
@@ -585,6 +585,9 @@ int __kprobes register_kretprobe(struct kretprobe *rp)
        int i;
 
        rp->kp.pre_handler = pre_handler_kretprobe;
+       rp->kp.post_handler = NULL;
+       rp->kp.fault_handler = NULL;
+       rp->kp.break_handler = NULL;
 
        /* Pre-allocate memory for max kretprobe instances */
        if (rp->maxactive <= 0) {
index c5863d02c89efc08ef430752bb062f0aafcb4bc7..3eeedbb13b7864d525c6740a99156b433e3b6a51 100644 (file)
@@ -240,14 +240,15 @@ static void copy_data_pages(struct pbe *pblist)
  *     free_pagedir - free pages allocated with alloc_pagedir()
  */
 
-static void free_pagedir(struct pbe *pblist)
+static void free_pagedir(struct pbe *pblist, int clear_nosave_free)
 {
        struct pbe *pbe;
 
        while (pblist) {
                pbe = (pblist + PB_PAGE_SKIP)->next;
                ClearPageNosave(virt_to_page(pblist));
-               ClearPageNosaveFree(virt_to_page(pblist));
+               if (clear_nosave_free)
+                       ClearPageNosaveFree(virt_to_page(pblist));
                free_page((unsigned long)pblist);
                pblist = pbe;
        }
@@ -389,7 +390,7 @@ struct pbe *alloc_pagedir(unsigned int nr_pages, gfp_t gfp_mask, int safe_needed
                pbe->next = alloc_image_page(gfp_mask, safe_needed);
        }
        if (!pbe) { /* get_zeroed_page() failed */
-               free_pagedir(pblist);
+               free_pagedir(pblist, 1);
                pblist = NULL;
         } else
                create_pbe_list(pblist, nr_pages);
@@ -736,7 +737,7 @@ static int create_image(struct snapshot_handle *handle)
                pblist = alloc_pagedir(nr_copy_pages, GFP_ATOMIC, 1);
                if (pblist)
                        copy_page_backup_list(pblist, p);
-               free_pagedir(p);
+               free_pagedir(p, 0);
                if (!pblist)
                        error = -ENOMEM;
        }
index aa25605027c8eb19c682cd6efec17b0d79073451..187e2a423878229b53e7c5310946621274901bf7 100644 (file)
 
 asmlinkage long sys_chown16(const char __user * filename, old_uid_t user, old_gid_t group)
 {
-       return sys_chown(filename, low2highuid(user), low2highgid(group));
+       long ret = sys_chown(filename, low2highuid(user), low2highgid(group));
+       /* avoid REGPARM breakage on x86: */
+       prevent_tail_call(ret);
+       return ret;
 }
 
 asmlinkage long sys_lchown16(const char __user * filename, old_uid_t user, old_gid_t group)
 {
-       return sys_lchown(filename, low2highuid(user), low2highgid(group));
+       long ret = sys_lchown(filename, low2highuid(user), low2highgid(group));
+       /* avoid REGPARM breakage on x86: */
+       prevent_tail_call(ret);
+       return ret;
 }
 
 asmlinkage long sys_fchown16(unsigned int fd, old_uid_t user, old_gid_t group)
 {
-       return sys_fchown(fd, low2highuid(user), low2highgid(group));
+       long ret = sys_fchown(fd, low2highuid(user), low2highgid(group));
+       /* avoid REGPARM breakage on x86: */
+       prevent_tail_call(ret);
+       return ret;
 }
 
 asmlinkage long sys_setregid16(old_gid_t rgid, old_gid_t egid)
 {
-       return sys_setregid(low2highgid(rgid), low2highgid(egid));
+       long ret = sys_setregid(low2highgid(rgid), low2highgid(egid));
+       /* avoid REGPARM breakage on x86: */
+       prevent_tail_call(ret);
+       return ret;
 }
 
 asmlinkage long sys_setgid16(old_gid_t gid)
 {
-       return sys_setgid(low2highgid(gid));
+       long ret = sys_setgid(low2highgid(gid));
+       /* avoid REGPARM breakage on x86: */
+       prevent_tail_call(ret);
+       return ret;
 }
 
 asmlinkage long sys_setreuid16(old_uid_t ruid, old_uid_t euid)
 {
-       return sys_setreuid(low2highuid(ruid), low2highuid(euid));
+       long ret = sys_setreuid(low2highuid(ruid), low2highuid(euid));
+       /* avoid REGPARM breakage on x86: */
+       prevent_tail_call(ret);
+       return ret;
 }
 
 asmlinkage long sys_setuid16(old_uid_t uid)
 {
-       return sys_setuid(low2highuid(uid));
+       long ret = sys_setuid(low2highuid(uid));
+       /* avoid REGPARM breakage on x86: */
+       prevent_tail_call(ret);
+       return ret;
 }
 
 asmlinkage long sys_setresuid16(old_uid_t ruid, old_uid_t euid, old_uid_t suid)
 {
-       return sys_setresuid(low2highuid(ruid), low2highuid(euid),
-               low2highuid(suid));
+       long ret = sys_setresuid(low2highuid(ruid), low2highuid(euid),
+                                low2highuid(suid));
+       /* avoid REGPARM breakage on x86: */
+       prevent_tail_call(ret);
+       return ret;
 }
 
 asmlinkage long sys_getresuid16(old_uid_t __user *ruid, old_uid_t __user *euid, old_uid_t __user *suid)
@@ -72,8 +96,11 @@ asmlinkage long sys_getresuid16(old_uid_t __user *ruid, old_uid_t __user *euid,
 
 asmlinkage long sys_setresgid16(old_gid_t rgid, old_gid_t egid, old_gid_t sgid)
 {
-       return sys_setresgid(low2highgid(rgid), low2highgid(egid),
-               low2highgid(sgid));
+       long ret = sys_setresgid(low2highgid(rgid), low2highgid(egid),
+                                low2highgid(sgid));
+       /* avoid REGPARM breakage on x86: */
+       prevent_tail_call(ret);
+       return ret;
 }
 
 asmlinkage long sys_getresgid16(old_gid_t __user *rgid, old_gid_t __user *egid, old_gid_t __user *sgid)
@@ -89,12 +116,18 @@ asmlinkage long sys_getresgid16(old_gid_t __user *rgid, old_gid_t __user *egid,
 
 asmlinkage long sys_setfsuid16(old_uid_t uid)
 {
-       return sys_setfsuid(low2highuid(uid));
+       long ret = sys_setfsuid(low2highuid(uid));
+       /* avoid REGPARM breakage on x86: */
+       prevent_tail_call(ret);
+       return ret;
 }
 
 asmlinkage long sys_setfsgid16(old_gid_t gid)
 {
-       return sys_setfsgid(low2highgid(gid));
+       long ret = sys_setfsgid(low2highgid(gid));
+       /* avoid REGPARM breakage on x86: */
+       prevent_tail_call(ret);
+       return ret;
 }
 
 static int groups16_to_user(old_gid_t __user *grouplist,
index d57fd9181b187ed07856ae0bb845bcc6e93a006b..6ecc180beb7145c5c649f36bc2b7961eab7af13e 100644 (file)
@@ -101,7 +101,7 @@ config DEBUG_PREEMPT
 
 config DEBUG_MUTEXES
        bool "Mutex debugging, deadlock detection"
-       default y
+       default n
        depends on DEBUG_KERNEL
        help
         This allows mutex semantics violations and mutex related deadlocks
index af3d573b014122f7fd2a99c3ee90c3826f70457f..4e196155a0c3635801bd0f8dcff0b18ce1bbcf37 100644 (file)
@@ -168,6 +168,9 @@ static long madvise_remove(struct vm_area_struct *vma,
                        return -EINVAL;
        }
 
+       if ((vma->vm_flags & (VM_SHARED|VM_WRITE)) != (VM_SHARED|VM_WRITE))
+               return -EACCES;
+
        mapping = vma->vm_file->f_mapping;
 
        offset = (loff_t)(start - vma->vm_start)
index dec8249e972de3cdae046203b16ef32d25d1cda9..8778f58880c41c55cab9a2de035e960379b0cfe4 100644 (file)
@@ -1761,7 +1761,6 @@ static void gather_stats(struct page *page, void *private, int pte_dirty)
                md->mapcount_max = count;
 
        md->node[page_to_nid(page)]++;
-       cond_resched();
 }
 
 #ifdef CONFIG_HUGETLB_PAGE
index 78747afad6b0d6e2b2a2e0c08075e9911c8b85c6..042e6436c3ee8db6548a687dc289a207f2c43fd6 100644 (file)
 unsigned long badness(struct task_struct *p, unsigned long uptime)
 {
        unsigned long points, cpu_time, run_time, s;
-       struct list_head *tsk;
+       struct mm_struct *mm;
+       struct task_struct *child;
 
-       if (!p->mm)
+       task_lock(p);
+       mm = p->mm;
+       if (!mm) {
+               task_unlock(p);
                return 0;
+       }
 
        /*
         * The memory size of the process is the basis for the badness.
         */
-       points = p->mm->total_vm;
+       points = mm->total_vm;
+
+       /*
+        * After this unlock we can no longer dereference local variable `mm'
+        */
+       task_unlock(p);
 
        /*
         * Processes which fork a lot of child processes are likely
@@ -64,11 +74,11 @@ unsigned long badness(struct task_struct *p, unsigned long uptime)
         * child is eating the vast majority of memory, adding only half
         * to the parents will make the child our kill candidate of choice.
         */
-       list_for_each(tsk, &p->children) {
-               struct task_struct *chld;
-               chld = list_entry(tsk, struct task_struct, sibling);
-               if (chld->mm != p->mm && chld->mm)
-                       points += chld->mm->total_vm/2 + 1;
+       list_for_each_entry(child, &p->children, sibling) {
+               task_lock(child);
+               if (child->mm != mm && child->mm)
+                       points += child->mm->total_vm/2 + 1;
+               task_unlock(child);
        }
 
        /*
@@ -244,17 +254,24 @@ static void __oom_kill_task(task_t *p, const char *message)
        force_sig(SIGKILL, p);
 }
 
-static struct mm_struct *oom_kill_task(task_t *p, const char *message)
+static int oom_kill_task(task_t *p, const char *message)
 {
-       struct mm_struct *mm = get_task_mm(p);
+       struct mm_struct *mm;
        task_t * g, * q;
 
-       if (!mm)
-               return NULL;
-       if (mm == &init_mm) {
-               mmput(mm);
-               return NULL;
-       }
+       mm = p->mm;
+
+       /* WARNING: mm may not be dereferenced since we did not obtain its
+        * value from get_task_mm(p).  This is OK since all we need to do is
+        * compare mm to q->mm below.
+        *
+        * Furthermore, even if mm contains a non-NULL value, p->mm may
+        * change to NULL at any time since we do not hold task_lock(p).
+        * However, this is of no concern to us.
+        */
+
+       if (mm == NULL || mm == &init_mm)
+               return 1;
 
        __oom_kill_task(p, message);
        /*
@@ -266,13 +283,12 @@ static struct mm_struct *oom_kill_task(task_t *p, const char *message)
                        __oom_kill_task(q, message);
        while_each_thread(g, q);
 
-       return mm;
+       return 0;
 }
 
-static struct mm_struct *oom_kill_process(struct task_struct *p,
-                               unsigned long points, const char *message)
+static int oom_kill_process(struct task_struct *p, unsigned long points,
+               const char *message)
 {
-       struct mm_struct *mm;
        struct task_struct *c;
        struct list_head *tsk;
 
@@ -283,9 +299,8 @@ static struct mm_struct *oom_kill_process(struct task_struct *p,
                c = list_entry(tsk, struct task_struct, sibling);
                if (c->mm == p->mm)
                        continue;
-               mm = oom_kill_task(c, message);
-               if (mm)
-                       return mm;
+               if (!oom_kill_task(c, message))
+                       return 0;
        }
        return oom_kill_task(p, message);
 }
@@ -300,7 +315,6 @@ static struct mm_struct *oom_kill_process(struct task_struct *p,
  */
 void out_of_memory(struct zonelist *zonelist, gfp_t gfp_mask, int order)
 {
-       struct mm_struct *mm = NULL;
        task_t *p;
        unsigned long points = 0;
 
@@ -320,12 +334,12 @@ void out_of_memory(struct zonelist *zonelist, gfp_t gfp_mask, int order)
         */
        switch (constrained_alloc(zonelist, gfp_mask)) {
        case CONSTRAINT_MEMORY_POLICY:
-               mm = oom_kill_process(current, points,
+               oom_kill_process(current, points,
                                "No available memory (MPOL_BIND)");
                break;
 
        case CONSTRAINT_CPUSET:
-               mm = oom_kill_process(current, points,
+               oom_kill_process(current, points,
                                "No available memory in cpuset");
                break;
 
@@ -347,8 +361,7 @@ retry:
                        panic("Out of memory and no killable processes...\n");
                }
 
-               mm = oom_kill_process(p, points, "Out of memory");
-               if (!mm)
+               if (oom_kill_process(p, points, "Out of memory"))
                        goto retry;
 
                break;
@@ -357,8 +370,6 @@ retry:
 out:
        read_unlock(&tasklist_lock);
        cpuset_unlock();
-       if (mm)
-               mmput(mm);
 
        /*
         * Give "p" a good chance of killing itself before we
index 97d6827c7d669529fb7e5607cad4ba838d1847bf..123c605867404ecfc00ef0d19a8a65d852ed0be0 100644 (file)
@@ -232,11 +232,13 @@ static inline void prep_zero_page(struct page *page, int order, gfp_t gfp_flags)
  * zone->lock is already acquired when we use these.
  * So, we don't need atomic page->flags operations here.
  */
-static inline unsigned long page_order(struct page *page) {
+static inline unsigned long page_order(struct page *page)
+{
        return page_private(page);
 }
 
-static inline void set_page_order(struct page *page, int order) {
+static inline void set_page_order(struct page *page, int order)
+{
        set_page_private(page, order);
        __SetPageBuddy(page);
 }
@@ -299,9 +301,9 @@ static inline int page_is_buddy(struct page *page, int order)
 
        if (PageBuddy(page) && page_order(page) == order) {
                BUG_ON(page_count(page) != 0);
-               return 1;
+               return 1;
        }
-       return 0;
+       return 0;
 }
 
 /*
index 9bcc7e2cabfd4d5b9147b8547a34e6dd0594a629..a68255ba4553770f7c4050857a11661160ea3942 100644 (file)
--- a/mm/slob.c
+++ b/mm/slob.c
@@ -354,9 +354,7 @@ void *__alloc_percpu(size_t size)
        if (!pdata)
                return NULL;
 
-       for (i = 0; i < NR_CPUS; i++) {
-               if (!cpu_possible(i))
-                       continue;
+       for_each_possible_cpu(i) {
                pdata->ptrs[i] = kmalloc(size, GFP_KERNEL);
                if (!pdata->ptrs[i])
                        goto unwind_oom;
@@ -383,11 +381,9 @@ free_percpu(const void *objp)
        int i;
        struct percpu_data *p = (struct percpu_data *) (~(unsigned long) objp);
 
-       for (i = 0; i < NR_CPUS; i++) {
-               if (!cpu_possible(i))
-                       continue;
+       for_each_possible_cpu(i)
                kfree(p->ptrs[i]);
-       }
+
        kfree(p);
 }
 EXPORT_SYMBOL(free_percpu);
index 93fbd01d225952c66228d228a66340101448166a..5b4486a60cf6bca668bf4f5e7232d6df1a37dbb9 100644 (file)
@@ -34,6 +34,7 @@
 #include <linux/timer.h>
 #include <asm/system.h>
 #include <asm/uaccess.h>
+#include <asm/unaligned.h>
 #include <linux/filter.h>
 
 /* No hurry in this branch */
@@ -177,7 +178,7 @@ unsigned int sk_run_filter(struct sk_buff *skb, struct sock_filter *filter, int
 load_w:
                        ptr = load_pointer(skb, k, 4, &tmp);
                        if (ptr != NULL) {
-                               A = ntohl(*(u32 *)ptr);
+                               A = ntohl(get_unaligned((u32 *)ptr));
                                continue;
                        }
                        break;
@@ -186,7 +187,7 @@ load_w:
 load_h:
                        ptr = load_pointer(skb, k, 2, &tmp);
                        if (ptr != NULL) {
-                               A = ntohs(*(u16 *)ptr);
+                               A = ntohs(get_unaligned((u16 *)ptr));
                                continue;
                        }
                        break;
index 04a429465665cd8ff0c377eed4d1caf0d40a4a3a..cd810f41af1a71db684a7787bde2bbc8e5d601f7 100644 (file)
@@ -290,11 +290,8 @@ static void ipcomp_free_scratches(void)
        if (!scratches)
                return;
 
-       for_each_possible_cpu(i) {
-               void *scratch = *per_cpu_ptr(scratches, i);
-               if (scratch)
-                       vfree(scratch);
-       }
+       for_each_possible_cpu(i)
+               vfree(*per_cpu_ptr(scratches, i));
 
        free_percpu(scratches);
 }
index ff434821909f12f26a6d142d3c3ae843580deed3..cc9423de7311fcac8845b38a055b6ea008b22ec7 100644 (file)
@@ -2741,7 +2741,10 @@ int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void *arg)
        /* Reserve room for dummy headers, this skb can pass
           through good chunk of routing engine.
         */
-       skb->mac.raw = skb->data;
+       skb->mac.raw = skb->nh.raw = skb->data;
+
+       /* Bugfix: need to give ip_route_input enough of an IP header to not gag. */
+       skb->nh.iph->protocol = IPPROTO_ICMP;
        skb_reserve(skb, MAX_HEADER + sizeof(struct iphdr));
 
        if (rta[RTA_SRC - 1])
index b871db6adc55cd838c07b11b4461bc5e879f5377..44df1db726a37bc77c28dda33d5238b9f40a5a8e 100644 (file)
@@ -551,7 +551,9 @@ int tcp_fragment(struct sock *sk, struct sk_buff *skb, u32 len, unsigned int mss
        buff = sk_stream_alloc_skb(sk, nsize, GFP_ATOMIC);
        if (buff == NULL)
                return -ENOMEM; /* We'll just try again later. */
-       sk_charge_skb(sk, buff);
+
+       buff->truesize = skb->len - len;
+       skb->truesize -= buff->truesize;
 
        /* Correct the sequence numbers. */
        TCP_SKB_CB(buff)->seq = TCP_SKB_CB(skb)->seq + len;
index 2a1e7e45b890ff9eccb841c3271b3b09e52c8305..a18d4256372cf988e66d1feef51507b7163b8103 100644 (file)
@@ -485,15 +485,27 @@ static struct tlvtype_proc tlvprochopopt_lst[] = {
        { -1, }
 };
 
-int ipv6_parse_hopopts(struct sk_buff *skb, int nhoff)
+int ipv6_parse_hopopts(struct sk_buff *skb)
 {
        struct inet6_skb_parm *opt = IP6CB(skb);
 
+       /*
+        * skb->nh.raw is equal to skb->data, and
+        * skb->h.raw - skb->nh.raw is always equal to
+        * sizeof(struct ipv6hdr) by definition of
+        * hop-by-hop options.
+        */
+       if (!pskb_may_pull(skb, sizeof(struct ipv6hdr) + 8) ||
+           !pskb_may_pull(skb, sizeof(struct ipv6hdr) + ((skb->h.raw[1] + 1) << 3))) {
+               kfree_skb(skb);
+               return -1;
+       }
+
        opt->hop = sizeof(struct ipv6hdr);
        if (ip6_parse_tlv(tlvprochopopt_lst, skb)) {
                skb->h.raw += (skb->h.raw[1]+1)<<3;
                opt->nhoff = sizeof(struct ipv6hdr);
-               return sizeof(struct ipv6hdr);
+               return 1;
        }
        return -1;
 }
index 29f73592e68e51304c7c6859c82eb44248e3a3ae..aceee252503dfe84f5ccb34b950949f284577d0a 100644 (file)
@@ -114,11 +114,10 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt
        }
 
        if (hdr->nexthdr == NEXTHDR_HOP) {
-               if (ipv6_parse_hopopts(skb, IP6CB(skb)->nhoff) < 0) {
+               if (ipv6_parse_hopopts(skb) < 0) {
                        IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
                        return 0;
                }
-               hdr = skb->nh.ipv6h;
        }
 
        return NF_HOOK(PF_INET6,NF_IP6_PRE_ROUTING, skb, dev, NULL, ip6_rcv_finish);
index 91cce8b2d7a5643b523c55b12758756a0d374aee..88c840f1beb678a373284799dc6f8a693fd89544 100644 (file)
@@ -191,16 +191,18 @@ error:
 static inline void
 _decode_session6(struct sk_buff *skb, struct flowi *fl)
 {
-       u16 offset = sizeof(struct ipv6hdr);
+       u16 offset = skb->h.raw - skb->nh.raw;
        struct ipv6hdr *hdr = skb->nh.ipv6h;
-       struct ipv6_opt_hdr *exthdr = (struct ipv6_opt_hdr*)(skb->nh.raw + offset);
-       u8 nexthdr = skb->nh.ipv6h->nexthdr;
+       struct ipv6_opt_hdr *exthdr;
+       u8 nexthdr = skb->nh.raw[IP6CB(skb)->nhoff];
 
        memset(fl, 0, sizeof(struct flowi));
        ipv6_addr_copy(&fl->fl6_dst, &hdr->daddr);
        ipv6_addr_copy(&fl->fl6_src, &hdr->saddr);
 
        while (pskb_may_pull(skb, skb->nh.raw + offset + 1 - skb->data)) {
+               exthdr = (struct ipv6_opt_hdr*)(skb->nh.raw + offset);
+
                switch (nexthdr) {
                case NEXTHDR_ROUTING:
                case NEXTHDR_HOP:
index 900ef31f5a0e601bd7f0a4cfc9fbfea06584c3c4..519ebc17c02845a762102c00b35efb6f01b73b46 100644 (file)
@@ -794,7 +794,6 @@ gss_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags)
 
 out_err:
        dprintk("RPC:      gss_create_cred failed with error %d\n", err);
-       if (cred) gss_destroy_cred(&cred->gc_base);
        return ERR_PTR(err);
 }
 
index 97c981fa6b8ee4a48118cf46801e1fef60388b23..76b969e6904fdca3607845a050c331376845b180 100644 (file)
@@ -212,7 +212,6 @@ make_checksum(s32 cksumtype, char *header, int hdrlen, struct xdr_buf *body,
        char                            *cksumname;
        struct crypto_tfm               *tfm = NULL; /* XXX add to ctx? */
        struct scatterlist              sg[1];
-       u32                             code = GSS_S_FAILURE;
 
        switch (cksumtype) {
                case CKSUMTYPE_RSA_MD5:
@@ -221,13 +220,11 @@ make_checksum(s32 cksumtype, char *header, int hdrlen, struct xdr_buf *body,
                default:
                        dprintk("RPC:      krb5_make_checksum:"
                                " unsupported checksum %d", cksumtype);
-                       goto out;
+                       return GSS_S_FAILURE;
        }
        if (!(tfm = crypto_alloc_tfm(cksumname, CRYPTO_TFM_REQ_MAY_SLEEP)))
-               goto out;
+               return GSS_S_FAILURE;
        cksum->len = crypto_tfm_alg_digestsize(tfm);
-       if ((cksum->data = kmalloc(cksum->len, GFP_KERNEL)) == NULL)
-               goto out;
 
        crypto_digest_init(tfm);
        sg_set_buf(sg, header, hdrlen);
@@ -235,10 +232,8 @@ make_checksum(s32 cksumtype, char *header, int hdrlen, struct xdr_buf *body,
        process_xdr_buf(body, body_offset, body->len - body_offset,
                        checksummer, tfm);
        crypto_digest_final(tfm, cksum->data);
-       code = 0;
-out:
        crypto_free_tfm(tfm);
-       return code;
+       return 0;
 }
 
 EXPORT_SYMBOL(make_checksum);
index dea529666d6991077aa69deaecad2818033def0c..15c2db26767bc5e5b6848d904078c9b0975dcfa4 100644 (file)
@@ -176,7 +176,8 @@ void rpc_count_iostats(struct rpc_task *task)
        op_metrics->om_execute += execute;
 }
 
-void _print_name(struct seq_file *seq, unsigned int op, struct rpc_procinfo *procs)
+static void _print_name(struct seq_file *seq, unsigned int op,
+                       struct rpc_procinfo *procs)
 {
        if (procs[op].p_name)
                seq_printf(seq, "\t%12s: ", procs[op].p_name);
index 953307a9df1d852c3eac546d9e1d97e728f0df3e..a3bbc891f95997bf7e186607214aedddc7c1d454 100644 (file)
@@ -229,8 +229,7 @@ static void node_is_down(struct publication *publ)
                                     publ->node, publ->ref, publ->key);
         assert(p == publ);
        write_unlock_bh(&tipc_nametbl_lock);
-       if (publ)
-               kfree(publ);
+       kfree(publ);
 }
 
 /**
index ae5ab981bb1d170d215bf9bde96845d731c8e7e0..8012d1076876bb1f4ee9766a63720f0e53d9f829 100644 (file)
@@ -5,6 +5,7 @@
 
 #include <ctype.h>
 #include <stdlib.h>
+#include <stdio.h>
 #include <string.h>
 #include <unistd.h>
 #include <time.h>
@@ -531,7 +532,7 @@ int main(int ac, char **av)
                        break;
                case 'h':
                case '?':
-                       printf("%s [-o|-s] config\n", av[0]);
+                       fprintf(stderr, "See README for usage info\n");
                        exit(0);
                }
        }
index 640d0bfdbc6819e4ffa7845f1e10e92b5640e14a..84047f69f9c1b4d0bdfbbfe511457d6a62c18dad 100644 (file)
@@ -264,7 +264,7 @@ int mls_context_to_sid(char oldc,
 
        if (!selinux_mls_enabled) {
                if (def_sid != SECSID_NULL && oldc)
-                       *scontext += strlen(*scontext);
+                       *scontext += strlen(*scontext)+1;
                return 0;
        }
 
index 8687ae3c66b8c54bf156e2424c0a9ecf6d8e4c9a..b49a45cbf67a09aa9faf39ae75671dd0f7cad1bf 100644 (file)
@@ -183,7 +183,8 @@ static void snd_mpu401_uart_remove_timer (struct snd_mpu401 *mpu, int input)
 
  */
 
-static void snd_mpu401_uart_cmd(struct snd_mpu401 * mpu, unsigned char cmd, int ack)
+static int snd_mpu401_uart_cmd(struct snd_mpu401 * mpu, unsigned char cmd,
+               int ack)
 {
        unsigned long flags;
        int timeout, ok;
@@ -218,9 +219,11 @@ static void snd_mpu401_uart_cmd(struct snd_mpu401 * mpu, unsigned char cmd, int
                ok = 1;
        }
        spin_unlock_irqrestore(&mpu->input_lock, flags);
-       if (! ok)
+       if (!ok) {
                snd_printk("cmd: 0x%x failed at 0x%lx (status = 0x%x, data = 0x%x)\n", cmd, mpu->port, mpu->read(mpu, MPU401C(mpu)), mpu->read(mpu, MPU401D(mpu)));
-       // snd_printk("cmd: 0x%x at 0x%lx (status = 0x%x, data = 0x%x)\n", cmd, mpu->port, mpu->read(mpu, MPU401C(mpu)), mpu->read(mpu, MPU401D(mpu)));
+               return 1;
+       }
+       return 0;
 }
 
 /*
@@ -235,12 +238,19 @@ static int snd_mpu401_uart_input_open(struct snd_rawmidi_substream *substream)
        if (mpu->open_input && (err = mpu->open_input(mpu)) < 0)
                return err;
        if (! test_bit(MPU401_MODE_BIT_OUTPUT, &mpu->mode)) {
-               snd_mpu401_uart_cmd(mpu, MPU401_RESET, 1);
-               snd_mpu401_uart_cmd(mpu, MPU401_ENTER_UART, 1);
+               if (snd_mpu401_uart_cmd(mpu, MPU401_RESET, 1))
+                       goto error_out;
+               if (snd_mpu401_uart_cmd(mpu, MPU401_ENTER_UART, 1))
+                       goto error_out;
        }
        mpu->substream_input = substream;
        set_bit(MPU401_MODE_BIT_INPUT, &mpu->mode);
        return 0;
+
+error_out:
+       if (mpu->open_input && mpu->close_input)
+               mpu->close_input(mpu);
+       return -EIO;
 }
 
 static int snd_mpu401_uart_output_open(struct snd_rawmidi_substream *substream)
@@ -252,39 +262,52 @@ static int snd_mpu401_uart_output_open(struct snd_rawmidi_substream *substream)
        if (mpu->open_output && (err = mpu->open_output(mpu)) < 0)
                return err;
        if (! test_bit(MPU401_MODE_BIT_INPUT, &mpu->mode)) {
-               snd_mpu401_uart_cmd(mpu, MPU401_RESET, 1);
-               snd_mpu401_uart_cmd(mpu, MPU401_ENTER_UART, 1);
+               if (snd_mpu401_uart_cmd(mpu, MPU401_RESET, 1))
+                       goto error_out;
+               if (snd_mpu401_uart_cmd(mpu, MPU401_ENTER_UART, 1))
+                       goto error_out;
        }
        mpu->substream_output = substream;
        set_bit(MPU401_MODE_BIT_OUTPUT, &mpu->mode);
        return 0;
+
+error_out:
+       if (mpu->open_output && mpu->close_output)
+               mpu->close_output(mpu);
+       return -EIO;
 }
 
 static int snd_mpu401_uart_input_close(struct snd_rawmidi_substream *substream)
 {
        struct snd_mpu401 *mpu;
+       int err = 0;
 
        mpu = substream->rmidi->private_data;
        clear_bit(MPU401_MODE_BIT_INPUT, &mpu->mode);
        mpu->substream_input = NULL;
        if (! test_bit(MPU401_MODE_BIT_OUTPUT, &mpu->mode))
-               snd_mpu401_uart_cmd(mpu, MPU401_RESET, 0);
+               err = snd_mpu401_uart_cmd(mpu, MPU401_RESET, 0);
        if (mpu->close_input)
                mpu->close_input(mpu);
+       if (err)
+               return -EIO;
        return 0;
 }
 
 static int snd_mpu401_uart_output_close(struct snd_rawmidi_substream *substream)
 {
        struct snd_mpu401 *mpu;
+       int err = 0;
 
        mpu = substream->rmidi->private_data;
        clear_bit(MPU401_MODE_BIT_OUTPUT, &mpu->mode);
        mpu->substream_output = NULL;
        if (! test_bit(MPU401_MODE_BIT_INPUT, &mpu->mode))
-               snd_mpu401_uart_cmd(mpu, MPU401_RESET, 0);
+               err = snd_mpu401_uart_cmd(mpu, MPU401_RESET, 0);
        if (mpu->close_output)
                mpu->close_output(mpu);
+       if (err)
+               return -EIO;
        return 0;
 }
 
@@ -316,6 +339,7 @@ static void snd_mpu401_uart_input_trigger(struct snd_rawmidi_substream *substrea
                        snd_mpu401_uart_remove_timer(mpu, 1);
                clear_bit(MPU401_MODE_BIT_INPUT_TRIGGER, &mpu->mode);
        }
+
 }
 
 /*
index 88e52dc84c096b94514fd2e4ed76761edaceb42a..6275266dde2e754104badf084ce20003596a0d36 100644 (file)
@@ -5,23 +5,9 @@
 #
 # Prompt user for primary drivers.
 
-config OBSOLETE_OSS_DRIVER
-       bool "Obsolete OSS drivers"
-       depends on SOUND_PRIME
-       help
-         This option enables support for obsolete OSS drivers that
-         are scheduled for removal in the near future since there
-         are ALSA drivers for the same hardware.
-
-         Please contact Adrian Bunk <bunk@stusta.de> if you had to
-         say Y here because your soundcard is not properly supported
-         by ALSA.
-
-         If unsure, say N.
-
 config SOUND_BT878
        tristate "BT878 audio dma"
-       depends on SOUND_PRIME && PCI && OBSOLETE_OSS_DRIVER
+       depends on SOUND_PRIME && PCI
        ---help---
          Audio DMA support for bt878 based grabber boards.  As you might have
          already noticed, bt878 is listed with two functions in /proc/pci.
@@ -35,48 +21,9 @@ config SOUND_BT878
          To compile this driver as a module, choose M here: the module will
          be called btaudio.
 
-config SOUND_CMPCI
-       tristate "C-Media PCI (CMI8338/8738)"
-       depends on SOUND_PRIME && PCI && OBSOLETE_OSS_DRIVER
-       help
-         Say Y or M if you have a PCI sound card using the CMI8338
-         or the CMI8738 chipset.  Data on these chips are available at
-         <http://www.cmedia.com.tw/>.
-
-         A userspace utility to control some internal registers of these
-         chips is available at
-         <http://member.nifty.ne.jp/Breeze/softwares/unix/cmictl-e.html>.
-
-config SOUND_CMPCI_FM
-       bool "Enable legacy FM"
-       depends on SOUND_CMPCI && X86
-       help
-         Say Y here to enable the legacy FM (frequency-modulation) synthesizer
-         support on a card using the CMI8338 or CMI8378 chipset. Even it is
-         enabled, you need to set fmio as proper value to enable it.
-         Say N here if you don't need this.
-
-config SOUND_CMPCI_MIDI
-       bool "Enable legacy MPU-401"
-       depends on SOUND_CMPCI && X86
-       help
-         Say Y here to enable the legacy MPU401 MIDI synthesizer support on a
-         card using the CMI8338 or CMI8378 chipset. Even it is enabled,
-         you need to set mpuio as proper value to enable it.
-         Say N here if you don't need this.
-
-config SOUND_CMPCI_JOYSTICK
-       bool "Enable joystick"
-       depends on SOUND_CMPCI && X86 && (GAMEPORT=y || SOUND_CMPCI=GAMEPORT)
-       help
-         Say Y here in order to enable the joystick port on a sound card using
-         the CMI8338 or the CMI8738 chipset.  You need to config the
-         gameport support and set joystick parameter as 1 to use it.
-         Say N here if you don't need this.
-
 config SOUND_EMU10K1
        tristate "Creative SBLive! (EMU10K1)"
-       depends on SOUND_PRIME && PCI && OBSOLETE_OSS_DRIVER
+       depends on SOUND_PRIME && PCI
        ---help---
          Say Y or M if you have a PCI sound card using the EMU10K1 chipset,
          such as the Creative SBLive!, SB PCI512 or Emu-APS.
@@ -108,13 +55,6 @@ config SOUND_FUSION
          series) when wired as native sound drivers with AC97 codecs.  If
          this driver does not work try the CS4232 driver.
 
-config SOUND_CS4281
-       tristate "Crystal Sound CS4281"
-       depends on SOUND_PRIME && PCI && OBSOLETE_OSS_DRIVER
-       help
-         Picture and feature list at
-         <http://www.pcbroker.com/crystal4281.html>.
-
 config SOUND_BCM_CS4297A
        tristate "Crystal Sound CS4297a (for Swarm)"
        depends on SOUND_PRIME && SIBYTE_SWARM
@@ -125,22 +65,9 @@ config SOUND_BCM_CS4297A
          note that CONFIG_KGDB should not be enabled at the same
          time, since it also attempts to use this UART port.
 
-config SOUND_ES1370
-       tristate "Ensoniq AudioPCI (ES1370)"
-       depends on SOUND_PRIME && PCI && OBSOLETE_OSS_DRIVER
-       help
-         Say Y or M if you have a PCI sound card utilizing the Ensoniq
-         ES1370 chipset, such as Ensoniq's AudioPCI (non-97). To find
-         out if your sound card uses an ES1370 without removing your
-         computer's cover, use lspci -n and look for the PCI ID
-         1274:5000. Since Ensoniq was bought by Creative Labs,
-         Sound Blaster 64/PCI models are either ES1370 or ES1371 based.
-         This driver differs slightly from OSS/Free, so PLEASE READ
-         <file:Documentation/sound/oss/es1370>.
-
 config SOUND_ES1371
        tristate "Creative Ensoniq AudioPCI 97 (ES1371)"
-       depends on SOUND_PRIME && PCI && OBSOLETE_OSS_DRIVER
+       depends on SOUND_PRIME && PCI
        help
          Say Y or M if you have a PCI sound card utilizing the Ensoniq
          ES1371 chipset, such as Ensoniq's AudioPCI97. To find out if
@@ -151,33 +78,6 @@ config SOUND_ES1371
          slightly from OSS/Free, so PLEASE READ
          <file:Documentation/sound/oss/es1371>.
 
-config SOUND_ESSSOLO1
-       tristate "ESS Technology Solo1" 
-       depends on SOUND_PRIME && PCI && OBSOLETE_OSS_DRIVER
-       help
-         Say Y or M if you have a PCI sound card utilizing the ESS Technology
-         Solo1 chip. To find out if your sound card uses a
-         Solo1 chip without removing your computer's cover, use
-         lspci -n and look for the PCI ID 125D:1969. This driver
-         differs slightly from OSS/Free, so PLEASE READ
-         <file:Documentation/sound/oss/solo1>.
-
-config SOUND_MAESTRO
-       tristate "ESS Maestro, Maestro2, Maestro2E driver"
-       depends on SOUND_PRIME && PCI && OBSOLETE_OSS_DRIVER
-       help
-         Say Y or M if you have a sound system driven by ESS's Maestro line
-         of PCI sound chips.  These include the Maestro 1, Maestro 2, and
-         Maestro 2E.  See <file:Documentation/sound/oss/Maestro> for more
-         details.
-
-config SOUND_MAESTRO3
-       tristate "ESS Maestro3/Allegro driver (EXPERIMENTAL)"
-       depends on SOUND_PRIME && PCI && EXPERIMENTAL && OBSOLETE_OSS_DRIVER
-       help
-         Say Y or M if you have a sound system driven by ESS's Maestro 3
-         PCI sound chip.
-
 config SOUND_ICH
        tristate "Intel ICH (i8xx) audio support"
        depends on SOUND_PRIME && PCI
@@ -185,24 +85,6 @@ config SOUND_ICH
          Support for integral audio in Intel's I/O Controller Hub (ICH)
          chipset, as used on the 810/820/840 motherboards.
 
-config SOUND_HARMONY
-       tristate "PA Harmony audio driver"
-       depends on GSC_LASI && SOUND_PRIME && OBSOLETE_OSS_DRIVER
-       help
-         Say 'Y' or 'M' to include support for Harmony soundchip
-         on HP 712, 715/new and many other GSC based machines.
-
-config SOUND_SONICVIBES
-       tristate "S3 SonicVibes"
-       depends on SOUND_PRIME && PCI && OBSOLETE_OSS_DRIVER
-       help
-         Say Y or M if you have a PCI sound card utilizing the S3
-         SonicVibes chipset. To find out if your sound card uses a
-         SonicVibes chip without removing your computer's cover, use
-         lspci -n and look for the PCI ID 5333:CA00. This driver
-         differs slightly from OSS/Free, so PLEASE READ
-         <file:Documentation/sound/oss/sonicvibes>.
-
 config SOUND_VWSND
        tristate "SGI Visual Workstation Sound"
        depends on SOUND_PRIME && X86_VISWS
@@ -231,10 +113,6 @@ config SOUND_VRC5477
          integrated, multi-function controller chip for MIPS CPUs.  Works
          with the AC97 codec.
 
-config SOUND_AU1000
-       tristate "Au1000 Sound"
-       depends on SOUND_PRIME && (SOC_AU1000 || SOC_AU1100 || SOC_AU1500) && OBSOLETE_OSS_DRIVER
-
 config SOUND_AU1550_AC97
        tristate "Au1550 AC97 Sound"
        depends on SOUND_PRIME && SOC_AU1550
@@ -507,7 +385,7 @@ config MSND_FIFOSIZE
 
 config SOUND_VIA82CXXX
        tristate "VIA 82C686 Audio Codec"
-       depends on SOUND_PRIME && PCI && OBSOLETE_OSS_DRIVER
+       depends on SOUND_PRIME && PCI
        help
          Say Y here to include support for the audio codec found on VIA
          82Cxxx-based chips. Typically these are built into a motherboard.
@@ -576,18 +454,6 @@ config SOUND_AD1889
          Say M here if you have a sound card based on the Analog Devices
          AD1889 chip.
 
-config SOUND_SGALAXY
-       tristate "Aztech Sound Galaxy (non-PnP) cards"
-       depends on SOUND_OSS && OBSOLETE_OSS_DRIVER
-       help
-         This module initializes the older non Plug and Play sound galaxy
-         cards from Aztech. It supports the Waverider Pro 32 - 3D and the
-         Galaxy Washington 16.
-
-         If you compile the driver into the kernel, you have to add
-         "sgalaxy=<io>,<irq>,<dma>,<dma2>,<sgbase>" to the kernel command
-         line.
-
 config SOUND_ADLIB
        tristate "Adlib Cards"
        depends on SOUND_OSS
@@ -612,56 +478,6 @@ config SOUND_ACI_MIXER
 
          This driver is also available as a module and will be called aci.
 
-config SOUND_CS4232
-       tristate "Crystal CS4232 based (PnP) cards"
-       depends on SOUND_OSS && OBSOLETE_OSS_DRIVER
-       help
-         Say Y here if you have a card based on the Crystal CS4232 chip set,
-         which uses its own Plug and Play protocol.
-
-         If you compile the driver into the kernel, you have to add
-         "cs4232=<io>,<irq>,<dma>,<dma2>,<mpuio>,<mpuirq>" to the kernel
-         command line.
-
-         See <file:Documentation/sound/oss/CS4232> for more information on
-         configuring this card.
-
-config SOUND_SSCAPE
-       tristate "Ensoniq SoundScape support"
-       depends on SOUND_OSS && OBSOLETE_OSS_DRIVER
-       help
-         Answer Y if you have a sound card based on the Ensoniq SoundScape
-         chipset. Such cards are being manufactured at least by Ensoniq, Spea
-         and Reveal (Reveal makes also other cards).
-
-         If you compile the driver into the kernel, you have to add
-         "sscape=<io>,<irq>,<dma>,<mpuio>,<mpuirq>" to the kernel command
-         line.
-
-config SOUND_GUS
-       tristate "Gravis Ultrasound support"
-       depends on SOUND_OSS && OBSOLETE_OSS_DRIVER
-       help
-         Say Y here for any type of Gravis Ultrasound card, including the GUS
-         or GUS MAX.  See also <file:Documentation/sound/oss/ultrasound> for more
-         information on configuring this card with modules.
-
-         If you compile the driver into the kernel, you have to add
-         "gus=<io>,<irq>,<dma>,<dma2>" to the kernel command line.
-
-config SOUND_GUS16
-       bool "16 bit sampling option of GUS (_NOT_ GUS MAX)"
-       depends on SOUND_GUS
-       help
-         Support for Gravis Ulstrasound (GUS) cards (other than the GUS),
-         sampling at 16-bit width.
-
-config SOUND_GUSMAX
-       bool "GUS MAX support"
-       depends on SOUND_GUS
-       help
-         Support for Gravis Ulstrasound MAX.
-
 config SOUND_VMIDI
        tristate "Loopback MIDI device support"
        depends on SOUND_OSS
@@ -742,7 +558,7 @@ config SOUND_MPU401
 
 config SOUND_NM256
        tristate "NM256AV/NM256ZX audio support"
-       depends on SOUND_OSS && OBSOLETE_OSS_DRIVER
+       depends on SOUND_OSS
        help
          Say M here to include audio support for the NeoMagic 256AV/256ZX
          chipsets. These are the audio chipsets found in the Sony
@@ -752,35 +568,6 @@ config SOUND_NM256
 
          See <file:Documentation/sound/oss/NM256> for further information.
 
-config SOUND_MAD16
-       tristate "OPTi MAD16 and/or Mozart based cards"
-       depends on SOUND_OSS && OBSOLETE_OSS_DRIVER
-       ---help---
-         Answer Y if your card has a Mozart (OAK OTI-601) or MAD16 (OPTi
-         82C928 or 82C929 or 82C931) audio interface chip. These chips are
-         quite common so it's possible that many no-name cards have one of
-         them. In addition the MAD16 chip is used in some cards made by known
-         manufacturers such as Turtle Beach (Tropez), Reveal (some models)
-         and Diamond (latest ones). Note however that the Tropez sound cards
-         have their own driver; if you have one of those, say N here and Y or
-         M to "Full support for Turtle Beach WaveFront", below.
-
-         If you compile the driver into the kernel, you have to add
-         "mad16=<io>,<irq>,<dma>,<dma2>,<mpuio>,<mpuirq>" to the
-         kernel command line.
-
-         See also <file:Documentation/sound/oss/Opti> and
-         <file:Documentation/sound/oss/MAD16> for more information on setting
-         these cards up as modules.
-
-config MAD16_OLDCARD
-       bool "Support MIDI in older MAD16 based cards (requires SB)"
-       depends on SOUND_MAD16
-       help
-         Answer Y (or M) if you have an older card based on the C928 or
-         Mozart chipset and you want to have MIDI support. If you enable this
-         option you also need to enable support for Sound Blaster.
-
 config SOUND_PAS
        tristate "ProAudioSpectrum 16 support"
        depends on SOUND_OSS
@@ -873,53 +660,9 @@ config SOUND_SB
          You can say M here to compile this driver as a module; the module is
          called sb.
 
-config SOUND_AWE32_SYNTH
-       tristate "AWE32 synth"
-       depends on SOUND_OSS && OBSOLETE_OSS_DRIVER
-       help
-         Say Y here if you have a Sound Blaster SB32, AWE32-PnP, SB AWE64 or
-         similar sound card. See <file:Documentation/sound/oss/README.awe>,
-         <file:Documentation/sound/oss/AWE32> and the Soundblaster-AWE
-         mini-HOWTO, available from <http://www.tldp.org/docs.html#howto>
-         for more info.
-
-config SOUND_WAVEFRONT
-       tristate "Full support for Turtle Beach WaveFront (Tropez Plus, Tropez, Maui) synth/soundcards"
-       depends on SOUND_OSS && m && OBSOLETE_OSS_DRIVER
-       help
-         Answer Y or M if you have a Tropez Plus, Tropez or Maui sound card
-         and read the files <file:Documentation/sound/oss/Wavefront> and
-         <file:Documentation/sound/oss/Tropez+>.
-
-config SOUND_MAUI
-       tristate "Limited support for Turtle Beach Wave Front (Maui, Tropez) synthesizers"
-       depends on SOUND_OSS && OBSOLETE_OSS_DRIVER
-       help
-         Say Y here if you have a Turtle Beach Wave Front, Maui, or Tropez
-         sound card.
-
-         If you compile the driver into the kernel, you have to add
-         "maui=<io>,<irq>" to the kernel command line.
-
-config MAUI_HAVE_BOOT
-       bool "Have OSWF.MOT firmware file"
-       depends on SOUND_MAUI=y && !STANDALONE
-       help
-         Turtle Beach Maui and Tropez sound cards have a microcontroller
-         which needs to be initialized prior to use. OSWF.MOT is a file
-         distributed with the card's DOS/Windows drivers. Answer Y if you
-         have this file.
-
-config MAUI_BOOT_FILE
-       string "Full pathname of OSWF.MOT firmware file"
-       depends on MAUI_HAVE_BOOT
-       default "/etc/sound/oswf.mot"
-       help
-         Enter the full pathname of your OSWF.MOT file, starting from /.
-
 config SOUND_YM3812
        tristate "Yamaha FM synthesizer (YM3812/OPL-3) support"
-       depends on SOUND_OSS && OBSOLETE_OSS_DRIVER
+       depends on SOUND_OSS
        ---help---
          Answer Y if your card has a FM chip made by Yamaha (OPL2/OPL3/OPL4).
          Answering Y is usually a safe and recommended choice, however some
@@ -933,18 +676,6 @@ config SOUND_YM3812
 
          If unsure, say Y.
 
-config SOUND_OPL3SA1
-       tristate "Yamaha OPL3-SA1 audio controller"
-       depends on SOUND_OSS && OBSOLETE_OSS_DRIVER
-       help
-         Say Y or M if you have a Yamaha OPL3-SA1 sound chip, which is
-         usually built into motherboards. Read
-         <file:Documentation/sound/oss/OPL3-SA> for details.
-
-         If you compile the driver into the kernel, you have to add
-         "opl3sa=<io>,<irq>,<dma>,<dma2>,<mpuio>,<mpuirq>" to the kernel
-         command line.
-
 config SOUND_OPL3SA2
        tristate "Yamaha OPL3-SA2 and SA3 based PnP cards"
        depends on SOUND_OSS
@@ -959,19 +690,6 @@ config SOUND_OPL3SA2
          "opl3sa2=<io>,<irq>,<dma>,<dma2>,<mssio>,<mpuio>" to the kernel
          command line.
 
-config SOUND_YMFPCI
-       tristate "Yamaha YMF7xx PCI audio (native mode)"
-       depends on SOUND_OSS && PCI && OBSOLETE_OSS_DRIVER
-       help
-         Support for Yamaha cards including the YMF711, YMF715, YMF718,
-         YMF719, YMF724, Waveforce 192XG, and Waveforce 192 Digital.
-
-config SOUND_YMFPCI_LEGACY
-       bool "Yamaha PCI legacy ports support"
-       depends on SOUND_YMFPCI
-       help
-         Support for YMF7xx PCI cards emulating an MP401.
-
 config SOUND_UART6850
        tristate "6850 UART support"
        depends on SOUND_OSS
@@ -1101,30 +819,6 @@ config SOUND_KAHLUA
        tristate "XpressAudio Sound Blaster emulation"
        depends on SOUND_SB
 
-config SOUND_ALI5455
-       tristate "ALi5455 audio support"
-       depends on SOUND_PRIME && PCI && OBSOLETE_OSS_DRIVER
-
-config SOUND_FORTE
-       tristate "ForteMedia FM801 driver"
-       depends on SOUND_PRIME && PCI && OBSOLETE_OSS_DRIVER
-       help
-         Say Y or M if you want driver support for the ForteMedia FM801 PCI
-         audio controller (Abit AU10, Genius Sound Maker, HP Workstation
-         zx2000, and others).
-
-config SOUND_RME96XX
-       tristate "RME Hammerfall (RME96XX) support"
-       depends on SOUND_PRIME && PCI && OBSOLETE_OSS_DRIVER
-       help
-         Say Y or M if you have a Hammerfall or Hammerfall light
-         multichannel card from RME. If you want to access advanced
-         features of the card, read <file:Documentation/sound/oss/rme96xx>.
-
-config SOUND_AD1980
-       tristate "AD1980 front/back switch plugin"
-       depends on SOUND_PRIME && OBSOLETE_OSS_DRIVER
-
 config SOUND_SH_DAC_AUDIO
        tristate "SuperH DAC audio support"
        depends on SOUND_PRIME && CPU_SH3
index 33dbcbf77c5b0d5713d4c6774e5c7f863d4750fb..83acd6cc0b3cd70325ec383eb8fdc309918a0a98 100644 (file)
@@ -471,6 +471,7 @@ int main (int argc, char *argv[])
                                "ERROR: incorrect format, could not locate file type line %d: '%s'\n",
                                line_nr, line);
                        ec = -1;
+                       break;
                }
 
                if ('\n' == *type) {
@@ -506,7 +507,8 @@ int main (int argc, char *argv[])
                                line_nr, line);
                }
        }
-       cpio_trailer();
+       if (ec == 0)
+               cpio_trailer();
 
        exit(ec);
 }