summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKai Germaschewski <kai@tp1.ruhr-uni-bochum.de>2002-12-29 13:51:34 -0600
committerKai Germaschewski <kai@tp1.ruhr-uni-bochum.de>2002-12-29 13:51:34 -0600
commitf5a46614de328e867f778e4dffa71b48eb29340f (patch)
treee20250a27ae5dbeb927a7d085cd7dc162aa829e5
parent8f99d72cc9359b80ef6c50a00ad098c78ac035ed (diff)
parentbec7aa00ffe5b1270837b965fdfe80be3e8e6e2e (diff)
Merge tp1.ruhr-uni-bochum.de:/home/kai/kernel/v2.5/linux-2.5
into tp1.ruhr-uni-bochum.de:/home/kai/kernel/v2.5/linux-2.5.make
-rw-r--r--Documentation/Changes13
-rw-r--r--Documentation/kbuild/makefiles.txt2
-rw-r--r--Documentation/modules.txt14
-rw-r--r--Documentation/networking/z8530drv.txt2
-rw-r--r--Documentation/sound/oss/Introduction6
-rw-r--r--Documentation/sysctl/kernel.txt4
-rw-r--r--Documentation/sysrq.txt2
-rw-r--r--Documentation/uml/UserModeLinux-HOWTO.txt4686
-rw-r--r--Documentation/usb/dma.txt104
-rw-r--r--Documentation/usb/hotplug.txt14
-rw-r--r--Documentation/usb/usb-serial.txt36
-rw-r--r--Documentation/video4linux/README.cpia6
-rw-r--r--MAINTAINERS9
-rw-r--r--arch/i386/Kconfig135
-rw-r--r--arch/i386/Makefile5
-rw-r--r--arch/i386/boot/compressed/head.S8
-rw-r--r--arch/i386/boot/compressed/misc.c2
-rw-r--r--arch/i386/boot/setup.S56
-rw-r--r--arch/i386/defconfig345
-rw-r--r--arch/i386/kernel/Makefile3
-rw-r--r--arch/i386/kernel/apic.c3
-rw-r--r--arch/i386/kernel/cpu/common.c19
-rw-r--r--arch/i386/kernel/cpu/mcheck/k7.c5
-rw-r--r--arch/i386/kernel/cpu/mtrr/main.c2
-rw-r--r--arch/i386/kernel/cpu/proc.c2
-rw-r--r--arch/i386/kernel/head.S22
-rw-r--r--arch/i386/kernel/ioport.c3
-rw-r--r--arch/i386/kernel/mpparse.c2
-rw-r--r--arch/i386/kernel/nmi.c4
-rw-r--r--arch/i386/kernel/process.c5
-rw-r--r--arch/i386/kernel/smpboot.c12
-rw-r--r--arch/i386/kernel/suspend_asm.S3
-rw-r--r--arch/i386/kernel/timers/Makefile6
-rw-r--r--arch/i386/kernel/timers/timer.c2
-rw-r--r--arch/i386/kernel/timers/timer_pit.c2
-rw-r--r--arch/i386/kernel/timers/timer_tsc.c16
-rw-r--r--arch/i386/kernel/trampoline.S6
-rw-r--r--arch/i386/mach-voyager/setup.c3
-rw-r--r--arch/i386/mach-voyager/voyager_basic.c28
-rw-r--r--arch/i386/mach-voyager/voyager_smp.c59
-rw-r--r--arch/i386/oprofile/nmi_int.c2
-rw-r--r--arch/i386/oprofile/op_model_athlon.c2
-rw-r--r--arch/i386/oprofile/op_model_ppro.c2
-rw-r--r--arch/i386/oprofile/timer_int.c2
-rw-r--r--arch/m68k/Kconfig44
-rw-r--r--arch/m68k/Makefile1
-rw-r--r--arch/m68k/amiga/cia.c1
-rw-r--r--arch/m68k/amiga/config.c1
-rw-r--r--arch/m68k/apollo/config.c1
-rw-r--r--arch/m68k/atari/ataints.c24
-rw-r--r--arch/m68k/atari/atasound.c5
-rw-r--r--arch/m68k/atari/config.c7
-rw-r--r--arch/m68k/atari/stdma.c17
-rw-r--r--arch/m68k/atari/stram.c4
-rw-r--r--arch/m68k/atari/time.c5
-rw-r--r--arch/m68k/bvme6000/config.c6
-rw-r--r--arch/m68k/bvme6000/rtc.c13
-rw-r--r--arch/m68k/kernel/entry.S6
-rw-r--r--arch/m68k/kernel/head.S60
-rw-r--r--arch/m68k/kernel/m68k_defs.c14
-rw-r--r--arch/m68k/kernel/m68k_ksyms.c1
-rw-r--r--arch/m68k/kernel/process.c13
-rw-r--r--arch/m68k/kernel/setup.c3
-rw-r--r--arch/m68k/kernel/signal.c2
-rw-r--r--arch/m68k/kernel/traps.c27
-rw-r--r--arch/m68k/mac/config.c38
-rw-r--r--arch/m68k/mac/iop.c10
-rw-r--r--arch/m68k/mac/macboing.c15
-rw-r--r--arch/m68k/mac/macints.c28
-rw-r--r--arch/m68k/mac/misc.c20
-rw-r--r--arch/m68k/mac/via.c74
-rw-r--r--arch/m68k/mm/extable.c26
-rw-r--r--arch/m68k/mm/sun3mmu.c2
-rw-r--r--arch/m68k/mvme147/config.c8
-rw-r--r--arch/m68k/mvme16x/config.c1
-rw-r--r--arch/m68k/mvme16x/rtc.c13
-rw-r--r--arch/m68k/q40/q40ints.c3
-rw-r--r--arch/m68k/sun3/config.c5
-rw-r--r--arch/m68k/sun3/dvma.c12
-rw-r--r--arch/m68k/sun3/intersil.c4
-rw-r--r--arch/m68k/sun3/prom/console.c16
-rw-r--r--arch/m68k/sun3/prom/misc.c8
-rw-r--r--arch/m68k/sun3/sbus.c9
-rw-r--r--arch/m68k/sun3x/dvma.c7
-rw-r--r--arch/m68k/sun3x/prom.c8
-rw-r--r--arch/m68k/sun3x/time.c4
-rw-r--r--arch/m68k/vmlinux-std.lds7
-rw-r--r--arch/m68k/vmlinux-sun3.lds7
-rw-r--r--arch/sparc/vmlinux.lds.S3
-rw-r--r--arch/um/Kconfig93
-rw-r--r--arch/um/Kconfig_block34
-rw-r--r--arch/um/Kconfig_char76
-rw-r--r--arch/um/Kconfig_net147
-rw-r--r--arch/um/Makefile78
-rw-r--r--arch/um/Makefile-i3864
-rw-r--r--arch/um/boot/Makefile3
-rw-r--r--arch/um/config_block.in16
-rw-r--r--arch/um/config_char.in37
-rw-r--r--arch/um/config_net.in46
-rw-r--r--arch/um/config_scsi.in30
-rw-r--r--arch/um/drivers/Makefile24
-rw-r--r--arch/um/drivers/chan_kern.c66
-rw-r--r--arch/um/drivers/chan_user.c33
-rw-r--r--arch/um/drivers/fd.c8
-rw-r--r--arch/um/drivers/line.c108
-rw-r--r--arch/um/drivers/mcast_kern.c4
-rw-r--r--arch/um/drivers/mconsole_kern.c62
-rw-r--r--arch/um/drivers/net_kern.c111
-rw-r--r--arch/um/drivers/null.c5
-rw-r--r--arch/um/drivers/port_kern.c25
-rw-r--r--arch/um/drivers/port_user.c47
-rw-r--r--arch/um/drivers/pty.c19
-rw-r--r--arch/um/drivers/slip.h10
-rw-r--r--arch/um/drivers/slip_kern.c9
-rw-r--r--arch/um/drivers/slip_proto.h93
-rw-r--r--arch/um/drivers/slip_user.c106
-rw-r--r--arch/um/drivers/slirp.h51
-rw-r--r--arch/um/drivers/slirp_kern.c132
-rw-r--r--arch/um/drivers/slirp_user.c202
-rw-r--r--arch/um/drivers/ssl.c36
-rw-r--r--arch/um/drivers/stdio_console.c32
-rw-r--r--arch/um/drivers/tty.c8
-rw-r--r--arch/um/drivers/ubd_kern.c48
-rw-r--r--arch/um/drivers/ubd_user.c2
-rw-r--r--arch/um/drivers/xterm.c7
-rw-r--r--arch/um/drivers/xterm_kern.c6
-rw-r--r--arch/um/include/chan_kern.h3
-rw-r--r--arch/um/include/chan_user.h4
-rw-r--r--arch/um/include/choose-mode.h35
-rw-r--r--arch/um/include/frame.h18
-rw-r--r--arch/um/include/kern.h2
-rw-r--r--arch/um/include/kern_util.h28
-rw-r--r--arch/um/include/line.h11
-rw-r--r--arch/um/include/mconsole_kern.h16
-rw-r--r--arch/um/include/mem.h1
-rw-r--r--arch/um/include/mem_user.h12
-rw-r--r--arch/um/include/mode.h30
-rw-r--r--arch/um/include/mode_kern.h30
-rw-r--r--arch/um/include/net_kern.h5
-rw-r--r--arch/um/include/net_user.h5
-rw-r--r--arch/um/include/os.h8
-rw-r--r--arch/um/include/sigcontext.h2
-rw-r--r--arch/um/include/syscall_user.h13
-rw-r--r--arch/um/include/sysdep-i386/checksum.h217
-rw-r--r--arch/um/include/sysdep-i386/frame_kern.h9
-rw-r--r--arch/um/include/sysdep-i386/ptrace.h111
-rw-r--r--arch/um/include/sysdep-i386/sigcontext.h33
-rw-r--r--arch/um/include/time_user.h2
-rw-r--r--arch/um/include/um_mmu.h40
-rw-r--r--arch/um/include/um_uaccess.h73
-rw-r--r--arch/um/include/user_util.h26
-rw-r--r--arch/um/kernel/Makefile56
-rw-r--r--arch/um/kernel/checksum.c42
-rw-r--r--arch/um/kernel/exec_kern.c64
-rw-r--r--arch/um/kernel/exitcode.c2
-rw-r--r--arch/um/kernel/frame.c202
-rw-r--r--arch/um/kernel/frame_kern.c85
-rw-r--r--arch/um/kernel/helper.c10
-rw-r--r--arch/um/kernel/init_task.c2
-rw-r--r--arch/um/kernel/irq_user.c4
-rw-r--r--arch/um/kernel/ksyms.c17
-rw-r--r--arch/um/kernel/mem.c71
-rw-r--r--arch/um/kernel/mem_user.c44
-rw-r--r--arch/um/kernel/process.c136
-rw-r--r--arch/um/kernel/process_kern.c477
-rw-r--r--arch/um/kernel/ptrace.c61
-rw-r--r--arch/um/kernel/reboot.c25
-rw-r--r--arch/um/kernel/sigio_user.c13
-rw-r--r--arch/um/kernel/signal_kern.c27
-rw-r--r--arch/um/kernel/signal_user.c9
-rw-r--r--arch/um/kernel/skas/Makefile24
-rw-r--r--arch/um/kernel/skas/exec_kern.c41
-rw-r--r--arch/um/kernel/skas/exec_user.c61
-rw-r--r--arch/um/kernel/skas/include/mmu.h27
-rw-r--r--arch/um/kernel/skas/include/mode.h34
-rw-r--r--arch/um/kernel/skas/include/mode_kern.h52
-rw-r--r--arch/um/kernel/skas/include/proc_mm.h55
-rw-r--r--arch/um/kernel/skas/include/ptrace-skas.h57
-rw-r--r--arch/um/kernel/skas/include/skas.h49
-rw-r--r--arch/um/kernel/skas/include/skas_ptrace.h36
-rw-r--r--arch/um/kernel/skas/include/uaccess.h236
-rw-r--r--arch/um/kernel/skas/mem.c35
-rw-r--r--arch/um/kernel/skas/mem_user.c95
-rw-r--r--arch/um/kernel/skas/mmu.c46
-rw-r--r--arch/um/kernel/skas/process.c386
-rw-r--r--arch/um/kernel/skas/process_kern.c195
-rw-r--r--arch/um/kernel/skas/sys-i386/Makefile14
-rw-r--r--arch/um/kernel/skas/sys-i386/sigcontext.c114
-rw-r--r--arch/um/kernel/skas/syscall_kern.c42
-rw-r--r--arch/um/kernel/skas/syscall_user.c47
-rw-r--r--arch/um/kernel/skas/time.c30
-rw-r--r--arch/um/kernel/skas/tlb.c156
-rw-r--r--arch/um/kernel/skas/trap_user.c66
-rw-r--r--arch/um/kernel/skas/util/Makefile10
-rw-r--r--arch/um/kernel/skas/util/mk_ptregs.c50
-rw-r--r--arch/um/kernel/smp.c12
-rw-r--r--arch/um/kernel/sys_call_table.c19
-rw-r--r--arch/um/kernel/syscall_kern.c132
-rw-r--r--arch/um/kernel/syscall_user.c79
-rw-r--r--arch/um/kernel/sysrq.c8
-rw-r--r--arch/um/kernel/tempfile.c3
-rw-r--r--arch/um/kernel/time.c22
-rw-r--r--arch/um/kernel/time_kern.c3
-rw-r--r--arch/um/kernel/tlb.c219
-rw-r--r--arch/um/kernel/trap_kern.c361
-rw-r--r--arch/um/kernel/trap_user.c492
-rw-r--r--arch/um/kernel/tt/Makefile20
-rw-r--r--arch/um/kernel/tt/exec_kern.c84
-rw-r--r--arch/um/kernel/tt/exec_user.c (renamed from arch/um/kernel/exec_user.c)0
-rw-r--r--arch/um/kernel/tt/gdb.c278
-rw-r--r--arch/um/kernel/tt/gdb_kern.c40
-rw-r--r--arch/um/kernel/tt/include/debug.h (renamed from arch/um/include/debug.h)3
-rw-r--r--arch/um/kernel/tt/include/mmu.h (renamed from arch/um/kernel/setup.c)11
-rw-r--r--arch/um/kernel/tt/include/mode.h35
-rw-r--r--arch/um/kernel/tt/include/mode_kern.h53
-rw-r--r--arch/um/kernel/tt/include/ptrace-tt.h26
-rw-r--r--arch/um/kernel/tt/include/tt.h45
-rw-r--r--arch/um/kernel/tt/include/uaccess.h119
-rw-r--r--arch/um/kernel/tt/ksyms.c28
-rw-r--r--arch/um/kernel/tt/mem.c77
-rw-r--r--arch/um/kernel/tt/process_kern.c513
-rw-r--r--arch/um/kernel/tt/ptproxy/Makefile13
-rw-r--r--arch/um/kernel/tt/ptproxy/proxy.c (renamed from arch/um/ptproxy/proxy.c)0
-rw-r--r--arch/um/kernel/tt/ptproxy/ptproxy.h (renamed from arch/um/ptproxy/ptproxy.h)0
-rw-r--r--arch/um/kernel/tt/ptproxy/ptrace.c (renamed from arch/um/ptproxy/ptrace.c)1
-rw-r--r--arch/um/kernel/tt/ptproxy/sysdep.c (renamed from arch/um/ptproxy/sysdep.c)0
-rw-r--r--arch/um/kernel/tt/ptproxy/sysdep.h (renamed from arch/um/ptproxy/sysdep.h)0
-rw-r--r--arch/um/kernel/tt/ptproxy/wait.c (renamed from arch/um/ptproxy/wait.c)0
-rw-r--r--arch/um/kernel/tt/ptproxy/wait.h (renamed from arch/um/ptproxy/wait.h)0
-rw-r--r--arch/um/kernel/tt/sys-i386/Makefile14
-rw-r--r--arch/um/kernel/tt/sys-i386/sigcontext.c59
-rw-r--r--arch/um/kernel/tt/syscall_kern.c140
-rw-r--r--arch/um/kernel/tt/syscall_user.c90
-rw-r--r--arch/um/kernel/tt/time.c28
-rw-r--r--arch/um/kernel/tt/tlb.c226
-rw-r--r--arch/um/kernel/tt/tracer.c466
-rw-r--r--arch/um/kernel/tt/trap_user.c58
-rw-r--r--arch/um/kernel/tt/uaccess_user.c (renamed from arch/um/kernel/uaccess_user.c)0
-rw-r--r--arch/um/kernel/tty_log.c2
-rw-r--r--arch/um/kernel/um_arch.c119
-rw-r--r--arch/um/kernel/umid.c6
-rw-r--r--arch/um/main.c64
-rw-r--r--arch/um/os-Linux/Makefile6
-rw-r--r--arch/um/os-Linux/drivers/Makefile3
-rw-r--r--arch/um/os-Linux/file.c4
-rw-r--r--arch/um/os-Linux/process.c42
-rw-r--r--arch/um/os-Linux/tty.c2
-rw-r--r--arch/um/ptproxy/Makefile10
-rw-r--r--arch/um/sys-i386/Makefile32
-rw-r--r--arch/um/sys-i386/checksum.S460
-rw-r--r--arch/um/sys-i386/ksyms.c3
-rw-r--r--arch/um/sys-i386/ldt.c69
-rw-r--r--arch/um/sys-i386/ptrace.c57
-rw-r--r--arch/um/sys-i386/ptrace_user.c2
-rw-r--r--arch/um/sys-i386/sigcontext.c39
-rw-r--r--arch/um/sys-i386/util/mk_thread_kern.c16
-rw-r--r--arch/um/sys-i386/util/mk_thread_user.c32
-rw-r--r--arch/um/uml.lds.S12
-rw-r--r--arch/um/util/Makefile11
-rw-r--r--arch/um/util/mk_constants_kern.c24
-rw-r--r--arch/um/util/mk_constants_user.c28
-rw-r--r--arch/x86_64/Kconfig2
-rw-r--r--arch/x86_64/Makefile2
-rw-r--r--arch/x86_64/boot/Makefile1
-rw-r--r--arch/x86_64/defconfig6
-rw-r--r--arch/x86_64/ia32/Makefile2
-rw-r--r--arch/x86_64/ia32/fpu32.c12
-rw-r--r--arch/x86_64/ia32/ia32_binfmt.c6
-rw-r--r--arch/x86_64/ia32/ia32entry.S48
-rw-r--r--arch/x86_64/ia32/sys_ia32.c5
-rw-r--r--arch/x86_64/ia32/syscall32.c64
-rw-r--r--arch/x86_64/kernel/Makefile4
-rw-r--r--arch/x86_64/kernel/apic.c1
-rw-r--r--arch/x86_64/kernel/signal.c5
-rw-r--r--arch/x86_64/kernel/time.c13
-rw-r--r--arch/x86_64/kernel/traps.c5
-rw-r--r--arch/x86_64/kernel/x8664_ksyms.c10
-rw-r--r--arch/x86_64/mm/fault.c14
-rw-r--r--arch/x86_64/oprofile/Kconfig23
-rw-r--r--arch/x86_64/oprofile/Makefile33
-rw-r--r--crypto/api.c3
-rw-r--r--drivers/block/acsi.c5
-rw-r--r--drivers/block/acsi_slm.c20
-rw-r--r--drivers/block/amiflop.c33
-rw-r--r--drivers/block/ataflop.c69
-rw-r--r--drivers/block/genhd.c6
-rw-r--r--drivers/block/paride/paride.c15
-rw-r--r--drivers/block/swim_iop.c25
-rw-r--r--drivers/block/z2ram.c2
-rw-r--r--drivers/bluetooth/hci_usb.c6
-rw-r--r--drivers/char/amiserial.c124
-rw-r--r--drivers/char/busmouse.c7
-rw-r--r--drivers/char/mem.c6
-rw-r--r--drivers/char/ser_a2232.c25
-rw-r--r--drivers/char/serial167.c144
-rw-r--r--drivers/char/sysrq.c20
-rw-r--r--drivers/char/vme_scc.c60
-rw-r--r--drivers/hotplug/pci_hotplug_core.c52
-rw-r--r--drivers/i2c/Kconfig5
-rw-r--r--drivers/i2c/Makefile4
-rw-r--r--drivers/i2c/busses/Kconfig43
-rw-r--r--drivers/i2c/busses/Makefile6
-rw-r--r--drivers/i2c/busses/i2c-amd756.c435
-rw-r--r--drivers/i2c/busses/i2c-amd8111.c425
-rw-r--r--drivers/i2c/chips/Kconfig40
-rw-r--r--drivers/i2c/chips/Makefile6
-rw-r--r--drivers/i2c/chips/adm1021.c600
-rw-r--r--drivers/i2c/chips/lm75.c361
-rw-r--r--drivers/i2c/i2c-adap-ite.c24
-rw-r--r--drivers/i2c/i2c-algo-bit.c19
-rw-r--r--drivers/i2c/i2c-algo-pcf.c19
-rw-r--r--drivers/i2c/i2c-core.c177
-rw-r--r--drivers/i2c/i2c-dev.c24
-rw-r--r--drivers/i2c/i2c-elektor.c71
-rw-r--r--drivers/i2c/i2c-elv.c70
-rw-r--r--drivers/i2c/i2c-frodo.c7
-rw-r--r--drivers/i2c/i2c-philips-par.c13
-rw-r--r--drivers/i2c/i2c-proc.c63
-rw-r--r--drivers/i2c/i2c-rpx.c3
-rw-r--r--drivers/i2c/i2c-velleman.c29
-rw-r--r--drivers/ide/ide-io.c4
-rw-r--r--drivers/ide/ide-timing.h8
-rw-r--r--drivers/ide/ide.c18
-rw-r--r--drivers/ide/legacy/falconide.c8
-rw-r--r--drivers/ieee1394/ieee1394_core.c23
-rw-r--r--drivers/input/joystick/amijoy.c1
-rw-r--r--drivers/input/joystick/iforce/iforce-usb.c6
-rw-r--r--drivers/input/keyboard/amikbd.c1
-rw-r--r--drivers/input/mouse/amimouse.c1
-rw-r--r--drivers/input/serio/q40kbd.c4
-rw-r--r--drivers/isdn/capi/kcapi.c3
-rw-r--r--drivers/isdn/hisax/st5481_b.c2
-rw-r--r--drivers/isdn/hisax/st5481_d.c2
-rw-r--r--drivers/isdn/hisax/st5481_init.c6
-rw-r--r--drivers/isdn/hisax/st5481_usb.c2
-rw-r--r--drivers/macintosh/adb-iop.c20
-rw-r--r--drivers/macintosh/via-cuda.c1
-rw-r--r--drivers/macintosh/via-macii.c36
-rw-r--r--drivers/macintosh/via-maciisi.c22
-rw-r--r--drivers/macintosh/via-pmu68k.c20
-rw-r--r--drivers/md/dm-target.c14
-rw-r--r--drivers/media/dvb/dvb-core/dvb_i2c.c23
-rw-r--r--drivers/media/video/cpia.c3
-rw-r--r--drivers/media/video/cpia_usb.c10
-rw-r--r--drivers/mtd/chips/chipreg.c6
-rw-r--r--drivers/net/a2065.c7
-rw-r--r--drivers/net/ariadne.c10
-rw-r--r--drivers/net/atari_bionet.c24
-rw-r--r--drivers/net/atari_pamsnet.c14
-rw-r--r--drivers/net/atarilance.c5
-rw-r--r--drivers/net/irda/irda-usb.c6
-rw-r--r--drivers/net/irda/sir_dev.c9
-rw-r--r--drivers/net/irda/sir_dongle.c7
-rw-r--r--drivers/net/mac8390.c4
-rw-r--r--drivers/net/mac89x0.c20
-rw-r--r--drivers/net/macmace.c5
-rw-r--r--drivers/net/macsonic.c5
-rw-r--r--drivers/net/sun3_82586.c5
-rw-r--r--drivers/net/sun3lance.c4
-rw-r--r--drivers/nubus/nubus.c5
-rw-r--r--drivers/parport/parport_amiga.c1
-rw-r--r--drivers/parport/parport_atari.c36
-rw-r--r--drivers/parport/parport_mfc3.c1
-rw-r--r--drivers/pci/probe.c9
-rw-r--r--drivers/pcmcia/yenta.c1
-rw-r--r--drivers/s390/block/dasd.c3
-rw-r--r--drivers/s390/block/dasd_ioctl.c2
-rw-r--r--drivers/s390/char/tape_core.c3
-rw-r--r--drivers/scsi/53c7xx.c163
-rw-r--r--drivers/scsi/NCR5380.c3
-rw-r--r--drivers/scsi/NCR53C9x.c57
-rw-r--r--drivers/scsi/NCR53C9x.h8
-rw-r--r--drivers/scsi/a2091.c17
-rw-r--r--drivers/scsi/a2091.h13
-rw-r--r--drivers/scsi/a3000.c17
-rw-r--r--drivers/scsi/a3000.h14
-rw-r--r--drivers/scsi/aic7xxx/Kconfig.aic79xx2
-rw-r--r--drivers/scsi/aic7xxx/Kconfig.aic7xxx2
-rw-r--r--drivers/scsi/amiga7xx.c15
-rw-r--r--drivers/scsi/amiga7xx.h11
-rw-r--r--drivers/scsi/atari_NCR5380.c95
-rw-r--r--drivers/scsi/atari_scsi.c34
-rw-r--r--drivers/scsi/atari_scsi.h14
-rw-r--r--drivers/scsi/blz1230.c65
-rw-r--r--drivers/scsi/blz1230.h75
-rw-r--r--drivers/scsi/blz2060.c60
-rw-r--r--drivers/scsi/blz2060.h70
-rw-r--r--drivers/scsi/bvme6000.c15
-rw-r--r--drivers/scsi/bvme6000.h11
-rw-r--r--drivers/scsi/cyberstorm.c65
-rw-r--r--drivers/scsi/cyberstorm.h73
-rw-r--r--drivers/scsi/cyberstormII.c53
-rw-r--r--drivers/scsi/cyberstormII.h60
-rw-r--r--drivers/scsi/dec_esp.c26
-rw-r--r--drivers/scsi/dec_esp.h45
-rw-r--r--drivers/scsi/fastlane.c60
-rw-r--r--drivers/scsi/fastlane.h65
-rw-r--r--drivers/scsi/fcal.c10
-rw-r--r--drivers/scsi/gvp11.c17
-rw-r--r--drivers/scsi/gvp11.h16
-rw-r--r--drivers/scsi/jazz_esp.c19
-rw-r--r--drivers/scsi/jazz_esp.h39
-rw-r--r--drivers/scsi/mac_NCR5380.c105
-rw-r--r--drivers/scsi/mac_esp.c21
-rw-r--r--drivers/scsi/mac_esp.h40
-rw-r--r--drivers/scsi/mac_scsi.c14
-rw-r--r--drivers/scsi/mca_53c9x.c43
-rw-r--r--drivers/scsi/mca_53c9x.h66
-rw-r--r--drivers/scsi/mvme147.c17
-rw-r--r--drivers/scsi/mvme147.h18
-rw-r--r--drivers/scsi/mvme16x.c15
-rw-r--r--drivers/scsi/mvme16x.h11
-rw-r--r--drivers/scsi/oktagon_esp.c34
-rw-r--r--drivers/scsi/oktagon_esp.h57
-rw-r--r--drivers/scsi/pluto.c8
-rw-r--r--drivers/scsi/sun3_NCR5380.c88
-rw-r--r--drivers/scsi/sun3_scsi.c21
-rw-r--r--drivers/scsi/sun3_scsi.h16
-rw-r--r--drivers/scsi/sun3_scsi_vme.c21
-rw-r--r--drivers/scsi/sun3x_esp.c20
-rw-r--r--drivers/scsi/sun3x_esp.h39
-rw-r--r--drivers/scsi/wd33c93.c67
-rw-r--r--drivers/scsi/wd33c93.h1
-rw-r--r--drivers/serial/core.c8
-rw-r--r--drivers/usb/class/audio.c6
-rw-r--r--drivers/usb/class/bluetty.c6
-rw-r--r--drivers/usb/class/cdc-acm.c6
-rw-r--r--drivers/usb/class/usb-midi.c6
-rw-r--r--drivers/usb/class/usblp.c8
-rw-r--r--drivers/usb/core/buffer.c100
-rw-r--r--drivers/usb/core/config.c1
-rw-r--r--drivers/usb/core/devio.c4
-rw-r--r--drivers/usb/core/hcd-pci.c3
-rw-r--r--drivers/usb/core/hcd.c20
-rw-r--r--drivers/usb/core/hcd.h37
-rw-r--r--drivers/usb/core/hub.c10
-rw-r--r--drivers/usb/core/usb-debug.c2
-rw-r--r--drivers/usb/core/usb.c194
-rw-r--r--drivers/usb/host/ehci-hcd.c9
-rw-r--r--drivers/usb/host/hc_sl811_rh.c2
-rw-r--r--drivers/usb/host/ohci-hcd.c2
-rw-r--r--drivers/usb/host/ohci-sa1111.c3
-rw-r--r--drivers/usb/host/uhci-hcd.c2
-rw-r--r--drivers/usb/image/hpusbscsi.c6
-rw-r--r--drivers/usb/image/mdc800.c6
-rw-r--r--drivers/usb/image/microtek.c6
-rw-r--r--drivers/usb/image/scanner.c24
-rw-r--r--drivers/usb/input/aiptek.c6
-rw-r--r--drivers/usb/input/hid-core.c10
-rw-r--r--drivers/usb/input/hid-input.c5
-rw-r--r--drivers/usb/input/hid.h1
-rw-r--r--drivers/usb/input/pid.c5
-rw-r--r--drivers/usb/input/powermate.c6
-rw-r--r--drivers/usb/input/usbkbd.c6
-rw-r--r--drivers/usb/input/usbmouse.c6
-rw-r--r--drivers/usb/input/wacom.c6
-rw-r--r--drivers/usb/input/xpad.c6
-rw-r--r--drivers/usb/media/dabusb.c6
-rw-r--r--drivers/usb/media/dsbr100.c6
-rw-r--r--drivers/usb/media/ibmcam.c2
-rw-r--r--drivers/usb/media/konicawc.c2
-rw-r--r--drivers/usb/media/ov511.c38
-rw-r--r--drivers/usb/media/pwc-if.c6
-rw-r--r--drivers/usb/media/se401.c6
-rw-r--r--drivers/usb/media/stv680.c6
-rw-r--r--drivers/usb/media/ultracam.c35
-rw-r--r--drivers/usb/media/usbvideo.c12
-rw-r--r--drivers/usb/media/vicam.c6
-rw-r--r--drivers/usb/misc/auerswald.c6
-rw-r--r--drivers/usb/misc/brlvger.c6
-rw-r--r--drivers/usb/misc/rio500.c6
-rw-r--r--drivers/usb/misc/speedtouch.c6
-rw-r--r--drivers/usb/misc/tiglusb.c6
-rw-r--r--drivers/usb/misc/usblcd.c6
-rw-r--r--drivers/usb/misc/usbtest.c9
-rw-r--r--drivers/usb/misc/uss720.c6
-rw-r--r--drivers/usb/net/catc.c6
-rw-r--r--drivers/usb/net/cdc-ether.c4
-rw-r--r--drivers/usb/net/kaweth.c11
-rw-r--r--drivers/usb/net/pegasus.c6
-rw-r--r--drivers/usb/net/rtl8150.c6
-rw-r--r--drivers/usb/net/usbnet.c17
-rw-r--r--drivers/usb/serial/Kconfig4
-rw-r--r--drivers/usb/serial/belkin_sa.c18
-rw-r--r--drivers/usb/serial/bus.c12
-rw-r--r--drivers/usb/serial/cyberjack.c22
-rw-r--r--drivers/usb/serial/digi_acceleport.c75
-rw-r--r--drivers/usb/serial/empeg.c12
-rw-r--r--drivers/usb/serial/ezusb.c4
-rw-r--r--drivers/usb/serial/ftdi_sio.c29
-rw-r--r--drivers/usb/serial/generic.c6
-rw-r--r--drivers/usb/serial/io_edgeport.c88
-rw-r--r--drivers/usb/serial/io_ti.c108
-rw-r--r--drivers/usb/serial/ipaq.c56
-rw-r--r--drivers/usb/serial/ipaq.h53
-rw-r--r--drivers/usb/serial/ir-usb.c20
-rw-r--r--drivers/usb/serial/keyspan.c100
-rw-r--r--drivers/usb/serial/keyspan_pda.c20
-rw-r--r--drivers/usb/serial/kl5kusb105.c35
-rw-r--r--drivers/usb/serial/kobil_sct.c19
-rw-r--r--drivers/usb/serial/mct_u232.c28
-rw-r--r--drivers/usb/serial/omninet.c6
-rw-r--r--drivers/usb/serial/pl2303.c44
-rw-r--r--drivers/usb/serial/usb-serial.c48
-rw-r--r--drivers/usb/serial/usb-serial.h29
-rw-r--r--drivers/usb/serial/visor.c67
-rw-r--r--drivers/usb/serial/whiteheat.c54
-rw-r--r--drivers/usb/storage/usb.c6
-rw-r--r--drivers/usb/usb-skeleton.c8
-rw-r--r--drivers/video/Makefile3
-rw-r--r--drivers/video/atafb.c6
-rw-r--r--drivers/video/aty128fb.c2
-rw-r--r--drivers/video/cfbcopyarea.c2
-rw-r--r--drivers/video/cfbimgblt.c94
-rw-r--r--drivers/video/console/fbcon.c1
-rw-r--r--drivers/video/console/font.h16
-rw-r--r--drivers/video/tgafb.c1520
-rw-r--r--fs/block_dev.c11
-rw-r--r--fs/dquot.c3
-rw-r--r--fs/exec.c17
-rw-r--r--fs/jbd/journal.c4
-rw-r--r--fs/libfs.c9
-rw-r--r--fs/nls/nls_base.c3
-rw-r--r--fs/partitions/check.c3
-rw-r--r--fs/proc/array.c6
-rw-r--r--fs/proc/base.c10
-rw-r--r--fs/ramfs/inode.c7
-rw-r--r--fs/select.c2
-rw-r--r--include/asm-arm/arch-arc/io.h2
-rw-r--r--include/asm-arm/arch-cl7500/io.h2
-rw-r--r--include/asm-arm/arch-rpc/io.h2
-rw-r--r--include/asm-arm/memory.h4
-rw-r--r--include/asm-arm/setup.h2
-rw-r--r--include/asm-generic/pci-dma-compat.h22
-rw-r--r--include/asm-i386/bugs.h5
-rw-r--r--include/asm-i386/cpufeature.h1
-rw-r--r--include/asm-i386/desc.h1
-rw-r--r--include/asm-i386/hw_irq.h2
-rw-r--r--include/asm-i386/mach-default/mach_apic.h3
-rw-r--r--include/asm-i386/mach-numaq/mach_apic.h3
-rw-r--r--include/asm-i386/mach-numaq/mach_mpparse.h3
-rw-r--r--include/asm-i386/mach-summit/mach_apic.h3
-rw-r--r--include/asm-i386/processor.h37
-rw-r--r--include/asm-i386/segment.h8
-rw-r--r--include/asm-i386/smp.h21
-rw-r--r--include/asm-i386/system.h6
-rw-r--r--include/asm-i386/uaccess.h2
-rw-r--r--include/asm-i386/voyager.h1
-rw-r--r--include/asm-m68k/ide.h18
-rw-r--r--include/asm-m68k/macintosh.h7
-rw-r--r--include/asm-m68k/mman.h2
-rw-r--r--include/asm-m68k/module.h13
-rw-r--r--include/asm-m68k/sbus.h2
-rw-r--r--include/asm-m68k/system.h2
-rw-r--r--include/asm-m68k/thread_info.h4
-rw-r--r--include/asm-um/a.out.h8
-rw-r--r--include/asm-um/checksum.h2
-rw-r--r--include/asm-um/mmu.h18
-rw-r--r--include/asm-um/mmu_context.h51
-rw-r--r--include/asm-um/page.h2
-rw-r--r--include/asm-um/pgtable.h6
-rw-r--r--include/asm-um/processor-generic.h39
-rw-r--r--include/asm-um/ptrace-generic.h2
-rw-r--r--include/asm-um/system-generic.h1
-rw-r--r--include/asm-um/thread_info.h10
-rw-r--r--include/asm-um/uaccess.h100
-rw-r--r--include/asm-x86_64/bitops.h2
-rw-r--r--include/asm-x86_64/desc.h2
-rw-r--r--include/asm-x86_64/dma-mapping.h1
-rw-r--r--include/asm-x86_64/hw_irq.h15
-rw-r--r--include/asm-x86_64/ia32.h2
-rw-r--r--include/asm-x86_64/io_apic.h1
-rw-r--r--include/asm-x86_64/processor.h2
-rw-r--r--include/asm-x86_64/proto.h2
-rw-r--r--include/asm-x86_64/spinlock.h2
-rw-r--r--include/asm-x86_64/system.h7
-rw-r--r--include/asm-x86_64/thread_info.h2
-rw-r--r--include/asm-x86_64/uaccess.h106
-rw-r--r--include/linux/ax25.h2
-rw-r--r--include/linux/binfmts.h8
-rw-r--r--include/linux/compiler.h13
-rw-r--r--include/linux/fb.h2
-rw-r--r--include/linux/fs.h5
-rw-r--r--include/linux/i2c-id.h1
-rw-r--r--include/linux/i2c-proc.h25
-rw-r--r--include/linux/ide.h4
-rw-r--r--include/linux/init.h5
-rw-r--r--include/linux/ioport.h3
-rw-r--r--include/linux/module.h68
-rw-r--r--include/linux/moduleparam.h2
-rw-r--r--include/linux/mtd/map.h5
-rw-r--r--include/linux/mtd/mtd.h3
-rw-r--r--include/linux/nubus.h51
-rw-r--r--include/linux/personality.h18
-rw-r--r--include/linux/sensors.h690
-rw-r--r--include/linux/usb.h31
-rw-r--r--include/video/font.h24
-rw-r--r--include/video/tgafb.h (renamed from drivers/video/tgafb.h)149
-rw-r--r--kernel/exec_domain.c7
-rw-r--r--kernel/exit.c6
-rw-r--r--kernel/fork.c14
-rw-r--r--kernel/intermodule.c2
-rw-r--r--kernel/ksyms.c1
-rw-r--r--kernel/module.c112
-rw-r--r--kernel/printk.c2
-rw-r--r--kernel/resource.c2
-rw-r--r--net/ax25/af_ax25.c2
-rw-r--r--net/core/dev.c9
-rw-r--r--net/ipv4/xfrm_policy.c3
-rw-r--r--net/rxrpc/call.c2
-rw-r--r--scripts/ver_linux2
-rw-r--r--sound/core/control.c10
-rw-r--r--sound/core/info.c10
-rw-r--r--sound/core/oss/mixer_oss.c8
-rw-r--r--sound/core/oss/pcm_oss.c10
-rw-r--r--sound/core/pcm_native.c12
-rw-r--r--sound/core/rawmidi.c10
-rw-r--r--sound/core/seq/oss/seq_oss_synth.c10
-rw-r--r--sound/core/seq/seq_ports.c10
-rw-r--r--sound/core/seq/seq_virmidi.c10
-rw-r--r--sound/core/timer.c8
-rw-r--r--sound/drivers/opl3/opl3_seq.c8
-rw-r--r--sound/isa/gus/gus_main.c8
-rw-r--r--sound/isa/wavefront/wavefront_fx.c9
-rw-r--r--sound/isa/wavefront/wavefront_synth.c9
-rw-r--r--sound/oss/audio.c26
-rw-r--r--sound/oss/midibuf.c6
-rw-r--r--sound/oss/mpu401.c18
-rw-r--r--sound/oss/sequencer.c22
-rw-r--r--sound/oss/soundcard.c10
-rw-r--r--sound/synth/emux/emux_seq.c12
-rw-r--r--sound/usb/usbaudio.c4
632 files changed, 20079 insertions, 8136 deletions
diff --git a/Documentation/Changes b/Documentation/Changes
index a57fca2015c2..8df1075acfe8 100644
--- a/Documentation/Changes
+++ b/Documentation/Changes
@@ -52,7 +52,7 @@ o Gnu C 2.95.3 # gcc --version
o Gnu make 3.78 # make --version
o binutils 2.9.5.0.25 # ld -v
o util-linux 2.10o # fdformat --version
-o modutils 2.4.2 # insmod -V
+o module-init-tools 0.9 # rmmod -V
o e2fsprogs 1.29 # tune2fs
o jfsutils 1.0.14 # fsck.jfs -V
o reiserfsprogs 3.6.3 # reiserfsck -V 2>&1|grep reiserfsprogs
@@ -141,14 +141,11 @@ If the unthinkable happens and your kernel oopses, you'll need a 2.4
version of ksymoops to decode the report; see REPORTING-BUGS in the
root of the Linux source for more information.
-Modutils
+Module-Init-Tools
--------
-Upgrade to recent modutils to fix various outstanding bugs which are
-seen more frequently under 2.4.x, and to enable auto-loading of USB
-modules. In addition, the layout of modules under
-/lib/modules/`uname -r`/ has been made more sane. This change also
-requires that you upgrade to a recent modutils.
+A new module loader is now in the kernel that requires module-init-tools
+to use. It is backward compatible with the 2.4.x series kernels.
Mkinitrd
--------
@@ -306,7 +303,7 @@ o <ftp://ftp.kernel.org/pub/linux/utils/kernel/ksymoops/v2.4/>
Modutils
--------
-o <ftp://ftp.kernel.org/pub/linux/utils/kernel/modutils/v2.4/>
+o <ftp://ftp.kernel.org/pub/linux/kernel/people/rusty/modules/>
Mkinitrd
--------
diff --git a/Documentation/kbuild/makefiles.txt b/Documentation/kbuild/makefiles.txt
index 12b0086b75ea..b3c00ed92451 100644
--- a/Documentation/kbuild/makefiles.txt
+++ b/Documentation/kbuild/makefiles.txt
@@ -213,7 +213,7 @@ The top Makefile exports the following variables:
$(GENKSYMS) contains the command used to generate kernel symbol
signatures when CONFIG_MODVERSIONS is enabled. The genksyms
- command comes from the modutils package.
+ command comes from the module-init-tools package.
CROSS_COMPILE
diff --git a/Documentation/modules.txt b/Documentation/modules.txt
index 833a05804052..e30516d41121 100644
--- a/Documentation/modules.txt
+++ b/Documentation/modules.txt
@@ -3,12 +3,11 @@ in the Linux kernel. This is not a technical description on
the internals of module, but mostly a sample of how to compile
and use modules.
-Note: You should ensure that the modutils-X.Y.Z.tar.gz you are using
-is the most up to date one for this kernel. The "X.Y.Z" will reflect
-the kernel version at the time of the release of the modules package.
-Some older modules packages aren't aware of some of the newer modular
-features that the kernel now supports. The current required version
-is listed in the file linux/Documentation/Changes.
+Note: You should ensure that the module-init-tools-X.Y.Z.tar.gz you
+are using is the most up to date one for this kernel. Some older
+modules packages aren't aware of some of the newer modular features
+that the kernel now supports. The current required version is listed
+in the file linux/Documentation/Changes.
* * * NOTE * * *
The kernel has been changed to remove kerneld support and use
@@ -124,7 +123,8 @@ And, yes, there _are_ man-pages for all this...
To use modprobe successfully, you generally place the following
command in your /etc/rc.d/rc.S script. (Read more about this in the
-"rc.hints" file in the module utilities package, "modutils-x.y.z.tar.gz".)
+"rc.hints" file in the module utilities package,
+"module-init-tools-x.y.z.tar.gz".)
/sbin/depmod -a
diff --git a/Documentation/networking/z8530drv.txt b/Documentation/networking/z8530drv.txt
index 60f453d18f89..2206abbc3e1b 100644
--- a/Documentation/networking/z8530drv.txt
+++ b/Documentation/networking/z8530drv.txt
@@ -54,7 +54,7 @@ Before you can use a module, you'll have to load it with
insmod scc.o
-please read 'man insmod' that comes with modutils.
+please read 'man insmod' that comes with module-init-tools.
You should include the insmod in one of the /etc/rc.d/rc.* files,
and don't forget to insert a call of sccinit after that. It
diff --git a/Documentation/sound/oss/Introduction b/Documentation/sound/oss/Introduction
index 0b7fdc9593a4..90b41f8c3b4c 100644
--- a/Documentation/sound/oss/Introduction
+++ b/Documentation/sound/oss/Introduction
@@ -119,9 +119,9 @@ the README takes precedence.
6. Make the modules and install them (make modules; make modules_install).
-Note, for 2.4.x kernels, make sure you have the newer modutils
-loaded or modules will not be loaded properly. 2.4.x changed the
-layout of /lib/modules/2.4.x and requires an updated modutils.
+Note, for 2.5.x kernels, make sure you have the newer module-init-tools
+installed or modules will not be loaded properly. 2.5.x requires an
+updated module-init-tools.
Plug and Play (PnP:
diff --git a/Documentation/sysctl/kernel.txt b/Documentation/sysctl/kernel.txt
index ac873ad4ce6e..424ccd9f7c45 100644
--- a/Documentation/sysctl/kernel.txt
+++ b/Documentation/sysctl/kernel.txt
@@ -286,9 +286,9 @@ can be ORed together:
1 - A module with a non-GPL license has been loaded, this
includes modules with no license.
- Set by modutils >= 2.4.9.
+ Set by modutils >= 2.4.9 and module-init-tools.
2 - A module was force loaded by insmod -f.
- Set by modutils >= 2.4.9.
+ Set by modutils >= 2.4.9 and module-init-tools.
4 - Unsafe SMP processors: SMP with CPUs not designed for SMP.
==============================================================
diff --git a/Documentation/sysrq.txt b/Documentation/sysrq.txt
index 2ce147d262ab..8abc2cee103c 100644
--- a/Documentation/sysrq.txt
+++ b/Documentation/sysrq.txt
@@ -59,6 +59,8 @@ On other - If you know of the key combos for other architectures, please
'm' - Will dump current memory info to your console.
+'v' - Dumps Voyager SMP processor info to your console.
+
'0'-'9' - Sets the console log level, controlling which kernel messages
will be printed to your console. ('0', for example would make
it so that only emergency messages like PANICs or OOPSes would
diff --git a/Documentation/uml/UserModeLinux-HOWTO.txt b/Documentation/uml/UserModeLinux-HOWTO.txt
new file mode 100644
index 000000000000..2950ab0012bf
--- /dev/null
+++ b/Documentation/uml/UserModeLinux-HOWTO.txt
@@ -0,0 +1,4686 @@
+ User Mode Linux HOWTO
+ User Mode Linux Core Team
+ Mon Nov 18 14:16:16 EST 2002
+
+ This document describes the use and abuse of Jeff Dike's User Mode
+ Linux: a port of the Linux kernel as a normal Intel Linux process.
+ ______________________________________________________________________
+
+ Table of Contents
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1. Introduction
+
+ 1.1 How is User Mode Linux Different?
+ 1.2 Why Would I Want User Mode Linux?
+
+ 2. Compiling the kernel and modules
+
+ 2.1 Compiling the kernel
+ 2.2 Compiling and installing kernel modules
+ 2.3 Compiling and installing uml_utilities
+
+ 3. Running UML and logging in
+
+ 3.1 Running UML
+ 3.2 Logging in
+ 3.3 Examples
+
+ 4. UML on 2G/2G hosts
+
+ 4.1 Introduction
+ 4.2 The problem
+ 4.3 The solution
+
+ 5. Setting up serial lines and consoles
+
+ 5.1 Specifying the device
+ 5.2 Specifying the channel
+ 5.3 Examples
+
+ 6. Setting up the network
+
+ 6.1 General setup
+ 6.2 Userspace daemons
+ 6.3 Specifying ethernet addresses
+ 6.4 UML interface setup
+ 6.5 Multicast
+ 6.6 TUN/TAP with the uml_net helper
+ 6.7 TUN/TAP with a preconfigured tap device
+ 6.8 Ethertap
+ 6.9 The switch daemon
+ 6.10 Slip
+ 6.11 Slirp
+ 6.12 pcap
+ 6.13 Setting up the host yourself
+
+ 7. Sharing Filesystems between Virtual Machines
+
+ 7.1 A warning
+ 7.2 Using layered block devices
+ 7.3 Note!
+ 7.4 Another warning
+ 7.5 uml_moo : Merging a COW file with its backing file
+
+ 8. Creating filesystems
+
+ 8.1 Create the filesystem file
+ 8.2 Assign the file to a UML device
+ 8.3 Creating and mounting the filesystem
+
+ 9. Host file access
+
+ 9.1 Using hostfs
+ 9.2 hostfs as the root filesystem
+ 9.3 Building hostfs
+
+ 10. The Management Console
+ 10.1 version
+ 10.2 halt and reboot
+ 10.3 config
+ 10.4 remove
+ 10.5 sysrq
+ 10.6 help
+ 10.7 cad
+ 10.8 stop
+ 10.9 go
+
+ 11. Kernel debugging
+
+ 11.1 Starting the kernel under gdb
+ 11.2 Examining sleeping processes
+ 11.3 Running ddd on UML
+ 11.4 Debugging modules
+ 11.5 Attaching gdb to the kernel
+ 11.6 Using alternate debuggers
+
+ 12. Kernel debugging examples
+
+ 12.1 The case of the hung fsck
+ 12.2 Episode 2: The case of the hung fsck
+
+ 13. What to do when UML doesn't work
+
+ 13.1 Strange compilation errors when you build from source
+ 13.2 UML hangs on boot after mounting devfs
+ 13.3 A variety of panics and hangs with /tmp on a reiserfs filesystem
+ 13.4 The compile fails with errors about conflicting types for 'open', 'dup', and 'waitpid'
+ 13.5 UML doesn't work when /tmp is an NFS filesystem
+ 13.6 UML hangs on boot when compiled with gprof support
+ 13.7 syslogd dies with a SIGTERM on startup
+ 13.8 TUN/TAP networking doesn't work on a 2.4 host
+ 13.9 You can network to the host but not to other machines on the net
+ 13.10 I have no root and I want to scream
+ 13.11 UML build conflict between ptrace.h and ucontext.h
+ 13.12 The UML BogoMips is exactly half the host's BogoMips
+ 13.13 When you run UML, it immediately segfaults
+ 13.14 xterms appear, then immediately disappear
+ 13.15 Any other panic, hang, or strange behavior
+
+ 14. Diagnosing Problems
+
+ 14.1 Case 1 : Normal kernel panics
+ 14.2 Case 2 : Tracing thread panics
+ 14.3 Case 3 : Tracing thread panics caused by other threads
+ 14.4 Case 4 : Hangs
+
+ 15. Thanks
+
+ 15.1 Code and Documentation
+ 15.2 Flushing out bugs
+ 15.3 Buglets and clean-ups
+ 15.4 Case Studies
+ 15.5 Other contributions
+
+
+ ______________________________________________________________________
+
+ 11.. IInnttrroodduuccttiioonn
+
+ Welcome to User Mode Linux. It's going to be fun.
+
+
+
+ 11..11.. HHooww iiss UUsseerr MMooddee LLiinnuuxx DDiiffffeerreenntt??
+
+ Normally, the Linux Kernel talks straight to your hardware (video
+ card, keyboard, hard drives, etc), and any programs which run ask the
+ kernel to operate the hardware, like so:
+
+
+
+ +-----------+-----------+----+
+ | Process 1 | Process 2 | ...|
+ +-----------+-----------+----+
+ | Linux Kernel |
+ +----------------------------+
+ | Hardware |
+ +----------------------------+
+
+
+
+
+ The User Mode Linux Kernel is different; instead of talking to the
+ hardware, it talks to a `real' Linux kernel (called the `host kernel'
+ from now on), like any other program. Programs can then run inside
+ User-Mode Linux as if they were running under a normal kernel, like
+ so:
+
+
+
+ +----------------+
+ | Process 2 | ...|
+ +-----------+----------------+
+ | Process 1 | User-Mode Linux|
+ +----------------------------+
+ | Linux Kernel |
+ +----------------------------+
+ | Hardware |
+ +----------------------------+
+
+
+
+
+
+ 11..22.. WWhhyy WWoouulldd II WWaanntt UUsseerr MMooddee LLiinnuuxx??
+
+
+ 1. If User Mode Linux crashes, your host kernel is still fine.
+
+ 2. You can run a usermode kernel as a non-root user.
+
+ 3. You can debug the User Mode Linux like any normal process.
+
+ 4. You can run gprof (profiling) and gcov (coverage testing).
+
+ 5. You can play with your kernel without breaking things.
+
+ 6. You can use it as a sandbox for testing new apps.
+
+ 7. You can try new development kernels safely.
+
+ 8. You can run different distributions simultaneously.
+
+ 9. It's extremely fun.
+
+
+
+
+
+ 22.. CCoommppiilliinngg tthhee kkeerrnneell aanndd mmoodduulleess
+
+
+
+
+ 22..11.. CCoommppiilliinngg tthhee kkeerrnneell
+
+
+ Compiling the user mode kernel is just like compiling any other
+ kernel. Let's go through the steps, using 2.4.0-prerelease (current
+ as of this writing) as an example:
+
+
+ 1. Download the latest UML patch from
+
+ the download page <http://user-mode-linux.sourceforge.net/dl-
+ sf.html>
+
+ In this example, the file is uml-patch-2.4.0-prerelease.bz2.
+
+
+ 2. Download the matching kernel from your favourite kernel mirror,
+ such as:
+
+ ftp://ftp.ca.kernel.org/pub/kernel/v2.4/linux-2.4.0-prerelease.tar.bz2
+ <ftp://ftp.ca.kernel.org/pub/kernel/v2.4/linux-2.4.0-prerelease.tar.bz2>
+ .
+
+
+ 3. Make a directory and unpack the kernel into it.
+
+
+
+ host%
+ mkdir ~/uml
+
+
+
+
+
+
+ host%
+ cd ~/uml
+
+
+
+
+
+
+ host%
+ tar -xzvf linux-2.4.0-prerelease.tar.bz2
+
+
+
+
+
+
+ 4. Apply the patch using
+
+
+
+ host%
+ cd ~/uml/linux
+
+
+
+ host%
+ bzcat uml-patch-2.4.0-prerelease.bz2 | patch -p1
+
+
+
+
+
+
+ 5. Run your favorite config; `make xconfig ARCH=um' is the most
+ convenient. `make config ARCH=um' and 'make menuconfig ARCH=um'
+ will work as well. The defaults will give you a useful kernel. If
+ you want to change something, go ahead, it probably won't hurt
+ anything.
+
+
+ Note: If the host is configured with a 2G/2G address space split
+ rather than the usual 3G/1G split, then the packaged UML binaries
+ will not run. They will immediately segfault. See ``UML on 2G/2G
+ hosts'' for the scoop on running UML on your system.
+
+
+
+ 6. Finish with `make linux ARCH=um': the result is a file called
+ `linux' in the top directory of your source tree.
+
+ Make sure that you don't build this kernel in /usr/src/linux. On some
+ distributions, /usr/include/asm is a link into this pool. The user-
+ mode build changes the other end of that link, and things that include
+ <asm/anything.h> stop compiling.
+
+ The sources are also available from cvs at the project's cvs page,
+ which has directions on getting the sources. You can also browse the
+ CVS pool from there.
+
+ If you get the CVS sources, you will have to check them out into an
+ empty directory. You will then have to copy each file into the
+ corresponding directory in the appropriate kernel pool.
+
+ If you don't have the latest kernel pool, you can get the
+ corresponding user-mode sources with
+
+
+ host% cvs co -r v_2_3_x linux
+
+
+
+
+ where 'x' is the version in your pool. Note that you will not get the
+ bug fixes and enhancements that have gone into subsequent releases.
+
+
+ If you build your own kernel, and want to boot it from one of the
+ filesystems distributed from this site, then, in nearly all cases,
+ devfs must be compiled into the kernel and mounted at boot time. The
+ exception is the SuSE filesystem. For this, devfs must either not be
+ in the kernel at all, or "devfs=nomount" must be on the kernel command
+ line. Any disagreement between the kernel and the filesystem being
+ booted about whether devfs is being used will result in the boot
+ getting no further than single-user mode.
+
+
+ If you don't want to use devfs, you can remove the need for it from a
+ filesystem by copying /dev from someplace, making a bunch of /dev/ubd
+ devices:
+
+
+ UML# for i in 0 1 2 3 4 5 6 7; do mknod ubd$i b 98 $i; done
+
+
+
+
+ and changing /etc/fstab and /etc/inittab to refer to the non-devfs
+ devices.
+
+
+
+ 22..22.. CCoommppiilliinngg aanndd iinnssttaalllliinngg kkeerrnneell mmoodduulleess
+
+ UML modules are built in the same way as the native kernel (with the
+ exception of the 'ARCH=um' that you always need for UML):
+
+
+ host% make modules ARCH=um
+
+
+
+
+ Any modules that you want to load into this kernel need to be built in
+ the user-mode pool. Modules from the native kernel won't work.
+
+ You can install them by using ftp or something to copy them into the
+ virtual machine and dropping them into /lib/modules/`uname -r`.
+
+ You can also get the kernel build process to install them as follows:
+
+ 1. with the kernel not booted, mount the root filesystem in the top
+ level of the kernel pool:
+
+
+ host% mount root_fs mnt -o loop
+
+
+
+
+
+
+ 2. run
+
+
+ host%
+ make modules_install INSTALL_MOD_PATH=`pwd`/mnt ARCH=um
+
+
+
+
+
+
+ 3. unmount the filesystem
+
+
+ host% umount mnt
+
+
+
+
+
+
+ 4. boot the kernel on it
+
+
+ When the system is booted, you can use insmod as usual to get the
+ modules into the kernel. A number of things have been loaded into UML
+ as modules, especially filesystems and network protocols and filters,
+ so most symbols which need to be exported probably already are.
+ However, if you do find symbols that need exporting, let us
+ <http://user-mode-linux.sourceforge.net/contacts.html> know, and
+ they'll be "taken care of".
+
+
+
+ 22..33.. CCoommppiilliinngg aanndd iinnssttaalllliinngg uummll__uuttiilliittiieess
+
+ Many features of the UML kernel require a user-space helper program,
+ so a uml_utilities package is distributed separately from the kernel
+ patch which provides these helpers. Included within this is:
+
+ +o port-helper - Used by consoles which connect to xterms or ports
+
+ +o tunctl - Configuration tool to create and delete tap devices
+
+ +o uml_net - Setuid binary for automatic tap device configuration
+
+ +o uml_switch - User-space virtual switch required for daemon
+ transport
+
+ The uml_utilities tree is compiled with:
+
+
+ host#
+ make && make install
+
+
+
+
+ Note that UML kernel patches may require a specific version of the
+ uml_utilities distribution. If you don't keep up with the mailing
+ lists, ensure that you have the latest release of uml_utilities if you
+ are experiencing problems with your UML kernel, particularly when
+ dealing with consoles or command-line switches to the helper programs
+
+
+
+
+
+
+
+
+ 33.. RRuunnnniinngg UUMMLL aanndd llooggggiinngg iinn
+
+
+
+ 33..11.. RRuunnnniinngg UUMMLL
+
+ It runs on 2.2.15 or later, and all 2.4 kernels.
+
+
+ Booting UML is straightforward. Simply run 'linux': it will try to
+ mount the file `root_fs' in the current directory. You do not need to
+ run it as root. If your root filesystem is not named `root_fs', then
+ you need to put a `ubd0=root_fs_whatever' switch on the linux command
+ line.
+
+
+ You will need a filesystem to boot UML from. There are a number
+ available for download from here <http://user-mode-
+ linux.sourceforge.net/dl-sf.html> . There are also several tools
+ <http://user-mode-linux.sourceforge.net/fs_making.html> which can be
+ used to generate UML-compatible filesystem images from media.
+ The kernel will boot up and present you with a login prompt.
+
+
+ Note: If the host is configured with a 2G/2G address space split
+ rather than the usual 3G/1G split, then the packaged UML binaries will
+ not run. They will immediately segfault. See ``UML on 2G/2G hosts''
+ for the scoop on running UML on your system.
+
+
+
+ 33..22.. LLooggggiinngg iinn
+
+
+
+ The prepackaged filesystems have a root account with password 'root'
+ and a user account with password 'user'. The login banner will
+ generally tell you how to log in. So, you log in and you will find
+ yourself inside a little virtual machine. Our filesystems have a
+ variety of commands and utilities installed (and it is fairly easy to
+ add more), so you will have a lot of tools with which to poke around
+ the system.
+
+ There are a couple of other ways to log in:
+
+ +o On a virtual console
+
+
+
+ Each virtual console that is configured (i.e. the device exists in
+ /dev and /etc/inittab runs a getty on it) will come up in its own
+ xterm. If you get tired of the xterms, read ``Setting up serial
+ lines and consoles'' to see how to attach the consoles to
+ something else, like host ptys.
+
+
+
+ +o Over the serial line
+
+
+ In the boot output, find a line that looks like:
+
+
+
+ serial line 0 assigned pty /dev/ptyp1
+
+
+
+
+ Attach your favorite terminal program to the corresponding tty. I.e.
+ for minicom, the command would be
+
+
+ host% minicom -o -p /dev/ttyp1
+
+
+
+
+
+
+ +o Over the net
+
+
+ If the network is running, then you can telnet to the virtual
+ machine and log in to it. See ``Setting up the network'' to learn
+ about setting up a virtual network.
+
+ When you're done using it, run halt, and the kernel will bring itself
+ down and the process will exit.
+
+
+ 33..33.. EExxaammpplleess
+
+ Here are some examples of UML in action:
+
+ +o A login session <http://user-mode-linux.sourceforge.net/login.html>
+
+ +o A virtual network <http://user-mode-linux.sourceforge.net/net.html>
+
+
+
+
+
+
+
+ 44.. UUMMLL oonn 22GG//22GG hhoossttss
+
+
+
+
+ 44..11.. IInnttrroodduuccttiioonn
+
+
+ Most Linux machines are configured so that the kernel occupies the
+ upper 1G (0xc0000000 - 0xffffffff) of the 4G address space and
+ processes use the lower 3G (0x00000000 - 0xbfffffff). However, some
+ machine are configured with a 2G/2G split, with the kernel occupying
+ the upper 2G (0x80000000 - 0xffffffff) and processes using the lower
+ 2G (0x00000000 - 0x7fffffff).
+
+
+
+
+ 44..22.. TThhee pprroobblleemm
+
+
+ The prebuilt UML binaries on this site will not run on 2G/2G hosts
+ because UML occupies the upper .5G of the 3G process address space
+ (0xa0000000 - 0xbfffffff). Obviously, on 2G/2G hosts, this is right
+ in the middle of the kernel address space, so UML won't even load - it
+ will immediately segfault.
+
+
+
+
+ 44..33.. TThhee ssoolluuttiioonn
+
+
+ The fix for this is to rebuild UML from source after enabling
+ CONFIG_HOST_2G_2G (under 'General Setup'). This will cause UML to
+ load itself in the top .5G of that smaller process address space,
+ where it will run fine. See ``Compiling the kernel and modules'' if
+ you need help building UML from source.
+
+
+
+
+
+
+
+
+
+
+ 55.. SSeettttiinngg uupp sseerriiaall lliinneess aanndd ccoonnssoolleess
+
+
+ It is possible to attach UML serial lines and consoles to many types
+ of host I/O channels by specifying them on the command line.
+
+
+ You can attach them to host ptys, ttys, file descriptors, and ports.
+ This allows you to do things like
+
+ +o have a UML console appear on an unused host console,
+
+ +o hook two virtual machines together by having one attach to a pty
+ and having the other attach to the corresponding tty
+
+ +o make a virtual machine accessible from the net by attaching a
+ console to a port on the host.
+
+
+ The general format of the command line option is device=channel.
+
+
+
+ 55..11.. SSppeecciiffyyiinngg tthhee ddeevviiccee
+
+ Devices are specified with "con" or "ssl" (console or serial line,
+ respectively), optionally with a device number if you are talking
+ about a specific device.
+
+
+ Using just "con" or "ssl" describes all of the consoles or serial
+ lines. If you want to talk about console #3 or serial line #10, they
+ would be "con3" and "ssl10", respectively.
+
+
+ A specific device name will override a less general "con=" or "ssl=".
+ So, for example, you can assign a pty to each of the serial lines
+ except for the first two like this:
+
+
+ ssl=pty ssl0=tty:/dev/tty0 ssl1=tty:/dev/tty1
+
+
+
+
+ The specificity of the device name is all that matters; order on the
+ command line is irrelevant.
+
+
+
+ 55..22.. SSppeecciiffyyiinngg tthhee cchhaannnneell
+
+ There are a number of different types of channels to attach a UML
+ device to, each with a different way of specifying exactly what to
+ attach to.
+
+ +o pseudo-terminals - device=pty pts terminals - device=pts
+
+
+ This will cause UML to allocate a free host pseudo-terminal for the
+ device. The terminal that it got will be announced in the boot
+ log. You access it by attaching a terminal program to the
+ corresponding tty:
+
+ +o screen /dev/pts/n
+
+ +o screen /dev/ttyxx
+
+ +o minicom -o -p /dev/ttyxx - minicom seems not able to handle pts
+ devices
+
+ +o kermit - start it up, 'open' the device, then 'connect'
+
+
+
+
+
+ +o terminals - device=tty:tty device file
+
+
+ This will make UML attach the device to the specified tty (i.e
+
+
+ con1=tty:/dev/tty3
+
+
+
+
+ will attach UML's console 1 to the host's /dev/tty3). If the tty that
+ you specify is the slave end of a tty/pty pair, something else must
+ have already opened the corresponding pty in order for this to work.
+
+
+
+
+
+ +o xterms - device=xterm
+
+
+ UML will run an xterm and the device will be attached to it.
+
+
+
+
+
+ +o Port - device=port:port number
+
+
+ This will attach the UML devices to the specified host port.
+ Attaching console 1 to the host's port 9000 would be done like
+ this:
+
+
+ con1=port:9000
+
+
+
+
+ Attaching all the serial lines to that port would be done similarly:
+
+
+ ssl=port:9000
+
+
+
+
+ You access these devices by telnetting to that port. Each active tel-
+ net session gets a different device. If there are more telnets to a
+ port than UML devices attached to it, then the extra telnet sessions
+ will block until an existing telnet detaches, or until another device
+ becomes active (i.e. by being activated in /etc/inittab).
+
+ This channel has the advantage that you can both attach multiple UML
+ devices to it and know how to access them without reading the UML boot
+ log. It is also unique in allowing access to a UML from remote
+ machines without requiring that the UML be networked. This could be
+ useful in allowing public access to UMLs because they would be
+ accessible from the net, but wouldn't need any kind of network
+ filtering or access control because they would have no network access.
+
+
+ If you attach the main console to a portal, then the UML boot will
+ appear to hang. In reality, it's waiting for a telnet to connect, at
+ which point the boot will proceed.
+
+
+
+
+
+ +o already-existing file descriptors - device=file descriptor
+
+
+ If you set up a file descriptor on the UML command line, you can
+ attach a UML device to it. This is most commonly used to put the
+ main console back on stdin and stdout after assigning all the other
+ consoles to something else:
+
+
+ con0=fd:0,fd:1 con=pts
+
+
+
+
+
+
+
+
+ +o Nothing - device=null
+
+
+ This allows the device to be opened, in contrast to 'none', but
+ reads will block, and writes will succeed and the data will be
+ thrown out.
+
+
+
+
+
+ +o None - device=none
+
+
+ This causes the device to disappear. If you are using devfs, the
+ device will not appear in /dev. If not, then attempts to open it
+ will return -ENODEV.
+
+
+
+ You can also specify different input and output channels for a device
+ by putting a comma between them:
+
+
+ ssl3=tty:/dev/tty2,xterm
+
+
+
+
+ will cause serial line 3 to accept input on the host's /dev/tty3 and
+ display output on an xterm. That's a silly example - the most common
+ use of this syntax is to reattach the main console to stdin and stdout
+ as shown above.
+
+
+ If you decide to move the main console away from stdin/stdout, the
+ initial boot output will appear in the terminal that you're running
+ UML in. However, once the console driver has been officially
+ initialized, then the boot output will start appearing wherever you
+ specified that console 0 should be. That device will receive all
+ subsequent output.
+
+
+
+ 55..33.. EExxaammpplleess
+
+ There are a number of interesting things you can do with this
+ capability.
+
+
+ First, this is how you get rid of those bleeding console xterms by
+ attaching them to host ptys:
+
+
+ con=pty con0=fd:0,fd:1
+
+
+
+
+ This will make a UML console take over an unused host virtual console,
+ so that when you switch to it, you will see the UML login prompt
+ rather than the host login prompt:
+
+
+ con1=tty:/dev/tty6
+
+
+
+
+ You can attach two virtual machines together with what amounts to a
+ serial line as follows:
+
+ Run one UML with a serial line attached to a pty -
+
+
+ ssl1=pty
+
+
+
+
+ Look at the boot log to see what pty it got (this example will assume
+ that it got /dev/ptyp1).
+
+ Boot the other UML with a serial line attached to the corresponding
+ tty -
+
+
+ ssl1=tty:/dev/ttyp1
+
+
+
+
+ Log in, make sure that it has no getty on that serial line, attach a
+ terminal program like minicom to it, and you should see the login
+ prompt of the other virtual machine.
+
+
+ 66.. SSeettttiinngg uupp tthhee nneettwwoorrkk
+
+
+
+ This page describes how to set up the various transports and to
+ provide a UML instance with network access to the host, other machines
+ on the local net, and the rest of the net.
+
+
+ As of 2.4.5, UML networking has been completely redone to make it much
+ easier to set up, fix bugs, and add new features.
+
+
+ There is a new helper, uml_net, which does the host setup that
+ requires root privileges.
+
+
+ There are currently five transport types available for a UML virtual
+ machine to exchange packets with other hosts:
+
+ +o ethertap
+
+ +o TUN/TAP
+
+ +o Multicast
+
+ +o a switch daemon
+
+ +o slip
+
+ +o slirp
+
+ +o pcap
+
+ The TUN/TAP, ethertap, slip, and slirp transports allow a UML
+ instance to exchange packets with the host. They may be directed
+ to the host or the host may just act as a router to provide access
+ to other physical or virtual machines.
+
+
+ The pcap transport is a synthetic read-only interface, using the
+ libpcap binary to collect packets from interfaces on the host and
+ filter them. This is useful for building preconfigured traffic
+ monitors or sniffers.
+
+
+ The daemon and multicast transports provide a completely virtual
+ network to other virtual machines. This network is completely
+ disconnected from the physical network unless one of the virtual
+ machines on it is acting as a gateway.
+
+
+ With so many host transports, which one should you use? Here's when
+ you should use each one:
+
+ +o ethertap - if you want access to the host networking and it is
+ running 2.2
+
+ +o TUN/TAP - if you want access to the host networking and it is
+ running 2.4. Also, the TUN/TAP transport is able to use a
+ preconfigured device, allowing it to avoid using the setuid uml_net
+ helper, which is a security advantage.
+
+ +o Multicast - if you want a purely virtual network and you don't want
+ to set up anything but the UML
+
+ +o a switch daemon - if you want a purely virtual network and you
+ don't mind running the daemon in order to get somewhat better
+ performance
+
+ +o slip - there is no particular reason to run the slip backend unless
+ ethertap and TUN/TAP are just not available for some reason
+
+ +o slirp - if you don't have root access on the host to setup
+ networking, or if you don't want to allocate an IP to your UML
+
+ +o pcap - not much use for actual network connectivity, but great for
+ monitoring traffic on the host
+
+ Ethertap is available on 2.4 and works fine. TUN/TAP is preferred
+ to it because it has better performance and ethertap is officially
+ considered obsolete in 2.4. Also, the root helper only needs to
+ run occasionally for TUN/TAP, rather than handling every packet, as
+ it does with ethertap. This is a slight security advantage since
+ it provides fewer opportunities for a nasty UML user to somehow
+ exploit the helper's root privileges.
+
+
+ 66..11.. GGeenneerraall sseettuupp
+
+ First, you must have the virtual network enabled in your UML. If are
+ running a prebuilt kernel from this site, everything is already
+ enabled. If you build the kernel yourself, under the "Network device
+ support" menu, enable "Network device support", and then the three
+ transports.
+
+
+ The next step is to provide a network device to the virtual machine.
+ This is done by describing it on the kernel command line.
+
+ The general format is
+
+
+ eth <n> = <transport> , <transport args>
+
+
+
+
+ For example, a virtual ethernet device may be attached to a host
+ ethertap device as follows:
+
+
+ eth0=ethertap,tap0,fe:fd:0:0:0:1,192.168.0.254
+
+
+
+
+ This sets up eth0 inside the virtual machine to attach itself to the
+ host /dev/tap0, assigns it an ethernet address, and assigns the host
+ tap0 interface an IP address.
+
+
+
+ Note that the IP address you assign to the host end of the tap device
+ must be different than the IP you assign to the eth device inside UML.
+ If you are short on IPs and don't want to comsume two per UML, then
+ you can reuse the host's eth IP address for the host ends of the tap
+ devices. Internally, the UMLs must still get unique IPs for their eth
+ devices. You can also give the UMLs non-routable IPs (192.168.x.x or
+ 10.x.x.x) and have the host masquerade them. This will let outgoing
+ connections work, but incoming connections won't without more work,
+ such as port forwarding from the host.
+ Also note that when you configure the host side of an interface, it is
+ only acting as a gateway. It will respond to pings sent to it
+ locally, but is not useful to do that since it's a host interface.
+ You are not talking to the UML when you ping that interface and get a
+ response.
+
+
+ You can also add devices to a UML and remove them at runtime. See the
+ ``The Management Console'' page for details.
+
+
+ The sections below describe this in more detail.
+
+
+ Once you've decided how you're going to set up the devices, you boot
+ UML, log in, configure the UML side of the devices, and set up routes
+ to the outside world. At that point, you will be able to talk to any
+ other machines, physical or virtual, on the net.
+
+
+ If ifconfig inside UML fails and the network refuses to come up, run
+ tell you what went wrong.
+
+
+
+ 66..22.. UUsseerrssppaaccee ddaaeemmoonnss
+
+ You will likely need the setuid helper, or the switch daemon, or both.
+ They are both installed with the RPM and deb, so if you've installed
+ either, you can skip the rest of this section.
+
+
+ If not, then you need to check them out of CVS, build them, and
+ install them. The helper is uml_net, in CVS /tools/uml_net, and the
+ daemon is uml_switch, in CVS /tools/uml_router. They are both built
+ with a plain 'make'. Both need to be installed in a directory that's
+ in your path - /usr/bin is recommend. On top of that, uml_net needs
+ to be setuid root.
+
+
+
+ 66..33.. SSppeecciiffyyiinngg eetthheerrnneett aaddddrreesssseess
+
+ Below, you will see that the TUN/TAP, ethertap, and daemon interfaces
+ allow you to specify hardware addresses for the virtual ethernet
+ devices. This is generally not necessary. If you don't have a
+ specific reason to do it, you probably shouldn't. If one is not
+ specified on the command line, the driver will assign one based on the
+ device IP address. It will provide the address fe:fd:nn:nn:nn:nn
+ where nn.nn.nn.nn is the device IP address. This is nearly always
+ sufficient to guarantee a unique hardware address for the device. A
+ couple of exceptions are:
+
+ +o Another set of virtual ethernet devices are on the same network and
+ they are assigned hardware addresses using a different scheme which
+ may conflict with the UML IP address-based scheme
+
+ +o You aren't going to use the device for IP networking, so you don't
+ assign the device an IP address
+
+ If you let the driver provide the hardware address, you should make
+ sure that the device IP address is known before the interface is
+ brought up. So, inside UML, this will guarantee that:
+
+
+
+ UML#
+ ifconfig eth0 192.168.0.250 up
+
+
+
+
+ If you decide to assign the hardware address yourself, make sure that
+ the first byte of the address is even. Addresses with an odd first
+ byte are broadcast addresses, which you don't want assigned to a
+ device.
+
+
+
+ 66..44.. UUMMLL iinntteerrffaaccee sseettuupp
+
+ Once the network devices have been described on the command line, you
+ should boot UML and log in.
+
+
+ The first thing to do is bring the interface up:
+
+
+ UML# ifconfig ethn ip-address up
+
+
+
+
+ You should be able to ping the host at this point.
+
+
+ To reach the rest of the world, you should set a default route to the
+ host:
+
+
+ UML# route add default gw host ip
+
+
+
+
+ Again, with host ip of 192.168.0.4:
+
+
+ UML# route add default gw 192.168.0.4
+
+
+
+
+ This page used to recommend setting a network route to your local net.
+ This is wrong, because it will cause UML to try to figure out hardware
+ addresses of the local machines by arping on the interface to the
+ host. Since that interface is basically a single strand of ethernet
+ with two nodes on it (UML and the host) and arp requests don't cross
+ networks, they will fail to elicit any responses. So, what you want
+ is for UML to just blindly throw all packets at the host and let it
+ figure out what to do with them, which is what leaving out the network
+ route and adding the default route does.
+
+
+ Note: If you can't communicate with other hosts on your physical
+ ethernet, it's probably because of a network route that's
+ automatically set up. If you run 'route -n' and see a route that
+ looks like this:
+
+
+
+
+ Destination Gateway Genmask Flags Metric Ref Use Iface
+ 192.168.0.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0
+
+
+
+
+ with a mask that's not 255.255.255.255, then replace it with a route
+ to your host:
+
+
+ UML#
+ route del -net 192.168.0.0 dev eth0 netmask 255.255.255.0
+
+
+
+
+
+
+ UML#
+ route add -host 192.168.0.4 dev eth0
+
+
+
+
+ This, plus the default route to the host, will allow UML to exchange
+ packets with any machine on your ethernet.
+
+
+
+ 66..55.. MMuullttiiccaasstt
+
+ The simplest way to set up a virtual network between multiple UMLs is
+ to use the mcast transport. This was written by Harald Welte and is
+ present in UML version 2.4.5-5um and later. Your system must have
+ multicast enabled in the kernel and there must be a multicast-capable
+ network device on the host. Normally, this is eth0, but if there is
+ no ethernet card on the host, then you will likely get strange error
+ messages when you bring the device up inside UML.
+
+
+ To use it, run two UMLs with
+
+
+ eth0=mcast
+
+
+
+
+ on their command lines. Log in, configure the ethernet device in each
+ machine with different IP addresses:
+
+
+ UML1# ifconfig eth0 192.168.0.254
+
+
+
+
+
+
+ UML2# ifconfig eth0 192.168.0.253
+
+
+
+
+ and they should be able to talk to each other.
+
+ The full set of command line options for this transport are
+
+
+
+ ethn=mcast,ethernet address,multicast
+ address,multicast port,ttl
+
+
+
+
+ Harald's original README is here <http://user-mode-linux.source-
+ forge.net/text/mcast.txt> and explains these in detail, as well as
+ some other issues.
+
+
+
+ 66..66.. TTUUNN//TTAAPP wwiitthh tthhee uummll__nneett hheellppeerr
+
+ TUN/TAP is the preferred mechanism on 2.4 to exchange packets with the
+ host. The TUN/TAP backend has been in UML since 2.4.9-3um.
+
+
+ The easiest way to get up and running is to let the setuid uml_net
+ helper do the host setup for you. This involves insmod-ing the tun.o
+ module if necessary, configuring the device, and setting up IP
+ forwarding, routing, and proxy arp. If you are new to UML networking,
+ do this first. If you're concerned about the security implications of
+ the setuid helper, use it to get up and running, then read the next
+ section to see how to have UML use a preconfigured tap device, which
+ avoids the use of uml_net.
+
+
+ If you specify an IP address for the host side of the device, the
+ uml_net helper will do all necessary setup on the host - the only
+ requirement is that TUN/TAP be available, either built in to the host
+ kernel or as the tun.o module.
+
+ The format of the command line switch to attach a device to a TUN/TAP
+ device is
+
+
+ eth <n> =tuntap,,, <IP address>
+
+
+
+
+ For example, this argument will attach the UML's eth0 to the next
+ available tap device and assign an ethernet address to it based on its
+ IP address
+
+
+ eth0=tuntap,,,192.168.0.254
+
+
+
+
+
+
+ Note that the IP address that must be used for the eth device inside
+ UML is fixed by the routing and proxy arp that is set up on the
+ TUN/TAP device on the host. You can use a different one, but it won't
+ work because reply packets won't reach the UML. This is a feature.
+ It prevents a nasty UML user from doing things like setting the UML IP
+ to the same as the network's nameserver or mail server.
+
+
+ There are a couple potential problems with running the TUN/TAP
+ transport on a 2.4 host kernel
+
+ +o TUN/TAP seems not to work on 2.4.3 and earlier. Upgrade the host
+ kernel or use the ethertap transport.
+
+ +o With an upgraded kernel, TUN/TAP may fail with
+
+
+ File descriptor in bad state
+
+
+
+
+ This is due to a header mismatch between the upgraded kernel and the
+ kernel that was originally installed on the machine. The fix is to
+ make sure that /usr/src/linux points to the headers for the running
+ kernel.
+
+ These were pointed out by Tim Robinson <timro at trkr dot net> in
+ <http://www.geocrawler.com/lists/3/SourceForge/597/0/> name="this uml-
+ user post"> .
+
+
+
+ 66..77.. TTUUNN//TTAAPP wwiitthh aa pprreeccoonnffiigguurreedd ttaapp ddeevviiccee
+
+ If you prefer not to have UML use uml_net (which is somewhat
+ insecure), with UML 2.4.17-11, you can set up a TUN/TAP device
+ beforehand. The setup needs to be done as root, but once that's done,
+ there is no need for root assistance. Setting up the device is done
+ as follows:
+
+ +o Create the device with tunctl (available from the UML utilities
+ tarball)
+
+
+
+
+ host# tunctl -u uid
+
+
+
+
+ where uid is the user id or username that UML will be run as. This
+ will tell you what device was created.
+
+ +o Configure the device IP (change IP addresses and device name to
+ suit)
+
+
+
+
+ host# ifconfig tap0 192.168.0.254 up
+
+
+
+
+
+ +o Set up routing and arping if desired - this is my recipe, there are
+ other ways of doing the same thing
+
+
+ host#
+ bash -c 'echo 1 > /proc/sys/net/ipv4/ip_forward'
+
+ host#
+ route add -host 192.168.0.253 dev tap0
+
+
+
+
+
+
+ host#
+ bash -c 'echo 1 > /proc/sys/net/ipv4/conf/tap0/proxy_arp'
+
+
+
+
+
+
+ host#
+ arp -Ds 192.168.0.253 eth0 pub
+
+
+
+
+ Note that this must be done every time the host boots - this configu-
+ ration is not stored across host reboots. So, it's probably a good
+ idea to stick it in an rc file. An even better idea would be a little
+ utility which reads the information from a config file and sets up
+ devices at boot time.
+
+ +o Rather than using up two IPs and ARPing for one of them, you can
+ also provide direct access to your LAN by the UML by using a
+ bridge.
+
+
+ host#
+ brctl addbr br0
+
+
+
+
+
+
+ host#
+ ifconfig eth0 0.0.0.0 promisc up
+
+
+
+
+
+
+ host#
+ ifconfig tap0 0.0.0.0 promisc up
+
+
+
+
+
+
+ host#
+ ifconfig br0 192.168.0.1 netmask 255.255.255.0 up
+
+
+
+
+
+
+
+ host#
+ brctl stp br0 off
+
+
+
+
+
+
+ host#
+ brctl setfd br0 1
+
+
+
+
+
+
+ host#
+ brctl sethello br0 1
+
+
+
+
+
+
+ host#
+ brctl addif br0 eth0
+
+
+
+
+
+
+ host#
+ brctl addif br0 tap0
+
+
+
+
+ Note that 'br0' should be setup using ifconfig with the existing IP
+ address of eth0, as eth0 no longer has its own IP.
+
+ +o
+
+
+ Also, the /dev/net/tun device must be writable by the user running
+ UML in order for the UML to use the device that's been configured
+ for it. The simplest thing to do is
+
+
+ host# chmod 666 /dev/net/tun
+
+
+
+
+ Making it world-writeable looks bad, but it seems not to be
+ exploitable as a security hole. However, it does allow anyone to cre-
+ ate useless tap devices (useless because they can't configure them),
+ which is a DOS attack. A somewhat more secure alternative would to be
+ to create a group containing all the users who have preconfigured tap
+ devices and chgrp /dev/net/tun to that group with mode 664 or 660.
+
+
+ +o Once the device is set up, run UML with 'eth0=tuntap,device name'
+ (i.e. 'eth0=tuntap,tap0') on the command line (or do it with the
+ mconsole config command).
+
+ +o Bring the eth device up in UML and you're in business.
+
+ If you don't want that tap device any more, you can make it non-
+ persistent with
+
+
+ host# tunctl -d tap device
+
+
+
+
+ Finally, tunctl has a -b (for brief mode) switch which causes it to
+ output only the name of the tap device it created. This makes it
+ suitable for capture by a script:
+
+
+ host# TAP=`tunctl -u 1000 -b`
+
+
+
+
+
+
+ 66..88.. EEtthheerrttaapp
+
+ Ethertap is the general mechanism on 2.2 for userspace processes to
+ exchange packets with the kernel.
+
+
+
+ To use this transport, you need to describe the virtual network device
+ on the UML command line. The general format for this is
+
+
+ eth <n> =ethertap, <device> , <ethernet address> , <tap IP address>
+
+
+
+
+ So, the previous example
+
+
+ eth0=ethertap,tap0,fe:fd:0:0:0:1,192.168.0.254
+
+
+
+
+ attaches the UML eth0 device to the host /dev/tap0, assigns it the
+ ethernet address fe:fd:0:0:0:1, and assigns the IP address
+ 192.168.0.254 to the tap device.
+
+
+
+ The tap device is mandatory, but the others are optional. If the
+ ethernet address is omitted, one will be assigned to it.
+
+
+ The presence of the tap IP address will cause the helper to run and do
+ whatever host setup is needed to allow the virtual machine to
+ communicate with the outside world. If you're not sure you know what
+ you're doing, this is the way to go.
+
+
+ If it is absent, then you must configure the tap device and whatever
+ arping and routing you will need on the host. However, even in this
+ case, the uml_net helper still needs to be in your path and it must be
+ setuid root if you're not running UML as root. This is because the
+ tap device doesn't support SIGIO, which UML needs in order to use
+ something as a source of input. So, the helper is used as a
+ convenient asynchronous IO thread.
+
+ If you're using the uml_net helper, you can ignore the following host
+ setup - uml_net will do it for you. You just need to make sure you
+ have ethertap available, either built in to the host kernel or
+ available as a module.
+
+
+ If you want to set things up yourself, you need to make sure that the
+ appropriate /dev entry exists. If it doesn't, become root and create
+ it as follows:
+
+
+ mknod /dev/tap <minor> c 36 <minor> + 16
+
+
+
+
+ For example, this is how to create /dev/tap0:
+
+
+ mknod /dev/tap0 c 36 0 + 16
+
+
+
+
+ You also need to make sure that the host kernel has ethertap support.
+ If ethertap is enabled as a module, you apparently need to insmod
+ ethertap once for each ethertap device you want to enable. So,
+
+
+ host#
+ insmod ethertap
+
+
+
+
+ will give you the tap0 interface. To get the tap1 interface, you need
+ to run
+
+
+ host#
+ insmod ethertap unit=1 -o ethertap1
+
+
+
+
+
+
+
+ 66..99.. TThhee sswwiittcchh ddaaeemmoonn
+
+ NNoottee: This is the daemon formerly known as uml_router, but which was
+ renamed so the network weenies of the world would stop growling at me.
+
+
+ The switch daemon, uml_switch, provides a mechanism for creating a
+ totally virtual network. By default, it provides no connection to the
+ host network (but see -tap, below).
+
+
+ The first thing you need to do is run the daemon. Running it with no
+ arguments will make it listen on a default pair of unix domain
+ sockets.
+
+
+ If you want it to listen on a different pair of sockets, use
+
+
+ -unix control socket data socket
+
+
+
+
+
+ If you want it to act as a hub rather than a switch, use
+
+
+ -hub
+
+
+
+
+
+ If you want the switch to be connected to host networking (allowing
+ the umls to get access to the outside world through the host), use
+
+
+ -tap tap0
+
+
+
+
+
+ Note that the tap device must be preconfigured (see "TUN/TAP with a
+ preconfigured tap device", above). If you're using a different tap
+ device than tap0, specify that instead of tap0.
+
+
+ uml_switch can be backgrounded as follows
+
+
+ host%
+ uml_switch [ options ] < /dev/null > /dev/null
+
+
+
+
+ The reason it doesn't background by default is that it listens to
+ stdin for EOF. When it sees that, it exits.
+
+
+ The general format of the kernel command line switch is
+
+
+
+ ethn=daemon,ethernet address,socket
+ type,control socket,data socket
+
+
+
+
+ You can leave off everything except the 'daemon'. You only need to
+ specify the ethernet address if the one that will be assigned to it
+ isn't acceptable for some reason. The rest of the arguments describe
+ how to communicate with the daemon. You should only specify them if
+ you told the daemon to use different sockets than the default. So, if
+ you ran the daemon with no arguments, running the UML on the same
+ machine with
+ eth0=daemon
+
+
+
+
+ will cause the eth0 driver to attach itself to the daemon correctly.
+
+
+
+ 66..1100.. SSlliipp
+
+ Slip is another, less general, mechanism for a process to communicate
+ with the host networking. In contrast to the ethertap interface,
+ which exchanges ethernet frames with the host and can be used to
+ transport any higher-level protocol, it can only be used to transport
+ IP.
+
+
+ The general format of the command line switch is
+
+
+
+ ethn=slip,slip IP
+
+
+
+
+ The slip IP argument is the IP address that will be assigned to the
+ host end of the slip device. If it is specified, the helper will run
+ and will set up the host so that the virtual machine can reach it and
+ the rest of the network.
+
+
+ There are some oddities with this interface that you should be aware
+ of. You should only specify one slip device on a given virtual
+ machine, and its name inside UML will be 'umn', not 'eth0' or whatever
+ you specified on the command line. These problems will be fixed at
+ some point.
+
+
+
+ 66..1111.. SSlliirrpp
+
+ slirp uses an external program, usually /usr/bin/slirp, to provide IP
+ only networking connectivity through the host. This is similar to IP
+ masquerading with a firewall, although the translation is performed in
+ user-space, rather than by the kernel. As slirp does not set up any
+ interfaces on the host, or changes routing, slirp does not require
+ root access or setuid binaries on the host.
+
+
+ The general format of the command line switch for slirp is:
+
+
+
+ ethn=slirp,ethernet address,slirp path
+
+
+
+
+ The ethernet address is optional, as UML will set up the interface
+ with an ethernet address based upon the initial IP address of the
+ interface. The slirp path is generally /usr/bin/slirp, although it
+ will depend on distribution.
+
+
+ The slirp program can have a number of options passed to the command
+ line and we can't add them to the UML command line, as they will be
+ parsed incorrectly. Instead, a wrapper shell script can be written or
+ the options inserted into the /.slirprc file. More information on
+ all of the slirp options can be found in its man pages.
+
+
+ The eth0 interface on UML should be set up with the IP 10.2.0.15,
+ although you can use anything as long as it is not used by a network
+ you will be connecting to. The default route on UML should be set to
+ use
+
+
+ UML#
+ route add default dev eth0
+
+
+
+
+ slirp provides a number of useful IP addresses which can be used by
+ UML, such as 10.0.2.3 which is an alias for the DNS server specified
+ in /etc/resolv.conf on the host or the IP given in the 'dns' option
+ for slirp.
+
+
+ Even with a baudrate setting higher than 115200, the slirp connection
+ is limited to 115200. If you need it to go faster, the slirp binary
+ needs to be compiled with FULL_BOLT defined in config.h.
+
+
+
+ 66..1122.. ppccaapp
+
+ The pcap transport is attached to a UML ethernet device on the command
+ line or with uml_mconsole with the following syntax:
+
+
+
+ ethn=pcap,host interface,filter
+ expression,option1,option2
+
+
+
+
+ The expression and options are optional.
+
+
+ The interface is whatever network device on the host you want to
+ sniff. The expression is a pcap filter expression, which is also what
+ tcpdump uses, so if you know how to specify tcpdump filters, you will
+ use the same expressions here. The options are up to two of
+ 'promisc', control whether pcap puts the host interface into
+ promiscuous mode. 'optimize' and 'nooptimize' control whether the pcap
+ expression optimizer is used.
+
+
+ Example:
+
+
+
+ eth0=pcap,eth0,tcp
+
+ eth1=pcap,eth0,!tcp
+
+
+
+ will cause the UML eth0 to emit all tcp packets on the host eth0 and
+ the UML eth1 to emit all non-tcp packets on the host eth0.
+
+
+
+ 66..1133.. SSeettttiinngg uupp tthhee hhoosstt yyoouurrsseellff
+
+ If you don't specify an address for the host side of the ethertap or
+ slip device, UML won't do any setup on the host. So this is what is
+ needed to get things working (the examples use a host-side IP of
+ 192.168.0.251 and a UML-side IP of 192.168.0.250 - adjust to suit your
+ own network):
+
+ +o The device needs to be configured with its IP address. Tap devices
+ are also configured with an mtu of 1484. Slip devices are
+ configured with a point-to-point address pointing at the UML ip
+ address.
+
+
+ host# ifconfig tap0 arp mtu 1484 192.168.0.251 up
+
+
+
+
+
+
+ host#
+ ifconfig sl0 192.168.0.251 pointopoint 192.168.0.250 up
+
+
+
+
+
+ +o If a tap device is being set up, a route is set to the UML IP.
+
+
+ UML# route add -host 192.168.0.250 gw 192.168.0.251
+
+
+
+
+
+ +o To allow other hosts on your network to see the virtual machine,
+ proxy arp is set up for it.
+
+
+ host# arp -Ds 192.168.0.250 eth0 pub
+
+
+
+
+
+ +o Finally, the host is set up to route packets.
+
+
+ host# echo 1 > /proc/sys/net/ipv4/ip_forward
+
+
+
+
+
+
+
+
+
+
+ 77.. SShhaarriinngg FFiilleessyysstteemmss bbeettwweeeenn VViirrttuuaall MMaacchhiinneess
+
+
+
+
+ 77..11.. AA wwaarrnniinngg
+
+ Don't attempt to share filesystems simply by booting two UMLs from the
+ same file. That's the same thing as booting two physical machines
+ from a shared disk. It will result in filesystem corruption.
+
+
+
+ 77..22.. UUssiinngg llaayyeerreedd bblloocckk ddeevviicceess
+
+ The way to share a filesystem between two virtual machines is to use
+ the copy-on-write (COW) layering capability of the ubd block driver.
+ As of 2.4.6-2um, the driver supports layering a read-write private
+ device over a read-only shared device. A machine's writes are stored
+ in the private device, while reads come from either device - the
+ private one if the requested block is valid in it, the shared one if
+ not. Using this scheme, the majority of data which is unchanged is
+ shared between an arbitrary number of virtual machines, each of which
+ has a much smaller file containing the changes that it has made. With
+ a large number of UMLs booting from a large root filesystem, this
+ leads to a huge disk space saving. It will also help performance,
+ since the host will be able to cache the shared data using a much
+ smaller amount of memory, so UML disk requests will be served from the
+ host's memory rather than its disks.
+
+
+
+
+ To add a copy-on-write layer to an existing block device file, simply
+ add the name of the COW file to the appropriate ubd switch:
+
+
+ ubd0=root_fs_cow,root_fs_debian_22
+
+
+
+
+ where 'root_fs_cow' is the private COW file and 'root_fs_debian_22' is
+ the existing shared filesystem. The COW file need not exist. If it
+ doesn't, the driver will create and initialize it. Once the COW file
+ has been initialized, it can be used on its own on the command line:
+
+
+ ubd0=root_fs_cow
+
+
+
+
+ The name of the backing file is stored in the COW file header, so it
+ would be redundant to continue specifying it on the command line.
+
+
+
+ 77..33.. NNoottee!!
+
+ When checking the size of the COW file in order to see the gobs of
+ space that you're saving, make sure you use 'ls -ls' to see the actual
+ disk consumption rather than the length of the file. The COW file is
+ sparse, so the length will be very different from the disk usage.
+ Here is a 'ls -l' of a COW file and backing file from one boot and
+ shutdown:
+ host% ls -l cow.debian debian2.2
+ -rw-r--r-- 1 jdike jdike 492504064 Aug 6 21:16 cow.debian
+ -rwxrw-rw- 1 jdike jdike 537919488 Aug 6 20:42 debian2.2
+
+
+
+
+ Doesn't look like much saved space, does it? Well, here's 'ls -ls':
+
+
+ host% ls -ls cow.debian debian2.2
+ 880 -rw-r--r-- 1 jdike jdike 492504064 Aug 6 21:16 cow.debian
+ 525832 -rwxrw-rw- 1 jdike jdike 537919488 Aug 6 20:42 debian2.2
+
+
+
+
+ Now, you can see that the COW file has less than a meg of disk, rather
+ than 492 meg.
+
+
+
+ 77..44.. AAnnootthheerr wwaarrnniinngg
+
+ Once a filesystem is being used as a readonly backing file for a COW
+ file, do not boot directly from it or modify it in any way. Doing so
+ will invalidate any COW files that are using it. The mtime and size
+ of the backing file are stored in the COW file header at its creation,
+ and they must continue to match. If they don't, the driver will
+ refuse to use the COW file.
+
+
+
+
+ If you attempt to evade this restriction by changing either the
+ backing file or the COW header by hand, you will get a corrupted
+ filesystem.
+
+
+
+
+ Among other things, this means that upgrading the distribution in a
+ backing file and expecting that all of the COW files using it will see
+ the upgrade will not work.
+
+
+
+
+ 77..55.. uummll__mmoooo :: MMeerrggiinngg aa CCOOWW ffiillee wwiitthh iittss bbaacckkiinngg ffiillee
+
+ Depending on how you use UML and COW devices, it may be advisable to
+ merge the changes in the COW file into the backing file every once in
+ a while.
+
+
+
+
+ The utility that does this is uml_moo. Its usage is
+
+
+ host% uml_moo COW file new backing file
+
+
+
+
+ There's no need to specify the backing file since that information is
+ already in the COW file header. If you're paranoid, boot the new
+ merged file, and if you're happy with it, move it over the old backing
+ file.
+
+
+
+
+ uml_moo creates a new backing file by default as a safety measure. It
+ also has a destructive merge option which will merge the COW file
+ directly into its current backing file. This is really only usable
+ when the backing file only has one COW file associated with it. If
+ there are multiple COWs associated with a backing file, a -d merge of
+ one of them will invalidate all of the others. However, it is
+ convenient if you're short of disk space, and it should also be
+ noticably faster than a non-destructive merge.
+
+
+
+
+ uml_moo is installed with the UML deb and RPM. If you didn't install
+ UML from one of those packages, you can also get it from the UML
+ utilities <http://user-mode-linux.sourceforge.net/dl-sf.html#UML
+ utilities> tar file in tools/moo.
+
+
+
+
+
+
+
+
+ 88.. CCrreeaattiinngg ffiilleessyysstteemmss
+
+
+ You may want to create and mount new UML filesystems, either because
+ your root filesystem isn't large enough or because you want to use a
+ filesystem other than ext2.
+
+
+ This was written on the occasion of reiserfs being included in the
+ 2.4.1 kernel pool, and therefore the 2.4.1 UML, so the examples will
+ talk about reiserfs. This information is generic, and the examples
+ should be easy to translate to the filesystem of your choice.
+
+
+ 88..11.. CCrreeaattee tthhee ffiilleessyysstteemm ffiillee
+
+ dd is your friend. All you need to do is tell dd to create an empty
+ file of the appropriate size. I usually make it sparse to save time
+ and to avoid allocating disk space until it's actually used. For
+ example, the following command will create a sparse 100 meg file full
+ of zeroes.
+
+
+ host%
+ dd if=/dev/zero of=new_filesystem seek=100 count=1 bs=1M
+
+
+
+
+
+
+ 88..22.. AAssssiiggnn tthhee ffiillee ttoo aa UUMMLL ddeevviiccee
+
+ Add an argument like the following to the UML command line:
+
+ ubd4=new_filesystem
+
+
+
+
+ making sure that you use an unassigned ubd device number.
+
+
+
+ 88..33.. CCrreeaattiinngg aanndd mmoouunnttiinngg tthhee ffiilleessyysstteemm
+
+ Make sure that the filesystem is available, either by being built into
+ the kernel, or available as a module, then boot up UML and log in. If
+ the root filesystem doesn't have the filesystem utilities (mkfs, fsck,
+ etc), then get them into UML by way of the net or hostfs.
+
+
+ Make the new filesystem on the device assigned to the new file:
+
+
+ host# mkreiserfs /dev/ubd/4
+
+
+ <----------- MKREISERFSv2 ----------->
+
+ ReiserFS version 3.6.25
+ Block size 4096 bytes
+ Block count 25856
+ Used blocks 8212
+ Journal - 8192 blocks (18-8209), journal header is in block 8210
+ Bitmaps: 17
+ Root block 8211
+ Hash function "r5"
+ ATTENTION: ALL DATA WILL BE LOST ON '/dev/ubd/4'! (y/n)y
+ journal size 8192 (from 18)
+ Initializing journal - 0%....20%....40%....60%....80%....100%
+ Syncing..done.
+
+
+
+
+ Now, mount it:
+
+
+ UML#
+ mount /dev/ubd/4 /mnt
+
+
+
+
+ and you're in business.
+
+
+
+
+
+
+
+
+
+ 99.. HHoosstt ffiillee aacccceessss
+
+
+ If you want to access files on the host machine from inside UML, you
+ can treat it as a separate machine and either nfs mount directories
+ from the host or copy files into the virtual machine with scp or rcp.
+ However, since UML is running on the the host, it can access those
+ files just like any other process and make them available inside the
+ virtual machine without needing to use the network.
+
+
+ This is now possible with the hostfs virtual filesystem. With it, you
+ can mount a host directory into the UML filesystem and access the
+ files contained in it just as you would on the host.
+
+
+ 99..11.. UUssiinngg hhoossttffss
+
+ To begin with, make sure that hostfs is available inside the virtual
+ machine with
+
+
+ UML# cat /proc/filesystems
+
+
+
+ . hostfs should be listed. If it's not, either rebuild the kernel
+ with hostfs configured into it or make sure that hostfs is built as a
+ module and available inside the virtual machine, and insmod it.
+
+
+ Now all you need to do is run mount:
+
+
+ UML# mount none /mnt/host -t hostfs
+
+
+
+
+ will mount the host's / on the virtual machine's /mnt/host.
+
+
+ If you don't want to mount the host root directory, then you can
+ specify a subdirectory to mount with the -o switch to mount:
+
+
+ UML# mount none /mnt/home -t hostfs -o /home
+
+
+
+
+ will mount the hosts's /home on the virtual machine's /mnt/home.
+
+
+
+ 99..22.. hhoossttffss aass tthhee rroooott ffiilleessyysstteemm
+
+ It's possible to boot from a directory hierarchy on the host using
+ hostfs rather than using the standard filesystem in a file.
+
+ To start, you need that hierarchy. The easiest way is to loop mount
+ an existing root_fs file:
+
+
+ host# mount root_fs uml_root_dir -o loop
+
+
+
+
+ You need to change the filesystem type of / in etc/fstab to be
+ 'hostfs', so that line looks like this:
+
+ /dev/ubd/0 / hostfs defaults 1 1
+
+
+
+
+ Then you need to chown to yourself all the files in that directory
+ that are owned by root. This worked for me:
+
+
+ host# find . -uid 0 -exec chown jdike {} \;
+
+
+
+
+ Next, make sure that your UML kernel has hostfs compiled in, not as a
+ module. Then run UML with the boot device pointing at that directory:
+
+
+ ubd0=/path/to/uml/root/directory
+
+
+
+
+ UML should then boot as it does normally.
+
+
+ 99..33.. BBuuiillddiinngg hhoossttffss
+
+ If you need to build hostfs because it's not in your kernel, you have
+ two choices:
+
+
+
+ +o Compiling hostfs into the kernel:
+
+
+ Reconfigure the kernel and set the 'Host filesystem' option under
+
+
+ +o Compiling hostfs as a module:
+
+
+ Reconfigure the kernel and set the 'Host filesystem' option under
+ be in arch/um/fs/hostfs/hostfs.o. Install that in
+ /lib/modules/`uname -r`/fs in the virtual machine, boot it up, and
+
+
+ UML# insmod hostfs
+
+
+
+
+
+
+
+
+
+
+
+
+ 1100.. TThhee MMaannaaggeemmeenntt CCoonnssoollee
+
+
+
+ The UML management console is a low-level interface to the kernel,
+ somewhat like the i386 SysRq interface. Since there is a full-blown
+ operating system under UML, there is much greater flexibility possible
+ than with the SysRq mechanism.
+
+
+ There are a number of things you can do with the mconsole interface:
+
+ +o get the kernel version
+
+ +o add and remove devices
+
+ +o halt or reboot the machine
+
+ +o Send SysRq commands
+
+ +o Pause and resume the UML
+
+
+ You need the mconsole client (uml_mconsole) which is present in CVS
+ (/tools/mconsole) in 2.4.5-9um and later, and will be in the RPM in
+ 2.4.6.
+
+
+ You also need CONFIG_MCONSOLE (under 'General Setup') enabled in UML.
+ When you boot UML, you'll see a line like:
+
+
+ mconsole initialized on /home/jdike/.uml/umlNJ32yL/mconsole
+
+
+
+
+ If you specify a unique machine id one the UML command line, i.e.
+
+
+ umid=debian
+
+
+
+
+ you'll see this
+
+
+ mconsole initialized on /home/jdike/.uml/debian/mconsole
+
+
+
+
+ That file is the socket that uml_mconsole will use to communicate with
+ UML. Run it with either the umid or the full path as its argument:
+
+
+ host% uml_mconsole debian
+
+
+
+
+ or
+
+
+ host% uml_mconsole /home/jdike/.uml/debian/mconsole
+
+
+
+
+ You'll get a prompt, at which you can run one of these commands:
+
+ +o version
+
+ +o halt
+
+ +o reboot
+
+ +o config
+
+ +o remove
+
+ +o sysrq
+
+ +o help
+
+ +o cad
+
+ +o stop
+
+ +o go
+
+
+ 1100..11.. vveerrssiioonn
+
+ This takes no arguments. It prints the UML version.
+
+
+ (mconsole) version
+ OK Linux usermode 2.4.5-9um #1 Wed Jun 20 22:47:08 EDT 2001 i686
+
+
+
+
+ There are a couple actual uses for this. It's a simple no-op which
+ can be used to check that a UML is running. It's also a way of
+ sending an interrupt to the UML. This is sometimes useful on SMP
+ hosts, where there's a bug which causes signals to UML to be lost,
+ often causing it to appear to hang. Sending such a UML the mconsole
+ version command is a good way to 'wake it up' before networking has
+ been enabled, as it does not do anything to the function of the UML.
+
+
+
+ 1100..22.. hhaalltt aanndd rreebboooott
+
+ These take no arguments. They shut the machine down immediately, with
+ no syncing of disks and no clean shutdown of userspace. So, they are
+ pretty close to crashing the machine.
+
+
+ (mconsole) halt
+ OK
+
+
+
+
+
+
+ 1100..33.. ccoonnffiigg
+
+ "config" adds a new device to the virtual machine. Currently the ubd
+ and network drivers support this. It takes one argument, which is the
+ device to add, with the same syntax as the kernel command line.
+
+
+
+
+ (mconsole)
+ config ubd3=/home/jdike/incoming/roots/root_fs_debian22
+
+ OK
+ (mconsole) config eth1=mcast
+ OK
+
+
+
+
+
+
+ 1100..44.. rreemmoovvee
+
+ "remove" deletes a device from the system. Its argument is just the
+ name of the device to be removed. The device must be idle in whatever
+ sense the driver considers necessary. In the case of the ubd driver,
+ the removed block device must not be mounted, swapped on, or otherwise
+ open, and in the case of the network driver, the device must be down.
+
+
+ (mconsole) remove ubd3
+ OK
+ (mconsole) remove eth1
+ OK
+
+
+
+
+
+
+ 1100..55.. ssyyssrrqq
+
+ This takes one argument, which is a single letter. It calls the
+ generic kernel's SysRq driver, which does whatever is called for by
+ that argument. See the SysRq documentation in Documentation/sysrq.txt
+ in your favorite kernel tree to see what letters are valid and what
+ they do.
+
+
+
+ 1100..66.. hheellpp
+
+ "help" returns a string listing the valid commands and what each one
+ does.
+
+
+
+ 1100..77.. ccaadd
+
+ This invokes the Ctl-Alt-Del action on init. What exactly this ends
+ up doing is up to /etc/inittab. Normally, it reboots the machine.
+ With UML, this is usually not desired, so if a halt would be better,
+ then find the section of inittab that looks like this
+
+
+ # What to do when CTRL-ALT-DEL is pressed.
+ ca:12345:ctrlaltdel:/sbin/shutdown -t1 -a -r now
+
+
+
+
+ and change the command to halt.
+
+
+
+ 1100..88.. ssttoopp
+
+ This puts the UML in a loop reading mconsole requests until a 'go'
+ mconsole command is recieved. This is very useful for making backups
+ of UML filesystems, as the UML can be stopped, then synced via 'sysrq
+ s', so that everything is written to the filesystem. You can then copy
+ the filesystem and then send the UML 'go' via mconsole.
+
+
+ Note that a UML running with more than one CPU will have problems
+ after you send the 'stop' command, as only one CPU will be held in a
+ mconsole loop and all others will continue as normal. This is a bug,
+ and will be fixed.
+
+
+
+ 1100..99.. ggoo
+
+ This resumes a UML after being paused by a 'stop' command. Note that
+ when the UML has resumed, TCP connections may have timed out and if
+ the UML is paused for a long period of time, crond might go a little
+ crazy, running all the jobs it didn't do earlier.
+
+
+
+
+
+
+
+
+ 1111.. KKeerrnneell ddeebbuuggggiinngg
+
+
+ NNoottee:: The interface that makes debugging, as described here, possible
+ is present in 2.4.0-test6 kernels and later.
+
+
+ Since the user-mode kernel runs as a normal Linux process, it is
+ possible to debug it with gdb almost like any other process. It is
+ slightly different because the kernel's threads are already being
+ ptraced for system call interception, so gdb can't ptrace them.
+ However, a mechanism has been added to work around that problem.
+
+
+ In order to debug the kernel, you need build it from source. See
+ ``Compiling the kernel and modules'' for information on doing that.
+ Make sure that you enable CONFIG_DEBUGSYM and CONFIG_PT_PROXY during
+ the config. These will compile the kernel with -g, and enable the
+ ptrace proxy so that gdb works with UML, respectively.
+
+
+
+
+ 1111..11.. SSttaarrttiinngg tthhee kkeerrnneell uunnddeerr ggddbb
+
+ You can have the kernel running under the control of gdb from the
+ beginning by putting 'debug' on the command line. You will get an
+ xterm with gdb running inside it. The kernel will send some commands
+ to gdb which will leave it stopped at the beginning of start_kernel.
+ At this point, you can get things going with 'next', 'step', or
+ 'cont'.
+
+
+ There is a transcript of a debugging session here <debug-
+ session.html> , with breakpoints being set in the scheduler and in an
+ interrupt handler.
+ 1111..22.. EExxaammiinniinngg sslleeeeppiinngg pprroocceesssseess
+
+ Not every bug is evident in the currently running process. Sometimes,
+ processes hang in the kernel when they shouldn't because they've
+ deadlocked on a semaphore or something similar. In this case, when
+ you ^C gdb and get a backtrace, you will see the idle thread, which
+ isn't very relevant.
+
+
+ What you want is the stack of whatever process is sleeping when it
+ shouldn't be. You need to figure out which process that is, which is
+ generally fairly easy. Then you need to get its host process id,
+ which you can do either by looking at ps on the host or at
+ task.thread.extern_pid in gdb.
+
+
+ Now what you do is this:
+
+ +o detach from the current thread
+
+
+ (UML gdb) det
+
+
+
+
+
+ +o attach to the thread you are interested in
+
+
+ (UML gdb) att <host pid>
+
+
+
+
+
+ +o look at its stack and anything else of interest
+
+
+ (UML gdb) bt
+
+
+
+
+ Note that you can't do anything at this point that requires that a
+ process execute, e.g. calling a function
+
+ +o when you're done looking at that process, reattach to the current
+ thread and continue it
+
+
+ (UML gdb)
+ att 1
+
+
+
+
+
+
+ (UML gdb)
+ c
+
+
+
+
+ Here, specifying any pid which is not the process id of a UML thread
+ will cause gdb to reattach to the current thread. I commonly use 1,
+ but any other invalid pid would work.
+
+
+
+ 1111..33.. RRuunnnniinngg dddddd oonn UUMMLL
+
+ ddd works on UML, but requires a special kludge. The process goes
+ like this:
+
+ +o Start ddd
+
+
+ host% ddd linux
+
+
+
+
+
+ +o With ps, get the pid of the gdb that ddd started. You can ask the
+ gdb to tell you, but for some reason that confuses things and
+ causes a hang.
+
+ +o run UML with 'debug=parent gdb-pid=<pid>' added to the command line
+ - it will just sit there after you hit return
+
+ +o type 'att 1' to the ddd gdb and you will see something like
+
+
+ 0xa013dc51 in __kill ()
+
+
+ (gdb)
+
+
+
+
+
+ +o At this point, type 'c', UML will boot up, and you can use ddd just
+ as you do on any other process.
+
+
+
+ 1111..44.. DDeebbuuggggiinngg mmoodduulleess
+
+ gdb has support for debugging code which is dynamically loaded into
+ the process. This support is what is needed to debug kernel modules
+ under UML.
+
+
+ Using that support is somewhat complicated. You have to tell gdb what
+ object file you just loaded into UML and where in memory it is. Then,
+ it can read the symbol table, and figure out where all the symbols are
+ from the load address that you provided. It gets more interesting
+ when you load the module again (i.e. after an rmmod). You have to
+ tell gdb to forget about all its symbols, including the main UML ones
+ for some reason, then load then all back in again.
+
+
+ There's an easy way and a hard way to do this. The easy way is to use
+ the umlgdb expect script written by Chandan Kudige. It basically
+ automates the process for you.
+
+
+ First, you must tell it where your modules are. There is a list in
+ the script that looks like this:
+ set MODULE_PATHS {
+ "fat" "/usr/src/uml/linux-2.4.18/fs/fat/fat.o"
+ "isofs" "/usr/src/uml/linux-2.4.18/fs/isofs/isofs.o"
+ "minix" "/usr/src/uml/linux-2.4.18/fs/minix/minix.o"
+ }
+
+
+
+
+ You change that to list the names and paths of the modules that you
+ are going to debug. Then you run it from the toplevel directory of
+ your UML pool and it basically tells you what to do:
+
+
+
+
+ ******** GDB pid is 21903 ********
+ Start UML as: ./linux <kernel switches> debug gdb-pid=21903
+
+
+
+ GNU gdb 5.0rh-5 Red Hat Linux 7.1
+ Copyright 2001 Free Software Foundation, Inc.
+ GDB is free software, covered by the GNU General Public License, and you are
+ welcome to change it and/or distribute copies of it under certain conditions.
+ Type "show copying" to see the conditions.
+ There is absolutely no warranty for GDB. Type "show warranty" for details.
+ This GDB was configured as "i386-redhat-linux"...
+ (gdb) b sys_init_module
+ Breakpoint 1 at 0xa0011923: file module.c, line 349.
+ (gdb) att 1
+
+
+
+
+ After you run UML and it sits there doing nothing, you hit return at
+ the 'att 1' and continue it:
+
+
+ Attaching to program: /home/jdike/linux/2.4/um/./linux, process 1
+ 0xa00f4221 in __kill ()
+ (UML gdb) c
+ Continuing.
+
+
+
+
+ At this point, you debug normally. When you insmod something, the
+ expect magic will kick in and you'll see something like:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ *** Module hostfs loaded ***
+ Breakpoint 1, sys_init_module (name_user=0x805abb0 "hostfs",
+ mod_user=0x8070e00) at module.c:349
+ 349 char *name, *n_name, *name_tmp = NULL;
+ (UML gdb) finish
+ Run till exit from #0 sys_init_module (name_user=0x805abb0 "hostfs",
+ mod_user=0x8070e00) at module.c:349
+ 0xa00e2e23 in execute_syscall (r=0xa8140284) at syscall_kern.c:411
+ 411 else res = EXECUTE_SYSCALL(syscall, regs);
+ Value returned is $1 = 0
+ (UML gdb)
+ p/x (int)module_list + module_list->size_of_struct
+
+ $2 = 0xa9021054
+ (UML gdb) symbol-file ./linux
+ Load new symbol table from "./linux"? (y or n) y
+ Reading symbols from ./linux...
+ done.
+ (UML gdb)
+ add-symbol-file /home/jdike/linux/2.4/um/arch/um/fs/hostfs/hostfs.o 0xa9021054
+
+ add symbol table from file "/home/jdike/linux/2.4/um/arch/um/fs/hostfs/hostfs.o" at
+ .text_addr = 0xa9021054
+ (y or n) y
+
+ Reading symbols from /home/jdike/linux/2.4/um/arch/um/fs/hostfs/hostfs.o...
+ done.
+ (UML gdb) p *module_list
+ $1 = {size_of_struct = 84, next = 0xa0178720, name = 0xa9022de0 "hostfs",
+ size = 9016, uc = {usecount = {counter = 0}, pad = 0}, flags = 1,
+ nsyms = 57, ndeps = 0, syms = 0xa9023170, deps = 0x0, refs = 0x0,
+ init = 0xa90221f0 <init_hostfs>, cleanup = 0xa902222c <exit_hostfs>,
+ ex_table_start = 0x0, ex_table_end = 0x0, persist_start = 0x0,
+ persist_end = 0x0, can_unload = 0, runsize = 0, kallsyms_start = 0x0,
+ kallsyms_end = 0x0,
+ archdata_start = 0x1b855 <Address 0x1b855 out of bounds>,
+ archdata_end = 0xe5890000 <Address 0xe5890000 out of bounds>,
+ kernel_data = 0xf689c35d <Address 0xf689c35d out of bounds>}
+ >> Finished loading symbols for hostfs ...
+
+
+
+
+ That's the easy way. It's highly recommended. The hard way is
+ described below in case you're interested in what's going on.
+
+
+ Boot the kernel under the debugger and load the module with insmod or
+ modprobe. With gdb, do:
+
+
+ (UML gdb) p module_list
+
+
+
+
+ This is a list of modules that have been loaded into the kernel, with
+ the most recently loaded module first. Normally, the module you want
+ is at module_list. If it's not, walk down the next links, looking at
+ the name fields until find the module you want to debug. Take the
+ address of that structure, and add module.size_of_struct (which in
+ 2.4.10 kernels is 96 (0x60)) to it. Gdb can make this hard addition
+ for you :-):
+
+
+
+ (UML gdb)
+ printf "%#x\n", (int)module_list module_list->size_of_struct
+
+
+
+
+ The offset from the module start occasionally changes (before 2.4.0,
+ it was module.size_of_struct + 4), so it's a good idea to check the
+ init and cleanup addresses once in a while, as describe below. Now
+ do:
+
+
+ (UML gdb)
+ add-symbol-file /path/to/module/on/host that_address
+
+
+
+
+ Tell gdb you really want to do it, and you're in business.
+
+
+ If there's any doubt that you got the offset right, like breakpoints
+ appear not to work, or they're appearing in the wrong place, you can
+ check it by looking at the module structure. The init and cleanup
+ fields should look like:
+
+
+ init = 0x588066b0 <init_hostfs>, cleanup = 0x588066c0 <exit_hostfs>
+
+
+
+
+ with no offsets on the symbol names. If the names are right, but they
+ are offset, then the offset tells you how much you need to add to the
+ address you gave to add-symbol-file.
+
+
+ When you want to load in a new version of the module, you need to get
+ gdb to forget about the old one. The only way I've found to do that
+ is to tell gdb to forget about all symbols that it knows about:
+
+
+ (UML gdb) symbol-file
+
+
+
+
+ Then reload the symbols from the kernel binary:
+
+
+ (UML gdb) symbol-file /path/to/kernel
+
+
+
+
+ and repeat the process above. You'll also need to re-enable break-
+ points. They were disabled when you dumped all the symbols because
+ gdb couldn't figure out where they should go.
+
+
+
+ 1111..55.. AAttttaacchhiinngg ggddbb ttoo tthhee kkeerrnneell
+
+ If you don't have the kernel running under gdb, you can attach gdb to
+ it later by sending the tracing thread a SIGUSR1. The first line of
+ the console output identifies its pid:
+ tracing thread pid = 20093
+
+
+
+
+ When you send it the signal:
+
+
+ host% kill -USR1 20093
+
+
+
+
+ you will get an xterm with gdb running in it.
+
+
+ If you have the mconsole compiled into UML, then the mconsole client
+ can be used to start gdb:
+
+
+ (mconsole) (mconsole) config gdb=xterm
+
+
+
+
+ will fire up an xterm with gdb running in it.
+
+
+
+ 1111..66.. UUssiinngg aalltteerrnnaattee ddeebbuuggggeerrss
+
+ UML has support for attaching to an already running debugger rather
+ than starting gdb itself. This is present in CVS as of 17 Apr 2001.
+ I sent it to Alan for inclusion in the ac tree, and it will be in my
+ 2.4.4 release.
+
+
+ This is useful when gdb is a subprocess of some UI, such as emacs or
+ ddd. It can also be used to run debuggers other than gdb on UML.
+ Below is an example of using strace as an alternate debugger.
+
+
+ To do this, you need to get the pid of the debugger and pass it in
+ with the
+
+
+ If you are using gdb under some UI, then tell it to 'att 1', and
+ you'll find yourself attached to UML.
+
+
+ If you are using something other than gdb as your debugger, then
+ you'll need to get it to do the equivalent of 'att 1' if it doesn't do
+ it automatically.
+
+
+ An example of an alternate debugger is strace. You can strace the
+ actual kernel as follows:
+
+ +o Run the following in a shell
+
+
+ host%
+ sh -c 'echo pid=$$; echo -n hit return; read x; exec strace -p 1 -o strace.out'
+
+
+
+ +o Run UML with 'debug' and 'gdb-pid=<pid>' with the pid printed out
+ by the previous command
+
+ +o Hit return in the shell, and UML will start running, and strace
+ output will start accumulating in the output file.
+
+ Note that this is different from running
+
+
+ host% strace ./linux
+
+
+
+
+ That will strace only the main UML thread, the tracing thread, which
+ doesn't do any of the actual kernel work. It just oversees the vir-
+ tual machine. In contrast, using strace as described above will show
+ you the low-level activity of the virtual machine.
+
+
+
+
+
+ 1122.. KKeerrnneell ddeebbuuggggiinngg eexxaammpplleess
+
+ 1122..11.. TThhee ccaassee ooff tthhee hhuunngg ffsscckk
+
+ When booting up the kernel, fsck failed, and dropped me into a shell
+ to fix things up. I ran fsck -y, which hung:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Setting hostname uml [ OK ]
+ Checking root filesystem
+ /dev/fhd0 was not cleanly unmounted, check forced.
+ Error reading block 86894 (Attempt to read block from filesystem resulted in short read) while reading indirect blocks of inode 19780.
+
+ /dev/fhd0: UNEXPECTED INCONSISTENCY; RUN fsck MANUALLY.
+ (i.e., without -a or -p options)
+ [ FAILED ]
+
+ *** An error occurred during the file system check.
+ *** Dropping you to a shell; the system will reboot
+ *** when you leave the shell.
+ Give root password for maintenance
+ (or type Control-D for normal startup):
+
+ [root@uml /root]# fsck -y /dev/fhd0
+ fsck -y /dev/fhd0
+ Parallelizing fsck version 1.14 (9-Jan-1999)
+ e2fsck 1.14, 9-Jan-1999 for EXT2 FS 0.5b, 95/08/09
+ /dev/fhd0 contains a file system with errors, check forced.
+ Pass 1: Checking inodes, blocks, and sizes
+ Error reading block 86894 (Attempt to read block from filesystem resulted in short read) while reading indirect blocks of inode 19780. Ignore error? yes
+
+ Inode 19780, i_blocks is 1548, should be 540. Fix? yes
+
+ Pass 2: Checking directory structure
+ Error reading block 49405 (Attempt to read block from filesystem resulted in short read). Ignore error? yes
+
+ Directory inode 11858, block 0, offset 0: directory corrupted
+ Salvage? yes
+
+ Missing '.' in directory inode 11858.
+ Fix? yes
+
+ Missing '..' in directory inode 11858.
+ Fix? yes
+
+
+
+
+
+ The standard drill in this sort of situation is to fire up gdb on the
+ signal thread, which, in this case, was pid 1935. In another window,
+ I run gdb and attach pid 1935.
+
+
+
+
+ ~/linux/2.3.26/um 1016: gdb linux
+ GNU gdb 4.17.0.11 with Linux support
+ Copyright 1998 Free Software Foundation, Inc.
+ GDB is free software, covered by the GNU General Public License, and you are
+ welcome to change it and/or distribute copies of it under certain conditions.
+ Type "show copying" to see the conditions.
+ There is absolutely no warranty for GDB. Type "show warranty" for details.
+ This GDB was configured as "i386-redhat-linux"...
+
+ (gdb) att 1935
+ Attaching to program `/home/dike/linux/2.3.26/um/linux', Pid 1935
+ 0x100756d9 in __wait4 ()
+
+
+
+
+
+
+ Let's see what's currently running:
+
+
+
+ (gdb) p current_task.pid
+ $1 = 0
+
+
+
+
+
+ It's the idle thread, which means that fsck went to sleep for some
+ reason and never woke up.
+
+
+ Let's guess that the last process in the process list is fsck:
+
+
+
+ (gdb) p current_task.prev_task.comm
+ $13 = "fsck.ext2\000\000\000\000\000\000"
+
+
+
+
+
+ It is, so let's see what it thinks it's up to:
+
+
+
+ (gdb) p current_task.prev_task.thread
+ $14 = {extern_pid = 1980, tracing = 0, want_tracing = 0, forking = 0,
+ kernel_stack_page = 0, signal_stack = 1342627840, syscall = {id = 4, args = {
+ 3, 134973440, 1024, 0, 1024}, have_result = 0, result = 50590720},
+ request = {op = 2, u = {exec = {ip = 1350467584, sp = 2952789424}, fork = {
+ regs = {1350467584, 2952789424, 0 <repeats 15 times>}, sigstack = 0,
+ pid = 0}, switch_to = 0x507e8000, thread = {proc = 0x507e8000,
+ arg = 0xaffffdb0, flags = 0, new_pid = 0}, input_request = {
+ op = 1350467584, fd = -1342177872, proc = 0, pid = 0}}}}
+
+
+
+
+
+ The interesting things here are the fact that its .thread.syscall.id
+ is __NR_write (see the big switch in arch/um/kernel/syscall_kern.c or
+ the defines in include/asm-um/arch/unistd.h), and that it never
+ returned. Also, its .request.op is OP_SWITCH (see
+ arch/um/include/user_util.h). These mean that it went into a write,
+ and, for some reason, called schedule().
+
+
+ The fact that it never returned from write means that its stack should
+ be fairly interesting. Its pid is 1980 (.thread.extern_pid). That
+ process is being ptraced by the signal thread, so it must be detached
+ before gdb can attach it:
+
+
+
+
+
+
+
+
+
+
+ (gdb) call detach(1980)
+
+ Program received signal SIGSEGV, Segmentation fault.
+ <function called from gdb>
+ The program being debugged stopped while in a function called from GDB.
+ When the function (detach) is done executing, GDB will silently
+ stop (instead of continuing to evaluate the expression containing
+ the function call).
+ (gdb) call detach(1980)
+ $15 = 0
+
+
+
+
+
+ The first detach segfaults for some reason, and the second one
+ succeeds.
+
+
+ Now I detach from the signal thread, attach to the fsck thread, and
+ look at its stack:
+
+
+ (gdb) det
+ Detaching from program: /home/dike/linux/2.3.26/um/linux Pid 1935
+ (gdb) att 1980
+ Attaching to program `/home/dike/linux/2.3.26/um/linux', Pid 1980
+ 0x10070451 in __kill ()
+ (gdb) bt
+ #0 0x10070451 in __kill ()
+ #1 0x10068ccd in usr1_pid (pid=1980) at process.c:30
+ #2 0x1006a03f in _switch_to (prev=0x50072000, next=0x507e8000)
+ at process_kern.c:156
+ #3 0x1006a052 in switch_to (prev=0x50072000, next=0x507e8000, last=0x50072000)
+ at process_kern.c:161
+ #4 0x10001d12 in schedule () at sched.c:777
+ #5 0x1006a744 in __down (sem=0x507d241c) at semaphore.c:71
+ #6 0x1006aa10 in __down_failed () at semaphore.c:157
+ #7 0x1006c5d8 in segv_handler (sc=0x5006e940) at trap_user.c:174
+ #8 0x1006c5ec in kern_segv_handler (sig=11) at trap_user.c:182
+ #9 <signal handler called>
+ #10 0x10155404 in errno ()
+ #11 0x1006c0aa in segv (address=1342179328, is_write=2) at trap_kern.c:50
+ #12 0x1006c5d8 in segv_handler (sc=0x5006eaf8) at trap_user.c:174
+ #13 0x1006c5ec in kern_segv_handler (sig=11) at trap_user.c:182
+ #14 <signal handler called>
+ #15 0xc0fd in ?? ()
+ #16 0x10016647 in sys_write (fd=3,
+ buf=0x80b8800 <Address 0x80b8800 out of bounds>, count=1024)
+ at read_write.c:159
+ #17 0x1006d5b3 in execute_syscall (syscall=4, args=0x5006ef08)
+ at syscall_kern.c:254
+ #18 0x1006af87 in really_do_syscall (sig=12) at syscall_user.c:35
+ #19 <signal handler called>
+ #20 0x400dc8b0 in ?? ()
+
+
+
+
+
+ The interesting things here are :
+
+ +o There are two segfaults on this stack (frames 9 and 14)
+
+ +o The first faulting address (frame 11) is 0x50000800
+
+ (gdb) p (void *)1342179328
+ $16 = (void *) 0x50000800
+
+
+
+
+
+ The initial faulting address is interesting because it is on the idle
+ thread's stack. I had been seeing the idle thread segfault for no
+ apparent reason, and the cause looked like stack corruption. In hopes
+ of catching the culprit in the act, I had turned off all protections
+ to that stack while the idle thread wasn't running. This apparently
+ tripped that trap.
+
+
+ However, the more immediate problem is that second segfault and I'm
+ going to concentrate on that. First, I want to see where the fault
+ happened, so I have to go look at the sigcontent struct in frame 8:
+
+
+
+ (gdb) up
+ #1 0x10068ccd in usr1_pid (pid=1980) at process.c:30
+ 30 kill(pid, SIGUSR1);
+ (gdb)
+ #2 0x1006a03f in _switch_to (prev=0x50072000, next=0x507e8000)
+ at process_kern.c:156
+ 156 usr1_pid(getpid());
+ (gdb)
+ #3 0x1006a052 in switch_to (prev=0x50072000, next=0x507e8000, last=0x50072000)
+ at process_kern.c:161
+ 161 _switch_to(prev, next);
+ (gdb)
+ #4 0x10001d12 in schedule () at sched.c:777
+ 777 switch_to(prev, next, prev);
+ (gdb)
+ #5 0x1006a744 in __down (sem=0x507d241c) at semaphore.c:71
+ 71 schedule();
+ (gdb)
+ #6 0x1006aa10 in __down_failed () at semaphore.c:157
+ 157 }
+ (gdb)
+ #7 0x1006c5d8 in segv_handler (sc=0x5006e940) at trap_user.c:174
+ 174 segv(sc->cr2, sc->err & 2);
+ (gdb)
+ #8 0x1006c5ec in kern_segv_handler (sig=11) at trap_user.c:182
+ 182 segv_handler(sc);
+ (gdb) p *sc
+ Cannot access memory at address 0x0.
+
+
+
+
+ That's not very useful, so I'll try a more manual method:
+
+
+ (gdb) p *((struct sigcontext *) (&sig + 1))
+ $19 = {gs = 0, __gsh = 0, fs = 0, __fsh = 0, es = 43, __esh = 0, ds = 43,
+ __dsh = 0, edi = 1342179328, esi = 1350378548, ebp = 1342630440,
+ esp = 1342630420, ebx = 1348150624, edx = 1280, ecx = 0, eax = 0,
+ trapno = 14, err = 4, eip = 268480945, cs = 35, __csh = 0, eflags = 66118,
+ esp_at_signal = 1342630420, ss = 43, __ssh = 0, fpstate = 0x0, oldmask = 0,
+ cr2 = 1280}
+
+
+
+ The ip is in handle_mm_fault:
+
+
+ (gdb) p (void *)268480945
+ $20 = (void *) 0x1000b1b1
+ (gdb) i sym $20
+ handle_mm_fault + 57 in section .text
+
+
+
+
+
+ Specifically, it's in pte_alloc:
+
+
+ (gdb) i line *$20
+ Line 124 of "/home/dike/linux/2.3.26/um/include/asm/pgalloc.h"
+ starts at address 0x1000b1b1 <handle_mm_fault+57>
+ and ends at 0x1000b1b7 <handle_mm_fault+63>.
+
+
+
+
+
+ To find where in handle_mm_fault this is, I'll jump forward in the
+ code until I see an address in that procedure:
+
+
+
+ (gdb) i line *0x1000b1c0
+ Line 126 of "/home/dike/linux/2.3.26/um/include/asm/pgalloc.h"
+ starts at address 0x1000b1b7 <handle_mm_fault+63>
+ and ends at 0x1000b1c3 <handle_mm_fault+75>.
+ (gdb) i line *0x1000b1d0
+ Line 131 of "/home/dike/linux/2.3.26/um/include/asm/pgalloc.h"
+ starts at address 0x1000b1d0 <handle_mm_fault+88>
+ and ends at 0x1000b1da <handle_mm_fault+98>.
+ (gdb) i line *0x1000b1e0
+ Line 61 of "/home/dike/linux/2.3.26/um/include/asm/pgalloc.h"
+ starts at address 0x1000b1da <handle_mm_fault+98>
+ and ends at 0x1000b1e1 <handle_mm_fault+105>.
+ (gdb) i line *0x1000b1f0
+ Line 134 of "/home/dike/linux/2.3.26/um/include/asm/pgalloc.h"
+ starts at address 0x1000b1f0 <handle_mm_fault+120>
+ and ends at 0x1000b200 <handle_mm_fault+136>.
+ (gdb) i line *0x1000b200
+ Line 135 of "/home/dike/linux/2.3.26/um/include/asm/pgalloc.h"
+ starts at address 0x1000b200 <handle_mm_fault+136>
+ and ends at 0x1000b208 <handle_mm_fault+144>.
+ (gdb) i line *0x1000b210
+ Line 139 of "/home/dike/linux/2.3.26/um/include/asm/pgalloc.h"
+ starts at address 0x1000b210 <handle_mm_fault+152>
+ and ends at 0x1000b219 <handle_mm_fault+161>.
+ (gdb) i line *0x1000b220
+ Line 1168 of "memory.c" starts at address 0x1000b21e <handle_mm_fault+166>
+ and ends at 0x1000b222 <handle_mm_fault+170>.
+
+
+
+
+
+ Something is apparently wrong with the page tables or vma_structs, so
+ lets go back to frame 11 and have a look at them:
+
+
+
+ #11 0x1006c0aa in segv (address=1342179328, is_write=2) at trap_kern.c:50
+ 50 handle_mm_fault(current, vma, address, is_write);
+ (gdb) call pgd_offset_proc(vma->vm_mm, address)
+ $22 = (pgd_t *) 0x80a548c
+
+
+
+
+
+ That's pretty bogus. Page tables aren't supposed to be in process
+ text or data areas. Let's see what's in the vma:
+
+
+ (gdb) p *vma
+ $23 = {vm_mm = 0x507d2434, vm_start = 0, vm_end = 134512640,
+ vm_next = 0x80a4f8c, vm_page_prot = {pgprot = 0}, vm_flags = 31200,
+ vm_avl_height = 2058, vm_avl_left = 0x80a8c94, vm_avl_right = 0x80d1000,
+ vm_next_share = 0xaffffdb0, vm_pprev_share = 0xaffffe63,
+ vm_ops = 0xaffffe7a, vm_pgoff = 2952789626, vm_file = 0xafffffec,
+ vm_private_data = 0x62}
+ (gdb) p *vma.vm_mm
+ $24 = {mmap = 0x507d2434, mmap_avl = 0x0, mmap_cache = 0x8048000,
+ pgd = 0x80a4f8c, mm_users = {counter = 0}, mm_count = {counter = 134904288},
+ map_count = 134909076, mmap_sem = {count = {counter = 135073792},
+ sleepers = -1342177872, wait = {lock = <optimized out or zero length>,
+ task_list = {next = 0xaffffe63, prev = 0xaffffe7a},
+ __magic = -1342177670, __creator = -1342177300}, __magic = 98},
+ page_table_lock = {}, context = 138, start_code = 0, end_code = 0,
+ start_data = 0, end_data = 0, start_brk = 0, brk = 0, start_stack = 0,
+ arg_start = 0, arg_end = 0, env_start = 0, env_end = 0, rss = 1350381536,
+ total_vm = 0, locked_vm = 0, def_flags = 0, cpu_vm_mask = 0, swap_cnt = 0,
+ swap_address = 0, segments = 0x0}
+
+
+
+
+
+ This also pretty bogus. With all of the 0x80xxxxx and 0xaffffxxx
+ addresses, this is looking like a stack was plonked down on top of
+ these structures. Maybe it's a stack overflow from the next page:
+
+
+
+ (gdb) p vma
+ $25 = (struct vm_area_struct *) 0x507d2434
+
+
+
+
+
+ That's towards the lower quarter of the page, so that would have to
+ have been pretty heavy stack overflow:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ (gdb) x/100x $25
+ 0x507d2434: 0x507d2434 0x00000000 0x08048000 0x080a4f8c
+ 0x507d2444: 0x00000000 0x080a79e0 0x080a8c94 0x080d1000
+ 0x507d2454: 0xaffffdb0 0xaffffe63 0xaffffe7a 0xaffffe7a
+ 0x507d2464: 0xafffffec 0x00000062 0x0000008a 0x00000000
+ 0x507d2474: 0x00000000 0x00000000 0x00000000 0x00000000
+ 0x507d2484: 0x00000000 0x00000000 0x00000000 0x00000000
+ 0x507d2494: 0x00000000 0x00000000 0x507d2fe0 0x00000000
+ 0x507d24a4: 0x00000000 0x00000000 0x00000000 0x00000000
+ 0x507d24b4: 0x00000000 0x00000000 0x00000000 0x00000000
+ 0x507d24c4: 0x00000000 0x00000000 0x00000000 0x00000000
+ 0x507d24d4: 0x00000000 0x00000000 0x00000000 0x00000000
+ 0x507d24e4: 0x00000000 0x00000000 0x00000000 0x00000000
+ 0x507d24f4: 0x00000000 0x00000000 0x00000000 0x00000000
+ 0x507d2504: 0x00000000 0x00000000 0x00000000 0x00000000
+ 0x507d2514: 0x00000000 0x00000000 0x00000000 0x00000000
+ 0x507d2524: 0x00000000 0x00000000 0x00000000 0x00000000
+ 0x507d2534: 0x00000000 0x00000000 0x507d25dc 0x00000000
+ 0x507d2544: 0x00000000 0x00000000 0x00000000 0x00000000
+ 0x507d2554: 0x00000000 0x00000000 0x00000000 0x00000000
+ 0x507d2564: 0x00000000 0x00000000 0x00000000 0x00000000
+ 0x507d2574: 0x00000000 0x00000000 0x00000000 0x00000000
+ 0x507d2584: 0x00000000 0x00000000 0x00000000 0x00000000
+ 0x507d2594: 0x00000000 0x00000000 0x00000000 0x00000000
+ 0x507d25a4: 0x00000000 0x00000000 0x00000000 0x00000000
+ 0x507d25b4: 0x00000000 0x00000000 0x00000000 0x00000000
+
+
+
+
+
+ It's not stack overflow. The only "stack-like" piece of this data is
+ the vma_struct itself.
+
+
+ At this point, I don't see any avenues to pursue, so I just have to
+ admit that I have no idea what's going on. What I will do, though, is
+ stick a trap on the segfault handler which will stop if it sees any
+ writes to the idle thread's stack. That was the thing that happened
+ first, and it may be that if I can catch it immediately, what's going
+ on will be somewhat clearer.
+
+
+ 1122..22.. EEppiissooddee 22:: TThhee ccaassee ooff tthhee hhuunngg ffsscckk
+
+ After setting a trap in the SEGV handler for accesses to the signal
+ thread's stack, I reran the kernel.
+
+
+ fsck hung again, this time by hitting the trap:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Setting hostname uml [ OK ]
+ Checking root filesystem
+ /dev/fhd0 contains a file system with errors, check forced.
+ Error reading block 86894 (Attempt to read block from filesystem resulted in short read) while reading indirect blocks of inode 19780.
+
+ /dev/fhd0: UNEXPECTED INCONSISTENCY; RUN fsck MANUALLY.
+ (i.e., without -a or -p options)
+ [ FAILED ]
+
+ *** An error occurred during the file system check.
+ *** Dropping you to a shell; the system will reboot
+ *** when you leave the shell.
+ Give root password for maintenance
+ (or type Control-D for normal startup):
+
+ [root@uml /root]# fsck -y /dev/fhd0
+ fsck -y /dev/fhd0
+ Parallelizing fsck version 1.14 (9-Jan-1999)
+ e2fsck 1.14, 9-Jan-1999 for EXT2 FS 0.5b, 95/08/09
+ /dev/fhd0 contains a file system with errors, check forced.
+ Pass 1: Checking inodes, blocks, and sizes
+ Error reading block 86894 (Attempt to read block from filesystem resulted in short read) while reading indirect blocks of inode 19780. Ignore error? yes
+
+ Pass 2: Checking directory structure
+ Error reading block 49405 (Attempt to read block from filesystem resulted in short read). Ignore error? yes
+
+ Directory inode 11858, block 0, offset 0: directory corrupted
+ Salvage? yes
+
+ Missing '.' in directory inode 11858.
+ Fix? yes
+
+ Missing '..' in directory inode 11858.
+ Fix? yes
+
+ Untested (4127) [100fe44c]: trap_kern.c line 31
+
+
+
+
+
+ I need to get the signal thread to detach from pid 4127 so that I can
+ attach to it with gdb. This is done by sending it a SIGUSR1, which is
+ caught by the signal thread, which detaches the process:
+
+
+ kill -USR1 4127
+
+
+
+
+
+ Now I can run gdb on it:
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ~/linux/2.3.26/um 1034: gdb linux
+ GNU gdb 4.17.0.11 with Linux support
+ Copyright 1998 Free Software Foundation, Inc.
+ GDB is free software, covered by the GNU General Public License, and you are
+ welcome to change it and/or distribute copies of it under certain conditions.
+ Type "show copying" to see the conditions.
+ There is absolutely no warranty for GDB. Type "show warranty" for details.
+ This GDB was configured as "i386-redhat-linux"...
+ (gdb) att 4127
+ Attaching to program `/home/dike/linux/2.3.26/um/linux', Pid 4127
+ 0x10075891 in __libc_nanosleep ()
+
+
+
+
+
+ The backtrace shows that it was in a write and that the fault address
+ (address in frame 3) is 0x50000800, which is right in the middle of
+ the signal thread's stack page:
+
+
+ (gdb) bt
+ #0 0x10075891 in __libc_nanosleep ()
+ #1 0x1007584d in __sleep (seconds=1000000)
+ at ../sysdeps/unix/sysv/linux/sleep.c:78
+ #2 0x1006ce9a in stop () at user_util.c:191
+ #3 0x1006bf88 in segv (address=1342179328, is_write=2) at trap_kern.c:31
+ #4 0x1006c628 in segv_handler (sc=0x5006eaf8) at trap_user.c:174
+ #5 0x1006c63c in kern_segv_handler (sig=11) at trap_user.c:182
+ #6 <signal handler called>
+ #7 0xc0fd in ?? ()
+ #8 0x10016647 in sys_write (fd=3, buf=0x80b8800 "R.", count=1024)
+ at read_write.c:159
+ #9 0x1006d603 in execute_syscall (syscall=4, args=0x5006ef08)
+ at syscall_kern.c:254
+ #10 0x1006af87 in really_do_syscall (sig=12) at syscall_user.c:35
+ #11 <signal handler called>
+ #12 0x400dc8b0 in ?? ()
+ #13 <signal handler called>
+ #14 0x400dc8b0 in ?? ()
+ #15 0x80545fd in ?? ()
+ #16 0x804daae in ?? ()
+ #17 0x8054334 in ?? ()
+ #18 0x804d23e in ?? ()
+ #19 0x8049632 in ?? ()
+ #20 0x80491d2 in ?? ()
+ #21 0x80596b5 in ?? ()
+ (gdb) p (void *)1342179328
+ $3 = (void *) 0x50000800
+
+
+
+
+
+ Going up the stack to the segv_handler frame and looking at where in
+ the code the access happened shows that it happened near line 110 of
+ block_dev.c:
+
+
+
+
+
+
+
+
+
+ (gdb) up
+ #1 0x1007584d in __sleep (seconds=1000000)
+ at ../sysdeps/unix/sysv/linux/sleep.c:78
+ ../sysdeps/unix/sysv/linux/sleep.c:78: No such file or directory.
+ (gdb)
+ #2 0x1006ce9a in stop () at user_util.c:191
+ 191 while(1) sleep(1000000);
+ (gdb)
+ #3 0x1006bf88 in segv (address=1342179328, is_write=2) at trap_kern.c:31
+ 31 KERN_UNTESTED();
+ (gdb)
+ #4 0x1006c628 in segv_handler (sc=0x5006eaf8) at trap_user.c:174
+ 174 segv(sc->cr2, sc->err & 2);
+ (gdb) p *sc
+ $1 = {gs = 0, __gsh = 0, fs = 0, __fsh = 0, es = 43, __esh = 0, ds = 43,
+ __dsh = 0, edi = 1342179328, esi = 134973440, ebp = 1342631484,
+ esp = 1342630864, ebx = 256, edx = 0, ecx = 256, eax = 1024, trapno = 14,
+ err = 6, eip = 268550834, cs = 35, __csh = 0, eflags = 66070,
+ esp_at_signal = 1342630864, ss = 43, __ssh = 0, fpstate = 0x0, oldmask = 0,
+ cr2 = 1342179328}
+ (gdb) p (void *)268550834
+ $2 = (void *) 0x1001c2b2
+ (gdb) i sym $2
+ block_write + 1090 in section .text
+ (gdb) i line *$2
+ Line 209 of "/home/dike/linux/2.3.26/um/include/asm/arch/string.h"
+ starts at address 0x1001c2a1 <block_write+1073>
+ and ends at 0x1001c2bf <block_write+1103>.
+ (gdb) i line *0x1001c2c0
+ Line 110 of "block_dev.c" starts at address 0x1001c2bf <block_write+1103>
+ and ends at 0x1001c2e3 <block_write+1139>.
+
+
+
+
+
+ Looking at the source shows that the fault happened during a call to
+ copy_to_user to copy the data into the kernel:
+
+
+ 107 count -= chars;
+ 108 copy_from_user(p,buf,chars);
+ 109 p += chars;
+ 110 buf += chars;
+
+
+
+
+
+ p is the pointer which must contain 0x50000800, since buf contains
+ 0x80b8800 (frame 8 above). It is defined as:
+
+
+ p = offset + bh->b_data;
+
+
+
+
+
+ I need to figure out what bh is, and it just so happens that bh is
+ passed as an argument to mark_buffer_uptodate and mark_buffer_dirty a
+ few lines later, so I do a little disassembly:
+
+
+
+
+ (gdb) disas 0x1001c2bf 0x1001c2e0
+ Dump of assembler code from 0x1001c2bf to 0x1001c2d0:
+ 0x1001c2bf <block_write+1103>: addl %eax,0xc(%ebp)
+ 0x1001c2c2 <block_write+1106>: movl 0xfffffdd4(%ebp),%edx
+ 0x1001c2c8 <block_write+1112>: btsl $0x0,0x18(%edx)
+ 0x1001c2cd <block_write+1117>: btsl $0x1,0x18(%edx)
+ 0x1001c2d2 <block_write+1122>: sbbl %ecx,%ecx
+ 0x1001c2d4 <block_write+1124>: testl %ecx,%ecx
+ 0x1001c2d6 <block_write+1126>: jne 0x1001c2e3 <block_write+1139>
+ 0x1001c2d8 <block_write+1128>: pushl $0x0
+ 0x1001c2da <block_write+1130>: pushl %edx
+ 0x1001c2db <block_write+1131>: call 0x1001819c <__mark_buffer_dirty>
+ End of assembler dump.
+
+
+
+
+
+ At that point, bh is in %edx (address 0x1001c2da), which is calculated
+ at 0x1001c2c2 as %ebp + 0xfffffdd4, so I figure exactly what that is,
+ taking %ebp from the sigcontext_struct above:
+
+
+ (gdb) p (void *)1342631484
+ $5 = (void *) 0x5006ee3c
+ (gdb) p 0x5006ee3c+0xfffffdd4
+ $6 = 1342630928
+ (gdb) p (void *)$6
+ $7 = (void *) 0x5006ec10
+ (gdb) p *((void **)$7)
+ $8 = (void *) 0x50100200
+
+
+
+
+
+ Now, I look at the structure to see what's in it, and particularly,
+ what its b_data field contains:
+
+
+ (gdb) p *((struct buffer_head *)0x50100200)
+ $13 = {b_next = 0x50289380, b_blocknr = 49405, b_size = 1024, b_list = 0,
+ b_dev = 15872, b_count = {counter = 1}, b_rdev = 15872, b_state = 24,
+ b_flushtime = 0, b_next_free = 0x501001a0, b_prev_free = 0x50100260,
+ b_this_page = 0x501001a0, b_reqnext = 0x0, b_pprev = 0x507fcf58,
+ b_data = 0x50000800 "", b_page = 0x50004000,
+ b_end_io = 0x10017f60 <end_buffer_io_sync>, b_dev_id = 0x0,
+ b_rsector = 98810, b_wait = {lock = <optimized out or zero length>,
+ task_list = {next = 0x50100248, prev = 0x50100248}, __magic = 1343226448,
+ __creator = 0}, b_kiobuf = 0x0}
+
+
+
+
+
+ The b_data field is indeed 0x50000800, so the question becomes how
+ that happened. The rest of the structure looks fine, so this probably
+ is not a case of data corruption. It happened on purpose somehow.
+
+
+ The b_page field is a pointer to the page_struct representing the
+ 0x50000000 page. Looking at it shows the kernel's idea of the state
+ of that page:
+
+
+
+ (gdb) p *$13.b_page
+ $17 = {list = {next = 0x50004a5c, prev = 0x100c5174}, mapping = 0x0,
+ index = 0, next_hash = 0x0, count = {counter = 1}, flags = 132, lru = {
+ next = 0x50008460, prev = 0x50019350}, wait = {
+ lock = <optimized out or zero length>, task_list = {next = 0x50004024,
+ prev = 0x50004024}, __magic = 1342193708, __creator = 0},
+ pprev_hash = 0x0, buffers = 0x501002c0, virtual = 1342177280,
+ zone = 0x100c5160}
+
+
+
+
+
+ Some sanity-checking: the virtual field shows the "virtual" address of
+ this page, which in this kernel is the same as its "physical" address,
+ and the page_struct itself should be mem_map[0], since it represents
+ the first page of memory:
+
+
+
+ (gdb) p (void *)1342177280
+ $18 = (void *) 0x50000000
+ (gdb) p mem_map
+ $19 = (mem_map_t *) 0x50004000
+
+
+
+
+
+ These check out fine.
+
+
+ Now to check out the page_struct itself. In particular, the flags
+ field shows whether the page is considered free or not:
+
+
+ (gdb) p (void *)132
+ $21 = (void *) 0x84
+
+
+
+
+
+ The "reserved" bit is the high bit, which is definitely not set, so
+ the kernel considers the signal stack page to be free and available to
+ be used.
+
+
+ At this point, I jump to conclusions and start looking at my early
+ boot code, because that's where that page is supposed to be reserved.
+
+
+ In my setup_arch procedure, I have the following code which looks just
+ fine:
+
+
+
+ bootmap_size = init_bootmem(start_pfn, end_pfn - start_pfn);
+ free_bootmem(__pa(low_physmem) + bootmap_size, high_physmem - low_physmem);
+
+
+
+
+
+ Two stack pages have already been allocated, and low_physmem points to
+ the third page, which is the beginning of free memory.
+ The init_bootmem call declares the entire memory to the boot memory
+ manager, which marks it all reserved. The free_bootmem call frees up
+ all of it, except for the first two pages. This looks correct to me.
+
+
+ So, I decide to see init_bootmem run and make sure that it is marking
+ those first two pages as reserved. I never get that far.
+
+
+ Stepping into init_bootmem, and looking at bootmem_map before looking
+ at what it contains shows the following:
+
+
+
+ (gdb) p bootmem_map
+ $3 = (void *) 0x50000000
+
+
+
+
+
+ Aha! The light dawns. That first page is doing double duty as a
+ stack and as the boot memory map. The last thing that the boot memory
+ manager does is to free the pages used by its memory map, so this page
+ is getting freed even its marked as reserved.
+
+
+ The fix was to initialize the boot memory manager before allocating
+ those two stack pages, and then allocate them through the boot memory
+ manager. After doing this, and fixing a couple of subsequent buglets,
+ the stack corruption problem disappeared.
+
+
+
+
+
+ 1133.. WWhhaatt ttoo ddoo wwhheenn UUMMLL ddooeessnn''tt wwoorrkk
+
+
+
+
+ 1133..11.. SSttrraannggee ccoommppiillaattiioonn eerrrroorrss wwhheenn yyoouu bbuuiilldd ffrroomm ssoouurrccee
+
+ As of test11, it is necessary to have "ARCH=um" in the environment or
+ on the make command line for all steps in building UML, including
+ clean, distclean, or mrproper, config, menuconfig, or xconfig, dep,
+ and linux. If you forget for any of them, the i386 build seems to
+ contaminate the UML build. If this happens, start from scratch with
+
+
+ host%
+ make mrproper ARCH=um
+
+
+
+
+ and repeat the build process with ARCH=um on all the steps.
+
+
+ See ``Compiling the kernel and modules'' for more details.
+
+
+ Another cause of strange compilation errors is building UML in
+ /usr/src/linux. If you do this, the first thing you need to do is
+ clean up the mess you made. The /usr/src/linux/asm link will now
+ point to /usr/src/linux/asm-um. Make it point back to
+ /usr/src/linux/asm-i386. Then, move your UML pool someplace else and
+ build it there. Also see below, where a more specific set of symptoms
+ is described.
+
+
+
+ 1133..22.. UUMMLL hhaannggss oonn bboooott aafftteerr mmoouunnttiinngg ddeevvffss
+
+ The boot looks like this:
+
+
+ VFS: Mounted root (ext2 filesystem) readonly.
+ Mounted devfs on /dev
+
+
+
+
+ You're probably running a recent distribution on an old machine. I
+ saw this with the RH7.1 filesystem running on a Pentium. The shared
+ library loader, ld.so, was executing an instruction (cmove) which the
+ Pentium didn't support. That instruction was apparently added later.
+ If you run UML under the debugger, you'll see the hang caused by one
+ instruction causing an infinite SIGILL stream.
+
+
+ The fix is to boot UML on an older filesystem.
+
+
+
+ 1133..33.. AA vvaarriieettyy ooff ppaanniiccss aanndd hhaannggss wwiitthh //ttmmpp oonn aa rreeiisseerrffss ffiilleessyyss--
+ tteemm
+
+ I saw this on reiserfs 3.5.21 and it seems to be fixed in 3.5.27.
+ Panics preceded by
+
+
+ Detaching pid nnnn
+
+
+
+ are diagnostic of this problem. This is a reiserfs bug which causes a
+ thread to occasionally read stale data from a mmapped page shared with
+ another thread. The fix is to upgrade the filesystem or to have /tmp
+ be an ext2 filesystem.
+
+
+
+ 1133..44.. TThhee ccoommppiillee ffaaiillss wwiitthh eerrrroorrss aabboouutt ccoonnfflliiccttiinngg ttyyppeess ffoorr
+ ''ooppeenn'',, ''dduupp'',, aanndd ''wwaaiittppiidd''
+
+ This happens when you build in /usr/src/linux. The UML build makes
+ the include/asm link point to include/asm-um. /usr/include/asm points
+ to /usr/src/linux/include/asm, so when that link gets moved, files
+ which need to include the asm-i386 versions of headers get the
+ incompatible asm-um versions. The fix is to move the include/asm link
+ back to include/asm-i386 and to do UML builds someplace else.
+
+
+
+ 1133..55.. UUMMLL ddooeessnn''tt wwoorrkk wwhheenn //ttmmpp iiss aann NNFFSS ffiilleessyysstteemm
+
+ This seems to be a similar situation with the resierfs problem above.
+ Some versions of NFS seems not to handle mmap correctly, which UML
+ depends on. The workaround is have /tmp be non-NFS directory.
+
+
+ 1133..66.. UUMMLL hhaannggss oonn bboooott wwhheenn ccoommppiilleedd wwiitthh ggpprrooff ssuuppppoorrtt
+
+ If you build UML with gprof support and, early in the boot, it does
+ this
+
+
+ kernel BUG at page_alloc.c:100!
+
+
+
+
+ you have a buggy gcc. You can work around the problem by removing
+ UM_FASTCALL from CFLAGS in arch/um/Makefile-i386. This will open up
+ another bug, but that one is fairly hard to reproduce.
+
+
+
+ 1133..77.. ssyyssllooggdd ddiieess wwiitthh aa SSIIGGTTEERRMM oonn ssttaarrttuupp
+
+ The exact boot error depends on the distribution that you're booting,
+ but Debian produces this:
+
+
+ /etc/rc2.d/S10sysklogd: line 49: 93 Terminated
+ start-stop-daemon --start --quiet --exec /sbin/syslogd -- $SYSLOGD
+
+
+
+
+ This is a syslogd bug. There's a race between a parent process
+ installing a signal handler and its child sending the signal. See
+ this uml-devel post <http://www.geocrawler.com/lists/3/Source-
+ Forge/709/0/6612801> for the details.
+
+
+
+ 1133..88.. TTUUNN//TTAAPP nneettwwoorrkkiinngg ddooeessnn''tt wwoorrkk oonn aa 22..44 hhoosstt
+
+ There are a couple of problems which were
+ <http://www.geocrawler.com/lists/3/SourceForge/597/0/> name="pointed
+ out"> by Tim Robinson <timro at trkr dot net>
+
+ +o It doesn't work on hosts running 2.4.7 (or thereabouts) or earlier.
+ The fix is to upgrade to something more recent and then read the
+ next item.
+
+ +o If you see
+
+
+ File descriptor in bad state
+
+
+
+ when you bring up the device inside UML, you have a header mismatch
+ between the original kernel and the upgraded one. Make /usr/src/linux
+ point at the new headers. This will only be a problem if you build
+ uml_net yourself.
+
+
+
+ 1133..99.. YYoouu ccaann nneettwwoorrkk ttoo tthhee hhoosstt bbuutt nnoott ttoo ootthheerr mmaacchhiinneess oonn tthhee
+ nneett
+
+ If you can connect to the host, and the host can connect to UML, but
+ you can not connect to any other machines, then you may need to enable
+ IP Masquerading on the host. Usually this is only experienced when
+ using private IP addresses (192.168.x.x or 10.x.x.x) for host/UML
+ networking, rather than the public address space that your host is
+ connected to. UML does not enable IP Masquerading, so you will need
+ to create a static rule to enable it:
+
+
+ host%
+ iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
+
+
+
+
+ Replace eth0 with the interface that you use to talk to the rest of
+ the world.
+
+
+ Documentation on IP Masquerading, and SNAT, can be found at
+ www.netfilter.org <http://www.netfilter.org> .
+
+
+ If you can reach the local net, but not the outside Internet, then
+ that is usually a routing problem. The UML needs a default route:
+
+
+ UML#
+ route add default gw gateway IP
+
+
+
+
+ The gateway IP can be any machine on the local net that knows how to
+ reach the outside world. Usually, this is the host or the local net-
+ work's gateway.
+
+
+ Occasionally, we hear from someone who can reach some machines, but
+ not others on the same net, or who can reach some ports on other
+ machines, but not others. These are usually caused by strange
+ firewalling somewhere between the UML and the other box. You track
+ this down by running tcpdump on every interface the packets travel
+ over and see where they disappear. When you find a machine that takes
+ the packets in, but does not send them onward, that's the culprit.
+
+
+
+ 1133..1100.. II hhaavvee nnoo rroooott aanndd II wwaanntt ttoo ssccrreeaamm
+
+ Thanks to Birgit Wahlich for telling me about this strange one. It
+ turns out that there's a limit of six environment variables on the
+ kernel command line. When that limit is reached or exceeded, argument
+ processing stops, which means that the 'root=' argument that UML
+ usually adds is not seen. So, the filesystem has no idea what the
+ root device is, so it panics.
+
+
+ The fix is to put less stuff on the command line. Glomming all your
+ setup variables into one is probably the best way to go.
+
+
+
+ 1133..1111.. UUMMLL bbuuiilldd ccoonnfflliicctt bbeettwweeeenn ppttrraaccee..hh aanndd uuccoonntteexxtt..hh
+
+ On some older systems, /usr/include/asm/ptrace.h and
+ /usr/include/sys/ucontext.h define the same names. So, when they're
+ included together, the defines from one completely mess up the parsing
+ of the other, producing errors like:
+ /usr/include/sys/ucontext.h:47: parse error before
+ `10'
+
+
+
+
+ plus a pile of warnings.
+
+
+ This is a libc botch, which has since been fixed, and I don't see any
+ way around it besides upgrading.
+
+
+
+ 1133..1122.. TThhee UUMMLL BBooggooMMiippss iiss eexxaaccttllyy hhaallff tthhee hhoosstt''ss BBooggooMMiippss
+
+ On i386 kernels, there are two ways of running the loop that is used
+ to calculate the BogoMips rating, using the TSC if it's there or using
+ a one-instruction loop. The TSC produces twice the BogoMips as the
+ loop. UML uses the loop, since it has nothing resembling a TSC, and
+ will get almost exactly the same BogoMips as a host using the loop.
+ However, on a host with a TSC, its BogoMips will be double the loop
+ BogoMips, and therefore double the UML BogoMips.
+
+
+
+ 1133..1133.. WWhheenn yyoouu rruunn UUMMLL,, iitt iimmmmeeddiiaatteellyy sseeggffaauullttss
+
+ If the host is configured with the 2G/2G address space split, that's
+ why. See ``UML on 2G/2G hosts'' for the details on getting UML to
+ run on your host.
+
+
+
+ 1133..1144.. xxtteerrmmss aappppeeaarr,, tthheenn iimmmmeeddiiaatteellyy ddiissaappppeeaarr
+
+ If you're running an up to date kernel with an old release of
+ uml_utilities, the port-helper program will not work properly, so
+ xterms will exit straight after they appear. The solution is to
+ upgrade to the latest release of uml_utilities. Usually this problem
+ occurs when you have installed a packaged release of UML then compiled
+ your own development kernel without upgrading the uml_utilities from
+ the source distribution.
+
+
+
+ 1133..1155.. AAnnyy ootthheerr ppaanniicc,, hhaanngg,, oorr ssttrraannggee bbeehhaavviioorr
+
+ If you're seeing truly strange behavior, such as hangs or panics that
+ happen in random places, or you try running the debugger to see what's
+ happening and it acts strangely, then it could be a problem in the
+ host kernel. If you're not running a stock Linus or -ac kernel, then
+ try that. An early version of the preemption patch and a 2.4.10 SuSE
+ kernel have caused very strange problems in UML.
+
+
+ Otherwise, let me know about it. Send a message to one of the UML
+ mailing lists - either the developer list - user-mode-linux-devel at
+ lists dot sourceforge dot net (subscription info) or the user list -
+ user-mode-linux-user at lists dot sourceforge do net (subscription
+ info), whichever you prefer. Don't assume that everyone knows about
+ it and that a fix is imminent.
+
+
+ If you want to be super-helpful, read ``Diagnosing Problems'' and
+ follow the instructions contained therein.
+ 1144.. DDiiaaggnnoossiinngg PPrroobblleemmss
+
+
+ If you get UML to crash, hang, or otherwise misbehave, you should
+ report this on one of the project mailing lists, either the developer
+ list - user-mode-linux-devel at lists dot sourceforge dot net
+ (subscription info) or the user list - user-mode-linux-user at lists
+ dot sourceforge dot net (subscription info). When you do, it is
+ likely that I will want more information. So, it would be helpful to
+ read the stuff below, do whatever is applicable in your case, and
+ report the results to the list.
+
+
+ For any diagnosis, you're going to need to build a debugging kernel.
+ The binaries from this site aren't debuggable. If you haven't done
+ this before, read about ``Compiling the kernel and modules'' and
+ ``Kernel debugging'' UML first.
+
+
+ 1144..11.. CCaassee 11 :: NNoorrmmaall kkeerrnneell ppaanniiccss
+
+ The most common case is for a normal thread to panic. To debug this,
+ you will need to run it under the debugger (add 'debug' to the command
+ line). An xterm will start up with gdb running inside it. Continue
+ it when it stops in start_kernel and make it crash. Now ^C gdb and
+
+
+ If the panic was a "Kernel mode fault", then there will be a segv
+ frame on the stack and I'm going to want some more information. The
+ stack might look something like this:
+
+
+ (UML gdb) backtrace
+ #0 0x1009bf76 in __sigprocmask (how=1, set=0x5f347940, oset=0x0)
+ at ../sysdeps/unix/sysv/linux/sigprocmask.c:49
+ #1 0x10091411 in change_sig (signal=10, on=1) at process.c:218
+ #2 0x10094785 in timer_handler (sig=26) at time_kern.c:32
+ #3 0x1009bf38 in __restore ()
+ at ../sysdeps/unix/sysv/linux/i386/sigaction.c:125
+ #4 0x1009534c in segv (address=8, ip=268849158, is_write=2, is_user=0)
+ at trap_kern.c:66
+ #5 0x10095c04 in segv_handler (sig=11) at trap_user.c:285
+ #6 0x1009bf38 in __restore ()
+
+
+
+
+ I'm going to want to see the symbol and line information for the value
+ of ip in the segv frame. In this case, you would do the following:
+
+
+ (UML gdb) i sym 268849158
+
+
+
+
+ and
+
+
+ (UML gdb) i line *268849158
+
+
+
+
+ The reason for this is the __restore frame right above the segv_han-
+ dler frame is hiding the frame that actually segfaulted. So, I have
+ to get that information from the faulting ip.
+
+
+ 1144..22.. CCaassee 22 :: TTrraacciinngg tthhrreeaadd ppaanniiccss
+
+ The less common and more painful case is when the tracing thread
+ panics. In this case, the kernel debugger will be useless because it
+ needs a healthy tracing thread in order to work. The first thing to
+ do is get a backtrace from the tracing thread. This is done by
+ figuring out what its pid is, firing up gdb, and attaching it to that
+ pid. You can figure out the tracing thread pid by looking at the
+ first line of the console output, which will look like this:
+
+
+ tracing thread pid = 15851
+
+
+
+
+ or by running ps on the host and finding the line that looks like
+ this:
+
+
+ jdike 15851 4.5 0.4 132568 1104 pts/0 S 21:34 0:05 ./linux [(tracing thread)]
+
+
+
+
+ If the panic was 'segfault in signals', then follow the instructions
+ above for collecting information about the location of the seg fault.
+
+
+ If the tracing thread flaked out all by itself, then send that
+ backtrace in and wait for our crack debugging team to fix the problem.
+
+
+ 1144..33.. CCaassee 33 :: TTrraacciinngg tthhrreeaadd ppaanniiccss ccaauusseedd bbyy ootthheerr tthhrreeaaddss
+
+ However, there are cases where the misbehavior of another thread
+ caused the problem. The most common panic of this type is:
+
+
+ wait_for_stop failed to wait for <pid> to stop with <signal number>
+
+
+
+
+ In this case, you'll need to get a backtrace from the process men-
+ tioned in the panic, which is complicated by the fact that the kernel
+ debugger is defunct and without some fancy footwork, another gdb can't
+ attach to it. So, this is how the fancy footwork goes:
+
+ In a shell:
+
+
+ host% kill -STOP pid
+
+
+
+
+ Run gdb on the tracing thread as described in case 2 and do:
+
+
+ (host gdb) call detach(pid)
+
+
+ If you get a segfault, do it again. It always works the second time.
+
+ Detach from the tracing thread and attach to that other thread:
+
+
+ (host gdb) detach
+
+
+
+
+
+
+ (host gdb) attach pid
+
+
+
+
+ If gdb hangs when attaching to that process, go back to a shell and
+ do:
+
+
+ host%
+ kill -CONT pid
+
+
+
+
+ And then get the backtrace:
+
+
+ (host gdb) backtrace
+
+
+
+
+
+ 1144..44.. CCaassee 44 :: HHaannggss
+
+ Hangs seem to be fairly rare, but they sometimes happen. When a hang
+ happens, we need a backtrace from the offending process. Run the
+ kernel debugger as described in case 1 and get a backtrace. If the
+ current process is not the idle thread, then send in the backtrace.
+ You can tell that it's the idle thread if the stack looks like this:
+
+
+ #0 0x100b1401 in __libc_nanosleep ()
+ #1 0x100a2885 in idle_sleep (secs=10) at time.c:122
+ #2 0x100a546f in do_idle () at process_kern.c:445
+ #3 0x100a5508 in cpu_idle () at process_kern.c:471
+ #4 0x100ec18f in start_kernel () at init/main.c:592
+ #5 0x100a3e10 in start_kernel_proc (unused=0x0) at um_arch.c:71
+ #6 0x100a383f in signal_tramp (arg=0x100a3dd8) at trap_user.c:50
+
+
+
+
+ If this is the case, then some other process is at fault, and went to
+ sleep when it shouldn't have. Run ps on the host and figure out which
+ process should not have gone to sleep and stayed asleep. Then attach
+ to it with gdb and get a backtrace as described in case 3.
+
+
+
+
+
+
+ 1155.. TThhaannkkss
+
+
+ A number of people have helped this project in various ways, and this
+ page gives recognition where recognition is due.
+
+
+ If you're listed here and you would prefer a real link on your name,
+ or no link at all, instead of the despammed email address pseudo-link,
+ let me know.
+
+
+ If you're not listed here and you think maybe you should be, please
+ let me know that as well. I try to get everyone, but sometimes my
+ bookkeeping lapses and I forget about contributions.
+
+
+ 1155..11.. CCooddee aanndd DDooccuummeennttaattiioonn
+
+ Rusty Russell <rusty at linuxcare.com.au> -
+
+ +o wrote the HOWTO <http://user-mode-
+ linux.sourceforge.net/UserModeLinux-HOWTO.html>
+
+ +o prodded me into making this project official and putting it on
+ SourceForge
+
+ +o came up with the way cool UML logo <http://user-mode-
+ linux.sourceforge.net/uml-small.png>
+
+ +o redid the config process
+
+
+ Peter Moulder <reiter at netspace.net.au> - Fixed my config and build
+ processes, and added some useful code to the block driver
+
+
+ Bill Stearns <wstearns at pobox.com> -
+
+ +o HOWTO updates
+
+ +o lots of bug reports
+
+ +o lots of testing
+
+ +o dedicated a box (uml.ists.dartmouth.edu) to support UML development
+
+ +o wrote the mkrootfs script, which allows bootable filesystems of
+ RPM-based distributions to be cranked out
+
+ +o cranked out a large number of filesystems with said script
+
+
+ Jim Leu <jleu at mindspring.com> - Wrote the virtual ethernet driver
+ and associated usermode tools
+
+ Lars Brinkhoff <http://lars.nocrew.org/> - Contributed the ptrace
+ proxy from his own project <http://a386.nocrew.org/> to allow easier
+ kernel debugging
+
+
+ Andrea Arcangeli <andrea at suse.de> - Redid some of the early boot
+ code so that it would work on machines with Large File Support
+
+
+ Chris Emerson <http://www.chiark.greenend.org.uk/~cemerson/> - Did
+ the first UML port to Linux/ppc
+
+
+ Harald Welte <laforge at gnumonks.org> - Wrote the multicast
+ transport for the network driver
+
+
+ Jorgen Cederlof - Added special file support to hostfs
+
+
+ Greg Lonnon <glonnon at ridgerun dot com> - Changed the ubd driver
+ to allow it to layer a COW file on a shared read-only filesystem and
+ wrote the iomem emulation support
+
+
+ Henrik Nordstrom <http://hem.passagen.se/hno/> - Provided a variety
+ of patches, fixes, and clues
+
+
+ Lennert Buytenhek - Contributed various patches, a rewrite of the
+ network driver, the first implementation of the mconsole driver, and
+ did the bulk of the work needed to get SMP working again.
+
+
+ Yon Uriarte - Fixed the TUN/TAP network backend while I slept.
+
+
+ Adam Heath - Made a bunch of nice cleanups to the initialization code,
+ plus various other small patches.
+
+
+ Matt Zimmerman - Matt volunteered to be the UML Debian maintainer and
+ is doing a real nice job of it. He also noticed and fixed a number of
+ actually and potentially exploitable security holes in uml_net. Plus
+ the occasional patch. I like patches.
+
+
+ James McMechan - James seems to have taken over maintenance of the ubd
+ driver and is doing a nice job of it.
+
+
+ Chandan Kudige - wrote the umlgdb script which automates the reloading
+ of module symbols.
+
+
+ Steve Schmidtke - wrote the UML slirp transport and hostaudio drivers,
+ enabling UML processes to access audio devices on the host. He also
+ submitted patches for the slip transport and lots of other things.
+
+
+ David Coulson <http://davidcoulson.net> -
+
+ +o Set up the usermodelinux.org <http://usermodelinux.org> site,
+ which is a great way of keeping the UML user community on top of
+ UML goings-on.
+
+ +o Site documentation and updates
+
+ +o Nifty little UML management daemon UMLd
+ <http://uml.openconsultancy.com/umld/>
+
+ +o Lots of testing and bug reports
+
+
+
+
+ 1155..22.. FFlluusshhiinngg oouutt bbuuggss
+
+
+
+ +o Yuri Pudgorodsky
+
+ +o Gerald Britton
+
+ +o Ian Wehrman
+
+ +o Gord Lamb
+
+ +o Eugene Koontz
+
+ +o John H. Hartman
+
+ +o Anders Karlsson
+
+ +o Daniel Phillips
+
+ +o John Fremlin
+
+ +o Rainer Burgstaller
+
+ +o James Stevenson
+
+ +o Matt Clay
+
+ +o Cliff Jefferies
+
+ +o Geoff Hoff
+
+ +o Lennert Buytenhek
+
+ +o Al Viro
+
+ +o Frank Klingenhoefer
+
+ +o Livio Baldini Soares
+
+ +o Jon Burgess
+
+ +o Petru Paler
+
+ +o Paul
+
+ +o Chris Reahard
+
+ +o Sverker Nilsson
+
+ +o Gong Su
+
+ +o johan verrept
+
+ +o Bjorn Eriksson
+
+ +o Lorenzo Allegrucci
+
+ +o Muli Ben-Yehuda
+
+ +o David Mansfield
+
+ +o Howard Goff
+
+ +o Mike Anderson
+
+ +o John Byrne
+
+ +o Sapan J. Batia
+
+ +o Iris Huang
+
+ +o Jan Hudec
+
+ +o Voluspa
+
+
+
+
+ 1155..33.. BBuugglleettss aanndd cclleeaann--uuppss
+
+
+
+ +o Dave Zarzycki
+
+ +o Adam Lazur
+
+ +o Boria Feigin
+
+ +o Brian J. Murrell
+
+ +o JS
+
+ +o Roman Zippel
+
+ +o Wil Cooley
+
+ +o Ayelet Shemesh
+
+ +o Will Dyson
+
+ +o Sverker Nilsson
+
+ +o dvorak
+
+ +o v.naga srinivas
+
+ +o Shlomi Fish
+
+ +o Roger Binns
+
+ +o johan verrept
+
+ +o MrChuoi
+
+ +o Peter Cleve
+
+ +o Vincent Guffens
+
+ +o Nathan Scott
+
+ +o Patrick Caulfield
+
+ +o jbearce
+
+ +o Catalin Marinas
+
+ +o Shane Spencer
+
+ +o Zou Min
+
+
+ +o Ryan Boder
+
+ +o Lorenzo Colitti
+
+ +o Gwendal Grignou
+
+ +o Andre' Breiler
+
+ +o Tsutomu Yasuda
+
+
+
+ 1155..44.. CCaassee SSttuuddiieess
+
+
+ +o Jon Wright
+
+ +o William McEwan
+
+ +o Michael Richardson
+
+
+
+ 1155..55.. OOtthheerr ccoonnttrriibbuuttiioonnss
+
+
+ Bill Carr <Bill.Carr at compaq.com> made the Red Hat mkrootfs script
+ work with RH 6.2.
+
+ Michael Jennings <mikejen at hevanet.com> sent in some material which
+ is now gracing the top of the index page <http://user-mode-
+ linux.sourceforge.net/index.html> of this site.
+
+ SGI <http://www.sgi.com> (and more specifically Ralf Baechle <ralf at
+ uni-koblenz.de> ) gave me an account on oss.sgi.com
+ <http://www.oss.sgi.com> . The bandwidth there made it possible to
+ produce most of the filesystems available on the project download
+ page.
+
+ Laurent Bonnaud <Laurent.Bonnaud at inpg.fr> took the old grotty
+ Debian filesystem that I've been distributing and updated it to 2.2.
+ It is now available by itself here.
+
+ Rik van Riel gave me some ftp space on ftp.nl.linux.org so I can make
+ releases even when Sourceforge is broken.
+
+ Rodrigo de Castro looked at my broken pte code and told me what was
+ wrong with it, letting me fix a long-standing (several weeks) and
+ serious set of bugs.
+
+ Chris Reahard built a specialized root filesystem for running a DNS
+ server jailed inside UML. It's available from the download
+ <http://user-mode-linux.sourceforge.net/dl-sf.html> page in the Jail
+ Filesysems section.
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Documentation/usb/dma.txt b/Documentation/usb/dma.txt
new file mode 100644
index 000000000000..fae537186570
--- /dev/null
+++ b/Documentation/usb/dma.txt
@@ -0,0 +1,104 @@
+In Linux 2.5 kernels (and later), USB device drivers have additional control
+over how DMA may be used to perform I/O operations. The APIs are detailed
+in the kernel usb programming guide (kerneldoc, from the source code).
+
+
+API OVERVIEW
+
+The big picture is that USB drivers can continue to ignore most DMA issues,
+though they still must provide DMA-ready buffers (see DMA-mapping.txt).
+That's how they've worked through the 2.4 (and earlier) kernels.
+
+OR: they can now be DMA-aware.
+
+- New calls enable DMA-aware drivers, letting them allocate dma buffers and
+ manage dma mappings for existing dma-ready buffers (see below).
+
+- URBs have an additional "transfer_dma" field, as well as a transfer_flags
+ bit saying if it's valid. (Control requests also needed "setup_dma".)
+
+- "usbcore" will map those DMA addresses, if a DMA-aware driver didn't do it
+ first and set URB_NO_DMA_MAP. HCDs don't manage dma mappings for urbs.
+
+- There's a new "generic DMA API", parts of which are usable by USB device
+ drivers. Never use dma_set_mask() on any USB interface or device; that
+ would potentially break all devices sharing that bus.
+
+
+ELIMINATING COPIES
+
+It's good to avoid making CPUs copy data needlessly. The costs can add up,
+and effects like cache-trashing can impose subtle penalties.
+
+- When you're allocating a buffer for DMA purposes anyway, use the buffer
+ primitives. Think of them as kmalloc and kfree that give you the right
+ kind of addresses to store in urb->transfer_buffer and urb->transfer_dma,
+ while guaranteeing that hidden copies through DMA "bounce" buffers won't
+ slow things down. You'd also set URB_NO_DMA_MAP in urb->transfer_flags:
+
+ void *usb_buffer_alloc (struct usb_device *dev, size_t size,
+ int mem_flags, dma_addr_t *dma);
+
+ void usb_buffer_free (struct usb_device *dev, size_t size,
+ void *addr, dma_addr_t dma);
+
+ The memory buffer returned is "dma-coherent"; sometimes you might need to
+ force a consistent memory access ordering by using memory barriers. It's
+ not using a streaming DMA mapping, so it's good for small transfers on
+ systems where the I/O would otherwise tie up an IOMMU mapping.
+
+ Asking for 1/Nth of a page (as well as asking for N pages) is reasonably
+ space-efficient.
+
+- Devices on some EHCI controllers could handle DMA to/from high memory.
+ Driver probe() routines can notice this using a generic DMA call, then
+ tell higher level code (network, scsi, etc) about it like this:
+
+ if (dma_supported (&intf->dev, 0xffffffffffffffffULL))
+ net->features |= NETIF_F_HIGHDMA;
+
+ That can eliminate dma bounce buffering of requests that originate (or
+ terminate) in high memory, in cases where the buffers aren't allocated
+ with usb_buffer_alloc() but instead are dma-mapped.
+
+
+WORKING WITH EXISTING BUFFERS
+
+Existing buffers aren't usable for DMA without first being mapped into the
+DMA address space of the device.
+
+- When you're using scatterlists, you can map everything at once. On some
+ systems, this kicks in an IOMMU and turns the scatterlists into single
+ DMA transactions:
+
+ int usb_buffer_map_sg (struct usb_device *dev, unsigned pipe,
+ struct scatterlist *sg, int nents);
+
+ void usb_buffer_dmasync_sg (struct usb_device *dev, unsigned pipe,
+ struct scatterlist *sg, int n_hw_ents);
+
+ void usb_buffer_unmap_sg (struct usb_device *dev, unsigned pipe,
+ struct scatterlist *sg, int n_hw_ents);
+
+ It's probably easier to use the new usb_sg_*() calls, which do the DMA
+ mapping and apply other tweaks to make scatterlist i/o be fast.
+
+- Some drivers may prefer to work with the model that they're mapping large
+ buffers, synchronizing their safe re-use. (If there's no re-use, then let
+ usbcore do the map/unmap.) Large periodic transfers make good examples
+ here, since it's cheaper to just synchronize the buffer than to unmap it
+ each time an urb completes and then re-map it on during resubmission.
+
+ These calls all work with initialized urbs: urb->dev, urb->pipe,
+ urb->transfer_buffer, and urb->transfer_buffer_length must all be
+ valid when these calls are used:
+
+ struct urb *usb_buffer_map (struct urb *urb);
+
+ void usb_buffer_dmasync (struct urb *urb);
+
+ void usb_buffer_unmap (struct urb *urb);
+
+ The calls manage urb->transfer_dma for you, and set URB_NO_DMA_MAP so that
+ usbcore won't map or unmap the buffer.
+
diff --git a/Documentation/usb/hotplug.txt b/Documentation/usb/hotplug.txt
index 9e3b8fe50405..62d5860f324e 100644
--- a/Documentation/usb/hotplug.txt
+++ b/Documentation/usb/hotplug.txt
@@ -5,8 +5,8 @@ into the bus with power on. In most cases, users expect the devices to become
immediately usable. That means the system must do many things, including:
- Find a driver that can handle the device. That may involve
- loading a kernel module; newer drivers can use modutils to
- publish their device (and class) support to user utilities.
+ loading a kernel module; newer drivers can use module-init-tools
+ to publish their device (and class) support to user utilities.
- Bind a driver to that device. Bus frameworks do that using a
device driver's probe() routine.
@@ -76,15 +76,15 @@ user mode daemon to detect changes in system configuration.
Currently available policy agent implementations can load drivers for
modules, and can invoke driver-specific setup scripts. The newest ones
-leverage USB modutils support. Later agents might unload drivers.
+leverage USB module-init-tools support. Later agents might unload drivers.
USB MODUTILS SUPPORT
-Current versions of modutils will create a "modules.usbmap" file which
-contains the entries from each driver's MODULE_DEVICE_TABLE. Such files
-can be used by various user mode policy agents to make sure all the right
-driver modules get loaded, either at boot time or later.
+Current versions of module-init-tools will create a "modules.usbmap" file
+which contains the entries from each driver's MODULE_DEVICE_TABLE. Such
+files can be used by various user mode policy agents to make sure all the
+right driver modules get loaded, either at boot time or later.
See <linux/usb.h> for full information about such table entries; or look
at existing drivers. Each table entry describes one or more criteria to
diff --git a/Documentation/usb/usb-serial.txt b/Documentation/usb/usb-serial.txt
index 7e6150c50088..82d73ba58392 100644
--- a/Documentation/usb/usb-serial.txt
+++ b/Documentation/usb/usb-serial.txt
@@ -91,27 +91,27 @@ HandSpring Visor, Palm USB, and Clié USB driver
Kroah-Hartman at greg@kroah.com
-Compaq iPAQ, HP Jornada and Casio EM500 driver
+PocketPC PDA Driver
- This driver can be used to connect to Compaq iPAQ, HP Jornada and Casio EM500
- PDAs running Windows CE 3.0 or PocketPC 2002 using a USB cable/cradle.
- It's very likely that every device supported by ActiveSync USB works with this
- driver. The driver supports the Compaq iPAQ, Jornada 548/568 and the Casio
- EM500 out of the box. For others, please use module parameters to specify
- the product and vendor id. e.g. modprobe ipaq vendor=0x3f0 product=0x1125
+ This driver can be used to connect to Compaq iPAQ, HP Jornada, Casio EM500
+ and other PDAs running Windows CE 3.0 or PocketPC 2002 using a USB
+ cable/cradle.
+ Most devices supported by ActiveSync are supported out of the box.
+ For others, please use module parameters to specify the product and vendor
+ id. e.g. modprobe ipaq vendor=0x3f0 product=0x1125
The driver presents a serial interface (usually on /dev/ttyUSB0) over
- which one may run ppp and establish a TCP/IP link to the iPAQ. Once this
+ which one may run ppp and establish a TCP/IP link to the PDA. Once this
is done, you can transfer files, backup, download email etc. The most
- significant advantage of using USB is speed - you can get 73 to 113
- kbytes/sec for download/upload to the iPAQ.
+ significant advantage of using USB is speed - I can get 73 to 113
+ kbytes/sec for download/upload to my iPAQ.
This driver is only one of a set of components required to utilize
the USB connection. Please visit http://synce.sourceforge.net which
contains the necessary packages and a simple step-by-step howto.
Once connected, you can use Win CE programs like ftpView, Pocket Outlook
- from the iPAQ and xcerdisp, synce utilities from the Linux side.
+ from the PDA and xcerdisp, synce utilities from the Linux side.
To use Pocket IE, follow the instructions given at
http://www.tekguru.co.uk/EM500/usbtonet.htm to achieve the same thing
@@ -126,8 +126,18 @@ Compaq iPAQ, HP Jornada and Casio EM500 driver
If it doesn't work for some reason, load both the usbserial and ipaq module
with the module parameter "debug" set to 1 and examine the system log.
- You can also try soft-resetting your iPAQ before attempting a connection.
-
+ You can also try soft-resetting your PDA before attempting a connection.
+
+ Other functionality may be possible depending on your PDA. According to
+ Wes Cilldhaire <billybobjoehenrybob@hotmail.com>, with the Toshiba E570,
+ ...if you boot into the bootloader (hold down the power when hitting the
+ reset button, continuing to hold onto the power until the bootloader screen
+ is displayed), then put it in the cradle with the ipaq driver loaded, open
+ a terminal on /dev/ttyUSB0, it gives you a "USB Reflash" terminal, which can
+ be used to flash the ROM, as well as the microP code.. so much for needing
+ Toshiba's $350 serial cable for flashing!! :D
+ NOTE: This has NOT been tested. Use at your own risk.
+
For any questions or problems with the driver, please contact Ganesh
Varadarajan <ganesh@veritas.com>
diff --git a/Documentation/video4linux/README.cpia b/Documentation/video4linux/README.cpia
index 521ef795a647..c95e7bbc0fdf 100644
--- a/Documentation/video4linux/README.cpia
+++ b/Documentation/video4linux/README.cpia
@@ -51,9 +51,9 @@ CONFIG_VIDEO_DEV=m
CONFIG_VIDEO_CPIA=m
CONFIG_VIDEO_CPIA_PP=m
-For autoloading of all those modules you need to tell modutils some
-stuff. Add the following line to your modutils config-file
-(e.g. /etc/modules.conf or wherever your distribution does store that
+For autoloading of all those modules you need to tell module-init-tools
+some stuff. Add the following line to your module-init-tools config-file
+(e.g. /etc/modprobe.conf or wherever your distribution does store that
stuff):
options parport_pc io=0x378 irq=7 dma=3
diff --git a/MAINTAINERS b/MAINTAINERS
index 8e382197d494..e8b5a59b5353 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -762,6 +762,15 @@ L: linux-i2c@pelican.tk.uni-linz.ac.at
W: http://www.tk.uni-linz.ac.at/~simon/private/i2c
S: Maintained
+SENSORS DRIVERS
+P: Frodo Looijaard
+M: frodol@dds.nl
+P: Philip Edelbrock
+M: phil@netroedge.com
+L: sensors@stimpy.netroedge.com
+W: http://www.lm-sensors.nu/
+S: Maintained
+
i386 BOOT CODE
P: Riley H. Williams
M: Riley@Williams.Name
diff --git a/arch/i386/Kconfig b/arch/i386/Kconfig
index e55289e7ea33..ddaf6c1e0b16 100644
--- a/arch/i386/Kconfig
+++ b/arch/i386/Kconfig
@@ -39,6 +39,59 @@ source "init/Kconfig"
menu "Processor type and features"
choice
+ prompt "Subarchitecture Type"
+ default PC
+
+config PC
+ bool "IBM PC (and compatible)"
+ help
+ Choose this option if your computer is a standard PC or compatible.
+
+config VOYAGER
+ bool "NCR Voyager"
+ help
+ Voyager is a MCA based 32 way capable SMP architecture proprietary
+ to NCR Corp. Machine classes 345x/35xx/4100/51xx are voyager based.
+
+ *** WARNING ***
+
+ If you do not specifically know you have a Voyager based machine,
+ say N here otherwise the kernel you build will not be bootable.
+
+config X86_NUMAQ
+ bool "IBM/Sequent NUMAQ"
+ help
+ This option is used for getting Linux to run on a (IBM/Sequent) NUMA
+ multiquad box. This changes the way that processors are bootstrapped,
+ and uses Clustered Logical APIC addressing mode instead of Flat Logical.
+ You will need a new lynxer.elf file to flash your firmware with - send
+ email to Martin.Bligh@us.ibm.com
+
+config X86_SUMMIT
+ bool "IBM x440 (Summit/EXA)"
+ help
+ This option is needed for IBM systems that use the Summit/EXA chipset.
+ In particular, it is needed for the x440.
+
+ If you don't have one of these computers, you should say N here.
+
+# Visual Workstation support is utterly broken.
+# If you want to see it working mail an VW540 to hch@infradead.org 8)
+#config X86_VISWS
+# bool "SGI 320/540 (Visual Workstation)"
+# help
+# The SGI Visual Workstation series is an IA32-based workstation
+# based on SGI systems chips with some legacy PC hardware attached.
+#
+# Say Y here to create a kernel to run on the SGI 320 or 540.
+#
+# A kernel compiled for the Visual Workstation will not run on PCs
+# and vice versa. See <file:Documentation/sgi-visws.txt> for details.
+
+endchoice
+
+
+choice
prompt "Processor family"
default M686
@@ -140,6 +193,13 @@ config MK7
some extended instructions, and passes appropriate optimization
flags to GCC.
+config MK8
+ bool "Opteron/Athlon64/Hammer/K8"
+ help
+ Select this for an AMD Opteron or Athlon64 Hammer-family processor. Enables
+ use of some extended instructions, and passes appropriate optimization
+ flags to GCC.
+
config MELAN
bool "Elan"
@@ -200,7 +260,7 @@ config X86_L1_CACHE_SHIFT
int
default "5" if MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCRUSOE || MCYRIXIII || MK6 || MPENTIUMIII || M686 || M586MMX || M586TSC || M586
default "4" if MELAN || M486 || M386
- default "6" if MK7
+ default "6" if MK7 || MK8
default "7" if MPENTIUM4
config RWSEM_GENERIC_SPINLOCK
@@ -255,12 +315,12 @@ config X86_ALIGNMENT_16
config X86_TSC
bool
- depends on MWINCHIP3D || MWINCHIP2 || MCRUSOE || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMIII || M686 || M586MMX || M586TSC
+ depends on MWINCHIP3D || MWINCHIP2 || MCRUSOE || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMIII || M686 || M586MMX || M586TSC || MK8
default y
config X86_GOOD_APIC
bool
- depends on MK7 || MPENTIUM4 || MPENTIUMIII || M686 || M586MMX
+ depends on MK7 || MPENTIUM4 || MPENTIUMIII || M686 || M586MMX || MK8
default y
config X86_INTEL_USERCOPY
@@ -270,7 +330,7 @@ config X86_INTEL_USERCOPY
config X86_USE_PPRO_CHECKSUM
bool
- depends on MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMIII || M686
+ depends on MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMIII || M686 || MK8
default y
config X86_USE_3DNOW
@@ -283,6 +343,16 @@ config X86_OOSTORE
depends on MWINCHIP3D || MWINCHIP2 || MWINCHIPC6
default y
+config X86_PREFETCH
+ bool
+ depends on MPENTIUMIII || MP4
+ default y
+
+config X86_SSE2
+ bool
+ depends on MK8 || MPENTIUM4
+ default y
+
config HUGETLB_PAGE
bool "Huge TLB Page Support"
help
@@ -337,6 +407,7 @@ config PREEMPT
config X86_UP_APIC
bool "Local APIC support on uniprocessors" if !SMP
+ depends on !VOYAGER
---help---
A local APIC (Advanced Programmable Interrupt Controller) is an
integrated interrupt controller in the CPU. If you have a single-CPU
@@ -385,33 +456,9 @@ config NR_CPUS
This is purely to save memory - each supported CPU adds
approximately eight kilobytes to the kernel image.
-config X86_NUMA
- bool "Multi-node NUMA system support"
- depends on SMP
-
-#Platform Choices
-config X86_NUMAQ
- bool "Multiquad (IBM/Sequent) NUMAQ support"
- depends on X86_NUMA
- help
- This option is used for getting Linux to run on a (IBM/Sequent) NUMA
- multiquad box. This changes the way that processors are bootstrapped,
- and uses Clustered Logical APIC addressing mode instead of Flat Logical.
- You will need a new lynxer.elf file to flash your firmware with - send
- email to Martin.Bligh@us.ibm.com
-
-config X86_SUMMIT
- bool "IBM x440 (Summit/EXA) support"
- depends on X86_NUMA
- help
- This option is needed for IBM systems that use the Summit/EXA chipset.
- In particular, it is needed for the x440.
-
- If you don't have one of these computers, you should say N here.
-
config CLUSTERED_APIC
bool
- depends on X86_NUMA && (X86_NUMAQ || X86_SUMMIT)
+ depends on X86_NUMAQ || X86_SUMMIT
default y
# Common NUMA Features
@@ -690,6 +737,7 @@ endmenu
menu "Power management options (ACPI, APM)"
+ depends on !VOYAGER
config PM
bool "Power Management support"
@@ -990,9 +1038,6 @@ endmenu
menu "Bus options (PCI, PCMCIA, EISA, MCA, ISA)"
-# Visual Workstation support is utterly broken.
-# If you want to see it working mail an VW540 to hch@infradead.org 8)
-#bool 'SGI Visual Workstation support' CONFIG_VISWS
config X86_VISWS_APIC
bool
depends on VISWS
@@ -1000,11 +1045,12 @@ config X86_VISWS_APIC
config X86_LOCAL_APIC
bool
- depends on !VISWS && SMP || VISWS
+ depends on ((!VISWS && SMP) || VISWS) && !VOYAGER
default y
config PCI
bool "PCI support" if !VISWS
+ depends on !VOYAGER
default y if VISWS
help
Find out whether you have a PCI motherboard. PCI is the name of a
@@ -1019,7 +1065,7 @@ config PCI
config X86_IO_APIC
bool
- depends on !VISWS && SMP
+ depends on !VISWS && SMP && !VOYAGER
default y
choice
@@ -1063,6 +1109,7 @@ config PCI_DIRECT
config SCx200
tristate "NatSemi SCx200 support"
+ depends on !VOYAGER
help
This provides basic support for the National Semiconductor SCx200
processor. Right now this is just a driver for the GPIO pins.
@@ -1076,6 +1123,7 @@ source "drivers/pci/Kconfig"
config ISA
bool "ISA support"
+ depends on !VOYAGER
help
Find out whether you have ISA slots on your motherboard. ISA is the
name of a bus system, i.e. the way the CPU talks to the other stuff
@@ -1101,13 +1149,17 @@ config EISA
config MCA
bool "MCA support"
- depends on !VISWS
+ depends on !VISWS && !VOYAGER
help
MicroChannel Architecture is found in some IBM PS/2 machines and
laptops. It is a bus system similar to PCI or ISA. See
<file:Documentation/mca.txt> (and especially the web page given
there) before attempting to build an MCA bus kernel.
+config MCA
+ depends on VOYAGER
+ default y if VOYAGER
+
source "drivers/mca/Kconfig"
config HOTPLUG
@@ -1574,12 +1626,12 @@ config FRAME_POINTER
config X86_EXTRA_IRQS
bool
- depends on X86_LOCAL_APIC
+ depends on X86_LOCAL_APIC || VOYAGER
default y
config X86_FIND_SMP_CONFIG
bool
- depends on X86_LOCAL_APIC
+ depends on X86_LOCAL_APIC || VOYAGER
default y
config X86_MPPARSE
@@ -1597,15 +1649,20 @@ source "lib/Kconfig"
config X86_SMP
bool
- depends on SMP
+ depends on SMP && !VOYAGER
default y
config X86_HT
bool
- depends on SMP
+ depends on SMP && !VOYAGER
default y
config X86_BIOS_REBOOT
bool
+ depends on !VOYAGER
default y
+config X86_TRAMPOLINE
+ bool
+ depends on SMP
+ default y
diff --git a/arch/i386/Makefile b/arch/i386/Makefile
index 383bc1dfec29..6277bdd05469 100644
--- a/arch/i386/Makefile
+++ b/arch/i386/Makefile
@@ -38,6 +38,7 @@ cflags-$(CONFIG_MPENTIUMIII) += $(call check_gcc,-march=pentium3,-march=i686)
cflags-$(CONFIG_MPENTIUM4) += $(call check_gcc,-march=pentium4,-march=i686)
cflags-$(CONFIG_MK6) += $(call check_gcc,-march=k6,-march=i586)
cflags-$(CONFIG_MK7) += $(call check_gcc,-march=athlon,-march=i686 -malign-functions=4)
+cflags-$(CONFIG_MK8) += $(call check_gcc,-march=k8,$(call check_gcc,-march=athlon,-march=i686 -malign-functions=4))
cflags-$(CONFIG_MCRUSOE) += -march=i686 -malign-functions=0 -malign-jumps=0 -malign-loops=0
cflags-$(CONFIG_MWINCHIPC6) += $(call check_gcc,-march=winchip-c6,-march=i586)
cflags-$(CONFIG_MWINCHIP2) += $(call check_gcc,-march=winchip2,-march=i586)
@@ -51,6 +52,10 @@ CFLAGS += $(cflags-y)
#default subarch .c files
mcore-y := mach-default
+#Voyager subarch support
+mflags-$(CONFIG_VOYAGER) := -Iinclude/asm-i386/mach-voyager
+mcore-$(CONFIG_VOYAGER) := mach-voyager
+
#VISWS subarch support
mflags-$(CONFIG_VISWS) := -Iinclude/asm-i386/mach-visws
mcore-$(CONFIG_VISWS) := mach-visws
diff --git a/arch/i386/boot/compressed/head.S b/arch/i386/boot/compressed/head.S
index 917a14416750..c5e80b69e7d4 100644
--- a/arch/i386/boot/compressed/head.S
+++ b/arch/i386/boot/compressed/head.S
@@ -31,7 +31,7 @@
startup_32:
cld
cli
- movl $(__KERNEL_DS),%eax
+ movl $(__BOOT_DS),%eax
movl %eax,%ds
movl %eax,%es
movl %eax,%fs
@@ -74,7 +74,7 @@ startup_32:
popl %esi # discard address
popl %esi # real mode pointer
xorl %ebx,%ebx
- ljmp $(__KERNEL_CS), $0x100000
+ ljmp $(__BOOT_CS), $0x100000
/*
* We come here, if we were loaded high.
@@ -101,7 +101,7 @@ startup_32:
popl %eax # hcount
movl $0x100000,%edi
cli # make sure we don't get interrupted
- ljmp $(__KERNEL_CS), $0x1000 # and jump to the move routine
+ ljmp $(__BOOT_CS), $0x1000 # and jump to the move routine
/*
* Routine (template) for moving the decompressed kernel in place,
@@ -124,5 +124,5 @@ move_routine_start:
movsl
movl %ebx,%esi # Restore setup pointer
xorl %ebx,%ebx
- ljmp $(__KERNEL_CS), $0x100000
+ ljmp $(__BOOT_CS), $0x100000
move_routine_end:
diff --git a/arch/i386/boot/compressed/misc.c b/arch/i386/boot/compressed/misc.c
index 20b1677d7efc..b0483a3c867a 100644
--- a/arch/i386/boot/compressed/misc.c
+++ b/arch/i386/boot/compressed/misc.c
@@ -299,7 +299,7 @@ long user_stack [STACK_SIZE];
struct {
long * a;
short b;
- } stack_start = { & user_stack [STACK_SIZE] , __KERNEL_DS };
+ } stack_start = { & user_stack [STACK_SIZE] , __BOOT_DS };
static void setup_normal_output_buffer(void)
{
diff --git a/arch/i386/boot/setup.S b/arch/i386/boot/setup.S
index 66feeb7d1f87..59b2c46745a6 100644
--- a/arch/i386/boot/setup.S
+++ b/arch/i386/boot/setup.S
@@ -476,6 +476,24 @@ sysdesc_ok:
movsb
popw %ds
no_mca:
+#ifdef CONFIG_VOYAGER
+ movb $0xff, 0x40 # flag on config found
+ movb $0xc0, %al
+ mov $0xff, %ah
+ int $0x15 # put voyager config info at es:di
+ jc no_voyager
+ movw $0x40, %si # place voyager info in apm table
+ cld
+ movw $7, %cx
+voyager_rep:
+ movb %es:(%di), %al
+ movb %al,(%si)
+ incw %di
+ incw %si
+ decw %cx
+ jnz voyager_rep
+no_voyager:
+#endif
# Check for PS/2 pointing device
movw %cs, %ax # aka SETUPSEG
subw $DELTA_INITSEG, %ax # aka INITSEG
@@ -740,6 +758,7 @@ A20_TEST_LOOPS = 32 # Iterations per wait
A20_ENABLE_LOOPS = 255 # Total loops to try
+#ifndef CONFIG_VOYAGER
a20_try_loop:
# First, see if we are on a system with no A20 gate.
@@ -758,11 +777,14 @@ a20_bios:
jnz a20_done
# Try enabling A20 through the keyboard controller
+#endif /* CONFIG_VOYAGER */
a20_kbc:
call empty_8042
+#ifndef CONFIG_VOYAGER
call a20_test # Just in case the BIOS worked
jnz a20_done # but had a delayed reaction.
+#endif
movb $0xD1, %al # command write
outb %al, $0x64
@@ -772,6 +794,7 @@ a20_kbc:
outb %al, $0x60
call empty_8042
+#ifndef CONFIG_VOYAGER
# Wait until a20 really *is* enabled; it can take a fair amount of
# time on certain systems; Toshiba Tecras are known to have this
# problem.
@@ -819,6 +842,7 @@ a20_err_msg:
# If we get here, all is good
a20_done:
+#endif /* CONFIG_VOYAGER */
# set up gdt and idt
lidt idt_48 # load idt with 0,0
xorl %eax, %eax # Compute gdt_base
@@ -870,7 +894,7 @@ flush_instr:
subw $DELTA_INITSEG, %si
shll $4, %esi # Convert to 32-bit pointer
# NOTE: For high loaded big kernels we need a
-# jmpi 0x100000,__KERNEL_CS
+# jmpi 0x100000,__BOOT_CS
#
# but we yet haven't reloaded the CS register, so the default size
# of the target offset still is 16 bit.
@@ -881,7 +905,7 @@ flush_instr:
.byte 0x66, 0xea # prefix + jmpi-opcode
code32: .long 0x1000 # will be set to 0x100000
# for big kernels
- .word __KERNEL_CS
+ .word __BOOT_CS
# Here's a bunch of information about your current kernel..
kernel_version: .ascii UTS_RELEASE
@@ -985,6 +1009,7 @@ bootsect_panic_mess:
.string "INT15 refuses to access high mem, giving up."
+#ifndef CONFIG_VOYAGER
# This routine tests whether or not A20 is enabled. If so, it
# exits with zf = 0.
#
@@ -1015,6 +1040,8 @@ a20_test_wait:
popw %cx
ret
+#endif /* CONFIG_VOYAGER */
+
# This routine checks that the keyboard command queue is empty
# (after emptying the output buffers)
#
@@ -1075,13 +1102,19 @@ delay:
# Descriptor tables
#
-# NOTE: if you think the GDT is large, you can make it smaller by just
-# defining the KERNEL_CS and KERNEL_DS entries and shifting the gdt
-# address down by GDT_ENTRY_KERNEL_CS*8. This puts bogus entries into
-# the GDT, but those wont be used so it's not a problem.
+# NOTE: The intel manual says gdt should be sixteen bytes aligned for
+# efficiency reasons. However, there are machines which are known not
+# to boot with misaligned GDTs, so alter this at your peril! If you alter
+# GDT_ENTRY_BOOT_CS (in asm/segment.h) remember to leave at least two
+# empty GDT entries (one for NULL and one reserved).
#
+# NOTE: On some CPUs, the GDT must be 8 byte aligned. This is
+# true for the Voyager Quad CPU card which will not boot without
+# This directive. 16 byte aligment is recommended by intel.
+#
+ .align 16
gdt:
- .fill GDT_ENTRY_KERNEL_CS,8,0
+ .fill GDT_ENTRY_BOOT_CS,8,0
.word 0xFFFF # 4Gb - (0x100000*0x1000 = 4Gb)
.word 0 # base address = 0
@@ -1094,12 +1127,17 @@ gdt:
.word 0x9200 # data read/write
.word 0x00CF # granularity = 4096, 386
# (+5th nibble of limit)
+gdt_end:
+ .align 4
+
+ .word 0 # alignment byte
idt_48:
.word 0 # idt limit = 0
.word 0, 0 # idt base = 0L
-gdt_48:
- .word GDT_ENTRY_KERNEL_CS*8 + 16 - 1 # gdt limit
+ .word 0 # alignment byte
+gdt_48:
+ .word gdt_end - gdt - 1 # gdt limit
.word 0, 0 # gdt base (filled in later)
# Include video setup & detection code
diff --git a/arch/i386/defconfig b/arch/i386/defconfig
index b1300d317104..dc9338a71390 100644
--- a/arch/i386/defconfig
+++ b/arch/i386/defconfig
@@ -2,8 +2,8 @@
# Automatically generated make config: don't edit
#
CONFIG_X86=y
-CONFIG_ISA=y
-# CONFIG_SBUS is not set
+CONFIG_MMU=y
+CONFIG_SWAP=y
CONFIG_UID16=y
CONFIG_GENERIC_ISA_DMA=y
@@ -24,12 +24,16 @@ CONFIG_SYSCTL=y
# Loadable module support
#
CONFIG_MODULES=y
-CONFIG_MODVERSIONS=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_OBSOLETE_MODPARM=y
CONFIG_KMOD=y
#
# Processor type and features
#
+CONFIG_PC=y
+# CONFIG_VOYAGER is not set
# CONFIG_M386 is not set
# CONFIG_M486 is not set
# CONFIG_M586 is not set
@@ -40,27 +44,32 @@ CONFIG_KMOD=y
CONFIG_MPENTIUM4=y
# CONFIG_MK6 is not set
# CONFIG_MK7 is not set
+# CONFIG_MK8 is not set
# CONFIG_MELAN is not set
# CONFIG_MCRUSOE is not set
# CONFIG_MWINCHIPC6 is not set
# CONFIG_MWINCHIP2 is not set
# CONFIG_MWINCHIP3D is not set
# CONFIG_MCYRIXIII is not set
-CONFIG_X86_WP_WORKS_OK=y
-CONFIG_X86_INVLPG=y
CONFIG_X86_CMPXCHG=y
CONFIG_X86_XADD=y
+CONFIG_X86_L1_CACHE_SHIFT=7
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_X86_WP_WORKS_OK=y
+CONFIG_X86_INVLPG=y
CONFIG_X86_BSWAP=y
CONFIG_X86_POPAD_OK=y
-# CONFIG_RWSEM_GENERIC_SPINLOCK is not set
-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
-CONFIG_X86_L1_CACHE_SHIFT=7
CONFIG_X86_TSC=y
CONFIG_X86_GOOD_APIC=y
+CONFIG_X86_INTEL_USERCOPY=y
CONFIG_X86_USE_PPRO_CHECKSUM=y
+CONFIG_X86_SSE2=y
# CONFIG_HUGETLB_PAGE is not set
CONFIG_SMP=y
-CONFIG_PREEMPT=y
+# CONFIG_PREEMPT is not set
+CONFIG_X86_LOCAL_APIC=y
+CONFIG_X86_IO_APIC=y
+CONFIG_NR_CPUS=32
# CONFIG_X86_NUMA is not set
CONFIG_X86_MCE=y
# CONFIG_X86_MCE_NONFATAL is not set
@@ -70,18 +79,19 @@ CONFIG_X86_MCE_P4THERMAL=y
# CONFIG_MICROCODE is not set
# CONFIG_X86_MSR is not set
# CONFIG_X86_CPUID is not set
-# CONFIG_EDD is not set
+CONFIG_EDD=y
CONFIG_NOHIGHMEM=y
# CONFIG_HIGHMEM4G is not set
# CONFIG_HIGHMEM64G is not set
# CONFIG_MATH_EMULATION is not set
CONFIG_MTRR=y
CONFIG_HAVE_DEC_LOCK=y
-CONFIG_NR_CPUS=32
#
# Power management options (ACPI, APM)
#
+CONFIG_PM=y
+# CONFIG_SOFTWARE_SUSPEND is not set
#
# ACPI Support
@@ -89,7 +99,6 @@ CONFIG_NR_CPUS=32
CONFIG_ACPI=y
# CONFIG_ACPI_HT_ONLY is not set
CONFIG_ACPI_BOOT=y
-# CONFIG_ACPI_SLEEP is not set
CONFIG_ACPI_AC=y
CONFIG_ACPI_BATTERY=y
CONFIG_ACPI_BUTTON=y
@@ -98,28 +107,27 @@ CONFIG_ACPI_PROCESSOR=y
CONFIG_ACPI_THERMAL=y
# CONFIG_ACPI_TOSHIBA is not set
CONFIG_ACPI_DEBUG=y
-CONFIG_ACPI_BOOT=y
CONFIG_ACPI_BUS=y
CONFIG_ACPI_INTERPRETER=y
CONFIG_ACPI_EC=y
CONFIG_ACPI_POWER=y
CONFIG_ACPI_PCI=y
CONFIG_ACPI_SYSTEM=y
-CONFIG_PM=y
# CONFIG_APM is not set
+# CONFIG_CPU_FREQ is not set
#
# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
#
-CONFIG_X86_IO_APIC=y
-CONFIG_X86_LOCAL_APIC=y
CONFIG_PCI=y
# CONFIG_PCI_GOBIOS is not set
# CONFIG_PCI_GODIRECT is not set
CONFIG_PCI_GOANY=y
CONFIG_PCI_BIOS=y
CONFIG_PCI_DIRECT=y
+# CONFIG_SCx200 is not set
CONFIG_PCI_NAMES=y
+CONFIG_ISA=y
# CONFIG_EISA is not set
# CONFIG_MCA is not set
CONFIG_HOTPLUG=y
@@ -137,9 +145,6 @@ CONFIG_CARDBUS=y
# PCI Hotplug Support
#
# CONFIG_HOTPLUG_PCI is not set
-# CONFIG_HOTPLUG_PCI_COMPAQ is not set
-# CONFIG_HOTPLUG_PCI_COMPAQ_NVRAM is not set
-# CONFIG_HOTPLUG_PCI_IBM is not set
#
# Executable file formats
@@ -165,19 +170,20 @@ CONFIG_PARPORT_PC_CML1=y
# CONFIG_PARPORT_PC_FIFO is not set
# CONFIG_PARPORT_PC_SUPERIO is not set
# CONFIG_PARPORT_PC_PCMCIA is not set
-# CONFIG_PARPORT_AMIGA is not set
-# CONFIG_PARPORT_MFC3 is not set
-# CONFIG_PARPORT_ATARI is not set
-# CONFIG_PARPORT_GSC is not set
-# CONFIG_PARPORT_SUNBPP is not set
# CONFIG_PARPORT_OTHER is not set
CONFIG_PARPORT_1284=y
#
-# Plug and Play configuration
+# Plug and Play support
#
CONFIG_PNP=y
-CONFIG_ISAPNP=y
+CONFIG_PNP_NAMES=y
+# CONFIG_PNP_CARD is not set
+# CONFIG_PNP_DEBUG is not set
+
+#
+# Protocols
+#
# CONFIG_PNPBIOS is not set
#
@@ -188,13 +194,12 @@ CONFIG_BLK_DEV_FD=y
# CONFIG_PARIDE is not set
# CONFIG_BLK_CPQ_DA is not set
# CONFIG_BLK_CPQ_CISS_DA is not set
-# CONFIG_CISS_SCSI_TAPE is not set
# CONFIG_BLK_DEV_DAC960 is not set
# CONFIG_BLK_DEV_UMEM is not set
# CONFIG_BLK_DEV_LOOP is not set
# CONFIG_BLK_DEV_NBD is not set
# CONFIG_BLK_DEV_RAM is not set
-# CONFIG_BLK_DEV_INITRD is not set
+CONFIG_LBD=y
#
# ATA/ATAPI/MFM/RLL device support
@@ -225,38 +230,33 @@ CONFIG_BLK_DEV_IDECD=y
#
CONFIG_BLK_DEV_CMD640=y
# CONFIG_BLK_DEV_CMD640_ENHANCED is not set
-# CONFIG_BLK_DEV_ISAPNP is not set
CONFIG_BLK_DEV_IDEPCI=y
CONFIG_BLK_DEV_GENERIC=y
CONFIG_IDEPCI_SHARE_IRQ=y
CONFIG_BLK_DEV_IDEDMA_PCI=y
+# CONFIG_BLK_DEV_IDE_TCQ is not set
# CONFIG_BLK_DEV_OFFBOARD is not set
# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
CONFIG_IDEDMA_PCI_AUTO=y
# CONFIG_IDEDMA_ONLYDISK is not set
CONFIG_BLK_DEV_IDEDMA=y
# CONFIG_IDEDMA_PCI_WIP is not set
-# CONFIG_IDEDMA_NEW_DRIVE_LISTINGS is not set
CONFIG_BLK_DEV_ADMA=y
# CONFIG_BLK_DEV_AEC62XX is not set
# CONFIG_BLK_DEV_ALI15X3 is not set
-# CONFIG_WDC_ALI15X3 is not set
# CONFIG_BLK_DEV_AMD74XX is not set
-# CONFIG_AMD74XX_OVERRIDE is not set
# CONFIG_BLK_DEV_CMD64X is not set
# CONFIG_BLK_DEV_CY82C693 is not set
-# CONFIG_BLK_DEV_CS5530 is not set
+# CONFIG_BLK_DEV_CS5520 is not set
# CONFIG_BLK_DEV_HPT34X is not set
-# CONFIG_HPT34X_AUTODMA is not set
# CONFIG_BLK_DEV_HPT366 is not set
+# CONFIG_BLK_DEV_SC1200 is not set
CONFIG_BLK_DEV_PIIX=y
# CONFIG_BLK_DEV_NFORCE is not set
# CONFIG_BLK_DEV_NS87415 is not set
# CONFIG_BLK_DEV_OPTI621 is not set
# CONFIG_BLK_DEV_PDC202XX_OLD is not set
-# CONFIG_PDC202XX_BURST is not set
# CONFIG_BLK_DEV_PDC202XX_NEW is not set
-# CONFIG_PDC202XX_FORCE is not set
CONFIG_BLK_DEV_RZ1000=y
# CONFIG_BLK_DEV_SVWKS is not set
# CONFIG_BLK_DEV_SIIMAGE is not set
@@ -267,7 +267,6 @@ CONFIG_BLK_DEV_RZ1000=y
# CONFIG_IDE_CHIPSETS is not set
CONFIG_IDEDMA_AUTO=y
# CONFIG_IDEDMA_IVB is not set
-# CONFIG_DMA_NONPCI is not set
CONFIG_BLK_DEV_IDE_MODES=y
#
@@ -279,12 +278,10 @@ CONFIG_SCSI=y
# SCSI support type (disk, tape, CD-ROM)
#
CONFIG_BLK_DEV_SD=y
-CONFIG_SD_EXTRA_DEVS=40
# CONFIG_CHR_DEV_ST is not set
# CONFIG_CHR_DEV_OSST is not set
CONFIG_BLK_DEV_SR=y
CONFIG_BLK_DEV_SR_VENDOR=y
-CONFIG_SR_EXTRA_DEVS=2
CONFIG_CHR_DEV_SG=y
#
@@ -303,10 +300,16 @@ CONFIG_SCSI_CONSTANTS=y
# CONFIG_SCSI_ACARD is not set
# CONFIG_SCSI_AHA152X is not set
# CONFIG_SCSI_AHA1542 is not set
+# CONFIG_SCSI_AACRAID is not set
CONFIG_SCSI_AIC7XXX=y
CONFIG_AIC7XXX_CMDS_PER_DEVICE=64
CONFIG_AIC7XXX_RESET_DELAY_MS=2000
+# CONFIG_AIC7XXX_PROBE_EISA_VL is not set
# CONFIG_AIC7XXX_BUILD_FIRMWARE is not set
+# CONFIG_AIC7XXX_DEBUG_ENABLE is not set
+CONFIG_AIC7XXX_DEBUG_MASK=0
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
# CONFIG_SCSI_DPT_I2O is not set
# CONFIG_SCSI_ADVANSYS is not set
# CONFIG_SCSI_IN2000 is not set
@@ -322,6 +325,7 @@ CONFIG_AIC7XXX_RESET_DELAY_MS=2000
# CONFIG_SCSI_FUTURE_DOMAIN is not set
# CONFIG_SCSI_GDTH is not set
# CONFIG_SCSI_GENERIC_NCR5380 is not set
+# CONFIG_SCSI_GENERIC_NCR5380_MMIO is not set
# CONFIG_SCSI_IPS is not set
# CONFIG_SCSI_INITIO is not set
# CONFIG_SCSI_INIA100 is not set
@@ -347,6 +351,7 @@ CONFIG_SCSI_QLOGIC_1280=y
# CONFIG_SCSI_T128 is not set
# CONFIG_SCSI_U14_34F is not set
# CONFIG_SCSI_ULTRASTOR is not set
+# CONFIG_SCSI_NSP32 is not set
# CONFIG_SCSI_DEBUG is not set
#
@@ -355,7 +360,7 @@ CONFIG_SCSI_QLOGIC_1280=y
# CONFIG_SCSI_PCMCIA is not set
#
-# Old non-SCSI/ATAPI CD-ROM drives
+# Old CD-ROM drivers (not SCSI, not IDE)
#
# CONFIG_CD_NO_IDESCSI is not set
@@ -363,22 +368,11 @@ CONFIG_SCSI_QLOGIC_1280=y
# Multi-device support (RAID and LVM)
#
# CONFIG_MD is not set
-# CONFIG_BLK_DEV_MD is not set
-# CONFIG_MD_LINEAR is not set
-# CONFIG_MD_RAID0 is not set
-# CONFIG_MD_RAID1 is not set
-# CONFIG_MD_RAID5 is not set
-# CONFIG_MD_MULTIPATH is not set
-# CONFIG_BLK_DEV_LVM is not set
#
# Fusion MPT device support
#
# CONFIG_FUSION is not set
-# CONFIG_FUSION_BOOT is not set
-# CONFIG_FUSION_ISENSE is not set
-# CONFIG_FUSION_CTL is not set
-# CONFIG_FUSION_LAN is not set
#
# IEEE 1394 (FireWire) support (EXPERIMENTAL)
@@ -389,11 +383,6 @@ CONFIG_SCSI_QLOGIC_1280=y
# I2O device support
#
# CONFIG_I2O is not set
-# CONFIG_I2O_PCI is not set
-# CONFIG_I2O_BLOCK is not set
-# CONFIG_I2O_LAN is not set
-# CONFIG_I2O_SCSI is not set
-# CONFIG_I2O_PROC is not set
#
# Networking options
@@ -404,6 +393,7 @@ CONFIG_PACKET=y
# CONFIG_NETFILTER is not set
# CONFIG_FILTER is not set
CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
CONFIG_INET=y
CONFIG_IP_MULTICAST=y
# CONFIG_IP_ADVANCED_ROUTER is not set
@@ -414,19 +404,19 @@ CONFIG_IP_MULTICAST=y
# CONFIG_ARPD is not set
# CONFIG_INET_ECN is not set
# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_XFRM_USER is not set
# CONFIG_IPV6 is not set
#
-# SCTP Configuration (EXPERIMENTAL)
+# SCTP Configuration (EXPERIMENTAL)
#
CONFIG_IPV6_SCTP__=y
# CONFIG_IP_SCTP is not set
# CONFIG_ATM is not set
# CONFIG_VLAN_8021Q is not set
# CONFIG_LLC is not set
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-# CONFIG_DEV_APPLETALK is not set
# CONFIG_DECNET is not set
# CONFIG_BRIDGE is not set
# CONFIG_X25 is not set
@@ -443,6 +433,11 @@ CONFIG_IPV6_SCTP__=y
# CONFIG_NET_SCHED is not set
#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+
+#
# Network device support
#
CONFIG_NETDEVICES=y
@@ -456,21 +451,22 @@ CONFIG_DUMMY=m
# CONFIG_EQUALIZER is not set
# CONFIG_TUN is not set
# CONFIG_ETHERTAP is not set
-# CONFIG_NET_SB1000 is not set
#
# Ethernet (10 or 100Mbit)
#
CONFIG_NET_ETHERNET=y
-# CONFIG_SUNLANCE is not set
# CONFIG_HAPPYMEAL is not set
-# CONFIG_SUNBMAC is not set
-# CONFIG_SUNQE is not set
# CONFIG_SUNGEM is not set
# CONFIG_NET_VENDOR_3COM is not set
# CONFIG_LANCE is not set
# CONFIG_NET_VENDOR_SMC is not set
# CONFIG_NET_VENDOR_RACAL is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
# CONFIG_AT1700 is not set
# CONFIG_DEPCA is not set
# CONFIG_HP100 is not set
@@ -480,29 +476,21 @@ CONFIG_NET_PCI=y
# CONFIG_ADAPTEC_STARFIRE is not set
# CONFIG_AC3200 is not set
# CONFIG_APRICOT is not set
+# CONFIG_B44 is not set
# CONFIG_CS89x0 is not set
# CONFIG_DGRS is not set
# CONFIG_EEPRO100 is not set
CONFIG_E100=y
-# CONFIG_LNE390 is not set
# CONFIG_FEALNX is not set
# CONFIG_NATSEMI is not set
# CONFIG_NE2K_PCI is not set
-# CONFIG_NE3210 is not set
-# CONFIG_ES3210 is not set
# CONFIG_8139CP is not set
# CONFIG_8139TOO is not set
-# CONFIG_8139TOO_PIO is not set
-# CONFIG_8139TOO_TUNE_TWISTER is not set
-# CONFIG_8139TOO_8129 is not set
-# CONFIG_8139_OLD_RX_RESET is not set
# CONFIG_SIS900 is not set
# CONFIG_EPIC100 is not set
# CONFIG_SUNDANCE is not set
-# CONFIG_SUNDANCE_MMIO is not set
# CONFIG_TLAN is not set
# CONFIG_VIA_RHINE is not set
-# CONFIG_VIA_RHINE_MMIO is not set
# CONFIG_NET_POCKET is not set
#
@@ -511,11 +499,10 @@ CONFIG_E100=y
# CONFIG_ACENIC is not set
# CONFIG_DL2K is not set
# CONFIG_E1000 is not set
-# CONFIG_E1000_NAPI is not set
-# CONFIG_MYRI_SBUS is not set
# CONFIG_NS83820 is not set
# CONFIG_HAMACHI is not set
# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
# CONFIG_SK98LIN is not set
# CONFIG_TIGON3 is not set
# CONFIG_FDDI is not set
@@ -530,9 +517,8 @@ CONFIG_E100=y
# CONFIG_NET_RADIO is not set
#
-# Token Ring devices
+# Token Ring devices (depends on LLC=y)
#
-# CONFIG_TR is not set
# CONFIG_NET_FC is not set
# CONFIG_RCPCI is not set
# CONFIG_SHAPER is not set
@@ -543,11 +529,6 @@ CONFIG_E100=y
# CONFIG_WAN is not set
#
-# Tulip family network device support
-#
-# CONFIG_NET_TULIP is not set
-
-#
# PCMCIA network device support
#
CONFIG_NET_PCMCIA=y
@@ -559,11 +540,8 @@ CONFIG_PCMCIA_PCNET=y
# CONFIG_PCMCIA_SMC91C92 is not set
# CONFIG_PCMCIA_XIRC2PS is not set
# CONFIG_PCMCIA_AXNET is not set
-# CONFIG_ARCNET_COM20020_CS is not set
-# CONFIG_PCMCIA_IBMTR is not set
CONFIG_NET_PCMCIA_RADIO=y
CONFIG_PCMCIA_RAYCS=y
-# CONFIG_AIRONET4500_CS is not set
#
# Amateur Radio support
@@ -584,8 +562,6 @@ CONFIG_PCMCIA_RAYCS=y
# Telephony Support
#
# CONFIG_PHONE is not set
-# CONFIG_PHONE_IXJ is not set
-# CONFIG_PHONE_IXJ_PCMCIA is not set
#
# Input device support
@@ -609,12 +585,6 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
#
# CONFIG_GAMEPORT is not set
CONFIG_SOUND_GAMEPORT=y
-# CONFIG_GAMEPORT_NS558 is not set
-# CONFIG_GAMEPORT_L4 is not set
-# CONFIG_GAMEPORT_EMU10K1 is not set
-# CONFIG_GAMEPORT_VORTEX is not set
-# CONFIG_GAMEPORT_FM801 is not set
-# CONFIG_GAMEPORT_CS461x is not set
CONFIG_SERIO=y
CONFIG_SERIO_I8042=y
# CONFIG_SERIO_SERPORT is not set
@@ -636,33 +606,8 @@ CONFIG_MOUSE_PS2=y
# CONFIG_MOUSE_LOGIBM is not set
# CONFIG_MOUSE_PC110PAD is not set
# CONFIG_INPUT_JOYSTICK is not set
-# CONFIG_JOYSTICK_ANALOG is not set
-# CONFIG_JOYSTICK_A3D is not set
-# CONFIG_JOYSTICK_ADI is not set
-# CONFIG_JOYSTICK_COBRA is not set
-# CONFIG_JOYSTICK_GF2K is not set
-# CONFIG_JOYSTICK_GRIP is not set
-# CONFIG_JOYSTICK_GRIP_MP is not set
-# CONFIG_JOYSTICK_GUILLEMOT is not set
-# CONFIG_JOYSTICK_INTERACT is not set
-# CONFIG_JOYSTICK_SIDEWINDER is not set
-# CONFIG_JOYSTICK_TMDC is not set
-# CONFIG_JOYSTICK_IFORCE is not set
-# CONFIG_JOYSTICK_WARRIOR is not set
-# CONFIG_JOYSTICK_MAGELLAN is not set
-# CONFIG_JOYSTICK_SPACEORB is not set
-# CONFIG_JOYSTICK_SPACEBALL is not set
-# CONFIG_JOYSTICK_STINGER is not set
-# CONFIG_JOYSTICK_TWIDDLER is not set
-# CONFIG_JOYSTICK_DB9 is not set
-# CONFIG_JOYSTICK_GAMECON is not set
-# CONFIG_JOYSTICK_TURBOGRAFX is not set
-# CONFIG_INPUT_JOYDUMP is not set
# CONFIG_INPUT_TOUCHSCREEN is not set
-# CONFIG_TOUCHSCREEN_GUNZE is not set
# CONFIG_INPUT_MISC is not set
-# CONFIG_INPUT_PCSPKR is not set
-# CONFIG_INPUT_UINPUT is not set
#
# Character devices
@@ -679,11 +624,6 @@ CONFIG_SERIAL_8250=y
# CONFIG_SERIAL_8250_CONSOLE is not set
# CONFIG_SERIAL_8250_CS is not set
# CONFIG_SERIAL_8250_EXTENDED is not set
-# CONFIG_SERIAL_8250_MANY_PORTS is not set
-# CONFIG_SERIAL_8250_SHARE_IRQ is not set
-# CONFIG_SERIAL_8250_DETECT_IRQ is not set
-# CONFIG_SERIAL_8250_MULTIPORT is not set
-# CONFIG_SERIAL_8250_RSA is not set
#
# Non-8250 serial port support
@@ -694,6 +634,7 @@ CONFIG_UNIX98_PTY_COUNT=256
CONFIG_PRINTER=y
# CONFIG_LP_CONSOLE is not set
# CONFIG_PPDEV is not set
+# CONFIG_TIPAR is not set
#
# I2C support
@@ -701,6 +642,14 @@ CONFIG_PRINTER=y
# CONFIG_I2C is not set
#
+# I2C Hardware Sensors Mainboard support
+#
+
+#
+# I2C Hardware Sensors Chip support
+#
+
+#
# Mice
#
# CONFIG_BUSMOUSE is not set
@@ -711,6 +660,7 @@ CONFIG_PRINTER=y
#
# CONFIG_WATCHDOG is not set
CONFIG_INTEL_RNG=y
+# CONFIG_AMD_RNG is not set
# CONFIG_NVRAM is not set
# CONFIG_RTC is not set
# CONFIG_GEN_RTC is not set
@@ -724,16 +674,16 @@ CONFIG_INTEL_RNG=y
#
# CONFIG_FTAPE is not set
CONFIG_AGP=y
+# CONFIG_AGP3 is not set
CONFIG_AGP_INTEL=y
-CONFIG_AGP_I810=y
CONFIG_AGP_VIA=y
CONFIG_AGP_AMD=y
CONFIG_AGP_SIS=y
CONFIG_AGP_ALI=y
CONFIG_AGP_SWORKS=y
+# CONFIG_AGP_AMD_8151 is not set
CONFIG_DRM=y
# CONFIG_DRM_TDFX is not set
-# CONFIG_DRM_GAMMA is not set
# CONFIG_DRM_R128 is not set
CONFIG_DRM_RADEON=y
# CONFIG_DRM_I810 is not set
@@ -756,28 +706,25 @@ CONFIG_DRM_RADEON=y
# File systems
#
# CONFIG_QUOTA is not set
-# CONFIG_QFMT_V1 is not set
-# CONFIG_QFMT_V2 is not set
# CONFIG_AUTOFS_FS is not set
CONFIG_AUTOFS4_FS=y
CONFIG_REISERFS_FS=y
# CONFIG_REISERFS_CHECK is not set
# CONFIG_REISERFS_PROC_INFO is not set
# CONFIG_ADFS_FS is not set
-# CONFIG_ADFS_FS_RW is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
+# CONFIG_BEFS_FS is not set
# CONFIG_BFS_FS is not set
CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+CONFIG_EXT3_FS_POSIX_ACL=y
CONFIG_JBD=y
# CONFIG_JBD_DEBUG is not set
CONFIG_FAT_FS=y
CONFIG_MSDOS_FS=y
-# CONFIG_UMSDOS_FS is not set
CONFIG_VFAT_FS=y
# CONFIG_EFS_FS is not set
-# CONFIG_JFFS_FS is not set
-# CONFIG_JFFS2_FS is not set
# CONFIG_CRAMFS is not set
CONFIG_TMPFS=y
CONFIG_RAMFS=y
@@ -785,31 +732,22 @@ CONFIG_ISO9660_FS=y
CONFIG_JOLIET=y
# CONFIG_ZISOFS is not set
# CONFIG_JFS_FS is not set
-# CONFIG_JFS_DEBUG is not set
-# CONFIG_JFS_STATISTICS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_NTFS_FS is not set
-# CONFIG_NTFS_DEBUG is not set
-# CONFIG_NTFS_RW is not set
# CONFIG_HPFS_FS is not set
CONFIG_PROC_FS=y
# CONFIG_DEVFS_FS is not set
-# CONFIG_DEVFS_MOUNT is not set
-# CONFIG_DEVFS_DEBUG is not set
CONFIG_DEVPTS_FS=y
# CONFIG_QNX4FS_FS is not set
-# CONFIG_QNX4FS_RW is not set
# CONFIG_ROMFS_FS is not set
CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+# CONFIG_EXT2_FS_POSIX_ACL is not set
# CONFIG_SYSV_FS is not set
CONFIG_UDF_FS=y
-# CONFIG_UDF_RW is not set
# CONFIG_UFS_FS is not set
-# CONFIG_UFS_FS_WRITE is not set
# CONFIG_XFS_FS is not set
-# CONFIG_XFS_RT is not set
-# CONFIG_XFS_QUOTA is not set
#
# Network File Systems
@@ -818,31 +756,25 @@ CONFIG_UDF_FS=y
# CONFIG_INTERMEZZO_FS is not set
CONFIG_NFS_FS=y
# CONFIG_NFS_V3 is not set
-# CONFIG_ROOT_NFS is not set
+# CONFIG_NFS_V4 is not set
CONFIG_NFSD=y
# CONFIG_NFSD_V3 is not set
# CONFIG_NFSD_TCP is not set
CONFIG_SUNRPC=y
CONFIG_LOCKD=y
CONFIG_EXPORTFS=y
+# CONFIG_CIFS is not set
# CONFIG_SMB_FS is not set
# CONFIG_NCP_FS is not set
-# CONFIG_NCPFS_PACKET_SIGNING is not set
-# CONFIG_NCPFS_IOCTL_LOCKING is not set
-# CONFIG_NCPFS_STRONG is not set
-# CONFIG_NCPFS_NFS_NS is not set
-# CONFIG_NCPFS_OS2_NS is not set
-# CONFIG_NCPFS_SMALLDOS is not set
-# CONFIG_NCPFS_NLS is not set
-# CONFIG_NCPFS_EXTRAS is not set
-# CONFIG_ZISOFS_FS is not set
+# CONFIG_AFS_FS is not set
+CONFIG_FS_MBCACHE=y
+CONFIG_FS_POSIX_ACL=y
#
# Partition Types
#
# CONFIG_PARTITION_ADVANCED is not set
CONFIG_MSDOS_PARTITION=y
-# CONFIG_SMB_NLS is not set
CONFIG_NLS=y
#
@@ -888,16 +820,17 @@ CONFIG_NLS_ISO8859_1=y
# CONFIG_NLS_UTF8 is not set
#
-# Console drivers
+# Graphics support
#
-CONFIG_VGA_CONSOLE=y
+# CONFIG_FB is not set
# CONFIG_VIDEO_SELECT is not set
-# CONFIG_MDA_CONSOLE is not set
#
-# Frame-buffer support
+# Console display driver support
#
-# CONFIG_FB is not set
+CONFIG_VGA_CONSOLE=y
+# CONFIG_MDA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
#
# Sound
@@ -919,11 +852,8 @@ CONFIG_SND_OSSEMUL=y
CONFIG_SND_MIXER_OSS=y
CONFIG_SND_PCM_OSS=y
CONFIG_SND_SEQUENCER_OSS=y
-# CONFIG_SND_RTCTIMER is not set
# CONFIG_SND_VERBOSE_PRINTK is not set
# CONFIG_SND_DEBUG is not set
-# CONFIG_SND_DEBUG_MEMORY is not set
-# CONFIG_SND_DEBUG_DETECT is not set
#
# Generic devices
@@ -937,12 +867,10 @@ CONFIG_SND_SEQUENCER_OSS=y
#
# ISA devices
#
-# CONFIG_SND_AD1816A is not set
# CONFIG_SND_AD1848 is not set
# CONFIG_SND_CS4231 is not set
# CONFIG_SND_CS4232 is not set
# CONFIG_SND_CS4236 is not set
-# CONFIG_SND_ES968 is not set
# CONFIG_SND_ES1688 is not set
# CONFIG_SND_ES18XX is not set
# CONFIG_SND_GUSCLASSIC is not set
@@ -957,10 +885,7 @@ CONFIG_SND_SEQUENCER_OSS=y
# CONFIG_SND_SB16 is not set
# CONFIG_SND_SBAWE is not set
# CONFIG_SND_WAVEFRONT is not set
-# CONFIG_SND_ALS100 is not set
-# CONFIG_SND_AZT2320 is not set
# CONFIG_SND_CMI8330 is not set
-# CONFIG_SND_DT0197H is not set
# CONFIG_SND_OPL3SA2 is not set
# CONFIG_SND_SGALAXY is not set
@@ -990,8 +915,12 @@ CONFIG_SND_SEQUENCER_OSS=y
# CONFIG_SND_ICE1712 is not set
CONFIG_SND_INTEL8X0=y
# CONFIG_SND_SONICVIBES is not set
-# CONFIG_SND_VIA686 is not set
-# CONFIG_SND_VIA8233 is not set
+# CONFIG_SND_VIA82XX is not set
+
+#
+# ALSA USB devices
+#
+# CONFIG_SND_USB_AUDIO is not set
#
# USB support
@@ -1003,7 +932,6 @@ CONFIG_USB=y
# Miscellaneous USB options
#
CONFIG_USB_DEVICEFS=y
-CONFIG_USB_LONG_TIMEOUT=y
CONFIG_USB_BANDWIDTH=y
# CONFIG_USB_DYNAMIC_MINORS is not set
@@ -1012,7 +940,7 @@ CONFIG_USB_BANDWIDTH=y
#
CONFIG_USB_EHCI_HCD=y
# CONFIG_USB_OHCI_HCD is not set
-CONFIG_USB_UHCI_HCD_ALT=y
+CONFIG_USB_UHCI_HCD=y
#
# USB Device Class drivers
@@ -1037,11 +965,10 @@ CONFIG_USB_STORAGE=y
# USB Human Interface Devices (HID)
#
# CONFIG_USB_HID is not set
-# CONFIG_USB_HIDINPUT is not set
-# CONFIG_HID_FF is not set
-# CONFIG_HID_PID is not set
-# CONFIG_LOGITECH_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
@@ -1063,16 +990,8 @@ CONFIG_USB_STORAGE=y
# CONFIG_USB_DABUSB is not set
#
-# Video4Linux support is needed for USB Multimedia device support
+# Video4Linux support is needed for USB Multimedia device support
#
-# CONFIG_USB_VICAM is not set
-# CONFIG_USB_DSBR is not set
-# CONFIG_USB_IBMCAM is not set
-# CONFIG_USB_KONICAWC is not set
-# CONFIG_USB_OV511 is not set
-# CONFIG_USB_PWC is not set
-# CONFIG_USB_SE401 is not set
-# CONFIG_USB_STV680 is not set
#
# USB Network adaptors
@@ -1093,48 +1012,16 @@ CONFIG_USB_STORAGE=y
# USB Serial Converter support
#
# CONFIG_USB_SERIAL is not set
-# CONFIG_USB_SERIAL_GENERIC is not set
-# CONFIG_USB_SERIAL_BELKIN is not set
-# CONFIG_USB_SERIAL_WHITEHEAT is not set
-# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set
-# CONFIG_USB_SERIAL_EMPEG is not set
-# CONFIG_USB_SERIAL_FTDI_SIO is not set
-# CONFIG_USB_SERIAL_VISOR is not set
-# CONFIG_USB_SERIAL_IPAQ is not set
-# CONFIG_USB_SERIAL_IR is not set
-# CONFIG_USB_SERIAL_EDGEPORT is not set
-# CONFIG_USB_SERIAL_EDGEPORT_TI is not set
-# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set
-# CONFIG_USB_SERIAL_KEYSPAN is not set
-# CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set
-# CONFIG_USB_SERIAL_KEYSPAN_USA28X is not set
-# CONFIG_USB_SERIAL_KEYSPAN_USA28XA is not set
-# CONFIG_USB_SERIAL_KEYSPAN_USA28XB is not set
-# CONFIG_USB_SERIAL_KEYSPAN_USA19 is not set
-# CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set
-# CONFIG_USB_SERIAL_KEYSPAN_USA19W is not set
-# CONFIG_USB_SERIAL_KEYSPAN_USA19QW is not set
-# CONFIG_USB_SERIAL_KEYSPAN_USA19QI is not set
-# CONFIG_USB_SERIAL_KEYSPAN_USA49W is not set
-# CONFIG_USB_SERIAL_KLSI is not set
-# CONFIG_USB_SERIAL_MCT_U232 is not set
-# CONFIG_USB_SERIAL_PL2303 is not set
-# CONFIG_USB_SERIAL_SAFE is not set
-# CONFIG_USB_SERIAL_SAFE_PADDED is not set
-# CONFIG_USB_SERIAL_CYBERJACK is not set
-# CONFIG_USB_SERIAL_XIRCOM is not set
-# CONFIG_USB_SERIAL_OMNINET is not set
#
# USB Miscellaneous drivers
#
-# CONFIG_USB_EMI26 is not set
# CONFIG_USB_TIGL is not set
# CONFIG_USB_AUERSWALD is not set
# CONFIG_USB_RIO500 is not set
# CONFIG_USB_BRLVGER is not set
# CONFIG_USB_LCD is not set
-# CONFIG_USB_SPEEDTOUCH is not set
+# CONFIG_USB_TEST is not set
#
# Bluetooth support
@@ -1142,15 +1029,17 @@ CONFIG_USB_STORAGE=y
# CONFIG_BT is not set
#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
# Kernel hacking
#
-# CONFIG_SOFTWARE_SUSPEND is not set
-CONFIG_DEBUG_KERNEL=y
-CONFIG_DEBUG_SLAB=y
-# CONFIG_DEBUG_IOVIRT is not set
-# CONFIG_MAGIC_SYSRQ is not set
-CONFIG_DEBUG_SPINLOCK=y
+# CONFIG_DEBUG_KERNEL is not set
CONFIG_KALLSYMS=y
+CONFIG_DEBUG_SPINLOCK_SLEEP=y
+CONFIG_FRAME_POINTER=y
CONFIG_X86_EXTRA_IRQS=y
CONFIG_X86_FIND_SMP_CONFIG=y
CONFIG_X86_MPPARSE=y
@@ -1158,14 +1047,18 @@ CONFIG_X86_MPPARSE=y
#
# Security options
#
-CONFIG_SECURITY_CAPABILITIES=y
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
#
# Library routines
#
# CONFIG_CRC32 is not set
-# CONFIG_ZLIB_INFLATE is not set
-# CONFIG_ZLIB_DEFLATE is not set
CONFIG_X86_SMP=y
CONFIG_X86_HT=y
CONFIG_X86_BIOS_REBOOT=y
+CONFIG_X86_TRAMPOLINE=y
diff --git a/arch/i386/kernel/Makefile b/arch/i386/kernel/Makefile
index 78f28e2486a3..386e061795eb 100644
--- a/arch/i386/kernel/Makefile
+++ b/arch/i386/kernel/Makefile
@@ -20,7 +20,8 @@ obj-$(CONFIG_MICROCODE) += microcode.o
obj-$(CONFIG_APM) += apm.o
obj-$(CONFIG_ACPI) += acpi.o
obj-$(CONFIG_ACPI_SLEEP) += acpi_wakeup.o
-obj-$(CONFIG_X86_SMP) += smp.o smpboot.o trampoline.o
+obj-$(CONFIG_X86_SMP) += smp.o smpboot.o
+obj-$(CONFIG_X86_TRAMPOLINE) += trampoline.o
obj-$(CONFIG_X86_MPPARSE) += mpparse.o
obj-$(CONFIG_X86_LOCAL_APIC) += apic.o nmi.o
obj-$(CONFIG_X86_IO_APIC) += io_apic.o
diff --git a/arch/i386/kernel/apic.c b/arch/i386/kernel/apic.c
index 98936e86c9b8..73d1bbdbf43c 100644
--- a/arch/i386/kernel/apic.c
+++ b/arch/i386/kernel/apic.c
@@ -614,7 +614,8 @@ static int __init detect_init_APIC (void)
switch (boot_cpu_data.x86_vendor) {
case X86_VENDOR_AMD:
- if (boot_cpu_data.x86 == 6 && boot_cpu_data.x86_model > 1)
+ if ((boot_cpu_data.x86 == 6 && boot_cpu_data.x86_model > 1) ||
+ (boot_cpu_data.x86 == 15))
break;
goto no_apic;
case X86_VENDOR_INTEL:
diff --git a/arch/i386/kernel/cpu/common.c b/arch/i386/kernel/cpu/common.c
index eb0f950c0304..e5ae21380f4b 100644
--- a/arch/i386/kernel/cpu/common.c
+++ b/arch/i386/kernel/cpu/common.c
@@ -45,25 +45,6 @@ static int __init cachesize_setup(char *str)
}
__setup("cachesize=", cachesize_setup);
-#ifndef CONFIG_X86_TSC
-static int tsc_disable __initdata = 0;
-
-static int __init tsc_setup(char *str)
-{
- tsc_disable = 1;
- return 1;
-}
-#else
-#define tsc_disable 0
-
-static int __init tsc_setup(char *str)
-{
- printk("notsc: Kernel compiled with CONFIG_X86_TSC, cannot disable TSC.\n");
- return 1;
-}
-#endif
-__setup("notsc", tsc_setup);
-
int __init get_model_name(struct cpuinfo_x86 *c)
{
unsigned int *v;
diff --git a/arch/i386/kernel/cpu/mcheck/k7.c b/arch/i386/kernel/cpu/mcheck/k7.c
index 294c78c9b534..1df54f5a7087 100644
--- a/arch/i386/kernel/cpu/mcheck/k7.c
+++ b/arch/i386/kernel/cpu/mcheck/k7.c
@@ -1,5 +1,5 @@
/*
- * Athlon specific Machine Check Exception Reporting
+ * Athlon/Hammer specific Machine Check Exception Reporting
*/
#include <linux/init.h>
@@ -82,6 +82,9 @@ void __init amd_mcheck_init(struct cpuinfo_x86 *c)
nr_mce_banks = l & 0xff;
for (i=0; i<nr_mce_banks; i++) {
+ /* Don't enable northbridge MCE by default on Hammer */
+ if (boot_cpu_data.x86_model == 15 && i == 4)
+ continue;
wrmsr (MSR_IA32_MC0_CTL+4*i, 0xffffffff, 0xffffffff);
wrmsr (MSR_IA32_MC0_STATUS+4*i, 0x0, 0x0);
}
diff --git a/arch/i386/kernel/cpu/mtrr/main.c b/arch/i386/kernel/cpu/mtrr/main.c
index 46caa93519aa..5b82d52983db 100644
--- a/arch/i386/kernel/cpu/mtrr/main.c
+++ b/arch/i386/kernel/cpu/mtrr/main.c
@@ -574,7 +574,7 @@ static int __init mtrr_init(void)
query the width (in bits) of the physical
addressable memory on the Hammer family.
*/
- if (boot_cpu_data.x86 >= 7
+ if (boot_cpu_data.x86 == 15
&& (cpuid_eax(0x80000000) >= 0x80000008)) {
u32 phys_addr;
phys_addr = cpuid_eax(0x80000008) & 0xff;
diff --git a/arch/i386/kernel/cpu/proc.c b/arch/i386/kernel/cpu/proc.c
index 46d84211917c..af05636fe86d 100644
--- a/arch/i386/kernel/cpu/proc.c
+++ b/arch/i386/kernel/cpu/proc.c
@@ -74,7 +74,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
/* Cache size */
if (c->x86_cache_size >= 0)
seq_printf(m, "cache size\t: %d KB\n", c->x86_cache_size);
-#ifdef CONFIG_SMP
+#ifdef CONFIG_X86_HT
if (cpu_has_ht) {
extern int phys_proc_id[NR_CPUS];
seq_printf(m, "physical id\t: %d\n", phys_proc_id[n]);
diff --git a/arch/i386/kernel/head.S b/arch/i386/kernel/head.S
index fa65e6fd8567..f7bfd10c774c 100644
--- a/arch/i386/kernel/head.S
+++ b/arch/i386/kernel/head.S
@@ -15,6 +15,7 @@
#include <asm/page.h>
#include <asm/pgtable.h>
#include <asm/desc.h>
+#include <asm/cache.h>
#define OLD_CL_MAGIC_ADDR 0x90020
#define OLD_CL_MAGIC 0xA33F
@@ -46,7 +47,7 @@ startup_32:
* Set segments to known values
*/
cld
- movl $(__KERNEL_DS),%eax
+ movl $(__BOOT_DS),%eax
movl %eax,%ds
movl %eax,%es
movl %eax,%fs
@@ -309,7 +310,7 @@ rp_sidt:
ENTRY(stack_start)
.long init_thread_union+8192
- .long __KERNEL_DS
+ .long __BOOT_DS
/* This is the default interrupt "handler" :-) */
int_msg:
@@ -352,12 +353,12 @@ idt_descr:
.long idt_table
# boot GDT descriptor (later on used by CPU#0):
-
+ .word 0 # 32 bit align gdt_desc.address
cpu_gdt_descr:
.word GDT_ENTRIES*8-1
.long cpu_gdt_table
- .fill NR_CPUS-1,6,0 # space for the other GDT descriptors
+ .fill NR_CPUS-1,8,0 # space for the other GDT descriptors
/*
* This is initialized to create an identity-mapping at 0-8M (for bootup
@@ -408,10 +409,21 @@ ENTRY(_stext)
*/
.data
-ALIGN
/*
* The Global Descriptor Table contains 28 quadwords, per-CPU.
*/
+#ifdef CONFIG_SMP
+/*
+ * The boot_gdt_table must mirror the equivalent in setup.S and is
+ * used only by the trampoline for booting other CPUs
+ */
+ .align L1_CACHE_BYTES
+ENTRY(boot_gdt_table)
+ .fill GDT_ENTRY_BOOT_CS,8,0
+ .quad 0x00cf9a000000ffff /* kernel 4GB code at 0x00000000 */
+ .quad 0x00cf92000000ffff /* kernel 4GB data at 0x00000000 */
+#endif
+ .align L1_CACHE_BYTES
ENTRY(cpu_gdt_table)
.quad 0x0000000000000000 /* NULL descriptor */
.quad 0x0000000000000000 /* 0x0b reserved */
diff --git a/arch/i386/kernel/ioport.c b/arch/i386/kernel/ioport.c
index d80fd0b70284..a795bafc6f17 100644
--- a/arch/i386/kernel/ioport.c
+++ b/arch/i386/kernel/ioport.c
@@ -14,6 +14,7 @@
#include <linux/smp_lock.h>
#include <linux/stddef.h>
#include <linux/slab.h>
+#include <linux/thread_info.h>
/* Set EXTENT bits starting at BASE in BITMAP to value TURN_ON. */
static void set_bitmap(unsigned long *bitmap, short base, short extent, int new_value)
@@ -122,5 +123,7 @@ asmlinkage int sys_iopl(unsigned long unused)
return -EPERM;
}
regs->eflags = (regs->eflags & 0xffffcfff) | (level << 12);
+ /* Make sure we return the long way (not sysenter) */
+ set_thread_flag(TIF_SIGPENDING);
return 0;
}
diff --git a/arch/i386/kernel/mpparse.c b/arch/i386/kernel/mpparse.c
index fb5baa1754cc..be74791bdbe7 100644
--- a/arch/i386/kernel/mpparse.c
+++ b/arch/i386/kernel/mpparse.c
@@ -269,6 +269,7 @@ static void __init MP_lintsrc_info (struct mpc_config_lintsrc *m)
BUG();
}
+#if 0
static void __init MP_translation_info (struct mpc_config_translation *m)
{
printk("Translation: record %d, type %d, quad %d, global %d, local %d\n", mpc_record, m->trans_type, m->trans_quad, m->trans_global, m->trans_local);
@@ -327,6 +328,7 @@ static void __init smp_read_mpc_oem(struct mp_config_oemtable *oemtable, \
}
}
}
+#endif
/*
* Read/parse the MPC
diff --git a/arch/i386/kernel/nmi.c b/arch/i386/kernel/nmi.c
index fbae2c8deeaf..9eeaca1be2a1 100644
--- a/arch/i386/kernel/nmi.c
+++ b/arch/i386/kernel/nmi.c
@@ -123,7 +123,7 @@ static int __init setup_nmi_watchdog(char *str)
nmi_watchdog = nmi;
if ((nmi == NMI_LOCAL_APIC) &&
(boot_cpu_data.x86_vendor == X86_VENDOR_AMD) &&
- (boot_cpu_data.x86 == 6))
+ (boot_cpu_data.x86 == 6 || boot_cpu_data.x86 == 15))
nmi_watchdog = nmi;
/*
* We can enable the IO-APIC watchdog
@@ -294,7 +294,7 @@ void __pminit setup_apic_nmi_watchdog (void)
{
switch (boot_cpu_data.x86_vendor) {
case X86_VENDOR_AMD:
- if (boot_cpu_data.x86 != 6)
+ if (boot_cpu_data.x86 != 6 && boot_cpu_data.x86 != 15)
return;
setup_k7_watchdog();
break;
diff --git a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c
index f5e6bb394864..1c9c7d17dcc5 100644
--- a/arch/i386/kernel/process.c
+++ b/arch/i386/kernel/process.c
@@ -558,8 +558,11 @@ asmlinkage int sys_execve(struct pt_regs regs)
if (IS_ERR(filename))
goto out;
error = do_execve(filename, (char **) regs.ecx, (char **) regs.edx, &regs);
- if (error == 0)
+ if (error == 0) {
current->ptrace &= ~PT_DTRACE;
+ /* Make sure we don't return using sysenter.. */
+ set_thread_flag(TIF_SIGPENDING);
+ }
putname(filename);
out:
return error;
diff --git a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c
index 4f0b998e9496..7c08f768281c 100644
--- a/arch/i386/kernel/smpboot.c
+++ b/arch/i386/kernel/smpboot.c
@@ -596,12 +596,14 @@ static inline void inquire_remote_apic(int apicid)
}
#endif
-static int __init wakeup_secondary_via_NMI(int logical_apicid)
+#ifdef WAKE_SECONDARY_VIA_NMI
/*
- * Poke the other CPU in the eye to wake it up. Remember that the normal
+ * Poke the other CPU in the eye via NMI to wake it up. Remember that the normal
* INIT, INIT, STARTUP sequence will reset the chip hard for us, and this
* won't ... remember to clear down the APIC, etc later.
*/
+static int __init
+wakeup_secondary_cpu(int logical_apicid, unsigned long start_eip)
{
unsigned long send_status = 0, accept_status = 0;
int timeout, maxlvt;
@@ -643,8 +645,11 @@ static int __init wakeup_secondary_via_NMI(int logical_apicid)
return (send_status | accept_status);
}
+#endif /* WAKE_SECONDARY_VIA_NMI */
-static int __init wakeup_secondary_via_INIT(int phys_apicid, unsigned long start_eip)
+#ifdef WAKE_SECONDARY_VIA_INIT
+static int __init
+wakeup_secondary_cpu(int phys_apicid, unsigned long start_eip)
{
unsigned long send_status = 0, accept_status = 0;
int maxlvt, timeout, num_starts, j;
@@ -766,6 +771,7 @@ static int __init wakeup_secondary_via_INIT(int phys_apicid, unsigned long start
return (send_status | accept_status);
}
+#endif /* WAKE_SECONDARY_VIA_INIT */
extern unsigned long cpu_initialized;
diff --git a/arch/i386/kernel/suspend_asm.S b/arch/i386/kernel/suspend_asm.S
index e454ec55b824..6fe892675869 100644
--- a/arch/i386/kernel/suspend_asm.S
+++ b/arch/i386/kernel/suspend_asm.S
@@ -64,9 +64,10 @@ ENTRY(do_magic)
jb .L1455
.p2align 4,,7
.L1453:
- movl $104,%eax
+ movl $__USER_DS,%eax
movw %ax, %ds
+ movw %ax, %es
movl saved_context_esp, %esp
movl saved_context_ebp, %ebp
movl saved_context_eax, %eax
diff --git a/arch/i386/kernel/timers/Makefile b/arch/i386/kernel/timers/Makefile
index 69f00b2e02da..4e891aabbfa5 100644
--- a/arch/i386/kernel/timers/Makefile
+++ b/arch/i386/kernel/timers/Makefile
@@ -2,8 +2,6 @@
# Makefile for x86 timers
#
-obj-y := timer.o
+obj-y := timer.o timer_tsc.o timer_pit.o
-obj-y += timer_tsc.o
-obj-y += timer_pit.o
-obj-$(CONFIG_X86_CYCLONE) += timer_cyclone.o
+obj-$(CONFIG_X86_CYCLONE) += timer_cyclone.o
diff --git a/arch/i386/kernel/timers/timer.c b/arch/i386/kernel/timers/timer.c
index 025c8c58fa5d..1ef706d8f878 100644
--- a/arch/i386/kernel/timers/timer.c
+++ b/arch/i386/kernel/timers/timer.c
@@ -8,9 +8,7 @@ extern struct timer_opts timer_tsc;
/* list of timers, ordered by preference, NULL terminated */
static struct timer_opts* timers[] = {
&timer_tsc,
-#ifndef CONFIG_X86_TSC
&timer_pit,
-#endif
NULL,
};
diff --git a/arch/i386/kernel/timers/timer_pit.c b/arch/i386/kernel/timers/timer_pit.c
index 0211f6bceb1d..5ef2af67de6f 100644
--- a/arch/i386/kernel/timers/timer_pit.c
+++ b/arch/i386/kernel/timers/timer_pit.c
@@ -9,7 +9,9 @@
#include <linux/irq.h>
#include <asm/mpspec.h>
#include <asm/timer.h>
+#include <asm/smp.h>
#include <asm/io.h>
+#include <asm/arch_hooks.h>
extern spinlock_t i8259A_lock;
extern spinlock_t i8253_lock;
diff --git a/arch/i386/kernel/timers/timer_tsc.c b/arch/i386/kernel/timers/timer_tsc.c
index 066a86fc5868..2f84d4172cd8 100644
--- a/arch/i386/kernel/timers/timer_tsc.c
+++ b/arch/i386/kernel/timers/timer_tsc.c
@@ -11,6 +11,10 @@
#include <asm/timer.h>
#include <asm/io.h>
+/* processor.h for distable_tsc flag */
+#include <asm/processor.h>
+
+int tsc_disable __initdata = 0;
extern int x86_udelay_tsc;
extern spinlock_t i8253_lock;
@@ -287,6 +291,18 @@ static int init_tsc(void)
return -ENODEV;
}
+/* disable flag for tsc. Takes effect by clearing the TSC cpu flag
+ * in cpu/common.c */
+static int __init tsc_setup(char *str)
+{
+ tsc_disable = 1;
+ return 1;
+}
+
+__setup("notsc", tsc_setup);
+
+
+
/************************************************************/
/* tsc timer_opts struct */
diff --git a/arch/i386/kernel/trampoline.S b/arch/i386/kernel/trampoline.S
index c8d538605faf..28030a414ccf 100644
--- a/arch/i386/kernel/trampoline.S
+++ b/arch/i386/kernel/trampoline.S
@@ -54,7 +54,7 @@ r_base = .
lmsw %ax # into protected mode
jmp flush_instr
flush_instr:
- ljmpl $__KERNEL_CS, $0x00100000
+ ljmpl $__BOOT_CS, $0x00100000
# jump to startup_32 in arch/i386/kernel/head.S
idt_48:
@@ -67,8 +67,8 @@ idt_48:
#
gdt_48:
- .word 0x0800 # gdt limit = 2048, 256 GDT entries
- .long cpu_gdt_table-__PAGE_OFFSET # gdt base = gdt (first SMP CPU)
+ .word __BOOT_DS + 7 # gdt limit
+ .long boot_gdt_table-__PAGE_OFFSET # gdt base = gdt (first SMP CPU)
.globl trampoline_end
trampoline_end:
diff --git a/arch/i386/mach-voyager/setup.c b/arch/i386/mach-voyager/setup.c
index a005c23b88c8..5cd51034dad9 100644
--- a/arch/i386/mach-voyager/setup.c
+++ b/arch/i386/mach-voyager/setup.c
@@ -29,6 +29,9 @@ void __init intr_init_hook(void)
void __init pre_setup_arch_hook(void)
{
+ /* Voyagers run their CPUs from independent clocks, so disable
+ * the TSC code because we can't sync them */
+ tsc_disable = 1;
}
void __init trap_init_hook(void)
diff --git a/arch/i386/mach-voyager/voyager_basic.c b/arch/i386/mach-voyager/voyager_basic.c
index d14e26500377..8c332bc61ce4 100644
--- a/arch/i386/mach-voyager/voyager_basic.c
+++ b/arch/i386/mach-voyager/voyager_basic.c
@@ -21,6 +21,7 @@
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/reboot.h>
+#include <linux/sysrq.h>
#include <asm/io.h>
#include <asm/pgalloc.h>
#include <asm/voyager.h>
@@ -41,6 +42,21 @@ int voyager_level = 0;
struct voyager_SUS *voyager_SUS = NULL;
+#ifdef CONFIG_SMP
+static void
+voyager_dump(int dummy1, struct pt_regs *dummy2, struct tty_struct *dummy3)
+{
+ /* get here via a sysrq */
+ voyager_smp_dump();
+}
+
+static struct sysrq_key_op sysrq_voyager_dump_op = {
+ .handler = voyager_dump,
+ .help_msg = "Voyager",
+ .action_msg = "Dump Voyager Status\n",
+};
+#endif
+
void
voyager_detect(struct voyager_bios_info *bios)
{
@@ -62,6 +78,9 @@ voyager_detect(struct voyager_bios_info *bios)
printk("\n**WARNING**: Voyager HAL only supports Levels 4 and 5 Architectures at the moment\n\n");
/* install the power off handler */
pm_power_off = voyager_power_off;
+#ifdef CONFIG_SMP
+ register_sysrq_key('v', &sysrq_voyager_dump_op);
+#endif
} else {
printk("\n\n**WARNING**: No Voyager Subsystem Found\n");
}
@@ -143,15 +162,6 @@ voyager_memory_detect(int region, __u32 *start, __u32 *length)
return retval;
}
-void
-voyager_dump()
-{
- /* get here via a sysrq */
-#ifdef CONFIG_SMP
- voyager_smp_dump();
-#endif
-}
-
/* voyager specific handling code for timer interrupts. Used to hand
* off the timer tick to the SMP code, since the VIC doesn't have an
* internal timer (The QIC does, but that's another story). */
diff --git a/arch/i386/mach-voyager/voyager_smp.c b/arch/i386/mach-voyager/voyager_smp.c
index d8384ea6463f..6875c8346171 100644
--- a/arch/i386/mach-voyager/voyager_smp.c
+++ b/arch/i386/mach-voyager/voyager_smp.c
@@ -50,11 +50,6 @@ int smp_threads_ready = 0;
* indexed physically */
struct cpuinfo_x86 cpu_data[NR_CPUS] __cacheline_aligned;
-/* Per CPU interrupt stacks */
-extern union thread_union init_irq_union;
-union thread_union *irq_stacks[NR_CPUS] __cacheline_aligned =
- { &init_irq_union, };
-
/* physical ID of the CPU used to boot the system */
unsigned char boot_cpu_id;
@@ -450,6 +445,7 @@ smp_store_cpu_info(int id)
struct cpuinfo_x86 *c=&cpu_data[id];
*c = boot_cpu_data;
+
identify_cpu(c);
}
@@ -512,6 +508,11 @@ start_secondary(void *unused)
/* if we're a quad, we may need to bootstrap other CPUs */
do_quad_bootstrap();
+ /* FIXME: this is rather a poor hack to prevent the CPU
+ * activating softirqs while it's supposed to be waiting for
+ * permission to proceed. Without this, the new per CPU stuff
+ * in the softirqs will fail */
+ local_irq_disable();
set_bit(cpuid, &cpu_callin_map);
/* signal that we're done */
@@ -519,6 +520,7 @@ start_secondary(void *unused)
while (!test_bit(cpuid, &smp_commenced_mask))
rep_nop();
+ local_irq_enable();
local_flush_tlb();
@@ -533,29 +535,7 @@ fork_by_hand(void)
struct pt_regs regs;
/* don't care about the eip and regs settings since we'll
* never reschedule the forked task. */
- return do_fork(CLONE_VM|CLONE_IDLETASK, 0, &regs, 0, NULL);
-}
-
-
-static void __init setup_irq_stack(struct task_struct *p, int cpu)
-{
- unsigned long stk;
-
- stk = __get_free_pages(GFP_KERNEL, THREAD_ORDER+1);
- if (!stk)
- panic("I can't seem to allocate my irq stack. Oh well, giving up.");
-
- irq_stacks[cpu] = (void *)stk;
- memset(irq_stacks[cpu], 0, THREAD_SIZE);
- irq_stacks[cpu]->thread_info.cpu = cpu;
- irq_stacks[cpu]->thread_info.preempt_count = 1;
- /* interrupts are not preemptable */
- p->thread_info->irq_stack = irq_stacks[cpu];
-
- /* If we want to make the irq stack more than one unit
- * deep, we can chain then off of the irq_stack pointer
- * here.
- */
+ return do_fork(CLONE_VM|CLONE_IDLETASK, 0, &regs, 0, NULL, NULL);
}
@@ -617,20 +597,17 @@ do_boot_cpu(__u8 cpu)
if(IS_ERR(idle))
panic("failed fork for CPU%d", cpu);
- setup_irq_stack(idle, cpu);
-
init_idle(idle, cpu);
idle->thread.eip = (unsigned long) start_secondary;
unhash_process(idle);
-
- /* The -4 is to correct for the fact that the stack pointer
- * is used to find the location of the thread_info structure
- * by masking off several of the LSBs. Without the -4, esp
- * is pointing to the page after the one the stack is on.
- */
- stack_start.esp = (void *)(THREAD_SIZE - 4 + (char *)idle->thread_info);
-
+ /* init_tasks (in sched.c) is indexed logically */
+#if 0
+ // for AC kernels
+ stack_start.esp = (THREAD_SIZE + (__u8 *)TSK_TO_KSTACK(idle));
+#else
+ stack_start.esp = (void *) (1024 + PAGE_SIZE + (char *)idle->thread_info);
+#endif
/* Note: Don't modify initial ss override */
VDEBUG(("VOYAGER SMP: Booting CPU%d at 0x%lx[%x:%x], stack %p\n", cpu,
(unsigned long)hijack_source.val, hijack_source.idt.Segment,
@@ -764,6 +741,9 @@ smp_boot_cpus(void)
/* enable our own CPIs */
vic_enable_cpi();
+
+ set_bit(boot_cpu_id, &cpu_online_map);
+ set_bit(boot_cpu_id, &cpu_callout_map);
/* loop over all the extended VIC CPUs and boot them. The
* Quad CPUs must be bootstrapped by their extended VIC cpu */
@@ -1312,12 +1292,9 @@ smp_vic_timer_interrupt(struct pt_regs *regs)
static inline void
wrapper_smp_local_timer_interrupt(struct pt_regs *regs)
{
- __u8 cpu = smp_processor_id();
-
irq_enter();
smp_local_timer_interrupt(regs);
irq_exit();
-
}
/* local (per CPU) timer interrupt. It does both profiling and
diff --git a/arch/i386/oprofile/nmi_int.c b/arch/i386/oprofile/nmi_int.c
index 45c65d3a4efa..f33880c8f87b 100644
--- a/arch/i386/oprofile/nmi_int.c
+++ b/arch/i386/oprofile/nmi_int.c
@@ -233,6 +233,7 @@ int __init nmi_init(struct oprofile_operations ** ops, enum oprofile_cpu * cpu)
*cpu = OPROFILE_CPU_ATHLON;
break;
+#ifndef CONFIG_X86_64
case X86_VENDOR_INTEL:
/* Less than a P6-class processor */
if (family != 6)
@@ -248,6 +249,7 @@ int __init nmi_init(struct oprofile_operations ** ops, enum oprofile_cpu * cpu)
model = &op_ppro_spec;
break;
+#endif
default:
return 0;
diff --git a/arch/i386/oprofile/op_model_athlon.c b/arch/i386/oprofile/op_model_athlon.c
index b4aabede5531..722353a5b7ff 100644
--- a/arch/i386/oprofile/op_model_athlon.c
+++ b/arch/i386/oprofile/op_model_athlon.c
@@ -99,7 +99,7 @@ static int athlon_check_ctrs(unsigned int const cpu,
for (i = 0 ; i < NUM_COUNTERS; ++i) {
CTR_READ(low, high, msrs, i);
if (CTR_OVERFLOWED(low)) {
- oprofile_add_sample(regs->eip, i, cpu);
+ oprofile_add_sample(instruction_pointer(regs), i, cpu);
CTR_WRITE(reset_value[i], msrs, i);
return 1;
}
diff --git a/arch/i386/oprofile/op_model_ppro.c b/arch/i386/oprofile/op_model_ppro.c
index 0f00c4d1e924..cff299fb1461 100644
--- a/arch/i386/oprofile/op_model_ppro.c
+++ b/arch/i386/oprofile/op_model_ppro.c
@@ -94,7 +94,7 @@ static int ppro_check_ctrs(unsigned int const cpu,
for (i = 0 ; i < NUM_COUNTERS; ++i) {
CTR_READ(low, high, msrs, i);
if (CTR_OVERFLOWED(low)) {
- oprofile_add_sample(regs->eip, i, cpu);
+ oprofile_add_sample(instruction_pointer(regs), i, cpu);
CTR_WRITE(reset_value[i], msrs, i);
return 1;
}
diff --git a/arch/i386/oprofile/timer_int.c b/arch/i386/oprofile/timer_int.c
index 1159b7597eef..d4f0c24d89d9 100644
--- a/arch/i386/oprofile/timer_int.c
+++ b/arch/i386/oprofile/timer_int.c
@@ -21,7 +21,7 @@ static int timer_notify(struct notifier_block * self, unsigned long val, void *
struct pt_regs * regs = (struct pt_regs *)data;
int cpu = smp_processor_id();
- oprofile_add_sample(regs->eip, 0, cpu);
+ oprofile_add_sample(instruction_pointer(regs), 0, cpu);
return 0;
}
diff --git a/arch/m68k/Kconfig b/arch/m68k/Kconfig
index 59e449a9187f..82fb20e2b639 100644
--- a/arch/m68k/Kconfig
+++ b/arch/m68k/Kconfig
@@ -2070,48 +2070,6 @@ config HPDCA
If you want to use the internal "DCA" serial ports on an HP300
machine, say Y here.
-config SUN3X_ZS
- bool "Sun3/3x builtin serial support"
- depends on SUN3 || SUN3X
- help
- ZS refers to a type of asynchronous serial port built in to the Sun3
- and Sun3x workstations; if you have a Sun 3, you probably have
- these. Say 'Y' to support ZS ports directly. This option must be
- enabled in order to support the
- keyboard and mouse ports.
-
-config SUN_KEYBOARD
- bool
- depends on SUN3X_ZS
- default y
- help
- Say Y here to support the keyboard found on Sun 3 and 3x
- workstations. It can also be used support Sun Type-5 keyboards
- through an adaptor. See
- <http://www.suse.cz/development/input/adapters.html> and
- <http://sourceforge.net/projects/linuxconsole/> for details on the
- latter.
-
-config SUN_MOUSE
- bool
- depends on SUN3X_ZS
- default y
-
-config SBUS
- bool
- depends on SUN3X_ZS
- default y
-
-config SBUSCHAR
- bool
- depends on SUN3X_ZS
- default y
-
-config SUN_SERIAL
- bool
- depends on SUN3X_ZS
- default y
-
config MVME147_SCC
bool "SCC support for MVME147 serial ports"
depends on MVME147
@@ -2148,7 +2106,7 @@ config DN_SERIAL
config SERIAL_CONSOLE
bool "Support for serial port console"
- depends on (AMIGA || ATARI || MAC || HP300 || SUN3 || SUN3X || VME || APOLLO) && (ATARI_MFPSER=y || ATARI_SCC=y || ATARI_MIDI=y || MAC_SCC=y || AMIGA_BUILTIN_SERIAL=y || GVPIOEXT=y || MULTIFACE_III_TTY=y || HPDCA=y || SUN3X_ZS || SERIAL=y || MVME147_SCC || SERIAL167 || MVME162_SCC || BVME6000_SCC || DN_SERIAL)
+ depends on (AMIGA || ATARI || MAC || HP300 || SUN3 || SUN3X || VME || APOLLO) && (ATARI_MFPSER=y || ATARI_SCC=y || ATARI_MIDI=y || MAC_SCC=y || AMIGA_BUILTIN_SERIAL=y || GVPIOEXT=y || MULTIFACE_III_TTY=y || HPDCA=y || SERIAL=y || MVME147_SCC || SERIAL167 || MVME162_SCC || BVME6000_SCC || DN_SERIAL)
---help---
If you say Y here, it will be possible to use a serial port as the
system console (the system console is the device which receives all
diff --git a/arch/m68k/Makefile b/arch/m68k/Makefile
index 31cff1fde9c5..8bf52e30794c 100644
--- a/arch/m68k/Makefile
+++ b/arch/m68k/Makefile
@@ -19,6 +19,7 @@ COMPILE_ARCH = $(shell uname -m)
# override top level makefile
AS += -m68020
LDFLAGS := -m m68kelf
+LDFLAGS_BLOB := --format binary --oformat elf32-m68k
ifneq ($(COMPILE_ARCH),$(ARCH))
# prefix for cross-compiling binaries
CROSS_COMPILE = m68k-linux-
diff --git a/arch/m68k/amiga/cia.c b/arch/m68k/amiga/cia.c
index bebb2d4b171c..bceff2e4c7c4 100644
--- a/arch/m68k/amiga/cia.c
+++ b/arch/m68k/amiga/cia.c
@@ -17,6 +17,7 @@
#include <linux/kernel_stat.h>
#include <linux/init.h>
#include <linux/seq_file.h>
+#include <linux/interrupt.h>
#include <asm/irq.h>
#include <asm/amigahw.h>
diff --git a/arch/m68k/amiga/config.c b/arch/m68k/amiga/config.c
index 5abf761945ac..49e2b36659c9 100644
--- a/arch/m68k/amiga/config.c
+++ b/arch/m68k/amiga/config.c
@@ -21,6 +21,7 @@
#include <linux/rtc.h>
#include <linux/init.h>
#include <linux/vt_kern.h>
+#include <linux/interrupt.h>
#ifdef CONFIG_ZORRO
#include <linux/zorro.h>
#endif
diff --git a/arch/m68k/apollo/config.c b/arch/m68k/apollo/config.c
index 54f4d43d1ed3..5dae74f908f3 100644
--- a/arch/m68k/apollo/config.c
+++ b/arch/m68k/apollo/config.c
@@ -6,6 +6,7 @@
#include <linux/console.h>
#include <linux/rtc.h>
#include <linux/vt_kern.h>
+#include <linux/interrupt.h>
#include <asm/setup.h>
#include <asm/bootinfo.h>
diff --git a/arch/m68k/atari/ataints.c b/arch/m68k/atari/ataints.c
index 8fc840c0bafc..80c45418188c 100644
--- a/arch/m68k/atari/ataints.c
+++ b/arch/m68k/atari/ataints.c
@@ -168,7 +168,7 @@ asmlinkage void IRQ_NAME(n); \
void atari_slow_irq_##n##_dummy (void) { \
__asm__ (__ALIGN_STR "\n" \
"atari_slow_irq_" #n "_handler:\t" \
-" addql #1,%5\n" /* local_irq_count++ */ \
+" addl %6,%5\n" /* preempt_count() += HARDIRQ_OFFSET */ \
SAVE_ALL_INT "\n" \
GET_CURRENT(%%d0) "\n" \
" andb #~(1<<(%c3&7)),%a4:w\n" /* mask this interrupt */ \
@@ -194,7 +194,7 @@ __asm__ (__ALIGN_STR "\n" \
"n" (PT_OFF_SR), "n" (n), \
"i" (n & 8 ? (n & 16 ? &tt_mfp.int_mk_a : &mfp.int_mk_a) \
: (n & 16 ? &tt_mfp.int_mk_b : &mfp.int_mk_b)), \
- "m" (local_irq_count(0)) \
+ "m" (preempt_count()), "di" (HARDIRQ_OFFSET) \
); \
for (;;); /* fake noreturn */ \
}
@@ -276,7 +276,7 @@ __asm__ (__ALIGN_STR "\n"
"atari_fast_irq_handler:
orw #0x700,%%sr /* disable all interrupts */
atari_prio_irq_handler:\t
- addql #1,%2\n" /* local_irq_count++ */
+ addl %3,%2\n" /* preempt_count() += HARDIRQ_OFFSET */
SAVE_ALL_INT "\n"
GET_CURRENT(%%d0) "
/* get vector number from stack frame and convert to source */
@@ -297,7 +297,7 @@ atari_prio_irq_handler:\t
addql #4,%%sp
jbra ret_from_interrupt"
: : "i" (&kstat_cpu(0).irqs), "n" (PT_OFF_FORMATVEC),
- "m" (local_irq_count(0))
+ "m" (preempt_count()), "di" (HARDIRQ_OFFSET)
);
for (;;);
}
@@ -481,8 +481,7 @@ int atari_request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_r
irq_node_t *node;
unsigned long flags;
- save_flags(flags);
- cli();
+ local_irq_save(flags);
if (irq_handler[irq].handler != atari_call_irq_list) {
/* Only one handler yet, make a node for this first one */
@@ -507,7 +506,7 @@ int atari_request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_r
node->next = irq_handler[irq].dev_id;
irq_handler[irq].dev_id = node;
- restore_flags(flags);
+ local_irq_restore(flags);
return 0;
} else {
printk ("%s: Irq %d allocated by other type int (call from %s)\n",
@@ -531,13 +530,12 @@ void atari_free_irq(unsigned int irq, void *dev_id)
if (vectors[vector] == bad_interrupt)
goto not_found;
- save_flags(flags);
- cli();
+ local_irq_save(flags);
if (irq_handler[irq].handler != atari_call_irq_list) {
/* It's the only handler for the interrupt */
if (irq_handler[irq].dev_id != dev_id) {
- restore_flags(flags);
+ local_irq_restore(flags);
goto not_found;
}
irq_handler[irq].handler = NULL;
@@ -548,7 +546,7 @@ void atari_free_irq(unsigned int irq, void *dev_id)
atari_disable_irq(irq);
atari_turnoff_irq(irq);
- restore_flags(flags);
+ local_irq_restore(flags);
return;
}
@@ -557,7 +555,7 @@ void atari_free_irq(unsigned int irq, void *dev_id)
if ((*list)->dev_id == dev_id) break;
}
if (!*list) {
- restore_flags(flags);
+ local_irq_restore(flags);
goto not_found;
}
@@ -574,7 +572,7 @@ void atari_free_irq(unsigned int irq, void *dev_id)
node->handler = NULL; /* Mark it as free for reallocation */
}
- restore_flags(flags);
+ local_irq_restore(flags);
return;
not_found:
diff --git a/arch/m68k/atari/atasound.c b/arch/m68k/atari/atasound.c
index 7b401d17fef9..d3a60be60069 100644
--- a/arch/m68k/atari/atasound.c
+++ b/arch/m68k/atari/atasound.c
@@ -58,8 +58,7 @@ void atari_mksound (unsigned int hz, unsigned int ticks)
unsigned char tmp;
int period;
- save_flags(flags);
- cli();
+ local_irq_save(flags);
/* Disable generator A in mixer control. */
@@ -106,5 +105,5 @@ void atari_mksound (unsigned int hz, unsigned int ticks)
tmp &= ~1;
sound_ym.wd_data = tmp;
}
- restore_flags(flags);
+ local_irq_restore(flags);
}
diff --git a/arch/m68k/atari/config.c b/arch/m68k/atari/config.c
index 035bb3e264dc..8fa786dbd982 100644
--- a/arch/m68k/atari/config.c
+++ b/arch/m68k/atari/config.c
@@ -509,12 +509,11 @@ static void atari_heartbeat( int on )
if (atari_dont_touch_floppy_select)
return;
- save_flags(flags);
- cli();
+ local_irq_save(flags);
sound_ym.rd_data_reg_sel = 14; /* Select PSG Port A */
tmp = sound_ym.rd_data_reg_sel;
sound_ym.wd_data = on ? (tmp & ~0x02) : (tmp | 0x02);
- restore_flags(flags);
+ local_irq_restore(flags);
}
#endif
@@ -569,7 +568,7 @@ static void atari_reset (void)
/* processor independent: turn off interrupts and reset the VBR;
* the caches must be left enabled, else prefetching the final jump
* instruction doesn't work. */
- cli();
+ local_irq_disable();
__asm__ __volatile__
("moveq #0,%/d0\n\t"
"movec %/d0,%/vbr"
diff --git a/arch/m68k/atari/stdma.c b/arch/m68k/atari/stdma.c
index 1aff226be34b..ec7230628c76 100644
--- a/arch/m68k/atari/stdma.c
+++ b/arch/m68k/atari/stdma.c
@@ -33,6 +33,7 @@
#include <linux/genhd.h>
#include <linux/sched.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <asm/atari_stdma.h>
#include <asm/atariints.h>
@@ -75,10 +76,9 @@ static void stdma_int (int irq, void *dummy, struct pt_regs *fp);
void stdma_lock(void (*handler)(int, void *, struct pt_regs *), void *data)
{
- unsigned long oldflags;
+ unsigned long flags;
- save_flags(oldflags);
- cli(); /* protect lock */
+ local_irq_save(flags); /* protect lock */
while(stdma_locked)
/* Since the DMA is used for file system purposes, we
@@ -89,7 +89,7 @@ void stdma_lock(void (*handler)(int, void *, struct pt_regs *), void *data)
stdma_locked = 1;
stdma_isr = handler;
stdma_isr_data = data;
- restore_flags(oldflags);
+ local_irq_restore(flags);
}
@@ -106,17 +106,16 @@ void stdma_lock(void (*handler)(int, void *, struct pt_regs *), void *data)
void stdma_release(void)
{
- unsigned long oldflags;
+ unsigned long flags;
+
+ local_irq_save(flags);
- save_flags(oldflags);
- cli();
-
stdma_locked = 0;
stdma_isr = NULL;
stdma_isr_data = NULL;
wake_up(&stdma_wait);
- restore_flags(oldflags);
+ local_irq_restore(flags);
}
diff --git a/arch/m68k/atari/stram.c b/arch/m68k/atari/stram.c
index 1c9268b5ed4f..cc1586d87845 100644
--- a/arch/m68k/atari/stram.c
+++ b/arch/m68k/atari/stram.c
@@ -765,7 +765,7 @@ static int unswap_by_read(unsigned short *map, unsigned long max,
return -ENOMEM;
}
read_lock(&tasklist_lock);
- for_each_task(p)
+ for_each_process(p)
unswap_process(p->mm, entry, page);
read_unlock(&tasklist_lock);
shmem_unuse(entry, page);
@@ -984,7 +984,7 @@ static void do_stram_request(request_queue_t *q)
unsigned long len = req->current_nr_sectors << 9;
if ((start + len) > swap_end) {
printk( KERN_ERR "stram: bad access beyond end of device: "
- "block=%ld, count=%ld\n",
+ "block=%ld, count=%d\n",
req->sector,
req->current_nr_sectors );
end_request(req, 0);
diff --git a/arch/m68k/atari/time.c b/arch/m68k/atari/time.c
index b57a80594a9a..98e344a0111c 100644
--- a/arch/m68k/atari/time.c
+++ b/arch/m68k/atari/time.c
@@ -216,8 +216,7 @@ int atari_tt_hwclk( int op, struct rtc_time *t )
schedule_timeout(HWCLK_POLL_INTERVAL);
}
- save_flags(flags);
- cli();
+ local_irq_save(flags);
RTC_WRITE( RTC_CONTROL, ctrl | RTC_SET );
if (!op) {
sec = RTC_READ( RTC_SECONDS );
@@ -238,7 +237,7 @@ int atari_tt_hwclk( int op, struct rtc_time *t )
if (wday >= 0) RTC_WRITE( RTC_DAY_OF_WEEK, wday );
}
RTC_WRITE( RTC_CONTROL, ctrl & ~RTC_SET );
- restore_flags(flags);
+ local_irq_restore(flags);
if (!op) {
/* read: adjust values */
diff --git a/arch/m68k/bvme6000/config.c b/arch/m68k/bvme6000/config.c
index eff77830e92c..58771d3367be 100644
--- a/arch/m68k/bvme6000/config.c
+++ b/arch/m68k/bvme6000/config.c
@@ -24,6 +24,7 @@
#include <linux/major.h>
#include <linux/genhd.h>
#include <linux/rtc.h>
+#include <linux/interrupt.h>
#include <asm/bootinfo.h>
#include <asm/system.h>
@@ -358,8 +359,7 @@ int bvme6000_set_clock_mmss (unsigned long nowtime)
? real_minutes - rtc_minutes
: rtc_minutes - real_minutes) < 30)
{
- save_flags(flags);
- cli();
+ local_irq_save(flags);
rtc_tenms = rtc->bcd_tenms;
while (rtc_tenms == rtc->bcd_tenms)
;
@@ -367,7 +367,7 @@ int bvme6000_set_clock_mmss (unsigned long nowtime)
;
rtc->bcd_min = bin2bcd(real_minutes);
rtc->bcd_sec = bin2bcd(real_seconds);
- restore_flags(flags);
+ local_irq_restore(flags);
}
else
retval = -1;
diff --git a/arch/m68k/bvme6000/rtc.c b/arch/m68k/bvme6000/rtc.c
index 071771d0182b..e9fe8968fb5f 100644
--- a/arch/m68k/bvme6000/rtc.c
+++ b/arch/m68k/bvme6000/rtc.c
@@ -49,8 +49,7 @@ static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
switch (cmd) {
case RTC_RD_TIME: /* Read the time/date from RTC */
{
- save_flags(flags);
- cli();
+ local_irq_save(flags);
/* Ensure clock and real-time-mode-register are accessible */
msr = rtc->msr & 0xc0;
rtc->msr = 0x40;
@@ -66,7 +65,7 @@ static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
wtime.tm_wday = BCD2BIN(rtc->bcd_dow)-1;
} while (wtime.tm_sec != BCD2BIN(rtc->bcd_sec));
rtc->msr = msr;
- restore_flags(flags);
+ local_irq_restore(flags);
return copy_to_user((void *)arg, &wtime, sizeof wtime) ?
-EFAULT : 0;
}
@@ -106,8 +105,7 @@ static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
if (yrs >= 2070)
return -EINVAL;
- save_flags(flags);
- cli();
+ local_irq_save(flags);
/* Ensure clock and real-time-mode-register are accessible */
msr = rtc->msr & 0xc0;
rtc->msr = 0x40;
@@ -125,7 +123,7 @@ static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
rtc->t0cr_rtmr = yrs%4 | 0x08;
rtc->msr = msr;
- restore_flags(flags);
+ local_irq_restore(flags);
return 0;
}
default:
@@ -179,7 +177,6 @@ int __init rtc_DP8570A_init(void)
return -ENODEV;
printk(KERN_INFO "DP8570A Real Time Clock Driver v%s\n", RTC_VERSION);
- misc_register(&rtc_dev);
- return 0;
+ return misc_register(&rtc_dev);
}
diff --git a/arch/m68k/kernel/entry.S b/arch/m68k/kernel/entry.S
index 6e371c61c727..1faabadaf569 100644
--- a/arch/m68k/kernel/entry.S
+++ b/arch/m68k/kernel/entry.S
@@ -552,10 +552,10 @@ sys_call_table:
.long sys_adjtimex
.long sys_mprotect /* 125 */
.long sys_sigprocmask
- .long sys_create_module
+ .long sys_ni_syscall /* old "create_module" */
.long sys_init_module
.long sys_delete_module
- .long sys_get_kernel_syms /* 130 */
+ .long sys_ni_syscall /* 130 - old "get_kernel_syms" */
.long sys_quotactl
.long sys_getpgid
.long sys_fchdir
@@ -592,7 +592,7 @@ sys_call_table:
.long sys_setresuid16
.long sys_getresuid16 /* 165 */
.long sys_getpagesize
- .long sys_query_module
+ .long sys_ni_syscall /* old sys_query_module */
.long sys_poll
.long sys_nfsservctl
.long sys_setresgid16 /* 170 */
diff --git a/arch/m68k/kernel/head.S b/arch/m68k/kernel/head.S
index bcaba1d0d973..bccb3147ee81 100644
--- a/arch/m68k/kernel/head.S
+++ b/arch/m68k/kernel/head.S
@@ -21,7 +21,7 @@
** 96/04/26 Guenther Kelleter: fixed identity mapping for Falcon with
** Magnum- and FX-alternate ram
** 98/04/25 Phil Blundell: added HP300 support
-** 1998/08/30 David Kilzer: Added support for fbcon_font_desc structures
+** 1998/08/30 David Kilzer: Added support for font_desc structures
** for linux-2.1.115
** 9/02/11 Richard Zidlicky: added Q40 support (initial vesion 99/01/01)
**
@@ -130,7 +130,7 @@
*
* mmu_engage
* ----------
- * Thanks to a small helping routine enabling the mmu got quiet simple
+ * Thanks to a small helping routine enabling the mmu got quite simple
* and there is only one way left. mmu_engage makes a complete a new mapping
* that only includes the absolute necessary to be able to jump to the final
* postion and to restore the original mapping.
@@ -238,7 +238,7 @@
* In theory these could be determined at run time or handed
* over by the booter. But, let's be real, it's a fine hard
* coded value. (But, you will notice the code is run-time
- * flexible!) A pointer to the font's struct fbcon_font_desc
+ * flexible!) A pointer to the font's struct font_desc
* is kept locally in Lconsole_font. It is used to determine
* font size information dynamically.
*
@@ -1202,7 +1202,7 @@ L(not6000):
*
* Map the kernel (that's already done),
* Map the I/O (on most machines that's the
- * 0x5000.0000 ... 0x5200.0000 range,
+ * 0x5000.0000 ... 0x5300.0000 range,
* Map the video frame buffer using as few pages
* as absolutely (this requirement mostly stems from
* the fact that when the frame buffer is at
@@ -1246,10 +1246,11 @@ L(mmu_init_mac):
andl L(mac_videobase),%d0
mmu_map #VIDEOMEMBASE,%d0,#VIDEOMEMSIZE,%d3
- mmu_map_eq #0x40800000,#0x02000000,%d3 /* rom ? */
- mmu_map_eq #0x50000000,#0x02000000,%d3
- mmu_map_eq #0x60000000,#0x00400000,%d3
- mmu_map_eq #0x9c000000,#0x00400000,%d3
+ /* The ROM starts at 4000 0000 */
+ mmu_map_eq #0x40000000,#0x02000000,%d3
+ /* IO devices */
+ mmu_map_eq #0x50000000,#0x03000000,%d3
+ /* NuBus slot space */
mmu_map_tt #1,#0xf8000000,#0x08000000,%d3
jbra L(mmu_init_done)
@@ -1461,6 +1462,9 @@ L(mmu_fixup_done):
andl L(mac_videobase),%d0
addl #VIDEOMEMBASE,%d0
movel %d0,L(mac_videobase)
+#ifdef MAC_SERIAL_DEBUG
+ orl #0x50000000,L(mac_sccbase)
+#endif
1:
#endif
@@ -3032,10 +3036,6 @@ func_start serial_putc,%d0/%d1/%a0/%a1
#ifdef CONFIG_MAC
is_not_mac(5f)
-#ifdef CONSOLE
- console_putc %d0
-#endif /* CONSOLE */
-
#ifdef MAC_SERIAL_DEBUG
#ifdef MAC_USE_SCC_A
@@ -3371,7 +3371,7 @@ console_clear_loop:
* a1 = address of Lconsole_font pointer
*/
lea %pc@(L(console_font)),%a1
- movel %a0,%a1@ /* store pointer to struct fbcon_font_desc in Lconsole_font */
+ movel %a0,%a1@ /* store pointer to struct font_desc in Lconsole_font */
tstl %a0
jeq 1f
@@ -3383,10 +3383,10 @@ console_clear_loop:
*/
/* ASSERT: a0 = contents of Lconsole_font */
movel %d3,%d0 /* screen width in pixels */
- divul %a0@(FBCON_FONT_DESC_WIDTH),%d0 /* d0 = max num chars per row */
+ divul %a0@(FONT_DESC_WIDTH),%d0 /* d0 = max num chars per row */
movel %d4,%d1 /* screen height in pixels */
- divul %a0@(FBCON_FONT_DESC_HEIGHT),%d1 /* d1 = max num rows */
+ divul %a0@(FONT_DESC_HEIGHT),%d1 /* d1 = max num rows */
movel %d0,%a2@(Lconsole_struct_num_columns)
movel %d1,%a2@(Lconsole_struct_num_rows)
@@ -3430,6 +3430,10 @@ L(console_put_stats):
putn %pc@(L(cputype))
putc '\n'
+#ifdef MAC_SERIAL_DEBUG
+ putn %pc@(L(mac_sccbase))
+ putc '\n'
+#endif
# if defined(MMU_PRINT)
jbsr mmu_print_machine_cpu_types
# endif /* MMU_PRINT */
@@ -3489,7 +3493,7 @@ console_scroll:
movel %pc@(L(console_font)),%a0
tstl %a0
jeq 1f
- mulul %a0@(FBCON_FONT_DESC_HEIGHT),%d5 /* account for # scan lines per character */
+ mulul %a0@(FONT_DESC_HEIGHT),%d5 /* account for # scan lines per character */
addal %d5,%a2
/*
@@ -3508,7 +3512,7 @@ console_scroll:
lea %pc@(L(mac_rowbytes)),%a0
movel %a0@,%d6
movel %pc@(L(console_font)),%a0
- subl %a0@(FBCON_FONT_DESC_HEIGHT),%d4 /* we're not scrolling the top row! */
+ subl %a0@(FONT_DESC_HEIGHT),%d4 /* we're not scrolling the top row! */
mulul %d4,%d6 /* scan line bytes x num scan lines */
divul #32,%d6 /* we'll move 8 longs at a time */
subq #1,%d6
@@ -3527,7 +3531,7 @@ console_scroll_loop:
lea %pc@(L(mac_rowbytes)),%a0
movel %a0@,%d6
movel %pc@(L(console_font)),%a0
- mulul %a0@(FBCON_FONT_DESC_HEIGHT),%d6 /* scan line bytes x font height */
+ mulul %a0@(FONT_DESC_HEIGHT),%d6 /* scan line bytes x font height */
divul #32,%d6 /* we'll move 8 words at a time */
subq #1,%d6
@@ -3606,19 +3610,19 @@ console_not_home:
movel %a0@(Lconsole_struct_num_columns),%d1
cmpl %d1,%d0
jcs 1f
- putc '\n' /* recursion is OK! */
+ console_putc #'\n' /* recursion is OK! */
1:
movel %a0@(Lconsole_struct_cur_row),%d1
/*
* At this point we make a shift in register usage
- * a0 = address of pointer to font data (fbcon_font_desc)
+ * a0 = address of pointer to font data (font_desc)
*/
movel %pc@(L(console_font)),%a0
- movel %a0@(FBCON_FONT_DESC_DATA),%a1 /* Load fbcon_font_desc.data into a1 */
+ movel %a0@(FONT_DESC_DATA),%a1 /* Load font_desc.data into a1 */
andl #0x000000ff,%d7
/* ASSERT: a0 = contents of Lconsole_font */
- mulul %a0@(FBCON_FONT_DESC_HEIGHT),%d7 /* d7 = index into font data */
+ mulul %a0@(FONT_DESC_HEIGHT),%d7 /* d7 = index into font data */
addl %d7,%a1 /* a1 = points to char image */
/*
@@ -3631,15 +3635,15 @@ console_not_home:
* d7 = count down for the font's pixel count in height
*/
/* ASSERT: a0 = contents of Lconsole_font */
- mulul %a0@(FBCON_FONT_DESC_WIDTH),%d0
- mulul %a0@(FBCON_FONT_DESC_HEIGHT),%d1
- movel %a0@(FBCON_FONT_DESC_HEIGHT),%d7 /* Load fbcon_font_desc.height into d7 */
+ mulul %a0@(FONT_DESC_WIDTH),%d0
+ mulul %a0@(FONT_DESC_HEIGHT),%d1
+ movel %a0@(FONT_DESC_HEIGHT),%d7 /* Load font_desc.height into d7 */
subq #1,%d7
console_read_char_scanline:
moveb %a1@+,%d3
/* ASSERT: a0 = contents of Lconsole_font */
- movel %a0@(FBCON_FONT_DESC_WIDTH),%d6 /* Load fbcon_font_desc.width into d6 */
+ movel %a0@(FONT_DESC_WIDTH),%d6 /* Load font_desc.width into d6 */
subql #1,%d6
console_do_font_scanline:
@@ -3650,7 +3654,7 @@ console_do_font_scanline:
dbra %d6,console_do_font_scanline
/* ASSERT: a0 = contents of Lconsole_font */
- subl %a0@(FBCON_FONT_DESC_WIDTH),%d0
+ subl %a0@(FONT_DESC_WIDTH),%d0
addq #1,%d1
dbra %d7,console_read_char_scanline
@@ -3848,7 +3852,7 @@ L(console_globals):
.long 0 /* left edge */
.long 0 /* mac putc */
L(console_font):
- .long 0 /* pointer to console font (struct fbcon_font_desc) */
+ .long 0 /* pointer to console font (struct font_desc) */
#endif /* CONSOLE */
#if defined(MMU_PRINT)
diff --git a/arch/m68k/kernel/m68k_defs.c b/arch/m68k/kernel/m68k_defs.c
index 55a386813236..4dd235d15b29 100644
--- a/arch/m68k/kernel/m68k_defs.c
+++ b/arch/m68k/kernel/m68k_defs.c
@@ -78,13 +78,13 @@ int main(void)
DEFINE(BIR_SIZE, offsetof(struct bi_record, size));
DEFINE(BIR_DATA, offsetof(struct bi_record, data));
- /* offsets into fbcon_font_desc (video/font.h) */
- DEFINE(FBCON_FONT_DESC_IDX, offsetof(struct fbcon_font_desc, idx));
- DEFINE(FBCON_FONT_DESC_NAME, offsetof(struct fbcon_font_desc, name));
- DEFINE(FBCON_FONT_DESC_WIDTH, offsetof(struct fbcon_font_desc, width));
- DEFINE(FBCON_FONT_DESC_HEIGHT, offsetof(struct fbcon_font_desc, height));
- DEFINE(FBCON_FONT_DESC_DATA, offsetof(struct fbcon_font_desc, data));
- DEFINE(FBCON_FONT_DESC_PREF, offsetof(struct fbcon_font_desc, pref));
+ /* offsets into font_desc (drivers/video/console/font.h) */
+ DEFINE(FONT_DESC_IDX, offsetof(struct font_desc, idx));
+ DEFINE(FONT_DESC_NAME, offsetof(struct font_desc, name));
+ DEFINE(FONT_DESC_WIDTH, offsetof(struct font_desc, width));
+ DEFINE(FONT_DESC_HEIGHT, offsetof(struct font_desc, height));
+ DEFINE(FONT_DESC_DATA, offsetof(struct font_desc, data));
+ DEFINE(FONT_DESC_PREF, offsetof(struct font_desc, pref));
/* signal defines */
DEFINE(SIGSEGV, SIGSEGV);
diff --git a/arch/m68k/kernel/m68k_ksyms.c b/arch/m68k/kernel/m68k_ksyms.c
index 15b76c74ba60..ad8aebdfd0e5 100644
--- a/arch/m68k/kernel/m68k_ksyms.c
+++ b/arch/m68k/kernel/m68k_ksyms.c
@@ -26,7 +26,6 @@ asmlinkage long long __muldi3 (long long, long long);
extern char m68k_debug_device[];
extern void dump_thread(struct pt_regs *, struct user *);
-extern int dump_fpu(elf_fpregset_t *);
/* platform dependent support */
diff --git a/arch/m68k/kernel/process.c b/arch/m68k/kernel/process.c
index 5c50d1f142a2..4d19c1c3979b 100644
--- a/arch/m68k/kernel/process.c
+++ b/arch/m68k/kernel/process.c
@@ -202,14 +202,15 @@ void flush_thread(void)
asmlinkage int m68k_fork(struct pt_regs *regs)
{
struct task_struct *p;
- p = do_fork(SIGCHLD, rdusp(), regs, 0, NULL);
+ p = do_fork(SIGCHLD, rdusp(), regs, 0, NULL, NULL);
return IS_ERR(p) ? PTR_ERR(p) : p->pid;
}
asmlinkage int m68k_vfork(struct pt_regs *regs)
{
struct task_struct *p;
- p = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, rdusp(), regs, 0, NULL);
+ p = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, rdusp(), regs, 0, NULL,
+ NULL);
return IS_ERR(p) ? PTR_ERR(p) : p->pid;
}
@@ -218,15 +219,17 @@ asmlinkage int m68k_clone(struct pt_regs *regs)
unsigned long clone_flags;
unsigned long newsp;
struct task_struct *p;
- int *user_tid;
+ int *parent_tidptr, *child_tidptr;
/* syscall2 puts clone_flags in d1 and usp in d2 */
clone_flags = regs->d1;
newsp = regs->d2;
- user_tid = (int *)regs->d3;
+ parent_tidptr = (int *)regs->d3;
+ child_tidptr = (int *)regs->d4;
if (!newsp)
newsp = rdusp();
- p = do_fork(clone_flags & ~CLONE_IDLETASK, newsp, regs, 0, user_tid);
+ p = do_fork(clone_flags & ~CLONE_IDLETASK, newsp, regs, 0,
+ parent_tidptr, child_tidptr);
return IS_ERR(p) ? PTR_ERR(p) : p->pid;
}
diff --git a/arch/m68k/kernel/setup.c b/arch/m68k/kernel/setup.c
index bf1d0ab11f52..ba0ea7d6361c 100644
--- a/arch/m68k/kernel/setup.c
+++ b/arch/m68k/kernel/setup.c
@@ -380,9 +380,6 @@ void __init setup_arch(char **cmdline_p)
#ifdef CONFIG_SUN3X
if (MACH_IS_SUN3X) {
dvma_init();
-#ifdef CONFIG_SUN3X_ZS
- sun_serial_setup();
-#endif
}
#endif
diff --git a/arch/m68k/kernel/signal.c b/arch/m68k/kernel/signal.c
index e45e7441d1a3..908785fd123f 100644
--- a/arch/m68k/kernel/signal.c
+++ b/arch/m68k/kernel/signal.c
@@ -1101,7 +1101,7 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs)
case SIGQUIT: case SIGILL: case SIGTRAP:
case SIGIOT: case SIGFPE: case SIGSEGV:
case SIGBUS: case SIGSYS: case SIGXCPU: case SIGXFSZ:
- if (do_coredump(signr, regs))
+ if (do_coredump(signr, exit_code, regs))
exit_code |= 0x80;
/* FALLTHRU */
diff --git a/arch/m68k/kernel/traps.c b/arch/m68k/kernel/traps.c
index 4343116eef4e..ad20bedba50c 100644
--- a/arch/m68k/kernel/traps.c
+++ b/arch/m68k/kernel/traps.c
@@ -820,32 +820,43 @@ asmlinkage void buserr_c(struct frame *fp)
static int kstack_depth_to_print = 48;
-extern struct module kernel_module;
+
+extern char _stext, _etext;
+
+#ifdef CONFIG_MODULES
+
+/* FIXME: Accessed without a lock --RR */
+extern struct list_head modules;
static inline int kernel_text_address(unsigned long addr)
{
-#ifdef CONFIG_MODULES
struct module *mod;
-#endif
- extern char _stext, _etext;
if (addr >= (unsigned long) &_stext &&
addr <= (unsigned long) &_etext)
return 1;
-#ifdef CONFIG_MODULES
- for (mod = module_list; mod != &kernel_module; mod = mod->next) {
+ list_for_each_entry(mod, &modules, list) {
/* mod_bound tests for addr being inside the vmalloc'ed
* module area. Of course it'd be better to test only
* for the .text subset... */
- if (mod_bound(addr, 0, mod))
+ if (mod_bound((void *)addr, 0, mod))
return 1;
}
-#endif
return 0;
}
+#else // !CONFIG_MODULES
+
+static inline int kernel_text_address(unsigned long addr)
+{
+ return (addr >= (unsigned long) &_stext &&
+ addr <= (unsigned long) &_etext);
+}
+
+#endif // !CONFIG_MODULES
+
void show_trace(unsigned long *stack)
{
unsigned long *endstack;
diff --git a/arch/m68k/mac/config.c b/arch/m68k/mac/config.c
index b30459aedb31..17ce0248fbfe 100644
--- a/arch/m68k/mac/config.c
+++ b/arch/m68k/mac/config.c
@@ -90,7 +90,7 @@ static void mac_get_model(char *str);
void mac_bang(int irq, void *vector, struct pt_regs *p)
{
- printk("Resetting ...\n");
+ printk(KERN_INFO "Resetting ...\n");
mac_reset();
}
@@ -181,17 +181,16 @@ int __init mac_parse_bootinfo(const struct bi_record *record)
static void mac_cache_card_flush(int writeback)
{
- unsigned long cpu_flags;
- save_flags(cpu_flags);
- cli();
+ unsigned long flags;
+ local_irq_save(flags);
via_flush_cache();
- restore_flags(cpu_flags);
+ local_irq_restore(flags);
}
void __init config_mac(void)
{
if (!MACH_IS_MAC) {
- printk("ERROR: no Mac, but config_mac() called!! \n");
+ printk(KERN_ERR "ERROR: no Mac, but config_mac() called!! \n");
}
mach_sched_init = mac_sched_init;
@@ -326,13 +325,14 @@ static struct mac_model mac_data_table[]=
*/
{ MAC_MODEL_Q605, "Quadra 605", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS},
+ { MAC_MODEL_Q605_ACC, "Quadra 605", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_NONE, MAC_NUBUS},
{ MAC_MODEL_Q610, "Quadra 610", MAC_ADB_II, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_SONIC, MAC_NUBUS},
{ MAC_MODEL_Q630, "Quadra 630", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_QUADRA, MAC_SCC_QUADRA, MAC_ETHER_SONIC, MAC_NUBUS},
{ MAC_MODEL_Q650, "Quadra 650", MAC_ADB_II, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_SONIC, MAC_NUBUS},
/* The Q700 does have a NS Sonic */
- { MAC_MODEL_Q700, "Quadra 700", MAC_ADB_II, MAC_VIA_QUADRA, MAC_SCSI_QUADRA2, MAC_IDE_NONE, MAC_SCC_QUADRA2, MAC_ETHER_SONIC, MAC_NUBUS},
+ { MAC_MODEL_Q700, "Quadra 700", MAC_ADB_II, MAC_VIA_QUADRA, MAC_SCSI_QUADRA2, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_SONIC, MAC_NUBUS},
{ MAC_MODEL_Q800, "Quadra 800", MAC_ADB_II, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_SONIC, MAC_NUBUS},
- { MAC_MODEL_Q840, "Quadra 840AV", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA3, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_MACE, MAC_NUBUS},
+ { MAC_MODEL_Q840, "Quadra 840AV", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA3, MAC_IDE_NONE, MAC_SCC_PSC, MAC_ETHER_MACE, MAC_NUBUS},
{ MAC_MODEL_Q900, "Quadra 900", MAC_ADB_IOP, MAC_VIA_QUADRA, MAC_SCSI_QUADRA2, MAC_IDE_NONE, MAC_SCC_IOP, MAC_ETHER_SONIC, MAC_NUBUS},
{ MAC_MODEL_Q950, "Quadra 950", MAC_ADB_IOP, MAC_VIA_QUADRA, MAC_SCSI_QUADRA2, MAC_IDE_NONE, MAC_SCC_IOP, MAC_ETHER_SONIC, MAC_NUBUS},
@@ -345,8 +345,8 @@ static struct mac_model mac_data_table[]=
{ MAC_MODEL_P475F, "Performa 475", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS},
{ MAC_MODEL_P520, "Performa 520", MAC_ADB_CUDA, MAC_VIA_IIci, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS},
{ MAC_MODEL_P550, "Performa 550", MAC_ADB_CUDA, MAC_VIA_IIci, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS},
- { MAC_MODEL_P575, "Performa 575", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS},
/* These have the comm slot, and therefore the possibility of SONIC ethernet */
+ { MAC_MODEL_P575, "Performa 575", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_SONIC, MAC_NUBUS},
{ MAC_MODEL_P588, "Performa 588", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_QUADRA, MAC_SCC_II, MAC_ETHER_SONIC, MAC_NUBUS},
{ MAC_MODEL_TV, "TV", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS},
{ MAC_MODEL_P600, "Performa 600", MAC_ADB_IISI, MAC_VIA_IIci, MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_II, MAC_ETHER_NONE, MAC_NUBUS},
@@ -358,7 +358,7 @@ static struct mac_model mac_data_table[]=
/* The C610 may or may not have SONIC. We probe to make sure */
{ MAC_MODEL_C610, "Centris 610", MAC_ADB_II, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_SONIC, MAC_NUBUS},
{ MAC_MODEL_C650, "Centris 650", MAC_ADB_II, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_SONIC, MAC_NUBUS},
- { MAC_MODEL_C660, "Centris 660AV", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA3, MAC_IDE_NONE, MAC_SCC_QUADRA, MAC_ETHER_MACE, MAC_NUBUS},
+ { MAC_MODEL_C660, "Centris 660AV", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA3, MAC_IDE_NONE, MAC_SCC_PSC, MAC_ETHER_MACE, MAC_NUBUS},
/*
* The PowerBooks all the same "Combo" custom IC for SCSI and SCC
@@ -411,7 +411,7 @@ void mac_identify(void)
/* no bootinfo model id -> NetBSD booter was used! */
/* XXX FIXME: breaks for model > 31 */
model=(mac_bi_data.cpuid>>2)&63;
- printk ("No bootinfo model ID, using cpuid instead (hey, use Penguin!)\n");
+ printk (KERN_WARNING "No bootinfo model ID, using cpuid instead (hey, use Penguin!)\n");
}
macintosh_config = mac_data_table;
@@ -429,22 +429,22 @@ void mac_identify(void)
iop_preinit();
mac_debug_init();
- printk ("Detected Macintosh model: %d \n", model);
+ printk (KERN_INFO "Detected Macintosh model: %d \n", model);
/*
* Report booter data:
*/
- printk (" Penguin bootinfo data:\n");
- printk (" Video: addr 0x%lx row 0x%lx depth %lx dimensions %ld x %ld\n",
+ printk (KERN_DEBUG " Penguin bootinfo data:\n");
+ printk (KERN_DEBUG " Video: addr 0x%lx row 0x%lx depth %lx dimensions %ld x %ld\n",
mac_bi_data.videoaddr, mac_bi_data.videorow,
mac_bi_data.videodepth, mac_bi_data.dimensions & 0xFFFF,
mac_bi_data.dimensions >> 16);
- printk (" Videological 0x%lx phys. 0x%lx, SCC at 0x%lx \n",
+ printk (KERN_DEBUG " Videological 0x%lx phys. 0x%lx, SCC at 0x%lx \n",
mac_bi_data.videological, mac_orig_videoaddr,
mac_bi_data.sccbase);
- printk (" Boottime: 0x%lx GMTBias: 0x%lx \n",
+ printk (KERN_DEBUG " Boottime: 0x%lx GMTBias: 0x%lx \n",
mac_bi_data.boottime, mac_bi_data.gmtbias);
- printk (" Machine ID: %ld CPUid: 0x%lx memory size: 0x%lx \n",
+ printk (KERN_DEBUG " Machine ID: %ld CPUid: 0x%lx memory size: 0x%lx \n",
mac_bi_data.id, mac_bi_data.cpuid, mac_bi_data.memsize);
#if 0
printk ("Ramdisk: addr 0x%lx size 0x%lx\n",
@@ -467,7 +467,7 @@ void mac_identify(void)
MACHW_SET(MAC_SCSI_96_2);
break;
default:
- printk("config.c: wtf: unknown scsi, using 53c80\n");
+ printk(KERN_WARNING "config.c: wtf: unknown scsi, using 53c80\n");
MACHW_SET(MAC_SCSI_80);
break;
@@ -481,7 +481,7 @@ void mac_identify(void)
void mac_report_hardware(void)
{
- printk("Apple Macintosh %s\n", macintosh_config->name);
+ printk(KERN_INFO "Apple Macintosh %s\n", macintosh_config->name);
}
static void mac_get_model(char *str)
diff --git a/arch/m68k/mac/iop.c b/arch/m68k/mac/iop.c
index 627a7580fa01..737037841835 100644
--- a/arch/m68k/mac/iop.c
+++ b/arch/m68k/mac/iop.c
@@ -111,6 +111,7 @@
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/proc_fs.h>
+#include <linux/interrupt.h>
#include <asm/bootinfo.h>
#include <asm/macintosh.h>
@@ -212,20 +213,19 @@ static int iop_alive(volatile struct mac_iop *iop)
static struct iop_msg *iop_alloc_msg(void)
{
int i;
- ulong cpu_flags;
+ unsigned long flags;
- save_flags(cpu_flags);
- cli();
+ local_irq_save(flags);
for (i = 0 ; i < NUM_IOP_MSGS ; i++) {
if (iop_msg_pool[i].status == IOP_MSGSTATUS_UNUSED) {
iop_msg_pool[i].status = IOP_MSGSTATUS_WAITING;
- restore_flags(cpu_flags);
+ local_irq_restore(flags);
return &iop_msg_pool[i];
}
}
- restore_flags(cpu_flags);
+ local_irq_restore(flags);
return NULL;
}
diff --git a/arch/m68k/mac/macboing.c b/arch/m68k/mac/macboing.c
index 4ef9220463e2..b9f73f9e76d0 100644
--- a/arch/m68k/mac/macboing.c
+++ b/arch/m68k/mac/macboing.c
@@ -187,8 +187,7 @@ void mac_mksound( unsigned int freq, unsigned int length )
return;
}
- save_flags( flags );
- cli();
+ local_irq_save(flags);
del_timer( &mac_sound_timer );
@@ -210,7 +209,7 @@ void mac_mksound( unsigned int freq, unsigned int length )
mac_sound_timer.expires = jiffies + length;
add_timer( &mac_sound_timer );
- restore_flags( flags );
+ local_irq_restore(flags);
}
/*
@@ -240,8 +239,7 @@ static void mac_quadra_start_bell( unsigned int freq, unsigned int length, unsig
mac_bell_phasepersample = ( freq * sizeof( mac_asc_wave_tab ) ) / mac_asc_samplespersec;
/* this is reasonably big for small frequencies */
- save_flags( flags );
- cli();
+ local_irq_save(flags);
/* set the volume */
mac_asc_regs[ 0x806 ] = volume;
@@ -263,7 +261,7 @@ static void mac_quadra_start_bell( unsigned int freq, unsigned int length, unsig
mac_sound_timer.expires = jiffies + 1;
add_timer( &mac_sound_timer );
- restore_flags( flags );
+ local_irq_restore(flags);
}
/*
@@ -283,8 +281,7 @@ static void mac_quadra_ring_bell( unsigned long ignored )
* ...and the possibility to use a real sample (a boingy noise, maybe...)
*/
- save_flags( flags );
- cli();
+ local_irq_save(flags);
del_timer( &mac_sound_timer );
@@ -301,7 +298,7 @@ static void mac_quadra_ring_bell( unsigned long ignored )
else
mac_asc_regs[ 0x801 ] = 0;
- restore_flags( flags );
+ local_irq_restore(flags);
}
/*
diff --git a/arch/m68k/mac/macints.c b/arch/m68k/mac/macints.c
index 40938c05f60c..4f8ea17f57ac 100644
--- a/arch/m68k/mac/macints.c
+++ b/arch/m68k/mac/macints.c
@@ -276,15 +276,14 @@ void mac_init_IRQ(void)
static inline void mac_insert_irq(irq_node_t **list, irq_node_t *node)
{
- unsigned long cpu_flags;
+ unsigned long flags;
irq_node_t *cur;
if (!node->dev_id)
printk("%s: Warning: dev_id of %s is zero\n",
__FUNCTION__, node->devname);
- save_flags(cpu_flags);
- cli();
+ local_irq_save(flags);
cur = *list;
@@ -309,27 +308,26 @@ static inline void mac_insert_irq(irq_node_t **list, irq_node_t *node)
node->next = cur;
*list = node;
- restore_flags(cpu_flags);
+ local_irq_restore(flags);
}
static inline void mac_delete_irq(irq_node_t **list, void *dev_id)
{
- unsigned long cpu_flags;
+ unsigned long flags;
irq_node_t *node;
- save_flags(cpu_flags);
- cli();
+ local_irq_save(flags);
for (node = *list; node; list = &node->next, node = *list) {
if (node->dev_id == dev_id) {
*list = node->next;
/* Mark it as free. */
node->handler = NULL;
- restore_flags(cpu_flags);
+ local_irq_restore(flags);
return;
}
}
- restore_flags(cpu_flags);
+ local_irq_restore(flags);
printk ("%s: tried to remove invalid irq\n", __FUNCTION__);
}
@@ -343,7 +341,7 @@ static inline void mac_delete_irq(irq_node_t **list, void *dev_id)
void mac_do_irq_list(int irq, struct pt_regs *fp)
{
irq_node_t *node, *slow_nodes;
- unsigned long cpu_flags;
+ unsigned long flags;
kstat_cpu(0).irqs[irq]++;
@@ -360,8 +358,8 @@ void mac_do_irq_list(int irq, struct pt_regs *fp)
node = node->next)
node->handler(irq, node->dev_id, fp);
if (!node) return;
- save_flags(cpu_flags);
- restore_flags((cpu_flags & ~0x0700) | (fp->sr & 0x0700));
+ local_save_flags(flags);
+ local_irq_restore((flags & ~0x0700) | (fp->sr & 0x0700));
/* if slow handlers exists, serve them now */
slow_nodes = node;
for (; node; node = node->next) {
@@ -735,15 +733,15 @@ void mac_scc_dispatch(int irq, void *dev_id, struct pt_regs *regs)
{
volatile unsigned char *scc = (unsigned char *) mac_bi_data.sccbase + 2;
unsigned char reg;
- unsigned long cpu_flags;
+ unsigned long flags;
/* Read RR3 from the chip. Always do this on channel A */
/* This must be an atomic operation so disable irqs. */
- save_flags(cpu_flags); cli();
+ local_irq_save(flags);
*scc = 3;
reg = *scc;
- restore_flags(cpu_flags);
+ local_irq_restore(flags);
/* Now dispatch. Bits 0-2 are for channel B and */
/* bits 3-5 are for channel A. We can safely */
diff --git a/arch/m68k/mac/misc.c b/arch/m68k/mac/misc.c
index 04fc953d271c..61f41a8026a8 100644
--- a/arch/m68k/mac/misc.c
+++ b/arch/m68k/mac/misc.c
@@ -165,11 +165,10 @@ static void via_pram_writebyte(__u8 data)
static void via_pram_command(int command, __u8 *data)
{
- unsigned long cpu_flags;
+ unsigned long flags;
int is_read;
- save_flags(cpu_flags);
- cli();
+ local_irq_save(flags);
/* Enable the RTC and make sure the strobe line is high */
@@ -193,7 +192,7 @@ static void via_pram_command(int command, __u8 *data)
via1[vBufB] |= VIA1B_vRTCEnb;
- restore_flags(cpu_flags);
+ local_irq_restore(flags);
}
static __u8 via_read_pram(int offset)
@@ -405,7 +404,7 @@ void mac_poweroff(void)
pmu_shutdown();
#endif
}
- sti();
+ local_irq_enable();
printk("It is now safe to turn off your Macintosh.\n");
while(1);
}
@@ -413,7 +412,7 @@ void mac_poweroff(void)
void mac_reset(void)
{
if (macintosh_config->adb_type == MAC_ADB_II) {
- unsigned long cpu_flags;
+ unsigned long flags;
/* need ROMBASE in booter */
/* indeed, plus need to MAP THE ROM !! */
@@ -429,12 +428,11 @@ void mac_reset(void)
* MSch: Machines known to crash on ROM reset ...
*/
} else {
- save_flags(cpu_flags);
- cli();
+ local_irq_save(flags);
rom_reset();
- restore_flags(cpu_flags);
+ local_irq_restore(flags);
}
#ifdef CONFIG_ADB_CUDA
} else if (macintosh_config->adb_type == MAC_ADB_CUDA) {
@@ -459,7 +457,7 @@ void mac_reset(void)
unsigned long virt = (unsigned long) mac_reset;
unsigned long phys = virt_to_phys(mac_reset);
unsigned long offset = phys-virt;
- cli(); /* lets not screw this up, ok? */
+ local_irq_disable(); /* lets not screw this up, ok? */
__asm__ __volatile__(".chip 68030\n\t"
"pmove %0,%/tt0\n\t"
".chip 68k"
@@ -495,7 +493,7 @@ void mac_reset(void)
}
/* should never get here */
- sti();
+ local_irq_enable();
printk ("Restart failed. Please restart manually.\n");
while(1);
}
diff --git a/arch/m68k/mac/via.c b/arch/m68k/mac/via.c
index 4c453339112b..53b448deb37a 100644
--- a/arch/m68k/mac/via.c
+++ b/arch/m68k/mac/via.c
@@ -137,15 +137,15 @@ void __init via_init(void)
panic("UNKNOWN VIA TYPE");
}
- printk("VIA1 at %p is a 6522 or clone\n", via1);
+ printk(KERN_INFO "VIA1 at %p is a 6522 or clone\n", via1);
- printk("VIA2 at %p is ", via2);
+ printk(KERN_INFO "VIA2 at %p is ", via2);
if (rbv_present) {
- printk("an RBV\n");
+ printk(KERN_INFO "an RBV\n");
} else if (oss_present) {
- printk("an OSS\n");
+ printk(KERN_INFO "an OSS\n");
} else {
- printk("a 6522 or clone\n");
+ printk(KERN_INFO "a 6522 or clone\n");
}
#ifdef DEBUG_VIA
@@ -291,22 +291,22 @@ void __init via_register_interrupts(void)
void via_debug_dump(void)
{
- printk("VIA1: DDRA = 0x%02X DDRB = 0x%02X ACR = 0x%02X\n",
+ printk(KERN_DEBUG "VIA1: DDRA = 0x%02X DDRB = 0x%02X ACR = 0x%02X\n",
(uint) via1[vDirA], (uint) via1[vDirB], (uint) via1[vACR]);
- printk(" PCR = 0x%02X IFR = 0x%02X IER = 0x%02X\n",
+ printk(KERN_DEBUG " PCR = 0x%02X IFR = 0x%02X IER = 0x%02X\n",
(uint) via1[vPCR], (uint) via1[vIFR], (uint) via1[vIER]);
if (oss_present) {
- printk("VIA2: <OSS>\n");
+ printk(KERN_DEBUG "VIA2: <OSS>\n");
} else if (rbv_present) {
- printk("VIA2: IFR = 0x%02X IER = 0x%02X\n",
+ printk(KERN_DEBUG "VIA2: IFR = 0x%02X IER = 0x%02X\n",
(uint) via2[rIFR], (uint) via2[rIER]);
- printk(" SIFR = 0x%02X SIER = 0x%02X\n",
+ printk(KERN_DEBUG " SIFR = 0x%02X SIER = 0x%02X\n",
(uint) via2[rSIFR], (uint) via2[rSIER]);
} else {
- printk("VIA2: DDRA = 0x%02X DDRB = 0x%02X ACR = 0x%02X\n",
+ printk(KERN_DEBUG "VIA2: DDRA = 0x%02X DDRB = 0x%02X ACR = 0x%02X\n",
(uint) via2[vDirA], (uint) via2[vDirB],
(uint) via2[vACR]);
- printk(" PCR = 0x%02X IFR = 0x%02X IER = 0x%02X\n",
+ printk(KERN_DEBUG " PCR = 0x%02X IFR = 0x%02X IER = 0x%02X\n",
(uint) via2[vPCR],
(uint) via2[vIFR], (uint) via2[vIER]);
}
@@ -374,7 +374,10 @@ void __init via_nubus_init(void)
if (!rbv_present) {
/* set the line to be an output on non-RBV machines */
- via2[vDirB] |= 0x02;
+ if ((macintosh_config->adb_type != MAC_ADB_PB1) &&
+ (macintosh_config->adb_type != MAC_ADB_PB2)) {
+ via2[vDirB] |= 0x02;
+ }
}
/* this seems to be an ADB bit on PMU machines */
@@ -390,8 +393,23 @@ void __init via_nubus_init(void)
via2[rSIER] = 0x7F;
via2[rSIER] = nubus_active | 0x80;
} else {
- via2[vBufA] = 0xFF;
- via2[vDirA] = ~nubus_active;
+ /* These are ADB bits on PMU */
+ if ((macintosh_config->adb_type != MAC_ADB_PB1) &&
+ (macintosh_config->adb_type != MAC_ADB_PB2)) {
+ switch(macintosh_config->ident)
+ {
+ case MAC_MODEL_II:
+ case MAC_MODEL_IIX:
+ case MAC_MODEL_IICX:
+ case MAC_MODEL_SE30:
+ via2[vBufA] |= 0x3F;
+ via2[vDirA] = ~nubus_active | 0xc0;
+ break;
+ default:
+ via2[vBufA] = 0xFF;
+ via2[vDirA] = ~nubus_active;
+ }
+ }
}
}
@@ -481,7 +499,7 @@ void via_irq_enable(int irq) {
int irq_bit = 1 << irq_idx;
#ifdef DEBUG_IRQUSE
- printk("via_irq_enable(%d)\n", irq);
+ printk(KERN_DEBUG "via_irq_enable(%d)\n", irq);
#endif
if (irq_src == 1) {
@@ -508,7 +526,21 @@ void via_irq_enable(int irq) {
via2[rSIER] = IER_SET_BIT(irq_idx);
} else {
/* Make sure the bit is an input, to enable the irq */
- via2[vDirA] &= ~irq_bit;
+ /* But not on PowerBooks, that's ADB... */
+ if ((macintosh_config->adb_type != MAC_ADB_PB1) &&
+ (macintosh_config->adb_type != MAC_ADB_PB2)) {
+ switch(macintosh_config->ident)
+ {
+ case MAC_MODEL_II:
+ case MAC_MODEL_IIX:
+ case MAC_MODEL_IICX:
+ case MAC_MODEL_SE30:
+ via2[vDirA] &= (~irq_bit | 0xc0);
+ break;
+ default:
+ via2[vDirA] &= ~irq_bit;
+ }
+ }
}
nubus_active |= irq_bit;
}
@@ -520,7 +552,7 @@ void via_irq_disable(int irq) {
int irq_bit = 1 << irq_idx;
#ifdef DEBUG_IRQUSE
- printk("via_irq_disable(%d)\n", irq);
+ printk(KERN_DEBUG "via_irq_disable(%d)\n", irq);
#endif
if (irq_src == 1) {
@@ -533,7 +565,11 @@ void via_irq_disable(int irq) {
via2[rSIER] = IER_CLR_BIT(irq_idx);
} else {
/* disable the nubus irq by changing dir to output */
- via2[vDirA] |= irq_bit;
+ /* except on PMU */
+ if ((macintosh_config->adb_type != MAC_ADB_PB1) &&
+ (macintosh_config->adb_type != MAC_ADB_PB2)) {
+ via2[vDirA] |= irq_bit;
+ }
}
nubus_active &= ~irq_bit;
}
diff --git a/arch/m68k/mm/extable.c b/arch/m68k/mm/extable.c
index 1f8d9e8c3323..bb854b6e92e9 100644
--- a/arch/m68k/mm/extable.c
+++ b/arch/m68k/mm/extable.c
@@ -33,23 +33,29 @@ search_one_table(const struct exception_table_entry *first,
unsigned long
search_exception_table(unsigned long addr)
{
- unsigned long ret;
+ unsigned long ret = 0;
#ifndef CONFIG_MODULES
/* There is only the kernel to search. */
ret = search_one_table(__start___ex_table, __stop___ex_table-1, addr);
- if (ret) return ret;
+ return ret;
#else
+ unsigned long flags;
+ struct list_head *i;
+
/* The kernel is the last "module" -- no need to treat it special. */
- struct module *mp;
- for (mp = module_list; mp != NULL; mp = mp->next) {
- if (mp->ex_table_start == NULL)
+ spin_lock_irqsave(&modlist_lock, flags);
+ list_for_each(i, &extables) {
+ struct exception_table *ex
+ = list_entry(i, struct exception_table, list);
+ if (ex->num_entries == 0)
continue;
- ret = search_one_table(mp->ex_table_start,
- mp->ex_table_end-1, addr);
- if (ret) return ret;
+ ret = search_one_table(ex->entry,
+ ex->entry + ex->num_entries - 1, addr);
+ if (ret)
+ break;
}
+ spin_unlock_irqrestore(&modlist_lock, flags);
+ return ret;
#endif
-
- return 0;
}
diff --git a/arch/m68k/mm/sun3mmu.c b/arch/m68k/mm/sun3mmu.c
index dd3411170472..a1dcc2ed06aa 100644
--- a/arch/m68k/mm/sun3mmu.c
+++ b/arch/m68k/mm/sun3mmu.c
@@ -83,7 +83,7 @@ void __init paging_init(void)
/* now change pg_table to kernel virtual addresses */
pg_table = (pte_t *) __va ((unsigned long) pg_table);
for (i=0; i<PTRS_PER_PTE; ++i, ++pg_table) {
- pte_t pte = __mk_pte(address, PAGE_INIT);
+ pte_t pte = pfn_pte(virt_to_pfn(address), PAGE_INIT);
if (address >= (unsigned long)high_memory)
pte_val (pte) = 0;
set_pte (pg_table, pte);
diff --git a/arch/m68k/mvme147/config.c b/arch/m68k/mvme147/config.c
index 25c324c036f4..5f5342a2a67f 100644
--- a/arch/m68k/mvme147/config.c
+++ b/arch/m68k/mvme147/config.c
@@ -23,6 +23,7 @@
#include <linux/major.h>
#include <linux/genhd.h>
#include <linux/rtc.h>
+#include <linux/interrupt.h>
#include <asm/bootinfo.h>
#include <asm/system.h>
@@ -209,10 +210,9 @@ static void scc_write (char ch)
void m147_scc_write (struct console *co, const char *str, unsigned count)
{
- unsigned long flags;
+ unsigned long flags;
- save_flags(flags);
- cli();
+ local_irq_save(flags);
while (count--)
{
@@ -220,7 +220,7 @@ void m147_scc_write (struct console *co, const char *str, unsigned count)
scc_write ('\r');
scc_write (*str++);
}
- restore_flags(flags);
+ local_irq_restore(flags);
}
void mvme147_init_console_port (struct console *co, int cflag)
diff --git a/arch/m68k/mvme16x/config.c b/arch/m68k/mvme16x/config.c
index cf42754a0980..713c18b54c7e 100644
--- a/arch/m68k/mvme16x/config.c
+++ b/arch/m68k/mvme16x/config.c
@@ -24,6 +24,7 @@
#include <linux/major.h>
#include <linux/genhd.h>
#include <linux/rtc.h>
+#include <linux/interrupt.h>
#include <asm/bootinfo.h>
#include <asm/system.h>
diff --git a/arch/m68k/mvme16x/rtc.c b/arch/m68k/mvme16x/rtc.c
index 6f88e9d2bbd7..ec79bfc53d34 100644
--- a/arch/m68k/mvme16x/rtc.c
+++ b/arch/m68k/mvme16x/rtc.c
@@ -48,8 +48,7 @@ static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
switch (cmd) {
case RTC_RD_TIME: /* Read the time/date from RTC */
{
- save_flags(flags);
- cli();
+ local_irq_save(flags);
/* Ensure clock and real-time-mode-register are accessible */
rtc->ctrl = RTC_READ;
wtime.tm_sec = BCD2BIN(rtc->bcd_sec);
@@ -62,7 +61,7 @@ static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
wtime.tm_year += 100;
wtime.tm_wday = BCD2BIN(rtc->bcd_dow)-1;
rtc->ctrl = 0;
- restore_flags(flags);
+ local_irq_restore(flags);
return copy_to_user((void *)arg, &wtime, sizeof wtime) ?
-EFAULT : 0;
}
@@ -102,8 +101,7 @@ static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
if (yrs >= 2070)
return -EINVAL;
- save_flags(flags);
- cli();
+ local_irq_save(flags);
rtc->ctrl = RTC_WRITE;
rtc->bcd_sec = BIN2BCD(sec);
@@ -114,7 +112,7 @@ static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
rtc->bcd_year = BIN2BCD(yrs%100);
rtc->ctrl = 0;
- restore_flags(flags);
+ local_irq_restore(flags);
return 0;
}
default:
@@ -168,7 +166,6 @@ int __init rtc_MK48T08_init(void)
return -ENODEV;
printk(KERN_INFO "MK48T08 Real Time Clock Driver v%s\n", RTC_VERSION);
- misc_register(&rtc_dev);
- return 0;
+ return misc_register(&rtc_dev);
}
diff --git a/arch/m68k/q40/q40ints.c b/arch/m68k/q40/q40ints.c
index 54fe9303cbd4..da640dfb0bbd 100644
--- a/arch/m68k/q40/q40ints.c
+++ b/arch/m68k/q40/q40ints.c
@@ -18,6 +18,7 @@
#include <linux/string.h>
#include <linux/sched.h>
#include <linux/seq_file.h>
+#include <linux/interrupt.h>
#include <asm/rtc.h>
#include <asm/ptrace.h>
@@ -374,7 +375,7 @@ void q40_irq2_handler (int vec, void *devname, struct pt_regs *fp)
}
if ( irq_tab[irq].state & IRQ_INPROGRESS )
{
- /* some handlers do sti() for irq latency reasons, */
+ /* some handlers do local_irq_enable() for irq latency reasons, */
/* however reentering an active irq handler is not permitted */
#ifdef IP_USE_DISABLE
/* in theory this is the better way to do it because it still */
diff --git a/arch/m68k/sun3/config.c b/arch/m68k/sun3/config.c
index 3aaa166f5612..2c21cfb5337f 100644
--- a/arch/m68k/sun3/config.c
+++ b/arch/m68k/sun3/config.c
@@ -42,7 +42,6 @@ extern void sun3_get_model (char* model);
extern void idprom_init (void);
extern int sun3_hwclk(int set, struct rtc_time *t);
-extern void sun_serial_setup(void);
volatile char* clock_va;
extern volatile unsigned char* sun3_intreg;
extern unsigned long availmem;
@@ -173,10 +172,6 @@ void __init config_sun3(void)
m68k_memory[0].size=*(romvec->pv_sun3mem);
sun3_bootmem_alloc(memory_start, memory_end);
-
-#ifdef CONFIG_SUN3X_ZS
- sun_serial_setup();
-#endif
}
void __init sun3_sched_init(void (*timer_routine)(int, void *, struct pt_regs *))
diff --git a/arch/m68k/sun3/dvma.c b/arch/m68k/sun3/dvma.c
index 1c47cc14415c..af1b60199455 100644
--- a/arch/m68k/sun3/dvma.c
+++ b/arch/m68k/sun3/dvma.c
@@ -1,5 +1,11 @@
-
-/* dvma support routines */
+/*
+ * linux/arch/m68k/sun3/dvma.c
+ *
+ * Written by Sam Creasey
+ *
+ * Sun3 IOMMU routines used for dvma accesses.
+ *
+ */
#include <linux/kernel.h>
#include <linux/mm.h>
@@ -22,7 +28,7 @@ inline unsigned long dvma_page(unsigned long kaddr, unsigned long vaddr)
j = *(volatile unsigned long *)kaddr;
*(volatile unsigned long *)kaddr = j;
- ptep = __mk_pte(kaddr, PAGE_KERNEL);
+ ptep = pfn_pte(virt_to_pfn(kaddr), PAGE_KERNEL);
pte = pte_val(ptep);
// printk("dvma_remap: addr %lx -> %lx pte %08lx len %x\n",
// kaddr, vaddr, pte, len);
diff --git a/arch/m68k/sun3/intersil.c b/arch/m68k/sun3/intersil.c
index 1015f247ae7e..fce7e6f03172 100644
--- a/arch/m68k/sun3/intersil.c
+++ b/arch/m68k/sun3/intersil.c
@@ -40,7 +40,7 @@ int sun3_hwclk(int set, struct rtc_time *t)
todintersil = (struct intersil_dt *) &intersil_clock->counter;
- save_and_cli(flags);
+ local_irq_save(flags);
intersil_clock->cmd_reg = STOP_VAL;
@@ -68,7 +68,7 @@ int sun3_hwclk(int set, struct rtc_time *t)
intersil_clock->cmd_reg = START_VAL;
- restore_flags(flags);
+ local_irq_restore(flags);
return 0;
diff --git a/arch/m68k/sun3/prom/console.c b/arch/m68k/sun3/prom/console.c
index 5ec12de10fbd..52c1427863de 100644
--- a/arch/m68k/sun3/prom/console.c
+++ b/arch/m68k/sun3/prom/console.c
@@ -22,9 +22,9 @@ prom_nbgetchar(void)
int i = -1;
unsigned long flags;
- save_flags(flags); cli();
+ local_irq_save(flags);
i = (*(romvec->pv_nbgetchar))();
- restore_flags(flags);
+ local_irq_restore(flags);
return i; /* Ugh, we could spin forever on unsupported proms ;( */
}
@@ -37,9 +37,9 @@ prom_nbputchar(char c)
unsigned long flags;
int i = -1;
- save_flags(flags); cli();
+ local_irq_save(flags);
i = (*(romvec->pv_nbputchar))(c);
- restore_flags(flags);
+ local_irq_restore(flags);
return i; /* Ugh, we could spin forever on unsupported proms ;( */
}
@@ -83,12 +83,12 @@ prom_query_input_device()
};
case PROM_V3:
case PROM_P1275:
- save_flags(flags); cli();
+ local_irq_save(flags);
st_p = (*romvec->pv_v2devops.v2_inst2pkg)(*romvec->pv_v2bootargs.fd_stdin);
__asm__ __volatile__("ld [%0], %%g6\n\t" : :
"r" (&current_set[smp_processor_id()]) :
"memory");
- restore_flags(flags);
+ local_irq_restore(flags);
if(prom_node_has_property(st_p, "keyboard"))
return PROMDEV_IKBD;
prom_getproperty(st_p, "device_type", propb, sizeof(propb));
@@ -133,12 +133,12 @@ prom_query_output_device()
case PROM_V2:
case PROM_V3:
case PROM_P1275:
- save_flags(flags); cli();
+ local_irq_save(flags);
st_p = (*romvec->pv_v2devops.v2_inst2pkg)(*romvec->pv_v2bootargs.fd_stdout);
__asm__ __volatile__("ld [%0], %%g6\n\t" : :
"r" (&current_set[smp_processor_id()]) :
"memory");
- restore_flags(flags);
+ local_irq_restore(flags);
propl = prom_getproperty(st_p, "device_type", propb, sizeof(propb));
if (propl >= 0 && propl == sizeof("display") &&
strncmp("display", propb, sizeof("display")) == 0)
diff --git a/arch/m68k/sun3/prom/misc.c b/arch/m68k/sun3/prom/misc.c
index 1d19e8d49b91..b88716f2c68c 100644
--- a/arch/m68k/sun3/prom/misc.c
+++ b/arch/m68k/sun3/prom/misc.c
@@ -19,9 +19,9 @@ void
prom_reboot(char *bcommand)
{
unsigned long flags;
- save_flags(flags); cli();
+ local_irq_save(flags);
(*(romvec->pv_reboot))(bcommand);
- restore_flags(flags);
+ local_irq_restore(flags);
}
/* Drop into the prom, with the chance to continue with the 'go'
@@ -40,9 +40,9 @@ prom_halt(void)
{
unsigned long flags;
again:
- save_flags(flags); cli();
+ local_irq_save(flags);
(*(romvec->pv_halt))();
- restore_flags(flags);
+ local_irq_restore(flags);
goto again; /* PROM is out to get me -DaveM */
}
diff --git a/arch/m68k/sun3/sbus.c b/arch/m68k/sun3/sbus.c
index fe148907acd8..52a39cb28b97 100644
--- a/arch/m68k/sun3/sbus.c
+++ b/arch/m68k/sun3/sbus.c
@@ -12,13 +12,9 @@
#include <linux/types.h>
#include <linux/init.h>
-extern void rs_init(void);
-
-void __init sbus_init(void)
+int __init sbus_init(void)
{
-
- rs_init();
-
+ return 0;
}
void *sparc_alloc_io (u32 address, void *virtual, int len, char *name,
@@ -27,3 +23,4 @@ void *sparc_alloc_io (u32 address, void *virtual, int len, char *name,
return (void *)address;
}
+subsys_initcall(sbus_init);
diff --git a/arch/m68k/sun3x/dvma.c b/arch/m68k/sun3x/dvma.c
index 3f28e3565235..4fc997c9b2ef 100644
--- a/arch/m68k/sun3x/dvma.c
+++ b/arch/m68k/sun3x/dvma.c
@@ -102,7 +102,7 @@ inline int dvma_map_cpu(unsigned long kaddr,
pmd_t *pmd;
unsigned long end2;
- if((pmd = pmd_alloc_kernel(pgd, vaddr)) == NULL) {
+ if((pmd = pmd_alloc(&init_mm, pgd, vaddr)) == NULL) {
ret = -ENOMEM;
goto out;
}
@@ -116,7 +116,7 @@ inline int dvma_map_cpu(unsigned long kaddr,
pte_t *pte;
unsigned long end3;
- if((pte = pte_alloc_kernel(pmd, vaddr)) == NULL) {
+ if((pte = pte_alloc_kernel(&init_mm, pmd, vaddr)) == NULL) {
ret = -ENOMEM;
goto out;
}
@@ -131,7 +131,8 @@ inline int dvma_map_cpu(unsigned long kaddr,
printk("mapping %08lx phys to %08lx\n",
__pa(kaddr), vaddr);
#endif
- set_pte(pte, __mk_pte(kaddr, PAGE_KERNEL));
+ set_pte(pte, pfn_pte(virt_to_pfn(kaddr),
+ PAGE_KERNEL));
pte++;
kaddr += PAGE_SIZE;
vaddr += PAGE_SIZE;
diff --git a/arch/m68k/sun3x/prom.c b/arch/m68k/sun3x/prom.c
index d738e0536a34..93dd64576e1a 100644
--- a/arch/m68k/sun3x/prom.c
+++ b/arch/m68k/sun3x/prom.c
@@ -37,9 +37,9 @@ extern e_vector vectors[256]; /* arch/m68k/kernel/traps.c */
void sun3x_halt(void)
{
unsigned long flags;
-
+
/* Disable interrupts while we mess with things */
- save_flags(flags); cli();
+ local_irq_save(flags);
/* Restore prom vbr */
__asm__ volatile ("movec %0,%%vbr" : : "r" ((void*)sun3x_prom_vbr));
@@ -56,13 +56,13 @@ void sun3x_halt(void)
sun3_enable_irq(5);
__asm__ volatile ("movec %0,%%vbr" : : "r" ((void*)vectors));
- restore_flags(flags);
+ local_irq_restore(flags);
}
void sun3x_reboot(void)
{
/* This never returns, don't bother saving things */
- cli();
+ local_irq_disable();
/* Restore prom vbr */
__asm__ volatile ("movec %0,%%vbr" : : "r" ((void*)sun3x_prom_vbr));
diff --git a/arch/m68k/sun3x/time.c b/arch/m68k/sun3x/time.c
index b72f3c2eb65d..683a34e815d4 100644
--- a/arch/m68k/sun3x/time.c
+++ b/arch/m68k/sun3x/time.c
@@ -45,7 +45,7 @@ int sun3x_hwclk(int set, struct rtc_time *t)
(struct mostek_dt *)(SUN3X_EEPROM+M_CONTROL);
unsigned long flags;
- save_and_cli(flags);
+ local_irq_save(flags);
if(set) {
h->csr |= C_WRITE;
@@ -69,7 +69,7 @@ int sun3x_hwclk(int set, struct rtc_time *t)
h->csr &= ~C_READ;
}
- restore_flags(flags);
+ local_irq_restore(flags);
return 0;
}
diff --git a/arch/m68k/vmlinux-std.lds b/arch/m68k/vmlinux-std.lds
index c0ac0012d92d..c31bc1da259b 100644
--- a/arch/m68k/vmlinux-std.lds
+++ b/arch/m68k/vmlinux-std.lds
@@ -47,6 +47,9 @@ SECTIONS
__setup_start = .;
.init.setup : { *(.init.setup) }
__setup_end = .;
+ __start___param = .;
+ __param : { *(__param) }
+ __stop___param = .;
__initcall_start = .;
.initcall.init : {
*(.initcall1.init)
@@ -59,6 +62,10 @@ SECTIONS
}
__initcall_end = .;
. = ALIGN(8192);
+ __initramfs_start = .;
+ .init.ramfs : { *(.init.ramfs) }
+ __initramfs_end = .;
+ . = ALIGN(8192);
__init_end = .;
.data.init_task : { *(.data.init_task) } /* The initial task and kernel stack */
diff --git a/arch/m68k/vmlinux-sun3.lds b/arch/m68k/vmlinux-sun3.lds
index 83aa0185079c..9ce55a8120c0 100644
--- a/arch/m68k/vmlinux-sun3.lds
+++ b/arch/m68k/vmlinux-sun3.lds
@@ -43,6 +43,9 @@ __init_begin = .;
__setup_start = .;
.init.setup : { *(.init.setup) }
__setup_end = .;
+ __start___param = .;
+ __param : { *(__param) }
+ __stop___param = .;
__initcall_start = .;
.initcall.init : {
*(.initcall1.init)
@@ -55,6 +58,10 @@ __init_begin = .;
}
__initcall_end = .;
. = ALIGN(8192);
+ __initramfs_start = .;
+ .init.ramfs : { *(.init.ramfs) }
+ __initramfs_end = .;
+ . = ALIGN(8192);
__init_end = .;
.init.task : { *(init_task) }
diff --git a/arch/sparc/vmlinux.lds.S b/arch/sparc/vmlinux.lds.S
index e0610ed2df4c..a9343f993144 100644
--- a/arch/sparc/vmlinux.lds.S
+++ b/arch/sparc/vmlinux.lds.S
@@ -48,6 +48,9 @@ SECTIONS
__setup_start = .;
.init.setup : { *(.init.setup) }
__setup_end = .;
+ __start___param = .;
+ __param : { *(__param) }
+ __stop___param = .;
__initcall_start = .;
.initcall.init : {
*(.initcall1.init)
diff --git a/arch/um/Kconfig b/arch/um/Kconfig
index f7e8005ebf38..cb59d60d0fff 100644
--- a/arch/um/Kconfig
+++ b/arch/um/Kconfig
@@ -30,6 +30,13 @@ config RWSEM_GENERIC_SPINLOCK
bool
default y
+config MODE_TT
+ bool
+ default y
+
+config MODE_SKAS
+ bool
+ default y
menu "Code maturity level options"
@@ -64,9 +71,41 @@ config BINFMT_MISC
config HOSTFS
tristate "Host filesystem"
+ help
+ While the User-Mode Linux port uses its own root file system for
+ booting and normal file access, this module lets the UML user
+ access files stored on the host. It does not require any
+ network connection between the Host and UML. An example use of
+ this might be:
+
+ mount none /tmp/fromhost -t hostfs -o /tmp/umlshare
+
+ where /tmp/fromhost is an empty directory inside UML and
+ /tmp/umlshare is a directory on the host with files the UML user
+ wishes to access.
+
+ For more information, see
+ <http://user-mode-linux.sourceforge.net/hostfs.html>.
+
+ If you'd like to be able to work with files stored on the host,
+ say Y or M here; otherwise say N.
+
config MCONSOLE
bool "Management console"
+ help
+ The user mode linux management console is a low-level interface to
+ the kernel, somewhat like the i386 SysRq interface. Since there is
+ a full-blown operating system running under every user mode linux
+ instance, there is much greater flexibility possible than with the
+ SysRq mechanism.
+
+ If you answer 'Y' to this option, to use this feature, you need the
+ mconsole client (called uml_mconsole) which is present in CVS in
+ 2.4.5-9um and later (path /tools/mconsole), and is also in the
+ distribution RPM package in 2.4.6 and later.
+
+ It is safe to say 'Y' here.
config MAGIC_SYSRQ
bool "Magic SysRq key"
@@ -77,6 +116,16 @@ config HOST_2G_2G
config UML_SMP
bool "Symmetric multi-processing support"
+ help
+ This option enables UML SMP support. UML implements virtual SMP by
+ allowing as many processes to run simultaneously on the host as
+ there are virtual processors configured. Obviously, if the host is
+ a uniprocessor, those processes will timeshare, but, inside UML,
+ will appear to be running simultaneously. If the host is a
+ multiprocessor, then UML processes may run simultaneously, depending
+ on the host scheduler.
+ CONFIG_SMP will be set to whatever this option is set to.
+ It is safe to leave this unchanged.
config SMP
bool
@@ -90,10 +139,27 @@ config NR_CPUS
config NEST_LEVEL
int "Nesting level"
default "0"
+ help
+ This is set to the number of layers of UMLs that this UML will be run
+ in. Normally, this is zero, meaning that it will run directly on the
+ host. Setting it to one will build a UML that can run inside a UML
+ that is running on the host. Generally, if you intend this UML to run
+ inside another UML, set CONFIG_NEST_LEVEL to one more than the host
+ UML.
+
+ Note that if the hosting UML has its CONFIG_KERNEL_HALF_GIGS set to
+ greater than one, then the guest UML should have its CONFIG_NEST_LEVEL
+ set to the host's CONFIG_NEST_LEVEL + CONFIG_KERNEL_HALF_GIGS.
+ Only change this if you are running nested UMLs.
config KERNEL_HALF_GIGS
int "Kernel address space size (in .5G units)"
default "1"
+ help
+ This determines the amount of address space that UML will allocate for
+ its own, measured in half Gigabyte units. The default is 1.
+ Change this only if you need to boot UML with an unusually large amount
+ of physical memory.
config HIGHMEM
bool "Highmem support"
@@ -128,6 +194,7 @@ source "net/Kconfig"
source "fs/Kconfig"
+source "lib/Kconfig"
menu "SCSI support"
@@ -156,6 +223,14 @@ config DEBUG_SLAB
config DEBUGSYM
bool "Enable kernel debugging symbols"
+ help
+ When this is enabled, the User-Mode Linux binary will include
+ debugging symbols. This enlarges the binary by a few megabytes,
+ but aids in tracking down kernel problems in UML. It is required
+ if you intend to do any kernel development.
+
+ If you're truly short on disk space or don't expect to report any
+ bugs back to the UML developers, say N, otherwise say Y.
config PT_PROXY
bool "Enable ptrace proxy"
@@ -164,10 +239,28 @@ config PT_PROXY
config GPROF
bool "Enable gprof support"
depends on DEBUGSYM
+ help
+ This allows profiling of a User-Mode Linux kernel with the gprof
+ utility.
+
+ See <http://user-mode-linux.sourceforge.net/gprof.html> for more
+ details.
+
+ If you're involved in UML kernel development and want to use gprof,
+ say Y. If you're unsure, say N.
config GCOV
bool "Enable gcov support"
depends on DEBUGSYM
+ help
+ This option allows developers to retrieve coverage data from a UML
+ session.
+
+ See <http://user-mode-linux.sourceforge.net/gcov.html> for more
+ details.
+
+ If you're involved in UML kernel development and want to use gcov,
+ say Y. If you're unsure, say N.
endmenu
diff --git a/arch/um/Kconfig_block b/arch/um/Kconfig_block
index 542627172e92..fba53d9bb983 100644
--- a/arch/um/Kconfig_block
+++ b/arch/um/Kconfig_block
@@ -3,10 +3,31 @@ menu "Block Devices"
config BLK_DEV_UBD
bool "Virtual block device"
+ help
+ The User-Mode Linux port includes a driver called UBD which will let
+ you access arbitrary files on the host computer as block devices.
+ Unless you know that you do not need such virtual block devices say
+ Y here.
config BLK_DEV_UBD_SYNC
bool "Always do synchronous disk IO for UBD"
depends on BLK_DEV_UBD
+ help
+ Writes to the virtual block device are not immediately written to the
+ host's disk; this may cause problems if, for example, the
+ User-Mode Linux 'Virtual Machine' uses a journalling filesystem and
+ the host computer crashes.
+
+ Synchronous operation (i.e. always writing data to the host's disk
+ immediately) is configurable on a per-UBD basis by using a special
+ kernel command line option. Alternatively, you can say Y here to
+ turn on synchronous operation by default for all block devices.
+
+ If you're running a journalling file system (like reiserfs, for
+ example) in your virtual machine, you will want to say Y here. If
+ you care for the safety of the data in your virtual machine, Y is a
+ wise choice too. In all other cases (for example, if you're just
+ playing around with User-Mode Linux) you can choose N.
config BLK_DEV_LOOP
tristate "Loopback device support"
@@ -29,6 +50,19 @@ config BLK_DEV_INITRD
config MMAPPER
tristate "Example IO memory driver"
+ help
+ The User-Mode Linux port can provide support for IO Memory
+ emulation with this option. This allows a host file to be
+ specified as an I/O region on the kernel command line. That file
+ will be mapped into UML's kernel address space where a driver can
+ locate it and do whatever it wants with the memory, including
+ providing an interface to it for UML processes to use.
+
+ For more information, see
+ <http://user-mode-linux.sourceforge.net/iomem.html>.
+
+ If you'd like to be able to provide a simulated IO port space for
+ User-Mode Linux processes, say Y. If unsure, say N.
endmenu
diff --git a/arch/um/Kconfig_char b/arch/um/Kconfig_char
index 8a3367c10310..a21cbbc7efde 100644
--- a/arch/um/Kconfig_char
+++ b/arch/um/Kconfig_char
@@ -7,36 +7,104 @@ config STDIO_CONSOLE
config SSL
bool "Virtual serial line"
+ help
+ The User-Mode Linux environment allows you to create virtual serial
+ lines on the UML that are usually made to show up on the host as
+ ttys or ptys.
+
+ See <http://user-mode-linux.sourceforge.net/input.html> for more
+ information and command line examples of how to use this facility.
+
+ Unless you have a specific reason for disabling this, say Y.
config FD_CHAN
bool "file descriptor channel support"
+ help
+ This option enables support for attaching UML consoles and serial
+ lines to already set up file descriptors. Generally, the main
+ console is attached to file descriptors 0 and 1 (stdin and stdout),
+ so it would be wise to leave this enabled unless you intend to
+ attach it to some other host device.
config NULL_CHAN
bool "null channel support"
+ help
+ This option enables support for attaching UML consoles and serial
+ lines to a device similar to /dev/null. Data written to it disappears
+ and there is never any data to be read.
config PORT_CHAN
bool "port channel support"
+ help
+ This option enables support for attaching UML consoles and serial
+ lines to host portals. They may be accessed with 'telnet <host>
+ <port number>'. Any number of consoles and serial lines may be
+ attached to a single portal, although what UML device you get when
+ you telnet to that portal will be unpredictable.
+ It is safe to say 'Y' here.
config PTY_CHAN
bool "pty channel support"
+ help
+ This option enables support for attaching UML consoles and serial
+ lines to host pseudo-terminals. Access to both traditional
+ pseudo-terminals (/dev/pty*) and pts pseudo-terminals are controlled
+ with this option. The assignment of UML devices to host devices
+ will be announced in the kernel message log.
+ It is safe to say 'Y' here.
config TTY_CHAN
bool "tty channel support"
+ help
+ This option enables support for attaching UML consoles and serial
+ lines to host terminals. Access to both virtual consoles
+ (/dev/tty*) and the slave side of pseudo-terminals (/dev/ttyp* and
+ /dev/pts/*) are controlled by this option.
+ It is safe to say 'Y' here.
config XTERM_CHAN
bool "xterm channel support"
+ help
+ This option enables support for attaching UML consoles and serial
+ lines to xterms. Each UML device so assigned will be brought up in
+ its own xterm.
+ If you disable this option, then CONFIG_PT_PROXY will be disabled as
+ well, since UML's gdb currently requires an xterm.
+ It is safe to say 'Y' here.
config CON_ZERO_CHAN
string "Default main console channel initialization"
default "fd:0,fd:1"
+ help
+ This is the string describing the channel to which the main console
+ will be attached by default. This value can be overridden from the
+ command line. The default value is "fd:0,fd:1", which attaches the
+ main console to stdin and stdout.
+ It is safe to leave this unchanged.
config CON_CHAN
string "Default console channel initialization"
default "xterm"
+ help
+ This is the string describing the channel to which all consoles
+ except the main console will be attached by default. This value can
+ be overridden from the command line. The default value is "xterm",
+ which brings them up in xterms.
+ It is safe to leave this unchanged, although you may wish to change
+ this if you expect the UML that you build to be run in environments
+ which don't have X or xterm available.
config SSL_CHAN
string "Default serial line channel initialization"
default "pty"
+ help
+ This is the string describing the channel to which the serial lines
+ will be attached by default. This value can be overridden from the
+ command line. The default value is "pty", which attaches them to
+ traditional pseudo-terminals.
+ It is safe to leave this unchanged, although you may wish to change
+ this if you expect the UML that you build to be run in environments
+ which don't have a set of /dev/pty* devices.
config UNIX98_PTYS
bool "Unix98 PTY support"
@@ -63,6 +131,11 @@ config UML_WATCHDOG
config UML_SOUND
tristate "Sound support"
+ help
+ This option enables UML sound support. If enabled, it will pull in
+ soundcore and the UML hostaudio relay, which acts as a intermediary
+ between the host's dsp and mixer devices and the UML sound system.
+ It is safe to say 'Y' here.
config SOUND
tristate
@@ -72,8 +145,5 @@ config HOSTAUDIO
tristate
default UML_SOUND
-config TTY_LOG
- bool "Enable tty logging"
-
endmenu
diff --git a/arch/um/Kconfig_net b/arch/um/Kconfig_net
index ba311513abc3..443a74bd622d 100644
--- a/arch/um/Kconfig_net
+++ b/arch/um/Kconfig_net
@@ -5,30 +5,177 @@ menu "Network Devices"
# UML virtual driver
config UML_NET
bool "Virtual network device"
+ help
+ While the User-Mode port cannot directly talk to any physical
+ hardware devices, this choice and the following transport options
+ provide one or more virtual network devices through which the UML
+ kernels can talk to each other, the host, and with the host's help,
+ machines on the outside world.
+
+ For more information, including explanations of the networking and
+ sample configurations, see
+ <http://user-mode-linux.sourceforge.net/networking.html>.
+
+ If you'd like to be able to enable networking in the User-Mode
+ linux environment, say Y; otherwise say N. Note that you must
+ enable at least one of the following transport options to actually
+ make use of UML networking.
config UML_NET_ETHERTAP
bool "Ethertap transport"
depends on UML_NET
+ help
+ The Ethertap User-Mode Linux network transport allows a single
+ running UML to exchange packets with its host over one of the
+ host's Ethertap devices, such as /dev/tap0. Additional running
+ UMLs can use additional Ethertap devices, one per running UML.
+ While the UML believes it's on a (multi-device, broadcast) virtual
+ Ethernet network, it's in fact communicating over a point-to-point
+ link with the host.
+
+ To use this, your host kernel must have support for Ethertap
+ devices. Also, if your host kernel is 2.4.x, it must have
+ CONFIG_NETLINK_DEV configured as Y or M.
+
+ For more information, see
+ <http://user-mode-linux.sourceforge.net/networking.html> That site
+ has examples of the UML command line to use to enable Ethertap
+ networking.
+
+ If you'd like to set up an IP network with the host and/or the
+ outside world, say Y to this, the Daemon Transport and/or the
+ Slip Transport. You'll need at least one of them, but may choose
+ more than one without conflict. If you don't need UML networking,
+ say N.
config UML_NET_TUNTAP
bool "TUN/TAP transport"
depends on UML_NET
+ help
+ The UML TUN/TAP network transport allows a UML instance to exchange
+ packets with the host over a TUN/TAP device. This option will only
+ work with a 2.4 host, unless you've applied the TUN/TAP patch to
+ your 2.2 host kernel.
+
+ To use this transport, your host kernel must have support for TUN/TAP
+ devices, either built-in or as a module.
config UML_NET_SLIP
bool "SLIP transport"
depends on UML_NET
+ help
+ The slip User-Mode Linux network transport allows a running UML to
+ network with its host over a point-to-point link. Unlike Ethertap,
+ which can carry any Ethernet frame (and hence even non-IP packets),
+ the slip transport can only carry IP packets.
+
+ To use this, your host must support slip devices.
+
+ For more information, see
+ <http://user-mode-linux.sourceforge.net/networking.html>. That site
+ has examples of the UML command line to use to enable slip
+ networking, and details of a few quirks with it.
+
+ The Ethertap Transport is preferred over slip because of its
+ limitations. If you prefer slip, however, say Y here. Otherwise
+ choose the Multicast transport (to network multiple UMLs on
+ multiple hosts), Ethertap (to network with the host and the
+ outside world), and/or the Daemon transport (to network multiple
+ UMLs on a single host). You may choose more than one without
+ conflict. If you don't need UML networking, say N.
config UML_NET_DAEMON
bool "Daemon transport"
depends on UML_NET
+ help
+ This User-Mode Linux network transport allows one or more running
+ UMLs on a single host to communicate with each other, but not to
+ the host.
+
+ To use this form of networking, you'll need to run the UML
+ networking daemon on the host.
+
+ For more information, see
+ <http://user-mode-linux.sourceforge.net/networking.html> That site
+ has examples of the UML command line to use to enable Daemon
+ networking.
+
+ If you'd like to set up a network with other UMLs on a single host,
+ say Y. If you need a network between UMLs on multiple physical
+ hosts, choose the Multicast Transport. To set up a network with
+ the host and/or other IP machines, say Y to the Ethertap or Slip
+ transports. You'll need at least one of them, but may choose
+ more than one without conflict. If you don't need UML networking,
+ say N.
config UML_NET_MCAST
bool "Multicast transport"
depends on UML_NET
+ help
+ This Multicast User-Mode Linux network transport allows multiple
+ UMLs (even ones running on different host machines!) to talk to
+ each other over a virtual ethernet network. However, it requires
+ at least one UML with one of the other transports to act as a
+ bridge if any of them need to be able to talk to their hosts or any
+ other IP machines.
+
+ To use this, your host kernel(s) must support IP Multicasting.
+
+ For more information, see
+ <http://user-mode-linux.sourceforge.net/networking.html> That site
+ has examples of the UML command line to use to enable Multicast
+ networking, and notes about the security of this approach.
+
+ If you need UMLs on multiple physical hosts to communicate as if
+ they shared an Ethernet network, say Y. If you need to communicate
+ with other IP machines, make sure you select one of the other
+ transports (possibly in addition to Multicast; they're not
+ exclusive). If you don't need to network UMLs say N to each of
+ the transports.
config UML_NET_PCAP
bool "pcap transport"
depends on UML_NET
+ help
+ The pcap transport makes a pcap packet stream on the host look
+ like an ethernet device inside UML. This is useful for making
+ UML act as a network monitor for the host. You must have libcap
+ installed in order to build the pcap transport into UML.
+
+ For more information, see
+ <http://user-mode-linux.sourceforge.net/networking.html> That site
+ has examples of the UML command line to use to enable this option.
+
+ If you intend to use UML as a network monitor for the host, say
+ Y here. Otherwise, say N.
+
+config UML_NET_SLIRP
+ bool "SLiRP transport"
+ depends on UML_NET
+ help
+ The SLiRP User-Mode Linux network transport allows a running UML
+ to network by invoking a program that can handle SLIP encapsulated
+ packets. This is commonly (but not limited to) the application
+ known as SLiRP, a program that can re-socket IP packets back onto
+ the host on which it is run. Only IP packets are supported,
+ unlike other network transports that can handle all Ethernet
+ frames. In general, slirp allows the UML the same IP connectivity
+ to the outside world that the host user is permitted, and unlike
+ other transports, SLiRP works without the need of root level
+ privleges, setuid binaries, or SLIP devices on the host. This
+ also means not every type of connection is possible, but most
+ situations can be accomodated with carefully crafted slirp
+ commands that can be passed along as part of the network device's
+ setup string. The effect of this transport on the UML is similar
+ that of a host behind a firewall that masquerades all network
+ connections passing through it (but is less secure).
+
+ To use this you should first have slirp compiled somewhere
+ accessible on the host, and have read its documentation. If you
+ don't need UML networking, say N.
+
+ Startup example: "eth0=slirp,FE:FD:01:02:03:04,/usr/local/bin/slirp"
+
# Below are hardware-independent drivers mirrored from
# drivers/net/Config.in. It would be nice if Linux
diff --git a/arch/um/Makefile b/arch/um/Makefile
index e4ad81702045..6fd0df8cd4e3 100644
--- a/arch/um/Makefile
+++ b/arch/um/Makefile
@@ -1,3 +1,8 @@
+#
+# Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+# Licensed under the GPL
+#
+
ARCH_DIR = arch/um
OS := $(shell uname -s)
@@ -11,37 +16,31 @@ include/linux/version.h: arch/$(ARCH)/Makefile
# EXTRAVERSION...
MODLIB := $(INSTALL_MOD_PATH)/lib/modules/$(KERNELRELEASE)
-MAKEBOOT = $(MAKE) -C $(ARCH_DIR)/boot
-
ifeq ($(CONFIG_DEBUGSYM),y)
-DEBUG = -g
CFLAGS := $(subst -fomit-frame-pointer,,$(CFLAGS))
endif
-ifeq ($(CONFIG_GCOV),y)
-CFLAGS += -fprofile-arcs -ftest-coverage
-endif
-
-ifeq ($(CONFIG_GPROF), y)
-PROFILE += -pg -DPROFILING
-LINK_PROFILE = $(PROFILE) -Wl,--wrap,__monstartup
-endif
+CFLAGS-$(CONFIG_DEBUGSYM) += -g
+CFLAGS-$(CONFIG_GCOV) += -fprofile-arcs -ftest-coverage
+CFLAGS-$(CONFIG_GPROF) += $(PROFILE)
+LINK-$(CONFIG_GPROF) += $(PROFILE) -Wl,--wrap,__monstartup
core-y += $(ARCH_DIR)/kernel/ \
$(ARCH_DIR)/drivers/ \
$(ARCH_DIR)/sys-$(SUBARCH)/
-core-$(CONFIG_PT_PROXY) += $(ARCH_DIR)/ptproxy/
-
-ARCH_INCLUDE = $(TOPDIR)/$(ARCH_DIR)/include
+ARCH_INCLUDE = -I$(ARCH_DIR)/include
+MODE_INCLUDE = -I$(ARCH_DIR)/kernel/tt/include \
+ -I$(ARCH_DIR)/kernel/skas/include
# -Derrno=kernel_errno - This turns all kernel references to errno into
# kernel_errno to separate them from the libc errno. This allows -fno-common
# in CFLAGS. Otherwise, it would cause ld to complain about the two different
# errnos.
-CFLAGS += $(DEBUG) $(PROFILE) -D__arch_um__ -DSUBARCH=\"$(SUBARCH)\" \
- -D_LARGEFILE64_SOURCE -I$(ARCH_INCLUDE) -Derrno=kernel_errno
+CFLAGS += $(CFLAGS-y) -D__arch_um__ -DSUBARCH=\"$(SUBARCH)\" \
+ -D_LARGEFILE64_SOURCE $(ARCH_INCLUDE) -Derrno=kernel_errno \
+ $(MODE_INCLUDE)
LINK_WRAPS = -Wl,--wrap,malloc -Wl,--wrap,free -Wl,--wrap,calloc
@@ -51,10 +50,16 @@ SYMLINK_HEADERS = include/asm-um/archparam.h include/asm-um/system.h \
include/asm-um/sigcontext.h include/asm-um/processor.h \
include/asm-um/ptrace.h include/asm-um/arch-signal.h
-ARCH_SYMLINKS = include/asm-um/arch arch/um/include/sysdep arch/um/os \
- $(SYMLINK_HEADERS)
+ARCH_SYMLINKS = include/asm-um/arch $(ARCH_DIR)/include/sysdep $(ARCH_DIR)/os \
+ $(SYMLINK_HEADERS) $(ARCH_DIR)/include/uml-config.h
+
+ifeq ($(CONFIG_MODE_SKAS), y)
+GEN_HEADERS = $(ARCH_DIR)/kernel/skas/include/skas_ptregs.h
-GEN_HEADERS = $(ARCH_DIR)/include/task.h
+$(SYS_HEADERS) : $(ARCH_DIR)/kernel/skas/include/skas_ptregs.h
+endif
+
+GEN_HEADERS += $(ARCH_DIR)/include/task.h $(ARCH_DIR)/include/kern_constants.h
include $(ARCH_DIR)/Makefile-$(SUBARCH)
include $(ARCH_DIR)/Makefile-os-$(OS)
@@ -62,9 +67,9 @@ include $(ARCH_DIR)/Makefile-os-$(OS)
$(ARCH_DIR)/vmlinux.lds.S :
touch $@
-prepare: $(ARCH_SYMLINKS) $(GEN_HEADERS)
+prepare: $(ARCH_SYMLINKS) $(SYS_HEADERS) $(GEN_HEADERS)
-LDFLAGS_vmlinux = -r $(ARCH_DIR)/main.o
+LDFLAGS_vmlinux = -r
vmlinux: $(ARCH_DIR)/main.o
@@ -74,18 +79,21 @@ $(ARCH_DIR)/uml.lds.s : $(ARCH_DIR)/uml.lds.S scripts FORCE
AFLAGS_uml.lds.o = -U$(SUBARCH) -DSTART=$$(($(TOP_ADDR) - $(SIZE))) \
-DELF_ARCH=$(ELF_ARCH) -DELF_FORMAT=\"$(ELF_FORMAT)\" -P -C -Uum
-linux: arch/um/uml.lds.s vmlinux
- $(CC) -Wl,-T,arch/um/uml.lds.s -o $@ $(LINK_PROFILE) \
- $(LINK_WRAPS) -static vmlinux -L/usr/lib -lutil
+linux: $(ARCH_DIR)/uml.lds.s vmlinux
+ $(CC) -Wl,-T,$(ARCH_DIR)/uml.lds.s -static $(LINK-y) $(LINK_WRAPS) \
+ -o linux $(ARCH_DIR)/main.o vmlinux -L/usr/lib -lutil
USER_CFLAGS := $(patsubst -I%,,$(CFLAGS))
USER_CFLAGS := $(patsubst -Derrno=kernel_errno,,$(USER_CFLAGS))
-USER_CFLAGS := $(patsubst -D__KERNEL__,,$(USER_CFLAGS)) -I$(ARCH_INCLUDE)
+USER_CFLAGS := $(patsubst -D__KERNEL__,,$(USER_CFLAGS)) $(ARCH_INCLUDE) \
+ $(MODE_INCLUDE)
# To get a definition of F_SETSIG
USER_CFLAGS += -D_GNU_SOURCE
+CLEAN_FILES += linux x.i gmon.out $(ARCH_DIR)/link.ld $(GEN_HEADERS)
+
$(ARCH_DIR)/main.o: $(ARCH_DIR)/main.c
$(CC) $(USER_CFLAGS) $(EXTRA_CFLAGS) -c -o $@ $<
@@ -106,11 +114,9 @@ archclean: sysclean
find . \( -name '*.bb' -o -name '*.bbg' -o -name '*.da' \
-o -name '*.gcov' \) -type f -print | xargs rm -f
rm -f linux x.i gmon.out $(ARCH_DIR)/link.ld $(GEN_HEADERS)
- @$(MAKEBOOT) clean
archdep:
for d in $(ARCH_SUBDIRS); do $(MAKE) -C $$d fastdep; done
- @$(MAKEBOOT) dep
$(SYMLINK_HEADERS):
cd $(TOPDIR)/$(dir $@) ; \
@@ -119,18 +125,28 @@ $(SYMLINK_HEADERS):
include/asm-um/arch:
cd $(TOPDIR)/include/asm-um && ln -sf ../asm-$(SUBARCH) arch
-arch/um/include/sysdep:
- cd $(TOPDIR)/arch/um/include && ln -sf sysdep-$(SUBARCH) sysdep
+$(ARCH_DIR)/include/sysdep:
+ cd $(ARCH_DIR)/include && ln -sf sysdep-$(SUBARCH) sysdep
-arch/um/os:
+$(ARCH_DIR)/os:
cd $(ARCH_DIR) && ln -sf os-$(OS) os
+$(ARCH_DIR)/include/uml-config.h :
+ ln -sf $(TOPDIR)/include/linux/autoconf.h $@
+
$(ARCH_DIR)/include/task.h : $(ARCH_DIR)/util/mk_task
$< > $@
-$(ARCH_DIR)/util/mk_task : $(ARCH_DIR)/util FORCE ;
+$(ARCH_DIR)/include/kern_constants.h : $(ARCH_DIR)/util/mk_constants
+ $< > $@
+
+$(ARCH_DIR)/util/mk_task : $(ARCH_DIR)/kernel/skas/include/skas_ptregs.h \
+ $(ARCH_DIR)/util FORCE ;
$(ARCH_DIR)/util: FORCE
@$(call descend,$@,)
+$(ARCH_DIR)/kernel/skas/include/skas_ptregs.h :
+ $(MAKE) -C $(ARCH_DIR)/kernel/skas include/skas_ptregs.h
+
export SUBARCH USER_CFLAGS OS
diff --git a/arch/um/Makefile-i386 b/arch/um/Makefile-i386
index e4a66c4fbacf..3bd90fbdb7e0 100644
--- a/arch/um/Makefile-i386
+++ b/arch/um/Makefile-i386
@@ -21,13 +21,13 @@ prepare: $(SYS_HEADERS)
$(SYS_DIR)/sc.h: $(SYS_UTIL_DIR)/mk_sc
$< > $@
-$(SYS_DIR)/thread.h: $(SYS_UTIL_DIR)/mk_thread
+$(SYS_DIR)/thread.h: $(SYS_UTIL_DIR)/mk_thread
$< > $@
$(SYS_UTIL_DIR)/mk_sc: FORCE ;
@$(call descend,$(SYS_UTIL_DIR),$@)
-$(SYS_UTIL_DIR)/mk_thread: $(ARCH_SYMLINKS) FORCE ;
+$(SYS_UTIL_DIR)/mk_thread: $(ARCH_SYMLINKS) $(GEN_HEADERS) FORCE ;
@$(call descend,$(SYS_UTIL_DIR),$@)
$(SYS_UTIL_DIR): include/asm FORCE
diff --git a/arch/um/boot/Makefile b/arch/um/boot/Makefile
deleted file mode 100644
index f5dc182a5fb4..000000000000
--- a/arch/um/boot/Makefile
+++ /dev/null
@@ -1,3 +0,0 @@
-dep:
-
-clean:
diff --git a/arch/um/config_block.in b/arch/um/config_block.in
deleted file mode 100644
index 419bb713354a..000000000000
--- a/arch/um/config_block.in
+++ /dev/null
@@ -1,16 +0,0 @@
-mainmenu_option next_comment
-comment 'Block Devices'
-
-bool 'Virtual block device' CONFIG_BLK_DEV_UBD
-dep_bool ' Always do synchronous disk IO for UBD' CONFIG_BLK_DEV_UBD_SYNC $CONFIG_BLK_DEV_UBD
-tristate 'Loopback device support' CONFIG_BLK_DEV_LOOP
-dep_tristate 'Network block device support' CONFIG_BLK_DEV_NBD $CONFIG_NET
-tristate 'RAM disk support' CONFIG_BLK_DEV_RAM
-if [ "$CONFIG_BLK_DEV_RAM" = "y" -o "$CONFIG_BLK_DEV_RAM" = "m" ]; then
- int ' Default RAM disk size' CONFIG_BLK_DEV_RAM_SIZE 4096
-fi
-dep_bool ' Initial RAM disk (initrd) support' CONFIG_BLK_DEV_INITRD $CONFIG_BLK_DEV_RAM
-
-tristate 'Example IO memory driver' CONFIG_MMAPPER
-
-endmenu
diff --git a/arch/um/config_char.in b/arch/um/config_char.in
deleted file mode 100644
index dfb87d66b8de..000000000000
--- a/arch/um/config_char.in
+++ /dev/null
@@ -1,37 +0,0 @@
-mainmenu_option next_comment
-comment 'Character Devices'
-
-define_bool CONFIG_STDIO_CONSOLE y
-
-bool 'Virtual serial line' CONFIG_SSL
-
-bool 'file descriptor channel support' CONFIG_FD_CHAN
-bool 'null channel support' CONFIG_NULL_CHAN
-bool 'port channel support' CONFIG_PORT_CHAN
-bool 'pty channel support' CONFIG_PTY_CHAN
-bool 'tty channel support' CONFIG_TTY_CHAN
-bool 'xterm channel support' CONFIG_XTERM_CHAN
-string 'Default main console channel initialization' CONFIG_CON_ZERO_CHAN \
- "fd:0,fd:1"
-string 'Default console channel initialization' CONFIG_CON_CHAN "xterm"
-string 'Default serial line channel initialization' CONFIG_SSL_CHAN "pty"
-
-
-bool 'Unix98 PTY support' CONFIG_UNIX98_PTYS
-if [ "$CONFIG_UNIX98_PTYS" = "y" ]; then
- int 'Maximum number of Unix98 PTYs in use (0-2048)' CONFIG_UNIX98_PTY_COUNT 256
-fi
-
-bool 'Watchdog Timer Support' CONFIG_WATCHDOG
-dep_bool ' Disable watchdog shutdown on close' CONFIG_WATCHDOG_NOWAYOUT \
- $CONFIG_WATCHDOG
-dep_tristate ' Software Watchdog' CONFIG_SOFT_WATCHDOG $CONFIG_WATCHDOG
-dep_tristate ' UML watchdog' CONFIG_UML_WATCHDOG $CONFIG_WATCHDOG
-
-tristate 'Sound support' CONFIG_UML_SOUND
-define_tristate CONFIG_SOUND $CONFIG_UML_SOUND
-define_tristate CONFIG_HOSTAUDIO $CONFIG_UML_SOUND
-
-bool 'Enable tty logging' CONFIG_TTY_LOG
-
-endmenu
diff --git a/arch/um/config_net.in b/arch/um/config_net.in
deleted file mode 100644
index f1f6a6e9b13f..000000000000
--- a/arch/um/config_net.in
+++ /dev/null
@@ -1,46 +0,0 @@
-mainmenu_option next_comment
-comment 'Network Devices'
-
-# UML virtual driver
-bool 'Virtual network device' CONFIG_UML_NET
-
-dep_bool ' Ethertap transport' CONFIG_UML_NET_ETHERTAP $CONFIG_UML_NET
-dep_bool ' TUN/TAP transport' CONFIG_UML_NET_TUNTAP $CONFIG_UML_NET
-dep_bool ' SLIP transport' CONFIG_UML_NET_SLIP $CONFIG_UML_NET
-dep_bool ' Daemon transport' CONFIG_UML_NET_DAEMON $CONFIG_UML_NET
-dep_bool ' Multicast transport' CONFIG_UML_NET_MCAST $CONFIG_UML_NET
-dep_bool ' pcap transport' CONFIG_UML_NET_PCAP $CONFIG_UML_NET
-
-# Below are hardware-independent drivers mirrored from
-# drivers/net/Config.in. It would be nice if Linux
-# had HW independent drivers separated from the other
-# but it does not. Until then each non-ISA/PCI arch
-# needs to provide it's own menu of network drivers
-
-tristate 'Dummy net driver support' CONFIG_DUMMY
-tristate 'Bonding driver support' CONFIG_BONDING
-tristate 'EQL (serial line load balancing) support' CONFIG_EQUALIZER
-tristate 'Universal TUN/TAP device driver support' CONFIG_TUN
-if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
- if [ "$CONFIG_NETLINK" = "y" ]; then
- tristate 'Ethertap network tap (OBSOLETE)' CONFIG_ETHERTAP
- fi
-fi
-
-tristate 'PPP (point-to-point protocol) support' CONFIG_PPP
-if [ ! "$CONFIG_PPP" = "n" ]; then
- dep_bool ' PPP multilink support (EXPERIMENTAL)' CONFIG_PPP_MULTILINK $CONFIG_EXPERIMENTAL
- dep_bool ' PPP filtering' CONFIG_PPP_FILTER $CONFIG_FILTER
- dep_tristate ' PPP support for async serial ports' CONFIG_PPP_ASYNC $CONFIG_PPP
- dep_tristate ' PPP support for sync tty ports' CONFIG_PPP_SYNC_TTY $CONFIG_PPP
- dep_tristate ' PPP Deflate compression' CONFIG_PPP_DEFLATE $CONFIG_PPP
- dep_tristate ' PPP BSD-Compress compression' CONFIG_PPP_BSDCOMP $CONFIG_PPP
- dep_tristate ' PPP over Ethernet (EXPERIMENTAL)' CONFIG_PPPOE $CONFIG_PPP $CONFIG_EXPERIMENTAL
-fi
-
-tristate 'SLIP (serial line) support' CONFIG_SLIP
-dep_bool ' CSLIP compressed headers' CONFIG_SLIP_COMPRESSED $CONFIG_SLIP
-dep_bool ' Keepalive and linefill' CONFIG_SLIP_SMART $CONFIG_SLIP
-dep_bool ' Six bit SLIP encapsulation' CONFIG_SLIP_MODE_SLIP6 $CONFIG_SLIP
-
-endmenu
diff --git a/arch/um/config_scsi.in b/arch/um/config_scsi.in
deleted file mode 100644
index ed363965b73f..000000000000
--- a/arch/um/config_scsi.in
+++ /dev/null
@@ -1,30 +0,0 @@
-comment 'SCSI support type (disk, tape, CD-ROM)'
-
-dep_tristate ' SCSI disk support' CONFIG_BLK_DEV_SD $CONFIG_SCSI
-
-if [ "$CONFIG_BLK_DEV_SD" != "n" ]; then
- int 'Maximum number of SCSI disks that can be loaded as modules' CONFIG_SD_EXTRA_DEVS 40
-fi
-
-dep_tristate ' SCSI tape support' CONFIG_CHR_DEV_ST $CONFIG_SCSI
-
-dep_tristate ' SCSI CD-ROM support' CONFIG_BLK_DEV_SR $CONFIG_SCSI
-
-if [ "$CONFIG_BLK_DEV_SR" != "n" ]; then
- bool ' Enable vendor-specific extensions (for SCSI CDROM)' CONFIG_BLK_DEV_SR_VENDOR
- int 'Maximum number of CDROM devices that can be loaded as modules' CONFIG_SR_EXTRA_DEVS 2
-fi
-dep_tristate ' SCSI generic support' CONFIG_CHR_DEV_SG $CONFIG_SCSI
-
-comment 'Some SCSI devices (e.g. CD jukebox) support multiple LUNs'
-
-#if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
- bool ' Enable extra checks in new queueing code' CONFIG_SCSI_DEBUG_QUEUES
-#fi
-
-bool ' Probe all LUNs on each SCSI device' CONFIG_SCSI_MULTI_LUN
-
-bool ' Verbose SCSI error reporting (kernel size +=12K)' CONFIG_SCSI_CONSTANTS
-bool ' SCSI logging facility' CONFIG_SCSI_LOGGING
-
-dep_tristate 'SCSI debugging host simulator (EXPERIMENTAL)' CONFIG_SCSI_DEBUG $CONFIG_SCSI
diff --git a/arch/um/drivers/Makefile b/arch/um/drivers/Makefile
index bd963ccdc7e8..8e72f9032ab6 100644
--- a/arch/um/drivers/Makefile
+++ b/arch/um/drivers/Makefile
@@ -5,23 +5,14 @@
CHAN_OBJS := chan_kern.o chan_user.o line.o
-# This nonsense is due to kbuild. In the 2.4 build, I stick -lpcap in
-# pcap-objs, and that is just included in the link command. The 2.5 kbuild
-# filters out everything from pcap-objs which are not in the built-in.o
-# dependencies, which are $(obj-y). So, -lpcap must be in $(obj-y), too.
-# However, make magically expands -lfoo prerequisites into /usr/lib/libfoo.a
-# file names. This causes the kbuild filtering to filter the -lpcap from
-# pcap-objs, causing the link to fail.
-# So, what this does is figure out by hand (crudely) what file -lpcap really
-# is and just use it.
-
-PCAP = $(shell for f in echo {/lib,/usr/lib}/libpcap.a; do \
- [ -f $$f ] && echo $$f ; done | head -1)
+# pcap is broken in 2.5 because kbuild doesn't allow pcap.a to be linked
+# in to pcap.o
slip-objs := slip_kern.o slip_user.o
+slirp-objs := slirp_kern.o slirp_user.o
daemon-objs := daemon_kern.o daemon_user.o
mcast-objs := mcast_kern.o mcast_user.o
-pcap-objs := pcap_kern.o pcap_user.o $(PCAP)
+#pcap-objs := pcap_kern.o pcap_user.o $(PCAP)
net-objs := net_kern.o net_user.o
mconsole-objs := mconsole_kern.o mconsole_user.o
hostaudio-objs := hostaudio_kern.o hostaudio_user.o
@@ -34,9 +25,10 @@ export-objs := mconsole_kern.o
obj-y =
obj-$(CONFIG_SSL) += ssl.o
obj-$(CONFIG_UML_NET_SLIP) += slip.o
+obj-$(CONFIG_UML_NET_SLIRP) += slirp.o
obj-$(CONFIG_UML_NET_DAEMON) += daemon.o
obj-$(CONFIG_UML_NET_MCAST) += mcast.o
-obj-$(CONFIG_UML_NET_PCAP) += pcap.o $(PCAP)
+#obj-$(CONFIG_UML_NET_PCAP) += pcap.o $(PCAP)
obj-$(CONFIG_UML_NET) += net.o
obj-$(CONFIG_MCONSOLE) += mconsole.o
obj-$(CONFIG_MMAPPER) += mmapper_kern.o
@@ -50,8 +42,6 @@ obj-$(CONFIG_TTY_CHAN) += tty.o
obj-$(CONFIG_XTERM_CHAN) += xterm.o xterm_kern.o
obj-$(CONFIG_UML_WATCHDOG) += harddog.o
-CFLAGS_pcap_user.o = -I/usr/include/pcap
-
obj-y += stdio_console.o $(CHAN_OBJS)
USER_SINGLE_OBJS = $(foreach f,$(patsubst %.o,%,$(obj-y) $(obj-m)),$($(f)-objs))
@@ -61,7 +51,7 @@ USER_OBJS := $(filter %_user.o,$(obj-y) $(obj-m) $(USER_SINGLE_OBJS)) fd.o \
USER_OBJS := $(foreach file,$(USER_OBJS),arch/um/drivers/$(file))
$(USER_OBJS) : %.o: %.c
- $(CC) $(CFLAGS_$@) $(USER_CFLAGS) -c -o $@ $<
+ $(CC) $(CFLAGS_$(notdir $@)) $(USER_CFLAGS) -c -o $@ $<
clean:
diff --git a/arch/um/drivers/chan_kern.c b/arch/um/drivers/chan_kern.c
index 46a84e8e916c..119cce1bb689 100644
--- a/arch/um/drivers/chan_kern.c
+++ b/arch/um/drivers/chan_kern.c
@@ -24,7 +24,8 @@ static void *not_configged_init(char *str, int device, struct chan_opts *opts)
return(NULL);
}
-static int not_configged_open(int input, int output, int primary, void *data)
+static int not_configged_open(int input, int output, int primary, void *data,
+ char **dev_out)
{
printk(KERN_ERR "Using a channel type which is configured out of "
"UML\n");
@@ -112,7 +113,8 @@ static int open_one_chan(struct chan *chan, int input, int output, int primary)
if(chan->opened) return(0);
if(chan->ops->open == NULL) fd = 0;
- else fd = (*chan->ops->open)(input, output, primary, chan->data);
+ else fd = (*chan->ops->open)(input, output, primary, chan->data,
+ &chan->dev);
if(fd < 0) return(fd);
chan->fd = fd;
@@ -258,6 +260,66 @@ void free_chan(struct list_head *chans)
}
}
+static int one_chan_config_string(struct chan *chan, char *str, int size,
+ char **error_out)
+{
+ int n = 0;
+
+ CONFIG_CHUNK(str, size, n, chan->ops->type, 0);
+
+ if(chan->dev == NULL){
+ CONFIG_CHUNK(str, size, n, "", 1);
+ return(n);
+ }
+
+ CONFIG_CHUNK(str, size, n, ":", 0);
+ CONFIG_CHUNK(str, size, n, chan->dev, 0);
+
+ return(n);
+}
+
+static int chan_pair_config_string(struct chan *in, struct chan *out,
+ char *str, int size, char **error_out)
+{
+ int n;
+
+ n = one_chan_config_string(in, str, size, error_out);
+ str += n;
+ size -= n;
+
+ if(in == out){
+ CONFIG_CHUNK(str, size, n, "", 1);
+ return(n);
+ }
+
+ CONFIG_CHUNK(str, size, n, ",", 1);
+ n = one_chan_config_string(out, str, size, error_out);
+ str += n;
+ size -= n;
+ CONFIG_CHUNK(str, size, n, "", 1);
+
+ return(n);
+}
+
+int chan_config_string(struct list_head *chans, char *str, int size,
+ char **error_out)
+{
+ struct list_head *ele;
+ struct chan *chan, *in = NULL, *out = NULL;
+
+ list_for_each(ele, chans){
+ chan = list_entry(ele, struct chan, list);
+ if(!chan->primary)
+ continue;
+ if(chan->input)
+ in = chan;
+ if(chan->output)
+ out = chan;
+ }
+
+ return(chan_pair_config_string(in, out, str, size, error_out));
+}
+
struct chan_type {
char *key;
struct chan_ops *ops;
diff --git a/arch/um/drivers/chan_user.c b/arch/um/drivers/chan_user.c
index 79879f30aef5..e06f20a14877 100644
--- a/arch/um/drivers/chan_user.c
+++ b/arch/um/drivers/chan_user.c
@@ -19,6 +19,8 @@
#include "user.h"
#include "helper.h"
#include "os.h"
+#include "choose-mode.h"
+#include "mode.h"
void generic_close(int fd, void *unused)
{
@@ -144,32 +146,6 @@ static int winch_thread(void *arg)
}
}
-static int tracer_winch[2];
-
-static void tracer_winch_handler(int sig)
-{
- char c = 1;
-
- if(write(tracer_winch[1], &c, sizeof(c)) != sizeof(c))
- printk("tracer_winch_handler - write failed, errno = %d\n",
- errno);
-}
-
-/* Called only by the tracing thread during initialization */
-
-void setup_tracer_winch(void)
-{
- int err;
-
- err = os_pipe(tracer_winch, 1, 1);
- if(err){
- printk("setup_tracer_winch : os_pipe failed, errno = %d\n",
- -err);
- return;
- }
- signal(SIGWINCH, tracer_winch_handler);
-}
-
static int winch_tramp(int fd, void *device_data, int *fd_out)
{
struct winch_data data;
@@ -212,9 +188,8 @@ void register_winch(int fd, void *device_data)
if(!isatty(fd)) return;
pid = tcgetpgrp(fd);
- if(pid == tracing_pid)
- register_winch_irq(tracer_winch[0], fd, -1, device_data);
- else if(pid == -1){
+ if(!CHOOSE_MODE(is_tracer_winch(pid, fd, device_data), 0) &&
+ (pid == -1)){
thread = winch_tramp(fd, device_data, &thread_fd);
if(fd != -1){
register_winch_irq(thread_fd, fd, thread, device_data);
diff --git a/arch/um/drivers/fd.c b/arch/um/drivers/fd.c
index e31620d15a77..60fc63adce4a 100644
--- a/arch/um/drivers/fd.c
+++ b/arch/um/drivers/fd.c
@@ -15,6 +15,7 @@ struct fd_chan {
int fd;
int raw;
struct termios tt;
+ char str[sizeof("1234567890\0")];
};
void *fd_init(char *str, int device, struct chan_opts *opts)
@@ -30,7 +31,7 @@ void *fd_init(char *str, int device, struct chan_opts *opts)
}
str++;
n = strtoul(str, &end, 0);
- if(*end != '\0'){
+ if((*end != '\0') || (end == str)){
printk("fd_init : couldn't parse file descriptor '%s'\n", str);
return(NULL);
}
@@ -40,7 +41,7 @@ void *fd_init(char *str, int device, struct chan_opts *opts)
return(data);
}
-int fd_open(int input, int output, int primary, void *d)
+int fd_open(int input, int output, int primary, void *d, char **dev_out)
{
struct fd_chan *data = d;
@@ -48,6 +49,8 @@ int fd_open(int input, int output, int primary, void *d)
tcgetattr(data->fd, &data->tt);
raw(data->fd, 0);
}
+ sprintf(data->str, "%d", data->fd);
+ *dev_out = data->str;
return(data->fd);
}
@@ -69,6 +72,7 @@ int fd_console_write(int fd, const char *buf, int n, void *d)
}
struct chan_ops fd_ops = {
+ type: "fd",
init: fd_init,
open: fd_open,
close: fd_close,
diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c
index 837c07f41669..576f3f655a04 100644
--- a/arch/um/drivers/line.c
+++ b/arch/um/drivers/line.c
@@ -8,11 +8,13 @@
#include "linux/list.h"
#include "linux/devfs_fs_kernel.h"
#include "asm/irq.h"
+#include "asm/uaccess.h"
#include "chan_kern.h"
#include "irq_user.h"
#include "line.h"
#include "kern.h"
#include "user_util.h"
+#include "kern_util.h"
#include "os.h"
#define LINE_BUFSIZE 4096
@@ -87,15 +89,26 @@ static int flush_buffer(struct line *line)
return(line->head == line->tail);
}
-int line_write(struct line *lines, struct tty_struct *tty, const char *buf,
- int len)
+int line_write(struct line *lines, struct tty_struct *tty, int from_user,
+ const char *buf, int len)
{
struct line *line;
+ char *new;
unsigned long flags;
int n, err, i;
if(tty->stopped) return 0;
+ if(from_user){
+ new = kmalloc(len, GFP_KERNEL);
+ if(new == NULL)
+ return(0);
+ n = copy_from_user(new, buf, len);
+ if(n == len)
+ return(-EFAULT);
+ buf = new;
+ }
+
i = minor(tty->device) - tty->driver.minor_start;
line = &lines[i];
@@ -281,7 +294,7 @@ void close_lines(struct line *lines, int nlines)
close_chan(&lines[i].chan_list);
}
-void line_setup(struct line *lines, int num, char *init)
+int line_setup(struct line *lines, int num, char *init, int all_allowed)
{
int i, n;
char *end;
@@ -292,12 +305,36 @@ void line_setup(struct line *lines, int num, char *init)
if(*end != '='){
printk(KERN_ERR "line_setup failed to parse \"%s\"\n",
init);
- return;
+ return(1);
}
init = end;
}
init++;
- if(n == -1){
+ if((n >= 0) && (n >= num)){
+ printk("line_setup - %d out of range ((0 ... %d) allowed)\n",
+ n, num);
+ return(1);
+ }
+ else if(n >= 0){
+ if(lines[n].count > 0){
+ printk("line_setup - device %d is open\n", n);
+ return(1);
+ }
+ if(lines[n].init_pri <= INIT_ONE){
+ lines[n].init_pri = INIT_ONE;
+ if(!strcmp(init, "none")) lines[n].valid = 0;
+ else {
+ lines[n].init_str = init;
+ lines[n].valid = 1;
+ }
+ }
+ }
+ else if(!all_allowed){
+ printk("line_setup - can't configure all devices from "
+ "mconsole\n");
+ return(1);
+ }
+ else {
for(i = 0; i < num; i++){
if(lines[i].init_pri <= INIT_ALL){
lines[i].init_pri = INIT_ALL;
@@ -309,14 +346,57 @@ void line_setup(struct line *lines, int num, char *init)
}
}
}
- else if(lines[n].init_pri <= INIT_ONE){
- lines[n].init_pri = INIT_ONE;
- if(!strcmp(init, "none")) lines[n].valid = 0;
- else {
- lines[n].init_str = init;
- lines[n].valid = 1;
- }
+ return(0);
+}
+
+int line_config(struct line *lines, int num, char *str)
+{
+ char *new = uml_strdup(str);
+
+ if(new == NULL){
+ printk("line_config - uml_strdup failed\n");
+ return(-ENOMEM);
}
+ return(line_setup(lines, num, new, 0));
+}
+
+int line_get_config(char *name, struct line *lines, int num, char *str,
+ int size, char **error_out)
+{
+ struct line *line;
+ char *end;
+ int dev, n = 0;
+
+ dev = simple_strtoul(name, &end, 0);
+ if((*end != '\0') || (end == name)){
+ *error_out = "line_setup failed to parse device number";
+ return(0);
+ }
+
+ if((dev < 0) || (dev >= num)){
+ *error_out = "device number of of range";
+ return(0);
+ }
+
+ line = &lines[dev];
+ down(&line->sem);
+
+ if(!line->valid)
+ CONFIG_CHUNK(str, size, n, "none", 1);
+ else if(line->count == 0)
+ CONFIG_CHUNK(str, size, n, line->init_str, 1);
+ else n = chan_config_string(&line->chan_list, str, size, error_out);
+
+ up(&line->sem);
+ return(n);
+}
+
+int line_remove(struct line *lines, int num, char *str)
+{
+ char config[sizeof("conxxxx=none\0")];
+
+ sprintf(config, "%s=none", str);
+ return(line_setup(lines, num, config, 0));
}
void line_register_devfs(struct lines *set, struct line_driver *line_driver,
@@ -366,6 +446,8 @@ void line_register_devfs(struct lines *set, struct line_driver *line_driver,
if(!lines[i].valid)
tty_unregister_devfs(driver, driver->minor_start + i);
}
+
+ mconsole_register_dev(&line_driver->mc);
}
void lines_init(struct line *lines, int nlines)
@@ -451,7 +533,7 @@ static void winch_cleanup(void)
list_for_each(ele, &winch_handlers){
winch = list_entry(ele, struct winch, list);
close(winch->fd);
- if(winch->pid != -1) os_kill_process(winch->pid);
+ if(winch->pid != -1) os_kill_process(winch->pid, 0);
}
}
diff --git a/arch/um/drivers/mcast_kern.c b/arch/um/drivers/mcast_kern.c
index 25158ba650c2..a0cbc72b8cd3 100644
--- a/arch/um/drivers/mcast_kern.c
+++ b/arch/um/drivers/mcast_kern.c
@@ -92,7 +92,7 @@ int mcast_setup(char *str, char **mac_out, void *data)
if(port_str != NULL){
n = simple_strtoul(port_str, &last, 10);
- if(*last != '\0'){
+ if((*last != '\0') || (last == port_str)){
printk(KERN_ERR "mcast_setup - Bad port : '%s'\n",
port_str);
return(0);
@@ -102,7 +102,7 @@ int mcast_setup(char *str, char **mac_out, void *data)
if(ttl_str != NULL){
init->ttl = simple_strtoul(ttl_str, &last, 10);
- if(*last != '\0'){
+ if((*last != '\0') || (last == ttl_str)){
printk(KERN_ERR "mcast_setup - Bad ttl : '%s'\n",
ttl_str);
return(0);
diff --git a/arch/um/drivers/mconsole_kern.c b/arch/um/drivers/mconsole_kern.c
index 49c1773e0c9b..8ba898759587 100644
--- a/arch/um/drivers/mconsole_kern.c
+++ b/arch/um/drivers/mconsole_kern.c
@@ -108,6 +108,7 @@ void mconsole_version(struct mc_request *req)
reboot - Reboot UML
config <dev>=<config> - Add a new device to UML;
same syntax as command line
+ config <dev> - Query the configuration of a device
remove <dev> - Remove a device from UML
sysrq <letter> - Performs the SysRq action controlled by the letter
cad - invoke the Ctl-Alt-Del handler
@@ -181,10 +182,56 @@ static struct mc_device *mconsole_find_dev(char *name)
return(NULL);
}
+#define CONFIG_BUF_SIZE 64
+
+static void mconsole_get_config(int (*get_config)(char *, char *, int,
+ char **),
+ struct mc_request *req, char *name)
+{
+ char default_buf[CONFIG_BUF_SIZE], *error, *buf;
+ int n, size;
+
+ if(get_config == NULL){
+ mconsole_reply(req, "No get_config routine defined", 1, 0);
+ return;
+ }
+
+ error = NULL;
+ size = sizeof(default_buf)/sizeof(default_buf[0]);
+ buf = default_buf;
+
+ while(1){
+ n = (*get_config)(name, buf, size, &error);
+ if(error != NULL){
+ mconsole_reply(req, error, 1, 0);
+ goto out;
+ }
+
+ if(n <= size){
+ mconsole_reply(req, buf, 0, 0);
+ goto out;
+ }
+
+ if(buf != default_buf)
+ kfree(buf);
+
+ size = n;
+ buf = kmalloc(size, GFP_KERNEL);
+ if(buf == NULL){
+ mconsole_reply(req, "Failed to allocate buffer", 1, 0);
+ return;
+ }
+ }
+ out:
+ if(buf != default_buf)
+ kfree(buf);
+
+}
+
void mconsole_config(struct mc_request *req)
{
struct mc_device *dev;
- char *ptr = req->request.data;
+ char *ptr = req->request.data, *name;
int err;
ptr += strlen("config");
@@ -194,8 +241,17 @@ void mconsole_config(struct mc_request *req)
mconsole_reply(req, "Bad configuration option", 1, 0);
return;
}
- err = (*dev->config)(&ptr[strlen(dev->name)]);
- mconsole_reply(req, "", err, 0);
+
+ name = &ptr[strlen(dev->name)];
+ ptr = name;
+ while((*ptr != '=') && (*ptr != '\0'))
+ ptr++;
+
+ if(*ptr == '='){
+ err = (*dev->config)(name);
+ mconsole_reply(req, "", err, 0);
+ }
+ else mconsole_get_config(dev->get_config, req, name);
}
void mconsole_remove(struct mc_request *req)
diff --git a/arch/um/drivers/net_kern.c b/arch/um/drivers/net_kern.c
index deef1a0a75e3..f6bda1b3b1fe 100644
--- a/arch/um/drivers/net_kern.c
+++ b/arch/um/drivers/net_kern.c
@@ -39,7 +39,6 @@ static int uml_net_rx(struct net_device *dev)
/* If we can't allocate memory, try again next round. */
if ((skb = dev_alloc_skb(dev->mtu)) == NULL) {
lp->stats.rx_dropped++;
- reactivate_fd(lp->fd, UM_ETH_IRQ);
return 0;
}
@@ -48,7 +47,6 @@ static int uml_net_rx(struct net_device *dev)
skb->mac.raw = skb->data;
pkt_len = (*lp->read)(lp->fd, &skb, lp);
- reactivate_fd(lp->fd, UM_ETH_IRQ);
if (pkt_len > 0) {
skb_trim(skb, pkt_len);
skb->protocol = (*lp->protocol)(skb);
@@ -69,18 +67,22 @@ void uml_net_interrupt(int irq, void *dev_id, struct pt_regs *regs)
struct uml_net_private *lp = dev->priv;
int err;
- if (netif_running(dev)) {
- spin_lock(&lp->lock);
- while((err = uml_net_rx(dev)) > 0) ;
- if(err < 0) {
- printk(KERN_ERR
- "Device '%s' read returned %d, shutting it "
- "down\n", dev->name, err);
- dev->flags &= ~IFF_UP;
- dev_close(dev);
- }
- spin_unlock(&lp->lock);
+ if(!netif_running(dev))
+ return;
+
+ spin_lock(&lp->lock);
+ while((err = uml_net_rx(dev)) > 0) ;
+ if(err < 0) {
+ printk(KERN_ERR
+ "Device '%s' read returned %d, shutting it down\n",
+ dev->name, err);
+ dev_close(dev);
+ goto out;
}
+ reactivate_fd(lp->fd, UM_ETH_IRQ);
+
+ out:
+ spin_unlock(&lp->lock);
}
static int uml_net_open(struct net_device *dev)
@@ -250,6 +252,37 @@ void uml_net_user_timer_expire(unsigned long _conn)
#endif
}
+/*
+ * default do nothing hard header packet routines for struct net_device init.
+ * real ethernet transports will overwrite with real routines.
+ */
+static int uml_net_hard_header(struct sk_buff *skb, struct net_device *dev,
+ unsigned short type, void *daddr, void *saddr, unsigned len)
+{
+ return(0); /* no change */
+}
+
+static int uml_net_rebuild_header(struct sk_buff *skb)
+{
+ return(0); /* ignore */
+}
+
+static int uml_net_header_cache(struct neighbour *neigh, struct hh_cache *hh)
+{
+ return(-1); /* fail */
+}
+
+static void uml_net_header_cache_update(struct hh_cache *hh,
+ struct net_device *dev, unsigned char * haddr)
+{
+ /* ignore */
+}
+
+static int uml_net_header_parse(struct sk_buff *skb, unsigned char *haddr)
+{
+ return(0); /* nothing */
+}
+
static spinlock_t devices_lock = SPIN_LOCK_UNLOCKED;
static struct list_head devices = LIST_HEAD_INIT(devices);
@@ -261,21 +294,25 @@ static int eth_configure(int n, void *init, char *mac,
struct uml_net_private *lp;
int save, err, size;
+ size = transport->private_size + sizeof(struct uml_net_private) +
+ sizeof(((struct uml_net_private *) 0)->user);
+
device = kmalloc(sizeof(*device), GFP_KERNEL);
if(device == NULL){
printk(KERN_ERR "eth_configure failed to allocate uml_net\n");
return(1);
}
+ *device = ((struct uml_net) { .list = LIST_HEAD_INIT(device->list),
+ .dev = NULL,
+ .index = n,
+ .mac = { [ 0 ... 5 ] = 0 },
+ .have_mac = 0 });
+
spin_lock(&devices_lock);
list_add(&device->list, &devices);
spin_unlock(&devices_lock);
- device->index = n;
-
- size = transport->private_size + sizeof(struct uml_net_private) +
- sizeof(((struct uml_net_private *) 0)->user);
-
if(setup_etheraddr(mac, device->mac))
device->have_mac = 1;
@@ -290,10 +327,18 @@ static int eth_configure(int n, void *init, char *mac,
printk(KERN_ERR "eth_configure: failed to allocate device\n");
return(1);
}
+ memset(dev, 0, sizeof(*dev) + size);
+
snprintf(dev->name, sizeof(dev->name), "eth%d", n);
dev->priv = (void *) &dev[1];
device->dev = dev;
+ dev->hard_header = uml_net_hard_header;
+ dev->rebuild_header = uml_net_rebuild_header;
+ dev->hard_header_cache = uml_net_header_cache;
+ dev->header_cache_update= uml_net_header_cache_update;
+ dev->hard_header_parse = uml_net_header_parse;
+
(*transport->kern->init)(dev, init);
dev->mtu = transport->user->max_packet;
@@ -308,32 +353,6 @@ static int eth_configure(int n, void *init, char *mac,
dev->do_ioctl = uml_net_ioctl;
dev->watchdog_timeo = (HZ >> 1);
dev->irq = UM_ETH_IRQ;
- dev->init = NULL;
- dev->master = NULL;
- dev->neigh_setup = NULL;
- dev->owner = NULL;
- dev->state = 0;
- dev->next_sched = 0;
- dev->get_wireless_stats = 0;
- dev->wireless_handlers = 0;
- dev->gflags = 0;
- dev->mc_list = NULL;
- dev->mc_count = 0;
- dev->promiscuity = 0;
- dev->atalk_ptr = NULL;
- dev->ip_ptr = NULL;
- dev->dn_ptr = NULL;
- dev->ip6_ptr = NULL;
- dev->ec_ptr = NULL;
- atomic_set(&dev->refcnt, 0);
- dev->features = 0;
- dev->uninit = NULL;
- dev->destructor = NULL;
- dev->set_config = NULL;
- dev->accept_fastpath = 0;
- dev->br_port = 0;
- dev->mem_start = 0;
- dev->mem_end = 0;
rtnl_lock();
err = register_netdevice(dev);
@@ -372,6 +391,7 @@ static int eth_configure(int n, void *init, char *mac,
if(transport->user->init)
(*transport->user->init)(&lp->user, dev);
+
if(device->have_mac)
set_ether_mac(dev, device->mac);
return(0);
@@ -486,7 +506,6 @@ void register_transport(struct transport *new)
kfree(init);
}
list_del(&eth->list);
- return;
}
}
@@ -580,7 +599,7 @@ static int net_remove(char *str)
int n;
n = simple_strtoul(str, &end, 0);
- if(*end != '\0')
+ if((*end != '\0') || (end == str))
return(-1);
device = find_device(n);
diff --git a/arch/um/drivers/null.c b/arch/um/drivers/null.c
index 08cc7b0a165e..6a41c213e0d6 100644
--- a/arch/um/drivers/null.c
+++ b/arch/um/drivers/null.c
@@ -3,6 +3,7 @@
* Licensed under the GPL
*/
+#include <stdlib.h>
#include <errno.h>
#include <fcntl.h>
#include "chan_user.h"
@@ -15,8 +16,9 @@ void *null_init(char *str, int device, struct chan_opts *opts)
return(&null_chan);
}
-int null_open(int input, int output, int primary, void *d)
+int null_open(int input, int output, int primary, void *d, char **dev_out)
{
+ *dev_out = NULL;
return(os_open_file(DEV_NULL, of_rdwr(OPENFLAGS()), 0));
}
@@ -30,6 +32,7 @@ void null_free(void *data)
}
struct chan_ops null_ops = {
+ type: "null",
init: null_init,
open: null_open,
close: generic_close,
diff --git a/arch/um/drivers/port_kern.c b/arch/um/drivers/port_kern.c
index 25a1c47c116f..15ce4f90ab95 100644
--- a/arch/um/drivers/port_kern.c
+++ b/arch/um/drivers/port_kern.c
@@ -32,8 +32,8 @@ struct port_list {
struct port_dev {
struct port_list *port;
int fd;
- int helper_pid;
- int telnetd_pid;
+ int helper_pid;
+ int telnetd_pid;
};
struct connection {
@@ -50,7 +50,7 @@ static void pipe_interrupt(int irq, void *data, struct pt_regs *regs)
struct connection *conn = data;
int fd;
- fd = os_rcv_fd(conn->socket[0], &conn->helper_pid);
+ fd = os_rcv_fd(conn->socket[0], &conn->helper_pid);
if(fd < 0){
if(fd == -EAGAIN)
return;
@@ -99,14 +99,13 @@ static int port_accept(struct port_list *port)
}
list_add(&conn->list, &port->pending);
- ret = 1;
- goto out;
+ return(1);
out_free:
kfree(conn);
out_close:
os_close_file(fd);
- if(pid != -1) os_kill_process(pid);
+ if(pid != -1) os_kill_process(pid, 0);
out:
return(ret);
}
@@ -191,9 +190,9 @@ void *port_data(int port_num)
goto out;
}
- *dev = ((struct port_dev) { port : port,
- fd : -1,
- helper_pid : -1 });
+ *dev = ((struct port_dev) { port : port,
+ fd : -1,
+ helper_pid : -1 });
goto out;
out_free:
@@ -210,9 +209,9 @@ void port_remove_dev(void *d)
struct port_dev *dev = d;
if(dev->helper_pid != -1)
- os_kill_process(dev->helper_pid);
+ os_kill_process(dev->helper_pid, 0);
if(dev->telnetd_pid != -1)
- os_kill_process(dev->telnetd_pid);
+ os_kill_process(dev->telnetd_pid, 0);
dev->helper_pid = -1;
}
@@ -275,8 +274,8 @@ void port_kern_free(void *d)
{
struct port_dev *dev = d;
- if(dev->helper_pid != -1) os_kill_process(dev->telnetd_pid);
- if(dev->telnetd_pid != -1) os_kill_process(dev->telnetd_pid);
+ if(dev->helper_pid != -1) os_kill_process(dev->helper_pid, 0);
+ if(dev->telnetd_pid != -1) os_kill_process(dev->telnetd_pid, 0);
kfree(dev);
}
diff --git a/arch/um/drivers/port_user.c b/arch/um/drivers/port_user.c
index 35f163da9d32..3e0d3950ac1c 100644
--- a/arch/um/drivers/port_user.c
+++ b/arch/um/drivers/port_user.c
@@ -3,11 +3,12 @@
* Licensed under the GPL
*/
+#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
+#include <string.h>
#include <errno.h>
#include <unistd.h>
-#include <string.h>
#include <termios.h>
#include <sys/socket.h>
#include <sys/un.h>
@@ -24,6 +25,7 @@ struct port_chan {
int raw;
struct termios tt;
void *kernel_data;
+ char dev[sizeof("32768\0")];
};
void *port_init(char *str, int device, struct chan_opts *opts)
@@ -40,7 +42,7 @@ void *port_init(char *str, int device, struct chan_opts *opts)
}
str++;
port = strtoul(str, &end, 0);
- if(*end != '\0'){
+ if((*end != '\0') || (end == str)){
printk("port_init : couldn't parse port '%s'\n", str);
return(NULL);
}
@@ -50,11 +52,12 @@ void *port_init(char *str, int device, struct chan_opts *opts)
if((data = um_kmalloc(sizeof(*data))) == NULL) return(NULL);
*data = ((struct port_chan) { raw : opts->raw,
kernel_data : kern_data });
+ sprintf(data->dev, "%d", port);
return(data);
}
-int port_open(int input, int output, int primary, void *d)
+int port_open(int input, int output, int primary, void *d, char **dev_out)
{
struct port_chan *data = d;
int fd;
@@ -64,6 +67,7 @@ int port_open(int input, int output, int primary, void *d)
tcgetattr(fd, &data->tt);
raw(fd, 0);
}
+ *dev_out = data->dev;
return(fd);
}
@@ -91,6 +95,7 @@ void port_free(void *d)
}
struct chan_ops port_ops = {
+ type: "port",
init: port_init,
open: port_open,
close: port_close,
@@ -129,42 +134,6 @@ int port_listen_fd(int port)
return(err);
}
-int port_rcv_fd(int fd)
-{
- int new, n;
- char buf[CMSG_SPACE(sizeof(new))];
- struct msghdr msg;
- struct cmsghdr *cmsg;
-
- msg.msg_name = NULL;
- msg.msg_namelen = 0;
- msg.msg_iov = NULL;
- msg.msg_iovlen = 0;
- msg.msg_control = buf;
- msg.msg_controllen = sizeof(buf);
- msg.msg_flags = 0;
-
- n = recvmsg(fd, &msg, 0);
- if(n < 0){
- printk("rcv_fd : recvmsg failed - errno = %d\n", errno);
- return(-1);
- }
-
- cmsg = CMSG_FIRSTHDR(&msg);
- if(cmsg == NULL){
- printk("rcv_fd didn't receive anything, error = %d\n", errno);
- return(-1);
- }
- if((cmsg->cmsg_level != SOL_SOCKET) ||
- (cmsg->cmsg_type != SCM_RIGHTS)){
- printk("rcv_fd didn't receive a descriptor\n");
- return(-1);
- }
-
- new = ((int *) CMSG_DATA(cmsg))[0];
- return(new);
-}
-
struct port_pre_exec_data {
int sock_fd;
int pipe_fd;
diff --git a/arch/um/drivers/pty.c b/arch/um/drivers/pty.c
index 6054dd6aa9ac..213b35d1dcfc 100644
--- a/arch/um/drivers/pty.c
+++ b/arch/um/drivers/pty.c
@@ -19,6 +19,7 @@ struct pty_chan {
int dev;
int raw;
struct termios tt;
+ char dev_name[sizeof("/dev/pts/0123456\0")];
};
void *pty_chan_init(char *str, int device, struct chan_opts *opts)
@@ -32,9 +33,10 @@ void *pty_chan_init(char *str, int device, struct chan_opts *opts)
return(data);
}
-int pts_open(int input, int output, int primary, void *d)
+int pts_open(int input, int output, int primary, void *d, char **dev_out)
{
struct pty_chan *data = d;
+ char *dev;
int fd;
if((fd = get_pty()) < 0){
@@ -45,7 +47,11 @@ int pts_open(int input, int output, int primary, void *d)
tcgetattr(fd, &data->tt);
raw(fd, 0);
}
- if(data->announce) (*data->announce)(ptsname(fd), data->dev);
+
+ dev = ptsname(fd);
+ sprintf(data->dev_name, "%s", dev);
+ *dev_out = data->dev_name;
+ if(data->announce) (*data->announce)(dev, data->dev);
return(fd);
}
@@ -94,7 +100,7 @@ static void grantpt_cb(void *arg)
info->err = errno;
}
-int pty_open(int input, int output, int primary, void *d)
+int pty_open(int input, int output, int primary, void *d, char **dev_out)
{
struct pty_chan *data = d;
int fd;
@@ -105,11 +111,14 @@ int pty_open(int input, int output, int primary, void *d)
if(fd < 0) return(-errno);
info.fd = fd;
- tracing_cb(grantpt_cb, &info);
+ initial_thread_cb(grantpt_cb, &info);
unlockpt(fd);
if(data->raw) raw(fd, 0);
if(data->announce) (*data->announce)(dev, data->dev);
+
+ sprintf(data->dev_name, "%s", dev);
+ *dev_out = data->dev_name;
return(fd);
}
@@ -121,6 +130,7 @@ int pty_console_write(int fd, const char *buf, int n, void *d)
}
struct chan_ops pty_ops = {
+ type: "pty",
init: pty_chan_init,
open: pty_open,
close: generic_close,
@@ -133,6 +143,7 @@ struct chan_ops pty_ops = {
};
struct chan_ops pts_ops = {
+ type: "pts",
init: pty_chan_init,
open: pts_open,
close: generic_close,
diff --git a/arch/um/drivers/slip.h b/arch/um/drivers/slip.h
index 6fe5588e8a21..495f2f1b1420 100644
--- a/arch/um/drivers/slip.h
+++ b/arch/um/drivers/slip.h
@@ -2,6 +2,9 @@
#define __UM_SLIP_H
#define BUF_SIZE 1500
+ /* two bytes each for a (pathological) max packet of escaped chars + *
+ * terminating END char + initial END char */
+#define ENC_BUF_SIZE (2 * BUF_SIZE + 2)
struct slip_data {
void *dev;
@@ -9,10 +12,9 @@ struct slip_data {
char *addr;
char *gate_addr;
int slave;
- /* two bytes each for a (pathological) max packet of escaped chars +
- * terminating END char + inital END char
- */
- char buf[2 * BUF_SIZE + 2];
+ char ibuf[ENC_BUF_SIZE];
+ char obuf[ENC_BUF_SIZE];
+ int more; /* more data: do not read fd until ibuf has been drained */
int pos;
int esc;
};
diff --git a/arch/um/drivers/slip_kern.c b/arch/um/drivers/slip_kern.c
index 1ca56f563757..f498a83d9db5 100644
--- a/arch/um/drivers/slip_kern.c
+++ b/arch/um/drivers/slip_kern.c
@@ -1,3 +1,4 @@
+#include "linux/config.h"
#include "linux/kernel.h"
#include "linux/stddef.h"
#include "linux/init.h"
@@ -24,21 +25,19 @@ void slip_init(struct net_device *dev, void *data)
{ name : { '\0' },
addr: NULL,
gate_addr : init->gate_addr,
- slave : 0,
- buf : { '\0' },
+ slave : -1,
+ ibuf : { '\0' },
+ obuf : { '\0' },
pos : 0,
esc : 0,
dev : dev });
- strncpy(dev->name, "umn", IFNAMSIZ);
dev->init = NULL;
dev->hard_header_len = 0;
dev->addr_len = 4;
dev->type = ARPHRD_ETHER;
dev->tx_queue_len = 256;
dev->flags = IFF_NOARP;
- if(register_netdev(dev))
- printk(KERN_ERR "Couldn't initialize umn\n");
printk("SLIP backend - SLIP IP = %s\n", spri->gate_addr);
}
diff --git a/arch/um/drivers/slip_proto.h b/arch/um/drivers/slip_proto.h
new file mode 100644
index 000000000000..7206361ace45
--- /dev/null
+++ b/arch/um/drivers/slip_proto.h
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#ifndef __UM_SLIP_PROTO_H__
+#define __UM_SLIP_PROTO_H__
+
+/* SLIP protocol characters. */
+#define SLIP_END 0300 /* indicates end of frame */
+#define SLIP_ESC 0333 /* indicates byte stuffing */
+#define SLIP_ESC_END 0334 /* ESC ESC_END means END 'data' */
+#define SLIP_ESC_ESC 0335 /* ESC ESC_ESC means ESC 'data' */
+
+static inline int slip_unesc(unsigned char c,char *buf,int *pos, int *esc)
+{
+ int ret;
+
+ switch(c){
+ case SLIP_END:
+ *esc = 0;
+ ret=*pos;
+ *pos=0;
+ return(ret);
+ case SLIP_ESC:
+ *esc = 1;
+ return(0);
+ case SLIP_ESC_ESC:
+ if(*esc){
+ *esc = 0;
+ c = SLIP_ESC;
+ }
+ break;
+ case SLIP_ESC_END:
+ if(*esc){
+ *esc = 0;
+ c = SLIP_END;
+ }
+ break;
+ }
+ buf[(*pos)++] = c;
+ return(0);
+}
+
+static inline int slip_esc(unsigned char *s, unsigned char *d, int len)
+{
+ unsigned char *ptr = d;
+ unsigned char c;
+
+ /*
+ * Send an initial END character to flush out any
+ * data that may have accumulated in the receiver
+ * due to line noise.
+ */
+
+ *ptr++ = SLIP_END;
+
+ /*
+ * For each byte in the packet, send the appropriate
+ * character sequence, according to the SLIP protocol.
+ */
+
+ while (len-- > 0) {
+ switch(c = *s++) {
+ case SLIP_END:
+ *ptr++ = SLIP_ESC;
+ *ptr++ = SLIP_ESC_END;
+ break;
+ case SLIP_ESC:
+ *ptr++ = SLIP_ESC;
+ *ptr++ = SLIP_ESC_ESC;
+ break;
+ default:
+ *ptr++ = c;
+ break;
+ }
+ }
+ *ptr++ = SLIP_END;
+ return (ptr - d);
+}
+
+#endif
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only. This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff --git a/arch/um/drivers/slip_user.c b/arch/um/drivers/slip_user.c
index d8cd43c2f555..e36e8213671b 100644
--- a/arch/um/drivers/slip_user.c
+++ b/arch/um/drivers/slip_user.c
@@ -15,6 +15,7 @@
#include "user.h"
#include "net_user.h"
#include "slip.h"
+#include "slip_proto.h"
#include "helper.h"
#include "os.h"
@@ -66,7 +67,7 @@ static void slip_pre_exec(void *arg)
if(data->stdin != -1) dup2(data->stdin, 0);
dup2(data->stdout, 1);
- close(data->close_me);
+ if(data->close_me != -1) close(data->close_me);
}
static int slip_tramp(char **argv, int fd)
@@ -156,7 +157,7 @@ static int slip_open(void *data)
}
sencap = 0;
if(ioctl(sfd, SIOCSIFENCAP, &sencap) < 0){
- printk("Failed to sett slip encapsulation - "
+ printk("Failed to set slip encapsulation - "
"errno = %d\n", errno);
return(-errno);
}
@@ -186,103 +187,48 @@ static void slip_close(int fd, void *data)
pri->slave = -1;
}
-/* SLIP protocol characters. */
-#define END 0300 /* indicates end of frame */
-#define ESC 0333 /* indicates byte stuffing */
-#define ESC_END 0334 /* ESC ESC_END means END 'data' */
-#define ESC_ESC 0335 /* ESC ESC_ESC means ESC 'data' */
-
-static int slip_unesc(struct slip_data *sl, unsigned char c)
-{
- int ret;
-
- switch(c){
- case END:
- sl->esc = 0;
- ret = sl->pos;
- sl->pos = 0;
- return(ret);
- case ESC:
- sl->esc = 1;
- return(0);
- case ESC_ESC:
- if(sl->esc){
- sl->esc = 0;
- c = ESC;
- }
- break;
- case ESC_END:
- if(sl->esc){
- sl->esc = 0;
- c = END;
- }
- break;
- }
- sl->buf[sl->pos++] = c;
- return(0);
-}
-
int slip_user_read(int fd, void *buf, int len, struct slip_data *pri)
{
int i, n, size, start;
- n = net_read(fd, &pri->buf[pri->pos], sizeof(pri->buf) - pri->pos);
+ if(pri->more>0) {
+ i = 0;
+ while(i < pri->more) {
+ size = slip_unesc(pri->ibuf[i++],
+ pri->ibuf, &pri->pos, &pri->esc);
+ if(size){
+ memcpy(buf, pri->ibuf, size);
+ memmove(pri->ibuf, &pri->ibuf[i], pri->more-i);
+ pri->more=pri->more-i;
+ return(size);
+ }
+ }
+ pri->more=0;
+ }
+
+ n = net_read(fd, &pri->ibuf[pri->pos], sizeof(pri->ibuf) - pri->pos);
if(n <= 0) return(n);
start = pri->pos;
for(i = 0; i < n; i++){
- size = slip_unesc(pri, pri->buf[start + i]);
+ size = slip_unesc(pri->ibuf[start + i],
+ pri->ibuf, &pri->pos, &pri->esc);
if(size){
- memcpy(buf, pri->buf, size);
+ memcpy(buf, pri->ibuf, size);
+ memmove(pri->ibuf, &pri->ibuf[start+i+1], n-(i+1));
+ pri->more=n-(i+1);
return(size);
}
}
return(0);
}
-static int slip_esc(unsigned char *s, unsigned char *d, int len)
-{
- unsigned char *ptr = d;
- unsigned char c;
-
- /*
- * Send an initial END character to flush out any
- * data that may have accumulated in the receiver
- * due to line noise.
- */
-
- *ptr++ = END;
-
- /*
- * For each byte in the packet, send the appropriate
- * character sequence, according to the SLIP protocol.
- */
-
- while (len-- > 0) {
- switch(c = *s++) {
- case END:
- *ptr++ = ESC;
- *ptr++ = ESC_END;
- break;
- case ESC:
- *ptr++ = ESC;
- *ptr++ = ESC_ESC;
- break;
- default:
- *ptr++ = c;
- break;
- }
- }
- *ptr++ = END;
- return (ptr - d);
-}
-
int slip_user_write(int fd, void *buf, int len, struct slip_data *pri)
{
int actual, n;
- actual = slip_esc(buf, pri->buf, len);
- n = net_write(fd, pri->buf, actual);
+ actual = slip_esc(buf, pri->obuf, len);
+ n = net_write(fd, pri->obuf, actual);
if(n < 0) return(n);
else return(len);
}
diff --git a/arch/um/drivers/slirp.h b/arch/um/drivers/slirp.h
new file mode 100644
index 000000000000..04e407d1e44a
--- /dev/null
+++ b/arch/um/drivers/slirp.h
@@ -0,0 +1,51 @@
+#ifndef __UM_SLIRP_H
+#define __UM_SLIRP_H
+
+#define BUF_SIZE 1500
+ /* two bytes each for a (pathological) max packet of escaped chars + *
+ * terminating END char + initial END char */
+#define ENC_BUF_SIZE (2 * BUF_SIZE + 2)
+
+#define SLIRP_MAX_ARGS 100
+/*
+ * XXX this next definition is here because I don't understand why this
+ * initializer doesn't work in slirp_kern.c:
+ *
+ * argv : { init->argv[ 0 ... SLIRP_MAX_ARGS-1 ] },
+ *
+ * or why I can't typecast like this:
+ *
+ * argv : (char* [SLIRP_MAX_ARGS])(init->argv),
+ */
+struct arg_list_dummy_wrapper { char *argv[SLIRP_MAX_ARGS]; };
+
+struct slirp_data {
+ void *dev;
+ struct arg_list_dummy_wrapper argw;
+ int pid;
+ int slave;
+ char ibuf[ENC_BUF_SIZE];
+ char obuf[ENC_BUF_SIZE];
+ int more; /* more data: do not read fd until ibuf has been drained */
+ int pos;
+ int esc;
+};
+
+extern struct net_user_info slirp_user_info;
+
+extern int set_umn_addr(int fd, char *addr, char *ptp_addr);
+extern int slirp_user_read(int fd, void *buf, int len, struct slirp_data *pri);
+extern int slirp_user_write(int fd, void *buf, int len, struct slirp_data *pri);
+
+#endif
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only. This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff --git a/arch/um/drivers/slirp_kern.c b/arch/um/drivers/slirp_kern.c
new file mode 100644
index 000000000000..1a459dd94d76
--- /dev/null
+++ b/arch/um/drivers/slirp_kern.c
@@ -0,0 +1,132 @@
+#include "linux/kernel.h"
+#include "linux/stddef.h"
+#include "linux/init.h"
+#include "linux/netdevice.h"
+#include "linux/if_arp.h"
+#include "net_kern.h"
+#include "net_user.h"
+#include "kern.h"
+#include "slirp.h"
+
+struct slirp_init {
+ struct arg_list_dummy_wrapper argw; /* XXX should be simpler... */
+};
+
+void slirp_init(struct net_device *dev, void *data)
+{
+ struct uml_net_private *private;
+ struct slirp_data *spri;
+ struct slirp_init *init = data;
+ int i;
+
+ private = dev->priv;
+ spri = (struct slirp_data *) private->user;
+ *spri = ((struct slirp_data)
+ { argw : init->argw,
+ pid : -1,
+ slave : -1,
+ ibuf : { '\0' },
+ obuf : { '\0' },
+ pos : 0,
+ esc : 0,
+ dev : dev });
+
+ dev->init = NULL;
+ dev->hard_header_len = 0;
+ dev->addr_len = 4;
+ dev->type = ARPHRD_ETHER;
+ dev->tx_queue_len = 256;
+ dev->flags = IFF_NOARP;
+ printk("SLIRP backend - command line:");
+ for(i=0;spri->argw.argv[i]!=NULL;i++) {
+ printk(" '%s'",spri->argw.argv[i]);
+ }
+ printk("\n");
+}
+
+static unsigned short slirp_protocol(struct sk_buff *skbuff)
+{
+ return(htons(ETH_P_IP));
+}
+
+static int slirp_read(int fd, struct sk_buff **skb,
+ struct uml_net_private *lp)
+{
+ return(slirp_user_read(fd, (*skb)->mac.raw, (*skb)->dev->mtu,
+ (struct slirp_data *) &lp->user));
+}
+
+static int slirp_write(int fd, struct sk_buff **skb,
+ struct uml_net_private *lp)
+{
+ return(slirp_user_write(fd, (*skb)->data, (*skb)->len,
+ (struct slirp_data *) &lp->user));
+}
+
+struct net_kern_info slirp_kern_info = {
+ init: slirp_init,
+ protocol: slirp_protocol,
+ read: slirp_read,
+ write: slirp_write,
+};
+
+static int slirp_setup(char *str, char **mac_out, void *data)
+{
+ struct slirp_init *init = data;
+ int i=0;
+
+ *init = ((struct slirp_init)
+ { argw : { { "slirp", NULL } } });
+
+ str = split_if_spec(str, mac_out, NULL);
+
+ if(str == NULL) { /* no command line given after MAC addr */
+ return(1);
+ }
+
+ do {
+ if(i>=SLIRP_MAX_ARGS-1) {
+ printk("slirp_setup: truncating slirp arguments\n");
+ break;
+ }
+ init->argw.argv[i++] = str;
+ while(*str && *str!=',') {
+ if(*str=='_') *str=' ';
+ str++;
+ }
+ if(*str!=',')
+ break;
+ *str++='\0';
+ } while(1);
+ init->argw.argv[i]=NULL;
+ return(1);
+}
+
+static struct transport slirp_transport = {
+ list : LIST_HEAD_INIT(slirp_transport.list),
+ name : "slirp",
+ setup : slirp_setup,
+ user : &slirp_user_info,
+ kern : &slirp_kern_info,
+ private_size : sizeof(struct slirp_data),
+ setup_size : sizeof(struct slirp_init),
+};
+
+static int register_slirp(void)
+{
+ register_transport(&slirp_transport);
+ return(1);
+}
+
+__initcall(register_slirp);
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only. This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff --git a/arch/um/drivers/slirp_user.c b/arch/um/drivers/slirp_user.c
new file mode 100644
index 000000000000..bba76df0f33d
--- /dev/null
+++ b/arch/um/drivers/slirp_user.c
@@ -0,0 +1,202 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stddef.h>
+#include <sched.h>
+#include <string.h>
+#include <sys/fcntl.h>
+#include <sys/errno.h>
+#include <sys/wait.h>
+#include <sys/signal.h>
+#include "user_util.h"
+#include "kern_util.h"
+#include "user.h"
+#include "net_user.h"
+#include "slirp.h"
+#include "slip_proto.h"
+#include "helper.h"
+#include "os.h"
+
+void slirp_user_init(void *data, void *dev)
+{
+ struct slirp_data *pri = data;
+
+ pri->dev = dev;
+}
+
+struct slirp_pre_exec_data {
+ int stdin;
+ int stdout;
+};
+
+static void slirp_pre_exec(void *arg)
+{
+ struct slirp_pre_exec_data *data = arg;
+
+ if(data->stdin != -1) dup2(data->stdin, 0);
+ if(data->stdout != -1) dup2(data->stdout, 1);
+}
+
+static int slirp_tramp(char **argv, int fd)
+{
+ struct slirp_pre_exec_data pe_data;
+ int pid;
+
+ pe_data.stdin = fd;
+ pe_data.stdout = fd;
+ pid = run_helper(slirp_pre_exec, &pe_data, argv, NULL);
+
+ return(pid);
+}
+
+static int slirp_datachan(int *mfd, int *sfd)
+{
+ int fds[2], err;
+
+ err = os_pipe(fds, 1, 1);
+ if(err){
+ printk("slirp_datachan: Failed to open pipe, errno = %d\n",
+ -err);
+ return(err);
+ }
+
+ *mfd = fds[0];
+ *sfd = fds[1];
+ return(0);
+}
+
+static int slirp_open(void *data)
+{
+ struct slirp_data *pri = data;
+ int sfd, mfd, pid, err;
+
+ err = slirp_datachan(&mfd, &sfd);
+ if(err)
+ return(err);
+
+ pid = slirp_tramp(pri->argw.argv, sfd);
+
+ if(pid < 0){
+ printk("slirp_tramp failed - errno = %d\n", pid);
+ os_close_file(sfd);
+ os_close_file(mfd);
+ return(pid);
+ }
+
+ pri->slave = sfd;
+ pri->pos = 0;
+ pri->esc = 0;
+
+ pri->pid = pid;
+
+ return(mfd);
+}
+
+static void slirp_close(int fd, void *data)
+{
+ struct slirp_data *pri = data;
+ int status,err;
+
+ close(fd);
+ close(pri->slave);
+
+ pri->slave = -1;
+
+ if(pri->pid<1) {
+ printk("slirp_close: no child process to shut down\n");
+ return;
+ }
+
+#if 0
+ if(kill(pri->pid, SIGHUP)<0) {
+ printk("slirp_close: sending hangup to %d failed (%d)\n",
+ pri->pid, errno);
+ }
+#endif
+
+ err = waitpid(pri->pid, &status, WNOHANG);
+ if(err<0) {
+ printk("slirp_close: waitpid returned %d\n", errno);
+ return;
+ }
+
+ if(err==0) {
+ printk("slirp_close: process %d has not exited\n");
+ return;
+ }
+
+ pri->pid = -1;
+}
+
+int slirp_user_read(int fd, void *buf, int len, struct slirp_data *pri)
+{
+ int i, n, size, start;
+
+ if(pri->more>0) {
+ i = 0;
+ while(i < pri->more) {
+ size = slip_unesc(pri->ibuf[i++],
+ pri->ibuf,&pri->pos,&pri->esc);
+ if(size){
+ memcpy(buf, pri->ibuf, size);
+ memmove(pri->ibuf, &pri->ibuf[i], pri->more-i);
+ pri->more=pri->more-i;
+ return(size);
+ }
+ }
+ pri->more=0;
+ }
+
+ n = net_read(fd, &pri->ibuf[pri->pos], sizeof(pri->ibuf) - pri->pos);
+ if(n <= 0) return(n);
+
+ start = pri->pos;
+ for(i = 0; i < n; i++){
+ size = slip_unesc(pri->ibuf[start + i],
+ pri->ibuf,&pri->pos,&pri->esc);
+ if(size){
+ memcpy(buf, pri->ibuf, size);
+ memmove(pri->ibuf, &pri->ibuf[start+i+1], n-(i+1));
+ pri->more=n-(i+1);
+ return(size);
+ }
+ }
+ return(0);
+}
+
+int slirp_user_write(int fd, void *buf, int len, struct slirp_data *pri)
+{
+ int actual, n;
+
+ actual = slip_esc(buf, pri->obuf, len);
+ n = net_write(fd, pri->obuf, actual);
+ if(n < 0) return(n);
+ else return(len);
+}
+
+static int slirp_set_mtu(int mtu, void *data)
+{
+ return(mtu);
+}
+
+struct net_user_info slirp_user_info = {
+ init: slirp_user_init,
+ open: slirp_open,
+ close: slirp_close,
+ remove: NULL,
+ set_mtu: slirp_set_mtu,
+ add_address: NULL,
+ delete_address: NULL,
+ max_packet: BUF_SIZE
+};
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only. This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff --git a/arch/um/drivers/ssl.c b/arch/um/drivers/ssl.c
index c0cd826d9d8b..4f0b772a4f88 100644
--- a/arch/um/drivers/ssl.c
+++ b/arch/um/drivers/ssl.c
@@ -20,6 +20,7 @@
#include "kern.h"
#include "init.h"
#include "irq_user.h"
+#include "mconsole_kern.h"
#include "2_5compat.h"
static int ssl_version = 1;
@@ -47,6 +48,10 @@ static struct chan_opts opts = {
in_kernel : 1,
};
+static int ssl_config(char *str);
+static int ssl_get_config(char *dev, char *str, int size, char **error_out);
+static int ssl_remove(char *str);
+
static struct line_driver driver = {
name : "UML serial line",
devfs_name : "tts/%d",
@@ -60,6 +65,12 @@ static struct line_driver driver = {
write_irq_name : "ssl-write",
symlink_from : "serial",
symlink_to : "tts",
+ mc : {
+ name : "ssl",
+ config : ssl_config,
+ get_config : ssl_get_config,
+ remove : ssl_remove,
+ },
};
/* The array is initialized by line_init, which is an initcall. The
@@ -70,6 +81,25 @@ static struct line serial_lines[NR_PORTS] =
static struct lines lines = LINES_INIT(NR_PORTS);
+static int ssl_config(char *str)
+{
+ return(line_config(serial_lines,
+ sizeof(serial_lines)/sizeof(serial_lines[0]), str));
+}
+
+static int ssl_get_config(char *dev, char *str, int size, char **error_out)
+{
+ return(line_get_config(dev, serial_lines,
+ sizeof(serial_lines)/sizeof(serial_lines[0]),
+ str, size, error_out));
+}
+
+static int ssl_remove(char *str)
+{
+ return(line_remove(serial_lines,
+ sizeof(serial_lines)/sizeof(serial_lines[0]), str));
+}
+
int ssl_open(struct tty_struct *tty, struct file *filp)
{
return(line_open(serial_lines, tty, &opts));
@@ -83,12 +113,12 @@ static void ssl_close(struct tty_struct *tty, struct file * filp)
static int ssl_write(struct tty_struct * tty, int from_user,
const unsigned char *buf, int count)
{
- return(line_write(serial_lines, tty, buf, count));
+ return(line_write(serial_lines, tty, from_user, buf, count));
}
static void ssl_put_char(struct tty_struct *tty, unsigned char ch)
{
- line_write(serial_lines, tty, &ch, sizeof(ch));
+ line_write(serial_lines, tty, 0, &ch, sizeof(ch));
}
static void ssl_flush_chars(struct tty_struct *tty)
@@ -207,7 +237,7 @@ __initcall(ssl_init);
static int ssl_chan_setup(char *str)
{
line_setup(serial_lines, sizeof(serial_lines)/sizeof(serial_lines[0]),
- str);
+ str, 1);
return(1);
}
diff --git a/arch/um/drivers/stdio_console.c b/arch/um/drivers/stdio_console.c
index 4803c3e071b0..3844a7188508 100644
--- a/arch/um/drivers/stdio_console.c
+++ b/arch/um/drivers/stdio_console.c
@@ -27,6 +27,7 @@
#include "user_util.h"
#include "kern_util.h"
#include "irq_user.h"
+#include "mconsole_kern.h"
#include "init.h"
#include "2_5compat.h"
@@ -41,6 +42,7 @@ static struct tty_driver console_driver;
static int console_refcount = 0;
static struct chan_ops init_console_ops = {
+ type: "you shouldn't see this",
init : NULL,
open : NULL,
close : NULL,
@@ -78,6 +80,10 @@ static struct chan_opts opts = {
in_kernel : 1,
};
+static int con_config(char *str);
+static int con_get_config(char *dev, char *str, int size, char **error_out);
+static int con_remove(char *str);
+
static struct line_driver driver = {
name : "UML console",
devfs_name : "vc/%d",
@@ -91,6 +97,12 @@ static struct line_driver driver = {
write_irq_name : "console-write",
symlink_from : "ttys",
symlink_to : "vc",
+ mc : {
+ name : "con",
+ config : con_config,
+ get_config : con_get_config,
+ remove : con_remove,
+ },
};
static struct lines console_lines = LINES_INIT(MAX_TTYS);
@@ -102,6 +114,22 @@ struct line vts[MAX_TTYS] = { LINE_INIT(CONFIG_CON_ZERO_CHAN, &driver),
[ 1 ... MAX_TTYS - 1 ] =
LINE_INIT(CONFIG_CON_CHAN, &driver) };
+static int con_config(char *str)
+{
+ return(line_config(vts, sizeof(vts)/sizeof(vts[0]), str));
+}
+
+static int con_get_config(char *dev, char *str, int size, char **error_out)
+{
+ return(line_get_config(dev, vts, sizeof(vts)/sizeof(vts[0]), str,
+ size, error_out));
+}
+
+static int con_remove(char *str)
+{
+ return(line_remove(vts, sizeof(vts)/sizeof(vts[0]), str));
+}
+
static int open_console(struct tty_struct *tty)
{
return(line_open(vts, tty, &opts));
@@ -120,7 +148,7 @@ static void con_close(struct tty_struct *tty, struct file *filp)
static int con_write(struct tty_struct *tty, int from_user,
const unsigned char *buf, int count)
{
- return(line_write(vts, tty, buf, count));
+ return(line_write(vts, tty, from_user, buf, count));
}
static void set_termios(struct tty_struct *tty, struct termios * old)
@@ -195,7 +223,7 @@ void stdio_console_init(void)
static int console_chan_setup(char *str)
{
- line_setup(vts, sizeof(vts)/sizeof(vts[0]), str);
+ line_setup(vts, sizeof(vts)/sizeof(vts[0]), str, 1);
return(1);
}
diff --git a/arch/um/drivers/tty.c b/arch/um/drivers/tty.c
index 75b4b93102b0..438e72268ef6 100644
--- a/arch/um/drivers/tty.c
+++ b/arch/um/drivers/tty.c
@@ -30,14 +30,15 @@ void *tty_chan_init(char *str, int device, struct chan_opts *opts)
}
str++;
- if((data = um_kmalloc(sizeof(*data))) == NULL) return(NULL);
+ if((data = um_kmalloc(sizeof(*data))) == NULL)
+ return(NULL);
*data = ((struct tty_chan) { dev : str,
raw : opts->raw });
return(data);
}
-int tty_open(int input, int output, int primary, void *d)
+int tty_open(int input, int output, int primary, void *d, char **dev_out)
{
struct tty_chan *data = d;
int fd;
@@ -48,6 +49,8 @@ int tty_open(int input, int output, int primary, void *d)
tcgetattr(fd, &data->tt);
raw(fd, 0);
}
+
+ *dev_out = data->dev;
return(fd);
}
@@ -59,6 +62,7 @@ int tty_console_write(int fd, const char *buf, int n, void *d)
}
struct chan_ops tty_ops = {
+ type: "tty",
init: tty_chan_init,
open: tty_open,
close: generic_close,
diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c
index 93228f048940..2d9dfba302e8 100644
--- a/arch/um/drivers/ubd_kern.c
+++ b/arch/um/drivers/ubd_kern.c
@@ -218,7 +218,7 @@ static int ubd_setup_common(char *str, int *index_out)
return(0);
}
major = simple_strtoul(str, &end, 0);
- if(*end != '\0'){
+ if((*end != '\0') || (end == str)){
printk(KERN_ERR
"ubd_setup : didn't parse major number\n");
return(1);
@@ -520,7 +520,10 @@ static int ubd_add(int n)
struct ubd *dev = &ubd_dev[n];
int err;
- if (!dev->file || dev->is_dir)
+ if(dev->is_dir)
+ return(-EISDIR);
+
+ if (!dev->file)
return(-ENODEV);
if (ubd_open_dev(dev))
@@ -574,6 +577,44 @@ static int ubd_config(char *str)
return(err);
}
+static int ubd_get_config(char *dev, char *str, int size, char **error_out)
+{
+ struct ubd *ubd;
+ char *end;
+ int major, n = 0;
+
+ major = simple_strtoul(dev, &end, 0);
+ if((*end != '\0') || (end == dev)){
+ *error_out = "ubd_get_config : didn't parse major number";
+ return(-1);
+ }
+
+ if((major >= MAX_DEV) || (major < 0)){
+ *error_out = "ubd_get_config : major number out of range";
+ return(-1);
+ }
+
+ ubd = &ubd_dev[major];
+ spin_lock(&ubd_lock);
+
+ if(ubd->file == NULL){
+ CONFIG_CHUNK(str, size, n, "", 1);
+ goto out;
+ }
+
+ CONFIG_CHUNK(str, size, n, ubd->file, 0);
+
+ if(ubd->cow.file != NULL){
+ CONFIG_CHUNK(str, size, n, ",", 0);
+ CONFIG_CHUNK(str, size, n, ubd->cow.file, 1);
+ }
+ else CONFIG_CHUNK(str, size, n, "", 1);
+
+ out:
+ spin_unlock(&ubd_lock);
+ return(n);
+}
+
static int ubd_remove(char *str)
{
struct ubd *dev;
@@ -583,7 +624,7 @@ static int ubd_remove(char *str)
return(err); /* it should be a number 0-7/a-h */
n = *str - '0';
- if(n > MAX_DEV)
+ if(n >= MAX_DEV)
return(err);
dev = &ubd_dev[n];
@@ -620,6 +661,7 @@ static int ubd_remove(char *str)
static struct mc_device ubd_mc = {
.name = "ubd",
.config = ubd_config,
+ .get_config = ubd_get_config,
.remove = ubd_remove,
};
diff --git a/arch/um/drivers/ubd_user.c b/arch/um/drivers/ubd_user.c
index 8a4b6f52888c..93b6f3e90c22 100644
--- a/arch/um/drivers/ubd_user.c
+++ b/arch/um/drivers/ubd_user.c
@@ -473,6 +473,8 @@ void do_io(struct io_thread_req *req)
&req->sector_mask) == bit))
end++;
+ if(end != nsectors)
+ printk("end != nsectors\n");
off = req->offset + req->offsets[bit] +
start * req->sectorsize;
len = (end - start) * req->sectorsize;
diff --git a/arch/um/drivers/xterm.c b/arch/um/drivers/xterm.c
index e7b4ab83c8f7..7e351c8012ad 100644
--- a/arch/um/drivers/xterm.c
+++ b/arch/um/drivers/xterm.c
@@ -83,7 +83,7 @@ __uml_setup("xterm=", xterm_setup,
" are 'xterm=gnome-terminal,-t,-x'.\n\n"
);
-int xterm_open(int input, int output, int primary, void *d)
+int xterm_open(int input, int output, int primary, void *d, char **dev_out)
{
struct xterm_chan *data = d;
unsigned long stack;
@@ -93,6 +93,9 @@ int xterm_open(int input, int output, int primary, void *d)
"/usr/lib/uml/port-helper", "-uml-socket",
file, NULL };
+ if(access(argv[4], X_OK))
+ argv[4] = "port-helper";
+
fd = mkstemp(file);
if(fd < 0){
printk("xterm_open : mkstemp failed, errno = %d\n", errno);
@@ -141,6 +144,7 @@ int xterm_open(int input, int output, int primary, void *d)
if(data->raw) raw(new, 0);
data->pid = pid;
+ *dev_out = NULL;
return(new);
}
@@ -168,6 +172,7 @@ int xterm_console_write(int fd, const char *buf, int n, void *d)
}
struct chan_ops xterm_ops = {
+ type: "xterm",
init: xterm_init,
open: xterm_open,
close: xterm_close,
diff --git a/arch/um/drivers/xterm_kern.c b/arch/um/drivers/xterm_kern.c
index 28b2835bcb7c..c2308894a81e 100644
--- a/arch/um/drivers/xterm_kern.c
+++ b/arch/um/drivers/xterm_kern.c
@@ -22,11 +22,13 @@ struct xterm_wait {
static void xterm_interrupt(int irq, void *data, struct pt_regs *regs)
{
struct xterm_wait *xterm = data;
+ int fd;
- xterm->new_fd = os_rcv_fd(xterm->fd, &xterm->pid);
- if(xterm->new_fd == -EAGAIN)
+ fd = os_rcv_fd(xterm->fd, &xterm->pid);
+ if(fd == -EAGAIN)
return;
+ xterm->new_fd = fd;
up(&xterm->sem);
}
diff --git a/arch/um/include/chan_kern.h b/arch/um/include/chan_kern.h
index 8c2bb85c9edf..d2cd02a03c61 100644
--- a/arch/um/include/chan_kern.h
+++ b/arch/um/include/chan_kern.h
@@ -12,6 +12,7 @@
struct chan {
struct list_head list;
+ char *dev;
unsigned int primary:1;
unsigned int input:1;
unsigned int output:1;
@@ -38,6 +39,8 @@ extern int chan_window_size(struct list_head *chans,
unsigned short *rows_out,
unsigned short *cols_out);
extern int chan_out_fd(struct list_head *chans);
+extern int chan_config_string(struct list_head *chans, char *str, int size,
+ char **error_out);
#endif
diff --git a/arch/um/include/chan_user.h b/arch/um/include/chan_user.h
index 639ca8d6121a..9414c1a44c6d 100644
--- a/arch/um/include/chan_user.h
+++ b/arch/um/include/chan_user.h
@@ -19,8 +19,9 @@ struct chan_opts {
enum chan_init_pri { INIT_STATIC, INIT_ALL, INIT_ONE };
struct chan_ops {
+ char *type;
void *(*init)(char *, int, struct chan_opts *);
- int (*open)(int, int, int, void *);
+ int (*open)(int, int, int, void *, char **);
void (*close)(int, void *);
int (*read)(int, char *, void *);
int (*write)(int, const char *, int, void *);
@@ -43,7 +44,6 @@ extern void generic_free(void *data);
extern void register_winch(int fd, void *device_data);
extern void register_winch_irq(int fd, int tty_fd, int pid, void *line);
-extern void setup_tracer_winch(void);
#define __channel_help(fn, prefix) \
__uml_help(fn, prefix "[0-9]*=<channel description>\n" \
diff --git a/arch/um/include/choose-mode.h b/arch/um/include/choose-mode.h
new file mode 100644
index 000000000000..55548984bd85
--- /dev/null
+++ b/arch/um/include/choose-mode.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#ifndef __CHOOSE_MODE_H__
+#define __CHOOSE_MODE_H__
+
+#include "uml-config.h"
+
+#if defined(CONFIG_MODE_TT) && defined(CONFIG_MODE_SKAS)
+#define CHOOSE_MODE(tt, skas) (mode_tt ? (tt) : (skas))
+
+#elif defined(CONFIG_MODE_SKAS)
+#define CHOOSE_MODE(tt, skas) (skas)
+
+#elif defined(CONFIG_MODE_TT)
+#define CHOOSE_MODE(tt, skas) (tt)
+#endif
+
+#define CHOOSE_MODE_PROC(tt, skas, args...) \
+ CHOOSE_MODE(tt(args), skas(args))
+
+#endif
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only. This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff --git a/arch/um/include/frame.h b/arch/um/include/frame.h
index 9df95a5f00a1..b4e12946f54f 100644
--- a/arch/um/include/frame.h
+++ b/arch/um/include/frame.h
@@ -8,34 +8,34 @@
#include "sysdep/frame.h"
-struct sc_frame {
+struct frame_common {
void *data;
int len;
int sig_index;
- int sc_index;
int sr_index;
int sr_relative;
int sp_index;
+};
+
+struct sc_frame {
+ struct frame_common common;
+ int sc_index;
struct arch_frame_data arch;
};
extern struct sc_frame signal_frame_sc;
+extern struct sc_frame signal_frame_sc_sr;
+
struct si_frame {
- void *data;
- int len;
- int sig_index;
+ struct frame_common common;
int sip_index;
int si_index;
- int sr_index;
- int sr_relative;
- int sp_index;
};
extern struct si_frame signal_frame_si;
extern void capture_signal_stack(void);
-extern void set_sc_ip_sp(void *sc_ptr, unsigned long ip, unsigned long sp);
#endif
diff --git a/arch/um/include/kern.h b/arch/um/include/kern.h
index 09eae635a15e..3e3aed19f54c 100644
--- a/arch/um/include/kern.h
+++ b/arch/um/include/kern.h
@@ -25,7 +25,6 @@ extern void *sbrk(int increment);
extern void *malloc(int size);
extern void perror(char *err);
extern int kill(int pid, int sig);
-extern int getpid(void);
extern int getuid(void);
extern int pause(void);
extern int write(int, const void *, int);
@@ -34,6 +33,7 @@ extern int close(int);
extern int read(unsigned int, char *, int);
extern int pipe(int *);
extern int sched_yield(void);
+extern int ptrace(int op, int pid, long addr, long data);
#endif
/*
diff --git a/arch/um/include/kern_util.h b/arch/um/include/kern_util.h
index 076b94d75765..8bef1a8a6153 100644
--- a/arch/um/include/kern_util.h
+++ b/arch/um/include/kern_util.h
@@ -15,23 +15,26 @@ extern char *gdb_init;
extern int kmalloc_ok;
extern int timer_irq_inited;
extern int jail;
+extern int nsyscalls;
+
extern struct task_struct *idle_threads[NR_CPUS];
-#define ROUND_DOWN(addr) ((void *)(((unsigned long) addr) & PAGE_MASK))
-#define ROUND_UP(addr) ROUND_DOWN(((unsigned long) addr) + PAGE_SIZE - 1)
+#define UML_ROUND_DOWN(addr) ((void *)(((unsigned long) addr) & PAGE_MASK))
+#define UML_ROUND_UP(addr) \
+ UML_ROUND_DOWN(((unsigned long) addr) + PAGE_SIZE - 1)
extern int kernel_fork(unsigned long flags, int (*fn)(void *), void * arg);
extern unsigned long stack_sp(unsigned long page);
extern int kernel_thread_proc(void *data);
extern void syscall_segv(int sig);
extern int current_pid(void);
-extern void set_init_pid(int pid);
extern unsigned long alloc_stack(int order, int atomic);
extern int do_signal(int error);
extern int is_stack_fault(unsigned long sp);
extern unsigned long segv(unsigned long address, unsigned long ip,
- int is_write, int is_user, void *sc_ptr);
-extern int set_user_mode(void *task);
+ int is_write, int is_user, void *sc);
+extern int handle_page_fault(unsigned long address, unsigned long ip,
+ int is_write, int is_user, int *code_out);
extern void syscall_ready(void);
extern void set_tracing(void *t, int tracing);
extern int is_tracing(void *task);
@@ -40,7 +43,6 @@ extern void kern_finish_exec(void *task, int new_pid, unsigned long stack);
extern int page_size(void);
extern int page_mask(void);
extern int need_finish_fork(void);
-extern int do_proc_op(void *t, int proc_id);
extern void free_stack(unsigned long stack, int order);
extern void add_input_request(int op, void (*proc)(int), void *arg);
extern int sys_execve(char *file, char **argv, char **env);
@@ -57,7 +59,6 @@ extern int next_trap_index(int max);
extern void default_idle(void);
extern void finish_fork(void);
extern void paging_init(void);
-extern unsigned long um_virt_to_phys(void *t, unsigned long addr);
extern void init_flush_vm(void);
extern void *syscall_sp(void *t);
extern void syscall_trace(void);
@@ -68,35 +69,28 @@ extern int external_pid(void *t);
extern int pid_to_processor_id(int pid);
extern void boot_timer_handler(int sig);
extern void interrupt_end(void);
-extern void tracing_reboot(void);
-extern void tracing_halt(void);
-extern void tracing_cb(void (*proc)(void *), void *arg);
+extern void initial_thread_cb(void (*proc)(void *), void *arg);
extern int debugger_signal(int status, int pid);
extern void debugger_parent_signal(int status, int pid);
extern void child_signal(int pid, int status);
extern int init_ptrace_proxy(int idle_pid, int startup, int stop);
extern int init_parent_proxy(int pid);
+extern int singlestepping(void *t);
extern void check_stack_overflow(void *ptr);
extern void relay_signal(int sig, struct uml_pt_regs *regs);
-extern int singlestepping(void *t);
-extern void clear_singlestep(void *t);
extern void not_implemented(void);
extern int user_context(unsigned long sp);
extern void timer_irq(struct uml_pt_regs *regs);
extern void unprotect_stack(unsigned long stack);
extern void do_uml_exitcalls(void);
extern int attach_debugger(int idle_pid, int pid, int stop);
-extern void *round_up(unsigned long addr);
-extern void *round_down(unsigned long addr);
extern void bad_segv(unsigned long address, unsigned long ip, int is_write);
extern int config_gdb(char *str);
extern int remove_gdb(void);
extern char *uml_strdup(char *string);
extern void unprotect_kernel_mem(void);
extern void protect_kernel_mem(void);
-extern unsigned long get_kmem_end(void);
extern void set_kmem_end(unsigned long);
-extern void set_task_sizes(int arg);
extern void uml_cleanup(void);
extern int pid_to_processor_id(int pid);
extern void set_current(void *t);
@@ -107,7 +101,6 @@ extern void *get_init_task(void);
extern int clear_user_proc(void *buf, int size);
extern int copy_to_user_proc(void *to, void *from, int size);
extern int copy_from_user_proc(void *to, void *from, int size);
-extern void set_thread_sc(void *sc);
extern void bus_handler(int sig, struct uml_pt_regs *regs);
extern long execute_syscall(void *r);
extern int smp_sigio_handler(void);
@@ -116,7 +109,6 @@ extern struct task_struct *get_task(int pid, int require);
extern void machine_halt(void);
extern int is_syscall(unsigned long addr);
extern void arch_switch(void);
-extern int is_valid_pid(int pid);
extern void free_irq(unsigned int, void *);
extern int um_in_interrupt(void);
extern int cpu(void);
diff --git a/arch/um/include/line.h b/arch/um/include/line.h
index 4d45c270a80e..8bad9c56c66e 100644
--- a/arch/um/include/line.h
+++ b/arch/um/include/line.h
@@ -11,6 +11,7 @@
#include "linux/tty.h"
#include "asm/semaphore.h"
#include "chan_user.h"
+#include "mconsole_kern.h"
struct line_driver {
char *name;
@@ -25,6 +26,7 @@ struct line_driver {
char *write_irq_name;
char *symlink_from;
char *symlink_to;
+ struct mc_device mc;
};
struct line {
@@ -70,8 +72,9 @@ extern void line_write_interrupt(int irq, void *data, struct pt_regs *unused);
extern void line_close(struct line *lines, struct tty_struct *tty);
extern int line_open(struct line *lines, struct tty_struct *tty,
struct chan_opts *opts);
-extern void line_setup(struct line *lines, int num, char *init);
-extern int line_write(struct line *line, struct tty_struct *tty,
+extern int line_setup(struct line *lines, int num, char *init,
+ int all_allowed);
+extern int line_write(struct line *line, struct tty_struct *tty, int from_user,
const char *buf, int len);
extern int line_write_room(struct tty_struct *tty);
extern char *add_xterm_umid(char *base);
@@ -84,6 +87,10 @@ extern void line_register_devfs(struct lines *set,
int nlines);
extern void lines_init(struct line *lines, int nlines);
extern void close_lines(struct line *lines, int nlines);
+extern int line_config(struct line *lines, int num, char *str);
+extern int line_remove(struct line *lines, int num, char *str);
+extern int line_get_config(char *dev, struct line *lines, int num, char *str,
+ int size, char **error_out);
#endif
diff --git a/arch/um/include/mconsole_kern.h b/arch/um/include/mconsole_kern.h
index 03c6d1734a28..61c274fcee5d 100644
--- a/arch/um/include/mconsole_kern.h
+++ b/arch/um/include/mconsole_kern.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2001 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
* Licensed under the GPL
*/
@@ -19,9 +19,23 @@ struct mc_device {
struct list_head list;
char *name;
int (*config)(char *);
+ int (*get_config)(char *, char *, int, char **);
int (*remove)(char *);
};
+#define CONFIG_CHUNK(str, size, current, chunk, end) \
+do { \
+ current += strlen(chunk); \
+ if(current >= size) \
+ str = NULL; \
+ if(str != NULL){ \
+ strcpy(str, chunk); \
+ str += strlen(chunk); \
+ } \
+ if(end) \
+ current++; \
+} while(0)
+
#ifdef CONFIG_MCONSOLE
extern void mconsole_register_dev(struct mc_device *new);
diff --git a/arch/um/include/mem.h b/arch/um/include/mem.h
index e7835b541196..bad6b30b8f7d 100644
--- a/arch/um/include/mem.h
+++ b/arch/um/include/mem.h
@@ -13,6 +13,7 @@ struct vm_reserved {
};
extern void set_usable_vm(unsigned long start, unsigned long end);
+extern void set_kmem_end(unsigned long new);
#endif
diff --git a/arch/um/include/mem_user.h b/arch/um/include/mem_user.h
index 4a3e68d56a5a..d80ac354bf28 100644
--- a/arch/um/include/mem_user.h
+++ b/arch/um/include/mem_user.h
@@ -54,11 +54,6 @@ extern int create_mem_file(unsigned long len);
extern void setup_range(int fd, char *driver, unsigned long start,
unsigned long pfn, unsigned long total, int need_vm,
struct mem_region *region, void *reserved);
-extern void map(unsigned long virt, unsigned long p, unsigned long len,
- int r, int w, int x);
-extern int unmap(void *addr, int len);
-extern int protect(unsigned long addr, unsigned long len, int r, int w,
- int x, int must_succeed);
extern void setup_memory(void *entry);
extern unsigned long find_iomem(char *driver, unsigned long *len_out);
extern int init_maps(struct mem_region *region);
@@ -68,10 +63,15 @@ extern unsigned long get_vm(unsigned long len);
extern void setup_physmem(unsigned long start, unsigned long usable,
unsigned long len);
extern int setup_region(struct mem_region *region, void *entry);
-extern void add_iomem(char *name, int fd, int size);
+extern void add_iomem(char *name, int fd, unsigned long size);
extern struct mem_region *phys_region(unsigned long phys);
extern unsigned long phys_offset(unsigned long phys);
extern void unmap_physmem(void);
+extern int map_memory(unsigned long virt, unsigned long phys,
+ unsigned long len, int r, int w, int x);
+extern int protect_memory(unsigned long addr, unsigned long len,
+ int r, int w, int x, int must_succeed);
+extern unsigned long get_kmem_end(void);
#endif
diff --git a/arch/um/include/mode.h b/arch/um/include/mode.h
new file mode 100644
index 000000000000..ba7f6ff04121
--- /dev/null
+++ b/arch/um/include/mode.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#ifndef __MODE_H__
+#define __MODE_H__
+
+#include "uml-config.h"
+
+#ifdef CONFIG_MODE_TT
+#include "../kernel/tt/include/mode.h"
+#endif
+
+#ifdef CONFIG_MODE_SKAS
+#include "../kernel/skas/include/mode.h"
+#endif
+
+#endif
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only. This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff --git a/arch/um/include/mode_kern.h b/arch/um/include/mode_kern.h
new file mode 100644
index 000000000000..562174bf48a0
--- /dev/null
+++ b/arch/um/include/mode_kern.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#ifndef __MODE_KERN_H__
+#define __MODE_KERN_H__
+
+#include "linux/config.h"
+
+#ifdef CONFIG_MODE_TT
+#include "../kernel/tt/include/mode_kern.h"
+#endif
+
+#ifdef CONFIG_MODE_SKAS
+#include "../kernel/skas/include/mode_kern.h"
+#endif
+
+#endif
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only. This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff --git a/arch/um/include/net_kern.h b/arch/um/include/net_kern.h
index 22d43acb78f1..de793e9bf438 100644
--- a/arch/um/include/net_kern.h
+++ b/arch/um/include/net_kern.h
@@ -1,3 +1,8 @@
+/*
+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
#ifndef __UM_NET_KERN_H
#define __UM_NET_KERN_H
diff --git a/arch/um/include/net_user.h b/arch/um/include/net_user.h
index 01867cae92e2..36807b796e9f 100644
--- a/arch/um/include/net_user.h
+++ b/arch/um/include/net_user.h
@@ -1,3 +1,8 @@
+/*
+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
#ifndef __UM_NET_USER_H__
#define __UM_NET_USER_H__
diff --git a/arch/um/include/os.h b/arch/um/include/os.h
index 1c1e3a8b5eb6..524a60875d7b 100644
--- a/arch/um/include/os.h
+++ b/arch/um/include/os.h
@@ -103,10 +103,16 @@ extern int os_write_file(int fd, char *buf, int count);
extern unsigned long os_process_pc(int pid);
extern int os_process_parent(int pid);
extern void os_stop_process(int pid);
-extern void os_kill_process(int pid);
+extern void os_kill_process(int pid, int reap_child);
extern void os_usr1_process(int pid);
extern int os_getpid(void);
+extern int os_map_memory(void *virt, int fd, unsigned long off,
+ unsigned long len, int r, int w, int x);
+extern int os_protect_memory(void *addr, unsigned long len,
+ int r, int w, int x);
+extern int os_unmap_memory(void *addr, int len);
+
#endif
/*
diff --git a/arch/um/include/sigcontext.h b/arch/um/include/sigcontext.h
index 1d2b195bc5f8..59816ca7a8df 100644
--- a/arch/um/include/sigcontext.h
+++ b/arch/um/include/sigcontext.h
@@ -9,8 +9,6 @@
#include "sysdep/sigcontext.h"
extern int sc_size(void *data);
-extern int copy_sc_to_user(void *to_ptr, void *from_ptr, void *data);
-extern int copy_sc_from_user(void *to_ptr, void *from_ptr, void *data);
extern void sc_to_sc(void *to_ptr, void *from_ptr);
#endif
diff --git a/arch/um/include/syscall_user.h b/arch/um/include/syscall_user.h
index e430752cb7ec..bc7be6293702 100644
--- a/arch/um/include/syscall_user.h
+++ b/arch/um/include/syscall_user.h
@@ -1,16 +1,13 @@
/*
- * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
* Licensed under the GPL
*/
-#ifndef __SYSCALL_USER_H__
-#define __SYSCALL_USER_H__
+#ifndef __SYSCALL_USER_H
+#define __SYSCALL_USER_H
-#include <asm/sigcontext.h>
-
-extern void syscall_handler(int sig, struct uml_pt_regs *regs);
-extern void exit_kernel(int pid, void *task);
-extern int do_syscall(void *task, int pid);
+extern int record_syscall_start(int syscall);
+extern void record_syscall_end(int index, int result);
#endif
diff --git a/arch/um/include/sysdep-i386/checksum.h b/arch/um/include/sysdep-i386/checksum.h
new file mode 100644
index 000000000000..c77e434d61a9
--- /dev/null
+++ b/arch/um/include/sysdep-i386/checksum.h
@@ -0,0 +1,217 @@
+/*
+ * Licensed under the GPL
+ */
+
+#ifndef __UM_SYSDEP_CHECKSUM_H
+#define __UM_SYSDEP_CHECKSUM_H
+
+#include "linux/string.h"
+
+/*
+ * computes the checksum of a memory block at buff, length len,
+ * and adds in "sum" (32-bit)
+ *
+ * returns a 32-bit number suitable for feeding into itself
+ * or csum_tcpudp_magic
+ *
+ * this function must be called with even lengths, except
+ * for the last fragment, which may be odd
+ *
+ * it's best to have buff aligned on a 32-bit boundary
+ */
+unsigned int csum_partial(const unsigned char * buff, int len,
+ unsigned int sum);
+
+/*
+ * the same as csum_partial, but copies from src while it
+ * checksums, and handles user-space pointer exceptions correctly, when needed.
+ *
+ * here even more important to align src and dst on a 32-bit (or even
+ * better 64-bit) boundary
+ */
+
+unsigned int csum_partial_copy_to(const char *src, char *dst, int len,
+ int sum, int *err_ptr);
+unsigned int csum_partial_copy_from(const char *src, char *dst, int len,
+ int sum, int *err_ptr);
+
+/*
+ * Note: when you get a NULL pointer exception here this means someone
+ * passed in an incorrect kernel address to one of these functions.
+ *
+ * If you use these functions directly please don't forget the
+ * verify_area().
+ */
+
+static __inline__
+unsigned int csum_partial_copy_nocheck(const char *src, char *dst,
+ int len, int sum)
+{
+ memcpy(dst, src, len);
+ return(csum_partial(dst, len, sum));
+}
+
+static __inline__
+unsigned int csum_partial_copy_from_user(const char *src, char *dst,
+ int len, int sum, int *err_ptr)
+{
+ return csum_partial_copy_from(src, dst, len, sum, err_ptr);
+}
+
+/*
+ * These are the old (and unsafe) way of doing checksums, a warning message
+ * will be printed if they are used and an exeption occurs.
+ *
+ * these functions should go away after some time.
+ */
+
+#define csum_partial_copy_fromuser csum_partial_copy_from_user
+unsigned int csum_partial_copy( const char *src, char *dst, int len, int sum);
+
+/*
+ * This is a version of ip_compute_csum() optimized for IP headers,
+ * which always checksum on 4 octet boundaries.
+ *
+ * By Jorge Cwik <jorge@laser.satlink.net>, adapted for linux by
+ * Arnt Gulbrandsen.
+ */
+static inline unsigned short ip_fast_csum(unsigned char * iph,
+ unsigned int ihl)
+{
+ unsigned int sum;
+
+ __asm__ __volatile__(
+ "movl (%1), %0 ;\n"
+ "subl $4, %2 ;\n"
+ "jbe 2f ;\n"
+ "addl 4(%1), %0 ;\n"
+ "adcl 8(%1), %0 ;\n"
+ "adcl 12(%1), %0 ;\n"
+"1: adcl 16(%1), %0 ;\n"
+ "lea 4(%1), %1 ;\n"
+ "decl %2 ;\n"
+ "jne 1b ;\n"
+ "adcl $0, %0 ;\n"
+ "movl %0, %2 ;\n"
+ "shrl $16, %0 ;\n"
+ "addw %w2, %w0 ;\n"
+ "adcl $0, %0 ;\n"
+ "notl %0 ;\n"
+"2: ;\n"
+ /* Since the input registers which are loaded with iph and ipl
+ are modified, we must also specify them as outputs, or gcc
+ will assume they contain their original values. */
+ : "=r" (sum), "=r" (iph), "=r" (ihl)
+ : "1" (iph), "2" (ihl));
+ return(sum);
+}
+
+/*
+ * Fold a partial checksum
+ */
+
+static inline unsigned int csum_fold(unsigned int sum)
+{
+ __asm__(
+ "addl %1, %0 ;\n"
+ "adcl $0xffff, %0 ;\n"
+ : "=r" (sum)
+ : "r" (sum << 16), "0" (sum & 0xffff0000)
+ );
+ return (~sum) >> 16;
+}
+
+static inline unsigned long csum_tcpudp_nofold(unsigned long saddr,
+ unsigned long daddr,
+ unsigned short len,
+ unsigned short proto,
+ unsigned int sum)
+{
+ __asm__(
+ "addl %1, %0 ;\n"
+ "adcl %2, %0 ;\n"
+ "adcl %3, %0 ;\n"
+ "adcl $0, %0 ;\n"
+ : "=r" (sum)
+ : "g" (daddr), "g"(saddr), "g"((ntohs(len)<<16)+proto*256), "0"(sum));
+ return sum;
+}
+
+/*
+ * computes the checksum of the TCP/UDP pseudo-header
+ * returns a 16-bit checksum, already complemented
+ */
+static inline unsigned short int csum_tcpudp_magic(unsigned long saddr,
+ unsigned long daddr,
+ unsigned short len,
+ unsigned short proto,
+ unsigned int sum)
+{
+ return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum));
+}
+
+/*
+ * this routine is used for miscellaneous IP-like checksums, mainly
+ * in icmp.c
+ */
+
+static inline unsigned short ip_compute_csum(unsigned char * buff, int len)
+{
+ return csum_fold (csum_partial(buff, len, 0));
+}
+
+#define _HAVE_ARCH_IPV6_CSUM
+static __inline__ unsigned short int csum_ipv6_magic(struct in6_addr *saddr,
+ struct in6_addr *daddr,
+ __u32 len,
+ unsigned short proto,
+ unsigned int sum)
+{
+ __asm__(
+ "addl 0(%1), %0 ;\n"
+ "adcl 4(%1), %0 ;\n"
+ "adcl 8(%1), %0 ;\n"
+ "adcl 12(%1), %0 ;\n"
+ "adcl 0(%2), %0 ;\n"
+ "adcl 4(%2), %0 ;\n"
+ "adcl 8(%2), %0 ;\n"
+ "adcl 12(%2), %0 ;\n"
+ "adcl %3, %0 ;\n"
+ "adcl %4, %0 ;\n"
+ "adcl $0, %0 ;\n"
+ : "=&r" (sum)
+ : "r" (saddr), "r" (daddr),
+ "r"(htonl(len)), "r"(htonl(proto)), "0"(sum));
+
+ return csum_fold(sum);
+}
+
+/*
+ * Copy and checksum to user
+ */
+#define HAVE_CSUM_COPY_USER
+static __inline__ unsigned int csum_and_copy_to_user(const char *src,
+ char *dst, int len,
+ int sum, int *err_ptr)
+{
+ if (access_ok(VERIFY_WRITE, dst, len))
+ return(csum_partial_copy_to(src, dst, len, sum, err_ptr));
+
+ if (len)
+ *err_ptr = -EFAULT;
+
+ return -1; /* invalid checksum */
+}
+
+#endif
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only. This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff --git a/arch/um/include/sysdep-i386/frame_kern.h b/arch/um/include/sysdep-i386/frame_kern.h
index ec234c6e15c1..f469b8c6ea23 100644
--- a/arch/um/include/sysdep-i386/frame_kern.h
+++ b/arch/um/include/sysdep-i386/frame_kern.h
@@ -20,7 +20,8 @@ static inline void *sp_to_rt_sc(unsigned long sp)
{
unsigned long sc;
- sc = sp - signal_frame_si.sp_index + signal_frame_si.len - 4;
+ sc = sp - signal_frame_si.common.sp_index +
+ signal_frame_si.common.len - 4;
return((void *) sc);
}
@@ -28,7 +29,8 @@ static inline void *sp_to_mask(unsigned long sp)
{
unsigned long mask;
- mask = sp - signal_frame_sc.sp_index + signal_frame_sc.len - 8;
+ mask = sp - signal_frame_sc.common.sp_index +
+ signal_frame_sc.common.len - 8;
return((void *) mask);
}
@@ -38,7 +40,8 @@ static inline void *sp_to_rt_mask(unsigned long sp)
{
unsigned long mask;
- mask = sp - signal_frame_si.sp_index + signal_frame_si.len +
+ mask = sp - signal_frame_si.common.sp_index +
+ signal_frame_si.common.len +
sc_size(&signal_frame_sc.arch) - 4;
return((void *) mask);
}
diff --git a/arch/um/include/sysdep-i386/ptrace.h b/arch/um/include/sysdep-i386/ptrace.h
index 46aa12342153..e658d491bc5b 100644
--- a/arch/um/include/sysdep-i386/ptrace.h
+++ b/arch/um/include/sysdep-i386/ptrace.h
@@ -1,44 +1,78 @@
/*
- * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
* Licensed under the GPL
*/
#ifndef __SYSDEP_I386_PTRACE_H
#define __SYSDEP_I386_PTRACE_H
-#include "sysdep/sc.h"
+#include "uml-config.h"
+#include "ptrace-tt.h"
+#include "ptrace-skas.h"
+#include "choose-mode.h"
struct uml_pt_regs {
unsigned long args[6];
long syscall;
int is_user;
- void *sc;
+ union {
+#ifdef CONFIG_MODE_TT
+ void *tt;
+#endif
+#ifdef CONFIG_MODE_SKAS
+ struct {
+ unsigned long regs[HOST_FRAME_SIZE];
+ unsigned long fp[HOST_FP_SIZE];
+ unsigned long xfp[HOST_XFP_SIZE];
+ unsigned long fault_addr;
+ unsigned long fault_type;
+ unsigned long trap_type;
+ } skas;
+#endif
+ } mode;
};
#define EMPTY_UML_PT_REGS { \
syscall : -1, \
args : { [0 ... 5] = 0 }, \
- is_user : 0, \
- sc : NULL }
-
-#define UPT_IP(regs) SC_IP((regs)->sc)
-#define UPT_SP(regs) SC_SP((regs)->sc)
-#define UPT_EFLAGS(regs) SC_EFLAGS((regs)->sc)
-#define UPT_EAX(regs) SC_EAX((regs)->sc)
-#define UPT_EBX(regs) SC_EBX((regs)->sc)
-#define UPT_ECX(regs) SC_ECX((regs)->sc)
-#define UPT_EDX(regs) SC_EDX((regs)->sc)
-#define UPT_ESI(regs) SC_ESI((regs)->sc)
-#define UPT_EDI(regs) SC_EDI((regs)->sc)
-#define UPT_EBP(regs) SC_EBP((regs)->sc)
-#define UPT_ORIG_EAX(regs) ((regs)->syscall)
-#define UPT_CS(regs) SC_CS((regs)->sc)
-#define UPT_SS(regs) SC_SS((regs)->sc)
-#define UPT_DS(regs) SC_DS((regs)->sc)
-#define UPT_ES(regs) SC_ES((regs)->sc)
-#define UPT_FS(regs) SC_FS((regs)->sc)
-#define UPT_GS(regs) SC_GS((regs)->sc)
-#define UPT_SC(regs) ((regs)->sc)
+ is_user : 0 }
+
+extern int mode_tt;
+
+#define UPT_IP(r) \
+ CHOOSE_MODE(SC_IP((r)->mode.tt), REGS_IP((r)->mode.skas.regs))
+#define UPT_SP(r) \
+ CHOOSE_MODE(SC_SP((r)->mode.tt), REGS_SP((r)->mode.skas.regs))
+#define UPT_EFLAGS(r) \
+ CHOOSE_MODE(SC_EFLAGS((r)->mode.tt), REGS_EFLAGS((r)->mode.skas.regs))
+#define UPT_EAX(r) \
+ CHOOSE_MODE(SC_EAX((r)->mode.tt), REGS_EAX((r)->mode.skas.regs))
+#define UPT_EBX(r) \
+ CHOOSE_MODE(SC_EBX((r)->mode.tt), REGS_EBX((r)->mode.skas.regs))
+#define UPT_ECX(r) \
+ CHOOSE_MODE(SC_ECX((r)->mode.tt), REGS_ECX((r)->mode.skas.regs))
+#define UPT_EDX(r) \
+ CHOOSE_MODE(SC_EDX((r)->mode.tt), REGS_EDX((r)->mode.skas.regs))
+#define UPT_ESI(r) \
+ CHOOSE_MODE(SC_ESI((r)->mode.tt), REGS_ESI((r)->mode.skas.regs))
+#define UPT_EDI(r) \
+ CHOOSE_MODE(SC_EDI((r)->mode.tt), REGS_EDI((r)->mode.skas.regs))
+#define UPT_EBP(r) \
+ CHOOSE_MODE(SC_EBP((r)->mode.tt), REGS_EBP((r)->mode.skas.regs))
+#define UPT_ORIG_EAX(r) ((r)->syscall)
+#define UPT_CS(r) \
+ CHOOSE_MODE(SC_CS((r)->mode.tt), REGS_CS((r)->mode.skas.regs))
+#define UPT_SS(r) \
+ CHOOSE_MODE(SC_SS((r)->mode.tt), REGS_SS((r)->mode.skas.regs))
+#define UPT_DS(r) \
+ CHOOSE_MODE(SC_DS((r)->mode.tt), REGS_DS((r)->mode.skas.regs))
+#define UPT_ES(r) \
+ CHOOSE_MODE(SC_ES((r)->mode.tt), REGS_ES((r)->mode.skas.regs))
+#define UPT_FS(r) \
+ CHOOSE_MODE(SC_FS((r)->mode.tt), REGS_FS((r)->mode.skas.regs))
+#define UPT_GS(r) \
+ CHOOSE_MODE(SC_GS((r)->mode.tt), REGS_GS((r)->mode.skas.regs))
+#define UPT_SC(r) ((r)->mode.tt)
#define UPT_REG(regs, reg) \
({ unsigned long val; \
@@ -94,12 +128,29 @@ struct uml_pt_regs {
} \
} while (0)
-#define UPT_SET_SYSCALL_RETURN(regs, res) \
- SC_SET_SYSCALL_RETURN((regs)->sc, (res))
-#define UPT_RESTART_SYSCALL(regs) SC_RESTART_SYSCALL((regs)->sc)
-#define UPT_ORIG_SYSCALL(regs) UPT_EAX(regs)
-#define UPT_SYSCALL_NR(regs) ((regs)->syscall)
-#define UPT_SYSCALL_RET(regs) UPT_EAX(regs)
+#define UPT_SET_SYSCALL_RETURN(r, res) \
+ CHOOSE_MODE(SC_SET_SYSCALL_RETURN((r)->mode.tt, (res)), \
+ REGS_SET_SYSCALL_RETURN((r)->mode.skas.regs, (res)))
+
+#define UPT_RESTART_SYSCALL(r) \
+ CHOOSE_MODE(SC_RESTART_SYSCALL((r)->mode.tt), \
+ REGS_RESTART_SYSCALL((r)->mode.skas.regs))
+
+#define UPT_ORIG_SYSCALL(r) UPT_EAX(r)
+#define UPT_SYSCALL_NR(r) ((r)->syscall)
+#define UPT_SYSCALL_RET(r) UPT_EAX(r)
+
+#define UPT_SEGV_IS_FIXABLE(r) \
+ CHOOSE_MODE(SC_SEGV_IS_FIXABLE(r->mode.tt), \
+ REGS_SEGV_IS_FIXABLE(&r->mode.skas))
+
+#define UPT_FAULT_ADDR(r) \
+ CHOOSE_MODE(SC_FAULT_ADDR(r->mode.tt), \
+ REGS_FAULT_ADDR(&r->mode.skas))
+
+#define UPT_FAULT_WRITE(r) \
+ CHOOSE_MODE(SC_FAULT_WRITE(r->mode.tt), \
+ REGS_FAULT_WRITE(&r->mode.skas))
#endif
diff --git a/arch/um/include/sysdep-i386/sigcontext.h b/arch/um/include/sysdep-i386/sigcontext.h
index f445f375c9a4..d52262e31499 100644
--- a/arch/um/include/sysdep-i386/sigcontext.h
+++ b/arch/um/include/sysdep-i386/sigcontext.h
@@ -6,13 +6,22 @@
#ifndef __SYS_SIGCONTEXT_I386_H
#define __SYS_SIGCONTEXT_I386_H
+#include "sc.h"
+
#define IP_RESTART_SYSCALL(ip) ((ip) -= 2)
#define SC_RESTART_SYSCALL(sc) IP_RESTART_SYSCALL(SC_IP(sc))
-#define SC_SET_SYSCALL_RETURN(sc, result) do SC_EAX(sc) = (result) ; while(0)
+#define SC_SET_SYSCALL_RETURN(sc, result) SC_EAX(sc) = (result)
#define SC_FAULT_ADDR(sc) SC_CR2(sc)
-#define SC_FAULT_WRITE(sc) (SC_ERR(sc) & 2)
+#define SC_FAULT_TYPE(sc) SC_ERR(sc)
+
+#define FAULT_WRITE(err) (err & 2)
+#define TO_SC_ERR(is_write) ((is_write) ? 2 : 0)
+
+#define SC_FAULT_WRITE(sc) (FAULT_WRITE(SC_ERR(sc)))
+
+#define SC_TRAP_TYPE(sc) SC_TRAPNO(sc)
/* ptrace expects that, at the start of a system call, %eax contains
* -ENOSYS, so this makes it so.
@@ -20,10 +29,12 @@
#define SC_START_SYSCALL(sc) do SC_EAX(sc) = -ENOSYS; while(0)
/* These are General Protection and Page Fault */
-#define SEGV_IS_FIXABLE(sc) ((SC_TRAPNO(sc) == 13) || (SC_TRAPNO(sc) == 14))
+#define SEGV_IS_FIXABLE(trap) ((trap == 13) || (trap == 14))
-/* XXX struct sigcontext needs declaring by now */
+#define SC_SEGV_IS_FIXABLE(sc) (SEGV_IS_FIXABLE(SC_TRAPNO(sc)))
+#ifdef CONFIG_MODE_TT
+/* XXX struct sigcontext needs declaring by now */
static inline void sc_to_regs(struct uml_pt_regs *regs, struct sigcontext *sc,
unsigned long syscall)
{
@@ -35,6 +46,20 @@ static inline void sc_to_regs(struct uml_pt_regs *regs, struct sigcontext *sc,
regs->args[4] = SC_EDI(sc);
regs->args[5] = SC_EBP(sc);
}
+#endif
+
+#ifdef CONFIG_MODE_SKAS
+static inline void host_to_regs(struct uml_pt_regs *regs)
+{
+ regs->syscall = UPT_ORIG_EAX(regs);
+ regs->args[0] = UPT_EBX(regs);
+ regs->args[1] = UPT_ECX(regs);
+ regs->args[2] = UPT_EDX(regs);
+ regs->args[3] = UPT_ESI(regs);
+ regs->args[4] = UPT_EDI(regs);
+ regs->args[5] = UPT_EBP(regs);
+}
+#endif
extern unsigned long *sc_sigmask(void *sc_ptr);
extern int sc_get_fpregs(unsigned long buf, void *sc_ptr);
diff --git a/arch/um/include/time_user.h b/arch/um/include/time_user.h
index d49a34f0bee8..ec7dc1a65465 100644
--- a/arch/um/include/time_user.h
+++ b/arch/um/include/time_user.h
@@ -8,7 +8,7 @@
extern void timer(void);
extern void switch_timers(int to_real);
-extern void user_time_init(void);
+extern void set_interval(int timer_type);
extern void idle_sleep(int secs);
extern void enable_timer(void);
extern void time_lock(void);
diff --git a/arch/um/include/um_mmu.h b/arch/um/include/um_mmu.h
new file mode 100644
index 000000000000..3c5660ff97d7
--- /dev/null
+++ b/arch/um/include/um_mmu.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#ifndef __ARCH_UM_MMU_H
+#define __ARCH_UM_MMU_H
+
+#include "linux/config.h"
+#include "choose-mode.h"
+
+#ifdef CONFIG_MODE_TT
+#include "../kernel/tt/include/mmu.h"
+#endif
+
+#ifdef CONFIG_MODE_SKAS
+#include "../kernel/skas/include/mmu.h"
+#endif
+
+typedef union {
+#ifdef CONFIG_MODE_TT
+ struct mmu_context_tt tt;
+#endif
+#ifdef CONFIG_MODE_SKAS
+ struct mmu_context_skas skas;
+#endif
+} mm_context_t;
+
+#endif
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only. This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff --git a/arch/um/include/um_uaccess.h b/arch/um/include/um_uaccess.h
new file mode 100644
index 000000000000..41afa3a8f086
--- /dev/null
+++ b/arch/um/include/um_uaccess.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#ifndef __ARCH_UM_UACCESS_H
+#define __ARCH_UM_UACCESS_H
+
+#include "linux/config.h"
+#include "choose-mode.h"
+
+#ifdef CONFIG_MODE_TT
+#include "../kernel/tt/include/uaccess.h"
+#endif
+
+#ifdef CONFIG_MODE_SKAS
+#include "../kernel/skas/include/uaccess.h"
+#endif
+
+#define access_ok(type, addr, size) \
+ CHOOSE_MODE_PROC(access_ok_tt, access_ok_skas, type, addr, size)
+
+static inline int verify_area(int type, const void * addr, unsigned long size)
+{
+ return(CHOOSE_MODE_PROC(verify_area_tt, verify_area_skas, type, addr,
+ size));
+}
+
+static inline int copy_from_user(void *to, const void *from, int n)
+{
+ return(CHOOSE_MODE_PROC(copy_from_user_tt, copy_from_user_skas, to,
+ from, n));
+}
+
+static inline int copy_to_user(void *to, const void *from, int n)
+{
+ return(CHOOSE_MODE_PROC(copy_to_user_tt, copy_to_user_skas, to,
+ from, n));
+}
+
+static inline int strncpy_from_user(char *dst, const char *src, int count)
+{
+ return(CHOOSE_MODE_PROC(strncpy_from_user_tt, strncpy_from_user_skas,
+ dst, src, count));
+}
+
+static inline int __clear_user(void *mem, int len)
+{
+ return(CHOOSE_MODE_PROC(__clear_user_tt, __clear_user_skas, mem, len));
+}
+
+static inline int clear_user(void *mem, int len)
+{
+ return(CHOOSE_MODE_PROC(clear_user_tt, clear_user_skas, mem, len));
+}
+
+static inline int strnlen_user(const void *str, int len)
+{
+ return(CHOOSE_MODE_PROC(strnlen_user_tt, strnlen_user_skas, str, len));
+}
+
+#endif
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only. This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff --git a/arch/um/include/user_util.h b/arch/um/include/user_util.h
index 5f50aed753b2..a419cc9ccfff 100644
--- a/arch/um/include/user_util.h
+++ b/arch/um/include/user_util.h
@@ -8,6 +8,8 @@
#include "sysdep/ptrace.h"
+extern int mode_tt;
+
extern int grantpt(int __fd);
extern int unlockpt(int __fd);
extern char *ptsname(int __fd);
@@ -21,6 +23,13 @@ struct cpu_task {
extern struct cpu_task cpu_tasks[];
+struct signal_info {
+ void (*handler)(int, struct uml_pt_regs *);
+ int is_irq;
+};
+
+extern struct signal_info sig_info[];
+
extern unsigned long low_physmem;
extern unsigned long high_physmem;
extern unsigned long uml_physmem;
@@ -29,16 +38,11 @@ extern unsigned long end_vm;
extern unsigned long start_vm;
extern unsigned long highmem;
-extern int tracing_pid;
-extern int honeypot;
-
extern char host_info[];
extern char saved_command_line[];
extern char command_line[];
-extern int gdb_pid;
-
extern char *tempdir;
extern unsigned long _stext, _etext, _sdata, _edata, __bss_start, _end;
@@ -51,12 +55,10 @@ extern int pty_close_sigio;
extern void stop(void);
extern void stack_protections(unsigned long address);
extern void task_protections(unsigned long address);
-extern int signals(int (*init_proc)(void *), void *sp);
extern int wait_for_stop(int pid, int sig, int cont_type, void *relay);
extern void *add_signal_handler(int sig, void (*handler)(int));
extern int start_fork_tramp(void *arg, unsigned long temp_stack,
int clone_flags, int (*tramp)(void *));
-extern void trace_myself(void);
extern int clone_and_wait(int (*fn)(void *), void *arg, void *sp, int flags);
extern int linux_main(int argc, char **argv);
extern void remap_data(void *segment_start, void *segment_end, int w);
@@ -69,13 +71,12 @@ extern int switcheroo(int fd, int prot, void *from, void *to, int size);
extern void setup_machinename(char *machine_out);
extern void setup_hostinfo(void);
extern void add_arg(char *cmd_line, char *arg);
-extern void init_new_thread(void *sig_stack, void (*usr1_handler)(int));
-extern void attach_process(int pid);
-extern int fork_tramp(void *sig_stack);
+extern void init_new_thread_stack(void *sig_stack, void (*usr1_handler)(int));
+extern void init_new_thread_signals(int altstack);
extern void do_exec(int old_pid, int new_pid);
extern void tracer_panic(char *msg, ...);
extern char *get_umid(int only_if_set);
-extern void do_longjmp(void *p);
+extern void do_longjmp(void *p, int val);
extern void suspend_new_thread(int fd);
extern int detach(int pid, int sig);
extern int attach(int pid);
@@ -89,7 +90,8 @@ extern void arch_check_bugs(void);
extern int arch_handle_signal(int sig, struct uml_pt_regs *regs);
extern int arch_fixup(unsigned long address, void *sc_ptr);
extern void forward_pending_sigio(int target);
-
+extern int can_do_skas(void);
+
#endif
/*
diff --git a/arch/um/kernel/Makefile b/arch/um/kernel/Makefile
index 82736d449d8b..de98110a7494 100644
--- a/arch/um/kernel/Makefile
+++ b/arch/um/kernel/Makefile
@@ -1,40 +1,47 @@
+#
+# Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+# Licensed under the GPL
+#
+
EXTRA_TARGETS := unmap_fin.o
-obj-y = config.o exec_kern.o exec_user.o exitcode.o frame_kern.o frame.o \
+obj-y = checksum.o config.o exec_kern.o exitcode.o frame_kern.o frame.o \
helper.o init_task.o irq.o irq_user.o ksyms.o mem.o mem_user.o \
process.o process_kern.o ptrace.o reboot.o resource.o sigio_user.o \
sigio_kern.o signal_kern.o signal_user.o smp.o syscall_kern.o \
syscall_user.o sysrq.o sys_call_table.o tempfile.o time.o \
- time_kern.o tlb.o trap_kern.o trap_user.o uaccess_user.o um_arch.o \
+ time_kern.o tlb.o trap_kern.o trap_user.o um_arch.o \
umid.o user_util.o
obj-$(CONFIG_BLK_DEV_INITRD) += initrd_kern.o initrd_user.o
+obj-$(CONFIG_GPROF) += gprof_syms.o
+obj-$(CONFIG_GCOV) += gmon_syms.o
+obj-$(CONFIG_TTY_LOG) += tty_log.o
-# user_syms.o not included here because kbuild has its own ideas about
-# building anything in export-objs
+obj-$(CONFIG_MODE_TT) += tt/
+obj-$(CONFIG_MODE_SKAS) += skas/
-USER_OBJS := $(filter %_user.o,$(obj-y)) config.o helper.o process.o \
- tempfile.o time.o tty_log.o umid.o user_util.o user_syms.o
-USER_OBJS := $(foreach file,$(USER_OBJS),arch/um/kernel/$(file))
+user-objs-$(CONFIG_TTY_LOG) += tty_log.o
-export-objs := ksyms.o process_kern.o signal_kern.o gprof_syms.o gmon_syms.o
+# user_syms.o not included here because Rules.make has its own ideas about
+# building anything in export-objs
+
+USER_OBJS := $(filter %_user.o,$(obj-y)) $(user-objs-y) config.o helper.o \
+ process.o tempfile.o time.o tty_log.o umid.o user_util.o user_syms.o
+USER_OBJS := $(foreach file,$(USER_OBJS),$(obj)/$(file))
UNMAP_CFLAGS := $(patsubst -pg -DPROFILING,,$(USER_CFLAGS))
UNMAP_CFLAGS := $(patsubst -fprofile-arcs -ftest-coverage,,$(UNMAP_CFLAGS))
-ifeq ($(CONFIG_MODULES), y)
- DMODULES = -D__CONFIG_MODULES__
-endif
+DMODULES-$(CONFIG_MODULES) = -D__CONFIG_MODULES__
+DMODVERSIONS-$(CONFIG_MODVERSIONS) = -D__CONFIG_MODVERSIONS__
-ifeq ($(CONFIG_MODVERSIONS), y)
- DMODVERSIONS = -D__CONFIG_MODVERSIONS__
-endif
+export-objs-$(CONFIG_GPROF) += gprof_syms.o
+export-objs-$(CONFIG_GCOV) += gmon_syms.o
-obj-$(CONFIG_GPROF) += gprof_syms.o
-obj-$(CONFIG_GCOV) += gmon_syms.o
-obj-$(CONFIG_TTY_LOG) += tty_log.o
+export-objs := ksyms.o process_kern.o signal_kern.o $(export-objs-y)
-CFLAGS_user_syms.o = -D__AUTOCONF_INCLUDED__ $(DMODULES) $(DMODVERSIONS) \
+CFLAGS_user_syms.o = -D__AUTOCONF_INCLUDED__ $(DMODULES-y) $(DMODVERSIONS-y) \
-I/usr/include -I../include
CFLAGS_frame.o := $(patsubst -fomit-frame-pointer,,$(USER_CFLAGS))
@@ -42,27 +49,28 @@ CFLAGS_frame.o := $(patsubst -fomit-frame-pointer,,$(USER_CFLAGS))
$(USER_OBJS) : %.o: %.c
$(CC) $(CFLAGS_$@) $(USER_CFLAGS) -c -o $@ $<
-arch/um/kernel/unmap.o: arch/um/kernel/unmap.c
+$(obj)/unmap.o: $(src)/unmap.c
$(CC) $(UNMAP_CFLAGS) -c -o $@ $<
-arch/um/kernel/unmap_fin.o : arch/um/kernel/unmap.o
+$(obj)/unmap_fin.o : $(src)/unmap.o
ld -r -o $@ $< -lc -L/usr/lib
# This has to be separate because it needs be compiled with frame pointers
# regardless of how the rest of the kernel is built.
-arch/um/kernel/frame.o: arch/um/kernel/frame.c
+$(obj)/frame.o: $(src)/frame.c
$(CC) $(CFLAGS_$(notdir $@)) -c -o $@ $<
QUOTE = 'my $$config=`cat $(TOPDIR)/.config`; $$config =~ s/"/\\"/g ; while(<STDIN>) { $$_ =~ s/CONFIG/$$config/; print $$_ }'
-arch/um/kernel/config.c : arch/um/kernel/config.c.in $(TOPDIR)/.config
- $(PERL) -e $(QUOTE) < arch/um/kernel/config.c.in > $@
+$(obj)/config.c : $(src)/config.c.in $(TOPDIR)/.config
+ $(PERL) -e $(QUOTE) < $(src)/config.c.in > $@
-arch/um/kernel/config.o : arch/um/kernel/config.c
+$(obj)/config.o : $(obj)/config.c
clean:
rm -f config.c
+ for dir in $(subdir-y) ; do $(MAKE) -C $$dir clean; done
modules:
diff --git a/arch/um/kernel/checksum.c b/arch/um/kernel/checksum.c
new file mode 100644
index 000000000000..6e27cb032258
--- /dev/null
+++ b/arch/um/kernel/checksum.c
@@ -0,0 +1,42 @@
+#include "asm/uaccess.h"
+#include "linux/errno.h"
+
+extern unsigned int arch_csum_partial(const char *buff, int len, int sum);
+
+extern unsigned int csum_partial(char *buff, int len, int sum)
+{
+ return(arch_csum_partial(buff, len, sum));
+}
+
+unsigned int csum_partial_copy_to(const char *src, char *dst, int len,
+ int sum, int *err_ptr)
+{
+ if(copy_to_user(dst, src, len)){
+ *err_ptr = -EFAULT;
+ return(-1);
+ }
+
+ return(arch_csum_partial(src, len, sum));
+}
+
+unsigned int csum_partial_copy_from(const char *src, char *dst, int len,
+ int sum, int *err_ptr)
+{
+ if(copy_from_user(dst, src, len)){
+ *err_ptr = -EFAULT;
+ return(-1);
+ }
+
+ return(arch_csum_partial(dst, len, sum));
+}
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only. This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff --git a/arch/um/kernel/exec_kern.c b/arch/um/kernel/exec_kern.c
index 353bfa4da610..eaae628fa902 100644
--- a/arch/um/kernel/exec_kern.c
+++ b/arch/um/kernel/exec_kern.c
@@ -18,65 +18,17 @@
#include "2_5compat.h"
#include "os.h"
#include "time_user.h"
-
-/* See comment above fork_tramp for why sigstop is defined and used like
- * this
- */
-
-static int sigstop = SIGSTOP;
-
-static int exec_tramp(void *sig_stack)
-{
- int sig = sigstop;
-
- init_new_thread(sig_stack, NULL);
- kill(os_getpid(), sig);
- return(0);
-}
+#include "choose-mode.h"
+#include "mode_kern.h"
void flush_thread(void)
{
- unsigned long stack;
- int new_pid;
-
- stack = alloc_stack(0, 0);
- if(stack == 0){
- printk(KERN_ERR
- "flush_thread : failed to allocate temporary stack\n");
- do_exit(SIGKILL);
- }
-
- new_pid = start_fork_tramp((void *) current->thread.kernel_stack,
- stack, 0, exec_tramp);
- if(new_pid < 0){
- printk(KERN_ERR
- "flush_thread : new thread failed, errno = %d\n",
- -new_pid);
- do_exit(SIGKILL);
- }
-
- if(current->thread_info->cpu == 0)
- forward_interrupts(new_pid);
- current->thread.request.op = OP_EXEC;
- current->thread.request.u.exec.pid = new_pid;
- unprotect_stack((unsigned long) current->thread_info);
- os_usr1_process(os_getpid());
-
- enable_timer();
- free_page(stack);
- protect(uml_reserved, high_physmem - uml_reserved, 1, 1, 0, 1);
- task_protections((unsigned long) current->thread_info);
- force_flush_all();
- unblock_signals();
+ CHOOSE_MODE(flush_thread_tt(), flush_thread_skas());
}
void start_thread(struct pt_regs *regs, unsigned long eip, unsigned long esp)
{
- set_fs(USER_DS);
- flush_tlb_mm(current->mm);
- PT_REGS_IP(regs) = eip;
- PT_REGS_SP(regs) = esp;
- PT_FIX_EXEC_STACK(esp);
+ CHOOSE_MODE_PROC(start_thread_tt, start_thread_skas, regs, eip, esp);
}
static int execve1(char *file, char **argv, char **env)
@@ -93,8 +45,12 @@ static int execve1(char *file, char **argv, char **env)
int um_execve(char *file, char **argv, char **env)
{
- if(execve1(file, argv, env) == 0) do_longjmp(current->thread.jmp);
- return(-1);
+ int err;
+
+ err = execve1(file, argv, env);
+ if(!err)
+ do_longjmp(current->thread.exec_buf, 1);
+ return(err);
}
int sys_execve(char *file, char **argv, char **env)
diff --git a/arch/um/kernel/exitcode.c b/arch/um/kernel/exitcode.c
index 788f914d8510..14a748e2e25a 100644
--- a/arch/um/kernel/exitcode.c
+++ b/arch/um/kernel/exitcode.c
@@ -42,7 +42,7 @@ static int write_proc_exitcode(struct file *file, const char *buffer,
return(count);
}
-int make_proc_exitcode(void)
+static int make_proc_exitcode(void)
{
struct proc_dir_entry *ent;
diff --git a/arch/um/kernel/frame.c b/arch/um/kernel/frame.c
index 28793041426a..ae5b0e3e5158 100644
--- a/arch/um/kernel/frame.c
+++ b/arch/um/kernel/frame.c
@@ -12,6 +12,7 @@
#include <sched.h>
#include <errno.h>
#include <sys/ptrace.h>
+#include <sys/syscall.h>
#include <sys/mman.h>
#include <asm/page.h>
#include <asm/ptrace.h>
@@ -84,8 +85,8 @@ static int capture_stack(int (*child)(void *arg), void *arg, void *sp,
printf("capture_stack : waitpid failed - errno = %d\n", errno);
exit(1);
}
- if(!WIFEXITED(status) || (WEXITSTATUS(status) != 0)){
- printf("capture_stack : Expected exit status 0, "
+ if(!WIFSIGNALED(status) || (WTERMSIG(status) != 9)){
+ printf("capture_stack : Expected exit signal 9, "
"got status = 0x%x\n", status);
exit(1);
}
@@ -103,28 +104,61 @@ static int capture_stack(int (*child)(void *arg), void *arg, void *sp,
return(len);
}
-static void child_common(void *sp, int size, sighandler_t handler, int flags)
+struct common_raw {
+ void *stack;
+ int size;
+ unsigned long sig;
+ unsigned long sr;
+ unsigned long sp;
+};
+
+#define SA_RESTORER (0x04000000)
+
+typedef unsigned long old_sigset_t;
+
+struct old_sigaction {
+ __sighandler_t handler;
+ old_sigset_t sa_mask;
+ unsigned long sa_flags;
+ void (*sa_restorer)(void);
+};
+
+static void child_common(struct common_raw *common, sighandler_t handler,
+ int restorer, int flags)
{
- stack_t ss;
- struct sigaction sa;
+ stack_t ss = ((stack_t) { .ss_sp = common->stack,
+ .ss_flags = 0,
+ .ss_size = common->size });
+ int err;
if(ptrace(PTRACE_TRACEME, 0, 0, 0) < 0){
printf("PTRACE_TRACEME failed, errno = %d\n", errno);
}
- ss.ss_sp = sp;
- ss.ss_flags = 0;
- ss.ss_size = size;
if(sigaltstack(&ss, NULL) < 0){
printf("sigaltstack failed - errno = %d\n", errno);
- _exit(1);
+ kill(getpid(), SIGKILL);
}
- sa.sa_handler = handler;
- sigemptyset(&sa.sa_mask);
- sa.sa_flags = SA_ONSTACK | flags;
- if(sigaction(SIGUSR1, &sa, NULL) < 0){
+ if(restorer){
+ struct sigaction sa;
+
+ sa.sa_handler = handler;
+ sigemptyset(&sa.sa_mask);
+ sa.sa_flags = SA_ONSTACK | flags;
+ err = sigaction(SIGUSR1, &sa, NULL);
+ }
+ else {
+ struct old_sigaction sa;
+
+ sa.handler = handler;
+ sa.sa_mask = 0;
+ sa.sa_flags = (SA_ONSTACK | flags) & ~SA_RESTORER;
+ err = syscall(__NR_sigaction, SIGUSR1, &sa, NULL);
+ }
+
+ if(err < 0){
printf("sigaction failed - errno = %d\n", errno);
- _exit(1);
+ kill(getpid(), SIGKILL);
}
os_stop_process(os_getpid());
@@ -133,13 +167,12 @@ static void child_common(void *sp, int size, sighandler_t handler, int flags)
/* Changed only during early boot */
struct sc_frame signal_frame_sc;
+struct sc_frame signal_frame_sc_sr;
+
struct sc_frame_raw {
- void *stack;
- int size;
- unsigned long sig;
+ struct common_raw common;
unsigned long sc;
- unsigned long sr;
- unsigned long sp;
+ int restorer;
struct arch_frame_data_raw arch;
};
@@ -148,20 +181,20 @@ static struct sc_frame_raw *raw_sc = NULL;
static void sc_handler(int sig, struct sigcontext sc)
{
- raw_sc->sig = (unsigned long) &sig;
+ raw_sc->common.sig = (unsigned long) &sig;
+ raw_sc->common.sr = frame_restorer();
+ raw_sc->common.sp = frame_sp();
raw_sc->sc = (unsigned long) &sc;
- raw_sc->sr = frame_restorer();
- raw_sc->sp = frame_sp();
setup_arch_frame_raw(&raw_sc->arch, &sc);
os_stop_process(os_getpid());
- _exit(0);
+ kill(getpid(), SIGKILL);
}
static int sc_child(void *arg)
{
raw_sc = arg;
- child_common(raw_sc->stack, raw_sc->size, (sighandler_t) sc_handler,
- 0);
+ child_common(&raw_sc->common, (sighandler_t) sc_handler,
+ raw_sc->restorer, 0);
return(-1);
}
@@ -169,13 +202,9 @@ static int sc_child(void *arg)
struct si_frame signal_frame_si;
struct si_frame_raw {
- void *stack;
- int size;
- unsigned long sig;
+ struct common_raw common;
unsigned long sip;
unsigned long si;
- unsigned long sr;
- unsigned long sp;
};
/* Changed only during early boot */
@@ -183,23 +212,59 @@ static struct si_frame_raw *raw_si = NULL;
static void si_handler(int sig, siginfo_t *si)
{
- raw_si->sig = (unsigned long) &sig;
+ raw_si->common.sig = (unsigned long) &sig;
+ raw_si->common.sr = frame_restorer();
+ raw_si->common.sp = frame_sp();
raw_si->sip = (unsigned long) &si;
raw_si->si = (unsigned long) si;
- raw_si->sr = frame_restorer();
- raw_si->sp = frame_sp();
os_stop_process(os_getpid());
- _exit(0);
+ kill(getpid(), SIGKILL);
}
static int si_child(void *arg)
{
raw_si = arg;
- child_common(raw_si->stack, raw_si->size, (sighandler_t) si_handler,
- SA_SIGINFO);
+ child_common(&raw_si->common, (sighandler_t) si_handler, 1,
+ SA_SIGINFO);
return(-1);
}
+static int relative_sr(unsigned long sr, int sr_index, void *stack,
+ void *framep)
+{
+ unsigned long *srp = (unsigned long *) sr;
+ unsigned long frame = (unsigned long) framep;
+
+ if((*srp & PAGE_MASK) == (unsigned long) stack){
+ *srp -= sr;
+ *((unsigned long *) (frame + sr_index)) = *srp;
+ return(1);
+ }
+ else return(0);
+}
+
+static unsigned long capture_stack_common(int (*proc)(void *), void *arg,
+ struct common_raw *common_in,
+ void *top, void *sigstack,
+ int stack_len,
+ struct frame_common *common_out)
+{
+ unsigned long sig_top = (unsigned long) sigstack + stack_len, base;
+
+ common_in->stack = (void *) sigstack;
+ common_in->size = stack_len;
+ common_out->len = capture_stack(proc, arg, top, sig_top,
+ &common_out->data);
+ base = sig_top - common_out->len;
+ common_out->sig_index = common_in->sig - base;
+ common_out->sp_index = common_in->sp - base;
+ common_out->sr_index = common_in->sr - base;
+ common_out->sr_relative = relative_sr(common_in->sr,
+ common_out->sr_index, sigstack,
+ common_out->data);
+ return(base);
+}
+
void capture_signal_stack(void)
{
struct sc_frame_raw raw_sc;
@@ -220,54 +285,29 @@ void capture_signal_stack(void)
top = (unsigned long) stack + PAGE_SIZE - sizeof(void *);
sig_top = (unsigned long) sigstack + PAGE_SIZE;
- raw_sc.stack = sigstack;
- raw_sc.size = PAGE_SIZE;
- signal_frame_sc.len = capture_stack(sc_child, &raw_sc, (void *) top,
- sig_top, &signal_frame_sc.data);
-
- /* These are the offsets within signal_frame_sc.data (counting from
- * the bottom) of sig, sc, SA_RESTORER, and the initial sp.
- */
+ /* Get the sigcontext, no sigrestorer layout */
+ raw_sc.restorer = 0;
+ base = capture_stack_common(sc_child, &raw_sc, &raw_sc.common,
+ (void *) top, sigstack, PAGE_SIZE,
+ &signal_frame_sc.common);
- base = sig_top - signal_frame_sc.len;
- signal_frame_sc.sig_index = raw_sc.sig - base;
signal_frame_sc.sc_index = raw_sc.sc - base;
- signal_frame_sc.sr_index = raw_sc.sr - base;
- if((*((unsigned long *) raw_sc.sr) & PAGE_MASK) ==
- (unsigned long) sigstack){
- unsigned long *sr = (unsigned long *) raw_sc.sr;
- unsigned long frame = (unsigned long) signal_frame_sc.data;
-
- signal_frame_sc.sr_relative = 1;
- *sr -= raw_sc.sr;
- *((unsigned long *) (frame + signal_frame_sc.sr_index)) = *sr;
- }
- else signal_frame_sc.sr_relative = 0;
- signal_frame_sc.sp_index = raw_sc.sp - base;
setup_arch_frame(&raw_sc.arch, &signal_frame_sc.arch);
- /* Repeat for the siginfo variant */
+ /* Ditto for the sigcontext, sigrestorer layout */
+ raw_sc.restorer = 1;
+ base = capture_stack_common(sc_child, &raw_sc, &raw_sc.common,
+ (void *) top, sigstack, PAGE_SIZE,
+ &signal_frame_sc_sr.common);
+ signal_frame_sc_sr.sc_index = raw_sc.sc - base;
+
+ /* And the siginfo layout */
- raw_si.stack = sigstack;
- raw_si.size = PAGE_SIZE;
- signal_frame_si.len = capture_stack(si_child, &raw_si, (void *) top,
- sig_top, &signal_frame_si.data);
- base = sig_top - signal_frame_si.len;
- signal_frame_si.sig_index = raw_si.sig - base;
+ base = capture_stack_common(si_child, &raw_si, &raw_si.common,
+ (void *) top, sigstack, PAGE_SIZE,
+ &signal_frame_si.common);
signal_frame_si.sip_index = raw_si.sip - base;
signal_frame_si.si_index = raw_si.si - base;
- signal_frame_si.sr_index = raw_si.sr - base;
- if((*((unsigned long *) raw_si.sr) & PAGE_MASK) ==
- (unsigned long) sigstack){
- unsigned long *sr = (unsigned long *) raw_si.sr;
- unsigned long frame = (unsigned long) signal_frame_si.data;
-
- signal_frame_sc.sr_relative = 1;
- *sr -= raw_si.sr;
- *((unsigned long *) (frame + signal_frame_si.sr_index)) = *sr;
- }
- else signal_frame_si.sr_relative = 0;
- signal_frame_si.sp_index = raw_si.sp - base;
if((munmap(stack, PAGE_SIZE) < 0) ||
(munmap(sigstack, PAGE_SIZE) < 0)){
@@ -277,14 +317,6 @@ void capture_signal_stack(void)
}
}
-void set_sc_ip_sp(void *sc_ptr, unsigned long ip, unsigned long sp)
-{
- struct sigcontext *sc = sc_ptr;
-
- SC_IP(sc) = ip;
- SC_SP(sc) = sp;
-}
-
/*
* Overrides for Emacs so that we follow Linus's tabbing style.
* Emacs will notice this stuff at the end of the file and automatically
diff --git a/arch/um/kernel/frame_kern.c b/arch/um/kernel/frame_kern.c
index f71451c4c780..cd2177629bec 100644
--- a/arch/um/kernel/frame_kern.c
+++ b/arch/um/kernel/frame_kern.c
@@ -9,20 +9,31 @@
#include "frame_kern.h"
#include "sigcontext.h"
#include "sysdep/ptrace.h"
+#include "choose-mode.h"
+#include "mode.h"
static int copy_restorer(void (*restorer)(void), unsigned long start,
unsigned long sr_index, int sr_relative)
{
- if(restorer != 0){
- if(copy_to_user((void *) (start + sr_index), &restorer,
- sizeof(restorer)))
- return(1);
- }
- else if(sr_relative){
- unsigned long *sr = (unsigned long *) (start + sr_index);
- *sr += (unsigned long) sr;
+ unsigned long sr;
+
+ if(sr_relative){
+ sr = (unsigned long) restorer;
+ sr += start + sr_index;
+ restorer = (void (*)(void)) sr;
}
- return(0);
+
+ return(copy_to_user((void *) (start + sr_index), &restorer,
+ sizeof(restorer)));
+}
+
+static int copy_sc_to_user(void *to, struct pt_regs *from)
+{
+ return(CHOOSE_MODE(copy_sc_to_user_tt(to, from->regs.mode.tt,
+ &signal_frame_sc_sr.arch),
+ copy_sc_to_user_skas(to, &from->regs,
+ current->thread.cr2,
+ current->thread.err)));
}
int setup_signal_stack_si(unsigned long stack_top, int sig,
@@ -34,27 +45,30 @@ int setup_signal_stack_si(unsigned long stack_top, int sig,
void *sip;
int sig_size = _NSIG_WORDS * sizeof(unsigned long);
- start = stack_top - signal_frame_si.len -
+ start = stack_top - signal_frame_si.common.len -
sc_size(&signal_frame_sc.arch) - sig_size;
sip = (void *) (start + signal_frame_si.si_index);
- sc = start + signal_frame_si.len;
+ sc = start + signal_frame_si.common.len;
sigs = sc + sc_size(&signal_frame_sc.arch);
- if(copy_sc_to_user((void *) sc, regs->regs.sc,
- &signal_frame_sc.arch) ||
- copy_to_user((void *) start, signal_frame_si.data,
- signal_frame_si.len) ||
- copy_to_user((void *) (start + signal_frame_si.sig_index), &sig,
- sizeof(sig)) ||
+
+ if(restorer == NULL)
+ panic("setup_signal_stack_si - no restorer");
+
+ if(copy_sc_to_user((void *) sc, regs) ||
+ copy_to_user((void *) start, signal_frame_si.common.data,
+ signal_frame_si.common.len) ||
+ copy_to_user((void *) (start + signal_frame_si.common.sig_index),
+ &sig, sizeof(sig)) ||
copy_siginfo_to_user(sip, info) ||
copy_to_user((void *) (start + signal_frame_si.sip_index), &sip,
sizeof(sip)) ||
copy_to_user((void *) sigs, mask, sig_size) ||
- copy_restorer(restorer, start, signal_frame_si.sr_index,
- signal_frame_si.sr_relative))
+ copy_restorer(restorer, start, signal_frame_si.common.sr_index,
+ signal_frame_si.common.sr_relative))
return(1);
PT_REGS_IP(regs) = handler;
- PT_REGS_SP(regs) = start + signal_frame_sc.sp_index;
+ PT_REGS_SP(regs) = start + signal_frame_sc.common.sp_index;
return(0);
}
@@ -62,26 +76,35 @@ int setup_signal_stack_sc(unsigned long stack_top, int sig,
unsigned long handler, void (*restorer)(void),
struct pt_regs *regs, sigset_t *mask)
{
+ struct frame_common *frame = &signal_frame_sc_sr.common;
+ void *user_sc;
int sig_size = (_NSIG_WORDS - 1) * sizeof(unsigned long);
- unsigned long sigs, start = stack_top - signal_frame_sc.len - sig_size;
- void *user_sc = (void *) (start + signal_frame_sc.sc_index);
+ unsigned long sigs, sr;
+ unsigned long start = stack_top - frame->len - sig_size;
+
+ user_sc = (void *) (start + signal_frame_sc_sr.sc_index);
+ if(restorer == NULL){
+ frame = &signal_frame_sc.common;
+ user_sc = (void *) (start + signal_frame_sc.sc_index);
+ sr = (unsigned long) frame->data;
+ sr += frame->sr_index;
+ sr = *((unsigned long *) sr);
+ restorer = ((void (*)(void)) sr);
+ }
- sigs = start + signal_frame_sc.len;
- if(copy_to_user((void *) start, signal_frame_sc.data,
- signal_frame_sc.len) ||
- copy_to_user((void *) (start + signal_frame_sc.sig_index), &sig,
+ sigs = start + frame->len;
+ if(copy_to_user((void *) start, frame->data, frame->len) ||
+ copy_to_user((void *) (start + frame->sig_index), &sig,
sizeof(sig)) ||
- copy_sc_to_user(user_sc, regs->regs.sc, &signal_frame_sc.arch) ||
+ copy_sc_to_user(user_sc, regs) ||
copy_to_user(sc_sigmask(user_sc), mask, sizeof(mask->sig[0])) ||
copy_to_user((void *) sigs, &mask->sig[1], sig_size) ||
- copy_restorer(restorer, start, signal_frame_sc.sr_index,
- signal_frame_sc.sr_relative))
+ copy_restorer(restorer, start, frame->sr_index, frame->sr_relative))
return(1);
PT_REGS_IP(regs) = handler;
- PT_REGS_SP(regs) = start + signal_frame_sc.sp_index;
+ PT_REGS_SP(regs) = start + frame->sp_index;
- set_sc_ip_sp(regs->regs.sc, handler, start + signal_frame_sc.sp_index);
return(0);
}
diff --git a/arch/um/kernel/helper.c b/arch/um/kernel/helper.c
index 5d8fb7bba2b1..5c4b27942da3 100644
--- a/arch/um/kernel/helper.c
+++ b/arch/um/kernel/helper.c
@@ -43,9 +43,12 @@ static int helper_child(void *arg)
execvp(argv[0], argv);
printk("execvp of '%s' failed - errno = %d\n", argv[0], errno);
write(data->fd, &errno, sizeof(errno));
- _exit(1);
+ os_kill_process(os_getpid(), 0);
+ return(0);
}
+/* XXX The alloc_stack here breaks if this is called in the tracing thread */
+
int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv,
unsigned long *stack_out)
{
@@ -86,7 +89,10 @@ int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv,
errno);
return(-errno);
}
- else if(n != 0) pid = -err;
+ else if(n != 0){
+ waitpid(pid, NULL, 0);
+ pid = -err;
+ }
if(stack_out == NULL) free_stack(stack, 0);
else *stack_out = stack;
diff --git a/arch/um/kernel/init_task.c b/arch/um/kernel/init_task.c
index f06162f5a113..c9bc00a19403 100644
--- a/arch/um/kernel/init_task.c
+++ b/arch/um/kernel/init_task.c
@@ -47,7 +47,7 @@ struct task_struct *alloc_task_struct(void){
void unprotect_stack(unsigned long stack)
{
- protect(stack, 4 * PAGE_SIZE, 1, 1, 0, 1);
+ protect_memory(stack, 4 * PAGE_SIZE, 1, 1, 0, 1);
}
void free_task_struct(struct task_struct *task)
diff --git a/arch/um/kernel/irq_user.c b/arch/um/kernel/irq_user.c
index a5abb61536cf..239a6a6126c9 100644
--- a/arch/um/kernel/irq_user.c
+++ b/arch/um/kernel/irq_user.c
@@ -188,7 +188,8 @@ int activate_fd(int irq, int fd, int type, void *dev_id)
pollfds_size++;
}
- if(type == IRQ_WRITE) events = 0;
+ if(type == IRQ_WRITE)
+ fd = -1;
pollfds[pollfds_num] = ((struct pollfd) { fd : fd,
events : events,
@@ -337,6 +338,7 @@ void reactivate_fd(int fd, int irqnum)
irq_unlock(flags);
return;
}
+
pollfds[i].fd = irq->fd;
irq_unlock(flags);
diff --git a/arch/um/kernel/ksyms.c b/arch/um/kernel/ksyms.c
index 28e728347041..7de3e05edbab 100644
--- a/arch/um/kernel/ksyms.c
+++ b/arch/um/kernel/ksyms.c
@@ -1,3 +1,8 @@
+/*
+ * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
#include "linux/config.h"
#include "linux/module.h"
#include "linux/string.h"
@@ -19,17 +24,13 @@
EXPORT_SYMBOL(stop);
EXPORT_SYMBOL(uml_physmem);
EXPORT_SYMBOL(set_signals);
+EXPORT_SYMBOL(get_signals);
EXPORT_SYMBOL(kernel_thread);
EXPORT_SYMBOL(__const_udelay);
+EXPORT_SYMBOL(__udelay);
EXPORT_SYMBOL(sys_waitpid);
EXPORT_SYMBOL(task_size);
-EXPORT_SYMBOL(__do_copy_from_user);
-EXPORT_SYMBOL(__do_copy_to_user);
-EXPORT_SYMBOL(__do_strncpy_from_user);
-EXPORT_SYMBOL(__do_strnlen_user);
EXPORT_SYMBOL(flush_tlb_range);
-EXPORT_SYMBOL(__do_clear_user);
-EXPORT_SYMBOL(honeypot);
EXPORT_SYMBOL(host_task_size);
EXPORT_SYMBOL(arch_validate);
@@ -37,10 +38,10 @@ EXPORT_SYMBOL(region_pa);
EXPORT_SYMBOL(region_va);
EXPORT_SYMBOL(phys_mem_map);
EXPORT_SYMBOL(page_mem_map);
-EXPORT_SYMBOL(get_signals);
EXPORT_SYMBOL(page_to_phys);
EXPORT_SYMBOL(phys_to_page);
EXPORT_SYMBOL(high_physmem);
+EXPORT_SYMBOL(empty_zero_page);
EXPORT_SYMBOL(os_open_file);
EXPORT_SYMBOL(os_read_file);
@@ -53,7 +54,6 @@ EXPORT_SYMBOL(helper_wait);
EXPORT_SYMBOL(os_shutdown_socket);
EXPORT_SYMBOL(os_connect_socket);
EXPORT_SYMBOL(run_helper);
-EXPORT_SYMBOL(tracing_pid);
EXPORT_SYMBOL(start_thread);
EXPORT_SYMBOL(dump_thread);
@@ -75,6 +75,7 @@ EXPORT_SYMBOL_NOVERS(__write_lock_failed);
extern void FASTCALL( __read_lock_failed(rwlock_t *rw));
EXPORT_SYMBOL_NOVERS(__read_lock_failed);
+EXPORT_SYMBOL(smp_num_cpus);
#endif
#ifdef CONFIG_HIGHMEM
diff --git a/arch/um/kernel/mem.c b/arch/um/kernel/mem.c
index 5a582a8de7d1..178223bf2bfa 100644
--- a/arch/um/kernel/mem.c
+++ b/arch/um/kernel/mem.c
@@ -25,6 +25,8 @@
#include "mem.h"
#include "kern.h"
#include "init.h"
+#include "os.h"
+#include "mode_kern.h"
/* Changed during early boot */
pgd_t swapper_pg_dir[1024];
@@ -56,12 +58,12 @@ static unsigned long brk_end;
static void map_cb(void *unused)
{
- map(brk_end, __pa(brk_end), uml_reserved - brk_end, 1, 1, 0);
+ map_memory(brk_end, __pa(brk_end), uml_reserved - brk_end, 1, 1, 0);
}
void unmap_physmem(void)
{
- unmap((void *) brk_end, uml_reserved - brk_end);
+ os_unmap_memory((void *) brk_end, uml_reserved - brk_end);
}
extern char __binary_start;
@@ -81,17 +83,17 @@ void mem_init(void)
/* Map in the area just after the brk now that kmalloc is about
* to be turned on.
*/
- brk_end = (unsigned long) ROUND_UP(sbrk(0));
+ brk_end = (unsigned long) UML_ROUND_UP(sbrk(0));
map_cb(NULL);
- tracing_cb(map_cb, NULL);
+ initial_thread_cb(map_cb, NULL);
free_bootmem(__pa(brk_end), uml_reserved - brk_end);
uml_reserved = brk_end;
/* Fill in any hole at the start of the binary */
start = (unsigned long) &__binary_start;
if(uml_physmem != start){
- map(uml_physmem, __pa(uml_physmem), start - uml_physmem,
- 1, 1, 0);
+ map_memory(uml_physmem, __pa(uml_physmem), start - uml_physmem,
+ 1, 1, 0);
}
/* this will put all low memory onto the freelists */
@@ -106,6 +108,21 @@ void mem_init(void)
kmalloc_ok = 1;
}
+/* Changed during early boot */
+static unsigned long kmem_top = 0;
+
+unsigned long get_kmem_end(void)
+{
+ if(kmem_top == 0)
+ kmem_top = CHOOSE_MODE(kmem_end_tt, kmem_end_skas);
+ return(kmem_top);
+}
+
+void set_kmem_end(unsigned long new)
+{
+ kmem_top = new;
+}
+
#if CONFIG_HIGHMEM
/* Changed during early boot */
pte_t *kmap_pte;
@@ -379,20 +396,6 @@ void show_mem(void)
printk("%d pages swap cached\n", cached);
}
-/* Changed during early boot */
-static unsigned long kmem_top = 0;
-
-unsigned long get_kmem_end(void)
-{
- if(kmem_top == 0) kmem_top = host_task_size - ABOVE_KMEM;
- return(kmem_top);
-}
-
-void set_kmem_end(unsigned long new)
-{
- kmem_top = new;
-}
-
static int __init uml_mem_setup(char *line, int *add)
{
char *retptr;
@@ -411,28 +414,8 @@ __uml_setup("mem=", uml_mem_setup,
struct page *arch_validate(struct page *page, int mask, int order)
{
- unsigned long addr, zero = 0;
- int i;
-
- again:
- if(page == NULL) return(page);
- if(PageHighMem(page)) return(page);
-
- addr = (unsigned long) page_address(page);
- for(i = 0; i < (1 << order); i++){
- current->thread.fault_addr = (void *) addr;
- if(__do_copy_to_user((void *) addr, &zero,
- sizeof(zero),
- &current->thread.fault_addr,
- &current->thread.fault_catcher)){
- if(!(mask & __GFP_WAIT)) return(NULL);
- else break;
- }
- addr += PAGE_SIZE;
- }
- if(i == (1 << order)) return(page);
- page = alloc_pages(mask, order);
- goto again;
+ return(CHOOSE_MODE_PROC(arch_validate_tt, arch_validate_skas, page,
+ mask, order));
}
DECLARE_MUTEX(vm_reserved_sem);
@@ -513,7 +496,7 @@ unsigned long get_vm(unsigned long len)
return(0);
found:
up(&vm_reserved_sem);
- start = (unsigned long) ROUND_UP(this->end) + PAGE_SIZE;
+ start = (unsigned long) UML_ROUND_UP(this->end) + PAGE_SIZE;
err = reserve_vm(start, start + len, NULL);
if(err) return(0);
return(start);
@@ -562,7 +545,7 @@ struct iomem iomem_regions[NREGIONS] = { [ 0 ... NREGIONS - 1 ] =
int num_iomem_regions = 0;
-void add_iomem(char *name, int fd, int size)
+void add_iomem(char *name, int fd, unsigned long size)
{
if(num_iomem_regions == sizeof(iomem_regions)/sizeof(iomem_regions[0]))
return;
diff --git a/arch/um/kernel/mem_user.c b/arch/um/kernel/mem_user.c
index af857510d17a..d90345b5fd44 100644
--- a/arch/um/kernel/mem_user.c
+++ b/arch/um/kernel/mem_user.c
@@ -181,44 +181,22 @@ void log(char *fmt, ...)
}
#endif
-void map(unsigned long virt, unsigned long phys, unsigned long len,
- int r, int w, int x)
+int map_memory(unsigned long virt, unsigned long phys, unsigned long len,
+ int r, int w, int x)
{
- struct mem_region *region;
- void *loc;
- int prot;
-
- prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) |
- (x ? PROT_EXEC : 0);
- region = phys_region(phys);
-
- loc = mmap((void *) virt, len, prot, MAP_SHARED | MAP_FIXED,
- region->fd, phys_offset(phys));
- if(loc != (void *) virt){
- panic("Error mapping a page - errno = %d", errno);
- }
-}
-
-int unmap(void *addr, int len)
-{
- int err;
+ struct mem_region *region = phys_region(phys);
- err = munmap(addr, len);
- if(err < 0) return(-errno);
- else return(err);
+ return(os_map_memory((void *) virt, region->fd, phys_offset(phys), len,
+ r, w, x));
}
-int protect(unsigned long addr, unsigned long len, int r, int w, int x,
- int must_succeed)
+int protect_memory(unsigned long addr, unsigned long len, int r, int w, int x,
+ int must_succeed)
{
- int prot;
-
- prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) |
- (x ? PROT_EXEC : 0);
- if(mprotect((void *) addr, len, prot) == -1){
- if(must_succeed)
- panic("protect failed, errno = %d", errno);
- else return(-errno);
+ if(os_protect_memory((void *) addr, len, r, w, x) < 0){
+ if(must_succeed)
+ panic("protect failed, errno = %d", errno);
+ else return(-errno);
}
return(0);
}
diff --git a/arch/um/kernel/process.c b/arch/um/kernel/process.c
index d410aaa7332b..44e9a980949f 100644
--- a/arch/um/kernel/process.c
+++ b/arch/um/kernel/process.c
@@ -21,9 +21,6 @@
#include <asm/sigcontext.h>
#include <asm/unistd.h>
#include <asm/page.h>
-#ifdef PROFILING
-#include <sys/gmon.h>
-#endif
#include "user_util.h"
#include "kern_util.h"
#include "user.h"
@@ -33,13 +30,19 @@
#include "sysdep/ptrace.h"
#include "sysdep/sigcontext.h"
#include "irq_user.h"
-#include "syscall_user.h"
#include "ptrace_user.h"
#include "time_user.h"
#include "init.h"
#include "os.h"
+#include "uml-config.h"
+#include "choose-mode.h"
+#include "mode.h"
+#ifdef CONFIG_MODE_SKAS
+#include "skas_ptrace.h"
+#include "skas.h"
+#endif
-void init_new_thread(void *sig_stack, void (*usr1_handler)(int))
+void init_new_thread_stack(void *sig_stack, void (*usr1_handler)(int))
{
int flags = 0;
@@ -47,6 +50,13 @@ void init_new_thread(void *sig_stack, void (*usr1_handler)(int))
set_sigstack(sig_stack, 2 * page_size());
flags = SA_ONSTACK;
}
+ if(usr1_handler) set_handler(SIGUSR1, usr1_handler, flags, -1);
+}
+
+void init_new_thread_signals(int altstack)
+{
+ int flags = altstack ? SA_ONSTACK : 0;
+
set_handler(SIGSEGV, (__sighandler_t) sig_handler, flags,
SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1);
set_handler(SIGTRAP, (__sighandler_t) sig_handler, flags,
@@ -61,11 +71,10 @@ void init_new_thread(void *sig_stack, void (*usr1_handler)(int))
SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1);
set_handler(SIGUSR2, (__sighandler_t) sig_handler,
SA_NOMASK | flags, -1);
- if(usr1_handler) set_handler(SIGUSR1, usr1_handler, flags, -1);
- signal(SIGCHLD, SIG_IGN);
+ (void) CHOOSE_MODE(signal(SIGCHLD, SIG_IGN), (void *) 0);
signal(SIGHUP, SIG_IGN);
- init_irq_signals(sig_stack != NULL);
+ init_irq_signals(altstack);
}
struct tramp {
@@ -122,32 +131,6 @@ int start_fork_tramp(void *thread_arg, unsigned long temp_stack,
return(arg.pid);
}
-void trace_myself(void)
-{
- if(ptrace(PTRACE_TRACEME, 0, 0, 0) < 0)
- panic("ptrace failed in trace_myself");
-}
-
-void attach_process(int pid)
-{
- if((ptrace(PTRACE_ATTACH, pid, 0, 0) < 0) ||
- (ptrace(PTRACE_CONT, pid, 0, 0) < 0))
- tracer_panic("OP_FORK failed to attach pid");
- wait_for_stop(pid, SIGSTOP, PTRACE_CONT, NULL);
- if(ptrace(PTRACE_CONT, pid, 0, 0) < 0)
- tracer_panic("OP_FORK failed to continue process");
-}
-
-void tracer_panic(char *format, ...)
-{
- va_list ap;
-
- va_start(ap, format);
- vprintf(format, ap);
- printf("\n");
- while(1) sleep(10);
-}
-
void suspend_new_thread(int fd)
{
char c;
@@ -164,19 +147,18 @@ static int ptrace_child(void *arg)
if(ptrace(PTRACE_TRACEME, 0, 0, 0) < 0){
perror("ptrace");
- _exit(1);
+ os_kill_process(pid, 0);
}
os_stop_process(pid);
_exit(os_getpid() == pid);
}
-void __init check_ptrace(void)
+static int start_ptraced_child(void **stack_out)
{
void *stack;
unsigned long sp;
- int status, pid, n, syscall;
-
- printk("Checking that ptrace can change system call numbers...");
+ int pid, n, status;
+
stack = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
if(stack == MAP_FAILED)
@@ -191,6 +173,33 @@ void __init check_ptrace(void)
if(!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGSTOP))
panic("check_ptrace : expected SIGSTOP, got status = %d",
status);
+
+ *stack_out = stack;
+ return(pid);
+}
+
+static void stop_ptraced_child(int pid, void *stack, int exitcode)
+{
+ int status, n;
+
+ if(ptrace(PTRACE_CONT, pid, 0, 0) < 0)
+ panic("check_ptrace : ptrace failed, errno = %d", errno);
+ n = waitpid(pid, &status, 0);
+ if(!WIFEXITED(status) || (WEXITSTATUS(status) != exitcode))
+ panic("check_ptrace : child exited with status 0x%x", status);
+
+ if(munmap(stack, PAGE_SIZE) < 0)
+ panic("check_ptrace : munmap failed, errno = %d", errno);
+}
+
+void __init check_ptrace(void)
+{
+ void *stack;
+ int pid, syscall, n, status;
+
+ printk("Checking that ptrace can change system call numbers...");
+ pid = start_ptraced_child(&stack);
+
while(1){
if(ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0)
panic("check_ptrace : ptrace failed, errno = %d",
@@ -213,23 +222,19 @@ void __init check_ptrace(void)
break;
}
}
- if(ptrace(PTRACE_CONT, pid, 0, 0) < 0)
- panic("check_ptrace : ptrace failed, errno = %d", errno);
- n = waitpid(pid, &status, 0);
- if(!WIFEXITED(status) || (WEXITSTATUS(status) != 0))
- panic("check_ptrace : child exited with status 0x%x", status);
-
- if(munmap(stack, PAGE_SIZE) < 0)
- panic("check_ptrace : munmap failed, errno = %d", errno);
+ stop_ptraced_child(pid, stack, 0);
printk("OK\n");
}
int run_kernel_thread(int (*fn)(void *), void *arg, void **jmp_ptr)
{
jmp_buf buf;
+ int n;
*jmp_ptr = &buf;
- if(setjmp(buf)) return(1);
+ n = setjmp(buf);
+ if(n != 0)
+ return(n);
(*fn)(arg);
return(0);
}
@@ -244,6 +249,41 @@ void forward_pending_sigio(int target)
kill(target, SIGIO);
}
+int can_do_skas(void)
+{
+#ifdef CONFIG_MODE_SKAS
+ struct ptrace_faultinfo fi;
+ void *stack;
+ int pid, n, ret = 1;
+
+ printk("Checking for the skas3 patch in the host...");
+ pid = start_ptraced_child(&stack);
+
+ n = ptrace(PTRACE_FAULTINFO, pid, 0, &fi);
+ if(n < 0){
+ if(errno == EIO)
+ printk("not found\n");
+ else printk("No (unexpected errno - %d)\n", errno);
+ ret = 0;
+ }
+ else printk("found\n");
+
+ init_registers(pid);
+ stop_ptraced_child(pid, stack, 1);
+
+ printk("Checking for /proc/mm...");
+ if(access("/proc/mm", W_OK)){
+ printk("not found\n");
+ ret = 0;
+ }
+ else printk("found\n");
+
+ return(ret);
+#else
+ return(0);
+#endif
+}
+
/*
* Overrides for Emacs so that we follow Linus's tabbing style.
* Emacs will notice this stuff at the end of the file and automatically
diff --git a/arch/um/kernel/process_kern.c b/arch/um/kernel/process_kern.c
index 1588e175b4db..faf8609ceaf8 100644
--- a/arch/um/kernel/process_kern.c
+++ b/arch/um/kernel/process_kern.c
@@ -40,6 +40,9 @@
#include "sigcontext.h"
#include "2_5compat.h"
#include "os.h"
+#include "mode.h"
+#include "mode_kern.h"
+#include "choose-mode.h"
/* This is a per-cpu array. A processor only modifies its entry and it only
* cares about its entry, so it's OK if another processor is modifying its
@@ -64,26 +67,11 @@ struct task_struct *get_task(int pid, int require)
return(ret);
}
-int is_valid_pid(int pid)
-{
- struct task_struct *task;
-
- read_lock(&tasklist_lock);
- for_each_process(task){
- if(task->thread.extern_pid == pid){
- read_unlock(&tasklist_lock);
- return(1);
- }
- }
- read_unlock(&tasklist_lock);
- return(0);
-}
-
int external_pid(void *t)
{
struct task_struct *task = t ? t : current;
- return(task->thread.extern_pid);
+ return(CHOOSE_MODE_PROC(external_pid_tt, external_pid_skas, task));
}
int pid_to_processor_id(int pid)
@@ -101,37 +89,6 @@ void free_stack(unsigned long stack, int order)
free_pages(stack, order);
}
-void set_init_pid(int pid)
-{
- int err;
-
- init_task.thread.extern_pid = pid;
- err = os_pipe(init_task.thread.switch_pipe, 1, 1);
- if(err) panic("Can't create switch pipe for init_task, errno = %d",
- err);
-}
-
-int set_user_mode(void *t)
-{
- struct task_struct *task;
-
- task = t ? t : current;
- if(task->thread.tracing) return(1);
- task->thread.request.op = OP_TRACE_ON;
- os_usr1_process(os_getpid());
- return(0);
-}
-
-void set_tracing(void *task, int tracing)
-{
- ((struct task_struct *) task)->thread.tracing = tracing;
-}
-
-int is_tracing(void *t)
-{
- return (((struct task_struct *) t)->thread.tracing);
-}
-
unsigned long alloc_stack(int order, int atomic)
{
unsigned long page;
@@ -144,53 +101,13 @@ unsigned long alloc_stack(int order, int atomic)
return(page);
}
-extern void schedule_tail(struct task_struct *prev);
-
-static void new_thread_handler(int sig)
-{
- int (*fn)(void *);
- void *arg;
-
- fn = current->thread.request.u.thread.proc;
- arg = current->thread.request.u.thread.arg;
- current->thread.regs.regs.sc = (void *) (&sig + 1);
- suspend_new_thread(current->thread.switch_pipe[0]);
-
- block_signals();
-#ifdef CONFIG_SMP
- schedule_tail(NULL);
-#endif
- enable_timer();
- free_page(current->thread.temp_stack);
- set_cmdline("(kernel thread)");
- force_flush_all();
-
- current->thread.prev_sched = NULL;
- change_sig(SIGUSR1, 1);
- change_sig(SIGVTALRM, 1);
- change_sig(SIGPROF, 1);
- unblock_signals();
- if(!run_kernel_thread(fn, arg, &current->thread.jmp))
- do_exit(0);
-}
-
-static int new_thread_proc(void *stack)
-{
- change_sig(SIGIO, 0);
- change_sig(SIGVTALRM, 0);
- change_sig(SIGPROF, 0);
- init_new_thread(stack, new_thread_handler);
- os_usr1_process(os_getpid());
- return(0);
-}
-
int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
{
struct task_struct *p;
current->thread.request.u.thread.proc = fn;
current->thread.request.u.thread.arg = arg;
- p = do_fork(CLONE_VM | flags, 0, NULL, 0, NULL);
+ p = do_fork(CLONE_VM | flags, 0, NULL, 0, NULL, NULL);
if(IS_ERR(p)) panic("do_fork failed in kernel_thread");
return(p->pid);
}
@@ -208,83 +125,13 @@ void set_current(void *t)
struct task_struct *task = t;
cpu_tasks[task->thread_info->cpu] = ((struct cpu_task)
- { task->thread.extern_pid, task });
+ { external_pid(task), task });
}
void *switch_to(void *prev, void *next, void *last)
{
- struct task_struct *from, *to;
- unsigned long flags;
- int vtalrm, alrm, prof, err, cpu;
- char c;
- /* jailing and SMP are incompatible, so this doesn't need to be
- * made per-cpu
- */
- static int reading;
-
- from = prev;
- to = next;
-
- to->thread.prev_sched = from;
-
- cpu = from->thread_info->cpu;
- if(cpu == 0)
- forward_interrupts(to->thread.extern_pid);
-#ifdef CONFIG_SMP
- forward_ipi(cpu_data[cpu].ipi_pipe[0], to->thread.extern_pid);
-#endif
- local_irq_save(flags);
-
- vtalrm = change_sig(SIGVTALRM, 0);
- alrm = change_sig(SIGALRM, 0);
- prof = change_sig(SIGPROF, 0);
-
- forward_pending_sigio(to->thread.extern_pid);
-
- c = 0;
- set_current(to);
-
- reading = 0;
- err = os_write_file(to->thread.switch_pipe[1], &c, sizeof(c));
- if(err != sizeof(c))
- panic("write of switch_pipe failed, errno = %d", -err);
-
- reading = 1;
- if((from->state == TASK_ZOMBIE) || (from->state == TASK_DEAD))
- os_kill_process(os_getpid());
-
- err = os_read_file(from->thread.switch_pipe[0], &c, sizeof(c));
- if(err != sizeof(c))
- panic("read of switch_pipe failed, errno = %d", -err);
-
- /* This works around a nasty race with 'jail'. If we are switching
- * between two threads of a threaded app and the incoming process
- * runs before the outgoing process reaches the read, and it makes
- * it all the way out to userspace, then it will have write-protected
- * the outgoing process stack. Then, when the outgoing process
- * returns from the write, it will segfault because it can no longer
- * write its own stack. So, in order to avoid that, the incoming
- * thread sits in a loop yielding until 'reading' is set. This
- * isn't entirely safe, since there may be a reschedule from a timer
- * happening between setting 'reading' and sleeping in read. But,
- * it should get a whole quantum in which to reach the read and sleep,
- * which should be enough.
- */
-
- if(jail){
- while(!reading) sched_yield();
- }
-
- change_sig(SIGVTALRM, vtalrm);
- change_sig(SIGALRM, alrm);
- change_sig(SIGPROF, prof);
-
- arch_switch();
-
- flush_tlb_all();
- local_irq_restore(flags);
-
- return(current->thread.prev_sched);
+ return(CHOOSE_MODE(switch_to_tt(prev, next),
+ switch_to_skas(prev, next)));
}
void interrupt_end(void)
@@ -295,193 +142,37 @@ void interrupt_end(void)
void release_thread(struct task_struct *task)
{
- os_kill_process(task->thread.extern_pid);
+ CHOOSE_MODE(release_thread_tt(task), release_thread_skas(task));
}
-
+
void exit_thread(void)
{
- close(current->thread.switch_pipe[0]);
- close(current->thread.switch_pipe[1]);
+ CHOOSE_MODE(exit_thread_tt(), exit_thread_skas());
unprotect_stack((unsigned long) current->thread_info);
}
-
-/* Signal masking - signals are blocked at the start of fork_tramp. They
- * are re-enabled when finish_fork_handler is entered by fork_tramp hitting
- * itself with a SIGUSR1. set_user_mode has to be run with SIGUSR1 off,
- * so it is blocked before it's called. They are re-enabled on sigreturn
- * despite the fact that they were blocked when the SIGUSR1 was issued because
- * copy_thread copies the parent's signcontext, including the signal mask
- * onto the signal frame.
- */
-
-void finish_fork_handler(int sig)
-{
- current->thread.regs.regs.sc = (void *) (&sig + 1);
- suspend_new_thread(current->thread.switch_pipe[0]);
-
-#ifdef CONFIG_SMP
- schedule_tail(NULL);
-#endif
- enable_timer();
- change_sig(SIGVTALRM, 1);
- force_flush_all();
- if(current->mm != current->parent->mm)
- protect(uml_reserved, high_physmem - uml_reserved, 1, 1, 0, 1);
- task_protections((unsigned long) current->thread_info);
-
- current->thread.prev_sched = NULL;
-
- free_page(current->thread.temp_stack);
- change_sig(SIGUSR1, 0);
- set_user_mode(current);
-}
-
+
void *get_current(void)
{
return(current);
}
-/* This sigusr1 business works around a bug in gcc's -pg support.
- * Normally a procedure's mcount call comes after esp has been copied to
- * ebp and the new frame is constructed. With procedures with no locals,
- * the mcount comes before, as the first thing that the procedure does.
- * When that procedure is main for a thread, ebp comes in as NULL. So,
- * when mcount dereferences it, it segfaults. So, UML works around this
- * by adding a non-optimizable local to the various trampolines, fork_tramp
- * and outer_tramp below, and exec_tramp.
- */
-
-static int sigusr1 = SIGUSR1;
-
-int fork_tramp(void *stack)
-{
- int sig = sigusr1;
-
- change_sig(SIGIO, 0);
- change_sig(SIGVTALRM, 0);
- change_sig(SIGPROF, 0);
- init_new_thread(stack, finish_fork_handler);
-
- kill(os_getpid(), sig);
- return(0);
-}
-
int copy_thread(int nr, unsigned long clone_flags, unsigned long sp,
unsigned long stack_top, struct task_struct * p,
struct pt_regs *regs)
{
- int new_pid, err;
- unsigned long stack;
- int (*tramp)(void *);
-
p->thread = (struct thread_struct) INIT_THREAD;
p->thread.kernel_stack =
(unsigned long) p->thread_info + 2 * PAGE_SIZE;
-
- if(current->thread.forking)
- tramp = fork_tramp;
- else {
- tramp = new_thread_proc;
- p->thread.request.u.thread = current->thread.request.u.thread;
- }
-
- err = os_pipe(p->thread.switch_pipe, 1, 1);
- if(err){
- printk("copy_thread : pipe failed, errno = %d\n", -err);
- return(err);
- }
-
- stack = alloc_stack(0, 0);
- if(stack == 0){
- printk(KERN_ERR "copy_thread : failed to allocate "
- "temporary stack\n");
- return(-ENOMEM);
- }
-
- clone_flags &= CLONE_VM;
- p->thread.temp_stack = stack;
- new_pid = start_fork_tramp((void *) p->thread.kernel_stack, stack,
- clone_flags, tramp);
- if(new_pid < 0){
- printk(KERN_ERR "copy_thread : clone failed - errno = %d\n",
- -new_pid);
- return(new_pid);
- }
-
- if(current->thread.forking){
- sc_to_sc(p->thread.regs.regs.sc, current->thread.regs.regs.sc);
- PT_REGS_SET_SYSCALL_RETURN(&p->thread.regs, 0);
- if(sp != 0) PT_REGS_SP(&p->thread.regs) = sp;
- }
- p->thread.extern_pid = new_pid;
-
- current->thread.request.op = OP_FORK;
- current->thread.request.u.fork.pid = new_pid;
- os_usr1_process(os_getpid());
- return(0);
-}
-
-void tracing_reboot(void)
-{
- current->thread.request.op = OP_REBOOT;
- os_usr1_process(os_getpid());
+ return(CHOOSE_MODE_PROC(copy_thread_tt, copy_thread_skas, nr,
+ clone_flags, sp, stack_top, p, regs));
}
-void tracing_halt(void)
+void initial_thread_cb(void (*proc)(void *), void *arg)
{
- current->thread.request.op = OP_HALT;
- os_usr1_process(os_getpid());
+ CHOOSE_MODE_PROC(initial_thread_cb_tt, initial_thread_cb_skas, proc,
+ arg);
}
-
-void tracing_cb(void (*proc)(void *), void *arg)
-{
- if(os_getpid() == tracing_pid){
- (*proc)(arg);
- }
- else {
- current->thread.request.op = OP_CB;
- current->thread.request.u.cb.proc = proc;
- current->thread.request.u.cb.arg = arg;
- os_usr1_process(os_getpid());
- }
-}
-
-int do_proc_op(void *t, int proc_id)
-{
- struct task_struct *task;
- struct thread_struct *thread;
- int op, pid;
-
- task = t;
- thread = &task->thread;
- op = thread->request.op;
- switch(op){
- case OP_NONE:
- case OP_TRACE_ON:
- break;
- case OP_EXEC:
- pid = thread->request.u.exec.pid;
- do_exec(thread->extern_pid, pid);
- thread->extern_pid = pid;
- cpu_tasks[task->thread_info->cpu].pid = pid;
- break;
- case OP_FORK:
- attach_process(thread->request.u.fork.pid);
- break;
- case OP_CB:
- (*thread->request.u.cb.proc)(thread->request.u.cb.arg);
- break;
- case OP_REBOOT:
- case OP_HALT:
- break;
- default:
- tracer_panic("Bad op in do_proc_op");
- break;
- }
- thread->request.op = OP_NONE;
- return(op);
-}
-
+
unsigned long stack_sp(unsigned long page)
{
return(page + PAGE_SIZE - sizeof(void *));
@@ -518,7 +209,7 @@ void default_idle(void)
void cpu_idle(void)
{
- default_idle();
+ CHOOSE_MODE(init_idle_tt(), init_idle_skas());
}
int page_size(void)
@@ -531,21 +222,25 @@ int page_mask(void)
return(PAGE_MASK);
}
-unsigned long um_virt_to_phys(void *t, unsigned long addr)
+void *um_virt_to_phys(struct task_struct *task, unsigned long addr,
+ pte_t *pte_out)
{
- struct task_struct *task;
pgd_t *pgd;
pmd_t *pmd;
pte_t *pte;
- task = t;
- if(task->mm == NULL) return(0xffffffff);
+ if(task->mm == NULL)
+ return(ERR_PTR(-EINVAL));
pgd = pgd_offset(task->mm, addr);
pmd = pmd_offset(pgd, addr);
- if(!pmd_present(*pmd)) return(0xffffffff);
+ if(!pmd_present(*pmd))
+ return(ERR_PTR(-EINVAL));
pte = pte_offset_kernel(pmd, addr);
- if(!pte_present(*pte)) return(0xffffffff);
- return((pte_val(*pte) & PAGE_MASK) + (addr & ~PAGE_MASK));
+ if(!pte_present(*pte))
+ return(ERR_PTR(-EINVAL));
+ if(pte_out != NULL)
+ *pte_out = *pte;
+ return((void *) (pte_val(*pte) & PAGE_MASK) + (addr & ~PAGE_MASK));
}
char *current_cmd(void)
@@ -553,8 +248,8 @@ char *current_cmd(void)
#if defined(CONFIG_SMP) || defined(CONFIG_HIGHMEM)
return("(Unknown)");
#else
- unsigned long addr = um_virt_to_phys(current, current->mm->arg_start);
- return addr == 0xffffffff? "(Unknown)": __va(addr);
+ void *addr = um_virt_to_phys(current, current->mm->arg_start, NULL);
+ return IS_ERR(addr) ? "(Unknown)": __va((unsigned long) addr);
#endif
}
@@ -602,22 +297,6 @@ unsigned long get_fault_addr(void)
EXPORT_SYMBOL(get_fault_addr);
-void clear_singlestep(void *t)
-{
- struct task_struct *task = (struct task_struct *) t;
-
- task->ptrace &= ~PT_DTRACE;
-}
-
-int singlestepping(void *t)
-{
- struct task_struct *task = (struct task_struct *) t;
-
- if(task->thread.singlestep_syscall)
- return(0);
- return(task->ptrace & PT_DTRACE);
-}
-
void not_implemented(void)
{
printk(KERN_DEBUG "Something isn't implemented in here\n");
@@ -631,6 +310,7 @@ int user_context(unsigned long sp)
}
extern void remove_umid_dir(void);
+
__uml_exitcall(remove_umid_dir);
extern exitcall_t __uml_exitcall_begin, __uml_exitcall_end;
@@ -644,16 +324,6 @@ void do_uml_exitcalls(void)
(*call)();
}
-void *round_up(unsigned long addr)
-{
- return(ROUND_UP(addr));
-}
-
-void *round_down(unsigned long addr)
-{
- return(ROUND_DOWN(addr));
-}
-
char *uml_strdup(char *string)
{
char *new;
@@ -664,82 +334,6 @@ char *uml_strdup(char *string)
return(new);
}
-/* Changed by jail_setup, which is a setup */
-int jail = 0;
-
-int __init jail_setup(char *line, int *add)
-{
- int ok = 1;
-
- if(jail) return(0);
-#ifdef CONFIG_SMP
- printf("'jail' may not used used in a kernel with CONFIG_SMP "
- "enabled\n");
- ok = 0;
-#endif
-#ifdef CONFIG_HOSTFS
- printf("'jail' may not used used in a kernel with CONFIG_HOSTFS "
- "enabled\n");
- ok = 0;
-#endif
-#ifdef CONFIG_MODULES
- printf("'jail' may not used used in a kernel with CONFIG_MODULES "
- "enabled\n");
- ok = 0;
-#endif
- if(!ok) exit(1);
-
- /* CAP_SYS_RAWIO controls the ability to open /dev/mem and /dev/kmem.
- * Removing it from the bounding set eliminates the ability of anything
- * to acquire it, and thus read or write kernel memory.
- */
- cap_lower(cap_bset, CAP_SYS_RAWIO);
- jail = 1;
- return(0);
-}
-
-__uml_setup("jail", jail_setup,
-"jail\n"
-" Enables the protection of kernel memory from processes.\n\n"
-);
-
-static void mprotect_kernel_mem(int w)
-{
- unsigned long start, end;
-
- if(!jail || (current == &init_task)) return;
-
- start = (unsigned long) current->thread_info + PAGE_SIZE;
- end = (unsigned long) current->thread_info + PAGE_SIZE * 4;
- protect(uml_reserved, start - uml_reserved, 1, w, 1, 1);
- protect(end, high_physmem - end, 1, w, 1, 1);
-
- start = (unsigned long) ROUND_DOWN(&_stext);
- end = (unsigned long) ROUND_UP(&_etext);
- protect(start, end - start, 1, w, 1, 1);
-
- start = (unsigned long) ROUND_DOWN(&_unprotected_end);
- end = (unsigned long) ROUND_UP(&_edata);
- protect(start, end - start, 1, w, 1, 1);
-
- start = (unsigned long) ROUND_DOWN(&__bss_start);
- end = (unsigned long) ROUND_UP(brk_start);
- protect(start, end - start, 1, w, 1, 1);
-
- mprotect_kernel_vm(w);
-}
-
-/* No SMP problems since jailing and SMP are incompatible */
-void unprotect_kernel_mem(void)
-{
- mprotect_kernel_mem(1);
-}
-
-void protect_kernel_mem(void)
-{
- mprotect_kernel_mem(0);
-}
-
void *get_init_task(void)
{
return(&init_thread_union.thread_info.task);
@@ -760,11 +354,6 @@ int clear_user_proc(void *buf, int size)
return(clear_user(buf, size));
}
-void set_thread_sc(void *sc)
-{
- current->thread.regs.regs.sc = sc;
-}
-
int smp_sigio_handler(void)
{
#ifdef CONFIG_SMP
diff --git a/arch/um/kernel/ptrace.c b/arch/um/kernel/ptrace.c
index d6dacf475c33..5a32974de6d8 100644
--- a/arch/um/kernel/ptrace.c
+++ b/arch/um/kernel/ptrace.c
@@ -9,6 +9,7 @@
#include "linux/smp_lock.h"
#include "linux/security.h"
#include "linux/ptrace.h"
+#include "linux/proc_mm.h"
#include "asm/ptrace.h"
#include "asm/uaccess.h"
#include "kern_util.h"
@@ -21,6 +22,11 @@ void ptrace_disable(struct task_struct *child)
{
}
+extern long do_mmap2(struct task_struct *task, unsigned long addr,
+ unsigned long len, unsigned long prot,
+ unsigned long flags, unsigned long fd,
+ unsigned long pgoff);
+
int sys_ptrace(long request, long pid, long addr, long data)
{
struct task_struct *child;
@@ -182,13 +188,13 @@ int sys_ptrace(long request, long pid, long addr, long data)
#ifdef PTRACE_GETREGS
case PTRACE_GETREGS: { /* Get all gp regs from the child. */
- if (!access_ok(VERIFY_WRITE, (unsigned *)data,
+ if (!access_ok(VERIFY_WRITE, (unsigned long *)data,
FRAME_SIZE_OFFSET)) {
ret = -EIO;
break;
}
for ( i = 0; i < FRAME_SIZE_OFFSET; i += sizeof(long) ) {
- __put_user(getreg(child, i),(unsigned long *) data);
+ __put_user(getreg(child, i), (unsigned long *) data);
data += sizeof(long);
}
ret = 0;
@@ -232,6 +238,57 @@ int sys_ptrace(long request, long pid, long addr, long data)
ret = set_fpxregs(data, child);
break;
#endif
+ case PTRACE_FAULTINFO: {
+ struct ptrace_faultinfo fault;
+
+ fault = ((struct ptrace_faultinfo)
+ { .is_write = child->thread.err,
+ .addr = child->thread.cr2 });
+ ret = copy_to_user((unsigned long *) data, &fault,
+ sizeof(fault));
+ if(ret)
+ break;
+ break;
+ }
+ case PTRACE_SIGPENDING:
+ ret = copy_to_user((unsigned long *) data,
+ &child->pending.signal,
+ sizeof(child->pending.signal));
+ break;
+
+ case PTRACE_LDT: {
+ struct ptrace_ldt ldt;
+
+ if(copy_from_user(&ldt, (unsigned long *) data,
+ sizeof(ldt))){
+ ret = -EIO;
+ break;
+ }
+
+ /* This one is confusing, so just punt and return -EIO for
+ * now
+ */
+ ret = -EIO;
+ break;
+ }
+#ifdef CONFIG_PROC_MM
+ case PTRACE_SWITCH_MM: {
+ struct mm_struct *old = child->mm;
+ struct mm_struct *new = proc_mm_get_mm(data);
+
+ if(IS_ERR(new)){
+ ret = PTR_ERR(new);
+ break;
+ }
+
+ atomic_inc(&new->mm_users);
+ child->mm = new;
+ child->active_mm = new;
+ mmput(old);
+ ret = 0;
+ break;
+ }
+#endif
default:
ret = -EIO;
break;
diff --git a/arch/um/kernel/reboot.c b/arch/um/kernel/reboot.c
index 41b1faec8140..61d7a4e6000f 100644
--- a/arch/um/kernel/reboot.c
+++ b/arch/um/kernel/reboot.c
@@ -8,6 +8,8 @@
#include "kern_util.h"
#include "kern.h"
#include "os.h"
+#include "mode.h"
+#include "choose-mode.h"
#ifdef CONFIG_SMP
static void kill_idlers(int me)
@@ -17,26 +19,17 @@ static void kill_idlers(int me)
for(i = 0; i < sizeof(idle_threads)/sizeof(idle_threads[0]); i++){
p = idle_threads[i];
- if((p != NULL) && (p->thread.extern_pid != me))
- os_kill_process(p->thread.extern_pid);
+ if((p != NULL) && (p->thread.mode.tt.extern_pid != me))
+ os_kill_process(p->thread.mode.tt.extern_pid, 0);
}
}
#endif
static void kill_off_processes(void)
{
- struct task_struct *p;
- int me;
-
- me = os_getpid();
- for_each_process(p){
- if(p->thread.extern_pid != me)
- os_kill_process(p->thread.extern_pid);
- }
- if(init_task.thread.extern_pid != me)
- os_kill_process(init_task.thread.extern_pid);
+ CHOOSE_MODE(kill_off_processes_tt(), kill_off_processes_skas());
#ifdef CONFIG_SMP
- kill_idlers(me);
+ kill_idlers(os_getpid());
#endif
}
@@ -50,16 +43,14 @@ void machine_restart(char * __unused)
{
do_uml_exitcalls();
kill_off_processes();
- tracing_reboot();
- os_kill_process(os_getpid());
+ CHOOSE_MODE(reboot_tt(), reboot_skas());
}
void machine_power_off(void)
{
do_uml_exitcalls();
kill_off_processes();
- tracing_halt();
- os_kill_process(os_getpid());
+ CHOOSE_MODE(halt_tt(), halt_skas());
}
void machine_halt(void)
diff --git a/arch/um/kernel/sigio_user.c b/arch/um/kernel/sigio_user.c
index 740608075b7c..da00ed4feede 100644
--- a/arch/um/kernel/sigio_user.c
+++ b/arch/um/kernel/sigio_user.c
@@ -39,14 +39,13 @@ struct openpty_arg {
int err;
};
-static int openpty_cb(void *arg)
+static void openpty_cb(void *arg)
{
struct openpty_arg *info = arg;
info->err = 0;
if(openpty(&info->master, &info->slave, NULL, NULL, NULL))
info->err = errno;
- return(0);
}
void __init check_one_sigio(void (*proc)(int, int))
@@ -54,13 +53,9 @@ void __init check_one_sigio(void (*proc)(int, int))
struct sigaction old, new;
struct termios tt;
struct openpty_arg pty = { master : -1, slave : -1 };
- int master, slave, flags, err;
+ int master, slave, flags;
- err = run_helper_thread(openpty_cb, &pty, CLONE_FILES, NULL, 2);
- if(err < 0){
- printk("run_helper_thread failed, errno = %d\n", -err);
- return;
- }
+ initial_thread_cb(openpty_cb, &pty);
if(pty.err){
printk("openpty failed, errno = %d\n", pty.err);
return;
@@ -387,7 +382,7 @@ void write_sigio_workaround(void)
goto out_close2;
write_sigio_pid = run_helper_thread(write_sigio_thread, NULL,
- CLONE_FILES, &stack, 0);
+ CLONE_FILES | CLONE_VM, &stack, 0);
if(write_sigio_pid < 0) goto out_close2;
diff --git a/arch/um/kernel/signal_kern.c b/arch/um/kernel/signal_kern.c
index be60440cf012..f18ea0e1ac01 100644
--- a/arch/um/kernel/signal_kern.c
+++ b/arch/um/kernel/signal_kern.c
@@ -16,6 +16,7 @@
#include "linux/binfmts.h"
#include "asm/signal.h"
#include "asm/uaccess.h"
+#include "asm/unistd.h"
#include "user_util.h"
#include "kern_util.h"
#include "signal_kern.h"
@@ -23,6 +24,7 @@
#include "kern.h"
#include "frame_kern.h"
#include "sigcontext.h"
+#include "mode.h"
EXPORT_SYMBOL(block_signals);
EXPORT_SYMBOL(unblock_signals);
@@ -69,6 +71,9 @@ static int handle_signal(struct pt_regs *regs, unsigned long signr,
ret = 0;
switch(error){
+ case -ERESTART_RESTARTBLOCK:
+ current_thread_info()->restart_block.fn =
+ do_no_restart_syscall;
case -ERESTARTNOHAND:
ret = -EINTR;
break;
@@ -160,6 +165,10 @@ static int kern_do_signal(struct pt_regs *regs, sigset_t *oldset, int error)
PT_REGS_ORIG_SYSCALL(regs) = PT_REGS_SYSCALL_NR(regs);
PT_REGS_RESTART_SYSCALL(regs);
}
+ else if(PT_REGS_SYSCALL_RET(regs) == -ERESTART_RESTARTBLOCK){
+ PT_REGS_SYSCALL_RET(regs) = __NR_restart_syscall;
+ PT_REGS_RESTART_SYSCALL(regs);
+ }
}
/* This closes a way to execute a system call on the host. If
@@ -171,7 +180,7 @@ static int kern_do_signal(struct pt_regs *regs, sigset_t *oldset, int error)
*/
if((current->ptrace & PT_DTRACE) &&
is_syscall(PT_REGS_IP(&current->thread.regs)))
- current->thread.singlestep_syscall = 1;
+ (void) CHOOSE_MODE(current->thread.mode.tt.singlestep_syscall = 1, 0);
return(0);
}
@@ -228,6 +237,16 @@ int sys_rt_sigsuspend(sigset_t *unewset, size_t sigsetsize)
}
}
+static int copy_sc_from_user(struct pt_regs *to, void *from)
+{
+ int ret;
+
+ ret = CHOOSE_MODE(copy_sc_from_user_tt(to->regs.mode.tt, from,
+ &signal_frame_sc.arch),
+ copy_sc_from_user_skas(&to->regs, from));
+ return(ret);
+}
+
int sys_sigreturn(struct pt_regs regs)
{
void *sc = sp_to_sc(PT_REGS_SP(&regs));
@@ -241,8 +260,7 @@ int sys_sigreturn(struct pt_regs regs)
sigdelsetmask(&current->blocked, ~_BLOCKABLE);
recalc_sigpending();
spin_unlock_irq(&current->sig->siglock);
- copy_sc_from_user(current->thread.regs.regs.sc, sc,
- &signal_frame_sc.arch);
+ copy_sc_from_user(&current->thread.regs, sc);
return(PT_REGS_SYSCALL_RET(&current->thread.regs));
}
@@ -257,8 +275,7 @@ int sys_rt_sigreturn(struct pt_regs regs)
sigdelsetmask(&current->blocked, ~_BLOCKABLE);
recalc_sigpending();
spin_unlock_irq(&current->sig->siglock);
- copy_sc_from_user(current->thread.regs.regs.sc, sc,
- &signal_frame_sc.arch);
+ copy_sc_from_user(&current->thread.regs, sc);
return(PT_REGS_SYSCALL_RET(&current->thread.regs));
}
diff --git a/arch/um/kernel/signal_user.c b/arch/um/kernel/signal_user.c
index 2ef64a89e014..52cfd60a1433 100644
--- a/arch/um/kernel/signal_user.c
+++ b/arch/um/kernel/signal_user.c
@@ -21,13 +21,12 @@
void set_sigstack(void *sig_stack, int size)
{
- stack_t stack;
+ stack_t stack = ((stack_t) { .ss_flags = 0,
+ .ss_sp = (__ptr_t) sig_stack,
+ .ss_size = size - sizeof(void *) });
- stack.ss_sp = (__ptr_t) sig_stack;
- stack.ss_flags = 0;
- stack.ss_size = size - sizeof(void *);
if(sigaltstack(&stack, NULL) != 0)
- panic("sigaltstack failed");
+ panic("enabling signal stack failed, errno = %d\n", errno);
}
void set_handler(int sig, void (*handler)(int), int flags, ...)
diff --git a/arch/um/kernel/skas/Makefile b/arch/um/kernel/skas/Makefile
new file mode 100644
index 000000000000..72c79956f6a6
--- /dev/null
+++ b/arch/um/kernel/skas/Makefile
@@ -0,0 +1,24 @@
+#
+# Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+# Licensed under the GPL
+#
+
+obj-y = exec_kern.o exec_user.o mem.o mem_user.o mmu.o process.o \
+ process_kern.o syscall_kern.o syscall_user.o time.o tlb.o trap_user.o \
+ sys-$(SUBARCH)/
+
+USER_OBJS = $(filter %_user.o,$(obj-y)) process.o time.o
+USER_OBJS := $(foreach file,$(USER_OBJS),$(obj)/$(file))
+
+include/skas_ptregs.h : util/mk_ptregs
+ util/mk_ptregs > $@
+
+util/mk_ptregs :
+ $(MAKE) -C util
+
+$(USER_OBJS) : %.o: %.c
+ $(CC) $(CFLAGS_$(notdir $@)) $(USER_CFLAGS) -c -o $@ $<
+
+clean :
+ $(MAKE) -C util clean
+ $(RM) -f include/skas_ptregs.h
diff --git a/arch/um/kernel/skas/exec_kern.c b/arch/um/kernel/skas/exec_kern.c
new file mode 100644
index 000000000000..49356d26ac28
--- /dev/null
+++ b/arch/um/kernel/skas/exec_kern.c
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#include "linux/kernel.h"
+#include "asm/current.h"
+#include "asm/page.h"
+#include "asm/signal.h"
+#include "asm/ptrace.h"
+#include "asm/uaccess.h"
+#include "asm/mmu_context.h"
+#include "tlb.h"
+#include "skas.h"
+#include "mmu.h"
+#include "os.h"
+
+void flush_thread_skas(void)
+{
+ force_flush_all();
+ switch_mm_skas(current->mm->context.skas.mm_fd);
+}
+
+void start_thread_skas(struct pt_regs *regs, unsigned long eip,
+ unsigned long esp)
+{
+ set_fs(USER_DS);
+ PT_REGS_IP(regs) = eip;
+ PT_REGS_SP(regs) = esp;
+}
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only. This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff --git a/arch/um/kernel/skas/exec_user.c b/arch/um/kernel/skas/exec_user.c
new file mode 100644
index 000000000000..c9942b6fc79b
--- /dev/null
+++ b/arch/um/kernel/skas/exec_user.c
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#include <stdlib.h>
+#include <errno.h>
+#include <signal.h>
+#include <sched.h>
+#include <sys/wait.h>
+#include <sys/ptrace.h>
+#include "user.h"
+#include "kern_util.h"
+#include "os.h"
+#include "time_user.h"
+
+static int user_thread_tramp(void *arg)
+{
+ if(ptrace(PTRACE_TRACEME, 0, 0, 0) < 0)
+ panic("user_thread_tramp - PTRACE_TRACEME failed, "
+ "errno = %d\n", errno);
+ enable_timer();
+ os_stop_process(os_getpid());
+ return(0);
+}
+
+int user_thread(unsigned long stack, int flags)
+{
+ int pid, status;
+
+ pid = clone(user_thread_tramp, (void *) stack_sp(stack),
+ flags | CLONE_FILES | SIGCHLD, NULL);
+ if(pid < 0){
+ printk("user_thread - clone failed, errno = %d\n", errno);
+ return(pid);
+ }
+
+ if(waitpid(pid, &status, WUNTRACED) < 0){
+ printk("user_thread - waitpid failed, errno = %d\n", errno);
+ return(-errno);
+ }
+
+ if(!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGSTOP)){
+ printk("user_thread - trampoline didn't stop, status = %d\n",
+ status);
+ return(-EINVAL);
+ }
+
+ return(pid);
+}
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only. This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff --git a/arch/um/kernel/skas/include/mmu.h b/arch/um/kernel/skas/include/mmu.h
new file mode 100644
index 000000000000..cfbc062bd9dc
--- /dev/null
+++ b/arch/um/kernel/skas/include/mmu.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#ifndef __SKAS_MMU_H
+#define __SKAS_MMU_H
+
+#include "linux/list.h"
+#include "linux/spinlock.h"
+
+struct mmu_context_skas {
+ int mm_fd;
+};
+
+#endif
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only. This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff --git a/arch/um/kernel/skas/include/mode.h b/arch/um/kernel/skas/include/mode.h
new file mode 100644
index 000000000000..09cadc99edc5
--- /dev/null
+++ b/arch/um/kernel/skas/include/mode.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#ifndef __MODE_SKAS_H__
+#define __MODE_SKAS_H__
+
+extern unsigned long exec_regs[];
+extern unsigned long exec_fp_regs[];
+extern unsigned long exec_fpx_regs[];
+extern int have_fpx_regs;
+
+extern void user_time_init_skas(void);
+extern int copy_sc_from_user_skas(struct uml_pt_regs *regs, void *from_ptr);
+extern int copy_sc_to_user_skas(void *to_ptr, struct uml_pt_regs *regs,
+ unsigned long fault_addr, int fault_type);
+extern void sig_handler_common_skas(int sig, struct sigcontext *sc);
+extern void halt_skas(void);
+extern void reboot_skas(void);
+extern void kill_off_processes_skas(void);
+
+#endif
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only. This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff --git a/arch/um/kernel/skas/include/mode_kern.h b/arch/um/kernel/skas/include/mode_kern.h
new file mode 100644
index 000000000000..e4b472ac7d2d
--- /dev/null
+++ b/arch/um/kernel/skas/include/mode_kern.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#ifndef __SKAS_MODE_KERN_H__
+#define __SKAS_MODE_KERN_H__
+
+#include "linux/sched.h"
+#include "asm/page.h"
+#include "asm/ptrace.h"
+
+extern void flush_thread_skas(void);
+extern void *switch_to_skas(void *prev, void *next);
+extern void start_thread_skas(struct pt_regs *regs, unsigned long eip,
+ unsigned long esp);
+extern int copy_thread_skas(int nr, unsigned long clone_flags,
+ unsigned long sp, unsigned long stack_top,
+ struct task_struct *p, struct pt_regs *regs);
+extern void release_thread_skas(struct task_struct *task);
+extern void exit_thread_skas(void);
+extern void initial_thread_cb_skas(void (*proc)(void *), void *arg);
+extern void init_idle_skas(void);
+extern void flush_tlb_kernel_vm_skas(void);
+extern void __flush_tlb_one_skas(unsigned long addr);
+extern void flush_tlb_range_skas(struct vm_area_struct *vma,
+ unsigned long start, unsigned long end);
+extern void flush_tlb_mm_skas(struct mm_struct *mm);
+extern void force_flush_all_skas(void);
+extern long execute_syscall_skas(void *r);
+extern void before_mem_skas(unsigned long unused);
+extern unsigned long set_task_sizes_skas(int arg, unsigned long *host_size_out,
+ unsigned long *task_size_out);
+extern int start_uml_skas(void);
+extern struct page *arch_validate_skas(struct page *page, int mask, int order);
+extern int external_pid_skas(struct task_struct *task);
+extern int thread_pid_skas(struct task_struct *task);
+
+#define kmem_end_skas (host_task_size)
+
+#endif
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only. This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff --git a/arch/um/kernel/skas/include/proc_mm.h b/arch/um/kernel/skas/include/proc_mm.h
new file mode 100644
index 000000000000..cce61a679052
--- /dev/null
+++ b/arch/um/kernel/skas/include/proc_mm.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#ifndef __SKAS_PROC_MM_H
+#define __SKAS_PROC_MM_H
+
+#define MM_MMAP 54
+#define MM_MUNMAP 55
+#define MM_MPROTECT 56
+#define MM_COPY_SEGMENTS 57
+
+struct mm_mmap {
+ unsigned long addr;
+ unsigned long len;
+ unsigned long prot;
+ unsigned long flags;
+ unsigned long fd;
+ unsigned long offset;
+};
+
+struct mm_munmap {
+ unsigned long addr;
+ unsigned long len;
+};
+
+struct mm_mprotect {
+ unsigned long addr;
+ unsigned long len;
+ unsigned int prot;
+};
+
+struct proc_mm_op {
+ int op;
+ union {
+ struct mm_mmap mmap;
+ struct mm_munmap munmap;
+ struct mm_mprotect mprotect;
+ int copy_segments;
+ } u;
+};
+
+#endif
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only. This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff --git a/arch/um/kernel/skas/include/ptrace-skas.h b/arch/um/kernel/skas/include/ptrace-skas.h
new file mode 100644
index 000000000000..f4ab3fb43339
--- /dev/null
+++ b/arch/um/kernel/skas/include/ptrace-skas.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#ifndef __PTRACE_SKAS_H
+#define __PTRACE_SKAS_H
+
+#include "uml-config.h"
+
+#ifdef CONFIG_MODE_SKAS
+
+#include "skas_ptregs.h"
+
+#define HOST_FRAME_SIZE 17
+
+#define REGS_IP(r) ((r)[HOST_IP])
+#define REGS_SP(r) ((r)[HOST_SP])
+#define REGS_EFLAGS(r) ((r)[HOST_EFLAGS])
+#define REGS_EAX(r) ((r)[HOST_EAX])
+#define REGS_EBX(r) ((r)[HOST_EBX])
+#define REGS_ECX(r) ((r)[HOST_ECX])
+#define REGS_EDX(r) ((r)[HOST_EDX])
+#define REGS_ESI(r) ((r)[HOST_ESI])
+#define REGS_EDI(r) ((r)[HOST_EDI])
+#define REGS_EBP(r) ((r)[HOST_EBP])
+#define REGS_CS(r) ((r)[HOST_CS])
+#define REGS_SS(r) ((r)[HOST_SS])
+#define REGS_DS(r) ((r)[HOST_DS])
+#define REGS_ES(r) ((r)[HOST_ES])
+#define REGS_FS(r) ((r)[HOST_FS])
+#define REGS_GS(r) ((r)[HOST_GS])
+
+#define REGS_SET_SYSCALL_RETURN(r, res) REGS_EAX(r) = (res)
+
+#define REGS_RESTART_SYSCALL(r) IP_RESTART_SYSCALL(REGS_IP(r))
+
+#define REGS_SEGV_IS_FIXABLE(r) SEGV_IS_FIXABLE((r)->trap_type)
+
+#define REGS_FAULT_ADDR(r) ((r)->fault_addr)
+
+#define REGS_FAULT_WRITE(r) FAULT_WRITE((r)->fault_type)
+
+#endif
+
+#endif
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only. This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff --git a/arch/um/kernel/skas/include/skas.h b/arch/um/kernel/skas/include/skas.h
new file mode 100644
index 000000000000..e733b0c87448
--- /dev/null
+++ b/arch/um/kernel/skas/include/skas.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#ifndef __SKAS_H
+#define __SKAS_H
+
+#include "sysdep/ptrace.h"
+
+extern int userspace_pid;
+
+extern void switch_threads(void *me, void *next);
+extern void thread_wait(void *sw, void *fb);
+extern void new_thread(void *stack, void **switch_buf_ptr, void **fork_buf_ptr,
+ void (*handler)(int));
+extern int start_idle_thread(void *stack, void *switch_buf_ptr,
+ void **fork_buf_ptr);
+extern int user_thread(unsigned long stack, int flags);
+extern void userspace(struct uml_pt_regs *regs);
+extern void new_thread_proc(void *stack, void (*handler)(int sig));
+extern void remove_sigstack(void);
+extern void new_thread_handler(int sig);
+extern void handle_syscall(struct uml_pt_regs *regs);
+extern void map(int fd, unsigned long virt, unsigned long phys,
+ unsigned long len, int r, int w, int x);
+extern int unmap(int fd, void *addr, int len);
+extern int protect(int fd, unsigned long addr, unsigned long len,
+ int r, int w, int x, int must_succeed);
+extern void user_signal(int sig, struct uml_pt_regs *regs);
+extern int singlestepping_skas(void);
+extern int new_mm(int from);
+extern void save_registers(struct uml_pt_regs *regs);
+extern void restore_registers(struct uml_pt_regs *regs);
+extern void start_userspace(void);
+extern void init_registers(int pid);
+
+#endif
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only. This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff --git a/arch/um/kernel/skas/include/skas_ptrace.h b/arch/um/kernel/skas/include/skas_ptrace.h
new file mode 100644
index 000000000000..7cd983d88d51
--- /dev/null
+++ b/arch/um/kernel/skas/include/skas_ptrace.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#ifndef __SKAS_PTRACE_H
+#define __SKAS_PTRACE_H
+
+struct ptrace_faultinfo {
+ int is_write;
+ unsigned long addr;
+};
+
+struct ptrace_ldt {
+ int func;
+ void *ptr;
+ unsigned long bytecount;
+};
+
+#define PTRACE_FAULTINFO 52
+#define PTRACE_SIGPENDING 53
+#define PTRACE_LDT 54
+#define PTRACE_SWITCH_MM 55
+
+#endif
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only. This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff --git a/arch/um/kernel/skas/include/uaccess.h b/arch/um/kernel/skas/include/uaccess.h
new file mode 100644
index 000000000000..df408e12d933
--- /dev/null
+++ b/arch/um/kernel/skas/include/uaccess.h
@@ -0,0 +1,236 @@
+/*
+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#ifndef __SKAS_UACCESS_H
+#define __SKAS_UACCESS_H
+
+#include "linux/string.h"
+#include "linux/sched.h"
+#include "linux/err.h"
+#include "asm/processor.h"
+#include "asm/pgtable.h"
+#include "asm/errno.h"
+#include "asm/current.h"
+#include "asm/a.out.h"
+#include "kern_util.h"
+
+#define access_ok_skas(type, addr, size) \
+ ((segment_eq(get_fs(), KERNEL_DS)) || \
+ (((unsigned long) (addr) < TASK_SIZE) && \
+ ((unsigned long) (addr) + (size) < TASK_SIZE)))
+
+static inline int verify_area_skas(int type, const void * addr,
+ unsigned long size)
+{
+ return(access_ok_skas(type, addr, size) ? 0 : -EFAULT);
+}
+
+extern void *um_virt_to_phys(struct task_struct *task, unsigned long virt,
+ pte_t *pte_out);
+
+static inline unsigned long maybe_map(unsigned long virt, int is_write)
+{
+ pte_t pte;
+
+ void *phys = um_virt_to_phys(current, virt, &pte);
+ int dummy_code;
+
+ if(IS_ERR(phys) || (is_write && !pte_write(pte))){
+ if(handle_page_fault(virt, 0, is_write, 0, &dummy_code))
+ return(0);
+ phys = um_virt_to_phys(current, virt, NULL);
+ }
+ return((unsigned long) __va((unsigned long) phys));
+}
+
+static inline int buffer_op(unsigned long addr, int len,
+ int (*op)(unsigned long addr, int len, void *arg),
+ void *arg)
+{
+ int size = min(PAGE_ALIGN(addr) - addr, (unsigned long) len);
+ int remain = len, n;
+
+ n = (*op)(addr, size, arg);
+ if(n != 0)
+ return(n < 0 ? remain : 0);
+
+ addr += size;
+ remain -= size;
+ if(remain == 0)
+ return(0);
+
+ while(addr < ((addr + remain) & PAGE_MASK)){
+ n = (*op)(addr, PAGE_SIZE, arg);
+ if(n != 0)
+ return(n < 0 ? remain : 0);
+
+ addr += PAGE_SIZE;
+ remain -= PAGE_SIZE;
+ }
+ if(remain == 0)
+ return(0);
+
+ n = (*op)(addr, remain, arg);
+ if(n != 0)
+ return(n < 0 ? remain : 0);
+ return(0);
+}
+
+static inline int copy_chunk_from_user(unsigned long from, int len, void *arg)
+{
+ unsigned long *to_ptr = arg, to = *to_ptr;
+
+ from = maybe_map(from, 0);
+ if(from == 0)
+ return(-1);
+
+ memcpy((void *) to, (void *) from, len);
+ *to_ptr += len;
+ return(0);
+}
+
+static inline int copy_from_user_skas(void *to, const void *from, int n)
+{
+ if(segment_eq(get_fs(), KERNEL_DS)){
+ memcpy(to, from, n);
+ return(0);
+ }
+
+ return(access_ok_skas(VERIFY_READ, from, n) ?
+ buffer_op((unsigned long) from, n, copy_chunk_from_user, &to) :
+ n);
+}
+
+static inline int copy_chunk_to_user(unsigned long to, int len, void *arg)
+{
+ unsigned long *from_ptr = arg, from = *from_ptr;
+
+ to = maybe_map(to, 1);
+ if(to == 0)
+ return(-1);
+
+ memcpy((void *) to, (void *) from, len);
+ *from_ptr += len;
+ return(0);
+}
+
+static inline int copy_to_user_skas(void *to, const void *from, int n)
+{
+ if(segment_eq(get_fs(), KERNEL_DS)){
+ memcpy(to, from, n);
+ return(0);
+ }
+
+ return(access_ok_skas(VERIFY_WRITE, to, n) ?
+ buffer_op((unsigned long) to, n, copy_chunk_to_user, &from) :
+ n);
+}
+
+static inline int strncpy_chunk_from_user(unsigned long from, int len,
+ void *arg)
+{
+ char **to_ptr = arg, *to = *to_ptr;
+ int n;
+
+ from = maybe_map(from, 0);
+ if(from == 0)
+ return(-1);
+
+ strncpy(to, (void *) from, len);
+ n = strnlen(to, len);
+ *to_ptr += n;
+
+ if(n < len)
+ return(1);
+ return(0);
+}
+
+static inline int strncpy_from_user_skas(char *dst, const char *src, int count)
+{
+ int n;
+ char *ptr = dst;
+
+ if(segment_eq(get_fs(), KERNEL_DS)){
+ strncpy(dst, src, count);
+ return(strnlen(dst, count));
+ }
+
+ if(!access_ok_skas(VERIFY_READ, src, 1))
+ return(-EFAULT);
+
+ n = buffer_op((unsigned long) src, count, strncpy_chunk_from_user,
+ &ptr);
+ if(n != 0)
+ return(-EFAULT);
+ return(strnlen(dst, count));
+}
+
+static inline int clear_chunk(unsigned long addr, int len, void *unused)
+{
+ addr = maybe_map(addr, 1);
+ if(addr == 0)
+ return(-1);
+
+ memset((void *) addr, 0, len);
+ return(0);
+}
+
+static inline int __clear_user_skas(void *mem, int len)
+{
+ return(buffer_op((unsigned long) mem, len, clear_chunk, NULL));
+}
+
+static inline int clear_user_skas(void *mem, int len)
+{
+ if(segment_eq(get_fs(), KERNEL_DS)){
+ memset(mem, 0, len);
+ return(0);
+ }
+
+ return(access_ok_skas(VERIFY_WRITE, mem, len) ?
+ buffer_op((unsigned long) mem, len, clear_chunk, NULL) : len);
+}
+
+static inline int strnlen_chunk(unsigned long str, int len, void *arg)
+{
+ int *len_ptr = arg, n;
+
+ str = maybe_map(str, 0);
+ if(str == 0)
+ return(-1);
+
+ n = strnlen((void *) str, len);
+ *len_ptr += n;
+
+ if(n < len)
+ return(1);
+ return(0);
+}
+
+static inline int strnlen_user_skas(const void *str, int len)
+{
+ int count = 0, n;
+
+ if(segment_eq(get_fs(), KERNEL_DS))
+ return(strnlen(str, len) + 1);
+
+ n = buffer_op((unsigned long) str, len, strnlen_chunk, &count);
+ if(n == 0)
+ return(count + 1);
+ return(-EFAULT);
+}
+
+#endif
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only. This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff --git a/arch/um/kernel/skas/mem.c b/arch/um/kernel/skas/mem.c
new file mode 100644
index 000000000000..0968b583473a
--- /dev/null
+++ b/arch/um/kernel/skas/mem.c
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#include "linux/config.h"
+#include "linux/mm.h"
+#include "mem_user.h"
+
+unsigned long set_task_sizes_skas(int arg, unsigned long *host_size_out,
+ unsigned long *task_size_out)
+{
+ /* Round up to the nearest 4M */
+ unsigned long top = ROUND_4M((unsigned long) &arg);
+
+ *host_size_out = top;
+ *task_size_out = top;
+ return(((unsigned long) set_task_sizes_skas) & ~0xffffff);
+}
+
+struct page *arch_validate_skas(struct page *page, int mask, int order)
+{
+ return(page);
+}
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only. This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff --git a/arch/um/kernel/skas/mem_user.c b/arch/um/kernel/skas/mem_user.c
new file mode 100644
index 000000000000..7d12cdd621ae
--- /dev/null
+++ b/arch/um/kernel/skas/mem_user.c
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#include <errno.h>
+#include <sys/mman.h>
+#include <sys/ptrace.h>
+#include "mem_user.h"
+#include "user.h"
+#include "os.h"
+#include "proc_mm.h"
+
+void map(int fd, unsigned long virt, unsigned long phys, unsigned long len,
+ int r, int w, int x)
+{
+ struct proc_mm_op map;
+ struct mem_region *region;
+ int prot, n;
+
+ prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) |
+ (x ? PROT_EXEC : 0);
+ region = phys_region(phys);
+
+ map = ((struct proc_mm_op) { .op = MM_MMAP,
+ .u =
+ { .mmap =
+ { .addr = virt,
+ .len = len,
+ .prot = prot,
+ .flags = MAP_SHARED |
+ MAP_FIXED,
+ .fd = region->fd,
+ .offset = phys_offset(phys)
+ } } } );
+ n = os_write_file(fd, (char *) &map, sizeof(map));
+ if(n != sizeof(map))
+ printk("map : /proc/mm map failed, errno = %d\n", errno);
+}
+
+int unmap(int fd, void *addr, int len)
+{
+ struct proc_mm_op unmap;
+ int n;
+
+ unmap = ((struct proc_mm_op) { .op = MM_MUNMAP,
+ .u =
+ { .munmap =
+ { .addr = (unsigned long) addr,
+ .len = len } } } );
+ n = os_write_file(fd, (char *) &unmap, sizeof(unmap));
+ if((n != 0) && (n != sizeof(unmap)))
+ return(-errno);
+ return(0);
+}
+
+int protect(int fd, unsigned long addr, unsigned long len, int r, int w,
+ int x, int must_succeed)
+{
+ struct proc_mm_op protect;
+ int prot, n;
+
+ prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) |
+ (x ? PROT_EXEC : 0);
+
+ protect = ((struct proc_mm_op) { .op = MM_MPROTECT,
+ .u =
+ { .mprotect =
+ { .addr = (unsigned long) addr,
+ .len = len,
+ .prot = prot } } } );
+
+ n = os_write_file(fd, (char *) &protect, sizeof(protect));
+ if((n != 0) && (n != sizeof(protect))){
+ if(must_succeed)
+ panic("protect failed, errno = %d", errno);
+ return(-errno);
+ }
+ return(0);
+}
+
+void before_mem_skas(unsigned long unused)
+{
+}
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only. This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff --git a/arch/um/kernel/skas/mmu.c b/arch/um/kernel/skas/mmu.c
new file mode 100644
index 000000000000..5911cdd0c0b7
--- /dev/null
+++ b/arch/um/kernel/skas/mmu.c
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#include "linux/sched.h"
+#include "linux/list.h"
+#include "linux/spinlock.h"
+#include "linux/slab.h"
+#include "asm/current.h"
+#include "asm/segment.h"
+#include "asm/mmu.h"
+#include "os.h"
+#include "skas.h"
+
+int init_new_context_skas(struct task_struct *task, struct mm_struct *mm)
+{
+ int from;
+
+ if((current->mm != NULL) && (current->mm != &init_mm))
+ from = current->mm->context.skas.mm_fd;
+ else from = -1;
+
+ mm->context.skas.mm_fd = new_mm(from);
+ if(mm->context.skas.mm_fd < 0)
+ panic("init_new_context_skas - new_mm failed, errno = %d\n",
+ mm->context.skas.mm_fd);
+
+ return(0);
+}
+
+void destroy_context_skas(struct mm_struct *mm)
+{
+ os_close_file(mm->context.skas.mm_fd);
+}
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only. This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff --git a/arch/um/kernel/skas/process.c b/arch/um/kernel/skas/process.c
new file mode 100644
index 000000000000..15a1fd345178
--- /dev/null
+++ b/arch/um/kernel/skas/process.c
@@ -0,0 +1,386 @@
+/*
+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#include <stdlib.h>
+#include <errno.h>
+#include <signal.h>
+#include <setjmp.h>
+#include <sched.h>
+#include <sys/wait.h>
+#include <sys/ptrace.h>
+#include <sys/mman.h>
+#include <sys/user.h>
+#include <asm/unistd.h>
+#include "user.h"
+#include "ptrace_user.h"
+#include "time_user.h"
+#include "sysdep/ptrace.h"
+#include "user_util.h"
+#include "kern_util.h"
+#include "skas.h"
+#include "skas_ptrace.h"
+#include "sysdep/sigcontext.h"
+#include "os.h"
+#include "proc_mm.h"
+
+unsigned long exec_regs[FRAME_SIZE];
+unsigned long exec_fp_regs[HOST_FP_SIZE];
+unsigned long exec_fpx_regs[HOST_XFP_SIZE];
+int have_fpx_regs = 1;
+
+static void handle_segv(int pid)
+{
+ struct ptrace_faultinfo fault;
+ int err;
+
+ err = ptrace(PTRACE_FAULTINFO, pid, 0, &fault);
+ if(err)
+ panic("handle_segv - PTRACE_FAULTINFO failed, errno = %d\n",
+ errno);
+ segv(fault.addr, 0, FAULT_WRITE(fault.is_write), 1, NULL);
+}
+
+static void handle_trap(int pid, struct uml_pt_regs *regs)
+{
+ int err, syscall_nr, status;
+
+ syscall_nr = PT_SYSCALL_NR(regs->mode.skas.regs);
+ if(syscall_nr < 1){
+ relay_signal(SIGTRAP, regs);
+ return;
+ }
+ UPT_SYSCALL_NR(regs) = syscall_nr;
+
+ err = ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_NR_OFFSET, __NR_getpid);
+ if(err < 0)
+ panic("handle_trap - nullifying syscall failed errno = %d\n",
+ errno);
+
+ err = ptrace(PTRACE_SYSCALL, pid, 0, 0);
+ if(err < 0)
+ panic("handle_trap - continuing to end of syscall failed, "
+ "errno = %d\n", errno);
+
+ err = waitpid(pid, &status, WUNTRACED);
+ if((err < 0) || !WIFSTOPPED(status) || (WSTOPSIG(status) != SIGTRAP))
+ panic("handle_trap - failed to wait at end of syscall, "
+ "errno = %d, status = %d\n", errno, status);
+
+ handle_syscall(regs);
+}
+
+int userspace_pid;
+
+static int userspace_tramp(void *arg)
+{
+ init_new_thread_signals(0);
+ enable_timer();
+ ptrace(PTRACE_TRACEME, 0, 0, 0);
+ os_stop_process(os_getpid());
+}
+
+void start_userspace(void)
+{
+ void *stack;
+ unsigned long sp;
+ int pid, status, n;
+
+ stack = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC,
+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+ if(stack == MAP_FAILED)
+ panic("start_userspace : mmap failed, errno = %d", errno);
+ sp = (unsigned long) stack + PAGE_SIZE - sizeof(void *);
+
+ pid = clone(userspace_tramp, (void *) sp,
+ CLONE_FILES | CLONE_VM | SIGCHLD, NULL);
+ if(pid < 0)
+ panic("start_userspace : clone failed, errno = %d", errno);
+
+ do {
+ n = waitpid(pid, &status, WUNTRACED);
+ if(n < 0)
+ panic("start_userspace : wait failed, errno = %d",
+ errno);
+ } while(WIFSTOPPED(status) && (WSTOPSIG(status) == SIGVTALRM));
+
+ if(!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGSTOP))
+ panic("start_userspace : expected SIGSTOP, got status = %d",
+ status);
+
+ if(munmap(stack, PAGE_SIZE) < 0)
+ panic("start_userspace : munmap failed, errno = %d\n", errno);
+
+ userspace_pid = pid;
+}
+
+void userspace(struct uml_pt_regs *regs)
+{
+ int err, status, op;
+
+ restore_registers(regs);
+
+ err = ptrace(PTRACE_SYSCALL, userspace_pid, 0, 0);
+ if(err)
+ panic("userspace - PTRACE_SYSCALL failed, errno = %d\n",
+ errno);
+ while(1){
+ err = waitpid(userspace_pid, &status, WUNTRACED);
+ if(err < 0)
+ panic("userspace - waitpid failed, errno = %d\n",
+ errno);
+
+ regs->is_user = 1;
+ save_registers(regs);
+
+ if(WIFSTOPPED(status)){
+ switch(WSTOPSIG(status)){
+ case SIGSEGV:
+ handle_segv(userspace_pid);
+ break;
+ case SIGTRAP:
+ handle_trap(userspace_pid, regs);
+ break;
+ case SIGIO:
+ case SIGVTALRM:
+ case SIGILL:
+ case SIGBUS:
+ case SIGFPE:
+ user_signal(WSTOPSIG(status), regs);
+ break;
+ default:
+ printk("userspace - child stopped with signal "
+ "%d\n", WSTOPSIG(status));
+ }
+ interrupt_end();
+ }
+
+ restore_registers(regs);
+
+ op = singlestepping_skas() ? PTRACE_SINGLESTEP :
+ PTRACE_SYSCALL;
+ err = ptrace(op, userspace_pid, 0, 0);
+ if(err)
+ panic("userspace - PTRACE_SYSCALL failed, "
+ "errno = %d\n", errno);
+ }
+}
+
+void new_thread(void *stack, void **switch_buf_ptr, void **fork_buf_ptr,
+ void (*handler)(int))
+{
+ jmp_buf switch_buf, fork_buf;
+
+ *switch_buf_ptr = &switch_buf;
+ *fork_buf_ptr = &fork_buf;
+
+ if(setjmp(fork_buf) == 0)
+ new_thread_proc(stack, handler);
+
+ remove_sigstack();
+}
+
+void thread_wait(void *sw, void *fb)
+{
+ jmp_buf buf, **switch_buf = sw, *fork_buf;
+
+ *switch_buf = &buf;
+ fork_buf = fb;
+ if(setjmp(buf) == 0)
+ longjmp(*fork_buf, 1);
+}
+
+static int move_registers(int int_op, int fp_op, struct uml_pt_regs *regs,
+ unsigned long *fp_regs)
+{
+ if(ptrace(int_op, userspace_pid, 0, regs->mode.skas.regs) < 0)
+ return(-errno);
+ if(ptrace(fp_op, userspace_pid, 0, fp_regs) < 0)
+ return(-errno);
+ return(0);
+}
+
+void save_registers(struct uml_pt_regs *regs)
+{
+ unsigned long *fp_regs;
+ int err, fp_op;
+
+ if(have_fpx_regs){
+ fp_op = PTRACE_GETFPXREGS;
+ fp_regs = regs->mode.skas.xfp;
+ }
+ else {
+ fp_op = PTRACE_GETFPREGS;
+ fp_regs = regs->mode.skas.fp;
+ }
+
+ err = move_registers(PTRACE_GETREGS, fp_op, regs, fp_regs);
+ if(err)
+ panic("save_registers - saving registers failed, errno = %d\n",
+ err);
+}
+
+void restore_registers(struct uml_pt_regs *regs)
+{
+ unsigned long *fp_regs;
+ int err, fp_op;
+
+ if(have_fpx_regs){
+ fp_op = PTRACE_SETFPXREGS;
+ fp_regs = regs->mode.skas.xfp;
+ }
+ else {
+ fp_op = PTRACE_SETFPREGS;
+ fp_regs = regs->mode.skas.fp;
+ }
+
+ err = move_registers(PTRACE_SETREGS, fp_op, regs, fp_regs);
+ if(err)
+ panic("restore_registers - saving registers failed, "
+ "errno = %d\n", err);
+}
+
+void switch_threads(void *me, void *next)
+{
+ jmp_buf my_buf, **me_ptr = me, *next_buf = next;
+
+ *me_ptr = &my_buf;
+ if(setjmp(my_buf) == 0)
+ longjmp(*next_buf, 1);
+}
+
+static jmp_buf initial_jmpbuf;
+
+/* XXX Make these percpu */
+static void (*cb_proc)(void *arg);
+static void *cb_arg;
+static jmp_buf *cb_back;
+
+int start_idle_thread(void *stack, void *switch_buf_ptr, void **fork_buf_ptr)
+{
+ jmp_buf **switch_buf = switch_buf_ptr;
+ int n;
+
+ *fork_buf_ptr = &initial_jmpbuf;
+ n = setjmp(initial_jmpbuf);
+ if(n == 0)
+ new_thread_proc((void *) stack, new_thread_handler);
+ else if(n == 1)
+ remove_sigstack();
+ else if(n == 2){
+ (*cb_proc)(cb_arg);
+ longjmp(*cb_back, 1);
+ }
+ else if(n == 3)
+ return(0);
+ else if(n == 4)
+ return(1);
+ longjmp(**switch_buf, 1);
+}
+
+void remove_sigstack(void)
+{
+ stack_t stack = ((stack_t) { .ss_flags = SS_DISABLE,
+ .ss_sp = NULL,
+ .ss_size = 0 });
+
+ if(sigaltstack(&stack, NULL) != 0)
+ panic("disabling signal stack failed, errno = %d\n", errno);
+}
+
+void initial_thread_cb_skas(void (*proc)(void *), void *arg)
+{
+ jmp_buf here;
+
+ cb_proc = proc;
+ cb_arg = arg;
+ cb_back = &here;
+ if(setjmp(here) == 0)
+ longjmp(initial_jmpbuf, 2);
+
+ cb_proc = NULL;
+ cb_arg = NULL;
+ cb_back = NULL;
+}
+
+void halt_skas(void)
+{
+ block_signals();
+ longjmp(initial_jmpbuf, 3);
+}
+
+void reboot_skas(void)
+{
+ block_signals();
+ longjmp(initial_jmpbuf, 4);
+}
+
+int new_mm(int from)
+{
+ struct proc_mm_op copy;
+ int n, fd = os_open_file("/proc/mm", of_write(OPENFLAGS()), 0);
+
+ if(fd < 0)
+ return(-errno);
+
+ if(from != -1){
+ copy = ((struct proc_mm_op) { .op = MM_COPY_SEGMENTS,
+ .u =
+ { .copy_segments = from } } );
+ n = os_write_file(fd, (char *) &copy, sizeof(copy));
+ if(n != sizeof(copy))
+ printk("new_mm : /proc/mm copy_segments failed, "
+ "errno = %d\n", errno);
+ }
+ return(fd);
+}
+
+void switch_mm_skas(int mm_fd)
+{
+ int err;
+
+ err = ptrace(PTRACE_SWITCH_MM, userspace_pid, 0, mm_fd);
+ if(err)
+ panic("switch_mm_skas - PTRACE_SWITCH_MM failed, errno = %d\n",
+ errno);
+}
+
+void kill_off_processes_skas(void)
+{
+ os_kill_process(userspace_pid, 1);
+}
+
+void init_registers(int pid)
+{
+ int err;
+
+ if(ptrace(PTRACE_GETREGS, pid, 0, exec_regs) < 0)
+ panic("check_ptrace : PTRACE_GETREGS failed, errno = %d",
+ errno);
+
+ err = ptrace(PTRACE_GETFPXREGS, pid, 0, exec_fpx_regs);
+ if(!err)
+ return;
+
+ have_fpx_regs = 0;
+ if(errno != EIO)
+ panic("check_ptrace : PTRACE_GETFPXREGS failed, errno = %d",
+ errno);
+
+ err = ptrace(PTRACE_GETFPREGS, pid, 0, exec_fp_regs);
+ if(err)
+ panic("check_ptrace : PTRACE_GETFPREGS failed, errno = %d",
+ errno);
+}
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only. This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff --git a/arch/um/kernel/skas/process_kern.c b/arch/um/kernel/skas/process_kern.c
new file mode 100644
index 000000000000..ed17599d2c56
--- /dev/null
+++ b/arch/um/kernel/skas/process_kern.c
@@ -0,0 +1,195 @@
+/*
+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#include "linux/sched.h"
+#include "linux/slab.h"
+#include "kern_util.h"
+#include "time_user.h"
+#include "signal_user.h"
+#include "skas.h"
+#include "os.h"
+#include "user_util.h"
+#include "tlb.h"
+#include "frame.h"
+#include "kern.h"
+#include "mode.h"
+
+int singlestepping_skas(void)
+{
+ int ret = current->ptrace & PT_DTRACE;
+
+ current->ptrace &= ~PT_DTRACE;
+ return(ret);
+}
+
+void *switch_to_skas(void *prev, void *next)
+{
+ struct task_struct *from, *to;
+
+ from = prev;
+ to = next;
+
+ /* XXX need to check runqueues[cpu].idle */
+ if(current->pid == 0)
+ switch_timers(0);
+
+ to->thread.prev_sched = from;
+ set_current(to);
+
+ switch_threads(&from->thread.mode.skas.switch_buf,
+ to->thread.mode.skas.switch_buf);
+
+ if(current->pid == 0)
+ switch_timers(1);
+
+ return(current->thread.prev_sched);
+}
+
+extern void schedule_tail(struct task_struct *prev);
+
+void new_thread_handler(int sig)
+{
+ int (*fn)(void *), n;
+ void *arg;
+
+ fn = current->thread.request.u.thread.proc;
+ arg = current->thread.request.u.thread.arg;
+ change_sig(SIGUSR1, 1);
+ thread_wait(&current->thread.mode.skas.switch_buf,
+ current->thread.mode.skas.fork_buf);
+
+#ifdef CONFIG_SMP
+ schedule_tail(NULL);
+#endif
+ current->thread.prev_sched = NULL;
+
+ n = run_kernel_thread(fn, arg, &current->thread.exec_buf);
+ if(n == 1)
+ userspace(&current->thread.regs.regs);
+ else if(n == 2)
+ do_exit(0);
+}
+
+void new_thread_proc(void *stack, void (*handler)(int sig))
+{
+ init_new_thread_stack(stack, handler);
+ os_usr1_process(os_getpid());
+}
+
+void release_thread_skas(struct task_struct *task)
+{
+}
+
+void exit_thread_skas(void)
+{
+}
+
+void fork_handler(int sig)
+{
+ change_sig(SIGUSR1, 1);
+ thread_wait(&current->thread.mode.skas.switch_buf,
+ current->thread.mode.skas.fork_buf);
+
+ force_flush_all();
+#ifdef CONFIG_SMP
+ schedule_tail(current->thread.prev_sched);
+#endif
+ current->thread.prev_sched = NULL;
+ unblock_signals();
+
+ userspace(&current->thread.regs.regs);
+}
+
+int copy_thread_skas(int nr, unsigned long clone_flags, unsigned long sp,
+ unsigned long stack_top, struct task_struct * p,
+ struct pt_regs *regs)
+{
+ void (*handler)(int);
+
+ if(current->thread.forking){
+ memcpy(&p->thread.regs.regs.mode.skas,
+ &current->thread.regs.regs.mode.skas,
+ sizeof(p->thread.regs.regs.mode.skas));
+ REGS_SET_SYSCALL_RETURN(p->thread.regs.regs.mode.skas.regs, 0);
+ if(sp != 0) REGS_SP(p->thread.regs.regs.mode.skas.regs) = sp;
+
+ handler = fork_handler;
+ }
+ else {
+ memcpy(p->thread.regs.regs.mode.skas.regs, exec_regs,
+ sizeof(p->thread.regs.regs.mode.skas.regs));
+ memcpy(p->thread.regs.regs.mode.skas.fp, exec_fp_regs,
+ sizeof(p->thread.regs.regs.mode.skas.fp));
+ memcpy(p->thread.regs.regs.mode.skas.xfp, exec_fpx_regs,
+ sizeof(p->thread.regs.regs.mode.skas.xfp));
+ p->thread.request.u.thread = current->thread.request.u.thread;
+ handler = new_thread_handler;
+ }
+
+ new_thread((void *) p->thread.kernel_stack,
+ &p->thread.mode.skas.switch_buf,
+ &p->thread.mode.skas.fork_buf, handler);
+ return(0);
+}
+
+void init_idle_skas(void)
+{
+ cpu_tasks[current->thread_info->cpu].pid = os_getpid();
+ default_idle();
+}
+
+extern void start_kernel(void);
+
+static int start_kernel_proc(void *unused)
+{
+ int pid;
+
+ block_signals();
+ pid = os_getpid();
+
+ cpu_tasks[0].pid = pid;
+ cpu_tasks[0].task = current;
+#ifdef CONFIG_SMP
+ cpu_online_map = 1;
+#endif
+ start_kernel();
+ return(0);
+}
+
+int start_uml_skas(void)
+{
+ start_userspace();
+ capture_signal_stack();
+
+ init_new_thread_signals(1);
+ idle_timer();
+
+ init_task.thread.request.u.thread.proc = start_kernel_proc;
+ init_task.thread.request.u.thread.arg = NULL;
+ return(start_idle_thread((void *) init_task.thread.kernel_stack,
+ &init_task.thread.mode.skas.switch_buf,
+ &init_task.thread.mode.skas.fork_buf));
+}
+
+int external_pid_skas(struct task_struct *task)
+{
+ return(userspace_pid);
+}
+
+int thread_pid_skas(struct task_struct *task)
+{
+ return(userspace_pid);
+}
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only. This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff --git a/arch/um/kernel/skas/sys-i386/Makefile b/arch/um/kernel/skas/sys-i386/Makefile
new file mode 100644
index 000000000000..2ad8271c604d
--- /dev/null
+++ b/arch/um/kernel/skas/sys-i386/Makefile
@@ -0,0 +1,14 @@
+#
+# Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+# Licensed under the GPL
+#
+
+obj-y = sigcontext.o
+
+USER_OBJS = sigcontext.o
+USER_OBJS := $(foreach file,$(USER_OBJS),$(obj)/$(file))
+
+$(USER_OBJS) : %.o: %.c
+ $(CC) $(CFLAGS_$(notdir $@)) $(USER_CFLAGS) -c -o $@ $<
+
+clean :
diff --git a/arch/um/kernel/skas/sys-i386/sigcontext.c b/arch/um/kernel/skas/sys-i386/sigcontext.c
new file mode 100644
index 000000000000..07bb0ea0ed8a
--- /dev/null
+++ b/arch/um/kernel/skas/sys-i386/sigcontext.c
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#include <errno.h>
+#include <asm/sigcontext.h>
+#include <sys/ptrace.h>
+#include <linux/ptrace.h>
+#include "sysdep/ptrace.h"
+#include "sysdep/ptrace_user.h"
+#include "kern_util.h"
+#include "user.h"
+#include "sigcontext.h"
+
+extern int userspace_pid;
+
+int copy_sc_from_user_skas(struct uml_pt_regs *regs, void *from_ptr)
+{
+ struct sigcontext sc, *from = from_ptr;
+ unsigned long fpregs[FP_FRAME_SIZE];
+ int err;
+
+ err = copy_from_user_proc(&sc, from, sizeof(sc));
+ err |= copy_from_user_proc(fpregs, sc.fpstate, sizeof(fpregs));
+ if(err)
+ return(err);
+
+ regs->mode.skas.regs[GS] = sc.gs;
+ regs->mode.skas.regs[FS] = sc.fs;
+ regs->mode.skas.regs[ES] = sc.es;
+ regs->mode.skas.regs[DS] = sc.ds;
+ regs->mode.skas.regs[EDI] = sc.edi;
+ regs->mode.skas.regs[ESI] = sc.esi;
+ regs->mode.skas.regs[EBP] = sc.ebp;
+ regs->mode.skas.regs[UESP] = sc.esp;
+ regs->mode.skas.regs[EBX] = sc.ebx;
+ regs->mode.skas.regs[EDX] = sc.edx;
+ regs->mode.skas.regs[ECX] = sc.ecx;
+ regs->mode.skas.regs[EAX] = sc.eax;
+ regs->mode.skas.regs[EIP] = sc.eip;
+ regs->mode.skas.regs[CS] = sc.cs;
+ regs->mode.skas.regs[EFL] = sc.eflags;
+ regs->mode.skas.regs[UESP] = sc.esp_at_signal;
+ regs->mode.skas.regs[SS] = sc.ss;
+ regs->mode.skas.fault_addr = sc.cr2;
+ regs->mode.skas.fault_type = FAULT_WRITE(sc.err);
+ regs->mode.skas.trap_type = sc.trapno;
+
+ err = ptrace(PTRACE_SETFPREGS, userspace_pid, 0, fpregs);
+ if(err < 0){
+ printk("copy_sc_to_user - PTRACE_SETFPREGS failed, "
+ "errno = %d\n", errno);
+ return(1);
+ }
+
+ return(0);
+}
+
+int copy_sc_to_user_skas(void *to_ptr, struct uml_pt_regs *regs,
+ unsigned long fault_addr, int fault_type)
+{
+ struct sigcontext sc, *to = to_ptr;
+ struct _fpstate *to_fp;
+ unsigned long fpregs[FP_FRAME_SIZE];
+ int err;
+
+ sc.gs = regs->mode.skas.regs[GS];
+ sc.fs = regs->mode.skas.regs[FS];
+ sc.es = regs->mode.skas.regs[ES];
+ sc.ds = regs->mode.skas.regs[DS];
+ sc.edi = regs->mode.skas.regs[EDI];
+ sc.esi = regs->mode.skas.regs[ESI];
+ sc.ebp = regs->mode.skas.regs[EBP];
+ sc.esp = regs->mode.skas.regs[UESP];
+ sc.ebx = regs->mode.skas.regs[EBX];
+ sc.edx = regs->mode.skas.regs[EDX];
+ sc.ecx = regs->mode.skas.regs[ECX];
+ sc.eax = regs->mode.skas.regs[EAX];
+ sc.eip = regs->mode.skas.regs[EIP];
+ sc.cs = regs->mode.skas.regs[CS];
+ sc.eflags = regs->mode.skas.regs[EFL];
+ sc.esp_at_signal = regs->mode.skas.regs[UESP];
+ sc.ss = regs->mode.skas.regs[SS];
+ sc.cr2 = fault_addr;
+ sc.err = TO_SC_ERR(fault_type);
+ sc.trapno = regs->mode.skas.trap_type;
+
+ err = ptrace(PTRACE_GETFPREGS, userspace_pid, 0, fpregs);
+ if(err < 0){
+ printk("copy_sc_to_user - PTRACE_GETFPREGS failed, "
+ "errno = %d\n", errno);
+ return(1);
+ }
+ to_fp = (struct _fpstate *)((unsigned long) to + sizeof(*to));
+ sc.fpstate = to_fp;
+
+ if(err)
+ return(err);
+
+ return(copy_to_user_proc(to, &sc, sizeof(sc)) ||
+ copy_to_user_proc(to_fp, fpregs, sizeof(fpregs)));
+}
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only. This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff --git a/arch/um/kernel/skas/syscall_kern.c b/arch/um/kernel/skas/syscall_kern.c
new file mode 100644
index 000000000000..d870870db1ac
--- /dev/null
+++ b/arch/um/kernel/skas/syscall_kern.c
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#include "linux/sys.h"
+#include "asm/errno.h"
+#include "asm/unistd.h"
+#include "asm/ptrace.h"
+#include "asm/current.h"
+#include "sysdep/syscalls.h"
+#include "kern_util.h"
+
+extern syscall_handler_t *sys_call_table[];
+
+long execute_syscall_skas(void *r)
+{
+ struct pt_regs *regs = r;
+ long res;
+ int syscall;
+
+ current->thread.nsyscalls++;
+ nsyscalls++;
+ syscall = regs->regs.syscall;
+
+ if((syscall >= NR_syscalls) || (syscall < 0))
+ res = -ENOSYS;
+ else res = EXECUTE_SYSCALL(syscall, regs);
+
+ return(res);
+}
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only. This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff --git a/arch/um/kernel/skas/syscall_user.c b/arch/um/kernel/skas/syscall_user.c
new file mode 100644
index 000000000000..4f43f5492163
--- /dev/null
+++ b/arch/um/kernel/skas/syscall_user.c
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#include <stdlib.h>
+#include <signal.h>
+#include "kern_util.h"
+#include "syscall_user.h"
+#include "sysdep/ptrace.h"
+#include "sysdep/sigcontext.h"
+
+/* XXX Bogus */
+#define ERESTARTSYS 512
+#define ERESTARTNOINTR 513
+#define ERESTARTNOHAND 514
+
+void handle_syscall(struct uml_pt_regs *regs)
+{
+ long result;
+ int index;
+
+ host_to_regs(regs);
+ index = record_syscall_start(UPT_SYSCALL_NR(regs));
+
+ syscall_trace();
+ result = execute_syscall(regs);
+
+ REGS_SET_SYSCALL_RETURN(regs->mode.skas.regs, result);
+ if((result == -ERESTARTNOHAND) || (result == -ERESTARTSYS) ||
+ (result == -ERESTARTNOINTR))
+ do_signal(result);
+
+ syscall_trace();
+ record_syscall_end(index, result);
+}
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only. This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff --git a/arch/um/kernel/skas/time.c b/arch/um/kernel/skas/time.c
new file mode 100644
index 000000000000..98091494b897
--- /dev/null
+++ b/arch/um/kernel/skas/time.c
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#include <sys/signal.h>
+#include <sys/time.h>
+#include "time_user.h"
+#include "process.h"
+#include "user.h"
+
+void user_time_init_skas(void)
+{
+ if(signal(SIGALRM, (__sighandler_t) alarm_handler) == SIG_ERR)
+ panic("Couldn't set SIGALRM handler");
+ if(signal(SIGVTALRM, (__sighandler_t) alarm_handler) == SIG_ERR)
+ panic("Couldn't set SIGVTALRM handler");
+ set_interval(ITIMER_VIRTUAL);
+}
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only. This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff --git a/arch/um/kernel/skas/tlb.c b/arch/um/kernel/skas/tlb.c
new file mode 100644
index 000000000000..655d3cdee856
--- /dev/null
+++ b/arch/um/kernel/skas/tlb.c
@@ -0,0 +1,156 @@
+/*
+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#include "linux/stddef.h"
+#include "linux/sched.h"
+#include "linux/mm.h"
+#include "asm/page.h"
+#include "asm/pgtable.h"
+#include "asm/mmu.h"
+#include "user_util.h"
+#include "mem_user.h"
+#include "skas.h"
+#include "os.h"
+
+static void fix_range(struct mm_struct *mm, unsigned long start_addr,
+ unsigned long end_addr, int force)
+{
+ pgd_t *npgd;
+ pmd_t *npmd;
+ pte_t *npte;
+ unsigned long addr;
+ int r, w, x, err, fd;
+
+ if(mm == NULL) return;
+ fd = mm->context.skas.mm_fd;
+ for(addr = start_addr; addr < end_addr;){
+ npgd = pgd_offset(mm, addr);
+ npmd = pmd_offset(npgd, addr);
+ if(pmd_present(*npmd)){
+ npte = pte_offset_kernel(npmd, addr);
+ r = pte_read(*npte);
+ w = pte_write(*npte);
+ x = pte_exec(*npte);
+ if(!pte_dirty(*npte)) w = 0;
+ if(!pte_young(*npte)){
+ r = 0;
+ w = 0;
+ }
+ if(force || pte_newpage(*npte)){
+ err = unmap(fd, (void *) addr, PAGE_SIZE);
+ if(err < 0)
+ panic("munmap failed, errno = %d\n",
+ -err);
+ if(pte_present(*npte))
+ map(fd, addr,
+ pte_val(*npte) & PAGE_MASK,
+ PAGE_SIZE, r, w, x);
+ }
+ else if(pte_newprot(*npte)){
+ protect(fd, addr, PAGE_SIZE, r, w, x, 1);
+ }
+ *npte = pte_mkuptodate(*npte);
+ addr += PAGE_SIZE;
+ }
+ else {
+ if(force || pmd_newpage(*npmd)){
+ err = unmap(fd, (void *) addr, PMD_SIZE);
+ if(err < 0)
+ panic("munmap failed, errno = %d\n",
+ -err);
+ pmd_mkuptodate(*npmd);
+ }
+ addr += PMD_SIZE;
+ }
+ }
+}
+
+static void flush_kernel_vm_range(unsigned long start, unsigned long end)
+{
+ struct mm_struct *mm;
+ pgd_t *pgd;
+ pmd_t *pmd;
+ pte_t *pte;
+ unsigned long addr;
+ int updated = 0, err;
+
+ mm = &init_mm;
+ for(addr = start_vm; addr < end_vm;){
+ pgd = pgd_offset(mm, addr);
+ pmd = pmd_offset(pgd, addr);
+ if(pmd_present(*pmd)){
+ pte = pte_offset_kernel(pmd, addr);
+ if(!pte_present(*pte) || pte_newpage(*pte)){
+ updated = 1;
+ err = os_unmap_memory((void *) addr,
+ PAGE_SIZE);
+ if(err < 0)
+ panic("munmap failed, errno = %d\n",
+ -err);
+ if(pte_present(*pte))
+ map_memory(addr,
+ pte_val(*pte) & PAGE_MASK,
+ PAGE_SIZE, 1, 1, 1);
+ }
+ else if(pte_newprot(*pte)){
+ updated = 1;
+ protect_memory(addr, PAGE_SIZE, 1, 1, 1, 1);
+ }
+ addr += PAGE_SIZE;
+
+ }
+ else {
+ if(pmd_newpage(*pmd)){
+ updated = 1;
+ err = os_unmap_memory((void *) addr, PMD_SIZE);
+ if(err < 0)
+ panic("munmap failed, errno = %d\n",
+ -err);
+ }
+ addr += PMD_SIZE;
+ }
+ }
+}
+
+void flush_tlb_kernel_vm_skas(void)
+{
+ flush_kernel_vm_range(start_vm, end_vm);
+}
+
+void __flush_tlb_one_skas(unsigned long addr)
+{
+ flush_kernel_vm_range(addr, addr + PAGE_SIZE);
+}
+
+void flush_tlb_range_skas(struct vm_area_struct *vma, unsigned long start,
+ unsigned long end)
+{
+ if(vma->vm_mm == NULL)
+ flush_kernel_vm_range(start, end);
+ else fix_range(vma->vm_mm, start, end, 0);
+}
+
+void flush_tlb_mm_skas(struct mm_struct *mm)
+{
+ if(mm == NULL)
+ flush_tlb_kernel_vm_skas();
+ else fix_range(mm, 0, host_task_size, 0);
+}
+
+void force_flush_all_skas(void)
+{
+ fix_range(current->mm, 0, host_task_size, 1);
+}
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only. This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff --git a/arch/um/kernel/skas/trap_user.c b/arch/um/kernel/skas/trap_user.c
new file mode 100644
index 000000000000..e906e5a630cb
--- /dev/null
+++ b/arch/um/kernel/skas/trap_user.c
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#include <signal.h>
+#include <errno.h>
+#include <asm/sigcontext.h>
+#include "sysdep/ptrace.h"
+#include "signal_user.h"
+#include "user_util.h"
+#include "kern_util.h"
+#include "task.h"
+#include "sigcontext.h"
+
+void sig_handler_common_skas(int sig, struct sigcontext *sc)
+{
+ struct uml_pt_regs save_regs, *r;
+ struct signal_info *info;
+ int save_errno = errno;
+
+ r = (struct uml_pt_regs *) TASK_REGS(get_current());
+ save_regs = *r;
+ r->is_user = 0;
+ r->mode.skas.fault_addr = SC_FAULT_ADDR(sc);
+ r->mode.skas.fault_type = SC_FAULT_TYPE(sc);
+ r->mode.skas.trap_type = SC_TRAP_TYPE(sc);
+
+ change_sig(SIGUSR1, 1);
+ info = &sig_info[sig];
+ if(!info->is_irq) unblock_signals();
+
+ (*info->handler)(sig, r);
+
+ *r = save_regs;
+ errno = save_errno;
+}
+
+extern int missed_ticks[];
+
+void user_signal(int sig, struct uml_pt_regs *regs)
+{
+ struct signal_info *info;
+
+ if(sig == SIGVTALRM)
+ missed_ticks[cpu()]++;
+ regs->is_user = 1;
+ regs->mode.skas.fault_addr = 0;
+ regs->mode.skas.fault_type = 0;
+ regs->mode.skas.trap_type = 0;
+ info = &sig_info[sig];
+ (*info->handler)(sig, regs);
+
+ unblock_signals();
+}
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only. This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff --git a/arch/um/kernel/skas/util/Makefile b/arch/um/kernel/skas/util/Makefile
new file mode 100644
index 000000000000..e62dc253e895
--- /dev/null
+++ b/arch/um/kernel/skas/util/Makefile
@@ -0,0 +1,10 @@
+all: mk_ptregs
+
+mk_ptregs : mk_ptregs.o
+ $(CC) -o mk_ptregs mk_ptregs.o
+
+mk_ptregs.o : mk_ptregs.c
+ $(CC) -c $<
+
+clean :
+ $(RM) -f mk_ptregs *.o *~
diff --git a/arch/um/kernel/skas/util/mk_ptregs.c b/arch/um/kernel/skas/util/mk_ptregs.c
new file mode 100644
index 000000000000..658791017373
--- /dev/null
+++ b/arch/um/kernel/skas/util/mk_ptregs.c
@@ -0,0 +1,50 @@
+#include <asm/ptrace.h>
+#include <asm/user.h>
+
+#define PRINT_REG(name, val) printf("#define HOST_%s %d\n", (name), (val))
+
+int main(int argc, char **argv)
+{
+ printf("/* Automatically generated by "
+ "arch/um/kernel/skas/util/mk_ptregs */\n");
+ printf("\n");
+ printf("#ifndef __SKAS_PT_REGS_\n");
+ printf("#define __SKAS_PT_REGS_\n");
+ printf("\n");
+ printf("#define HOST_FRAME_SIZE %d\n", FRAME_SIZE);
+ printf("#define HOST_FP_SIZE %d\n",
+ sizeof(struct user_i387_struct) / sizeof(unsigned long));
+ printf("#define HOST_XFP_SIZE %d\n",
+ sizeof(struct user_fxsr_struct) / sizeof(unsigned long));
+
+ PRINT_REG("IP", EIP);
+ PRINT_REG("SP", UESP);
+ PRINT_REG("EFLAGS", EFL);
+ PRINT_REG("EAX", EAX);
+ PRINT_REG("EBX", EBX);
+ PRINT_REG("ECX", ECX);
+ PRINT_REG("EDX", EDX);
+ PRINT_REG("ESI", ESI);
+ PRINT_REG("EDI", EDI);
+ PRINT_REG("EBP", EBP);
+ PRINT_REG("CS", CS);
+ PRINT_REG("SS", SS);
+ PRINT_REG("DS", DS);
+ PRINT_REG("FS", FS);
+ PRINT_REG("ES", ES);
+ PRINT_REG("GS", GS);
+ printf("\n");
+ printf("#endif\n");
+ return(0);
+}
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only. This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff --git a/arch/um/kernel/smp.c b/arch/um/kernel/smp.c
index c9d9b15789d1..3503ed13f59a 100644
--- a/arch/um/kernel/smp.c
+++ b/arch/um/kernel/smp.c
@@ -116,7 +116,8 @@ static int idle_proc(void *cpup)
panic("CPU#%d failed to create IPI pipe, errno = %d", cpu,
-err);
- activate_ipi(cpu_data[cpu].ipi_pipe[0], current->thread.extern_pid);
+ activate_ipi(cpu_data[cpu].ipi_pipe[0],
+ current->thread.mode.tt.extern_pid);
wmb();
if (test_and_set_bit(cpu, &smp_callin_map)) {
@@ -143,10 +144,12 @@ static struct task_struct *idle_thread(int cpu)
if(IS_ERR(new_task)) panic("do_fork failed in idle_thread");
cpu_tasks[cpu] = ((struct cpu_task)
- { .pid = new_task->thread.extern_pid,
+ { .pid = new_task->thread.mode.tt.extern_pid,
.task = new_task } );
idle_threads[cpu] = new_task;
- write(new_task->thread.switch_pipe[1], &c, sizeof(c));
+ CHOOSE_MODE(write(new_task->thread.mode.tt.switch_pipe[1], &c,
+ sizeof(c)),
+ ({ panic("skas mode doesn't support SMP"); }));
return(new_task);
}
@@ -162,7 +165,8 @@ void smp_prepare_cpus(unsigned int maxcpus)
err = os_pipe(cpu_data[0].ipi_pipe, 1, 1);
if(err) panic("CPU#0 failed to create IPI pipe, errno = %d", -err);
- activate_ipi(cpu_data[0].ipi_pipe[0], current->thread.extern_pid);
+ activate_ipi(cpu_data[0].ipi_pipe[0],
+ current->thread.mode.tt.extern_pid);
for(cpu = 1; cpu < ncpus; cpu++){
printk("Booting processor %d...\n", cpu);
diff --git a/arch/um/kernel/sys_call_table.c b/arch/um/kernel/sys_call_table.c
index f76c35dc568b..f54c2ae723b5 100644
--- a/arch/um/kernel/sys_call_table.c
+++ b/arch/um/kernel/sys_call_table.c
@@ -8,10 +8,12 @@
#include "linux/version.h"
#include "linux/sys.h"
#include "linux/swap.h"
+#include "linux/sysctl.h"
#include "asm/signal.h"
#include "sysdep/syscalls.h"
#include "kern_util.h"
+extern syscall_handler_t sys_restart_syscall;
extern syscall_handler_t sys_ni_syscall;
extern syscall_handler_t sys_exit;
extern syscall_handler_t sys_fork;
@@ -125,10 +127,8 @@ extern syscall_handler_t sys_ni_syscall;
extern syscall_handler_t sys_adjtimex;
extern syscall_handler_t sys_mprotect;
extern syscall_handler_t sys_sigprocmask;
-extern syscall_handler_t sys_create_module;
extern syscall_handler_t sys_init_module;
extern syscall_handler_t sys_delete_module;
-extern syscall_handler_t sys_get_kernel_syms;
extern syscall_handler_t sys_quotactl;
extern syscall_handler_t sys_getpgid;
extern syscall_handler_t sys_fchdir;
@@ -162,7 +162,6 @@ extern syscall_handler_t sys_mremap;
extern syscall_handler_t sys_setresuid16;
extern syscall_handler_t sys_getresuid16;
extern syscall_handler_t sys_ni_syscall;
-extern syscall_handler_t sys_query_module;
extern syscall_handler_t sys_poll;
extern syscall_handler_t sys_nfsservctl;
extern syscall_handler_t sys_setresgid16;
@@ -235,9 +234,10 @@ extern syscall_handler_t sys_epoll_create;
extern syscall_handler_t sys_epoll_ctl;
extern syscall_handler_t sys_epoll_wait;
extern syscall_handler_t sys_remap_file_pages;
+extern syscall_handler_t sys_set_tid_address;
#if CONFIG_NFSD
-#define NFSSERVCTL sys_nfsserctl
+#define NFSSERVCTL sys_nfsservctl
#else
#define NFSSERVCTL sys_ni_syscall
#endif
@@ -246,7 +246,7 @@ extern syscall_handler_t um_mount;
extern syscall_handler_t um_time;
extern syscall_handler_t um_stime;
-#define LAST_GENERIC_SYSCALL __NR_remap_file_pages
+#define LAST_GENERIC_SYSCALL __NR_set_tid_address
#if LAST_GENERIC_SYSCALL > LAST_ARCH_SYSCALL
#define LAST_SYSCALL LAST_GENERIC_SYSCALL
@@ -255,7 +255,7 @@ extern syscall_handler_t um_stime;
#endif
syscall_handler_t *sys_call_table[] = {
- [ 0 ] = sys_ni_syscall,
+ [ __NR_restart_syscall ] = sys_restart_syscall,
[ __NR_exit ] = sys_exit,
[ __NR_fork ] = sys_fork,
[ __NR_read ] = (syscall_handler_t *) sys_read,
@@ -384,10 +384,10 @@ syscall_handler_t *sys_call_table[] = {
[ __NR_adjtimex ] = sys_adjtimex,
[ __NR_mprotect ] = sys_mprotect,
[ __NR_sigprocmask ] = sys_sigprocmask,
- [ __NR_create_module ] = sys_create_module,
+ [ __NR_create_module ] = sys_ni_syscall,
[ __NR_init_module ] = sys_init_module,
[ __NR_delete_module ] = sys_delete_module,
- [ __NR_get_kernel_syms ] = sys_get_kernel_syms,
+ [ __NR_get_kernel_syms ] = sys_ni_syscall,
[ __NR_quotactl ] = sys_quotactl,
[ __NR_getpgid ] = sys_getpgid,
[ __NR_fchdir ] = sys_fchdir,
@@ -424,7 +424,7 @@ syscall_handler_t *sys_call_table[] = {
[ __NR_setresuid ] = sys_setresuid16,
[ __NR_getresuid ] = sys_getresuid16,
[ __NR_vm86 ] = sys_ni_syscall,
- [ __NR_query_module ] = sys_query_module,
+ [ __NR_query_module ] = sys_ni_syscall,
[ __NR_poll ] = sys_poll,
[ __NR_nfsservctl ] = NFSSERVCTL,
[ __NR_setresgid ] = sys_setresgid16,
@@ -489,6 +489,7 @@ syscall_handler_t *sys_call_table[] = {
[ __NR_epoll_ctl ] = sys_epoll_ctl,
[ __NR_epoll_wait ] = sys_epoll_wait,
[ __NR_remap_file_pages ] = sys_remap_file_pages,
+ [ __NR_set_tid_address ] = sys_set_tid_address,
ARCH_SYSCALLS
[ LAST_SYSCALL + 1 ... NR_syscalls ] =
diff --git a/arch/um/kernel/syscall_kern.c b/arch/um/kernel/syscall_kern.c
index b15340a6b837..bcebea22c940 100644
--- a/arch/um/kernel/syscall_kern.c
+++ b/arch/um/kernel/syscall_kern.c
@@ -20,6 +20,11 @@
#include "kern_util.h"
#include "user_util.h"
#include "sysdep/syscalls.h"
+#include "mode_kern.h"
+#include "choose-mode.h"
+
+/* Unlocked, I don't care if this is a bit off */
+int nsyscalls = 0;
long um_mount(char * dev_name, char * dir_name, char * type,
unsigned long new_flags, void * data)
@@ -33,7 +38,7 @@ long sys_fork(void)
struct task_struct *p;
current->thread.forking = 1;
- p = do_fork(SIGCHLD, 0, NULL, 0, NULL);
+ p = do_fork(SIGCHLD, 0, NULL, 0, NULL, NULL);
current->thread.forking = 0;
return(IS_ERR(p) ? PTR_ERR(p) : p->pid);
}
@@ -43,7 +48,7 @@ long sys_clone(unsigned long clone_flags, unsigned long newsp)
struct task_struct *p;
current->thread.forking = 1;
- p = do_fork(clone_flags, newsp, NULL, 0, NULL);
+ p = do_fork(clone_flags, newsp, NULL, 0, NULL, NULL);
current->thread.forking = 0;
return(IS_ERR(p) ? PTR_ERR(p) : p->pid);
}
@@ -53,7 +58,7 @@ long sys_vfork(void)
struct task_struct *p;
current->thread.forking = 1;
- p = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, 0, NULL, 0, NULL);
+ p = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, 0, NULL, 0, NULL, NULL);
current->thread.forking = 0;
return(IS_ERR(p) ? PTR_ERR(p) : p->pid);
}
@@ -182,7 +187,11 @@ int sys_ipc (uint call, int first, int second,
switch (call) {
case SEMOP:
- return sys_semop (first, (struct sembuf *)ptr, second);
+ return sys_semtimedop(first, (struct sembuf *) ptr, second,
+ NULL);
+ case SEMTIMEDOP:
+ return sys_semtimedop(first, (struct sembuf *) ptr, second,
+ (const struct timespec *) fifth);
case SEMGET:
return sys_semget (first, second, third);
case SEMCTL: {
@@ -298,122 +307,9 @@ int sys_sigaltstack(const stack_t *uss, stack_t *uoss)
return(do_sigaltstack(uss, uoss, PT_REGS_SP(&current->thread.regs)));
}
-static inline int check_area(void *ptr, int size)
-{
- return(verify_area(VERIFY_WRITE, ptr, size));
-}
-
-static int check_readlink(struct pt_regs *regs)
-{
- return(check_area((void *) regs->regs.args[1], regs->regs.args[2]));
-}
-
-static int check_utime(struct pt_regs *regs)
-{
- return(check_area((void *) regs->regs.args[1],
- sizeof(struct utimbuf)));
-}
-
-static int check_oldstat(struct pt_regs *regs)
-{
- return(check_area((void *) regs->regs.args[1],
- sizeof(struct __old_kernel_stat)));
-}
-
-static int check_stat(struct pt_regs *regs)
-{
- return(check_area((void *) regs->regs.args[1], sizeof(struct stat)));
-}
-
-static int check_stat64(struct pt_regs *regs)
-{
- return(check_area((void *) regs->regs.args[1], sizeof(struct stat64)));
-}
-
-struct bogus {
- int kernel_ds;
- int (*check_params)(struct pt_regs *);
-};
-
-struct bogus this_is_bogus[256] = {
- [ __NR_mknod ] = { 1, NULL },
- [ __NR_mkdir ] = { 1, NULL },
- [ __NR_rmdir ] = { 1, NULL },
- [ __NR_unlink ] = { 1, NULL },
- [ __NR_symlink ] = { 1, NULL },
- [ __NR_link ] = { 1, NULL },
- [ __NR_rename ] = { 1, NULL },
- [ __NR_umount ] = { 1, NULL },
- [ __NR_mount ] = { 1, NULL },
- [ __NR_pivot_root ] = { 1, NULL },
- [ __NR_chdir ] = { 1, NULL },
- [ __NR_chroot ] = { 1, NULL },
- [ __NR_open ] = { 1, NULL },
- [ __NR_quotactl ] = { 1, NULL },
- [ __NR_sysfs ] = { 1, NULL },
- [ __NR_readlink ] = { 1, check_readlink },
- [ __NR_acct ] = { 1, NULL },
- [ __NR_execve ] = { 1, NULL },
- [ __NR_uselib ] = { 1, NULL },
- [ __NR_statfs ] = { 1, NULL },
- [ __NR_truncate ] = { 1, NULL },
- [ __NR_access ] = { 1, NULL },
- [ __NR_chmod ] = { 1, NULL },
- [ __NR_chown ] = { 1, NULL },
- [ __NR_lchown ] = { 1, NULL },
- [ __NR_utime ] = { 1, check_utime },
- [ __NR_oldlstat ] = { 1, check_oldstat },
- [ __NR_oldstat ] = { 1, check_oldstat },
- [ __NR_stat ] = { 1, check_stat },
- [ __NR_lstat ] = { 1, check_stat },
- [ __NR_stat64 ] = { 1, check_stat64 },
- [ __NR_lstat64 ] = { 1, check_stat64 },
- [ __NR_chown32 ] = { 1, NULL },
-};
-
-/* sys_utimes */
-
-static int check_bogosity(struct pt_regs *regs)
-{
- struct bogus *bogon = &this_is_bogus[regs->regs.syscall];
-
- if(!bogon->kernel_ds) return(0);
- if(bogon->check_params && (*bogon->check_params)(regs))
- return(-EFAULT);
- set_fs(KERNEL_DS);
- return(0);
-}
-
-/* Unlocked, I don't care if this is a bit off */
-int nsyscalls = 0;
-
-extern syscall_handler_t *sys_call_table[];
-
long execute_syscall(void *r)
{
- struct pt_regs *regs = r;
- long res;
- int syscall;
-
- current->thread.nsyscalls++;
- nsyscalls++;
- syscall = regs->regs.syscall;
-
- if((syscall >= NR_syscalls) || (syscall < 0))
- res = -ENOSYS;
- else if(honeypot && check_bogosity(regs))
- res = -EFAULT;
- else res = EXECUTE_SYSCALL(syscall, regs);
-
- set_fs(USER_DS);
-
- if(current->thread.singlestep_syscall){
- current->thread.singlestep_syscall = 0;
- current->ptrace &= ~PT_DTRACE;
- force_sig(SIGTRAP, current);
- }
-
- return(res);
+ return(CHOOSE_MODE_PROC(execute_syscall_tt, execute_syscall_skas, r));
}
spinlock_t syscall_lock = SPIN_LOCK_UNLOCKED;
diff --git a/arch/um/kernel/syscall_user.c b/arch/um/kernel/syscall_user.c
index 5da5aefce6d8..3712286fe5cb 100644
--- a/arch/um/kernel/syscall_user.c
+++ b/arch/um/kernel/syscall_user.c
@@ -1,30 +1,12 @@
/*
- * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
* Licensed under the GPL
*/
-/* XXX FIXME : Ensure that SIGIO and SIGVTALRM can't happen immediately
- * after setting up syscall stack
- * block SIGVTALRM in any code that's under wait_for_stop
- */
-
-#include <unistd.h>
+#include <stdlib.h>
#include <sys/time.h>
-#include <signal.h>
-#include <errno.h>
-#include <sys/ptrace.h>
-#include <asm/unistd.h>
-#include "sysdep/ptrace.h"
-#include "sigcontext.h"
-#include "ptrace_user.h"
-#include "task.h"
-#include "user_util.h"
#include "kern_util.h"
-
-/* XXX Bogus */
-#define ERESTARTSYS 512
-#define ERESTARTNOINTR 513
-#define ERESTARTNOHAND 514
+#include "syscall_user.h"
struct {
int syscall;
@@ -34,67 +16,24 @@ struct {
struct timeval end;
} syscall_record[1024];
-void syscall_handler(int sig, struct uml_pt_regs *regs)
+int record_syscall_start(int syscall)
{
- void *sc;
- long result;
- int index, max, syscall;
+ int max, index;
max = sizeof(syscall_record)/sizeof(syscall_record[0]);
index = next_syscall_index(max);
- syscall = regs->syscall;
- sc = regs->sc;
- sc_to_regs(regs, sc, syscall);
- SC_START_SYSCALL(sc);
-
syscall_record[index].syscall = syscall;
syscall_record[index].pid = current_pid();
syscall_record[index].result = 0xdeadbeef;
gettimeofday(&syscall_record[index].start, NULL);
- syscall_trace();
- result = execute_syscall(regs);
-
- /* regs->sc may have changed while the system call ran (there may
- * have been an interrupt or segfault), so it needs to be refreshed.
- */
- regs->sc = sc;
-
- SC_SET_SYSCALL_RETURN(sc, result);
- if((result == -ERESTARTNOHAND) || (result == -ERESTARTSYS) ||
- (result == -ERESTARTNOINTR))
- do_signal(result);
-
- syscall_trace();
- syscall_record[index].result = result;
- gettimeofday(&syscall_record[index].end, NULL);
+ return(index);
}
-int do_syscall(void *task, int pid)
+void record_syscall_end(int index, int result)
{
- unsigned long proc_regs[FRAME_SIZE];
- struct uml_pt_regs *regs;
- int syscall;
-
- if(ptrace_getregs(pid, proc_regs) < 0)
- tracer_panic("Couldn't read registers");
- syscall = PT_SYSCALL_NR(proc_regs);
-
- regs = TASK_REGS(task);
- UPT_SYSCALL_NR(regs) = syscall;
-
- if(syscall < 1) return(0);
-
- if((syscall != __NR_sigreturn) &&
- ((unsigned long *) PT_IP(proc_regs) >= &_stext) &&
- ((unsigned long *) PT_IP(proc_regs) <= &_etext))
- tracer_panic("I'm tracing myself and I can't get out");
-
- if(ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_NR_OFFSET,
- __NR_getpid) < 0)
- tracer_panic("do_syscall : Nullifying syscall failed, "
- "errno = %d", errno);
- return(1);
+ syscall_record[index].result = result;
+ gettimeofday(&syscall_record[index].end, NULL);
}
/*
diff --git a/arch/um/kernel/sysrq.c b/arch/um/kernel/sysrq.c
index 5a05d66a125f..2bf29ad7ad27 100644
--- a/arch/um/kernel/sysrq.c
+++ b/arch/um/kernel/sysrq.c
@@ -19,8 +19,8 @@
#ifdef CONFIG_MODULES
-extern struct module *module_list;
-extern struct module kernel_module;
+/* FIXME: Accessed without a lock --RR */
+extern struct list_head modules;
static inline int kernel_text_address(unsigned long addr)
{
@@ -31,11 +31,11 @@ static inline int kernel_text_address(unsigned long addr)
addr <= (unsigned long) &_etext)
return 1;
- for (mod = module_list; mod != &kernel_module; mod = mod->next) {
+ list_for_each_entry(mod, &modules, list) {
/* mod_bound tests for addr being inside the vmalloc'ed
* module area. Of course it'd be better to test only
* for the .text subset... */
- if (mod_bound(addr, 0, mod)) {
+ if (mod_bound((void *) addr, 0, mod)) {
retval = 1;
break;
}
diff --git a/arch/um/kernel/tempfile.c b/arch/um/kernel/tempfile.c
index 0869e1a85ec9..64cd546a3a2d 100644
--- a/arch/um/kernel/tempfile.c
+++ b/arch/um/kernel/tempfile.c
@@ -11,7 +11,8 @@
#include <sys/param.h>
#include "init.h"
-char *tempdir = NULL;
+/* Modified from create_mem_file and start_debugger */
+static char *tempdir = NULL;
static void __init find_tempdir(void)
{
diff --git a/arch/um/kernel/time.c b/arch/um/kernel/time.c
index 2ab57626b43f..282756af3779 100644
--- a/arch/um/kernel/time.c
+++ b/arch/um/kernel/time.c
@@ -23,22 +23,21 @@ void timer(void)
gettimeofday(&xtime, NULL);
}
-static void set_interval(int timer_type)
+void set_interval(int timer_type)
{
- struct itimerval interval;
+ int usec = 1000000/hz();
+ struct itimerval interval = ((struct itimerval) { { 0, usec },
+ { 0, usec } });
- interval.it_interval.tv_sec = 0;
- interval.it_interval.tv_usec = 1000000/hz();
- interval.it_value.tv_sec = 0;
- interval.it_value.tv_usec = 1000000/hz();
if(setitimer(timer_type, &interval, NULL) == -1)
panic("setitimer failed - errno = %d\n", errno);
}
void enable_timer(void)
{
- struct itimerval enable = ((struct itimerval) { { 0, 1000000/hz() },
- { 0, 1000000/hz() }});
+ int usec = 1000000/hz();
+ struct itimerval enable = ((struct itimerval) { { 0, usec },
+ { 0, usec }});
if(setitimer(ITIMER_VIRTUAL, &enable, NULL))
printk("enable_timer - setitimer failed, errno = %d\n",
errno);
@@ -76,13 +75,6 @@ void idle_timer(void)
set_interval(ITIMER_REAL);
}
-void user_time_init(void)
-{
- if(signal(SIGVTALRM, (__sighandler_t) alarm_handler) == SIG_ERR)
- panic("Couldn't set SIGVTALRM handler");
- set_interval(ITIMER_VIRTUAL);
-}
-
void time_init(void)
{
if(signal(SIGVTALRM, boot_timer_handler) == SIG_ERR)
diff --git a/arch/um/kernel/time_kern.c b/arch/um/kernel/time_kern.c
index 93199e99c6f8..713d7af4a696 100644
--- a/arch/um/kernel/time_kern.c
+++ b/arch/um/kernel/time_kern.c
@@ -17,6 +17,7 @@
#include "kern_util.h"
#include "user_util.h"
#include "time_user.h"
+#include "mode.h"
u64 jiffies_64;
@@ -142,7 +143,7 @@ int __init timer_init(void)
{
int err;
- user_time_init();
+ CHOOSE_MODE(user_time_init_tt(), user_time_init_skas());
if((err = request_irq(TIMER_IRQ, um_timer, SA_INTERRUPT, "timer",
NULL)) != 0)
printk(KERN_ERR "timer_init : request_irq failed - "
diff --git a/arch/um/kernel/tlb.c b/arch/um/kernel/tlb.c
index f5e8458ff866..ea2ed5486881 100644
--- a/arch/um/kernel/tlb.c
+++ b/arch/um/kernel/tlb.c
@@ -1,232 +1,51 @@
/*
- * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
* Licensed under the GPL
*/
-#include "linux/sched.h"
-#include "linux/slab.h"
-#include "linux/bootmem.h"
+#include "linux/mm.h"
+#include "asm/page.h"
#include "asm/pgalloc.h"
-#include "asm-generic/tlb.h"
-#include "asm/pgtable.h"
-#include "asm/a.out.h"
-#include "asm/processor.h"
-#include "asm/mmu_context.h"
-#include "asm/uaccess.h"
-#include "asm/atomic.h"
-#include "mem_user.h"
-#include "user_util.h"
-#include "kern_util.h"
-#include "kern.h"
-#include "tlb.h"
-#include "os.h"
+#include "asm/tlbflush.h"
+#include "choose-mode.h"
+#include "mode_kern.h"
-static void fix_range(struct mm_struct *mm, unsigned long start_addr,
- unsigned long end_addr, int force)
-{
- pgd_t *npgd;
- pmd_t *npmd;
- pte_t *npte;
- unsigned long addr;
- int r, w, x, err;
-
- if((current->thread.extern_pid != -1) &&
- (current->thread.extern_pid != os_getpid()))
- panic("fix_range fixing wrong address space, current = 0x%p",
- current);
- if(mm == NULL) return;
- for(addr=start_addr;addr<end_addr;){
- if(addr == TASK_SIZE){
- /* Skip over kernel text, kernel data, and physical
- * memory, which don't have ptes, plus kernel virtual
- * memory, which is flushed separately, and remap
- * the process stack. The only way to get here is
- * if (end_addr == STACK_TOP) > TASK_SIZE, which is
- * only true in the honeypot case.
- */
- addr = STACK_TOP - ABOVE_KMEM;
- continue;
- }
- npgd = pgd_offset(mm, addr);
- npmd = pmd_offset(npgd, addr);
- if(pmd_present(*npmd)){
- npte = pte_offset_kernel(npmd, addr);
- r = pte_read(*npte);
- w = pte_write(*npte);
- x = pte_exec(*npte);
- if(!pte_dirty(*npte)) w = 0;
- if(!pte_young(*npte)){
- r = 0;
- w = 0;
- }
- if(force || pte_newpage(*npte)){
- err = unmap((void *) addr, PAGE_SIZE);
- if(err < 0)
- panic("munmap failed, errno = %d\n",
- -err);
- if(pte_present(*npte))
- map(addr, pte_val(*npte) & PAGE_MASK,
- PAGE_SIZE, r, w, x);
- }
- else if(pte_newprot(*npte)){
- protect(addr, PAGE_SIZE, r, w, x, 1);
- }
- *npte = pte_mkuptodate(*npte);
- addr += PAGE_SIZE;
- }
- else {
- if(force || pmd_newpage(*npmd)){
- err = unmap((void *) addr, PMD_SIZE);
- if(err < 0)
- panic("munmap failed, errno = %d\n",
- -err);
- pmd_mkuptodate(*npmd);
- }
- addr += PMD_SIZE;
- }
- }
-}
-
-atomic_t vmchange_seq = ATOMIC_INIT(1);
-
-void flush_kernel_range(unsigned long start, unsigned long end, int update_seq)
-{
- struct mm_struct *mm;
- pgd_t *pgd;
- pmd_t *pmd;
- pte_t *pte;
- unsigned long addr;
- int updated = 0, err;
-
- mm = &init_mm;
- for(addr = start; addr < end;){
- pgd = pgd_offset(mm, addr);
- pmd = pmd_offset(pgd, addr);
- if(pmd_present(*pmd)){
- pte = pte_offset_kernel(pmd, addr);
- if(!pte_present(*pte) || pte_newpage(*pte)){
- updated = 1;
- err = unmap((void *) addr, PAGE_SIZE);
- if(err < 0)
- panic("munmap failed, errno = %d\n",
- -err);
- if(pte_present(*pte))
- map(addr, pte_val(*pte) & PAGE_MASK,
- PAGE_SIZE, 1, 1, 1);
- }
- else if(pte_newprot(*pte)){
- updated = 1;
- protect(addr, PAGE_SIZE, 1, 1, 1, 1);
- }
- addr += PAGE_SIZE;
- }
- else {
- if(pmd_newpage(*pmd)){
- updated = 1;
- err = unmap((void *) addr, PMD_SIZE);
- if(err < 0)
- panic("munmap failed, errno = %d\n",
- -err);
- }
- addr += PMD_SIZE;
- }
- }
- if(updated && update_seq) atomic_inc(&vmchange_seq);
-}
-
-void flush_tlb_kernel_range(unsigned long start, unsigned long end)
-{
- flush_kernel_range(start, end, 1);
-}
-
-static void protect_vm_page(unsigned long addr, int w, int must_succeed)
+void flush_tlb_page(struct vm_area_struct *vma, unsigned long address)
{
- int err;
-
- err = protect(addr, PAGE_SIZE, 1, w, 1, must_succeed);
- if(err == 0) return;
- else if((err == -EFAULT) || (err == -ENOMEM)){
- flush_tlb_kernel_range(addr, addr + PAGE_SIZE);
- protect_vm_page(addr, w, 1);
- }
- else panic("protect_vm_page : protect failed, errno = %d\n", err);
+ address &= PAGE_MASK;
+ flush_tlb_range(vma, address, address + PAGE_SIZE);
}
-void mprotect_kernel_vm(int w)
+void flush_tlb_all(void)
{
- struct mm_struct *mm;
- pgd_t *pgd;
- pmd_t *pmd;
- pte_t *pte;
- unsigned long addr;
-
- mm = &init_mm;
- for(addr = start_vm; addr < end_vm;){
- pgd = pgd_offset(mm, addr);
- pmd = pmd_offset(pgd, addr);
- if(pmd_present(*pmd)){
- pte = pte_offset_kernel(pmd, addr);
- if(pte_present(*pte)) protect_vm_page(addr, w, 0);
- addr += PAGE_SIZE;
- }
- else addr += PMD_SIZE;
- }
+ flush_tlb_mm(current->mm);
}
-
+
void flush_tlb_kernel_vm(void)
{
- flush_tlb_kernel_range(start_vm, end_vm);
+ CHOOSE_MODE(flush_tlb_kernel_vm_tt(), flush_tlb_kernel_vm_skas());
}
void __flush_tlb_one(unsigned long addr)
{
- flush_tlb_kernel_range(addr, addr + PAGE_SIZE);
+ CHOOSE_MODE_PROC(__flush_tlb_one_tt, __flush_tlb_one_skas, addr);
}
-
+
void flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
unsigned long end)
{
- if(vma->vm_mm != current->mm)
- return;
-
- /* Assumes that the range start ... end is entirely within
- * either process memory or kernel vm
- */
- if((start >= start_vm) && (start < end_vm))
- flush_kernel_range(start, end, 1);
- else fix_range(vma->vm_mm, start, end, 0);
+ CHOOSE_MODE_PROC(flush_tlb_range_tt, flush_tlb_range_skas, vma, start,
+ end);
}
void flush_tlb_mm(struct mm_struct *mm)
{
- unsigned long seq;
-
- if(mm != current->mm)
- return;
-
- fix_range(mm, 0, STACK_TOP, 0);
-
- seq = atomic_read(&vmchange_seq);
- if(current->thread.vm_seq == seq) return;
- current->thread.vm_seq = seq;
- flush_kernel_range(start_vm, end_vm, 0);
-}
-
-void flush_tlb_page(struct vm_area_struct *vma, unsigned long address)
-{
- address &= PAGE_MASK;
- flush_tlb_range(vma, address, address + PAGE_SIZE);
-}
-
-void flush_tlb_all(void)
-{
- flush_tlb_mm(current->mm);
+ CHOOSE_MODE_PROC(flush_tlb_mm_tt, flush_tlb_mm_skas, mm);
}
void force_flush_all(void)
{
- fix_range(current->mm, 0, STACK_TOP, 1);
- flush_kernel_range(start_vm, end_vm, 0);
+ CHOOSE_MODE(force_flush_all_tt(), force_flush_all_skas());
}
pgd_t *pgd_offset_proc(struct mm_struct *mm, unsigned long address)
diff --git a/arch/um/kernel/trap_kern.c b/arch/um/kernel/trap_kern.c
index 33bfc04fc5d0..b93c2b4eb9c7 100644
--- a/arch/um/kernel/trap_kern.c
+++ b/arch/um/kernel/trap_kern.c
@@ -4,6 +4,7 @@
*/
#include "linux/kernel.h"
+#include "asm/errno.h"
#include "linux/sched.h"
#include "linux/mm.h"
#include "linux/spinlock.h"
@@ -19,41 +20,36 @@
#include "kern_util.h"
#include "kern.h"
#include "chan_kern.h"
-#include "debug.h"
#include "mconsole_kern.h"
#include "2_5compat.h"
-extern int nsyscalls;
-
-unsigned long segv(unsigned long address, unsigned long ip, int is_write,
- int is_user, void *sc)
+int handle_page_fault(unsigned long address, unsigned long ip,
+ int is_write, int is_user, int *code_out)
{
struct mm_struct *mm = current->mm;
struct vm_area_struct *vma;
- struct siginfo si;
- void *catcher;
pgd_t *pgd;
pmd_t *pmd;
pte_t *pte;
unsigned long page;
+ int err = -EFAULT;
- if((address >= start_vm) && (address < end_vm)){
- flush_tlb_kernel_vm();
- return(0);
- }
- if(mm == NULL) panic("Segfault with no mm");
- catcher = current->thread.fault_catcher;
- si.si_code = SEGV_MAPERR;
+ *code_out = SEGV_MAPERR;
down_read(&mm->mmap_sem);
vma = find_vma(mm, address);
- if(!vma) goto bad;
- else if(vma->vm_start <= address) goto good_area;
- else if(!(vma->vm_flags & VM_GROWSDOWN)) goto bad;
- else if(expand_stack(vma, address)) goto bad;
+ if(!vma)
+ goto out;
+ else if(vma->vm_start <= address)
+ goto good_area;
+ else if(!(vma->vm_flags & VM_GROWSDOWN))
+ goto out;
+ else if(expand_stack(vma, address))
+ goto out;
good_area:
- si.si_code = SEGV_ACCERR;
- if(is_write && !(vma->vm_flags & VM_WRITE)) goto bad;
+ *code_out = SEGV_ACCERR;
+ if(is_write && !(vma->vm_flags & VM_WRITE))
+ goto out;
page = address & PAGE_MASK;
if(page == (unsigned long) current->thread_info + PAGE_SIZE)
panic("Kernel stack overflow");
@@ -69,8 +65,10 @@ unsigned long segv(unsigned long address, unsigned long ip, int is_write,
current->maj_flt++;
break;
case VM_FAULT_SIGBUS:
- goto do_sigbus;
+ err = -EACCES;
+ goto out;
case VM_FAULT_OOM:
+ err = -ENOMEM;
goto out_of_memory;
default:
BUG();
@@ -80,44 +78,46 @@ unsigned long segv(unsigned long address, unsigned long ip, int is_write,
*pte = pte_mkyoung(*pte);
if(pte_write(*pte)) *pte = pte_mkdirty(*pte);
flush_tlb_page(vma, page);
+ err = 0;
+ out:
up_read(&mm->mmap_sem);
- return(0);
-do_sigbus:
- up_read(&mm->mmap_sem);
+ return(err);
- /*
- * Send a sigbus, regardless of whether we were in kernel
- * or user mode.
- */
- si.si_signo = SIGBUS;
- si.si_errno = 0;
- si.si_code = BUS_ADRERR;
- si.si_addr = (void *)address;
- force_sig_info(SIGBUS, &si, current);
- if(!is_user) goto bad;
- return(0);
/*
* We ran out of memory, or some other thing happened to us that made
* us unable to handle the page fault gracefully.
*/
out_of_memory:
- up_read(&mm->mmap_sem);
if (current->pid == 1) {
+ up_read(&mm->mmap_sem);
yield();
down_read(&mm->mmap_sem);
goto survive;
}
- printk("VM: killing process %s\n", current->comm);
- if(is_user)
- do_exit(SIGKILL);
+ err = -ENOMEM;
+ goto out;
+}
+
+unsigned long segv(unsigned long address, unsigned long ip, int is_write,
+ int is_user, void *sc)
+{
+ struct siginfo si;
+ void *catcher;
+ int err;
- /* Fall through to bad */
+ if(!is_user && (address >= start_vm) && (address < end_vm)){
+ flush_tlb_kernel_vm();
+ return(0);
+ }
+ if(current->mm == NULL) panic("Segfault with no mm");
+ err = handle_page_fault(address, ip, is_write, is_user, &si.si_code);
- bad:
- if(catcher != NULL){
+ catcher = current->thread.fault_catcher;
+ if(!err)
+ return(0);
+ else if(catcher != NULL){
current->thread.fault_addr = (void *) address;
- up_read(&mm->mmap_sem);
- do_longjmp(catcher);
+ do_longjmp(catcher, 1);
}
else if(current->thread.fault_addr != NULL){
panic("fault_addr set but no fault catcher");
@@ -125,15 +125,28 @@ out_of_memory:
else if(arch_fixup(ip, sc))
return(0);
- if(!is_user)
+ if(!is_user)
panic("Kernel mode fault at addr 0x%lx, ip 0x%lx",
address, ip);
- si.si_signo = SIGSEGV;
- si.si_addr = (void *) address;
- current->thread.cr2 = address;
- current->thread.err = is_write;
- force_sig_info(SIGSEGV, &si, current);
- up_read(&mm->mmap_sem);
+
+ if(err == -EACCES){
+ si.si_signo = SIGBUS;
+ si.si_errno = 0;
+ si.si_code = BUS_ADRERR;
+ si.si_addr = (void *)address;
+ force_sig_info(SIGBUS, &si, current);
+ }
+ else if(err == -ENOMEM){
+ printk("VM: killing process %s\n", current->comm);
+ do_exit(SIGKILL);
+ }
+ else {
+ si.si_signo = SIGSEGV;
+ si.si_addr = (void *) address;
+ current->thread.cr2 = address;
+ current->thread.err = is_write;
+ force_sig_info(SIGSEGV, &si, current);
+ }
return(0);
}
@@ -161,7 +174,7 @@ void relay_signal(int sig, struct uml_pt_regs *regs)
void bus_handler(int sig, struct uml_pt_regs *regs)
{
if(current->thread.fault_catcher != NULL)
- do_longjmp(current->thread.fault_catcher);
+ do_longjmp(current->thread.fault_catcher, 1);
else relay_signal(sig, regs);
}
@@ -185,250 +198,6 @@ int next_trap_index(int limit)
return(ret);
}
-extern int debugger_pid;
-extern int debugger_fd;
-extern int debugger_parent;
-
-#ifdef CONFIG_PT_PROXY
-
-int debugger_signal(int status, pid_t pid)
-{
- return(debugger_proxy(status, pid));
-}
-
-void child_signal(pid_t pid, int status)
-{
- child_proxy(pid, status);
-}
-
-static void gdb_announce(char *dev_name, int dev)
-{
- printf("gdb assigned device '%s'\n", dev_name);
-}
-
-static struct chan_opts opts = {
- announce : gdb_announce,
- xterm_title : "UML kernel debugger",
- raw : 0,
- tramp_stack : 0,
- in_kernel : 0,
-};
-
-/* Accessed by the tracing thread, which automatically serializes access */
-static void *xterm_data;
-static int xterm_fd;
-
-extern void *xterm_init(char *, int, struct chan_opts *);
-extern int xterm_open(int, int, int, void *);
-extern void xterm_close(int, void *);
-
-int open_gdb_chan(void)
-{
- char stack[PAGE_SIZE];
-
- opts.tramp_stack = (unsigned long) stack;
- xterm_data = xterm_init("", 0, &opts);
- xterm_fd = xterm_open(1, 1, 1, xterm_data);
- return(xterm_fd);
-}
-
-static void exit_debugger_cb(void *unused)
-{
- if(debugger_pid != -1){
- if(gdb_pid != -1){
- fake_child_exit();
- gdb_pid = -1;
- }
- else kill_child_dead(debugger_pid);
- debugger_pid = -1;
- if(debugger_parent != -1)
- detach(debugger_parent, SIGINT);
- }
- if(xterm_data != NULL) xterm_close(xterm_fd, xterm_data);
-}
-
-static void exit_debugger(void)
-{
- tracing_cb(exit_debugger_cb, NULL);
-}
-
-__uml_exitcall(exit_debugger);
-
-struct gdb_data {
- char *str;
- int err;
-};
-
-static void config_gdb_cb(void *arg)
-{
- struct gdb_data *data = arg;
- struct task_struct *task;
- int pid;
-
- data->err = -1;
- if(debugger_pid != -1) exit_debugger_cb(NULL);
- if(!strncmp(data->str, "pid,", strlen("pid,"))){
- data->str += strlen("pid,");
- pid = simple_strtoul(data->str, NULL, 0);
- task = cpu_tasks[0].task;
- debugger_pid = attach_debugger(task->thread.extern_pid,
- pid, 0);
- if(debugger_pid != -1){
- data->err = 0;
- gdb_pid = pid;
- }
- return;
- }
- data->err = 0;
- debugger_pid = start_debugger(linux_prog, 0, 0, &debugger_fd);
- init_proxy(debugger_pid, 0, 0);
-}
-
-int gdb_config(char *str)
-{
- struct gdb_data data;
-
- if(*str++ != '=') return(-1);
- data.str = str;
- tracing_cb(config_gdb_cb, &data);
- return(data.err);
-}
-
-void remove_gdb_cb(void *unused)
-{
- exit_debugger_cb(NULL);
-}
-
-int gdb_remove(char *unused)
-{
- tracing_cb(remove_gdb_cb, NULL);
- return(0);
-}
-
-#ifdef CONFIG_MCONSOLE
-
-static struct mc_device gdb_mc = {
- name: "gdb",
- config: gdb_config,
- remove: gdb_remove,
-};
-
-int gdb_mc_init(void)
-{
- mconsole_register_dev(&gdb_mc);
- return(0);
-}
-
-__initcall(gdb_mc_init);
-
-#endif
-
-void signal_usr1(int sig)
-{
- if(debugger_pid != -1){
- printk(KERN_ERR "The debugger is already running\n");
- return;
- }
- debugger_pid = start_debugger(linux_prog, 0, 0, &debugger_fd);
- init_proxy(debugger_pid, 0, 0);
-}
-
-int init_ptrace_proxy(int idle_pid, int startup, int stop)
-{
- int pid, status;
-
- pid = start_debugger(linux_prog, startup, stop, &debugger_fd);
- status = wait_for_stop(idle_pid, SIGSTOP, PTRACE_CONT, NULL);
- if(pid < 0){
- cont(idle_pid);
- return(-1);
- }
- init_proxy(pid, 1, status);
- return(pid);
-}
-
-int attach_debugger(int idle_pid, int pid, int stop)
-{
- int status = 0, err;
-
- err = attach(pid);
- if(err < 0){
- printf("Failed to attach pid %d, errno = %d\n", pid, -err);
- return(-1);
- }
- if(stop) status = wait_for_stop(idle_pid, SIGSTOP, PTRACE_CONT, NULL);
- init_proxy(pid, 1, status);
- return(pid);
-}
-
-#ifdef notdef /* Put this back in when it does something useful */
-static int __init uml_gdb_init_setup(char *line, int *add)
-{
- gdb_init = uml_strdup(line);
- return 0;
-}
-
-__uml_setup("gdb=", uml_gdb_init_setup,
-"gdb=<channel description>\n\n"
-);
-#endif
-
-static int __init uml_gdb_pid_setup(char *line, int *add)
-{
- gdb_pid = simple_strtoul(line, NULL, 0);
- *add = 0;
- return 0;
-}
-
-__uml_setup("gdb-pid=", uml_gdb_pid_setup,
-"gdb-pid=<pid>\n"
-" gdb-pid is used to attach an external debugger to UML. This may be\n"
-" an already-running gdb or a debugger-like process like strace.\n\n"
-);
-
-#else
-
-int debugger_signal(int status, pid_t pid){ return(0); }
-void child_signal(pid_t pid, int status){ }
-int init_ptrace_proxy(int idle_pid, int startup, int stop)
-{
- printk(KERN_ERR "debug requested when CONFIG_PT_PROXY is off\n");
- kill_child_dead(idle_pid);
- exit(1);
-}
-
-void signal_usr1(int sig)
-{
- printk(KERN_ERR "debug requested when CONFIG_PT_PROXY is off\n");
-}
-
-int attach_debugger(int idle_pid, int pid, int stop)
-{
- printk(KERN_ERR "attach_debugger called when CONFIG_PT_PROXY "
- "is off\n");
- return(-1);
-}
-
-int config_gdb(char *str)
-{
- return(-1);
-}
-
-int remove_gdb(void)
-{
- return(-1);
-}
-
-int init_parent_proxy(int pid)
-{
- return(-1);
-}
-
-void debugger_parent_signal(int status, int pid)
-{
-}
-
-#endif
/*
* Overrides for Emacs so that we follow Linus's tabbing style.
* Emacs will notice this stuff at the end of the file and automatically
diff --git a/arch/um/kernel/trap_user.c b/arch/um/kernel/trap_user.c
index 8971a61c8310..02e7b0eede15 100644
--- a/arch/um/kernel/trap_user.c
+++ b/arch/um/kernel/trap_user.c
@@ -3,66 +3,33 @@
* Licensed under the GPL
*/
-#include <stdio.h>
#include <stdlib.h>
-#include <unistd.h>
-#include <signal.h>
#include <errno.h>
-#include <sched.h>
#include <fcntl.h>
#include <setjmp.h>
-#include <string.h>
-#include <sys/ptrace.h>
+#include <signal.h>
#include <sys/time.h>
-#include <sys/wait.h>
-#include <sys/mman.h>
#include <sys/ioctl.h>
+#include <sys/ptrace.h>
+#include <sys/wait.h>
#include <asm/page.h>
#include <asm/unistd.h>
#include <asm/ptrace.h>
-#include "user_util.h"
-#include "kern_util.h"
-#include "signal_user.h"
-#include "mem_user.h"
-#include "user.h"
-#include "process.h"
+#include "init.h"
+#include "sysdep/ptrace.h"
#include "sigcontext.h"
#include "sysdep/sigcontext.h"
-#include "init.h"
-#include "chan_user.h"
#include "irq_user.h"
#include "frame_user.h"
-#include "syscall_user.h"
-#include "ptrace_user.h"
+#include "signal_user.h"
#include "time_user.h"
#include "task.h"
+#include "mode.h"
+#include "choose-mode.h"
+#include "kern_util.h"
+#include "user_util.h"
#include "os.h"
-static void signal_segv(int sig)
-{
- write(2, "Seg fault in signals\n", strlen("Seg fault in signals\n"));
- for(;;) ;
-}
-
-int detach(int pid, int sig)
-{
- return(ptrace(PTRACE_DETACH, pid, 0, sig));
-}
-
-int attach(int pid)
-{
- int err;
-
- err = ptrace(PTRACE_ATTACH, pid, 0, 0);
- if(err < 0) return(-errno);
- else return(err);
-}
-
-int cont(int pid)
-{
- return(ptrace(PTRACE_CONT, pid, 0, 0));
-}
-
void kill_child_dead(int pid)
{
kill(pid, SIGKILL);
@@ -70,336 +37,6 @@ void kill_child_dead(int pid)
while(waitpid(pid, NULL, 0) > 0) kill(pid, SIGCONT);
}
-/* Changed early in boot, and then only read */
-int debug = 0;
-int debug_stop = 1;
-int debug_parent = 0;
-int honeypot = 0;
-
-static int signal_tramp(void *arg)
-{
- int (*proc)(void *);
-
- if(honeypot && munmap((void *) (host_task_size - 0x10000000),
- 0x10000000))
- panic("Unmapping stack failed");
- if(ptrace(PTRACE_TRACEME, 0, 0, 0) < 0)
- panic("ptrace PTRACE_TRACEME failed");
- os_stop_process(os_getpid());
- change_sig(SIGWINCH, 0);
- signal(SIGUSR1, SIG_IGN);
- change_sig(SIGCHLD, 0);
- signal(SIGSEGV, (__sighandler_t) sig_handler);
- set_cmdline("(idle thread)");
- set_init_pid(os_getpid());
- proc = arg;
- return((*proc)(NULL));
-}
-
-static void last_ditch_exit(int sig)
-{
- kmalloc_ok = 0;
- signal(SIGINT, SIG_DFL);
- signal(SIGTERM, SIG_DFL);
- signal(SIGHUP, SIG_DFL);
- uml_cleanup();
- exit(1);
-}
-
-static void sleeping_process_signal(int pid, int sig)
-{
- switch(sig){
- /* These two result from UML being ^Z-ed and bg-ed. PTRACE_CONT is
- * right because the process must be in the kernel already.
- */
- case SIGCONT:
- case SIGTSTP:
- if(ptrace(PTRACE_CONT, pid, 0, sig) < 0)
- tracer_panic("sleeping_process_signal : Failed to "
- "continue pid %d, errno = %d\n", pid,
- sig);
- break;
-
- /* This happens when the debugger (e.g. strace) is doing system call
- * tracing on the kernel. During a context switch, the current task
- * will be set to the incoming process and the outgoing process will
- * hop into write and then read. Since it's not the current process
- * any more, the trace of those will land here. So, we need to just
- * PTRACE_SYSCALL it.
- */
- case SIGTRAP:
- if(ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0)
- tracer_panic("sleeping_process_signal : Failed to "
- "PTRACE_SYSCALL pid %d, errno = %d\n",
- pid, sig);
- break;
- case SIGSTOP:
- break;
- default:
- tracer_panic("sleeping process %d got unexpected "
- "signal : %d\n", pid, sig);
- break;
- }
-}
-
-/* Accessed only by the tracing thread */
-int debugger_pid = -1;
-int debugger_parent = -1;
-int debugger_fd = -1;
-int gdb_pid = -1;
-
-struct {
- int pid;
- int signal;
- unsigned long addr;
- struct timeval time;
-} signal_record[1024][32];
-
-int signal_index[32];
-int nsignals = 0;
-int debug_trace = 0;
-extern int io_nsignals, io_count, intr_count;
-
-extern void signal_usr1(int sig);
-
-int tracing_pid = -1;
-
-int signals(int (*init_proc)(void *), void *sp)
-{
- void *task = NULL;
- unsigned long eip = 0;
- int status, pid = 0, sig = 0, cont_type, tracing = 0, op = 0;
- int last_index, proc_id = 0, n, err, old_tracing = 0, strace = 0;
-
- capture_signal_stack();
- signal(SIGPIPE, SIG_IGN);
- setup_tracer_winch();
- tracing_pid = os_getpid();
- printf("tracing thread pid = %d\n", tracing_pid);
-
- pid = clone(signal_tramp, sp, CLONE_FILES | SIGCHLD, init_proc);
- n = waitpid(pid, &status, WUNTRACED);
- if(n < 0){
- printf("waitpid on idle thread failed, errno = %d\n", errno);
- exit(1);
- }
- if((ptrace(PTRACE_CONT, pid, 0, 0) < 0)){
- printf("Failed to continue idle thread, errno = %d\n", errno);
- exit(1);
- }
-
- signal(SIGSEGV, signal_segv);
- signal(SIGUSR1, signal_usr1);
- set_handler(SIGINT, last_ditch_exit, SA_ONESHOT | SA_NODEFER, -1);
- set_handler(SIGTERM, last_ditch_exit, SA_ONESHOT | SA_NODEFER, -1);
- set_handler(SIGHUP, last_ditch_exit, SA_ONESHOT | SA_NODEFER, -1);
- if(debug_trace){
- printf("Tracing thread pausing to be attached\n");
- stop();
- }
- if(debug){
- if(gdb_pid != -1)
- debugger_pid = attach_debugger(pid, gdb_pid, 1);
- else debugger_pid = init_ptrace_proxy(pid, 1, debug_stop);
- if(debug_parent){
- debugger_parent = os_process_parent(debugger_pid);
- init_parent_proxy(debugger_parent);
- err = attach(debugger_parent);
- if(err){
- printf("Failed to attach debugger parent %d, "
- "errno = %d\n", debugger_parent, err);
- debugger_parent = -1;
- }
- else {
- if(ptrace(PTRACE_SYSCALL, debugger_parent,
- 0, 0) < 0){
- printf("Failed to continue debugger "
- "parent, errno = %d\n", errno);
- debugger_parent = -1;
- }
- }
- }
- }
- set_cmdline("(tracing thread)");
- while(1){
- if((pid = waitpid(-1, &status, WUNTRACED)) <= 0){
- if(errno != ECHILD){
- printf("wait failed - errno = %d\n", errno);
- }
- continue;
- }
- if(pid == debugger_pid){
- int cont = 0;
-
- if(WIFEXITED(status) || WIFSIGNALED(status))
- debugger_pid = -1;
- /* XXX Figure out how to deal with gdb and SMP */
- else cont = debugger_signal(status, cpu_tasks[0].pid);
- if(cont == PTRACE_SYSCALL) strace = 1;
- continue;
- }
- else if(pid == debugger_parent){
- debugger_parent_signal(status, pid);
- continue;
- }
- nsignals++;
- if(WIFEXITED(status)) ;
-#ifdef notdef
- {
- printf("Child %d exited with status %d\n", pid,
- WEXITSTATUS(status));
- }
-#endif
- else if(WIFSIGNALED(status)){
- sig = WTERMSIG(status);
- if(sig != 9){
- printf("Child %d exited with signal %d\n", pid,
- sig);
- }
- }
- else if(WIFSTOPPED(status)){
- proc_id = pid_to_processor_id(pid);
- sig = WSTOPSIG(status);
- if(signal_index[proc_id] == 1024){
- signal_index[proc_id] = 0;
- last_index = 1023;
- }
- else last_index = signal_index[proc_id] - 1;
- if(((sig == SIGPROF) || (sig == SIGVTALRM) ||
- (sig == SIGALRM)) &&
- (signal_record[proc_id][last_index].signal == sig)&&
- (signal_record[proc_id][last_index].pid == pid))
- signal_index[proc_id] = last_index;
- signal_record[proc_id][signal_index[proc_id]].pid = pid;
- gettimeofday(&signal_record[proc_id][signal_index[proc_id]].time, NULL);
- eip = ptrace(PTRACE_PEEKUSER, pid, PT_IP_OFFSET, 0);
- signal_record[proc_id][signal_index[proc_id]].addr = eip;
- signal_record[proc_id][signal_index[proc_id]++].signal = sig;
-
- if(proc_id == -1){
- sleeping_process_signal(pid, sig);
- continue;
- }
-
- task = cpu_tasks[proc_id].task;
- tracing = is_tracing(task);
- old_tracing = tracing;
-
- switch(sig){
- case SIGUSR1:
- sig = 0;
- op = do_proc_op(task, proc_id);
- switch(op){
- case OP_TRACE_ON:
- arch_leave_kernel(task, pid);
- tracing = 1;
- break;
- case OP_REBOOT:
- case OP_HALT:
- unmap_physmem();
- kmalloc_ok = 0;
- ptrace(PTRACE_KILL, pid, 0, 0);
- return(op == OP_REBOOT);
- case OP_NONE:
- printf("Detaching pid %d\n", pid);
- detach(pid, SIGSTOP);
- continue;
- default:
- break;
- }
- /* OP_EXEC switches host processes on us,
- * we want to continue the new one.
- */
- pid = cpu_tasks[proc_id].pid;
- break;
- case SIGTRAP:
- if(!tracing && (debugger_pid != -1)){
- child_signal(pid, status);
- continue;
- }
- tracing = 0;
- if(do_syscall(task, pid)) sig = SIGUSR2;
- else clear_singlestep(task);
- break;
- case SIGPROF:
- if(tracing) sig = 0;
- break;
- case SIGCHLD:
- case SIGHUP:
- sig = 0;
- break;
- case SIGSEGV:
- case SIGIO:
- case SIGALRM:
- case SIGVTALRM:
- case SIGFPE:
- case SIGBUS:
- case SIGILL:
- case SIGWINCH:
- default:
- tracing = 0;
- break;
- }
- set_tracing(task, tracing);
-
- if(!tracing && old_tracing)
- arch_enter_kernel(task, pid);
-
- if(!tracing && (debugger_pid != -1) && (sig != 0) &&
- (sig != SIGALRM) && (sig != SIGVTALRM) &&
- (sig != SIGSEGV) && (sig != SIGTRAP) &&
- (sig != SIGUSR2) && (sig != SIGIO)){
- child_signal(pid, status);
- continue;
- }
-
- if(tracing){
- if(singlestepping(task))
- cont_type = PTRACE_SINGLESTEP;
- else cont_type = PTRACE_SYSCALL;
- }
- else cont_type = PTRACE_CONT;
-
- if((cont_type == PTRACE_CONT) &&
- (debugger_pid != -1) && strace)
- cont_type = PTRACE_SYSCALL;
-
- if(ptrace(cont_type, pid, 0, sig) != 0){
- tracer_panic("ptrace failed to continue "
- "process - errno = %d\n",
- errno);
- }
- }
- }
- return(0);
-}
-
-static int __init uml_debugtrace_setup(char *line, int *add)
-{
- debug_trace = 1;
- return 0;
-}
-__uml_setup("debugtrace", uml_debugtrace_setup,
-"debugtrace\n"
-" Causes the tracing thread to pause until it is attached by a\n"
-" debugger and continued. This is mostly for debugging crashes\n"
-" early during boot, and should be pretty much obsoleted by\n"
-" the debug switch.\n\n"
-);
-
-static int __init uml_honeypot_setup(char *line, int *add)
-{
- jail_setup("", add);
- honeypot = 1;
- return 0;
-}
-__uml_setup("honeypot", uml_honeypot_setup,
-"honeypot\n"
-" This makes UML put process stacks in the same location as they are\n"
-" on the host, allowing expoits such as stack smashes to work against\n"
-" UML. This implies 'jail'.\n\n"
-);
-
/* Unlocked - don't care if this is a bit off */
int nsegfaults = 0;
@@ -413,33 +50,32 @@ struct {
void segv_handler(int sig, struct uml_pt_regs *regs)
{
- struct sigcontext *context = regs->sc;
int index, max;
- if(regs->is_user && !SEGV_IS_FIXABLE(context)){
- bad_segv(SC_FAULT_ADDR(context), SC_IP(context),
- SC_FAULT_WRITE(context));
+ if(regs->is_user && !UPT_SEGV_IS_FIXABLE(regs)){
+ bad_segv(UPT_FAULT_ADDR(regs), UPT_IP(regs),
+ UPT_FAULT_WRITE(regs));
return;
}
max = sizeof(segfault_record)/sizeof(segfault_record[0]);
index = next_trap_index(max);
nsegfaults++;
- segfault_record[index].address = SC_FAULT_ADDR(context);
+ segfault_record[index].address = UPT_FAULT_ADDR(regs);
segfault_record[index].pid = os_getpid();
- segfault_record[index].is_write = SC_FAULT_WRITE(context);
- segfault_record[index].sp = SC_SP(context);
+ segfault_record[index].is_write = UPT_FAULT_WRITE(regs);
+ segfault_record[index].sp = UPT_SP(regs);
segfault_record[index].is_user = regs->is_user;
- segv(SC_FAULT_ADDR(context), SC_IP(context), SC_FAULT_WRITE(context),
- regs->is_user, context);
+ segv(UPT_FAULT_ADDR(regs), UPT_IP(regs), UPT_FAULT_WRITE(regs),
+ regs->is_user, regs);
}
-struct signal_info {
- void (*handler)(int, struct uml_pt_regs *);
- int is_irq;
-};
+void usr2_handler(int sig, struct uml_pt_regs *regs)
+{
+ CHOOSE_MODE(syscall_handler_tt(sig, regs), (void) 0);
+}
-static struct signal_info sig_info[] = {
+struct signal_info sig_info[] = {
[ SIGTRAP ] { handler : relay_signal,
is_irq : 0 },
[ SIGFPE ] { handler : relay_signal,
@@ -454,104 +90,42 @@ static struct signal_info sig_info[] = {
is_irq : 1 },
[ SIGVTALRM ] { handler : timer_handler,
is_irq : 1 },
- [ SIGALRM ] { handler : timer_handler,
- is_irq : 1 },
- [ SIGUSR2 ] { handler : syscall_handler,
+ [ SIGALRM ] { handler : timer_handler,
+ is_irq : 1 },
+ [ SIGUSR2 ] { handler : usr2_handler,
is_irq : 0 },
};
-void sig_handler_common(int sig, struct sigcontext *sc)
-{
- struct uml_pt_regs save_regs, *r;
- struct signal_info *info;
- int save_errno = errno, is_user;
-
- unprotect_kernel_mem();
-
- r = (struct uml_pt_regs *) TASK_REGS(get_current());
- save_regs = *r;
- is_user = user_context(SC_SP(sc));
- r->is_user = is_user;
- r->sc = sc;
- if(sig != SIGUSR2) r->syscall = -1;
-
- change_sig(SIGUSR1, 1);
- info = &sig_info[sig];
- if(!info->is_irq) unblock_signals();
-
- (*info->handler)(sig, r);
-
- if(is_user){
- interrupt_end();
- block_signals();
- change_sig(SIGUSR1, 0);
- set_user_mode(NULL);
- }
- *r = save_regs;
- errno = save_errno;
- if(is_user) protect_kernel_mem();
-}
-
void sig_handler(int sig, struct sigcontext sc)
{
- sig_handler_common(sig, &sc);
+ CHOOSE_MODE_PROC(sig_handler_common_tt, sig_handler_common_skas,
+ sig, &sc);
}
extern int timer_irq_inited, missed_ticks[];
void alarm_handler(int sig, struct sigcontext sc)
{
- int user;
-
if(!timer_irq_inited) return;
missed_ticks[cpu()]++;
- user = user_context(SC_SP(&sc));
if(sig == SIGALRM)
switch_timers(0);
- sig_handler_common(sig, &sc);
+ CHOOSE_MODE_PROC(sig_handler_common_tt, sig_handler_common_skas,
+ sig, &sc);
if(sig == SIGALRM)
switch_timers(1);
}
-void do_longjmp(void *p)
+void do_longjmp(void *b, int val)
{
- jmp_buf *jbuf = (jmp_buf *) p;
+ jmp_buf *buf = b;
- longjmp(*jbuf, 1);
+ longjmp(*buf, val);
}
-static int __init uml_debug_setup(char *line, int *add)
-{
- char *next;
-
- debug = 1;
- *add = 0;
- if(*line != '=') return(0);
- line++;
-
- while(line != NULL){
- next = strchr(line, ',');
- if(next) *next++ = '\0';
-
- if(!strcmp(line, "go")) debug_stop = 0;
- else if(!strcmp(line, "parent")) debug_parent = 1;
- else printk("Unknown debug option : '%s'\n", line);
-
- line = next;
- }
- return(0);
-}
-
-__uml_setup("debug", uml_debug_setup,
-"debug\n"
-" Starts up the kernel under the control of gdb. See the \n"
-" kernel debugging tutorial and the debugging session pages\n"
-" at http://user-mode-linux.sourceforge.net/ for more information.\n\n"
-);
-
/*
* Overrides for Emacs so that we follow Linus's tabbing style.
* Emacs will notice this stuff at the end of the file and automatically
diff --git a/arch/um/kernel/tt/Makefile b/arch/um/kernel/tt/Makefile
new file mode 100644
index 000000000000..9b436c8ef1bb
--- /dev/null
+++ b/arch/um/kernel/tt/Makefile
@@ -0,0 +1,20 @@
+#
+# Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+# Licensed under the GPL
+#
+
+obj-y = exec_kern.o exec_user.o gdb.o gdb_kern.o ksyms.o mem.o process_kern.o \
+ syscall_kern.o syscall_user.o time.o tlb.o tracer.o trap_user.o \
+ uaccess_user.o sys-$(SUBARCH)/
+
+obj-$(CONFIG_PT_PROXY) += ptproxy/
+
+export-objs = ksyms.o
+
+USER_OBJS := $(filter %_user.o,$(obj-y)) gdb.o time.o tracer.o
+USER_OBJS := $(foreach file,$(USER_OBJS),$(obj)/$(file))
+
+$(USER_OBJS) : %.o: %.c
+ $(CC) $(CFLAGS_$(notdir $@)) $(USER_CFLAGS) -c -o $@ $<
+
+clean :
diff --git a/arch/um/kernel/tt/exec_kern.c b/arch/um/kernel/tt/exec_kern.c
new file mode 100644
index 000000000000..afd94713d742
--- /dev/null
+++ b/arch/um/kernel/tt/exec_kern.c
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#include "linux/kernel.h"
+#include "linux/mm.h"
+#include "asm/signal.h"
+#include "asm/ptrace.h"
+#include "asm/uaccess.h"
+#include "asm/pgalloc.h"
+#include "asm/tlbflush.h"
+#include "user_util.h"
+#include "kern_util.h"
+#include "irq_user.h"
+#include "time_user.h"
+#include "mem_user.h"
+#include "os.h"
+#include "tlb.h"
+
+static int exec_tramp(void *sig_stack)
+{
+ init_new_thread_stack(sig_stack, NULL);
+ init_new_thread_signals(1);
+ os_stop_process(os_getpid());
+ return(0);
+}
+
+void flush_thread_tt(void)
+{
+ unsigned long stack;
+ int new_pid;
+
+ stack = alloc_stack(0, 0);
+ if(stack == 0){
+ printk(KERN_ERR
+ "flush_thread : failed to allocate temporary stack\n");
+ do_exit(SIGKILL);
+ }
+
+ new_pid = start_fork_tramp((void *) current->thread.kernel_stack,
+ stack, 0, exec_tramp);
+ if(new_pid < 0){
+ printk(KERN_ERR
+ "flush_thread : new thread failed, errno = %d\n",
+ -new_pid);
+ do_exit(SIGKILL);
+ }
+
+ if(current->thread_info->cpu == 0)
+ forward_interrupts(new_pid);
+ current->thread.request.op = OP_EXEC;
+ current->thread.request.u.exec.pid = new_pid;
+ unprotect_stack((unsigned long) current->thread_info);
+ os_usr1_process(os_getpid());
+
+ enable_timer();
+ free_page(stack);
+ protect_memory(uml_reserved, high_physmem - uml_reserved, 1, 1, 0, 1);
+ task_protections((unsigned long) current->thread_info);
+ force_flush_all();
+ unblock_signals();
+}
+
+void start_thread_tt(struct pt_regs *regs, unsigned long eip,
+ unsigned long esp)
+{
+ set_fs(USER_DS);
+ flush_tlb_mm(current->mm);
+ PT_REGS_IP(regs) = eip;
+ PT_REGS_SP(regs) = esp;
+ PT_FIX_EXEC_STACK(esp);
+}
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only. This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff --git a/arch/um/kernel/exec_user.c b/arch/um/kernel/tt/exec_user.c
index 35d108266d41..35d108266d41 100644
--- a/arch/um/kernel/exec_user.c
+++ b/arch/um/kernel/tt/exec_user.c
diff --git a/arch/um/kernel/tt/gdb.c b/arch/um/kernel/tt/gdb.c
new file mode 100644
index 000000000000..22753784178a
--- /dev/null
+++ b/arch/um/kernel/tt/gdb.c
@@ -0,0 +1,278 @@
+/*
+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <signal.h>
+#include <sys/ptrace.h>
+#include <sys/types.h>
+#include "uml-config.h"
+#include "kern_constants.h"
+#include "chan_user.h"
+#include "init.h"
+#include "user.h"
+#include "debug.h"
+#include "kern_util.h"
+#include "user_util.h"
+#include "tt.h"
+#include "sysdep/thread.h"
+
+extern int debugger_pid;
+extern int debugger_fd;
+extern int debugger_parent;
+
+int detach(int pid, int sig)
+{
+ return(ptrace(PTRACE_DETACH, pid, 0, sig));
+}
+
+int attach(int pid)
+{
+ int err;
+
+ err = ptrace(PTRACE_ATTACH, pid, 0, 0);
+ if(err < 0) return(-errno);
+ else return(err);
+}
+
+int cont(int pid)
+{
+ return(ptrace(PTRACE_CONT, pid, 0, 0));
+}
+
+#ifdef CONFIG_PT_PROXY
+
+int debugger_signal(int status, pid_t pid)
+{
+ return(debugger_proxy(status, pid));
+}
+
+void child_signal(pid_t pid, int status)
+{
+ child_proxy(pid, status);
+}
+
+static void gdb_announce(char *dev_name, int dev)
+{
+ printf("gdb assigned device '%s'\n", dev_name);
+}
+
+static struct chan_opts opts = {
+ announce : gdb_announce,
+ xterm_title : "UML kernel debugger",
+ raw : 0,
+ tramp_stack : 0,
+ in_kernel : 0,
+};
+
+/* Accessed by the tracing thread, which automatically serializes access */
+static void *xterm_data;
+static int xterm_fd;
+
+extern void *xterm_init(char *, int, struct chan_opts *);
+extern int xterm_open(int, int, int, void *);
+extern void xterm_close(int, void *);
+
+int open_gdb_chan(void)
+{
+ char stack[UM_KERN_PAGE_SIZE];
+
+ opts.tramp_stack = (unsigned long) stack;
+ xterm_data = xterm_init("", 0, &opts);
+ xterm_fd = xterm_open(1, 1, 1, xterm_data);
+ return(xterm_fd);
+}
+
+static void exit_debugger_cb(void *unused)
+{
+ if(debugger_pid != -1){
+ if(gdb_pid != -1){
+ fake_child_exit();
+ gdb_pid = -1;
+ }
+ else kill_child_dead(debugger_pid);
+ debugger_pid = -1;
+ if(debugger_parent != -1)
+ detach(debugger_parent, SIGINT);
+ }
+ if(xterm_data != NULL) xterm_close(xterm_fd, xterm_data);
+}
+
+static void exit_debugger(void)
+{
+ initial_thread_cb(exit_debugger_cb, NULL);
+}
+
+__uml_exitcall(exit_debugger);
+
+struct gdb_data {
+ char *str;
+ int err;
+};
+
+static void config_gdb_cb(void *arg)
+{
+ struct gdb_data *data = arg;
+ void *task;
+ int pid;
+
+ data->err = -1;
+ if(debugger_pid != -1) exit_debugger_cb(NULL);
+ if(!strncmp(data->str, "pid,", strlen("pid,"))){
+ data->str += strlen("pid,");
+ pid = strtoul(data->str, NULL, 0);
+ task = cpu_tasks[0].task;
+ debugger_pid = attach_debugger(TASK_EXTERN_PID(task), pid, 0);
+ if(debugger_pid != -1){
+ data->err = 0;
+ gdb_pid = pid;
+ }
+ return;
+ }
+ data->err = 0;
+ debugger_pid = start_debugger(linux_prog, 0, 0, &debugger_fd);
+ init_proxy(debugger_pid, 0, 0);
+}
+
+int gdb_config(char *str)
+{
+ struct gdb_data data;
+
+ if(*str++ != '=') return(-1);
+ data.str = str;
+ initial_thread_cb(config_gdb_cb, &data);
+ return(data.err);
+}
+
+void remove_gdb_cb(void *unused)
+{
+ exit_debugger_cb(NULL);
+}
+
+int gdb_remove(char *unused)
+{
+ initial_thread_cb(remove_gdb_cb, NULL);
+ return(0);
+}
+
+void signal_usr1(int sig)
+{
+ if(debugger_pid != -1){
+ printk(UM_KERN_ERR "The debugger is already running\n");
+ return;
+ }
+ debugger_pid = start_debugger(linux_prog, 0, 0, &debugger_fd);
+ init_proxy(debugger_pid, 0, 0);
+}
+
+int init_ptrace_proxy(int idle_pid, int startup, int stop)
+{
+ int pid, status;
+
+ pid = start_debugger(linux_prog, startup, stop, &debugger_fd);
+ status = wait_for_stop(idle_pid, SIGSTOP, PTRACE_CONT, NULL);
+ if(pid < 0){
+ cont(idle_pid);
+ return(-1);
+ }
+ init_proxy(pid, 1, status);
+ return(pid);
+}
+
+int attach_debugger(int idle_pid, int pid, int stop)
+{
+ int status = 0, err;
+
+ err = attach(pid);
+ if(err < 0){
+ printf("Failed to attach pid %d, errno = %d\n", pid, -err);
+ return(-1);
+ }
+ if(stop) status = wait_for_stop(idle_pid, SIGSTOP, PTRACE_CONT, NULL);
+ init_proxy(pid, 1, status);
+ return(pid);
+}
+
+#ifdef notdef /* Put this back in when it does something useful */
+static int __init uml_gdb_init_setup(char *line, int *add)
+{
+ gdb_init = uml_strdup(line);
+ return 0;
+}
+
+__uml_setup("gdb=", uml_gdb_init_setup,
+"gdb=<channel description>\n\n"
+);
+#endif
+
+static int __init uml_gdb_pid_setup(char *line, int *add)
+{
+ gdb_pid = strtoul(line, NULL, 0);
+ *add = 0;
+ return 0;
+}
+
+__uml_setup("gdb-pid=", uml_gdb_pid_setup,
+"gdb-pid=<pid>\n"
+" gdb-pid is used to attach an external debugger to UML. This may be\n"
+" an already-running gdb or a debugger-like process like strace.\n\n"
+);
+
+#else
+
+int debugger_signal(int status, pid_t pid){ return(0); }
+void child_signal(pid_t pid, int status){ }
+int init_ptrace_proxy(int idle_pid, int startup, int stop)
+{
+ printk(UM_KERN_ERR "debug requested when CONFIG_PT_PROXY is off\n");
+ kill_child_dead(idle_pid);
+ exit(1);
+}
+
+void signal_usr1(int sig)
+{
+ printk(UM_KERN_ERR "debug requested when CONFIG_PT_PROXY is off\n");
+}
+
+int attach_debugger(int idle_pid, int pid, int stop)
+{
+ printk(UM_KERN_ERR "attach_debugger called when CONFIG_PT_PROXY "
+ "is off\n");
+ return(-1);
+}
+
+int config_gdb(char *str)
+{
+ return(-1);
+}
+
+int remove_gdb(void)
+{
+ return(-1);
+}
+
+int init_parent_proxy(int pid)
+{
+ return(-1);
+}
+
+void debugger_parent_signal(int status, int pid)
+{
+}
+
+#endif
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only. This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff --git a/arch/um/kernel/tt/gdb_kern.c b/arch/um/kernel/tt/gdb_kern.c
new file mode 100644
index 000000000000..2b4320c1480c
--- /dev/null
+++ b/arch/um/kernel/tt/gdb_kern.c
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#include "linux/init.h"
+#include "linux/config.h"
+#include "mconsole_kern.h"
+
+#ifdef CONFIG_MCONSOLE
+
+extern int gdb_config(char *str);
+extern int gdb_remove(char *unused);
+
+static struct mc_device gdb_mc = {
+ name: "gdb",
+ config: gdb_config,
+ remove: gdb_remove,
+};
+
+int gdb_mc_init(void)
+{
+ mconsole_register_dev(&gdb_mc);
+ return(0);
+}
+
+__initcall(gdb_mc_init);
+
+#endif
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only. This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff --git a/arch/um/include/debug.h b/arch/um/kernel/tt/include/debug.h
index 1d8b0a2638a8..8eff674107ca 100644
--- a/arch/um/include/debug.h
+++ b/arch/um/kernel/tt/include/debug.h
@@ -3,6 +3,7 @@
* Lars Brinkhoff.
* Licensed under the GPL
*/
+
#ifndef __DEBUG_H
#define __DEBUG_H
@@ -11,6 +12,8 @@ extern void child_proxy(pid_t pid, int status);
extern void init_proxy (pid_t pid, int waiting, int status);
extern int start_debugger(char *prog, int startup, int stop, int *debugger_fd);
extern void fake_child_exit(void);
+extern int gdb_config(char *str);
+extern int gdb_remove(char *unused);
#endif
diff --git a/arch/um/kernel/setup.c b/arch/um/kernel/tt/include/mmu.h
index 3e4290a285f6..6b146bd84ca7 100644
--- a/arch/um/kernel/setup.c
+++ b/arch/um/kernel/tt/include/mmu.h
@@ -1,12 +1,15 @@
/*
- * Copyright (C) 2000, 2002 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
* Licensed under the GPL
*/
-#include "asm/processor.h"
+#ifndef __TT_MMU_H
+#define __TT_MMU_H
-struct cpuinfo_um boot_cpu_data = { loops_per_jiffy : 0,
- ipi_pipe : { -1, -1 } };
+struct mmu_context_tt {
+};
+
+#endif
/*
* Overrides for Emacs so that we follow Linus's tabbing style.
diff --git a/arch/um/kernel/tt/include/mode.h b/arch/um/kernel/tt/include/mode.h
new file mode 100644
index 000000000000..183a61d40453
--- /dev/null
+++ b/arch/um/kernel/tt/include/mode.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#ifndef __MODE_TT_H__
+#define __MODE_TT_H__
+
+#include "sysdep/ptrace.h"
+
+extern int tracing_pid;
+
+extern int tracer(int (*init_proc)(void *), void *sp);
+extern void user_time_init_tt(void);
+extern int copy_sc_from_user_tt(void *to_ptr, void *from_ptr, void *data);
+extern int copy_sc_to_user_tt(void *to_ptr, void *from_ptr, void *data);
+extern void sig_handler_common_tt(int sig, struct sigcontext *sc);
+extern void syscall_handler_tt(int sig, struct uml_pt_regs *regs);
+extern void reboot_tt(void);
+extern void halt_tt(void);
+extern int is_tracer_winch(int pid, int fd, void *data);
+extern void kill_off_processes_tt(void);
+
+#endif
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only. This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff --git a/arch/um/kernel/tt/include/mode_kern.h b/arch/um/kernel/tt/include/mode_kern.h
new file mode 100644
index 000000000000..3dbd434f1abe
--- /dev/null
+++ b/arch/um/kernel/tt/include/mode_kern.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#ifndef __TT_MODE_KERN_H__
+#define __TT_MODE_KERN_H__
+
+#include "linux/sched.h"
+#include "asm/page.h"
+#include "asm/ptrace.h"
+#include "asm/uaccess.h"
+
+extern void *switch_to_tt(void *prev, void *next);
+extern void flush_thread_tt(void);
+extern void start_thread_tt(struct pt_regs *regs, unsigned long eip,
+ unsigned long esp);
+extern int copy_thread_tt(int nr, unsigned long clone_flags, unsigned long sp,
+ unsigned long stack_top, struct task_struct *p,
+ struct pt_regs *regs);
+extern void release_thread_tt(struct task_struct *task);
+extern void exit_thread_tt(void);
+extern void initial_thread_cb_tt(void (*proc)(void *), void *arg);
+extern void init_idle_tt(void);
+extern void flush_tlb_kernel_vm_tt(void);
+extern void __flush_tlb_one_tt(unsigned long addr);
+extern void flush_tlb_range_tt(struct vm_area_struct *vma,
+ unsigned long start, unsigned long end);
+extern void flush_tlb_mm_tt(struct mm_struct *mm);
+extern void force_flush_all_tt(void);
+extern long execute_syscall_tt(void *r);
+extern void before_mem_tt(unsigned long brk_start);
+extern unsigned long set_task_sizes_tt(int arg, unsigned long *host_size_out,
+ unsigned long *task_size_out);
+extern int start_uml_tt(void);
+extern struct page *arch_validate_tt(struct page *page, int mask, int order);
+extern int external_pid_tt(struct task_struct *task);
+extern int thread_pid_tt(struct task_struct *task);
+
+#define kmem_end_tt (host_task_size - ABOVE_KMEM)
+
+#endif
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only. This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff --git a/arch/um/kernel/tt/include/ptrace-tt.h b/arch/um/kernel/tt/include/ptrace-tt.h
new file mode 100644
index 000000000000..4e22b772c8f5
--- /dev/null
+++ b/arch/um/kernel/tt/include/ptrace-tt.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#ifndef __PTRACE_TT_H
+#define __PTRACE_TT_H
+
+#include "uml-config.h"
+
+#ifdef CONFIG_MODE_TT
+#include "sysdep/sc.h"
+#endif
+
+#endif
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only. This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff --git a/arch/um/kernel/tt/include/tt.h b/arch/um/kernel/tt/include/tt.h
new file mode 100644
index 000000000000..3769d2aabc66
--- /dev/null
+++ b/arch/um/kernel/tt/include/tt.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#ifndef __TT_H__
+#define __TT_H__
+
+#include "sysdep/ptrace.h"
+
+extern int gdb_pid;
+extern int debug;
+extern int debug_stop;
+extern int debug_trace;
+
+extern int honeypot;
+
+extern int fork_tramp(void *sig_stack);
+extern int do_proc_op(void *t, int proc_id);
+extern int tracer(int (*init_proc)(void *), void *sp);
+extern void attach_process(int pid);
+extern void tracer_panic(char *format, ...);
+extern void set_init_pid(int pid);
+extern int set_user_mode(void *task);
+extern void set_tracing(void *t, int tracing);
+extern int is_tracing(void *task);
+extern int singlestepping_tt(void *t);
+extern void clear_singlestep(void *t);
+extern void syscall_handler(int sig, struct uml_pt_regs *regs);
+extern void exit_kernel(int pid, void *task);
+extern int do_syscall(void *task, int pid);
+extern int is_valid_pid(int pid);
+
+#endif
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only. This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff --git a/arch/um/kernel/tt/include/uaccess.h b/arch/um/kernel/tt/include/uaccess.h
new file mode 100644
index 000000000000..902de9f3783c
--- /dev/null
+++ b/arch/um/kernel/tt/include/uaccess.h
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#ifndef __TT_UACCESS_H
+#define __TT_UACCESS_H
+
+#include "linux/string.h"
+#include "linux/sched.h"
+#include "asm/processor.h"
+#include "asm/errno.h"
+#include "asm/current.h"
+#include "asm/a.out.h"
+
+#define ABOVE_KMEM (16 * 1024 * 1024)
+
+extern unsigned long end_vm;
+extern unsigned long uml_physmem;
+
+#define under_task_size(addr, size) \
+ (((unsigned long) (addr) < TASK_SIZE) && \
+ (((unsigned long) (addr) + (size)) < TASK_SIZE))
+
+#define is_stack(addr, size) \
+ (((unsigned long) (addr) < STACK_TOP) && \
+ ((unsigned long) (addr) >= STACK_TOP - ABOVE_KMEM) && \
+ (((unsigned long) (addr) + (size)) <= STACK_TOP))
+
+#define access_ok_tt(type, addr, size) \
+ ((type == VERIFY_READ) || (segment_eq(get_fs(), KERNEL_DS)) || \
+ (((unsigned long) (addr) <= ((unsigned long) (addr) + (size))) && \
+ (under_task_size(addr, size) || is_stack(addr, size))))
+
+static inline int verify_area_tt(int type, const void * addr,
+ unsigned long size)
+{
+ return(access_ok_tt(type, addr, size) ? 0 : -EFAULT);
+}
+
+extern unsigned long get_fault_addr(void);
+
+extern int __do_copy_from_user(void *to, const void *from, int n,
+ void **fault_addr, void **fault_catcher);
+
+static inline int copy_from_user_tt(void *to, const void *from, int n)
+{
+ return(access_ok_tt(VERIFY_READ, from, n) ?
+ __do_copy_from_user(to, from, n,
+ &current->thread.fault_addr,
+ &current->thread.fault_catcher) : n);
+}
+
+extern int __do_copy_to_user(void *to, const void *from, int n,
+ void **fault_addr, void **fault_catcher);
+
+static inline int copy_to_user_tt(void *to, const void *from, int n)
+{
+ return(access_ok_tt(VERIFY_WRITE, to, n) ?
+ __do_copy_to_user(to, from, n,
+ &current->thread.fault_addr,
+ &current->thread.fault_catcher) : n);
+}
+
+extern int __do_strncpy_from_user(char *dst, const char *src, size_t n,
+ void **fault_addr, void **fault_catcher);
+
+static inline int strncpy_from_user_tt(char *dst, const char *src, int count)
+{
+ int n;
+
+ if(!access_ok_tt(VERIFY_READ, src, 1)) return(-EFAULT);
+ n = __do_strncpy_from_user(dst, src, count,
+ &current->thread.fault_addr,
+ &current->thread.fault_catcher);
+ if(n < 0) return(-EFAULT);
+ return(n);
+}
+
+extern int __do_clear_user(void *mem, size_t len, void **fault_addr,
+ void **fault_catcher);
+
+static inline int __clear_user_tt(void *mem, int len)
+{
+ return(__do_clear_user(mem, len,
+ &current->thread.fault_addr,
+ &current->thread.fault_catcher));
+}
+
+static inline int clear_user_tt(void *mem, int len)
+{
+ return(access_ok_tt(VERIFY_WRITE, mem, len) ?
+ __do_clear_user(mem, len,
+ &current->thread.fault_addr,
+ &current->thread.fault_catcher) : len);
+}
+
+extern int __do_strnlen_user(const char *str, unsigned long n,
+ void **fault_addr, void **fault_catcher);
+
+static inline int strnlen_user_tt(const void *str, int len)
+{
+ return(__do_strnlen_user(str, len,
+ &current->thread.fault_addr,
+ &current->thread.fault_catcher));
+}
+
+#endif
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only. This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff --git a/arch/um/kernel/tt/ksyms.c b/arch/um/kernel/tt/ksyms.c
new file mode 100644
index 000000000000..92ec85d67c7c
--- /dev/null
+++ b/arch/um/kernel/tt/ksyms.c
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#include "linux/module.h"
+#include "asm/uaccess.h"
+#include "mode.h"
+
+EXPORT_SYMBOL(__do_copy_from_user);
+EXPORT_SYMBOL(__do_copy_to_user);
+EXPORT_SYMBOL(__do_strncpy_from_user);
+EXPORT_SYMBOL(__do_strnlen_user);
+EXPORT_SYMBOL(__do_clear_user);
+
+EXPORT_SYMBOL(tracing_pid);
+EXPORT_SYMBOL(honeypot);
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only. This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff --git a/arch/um/kernel/tt/mem.c b/arch/um/kernel/tt/mem.c
new file mode 100644
index 000000000000..ff92e59bd86b
--- /dev/null
+++ b/arch/um/kernel/tt/mem.c
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#include "linux/stddef.h"
+#include "linux/config.h"
+#include "linux/mm.h"
+#include "asm/uaccess.h"
+#include "mem_user.h"
+#include "kern_util.h"
+#include "user_util.h"
+#include "kern.h"
+#include "tt.h"
+
+void before_mem_tt(unsigned long brk_start)
+{
+ if(!jail || debug)
+ remap_data(UML_ROUND_DOWN(&_stext), UML_ROUND_UP(&_etext), 1);
+ remap_data(UML_ROUND_DOWN(&_sdata), UML_ROUND_UP(&_edata), 1);
+ remap_data(UML_ROUND_DOWN(&__bss_start), UML_ROUND_UP(brk_start), 1);
+}
+
+#ifdef CONFIG_HOST_2G_2G
+#define TOP 0x80000000
+#else
+#define TOP 0xc0000000
+#endif
+
+#define SIZE ((CONFIG_NEST_LEVEL + CONFIG_KERNEL_HALF_GIGS) * 0x20000000)
+#define START (TOP - SIZE)
+
+unsigned long set_task_sizes_tt(int arg, unsigned long *host_size_out,
+ unsigned long *task_size_out)
+{
+ /* Round up to the nearest 4M */
+ *host_size_out = ROUND_4M((unsigned long) &arg);
+ *task_size_out = START;
+ return(START);
+}
+
+struct page *arch_validate_tt(struct page *page, int mask, int order)
+{
+ unsigned long addr, zero = 0;
+ int i;
+
+ again:
+ if(page == NULL) return(page);
+ if(PageHighMem(page)) return(page);
+
+ addr = (unsigned long) page_address(page);
+ for(i = 0; i < (1 << order); i++){
+ current->thread.fault_addr = (void *) addr;
+ if(__do_copy_to_user((void *) addr, &zero,
+ sizeof(zero),
+ &current->thread.fault_addr,
+ &current->thread.fault_catcher)){
+ if(!(mask & __GFP_WAIT)) return(NULL);
+ else break;
+ }
+ addr += PAGE_SIZE;
+ }
+ if(i == (1 << order)) return(page);
+ page = alloc_pages(mask, order);
+ goto again;
+}
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only. This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff --git a/arch/um/kernel/tt/process_kern.c b/arch/um/kernel/tt/process_kern.c
new file mode 100644
index 000000000000..a9f6264d1fc9
--- /dev/null
+++ b/arch/um/kernel/tt/process_kern.c
@@ -0,0 +1,513 @@
+/*
+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#include "linux/sched.h"
+#include "linux/signal.h"
+#include "linux/kernel.h"
+#include "asm/system.h"
+#include "asm/pgalloc.h"
+#include "asm/ptrace.h"
+#include "asm/tlbflush.h"
+#include "irq_user.h"
+#include "signal_user.h"
+#include "kern_util.h"
+#include "user_util.h"
+#include "os.h"
+#include "kern.h"
+#include "sigcontext.h"
+#include "time_user.h"
+#include "mem_user.h"
+#include "tlb.h"
+#include "mode.h"
+#include "init.h"
+#include "tt.h"
+
+void *switch_to_tt(void *prev, void *next, void *last)
+{
+ struct task_struct *from, *to;
+ unsigned long flags;
+ int err, vtalrm, alrm, prof, cpu;
+ char c;
+ /* jailing and SMP are incompatible, so this doesn't need to be
+ * made per-cpu
+ */
+ static int reading;
+
+ from = prev;
+ to = next;
+
+ to->thread.prev_sched = from;
+
+ cpu = from->thread_info->cpu;
+ if(cpu == 0)
+ forward_interrupts(to->thread.mode.tt.extern_pid);
+#ifdef CONFIG_SMP
+ forward_ipi(cpu_data[cpu].ipi_pipe[0], to->thread.mode.tt.extern_pid);
+#endif
+ local_irq_save(flags);
+
+ vtalrm = change_sig(SIGVTALRM, 0);
+ alrm = change_sig(SIGALRM, 0);
+ prof = change_sig(SIGPROF, 0);
+
+ forward_pending_sigio(to->thread.mode.tt.extern_pid);
+
+ c = 0;
+ set_current(to);
+
+ reading = 0;
+ err = os_write_file(to->thread.mode.tt.switch_pipe[1], &c, sizeof(c));
+ if(err != sizeof(c))
+ panic("write of switch_pipe failed, errno = %d", -err);
+
+ reading = 1;
+ if((from->state == TASK_ZOMBIE) || (from->state == TASK_DEAD))
+ os_kill_process(os_getpid(), 0);
+
+ err = os_read_file(from->thread.mode.tt.switch_pipe[0], &c, sizeof(c));
+ if(err != sizeof(c))
+ panic("read of switch_pipe failed, errno = %d", -err);
+
+ /* This works around a nasty race with 'jail'. If we are switching
+ * between two threads of a threaded app and the incoming process
+ * runs before the outgoing process reaches the read, and it makes
+ * it all the way out to userspace, then it will have write-protected
+ * the outgoing process stack. Then, when the outgoing process
+ * returns from the write, it will segfault because it can no longer
+ * write its own stack. So, in order to avoid that, the incoming
+ * thread sits in a loop yielding until 'reading' is set. This
+ * isn't entirely safe, since there may be a reschedule from a timer
+ * happening between setting 'reading' and sleeping in read. But,
+ * it should get a whole quantum in which to reach the read and sleep,
+ * which should be enough.
+ */
+
+ if(jail){
+ while(!reading) sched_yield();
+ }
+
+ change_sig(SIGVTALRM, vtalrm);
+ change_sig(SIGALRM, alrm);
+ change_sig(SIGPROF, prof);
+
+ arch_switch();
+
+ flush_tlb_all();
+ local_irq_restore(flags);
+
+ return(current->thread.prev_sched);
+}
+
+void release_thread_tt(struct task_struct *task)
+{
+ os_kill_process(task->thread.mode.tt.extern_pid, 0);
+}
+
+void exit_thread_tt(void)
+{
+ close(current->thread.mode.tt.switch_pipe[0]);
+ close(current->thread.mode.tt.switch_pipe[1]);
+}
+
+extern void schedule_tail(struct task_struct *prev);
+
+static void new_thread_handler(int sig)
+{
+ int (*fn)(void *);
+ void *arg;
+
+ fn = current->thread.request.u.thread.proc;
+ arg = current->thread.request.u.thread.arg;
+ current->thread.regs.regs.mode.tt = (void *) (&sig + 1);
+ suspend_new_thread(current->thread.mode.tt.switch_pipe[0]);
+
+ block_signals();
+ init_new_thread_signals(1);
+#ifdef CONFIG_SMP
+ schedule_tail(NULL);
+#endif
+ enable_timer();
+ free_page(current->thread.temp_stack);
+ set_cmdline("(kernel thread)");
+ force_flush_all();
+
+ current->thread.prev_sched = NULL;
+ change_sig(SIGUSR1, 1);
+ change_sig(SIGVTALRM, 1);
+ change_sig(SIGPROF, 1);
+ unblock_signals();
+ if(!run_kernel_thread(fn, arg, &current->thread.exec_buf))
+ do_exit(0);
+}
+
+static int new_thread_proc(void *stack)
+{
+ init_new_thread_stack(stack, new_thread_handler);
+ os_usr1_process(os_getpid());
+ return(0);
+}
+
+/* Signal masking - signals are blocked at the start of fork_tramp. They
+ * are re-enabled when finish_fork_handler is entered by fork_tramp hitting
+ * itself with a SIGUSR1. set_user_mode has to be run with SIGUSR1 off,
+ * so it is blocked before it's called. They are re-enabled on sigreturn
+ * despite the fact that they were blocked when the SIGUSR1 was issued because
+ * copy_thread copies the parent's signcontext, including the signal mask
+ * onto the signal frame.
+ */
+
+void finish_fork_handler(int sig)
+{
+ current->thread.regs.regs.mode.tt = (void *) (&sig + 1);
+ suspend_new_thread(current->thread.mode.tt.switch_pipe[0]);
+
+#ifdef CONFIG_SMP
+ schedule_tail(NULL);
+#endif
+ enable_timer();
+ change_sig(SIGVTALRM, 1);
+ force_flush_all();
+ if(current->mm != current->parent->mm)
+ protect_memory(uml_reserved, high_physmem - uml_reserved, 1,
+ 1, 0, 1);
+ task_protections((unsigned long) current->thread_info);
+
+ current->thread.prev_sched = NULL;
+
+ free_page(current->thread.temp_stack);
+ change_sig(SIGUSR1, 0);
+ set_user_mode(current);
+}
+
+static int sigusr1 = SIGUSR1;
+
+int fork_tramp(void *stack)
+{
+ int sig = sigusr1;
+
+ init_new_thread_stack(stack, finish_fork_handler);
+
+ kill(os_getpid(), sig);
+ return(0);
+}
+
+int copy_thread_tt(int nr, unsigned long clone_flags, unsigned long sp,
+ unsigned long stack_top, struct task_struct * p,
+ struct pt_regs *regs)
+{
+ int (*tramp)(void *);
+ int new_pid, err;
+ unsigned long stack;
+
+ if(current->thread.forking)
+ tramp = fork_tramp;
+ else {
+ tramp = new_thread_proc;
+ p->thread.request.u.thread = current->thread.request.u.thread;
+ }
+
+ err = os_pipe(p->thread.mode.tt.switch_pipe, 1, 1);
+ if(err){
+ printk("copy_thread : pipe failed, errno = %d\n", -err);
+ return(err);
+ }
+
+ stack = alloc_stack(0, 0);
+ if(stack == 0){
+ printk(KERN_ERR "copy_thread : failed to allocate "
+ "temporary stack\n");
+ return(-ENOMEM);
+ }
+
+ clone_flags &= CLONE_VM;
+ p->thread.temp_stack = stack;
+ new_pid = start_fork_tramp((void *) p->thread.kernel_stack, stack,
+ clone_flags, tramp);
+ if(new_pid < 0){
+ printk(KERN_ERR "copy_thread : clone failed - errno = %d\n",
+ -new_pid);
+ return(new_pid);
+ }
+
+ if(current->thread.forking){
+ sc_to_sc(p->thread.regs.regs.mode.tt,
+ current->thread.regs.regs.mode.tt);
+ SC_SET_SYSCALL_RETURN(p->thread.regs.regs.mode.tt, 0);
+ if(sp != 0) SC_SP(p->thread.regs.regs.mode.tt) = sp;
+ }
+ p->thread.mode.tt.extern_pid = new_pid;
+
+ current->thread.request.op = OP_FORK;
+ current->thread.request.u.fork.pid = new_pid;
+ os_usr1_process(os_getpid());
+ return(0);
+}
+
+void reboot_tt(void)
+{
+ current->thread.request.op = OP_REBOOT;
+ os_usr1_process(os_getpid());
+}
+
+void halt_tt(void)
+{
+ current->thread.request.op = OP_HALT;
+ os_usr1_process(os_getpid());
+}
+
+void kill_off_processes_tt(void)
+{
+ struct task_struct *p;
+ int me;
+
+ me = os_getpid();
+ for_each_process(p){
+ if(p->thread.mode.tt.extern_pid != me)
+ os_kill_process(p->thread.mode.tt.extern_pid, 0);
+ }
+ if(init_task.thread.mode.tt.extern_pid != me)
+ os_kill_process(init_task.thread.mode.tt.extern_pid, 0);
+}
+
+void initial_thread_cb_tt(void (*proc)(void *), void *arg)
+{
+ if(os_getpid() == tracing_pid){
+ (*proc)(arg);
+ }
+ else {
+ current->thread.request.op = OP_CB;
+ current->thread.request.u.cb.proc = proc;
+ current->thread.request.u.cb.arg = arg;
+ os_usr1_process(os_getpid());
+ }
+}
+
+int do_proc_op(void *t, int proc_id)
+{
+ struct task_struct *task;
+ struct thread_struct *thread;
+ int op, pid;
+
+ task = t;
+ thread = &task->thread;
+ op = thread->request.op;
+ switch(op){
+ case OP_NONE:
+ case OP_TRACE_ON:
+ break;
+ case OP_EXEC:
+ pid = thread->request.u.exec.pid;
+ do_exec(thread->mode.tt.extern_pid, pid);
+ thread->mode.tt.extern_pid = pid;
+ cpu_tasks[task->thread_info->cpu].pid = pid;
+ break;
+ case OP_FORK:
+ attach_process(thread->request.u.fork.pid);
+ break;
+ case OP_CB:
+ (*thread->request.u.cb.proc)(thread->request.u.cb.arg);
+ break;
+ case OP_REBOOT:
+ case OP_HALT:
+ break;
+ default:
+ tracer_panic("Bad op in do_proc_op");
+ break;
+ }
+ thread->request.op = OP_NONE;
+ return(op);
+}
+
+void init_idle_tt(void)
+{
+ default_idle();
+}
+
+/* Changed by jail_setup, which is a setup */
+int jail = 0;
+
+int __init jail_setup(char *line, int *add)
+{
+ int ok = 1;
+
+ if(jail) return(0);
+#ifdef CONFIG_SMP
+ printf("'jail' may not used used in a kernel with CONFIG_SMP "
+ "enabled\n");
+ ok = 0;
+#endif
+#ifdef CONFIG_HOSTFS
+ printf("'jail' may not used used in a kernel with CONFIG_HOSTFS "
+ "enabled\n");
+ ok = 0;
+#endif
+#ifdef CONFIG_MODULES
+ printf("'jail' may not used used in a kernel with CONFIG_MODULES "
+ "enabled\n");
+ ok = 0;
+#endif
+ if(!ok) exit(1);
+
+ /* CAP_SYS_RAWIO controls the ability to open /dev/mem and /dev/kmem.
+ * Removing it from the bounding set eliminates the ability of anything
+ * to acquire it, and thus read or write kernel memory.
+ */
+ cap_lower(cap_bset, CAP_SYS_RAWIO);
+ jail = 1;
+ return(0);
+}
+
+__uml_setup("jail", jail_setup,
+"jail\n"
+" Enables the protection of kernel memory from processes.\n\n"
+);
+
+static void mprotect_kernel_mem(int w)
+{
+ unsigned long start, end;
+
+ if(!jail || (current == &init_task)) return;
+
+ start = (unsigned long) current->thread_info + PAGE_SIZE;
+ end = (unsigned long) current->thread_info + PAGE_SIZE * 4;
+ protect_memory(uml_reserved, start - uml_reserved, 1, w, 1, 1);
+ protect_memory(end, high_physmem - end, 1, w, 1, 1);
+
+ start = (unsigned long) UML_ROUND_DOWN(&_stext);
+ end = (unsigned long) UML_ROUND_UP(&_etext);
+ protect_memory(start, end - start, 1, w, 1, 1);
+
+ start = (unsigned long) UML_ROUND_DOWN(&_unprotected_end);
+ end = (unsigned long) UML_ROUND_UP(&_edata);
+ protect_memory(start, end - start, 1, w, 1, 1);
+
+ start = (unsigned long) UML_ROUND_DOWN(&__bss_start);
+ end = (unsigned long) UML_ROUND_UP(brk_start);
+ protect_memory(start, end - start, 1, w, 1, 1);
+
+ mprotect_kernel_vm(w);
+}
+
+void unprotect_kernel_mem(void)
+{
+ mprotect_kernel_mem(1);
+}
+
+void protect_kernel_mem(void)
+{
+ mprotect_kernel_mem(0);
+}
+
+extern void start_kernel(void);
+
+static int start_kernel_proc(void *unused)
+{
+ int pid;
+
+ block_signals();
+ pid = os_getpid();
+
+ cpu_tasks[0].pid = pid;
+ cpu_tasks[0].task = current;
+#ifdef CONFIG_SMP
+ cpu_online_map = 1;
+#endif
+ if(debug) os_stop_process(pid);
+ start_kernel();
+ return(0);
+}
+
+void set_tracing(void *task, int tracing)
+{
+ ((struct task_struct *) task)->thread.mode.tt.tracing = tracing;
+}
+
+int is_tracing(void *t)
+{
+ return (((struct task_struct *) t)->thread.mode.tt.tracing);
+}
+
+int set_user_mode(void *t)
+{
+ struct task_struct *task;
+
+ task = t ? t : current;
+ if(task->thread.mode.tt.tracing)
+ return(1);
+ task->thread.request.op = OP_TRACE_ON;
+ os_usr1_process(os_getpid());
+ return(0);
+}
+
+void set_init_pid(int pid)
+{
+ int err;
+
+ init_task.thread.mode.tt.extern_pid = pid;
+ err = os_pipe(init_task.thread.mode.tt.switch_pipe, 1, 1);
+ if(err) panic("Can't create switch pipe for init_task, errno = %d",
+ err);
+}
+
+int singlestepping_tt(void *t)
+{
+ struct task_struct *task = t;
+
+ if(task->thread.mode.tt.singlestep_syscall)
+ return(0);
+ return(task->ptrace & PT_DTRACE);
+}
+
+void clear_singlestep(void *t)
+{
+ struct task_struct *task = t;
+
+ task->ptrace &= ~PT_DTRACE;
+}
+
+int start_uml_tt(void)
+{
+ void *sp;
+
+ sp = (void *) init_task.thread.kernel_stack + 2 * PAGE_SIZE -
+ sizeof(unsigned long);
+ return(tracer(start_kernel_proc, sp));
+}
+
+int external_pid_tt(struct task_struct *task)
+{
+ return(task->thread.mode.tt.extern_pid);
+}
+
+int thread_pid_tt(struct task_struct *task)
+{
+ return(task->thread.mode.tt.extern_pid);
+}
+
+int is_valid_pid(int pid)
+{
+ struct task_struct *task;
+
+ read_lock(&tasklist_lock);
+ for_each_process(task){
+ if(task->thread.mode.tt.extern_pid == pid){
+ read_unlock(&tasklist_lock);
+ return(1);
+ }
+ }
+ read_unlock(&tasklist_lock);
+ return(0);
+}
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only. This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff --git a/arch/um/kernel/tt/ptproxy/Makefile b/arch/um/kernel/tt/ptproxy/Makefile
new file mode 100644
index 000000000000..97d4f0bc18d7
--- /dev/null
+++ b/arch/um/kernel/tt/ptproxy/Makefile
@@ -0,0 +1,13 @@
+#
+# Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+# Licensed under the GPL
+#
+
+obj-y = proxy.o ptrace.o sysdep.o wait.o
+
+USER_OBJS := $(foreach file,$(obj-y),$(src)/$(file))
+
+$(USER_OBJS) : %.o: %.c
+ $(CC) $(CFLAGS_$(notdir $@)) $(USER_CFLAGS) -c -o $@ $<
+
+clean:
diff --git a/arch/um/ptproxy/proxy.c b/arch/um/kernel/tt/ptproxy/proxy.c
index d5cd8c8919ba..d5cd8c8919ba 100644
--- a/arch/um/ptproxy/proxy.c
+++ b/arch/um/kernel/tt/ptproxy/proxy.c
diff --git a/arch/um/ptproxy/ptproxy.h b/arch/um/kernel/tt/ptproxy/ptproxy.h
index 5eb0285b1968..5eb0285b1968 100644
--- a/arch/um/ptproxy/ptproxy.h
+++ b/arch/um/kernel/tt/ptproxy/ptproxy.h
diff --git a/arch/um/ptproxy/ptrace.c b/arch/um/kernel/tt/ptproxy/ptrace.c
index 910d026677ca..721d0a306fde 100644
--- a/arch/um/ptproxy/ptrace.c
+++ b/arch/um/kernel/tt/ptproxy/ptrace.c
@@ -21,6 +21,7 @@ Jeff Dike (jdike@karaya.com) : Modified for integration into uml
#include "user_util.h"
#include "kern_util.h"
#include "ptrace_user.h"
+#include "tt.h"
long proxy_ptrace(struct debugger *debugger, int arg1, pid_t arg2,
long arg3, long arg4, pid_t child, int *ret)
diff --git a/arch/um/ptproxy/sysdep.c b/arch/um/kernel/tt/ptproxy/sysdep.c
index 50a120d5e65c..50a120d5e65c 100644
--- a/arch/um/ptproxy/sysdep.c
+++ b/arch/um/kernel/tt/ptproxy/sysdep.c
diff --git a/arch/um/ptproxy/sysdep.h b/arch/um/kernel/tt/ptproxy/sysdep.h
index 735f488049aa..735f488049aa 100644
--- a/arch/um/ptproxy/sysdep.h
+++ b/arch/um/kernel/tt/ptproxy/sysdep.h
diff --git a/arch/um/ptproxy/wait.c b/arch/um/kernel/tt/ptproxy/wait.c
index aad7e4b62ee5..aad7e4b62ee5 100644
--- a/arch/um/ptproxy/wait.c
+++ b/arch/um/kernel/tt/ptproxy/wait.c
diff --git a/arch/um/ptproxy/wait.h b/arch/um/kernel/tt/ptproxy/wait.h
index 542e73ee2cee..542e73ee2cee 100644
--- a/arch/um/ptproxy/wait.h
+++ b/arch/um/kernel/tt/ptproxy/wait.h
diff --git a/arch/um/kernel/tt/sys-i386/Makefile b/arch/um/kernel/tt/sys-i386/Makefile
new file mode 100644
index 000000000000..2ad8271c604d
--- /dev/null
+++ b/arch/um/kernel/tt/sys-i386/Makefile
@@ -0,0 +1,14 @@
+#
+# Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+# Licensed under the GPL
+#
+
+obj-y = sigcontext.o
+
+USER_OBJS = sigcontext.o
+USER_OBJS := $(foreach file,$(USER_OBJS),$(obj)/$(file))
+
+$(USER_OBJS) : %.o: %.c
+ $(CC) $(CFLAGS_$(notdir $@)) $(USER_CFLAGS) -c -o $@ $<
+
+clean :
diff --git a/arch/um/kernel/tt/sys-i386/sigcontext.c b/arch/um/kernel/tt/sys-i386/sigcontext.c
new file mode 100644
index 000000000000..1701c0dfb030
--- /dev/null
+++ b/arch/um/kernel/tt/sys-i386/sigcontext.c
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#include <stdlib.h>
+#include <asm/sigcontext.h>
+#include "kern_util.h"
+#include "sysdep/frame.h"
+
+int copy_sc_from_user_tt(void *to_ptr, void *from_ptr, void *data)
+{
+ struct arch_frame_data *arch = data;
+ struct sigcontext *to = to_ptr, *from = from_ptr;
+ struct _fpstate *to_fp, *from_fp;
+ unsigned long sigs;
+ int err;
+
+ to_fp = to->fpstate;
+ from_fp = from->fpstate;
+ sigs = to->oldmask;
+ err = copy_from_user_proc(to, from, sizeof(*to));
+ to->oldmask = sigs;
+ if(to_fp != NULL){
+ err |= copy_from_user_proc(&to->fpstate, &to_fp,
+ sizeof(to->fpstate));
+ err |= copy_from_user_proc(to_fp, from_fp, arch->fpstate_size);
+ }
+ return(err);
+}
+
+int copy_sc_to_user_tt(void *to_ptr, void *from_ptr, void *data)
+{
+ struct arch_frame_data *arch = data;
+ struct sigcontext *to = to_ptr, *from = from_ptr;
+ struct _fpstate *to_fp, *from_fp;
+ int err;
+
+ to_fp = (struct _fpstate *)((unsigned long) to + sizeof(*to));
+ from_fp = from->fpstate;
+ err = copy_to_user_proc(to, from, sizeof(*to));
+ if(from_fp != NULL){
+ err |= copy_to_user_proc(&to->fpstate, &to_fp,
+ sizeof(to->fpstate));
+ err |= copy_to_user_proc(to_fp, from_fp, arch->fpstate_size);
+ }
+ return(err);
+}
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only. This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff --git a/arch/um/kernel/tt/syscall_kern.c b/arch/um/kernel/tt/syscall_kern.c
new file mode 100644
index 000000000000..3fb449db2885
--- /dev/null
+++ b/arch/um/kernel/tt/syscall_kern.c
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#include "linux/types.h"
+#include "linux/utime.h"
+#include "linux/sys.h"
+#include "asm/unistd.h"
+#include "asm/ptrace.h"
+#include "asm/uaccess.h"
+#include "asm/stat.h"
+#include "sysdep/syscalls.h"
+#include "kern_util.h"
+
+static inline int check_area(void *ptr, int size)
+{
+ return(verify_area(VERIFY_WRITE, ptr, size));
+}
+
+static int check_readlink(struct pt_regs *regs)
+{
+ return(check_area((void *) regs->regs.args[1], regs->regs.args[2]));
+}
+
+static int check_utime(struct pt_regs *regs)
+{
+ return(check_area((void *) regs->regs.args[1],
+ sizeof(struct utimbuf)));
+}
+
+static int check_oldstat(struct pt_regs *regs)
+{
+ return(check_area((void *) regs->regs.args[1],
+ sizeof(struct __old_kernel_stat)));
+}
+
+static int check_stat(struct pt_regs *regs)
+{
+ return(check_area((void *) regs->regs.args[1], sizeof(struct stat)));
+}
+
+static int check_stat64(struct pt_regs *regs)
+{
+ return(check_area((void *) regs->regs.args[1], sizeof(struct stat64)));
+}
+
+struct bogus {
+ int kernel_ds;
+ int (*check_params)(struct pt_regs *);
+};
+
+struct bogus this_is_bogus[256] = {
+ [ __NR_mknod ] = { 1, NULL },
+ [ __NR_mkdir ] = { 1, NULL },
+ [ __NR_rmdir ] = { 1, NULL },
+ [ __NR_unlink ] = { 1, NULL },
+ [ __NR_symlink ] = { 1, NULL },
+ [ __NR_link ] = { 1, NULL },
+ [ __NR_rename ] = { 1, NULL },
+ [ __NR_umount ] = { 1, NULL },
+ [ __NR_mount ] = { 1, NULL },
+ [ __NR_pivot_root ] = { 1, NULL },
+ [ __NR_chdir ] = { 1, NULL },
+ [ __NR_chroot ] = { 1, NULL },
+ [ __NR_open ] = { 1, NULL },
+ [ __NR_quotactl ] = { 1, NULL },
+ [ __NR_sysfs ] = { 1, NULL },
+ [ __NR_readlink ] = { 1, check_readlink },
+ [ __NR_acct ] = { 1, NULL },
+ [ __NR_execve ] = { 1, NULL },
+ [ __NR_uselib ] = { 1, NULL },
+ [ __NR_statfs ] = { 1, NULL },
+ [ __NR_truncate ] = { 1, NULL },
+ [ __NR_access ] = { 1, NULL },
+ [ __NR_chmod ] = { 1, NULL },
+ [ __NR_chown ] = { 1, NULL },
+ [ __NR_lchown ] = { 1, NULL },
+ [ __NR_utime ] = { 1, check_utime },
+ [ __NR_oldlstat ] = { 1, check_oldstat },
+ [ __NR_oldstat ] = { 1, check_oldstat },
+ [ __NR_stat ] = { 1, check_stat },
+ [ __NR_lstat ] = { 1, check_stat },
+ [ __NR_stat64 ] = { 1, check_stat64 },
+ [ __NR_lstat64 ] = { 1, check_stat64 },
+ [ __NR_chown32 ] = { 1, NULL },
+};
+
+/* sys_utimes */
+
+static int check_bogosity(struct pt_regs *regs)
+{
+ struct bogus *bogon = &this_is_bogus[regs->regs.syscall];
+
+ if(!bogon->kernel_ds) return(0);
+ if(bogon->check_params && (*bogon->check_params)(regs))
+ return(-EFAULT);
+ set_fs(KERNEL_DS);
+ return(0);
+}
+
+extern syscall_handler_t *sys_call_table[];
+
+long execute_syscall_tt(void *r)
+{
+ struct pt_regs *regs = r;
+ long res;
+ int syscall;
+
+ current->thread.nsyscalls++;
+ nsyscalls++;
+ syscall = regs->regs.syscall;
+
+ if((syscall >= NR_syscalls) || (syscall < 0))
+ res = -ENOSYS;
+ else if(honeypot && check_bogosity(regs))
+ res = -EFAULT;
+ else res = EXECUTE_SYSCALL(syscall, regs);
+
+ set_fs(USER_DS);
+
+ if(current->thread.mode.tt.singlestep_syscall){
+ current->thread.mode.tt.singlestep_syscall = 0;
+ current->ptrace &= ~PT_DTRACE;
+ force_sig(SIGTRAP, current);
+ }
+
+ return(res);
+}
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only. This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff --git a/arch/um/kernel/tt/syscall_user.c b/arch/um/kernel/tt/syscall_user.c
new file mode 100644
index 000000000000..699e91f09c92
--- /dev/null
+++ b/arch/um/kernel/tt/syscall_user.c
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#include <unistd.h>
+#include <signal.h>
+#include <errno.h>
+#include <sys/ptrace.h>
+#include <asm/unistd.h>
+#include "sysdep/ptrace.h"
+#include "sigcontext.h"
+#include "ptrace_user.h"
+#include "task.h"
+#include "user_util.h"
+#include "kern_util.h"
+#include "syscall_user.h"
+#include "tt.h"
+
+/* XXX Bogus */
+#define ERESTARTSYS 512
+#define ERESTARTNOINTR 513
+#define ERESTARTNOHAND 514
+
+void syscall_handler_tt(int sig, struct uml_pt_regs *regs)
+{
+ void *sc;
+ long result;
+ int index, syscall;
+
+ syscall = regs->syscall;
+ sc = regs->mode.tt;
+ sc_to_regs(regs, sc, syscall);
+ SC_START_SYSCALL(sc);
+
+ index = record_syscall_start(syscall);
+ syscall_trace();
+ result = execute_syscall(regs);
+
+ /* regs->sc may have changed while the system call ran (there may
+ * have been an interrupt or segfault), so it needs to be refreshed.
+ */
+ regs->mode.tt = sc;
+
+ SC_SET_SYSCALL_RETURN(sc, result);
+ if((result == -ERESTARTNOHAND) || (result == -ERESTARTSYS) ||
+ (result == -ERESTARTNOINTR))
+ do_signal(result);
+
+ syscall_trace();
+ record_syscall_end(index, result);
+}
+
+int do_syscall(void *task, int pid)
+{
+ unsigned long proc_regs[FRAME_SIZE];
+ struct uml_pt_regs *regs;
+ int syscall;
+
+ if(ptrace_getregs(pid, proc_regs) < 0)
+ tracer_panic("Couldn't read registers");
+ syscall = PT_SYSCALL_NR(proc_regs);
+
+ regs = TASK_REGS(task);
+ UPT_SYSCALL_NR(regs) = syscall;
+
+ if(syscall < 1) return(0);
+
+ if((syscall != __NR_sigreturn) &&
+ ((unsigned long *) PT_IP(proc_regs) >= &_stext) &&
+ ((unsigned long *) PT_IP(proc_regs) <= &_etext))
+ tracer_panic("I'm tracing myself and I can't get out");
+
+ if(ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_NR_OFFSET,
+ __NR_getpid) < 0)
+ tracer_panic("do_syscall : Nullifying syscall failed, "
+ "errno = %d", errno);
+ return(1);
+}
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only. This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff --git a/arch/um/kernel/tt/time.c b/arch/um/kernel/tt/time.c
new file mode 100644
index 000000000000..8565b71b07cd
--- /dev/null
+++ b/arch/um/kernel/tt/time.c
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#include <signal.h>
+#include <sys/time.h>
+#include <time_user.h>
+#include "process.h"
+#include "user.h"
+
+void user_time_init_tt(void)
+{
+ if(signal(SIGVTALRM, (__sighandler_t) alarm_handler) == SIG_ERR)
+ panic("Couldn't set SIGVTALRM handler");
+ set_interval(ITIMER_VIRTUAL);
+}
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only. This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff --git a/arch/um/kernel/tt/tlb.c b/arch/um/kernel/tt/tlb.c
new file mode 100644
index 000000000000..e7e95a5c6ad2
--- /dev/null
+++ b/arch/um/kernel/tt/tlb.c
@@ -0,0 +1,226 @@
+/*
+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#include "linux/stddef.h"
+#include "linux/kernel.h"
+#include "linux/sched.h"
+#include "linux/mm.h"
+#include "asm/page.h"
+#include "asm/pgtable.h"
+#include "asm/uaccess.h"
+#include "user_util.h"
+#include "mem_user.h"
+#include "os.h"
+
+static void fix_range(struct mm_struct *mm, unsigned long start_addr,
+ unsigned long end_addr, int force)
+{
+ pgd_t *npgd;
+ pmd_t *npmd;
+ pte_t *npte;
+ unsigned long addr;
+ int r, w, x, err;
+
+ if((current->thread.mode.tt.extern_pid != -1) &&
+ (current->thread.mode.tt.extern_pid != os_getpid()))
+ panic("fix_range fixing wrong address space, current = 0x%p",
+ current);
+ if(mm == NULL) return;
+ for(addr=start_addr;addr<end_addr;){
+ if(addr == TASK_SIZE){
+ /* Skip over kernel text, kernel data, and physical
+ * memory, which don't have ptes, plus kernel virtual
+ * memory, which is flushed separately, and remap
+ * the process stack. The only way to get here is
+ * if (end_addr == STACK_TOP) > TASK_SIZE, which is
+ * only true in the honeypot case.
+ */
+ addr = STACK_TOP - ABOVE_KMEM;
+ continue;
+ }
+ npgd = pgd_offset(mm, addr);
+ npmd = pmd_offset(npgd, addr);
+ if(pmd_present(*npmd)){
+ npte = pte_offset_kernel(npmd, addr);
+ r = pte_read(*npte);
+ w = pte_write(*npte);
+ x = pte_exec(*npte);
+ if(!pte_dirty(*npte)) w = 0;
+ if(!pte_young(*npte)){
+ r = 0;
+ w = 0;
+ }
+ if(force || pte_newpage(*npte)){
+ err = os_unmap_memory((void *) addr,
+ PAGE_SIZE);
+ if(err < 0)
+ panic("munmap failed, errno = %d\n",
+ -err);
+ if(pte_present(*npte))
+ map_memory(addr,
+ pte_val(*npte) & PAGE_MASK,
+ PAGE_SIZE, r, w, x);
+ }
+ else if(pte_newprot(*npte)){
+ protect_memory(addr, PAGE_SIZE, r, w, x, 1);
+ }
+ *npte = pte_mkuptodate(*npte);
+ addr += PAGE_SIZE;
+ }
+ else {
+ if(force || pmd_newpage(*npmd)){
+ err = os_unmap_memory((void *) addr, PMD_SIZE);
+ if(err < 0)
+ panic("munmap failed, errno = %d\n",
+ -err);
+ pmd_mkuptodate(*npmd);
+ }
+ addr += PMD_SIZE;
+ }
+ }
+}
+
+atomic_t vmchange_seq = ATOMIC_INIT(1);
+
+static void flush_kernel_vm_range(unsigned long start, unsigned long end,
+ int update_seq)
+{
+ struct mm_struct *mm;
+ pgd_t *pgd;
+ pmd_t *pmd;
+ pte_t *pte;
+ unsigned long addr;
+ int updated = 0, err;
+
+ mm = &init_mm;
+ for(addr = start; addr < end;){
+ pgd = pgd_offset(mm, addr);
+ pmd = pmd_offset(pgd, addr);
+ if(pmd_present(*pmd)){
+ pte = pte_offset_kernel(pmd, addr);
+ if(!pte_present(*pte) || pte_newpage(*pte)){
+ updated = 1;
+ err = os_unmap_memory((void *) addr,
+ PAGE_SIZE);
+ if(err < 0)
+ panic("munmap failed, errno = %d\n",
+ -err);
+ if(pte_present(*pte))
+ map_memory(addr,
+ pte_val(*pte) & PAGE_MASK,
+ PAGE_SIZE, 1, 1, 1);
+ }
+ else if(pte_newprot(*pte)){
+ updated = 1;
+ protect_memory(addr, PAGE_SIZE, 1, 1, 1, 1);
+ }
+ addr += PAGE_SIZE;
+ }
+ else {
+ if(pmd_newpage(*pmd)){
+ updated = 1;
+ err = os_unmap_memory((void *) addr, PMD_SIZE);
+ if(err < 0)
+ panic("munmap failed, errno = %d\n",
+ -err);
+ }
+ addr += PMD_SIZE;
+ }
+ }
+ if(updated && update_seq) atomic_inc(&vmchange_seq);
+}
+
+void flush_tlb_kernel_range(unsigned long start, unsigned long end)
+{
+ flush_kernel_vm_range(start, end, 1);
+}
+
+static void protect_vm_page(unsigned long addr, int w, int must_succeed)
+{
+ int err;
+
+ err = protect_memory(addr, PAGE_SIZE, 1, w, 1, must_succeed);
+ if(err == 0) return;
+ else if((err == -EFAULT) || (err == -ENOMEM)){
+ flush_tlb_kernel_range(addr, addr + PAGE_SIZE);
+ protect_vm_page(addr, w, 1);
+ }
+ else panic("protect_vm_page : protect failed, errno = %d\n", err);
+}
+
+void mprotect_kernel_vm(int w)
+{
+ struct mm_struct *mm;
+ pgd_t *pgd;
+ pmd_t *pmd;
+ pte_t *pte;
+ unsigned long addr;
+
+ mm = &init_mm;
+ for(addr = start_vm; addr < end_vm;){
+ pgd = pgd_offset(mm, addr);
+ pmd = pmd_offset(pgd, addr);
+ if(pmd_present(*pmd)){
+ pte = pte_offset_kernel(pmd, addr);
+ if(pte_present(*pte)) protect_vm_page(addr, w, 0);
+ addr += PAGE_SIZE;
+ }
+ else addr += PMD_SIZE;
+ }
+}
+
+void flush_tlb_kernel_vm_tt(void)
+{
+ flush_tlb_kernel_range(start_vm, end_vm);
+}
+
+void __flush_tlb_one_tt(unsigned long addr)
+{
+ flush_tlb_kernel_range(addr, addr + PAGE_SIZE);
+}
+
+void flush_tlb_range_tt(struct vm_area_struct *vma, unsigned long start,
+ unsigned long end)
+{
+ if(vma->vm_mm != current->mm) return;
+
+ /* Assumes that the range start ... end is entirely within
+ * either process memory or kernel vm
+ */
+ if((start >= start_vm) && (start < end_vm))
+ flush_kernel_vm_range(start, end, 1);
+ else fix_range(vma->vm_mm, start, end, 0);
+}
+
+void flush_tlb_mm_tt(struct mm_struct *mm)
+{
+ unsigned long seq;
+
+ if(mm != current->mm) return;
+
+ fix_range(mm, 0, STACK_TOP, 0);
+
+ seq = atomic_read(&vmchange_seq);
+ if(current->thread.mode.tt.vm_seq == seq) return;
+ current->thread.mode.tt.vm_seq = seq;
+ flush_kernel_vm_range(start_vm, end_vm, 0);
+}
+
+void force_flush_all_tt(void)
+{
+ fix_range(current->mm, 0, STACK_TOP, 1);
+ flush_kernel_vm_range(start_vm, end_vm, 0);
+}
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only. This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff --git a/arch/um/kernel/tt/tracer.c b/arch/um/kernel/tt/tracer.c
new file mode 100644
index 000000000000..90e948c836bb
--- /dev/null
+++ b/arch/um/kernel/tt/tracer.c
@@ -0,0 +1,466 @@
+/*
+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <unistd.h>
+#include <signal.h>
+#include <errno.h>
+#include <sched.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <sys/ptrace.h>
+#include <sys/time.h>
+#include <sys/wait.h>
+#include "user.h"
+#include "sysdep/ptrace.h"
+#include "sigcontext.h"
+#include "sysdep/sigcontext.h"
+#include "os.h"
+#include "signal_user.h"
+#include "user_util.h"
+#include "mem_user.h"
+#include "process.h"
+#include "kern_util.h"
+#include "frame.h"
+#include "chan_user.h"
+#include "ptrace_user.h"
+#include "mode.h"
+#include "tt.h"
+
+static int tracer_winch[2];
+
+int is_tracer_winch(int pid, int fd, void *data)
+{
+ if(pid != tracing_pid)
+ return(0);
+
+ register_winch_irq(tracer_winch[0], fd, -1, data);
+ return(0);
+}
+
+static void tracer_winch_handler(int sig)
+{
+ char c = 1;
+
+ if(write(tracer_winch[1], &c, sizeof(c)) != sizeof(c))
+ printk("tracer_winch_handler - write failed, errno = %d\n",
+ errno);
+}
+
+/* Called only by the tracing thread during initialization */
+
+static void setup_tracer_winch(void)
+{
+ int err;
+
+ err = os_pipe(tracer_winch, 1, 1);
+ if(err){
+ printk("setup_tracer_winch : os_pipe failed, errno = %d\n",
+ -err);
+ return;
+ }
+ signal(SIGWINCH, tracer_winch_handler);
+}
+
+void attach_process(int pid)
+{
+ if((ptrace(PTRACE_ATTACH, pid, 0, 0) < 0) ||
+ (ptrace(PTRACE_CONT, pid, 0, 0) < 0))
+ tracer_panic("OP_FORK failed to attach pid");
+ wait_for_stop(pid, SIGSTOP, PTRACE_CONT, NULL);
+ if(ptrace(PTRACE_CONT, pid, 0, 0) < 0)
+ tracer_panic("OP_FORK failed to continue process");
+}
+
+void tracer_panic(char *format, ...)
+{
+ va_list ap;
+
+ va_start(ap, format);
+ vprintf(format, ap);
+ printf("\n");
+ while(1) pause();
+}
+
+static void tracer_segv(int sig, struct sigcontext sc)
+{
+ printf("Tracing thread segfault at address 0x%lx, ip 0x%lx\n",
+ SC_FAULT_ADDR(&sc), SC_IP(&sc));
+ while(1)
+ pause();
+}
+
+/* Changed early in boot, and then only read */
+int debug = 0;
+int debug_stop = 1;
+int debug_parent = 0;
+int honeypot = 0;
+
+static int signal_tramp(void *arg)
+{
+ int (*proc)(void *);
+
+ if(honeypot && munmap((void *) (host_task_size - 0x10000000),
+ 0x10000000))
+ panic("Unmapping stack failed");
+ if(ptrace(PTRACE_TRACEME, 0, 0, 0) < 0)
+ panic("ptrace PTRACE_TRACEME failed");
+ os_stop_process(os_getpid());
+ change_sig(SIGWINCH, 0);
+ signal(SIGUSR1, SIG_IGN);
+ change_sig(SIGCHLD, 0);
+ signal(SIGSEGV, (__sighandler_t) sig_handler);
+ set_cmdline("(idle thread)");
+ set_init_pid(os_getpid());
+ proc = arg;
+ return((*proc)(NULL));
+}
+
+static void last_ditch_exit(int sig)
+{
+ kmalloc_ok = 0;
+ signal(SIGINT, SIG_DFL);
+ signal(SIGTERM, SIG_DFL);
+ signal(SIGHUP, SIG_DFL);
+ uml_cleanup();
+ exit(1);
+}
+
+static void sleeping_process_signal(int pid, int sig)
+{
+ switch(sig){
+ /* These two result from UML being ^Z-ed and bg-ed. PTRACE_CONT is
+ * right because the process must be in the kernel already.
+ */
+ case SIGCONT:
+ case SIGTSTP:
+ if(ptrace(PTRACE_CONT, pid, 0, sig) < 0)
+ tracer_panic("sleeping_process_signal : Failed to "
+ "continue pid %d, errno = %d\n", pid,
+ sig);
+ break;
+
+ /* This happens when the debugger (e.g. strace) is doing system call
+ * tracing on the kernel. During a context switch, the current task
+ * will be set to the incoming process and the outgoing process will
+ * hop into write and then read. Since it's not the current process
+ * any more, the trace of those will land here. So, we need to just
+ * PTRACE_SYSCALL it.
+ */
+ case SIGTRAP:
+ if(ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0)
+ tracer_panic("sleeping_process_signal : Failed to "
+ "PTRACE_SYSCALL pid %d, errno = %d\n",
+ pid, sig);
+ break;
+ case SIGSTOP:
+ break;
+ default:
+ tracer_panic("sleeping process %d got unexpected "
+ "signal : %d\n", pid, sig);
+ break;
+ }
+}
+
+/* Accessed only by the tracing thread */
+int debugger_pid = -1;
+int debugger_parent = -1;
+int debugger_fd = -1;
+int gdb_pid = -1;
+
+struct {
+ int pid;
+ int signal;
+ unsigned long addr;
+ struct timeval time;
+} signal_record[1024][32];
+
+int signal_index[32];
+int nsignals = 0;
+int debug_trace = 0;
+extern int io_nsignals, io_count, intr_count;
+
+extern void signal_usr1(int sig);
+
+int tracing_pid = -1;
+
+int tracer(int (*init_proc)(void *), void *sp)
+{
+ void *task = NULL;
+ unsigned long eip = 0;
+ int status, pid = 0, sig = 0, cont_type, tracing = 0, op = 0;
+ int last_index, proc_id = 0, n, err, old_tracing = 0, strace = 0;
+
+ capture_signal_stack();
+ signal(SIGPIPE, SIG_IGN);
+ setup_tracer_winch();
+ tracing_pid = os_getpid();
+ printf("tracing thread pid = %d\n", tracing_pid);
+
+ pid = clone(signal_tramp, sp, CLONE_FILES | SIGCHLD, init_proc);
+ n = waitpid(pid, &status, WUNTRACED);
+ if(n < 0){
+ printf("waitpid on idle thread failed, errno = %d\n", errno);
+ exit(1);
+ }
+ if((ptrace(PTRACE_CONT, pid, 0, 0) < 0)){
+ printf("Failed to continue idle thread, errno = %d\n", errno);
+ exit(1);
+ }
+
+ signal(SIGSEGV, (sighandler_t) tracer_segv);
+ signal(SIGUSR1, signal_usr1);
+ set_handler(SIGINT, last_ditch_exit, SA_ONESHOT | SA_NODEFER, -1);
+ set_handler(SIGTERM, last_ditch_exit, SA_ONESHOT | SA_NODEFER, -1);
+ set_handler(SIGHUP, last_ditch_exit, SA_ONESHOT | SA_NODEFER, -1);
+ if(debug_trace){
+ printf("Tracing thread pausing to be attached\n");
+ stop();
+ }
+ if(debug){
+ if(gdb_pid != -1)
+ debugger_pid = attach_debugger(pid, gdb_pid, 1);
+ else debugger_pid = init_ptrace_proxy(pid, 1, debug_stop);
+ if(debug_parent){
+ debugger_parent = os_process_parent(debugger_pid);
+ init_parent_proxy(debugger_parent);
+ err = attach(debugger_parent);
+ if(err){
+ printf("Failed to attach debugger parent %d, "
+ "errno = %d\n", debugger_parent, err);
+ debugger_parent = -1;
+ }
+ else {
+ if(ptrace(PTRACE_SYSCALL, debugger_parent,
+ 0, 0) < 0){
+ printf("Failed to continue debugger "
+ "parent, errno = %d\n", errno);
+ debugger_parent = -1;
+ }
+ }
+ }
+ }
+ set_cmdline("(tracing thread)");
+ while(1){
+ if((pid = waitpid(-1, &status, WUNTRACED)) <= 0){
+ if(errno != ECHILD){
+ printf("wait failed - errno = %d\n", errno);
+ }
+ continue;
+ }
+ if(pid == debugger_pid){
+ int cont = 0;
+
+ if(WIFEXITED(status) || WIFSIGNALED(status))
+ debugger_pid = -1;
+ /* XXX Figure out how to deal with gdb and SMP */
+ else cont = debugger_signal(status, cpu_tasks[0].pid);
+ if(cont == PTRACE_SYSCALL) strace = 1;
+ continue;
+ }
+ else if(pid == debugger_parent){
+ debugger_parent_signal(status, pid);
+ continue;
+ }
+ nsignals++;
+ if(WIFEXITED(status)) ;
+#ifdef notdef
+ {
+ printf("Child %d exited with status %d\n", pid,
+ WEXITSTATUS(status));
+ }
+#endif
+ else if(WIFSIGNALED(status)){
+ sig = WTERMSIG(status);
+ if(sig != 9){
+ printf("Child %d exited with signal %d\n", pid,
+ sig);
+ }
+ }
+ else if(WIFSTOPPED(status)){
+ proc_id = pid_to_processor_id(pid);
+ sig = WSTOPSIG(status);
+ if(signal_index[proc_id] == 1024){
+ signal_index[proc_id] = 0;
+ last_index = 1023;
+ }
+ else last_index = signal_index[proc_id] - 1;
+ if(((sig == SIGPROF) || (sig == SIGVTALRM) ||
+ (sig == SIGALRM)) &&
+ (signal_record[proc_id][last_index].signal == sig)&&
+ (signal_record[proc_id][last_index].pid == pid))
+ signal_index[proc_id] = last_index;
+ signal_record[proc_id][signal_index[proc_id]].pid = pid;
+ gettimeofday(&signal_record[proc_id][signal_index[proc_id]].time, NULL);
+ eip = ptrace(PTRACE_PEEKUSER, pid, PT_IP_OFFSET, 0);
+ signal_record[proc_id][signal_index[proc_id]].addr = eip;
+ signal_record[proc_id][signal_index[proc_id]++].signal = sig;
+
+ if(proc_id == -1){
+ sleeping_process_signal(pid, sig);
+ continue;
+ }
+
+ task = cpu_tasks[proc_id].task;
+ tracing = is_tracing(task);
+ old_tracing = tracing;
+
+ switch(sig){
+ case SIGUSR1:
+ sig = 0;
+ op = do_proc_op(task, proc_id);
+ switch(op){
+ case OP_TRACE_ON:
+ arch_leave_kernel(task, pid);
+ tracing = 1;
+ break;
+ case OP_REBOOT:
+ case OP_HALT:
+ unmap_physmem();
+ kmalloc_ok = 0;
+ ptrace(PTRACE_KILL, pid, 0, 0);
+ return(op == OP_REBOOT);
+ case OP_NONE:
+ printf("Detaching pid %d\n", pid);
+ detach(pid, SIGSTOP);
+ continue;
+ default:
+ break;
+ }
+ /* OP_EXEC switches host processes on us,
+ * we want to continue the new one.
+ */
+ pid = cpu_tasks[proc_id].pid;
+ break;
+ case SIGTRAP:
+ if(!tracing && (debugger_pid != -1)){
+ child_signal(pid, status);
+ continue;
+ }
+ tracing = 0;
+ if(do_syscall(task, pid)) sig = SIGUSR2;
+ else clear_singlestep(task);
+ break;
+ case SIGPROF:
+ if(tracing) sig = 0;
+ break;
+ case SIGCHLD:
+ case SIGHUP:
+ sig = 0;
+ break;
+ case SIGSEGV:
+ case SIGIO:
+ case SIGALRM:
+ case SIGVTALRM:
+ case SIGFPE:
+ case SIGBUS:
+ case SIGILL:
+ case SIGWINCH:
+ default:
+ tracing = 0;
+ break;
+ }
+ set_tracing(task, tracing);
+
+ if(!tracing && old_tracing)
+ arch_enter_kernel(task, pid);
+
+ if(!tracing && (debugger_pid != -1) && (sig != 0) &&
+ (sig != SIGALRM) && (sig != SIGVTALRM) &&
+ (sig != SIGSEGV) && (sig != SIGTRAP) &&
+ (sig != SIGUSR2) && (sig != SIGIO) &&
+ (sig != SIGFPE)){
+ child_signal(pid, status);
+ continue;
+ }
+
+ if(tracing){
+ if(singlestepping_tt(task))
+ cont_type = PTRACE_SINGLESTEP;
+ else cont_type = PTRACE_SYSCALL;
+ }
+ else cont_type = PTRACE_CONT;
+
+ if((cont_type == PTRACE_CONT) &&
+ (debugger_pid != -1) && strace)
+ cont_type = PTRACE_SYSCALL;
+
+ if(ptrace(cont_type, pid, 0, sig) != 0){
+ tracer_panic("ptrace failed to continue "
+ "process - errno = %d\n",
+ errno);
+ }
+ }
+ }
+ return(0);
+}
+
+static int __init uml_debug_setup(char *line, int *add)
+{
+ char *next;
+
+ debug = 1;
+ *add = 0;
+ if(*line != '=') return(0);
+ line++;
+
+ while(line != NULL){
+ next = strchr(line, ',');
+ if(next) *next++ = '\0';
+
+ if(!strcmp(line, "go")) debug_stop = 0;
+ else if(!strcmp(line, "parent")) debug_parent = 1;
+ else printk("Unknown debug option : '%s'\n", line);
+
+ line = next;
+ }
+ return(0);
+}
+
+__uml_setup("debug", uml_debug_setup,
+"debug\n"
+" Starts up the kernel under the control of gdb. See the \n"
+" kernel debugging tutorial and the debugging session pages\n"
+" at http://user-mode-linux.sourceforge.net/ for more information.\n\n"
+);
+
+static int __init uml_debugtrace_setup(char *line, int *add)
+{
+ debug_trace = 1;
+ return 0;
+}
+__uml_setup("debugtrace", uml_debugtrace_setup,
+"debugtrace\n"
+" Causes the tracing thread to pause until it is attached by a\n"
+" debugger and continued. This is mostly for debugging crashes\n"
+" early during boot, and should be pretty much obsoleted by\n"
+" the debug switch.\n\n"
+);
+
+static int __init uml_honeypot_setup(char *line, int *add)
+{
+ jail_setup("", add);
+ honeypot = 1;
+ return 0;
+}
+__uml_setup("honeypot", uml_honeypot_setup,
+"honeypot\n"
+" This makes UML put process stacks in the same location as they are\n"
+" on the host, allowing expoits such as stack smashes to work against\n"
+" UML. This implies 'jail'.\n\n"
+);
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only. This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff --git a/arch/um/kernel/tt/trap_user.c b/arch/um/kernel/tt/trap_user.c
new file mode 100644
index 000000000000..37c8af88e39e
--- /dev/null
+++ b/arch/um/kernel/tt/trap_user.c
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#include <stdlib.h>
+#include <errno.h>
+#include <signal.h>
+#include <asm/sigcontext.h>
+#include "sysdep/ptrace.h"
+#include "signal_user.h"
+#include "user_util.h"
+#include "kern_util.h"
+#include "task.h"
+#include "tt.h"
+
+void sig_handler_common_tt(int sig, struct sigcontext *sc)
+{
+ struct uml_pt_regs save_regs, *r;
+ struct signal_info *info;
+ int save_errno = errno, is_user;
+
+ unprotect_kernel_mem();
+
+ r = (struct uml_pt_regs *) TASK_REGS(get_current());
+ save_regs = *r;
+ is_user = user_context(SC_SP(sc));
+ r->is_user = is_user;
+ r->mode.tt = sc;
+ if(sig != SIGUSR2) r->syscall = -1;
+
+ change_sig(SIGUSR1, 1);
+ info = &sig_info[sig];
+ if(!info->is_irq) unblock_signals();
+
+ (*info->handler)(sig, r);
+
+ if(is_user){
+ interrupt_end();
+ block_signals();
+ change_sig(SIGUSR1, 0);
+ set_user_mode(NULL);
+ }
+ *r = save_regs;
+ errno = save_errno;
+ if(is_user) protect_kernel_mem();
+}
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only. This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff --git a/arch/um/kernel/uaccess_user.c b/arch/um/kernel/tt/uaccess_user.c
index 639ea1c4be37..639ea1c4be37 100644
--- a/arch/um/kernel/uaccess_user.c
+++ b/arch/um/kernel/tt/uaccess_user.c
diff --git a/arch/um/kernel/tty_log.c b/arch/um/kernel/tty_log.c
index 7d53a6ea2ab0..61c4cc3af749 100644
--- a/arch/um/kernel/tty_log.c
+++ b/arch/um/kernel/tty_log.c
@@ -103,7 +103,7 @@ static int __init set_tty_log_fd(char *name, int *add)
char *end;
tty_log_fd = strtoul(name, &end, 0);
- if(*end != '\0'){
+ if((*end != '\0') || (end == name)){
printk("set_tty_log_fd - strtoul failed on '%s'\n", name);
tty_log_fd = -1;
}
diff --git a/arch/um/kernel/um_arch.c b/arch/um/kernel/um_arch.c
index b7d436981572..aacf0ca51a63 100644
--- a/arch/um/kernel/um_arch.c
+++ b/arch/um/kernel/um_arch.c
@@ -34,17 +34,21 @@
#include "initrd.h"
#include "init.h"
#include "os.h"
+#include "choose-mode.h"
+#include "mode_kern.h"
+#include "mode.h"
#define DEFAULT_COMMAND_LINE "root=6200"
struct cpuinfo_um boot_cpu_data = {
- .loops_per_jiffy = 0,
- .ipi_pipe = { -1, -1 }
+ .loops_per_jiffy = 0,
+ .ipi_pipe = { -1, -1 }
};
unsigned long thread_saved_pc(struct task_struct *task)
{
- return(os_process_pc(task->thread.extern_pid));
+ return(os_process_pc(CHOOSE_MODE_PROC(thread_pid_tt, thread_pid_skas,
+ task)));
}
static int show_cpuinfo(struct seq_file *m, void *v)
@@ -93,47 +97,11 @@ pte_t * __bad_pagetable(void)
return(NULL);
}
-extern void start_kernel(void);
-
-extern int debug;
-extern int debug_stop;
-
-static int start_kernel_proc(void *unused)
-{
- int pid;
-
- block_signals();
- pid = os_getpid();
-
- cpu_tasks[0].pid = pid;
- cpu_tasks[0].task = current;
-#ifdef CONFIG_SMP
- cpu_online_map = 1;
-#endif
- if(debug) os_stop_process(pid);
- start_kernel();
- return(0);
-}
-
-#ifdef CONFIG_HOST_2G_2G
-#define TOP 0x80000000
-#else
-#define TOP 0xc0000000
-#endif
-
-#define SIZE ((CONFIG_NEST_LEVEL + CONFIG_KERNEL_HALF_GIGS) * 0x20000000)
-#define START (TOP - SIZE)
-
-/* Set in main */
+/* Set in linux_main */
unsigned long host_task_size;
unsigned long task_size;
-void set_task_sizes(int arg)
-{
- /* Round up to the nearest 4M */
- host_task_size = ROUND_4M((unsigned long) &arg);
- task_size = START;
-}
+unsigned long uml_start;
/* Set in early boot */
unsigned long uml_physmem;
@@ -156,7 +124,8 @@ long physmem_size = 32 * 1024 * 1024;
void set_cmdline(char *cmd)
{
char *umid, *ptr;
- if(honeypot) return;
+
+ if(CHOOSE_MODE(honeypot, 0)) return;
umid = get_umid(1);
if(umid != NULL){
@@ -215,11 +184,48 @@ static int __init uml_ncpus_setup(char *line, int *add)
__uml_setup("ncpus=", uml_ncpus_setup,
"ncpus=<# of desired CPUs>\n"
-" This tells an SMP kernel how many virtual processors to start.\n"
-" Currently, this has no effect because SMP isn't enabled.\n\n"
+" This tells an SMP kernel how many virtual processors to start.\n\n"
);
#endif
+int force_tt = 0;
+
+#if defined(CONFIG_MODE_TT) && defined(CONFIG_MODE_SKAS)
+#define DEFAULT_TT 0
+
+static int __init mode_tt_setup(char *line, int *add)
+{
+ force_tt = 1;
+ return(0);
+}
+
+__uml_setup("mode=tt", mode_tt_setup,
+"mode=tt\n"
+" When both CONFIG_MODE_TT and CONFIG_MODE_SKAS are enabled, this option\n"
+" forces UML to run in tt (tracing thread) mode. It is not the default\n"
+" because it's slower and less secure than skas mode.\n\n"
+);
+
+#else
+#ifdef CONFIG_MODE_SKAS
+
+#define DEFAULT_TT 0
+
+#else
+#ifdef CONFIG_MODE_TT
+
+#define DEFAULT_TT 1
+
+#else
+
+#error Either CONFIG_MODE_TT or CONFIG_MODE_SKAS must be enabled
+
+#endif
+#endif
+#endif
+
+int mode_tt = DEFAULT_TT;
+
static int __init Usage(char *line, int *add)
{
const char **p;
@@ -267,8 +273,6 @@ static void __init uml_postsetup(void)
return;
}
-extern int debug_trace;
-
/* Set during early boot */
unsigned long brk_start;
static struct vm_reserved kernel_vm_reserved;
@@ -280,7 +284,6 @@ int linux_main(int argc, char **argv)
unsigned long avail;
unsigned long virtmem_size, max_physmem;
unsigned int i, add, err;
- void *sp;
for (i = 1; i < argc; i++){
if((i == 1) && (argv[i][0] == ' ')) continue;
@@ -290,13 +293,14 @@ int linux_main(int argc, char **argv)
}
if(have_root == 0) add_arg(saved_command_line, DEFAULT_COMMAND_LINE);
- if(!jail || debug)
- remap_data(ROUND_DOWN(&_stext), ROUND_UP(&_etext), 1);
- remap_data(ROUND_DOWN(&_sdata), ROUND_UP(&_edata), 1);
+ mode_tt = force_tt ? 1 : !can_do_skas();
+ uml_start = CHOOSE_MODE_PROC(set_task_sizes_tt, set_task_sizes_skas, 0,
+ &host_task_size, &task_size);
+
brk_start = (unsigned long) sbrk(0);
- remap_data(ROUND_DOWN(&__bss_start), ROUND_UP(brk_start), 1);
+ CHOOSE_MODE_PROC(before_mem_tt, before_mem_skas, brk_start);
- uml_physmem = START;
+ uml_physmem = uml_start;
/* Reserve up to 4M after the current brk */
uml_reserved = ROUND_4M(brk_start) + (1 << 22);
@@ -331,8 +335,10 @@ int linux_main(int argc, char **argv)
virtmem_size);
err = reserve_vm(high_physmem, end_vm, &kernel_vm_reserved);
- if(err)
- tracer_panic("Failed to reserve VM area for kernel VM\n");
+ if(err){
+ printf("Failed to reserve VM area for kernel VM\n");
+ exit(1);
+ }
uml_postsetup();
@@ -340,9 +346,8 @@ int linux_main(int argc, char **argv)
2 * PAGE_SIZE;
task_protections((unsigned long) &init_thread_info);
- sp = (void *) init_task.thread.kernel_stack + 2 * PAGE_SIZE -
- sizeof(unsigned long);
- return(signals(start_kernel_proc, sp));
+
+ return(CHOOSE_MODE(start_uml_tt(), start_uml_skas()));
}
static int panic_exit(struct notifier_block *self, unsigned long unused1,
diff --git a/arch/um/kernel/umid.c b/arch/um/kernel/umid.c
index 2ba2049510b3..e08acf5d5354 100644
--- a/arch/um/kernel/umid.c
+++ b/arch/um/kernel/umid.c
@@ -17,6 +17,8 @@
#include "umid.h"
#include "init.h"
#include "os.h"
+#include "user_util.h"
+#include "choose-mode.h"
#define UMID_LEN 64
#define UML_DIR "~/.uml/"
@@ -91,7 +93,7 @@ static int __init create_pid_file(void)
return 0;
}
- sprintf(pid, "%d\n", (tracing_pid == -1) ? os_getpid() : tracing_pid);
+ sprintf(pid, "%d\n", os_getpid());
if(write(fd, pid, strlen(pid)) != strlen(pid))
printk("Write of pid file failed - errno = %d\n", errno);
close(fd);
@@ -179,7 +181,7 @@ int not_dead_yet(char *dir)
dead = 1;
}
if(((kill(p, 0) < 0) && (errno == ESRCH)) ||
- (p == tracing_pid))
+ (p == CHOOSE_MODE(tracing_pid, os_getpid())))
dead = 1;
}
if(!dead) return(1);
diff --git a/arch/um/main.c b/arch/um/main.c
index 204c7a189fdd..3addff95120c 100644
--- a/arch/um/main.c
+++ b/arch/um/main.c
@@ -17,6 +17,8 @@
#include "mem_user.h"
#include "user.h"
#include "init.h"
+#include "mode.h"
+#include "choose-mode.h"
/* Set in set_stklim, which is called from main and __wrap_malloc.
* __wrap_malloc only calls it if main hasn't started.
@@ -97,9 +99,6 @@ int main(int argc, char **argv, char **envp)
new_argv[i] = argv[i - 1];
new_argv[argc + 1] = NULL;
-#ifdef PROFILING
- disable_profile_timer();
-#endif
execvp(new_argv[0], new_argv);
perror("execing with extended args");
exit(1);
@@ -108,7 +107,6 @@ int main(int argc, char **argv, char **envp)
linux_prog = argv[0];
set_stklim();
- set_task_sizes(0);
if((new_argv = malloc((argc + 1) * sizeof(char *))) == NULL){
perror("Mallocing argv");
@@ -136,60 +134,14 @@ int main(int argc, char **argv, char **envp)
return(uml_exitcode);
}
-/* Changed in __wrap___monstartup and __wrap_malloc very early */
-static int allocating_monbuf = 0;
-
-#ifdef PROFILING
-extern void __real___monstartup (unsigned long, unsigned long);
-
-void __wrap___monstartup (unsigned long lowpc, unsigned long highpc)
-{
- allocating_monbuf = 1;
- __real___monstartup(lowpc, highpc);
- allocating_monbuf = 0;
- get_profile_timer();
-}
-#endif
+#define CAN_KMALLOC() \
+ (kmalloc_ok && CHOOSE_MODE((getpid() != tracing_pid), 1))
extern void *__real_malloc(int);
-extern unsigned long host_task_size;
-
-/* Set in __wrap_malloc early */
-static void *gmon_buf = NULL;
void *__wrap_malloc(int size)
{
- if(allocating_monbuf){
- unsigned long start, end;
- int fd;
-
- /* Turn this off now in case create_mem_file tries allocating
- * memory
- */
- allocating_monbuf = 0;
- fd = create_mem_file(size);
-
- /* Calculate this here because linux_main hasn't run yet
- * and host_task_size figures in STACK_TOP, which figures
- * in kmem_end.
- */
- set_task_sizes(0);
-
- /* Same with stacksizelim */
- set_stklim();
-
- end = get_kmem_end();
- start = (end - size) & PAGE_MASK;
- gmon_buf = mmap((void *) start, size, PROT_READ | PROT_WRITE,
- MAP_SHARED | MAP_FIXED, fd, 0);
- if(gmon_buf != (void *) start){
- perror("Creating gprof buffer");
- exit(1);
- }
- set_kmem_end(start);
- return(gmon_buf);
- }
- if(kmalloc_ok) return(um_kmalloc(size));
+ if(CAN_KMALLOC()) return(um_kmalloc(size));
else return(__real_malloc(size));
}
@@ -206,11 +158,7 @@ extern void __real_free(void *);
void __wrap_free(void *ptr)
{
- /* Could maybe unmap the gmon buffer, but we're just about to
- * exit anyway
- */
- if(ptr == gmon_buf) return;
- if(kmalloc_ok) kfree(ptr);
+ if(CAN_KMALLOC()) kfree(ptr);
else __real_free(ptr);
}
diff --git a/arch/um/os-Linux/Makefile b/arch/um/os-Linux/Makefile
index d36e16af7732..37eea4a327a2 100644
--- a/arch/um/os-Linux/Makefile
+++ b/arch/um/os-Linux/Makefile
@@ -3,12 +3,12 @@
# Licensed under the GPL
#
-obj-y = file.o process.o tty.o
+obj-y = file.o process.o tty.o drivers/
-USER_OBJS := $(foreach file,$(obj-y),arch/um/os-Linux/$(file))
+USER_OBJS := $(foreach file,file.o process.o tty.o,$(obj)/$(file))
$(USER_OBJS) : %.o: %.c
- $(CC) $(CFLAGS_$@) $(USER_CFLAGS) -c -o $@ $<
+ $(CC) $(CFLAGS_$(notdir $@)) $(USER_CFLAGS) -c -o $@ $<
clean :
diff --git a/arch/um/os-Linux/drivers/Makefile b/arch/um/os-Linux/drivers/Makefile
index f3c044922133..52cae521eb65 100644
--- a/arch/um/os-Linux/drivers/Makefile
+++ b/arch/um/os-Linux/drivers/Makefile
@@ -13,6 +13,7 @@ obj-$(CONFIG_UML_NET_TUNTAP) += tuntap.o
USER_SINGLE_OBJS = $(foreach f,$(patsubst %.o,%,$(obj-y)),$($(f)-objs))
USER_OBJS = $(filter %_user.o,$(obj-y) $(USER_SINGLE_OBJS))
+USER_OBJS := $(foreach file,$(USER_OBJS),$(obj)/$(file))
$(USER_OBJS) : %.o: %.c
- $(CC) $(CFLAGS_$@) $(USER_CFLAGS) -c -o $@ $<
+ $(CC) $(CFLAGS_$(notdir $@)) $(USER_CFLAGS) -c -o $@ $<
diff --git a/arch/um/os-Linux/file.c b/arch/um/os-Linux/file.c
index 53e83d6607e1..318233b06e21 100644
--- a/arch/um/os-Linux/file.c
+++ b/arch/um/os-Linux/file.c
@@ -171,7 +171,8 @@ int os_pipe(int *fds, int stream, int close_on_exec)
int err, type = stream ? SOCK_STREAM : SOCK_DGRAM;
err = socketpair(AF_UNIX, type, 0, fds);
- if(err) return(-errno);
+ if(err)
+ return(-errno);
if(!close_on_exec)
return(0);
@@ -185,6 +186,7 @@ int os_pipe(int *fds, int stream, int close_on_exec)
int os_set_fd_async(int fd, int owner)
{
+ /* XXX This should do F_GETFL first */
if(fcntl(fd, F_SETFL, O_ASYNC | O_NONBLOCK) < 0){
printk("os_set_fd_async : failed to set O_ASYNC and "
"O_NONBLOCK on fd # %d, errno = %d\n", fd, errno);
diff --git a/arch/um/os-Linux/process.c b/arch/um/os-Linux/process.c
index ca5df7d03495..b7a565a2d721 100644
--- a/arch/um/os-Linux/process.c
+++ b/arch/um/os-Linux/process.c
@@ -7,6 +7,8 @@
#include <stdio.h>
#include <errno.h>
#include <signal.h>
+#include <sys/mman.h>
+#include <sys/wait.h>
#include "os.h"
#include "user.h"
@@ -75,9 +77,12 @@ void os_stop_process(int pid)
kill(pid, SIGSTOP);
}
-void os_kill_process(int pid)
+void os_kill_process(int pid, int reap_child)
{
kill(pid, SIGKILL);
+ if(reap_child)
+ waitpid(pid, NULL, 0);
+
}
void os_usr1_process(int pid)
@@ -90,6 +95,41 @@ int os_getpid(void)
return(getpid());
}
+int os_map_memory(void *virt, int fd, unsigned long off, unsigned long len,
+ int r, int w, int x)
+{
+ void *loc;
+ int prot;
+
+ prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) |
+ (x ? PROT_EXEC : 0);
+
+ loc = mmap((void *) virt, len, prot, MAP_SHARED | MAP_FIXED,
+ fd, off);
+ if(loc < 0)
+ return(-errno);
+ return(0);
+}
+
+int os_protect_memory(void *addr, unsigned long len, int r, int w, int x)
+{
+ int prot = ((r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) |
+ (x ? PROT_EXEC : 0));
+
+ if(mprotect(addr, len, prot) < 0)
+ return(-errno);
+ return(0);
+}
+
+int os_unmap_memory(void *addr, int len)
+{
+ int err;
+
+ err = munmap(addr, len);
+ if(err < 0) return(-errno);
+ return(0);
+}
+
/*
* Overrides for Emacs so that we follow Linus's tabbing style.
* Emacs will notice this stuff at the end of the file and automatically
diff --git a/arch/um/os-Linux/tty.c b/arch/um/os-Linux/tty.c
index 64a5c21bda29..2866ddbc9203 100644
--- a/arch/um/os-Linux/tty.c
+++ b/arch/um/os-Linux/tty.c
@@ -35,7 +35,7 @@ int get_pty(void)
}
info.fd = fd;
- tracing_cb(grantpt_cb, &info);
+ initial_thread_cb(grantpt_cb, &info);
if(info.res < 0){
printk("get_pty : Couldn't grant pty - errno = %d\n",
diff --git a/arch/um/ptproxy/Makefile b/arch/um/ptproxy/Makefile
deleted file mode 100644
index fdb1ba781043..000000000000
--- a/arch/um/ptproxy/Makefile
+++ /dev/null
@@ -1,10 +0,0 @@
-obj-y = proxy.o ptrace.o sysdep.o wait.o
-
-USER_OBJS := $(foreach file,$(obj-y),arch/um/ptproxy/$(file))
-
-$(USER_OBJS) : %.o: %.c
- $(CC) $(CFLAGS_$@) $(USER_CFLAGS) -c -o $@ $<
-
-clean:
- rm -f *.o core child ptproxy
-
diff --git a/arch/um/sys-i386/Makefile b/arch/um/sys-i386/Makefile
index 19258ea6e695..bc0cbe6ba325 100644
--- a/arch/um/sys-i386/Makefile
+++ b/arch/um/sys-i386/Makefile
@@ -1,4 +1,4 @@
-obj-y = bugs.o checksum.o extable.o fault.o ksyms.o ldt.o \
+obj-y = bugs.o checksum.o extable.o fault.o ksyms.o ldt.o module.o \
ptrace.o ptrace_user.o semaphore.o sigcontext.o syscalls.o sysrq.o
obj-$(CONFIG_HIGHMEM) += highmem.o
@@ -6,28 +6,26 @@ obj-$(CONFIG_HIGHMEM) += highmem.o
export-objs = ksyms.o
USER_OBJS := bugs.o ptrace_user.o sigcontext.o fault.o
-USER_OBJS := $(foreach file,$(USER_OBJS),arch/um/sys-i386/$(file))
+USER_OBJS := $(foreach file,$(USER_OBJS),$(obj)/$(file))
-SYMLINKS = semaphore.c checksum.S extable.c highmem.c
+SYMLINKS = semaphore.c extable.c highmem.c module.c
-$(USER_OBJS) : %.o: %.c
- $(CC) $(CFLAGS_$@) $(USER_CFLAGS) -c -o $@ $<
+semaphore.c-dir = kernel
+extable.c-dir = mm
+highmem.c-dir = mm
+module.c-dir = kernel
-arch/um/sys-i386/checksum.S:
- -rm -f $@
- -ln -s $(TOPDIR)/arch/i386/lib/$(notdir $@) $@
+define make_link
+ -rm -f $1
+ ln -sf $(TOPDIR)/arch/i386/$($(notdir $1)-dir)/$(notdir $1) $1
+endef
-arch/um/sys-i386/semaphore.c:
- -rm -f $@
- -ln -s $(TOPDIR)/arch/i386/kernel/$(notdir $@) $@
+$(USER_OBJS) : %.o: %.c
+ $(CC) $(CFLAGS_$(notdir $@)) $(USER_CFLAGS) -c -o $@ $<
-arch/um/sys-i386/extable.c:
- -rm -f $@
- -ln -s $(TOPDIR)/arch/i386/mm/$(notdir $@) $@
+$(foreach f,$(SYMLINKS),$(src)/$f):
+ $(call make_link,$@)
-arch/um/sys-i386/highmem.c:
- -rm -f $@
- -ln -s $(TOPDIR)/arch/i386/mm/$(notdir $@) $@
clean:
$(MAKE) -C util clean
diff --git a/arch/um/sys-i386/checksum.S b/arch/um/sys-i386/checksum.S
new file mode 100644
index 000000000000..a11171fb6223
--- /dev/null
+++ b/arch/um/sys-i386/checksum.S
@@ -0,0 +1,460 @@
+/*
+ * INET An implementation of the TCP/IP protocol suite for the LINUX
+ * operating system. INET is implemented using the BSD Socket
+ * interface as the means of communication with the user level.
+ *
+ * IP/TCP/UDP checksumming routines
+ *
+ * Authors: Jorge Cwik, <jorge@laser.satlink.net>
+ * Arnt Gulbrandsen, <agulbra@nvg.unit.no>
+ * Tom May, <ftom@netcom.com>
+ * Pentium Pro/II routines:
+ * Alexander Kjeldaas <astor@guardian.no>
+ * Finn Arne Gangstad <finnag@guardian.no>
+ * Lots of code moved from tcp.c and ip.c; see those files
+ * for more names.
+ *
+ * Changes: Ingo Molnar, converted csum_partial_copy() to 2.1 exception
+ * handling.
+ * Andi Kleen, add zeroing on error
+ * converted to pure assembler
+ *
+ * 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 <linux/config.h>
+#include <asm/errno.h>
+
+/*
+ * computes a partial checksum, e.g. for TCP/UDP fragments
+ */
+
+/*
+unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum)
+ */
+
+.text
+.align 4
+.globl arch_csum_partial
+
+#ifndef CONFIG_X86_USE_PPRO_CHECKSUM
+
+ /*
+ * Experiments with Ethernet and SLIP connections show that buff
+ * is aligned on either a 2-byte or 4-byte boundary. We get at
+ * least a twofold speedup on 486 and Pentium if it is 4-byte aligned.
+ * Fortunately, it is easy to convert 2-byte alignment to 4-byte
+ * alignment for the unrolled loop.
+ */
+arch_csum_partial:
+ pushl %esi
+ pushl %ebx
+ movl 20(%esp),%eax # Function arg: unsigned int sum
+ movl 16(%esp),%ecx # Function arg: int len
+ movl 12(%esp),%esi # Function arg: unsigned char *buff
+ testl $2, %esi # Check alignment.
+ jz 2f # Jump if alignment is ok.
+ subl $2, %ecx # Alignment uses up two bytes.
+ jae 1f # Jump if we had at least two bytes.
+ addl $2, %ecx # ecx was < 2. Deal with it.
+ jmp 4f
+1: movw (%esi), %bx
+ addl $2, %esi
+ addw %bx, %ax
+ adcl $0, %eax
+2:
+ movl %ecx, %edx
+ shrl $5, %ecx
+ jz 2f
+ testl %esi, %esi
+1: movl (%esi), %ebx
+ adcl %ebx, %eax
+ movl 4(%esi), %ebx
+ adcl %ebx, %eax
+ movl 8(%esi), %ebx
+ adcl %ebx, %eax
+ movl 12(%esi), %ebx
+ adcl %ebx, %eax
+ movl 16(%esi), %ebx
+ adcl %ebx, %eax
+ movl 20(%esi), %ebx
+ adcl %ebx, %eax
+ movl 24(%esi), %ebx
+ adcl %ebx, %eax
+ movl 28(%esi), %ebx
+ adcl %ebx, %eax
+ lea 32(%esi), %esi
+ dec %ecx
+ jne 1b
+ adcl $0, %eax
+2: movl %edx, %ecx
+ andl $0x1c, %edx
+ je 4f
+ shrl $2, %edx # This clears CF
+3: adcl (%esi), %eax
+ lea 4(%esi), %esi
+ dec %edx
+ jne 3b
+ adcl $0, %eax
+4: andl $3, %ecx
+ jz 7f
+ cmpl $2, %ecx
+ jb 5f
+ movw (%esi),%cx
+ leal 2(%esi),%esi
+ je 6f
+ shll $16,%ecx
+5: movb (%esi),%cl
+6: addl %ecx,%eax
+ adcl $0, %eax
+7:
+ popl %ebx
+ popl %esi
+ ret
+
+#else
+
+/* Version for PentiumII/PPro */
+
+arch_csum_partial:
+ pushl %esi
+ pushl %ebx
+ movl 20(%esp),%eax # Function arg: unsigned int sum
+ movl 16(%esp),%ecx # Function arg: int len
+ movl 12(%esp),%esi # Function arg: const unsigned char *buf
+
+ testl $2, %esi
+ jnz 30f
+10:
+ movl %ecx, %edx
+ movl %ecx, %ebx
+ andl $0x7c, %ebx
+ shrl $7, %ecx
+ addl %ebx,%esi
+ shrl $2, %ebx
+ negl %ebx
+ lea 45f(%ebx,%ebx,2), %ebx
+ testl %esi, %esi
+ jmp *%ebx
+
+ # Handle 2-byte-aligned regions
+20: addw (%esi), %ax
+ lea 2(%esi), %esi
+ adcl $0, %eax
+ jmp 10b
+
+30: subl $2, %ecx
+ ja 20b
+ je 32f
+ movzbl (%esi),%ebx # csumming 1 byte, 2-aligned
+ addl %ebx, %eax
+ adcl $0, %eax
+ jmp 80f
+32:
+ addw (%esi), %ax # csumming 2 bytes, 2-aligned
+ adcl $0, %eax
+ jmp 80f
+
+40:
+ addl -128(%esi), %eax
+ adcl -124(%esi), %eax
+ adcl -120(%esi), %eax
+ adcl -116(%esi), %eax
+ adcl -112(%esi), %eax
+ adcl -108(%esi), %eax
+ adcl -104(%esi), %eax
+ adcl -100(%esi), %eax
+ adcl -96(%esi), %eax
+ adcl -92(%esi), %eax
+ adcl -88(%esi), %eax
+ adcl -84(%esi), %eax
+ adcl -80(%esi), %eax
+ adcl -76(%esi), %eax
+ adcl -72(%esi), %eax
+ adcl -68(%esi), %eax
+ adcl -64(%esi), %eax
+ adcl -60(%esi), %eax
+ adcl -56(%esi), %eax
+ adcl -52(%esi), %eax
+ adcl -48(%esi), %eax
+ adcl -44(%esi), %eax
+ adcl -40(%esi), %eax
+ adcl -36(%esi), %eax
+ adcl -32(%esi), %eax
+ adcl -28(%esi), %eax
+ adcl -24(%esi), %eax
+ adcl -20(%esi), %eax
+ adcl -16(%esi), %eax
+ adcl -12(%esi), %eax
+ adcl -8(%esi), %eax
+ adcl -4(%esi), %eax
+45:
+ lea 128(%esi), %esi
+ adcl $0, %eax
+ dec %ecx
+ jge 40b
+ movl %edx, %ecx
+50: andl $3, %ecx
+ jz 80f
+
+ # Handle the last 1-3 bytes without jumping
+ notl %ecx # 1->2, 2->1, 3->0, higher bits are masked
+ movl $0xffffff,%ebx # by the shll and shrl instructions
+ shll $3,%ecx
+ shrl %cl,%ebx
+ andl -128(%esi),%ebx # esi is 4-aligned so should be ok
+ addl %ebx,%eax
+ adcl $0,%eax
+80:
+ popl %ebx
+ popl %esi
+ ret
+
+#endif
+
+/*
+unsigned int csum_partial_copy_generic (const char *src, char *dst,
+ int len, int sum, int *src_err_ptr, int *dst_err_ptr)
+ */
+
+/*
+ * Copy from ds while checksumming, otherwise like csum_partial
+ *
+ * The macros SRC and DST specify the type of access for the instruction.
+ * thus we can call a custom exception handler for all access types.
+ *
+ * FIXME: could someone double-check whether I haven't mixed up some SRC and
+ * DST definitions? It's damn hard to trigger all cases. I hope I got
+ * them all but there's no guarantee.
+ */
+
+#define SRC(y...) \
+ 9999: y; \
+ .section __ex_table, "a"; \
+ .long 9999b, 6001f ; \
+ .previous
+
+#define DST(y...) \
+ 9999: y; \
+ .section __ex_table, "a"; \
+ .long 9999b, 6002f ; \
+ .previous
+
+.align 4
+.globl csum_partial_copy_generic_i386
+
+#ifndef CONFIG_X86_USE_PPRO_CHECKSUM
+
+#define ARGBASE 16
+#define FP 12
+
+csum_partial_copy_generic_i386:
+ subl $4,%esp
+ pushl %edi
+ pushl %esi
+ pushl %ebx
+ movl ARGBASE+16(%esp),%eax # sum
+ movl ARGBASE+12(%esp),%ecx # len
+ movl ARGBASE+4(%esp),%esi # src
+ movl ARGBASE+8(%esp),%edi # dst
+
+ testl $2, %edi # Check alignment.
+ jz 2f # Jump if alignment is ok.
+ subl $2, %ecx # Alignment uses up two bytes.
+ jae 1f # Jump if we had at least two bytes.
+ addl $2, %ecx # ecx was < 2. Deal with it.
+ jmp 4f
+SRC(1: movw (%esi), %bx )
+ addl $2, %esi
+DST( movw %bx, (%edi) )
+ addl $2, %edi
+ addw %bx, %ax
+ adcl $0, %eax
+2:
+ movl %ecx, FP(%esp)
+ shrl $5, %ecx
+ jz 2f
+ testl %esi, %esi
+SRC(1: movl (%esi), %ebx )
+SRC( movl 4(%esi), %edx )
+ adcl %ebx, %eax
+DST( movl %ebx, (%edi) )
+ adcl %edx, %eax
+DST( movl %edx, 4(%edi) )
+
+SRC( movl 8(%esi), %ebx )
+SRC( movl 12(%esi), %edx )
+ adcl %ebx, %eax
+DST( movl %ebx, 8(%edi) )
+ adcl %edx, %eax
+DST( movl %edx, 12(%edi) )
+
+SRC( movl 16(%esi), %ebx )
+SRC( movl 20(%esi), %edx )
+ adcl %ebx, %eax
+DST( movl %ebx, 16(%edi) )
+ adcl %edx, %eax
+DST( movl %edx, 20(%edi) )
+
+SRC( movl 24(%esi), %ebx )
+SRC( movl 28(%esi), %edx )
+ adcl %ebx, %eax
+DST( movl %ebx, 24(%edi) )
+ adcl %edx, %eax
+DST( movl %edx, 28(%edi) )
+
+ lea 32(%esi), %esi
+ lea 32(%edi), %edi
+ dec %ecx
+ jne 1b
+ adcl $0, %eax
+2: movl FP(%esp), %edx
+ movl %edx, %ecx
+ andl $0x1c, %edx
+ je 4f
+ shrl $2, %edx # This clears CF
+SRC(3: movl (%esi), %ebx )
+ adcl %ebx, %eax
+DST( movl %ebx, (%edi) )
+ lea 4(%esi), %esi
+ lea 4(%edi), %edi
+ dec %edx
+ jne 3b
+ adcl $0, %eax
+4: andl $3, %ecx
+ jz 7f
+ cmpl $2, %ecx
+ jb 5f
+SRC( movw (%esi), %cx )
+ leal 2(%esi), %esi
+DST( movw %cx, (%edi) )
+ leal 2(%edi), %edi
+ je 6f
+ shll $16,%ecx
+SRC(5: movb (%esi), %cl )
+DST( movb %cl, (%edi) )
+6: addl %ecx, %eax
+ adcl $0, %eax
+7:
+5000:
+
+# Exception handler:
+.section .fixup, "ax"
+
+6001:
+ movl ARGBASE+20(%esp), %ebx # src_err_ptr
+ movl $-EFAULT, (%ebx)
+
+ # zero the complete destination - computing the rest
+ # is too much work
+ movl ARGBASE+8(%esp), %edi # dst
+ movl ARGBASE+12(%esp), %ecx # len
+ xorl %eax,%eax
+ rep ; stosb
+
+ jmp 5000b
+
+6002:
+ movl ARGBASE+24(%esp), %ebx # dst_err_ptr
+ movl $-EFAULT,(%ebx)
+ jmp 5000b
+
+.previous
+
+ popl %ebx
+ popl %esi
+ popl %edi
+ popl %ecx # equivalent to addl $4,%esp
+ ret
+
+#else
+
+/* Version for PentiumII/PPro */
+
+#define ROUND1(x) \
+ SRC(movl x(%esi), %ebx ) ; \
+ addl %ebx, %eax ; \
+ DST(movl %ebx, x(%edi) ) ;
+
+#define ROUND(x) \
+ SRC(movl x(%esi), %ebx ) ; \
+ adcl %ebx, %eax ; \
+ DST(movl %ebx, x(%edi) ) ;
+
+#define ARGBASE 12
+
+csum_partial_copy_generic_i386:
+ pushl %ebx
+ pushl %edi
+ pushl %esi
+ movl ARGBASE+4(%esp),%esi #src
+ movl ARGBASE+8(%esp),%edi #dst
+ movl ARGBASE+12(%esp),%ecx #len
+ movl ARGBASE+16(%esp),%eax #sum
+# movl %ecx, %edx
+ movl %ecx, %ebx
+ movl %esi, %edx
+ shrl $6, %ecx
+ andl $0x3c, %ebx
+ negl %ebx
+ subl %ebx, %esi
+ subl %ebx, %edi
+ lea -1(%esi),%edx
+ andl $-32,%edx
+ lea 3f(%ebx,%ebx), %ebx
+ testl %esi, %esi
+ jmp *%ebx
+1: addl $64,%esi
+ addl $64,%edi
+ SRC(movb -32(%edx),%bl) ; SRC(movb (%edx),%bl)
+ ROUND1(-64) ROUND(-60) ROUND(-56) ROUND(-52)
+ ROUND (-48) ROUND(-44) ROUND(-40) ROUND(-36)
+ ROUND (-32) ROUND(-28) ROUND(-24) ROUND(-20)
+ ROUND (-16) ROUND(-12) ROUND(-8) ROUND(-4)
+3: adcl $0,%eax
+ addl $64, %edx
+ dec %ecx
+ jge 1b
+4: movl ARGBASE+12(%esp),%edx #len
+ andl $3, %edx
+ jz 7f
+ cmpl $2, %edx
+ jb 5f
+SRC( movw (%esi), %dx )
+ leal 2(%esi), %esi
+DST( movw %dx, (%edi) )
+ leal 2(%edi), %edi
+ je 6f
+ shll $16,%edx
+5:
+SRC( movb (%esi), %dl )
+DST( movb %dl, (%edi) )
+6: addl %edx, %eax
+ adcl $0, %eax
+7:
+.section .fixup, "ax"
+6001: movl ARGBASE+20(%esp), %ebx # src_err_ptr
+ movl $-EFAULT, (%ebx)
+ # zero the complete destination (computing the rest is too much work)
+ movl ARGBASE+8(%esp),%edi # dst
+ movl ARGBASE+12(%esp),%ecx # len
+ xorl %eax,%eax
+ rep; stosb
+ jmp 7b
+6002: movl ARGBASE+24(%esp), %ebx # dst_err_ptr
+ movl $-EFAULT, (%ebx)
+ jmp 7b
+.previous
+
+ popl %esi
+ popl %edi
+ popl %ebx
+ ret
+
+#undef ROUND
+#undef ROUND1
+
+#endif
diff --git a/arch/um/sys-i386/ksyms.c b/arch/um/sys-i386/ksyms.c
index bf57ac7e04e1..74f70a120458 100644
--- a/arch/um/sys-i386/ksyms.c
+++ b/arch/um/sys-i386/ksyms.c
@@ -13,4 +13,5 @@ EXPORT_SYMBOL(__down_failed_trylock);
EXPORT_SYMBOL(__up_wakeup);
/* Networking helper routines. */
-EXPORT_SYMBOL(csum_partial_copy_generic);
+EXPORT_SYMBOL(csum_partial_copy_from);
+EXPORT_SYMBOL(csum_partial_copy_to);
diff --git a/arch/um/sys-i386/ldt.c b/arch/um/sys-i386/ldt.c
index 7af4ef3d5dfd..33e302160d7c 100644
--- a/arch/um/sys-i386/ldt.c
+++ b/arch/um/sys-i386/ldt.c
@@ -3,15 +3,82 @@
* Licensed under the GPL
*/
+#include "linux/config.h"
+#include "linux/slab.h"
#include "asm/uaccess.h"
+#include "asm/ptrace.h"
+#include "choose-mode.h"
+#include "kern.h"
+#ifdef CONFIG_MODE_TT
extern int modify_ldt(int func, void *ptr, unsigned long bytecount);
-int sys_modify_ldt(int func, void *ptr, unsigned long bytecount)
+int sys_modify_ldt_tt(int func, void *ptr, unsigned long bytecount)
{
if(verify_area(VERIFY_READ, ptr, bytecount)) return(-EFAULT);
return(modify_ldt(func, ptr, bytecount));
}
+#endif
+
+#ifdef CONFIG_MODE_SKAS
+extern int userspace_pid;
+
+int sys_modify_ldt_skas(int func, void *ptr, unsigned long bytecount)
+{
+ struct ptrace_ldt ldt;
+ void *buf;
+ int res, n;
+
+ buf = kmalloc(bytecount, GFP_KERNEL);
+ if(buf == NULL)
+ return(-ENOMEM);
+
+ res = 0;
+
+ switch(func){
+ case 1:
+ case 0x11:
+ res = copy_from_user(buf, ptr, bytecount);
+ break;
+ }
+
+ if(res != 0){
+ res = -EFAULT;
+ goto out;
+ }
+
+ ldt = ((struct ptrace_ldt) { .func = func,
+ .ptr = buf,
+ .bytecount = bytecount });
+ res = ptrace(PTRACE_LDT, userspace_pid, 0, (unsigned long) &ldt);
+ if(res < 0)
+ goto out;
+
+ switch(func){
+ case 0:
+ case 2:
+ n = res;
+ res = copy_to_user(ptr, buf, n);
+ if(res != 0)
+ res = -EFAULT;
+ else
+ res = n;
+ break;
+ }
+
+ out:
+ kfree(buf);
+ return(res);
+}
+#endif
+
+int sys_modify_ldt(int func, void *ptr, unsigned long bytecount)
+{
+ return(CHOOSE_MODE_PROC(sys_modify_ldt_tt, sys_modify_ldt_skas, func,
+ ptr, bytecount));
+}
+
+
/*
* Overrides for Emacs so that we follow Linus's tabbing style.
diff --git a/arch/um/sys-i386/ptrace.c b/arch/um/sys-i386/ptrace.c
index cb47c4e86b1e..817ef7479d3f 100644
--- a/arch/um/sys-i386/ptrace.c
+++ b/arch/um/sys-i386/ptrace.c
@@ -169,11 +169,12 @@ static inline unsigned long twd_fxsr_to_i387( struct i387_fxsave_struct *fxsave
}
/*
-b * FXSR floating point environment conversions.
+ * FXSR floating point environment conversions.
*/
-static inline int convert_fxsr_to_user(struct _fpstate *buf,
- struct pt_regs *regs)
+#ifdef CONFIG_MODE_TT
+static inline int convert_fxsr_to_user_tt(struct _fpstate *buf,
+ struct pt_regs *regs)
{
struct i387_fxsave_struct *fxsave = SC_FXSR_ENV(PT_REGS_SC(regs));
unsigned long env[7];
@@ -200,9 +201,17 @@ static inline int convert_fxsr_to_user(struct _fpstate *buf,
}
return 0;
}
+#endif
-static inline int convert_fxsr_from_user(struct pt_regs *regs,
- struct _fpstate *buf)
+static inline int convert_fxsr_to_user(struct _fpstate *buf,
+ struct pt_regs *regs)
+{
+ return(CHOOSE_MODE(convert_fxsr_to_user_tt(buf, regs), 0));
+}
+
+#ifdef CONFIG_MODE_TT
+static inline int convert_fxsr_from_user_tt(struct pt_regs *regs,
+ struct _fpstate *buf)
{
struct i387_fxsave_struct *fxsave = SC_FXSR_ENV(PT_REGS_SC(regs));
unsigned long env[7];
@@ -230,6 +239,13 @@ static inline int convert_fxsr_from_user(struct pt_regs *regs,
}
return 0;
}
+#endif
+
+static inline int convert_fxsr_from_user(struct pt_regs *regs,
+ struct _fpstate *buf)
+{
+ return(CHOOSE_MODE(convert_fxsr_from_user_tt(regs, buf), 0));
+}
int get_fpregs(unsigned long buf, struct task_struct *child)
{
@@ -251,7 +267,8 @@ int set_fpregs(unsigned long buf, struct task_struct *child)
else return(0);
}
-int get_fpxregs(unsigned long buf, struct task_struct *tsk)
+#ifdef CONFIG_MODE_TT
+int get_fpxregs_tt(unsigned long buf, struct task_struct *tsk)
{
struct pt_regs *regs = &tsk->thread.regs;
struct i387_fxsave_struct *fxsave = SC_FXSR_ENV(PT_REGS_SC(regs));
@@ -262,8 +279,15 @@ int get_fpxregs(unsigned long buf, struct task_struct *tsk)
if(err) return -EFAULT;
else return 0;
}
+#endif
-int set_fpxregs(unsigned long buf, struct task_struct *tsk)
+int get_fpxregs(unsigned long buf, struct task_struct *tsk)
+{
+ return(CHOOSE_MODE(get_fpxregs_tt(buf, tsk), 0));
+}
+
+#ifdef CONFIG_MODE_TT
+int set_fpxregs_tt(unsigned long buf, struct task_struct *tsk)
{
struct pt_regs *regs = &tsk->thread.regs;
struct i387_fxsave_struct *fxsave = SC_FXSR_ENV(PT_REGS_SC(regs));
@@ -274,6 +298,12 @@ int set_fpxregs(unsigned long buf, struct task_struct *tsk)
if(err) return -EFAULT;
else return 0;
}
+#endif
+
+int set_fpxregs(unsigned long buf, struct task_struct *tsk)
+{
+ return(CHOOSE_MODE(set_fpxregs_tt(buf, tsk), 0));
+}
#ifdef notdef
int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu)
@@ -291,8 +321,10 @@ int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu)
return(1);
}
#endif
-static inline void copy_fpu_fxsave(struct pt_regs *regs,
- struct user_i387_struct *buf)
+
+#ifdef CONFIG_MODE_TT
+static inline void copy_fpu_fxsave_tt(struct pt_regs *regs,
+ struct user_i387_struct *buf)
{
struct i387_fxsave_struct *fpu = SC_FXSR_ENV(PT_REGS_SC(regs));
unsigned short *to;
@@ -307,6 +339,13 @@ static inline void copy_fpu_fxsave(struct pt_regs *regs,
memcpy( to, from, 5 * sizeof(unsigned short) );
}
}
+#endif
+
+static inline void copy_fpu_fxsave(struct pt_regs *regs,
+ struct user_i387_struct *buf)
+{
+ (void) CHOOSE_MODE(copy_fpu_fxsave_tt(regs, buf), 0);
+}
int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu )
{
diff --git a/arch/um/sys-i386/ptrace_user.c b/arch/um/sys-i386/ptrace_user.c
index 659db8a6e2d8..70da62313616 100644
--- a/arch/um/sys-i386/ptrace_user.c
+++ b/arch/um/sys-i386/ptrace_user.c
@@ -102,7 +102,7 @@ void update_debugregs(int seq)
if(seq == debugregs_seq) return;
me = os_getpid();
- tracing_cb(update_debugregs_cb, &me);
+ initial_thread_cb(update_debugregs_cb, &me);
}
/*
diff --git a/arch/um/sys-i386/sigcontext.c b/arch/um/sys-i386/sigcontext.c
index e61a94651371..6d33bedc07d7 100644
--- a/arch/um/sys-i386/sigcontext.c
+++ b/arch/um/sys-i386/sigcontext.c
@@ -18,45 +18,6 @@ int sc_size(void *data)
return(sizeof(struct sigcontext) + arch->fpstate_size);
}
-int copy_sc_to_user(void *to_ptr, void *from_ptr, void *data)
-{
- struct arch_frame_data *arch = data;
- struct sigcontext *to = to_ptr, *from = from_ptr;
- struct _fpstate *to_fp, *from_fp;
- int err;
-
- to_fp = (struct _fpstate *)((unsigned long) to + sizeof(*to));
- from_fp = from->fpstate;
- err = copy_to_user_proc(to, from, sizeof(*to));
- if(from_fp != NULL){
- err |= copy_to_user_proc(&to->fpstate, &to_fp,
- sizeof(to->fpstate));
- err |= copy_to_user_proc(to_fp, from_fp, arch->fpstate_size);
- }
- return(err);
-}
-
-int copy_sc_from_user(void *to_ptr, void *from_ptr, void *data)
-{
- struct arch_frame_data *arch = data;
- struct sigcontext *to = to_ptr, *from = from_ptr;
- struct _fpstate *to_fp, *from_fp;
- unsigned long sigs;
- int err;
-
- to_fp = to->fpstate;
- from_fp = from->fpstate;
- sigs = to->oldmask;
- err = copy_from_user_proc(to, from, sizeof(*to));
- to->oldmask = sigs;
- if(to_fp != NULL){
- err |= copy_from_user_proc(&to->fpstate, &to_fp,
- sizeof(to->fpstate));
- err |= copy_from_user_proc(to_fp, from_fp, arch->fpstate_size);
- }
- return(err);
-}
-
void sc_to_sc(void *to_ptr, void *from_ptr)
{
struct sigcontext *to = to_ptr, *from = from_ptr;
diff --git a/arch/um/sys-i386/util/mk_thread_kern.c b/arch/um/sys-i386/util/mk_thread_kern.c
index 6d7b853a6157..ad3671423d41 100644
--- a/arch/um/sys-i386/util/mk_thread_kern.c
+++ b/arch/um/sys-i386/util/mk_thread_kern.c
@@ -1,7 +1,19 @@
#include "linux/stddef.h"
#include "linux/sched.h"
-int debugreg(void)
+extern void print_head(void);
+extern void print_constant_ptr(char *name, int value);
+extern void print_constant(char *name, char *type, int value);
+extern void print_tail(void);
+
+#define THREAD_OFFSET(field) offsetof(struct task_struct, thread.field)
+
+int main(int argc, char **argv)
{
- return(offsetof(struct task_struct, thread.arch.debugregs));
+ print_head();
+ print_constant_ptr("TASK_DEBUGREGS", THREAD_OFFSET(arch.debugregs));
+ print_constant("TASK_EXTERN_PID", "int", THREAD_OFFSET(mode.tt.extern_pid));
+ print_tail();
+ return(0);
}
+
diff --git a/arch/um/sys-i386/util/mk_thread_user.c b/arch/um/sys-i386/util/mk_thread_user.c
index 997a02e9b35a..2620cd6aa1f1 100644
--- a/arch/um/sys-i386/util/mk_thread_user.c
+++ b/arch/um/sys-i386/util/mk_thread_user.c
@@ -1,12 +1,30 @@
#include <stdio.h>
-#include <linux/stddef.h>
-#include <asm/user.h>
-extern int debugreg(void);
+void print_head(void)
+{
+ printf("/*\n");
+ printf(" * Generated by mk_thread\n");
+ printf(" */\n");
+ printf("\n");
+ printf("#ifndef __UM_THREAD_H\n");
+ printf("#define __UM_THREAD_H\n");
+ printf("\n");
+}
+
+void print_constant_ptr(char *name, int value)
+{
+ printf("#define %s(task) ((unsigned long *) "
+ "&(((char *) (task))[%d]))\n", name, value);
+}
+
+void print_constant(char *name, char *type, int value)
+{
+ printf("#define %s(task) *((%s *) &(((char *) (task))[%d]))\n", name, type,
+ value);
+}
-int main(int argc, char **argv)
+void print_tail(void)
{
- printf("#define TASK_DEBUGREGS(task) ((unsigned long *) "
- "&(((char *) (task))[%d]))\n", debugreg());
- return(0);
+ printf("\n");
+ printf("#endif\n");
}
diff --git a/arch/um/uml.lds.S b/arch/um/uml.lds.S
index c15bc24842c3..736df4695129 100644
--- a/arch/um/uml.lds.S
+++ b/arch/um/uml.lds.S
@@ -38,6 +38,7 @@ SECTIONS
__ex_table : { *(__ex_table) }
__stop___ex_table = .;
+ . = ALIGN(64);
__start___ksymtab = .; /* Kernel symbol table */
__ksymtab : { *(__ksymtab) }
__stop___ksymtab = .;
@@ -58,18 +59,27 @@ SECTIONS
__uml_setup_start = .;
.uml.setup.init : { *(.uml.setup.init) }
__uml_setup_end = .;
+
__uml_help_start = .;
.uml.help.init : { *(.uml.help.init) }
__uml_help_end = .;
+
__uml_postsetup_start = .;
.uml.postsetup.init : { *(.uml.postsetup.init) }
__uml_postsetup_end = .;
+
__setup_start = .;
.init.setup : { *(.init.setup) }
__setup_end = .;
+
+ __start___param = .;
+ __param : { *(__param) }
+ __stop___param = .;
+
__per_cpu_start = . ;
.data.percpu : { *(.data.percpu) }
- __per_cpu_end = . ;
+ __per_cpu_end = . ;
+
__initcall_start = .;
.initcall.init : {
*(.initcall1.init)
diff --git a/arch/um/util/Makefile b/arch/um/util/Makefile
index 1a59751c61e0..a595641bed1b 100644
--- a/arch/um/util/Makefile
+++ b/arch/um/util/Makefile
@@ -1,4 +1,4 @@
-EXTRA_TARGETS := mk_task mk_task_kern.o
+EXTRA_TARGETS := mk_task mk_constants
$(obj)/mk_task: $(obj)/mk_task_user.o $(obj)/mk_task_kern.o
$(CC) -o $@ $^
@@ -6,6 +6,15 @@ $(obj)/mk_task: $(obj)/mk_task_user.o $(obj)/mk_task_kern.o
$(obj)/mk_task_user.o: $(src)/mk_task_user.c
$(CC) -o $@ -c $<
+$(obj)/mk_constants : $(obj)/mk_constants_user.o $(obj)/mk_constants_kern.o
+ $(CC) -o $@ $^
+
+$(obj)/mk_constants_user.o : $(src)/mk_constants_user.c
+ $(CC) -c $< -o $@
+
+$(obj)/mk_constants_kern.o : $(src)/mk_constants_kern.c
+ $(CC) $(CFLAGS) -c $< -o $@
+
clean:
$(RM) $(EXTRA_TARGETS)
diff --git a/arch/um/util/mk_constants_kern.c b/arch/um/util/mk_constants_kern.c
new file mode 100644
index 000000000000..7e74934318c4
--- /dev/null
+++ b/arch/um/util/mk_constants_kern.c
@@ -0,0 +1,24 @@
+#include "linux/kernel.h"
+#include "linux/stringify.h"
+#include "asm/page.h"
+
+extern void print_head(void);
+extern void print_constant_str(char *name, char *value);
+extern void print_constant_int(char *name, int value);
+extern void print_tail(void);
+
+int main(int argc, char **argv)
+{
+ print_head();
+ print_constant_int("UM_KERN_PAGE_SIZE", PAGE_SIZE);
+ print_constant_str("UM_KERN_EMERG", KERN_EMERG);
+ print_constant_str("UM_KERN_ALERT", KERN_ALERT);
+ print_constant_str("UM_KERN_CRIT", KERN_CRIT);
+ print_constant_str("UM_KERN_ERR", KERN_ERR);
+ print_constant_str("UM_KERN_WARNING", KERN_WARNING);
+ print_constant_str("UM_KERN_NOTICE", KERN_NOTICE);
+ print_constant_str("UM_KERN_INFO", KERN_INFO);
+ print_constant_str("UM_KERN_DEBUG", KERN_DEBUG);
+ print_tail();
+ return(0);
+}
diff --git a/arch/um/util/mk_constants_user.c b/arch/um/util/mk_constants_user.c
new file mode 100644
index 000000000000..8f4d7e50be7c
--- /dev/null
+++ b/arch/um/util/mk_constants_user.c
@@ -0,0 +1,28 @@
+#include <stdio.h>
+
+void print_head(void)
+{
+ printf("/*\n");
+ printf(" * Generated by mk_constants\n");
+ printf(" */\n");
+ printf("\n");
+ printf("#ifndef __UM_CONSTANTS_H\n");
+ printf("#define __UM_CONSTANTS_H\n");
+ printf("\n");
+}
+
+void print_constant_str(char *name, char *value)
+{
+ printf("#define %s \"%s\"\n", name, value);
+}
+
+void print_constant_int(char *name, int value)
+{
+ printf("#define %s %d\n", name, value);
+}
+
+void print_tail(void)
+{
+ printf("\n");
+ printf("#endif\n");
+}
diff --git a/arch/x86_64/Kconfig b/arch/x86_64/Kconfig
index 91472e7f99f7..13f7e51be1b3 100644
--- a/arch/x86_64/Kconfig
+++ b/arch/x86_64/Kconfig
@@ -672,6 +672,7 @@ source "drivers/usb/Kconfig"
source "net/bluetooth/Kconfig"
+source "arch/x86_64/oprofile/Kconfig"
menu "Kernel hacking"
@@ -728,7 +729,6 @@ config INIT_DEBUG
config KALLSYMS
bool "Load all symbols for debugging/kksymoops"
- depends on DEBUG_KERNEL
help
Say Y here to let the kernel print out symbolic crash information and
symbolic stack backtraces. This increases the size of the kernel
diff --git a/arch/x86_64/Makefile b/arch/x86_64/Makefile
index ac9649fd9b87..05f428f6a8cf 100644
--- a/arch/x86_64/Makefile
+++ b/arch/x86_64/Makefile
@@ -54,6 +54,8 @@ libs-y += arch/x86_64/lib/
core-y += arch/x86_64/kernel/ arch/x86_64/mm/
core-$(CONFIG_IA32_EMULATION) += arch/x86_64/ia32/
drivers-$(CONFIG_PCI) += arch/x86_64/pci/
+# FIXME: is drivers- right ?
+drivers-$(CONFIG_OPROFILE) += arch/x86_64/oprofile/
makeboot =$(Q)$(MAKE) -f scripts/Makefile.build obj=arch/x86_64/boot $(1)
diff --git a/arch/x86_64/boot/Makefile b/arch/x86_64/boot/Makefile
index b81e05baff84..2d234181b61b 100644
--- a/arch/x86_64/boot/Makefile
+++ b/arch/x86_64/boot/Makefile
@@ -47,6 +47,7 @@ cmd_image = $(obj)/tools/build $(BUILDFLAGS) $(obj)/bootsect $(obj)/setup \
$(obj)/zImage $(obj)/bzImage: $(obj)/bootsect $(obj)/setup \
$(obj)/vmlinux.bin $(obj)/tools/build FORCE
$(call if_changed,image)
+ @echo 'Kernel: $@ is ready'
$(obj)/vmlinux.bin: $(obj)/compressed/vmlinux FORCE
$(call if_changed,objcopy)
diff --git a/arch/x86_64/defconfig b/arch/x86_64/defconfig
index 864d6aa2ba60..e628de000df2 100644
--- a/arch/x86_64/defconfig
+++ b/arch/x86_64/defconfig
@@ -470,6 +470,7 @@ CONFIG_RTC=y
# CONFIG_FTAPE is not set
# CONFIG_AGP is not set
# CONFIG_AGP_GART is not set
+# CONFIG_AGP3 is not set
# CONFIG_DRM is not set
# CONFIG_MWAVE is not set
CONFIG_RAW_DRIVER=y
@@ -586,6 +587,11 @@ CONFIG_DUMMY_CONSOLE=y
# CONFIG_BT is not set
#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
# Kernel hacking
#
CONFIG_DEBUG_KERNEL=y
diff --git a/arch/x86_64/ia32/Makefile b/arch/x86_64/ia32/Makefile
index 457a337a43c4..0fa49b5c536a 100644
--- a/arch/x86_64/ia32/Makefile
+++ b/arch/x86_64/ia32/Makefile
@@ -6,4 +6,4 @@ export-objs := ia32_ioctl.o sys_ia32.o
obj-$(CONFIG_IA32_EMULATION) := ia32entry.o sys_ia32.o ia32_ioctl.o \
ia32_signal.o \
- ia32_binfmt.o fpu32.o socket32.o ptrace32.o ipc32.o
+ ia32_binfmt.o fpu32.o socket32.o ptrace32.o ipc32.o syscall32.o
diff --git a/arch/x86_64/ia32/fpu32.c b/arch/x86_64/ia32/fpu32.c
index ab476cbb12c9..0528b55b42d5 100644
--- a/arch/x86_64/ia32/fpu32.c
+++ b/arch/x86_64/ia32/fpu32.c
@@ -70,10 +70,6 @@ static inline unsigned long twd_fxsr_to_i387(struct i387_fxsave_struct *fxsave)
return ret;
}
-struct s10 {
- u64 a;
- u16 b;
-} __attribute__((packed));
static inline int convert_fxsr_from_user(struct i387_fxsave_struct *fxsave,
struct _fpstate_ia32 *buf)
@@ -98,9 +94,7 @@ static inline int convert_fxsr_from_user(struct i387_fxsave_struct *fxsave,
to = (struct _fpxreg *)&fxsave->st_space[0];
from = &buf->_st[0];
for (i = 0 ; i < 8 ; i++, to++, from++) {
- struct s10 *top = (void *)to, *fromp = (void *)from;
- if (__put_user(fromp->a, &top->a) ||
- __put_user(fromp->b, &top->b))
+ if (__copy_from_user(to, from, sizeof(*from)))
return -1;
}
return 0;
@@ -136,9 +130,7 @@ static inline int convert_fxsr_to_user(struct _fpstate_ia32 *buf,
to = &buf->_st[0];
from = (struct _fpxreg *) &fxsave->st_space[0];
for ( i = 0 ; i < 8 ; i++, to++, from++ ) {
- struct s10 *top = (void *)top, *fromp = (void *)from;
- if (__get_user(fromp->a, &top->a) ||
- __get_user(fromp->b, &top->b))
+ if (__copy_to_user(to, from, sizeof(*to)))
return -1;
}
return 0;
diff --git a/arch/x86_64/ia32/ia32_binfmt.c b/arch/x86_64/ia32/ia32_binfmt.c
index 3fd8ae63faaf..be9f9da4bb2d 100644
--- a/arch/x86_64/ia32/ia32_binfmt.c
+++ b/arch/x86_64/ia32/ia32_binfmt.c
@@ -23,6 +23,12 @@
#include <asm/uaccess.h>
#include <asm/ia32.h>
+#define ELF_NAME "elf/i386"
+
+#define AT_SYSINFO 32
+
+#define ARCH_DLINFO NEW_AUX_ENT(AT_SYSINFO, 0xffffe000)
+
struct file;
struct elf_phdr;
diff --git a/arch/x86_64/ia32/ia32entry.S b/arch/x86_64/ia32/ia32entry.S
index 002940247a7f..b5f238bc5533 100644
--- a/arch/x86_64/ia32/ia32entry.S
+++ b/arch/x86_64/ia32/ia32entry.S
@@ -2,8 +2,6 @@
* Compatibility mode system call entry point for x86-64.
*
* Copyright 2000-2002 Andi Kleen, SuSE Labs.
- *
- * $Id: ia32entry.S,v 1.31 2002/03/24 13:01:45 ak Exp $
*/
#include <asm/calling.h>
@@ -15,19 +13,21 @@
#include <asm/segment.h>
#include <linux/linkage.h>
- .macro IA32_ARG_FIXUP
+ .macro IA32_ARG_FIXUP noebp=0
movl %edi,%r8d
+ .if \noebp
+ .else
movl %ebp,%r9d
+ .endif
xchg %ecx,%esi
movl %ebx,%edi
movl %edx,%edx /* zero extension */
.endm
/*
- * 32bit SYSCALL instruction entry. This is called from the 32bit vsyscall page.
- *
- * Register setup:
+ * 32bit SYSCALL instruction entry.
*
+ * Arguments:
* %eax System call number.
* %ebx Arg1
* %ecx return EIP
@@ -53,40 +53,51 @@ ENTRY(ia32_cstar_target)
movl %eax,%eax /* zero extension */
movq %rax,ORIG_RAX-ARGOFFSET(%rsp)
movq %rcx,RIP-ARGOFFSET(%rsp)
+ movq %rbp,RCX-ARGOFFSET(%rsp) /* this lies slightly to ptrace */
movl %ebp,%ecx
movq $__USER32_CS,CS-ARGOFFSET(%rsp)
movq $__USER32_DS,SS-ARGOFFSET(%rsp)
movq %r11,EFLAGS-ARGOFFSET(%rsp)
movq %r8,RSP-ARGOFFSET(%rsp)
- /* no need to do an access_ok check here because the 32bit
- user space cannot set r8 to a value > 4GB and the kernel has no
- memory mapping in the first 4GB. */
+ /* no need to do an access_ok check here because r8 has been
+ 32bit zero extended */
/* hardware stack frame is complete now */
-1: movl (%r8),%ebp
+1: movl (%r8),%r9d
.section __ex_table,"a"
.quad 1b,cstar_badarg
.previous
+ movq %r9,R9-ARGOFFSET(%rsp)
GET_THREAD_INFO(%r10)
bt $TIF_SYSCALL_TRACE,threadinfo_flags(%r10)
jc ia32_tracesys
+cstar_do_call:
cmpl $IA32_NR_syscalls,%eax
jae ia32_badsys
- IA32_ARG_FIXUP
+ IA32_ARG_FIXUP 1
call *ia32_sys_call_table(,%rax,8)
- .globl ia32_sysret
+ .globl cstar_sysret
cstar_sysret:
movq %rax,RAX-ARGOFFSET(%rsp)
GET_THREAD_INFO(%r10)
cli
- testl $_TIF_WORK_MASK,threadinfo_flags(%r10)
+ testl $_TIF_ALLWORK_MASK,threadinfo_flags(%r10)
jnz int_ret_from_sys_call
- RESTORE_ARGS 1,0,1,1 /* could avoid the stack restore here */
- movl RIP-SWFRAME(%rsp),%ecx
- movl RSP-SWFRAME(%rsp),%esp
- movl EFLAGS-SWFRAME(%rsp),%r11d
+ RESTORE_ARGS 1,-ARG_SKIP,1,1
+ movl RIP-ARGOFFSET(%rsp),%ecx
+ movl EFLAGS-ARGOFFSET(%rsp),%r11d
+ movl RSP-ARGOFFSET(%rsp),%esp
swapgs
sysretl
+cstar_tracesys:
+ SAVE_REST
+ movq $-ENOSYS,RAX(%rsp) /* really needed? */
+ movq %rsp,%rdi /* &pt_regs -> arg1 */
+ call syscall_trace
+ LOAD_ARGS ARGOFFSET /* reload args from stack in case ptrace changed it */
+ RESTORE_REST
+ jmp cstar_do_call
+
cstar_badarg:
movq $-EFAULT,%rax
jmp cstar_sysret
@@ -115,8 +126,11 @@ cstar_badarg:
ENTRY(ia32_syscall)
swapgs
sti
+ movl %eax,%eax
pushq %rax
cld
+ /* note the registers are not zero extended to the sf.
+ this could be a problem */
SAVE_ARGS
GET_THREAD_INFO(%r10)
bt $TIF_SYSCALL_TRACE,threadinfo_flags(%r10)
diff --git a/arch/x86_64/ia32/sys_ia32.c b/arch/x86_64/ia32/sys_ia32.c
index 24b33f75bfb5..3d9ef0ff67ce 100644
--- a/arch/x86_64/ia32/sys_ia32.c
+++ b/arch/x86_64/ia32/sys_ia32.c
@@ -86,6 +86,11 @@
extern int overflowuid,overflowgid;
+extern asmlinkage long sys_newstat(char * filename, struct stat * statbuf);
+extern asmlinkage long sys_newlstat(char * filename, struct stat * statbuf);
+extern asmlinkage long sys_newfstat(unsigned int fd, struct stat * statbuf);
+
+
int cp_compat_stat(struct kstat *kbuf, struct compat_stat *ubuf)
{
if (verify_area(VERIFY_WRITE, ubuf, sizeof(struct compat_stat)) ||
diff --git a/arch/x86_64/ia32/syscall32.c b/arch/x86_64/ia32/syscall32.c
new file mode 100644
index 000000000000..f0d45a725064
--- /dev/null
+++ b/arch/x86_64/ia32/syscall32.c
@@ -0,0 +1,64 @@
+/* Copyright 2002 Andi Kleen, SuSE Labs */
+
+/* vsyscall handling for 32bit processes. Map a stub page into it
+ on demand because 32bit cannot reach the kernel's fixmaps */
+
+#include <linux/mm.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/gfp.h>
+#include <linux/init.h>
+#include <asm/proto.h>
+#include <asm/tlbflush.h>
+
+/* 32bit SYSCALL stub mapped into user space. */
+asm(" .code32\n"
+ "\nsyscall32:\n"
+ " pushl %ebp\n"
+ " movl %ecx,%ebp\n"
+ " syscall\n"
+ " popl %ebp\n"
+ " ret\n"
+ "syscall32_end:\n"
+ " .code64\n");
+
+extern unsigned char syscall32[], syscall32_end[];
+
+static unsigned long syscall32_page;
+
+/* RED-PEN: This knows too much about high level VM */
+/* Alternative would be to generate a vma with appropiate backing options
+ and let it be handled by generic VM */
+int map_syscall32(struct mm_struct *mm, unsigned long address)
+{
+ pte_t *pte;
+ int err = 0;
+ down_read(&mm->mmap_sem);
+ spin_lock(&mm->page_table_lock);
+ pmd_t *pmd = pmd_alloc(mm, pgd_offset(mm, address), address);
+ if (pmd && (pte = pte_alloc_map(mm, pmd, address)) != NULL) {
+ if (pte_none(*pte)) {
+ set_pte(pte,
+ mk_pte(virt_to_page(syscall32_page),
+ PAGE_KERNEL_VSYSCALL));
+ }
+ /* Flush only the local CPU. Other CPUs taking a fault
+ will just end up here again */
+ __flush_tlb_one(address);
+ } else
+ err = -ENOMEM;
+ spin_unlock(&mm->page_table_lock);
+ up_read(&mm->mmap_sem);
+ return err;
+}
+
+static int __init init_syscall32(void)
+{
+ syscall32_page = get_zeroed_page(GFP_KERNEL);
+ if (!syscall32_page)
+ panic("Cannot allocate syscall32 page");
+ SetPageReserved(virt_to_page(syscall32_page));
+ memcpy((void *)syscall32_page, syscall32, syscall32_end - syscall32);
+}
+
+__initcall(init_syscall32);
diff --git a/arch/x86_64/kernel/Makefile b/arch/x86_64/kernel/Makefile
index e5b573273dd8..61d5387df48c 100644
--- a/arch/x86_64/kernel/Makefile
+++ b/arch/x86_64/kernel/Makefile
@@ -9,7 +9,7 @@ export-objs := x8664_ksyms.o pci-gart.o pci-dma.o
obj-y := process.o semaphore.o signal.o entry.o traps.o irq.o \
ptrace.o i8259.o ioport.o ldt.o setup.o time.o sys_x86_64.o \
pci-dma.o x8664_ksyms.o i387.o syscall.o vsyscall.o \
- setup64.o bluesmoke.o bootflag.o e820.o reboot.o profile.o
+ setup64.o bluesmoke.o bootflag.o e820.o reboot.o
obj-$(CONFIG_MTRR) += mtrr/
obj-$(CONFIG_X86_MSR) += msr.o
@@ -24,6 +24,8 @@ obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
obj-$(CONFIG_GART_IOMMU) += pci-gart.o aperture.o
obj-$(CONFIG_DUMMY_IOMMU) += pci-nommu.o
obj-$(CONFIG_MODULES) += module.o
+obj-$(CONFIG_PROFILING) += profile.o
+
$(obj)/bootflag.c:
@ln -sf ../../i386/kernel/bootflag.c $(obj)/bootflag.c
diff --git a/arch/x86_64/kernel/apic.c b/arch/x86_64/kernel/apic.c
index d1effba49185..f56ca7829a82 100644
--- a/arch/x86_64/kernel/apic.c
+++ b/arch/x86_64/kernel/apic.c
@@ -987,6 +987,7 @@ asmlinkage void smp_spurious_interrupt(void)
printk(KERN_INFO "spurious APIC interrupt on CPU#%d, %ld skipped.\n",
smp_processor_id(), skipped);
last_warning = jiffies;
+ skipped = 0;
} else {
skipped++;
}
diff --git a/arch/x86_64/kernel/signal.c b/arch/x86_64/kernel/signal.c
index d7e21aa7eb0a..a2c0878a1c16 100644
--- a/arch/x86_64/kernel/signal.c
+++ b/arch/x86_64/kernel/signal.c
@@ -472,6 +472,11 @@ void do_notify_resume(struct pt_regs *regs, sigset_t *oldset, __u32 thread_info_
thread_info_flags, regs->rip, regs->rsp, __builtin_return_address(0),signal_pending(current));
#endif
+ /* Pending single-step? */
+ if (thread_info_flags & _TIF_SINGLESTEP) {
+ regs->eflags |= TF_MASK;
+ clear_thread_flag(TIF_SINGLESTEP);
+ }
/* deal with pending signal delivery */
if (thread_info_flags & _TIF_SIGPENDING)
diff --git a/arch/x86_64/kernel/time.c b/arch/x86_64/kernel/time.c
index b1e4cefda410..67d2cf41c2ed 100644
--- a/arch/x86_64/kernel/time.c
+++ b/arch/x86_64/kernel/time.c
@@ -222,6 +222,19 @@ static void timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
do_timer(regs);
/*
+ * In the SMP case we use the local APIC timer interrupt to do the profiling,
+ * except when we simulate SMP mode on a uniprocessor system, in that case we
+ * have to call the local interrupt handler.
+ */
+
+#ifndef CONFIG_X86_LOCAL_APIC
+ x86_do_profile(regs);
+#else
+ if (!using_apic_timer)
+ smp_local_timer_interrupt(regs);
+#endif
+
+/*
* If we have an externally synchronized Linux clock, then update CMOS clock
* accordingly every ~11 minutes. set_rtc_mmss() will be called in the jiffy
* closest to exactly 500 ms before the next second. If the update fails, we
diff --git a/arch/x86_64/kernel/traps.c b/arch/x86_64/kernel/traps.c
index 21b3fbd5330e..46a397e924a3 100644
--- a/arch/x86_64/kernel/traps.c
+++ b/arch/x86_64/kernel/traps.c
@@ -635,7 +635,7 @@ asmlinkage void do_debug(struct pt_regs * regs, long error_code)
* interface.
*/
if ((regs->cs & 3) == 0)
- goto clear_TF;
+ goto clear_TF_reenable;
if ((tsk->ptrace & (PT_DTRACE|PT_PTRACED)) == PT_DTRACE)
goto clear_TF;
}
@@ -653,6 +653,9 @@ clear_dr7:
asm("movq %0,%%db7"::"r"(0UL));
return;
+clear_TF_reenable:
+ set_tsk_thread_flag(tsk, TIF_SINGLESTEP);
+
clear_TF:
regs->eflags &= ~TF_MASK;
return;
diff --git a/arch/x86_64/kernel/x8664_ksyms.c b/arch/x86_64/kernel/x8664_ksyms.c
index 7d2700fbbedd..2cb3459d0337 100644
--- a/arch/x86_64/kernel/x8664_ksyms.c
+++ b/arch/x86_64/kernel/x8664_ksyms.c
@@ -26,6 +26,7 @@
#include <asm/desc.h>
#include <asm/pgtable.h>
#include <asm/pgalloc.h>
+#include <asm/nmi.h>
#include <asm/kdebug.h>
#include <asm/unistd.h>
@@ -116,7 +117,11 @@ EXPORT_SYMBOL_NOVERS(__read_lock_failed);
EXPORT_SYMBOL(synchronize_irq);
EXPORT_SYMBOL(smp_call_function);
+#endif
+#if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_PM)
+EXPORT_SYMBOL_GPL(set_nmi_pm_callback);
+EXPORT_SYMBOL_GPL(unset_nmi_pm_callback);
#endif
#ifdef CONFIG_VT
@@ -127,6 +132,11 @@ EXPORT_SYMBOL(get_wchan);
EXPORT_SYMBOL(rtc_lock);
+EXPORT_SYMBOL_GPL(register_profile_notifier);
+EXPORT_SYMBOL_GPL(unregister_profile_notifier);
+EXPORT_SYMBOL_GPL(set_nmi_callback);
+EXPORT_SYMBOL_GPL(unset_nmi_callback);
+
/* Export string functions. We normally rely on gcc builtin for most of these,
but gcc sometimes decides not to inline them. */
#undef memcpy
diff --git a/arch/x86_64/mm/fault.c b/arch/x86_64/mm/fault.c
index 5f93c2d6ba2f..00708d1d82e3 100644
--- a/arch/x86_64/mm/fault.c
+++ b/arch/x86_64/mm/fault.c
@@ -29,6 +29,7 @@
#include <asm/hardirq.h>
#include <asm/smp.h>
#include <asm/tlbflush.h>
+#include <asm/proto.h>
extern void die(const char *,struct pt_regs *,long);
@@ -211,6 +212,15 @@ bad_area_nosemaphore:
/* User mode accesses just cause a SIGSEGV */
if (error_code & 4) {
+#ifdef CONFIG_IA32_EMULATION
+ /* 32bit vsyscall. map on demand. */
+ if (test_thread_flag(TIF_IA32) &&
+ address >= 0xffffe000 && address < 0xffffefff-7) {
+ if (map_syscall32(mm, address) < 0)
+ goto out_of_memory2;
+ return;
+ }
+#endif
printk("%s[%d] segfault at rip:%lx rsp:%lx adr:%lx err:%lx\n",
tsk->comm, tsk->pid, regs->rip, regs->rsp, address,
error_code);
@@ -263,6 +273,7 @@ no_context:
*/
out_of_memory:
up_read(&mm->mmap_sem);
+out_of_memory2:
if (current->pid == 1) {
yield();
goto again;
@@ -300,9 +311,6 @@ vmalloc_fault:
pmd_t *pmd;
pte_t *pte;
- printk("vmalloc_fault err %lx addr %lx rip %lx\n",
- error_code, address, regs->rip);
-
/*
* x86-64 has the same kernel 3rd level pages for all CPUs.
* But for vmalloc/modules the TLB synchronization works lazily,
diff --git a/arch/x86_64/oprofile/Kconfig b/arch/x86_64/oprofile/Kconfig
new file mode 100644
index 000000000000..5ade19801b97
--- /dev/null
+++ b/arch/x86_64/oprofile/Kconfig
@@ -0,0 +1,23 @@
+
+menu "Profiling support"
+ depends on EXPERIMENTAL
+
+config PROFILING
+ bool "Profiling support (EXPERIMENTAL)"
+ help
+ Say Y here to enable the extended profiling support mechanisms used
+ by profilers such as OProfile.
+
+
+config OPROFILE
+ tristate "OProfile system profiling (EXPERIMENTAL)"
+ depends on PROFILING
+ help
+ OProfile is a profiling system capable of profiling the
+ whole system, include the kernel, kernel modules, libraries,
+ and applications.
+
+ If unsure, say N.
+
+endmenu
+
diff --git a/arch/x86_64/oprofile/Makefile b/arch/x86_64/oprofile/Makefile
new file mode 100644
index 000000000000..ab145c3f81c5
--- /dev/null
+++ b/arch/x86_64/oprofile/Makefile
@@ -0,0 +1,33 @@
+#
+# oprofile for x86-64.
+# Just reuse the one from i386. The Hammer performance counters
+# are similar to Athlon.
+#
+
+obj-$(CONFIG_OPROFILE) += oprofile.o
+
+DRIVER_OBJS = $(addprefix ../../../drivers/oprofile/, \
+ oprof.o cpu_buffer.o buffer_sync.o \
+ event_buffer.o oprofile_files.o \
+ oprofilefs.o oprofile_stats.o )
+
+oprofile-objs := $(DRIVER_OBJS) init.o timer_int.o
+
+oprofile-$(CONFIG_X86_LOCAL_APIC) += nmi_int.o op_model_athlon.o
+
+INCL := $(obj)/op_counter.h $(obj)/op_x86_model.h
+
+$(obj)/nmi_int.c: ${INCL}
+ @ln -sf ../../i386/oprofile/nmi_int.c $(obj)/nmi_int.c
+$(obj)/op_model_athlon.c: ${INCL}
+ @ln -sf ../../i386/oprofile/op_model_athlon.c $(obj)/op_model_athlon.c
+$(obj)/init.c: ${INCL}
+ @ln -sf ../../i386/oprofile/init.c $(obj)/init.c
+$(obj)/timer_int.c: ${INCL}
+ @ln -sf ../../i386/oprofile/timer_int.c $(obj)/timer_int.c
+$(obj)/op_counter.h:
+ @ln -sf ../../i386/oprofile/op_counter.h $(obj)/op_counter.h
+$(obj)/op_x86_model.h:
+ @ln -sf ../../i386/oprofile/op_x86_model.h $(obj)/op_x86_model.h
+clean-files += op_x86_model.h op_counter.h timer_int.c init.c \
+ op_model_athlon.c nmi_int.c
diff --git a/crypto/api.c b/crypto/api.c
index 626437fb5dea..64886f4d6335 100644
--- a/crypto/api.c
+++ b/crypto/api.c
@@ -29,8 +29,7 @@ static inline int crypto_alg_get(struct crypto_alg *alg)
static inline void crypto_alg_put(struct crypto_alg *alg)
{
- if (alg->cra_module)
- __MOD_DEC_USE_COUNT(alg->cra_module);
+ module_put(alg->cra_module);
}
struct crypto_alg *crypto_alg_lookup(const char *name)
diff --git a/drivers/block/acsi.c b/drivers/block/acsi.c
index 2a3b46773d88..958ef4898971 100644
--- a/drivers/block/acsi.c
+++ b/drivers/block/acsi.c
@@ -493,8 +493,7 @@ static int acsicmd_dma( const char *cmd, char *buffer, int blocks, int rwflag, i
acsi_delay_end(COMMAND_DELAY);
DISABLE_IRQ();
- save_flags(flags);
- cli();
+ local_irq_save(flags);
/* Low on A1 */
dma_wd.dma_mode_status = 0x88 | rwflag;
MFPDELAY();
@@ -511,7 +510,7 @@ static int acsicmd_dma( const char *cmd, char *buffer, int blocks, int rwflag, i
else
dma_wd.dma_hi = (unsigned char)paddr;
MFPDELAY();
- restore_flags(flags);
+ local_irq_restore(flags);
/* send the command bytes except the last */
for( i = 0; i < 5; ++i ) {
diff --git a/drivers/block/acsi_slm.c b/drivers/block/acsi_slm.c
index 7ca90514abf0..918b0e8cb287 100644
--- a/drivers/block/acsi_slm.c
+++ b/drivers/block/acsi_slm.c
@@ -500,12 +500,11 @@ static void slm_test_ready( unsigned long dummy )
int did_wait = 0;
#endif
- save_flags(flags);
- cli();
-
+ local_irq_save(flags);
+
addr = get_dma_addr();
if ((d = SLMEndAddr - addr) > 0) {
- restore_flags(flags);
+ local_irq_restore(flags);
/* slice not yet finished, decide whether to start another timer or to
* busy-wait */
@@ -523,7 +522,7 @@ static void slm_test_ready( unsigned long dummy )
do_gettimeofday( &start_tm );
did_wait = 1;
#endif
- cli();
+ local_irq_disable();
while( get_dma_addr() < SLMEndAddr )
barrier();
}
@@ -547,7 +546,7 @@ static void slm_test_ready( unsigned long dummy )
DMA_LONG_WRITE( SLM_DMA_AMOUNT, 0x112 );
#endif
- restore_flags(flags);
+ local_irq_restore(flags);
#ifdef DEBUG
if (did_wait) {
@@ -584,10 +583,9 @@ static void slm_test_ready( unsigned long dummy )
static void set_dma_addr( unsigned long paddr )
-{ unsigned long flags;
-
- save_flags(flags);
- cli();
+{ unsigned long flags;
+
+ local_irq_save(flags);
dma_wd.dma_lo = (unsigned char)paddr;
paddr >>= 8;
MFPDELAY();
@@ -599,7 +597,7 @@ static void set_dma_addr( unsigned long paddr )
else
dma_wd.dma_hi = (unsigned char)paddr;
MFPDELAY();
- restore_flags(flags);
+ local_irq_restore(flags);
}
diff --git a/drivers/block/amiflop.c b/drivers/block/amiflop.c
index f28d18733af5..85728c00645f 100644
--- a/drivers/block/amiflop.c
+++ b/drivers/block/amiflop.c
@@ -72,6 +72,7 @@
#include <linux/amifd.h>
#include <linux/ioport.h>
#include <linux/buffer_head.h>
+#include <linux/interrupt.h>
#include <asm/setup.h>
#include <asm/uaccess.h>
@@ -228,12 +229,11 @@ static void ms_delay(int ms)
unsigned long flags;
int ticks;
if (ms > 0) {
- save_flags(flags);
- cli();
+ local_irq_save(flags);
while (ms_busy == 0)
sleep_on(&ms_wait);
ms_busy = 0;
- restore_flags(flags);
+ local_irq_restore(flags);
ticks = MS_TICKS*ms-1;
ciaa.tblo=ticks%256;
ciaa.tbhi=ticks/256;
@@ -259,13 +259,12 @@ static void get_fdc(int drive)
#ifdef DEBUG
printk("get_fdc: drive %d fdc_busy %d fdc_nested %d\n",drive,fdc_busy,fdc_nested);
#endif
- save_flags(flags);
- cli();
+ local_irq_save(flags);
while (!try_fdc(drive))
sleep_on(&fdc_wait);
fdc_busy = drive;
fdc_nested++;
- restore_flags(flags);
+ local_irq_restore(flags);
}
static inline void rel_fdc(void)
@@ -321,8 +320,7 @@ static void fd_deselect (int drive)
}
get_fdc(drive);
- save_flags (flags);
- sti();
+ local_irq_save(flags);
selected = -1;
@@ -330,7 +328,7 @@ static void fd_deselect (int drive)
prb |= (SELMASK(0)|SELMASK(1)|SELMASK(2)|SELMASK(3));
ciab.prb = prb;
- restore_flags (flags);
+ local_irq_restore (flags);
rel_fdc();
}
@@ -1305,10 +1303,9 @@ static int non_int_flush_track (unsigned long nr)
rel_fdc();
return 0;
}
- save_flags(flags);
- cli();
+ local_irq_save(flags);
if (writepending != 2) {
- restore_flags(flags);
+ local_irq_restore(flags);
(*unit[nr].dtype->write_fkt)(nr);
if (!raw_write(nr)) {
printk (KERN_NOTICE "floppy disk write protected "
@@ -1320,7 +1317,7 @@ static int non_int_flush_track (unsigned long nr)
sleep_on (&wait_fd_block);
}
else {
- restore_flags(flags);
+ local_irq_restore(flags);
ms_delay(2); /* 2 ms post_write delay */
post_write(nr);
}
@@ -1428,8 +1425,7 @@ static void redo_fd_request(void)
* setup a callback to write the track buffer
* after a short (1 tick) delay.
*/
- save_flags (flags);
- cli();
+ local_irq_save(flags);
floppy->dirty = 1;
/* reset the timer */
@@ -1437,7 +1433,7 @@ static void redo_fd_request(void)
flush_track_timer[drive].expires = jiffies + 1;
add_timer (flush_track_timer + drive);
- restore_flags (flags);
+ local_irq_restore(flags);
break;
}
}
@@ -1606,15 +1602,14 @@ static int floppy_open(struct inode *inode, struct file *filp)
}
}
- save_flags(flags);
- cli();
+ local_irq_save(flags);
fd_ref[drive]++;
fd_device[drive] = system;
#ifdef MODULE
if (unit[drive].motor == 0)
MOD_INC_USE_COUNT;
#endif
- restore_flags(flags);
+ local_irq_restore(flags);
if (old_dev != system)
invalidate_buffers(mk_kdev(FLOPPY_MAJOR, drive + (system << 2)));
diff --git a/drivers/block/ataflop.c b/drivers/block/ataflop.c
index d4d03d9a6a1d..c9dc16a8059e 100644
--- a/drivers/block/ataflop.c
+++ b/drivers/block/ataflop.c
@@ -248,24 +248,24 @@ static struct atari_floppy_struct {
#define FDC_READ(reg) ({ \
/* unsigned long __flags; */ \
unsigned short __val; \
- /* save_flags(__flags); cli(); */ \
+ /* local_irq_save(__flags); */ \
dma_wd.dma_mode_status = 0x80 | (reg); \
udelay(25); \
__val = dma_wd.fdc_acces_seccount; \
MFPDELAY(); \
- /* restore_flags(__flags); */ \
+ /* local_irq_restore(__flags); */ \
__val & 0xff; \
})
#define FDC_WRITE(reg,val) \
do { \
/* unsigned long __flags; */ \
- /* save_flags(__flags); cli(); */ \
+ /* local_irq_save(__flags); */ \
dma_wd.dma_mode_status = 0x80 | (reg); \
udelay(25); \
dma_wd.fdc_acces_seccount = (val); \
MFPDELAY(); \
- /* restore_flags(__flags); */ \
+ /* local_irq_restore(__flags); */ \
} while(0)
@@ -394,7 +394,7 @@ static int floppy_release( struct inode * inode, struct file * filp );
static struct timer_list motor_off_timer =
TIMER_INITIALIZER(fd_motor_off_timer, 0, 0);
-static struct timer_list readtrack_timer
+static struct timer_list readtrack_timer =
TIMER_INITIALIZER(fd_readtrack_check, 0, 0);
static struct timer_list timeout_timer =
@@ -434,14 +434,14 @@ static void fd_select_side( int side )
{
unsigned long flags;
- save_flags(flags);
- cli(); /* protect against various other ints mucking around with the PSG */
+ /* protect against various other ints mucking around with the PSG */
+ local_irq_save(flags);
sound_ym.rd_data_reg_sel = 14; /* Select PSG Port A */
sound_ym.wd_data = (side == 0) ? sound_ym.rd_data_reg_sel | 0x01 :
sound_ym.rd_data_reg_sel & 0xfe;
- restore_flags(flags);
+ local_irq_restore(flags);
}
@@ -457,13 +457,13 @@ static void fd_select_drive( int drive )
if (drive == SelectedDrive)
return;
- save_flags(flags);
- cli(); /* protect against various other ints mucking around with the PSG */
+ /* protect against various other ints mucking around with the PSG */
+ local_irq_save(flags);
sound_ym.rd_data_reg_sel = 14; /* Select PSG Port A */
tmp = sound_ym.rd_data_reg_sel;
sound_ym.wd_data = (tmp | DSKDRVNONE) & ~(drive == 0 ? DSKDRV0 : DSKDRV1);
atari_dont_touch_floppy_select = 1;
- restore_flags(flags);
+ local_irq_restore(flags);
/* restore track register to saved value */
FDC_WRITE( FDCREG_TRACK, UD.track );
@@ -484,8 +484,8 @@ static void fd_deselect( void )
{
unsigned long flags;
- save_flags(flags);
- cli(); /* protect against various other ints mucking around with the PSG */
+ /* protect against various other ints mucking around with the PSG */
+ local_irq_save(flags);
atari_dont_touch_floppy_select = 0;
sound_ym.rd_data_reg_sel=14; /* Select PSG Port A */
sound_ym.wd_data = (sound_ym.rd_data_reg_sel |
@@ -493,7 +493,7 @@ static void fd_deselect( void )
/* On Falcon, the drive B select line is used on the printer port, so
* leave it alone... */
SelectedDrive = -1;
- restore_flags(flags);
+ local_irq_restore(flags);
}
@@ -549,8 +549,8 @@ static void check_change( unsigned long dummy )
if (++drive > 1 || !UD.connected)
drive = 0;
- save_flags(flags);
- cli(); /* protect against various other ints mucking around with the PSG */
+ /* protect against various other ints mucking around with the PSG */
+ local_irq_save(flags);
if (!stdma_islocked()) {
sound_ym.rd_data_reg_sel = 14;
@@ -566,7 +566,7 @@ static void check_change( unsigned long dummy )
set_bit (drive, &changed_floppies);
}
}
- restore_flags(flags);
+ local_irq_restore(flags);
start_check_change_timer();
}
@@ -666,13 +666,12 @@ static int do_format(kdev_t device, struct atari_format_descr *desc)
DPRINT(("do_format( dr=%d tr=%d he=%d offs=%d )\n",
drive, desc->track, desc->head, desc->sect_offset ));
- save_flags(flags);
- cli();
+ local_irq_save(flags);
while( fdc_busy ) sleep_on( &fdc_wait );
fdc_busy = 1;
stdma_lock(floppy_irq, NULL);
atari_turnon_irq( IRQ_MFP_FDC ); /* should be already, just to be sure */
- restore_flags(flags);
+ local_irq_restore(flags);
type = minor(device) >> 2;
if (type) {
@@ -930,8 +929,7 @@ static void fd_rwsec( void )
udelay(25);
/* Setup DMA */
- save_flags(flags);
- cli();
+ local_irq_save(flags);
dma_wd.dma_lo = (unsigned char)paddr;
MFPDELAY();
paddr >>= 8;
@@ -943,7 +941,7 @@ static void fd_rwsec( void )
else
dma_wd.dma_hi = (unsigned char)paddr;
MFPDELAY();
- restore_flags(flags);
+ local_irq_restore(flags);
/* Clear FIFO and switch DMA to correct mode */
dma_wd.dma_mode_status = 0x90 | rwflag;
@@ -990,8 +988,7 @@ static void fd_readtrack_check( unsigned long dummy )
{
unsigned long flags, addr, addr2;
- save_flags(flags);
- cli();
+ local_irq_save(flags);
if (!MultReadInProgress) {
/* This prevents a race condition that could arise if the
@@ -1000,7 +997,7 @@ static void fd_readtrack_check( unsigned long dummy )
* already cleared 'MultReadInProgress' when flow of control
* gets here.
*/
- restore_flags(flags);
+ local_irq_restore(flags);
return;
}
@@ -1026,7 +1023,7 @@ static void fd_readtrack_check( unsigned long dummy )
*/
SET_IRQ_HANDLER( NULL );
MultReadInProgress = 0;
- restore_flags(flags);
+ local_irq_restore(flags);
DPRINT(("fd_readtrack_check(): done\n"));
FDC_WRITE( FDCREG_CMD, FDCCMD_FORCI );
udelay(25);
@@ -1038,7 +1035,7 @@ static void fd_readtrack_check( unsigned long dummy )
}
else {
/* not yet finished, wait another tenth rotation */
- restore_flags(flags);
+ local_irq_restore(flags);
DPRINT(("fd_readtrack_check(): not yet finished\n"));
mod_timer(&readtrack_timer, jiffies + HZ/5/10);
}
@@ -1199,8 +1196,7 @@ static void fd_writetrack( void )
udelay(40);
/* Setup DMA */
- save_flags(flags);
- cli();
+ local_irq_save(flags);
dma_wd.dma_lo = (unsigned char)paddr;
MFPDELAY();
paddr >>= 8;
@@ -1212,7 +1208,7 @@ static void fd_writetrack( void )
else
dma_wd.dma_hi = (unsigned char)paddr;
MFPDELAY();
- restore_flags(flags);
+ local_irq_restore(flags);
/* Clear FIFO and switch DMA to correct mode */
dma_wd.dma_mode_status = 0x190;
@@ -1325,12 +1321,11 @@ static void finish_fdc_done( int dummy )
start_check_change_timer();
start_motor_off_timer();
- save_flags(flags);
- cli();
+ local_irq_save(flags);
stdma_release();
fdc_busy = 0;
wake_up( &fdc_wait );
- restore_flags(flags);
+ local_irq_restore(flags);
DPRINT(("finish_fdc() finished\n"));
}
@@ -1519,10 +1514,10 @@ void do_fd_request(request_queue_t * q)
stdma_lock(floppy_irq, NULL);
atari_disable_irq( IRQ_MFP_FDC );
- save_flags(flags); /* The request function is called with ints
- sti(); * disabled... so must save the IPL for later */
+ local_save_flags(flags); /* The request function is called with ints
+ local_irq_disable(); * disabled... so must save the IPL for later */
redo_fd_request();
- restore_flags(flags);
+ local_irq_restore(flags);
atari_enable_irq( IRQ_MFP_FDC );
}
diff --git a/drivers/block/genhd.c b/drivers/block/genhd.c
index 98a62d7c7a6b..c133b454b2fb 100644
--- a/drivers/block/genhd.c
+++ b/drivers/block/genhd.c
@@ -168,15 +168,13 @@ retry:
best = p->range;
*part = dev - p->dev;
if (p->lock && p->lock(dev, data) < 0) {
- if (owner)
- __MOD_DEC_USE_COUNT(owner);
+ module_put(owner);
continue;
}
read_unlock(&gendisk_lock);
disk = probe(dev, part, data);
/* Currently ->owner protects _only_ ->probe() itself. */
- if (owner)
- __MOD_DEC_USE_COUNT(owner);
+ module_put(owner);
if (disk)
return disk;
goto retry;
diff --git a/drivers/block/paride/paride.c b/drivers/block/paride/paride.c
index 3c1161767acf..0b19343f6969 100644
--- a/drivers/block/paride/paride.c
+++ b/drivers/block/paride/paride.c
@@ -175,8 +175,7 @@ void pi_release(PIA * pi)
#endif /* !CONFIG_PARPORT */
if (pi->proto->release_proto)
pi->proto->release_proto(pi);
- if (pi->proto->owner)
- __MOD_DEC_USE_COUNT(pi->proto->owner);
+ module_put(pi->proto->owner);
}
EXPORT_SYMBOL(pi_release);
@@ -238,7 +237,6 @@ int pi_register(PIP * pr)
printk("paride: protocol table full\n");
return 0;
}
- MOD_INC_USE_COUNT;
protocols[k] = pr;
pr->index = k;
printk("paride: %s registered as protocol %d\n", pr->name, k);
@@ -256,7 +254,6 @@ void pi_unregister(PIP * pr)
return;
}
protocols[pr->index] = 0;
- MOD_DEC_USE_COUNT;
}
EXPORT_SYMBOL(pi_unregister);
@@ -392,14 +389,13 @@ int pi_init(PIA * pi, int autoprobe, int port, int mode,
if (!proto)
continue;
/* still racy */
- if (proto->owner)
- __MOD_INC_USE_COUNT(proto->owner);
+ if (!try_module_get(proto->owner))
+ continue;
pi->proto = proto;
pi->private = 0;
if (proto->init_proto && proto->init_proto(pi) < 0) {
pi->proto = NULL;
- if (proto->owner)
- __MOD_DEC_USE_COUNT(proto->owner);
+ module_put(proto->owner);
continue;
}
if (delay == -1)
@@ -432,8 +428,7 @@ int pi_init(PIA * pi, int autoprobe, int port, int mode,
}
if (pi->proto->release_proto)
pi->proto->release_proto(pi);
- if (proto->owner)
- __MOD_DEC_USE_COUNT(proto->owner);
+ module_put(proto->owner);
}
if (!pi->port) {
diff --git a/drivers/block/swim_iop.c b/drivers/block/swim_iop.c
index 18e8548bfcdb..755fc9c3a81f 100644
--- a/drivers/block/swim_iop.c
+++ b/drivers/block/swim_iop.c
@@ -209,17 +209,16 @@ static void swimiop_init_request(struct swim_iop_req *req)
static int swimiop_send_request(struct swim_iop_req *req)
{
- unsigned long cpu_flags;
+ unsigned long flags;
int err;
/* It's doubtful an interrupt routine would try to send */
/* a SWIM request, but I'd rather play it safe here. */
- save_flags(cpu_flags);
- cli();
+ local_irq_save(flags);
if (current_req != NULL) {
- restore_flags(cpu_flags);
+ local_irq_restore(flags);
return -ENOMEM;
}
@@ -227,7 +226,7 @@ static int swimiop_send_request(struct swim_iop_req *req)
/* Interrupts should be back on for iop_send_message() */
- restore_flags(cpu_flags);
+ local_irq_restore(flags);
err = iop_send_message(SWIM_IOP, SWIM_CHAN, (void *) req,
sizeof(req->command), (__u8 *) &req->command[0],
@@ -423,14 +422,13 @@ static int grab_drive(struct floppy_state *fs, enum swim_state state,
{
unsigned long flags;
- save_flags(flags);
- cli();
+ local_irq_save(flags);
if (fs->state != idle) {
++fs->wanted;
while (fs->state != available) {
if (interruptible && signal_pending(current)) {
--fs->wanted;
- restore_flags(flags);
+ local_irq_restore(flags);
return -EINTR;
}
interruptible_sleep_on(&fs->wait);
@@ -438,7 +436,7 @@ static int grab_drive(struct floppy_state *fs, enum swim_state state,
--fs->wanted;
}
fs->state = state;
- restore_flags(flags);
+ local_irq_restore(flags);
return 0;
}
@@ -446,11 +444,10 @@ static void release_drive(struct floppy_state *fs)
{
unsigned long flags;
- save_flags(flags);
- cli();
+ local_irq_save(flags);
fs->state = idle;
start_request(fs);
- restore_flags(flags);
+ local_irq_restore(flags);
}
static void set_timeout(struct floppy_state *fs, int nticks,
@@ -458,7 +455,7 @@ static void set_timeout(struct floppy_state *fs, int nticks,
{
unsigned long flags;
- save_flags(flags); cli();
+ local_irq_save(flags);
if (fs->timeout_pending)
del_timer(&fs->timeout);
init_timer(&fs->timeout);
@@ -467,7 +464,7 @@ static void set_timeout(struct floppy_state *fs, int nticks,
fs->timeout.data = (unsigned long) fs;
add_timer(&fs->timeout);
fs->timeout_pending = 1;
- restore_flags(flags);
+ local_irq_restore(flags);
}
static void do_fd_request(request_queue_t * q)
diff --git a/drivers/block/z2ram.c b/drivers/block/z2ram.c
index 80096fad0c32..263772c3ae1a 100644
--- a/drivers/block/z2ram.c
+++ b/drivers/block/z2ram.c
@@ -73,8 +73,6 @@ static struct gendisk *z2ram_gendisk;
static void do_z2_request(request_queue_t *q)
{
- u_long start, len, addr, size;
-
while (!blk_queue_empty(q)) {
struct request *req = elv_next_request(q);
unsigned long start = req->sector << 9;
diff --git a/drivers/bluetooth/hci_usb.c b/drivers/bluetooth/hci_usb.c
index dcc257777929..487b53690035 100644
--- a/drivers/bluetooth/hci_usb.c
+++ b/drivers/bluetooth/hci_usb.c
@@ -763,7 +763,7 @@ int hci_usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
goto probe_error;
}
- dev_set_drvdata(&intf->dev, husb);
+ usb_set_intfdata(intf, husb);
return 0;
probe_error:
@@ -775,12 +775,12 @@ done:
static void hci_usb_disconnect(struct usb_interface *intf)
{
- struct hci_usb *husb = dev_get_drvdata(&intf->dev);
+ struct hci_usb *husb = usb_get_intfdata(intf);
struct hci_dev *hdev;
if (!husb)
return;
- dev_set_drvdata(&intf->dev, NULL);
+ usb_set_intfdata(intf, NULL);
hdev = &husb->hdev;
BT_DBG("%s", hdev->name);
diff --git a/drivers/char/amiserial.c b/drivers/char/amiserial.c
index 79ac0284783e..ed775912bac9 100644
--- a/drivers/char/amiserial.c
+++ b/drivers/char/amiserial.c
@@ -213,7 +213,7 @@ static void rs_stop(struct tty_struct *tty)
if (serial_paranoia_check(info, tty->device, "rs_stop"))
return;
- save_flags(flags); cli();
+ local_irq_save(flags);
if (info->IER & UART_IER_THRI) {
info->IER &= ~UART_IER_THRI;
/* disable Tx interrupt and remove any pending interrupts */
@@ -222,7 +222,7 @@ static void rs_stop(struct tty_struct *tty)
custom.intreq = IF_TBE;
mb();
}
- restore_flags(flags);
+ local_irq_restore(flags);
}
static void rs_start(struct tty_struct *tty)
@@ -233,7 +233,7 @@ static void rs_start(struct tty_struct *tty)
if (serial_paranoia_check(info, tty->device, "rs_start"))
return;
- save_flags(flags); cli();
+ local_irq_save(flags);
if (info->xmit.head != info->xmit.tail
&& info->xmit.buf
&& !(info->IER & UART_IER_THRI)) {
@@ -244,7 +244,7 @@ static void rs_start(struct tty_struct *tty)
custom.intreq = IF_SETCLR | IF_TBE;
mb();
}
- restore_flags(flags);
+ local_irq_restore(flags);
}
/*
@@ -601,7 +601,7 @@ static int startup(struct async_struct * info)
if (!page)
return -ENOMEM;
- save_flags(flags); cli();
+ local_irq_save(flags);
if (info->flags & ASYNC_INITIALIZED) {
free_page(page);
@@ -672,11 +672,11 @@ static int startup(struct async_struct * info)
change_speed(info, 0);
info->flags |= ASYNC_INITIALIZED;
- restore_flags(flags);
+ local_irq_restore(flags);
return 0;
errout:
- restore_flags(flags);
+ local_irq_restore(flags);
return retval;
}
@@ -698,7 +698,7 @@ static void shutdown(struct async_struct * info)
printk("Shutting down serial port %d ....\n", info->line);
#endif
- save_flags(flags); cli(); /* Disable interrupts */
+ local_irq_save(flags); /* Disable interrupts */
/*
* clear delta_msr_wait queue to avoid mem leaks: we may free the irq
@@ -734,7 +734,7 @@ static void shutdown(struct async_struct * info)
set_bit(TTY_IO_ERROR, &info->tty->flags);
info->flags &= ~ASYNC_INITIALIZED;
- restore_flags(flags);
+ local_irq_restore(flags);
}
@@ -862,7 +862,7 @@ static void change_speed(struct async_struct *info,
*/
if ((cflag & CREAD) == 0)
info->ignore_status_mask |= UART_LSR_DR;
- save_flags(flags); cli();
+ local_irq_save(flags);
{
short serper;
@@ -880,7 +880,7 @@ static void change_speed(struct async_struct *info,
}
info->LCR = cval; /* Save LCR */
- restore_flags(flags);
+ local_irq_restore(flags);
}
static void rs_put_char(struct tty_struct *tty, unsigned char ch)
@@ -894,17 +894,17 @@ static void rs_put_char(struct tty_struct *tty, unsigned char ch)
if (!tty || !info->xmit.buf)
return;
- save_flags(flags); cli();
+ local_irq_save(flags);
if (CIRC_SPACE(info->xmit.head,
info->xmit.tail,
SERIAL_XMIT_SIZE) == 0) {
- restore_flags(flags);
+ local_irq_restore(flags);
return;
}
info->xmit.buf[info->xmit.head++] = ch;
info->xmit.head &= SERIAL_XMIT_SIZE-1;
- restore_flags(flags);
+ local_irq_restore(flags);
}
static void rs_flush_chars(struct tty_struct *tty)
@@ -921,14 +921,14 @@ static void rs_flush_chars(struct tty_struct *tty)
|| !info->xmit.buf)
return;
- save_flags(flags); cli();
+ local_irq_save(flags);
info->IER |= UART_IER_THRI;
custom.intena = IF_SETCLR | IF_TBE;
mb();
/* set a pending Tx Interrupt, transmitter should restart now */
custom.intreq = IF_SETCLR | IF_TBE;
mb();
- restore_flags(flags);
+ local_irq_restore(flags);
}
static int rs_write(struct tty_struct * tty, int from_user,
@@ -944,7 +944,7 @@ static int rs_write(struct tty_struct * tty, int from_user,
if (!tty || !info->xmit.buf || !tmp_buf)
return 0;
- save_flags(flags);
+ local_save_flags(flags);
if (from_user) {
down(&tmp_buf_sem);
while (1) {
@@ -961,7 +961,7 @@ static int rs_write(struct tty_struct * tty, int from_user,
ret = -EFAULT;
break;
}
- cli();
+ local_irq_disable();
c1 = CIRC_SPACE_TO_END(info->xmit.head,
info->xmit.tail,
SERIAL_XMIT_SIZE);
@@ -970,14 +970,14 @@ static int rs_write(struct tty_struct * tty, int from_user,
memcpy(info->xmit.buf + info->xmit.head, tmp_buf, c);
info->xmit.head = ((info->xmit.head + c) &
(SERIAL_XMIT_SIZE-1));
- restore_flags(flags);
+ local_irq_restore(flags);
buf += c;
count -= c;
ret += c;
}
up(&tmp_buf_sem);
} else {
- cli();
+ local_irq_disable();
while (1) {
c = CIRC_SPACE_TO_END(info->xmit.head,
info->xmit.tail,
@@ -994,20 +994,20 @@ static int rs_write(struct tty_struct * tty, int from_user,
count -= c;
ret += c;
}
- restore_flags(flags);
+ local_irq_restore(flags);
}
if (info->xmit.head != info->xmit.tail
&& !tty->stopped
&& !tty->hw_stopped
&& !(info->IER & UART_IER_THRI)) {
info->IER |= UART_IER_THRI;
- cli();
+ local_irq_disable();
custom.intena = IF_SETCLR | IF_TBE;
mb();
/* set a pending Tx Interrupt, transmitter should restart now */
custom.intreq = IF_SETCLR | IF_TBE;
mb();
- restore_flags(flags);
+ local_irq_restore(flags);
}
return ret;
}
@@ -1037,9 +1037,9 @@ static void rs_flush_buffer(struct tty_struct *tty)
if (serial_paranoia_check(info, tty->device, "rs_flush_buffer"))
return;
- save_flags(flags); cli();
+ local_irq_save(flags);
info->xmit.head = info->xmit.tail = 0;
- restore_flags(flags);
+ local_irq_restore(flags);
wake_up_interruptible(&tty->write_wait);
if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
tty->ldisc.write_wakeup)
@@ -1063,8 +1063,7 @@ static void rs_send_xchar(struct tty_struct *tty, char ch)
/* Make sure transmit interrupts are on */
/* Check this ! */
- save_flags(flags);
- cli();
+ local_irq_save(flags);
if(!(custom.intenar & IF_TBE)) {
custom.intena = IF_SETCLR | IF_TBE;
mb();
@@ -1072,7 +1071,7 @@ static void rs_send_xchar(struct tty_struct *tty, char ch)
custom.intreq = IF_SETCLR | IF_TBE;
mb();
}
- restore_flags(flags);
+ local_irq_restore(flags);
info->IER |= UART_IER_THRI;
}
@@ -1106,9 +1105,9 @@ static void rs_throttle(struct tty_struct * tty)
if (tty->termios->c_cflag & CRTSCTS)
info->MCR &= ~SER_RTS;
- save_flags(flags); cli();
+ local_irq_save(flags);
rtsdtr_ctrl(info->MCR);
- restore_flags(flags);
+ local_irq_restore(flags);
}
static void rs_unthrottle(struct tty_struct * tty)
@@ -1133,9 +1132,9 @@ static void rs_unthrottle(struct tty_struct * tty)
}
if (tty->termios->c_cflag & CRTSCTS)
info->MCR |= SER_RTS;
- save_flags(flags); cli();
+ local_irq_save(flags);
rtsdtr_ctrl(info->MCR);
- restore_flags(flags);
+ local_irq_restore(flags);
}
/*
@@ -1256,10 +1255,10 @@ static int get_lsr_info(struct async_struct * info, unsigned int *value)
unsigned int result;
unsigned long flags;
- save_flags(flags); cli();
+ local_irq_save(flags);
status = custom.serdatr;
mb();
- restore_flags(flags);
+ local_irq_restore(flags);
result = ((status & SDR_TSRE) ? TIOCSER_TEMT : 0);
if (copy_to_user(value, &result, sizeof(int)))
return -EFAULT;
@@ -1274,9 +1273,9 @@ static int get_modem_info(struct async_struct * info, unsigned int *value)
unsigned long flags;
control = info->MCR;
- save_flags(flags); cli();
+ local_irq_save(flags);
status = ciab.pra;
- restore_flags(flags);
+ local_irq_restore(flags);
result = ((control & SER_RTS) ? TIOCM_RTS : 0)
| ((control & SER_DTR) ? TIOCM_DTR : 0)
| (!(status & SER_DCD) ? TIOCM_CAR : 0)
@@ -1317,9 +1316,9 @@ static int set_modem_info(struct async_struct * info, unsigned int cmd,
default:
return -EINVAL;
}
- save_flags(flags); cli();
+ local_irq_save(flags);
rtsdtr_ctrl(info->MCR);
- restore_flags(flags);
+ local_irq_restore(flags);
return 0;
}
@@ -1334,13 +1333,13 @@ static void rs_break(struct tty_struct *tty, int break_state)
if (serial_paranoia_check(info, tty->device, "rs_break"))
return;
- save_flags(flags); cli();
+ local_irq_save(flags);
if (break_state == -1)
custom.adkcon = AC_SETCLR | AC_UARTBRK;
else
custom.adkcon = AC_UARTBRK;
mb();
- restore_flags(flags);
+ local_irq_restore(flags);
}
@@ -1394,18 +1393,18 @@ static int rs_ioctl(struct tty_struct *tty, struct file * file,
* Caller should use TIOCGICOUNT to see which one it was
*/
case TIOCMIWAIT:
- save_flags(flags); cli();
+ local_irq_save(flags);
/* note the counters on entry */
cprev = info->state->icount;
- restore_flags(flags);
+ local_irq_restore(flags);
while (1) {
interruptible_sleep_on(&info->delta_msr_wait);
/* see if a signal did it */
if (signal_pending(current))
return -ERESTARTSYS;
- save_flags(flags); cli();
+ local_irq_save(flags);
cnow = info->state->icount; /* atomic copy */
- restore_flags(flags);
+ local_irq_restore(flags);
if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
cnow.dcd == cprev.dcd && cnow.cts == cprev.cts)
return -EIO; /* no change => error */
@@ -1426,9 +1425,9 @@ static int rs_ioctl(struct tty_struct *tty, struct file * file,
* RI where only 0->1 is counted.
*/
case TIOCGICOUNT:
- save_flags(flags); cli();
+ local_irq_save(flags);
cnow = info->state->icount;
- restore_flags(flags);
+ local_irq_restore(flags);
icount.cts = cnow.cts;
icount.dsr = cnow.dsr;
icount.rng = cnow.rng;
@@ -1473,9 +1472,9 @@ static void rs_set_termios(struct tty_struct *tty, struct termios *old_termios)
if ((old_termios->c_cflag & CBAUD) &&
!(cflag & CBAUD)) {
info->MCR &= ~(SER_DTR|SER_RTS);
- save_flags(flags); cli();
+ local_irq_save(flags);
rtsdtr_ctrl(info->MCR);
- restore_flags(flags);
+ local_irq_restore(flags);
}
/* Handle transition away from B0 status */
@@ -1486,9 +1485,9 @@ static void rs_set_termios(struct tty_struct *tty, struct termios *old_termios)
!test_bit(TTY_THROTTLED, &tty->flags)) {
info->MCR |= SER_RTS;
}
- save_flags(flags); cli();
+ local_irq_save(flags);
rtsdtr_ctrl(info->MCR);
- restore_flags(flags);
+ local_irq_restore(flags);
}
/* Handle turning off CRTSCTS */
@@ -1532,12 +1531,12 @@ static void rs_close(struct tty_struct *tty, struct file * filp)
state = info->state;
- save_flags(flags); cli();
+ local_irq_save(flags);
if (tty_hung_up_p(filp)) {
DBG_CNT("before DEC-hung");
MOD_DEC_USE_COUNT;
- restore_flags(flags);
+ local_irq_restore(flags);
return;
}
@@ -1564,7 +1563,7 @@ static void rs_close(struct tty_struct *tty, struct file * filp)
if (state->count) {
DBG_CNT("before DEC-2");
MOD_DEC_USE_COUNT;
- restore_flags(flags);
+ local_irq_restore(flags);
return;
}
info->flags |= ASYNC_CLOSING;
@@ -1624,7 +1623,7 @@ static void rs_close(struct tty_struct *tty, struct file * filp)
ASYNC_CLOSING);
wake_up_interruptible(&info->close_wait);
MOD_DEC_USE_COUNT;
- restore_flags(flags);
+ local_irq_restore(flags);
}
/*
@@ -1797,19 +1796,19 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp,
printk("block_til_ready before block: ttys%d, count = %d\n",
state->line, state->count);
#endif
- save_flags(flags); cli();
+ local_irq_save(flags);
if (!tty_hung_up_p(filp)) {
extra_count = 1;
state->count--;
}
- restore_flags(flags);
+ local_irq_restore(flags);
info->blocked_open++;
while (1) {
- save_flags(flags); cli();
+ local_irq_save(flags);
if (!(info->flags & ASYNC_CALLOUT_ACTIVE) &&
(tty->termios->c_cflag & CBAUD))
rtsdtr_ctrl(SER_DTR|SER_RTS);
- restore_flags(flags);
+ local_irq_restore(flags);
set_current_state(TASK_INTERRUPTIBLE);
if (tty_hung_up_p(filp) ||
!(info->flags & ASYNC_INITIALIZED)) {
@@ -2009,10 +2008,10 @@ static inline int line_info(char *buf, struct serial_state *state)
info->quot = 0;
info->tty = 0;
}
- save_flags(flags); cli();
+ local_irq_save(flags);
status = ciab.pra;
control = info ? info->MCR : status;
- restore_flags(flags);
+ local_irq_restore(flags);
stat_buf[0] = 0;
stat_buf[1] = 0;
@@ -2207,8 +2206,7 @@ static int __init rs_init(void)
state->baud_base = amiga_colorclock;
state->xmit_fifo_size = 1;
- save_flags (flags);
- cli();
+ local_irq_save(flags);
/* set ISRs, and then disable the rx interrupts */
request_irq(IRQ_AMIGA_TBE, ser_tx_int, 0, "serial TX", state);
@@ -2222,7 +2220,7 @@ static int __init rs_init(void)
custom.intreq = IF_RBF | IF_TBE;
mb();
- restore_flags (flags);
+ local_irq_restore(flags);
/*
* set the appropriate directions for the modem control flags,
diff --git a/drivers/char/busmouse.c b/drivers/char/busmouse.c
index 29362e24aa4c..85baa0cdf51b 100644
--- a/drivers/char/busmouse.c
+++ b/drivers/char/busmouse.c
@@ -175,8 +175,7 @@ static int busmouse_release(struct inode *inode, struct file *file)
if (--mse->active == 0) {
if (mse->ops->release)
ret = mse->ops->release(inode, file);
- if (mse->ops->owner)
- __MOD_DEC_USE_COUNT(mse->ops->owner);
+ module_put(mse->ops->owner);
mse->ready = 0;
}
unlock_kernel();
@@ -207,8 +206,8 @@ static int busmouse_open(struct inode *inode, struct file *file)
ret = 0;
if (mse->ops->open) {
ret = mse->ops->open(inode, file);
- if (ret && mse->ops->owner)
- __MOD_DEC_USE_COUNT(mse->ops->owner);
+ if (ret)
+ module_put(mse->ops->owner);
}
if (ret)
diff --git a/drivers/char/mem.c b/drivers/char/mem.c
index 3df145966b6d..e7ed88e4ac02 100644
--- a/drivers/char/mem.c
+++ b/drivers/char/mem.c
@@ -27,9 +27,6 @@
#include <asm/io.h>
#include <asm/pgalloc.h>
-#ifdef CONFIG_I2C
-extern int i2c_init_all(void);
-#endif
#ifdef CONFIG_FB
extern void fbmem_init(void);
#endif
@@ -702,9 +699,6 @@ int __init chr_dev_init(void)
printk("unable to get major %d for memory devs\n", MEM_MAJOR);
memory_devfs_register();
rand_initialize();
-#ifdef CONFIG_I2C
- i2c_init_all();
-#endif
#if defined (CONFIG_FB)
fbmem_init();
#endif
diff --git a/drivers/char/ser_a2232.c b/drivers/char/ser_a2232.c
index 8e373bcbe71b..b8a01d45027d 100644
--- a/drivers/char/ser_a2232.c
+++ b/drivers/char/ser_a2232.c
@@ -201,10 +201,9 @@ static void a2232_disable_tx_interrupts(void *ptr)
stat->OutDisable = -1;
/* Does this here really have to be? */
- save_flags(flags);
- cli();
+ local_irq_save(flags);
port->gs.flags &= ~GS_TX_INTEN;
- restore_flags(flags);
+ local_irq_restore(flags);
}
static void a2232_enable_tx_interrupts(void *ptr)
@@ -218,10 +217,9 @@ static void a2232_enable_tx_interrupts(void *ptr)
stat->OutDisable = 0;
/* Does this here really have to be? */
- save_flags(flags);
- cli();
+ local_irq_save(flags);
port->gs.flags |= GS_TX_INTEN;
- restore_flags(flags);
+ local_irq_restore(flags);
}
static void a2232_disable_rx_interrupts(void *ptr)
@@ -252,8 +250,7 @@ static void a2232_shutdown_port(void *ptr)
port = ptr;
stat = a2232stat(port->which_a2232, port->which_port_on_a2232);
- save_flags(flags);
- cli();
+ local_irq_save(flags);
port->gs.flags &= ~GS_ACTIVE;
@@ -266,7 +263,7 @@ static void a2232_shutdown_port(void *ptr)
stat->Setup = -1;
}
- restore_flags(flags);
+ local_irq_restore(flags);
/* After analyzing control flow, I think a2232_shutdown_port
is actually the last call from the system when at application
@@ -300,15 +297,14 @@ static int a2232_set_real_termios(void *ptr)
baud = port->gs.baud;
if (baud == 0) {
/* speed == 0 -> drop DTR, do nothing else */
- save_flags(flags);
- cli();
+ local_irq_save(flags);
// Clear DTR (and RTS... mhhh).
status->Command = ( (status->Command & ~A2232CMD_CMask) |
A2232CMD_Close );
status->OutFlush = -1;
status->Setup = -1;
- restore_flags(flags);
+ local_irq_restore(flags);
return 0;
}
@@ -387,8 +383,7 @@ static int a2232_set_real_termios(void *ptr)
/* Now we have all parameters and can go to set them: */
- save_flags(flags);
- cli();
+ local_irq_save(flags);
status->Param = a2232_param | A2232PARAM_RcvBaud;
status->Command = a2232_cmd | A2232CMD_Open | A2232CMD_Enable;
@@ -396,7 +391,7 @@ static int a2232_set_real_termios(void *ptr)
status->OutDisable = 0;
status->Setup = -1;
- restore_flags(flags);
+ local_irq_restore(flags);
return 0;
}
diff --git a/drivers/char/serial167.c b/drivers/char/serial167.c
index e6d33dc1e8ab..65a8e8438c0a 100644
--- a/drivers/char/serial167.c
+++ b/drivers/char/serial167.c
@@ -274,18 +274,18 @@ serial_paranoia_check(struct cyclades_port *info, kdev_t device,
void
SP(char *data){
unsigned long flags;
- save_flags(flags); cli();
+ local_irq_save(flags);
console_print(data);
- restore_flags(flags);
+ local_irq_restore(flags);
}
char scrn[2];
void
CP(char data){
unsigned long flags;
- save_flags(flags); cli();
+ local_irq_save(flags);
scrn[0] = data;
console_print(scrn);
- restore_flags(flags);
+ local_irq_restore(flags);
}/* CP */
void CP1(int data) { (data<10)? CP(data+'0'): CP(data+'A'-10); }/* CP1 */
@@ -305,7 +305,7 @@ write_cy_cmd(volatile u_char *base_addr, u_char cmd)
unsigned long flags;
volatile int i;
- save_flags(flags); cli();
+ local_irq_save(flags);
/* Check to see that the previous command has completed */
for(i = 0 ; i < 100 ; i++){
if (base_addr[CyCCR] == 0){
@@ -316,13 +316,13 @@ write_cy_cmd(volatile u_char *base_addr, u_char cmd)
/* if the CCR never cleared, the previous command
didn't finish within the "reasonable time" */
if ( i == 10 ) {
- restore_flags(flags);
+ local_irq_restore(flags);
return (-1);
}
/* Issue the new command */
base_addr[CyCCR] = cmd;
- restore_flags(flags);
+ local_irq_restore(flags);
return(0);
} /* write_cy_cmd */
@@ -347,10 +347,10 @@ cy_stop(struct tty_struct *tty)
channel = info->line;
- save_flags(flags); cli();
+ local_irq_save(flags);
base_addr[CyCAR] = (u_char)(channel); /* index channel */
base_addr[CyIER] &= ~(CyTxMpty|CyTxRdy);
- restore_flags(flags);
+ local_irq_restore(flags);
return;
} /* cy_stop */
@@ -372,10 +372,10 @@ cy_start(struct tty_struct *tty)
channel = info->line;
- save_flags(flags); cli();
+ local_irq_save(flags);
base_addr[CyCAR] = (u_char)(channel);
base_addr[CyIER] |= CyTxMpty;
- restore_flags(flags);
+ local_irq_restore(flags);
return;
} /* cy_start */
@@ -816,7 +816,7 @@ startup(struct cyclades_port * info)
printk("startup channel %d\n", channel);
#endif
- save_flags(flags); cli();
+ local_irq_save(flags);
base_addr[CyCAR] = (u_char)channel;
write_cy_cmd(base_addr,CyENB_RCVR|CyENB_XMTR);
@@ -838,7 +838,7 @@ startup(struct cyclades_port * info)
}
info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
- restore_flags(flags);
+ local_irq_restore(flags);
#ifdef SERIAL_DEBUG_OPEN
printk(" done\n");
@@ -854,10 +854,10 @@ start_xmit( struct cyclades_port *info )
int channel;
channel = info->line;
- save_flags(flags); cli();
+ local_irq_save(flags);
base_addr[CyCAR] = channel;
base_addr[CyIER] |= CyTxMpty;
- restore_flags(flags);
+ local_irq_restore(flags);
} /* start_xmit */
/*
@@ -888,7 +888,7 @@ shutdown(struct cyclades_port * info)
Other choices are to delay some fixed interval
or schedule some later processing.
*/
- save_flags(flags); cli();
+ local_irq_save(flags);
if (info->xmit_buf){
free_page((unsigned long) info->xmit_buf);
info->xmit_buf = 0;
@@ -912,7 +912,7 @@ shutdown(struct cyclades_port * info)
set_bit(TTY_IO_ERROR, &info->tty->flags);
}
info->flags &= ~ASYNC_INITIALIZED;
- restore_flags(flags);
+ local_irq_restore(flags);
#ifdef SERIAL_DEBUG_OPEN
printk(" done\n");
@@ -1079,7 +1079,7 @@ config_setup(struct cyclades_port * info)
channel = info->line;
- save_flags(flags); cli();
+ local_irq_save(flags);
base_addr[CyCAR] = (u_char)channel;
/* CyCMR set once only in mvme167_init_serial() */
@@ -1159,7 +1159,7 @@ config_setup(struct cyclades_port * info)
clear_bit(TTY_IO_ERROR, &info->tty->flags);
}
- restore_flags(flags);
+ local_irq_restore(flags);
} /* config_setup */
@@ -1180,16 +1180,16 @@ cy_put_char(struct tty_struct *tty, unsigned char ch)
if (!tty || !info->xmit_buf)
return;
- save_flags(flags); cli();
+ local_irq_save(flags);
if (info->xmit_cnt >= PAGE_SIZE - 1) {
- restore_flags(flags);
+ local_irq_restore(flags);
return;
}
info->xmit_buf[info->xmit_head++] = ch;
info->xmit_head &= PAGE_SIZE - 1;
info->xmit_cnt++;
- restore_flags(flags);
+ local_irq_restore(flags);
} /* cy_put_char */
@@ -1214,10 +1214,10 @@ cy_flush_chars(struct tty_struct *tty)
channel = info->line;
- save_flags(flags); cli();
+ local_irq_save(flags);
base_addr[CyCAR] = channel;
base_addr[CyIER] |= CyTxMpty;
- restore_flags(flags);
+ local_irq_restore(flags);
} /* cy_flush_chars */
@@ -1262,13 +1262,13 @@ cy_write(struct tty_struct * tty, int from_user,
break;
}
- save_flags(flags); cli();
+ local_irq_save(flags);
c = MIN(c, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
SERIAL_XMIT_SIZE - info->xmit_head));
memcpy(info->xmit_buf + info->xmit_head, tmp_buf, c);
info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE-1);
info->xmit_cnt += c;
- restore_flags(flags);
+ local_irq_restore(flags);
buf += c;
count -= c;
@@ -1277,18 +1277,18 @@ cy_write(struct tty_struct * tty, int from_user,
up(&tmp_buf_sem);
} else {
while (1) {
- save_flags(flags); cli();
+ local_irq_save(flags);
c = MIN(count, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
SERIAL_XMIT_SIZE - info->xmit_head));
if (c <= 0) {
- restore_flags(flags);
+ local_irq_restore(flags);
break;
}
memcpy(info->xmit_buf + info->xmit_head, buf, c);
info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE-1);
info->xmit_cnt += c;
- restore_flags(flags);
+ local_irq_restore(flags);
buf += c;
count -= c;
@@ -1352,9 +1352,9 @@ cy_flush_buffer(struct tty_struct *tty)
if (serial_paranoia_check(info, tty->device, "cy_flush_buffer"))
return;
- save_flags(flags); cli();
+ local_irq_save(flags);
info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
- restore_flags(flags);
+ local_irq_restore(flags);
wake_up_interruptible(&tty->write_wait);
if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP))
&& tty->ldisc.write_wakeup)
@@ -1393,10 +1393,10 @@ cy_throttle(struct tty_struct * tty)
channel = info->line;
- save_flags(flags); cli();
+ local_irq_save(flags);
base_addr[CyCAR] = (u_char)channel;
base_addr[CyMSVR1] = 0;
- restore_flags(flags);
+ local_irq_restore(flags);
return;
} /* cy_throttle */
@@ -1429,10 +1429,10 @@ cy_unthrottle(struct tty_struct * tty)
channel = info->line;
- save_flags(flags); cli();
+ local_irq_save(flags);
base_addr[CyCAR] = (u_char)channel;
base_addr[CyMSVR1] = CyRTS;
- restore_flags(flags);
+ local_irq_restore(flags);
return;
} /* cy_unthrottle */
@@ -1514,10 +1514,10 @@ get_modem_info(struct cyclades_port * info, unsigned int *value)
channel = info->line;
- save_flags(flags); cli();
+ local_irq_save(flags);
base_addr[CyCAR] = (u_char)channel;
status = base_addr[CyMSVR1] | base_addr[CyMSVR2];
- restore_flags(flags);
+ local_irq_restore(flags);
result = ((status & CyRTS) ? TIOCM_RTS : 0)
| ((status & CyDTR) ? TIOCM_DTR : 0)
@@ -1543,13 +1543,13 @@ set_modem_info(struct cyclades_port * info, unsigned int cmd,
switch (cmd) {
case TIOCMBIS:
if (arg & TIOCM_RTS){
- save_flags(flags); cli();
+ local_irq_save(flags);
base_addr[CyCAR] = (u_char)channel;
base_addr[CyMSVR1] = CyRTS;
- restore_flags(flags);
+ local_irq_restore(flags);
}
if (arg & TIOCM_DTR){
- save_flags(flags); cli();
+ local_irq_save(flags);
base_addr[CyCAR] = (u_char)channel;
/* CP('S');CP('2'); */
base_addr[CyMSVR2] = CyDTR;
@@ -1557,18 +1557,18 @@ set_modem_info(struct cyclades_port * info, unsigned int cmd,
printk("cyc: %d: raising DTR\n", __LINE__);
printk(" status: 0x%x, 0x%x\n", base_addr[CyMSVR1], base_addr[CyMSVR2]);
#endif
- restore_flags(flags);
+ local_irq_restore(flags);
}
break;
case TIOCMBIC:
if (arg & TIOCM_RTS){
- save_flags(flags); cli();
+ local_irq_save(flags);
base_addr[CyCAR] = (u_char)channel;
base_addr[CyMSVR1] = 0;
- restore_flags(flags);
+ local_irq_restore(flags);
}
if (arg & TIOCM_DTR){
- save_flags(flags); cli();
+ local_irq_save(flags);
base_addr[CyCAR] = (u_char)channel;
/* CP('C');CP('2'); */
base_addr[CyMSVR2] = 0;
@@ -1576,23 +1576,23 @@ set_modem_info(struct cyclades_port * info, unsigned int cmd,
printk("cyc: %d: dropping DTR\n", __LINE__);
printk(" status: 0x%x, 0x%x\n", base_addr[CyMSVR1], base_addr[CyMSVR2]);
#endif
- restore_flags(flags);
+ local_irq_restore(flags);
}
break;
case TIOCMSET:
if (arg & TIOCM_RTS){
- save_flags(flags); cli();
+ local_irq_save(flags);
base_addr[CyCAR] = (u_char)channel;
base_addr[CyMSVR1] = CyRTS;
- restore_flags(flags);
+ local_irq_restore(flags);
}else{
- save_flags(flags); cli();
+ local_irq_save(flags);
base_addr[CyCAR] = (u_char)channel;
base_addr[CyMSVR1] = 0;
- restore_flags(flags);
+ local_irq_restore(flags);
}
if (arg & TIOCM_DTR){
- save_flags(flags); cli();
+ local_irq_save(flags);
base_addr[CyCAR] = (u_char)channel;
/* CP('S');CP('3'); */
base_addr[CyMSVR2] = CyDTR;
@@ -1600,9 +1600,9 @@ set_modem_info(struct cyclades_port * info, unsigned int cmd,
printk("cyc: %d: raising DTR\n", __LINE__);
printk(" status: 0x%x, 0x%x\n", base_addr[CyMSVR1], base_addr[CyMSVR2]);
#endif
- restore_flags(flags);
+ local_irq_restore(flags);
}else{
- save_flags(flags); cli();
+ local_irq_save(flags);
base_addr[CyCAR] = (u_char)channel;
/* CP('C');CP('3'); */
base_addr[CyMSVR2] = 0;
@@ -1610,7 +1610,7 @@ set_modem_info(struct cyclades_port * info, unsigned int cmd,
printk("cyc: %d: dropping DTR\n", __LINE__);
printk(" status: 0x%x, 0x%x\n", base_addr[CyMSVR1], base_addr[CyMSVR2]);
#endif
- restore_flags(flags);
+ local_irq_restore(flags);
}
break;
default:
@@ -2060,7 +2060,7 @@ block_til_ready(struct tty_struct *tty, struct file * filp,
channel = info->line;
while (1) {
- save_flags(flags); cli();
+ local_irq_save(flags);
if (!(info->flags & ASYNC_CALLOUT_ACTIVE)){
base_addr[CyCAR] = (u_char)channel;
base_addr[CyMSVR1] = CyRTS;
@@ -2071,7 +2071,7 @@ block_til_ready(struct tty_struct *tty, struct file * filp,
printk(" status: 0x%x, 0x%x\n", base_addr[CyMSVR1], base_addr[CyMSVR2]);
#endif
}
- restore_flags(flags);
+ local_irq_restore(flags);
set_current_state(TASK_INTERRUPTIBLE);
if (tty_hung_up_p(filp)
|| !(info->flags & ASYNC_INITIALIZED) ){
@@ -2082,17 +2082,17 @@ block_til_ready(struct tty_struct *tty, struct file * filp,
}
break;
}
- save_flags(flags); cli();
+ local_irq_save(flags);
base_addr[CyCAR] = (u_char)channel;
/* CP('L');CP1(1 && C_CLOCAL(tty)); CP1(1 && (base_addr[CyMSVR1] & CyDCD) ); */
if (!(info->flags & ASYNC_CALLOUT_ACTIVE)
&& !(info->flags & ASYNC_CLOSING)
&& (C_CLOCAL(tty)
|| (base_addr[CyMSVR1] & CyDCD))) {
- restore_flags(flags);
+ local_irq_restore(flags);
break;
}
- restore_flags(flags);
+ local_irq_restore(flags);
if (signal_pending(current)) {
retval = -ERESTARTSYS;
break;
@@ -2238,7 +2238,7 @@ mvme167_serial_console_setup(int cflag)
u_char rcor, rbpr, badspeed = 0;
unsigned long flags;
- save_flags(flags); cli();
+ local_irq_save(flags);
/*
* First probe channel zero of the chip, to see what speed has
@@ -2263,7 +2263,7 @@ mvme167_serial_console_setup(int cflag)
my_udelay(20000L); /* Allow time for any active o/p to complete */
if(base_addr[CyCCR] != 0x00){
- restore_flags(flags);
+ local_irq_restore(flags);
/* printk(" chip is never idle (CCR != 0)\n"); */
return;
}
@@ -2272,7 +2272,7 @@ mvme167_serial_console_setup(int cflag)
my_udelay(1000L);
if(base_addr[CyGFRCR] == 0x00){
- restore_flags(flags);
+ local_irq_restore(flags);
/* printk(" chip is not responding (GFRCR stayed 0)\n"); */
return;
}
@@ -2331,7 +2331,7 @@ mvme167_serial_console_setup(int cflag)
base_addr[CyIER] = CyRxData;
write_cy_cmd(base_addr,CyENB_RCVR|CyENB_XMTR);
- restore_flags(flags);
+ local_irq_restore(flags);
my_udelay(20000L); /* Let it all settle down */
@@ -2606,7 +2606,7 @@ show_status(int line_num)
info->session, info->pgrp, (long)info->open_wait);
- save_flags(flags); cli();
+ local_irq_save(flags);
/* Global Registers */
@@ -2664,7 +2664,7 @@ show_status(int line_num)
printk(" CyTBPR %x\n", base_addr[CyTBPR]);
printk(" CyTCOR %x\n", base_addr[CyTCOR]);
- restore_flags(flags);
+ local_irq_restore(flags);
} /* show_status */
#endif
@@ -2764,7 +2764,7 @@ void serial167_console_write(struct console *co, const char *str, unsigned count
u_char do_lf = 0;
int i = 0;
- save_flags(flags); cli();
+ local_irq_save(flags);
/* Ensure transmitter is enabled! */
@@ -2811,7 +2811,7 @@ void serial167_console_write(struct console *co, const char *str, unsigned count
base_addr[CyIER] = ier;
- restore_flags(flags);
+ local_irq_restore(flags);
}
static kdev_t serial167_console_device(struct console *c)
@@ -2855,7 +2855,7 @@ void putDebugChar (int c)
u_char ier;
int port;
- save_flags(flags); cli();
+ local_irq_save(flags);
/* Ensure transmitter is enabled! */
@@ -2885,7 +2885,7 @@ void putDebugChar (int c)
base_addr[CyIER] = ier;
- restore_flags(flags);
+ local_irq_restore(flags);
}
int getDebugChar()
@@ -2907,7 +2907,7 @@ int getDebugChar()
}
/* OK, nothing in queue, wait in poll loop */
- save_flags(flags); cli();
+ local_irq_save(flags);
/* Ensure receiver is enabled! */
@@ -2953,7 +2953,7 @@ int getDebugChar()
base_addr[CyIER] = ier;
- restore_flags(flags);
+ local_irq_restore(flags);
return (c);
}
@@ -2979,7 +2979,7 @@ debug_setup()
cflag = B19200;
- save_flags(flags); cli();
+ local_irq_save(flags);
for (i = 0; i < 4; i++)
{
@@ -3034,7 +3034,7 @@ debug_setup()
base_addr[CyIER] = CyRxData;
- restore_flags(flags);
+ local_irq_restore(flags);
} /* debug_setup */
diff --git a/drivers/char/sysrq.c b/drivers/char/sysrq.c
index 90f41e8d6cf0..1e08dc71a1ae 100644
--- a/drivers/char/sysrq.c
+++ b/drivers/char/sysrq.c
@@ -36,10 +36,6 @@
#include <asm/ptrace.h>
-#ifdef CONFIG_VOYAGER
-#include <asm/voyager.h>
-#endif
-
extern void reset_vc(unsigned int);
extern struct list_head super_blocks;
@@ -324,14 +320,6 @@ static struct sysrq_key_op sysrq_term_op = {
.action_msg = "Terminate All Tasks",
};
-#ifdef CONFIG_VOYAGER
-static struct sysrq_key_op sysrq_voyager_dump_op = {
- .handler = voyager_dump,
- .help_msg = "voyager",
- .action_msg = "Dump Voyager Status\n",
-};
-#endif
-
static void sysrq_handle_kill(int key, struct pt_regs *pt_regs,
struct tty_struct *tty)
{
@@ -365,11 +353,7 @@ static struct sysrq_key_op *sysrq_key_table[SYSRQ_KEY_TABLE_LENGTH] = {
it is handled specially on the sparc
and will never arrive */
/* b */ &sysrq_reboot_op,
-#ifdef CONFIG_VOYAGER
-/* c */ &sysrq_voyager_dump_op,
-#else
-/* c */ NULL,
-#endif
+/* c */ NULL,
/* d */ NULL,
/* e */ &sysrq_term_op,
/* f */ NULL,
@@ -397,7 +381,7 @@ static struct sysrq_key_op *sysrq_key_table[SYSRQ_KEY_TABLE_LENGTH] = {
/* s */ &sysrq_sync_op,
/* t */ &sysrq_showstate_op,
/* u */ &sysrq_mountro_op,
-/* v */ NULL,
+/* v */ NULL, /* May be assigned at init time by SMP VOYAGER */
/* w */ NULL,
/* x */ NULL,
/* y */ NULL,
diff --git a/drivers/char/vme_scc.c b/drivers/char/vme_scc.c
index 5b0351cc11cf..4cadd82064be 100644
--- a/drivers/char/vme_scc.c
+++ b/drivers/char/vme_scc.c
@@ -624,11 +624,10 @@ static void scc_disable_tx_interrupts(void *ptr)
unsigned long flags;
SCC_ACCESS_INIT(port);
- save_flags(flags);
- cli();
+ local_irq_save(flags);
SCCmod(INT_AND_DMA_REG, ~IDR_TX_INT_ENAB, 0);
port->gs.flags &= ~GS_TX_INTEN;
- restore_flags(flags);
+ local_irq_restore(flags);
}
@@ -638,12 +637,11 @@ static void scc_enable_tx_interrupts(void *ptr)
unsigned long flags;
SCC_ACCESS_INIT(port);
- save_flags(flags);
- cli();
+ local_irq_save(flags);
SCCmod(INT_AND_DMA_REG, 0xff, IDR_TX_INT_ENAB);
/* restart the transmitter */
scc_tx_int (0, port, 0);
- restore_flags(flags);
+ local_irq_restore(flags);
}
@@ -653,11 +651,10 @@ static void scc_disable_rx_interrupts(void *ptr)
unsigned long flags;
SCC_ACCESS_INIT(port);
- save_flags(flags);
- cli();
+ local_irq_save(flags);
SCCmod(INT_AND_DMA_REG,
~(IDR_RX_INT_MASK|IDR_PARERR_AS_SPCOND|IDR_EXTSTAT_INT_ENAB), 0);
- restore_flags(flags);
+ local_irq_restore(flags);
}
@@ -667,11 +664,10 @@ static void scc_enable_rx_interrupts(void *ptr)
unsigned long flags;
SCC_ACCESS_INIT(port);
- save_flags(flags);
- cli();
+ local_irq_save(flags);
SCCmod(INT_AND_DMA_REG, 0xff,
IDR_EXTSTAT_INT_ENAB|IDR_PARERR_AS_SPCOND|IDR_RX_INT_ALL);
- restore_flags(flags);
+ local_irq_restore(flags);
}
@@ -717,10 +713,9 @@ static int scc_set_real_termios (void *ptr)
if (baud == 0) {
/* speed == 0 -> drop DTR */
- save_flags(flags);
- cli();
+ local_irq_save(flags);
SCCmod(TX_CTRL_REG, ~TCR_DTR, 0);
- restore_flags(flags);
+ local_irq_restore(flags);
return 0;
}
else if ((MACH_IS_MVME16x && (baud < 50 || baud > 38400)) ||
@@ -748,8 +743,7 @@ static int scc_set_real_termios (void *ptr)
brgval = (BVME_SCC_RTxC + baud/2) / (16 * 2 * baud) - 2;
#endif
/* Now we have all parameters and can go to set them: */
- save_flags(flags);
- cli();
+ local_irq_save(flags);
/* receiver's character size and auto-enables */
SCCmod(RX_CTRL_REG, ~(RCR_CHSIZE_MASK|RCR_AUTO_ENAB_MODE),
@@ -773,7 +767,7 @@ static int scc_set_real_termios (void *ptr)
/* BRG enable, and clock source never changes */
SCCmod(DPLL_CTRL_REG, 0xff, DCR_BRG_ENAB);
- restore_flags(flags);
+ local_irq_restore(flags);
return 0;
}
@@ -823,13 +817,12 @@ static void scc_setsignals(struct scc_port *port, int dtr, int rts)
unsigned char t;
SCC_ACCESS_INIT(port);
- save_flags(flags);
- cli();
+ local_irq_save(flags);
t = SCCread(TX_CTRL_REG);
if (dtr >= 0) t = dtr? (t | TCR_DTR): (t & ~TCR_DTR);
if (rts >= 0) t = rts? (t | TCR_RTS): (t & ~TCR_RTS);
SCCwrite(TX_CTRL_REG, t);
- restore_flags(flags);
+ local_irq_restore(flags);
}
@@ -914,8 +907,7 @@ static int scc_open (struct tty_struct * tty, struct file * filp)
};
#endif
if (!(port->gs.flags & ASYNC_INITIALIZED)) {
- save_flags(flags);
- cli();
+ local_irq_save(flags);
#if defined(CONFIG_MVME147_SCC) || defined(CONFIG_MVME162_SCC)
if (MACH_IS_MVME147 || MACH_IS_MVME16x) {
for (i=0; i<sizeof(mvme_init_tab)/sizeof(*mvme_init_tab); ++i)
@@ -934,7 +926,7 @@ static int scc_open (struct tty_struct * tty, struct file * filp)
port->c_dcd = 0; /* Prevent initial 1->0 interrupt */
scc_setsignals (port, 1,1);
- restore_flags(flags);
+ local_irq_restore(flags);
}
tty->driver_data = port;
@@ -982,10 +974,9 @@ static void scc_throttle (struct tty_struct * tty)
SCC_ACCESS_INIT(port);
if (tty->termios->c_cflag & CRTSCTS) {
- save_flags(flags);
- cli();
+ local_irq_save(flags);
SCCmod(TX_CTRL_REG, ~TCR_RTS, 0);
- restore_flags(flags);
+ local_irq_restore(flags);
}
if (I_IXOFF(tty))
scc_send_xchar(tty, STOP_CHAR(tty));
@@ -999,10 +990,9 @@ static void scc_unthrottle (struct tty_struct * tty)
SCC_ACCESS_INIT(port);
if (tty->termios->c_cflag & CRTSCTS) {
- save_flags(flags);
- cli();
+ local_irq_save(flags);
SCCmod(TX_CTRL_REG, 0xff, TCR_RTS);
- restore_flags(flags);
+ local_irq_restore(flags);
}
if (I_IXOFF(tty))
scc_send_xchar(tty, START_CHAR(tty));
@@ -1022,11 +1012,10 @@ static void scc_break_ctl(struct tty_struct *tty, int break_state)
unsigned long flags;
SCC_ACCESS_INIT(port);
- save_flags(flags);
- cli();
+ local_irq_save(flags);
SCCmod(TX_CTRL_REG, ~TCR_SEND_BREAK,
break_state ? TCR_SEND_BREAK : 0);
- restore_flags(flags);
+ local_irq_restore(flags);
}
@@ -1069,8 +1058,7 @@ static void scc_console_write (struct console *co, const char *str, unsigned cou
{
unsigned long flags;
- save_flags(flags);
- cli();
+ local_irq_save(flags);
while (count--)
{
@@ -1078,7 +1066,7 @@ static void scc_console_write (struct console *co, const char *str, unsigned cou
scc_ch_write ('\r');
scc_ch_write (*str++);
}
- restore_flags(flags);
+ local_irq_restore(flags);
}
static kdev_t scc_console_device(struct console *c)
diff --git a/drivers/hotplug/pci_hotplug_core.c b/drivers/hotplug/pci_hotplug_core.c
index b03104c8edd1..5e4c1748b7d1 100644
--- a/drivers/hotplug/pci_hotplug_core.c
+++ b/drivers/hotplug/pci_hotplug_core.c
@@ -561,19 +561,19 @@ static void fs_remove_file (struct dentry *dentry)
up(&parent->d_inode->i_sem);
}
+/* yuck, WFT is this? */
#define GET_STATUS(name,type) \
static int get_##name (struct hotplug_slot *slot, type *value) \
{ \
struct hotplug_slot_ops *ops = slot->ops; \
int retval = 0; \
- if (ops->owner) \
- __MOD_INC_USE_COUNT(ops->owner); \
- if (ops->get_##name) \
- retval = ops->get_##name (slot, value); \
- else \
- *value = slot->info->name; \
- if (ops->owner) \
- __MOD_DEC_USE_COUNT(ops->owner); \
+ if (try_module_get(ops->owner)) { \
+ if (ops->get_##name) \
+ retval = ops->get_##name (slot, value); \
+ else \
+ *value = slot->info->name; \
+ module_put(ops->owner); \
+ } \
return retval; \
}
@@ -665,21 +665,19 @@ static ssize_t power_write_file (struct file *file, const char *ubuff, size_t co
case 0:
if (!slot->ops->disable_slot)
break;
- if (slot->ops->owner)
- __MOD_INC_USE_COUNT(slot->ops->owner);
- retval = slot->ops->disable_slot(slot);
- if (slot->ops->owner)
- __MOD_DEC_USE_COUNT(slot->ops->owner);
+ if (try_module_get(slot->ops->owner)) {
+ retval = slot->ops->disable_slot(slot);
+ module_put(slot->ops->owner);
+ }
break;
case 1:
if (!slot->ops->enable_slot)
break;
- if (slot->ops->owner)
- __MOD_INC_USE_COUNT(slot->ops->owner);
- retval = slot->ops->enable_slot(slot);
- if (slot->ops->owner)
- __MOD_DEC_USE_COUNT(slot->ops->owner);
+ if (try_module_get(slot->ops->owner)) {
+ retval = slot->ops->enable_slot(slot);
+ module_put(slot->ops->owner);
+ }
break;
default:
@@ -773,11 +771,10 @@ static ssize_t attention_write_file (struct file *file, const char *ubuff, size_
dbg (" - attention = %d\n", attention);
if (slot->ops->set_attention_status) {
- if (slot->ops->owner)
- __MOD_INC_USE_COUNT(slot->ops->owner);
- retval = slot->ops->set_attention_status(slot, attention);
- if (slot->ops->owner)
- __MOD_DEC_USE_COUNT(slot->ops->owner);
+ if (try_module_get(slot->ops->owner)) {
+ retval = slot->ops->set_attention_status(slot, attention);
+ module_put(slot->ops->owner);
+ }
}
exit:
@@ -1011,11 +1008,10 @@ static ssize_t test_write_file (struct file *file, const char *ubuff, size_t cou
dbg ("test = %d\n", test);
if (slot->ops->hardware_test) {
- if (slot->ops->owner)
- __MOD_INC_USE_COUNT(slot->ops->owner);
- retval = slot->ops->hardware_test(slot, test);
- if (slot->ops->owner)
- __MOD_DEC_USE_COUNT(slot->ops->owner);
+ if (try_module_get(slot->ops->owner)) {
+ retval = slot->ops->hardware_test(slot, test);
+ module_put(slot->ops->owner);
+ }
}
exit:
diff --git a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig
index 131f4c901af5..ab26300729b2 100644
--- a/drivers/i2c/Kconfig
+++ b/drivers/i2c/Kconfig
@@ -166,8 +166,6 @@ config I2C_IBM_OCP_ADAP
tristate "IBM on-chip I2C Adapter"
depends on I2C_IBM_OCP_ALGO
-# This is needed for automatic patch generation: sensors code starts here
-# This is needed for automatic patch generation: sensors code ends here
config I2C_CHARDEV
tristate "I2C device interface"
depends on I2C
@@ -193,5 +191,8 @@ config I2C_PROC
it as a module, say M here and read <file:Documentation/modules.txt>.
The module will be called i2c-proc.o.
+ source drivers/i2c/busses/Kconfig
+ source drivers/i2c/chips/Kconfig
+
endmenu
diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile
index 924e971081b7..69595aa670e9 100644
--- a/drivers/i2c/Makefile
+++ b/drivers/i2c/Makefile
@@ -18,6 +18,4 @@ obj-$(CONFIG_ITE_I2C_ADAP) += i2c-adap-ite.o
obj-$(CONFIG_SCx200_I2C) += scx200_i2c.o
obj-$(CONFIG_SCx200_ACB) += scx200_acb.o
obj-$(CONFIG_I2C_PROC) += i2c-proc.o
-
-# This is needed for automatic patch generation: sensors code starts here
-# This is needed for automatic patch generation: sensors code ends here
+obj-y += busses/ chips/
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
new file mode 100644
index 000000000000..8750653989a9
--- /dev/null
+++ b/drivers/i2c/busses/Kconfig
@@ -0,0 +1,43 @@
+#
+# Sensor device configuration
+# All depend on EXPERIMENTAL, I2C and I2C_PROC.
+#
+
+menu "I2C Hardware Sensors Mainboard support"
+
+config I2C_AMD756
+ tristate " AMD 756/766"
+ depends on I2C && I2C_PROC
+ help
+ If you say yes to this option, support will be included for the AMD
+ 756/766/768 mainboard I2C interfaces.
+
+ This can also be built as a module which can be inserted and removed
+ while the kernel is running. If you want to compile it as a module,
+ say M here and read <file:Documentation/modules.txt>.
+
+ The module will be called i2c-amd756.o.
+
+ You will also need the latest user-space utilties: you can find them
+ in the lm_sensors package, which you can download at
+ http://www.lm-sensors.nu
+
+config I2C_AMD8111
+ tristate " AMD 8111"
+ depends on I2C && I2C_PROC
+ help
+ If you say yes to this option, support will be included for the AMD
+ 8111 mainboard I2C interfaces.
+
+ This can also be built as a module which can be inserted and removed
+ while the kernel is running. If you want to compile it as a module,
+ say M here and read <file:Documentation/modules.txt>.
+
+ The module will be called i2c-amd8111.o.
+
+ You will also need the latest user-space utilties: you can find them
+ in the lm_sensors package, which you can download at
+ http://www.lm-sensors.nu
+
+endmenu
+
diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
new file mode 100644
index 000000000000..181b1d97e0a9
--- /dev/null
+++ b/drivers/i2c/busses/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for the kernel hardware sensors bus drivers.
+#
+
+obj-$(CONFIG_I2C_AMD756) += i2c-amd756.o
+obj-$(CONFIG_I2C_AMD8111) += i2c-amd8111.o
diff --git a/drivers/i2c/busses/i2c-amd756.c b/drivers/i2c/busses/i2c-amd756.c
new file mode 100644
index 000000000000..aba96ef80719
--- /dev/null
+++ b/drivers/i2c/busses/i2c-amd756.c
@@ -0,0 +1,435 @@
+/*
+ amd756.c - Part of lm_sensors, Linux kernel modules for hardware
+ monitoring
+
+ Copyright (c) 1999-2002 Merlin Hughes <merlin@merlin.org>
+
+ Shamelessly ripped from i2c-piix4.c:
+
+ Copyright (c) 1998, 1999 Frodo Looijaard <frodol@dds.nl> and
+ Philip Edelbrock <phil@netroedge.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 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+/*
+ 2002-04-08: Added nForce support. (Csaba Halasz)
+ 2002-10-03: Fixed nForce PnP I/O port. (Michael Steil)
+ 2002-12-28: Rewritten into something that resembles a Linux driver (hch)
+*/
+
+/*
+ Supports AMD756, AMD766, AMD768 and nVidia nForce
+ Note: we assume there can only be one device, with one SMBus interface.
+*/
+
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/stddef.h>
+#include <linux/sched.h>
+#include <linux/ioport.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <asm/io.h>
+
+#define DRV_NAME "i2c-amd756"
+
+/* AMD756 SMBus address offsets */
+#define SMB_ADDR_OFFSET 0xE0
+#define SMB_IOSIZE 16
+#define SMB_GLOBAL_STATUS (0x0 + amd756_ioport)
+#define SMB_GLOBAL_ENABLE (0x2 + amd756_ioport)
+#define SMB_HOST_ADDRESS (0x4 + amd756_ioport)
+#define SMB_HOST_DATA (0x6 + amd756_ioport)
+#define SMB_HOST_COMMAND (0x8 + amd756_ioport)
+#define SMB_HOST_BLOCK_DATA (0x9 + amd756_ioport)
+#define SMB_HAS_DATA (0xA + amd756_ioport)
+#define SMB_HAS_DEVICE_ADDRESS (0xC + amd756_ioport)
+#define SMB_HAS_HOST_ADDRESS (0xE + amd756_ioport)
+#define SMB_SNOOP_ADDRESS (0xF + amd756_ioport)
+
+/* PCI Address Constants */
+
+/* address of I/O space */
+#define SMBBA 0x058 /* mh */
+#define SMBBANFORCE 0x014
+
+/* general configuration */
+#define SMBGCFG 0x041 /* mh */
+
+/* silicon revision code */
+#define SMBREV 0x008
+
+/* Other settings */
+#define MAX_TIMEOUT 500
+
+/* AMD756 constants */
+#define AMD756_QUICK 0x00
+#define AMD756_BYTE 0x01
+#define AMD756_BYTE_DATA 0x02
+#define AMD756_WORD_DATA 0x03
+#define AMD756_PROCESS_CALL 0x04
+#define AMD756_BLOCK_DATA 0x05
+
+
+static unsigned short amd756_ioport = 0;
+
+/*
+ SMBUS event = I/O 28-29 bit 11
+ see E0 for the status bits and enabled in E2
+
+*/
+
+/* Internally used pause function */
+static void amd756_do_pause(unsigned int amount)
+{
+ current->state = TASK_INTERRUPTIBLE;
+ schedule_timeout(amount);
+}
+
+#define GS_ABRT_STS (1 << 0)
+#define GS_COL_STS (1 << 1)
+#define GS_PRERR_STS (1 << 2)
+#define GS_HST_STS (1 << 3)
+#define GS_HCYC_STS (1 << 4)
+#define GS_TO_STS (1 << 5)
+#define GS_SMB_STS (1 << 11)
+
+#define GS_CLEAR_STS (GS_ABRT_STS | GS_COL_STS | GS_PRERR_STS | \
+ GS_HCYC_STS | GS_TO_STS )
+
+#define GE_CYC_TYPE_MASK (7)
+#define GE_HOST_STC (1 << 3)
+#define GE_ABORT (1 << 5)
+
+
+static int amd756_transaction(void)
+{
+ int temp;
+ int result = 0;
+ int timeout = 0;
+
+ pr_debug(DRV_NAME
+ ": Transaction (pre): GS=%04x, GE=%04x, ADD=%04x, DAT=%04x\n",
+ inw_p(SMB_GLOBAL_STATUS), inw_p(SMB_GLOBAL_ENABLE),
+ inw_p(SMB_HOST_ADDRESS), inb_p(SMB_HOST_DATA));
+
+ /* Make sure the SMBus host is ready to start transmitting */
+ if ((temp = inw_p(SMB_GLOBAL_STATUS)) & (GS_HST_STS | GS_SMB_STS)) {
+ pr_debug(DRV_NAME ": SMBus busy (%04x). Waiting... \n", temp);
+ do {
+ amd756_do_pause(1);
+ temp = inw_p(SMB_GLOBAL_STATUS);
+ } while ((temp & (GS_HST_STS | GS_SMB_STS)) &&
+ (timeout++ < MAX_TIMEOUT));
+ /* If the SMBus is still busy, we give up */
+ if (timeout >= MAX_TIMEOUT) {
+ pr_debug(DRV_NAME ": Busy wait timeout (%04x)\n", temp);
+ goto abort;
+ }
+ timeout = 0;
+ }
+
+ /* start the transaction by setting the start bit */
+ outw_p(inw(SMB_GLOBAL_ENABLE) | GE_HOST_STC, SMB_GLOBAL_ENABLE);
+
+ /* We will always wait for a fraction of a second! */
+ do {
+ amd756_do_pause(1);
+ temp = inw_p(SMB_GLOBAL_STATUS);
+ } while ((temp & GS_HST_STS) && (timeout++ < MAX_TIMEOUT));
+
+ /* If the SMBus is still busy, we give up */
+ if (timeout >= MAX_TIMEOUT) {
+ pr_debug(DRV_NAME ": Completion timeout!\n");
+ goto abort;
+ }
+
+ if (temp & GS_PRERR_STS) {
+ result = -1;
+ pr_debug(DRV_NAME ": SMBus Protocol error (no response)!\n");
+ }
+
+ if (temp & GS_COL_STS) {
+ result = -1;
+ printk(KERN_WARNING DRV_NAME " SMBus collision!\n");
+ }
+
+ if (temp & GS_TO_STS) {
+ result = -1;
+ pr_debug(DRV_NAME ": SMBus protocol timeout!\n");
+ }
+
+ if (temp & GS_HCYC_STS)
+ pr_debug(DRV_NAME " SMBus protocol success!\n");
+
+ outw_p(GS_CLEAR_STS, SMB_GLOBAL_STATUS);
+
+#ifdef DEBUG
+ if (((temp = inw_p(SMB_GLOBAL_STATUS)) & GS_CLEAR_STS) != 0x00) {
+ pr_debug(DRV_NAME
+ ": Failed reset at end of transaction (%04x)\n", temp);
+ }
+
+ pr_debug(DRV_NAME
+ ": Transaction (post): GS=%04x, GE=%04x, ADD=%04x, DAT=%04x\n",
+ inw_p(SMB_GLOBAL_STATUS), inw_p(SMB_GLOBAL_ENABLE),
+ inw_p(SMB_HOST_ADDRESS), inb_p(SMB_HOST_DATA));
+#endif
+
+ return result;
+
+ abort:
+ printk(KERN_WARNING DRV_NAME ": Sending abort.\n");
+ outw_p(inw(SMB_GLOBAL_ENABLE) | GE_ABORT, SMB_GLOBAL_ENABLE);
+ amd756_do_pause(100);
+ outw_p(GS_CLEAR_STS, SMB_GLOBAL_STATUS);
+ return -1;
+}
+
+/* Return -1 on error. */
+static s32 amd756_access(struct i2c_adapter * adap, u16 addr,
+ unsigned short flags, char read_write,
+ u8 command, int size, union i2c_smbus_data * data)
+{
+ int i, len;
+
+ /** TODO: Should I supporte the 10-bit transfers? */
+ switch (size) {
+ case I2C_SMBUS_PROC_CALL:
+ pr_debug(DRV_NAME ": I2C_SMBUS_PROC_CALL not supported!\n");
+ /* TODO: Well... It is supported, I'm just not sure what to do here... */
+ return -1;
+ case I2C_SMBUS_QUICK:
+ outw_p(((addr & 0x7f) << 1) | (read_write & 0x01),
+ SMB_HOST_ADDRESS);
+ size = AMD756_QUICK;
+ break;
+ case I2C_SMBUS_BYTE:
+ outw_p(((addr & 0x7f) << 1) | (read_write & 0x01),
+ SMB_HOST_ADDRESS);
+ /* TODO: Why only during write? */
+ if (read_write == I2C_SMBUS_WRITE)
+ outb_p(command, SMB_HOST_COMMAND);
+ size = AMD756_BYTE;
+ break;
+ case I2C_SMBUS_BYTE_DATA:
+ outw_p(((addr & 0x7f) << 1) | (read_write & 0x01),
+ SMB_HOST_ADDRESS);
+ outb_p(command, SMB_HOST_COMMAND);
+ if (read_write == I2C_SMBUS_WRITE)
+ outw_p(data->byte, SMB_HOST_DATA);
+ size = AMD756_BYTE_DATA;
+ break;
+ case I2C_SMBUS_WORD_DATA:
+ outw_p(((addr & 0x7f) << 1) | (read_write & 0x01),
+ SMB_HOST_ADDRESS);
+ outb_p(command, SMB_HOST_COMMAND);
+ if (read_write == I2C_SMBUS_WRITE)
+ outw_p(data->word, SMB_HOST_DATA); /* TODO: endian???? */
+ size = AMD756_WORD_DATA;
+ break;
+ case I2C_SMBUS_BLOCK_DATA:
+ outw_p(((addr & 0x7f) << 1) | (read_write & 0x01),
+ SMB_HOST_ADDRESS);
+ outb_p(command, SMB_HOST_COMMAND);
+ if (read_write == I2C_SMBUS_WRITE) {
+ len = data->block[0];
+ if (len < 0)
+ len = 0;
+ if (len > 32)
+ len = 32;
+ outw_p(len, SMB_HOST_DATA);
+ /* i = inw_p(SMBHSTCNT); Reset SMBBLKDAT */
+ for (i = 1; i <= len; i++)
+ outb_p(data->block[i],
+ SMB_HOST_BLOCK_DATA);
+ }
+ size = AMD756_BLOCK_DATA;
+ break;
+ }
+
+ /* How about enabling interrupts... */
+ outw_p(size & GE_CYC_TYPE_MASK, SMB_GLOBAL_ENABLE);
+
+ if (amd756_transaction()) /* Error in transaction */
+ return -1;
+
+ if ((read_write == I2C_SMBUS_WRITE) || (size == AMD756_QUICK))
+ return 0;
+
+
+ switch (size) {
+ case AMD756_BYTE:
+ data->byte = inw_p(SMB_HOST_DATA);
+ break;
+ case AMD756_BYTE_DATA:
+ data->byte = inw_p(SMB_HOST_DATA);
+ break;
+ case AMD756_WORD_DATA:
+ data->word = inw_p(SMB_HOST_DATA); /* TODO: endian???? */
+ break;
+ case AMD756_BLOCK_DATA:
+ data->block[0] = inw_p(SMB_HOST_DATA) & 0x3f;
+ if(data->block[0] > 32)
+ data->block[0] = 32;
+ /* i = inw_p(SMBHSTCNT); Reset SMBBLKDAT */
+ for (i = 1; i <= data->block[0]; i++)
+ data->block[i] = inb_p(SMB_HOST_BLOCK_DATA);
+ break;
+ }
+
+ return 0;
+}
+
+static void amd756_inc(struct i2c_adapter *adapter)
+{
+ MOD_INC_USE_COUNT;
+}
+
+static void amd756_dec(struct i2c_adapter *adapter)
+{
+
+ MOD_DEC_USE_COUNT;
+}
+
+static u32 amd756_func(struct i2c_adapter *adapter)
+{
+ return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
+ I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
+ I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_SMBUS_PROC_CALL;
+}
+
+static struct i2c_algorithm smbus_algorithm = {
+ .name = "Non-I2C SMBus adapter",
+ .id = I2C_ALGO_SMBUS,
+ .smbus_xfer = amd756_access,
+ .functionality = amd756_func,
+};
+
+static struct i2c_adapter amd756_adapter = {
+ .name = "unset",
+ .id = I2C_ALGO_SMBUS | I2C_HW_SMBUS_AMD756,
+ .algo = &smbus_algorithm,
+ .inc_use = amd756_inc,
+ .dec_use = amd756_dec,
+};
+
+enum chiptype { AMD756, AMD766, AMD768, NFORCE };
+
+static struct pci_device_id amd756_ids[] __devinitdata = {
+ {PCI_VENDOR_ID_AMD, 0x740B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AMD756 },
+ {PCI_VENDOR_ID_AMD, 0x7413, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AMD766 },
+ {PCI_VENDOR_ID_AMD, 0x7443, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AMD768 },
+ {PCI_VENDOR_ID_NVIDIA, 0x01B4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NFORCE },
+ { 0, }
+};
+
+static int __devinit amd756_probe(struct pci_dev *pdev,
+ const struct pci_device_id *id)
+{
+ int nforce = (id->driver_data == NFORCE), error;
+ u8 temp;
+
+ if (amd756_ioport) {
+ printk(KERN_ERR DRV_NAME ": Only one device supported. "
+ "(you have a strange motherboard, btw..)\n");
+ return -ENODEV;
+ }
+
+ if (nforce) {
+ if (PCI_FUNC(pdev->devfn) != 1)
+ return -ENODEV;
+
+ pci_read_config_word(pdev, SMBBANFORCE, &amd756_ioport);
+ amd756_ioport &= 0xfffc;
+ } else { /* amd */
+ if (PCI_FUNC(pdev->devfn) != 3)
+ return -ENODEV;
+
+ pci_read_config_byte(pdev, SMBGCFG, &temp);
+ if ((temp & 128) == 0) {
+ printk(KERN_ERR DRV_NAME
+ ": Error: SMBus controller I/O not enabled!\n");
+ return -ENODEV;
+ }
+
+ /* Determine the address of the SMBus areas */
+ /* Technically it is a dword but... */
+ pci_read_config_word(pdev, SMBBA, &amd756_ioport);
+ amd756_ioport &= 0xff00;
+ amd756_ioport += SMB_ADDR_OFFSET;
+ }
+
+ if (!request_region(amd756_ioport, SMB_IOSIZE, "amd756-smbus")) {
+ printk(KERN_ERR DRV_NAME
+ ": SMB region 0x%x already in use!\n", amd756_ioport);
+ return -ENODEV;
+ }
+
+#ifdef DEBUG
+ pci_read_config_byte(pdev, SMBREV, &temp);
+ printk(KERN_DEBUG DRV_NAME ": SMBREV = 0x%X\n", temp);
+ printk(KERN_DEBUG DRV_NAME ": AMD756_smba = 0x%X\n", amd756_ioport);
+#endif
+
+ sprintf(amd756_adapter.name,
+ "SMBus AMD75x adapter at %04x", amd756_ioport);
+
+ error = i2c_add_adapter(&amd756_adapter);
+ if (error) {
+ printk(KERN_ERR DRV_NAME
+ ": Adapter registration failed, module not inserted.\n");
+ goto out_err;
+ }
+
+ return 0;
+
+ out_err:
+ release_region(amd756_ioport, SMB_IOSIZE);
+ return error;
+}
+
+static void __devexit amd756_remove(struct pci_dev *dev)
+{
+ i2c_del_adapter(&amd756_adapter);
+ release_region(amd756_ioport, SMB_IOSIZE);
+}
+
+static struct pci_driver amd756_driver = {
+ .name = "amd75x smbus",
+ .id_table = amd756_ids,
+ .probe = amd756_probe,
+ .remove = __devexit_p(amd756_remove),
+};
+
+static int __init amd756_init(void)
+{
+ return pci_module_init(&amd756_driver);
+}
+
+static void __exit amd756_exit(void)
+{
+ pci_unregister_driver(&amd756_driver);
+}
+
+MODULE_AUTHOR("Merlin Hughes <merlin@merlin.org>");
+MODULE_DESCRIPTION("AMD756/766/768/nVidia nForce SMBus driver");
+MODULE_LICENSE("GPL");
+
+module_init(amd756_init)
+module_exit(amd756_exit)
diff --git a/drivers/i2c/busses/i2c-amd8111.c b/drivers/i2c/busses/i2c-amd8111.c
new file mode 100644
index 000000000000..ac2f741d3843
--- /dev/null
+++ b/drivers/i2c/busses/i2c-amd8111.c
@@ -0,0 +1,425 @@
+/*
+ * SMBus 2.0 driver for AMD-8111 IO-Hub.
+ *
+ * Copyright (c) 2002 Vojtech Pavlik
+ *
+ * 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 version 2.
+ */
+
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <asm/io.h>
+#include <linux/kernel.h>
+#include <linux/stddef.h>
+#include <linux/sched.h>
+#include <linux/ioport.h>
+#include <linux/init.h>
+#include <linux/i2c.h>
+#include <linux/delay.h>
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR ("Vojtech Pavlik <vojtech@suse.cz>");
+MODULE_DESCRIPTION("AMD8111 SMBus 2.0 driver");
+
+struct amd_smbus {
+ struct pci_dev *dev;
+ struct i2c_adapter adapter;
+ int base;
+ int size;
+};
+
+/*
+ * AMD PCI control registers definitions.
+ */
+
+#define AMD_PCI_MISC 0x48
+
+#define AMD_PCI_MISC_SCI 0x04 /* deliver SCI */
+#define AMD_PCI_MISC_INT 0x02 /* deliver PCI IRQ */
+#define AMD_PCI_MISC_SPEEDUP 0x01 /* 16x clock speedup */
+
+/*
+ * ACPI 2.0 chapter 13 PCI interface definitions.
+ */
+
+#define AMD_EC_DATA 0x00 /* data register */
+#define AMD_EC_SC 0x04 /* status of controller */
+#define AMD_EC_CMD 0x04 /* command register */
+#define AMD_EC_ICR 0x08 /* interrupt control register */
+
+#define AMD_EC_SC_SMI 0x04 /* smi event pending */
+#define AMD_EC_SC_SCI 0x02 /* sci event pending */
+#define AMD_EC_SC_BURST 0x01 /* burst mode enabled */
+#define AMD_EC_SC_CMD 0x08 /* byte in data reg is command */
+#define AMD_EC_SC_IBF 0x02 /* data ready for embedded controller */
+#define AMD_EC_SC_OBF 0x01 /* data ready for host */
+
+#define AMD_EC_CMD_RD 0x80 /* read EC */
+#define AMD_EC_CMD_WR 0x81 /* write EC */
+#define AMD_EC_CMD_BE 0x82 /* enable burst mode */
+#define AMD_EC_CMD_BD 0x83 /* disable burst mode */
+#define AMD_EC_CMD_QR 0x84 /* query EC */
+
+/*
+ * ACPI 2.0 chapter 13 access of registers of the EC
+ */
+
+unsigned int amd_ec_wait_write(struct amd_smbus *smbus)
+{
+ int timeout = 500;
+
+ while (timeout-- && (inb(smbus->base + AMD_EC_SC) & AMD_EC_SC_IBF))
+ udelay(1);
+
+ if (!timeout) {
+ printk(KERN_WARNING "i2c-amd8111.c: Timeout while waiting for IBF to clear\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+unsigned int amd_ec_wait_read(struct amd_smbus *smbus)
+{
+ int timeout = 500;
+
+ while (timeout-- && (~inb(smbus->base + AMD_EC_SC) & AMD_EC_SC_OBF))
+ udelay(1);
+
+ if (!timeout) {
+ printk(KERN_WARNING "i2c-amd8111.c: Timeout while waiting for OBF to set\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+unsigned int amd_ec_read(struct amd_smbus *smbus, unsigned char address, unsigned char *data)
+{
+ if (amd_ec_wait_write(smbus))
+ return -1;
+ outb(AMD_EC_CMD_RD, smbus->base + AMD_EC_CMD);
+
+ if (amd_ec_wait_write(smbus))
+ return -1;
+ outb(address, smbus->base + AMD_EC_DATA);
+
+ if (amd_ec_wait_read(smbus))
+ return -1;
+ *data = inb(smbus->base + AMD_EC_DATA);
+
+ return 0;
+}
+
+unsigned int amd_ec_write(struct amd_smbus *smbus, unsigned char address, unsigned char data)
+{
+ if (amd_ec_wait_write(smbus))
+ return -1;
+ outb(AMD_EC_CMD_WR, smbus->base + AMD_EC_CMD);
+
+ if (amd_ec_wait_write(smbus))
+ return -1;
+ outb(address, smbus->base + AMD_EC_DATA);
+
+ if (amd_ec_wait_write(smbus))
+ return -1;
+ outb(data, smbus->base + AMD_EC_DATA);
+
+ return 0;
+}
+
+/*
+ * ACPI 2.0 chapter 13 SMBus 2.0 EC register model
+ */
+
+#define AMD_SMB_PRTCL 0x00 /* protocol, PEC */
+#define AMD_SMB_STS 0x01 /* status */
+#define AMD_SMB_ADDR 0x02 /* address */
+#define AMD_SMB_CMD 0x03 /* command */
+#define AMD_SMB_DATA 0x04 /* 32 data registers */
+#define AMD_SMB_BCNT 0x24 /* number of data bytes */
+#define AMD_SMB_ALRM_A 0x25 /* alarm address */
+#define AMD_SMB_ALRM_D 0x26 /* 2 bytes alarm data */
+
+#define AMD_SMB_STS_DONE 0x80
+#define AMD_SMB_STS_ALRM 0x40
+#define AMD_SMB_STS_RES 0x20
+#define AMD_SMB_STS_STATUS 0x1f
+
+#define AMD_SMB_STATUS_OK 0x00
+#define AMD_SMB_STATUS_FAIL 0x07
+#define AMD_SMB_STATUS_DNAK 0x10
+#define AMD_SMB_STATUS_DERR 0x11
+#define AMD_SMB_STATUS_CMD_DENY 0x12
+#define AMD_SMB_STATUS_UNKNOWN 0x13
+#define AMD_SMB_STATUS_ACC_DENY 0x17
+#define AMD_SMB_STATUS_TIMEOUT 0x18
+#define AMD_SMB_STATUS_NOTSUP 0x19
+#define AMD_SMB_STATUS_BUSY 0x1A
+#define AMD_SMB_STATUS_PEC 0x1F
+
+#define AMD_SMB_PRTCL_WRITE 0x00
+#define AMD_SMB_PRTCL_READ 0x01
+#define AMD_SMB_PRTCL_QUICK 0x02
+#define AMD_SMB_PRTCL_BYTE 0x04
+#define AMD_SMB_PRTCL_BYTE_DATA 0x06
+#define AMD_SMB_PRTCL_WORD_DATA 0x08
+#define AMD_SMB_PRTCL_BLOCK_DATA 0x0a
+#define AMD_SMB_PRTCL_PROC_CALL 0x0c
+#define AMD_SMB_PRTCL_BLOCK_PROC_CALL 0x0d
+#define AMD_SMB_PRTCL_I2C_BLOCK_DATA 0x4a
+#define AMD_SMB_PRTCL_PEC 0x80
+
+
+s32 amd8111_access(struct i2c_adapter * adap, u16 addr, unsigned short flags,
+ char read_write, u8 command, int size, union i2c_smbus_data * data)
+{
+ struct amd_smbus *smbus = adap->algo_data;
+ unsigned char protocol, len, pec, temp[2];
+ int i;
+
+ protocol = (read_write == I2C_SMBUS_READ) ? AMD_SMB_PRTCL_READ : AMD_SMB_PRTCL_WRITE;
+ pec = (flags & I2C_CLIENT_PEC) ? AMD_SMB_PRTCL_PEC : 0;
+
+ switch (size) {
+
+ case I2C_SMBUS_QUICK:
+ protocol |= AMD_SMB_PRTCL_QUICK;
+ read_write = I2C_SMBUS_WRITE;
+ break;
+
+ case I2C_SMBUS_BYTE:
+ if (read_write == I2C_SMBUS_WRITE)
+ amd_ec_write(smbus, AMD_SMB_DATA, data->byte);
+ protocol |= AMD_SMB_PRTCL_BYTE;
+ break;
+
+ case I2C_SMBUS_BYTE_DATA:
+ amd_ec_write(smbus, AMD_SMB_CMD, command);
+ if (read_write == I2C_SMBUS_WRITE)
+ amd_ec_write(smbus, AMD_SMB_DATA, data->byte);
+ protocol |= AMD_SMB_PRTCL_BYTE_DATA;
+ break;
+
+ case I2C_SMBUS_WORD_DATA_PEC:
+ protocol |= AMD_SMB_PRTCL_PEC;
+ case I2C_SMBUS_WORD_DATA:
+ amd_ec_write(smbus, AMD_SMB_CMD, command);
+ if (read_write == I2C_SMBUS_WRITE) {
+ amd_ec_write(smbus, AMD_SMB_DATA, data->word);
+ amd_ec_write(smbus, AMD_SMB_DATA + 1, data->word >> 8);
+ }
+ protocol |= AMD_SMB_PRTCL_WORD_DATA | pec;
+ break;
+
+ case I2C_SMBUS_BLOCK_DATA_PEC:
+ protocol |= AMD_SMB_PRTCL_PEC;
+ case I2C_SMBUS_BLOCK_DATA:
+ amd_ec_write(smbus, AMD_SMB_CMD, command);
+ if (read_write == I2C_SMBUS_WRITE) {
+ len = min_t(u8, data->block[0], 32);
+ amd_ec_write(smbus, AMD_SMB_BCNT, len);
+ for (i = 0; i < len; i++)
+ amd_ec_write(smbus, AMD_SMB_DATA + i, data->block[i + 1]);
+ }
+ protocol |= AMD_SMB_PRTCL_BLOCK_DATA | pec;
+ break;
+
+ case I2C_SMBUS_I2C_BLOCK_DATA:
+ len = min_t(u8, data->block[0], 32);
+ amd_ec_write(smbus, AMD_SMB_CMD, command);
+ amd_ec_write(smbus, AMD_SMB_BCNT, len);
+ if (read_write == I2C_SMBUS_WRITE)
+ for (i = 0; i < len; i++)
+ amd_ec_write(smbus, AMD_SMB_DATA + i, data->block[i + 1]);
+ protocol |= AMD_SMB_PRTCL_I2C_BLOCK_DATA;
+ break;
+
+ case I2C_SMBUS_PROC_CALL_PEC:
+ protocol |= AMD_SMB_PRTCL_PEC;
+ case I2C_SMBUS_PROC_CALL:
+ amd_ec_write(smbus, AMD_SMB_CMD, command);
+ amd_ec_write(smbus, AMD_SMB_DATA, data->word);
+ amd_ec_write(smbus, AMD_SMB_DATA + 1, data->word >> 8);
+ protocol = AMD_SMB_PRTCL_PROC_CALL | pec;
+ read_write = I2C_SMBUS_READ;
+ break;
+
+ case I2C_SMBUS_BLOCK_PROC_CALL_PEC:
+ protocol |= AMD_SMB_PRTCL_PEC;
+ case I2C_SMBUS_BLOCK_PROC_CALL:
+ protocol |= pec;
+ len = min_t(u8, data->block[0], 31);
+ amd_ec_write(smbus, AMD_SMB_CMD, command);
+ amd_ec_write(smbus, AMD_SMB_BCNT, len);
+ for (i = 0; i < len; i++)
+ amd_ec_write(smbus, AMD_SMB_DATA + i, data->block[i + 1]);
+ protocol = AMD_SMB_PRTCL_BLOCK_PROC_CALL | pec;
+ read_write = I2C_SMBUS_READ;
+ break;
+
+ default:
+ printk(KERN_WARNING "i2c-amd8111.c: Unsupported transaction %d\n", size);
+ return -1;
+ }
+
+ amd_ec_write(smbus, AMD_SMB_ADDR, addr << 1);
+ amd_ec_write(smbus, AMD_SMB_PRTCL, protocol);
+
+ amd_ec_read(smbus, AMD_SMB_STS, temp + 0);
+
+ if (~temp[0] & AMD_SMB_STS_DONE) {
+ udelay(500);
+ amd_ec_read(smbus, AMD_SMB_STS, temp + 0);
+ }
+
+ if (~temp[0] & AMD_SMB_STS_DONE) {
+ current->state = TASK_INTERRUPTIBLE;
+ schedule_timeout(HZ/100);
+ amd_ec_read(smbus, AMD_SMB_STS, temp + 0);
+ }
+
+ if ((~temp[0] & AMD_SMB_STS_DONE) || (temp[0] & AMD_SMB_STS_STATUS))
+ return -1;
+
+ if (read_write == I2C_SMBUS_WRITE)
+ return 0;
+
+ switch (size) {
+
+ case I2C_SMBUS_BYTE:
+ case I2C_SMBUS_BYTE_DATA:
+ amd_ec_read(smbus, AMD_SMB_DATA, &data->byte);
+ break;
+
+ case I2C_SMBUS_WORD_DATA:
+ case I2C_SMBUS_WORD_DATA_PEC:
+ case I2C_SMBUS_PROC_CALL:
+ case I2C_SMBUS_PROC_CALL_PEC:
+ amd_ec_read(smbus, AMD_SMB_DATA, temp + 0);
+ amd_ec_read(smbus, AMD_SMB_DATA + 1, temp + 1);
+ data->word = (temp[1] << 8) | temp[0];
+ break;
+
+ case I2C_SMBUS_BLOCK_DATA:
+ case I2C_SMBUS_BLOCK_DATA_PEC:
+ case I2C_SMBUS_BLOCK_PROC_CALL:
+ case I2C_SMBUS_BLOCK_PROC_CALL_PEC:
+ amd_ec_read(smbus, AMD_SMB_BCNT, &len);
+ len = min_t(u8, len, 32);
+ case I2C_SMBUS_I2C_BLOCK_DATA:
+ for (i = 0; i < len; i++)
+ amd_ec_read(smbus, AMD_SMB_DATA + i, data->block + i + 1);
+ data->block[0] = len;
+ break;
+ }
+
+ return 0;
+}
+
+void amd8111_inc(struct i2c_adapter *adapter)
+{
+ MOD_INC_USE_COUNT;
+}
+
+void amd8111_dec(struct i2c_adapter *adapter)
+{
+ MOD_DEC_USE_COUNT;
+}
+
+u32 amd8111_func(struct i2c_adapter *adapter)
+{
+ return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | I2C_FUNC_SMBUS_BYTE_DATA |
+ I2C_FUNC_SMBUS_WORD_DATA | I2C_FUNC_SMBUS_WORD_DATA_PEC |
+ I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_SMBUS_BLOCK_DATA_PEC |
+ I2C_FUNC_SMBUS_PROC_CALL | I2C_FUNC_SMBUS_PROC_CALL_PEC |
+ I2C_FUNC_SMBUS_BLOCK_PROC_CALL | I2C_FUNC_SMBUS_BLOCK_PROC_CALL_PEC |
+ I2C_FUNC_SMBUS_I2C_BLOCK | I2C_FUNC_SMBUS_HWPEC_CALC;
+}
+
+static struct i2c_algorithm smbus_algorithm = {
+ .name = "Non-I2C SMBus 2.0 adapter",
+ .id = I2C_ALGO_SMBUS,
+ .smbus_xfer = amd8111_access,
+ .functionality = amd8111_func,
+};
+
+static int __devinit amd8111_probe(struct pci_dev *dev, const struct pci_device_id *id)
+{
+ struct amd_smbus *smbus;
+
+ if (~pci_resource_flags(dev, 0) & IORESOURCE_IO)
+ return -1;
+
+ if (!(smbus = (void*)kmalloc(sizeof(struct amd_smbus), GFP_KERNEL)))
+ return -1;
+ memset(smbus, 0, sizeof(struct amd_smbus));
+
+ pci_set_drvdata(dev, smbus);
+ smbus->dev = dev;
+ smbus->base = pci_resource_start(dev, 0);
+ smbus->size = pci_resource_len(dev, 0);
+
+ if (!request_region(smbus->base, smbus->size, "amd8111 SMBus 2.0")) {
+ kfree(smbus);
+ return -1;
+ }
+
+ sprintf(smbus->adapter.name, "SMBus2 AMD8111 adapter at %04x", smbus->base);
+ smbus->adapter.id = I2C_ALGO_SMBUS | I2C_HW_SMBUS_AMD8111;
+ smbus->adapter.algo = &smbus_algorithm;
+ smbus->adapter.algo_data = smbus;
+ smbus->adapter.inc_use = amd8111_inc;
+ smbus->adapter.dec_use = amd8111_dec;
+
+ if (i2c_add_adapter(&smbus->adapter)) {
+ printk(KERN_WARNING "i2c-amd8111.c: Failed to register adapter.\n");
+ release_region(smbus->base, smbus->size);
+ kfree(smbus);
+ return -1;
+ }
+
+ pci_write_config_dword(smbus->dev, AMD_PCI_MISC, 0);
+
+ printk(KERN_INFO "i2c-amd8111.c: AMD8111 SMBus 2.0 adapter at %#x\n", smbus->base);
+ return 0;
+}
+
+static void __devexit amd8111_remove(struct pci_dev *dev)
+{
+ struct amd_smbus *smbus = (void*) pci_get_drvdata(dev);
+ if (i2c_del_adapter(&smbus->adapter)) {
+ printk(KERN_WARNING "i2c-amd8111.c: Failed to unregister adapter.\n");
+ return;
+ }
+ release_region(smbus->base, smbus->size);
+ kfree(smbus);
+}
+
+static struct pci_device_id amd8111_id_table[] __devinitdata =
+{{ 0x1022, 0x746a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+ { 0 }};
+
+
+static struct pci_driver amd8111_driver = {
+ .name = "amd8111 smbus 2.0",
+ .id_table = amd8111_id_table,
+ .probe = amd8111_probe,
+ .remove = __devexit_p(amd8111_remove),
+};
+
+int __init amd8111_init(void)
+{
+ return pci_module_init(&amd8111_driver);
+}
+
+void __exit amd8111_exit(void)
+{
+ pci_unregister_driver(&amd8111_driver);
+}
+
+module_init(amd8111_init);
+module_exit(amd8111_exit);
diff --git a/drivers/i2c/chips/Kconfig b/drivers/i2c/chips/Kconfig
new file mode 100644
index 000000000000..405db21a3a32
--- /dev/null
+++ b/drivers/i2c/chips/Kconfig
@@ -0,0 +1,40 @@
+#
+# Sensor device configuration
+# All depend on EXPERIMENTAL, I2C and I2C_PROC.
+#
+
+menu "I2C Hardware Sensors Chip support"
+
+config SENSORS_ADM1021
+ tristate " Analog Devices ADM1021 and compatibles"
+ depends on I2C && I2C_PROC
+ help
+ If you say yes here you get support for Analog Devices ADM1021
+ and ADM1023 sensor chips and clones: Maxim MAX1617 and MAX1617A,
+ Genesys Logic GL523SM, National Semi LM84, TI THMC10,
+ and the XEON processor built-in sensor. This can also
+ be built as a module which can be inserted and removed while the
+ kernel is running.
+
+ The module will be called adm1021.o.
+
+ You will also need the latest user-space utilties: you can find them
+ in the lm_sensors package, which you can download at
+ http://www.lm-sensors.nu
+
+config SENSORS_LM75
+ tristate " National Semiconductors LM75 and compatibles"
+ depends on I2C && I2C_PROC
+ help
+ If you say yes here you get support for National Semiconductor LM75
+ sensor chips and clones: Dallas Semi DS75 and DS1775, TelCon
+ TCN75, and National Semi LM77. This can also be built as a module
+ which can be inserted and removed while the kernel is running.
+
+ The module will be called lm75.o.
+
+ You will also need the latest user-space utilties: you can find them
+ in the lm_sensors package, which you can download at
+ http://www.lm-sensors.nu
+
+endmenu
diff --git a/drivers/i2c/chips/Makefile b/drivers/i2c/chips/Makefile
new file mode 100644
index 000000000000..835c8db87b4f
--- /dev/null
+++ b/drivers/i2c/chips/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for the kernel hardware sensors chip drivers.
+#
+
+obj-$(CONFIG_SENSORS_ADM1021) += adm1021.o
+obj-$(CONFIG_SENSORS_LM75) += lm75.o
diff --git a/drivers/i2c/chips/adm1021.c b/drivers/i2c/chips/adm1021.c
new file mode 100644
index 000000000000..abab348e5b1b
--- /dev/null
+++ b/drivers/i2c/chips/adm1021.c
@@ -0,0 +1,600 @@
+/*
+ adm1021.c - Part of lm_sensors, Linux kernel modules for hardware
+ monitoring
+ Copyright (c) 1998, 1999 Frodo Looijaard <frodol@dds.nl> and
+ Philip Edelbrock <phil@netroedge.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 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/sensors.h>
+#include <linux/init.h>
+
+
+/* Addresses to scan */
+static unsigned short normal_i2c[] = { SENSORS_I2C_END };
+static unsigned short normal_i2c_range[] = { 0x18, 0x1a, 0x29, 0x2b,
+ 0x4c, 0x4e, SENSORS_I2C_END
+};
+static unsigned int normal_isa[] = { SENSORS_ISA_END };
+static unsigned int normal_isa_range[] = { SENSORS_ISA_END };
+
+/* Insmod parameters */
+SENSORS_INSMOD_8(adm1021, adm1023, max1617, max1617a, thmc10, lm84, gl523sm, mc1066);
+
+/* adm1021 constants specified below */
+
+/* The adm1021 registers */
+/* Read-only */
+#define ADM1021_REG_TEMP 0x00
+#define ADM1021_REG_REMOTE_TEMP 0x01
+#define ADM1021_REG_STATUS 0x02
+#define ADM1021_REG_MAN_ID 0x0FE /* 0x41 = AMD, 0x49 = TI, 0x4D = Maxim, 0x23 = Genesys , 0x54 = Onsemi*/
+#define ADM1021_REG_DEV_ID 0x0FF /* ADM1021 = 0x0X, ADM1023 = 0x3X */
+#define ADM1021_REG_DIE_CODE 0x0FF /* MAX1617A */
+/* These use different addresses for reading/writing */
+#define ADM1021_REG_CONFIG_R 0x03
+#define ADM1021_REG_CONFIG_W 0x09
+#define ADM1021_REG_CONV_RATE_R 0x04
+#define ADM1021_REG_CONV_RATE_W 0x0A
+/* These are for the ADM1023's additional precision on the remote temp sensor */
+#define ADM1021_REG_REM_TEMP_PREC 0x010
+#define ADM1021_REG_REM_OFFSET 0x011
+#define ADM1021_REG_REM_OFFSET_PREC 0x012
+#define ADM1021_REG_REM_TOS_PREC 0x013
+#define ADM1021_REG_REM_THYST_PREC 0x014
+/* limits */
+#define ADM1021_REG_TOS_R 0x05
+#define ADM1021_REG_TOS_W 0x0B
+#define ADM1021_REG_REMOTE_TOS_R 0x07
+#define ADM1021_REG_REMOTE_TOS_W 0x0D
+#define ADM1021_REG_THYST_R 0x06
+#define ADM1021_REG_THYST_W 0x0C
+#define ADM1021_REG_REMOTE_THYST_R 0x08
+#define ADM1021_REG_REMOTE_THYST_W 0x0E
+/* write-only */
+#define ADM1021_REG_ONESHOT 0x0F
+
+
+/* Conversions. Rounding and limit checking is only done on the TO_REG
+ variants. Note that you should be a bit careful with which arguments
+ these macros are called: arguments may be evaluated more than once.
+ Fixing this is just not worth it. */
+/* Conversions note: 1021 uses normal integer signed-byte format*/
+#define TEMP_FROM_REG(val) (val > 127 ? val-256 : val)
+#define TEMP_TO_REG(val) (SENSORS_LIMIT((val < 0 ? val+256 : val),0,255))
+
+/* Initial values */
+
+/* Note: Eventhough I left the low and high limits named os and hyst,
+they don't quite work like a thermostat the way the LM75 does. I.e.,
+a lower temp than THYST actuall triggers an alarm instead of
+clearing it. Weird, ey? --Phil */
+#define adm1021_INIT_TOS 60
+#define adm1021_INIT_THYST 20
+#define adm1021_INIT_REMOTE_TOS 60
+#define adm1021_INIT_REMOTE_THYST 20
+
+/* Each client has this additional data */
+struct adm1021_data {
+ int sysctl_id;
+ enum chips type;
+
+ struct semaphore update_lock;
+ char valid; /* !=0 if following fields are valid */
+ unsigned long last_updated; /* In jiffies */
+
+ u8 temp, temp_os, temp_hyst; /* Register values */
+ u8 remote_temp, remote_temp_os, remote_temp_hyst, alarms, die_code;
+ /* Special values for ADM1023 only */
+ u8 remote_temp_prec, remote_temp_os_prec, remote_temp_hyst_prec,
+ remote_temp_offset, remote_temp_offset_prec;
+};
+
+static int adm1021_attach_adapter(struct i2c_adapter *adapter);
+static int adm1021_detect(struct i2c_adapter *adapter, int address,
+ unsigned short flags, int kind);
+static void adm1021_init_client(struct i2c_client *client);
+static int adm1021_detach_client(struct i2c_client *client);
+static int adm1021_command(struct i2c_client *client, unsigned int cmd,
+ void *arg);
+static void adm1021_inc_use(struct i2c_client *client);
+static void adm1021_dec_use(struct i2c_client *client);
+static int adm1021_read_value(struct i2c_client *client, u8 reg);
+static int adm1021_write_value(struct i2c_client *client, u8 reg,
+ u16 value);
+static void adm1021_temp(struct i2c_client *client, int operation,
+ int ctl_name, int *nrels_mag, long *results);
+static void adm1021_remote_temp(struct i2c_client *client, int operation,
+ int ctl_name, int *nrels_mag,
+ long *results);
+static void adm1021_alarms(struct i2c_client *client, int operation,
+ int ctl_name, int *nrels_mag, long *results);
+static void adm1021_die_code(struct i2c_client *client, int operation,
+ int ctl_name, int *nrels_mag, long *results);
+static void adm1021_update_client(struct i2c_client *client);
+
+/* (amalysh) read only mode, otherwise any limit's writing confuse BIOS */
+static int read_only = 0;
+
+
+/* This is the driver that will be inserted */
+static struct i2c_driver adm1021_driver = {
+ /* name */ "ADM1021, MAX1617 sensor driver",
+ /* id */ I2C_DRIVERID_ADM1021,
+ /* flags */ I2C_DF_NOTIFY,
+ /* attach_adapter */ &adm1021_attach_adapter,
+ /* detach_client */ &adm1021_detach_client,
+ /* command */ &adm1021_command,
+ /* inc_use */ &adm1021_inc_use,
+ /* dec_use */ &adm1021_dec_use
+};
+
+/* These files are created for each detected adm1021. This is just a template;
+ though at first sight, you might think we could use a statically
+ allocated list, we need some way to get back to the parent - which
+ is done through one of the 'extra' fields which are initialized
+ when a new copy is allocated. */
+static ctl_table adm1021_dir_table_template[] = {
+ {ADM1021_SYSCTL_TEMP, "temp1", NULL, 0, 0644, NULL, &i2c_proc_real,
+ &i2c_sysctl_real, NULL, &adm1021_temp},
+ {ADM1021_SYSCTL_REMOTE_TEMP, "temp2", NULL, 0, 0644, NULL, &i2c_proc_real,
+ &i2c_sysctl_real, NULL, &adm1021_remote_temp},
+ {ADM1021_SYSCTL_DIE_CODE, "die_code", NULL, 0, 0444, NULL, &i2c_proc_real,
+ &i2c_sysctl_real, NULL, &adm1021_die_code},
+ {ADM1021_SYSCTL_ALARMS, "alarms", NULL, 0, 0444, NULL, &i2c_proc_real,
+ &i2c_sysctl_real, NULL, &adm1021_alarms},
+ {0}
+};
+
+static ctl_table adm1021_max_dir_table_template[] = {
+ {ADM1021_SYSCTL_TEMP, "temp1", NULL, 0, 0644, NULL, &i2c_proc_real,
+ &i2c_sysctl_real, NULL, &adm1021_temp},
+ {ADM1021_SYSCTL_REMOTE_TEMP, "temp2", NULL, 0, 0644, NULL, &i2c_proc_real,
+ &i2c_sysctl_real, NULL, &adm1021_remote_temp},
+ {ADM1021_SYSCTL_ALARMS, "alarms", NULL, 0, 0444, NULL, &i2c_proc_real,
+ &i2c_sysctl_real, NULL, &adm1021_alarms},
+ {0}
+};
+
+/* I choose here for semi-static allocation. Complete dynamic
+ allocation could also be used; the code needed for this would probably
+ take more memory than the datastructure takes now. */
+static int adm1021_id = 0;
+
+int adm1021_attach_adapter(struct i2c_adapter *adapter)
+{
+ return i2c_detect(adapter, &addr_data, adm1021_detect);
+}
+
+static int adm1021_detect(struct i2c_adapter *adapter, int address,
+ unsigned short flags, int kind)
+{
+ int i;
+ struct i2c_client *new_client;
+ struct adm1021_data *data;
+ int err = 0;
+ const char *type_name = "";
+ const char *client_name = "";
+
+ /* Make sure we aren't probing the ISA bus!! This is just a safety check
+ at this moment; i2c_detect really won't call us. */
+#ifdef DEBUG
+ if (i2c_is_isa_adapter(adapter)) {
+ printk
+ ("adm1021.o: adm1021_detect called for an ISA bus adapter?!?\n");
+ return 0;
+ }
+#endif
+
+ if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+ goto error0;
+
+ /* OK. For now, we presume we have a valid client. We now create the
+ client structure, even though we cannot fill it completely yet.
+ But it allows us to access adm1021_{read,write}_value. */
+
+ if (!(new_client = kmalloc(sizeof(struct i2c_client) +
+ sizeof(struct adm1021_data),
+ GFP_KERNEL))) {
+ err = -ENOMEM;
+ goto error0;
+ }
+
+ data = (struct adm1021_data *) (new_client + 1);
+ new_client->addr = address;
+ new_client->data = data;
+ new_client->adapter = adapter;
+ new_client->driver = &adm1021_driver;
+ new_client->flags = 0;
+
+ /* Now, we do the remaining detection. */
+
+ if (kind < 0) {
+ if (
+ (adm1021_read_value(new_client, ADM1021_REG_STATUS) &
+ 0x03) != 0x00)
+ goto error1;
+ }
+
+ /* Determine the chip type. */
+
+ if (kind <= 0) {
+ i = adm1021_read_value(new_client, ADM1021_REG_MAN_ID);
+ if (i == 0x41)
+ if ((adm1021_read_value (new_client, ADM1021_REG_DEV_ID) & 0x0F0) == 0x030)
+ kind = adm1023;
+ else
+ kind = adm1021;
+ else if (i == 0x49)
+ kind = thmc10;
+ else if (i == 0x23)
+ kind = gl523sm;
+ else if ((i == 0x4d) &&
+ (adm1021_read_value
+ (new_client, ADM1021_REG_DEV_ID) == 0x01))
+ kind = max1617a;
+ /* LM84 Mfr ID in a different place */
+ else
+ if (adm1021_read_value
+ (new_client, ADM1021_REG_CONV_RATE_R) == 0x00)
+ kind = lm84;
+ else if (i == 0x54)
+ kind = mc1066;
+ else
+ kind = max1617;
+ }
+
+ if (kind == max1617) {
+ type_name = "max1617";
+ client_name = "MAX1617 chip";
+ } else if (kind == max1617a) {
+ type_name = "max1617a";
+ client_name = "MAX1617A chip";
+ } else if (kind == adm1021) {
+ type_name = "adm1021";
+ client_name = "ADM1021 chip";
+ } else if (kind == adm1023) {
+ type_name = "adm1023";
+ client_name = "ADM1023 chip";
+ } else if (kind == thmc10) {
+ type_name = "thmc10";
+ client_name = "THMC10 chip";
+ } else if (kind == lm84) {
+ type_name = "lm84";
+ client_name = "LM84 chip";
+ } else if (kind == gl523sm) {
+ type_name = "gl523sm";
+ client_name = "GL523SM chip";
+ } else if (kind == mc1066) {
+ type_name = "mc1066";
+ client_name = "MC1066 chip";
+ } else {
+#ifdef DEBUG
+ printk("adm1021.o: Internal error: unknown kind (%d)?!?",
+ kind);
+#endif
+ goto error1;
+ }
+
+ /* Fill in the remaining client fields and put it into the global list */
+ strcpy(new_client->name, client_name);
+ data->type = kind;
+
+ new_client->id = adm1021_id++;
+ data->valid = 0;
+ init_MUTEX(&data->update_lock);
+
+ /* Tell the I2C layer a new client has arrived */
+ if ((err = i2c_attach_client(new_client)))
+ goto error3;
+
+ /* Register a new directory entry with module sensors */
+ if ((i = i2c_register_entry(new_client,
+ type_name,
+ data->type ==
+ adm1021 ?
+ adm1021_dir_table_template :
+ adm1021_max_dir_table_template,
+ THIS_MODULE)) < 0) {
+ err = i;
+ goto error4;
+ }
+ data->sysctl_id = i;
+
+ /* Initialize the ADM1021 chip */
+ adm1021_init_client(new_client);
+ return 0;
+
+ error4:
+ i2c_detach_client(new_client);
+ error3:
+ error1:
+ kfree(new_client);
+ error0:
+ return err;
+}
+
+void adm1021_init_client(struct i2c_client *client)
+{
+ /* Initialize the adm1021 chip */
+ adm1021_write_value(client, ADM1021_REG_TOS_W,
+ TEMP_TO_REG(adm1021_INIT_TOS));
+ adm1021_write_value(client, ADM1021_REG_THYST_W,
+ TEMP_TO_REG(adm1021_INIT_THYST));
+ adm1021_write_value(client, ADM1021_REG_REMOTE_TOS_W,
+ TEMP_TO_REG(adm1021_INIT_REMOTE_TOS));
+ adm1021_write_value(client, ADM1021_REG_REMOTE_THYST_W,
+ TEMP_TO_REG(adm1021_INIT_REMOTE_THYST));
+ /* Enable ADC and disable suspend mode */
+ adm1021_write_value(client, ADM1021_REG_CONFIG_W, 0);
+ /* Set Conversion rate to 1/sec (this can be tinkered with) */
+ adm1021_write_value(client, ADM1021_REG_CONV_RATE_W, 0x04);
+}
+
+int adm1021_detach_client(struct i2c_client *client)
+{
+
+ int err;
+
+ i2c_deregister_entry(((struct adm1021_data *) (client->data))->
+ sysctl_id);
+
+ if ((err = i2c_detach_client(client))) {
+ printk
+ ("adm1021.o: Client deregistration failed, client not detached.\n");
+ return err;
+ }
+
+ kfree(client);
+
+ return 0;
+
+}
+
+
+/* No commands defined yet */
+int adm1021_command(struct i2c_client *client, unsigned int cmd, void *arg)
+{
+ return 0;
+}
+
+void adm1021_inc_use(struct i2c_client *client)
+{
+ MOD_INC_USE_COUNT;
+}
+
+void adm1021_dec_use(struct i2c_client *client)
+{
+ MOD_DEC_USE_COUNT;
+}
+
+/* All registers are byte-sized */
+int adm1021_read_value(struct i2c_client *client, u8 reg)
+{
+ return i2c_smbus_read_byte_data(client, reg);
+}
+
+int adm1021_write_value(struct i2c_client *client, u8 reg, u16 value)
+{
+ if (read_only > 0)
+ return 0;
+
+ return i2c_smbus_write_byte_data(client, reg, value);
+}
+
+void adm1021_update_client(struct i2c_client *client)
+{
+ struct adm1021_data *data = client->data;
+
+ down(&data->update_lock);
+
+ if ((jiffies - data->last_updated > HZ + HZ / 2) ||
+ (jiffies < data->last_updated) || !data->valid) {
+
+#ifdef DEBUG
+ printk("Starting adm1021 update\n");
+#endif
+
+ data->temp = adm1021_read_value(client, ADM1021_REG_TEMP);
+ data->temp_os =
+ adm1021_read_value(client, ADM1021_REG_TOS_R);
+ data->temp_hyst =
+ adm1021_read_value(client, ADM1021_REG_THYST_R);
+ data->remote_temp =
+ adm1021_read_value(client, ADM1021_REG_REMOTE_TEMP);
+ data->remote_temp_os =
+ adm1021_read_value(client, ADM1021_REG_REMOTE_TOS_R);
+ data->remote_temp_hyst =
+ adm1021_read_value(client, ADM1021_REG_REMOTE_THYST_R);
+ data->alarms =
+ adm1021_read_value(client, ADM1021_REG_STATUS) & 0xec;
+ if (data->type == adm1021)
+ data->die_code =
+ adm1021_read_value(client,
+ ADM1021_REG_DIE_CODE);
+ if (data->type == adm1023) {
+ data->remote_temp_prec =
+ adm1021_read_value(client, ADM1021_REG_REM_TEMP_PREC);
+ data->remote_temp_os_prec =
+ adm1021_read_value(client, ADM1021_REG_REM_TOS_PREC);
+ data->remote_temp_hyst_prec =
+ adm1021_read_value(client, ADM1021_REG_REM_THYST_PREC);
+ data->remote_temp_offset =
+ adm1021_read_value(client, ADM1021_REG_REM_OFFSET);
+ data->remote_temp_offset_prec =
+ adm1021_read_value(client, ADM1021_REG_REM_OFFSET_PREC);
+ }
+ data->last_updated = jiffies;
+ data->valid = 1;
+ }
+
+ up(&data->update_lock);
+}
+
+
+void adm1021_temp(struct i2c_client *client, int operation, int ctl_name,
+ int *nrels_mag, long *results)
+{
+ struct adm1021_data *data = client->data;
+ if (operation == SENSORS_PROC_REAL_INFO)
+ *nrels_mag = 0;
+ else if (operation == SENSORS_PROC_REAL_READ) {
+ adm1021_update_client(client);
+ results[0] = TEMP_FROM_REG(data->temp_os);
+ results[1] = TEMP_FROM_REG(data->temp_hyst);
+ results[2] = TEMP_FROM_REG(data->temp);
+ *nrels_mag = 3;
+ } else if (operation == SENSORS_PROC_REAL_WRITE) {
+ if (*nrels_mag >= 1) {
+ data->temp_os = TEMP_TO_REG(results[0]);
+ adm1021_write_value(client, ADM1021_REG_TOS_W,
+ data->temp_os);
+ }
+ if (*nrels_mag >= 2) {
+ data->temp_hyst = TEMP_TO_REG(results[1]);
+ adm1021_write_value(client, ADM1021_REG_THYST_W,
+ data->temp_hyst);
+ }
+ }
+}
+
+void adm1021_remote_temp(struct i2c_client *client, int operation,
+ int ctl_name, int *nrels_mag, long *results)
+{
+int prec=0;
+ struct adm1021_data *data = client->data;
+ if (operation == SENSORS_PROC_REAL_INFO)
+ if (data->type == adm1023) { *nrels_mag = 3; }
+ else { *nrels_mag = 0; }
+ else if (operation == SENSORS_PROC_REAL_READ) {
+ adm1021_update_client(client);
+ results[0] = TEMP_FROM_REG(data->remote_temp_os);
+ results[1] = TEMP_FROM_REG(data->remote_temp_hyst);
+ results[2] = TEMP_FROM_REG(data->remote_temp);
+ if (data->type == adm1023) {
+ results[0]=results[0]*1000 +
+ ((data->remote_temp_os_prec >> 5) * 125);
+ results[1]=results[1]*1000 +
+ ((data->remote_temp_hyst_prec >> 5) * 125);
+ results[2]=(TEMP_FROM_REG(data->remote_temp_offset)*1000) +
+ ((data->remote_temp_offset_prec >> 5) * 125);
+ results[3]=TEMP_FROM_REG(data->remote_temp)*1000 +
+ ((data->remote_temp_prec >> 5) * 125);
+ *nrels_mag = 4;
+ } else {
+ *nrels_mag = 3;
+ }
+ } else if (operation == SENSORS_PROC_REAL_WRITE) {
+ if (*nrels_mag >= 1) {
+ if (data->type == adm1023) {
+ prec=((results[0]-((results[0]/1000)*1000))/125)<<5;
+ adm1021_write_value(client,
+ ADM1021_REG_REM_TOS_PREC,
+ prec);
+ results[0]=results[0]/1000;
+ data->remote_temp_os_prec=prec;
+ }
+ data->remote_temp_os = TEMP_TO_REG(results[0]);
+ adm1021_write_value(client,
+ ADM1021_REG_REMOTE_TOS_W,
+ data->remote_temp_os);
+ }
+ if (*nrels_mag >= 2) {
+ if (data->type == adm1023) {
+ prec=((results[1]-((results[1]/1000)*1000))/125)<<5;
+ adm1021_write_value(client,
+ ADM1021_REG_REM_THYST_PREC,
+ prec);
+ results[1]=results[1]/1000;
+ data->remote_temp_hyst_prec=prec;
+ }
+ data->remote_temp_hyst = TEMP_TO_REG(results[1]);
+ adm1021_write_value(client,
+ ADM1021_REG_REMOTE_THYST_W,
+ data->remote_temp_hyst);
+ }
+ if (*nrels_mag >= 3) {
+ if (data->type == adm1023) {
+ prec=((results[2]-((results[2]/1000)*1000))/125)<<5;
+ adm1021_write_value(client,
+ ADM1021_REG_REM_OFFSET_PREC,
+ prec);
+ results[2]=results[2]/1000;
+ data->remote_temp_offset_prec=prec;
+ data->remote_temp_offset=results[2];
+ adm1021_write_value(client,
+ ADM1021_REG_REM_OFFSET,
+ data->remote_temp_offset);
+ }
+ }
+ }
+}
+
+void adm1021_die_code(struct i2c_client *client, int operation,
+ int ctl_name, int *nrels_mag, long *results)
+{
+ struct adm1021_data *data = client->data;
+ if (operation == SENSORS_PROC_REAL_INFO)
+ *nrels_mag = 0;
+ else if (operation == SENSORS_PROC_REAL_READ) {
+ adm1021_update_client(client);
+ results[0] = data->die_code;
+ *nrels_mag = 1;
+ } else if (operation == SENSORS_PROC_REAL_WRITE) {
+ /* Can't write to it */
+ }
+}
+
+void adm1021_alarms(struct i2c_client *client, int operation, int ctl_name,
+ int *nrels_mag, long *results)
+{
+ struct adm1021_data *data = client->data;
+ if (operation == SENSORS_PROC_REAL_INFO)
+ *nrels_mag = 0;
+ else if (operation == SENSORS_PROC_REAL_READ) {
+ adm1021_update_client(client);
+ results[0] = data->alarms;
+ *nrels_mag = 1;
+ } else if (operation == SENSORS_PROC_REAL_WRITE) {
+ /* Can't write to it */
+ }
+}
+
+static int __init sensors_adm1021_init(void)
+{
+
+ return i2c_add_driver(&adm1021_driver);
+}
+
+static void __exit sensors_adm1021_exit(void)
+{
+ i2c_del_driver(&adm1021_driver);
+}
+
+MODULE_AUTHOR
+ ("Frodo Looijaard <frodol@dds.nl> and Philip Edelbrock <phil@netroedge.com>");
+MODULE_DESCRIPTION("adm1021 driver");
+MODULE_LICENSE("GPL");
+
+MODULE_PARM(read_only, "i");
+MODULE_PARM_DESC(read_only, "Don't set any values, read only mode");
+
+module_init(sensors_adm1021_init)
+module_exit(sensors_adm1021_exit)
diff --git a/drivers/i2c/chips/lm75.c b/drivers/i2c/chips/lm75.c
new file mode 100644
index 000000000000..83b08f63c421
--- /dev/null
+++ b/drivers/i2c/chips/lm75.c
@@ -0,0 +1,361 @@
+/*
+ lm75.c - Part of lm_sensors, Linux kernel modules for hardware
+ monitoring
+ Copyright (c) 1998, 1999 Frodo Looijaard <frodol@dds.nl>
+
+ 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/sensors.h>
+#include <linux/init.h>
+
+
+/* Addresses to scan */
+static unsigned short normal_i2c[] = { SENSORS_I2C_END };
+static unsigned short normal_i2c_range[] = { 0x48, 0x4f, SENSORS_I2C_END };
+static unsigned int normal_isa[] = { SENSORS_ISA_END };
+static unsigned int normal_isa_range[] = { SENSORS_ISA_END };
+
+/* Insmod parameters */
+SENSORS_INSMOD_1(lm75);
+
+/* Many LM75 constants specified below */
+
+/* The LM75 registers */
+#define LM75_REG_TEMP 0x00
+#define LM75_REG_CONF 0x01
+#define LM75_REG_TEMP_HYST 0x02
+#define LM75_REG_TEMP_OS 0x03
+
+/* Conversions. Rounding and limit checking is only done on the TO_REG
+ variants. Note that you should be a bit careful with which arguments
+ these macros are called: arguments may be evaluated more than once.
+ Fixing this is just not worth it. */
+#define TEMP_FROM_REG(val) ((((val & 0x7fff) >> 7) * 5) | ((val & 0x8000)?-256:0))
+#define TEMP_TO_REG(val) (SENSORS_LIMIT((val<0?(0x200+((val)/5))<<7:(((val) + 2) / 5) << 7),0,0xffff))
+
+/* Initial values */
+#define LM75_INIT_TEMP_OS 600
+#define LM75_INIT_TEMP_HYST 500
+
+/* Each client has this additional data */
+struct lm75_data {
+ int sysctl_id;
+
+ struct semaphore update_lock;
+ char valid; /* !=0 if following fields are valid */
+ unsigned long last_updated; /* In jiffies */
+
+ u16 temp, temp_os, temp_hyst; /* Register values */
+};
+
+static int lm75_attach_adapter(struct i2c_adapter *adapter);
+static int lm75_detect(struct i2c_adapter *adapter, int address,
+ unsigned short flags, int kind);
+static void lm75_init_client(struct i2c_client *client);
+static int lm75_detach_client(struct i2c_client *client);
+static int lm75_command(struct i2c_client *client, unsigned int cmd,
+ void *arg);
+static void lm75_inc_use(struct i2c_client *client);
+static void lm75_dec_use(struct i2c_client *client);
+static u16 swap_bytes(u16 val);
+static int lm75_read_value(struct i2c_client *client, u8 reg);
+static int lm75_write_value(struct i2c_client *client, u8 reg, u16 value);
+static void lm75_temp(struct i2c_client *client, int operation,
+ int ctl_name, int *nrels_mag, long *results);
+static void lm75_update_client(struct i2c_client *client);
+
+
+/* This is the driver that will be inserted */
+static struct i2c_driver lm75_driver = {
+ /* name */ "LM75 sensor chip driver",
+ /* id */ I2C_DRIVERID_LM75,
+ /* flags */ I2C_DF_NOTIFY,
+ /* attach_adapter */ &lm75_attach_adapter,
+ /* detach_client */ &lm75_detach_client,
+ /* command */ &lm75_command,
+ /* inc_use */ &lm75_inc_use,
+ /* dec_use */ &lm75_dec_use
+};
+
+/* These files are created for each detected LM75. This is just a template;
+ though at first sight, you might think we could use a statically
+ allocated list, we need some way to get back to the parent - which
+ is done through one of the 'extra' fields which are initialized
+ when a new copy is allocated. */
+static ctl_table lm75_dir_table_template[] = {
+ {LM75_SYSCTL_TEMP, "temp", NULL, 0, 0644, NULL, &i2c_proc_real,
+ &i2c_sysctl_real, NULL, &lm75_temp},
+ {0}
+};
+
+static int lm75_id = 0;
+
+int lm75_attach_adapter(struct i2c_adapter *adapter)
+{
+ return i2c_detect(adapter, &addr_data, lm75_detect);
+}
+
+/* This function is called by i2c_detect */
+int lm75_detect(struct i2c_adapter *adapter, int address,
+ unsigned short flags, int kind)
+{
+ int i, cur, conf, hyst, os;
+ struct i2c_client *new_client;
+ struct lm75_data *data;
+ int err = 0;
+ const char *type_name, *client_name;
+
+ /* Make sure we aren't probing the ISA bus!! This is just a safety check
+ at this moment; i2c_detect really won't call us. */
+#ifdef DEBUG
+ if (i2c_is_isa_adapter(adapter)) {
+ printk
+ ("lm75.o: lm75_detect called for an ISA bus adapter?!?\n");
+ return 0;
+ }
+#endif
+
+ if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA |
+ I2C_FUNC_SMBUS_WORD_DATA))
+ goto error0;
+
+ /* OK. For now, we presume we have a valid client. We now create the
+ client structure, even though we cannot fill it completely yet.
+ But it allows us to access lm75_{read,write}_value. */
+ if (!(new_client = kmalloc(sizeof(struct i2c_client) +
+ sizeof(struct lm75_data),
+ GFP_KERNEL))) {
+ err = -ENOMEM;
+ goto error0;
+ }
+
+ data = (struct lm75_data *) (new_client + 1);
+ new_client->addr = address;
+ new_client->data = data;
+ new_client->adapter = adapter;
+ new_client->driver = &lm75_driver;
+ new_client->flags = 0;
+
+ /* Now, we do the remaining detection. It is lousy. */
+ if (kind < 0) {
+ cur = i2c_smbus_read_word_data(new_client, 0);
+ conf = i2c_smbus_read_byte_data(new_client, 1);
+ hyst = i2c_smbus_read_word_data(new_client, 2);
+ os = i2c_smbus_read_word_data(new_client, 3);
+ for (i = 0; i <= 0x1f; i++)
+ if (
+ (i2c_smbus_read_byte_data
+ (new_client, i * 8 + 1) != conf)
+ ||
+ (i2c_smbus_read_word_data
+ (new_client, i * 8 + 2) != hyst)
+ ||
+ (i2c_smbus_read_word_data
+ (new_client, i * 8 + 3) != os))
+ goto error1;
+ }
+
+ /* Determine the chip type - only one kind supported! */
+ if (kind <= 0)
+ kind = lm75;
+
+ if (kind == lm75) {
+ type_name = "lm75";
+ client_name = "LM75 chip";
+ } else {
+ pr_debug("lm75.o: Internal error: unknown kind (%d)?!?", kind);
+ goto error1;
+ }
+
+ /* Fill in the remaining client fields and put it into the global list */
+ strcpy(new_client->name, client_name);
+
+ new_client->id = lm75_id++;
+ data->valid = 0;
+ init_MUTEX(&data->update_lock);
+
+ /* Tell the I2C layer a new client has arrived */
+ if ((err = i2c_attach_client(new_client)))
+ goto error3;
+
+ /* Register a new directory entry with module sensors */
+ if ((i = i2c_register_entry(new_client, type_name,
+ lm75_dir_table_template,
+ THIS_MODULE)) < 0) {
+ err = i;
+ goto error4;
+ }
+ data->sysctl_id = i;
+
+ lm75_init_client(new_client);
+ return 0;
+
+/* OK, this is not exactly good programming practice, usually. But it is
+ very code-efficient in this case. */
+
+ error4:
+ i2c_detach_client(new_client);
+ error3:
+ error1:
+ kfree(new_client);
+ error0:
+ return err;
+}
+
+int lm75_detach_client(struct i2c_client *client)
+{
+ int err;
+
+#ifdef MODULE
+ if (MOD_IN_USE)
+ return -EBUSY;
+#endif
+
+ i2c_deregister_entry(((struct lm75_data *) (client->data))->
+ sysctl_id);
+
+ if ((err = i2c_detach_client(client))) {
+ printk
+ ("lm75.o: Client deregistration failed, client not detached.\n");
+ return err;
+ }
+
+ kfree(client);
+
+ return 0;
+}
+
+int lm75_command(struct i2c_client *client, unsigned int cmd, void *arg)
+{
+ return 0;
+}
+
+void lm75_inc_use(struct i2c_client *client)
+{
+ MOD_INC_USE_COUNT;
+}
+
+void lm75_dec_use(struct i2c_client *client)
+{
+ MOD_DEC_USE_COUNT;
+}
+
+u16 swap_bytes(u16 val)
+{
+ return (val >> 8) | (val << 8);
+}
+
+/* All registers are word-sized, except for the configuration register.
+ LM75 uses a high-byte first convention, which is exactly opposite to
+ the usual practice. */
+int lm75_read_value(struct i2c_client *client, u8 reg)
+{
+ if (reg == LM75_REG_CONF)
+ return i2c_smbus_read_byte_data(client, reg);
+ else
+ return swap_bytes(i2c_smbus_read_word_data(client, reg));
+}
+
+/* All registers are word-sized, except for the configuration register.
+ LM75 uses a high-byte first convention, which is exactly opposite to
+ the usual practice. */
+int lm75_write_value(struct i2c_client *client, u8 reg, u16 value)
+{
+ if (reg == LM75_REG_CONF)
+ return i2c_smbus_write_byte_data(client, reg, value);
+ else
+ return i2c_smbus_write_word_data(client, reg,
+ swap_bytes(value));
+}
+
+void lm75_init_client(struct i2c_client *client)
+{
+ /* Initialize the LM75 chip */
+ lm75_write_value(client, LM75_REG_TEMP_OS,
+ TEMP_TO_REG(LM75_INIT_TEMP_OS));
+ lm75_write_value(client, LM75_REG_TEMP_HYST,
+ TEMP_TO_REG(LM75_INIT_TEMP_HYST));
+ lm75_write_value(client, LM75_REG_CONF, 0);
+}
+
+void lm75_update_client(struct i2c_client *client)
+{
+ struct lm75_data *data = client->data;
+
+ down(&data->update_lock);
+
+ if ((jiffies - data->last_updated > HZ + HZ / 2) ||
+ (jiffies < data->last_updated) || !data->valid) {
+ pr_debug("Starting lm75 update\n");
+
+ data->temp = lm75_read_value(client, LM75_REG_TEMP);
+ data->temp_os = lm75_read_value(client, LM75_REG_TEMP_OS);
+ data->temp_hyst =
+ lm75_read_value(client, LM75_REG_TEMP_HYST);
+ data->last_updated = jiffies;
+ data->valid = 1;
+ }
+
+ up(&data->update_lock);
+}
+
+
+void lm75_temp(struct i2c_client *client, int operation, int ctl_name,
+ int *nrels_mag, long *results)
+{
+ struct lm75_data *data = client->data;
+ if (operation == SENSORS_PROC_REAL_INFO)
+ *nrels_mag = 1;
+ else if (operation == SENSORS_PROC_REAL_READ) {
+ lm75_update_client(client);
+ results[0] = TEMP_FROM_REG(data->temp_os);
+ results[1] = TEMP_FROM_REG(data->temp_hyst);
+ results[2] = TEMP_FROM_REG(data->temp);
+ *nrels_mag = 3;
+ } else if (operation == SENSORS_PROC_REAL_WRITE) {
+ if (*nrels_mag >= 1) {
+ data->temp_os = TEMP_TO_REG(results[0]);
+ lm75_write_value(client, LM75_REG_TEMP_OS,
+ data->temp_os);
+ }
+ if (*nrels_mag >= 2) {
+ data->temp_hyst = TEMP_TO_REG(results[1]);
+ lm75_write_value(client, LM75_REG_TEMP_HYST,
+ data->temp_hyst);
+ }
+ }
+}
+
+int __init sensors_lm75_init(void)
+{
+ return i2c_add_driver(&lm75_driver);
+}
+
+static void __exit sensors_lm75_exit(void)
+{
+ i2c_del_driver(&lm75_driver);
+}
+
+MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>");
+MODULE_DESCRIPTION("LM75 driver");
+MODULE_LICENSE("GPL");
+
+module_init(sensors_lm75_init);
+module_exit(sensors_lm75_exit);
diff --git a/drivers/i2c/i2c-adap-ite.c b/drivers/i2c/i2c-adap-ite.c
index 46ba5149995b..9e2904c0f5e8 100644
--- a/drivers/i2c/i2c-adap-ite.c
+++ b/drivers/i2c/i2c-adap-ite.c
@@ -160,19 +160,17 @@ static void iic_ite_handler(int this_irq, void *dev_id, struct pt_regs *regs)
*/
static int iic_hw_resrc_init(void)
{
- if (check_region(gpi.iic_base, ITE_IIC_IO_SIZE) < 0 ) {
- return -ENODEV;
- } else {
- request_region(gpi.iic_base, ITE_IIC_IO_SIZE,
- "i2c (i2c bus adapter)");
- }
- if (gpi.iic_irq > 0) {
- if (request_irq(gpi.iic_irq, iic_ite_handler, 0, "ITE IIC", 0) < 0) {
- gpi.iic_irq = 0;
- } else
- DEB3(printk("Enabled IIC IRQ %d\n", gpi.iic_irq));
- enable_irq(gpi.iic_irq);
- }
+ if (!request_region(gpi.iic_base, ITE_IIC_IO_SIZE, "i2c"))
+ return -ENODEV;
+
+ if (gpi.iic_irq <= 0)
+ return 0;
+
+ if (request_irq(gpi.iic_irq, iic_ite_handler, 0, "ITE IIC", 0) < 0)
+ gpi.iic_irq = 0;
+ else
+ enable_irq(gpi.iic_irq);
+
return 0;
}
diff --git a/drivers/i2c/i2c-algo-bit.c b/drivers/i2c/i2c-algo-bit.c
index 60d6da9c9eaf..9551f0d27e6f 100644
--- a/drivers/i2c/i2c-algo-bit.c
+++ b/drivers/i2c/i2c-algo-bit.c
@@ -605,18 +605,9 @@ int i2c_bit_del_bus(struct i2c_adapter *adap)
return 0;
}
-int __init i2c_algo_bit_init (void)
-{
- printk(KERN_INFO "i2c-algo-bit.o: i2c bit algorithm module version %s (%s)\n", I2C_VERSION, I2C_DATE);
- return 0;
-}
-
-
-
EXPORT_SYMBOL(i2c_bit_add_bus);
EXPORT_SYMBOL(i2c_bit_del_bus);
-#ifdef MODULE
MODULE_AUTHOR("Simon G. Vogl <simon@tk.uni-linz.ac.at>");
MODULE_DESCRIPTION("I2C-Bus bit-banging algorithm");
MODULE_LICENSE("GPL");
@@ -629,13 +620,3 @@ MODULE_PARM_DESC(bit_test, "Test the lines of the bus to see if it is stuck");
MODULE_PARM_DESC(bit_scan, "Scan for active chips on the bus");
MODULE_PARM_DESC(i2c_debug,
"debug level - 0 off; 1 normal; 2,3 more verbose; 9 bit-protocol");
-
-int init_module(void)
-{
- return i2c_algo_bit_init();
-}
-
-void cleanup_module(void)
-{
-}
-#endif
diff --git a/drivers/i2c/i2c-algo-pcf.c b/drivers/i2c/i2c-algo-pcf.c
index 407656271ce5..000b34a84d4c 100644
--- a/drivers/i2c/i2c-algo-pcf.c
+++ b/drivers/i2c/i2c-algo-pcf.c
@@ -520,17 +520,9 @@ int i2c_pcf_del_bus(struct i2c_adapter *adap)
return 0;
}
-int __init i2c_algo_pcf_init (void)
-{
- printk(KERN_INFO "i2c-algo-pcf.o: i2c pcf8584 algorithm module version %s (%s)\n", I2C_VERSION, I2C_DATE);
- return 0;
-}
-
-
EXPORT_SYMBOL(i2c_pcf_add_bus);
EXPORT_SYMBOL(i2c_pcf_del_bus);
-#ifdef MODULE
MODULE_AUTHOR("Hans Berglund <hb@spacetec.no>");
MODULE_DESCRIPTION("I2C-Bus PCF8584 algorithm");
MODULE_LICENSE("GPL");
@@ -541,14 +533,3 @@ MODULE_PARM(i2c_debug,"i");
MODULE_PARM_DESC(pcf_scan, "Scan for active chips on the bus");
MODULE_PARM_DESC(i2c_debug,
"debug level - 0 off; 1 normal; 2,3 more verbose; 9 pcf-protocol");
-
-
-int init_module(void)
-{
- return i2c_algo_pcf_init();
-}
-
-void cleanup_module(void)
-{
-}
-#endif
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index 0716d42479f7..4ddcb6a26401 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -21,7 +21,7 @@
All SMBus-related things are written by Frodo Looijaard <frodol@dds.nl>
SMBus 2.0 support by Mark Studebaker <mdsxyz123@yahoo.com> */
-/* $Id: i2c-core.c,v 1.86 2002/09/12 06:47:26 ac9410 Exp $ */
+/* $Id: i2c-core.c,v 1.89 2002/11/03 16:47:16 mds Exp $ */
#include <linux/module.h>
#include <linux/kernel.h>
@@ -56,8 +56,8 @@
/* ----- global variables -------------------------------------------------- */
/**** lock for writing to global variables: the adapter & driver list */
-struct semaphore adap_lock;
-struct semaphore driver_lock;
+DECLARE_MUTEX(adap_lock);
+DECLARE_MUTEX(driver_lock);
/**** adapter list */
static struct i2c_adapter *adapters[I2C_ADAP_MAX];
@@ -76,10 +76,6 @@ static int i2c_debug;
*/
#ifdef CONFIG_PROC_FS
-
-static int i2cproc_init(void);
-static int i2cproc_cleanup(void);
-
static ssize_t i2cproc_bus_read(struct file * file, char * buf,size_t count,
loff_t *ppos);
static int read_bus_i2c(char *buf, char **start, off_t offset, int len,
@@ -90,14 +86,6 @@ static int read_bus_i2c(char *buf, char **start, off_t offset, int len,
static struct file_operations i2cproc_operations = {
.read = i2cproc_bus_read,
};
-
-static int i2cproc_initialized = 0;
-
-#else /* undef CONFIG_PROC_FS */
-
-#define i2cproc_init() 0
-#define i2cproc_cleanup() 0
-
#endif /* CONFIG_PROC_FS */
@@ -135,8 +123,7 @@ int i2c_add_adapter(struct i2c_adapter *adap)
init_MUTEX(&adap->lock);
#ifdef CONFIG_PROC_FS
-
- if (i2cproc_initialized) {
+ {
char name[8];
struct proc_dir_entry *proc_entry;
@@ -154,7 +141,6 @@ int i2c_add_adapter(struct i2c_adapter *adap)
proc_entry->owner = THIS_MODULE;
adap->inode = proc_entry->low_ino;
}
-
#endif /* def CONFIG_PROC_FS */
/* inform drivers of new adapters */
@@ -233,10 +219,10 @@ int i2c_del_adapter(struct i2c_adapter *adap)
}
}
#ifdef CONFIG_PROC_FS
- if (i2cproc_initialized) {
+ {
char name[8];
sprintf(name,"i2c-%d", i);
- remove_proc_entry(name,proc_bus);
+ remove_proc_entry(name, proc_bus);
}
#endif /* def CONFIG_PROC_FS */
@@ -680,41 +666,30 @@ ssize_t i2cproc_bus_read(struct file * file, char * buf,size_t count,
return -ENOENT;
}
-int i2cproc_init(void)
+static int i2cproc_init(void)
{
struct proc_dir_entry *proc_bus_i2c;
- i2cproc_initialized = 0;
-
- if (! proc_bus) {
- printk(KERN_ERR "i2c-core.o: /proc/bus/ does not exist");
- i2cproc_cleanup();
- return -ENOENT;
- }
proc_bus_i2c = create_proc_entry("i2c",0,proc_bus);
if (!proc_bus_i2c) {
printk(KERN_ERR "i2c-core.o: Could not create /proc/bus/i2c");
- i2cproc_cleanup();
return -ENOENT;
}
+
proc_bus_i2c->read_proc = &read_bus_i2c;
proc_bus_i2c->owner = THIS_MODULE;
- i2cproc_initialized += 2;
return 0;
}
-int i2cproc_cleanup(void)
+static void __exit i2cproc_cleanup(void)
{
- if (i2cproc_initialized >= 1) {
- remove_proc_entry("i2c",proc_bus);
- i2cproc_initialized -= 2;
- }
- return 0;
+ remove_proc_entry("i2c",proc_bus);
}
-
+module_init(i2cproc_init);
+module_exit(i2cproc_cleanup);
#endif /* def CONFIG_PROC_FS */
/* ----------------------------------------------------
@@ -1332,15 +1307,15 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr,
if (read_write == I2C_SMBUS_READ) {
msg[1].len = I2C_SMBUS_I2C_BLOCK_MAX;
} else {
- msg[0].len = data->block[0] + 2;
- if (msg[0].len > I2C_SMBUS_I2C_BLOCK_MAX + 2) {
+ msg[0].len = data->block[0] + 1;
+ if (msg[0].len > I2C_SMBUS_I2C_BLOCK_MAX + 1) {
printk("i2c-core.o: i2c_smbus_xfer_emulated called with "
"invalid block write size (%d)\n",
data->block[0]);
return -1;
}
- for (i = 0; i < data->block[0]; i++)
- msgbuf0[i] = data->block[i+1];
+ for (i = 1; i <= data->block[0]; i++)
+ msgbuf0[i] = data->block[i];
}
break;
default:
@@ -1439,120 +1414,6 @@ int i2c_check_functionality (struct i2c_adapter *adap, u32 func)
return (func & adap_func) == func;
}
-
-static int __init i2c_init(void)
-{
- printk(KERN_INFO "i2c-core.o: i2c core module version %s (%s)\n", I2C_VERSION, I2C_DATE);
- memset(adapters,0,sizeof(adapters));
- memset(drivers,0,sizeof(drivers));
- adap_count=0;
- driver_count=0;
-
- init_MUTEX(&adap_lock);
- init_MUTEX(&driver_lock);
-
- i2cproc_init();
-
- return 0;
-}
-
-static void __exit i2c_exit(void)
-{
- i2cproc_cleanup();
-}
-
-#ifndef MODULE
-#ifdef CONFIG_I2C_CHARDEV
- extern int i2c_dev_init(void);
-#endif
-#ifdef CONFIG_I2C_ALGOBIT
- extern int i2c_algo_bit_init(void);
-#endif
-#ifdef CONFIG_I2C_PHILIPSPAR
- extern int i2c_bitlp_init(void);
-#endif
-#ifdef CONFIG_I2C_ELV
- extern int i2c_bitelv_init(void);
-#endif
-#ifdef CONFIG_I2C_VELLEMAN
- extern int i2c_bitvelle_init(void);
-#endif
-#ifdef CONFIG_I2C_BITVIA
- extern int i2c_bitvia_init(void);
-#endif
-
-#ifdef CONFIG_I2C_ALGOPCF
- extern int i2c_algo_pcf_init(void);
-#endif
-#ifdef CONFIG_I2C_ELEKTOR
- extern int i2c_pcfisa_init(void);
-#endif
-
-#ifdef CONFIG_I2C_ALGO8XX
- extern int i2c_algo_8xx_init(void);
-#endif
-#ifdef CONFIG_I2C_RPXLITE
- extern int i2c_rpx_init(void);
-#endif
-#ifdef CONFIG_I2C_PROC
- extern int sensors_init(void);
-#endif
-
-/* This is needed for automatic patch generation: sensors code starts here */
-/* This is needed for automatic patch generation: sensors code ends here */
-
-int __init i2c_init_all(void)
-{
- /* --------------------- global ----- */
- i2c_init();
-
-#ifdef CONFIG_I2C_CHARDEV
- i2c_dev_init();
-#endif
- /* --------------------- bit -------- */
-#ifdef CONFIG_I2C_ALGOBIT
- i2c_algo_bit_init();
-#endif
-#ifdef CONFIG_I2C_PHILIPSPAR
- i2c_bitlp_init();
-#endif
-#ifdef CONFIG_I2C_ELV
- i2c_bitelv_init();
-#endif
-#ifdef CONFIG_I2C_VELLEMAN
- i2c_bitvelle_init();
-#endif
-
- /* --------------------- pcf -------- */
-#ifdef CONFIG_I2C_ALGOPCF
- i2c_algo_pcf_init();
-#endif
-#ifdef CONFIG_I2C_ELEKTOR
- i2c_pcfisa_init();
-#endif
-
- /* --------------------- 8xx -------- */
-#ifdef CONFIG_I2C_ALGO8XX
- i2c_algo_8xx_init();
-#endif
-#ifdef CONFIG_I2C_RPXLITE
- i2c_rpx_init();
-#endif
-
- /* -------------- proc interface ---- */
-#ifdef CONFIG_I2C_PROC
- sensors_init();
-#endif
-/* This is needed for automatic patch generation: sensors code starts here */
-/* This is needed for automatic patch generation: sensors code ends here */
-
- return 0;
-}
-
-#endif
-
-
-
EXPORT_SYMBOL(i2c_add_adapter);
EXPORT_SYMBOL(i2c_del_adapter);
EXPORT_SYMBOL(i2c_add_driver);
@@ -1593,9 +1454,7 @@ EXPORT_SYMBOL(i2c_check_functionality);
MODULE_AUTHOR("Simon G. Vogl <simon@tk.uni-linz.ac.at>");
MODULE_DESCRIPTION("I2C-Bus main module");
-MODULE_PARM(i2c_debug, "i");
-MODULE_PARM_DESC(i2c_debug,"debug level");
MODULE_LICENSE("GPL");
-module_init(i2c_init);
-module_exit(i2c_exit);
+MODULE_PARM(i2c_debug, "i");
+MODULE_PARM_DESC(i2c_debug,"debug level");
diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c
index 73c20b3069be..a702cc953dc7 100644
--- a/drivers/i2c/i2c-dev.c
+++ b/drivers/i2c/i2c-dev.c
@@ -28,7 +28,7 @@
/* The devfs code is contributed by Philipp Matthias Hahn
<pmhahn@titan.lahn.de> */
-/* $Id: i2c-dev.c,v 1.46 2002/07/06 02:07:39 mds Exp $ */
+/* $Id: i2c-dev.c,v 1.48 2002/10/01 14:10:04 ac9410 Exp $ */
#include <linux/config.h>
#include <linux/kernel.h>
@@ -433,19 +433,6 @@ static int i2cdev_command(struct i2c_client *client, unsigned int cmd,
return -1;
}
-static void i2cdev_cleanup(void)
-{
- int res;
-
- if ((res = i2c_del_driver(&i2cdev_driver))) {
- printk(KERN_ERR "i2c-dev.o: Driver deregistration failed, "
- "module not removed.\n");
- }
-
- devfs_remove("i2c");
- unregister_chrdev(I2C_MAJOR,"i2c");
-}
-
int __init i2c_dev_init(void)
{
int res;
@@ -467,11 +454,16 @@ int __init i2c_dev_init(void)
return 0;
}
-EXPORT_NO_SYMBOLS;
+static void __exit i2c_dev_exit(void)
+{
+ i2c_del_driver(&i2cdev_driver);
+ devfs_remove("i2c");
+ unregister_chrdev(I2C_MAJOR,"i2c");
+}
MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl> and Simon G. Vogl <simon@tk.uni-linz.ac.at>");
MODULE_DESCRIPTION("I2C /dev entries driver");
MODULE_LICENSE("GPL");
module_init(i2c_dev_init);
-module_exit(i2cdev_cleanup);
+module_exit(i2c_dev_exit);
diff --git a/drivers/i2c/i2c-elektor.c b/drivers/i2c/i2c-elektor.c
index d6c37f8bdd05..f142e72e9b75 100644
--- a/drivers/i2c/i2c-elektor.c
+++ b/drivers/i2c/i2c-elektor.c
@@ -142,11 +142,11 @@ static void pcf_isa_handler(int this_irq, void *dev_id, struct pt_regs *regs) {
static int pcf_isa_init(void)
{
if (!mmapped) {
- if (check_region(base, 2) < 0 ) {
- printk(KERN_ERR "i2c-elektor.o: requested I/O region (0x%X:2) is in use.\n", base);
+ if (!request_region(base, 2, "i2c (isa bus adapter)"))
+ printk(KERN_ERR
+ "i2c-elektor.o: requested I/O region (0x%X:2) "
+ "is in use.\n", base);
return -ENODEV;
- } else {
- request_region(base, 2, "i2c (isa bus adapter)");
}
}
if (irq > 0) {
@@ -159,19 +159,6 @@ static int pcf_isa_init(void)
return 0;
}
-
-static void pcf_isa_exit(void)
-{
- if (irq > 0) {
- disable_irq(irq);
- free_irq(irq, 0);
- }
- if (!mmapped) {
- release_region(base , 2);
- }
-}
-
-
static int pcf_isa_reg(struct i2c_client *client)
{
return 0;
@@ -223,7 +210,7 @@ static struct i2c_adapter pcf_isa_ops = {
.client_unregister = pcf_isa_unreg,
};
-int __init i2c_pcfisa_init(void)
+static int __init i2c_pcfisa_init(void)
{
#ifdef __alpha__
/* check to see we have memory mapped PCF8584 connected to the
@@ -281,23 +268,39 @@ int __init i2c_pcfisa_init(void)
}
init_waitqueue_head(&pcf_wait);
- if (pcf_isa_init() == 0) {
- if (i2c_pcf_add_bus(&pcf_isa_ops) < 0) {
- pcf_isa_exit();
- return -ENODEV;
- }
- } else {
+ if (pcf_isa_init())
return -ENODEV;
- }
+ if (i2c_pcf_add_bus(&pcf_isa_ops) < 0)
+ goto fail;
printk(KERN_ERR "i2c-elektor.o: found device at %#x.\n", base);
return 0;
+
+ fail:
+ if (irq > 0) {
+ disable_irq(irq);
+ free_irq(irq, 0);
+ }
+
+ if (!mmapped)
+ release_region(base , 2);
+ return -ENODEV;
}
-EXPORT_NO_SYMBOLS;
+static void i2c_pcfisa_exit(void)
+{
+ i2c_pcf_del_bus(&pcf_isa_ops);
+
+ if (irq > 0) {
+ disable_irq(irq);
+ free_irq(irq, 0);
+ }
+
+ if (!mmapped)
+ release_region(base , 2);
+}
-#ifdef MODULE
MODULE_AUTHOR("Hans Berglund <hb@spacetec.no>");
MODULE_DESCRIPTION("I2C-Bus adapter routines for PCF8584 ISA bus adapter");
MODULE_LICENSE("GPL");
@@ -309,15 +312,5 @@ MODULE_PARM(own, "i");
MODULE_PARM(mmapped, "i");
MODULE_PARM(i2c_debug, "i");
-int init_module(void)
-{
- return i2c_pcfisa_init();
-}
-
-void cleanup_module(void)
-{
- i2c_pcf_del_bus(&pcf_isa_ops);
- pcf_isa_exit();
-}
-
-#endif
+module_init(i2c_pcfisa_init);
+module_exit(i2c_pcfisa_exit);
diff --git a/drivers/i2c/i2c-elv.c b/drivers/i2c/i2c-elv.c
index c1ad9f5ed63b..a11ba27ffa2e 100644
--- a/drivers/i2c/i2c-elv.c
+++ b/drivers/i2c/i2c-elv.c
@@ -88,34 +88,31 @@ static int bit_elv_getsda(void *data)
static int bit_elv_init(void)
{
- if (check_region(base,(base == 0x3bc)? 3 : 8) < 0 ) {
- return -ENODEV;
- } else {
- /* test for ELV adap. */
- if (inb(base+1) & 0x80) { /* BUSY should be high */
- DEBINIT(printk(KERN_DEBUG "i2c-elv.o: Busy was low.\n"));
- return -ENODEV;
- } else {
- outb(0x0c,base+2); /* SLCT auf low */
- udelay(400);
- if ( !(inb(base+1) && 0x10) ) {
- outb(0x04,base+2);
- DEBINIT(printk(KERN_DEBUG "i2c-elv.o: Select was high.\n"));
- return -ENODEV;
- }
- }
- request_region(base,(base == 0x3bc)? 3 : 8,
- "i2c (ELV adapter)");
- PortData = 0;
- bit_elv_setsda((void*)base,1);
- bit_elv_setscl((void*)base,1);
+ if (!request_region(base, (base == 0x3bc) ? 3 : 8,
+ "i2c (ELV adapter)"))
+ return -ENODEV;
+
+ if (inb(base+1) & 0x80) { /* BUSY should be high */
+ DEBINIT(printk(KERN_DEBUG "i2c-elv.o: Busy was low.\n"));
+ goto fail;
+ }
+
+ outb(0x0c,base+2); /* SLCT auf low */
+ udelay(400);
+ if (!(inb(base+1) && 0x10)) {
+ outb(0x04,base+2);
+ DEBINIT(printk(KERN_DEBUG "i2c-elv.o: Select was high.\n"));
+ goto fail;
}
+
+ PortData = 0;
+ bit_elv_setsda((void*)base,1);
+ bit_elv_setscl((void*)base,1);
return 0;
-}
-static void __exit bit_elv_exit(void)
-{
- release_region( base , (base == 0x3bc)? 3 : 8 );
+fail:
+ release_region(base , (base == 0x3bc) ? 3 : 8);
+ return -ENODEV;
}
static int bit_elv_reg(struct i2c_client *client)
@@ -166,7 +163,7 @@ static struct i2c_adapter bit_elv_ops = {
bit_elv_unreg,
};
-int __init i2c_bitelv_init(void)
+static int __init i2c_bitelv_init(void)
{
printk(KERN_INFO "i2c-elv.o: i2c ELV parallel port adapter module version %s (%s)\n", I2C_VERSION, I2C_DATE);
if (base==0) {
@@ -192,24 +189,17 @@ int __init i2c_bitelv_init(void)
return 0;
}
+static void __exit i2c_bitelv_exit(void)
+{
+ i2c_bit_del_bus(&bit_elv_ops);
+ release_region(base , (base == 0x3bc) ? 3 : 8);
+}
-#ifdef MODULE
MODULE_AUTHOR("Simon G. Vogl <simon@tk.uni-linz.ac.at>");
MODULE_DESCRIPTION("I2C-Bus adapter routines for ELV parallel port adapter");
MODULE_LICENSE("GPL");
-
MODULE_PARM(base, "i");
-int init_module(void)
-{
- return i2c_bitelv_init();
-}
-
-void cleanup_module(void)
-{
- i2c_bit_del_bus(&bit_elv_ops);
- bit_elv_exit();
-}
-
-#endif
+module_init(i2c_bitelv_init);
+module_exit(i2c_bitelv_exit);
diff --git a/drivers/i2c/i2c-frodo.c b/drivers/i2c/i2c-frodo.c
index de38a02e29de..634a4ac46457 100644
--- a/drivers/i2c/i2c-frodo.c
+++ b/drivers/i2c/i2c-frodo.c
@@ -96,8 +96,6 @@ static int __init i2c_frodo_init (void)
return (i2c_bit_add_bus (&frodo_ops));
}
-EXPORT_NO_SYMBOLS;
-
static void __exit i2c_frodo_exit (void)
{
i2c_bit_del_bus (&frodo_ops);
@@ -105,12 +103,7 @@ static void __exit i2c_frodo_exit (void)
MODULE_AUTHOR ("Abraham van der Merwe <abraham@2d3d.co.za>");
MODULE_DESCRIPTION ("I2C-Bus adapter routines for Frodo");
-
-#ifdef MODULE_LICENSE
MODULE_LICENSE ("GPL");
-#endif /* #ifdef MODULE_LICENSE */
-
-EXPORT_NO_SYMBOLS;
module_init (i2c_frodo_init);
module_exit (i2c_frodo_exit);
diff --git a/drivers/i2c/i2c-philips-par.c b/drivers/i2c/i2c-philips-par.c
index c26e74304724..be9a49f146b8 100644
--- a/drivers/i2c/i2c-philips-par.c
+++ b/drivers/i2c/i2c-philips-par.c
@@ -297,14 +297,5 @@ MODULE_LICENSE("GPL");
MODULE_PARM(type, "i");
-#ifdef MODULE
-int init_module(void)
-{
- return i2c_bitlp_init();
-}
-
-void cleanup_module(void)
-{
- i2c_bitlp_exit();
-}
-#endif
+module_init(i2c_bitlp_init);
+module_exit(i2c_bitlp_exit);
diff --git a/drivers/i2c/i2c-proc.c b/drivers/i2c/i2c-proc.c
index 6c6d4903a023..2273dbf684f9 100644
--- a/drivers/i2c/i2c-proc.c
+++ b/drivers/i2c/i2c-proc.c
@@ -56,6 +56,7 @@ static int i2c_sysctl_chips(ctl_table * table, int *name, int nlen,
#define SENSORS_ENTRY_MAX 20
static struct ctl_table_header *i2c_entries[SENSORS_ENTRY_MAX];
+static unsigned short i2c_inodes[SENSORS_ENTRY_MAX];
static struct i2c_client *i2c_clients[SENSORS_ENTRY_MAX];
@@ -87,7 +88,6 @@ static ctl_table i2c_proc[] = {
static struct ctl_table_header *i2c_proc_header;
-static int i2c_initialized;
/* This returns a nice name for a new directory; for example lm78-isa-0310
(for a LM78 chip on the ISA bus at port 0x310), or lm75-i2c-3-4e (for
@@ -186,6 +186,8 @@ int i2c_register_entry(struct i2c_client *client, const char *prefix,
return id;
}
#endif /* DEBUG */
+ i2c_inodes[id - 256] =
+ new_header->ctl_table->child->child->de->low_ino;
new_header->ctl_table->child->child->de->owner = controlling_mod;
return id;
@@ -208,6 +210,49 @@ void i2c_deregister_entry(int id)
}
}
+/* Monitor access for /proc/sys/dev/sensors; make unloading i2c-proc.o
+ impossible if some process still uses it or some file in it */
+void i2c_fill_inode(struct inode *inode, int fill)
+{
+ if (fill)
+ MOD_INC_USE_COUNT;
+ else
+ MOD_DEC_USE_COUNT;
+}
+
+/* Monitor access for /proc/sys/dev/sensors/ directories; make unloading
+ the corresponding module impossible if some process still uses it or
+ some file in it */
+void i2c_dir_fill_inode(struct inode *inode, int fill)
+{
+ int i;
+ struct i2c_client *client;
+
+#ifdef DEBUG
+ if (!inode) {
+ printk(KERN_ERR "i2c-proc.o: Warning: inode NULL in fill_inode()\n");
+ return;
+ }
+#endif /* def DEBUG */
+
+ for (i = 0; i < SENSORS_ENTRY_MAX; i++)
+ if (i2c_clients[i]
+ && (i2c_inodes[i] == inode->i_ino)) break;
+#ifdef DEBUG
+ if (i == SENSORS_ENTRY_MAX) {
+ printk
+ (KERN_ERR "i2c-proc.o: Warning: inode (%ld) not found in fill_inode()\n",
+ inode->i_ino);
+ return;
+ }
+#endif /* def DEBUG */
+ client = i2c_clients[i];
+ if (fill)
+ client->driver->inc_use(client);
+ else
+ client->driver->dec_use(client);
+}
+
int i2c_proc_chips(ctl_table * ctl, int write, struct file *filp,
void *buffer, size_t * lenp)
{
@@ -598,6 +643,7 @@ int i2c_detect(struct i2c_adapter *adapter,
I2C_FUNC_SMBUS_QUICK)) return -1;
for (addr = 0x00; addr <= (is_isa ? 0xffff : 0x7f); addr++) {
+ /* XXX: WTF is going on here??? */
if ((is_isa && check_region(addr, 1)) ||
(!is_isa && i2c_check_addr(adapter, addr)))
continue;
@@ -798,10 +844,9 @@ int i2c_detect(struct i2c_adapter *adapter,
return 0;
}
-int __init sensors_init(void)
+static int __init i2c_proc_init(void)
{
printk(KERN_INFO "i2c-proc.o version %s (%s)\n", I2C_VERSION, I2C_DATE);
- i2c_initialized = 0;
if (!
(i2c_proc_header =
register_sysctl_table(i2c_proc, 0))) {
@@ -809,16 +854,12 @@ int __init sensors_init(void)
return -EPERM;
}
i2c_proc_header->ctl_table->child->de->owner = THIS_MODULE;
- i2c_initialized++;
return 0;
}
-static void __exit i2c_cleanup(void)
+static void __exit i2c_proc_exit(void)
{
- if (i2c_initialized >= 1) {
- unregister_sysctl_table(i2c_proc_header);
- i2c_initialized--;
- }
+ unregister_sysctl_table(i2c_proc_header);
}
EXPORT_SYMBOL(i2c_deregister_entry);
@@ -831,5 +872,5 @@ MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>");
MODULE_DESCRIPTION("i2c-proc driver");
MODULE_LICENSE("GPL");
-module_init(sensors_init);
-module_exit(i2c_cleanup);
+module_init(i2c_proc_init);
+module_exit(i2c_proc_exit);
diff --git a/drivers/i2c/i2c-rpx.c b/drivers/i2c/i2c-rpx.c
index af9a6368c3c2..a449ae9c8724 100644
--- a/drivers/i2c/i2c-rpx.c
+++ b/drivers/i2c/i2c-rpx.c
@@ -126,11 +126,8 @@ void __exit i2c_rpx_exit(void)
i2c_8xx_del_bus(&rpx_ops);
}
-#ifdef MODULE
MODULE_AUTHOR("Dan Malek <dmalek@jlc.net>");
MODULE_DESCRIPTION("I2C-Bus adapter routines for MPC8xx boards");
module_init(i2c_rpx_init);
module_exit(i2c_rpx_exit);
-#endif
-
diff --git a/drivers/i2c/i2c-velleman.c b/drivers/i2c/i2c-velleman.c
index 71d8934a94a1..9ae1a20cc868 100644
--- a/drivers/i2c/i2c-velleman.c
+++ b/drivers/i2c/i2c-velleman.c
@@ -102,12 +102,6 @@ static int bit_velle_init(void)
return 0;
}
-static void __exit bit_velle_exit(void)
-{
- release_region( base , (base == 0x3bc)? 3 : 8 );
-}
-
-
static int bit_velle_reg(struct i2c_client *client)
{
return 0;
@@ -157,7 +151,7 @@ static struct i2c_adapter bit_velle_ops = {
bit_velle_unreg,
};
-int __init i2c_bitvelle_init(void)
+static int __init i2c_bitvelle_init(void)
{
printk(KERN_INFO "i2c-velleman.o: i2c Velleman K8000 adapter module version %s (%s)\n", I2C_VERSION, I2C_DATE);
if (base==0) {
@@ -183,22 +177,17 @@ int __init i2c_bitvelle_init(void)
return 0;
}
-#ifdef MODULE
+static void __exit i2c_bitvelle_exit(void)
+{
+ i2c_bit_del_bus(&bit_velle_ops);
+ release_region(base, (base == 0x3bc) ? 3 : 8);
+}
+
MODULE_AUTHOR("Simon G. Vogl <simon@tk.uni-linz.ac.at>");
MODULE_DESCRIPTION("I2C-Bus adapter routines for Velleman K8000 adapter");
MODULE_LICENSE("GPL");
MODULE_PARM(base, "i");
-int init_module(void)
-{
- return i2c_bitvelle_init();
-}
-
-void cleanup_module(void)
-{
- i2c_bit_del_bus(&bit_velle_ops);
- bit_velle_exit();
-}
-
-#endif
+module_init(i2c_bitvelle_init);
+module_exit(i2c_bitvelle_exit);
diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c
index 89e956d8b011..64ee462aaa97 100644
--- a/drivers/ide/ide-io.c
+++ b/drivers/ide/ide-io.c
@@ -743,7 +743,7 @@ void ide_do_request (ide_hwgroup_t *hwgroup, int masked_irq)
ide_startstop_t startstop;
/* for atari only: POSSIBLY BROKEN HERE(?) */
- ide_get_lock(&ide_intr_lock, ide_intr, hwgroup);
+ ide_get_lock(ide_intr, hwgroup);
/* necessary paranoia: ensure IRQs are masked on local CPU */
local_irq_disable();
@@ -783,7 +783,7 @@ void ide_do_request (ide_hwgroup_t *hwgroup, int masked_irq)
*/
/* for atari only */
- ide_release_lock(&ide_intr_lock);
+ ide_release_lock();
hwgroup->busy = 0;
}
diff --git a/drivers/ide/ide-timing.h b/drivers/ide/ide-timing.h
index c1196ce15b4d..cb42f1180b86 100644
--- a/drivers/ide/ide-timing.h
+++ b/drivers/ide/ide-timing.h
@@ -245,6 +245,14 @@ static int ide_timing_compute(ide_drive_t *drive, short speed, struct ide_timing
}
/*
+ * If the drive is an ATAPI device it may need slower address setup timing,
+ * so we stay on the safe side.
+ */
+
+ if (drive->media != ide_disk)
+ p.setup = 120;
+
+/*
* Convert the timing to bus clock counts.
*/
diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c
index 9b4130b92ae6..0ae396abfcc1 100644
--- a/drivers/ide/ide.c
+++ b/drivers/ide/ide.c
@@ -181,14 +181,6 @@ spinlock_t ide_lock __cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED;
static int ide_scan_direction; /* THIS was formerly 2.2.x pci=reverse */
-#ifdef IDE_ARCH_LOCK
-/*
- * ide_lock is used by the Atari code to obtain access to the IDE interrupt,
- * which is shared between several drivers.
- */
-static int ide_intr_lock;
-#endif /* IDE_ARCH_LOCK */
-
#ifdef CONFIG_IDEDMA_AUTO
int noautodma = 0;
#else
@@ -1344,14 +1336,12 @@ int ata_attach(ide_drive_t *drive)
continue;
spin_unlock(&drivers_lock);
if (driver->attach(drive) == 0) {
- if (driver->owner)
- __MOD_DEC_USE_COUNT(driver->owner);
+ module_put(driver->owner);
drive->gendev.driver = &driver->gen_driver;
return 0;
}
spin_lock(&drivers_lock);
- if (driver->owner)
- __MOD_DEC_USE_COUNT(driver->owner);
+ module_put(driver->owner);
}
spin_unlock(&drivers_lock);
spin_lock(&drives_lock);
@@ -2097,12 +2087,12 @@ void __init ide_init_builtin_drivers (void)
#ifdef CONFIG_BLK_DEV_IDE
if (ide_hwifs[0].io_ports[IDE_DATA_OFFSET])
- ide_get_lock(&ide_intr_lock, NULL, NULL); /* for atari only */
+ ide_get_lock(NULL, NULL); /* for atari only */
(void) ideprobe_init();
if (ide_hwifs[0].io_ports[IDE_DATA_OFFSET])
- ide_release_lock(&ide_intr_lock); /* for atari only */
+ ide_release_lock(); /* for atari only */
#endif /* CONFIG_BLK_DEV_IDE */
#ifdef CONFIG_PROC_FS
diff --git a/drivers/ide/legacy/falconide.c b/drivers/ide/legacy/falconide.c
index 407276e6aab3..b0babb4acc08 100644
--- a/drivers/ide/legacy/falconide.c
+++ b/drivers/ide/legacy/falconide.c
@@ -49,6 +49,14 @@ static int falconide_offsets[IDE_NR_PORTS] __initdata = {
/*
+ * falconide_intr_lock is used to obtain access to the IDE interrupt,
+ * which is shared between several drivers.
+ */
+
+int falconide_intr_lock;
+
+
+ /*
* Probe for a Falcon IDE interface
*/
diff --git a/drivers/ieee1394/ieee1394_core.c b/drivers/ieee1394/ieee1394_core.c
index 0b251ee098c1..b5e00b4b12b5 100644
--- a/drivers/ieee1394/ieee1394_core.c
+++ b/drivers/ieee1394/ieee1394_core.c
@@ -1135,28 +1135,19 @@ static int ieee1394_dispatch_open(struct inode *inode, struct file *file)
unloading while the file is open, and will be
dropped by the VFS when the file is released.
*/
-
- if(THIS_MODULE)
- __MOD_DEC_USE_COUNT((struct module*) THIS_MODULE);
-
- /* note that if ieee1394 is compiled into the kernel,
- THIS_MODULE will be (void*) NULL, hence the if and
- the cast are necessary */
-
+ module_put(THIS_MODULE);
} else {
-
- /* if the open() failed, then we need to drop the
- extra reference we gave to the task-specific
- driver */
-
- if(module)
- __MOD_DEC_USE_COUNT(module);
-
/* point the file's f_ops back to ieee1394. The VFS will then
decrement ieee1394's reference count immediately after this
function returns. */
file->f_op = &ieee1394_chardev_ops;
+
+ /* if the open() failed, then we need to drop the
+ extra reference we gave to the task-specific
+ driver */
+ module_put(module);
+
}
return retval;
diff --git a/drivers/input/joystick/amijoy.c b/drivers/input/joystick/amijoy.c
index 0ff0a3c54cff..f51ff785d0ab 100644
--- a/drivers/input/joystick/amijoy.c
+++ b/drivers/input/joystick/amijoy.c
@@ -34,6 +34,7 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/input.h>
+#include <linux/interrupt.h>
#include <asm/system.h>
#include <asm/amigahw.h>
diff --git a/drivers/input/joystick/iforce/iforce-usb.c b/drivers/input/joystick/iforce/iforce-usb.c
index 673ed522f1cf..63cf238d6be3 100644
--- a/drivers/input/joystick/iforce/iforce-usb.c
+++ b/drivers/input/joystick/iforce/iforce-usb.c
@@ -174,7 +174,7 @@ static int iforce_usb_probe(struct usb_interface *intf,
if (iforce_init_device(iforce)) goto fail;
- dev_set_drvdata (&intf->dev, iforce);
+ usb_set_intfdata(intf, iforce);
return 0;
fail:
@@ -203,10 +203,10 @@ void iforce_usb_delete(struct iforce* iforce)
static void iforce_usb_disconnect(struct usb_interface *intf)
{
- struct iforce *iforce = dev_get_drvdata (&intf->dev);
+ struct iforce *iforce = usb_get_intfdata(intf);
int open = 0; /* FIXME! iforce->dev.handle->open; */
- dev_set_drvdata (&intf->dev, NULL);
+ usb_set_intfdata(intf, NULL);
if (iforce) {
iforce->usbdev = NULL;
input_unregister_device(&iforce->dev);
diff --git a/drivers/input/keyboard/amikbd.c b/drivers/input/keyboard/amikbd.c
index d0a5b7617fd3..5e1cea29ffb2 100644
--- a/drivers/input/keyboard/amikbd.c
+++ b/drivers/input/keyboard/amikbd.c
@@ -35,6 +35,7 @@
#include <linux/init.h>
#include <linux/input.h>
#include <linux/delay.h>
+#include <linux/interrupt.h>
#include <asm/amigaints.h>
#include <asm/amigahw.h>
diff --git a/drivers/input/mouse/amimouse.c b/drivers/input/mouse/amimouse.c
index 91b9de9c5d47..f89593c4f4bf 100644
--- a/drivers/input/mouse/amimouse.c
+++ b/drivers/input/mouse/amimouse.c
@@ -20,6 +20,7 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/input.h>
+#include <linux/interrupt.h>
#include <asm/irq.h>
#include <asm/setup.h>
diff --git a/drivers/input/serio/q40kbd.c b/drivers/input/serio/q40kbd.c
index c54b7317e59f..ad69eedf557e 100644
--- a/drivers/input/serio/q40kbd.c
+++ b/drivers/input/serio/q40kbd.c
@@ -34,6 +34,7 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/serio.h>
+#include <linux/interrupt.h>
#include <asm/keyboard.h>
#include <asm/bitops.h>
@@ -54,7 +55,6 @@ static int q40kbd_open(struct serio *port)
}
static void q40kbd_close(struct serio *port)
{
- return 0;
}
static struct serio q40kbd_port =
@@ -69,8 +69,6 @@ static struct serio q40kbd_port =
static void q40kbd_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
- unsigned long flags;
-
if (IRQ_KEYB_MASK & master_inb(INTERRUPT_REG))
if (q40kbd_port.dev)
q40kbd_port.dev->interrupt(&q40kbd_port, master_inb(KEYCODE_REG), 0);
diff --git a/drivers/isdn/capi/kcapi.c b/drivers/isdn/capi/kcapi.c
index 949a9497b0b5..337124784e9c 100644
--- a/drivers/isdn/capi/kcapi.c
+++ b/drivers/isdn/capi/kcapi.c
@@ -91,8 +91,7 @@ capi_ctr_get(struct capi_ctr *card)
static inline void
capi_ctr_put(struct capi_ctr *card)
{
- if (card->owner)
- __MOD_DEC_USE_COUNT(card->owner);
+ module_put(card->owner);
DBG("MOD_COUNT DEC");
}
diff --git a/drivers/isdn/hisax/st5481_b.c b/drivers/isdn/hisax/st5481_b.c
index cf0d582ca83d..769eb5e7cc4d 100644
--- a/drivers/isdn/hisax/st5481_b.c
+++ b/drivers/isdn/hisax/st5481_b.c
@@ -152,7 +152,7 @@ static void led_blink(struct st5481_adapter *adapter)
st5481_usb_device_ctrl_msg(adapter, GPIO_OUT, leds, NULL, NULL);
}
-static void usb_b_out_complete(struct urb *urb)
+static void usb_b_out_complete(struct urb *urb, struct pt_regs *regs)
{
struct st5481_bcs *bcs = urb->context;
struct st5481_b_out *b_out = &bcs->b_out;
diff --git a/drivers/isdn/hisax/st5481_d.c b/drivers/isdn/hisax/st5481_d.c
index 02feec24fbb4..b8008955aeee 100644
--- a/drivers/isdn/hisax/st5481_d.c
+++ b/drivers/isdn/hisax/st5481_d.c
@@ -370,7 +370,7 @@ static void fifo_reseted(void *context)
FsmEvent(&adapter->d_out.fsm, EV_DOUT_RESETED, NULL);
}
-static void usb_d_out_complete(struct urb *urb)
+static void usb_d_out_complete(struct urb *urb, struct pt_regs *regs)
{
struct st5481_adapter *adapter = urb->context;
struct st5481_d_out *d_out = &adapter->d_out;
diff --git a/drivers/isdn/hisax/st5481_init.c b/drivers/isdn/hisax/st5481_init.c
index 703fa4b1f9d7..e3329417b55d 100644
--- a/drivers/isdn/hisax/st5481_init.c
+++ b/drivers/isdn/hisax/st5481_init.c
@@ -114,7 +114,7 @@ static int probe_st5481(struct usb_interface *intf,
hisax_register(&adapter->hisax_d_if, b_if, "st5481_usb", protocol);
st5481_start(adapter);
- dev_set_drvdata(&intf->dev, adapter);
+ usb_set_intfdata(intf, adapter);
return 0;
err_b:
@@ -133,11 +133,11 @@ static int probe_st5481(struct usb_interface *intf,
*/
static void disconnect_st5481(struct usb_interface *intf)
{
- struct st5481_adapter *adapter = dev_get_drvdata(&intf->dev);
+ struct st5481_adapter *adapter = usb_get_intfdata(intf);
DBG(1,"");
- dev_set_drvdata(&intf->dev, NULL);
+ usb_set_intfdata(intf, NULL);
if (!adapter)
return;
diff --git a/drivers/isdn/hisax/st5481_usb.c b/drivers/isdn/hisax/st5481_usb.c
index 13a13d10a95c..4170ea091fa6 100644
--- a/drivers/isdn/hisax/st5481_usb.c
+++ b/drivers/isdn/hisax/st5481_usb.c
@@ -474,7 +474,7 @@ void st5481_release_isocpipes(struct urb* urb[2])
* called 50 times per second with 20 ISOC descriptors.
* Called at interrupt.
*/
-static void usb_in_complete(struct urb *urb)
+static void usb_in_complete(struct urb *urb, struct pt_regs *regs)
{
struct st5481_in *in = urb->context;
unsigned char *ptr;
diff --git a/drivers/macintosh/adb-iop.c b/drivers/macintosh/adb-iop.c
index cf0504e0e233..9a2392ac290e 100644
--- a/drivers/macintosh/adb-iop.c
+++ b/drivers/macintosh/adb-iop.c
@@ -83,15 +83,14 @@ static void adb_iop_complete(struct iop_msg *msg, struct pt_regs *regs)
struct adb_request *req;
uint flags;
- save_flags(flags);
- cli();
+ local_irq_save(flags);
req = current_req;
if ((adb_iop_state == sending) && req && req->reply_expected) {
adb_iop_state = awaiting_reply;
}
- restore_flags(flags);
+ local_irq_restore(flags);
}
/*
@@ -107,8 +106,7 @@ static void adb_iop_listen(struct iop_msg *msg, struct pt_regs *regs)
struct adb_request *req;
uint flags;
- save_flags(flags);
- cli();
+ local_irq_save(flags);
req = current_req;
@@ -150,7 +148,7 @@ static void adb_iop_listen(struct iop_msg *msg, struct pt_regs *regs)
memcpy(msg->reply, msg->message, IOP_MSG_LEN);
}
iop_complete_message(msg);
- restore_flags(flags);
+ local_irq_restore(flags);
}
/*
@@ -170,8 +168,7 @@ static void adb_iop_start(void)
req = current_req;
if (!req) return;
- save_flags(flags);
- cli();
+ local_irq_save(flags);
#ifdef DEBUG_ADB_IOP
printk("adb_iop_start: sending packet, %d bytes:", req->nbytes);
@@ -192,7 +189,7 @@ static void adb_iop_start(void)
req->sent = 1;
adb_iop_state = sending;
- restore_flags(flags);
+ local_irq_restore(flags);
/* Now send it. The IOP manager will call adb_iop_complete */
/* when the packet has been sent. */
@@ -236,8 +233,7 @@ static int adb_iop_write(struct adb_request *req)
return -EINVAL;
}
- save_flags(flags);
- cli();
+ local_irq_save(flags);
req->next = 0;
req->sent = 0;
@@ -252,7 +248,7 @@ static int adb_iop_write(struct adb_request *req)
last_req = req;
}
- restore_flags(flags);
+ local_irq_restore(flags);
if (adb_iop_state == idle) adb_iop_start();
return 0;
}
diff --git a/drivers/macintosh/via-cuda.c b/drivers/macintosh/via-cuda.c
index 38b2c1afdaba..32dcc992231e 100644
--- a/drivers/macintosh/via-cuda.c
+++ b/drivers/macintosh/via-cuda.c
@@ -18,6 +18,7 @@
#include <linux/adb.h>
#include <linux/cuda.h>
#include <linux/spinlock.h>
+#include <linux/interrupt.h>
#ifdef CONFIG_PPC
#include <asm/prom.h>
#include <asm/machdep.h>
diff --git a/drivers/macintosh/via-macii.c b/drivers/macintosh/via-macii.c
index 82cc3df633f1..0aa34eebe478 100644
--- a/drivers/macintosh/via-macii.c
+++ b/drivers/macintosh/via-macii.c
@@ -21,6 +21,7 @@
#include <linux/delay.h>
#include <linux/sched.h>
#include <linux/adb.h>
+#include <linux/interrupt.h>
#include <asm/macintosh.h>
#include <asm/macints.h>
#include <asm/machw.h>
@@ -144,8 +145,7 @@ int macii_init(void)
unsigned long flags;
int err;
- save_flags(flags);
- cli();
+ local_irq_save(flags);
err = macii_init_via();
if (err) return err;
@@ -155,7 +155,7 @@ int macii_init(void)
if (err) return err;
macii_state = idle;
- restore_flags(flags);
+ local_irq_restore(flags);
return 0;
}
@@ -196,13 +196,12 @@ static void macii_queue_poll(void)
adb_request(&req, NULL, ADBREQ_REPLY|ADBREQ_NOSEND, 1,
ADB_READREG(device, 0));
- save_flags(flags);
- cli();
+ local_irq_save(flags);
req.next = current_req;
current_req = &req;
- restore_flags(flags);
+ local_irq_restore(flags);
macii_start();
in_poll--;
}
@@ -221,8 +220,7 @@ static void macii_retransmit(int device)
adb_request(&rt, NULL, ADBREQ_REPLY|ADBREQ_NOSEND, 1,
ADB_READREG(device, 0));
- save_flags(flags);
- cli();
+ local_irq_save(flags);
if (current_req != NULL) {
last_req->next = &rt;
@@ -234,7 +232,7 @@ static void macii_retransmit(int device)
if (macii_state == idle) macii_start();
- restore_flags(flags);
+ local_irq_restore(flags);
in_retransmit--;
}
@@ -267,7 +265,7 @@ static int macii_write(struct adb_request *req)
req->complete = 0;
req->reply_len = 0;
- save_flags(flags); cli();
+ local_irq_save(flags);
if (current_req != NULL) {
last_req->next = req;
@@ -278,7 +276,7 @@ static int macii_write(struct adb_request *req)
if (macii_state == idle) macii_start();
}
- restore_flags(flags);
+ local_irq_restore(flags);
return 0;
}
@@ -296,9 +294,9 @@ static void macii_poll(void)
{
unsigned long flags;
- save_flags(flags); cli();
+ local_irq_save(flags);
if (via[IFR] & SR_INT) macii_interrupt(0, 0, 0);
- restore_flags(flags);
+ local_irq_restore(flags);
}
/* Reset the bus */
@@ -328,7 +326,7 @@ static void macii_start(void)
return;
}
- save_flags(flags); cli();
+ local_irq_save(flags);
/*
* IRQ signaled ?? (means ADB controller wants to send, or might
@@ -356,7 +354,7 @@ static void macii_start(void)
(uint) via[B] & (ST_MASK|TREQ));
retry_req = req;
/* set ADB status here ? */
- restore_flags(flags);
+ local_irq_restore(flags);
return;
} else {
need_poll = 0;
@@ -385,7 +383,7 @@ static void macii_start(void)
macii_state = sending;
data_index = 2;
- restore_flags(flags);
+ local_irq_restore(flags);
}
/*
@@ -421,10 +419,10 @@ void macii_interrupt(int irq, void *arg, struct pt_regs *regs)
last_status = status;
/* prevent races due to SCSI enabling ints */
- save_flags(flags); cli();
+ local_irq_save(flags);
if (driver_running) {
- restore_flags(flags);
+ local_irq_restore(flags);
return;
}
@@ -650,5 +648,5 @@ void macii_interrupt(int irq, void *arg, struct pt_regs *regs)
}
/* reset mutex and interrupts */
driver_running = 0;
- restore_flags(flags);
+ local_irq_restore(flags);
}
diff --git a/drivers/macintosh/via-maciisi.c b/drivers/macintosh/via-maciisi.c
index 7a32a295fd52..162ce3f2acd0 100644
--- a/drivers/macintosh/via-maciisi.c
+++ b/drivers/macintosh/via-maciisi.c
@@ -22,6 +22,7 @@
#include <linux/adb.h>
#include <linux/cuda.h>
#include <linux/delay.h>
+#include <linux/interrupt.h>
#include <asm/macintosh.h>
#include <asm/macints.h>
#include <asm/machw.h>
@@ -312,8 +313,7 @@ maciisi_write(struct adb_request* req)
req->complete = 0;
req->reply_len = 0;
- save_flags(flags);
- cli();
+ local_irq_save(flags);
if (current_req) {
last_req->next = req;
@@ -327,7 +327,7 @@ maciisi_write(struct adb_request* req)
i = maciisi_start();
if(i != 0)
{
- restore_flags(flags);
+ local_irq_restore(flags);
return i;
}
}
@@ -336,11 +336,11 @@ maciisi_write(struct adb_request* req)
#ifdef DEBUG_MACIISI_ADB
printk(KERN_DEBUG "maciisi_write: would start, but state is %d\n", maciisi_state);
#endif
- restore_flags(flags);
+ local_irq_restore(flags);
return -EBUSY;
}
- restore_flags(flags);
+ local_irq_restore(flags);
return 0;
}
@@ -401,15 +401,14 @@ maciisi_poll(void)
{
unsigned long flags;
- save_flags(flags);
- cli();
+ local_irq_save(flags);
if (via[IFR] & SR_INT) {
maciisi_interrupt(0, 0, 0);
}
else /* avoid calling this function too quickly in a loop */
udelay(ADB_DELAY);
- restore_flags(flags);
+ local_irq_restore(flags);
}
/* Shift register interrupt - this is *supposed* to mean that the
@@ -426,8 +425,7 @@ maciisi_interrupt(int irq, void* arg, struct pt_regs* regs)
int i;
unsigned long flags;
- save_flags(flags);
- cli();
+ local_irq_save(flags);
status = via[B] & (TIP|TREQ);
#ifdef DEBUG_MACIISI_ADB
@@ -437,7 +435,7 @@ maciisi_interrupt(int irq, void* arg, struct pt_regs* regs)
if (!(via[IFR] & SR_INT)) {
/* Shouldn't happen, we hope */
printk(KERN_ERR "maciisi_interrupt: called without interrupt flag set\n");
- restore_flags(flags);
+ local_irq_restore(flags);
return;
}
@@ -636,7 +634,7 @@ maciisi_interrupt(int irq, void* arg, struct pt_regs* regs)
default:
printk("maciisi_interrupt: unknown maciisi_state %d?\n", maciisi_state);
}
- restore_flags(flags);
+ local_irq_restore(flags);
}
static void
diff --git a/drivers/macintosh/via-pmu68k.c b/drivers/macintosh/via-pmu68k.c
index 50f62a8d2505..3bb653489391 100644
--- a/drivers/macintosh/via-pmu68k.c
+++ b/drivers/macintosh/via-pmu68k.c
@@ -28,6 +28,7 @@
#include <linux/pci.h>
#include <linux/slab.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/adb.h>
#include <linux/pmu.h>
@@ -495,7 +496,7 @@ pmu_queue_request(struct adb_request *req)
req->next = 0;
req->sent = 0;
req->complete = 0;
- save_flags(flags); cli();
+ local_irq_save(flags);
if (current_req != 0) {
last_req->next = req;
@@ -507,7 +508,7 @@ pmu_queue_request(struct adb_request *req)
pmu_start();
}
- restore_flags(flags);
+ local_irq_restore(flags);
return 0;
}
@@ -537,7 +538,7 @@ pmu_start()
/* assert pmu_state == idle */
/* get the packet to send */
- save_flags(flags); cli();
+ local_irq_save(flags);
req = current_req;
if (req == 0 || pmu_state != idle
|| (req->reply_expected && req_awaiting_reply))
@@ -551,16 +552,15 @@ pmu_start()
send_byte(req->data[0]);
out:
- restore_flags(flags);
+ local_irq_restore(flags);
}
void
pmu_poll()
{
- unsigned long cpu_flags;
+ unsigned long flags;
- save_flags(cpu_flags);
- cli();
+ local_irq_save(flags);
if (via1[IFR] & SR_INT) {
via1[IFR] = SR_INT;
pmu_interrupt(IRQ_MAC_ADB_SR, NULL, NULL);
@@ -569,7 +569,7 @@ pmu_poll()
via1[IFR] = CB1_INT;
pmu_interrupt(IRQ_MAC_ADB_CL, NULL, NULL);
}
- restore_flags(cpu_flags);
+ local_irq_restore(flags);
}
static void
@@ -963,9 +963,9 @@ int __openfirmware powerbook_sleep(void)
asm volatile("mfspr %0,1008" : "=r" (hid0) :);
hid0 = (hid0 & ~(HID0_NAP | HID0_DOZE)) | HID0_SLEEP;
asm volatile("mtspr 1008,%0" : : "r" (hid0));
- save_flags(msr);
+ local_save_flags(msr);
msr |= MSR_POW | MSR_EE;
- restore_flags(msr);
+ local_irq_restore(msr);
udelay(10);
/* OK, we're awake again, start restoring things */
diff --git a/drivers/md/dm-target.c b/drivers/md/dm-target.c
index 6bf8310ac1e9..886302cbd2b1 100644
--- a/drivers/md/dm-target.c
+++ b/drivers/md/dm-target.c
@@ -44,11 +44,11 @@ static struct tt_internal *get_target_type(const char *name)
read_lock(&_lock);
ti = __find_target_type(name);
-
- if (ti) {
- if (ti->use == 0 && ti->tt.module)
- __MOD_INC_USE_COUNT(ti->tt.module);
- ti->use++;
+ if (ti && ti->use == 0) {
+ if (try_module_get(ti->tt.module))
+ ti->use++;
+ else
+ ti = NULL;
}
read_unlock(&_lock);
@@ -86,8 +86,8 @@ void dm_put_target_type(struct target_type *t)
struct tt_internal *ti = (struct tt_internal *) t;
read_lock(&_lock);
- if (--ti->use == 0 && ti->tt.module)
- __MOD_DEC_USE_COUNT(ti->tt.module);
+ if (--ti->use == 0)
+ module_put(ti->tt.module);
if (ti->use < 0)
BUG();
diff --git a/drivers/media/dvb/dvb-core/dvb_i2c.c b/drivers/media/dvb/dvb-core/dvb_i2c.c
index e9a48ba1af9f..9eefbf4513d1 100644
--- a/drivers/media/dvb/dvb-core/dvb_i2c.c
+++ b/drivers/media/dvb/dvb-core/dvb_i2c.c
@@ -63,18 +63,11 @@ int register_i2c_client (struct dvb_i2c_bus *i2c, struct dvb_i2c_device *dev)
static
void try_attach_device (struct dvb_i2c_bus *i2c, struct dvb_i2c_device *dev)
{
- if (dev->owner) {
- if (!MOD_CAN_QUERY(dev->owner))
- return;
-
- __MOD_INC_USE_COUNT(dev->owner);
- }
-
- if (dev->attach (i2c) == 0) {
- register_i2c_client (i2c, dev);
- } else {
- if (dev->owner)
- __MOD_DEC_USE_COUNT(dev->owner);
+ if (try_module_get(dev->owner)) {
+ if (dev->attach(i2c) == 0)
+ register_i2c_client(i2c, dev);
+ else
+ module_put(dev->owner);
}
}
@@ -82,10 +75,8 @@ void try_attach_device (struct dvb_i2c_bus *i2c, struct dvb_i2c_device *dev)
static
void detach_device (struct dvb_i2c_bus *i2c, struct dvb_i2c_device *dev)
{
- dev->detach (i2c);
-
- if (dev->owner)
- __MOD_DEC_USE_COUNT(dev->owner);
+ dev->detach(i2c);
+ module_put(dev->owner);
}
diff --git a/drivers/media/video/cpia.c b/drivers/media/video/cpia.c
index 1abef42a5896..bcc26db53c6a 100644
--- a/drivers/media/video/cpia.c
+++ b/drivers/media/video/cpia.c
@@ -3158,8 +3158,7 @@ static int reset_camera(struct cam_data *cam)
static void put_cam(struct cpia_camera_ops* ops)
{
- if (ops->owner)
- __MOD_DEC_USE_COUNT(ops->owner);
+ module_put(ops->owner);
}
/* ------------------------- V4L interface --------------------- */
diff --git a/drivers/media/video/cpia_usb.c b/drivers/media/video/cpia_usb.c
index 1c01ef626204..4c4e968b95db 100644
--- a/drivers/media/video/cpia_usb.c
+++ b/drivers/media/video/cpia_usb.c
@@ -486,7 +486,7 @@ static int cpia_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
struct usb_device *udev = interface_to_usbdev(intf);
- struct usb_interface_descriptor *interface;
+ struct usb_host_interface *interface;
struct usb_cpia *ucpia;
struct cam_data *cam;
int ret;
@@ -508,7 +508,7 @@ static int cpia_probe(struct usb_interface *intf,
memset(ucpia, 0, sizeof(*ucpia));
ucpia->dev = udev;
- ucpia->iface = interface->bInterfaceNumber;
+ ucpia->iface = interface->desc.bInterfaceNumber;
init_waitqueue_head(&ucpia->wq_stream);
ucpia->buffers[0] = vmalloc(sizeof(*ucpia->buffers[0]));
@@ -552,7 +552,7 @@ static int cpia_probe(struct usb_interface *intf,
cpia_add_to_list(&cam_list, &cam);
spin_unlock( &cam_list_lock_usb );
- dev_set_drvdata(&intf->dev, cam);
+ usb_set_intfdata(intf, cam);
return 0;
fail_all:
@@ -593,11 +593,11 @@ static struct usb_driver cpia_driver = {
/* will do it for us as well as passing a udev structure - jerdfelt */
static void cpia_disconnect(struct usb_interface *intf)
{
- struct cam_data *cam = dev_get_drvdata(&intf->dev);
+ struct cam_data *cam = usb_get_intfdata(intf);
struct usb_cpia *ucpia;
struct usb_device *udev;
- dev_set_drvdata(&intf->dev, NULL);
+ usb_set_intfdata(intf, NULL);
if (!cam)
return;
diff --git a/drivers/mtd/chips/chipreg.c b/drivers/mtd/chips/chipreg.c
index da5512cd14e3..efdd7ee41d34 100644
--- a/drivers/mtd/chips/chipreg.c
+++ b/drivers/mtd/chips/chipreg.c
@@ -71,15 +71,13 @@ struct mtd_info *do_map_probe(char *name, struct map_info *map)
return NULL;
ret = drv->probe(map);
-#ifdef CONFIG_MODULES
+
/* We decrease the use count here. It may have been a
probe-only module, which is no longer required from this
point, having given us a handle on (and increased the use
count of) the actual driver code.
*/
- if(drv->module)
- __MOD_DEC_USE_COUNT(drv->module);
-#endif
+ module_put(drv->module);
if (ret)
return ret;
diff --git a/drivers/net/a2065.c b/drivers/net/a2065.c
index 7661224c7286..9c986c98384b 100644
--- a/drivers/net/a2065.c
+++ b/drivers/net/a2065.c
@@ -571,11 +571,10 @@ static int lance_start_xmit (struct sk_buff *skb, struct net_device *dev)
skblen = skb->len;
- save_flags(flags);
- cli();
+ local_irq_save(flags);
if (!TX_BUFFS_AVAIL){
- restore_flags(flags);
+ local_irq_restore(flags);
return -1;
}
@@ -616,7 +615,7 @@ static int lance_start_xmit (struct sk_buff *skb, struct net_device *dev)
dev->trans_start = jiffies;
dev_kfree_skb (skb);
- restore_flags(flags);
+ local_irq_restore(flags);
return status;
}
diff --git a/drivers/net/ariadne.c b/drivers/net/ariadne.c
index 9055f2a8317b..ea8272358c98 100644
--- a/drivers/net/ariadne.c
+++ b/drivers/net/ariadne.c
@@ -604,8 +604,7 @@ static int ariadne_start_xmit(struct sk_buff *skb, struct net_device *dev)
printk(" data 0x%08x len %d\n", (int)skb->data, (int)skb->len);
#endif
- save_flags(flags);
- cli();
+ local_irq_save(flags);
entry = priv->cur_tx % TX_RING_SIZE;
@@ -662,7 +661,7 @@ static int ariadne_start_xmit(struct sk_buff *skb, struct net_device *dev)
netif_stop_queue(dev);
priv->tx_full = 1;
}
- restore_flags(flags);
+ local_irq_restore(flags);
return 0;
}
@@ -765,13 +764,12 @@ static struct net_device_stats *ariadne_get_stats(struct net_device *dev)
short saved_addr;
unsigned long flags;
- save_flags(flags);
- cli();
+ local_irq_save(flags);
saved_addr = lance->RAP;
lance->RAP = CSR112; /* Missed Frame Count */
priv->stats.rx_missed_errors = swapw(lance->RDP);
lance->RAP = saved_addr;
- restore_flags(flags);
+ local_irq_restore(flags);
return &priv->stats;
}
diff --git a/drivers/net/atari_bionet.c b/drivers/net/atari_bionet.c
index 4dd5791c553c..1cd15dae2a5b 100644
--- a/drivers/net/atari_bionet.c
+++ b/drivers/net/atari_bionet.c
@@ -235,8 +235,7 @@ get_frame(unsigned long paddr, int odd) {
unsigned long flags;
DISABLE_IRQ();
- save_flags(flags);
- cli();
+ local_irq_save(flags);
dma_wd.dma_mode_status = 0x9a;
dma_wd.dma_mode_status = 0x19a;
@@ -247,7 +246,7 @@ get_frame(unsigned long paddr, int odd) {
dma_wd.dma_md = (unsigned char)paddr;
paddr >>= 8;
dma_wd.dma_hi = (unsigned char)paddr;
- restore_flags(flags);
+ local_irq_restore(flags);
c = sendcmd(0,0x00,NODE_ADR | C_READ); /* CMD: READ */
if( c < 128 ) goto rend;
@@ -284,8 +283,7 @@ hardware_send_packet(unsigned long paddr, int cnt) {
unsigned long flags;
DISABLE_IRQ();
- save_flags(flags);
- cli();
+ local_irq_save(flags);
dma_wd.dma_mode_status = 0x19a;
dma_wd.dma_mode_status = 0x9a;
@@ -297,7 +295,7 @@ hardware_send_packet(unsigned long paddr, int cnt) {
dma_wd.dma_hi = (unsigned char)paddr;
dma_wd.fdc_acces_seccount = 0x4; /* sector count */
- restore_flags(flags);
+ local_irq_restore(flags);
c = sendcmd(0,0x100,NODE_ADR | C_WRITE); /* CMD: WRITE */
c = sendcmd(1,0x100,cnt&0xff);
@@ -438,11 +436,10 @@ bionet_send_packet(struct sk_buff *skb, struct net_device *dev) {
/* Block a timer-based transmit from overlapping. This could better be
* done with atomic_swap(1, dev->tbusy), but set_bit() works as well.
*/
- save_flags(flags);
- cli();
+ local_irq_save(flags);
if (stdma_islocked()) {
- restore_flags(flags);
+ local_irq_restore(flags);
lp->stats.tx_errors++;
}
else {
@@ -451,7 +448,7 @@ bionet_send_packet(struct sk_buff *skb, struct net_device *dev) {
int stat;
stdma_lock(bionet_intr, NULL);
- restore_flags(flags);
+ local_irq_restore(flags);
if( !STRAM_ADDR(buf+length-1) ) {
memcpy(nic_packet->buffer, skb->data, length);
buf = (unsigned long)&((struct nic_pkt_s *)phys_nic_packet)->buffer;
@@ -504,20 +501,19 @@ bionet_poll_rx(struct net_device *dev) {
int pkt_len, status;
unsigned long flags;
- save_flags(flags);
- cli();
+ local_irq_save(flags);
/* ++roman: Take care at locking the ST-DMA... This must be done with ints
* off, since otherwise an int could slip in between the question and the
* locking itself, and then we'd go to sleep... And locking itself is
* necessary to keep the floppy_change timer from working with ST-DMA
* registers. */
if (stdma_islocked()) {
- restore_flags(flags);
+ local_irq_restore(flags);
return;
}
stdma_lock(bionet_intr, NULL);
DISABLE_IRQ();
- restore_flags(flags);
+ local_irq_restore(flags);
if( lp->poll_time < MAX_POLL_TIME ) lp->poll_time++;
diff --git a/drivers/net/atari_pamsnet.c b/drivers/net/atari_pamsnet.c
index c42659667d35..95d6640fabd5 100644
--- a/drivers/net/atari_pamsnet.c
+++ b/drivers/net/atari_pamsnet.c
@@ -702,11 +702,10 @@ pamsnet_send_packet(struct sk_buff *skb, struct net_device *dev) {
/* Block a timer-based transmit from overlapping. This could better be
* done with atomic_swap(1, dev->tbusy), but set_bit() works as well.
*/
- save_flags(flags);
- cli();
+ local_irq_save(flags);
if (stdma_islocked()) {
- restore_flags(flags);
+ local_irq_restore(flags);
lp->stats.tx_errors++;
}
else {
@@ -717,7 +716,7 @@ pamsnet_send_packet(struct sk_buff *skb, struct net_device *dev) {
stdma_lock(pamsnet_intr, NULL);
DISABLE_IRQ();
- restore_flags(flags);
+ local_irq_restore(flags);
if( !STRAM_ADDR(buf+length-1) ) {
memcpy(nic_packet->buffer, skb->data, length);
buf = (unsigned long)phys_nic_packet;
@@ -749,20 +748,19 @@ pamsnet_poll_rx(struct net_device *dev) {
struct sk_buff *skb;
unsigned long flags;
- save_flags(flags);
- cli();
+ local_irq_save(flags);
/* ++roman: Take care at locking the ST-DMA... This must be done with ints
* off, since otherwise an int could slip in between the question and the
* locking itself, and then we'd go to sleep... And locking itself is
* necessary to keep the floppy_change timer from working with ST-DMA
* registers. */
if (stdma_islocked()) {
- restore_flags(flags);
+ local_irq_restore(flags);
return;
}
stdma_lock(pamsnet_intr, NULL);
DISABLE_IRQ();
- restore_flags(flags);
+ local_irq_restore(flags);
boguscount = testpkt(lance_target);
if( lp->poll_time < MAX_POLL_TIME ) lp->poll_time++;
diff --git a/drivers/net/atarilance.c b/drivers/net/atarilance.c
index e8e91d299896..a23c024c1da1 100644
--- a/drivers/net/atarilance.c
+++ b/drivers/net/atarilance.c
@@ -402,8 +402,7 @@ static int __init addr_accessible( volatile void *regp, int wordflag, int writef
long flags;
long *vbr, save_berr;
- save_flags(flags);
- cli();
+ local_irq_save(flags);
__asm__ __volatile__ ( "movec %/vbr,%0" : "=r" (vbr) : );
save_berr = vbr[2];
@@ -440,7 +439,7 @@ static int __init addr_accessible( volatile void *regp, int wordflag, int writef
);
vbr[2] = save_berr;
- restore_flags(flags);
+ local_irq_restore(flags);
return( ret );
}
diff --git a/drivers/net/irda/irda-usb.c b/drivers/net/irda/irda-usb.c
index d9af92cccc80..b1bd18dbb347 100644
--- a/drivers/net/irda/irda-usb.c
+++ b/drivers/net/irda/irda-usb.c
@@ -1524,7 +1524,7 @@ static int irda_usb_probe(struct usb_interface *intf,
if (ret)
return -ENOMEM;
- dev_set_drvdata(&intf->dev, self);
+ usb_set_intfdata(intf, self);
return 0;
}
@@ -1543,12 +1543,12 @@ static int irda_usb_probe(struct usb_interface *intf,
static void irda_usb_disconnect(struct usb_interface *intf)
{
unsigned long flags;
- struct irda_usb_cb *self = dev_get_drvdata (&intf->dev);
+ struct irda_usb_cb *self = usb_get_intfdata(intf);
int i;
IRDA_DEBUG(1, "%s()\n", __FUNCTION__);
- dev_set_drvdata(&intf->dev, NULL);
+ usb_set_intfdata(intf, NULL);
if (!self)
return;
diff --git a/drivers/net/irda/sir_dev.c b/drivers/net/irda/sir_dev.c
index a73fe2c3db70..a27737026547 100644
--- a/drivers/net/irda/sir_dev.c
+++ b/drivers/net/irda/sir_dev.c
@@ -502,8 +502,7 @@ errout_stop:
errout_free:
sirdev_free_buffers(dev);
errout_dec:
- if (drv->owner)
- __MOD_DEC_USE_COUNT(drv->owner);
+ module_put(drv->owner);
return -EAGAIN;
}
@@ -533,11 +532,7 @@ static int sirdev_close(struct net_device *ndev)
drv->stop_dev(dev);
sirdev_free_buffers(dev);
-
- lock_kernel();
- if (drv->owner)
- __MOD_DEC_USE_COUNT(drv->owner);
- unlock_kernel();
+ module_put(drv->owner);
out:
dev->speed = 0;
diff --git a/drivers/net/irda/sir_dongle.c b/drivers/net/irda/sir_dongle.c
index 6384215dc27e..cf7a17a002d3 100644
--- a/drivers/net/irda/sir_dongle.c
+++ b/drivers/net/irda/sir_dongle.c
@@ -121,8 +121,7 @@ int sirdev_get_dongle(struct sir_dev *dev, IRDA_DONGLE type)
out_reject:
dev->dongle_drv = NULL;
- if (drv->owner)
- __MOD_DEC_USE_COUNT(drv->owner);
+ module_put(drv->owner);
out_unlock:
up(&dongle_list_lock);
return err;
@@ -137,9 +136,7 @@ int sirdev_put_dongle(struct sir_dev *dev)
drv->close(dev); /* close this dongle instance */
dev->dongle_drv = NULL; /* unlink the dongle driver */
-
- if (drv->owner)
- __MOD_DEC_USE_COUNT(drv->owner);/* decrement driver's module refcount */
+ module_put(drv->owner);/* decrement driver's module refcount */
}
return 0;
diff --git a/drivers/net/mac8390.c b/drivers/net/mac8390.c
index c6255c3b8f21..45c74135572f 100644
--- a/drivers/net/mac8390.c
+++ b/drivers/net/mac8390.c
@@ -194,7 +194,7 @@ int __init mac8390_memsize(unsigned long membase)
unsigned long flags;
int i, j;
- save_flags(flags); cli();
+ local_irq_save(flags);
/* Check up to 32K in 4K increments */
for (i = 0; i < 8; i++) {
volatile unsigned short *m = (unsigned short *) (membase + (i * 0x1000));
@@ -217,7 +217,7 @@ int __init mac8390_memsize(unsigned long membase)
break;
}
}
- restore_flags(flags);
+ local_irq_restore(flags);
/* in any case, we stopped once we tried one block too many,
or once we reached 32K */
return i * 0x1000;
diff --git a/drivers/net/mac89x0.c b/drivers/net/mac89x0.c
index ba9adba053a0..95f72759aa0f 100644
--- a/drivers/net/mac89x0.c
+++ b/drivers/net/mac89x0.c
@@ -52,7 +52,8 @@
Arnaldo Carvalho de Melo <acme@conectiva.com.br> - 11/01/2001
check kmalloc and release the allocated memory on failure in
mac89x0_probe and in init_module
- use save_flags/restore_flags in net_get_stat, not just cli/sti
+ use local_irq_{save,restore}(flags) in net_get_stat, not just
+ local_irq_{dis,en}able()
*/
static char *version =
@@ -199,11 +200,10 @@ int __init mac89x0_probe(struct net_device *dev)
unsigned long flags;
int card_present;
- save_flags(flags);
- cli();
+ local_irq_save(flags);
card_present = hwreg_present((void*) ioaddr+4)
&& hwreg_present((void*) ioaddr + DATA_PORT);
- restore_flags(flags);
+ local_irq_restore(flags);
if (!card_present)
return -ENODEV;
@@ -397,8 +397,7 @@ net_send_packet(struct sk_buff *skb, struct net_device *dev)
/* keep the upload from being interrupted, since we
ask the chip to start transmitting before the
whole packet has been completely uploaded. */
- save_flags(flags);
- cli();
+ local_irq_save(flags);
/* initiate a transmit sequence */
writereg(dev, PP_TxCMD, lp->send_cmd);
@@ -408,14 +407,14 @@ net_send_packet(struct sk_buff *skb, struct net_device *dev)
if ((readreg(dev, PP_BusST) & READY_FOR_TX_NOW) == 0) {
/* Gasp! It hasn't. But that shouldn't happen since
we're waiting for TxOk, so return 1 and requeue this packet. */
- restore_flags(flags);
+ local_irq_restore(flags);
return 1;
}
/* Write the contents of the packet */
memcpy_toio(dev->mem_start + PP_TxFrame, skb->data, skb->len+1);
- restore_flags(flags);
+ local_irq_restore(flags);
dev->trans_start = jiffies;
}
dev_kfree_skb (skb);
@@ -568,12 +567,11 @@ net_get_stats(struct net_device *dev)
struct net_local *lp = (struct net_local *)dev->priv;
unsigned long flags;
- save_flags(flags);
- cli();
+ local_irq_save(flags);
/* Update the statistics from the device registers. */
lp->stats.rx_missed_errors += (readreg(dev, PP_RxMiss) >> 6);
lp->stats.collisions += (readreg(dev, PP_TxCol) >> 6);
- restore_flags(flags);
+ local_irq_restore(flags);
return &lp->stats;
}
diff --git a/drivers/net/macmace.c b/drivers/net/macmace.c
index 7bab986b43b4..4e8a08b78804 100644
--- a/drivers/net/macmace.c
+++ b/drivers/net/macmace.c
@@ -256,8 +256,7 @@ static int mace_set_address(struct net_device *dev, void *addr)
unsigned long flags;
u8 maccc;
- save_flags(flags);
- cli();
+ local_irq_save(flags);
maccc = mb->maccc;
@@ -270,7 +269,7 @@ static int mace_set_address(struct net_device *dev, void *addr)
}
mb->maccc = maccc;
- restore_flags(flags);
+ local_irq_restore(flags);
return 0;
}
diff --git a/drivers/net/macsonic.c b/drivers/net/macsonic.c
index e87f5aad0542..16c7160e0eb0 100644
--- a/drivers/net/macsonic.c
+++ b/drivers/net/macsonic.c
@@ -332,10 +332,9 @@ int __init mac_onboard_sonic_probe(struct net_device* dev)
unsigned long flags;
int card_present;
- save_flags(flags);
- cli();
+ local_irq_save(flags);
card_present = hwreg_present((void*)ONBOARD_SONIC_REGISTERS);
- restore_flags(flags);
+ local_irq_restore(flags);
if (!card_present) {
printk("none.\n");
diff --git a/drivers/net/sun3_82586.c b/drivers/net/sun3_82586.c
index cdd2252d83cf..61b6e3be8557 100644
--- a/drivers/net/sun3_82586.c
+++ b/drivers/net/sun3_82586.c
@@ -1078,12 +1078,11 @@ static int sun3_82586_send_packet(struct sk_buff *skb, struct net_device *dev)
{
unsigned long flags;
- save_flags(flags);
- cli();
+ local_irq_save(flags);
if(p->xmit_count != p->xmit_last)
netif_wake_queue(dev);
p->lock = 0;
- restore_flags(flags);
+ local_irq_restore(flags);
}
dev_kfree_skb(skb);
#endif
diff --git a/drivers/net/sun3lance.c b/drivers/net/sun3lance.c
index ed2070e280f0..70dbe64a2612 100644
--- a/drivers/net/sun3lance.c
+++ b/drivers/net/sun3lance.c
@@ -574,7 +574,7 @@ static int lance_start_xmit( struct sk_buff *skb, struct net_device *dev )
#endif
/* We're not prepared for the int until the last flags are set/reset.
* And the int may happen already after setting the OWN_CHIP... */
- save_and_cli(flags);
+ local_irq_save(flags);
/* Mask to ring buffer boundary. */
entry = lp->new_tx;
@@ -610,7 +610,7 @@ static int lance_start_xmit( struct sk_buff *skb, struct net_device *dev )
TMD1_OWN_HOST)
netif_start_queue(dev);
- restore_flags(flags);
+ local_irq_restore(flags);
return 0;
}
diff --git a/drivers/nubus/nubus.c b/drivers/nubus/nubus.c
index d6cfff7ff8fa..14cbe34eb897 100644
--- a/drivers/nubus/nubus.c
+++ b/drivers/nubus/nubus.c
@@ -915,10 +915,9 @@ void __init nubus_probe_slot(int slot)
int card_present;
rp--;
- save_flags(flags);
- cli();
+ local_irq_save(flags);
card_present = hwreg_present(rp);
- restore_flags(flags);
+ local_irq_restore(flags);
if (!card_present)
continue;
diff --git a/drivers/parport/parport_amiga.c b/drivers/parport/parport_amiga.c
index b09e1f2d5441..d1caad0d6744 100644
--- a/drivers/parport/parport_amiga.c
+++ b/drivers/parport/parport_amiga.c
@@ -17,6 +17,7 @@
#include <linux/init.h>
#include <linux/parport.h>
#include <linux/ioport.h>
+#include <linux/interrupt.h>
#include <asm/setup.h>
#include <asm/amigahw.h>
#include <asm/irq.h>
diff --git a/drivers/parport/parport_atari.c b/drivers/parport/parport_atari.c
index ae831176b7b1..461b3ffa2a66 100644
--- a/drivers/parport/parport_atari.c
+++ b/drivers/parport/parport_atari.c
@@ -12,6 +12,7 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/parport.h>
+#include <linux/interrupt.h>
#include <asm/setup.h>
#include <asm/atarihw.h>
#include <asm/irq.h>
@@ -25,11 +26,10 @@ parport_atari_read_data(struct parport *p)
unsigned long flags;
unsigned char data;
- save_flags(flags);
- cli();
+ local_irq_save(flags);
sound_ym.rd_data_reg_sel = 15;
data = sound_ym.rd_data_reg_sel;
- restore_flags(flags);
+ local_irq_restore(flags);
return data;
}
@@ -38,11 +38,10 @@ parport_atari_write_data(struct parport *p, unsigned char data)
{
unsigned long flags;
- save_flags(flags);
- cli();
+ local_irq_save(flags);
sound_ym.rd_data_reg_sel = 15;
sound_ym.wd_data = data;
- restore_flags(flags);
+ local_irq_restore(flags);
}
static unsigned char
@@ -51,12 +50,11 @@ parport_atari_read_control(struct parport *p)
unsigned long flags;
unsigned char control = 0;
- save_flags(flags);
- cli();
+ local_irq_save(flags);
sound_ym.rd_data_reg_sel = 14;
if (!(sound_ym.rd_data_reg_sel & (1 << 5)))
control = PARPORT_CONTROL_STROBE;
- restore_flags(flags);
+ local_irq_restore(flags);
return control;
}
@@ -65,14 +63,13 @@ parport_atari_write_control(struct parport *p, unsigned char control)
{
unsigned long flags;
- save_flags(flags);
- cli();
+ local_irq_save(flags);
sound_ym.rd_data_reg_sel = 14;
if (control & PARPORT_CONTROL_STROBE)
sound_ym.wd_data = sound_ym.rd_data_reg_sel & ~(1 << 5);
else
sound_ym.wd_data = sound_ym.rd_data_reg_sel | (1 << 5);
- restore_flags(flags);
+ local_irq_restore(flags);
}
static unsigned char
@@ -129,12 +126,11 @@ parport_atari_data_forward(struct parport *p)
{
unsigned long flags;
- save_flags(flags);
- cli();
+ local_irq_save(flags);
/* Soundchip port B as output. */
sound_ym.rd_data_reg_sel = 7;
sound_ym.wd_data = sound_ym.rd_data_reg_sel | 0x40;
- restore_flags(flags);
+ local_irq_restore(flags);
}
static void
@@ -143,12 +139,11 @@ parport_atari_data_reverse(struct parport *p)
#if 0 /* too dangerous, can kill sound chip */
unsigned long flags;
- save_flags(flags);
- cli();
+ local_irq_save(flags);
/* Soundchip port B as input. */
sound_ym.rd_data_reg_sel = 7;
sound_ym.wd_data = sound_ym.rd_data_reg_sel & ~0x40;
- restore_flags(flags);
+ local_irq_restore(flags);
#endif
}
@@ -209,15 +204,14 @@ parport_atari_init(void)
unsigned long flags;
if (MACH_IS_ATARI) {
- save_flags(flags);
- cli();
+ local_irq_save(flags);
/* Soundchip port A/B as output. */
sound_ym.rd_data_reg_sel = 7;
sound_ym.wd_data = (sound_ym.rd_data_reg_sel & 0x3f) | 0xc0;
/* STROBE high. */
sound_ym.rd_data_reg_sel = 14;
sound_ym.wd_data = sound_ym.rd_data_reg_sel | (1 << 5);
- restore_flags(flags);
+ local_irq_restore(flags);
/* MFP port I0 as input. */
mfp.data_dir &= ~1;
/* MFP port I0 interrupt on high->low edge. */
diff --git a/drivers/parport/parport_mfc3.c b/drivers/parport/parport_mfc3.c
index 2f78ad1450d8..e6582994fb99 100644
--- a/drivers/parport/parport_mfc3.c
+++ b/drivers/parport/parport_mfc3.c
@@ -59,6 +59,7 @@
#include <linux/delay.h>
#include <linux/mc6821.h>
#include <linux/zorro.h>
+#include <linux/interrupt.h>
#include <asm/setup.h>
#include <asm/amigahw.h>
#include <asm/irq.h>
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index a9064b0ffea8..2c14942cbb00 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -257,7 +257,6 @@ struct pci_bus * __devinit pci_add_new_bus(struct pci_bus *parent, struct pci_de
int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max, int pass)
{
unsigned int buses;
- unsigned short cr;
struct pci_bus *child;
int is_cardbus = (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS);
@@ -285,13 +284,12 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max
} else {
/*
* We need to assign a number to this bus which we always
- * do in the second pass. We also keep all address decoders
- * on the bridge disabled during scanning. FIXME: Why?
+ * do in the second pass.
*/
if (!pass)
return max;
- pci_read_config_word(dev, PCI_COMMAND, &cr);
- pci_write_config_word(dev, PCI_COMMAND, 0x0000);
+
+ /* Clear errors */
pci_write_config_word(dev, PCI_STATUS, 0xffff);
child = pci_add_new_bus(bus, dev, ++max);
@@ -319,7 +317,6 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max
*/
child->subordinate = max;
pci_write_config_byte(dev, PCI_SUBORDINATE_BUS, max);
- pci_write_config_word(dev, PCI_COMMAND, cr);
}
sprintf(child->name, (is_cardbus ? "PCI CardBus #%02x" : "PCI Bus #%02x"), child->number);
diff --git a/drivers/pcmcia/yenta.c b/drivers/pcmcia/yenta.c
index e05fb57bda60..f30641c4a23c 100644
--- a/drivers/pcmcia/yenta.c
+++ b/drivers/pcmcia/yenta.c
@@ -593,6 +593,7 @@ static void yenta_open_bh(void * data)
if (!socket->cb_irq || request_irq(socket->cb_irq, yenta_interrupt, SA_SHIRQ, socket->dev->dev.name, socket)) {
/* No IRQ or request_irq failed. Poll */
socket->cb_irq = 0; /* But zero is a valid IRQ number. */
+ init_timer(&socket->poll_timer);
socket->poll_timer.function = yenta_interrupt_wrapper;
socket->poll_timer.data = (unsigned long)socket;
socket->poll_timer.expires = jiffies + HZ;
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c
index 6f0cfa5c66bc..8eedee623a04 100644
--- a/drivers/s390/block/dasd.c
+++ b/drivers/s390/block/dasd.c
@@ -1757,8 +1757,7 @@ dasd_release(struct inode *inp, struct file *filp)
}
if (atomic_dec_return(&device->open_count) == 0) {
invalidate_buffers(inp->i_rdev);
- if (device->discipline->owner)
- __MOD_DEC_USE_COUNT(device->discipline->owner);
+ module_put(device->discipline->owner);
}
return 0;
}
diff --git a/drivers/s390/block/dasd_ioctl.c b/drivers/s390/block/dasd_ioctl.c
index def999eb4334..9047d68fb20a 100644
--- a/drivers/s390/block/dasd_ioctl.c
+++ b/drivers/s390/block/dasd_ioctl.c
@@ -115,7 +115,7 @@ dasd_ioctl(struct inode *inp, struct file *filp,
if (try_inc_mod_count(ioctl->owner) != 0)
continue;
rc = ioctl->handler(bdev, no, data);
- __MOD_DEC_USE_COUNT(ioctl->owner);
+ module_put(ioctl->owner);
} else
rc = ioctl->handler(bdev, no, data);
return rc;
diff --git a/drivers/s390/char/tape_core.c b/drivers/s390/char/tape_core.c
index 23c48e2e6381..af71fadf2f52 100644
--- a/drivers/s390/char/tape_core.c
+++ b/drivers/s390/char/tape_core.c
@@ -857,8 +857,7 @@ tape_release(struct tape_device *device)
spin_lock(get_ccwdev_lock(device->cdev));
if (device->tape_state == TS_IN_USE)
tape_state_set(device, TS_UNUSED);
- if (device->discipline->owner)
- __MOD_DEC_USE_COUNT(device->discipline->owner);
+ module_put(device->discipline->owner);
spin_unlock(get_ccwdev_lock(device->cdev));
return 0;
}
diff --git a/drivers/scsi/53c7xx.c b/drivers/scsi/53c7xx.c
index 4715fc295c29..e9b395952b38 100644
--- a/drivers/scsi/53c7xx.c
+++ b/drivers/scsi/53c7xx.c
@@ -251,6 +251,7 @@
#include <linux/time.h>
#include <linux/blk.h>
#include <linux/spinlock.h>
+#include <linux/interrupt.h>
#include <asm/pgtable.h>
#ifdef CONFIG_AMIGA
@@ -713,15 +714,14 @@ request_synchronous (int host, int target) {
}
hostdata = (struct NCR53c7x0_hostdata *)h->hostdata[0];
- save_flags(flags);
- cli();
+ local_irq_save(flags);
if (hostdata->initiate_sdtr & (1 << target)) {
- restore_flags(flags);
+ local_irq_restore(flags);
printk (KERN_ALERT "target %d already doing SDTR\n", target);
return -1;
}
hostdata->initiate_sdtr |= (1 << target);
- restore_flags(flags);
+ local_irq_restore(flags);
return 0;
}
#endif
@@ -1588,11 +1588,10 @@ NCR53c7xx_run_tests (struct Scsi_Host *host) {
/* The NCR chip _must_ be idle to run the test scripts */
- save_flags(flags);
- cli();
+ local_irq_save(flags);
if (!hostdata->idle) {
printk ("scsi%d : chip not idle, aborting tests\n", host->host_no);
- restore_flags(flags);
+ local_irq_restore(flags);
return -1;
}
@@ -1616,7 +1615,7 @@ NCR53c7xx_run_tests (struct Scsi_Host *host) {
NCR53c7x0_write8 (DCNTL_REG, hostdata->saved_dcntl | DCNTL_SSM |
DCNTL_STD);
printk (" started\n");
- restore_flags(flags);
+ local_irq_restore(flags);
/*
* This is currently a .5 second timeout, since (in theory) no slow
@@ -1655,7 +1654,7 @@ NCR53c7xx_run_tests (struct Scsi_Host *host) {
hostdata->script, start);
printk ("scsi%d : DSPS = 0x%x\n", host->host_no,
NCR53c7x0_read32(DSPS_REG));
- restore_flags(flags);
+ local_irq_restore(flags);
return -1;
}
hostdata->test_running = 0;
@@ -1690,10 +1689,10 @@ NCR53c7xx_run_tests (struct Scsi_Host *host) {
if (!hostdata->valid_ids[i])
continue;
#endif
- cli();
+ local_irq_disable();
if (!hostdata->idle) {
printk ("scsi%d : chip not idle, aborting tests\n", host->host_no);
- restore_flags(flags);
+ local_irq_restore(flags);
return -1;
}
@@ -1709,7 +1708,7 @@ NCR53c7xx_run_tests (struct Scsi_Host *host) {
if (hostdata->options & OPTION_DEBUG_TRACE)
NCR53c7x0_write8 (DCNTL_REG, hostdata->saved_dcntl |
DCNTL_SSM | DCNTL_STD);
- restore_flags(flags);
+ local_irq_restore(flags);
timeout = jiffies + 5 * HZ; /* arbitrary */
while ((hostdata->test_completed == -1) && time_before(jiffies, timeout))
@@ -1731,19 +1730,19 @@ NCR53c7xx_run_tests (struct Scsi_Host *host) {
host->host_no, i);
if (!hostdata->idle) {
printk("scsi%d : not idle\n", host->host_no);
- restore_flags(flags);
+ local_irq_restore(flags);
return -1;
}
} else if (hostdata->test_completed == -1) {
printk ("scsi%d : test 2 timed out\n", host->host_no);
- restore_flags(flags);
+ local_irq_restore(flags);
return -1;
}
hostdata->test_running = 0;
}
}
- restore_flags(flags);
+ local_irq_restore(flags);
return 0;
}
@@ -1826,8 +1825,7 @@ static volatile int process_issue_queue_running = 0;
static __inline__ void
run_process_issue_queue(void) {
unsigned long flags;
- save_flags (flags);
- cli();
+ local_irq_save(flags);
if (!process_issue_queue_running) {
process_issue_queue_running = 1;
process_issue_queue(flags);
@@ -1837,7 +1835,7 @@ run_process_issue_queue(void) {
* interrupts disabled.
*/
}
- restore_flags (flags);
+ local_irq_restore(flags);
}
/*
@@ -1871,8 +1869,7 @@ abnormal_finished (struct NCR53c7x0_cmd *cmd, int result) {
printk ("scsi%d: abnormal finished\n", host->host_no);
#endif
- save_flags(flags);
- cli();
+ local_irq_save(flags);
found = 0;
/*
* Traverse the NCR issue array until we find a match or run out
@@ -1955,7 +1952,7 @@ abnormal_finished (struct NCR53c7x0_cmd *cmd, int result) {
c->result = result;
c->scsi_done(c);
- restore_flags(flags);
+ local_irq_restore(flags);
run_process_issue_queue();
}
@@ -1990,8 +1987,7 @@ intr_break (struct Scsi_Host *host, struct
* dump the appropriate debugging information to standard
* output.
*/
- save_flags(flags);
- cli();
+ local_irq_save(flags);
dsp = (u32 *) bus_to_virt(NCR53c7x0_read32(DSP_REG));
for (bp = hostdata->breakpoints; bp && bp->address != dsp;
bp = bp->next);
@@ -2013,7 +2009,7 @@ intr_break (struct Scsi_Host *host, struct
* instruction in bytes.
*/
- restore_flags(flags);
+ local_irq_restore(flags);
}
/*
* Function : static void print_synchronous (const char *prefix,
@@ -2919,8 +2915,7 @@ NCR53c7x0_soft_reset (struct Scsi_Host *host) {
host->hostdata[0];
NCR53c7x0_local_setup(host);
- save_flags(flags);
- cli();
+ local_irq_save(flags);
/* Disable scsi chip and s/w level 7 ints */
@@ -3021,7 +3016,7 @@ NCR53c7x0_soft_reset (struct Scsi_Host *host) {
}
#endif
/* Anything needed for your hardware? */
- restore_flags(flags);
+ local_irq_restore(flags);
}
@@ -3122,19 +3117,17 @@ allocate_cmd (Scsi_Cmnd *cmd) {
tmp->real = (void *)real;
tmp->size = size;
tmp->free = ((void (*)(void *, int)) my_free_page);
- save_flags (flags);
- cli();
+ local_irq_save(flags);
tmp->next = hostdata->free;
hostdata->free = tmp;
- restore_flags (flags);
+ local_irq_restore(flags);
}
- save_flags(flags);
- cli();
+ local_irq_save(flags);
tmp = (struct NCR53c7x0_cmd *) hostdata->free;
if (tmp) {
hostdata->free = tmp->next;
}
- restore_flags(flags);
+ local_irq_restore(flags);
if (!tmp)
printk ("scsi%d : can't allocate command for target %d lun %d\n",
host->host_no, cmd->target, cmd->lun);
@@ -3353,19 +3346,17 @@ create_cmd (Scsi_Cmnd *cmd) {
memcpy ((void *) (tmp->select + 1), (void *) wdtr_message,
sizeof(wdtr_message));
patch_dsa_32(tmp->dsa, dsa_msgout, 0, 1 + sizeof(wdtr_message));
- save_flags(flags);
- cli();
+ local_irq_save(flags);
hostdata->initiate_wdtr &= ~(1 << cmd->target);
- restore_flags(flags);
+ local_irq_restore(flags);
} else if (hostdata->initiate_sdtr & (1 << cmd->target)) {
memcpy ((void *) (tmp->select + 1), (void *) sdtr_message,
sizeof(sdtr_message));
patch_dsa_32(tmp->dsa, dsa_msgout, 0, 1 + sizeof(sdtr_message));
tmp->flags |= CMD_FLAG_SDTR;
- save_flags(flags);
- cli();
+ local_irq_save(flags);
hostdata->initiate_sdtr &= ~(1 << cmd->target);
- restore_flags(flags);
+ local_irq_restore(flags);
}
#if 1
@@ -3622,8 +3613,7 @@ NCR53c7xx_queue_command (Scsi_Cmnd *cmd, void (* done)(Scsi_Cmnd *)) {
}
#endif
- save_flags(flags);
- cli();
+ local_irq_save(flags);
if ((hostdata->options & (OPTION_DEBUG_INIT_ONLY|OPTION_DEBUG_PROBE_ONLY))
|| ((hostdata->options & OPTION_DEBUG_TARGET_LIMIT) &&
!(hostdata->debug_lun_limit[cmd->target] & (1 << cmd->lun)))
@@ -3638,7 +3628,7 @@ NCR53c7xx_queue_command (Scsi_Cmnd *cmd, void (* done)(Scsi_Cmnd *)) {
cmd->target, cmd->lun);
cmd->result = (DID_BAD_TARGET << 16);
done(cmd);
- restore_flags (flags);
+ local_irq_restore(flags);
return 0;
}
@@ -3647,7 +3637,7 @@ NCR53c7xx_queue_command (Scsi_Cmnd *cmd, void (* done)(Scsi_Cmnd *)) {
printk("scsi%d : maximum commands exceeded\n", host->host_no);
cmd->result = (DID_BAD_TARGET << 16);
done(cmd);
- restore_flags (flags);
+ local_irq_restore(flags);
return 0;
}
@@ -3659,7 +3649,7 @@ NCR53c7xx_queue_command (Scsi_Cmnd *cmd, void (* done)(Scsi_Cmnd *)) {
host->host_no);
cmd->result = (DID_BAD_TARGET << 16);
done(cmd);
- restore_flags (flags);
+ local_irq_restore(flags);
return 0;
}
}
@@ -3686,7 +3676,7 @@ NCR53c7xx_queue_command (Scsi_Cmnd *cmd, void (* done)(Scsi_Cmnd *)) {
tmp = (Scsi_Cmnd *) tmp->SCp.ptr);
tmp->SCp.ptr = (unsigned char *) cmd;
}
- restore_flags (flags);
+ local_irq_restore(flags);
run_process_issue_queue();
return 0;
}
@@ -3726,8 +3716,7 @@ to_schedule_list (struct Scsi_Host *host, struct NCR53c7x0_hostdata *hostdata,
virt_to_bus(hostdata->dsa), hostdata->dsa);
#endif
- save_flags(flags);
- cli();
+ local_irq_save(flags);
/*
* Work around race condition : if an interrupt fired and we
@@ -3740,7 +3729,7 @@ to_schedule_list (struct Scsi_Host *host, struct NCR53c7x0_hostdata *hostdata,
cmd->next = (struct NCR53c7x0_cmd *) hostdata->free;
hostdata->free = cmd;
tmp->scsi_done(tmp);
- restore_flags (flags);
+ local_irq_restore(flags);
return;
}
@@ -3770,7 +3759,7 @@ to_schedule_list (struct Scsi_Host *host, struct NCR53c7x0_hostdata *hostdata,
cmd->next = (struct NCR53c7x0_cmd *) hostdata->free;
hostdata->free = cmd;
tmp->scsi_done(tmp);
- restore_flags (flags);
+ local_irq_restore(flags);
return;
}
@@ -3791,7 +3780,7 @@ to_schedule_list (struct Scsi_Host *host, struct NCR53c7x0_hostdata *hostdata,
NCR53c7x0_write8(hostdata->istat, ISTAT_10_SIGP);
}
- restore_flags(flags);
+ local_irq_restore(flags);
}
/*
@@ -3849,12 +3838,12 @@ process_issue_queue (unsigned long flags) {
*/
do {
- cli(); /* Freeze request queues */
+ local_irq_disable(); /* Freeze request queues */
done = 1;
for (host = first_host; host && host->hostt == the_template;
host = host->next) {
hostdata = (struct NCR53c7x0_hostdata *) host->hostdata[0];
- cli();
+ local_irq_disable();
if (hostdata->issue_queue) {
if (hostdata->state == STATE_DISABLED) {
tmp = (Scsi_Cmnd *) hostdata->issue_queue;
@@ -3904,7 +3893,7 @@ process_issue_queue (unsigned long flags) {
} /* if target/lun is not busy */
} /* if hostdata->issue_queue */
if (!done)
- restore_flags (flags);
+ local_irq_restore(flags);
} /* for host */
} while (!done);
process_issue_queue_running = 0;
@@ -4171,8 +4160,7 @@ NCR53c7x0_intfly (struct Scsi_Host *host)
* completion.
*/
- save_flags(flags);
- cli();
+ local_irq_save(flags);
restart:
for (cmd_prev_ptr = (struct NCR53c7x0_cmd **)&(hostdata->running_list),
cmd = (struct NCR53c7x0_cmd *) hostdata->running_list; cmd ;
@@ -4226,7 +4214,7 @@ restart:
tmp->scsi_done(tmp);
goto restart;
}
- restore_flags(flags);
+ local_irq_restore(flags);
if (!search_found) {
printk ("scsi%d : WARNING : INTFLY with no completed commands.\n",
@@ -4906,13 +4894,12 @@ intr_dma (struct Scsi_Host *host, struct NCR53c7x0_cmd *cmd) {
/* Don't print instr. until we write DSP at end of intr function */
} else if (hostdata->options & OPTION_DEBUG_SINGLE) {
print_insn (host, dsp, "s ", 0);
- save_flags(flags);
- cli();
+ local_irq_save(flags);
/* XXX - should we do this, or can we get away with writing dsp? */
NCR53c7x0_write8 (DCNTL_REG, (NCR53c7x0_read8(DCNTL_REG) &
~DCNTL_SSM) | DCNTL_STD);
- restore_flags(flags);
+ local_irq_restore(flags);
} else {
printk(KERN_ALERT "scsi%d : unexpected single step interrupt at\n"
" ", host->host_no);
@@ -5190,8 +5177,7 @@ NCR53c7xx_abort (Scsi_Cmnd *cmd) {
return SCSI_ABORT_BUSY;
}
- save_flags(flags);
- cli();
+ local_irq_save(flags);
#if 0
if (cache_pid == cmd->pid)
panic ("scsi%d : bloody fetus %d\n", host->host_no, cmd->pid);
@@ -5226,7 +5212,7 @@ NCR53c7xx_abort (Scsi_Cmnd *cmd) {
cmd->scsi_done(cmd);
printk ("scsi%d : found command %ld in Linux issue queue\n",
host->host_no, me->pid);
- restore_flags(flags);
+ local_irq_restore(flags);
run_process_issue_queue();
return SCSI_ABORT_SUCCESS;
}
@@ -5252,12 +5238,12 @@ NCR53c7xx_abort (Scsi_Cmnd *cmd) {
cmd->scsi_done(cmd);
printk ("scsi%d : found finished command %ld in running list\n",
host->host_no, cmd->pid);
- restore_flags(flags);
+ local_irq_restore(flags);
return SCSI_ABORT_NOT_RUNNING;
} else {
printk ("scsi%d : DANGER : command running, can not abort.\n",
cmd->host->host_no);
- restore_flags(flags);
+ local_irq_restore(flags);
return SCSI_ABORT_BUSY;
}
}
@@ -5289,7 +5275,7 @@ NCR53c7xx_abort (Scsi_Cmnd *cmd) {
*/
--hostdata->busy[cmd->target][cmd->lun];
}
- restore_flags(flags);
+ local_irq_restore(flags);
cmd->scsi_done(cmd);
/*
@@ -5337,8 +5323,7 @@ NCR53c7xx_reset (Scsi_Cmnd *cmd, unsigned int reset_flags) {
(struct NCR53c7x0_hostdata *) host->hostdata[0];
NCR53c7x0_local_setup(host);
- save_flags(flags);
- cli();
+ local_irq_save(flags);
ncr_halt (host);
print_lots (host);
dump_events (host, 30);
@@ -5372,13 +5357,13 @@ NCR53c7xx_reset (Scsi_Cmnd *cmd, unsigned int reset_flags) {
disable(host);
else if (hostdata->resets != -1)
--hostdata->resets;
- restore_flags(flags);
+ local_irq_restore(flags);
for (; nuke_list; nuke_list = tmp) {
tmp = (Scsi_Cmnd *) nuke_list->SCp.buffer;
nuke_list->result = DID_RESET << 16;
nuke_list->scsi_done (nuke_list);
}
- restore_flags(flags);
+ local_irq_restore(flags);
return SCSI_RESET_SUCCESS;
}
@@ -5607,8 +5592,7 @@ print_queues (struct Scsi_Host *host) {
left >= 0 && cmd;
cmd = next_cmd) {
next_cmd = (Scsi_Cmnd *) cmd->SCp.ptr;
- save_flags(flags);
- cli();
+ local_irq_save(flags);
if (cmd->host_scribble) {
if (check_address ((unsigned long) (cmd->host_scribble),
sizeof (cmd->host_scribble)) == -1)
@@ -5621,7 +5605,7 @@ print_queues (struct Scsi_Host *host) {
} else
printk ("scsi%d : scsi pid %ld for target %d lun %d has no NCR53c7x0_cmd\n",
host->host_no, cmd->pid, cmd->target, cmd->lun);
- restore_flags(flags);
+ local_irq_restore(flags);
}
if (left <= 0) {
@@ -5653,8 +5637,7 @@ print_queues (struct Scsi_Host *host) {
dsa = bus_to_virt (hostdata->reconnect_dsa_head);
left >= 0 && dsa;
dsa = next_dsa) {
- save_flags (flags);
- cli();
+ local_irq_save(flags);
if (check_address ((unsigned long) dsa, sizeof(dsa)) == -1) {
printk ("scsi%d: bad DSA pointer 0x%p", host->host_no,
dsa);
@@ -5665,7 +5648,7 @@ print_queues (struct Scsi_Host *host) {
next_dsa = bus_to_virt(dsa[hostdata->dsa_next / sizeof(u32)]);
print_dsa (host, dsa, "");
}
- restore_flags(flags);
+ local_irq_restore(flags);
}
printk ("scsi%d : end reconnect_dsa_head\n", host->host_no);
if (left < 0)
@@ -5755,15 +5738,14 @@ shutdown (struct Scsi_Host *host) {
struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
host->hostdata[0];
NCR53c7x0_local_setup(host);
- save_flags (flags);
- cli();
+ local_irq_save(flags);
/* Get in a state where we can reset the SCSI bus */
ncr_halt (host);
ncr_scsi_reset (host);
hostdata->soft_reset(host);
disable (host);
- restore_flags (flags);
+ local_irq_restore(flags);
return 0;
}
@@ -5778,12 +5760,11 @@ ncr_scsi_reset (struct Scsi_Host *host) {
NCR53c7x0_local_declare();
unsigned long flags;
NCR53c7x0_local_setup(host);
- save_flags (flags);
- cli();
+ local_irq_save(flags);
NCR53c7x0_write8(SCNTL1_REG, SCNTL1_RST);
udelay(25); /* Minimum amount of time to assert RST */
NCR53c7x0_write8(SCNTL1_REG, 0);
- restore_flags (flags);
+ local_irq_restore(flags);
}
/*
@@ -5796,13 +5777,12 @@ hard_reset (struct Scsi_Host *host) {
struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
host->hostdata[0];
unsigned long flags;
- save_flags (flags);
- cli();
+ local_irq_save(flags);
ncr_scsi_reset(host);
NCR53c7x0_driver_init (host);
if (hostdata->soft_reset)
hostdata->soft_reset (host);
- restore_flags(flags);
+ local_irq_restore(flags);
}
@@ -5898,14 +5878,13 @@ disable (struct Scsi_Host *host) {
host->hostdata[0];
unsigned long flags;
Scsi_Cmnd *nuke_list, *tmp;
- save_flags(flags);
- cli();
+ local_irq_save(flags);
if (hostdata->state != STATE_HALTED)
ncr_halt (host);
nuke_list = return_outstanding_commands (host, 1 /* free */, 1 /* issue */);
hard_reset (host);
hostdata->state = STATE_DISABLED;
- restore_flags(flags);
+ local_irq_restore(flags);
printk ("scsi%d : nuking commands\n", host->host_no);
for (; nuke_list; nuke_list = tmp) {
tmp = (Scsi_Cmnd *) nuke_list->SCp.buffer;
@@ -5938,8 +5917,7 @@ ncr_halt (struct Scsi_Host *host) {
int stage;
NCR53c7x0_local_setup(host);
- save_flags(flags);
- cli();
+ local_irq_save(flags);
/* Stage 0 : eat all interrupts
Stage 1 : set ABORT
Stage 2 : eat all but abort interrupts
@@ -5974,7 +5952,7 @@ ncr_halt (struct Scsi_Host *host) {
}
}
hostdata->state = STATE_HALTED;
- restore_flags(flags);
+ local_irq_restore(flags);
#if 0
print_lots (host);
#endif
@@ -6022,14 +6000,13 @@ dump_events (struct Scsi_Host *host, int count) {
count = hostdata->event_size;
for (i = hostdata->event_index; count > 0;
i = (i ? i - 1 : hostdata->event_size -1), --count) {
- save_flags(flags);
/*
* By copying the event we're currently examining with interrupts
* disabled, we can do multiple printk(), etc. operations and
* still be guaranteed that they're happening on the same
* event structure.
*/
- cli();
+ local_irq_save(flags);
#if 0
event = hostdata->events[i];
#else
@@ -6037,7 +6014,7 @@ dump_events (struct Scsi_Host *host, int count) {
sizeof(event));
#endif
- restore_flags(flags);
+ local_irq_restore(flags);
printk ("scsi%d : %s event %d at %ld secs %ld usecs target %d lun %d\n",
host->host_no, event_name (event.event), count,
(long) event.time.tv_sec, (long) event.time.tv_usec,
diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c
index cb389fef9700..4499f1f6b3ae 100644
--- a/drivers/scsi/NCR5380.c
+++ b/drivers/scsi/NCR5380.c
@@ -2489,8 +2489,9 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) {
hostdata->issue_queue;
hostdata->issue_queue = (Scsi_Cmnd *) cmd;
dprintk(NDEBUG_QUEUES, ("scsi%d : REQUEST SENSE added to head of issue queue\n", instance->host_no));
- } else {
+ } else
#endif /* def AUTOSENSE */
+ {
collect_stats(hostdata, cmd);
cmd->scsi_done(cmd);
}
diff --git a/drivers/scsi/NCR53C9x.c b/drivers/scsi/NCR53C9x.c
index ead703c05e88..43681be4afd5 100644
--- a/drivers/scsi/NCR53C9x.c
+++ b/drivers/scsi/NCR53C9x.c
@@ -715,6 +715,9 @@ void esp_initialize(struct NCR_ESP *esp)
esp->targets_present = 0;
esp->resetting_bus = 0;
esp->snip = 0;
+
+ init_waitqueue_head(&esp->reset_queue);
+
esp->fas_premature_intr_workaround = 0;
for(i = 0; i < 32; i++)
esp->espcmdlog[i] = 0;
@@ -1037,25 +1040,6 @@ static void esp_exec_cmd(struct NCR_ESP *esp)
lun = SCptr->lun;
target = SCptr->target;
- /*
- * If esp_dev == NULL then we need to allocate a struct for our data
- */
- if (!esp_dev) {
- esp_dev = kmalloc(sizeof(struct esp_device), GFP_ATOMIC);
- if (!esp_dev) {
- /* We're SOL. Print a message and bail */
- printk(KERN_WARNING "esp: no mem for esp_device %d/%d\n",
- target, lun);
- esp->current_SC = NULL;
- SCptr->result = DID_ERROR << 16;
- SCptr->done(SCptr);
- return;
- }
- memset(esp_dev, 0, sizeof(struct esp_device));
- SDptr->hostdata = esp_dev;
- }
-
-
esp->snip = 0;
esp->msgout_len = 0;
@@ -1371,7 +1355,7 @@ static void esp_dump_state(struct NCR_ESP *esp,
ESPLOG(("\n"));
}
-/* Abort a command. */
+/* Abort a command. The host_lock is acquired by caller. */
int esp_abort(Scsi_Cmnd *SCptr)
{
struct NCR_ESP *esp = (struct NCR_ESP *) SCptr->host->hostdata;
@@ -1392,7 +1376,7 @@ int esp_abort(Scsi_Cmnd *SCptr)
esp->msgout_len = 1;
esp->msgout_ctr = 0;
esp_cmd(esp, eregs, ESP_CMD_SATN);
- return SCSI_ABORT_PENDING;
+ return SUCCESS;
}
/* If it is still in the issue queue then we can safely
@@ -1417,7 +1401,7 @@ int esp_abort(Scsi_Cmnd *SCptr)
this->done(this);
if(don)
esp->dma_ints_on(esp);
- return SCSI_ABORT_SUCCESS;
+ return SUCCESS;
}
}
}
@@ -1430,19 +1414,19 @@ int esp_abort(Scsi_Cmnd *SCptr)
if(esp->current_SC) {
if(don)
esp->dma_ints_on(esp);
- return SCSI_ABORT_BUSY;
+ return FAILED;
}
/* It's disconnected, we have to reconnect to re-establish
* the nexus and tell the device to abort. However, we really
- * cannot 'reconnect' per se, therefore we tell the upper layer
- * the safest thing we can. This is, wait a bit, if nothing
- * happens, we are really hung so reset the bus.
+ * cannot 'reconnect' per se. Don't try to be fancy, just
+ * indicate failure, which causes our caller to reset the whole
+ * bus.
*/
if(don)
esp->dma_ints_on(esp);
- return SCSI_ABORT_SNOOZE;
+ return FAILED;
}
/* We've sent ESP_CMD_RS to the ESP, the interrupt had just
@@ -1476,6 +1460,7 @@ static int esp_finish_reset(struct NCR_ESP *esp,
/* SCSI bus reset is complete. */
esp->resetting_bus = 0;
+ wake_up(&esp->reset_queue);
/* Ok, now it is safe to get commands going once more. */
if(esp->issue_SC)
@@ -1496,13 +1481,22 @@ static int esp_do_resetbus(struct NCR_ESP *esp,
/* Reset ESP chip, reset hanging bus, then kill active and
* disconnected commands for targets without soft reset.
+ *
+ * The host_lock is acquired by caller.
*/
-int esp_reset(Scsi_Cmnd *SCptr, unsigned int how)
+int esp_reset(Scsi_Cmnd *SCptr)
{
struct NCR_ESP *esp = (struct NCR_ESP *) SCptr->host->hostdata;
(void) esp_do_resetbus(esp, esp->eregs);
- return SCSI_RESET_PENDING;
+
+ spin_unlock_irq(esp->ehost->host_lock);
+
+ wait_event(esp->reset_queue, (esp->resetting_bus == 0));
+
+ spin_lock_irq(esp->ehost->host_lock);
+
+ return SUCCESS;
}
/* Internal ESP done function. */
@@ -1859,8 +1853,7 @@ static int esp_do_data(struct NCR_ESP *esp, struct ESP_regs *eregs)
ESPDATA(( /*"\n"*/ "\r"));
#endif
#if 0
- save_flags(flags);
- cli();
+ local_irq_save(flags);
#endif
if(thisphase == in_datain) {
/* 'go' ... */
@@ -1951,7 +1944,7 @@ static int esp_do_data(struct NCR_ESP *esp, struct ESP_regs *eregs)
ESPDATA(("done! \n"));
#if 0
- restore_flags(flags);
+ local_irq_restore(flags);
#endif
/* check new bus phase */
diff --git a/drivers/scsi/NCR53C9x.h b/drivers/scsi/NCR53C9x.h
index d8e161840e1a..3f20b6aaffa9 100644
--- a/drivers/scsi/NCR53C9x.h
+++ b/drivers/scsi/NCR53C9x.h
@@ -407,6 +407,7 @@ struct NCR_ESP {
* cannot be assosciated with any specific command.
*/
unchar resetting_bus;
+ wait_queue_head_t reset_queue;
unchar do_pio_cmds; /* Do command transfer with pio */
@@ -657,4 +658,11 @@ extern void esp_deallocate(struct NCR_ESP *);
extern void esp_release(void);
extern void esp_initialize(struct NCR_ESP *);
extern void esp_intr(int, void *, struct pt_regs *);
+extern const char *esp_info(struct Scsi_Host *);
+extern int esp_queue(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
+extern int esp_command(Scsi_Cmnd *);
+extern int esp_abort(Scsi_Cmnd *);
+extern int esp_reset(Scsi_Cmnd *);
+extern int esp_proc_info(char *buffer, char **start, off_t offset, int length,
+ int hostno, int inout);
#endif /* !(NCR53C9X_H) */
diff --git a/drivers/scsi/a2091.c b/drivers/scsi/a2091.c
index d1f7b9fa0410..f8b04da74c83 100644
--- a/drivers/scsi/a2091.c
+++ b/drivers/scsi/a2091.c
@@ -4,6 +4,7 @@
#include <linux/sched.h>
#include <linux/version.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <asm/setup.h>
#include <asm/page.h>
@@ -230,7 +231,21 @@ int __init a2091_detect(Scsi_Host_Template *tpnt)
#define HOSTS_C
-static Scsi_Host_Template driver_template = A2091_SCSI;
+static Scsi_Host_Template driver_template = {
+ .proc_name = "A2901",
+ .name = "Commodore A2091/A590 SCSI",
+ .detect = a2091_detect,
+ .release = a2091_release,
+ .queuecommand = wd33c93_queuecommand,
+ .abort = wd33c93_abort,
+ .reset = wd33c93_reset,
+ .can_queue = CAN_QUEUE,
+ .this_id = 7,
+ .sg_tablesize = SG_ALL,
+ .cmd_per_lun = CMD_PER_LUN,
+ .use_clustering = DISABLE_CLUSTERING
+};
+
#include "scsi_module.c"
diff --git a/drivers/scsi/a2091.h b/drivers/scsi/a2091.h
index ad0e524f65f3..3b6e57c742a3 100644
--- a/drivers/scsi/a2091.h
+++ b/drivers/scsi/a2091.h
@@ -30,19 +30,6 @@ int wd33c93_reset(Scsi_Cmnd *, unsigned int);
#define CAN_QUEUE 16
#endif
-#define A2091_SCSI { .proc_name = "A2901", \
- .name = "Commodore A2091/A590 SCSI", \
- .detect = a2091_detect, \
- .release = a2091_release, \
- .queuecommand = wd33c93_queuecommand, \
- .abort = wd33c93_abort, \
- .reset = wd33c93_reset, \
- .can_queue = CAN_QUEUE, \
- .this_id = 7, \
- .sg_tablesize = SG_ALL, \
- .cmd_per_lun = CMD_PER_LUN, \
- .use_clustering = DISABLE_CLUSTERING }
-
/*
* if the transfer address ANDed with this results in a non-zero
* result, then we can't use DMA.
diff --git a/drivers/scsi/a3000.c b/drivers/scsi/a3000.c
index 15dd86e4b194..28a393b68c5c 100644
--- a/drivers/scsi/a3000.c
+++ b/drivers/scsi/a3000.c
@@ -6,6 +6,7 @@
#include <linux/ioport.h>
#include <linux/init.h>
#include <linux/spinlock.h>
+#include <linux/interrupt.h>
#include <asm/setup.h>
#include <asm/page.h>
@@ -206,7 +207,21 @@ fail_register:
#define HOSTS_C
-static Scsi_Host_Template driver_template = _A3000_SCSI;
+static Scsi_Host_Template driver_template = {
+ .proc_name = "A3000",
+ .name = "Amiga 3000 built-in SCSI",
+ .detect = a3000_detect,
+ .release = a3000_release,
+ .queuecommand = wd33c93_queuecommand,
+ .abort = wd33c93_abort,
+ .reset = wd33c93_reset,
+ .can_queue = CAN_QUEUE,
+ .this_id = 7,
+ .sg_tablesize = SG_ALL,
+ .cmd_per_lun = CMD_PER_LUN,
+ .use_clustering = ENABLE_CLUSTERING
+};
+
#include "scsi_module.c"
diff --git a/drivers/scsi/a3000.h b/drivers/scsi/a3000.h
index ee134f111792..ddd13e856fc4 100644
--- a/drivers/scsi/a3000.h
+++ b/drivers/scsi/a3000.h
@@ -30,20 +30,6 @@ int wd33c93_reset(Scsi_Cmnd *, unsigned int);
#define CAN_QUEUE 16
#endif
-#define _A3000_SCSI { .proc_name = "A3000", \
- .proc_info = NULL, \
- .name = "Amiga 3000 built-in SCSI", \
- .detect = a3000_detect, \
- .release = a3000_release, \
- .queuecommand = wd33c93_queuecommand, \
- .abort = wd33c93_abort, \
- .reset = wd33c93_reset, \
- .can_queue = CAN_QUEUE, \
- .this_id = 7, \
- .sg_tablesize = SG_ALL, \
- .cmd_per_lun = CMD_PER_LUN, \
- .use_clustering = ENABLE_CLUSTERING }
-
/*
* if the transfer address ANDed with this results in a non-zero
* result, then we can't use DMA.
diff --git a/drivers/scsi/aic7xxx/Kconfig.aic79xx b/drivers/scsi/aic7xxx/Kconfig.aic79xx
index c2404c8433f4..0b6c04b23581 100644
--- a/drivers/scsi/aic7xxx/Kconfig.aic79xx
+++ b/drivers/scsi/aic7xxx/Kconfig.aic79xx
@@ -87,7 +87,7 @@ config AIC79XX_DEBUG_MASK
config AIC79XX_REG_PRETTY_PRINT
bool "Decode registers during diagnostics"
- depends on SCSI_AIC79XX
+ depends on SCSI_AIC79XX && SCSI_AIC7XXX_BUILD_FIRMWARE
default y
help
Compile in register value tables for the output of expanded register
diff --git a/drivers/scsi/aic7xxx/Kconfig.aic7xxx b/drivers/scsi/aic7xxx/Kconfig.aic7xxx
index 760f98082ad2..9d9a9e4b02c7 100644
--- a/drivers/scsi/aic7xxx/Kconfig.aic7xxx
+++ b/drivers/scsi/aic7xxx/Kconfig.aic7xxx
@@ -92,7 +92,7 @@ config AIC7XXX_DEBUG_MASK
config AIC7XXX_REG_PRETTY_PRINT
bool "Decode registers during diagnostics"
- depends on SCSI_AIC7XXX
+ depends on SCSI_AIC7XXX && SCSI_AIC7XXX_BUILD_FIRMWARE
default y
help
Compile in register value tables for the output of expanded register
diff --git a/drivers/scsi/amiga7xx.c b/drivers/scsi/amiga7xx.c
index 3ab6a15e39ad..715365d8c02c 100644
--- a/drivers/scsi/amiga7xx.c
+++ b/drivers/scsi/amiga7xx.c
@@ -134,5 +134,18 @@ int __init amiga7xx_detect(Scsi_Host_Template *tpnt)
return num;
}
-static Scsi_Host_Template driver_template = AMIGA7XX_SCSI;
+static Scsi_Host_Template driver_template = {
+ .name = "Amiga NCR53c710 SCSI",
+ .detect = amiga7xx_detect,
+ .queuecommand = NCR53c7xx_queue_command,
+ .abort = NCR53c7xx_abort,
+ .reset = NCR53c7xx_reset,
+ .can_queue = 24,
+ .this_id = 7,
+ .sg_tablesize = 63,
+ .cmd_per_lun = 3,
+ .use_clustering = DISABLE_CLUSTERING
+};
+
+
#include "scsi_module.c"
diff --git a/drivers/scsi/amiga7xx.h b/drivers/scsi/amiga7xx.h
index d563ac5a7b82..80da6a8261fe 100644
--- a/drivers/scsi/amiga7xx.h
+++ b/drivers/scsi/amiga7xx.h
@@ -24,15 +24,4 @@ void NCR53c7x0_intr(int irq, void *dev_id, struct pt_regs * regs);
#include <scsi/scsicam.h>
-#define AMIGA7XX_SCSI {.name = "Amiga NCR53c710 SCSI", \
- .detect = amiga7xx_detect, \
- .queuecommand = NCR53c7xx_queue_command, \
- .abort = NCR53c7xx_abort, \
- .reset = NCR53c7xx_reset, \
- .can_queue = 24, \
- .this_id = 7, \
- .sg_tablesize = 63, \
- .cmd_per_lun = 3, \
- .use_clustering = DISABLE_CLUSTERING }
-
#endif /* AMIGA7XX_H */
diff --git a/drivers/scsi/atari_NCR5380.c b/drivers/scsi/atari_NCR5380.c
index 537e3a6f448f..70da49bc0372 100644
--- a/drivers/scsi/atari_NCR5380.c
+++ b/drivers/scsi/atari_NCR5380.c
@@ -315,7 +315,7 @@ static Scsi_Host_Template *the_template = NULL;
#endif
typedef struct {
- char allocated[MAX_TAGS/8];
+ long allocated[MAX_TAGS/32];
int nr_allocated;
int queue_size;
} TAG_ALLOC;
@@ -561,14 +561,13 @@ static void NCR5380_print(struct Scsi_Host *instance) {
unsigned char status, data, basr, mr, icr, i;
unsigned long flags;
- save_flags(flags);
- cli();
+ local_irq_save(flags);
data = NCR5380_read(CURRENT_SCSI_DATA_REG);
status = NCR5380_read(STATUS_REG);
mr = NCR5380_read(MODE_REG);
icr = NCR5380_read(INITIATOR_COMMAND_REG);
basr = NCR5380_read(BUS_AND_STATUS_REG);
- restore_flags(flags);
+ local_irq_restore(flags);
printk("STATUS_REG: %02x ", status);
for (i = 0; signals[i].mask ; ++i)
if (status & signals[i].mask)
@@ -769,9 +768,7 @@ int NCR5380_proc_info (char *buffer, char **start, off_t offset,
} \
} while (0)
- for (instance = first_instance; instance && HOSTNO != hostno;
- instance = instance->next)
- ;
+ instance = scsi_host_hn_get(hostno);
if (!instance)
return(-ESRCH);
hostdata = (struct NCR5380_hostdata *)instance->hostdata;
@@ -781,8 +778,7 @@ int NCR5380_proc_info (char *buffer, char **start, off_t offset,
}
SPRINTF("NCR5380 core release=%d.\n", NCR5380_PUBLIC_RELEASE);
check_offset();
- save_flags(flags);
- cli();
+ local_irq_save(flags);
SPRINTF("NCR5380: coroutine is%s running.\n", main_running ? "" : "n't");
check_offset();
if (!hostdata->connected)
@@ -805,7 +801,7 @@ int NCR5380_proc_info (char *buffer, char **start, off_t offset,
check_offset();
}
- restore_flags(flags);
+ local_irq_restore(flags);
*start = buffer + (offset - begin);
if (pos - buffer < offset - begin)
return 0;
@@ -979,8 +975,7 @@ int NCR5380_queue_command (Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *))
* sense data is only guaranteed to be valid while the condition exists.
*/
- save_flags(flags);
- cli();
+ local_irq_save(flags);
/* ++guenther: now that the issue queue is being set up, we can lock ST-DMA.
* Otherwise a running NCR5380_main may steal the lock.
* Lock before actually inserting due to fairness reasons explained in
@@ -1009,7 +1004,7 @@ int NCR5380_queue_command (Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *))
LIST(cmd, tmp);
NEXT(tmp) = cmd;
}
- restore_flags(flags);
+ local_irq_restore(flags);
QU_PRINTK("scsi%d: command added to %s of queue\n", H_NO(cmd),
(cmd->cmnd[0] == REQUEST_SENSE) ? "head" : "tail");
@@ -1073,9 +1068,9 @@ static void NCR5380_main (void)
return;
main_running = 1;
- save_flags(flags);
+ local_save_flags(flags);
do {
- cli(); /* Freeze request queues */
+ local_irq_disable(); /* Freeze request queues */
done = 1;
if (!hostdata->connected) {
@@ -1109,7 +1104,8 @@ static void NCR5380_main (void)
!(hostdata->busy[tmp->target] & (1 << tmp->lun))
#endif
) {
- cli(); /* ++guenther: just to be sure, this must be atomic */
+ /* ++guenther: just to be sure, this must be atomic */
+ local_irq_disable();
if (prev) {
REMOVE(prev, NEXT(prev), tmp, NEXT(tmp));
NEXT(prev) = NEXT(tmp);
@@ -1121,7 +1117,7 @@ static void NCR5380_main (void)
falcon_dont_release++;
/* reenable interrupts after finding one */
- restore_flags(flags);
+ local_irq_restore(flags);
/*
* Attempt to establish an I_T_L nexus here.
@@ -1153,7 +1149,7 @@ static void NCR5380_main (void)
falcon_release_lock_if_possible( hostdata );
break;
} else {
- cli();
+ local_irq_disable();
LIST(tmp, hostdata->issue_queue);
NEXT(tmp) = hostdata->issue_queue;
hostdata->issue_queue = tmp;
@@ -1161,7 +1157,7 @@ static void NCR5380_main (void)
cmd_free_tag( tmp );
#endif
falcon_dont_release--;
- restore_flags(flags);
+ local_irq_restore(flags);
MAIN_PRINTK("scsi%d: main(): select() failed, "
"returned to issue_queue\n", HOSTNO);
if (hostdata->connected)
@@ -1176,7 +1172,7 @@ static void NCR5380_main (void)
&& !hostdata->dma_len
#endif
) {
- restore_flags(flags);
+ local_irq_restore(flags);
MAIN_PRINTK("scsi%d: main: performing information transfer\n",
HOSTNO);
NCR5380_information_transfer(instance);
@@ -1189,7 +1185,7 @@ static void NCR5380_main (void)
an interrupt could believe we'll pick up the work it left for
us, but we won't see it anymore here... */
main_running = 0;
- restore_flags(flags);
+ local_irq_restore(flags);
}
@@ -1430,10 +1426,9 @@ static int NCR5380_select (struct Scsi_Host *instance, Scsi_Cmnd *cmd, int tag)
* data bus during SELECTION.
*/
- save_flags(flags);
- cli();
+ local_irq_save(flags);
if (hostdata->connected) {
- restore_flags(flags);
+ local_irq_restore(flags);
return -1;
}
NCR5380_write(TARGET_COMMAND_REG, 0);
@@ -1446,7 +1441,7 @@ static int NCR5380_select (struct Scsi_Host *instance, Scsi_Cmnd *cmd, int tag)
NCR5380_write(OUTPUT_DATA_REG, hostdata->id_mask);
NCR5380_write(MODE_REG, MR_ARBITRATE);
- restore_flags(flags);
+ local_irq_restore(flags);
/* Wait for arbitration logic to complete */
#if NCR_TIMEOUT
@@ -1954,12 +1949,11 @@ static int NCR5380_transfer_dma( struct Scsi_Host *instance,
/* On the Medusa, it is a must to initialize the DMA before
* starting the NCR. This is also the cleaner way for the TT.
*/
- save_flags(flags);
- cli();
+ local_irq_save(flags);
hostdata->dma_len = (p & SR_IO) ?
NCR5380_dma_read_setup(instance, d, c) :
NCR5380_dma_write_setup(instance, d, c);
- restore_flags(flags);
+ local_irq_restore(flags);
}
if (p & SR_IO)
@@ -1973,12 +1967,11 @@ static int NCR5380_transfer_dma( struct Scsi_Host *instance,
/* On the Falcon, the DMA setup must be done after the last */
/* NCR access, else the DMA setup gets trashed!
*/
- save_flags(flags);
- cli();
+ local_irq_save(flags);
hostdata->dma_len = (p & SR_IO) ?
NCR5380_dma_read_setup(instance, d, c) :
NCR5380_dma_write_setup(instance, d, c);
- restore_flags(flags);
+ local_irq_restore(flags);
}
return 0;
}
@@ -2259,12 +2252,11 @@ static void NCR5380_information_transfer (struct Scsi_Host *instance)
cmd->request_buffer = (char *) cmd->sense_buffer;
cmd->request_bufflen = sizeof(cmd->sense_buffer);
- save_flags(flags);
- cli();
+ local_irq_save(flags);
LIST(cmd,hostdata->issue_queue);
NEXT(cmd) = hostdata->issue_queue;
hostdata->issue_queue = (Scsi_Cmnd *) cmd;
- restore_flags(flags);
+ local_irq_restore(flags);
QU_PRINTK("scsi%d: REQUEST SENSE added to head of "
"issue queue\n", H_NO(cmd));
} else
@@ -2321,14 +2313,13 @@ static void NCR5380_information_transfer (struct Scsi_Host *instance)
case DISCONNECT:
/* Accept message by clearing ACK */
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
- save_flags(flags);
- cli();
+ local_irq_save(flags);
cmd->device->disconnect = 1;
LIST(cmd,hostdata->disconnected_queue);
NEXT(cmd) = hostdata->disconnected_queue;
hostdata->connected = NULL;
hostdata->disconnected_queue = cmd;
- restore_flags(flags);
+ local_irq_restore(flags);
QU_PRINTK("scsi%d: command for target %d lun %d was "
"moved from connected to the "
"disconnected_queue\n", HOSTNO,
@@ -2671,8 +2662,7 @@ int NCR5380_abort (Scsi_Cmnd *cmd)
NCR5380_print_status (instance);
- save_flags(flags);
- cli();
+ local_irq_save(flags);
if (!IS_A_TT() && !falcon_got_lock)
printk(KERN_ERR "scsi%d: !!BINGO!! Falcon has no lock in NCR5380_abort\n",
@@ -2718,12 +2708,12 @@ int NCR5380_abort (Scsi_Cmnd *cmd)
#else
hostdata->busy[cmd->target] &= ~(1 << cmd->lun);
#endif
- restore_flags(flags);
+ local_irq_restore(flags);
cmd->scsi_done(cmd);
falcon_release_lock_if_possible( hostdata );
return SCSI_ABORT_SUCCESS;
} else {
-/* restore_flags(flags); */
+/* local_irq_restore(flags); */
printk("scsi%d: abort of connected command failed!\n", HOSTNO);
return SCSI_ABORT_ERROR;
}
@@ -2742,7 +2732,7 @@ int NCR5380_abort (Scsi_Cmnd *cmd)
(*prev) = NEXT(tmp);
NEXT(tmp) = NULL;
tmp->result = DID_ABORT << 16;
- restore_flags(flags);
+ local_irq_restore(flags);
ABRT_PRINTK("scsi%d: abort removed command from issue queue.\n",
HOSTNO);
/* Tagged queuing note: no tag to free here, hasn't been assigned
@@ -2764,7 +2754,7 @@ int NCR5380_abort (Scsi_Cmnd *cmd)
*/
if (hostdata->connected) {
- restore_flags(flags);
+ local_irq_restore(flags);
ABRT_PRINTK("scsi%d: abort failed, command connected.\n", HOSTNO);
return SCSI_ABORT_SNOOZE;
}
@@ -2797,7 +2787,7 @@ int NCR5380_abort (Scsi_Cmnd *cmd)
for (tmp = (Scsi_Cmnd *) hostdata->disconnected_queue; tmp;
tmp = NEXT(tmp))
if (cmd == tmp) {
- restore_flags(flags);
+ local_irq_restore(flags);
ABRT_PRINTK("scsi%d: aborting disconnected command.\n", HOSTNO);
if (NCR5380_select (instance, cmd, (int) cmd->tag))
@@ -2807,8 +2797,7 @@ int NCR5380_abort (Scsi_Cmnd *cmd)
do_abort (instance);
- save_flags(flags);
- cli();
+ local_irq_save(flags);
for (prev = (Scsi_Cmnd **) &(hostdata->disconnected_queue),
tmp = (Scsi_Cmnd *) hostdata->disconnected_queue;
tmp; prev = NEXTADDR(tmp), tmp = NEXT(tmp) )
@@ -2826,7 +2815,7 @@ int NCR5380_abort (Scsi_Cmnd *cmd)
#else
hostdata->busy[cmd->target] &= ~(1 << cmd->lun);
#endif
- restore_flags(flags);
+ local_irq_restore(flags);
tmp->scsi_done(tmp);
falcon_release_lock_if_possible( hostdata );
return SCSI_ABORT_SUCCESS;
@@ -2843,7 +2832,7 @@ int NCR5380_abort (Scsi_Cmnd *cmd)
* broke.
*/
- restore_flags(flags);
+ local_irq_restore(flags);
printk(KERN_INFO "scsi%d: warning : SCSI command probably completed successfully\n"
KERN_INFO " before abortion\n", HOSTNO);
@@ -2906,8 +2895,7 @@ static int NCR5380_reset( Scsi_Cmnd *cmd, unsigned int reset_flags)
* into the issue_queue (via scsi_done()), the aborted commands are
* remembered in local variables first.
*/
- save_flags(flags);
- cli();
+ local_irq_save(flags);
connected = (Scsi_Cmnd *)hostdata->connected;
hostdata->connected = NULL;
disconnected_queue = (Scsi_Cmnd *)hostdata->disconnected_queue;
@@ -2920,7 +2908,7 @@ static int NCR5380_reset( Scsi_Cmnd *cmd, unsigned int reset_flags)
#ifdef REAL_DMA
hostdata->dma_len = 0;
#endif
- restore_flags(flags);
+ local_irq_restore(flags);
/* In order to tell the mid-level code which commands were aborted,
* set the command status to DID_RESET and call scsi_done() !!!
@@ -2986,8 +2974,7 @@ static int NCR5380_reset( Scsi_Cmnd *cmd, unsigned int reset_flags)
if (hostdata->disconnected_queue)
ABRT_PRINTK("scsi%d: reset aborted disconnected command(s)\n", H_NO(cmd));
- save_flags(flags);
- cli();
+ local_irq_save(flags);
hostdata->issue_queue = NULL;
hostdata->connected = NULL;
hostdata->disconnected_queue = NULL;
@@ -2999,7 +2986,7 @@ static int NCR5380_reset( Scsi_Cmnd *cmd, unsigned int reset_flags)
#ifdef REAL_DMA
hostdata->dma_len = 0;
#endif
- restore_flags(flags);
+ local_irq_restore(flags);
/* we did no complete reset of all commands, so a wakeup is required */
return SCSI_RESET_WAKEUP | SCSI_RESET_BUS_RESET;
diff --git a/drivers/scsi/atari_scsi.c b/drivers/scsi/atari_scsi.c
index 8572300a1282..07c40bd87e67 100644
--- a/drivers/scsi/atari_scsi.c
+++ b/drivers/scsi/atari_scsi.c
@@ -508,12 +508,11 @@ static int falcon_dont_release = 0;
static void
falcon_release_lock_if_possible( struct NCR5380_hostdata * hostdata )
{
- unsigned long oldflags;
+ unsigned long flags;
if (IS_A_TT()) return;
- save_flags(oldflags);
- cli();
+ local_irq_save(flags);
if (falcon_got_lock &&
!hostdata->disconnected_queue &&
@@ -524,7 +523,7 @@ falcon_release_lock_if_possible( struct NCR5380_hostdata * hostdata )
#if 0
printk("WARNING: Lock release not allowed. Ignored\n");
#endif
- restore_flags(oldflags);
+ local_irq_restore(flags);
return;
}
falcon_got_lock = 0;
@@ -532,7 +531,7 @@ falcon_release_lock_if_possible( struct NCR5380_hostdata * hostdata )
wake_up( &falcon_fairness_wait );
}
- restore_flags(oldflags);
+ local_irq_restore(flags);
}
/* This function manages the locking of the ST-DMA.
@@ -552,12 +551,11 @@ falcon_release_lock_if_possible( struct NCR5380_hostdata * hostdata )
static void falcon_get_lock( void )
{
- unsigned long oldflags;
+ unsigned long flags;
if (IS_A_TT()) return;
- save_flags(oldflags);
- cli();
+ local_irq_save(flags);
while( !in_interrupt() && falcon_got_lock && stdma_others_waiting() )
sleep_on( &falcon_fairness_wait );
@@ -577,7 +575,7 @@ static void falcon_get_lock( void )
}
}
- restore_flags(oldflags);
+ local_irq_restore(flags);
if (!falcon_got_lock)
panic("Falcon SCSI: someone stole the lock :-(\n");
}
@@ -1141,7 +1139,23 @@ static void atari_scsi_falcon_reg_write( unsigned char reg, unsigned char value
#include "atari_NCR5380.c"
-static Scsi_Host_Template driver_template = ATARI_SCSI;
+static Scsi_Host_Template driver_template = {
+ .proc_info = atari_scsi_proc_info,
+ .name = "Atari native SCSI",
+ .detect = atari_scsi_detect,
+ .release = atari_scsi_release,
+ .info = atari_scsi_info,
+ .queuecommand = atari_scsi_queue_command,
+ .abort = atari_scsi_abort,
+ .reset = atari_scsi_reset,
+ .can_queue = 0, /* initialized at run-time */
+ .this_id = 0, /* initialized at run-time */
+ .sg_tablesize = 0, /* initialized at run-time */
+ .cmd_per_lun = 0, /* initialized at run-time */
+ .use_clustering = DISABLE_CLUSTERING
+};
+
+
#include "scsi_module.c"
MODULE_LICENSE("GPL");
diff --git a/drivers/scsi/atari_scsi.h b/drivers/scsi/atari_scsi.h
index bab788445261..a6fd05a74d33 100644
--- a/drivers/scsi/atari_scsi.h
+++ b/drivers/scsi/atari_scsi.h
@@ -51,20 +51,6 @@ int atari_scsi_release (struct Scsi_Host *);
#define DEFAULT_USE_TAGGED_QUEUING 0
-#define ATARI_SCSI { .proc_info = atari_scsi_proc_info, \
- .name = "Atari native SCSI", \
- .detect = atari_scsi_detect, \
- .release = atari_scsi_release, \
- .info = atari_scsi_info, \
- .queuecommand = atari_scsi_queue_command, \
- .abort = atari_scsi_abort, \
- .reset = atari_scsi_reset, \
- .can_queue = 0, /* initialized at run-time */ \
- .this_id = 0, /* initialized at run-time */ \
- .sg_tablesize = 0, /* initialized at run-time */ \
- .cmd_per_lun = 0, /* initialized at run-time */ \
- .use_clustering = DISABLE_CLUSTERING }
-
#define NCR5380_implementation_fields /* none */
#define NCR5380_read(reg) atari_scsi_reg_read( reg )
diff --git a/drivers/scsi/blz1230.c b/drivers/scsi/blz1230.c
index 90221a640e15..57296ffd25af 100644
--- a/drivers/scsi/blz1230.c
+++ b/drivers/scsi/blz1230.c
@@ -25,11 +25,11 @@
#include <linux/blk.h>
#include <linux/proc_fs.h>
#include <linux/stat.h>
+#include <linux/interrupt.h>
#include "scsi.h"
#include "hosts.h"
#include "NCR53C9x.h"
-#include "blz1230.h"
#include <linux/zorro.h>
#include <asm/irq.h>
@@ -40,6 +40,42 @@
#define MKIV 1
+/* The controller registers can be found in the Z2 config area at these
+ * offsets:
+ */
+#define BLZ1230_ESP_ADDR 0x8000
+#define BLZ1230_DMA_ADDR 0x10000
+#define BLZ1230II_ESP_ADDR 0x10000
+#define BLZ1230II_DMA_ADDR 0x10021
+
+
+/* The Blizzard 1230 DMA interface
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ * Only two things can be programmed in the Blizzard DMA:
+ * 1) The data direction is controlled by the status of bit 31 (1 = write)
+ * 2) The source/dest address (word aligned, shifted one right) in bits 30-0
+ *
+ * Program DMA by first latching the highest byte of the address/direction
+ * (i.e. bits 31-24 of the long word constructed as described in steps 1+2
+ * above). Then write each byte of the address/direction (starting with the
+ * top byte, working down) to the DMA address register.
+ *
+ * Figure out interrupt status by reading the ESP status byte.
+ */
+struct blz1230_dma_registers {
+ volatile unsigned char dma_addr; /* DMA address [0x0000] */
+ unsigned char dmapad2[0x7fff];
+ volatile unsigned char dma_latch; /* DMA latch [0x8000] */
+};
+
+struct blz1230II_dma_registers {
+ volatile unsigned char dma_addr; /* DMA address [0x0000] */
+ unsigned char dmapad2[0xf];
+ volatile unsigned char dma_latch; /* DMA latch [0x0010] */
+};
+
+#define BLZ1230_DMA_WRITE 0x80000000
+
static int dma_bytes_sent(struct NCR_ESP *esp, int fifo_count);
static int dma_can_transfer(struct NCR_ESP *esp, Scsi_Cmnd *sp);
static void dma_dump_state(struct NCR_ESP *esp);
@@ -279,12 +315,6 @@ static void dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write)
#define HOSTS_C
-#include "blz1230.h"
-
-static Scsi_Host_Template driver_template = SCSI_BLZ1230;
-
-#include "scsi_module.c"
-
int blz1230_esp_release(struct Scsi_Host *instance)
{
#ifdef MODULE
@@ -297,4 +327,25 @@ int blz1230_esp_release(struct Scsi_Host *instance)
return 1;
}
+
+static Scsi_Host_Template driver_template = {
+ .proc_name = "esp-blz1230",
+ .proc_info = esp_proc_info,
+ .name = "Blizzard1230 SCSI IV",
+ .detect = blz1230_esp_detect,
+ .release = blz1230_esp_release,
+ .command = esp_command,
+ .queuecommand = esp_queue,
+ .eh_abort_handler = esp_abort,
+ .eh_bus_reset_handler = esp_reset,
+ .can_queue = 7,
+ .this_id = 7,
+ .sg_tablesize = SG_ALL,
+ .cmd_per_lun = 1,
+ .use_clustering = ENABLE_CLUSTERING
+};
+
+
+#include "scsi_module.c"
+
MODULE_LICENSE("GPL");
diff --git a/drivers/scsi/blz1230.h b/drivers/scsi/blz1230.h
deleted file mode 100644
index 233d500c9d9e..000000000000
--- a/drivers/scsi/blz1230.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/* blz1230.h: Defines and structures for the Blizzard 1230 SCSI IV driver.
- *
- * Copyright (C) 1996 Jesper Skov (jskov@cygnus.co.uk)
- *
- * This file is based on cyber_esp.h (hence the occasional reference to
- * CyberStorm).
- */
-
-#include "NCR53C9x.h"
-
-#ifndef BLZ1230_H
-#define BLZ1230_H
-
-/* The controller registers can be found in the Z2 config area at these
- * offsets:
- */
-#define BLZ1230_ESP_ADDR 0x8000
-#define BLZ1230_DMA_ADDR 0x10000
-#define BLZ1230II_ESP_ADDR 0x10000
-#define BLZ1230II_DMA_ADDR 0x10021
-
-
-/* The Blizzard 1230 DMA interface
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- * Only two things can be programmed in the Blizzard DMA:
- * 1) The data direction is controlled by the status of bit 31 (1 = write)
- * 2) The source/dest address (word aligned, shifted one right) in bits 30-0
- *
- * Program DMA by first latching the highest byte of the address/direction
- * (i.e. bits 31-24 of the long word constructed as described in steps 1+2
- * above). Then write each byte of the address/direction (starting with the
- * top byte, working down) to the DMA address register.
- *
- * Figure out interrupt status by reading the ESP status byte.
- */
-struct blz1230_dma_registers {
- volatile unsigned char dma_addr; /* DMA address [0x0000] */
- unsigned char dmapad2[0x7fff];
- volatile unsigned char dma_latch; /* DMA latch [0x8000] */
-};
-
-struct blz1230II_dma_registers {
- volatile unsigned char dma_addr; /* DMA address [0x0000] */
- unsigned char dmapad2[0xf];
- volatile unsigned char dma_latch; /* DMA latch [0x0010] */
-};
-
-#define BLZ1230_DMA_WRITE 0x80000000
-
-extern int blz1230_esp_detect(struct SHT *);
-extern int blz1230_esp_release(struct Scsi_Host *);
-extern const char *esp_info(struct Scsi_Host *);
-extern int esp_queue(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
-extern int esp_command(Scsi_Cmnd *);
-extern int esp_abort(Scsi_Cmnd *);
-extern int esp_reset(Scsi_Cmnd *, unsigned int);
-extern int esp_proc_info(char *buffer, char **start, off_t offset, int length,
- int hostno, int inout);
-
-#define SCSI_BLZ1230 { .proc_name = "esp-blz1230", \
- .proc_info = esp_proc_info, \
- .name = "Blizzard1230 SCSI IV", \
- .detect = blz1230_esp_detect, \
- .release = blz1230_esp_release, \
- .command = esp_command, \
- .queuecommand = esp_queue, \
- .abort = esp_abort, \
- .reset = esp_reset, \
- .can_queue = 7, \
- .this_id = 7, \
- .sg_tablesize = SG_ALL, \
- .cmd_per_lun = 1, \
- .use_clustering = ENABLE_CLUSTERING }
-
-#endif /* BLZ1230_H */
diff --git a/drivers/scsi/blz2060.c b/drivers/scsi/blz2060.c
index f5007bc6b697..07a9220816a3 100644
--- a/drivers/scsi/blz2060.c
+++ b/drivers/scsi/blz2060.c
@@ -25,11 +25,11 @@
#include <linux/blk.h>
#include <linux/proc_fs.h>
#include <linux/stat.h>
+#include <linux/interrupt.h>
#include "scsi.h"
#include "hosts.h"
#include "NCR53C9x.h"
-#include "blz2060.h"
#include <linux/zorro.h>
#include <asm/irq.h>
@@ -38,6 +38,38 @@
#include <asm/pgtable.h>
+/* The controller registers can be found in the Z2 config area at these
+ * offsets:
+ */
+#define BLZ2060_ESP_ADDR 0x1ff00
+#define BLZ2060_DMA_ADDR 0x1ffe0
+
+
+/* The Blizzard 2060 DMA interface
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ * Only two things can be programmed in the Blizzard DMA:
+ * 1) The data direction is controlled by the status of bit 31 (1 = write)
+ * 2) The source/dest address (word aligned, shifted one right) in bits 30-0
+ *
+ * Figure out interrupt status by reading the ESP status byte.
+ */
+struct blz2060_dma_registers {
+ volatile unsigned char dma_led_ctrl; /* DMA led control [0x000] */
+ unsigned char dmapad1[0x0f];
+ volatile unsigned char dma_addr0; /* DMA address (MSB) [0x010] */
+ unsigned char dmapad2[0x03];
+ volatile unsigned char dma_addr1; /* DMA address [0x014] */
+ unsigned char dmapad3[0x03];
+ volatile unsigned char dma_addr2; /* DMA address [0x018] */
+ unsigned char dmapad4[0x03];
+ volatile unsigned char dma_addr3; /* DMA address (LSB) [0x01c] */
+};
+
+#define BLZ2060_DMA_WRITE 0x80000000
+
+/* DMA control bits */
+#define BLZ2060_DMA_LED 0x02 /* HD led control 1 = off */
+
static int dma_bytes_sent(struct NCR_ESP *esp, int fifo_count);
static int dma_can_transfer(struct NCR_ESP *esp, Scsi_Cmnd *sp);
static void dma_dump_state(struct NCR_ESP *esp);
@@ -236,12 +268,6 @@ static void dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write)
#define HOSTS_C
-#include "blz2060.h"
-
-static Scsi_Host_Template driver_template = SCSI_BLZ2060;
-
-#include "scsi_module.c"
-
int blz2060_esp_release(struct Scsi_Host *instance)
{
#ifdef MODULE
@@ -255,4 +281,24 @@ int blz2060_esp_release(struct Scsi_Host *instance)
return 1;
}
+
+static Scsi_Host_Template driver_template = {
+ .proc_name = "esp-blz2060",
+ .proc_info = esp_proc_info,
+ .name = "Blizzard2060 SCSI",
+ .detect = blz2060_esp_detect,
+ .release = blz2060_esp_release,
+ .queuecommand = esp_queue,
+ .eh_abort_handler = esp_abort,
+ .eh_bus_reset_handler = esp_reset,
+ .can_queue = 7,
+ .this_id = 7,
+ .sg_tablesize = SG_ALL,
+ .cmd_per_lun = 1,
+ .use_clustering = ENABLE_CLUSTERING
+};
+
+
+#include "scsi_module.c"
+
MODULE_LICENSE("GPL");
diff --git a/drivers/scsi/blz2060.h b/drivers/scsi/blz2060.h
deleted file mode 100644
index ca119b9e6d67..000000000000
--- a/drivers/scsi/blz2060.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/* blz2060.h: Defines and structures for the Blizzard 2060 SCSI driver.
- *
- * Copyright (C) 1996 Jesper Skov (jskov@cygnus.co.uk)
- *
- * This file is based on cyber_esp.h (hence the occasional reference to
- * CyberStorm).
- */
-
-#include "NCR53C9x.h"
-
-#ifndef BLZ2060_H
-#define BLZ2060_H
-
-/* The controller registers can be found in the Z2 config area at these
- * offsets:
- */
-#define BLZ2060_ESP_ADDR 0x1ff00
-#define BLZ2060_DMA_ADDR 0x1ffe0
-
-
-/* The Blizzard 2060 DMA interface
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- * Only two things can be programmed in the Blizzard DMA:
- * 1) The data direction is controlled by the status of bit 31 (1 = write)
- * 2) The source/dest address (word aligned, shifted one right) in bits 30-0
- *
- * Figure out interrupt status by reading the ESP status byte.
- */
-struct blz2060_dma_registers {
- volatile unsigned char dma_led_ctrl; /* DMA led control [0x000] */
- unsigned char dmapad1[0x0f];
- volatile unsigned char dma_addr0; /* DMA address (MSB) [0x010] */
- unsigned char dmapad2[0x03];
- volatile unsigned char dma_addr1; /* DMA address [0x014] */
- unsigned char dmapad3[0x03];
- volatile unsigned char dma_addr2; /* DMA address [0x018] */
- unsigned char dmapad4[0x03];
- volatile unsigned char dma_addr3; /* DMA address (LSB) [0x01c] */
-};
-
-#define BLZ2060_DMA_WRITE 0x80000000
-
-/* DMA control bits */
-#define BLZ2060_DMA_LED 0x02 /* HD led control 1 = off */
-
-extern int blz2060_esp_detect(struct SHT *);
-extern int blz2060_esp_release(struct Scsi_Host *);
-extern const char *esp_info(struct Scsi_Host *);
-extern int esp_queue(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
-extern int esp_command(Scsi_Cmnd *);
-extern int esp_abort(Scsi_Cmnd *);
-extern int esp_reset(Scsi_Cmnd *, unsigned int);
-extern int esp_proc_info(char *buffer, char **start, off_t offset, int length,
- int hostno, int inout);
-
-#define SCSI_BLZ2060 { .proc_name = "esp-blz2060", \
- .proc_info = esp_proc_info, \
- .name = "Blizzard2060 SCSI", \
- .detect = blz2060_esp_detect, \
- .release = blz2060_esp_release, \
- .queuecommand = esp_queue, \
- .abort = esp_abort, \
- .reset = esp_reset, \
- .can_queue = 7, \
- .this_id = 7, \
- .sg_tablesize = SG_ALL, \
- .cmd_per_lun = 1, \
- .use_clustering = ENABLE_CLUSTERING }
-
-#endif /* BLZ2060_H */
diff --git a/drivers/scsi/bvme6000.c b/drivers/scsi/bvme6000.c
index 75b99d4a257e..9f7ba7890ad1 100644
--- a/drivers/scsi/bvme6000.c
+++ b/drivers/scsi/bvme6000.c
@@ -51,5 +51,18 @@ int bvme6000_scsi_detect(Scsi_Host_Template *tpnt)
return 1;
}
-static Scsi_Host_Template driver_template = BVME6000_SCSI;
+static Scsi_Host_Template driver_template = {
+ .name = "BVME6000 NCR53c710 SCSI",
+ .detect = bvme6000_scsi_detect,
+ .queuecommand = NCR53c7xx_queue_command,
+ .abort = NCR53c7xx_abort,
+ .reset = NCR53c7xx_reset,
+ .can_queue = 24,
+ .this_id = 7,
+ .sg_tablesize = 63,
+ .cmd_per_lun = 3,
+ .use_clustering = DISABLE_CLUSTERING
+};
+
+
#include "scsi_module.c"
diff --git a/drivers/scsi/bvme6000.h b/drivers/scsi/bvme6000.h
index a1bfe3b0e06c..61dd486b9677 100644
--- a/drivers/scsi/bvme6000.h
+++ b/drivers/scsi/bvme6000.h
@@ -25,15 +25,4 @@ void NCR53c7x0_intr(int irq, void *dev_id, struct pt_regs * regs);
#include <scsi/scsicam.h>
-#define BVME6000_SCSI {.name = "BVME6000 NCR53c710 SCSI", \
- .detect = bvme6000_scsi_detect, \
- .queuecommand = NCR53c7xx_queue_command, \
- .abort = NCR53c7xx_abort, \
- .reset = NCR53c7xx_reset, \
- .can_queue = 24, \
- .this_id = 7, \
- .sg_tablesize = 63, \
- .cmd_per_lun = 3, \
- .use_clustering = DISABLE_CLUSTERING }
-
#endif /* BVME6000_SCSI_H */
diff --git a/drivers/scsi/cyberstorm.c b/drivers/scsi/cyberstorm.c
index bb1fa3cf7cc2..83a3a0a9e5da 100644
--- a/drivers/scsi/cyberstorm.c
+++ b/drivers/scsi/cyberstorm.c
@@ -28,11 +28,11 @@
#include <linux/blk.h>
#include <linux/proc_fs.h>
#include <linux/stat.h>
+#include <linux/interrupt.h>
#include "scsi.h"
#include "hosts.h"
#include "NCR53C9x.h"
-#include "cyberstorm.h"
#include <linux/zorro.h>
#include <asm/irq.h>
@@ -41,6 +41,43 @@
#include <asm/pgtable.h>
+/* The controller registers can be found in the Z2 config area at these
+ * offsets:
+ */
+#define CYBER_ESP_ADDR 0xf400
+#define CYBER_DMA_ADDR 0xf800
+
+
+/* The CyberStorm DMA interface */
+struct cyber_dma_registers {
+ volatile unsigned char dma_addr0; /* DMA address (MSB) [0x000] */
+ unsigned char dmapad1[1];
+ volatile unsigned char dma_addr1; /* DMA address [0x002] */
+ unsigned char dmapad2[1];
+ volatile unsigned char dma_addr2; /* DMA address [0x004] */
+ unsigned char dmapad3[1];
+ volatile unsigned char dma_addr3; /* DMA address (LSB) [0x006] */
+ unsigned char dmapad4[0x3fb];
+ volatile unsigned char cond_reg; /* DMA cond (ro) [0x402] */
+#define ctrl_reg cond_reg /* DMA control (wo) [0x402] */
+};
+
+/* DMA control bits */
+#define CYBER_DMA_LED 0x80 /* HD led control 1 = on */
+#define CYBER_DMA_WRITE 0x40 /* DMA direction. 1 = write */
+#define CYBER_DMA_Z3 0x20 /* 16 (Z2) or 32 (CHIP/Z3) bit DMA transfer */
+
+/* DMA status bits */
+#define CYBER_DMA_HNDL_INTR 0x80 /* DMA IRQ pending? */
+
+/* The bits below appears to be Phase5 Debug bits only; they were not
+ * described by Phase5 so using them may seem a bit stupid...
+ */
+#define CYBER_HOST_ID 0x02 /* If set, host ID should be 7, otherwise
+ * it should be 6.
+ */
+#define CYBER_SLOW_CABLE 0x08 /* If *not* set, assume SLOW_CABLE */
+
static int dma_bytes_sent(struct NCR_ESP *esp, int fifo_count);
static int dma_can_transfer(struct NCR_ESP *esp, Scsi_Cmnd *sp);
static void dma_dump_state(struct NCR_ESP *esp);
@@ -302,12 +339,6 @@ static void dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write)
#define HOSTS_C
-#include "cyberstorm.h"
-
-static Scsi_Host_Template driver_template = SCSI_CYBERSTORM;
-
-#include "scsi_module.c"
-
int cyber_esp_release(struct Scsi_Host *instance)
{
#ifdef MODULE
@@ -321,4 +352,24 @@ int cyber_esp_release(struct Scsi_Host *instance)
return 1;
}
+
+static Scsi_Host_Template driver_template = {
+ .proc_name = "esp-cyberstorm",
+ .proc_info = esp_proc_info,
+ .name = "CyberStorm SCSI",
+ .detect = cyber_esp_detect,
+ .release = cyber_esp_release,
+ .queuecommand = esp_queue,
+ .eh_abort_handler = esp_abort,
+ .eh_bus_reset_handler = esp_reset,
+ .can_queue = 7,
+ .this_id = 7,
+ .sg_tablesize = SG_ALL,
+ .cmd_per_lun = 1,
+ .use_clustering = ENABLE_CLUSTERING
+};
+
+
+#include "scsi_module.c"
+
MODULE_LICENSE("GPL");
diff --git a/drivers/scsi/cyberstorm.h b/drivers/scsi/cyberstorm.h
deleted file mode 100644
index bbae3199b0ac..000000000000
--- a/drivers/scsi/cyberstorm.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/* cyberstorm.h: Defines and structures for the CyberStorm SCSI driver.
- *
- * Copyright (C) 1996 Jesper Skov (jskov@cygnus.co.uk)
- */
-
-#include "NCR53C9x.h"
-
-#ifndef CYBER_ESP_H
-#define CYBER_ESP_H
-
-/* The controller registers can be found in the Z2 config area at these
- * offsets:
- */
-#define CYBER_ESP_ADDR 0xf400
-#define CYBER_DMA_ADDR 0xf800
-
-
-/* The CyberStorm DMA interface */
-struct cyber_dma_registers {
- volatile unsigned char dma_addr0; /* DMA address (MSB) [0x000] */
- unsigned char dmapad1[1];
- volatile unsigned char dma_addr1; /* DMA address [0x002] */
- unsigned char dmapad2[1];
- volatile unsigned char dma_addr2; /* DMA address [0x004] */
- unsigned char dmapad3[1];
- volatile unsigned char dma_addr3; /* DMA address (LSB) [0x006] */
- unsigned char dmapad4[0x3fb];
- volatile unsigned char cond_reg; /* DMA cond (ro) [0x402] */
-#define ctrl_reg cond_reg /* DMA control (wo) [0x402] */
-};
-
-/* DMA control bits */
-#define CYBER_DMA_LED 0x80 /* HD led control 1 = on */
-#define CYBER_DMA_WRITE 0x40 /* DMA direction. 1 = write */
-#define CYBER_DMA_Z3 0x20 /* 16 (Z2) or 32 (CHIP/Z3) bit DMA transfer */
-
-/* DMA status bits */
-#define CYBER_DMA_HNDL_INTR 0x80 /* DMA IRQ pending? */
-
-/* The bits below appears to be Phase5 Debug bits only; they were not
- * described by Phase5 so using them may seem a bit stupid...
- */
-#define CYBER_HOST_ID 0x02 /* If set, host ID should be 7, otherwise
- * it should be 6.
- */
-#define CYBER_SLOW_CABLE 0x08 /* If *not* set, assume SLOW_CABLE */
-
-extern int cyber_esp_detect(struct SHT *);
-extern int cyber_esp_release(struct Scsi_Host *);
-extern const char *esp_info(struct Scsi_Host *);
-extern int esp_queue(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
-extern int esp_command(Scsi_Cmnd *);
-extern int esp_abort(Scsi_Cmnd *);
-extern int esp_reset(Scsi_Cmnd *, unsigned int);
-extern int esp_proc_info(char *buffer, char **start, off_t offset, int length,
- int hostno, int inout);
-
-
-#define SCSI_CYBERSTORM { .proc_name = "esp-cyberstorm", \
- .proc_info = esp_proc_info, \
- .name = "CyberStorm SCSI", \
- .detect = cyber_esp_detect, \
- .release = cyber_esp_release, \
- .queuecommand = esp_queue, \
- .abort = esp_abort, \
- .reset = esp_reset, \
- .can_queue = 7, \
- .this_id = 7, \
- .sg_tablesize = SG_ALL, \
- .cmd_per_lun = 1, \
- .use_clustering = ENABLE_CLUSTERING }
-
-#endif /* CYBER_ESP_H */
diff --git a/drivers/scsi/cyberstormII.c b/drivers/scsi/cyberstormII.c
index d35b853b7ab4..25eb423ce467 100644
--- a/drivers/scsi/cyberstormII.c
+++ b/drivers/scsi/cyberstormII.c
@@ -24,11 +24,11 @@
#include <linux/blk.h>
#include <linux/proc_fs.h>
#include <linux/stat.h>
+#include <linux/interrupt.h>
#include "scsi.h"
#include "hosts.h"
#include "NCR53C9x.h"
-#include "cyberstormII.h"
#include <linux/zorro.h>
#include <asm/irq.h>
@@ -37,6 +37,30 @@
#include <asm/pgtable.h>
+/* The controller registers can be found in the Z2 config area at these
+ * offsets:
+ */
+#define CYBERII_ESP_ADDR 0x1ff03
+#define CYBERII_DMA_ADDR 0x1ff43
+
+
+/* The CyberStorm II DMA interface */
+struct cyberII_dma_registers {
+ volatile unsigned char cond_reg; /* DMA cond (ro) [0x000] */
+#define ctrl_reg cond_reg /* DMA control (wo) [0x000] */
+ unsigned char dmapad4[0x3f];
+ volatile unsigned char dma_addr0; /* DMA address (MSB) [0x040] */
+ unsigned char dmapad1[3];
+ volatile unsigned char dma_addr1; /* DMA address [0x044] */
+ unsigned char dmapad2[3];
+ volatile unsigned char dma_addr2; /* DMA address [0x048] */
+ unsigned char dmapad3[3];
+ volatile unsigned char dma_addr3; /* DMA address (LSB) [0x04c] */
+};
+
+/* DMA control bits */
+#define CYBERII_DMA_LED 0x02 /* HD led control 1 = on */
+
static int dma_bytes_sent(struct NCR_ESP *esp, int fifo_count);
static int dma_can_transfer(struct NCR_ESP *esp, Scsi_Cmnd *sp);
static void dma_dump_state(struct NCR_ESP *esp);
@@ -252,13 +276,6 @@ static void dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write)
#define HOSTS_C
-#include "cyberstormII.h"
-
-static Scsi_Host_Template driver_template = SCSI_CYBERSTORMII;
-
-#include "scsi_module.c"
-
-
int cyberII_esp_release(struct Scsi_Host *instance)
{
#ifdef MODULE
@@ -272,4 +289,24 @@ int cyberII_esp_release(struct Scsi_Host *instance)
return 1;
}
+
+static Scsi_Host_Template driver_template = {
+ .proc_name = "esp-cyberstormII",
+ .proc_info = esp_proc_info,
+ .name = "CyberStorm Mk II SCSI",
+ .detect = cyberII_esp_detect,
+ .release = cyberII_esp_release,
+ .queuecommand = esp_queue,
+ .eh_abort_handler = esp_abort,
+ .eh_bus_reset_handler = esp_reset,
+ .can_queue = 7,
+ .this_id = 7,
+ .sg_tablesize = SG_ALL,
+ .cmd_per_lun = 1,
+ .use_clustering = ENABLE_CLUSTERING
+};
+
+
+#include "scsi_module.c"
+
MODULE_LICENSE("GPL");
diff --git a/drivers/scsi/cyberstormII.h b/drivers/scsi/cyberstormII.h
deleted file mode 100644
index 4a6bc0d9bf01..000000000000
--- a/drivers/scsi/cyberstormII.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/* cyberstormII.h: Defines and structures for the CyberStorm SCSI Mk II driver.
- *
- * Copyright (C) 1996 Jesper Skov (jskov@cygnus.co.uk)
- */
-
-#include "NCR53C9x.h"
-
-#ifndef CYBERII_ESP_H
-#define CYBERII_ESP_H
-
-/* The controller registers can be found in the Z2 config area at these
- * offsets:
- */
-#define CYBERII_ESP_ADDR 0x1ff03
-#define CYBERII_DMA_ADDR 0x1ff43
-
-
-/* The CyberStorm II DMA interface */
-struct cyberII_dma_registers {
- volatile unsigned char cond_reg; /* DMA cond (ro) [0x000] */
-#define ctrl_reg cond_reg /* DMA control (wo) [0x000] */
- unsigned char dmapad4[0x3f];
- volatile unsigned char dma_addr0; /* DMA address (MSB) [0x040] */
- unsigned char dmapad1[3];
- volatile unsigned char dma_addr1; /* DMA address [0x044] */
- unsigned char dmapad2[3];
- volatile unsigned char dma_addr2; /* DMA address [0x048] */
- unsigned char dmapad3[3];
- volatile unsigned char dma_addr3; /* DMA address (LSB) [0x04c] */
-};
-
-/* DMA control bits */
-#define CYBERII_DMA_LED 0x02 /* HD led control 1 = on */
-
-
-extern int cyberII_esp_detect(struct SHT *);
-extern int cyberII_esp_release(struct Scsi_Host *);
-extern const char *esp_info(struct Scsi_Host *);
-extern int esp_queue(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
-extern int esp_command(Scsi_Cmnd *);
-extern int esp_abort(Scsi_Cmnd *);
-extern int esp_reset(Scsi_Cmnd *, unsigned int);
-extern int esp_proc_info(char *buffer, char **start, off_t offset, int length,
- int hostno, int inout);
-
-#define SCSI_CYBERSTORMII { .proc_name = "esp-cyberstormII", \
- .proc_info = esp_proc_info, \
- .name = "CyberStorm Mk II SCSI", \
- .detect = cyberII_esp_detect, \
- .release = cyberII_esp_release, \
- .queuecommand = esp_queue, \
- .abort = esp_abort, \
- .reset = esp_reset, \
- .can_queue = 7, \
- .this_id = 7, \
- .sg_tablesize = SG_ALL, \
- .cmd_per_lun = 1, \
- .use_clustering = ENABLE_CLUSTERING }
-
-#endif /* CYBERII_ESP_H */
diff --git a/drivers/scsi/dec_esp.c b/drivers/scsi/dec_esp.c
index 23eabb24f434..b932a401df4f 100644
--- a/drivers/scsi/dec_esp.c
+++ b/drivers/scsi/dec_esp.c
@@ -31,7 +31,6 @@
#include "scsi.h"
#include "hosts.h"
#include "NCR53C9x.h"
-#include "dec_esp.h"
#include <asm/irq.h>
#include <asm/jazz.h>
@@ -46,6 +45,11 @@
#include <asm/dec/ioasic_ints.h>
#include <asm/dec/machtype.h>
+#define DEC_SCSI_SREG 0
+#define DEC_SCSI_DMAREG 0x40000
+#define DEC_SCSI_SRAM 0x80000
+#define DEC_SCSI_DIAG 0xC0000
+
/*
* Once upon a time the pmaz code used to be working but
* it hasn't been maintained for quite some time.
@@ -103,7 +107,25 @@ volatile unsigned long *scsi_sdr1;
static void scsi_dma_int(int, void *, struct pt_regs *);
-static Scsi_Host_Template driver_template = SCSI_DEC_ESP;
+int dec_esp_detect(Scsi_Host_Template * tpnt);
+
+static Scsi_Host_Template driver_template = {
+ .proc_name = "esp",
+ .proc_info = &esp_proc_info,
+ .name = "NCR53C94",
+ .detect = dec_esp_detect,
+ .info = esp_info,
+ .command = esp_command,
+ .queuecommand = esp_queue,
+ .eh_abort_handler = esp_abort,
+ .eh_bus_reset_handler = esp_reset,
+ .can_queue = 7,
+ .this_id = 7,
+ .sg_tablesize = SG_ALL,
+ .cmd_per_lun = 1,
+ .use_clustering = DISABLE_CLUSTERING,
+};
+
#include "scsi_module.c"
diff --git a/drivers/scsi/dec_esp.h b/drivers/scsi/dec_esp.h
deleted file mode 100644
index 6c428b553777..000000000000
--- a/drivers/scsi/dec_esp.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/* dec_esp.h: Defines and structures for the JAZZ SCSI driver.
- *
- * DECstation changes Copyright (C) 1998 Harald Koerfgen
- * and David Airlie
- *
- * based on jazz_esp.h:
- * Copyright (C) 1997 Thomas Bogendoerfer (tsbogend@alpha.franken.de)
- */
-
-#ifndef DEC_ESP_H
-#define DEC_ESP_H
-
-#include "NCR53C9x.h"
-
-#define DEC_SCSI_SREG 0
-#define DEC_SCSI_DMAREG 0x40000
-#define DEC_SCSI_SRAM 0x80000
-#define DEC_SCSI_DIAG 0xC0000
-
-extern int dec_esp_detect(struct SHT *);
-extern const char *esp_info(struct Scsi_Host *);
-extern int esp_queue(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
-extern int esp_command(Scsi_Cmnd *);
-extern int esp_abort(Scsi_Cmnd *);
-extern int esp_reset(Scsi_Cmnd *, unsigned int);
-extern int esp_proc_info(char *buffer, char **start, off_t offset, int length,
- int hostno, int inout);
-
-#define SCSI_DEC_ESP { \
- .proc_name = "esp", \
- .proc_info = &esp_proc_info, \
- .name = "NCR53C94", \
- .detect = dec_esp_detect, \
- .info = esp_info, \
- .command = esp_command, \
- .queuecommand = esp_queue, \
- .abort = esp_abort, \
- .reset = esp_reset, \
- .can_queue = 7, \
- .this_id = 7, \
- .sg_tablesize = SG_ALL, \
- .cmd_per_lun = 1, \
- .use_clustering = DISABLE_CLUSTERING, }
-
-#endif /* DEC_ESP_H */
diff --git a/drivers/scsi/fastlane.c b/drivers/scsi/fastlane.c
index b30cf21c8a91..b58c0289ea14 100644
--- a/drivers/scsi/fastlane.c
+++ b/drivers/scsi/fastlane.c
@@ -33,11 +33,11 @@
#include <linux/blk.h>
#include <linux/proc_fs.h>
#include <linux/stat.h>
+#include <linux/interrupt.h>
#include "scsi.h"
#include "hosts.h"
#include "NCR53C9x.h"
-#include "fastlane.h"
#include <linux/zorro.h>
#include <asm/irq.h>
@@ -53,6 +53,36 @@
#define NODMAIRQ
#endif
+/* The controller registers can be found in the Z2 config area at these
+ * offsets:
+ */
+#define FASTLANE_ESP_ADDR 0x1000001
+#define FASTLANE_DMA_ADDR 0x1000041
+
+
+/* The Fastlane DMA interface */
+struct fastlane_dma_registers {
+ volatile unsigned char cond_reg; /* DMA status (ro) [0x0000] */
+#define ctrl_reg cond_reg /* DMA control (wo) [0x0000] */
+ unsigned char dmapad1[0x3f];
+ volatile unsigned char clear_strobe; /* DMA clear (wo) [0x0040] */
+};
+
+
+/* DMA status bits */
+#define FASTLANE_DMA_MINT 0x80
+#define FASTLANE_DMA_IACT 0x40
+#define FASTLANE_DMA_CREQ 0x20
+
+/* DMA control bits */
+#define FASTLANE_DMA_FCODE 0xa0
+#define FASTLANE_DMA_MASK 0xf3
+#define FASTLANE_DMA_LED 0x10 /* HD led control 1 = on */
+#define FASTLANE_DMA_WRITE 0x08 /* 1 = write */
+#define FASTLANE_DMA_ENABLE 0x04 /* Enable DMA */
+#define FASTLANE_DMA_EDI 0x02 /* Enable DMA IRQ ? */
+#define FASTLANE_DMA_ESI 0x01 /* Enable SCSI IRQ */
+
static int dma_bytes_sent(struct NCR_ESP *esp, int fifo_count);
static int dma_can_transfer(struct NCR_ESP *esp, Scsi_Cmnd *sp);
static inline void dma_clear(struct NCR_ESP *esp);
@@ -140,7 +170,7 @@ int __init fastlane_esp_detect(Scsi_Host_Template *tpnt)
/* Map the physical address space into virtual kernel space */
address = (unsigned long)
- ioremap_nocache(board, z->resource.end-board+1);
+ z_ioremap(board, z->resource.end-board+1);
if(!address){
printk("Could not remap Fastlane controller memory!");
@@ -189,7 +219,7 @@ int __init fastlane_esp_detect(Scsi_Host_Template *tpnt)
return 0;
err_unmap:
- iounmap((void *)address);
+ z_iounmap((void *)address);
err_unregister:
scsi_unregister (esp->ehost);
err_release:
@@ -356,11 +386,6 @@ static void dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write)
#define HOSTS_C
-#include "fastlane.h"
-
-static Scsi_Host_Template driver_template = SCSI_FASTLANE;
-#include "scsi_module.c"
-
int fastlane_esp_release(struct Scsi_Host *instance)
{
#ifdef MODULE
@@ -373,4 +398,23 @@ int fastlane_esp_release(struct Scsi_Host *instance)
return 1;
}
+
+static Scsi_Host_Template driver_template = {
+ .proc_name = "esp-fastlane",
+ .proc_info = esp_proc_info,
+ .name = "Fastlane SCSI",
+ .detect = fastlane_esp_detect,
+ .release = fastlane_esp_release,
+ .queuecommand = esp_queue,
+ .eh_abort_handler = esp_abort,
+ .eh_bus_reset_handler = esp_reset,
+ .can_queue = 7,
+ .this_id = 7,
+ .sg_tablesize = SG_ALL,
+ .cmd_per_lun = 1,
+ .use_clustering = ENABLE_CLUSTERING
+};
+
+#include "scsi_module.c"
+
MODULE_LICENSE("GPL");
diff --git a/drivers/scsi/fastlane.h b/drivers/scsi/fastlane.h
deleted file mode 100644
index 57e956cf539a..000000000000
--- a/drivers/scsi/fastlane.h
+++ /dev/null
@@ -1,65 +0,0 @@
-/* fastlane.h: Defines and structures for the Fastlane SCSI driver.
- *
- * Copyright (C) 1996 Jesper Skov (jskov@cygnus.co.uk)
- */
-
-#include "NCR53C9x.h"
-
-#ifndef FASTLANE_H
-#define FASTLANE_H
-
-/* The controller registers can be found in the Z2 config area at these
- * offsets:
- */
-#define FASTLANE_ESP_ADDR 0x1000001
-#define FASTLANE_DMA_ADDR 0x1000041
-
-
-/* The Fastlane DMA interface */
-struct fastlane_dma_registers {
- volatile unsigned char cond_reg; /* DMA status (ro) [0x0000] */
-#define ctrl_reg cond_reg /* DMA control (wo) [0x0000] */
- unsigned char dmapad1[0x3f];
- volatile unsigned char clear_strobe; /* DMA clear (wo) [0x0040] */
-};
-
-
-/* DMA status bits */
-#define FASTLANE_DMA_MINT 0x80
-#define FASTLANE_DMA_IACT 0x40
-#define FASTLANE_DMA_CREQ 0x20
-
-/* DMA control bits */
-#define FASTLANE_DMA_FCODE 0xa0
-#define FASTLANE_DMA_MASK 0xf3
-#define FASTLANE_DMA_LED 0x10 /* HD led control 1 = on */
-#define FASTLANE_DMA_WRITE 0x08 /* 1 = write */
-#define FASTLANE_DMA_ENABLE 0x04 /* Enable DMA */
-#define FASTLANE_DMA_EDI 0x02 /* Enable DMA IRQ ? */
-#define FASTLANE_DMA_ESI 0x01 /* Enable SCSI IRQ */
-
-extern int fastlane_esp_detect(struct SHT *);
-extern int fastlane_esp_release(struct Scsi_Host *);
-extern const char *esp_info(struct Scsi_Host *);
-extern int esp_queue(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
-extern int esp_command(Scsi_Cmnd *);
-extern int esp_abort(Scsi_Cmnd *);
-extern int esp_reset(Scsi_Cmnd *, unsigned int);
-extern int esp_proc_info(char *buffer, char **start, off_t offset, int length,
- int hostno, int inout);
-
-#define SCSI_FASTLANE { .proc_name = "esp-fastlane", \
- .proc_info = esp_proc_info, \
- .name = "Fastlane SCSI", \
- .detect = fastlane_esp_detect, \
- .release = fastlane_esp_release, \
- .queuecommand = esp_queue, \
- .abort = esp_abort, \
- .reset = esp_reset, \
- .can_queue = 7, \
- .this_id = 7, \
- .sg_tablesize = SG_ALL, \
- .cmd_per_lun = 1, \
- .use_clustering = ENABLE_CLUSTERING }
-
-#endif /* FASTLANE_H */
diff --git a/drivers/scsi/fcal.c b/drivers/scsi/fcal.c
index ffeacdf56718..f8d8fa5adfb6 100644
--- a/drivers/scsi/fcal.c
+++ b/drivers/scsi/fcal.c
@@ -138,10 +138,14 @@ int __init fcal_detect(Scsi_Host_Template *tpnt)
continue;
}
+ if (!try_module_get(fc->module)) {
+ kfree(ages);
+ scsi_unregister(host);
+ continue;
+ }
+
nfcals++;
- if (fc->module) __MOD_INC_USE_COUNT(fc->module);
-
fcal = (struct fcal *)host->hostdata;
fc->fcp_register(fc, TYPE_SCSI_FCP, 0);
@@ -193,7 +197,7 @@ int fcal_release(struct Scsi_Host *host)
struct fcal *fcal = (struct fcal *)host->hostdata;
fc_channel *fc = fcal->fc;
- if (fc->module) __MOD_DEC_USE_COUNT(fc->module);
+ module_put(fc->module);
fc->fcp_register(fc, TYPE_SCSI_FCP, 1);
FCALND((" releasing fcal.\n"));
diff --git a/drivers/scsi/gvp11.c b/drivers/scsi/gvp11.c
index 5dece79737d7..ad2d6c301d30 100644
--- a/drivers/scsi/gvp11.c
+++ b/drivers/scsi/gvp11.c
@@ -4,6 +4,7 @@
#include <linux/sched.h>
#include <linux/version.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <asm/setup.h>
#include <asm/page.h>
@@ -355,7 +356,21 @@ release:
#include "gvp11.h"
-static Scsi_Host_Template driver_template = GVP11_SCSI;
+static Scsi_Host_Template driver_template = {
+ .proc_name = "GVP11",
+ .name = "GVP Series II SCSI",
+ .detect = gvp11_detect,
+ .release = gvp11_release,
+ .queuecommand = wd33c93_queuecommand,
+ .abort = wd33c93_abort,
+ .reset = wd33c93_reset,
+ .can_queue = CAN_QUEUE,
+ .this_id = 7,
+ .sg_tablesize = SG_ALL,
+ .cmd_per_lun = CMD_PER_LUN,
+ .use_clustering = DISABLE_CLUSTERING
+};
+
#include "scsi_module.c"
diff --git a/drivers/scsi/gvp11.h b/drivers/scsi/gvp11.h
index d95b1a63726d..c60eedbee117 100644
--- a/drivers/scsi/gvp11.h
+++ b/drivers/scsi/gvp11.h
@@ -30,21 +30,7 @@ int wd33c93_reset(Scsi_Cmnd *, unsigned int);
#define CAN_QUEUE 16
#endif
-#ifdef HOSTS_C
-
-#define GVP11_SCSI { .proc_name = "GVP11", \
- .name = "GVP Series II SCSI", \
- .detect = gvp11_detect, \
- .release = gvp11_release, \
- .queuecommand = wd33c93_queuecommand, \
- .abort = wd33c93_abort, \
- .reset = wd33c93_reset, \
- .can_queue = CAN_QUEUE, \
- .this_id = 7, \
- .sg_tablesize = SG_ALL, \
- .cmd_per_lun = CMD_PER_LUN, \
- .use_clustering = DISABLE_CLUSTERING }
-#else
+#ifndef HOSTS_C
/*
* if the transfer address ANDed with this results in a non-zero
diff --git a/drivers/scsi/jazz_esp.c b/drivers/scsi/jazz_esp.c
index 108bb4292725..29e0115ad68d 100644
--- a/drivers/scsi/jazz_esp.c
+++ b/drivers/scsi/jazz_esp.c
@@ -18,7 +18,6 @@
#include "scsi.h"
#include "hosts.h"
#include "NCR53C9x.h"
-#include "jazz_esp.h"
#include <asm/irq.h>
#include <asm/jazz.h>
@@ -273,3 +272,21 @@ static void dma_led_on(struct NCR_ESP *esp)
*(unsigned char *)JAZZ_HDC_LED = 1;
#endif
}
+
+static Scsi_Host_Template driver_template = {
+ .proc_name = "esp",
+ .proc_info = &esp_proc_info,
+ .name = "ESP 100/100a/200",
+ .detect = jazz_esp_detect,
+ .info = esp_info,
+ .command = esp_command,
+ .queuecommand = esp_queue,
+ .eh_abort_handler = esp_abort,
+ .eh_bus_reset_handler = esp_reset,
+ .can_queue = 7,
+ .this_id = 7,
+ .sg_tablesize = SG_ALL,
+ .cmd_per_lun = 1,
+ .use_clustering = DISABLE_CLUSTERING,
+};
+
diff --git a/drivers/scsi/jazz_esp.h b/drivers/scsi/jazz_esp.h
deleted file mode 100644
index 0f95410ed9a7..000000000000
--- a/drivers/scsi/jazz_esp.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/* jazz_esp.h: Defines and structures for the JAZZ SCSI driver.
- *
- * Copyright (C) 1997 Thomas Bogendoerfer (tsbogend@alpha.franken.de)
- */
-
-#ifndef JAZZ_ESP_H
-#define JAZZ_ESP_H
-
-#define EREGS_PAD(n)
-
-#include "NCR53C9x.h"
-
-
-extern int jazz_esp_detect(struct SHT *);
-extern const char *esp_info(struct Scsi_Host *);
-extern int esp_queue(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
-extern int esp_command(Scsi_Cmnd *);
-extern int esp_abort(Scsi_Cmnd *);
-extern int esp_reset(Scsi_Cmnd *, unsigned int);
-extern int esp_proc_info(char *buffer, char **start, off_t offset, int length,
- int hostno, int inout);
-
-#define SCSI_JAZZ_ESP { \
- .proc_name = "esp", \
- .proc_info = &esp_proc_info, \
- .name = "ESP 100/100a/200", \
- .detect = jazz_esp_detect, \
- .info = esp_info, \
- .command = esp_command, \
- .queuecommand = esp_queue, \
- .abort = esp_abort, \
- .reset = esp_reset, \
- .can_queue = 7, \
- .this_id = 7, \
- .sg_tablesize = SG_ALL, \
- .cmd_per_lun = 1, \
- .use_clustering = DISABLE_CLUSTERING, }
-
-#endif /* JAZZ_ESP_H */
diff --git a/drivers/scsi/mac_NCR5380.c b/drivers/scsi/mac_NCR5380.c
index 521338547345..2fe5a1c5b76e 100644
--- a/drivers/scsi/mac_NCR5380.c
+++ b/drivers/scsi/mac_NCR5380.c
@@ -578,14 +578,13 @@ static void NCR5380_print(struct Scsi_Host *instance) {
unsigned char status, data, basr, mr, icr, i;
unsigned long flags;
- save_flags(flags);
- cli();
+ local_irq_save(flags);
data = NCR5380_read(CURRENT_SCSI_DATA_REG);
status = NCR5380_read(STATUS_REG);
mr = NCR5380_read(MODE_REG);
icr = NCR5380_read(INITIATOR_COMMAND_REG);
basr = NCR5380_read(BUS_AND_STATUS_REG);
- restore_flags(flags);
+ local_irq_restore(flags);
printk("STATUS_REG: %02x ", status);
for (i = 0; signals[i].mask ; ++i)
if (status & signals[i].mask)
@@ -801,8 +800,7 @@ int NCR5380_proc_info (char *buffer, char **start, off_t offset,
}
SPRINTF("NCR5380 core release=%d.\n", NCR5380_PUBLIC_RELEASE);
check_offset();
- save_flags(flags);
- cli();
+ local_irq_save(flags);
SPRINTF("NCR5380: coroutine is%s running.\n", main_running ? "" : "n't");
check_offset();
if (!hostdata->connected)
@@ -825,7 +823,7 @@ int NCR5380_proc_info (char *buffer, char **start, off_t offset,
check_offset();
}
- restore_flags(flags);
+ local_irq_restore(flags);
*start = buffer + (offset - begin);
if (pos - buffer < offset - begin)
return 0;
@@ -999,8 +997,7 @@ int NCR5380_queue_command (Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *))
* sense data is only guaranteed to be valid while the condition exists.
*/
- save_flags(flags);
- cli();
+ local_irq_save(flags);
if (!(hostdata->issue_queue) || (cmd->cmnd[0] == REQUEST_SENSE)) {
LIST(cmd, hostdata->issue_queue);
@@ -1013,7 +1010,7 @@ int NCR5380_queue_command (Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *))
LIST(cmd, tmp);
NEXT(tmp) = cmd;
}
- restore_flags(flags);
+ local_irq_restore(flags);
QU_PRINTK("scsi%d: command added to %s of queue\n", H_NO(cmd),
(cmd->cmnd[0] == REQUEST_SENSE) ? "head" : "tail");
@@ -1077,9 +1074,9 @@ static void NCR5380_main (void)
return;
main_running = 1;
- save_flags(flags);
+ local_save_flags(flags);
do {
- cli(); /* Freeze request queues */
+ local_irq_disable(); /* Freeze request queues */
done = 1;
if (!hostdata->connected) {
@@ -1112,7 +1109,8 @@ static void NCR5380_main (void)
!(hostdata->busy[tmp->target] & (1 << tmp->lun))
#endif
) {
- cli(); /* ++guenther: just to be sure, this must be atomic */
+ /* ++guenther: just to be sure, this must be atomic */
+ local_irq_disable();
if (prev) {
REMOVE(prev, NEXT(prev), tmp, NEXT(tmp));
NEXT(prev) = NEXT(tmp);
@@ -1123,7 +1121,7 @@ static void NCR5380_main (void)
NEXT(tmp) = NULL;
/* reenable interrupts after finding one */
- restore_flags(flags);
+ local_irq_restore(flags);
/*
* Attempt to establish an I_T_L nexus here.
@@ -1152,14 +1150,14 @@ static void NCR5380_main (void)
TAG_NEXT)) {
break;
} else {
- cli();
+ local_irq_disable();
LIST(tmp, hostdata->issue_queue);
NEXT(tmp) = hostdata->issue_queue;
hostdata->issue_queue = tmp;
#ifdef SUPPORT_TAGS
cmd_free_tag( tmp );
#endif
- restore_flags(flags);
+ local_irq_restore(flags);
MAIN_PRINTK("scsi%d: main(): select() failed, "
"returned to issue_queue\n", HOSTNO);
if (hostdata->connected)
@@ -1174,7 +1172,7 @@ static void NCR5380_main (void)
&& !hostdata->dma_len
#endif
) {
- restore_flags(flags);
+ local_irq_restore(flags);
MAIN_PRINTK("scsi%d: main: performing information transfer\n",
HOSTNO);
NCR5380_information_transfer(instance);
@@ -1187,7 +1185,7 @@ static void NCR5380_main (void)
an interrupt could believe we'll pick up the work it left for
us, but we won't see it anymore here... */
main_running = 0;
- restore_flags(flags);
+ local_irq_restore(flags);
}
@@ -1428,10 +1426,9 @@ static int NCR5380_select (struct Scsi_Host *instance, Scsi_Cmnd *cmd, int tag)
* data bus during SELECTION.
*/
- save_flags(flags);
- cli();
+ local_irq_save(flags);
if (hostdata->connected) {
- restore_flags(flags);
+ local_irq_restore(flags);
return -1;
}
NCR5380_write(TARGET_COMMAND_REG, 0);
@@ -1444,7 +1441,7 @@ static int NCR5380_select (struct Scsi_Host *instance, Scsi_Cmnd *cmd, int tag)
NCR5380_write(OUTPUT_DATA_REG, hostdata->id_mask);
NCR5380_write(MODE_REG, MR_ARBITRATE);
- restore_flags(flags);
+ local_irq_restore(flags);
/* Wait for arbitration logic to complete */
#if NCR_TIMEOUT
@@ -1950,8 +1947,7 @@ static int NCR5380_transfer_dma( struct Scsi_Host *instance,
NCR5380_write(MODE_REG, MR_BASE | MR_DMA_MODE | MR_ENABLE_EOP_INTR | MR_MONITOR_BSY);
#else /* PSEUDO_DMA! */
#if defined(PSEUDO_DMA) && !defined(UNSAFE)
- save_flags(flags);
- cli();
+ local_irq_save(flags);
#endif
/* KLL May need eop and parity in 53c400 */
if (hostdata->flags & FLAG_NCR53C400)
@@ -1970,12 +1966,11 @@ static int NCR5380_transfer_dma( struct Scsi_Host *instance,
/* On the Medusa, it is a must to initialize the DMA before
* starting the NCR. This is also the cleaner way for the TT.
*/
- save_flags(flags);
- cli();
+ local_irq_save(flags);
hostdata->dma_len = (p & SR_IO) ?
NCR5380_dma_read_setup(instance, d, c) :
NCR5380_dma_write_setup(instance, d, c);
- restore_flags(flags);
+ local_irq_restore(flags);
#endif /* def REAL_DMA */
#ifndef EMULATE_PSEUDO_DMA
@@ -2120,7 +2115,7 @@ static int NCR5380_transfer_dma( struct Scsi_Host *instance,
NCR5380_print_phase(instance);
#endif
#if defined(PSEUDO_DMA) && !defined(UNSAFE)
- restore_flags(flags);
+ local_irq_restore(flags);
#endif /* defined(REAL_DMA_POLL) */
return foo;
#endif /* def REAL_DMA */
@@ -2410,12 +2405,11 @@ static void NCR5380_information_transfer (struct Scsi_Host *instance)
cmd->request_buffer = (char *) cmd->sense_buffer;
cmd->request_bufflen = sizeof(cmd->sense_buffer);
- save_flags(flags);
- cli();
+ local_irq_save(flags);
LIST(cmd,hostdata->issue_queue);
NEXT(cmd) = hostdata->issue_queue;
hostdata->issue_queue = (Scsi_Cmnd *) cmd;
- restore_flags(flags);
+ local_irq_restore(flags);
QU_PRINTK("scsi%d: REQUEST SENSE added to head of "
"issue queue\n", H_NO(cmd));
} else
@@ -2466,14 +2460,13 @@ static void NCR5380_information_transfer (struct Scsi_Host *instance)
case DISCONNECT:
/* Accept message by clearing ACK */
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
- save_flags(flags);
- cli();
+ local_irq_save(flags);
cmd->device->disconnect = 1;
LIST(cmd,hostdata->disconnected_queue);
NEXT(cmd) = hostdata->disconnected_queue;
hostdata->connected = NULL;
hostdata->disconnected_queue = cmd;
- restore_flags(flags);
+ local_irq_restore(flags);
QU_PRINTK("scsi%d: command for target %d lun %d was "
"moved from connected to the "
"disconnected_queue\n", HOSTNO,
@@ -2812,8 +2805,7 @@ int NCR5380_abort (Scsi_Cmnd *cmd)
NCR5380_print_status (instance);
- save_flags(flags);
- cli();
+ local_irq_save(flags);
ABRT_PRINTK("scsi%d: abort called basr 0x%02x, sr 0x%02x\n", HOSTNO,
NCR5380_read(BUS_AND_STATUS_REG),
@@ -2855,11 +2847,11 @@ int NCR5380_abort (Scsi_Cmnd *cmd)
#else
hostdata->busy[cmd->target] &= ~(1 << cmd->lun);
#endif
- restore_flags(flags);
+ local_irq_restore(flags);
cmd->scsi_done(cmd);
return SCSI_ABORT_SUCCESS;
} else {
-/* restore_flags(flags); */
+/* local_irq_restore(flags); */
printk("scsi%d: abort of connected command failed!\n", HOSTNO);
return SCSI_ABORT_ERROR;
}
@@ -2878,7 +2870,7 @@ int NCR5380_abort (Scsi_Cmnd *cmd)
(*prev) = NEXT(tmp);
NEXT(tmp) = NULL;
tmp->result = DID_ABORT << 16;
- restore_flags(flags);
+ local_irq_restore(flags);
ABRT_PRINTK("scsi%d: abort removed command from issue queue.\n",
HOSTNO);
/* Tagged queuing note: no tag to free here, hasn't been assigned
@@ -2899,7 +2891,7 @@ int NCR5380_abort (Scsi_Cmnd *cmd)
*/
if (hostdata->connected) {
- restore_flags(flags);
+ local_irq_restore(flags);
ABRT_PRINTK("scsi%d: abort failed, command connected.\n", HOSTNO);
return SCSI_ABORT_SNOOZE;
}
@@ -2932,7 +2924,7 @@ int NCR5380_abort (Scsi_Cmnd *cmd)
for (tmp = (Scsi_Cmnd *) hostdata->disconnected_queue; tmp;
tmp = NEXT(tmp))
if (cmd == tmp) {
- restore_flags(flags);
+ local_irq_restore(flags);
ABRT_PRINTK("scsi%d: aborting disconnected command.\n", HOSTNO);
if (NCR5380_select (instance, cmd, (int) cmd->tag))
@@ -2942,8 +2934,7 @@ int NCR5380_abort (Scsi_Cmnd *cmd)
do_abort (instance);
- save_flags(flags);
- cli();
+ local_irq_save(flags);
for (prev = (Scsi_Cmnd **) &(hostdata->disconnected_queue),
tmp = (Scsi_Cmnd *) hostdata->disconnected_queue;
tmp; prev = NEXTADDR(tmp), tmp = NEXT(tmp) )
@@ -2961,7 +2952,7 @@ int NCR5380_abort (Scsi_Cmnd *cmd)
#else
hostdata->busy[cmd->target] &= ~(1 << cmd->lun);
#endif
- restore_flags(flags);
+ local_irq_restore(flags);
tmp->scsi_done(tmp);
return SCSI_ABORT_SUCCESS;
}
@@ -2977,7 +2968,7 @@ int NCR5380_abort (Scsi_Cmnd *cmd)
* broke.
*/
- restore_flags(flags);
+ local_irq_restore(flags);
printk(KERN_INFO "scsi%d: warning : SCSI command probably completed successfully\n"
KERN_INFO " before abortion\n", HOSTNO);
@@ -3035,8 +3026,7 @@ static int NCR5380_reset( Scsi_Cmnd *cmd, unsigned int reset_flags)
* into the issue_queue (via scsi_done()), the aborted commands are
* remembered in local variables first.
*/
- save_flags(flags);
- cli();
+ local_irq_save(flags);
connected = (Scsi_Cmnd *)hostdata->connected;
hostdata->connected = NULL;
disconnected_queue = (Scsi_Cmnd *)hostdata->disconnected_queue;
@@ -3049,7 +3039,7 @@ static int NCR5380_reset( Scsi_Cmnd *cmd, unsigned int reset_flags)
#ifdef REAL_DMA
hostdata->dma_len = 0;
#endif
- restore_flags(flags);
+ local_irq_restore(flags);
/* In order to tell the mid-level code which commands were aborted,
* set the command status to DID_RESET and call scsi_done() !!!
@@ -3108,8 +3098,7 @@ static int NCR5380_reset( Scsi_Cmnd *cmd, unsigned int reset_flags)
if (hostdata->disconnected_queue)
ABRT_PRINTK("scsi%d: reset aborted disconnected command(s)\n", H_NO(cmd));
- save_flags(flags);
- cli();
+ local_irq_save(flags);
hostdata->issue_queue = NULL;
hostdata->connected = NULL;
hostdata->disconnected_queue = NULL;
@@ -3121,14 +3110,28 @@ static int NCR5380_reset( Scsi_Cmnd *cmd, unsigned int reset_flags)
#ifdef REAL_DMA
hostdata->dma_len = 0;
#endif
- restore_flags(flags);
+ local_irq_restore(flags);
/* we did no complete reset of all commands, so a wakeup is required */
return SCSI_RESET_WAKEUP | SCSI_RESET_BUS_RESET;
#endif /* 1 */
}
-static Scsi_Host_Template driver_template = MAC_NCR5380;
+static Scsi_Host_Template driver_template = {
+ .name = "Macintosh NCR5380 SCSI",
+ .detect = macscsi_detect,
+ .release = macscsi_release,
+ .info = macscsi_info,
+ .queuecommand = macscsi_queue_command,
+ .abort = macscsi_abort,
+ .reset = macscsi_reset,
+ .can_queue = CAN_QUEUE,
+ .this_id = 7,
+ .sg_tablesize = SG_ALL,
+ .cmd_per_lun = CMD_PER_LUN,
+ .use_clustering = DISABLE_CLUSTERING
+};
+
#include "scsi_module.c"
diff --git a/drivers/scsi/mac_esp.c b/drivers/scsi/mac_esp.c
index dcaa2dbe8c3f..cc01741d1416 100644
--- a/drivers/scsi/mac_esp.c
+++ b/drivers/scsi/mac_esp.c
@@ -23,11 +23,11 @@
#include <linux/proc_fs.h>
#include <linux/stat.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include "scsi.h"
#include "hosts.h"
#include "NCR53C9x.h"
-#include "mac_esp.h"
#include <asm/io.h>
@@ -41,6 +41,8 @@
#include <asm/macintosh.h>
+/* #define DEBUG_MAC_ESP */
+
#define mac_turnon_irq(x) mac_enable_irq(x)
#define mac_turnoff_irq(x) mac_disable_irq(x)
@@ -710,7 +712,22 @@ static void dma_setup_quick(struct NCR_ESP * esp, __u32 addr, int count, int wri
#endif
}
-static Scsi_Host_Template driver_template = SCSI_MAC_ESP;
+static Scsi_Host_Template driver_template = {
+ .proc_name = "esp",
+ .name = "Mac 53C9x SCSI",
+ .detect = mac_esp_detect,
+ .info = esp_info,
+ /* .command = esp_command, */
+ .queuecommand = esp_queue,
+ .eh_abort_handler = esp_abort,
+ .eh_bus_reset_handler = esp_reset,
+ .can_queue = 7,
+ .this_id = 7,
+ .sg_tablesize = SG_ALL,
+ .cmd_per_lun = 1,
+ .use_clustering = DISABLE_CLUSTERING
+};
+
#include "scsi_module.c"
diff --git a/drivers/scsi/mac_esp.h b/drivers/scsi/mac_esp.h
deleted file mode 100644
index c0113e76132a..000000000000
--- a/drivers/scsi/mac_esp.h
+++ /dev/null
@@ -1,40 +0,0 @@
-
-/*
-mac_esp.h
-
-copyright 1997 David Weis, weisd3458@uni.edu
-*/
-
-
-#include "NCR53C9x.h"
-
-#ifndef MAC_ESP_H
-#define MAC_ESP_H
-
-/* #define DEBUG_MAC_ESP */
-
-extern int mac_esp_detect(struct SHT *);
-extern const char *esp_info(struct Scsi_Host *);
-extern int esp_queue(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
-extern int esp_command(Scsi_Cmnd *);
-extern int esp_abort(Scsi_Cmnd *);
-extern int esp_reset(Scsi_Cmnd *, unsigned int);
-
-
-#define SCSI_MAC_ESP { .proc_name = "esp", \
- .name = "Mac 53C9x SCSI", \
- .detect = mac_esp_detect, \
- .release = NULL, \
- .info = esp_info, \
- /* command: esp_command, */ \
- .queuecommand = esp_queue, \
- .abort = esp_abort, \
- .reset = esp_reset, \
- .can_queue = 7, \
- .this_id = 7, \
- .sg_tablesize = SG_ALL, \
- .cmd_per_lun = 1, \
- .use_clustering = DISABLE_CLUSTERING }
-
-#endif /* MAC_ESP_H */
-
diff --git a/drivers/scsi/mac_scsi.c b/drivers/scsi/mac_scsi.c
index a1b77530096e..e045d02b5f83 100644
--- a/drivers/scsi/mac_scsi.c
+++ b/drivers/scsi/mac_scsi.c
@@ -370,9 +370,9 @@ void restore_irq(struct pt_regs *regs)
{
unsigned long flags;
- save_flags(flags);
+ local_save_flags(flags);
flags = (flags & ~0x0700) | (regs->sr & 0x0700);
- restore_flags(flags);
+ local_irq_restore(flags);
}
/*
@@ -621,10 +621,9 @@ void scsi_mac_debug (void)
NCR5380_setup(default_instance);
if(NCR5380_read(BUS_AND_STATUS_REG)&BASR_IRQ)
#endif
- save_flags(flags);
- cli();
+ local_irq_save(flags);
NCR5380_print_status(default_instance);
- restore_flags(flags);
+ local_irq_restore(flags);
}
#if 0
polled_scsi_on = 1;
@@ -651,10 +650,9 @@ void scsi_mac_polled (void)
if(NCR5380_read(BUS_AND_STATUS_REG)&BASR_IRQ)
{
printk("SCSI poll\n");
- save_flags(flags);
- cli();
+ local_irq_save(flags);
NCR5380_intr(IRQ_MAC_SCSI, instance, NULL);
- restore_flags(flags);
+ local_irq_restore(flags);
}
#if 0
}
diff --git a/drivers/scsi/mca_53c9x.c b/drivers/scsi/mca_53c9x.c
index cbadd79b29ce..9918b52216da 100644
--- a/drivers/scsi/mca_53c9x.c
+++ b/drivers/scsi/mca_53c9x.c
@@ -44,13 +44,37 @@
#include "scsi.h"
#include "hosts.h"
#include "NCR53C9x.h"
-#include "mca_53c9x.h"
#include <asm/dma.h>
#include <asm/irq.h>
#include <asm/mca_dma.h>
#include <asm/pgtable.h>
+/*
+ * From ibmmca.c (IBM scsi controller card driver) -- used for turning PS2 disk
+ * activity LED on and off
+ */
+
+#define PS2_SYS_CTR 0x92
+
+/* Ports the ncr's 53c94 can be put at; indexed by pos register value */
+
+#define MCA_53C9X_IO_PORTS { \
+ 0x0000, 0x0240, 0x0340, 0x0400, \
+ 0x0420, 0x3240, 0x8240, 0xA240, \
+ }
+
+/*
+ * Supposedly there were some cards put together with the 'c9x and 86c01. If
+ * they have different ID's from the ones on the 3500 series machines,
+ * you can add them here and hopefully things will work out.
+ */
+
+#define MCA_53C9X_IDS { \
+ 0x7F4C, \
+ 0x0000, \
+ }
+
static int dma_bytes_sent(struct NCR_ESP *, int);
static int dma_can_transfer(struct NCR_ESP *, Scsi_Cmnd *);
static void dma_dump_state(struct NCR_ESP *);
@@ -419,7 +443,22 @@ static void dma_led_off(struct NCR_ESP *esp)
outb(inb(PS2_SYS_CTR) & 0x3f, PS2_SYS_CTR);
}
-static Scsi_Host_Template driver_template = MCA_53C9X;
+static Scsi_Host_Template driver_template = {
+ .proc_name = "esp",
+ .name = "NCR 53c9x SCSI",
+ .detect = mca_esp_detect,
+ .release = mca_esp_release,
+ .queuecommand = esp_queue,
+ .eh_abort_handler = esp_abort,
+ .eh_bus_reset_handler = esp_reset,
+ .can_queue = 7,
+ .sg_tablesize = SG_ALL,
+ .cmd_per_lun = 1,
+ .unchecked_isa_dma = 1,
+ .use_clustering = DISABLE_CLUSTERING
+};
+
+
#include "scsi_module.c"
/*
diff --git a/drivers/scsi/mca_53c9x.h b/drivers/scsi/mca_53c9x.h
deleted file mode 100644
index 9b7b7df42ed8..000000000000
--- a/drivers/scsi/mca_53c9x.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/* mca_53c94.h: Defines and structures for the SCSI adapter found on NCR 35xx
- * (and maybe some other) Microchannel machines.
- *
- * Code taken mostly from Cyberstorm SCSI drivers
- * Copyright (C) 1996 Jesper Skov (jskov@cygnus.co.uk)
- *
- * Hacked to work with the NCR MCA stuff by Tymm Twillman (tymm@computer.org)
- * 1998
- */
-
-#include "NCR53C9x.h"
-
-#ifndef MCA_53C9X_H
-#define MCA_53C9X_H
-
-/*
- * From ibmmca.c (IBM scsi controller card driver) -- used for turning PS2 disk
- * activity LED on and off
- */
-
-#define PS2_SYS_CTR 0x92
-
-extern int mca_esp_detect(struct SHT *);
-extern int mca_esp_release(struct Scsi_Host *);
-extern const char *esp_info(struct Scsi_Host *);
-extern int esp_queue(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
-extern int esp_command(Scsi_Cmnd *);
-extern int esp_abort(Scsi_Cmnd *);
-extern int esp_reset(Scsi_Cmnd *, unsigned int);
-extern int esp_proc_info(char *buffer, char **start, off_t offset, int length,
- int hostno, int inout);
-
-
-#define MCA_53C9X { .proc_name = "esp", \
- .name = "NCR 53c9x SCSI", \
- .detect = mca_esp_detect, \
- .release = mca_esp_release, \
- .queuecommand = esp_queue, \
- .abort = esp_abort, \
- .reset = esp_reset, \
- .can_queue = 7, \
- .sg_tablesize = SG_ALL, \
- .cmd_per_lun = 1, \
- .unchecked_isa_dma = 1, \
- .use_clustering = DISABLE_CLUSTERING }
-
-/* Ports the ncr's 53c94 can be put at; indexed by pos register value */
-
-#define MCA_53C9X_IO_PORTS { \
- 0x0000, 0x0240, 0x0340, 0x0400, \
- 0x0420, 0x3240, 0x8240, 0xA240, \
- }
-
-/*
- * Supposedly there were some cards put together with the 'c9x and 86c01. If
- * they have different ID's from the ones on the 3500 series machines,
- * you can add them here and hopefully things will work out.
- */
-
-#define MCA_53C9X_IDS { \
- 0x7F4C, \
- 0x0000, \
- }
-
-#endif /* MCA_53C9X_H */
-
diff --git a/drivers/scsi/mvme147.c b/drivers/scsi/mvme147.c
index 81a2d699a821..5f081518ddce 100644
--- a/drivers/scsi/mvme147.c
+++ b/drivers/scsi/mvme147.c
@@ -3,6 +3,7 @@
#include <linux/blk.h>
#include <linux/sched.h>
#include <linux/version.h>
+#include <linux/interrupt.h>
#include <asm/page.h>
#include <asm/pgtable.h>
@@ -115,7 +116,21 @@ int mvme147_detect(Scsi_Host_Template *tpnt)
#include "mvme147.h"
-static Scsi_Host_Template driver_template = MVME147_SCSI;
+static Scsi_Host_Template driver_template = {
+ .proc_name = "MVME147",
+ .name = "MVME147 built-in SCSI",
+ .detect = mvme147_detect,
+ .release = mvme147_release,
+ .queuecommand = wd33c93_queuecommand,
+ .abort = wd33c93_abort,
+ .reset = wd33c93_reset,
+ .can_queue = CAN_QUEUE,
+ .this_id = 7,
+ .sg_tablesize = SG_ALL,
+ .cmd_per_lun = CMD_PER_LUN,
+ .use_clustering = ENABLE_CLUSTERING
+};
+
#include "scsi_module.c"
diff --git a/drivers/scsi/mvme147.h b/drivers/scsi/mvme147.h
index e68f86fdada0..264a9fdce90d 100644
--- a/drivers/scsi/mvme147.h
+++ b/drivers/scsi/mvme147.h
@@ -29,22 +29,4 @@ int wd33c93_reset(Scsi_Cmnd *, unsigned int);
#define CAN_QUEUE 16
#endif
-#ifdef HOSTS_C
-
-#define MVME147_SCSI {.proc_name = "MVME147", \
- .proc_info = NULL, \
- .name = "MVME147 built-in SCSI", \
- .detect = mvme147_detect, \
- .release = mvme147_release, \
- .queuecommand = wd33c93_queuecommand, \
- .abort = wd33c93_abort, \
- .reset = wd33c93_reset, \
- .can_queue = CAN_QUEUE, \
- .this_id = 7, \
- .sg_tablesize = SG_ALL, \
- .cmd_per_lun = CMD_PER_LUN, \
- .use_clustering = ENABLE_CLUSTERING }
-
-#endif /* else def HOSTS_C */
-
#endif /* MVME147_H */
diff --git a/drivers/scsi/mvme16x.c b/drivers/scsi/mvme16x.c
index dc5052dbb1c4..45df12009189 100644
--- a/drivers/scsi/mvme16x.c
+++ b/drivers/scsi/mvme16x.c
@@ -53,5 +53,18 @@ int mvme16x_scsi_detect(Scsi_Host_Template *tpnt)
return 1;
}
-static Scsi_Host_Template driver_template = MVME16x_SCSI;
+static Scsi_Host_Template driver_template = {
+ .name = "MVME16x NCR53c710 SCSI",
+ .detect = mvme16x_scsi_detect,
+ .queuecommand = NCR53c7xx_queue_command,
+ .abort = NCR53c7xx_abort,
+ .reset = NCR53c7xx_reset,
+ .can_queue = 24,
+ .this_id = 7,
+ .sg_tablesize = 63,
+ .cmd_per_lun = 3,
+ .use_clustering = DISABLE_CLUSTERING
+};
+
+
#include "scsi_module.c"
diff --git a/drivers/scsi/mvme16x.h b/drivers/scsi/mvme16x.h
index 33e4225a5980..f2e56196aff2 100644
--- a/drivers/scsi/mvme16x.h
+++ b/drivers/scsi/mvme16x.h
@@ -25,15 +25,4 @@ void NCR53c7x0_intr(int irq, void *dev_id, struct pt_regs * regs);
#include <scsi/scsicam.h>
-#define MVME16x_SCSI {.name = "MVME16x NCR53c710 SCSI", \
- .detect = mvme16x_scsi_detect, \
- .queuecommand = NCR53c7xx_queue_command, \
- .abort = NCR53c7xx_abort, \
- .reset = NCR53c7xx_reset, \
- .can_queue = 24, \
- .this_id = 7, \
- .sg_tablesize = 63, \
- .cmd_per_lun = 3, \
- .use_clustering = DISABLE_CLUSTERING }
-
#endif /* MVME16x_SCSI_H */
diff --git a/drivers/scsi/oktagon_esp.c b/drivers/scsi/oktagon_esp.c
index cef821562879..cda75b428d50 100644
--- a/drivers/scsi/oktagon_esp.c
+++ b/drivers/scsi/oktagon_esp.c
@@ -32,7 +32,6 @@
#include "scsi.h"
#include "hosts.h"
#include "NCR53C9x.h"
-#include "oktagon_esp.h"
#include <linux/zorro.h>
#include <asm/irq.h>
@@ -46,6 +45,13 @@
#include <linux/unistd.h>
+/* The controller registers can be found in the Z2 config area at these
+ * offsets:
+ */
+#define OKTAGON_ESP_ADDR 0x03000
+#define OKTAGON_DMA_ADDR 0x01000
+
+
static int dma_bytes_sent(struct NCR_ESP *esp, int fifo_count);
static int dma_can_transfer(struct NCR_ESP *esp, Scsi_Cmnd *sp);
static void dma_dump_state(struct NCR_ESP *esp);
@@ -571,12 +577,6 @@ void dma_advance_sg(Scsi_Cmnd *sp)
#define HOSTS_C
-#include "oktagon_esp.h"
-
-static Scsi_Host_Template driver_template = SCSI_OKTAGON_ESP;
-
-#include "scsi_module.c"
-
int oktagon_esp_release(struct Scsi_Host *instance)
{
#ifdef MODULE
@@ -589,4 +589,24 @@ int oktagon_esp_release(struct Scsi_Host *instance)
return 1;
}
+
+static Scsi_Host_Template driver_template = {
+ .proc_name = "esp-oktagon",
+ .proc_info = &esp_proc_info,
+ .name = "BSC Oktagon SCSI",
+ .detect = oktagon_esp_detect,
+ .release = oktagon_esp_release,
+ .queuecommand = esp_queue,
+ .eh_abort_handler = esp_abort,
+ .eh_bus_reset_handler = esp_reset,
+ .can_queue = 7,
+ .this_id = 7,
+ .sg_tablesize = SG_ALL,
+ .cmd_per_lun = 1,
+ .use_clustering = ENABLE_CLUSTERING
+};
+
+
+#include "scsi_module.c"
+
MODULE_LICENSE("GPL");
diff --git a/drivers/scsi/oktagon_esp.h b/drivers/scsi/oktagon_esp.h
deleted file mode 100644
index f4ba3350c726..000000000000
--- a/drivers/scsi/oktagon_esp.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/* oktagon_esp.h: Defines and structures for the CyberStorm SCSI Mk II driver.
- *
- * Copyright (C) 1996 Jesper Skov (jskov@cs.auc.dk)
- */
-
-#include "NCR53C9x.h"
-
-#ifndef OKTAGON_ESP_H
-#define OKTAGON_ESP_H
-
-/* The controller registers can be found in the Z2 config area at these
- * offsets:
- */
-#define OKTAGON_ESP_ADDR 0x03000
-#define OKTAGON_DMA_ADDR 0x01000
-
-
-/* The CyberStorm II DMA interface */
-struct oktagon_dma_registers {
- volatile unsigned char cond_reg; /* DMA cond (ro) [0x000] */
-#define ctrl_reg cond_reg /* DMA control (wo) [0x000] */
- unsigned char dmapad4[0x3f];
- volatile unsigned char dma_addr0; /* DMA address (MSB) [0x040] */
- unsigned char dmapad1[3];
- volatile unsigned char dma_addr1; /* DMA address [0x044] */
- unsigned char dmapad2[3];
- volatile unsigned char dma_addr2; /* DMA address [0x048] */
- unsigned char dmapad3[3];
- volatile unsigned char dma_addr3; /* DMA address (LSB) [0x04c] */
-};
-
-extern int oktagon_esp_detect(struct SHT *);
-extern int oktagon_esp_release(struct Scsi_Host *);
-extern const char *esp_info(struct Scsi_Host *);
-extern int esp_queue(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
-extern int esp_command(Scsi_Cmnd *);
-extern int esp_abort(Scsi_Cmnd *);
-extern int esp_reset(Scsi_Cmnd *, unsigned int);
-extern int esp_proc_info(char *buffer, char **start, off_t offset, int length,
- int hostno, int inout);
-
-#define SCSI_OKTAGON_ESP { \
- .proc_name = "esp-oktagon", \
- .proc_info = &esp_proc_info, \
- .name = "BSC Oktagon SCSI", \
- .detect = oktagon_esp_detect, \
- .release = oktagon_esp_release, \
- .queuecommand = esp_queue, \
- .abort = esp_abort, \
- .reset = esp_reset, \
- .can_queue = 7, \
- .this_id = 7, \
- .sg_tablesize = SG_ALL, \
- .cmd_per_lun = 1, \
- .use_clustering = ENABLE_CLUSTERING }
-
-#endif /* OKTAGON_ESP_H */
diff --git a/drivers/scsi/pluto.c b/drivers/scsi/pluto.c
index 84024bc0adb9..3c3452557f8b 100644
--- a/drivers/scsi/pluto.c
+++ b/drivers/scsi/pluto.c
@@ -232,10 +232,14 @@ int __init pluto_detect(Scsi_Host_Template *tpnt)
continue;
}
+ if (!try_module_get(fc->module)) {
+ kfree(ages);
+ scsi_unregister(host);
+ continue;
+ }
+
nplutos++;
- if (fc->module) __MOD_INC_USE_COUNT(fc->module);
-
pluto = (struct pluto *)host->hostdata;
host->max_id = inq->targets;
diff --git a/drivers/scsi/sun3_NCR5380.c b/drivers/scsi/sun3_NCR5380.c
index 1dd34aeb225e..62ee4cf8e5f3 100644
--- a/drivers/scsi/sun3_NCR5380.c
+++ b/drivers/scsi/sun3_NCR5380.c
@@ -567,14 +567,13 @@ static void NCR5380_print(struct Scsi_Host *instance) {
unsigned char status, data, basr, mr, icr, i;
unsigned long flags;
- save_flags(flags);
- cli();
+ local_irq_save(flags);
data = NCR5380_read(CURRENT_SCSI_DATA_REG);
status = NCR5380_read(STATUS_REG);
mr = NCR5380_read(MODE_REG);
icr = NCR5380_read(INITIATOR_COMMAND_REG);
basr = NCR5380_read(BUS_AND_STATUS_REG);
- restore_flags(flags);
+ local_irq_restore(flags);
printk("STATUS_REG: %02x ", status);
for (i = 0; signals[i].mask ; ++i)
if (status & signals[i].mask)
@@ -772,9 +771,7 @@ static int NCR5380_proc_info (char *buffer, char **start, off_t offset,
} \
} while (0)
- for (instance = first_instance; instance && HOSTNO != hostno;
- instance = instance->next)
- ;
+ instance = scsi_host_hn_get(hostno);
if (!instance)
return(-ESRCH);
hostdata = (struct NCR5380_hostdata *)instance->hostdata;
@@ -784,8 +781,7 @@ static int NCR5380_proc_info (char *buffer, char **start, off_t offset,
}
SPRINTF("NCR5380 core release=%d.\n", NCR5380_PUBLIC_RELEASE);
check_offset();
- save_flags(flags);
- cli();
+ local_irq_save(flags);
SPRINTF("NCR5380: coroutine is%s running.\n", main_running ? "" : "n't");
check_offset();
if (!hostdata->connected)
@@ -808,7 +804,7 @@ static int NCR5380_proc_info (char *buffer, char **start, off_t offset,
check_offset();
}
- restore_flags(flags);
+ local_irq_restore(flags);
*start = buffer + (offset - begin);
if (pos - buffer < offset - begin)
return 0;
@@ -978,8 +974,7 @@ static int NCR5380_queue_command (Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *))
* sense data is only guaranteed to be valid while the condition exists.
*/
- save_flags(flags);
- cli();
+ local_irq_save(flags);
/* ++guenther: now that the issue queue is being set up, we can lock ST-DMA.
* Otherwise a running NCR5380_main may steal the lock.
* Lock before actually inserting due to fairness reasons explained in
@@ -1004,7 +999,7 @@ static int NCR5380_queue_command (Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *))
NEXT(tmp) = cmd;
}
- restore_flags(flags);
+ local_irq_restore(flags);
QU_PRINTK("scsi%d: command added to %s of queue\n", H_NO(cmd),
(cmd->cmnd[0] == REQUEST_SENSE) ? "head" : "tail");
@@ -1068,9 +1063,9 @@ static void NCR5380_main (void)
return;
main_running = 1;
- save_flags(flags);
+ local_save_flags(flags);
do {
- cli(); /* Freeze request queues */
+ local_irq_disable(flags); /* Freeze request queues */
done = 1;
if (!hostdata->connected) {
@@ -1103,7 +1098,8 @@ static void NCR5380_main (void)
!(hostdata->busy[tmp->target] & (1 << tmp->lun))
#endif
) {
- cli(); /* ++guenther: just to be sure, this must be atomic */
+ /* ++guenther: just to be sure, this must be atomic */
+ local_irq_disable();
if (prev) {
REMOVE(prev, NEXT(prev), tmp, NEXT(tmp));
NEXT(prev) = NEXT(tmp);
@@ -1114,7 +1110,7 @@ static void NCR5380_main (void)
NEXT(tmp) = NULL;
/* reenable interrupts after finding one */
- restore_flags(flags);
+ local_irq_restore(flags);
/*
* Attempt to establish an I_T_L nexus here.
@@ -1143,14 +1139,14 @@ static void NCR5380_main (void)
TAG_NEXT)) {
break;
} else {
- cli();
+ local_irq_disable();
LIST(tmp, hostdata->issue_queue);
NEXT(tmp) = hostdata->issue_queue;
hostdata->issue_queue = tmp;
#ifdef SUPPORT_TAGS
cmd_free_tag( tmp );
#endif
- restore_flags(flags);
+ local_irq_restore(flags);
MAIN_PRINTK("scsi%d: main(): select() failed, "
"returned to issue_queue\n", HOSTNO);
if (hostdata->connected)
@@ -1164,7 +1160,7 @@ static void NCR5380_main (void)
&& !hostdata->dma_len
#endif
) {
- restore_flags(flags);
+ local_irq_restore(flags);
MAIN_PRINTK("scsi%d: main: performing information transfer\n",
HOSTNO);
NCR5380_information_transfer(instance);
@@ -1177,7 +1173,7 @@ static void NCR5380_main (void)
an interrupt could believe we'll pick up the work it left for
us, but we won't see it anymore here... */
main_running = 0;
- restore_flags(flags);
+ local_irq_restore(flags);
}
@@ -1418,10 +1414,9 @@ static int NCR5380_select (struct Scsi_Host *instance, Scsi_Cmnd *cmd, int tag)
* data bus during SELECTION.
*/
- save_flags(flags);
- cli();
+ local_irq_save(flags);
if (hostdata->connected) {
- restore_flags(flags);
+ local_irq_restore(flags);
return -1;
}
NCR5380_write(TARGET_COMMAND_REG, 0);
@@ -1434,7 +1429,7 @@ static int NCR5380_select (struct Scsi_Host *instance, Scsi_Cmnd *cmd, int tag)
NCR5380_write(OUTPUT_DATA_REG, hostdata->id_mask);
NCR5380_write(MODE_REG, MR_ARBITRATE);
- restore_flags(flags);
+ local_irq_restore(flags);
/* Wait for arbitration logic to complete */
#if NCR_TIMEOUT
@@ -1931,8 +1926,7 @@ static int NCR5380_transfer_dma( struct Scsi_Host *instance,
c, (p & SR_IO) ? "to" : "from", *data);
/* netbsd turns off ints here, why not be safe and do it too */
- save_flags(flags);
- cli();
+ local_irq_save(flags);
/* send start chain */
sun3scsi_dma_start(c, *data);
@@ -1955,7 +1949,7 @@ static int NCR5380_transfer_dma( struct Scsi_Host *instance,
dregs->csr |= CSR_DMA_ENABLE;
#endif
- restore_flags(flags);
+ local_irq_restore(flags);
sun3_dma_active = 1;
return 0;
@@ -2275,12 +2269,11 @@ static void NCR5380_information_transfer (struct Scsi_Host *instance)
cmd->request_buffer = (char *) cmd->sense_buffer;
cmd->request_bufflen = sizeof(cmd->sense_buffer);
- save_flags(flags);
- cli();
+ local_irq_save(flags);
LIST(cmd,hostdata->issue_queue);
NEXT(cmd) = hostdata->issue_queue;
hostdata->issue_queue = (Scsi_Cmnd *) cmd;
- restore_flags(flags);
+ local_irq_restore(flags);
QU_PRINTK("scsi%d: REQUEST SENSE added to head of "
"issue queue\n", H_NO(cmd));
} else
@@ -2331,14 +2324,13 @@ static void NCR5380_information_transfer (struct Scsi_Host *instance)
case DISCONNECT:
/* Accept message by clearing ACK */
NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
- save_flags(flags);
- cli();
+ local_irq_save(flags);
cmd->device->disconnect = 1;
LIST(cmd,hostdata->disconnected_queue);
NEXT(cmd) = hostdata->disconnected_queue;
hostdata->connected = NULL;
hostdata->disconnected_queue = cmd;
- restore_flags(flags);
+ local_irq_restore(flags);
QU_PRINTK("scsi%d: command for target %d lun %d was "
"moved from connected to the "
"disconnected_queue\n", HOSTNO,
@@ -2704,8 +2696,7 @@ static int NCR5380_abort (Scsi_Cmnd *cmd)
NCR5380_print_status (instance);
- save_flags(flags);
- cli();
+ local_irq_save(flags);
ABRT_PRINTK("scsi%d: abort called basr 0x%02x, sr 0x%02x\n", HOSTNO,
NCR5380_read(BUS_AND_STATUS_REG),
@@ -2747,11 +2738,11 @@ static int NCR5380_abort (Scsi_Cmnd *cmd)
#else
hostdata->busy[cmd->target] &= ~(1 << cmd->lun);
#endif
- restore_flags(flags);
+ local_irq_restore(flags);
cmd->scsi_done(cmd);
return SCSI_ABORT_SUCCESS;
} else {
-/* restore_flags(flags); */
+/* local_irq_restore(flags); */
printk("scsi%d: abort of connected command failed!\n", HOSTNO);
return SCSI_ABORT_ERROR;
}
@@ -2770,7 +2761,7 @@ static int NCR5380_abort (Scsi_Cmnd *cmd)
(*prev) = NEXT(tmp);
NEXT(tmp) = NULL;
tmp->result = DID_ABORT << 16;
- restore_flags(flags);
+ local_irq_restore(flags);
ABRT_PRINTK("scsi%d: abort removed command from issue queue.\n",
HOSTNO);
/* Tagged queuing note: no tag to free here, hasn't been assigned
@@ -2791,7 +2782,7 @@ static int NCR5380_abort (Scsi_Cmnd *cmd)
*/
if (hostdata->connected) {
- restore_flags(flags);
+ local_irq_restore(flags);
ABRT_PRINTK("scsi%d: abort failed, command connected.\n", HOSTNO);
return SCSI_ABORT_SNOOZE;
}
@@ -2824,7 +2815,7 @@ static int NCR5380_abort (Scsi_Cmnd *cmd)
for (tmp = (Scsi_Cmnd *) hostdata->disconnected_queue; tmp;
tmp = NEXT(tmp))
if (cmd == tmp) {
- restore_flags(flags);
+ local_irq_restore(flags);
ABRT_PRINTK("scsi%d: aborting disconnected command.\n", HOSTNO);
if (NCR5380_select (instance, cmd, (int) cmd->tag))
@@ -2834,8 +2825,7 @@ static int NCR5380_abort (Scsi_Cmnd *cmd)
do_abort (instance);
- save_flags(flags);
- cli();
+ local_irq_save(flags);
for (prev = (Scsi_Cmnd **) &(hostdata->disconnected_queue),
tmp = (Scsi_Cmnd *) hostdata->disconnected_queue;
tmp; prev = NEXTADDR(tmp), tmp = NEXT(tmp) )
@@ -2853,7 +2843,7 @@ static int NCR5380_abort (Scsi_Cmnd *cmd)
#else
hostdata->busy[cmd->target] &= ~(1 << cmd->lun);
#endif
- restore_flags(flags);
+ local_irq_restore(flags);
tmp->scsi_done(tmp);
return SCSI_ABORT_SUCCESS;
}
@@ -2869,7 +2859,7 @@ static int NCR5380_abort (Scsi_Cmnd *cmd)
* broke.
*/
- restore_flags(flags);
+ local_irq_restore(flags);
printk(KERN_INFO "scsi%d: warning : SCSI command probably completed successfully\n"
KERN_INFO " before abortion\n", HOSTNO);
@@ -2923,8 +2913,7 @@ static int NCR5380_reset( Scsi_Cmnd *cmd, unsigned int reset_flags)
* into the issue_queue (via scsi_done()), the aborted commands are
* remembered in local variables first.
*/
- save_flags(flags);
- cli();
+ local_irq_save(flags);
connected = (Scsi_Cmnd *)hostdata->connected;
hostdata->connected = NULL;
disconnected_queue = (Scsi_Cmnd *)hostdata->disconnected_queue;
@@ -2937,7 +2926,7 @@ static int NCR5380_reset( Scsi_Cmnd *cmd, unsigned int reset_flags)
#ifdef REAL_DMA
hostdata->dma_len = 0;
#endif
- restore_flags(flags);
+ local_irq_restore(flags);
/* In order to tell the mid-level code which commands were aborted,
* set the command status to DID_RESET and call scsi_done() !!!
@@ -2997,8 +2986,7 @@ static int NCR5380_reset( Scsi_Cmnd *cmd, unsigned int reset_flags)
if (hostdata->disconnected_queue)
ABRT_PRINTK("scsi%d: reset aborted disconnected command(s)\n", H_NO(cmd));
- save_flags(flags);
- cli();
+ local_irq_save(flags);
hostdata->issue_queue = NULL;
hostdata->connected = NULL;
hostdata->disconnected_queue = NULL;
@@ -3010,7 +2998,7 @@ static int NCR5380_reset( Scsi_Cmnd *cmd, unsigned int reset_flags)
#ifdef REAL_DMA
hostdata->dma_len = 0;
#endif
- restore_flags(flags);
+ local_irq_restore(flags);
/* we did no complete reset of all commands, so a wakeup is required */
return SCSI_RESET_WAKEUP | SCSI_RESET_BUS_RESET;
diff --git a/drivers/scsi/sun3_scsi.c b/drivers/scsi/sun3_scsi.c
index 502f764b4233..7fd253d96f8a 100644
--- a/drivers/scsi/sun3_scsi.c
+++ b/drivers/scsi/sun3_scsi.c
@@ -402,10 +402,9 @@ void sun3_sun3_debug (void)
NCR5380_local_declare();
if (default_instance) {
- save_flags(flags);
- cli();
+ local_irq_save(flags);
NCR5380_print_status(default_instance);
- restore_flags(flags);
+ local_irq_restore(flags);
}
}
#endif
@@ -616,7 +615,21 @@ static int sun3scsi_dma_finish(int write_flag)
#include "sun3_NCR5380.c"
-static Scsi_Host_Template driver_template = SUN3_NCR5380;
+static Scsi_Host_Template driver_template = {
+ .name = SUN3_SCSI_NAME,
+ .detect = sun3scsi_detect,
+ .release = sun3scsi_release,
+ .info = sun3scsi_info,
+ .queuecommand = sun3scsi_queue_command,
+ .abort = sun3scsi_abort,
+ .reset = sun3scsi_reset,
+ .can_queue = CAN_QUEUE,
+ .this_id = 7,
+ .sg_tablesize = SG_TABLESIZE,
+ .cmd_per_lun = CMD_PER_LUN,
+ .use_clustering = DISABLE_CLUSTERING
+};
+
#include "scsi_module.c"
diff --git a/drivers/scsi/sun3_scsi.h b/drivers/scsi/sun3_scsi.h
index 230f8c31c9ab..b7a569b3d2bb 100644
--- a/drivers/scsi/sun3_scsi.h
+++ b/drivers/scsi/sun3_scsi.h
@@ -93,22 +93,6 @@ static int sun3scsi_release (struct Scsi_Host *);
#define SUN3_SCSI_NAME "Sun3 NCR5380 SCSI"
#endif
-#define SUN3_NCR5380 { \
-.name = SUN3_SCSI_NAME, \
-.detect = sun3scsi_detect, \
-.release = sun3scsi_release, /* Release */ \
-.info = sun3scsi_info, \
-.queuecommand = sun3scsi_queue_command, \
-.abort = sun3scsi_abort, \
-.reset = sun3scsi_reset, \
-.can_queue = CAN_QUEUE, /* can queue */ \
-.this_id = 7, /* id */ \
-.sg_tablesize = SG_TABLESIZE, /* sg_tablesize */ \
-.cmd_per_lun = CMD_PER_LUN, /* cmd per lun */ \
-.unchecked_isa_dma = 0, /* unchecked_isa_dma */ \
-.use_clustering = DISABLE_CLUSTERING \
- }
-
#ifndef HOSTS_C
#define NCR5380_implementation_fields \
diff --git a/drivers/scsi/sun3_scsi_vme.c b/drivers/scsi/sun3_scsi_vme.c
index f6f2b810f577..056a65cd4551 100644
--- a/drivers/scsi/sun3_scsi_vme.c
+++ b/drivers/scsi/sun3_scsi_vme.c
@@ -387,10 +387,9 @@ void sun3_sun3_debug (void)
NCR5380_local_declare();
if (default_instance) {
- save_flags(flags);
- cli();
+ local_irq_save(flags);
NCR5380_print_status(default_instance);
- restore_flags(flags);
+ local_irq_restore(flags);
}
}
#endif
@@ -561,7 +560,21 @@ static int sun3scsi_dma_finish(int write_flag)
#include "sun3_NCR5380.c"
-static Scsi_Host_Template driver_template = SUN3_NCR5380;
+static Scsi_Host_Template driver_template = {
+ .name = SUN3_SCSI_NAME,
+ .detect = sun3scsi_detect,
+ .release = sun3scsi_release,
+ .info = sun3scsi_info,
+ .queuecommand = sun3scsi_queue_command,
+ .abort = sun3scsi_abort,
+ .reset = sun3scsi_reset,
+ .can_queue = CAN_QUEUE,
+ .this_id = 7,
+ .sg_tablesize = SG_TABLESIZE,
+ .cmd_per_lun = CMD_PER_LUN,
+ .use_clustering = DISABLE_CLUSTERING
+};
+
#include "scsi_module.c"
diff --git a/drivers/scsi/sun3x_esp.c b/drivers/scsi/sun3x_esp.c
index 76607c5e190a..bfbdf74c018b 100644
--- a/drivers/scsi/sun3x_esp.c
+++ b/drivers/scsi/sun3x_esp.c
@@ -13,12 +13,12 @@
#include <linux/proc_fs.h>
#include <linux/stat.h>
#include <linux/delay.h>
+#include <linux/interrupt.h>
#include "scsi.h"
#include "hosts.h"
#include "NCR53C9x.h"
-#include "sun3x_esp.h"
#include <asm/sun3x.h>
#include <asm/dvma.h>
#include <asm/irq.h>
@@ -374,7 +374,23 @@ static void dma_advance_sg (Scsi_Cmnd *sp)
sp->SCp.ptr = (char *)((unsigned long)sp->SCp.buffer->dvma_address);
}
-static Scsi_Host_Template driver_template = SCSI_SUN3X_ESP;
+static Scsi_Host_Template driver_template = {
+ .proc_name = "esp",
+ .proc_info = &esp_proc_info,
+ .name = "Sun ESP 100/100a/200",
+ .detect = sun3x_esp_detect,
+ .info = esp_info,
+ .command = esp_command,
+ .queuecommand = esp_queue,
+ .eh_abort_handler = esp_abort,
+ .eh_bus_reset_handler = esp_reset,
+ .can_queue = 7,
+ .this_id = 7,
+ .sg_tablesize = SG_ALL,
+ .cmd_per_lun = 1,
+ .use_clustering = DISABLE_CLUSTERING,
+};
+
#include "scsi_module.c"
diff --git a/drivers/scsi/sun3x_esp.h b/drivers/scsi/sun3x_esp.h
deleted file mode 100644
index 653a775ef185..000000000000
--- a/drivers/scsi/sun3x_esp.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/* sun3x_esp.h: Defines and structures for the Sun3x ESP
- *
- * (C) 1995 Thomas Bogendoerfer (tsbogend@alpha.franken.de)
- */
-
-#ifndef _SUN3X_ESP_H
-#define _SUN3X_ESP_H
-
-/* For dvma controller register definitions. */
-#include <asm/dvma.h>
-
-extern int sun3x_esp_detect(struct SHT *);
-extern const char *esp_info(struct Scsi_Host *);
-extern int esp_queue(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
-extern int esp_command(Scsi_Cmnd *);
-extern int esp_abort(Scsi_Cmnd *);
-extern int esp_reset(Scsi_Cmnd *, unsigned int);
-extern int esp_proc_info(char *buffer, char **start, off_t offset, int length,
- int hostno, int inout);
-
-#define DMA_PORTS_P (dregs->cond_reg & DMA_INT_ENAB)
-
-#define SCSI_SUN3X_ESP { \
- .proc_name = "esp", \
- .proc_info = &esp_proc_info, \
- .name = "Sun ESP 100/100a/200", \
- .detect = sun3x_esp_detect, \
- .info = esp_info, \
- .command = esp_command, \
- .queuecommand = esp_queue, \
- .abort = esp_abort, \
- .reset = esp_reset, \
- .can_queue = 7, \
- .this_id = 7, \
- .sg_tablesize = SG_ALL, \
- .cmd_per_lun = 1, \
- .use_clustering = DISABLE_CLUSTERING, }
-
-#endif /* !(_SUN3X_ESP_H) */
diff --git a/drivers/scsi/wd33c93.c b/drivers/scsi/wd33c93.c
index 4ce9a4a76ec0..37bb9c87e677 100644
--- a/drivers/scsi/wd33c93.c
+++ b/drivers/scsi/wd33c93.c
@@ -315,7 +315,6 @@ int wd33c93_queuecommand (Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *))
{
struct WD33C93_hostdata *hostdata;
Scsi_Cmnd *tmp;
- unsigned long flags;
hostdata = (struct WD33C93_hostdata *)cmd->host->hostdata;
@@ -385,8 +384,7 @@ DB(DB_QUEUE_COMMAND,printk("Q-%d-%02x-%ld( ",cmd->target,cmd->cmnd[0],cmd->pid))
* sense data is not lost before REQUEST_SENSE executes.
*/
- save_flags(flags);
- cli();
+ spin_lock_irq(&hostdata->lock);
if (!(hostdata->input_Q) || (cmd->cmnd[0] == REQUEST_SENSE)) {
cmd->host_scribble = (uchar *)hostdata->input_Q;
@@ -407,7 +405,7 @@ DB(DB_QUEUE_COMMAND,printk("Q-%d-%02x-%ld( ",cmd->target,cmd->cmnd[0],cmd->pid))
DB(DB_QUEUE_COMMAND,printk(")Q-%ld ",cmd->pid))
- restore_flags(flags);
+ spin_unlock_irq(&hostdata->lock);
return 0;
}
@@ -765,7 +763,7 @@ unsigned long length, flags;
if (!(asr & ASR_INT) || (asr & ASR_BSY))
return;
- save_flags(flags);
+ spin_lock_irqsave(&hostdata->lock, flags);
#ifdef PROC_STATISTICS
hostdata->int_cnt++;
@@ -831,7 +829,7 @@ DB(DB_INTR,printk("TIMEOUT"))
* is here...
*/
- restore_flags(flags);
+ spin_unlock_irqrestore(&hostdata->lock, flags);
/* We are not connected to a target - check to see if there
* are commands waiting to be executed.
@@ -885,7 +883,8 @@ printk(" sending SDTR ");
hostdata->outgoing_len = 1;
hostdata->state = S_CONNECTED;
- break;
+ spin_unlock_irqrestore(&hostdata->lock, flags);
+ break;
case CSR_XFER_DONE|PHS_DATA_IN:
@@ -895,7 +894,8 @@ DB(DB_INTR,printk("IN-%d.%d",cmd->SCp.this_residual,cmd->SCp.buffers_residual))
transfer_bytes(regs, cmd, DATA_IN_DIR);
if (hostdata->state != S_RUNNING_LEVEL2)
hostdata->state = S_CONNECTED;
- break;
+ spin_unlock_irqrestore(&hostdata->lock, flags);
+ break;
case CSR_XFER_DONE|PHS_DATA_OUT:
@@ -905,7 +905,8 @@ DB(DB_INTR,printk("OUT-%d.%d",cmd->SCp.this_residual,cmd->SCp.buffers_residual))
transfer_bytes(regs, cmd, DATA_OUT_DIR);
if (hostdata->state != S_RUNNING_LEVEL2)
hostdata->state = S_CONNECTED;
- break;
+ spin_unlock_irqrestore(&hostdata->lock, flags);
+ break;
/* Note: this interrupt should not occur in a LEVEL2 command */
@@ -916,7 +917,8 @@ DB(DB_INTR,printk("OUT-%d.%d",cmd->SCp.this_residual,cmd->SCp.buffers_residual))
DB(DB_INTR,printk("CMND-%02x,%ld",cmd->cmnd[0],cmd->pid))
transfer_pio(regs, cmd->cmnd, cmd->cmd_len, DATA_OUT_DIR, hostdata);
hostdata->state = S_CONNECTED;
- break;
+ spin_unlock_irqrestore(&hostdata->lock, flags);
+ break;
case CSR_XFER_DONE|PHS_STATUS:
@@ -935,7 +937,8 @@ DB(DB_INTR,printk("%02x",cmd->SCp.Status))
else {
hostdata->state = S_CONNECTED;
}
- break;
+ spin_unlock_irqrestore(&hostdata->lock, flags);
+ break;
case CSR_XFER_DONE|PHS_MESS_IN:
@@ -1085,7 +1088,7 @@ printk("sync_xfer=%02x",hostdata->sync_xfer[cmd->target]);
write_wd33c93_cmd(regs, WD_CMD_NEGATE_ACK);
hostdata->state = S_CONNECTED;
}
- restore_flags(flags);
+ spin_unlock_irqrestore(&hostdata->lock, flags);
break;
@@ -1117,12 +1120,13 @@ DB(DB_INTR,printk(":%d.%d",cmd->SCp.Status,lun))
/* We are no longer connected to a target - check to see if
* there are commands waiting to be executed.
*/
- restore_flags(flags);
+ spin_unlock_irqrestore(&hostdata->lock, flags);
wd33c93_execute(instance);
}
else {
printk("%02x:%02x:%02x-%ld: Unknown SEL_XFER_DONE phase!!---",asr,sr,phs,cmd->pid);
- }
+ spin_unlock_irqrestore(&hostdata->lock, flags);
+ }
break;
@@ -1133,7 +1137,8 @@ DB(DB_INTR,printk("SDP"))
hostdata->state = S_RUNNING_LEVEL2;
write_wd33c93(regs, WD_COMMAND_PHASE, 0x41);
write_wd33c93_cmd(regs, WD_CMD_SEL_ATN_XFER);
- break;
+ spin_unlock_irqrestore(&hostdata->lock, flags);
+ break;
case CSR_XFER_DONE|PHS_MESS_OUT:
@@ -1163,7 +1168,8 @@ DB(DB_INTR,printk("MSG_OUT="))
DB(DB_INTR,printk("%02x",hostdata->outgoing_msg[0]))
hostdata->outgoing_len = 0;
hostdata->state = S_CONNECTED;
- break;
+ spin_unlock_irqrestore(&hostdata->lock, flags);
+ break;
case CSR_UNEXP_DISC:
@@ -1184,7 +1190,8 @@ DB(DB_INTR,printk("%02x",hostdata->outgoing_msg[0]))
if (cmd == NULL) {
printk(" - Already disconnected! ");
hostdata->state = S_UNCONNECTED;
- return;
+ spin_unlock_irqrestore(&hostdata->lock, flags);
+ return;
}
DB(DB_INTR,printk("UNEXP_DISC-%ld",cmd->pid))
hostdata->connected = NULL;
@@ -1200,7 +1207,7 @@ DB(DB_INTR,printk("UNEXP_DISC-%ld",cmd->pid))
* there are commands waiting to be executed.
*/
/* look above for comments on scsi_done() */
- restore_flags(flags);
+ spin_unlock_irqrestore(&hostdata->lock, flags);
wd33c93_execute(instance);
break;
@@ -1228,7 +1235,6 @@ DB(DB_INTR,printk(":%d",cmd->SCp.Status))
else
cmd->result = cmd->SCp.Status | (cmd->SCp.Message << 8);
cmd->scsi_done(cmd);
- restore_flags(flags);
break;
case S_PRE_TMP_DISC:
case S_RUNNING_LEVEL2:
@@ -1250,6 +1256,7 @@ DB(DB_INTR,printk(":%d",cmd->SCp.Status))
/* We are no longer connected to a target - check to see if
* there are commands waiting to be executed.
*/
+ spin_unlock_irqrestore(&hostdata->lock, flags);
wd33c93_execute(instance);
break;
@@ -1367,7 +1374,8 @@ DB(DB_INTR,printk("RESEL%s", sr == CSR_RESEL_AM ? "_AM" : ""))
if (!cmd) {
printk("---TROUBLE: target %d.%d not in disconnect queue---",id,lun);
- return;
+ spin_unlock_irqrestore(&hostdata->lock, flags);
+ return;
}
/* Ok, found the command - now start it up again. */
@@ -1397,10 +1405,12 @@ DB(DB_INTR,printk("RESEL%s", sr == CSR_RESEL_AM ? "_AM" : ""))
hostdata->state = S_CONNECTED;
DB(DB_INTR,printk("-%ld",cmd->pid))
- break;
+ spin_unlock_irqrestore(&hostdata->lock, flags);
+ break;
default:
printk("--UNKNOWN INTERRUPT:%02x:%02x:%02x--",asr,sr,phs);
+ spin_unlock_irqrestore(&hostdata->lock, flags);
}
DB(DB_INTR,printk("} "))
@@ -1830,12 +1840,9 @@ char buf[32];
#endif
- { unsigned long flags;
- save_flags(flags);
- cli();
- reset_wd33c93(instance);
- restore_flags(flags);
- }
+ spin_lock_irq(&hostdata->lock);
+ reset_wd33c93(instance);
+ spin_unlock_irq(&hostdata->lock);
printk("wd33c93-%d: chip=%s/%d no_sync=0x%x no_dma=%d",instance->host_no,
(hostdata->chip==C_WD33C93)?"WD33c93":
@@ -1863,7 +1870,6 @@ int wd33c93_proc_info(char *buf, char **start, off_t off, int len, int hn, int i
char *bp;
char tbuf[128];
-unsigned long flags;
struct Scsi_Host *instance;
struct WD33C93_hostdata *hd;
Scsi_Cmnd *cmd;
@@ -1928,8 +1934,7 @@ static int stop = 0;
return len;
}
- save_flags(flags);
- cli();
+ spin_lock_irq(&hd->lock);
bp = buf;
*bp = '\0';
if (hd->proc & PR_VERSION) {
@@ -2004,7 +2009,7 @@ static int stop = 0;
}
}
strcat(bp,"\n");
- restore_flags(flags);
+ spin_unlock_irq(&hd->lock);
*start = buf;
if (stop) {
stop = 0;
diff --git a/drivers/scsi/wd33c93.h b/drivers/scsi/wd33c93.h
index 7d55ed8bd47f..47fd46fc4022 100644
--- a/drivers/scsi/wd33c93.h
+++ b/drivers/scsi/wd33c93.h
@@ -217,6 +217,7 @@ struct sx_period {
struct WD33C93_hostdata {
struct Scsi_Host *next;
wd33c93_regs regs;
+ spinlock_t lock;
uchar clock_freq;
uchar chip; /* what kind of wd33c93? */
uchar microcode; /* microcode rev */
diff --git a/drivers/serial/core.c b/drivers/serial/core.c
index 4e6c1a543e55..4e4c736318bb 100644
--- a/drivers/serial/core.c
+++ b/drivers/serial/core.c
@@ -396,7 +396,7 @@ uart_get_divisor(struct uart_port *port, struct termios *termios,
baud = uart_get_baud_rate(port, termios);
quot = uart_calculate_quot(port, baud);
if (quot)
- break;
+ return quot;
/*
* Oops, the quotient was zero. Try again with
@@ -1294,8 +1294,7 @@ static void uart_close(struct tty_struct *tty, struct file *filp)
wake_up_interruptible(&info->open_wait);
done:
- if (drv->owner)
- __MOD_DEC_USE_COUNT(drv->owner);
+ module_put(drv->owner);
}
static void uart_wait_until_sent(struct tty_struct *tty, int timeout)
@@ -1665,8 +1664,7 @@ static int uart_open(struct tty_struct *tty, struct file *filp)
return retval;
out:
- if (drv->owner)
- __MOD_DEC_USE_COUNT(drv->owner);
+ module_put(drv->owner);
fail:
return retval;
}
diff --git a/drivers/usb/class/audio.c b/drivers/usb/class/audio.c
index d3fe8391953f..79f0f552f7b6 100644
--- a/drivers/usb/class/audio.c
+++ b/drivers/usb/class/audio.c
@@ -3815,7 +3815,7 @@ static int usb_audio_probe(struct usb_interface *intf,
}
s = usb_audio_parsecontrol(dev, buffer, buflen, intf->altsetting->desc.bInterfaceNumber);
if (s) {
- dev_set_drvdata (&intf->dev, s);
+ usb_set_intfdata (intf, s);
return 0;
}
return -ENODEV;
@@ -3826,7 +3826,7 @@ static int usb_audio_probe(struct usb_interface *intf,
static void usb_audio_disconnect(struct usb_interface *intf)
{
- struct usb_audio_state *s = dev_get_drvdata (&intf->dev);
+ struct usb_audio_state *s = usb_get_intfdata (intf);
struct list_head *list;
struct usb_audiodev *as;
struct usb_mixerdev *ms;
@@ -3846,7 +3846,7 @@ static void usb_audio_disconnect(struct usb_interface *intf)
down(&open_sem);
list_del_init(&s->audiodev);
s->usbdev = NULL;
- dev_set_drvdata (&intf->dev, NULL);
+ usb_set_intfdata (intf, NULL);
/* deregister all audio and mixer devices, so no new processes can open this device */
for(list = s->audiolist.next; list != &s->audiolist; list = list->next) {
diff --git a/drivers/usb/class/bluetty.c b/drivers/usb/class/bluetty.c
index 634efc509023..cf977e5d7f8f 100644
--- a/drivers/usb/class/bluetty.c
+++ b/drivers/usb/class/bluetty.c
@@ -1207,7 +1207,7 @@ static int usb_bluetooth_probe (struct usb_interface *intf,
bluetooth_table[minor] = bluetooth;
/* success */
- dev_set_drvdata (&intf->dev, bluetooth);
+ usb_set_intfdata (intf, bluetooth);
return 0;
probe_error:
@@ -1243,10 +1243,10 @@ probe_error:
static void usb_bluetooth_disconnect(struct usb_interface *intf)
{
- struct usb_bluetooth *bluetooth = dev_get_drvdata (&intf->dev);
+ struct usb_bluetooth *bluetooth = usb_get_intfdata (intf);
int i;
- dev_set_drvdata (&intf->dev, NULL);
+ usb_set_intfdata (intf, NULL);
if (bluetooth) {
if ((bluetooth->open_count) && (bluetooth->tty))
tty_hangup(bluetooth->tty);
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
index 9729e3618d42..d9a98785a569 100644
--- a/drivers/usb/class/cdc-acm.c
+++ b/drivers/usb/class/cdc-acm.c
@@ -652,7 +652,7 @@ static int acm_probe (struct usb_interface *intf,
tty_register_devfs(&acm_tty_driver, 0, minor);
acm_table[minor] = acm;
- dev_set_drvdata (&intf->dev, acm);
+ usb_set_intfdata (intf, acm);
return 0;
}
@@ -661,7 +661,7 @@ static int acm_probe (struct usb_interface *intf,
static void acm_disconnect(struct usb_interface *intf)
{
- struct acm *acm = dev_get_drvdata (&intf->dev);
+ struct acm *acm = usb_get_intfdata (intf);
if (!acm || !acm->dev) {
dbg("disconnect on nonexisting interface");
@@ -669,7 +669,7 @@ static void acm_disconnect(struct usb_interface *intf)
}
acm->dev = NULL;
- dev_set_drvdata (&intf->dev, NULL);
+ usb_set_intfdata (intf, NULL);
usb_unlink_urb(acm->ctrlurb);
usb_unlink_urb(acm->readurb);
diff --git a/drivers/usb/class/usb-midi.c b/drivers/usb/class/usb-midi.c
index 4a9e4716f2a4..a62b947b9cc7 100644
--- a/drivers/usb/class/usb-midi.c
+++ b/drivers/usb/class/usb-midi.c
@@ -2056,14 +2056,14 @@ static int usb_midi_probe(struct usb_interface *intf,
MOD_INC_USE_COUNT;
#endif
- dev_set_drvdata (&intf->dev, s);
+ usb_set_intfdata (intf, s);
return 0;
}
static void usb_midi_disconnect(struct usb_interface *intf)
{
- struct usb_midi_state *s = dev_get_drvdata (&intf->dev);
+ struct usb_midi_state *s = usb_get_intfdata (intf);
struct list_head *list;
struct usb_mididev *m;
@@ -2080,7 +2080,7 @@ static void usb_midi_disconnect(struct usb_interface *intf)
list_del(&s->mididev);
INIT_LIST_HEAD(&s->mididev);
s->usbdev = NULL;
- dev_set_drvdata (&intf->dev, NULL);
+ usb_set_intfdata (intf, NULL);
for ( list = s->midiDevList.next; list != &s->midiDevList; list = list->next ) {
m = list_entry(list, struct usb_mididev, list);
diff --git a/drivers/usb/class/usblp.c b/drivers/usb/class/usblp.c
index 1229f0d168d9..ad6e09065762 100644
--- a/drivers/usb/class/usblp.c
+++ b/drivers/usb/class/usblp.c
@@ -338,7 +338,7 @@ static int usblp_open(struct inode *inode, struct file *file)
if (!intf) {
goto out;
}
- usblp = dev_get_drvdata (&intf->dev);
+ usblp = usb_get_intfdata (intf);
if (!usblp || !usblp->dev)
goto out;
@@ -923,7 +923,7 @@ static int usblp_probe(struct usb_interface *intf,
usblp->current_protocol, usblp->dev->descriptor.idVendor,
usblp->dev->descriptor.idProduct);
- dev_set_drvdata (&intf->dev, usblp);
+ usb_set_intfdata (intf, usblp);
/* add device id so the device works when advertised */
intf->kdev = mk_kdev(USB_MAJOR,usblp->minor);
@@ -1110,7 +1110,7 @@ static int usblp_cache_device_id_string(struct usblp *usblp)
static void usblp_disconnect(struct usb_interface *intf)
{
- struct usblp *usblp = dev_get_drvdata (&intf->dev);
+ struct usblp *usblp = usb_get_intfdata (intf);
/* remove device id to disable open() */
intf->kdev = NODEV;
@@ -1123,7 +1123,7 @@ static void usblp_disconnect(struct usb_interface *intf)
down (&usblp->sem);
lock_kernel();
usblp->dev = NULL;
- dev_set_drvdata (&intf->dev, NULL);
+ usb_set_intfdata (intf, NULL);
usblp_unlink_urbs(usblp);
diff --git a/drivers/usb/core/buffer.c b/drivers/usb/core/buffer.c
index 4f4211af98b6..6e4392596750 100644
--- a/drivers/usb/core/buffer.c
+++ b/drivers/usb/core/buffer.c
@@ -24,11 +24,14 @@
/*
- * DMA-Consistent Buffers
+ * DMA-Coherent Buffers
*/
/* FIXME tune these based on pool statistics ... */
static const size_t pool_max [HCD_BUFFER_POOLS] = {
+ /* platforms without dma-friendly caches might need to
+ * prevent cacheline sharing...
+ */
32,
128,
512,
@@ -133,98 +136,3 @@ void hcd_buffer_free (
}
pci_free_consistent (hcd->pdev, size, addr, dma);
}
-
-
-/*
- * DMA-Mappings for arbitrary memory buffers
- */
-
-int hcd_buffer_map (
- struct usb_bus *bus,
- void *addr,
- dma_addr_t *dma,
- size_t size,
- int direction
-) {
- struct usb_hcd *hcd = bus->hcpriv;
-
- // FIXME pci_map_single() has no standard failure mode!
- *dma = pci_map_single (hcd->pdev, addr, size,
- (direction == USB_DIR_IN)
- ? PCI_DMA_FROMDEVICE
- : PCI_DMA_TODEVICE);
- return 0;
-}
-
-void hcd_buffer_dmasync (
- struct usb_bus *bus,
- dma_addr_t dma,
- size_t size,
- int direction
-) {
- struct usb_hcd *hcd = bus->hcpriv;
-
- pci_dma_sync_single (hcd->pdev, dma, size,
- (direction == USB_DIR_IN)
- ? PCI_DMA_FROMDEVICE
- : PCI_DMA_TODEVICE);
-}
-
-void hcd_buffer_unmap (
- struct usb_bus *bus,
- dma_addr_t dma,
- size_t size,
- int direction
-) {
- struct usb_hcd *hcd = bus->hcpriv;
-
- pci_unmap_single (hcd->pdev, dma, size,
- (direction == USB_DIR_IN)
- ? PCI_DMA_FROMDEVICE
- : PCI_DMA_TODEVICE);
-}
-
-int hcd_buffer_map_sg (
- struct usb_bus *bus,
- struct scatterlist *sg,
- int *n_hw_ents,
- int nents,
- int direction
-) {
- struct usb_hcd *hcd = bus->hcpriv;
-
- // FIXME pci_map_sg() has no standard failure mode!
- *n_hw_ents = pci_map_sg(hcd->pdev, sg, nents,
- (direction == USB_DIR_IN)
- ? PCI_DMA_FROMDEVICE
- : PCI_DMA_TODEVICE);
- return 0;
-}
-
-void hcd_buffer_sync_sg (
- struct usb_bus *bus,
- struct scatterlist *sg,
- int n_hw_ents,
- int direction
-) {
- struct usb_hcd *hcd = bus->hcpriv;
-
- pci_dma_sync_sg(hcd->pdev, sg, n_hw_ents,
- (direction == USB_DIR_IN)
- ? PCI_DMA_FROMDEVICE
- : PCI_DMA_TODEVICE);
-}
-
-void hcd_buffer_unmap_sg (
- struct usb_bus *bus,
- struct scatterlist *sg,
- int n_hw_ents,
- int direction
-) {
- struct usb_hcd *hcd = bus->hcpriv;
-
- pci_unmap_sg(hcd->pdev, sg, n_hw_ents,
- (direction == USB_DIR_IN)
- ? PCI_DMA_FROMDEVICE
- : PCI_DMA_TODEVICE);
-}
diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c
index 3a3dfdc54e97..69a4e2f83045 100644
--- a/drivers/usb/core/config.c
+++ b/drivers/usb/core/config.c
@@ -108,6 +108,7 @@ static int usb_parse_interface(struct usb_interface *interface, unsigned char *b
interface->act_altsetting = 0;
interface->num_altsetting = 0;
interface->max_altsetting = USB_ALTSETTINGALLOC;
+ device_initialize(&interface->dev);
interface->altsetting = kmalloc(sizeof(*interface->altsetting) * interface->max_altsetting,
GFP_KERNEL);
diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
index 4093e130e44d..99ff3e881def 100644
--- a/drivers/usb/core/devio.c
+++ b/drivers/usb/core/devio.c
@@ -322,7 +322,7 @@ static int driver_probe (struct usb_interface *intf,
static void driver_disconnect(struct usb_interface *intf)
{
- struct dev_state *ps = dev_get_drvdata (&intf->dev);
+ struct dev_state *ps = usb_get_intfdata (intf);
if (!ps)
return;
@@ -333,7 +333,7 @@ static void driver_disconnect(struct usb_interface *intf)
/* prevent new I/O requests */
ps->dev = 0;
ps->ifclaimed = 0;
- dev_set_drvdata (&intf->dev, NULL);
+ usb_set_intfdata (intf, NULL);
/* force async requests to complete */
destroy_all_async (ps);
diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c
index e66aaac9fa78..9ca856cd6a42 100644
--- a/drivers/usb/core/hcd-pci.c
+++ b/drivers/usb/core/hcd-pci.c
@@ -138,7 +138,8 @@ clean_2:
hcd->pdev = dev;
hcd->self.bus_name = dev->slot_name;
hcd->product_desc = dev->dev.name;
- hcd->controller = &dev->dev;
+ hcd->self.controller = &dev->dev;
+ hcd->controller = hcd->self.controller;
if ((retval = hcd_buffer_create (hcd)) != 0) {
clean_3:
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index 74a3993826fd..624beac700b4 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -1031,19 +1031,19 @@ static int hcd_submit_urb (struct urb *urb, int mem_flags)
/* lower level hcd code should use *_dma exclusively */
if (!(urb->transfer_flags & URB_NO_DMA_MAP)) {
if (usb_pipecontrol (urb->pipe))
- urb->setup_dma = pci_map_single (
- hcd->pdev,
+ urb->setup_dma = dma_map_single (
+ hcd->controller,
urb->setup_packet,
sizeof (struct usb_ctrlrequest),
- PCI_DMA_TODEVICE);
+ DMA_TO_DEVICE);
if (urb->transfer_buffer_length != 0)
- urb->transfer_dma = pci_map_single (
- hcd->pdev,
+ urb->transfer_dma = dma_map_single (
+ hcd->controller,
urb->transfer_buffer,
urb->transfer_buffer_length,
usb_pipein (urb->pipe)
- ? PCI_DMA_FROMDEVICE
- : PCI_DMA_TODEVICE);
+ ? DMA_FROM_DEVICE
+ : DMA_TO_DEVICE);
}
status = hcd->driver->urb_enqueue (hcd, urb, mem_flags);
@@ -1265,12 +1265,6 @@ struct usb_operations usb_hcd_operations = {
.deallocate = hcd_free_dev,
.buffer_alloc = hcd_buffer_alloc,
.buffer_free = hcd_buffer_free,
- .buffer_map = hcd_buffer_map,
- .buffer_dmasync = hcd_buffer_dmasync,
- .buffer_unmap = hcd_buffer_unmap,
- .buffer_map_sg = hcd_buffer_map_sg,
- .buffer_dmasync_sg = hcd_buffer_sync_sg,
- .buffer_unmap_sg = hcd_buffer_unmap_sg,
};
EXPORT_SYMBOL (usb_hcd_operations);
diff --git a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h
index 0db63cf30e7a..99cb0f4b2c84 100644
--- a/drivers/usb/core/hcd.h
+++ b/drivers/usb/core/hcd.h
@@ -145,26 +145,6 @@ struct usb_operations {
dma_addr_t *dma);
void (*buffer_free)(struct usb_bus *bus, size_t size,
void *addr, dma_addr_t dma);
-
- int (*buffer_map) (struct usb_bus *bus,
- void *addr, dma_addr_t *dma,
- size_t size, int direction);
- void (*buffer_dmasync) (struct usb_bus *bus,
- dma_addr_t dma,
- size_t size, int direction);
- void (*buffer_unmap) (struct usb_bus *bus,
- dma_addr_t dma,
- size_t size, int direction);
-
- int (*buffer_map_sg) (struct usb_bus *bus,
- struct scatterlist *sg, int *n_hw_ents,
- int nents, int direction);
- void (*buffer_dmasync_sg) (struct usb_bus *bus,
- struct scatterlist *sg,
- int n_hw_ents, int direction);
- void (*buffer_unmap_sg) (struct usb_bus *bus,
- struct scatterlist *sg,
- int n_hw_ents, int direction);
};
/* each driver provides one of these, and hardware init support */
@@ -248,23 +228,6 @@ void *hcd_buffer_alloc (struct usb_bus *bus, size_t size,
void hcd_buffer_free (struct usb_bus *bus, size_t size,
void *addr, dma_addr_t dma);
-int hcd_buffer_map (struct usb_bus *bus,
- void *addr, dma_addr_t *dma,
- size_t size, int direction);
-void hcd_buffer_dmasync (struct usb_bus *bus,
- dma_addr_t dma,
- size_t size, int direction);
-void hcd_buffer_unmap (struct usb_bus *bus,
- dma_addr_t dma,
- size_t size, int direction);
-int hcd_buffer_map_sg (struct usb_bus *bus, struct scatterlist *sg,
- int *n_hw_ents, int nents, int direction);
-void hcd_buffer_sync_sg (struct usb_bus *bus, struct scatterlist *sg,
- int n_hw_ents, int direction);
-
-void hcd_buffer_unmap_sg (struct usb_bus *bus, struct scatterlist *sg,
- int n_hw_ents, int direction);
-
/* generic bus glue, needed for host controllers that don't use PCI */
extern struct usb_operations usb_hcd_operations;
extern void usb_hcd_irq (int irq, void *__hcd, struct pt_regs *r);
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 3ccdaf5bdb65..d013ec009f87 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -447,13 +447,13 @@ fail:
static void hub_disconnect(struct usb_interface *intf)
{
- struct usb_hub *hub = dev_get_drvdata (&intf->dev);
+ struct usb_hub *hub = usb_get_intfdata (intf);
unsigned long flags;
if (!hub)
return;
- dev_set_drvdata (&intf->dev, NULL);
+ usb_set_intfdata (intf, NULL);
spin_lock_irqsave(&hub_event_lock, flags);
/* Delete it and then reset it */
@@ -546,7 +546,7 @@ descriptor_error:
list_add(&hub->hub_list, &hub_list);
spin_unlock_irqrestore(&hub_event_lock, flags);
- dev_set_drvdata (&intf->dev, hub);
+ usb_set_intfdata (intf, hub);
if (usb_hub_configure(hub, endpoint) >= 0) {
strcpy (intf->dev.name, "Hub");
@@ -876,7 +876,7 @@ static void usb_hub_port_connect_change(struct usb_hub *hubstate, int port,
/* Reset the device, and detect its speed */
if (usb_hub_port_reset(hub, port, dev, delay)) {
- usb_free_dev(dev);
+ usb_put_dev(dev);
break;
}
@@ -928,7 +928,7 @@ static void usb_hub_port_connect_change(struct usb_hub *hubstate, int port,
goto done;
/* Free the configuration if there was an error */
- usb_free_dev(dev);
+ usb_put_dev(dev);
/* Switch to a long reset time */
delay = HUB_LONG_RESET_TIME;
diff --git a/drivers/usb/core/usb-debug.c b/drivers/usb/core/usb-debug.c
index c3e29a37665e..f0348fa89dbb 100644
--- a/drivers/usb/core/usb-debug.c
+++ b/drivers/usb/core/usb-debug.c
@@ -177,7 +177,7 @@ void usb_show_string(struct usb_device *dev, char *id, int index)
if (!(buf = kmalloc(256, GFP_KERNEL)))
return;
if (usb_string(dev, index, buf, 256) > 0)
- printk(KERN_INFO "%s: %s\n", id, buf);
+ dev_printk(KERN_INFO, dev->dev, "%s: %s\n", id, buf);
kfree(buf);
}
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
index 1325fc9b8a09..c367260c4d98 100644
--- a/drivers/usb/core/usb.c
+++ b/drivers/usb/core/usb.c
@@ -23,6 +23,13 @@
*/
#include <linux/config.h>
+
+#ifdef CONFIG_USB_DEBUG
+ #define DEBUG
+#else
+ #undef DEBUG
+#endif
+
#include <linux/module.h>
#include <linux/string.h>
#include <linux/bitops.h>
@@ -33,14 +40,13 @@
#include <linux/spinlock.h>
#include <linux/errno.h>
#include <linux/smp_lock.h>
-
-#ifdef CONFIG_USB_DEBUG
- #define DEBUG
-#else
- #undef DEBUG
-#endif
#include <linux/usb.h>
+#include <asm/io.h>
+#include <asm/scatterlist.h>
+#include <linux/mm.h>
+#include <linux/dma-mapping.h>
+
#include "hcd.h"
#include "usb.h"
@@ -293,7 +299,7 @@ void usb_driver_claim_interface(struct usb_driver *driver, struct usb_interface
dbg("%s driver claimed interface %p", driver->name, iface);
iface->driver = driver;
- iface->private_data = priv;
+ usb_set_intfdata(iface, priv);
}
/**
@@ -336,7 +342,7 @@ void usb_driver_release_interface(struct usb_driver *driver, struct usb_interfac
return;
iface->driver = NULL;
- iface->private_data = NULL;
+ usb_set_intfdata(iface, NULL);
}
/**
@@ -672,13 +678,14 @@ struct usb_device *usb_alloc_dev(struct usb_device *parent, struct usb_bus *bus)
memset(dev, 0, sizeof(*dev));
+ device_initialize(&dev->dev);
+
usb_bus_get(bus);
if (!parent)
dev->devpath [0] = '0';
dev->bus = bus;
dev->parent = parent;
- atomic_set(&dev->refcnt, 1);
INIT_LIST_HEAD(&dev->filelist);
init_MUTEX(&dev->serialize);
@@ -690,7 +697,7 @@ struct usb_device *usb_alloc_dev(struct usb_device *parent, struct usb_bus *bus)
}
/**
- * usb_get_dev - increments the reference count of the device
+ * usb_get_dev - increments the reference count of the usb device structure
* @dev: the device being referenced
*
* Each live reference to a device should be refcounted.
@@ -703,34 +710,51 @@ struct usb_device *usb_alloc_dev(struct usb_device *parent, struct usb_bus *bus)
*/
struct usb_device *usb_get_dev (struct usb_device *dev)
{
- if (dev) {
- atomic_inc (&dev->refcnt);
- return dev;
- }
- return NULL;
+ struct device *tmp;
+
+ if (!dev)
+ return NULL;
+
+ tmp = get_device(&dev->dev);
+ if (tmp)
+ return to_usb_device(tmp);
+ else
+ return NULL;
}
/**
- * usb_free_dev - free a usb device structure when all users of it are finished.
+ * usb_put_dev - release a use of the usb device structure
* @dev: device that's been disconnected
- * Context: !in_interrupt ()
*
* Must be called when a user of a device is finished with it. When the last
* user of the device calls this function, the memory of the device is freed.
+ */
+void usb_put_dev(struct usb_device *dev)
+{
+ if (dev)
+ put_device(&dev->dev);
+}
+
+/**
+ * usb_release_dev - free a usb device structure when all users of it are finished.
+ * @dev: device that's been disconnected
*
- * Used by hub and virtual root hub drivers. The device is completely
- * gone, everything is cleaned up, so it's time to get rid of these last
- * records of this device.
+ * Will be called only by the device core when all users of this usb device are
+ * done.
*/
-void usb_free_dev(struct usb_device *dev)
+static void usb_release_dev(struct device *dev)
{
- if (atomic_dec_and_test(&dev->refcnt)) {
- if (dev->bus->op->deallocate)
- dev->bus->op->deallocate(dev);
- usb_destroy_configuration (dev);
- usb_bus_put (dev->bus);
- kfree (dev);
- }
+ struct usb_device *udev;
+
+ udev = to_usb_device(dev);
+ if (!udev)
+ return;
+
+ if (udev->bus && udev->bus->op && udev->bus->op->deallocate)
+ udev->bus->op->deallocate(udev);
+ usb_destroy_configuration (udev);
+ usb_bus_put (udev->bus);
+ kfree (udev);
}
@@ -803,7 +827,7 @@ void usb_disconnect(struct usb_device **pdev)
*pdev = NULL;
- info("USB disconnect on device %d", dev->devnum);
+ dev_info (dev->dev, "USB disconnect, address %d\n", dev->devnum);
/* Free up all the children before we remove this device */
for (i = 0; i < USB_MAXCHILDREN; i++) {
@@ -812,7 +836,7 @@ void usb_disconnect(struct usb_device **pdev)
usb_disconnect(child);
}
- dbg ("unregistering interfaces on device %d", dev->devnum);
+ dev_dbg (dev->dev, "unregistering interfaces\n");
if (dev->actconfig) {
for (i = 0; i < dev->actconfig->desc.bNumInterfaces; i++) {
struct usb_interface *interface = &dev->actconfig->interface[i];
@@ -822,7 +846,7 @@ void usb_disconnect(struct usb_device **pdev)
}
}
- dbg ("unregistering the device %d", dev->devnum);
+ dev_dbg (dev->dev, "unregistering device\n");
/* Free the device number and remove the /proc/bus/usb entry */
if (dev->devnum > 0) {
clear_bit(dev->devnum, dev->bus->devmap.devicemap);
@@ -907,7 +931,7 @@ static void set_device_description (struct usb_device *dev)
if (prod && usb_string (dev, prod, prod_str, 256) > 0) {
#ifdef DEBUG
- printk (KERN_INFO "Product: %s\n", prod_str);
+ dev_printk (KERN_INFO, dev->dev, "Product: %s\n", prod_str);
#endif
} else {
prod_str = 0;
@@ -915,7 +939,7 @@ static void set_device_description (struct usb_device *dev)
if (mfgr && usb_string (dev, mfgr, mfgr_str, 256) > 0) {
#ifdef DEBUG
- printk (KERN_INFO "Manufacturer: %s\n", mfgr_str);
+ dev_printk (KERN_INFO, dev->dev, "Manufacturer: %s\n", mfgr_str);
#endif
} else {
mfgr_str = 0;
@@ -976,10 +1000,15 @@ int usb_new_device(struct usb_device *dev, struct device *parent)
dev->dev.parent = parent;
dev->dev.driver = &usb_generic_driver;
dev->dev.bus = &usb_bus_type;
+ dev->dev.release = usb_release_dev;
+ usb_get_dev(dev);
if (dev->dev.bus_id[0] == 0)
sprintf (&dev->dev.bus_id[0], "%d-%s",
dev->bus->busnum, dev->devpath);
+ /* dma masks come from the controller; readonly, except to hcd */
+ dev->dev.dma_mask = parent->dma_mask;
+
/* USB device state == default ... it's not usable yet */
/* USB 2.0 section 5.5.3 talks about ep0 maxpacket ...
@@ -1079,7 +1108,7 @@ int usb_new_device(struct usb_device *dev, struct device *parent)
/* USB device state == configured ... tell the world! */
- dbg("new device strings: Mfr=%d, Product=%d, SerialNumber=%d",
+ dev_dbg(dev->dev, "new device strings: Mfr=%d, Product=%d, SerialNumber=%d\n",
dev->descriptor.iManufacturer, dev->descriptor.iProduct, dev->descriptor.iSerialNumber);
set_device_description (dev);
@@ -1089,7 +1118,7 @@ int usb_new_device(struct usb_device *dev, struct device *parent)
#endif
/* put into sysfs, with device and config specific files */
- err = device_register (&dev->dev);
+ err = device_add (&dev->dev);
if (err)
return err;
usb_create_driverfs_dev_files (dev);
@@ -1104,6 +1133,7 @@ int usb_new_device(struct usb_device *dev, struct device *parent)
interface->dev.parent = &dev->dev;
interface->dev.driver = NULL;
interface->dev.bus = &usb_bus_type;
+ interface->dev.dma_mask = parent->dma_mask;
sprintf (&interface->dev.bus_id[0], "%d-%s:%d",
dev->bus->busnum, dev->devpath,
desc->bInterfaceNumber);
@@ -1122,7 +1152,7 @@ int usb_new_device(struct usb_device *dev, struct device *parent)
desc->bInterfaceNumber);
}
dbg ("%s - registering %s", __FUNCTION__, interface->dev.bus_id);
- device_register (&interface->dev);
+ device_add (&interface->dev);
usb_create_driverfs_intf_files (interface);
}
@@ -1206,24 +1236,21 @@ void usb_buffer_free (
struct urb *usb_buffer_map (struct urb *urb)
{
struct usb_bus *bus;
- struct usb_operations *op;
+ struct device *controller;
if (!urb
|| usb_pipecontrol (urb->pipe)
|| !urb->dev
|| !(bus = urb->dev->bus)
- || !(op = bus->op)
- || !op->buffer_map)
+ || !(controller = bus->controller))
return 0;
- if (op->buffer_map (bus,
- urb->transfer_buffer,
- &urb->transfer_dma,
- urb->transfer_buffer_length,
+ urb->transfer_dma = dma_map_single (controller,
+ urb->transfer_buffer, urb->transfer_buffer_length,
usb_pipein (urb->pipe)
- ? USB_DIR_IN
- : USB_DIR_OUT))
- return 0;
+ ? DMA_FROM_DEVICE : DMA_TO_DEVICE);
+ // FIXME generic api broken like pci, can't report errors
+ // if (urb->transfer_dma == DMA_ADDR_INVALID) return 0;
urb->transfer_flags |= URB_NO_DMA_MAP;
return urb;
}
@@ -1235,22 +1262,19 @@ struct urb *usb_buffer_map (struct urb *urb)
void usb_buffer_dmasync (struct urb *urb)
{
struct usb_bus *bus;
- struct usb_operations *op;
+ struct device *controller;
if (!urb
|| !(urb->transfer_flags & URB_NO_DMA_MAP)
|| !urb->dev
|| !(bus = urb->dev->bus)
- || !(op = bus->op)
- || !op->buffer_dmasync)
+ || !(controller = bus->controller))
return;
- op->buffer_dmasync (bus,
- urb->transfer_dma,
- urb->transfer_buffer_length,
+ dma_sync_single (controller,
+ urb->transfer_dma, urb->transfer_buffer_length,
usb_pipein (urb->pipe)
- ? USB_DIR_IN
- : USB_DIR_OUT);
+ ? DMA_FROM_DEVICE : DMA_TO_DEVICE);
}
/**
@@ -1262,23 +1286,21 @@ void usb_buffer_dmasync (struct urb *urb)
void usb_buffer_unmap (struct urb *urb)
{
struct usb_bus *bus;
- struct usb_operations *op;
+ struct device *controller;
if (!urb
|| !(urb->transfer_flags & URB_NO_DMA_MAP)
|| !urb->dev
|| !(bus = urb->dev->bus)
- || !(op = bus->op)
- || !op->buffer_unmap)
+ || !(controller = bus->controller))
return;
- op->buffer_unmap (bus,
- urb->transfer_dma,
- urb->transfer_buffer_length,
+ dma_unmap_single (controller,
+ urb->transfer_dma, urb->transfer_buffer_length,
usb_pipein (urb->pipe)
- ? USB_DIR_IN
- : USB_DIR_OUT);
+ ? DMA_FROM_DEVICE : DMA_TO_DEVICE);
}
+
/**
* usb_buffer_map_sg - create scatterlist DMA mapping(s) for an endpoint
* @dev: device to which the scatterlist will be mapped
@@ -1297,6 +1319,7 @@ void usb_buffer_unmap (struct urb *urb)
* to complete before starting the next I/O. This is particularly easy
* to do with scatterlists. Just allocate and submit one URB for each DMA
* mapping entry returned, stopping on the first error or when all succeed.
+ * Better yet, use the usb_sg_*() calls, which do that (and more) for you.
*
* This call would normally be used when translating scatterlist requests,
* rather than usb_buffer_map(), since on some hardware (with IOMMUs) it
@@ -1308,26 +1331,17 @@ int usb_buffer_map_sg (struct usb_device *dev, unsigned pipe,
struct scatterlist *sg, int nents)
{
struct usb_bus *bus;
- struct usb_operations *op;
- int n_hw_ents;
+ struct device *controller;
if (!dev
|| usb_pipecontrol (pipe)
|| !(bus = dev->bus)
- || !(op = bus->op)
- || !op->buffer_map_sg)
- return -1;
-
- if (op->buffer_map_sg (bus,
- sg,
- &n_hw_ents,
- nents,
- usb_pipein (pipe)
- ? USB_DIR_IN
- : USB_DIR_OUT))
+ || !(controller = bus->controller))
return -1;
- return n_hw_ents;
+ // FIXME generic api broken like pci, can't report errors
+ return dma_map_sg (controller, sg, nents,
+ usb_pipein (pipe) ? DMA_FROM_DEVICE : DMA_TO_DEVICE);
}
/**
@@ -1344,20 +1358,15 @@ void usb_buffer_dmasync_sg (struct usb_device *dev, unsigned pipe,
struct scatterlist *sg, int n_hw_ents)
{
struct usb_bus *bus;
- struct usb_operations *op;
+ struct device *controller;
if (!dev
|| !(bus = dev->bus)
- || !(op = bus->op)
- || !op->buffer_dmasync_sg)
+ || !(controller = bus->controller))
return;
- op->buffer_dmasync_sg (bus,
- sg,
- n_hw_ents,
- usb_pipein (pipe)
- ? USB_DIR_IN
- : USB_DIR_OUT);
+ dma_sync_sg (controller, sg, n_hw_ents,
+ usb_pipein (pipe) ? DMA_FROM_DEVICE : DMA_TO_DEVICE);
}
/**
@@ -1373,20 +1382,15 @@ void usb_buffer_unmap_sg (struct usb_device *dev, unsigned pipe,
struct scatterlist *sg, int n_hw_ents)
{
struct usb_bus *bus;
- struct usb_operations *op;
+ struct device *controller;
if (!dev
|| !(bus = dev->bus)
- || !(op = bus->op)
- || !op->buffer_unmap_sg)
+ || !(controller = bus->controller))
return;
- op->buffer_unmap_sg (bus,
- sg,
- n_hw_ents,
- usb_pipein (pipe)
- ? USB_DIR_IN
- : USB_DIR_OUT);
+ dma_unmap_sg (controller, sg, n_hw_ents,
+ usb_pipein (pipe) ? DMA_FROM_DEVICE : DMA_TO_DEVICE);
}
@@ -1471,7 +1475,7 @@ EXPORT_SYMBOL(usb_device_probe);
EXPORT_SYMBOL(usb_device_remove);
EXPORT_SYMBOL(usb_alloc_dev);
-EXPORT_SYMBOL(usb_free_dev);
+EXPORT_SYMBOL(usb_put_dev);
EXPORT_SYMBOL(usb_get_dev);
EXPORT_SYMBOL(usb_hub_tt_clear_buffer);
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 48d9b806fcb2..3da8c9b228ef 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -405,9 +405,10 @@ static int ehci_start (struct usb_hcd *hcd)
* streaming mappings for I/O buffers, like pci_map_single(),
* can return segments above 4GB, if the device allows.
*
- * NOTE: layered drivers can't yet tell when we enable that,
- * so they can't pass this info along (like NETIF_F_HIGHDMA)
- * (or like Scsi_Host.highmem_io) ... usb_bus.flags?
+ * NOTE: the dma mask is visible through dma_supported(), so
+ * drivers can pass this info along ... like NETIF_F_HIGHDMA,
+ * Scsi_Host.highmem_io, and so forth. It's readonly to all
+ * host side drivers though.
*/
if (HCC_64BIT_ADDR (hcc_params)) {
writel (0, &ehci->regs->segment);
@@ -475,7 +476,7 @@ done2:
ehci_ready (ehci);
ehci_reset (ehci);
bus->root_hub = 0;
- usb_free_dev (udev);
+ usb_put_dev (udev);
retval = -ENODEV;
goto done2;
}
diff --git a/drivers/usb/host/hc_sl811_rh.c b/drivers/usb/host/hc_sl811_rh.c
index 786bb4dec196..203a909fdcd5 100644
--- a/drivers/usb/host/hc_sl811_rh.c
+++ b/drivers/usb/host/hc_sl811_rh.c
@@ -566,7 +566,7 @@ static int rh_connect_rh (hci_t * hci)
hci->bus->root_hub = usb_dev;
usb_connect (usb_dev);
if (usb_new_device (usb_dev) != 0) {
- usb_free_dev (usb_dev);
+ usb_put_dev (usb_dev);
return -ENODEV;
}
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
index af15bea5fa45..17a794b3ce54 100644
--- a/drivers/usb/host/ohci-hcd.c
+++ b/drivers/usb/host/ohci-hcd.c
@@ -515,7 +515,7 @@ static int hc_start (struct ohci_hcd *ohci)
usb_connect (udev);
udev->speed = USB_SPEED_FULL;
if (usb_register_root_hub (udev, ohci->hcd.controller) != 0) {
- usb_free_dev (udev);
+ usb_put_dev (udev);
ohci->hcd.self.root_hub = NULL;
disable (ohci);
ohci->hc_control &= ~OHCI_CTRL_HCFS;
diff --git a/drivers/usb/host/ohci-sa1111.c b/drivers/usb/host/ohci-sa1111.c
index d03fce1c7da5..11d4fed34233 100644
--- a/drivers/usb/host/ohci-sa1111.c
+++ b/drivers/usb/host/ohci-sa1111.c
@@ -176,7 +176,8 @@ int usb_hcd_sa1111_probe (const struct hc_driver *driver,
hcd->irq = dev->irq[1];
hcd->regs = dev->mapbase;
hcd->pdev = SA1111_FAKE_PCIDEV;
- hcd->controller = &dev->dev;
+ hcd->self.controller = &dev->dev;
+ hcd->controller = hcd->self.controller;
retval = hcd_buffer_create (hcd);
if (retval != 0) {
diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
index f258f2b92ccb..3b5768ee1812 100644
--- a/drivers/usb/host/uhci-hcd.c
+++ b/drivers/usb/host/uhci-hcd.c
@@ -2280,7 +2280,7 @@ err_alloc_skelqh:
uhci->term_td = NULL;
err_alloc_term_td:
- usb_free_dev(udev);
+ usb_put_dev(udev);
hcd->self.root_hub = NULL;
err_alloc_root_hub:
diff --git a/drivers/usb/image/hpusbscsi.c b/drivers/usb/image/hpusbscsi.c
index d82059f6f186..ffe02faa4a0e 100644
--- a/drivers/usb/image/hpusbscsi.c
+++ b/drivers/usb/image/hpusbscsi.c
@@ -130,7 +130,7 @@ hpusbscsi_usb_probe (struct usb_interface *intf,
/* adding to list for module unload */
list_add (&hpusbscsi_devices, &new->lh);
- dev_set_drvdata(&intf->dev, new);
+ usb_set_intfdata(intf, new);
return 0;
err_out:
@@ -143,9 +143,9 @@ hpusbscsi_usb_probe (struct usb_interface *intf,
static void
hpusbscsi_usb_disconnect (struct usb_interface *intf)
{
- struct hpusbscsi *desc = dev_get_drvdata(&intf->dev);
+ struct hpusbscsi *desc = usb_get_intfdata(intf);
- dev_set_drvdata(&intf->dev, NULL);
+ usb_set_intfdata(intf, NULL);
if (desc)
usb_unlink_urb(desc->controlurb);
}
diff --git a/drivers/usb/image/mdc800.c b/drivers/usb/image/mdc800.c
index 9a150b9075c1..d829ea19f454 100644
--- a/drivers/usb/image/mdc800.c
+++ b/drivers/usb/image/mdc800.c
@@ -523,7 +523,7 @@ static int mdc800_usb_probe (struct usb_interface *intf,
up (&mdc800->io_lock);
- dev_set_drvdata(&intf->dev, mdc800);
+ usb_set_intfdata(intf, mdc800);
return 0;
}
@@ -533,7 +533,7 @@ static int mdc800_usb_probe (struct usb_interface *intf,
*/
static void mdc800_usb_disconnect (struct usb_interface *intf)
{
- struct mdc800_data* mdc800 = dev_get_drvdata(&intf->dev);
+ struct mdc800_data* mdc800 = usb_get_intfdata(intf);
dbg ("(mdc800_usb_disconnect) called");
@@ -552,7 +552,7 @@ static void mdc800_usb_disconnect (struct usb_interface *intf)
usb_driver_release_interface (&mdc800_usb_driver, intf);
mdc800->dev=0;
- dev_set_drvdata(&intf->dev, NULL);
+ usb_set_intfdata(intf, NULL);
}
info ("Mustek MDC800 disconnected from USB.");
}
diff --git a/drivers/usb/image/microtek.c b/drivers/usb/image/microtek.c
index efd412c85185..ddd98e4c6cf5 100644
--- a/drivers/usb/image/microtek.c
+++ b/drivers/usb/image/microtek.c
@@ -774,11 +774,11 @@ static Scsi_Host_Template mts_scsi_host_template = {
static void mts_usb_disconnect (struct usb_interface *intf)
{
- struct mts_desc* to_remove = dev_get_drvdata(&intf->dev);
+ struct mts_desc* to_remove = usb_get_intfdata(intf);
MTS_DEBUG_GOT_HERE();
- dev_set_drvdata(&intf->dev, NULL);
+ usb_set_intfdata(intf, NULL);
if (to_remove) {
/* leave the list - lock it */
down(&mts_list_semaphore);
@@ -1007,7 +1007,7 @@ static int mts_usb_probe (struct usb_interface *intf,
MTS_DEBUG("completed probe and exiting happily\n");
- dev_set_drvdata(&intf->dev, new_desc);
+ usb_set_intfdata(intf, new_desc);
return 0;
}
diff --git a/drivers/usb/image/scanner.c b/drivers/usb/image/scanner.c
index 27591a0898e0..d0fee7cd6061 100644
--- a/drivers/usb/image/scanner.c
+++ b/drivers/usb/image/scanner.c
@@ -321,10 +321,13 @@
* "Jaeger, Gerhard" <gerhard@gjaeger.de>, Ira Childress
* <ichildress@mn.rr.com>, Till Kamppeter <till.kamppeter@gmx.net>,
* Ed Hamrick <EdHamrick@aol.com>, Oliver Schwartz
- * <Oliver.Schwartz@gmx.de> and everyone else who sent ids.
+ * <Oliver.Schwartz@gmx.de> and everyone else who sent ids.
* - Some Benq, Genius and Plustek ids are identified now.
* - Accept scanners with only one bulk (in) endpoint (thanks to Sergey
* Vlasov <vsu@mivlgu.murom.ru>).
+ * - Accept devices with more than one interface. Only use interfaces that
+ * look like belonging to scanners.
+ * - Fix compilation error when debugging is enabled.
*
* TODO
* - Remove the 2/3 endpoint limitation
@@ -429,7 +432,7 @@ open_scanner(struct inode * inode, struct file * file)
err("open_scanner(%d): Unable to access minor data", scn_minor);
return -ENODEV;
}
- scn = dev_get_drvdata (&intf->dev);
+ scn = usb_get_intfdata(intf);
dev = scn->scn_dev;
@@ -858,7 +861,6 @@ probe_scanner(struct usb_interface *intf,
}
dbg("probe_scanner: USB dev address:%p", dev);
- dbg("probe_scanner: ifnum:%u", ifnum);
/*
* 1. Check Vendor/Product
@@ -907,13 +909,15 @@ probe_scanner(struct usb_interface *intf,
return -ENODEV;
}
- if (dev->config[0].desc.bNumInterfaces != 1) {
- info("probe_scanner: Only one device interface is supported.");
+ interface = intf->altsetting;
+
+ if (interface[0].desc.bInterfaceClass != USB_CLASS_VENDOR_SPEC &&
+ interface[0].desc.bInterfaceClass != USB_CLASS_PER_INTERFACE &&
+ interface[0].desc.bInterfaceClass != 16) {
+ dbg("probe_scanner: This interface doesn't look like a scanner (class=0x%x).", interface[0].desc.bInterfaceClass);
return -ENODEV;
}
- interface = intf->altsetting;
-
/*
* Start checking for one or two bulk endpoints and an optional
* interrupt endpoint. If we have an interrupt endpoint go ahead and
@@ -1098,7 +1102,7 @@ probe_scanner(struct usb_interface *intf,
up(&scn_mutex);
- dev_set_drvdata(&intf->dev, scn);
+ usb_set_intfdata(intf, scn);
/* add device id so the device works when advertised */
intf->kdev = mk_kdev(USB_MAJOR,scn->scn_minor);
@@ -1109,12 +1113,12 @@ probe_scanner(struct usb_interface *intf,
static void
disconnect_scanner(struct usb_interface *intf)
{
- struct scn_usb_data *scn = dev_get_drvdata(&intf->dev);
+ struct scn_usb_data *scn = usb_get_intfdata(intf);
/* remove device id to disable open() */
intf->kdev = NODEV;
- dev_set_drvdata(&intf->dev, NULL);
+ usb_set_intfdata(intf, NULL);
if (scn) {
down (&scn_mutex);
down (&(scn->sem));
diff --git a/drivers/usb/input/aiptek.c b/drivers/usb/input/aiptek.c
index 26946e593f64..a40dd8132b8b 100644
--- a/drivers/usb/input/aiptek.c
+++ b/drivers/usb/input/aiptek.c
@@ -330,16 +330,16 @@ aiptek_probe(struct usb_interface *intf,
printk(KERN_INFO "input: %s on usb%d:%d\n",
aiptek->features->name, dev->bus->busnum, dev->devnum);
- dev_set_drvdata(&intf->dev, aiptek);
+ usb_set_intfdata(intf, aiptek);
return 0;
}
static void
aiptek_disconnect(struct usb_interface *intf)
{
- struct aiptek *aiptek = dev_get_drvdata(&intf->dev);
+ struct aiptek *aiptek = usb_get_intfdata (intf);
- dev_set_drvdata(&intf->dev, NULL);
+ usb_set_intfdata(intf, NULL);
if (aiptek) {
usb_unlink_urb(aiptek->irq);
input_unregister_device(&aiptek->dev);
diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c
index 88523db2a603..2da265ac3202 100644
--- a/drivers/usb/input/hid-core.c
+++ b/drivers/usb/input/hid-core.c
@@ -1317,6 +1317,9 @@ void hid_init_reports(struct hid_device *hid)
#define USB_DEVICE_ID_ATEN_2PORTKVM 0x2204
#define USB_DEVICE_ID_ATEN_4PORTKVM 0x2205
+#define USB_VENDOR_ID_TOPMAX 0x0663
+#define USB_DEVICE_ID_TOPMAX_COBRAPAD 0x0103
+
#define USB_VENDOR_ID_MGE 0x0463
#define USB_DEVICE_ID_MGE_UPS 0xffff
#define USB_DEVICE_ID_MGE_UPS1 0x0001
@@ -1355,6 +1358,7 @@ struct hid_blacklist {
{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVM, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS, HID_QUIRK_HIDDEV },
{ USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS1, HID_QUIRK_HIDDEV },
+ { USB_VENDOR_ID_TOPMAX, USB_DEVICE_ID_TOPMAX_COBRAPAD, HID_QUIRK_BADPAD },
{ 0, 0 }
};
@@ -1541,12 +1545,12 @@ fail:
static void hid_disconnect(struct usb_interface *intf)
{
- struct hid_device *hid = dev_get_drvdata(&intf->dev);
+ struct hid_device *hid = usb_get_intfdata (intf);
if (!hid)
return;
- dev_set_drvdata (&intf->dev, NULL);
+ usb_set_intfdata(intf, NULL);
usb_unlink_urb(hid->urbin);
usb_unlink_urb(hid->urbout);
usb_unlink_urb(hid->urbctrl);
@@ -1588,7 +1592,7 @@ static int hid_probe (struct usb_interface *intf, const struct usb_device_id *id
if (!hiddev_connect(hid))
hid->claimed |= HID_CLAIMED_HIDDEV;
- dev_set_drvdata(&intf->dev, hid);
+ usb_set_intfdata(intf, hid);
if (!hid->claimed) {
printk ("HID device not claimed by input or hiddev\n");
diff --git a/drivers/usb/input/hid-input.c b/drivers/usb/input/hid-input.c
index 9090b577643f..1fae2bc757fc 100644
--- a/drivers/usb/input/hid-input.c
+++ b/drivers/usb/input/hid-input.c
@@ -357,6 +357,11 @@ static void hidinput_configure_usage(struct hid_device *device, struct hid_field
int a = field->logical_minimum;
int b = field->logical_maximum;
+ if ((device->quirks & HID_QUIRK_BADPAD) && (usage->code == ABS_X || usage->code == ABS_Y)) {
+ a = field->logical_minimum = 0;
+ b = field->logical_maximum = 255;
+ }
+
input->absmin[usage->code] = a;
input->absmax[usage->code] = b;
input->absfuzz[usage->code] = (b - a) >> 8;
diff --git a/drivers/usb/input/hid.h b/drivers/usb/input/hid.h
index 4f40b1b70d8f..2672f12ada5a 100644
--- a/drivers/usb/input/hid.h
+++ b/drivers/usb/input/hid.h
@@ -206,6 +206,7 @@ struct hid_item {
#define HID_QUIRK_IGNORE 0x04
#define HID_QUIRK_NOGET 0x08
#define HID_QUIRK_HIDDEV 0x10
+#define HID_QUIRK_BADPAD 0x12
/*
* This is the global enviroment of the parser. This information is
diff --git a/drivers/usb/input/pid.c b/drivers/usb/input/pid.c
index e98387579369..6752f17b9df6 100644
--- a/drivers/usb/input/pid.c
+++ b/drivers/usb/input/pid.c
@@ -133,6 +133,11 @@ static int hid_pid_erase(struct input_dev *dev, int id)
/* Find field */
field = (struct hid_field *) kmalloc(sizeof(struct hid_field), GFP_KERNEL);
+ if(!field) {
+ printk("Couldn't allocate field\n");
+ return -ENOMEM;
+ }
+
ret = hid_set_field(field, ret, pid->effects[id].device_id);
if(!ret) {
printk("Couldn't set field\n");
diff --git a/drivers/usb/input/powermate.c b/drivers/usb/input/powermate.c
index 52d7b5d1f6c8..dfd55ce2f252 100644
--- a/drivers/usb/input/powermate.c
+++ b/drivers/usb/input/powermate.c
@@ -388,16 +388,16 @@ static int powermate_probe(struct usb_interface *intf, const struct usb_device_i
pm->requires_update = UPDATE_PULSE_ASLEEP | UPDATE_PULSE_AWAKE | UPDATE_PULSE_MODE | UPDATE_STATIC_BRIGHTNESS;
powermate_pulse_led(pm, 0x80, 255, 0, 1, 0); // set default pulse parameters
- dev_set_drvdata(&intf->dev, pm);
+ usb_set_intfdata(intf, pm);
return 0;
}
/* Called when a USB device we've accepted ownership of is removed */
static void powermate_disconnect(struct usb_interface *intf)
{
- struct powermate_device *pm = dev_get_drvdata(&intf->dev);
+ struct powermate_device *pm = usb_get_intfdata (intf);
- dev_set_drvdata(&intf->dev, NULL);
+ usb_set_intfdata(intf, NULL);
if (pm) {
down(&pm->lock);
pm->requires_update = 0;
diff --git a/drivers/usb/input/usbkbd.c b/drivers/usb/input/usbkbd.c
index 0d0288b1328c..96d7b2301bbb 100644
--- a/drivers/usb/input/usbkbd.c
+++ b/drivers/usb/input/usbkbd.c
@@ -328,15 +328,15 @@ static int usb_kbd_probe(struct usb_interface *iface,
printk(KERN_INFO "input: %s on %s\n", kbd->name, path);
- dev_set_drvdata(&iface->dev, kbd);
+ usb_set_intfdata(iface, kbd);
return 0;
}
static void usb_kbd_disconnect(struct usb_interface *intf)
{
- struct usb_kbd *kbd = dev_get_drvdata(&intf->dev);
+ struct usb_kbd *kbd = usb_get_intfdata (intf);
- dev_set_drvdata(&intf->dev, NULL);
+ usb_set_intfdata(intf, NULL);
if (kbd) {
usb_unlink_urb(kbd->irq);
input_unregister_device(&kbd->dev);
diff --git a/drivers/usb/input/usbmouse.c b/drivers/usb/input/usbmouse.c
index 1c88156effdc..9914ba86e8e7 100644
--- a/drivers/usb/input/usbmouse.c
+++ b/drivers/usb/input/usbmouse.c
@@ -211,15 +211,15 @@ static int usb_mouse_probe(struct usb_interface * intf, const struct usb_device_
input_register_device(&mouse->dev);
printk(KERN_INFO "input: %s on %s\n", mouse->name, path);
- dev_set_drvdata(&intf->dev, mouse);
+ usb_set_intfdata(intf, mouse);
return 0;
}
static void usb_mouse_disconnect(struct usb_interface *intf)
{
- struct usb_mouse *mouse = dev_get_drvdata(&intf->dev);
+ struct usb_mouse *mouse = usb_get_intfdata (intf);
- dev_set_drvdata(&intf->dev, NULL);
+ usb_set_intfdata(intf, NULL);
if (mouse) {
usb_unlink_urb(mouse->irq);
input_unregister_device(&mouse->dev);
diff --git a/drivers/usb/input/wacom.c b/drivers/usb/input/wacom.c
index e9900ce3439c..efa3455f6cef 100644
--- a/drivers/usb/input/wacom.c
+++ b/drivers/usb/input/wacom.c
@@ -583,16 +583,16 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
printk(KERN_INFO "input: %s on %s\n", wacom->features->name, path);
- dev_set_drvdata(&intf->dev, wacom);
+ usb_set_intfdata(intf, wacom);
return 0;
}
static void wacom_disconnect(struct usb_interface *intf)
{
- struct wacom *wacom = dev_get_drvdata(&intf->dev);
+ struct wacom *wacom = usb_get_intfdata (intf);
- dev_set_drvdata(&intf->dev, NULL);
+ usb_set_intfdata(intf, NULL);
if (wacom) {
usb_unlink_urb(wacom->irq);
input_unregister_device(&wacom->dev);
diff --git a/drivers/usb/input/xpad.c b/drivers/usb/input/xpad.c
index 596c19dec29b..1e7edc552343 100644
--- a/drivers/usb/input/xpad.c
+++ b/drivers/usb/input/xpad.c
@@ -311,15 +311,15 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id
printk(KERN_INFO "input: %s on %s", xpad->dev.name, path);
- dev_set_drvdata(&intf->dev, xpad);
+ usb_set_intfdata(intf, xpad);
return 0;
}
static void xpad_disconnect(struct usb_interface *intf)
{
- struct usb_xpad *xpad = dev_get_drvdata(&intf->dev);
+ struct usb_xpad *xpad = usb_get_intfdata (intf);
- dev_set_drvdata(&intf->dev, NULL);
+ usb_set_intfdata(intf, NULL);
if (xpad) {
usb_unlink_urb(xpad->irq_in);
input_unregister_device(&xpad->dev);
diff --git a/drivers/usb/media/dabusb.c b/drivers/usb/media/dabusb.c
index 254dff941bcc..aa9c99ecc74a 100644
--- a/drivers/usb/media/dabusb.c
+++ b/drivers/usb/media/dabusb.c
@@ -761,7 +761,7 @@ static int dabusb_probe (struct usb_interface *intf,
dbg("bound to interface: %d", ifnum);
up (&s->mutex);
MOD_INC_USE_COUNT;
- dev_set_drvdata (&intf->dev, s);
+ usb_set_intfdata (intf, s);
return 0;
reject:
@@ -772,11 +772,11 @@ static int dabusb_probe (struct usb_interface *intf,
static void dabusb_disconnect (struct usb_interface *intf)
{
- pdabusb_t s = dev_get_drvdata (&intf->dev);
+ pdabusb_t s = usb_get_intfdata (intf);
dbg("dabusb_disconnect");
- dev_set_drvdata (&intf->dev, NULL);
+ usb_set_intfdata (intf, NULL);
if (s) {
usb_deregister_dev (1, s->devnum);
s->remove_pending = 1;
diff --git a/drivers/usb/media/dsbr100.c b/drivers/usb/media/dsbr100.c
index 7b9652fc9bb6..cc099cb8d91d 100644
--- a/drivers/usb/media/dsbr100.c
+++ b/drivers/usb/media/dsbr100.c
@@ -190,15 +190,15 @@ static int usb_dsbr100_probe(struct usb_interface *intf,
usb_dsbr100_radio.priv = radio;
radio->dev = interface_to_usbdev (intf);
radio->curfreq = 1454000;
- dev_set_drvdata (&intf->dev, radio);
+ usb_set_intfdata (intf, radio);
return 0;
}
static void usb_dsbr100_disconnect(struct usb_interface *intf)
{
- usb_dsbr100 *radio = dev_get_drvdata (&intf->dev);
+ usb_dsbr100 *radio = usb_get_intfdata (intf);
- dev_set_drvdata (&intf->dev, NULL);
+ usb_set_intfdata (intf, NULL);
if (radio) {
lock_kernel();
diff --git a/drivers/usb/media/ibmcam.c b/drivers/usb/media/ibmcam.c
index 5400823e6b86..6eea2335846f 100644
--- a/drivers/usb/media/ibmcam.c
+++ b/drivers/usb/media/ibmcam.c
@@ -3898,7 +3898,7 @@ static int ibmcam_probe(struct usb_interface *intf, const struct usb_device_id *
}
}
MOD_DEC_USE_COUNT;
- dev_set_drvdata (&intf->dev, uvd);
+ usb_set_intfdata (intf, uvd);
return 0;
}
diff --git a/drivers/usb/media/konicawc.c b/drivers/usb/media/konicawc.c
index 324d3ab0fcfd..86cc8b3628c0 100644
--- a/drivers/usb/media/konicawc.c
+++ b/drivers/usb/media/konicawc.c
@@ -860,7 +860,7 @@ static int konicawc_probe(struct usb_interface *intf, const struct usb_device_id
MOD_DEC_USE_COUNT;
if (uvd) {
- dev_set_drvdata (&intf->dev, uvd);
+ usb_set_intfdata (intf, uvd);
return 0;
}
return -EIO;
diff --git a/drivers/usb/media/ov511.c b/drivers/usb/media/ov511.c
index 3511edd1d0e1..6d3c093afa1d 100644
--- a/drivers/usb/media/ov511.c
+++ b/drivers/usb/media/ov511.c
@@ -3278,19 +3278,23 @@ request_decompressor(struct usb_ov511 *ov)
err("Unknown bridge");
}
- if (ov->decomp_ops) {
- if (!ov->decomp_ops->owner) {
- ov->decomp_ops = NULL;
- unlock_kernel();
- return -ENOSYS;
- }
- __MOD_INC_USE_COUNT(ov->decomp_ops->owner);
- unlock_kernel();
- return 0;
- } else {
- unlock_kernel();
- return -ENOSYS;
+ if (!ov->decomp_ops)
+ goto nosys;
+
+ if (!ov->decomp_ops->owner) {
+ ov->decomp_ops = NULL;
+ goto nosys;
}
+
+ if (!try_module_get(ov->decomp_ops->owner))
+ goto nosys;
+
+ unlock_kernel();
+ return 0;
+
+ nosys:
+ unlock_kernel();
+ return -ENOSYS;
}
/* Unlocks decompression module and nulls ov->decomp_ops. Safe to call even
@@ -3306,8 +3310,8 @@ release_decompressor(struct usb_ov511 *ov)
lock_kernel();
- if (ov->decomp_ops && ov->decomp_ops->owner) {
- __MOD_DEC_USE_COUNT(ov->decomp_ops->owner);
+ if (ov->decomp_ops) {
+ module_put(ov->decomp_ops->owner);
released = 1;
}
@@ -6247,7 +6251,7 @@ ov51x_probe(struct usb_interface *intf,
create_proc_ov511_cam(ov);
- dev_set_drvdata (&intf->dev, ov);
+ usb_set_intfdata (intf, ov);
return 0;
error:
@@ -6274,12 +6278,12 @@ error_out:
static void
ov51x_disconnect(struct usb_interface *intf)
{
- struct usb_ov511 *ov = dev_get_drvdata (&intf->dev);
+ struct usb_ov511 *ov = usb_get_intfdata (intf);
int n;
PDEBUG(3, "");
- dev_set_drvdata (&intf->dev, NULL);
+ usb_set_intfdata (intf, NULL);
if (!ov)
return;
diff --git a/drivers/usb/media/pwc-if.c b/drivers/usb/media/pwc-if.c
index d6352f45f261..6414b56defa4 100644
--- a/drivers/usb/media/pwc-if.c
+++ b/drivers/usb/media/pwc-if.c
@@ -1840,7 +1840,7 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
device_hint[hint].pdev = pdev;
Trace(TRACE_PROBE, "probe() function returning struct at 0x%p.\n", pdev);
- dev_set_drvdata (&intf->dev, pdev);
+ usb_set_intfdata (intf, pdev);
return 0;
}
@@ -1854,8 +1854,8 @@ static void usb_pwc_disconnect(struct usb_interface *intf)
lock_kernel();
free_mem_leak();
- pdev = dev_get_drvdata (&intf->dev);
- dev_set_drvdata (&intf->dev, NULL);
+ pdev = usb_get_intfdata (intf);
+ usb_set_intfdata (intf, NULL);
if (pdev == NULL) {
Err("pwc_disconnect() Called without private pointer.\n");
goto disconnect_out;
diff --git a/drivers/usb/media/se401.c b/drivers/usb/media/se401.c
index e527235276ea..cde8b307a2a1 100644
--- a/drivers/usb/media/se401.c
+++ b/drivers/usb/media/se401.c
@@ -1521,15 +1521,15 @@ static int se401_probe(struct usb_interface *intf,
#endif
info("registered new video device: video%d", se401->vdev.minor);
- dev_set_drvdata (&intf->dev, se401);
+ usb_set_intfdata (intf, se401);
return 0;
}
static void se401_disconnect(struct usb_interface *intf)
{
- struct usb_se401 *se401 = dev_get_drvdata (&intf->dev);
+ struct usb_se401 *se401 = usb_get_intfdata (intf);
- dev_set_drvdata (&intf->dev, NULL);
+ usb_set_intfdata (intf, NULL);
if (se401) {
video_unregister_device(&se401->vdev);
if (!se401->user){
diff --git a/drivers/usb/media/stv680.c b/drivers/usb/media/stv680.c
index 1dc71245999e..1b5df6990a4c 100644
--- a/drivers/usb/media/stv680.c
+++ b/drivers/usb/media/stv680.c
@@ -1498,7 +1498,7 @@ static int stv680_probe (struct usb_interface *intf, const struct usb_device_id
#endif
PDEBUG (0, "STV(i): registered new video device: video%d", stv680->vdev.minor);
- dev_set_drvdata (&intf->dev, stv680);
+ usb_set_intfdata (intf, stv680);
return 0;
}
@@ -1535,9 +1535,9 @@ static inline void usb_stv680_remove_disconnected (struct usb_stv *stv680)
static void stv680_disconnect (struct usb_interface *intf)
{
- struct usb_stv *stv680 = dev_get_drvdata (&intf->dev);
+ struct usb_stv *stv680 = usb_get_intfdata (intf);
- dev_set_drvdata (&intf->dev, NULL);
+ usb_set_intfdata (intf, NULL);
if (stv680) {
/* We don't want people trying to open up the device */
diff --git a/drivers/usb/media/ultracam.c b/drivers/usb/media/ultracam.c
index cc8bca854b56..d6cacadacc8a 100644
--- a/drivers/usb/media/ultracam.c
+++ b/drivers/usb/media/ultracam.c
@@ -1,5 +1,8 @@
/*
* USB NB Camera driver
+ *
+ * HISTORY:
+ * 25-Dec-2002 Dmitri Removed lighting, sharpness parameters, methods.
*/
#include <linux/kernel.h>
@@ -34,12 +37,6 @@ static int flags = 0; /* FLAGS_DISPLAY_HINTS | FLAGS_OVERLAY_STATS; */
static const int min_canvasWidth = 8;
static const int min_canvasHeight = 4;
-//static int lighting = 1; /* Medium */
-
-#define SHARPNESS_MIN 0
-#define SHARPNESS_MAX 6
-//static int sharpness = 4; /* Low noise, good details */
-
#define FRAMERATE_MIN 0
#define FRAMERATE_MAX 6
static int framerate = -1;
@@ -77,10 +74,6 @@ MODULE_PARM_DESC(flags,
"6=clean frames");
MODULE_PARM(framerate, "i");
MODULE_PARM_DESC(framerate, "Framerate setting: 0=slowest, 6=fastest (default=2)");
-MODULE_PARM(lighting, "i");
-MODULE_PARM_DESC(lighting, "Photosensitivity: 0=bright, 1=medium (default), 2=low light");
-MODULE_PARM(sharpness, "i");
-MODULE_PARM_DESC(sharpness, "Model1 noise reduction: 0=smooth, 6=sharp (default=4)");
MODULE_PARM(init_brightness, "i");
MODULE_PARM_DESC(init_brightness, "Brightness preconfiguration: 0-255 (default=128)");
@@ -206,24 +199,6 @@ static void ultracam_adjust_contrast(struct uvd *uvd)
}
/*
- * ultracam_change_lighting_conditions()
- */
-static void ultracam_change_lighting_conditions(struct uvd *uvd)
-{
-}
-
-/*
- * ultracam_set_sharpness()
- *
- * Cameras model 1 have internal smoothing feature. It is controlled by value in
- * range [0..6], where 0 is most smooth and 6 is most sharp (raw image, I guess).
- * Recommended value is 4. Cameras model 2 do not have this feature at all.
- */
-static void ultracam_set_sharpness(struct uvd *uvd)
-{
-}
-
-/*
* ultracam_set_brightness()
*
* This procedure changes brightness of the picture.
@@ -272,8 +247,6 @@ static void ultracam_reinit_iso(struct uvd *uvd, int do_stop)
static void ultracam_video_start(struct uvd *uvd)
{
- ultracam_change_lighting_conditions(uvd);
- ultracam_set_sharpness(uvd);
ultracam_reinit_iso(uvd, 0);
}
@@ -662,7 +635,7 @@ static int ultracam_probe(struct usb_interface *intf, const struct usb_device_id
MOD_DEC_USE_COUNT;
if (uvd) {
- dev_set_drvdata (&intf->dev, uvd);
+ usb_set_intfdata (intf, uvd);
return 0;
}
return -EIO;
diff --git a/drivers/usb/media/usbvideo.c b/drivers/usb/media/usbvideo.c
index fe0c7e35f812..4c81b621ff76 100644
--- a/drivers/usb/media/usbvideo.c
+++ b/drivers/usb/media/usbvideo.c
@@ -730,6 +730,7 @@ EXPORT_SYMBOL(usbvideo_SayAndWait);
/* ******************************************************************** */
+/* XXX: this piece of crap really wants some error handling.. */
static void usbvideo_ClientIncModCount(struct uvd *uvd)
{
if (uvd == NULL) {
@@ -744,7 +745,10 @@ static void usbvideo_ClientIncModCount(struct uvd *uvd)
err("%s: uvd->handle->md_module == NULL", __FUNCTION__);
return;
}
- __MOD_INC_USE_COUNT(uvd->handle->md_module);
+ if (!try_module_get(uvd->handle->md_module)) {
+ err("%s: try_module_get() == 0", __FUNCTION__);
+ return;
+ }
}
static void usbvideo_ClientDecModCount(struct uvd *uvd)
@@ -761,7 +765,7 @@ static void usbvideo_ClientDecModCount(struct uvd *uvd)
err("%s: uvd->handle->md_module == NULL", __FUNCTION__);
return;
}
- __MOD_DEC_USE_COUNT(uvd->handle->md_module);
+ module_put(uvd->handle->md_module);
}
int usbvideo_register(
@@ -968,7 +972,7 @@ EXPORT_SYMBOL(usbvideo_Deregister);
*/
static void usbvideo_Disconnect(struct usb_interface *intf)
{
- struct uvd *uvd = dev_get_drvdata (&intf->dev);
+ struct uvd *uvd = usb_get_intfdata (intf);
int i;
if (uvd == NULL) {
@@ -976,7 +980,7 @@ static void usbvideo_Disconnect(struct usb_interface *intf)
return;
}
- dev_set_drvdata (&intf->dev, NULL);
+ usb_set_intfdata (intf, NULL);
usbvideo_ClientIncModCount(uvd);
if (uvd->debug > 0)
diff --git a/drivers/usb/media/vicam.c b/drivers/usb/media/vicam.c
index d7ba9d6440bf..44acb135ba96 100644
--- a/drivers/usb/media/vicam.c
+++ b/drivers/usb/media/vicam.c
@@ -1307,7 +1307,7 @@ vicam_probe( struct usb_interface *intf, const struct usb_device_id *id)
printk(KERN_INFO "ViCam webcam driver now controlling video device %d\n",cam->vdev.minor);
- dev_set_drvdata(&intf->dev, cam);
+ usb_set_intfdata (intf, cam);
return 0;
}
@@ -1316,8 +1316,8 @@ static void
vicam_disconnect(struct usb_interface *intf)
{
int open_count;
- struct vicam_camera *cam = dev_get_drvdata(&intf->dev);
- dev_set_drvdata ( &intf->dev, NULL );
+ struct vicam_camera *cam = usb_get_intfdata (intf);
+ usb_set_intfdata (intf, NULL);
/* we must unregister the device before taking its
* cam_lock. This is because the video open call
diff --git a/drivers/usb/misc/auerswald.c b/drivers/usb/misc/auerswald.c
index 476ae293a56d..48b0e8ba6a81 100644
--- a/drivers/usb/misc/auerswald.c
+++ b/drivers/usb/misc/auerswald.c
@@ -2061,7 +2061,7 @@ static int auerswald_probe (struct usb_interface *intf,
}
/* all OK */
- dev_set_drvdata (&intf->dev, cp);
+ usb_set_intfdata (intf, cp);
return 0;
/* Error exit: clean up the memory */
@@ -2085,10 +2085,10 @@ pfail: auerswald_delete (cp);
*/
static void auerswald_disconnect (struct usb_interface *intf)
{
- pauerswald_t cp = dev_get_drvdata (&intf->dev);
+ pauerswald_t cp = usb_get_intfdata (intf);
unsigned int u;
- dev_set_drvdata (&intf->dev, NULL);
+ usb_set_intfdata (intf, NULL);
if (!cp)
return;
diff --git a/drivers/usb/misc/brlvger.c b/drivers/usb/misc/brlvger.c
index 279d6bb94d99..4c8191072665 100644
--- a/drivers/usb/misc/brlvger.c
+++ b/drivers/usb/misc/brlvger.c
@@ -406,7 +406,7 @@ brlvger_probe (struct usb_interface *intf,
out:
up(&reserve_sem);
if (priv) {
- dev_set_drvdata (&intf->dev, priv);
+ usb_set_intfdata (intf, priv);
return 0;
}
return -EIO;
@@ -415,10 +415,10 @@ brlvger_probe (struct usb_interface *intf,
static void
brlvger_disconnect(struct usb_interface *intf)
{
- struct brlvger_priv *priv = dev_get_drvdata (&intf->dev);
+ struct brlvger_priv *priv = usb_get_intfdata (intf);
int r;
- dev_set_drvdata (&intf->dev, NULL);
+ usb_set_intfdata (intf, NULL);
if(priv){
info("Display %d disconnecting", priv->subminor);
diff --git a/drivers/usb/misc/rio500.c b/drivers/usb/misc/rio500.c
index f4c86b6d19e6..9c8e01184393 100644
--- a/drivers/usb/misc/rio500.c
+++ b/drivers/usb/misc/rio500.c
@@ -491,15 +491,15 @@ static int probe_rio(struct usb_interface *intf,
init_MUTEX(&(rio->lock));
- dev_set_drvdata (&intf->dev, rio);
+ usb_set_intfdata (intf, rio);
return 0;
}
static void disconnect_rio(struct usb_interface *intf)
{
- struct rio_usb_data *rio = dev_get_drvdata (&intf->dev);
+ struct rio_usb_data *rio = usb_get_intfdata (intf);
- dev_set_drvdata (&intf->dev, NULL);
+ usb_set_intfdata (intf, NULL);
if (rio) {
devfs_unregister(rio->devfs);
usb_deregister_dev(1, rio->minor);
diff --git a/drivers/usb/misc/speedtouch.c b/drivers/usb/misc/speedtouch.c
index 53d09d199270..645591463439 100644
--- a/drivers/usb/misc/speedtouch.c
+++ b/drivers/usb/misc/speedtouch.c
@@ -973,16 +973,16 @@ static int udsl_usb_probe (struct usb_interface *intf, const struct usb_device_i
minor_data[instance->minor] = instance;
- dev_set_drvdata (&intf->dev, instance);
+ usb_set_intfdata (intf, instance);
return 0;
}
static void udsl_usb_disconnect (struct usb_interface *intf)
{
- struct udsl_instance_data *instance = dev_get_drvdata (&intf->dev);
+ struct udsl_instance_data *instance = usb_get_intfdata (intf);
int i;
- dev_set_drvdata (&intf->dev, NULL);
+ usb_set_intfdata (intf, NULL);
if (instance) {
i = instance->minor;
/* unlinking receive buffers */
diff --git a/drivers/usb/misc/tiglusb.c b/drivers/usb/misc/tiglusb.c
index 28e8a17c93c6..7ba36f37036e 100644
--- a/drivers/usb/misc/tiglusb.c
+++ b/drivers/usb/misc/tiglusb.c
@@ -383,7 +383,7 @@ tiglusb_probe (struct usb_interface *intf,
dev->descriptor.bcdDevice >> 8,
dev->descriptor.bcdDevice & 0xff);
- dev_set_drvdata (&intf->dev, s);
+ usb_set_intfdata (intf, s);
return 0;
}
@@ -392,9 +392,9 @@ tiglusb_disconnect (struct usb_interface *intf)
{
char name[32];
- ptiglusb_t s = dev_get_drvdata (&intf->dev);
+ ptiglusb_t s = usb_get_intfdata (intf);
- dev_set_drvdata (&intf->dev, NULL);
+ usb_set_intfdata (intf, NULL);
if (!s || !s->dev) {
info ("bogus disconnect");
return;
diff --git a/drivers/usb/misc/usblcd.c b/drivers/usb/misc/usblcd.c
index 7fc2e2ab224d..27dc40d0c69c 100644
--- a/drivers/usb/misc/usblcd.c
+++ b/drivers/usb/misc/usblcd.c
@@ -290,15 +290,15 @@ static int probe_lcd(struct usb_interface *intf, const struct usb_device_id *id)
}
dbg("probe_lcd: ibuf address:%p", lcd->ibuf);
- dev_set_drvdata (&intf->dev, lcd);
+ usb_set_intfdata (intf, lcd);
return 0;
}
static void disconnect_lcd(struct usb_interface *intf)
{
- struct lcd_usb_data *lcd = dev_get_drvdata (&intf->dev);
+ struct lcd_usb_data *lcd = usb_get_intfdata (intf);
- dev_set_drvdata (&intf->dev, NULL);
+ usb_set_intfdata (intf, NULL);
if (lcd) {
usb_deregister_dev(1, lcd->minor);
diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c
index 7d6ee5ba3e86..289ab9c6dc69 100644
--- a/drivers/usb/misc/usbtest.c
+++ b/drivers/usb/misc/usbtest.c
@@ -635,7 +635,7 @@ static int unlink_simple (struct usbtest_dev *dev, int pipe, int len)
static int
usbtest_ioctl (struct usb_interface *intf, unsigned int code, void *buf)
{
- struct usbtest_dev *dev = dev_get_drvdata (&intf->dev);
+ struct usbtest_dev *dev = usb_get_intfdata (intf);
struct usb_device *udev = testdev_to_usbdev (dev);
struct usbtest_param *param = buf;
int retval = -EOPNOTSUPP;
@@ -957,7 +957,7 @@ usbtest_probe (struct usb_interface *intf, const struct usb_device_id *id)
}
}
- dev_set_drvdata (&intf->dev, dev);
+ usb_set_intfdata (intf, dev);
info ("%s at %s ... %s speed {control%s%s} tests",
info->name, dev->id,
({ char *tmp;
@@ -972,13 +972,12 @@ usbtest_probe (struct usb_interface *intf, const struct usb_device_id *id)
static void usbtest_disconnect (struct usb_interface *intf)
{
- struct usbtest_dev *dev = dev_get_drvdata (&intf->dev);
+ struct usbtest_dev *dev = usb_get_intfdata (intf);
down (&dev->sem);
- dev_set_drvdata (&intf->dev, 0);
+ usb_set_intfdata (intf, NULL);
info ("unbound %s", dev->id);
- kfree (intf->private_data);
}
/* Basic testing only needs a device that can source or sink bulk traffic.
diff --git a/drivers/usb/misc/uss720.c b/drivers/usb/misc/uss720.c
index 3756af894c20..667195b1cb4a 100644
--- a/drivers/usb/misc/uss720.c
+++ b/drivers/usb/misc/uss720.c
@@ -608,7 +608,7 @@ static int uss720_probe(struct usb_interface *intf,
parport_announce_port(pp);
MOD_INC_USE_COUNT;
- dev_set_drvdata (&intf->dev, pp);
+ usb_set_intfdata (intf, pp);
return 0;
#if 0
@@ -622,10 +622,10 @@ probe_abort:
static void uss720_disconnect(struct usb_interface *intf)
{
- struct parport *pp = dev_get_drvdata (&intf->dev);
+ struct parport *pp = usb_get_intfdata (intf);
struct parport_uss720_private *priv;
- dev_set_drvdata (&intf->dev, NULL);
+ usb_set_intfdata (intf, NULL);
if (pp) {
priv = pp->private_data;
#if 0
diff --git a/drivers/usb/net/catc.c b/drivers/usb/net/catc.c
index a8a33237384e..1cfb0e42f91f 100644
--- a/drivers/usb/net/catc.c
+++ b/drivers/usb/net/catc.c
@@ -928,15 +928,15 @@ static int catc_probe(struct usb_interface *intf, const struct usb_device_id *id
usbdev->bus->bus_name, usbdev->devpath);
for (i = 0; i < 5; i++) printk("%2.2x:", netdev->dev_addr[i]);
printk("%2.2x.\n", netdev->dev_addr[i]);
- dev_set_drvdata (&intf->dev, catc);
+ usb_set_intfdata(intf, catc);
return 0;
}
static void catc_disconnect(struct usb_interface *intf)
{
- struct catc *catc = dev_get_drvdata (&intf->dev);
+ struct catc *catc = usb_get_intfdata(intf);
- dev_set_drvdata (&intf->dev, NULL);
+ usb_set_intfdata(intf, NULL);
if (catc) {
unregister_netdev(catc->netdev);
usb_free_urb(catc->ctrl_urb);
diff --git a/drivers/usb/net/cdc-ether.c b/drivers/usb/net/cdc-ether.c
index 46271a3c1e64..2dc8dfe0ba99 100644
--- a/drivers/usb/net/cdc-ether.c
+++ b/drivers/usb/net/cdc-ether.c
@@ -1287,10 +1287,10 @@ error_all:
static void CDCEther_disconnect( struct usb_interface *intf )
{
- ether_dev_t *ether_dev = dev_get_drvdata (&intf->dev);
+ ether_dev_t *ether_dev = usb_get_intfdata(intf);
struct usb_device *usb;
- dev_set_drvdata (&intf->dev, NULL);
+ usb_set_intfdata(intf, NULL);
// Sanity check!!!
if ( !ether_dev || !ether_dev->usb ) {
diff --git a/drivers/usb/net/kaweth.c b/drivers/usb/net/kaweth.c
index 831f9ef4eea3..6fe19a3ca9f6 100644
--- a/drivers/usb/net/kaweth.c
+++ b/drivers/usb/net/kaweth.c
@@ -612,8 +612,6 @@ static int kaweth_open(struct net_device *net)
struct kaweth_device *kaweth = (struct kaweth_device *)net->priv;
int res;
- kaweth_dbg("Dev usage: %d", kaweth->dev->refcnt.counter);
-
kaweth_dbg("Opening network device.");
res = kaweth_resubmit_rx_urb(kaweth, GFP_KERNEL);
@@ -658,9 +656,6 @@ static int kaweth_close(struct net_device *net)
kaweth->status &= ~KAWETH_STATUS_CLOSING;
-
- printk("Dev usage: %d", kaweth->dev->refcnt.counter);
-
return 0;
}
@@ -1066,7 +1061,7 @@ static int kaweth_probe(
kaweth_dbg("Kaweth probe returning.");
- dev_set_drvdata (&intf->dev, kaweth);
+ usb_set_intfdata(intf, kaweth);
return 0;
err_tx_and_rx:
@@ -1085,11 +1080,11 @@ err_no_netdev:
****************************************************************/
static void kaweth_disconnect(struct usb_interface *intf)
{
- struct kaweth_device *kaweth = dev_get_drvdata (&intf->dev);
+ struct kaweth_device *kaweth = usb_get_intfdata(intf);
kaweth_info("Unregistering");
- dev_set_drvdata (&intf->dev, NULL);
+ usb_set_intfdata(intf, NULL);
if (!kaweth) {
kaweth_warn("unregistering non-existant device");
return;
diff --git a/drivers/usb/net/pegasus.c b/drivers/usb/net/pegasus.c
index 17e538bcbfae..8efd680e7b70 100644
--- a/drivers/usb/net/pegasus.c
+++ b/drivers/usb/net/pegasus.c
@@ -1244,7 +1244,7 @@ static int pegasus_probe(struct usb_interface *intf,
exit:
up(&pegasus->sem);
if (pegasus) {
- dev_set_drvdata(&intf->dev, pegasus);
+ usb_set_intfdata(intf, pegasus);
return 0;
}
return -EIO;
@@ -1252,9 +1252,9 @@ exit:
static void pegasus_disconnect(struct usb_interface *intf)
{
- struct pegasus *pegasus = dev_get_drvdata(&intf->dev);
+ struct pegasus *pegasus = usb_get_intfdata(intf);
- dev_set_drvdata(&intf->dev, NULL);
+ usb_set_intfdata(intf, NULL);
if (!pegasus) {
warn("unregistering non-existant device");
return;
diff --git a/drivers/usb/net/rtl8150.c b/drivers/usb/net/rtl8150.c
index fbbb6d5d2025..d430dbd6e338 100644
--- a/drivers/usb/net/rtl8150.c
+++ b/drivers/usb/net/rtl8150.c
@@ -842,7 +842,7 @@ static int rtl8150_probe(struct usb_interface *intf,
info("%s: rtl8150 is detected", netdev->name);
up(&dev->sem);
- dev_set_drvdata(&intf->dev, dev);
+ usb_set_intfdata(intf, dev);
return 0;
err:
unregister_netdev(dev->netdev);
@@ -854,9 +854,9 @@ err:
static void rtl8150_disconnect(struct usb_interface *intf)
{
- rtl8150_t *dev = dev_get_drvdata(&intf->dev);
+ rtl8150_t *dev = usb_get_intfdata(intf);
- dev_set_drvdata(&intf->dev, NULL);
+ usb_set_intfdata(intf, NULL);
if (dev) {
set_bit(RTL8150_UNPLUG, &dev->flags);
unregister_netdev(dev->netdev);
diff --git a/drivers/usb/net/usbnet.c b/drivers/usb/net/usbnet.c
index 17eb48408556..f28782b6cc9f 100644
--- a/drivers/usb/net/usbnet.c
+++ b/drivers/usb/net/usbnet.c
@@ -146,6 +146,11 @@
#endif
#include <linux/usb.h>
+#include <asm/io.h>
+#include <asm/scatterlist.h>
+#include <linux/mm.h>
+#include <linux/dma-mapping.h>
+
/* minidrivers _could_ be individually configured */
#define CONFIG_USB_AN2720
@@ -2089,8 +2094,8 @@ static void usbnet_disconnect (struct usb_interface *intf)
struct usbnet *dev;
struct usb_device *xdev;
- dev = dev_get_drvdata (&intf->dev);
- dev_set_drvdata (&intf->dev, NULL);
+ dev = usb_get_intfdata(intf);
+ usb_set_intfdata(intf, NULL);
if (!dev)
return;
@@ -2169,9 +2174,13 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod)
memcpy (net->dev_addr, node_id, sizeof node_id);
// point-to-point link ... we always use Ethernet headers
- // supports win32 interop and the bridge driver.
+ // supports win32 interop (some devices) and the bridge driver.
ether_setup (net);
+ // possible with some EHCI controllers
+ if (dma_supported (&udev->dev, 0xffffffffffffffffULL))
+ net->features |= NETIF_F_HIGHDMA;
+
net->change_mtu = usbnet_change_mtu;
net->get_stats = usbnet_get_stats;
net->hard_start_xmit = usbnet_start_xmit;
@@ -2197,7 +2206,7 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod)
#endif
// ok, it's ready to go.
- dev_set_drvdata (&udev->dev, dev);
+ usb_set_intfdata(udev, dev);
mutex_lock (&usbnet_mutex);
list_add (&dev->dev_list, &usbnet_list);
mutex_unlock (&dev->mutex);
diff --git a/drivers/usb/serial/Kconfig b/drivers/usb/serial/Kconfig
index 1e0dfb0dd9e7..82f3db1ee634 100644
--- a/drivers/usb/serial/Kconfig
+++ b/drivers/usb/serial/Kconfig
@@ -150,11 +150,11 @@ config USB_SERIAL_VISOR
module, say M here and read <file:Documentation/modules.txt>.
config USB_SERIAL_IPAQ
- tristate "USB Compaq iPAQ / HP Jornada / Casio EM500 Driver"
+ tristate "USB PocketPC PDA Driver"
depends on USB_SERIAL
help
Say Y here if you want to connect to your Compaq iPAQ, HP Jornada
- 548/568 or Casio EM500 running Windows CE 3.0 or PocketPC 2002
+ or any other PDA running Windows CE 3.0 or PocketPC 2002
using a USB cradle/cable. For information on using the driver,
read <file:Documentation/usb/usb-serial.txt>.
diff --git a/drivers/usb/serial/belkin_sa.c b/drivers/usb/serial/belkin_sa.c
index b41178f59bf0..17c1b2f587c8 100644
--- a/drivers/usb/serial/belkin_sa.c
+++ b/drivers/usb/serial/belkin_sa.c
@@ -171,10 +171,9 @@ static int belkin_sa_startup (struct usb_serial *serial)
struct belkin_sa_private *priv;
/* allocate the private data structure */
- serial->port->private = kmalloc(sizeof(struct belkin_sa_private), GFP_KERNEL);
- if (!serial->port->private)
+ priv = kmalloc(sizeof(struct belkin_sa_private), GFP_KERNEL);
+ if (!priv)
return (-1); /* error */
- priv = (struct belkin_sa_private *)serial->port->private;
/* set initial values for control structures */
priv->control_state = 0;
priv->last_lsr = 0;
@@ -184,6 +183,7 @@ static int belkin_sa_startup (struct usb_serial *serial)
info("bcdDevice: %04x, bfc: %d", dev->descriptor.bcdDevice, priv->bad_flow_control);
init_waitqueue_head(&serial->port->write_wait);
+ usb_set_serial_port_data(serial->port, priv);
return (0);
}
@@ -191,6 +191,7 @@ static int belkin_sa_startup (struct usb_serial *serial)
static void belkin_sa_shutdown (struct usb_serial *serial)
{
+ struct belkin_sa_private *priv;
int i;
dbg ("%s", __FUNCTION__);
@@ -198,8 +199,9 @@ static void belkin_sa_shutdown (struct usb_serial *serial)
/* stop reads and writes on all ports */
for (i=0; i < serial->num_ports; ++i) {
/* My special items, the standard routines free my urbs */
- if (serial->port[i].private)
- kfree(serial->port[i].private);
+ priv = usb_get_serial_port_data(&serial->port[i]);
+ if (priv)
+ kfree(priv);
}
}
@@ -286,7 +288,7 @@ static void belkin_sa_read_int_callback (struct urb *urb, struct pt_regs *regs)
/* Handle known interrupt data */
/* ignore data[0] and data[1] */
- priv = (struct belkin_sa_private *)port->private;
+ priv = usb_get_serial_port_data(port);
priv->last_msr = data[BELKIN_SA_MSR_INDEX];
/* Record Control Line states */
@@ -344,7 +346,7 @@ exit:
static void belkin_sa_set_termios (struct usb_serial_port *port, struct termios *old_termios)
{
struct usb_serial *serial = port->serial;
- struct belkin_sa_private *priv = (struct belkin_sa_private *)port->private;
+ struct belkin_sa_private *priv = usb_get_serial_port_data(port);
unsigned int iflag;
unsigned int cflag;
unsigned int old_iflag = 0;
@@ -485,7 +487,7 @@ static int belkin_sa_ioctl (struct usb_serial_port *port, struct file * file, un
{
struct usb_serial *serial = port->serial;
__u16 urb_value; /* Will hold the new flags */
- struct belkin_sa_private *priv = (struct belkin_sa_private *)port->private;
+ struct belkin_sa_private *priv = usb_get_serial_port_data(port);
int ret, mask;
/* Based on code from acm.c and others */
diff --git a/drivers/usb/serial/bus.c b/drivers/usb/serial/bus.c
index 3d99da8441d5..fee75805b1c9 100644
--- a/drivers/usb/serial/bus.c
+++ b/drivers/usb/serial/bus.c
@@ -66,7 +66,7 @@ static int usb_serial_device_probe (struct device *dev)
driver = port->serial->type;
if (driver->port_probe) {
if (!try_module_get(driver->owner)) {
- err ("module get failed, exiting");
+ dev_err(*dev, "module get failed, exiting\n");
retval = -EIO;
goto exit;
}
@@ -79,8 +79,8 @@ static int usb_serial_device_probe (struct device *dev)
minor = port->number;
tty_register_devfs (&usb_serial_tty_driver, 0, minor);
- info("%s converter now attached to ttyUSB%d (or usb/tts/%d for devfs)",
- driver->name, minor, minor);
+ dev_info(*dev, "%s converter now attached to ttyUSB%d (or usb/tts/%d for devfs)\n",
+ driver->name, minor, minor);
exit:
return retval;
@@ -101,7 +101,7 @@ static int usb_serial_device_remove (struct device *dev)
driver = port->serial->type;
if (driver->port_remove) {
if (!try_module_get(driver->owner)) {
- err ("module get failed, exiting");
+ dev_err(*dev, "module get failed, exiting\n");
retval = -EIO;
goto exit;
}
@@ -111,8 +111,8 @@ static int usb_serial_device_remove (struct device *dev)
exit:
minor = port->number;
tty_unregister_devfs (&usb_serial_tty_driver, minor);
- info("%s converter now disconnected from ttyUSB%d",
- driver->name, minor);
+ dev_info(*dev, "%s converter now disconnected from ttyUSB%d\n",
+ driver->name, minor);
return retval;
}
diff --git a/drivers/usb/serial/cyberjack.c b/drivers/usb/serial/cyberjack.c
index a532245eee80..8f6dcd730173 100644
--- a/drivers/usb/serial/cyberjack.c
+++ b/drivers/usb/serial/cyberjack.c
@@ -114,15 +114,15 @@ static int cyberjack_startup (struct usb_serial *serial)
dbg("%s", __FUNCTION__);
/* allocate the private data structure */
- serial->port->private = kmalloc(sizeof(struct cyberjack_private), GFP_KERNEL);
- if (!serial->port->private)
- return (-1); /* error */
+ priv = kmalloc(sizeof(struct cyberjack_private), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
/* set initial values */
- priv = (struct cyberjack_private *)serial->port->private;
priv->rdtodo = 0;
priv->wrfilled = 0;
priv->wrsent = 0;
+ usb_set_serial_port_data(serial->port, priv);
init_waitqueue_head(&serial->port->write_wait);
@@ -137,8 +137,8 @@ static void cyberjack_shutdown (struct usb_serial *serial)
for (i=0; i < serial->num_ports; ++i) {
/* My special items, the standard routines free my urbs */
- if (serial->port[i].private)
- kfree(serial->port[i].private);
+ kfree(usb_get_serial_port_data(&serial->port[i]));
+ usb_set_serial_port_data(&serial->port[i], NULL);
}
}
@@ -158,7 +158,7 @@ static int cyberjack_open (struct usb_serial_port *port, struct file *filp)
*/
port->tty->low_latency = 1;
- priv = (struct cyberjack_private *)port->private;
+ priv = usb_get_serial_port_data(port);
priv->rdtodo = 0;
priv->wrfilled = 0;
priv->wrsent = 0;
@@ -192,7 +192,7 @@ static void cyberjack_close (struct usb_serial_port *port, struct file *filp)
static int cyberjack_write (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count)
{
struct usb_serial *serial = port->serial;
- struct cyberjack_private *priv = (struct cyberjack_private *)port->private;
+ struct cyberjack_private *priv = usb_get_serial_port_data(port);
int result;
int wrexpected;
@@ -280,7 +280,7 @@ static int cyberjack_write (struct usb_serial_port *port, int from_user, const u
static void cyberjack_read_int_callback( struct urb *urb, struct pt_regs *regs )
{
struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
- struct cyberjack_private *priv = (struct cyberjack_private *)port->private;
+ struct cyberjack_private *priv = usb_get_serial_port_data(port);
struct usb_serial *serial;
unsigned char *data = urb->transfer_buffer;
@@ -334,7 +334,7 @@ static void cyberjack_read_int_callback( struct urb *urb, struct pt_regs *regs )
static void cyberjack_read_bulk_callback (struct urb *urb, struct pt_regs *regs)
{
struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
- struct cyberjack_private *priv = (struct cyberjack_private *)port->private;
+ struct cyberjack_private *priv = usb_get_serial_port_data(port);
struct usb_serial *serial = get_usb_serial (port, __FUNCTION__);
struct tty_struct *tty;
unsigned char *data = urb->transfer_buffer;
@@ -389,7 +389,7 @@ static void cyberjack_read_bulk_callback (struct urb *urb, struct pt_regs *regs)
static void cyberjack_write_bulk_callback (struct urb *urb, struct pt_regs *regs)
{
struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
- struct cyberjack_private *priv = (struct cyberjack_private *)port->private;
+ struct cyberjack_private *priv = usb_get_serial_port_data(port);
struct usb_serial *serial = get_usb_serial (port, __FUNCTION__);
dbg("%s - port %d", __FUNCTION__, port->number);
diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c
index 659e91cfd1f7..76fb9c41fe2d 100644
--- a/drivers/usb/serial/digi_acceleport.c
+++ b/drivers/usb/serial/digi_acceleport.c
@@ -604,7 +604,7 @@ static void digi_wakeup_write_lock( struct usb_serial_port *port )
{
unsigned long flags;
- struct digi_port *priv = (struct digi_port *)(port->private);
+ struct digi_port *priv = usb_get_serial_port_data(port);
spin_lock_irqsave( &priv->dp_port_lock, flags );
@@ -650,8 +650,8 @@ static int digi_write_oob_command( struct usb_serial_port *port,
int ret = 0;
int len;
- struct usb_serial_port *oob_port = (struct usb_serial_port *)((struct digi_serial *)port->serial->private)->ds_oob_port;
- struct digi_port *oob_priv = (struct digi_port *)oob_port->private;
+ struct usb_serial_port *oob_port = (struct usb_serial_port *)((struct digi_serial *)(usb_get_serial_data(port->serial)))->ds_oob_port;
+ struct digi_port *oob_priv = usb_get_serial_port_data(oob_port);
unsigned long flags = 0;
@@ -719,7 +719,7 @@ static int digi_write_inb_command( struct usb_serial_port *port,
int ret = 0;
int len;
- struct digi_port *priv = (struct digi_port *)(port->private);
+ struct digi_port *priv = usb_get_serial_port_data(port);
unsigned char *data = port->write_urb->transfer_buffer;
unsigned long flags = 0;
@@ -805,9 +805,9 @@ static int digi_set_modem_signals( struct usb_serial_port *port,
{
int ret;
- struct digi_port *port_priv = (struct digi_port *)port->private;
- struct usb_serial_port *oob_port = (struct usb_serial_port *)((struct digi_serial *)port->serial->private)->ds_oob_port;
- struct digi_port *oob_priv = (struct digi_port *)oob_port->private;
+ struct digi_port *port_priv = usb_get_serial_port_data(port);
+ struct usb_serial_port *oob_port = (struct usb_serial_port *)((struct digi_serial *)(usb_get_serial_data(port->serial)))->ds_oob_port;
+ struct digi_port *oob_priv = usb_get_serial_port_data(oob_port);
unsigned char *data = oob_port->write_urb->transfer_buffer;
unsigned long flags = 0;
@@ -884,7 +884,7 @@ static int digi_transmit_idle( struct usb_serial_port *port,
int ret;
unsigned char buf[2];
- struct digi_port *priv = (struct digi_port *)(port->private);
+ struct digi_port *priv = usb_get_serial_port_data(port);
unsigned long flags = 0;
@@ -924,7 +924,7 @@ static void digi_rx_throttle( struct usb_serial_port *port )
{
unsigned long flags;
- struct digi_port *priv = (struct digi_port *)(port->private);
+ struct digi_port *priv = usb_get_serial_port_data(port);
dbg( "digi_rx_throttle: TOP: port=%d", priv->dp_port_num );
@@ -945,7 +945,7 @@ static void digi_rx_unthrottle( struct usb_serial_port *port )
int ret = 0;
int len;
unsigned long flags;
- struct digi_port *priv = (struct digi_port *)(port->private);
+ struct digi_port *priv = usb_get_serial_port_data(port);
struct tty_struct *tty = port->tty;
@@ -989,7 +989,7 @@ static void digi_set_termios( struct usb_serial_port *port,
struct termios *old_termios )
{
- struct digi_port *priv = (struct digi_port *)(port->private);
+ struct digi_port *priv = usb_get_serial_port_data(port);
unsigned int iflag = port->tty->termios->c_iflag;
unsigned int cflag = port->tty->termios->c_cflag;
unsigned int old_iflag = old_termios->c_iflag;
@@ -1213,7 +1213,7 @@ static int digi_ioctl( struct usb_serial_port *port, struct file *file,
unsigned int cmd, unsigned long arg )
{
- struct digi_port *priv = (struct digi_port *)(port->private);
+ struct digi_port *priv = usb_get_serial_port_data(port);
unsigned int val;
unsigned long flags = 0;
@@ -1265,7 +1265,7 @@ static int digi_write( struct usb_serial_port *port, int from_user,
{
int ret,data_len,new_len;
- struct digi_port *priv = (struct digi_port *)(port->private);
+ struct digi_port *priv = usb_get_serial_port_data(port);
unsigned char *data = port->write_urb->transfer_buffer;
unsigned char user_buf[64]; /* 64 bytes is max USB bulk packet */
unsigned long flags = 0;
@@ -1353,26 +1353,26 @@ static void digi_write_bulk_callback( struct urb *urb, struct pt_regs *regs )
struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
struct usb_serial *serial;
struct digi_port *priv;
+ struct digi_serial *serial_priv;
int ret = 0;
dbg( "digi_write_bulk_callback: TOP, urb->status=%d", urb->status );
/* port and serial sanity check */
- if( port == NULL || (priv=(struct digi_port *)(port->private)) == NULL ) {
+ if( port == NULL || (priv=usb_get_serial_port_data(port)) == NULL ) {
err("%s: port or port->private is NULL, status=%d", __FUNCTION__,
urb->status );
return;
}
serial = port->serial;
- if( serial == NULL || serial->private == NULL ) {
+ if( serial == NULL || (serial_priv=usb_get_serial_data(serial)) == NULL ) {
err("%s: serial or serial->private is NULL, status=%d", __FUNCTION__, urb->status );
return;
}
/* handle oob callback */
- if( priv->dp_port_num
- == ((struct digi_serial *)(serial->private))->ds_oob_port_num ) {
+ if( priv->dp_port_num == serial_priv->ds_oob_port_num ) {
dbg( "digi_write_bulk_callback: oob callback" );
spin_lock( &priv->dp_port_lock );
priv->dp_write_urb_in_use = 0;
@@ -1432,7 +1432,7 @@ static int digi_write_room( struct usb_serial_port *port )
{
int room;
- struct digi_port *priv = (struct digi_port *)(port->private);
+ struct digi_port *priv = usb_get_serial_port_data(port);
unsigned long flags = 0;
@@ -1455,7 +1455,7 @@ dbg( "digi_write_room: port=%d, room=%d", priv->dp_port_num, room );
static int digi_chars_in_buffer( struct usb_serial_port *port )
{
- struct digi_port *priv = (struct digi_port *)(port->private);
+ struct digi_port *priv = usb_get_serial_port_data(port);
if( port->write_urb->status == -EINPROGRESS
@@ -1476,7 +1476,7 @@ static int digi_open( struct usb_serial_port *port, struct file *filp )
int ret;
unsigned char buf[32];
- struct digi_port *priv = (struct digi_port *)(port->private);
+ struct digi_port *priv = usb_get_serial_port_data(port);
struct termios not_termios;
unsigned long flags = 0;
@@ -1542,7 +1542,7 @@ static void digi_close( struct usb_serial_port *port, struct file *filp )
int ret;
unsigned char buf[32];
struct tty_struct *tty = port->tty;
- struct digi_port *priv = (struct digi_port *)port->private;
+ struct digi_port *priv = usb_get_serial_port_data(port);
unsigned long flags = 0;
@@ -1641,7 +1641,7 @@ static int digi_startup_device( struct usb_serial *serial )
{
int i,ret = 0;
- struct digi_serial *serial_priv = (struct digi_serial *)serial->private;
+ struct digi_serial *serial_priv = usb_get_serial_data(serial);
struct usb_serial_port *port;
@@ -1690,12 +1690,11 @@ dbg( "digi_startup: TOP" );
for( i=0; i<serial->type->num_ports+1; i++ ) {
/* allocate port private structure */
- priv = serial->port[i].private =
- (struct digi_port *)kmalloc( sizeof(struct digi_port),
+ priv = (struct digi_port *)kmalloc( sizeof(struct digi_port),
GFP_KERNEL );
if( priv == (struct digi_port *)0 ) {
while( --i >= 0 )
- kfree( serial->port[i].private );
+ kfree( usb_get_serial_port_data(&serial->port[i]) );
return( 1 ); /* error */
}
@@ -1720,15 +1719,15 @@ dbg( "digi_startup: TOP" );
/* initialize write wait queue for this port */
init_waitqueue_head( &serial->port[i].write_wait );
+ usb_set_serial_port_data(&serial->port[i], priv);
}
/* allocate serial private structure */
- serial_priv = serial->private =
- (struct digi_serial *)kmalloc( sizeof(struct digi_serial),
+ serial_priv = (struct digi_serial *)kmalloc( sizeof(struct digi_serial),
GFP_KERNEL );
if( serial_priv == (struct digi_serial *)0 ) {
for( i=0; i<serial->type->num_ports+1; i++ )
- kfree( serial->port[i].private );
+ kfree( usb_get_serial_port_data(&serial->port[i]) );
return( 1 ); /* error */
}
@@ -1737,6 +1736,7 @@ dbg( "digi_startup: TOP" );
serial_priv->ds_oob_port_num = serial->type->num_ports;
serial_priv->ds_oob_port = &serial->port[serial_priv->ds_oob_port_num];
serial_priv->ds_device_started = 0;
+ usb_set_serial_data(serial, serial_priv);
return( 0 );
@@ -1760,9 +1760,8 @@ dbg( "digi_shutdown: TOP, in_interrupt()=%ld", in_interrupt() );
/* free the private data structures for all ports */
/* number of regular ports + 1 for the out-of-band port */
for( i=0; i<serial->type->num_ports+1; i++ )
- kfree( serial->port[i].private );
- kfree( serial->private );
-
+ kfree( usb_get_serial_port_data(&serial->port[i]) );
+ kfree( usb_get_serial_data(serial) );
}
@@ -1771,20 +1770,21 @@ static void digi_read_bulk_callback( struct urb *urb, struct pt_regs *regs )
struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
struct digi_port *priv;
+ struct digi_serial *serial_priv;
int ret;
dbg( "digi_read_bulk_callback: TOP" );
/* port sanity check, do not resubmit if port is not valid */
- if( port == NULL || (priv=(struct digi_port *)(port->private)) == NULL ) {
+ if( port == NULL || (priv=usb_get_serial_port_data(port)) == NULL ) {
err("%s: port or port->private is NULL, status=%d", __FUNCTION__,
urb->status );
return;
}
if( port->serial == NULL
|| serial_paranoia_check( port->serial, __FUNCTION__ )
- || port->serial->private == NULL ) {
+ || (serial_priv=usb_get_serial_data(port->serial)) == NULL ) {
err("%s: serial is bad or serial->private is NULL, status=%d", __FUNCTION__, urb->status );
return;
}
@@ -1796,8 +1796,7 @@ dbg( "digi_read_bulk_callback: TOP" );
}
/* handle oob or inb callback, do not resubmit if error */
- if( priv->dp_port_num
- == ((struct digi_serial *)(port->serial->private))->ds_oob_port_num ) {
+ if( priv->dp_port_num == serial_priv->ds_oob_port_num ) {
if( digi_read_oob_callback( urb ) != 0 )
return;
} else {
@@ -1830,7 +1829,7 @@ static int digi_read_inb_callback( struct urb *urb )
struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
struct tty_struct *tty = port->tty;
- struct digi_port *priv = (struct digi_port *)(port->private);
+ struct digi_port *priv = usb_get_serial_port_data(port);
int opcode = ((unsigned char *)urb->transfer_buffer)[0];
int len = ((unsigned char *)urb->transfer_buffer)[1];
int status = ((unsigned char *)urb->transfer_buffer)[2];
@@ -1942,7 +1941,7 @@ static int digi_read_oob_callback( struct urb *urb )
struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
struct usb_serial *serial = port->serial;
- struct digi_port *priv = (struct digi_port *)(port->private);
+ struct digi_port *priv = usb_get_serial_port_data(port);
int opcode, line, status, val;
int i;
@@ -1967,7 +1966,7 @@ opcode, line, status, val );
port = &serial->port[line];
if( port_paranoia_check( port, __FUNCTION__ )
- || (priv=port->private) == NULL )
+ || (priv=usb_get_serial_port_data(port)) == NULL )
return( -1 );
if( opcode == DIGI_CMD_READ_INPUT_SIGNALS ) {
diff --git a/drivers/usb/serial/empeg.c b/drivers/usb/serial/empeg.c
index a5e3b7795d7d..984f1708ef78 100644
--- a/drivers/usb/serial/empeg.c
+++ b/drivers/usb/serial/empeg.c
@@ -181,7 +181,7 @@ static int empeg_open (struct usb_serial_port *port, struct file *filp)
result = usb_submit_urb(port->read_urb, GFP_KERNEL);
if (result)
- err("%s - failed submitting read urb, error %d", __FUNCTION__, result);
+ dev_err(port->dev, "%s - failed submitting read urb, error %d\n", __FUNCTION__, result);
return result;
}
@@ -205,7 +205,7 @@ static void empeg_close (struct usb_serial_port *port, struct file * filp)
usb_unlink_urb (port->read_urb);
}
/* Uncomment the following line if you want to see some statistics in your syslog */
- /* info ("Bytes In = %d Bytes Out = %d", bytes_in, bytes_out); */
+ /* dev_info (port->dev, "Bytes In = %d Bytes Out = %d\n", bytes_in, bytes_out); */
}
@@ -248,7 +248,7 @@ static int empeg_write (struct usb_serial_port *port, int from_user, const unsig
if (urb->transfer_buffer == NULL) {
urb->transfer_buffer = kmalloc (URB_TRANSFER_BUFFER_SIZE, GFP_ATOMIC);
if (urb->transfer_buffer == NULL) {
- err("%s no more kernel memory...", __FUNCTION__);
+ dev_err(port->dev, "%s no more kernel memory...\n", __FUNCTION__);
goto exit;
}
}
@@ -278,7 +278,7 @@ static int empeg_write (struct usb_serial_port *port, int from_user, const unsig
/* send it down the pipe */
status = usb_submit_urb(urb, GFP_ATOMIC);
if (status) {
- err("%s - usb_submit_urb(write bulk) failed with status = %d", __FUNCTION__, status);
+ dev_err(port->dev, "%s - usb_submit_urb(write bulk) failed with status = %d\n", __FUNCTION__, status);
bytes_sent = status;
break;
}
@@ -426,7 +426,7 @@ static void empeg_read_bulk_callback (struct urb *urb, struct pt_regs *regs)
result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
if (result)
- err("%s - failed resubmitting read urb, error %d", __FUNCTION__, result);
+ dev_err(urb->dev->dev, "%s - failed resubmitting read urb, error %d\n", __FUNCTION__, result);
return;
@@ -451,7 +451,7 @@ static void empeg_unthrottle (struct usb_serial_port *port)
result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
if (result)
- err("%s - failed submitting read urb, error %d", __FUNCTION__, result);
+ dev_err(port->dev, "%s - failed submitting read urb, error %d\n", __FUNCTION__, result);
return;
}
diff --git a/drivers/usb/serial/ezusb.c b/drivers/usb/serial/ezusb.c
index 35616b5e23a0..ad567d566953 100644
--- a/drivers/usb/serial/ezusb.c
+++ b/drivers/usb/serial/ezusb.c
@@ -41,7 +41,7 @@ int ezusb_writememory (struct usb_serial *serial, int address, unsigned char *da
transfer_buffer = kmalloc (length, GFP_KERNEL);
if (!transfer_buffer) {
- err("%s - kmalloc(%d) failed.", __FUNCTION__, length);
+ dev_err(serial->dev->dev, "%s - kmalloc(%d) failed.\n", __FUNCTION__, length);
return -ENOMEM;
}
memcpy (transfer_buffer, data, length);
@@ -56,7 +56,7 @@ int ezusb_set_reset (struct usb_serial *serial, unsigned char reset_bit)
dbg("%s - %d", __FUNCTION__, reset_bit);
response = ezusb_writememory (serial, CPUCS_REG, &reset_bit, 1, 0xa0);
if (response < 0) {
- err("%s- %d failed", __FUNCTION__, reset_bit);
+ dev_err(serial->dev->dev, "%s- %d failed\n", __FUNCTION__, reset_bit);
}
return response;
}
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index c696597fa4e2..0d24afa9864b 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -267,7 +267,7 @@ static int ftdi_sio_startup (struct usb_serial *serial)
struct ftdi_private *priv;
- priv = serial->port->private = kmalloc(sizeof(struct ftdi_private), GFP_KERNEL);
+ priv = kmalloc(sizeof(struct ftdi_private), GFP_KERNEL);
if (!priv){
err("%s- kmalloc(%Zd) failed.", __FUNCTION__, sizeof(struct ftdi_private));
return -ENOMEM;
@@ -275,7 +275,8 @@ static int ftdi_sio_startup (struct usb_serial *serial)
priv->ftdi_type = sio;
priv->write_offset = 1;
-
+ usb_set_serial_port_data(serial->port, priv);
+
return (0);
}
@@ -285,7 +286,7 @@ static int ftdi_8U232AM_startup (struct usb_serial *serial)
struct ftdi_private *priv;
- priv = serial->port->private = kmalloc(sizeof(struct ftdi_private), GFP_KERNEL);
+ priv = kmalloc(sizeof(struct ftdi_private), GFP_KERNEL);
if (!priv){
err("%s- kmalloc(%Zd) failed.", __FUNCTION__, sizeof(struct ftdi_private));
return -ENOMEM;
@@ -293,17 +294,21 @@ static int ftdi_8U232AM_startup (struct usb_serial *serial)
priv->ftdi_type = F8U232AM;
priv->write_offset = 0;
-
+ usb_set_serial_port_data(serial->port, priv);
+
return (0);
}
static void ftdi_sio_shutdown (struct usb_serial *serial)
{
+ void *priv;
+
dbg("%s", __FUNCTION__);
- if (serial->port[0].private){
- kfree(serial->port[0].private);
- serial->port[0].private = NULL;
+ priv = usb_get_serial_port_data(&serial->port[0]);
+ if (priv){
+ kfree(priv);
+ usb_set_serial_port_data(&serial->port[0], NULL);
}
}
@@ -405,7 +410,7 @@ static int ftdi_sio_write (struct usb_serial_port *port, int from_user,
const unsigned char *buf, int count)
{ /* ftdi_sio_write */
struct usb_serial *serial = port->serial;
- struct ftdi_private *priv = (struct ftdi_private *)port->private;
+ struct ftdi_private *priv = usb_get_serial_port_data(port);
unsigned char *first_byte = port->write_urb->transfer_buffer;
int data_offset ;
int result;
@@ -491,7 +496,7 @@ static void ftdi_sio_write_bulk_callback (struct urb *urb, struct pt_regs *regs)
static int ftdi_sio_write_room( struct usb_serial_port *port )
{
- struct ftdi_private *priv = (struct ftdi_private *)port->private;
+ struct ftdi_private *priv = usb_get_serial_port_data(port);
int room;
if ( port->write_urb->status == -EINPROGRESS) {
@@ -670,7 +675,7 @@ static __u16 translate_baudrate_to_ftdi(unsigned int cflag, enum ftdi_type ftdi_
static void ftdi_sio_break_ctl( struct usb_serial_port *port, int break_state )
{
struct usb_serial *serial = port->serial;
- struct ftdi_private *priv = (struct ftdi_private *)port->private;
+ struct ftdi_private *priv = usb_get_serial_port_data(port);
__u16 urb_value = 0;
char buf[1];
@@ -709,7 +714,7 @@ static void ftdi_sio_set_termios (struct usb_serial_port *port, struct termios *
{ /* ftdi_sio_set_termios */
struct usb_serial *serial = port->serial;
unsigned int cflag = port->tty->termios->c_cflag;
- struct ftdi_private *priv = (struct ftdi_private *)port->private;
+ struct ftdi_private *priv = usb_get_serial_port_data(port);
__u16 urb_value; /* will hold the new flags */
char buf[1]; /* Perhaps I should dynamically alloc this? */
@@ -819,7 +824,7 @@ static void ftdi_sio_set_termios (struct usb_serial_port *port, struct termios *
static int ftdi_sio_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg)
{
struct usb_serial *serial = port->serial;
- struct ftdi_private *priv = (struct ftdi_private *)port->private;
+ struct ftdi_private *priv = usb_get_serial_port_data(port);
__u16 urb_value=0; /* Will hold the new flags */
char buf[2];
int ret, mask;
diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c
index d4dde44d06b5..ae5bdb865bdc 100644
--- a/drivers/usb/serial/generic.c
+++ b/drivers/usb/serial/generic.c
@@ -106,7 +106,7 @@ int usb_serial_generic_open (struct usb_serial_port *port, struct file *filp)
port);
result = usb_submit_urb(port->read_urb, GFP_KERNEL);
if (result)
- err("%s - failed resubmitting read urb, error %d", __FUNCTION__, result);
+ dev_err(port->dev, "%s - failed resubmitting read urb, error %d\n", __FUNCTION__, result);
}
return result;
@@ -176,7 +176,7 @@ int usb_serial_generic_write (struct usb_serial_port *port, int from_user, const
/* send the data out the bulk port */
result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
if (result)
- err("%s - failed submitting write urb, error %d", __FUNCTION__, result);
+ dev_err(port->dev, "%s - failed submitting write urb, error %d\n", __FUNCTION__, result);
else
result = count;
@@ -266,7 +266,7 @@ void usb_serial_generic_read_bulk_callback (struct urb *urb, struct pt_regs *reg
usb_serial_generic_read_bulk_callback), port);
result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
if (result)
- err("%s - failed resubmitting read urb, error %d", __FUNCTION__, result);
+ dev_err(port->dev, "%s - failed resubmitting read urb, error %d\n", __FUNCTION__, result);
}
void usb_serial_generic_write_bulk_callback (struct urb *urb, struct pt_regs *regs)
diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c
index e0963b2ecf13..6e0efdfd5bb2 100644
--- a/drivers/usb/serial/io_edgeport.c
+++ b/drivers/usb/serial/io_edgeport.c
@@ -572,7 +572,7 @@ static void update_edgeport_E2PROM (struct edgeport_serial *edge_serial)
record = (struct edge_firmware_image_record *)firmware;
response = rom_write (edge_serial->serial, record->ExtAddr, record->Addr, record->Len, &record->Data[0]);
if (response < 0) {
- err("sram_write failed (%x, %x, %d)", record->ExtAddr, record->Addr, record->Len);
+ dev_err(edge_serial->serial->dev->dev, "sram_write failed (%x, %x, %d)\n", record->ExtAddr, record->Addr, record->Len);
break;
}
firmware += sizeof (struct edge_firmware_image_record) + record->Len;
@@ -818,7 +818,7 @@ static void edge_interrupt_callback (struct urb *urb, struct pt_regs *regs)
if (txCredits) {
port = &edge_serial->serial->port[portNumber];
if (port_paranoia_check (port, __FUNCTION__) == 0) {
- edge_port = (struct edgeport_port *)port->private;
+ edge_port = usb_get_serial_port_data(port);
if (edge_port->open) {
edge_port->txCredits += txCredits;
dbg("%s - txcredits for port%d = %d", __FUNCTION__, portNumber, edge_port->txCredits);
@@ -840,7 +840,7 @@ static void edge_interrupt_callback (struct urb *urb, struct pt_regs *regs)
exit:
result = usb_submit_urb (urb, GFP_ATOMIC);
if (result) {
- err("%s - Error %d submitting control urb", __FUNCTION__, result);
+ dev_err(urb->dev->dev, "%s - Error %d submitting control urb\n", __FUNCTION__, result);
}
}
@@ -889,7 +889,7 @@ static void edge_bulk_in_callback (struct urb *urb, struct pt_regs *regs)
edge_serial->read_urb->dev = edge_serial->serial->dev;
status = usb_submit_urb(edge_serial->read_urb, GFP_ATOMIC);
if (status) {
- err("%s - usb_submit_urb(read bulk) failed, status = %d", __FUNCTION__, status);
+ dev_err(urb->dev->dev, "%s - usb_submit_urb(read bulk) failed, status = %d\n", __FUNCTION__, status);
}
}
}
@@ -932,7 +932,7 @@ static void edge_bulk_out_data_callback (struct urb *urb, struct pt_regs *regs)
edge_port->write_in_progress = FALSE;
// Check if more data needs to be sent
- send_more_port_data((struct edgeport_serial *)(edge_port->port->serial->private), edge_port);
+ send_more_port_data((struct edgeport_serial *)(usb_get_serial_data(edge_port->port->serial)), edge_port);
}
@@ -996,7 +996,7 @@ static void edge_bulk_out_cmd_callback (struct urb *urb, struct pt_regs *regs)
*****************************************************************************/
static int edge_open (struct usb_serial_port *port, struct file * filp)
{
- struct edgeport_port *edge_port = (struct edgeport_port *)port->private;
+ struct edgeport_port *edge_port = usb_get_serial_port_data(port);
struct usb_serial *serial;
struct edgeport_serial *edge_serial;
int response;
@@ -1019,7 +1019,7 @@ static int edge_open (struct usb_serial_port *port, struct file * filp)
/* see if we've set up our endpoint info yet (can't set it up in edge_startup
as the structures were not set up at that time.) */
serial = port->serial;
- edge_serial = (struct edgeport_serial *)serial->private;
+ edge_serial = usb_get_serial_data(serial);
if (edge_serial == NULL) {
return -ENODEV;
}
@@ -1057,7 +1057,7 @@ static int edge_open (struct usb_serial_port *port, struct file * filp)
* this interrupt will continue as long as the edgeport is connected */
response = usb_submit_urb (edge_serial->interrupt_read_urb, GFP_KERNEL);
if (response) {
- err("%s - Error %d submitting control urb", __FUNCTION__, response);
+ dev_err(port->dev, "%s - Error %d submitting control urb\n", __FUNCTION__, response);
}
}
@@ -1081,7 +1081,7 @@ static int edge_open (struct usb_serial_port *port, struct file * filp)
response = send_iosp_ext_cmd (edge_port, IOSP_CMD_OPEN_PORT, 0);
if (response < 0) {
- err("%s - error sending open port command", __FUNCTION__);
+ dev_err(port->dev, "%s - error sending open port command\n", __FUNCTION__);
edge_port->openPending = FALSE;
return -ENODEV;
}
@@ -1247,8 +1247,8 @@ static void edge_close (struct usb_serial_port *port, struct file * filp)
if (!serial)
return;
- edge_serial = (struct edgeport_serial *)serial->private;
- edge_port = (struct edgeport_port *)port->private;
+ edge_serial = usb_get_serial_data(serial);
+ edge_port = usb_get_serial_port_data(port);
if ((edge_serial == NULL) || (edge_port == NULL))
return;
@@ -1307,7 +1307,7 @@ static void edge_close (struct usb_serial_port *port, struct file * filp)
*****************************************************************************/
static int edge_write (struct usb_serial_port *port, int from_user, const unsigned char *data, int count)
{
- struct edgeport_port *edge_port = (struct edgeport_port *)port->private;
+ struct edgeport_port *edge_port = usb_get_serial_port_data(port);
struct TxFifo *fifo;
int copySize;
int bytesleft;
@@ -1381,7 +1381,7 @@ static int edge_write (struct usb_serial_port *port, int from_user, const unsign
usb_serial_debug_data (__FILE__, __FUNCTION__, copySize, data);
}
- send_more_port_data((struct edgeport_serial *)port->serial->private, edge_port);
+ send_more_port_data((struct edgeport_serial *)usb_get_serial_data(port->serial), edge_port);
dbg("%s wrote %d byte(s) TxCredits %d, Fifo %d", __FUNCTION__, copySize, edge_port->txCredits, fifo->count);
@@ -1450,7 +1450,7 @@ static void send_more_port_data(struct edgeport_serial *edge_serial, struct edge
count = fifo->count;
buffer = kmalloc (count+2, GFP_ATOMIC);
if (buffer == NULL) {
- err("%s - no more kernel memory...", __FUNCTION__);
+ dev_err(edge_serial->serial->dev->dev, "%s - no more kernel memory...\n", __FUNCTION__);
edge_port->write_in_progress = FALSE;
return;
}
@@ -1508,7 +1508,7 @@ static void send_more_port_data(struct edgeport_serial *edge_serial, struct edge
*****************************************************************************/
static int edge_write_room (struct usb_serial_port *port)
{
- struct edgeport_port *edge_port = (struct edgeport_port *)(port->private);
+ struct edgeport_port *edge_port = usb_get_serial_port_data(port);
int room;
dbg("%s", __FUNCTION__);
@@ -1544,7 +1544,7 @@ static int edge_write_room (struct usb_serial_port *port)
*****************************************************************************/
static int edge_chars_in_buffer (struct usb_serial_port *port)
{
- struct edgeport_port *edge_port = (struct edgeport_port *)(port->private);
+ struct edgeport_port *edge_port = usb_get_serial_port_data(port);
int num_chars;
dbg("%s", __FUNCTION__);
@@ -1575,7 +1575,7 @@ static int edge_chars_in_buffer (struct usb_serial_port *port)
*****************************************************************************/
static void edge_throttle (struct usb_serial_port *port)
{
- struct edgeport_port *edge_port = (struct edgeport_port *)(port->private);
+ struct edgeport_port *edge_port = usb_get_serial_port_data(port);
struct tty_struct *tty;
int status;
@@ -1624,7 +1624,7 @@ static void edge_throttle (struct usb_serial_port *port)
*****************************************************************************/
static void edge_unthrottle (struct usb_serial_port *port)
{
- struct edgeport_port *edge_port = (struct edgeport_port *)(port->private);
+ struct edgeport_port *edge_port = usb_get_serial_port_data(port);
struct tty_struct *tty;
int status;
@@ -1672,7 +1672,7 @@ static void edge_unthrottle (struct usb_serial_port *port)
*****************************************************************************/
static void edge_set_termios (struct usb_serial_port *port, struct termios *old_termios)
{
- struct edgeport_port *edge_port = (struct edgeport_port *)(port->private);
+ struct edgeport_port *edge_port = usb_get_serial_port_data(port);
struct tty_struct *tty = port->tty;
unsigned int cflag;
@@ -1862,7 +1862,7 @@ static int get_serial_info(struct edgeport_port *edge_port, struct serial_struct
*****************************************************************************/
static int edge_ioctl (struct usb_serial_port *port, struct file *file, unsigned int cmd, unsigned long arg)
{
- struct edgeport_port *edge_port = (struct edgeport_port *)(port->private);
+ struct edgeport_port *edge_port = usb_get_serial_port_data(port);
struct async_icount cnow;
struct async_icount cprev;
struct serial_icounter_struct icount;
@@ -1953,7 +1953,7 @@ static int edge_ioctl (struct usb_serial_port *port, struct file *file, unsigned
*****************************************************************************/
static void edge_break (struct usb_serial_port *port, int break_state)
{
- struct edgeport_port *edge_port = (struct edgeport_port *)(port->private);
+ struct edgeport_port *edge_port = usb_get_serial_port_data(port);
int status;
/* flush and chase */
@@ -2086,7 +2086,7 @@ static int process_rcvd_data (struct edgeport_serial *edge_serial, unsigned char
if (rxLen) {
port = &edge_serial->serial->port[edge_serial->rxPort];
if (port_paranoia_check (port, __FUNCTION__) == 0) {
- edge_port = (struct edgeport_port *)port->private;
+ edge_port = usb_get_serial_port_data(port);
if (edge_port->open) {
tty = edge_port->port->tty;
if (tty) {
@@ -2141,9 +2141,9 @@ static void process_rcvd_status (struct edgeport_serial *edge_serial, __u8 byte2
if (port_paranoia_check (port, __FUNCTION__)) {
return;
}
- edge_port = (struct edgeport_port *)port->private;
+ edge_port = usb_get_serial_port_data(port);
if (edge_port == NULL) {
- err("%s - edge_port == NULL for port %d", __FUNCTION__, edge_serial->rxPort);
+ dev_err(edge_serial->serial->dev->dev, "%s - edge_port == NULL for port %d\n", __FUNCTION__, edge_serial->rxPort);
return;
}
@@ -2330,7 +2330,7 @@ static int sram_write (struct usb_serial *serial, __u16 extAddr, __u16 addr, __u
transfer_buffer = kmalloc (64, GFP_KERNEL);
if (!transfer_buffer) {
- err("%s - kmalloc(%d) failed.\n", __FUNCTION__, 64);
+ dev_err(serial->dev->dev, "%s - kmalloc(%d) failed.\n", __FUNCTION__, 64);
return -ENOMEM;
}
@@ -2375,7 +2375,7 @@ static int rom_write (struct usb_serial *serial, __u16 extAddr, __u16 addr, __u1
transfer_buffer = kmalloc (64, GFP_KERNEL);
if (!transfer_buffer) {
- err("%s - kmalloc(%d) failed.\n", __FUNCTION__, 64);
+ dev_err(serial->dev->dev, "%s - kmalloc(%d) failed.\n", __FUNCTION__, 64);
return -ENOMEM;
}
@@ -2420,7 +2420,7 @@ static int rom_read (struct usb_serial *serial, __u16 extAddr, __u16 addr, __u16
transfer_buffer = kmalloc (64, GFP_KERNEL);
if (!transfer_buffer) {
- err("%s - kmalloc(%d) failed.\n", __FUNCTION__, 64);
+ dev_err(serial->dev->dev, "%s - kmalloc(%d) failed.\n", __FUNCTION__, 64);
return -ENOMEM;
}
@@ -2463,7 +2463,7 @@ static int send_iosp_ext_cmd (struct edgeport_port *edge_port, __u8 command, __u
buffer = kmalloc (10, GFP_ATOMIC);
if (!buffer) {
- err("%s - kmalloc(%d) failed.\n", __FUNCTION__, 10);
+ dev_err(edge_port->port->dev, "%s - kmalloc(%d) failed.\n", __FUNCTION__, 10);
return -ENOMEM;
}
@@ -2489,7 +2489,7 @@ static int send_iosp_ext_cmd (struct edgeport_port *edge_port, __u8 command, __u
*****************************************************************************/
static int write_cmd_usb (struct edgeport_port *edge_port, unsigned char *buffer, int length)
{
- struct edgeport_serial *edge_serial = (struct edgeport_serial *)edge_port->port->serial->private;
+ struct edgeport_serial *edge_serial = usb_get_serial_data(edge_port->port->serial);
int status = 0;
struct urb *urb;
int timeout;
@@ -2554,14 +2554,14 @@ static int send_cmd_write_baud_rate (struct edgeport_port *edge_port, int baudRa
status = calc_baud_rate_divisor (baudRate, &divisor);
if (status) {
- err("%s - bad baud rate", __FUNCTION__);
+ dev_err(edge_port->port->dev, "%s - bad baud rate\n", __FUNCTION__);
return status;
}
// Alloc memory for the string of commands.
cmdBuffer = kmalloc (0x100, GFP_ATOMIC);
if (!cmdBuffer) {
- err("%s - kmalloc(%d) failed.\n", __FUNCTION__, 0x100);
+ dev_err(edge_port->port->dev, "%s - kmalloc(%d) failed.\n", __FUNCTION__, 0x100);
return -ENOMEM;
}
currCmd = cmdBuffer;
@@ -2838,7 +2838,7 @@ static void get_manufacturing_desc (struct edgeport_serial *edge_serial)
(__u8 *)(&edge_serial->manuf_descriptor));
if (response < 1) {
- err("error in getting manufacturer descriptor");
+ dev_err(edge_serial->serial->dev->dev, "error in getting manufacturer descriptor\n");
} else {
char string[30];
dbg("**Manufacturer Descriptor");
@@ -2877,7 +2877,7 @@ static void get_boot_desc (struct edgeport_serial *edge_serial)
(__u8 *)(&edge_serial->boot_descriptor));
if (response < 1) {
- err("error in getting boot descriptor");
+ dev_err(edge_serial->serial->dev->dev, "error in getting boot descriptor\n");
} else {
dbg("**Boot Descriptor:");
dbg(" BootCodeLength: %d", edge_serial->boot_descriptor.BootCodeLength);
@@ -2938,7 +2938,7 @@ static void load_application_firmware (struct edgeport_serial *edge_serial)
record = (struct edge_firmware_image_record *)firmware;
response = sram_write (edge_serial->serial, record->ExtAddr, record->Addr, record->Len, &record->Data[0]);
if (response < 0) {
- err("sram_write failed (%x, %x, %d)", record->ExtAddr, record->Addr, record->Len);
+ dev_err(edge_serial->serial->dev->dev, "sram_write failed (%x, %x, %d)\n", record->ExtAddr, record->Addr, record->Len);
break;
}
firmware += sizeof (struct edge_firmware_image_record) + record->Len;
@@ -2974,12 +2974,12 @@ static int edge_startup (struct usb_serial *serial)
/* create our private serial structure */
edge_serial = kmalloc (sizeof(struct edgeport_serial), GFP_KERNEL);
if (edge_serial == NULL) {
- err("%s - Out of memory", __FUNCTION__);
+ dev_err(serial->dev->dev, "%s - Out of memory", __FUNCTION__);
return -ENOMEM;
}
memset (edge_serial, 0, sizeof(struct edgeport_serial));
edge_serial->serial = serial;
- serial->private = edge_serial;
+ usb_set_serial_data(serial, edge_serial);
/* get the name for the device from the device */
if ( (i = get_string(dev, dev->descriptor.iManufacturer, &edge_serial->name[0])) != 0) {
@@ -2988,7 +2988,7 @@ static int edge_startup (struct usb_serial *serial)
get_string(dev, dev->descriptor.iProduct, &edge_serial->name[i]);
- info("%s detected", edge_serial->name);
+ dev_info(serial->dev->dev, "%s detected\n", edge_serial->name);
/* get the manufacturing descriptor for this device */
get_manufacturing_desc (edge_serial);
@@ -3030,12 +3030,14 @@ static int edge_startup (struct usb_serial *serial)
for (i = 0; i < serial->num_ports; ++i) {
edge_port = kmalloc (sizeof(struct edgeport_port), GFP_KERNEL);
if (edge_port == NULL) {
- err("%s - Out of memory", __FUNCTION__);
+ dev_err(serial->dev->dev, "%s - Out of memory", __FUNCTION__);
+ usb_set_serial_data(serial, NULL);
+ kfree(edge_serial);
return -ENOMEM;
}
memset (edge_port, 0, sizeof(struct edgeport_port));
edge_port->port = &serial->port[i];
- serial->port[i].private = edge_port;
+ usb_set_serial_port_data(&serial->port[i], edge_port);
}
return 0;
@@ -3055,11 +3057,11 @@ static void edge_shutdown (struct usb_serial *serial)
/* stop reads and writes on all ports */
for (i=0; i < serial->num_ports; ++i) {
- kfree (serial->port[i].private);
- serial->port[i].private = NULL;
+ kfree (usb_get_serial_port_data(&serial->port[i]));
+ usb_set_serial_port_data(&serial->port[i], NULL);
}
- kfree (serial->private);
- serial->private = NULL;
+ kfree (usb_get_serial_data(serial));
+ usb_set_serial_data(serial, NULL);
}
diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c
index ba9e939667f1..c2b110225712 100644
--- a/drivers/usb/serial/io_ti.c
+++ b/drivers/usb/serial/io_ti.c
@@ -473,7 +473,7 @@ static int TIIsTxActive (struct edgeport_port *port)
oedb = kmalloc (sizeof (* oedb), GFP_KERNEL);
if (!oedb) {
- err ("%s - out of memory", __FUNCTION__);
+ dev_err (port->port->dev, "%s - out of memory\n", __FUNCTION__);
return -ENOMEM;
}
@@ -592,7 +592,7 @@ static int TIChooseConfiguration (struct usb_device *dev)
dbg ("%s - MAX Power = %d", __FUNCTION__, dev->config->desc.bMaxPower*2);
if (dev->config->desc.bNumInterfaces != 1) {
- err ("%s - bNumInterfaces is not 1, ERROR!", __FUNCTION__);
+ dev_err (dev->dev, "%s - bNumInterfaces is not 1, ERROR!\n", __FUNCTION__);
return -ENODEV;
}
@@ -684,6 +684,7 @@ static int ValidChecksum(struct ti_i2c_desc *rom_desc, __u8 *buffer)
/* Make sure that the I2C image is good */
static int TiValidateI2cImage (struct edgeport_serial *serial)
{
+ struct device *dev = &serial->serial->dev->dev;
int status = 0;
struct ti_i2c_desc *rom_desc;
int start_address = 2;
@@ -691,12 +692,12 @@ static int TiValidateI2cImage (struct edgeport_serial *serial)
rom_desc = kmalloc (sizeof (*rom_desc), GFP_KERNEL);
if (!rom_desc) {
- err ("%s - out of memory", __FUNCTION__);
+ dev_err (*dev, "%s - out of memory\n", __FUNCTION__);
return -ENOMEM;
}
buffer = kmalloc (TI_MAX_I2C_SIZE, GFP_KERNEL);
if (!buffer) {
- err ("%s - out of memory when allocating buffer", __FUNCTION__);
+ dev_err (*dev, "%s - out of memory when allocating buffer\n", __FUNCTION__);
kfree (rom_desc);
return -ENOMEM;
}
@@ -707,7 +708,7 @@ static int TiValidateI2cImage (struct edgeport_serial *serial)
goto ExitTiValidateI2cImage;
if (*buffer != 0x52) {
- err ("%s - invalid buffer signature", __FUNCTION__);
+ dev_err (*dev, "%s - invalid buffer signature\n", __FUNCTION__);
status = -ENODEV;
goto ExitTiValidateI2cImage;
}
@@ -765,7 +766,7 @@ static int TIReadManufDescriptor (struct edgeport_serial *serial, __u8 *buffer)
rom_desc = kmalloc (sizeof (*rom_desc), GFP_KERNEL);
if (!rom_desc) {
- err ("%s - out of memory", __FUNCTION__);
+ dev_err (serial->serial->dev->dev, "%s - out of memory\n", __FUNCTION__);
return -ENOMEM;
}
start_address = TIGetDescriptorAddress (serial, I2C_DESC_TYPE_ION, rom_desc);
@@ -800,7 +801,7 @@ exit:
}
/* Build firmware header used for firmware update */
-static int BuildI2CFirmwareHeader (__u8 *header)
+static int BuildI2CFirmwareHeader (__u8 *header, struct device *dev)
{
__u8 *buffer;
int buffer_size;
@@ -822,7 +823,7 @@ static int BuildI2CFirmwareHeader (__u8 *header)
buffer = kmalloc (buffer_size, GFP_KERNEL);
if (!buffer) {
- err ("%s - out of memory", __FUNCTION__);
+ dev_err (*dev, "%s - out of memory\n", __FUNCTION__);
return -ENOMEM;
}
@@ -960,6 +961,7 @@ static int TIConfigureBootDevice (struct usb_device *dev)
*/
static int TIDownloadFirmware (struct edgeport_serial *serial)
{
+ struct device *dev = &serial->serial->dev->dev;
int status = 0;
int start_address;
struct edge_ti_manuf_descriptor *ti_manuf_desc;
@@ -982,7 +984,7 @@ static int TIDownloadFirmware (struct edgeport_serial *serial)
interface = &serial->serial->dev->config->interface->altsetting->desc;
if (!interface) {
- err ("%s - no interface set, error!", __FUNCTION__);
+ dev_err (serial->serial->dev->dev, "%s - no interface set, error!", __FUNCTION__);
return -ENODEV;
}
@@ -1019,7 +1021,7 @@ static int TIDownloadFirmware (struct edgeport_serial *serial)
*/
ti_manuf_desc = kmalloc (sizeof (*ti_manuf_desc), GFP_KERNEL);
if (!ti_manuf_desc) {
- err ("%s - out of memory.", __FUNCTION__);
+ dev_err (*dev, "%s - out of memory.\n", __FUNCTION__);
return -ENOMEM;
}
status = TIReadManufDescriptor (serial, (__u8 *)ti_manuf_desc);
@@ -1038,7 +1040,7 @@ static int TIDownloadFirmware (struct edgeport_serial *serial)
rom_desc = kmalloc (sizeof (*rom_desc), GFP_KERNEL);
if (!rom_desc) {
- err ("%s - out of memory.", __FUNCTION__);
+ dev_err (*dev, "%s - out of memory.\n", __FUNCTION__);
kfree (ti_manuf_desc);
return -ENOMEM;
}
@@ -1052,7 +1054,7 @@ static int TIDownloadFirmware (struct edgeport_serial *serial)
firmware_version = kmalloc (sizeof (*firmware_version), GFP_KERNEL);
if (!firmware_version) {
- err ("%s - out of memory.", __FUNCTION__);
+ dev_err (*dev, "%s - out of memory.\n", __FUNCTION__);
kfree (rom_desc);
kfree (ti_manuf_desc);
return -ENOMEM;
@@ -1129,7 +1131,7 @@ static int TIDownloadFirmware (struct edgeport_serial *serial)
}
if (record != I2C_DESC_TYPE_FIRMWARE_BLANK) {
- err ("%s - error resetting device", __FUNCTION__);
+ dev_err (*dev, "%s - error resetting device\n", __FUNCTION__);
kfree (firmware_version);
kfree (rom_desc);
kfree (ti_manuf_desc);
@@ -1160,7 +1162,7 @@ static int TIDownloadFirmware (struct edgeport_serial *serial)
header = kmalloc (HEADER_SIZE, GFP_KERNEL);
if (!header) {
- err ("%s - out of memory.", __FUNCTION__);
+ dev_err (*dev, "%s - out of memory.\n", __FUNCTION__);
kfree (rom_desc);
kfree (ti_manuf_desc);
return -ENOMEM;
@@ -1168,7 +1170,7 @@ static int TIDownloadFirmware (struct edgeport_serial *serial)
vheader = kmalloc (HEADER_SIZE, GFP_KERNEL);
if (!vheader) {
- err ("%s - out of memory.", __FUNCTION__);
+ dev_err (*dev, "%s - out of memory.\n", __FUNCTION__);
kfree (header);
kfree (rom_desc);
kfree (ti_manuf_desc);
@@ -1183,7 +1185,7 @@ static int TIDownloadFirmware (struct edgeport_serial *serial)
// And finally when the device comes back up in download mode the driver will cause
// the new firmware to be copied from the UMP Ram to I2C and the firmware will update
// the record type from 0xf2 to 0x02.
- status = BuildI2CFirmwareHeader(header);
+ status = BuildI2CFirmwareHeader(header, dev);
if (status) {
kfree (vheader);
kfree (header);
@@ -1300,7 +1302,7 @@ static int TIDownloadFirmware (struct edgeport_serial *serial)
*/
ti_manuf_desc = kmalloc (sizeof (*ti_manuf_desc), GFP_KERNEL);
if (!ti_manuf_desc) {
- err ("%s - out of memory.", __FUNCTION__);
+ dev_err (*dev, "%s - out of memory.\n", __FUNCTION__);
return -ENOMEM;
}
status = TIReadManufDescriptor (serial, (__u8 *)ti_manuf_desc);
@@ -1335,7 +1337,7 @@ static int TIDownloadFirmware (struct edgeport_serial *serial)
buffer_size = (((1024 * 16) - 512) + sizeof(struct ti_i2c_image_header));
buffer = kmalloc (buffer_size, GFP_KERNEL);
if (!buffer) {
- err ("%s - out of memory", __FUNCTION__);
+ dev_err (*dev, "%s - out of memory\n", __FUNCTION__);
return -ENOMEM;
}
@@ -1616,7 +1618,7 @@ static void handle_new_lsr (struct edgeport_port *edge_port, int lsr_data, __u8
static void edge_interrupt_callback (struct urb *urb, struct pt_regs *regs)
{
- struct edgeport_serial *edge_serial = (struct edgeport_serial *)urb->context;
+ struct edgeport_serial *edge_serial = (struct edgeport_serial *)urb->context;
struct usb_serial_port *port;
struct edgeport_port *edge_port;
unsigned char *data = urb->transfer_buffer;
@@ -1670,7 +1672,7 @@ static void edge_interrupt_callback (struct urb *urb, struct pt_regs *regs)
__FUNCTION__);
return;
}
- edge_port = port->private;
+ edge_port = usb_get_serial_port_data(port);
if (!edge_port) {
dbg ("%s - edge_port not found", __FUNCTION__);
return;
@@ -1700,8 +1702,8 @@ static void edge_interrupt_callback (struct urb *urb, struct pt_regs *regs)
break;
default:
- err ("%s - Unknown Interrupt code from UMP %x\n",
- __FUNCTION__, data[1]);
+ dev_err (urb->dev->dev, "%s - Unknown Interrupt code from UMP %x\n",
+ __FUNCTION__, data[1]);
break;
}
@@ -1709,8 +1711,8 @@ static void edge_interrupt_callback (struct urb *urb, struct pt_regs *regs)
exit:
status = usb_submit_urb (urb, GFP_ATOMIC);
if (status)
- err ("%s - usb_submit_urb failed with result %d",
- __FUNCTION__, status);
+ dev_err (urb->dev->dev, "%s - usb_submit_urb failed with result %d\n",
+ __FUNCTION__, status);
}
static void edge_bulk_in_callback (struct urb *urb, struct pt_regs *regs)
@@ -1777,8 +1779,8 @@ exit:
/* continue always trying to read */
status = usb_submit_urb (urb, GFP_ATOMIC);
if (status)
- err ("%s - usb_submit_urb failed with result %d",
- __FUNCTION__, status);
+ dev_err (urb->dev->dev, "%s - usb_submit_urb failed with result %d\n",
+ __FUNCTION__, status);
}
static void edge_bulk_out_callback (struct urb *urb, struct pt_regs *regs)
@@ -1819,7 +1821,7 @@ static void edge_bulk_out_callback (struct urb *urb, struct pt_regs *regs)
static int edge_open (struct usb_serial_port *port, struct file * filp)
{
- struct edgeport_port *edge_port = (struct edgeport_port *)port->private;
+ struct edgeport_port *edge_port = usb_get_serial_port_data(port);
struct edgeport_serial *edge_serial;
struct usb_device *dev;
struct urb *urb;
@@ -1853,7 +1855,7 @@ static int edge_open (struct usb_serial_port *port, struct file * filp)
edge_port->dma_address = UMPD_OEDB2_ADDRESS;
break;
default:
- err ("Unknown port number!!!");
+ dev_err (port->dev, "Unknown port number!!!\n");
return -ENODEV;
}
@@ -1929,7 +1931,7 @@ static int edge_open (struct usb_serial_port *port, struct file * filp)
/* we are the first port to be opened, let's post the interrupt urb */
urb = edge_serial->serial->port[0].interrupt_in_urb;
if (!urb) {
- err ("%s - no interrupt urb present, exiting", __FUNCTION__);
+ dev_err (port->dev, "%s - no interrupt urb present, exiting\n", __FUNCTION__);
return -EINVAL;
}
urb->complete = edge_interrupt_callback;
@@ -1937,7 +1939,7 @@ static int edge_open (struct usb_serial_port *port, struct file * filp)
urb->dev = dev;
status = usb_submit_urb (urb, GFP_KERNEL);
if (status) {
- err ("%s - usb_submit_urb failed with value %d", __FUNCTION__, status);
+ dev_err (port->dev, "%s - usb_submit_urb failed with value %d\n", __FUNCTION__, status);
return status;
}
}
@@ -1952,7 +1954,7 @@ static int edge_open (struct usb_serial_port *port, struct file * filp)
/* start up our bulk read urb */
urb = port->read_urb;
if (!urb) {
- err ("%s - no read urb present, exiting", __FUNCTION__);
+ dev_err (port->dev, "%s - no read urb present, exiting\n", __FUNCTION__);
return -EINVAL;
}
urb->complete = edge_bulk_in_callback;
@@ -1960,7 +1962,7 @@ static int edge_open (struct usb_serial_port *port, struct file * filp)
urb->dev = dev;
status = usb_submit_urb (urb, GFP_KERNEL);
if (status) {
- err ("%s - read bulk usb_submit_urb failed with value %d", __FUNCTION__, status);
+ dev_err (port->dev, "%s - read bulk usb_submit_urb failed with value %d\n", __FUNCTION__, status);
return status;
}
@@ -1988,8 +1990,8 @@ static void edge_close (struct usb_serial_port *port, struct file * filp)
if (!serial)
return;
- edge_serial = (struct edgeport_serial *)serial->private;
- edge_port = (struct edgeport_port *)port->private;
+ edge_serial = usb_get_serial_data(serial);
+ edge_port = usb_get_serial_port_data(port);
if ((edge_serial == NULL) || (edge_port == NULL))
return;
@@ -2028,7 +2030,7 @@ static void edge_close (struct usb_serial_port *port, struct file * filp)
static int edge_write (struct usb_serial_port *port, int from_user, const unsigned char *data, int count)
{
struct usb_serial *serial = port->serial;
- struct edgeport_port *edge_port = port->private;
+ struct edgeport_port *edge_port = usb_get_serial_port_data(port);
int result;
dbg("%s - port %d", __FUNCTION__, port->number);
@@ -2070,7 +2072,7 @@ static int edge_write (struct usb_serial_port *port, int from_user, const unsign
/* send the data out the bulk port */
result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
if (result)
- err("%s - failed submitting write urb, error %d", __FUNCTION__, result);
+ dev_err(port->dev, "%s - failed submitting write urb, error %d\n", __FUNCTION__, result);
else
result = count;
@@ -2082,7 +2084,7 @@ static int edge_write (struct usb_serial_port *port, int from_user, const unsign
static int edge_write_room (struct usb_serial_port *port)
{
- struct edgeport_port *edge_port = (struct edgeport_port *)(port->private);
+ struct edgeport_port *edge_port = usb_get_serial_port_data(port);
int room = 0;
dbg("%s", __FUNCTION__);
@@ -2103,7 +2105,7 @@ static int edge_write_room (struct usb_serial_port *port)
static int edge_chars_in_buffer (struct usb_serial_port *port)
{
- struct edgeport_port *edge_port = (struct edgeport_port *)(port->private);
+ struct edgeport_port *edge_port = usb_get_serial_port_data(port);
int chars = 0;
dbg("%s", __FUNCTION__);
@@ -2124,7 +2126,7 @@ static int edge_chars_in_buffer (struct usb_serial_port *port)
static void edge_throttle (struct usb_serial_port *port)
{
- struct edgeport_port *edge_port = (struct edgeport_port *)(port->private);
+ struct edgeport_port *edge_port = usb_get_serial_port_data(port);
struct tty_struct *tty;
int status;
@@ -2157,7 +2159,7 @@ static void edge_throttle (struct usb_serial_port *port)
static void edge_unthrottle (struct usb_serial_port *port)
{
- struct edgeport_port *edge_port = (struct edgeport_port *)(port->private);
+ struct edgeport_port *edge_port = usb_get_serial_port_data(port);
struct tty_struct *tty;
int status;
@@ -2189,7 +2191,7 @@ static void edge_unthrottle (struct usb_serial_port *port)
port->read_urb->dev = port->serial->dev;
status = usb_submit_urb (port->read_urb, GFP_ATOMIC);
if (status) {
- err ("%s - usb_submit_urb failed with value %d", __FUNCTION__, status);
+ dev_err (port->dev, "%s - usb_submit_urb failed with value %d\n", __FUNCTION__, status);
}
}
@@ -2215,7 +2217,7 @@ static void change_port_settings (struct edgeport_port *edge_port, struct termio
config = kmalloc (sizeof (*config), GFP_KERNEL);
if (!config) {
- err ("%s - out of memory", __FUNCTION__);
+ dev_err (edge_port->port->dev, "%s - out of memory\n", __FUNCTION__);
return;
}
@@ -2348,7 +2350,7 @@ static void change_port_settings (struct edgeport_port *edge_port, struct termio
static void edge_set_termios (struct usb_serial_port *port, struct termios *old_termios)
{
- struct edgeport_port *edge_port = (struct edgeport_port *)(port->private);
+ struct edgeport_port *edge_port = usb_get_serial_port_data(port);
struct tty_struct *tty = port->tty;
unsigned int cflag;
@@ -2482,7 +2484,7 @@ static int get_serial_info (struct edgeport_port *edge_port, struct serial_struc
static int edge_ioctl (struct usb_serial_port *port, struct file *file, unsigned int cmd, unsigned long arg)
{
- struct edgeport_port *edge_port = (struct edgeport_port *)(port->private);
+ struct edgeport_port *edge_port = usb_get_serial_port_data(port);
struct async_icount cnow;
struct async_icount cprev;
@@ -2556,7 +2558,7 @@ static int edge_ioctl (struct usb_serial_port *port, struct file *file, unsigned
static void edge_break (struct usb_serial_port *port, int break_state)
{
- struct edgeport_port *edge_port = (struct edgeport_port *)(port->private);
+ struct edgeport_port *edge_port = usb_get_serial_port_data(port);
int status;
dbg ("%s - state = %d", __FUNCTION__, break_state);
@@ -2588,12 +2590,12 @@ static int edge_startup (struct usb_serial *serial)
/* create our private serial structure */
edge_serial = kmalloc (sizeof(struct edgeport_serial), GFP_KERNEL);
if (edge_serial == NULL) {
- err("%s - Out of memory", __FUNCTION__);
+ dev_err(serial->dev->dev, "%s - Out of memory\n", __FUNCTION__);
return -ENOMEM;
}
memset (edge_serial, 0, sizeof(struct edgeport_serial));
edge_serial->serial = serial;
- serial->private = edge_serial;
+ usb_set_serial_data(serial, edge_serial);
status = TIDownloadFirmware (edge_serial);
if (status) {
@@ -2605,13 +2607,13 @@ static int edge_startup (struct usb_serial *serial)
for (i = 0; i < serial->num_ports; ++i) {
edge_port = kmalloc (sizeof(struct edgeport_port), GFP_KERNEL);
if (edge_port == NULL) {
- err("%s - Out of memory", __FUNCTION__);
+ dev_err(serial->dev->dev, "%s - Out of memory\n", __FUNCTION__);
return -ENOMEM;
}
memset (edge_port, 0, sizeof(struct edgeport_port));
edge_port->port = &serial->port[i];
edge_port->edge_serial = edge_serial;
- serial->port[i].private = edge_port;
+ usb_set_serial_port_data(&serial->port[i], edge_port);
}
return 0;
@@ -2624,11 +2626,11 @@ static void edge_shutdown (struct usb_serial *serial)
dbg ("%s", __FUNCTION__);
for (i=0; i < serial->num_ports; ++i) {
- kfree (serial->port[i].private);
- serial->port[i].private = NULL;
+ kfree (usb_get_serial_port_data(&serial->port[i]));
+ usb_set_serial_port_data(&serial->port[i], NULL);
}
- kfree (serial->private);
- serial->private = NULL;
+ kfree (usb_get_serial_data(serial));
+ usb_set_serial_data(serial, NULL);
}
diff --git a/drivers/usb/serial/ipaq.c b/drivers/usb/serial/ipaq.c
index b9e23ac67023..d5dc7d80a578 100644
--- a/drivers/usb/serial/ipaq.c
+++ b/drivers/usb/serial/ipaq.c
@@ -9,6 +9,10 @@
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
+ * (12/12/2002) ganesh
+ * Added support for practically all devices supported by ActiveSync
+ * on Windows. Thanks to Wes Cilldhaire <billybobjoehenrybob@hotmail.com>.
+ *
* (26/11/2002) ganesh
* Added insmod options to specify product and vendor id.
* Use modprobe ipaq vendor=0xfoo product=0xbar
@@ -68,9 +72,9 @@
* Version Information
*/
-#define DRIVER_VERSION "v0.4"
+#define DRIVER_VERSION "v0.5"
#define DRIVER_AUTHOR "Ganesh Varadarajan <ganesh@veritas.com>"
-#define DRIVER_DESC "USB Compaq iPAQ, HP Jornada, Casio EM500 driver"
+#define DRIVER_DESC "USB PocketPC PDA driver"
static int product, vendor;
@@ -94,10 +98,36 @@ static void ipaq_destroy_lists(struct usb_serial_port *port);
static struct usb_device_id ipaq_id_table [] = {
/* The first entry is a placeholder for the insmod-specified device */
{ USB_DEVICE(COMPAQ_VENDOR_ID, COMPAQ_IPAQ_ID) },
+ { USB_DEVICE(ASKEY_VENDOR_ID, ASKEY_PRODUCT_ID) },
+ { USB_DEVICE(BCOM_VENDOR_ID, BCOM_0065_ID) },
+ { USB_DEVICE(BCOM_VENDOR_ID, BCOM_0066_ID) },
+ { USB_DEVICE(BCOM_VENDOR_ID, BCOM_0067_ID) },
+ { USB_DEVICE(CASIO_VENDOR_ID, CASIO_2001_ID) },
+ { USB_DEVICE(CASIO_VENDOR_ID, CASIO_EM500_ID) },
{ USB_DEVICE(COMPAQ_VENDOR_ID, COMPAQ_IPAQ_ID) },
+ { USB_DEVICE(COMPAQ_VENDOR_ID, COMPAQ_0032_ID) },
{ USB_DEVICE(HP_VENDOR_ID, HP_JORNADA_548_ID) },
{ USB_DEVICE(HP_VENDOR_ID, HP_JORNADA_568_ID) },
- { USB_DEVICE(CASIO_VENDOR_ID, CASIO_EM500_ID) },
+ { USB_DEVICE(HP_VENDOR_ID, HP_2016_ID) },
+ { USB_DEVICE(HP_VENDOR_ID, HP_2116_ID) },
+ { USB_DEVICE(HP_VENDOR_ID, HP_2216_ID) },
+ { USB_DEVICE(HP_VENDOR_ID, HP_3016_ID) },
+ { USB_DEVICE(HP_VENDOR_ID, HP_3116_ID) },
+ { USB_DEVICE(HP_VENDOR_ID, HP_3216_ID) },
+ { USB_DEVICE(HP_VENDOR_ID, HP_4016_ID) },
+ { USB_DEVICE(HP_VENDOR_ID, HP_4116_ID) },
+ { USB_DEVICE(HP_VENDOR_ID, HP_4216_ID) },
+ { USB_DEVICE(HP_VENDOR_ID, HP_5016_ID) },
+ { USB_DEVICE(HP_VENDOR_ID, HP_5116_ID) },
+ { USB_DEVICE(HP_VENDOR_ID, HP_5216_ID) },
+ { USB_DEVICE(LINKUP_VENDOR_ID, LINKUP_PRODUCT_ID) },
+ { USB_DEVICE(MICROSOFT_VENDOR_ID, MICROSOFT_00CE_ID) },
+ { USB_DEVICE(PORTATEC_VENDOR_ID, PORTATEC_PRODUCT_ID) },
+ { USB_DEVICE(SAGEM_VENDOR_ID, SAGEM_WIRELESS_ID) },
+ { USB_DEVICE(SOCKET_VENDOR_ID, SOCKET_PRODUCT_ID) },
+ { USB_DEVICE(TOSHIBA_VENDOR_ID, TOSHIBA_PRODUCT_ID) },
+ { USB_DEVICE(HTC_VENDOR_ID, HTC_PRODUCT_ID) },
+ { USB_DEVICE(NEC_VENDOR_ID, NEC_PRODUCT_ID) },
{ } /* Terminating entry */
};
@@ -114,7 +144,7 @@ static struct usb_driver ipaq_driver = {
/* All of the device info needed for the Compaq iPAQ */
struct usb_serial_device_type ipaq_device = {
.owner = THIS_MODULE,
- .name = "Compaq iPAQ",
+ .name = "PocketPC PDA",
.id_table = ipaq_id_table,
.num_interrupt_in = NUM_DONT_CARE,
.num_bulk_in = 1,
@@ -156,7 +186,7 @@ static int ipaq_open(struct usb_serial_port *port, struct file *filp)
err("%s - Out of memory", __FUNCTION__);
return -ENOMEM;
}
- port->private = (void *)priv;
+ usb_set_serial_port_data(port, priv);
priv->active = 0;
priv->queue_len = 0;
INIT_LIST_HEAD(&priv->queue);
@@ -251,7 +281,7 @@ error:
static void ipaq_close(struct usb_serial_port *port, struct file *filp)
{
struct usb_serial *serial;
- struct ipaq_private *priv = port->private;
+ struct ipaq_private *priv = usb_get_serial_port_data(port);
if (port_paranoia_check(port, __FUNCTION__)) {
return;
@@ -271,7 +301,7 @@ static void ipaq_close(struct usb_serial_port *port, struct file *filp)
usb_unlink_urb(port->read_urb);
ipaq_destroy_lists(port);
kfree(priv);
- port->private = NULL;
+ usb_set_serial_port_data(port, NULL);
/* Uncomment the following line if you want to see some statistics in your syslog */
/* info ("Bytes In = %d Bytes Out = %d", bytes_in, bytes_out); */
@@ -355,7 +385,7 @@ static int ipaq_write(struct usb_serial_port *port, int from_user, const unsigne
static int ipaq_write_bulk(struct usb_serial_port *port, int from_user, const unsigned char *buf,
int count)
{
- struct ipaq_private *priv = port->private;
+ struct ipaq_private *priv = usb_get_serial_port_data(port);
struct ipaq_packet *pkt = NULL;
int result = 0;
unsigned long flags;
@@ -406,7 +436,7 @@ static int ipaq_write_bulk(struct usb_serial_port *port, int from_user, const un
static void ipaq_write_gather(struct usb_serial_port *port)
{
- struct ipaq_private *priv = (struct ipaq_private *)port->private;
+ struct ipaq_private *priv = usb_get_serial_port_data(port);
struct usb_serial *serial = port->serial;
int count, room;
struct ipaq_packet *pkt;
@@ -448,7 +478,7 @@ static void ipaq_write_gather(struct usb_serial_port *port)
static void ipaq_write_bulk_callback(struct urb *urb, struct pt_regs *regs)
{
struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
- struct ipaq_private *priv = (struct ipaq_private *)port->private;
+ struct ipaq_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
int result;
@@ -480,7 +510,7 @@ static void ipaq_write_bulk_callback(struct urb *urb, struct pt_regs *regs)
static int ipaq_write_room(struct usb_serial_port *port)
{
- struct ipaq_private *priv = (struct ipaq_private *)port->private;
+ struct ipaq_private *priv = usb_get_serial_port_data(port);
dbg("%s - freelen %d", __FUNCTION__, priv->free_len);
return priv->free_len;
@@ -488,7 +518,7 @@ static int ipaq_write_room(struct usb_serial_port *port)
static int ipaq_chars_in_buffer(struct usb_serial_port *port)
{
- struct ipaq_private *priv = (struct ipaq_private *)port->private;
+ struct ipaq_private *priv = usb_get_serial_port_data(port);
dbg("%s - queuelen %d", __FUNCTION__, priv->queue_len);
return priv->queue_len;
@@ -496,7 +526,7 @@ static int ipaq_chars_in_buffer(struct usb_serial_port *port)
static void ipaq_destroy_lists(struct usb_serial_port *port)
{
- struct ipaq_private *priv = (struct ipaq_private *)port->private;
+ struct ipaq_private *priv = usb_get_serial_port_data(port);
struct list_head *tmp;
struct ipaq_packet *pkt;
diff --git a/drivers/usb/serial/ipaq.h b/drivers/usb/serial/ipaq.h
index 16469a60b65d..f3302b337ee0 100644
--- a/drivers/usb/serial/ipaq.h
+++ b/drivers/usb/serial/ipaq.h
@@ -9,22 +9,66 @@
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
- *
*/
#ifndef __LINUX_USB_SERIAL_IPAQ_H
#define __LINUX_USB_SERIAL_IPAQ_H
+#define ASKEY_VENDOR_ID 0x1690
+#define ASKEY_PRODUCT_ID 0x0601
+
+#define BCOM_VENDOR_ID 0x0960
+#define BCOM_0065_ID 0x0065
+#define BCOM_0066_ID 0x0066
+#define BCOM_0067_ID 0x0067
+
+#define CASIO_VENDOR_ID 0x07cf
+#define CASIO_2001_ID 0x2001
+#define CASIO_EM500_ID 0x2002
#define COMPAQ_VENDOR_ID 0x049f
#define COMPAQ_IPAQ_ID 0x0003
+#define COMPAQ_0032_ID 0x0032
#define HP_VENDOR_ID 0x03f0
#define HP_JORNADA_548_ID 0x1016
#define HP_JORNADA_568_ID 0x1116
+#define HP_2016_ID 0x2016
+#define HP_2116_ID 0x2116
+#define HP_2216_ID 0x2216
+#define HP_3016_ID 0x3016
+#define HP_3116_ID 0x3116
+#define HP_3216_ID 0x3216
+#define HP_4016_ID 0x4016
+#define HP_4116_ID 0x4116
+#define HP_4216_ID 0x4216
+#define HP_5016_ID 0x5016
+#define HP_5116_ID 0x5116
+#define HP_5216_ID 0x5216
-#define CASIO_VENDOR_ID 0x07cf
-#define CASIO_EM500_ID 0x2002
+#define LINKUP_VENDOR_ID 0x094b
+#define LINKUP_PRODUCT_ID 0x0001
+
+#define MICROSOFT_VENDOR_ID 0x045e
+#define MICROSOFT_00CE_ID 0x00ce
+
+#define PORTATEC_VENDOR_ID 0x0961
+#define PORTATEC_PRODUCT_ID 0x0010
+
+#define SAGEM_VENDOR_ID 0x5e04
+#define SAGEM_WIRELESS_ID 0xce00
+
+#define SOCKET_VENDOR_ID 0x0104
+#define SOCKET_PRODUCT_ID 0x00be
+
+#define TOSHIBA_VENDOR_ID 0x0930
+#define TOSHIBA_PRODUCT_ID 0x0700
+
+#define HTC_VENDOR_ID 0x0bb4
+#define HTC_PRODUCT_ID 0x00ce
+
+#define NEC_VENDOR_ID 0x0409
+#define NEC_PRODUCT_ID 0x00d5
/*
* Since we can't queue our bulk write urbs (don't know why - it just
@@ -41,8 +85,7 @@
*
* The value of PACKET_SIZE was empirically determined by
* checking the maximum write sizes sent down by the ppp ldisc.
- * URBDATA_QUEUE_MAX is set to 64K, which is the maximum TCP window size
- * supported by the iPAQ.
+ * URBDATA_QUEUE_MAX is set to 64K, which is the maximum TCP window size.
*/
struct ipaq_packet {
diff --git a/drivers/usb/serial/ir-usb.c b/drivers/usb/serial/ir-usb.c
index d18801249d63..6d40da5bd9e7 100644
--- a/drivers/usb/serial/ir-usb.c
+++ b/drivers/usb/serial/ir-usb.c
@@ -243,7 +243,7 @@ static int ir_startup (struct usb_serial *serial)
irda_desc = irda_usb_find_class_desc (serial->dev, 0);
if (irda_desc == NULL) {
- err ("IRDA class descriptor not found, device not bound");
+ dev_err (serial->dev->dev, "IRDA class descriptor not found, device not bound\n");
return -ENODEV;
}
@@ -291,7 +291,7 @@ static int ir_open (struct usb_serial_port *port, struct file *filp)
/* override the default buffer sizes */
buffer = kmalloc (buffer_size, GFP_KERNEL);
if (!buffer) {
- err ("%s - out of memory.", __FUNCTION__);
+ dev_err (port->dev, "%s - out of memory.\n", __FUNCTION__);
return -ENOMEM;
}
kfree (port->read_urb->transfer_buffer);
@@ -300,7 +300,7 @@ static int ir_open (struct usb_serial_port *port, struct file *filp)
buffer = kmalloc (buffer_size, GFP_KERNEL);
if (!buffer) {
- err ("%s - out of memory.", __FUNCTION__);
+ dev_err (port->dev, "%s - out of memory.\n", __FUNCTION__);
return -ENOMEM;
}
kfree (port->write_urb->transfer_buffer);
@@ -320,7 +320,7 @@ static int ir_open (struct usb_serial_port *port, struct file *filp)
port);
result = usb_submit_urb(port->read_urb, GFP_KERNEL);
if (result)
- err("%s - failed submitting read urb, error %d", __FUNCTION__, result);
+ dev_err(port->dev, "%s - failed submitting read urb, error %d\n", __FUNCTION__, result);
return result;
}
@@ -353,7 +353,7 @@ static int ir_write (struct usb_serial_port *port, int from_user, const unsigned
dbg("%s - port = %d, count = %d", __FUNCTION__, port->number, count);
if (!port->tty) {
- err ("%s - no tty???", __FUNCTION__);
+ dev_err (port->dev, "%s - no tty???\n", __FUNCTION__);
return 0;
}
@@ -399,7 +399,7 @@ static int ir_write (struct usb_serial_port *port, int from_user, const unsigned
result = usb_submit_urb (port->write_urb, GFP_ATOMIC);
if (result)
- err("%s - failed submitting write urb, error %d", __FUNCTION__, result);
+ dev_err(port->dev, "%s - failed submitting write urb, error %d\n", __FUNCTION__, result);
else
result = transfer_size;
@@ -503,11 +503,9 @@ static void ir_read_bulk_callback (struct urb *urb, struct pt_regs *regs)
port);
result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
-
if (result)
- err("%s - failed resubmitting read urb, error %d",
- __FUNCTION__,
- result);
+ dev_err(port->dev, "%s - failed resubmitting read urb, error %d\n",
+ __FUNCTION__, result);
break ;
@@ -601,7 +599,7 @@ static void ir_set_termios (struct usb_serial_port *port, struct termios *old_te
result = usb_submit_urb (port->write_urb, GFP_KERNEL);
if (result)
- err("%s - failed submitting write urb, error %d", __FUNCTION__, result);
+ dev_err(port->dev, "%s - failed submitting write urb, error %d\n", __FUNCTION__, result);
}
return;
}
diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c
index e128949276bf..0aeafd9b417c 100644
--- a/drivers/usb/serial/keyspan.c
+++ b/drivers/usb/serial/keyspan.c
@@ -220,7 +220,7 @@ static void keyspan_break_ctl (struct usb_serial_port *port, int break_state)
dbg("%s", __FUNCTION__);
- p_priv = (struct keyspan_port_private *)port->private;
+ p_priv = usb_get_serial_port_data(port);
if (break_state == -1)
p_priv->break_on = 1;
@@ -241,7 +241,7 @@ static void keyspan_set_termios (struct usb_serial_port *port,
dbg("%s", __FUNCTION__);
- p_priv = (struct keyspan_port_private *)(port->private);
+ p_priv = usb_get_serial_port_data(port);
d_details = p_priv->device_details;
cflag = port->tty->termios->c_cflag;
device_port = port->number - port->serial->minor;
@@ -270,7 +270,7 @@ static int keyspan_ioctl(struct usb_serial_port *port, struct file *file,
unsigned int value, set;
struct keyspan_port_private *p_priv;
- p_priv = (struct keyspan_port_private *)(port->private);
+ p_priv = usb_get_serial_port_data(port);
switch (cmd) {
case TIOCMGET:
@@ -321,7 +321,7 @@ static int keyspan_write(struct usb_serial_port *port, int from_user,
struct urb *this_urb;
int err;
- p_priv = (struct keyspan_port_private *)(port->private);
+ p_priv = usb_get_serial_port_data(port);
d_details = p_priv->device_details;
dbg("%s - for port %d (%d chars [%x]), flip=%d",
@@ -444,7 +444,7 @@ static void usa2x_outdat_callback(struct urb *urb, struct pt_regs *regs)
struct keyspan_port_private *p_priv;
port = (struct usb_serial_port *) urb->context;
- p_priv = (struct keyspan_port_private *)(port->private);
+ p_priv = usb_get_serial_port_data(port);
dbg ("%s - urb %d", __FUNCTION__, urb == p_priv->out_urbs[1]);
if (port->open_count)
@@ -463,7 +463,7 @@ static void usa26_outcont_callback(struct urb *urb, struct pt_regs *regs)
struct keyspan_port_private *p_priv;
port = (struct usb_serial_port *) urb->context;
- p_priv = (struct keyspan_port_private *)(port->private);
+ p_priv = usb_get_serial_port_data(port);
if (p_priv->resend_cont) {
dbg ("%s - sending setup", __FUNCTION__);
@@ -508,7 +508,7 @@ static void usa26_instat_callback(struct urb *urb, struct pt_regs *regs)
goto exit;
}
port = &serial->port[msg->port];
- p_priv = (struct keyspan_port_private *)(port->private);
+ p_priv = usb_get_serial_port_data(port);
/* Update handshaking pin state information */
old_dcd_state = p_priv->dcd_state;
@@ -551,7 +551,7 @@ static void usa28_indat_callback(struct urb *urb, struct pt_regs *regs)
dbg ("%s", __FUNCTION__);
port = (struct usb_serial_port *) urb->context;
- p_priv = (struct keyspan_port_private *)(port->private);
+ p_priv = usb_get_serial_port_data(port);
data = urb->transfer_buffer;
if (urb != p_priv->in_urbs[p_priv->in_flip])
@@ -565,7 +565,7 @@ static void usa28_indat_callback(struct urb *urb, struct pt_regs *regs)
}
port = (struct usb_serial_port *) urb->context;
- p_priv = (struct keyspan_port_private *)(port->private);
+ p_priv = usb_get_serial_port_data(port);
data = urb->transfer_buffer;
tty = port->tty;
@@ -599,7 +599,7 @@ static void usa28_outcont_callback(struct urb *urb, struct pt_regs *regs)
struct keyspan_port_private *p_priv;
port = (struct usb_serial_port *) urb->context;
- p_priv = (struct keyspan_port_private *)(port->private);
+ p_priv = usb_get_serial_port_data(port);
if (p_priv->resend_cont) {
dbg ("%s - sending setup", __FUNCTION__);
@@ -643,7 +643,7 @@ static void usa28_instat_callback(struct urb *urb, struct pt_regs *regs)
goto exit;
}
port = &serial->port[msg->port];
- p_priv = (struct keyspan_port_private *)(port->private);
+ p_priv = usb_get_serial_port_data(port);
/* Update handshaking pin state information */
old_dcd_state = p_priv->dcd_state;
@@ -686,7 +686,7 @@ static void usa49_glocont_callback(struct urb *urb, struct pt_regs *regs)
serial = (struct usb_serial *) urb->context;
for (i = 0; i < serial->num_ports; ++i) {
port = &serial->port[i];
- p_priv = (struct keyspan_port_private *)(port->private);
+ p_priv = usb_get_serial_port_data(port);
if (p_priv->resend_cont) {
dbg ("%s - sending setup", __FUNCTION__);
@@ -735,7 +735,7 @@ static void usa49_instat_callback(struct urb *urb, struct pt_regs *regs)
goto exit;
}
port = &serial->port[msg->portNumber];
- p_priv = (struct keyspan_port_private *)(port->private);
+ p_priv = usb_get_serial_port_data(port);
/* Update handshaking pin state information */
old_dcd_state = p_priv->dcd_state;
@@ -834,7 +834,7 @@ static int keyspan_write_room (struct usb_serial_port *port)
struct urb *this_urb;
dbg("%s", __FUNCTION__);
- p_priv = (struct keyspan_port_private *)(port->private);
+ p_priv = usb_get_serial_port_data(port);
d_details = p_priv->device_details;
flip = p_priv->out_flip;
@@ -867,14 +867,12 @@ static int keyspan_open (struct usb_serial_port *port, struct file *filp)
int i, err;
struct urb *urb;
- s_priv = (struct keyspan_serial_private *)(serial->private);
- p_priv = (struct keyspan_port_private *)(port->private);
+ s_priv = usb_get_serial_data(serial);
+ p_priv = usb_get_serial_port_data(port);
d_details = s_priv->device_details;
dbg("%s - port%d.", __FUNCTION__, port->number);
- p_priv = (struct keyspan_port_private *)(port->private);
-
/* Set some sane defaults */
p_priv->rts_state = 1;
p_priv->dtr_state = 1;
@@ -929,8 +927,8 @@ static void keyspan_close(struct usb_serial_port *port, struct file *filp)
return;
dbg("%s", __FUNCTION__);
- s_priv = (struct keyspan_serial_private *)(serial->private);
- p_priv = (struct keyspan_port_private *)(port->private);
+ s_priv = usb_get_serial_data(serial);
+ p_priv = usb_get_serial_port_data(port);
p_priv->rts_state = 0;
p_priv->dtr_state = 0;
@@ -1037,7 +1035,7 @@ static int keyspan_fake_startup (struct usb_serial *serial)
}
if (record == NULL) {
- err("Required keyspan firmware image (%s) unavailable.", fw_name);
+ dev_err(serial->dev->dev, "Required keyspan firmware image (%s) unavailable.\n", fw_name);
return(1);
}
@@ -1051,10 +1049,10 @@ static int keyspan_fake_startup (struct usb_serial *serial)
(unsigned char *)record->data,
record->data_size, 0xa0);
if (response < 0) {
- err("ezusb_writememory failed for Keyspan"
- "firmware (%d %04X %p %d)",
- response,
- record->address, record->data, record->data_size);
+ dev_err(serial->dev->dev, "ezusb_writememory failed for Keyspan"
+ "firmware (%d %04X %p %d)\n",
+ response,
+ record->address, record->data, record->data_size);
break;
}
record++;
@@ -1141,7 +1139,7 @@ static void keyspan_setup_urbs(struct usb_serial *serial)
dbg ("%s", __FUNCTION__);
- s_priv = (struct keyspan_serial_private *)(serial->private);
+ s_priv = usb_get_serial_data(serial);
d_details = s_priv->device_details;
/* Setup values for the various callback routines */
@@ -1162,7 +1160,7 @@ static void keyspan_setup_urbs(struct usb_serial *serial)
/* Setup endpoints for each port specific thing */
for (i = 0; i < d_details->num_ports; i ++) {
port = &serial->port[i];
- p_priv = (struct keyspan_port_private *)(port->private);
+ p_priv = usb_get_serial_port_data(port);
/* Do indat endpoints first, once for each flip */
endp = d_details->indat_endpoints[i];
@@ -1377,8 +1375,8 @@ static int keyspan_usa26_send_setup(struct usb_serial *serial,
dbg ("%s reset=%d", __FUNCTION__, reset_port);
- s_priv = (struct keyspan_serial_private *)(serial->private);
- p_priv = (struct keyspan_port_private *)(port->private);
+ s_priv = usb_get_serial_data(serial);
+ p_priv = usb_get_serial_port_data(port);
d_details = s_priv->device_details;
device_port = port->number - port->serial->minor;
@@ -1532,8 +1530,8 @@ static int keyspan_usa28_send_setup(struct usb_serial *serial,
dbg ("%s", __FUNCTION__);
- s_priv = (struct keyspan_serial_private *)(serial->private);
- p_priv = (struct keyspan_port_private *)(port->private);
+ s_priv = usb_get_serial_data(serial);
+ p_priv = usb_get_serial_port_data(port);
d_details = s_priv->device_details;
device_port = port->number - port->serial->minor;
@@ -1657,8 +1655,8 @@ static int keyspan_usa49_send_setup(struct usb_serial *serial,
dbg ("%s", __FUNCTION__);
- s_priv = (struct keyspan_serial_private *)(serial->private);
- p_priv = (struct keyspan_port_private *)(port->private);
+ s_priv = usb_get_serial_data(serial);
+ p_priv = usb_get_serial_port_data(port);
d_details = s_priv->device_details;
glocont_urb = d_details->glocont_endpoint;
@@ -1817,7 +1815,7 @@ static void keyspan_send_setup(struct usb_serial_port *port, int reset_port)
dbg ("%s", __FUNCTION__);
- s_priv = (struct keyspan_serial_private *)(serial->private);
+ s_priv = usb_get_serial_data(serial);
d_details = s_priv->device_details;
switch (d_details->msg_format) {
@@ -1849,34 +1847,32 @@ static int keyspan_startup (struct usb_serial *serial)
if (d_details->product_id == serial->dev->descriptor.idProduct)
break;
if (d_details == NULL) {
- err("%s - unknown product id %x", __FUNCTION__, serial->dev->descriptor.idProduct);
+ dev_err(serial->dev->dev, "%s - unknown product id %x\n", __FUNCTION__, serial->dev->descriptor.idProduct);
return 1;
}
/* Setup private data for serial driver */
- serial->private = kmalloc(sizeof(struct keyspan_serial_private),
- GFP_KERNEL);
- if (!serial->private) {
+ s_priv = kmalloc(sizeof(struct keyspan_serial_private), GFP_KERNEL);
+ if (!s_priv) {
dbg("%s - kmalloc for keyspan_serial_private failed.", __FUNCTION__);
- return (1);
+ return -ENOMEM;
}
- memset(serial->private, 0, sizeof(struct keyspan_serial_private));
+ memset(s_priv, 0, sizeof(struct keyspan_serial_private));
- s_priv = (struct keyspan_serial_private *)(serial->private);
s_priv->device_details = d_details;
-
+ usb_set_serial_data(serial, s_priv);
+
/* Now setup per port private data */
for (i = 0; i < serial->num_ports; i++) {
port = &serial->port[i];
- port->private = kmalloc(sizeof(struct keyspan_port_private),
- GFP_KERNEL);
- if (!port->private) {
+ p_priv = kmalloc(sizeof(struct keyspan_port_private), GFP_KERNEL);
+ if (!p_priv) {
dbg("%s - kmalloc for keyspan_port_private (%d) failed!.", __FUNCTION__, i);
return (1);
}
- memset(port->private, 0, sizeof(struct keyspan_port_private));
- p_priv = (struct keyspan_port_private *)(port->private);
+ memset(p_priv, 0, sizeof(struct keyspan_port_private));
p_priv->device_details = d_details;
+ usb_set_serial_port_data(port, p_priv);
}
keyspan_setup_urbs(serial);
@@ -1898,14 +1894,14 @@ static void keyspan_shutdown (struct usb_serial *serial)
dbg("%s", __FUNCTION__);
- s_priv = (struct keyspan_serial_private *)(serial->private);
+ s_priv = usb_get_serial_data(serial);
/* Stop reading/writing urbs */
stop_urb(s_priv->instat_urb);
stop_urb(s_priv->glocont_urb);
for (i = 0; i < serial->num_ports; ++i) {
port = &serial->port[i];
- p_priv = (struct keyspan_port_private *)(port->private);
+ p_priv = usb_get_serial_port_data(port);
stop_urb(p_priv->inack_urb);
stop_urb(p_priv->outcont_urb);
for (j = 0; j < 2; j++) {
@@ -1921,7 +1917,7 @@ static void keyspan_shutdown (struct usb_serial *serial)
usb_free_urb(s_priv->glocont_urb);
for (i = 0; i < serial->num_ports; ++i) {
port = &serial->port[i];
- p_priv = (struct keyspan_port_private *)(port->private);
+ p_priv = usb_get_serial_port_data(port);
if (p_priv->inack_urb)
usb_free_urb(p_priv->inack_urb);
if (p_priv->outcont_urb)
@@ -1935,13 +1931,13 @@ static void keyspan_shutdown (struct usb_serial *serial)
}
/* dbg("Freeing serial->private."); */
- kfree(serial->private);
+ kfree(s_priv);
/* dbg("Freeing port->private."); */
/* Now free per port private data */
for (i = 0; i < serial->num_ports; i++) {
port = &serial->port[i];
- kfree(port->private);
+ kfree(usb_get_serial_port_data(port));
}
}
diff --git a/drivers/usb/serial/keyspan_pda.c b/drivers/usb/serial/keyspan_pda.c
index 02bbb9cb5174..76a0590933fc 100644
--- a/drivers/usb/serial/keyspan_pda.c
+++ b/drivers/usb/serial/keyspan_pda.c
@@ -231,7 +231,7 @@ static void keyspan_pda_rx_interrupt (struct urb *urb, struct pt_regs *regs)
int i;
int status;
struct keyspan_pda_private *priv;
- priv = (struct keyspan_pda_private *)(port->private);
+ priv = usb_get_serial_port_data(port);
switch (urb->status) {
case 0:
@@ -532,7 +532,7 @@ static int keyspan_pda_write(struct usb_serial_port *port, int from_user,
int rc = 0;
struct keyspan_pda_private *priv;
- priv = (struct keyspan_pda_private *)(port->private);
+ priv = usb_get_serial_port_data(port);
/* guess how much room is left in the device's ring buffer, and if we
want to send more than that, check first, updating our notion of
what is left. If our write will result in no room left, ask the
@@ -643,7 +643,7 @@ static void keyspan_pda_write_bulk_callback (struct urb *urb, struct pt_regs *re
struct usb_serial *serial;
struct keyspan_pda_private *priv;
- priv = (struct keyspan_pda_private *)(port->private);
+ priv = usb_get_serial_port_data(port);
if (port_paranoia_check (port, "keyspan_pda_rx_interrupt")) {
return;
@@ -662,7 +662,8 @@ static void keyspan_pda_write_bulk_callback (struct urb *urb, struct pt_regs *re
static int keyspan_pda_write_room (struct usb_serial_port *port)
{
struct keyspan_pda_private *priv;
- priv = (struct keyspan_pda_private *)(port->private);
+
+ priv = usb_get_serial_port_data(port);
/* used by n_tty.c for processing of tabs and such. Giving it our
conservative guess is probably good enough, but needs testing by
@@ -675,7 +676,8 @@ static int keyspan_pda_write_room (struct usb_serial_port *port)
static int keyspan_pda_chars_in_buffer (struct usb_serial_port *port)
{
struct keyspan_pda_private *priv;
- priv = (struct keyspan_pda_private *)(port->private);
+
+ priv = usb_get_serial_port_data(port);
/* when throttled, return at least WAKEUP_CHARS to tell select() (via
n_tty.c:normal_poll() ) that we're not writeable. */
@@ -711,7 +713,7 @@ static int keyspan_pda_open (struct usb_serial_port *port, struct file *filp)
rc = -EIO;
goto error;
}
- priv = (struct keyspan_pda_private *)(port->private);
+ priv = usb_get_serial_port_data(port);
priv->tx_room = room;
priv->tx_throttled = room ? 0 : 1;
@@ -803,10 +805,10 @@ static int keyspan_pda_startup (struct usb_serial *serial)
/* allocate the private data structures for all ports. Well, for all
one ports. */
- priv = serial->port[0].private
- = kmalloc(sizeof(struct keyspan_pda_private), GFP_KERNEL);
+ priv = kmalloc(sizeof(struct keyspan_pda_private), GFP_KERNEL);
if (!priv)
return (1); /* error */
+ usb_set_serial_port_data(&serial->port[0], priv);
init_waitqueue_head(&serial->port[0].write_wait);
INIT_WORK(&priv->wakeup_work, (void *)keyspan_pda_wakeup_write,
(void *)(&serial->port[0]));
@@ -820,7 +822,7 @@ static void keyspan_pda_shutdown (struct usb_serial *serial)
{
dbg("%s", __FUNCTION__);
- kfree(serial->port[0].private);
+ kfree(usb_get_serial_port_data(&serial->port[0]));
}
#ifdef KEYSPAN
diff --git a/drivers/usb/serial/kl5kusb105.c b/drivers/usb/serial/kl5kusb105.c
index 986c06cf45c0..6261e64c5e40 100644
--- a/drivers/usb/serial/kl5kusb105.c
+++ b/drivers/usb/serial/kl5kusb105.c
@@ -265,13 +265,12 @@ static int klsi_105_startup (struct usb_serial *serial)
/* allocate the private data structure */
for (i=0; i<serial->num_ports; i++) {
- serial->port[i].private = kmalloc(sizeof(struct klsi_105_private),
+ priv = kmalloc(sizeof(struct klsi_105_private),
GFP_KERNEL);
- if (!serial->port[i].private) {
+ if (!priv) {
dbg("%skmalloc for klsi_105_private failed.", __FUNCTION__);
- return (-1); /* error */
+ return -ENOMEM;
}
- priv = (struct klsi_105_private *)serial->port[i].private;
/* set initial values for control structures */
priv->cfg.pktlen = 5;
priv->cfg.baudrate = kl5kusb105a_sio_b9600;
@@ -283,6 +282,7 @@ static int klsi_105_startup (struct usb_serial *serial)
priv->bytes_in = 0;
priv->bytes_out = 0;
+ usb_set_serial_port_data(&serial->port[i], priv);
spin_lock_init (&priv->write_urb_pool_lock);
for (i=0; i<NUM_URBS; i++) {
@@ -319,8 +319,7 @@ static void klsi_105_shutdown (struct usb_serial *serial)
/* stop reads and writes on all ports */
for (i=0; i < serial->num_ports; ++i) {
- struct klsi_105_private *priv =
- (struct klsi_105_private*) serial->port[i].private;
+ struct klsi_105_private *priv = usb_get_serial_port_data(&serial->port[i]);
unsigned long flags;
if (priv) {
@@ -347,7 +346,8 @@ static void klsi_105_shutdown (struct usb_serial *serial)
spin_unlock_irqrestore (&priv->write_urb_pool_lock,
flags);
- kfree(serial->port[i].private);
+ kfree(priv);
+ usb_set_serial_port_data(&serial->port[i], NULL);
}
}
} /* klsi_105_shutdown */
@@ -355,7 +355,7 @@ static void klsi_105_shutdown (struct usb_serial *serial)
static int klsi_105_open (struct usb_serial_port *port, struct file *filp)
{
struct usb_serial *serial = port->serial;
- struct klsi_105_private *priv = (struct klsi_105_private *)port->private;
+ struct klsi_105_private *priv = usb_get_serial_port_data(port);
int retval = 0;
int rc;
int i;
@@ -436,8 +436,7 @@ exit:
static void klsi_105_close (struct usb_serial_port *port, struct file *filp)
{
struct usb_serial *serial;
- struct klsi_105_private *priv
- = (struct klsi_105_private *)port->private;
+ struct klsi_105_private *priv = usb_get_serial_port_data(port);
int rc;
dbg("%s port %d", __FUNCTION__, port->number);
@@ -481,8 +480,7 @@ static int klsi_105_write (struct usb_serial_port *port, int from_user,
const unsigned char *buf, int count)
{
struct usb_serial *serial = port->serial;
- struct klsi_105_private *priv =
- (struct klsi_105_private*) port->private;
+ struct klsi_105_private *priv = usb_get_serial_port_data(port);
int result, size;
int bytes_sent=0;
@@ -588,8 +586,7 @@ static int klsi_105_chars_in_buffer (struct usb_serial_port *port)
int chars = 0;
int i;
unsigned long flags;
- struct klsi_105_private *priv =
- (struct klsi_105_private*) port->private;
+ struct klsi_105_private *priv = usb_get_serial_port_data(port);
spin_lock_irqsave (&priv->write_urb_pool_lock, flags);
@@ -610,8 +607,7 @@ static int klsi_105_write_room (struct usb_serial_port *port)
unsigned long flags;
int i;
int room = 0;
- struct klsi_105_private *priv =
- (struct klsi_105_private*) port->private;
+ struct klsi_105_private *priv = usb_get_serial_port_data(port);
spin_lock_irqsave (&priv->write_urb_pool_lock, flags);
for (i = 0; i < NUM_URBS; ++i) {
@@ -632,8 +628,7 @@ static void klsi_105_read_bulk_callback (struct urb *urb, struct pt_regs *regs)
{
struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
struct usb_serial *serial = port->serial;
- struct klsi_105_private *priv =
- (struct klsi_105_private*) port->private;
+ struct klsi_105_private *priv = usb_get_serial_port_data(port);
struct tty_struct *tty;
unsigned char *data = urb->transfer_buffer;
int rc;
@@ -715,7 +710,7 @@ static void klsi_105_set_termios (struct usb_serial_port *port,
struct termios *old_termios)
{
struct usb_serial *serial = port->serial;
- struct klsi_105_private *priv = (struct klsi_105_private *)port->private;
+ struct klsi_105_private *priv = usb_get_serial_port_data(port);
unsigned int iflag = port->tty->termios->c_iflag;
unsigned int old_iflag = old_termios->c_iflag;
unsigned int cflag = port->tty->termios->c_cflag;
@@ -869,7 +864,7 @@ static int klsi_105_ioctl (struct usb_serial_port *port, struct file * file,
unsigned int cmd, unsigned long arg)
{
struct usb_serial *serial = port->serial;
- struct klsi_105_private *priv = (struct klsi_105_private *)port->private;
+ struct klsi_105_private *priv = usb_get_serial_port_data(port);
int mask;
dbg("%scmd=0x%x", __FUNCTION__, cmd);
diff --git a/drivers/usb/serial/kobil_sct.c b/drivers/usb/serial/kobil_sct.c
index f0981916ddba..1a7057ae1ac4 100644
--- a/drivers/usb/serial/kobil_sct.c
+++ b/drivers/usb/serial/kobil_sct.c
@@ -136,12 +136,11 @@ static int kobil_startup (struct usb_serial *serial)
struct usb_host_interface *altsetting;
struct usb_host_endpoint *endpoint;
- serial->port->private = kmalloc(sizeof(struct kobil_private), GFP_KERNEL);
- if (!serial->port->private){
- return -1;
+ priv = kmalloc(sizeof(struct kobil_private), GFP_KERNEL);
+ if (!priv){
+ return -ENOMEM;
}
- priv = (struct kobil_private *) serial->port->private;
priv->filled = 0;
priv->cur_pos = 0;
priv->device_type = serial->product;
@@ -158,6 +157,7 @@ static int kobil_startup (struct usb_serial *serial)
printk(KERN_DEBUG "KOBIL USBTWIN detected\n");
break;
}
+ usb_set_serial_port_data(serial->port, priv);
// search for the neccessary endpoints
pdev = serial->dev;
@@ -192,9 +192,8 @@ static void kobil_shutdown (struct usb_serial *serial)
while (serial->port[i].open_count > 0) {
kobil_close (&serial->port[i], NULL);
}
- if (serial->port[i].private) {
- kfree(serial->port[i].private);
- }
+ kfree(usb_get_serial_port_data(&serial->port[i]));
+ usb_set_serial_port_data(&serial->port[i], NULL);
}
}
@@ -208,7 +207,7 @@ static int kobil_open (struct usb_serial_port *port, struct file *filp)
int write_urb_transfer_buffer_length = 8;
dbg("%s - port %d", __FUNCTION__, port->number);
- priv = (struct kobil_private *) port->private;
+ priv = usb_get_serial_port_data(port);
priv->line_state = 0;
if (port_paranoia_check (port, __FUNCTION__))
@@ -413,7 +412,7 @@ static int kobil_write (struct usb_serial_port *port, int from_user,
return 0;
}
- priv = (struct kobil_private *) port->private;
+ priv = usb_get_serial_port_data(port);
if (count > (KOBIL_BUF_LENGTH - priv->filled)) {
dbg("%s - port %d Error: write request bigger than buffer size", __FUNCTION__, port->number);
@@ -513,7 +512,7 @@ static int kobil_ioctl(struct usb_serial_port *port, struct file *file,
int transfer_buffer_length = 8;
char *settings;
- priv = (struct kobil_private *) port->private;
+ priv = usb_get_serial_port_data(port);
if (priv->device_type == KOBIL_USBTWIN_PRODUCT_ID) {
// This device doesn't support ioctl calls
return 0;
diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c
index 525e0e5779e6..85fec580dc09 100644
--- a/drivers/usb/serial/mct_u232.c
+++ b/drivers/usb/serial/mct_u232.c
@@ -304,40 +304,40 @@ static int mct_u232_startup (struct usb_serial *serial)
struct mct_u232_private *priv;
/* allocate the private data structure */
- serial->port->private = kmalloc(sizeof(struct mct_u232_private),
- GFP_KERNEL);
- if (!serial->port->private)
+ priv = kmalloc(sizeof(struct mct_u232_private), GFP_KERNEL);
+ if (!priv)
return (-1); /* error */
- priv = (struct mct_u232_private *)serial->port->private;
/* set initial values for control structures */
priv->control_state = 0;
priv->last_lsr = 0;
priv->last_msr = 0;
+ usb_set_serial_port_data(serial->port, priv);
init_waitqueue_head(&serial->port->write_wait);
-
+
return (0);
} /* mct_u232_startup */
static void mct_u232_shutdown (struct usb_serial *serial)
{
+ struct mct_u232_private *priv;
int i;
dbg("%s", __FUNCTION__);
- /* stop reads and writes on all ports */
for (i=0; i < serial->num_ports; ++i) {
/* My special items, the standard routines free my urbs */
- if (serial->port[i].private)
- kfree(serial->port[i].private);
+ priv = usb_get_serial_port_data(&serial->port[i]);
+ if (priv)
+ kfree(priv);
}
} /* mct_u232_shutdown */
static int mct_u232_open (struct usb_serial_port *port, struct file *filp)
{
struct usb_serial *serial = port->serial;
- struct mct_u232_private *priv = (struct mct_u232_private *)port->private;
+ struct mct_u232_private *priv = usb_get_serial_port_data(port);
int retval = 0;
dbg("%s port %d", __FUNCTION__, port->number);
@@ -375,7 +375,7 @@ static int mct_u232_open (struct usb_serial_port *port, struct file *filp)
struct usb_serial_port *rport;
rport = &serial->port[1];
rport->tty = port->tty;
- rport->private = port->private;
+ usb_set_serial_port_data(rport, usb_get_serial_port_data(port));
port->read_urb = rport->interrupt_in_urb;
}
@@ -518,7 +518,7 @@ static void mct_u232_write_bulk_callback (struct urb *urb, struct pt_regs *regs)
static void mct_u232_read_int_callback (struct urb *urb, struct pt_regs *regs)
{
struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
- struct mct_u232_private *priv = (struct mct_u232_private *)port->private;
+ struct mct_u232_private *priv = usb_get_serial_port_data(port);
struct usb_serial *serial = port->serial;
struct tty_struct *tty;
unsigned char *data = urb->transfer_buffer;
@@ -609,7 +609,7 @@ static void mct_u232_set_termios (struct usb_serial_port *port,
struct termios *old_termios)
{
struct usb_serial *serial = port->serial;
- struct mct_u232_private *priv = (struct mct_u232_private *)port->private;
+ struct mct_u232_private *priv = usb_get_serial_port_data(port);
unsigned int iflag = port->tty->termios->c_iflag;
unsigned int old_iflag = old_termios->c_iflag;
unsigned int cflag = port->tty->termios->c_cflag;
@@ -725,7 +725,7 @@ static void mct_u232_set_termios (struct usb_serial_port *port,
static void mct_u232_break_ctl( struct usb_serial_port *port, int break_state )
{
struct usb_serial *serial = port->serial;
- struct mct_u232_private *priv = (struct mct_u232_private *)port->private;
+ struct mct_u232_private *priv = usb_get_serial_port_data(port);
unsigned char lcr = priv->last_lcr;
dbg("%sstate=%d", __FUNCTION__, break_state);
@@ -741,7 +741,7 @@ static int mct_u232_ioctl (struct usb_serial_port *port, struct file * file,
unsigned int cmd, unsigned long arg)
{
struct usb_serial *serial = port->serial;
- struct mct_u232_private *priv = (struct mct_u232_private *)port->private;
+ struct mct_u232_private *priv = usb_get_serial_port_data(port);
int mask;
dbg("%scmd=0x%x", __FUNCTION__, cmd);
diff --git a/drivers/usb/serial/omninet.c b/drivers/usb/serial/omninet.c
index 8bfaea63e419..da9202627baa 100644
--- a/drivers/usb/serial/omninet.c
+++ b/drivers/usb/serial/omninet.c
@@ -168,7 +168,7 @@ static int omninet_open (struct usb_serial_port *port, struct file *filp)
return -ENOMEM;
}
- port->private = od;
+ usb_set_serial_port_data(port, od);
wport = &serial->port[1];
wport->tty = port->tty;
@@ -205,7 +205,7 @@ static void omninet_close (struct usb_serial_port *port, struct file * filp)
usb_unlink_urb (port->read_urb);
}
- od = (struct omninet_data *)port->private;
+ od = usb_get_serial_port_data(port);
if (od)
kfree(od);
}
@@ -272,7 +272,7 @@ static int omninet_write (struct usb_serial_port *port, int from_user, const uns
struct usb_serial *serial = port->serial;
struct usb_serial_port *wport = &serial->port[1];
- struct omninet_data *od = (struct omninet_data *) port->private;
+ struct omninet_data *od = usb_get_serial_port_data(port);
struct omninet_header *header = (struct omninet_header *) wport->write_urb->transfer_buffer;
int result;
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
index 1284892b0fb4..95d4e882f3c7 100644
--- a/drivers/usb/serial/pl2303.c
+++ b/drivers/usb/serial/pl2303.c
@@ -163,7 +163,7 @@ static int pl2303_startup (struct usb_serial *serial)
if (!priv)
return -ENOMEM;
memset (priv, 0x00, sizeof (struct pl2303_private));
- serial->port[i].private = priv;
+ usb_set_serial_port_data(&serial->port[i], priv);
}
return 0;
}
@@ -204,7 +204,7 @@ static int pl2303_write (struct usb_serial_port *port, int from_user, const uns
port->write_urb->dev = port->serial->dev;
result = usb_submit_urb (port->write_urb, GFP_ATOMIC);
if (result)
- err("%s - failed submitting write urb, error %d", __FUNCTION__, result);
+ dev_err(port->dev, "%s - failed submitting write urb, error %d\n", __FUNCTION__, result);
else
result = count;
@@ -216,24 +216,23 @@ static int pl2303_write (struct usb_serial_port *port, int from_user, const uns
static void pl2303_set_termios (struct usb_serial_port *port, struct termios *old_termios)
{
struct usb_serial *serial = port->serial;
- struct pl2303_private *priv;
+ struct pl2303_private *priv = usb_get_serial_port_data(port);
unsigned int cflag;
unsigned char *buf;
int baud;
int i;
- dbg("%s - port %d, initialized = %d", __FUNCTION__, port->number,
- ((struct pl2303_private *) port->private)->termios_initialized);
+ dbg("%s - port %d, initialized = %d", __FUNCTION__, port->number, priv->termios_initialized);
if ((!port->tty) || (!port->tty->termios)) {
dbg("%s - no tty structures", __FUNCTION__);
return;
}
- if (!(((struct pl2303_private *) port->private)->termios_initialized)) {
+ if (!priv->termios_initialized) {
*(port->tty->termios) = tty_std_termios;
port->tty->termios->c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
- ((struct pl2303_private *) port->private)->termios_initialized = 1;
+ priv->termios_initialized = 1;
}
cflag = port->tty->termios->c_cflag;
/* check that they really want us to change something */
@@ -247,7 +246,7 @@ static void pl2303_set_termios (struct usb_serial_port *port, struct termios *ol
buf = kmalloc (7, GFP_KERNEL);
if (!buf) {
- err("%s - out of memory.", __FUNCTION__);
+ dev_err(port->dev, "%s - out of memory.\n", __FUNCTION__);
return;
}
memset (buf, 0x00, 0x07);
@@ -295,7 +294,7 @@ static void pl2303_set_termios (struct usb_serial_port *port, struct termios *ol
case B230400: baud = 230400; break;
case B460800: baud = 460800; break;
default:
- err ("pl2303 driver does not support the baudrate requested (fix it)");
+ dev_err(port->dev, "pl2303 driver does not support the baudrate requested (fix it)\n");
break;
}
dbg("%s - baud = %d", __FUNCTION__, baud);
@@ -341,7 +340,6 @@ static void pl2303_set_termios (struct usb_serial_port *port, struct termios *ol
dbg ("0x21:0x20:0:0 %d", i);
if (cflag && CBAUD) {
- priv = port->private;
if ((cflag && CBAUD) == B0)
priv->line_control &= ~(CONTROL_DTR | CONTROL_RTS);
else
@@ -413,7 +411,7 @@ static int pl2303_open (struct usb_serial_port *port, struct file *filp)
port->read_urb->dev = serial->dev;
result = usb_submit_urb (port->read_urb, GFP_KERNEL);
if (result) {
- err("%s - failed submitting read urb, error %d", __FUNCTION__, result);
+ dev_err(port->dev, "%s - failed submitting read urb, error %d\n", __FUNCTION__, result);
pl2303_close (port, NULL);
return -EPROTO;
}
@@ -422,7 +420,7 @@ static int pl2303_open (struct usb_serial_port *port, struct file *filp)
port->interrupt_in_urb->dev = serial->dev;
result = usb_submit_urb (port->interrupt_in_urb, GFP_KERNEL);
if (result) {
- err("%s - failed submitting interrupt urb, error %d", __FUNCTION__, result);
+ dev_err(port->dev, "%s - failed submitting interrupt urb, error %d\n", __FUNCTION__, result);
pl2303_close (port, NULL);
return -EPROTO;
}
@@ -450,7 +448,7 @@ static void pl2303_close (struct usb_serial_port *port, struct file *filp)
c_cflag = port->tty->termios->c_cflag;
if (c_cflag & HUPCL) {
/* drop DTR and RTS */
- priv = port->private;
+ priv = usb_get_serial_port_data(port);
priv->line_control = 0;
set_control_lines (port->serial->dev,
priv->line_control);
@@ -481,7 +479,7 @@ static void pl2303_close (struct usb_serial_port *port, struct file *filp)
static int set_modem_info (struct usb_serial_port *port, unsigned int cmd, unsigned int *value)
{
- struct pl2303_private *priv = port->private;
+ struct pl2303_private *priv = usb_get_serial_port_data(port);
unsigned int arg;
if (copy_from_user(&arg, value, sizeof(int)))
@@ -516,7 +514,7 @@ static int set_modem_info (struct usb_serial_port *port, unsigned int cmd, unsig
static int get_modem_info (struct usb_serial_port *port, unsigned int *value)
{
- struct pl2303_private *priv = port->private;
+ struct pl2303_private *priv = usb_get_serial_port_data(port);
unsigned int mcr = priv->line_control;
unsigned int result;
@@ -583,8 +581,10 @@ static void pl2303_shutdown (struct usb_serial *serial)
dbg("%s", __FUNCTION__);
- for (i = 0; i < serial->num_ports; ++i)
- kfree (serial->port[i].private);
+ for (i = 0; i < serial->num_ports; ++i) {
+ kfree (usb_get_serial_port_data(&serial->port[i]));
+ usb_set_serial_port_data(&serial->port[i], NULL);
+ }
}
@@ -621,8 +621,8 @@ static void pl2303_read_int_callback (struct urb *urb, struct pt_regs *regs)
exit:
status = usb_submit_urb (urb, GFP_ATOMIC);
if (status)
- err ("%s - usb_submit_urb failed with result %d",
- __FUNCTION__, status);
+ dev_err(urb->dev->dev, "%s - usb_submit_urb failed with result %d\n",
+ __FUNCTION__, status);
}
@@ -658,7 +658,7 @@ static void pl2303_read_bulk_callback (struct urb *urb, struct pt_regs *regs)
urb->dev = serial->dev;
result = usb_submit_urb(urb, GFP_ATOMIC);
if (result)
- err("%s - failed resubmitting read urb, error %d", __FUNCTION__, result);
+ dev_err(urb->dev->dev, "%s - failed resubmitting read urb, error %d\n", __FUNCTION__, result);
return;
}
dbg("%s - unable to handle the error, exiting.", __FUNCTION__);
@@ -683,7 +683,7 @@ static void pl2303_read_bulk_callback (struct urb *urb, struct pt_regs *regs)
urb->dev = serial->dev;
result = usb_submit_urb(urb, GFP_ATOMIC);
if (result)
- err("%s - failed resubmitting read urb, error %d", __FUNCTION__, result);
+ dev_err(urb->dev->dev, "%s - failed resubmitting read urb, error %d\n", __FUNCTION__, result);
}
return;
@@ -712,7 +712,7 @@ static void pl2303_write_bulk_callback (struct urb *urb, struct pt_regs *regs)
port->write_urb->dev = port->serial->dev;
result = usb_submit_urb (port->write_urb, GFP_ATOMIC);
if (result)
- err("%s - failed resubmitting write urb, error %d", __FUNCTION__, result);
+ dev_err(urb->dev->dev, "%s - failed resubmitting write urb, error %d\n", __FUNCTION__, result);
return;
}
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
index 5098b5e63d31..d047ee66e123 100644
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -366,7 +366,7 @@ static struct usb_device_id generic_serial_ids[] = {
/* Driver structure we register with the USB core */
static struct usb_driver usb_serial_driver = {
- .name = "serial",
+ .name = "usbserial",
.probe = usb_serial_probe,
.disconnect = usb_serial_disconnect,
#ifdef CONFIG_USB_SERIAL_GENERIC
@@ -841,7 +841,7 @@ static struct usb_serial * create_serial (struct usb_device *dev,
serial = kmalloc (sizeof (*serial), GFP_KERNEL);
if (!serial) {
- err ("%s - out of memory", __FUNCTION__);
+ dev_err(dev->dev, "%s - out of memory\n", __FUNCTION__);
return NULL;
}
memset (serial, 0, sizeof(*serial));
@@ -899,14 +899,14 @@ int usb_serial_probe(struct usb_interface *interface,
serial = create_serial (dev, interface, type);
if (!serial) {
- err ("%s - out of memory", __FUNCTION__);
+ dev_err(interface->dev, "%s - out of memory\n", __FUNCTION__);
return -ENODEV;
}
/* if this device type has a probe function, call it */
if (type->probe) {
if (!try_module_get(type->owner)) {
- err ("module get failed, exiting");
+ dev_err(interface->dev, "module get failed, exiting\n");
kfree (serial);
return -EIO;
}
@@ -980,7 +980,7 @@ int usb_serial_probe(struct usb_interface *interface,
* properly during a later invocation of usb_serial_probe
*/
if (num_bulk_in == 0 || num_bulk_out == 0) {
- info("PL-2303 hack: descriptors matched but endpoints did not");
+ dev_info(interface->dev, "PL-2303 hack: descriptors matched but endpoints did not\n");
kfree (serial);
return -ENODEV;
}
@@ -989,13 +989,13 @@ int usb_serial_probe(struct usb_interface *interface,
#endif
/* found all that we need */
- info("%s converter detected", type->name);
+ dev_info(interface->dev, "%s converter detected\n", type->name);
#ifdef CONFIG_USB_SERIAL_GENERIC
if (type == &usb_serial_generic_device) {
num_ports = num_bulk_out;
if (num_ports == 0) {
- err("Generic device with no bulk out, not allowed.");
+ dev_err(interface->dev, "Generic device with no bulk out, not allowed.\n");
kfree (serial);
return -EIO;
}
@@ -1005,7 +1005,7 @@ int usb_serial_probe(struct usb_interface *interface,
/* if this device type has a calc_num_ports function, call it */
if (type->calc_num_ports) {
if (!try_module_get(type->owner)) {
- err ("module get failed, exiting");
+ dev_err(interface->dev, "module get failed, exiting\n");
kfree (serial);
return -EIO;
}
@@ -1017,7 +1017,7 @@ int usb_serial_probe(struct usb_interface *interface,
}
if (get_free_serial (serial, num_ports, &minor) == NULL) {
- err("No more free serial devices");
+ dev_err(interface->dev, "No more free serial devices\n");
kfree (serial);
return -ENOMEM;
}
@@ -1034,14 +1034,14 @@ int usb_serial_probe(struct usb_interface *interface,
port = &serial->port[i];
port->read_urb = usb_alloc_urb (0, GFP_KERNEL);
if (!port->read_urb) {
- err("No free urbs available");
+ dev_err(interface->dev, "No free urbs available\n");
goto probe_error;
}
buffer_size = endpoint->wMaxPacketSize;
port->bulk_in_endpointAddress = endpoint->bEndpointAddress;
port->bulk_in_buffer = kmalloc (buffer_size, GFP_KERNEL);
if (!port->bulk_in_buffer) {
- err("Couldn't allocate bulk_in_buffer");
+ dev_err(interface->dev, "Couldn't allocate bulk_in_buffer\n");
goto probe_error;
}
usb_fill_bulk_urb (port->read_urb, dev,
@@ -1059,7 +1059,7 @@ int usb_serial_probe(struct usb_interface *interface,
port = &serial->port[i];
port->write_urb = usb_alloc_urb(0, GFP_KERNEL);
if (!port->write_urb) {
- err("No free urbs available");
+ dev_err(interface->dev, "No free urbs available\n");
goto probe_error;
}
buffer_size = endpoint->wMaxPacketSize;
@@ -1067,7 +1067,7 @@ int usb_serial_probe(struct usb_interface *interface,
port->bulk_out_endpointAddress = endpoint->bEndpointAddress;
port->bulk_out_buffer = kmalloc (buffer_size, GFP_KERNEL);
if (!port->bulk_out_buffer) {
- err("Couldn't allocate bulk_out_buffer");
+ dev_err(interface->dev, "Couldn't allocate bulk_out_buffer\n");
goto probe_error;
}
usb_fill_bulk_urb (port->write_urb, dev,
@@ -1085,14 +1085,14 @@ int usb_serial_probe(struct usb_interface *interface,
port = &serial->port[i];
port->interrupt_in_urb = usb_alloc_urb(0, GFP_KERNEL);
if (!port->interrupt_in_urb) {
- err("No free urbs available");
+ dev_err(interface->dev, "No free urbs available\n");
goto probe_error;
}
buffer_size = endpoint->wMaxPacketSize;
port->interrupt_in_endpointAddress = endpoint->bEndpointAddress;
port->interrupt_in_buffer = kmalloc (buffer_size, GFP_KERNEL);
if (!port->interrupt_in_buffer) {
- err("Couldn't allocate interrupt_in_buffer");
+ dev_err(interface->dev, "Couldn't allocate interrupt_in_buffer\n");
goto probe_error;
}
usb_fill_int_urb (port->interrupt_in_urb, dev,
@@ -1121,7 +1121,7 @@ int usb_serial_probe(struct usb_interface *interface,
/* if this device type has an attach function, call it */
if (type->attach) {
if (!try_module_get(type->owner)) {
- err ("module get failed, exiting");
+ dev_err(interface->dev, "module get failed, exiting\n");
goto probe_error;
}
retval = type->attach (serial);
@@ -1131,8 +1131,7 @@ int usb_serial_probe(struct usb_interface *interface,
if (retval > 0) {
/* quietly accept this device, but don't bind to a serial port
* as it's about to disappear */
- dev_set_drvdata (&interface->dev, serial);
- return 0;
+ goto exit;
}
}
@@ -1151,8 +1150,9 @@ int usb_serial_probe(struct usb_interface *interface,
usb_serial_console_init (debug, minor);
+exit:
/* success */
- dev_set_drvdata (&interface->dev, serial);
+ usb_set_intfdata (interface, serial);
return 0;
@@ -1189,13 +1189,14 @@ probe_error:
void usb_serial_disconnect(struct usb_interface *interface)
{
- struct usb_serial *serial = dev_get_drvdata (&interface->dev);
+ struct usb_serial *serial = usb_get_intfdata (interface);
+ struct device *dev = &interface->dev;
struct usb_serial_port *port;
int i;
dbg ("%s", __FUNCTION__);
- dev_set_drvdata (&interface->dev, NULL);
+ usb_set_intfdata (interface, NULL);
if (serial) {
/* fail all future close/read/write/ioctl/etc calls */
for (i = 0; i < serial->num_ports; ++i) {
@@ -1252,14 +1253,13 @@ void usb_serial_disconnect(struct usb_interface *interface)
/* free up any memory that we allocated */
kfree (serial);
}
- info("device disconnected");
-
+ dev_info(*dev, "device disconnected\n");
}
struct tty_driver usb_serial_tty_driver = {
.magic = TTY_DRIVER_MAGIC,
- .driver_name = "usb-serial",
+ .driver_name = "usbserial",
#ifndef CONFIG_DEVFS_FS
.name = "ttyUSB",
#else
diff --git a/drivers/usb/serial/usb-serial.h b/drivers/usb/serial/usb-serial.h
index 236b671f685f..ccac258bba98 100644
--- a/drivers/usb/serial/usb-serial.h
+++ b/drivers/usb/serial/usb-serial.h
@@ -90,9 +90,6 @@
* @work: work queue entry for the line discipline waking up.
* @open_count: number of times this port has been opened.
* @sem: struct semaphore used to lock this structure.
- * @private: place to put any driver specific information that is needed. The
- * usb-serial driver is required to manage this data, the usb-serial core
- * will not touch this.
*
* This structure is used by the usb-serial core and drivers for the specific
* ports of a device.
@@ -120,11 +117,21 @@ struct usb_serial_port {
struct work_struct work;
int open_count;
struct semaphore sem;
- void * private;
struct device dev;
};
#define to_usb_serial_port(d) container_of(d, struct usb_serial_port, dev)
+/* get and set the port private data pointer helper functions */
+static inline void *usb_get_serial_port_data (struct usb_serial_port *port)
+{
+ return dev_get_drvdata(&port->dev);
+}
+
+static inline void usb_set_serial_port_data (struct usb_serial_port *port, void *data)
+{
+ dev_set_drvdata(&port->dev, data);
+}
+
/**
* usb_serial - structure used by the usb-serial core for a device
* @magic: magic number for internal validity of this pointer.
@@ -141,7 +148,8 @@ struct usb_serial_port {
* @port: array of struct usb_serial_port structures for the different ports.
* @private: place to put any driver specific information that is needed. The
* usb-serial driver is required to manage this data, the usb-serial core
- * will not touch this.
+ * will not touch this. Use usb_get_serial_data() and
+ * usb_set_serial_data() to access this.
*/
struct usb_serial {
int magic;
@@ -159,9 +167,18 @@ struct usb_serial {
void * private;
};
-
#define NUM_DONT_CARE (-1)
+/* get and set the serial private data pointer helper functions */
+static inline void *usb_get_serial_data (struct usb_serial *serial)
+{
+ return serial->private;
+}
+
+static inline void usb_set_serial_data (struct usb_serial *serial, void *data)
+{
+ serial->private = data;
+}
/**
* usb_serial_device_type - a structure that defines a usb serial device
diff --git a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c
index ce7fb050ad8d..296212301f69 100644
--- a/drivers/usb/serial/visor.c
+++ b/drivers/usb/serial/visor.c
@@ -303,7 +303,7 @@ static int visor_open (struct usb_serial_port *port, struct file *filp)
if (!port->read_urb) {
/* this is needed for some brain dead Sony devices */
- err ("Device lied about number of ports, please use a lower one.");
+ dev_err(port->dev, "Device lied about number of ports, please use a lower one.\n");
return -ENODEV;
}
@@ -327,8 +327,8 @@ static int visor_open (struct usb_serial_port *port, struct file *filp)
visor_read_bulk_callback, port);
result = usb_submit_urb(port->read_urb, GFP_KERNEL);
if (result) {
- err("%s - failed submitting read urb, error %d",
- __FUNCTION__, result);
+ dev_err(port->dev, "%s - failed submitting read urb, error %d\n",
+ __FUNCTION__, result);
goto exit;
}
@@ -336,8 +336,8 @@ static int visor_open (struct usb_serial_port *port, struct file *filp)
dbg("%s - adding interrupt input for treo", __FUNCTION__);
result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
if (result)
- err("%s - failed submitting interrupt urb, error %d",
- __FUNCTION__, result);
+ dev_err(port->dev, "%s - failed submitting interrupt urb, error %d\n",
+ __FUNCTION__, result);
}
exit:
return result;
@@ -363,7 +363,7 @@ static void visor_close (struct usb_serial_port *port, struct file * filp)
* device is still here */
transfer_buffer = kmalloc (0x12, GFP_KERNEL);
if (!transfer_buffer) {
- err("%s - kmalloc(%d) failed.", __FUNCTION__, 0x12);
+ dev_err(port->dev, "%s - kmalloc(%d) failed.\n", __FUNCTION__, 0x12);
} else {
/* send a shutdown message to the device */
usb_control_msg (serial->dev,
@@ -380,7 +380,7 @@ static void visor_close (struct usb_serial_port *port, struct file * filp)
usb_unlink_urb (port->interrupt_in_urb);
}
/* Uncomment the following line if you want to see some statistics in your syslog */
- /* info ("Bytes In = %d Bytes Out = %d", bytes_in, bytes_out); */
+ /* dev_info (port->dev, "Bytes In = %d Bytes Out = %d\n", bytes_in, bytes_out); */
}
@@ -395,13 +395,13 @@ static int visor_write (struct usb_serial_port *port, int from_user, const unsig
buffer = kmalloc (count, GFP_ATOMIC);
if (!buffer) {
- err ("out of memory");
+ dev_err(port->dev, "out of memory\n");
return -ENOMEM;
}
urb = usb_alloc_urb(0, GFP_ATOMIC);
if (!urb) {
- err ("no more free urbs");
+ dev_err(port->dev, "no more free urbs\n");
kfree (buffer);
return -ENOMEM;
}
@@ -427,8 +427,8 @@ static int visor_write (struct usb_serial_port *port, int from_user, const unsig
/* send it down the pipe */
status = usb_submit_urb(urb, GFP_ATOMIC);
if (status) {
- err("%s - usb_submit_urb(write bulk) failed with status = %d",
- __FUNCTION__, status);
+ dev_err(port->dev, "%s - usb_submit_urb(write bulk) failed with status = %d\n",
+ __FUNCTION__, status);
count = status;
} else {
bytes_out += count;
@@ -539,7 +539,7 @@ static void visor_read_bulk_callback (struct urb *urb, struct pt_regs *regs)
visor_read_bulk_callback, port);
result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
if (result)
- err("%s - failed resubmitting read urb, error %d", __FUNCTION__, result);
+ dev_err(port->dev, "%s - failed resubmitting read urb, error %d\n", __FUNCTION__, result);
return;
}
@@ -577,8 +577,8 @@ static void visor_read_int_callback (struct urb *urb, struct pt_regs *regs)
exit:
result = usb_submit_urb (urb, GFP_ATOMIC);
if (result)
- err("%s - Error %d submitting interrupt urb",
- __FUNCTION__, result);
+ dev_err(urb->dev->dev, "%s - Error %d submitting interrupt urb\n",
+ __FUNCTION__, result);
}
static void visor_throttle (struct usb_serial_port *port)
@@ -597,18 +597,19 @@ static void visor_unthrottle (struct usb_serial_port *port)
port->read_urb->dev = port->serial->dev;
result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
if (result)
- err("%s - failed submitting read urb, error %d", __FUNCTION__, result);
+ dev_err(port->dev, "%s - failed submitting read urb, error %d\n", __FUNCTION__, result);
}
static int visor_probe (struct usb_serial *serial)
{
+ struct device *dev = &serial->dev->dev;
int response;
int i;
int num_ports;
unsigned char *transfer_buffer = kmalloc (256, GFP_KERNEL);
if (!transfer_buffer) {
- err("%s - kmalloc(%d) failed.", __FUNCTION__, 256);
+ dev_err(*dev, "%s - kmalloc(%d) failed.\n", __FUNCTION__, 256);
return -ENOMEM;
}
@@ -621,14 +622,14 @@ static int visor_probe (struct usb_serial *serial)
response = usb_control_msg (serial->dev, usb_rcvctrlpipe(serial->dev, 0), VISOR_GET_CONNECTION_INFORMATION,
0xc2, 0x0000, 0x0000, transfer_buffer, 0x12, 300);
if (response < 0) {
- err("%s - error getting connection information", __FUNCTION__);
+ dev_err(*dev, "%s - error getting connection information\n", __FUNCTION__);
} else {
struct visor_connection_info *connection_info = (struct visor_connection_info *)transfer_buffer;
char *string;
le16_to_cpus(&connection_info->num_ports);
num_ports = connection_info->num_ports;
- info("%s: Number of ports: %d", serial->type->name, connection_info->num_ports);
+ dev_info(*dev, "%s: Number of ports: %d\n", serial->type->name, connection_info->num_ports);
for (i = 0; i < num_ports; ++i) {
switch (connection_info->connections[i].port_function_id) {
case VISOR_FUNCTION_GENERIC:
@@ -650,10 +651,10 @@ static int visor_probe (struct usb_serial *serial)
string = "unknown";
break;
}
- info("%s: port %d, is for %s use", serial->type->name,
- connection_info->connections[i].port, string);
+ dev_info(*dev, "%s: port %d, is for %s use\n", serial->type->name,
+ connection_info->connections[i].port, string);
/* save off our num_ports info so that we can use it in the calc_num_ports call */
- serial->private = (void *)(long)num_ports;
+ usb_set_serial_data(serial, (void *)(long)num_ports);
}
}
@@ -666,7 +667,7 @@ static int visor_probe (struct usb_serial *serial)
0xc2, 0x0000, 0x0000, transfer_buffer,
0x14, 300);
if (response < 0) {
- err("%s - error getting first unknown palm command", __FUNCTION__);
+ dev_err(*dev, "%s - error getting first unknown palm command\n", __FUNCTION__);
} else {
usb_serial_debug_data (__FILE__, __FUNCTION__, 0x14, transfer_buffer);
}
@@ -675,7 +676,7 @@ static int visor_probe (struct usb_serial *serial)
0xc2, 0x0000, 0x0000, transfer_buffer,
0x14, 300);
if (response < 0) {
- err("%s - error getting second unknown palm command", __FUNCTION__);
+ dev_err(*dev, "%s - error getting second unknown palm command\n", __FUNCTION__);
} else {
usb_serial_debug_data (__FILE__, __FUNCTION__, 0x14, transfer_buffer);
}
@@ -685,7 +686,7 @@ static int visor_probe (struct usb_serial *serial)
response = usb_control_msg (serial->dev, usb_rcvctrlpipe(serial->dev, 0), VISOR_REQUEST_BYTES_AVAILABLE,
0xc2, 0x0000, 0x0005, transfer_buffer, 0x02, 300);
if (response < 0) {
- err("%s - error getting bytes available request", __FUNCTION__);
+ dev_err(*dev, "%s - error getting bytes available request\n", __FUNCTION__);
}
kfree (transfer_buffer);
@@ -696,17 +697,17 @@ static int visor_probe (struct usb_serial *serial)
static int visor_calc_num_ports (struct usb_serial *serial)
{
- int num_ports = 0;
+ int num_ports = (int)(long)(usb_get_serial_data(serial));
+
+ if (num_ports)
+ usb_set_serial_data(serial, NULL);
- if (serial->private) {
- num_ports = (int)(long)serial->private;
- serial->private = NULL;
- }
return num_ports;
}
static int clie_3_5_startup (struct usb_serial *serial)
{
+ struct device *dev = &serial->dev->dev;
int result;
u8 data;
@@ -721,11 +722,11 @@ static int clie_3_5_startup (struct usb_serial *serial)
USB_REQ_GET_CONFIGURATION, USB_DIR_IN,
0, 0, &data, 1, HZ * 3);
if (result < 0) {
- err("%s: get config number failed: %d", __FUNCTION__, result);
+ dev_err(*dev, "%s: get config number failed: %d\n", __FUNCTION__, result);
return result;
}
if (result != 1) {
- err("%s: get config number bad return length: %d", __FUNCTION__, result);
+ dev_err(*dev, "%s: get config number bad return length: %d\n", __FUNCTION__, result);
return -EIO;
}
@@ -735,11 +736,11 @@ static int clie_3_5_startup (struct usb_serial *serial)
USB_DIR_IN | USB_RECIP_INTERFACE,
0, 0, &data, 1, HZ * 3);
if (result < 0) {
- err("%s: get interface number failed: %d", __FUNCTION__, result);
+ dev_err(*dev, "%s: get interface number failed: %d\n", __FUNCTION__, result);
return result;
}
if (result != 1) {
- err("%s: get interface number bad return length: %d", __FUNCTION__, result);
+ dev_err(*dev, "%s: get interface number bad return length: %d\n", __FUNCTION__, result);
return -EIO;
}
diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c
index 6b4df93d85c4..b85d613bc6cc 100644
--- a/drivers/usb/serial/whiteheat.c
+++ b/drivers/usb/serial/whiteheat.c
@@ -464,7 +464,7 @@ static int whiteheat_attach (struct usb_serial *serial)
list_add(&wrap->list, &info->tx_urbs_free);
}
- port->private = info;
+ usb_set_serial_port_data(port, info);
}
command_info = (struct whiteheat_command_private *)kmalloc(sizeof(struct whiteheat_command_private), GFP_KERNEL);
@@ -476,7 +476,7 @@ static int whiteheat_attach (struct usb_serial *serial)
spin_lock_init(&command_info->lock);
command_info->port_running = 0;
init_waitqueue_head(&command_info->wait_command);
- command_port->private = command_info;
+ usb_set_serial_port_data(command_port, command_info);
command_port->write_urb->complete = command_port_write_callback;
command_port->read_urb->complete = command_port_read_callback;
@@ -492,7 +492,7 @@ no_firmware:
no_command_private:
for (i = serial->num_ports - 1; i >= 0; i--) {
port = &serial->port[i];
- info = port->private;
+ info = usb_get_serial_port_data(port);
for (j = urb_pool_size - 1; j >= 0; j--) {
tmp = list_first(&info->tx_urbs_free);
list_del(tmp);
@@ -539,11 +539,11 @@ static void whiteheat_shutdown (struct usb_serial *serial)
/* free up our private data for our command port */
command_port = &serial->port[COMMAND_PORT];
- kfree (command_port->private);
+ kfree (usb_get_serial_port_data(command_port));
for (i = 0; i < serial->num_ports; i++) {
port = &serial->port[i];
- info = port->private;
+ info = usb_get_serial_port_data(port);
list_for_each_safe(tmp, tmp2, &info->rx_urbs_free) {
list_del(tmp);
wrap = list_entry(tmp, struct whiteheat_urb_wrap, list);
@@ -620,7 +620,7 @@ exit:
static void whiteheat_close(struct usb_serial_port *port, struct file * filp)
{
- struct whiteheat_private *info = port->private;
+ struct whiteheat_private *info = usb_get_serial_port_data(port);
struct whiteheat_urb_wrap *wrap;
struct urb *urb;
struct list_head *tmp;
@@ -686,7 +686,7 @@ static void whiteheat_close(struct usb_serial_port *port, struct file * filp)
static int whiteheat_write(struct usb_serial_port *port, int from_user, const unsigned char *buf, int count)
{
struct usb_serial *serial = port->serial;
- struct whiteheat_private *info = port->private;
+ struct whiteheat_private *info = usb_get_serial_port_data(port);
struct whiteheat_urb_wrap *wrap;
struct urb *urb;
int result;
@@ -749,7 +749,7 @@ static int whiteheat_write(struct usb_serial_port *port, int from_user, const un
static int whiteheat_write_room(struct usb_serial_port *port)
{
- struct whiteheat_private *info = port->private;
+ struct whiteheat_private *info = usb_get_serial_port_data(port);
struct list_head *tmp;
int room = 0;
unsigned long flags;
@@ -769,7 +769,7 @@ static int whiteheat_write_room(struct usb_serial_port *port)
static int whiteheat_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg)
{
- struct whiteheat_private *info = (struct whiteheat_private *)port->private;
+ struct whiteheat_private *info = usb_get_serial_port_data(port);
unsigned int modem_signals = 0;
struct serial_struct serstruct;
@@ -903,7 +903,7 @@ static void whiteheat_break_ctl(struct usb_serial_port *port, int break_state) {
static int whiteheat_chars_in_buffer(struct usb_serial_port *port)
{
- struct whiteheat_private *info = port->private;
+ struct whiteheat_private *info = usb_get_serial_port_data(port);
struct list_head *tmp;
struct whiteheat_urb_wrap *wrap;
int chars = 0;
@@ -925,7 +925,7 @@ static int whiteheat_chars_in_buffer(struct usb_serial_port *port)
static void whiteheat_throttle (struct usb_serial_port *port)
{
- struct whiteheat_private *info = (struct whiteheat_private *)port->private;
+ struct whiteheat_private *info = usb_get_serial_port_data(port);
unsigned long flags;
dbg("%s - port %d", __FUNCTION__, port->number);
@@ -940,7 +940,7 @@ static void whiteheat_throttle (struct usb_serial_port *port)
static void whiteheat_unthrottle (struct usb_serial_port *port)
{
- struct whiteheat_private *info = (struct whiteheat_private *)port->private;
+ struct whiteheat_private *info = usb_get_serial_port_data(port);
int actually_throttled;
unsigned long flags;
@@ -999,7 +999,7 @@ static void command_port_read_callback (struct urb *urb, struct pt_regs *regs)
usb_serial_debug_data (__FILE__, __FUNCTION__, urb->actual_length, data);
- command_info = (struct whiteheat_command_private *)command_port->private;
+ command_info = usb_get_serial_port_data(command_port);
if (!command_info) {
dbg ("%s - command_info is NULL, exiting.", __FUNCTION__);
return;
@@ -1038,7 +1038,7 @@ static void whiteheat_read_callback(struct urb *urb, struct pt_regs *regs)
struct usb_serial *serial = get_usb_serial (port, __FUNCTION__);
struct whiteheat_urb_wrap *wrap;
unsigned char *data = urb->transfer_buffer;
- struct whiteheat_private *info = (struct whiteheat_private *)port->private;
+ struct whiteheat_private *info = usb_get_serial_port_data(port);
dbg("%s - port %d", __FUNCTION__, port->number);
@@ -1087,7 +1087,7 @@ static void whiteheat_write_callback(struct urb *urb, struct pt_regs *regs)
{
struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
struct usb_serial *serial = get_usb_serial (port, __FUNCTION__);
- struct whiteheat_private *info = port->private;
+ struct whiteheat_private *info = usb_get_serial_port_data(port);
struct whiteheat_urb_wrap *wrap;
dbg("%s - port %d", __FUNCTION__, port->number);
@@ -1135,7 +1135,7 @@ static int firm_send_command (struct usb_serial_port *port, __u8 command, __u8 *
dbg("%s - command %d", __FUNCTION__, command);
command_port = &port->serial->port[COMMAND_PORT];
- command_info = (struct whiteheat_command_private *)command_port->private;
+ command_info = usb_get_serial_port_data(command_port);
spin_lock_irqsave(&command_info->lock, flags);
command_info->command_finished = FALSE;
@@ -1175,7 +1175,7 @@ static int firm_send_command (struct usb_serial_port *port, __u8 command, __u8 *
dbg("%s - command completed.", __FUNCTION__);
switch (command) {
case WHITEHEAT_GET_DTR_RTS:
- info = (struct whiteheat_private *)port->private;
+ info = usb_get_serial_port_data(port);
memcpy(&info->mcr, command_info->result_buffer, sizeof(struct whiteheat_dr_info));
break;
}
@@ -1339,7 +1339,7 @@ static int start_command_port(struct usb_serial *serial)
int retval = 0;
command_port = &serial->port[COMMAND_PORT];
- command_info = (struct whiteheat_command_private *)command_port->private;
+ command_info = usb_get_serial_port_data(command_port);
spin_lock_irqsave(&command_info->lock, flags);
if (!command_info->port_running) {
/* Work around HCD bugs */
@@ -1367,7 +1367,7 @@ static void stop_command_port(struct usb_serial *serial)
unsigned long flags;
command_port = &serial->port[COMMAND_PORT];
- command_info = (struct whiteheat_command_private *)command_port->private;
+ command_info = usb_get_serial_port_data(command_port);
spin_lock_irqsave(&command_info->lock, flags);
command_info->port_running--;
if (!command_info->port_running)
@@ -1376,8 +1376,9 @@ static void stop_command_port(struct usb_serial *serial)
}
-static int start_port_read(struct usb_serial_port *port) {
- struct whiteheat_private *info = port->private;
+static int start_port_read(struct usb_serial_port *port)
+{
+ struct whiteheat_private *info = usb_get_serial_port_data(port);
struct whiteheat_urb_wrap *wrap;
struct urb *urb;
int retval = 0;
@@ -1413,7 +1414,8 @@ static int start_port_read(struct usb_serial_port *port) {
}
-static struct whiteheat_urb_wrap *urb_to_wrap(struct urb* urb, struct list_head *head) {
+static struct whiteheat_urb_wrap *urb_to_wrap(struct urb* urb, struct list_head *head)
+{
struct whiteheat_urb_wrap *wrap;
struct list_head *tmp;
@@ -1427,14 +1429,16 @@ static struct whiteheat_urb_wrap *urb_to_wrap(struct urb* urb, struct list_head
}
-static struct list_head *list_first(struct list_head *head) {
+static struct list_head *list_first(struct list_head *head)
+{
return head->next;
}
-static void rx_data_softint(void *private) {
+static void rx_data_softint(void *private)
+{
struct usb_serial_port *port = (struct usb_serial_port *)private;
- struct whiteheat_private *info = port->private;
+ struct whiteheat_private *info = usb_get_serial_port_data(port);
struct tty_struct *tty = port->tty;
struct whiteheat_urb_wrap *wrap;
struct urb *urb;
diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
index bf216fbd5ba7..c61df0831c23 100644
--- a/drivers/usb/storage/usb.c
+++ b/drivers/usb/storage/usb.c
@@ -1036,7 +1036,7 @@ static int storage_probe(struct usb_interface *intf,
"USB Mass Storage device found at %d\n", dev->devnum);
/* save a pointer to our structure */
- dev_set_drvdata (&intf->dev, ss);
+ usb_set_intfdata(intf, ss);
return 0;
/* we come here if there are any problems */
@@ -1053,11 +1053,11 @@ static int storage_probe(struct usb_interface *intf,
/* Handle a disconnect event from the USB core */
static void storage_disconnect(struct usb_interface *intf)
{
- struct us_data *ss = dev_get_drvdata (&intf->dev);
+ struct us_data *ss = usb_get_intfdata(intf);
US_DEBUGP("storage_disconnect() called\n");
- dev_set_drvdata (&intf->dev, NULL);
+ usb_set_intfdata(intf, NULL);
/* this is the odd case -- we disconnected but weren't using it */
if (!ss) {
diff --git a/drivers/usb/usb-skeleton.c b/drivers/usb/usb-skeleton.c
index 3ca9355d4c5e..db6942835c2f 100644
--- a/drivers/usb/usb-skeleton.c
+++ b/drivers/usb/usb-skeleton.c
@@ -235,7 +235,7 @@ static int skel_open (struct inode *inode, struct file *file)
return -ENODEV;
}
- dev = dev_get_drvdata (&interface->dev);
+ dev = usb_get_intfdata(interface);
if (!dev)
return -ENODEV;
@@ -582,7 +582,7 @@ exit_minor:
exit:
if (dev) {
- dev_set_drvdata (&interface->dev, dev);
+ usb_set_intfdata (interface, dev);
return 0;
}
return -ENODEV;
@@ -599,8 +599,8 @@ static void skel_disconnect(struct usb_interface *interface)
struct usb_skel *dev;
int minor;
- dev = dev_get_drvdata (&interface->dev);
- dev_set_drvdata (&interface->dev, NULL);
+ dev = usb_get_intfdata (interface);
+ usb_set_intfdata (interface, NULL);
if (!dev)
return;
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index d9767337fe1f..7faee8111c81 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -48,7 +48,7 @@ obj-$(CONFIG_FB_RETINAZ3) += retz3fb.o
obj-$(CONFIG_FB_CLGEN) += clgenfb.o
obj-$(CONFIG_FB_TRIDENT) += tridentfb.o
obj-$(CONFIG_FB_S3TRIO) += S3triofb.o
-obj-$(CONFIG_FB_TGA) += tgafb.o
+obj-$(CONFIG_FB_TGA) += tgafb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
obj-$(CONFIG_FB_VESA) += vesafb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
obj-$(CONFIG_FB_VGA16) += vga16fb.o cfbfillrect.o cfbcopyarea.o \
cfbimgblt.o vgastate.o
@@ -76,7 +76,6 @@ obj-$(CONFIG_FB_SIS) += sis/
obj-$(CONFIG_FB_ATY) += aty/ cfbimgblt.o
obj-$(CONFIG_FB_SUN3) += sun3fb.o
-obj-$(CONFIG_FB_BWTWO) += bwtwofb.o
obj-$(CONFIG_FB_HGA) += hgafb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
obj-$(CONFIG_FB_SA1100) += sa1100fb.o
obj-$(CONFIG_FB_VIRTUAL) += vfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
diff --git a/drivers/video/atafb.c b/drivers/video/atafb.c
index fd55dbcabf6f..1ef989cd66be 100644
--- a/drivers/video/atafb.c
+++ b/drivers/video/atafb.c
@@ -57,6 +57,7 @@
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <asm/setup.h>
#include <asm/uaccess.h>
@@ -2050,8 +2051,7 @@ static void st_ovsc_switch(void)
if (!(atari_switches & ATARI_SWITCH_OVSC_MASK))
return;
- save_flags(flags);
- cli();
+ local_irq_save(flags);
mfp.tim_ct_b = 0x10;
mfp.active_edge |= 8;
@@ -2079,7 +2079,7 @@ static void st_ovsc_switch(void)
((atari_switches&ATARI_SWITCH_OVSC_SND6) ? 0x40:0) |
((atari_switches&ATARI_SWITCH_OVSC_SND7) ? 0x80:0);
}
- restore_flags(flags);
+ local_irq_restore(flags);
}
/* ------------------- External Video ---------------------- */
diff --git a/drivers/video/aty128fb.c b/drivers/video/aty128fb.c
index 69f2d8d618c3..5545dbdb50ac 100644
--- a/drivers/video/aty128fb.c
+++ b/drivers/video/aty128fb.c
@@ -1415,7 +1415,7 @@ aty128fb_setup(char *options)
}
#endif
#ifdef CONFIG_ALL_PPC
- /* vmode and cmode depreciated */
+ /* vmode and cmode deprecated */
if (!strncmp(this_opt, "vmode:", 6)) {
unsigned int vmode = simple_strtoul(this_opt+6, NULL, 0);
if (vmode > 0 && vmode <= VMODE_MAX)
diff --git a/drivers/video/cfbcopyarea.c b/drivers/video/cfbcopyarea.c
index 43c030ff9ad7..f99a1692d5cb 100644
--- a/drivers/video/cfbcopyarea.c
+++ b/drivers/video/cfbcopyarea.c
@@ -38,7 +38,7 @@
#define BYTES_PER_LONG 4
#else
#define FB_WRITEL fb_writeq
-#define FB_READL fb_readq(x)
+#define FB_READL fb_readq
#define SHIFT_PER_LONG 6
#define BYTES_PER_LONG 8
#endif
diff --git a/drivers/video/cfbimgblt.c b/drivers/video/cfbimgblt.c
index 11a87a694a85..f47b173b383e 100644
--- a/drivers/video/cfbimgblt.c
+++ b/drivers/video/cfbimgblt.c
@@ -21,13 +21,13 @@
*
* FIXME
* The code for 24 bit is horrible. It copies byte by byte size instead of
- * longs like the other sizes. Needs to be optimized.
+ * words like the other sizes. Needs to be optimized.
*
* Tony:
* Incorporate mask tables similar to fbcon-cfb*.c in 2.4 API. This speeds
* up the code significantly.
*
- * Code for depths not multiples of BITS_PER_LONG is still kludgy, which is
+ * Code for depths not multiples of BITS_PER_WORD is still kludgy, which is
* still processed a bit at a time.
*
* Also need to add code to deal with cards endians that are different than
@@ -48,7 +48,11 @@
#define DPRINTK(fmt, args...)
#endif
-static u32 cfb_tab8[] = {
+/* The following code can *not* handle a 64-bit long. */
+#define WORD u32
+#define BITS_PER_WORD 32
+
+static WORD const cfb_tab8[] = {
#if defined(__BIG_ENDIAN)
0x00000000,0x000000ff,0x0000ff00,0x0000ffff,
0x00ff0000,0x00ff00ff,0x00ffff00,0x00ffffff,
@@ -64,7 +68,7 @@ static u32 cfb_tab8[] = {
#endif
};
-static u32 cfb_tab16[] = {
+static WORD const cfb_tab16[] = {
#if defined(__BIG_ENDIAN)
0x00000000, 0x0000ffff, 0xffff0000, 0xffffffff
#elif defined(__LITTLE_ENDIAN)
@@ -74,11 +78,11 @@ static u32 cfb_tab16[] = {
#endif
};
-static u32 cfb_tab32[] = {
+static WORD const cfb_tab32[] = {
0x00000000, 0xffffffff
};
-#if BITS_PER_LONG == 32
+#if BITS_PER_WORD == 32
#define FB_WRITEL fb_writel
#define FB_READL fb_readl
#else
@@ -87,7 +91,7 @@ static u32 cfb_tab32[] = {
#endif
#if defined (__BIG_ENDIAN)
-#define LEFT_POS(bpp) (BITS_PER_LONG - bpp)
+#define LEFT_POS(bpp) (BITS_PER_WORD - bpp)
#define NEXT_POS(pos, bpp) ((pos) -= (bpp))
#define SHIFT_HIGH(val, bits) ((val) >> (bits))
#define SHIFT_LOW(val, bits) ((val) << (bits))
@@ -99,25 +103,25 @@ static u32 cfb_tab32[] = {
#endif
static inline void color_imageblit(struct fb_image *image, struct fb_info *p, u8 *dst1,
- unsigned long start_index, unsigned long pitch_index)
+ WORD start_index, WORD pitch_index)
{
/* Draw the penguin */
int i, n;
- unsigned long bitmask = SHIFT_LOW(~0UL, BITS_PER_LONG - p->var.bits_per_pixel);
- unsigned long *palette = (unsigned long *) p->pseudo_palette;
- unsigned long *dst, *dst2, color = 0, val, shift;
- unsigned long null_bits = BITS_PER_LONG - p->var.bits_per_pixel;
+ WORD bitmask = SHIFT_LOW(~0UL, BITS_PER_WORD - p->var.bits_per_pixel);
+ u32 *palette = (u32 *) p->pseudo_palette;
+ WORD *dst, *dst2, color = 0, val, shift;
+ WORD null_bits = BITS_PER_WORD - p->var.bits_per_pixel;
u8 *src = image->data;
- dst2 = (unsigned long *) dst1;
+ dst2 = (WORD *) dst1;
for (i = image->height; i--; ) {
n = image->width;
- dst = (unsigned long *) dst1;
+ dst = (WORD *) dst1;
shift = 0;
val = 0;
if (start_index) {
- unsigned long start_mask = ~(SHIFT_HIGH(~0UL, start_index));
+ WORD start_mask = ~(SHIFT_HIGH(~0UL, start_index));
val = FB_READL(dst) & start_mask;
shift = start_index;
@@ -134,14 +138,14 @@ static inline void color_imageblit(struct fb_image *image, struct fb_info *p, u8
if (shift == null_bits)
val = 0;
else
- val = SHIFT_LOW(color, BITS_PER_LONG - shift);
+ val = SHIFT_LOW(color, BITS_PER_WORD - shift);
}
shift += p->var.bits_per_pixel;
- shift &= (BITS_PER_LONG - 1);
+ shift &= (BITS_PER_WORD - 1);
src++;
}
if (shift) {
- unsigned long end_mask = SHIFT_HIGH(~0UL, shift);
+ WORD end_mask = SHIFT_HIGH(~0UL, shift);
FB_WRITEL((FB_READL(dst) & end_mask) | val, dst);
}
@@ -149,35 +153,35 @@ static inline void color_imageblit(struct fb_image *image, struct fb_info *p, u8
if (pitch_index) {
dst2 += p->fix.line_length;
dst1 = (char *) dst2;
- (unsigned long) dst1 &= ~(sizeof(unsigned long) - 1);
+ (size_t) dst1 &= ~(sizeof(WORD) - 1);
start_index += pitch_index;
- start_index &= BITS_PER_LONG - 1;
+ start_index &= BITS_PER_WORD - 1;
}
}
}
static inline void slow_imageblit(struct fb_image *image, struct fb_info *p, u8 *dst1,
- unsigned long fgcolor, unsigned long bgcolor,
- unsigned long start_index, unsigned long pitch_index)
+ WORD fgcolor, WORD bgcolor,
+ WORD start_index, WORD pitch_index)
{
- unsigned long i, j, l = 8;
- unsigned long shift, color, bpp = p->var.bits_per_pixel;
- unsigned long *dst, *dst2, val, pitch = p->fix.line_length;
- unsigned long null_bits = BITS_PER_LONG - bpp;
+ WORD i, j, l = 8;
+ WORD shift, color, bpp = p->var.bits_per_pixel;
+ WORD *dst, *dst2, val, pitch = p->fix.line_length;
+ WORD null_bits = BITS_PER_WORD - bpp;
u8 *src = image->data;
- dst2 = (unsigned long *) dst1;
+ dst2 = (WORD *) dst1;
for (i = image->height; i--; ) {
shift = 0;
val = 0;
j = image->width;
- dst = (unsigned long *) dst1;
+ dst = (WORD *) dst1;
/* write leading bits */
if (start_index) {
- unsigned long start_mask = ~(SHIFT_HIGH(~0UL, start_index));
+ WORD start_mask = ~(SHIFT_HIGH(~0UL, start_index));
val = FB_READL(dst) & start_mask;
shift = start_index;
@@ -196,15 +200,15 @@ static inline void slow_imageblit(struct fb_image *image, struct fb_info *p, u8
if (shift == null_bits)
val = 0;
else
- val = SHIFT_LOW(color, BITS_PER_LONG - shift);
+ val = SHIFT_LOW(color, BITS_PER_WORD - shift);
}
shift += bpp;
- shift &= (BITS_PER_LONG - 1);
+ shift &= (BITS_PER_WORD - 1);
if (!l) { l = 8; src++; };
}
/* write trailing bits */
if (shift) {
- unsigned long end_mask = SHIFT_HIGH(~0UL, shift);
+ WORD end_mask = SHIFT_HIGH(~0UL, shift);
FB_WRITEL((FB_READL(dst) & end_mask) | val, dst);
}
@@ -213,24 +217,24 @@ static inline void slow_imageblit(struct fb_image *image, struct fb_info *p, u8
if (pitch_index) {
dst2 += pitch;
dst1 = (char *) dst2;
- (unsigned long) dst1 &= ~(sizeof(unsigned long) - 1);
+ (size_t) dst1 &= ~(sizeof(WORD) - 1);
start_index += pitch_index;
- start_index &= BITS_PER_LONG - 1;
+ start_index &= BITS_PER_WORD - 1;
}
}
}
static inline void fast_imageblit(struct fb_image *image, struct fb_info *p, u8 *dst1,
- unsigned long fgcolor, unsigned long bgcolor)
+ WORD fgcolor, WORD bgcolor)
{
int i, j, k, l = 8, n;
- unsigned long bit_mask, end_mask, eorx;
- unsigned long fgx = fgcolor, bgx = bgcolor, pad, bpp = p->var.bits_per_pixel;
- unsigned long tmp = (1 << bpp) - 1;
- unsigned long ppw = BITS_PER_LONG/bpp, ppos;
- unsigned long *dst;
+ WORD bit_mask, end_mask, eorx;
+ WORD fgx = fgcolor, bgx = bgcolor, pad, bpp = p->var.bits_per_pixel;
+ WORD tmp = (1 << bpp) - 1;
+ WORD ppw = BITS_PER_WORD/bpp, ppos;
+ WORD *dst;
u32 *tab = NULL;
char *src = image->data;
@@ -263,7 +267,7 @@ static inline void fast_imageblit(struct fb_image *image, struct fb_info *p, u8
k = image->width/ppw;
for (i = image->height; i--; ) {
- dst = (unsigned long *) dst1;
+ dst = (WORD *) dst1;
for (j = k; j--; ) {
l -= ppw;
@@ -291,8 +295,8 @@ static inline void fast_imageblit(struct fb_image *image, struct fb_info *p, u8
void cfb_imageblit(struct fb_info *p, struct fb_image *image)
{
int x2, y2, vxres, vyres;
- unsigned long fgcolor, bgcolor, start_index, bitstart, pitch_index = 0;
- unsigned long bpl = sizeof(unsigned long), bpp = p->var.bits_per_pixel;
+ WORD fgcolor, bgcolor, start_index, bitstart, pitch_index = 0;
+ WORD bpl = sizeof(WORD), bpp = p->var.bits_per_pixel;
u8 *dst1;
vxres = p->var.xres_virtual;
@@ -315,7 +319,7 @@ void cfb_imageblit(struct fb_info *p, struct fb_image *image)
image->height = y2 - image->dy;
bitstart = (image->dy * p->fix.line_length * 8) + (image->dx * bpp);
- start_index = bitstart & (BITS_PER_LONG - 1);
+ start_index = bitstart & (BITS_PER_WORD - 1);
pitch_index = (p->fix.line_length & (bpl - 1)) * 8;
bitstart /= 8;
@@ -332,7 +336,7 @@ void cfb_imageblit(struct fb_info *p, struct fb_image *image)
bgcolor = image->bg_color;
}
- if (BITS_PER_LONG % bpp == 0 && !start_index && !pitch_index &&
+ if (BITS_PER_WORD % bpp == 0 && !start_index && !pitch_index &&
bpp >= 8 && bpp <= 32 && (image->width & 7) == 0)
fast_imageblit(image, p, dst1, fgcolor, bgcolor);
else
diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c
index 6b3bc39bc559..57cd3ca0a32d 100644
--- a/drivers/video/console/fbcon.c
+++ b/drivers/video/console/fbcon.c
@@ -75,6 +75,7 @@
#include <linux/selection.h>
#include <linux/smp.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <asm/irq.h>
#include <asm/system.h>
diff --git a/drivers/video/console/font.h b/drivers/video/console/font.h
index d612657374d0..16564d51d28e 100644
--- a/drivers/video/console/font.h
+++ b/drivers/video/console/font.h
@@ -8,18 +8,10 @@
* for more details.
*/
-#ifndef _VIDEO_FONT_H
-#define _VIDEO_FONT_H
+#ifndef _VIDEO_CONSOLE_FONT_H
+#define _VIDEO_CONSOLE_FONT_H
-#include <linux/types.h>
-
-struct font_desc {
- int idx;
- char *name;
- int width, height;
- void *data;
- int pref;
-};
+#include <video/font.h> /* struct font_desc */
#define VGA8x8_IDX 0
#define VGA8x16_IDX 1
@@ -50,4 +42,4 @@ extern struct font_desc *get_default_font(int xres, int yres);
/* Max. length for the name of a predefined font */
#define MAX_FONT_NAME 32
-#endif /* _VIDEO_FONT_H */
+#endif /* _VIDEO_CONSOLE_FONT_H */
diff --git a/drivers/video/tgafb.c b/drivers/video/tgafb.c
index 325f0ab1ae6c..230f0c971e66 100644
--- a/drivers/video/tgafb.c
+++ b/drivers/video/tgafb.c
@@ -1,1009 +1,725 @@
/*
* linux/drivers/video/tgafb.c -- DEC 21030 TGA frame buffer device
*
- * Copyright (C) 1999,2000 Martin Lucina, Tom Zerucha
- *
- * $Id: tgafb.c,v 1.12.2.3 2000/04/04 06:44:56 mato Exp $
- *
- * This driver is partly based on the original TGA framebuffer device, which
- * was partly based on the original TGA console driver, which are
- *
- * Copyright (C) 1997 Geert Uytterhoeven
* Copyright (C) 1995 Jay Estabrook
+ * Copyright (C) 1997 Geert Uytterhoeven
+ * Copyright (C) 1999,2000 Martin Lucina, Tom Zerucha
+ * Copyright (C) 2002 Richard Henderson
*
* 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.
*/
-/* KNOWN PROBLEMS/TO DO ===================================================== *
- *
- * - How to set a single color register on 24-plane cards?
- *
- * - Hardware cursor/other text acceleration methods
- *
- * - Some redraws can stall kernel for several seconds
- * [This should now be solved by the fast memmove() patch in 2.3.6]
- *
- * KNOWN PROBLEMS/TO DO ==================================================== */
-
#include <linux/module.h>
-#include <linux/sched.h>
#include <linux/kernel.h>
+#include <linux/sched.h>
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/mm.h>
#include <linux/tty.h>
#include <linux/slab.h>
-#include <linux/vmalloc.h>
#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/fb.h>
#include <linux/init.h>
-#include <linux/pci.h>
+#include <linux/fb.h>
#include <linux/selection.h>
-#include <linux/console.h>
+#include <linux/pci.h>
#include <asm/io.h>
+#include <video/tgafb.h>
-#include <video/fbcon.h>
-#include <video/fbcon-cfb8.h>
-#include <video/fbcon-cfb32.h>
-#include "tgafb.h"
-
-
- /*
- * Global declarations
- */
-
-static struct tgafb_info fb_info;
-static struct tgafb_par current_par;
-static int current_par_valid = 0;
-static struct display disp;
-static char default_fontname[40] __initdata = { 0 };
-static struct fb_var_screeninfo default_var;
-static int default_var_valid = 0;
+/*
+ * Local functions.
+ */
-static struct { u_char red, green, blue, pad; } palette[256];
-#ifdef FBCON_HAS_CFB32
-static u32 fbcon_cfb32_cmap[16];
+static int tgafb_check_var(struct fb_var_screeninfo *, struct fb_info *);
+static int tgafb_set_par(struct fb_info *);
+static void tgafb_set_pll(struct tga_par *, int);
+static int tgafb_setcolreg(unsigned, unsigned, unsigned, unsigned,
+ unsigned, struct fb_info *);
+static int tgafb_blank(int, struct fb_info *);
+static void tgafb_init_fix(struct fb_info *);
+static int tgafb_pci_register(struct pci_dev *, const struct pci_device_id *);
+#ifdef MODULE
+static void tgafb_pci_unregister(struct pci_dev *);
#endif
+static const char *mode_option = "640x480@60";
- /*
- * Hardware presets
- */
-static unsigned int fb_offset_presets[4] = {
- TGA_8PLANE_FB_OFFSET,
- TGA_24PLANE_FB_OFFSET,
- 0xffffffff,
- TGA_24PLUSZ_FB_OFFSET
-};
+/*
+ * Frame buffer operations
+ */
-static unsigned int deep_presets[4] = {
- 0x00014000,
- 0x0001440d,
- 0xffffffff,
- 0x0001441d
+static struct fb_ops tgafb_ops = {
+ .owner = THIS_MODULE,
+ .fb_check_var = tgafb_check_var,
+ .fb_set_par = tgafb_set_par,
+ .fb_setcolreg = tgafb_setcolreg,
+ .fb_blank = tgafb_blank,
+ .fb_fillrect = cfb_fillrect,
+ .fb_copyarea = cfb_copyarea,
+ .fb_imageblit = cfb_imageblit,
+ .fb_cursor = soft_cursor,
};
-static unsigned int rasterop_presets[4] = {
- 0x00000003,
- 0x00000303,
- 0xffffffff,
- 0x00000303
-};
-static unsigned int mode_presets[4] = {
- 0x00002000,
- 0x00002300,
- 0xffffffff,
- 0x00002300
-};
+/*
+ * PCI registration operations
+ */
-static unsigned int base_addr_presets[4] = {
- 0x00000000,
- 0x00000001,
- 0xffffffff,
- 0x00000001
+static struct pci_device_id const tgafb_pci_table[] = {
+ { PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TGA, PCI_ANY_ID, PCI_ANY_ID,
+ 0, 0, 0 }
};
-
- /*
- * Predefined video modes
- * This is a subset of the standard VESA modes, recalculated from XFree86.
- *
- * XXX Should we store these in terms of the encoded par structs? Even better,
- * fbcon should provide a general mechanism for doing something like this.
- */
-
-static struct {
- const char *name;
- struct fb_var_screeninfo var;
-} tgafb_predefined[] __initdata = {
- { "640x480-60", {
- 640, 480, 640, 480, 0, 0, 0, 0,
- {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
- 0, 0, -1, -1, FB_ACCELF_TEXT, 39722, 40, 24, 32, 11, 96, 2,
- 0,
- FB_VMODE_NONINTERLACED
- }},
- { "800x600-56", {
- 800, 600, 800, 600, 0, 0, 0, 0,
- {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
- 0, 0, -1, -1, FB_ACCELF_TEXT, 27777, 128, 24, 22, 1, 72, 2,
- 0,
- FB_VMODE_NONINTERLACED
- }},
- { "640x480-72", {
- 640, 480, 640, 480, 0, 0, 0, 0,
- {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
- 0, 0, -1, -1, FB_ACCELF_TEXT, 31746, 144, 40, 30, 8, 40, 3,
- 0,
- FB_VMODE_NONINTERLACED
- }},
- { "800x600-60", {
- 800, 600, 800, 600, 0, 0, 0, 0,
- {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
- 0, 0, -1, -1, FB_ACCELF_TEXT, 25000, 88, 40, 23, 1, 128, 4,
- FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT,
- FB_VMODE_NONINTERLACED
- }},
- { "800x600-72", {
- 800, 600, 800, 600, 0, 0, 0, 0,
- {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
- 0, 0, -1, -1, FB_ACCELF_TEXT, 20000, 64, 56, 23, 37, 120, 6,
- FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT,
- FB_VMODE_NONINTERLACED
- }},
- { "1024x768-60", {
- 1024, 768, 1024, 768, 0, 0, 0, 0,
- {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
- 0, 0, -1, -1, FB_ACCELF_TEXT, 15384, 168, 8, 29, 3, 144, 6,
- 0,
- FB_VMODE_NONINTERLACED
- }},
- { "1152x864-60", {
- 1152, 864, 1152, 864, 0, 0, 0, 0,
- {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
- 0, 0, -1, -1, FB_ACCELF_TEXT, 11123, 208, 64, 16, 4, 256, 8,
- 0,
- FB_VMODE_NONINTERLACED
- }},
- { "1024x768-70", {
- 1024, 768, 1024, 768, 0, 0, 0, 0,
- {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
- 0, 0, -1, -1, FB_ACCELF_TEXT, 13333, 144, 24, 29, 3, 136, 6,
- 0,
- FB_VMODE_NONINTERLACED
- }},
- { "1024x768-76", {
- 1024, 768, 1024, 768, 0, 0, 0, 0,
- {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
- 0, 0, -1, -1, FB_ACCELF_TEXT, 11764, 208, 8, 36, 16, 120, 3,
- 0,
- FB_VMODE_NONINTERLACED
- }},
- { "1152x864-70", {
- 1152, 864, 1152, 864, 0, 0, 0, 0,
- {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
- 0, 0, -1, -1, FB_ACCELF_TEXT, 10869, 106, 56, 20, 1, 160, 10,
- 0,
- FB_VMODE_NONINTERLACED
- }},
- { "1280x1024-61", {
- 1280, 1024, 1280, 1024, 0, 0, 0, 0,
- {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
- 0, 0, -1, -1, FB_ACCELF_TEXT, 9090, 200, 48, 26, 1, 184, 3,
- 0,
- FB_VMODE_NONINTERLACED
- }},
- { "1024x768-85", {
- 1024, 768, 1024, 768, 0, 0, 0, 0,
- {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
- 0, 0, -1, -1, FB_ACCELF_TEXT, 10111, 192, 32, 34, 14, 160, 6,
- 0,
- FB_VMODE_NONINTERLACED
- }},
- { "1280x1024-70", {
- 1280, 1024, 1280, 1024, 0, 0, 0, 0,
- {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
- 0, 0, -1, -1, FB_ACCELF_TEXT, 7905, 224, 32, 28, 8, 160, 8,
- 0,
- FB_VMODE_NONINTERLACED
- }},
- { "1152x864-84", {
- 1152, 864, 1152, 864, 0, 0, 0, 0,
- {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
- 0, 0, -1, -1, FB_ACCELF_TEXT, 7407, 184, 312, 32, 0, 128, 12,
- 0,
- FB_VMODE_NONINTERLACED
- }},
- { "1280x1024-76", {
- 1280, 1024, 1280, 1024, 0, 0, 0, 0,
- {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
- 0, 0, -1, -1, FB_ACCELF_TEXT, 7407, 248, 32, 34, 3, 104, 3,
- 0,
- FB_VMODE_NONINTERLACED
- }},
- { "1280x1024-85", {
- 1280, 1024, 1280, 1024, 0, 0, 0, 0,
- {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
- 0, 0, -1, -1, FB_ACCELF_TEXT, 6349, 224, 64, 44, 1, 160, 3,
- 0,
- FB_VMODE_NONINTERLACED
- }},
-
- /* These are modes used by the two fixed-frequency monitors I have at home.
- * You may or may not find these useful.
- */
-
- { "WYSE1", { /* 1280x1024 @ 72 Hz, 130 Mhz clock */
- 1280, 1024, 1280, 1024, 0, 0, 0, 0,
- {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
- 0, 0, -1, -1, FB_ACCELF_TEXT, 7692, 192, 32, 47, 0, 192, 5,
- FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT,
- FB_VMODE_NONINTERLACED
- }},
- { "IBM3", { /* 1280x1024 @ 70 Hz, 120 Mhz clock */
- 1280, 1024, 1280, 1024, 0, 0, 0, 0,
- {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
- 0, 0, -1, -1, FB_ACCELF_TEXT, 8333, 192, 32, 47, 0, 192, 5,
- 0,
- FB_VMODE_NONINTERLACED
- }}
+static struct pci_driver tgafb_driver = {
+ .name = "tgafb",
+ .id_table = tgafb_pci_table,
+ .probe = tgafb_pci_register,
+ .remove = __devexit_p(tgafb_pci_unregister),
};
-#define NUM_TOTAL_MODES ARRAY_SIZE(tgafb_predefined)
-
-
- /*
- * Interface used by the world
- */
-
-static void tgafb_detect(void);
-static int tgafb_encode_fix(struct fb_fix_screeninfo *fix, const void *fb_par,
- struct fb_info_gen *info);
-static int tgafb_decode_var(const struct fb_var_screeninfo *var, void *fb_par,
- struct fb_info_gen *info);
-static int tgafb_encode_var(struct fb_var_screeninfo *var, const void *fb_par,
- struct fb_info_gen *info);
-static void tgafb_get_par(void *fb_par, struct fb_info_gen *info);
-static void tgafb_set_par(const void *fb_par, struct fb_info_gen *info);
-static int tgafb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
- u_int *transp, struct fb_info *info);
-static int tgafb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
- u_int transp, struct fb_info *info);
-static int tgafb_blank(int blank, struct fb_info_gen *info);
-static void tgafb_set_disp(const void *fb_par, struct display *disp,
- struct fb_info_gen *info);
-
-#ifndef MODULE
-int tgafb_setup(char*);
-#endif
-
-static void tgafb_set_pll(int f);
-#if 1
-static int tgafb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
- struct fb_info *info);
-static void tgafb_update_palette(void);
-#endif
-
-
- /*
- * Chipset specific functions
- */
-
-static void tgafb_detect(void)
+/**
+ * tgafb_check_var - Optional function. Validates a var passed in.
+ * @var: frame buffer variable screen structure
+ * @info: frame buffer structure that represents a single frame buffer
+ */
+static int
+tgafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
{
- return;
-}
+ struct tga_par *par = (struct tga_par *)info->par;
+
+ if (par->tga_type == TGA_TYPE_8PLANE) {
+ if (var->bits_per_pixel > 8)
+ return -EINVAL;
+ } else {
+ if (var->bits_per_pixel > 32)
+ return -EINVAL;
+ }
+ if (var->xres_virtual != var->xres || var->yres_virtual != var->yres)
+ return -EINVAL;
+ if (var->nonstd)
+ return -EINVAL;
+ if (1000000000 / var->pixclock > TGA_PLL_MAX_FREQ)
+ return -EINVAL;
+ if ((var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED)
+ return -EINVAL;
-static int tgafb_encode_fix(struct fb_fix_screeninfo *fix, const void *fb_par,
- struct fb_info_gen *info)
-{
- struct tgafb_par *par = (struct tgafb_par *)fb_par;
-
- strcpy(fix->id, fb_info.gen.info.modename);
-
- fix->type = FB_TYPE_PACKED_PIXELS;
- fix->type_aux = 0;
- if (fb_info.tga_type == TGA_TYPE_8PLANE) {
- fix->visual = FB_VISUAL_PSEUDOCOLOR;
- } else {
- fix->visual = FB_VISUAL_TRUECOLOR;
- }
-
- fix->line_length = par->xres * (par->bits_per_pixel >> 3);
- fix->smem_start = fb_info.tga_fb_base;
- fix->smem_len = fix->line_length * par->yres;
- fix->mmio_start = fb_info.tga_regs_base;
- fix->mmio_len = 0x1000; /* Is this sufficient? */
- fix->xpanstep = fix->ypanstep = fix->ywrapstep = 0;
- fix->accel = FB_ACCEL_DEC_TGA;
-
- return 0;
+ return 0;
}
-
-static int tgafb_decode_var(const struct fb_var_screeninfo *var, void *fb_par,
- struct fb_info_gen *info)
+/**
+ * tgafb_set_par - Optional function. Alters the hardware state.
+ * @info: frame buffer structure that represents a single frame buffer
+ */
+static int
+tgafb_set_par(struct fb_info *info)
{
- struct tgafb_par *par = (struct tgafb_par *)fb_par;
+ static unsigned int const deep_presets[4] = {
+ 0x00014000,
+ 0x0001440d,
+ 0xffffffff,
+ 0x0001441d
+ };
+ static unsigned int const rasterop_presets[4] = {
+ 0x00000003,
+ 0x00000303,
+ 0xffffffff,
+ 0x00000303
+ };
+ static unsigned int const mode_presets[4] = {
+ 0x00002000,
+ 0x00002300,
+ 0xffffffff,
+ 0x00002300
+ };
+ static unsigned int const base_addr_presets[4] = {
+ 0x00000000,
+ 0x00000001,
+ 0xffffffff,
+ 0x00000001
+ };
+
+ struct tga_par *par = (struct tga_par *) info->par;
+ u32 htimings, vtimings, pll_freq;
+ u8 tga_type;
+ int i, j;
+
+ /* Encode video timings. */
+ htimings = (((info->var.xres/4) & TGA_HORIZ_ACT_LSB)
+ | (((info->var.xres/4) & 0x600 << 19) & TGA_HORIZ_ACT_MSB));
+ vtimings = (info->var.yres & TGA_VERT_ACTIVE);
+ htimings |= ((info->var.right_margin/4) << 9) & TGA_HORIZ_FP;
+ vtimings |= (info->var.lower_margin << 11) & TGA_VERT_FP;
+ htimings |= ((info->var.hsync_len/4) << 14) & TGA_HORIZ_SYNC;
+ vtimings |= (info->var.vsync_len << 16) & TGA_VERT_SYNC;
+ htimings |= ((info->var.left_margin/4) << 21) & TGA_HORIZ_BP;
+ vtimings |= (info->var.upper_margin << 22) & TGA_VERT_BP;
+
+ if (info->var.sync & FB_SYNC_HOR_HIGH_ACT)
+ htimings |= TGA_HORIZ_POLARITY;
+ if (info->var.sync & FB_SYNC_VERT_HIGH_ACT)
+ vtimings |= TGA_VERT_POLARITY;
+
+ par->htimings = htimings;
+ par->vtimings = vtimings;
+
+ par->sync_on_green = !!(info->var.sync & FB_SYNC_ON_GREEN);
+
+ /* Store other useful values in par. */
+ par->xres = info->var.xres;
+ par->yres = info->var.yres;
+ par->pll_freq = pll_freq = 1000000000 / info->var.pixclock;
+ par->bits_per_pixel = info->var.bits_per_pixel;
+
+ tga_type = par->tga_type;
+
+ /* First, disable video. */
+ TGA_WRITE_REG(par, TGA_VALID_VIDEO | TGA_VALID_BLANK, TGA_VALID_REG);
+
+ /* Write the DEEP register. */
+ while (TGA_READ_REG(par, TGA_CMD_STAT_REG) & 1) /* wait for not busy */
+ continue;
+ mb();
+ TGA_WRITE_REG(par, deep_presets[tga_type], TGA_DEEP_REG);
+ while (TGA_READ_REG(par, TGA_CMD_STAT_REG) & 1) /* wait for not busy */
+ continue;
+ mb();
+
+ /* Write some more registers. */
+ TGA_WRITE_REG(par, rasterop_presets[tga_type], TGA_RASTEROP_REG);
+ TGA_WRITE_REG(par, mode_presets[tga_type], TGA_MODE_REG);
+ TGA_WRITE_REG(par, base_addr_presets[tga_type], TGA_BASE_ADDR_REG);
+
+ /* Calculate & write the PLL. */
+ tgafb_set_pll(par, pll_freq);
+
+ /* Write some more registers. */
+ TGA_WRITE_REG(par, 0xffffffff, TGA_PLANEMASK_REG);
+ TGA_WRITE_REG(par, 0xffffffff, TGA_PIXELMASK_REG);
+ TGA_WRITE_REG(par, 0x12345678, TGA_BLOCK_COLOR0_REG);
+ TGA_WRITE_REG(par, 0x12345678, TGA_BLOCK_COLOR1_REG);
+
+ /* Init video timing regs. */
+ TGA_WRITE_REG(par, htimings, TGA_HORIZ_REG);
+ TGA_WRITE_REG(par, vtimings, TGA_VERT_REG);
+
+ /* Initalise RAMDAC. */
+ if (tga_type == TGA_TYPE_8PLANE) {
+
+ /* Init BT485 RAMDAC registers. */
+ BT485_WRITE(par, 0xa2 | (par->sync_on_green ? 0x8 : 0x0),
+ BT485_CMD_0);
+ BT485_WRITE(par, 0x01, BT485_ADDR_PAL_WRITE);
+ BT485_WRITE(par, 0x14, BT485_CMD_3); /* cursor 64x64 */
+ BT485_WRITE(par, 0x40, BT485_CMD_1);
+ BT485_WRITE(par, 0x20, BT485_CMD_2); /* cursor off, for now */
+ BT485_WRITE(par, 0xff, BT485_PIXEL_MASK);
+
+ /* Fill palette registers. */
+ BT485_WRITE(par, 0x00, BT485_ADDR_PAL_WRITE);
+ TGA_WRITE_REG(par, BT485_DATA_PAL, TGA_RAMDAC_SETUP_REG);
+
+ for (i = 0; i < 16; i++) {
+ j = color_table[i];
+ TGA_WRITE_REG(par, default_red[j]|(BT485_DATA_PAL<<8),
+ TGA_RAMDAC_REG);
+ TGA_WRITE_REG(par, default_grn[j]|(BT485_DATA_PAL<<8),
+ TGA_RAMDAC_REG);
+ TGA_WRITE_REG(par, default_blu[j]|(BT485_DATA_PAL<<8),
+ TGA_RAMDAC_REG);
+ }
+ for (i = 0; i < 240*3; i += 4) {
+ TGA_WRITE_REG(par, 0x55|(BT485_DATA_PAL<<8),
+ TGA_RAMDAC_REG);
+ TGA_WRITE_REG(par, 0x00|(BT485_DATA_PAL<<8),
+ TGA_RAMDAC_REG);
+ TGA_WRITE_REG(par, 0x00|(BT485_DATA_PAL<<8),
+ TGA_RAMDAC_REG);
+ TGA_WRITE_REG(par, 0x00|(BT485_DATA_PAL<<8),
+ TGA_RAMDAC_REG);
+ }
+
+ } else { /* 24-plane or 24plusZ */
+
+ /* Init BT463 registers. */
+ BT463_WRITE(par, BT463_REG_ACC, BT463_CMD_REG_0, 0x40);
+ BT463_WRITE(par, BT463_REG_ACC, BT463_CMD_REG_1, 0x08);
+ BT463_WRITE(par, BT463_REG_ACC, BT463_CMD_REG_2,
+ (par->sync_on_green ? 0x80 : 0x40));
+
+ BT463_WRITE(par, BT463_REG_ACC, BT463_READ_MASK_0, 0xff);
+ BT463_WRITE(par, BT463_REG_ACC, BT463_READ_MASK_1, 0xff);
+ BT463_WRITE(par, BT463_REG_ACC, BT463_READ_MASK_2, 0xff);
+ BT463_WRITE(par, BT463_REG_ACC, BT463_READ_MASK_3, 0x0f);
+
+ BT463_WRITE(par, BT463_REG_ACC, BT463_BLINK_MASK_0, 0x00);
+ BT463_WRITE(par, BT463_REG_ACC, BT463_BLINK_MASK_1, 0x00);
+ BT463_WRITE(par, BT463_REG_ACC, BT463_BLINK_MASK_2, 0x00);
+ BT463_WRITE(par, BT463_REG_ACC, BT463_BLINK_MASK_3, 0x00);
+
+ /* Fill the palette. */
+ BT463_LOAD_ADDR(par, 0x0000);
+ TGA_WRITE_REG(par, BT463_PALETTE<<2, TGA_RAMDAC_REG);
+
+ for (i = 0; i < 16; i++) {
+ j = color_table[i];
+ TGA_WRITE_REG(par, default_red[j]|(BT463_PALETTE<<10),
+ TGA_RAMDAC_REG);
+ TGA_WRITE_REG(par, default_grn[j]|(BT463_PALETTE<<10),
+ TGA_RAMDAC_REG);
+ TGA_WRITE_REG(par, default_blu[j]|(BT463_PALETTE<<10),
+ TGA_RAMDAC_REG);
+ }
+ for (i = 0; i < 512*3; i += 4) {
+ TGA_WRITE_REG(par, 0x55|(BT463_PALETTE<<10),
+ TGA_RAMDAC_REG);
+ TGA_WRITE_REG(par, 0x00|(BT463_PALETTE<<10),
+ TGA_RAMDAC_REG);
+ TGA_WRITE_REG(par, 0x00|(BT463_PALETTE<<10),
+ TGA_RAMDAC_REG);
+ TGA_WRITE_REG(par, 0x00|(BT463_PALETTE<<10),
+ TGA_RAMDAC_REG);
+ }
+
+ /* Fill window type table after start of vertical retrace. */
+ while (!(TGA_READ_REG(par, TGA_INTR_STAT_REG) & 0x01))
+ continue;
+ TGA_WRITE_REG(par, 0x01, TGA_INTR_STAT_REG);
+ mb();
+ while (!(TGA_READ_REG(par, TGA_INTR_STAT_REG) & 0x01))
+ continue;
+ TGA_WRITE_REG(par, 0x01, TGA_INTR_STAT_REG);
+
+ BT463_LOAD_ADDR(par, BT463_WINDOW_TYPE_BASE);
+ TGA_WRITE_REG(par, BT463_REG_ACC<<2, TGA_RAMDAC_SETUP_REG);
+
+ for (i = 0; i < 16; i++) {
+ TGA_WRITE_REG(par, 0x00|(BT463_REG_ACC<<10),
+ TGA_RAMDAC_REG);
+ TGA_WRITE_REG(par, 0x01|(BT463_REG_ACC<<10),
+ TGA_RAMDAC_REG);
+ TGA_WRITE_REG(par, 0x80|(BT463_REG_ACC<<10),
+ TGA_RAMDAC_REG);
+ }
- /* round up some */
- if (fb_info.tga_type == TGA_TYPE_8PLANE) {
- if (var->bits_per_pixel > 8) {
- return -EINVAL;
- }
- par->bits_per_pixel = 8;
- } else {
- if (var->bits_per_pixel > 32) {
- return -EINVAL;
}
- par->bits_per_pixel = 32;
- }
-
- /* check the values for sanity */
- if (var->xres_virtual != var->xres ||
- var->yres_virtual != var->yres ||
- var->nonstd || (1000000000/var->pixclock) > TGA_PLL_MAX_FREQ ||
- (var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED
-#if 0 /* fbmon not done. uncomment for 2.5.x -brad */
- || !fbmon_valid_timings(var->pixclock, var->htotal, var->vtotal, info))
-#else
- )
-#endif
- return -EINVAL;
-
- /* encode video timings */
- par->htimings = ((var->xres/4) & TGA_HORIZ_ACT_LSB) |
- (((var->xres/4) & 0x600 << 19) & TGA_HORIZ_ACT_MSB);
- par->vtimings = (var->yres & TGA_VERT_ACTIVE);
- par->htimings |= ((var->right_margin/4) << 9) & TGA_HORIZ_FP;
- par->vtimings |= (var->lower_margin << 11) & TGA_VERT_FP;
- par->htimings |= ((var->hsync_len/4) << 14) & TGA_HORIZ_SYNC;
- par->vtimings |= (var->vsync_len << 16) & TGA_VERT_SYNC;
- par->htimings |= ((var->left_margin/4) << 21) & TGA_HORIZ_BP;
- par->vtimings |= (var->upper_margin << 22) & TGA_VERT_BP;
-
- if (var->sync & FB_SYNC_HOR_HIGH_ACT)
- par->htimings |= TGA_HORIZ_POLARITY;
- if (var->sync & FB_SYNC_VERT_HIGH_ACT)
- par->vtimings |= TGA_VERT_POLARITY;
- if (var->sync & FB_SYNC_ON_GREEN) {
- par->sync_on_green = 1;
- } else {
- par->sync_on_green = 0;
- }
-
- /* store other useful values in par */
- par->xres = var->xres;
- par->yres = var->yres;
- par->pll_freq = 1000000000/var->pixclock;
- par->bits_per_pixel = var->bits_per_pixel;
-
- return 0;
-}
+ /* Finally, enable video scan (and pray for the monitor... :-) */
+ TGA_WRITE_REG(par, TGA_VALID_VIDEO, TGA_VALID_REG);
-static int tgafb_encode_var(struct fb_var_screeninfo *var, const void *fb_par,
- struct fb_info_gen *info)
-{
- struct tgafb_par *par = (struct tgafb_par *)fb_par;
-
- /* decode video timings */
- var->xres = ((par->htimings & TGA_HORIZ_ACT_LSB) | ((par->htimings & TGA_HORIZ_ACT_MSB) >> 19)) * 4;
- var->yres = (par->vtimings & TGA_VERT_ACTIVE);
- var->right_margin = ((par->htimings & TGA_HORIZ_FP) >> 9) * 4;
- var->lower_margin = ((par->vtimings & TGA_VERT_FP) >> 11);
- var->hsync_len = ((par->htimings & TGA_HORIZ_SYNC) >> 14) * 4;
- var->vsync_len = ((par->vtimings & TGA_VERT_SYNC) >> 16);
- var->left_margin = ((par->htimings & TGA_HORIZ_BP) >> 21) * 4;
- var->upper_margin = ((par->vtimings & TGA_VERT_BP) >> 22);
-
- if (par->htimings & TGA_HORIZ_POLARITY)
- var->sync |= FB_SYNC_HOR_HIGH_ACT;
- if (par->vtimings & TGA_VERT_POLARITY)
- var->sync |= FB_SYNC_VERT_HIGH_ACT;
- if (par->sync_on_green == 1)
- var->sync |= FB_SYNC_ON_GREEN;
-
- var->xres_virtual = var->xres;
- var->yres_virtual = var->yres;
- var->xoffset = var->yoffset = 0;
-
- /* depth-related */
- if (fb_info.tga_type == TGA_TYPE_8PLANE) {
- var->red.offset = 0;
- var->green.offset = 0;
- var->blue.offset = 0;
- } else {
- var->red.offset = 16;
- var->green.offset = 8;
- var->blue.offset = 0;
- }
- var->bits_per_pixel = par->bits_per_pixel;
- var->grayscale = 0;
- var->red.length = var->green.length = var->blue.length = 8;
- var->red.msb_right = var->green.msb_right = var->blue.msb_right = 0;
- var->transp.offset = var->transp.length = var->transp.msb_right = 0;
-
- /* others */
- var->xoffset = var->yoffset = 0;
- var->pixclock = 1000000000/par->pll_freq;
- var->nonstd = 0;
- var->activate = 0;
- var->height = var->width = -1;
- var->accel_flags = 0;
-
- return 0;
+ return 0;
}
-
-static void tgafb_get_par(void *fb_par, struct fb_info_gen *info)
+#define DIFFCHECK(X) \
+do { \
+ if (m <= 0x3f) { \
+ int delta = f - (TGA_PLL_BASE_FREQ * (X)) / (r << shift); \
+ if (delta < 0) \
+ delta = -delta; \
+ if (delta < min_diff) \
+ min_diff = delta, vm = m, va = a, vr = r; \
+ } \
+} while (0)
+
+static void
+tgafb_set_pll(struct tga_par *par, int f)
{
- struct tgafb_par *par = (struct tgafb_par *)fb_par;
+ int n, shift, base, min_diff, target;
+ int r,a,m,vm = 34, va = 1, vr = 30;
+
+ for (r = 0 ; r < 12 ; r++)
+ TGA_WRITE_REG(par, !r, TGA_CLOCK_REG);
- if (current_par_valid)
- *par = current_par;
- else {
- if (fb_info.tga_type == TGA_TYPE_8PLANE)
- default_var.bits_per_pixel = 8;
+ if (f > TGA_PLL_MAX_FREQ)
+ f = TGA_PLL_MAX_FREQ;
+
+ if (f >= TGA_PLL_MAX_FREQ / 2)
+ shift = 0;
+ else if (f >= TGA_PLL_MAX_FREQ / 4)
+ shift = 1;
else
- default_var.bits_per_pixel = 32;
+ shift = 2;
- tgafb_decode_var(&default_var, par, info);
- }
-}
+ TGA_WRITE_REG(par, shift & 1, TGA_CLOCK_REG);
+ TGA_WRITE_REG(par, shift >> 1, TGA_CLOCK_REG);
+ for (r = 0 ; r < 10 ; r++)
+ TGA_WRITE_REG(par, 0, TGA_CLOCK_REG);
-static void tgafb_set_par(const void *fb_par, struct fb_info_gen *info)
-{
- int i, j;
- struct tgafb_par *par = (struct tgafb_par *)fb_par;
-
-#if 0
- /* XXX this will break console switching with X11, maybe I need to test KD_GRAPHICS? */
- /* if current_par is valid, check to see if we need to change anything */
- if (current_par_valid) {
- if (!memcmp(par, &current_par, sizeof current_par)) {
- return;
+ if (f <= 120000) {
+ TGA_WRITE_REG(par, 0, TGA_CLOCK_REG);
+ TGA_WRITE_REG(par, 0, TGA_CLOCK_REG);
}
- }
-#endif
- current_par = *par;
- current_par_valid = 1;
-
- /* first, disable video */
- TGA_WRITE_REG(TGA_VALID_VIDEO | TGA_VALID_BLANK, TGA_VALID_REG);
-
- /* write the DEEP register */
- while (TGA_READ_REG(TGA_CMD_STAT_REG) & 1) /* wait for not busy */
- continue;
-
- mb();
- TGA_WRITE_REG(deep_presets[fb_info.tga_type], TGA_DEEP_REG);
- while (TGA_READ_REG(TGA_CMD_STAT_REG) & 1) /* wait for not busy */
- continue;
- mb();
-
- /* write some more registers */
- TGA_WRITE_REG(rasterop_presets[fb_info.tga_type], TGA_RASTEROP_REG);
- TGA_WRITE_REG(mode_presets[fb_info.tga_type], TGA_MODE_REG);
- TGA_WRITE_REG(base_addr_presets[fb_info.tga_type], TGA_BASE_ADDR_REG);
-
- /* calculate & write the PLL */
- tgafb_set_pll(par->pll_freq);
-
- /* write some more registers */
- TGA_WRITE_REG(0xffffffff, TGA_PLANEMASK_REG);
- TGA_WRITE_REG(0xffffffff, TGA_PIXELMASK_REG);
- TGA_WRITE_REG(0x12345678, TGA_BLOCK_COLOR0_REG);
- TGA_WRITE_REG(0x12345678, TGA_BLOCK_COLOR1_REG);
-
- /* init video timing regs */
- TGA_WRITE_REG(par->htimings, TGA_HORIZ_REG);
- TGA_WRITE_REG(par->vtimings, TGA_VERT_REG);
-
- /* initalise RAMDAC */
- if (fb_info.tga_type == TGA_TYPE_8PLANE) {
-
- /* init BT485 RAMDAC registers */
- BT485_WRITE(0xa2 | (par->sync_on_green ? 0x8 : 0x0), BT485_CMD_0);
- BT485_WRITE(0x01, BT485_ADDR_PAL_WRITE);
- BT485_WRITE(0x14, BT485_CMD_3); /* cursor 64x64 */
- BT485_WRITE(0x40, BT485_CMD_1);
- BT485_WRITE(0x20, BT485_CMD_2); /* cursor off, for now */
- BT485_WRITE(0xff, BT485_PIXEL_MASK);
-
- /* fill palette registers */
- BT485_WRITE(0x00, BT485_ADDR_PAL_WRITE);
- TGA_WRITE_REG(BT485_DATA_PAL, TGA_RAMDAC_SETUP_REG);
-
- for (i = 0; i < 16; i++) {
- j = color_table[i];
- TGA_WRITE_REG(default_red[j]|(BT485_DATA_PAL<<8), TGA_RAMDAC_REG);
- TGA_WRITE_REG(default_grn[j]|(BT485_DATA_PAL<<8), TGA_RAMDAC_REG);
- TGA_WRITE_REG(default_blu[j]|(BT485_DATA_PAL<<8), TGA_RAMDAC_REG);
- palette[i].red=default_red[j];
- palette[i].green=default_grn[j];
- palette[i].blue=default_blu[j];
+ else if (f <= 200000) {
+ TGA_WRITE_REG(par, 1, TGA_CLOCK_REG);
+ TGA_WRITE_REG(par, 0, TGA_CLOCK_REG);
}
- for (i = 0; i < 240*3; i += 4) {
- TGA_WRITE_REG(0x55|(BT485_DATA_PAL<<8), TGA_RAMDAC_REG);
- TGA_WRITE_REG(0x00|(BT485_DATA_PAL<<8), TGA_RAMDAC_REG);
- TGA_WRITE_REG(0x00|(BT485_DATA_PAL<<8), TGA_RAMDAC_REG);
- TGA_WRITE_REG(0x00|(BT485_DATA_PAL<<8), TGA_RAMDAC_REG);
- }
-
- } else { /* 24-plane or 24plusZ */
-
- /* init BT463 registers */
- BT463_WRITE(BT463_REG_ACC, BT463_CMD_REG_0, 0x40);
- BT463_WRITE(BT463_REG_ACC, BT463_CMD_REG_1, 0x08);
- BT463_WRITE(BT463_REG_ACC, BT463_CMD_REG_2,
- (par->sync_on_green ? 0x80 : 0x40));
-
- BT463_WRITE(BT463_REG_ACC, BT463_READ_MASK_0, 0xff);
- BT463_WRITE(BT463_REG_ACC, BT463_READ_MASK_1, 0xff);
- BT463_WRITE(BT463_REG_ACC, BT463_READ_MASK_2, 0xff);
- BT463_WRITE(BT463_REG_ACC, BT463_READ_MASK_3, 0x0f);
-
- BT463_WRITE(BT463_REG_ACC, BT463_BLINK_MASK_0, 0x00);
- BT463_WRITE(BT463_REG_ACC, BT463_BLINK_MASK_1, 0x00);
- BT463_WRITE(BT463_REG_ACC, BT463_BLINK_MASK_2, 0x00);
- BT463_WRITE(BT463_REG_ACC, BT463_BLINK_MASK_3, 0x00);
-
- /* fill the palette */
- BT463_LOAD_ADDR(0x0000);
- TGA_WRITE_REG((BT463_PALETTE<<2), TGA_RAMDAC_REG);
-
- for (i = 0; i < 16; i++) {
- j = color_table[i];
- TGA_WRITE_REG(default_red[j]|(BT463_PALETTE<<10), TGA_RAMDAC_REG);
- TGA_WRITE_REG(default_grn[j]|(BT463_PALETTE<<10), TGA_RAMDAC_REG);
- TGA_WRITE_REG(default_blu[j]|(BT463_PALETTE<<10), TGA_RAMDAC_REG);
+ else {
+ TGA_WRITE_REG(par, 0, TGA_CLOCK_REG);
+ TGA_WRITE_REG(par, 1, TGA_CLOCK_REG);
}
- for (i = 0; i < 512*3; i += 4) {
- TGA_WRITE_REG(0x55|(BT463_PALETTE<<10), TGA_RAMDAC_REG);
- TGA_WRITE_REG(0x00|(BT463_PALETTE<<10), TGA_RAMDAC_REG);
- TGA_WRITE_REG(0x00|(BT463_PALETTE<<10), TGA_RAMDAC_REG);
- TGA_WRITE_REG(0x00|(BT463_PALETTE<<10), TGA_RAMDAC_REG);
- }
-
- /* fill window type table after start of vertical retrace */
- while (!(TGA_READ_REG(TGA_INTR_STAT_REG) & 0x01))
- continue;
- TGA_WRITE_REG(0x01, TGA_INTR_STAT_REG);
- mb();
- while (!(TGA_READ_REG(TGA_INTR_STAT_REG) & 0x01))
- continue;
- TGA_WRITE_REG(0x01, TGA_INTR_STAT_REG);
-
- BT463_LOAD_ADDR(BT463_WINDOW_TYPE_BASE);
- TGA_WRITE_REG((BT463_REG_ACC<<2), TGA_RAMDAC_SETUP_REG);
-
- for (i = 0; i < 16; i++) {
- TGA_WRITE_REG(0x00|(BT463_REG_ACC<<10), TGA_RAMDAC_REG);
- TGA_WRITE_REG(0x01|(BT463_REG_ACC<<10), TGA_RAMDAC_REG);
- TGA_WRITE_REG(0x80|(BT463_REG_ACC<<10), TGA_RAMDAC_REG);
+
+ TGA_WRITE_REG(par, 1, TGA_CLOCK_REG);
+ TGA_WRITE_REG(par, 0, TGA_CLOCK_REG);
+ TGA_WRITE_REG(par, 0, TGA_CLOCK_REG);
+ TGA_WRITE_REG(par, 1, TGA_CLOCK_REG);
+ TGA_WRITE_REG(par, 0, TGA_CLOCK_REG);
+ TGA_WRITE_REG(par, 1, TGA_CLOCK_REG);
+
+ target = (f << shift) / TGA_PLL_BASE_FREQ;
+ min_diff = TGA_PLL_MAX_FREQ;
+
+ r = 7 / target;
+ if (!r) r = 1;
+
+ base = target * r;
+ while (base < 449) {
+ for (n = base < 7 ? 7 : base; n < base + target && n < 449; n++) {
+ m = ((n + 3) / 7) - 1;
+ a = 0;
+ DIFFCHECK((m + 1) * 7);
+ m++;
+ DIFFCHECK((m + 1) * 7);
+ m = (n / 6) - 1;
+ if ((a = n % 6))
+ DIFFCHECK(n);
+ }
+ r++;
+ base += target;
}
-
- }
- /* finally, enable video scan
- (and pray for the monitor... :-) */
- TGA_WRITE_REG(TGA_VALID_VIDEO, TGA_VALID_REG);
-}
+ vr--;
+ for (r = 0; r < 8; r++)
+ TGA_WRITE_REG(par, (vm >> r) & 1, TGA_CLOCK_REG);
+ for (r = 0; r < 8 ; r++)
+ TGA_WRITE_REG(par, (va >> r) & 1, TGA_CLOCK_REG);
+ for (r = 0; r < 7 ; r++)
+ TGA_WRITE_REG(par, (vr >> r) & 1, TGA_CLOCK_REG);
+ TGA_WRITE_REG(par, ((vr >> 7) & 1)|2, TGA_CLOCK_REG);
+}
-#define DIFFCHECK(x) { if( m <= 0x3f ) { \
- int delta = f - (TGA_PLL_BASE_FREQ * (x)) / (r << shift); \
- if (delta < 0) delta = -delta; \
- if (delta < min_diff) min_diff = delta, vm = m, va = a, vr = r; } }
-static void tgafb_set_pll(int f)
+/**
+ * tgafb_setcolreg - Optional function. Sets a color register.
+ * @regno: boolean, 0 copy local, 1 get_user() function
+ * @red: frame buffer colormap structure
+ * @green: The green value which can be up to 16 bits wide
+ * @blue: The blue value which can be up to 16 bits wide.
+ * @transp: If supported the alpha value which can be up to 16 bits wide.
+ * @info: frame buffer info structure
+ */
+static int
+tgafb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue,
+ unsigned transp, struct fb_info *info)
{
- int n, shift, base, min_diff, target;
- int r,a,m,vm = 34, va = 1, vr = 30;
-
- for( r = 0 ; r < 12 ; r++ )
- TGA_WRITE_REG(!r, TGA_CLOCK_REG);
-
- if (f > TGA_PLL_MAX_FREQ)
- f = TGA_PLL_MAX_FREQ;
-
- if (f >= TGA_PLL_MAX_FREQ / 2)
- shift = 0;
- else if (f >= TGA_PLL_MAX_FREQ / 4)
- shift = 1;
- else
- shift = 2;
-
- TGA_WRITE_REG(shift & 1, TGA_CLOCK_REG);
- TGA_WRITE_REG(shift >> 1, TGA_CLOCK_REG);
-
- for( r = 0 ; r < 10 ; r++ ) {
- TGA_WRITE_REG(0, TGA_CLOCK_REG);
- }
-
- if (f <= 120000) {
- TGA_WRITE_REG(0, TGA_CLOCK_REG);
- TGA_WRITE_REG(0, TGA_CLOCK_REG);
- }
- else if (f <= 200000) {
- TGA_WRITE_REG(1, TGA_CLOCK_REG);
- TGA_WRITE_REG(0, TGA_CLOCK_REG);
- }
- else {
- TGA_WRITE_REG(0, TGA_CLOCK_REG);
- TGA_WRITE_REG(1, TGA_CLOCK_REG);
- }
-
- TGA_WRITE_REG(1, TGA_CLOCK_REG);
- TGA_WRITE_REG(0, TGA_CLOCK_REG);
- TGA_WRITE_REG(0, TGA_CLOCK_REG);
- TGA_WRITE_REG(1, TGA_CLOCK_REG);
- TGA_WRITE_REG(0, TGA_CLOCK_REG);
- TGA_WRITE_REG(1, TGA_CLOCK_REG);
-
- target = (f << shift) / TGA_PLL_BASE_FREQ;
- min_diff = TGA_PLL_MAX_FREQ;
-
- r = 7 / target;
- if (!r)
- r = 1;
-
- base = target * r;
- while (base < 449) {
- for (n = base < 7 ? 7 : base ; n < base + target && n < 449; n++) {
- m = ((n + 3) / 7) - 1;
- a = 0;
- DIFFCHECK((m + 1) * 7);
- m++;
- DIFFCHECK((m + 1) * 7);
- m = (n / 6) - 1;
- if( (a = n % 6))
- DIFFCHECK( n );
+ struct tga_par *par = (struct tga_par *) info->par;
+
+ if (regno > 255)
+ return 1;
+ red >>= 8;
+ green >>= 8;
+ blue >>= 8;
+
+ if (par->tga_type == TGA_TYPE_8PLANE) {
+ BT485_WRITE(par, regno, BT485_ADDR_PAL_WRITE);
+ TGA_WRITE_REG(par, BT485_DATA_PAL, TGA_RAMDAC_SETUP_REG);
+ TGA_WRITE_REG(par, red|(BT485_DATA_PAL<<8),TGA_RAMDAC_REG);
+ TGA_WRITE_REG(par, green|(BT485_DATA_PAL<<8),TGA_RAMDAC_REG);
+ TGA_WRITE_REG(par, blue|(BT485_DATA_PAL<<8),TGA_RAMDAC_REG);
+ } else if (regno < 16) {
+ u32 value = (red << 16) | (green << 8) | blue;
+ ((u32 *)info->pseudo_palette)[regno] = value;
}
- r++;
- base += target;
- }
-
- vr--;
-
- for( r=0; r<8 ; r++) {
- TGA_WRITE_REG((vm >> r) & 1, TGA_CLOCK_REG);
- }
- for( r=0; r<8 ; r++) {
- TGA_WRITE_REG((va >> r) & 1, TGA_CLOCK_REG);
- }
- for( r=0; r<7 ; r++) {
- TGA_WRITE_REG((vr >> r) & 1, TGA_CLOCK_REG);
- }
- TGA_WRITE_REG(((vr >> 7) & 1)|2, TGA_CLOCK_REG);
-}
-
-static int tgafb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
- u_int *transp, struct fb_info *info)
-{
- if (regno > 255)
- return 1;
- *red = (palette[regno].red<<8) | palette[regno].red;
- *green = (palette[regno].green<<8) | palette[regno].green;
- *blue = (palette[regno].blue<<8) | palette[regno].blue;
- *transp = 0;
- return 0;
+ return 0;
}
-static int tgafb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
- u_int transp, struct fb_info *info)
+/**
+ * tgafb_blank - Optional function. Blanks the display.
+ * @blank_mode: the blank mode we want.
+ * @info: frame buffer structure that represents a single frame buffer
+ */
+static int
+tgafb_blank(int blank, struct fb_info *info)
{
- if (regno > 255)
- return 1;
- red >>= 8;
- green >>= 8;
- blue >>= 8;
- palette[regno].red = red;
- palette[regno].green = green;
- palette[regno].blue = blue;
-
-#ifdef FBCON_HAS_CFB32
- if (regno < 16 && fb_info.tga_type != TGA_TYPE_8PLANE)
- fbcon_cfb32_cmap[regno] = (red << 16) | (green << 8) | blue;
-#endif
-
- if (fb_info.tga_type == TGA_TYPE_8PLANE) {
- BT485_WRITE(regno, BT485_ADDR_PAL_WRITE);
- TGA_WRITE_REG(BT485_DATA_PAL, TGA_RAMDAC_SETUP_REG);
- TGA_WRITE_REG(red|(BT485_DATA_PAL<<8),TGA_RAMDAC_REG);
- TGA_WRITE_REG(green|(BT485_DATA_PAL<<8),TGA_RAMDAC_REG);
- TGA_WRITE_REG(blue|(BT485_DATA_PAL<<8),TGA_RAMDAC_REG);
- }
- /* How to set a single color register on 24-plane cards?? */
+ struct tga_par *par = (struct tga_par *) info->par;
+ u32 vhcr, vvcr, vvvr;
+ unsigned long flags;
+
+ local_irq_save(flags);
+
+ vhcr = TGA_READ_REG(par, TGA_HORIZ_REG);
+ vvcr = TGA_READ_REG(par, TGA_VERT_REG);
+ vvvr = TGA_READ_REG(par, TGA_VALID_REG);
+ vvvr &= ~(TGA_VALID_VIDEO | TGA_VALID_BLANK);
+
+ switch (blank) {
+ case 0: /* Unblanking */
+ if (par->vesa_blanked) {
+ TGA_WRITE_REG(par, vhcr & 0xbfffffff, TGA_HORIZ_REG);
+ TGA_WRITE_REG(par, vvcr & 0xbfffffff, TGA_VERT_REG);
+ par->vesa_blanked = 0;
+ }
+ TGA_WRITE_REG(par, vvvr | TGA_VALID_VIDEO, TGA_VALID_REG);
+ break;
+
+ case 1: /* Normal blanking */
+ TGA_WRITE_REG(par, vvvr | TGA_VALID_VIDEO | TGA_VALID_BLANK,
+ TGA_VALID_REG);
+ break;
+
+ case 2: /* VESA blank (vsync off) */
+ TGA_WRITE_REG(par, vvcr | 0x40000000, TGA_VERT_REG);
+ TGA_WRITE_REG(par, vvvr | TGA_VALID_BLANK, TGA_VALID_REG);
+ par->vesa_blanked = 1;
+ break;
+
+ case 3: /* VESA blank (hsync off) */
+ TGA_WRITE_REG(par, vhcr | 0x40000000, TGA_HORIZ_REG);
+ TGA_WRITE_REG(par, vvvr | TGA_VALID_BLANK, TGA_VALID_REG);
+ par->vesa_blanked = 1;
+ break;
+
+ case 4: /* Poweroff */
+ TGA_WRITE_REG(par, vhcr | 0x40000000, TGA_HORIZ_REG);
+ TGA_WRITE_REG(par, vvcr | 0x40000000, TGA_VERT_REG);
+ TGA_WRITE_REG(par, vvvr | TGA_VALID_BLANK, TGA_VALID_REG);
+ par->vesa_blanked = 1;
+ break;
+ }
- return 0;
+ local_irq_restore(flags);
+ return 0;
}
-#if 1
- /*
- * FIXME: since I don't know how to set a single arbitrary color register
- * on 24-plane cards, all color palette registers have to be updated
- */
-static int tgafb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
- struct fb_info *info)
-{
- int err;
-
- if (!fb_display[con].cmap.len) { /* no colormap allocated? */
- if ((err = fb_alloc_cmap(&fb_display[con].cmap, 256, 0)))
- return err;
- }
- if (con == info->currcon) { /* current console? */
- err = fb_set_cmap(cmap, kspc, info);
-#if 1
- if (fb_info.tga_type != TGA_TYPE_8PLANE)
- tgafb_update_palette();
-#endif
- return err;
- } else
- fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1);
- return 0;
-}
+/*
+ * Initialisation
+ */
-static void tgafb_update_palette(void)
+static void
+tgafb_init_fix(struct fb_info *info)
{
- int i;
+ struct tga_par *par = (struct tga_par *)info->par;
+ u8 tga_type = par->tga_type;
+ const char *tga_type_name;
- BT463_LOAD_ADDR(0x0000);
- TGA_WRITE_REG((BT463_PALETTE<<2), TGA_RAMDAC_REG);
-
- for (i = 0; i < 256; i++) {
- TGA_WRITE_REG(palette[i].red|(BT463_PALETTE<<10), TGA_RAMDAC_REG);
- TGA_WRITE_REG(palette[i].green|(BT463_PALETTE<<10), TGA_RAMDAC_REG);
- TGA_WRITE_REG(palette[i].blue|(BT463_PALETTE<<10), TGA_RAMDAC_REG);
- }
-}
-#endif
+ switch (tga_type) {
+ case TGA_TYPE_8PLANE:
+ tga_type_name = "Digital ZLXp-E1";
+ break;
+ case TGA_TYPE_24PLANE:
+ tga_type_name = "Digital ZLXp-E2";
+ break;
+ case TGA_TYPE_24PLUSZ:
+ tga_type_name = "Digital ZLXp-E3";
+ break;
+ default:
+ tga_type_name = "Unknown";
+ break;
+ }
+ strncpy(info->fix.id, tga_type_name, sizeof(info->fix.id) - 1);
+ info->fix.id[sizeof(info->fix.id)-1] = 0;
-static int tgafb_blank(int blank, struct fb_info_gen *info)
-{
- static int tga_vesa_blanked = 0;
- u32 vhcr, vvcr, vvvr;
- unsigned long flags;
-
- local_irq_save(flags);
-
- vhcr = TGA_READ_REG(TGA_HORIZ_REG);
- vvcr = TGA_READ_REG(TGA_VERT_REG);
- vvvr = TGA_READ_REG(TGA_VALID_REG) & ~(TGA_VALID_VIDEO | TGA_VALID_BLANK);
-
- switch (blank) {
- case 0: /* Unblanking */
- if (tga_vesa_blanked) {
- TGA_WRITE_REG(vhcr & 0xbfffffff, TGA_HORIZ_REG);
- TGA_WRITE_REG(vvcr & 0xbfffffff, TGA_VERT_REG);
- tga_vesa_blanked = 0;
- }
- TGA_WRITE_REG(vvvr | TGA_VALID_VIDEO, TGA_VALID_REG);
- break;
-
- case 1: /* Normal blanking */
- TGA_WRITE_REG(vvvr | TGA_VALID_VIDEO | TGA_VALID_BLANK, TGA_VALID_REG);
- break;
-
- case 2: /* VESA blank (vsync off) */
- TGA_WRITE_REG(vvcr | 0x40000000, TGA_VERT_REG);
- TGA_WRITE_REG(vvvr | TGA_VALID_BLANK, TGA_VALID_REG);
- tga_vesa_blanked = 1;
- break;
-
- case 3: /* VESA blank (hsync off) */
- TGA_WRITE_REG(vhcr | 0x40000000, TGA_HORIZ_REG);
- TGA_WRITE_REG(vvvr | TGA_VALID_BLANK, TGA_VALID_REG);
- tga_vesa_blanked = 1;
- break;
-
- case 4: /* Poweroff */
- TGA_WRITE_REG(vhcr | 0x40000000, TGA_HORIZ_REG);
- TGA_WRITE_REG(vvcr | 0x40000000, TGA_VERT_REG);
- TGA_WRITE_REG(vvvr | TGA_VALID_BLANK, TGA_VALID_REG);
- tga_vesa_blanked = 1;
- break;
- }
-
- local_irq_restore(flags);
- return 0;
-}
+ info->fix.type = FB_TYPE_PACKED_PIXELS;
+ info->fix.type_aux = 0;
+ info->fix.visual = (tga_type == TGA_TYPE_8PLANE
+ ? FB_VISUAL_PSEUDOCOLOR
+ : FB_VISUAL_TRUECOLOR);
+ info->fix.line_length = par->xres * (par->bits_per_pixel >> 3);
+ info->fix.smem_start = (size_t) par->tga_fb_base;
+ info->fix.smem_len = info->fix.line_length * par->yres;
+ info->fix.mmio_start = (size_t) par->tga_regs_base;
+ info->fix.mmio_len = 0x1000; /* Is this sufficient? */
-static void tgafb_set_disp(const void *fb_par, struct display *disp,
- struct fb_info_gen *info)
-{
- switch (fb_info.tga_type) {
-#ifdef FBCON_HAS_CFB8
- case TGA_TYPE_8PLANE:
- disp->dispsw = &fbcon_cfb8;
- break;
-#endif
-#ifdef FBCON_HAS_CFB32
- case TGA_TYPE_24PLANE:
- case TGA_TYPE_24PLUSZ:
- disp->dispsw = &fbcon_cfb32;
- disp->dispsw_data = &fbcon_cfb32_cmap;
- break;
-#endif
- default:
- disp->dispsw = &fbcon_dummy;
- }
+ info->fix.xpanstep = 0;
+ info->fix.ypanstep = 0;
+ info->fix.ywrapstep = 0;
- disp->scrollmode = SCROLL_YREDRAW;
+ info->fix.accel = FB_ACCEL_DEC_TGA;
}
+static __devinit int
+tgafb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+ static unsigned int const fb_offset_presets[4] = {
+ TGA_8PLANE_FB_OFFSET,
+ TGA_24PLANE_FB_OFFSET,
+ 0xffffffff,
+ TGA_24PLUSZ_FB_OFFSET
+ };
+
+ struct all_info {
+ struct fb_info info;
+ struct tga_par par;
+ u32 pseudo_palette[16];
+ } *all;
+
+ void *mem_base;
+ unsigned long bar0_start, bar0_len;
+ u8 tga_type;
+ int ret;
+
+ /* Enable device in PCI config. */
+ if (pci_enable_device(pdev)) {
+ printk(KERN_ERR "tgafb: Cannot enable PCI device\n");
+ return -ENODEV;
+ }
-struct fbgen_hwswitch tgafb_hwswitch = {
- tgafb_detect, tgafb_encode_fix, tgafb_decode_var, tgafb_encode_var, tgafb_get_par,
- tgafb_set_par, tgafb_getcolreg, NULL, tgafb_blank,
- tgafb_set_disp
-};
-
+ /* Allocate the fb and par structures. */
+ all = kmalloc(sizeof(*all), GFP_KERNEL);
+ if (!all) {
+ printk(KERN_ERR "tgafb: Cannot allocate memory\n");
+ return -ENOMEM;
+ }
+ memset(all, 0, sizeof(*all));
+ pci_set_drvdata(pdev, all);
+
+ /* Request the mem regions. */
+ bar0_start = pci_resource_start(pdev, 0);
+ bar0_len = pci_resource_len(pdev, 0);
+ ret = -ENODEV;
+ if (!request_mem_region (bar0_start, bar0_len, "tgafb")) {
+ printk(KERN_ERR "tgafb: cannot reserve FB region\n");
+ goto err0;
+ }
- /*
- * Hardware Independent functions
- */
+ /* Map the framebuffer. */
+ mem_base = ioremap(bar0_start, bar0_len);
+ if (!mem_base) {
+ printk(KERN_ERR "tgafb: Cannot map MMIO\n");
+ goto err1;
+ }
+ /* Grab info about the card. */
+ tga_type = (readl(mem_base) >> 12) & 0x0f;
+ all->par.pdev = pdev;
+ all->par.tga_mem_base = mem_base;
+ all->par.tga_fb_base = mem_base + fb_offset_presets[tga_type];
+ all->par.tga_regs_base = mem_base + TGA_REGS_OFFSET;
+ all->par.tga_type = tga_type;
+ pci_read_config_byte(pdev, PCI_REVISION_ID, &all->par.tga_chip_rev);
+
+ /* Setup framebuffer. */
+ all->info.node = NODEV;
+ all->info.flags = FBINFO_FLAG_DEFAULT;
+ all->info.fbops = &tgafb_ops;
+ all->info.screen_base = (char *) all->par.tga_fb_base;
+ all->info.currcon = -1;
+ all->info.par = &all->par;
+ all->info.pseudo_palette = all->pseudo_palette;
+
+ /* This should give a reasonable default video mode. */
+
+ ret = fb_find_mode(&all->info.var, &all->info, mode_option,
+ NULL, 0, NULL,
+ tga_type == TGA_TYPE_8PLANE ? 8 : 32);
+ if (ret == 0 || ret == 4) {
+ printk(KERN_ERR "tgafb: Could not find valid video mode\n");
+ ret = -EINVAL;
+ goto err1;
+ }
- /*
- * Frame buffer operations
- */
+ if (fb_alloc_cmap(&all->info.cmap, 256, 0)) {
+ printk(KERN_ERR "tgafb: Could not allocate color map\n");
+ ret = -ENOMEM;
+ goto err1;
+ }
-static struct fb_ops tgafb_ops = {
- .owner = THIS_MODULE,
- .fb_get_fix = fbgen_get_fix,
- .fb_get_var = fbgen_get_var,
- .fb_set_var = fbgen_set_var,
- .fb_get_cmap = fbgen_get_cmap,
- .fb_set_cmap = tgafb_set_cmap,
- .fb_setcolreg = tgafb_setcolreg,
- .fb_blank = fbgen_blank,
-};
+ tgafb_set_par(&all->info);
+ tgafb_init_fix(&all->info);
+ if (register_framebuffer(&all->info) < 0) {
+ printk(KERN_ERR "tgafb: Could not register framebuffer\n");
+ ret = -EINVAL;
+ goto err1;
+ }
-#ifndef MODULE
- /*
- * Setup
- */
-
-int __init tgafb_setup(char *options) {
- char *this_opt;
- int i;
-
- if (options && *options) {
- while ((this_opt = strsep(&options, ",")) != NULL) {
- if (!*this_opt) { continue; }
-
- if (!strncmp(this_opt, "font:", 5)) {
- strncpy(default_fontname, this_opt+5, sizeof default_fontname);
- }
-
- else if (!strncmp(this_opt, "mode:", 5)) {
- for (i = 0; i < NUM_TOTAL_MODES; i++) {
- if (!strcmp(this_opt+5, tgafb_predefined[i].name))
- default_var = tgafb_predefined[i].var;
- default_var_valid = 1;
- }
- }
-
- else {
- printk(KERN_ERR "tgafb: unknown parameter %s\n", this_opt);
- }
- }
- }
- return 0;
+ printk(KERN_INFO "tgafb: DC21030 [TGA] detected, rev=0x%02x\n",
+ all->par.tga_chip_rev);
+ printk(KERN_INFO "tgafb: at PCI bus %d, device %d, function %d\n",
+ pdev->bus->number, PCI_SLOT(pdev->devfn),
+ PCI_FUNC(pdev->devfn));
+ printk(KERN_INFO "fb%d: %s frame buffer device at 0x%lx\n",
+ minor(all->info.node), all->info.fix.id, bar0_start);
+
+ return 0;
+
+ err1:
+ release_mem_region(bar0_start, bar0_len);
+ err0:
+ kfree(all);
+ return ret;
}
-#endif
-
- /*
- * Initialisation
- */
-
-int __init tgafb_init(void)
+int __init
+tgafb_init(void)
{
- struct pci_dev *pdev;
-
- pdev = pci_find_device(PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TGA, NULL);
- if (!pdev)
- return -ENXIO;
-
- /* divine board type */
-
- fb_info.tga_mem_base = (unsigned long)ioremap(pdev->resource[0].start, 0);
- fb_info.tga_type = (readl(fb_info.tga_mem_base) >> 12) & 0x0f;
- fb_info.tga_regs_base = fb_info.tga_mem_base + TGA_REGS_OFFSET;
- fb_info.tga_fb_base = (fb_info.tga_mem_base
- + fb_offset_presets[fb_info.tga_type]);
- pci_read_config_byte(pdev, PCI_REVISION_ID, &fb_info.tga_chip_rev);
-
- /* setup framebuffer */
-
- fb_info.gen.info.node = NODEV;
- fb_info.gen.info.flags = FBINFO_FLAG_DEFAULT;
- fb_info.gen.info.fbops = &tgafb_ops;
- fb_info.gen.info.screen_base = (char *)fb_info.tga_fb_base;
- fb_info.gen.info.disp = &disp;
- fb_info.gen.info.currcon = -1;
- fb_info.gen.info.changevar = NULL;
- fb_info.gen.info.switch_con = &fbgen_switch;
- fb_info.gen.info.updatevar = &fbgen_update_var;
- strcpy(fb_info.gen.info.fontname, default_fontname);
- fb_info.gen.parsize = sizeof (struct tgafb_par);
- fb_info.gen.fbhw = &tgafb_hwswitch;
- fb_info.gen.fbhw->detect();
-
- printk (KERN_INFO "tgafb: DC21030 [TGA] detected, rev=0x%02x\n", fb_info.tga_chip_rev);
- printk (KERN_INFO "tgafb: at PCI bus %d, device %d, function %d\n",
- pdev->bus->number, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn));
-
- switch (fb_info.tga_type)
- {
- case TGA_TYPE_8PLANE:
- strcpy (fb_info.gen.info.modename,"Digital ZLXp-E1");
- break;
-
- case TGA_TYPE_24PLANE:
- strcpy (fb_info.gen.info.modename,"Digital ZLXp-E2");
- break;
-
- case TGA_TYPE_24PLUSZ:
- strcpy (fb_info.gen.info.modename,"Digital ZLXp-E3");
- break;
- }
-
- /* This should give a reasonable default video mode */
-
- if (!default_var_valid) {
- default_var = tgafb_predefined[0].var;
- }
- fbgen_get_var(&disp.var, -1, &fb_info.gen.info);
- disp.var.activate = FB_ACTIVATE_NOW;
- fbgen_do_set_var(&disp.var, 1, &fb_info.gen);
- fbgen_set_disp(-1, &fb_info.gen);
- do_install_cmap(0, &fb_info.gen);
- if (register_framebuffer(&fb_info.gen.info) < 0)
- return -EINVAL;
- printk(KERN_INFO "fb%d: %s frame buffer device at 0x%lx\n",
- minor(fb_info.gen.info.node), fb_info.gen.info.modename,
- pdev->resource[0].start);
- return 0;
+ return pci_module_init(&tgafb_driver);
}
+#ifdef MODULE
+static void __exit
+tgafb_pci_unregister(struct pci_dev *pdev)
+{
+ struct fb_info *info = pci_get_drvdata(pdev);
+ struct tga_par *par = info->par;
+
+ if (!info)
+ return;
+ unregister_framebuffer(info);
+ iounmap(par->tga_mem_base);
+ release_mem_region(pci_resource_start(pdev, 0),
+ pci_resource_len(pdev, 0));
+ kfree(info);
+}
- /*
- * Cleanup
- */
-
-void __exit tgafb_cleanup(void)
+static void __exit
+tgafb_exit(void)
{
- unregister_framebuffer(&fb_info.gen.info);
+ pci_unregister_driver(&tgafb_driver);
}
+#endif /* MODULE */
+#ifndef MODULE
+int __init
+tgafb_setup(char *arg)
+{
+ char *this_opt;
+
+ if (arg && *arg) {
+ while ((this_opt = strsep(&arg, ","))) {
+ if (!*this_opt)
+ continue;
+ if (!strncmp(this_opt, "mode:", 5))
+ mode_option = this_opt+5;
+ else
+ printk(KERN_ERR
+ "tgafb: unknown parameter %s\n",
+ this_opt);
+ }
+ }
- /*
- * Modularisation
- */
+ return 0;
+}
+#endif /* !MODULE */
+
+/*
+ * Modularisation
+ */
#ifdef MODULE
-MODULE_LICENSE("GPL");
module_init(tgafb_init);
+module_exit(tgafb_exit);
#endif
-module_exit(tgafb_cleanup);
+MODULE_DESCRIPTION("framebuffer driver for TGA chipset");
+MODULE_LICENSE("GPL");
diff --git a/fs/block_dev.c b/fs/block_dev.c
index e6fc5b1984e3..2e0b69ff70a1 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -623,8 +623,7 @@ static int do_open(struct block_device *bdev, struct inode *inode, struct file *
}
} else {
put_disk(disk);
- if (owner)
- __MOD_DEC_USE_COUNT(owner);
+ module_put(owner);
if (bdev->bd_contains == bdev) {
if (bdev->bd_disk->fops->open) {
ret = bdev->bd_disk->fops->open(inode, file);
@@ -651,8 +650,7 @@ out_first:
blkdev_put(bdev->bd_contains, BDEV_RAW);
bdev->bd_contains = NULL;
put_disk(disk);
- if (owner)
- __MOD_DEC_USE_COUNT(owner);
+ module_put(owner);
out:
up(&bdev->bd_sem);
unlock_kernel();
@@ -723,9 +721,10 @@ int blkdev_put(struct block_device *bdev, int kind)
}
if (!bdev->bd_openers) {
struct module *owner = disk->fops->owner;
+
put_disk(disk);
- if (owner)
- __MOD_DEC_USE_COUNT(owner);
+ module_put(owner);
+
bdev->bd_disk = NULL;
bdev->bd_inode->i_data.backing_dev_info = &default_backing_dev_info;
if (bdev != bdev->bd_contains) {
diff --git a/fs/dquot.c b/fs/dquot.c
index 5da20a7049ce..8781f7201a87 100644
--- a/fs/dquot.c
+++ b/fs/dquot.c
@@ -111,8 +111,7 @@ static struct quota_format_type *find_quota_format(int id)
static void put_quota_format(struct quota_format_type *fmt)
{
- if (fmt->qf_owner)
- __MOD_DEC_USE_COUNT(fmt->qf_owner);
+ module_put(fmt->qf_owner);
}
/*
diff --git a/fs/exec.c b/fs/exec.c
index 1699f5bdf92e..901b8e12388f 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -102,8 +102,7 @@ int unregister_binfmt(struct linux_binfmt * fmt)
static inline void put_binfmt(struct linux_binfmt * fmt)
{
- if (fmt->module)
- __MOD_DEC_USE_COUNT(fmt->module);
+ module_put(fmt->module);
}
/*
@@ -1108,14 +1107,18 @@ out_file:
return retval;
}
-void set_binfmt(struct linux_binfmt *new)
+int set_binfmt(struct linux_binfmt *new)
{
struct linux_binfmt *old = current->binfmt;
- if (new && new->module)
- __MOD_INC_USE_COUNT(new->module);
+
+ if (new) {
+ if (!try_module_get(new->module))
+ return -1;
+ }
current->binfmt = new;
- if (old && old->module)
- __MOD_DEC_USE_COUNT(old->module);
+ if (old)
+ module_put(old->module);
+ return 0;
}
#define CORENAME_MAX_SIZE 64
diff --git a/fs/jbd/journal.c b/fs/jbd/journal.c
index 0fa6fcfe61b0..d2f5935ef972 100644
--- a/fs/jbd/journal.c
+++ b/fs/jbd/journal.c
@@ -694,8 +694,6 @@ static journal_t * journal_init_common (void)
journal_t *journal;
int err;
- MOD_INC_USE_COUNT;
-
journal = jbd_kmalloc(sizeof(*journal), GFP_KERNEL);
if (!journal)
goto fail;
@@ -724,7 +722,6 @@ static journal_t * journal_init_common (void)
}
return journal;
fail:
- MOD_DEC_USE_COUNT;
return NULL;
}
@@ -1131,7 +1128,6 @@ void journal_destroy (journal_t *journal)
unlock_journal(journal);
kfree(journal);
- MOD_DEC_USE_COUNT;
}
diff --git a/fs/libfs.c b/fs/libfs.c
index 813bc9046bcd..e3d30987c919 100644
--- a/fs/libfs.c
+++ b/fs/libfs.c
@@ -6,6 +6,15 @@
#include <linux/pagemap.h>
#include <linux/smp_lock.h>
+int simple_getattr(struct vfsmount *mnt, struct dentry *dentry,
+ struct kstat *stat)
+{
+ struct inode *inode = dentry->d_inode;
+ generic_fillattr(inode, stat);
+ stat->blocks = inode->i_mapping->nrpages << (PAGE_CACHE_SHIFT - 9);
+ return 0;
+}
+
int simple_statfs(struct super_block *sb, struct statfs *buf)
{
buf->f_type = sb->s_magic;
diff --git a/fs/nls/nls_base.c b/fs/nls/nls_base.c
index 0af5e08cb950..3ea711688341 100644
--- a/fs/nls/nls_base.c
+++ b/fs/nls/nls_base.c
@@ -245,8 +245,7 @@ struct nls_table *load_nls(char *charset)
void unload_nls(struct nls_table *nls)
{
- if (nls->owner)
- __MOD_DEC_USE_COUNT(nls->owner);
+ module_put(nls->owner);
}
wchar_t charset2uni[256] = {
diff --git a/fs/partitions/check.c b/fs/partitions/check.c
index da216ea3efa6..b1d436feb241 100644
--- a/fs/partitions/check.c
+++ b/fs/partitions/check.c
@@ -565,8 +565,7 @@ char *partition_name(dev_t dev)
dname->name = NULL;
if (hd) {
dname->name = disk_name(hd, part, dname->namebuf);
- if (hd->fops->owner)
- __MOD_DEC_USE_COUNT(hd->fops->owner);
+ module_put(hd->fops->owner);
put_disk(hd);
}
if (!dname->name) {
diff --git a/fs/proc/array.c b/fs/proc/array.c
index 2fa25e95712d..4dae164bc85a 100644
--- a/fs/proc/array.c
+++ b/fs/proc/array.c
@@ -513,8 +513,9 @@ static int proc_pid_maps_get_line (char *buf, struct vm_area_struct *map)
return len;
}
-ssize_t proc_pid_read_maps (struct task_struct *task, struct file * file, char * buf,
- size_t count, loff_t *ppos)
+#ifdef CONFIG_MMU
+ssize_t proc_pid_read_maps(struct task_struct *task, struct file *file,
+ char *buf, size_t count, loff_t *ppos)
{
struct mm_struct *mm;
struct vm_area_struct * map;
@@ -597,3 +598,4 @@ out_free1:
out:
return retval;
}
+#endif /* CONFIG_MMU */
diff --git a/fs/proc/base.c b/fs/proc/base.c
index d0c10bff3a9e..3867d87354b1 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -75,7 +75,9 @@ static struct pid_entry base_stuff[] = {
E(PROC_PID_CMDLINE, "cmdline", S_IFREG|S_IRUGO),
E(PROC_PID_STAT, "stat", S_IFREG|S_IRUGO),
E(PROC_PID_STATM, "statm", S_IFREG|S_IRUGO),
+#ifdef CONFIG_MMU
E(PROC_PID_MAPS, "maps", S_IFREG|S_IRUGO),
+#endif
E(PROC_PID_MEM, "mem", S_IFREG|S_IRUSR|S_IWUSR),
E(PROC_PID_CWD, "cwd", S_IFLNK|S_IRWXUGO),
E(PROC_PID_ROOT, "root", S_IFLNK|S_IRWXUGO),
@@ -98,7 +100,6 @@ static inline int proc_type(struct inode *inode)
return PROC_I(inode)->type;
}
-ssize_t proc_pid_read_maps(struct task_struct*,struct file*,char*,size_t,loff_t*);
int proc_pid_stat(struct task_struct*,char*);
int proc_pid_status(struct task_struct*,char*);
int proc_pid_statm(struct task_struct*,char*);
@@ -322,6 +323,9 @@ static int proc_permission(struct inode *inode, int mask)
return proc_check_root(inode);
}
+#ifdef CONFIG_MMU
+extern ssize_t proc_pid_read_maps(struct task_struct *, struct file *,
+ char *, size_t, loff_t *);
static ssize_t pid_maps_read(struct file * file, char * buf,
size_t count, loff_t *ppos)
{
@@ -336,6 +340,7 @@ static ssize_t pid_maps_read(struct file * file, char * buf,
static struct file_operations proc_maps_operations = {
.read = pid_maps_read,
};
+#endif /* CONFIG_MMU */
extern struct seq_operations mounts_op;
static int mounts_open(struct inode *inode, struct file *file)
@@ -1024,10 +1029,11 @@ static struct dentry *proc_base_lookup(struct inode *dir, struct dentry *dentry)
inode->i_fop = &proc_info_file_operations;
ei->op.proc_read = proc_pid_statm;
break;
+#ifdef CONFIG_MMU
case PROC_PID_MAPS:
inode->i_fop = &proc_maps_operations;
break;
-
+#endif
case PROC_PID_MEM:
inode->i_op = &proc_mem_inode_operations;
inode->i_fop = &proc_mem_operations;
diff --git a/fs/ramfs/inode.c b/fs/ramfs/inode.c
index 9f8ac09e12ce..15418ab4f490 100644
--- a/fs/ramfs/inode.c
+++ b/fs/ramfs/inode.c
@@ -40,6 +40,7 @@
static struct super_operations ramfs_ops;
static struct address_space_operations ramfs_aops;
static struct file_operations ramfs_file_operations;
+static struct inode_operations ramfs_file_inode_operations;
static struct inode_operations ramfs_dir_inode_operations;
static struct backing_dev_info ramfs_backing_dev_info = {
@@ -66,6 +67,7 @@ static struct inode *ramfs_get_inode(struct super_block *sb, int mode, dev_t dev
init_special_inode(inode, mode, dev);
break;
case S_IFREG:
+ inode->i_op = &ramfs_file_inode_operations;
inode->i_fop = &ramfs_file_operations;
break;
case S_IFDIR:
@@ -114,7 +116,6 @@ static int ramfs_create(struct inode *dir, struct dentry *dentry, int mode)
return ramfs_mknod(dir, dentry, mode | S_IFREG, 0);
}
-
static int ramfs_symlink(struct inode * dir, struct dentry *dentry, const char * symname)
{
struct inode *inode;
@@ -147,6 +148,10 @@ static struct file_operations ramfs_file_operations = {
.sendfile = generic_file_sendfile,
};
+static struct inode_operations ramfs_file_inode_operations = {
+ .getattr = simple_getattr,
+};
+
static struct inode_operations ramfs_dir_inode_operations = {
.create = ramfs_create,
.lookup = simple_lookup,
diff --git a/fs/select.c b/fs/select.c
index 456465510c09..510e1defe964 100644
--- a/fs/select.c
+++ b/fs/select.c
@@ -471,7 +471,7 @@ asmlinkage long sys_poll(struct pollfd * ufds, unsigned int nfds, long timeout)
walk->next = pp;
walk = pp;
- if (copy_from_user(pp+1, ufds + nfds-i,
+ if (copy_from_user(pp->entries, ufds + nfds-i,
sizeof(struct pollfd)*pp->len)) {
err = -EFAULT;
goto out_fds;
diff --git a/include/asm-arm/arch-arc/io.h b/include/asm-arm/arch-arc/io.h
index 11c9ce687ab4..5aab0c88953f 100644
--- a/include/asm-arm/arch-arc/io.h
+++ b/include/asm-arm/arch-arc/io.h
@@ -246,7 +246,7 @@ DECLARE_IO(int,l,"")
#define outw(v,p) (__builtin_constant_p((p)) ? __outwc(v,p) : __outw(v,p))
#define outl(v,p) (__builtin_constant_p((p)) ? __outlc(v,p) : __outl(v,p))
#define __ioaddr(p) (__builtin_constant_p((p)) ? __ioaddr(p) : __ioaddrc(p))
-/* the following macro is depreciated */
+/* the following macro is deprecated */
#define ioaddr(port) __ioaddr((port))
/*
diff --git a/include/asm-arm/arch-cl7500/io.h b/include/asm-arm/arch-cl7500/io.h
index 376ca94ebb9c..16a926084d5f 100644
--- a/include/asm-arm/arch-cl7500/io.h
+++ b/include/asm-arm/arch-cl7500/io.h
@@ -236,7 +236,7 @@ DECLARE_IO(int,l,"")
#define outw(v,p) (__builtin_constant_p((p)) ? __outwc(v,p) : __outw(v,p))
#define outl(v,p) (__builtin_constant_p((p)) ? __outlc(v,p) : __outl(v,p))
#define __ioaddr(p) (__builtin_constant_p((p)) ? __ioaddr(p) : __ioaddrc(p))
-/* the following macro is depreciated */
+/* the following macro is deprecated */
#define ioaddr(port) __ioaddr((port))
#endif
diff --git a/include/asm-arm/arch-rpc/io.h b/include/asm-arm/arch-rpc/io.h
index cb39453f5c9f..3a1c18ad63bb 100644
--- a/include/asm-arm/arch-rpc/io.h
+++ b/include/asm-arm/arch-rpc/io.h
@@ -238,7 +238,7 @@ DECLARE_IO(int,l,"")
#define outw(v,p) (__builtin_constant_p((p)) ? __outwc(v,p) : __outw(v,p))
#define outl(v,p) (__builtin_constant_p((p)) ? __outlc(v,p) : __outl(v,p))
#define __ioaddr(p) (__builtin_constant_p((p)) ? __ioaddr(p) : __ioaddrc(p))
-/* the following macro is depreciated */
+/* the following macro is deprecated */
#define ioaddr(port) __ioaddr((port))
#define insb(p,d,l) __raw_readsb(__ioaddr(p),d,l)
diff --git a/include/asm-arm/memory.h b/include/asm-arm/memory.h
index c936883e5f0e..38682a28d121 100644
--- a/include/asm-arm/memory.h
+++ b/include/asm-arm/memory.h
@@ -44,7 +44,7 @@ static inline void *phys_to_virt(unsigned long x)
/*
* Virtual <-> DMA view memory address translations
* Again, these are *only* valid on the kernel direct mapped RAM
- * memory. Use of these is *depreciated*.
+ * memory. Use of these is *deprecated*.
*/
#define virt_to_bus(x) (__virt_to_bus((unsigned long)(x)))
#define bus_to_virt(x) ((void *)(__bus_to_virt((unsigned long)(x))))
@@ -109,7 +109,7 @@ static inline void *phys_to_virt(unsigned long x)
#define page_to_phys(page) (page_to_pfn(page) << PAGE_SHIFT)
/*
- * We should really eliminate virt_to_bus() here - it's depreciated.
+ * We should really eliminate virt_to_bus() here - it's deprecated.
*/
#define page_to_bus(page) (virt_to_bus(page_address(page)))
diff --git a/include/asm-arm/setup.h b/include/asm-arm/setup.h
index 38f4ba0ecc67..f3319e9b4f29 100644
--- a/include/asm-arm/setup.h
+++ b/include/asm-arm/setup.h
@@ -68,7 +68,7 @@ struct tag_ramdisk {
/* describes where the compressed ramdisk image lives (virtual address) */
/*
* this one accidentally used virtual addresses - as such,
- * its depreciated.
+ * it's deprecated.
*/
#define ATAG_INITRD 0x54410005
diff --git a/include/asm-generic/pci-dma-compat.h b/include/asm-generic/pci-dma-compat.h
index b871ec69a79a..ef858eecbffd 100644
--- a/include/asm-generic/pci-dma-compat.h
+++ b/include/asm-generic/pci-dma-compat.h
@@ -12,76 +12,76 @@
static inline int
pci_dma_supported(struct pci_dev *hwdev, u64 mask)
{
- return dma_supported(&hwdev->dev, mask);
+ return dma_supported(hwdev == NULL ? NULL : &hwdev->dev, mask);
}
static inline void *
pci_alloc_consistent(struct pci_dev *hwdev, size_t size,
dma_addr_t *dma_handle)
{
- return dma_alloc_coherent(&hwdev->dev, size, dma_handle);
+ return dma_alloc_coherent(hwdev == NULL ? NULL : &hwdev->dev, size, dma_handle);
}
static inline void
pci_free_consistent(struct pci_dev *hwdev, size_t size,
void *vaddr, dma_addr_t dma_handle)
{
- dma_free_coherent(&hwdev->dev, size, vaddr, dma_handle);
+ dma_free_coherent(hwdev == NULL ? NULL : &hwdev->dev, size, vaddr, dma_handle);
}
static inline dma_addr_t
pci_map_single(struct pci_dev *hwdev, void *ptr, size_t size, int direction)
{
- return dma_map_single(&hwdev->dev, ptr, size, (enum dma_data_direction)direction);
+ return dma_map_single(hwdev == NULL ? NULL : &hwdev->dev, ptr, size, (enum dma_data_direction)direction);
}
static inline void
pci_unmap_single(struct pci_dev *hwdev, dma_addr_t dma_addr,
size_t size, int direction)
{
- dma_unmap_single(&hwdev->dev, dma_addr, size, (enum dma_data_direction)direction);
+ dma_unmap_single(hwdev == NULL ? NULL : &hwdev->dev, dma_addr, size, (enum dma_data_direction)direction);
}
static inline dma_addr_t
pci_map_page(struct pci_dev *hwdev, struct page *page,
unsigned long offset, size_t size, int direction)
{
- return dma_map_page(&hwdev->dev, page, offset, size, (enum dma_data_direction)direction);
+ return dma_map_page(hwdev == NULL ? NULL : &hwdev->dev, page, offset, size, (enum dma_data_direction)direction);
}
static inline void
pci_unmap_page(struct pci_dev *hwdev, dma_addr_t dma_address,
size_t size, int direction)
{
- dma_unmap_page(&hwdev->dev, dma_address, size, (enum dma_data_direction)direction);
+ dma_unmap_page(hwdev == NULL ? NULL : &hwdev->dev, dma_address, size, (enum dma_data_direction)direction);
}
static inline int
pci_map_sg(struct pci_dev *hwdev, struct scatterlist *sg,
int nents, int direction)
{
- return dma_map_sg(&hwdev->dev, sg, nents, (enum dma_data_direction)direction);
+ return dma_map_sg(hwdev == NULL ? NULL : &hwdev->dev, sg, nents, (enum dma_data_direction)direction);
}
static inline void
pci_unmap_sg(struct pci_dev *hwdev, struct scatterlist *sg,
int nents, int direction)
{
- dma_unmap_sg(&hwdev->dev, sg, nents, (enum dma_data_direction)direction);
+ dma_unmap_sg(hwdev == NULL ? NULL : &hwdev->dev, sg, nents, (enum dma_data_direction)direction);
}
static inline void
pci_dma_sync_single(struct pci_dev *hwdev, dma_addr_t dma_handle,
size_t size, int direction)
{
- dma_sync_single(&hwdev->dev, dma_handle, size, (enum dma_data_direction)direction);
+ dma_sync_single(hwdev == NULL ? NULL : &hwdev->dev, dma_handle, size, (enum dma_data_direction)direction);
}
static inline void
pci_dma_sync_sg(struct pci_dev *hwdev, struct scatterlist *sg,
int nelems, int direction)
{
- dma_sync_sg(&hwdev->dev, sg, nelems, (enum dma_data_direction)direction);
+ dma_sync_sg(hwdev == NULL ? NULL : &hwdev->dev, sg, nelems, (enum dma_data_direction)direction);
}
#endif
diff --git a/include/asm-i386/bugs.h b/include/asm-i386/bugs.h
index f236e21749ab..5410e84760e6 100644
--- a/include/asm-i386/bugs.h
+++ b/include/asm-i386/bugs.h
@@ -193,6 +193,11 @@ static void __init check_config(void)
&& (boot_cpu_data.x86_mask < 6 || boot_cpu_data.x86_mask == 11))
panic("Kernel compiled for PMMX+, assumes a local APIC without the read-before-write bug!");
#endif
+
+#ifdef CONFIG_X86_SSE2
+ if (!cpu_has_sse2)
+ panic("Kernel compiled for SSE2, CPU doesn't have it.");
+#endif
}
static void __init check_bugs(void)
diff --git a/include/asm-i386/cpufeature.h b/include/asm-i386/cpufeature.h
index 92ff7f79dee4..5f019713fa4c 100644
--- a/include/asm-i386/cpufeature.h
+++ b/include/asm-i386/cpufeature.h
@@ -75,6 +75,7 @@
#define cpu_has_tsc boot_cpu_has(X86_FEATURE_TSC)
#define cpu_has_pae boot_cpu_has(X86_FEATURE_PAE)
#define cpu_has_pge boot_cpu_has(X86_FEATURE_PGE)
+#define cpu_has_sse2 boot_cpu_has(X86_FEATURE_XMM2)
#define cpu_has_apic boot_cpu_has(X86_FEATURE_APIC)
#define cpu_has_sep boot_cpu_has(X86_FEATURE_SEP)
#define cpu_has_mtrr boot_cpu_has(X86_FEATURE_MTRR)
diff --git a/include/asm-i386/desc.h b/include/asm-i386/desc.h
index 77f2b1c0ec46..d42e28c1e3fa 100644
--- a/include/asm-i386/desc.h
+++ b/include/asm-i386/desc.h
@@ -16,6 +16,7 @@ extern struct desc_struct cpu_gdt_table[NR_CPUS][GDT_ENTRIES];
struct Xgt_desc_struct {
unsigned short size;
unsigned long address __attribute__((packed));
+ unsigned short pad;
} __attribute__ ((packed));
extern struct Xgt_desc_struct idt_descr, cpu_gdt_descr[NR_CPUS];
diff --git a/include/asm-i386/hw_irq.h b/include/asm-i386/hw_irq.h
index 1a60daa9172e..035a6af03c63 100644
--- a/include/asm-i386/hw_irq.h
+++ b/include/asm-i386/hw_irq.h
@@ -131,7 +131,7 @@ static inline int unregister_profile_notifier(struct notifier_block * nb)
#endif /* CONFIG_PROFILING */
-#ifdef CONFIG_SMP /*more of this file should probably be ifdefed SMP */
+#if defined(CONFIG_SMP) && !defined(CONFIG_VOYAGER) /*more of this file should probably be ifdefed SMP */
static inline void hw_resend_irq(struct hw_interrupt_type *h, unsigned int i) {
if (IO_APIC_IRQ(i))
send_IPI_self(IO_APIC_VECTOR(i));
diff --git a/include/asm-i386/mach-default/mach_apic.h b/include/asm-i386/mach-default/mach_apic.h
index a24df01ffe2e..905bc7a1284d 100644
--- a/include/asm-i386/mach-default/mach_apic.h
+++ b/include/asm-i386/mach-default/mach_apic.h
@@ -73,8 +73,7 @@ static inline int mpc_apic_id(struct mpc_config_processor *m, int quad)
return (m->mpc_apicid);
}
-#define wakeup_secondary_cpu(apicid, start_eip) \
- wakeup_secondary_via_INIT(apicid, start_eip)
+#define WAKE_SECONDARY_VIA_INIT
static inline void setup_portio_remap(void)
{
diff --git a/include/asm-i386/mach-numaq/mach_apic.h b/include/asm-i386/mach-numaq/mach_apic.h
index be8eacb32aa0..94d2f5f28275 100644
--- a/include/asm-i386/mach-numaq/mach_apic.h
+++ b/include/asm-i386/mach-numaq/mach_apic.h
@@ -69,8 +69,7 @@ static inline int mpc_apic_id(struct mpc_config_processor *m, int quad)
return logical_apicid;
}
-#define wakeup_secondary_cpu(apicid, start_eip) \
- wakeup_secondary_via_NMI(apicid)
+#define WAKE_SECONDARY_VIA_NMI
static inline void setup_portio_remap(void)
{
diff --git a/include/asm-i386/mach-numaq/mach_mpparse.h b/include/asm-i386/mach-numaq/mach_mpparse.h
index ddda81a724a8..f15b7b9ae1e8 100644
--- a/include/asm-i386/mach-numaq/mach_mpparse.h
+++ b/include/asm-i386/mach-numaq/mach_mpparse.h
@@ -1,9 +1,6 @@
#ifndef __ASM_MACH_MPPARSE_H
#define __ASM_MACH_MPPARSE_H
-static void __init smp_read_mpc_oem(struct mp_config_oemtable *oemtable,
- unsigned short oemsize);
-
static inline void mpc_oem_bus_info(struct mpc_config_bus *m, char *name,
struct mpc_config_translation *translation)
{
diff --git a/include/asm-i386/mach-summit/mach_apic.h b/include/asm-i386/mach-summit/mach_apic.h
index 2de1e9fea7cd..bf601c3368ad 100644
--- a/include/asm-i386/mach-summit/mach_apic.h
+++ b/include/asm-i386/mach-summit/mach_apic.h
@@ -54,8 +54,7 @@ static inline unsigned long apicid_to_phys_cpu_present(int apicid)
return (1ul << apicid);
}
-#define wakeup_secondary_cpu(apicid, start_eip) \
- wakeup_secondary_via_INIT(apicid, start_eip)
+#define WAKE_SECONDARY_VIA_INIT
static inline void setup_portio_remap(void)
{
diff --git a/include/asm-i386/processor.h b/include/asm-i386/processor.h
index 156c53c50c90..6ee68de9408b 100644
--- a/include/asm-i386/processor.h
+++ b/include/asm-i386/processor.h
@@ -19,6 +19,9 @@
#include <linux/config.h>
#include <linux/threads.h>
+/* flag for disabling the tsc */
+extern int tsc_disable;
+
struct desc_struct {
unsigned long a,b;
};
@@ -392,31 +395,17 @@ struct thread_struct {
unsigned long *ts_io_bitmap;
};
-#define INIT_THREAD { \
- { { 0, 0 } , }, \
- 0, \
- 0, 0, 0, 0, \
- { [0 ... 7] = 0 }, /* debugging registers */ \
- 0, 0, 0, \
- { { 0, }, }, /* 387 state */ \
- 0,0,0,0,0, \
- NULL, /* io permissions */ \
+#define INIT_THREAD { \
+ .vm86_info = NULL, \
+ .ts_io_bitmap = NULL, \
}
-#define INIT_TSS { \
- 0,0, /* back_link, __blh */ \
- sizeof(init_stack) + (long) &init_stack, /* esp0 */ \
- __KERNEL_DS, 0, /* ss0 */ \
- 0,0,0,0,0,0, /* stack1, stack2 */ \
- 0, /* cr3 */ \
- 0,0, /* eip,eflags */ \
- 0,0,0,0, /* eax,ecx,edx,ebx */ \
- 0,0,0,0, /* esp,ebp,esi,edi */ \
- 0,0,0,0,0,0, /* es,cs,ss */ \
- 0,0,0,0,0,0, /* ds,fs,gs */ \
- GDT_ENTRY_LDT,0, /* ldt */ \
- 0, INVALID_IO_BITMAP_OFFSET, /* tace, bitmap */ \
- {~0, } /* ioperm */ \
+#define INIT_TSS { \
+ .esp0 = sizeof(init_stack) + (long)&init_stack, \
+ .ss0 = __KERNEL_DS, \
+ .ldt = GDT_ENTRY_LDT, \
+ .bitmap = INVALID_IO_BITMAP_OFFSET, \
+ .io_bitmap = { [ 0 ... IO_BITMAP_SIZE ] = ~0 }, \
}
static inline void load_esp0(struct tss_struct *tss, unsigned long esp0)
@@ -486,7 +475,7 @@ static inline void rep_nop(void)
#define cpu_relax() rep_nop()
/* Prefetch instructions for Pentium III and AMD Athlon */
-#ifdef CONFIG_MPENTIUMIII
+#ifdef CONFIG_X86_PREFETCH
#define ARCH_HAS_PREFETCH
extern inline void prefetch(const void *x)
diff --git a/include/asm-i386/segment.h b/include/asm-i386/segment.h
index f6949fb109d9..3f272860a6b3 100644
--- a/include/asm-i386/segment.h
+++ b/include/asm-i386/segment.h
@@ -71,6 +71,14 @@
#define GDT_SIZE (GDT_ENTRIES * 8)
+/* Simple and small GDT entries for booting only */
+
+#define GDT_ENTRY_BOOT_CS 2
+#define __BOOT_CS (GDT_ENTRY_BOOT_CS * 8)
+
+#define GDT_ENTRY_BOOT_DS (GDT_ENTRY_BOOT_CS + 1)
+#define __BOOT_DS (GDT_ENTRY_BOOT_DS * 8)
+
/*
* The interrupt descriptor table has room for 256 idt's,
* the global descriptor table is dependent on the number
diff --git a/include/asm-i386/smp.h b/include/asm-i386/smp.h
index 32a8f5a05a84..71d58561d39c 100644
--- a/include/asm-i386/smp.h
+++ b/include/asm-i386/smp.h
@@ -6,6 +6,7 @@
*/
#ifndef __ASSEMBLY__
#include <linux/config.h>
+#include <linux/kernel.h>
#include <linux/threads.h>
#endif
@@ -83,11 +84,22 @@ extern volatile unsigned long cpu_callout_map;
#define cpu_possible(cpu) (cpu_callout_map & (1<<(cpu)))
#define cpu_online(cpu) (cpu_online_map & (1<<(cpu)))
+#define for_each_cpu(cpu, mask) \
+ for(mask = cpu_online_map; \
+ cpu = __ffs(mask), mask != 0; \
+ mask &= ~(1<<cpu))
+
extern inline unsigned int num_online_cpus(void)
{
return hweight32(cpu_online_map);
}
+/* We don't mark CPUs online until __cpu_up(), so we need another measure */
+static inline int num_booting_cpus(void)
+{
+ return hweight32(cpu_callout_map);
+}
+
extern inline int any_online_cpu(unsigned int mask)
{
if (mask & cpu_online_map)
@@ -95,7 +107,7 @@ extern inline int any_online_cpu(unsigned int mask)
return -1;
}
-
+#ifdef CONFIG_X86_LOCAL_APIC
static __inline int hard_smp_processor_id(void)
{
/* we don't want to mark this access volatile - bad code generation */
@@ -108,12 +120,7 @@ static __inline int logical_smp_processor_id(void)
return GET_APIC_LOGICAL_ID(*(unsigned long *)(APIC_BASE+APIC_LDR));
}
-/* We don't mark CPUs online until __cpu_up(), so we need another measure */
-static inline int num_booting_cpus(void)
-{
- return hweight32(cpu_callout_map);
-}
-
+#endif
#endif /* !__ASSEMBLY__ */
#define NO_PROC_ID 0xFF /* No processor magic marker */
diff --git a/include/asm-i386/system.h b/include/asm-i386/system.h
index fc8f116430bc..e085e51e9d25 100644
--- a/include/asm-i386/system.h
+++ b/include/asm-i386/system.h
@@ -288,9 +288,13 @@ static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
* nop for these.
*/
+#ifdef CONFIG_X86_SSE2
+#define mb() asm volatile("mfence" ::: "memory")
+#define rmb() asm volatile("lfence" ::: "memory")
+#else
#define mb() __asm__ __volatile__ ("lock; addl $0,0(%%esp)": : :"memory")
#define rmb() mb()
-
+#endif
/**
* read_barrier_depends - Flush all pending reads that subsequents reads
* depend on.
diff --git a/include/asm-i386/uaccess.h b/include/asm-i386/uaccess.h
index 05bdac770eed..377038170a0b 100644
--- a/include/asm-i386/uaccess.h
+++ b/include/asm-i386/uaccess.h
@@ -189,7 +189,7 @@ do { \
case 1: __put_user_asm(x,ptr,retval,"b","b","iq"); break; \
case 2: __put_user_asm(x,ptr,retval,"w","w","ir"); break; \
case 4: __put_user_asm(x,ptr,retval,"l","","ir"); break; \
- case 8: __put_user_u64(x,ptr,retval); break; \
+ case 8: __put_user_u64((__typeof__(*ptr))(x),ptr,retval); break; \
default: __put_user_bad(); \
} \
} while (0)
diff --git a/include/asm-i386/voyager.h b/include/asm-i386/voyager.h
index 1e97e05e17d0..aaf432dd7673 100644
--- a/include/asm-i386/voyager.h
+++ b/include/asm-i386/voyager.h
@@ -504,7 +504,6 @@ extern void voyager_setup_irqs(void);
extern int voyager_memory_detect(int region, __u32 *addr, __u32 *length);
extern void voyager_smp_intr_init(void);
extern __u8 voyager_extended_cmos_read(__u16 cmos_address);
-extern void voyager_dump(void);
extern void voyager_smp_dump(void);
extern void voyager_timer_interrupt(struct pt_regs *regs);
extern void smp_local_timer_interrupt(struct pt_regs * regs);
diff --git a/include/asm-m68k/ide.h b/include/asm-m68k/ide.h
index 1471687982a9..621be3adc24a 100644
--- a/include/asm-m68k/ide.h
+++ b/include/asm-m68k/ide.h
@@ -144,32 +144,34 @@ static __inline__ void ide_init_default_hwifs(void)
#define ATA_ARCH_ACK_INTR
-#ifdef CONFIG_ATARI
+#ifdef CONFIG_BLK_DEV_FALCON_IDE
#define ATA_ARCH_LOCK
-static __inline__ void ide_release_lock (int *ide_lock)
+extern int falconide_intr_lock;
+
+static __inline__ void ide_release_lock (void)
{
if (MACH_IS_ATARI) {
- if (*ide_lock == 0) {
+ if (falconide_intr_lock == 0) {
printk("ide_release_lock: bug\n");
return;
}
- *ide_lock = 0;
+ falconide_intr_lock = 0;
stdma_release();
}
}
-static __inline__ void ide_get_lock (int *ide_lock, void (*handler)(int, void *, struct pt_regs *), void *data)
+static __inline__ void ide_get_lock(void (*handler)(int, void *, struct pt_regs *), void *data)
{
if (MACH_IS_ATARI) {
- if (*ide_lock == 0) {
+ if (falconide_intr_lock == 0) {
if (in_interrupt() > 0)
panic( "Falcon IDE hasn't ST-DMA lock in interrupt" );
stdma_lock(handler, data);
- *ide_lock = 1;
+ falconide_intr_lock = 1;
}
}
}
-#endif /* CONFIG_ATARI */
+#endif /* CONFIG_BLK_DEV_FALCON_IDE */
#endif /* __KERNEL__ */
#endif /* _M68K_IDE_H */
diff --git a/include/asm-m68k/macintosh.h b/include/asm-m68k/macintosh.h
index 47ad33cc2254..cbb1cb10cf73 100644
--- a/include/asm-m68k/macintosh.h
+++ b/include/asm-m68k/macintosh.h
@@ -76,9 +76,9 @@ struct mac_model
#define MAC_IDE_BABOON 3
#define MAC_SCC_II 1
-#define MAC_SCC_QUADRA 2
-#define MAC_SCC_QUADRA2 3
-#define MAC_SCC_IOP 4
+#define MAC_SCC_IOP 2
+#define MAC_SCC_QUADRA 3
+#define MAC_SCC_PSC 4
#define MAC_ETHER_NONE 0
#define MAC_ETHER_SONIC 1
@@ -139,6 +139,7 @@ struct mac_model
#define MAC_MODEL_P475F 90 /* aka: P475 w/ FPU (no LC040) */
#define MAC_MODEL_P575 92 /* aka: LC575, P577/P578 */
#define MAC_MODEL_Q605 94
+#define MAC_MODEL_Q605_ACC 95 /* Q605 accelerated to 33 MHz */
#define MAC_MODEL_Q630 98 /* aka: LC630, P630/631/635/636/637/638/640 */
#define MAC_MODEL_P588 99 /* aka: LC580, P580 */
#define MAC_MODEL_PB280 102
diff --git a/include/asm-m68k/mman.h b/include/asm-m68k/mman.h
index a171fb7c7acf..59c2d3c265d1 100644
--- a/include/asm-m68k/mman.h
+++ b/include/asm-m68k/mman.h
@@ -18,6 +18,8 @@
#define MAP_EXECUTABLE 0x1000 /* mark it as an executable */
#define MAP_LOCKED 0x2000 /* pages are locked */
#define MAP_NORESERVE 0x4000 /* don't check for reservations */
+#define MAP_POPULATE 0x8000 /* populate (prefault) pagetables */
+#define MAP_NONBLOCK 0x10000 /* do not block on IO */
#define MS_ASYNC 1 /* sync memory asynchronously */
#define MS_INVALIDATE 2 /* invalidate the caches */
diff --git a/include/asm-m68k/module.h b/include/asm-m68k/module.h
index a978a053c89f..c6d75af2d8d3 100644
--- a/include/asm-m68k/module.h
+++ b/include/asm-m68k/module.h
@@ -1,12 +1,7 @@
#ifndef _ASM_M68K_MODULE_H
#define _ASM_M68K_MODULE_H
-/*
- * This file contains the m68k architecture specific module code.
- */
-
-#define module_map(x) vmalloc(x)
-#define module_unmap(x) vfree(x)
-#define module_arch_init(x) (0)
-#define arch_init_modules(x) do { } while (0)
-
+struct mod_arch_specific { };
+#define Elf_Shdr Elf32_Shdr
+#define Elf_Sym Elf32_Sym
+#define Elf_Ehdr Elf32_Ehdr
#endif /* _ASM_M68K_MODULE_H */
diff --git a/include/asm-m68k/sbus.h b/include/asm-m68k/sbus.h
index ed76953cafb1..5dd2fac1b9ce 100644
--- a/include/asm-m68k/sbus.h
+++ b/include/asm-m68k/sbus.h
@@ -5,7 +5,7 @@
#ifndef __M68K_SBUS_H
#define __M68K_SBUS_H
-struct linux_sbus_device {
+struct sbus_dev {
struct {
unsigned int which_io;
unsigned int phys_addr;
diff --git a/include/asm-m68k/system.h b/include/asm-m68k/system.h
index 8fe94c6017fd..112ea2a6a047 100644
--- a/include/asm-m68k/system.h
+++ b/include/asm-m68k/system.h
@@ -74,12 +74,14 @@ static inline int irqs_disabled(void)
#define mb() barrier()
#define rmb() barrier()
#define wmb() barrier()
+#define read_barrier_depends() do { } while(0)
#define set_mb(var, value) do { xchg(&var, value); } while (0)
#define set_wmb(var, value) do { var = value; wmb(); } while (0)
#define smp_mb() barrier()
#define smp_rmb() barrier()
#define smp_wmb() barrier()
+#define smp_read_barrier_depends() do { } while(0)
#define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
diff --git a/include/asm-m68k/thread_info.h b/include/asm-m68k/thread_info.h
index 55244ef06d37..49988674166f 100644
--- a/include/asm-m68k/thread_info.h
+++ b/include/asm-m68k/thread_info.h
@@ -10,6 +10,7 @@ struct thread_info {
struct exec_domain *exec_domain; /* execution domain */
__s32 preempt_count; /* 0 => preemptable, <0 => BUG */
__u32 cpu; /* should always be 0 on m68k */
+ struct restart_block restart_block;
__u8 supervisor_stack[0];
};
@@ -20,6 +21,9 @@ struct thread_info {
{ \
.task = &tsk, \
.exec_domain = &default_exec_domain, \
+ .restart_block = { \
+ .fn = do_no_restart_syscall, \
+ }, \
}
/* THREAD_SIZE should be 8k, so handle differently for 4k and 8k machines */
diff --git a/include/asm-um/a.out.h b/include/asm-um/a.out.h
index 2e208223f860..7c26265e1d7a 100644
--- a/include/asm-um/a.out.h
+++ b/include/asm-um/a.out.h
@@ -1,7 +1,9 @@
#ifndef __UM_A_OUT_H
#define __UM_A_OUT_H
+#include "linux/config.h"
#include "asm/arch/a.out.h"
+#include "choose-mode.h"
#undef STACK_TOP
@@ -9,10 +11,10 @@ extern unsigned long stacksizelim;
extern unsigned long host_task_size;
-extern int honeypot;
-
#define STACK_ROOM (stacksizelim)
-#define STACK_TOP (honeypot ? host_task_size : task_size)
+extern int honeypot;
+#define STACK_TOP \
+ CHOOSE_MODE((honeypot ? host_task_size : task_size), task_size)
#endif
diff --git a/include/asm-um/checksum.h b/include/asm-um/checksum.h
index 4b38f37c822e..5b501361e361 100644
--- a/include/asm-um/checksum.h
+++ b/include/asm-um/checksum.h
@@ -1,6 +1,6 @@
#ifndef __UM_CHECKSUM_H
#define __UM_CHECKSUM_H
-#include "asm/arch/checksum.h"
+#include "sysdep/checksum.h"
#endif
diff --git a/include/asm-um/mmu.h b/include/asm-um/mmu.h
index d276d24f07df..2cf35c21d694 100644
--- a/include/asm-um/mmu.h
+++ b/include/asm-um/mmu.h
@@ -1,6 +1,22 @@
+/*
+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
#ifndef __MMU_H
#define __MMU_H
-#include "asm/arch/mmu.h"
+#include "um_mmu.h"
#endif
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only. This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff --git a/include/asm-um/mmu_context.h b/include/asm-um/mmu_context.h
index 56ef77e1c1c8..e735fe0a95a9 100644
--- a/include/asm-um/mmu_context.h
+++ b/include/asm-um/mmu_context.h
@@ -1,20 +1,33 @@
+/*
+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
#ifndef __UM_MMU_CONTEXT_H
#define __UM_MMU_CONTEXT_H
#include "linux/sched.h"
+#include "choose-mode.h"
-#define init_new_context(task, mm) (0)
#define get_mmu_context(task) do ; while(0)
#define activate_context(tsk) do ; while(0)
-#define destroy_context(mm) do ; while(0)
static inline void activate_mm(struct mm_struct *old, struct mm_struct *new)
{
}
+extern void switch_mm_skas(int mm_fd);
+
static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
struct task_struct *tsk, unsigned cpu)
{
+ if(prev != next){
+ clear_bit(cpu, &prev->cpu_vm_mask);
+ set_bit(cpu, &next->cpu_vm_mask);
+ if(next != &init_mm)
+ CHOOSE_MODE((void) 0,
+ switch_mm_skas(next->context.skas.mm_fd));
+ }
}
static inline void enter_lazy_tlb(struct mm_struct *mm,
@@ -22,4 +35,38 @@ static inline void enter_lazy_tlb(struct mm_struct *mm,
{
}
+extern int init_new_context_skas(struct task_struct *task,
+ struct mm_struct *mm);
+
+static inline int init_new_context_tt(struct task_struct *task,
+ struct mm_struct *mm)
+{
+ return(0);
+}
+
+static inline int init_new_context(struct task_struct *task,
+ struct mm_struct *mm)
+{
+ return(CHOOSE_MODE_PROC(init_new_context_tt, init_new_context_skas,
+ task, mm));
+}
+
+extern void destroy_context_skas(struct mm_struct *mm);
+
+static inline void destroy_context(struct mm_struct *mm)
+{
+ CHOOSE_MODE((void) 0, destroy_context_skas(mm));
+}
+
#endif
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only. This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff --git a/include/asm-um/page.h b/include/asm-um/page.h
index e3279d1d0b31..f4c0f7eb0d05 100644
--- a/include/asm-um/page.h
+++ b/include/asm-um/page.h
@@ -18,6 +18,8 @@ struct page;
#undef PAGE_OFFSET
#undef KERNELBASE
+extern unsigned long uml_physmem;
+
#define PAGE_OFFSET (uml_physmem)
#define KERNELBASE PAGE_OFFSET
diff --git a/include/asm-um/pgtable.h b/include/asm-um/pgtable.h
index a79a756c3989..8d607c87418d 100644
--- a/include/asm-um/pgtable.h
+++ b/include/asm-um/pgtable.h
@@ -373,15 +373,15 @@ static inline pmd_t * pmd_offset(pgd_t * dir, unsigned long address)
}
/* Find an entry in the third-level page table.. */
-#define __pte_offset(address) ((address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
+#define __pte_offset(address) (((address) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
#define pte_offset_kernel(dir, address) \
((pte_t *) pmd_page_kernel(*(dir)) + __pte_offset(address))
#define pte_offset_map(dir, address) \
((pte_t *)kmap_atomic(pmd_page(*(dir)),KM_PTE0) + __pte_offset(address))
#define pte_offset_map_nested(dir, address) \
((pte_t *)kmap_atomic(pmd_page(*(dir)),KM_PTE1) + __pte_offset(address))
-#define pte_unmap(pte) kunmap_atomic(pte, KM_PTE0)
-#define pte_unmap_nested(pte) kunmap_atomic(pte, KM_PTE1)
+#define pte_unmap(pte) kunmap_atomic((pte), KM_PTE0)
+#define pte_unmap_nested(pte) kunmap_atomic((pte), KM_PTE1)
#if defined(CONFIG_HIGHPTE) && defined(CONFIG_HIGHMEM4G)
typedef u32 pte_addr_t;
diff --git a/include/asm-um/processor-generic.h b/include/asm-um/processor-generic.h
index 7e771b8ca7db..435380cc08d7 100644
--- a/include/asm-um/processor-generic.h
+++ b/include/asm-um/processor-generic.h
@@ -12,9 +12,9 @@ struct task_struct;
#include "linux/config.h"
#include "linux/signal.h"
-#include "asm/segment.h"
#include "asm/ptrace.h"
#include "asm/siginfo.h"
+#include "choose-mode.h"
struct mm_struct;
@@ -22,9 +22,24 @@ struct mm_struct;
#define cpu_relax() do ; while (0)
-struct thread_struct {
+#ifdef CONFIG_MODE_TT
+struct proc_tt_mode {
int extern_pid;
int tracing;
+ int switch_pipe[2];
+ int singlestep_syscall;
+ int vm_seq;
+};
+#endif
+
+#ifdef CONFIG_MODE_SKAS
+struct proc_skas_mode {
+ void *switch_buf;
+ void *fork_buf;
+};
+#endif
+
+struct thread_struct {
int forking;
unsigned long kernel_stack;
int nsyscalls;
@@ -33,13 +48,18 @@ struct thread_struct {
int err;
void *fault_addr;
void *fault_catcher;
- int vm_seq;
struct task_struct *prev_sched;
unsigned long temp_stack;
- int switch_pipe[2];
- void *jmp;
+ void *exec_buf;
struct arch_thread arch;
- int singlestep_syscall;
+ union {
+#ifdef CONFIG_MODE_TT
+ struct proc_tt_mode tt;
+#endif
+#ifdef CONFIG_MODE_SKAS
+ struct proc_skas_mode skas;
+#endif
+ } mode;
struct {
int op;
union {
@@ -60,8 +80,6 @@ struct thread_struct {
#define INIT_THREAD \
{ \
- extern_pid: -1, \
- tracing: 0, \
forking: 0, \
kernel_stack: 0, \
nsyscalls: 0, \
@@ -69,13 +87,10 @@ struct thread_struct {
cr2: 0, \
err: 0, \
fault_addr: NULL, \
- vm_seq: 0, \
prev_sched: NULL, \
temp_stack: 0, \
- switch_pipe: { -1, -1 }, \
- jmp: NULL, \
+ exec_buf: NULL, \
arch: INIT_ARCH_THREAD, \
- singlestep_syscall: 0, \
request: { 0 } \
}
diff --git a/include/asm-um/ptrace-generic.h b/include/asm-um/ptrace-generic.h
index 18f6b5991856..0a5f77de79ba 100644
--- a/include/asm-um/ptrace-generic.h
+++ b/include/asm-um/ptrace-generic.h
@@ -8,6 +8,8 @@
#ifndef __ASSEMBLY__
+#include "linux/config.h"
+#include "skas_ptrace.h"
#include "asm/current.h"
#define pt_regs pt_regs_subarch
diff --git a/include/asm-um/system-generic.h b/include/asm-um/system-generic.h
index 24d97e5fcf20..80b24a31b5fe 100644
--- a/include/asm-um/system-generic.h
+++ b/include/asm-um/system-generic.h
@@ -17,6 +17,7 @@
extern void *switch_to(void *prev, void *next, void *last);
+extern int get_signals(void);
extern int set_signals(int enable);
extern int get_signals(void);
extern void block_signals(void);
diff --git a/include/asm-um/thread_info.h b/include/asm-um/thread_info.h
index 1cb0f45359f5..bd3f4fe40c6b 100644
--- a/include/asm-um/thread_info.h
+++ b/include/asm-um/thread_info.h
@@ -20,14 +20,9 @@ struct thread_info {
mm_segment_t addr_limit; /* thread address space:
0-0xBFFFFFFF for user
0-0xFFFFFFFF for kernel */
+ struct restart_block restart_block;
};
-/*
- * macros/functions for gaining access to the thread information structure
- *
- * preempt_count needs to be 1 initially, until the scheduler is functional.
- */
-
#define INIT_THREAD_INFO(tsk) \
{ \
task: &tsk, \
@@ -36,6 +31,9 @@ struct thread_info {
cpu: 0, \
preempt_count: 1, \
addr_limit: KERNEL_DS, \
+ restart_block: { \
+ fn: do_no_restart_syscall, \
+ }, \
}
#define init_thread_info (init_thread_union.thread_info)
diff --git a/include/asm-um/uaccess.h b/include/asm-um/uaccess.h
index a8a7dfb7e4c8..e1dfea108857 100644
--- a/include/asm-um/uaccess.h
+++ b/include/asm-um/uaccess.h
@@ -1,18 +1,11 @@
/*
- * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
* Licensed under the GPL
*/
#ifndef __UM_UACCESS_H
#define __UM_UACCESS_H
-#include "linux/string.h"
-#include "linux/sched.h"
-#include "asm/processor.h"
-#include "asm/errno.h"
-#include "asm/current.h"
-#include "asm/a.out.h"
-
#define VERIFY_READ 0
#define VERIFY_WRITE 1
@@ -26,8 +19,6 @@
#define MAKE_MM_SEG(s) ((mm_segment_t) { (s) })
-#define ABOVE_KMEM (16 * 1024 * 1024)
-
#define KERNEL_DS MAKE_MM_SEG(0xFFFFFFFF)
#define USER_DS MAKE_MM_SEG(TASK_SIZE)
@@ -35,56 +26,12 @@
#define get_fs() (current_thread_info()->addr_limit)
#define set_fs(x) (current_thread_info()->addr_limit = (x))
-extern unsigned long end_vm;
-extern unsigned long uml_physmem;
-
-#define under_task_size(addr, size) \
- (((unsigned long) (addr) < TASK_SIZE) && \
- (((unsigned long) (addr) + (size)) < TASK_SIZE))
-
-#define is_stack(addr, size) \
- (((unsigned long) (addr) < STACK_TOP) && \
- ((unsigned long) (addr) >= STACK_TOP - ABOVE_KMEM) && \
- (((unsigned long) (addr) + (size)) <= STACK_TOP))
-
#define segment_eq(a, b) ((a).seg == (b).seg)
-#define access_ok(type, addr, size) \
- ((type == VERIFY_READ) || (segment_eq(get_fs(), KERNEL_DS)) || \
- (((unsigned long) (addr) <= ((unsigned long) (addr) + (size))) && \
- (under_task_size(addr, size) || is_stack(addr, size))))
-
-static inline int verify_area(int type, const void * addr, unsigned long size)
-{
- return(access_ok(type, addr, size) ? 0 : -EFAULT);
-}
-
-extern unsigned long get_fault_addr(void);
-
-extern int __do_copy_from_user(void *to, const void *from, int n,
- void **fault_addr, void **fault_catcher);
-
-static inline int copy_from_user(void *to, const void *from, int n)
-{
- return(access_ok(VERIFY_READ, from, n) ?
- __do_copy_from_user(to, from, n,
- &current->thread.fault_addr,
- &current->thread.fault_catcher) : n);
-}
+#include "um_uaccess.h"
#define __copy_from_user(to, from, n) copy_from_user(to, from, n)
-extern int __do_copy_to_user(void *to, const void *from, int n,
- void **fault_addr, void **fault_catcher);
-
-static inline int copy_to_user(void *to, const void *from, int n)
-{
- return(access_ok(VERIFY_WRITE, to, n) ?
- __do_copy_to_user(to, from, n,
- &current->thread.fault_addr,
- &current->thread.fault_catcher) : n);
-}
-
#define __copy_to_user(to, from, n) copy_to_user(to, from, n)
#define __get_user(x, ptr) \
@@ -128,49 +75,6 @@ static inline int copy_to_user(void *to, const void *from, int n)
__put_user(x, private_ptr) : -EFAULT); \
})
-extern int __do_strncpy_from_user(char *dst, const char *src, size_t n,
- void **fault_addr, void **fault_catcher);
-
-static inline int strncpy_from_user(char *dst, const char *src, int count)
-{
- int n;
-
- if(!access_ok(VERIFY_READ, src, 1)) return(-EFAULT);
- n = __do_strncpy_from_user(dst, src, count,
- &current->thread.fault_addr,
- &current->thread.fault_catcher);
- if(n < 0) return(-EFAULT);
- return(n);
-}
-
-extern int __do_clear_user(void *mem, size_t len, void **fault_addr,
- void **fault_catcher);
-
-static inline int __clear_user(void *mem, int len)
-{
- return(__do_clear_user(mem, len,
- &current->thread.fault_addr,
- &current->thread.fault_catcher));
-}
-
-static inline int clear_user(void *mem, int len)
-{
- return(access_ok(VERIFY_WRITE, mem, len) ?
- __do_clear_user(mem, len,
- &current->thread.fault_addr,
- &current->thread.fault_catcher) : len);
-}
-
-extern int __do_strnlen_user(const char *str, unsigned long n,
- void **fault_addr, void **fault_catcher);
-
-static inline int strnlen_user(void *str, int len)
-{
- return(__do_strnlen_user(str, len,
- &current->thread.fault_addr,
- &current->thread.fault_catcher));
-}
-
#define strlen_user(str) strnlen_user(str, ~0UL >> 1)
struct exception_table_entry
diff --git a/include/asm-x86_64/bitops.h b/include/asm-x86_64/bitops.h
index 72e575a68a33..c98d3c64bba0 100644
--- a/include/asm-x86_64/bitops.h
+++ b/include/asm-x86_64/bitops.h
@@ -244,7 +244,7 @@ static __inline__ int constant_test_bit(int nr, const volatile void * addr)
return ((1UL << (nr & 31)) & (((const volatile unsigned int *) addr)[nr >> 5])) != 0;
}
-static __inline__ int variable_test_bit(int nr, volatile void * addr)
+static __inline__ int variable_test_bit(int nr, volatile const void * addr)
{
int oldbit;
diff --git a/include/asm-x86_64/desc.h b/include/asm-x86_64/desc.h
index f5775b7ddde5..724777a946f6 100644
--- a/include/asm-x86_64/desc.h
+++ b/include/asm-x86_64/desc.h
@@ -131,7 +131,7 @@ static inline void set_tss_desc(unsigned cpu, void *addr)
static inline void set_ldt_desc(unsigned cpu, void *addr, int size)
{
- set_tssldt_descriptor(&cpu_gdt_table[cpu][GDT_ENTRY_TSS], (unsigned long)addr,
+ set_tssldt_descriptor(&cpu_gdt_table[cpu][GDT_ENTRY_LDT], (unsigned long)addr,
DESC_LDT, size);
}
diff --git a/include/asm-x86_64/dma-mapping.h b/include/asm-x86_64/dma-mapping.h
deleted file mode 100644
index e7e16901f686..000000000000
--- a/include/asm-x86_64/dma-mapping.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/dma-mapping.h>
diff --git a/include/asm-x86_64/hw_irq.h b/include/asm-x86_64/hw_irq.h
index 9d7d039d5222..bb096fb7ab06 100644
--- a/include/asm-x86_64/hw_irq.h
+++ b/include/asm-x86_64/hw_irq.h
@@ -168,9 +168,24 @@ static inline void x86_do_profile (struct pt_regs *regs)
struct notifier_block;
+#ifdef CONFIG_PROFILING
+
int register_profile_notifier(struct notifier_block * nb);
int unregister_profile_notifier(struct notifier_block * nb);
+#else
+
+static inline int register_profile_notifier(struct notifier_block * nb)
+{
+ return -ENOSYS;
+}
+
+static inline int unregister_profile_notifier(struct notifier_block * nb)
+{
+ return -ENOSYS;
+}
+
+#endif /* CONFIG_PROFILING */
#ifdef CONFIG_SMP /*more of this file should probably be ifdefed SMP */
static inline void hw_resend_irq(struct hw_interrupt_type *h, unsigned int i) {
if (IO_APIC_IRQ(i))
diff --git a/include/asm-x86_64/ia32.h b/include/asm-x86_64/ia32.h
index f257195d1740..23d4d607a398 100644
--- a/include/asm-x86_64/ia32.h
+++ b/include/asm-x86_64/ia32.h
@@ -202,7 +202,7 @@ struct iovec32 {
int iov_len;
};
-#define IA32_PAGE_OFFSET 0xffff0000
+#define IA32_PAGE_OFFSET 0xffffe000
#define IA32_STACK_TOP IA32_PAGE_OFFSET
#endif /* !CONFIG_IA32_SUPPORT */
diff --git a/include/asm-x86_64/io_apic.h b/include/asm-x86_64/io_apic.h
index 2975afd3f3e5..d5e3a3a81282 100644
--- a/include/asm-x86_64/io_apic.h
+++ b/include/asm-x86_64/io_apic.h
@@ -3,6 +3,7 @@
#include <linux/config.h>
#include <asm/types.h>
+#include <asm/mpspec.h>
/*
* Intel IO-APIC support for SMP and UP systems.
diff --git a/include/asm-x86_64/processor.h b/include/asm-x86_64/processor.h
index 075a49ff9ba4..9c84b14139f2 100644
--- a/include/asm-x86_64/processor.h
+++ b/include/asm-x86_64/processor.h
@@ -256,7 +256,7 @@ static inline void clear_in_cr4 (unsigned long mask)
/* This decides where the kernel will search for a free chunk of vm
* space during mmap's.
*/
-#define TASK_UNMAPPED_32 0x40000000
+#define TASK_UNMAPPED_32 0xa0000000
#define TASK_UNMAPPED_64 PAGE_ALIGN(TASK_SIZE/3)
#define TASK_UNMAPPED_BASE \
(test_thread_flag(TIF_IA32) ? TASK_UNMAPPED_32 : TASK_UNMAPPED_64)
diff --git a/include/asm-x86_64/proto.h b/include/asm-x86_64/proto.h
index a9f8d7e16ee6..9ca683849c42 100644
--- a/include/asm-x86_64/proto.h
+++ b/include/asm-x86_64/proto.h
@@ -42,6 +42,8 @@ extern void exception_table_check(void);
extern int acpi_boot_init(char *);
+extern int map_syscall32(struct mm_struct *mm, unsigned long address);
+
#define round_up(x,y) (((x) + (y) - 1) & ~((y)-1))
#define round_down(x,y) ((x) & ~((y)-1))
diff --git a/include/asm-x86_64/spinlock.h b/include/asm-x86_64/spinlock.h
index 52047a7e928b..b502884f490a 100644
--- a/include/asm-x86_64/spinlock.h
+++ b/include/asm-x86_64/spinlock.h
@@ -48,8 +48,8 @@ typedef struct {
"js 2f\n" \
LOCK_SECTION_START("") \
"2:\t" \
- "cmpb $0,%0\n\t" \
"rep;nop\n\t" \
+ "cmpb $0,%0\n\t" \
"jle 2b\n\t" \
"jmp 1b\n" \
LOCK_SECTION_END
diff --git a/include/asm-x86_64/system.h b/include/asm-x86_64/system.h
index f1281d48dc93..268865b34785 100644
--- a/include/asm-x86_64/system.h
+++ b/include/asm-x86_64/system.h
@@ -254,7 +254,12 @@ static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
*/
#define mb() asm volatile("mfence":::"memory")
#define rmb() asm volatile("lfence":::"memory")
-#define wmb() asm volatile("sfence":::"memory")
+
+/* could use SFENCE here, but it would be only needed for unordered SSE
+ store instructions and we always do an explicit sfence with them currently.
+ the ordering of normal stores is serialized enough. Just make it a compile
+ barrier. */
+#define wmb() asm volatile("" ::: "memory")
#define read_barrier_depends() do {} while(0)
#define set_mb(var, value) do { xchg(&var, value); } while (0)
#define set_wmb(var, value) do { var = value; wmb(); } while (0)
diff --git a/include/asm-x86_64/thread_info.h b/include/asm-x86_64/thread_info.h
index 69cac4da715d..9f034cf938d1 100644
--- a/include/asm-x86_64/thread_info.h
+++ b/include/asm-x86_64/thread_info.h
@@ -100,6 +100,7 @@ static inline struct thread_info *stack_thread_info(void)
#define TIF_NOTIFY_RESUME 1 /* resumption notification requested */
#define TIF_SIGPENDING 2 /* signal pending */
#define TIF_NEED_RESCHED 3 /* rescheduling necessary */
+#define TIF_SINGLESTEP 4 /* reenable singlestep on user return*/
#define TIF_USEDFPU 16 /* FPU was used by this task this quantum */
#define TIF_POLLING_NRFLAG 17 /* true if poll_idle() is polling TIF_NEED_RESCHED */
#define TIF_IA32 18 /* 32bit process */
@@ -107,6 +108,7 @@ static inline struct thread_info *stack_thread_info(void)
#define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE)
#define _TIF_NOTIFY_RESUME (1<<TIF_NOTIFY_RESUME)
#define _TIF_SIGPENDING (1<<TIF_SIGPENDING)
+#define _TIF_SINGLESTEP (1<<TIF_SINGLESTEP)
#define _TIF_NEED_RESCHED (1<<TIF_NEED_RESCHED)
#define _TIF_USEDFPU (1<<TIF_USEDFPU)
#define _TIF_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG)
diff --git a/include/asm-x86_64/uaccess.h b/include/asm-x86_64/uaccess.h
index 3cb62ac5fb08..065eb4c8dafb 100644
--- a/include/asm-x86_64/uaccess.h
+++ b/include/asm-x86_64/uaccess.h
@@ -103,7 +103,8 @@ extern void __get_user_8(void);
/* Careful: we have to cast the result to the type of the pointer for sign reasons */
#define get_user(x,ptr) \
-({ long __ret_gu,__val_gu; \
+({ long __val_gu; \
+ int __ret_gu; \
switch(sizeof (*(ptr))) { \
case 1: __get_user_x(1,__ret_gu,__val_gu,ptr); break; \
case 2: __get_user_x(2,__ret_gu,__val_gu,ptr); break; \
@@ -138,7 +139,7 @@ extern void __put_user_bad(void);
#define __put_user_nocheck(x,ptr,size) \
({ \
- long __pu_err; \
+ int __pu_err; \
__put_user_size((x),(ptr),(size),__pu_err); \
__pu_err; \
})
@@ -146,7 +147,7 @@ extern void __put_user_bad(void);
#define __put_user_check(x,ptr,size) \
({ \
- long __pu_err = -EFAULT; \
+ int __pu_err = -EFAULT; \
__typeof__(*(ptr)) *__pu_addr = (ptr); \
if (access_ok(VERIFY_WRITE,__pu_addr,size)) \
__put_user_size((x),__pu_addr,(size),__pu_err); \
@@ -157,10 +158,10 @@ extern void __put_user_bad(void);
do { \
retval = 0; \
switch (size) { \
- case 1: __put_user_asm(x,ptr,retval,"b","b","iq"); break; \
- case 2: __put_user_asm(x,ptr,retval,"w","w","ir"); break; \
- case 4: __put_user_asm(x,ptr,retval,"l","k","ir"); break; \
- case 8: __put_user_asm(x,ptr,retval,"q","","ir"); break; \
+ case 1: __put_user_asm(x,ptr,retval,"b","b","iq",-EFAULT); break;\
+ case 2: __put_user_asm(x,ptr,retval,"w","w","ir",-EFAULT); break;\
+ case 4: __put_user_asm(x,ptr,retval,"l","k","ir",-EFAULT); break;\
+ case 8: __put_user_asm(x,ptr,retval,"q","","ir",-EFAULT); break;\
default: __put_user_bad(); \
} \
} while (0)
@@ -174,12 +175,12 @@ struct __large_struct { unsigned long buf[100]; };
* we do not write to any memory gcc knows about, so there are no
* aliasing issues.
*/
-#define __put_user_asm(x, addr, err, itype, rtype, ltype) \
+#define __put_user_asm(x, addr, err, itype, rtype, ltype, errno) \
__asm__ __volatile__( \
"1: mov"itype" %"rtype"1,%2\n" \
"2:\n" \
".section .fixup,\"ax\"\n" \
- "3: movq %3,%0\n" \
+ "3: mov %3,%0\n" \
" jmp 2b\n" \
".previous\n" \
".section __ex_table,\"a\"\n" \
@@ -187,32 +188,33 @@ struct __large_struct { unsigned long buf[100]; };
" .quad 1b,3b\n" \
".previous" \
: "=r"(err) \
- : ltype (x), "m"(__m(addr)), "i"(-EFAULT), "0"(err))
+ : ltype (x), "m"(__m(addr)), "i"(errno), "0"(err))
#define __get_user_nocheck(x,ptr,size) \
({ \
- long __gu_err, __gu_val; \
+ int __gu_err; \
+ long __gu_val; \
__get_user_size(__gu_val,(ptr),(size),__gu_err); \
(x) = (__typeof__(*(ptr)))__gu_val; \
__gu_err; \
})
-extern long __get_user_bad(void);
+extern int __get_user_bad(void);
#define __get_user_size(x,ptr,size,retval) \
do { \
retval = 0; \
switch (size) { \
- case 1: __get_user_asm(x,ptr,retval,"b","b","=q"); break; \
- case 2: __get_user_asm(x,ptr,retval,"w","w","=r"); break; \
- case 4: __get_user_asm(x,ptr,retval,"l","k","=r"); break; \
- case 8: __get_user_asm(x,ptr,retval,"q","","=r"); break; \
+ case 1: __get_user_asm(x,ptr,retval,"b","b","=q",-EFAULT); break;\
+ case 2: __get_user_asm(x,ptr,retval,"w","w","=r",-EFAULT); break;\
+ case 4: __get_user_asm(x,ptr,retval,"l","k","=r",-EFAULT); break;\
+ case 8: __get_user_asm(x,ptr,retval,"q","","=r",-EFAULT); break;\
default: (x) = __get_user_bad(); \
} \
} while (0)
-#define __get_user_asm(x, addr, err, itype, rtype, ltype) \
+#define __get_user_asm(x, addr, err, itype, rtype, ltype, errno) \
__asm__ __volatile__( \
"1: mov"itype" %2,%"rtype"1\n" \
"2:\n" \
@@ -226,23 +228,77 @@ do { \
" .quad 1b,3b\n" \
".previous" \
: "=r"(err), ltype (x) \
- : "m"(__m(addr)), "i"(-EFAULT), "0"(err))
+ : "m"(__m(addr)), "i"(errno), "0"(err))
/*
* Copy To/From Userspace
- *
- * This relies on an optimized common worker function.
- *
- * Could do special inline versions for small constant copies, but avoid this
- * for now. It's not clear it is worth it.
*/
+/* Handles exceptions in both to and from, but doesn't do access_ok */
extern unsigned long copy_user_generic(void *to, const void *from, unsigned len);
extern unsigned long copy_to_user(void *to, const void *from, unsigned len);
extern unsigned long copy_from_user(void *to, const void *from, unsigned len);
-#define __copy_to_user copy_user_generic
-#define __copy_from_user copy_user_generic
+
+static inline int __copy_from_user(void *dst, void *src, unsigned size)
+{
+ if (!__builtin_constant_p(size))
+ return copy_user_generic(dst,src,size);
+ int ret = 0;
+ switch (size) {
+ case 1:__get_user_asm(*(u8*)dst,(u8 *)src,ret,"b","b","=q",1);
+ return ret;
+ case 2:__get_user_asm(*(u16*)dst,(u16*)src,ret,"w","w","=r",2);
+ return ret;
+ case 4:__get_user_asm(*(u32*)dst,(u32*)src,ret,"l","k","=r",4);
+ return ret;
+ case 8:__get_user_asm(*(u64*)dst,(u64*)src,ret,"q","","=r",8);
+ return ret;
+ case 10:
+ __get_user_asm(*(u64*)dst,(u64*)src,ret,"q","","=r",16);
+ if (ret) return ret;
+ __get_user_asm(*(u16*)(8+dst),(u16*)(8+src),ret,"w","w","=r",2);
+ return ret;
+ case 16:
+ __get_user_asm(*(u64*)dst,(u64*)src,ret,"q","","=r",16);
+ if (ret) return ret;
+ __get_user_asm(*(u64*)(8+dst),(u64*)(8+src),ret,"q","","=r",8);
+ return ret;
+ default:
+ return copy_user_generic(dst,src,size);
+ }
+}
+
+static inline int __copy_to_user(void *dst, void *src, unsigned size)
+{
+ if (!__builtin_constant_p(size))
+ return copy_user_generic(dst,src,size);
+ int ret = 0;
+ switch (size) {
+ case 1:__put_user_asm(*(u8*)src,(u8 *)dst,ret,"b","b","iq",1);
+ return ret;
+ case 2:__put_user_asm(*(u16*)src,(u16*)dst,ret,"w","w","ir",2);
+ return ret;
+ case 4:__put_user_asm(*(u32*)src,(u32*)dst,ret,"l","k","ir",4);
+ return ret;
+ case 8:__put_user_asm(*(u64*)src,(u64*)dst,ret,"q","","ir",8);
+ return ret;
+ case 10:
+ __put_user_asm(*(u64*)src,(u64*)dst,ret,"q","","ir",10);
+ if (ret) return ret;
+ asm("":::"memory");
+ __put_user_asm(4[(u16*)src],4+(u16*)dst,ret,"w","w","ir",2);
+ return ret;
+ case 16:
+ __put_user_asm(*(u64*)src,(u64*)dst,ret,"q","","ir",16);
+ if (ret) return ret;
+ asm("":::"memory");
+ __put_user_asm(1[(u64*)src],1+(u64*)dst,ret,"q","","ir",8);
+ return ret;
+ default:
+ return copy_user_generic(dst,src,size);
+ }
+}
long strncpy_from_user(char *dst, const char *src, long count);
long __strncpy_from_user(char *dst, const char *src, long count);
diff --git a/include/linux/ax25.h b/include/linux/ax25.h
index 6dfc8fc9116d..56c11f0dbd80 100644
--- a/include/linux/ax25.h
+++ b/include/linux/ax25.h
@@ -85,7 +85,7 @@ struct ax25_ctl_struct {
};
/* this will go away. Please do not export to user land */
-struct ax25_info_struct_depreciated {
+struct ax25_info_struct_deprecated {
unsigned int n2, n2count;
unsigned int t1, t1timer;
unsigned int t2, t2timer;
diff --git a/include/linux/binfmts.h b/include/linux/binfmts.h
index ae1b454395b5..bd929e344d75 100644
--- a/include/linux/binfmts.h
+++ b/include/linux/binfmts.h
@@ -58,13 +58,7 @@ extern int copy_strings(int argc,char ** argv,struct linux_binprm *bprm);
extern int copy_strings_kernel(int argc,char ** argv,struct linux_binprm *bprm);
extern void compute_creds(struct linux_binprm *binprm);
extern int do_coredump(long signr, int exit_code, struct pt_regs * regs);
-extern void set_binfmt(struct linux_binfmt *new);
-
-
-#if 0
-/* this went away now */
-#define change_ldt(a,b) setup_arg_pages(a,b)
-#endif
+extern int set_binfmt(struct linux_binfmt *new);
#endif /* __KERNEL__ */
#endif /* _LINUX_BINFMTS_H */
diff --git a/include/linux/compiler.h b/include/linux/compiler.h
index 6b19413b47a6..f88889740949 100644
--- a/include/linux/compiler.h
+++ b/include/linux/compiler.h
@@ -13,6 +13,19 @@
#define likely(x) __builtin_expect((x),1)
#define unlikely(x) __builtin_expect((x),0)
+/*
+ * Allow us to mark functions as 'deprecated' and have gcc emit a nice
+ * warning for each use, in hopes of speeding the functions removal.
+ * Usage is:
+ * int deprecated foo(void)
+ * and then gcc will emit a warning for each usage of the function.
+ */
+#if __GNUC__ >= 3
+#define __deprecated __attribute__((deprecated))
+#else
+#define __deprecated
+#endif
+
/* This macro obfuscates arithmetic on a variable address so that gcc
shouldn't recognize the original var, and make assumptions about it */
#define RELOC_HIDE(ptr, off) \
diff --git a/include/linux/fb.h b/include/linux/fb.h
index 23dd4c02ddec..188da2f94589 100644
--- a/include/linux/fb.h
+++ b/include/linux/fb.h
@@ -424,9 +424,11 @@ struct fb_info {
#define fb_readb __raw_readb
#define fb_readw __raw_readw
#define fb_readl __raw_readl
+#define fb_readq __raw_readq
#define fb_writeb __raw_writeb
#define fb_writew __raw_writew
#define fb_writel __raw_writel
+#define fb_writeq __raw_writeq
#define fb_memset memset_io
#else
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 500cb3ac421e..6c3188b991e6 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -983,13 +983,13 @@ struct super_block *get_sb_pseudo(struct file_system_type *, char *,
/* Alas, no aliases. Too much hassle with bringing module.h everywhere */
#define fops_get(fops) \
(((fops) && (fops)->owner) \
- ? ( try_inc_mod_count((fops)->owner) ? (fops) : NULL ) \
+ ? (try_inc_mod_count((fops)->owner) ? (fops) : NULL) \
: (fops))
#define fops_put(fops) \
do { \
if ((fops) && (fops)->owner) \
- __MOD_DEC_USE_COUNT((fops)->owner); \
+ module_put((fops)->owner); \
} while(0)
extern int register_filesystem(struct file_system_type *);
@@ -1300,6 +1300,7 @@ extern int dcache_dir_open(struct inode *, struct file *);
extern int dcache_dir_close(struct inode *, struct file *);
extern loff_t dcache_dir_lseek(struct file *, loff_t, int);
extern int dcache_readdir(struct file *, void *, filldir_t);
+extern int simple_getattr(struct vfsmount *, struct dentry *, struct kstat *);
extern int simple_statfs(struct super_block *, struct statfs *);
extern int simple_link(struct dentry *, struct inode *, struct dentry *);
extern int simple_unlink(struct inode *, struct dentry *);
diff --git a/include/linux/i2c-id.h b/include/linux/i2c-id.h
index 8a52e78b89f0..2b6394004ea1 100644
--- a/include/linux/i2c-id.h
+++ b/include/linux/i2c-id.h
@@ -233,6 +233,7 @@
#define I2C_HW_SMBUS_ALI1535 0x07
#define I2C_HW_SMBUS_SIS630 0x08
#define I2C_HW_SMBUS_SIS645 0x09
+#define I2C_HW_SMBUS_AMD8111 0x0a
/* --- ISA pseudo-adapter */
#define I2C_HW_ISA 0x00
diff --git a/include/linux/i2c-proc.h b/include/linux/i2c-proc.h
index 4a4c33db48d5..ccdd2a95b1d1 100644
--- a/include/linux/i2c-proc.h
+++ b/include/linux/i2c-proc.h
@@ -348,6 +348,31 @@ struct i2c_address_data {
{NULL}}; \
SENSORS_INSMOD
+#define SENSORS_INSMOD_8(chip1,chip2,chip3,chip4,chip5,chip6,chip7,chip8) \
+ enum chips { any_chip, chip1, chip2, chip3, chip4, chip5, chip6, chip7, chip8 }; \
+ SENSORS_MODULE_PARM(force, \
+ "List of adapter,address pairs to boldly assume " \
+ "to be present"); \
+ SENSORS_MODULE_PARM_FORCE(chip1); \
+ SENSORS_MODULE_PARM_FORCE(chip2); \
+ SENSORS_MODULE_PARM_FORCE(chip3); \
+ SENSORS_MODULE_PARM_FORCE(chip4); \
+ SENSORS_MODULE_PARM_FORCE(chip5); \
+ SENSORS_MODULE_PARM_FORCE(chip6); \
+ SENSORS_MODULE_PARM_FORCE(chip7); \
+ SENSORS_MODULE_PARM_FORCE(chip8); \
+ static struct i2c_force_data forces[] = {{force,any_chip}, \
+ {force_ ## chip1,chip1}, \
+ {force_ ## chip2,chip2}, \
+ {force_ ## chip3,chip3}, \
+ {force_ ## chip4,chip4}, \
+ {force_ ## chip5,chip5}, \
+ {force_ ## chip6,chip6}, \
+ {force_ ## chip7,chip7}, \
+ {force_ ## chip8,chip8}, \
+ {NULL}}; \
+ SENSORS_INSMOD
+
typedef int i2c_found_addr_proc(struct i2c_adapter *adapter,
int addr, unsigned short flags,
int kind);
diff --git a/include/linux/ide.h b/include/linux/ide.h
index 033e94a6d6e4..2e2718ebfd98 100644
--- a/include/linux/ide.h
+++ b/include/linux/ide.h
@@ -360,8 +360,8 @@ extern int ide_irq_lock;
/* Currently only Atari needs it */
#ifndef IDE_ARCH_LOCK
-# define ide_release_lock(lock) do {} while (0)
-# define ide_get_lock(lock, hdlr, data) do {} while (0)
+# define ide_release_lock() do {} while (0)
+# define ide_get_lock(hdlr, data) do {} while (0)
#endif /* IDE_ARCH_LOCK */
/*
diff --git a/include/linux/init.h b/include/linux/init.h
index 46b1ef190c52..b7c6363478aa 100644
--- a/include/linux/init.h
+++ b/include/linux/init.h
@@ -147,14 +147,13 @@ struct obs_kernel_param {
#define module_init(initfn) \
static inline initcall_t __inittest(void) \
{ return initfn; } \
- int __initfn(void) __attribute__((alias(#initfn)));
+ int init_module(void) __attribute__((alias(#initfn)));
/* This is only required if you want to be unloadable. */
#define module_exit(exitfn) \
static inline exitcall_t __exittest(void) \
{ return exitfn; } \
- void __exitfn(void) __attribute__((alias(#exitfn)));
-
+ void cleanup_module(void) __attribute__((alias(#exitfn)));
#define __setup(str,func) /* nothing */
#endif
diff --git a/include/linux/ioport.h b/include/linux/ioport.h
index 020bd1596ab9..edd1eadb98b8 100644
--- a/include/linux/ioport.h
+++ b/include/linux/ioport.h
@@ -8,6 +8,7 @@
#ifndef _LINUX_IOPORT_H
#define _LINUX_IOPORT_H
+#include <linux/compiler.h>
/*
* Resources are tree-like, allowing
* nesting etc..
@@ -107,7 +108,7 @@ extern struct resource * __request_region(struct resource *, unsigned long start
#define check_mem_region(start,n) __check_region(&iomem_resource, (start), (n))
#define release_mem_region(start,n) __release_region(&iomem_resource, (start), (n))
-extern int __check_region(struct resource *, unsigned long, unsigned long);
+extern int __deprecated __check_region(struct resource *, unsigned long, unsigned long);
extern void __release_region(struct resource *, unsigned long, unsigned long);
#define get_ioport_list(buf) get_resource_list(&ioport_resource, buf, PAGE_SIZE)
diff --git a/include/linux/module.h b/include/linux/module.h
index 2392edcc3307..3a411c8c6575 100644
--- a/include/linux/module.h
+++ b/include/linux/module.h
@@ -40,12 +40,11 @@ struct kernel_symbol
char name[MODULE_NAME_LEN];
};
-#ifdef MODULE
+/* These are either module local, or the kernel's dummy ones. */
+extern int init_module(void);
+extern void cleanup_module(void);
-#ifdef KBUILD_MODNAME
-static const char __module_name[MODULE_NAME_LEN] __attribute__((section(".gnu.linkonce.modname"))) = \
- __stringify(KBUILD_MODNAME);
-#endif
+#ifdef MODULE
/* For replacement modutils, use an alias not a pointer. */
#define MODULE_GENERIC_TABLE(gtype,name) \
@@ -56,9 +55,6 @@ static const struct gtype##_id * __module_##gtype##_table \
extern const struct gtype##_id __mod_##gtype##_table \
__attribute__ ((unused, alias(__stringify(name))))
-/* This is magically filled in by the linker, but THIS_MODULE must be
- a constant so it works in initializers. */
-extern struct module __this_module;
#define THIS_MODULE (&__this_module)
#else /* !MODULE */
@@ -176,7 +172,7 @@ struct module
/* The command line arguments (may be mangled). People like
keeping pointers to this stuff */
- char args[0];
+ char *args;
};
/* FIXME: It'd be nice to isolate modules during init, too, so they
@@ -289,6 +285,19 @@ static inline const char *module_address_lookup(unsigned long addr,
}
#endif /* CONFIG_MODULES */
+#if defined(MODULE) && defined(KBUILD_MODNAME)
+/* We make the linker do some of the work. */
+struct module __this_module
+__attribute__((section(".gnu.linkonce.this_module"))) = {
+ .name = __stringify(KBUILD_MODNAME),
+ .symbols = { .owner = &__this_module },
+ .init = init_module,
+#ifdef CONFIG_MODULE_UNLOAD
+ .exit = cleanup_module,
+#endif
+};
+#endif /* MODULE && KBUILD_MODNAME */
+
/* For archs to search exception tables */
extern struct list_head extables;
extern spinlock_t modlist_lock;
@@ -296,9 +305,20 @@ extern spinlock_t modlist_lock;
#define symbol_request(x) try_then_request_module(symbol_get(x), "symbol:" #x)
/* BELOW HERE ALL THESE ARE OBSOLETE AND WILL VANISH */
-#define __MOD_INC_USE_COUNT(mod) \
- do { __unsafe(mod); (void)try_module_get(mod); } while(0)
-#define __MOD_DEC_USE_COUNT(mod) module_put(mod)
+static inline void __deprecated __MOD_INC_USE_COUNT(struct module *module)
+{
+ __unsafe(module);
+ /*
+ * Yes, we ignore the retval here, that's why it's deprecated.
+ */
+ try_module_get(module);
+}
+
+static inline void __deprecated __MOD_DEC_USE_COUNT(struct module *module)
+{
+ module_put(module);
+}
+
#define SET_MODULE_OWNER(dev) ((dev)->owner = THIS_MODULE)
struct obsolete_modparm {
@@ -319,14 +339,21 @@ struct obsolete_modparm __parm_##var __attribute__((section("__obsparm"))) = \
/* People do this inside their init routines, when the module isn't
"live" yet. They should no longer be doing that, but
meanwhile... */
+static inline void __deprecated _MOD_INC_USE_COUNT(struct module *module)
+{
+ __unsafe(module);
+
#if defined(CONFIG_MODULE_UNLOAD) && defined(MODULE)
-#define MOD_INC_USE_COUNT \
- do { __unsafe(THIS_MODULE); local_inc(&THIS_MODULE->ref[get_cpu()].count); put_cpu(); } while (0)
+ local_inc(&module->ref[get_cpu()].count);
+ put_cpu();
#else
-#define MOD_INC_USE_COUNT \
- do { __unsafe(THIS_MODULE); (void)try_module_get(THIS_MODULE); } while (0)
+ try_module_get(module);
#endif
-#define MOD_DEC_USE_COUNT module_put(THIS_MODULE)
+}
+#define MOD_INC_USE_COUNT \
+ _MOD_INC_USE_COUNT(THIS_MODULE)
+#define MOD_DEC_USE_COUNT \
+ __MOD_DEC_USE_COUNT(THIS_MODULE)
#define try_inc_mod_count(mod) try_module_get(mod)
#define EXPORT_NO_SYMBOLS
extern int module_dummy_usage;
@@ -342,13 +369,6 @@ extern int module_dummy_usage;
&& __mod_between((p),(n),(m)->module_init,(m)->init_size)) \
|| __mod_between((p),(n),(m)->module_core,(m)->core_size))
-/* Old-style "I'll just call it init_module and it'll be run at
- insert". Use module_init(myroutine) instead. */
-#ifdef MODULE
-#define init_module(voidarg) __initfn(void)
-#define cleanup_module(voidarg) __exitfn(void)
-#endif
-
/*
* The exception and symbol tables, and the lock
* to protect them.
diff --git a/include/linux/moduleparam.h b/include/linux/moduleparam.h
index 92a1bc154e8e..e52553263640 100644
--- a/include/linux/moduleparam.h
+++ b/include/linux/moduleparam.h
@@ -39,7 +39,7 @@ struct kparam_string {
writable. */
#define __module_param_call(prefix, name, set, get, arg, perm) \
static char __param_str_##name[] __initdata = prefix #name; \
- static struct kernel_param __param_##name \
+ static struct kernel_param const __param_##name \
__attribute__ ((unused,__section__ ("__param"))) \
= { __param_str_##name, perm, set, get, arg }
diff --git a/include/linux/mtd/map.h b/include/linux/mtd/map.h
index 94ffed22315b..ad8dfcbda17d 100644
--- a/include/linux/mtd/map.h
+++ b/include/linux/mtd/map.h
@@ -81,10 +81,7 @@ static inline void map_destroy(struct mtd_info *mtd)
if (map->fldrv->destroy)
map->fldrv->destroy(mtd);
-#ifdef CONFIG_MODULES
- if (map->fldrv->module)
- __MOD_DEC_USE_COUNT(map->fldrv->module);
-#endif
+ module_put(map->fldrv->module);
kfree(mtd);
}
diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h
index ae5bfe3e10fb..52d38241e91e 100644
--- a/include/linux/mtd/mtd.h
+++ b/include/linux/mtd/mtd.h
@@ -224,8 +224,7 @@ static inline struct mtd_info *get_mtd_device(struct mtd_info *mtd, int num)
static inline void put_mtd_device(struct mtd_info *mtd)
{
- if (mtd->module)
- __MOD_DEC_USE_COUNT(mtd->module);
+ module_put(mtd->module);
}
diff --git a/include/linux/nubus.h b/include/linux/nubus.h
index a3fd37b33fdd..870e66a96286 100644
--- a/include/linux/nubus.h
+++ b/include/linux/nubus.h
@@ -28,18 +28,18 @@ enum nubus_category {
};
enum nubus_type_network {
- NUBUS_TYPE_ETHERNET = 0x0001,
- NUBUS_TYPE_RS232 = 0x0002
+ NUBUS_TYPE_ETHERNET = 0x0001,
+ NUBUS_TYPE_RS232 = 0x0002
};
enum nubus_type_display {
- NUBUS_TYPE_VIDEO = 0x0001
+ NUBUS_TYPE_VIDEO = 0x0001
};
enum nubus_type_cpu {
- NUBUS_TYPE_68020 = 0x0003,
- NUBUS_TYPE_68030 = 0x0004,
- NUBUS_TYPE_68040 = 0x0005
+ NUBUS_TYPE_68020 = 0x0003,
+ NUBUS_TYPE_68030 = 0x0004,
+ NUBUS_TYPE_68040 = 0x0005
};
/* Known <Cat,Type,SW,HW> tuples: (according to TattleTech and Slots)
@@ -80,22 +80,24 @@ enum nubus_type_cpu {
/* Add known DrSW values here */
enum nubus_drsw {
/* NUBUS_CAT_DISPLAY */
- NUBUS_DRSW_APPLE = 0x0001,
- NUBUS_DRSW_APPLE_HIRES = 0x0013, /* MacII HiRes card driver */
+ NUBUS_DRSW_APPLE = 0x0001,
+ NUBUS_DRSW_APPLE_HIRES = 0x0013, /* MacII HiRes card driver */
/* NUBUS_CAT_NETWORK */
- NUBUS_DRSW_CABLETRON = 0x0001,
- NUBUS_DRSW_SONIC_LC = 0x0001,
- NUBUS_DRSW_KINETICS = 0x0103,
- NUBUS_DRSW_ASANTE = 0x0104,
- NUBUS_DRSW_DAYNA = 0x010b,
- NUBUS_DRSW_FARALLON = 0x010c,
- NUBUS_DRSW_APPLE_SN = 0x010f,
- NUBUS_DRSW_FOCUS = 0x011a,
- NUBUS_DRSW_ASANTE_CS = 0x011d, /* use asante SMC9194 driver */
+ NUBUS_DRSW_CABLETRON = 0x0001,
+ NUBUS_DRSW_SONIC_LC = 0x0001,
+ NUBUS_DRSW_KINETICS = 0x0103,
+ NUBUS_DRSW_ASANTE = 0x0104,
+ NUBUS_DRSW_DAYNA = 0x010b,
+ NUBUS_DRSW_FARALLON = 0x010c,
+ NUBUS_DRSW_APPLE_SN = 0x010f,
+ NUBUS_DRSW_DAYNA2 = 0x0115,
+ NUBUS_DRSW_FOCUS = 0x011a,
+ NUBUS_DRSW_ASANTE_CS = 0x011d, /* use asante SMC9194 driver */
+ NUBUS_DRSW_DAYNA_LC = 0x011e,
/* NUBUS_CAT_CPU */
- NUBUS_DRSW_NONE = 0x0000,
+ NUBUS_DRSW_NONE = 0x0000,
};
/* DrHW: Uniquely identifies the hardware interface to a board (or at
@@ -106,11 +108,13 @@ enum nubus_drsw {
enum nubus_drhw {
/* NUBUS_CAT_DISPLAY */
NUBUS_DRHW_APPLE_TFB = 0x0001, /* Toby frame buffer card */
+ NUBUS_DRHW_APPLE_HRVC = 0x0013, /* Mac II High Res Video card */
NUBUS_DRHW_APPLE_RBV1 = 0x0018, /* IIci RBV video */
NUBUS_DRHW_APPLE_MDC = 0x0019, /* Macintosh Display Card */
NUBUS_DRHW_APPLE_SONORA = 0x0022, /* Sonora built-in video */
+ NUBUS_DRHW_APPLE_JET = 0x0029, /* Jet framebuffer (DuoDock) */
NUBUS_DRHW_APPLE_VALKYRIE = 0x002e,
- NUBUS_DRHW_APPLE_JET = 0x0029, /* Jet framebuffer (DuoDock) */
+ NUBUS_DRHW_THUNDER24 = 0x02cb, /* SuperMac Thunder/24 */
/* NUBUS_CAT_NETWORK */
NUBUS_DRHW_INTERLAN = 0x0100,
@@ -119,6 +123,11 @@ enum nubus_drhw {
NUBUS_DRHW_CABLETRON = 0x0109,
NUBUS_DRHW_ASANTE_LC = 0x010f,
NUBUS_DRHW_SONIC = 0x0110,
+ NUBUS_DRHW_SONIC_NB = 0x0118,
+ NUBUS_DRHW_SONIC_LC = 0x0119,
+
+ /* NUBUS_CAT_COMMUNICATIONS */
+ NUBUS_DRHW_DOVEFAX = 0x0100,
};
/* Resource IDs: These are the identifiers for the various weird and
@@ -153,8 +162,8 @@ enum nubus_board_res_id {
NUBUS_RESID_SECONDINIT = 0x0026,
/* Not sure why Apple put these next two in here */
- NUBUS_RESID_VIDNAMES = 0x0041,
- NUBUS_RESID_VIDMODES = 0x007e
+ NUBUS_RESID_VIDNAMES = 0x0041,
+ NUBUS_RESID_VIDMODES = 0x007e
};
/* Fields within the vendor info directory */
diff --git a/include/linux/personality.h b/include/linux/personality.h
index ca5d403e49ff..33802c8eeedb 100644
--- a/include/linux/personality.h
+++ b/include/linux/personality.h
@@ -107,22 +107,4 @@ struct exec_domain {
#define set_personality(pers) \
((current->personality == pers) ? 0 : __set_personality(pers))
-/*
- * Load an execution domain.
- */
-#define get_exec_domain(ep) \
-do { \
- if (ep != NULL && ep->module != NULL) \
- __MOD_INC_USE_COUNT(ep->module); \
-} while (0)
-
-/*
- * Unload an execution domain.
- */
-#define put_exec_domain(ep) \
-do { \
- if (ep != NULL && ep->module != NULL) \
- __MOD_DEC_USE_COUNT(ep->module); \
-} while (0)
-
#endif /* _LINUX_PERSONALITY_H */
diff --git a/include/linux/sensors.h b/include/linux/sensors.h
new file mode 100644
index 000000000000..31998faab1e6
--- /dev/null
+++ b/include/linux/sensors.h
@@ -0,0 +1,690 @@
+/*
+ sensors.h - Part of lm_sensors, Linux kernel modules for hardware
+ monitoring
+ Copyright (c) 1998, 1999 Frodo Looijaard <frodol@dds.nl>
+
+ 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifndef SENSORS_NSENSORS_H
+#define SENSORS_NSENSORS_H
+
+#define LM_DATE "20020915"
+#define LM_VERSION "2.6.5"
+
+#include <linux/i2c-proc.h>
+
+#define LM78_SYSCTL_IN0 1000 /* Volts * 100 */
+#define LM78_SYSCTL_IN1 1001
+#define LM78_SYSCTL_IN2 1002
+#define LM78_SYSCTL_IN3 1003
+#define LM78_SYSCTL_IN4 1004
+#define LM78_SYSCTL_IN5 1005
+#define LM78_SYSCTL_IN6 1006
+#define LM78_SYSCTL_FAN1 1101 /* Rotations/min */
+#define LM78_SYSCTL_FAN2 1102
+#define LM78_SYSCTL_FAN3 1103
+#define LM78_SYSCTL_TEMP 1200 /* Degrees Celcius * 10 */
+#define LM78_SYSCTL_VID 1300 /* Volts * 100 */
+#define LM78_SYSCTL_FAN_DIV 2000 /* 1, 2, 4 or 8 */
+#define LM78_SYSCTL_ALARMS 2001 /* bitvector */
+
+#define LM78_ALARM_IN0 0x0001
+#define LM78_ALARM_IN1 0x0002
+#define LM78_ALARM_IN2 0x0004
+#define LM78_ALARM_IN3 0x0008
+#define LM78_ALARM_IN4 0x0100
+#define LM78_ALARM_IN5 0x0200
+#define LM78_ALARM_IN6 0x0400
+#define LM78_ALARM_FAN1 0x0040
+#define LM78_ALARM_FAN2 0x0080
+#define LM78_ALARM_FAN3 0x0800
+#define LM78_ALARM_TEMP 0x0010
+#define LM78_ALARM_BTI 0x0020
+#define LM78_ALARM_CHAS 0x1000
+#define LM78_ALARM_FIFO 0x2000
+#define LM78_ALARM_SMI_IN 0x4000
+
+#define W83781D_SYSCTL_IN0 1000 /* Volts * 100 */
+#define W83781D_SYSCTL_IN1 1001
+#define W83781D_SYSCTL_IN2 1002
+#define W83781D_SYSCTL_IN3 1003
+#define W83781D_SYSCTL_IN4 1004
+#define W83781D_SYSCTL_IN5 1005
+#define W83781D_SYSCTL_IN6 1006
+#define W83781D_SYSCTL_IN7 1007
+#define W83781D_SYSCTL_IN8 1008
+#define W83781D_SYSCTL_FAN1 1101 /* Rotations/min */
+#define W83781D_SYSCTL_FAN2 1102
+#define W83781D_SYSCTL_FAN3 1103
+#define W83781D_SYSCTL_TEMP1 1200 /* Degrees Celcius * 10 */
+#define W83781D_SYSCTL_TEMP2 1201 /* Degrees Celcius * 10 */
+#define W83781D_SYSCTL_TEMP3 1202 /* Degrees Celcius * 10 */
+#define W83781D_SYSCTL_VID 1300 /* Volts * 1000 */
+#define W83781D_SYSCTL_VRM 1301
+#define W83781D_SYSCTL_PWM1 1401
+#define W83781D_SYSCTL_PWM2 1402
+#define W83781D_SYSCTL_PWM3 1403
+#define W83781D_SYSCTL_PWM4 1404
+#define W83781D_SYSCTL_SENS1 1501 /* 1, 2, or Beta (3000-5000) */
+#define W83781D_SYSCTL_SENS2 1502
+#define W83781D_SYSCTL_SENS3 1503
+#define W83781D_SYSCTL_RT1 1601 /* 32-entry table */
+#define W83781D_SYSCTL_RT2 1602 /* 32-entry table */
+#define W83781D_SYSCTL_RT3 1603 /* 32-entry table */
+#define W83781D_SYSCTL_FAN_DIV 2000 /* 1, 2, 4 or 8 */
+#define W83781D_SYSCTL_ALARMS 2001 /* bitvector */
+#define W83781D_SYSCTL_BEEP 2002 /* bitvector */
+
+#define W83781D_ALARM_IN0 0x0001
+#define W83781D_ALARM_IN1 0x0002
+#define W83781D_ALARM_IN2 0x0004
+#define W83781D_ALARM_IN3 0x0008
+#define W83781D_ALARM_IN4 0x0100
+#define W83781D_ALARM_IN5 0x0200
+#define W83781D_ALARM_IN6 0x0400
+#define W83782D_ALARM_IN7 0x10000
+#define W83782D_ALARM_IN8 0x20000
+#define W83781D_ALARM_FAN1 0x0040
+#define W83781D_ALARM_FAN2 0x0080
+#define W83781D_ALARM_FAN3 0x0800
+#define W83781D_ALARM_TEMP1 0x0010
+#define W83781D_ALARM_TEMP23 0x0020 /* 781D only */
+#define W83781D_ALARM_TEMP2 0x0020 /* 782D/783S */
+#define W83781D_ALARM_TEMP3 0x2000 /* 782D only */
+#define W83781D_ALARM_CHAS 0x1000
+
+#define LM75_SYSCTL_TEMP 1200 /* Degrees Celcius * 10 */
+
+#define ADM1021_SYSCTL_TEMP 1200
+#define ADM1021_SYSCTL_REMOTE_TEMP 1201
+#define ADM1021_SYSCTL_DIE_CODE 1202
+#define ADM1021_SYSCTL_ALARMS 1203
+
+#define ADM1021_ALARM_TEMP_HIGH 0x40
+#define ADM1021_ALARM_TEMP_LOW 0x20
+#define ADM1021_ALARM_RTEMP_HIGH 0x10
+#define ADM1021_ALARM_RTEMP_LOW 0x08
+#define ADM1021_ALARM_RTEMP_NA 0x04
+
+#define GL518_SYSCTL_VDD 1000 /* Volts * 100 */
+#define GL518_SYSCTL_VIN1 1001
+#define GL518_SYSCTL_VIN2 1002
+#define GL518_SYSCTL_VIN3 1003
+#define GL518_SYSCTL_FAN1 1101 /* RPM */
+#define GL518_SYSCTL_FAN2 1102
+#define GL518_SYSCTL_TEMP 1200 /* Degrees Celcius * 10 */
+#define GL518_SYSCTL_FAN_DIV 2000 /* 1, 2, 4 or 8 */
+#define GL518_SYSCTL_ALARMS 2001 /* bitvector */
+#define GL518_SYSCTL_BEEP 2002 /* bitvector */
+#define GL518_SYSCTL_FAN1OFF 2003
+#define GL518_SYSCTL_ITERATE 2004
+
+#define GL518_ALARM_VDD 0x01
+#define GL518_ALARM_VIN1 0x02
+#define GL518_ALARM_VIN2 0x04
+#define GL518_ALARM_VIN3 0x08
+#define GL518_ALARM_TEMP 0x10
+#define GL518_ALARM_FAN1 0x20
+#define GL518_ALARM_FAN2 0x40
+
+#define GL520_SYSCTL_VDD 1000 /* Volts * 100 */
+#define GL520_SYSCTL_VIN1 1001
+#define GL520_SYSCTL_VIN2 1002
+#define GL520_SYSCTL_VIN3 1003
+#define GL520_SYSCTL_VIN4 1004
+#define GL520_SYSCTL_FAN1 1101 /* RPM */
+#define GL520_SYSCTL_FAN2 1102
+#define GL520_SYSCTL_TEMP1 1200 /* Degrees Celcius * 10 */
+#define GL520_SYSCTL_TEMP2 1201 /* Degrees Celcius * 10 */
+#define GL520_SYSCTL_VID 1300
+#define GL520_SYSCTL_FAN_DIV 2000 /* 1, 2, 4 or 8 */
+#define GL520_SYSCTL_ALARMS 2001 /* bitvector */
+#define GL520_SYSCTL_BEEP 2002 /* bitvector */
+#define GL520_SYSCTL_FAN1OFF 2003
+#define GL520_SYSCTL_CONFIG 2004
+
+#define GL520_ALARM_VDD 0x01
+#define GL520_ALARM_VIN1 0x02
+#define GL520_ALARM_VIN2 0x04
+#define GL520_ALARM_VIN3 0x08
+#define GL520_ALARM_TEMP1 0x10
+#define GL520_ALARM_FAN1 0x20
+#define GL520_ALARM_FAN2 0x40
+#define GL520_ALARM_TEMP2 0x80
+#define GL520_ALARM_VIN4 0x80
+
+#define EEPROM_SYSCTL1 1000
+#define EEPROM_SYSCTL2 1001
+#define EEPROM_SYSCTL3 1002
+#define EEPROM_SYSCTL4 1003
+#define EEPROM_SYSCTL5 1004
+#define EEPROM_SYSCTL6 1005
+#define EEPROM_SYSCTL7 1006
+#define EEPROM_SYSCTL8 1007
+#define EEPROM_SYSCTL9 1008
+#define EEPROM_SYSCTL10 1009
+#define EEPROM_SYSCTL11 1010
+#define EEPROM_SYSCTL12 1011
+#define EEPROM_SYSCTL13 1012
+#define EEPROM_SYSCTL14 1013
+#define EEPROM_SYSCTL15 1014
+#define EEPROM_SYSCTL16 1015
+
+#define LM80_SYSCTL_IN0 1000 /* Volts * 100 */
+#define LM80_SYSCTL_IN1 1001
+#define LM80_SYSCTL_IN2 1002
+#define LM80_SYSCTL_IN3 1003
+#define LM80_SYSCTL_IN4 1004
+#define LM80_SYSCTL_IN5 1005
+#define LM80_SYSCTL_IN6 1006
+#define LM80_SYSCTL_FAN1 1101 /* Rotations/min */
+#define LM80_SYSCTL_FAN2 1102
+#define LM80_SYSCTL_TEMP 1250 /* Degrees Celcius * 100 */
+#define LM80_SYSCTL_FAN_DIV 2000 /* 1, 2, 4 or 8 */
+#define LM80_SYSCTL_ALARMS 2001 /* bitvector */
+
+#define ADM9240_SYSCTL_IN0 1000 /* Volts * 100 */
+#define ADM9240_SYSCTL_IN1 1001
+#define ADM9240_SYSCTL_IN2 1002
+#define ADM9240_SYSCTL_IN3 1003
+#define ADM9240_SYSCTL_IN4 1004
+#define ADM9240_SYSCTL_IN5 1005
+#define ADM9240_SYSCTL_FAN1 1101 /* Rotations/min */
+#define ADM9240_SYSCTL_FAN2 1102
+#define ADM9240_SYSCTL_TEMP 1250 /* Degrees Celcius * 100 */
+#define ADM9240_SYSCTL_FAN_DIV 2000 /* 1, 2, 4 or 8 */
+#define ADM9240_SYSCTL_ALARMS 2001 /* bitvector */
+#define ADM9240_SYSCTL_ANALOG_OUT 2002
+#define ADM9240_SYSCTL_VID 2003
+
+#define ADM9240_ALARM_IN0 0x0001
+#define ADM9240_ALARM_IN1 0x0002
+#define ADM9240_ALARM_IN2 0x0004
+#define ADM9240_ALARM_IN3 0x0008
+#define ADM9240_ALARM_IN4 0x0100
+#define ADM9240_ALARM_IN5 0x0200
+#define ADM9240_ALARM_FAN1 0x0040
+#define ADM9240_ALARM_FAN2 0x0080
+#define ADM9240_ALARM_TEMP 0x0010
+#define ADM9240_ALARM_CHAS 0x1000
+
+#define ADM1024_SYSCTL_IN0 1000 /* Volts * 100 */
+#define ADM1024_SYSCTL_IN1 1001
+#define ADM1024_SYSCTL_IN2 1002
+#define ADM1024_SYSCTL_IN3 1003
+#define ADM1024_SYSCTL_IN4 1004
+#define ADM1024_SYSCTL_IN5 1005
+#define ADM1024_SYSCTL_FAN1 1101 /* Rotations/min */
+#define ADM1024_SYSCTL_FAN2 1102
+#define ADM1024_SYSCTL_TEMP 1250 /* Degrees Celcius * 100 */
+#define ADM1024_SYSCTL_TEMP1 1290 /* Degrees Celcius */
+#define ADM1024_SYSCTL_TEMP2 1295 /* Degrees Celcius */
+#define ADM1024_SYSCTL_FAN_DIV 2000 /* 1, 2, 4 or 8 */
+#define ADM1024_SYSCTL_ALARMS 2001 /* bitvector */
+#define ADM1024_SYSCTL_ANALOG_OUT 2002
+#define ADM1024_SYSCTL_VID 2003
+
+#define ADM1024_ALARM_IN0 0x0001
+#define ADM1024_ALARM_IN1 0x0002
+#define ADM1024_ALARM_IN2 0x0004
+#define ADM1024_ALARM_IN3 0x0008
+#define ADM1024_ALARM_IN4 0x0100
+#define ADM1024_ALARM_IN5 0x0200
+#define ADM1024_ALARM_FAN1 0x0040
+#define ADM1024_ALARM_FAN2 0x0080
+#define ADM1024_ALARM_TEMP 0x0010
+#define ADM1024_ALARM_TEMP1 0x0020
+#define ADM1024_ALARM_TEMP2 0x0001
+#define ADM1024_ALARM_CHAS 0x1000
+
+#define ADM1025_SYSCTL_IN0 1000 /* Volts * 100 */
+#define ADM1025_SYSCTL_IN1 1001
+#define ADM1025_SYSCTL_IN2 1002
+#define ADM1025_SYSCTL_IN3 1003
+#define ADM1025_SYSCTL_IN4 1004
+#define ADM1025_SYSCTL_IN5 1005
+#define ADM1025_SYSCTL_RTEMP 1251
+#define ADM1025_SYSCTL_TEMP 1250 /* Degrees Celcius * 100 */
+#define ADM1025_SYSCTL_ALARMS 2001 /* bitvector */
+#define ADM1025_SYSCTL_ANALOG_OUT 2002
+#define ADM1025_SYSCTL_VID 2003
+#define ADM1025_SYSCTL_VRM 2004
+
+#define ADM1025_ALARM_IN0 0x0001
+#define ADM1025_ALARM_IN1 0x0002
+#define ADM1025_ALARM_IN2 0x0004
+#define ADM1025_ALARM_IN3 0x0008
+#define ADM1025_ALARM_IN4 0x0100
+#define ADM1025_ALARM_IN5 0x0200
+#define ADM1025_ALARM_RTEMP 0x0020
+#define ADM1025_ALARM_TEMP 0x0010
+
+#define LTC1710_SYSCTL_SWITCH_1 1000
+#define LTC1710_SYSCTL_SWITCH_2 1001
+
+#define LM80_ALARM_IN0 0x0001
+#define LM80_ALARM_IN1 0x0002
+#define LM80_ALARM_IN2 0x0004
+#define LM80_ALARM_IN3 0x0008
+#define LM80_ALARM_IN4 0x0010
+#define LM80_ALARM_IN5 0x0020
+#define LM80_ALARM_IN6 0x0040
+#define LM80_ALARM_FAN1 0x0400
+#define LM80_ALARM_FAN2 0x0800
+#define LM80_ALARM_TEMP_HOT 0x0100
+#define LM80_ALARM_TEMP_OS 0x2000
+#define LM80_ALARM_CHAS 0x1000
+#define LM80_ALARM_BTI 0x0200
+#define LM80_ALARM_INT_IN 0x0080
+
+#define MAXI_SYSCTL_FAN1 1101 /* Rotations/min */
+#define MAXI_SYSCTL_FAN2 1102 /* Rotations/min */
+#define MAXI_SYSCTL_FAN3 1103 /* Rotations/min */
+#define MAXI_SYSCTL_FAN4 1104 /* Rotations/min */
+#define MAXI_SYSCTL_TEMP1 1201 /* Degrees Celcius */
+#define MAXI_SYSCTL_TEMP2 1202 /* Degrees Celcius */
+#define MAXI_SYSCTL_TEMP3 1203 /* Degrees Celcius */
+#define MAXI_SYSCTL_TEMP4 1204 /* Degrees Celcius */
+#define MAXI_SYSCTL_TEMP5 1205 /* Degrees Celcius */
+#define MAXI_SYSCTL_TEMP6 1206 /* Degrees Celcius */
+#define MAXI_SYSCTL_PLL 1301 /* MHz */
+#define MAXI_SYSCTL_VID1 1401 /* Volts / 6.337, for nba just Volts */
+#define MAXI_SYSCTL_VID2 1402 /* Volts */
+#define MAXI_SYSCTL_VID3 1403 /* Volts */
+#define MAXI_SYSCTL_VID4 1404 /* Volts */
+#define MAXI_SYSCTL_VID5 1405 /* Volts */
+#define MAXI_SYSCTL_LCD1 1501 /* Line 1 of LCD */
+#define MAXI_SYSCTL_LCD2 1502 /* Line 2 of LCD */
+#define MAXI_SYSCTL_LCD3 1503 /* Line 3 of LCD */
+#define MAXI_SYSCTL_LCD4 1504 /* Line 4 of LCD */
+#define MAXI_SYSCTL_ALARMS 2001 /* Bitvector (see below) */
+
+#define MAXI_ALARM_VID4 0x0001
+#define MAXI_ALARM_TEMP2 0x0002
+#define MAXI_ALARM_VID1 0x0004
+#define MAXI_ALARM_VID2 0x0008
+#define MAXI_ALARM_VID3 0x0010
+#define MAXI_ALARM_PLL 0x0080
+#define MAXI_ALARM_TEMP4 0x0100
+#define MAXI_ALARM_TEMP5 0x0200
+#define MAXI_ALARM_FAN1 0x1000
+#define MAXI_ALARM_FAN2 0x2000
+#define MAXI_ALARM_FAN3 0x4000
+
+#define MAXI_ALARM_FAN 0x0100 /* To be used with MaxiLife'99 */
+#define MAXI_ALARM_VID 0x0200 /* The MSB specifies which sensor */
+#define MAXI_ALARM_TEMP 0x0400 /* in the alarm group failed, i.e.: */
+#define MAXI_ALARM_VADD 0x0800 /* 0x0402 = TEMP2 failed = CPU2 temp */
+
+#define SIS5595_SYSCTL_IN0 1000 /* Volts * 100 */
+#define SIS5595_SYSCTL_IN1 1001
+#define SIS5595_SYSCTL_IN2 1002
+#define SIS5595_SYSCTL_IN3 1003
+#define SIS5595_SYSCTL_IN4 1004
+#define SIS5595_SYSCTL_FAN1 1101 /* Rotations/min */
+#define SIS5595_SYSCTL_FAN2 1102
+#define SIS5595_SYSCTL_TEMP 1200 /* Degrees Celcius * 10 */
+#define SIS5595_SYSCTL_FAN_DIV 2000 /* 1, 2, 4 or 8 */
+#define SIS5595_SYSCTL_ALARMS 2001 /* bitvector */
+
+#define SIS5595_ALARM_IN0 0x01
+#define SIS5595_ALARM_IN1 0x02
+#define SIS5595_ALARM_IN2 0x04
+#define SIS5595_ALARM_IN3 0x08
+#define SIS5595_ALARM_BTI 0x20
+#define SIS5595_ALARM_FAN1 0x40
+#define SIS5595_ALARM_FAN2 0x80
+#define SIS5595_ALARM_IN4 0x8000
+#define SIS5595_ALARM_TEMP 0x8000
+
+#define VIA686A_SYSCTL_IN0 1000
+#define VIA686A_SYSCTL_IN1 1001
+#define VIA686A_SYSCTL_IN2 1002
+#define VIA686A_SYSCTL_IN3 1003
+#define VIA686A_SYSCTL_IN4 1004
+#define VIA686A_SYSCTL_FAN1 1101
+#define VIA686A_SYSCTL_FAN2 1102
+#define VIA686A_SYSCTL_TEMP 1200
+#define VIA686A_SYSCTL_TEMP2 1201
+#define VIA686A_SYSCTL_TEMP3 1202
+#define VIA686A_SYSCTL_FAN_DIV 2000
+#define VIA686A_SYSCTL_ALARMS 2001
+
+#define VIA686A_ALARM_IN0 0x01
+#define VIA686A_ALARM_IN1 0x02
+#define VIA686A_ALARM_IN2 0x04
+#define VIA686A_ALARM_IN3 0x08
+#define VIA686A_ALARM_TEMP 0x10
+#define VIA686A_ALARM_FAN1 0x40
+#define VIA686A_ALARM_FAN2 0x80
+#define VIA686A_ALARM_IN4 0x100
+#define VIA686A_ALARM_TEMP2 0x800
+#define VIA686A_ALARM_CHAS 0x1000
+#define VIA686A_ALARM_TEMP3 0x8000
+
+#define ICSPLL_SYSCTL1 1000
+
+#define BT869_SYSCTL_STATUS 1000
+#define BT869_SYSCTL_NTSC 1001
+#define BT869_SYSCTL_HALF 1002
+#define BT869_SYSCTL_RES 1003
+#define BT869_SYSCTL_COLORBARS 1004
+#define BT869_SYSCTL_DEPTH 1005
+#define BT869_SYSCTL_SVIDEO 1006
+
+#define MATORB_SYSCTL_DISP 1000
+
+#define THMC50_SYSCTL_TEMP 1200 /* Degrees Celcius */
+#define THMC50_SYSCTL_REMOTE_TEMP 1201 /* Degrees Celcius */
+#define THMC50_SYSCTL_INTER 1202
+#define THMC50_SYSCTL_INTER_MASK 1203
+#define THMC50_SYSCTL_DIE_CODE 1204
+#define THMC50_SYSCTL_ANALOG_OUT 1205
+
+#define DDCMON_SYSCTL_ID 1010
+#define DDCMON_SYSCTL_SIZE 1011
+#define DDCMON_SYSCTL_SYNC 1012
+#define DDCMON_SYSCTL_TIMINGS 1013
+#define DDCMON_SYSCTL_SERIAL 1014
+
+#define LM87_SYSCTL_IN0 1000 /* Volts * 100 */
+#define LM87_SYSCTL_IN1 1001
+#define LM87_SYSCTL_IN2 1002
+#define LM87_SYSCTL_IN3 1003
+#define LM87_SYSCTL_IN4 1004
+#define LM87_SYSCTL_IN5 1005
+#define LM87_SYSCTL_AIN1 1006
+#define LM87_SYSCTL_AIN2 1007
+#define LM87_SYSCTL_FAN1 1102
+#define LM87_SYSCTL_FAN2 1103
+#define LM87_SYSCTL_TEMP1 1250 /* Degrees Celcius * 100 */
+#define LM87_SYSCTL_TEMP2 1251 /* Degrees Celcius * 100 */
+#define LM87_SYSCTL_TEMP3 1252 /* Degrees Celcius * 100 */
+#define LM87_SYSCTL_FAN_DIV 2000 /* 1, 2, 4 or 8 */
+#define LM87_SYSCTL_ALARMS 2001 /* bitvector */
+#define LM87_SYSCTL_ANALOG_OUT 2002
+#define LM87_SYSCTL_VID 2003
+#define LM87_SYSCTL_VRM 2004
+
+#define LM87_ALARM_IN0 0x0001
+#define LM87_ALARM_IN1 0x0002
+#define LM87_ALARM_IN2 0x0004
+#define LM87_ALARM_IN3 0x0008
+#define LM87_ALARM_TEMP1 0x0010
+#define LM87_ALARM_TEMP2 0x0020
+#define LM87_ALARM_TEMP3 0x0020 /* same?? */
+#define LM87_ALARM_FAN1 0x0040
+#define LM87_ALARM_FAN2 0x0080
+#define LM87_ALARM_IN4 0x0100
+#define LM87_ALARM_IN5 0x0200
+#define LM87_ALARM_RESERVED1 0x0400
+#define LM87_ALARM_RESERVED2 0x0800
+#define LM87_ALARM_CHAS 0x1000
+#define LM87_ALARM_THERM_SIG 0x2000
+#define LM87_ALARM_TEMP2_FAULT 0x4000
+#define LM87_ALARM_TEMP3_FAULT 0x08000
+
+#define PCF8574_SYSCTL_READ 1000
+#define PCF8574_SYSCTL_WRITE 1001
+
+#define MTP008_SYSCTL_IN0 1000 /* Volts * 100 */
+#define MTP008_SYSCTL_IN1 1001
+#define MTP008_SYSCTL_IN2 1002
+#define MTP008_SYSCTL_IN3 1003
+#define MTP008_SYSCTL_IN4 1004
+#define MTP008_SYSCTL_IN5 1005
+#define MTP008_SYSCTL_IN6 1006
+#define MTP008_SYSCTL_FAN1 1101 /* Rotations/min */
+#define MTP008_SYSCTL_FAN2 1102
+#define MTP008_SYSCTL_FAN3 1103
+#define MTP008_SYSCTL_TEMP1 1200 /* Degrees Celcius * 10 */
+#define MTP008_SYSCTL_TEMP2 1201 /* Degrees Celcius * 10 */
+#define MTP008_SYSCTL_TEMP3 1202 /* Degrees Celcius * 10 */
+#define MTP008_SYSCTL_VID 1300 /* Volts * 100 */
+#define MTP008_SYSCTL_PWM1 1401
+#define MTP008_SYSCTL_PWM2 1402
+#define MTP008_SYSCTL_PWM3 1403
+#define MTP008_SYSCTL_SENS1 1501 /* 1, 2, or Beta (3000-5000) */
+#define MTP008_SYSCTL_SENS2 1502
+#define MTP008_SYSCTL_SENS3 1503
+#define MTP008_SYSCTL_FAN_DIV 2000 /* 1, 2, 4 or 8 */
+#define MTP008_SYSCTL_ALARMS 2001 /* bitvector */
+#define MTP008_SYSCTL_BEEP 2002 /* bitvector */
+
+#define MTP008_ALARM_IN0 0x0001
+#define MTP008_ALARM_IN1 0x0002
+#define MTP008_ALARM_IN2 0x0004
+#define MTP008_ALARM_IN3 0x0008
+#define MTP008_ALARM_IN4 0x0100
+#define MTP008_ALARM_IN5 0x0200
+#define MTP008_ALARM_IN6 0x0400
+#define MTP008_ALARM_FAN1 0x0040
+#define MTP008_ALARM_FAN2 0x0080
+#define MTP008_ALARM_FAN3 0x0800
+#define MTP008_ALARM_TEMP1 0x0010
+#define MTP008_ALARM_TEMP2 0x0100
+#define MTP008_ALARM_TEMP3 0x0200
+
+#define DS1621_SYSCTL_TEMP 1200 /* Degrees Celcius * 10 */
+#define DS1621_SYSCTL_ALARMS 2001 /* bitvector */
+#define DS1621_ALARM_TEMP_HIGH 0x40
+#define DS1621_ALARM_TEMP_LOW 0x20
+#define DS1621_SYSCTL_ENABLE 2002
+#define DS1621_SYSCTL_CONTINUOUS 2003
+#define DS1621_SYSCTL_POLARITY 2004
+
+#define IT87_SYSCTL_IN0 1000 /* Volts * 100 */
+#define IT87_SYSCTL_IN1 1001
+#define IT87_SYSCTL_IN2 1002
+#define IT87_SYSCTL_IN3 1003
+#define IT87_SYSCTL_IN4 1004
+#define IT87_SYSCTL_IN5 1005
+#define IT87_SYSCTL_IN6 1006
+#define IT87_SYSCTL_IN7 1007
+#define IT87_SYSCTL_IN8 1008
+#define IT87_SYSCTL_FAN1 1101 /* Rotations/min */
+#define IT87_SYSCTL_FAN2 1102
+#define IT87_SYSCTL_FAN3 1103
+#define IT87_SYSCTL_TEMP1 1200 /* Degrees Celcius * 10 */
+#define IT87_SYSCTL_TEMP2 1201 /* Degrees Celcius * 10 */
+#define IT87_SYSCTL_TEMP3 1202 /* Degrees Celcius * 10 */
+#define IT87_SYSCTL_VID 1300 /* Volts * 100 */
+#define IT87_SYSCTL_FAN_DIV 2000 /* 1, 2, 4 or 8 */
+#define IT87_SYSCTL_ALARMS 2004 /* bitvector */
+
+#define IT87_ALARM_IN0 0x000100
+#define IT87_ALARM_IN1 0x000200
+#define IT87_ALARM_IN2 0x000400
+#define IT87_ALARM_IN3 0x000800
+#define IT87_ALARM_IN4 0x001000
+#define IT87_ALARM_IN5 0x002000
+#define IT87_ALARM_IN6 0x004000
+#define IT87_ALARM_IN7 0x008000
+#define IT87_ALARM_FAN1 0x0001
+#define IT87_ALARM_FAN2 0x0002
+#define IT87_ALARM_FAN3 0x0004
+#define IT87_ALARM_TEMP1 0x00010000
+#define IT87_ALARM_TEMP2 0x00020000
+#define IT87_ALARM_TEMP3 0x00040000
+
+#define FSCPOS_SYSCTL_VOLT0 1000 /* 12 volt supply */
+#define FSCPOS_SYSCTL_VOLT1 1001 /* 5 volt supply */
+#define FSCPOS_SYSCTL_VOLT2 1002 /* batterie voltage*/
+#define FSCPOS_SYSCTL_FAN0 1101 /* state, min, ripple, actual value fan 0 */
+#define FSCPOS_SYSCTL_FAN1 1102 /* state, min, ripple, actual value fan 1 */
+#define FSCPOS_SYSCTL_FAN2 1103 /* state, min, ripple, actual value fan 2 */
+#define FSCPOS_SYSCTL_TEMP0 1201 /* state and value of sensor 0, cpu die */
+#define FSCPOS_SYSCTL_TEMP1 1202 /* state and value of sensor 1, motherboard */
+#define FSCPOS_SYSCTL_TEMP2 1203 /* state and value of sensor 2, chassis */
+#define FSCPOS_SYSCTL_REV 2000 /* Revision */
+#define FSCPOS_SYSCTL_EVENT 2001 /* global event status */
+#define FSCPOS_SYSCTL_CONTROL 2002 /* global control byte */
+#define FSCPOS_SYSCTL_WDOG 2003 /* state, min, ripple, actual value fan 2 */
+
+#define FSCSCY_SYSCTL_VOLT0 1000 /* 12 volt supply */
+#define FSCSCY_SYSCTL_VOLT1 1001 /* 5 volt supply */
+#define FSCSCY_SYSCTL_VOLT2 1002 /* batterie voltage*/
+#define FSCSCY_SYSCTL_FAN0 1101 /* state, min, ripple, actual value fan 0 */
+#define FSCSCY_SYSCTL_FAN1 1102 /* state, min, ripple, actual value fan 1 */
+#define FSCSCY_SYSCTL_FAN2 1103 /* state, min, ripple, actual value fan 2 */
+#define FSCSCY_SYSCTL_FAN3 1104 /* state, min, ripple, actual value fan 3 */
+#define FSCSCY_SYSCTL_FAN4 1105 /* state, min, ripple, actual value fan 4 */
+#define FSCSCY_SYSCTL_FAN5 1106 /* state, min, ripple, actual value fan 5 */
+#define FSCSCY_SYSCTL_TEMP0 1201 /* state and value of sensor 0, cpu die */
+#define FSCSCY_SYSCTL_TEMP1 1202 /* state and value of sensor 1, motherboard */
+#define FSCSCY_SYSCTL_TEMP2 1203 /* state and value of sensor 2, chassis */
+#define FSCSCY_SYSCTL_TEMP3 1204 /* state and value of sensor 3, chassis */
+#define FSCSCY_SYSCTL_REV 2000 /* Revision */
+#define FSCSCY_SYSCTL_EVENT 2001 /* global event status */
+#define FSCSCY_SYSCTL_CONTROL 2002 /* global control byte */
+#define FSCSCY_SYSCTL_WDOG 2003 /* state, min, ripple, actual value fan 2 */
+#define FSCSCY_SYSCTL_PCILOAD 2004 /* PCILoad value */
+#define FSCSCY_SYSCTL_INTRUSION 2005 /* state, control for intrusion sensor */
+
+#define PCF8591_SYSCTL_AIN_CONF 1000 /* Analog input configuration */
+#define PCF8591_SYSCTL_CH0 1001 /* Input channel 1 */
+#define PCF8591_SYSCTL_CH1 1002 /* Input channel 2 */
+#define PCF8591_SYSCTL_CH2 1003 /* Input channel 3 */
+#define PCF8591_SYSCTL_CH3 1004 /* Input channel 4 */
+#define PCF8591_SYSCTL_AOUT_ENABLE 1005 /* Analog output enable flag */
+#define PCF8591_SYSCTL_AOUT 1006 /* Analog output */
+
+#define ARP_SYSCTL1 1000
+#define ARP_SYSCTL2 1001
+#define ARP_SYSCTL3 1002
+#define ARP_SYSCTL4 1003
+#define ARP_SYSCTL5 1004
+#define ARP_SYSCTL6 1005
+#define ARP_SYSCTL7 1006
+#define ARP_SYSCTL8 1007
+
+#define SMSC47M1_SYSCTL_FAN1 1101 /* Rotations/min */
+#define SMSC47M1_SYSCTL_FAN2 1102
+#define SMSC47M1_SYSCTL_PWM1 1401
+#define SMSC47M1_SYSCTL_PWM2 1402
+#define SMSC47M1_SYSCTL_FAN_DIV 2000 /* 1, 2, 4 or 8 */
+#define SMSC47M1_SYSCTL_ALARMS 2004 /* bitvector */
+
+#define SMSC47M1_ALARM_FAN1 0x0001
+#define SMSC47M1_ALARM_FAN2 0x0002
+
+#define VT1211_SYSCTL_IN0 1000
+#define VT1211_SYSCTL_IN1 1001
+#define VT1211_SYSCTL_IN2 1002
+#define VT1211_SYSCTL_IN3 1003
+#define VT1211_SYSCTL_IN4 1004
+#define VT1211_SYSCTL_IN5 1005
+#define VT1211_SYSCTL_IN6 1006
+#define VT1211_SYSCTL_FAN1 1101
+#define VT1211_SYSCTL_FAN2 1102
+#define VT1211_SYSCTL_TEMP 1200
+#define VT1211_SYSCTL_TEMP2 1201
+#define VT1211_SYSCTL_TEMP3 1202
+#define VT1211_SYSCTL_TEMP4 1203
+#define VT1211_SYSCTL_TEMP5 1204
+#define VT1211_SYSCTL_TEMP6 1205
+#define VT1211_SYSCTL_TEMP7 1206
+#define VT1211_SYSCTL_VID 1300
+#define VT1211_SYSCTL_PWM1 1401
+#define VT1211_SYSCTL_PWM2 1402
+#define VT1211_SYSCTL_VRM 1600
+#define VT1211_SYSCTL_UCH 1700
+#define VT1211_SYSCTL_FAN_DIV 2000
+#define VT1211_SYSCTL_ALARMS 2001
+
+#define VT1211_ALARM_IN1 0x01
+#define VT1211_ALARM_IN2 0x02
+#define VT1211_ALARM_IN5 0x04
+#define VT1211_ALARM_IN3 0x08
+#define VT1211_ALARM_TEMP 0x10
+#define VT1211_ALARM_FAN1 0x40
+#define VT1211_ALARM_FAN2 0x80
+#define VT1211_ALARM_IN4 0x100
+#define VT1211_ALARM_IN6 0x200
+#define VT1211_ALARM_TEMP2 0x800
+#define VT1211_ALARM_CHAS 0x1000
+#define VT1211_ALARM_TEMP3 0x8000
+/* duplicates */
+#define VT1211_ALARM_IN0 VT1211_ALARM_TEMP
+#define VT1211_ALARM_TEMP4 VT1211_ALARM_IN1
+#define VT1211_ALARM_TEMP5 VT1211_ALARM_IN2
+#define VT1211_ALARM_TEMP6 VT1211_ALARM_IN3
+#define VT1211_ALARM_TEMP7 VT1211_ALARM_IN4
+
+#define LM92_SYSCTL_ALARMS 2001 /* high, low, critical */
+#define LM92_SYSCTL_TEMP 1200 /* high, low, critical, hysterisis, input */
+
+#define LM92_ALARM_TEMP_HIGH 0x01
+#define LM92_ALARM_TEMP_LOW 0x02
+#define LM92_ALARM_TEMP_CRIT 0x04
+#define LM92_TEMP_HIGH 0x08
+#define LM92_TEMP_LOW 0x10
+#define LM92_TEMP_CRIT 0x20
+#define LM92_TEMP_HYST 0x40
+#define LM92_TEMP_INPUT 0x80
+
+#define VT8231_SYSCTL_IN0 1000
+#define VT8231_SYSCTL_IN1 1001
+#define VT8231_SYSCTL_IN2 1002
+#define VT8231_SYSCTL_IN3 1003
+#define VT8231_SYSCTL_IN4 1004
+#define VT8231_SYSCTL_IN5 1005
+#define VT8231_SYSCTL_IN6 1006
+#define VT8231_SYSCTL_FAN1 1101
+#define VT8231_SYSCTL_FAN2 1102
+#define VT8231_SYSCTL_TEMP 1200
+#define VT8231_SYSCTL_TEMP2 1201
+#define VT8231_SYSCTL_TEMP3 1202
+#define VT8231_SYSCTL_TEMP4 1203
+#define VT8231_SYSCTL_TEMP5 1204
+#define VT8231_SYSCTL_TEMP6 1205
+#define VT8231_SYSCTL_TEMP7 1206
+#define VT8231_SYSCTL_VID 1300
+#define VT8231_SYSCTL_PWM1 1401
+#define VT8231_SYSCTL_PWM2 1402
+#define VT8231_SYSCTL_VRM 1600
+#define VT8231_SYSCTL_UCH 1700
+#define VT8231_SYSCTL_FAN_DIV 2000
+#define VT8231_SYSCTL_ALARMS 2001
+
+#define VT8231_ALARM_IN1 0x01
+#define VT8231_ALARM_IN2 0x02
+#define VT8231_ALARM_IN5 0x04
+#define VT8231_ALARM_IN3 0x08
+#define VT8231_ALARM_TEMP 0x10
+#define VT8231_ALARM_FAN1 0x40
+#define VT8231_ALARM_FAN2 0x80
+#define VT8231_ALARM_IN4 0x100
+#define VT8231_ALARM_IN6 0x200
+#define VT8231_ALARM_TEMP2 0x800
+#define VT8231_ALARM_CHAS 0x1000
+#define VT8231_ALARM_TEMP3 0x8000
+/* duplicates */
+#define VT8231_ALARM_IN0 VT8231_ALARM_TEMP
+#define VT8231_ALARM_TEMP4 VT8231_ALARM_IN1
+#define VT8231_ALARM_TEMP5 VT8231_ALARM_IN2
+#define VT8231_ALARM_TEMP6 VT8231_ALARM_IN3
+#define VT8231_ALARM_TEMP7 VT8231_ALARM_IN4
+
+#define SMARTBATT_SYSCTL_I 1001
+#define SMARTBATT_SYSCTL_V 1002
+#define SMARTBATT_SYSCTL_TEMP 1003
+#define SMARTBATT_SYSCTL_TIME 1004
+#define SMARTBATT_SYSCTL_ALARMS 1005
+#define SMARTBATT_SYSCTL_CHARGE 1006
+
+
+#endif /* def SENSORS_SENSORS_H */
diff --git a/include/linux/usb.h b/include/linux/usb.h
index 88557d5957a7..bcbfa72423c3 100644
--- a/include/linux/usb.h
+++ b/include/linux/usb.h
@@ -28,14 +28,6 @@ static __inline__ void wait_ms(unsigned int ms)
mdelay(ms);
}
-/*
- * USB device number allocation bitmap. There's one bitmap
- * per USB tree.
- */
-struct usb_devmap {
- unsigned long devicemap[128 / (8*sizeof(unsigned long))];
-};
-
struct usb_device;
/*-------------------------------------------------------------------------*/
@@ -119,12 +111,21 @@ struct usb_interface {
struct usb_driver *driver; /* driver */
kdev_t kdev; /* node this interface is bound to */
struct device dev; /* interface specific device info */
- void *private_data;
};
#define to_usb_interface(d) container_of(d, struct usb_interface, dev)
#define interface_to_usbdev(intf) \
container_of(intf->dev.parent, struct usb_device, dev)
+static inline void *usb_get_intfdata (struct usb_interface *intf)
+{
+ return dev_get_drvdata (&intf->dev);
+}
+
+static inline void usb_set_intfdata (struct usb_interface *intf, void *data)
+{
+ return dev_set_drvdata (&intf->dev, data);
+}
+
/* USB_DT_CONFIG: Configuration descriptor information.
*
* USB_DT_OTHER_SPEED_CONFIG is the same descriptor, except that the
@@ -159,10 +160,16 @@ int __usb_get_extra_descriptor(char *buffer, unsigned size,
struct usb_operations;
+/* USB device number allocation bitmap */
+struct usb_devmap {
+ unsigned long devicemap[128 / (8*sizeof(unsigned long))];
+};
+
/*
- * Allocated per bus we have
+ * Allocated per bus (tree of devices) we have:
*/
struct usb_bus {
+ struct device *controller; /* host/master side hardware */
int busnum; /* Bus number (in order of reg) */
char *bus_name; /* stable id (PCI slot_name etc) */
@@ -210,7 +217,6 @@ struct usb_device {
struct usb_tt *tt; /* low/full speed dev, highspeed hub */
int ttport; /* device port on that tt hub */
- atomic_t refcnt; /* Reference count */
struct semaphore serialize;
unsigned int toggle[2]; /* one bit for each endpoint ([0] = IN, [1] = OUT) */
@@ -254,8 +260,7 @@ struct usb_device {
extern struct usb_device *usb_alloc_dev(struct usb_device *parent, struct usb_bus *);
extern struct usb_device *usb_get_dev(struct usb_device *dev);
-extern void usb_free_dev(struct usb_device *);
-#define usb_put_dev usb_free_dev
+extern void usb_put_dev(struct usb_device *dev);
/* mostly for devices emulating SCSI over USB */
extern int usb_reset_device(struct usb_device *dev);
diff --git a/include/video/font.h b/include/video/font.h
new file mode 100644
index 000000000000..fd332b3a7179
--- /dev/null
+++ b/include/video/font.h
@@ -0,0 +1,24 @@
+/*
+ * font.h -- `Soft' font definitions
+ *
+ * Created 1995 by Geert Uytterhoeven
+ *
+ * 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.
+ */
+
+#ifndef _VIDEO_FONT_H
+#define _VIDEO_FONT_H
+
+#include <linux/types.h>
+
+struct font_desc {
+ int idx;
+ char *name;
+ int width, height;
+ void *data;
+ int pref;
+};
+
+#endif /* _VIDEO_FONT_H */
diff --git a/drivers/video/tgafb.h b/include/video/tgafb.h
index 748d53fbd313..fbfae108a525 100644
--- a/drivers/video/tgafb.h
+++ b/include/video/tgafb.h
@@ -13,17 +13,17 @@
#ifndef TGAFB_H
#define TGAFB_H
- /*
- * TGA hardware description (minimal)
- */
+/*
+ * TGA hardware description (minimal)
+ */
#define TGA_TYPE_8PLANE 0
#define TGA_TYPE_24PLANE 1
#define TGA_TYPE_24PLUSZ 3
- /*
- * Offsets within Memory Space
- */
+/*
+ * Offsets within Memory Space
+ */
#define TGA_ROM_OFFSET 0x0000000
#define TGA_REGS_OFFSET 0x0100000
@@ -52,9 +52,9 @@
#define TGA_CMD_STAT_REG 0x01f8
- /*
- * useful defines for managing the registers
- */
+/*
+ * Useful defines for managing the registers
+ */
#define TGA_HORIZ_ODD 0x80000000
#define TGA_HORIZ_POLARITY 0x40000000
@@ -77,17 +77,17 @@
#define TGA_VALID_CURSOR 0x04
- /*
- * useful defines for managing the ICS1562 PLL clock
- */
+/*
+ * Useful defines for managing the ICS1562 PLL clock
+ */
#define TGA_PLL_BASE_FREQ 14318 /* .18 */
#define TGA_PLL_MAX_FREQ 230000
- /*
- * useful defines for managing the BT485 on the 8-plane TGA
- */
+/*
+ * Useful defines for managing the BT485 on the 8-plane TGA
+ */
#define BT485_READ_BIT 0x01
#define BT485_WRITE_BIT 0x00
@@ -111,9 +111,9 @@
#define BT485_CUR_HIGH_Y 0x1e
- /*
- * useful defines for managing the BT463 on the 24-plane TGAs
- */
+/*
+ * Useful defines for managing the BT463 on the 24-plane TGAs
+ */
#define BT463_ADDR_LO 0x0
#define BT463_ADDR_HI 0x1
@@ -139,61 +139,72 @@
#define BT463_WINDOW_TYPE_BASE 0x0300
+/*
+ * The framebuffer driver private data.
+ */
- /*
- * Macros for reading/writing TGA and RAMDAC registers
- */
-
-#define TGA_WRITE_REG(v,r) \
- { writel((v), fb_info.tga_regs_base+(r)); mb(); }
-
-#define TGA_READ_REG(r) readl(fb_info.tga_regs_base+(r))
-
-#define BT485_WRITE(v,r) \
- TGA_WRITE_REG((r),TGA_RAMDAC_SETUP_REG); \
- TGA_WRITE_REG(((v)&0xff)|((r)<<8),TGA_RAMDAC_REG);
-
-#define BT463_LOAD_ADDR(a) \
- TGA_WRITE_REG(BT463_ADDR_LO<<2, TGA_RAMDAC_SETUP_REG); \
- TGA_WRITE_REG((BT463_ADDR_LO<<10)|((a)&0xff), TGA_RAMDAC_REG); \
- TGA_WRITE_REG(BT463_ADDR_HI<<2, TGA_RAMDAC_SETUP_REG); \
- TGA_WRITE_REG((BT463_ADDR_HI<<10)|(((a)>>8)&0xff), TGA_RAMDAC_REG);
-
-#define BT463_WRITE(m,a,v) \
- BT463_LOAD_ADDR((a)); \
- TGA_WRITE_REG(((m)<<2),TGA_RAMDAC_SETUP_REG); \
- TGA_WRITE_REG(((m)<<10)|((v)&0xff),TGA_RAMDAC_REG);
-
-
- /*
- * This structure describes the board.
- */
-
-struct tgafb_info {
- /* Use the generic framebuffer ops */
- struct fb_info_gen gen;
-
- /* Device dependent information */
- u8 tga_type; /* TGA_TYPE_XXX */
- u8 tga_chip_rev; /* dc21030 revision */
- u64 tga_mem_base;
- u64 tga_fb_base;
- u64 tga_regs_base;
- struct fb_var_screeninfo default_var; /* default video mode */
+struct tga_par {
+ /* PCI device. */
+ struct pci_dev *pdev;
+
+ /* Device dependent information. */
+ void *tga_mem_base;
+ void *tga_fb_base;
+ void *tga_regs_base;
+ u8 tga_type; /* TGA_TYPE_XXX */
+ u8 tga_chip_rev; /* dc21030 revision */
+
+ /* Remember blank mode. */
+ u8 vesa_blanked;
+
+ /* Define the video mode. */
+ u32 xres, yres; /* resolution in pixels */
+ u32 htimings; /* horizontal timing register */
+ u32 vtimings; /* vertical timing register */
+ u32 pll_freq; /* pixclock in mhz */
+ u32 bits_per_pixel; /* bits per pixel */
+ u32 sync_on_green; /* set if sync is on green */
};
- /*
- * This structure uniquely defines a video mode.
- */
+/*
+ * Macros for reading/writing TGA and RAMDAC registers
+ */
-struct tgafb_par {
- u32 xres, yres; /* resolution in pixels */
- u32 htimings; /* horizontal timing register */
- u32 vtimings; /* vertical timing register */
- u32 pll_freq; /* pixclock in mhz */
- u32 bits_per_pixel; /* bits per pixel */
- u32 sync_on_green; /* set if sync is on green */
-};
+static inline void
+TGA_WRITE_REG(struct tga_par *par, u32 v, u32 r)
+{
+ writel(v, par->tga_regs_base +r);
+}
+
+static inline u32
+TGA_READ_REG(struct tga_par *par, u32 r)
+{
+ return readl(par->tga_regs_base +r);
+}
+
+static inline void
+BT485_WRITE(struct tga_par *par, u8 v, u8 r)
+{
+ TGA_WRITE_REG(par, r, TGA_RAMDAC_SETUP_REG);
+ TGA_WRITE_REG(par, v | (r << 8), TGA_RAMDAC_REG);
+}
+
+static inline void
+BT463_LOAD_ADDR(struct tga_par *par, u16 a)
+{
+ TGA_WRITE_REG(par, BT463_ADDR_LO<<2, TGA_RAMDAC_SETUP_REG);
+ TGA_WRITE_REG(par, (BT463_ADDR_LO<<10) | (a & 0xff), TGA_RAMDAC_REG);
+ TGA_WRITE_REG(par, BT463_ADDR_HI<<2, TGA_RAMDAC_SETUP_REG);
+ TGA_WRITE_REG(par, (BT463_ADDR_HI<<10) | (a >> 8), TGA_RAMDAC_REG);
+}
+
+static inline void
+BT463_WRITE(struct tga_par *par, u32 m, u16 a, u8 v)
+{
+ BT463_LOAD_ADDR(par, a);
+ TGA_WRITE_REG(par, m << 2, TGA_RAMDAC_SETUP_REG);
+ TGA_WRITE_REG(par, m << 10 | v, TGA_RAMDAC_REG);
+}
#endif /* TGAFB_H */
diff --git a/kernel/exec_domain.c b/kernel/exec_domain.c
index e0b31f7f5243..162a5c23e606 100644
--- a/kernel/exec_domain.c
+++ b/kernel/exec_domain.c
@@ -172,7 +172,7 @@ __set_personality(u_long personality)
fsp = copy_fs_struct(current->fs);
if (fsp == NULL) {
- put_exec_domain(ep);
+ module_put(ep->module);
return -ENOMEM;;
}
@@ -194,10 +194,7 @@ __set_personality(u_long personality)
current_thread_info()->exec_domain = ep;
set_fs_altroot();
- put_exec_domain(oep);
-
- printk(KERN_DEBUG "[%s:%d]: set personality to %lx\n",
- current->comm, current->pid, personality);
+ module_put(oep->module);
return 0;
}
diff --git a/kernel/exit.c b/kernel/exit.c
index 5e7fcdaa6221..6adea537242a 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -664,9 +664,9 @@ fake_volatile:
if (current->leader)
disassociate_ctty(1);
- put_exec_domain(tsk->thread_info->exec_domain);
- if (tsk->binfmt && tsk->binfmt->module)
- __MOD_DEC_USE_COUNT(tsk->binfmt->module);
+ module_put(tsk->thread_info->exec_domain->module);
+ if (tsk->binfmt)
+ module_put(tsk->binfmt->module);
tsk->exit_code = code;
exit_notify();
diff --git a/kernel/fork.c b/kernel/fork.c
index b8771509f285..6f7298827344 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -743,10 +743,11 @@ static struct task_struct *copy_process(unsigned long clone_flags,
if (nr_threads >= max_threads)
goto bad_fork_cleanup_count;
- get_exec_domain(p->thread_info->exec_domain);
+ if (!try_module_get(p->thread_info->exec_domain->module))
+ goto bad_fork_cleanup_count;
- if (p->binfmt && p->binfmt->module)
- __MOD_INC_USE_COUNT(p->binfmt->module);
+ if (p->binfmt && !try_module_get(p->binfmt->module))
+ goto bad_fork_cleanup_put_domain;
#ifdef CONFIG_PREEMPT
/*
@@ -958,9 +959,10 @@ bad_fork_cleanup_security:
bad_fork_cleanup:
if (p->pid > 0)
free_pidmap(p->pid);
- put_exec_domain(p->thread_info->exec_domain);
- if (p->binfmt && p->binfmt->module)
- __MOD_DEC_USE_COUNT(p->binfmt->module);
+ if (p->binfmt)
+ module_put(p->binfmt->module);
+bad_fork_cleanup_put_domain:
+ module_put(p->thread_info->exec_domain->module);
bad_fork_cleanup_count:
atomic_dec(&p->user->processes);
free_uid(p->user);
diff --git a/kernel/intermodule.c b/kernel/intermodule.c
index a6cd1d08afa4..9228ca4fe035 100644
--- a/kernel/intermodule.c
+++ b/kernel/intermodule.c
@@ -166,7 +166,7 @@ void inter_module_put(const char *im_name)
ime = list_entry(tmp, struct inter_module_entry, list);
if (strcmp(ime->im_name, im_name) == 0) {
if (ime->owner)
- __MOD_DEC_USE_COUNT(ime->owner);
+ module_put(ime->owner);
spin_unlock(&ime_lock);
return;
}
diff --git a/kernel/ksyms.c b/kernel/ksyms.c
index f634f12d4bef..cd49778dd1f3 100644
--- a/kernel/ksyms.c
+++ b/kernel/ksyms.c
@@ -299,6 +299,7 @@ EXPORT_SYMBOL(dcache_dir_open);
EXPORT_SYMBOL(dcache_dir_close);
EXPORT_SYMBOL(dcache_dir_lseek);
EXPORT_SYMBOL(dcache_readdir);
+EXPORT_SYMBOL(simple_getattr);
EXPORT_SYMBOL(simple_statfs);
EXPORT_SYMBOL(simple_lookup);
EXPORT_SYMBOL(simple_dir_operations);
diff --git a/kernel/module.c b/kernel/module.c
index c73b19336f1e..4b789cf97f5d 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -60,6 +60,13 @@ struct sizes
unsigned long core_size;
};
+/* Stub function for modules which don't have an initfn */
+int init_module(void)
+{
+ return 0;
+}
+EXPORT_SYMBOL(init_module);
+
/* Find a symbol, return value and the symbol group */
static unsigned long __find_symbol(const char *name,
struct kernel_symbol_group **group)
@@ -357,6 +364,12 @@ static inline int try_force(unsigned int flags)
}
#endif /* CONFIG_MODULE_FORCE_UNLOAD */
+/* Stub function for modules which don't have an exitfn */
+void cleanup_module(void)
+{
+}
+EXPORT_SYMBOL(cleanup_module);
+
asmlinkage long
sys_delete_module(const char *name_user, unsigned int flags)
{
@@ -405,7 +418,9 @@ sys_delete_module(const char *name_user, unsigned int flags)
}
}
- if (!mod->exit || mod->unsafe) {
+ /* If it has an init func, it must have an exit func to unload */
+ if ((mod->init != init_module && mod->exit == cleanup_module)
+ || mod->unsafe) {
forced = try_force(flags);
if (!forced) {
/* This module can't be removed */
@@ -452,8 +467,7 @@ sys_delete_module(const char *name_user, unsigned int flags)
destroy:
/* Final destruction now noone is using it. */
- if (mod->exit)
- mod->exit();
+ mod->exit();
free_module(mod);
out:
@@ -473,7 +487,7 @@ static void print_unload_info(struct seq_file *m, struct module *mod)
if (mod->unsafe)
seq_printf(m, " [unsafe]");
- if (!mod->exit)
+ if (mod->init != init_module && mod->exit == cleanup_module)
seq_printf(m, " [permanent]");
seq_printf(m, "\n");
@@ -707,15 +721,15 @@ static void free_module(struct module *mod)
list_del(&mod->extable.list);
spin_unlock_irq(&modlist_lock);
- /* These may be NULL, but that's OK */
- module_free(mod, mod->module_init);
- module_free(mod, mod->module_core);
-
/* Module unload stuff */
module_unload_free(mod);
- /* Finally, free the module structure */
- module_free(mod, mod);
+ /* This may be NULL, but that's OK */
+ module_free(mod, mod->module_init);
+ kfree(mod->args);
+
+ /* Finally, free the core (containing the module structure) */
+ module_free(mod, mod->module_core);
}
void *__symbol_get(const char *symbol)
@@ -770,27 +784,6 @@ static void *copy_section(const char *name,
return dest;
}
-/* Look for the special symbols */
-static int grab_private_symbols(Elf_Shdr *sechdrs,
- unsigned int symbolsec,
- const char *strtab,
- struct module *mod)
-{
- Elf_Sym *sym = (void *)sechdrs[symbolsec].sh_offset;
- unsigned int i;
-
- for (i = 1; i < sechdrs[symbolsec].sh_size/sizeof(*sym); i++) {
- if (symbol_is("__initfn", strtab + sym[i].st_name))
- mod->init = (void *)sym[i].st_value;
-#ifdef CONFIG_MODULE_UNLOAD
- if (symbol_is("__exitfn", strtab + sym[i].st_name))
- mod->exit = (void *)sym[i].st_value;
-#endif
- }
-
- return 0;
-}
-
/* Deal with the given section */
static int handle_section(const char *name,
Elf_Shdr *sechdrs,
@@ -809,9 +802,6 @@ static int handle_section(const char *name,
case SHT_RELA:
ret = apply_relocate_add(sechdrs, strtab, symindex, i, mod);
break;
- case SHT_SYMTAB:
- ret = grab_private_symbols(sechdrs, i, strtab, mod);
- break;
default:
DEBUGP("Ignoring section %u: %s\n", i,
sechdrs[i].sh_type==SHT_NULL ? "NULL":
@@ -919,9 +909,6 @@ static void simplify_symbols(Elf_Shdr *sechdrs,
strtab + sym[i].st_name,
mod,
&ksg);
- /* We fake up "__this_module" */
- if (symbol_is("__this_module", strtab+sym[i].st_name))
- sym[i].st_value = (unsigned long)mod;
}
}
}
@@ -963,9 +950,9 @@ static struct module *load_module(void *umod,
{
Elf_Ehdr *hdr;
Elf_Shdr *sechdrs;
- char *secstrings;
+ char *secstrings, *args;
unsigned int i, symindex, exportindex, strindex, setupindex, exindex,
- modnameindex, obsparmindex;
+ modindex, obsparmindex;
long arglen;
unsigned long common_length;
struct sizes sizes, used;
@@ -1006,7 +993,7 @@ static struct module *load_module(void *umod,
exportindex = setupindex = obsparmindex = 0;
/* And these should exist, but gcc whinges if we don't init them */
- symindex = strindex = exindex = modnameindex = 0;
+ symindex = strindex = exindex = modindex = 0;
/* Find where important sections are */
for (i = 1; i < hdr->e_shnum; i++) {
@@ -1014,21 +1001,19 @@ static struct module *load_module(void *umod,
/* Internal symbols */
DEBUGP("Symbol table in section %u\n", i);
symindex = i;
+ /* Strings */
+ strindex = sechdrs[i].sh_link;
+ DEBUGP("String table found in section %u\n", strindex);
} else if (strcmp(secstrings+sechdrs[i].sh_name,
- ".gnu.linkonce.modname") == 0) {
- /* This module's name */
- DEBUGP("Module name in section %u\n", i);
- modnameindex = i;
+ ".gnu.linkonce.this_module") == 0) {
+ /* The module struct */
+ DEBUGP("Module in section %u\n", i);
+ modindex = i;
} else if (strcmp(secstrings+sechdrs[i].sh_name, "__ksymtab")
== 0) {
/* Exported symbols. */
DEBUGP("EXPORT table in section %u\n", i);
exportindex = i;
- } else if (strcmp(secstrings + sechdrs[i].sh_name, ".strtab")
- == 0) {
- /* Strings */
- DEBUGP("String table found in section %u\n", i);
- strindex = i;
} else if (strcmp(secstrings+sechdrs[i].sh_name, "__param")
== 0) {
/* Setup parameter info */
@@ -1057,39 +1042,35 @@ static struct module *load_module(void *umod,
#endif
}
- if (!modnameindex) {
- DEBUGP("Module has no name!\n");
+ if (!modindex) {
+ printk(KERN_WARNING "No module found in object\n");
err = -ENOEXEC;
goto free_hdr;
}
+ mod = (void *)hdr + sechdrs[modindex].sh_offset;
- /* Now allocate space for the module proper, and copy name and args. */
+ /* Now copy in args */
err = strlen_user(uargs);
if (err < 0)
goto free_hdr;
arglen = err;
- mod = module_alloc(sizeof(*mod) + arglen+1);
- if (!mod) {
+ args = kmalloc(arglen+1, GFP_KERNEL);
+ if (!args) {
err = -ENOMEM;
goto free_hdr;
}
- memset(mod, 0, sizeof(*mod) + arglen+1);
- if (copy_from_user(mod->args, uargs, arglen) != 0) {
+ if (copy_from_user(args, uargs, arglen+1) != 0) {
err = -EFAULT;
goto free_mod;
}
- strncpy(mod->name, (char *)hdr + sechdrs[modnameindex].sh_offset,
- sizeof(mod->name)-1);
if (find_module(mod->name)) {
err = -EEXIST;
goto free_mod;
}
- mod->symbols.owner = mod;
mod->state = MODULE_STATE_COMING;
- module_unload_init(mod);
/* How much space will we need? (Common area in first) */
common_length = read_commons(hdr, &sechdrs[symindex]);
@@ -1138,6 +1119,9 @@ static struct module *load_module(void *umod,
if (IS_ERR(ptr))
goto cleanup;
sechdrs[i].sh_offset = (unsigned long)ptr;
+ /* Have we just copied __this_module across? */
+ if (i == modindex)
+ mod = ptr;
} else {
sechdrs[i].sh_offset += (unsigned long)hdr;
}
@@ -1146,6 +1130,9 @@ static struct module *load_module(void *umod,
if (used.init_size > mod->init_size || used.core_size > mod->core_size)
BUG();
+ /* Now we've moved module, initialize linked lists, etc. */
+ module_unload_init(mod);
+
/* Fix up syms, so that st_value is a pointer to location. */
simplify_symbols(sechdrs, symindex, strindex, mod->module_core, mod);
@@ -1182,6 +1169,7 @@ static struct module *load_module(void *umod,
if (err < 0)
goto cleanup;
+ mod->args = args;
if (obsparmindex) {
err = obsolete_params(mod->name, mod->args,
(struct obsolete_modparm *)
@@ -1214,7 +1202,7 @@ static struct module *load_module(void *umod,
free_core:
module_free(mod, mod->module_core);
free_mod:
- module_free(mod, mod);
+ kfree(args);
free_hdr:
vfree(hdr);
if (err < 0) return ERR_PTR(err);
@@ -1265,7 +1253,7 @@ sys_init_module(void *umod,
up(&module_mutex);
/* Start the module */
- ret = mod->init ? mod->init() : 0;
+ ret = mod->init();
if (ret < 0) {
/* Init routine failed: abort. Try to protect us from
buggy refcounters. */
diff --git a/kernel/printk.c b/kernel/printk.c
index cbe027aaf151..bb1bcb0d723f 100644
--- a/kernel/printk.c
+++ b/kernel/printk.c
@@ -638,7 +638,7 @@ void register_console(struct console * console)
}
if (console->flags & CON_PRINTBUFFER) {
/*
- * release_cosole_sem() will print out the buffered messages for us.
+ * release_console_sem() will print out the buffered messages for us.
*/
spin_lock_irqsave(&logbuf_lock, flags);
con_start = log_start;
diff --git a/kernel/resource.c b/kernel/resource.c
index 9664ad073db7..83d04826245d 100644
--- a/kernel/resource.c
+++ b/kernel/resource.c
@@ -237,7 +237,7 @@ struct resource * __request_region(struct resource *parent, unsigned long start,
return res;
}
-int __check_region(struct resource *parent, unsigned long start, unsigned long n)
+int __deprecated __check_region(struct resource *parent, unsigned long start, unsigned long n)
{
struct resource * res;
diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c
index 82a847128a31..1eedb5ed6cb2 100644
--- a/net/ax25/af_ax25.c
+++ b/net/ax25/af_ax25.c
@@ -1786,7 +1786,7 @@ static int ax25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
warned=1;
}
- if (copy_to_user((void *)arg, &ax25_info, sizeof(struct ax25_info_struct_depreciated))) {
+ if (copy_to_user((void *)arg, &ax25_info, sizeof(struct ax25_info_struct_deprecated))) {
res = -EFAULT;
break;
}
diff --git a/net/core/dev.c b/net/core/dev.c
index e48cb774fe0f..97e772ff5f82 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -703,8 +703,7 @@ int dev_open(struct net_device *dev)
ret = dev->open(dev);
if (ret) {
clear_bit(__LINK_STATE_START, &dev->state);
- if (dev->owner)
- __MOD_DEC_USE_COUNT(dev->owner);
+ module_put(dev->owner);
}
}
} else {
@@ -829,16 +828,14 @@ int dev_close(struct net_device *dev)
#endif
/*
- * Tell people we are down
+ * Tell people we are down
*/
notifier_call_chain(&netdev_chain, NETDEV_DOWN, dev);
/*
* Drop the module refcount
*/
- if (dev->owner)
- __MOD_DEC_USE_COUNT(dev->owner);
-
+ module_put(dev->owner);
return 0;
}
diff --git a/net/ipv4/xfrm_policy.c b/net/ipv4/xfrm_policy.c
index d21d597e7be1..fe30556f78d6 100644
--- a/net/ipv4/xfrm_policy.c
+++ b/net/ipv4/xfrm_policy.c
@@ -200,8 +200,7 @@ struct xfrm_type *xfrm_get_type(u8 proto)
void xfrm_put_type(struct xfrm_type *type)
{
- if (type->owner)
- __MOD_DEC_USE_COUNT(type->owner);
+ module_put(type->owner);
}
static inline unsigned long make_jiffies(long secs)
diff --git a/net/rxrpc/call.c b/net/rxrpc/call.c
index 6bba546eece7..a0e81b58191d 100644
--- a/net/rxrpc/call.c
+++ b/net/rxrpc/call.c
@@ -435,7 +435,7 @@ void rxrpc_put_call(struct rxrpc_call *call)
rxrpc_put_message(msg);
}
- if (call->owner) __MOD_DEC_USE_COUNT(call->owner);
+ module_put(call->owner);
down_write(&rxrpc_calls_sem);
list_del(&call->call_link);
diff --git a/scripts/ver_linux b/scripts/ver_linux
index edc3ec1f26a4..9fe09a9c7f94 100644
--- a/scripts/ver_linux
+++ b/scripts/ver_linux
@@ -28,7 +28,7 @@ fdformat --version | awk -F\- '{print "util-linux ", $NF}'
mount --version | awk -F\- '{print "mount ", $NF}'
-insmod -V 2>&1 | awk 'NR==1 {print "modutils ",$NF}'
+rmmod -V 2>&1 | awk 'NR==1 {print "module-init-tools ",$NF}'
tune2fs 2>&1 | grep "^tune2fs" | sed 's/,//' | awk \
'NR==1 {print "e2fsprogs ", $2}'
diff --git a/sound/core/control.c b/sound/core/control.c
index 6dce340429ff..7de5256c19fc 100644
--- a/sound/core/control.c
+++ b/sound/core/control.c
@@ -40,12 +40,6 @@ typedef struct _snd_kctl_ioctl {
static DECLARE_RWSEM(snd_ioctl_rwsem);
static LIST_HEAD(snd_control_ioctls);
-static inline void dec_mod_count(struct module *module)
-{
- if (module)
- __MOD_DEC_USE_COUNT(module);
-}
-
static int snd_ctl_open(struct inode *inode, struct file *file)
{
int cardnum = SNDRV_MINOR_CARD(minor(inode->i_rdev));
@@ -88,7 +82,7 @@ static int snd_ctl_open(struct inode *inode, struct file *file)
return 0;
__error:
- dec_mod_count(card->module);
+ module_put(card->module);
__error2:
snd_card_file_remove(card, file);
__error1:
@@ -135,7 +129,7 @@ static int snd_ctl_release(struct inode *inode, struct file *file)
up_write(&card->controls_rwsem);
snd_ctl_empty_read_queue(ctl);
snd_magic_kfree(ctl);
- dec_mod_count(card->module);
+ module_put(card->module);
snd_card_file_remove(card, file);
#ifdef LINUX_2_2
MOD_DEC_USE_COUNT;
diff --git a/sound/core/info.c b/sound/core/info.c
index 808f46456976..0ae2541810a6 100644
--- a/sound/core/info.c
+++ b/sound/core/info.c
@@ -36,12 +36,6 @@
*
*/
-static inline void dec_mod_count(struct module *module)
-{
- if (module)
- __MOD_DEC_USE_COUNT(module);
-}
-
int snd_info_check_reserved_words(const char *str)
{
static char *reserved[] =
@@ -407,7 +401,7 @@ static int snd_info_entry_open(struct inode *inode, struct file *file)
return 0;
__error:
- dec_mod_count(entry->module);
+ module_put(entry->module);
__error1:
#ifdef LINUX_2_2
MOD_DEC_USE_COUNT;
@@ -450,7 +444,7 @@ static int snd_info_entry_release(struct inode *inode, struct file *file)
data->file_private_data);
break;
}
- dec_mod_count(entry->module);
+ module_put(entry->module);
#ifdef LINUX_2_2
MOD_DEC_USE_COUNT;
#endif
diff --git a/sound/core/oss/mixer_oss.c b/sound/core/oss/mixer_oss.c
index 0d6aecd9016c..088bf5ea33c1 100644
--- a/sound/core/oss/mixer_oss.c
+++ b/sound/core/oss/mixer_oss.c
@@ -34,12 +34,6 @@ MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
MODULE_DESCRIPTION("Mixer OSS emulation for ALSA.");
MODULE_LICENSE("GPL");
-static inline void dec_mod_count(struct module *module)
-{
- if (module)
- __MOD_DEC_USE_COUNT(module);
-}
-
static int snd_mixer_oss_open(struct inode *inode, struct file *file)
{
int cardnum = SNDRV_MINOR_OSS_CARD(minor(inode->i_rdev));
@@ -82,7 +76,7 @@ static int snd_mixer_oss_release(struct inode *inode, struct file *file)
if (file->private_data) {
fmixer = (snd_mixer_oss_file_t *) file->private_data;
- dec_mod_count(fmixer->card->module);
+ module_put(fmixer->card->module);
#ifdef LINUX_2_2
MOD_DEC_USE_COUNT;
#endif
diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c
index c6e18a7e0d0a..4febec2769c2 100644
--- a/sound/core/oss/pcm_oss.c
+++ b/sound/core/oss/pcm_oss.c
@@ -71,12 +71,6 @@ static inline void snd_leave_user(mm_segment_t fs)
set_fs(fs);
}
-static inline void dec_mod_count(struct module *module)
-{
- if (module)
- __MOD_DEC_USE_COUNT(module);
-}
-
int snd_pcm_oss_plugin_clear(snd_pcm_substream_t *substream)
{
snd_pcm_runtime_t *runtime = substream->runtime;
@@ -1617,7 +1611,7 @@ static int snd_pcm_oss_open(struct inode *inode, struct file *file)
return err;
__error:
- dec_mod_count(pcm->card->module);
+ module_put(pcm->card->module);
__error2:
snd_card_file_remove(pcm->card, file);
__error1:
@@ -1644,7 +1638,7 @@ static int snd_pcm_oss_release(struct inode *inode, struct file *file)
snd_pcm_oss_release_file(pcm_oss_file);
up(&pcm->open_mutex);
wake_up(&pcm->open_wait);
- dec_mod_count(pcm->card->module);
+ module_put(pcm->card->module);
snd_card_file_remove(pcm->card, file);
#ifdef LINUX_2_2
MOD_DEC_USE_COUNT;
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index 773d3a10c567..57f2a9c0f4a2 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -76,14 +76,6 @@ static inline void snd_leave_user(mm_segment_t fs)
set_fs(fs);
}
-static inline void dec_mod_count(struct module *module)
-{
- if (module)
- __MOD_DEC_USE_COUNT(module);
-}
-
-
-
int snd_pcm_info(snd_pcm_substream_t * substream, snd_pcm_info_t *info)
{
snd_pcm_runtime_t * runtime;
@@ -1833,7 +1825,7 @@ int snd_pcm_open(struct inode *inode, struct file *file)
return err;
__error:
- dec_mod_count(pcm->card->module);
+ module_put(pcm->card->module);
__error2:
snd_card_file_remove(pcm->card, file);
__error1:
@@ -1863,7 +1855,7 @@ int snd_pcm_release(struct inode *inode, struct file *file)
snd_pcm_release_file(pcm_file);
up(&pcm->open_mutex);
wake_up(&pcm->open_wait);
- dec_mod_count(pcm->card->module);
+ module_put(pcm->card->module);
snd_card_file_remove(pcm->card, file);
#ifdef LINUX_2_2
MOD_DEC_USE_COUNT;
diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c
index 18dc962f094d..a03924780f93 100644
--- a/sound/core/rawmidi.c
+++ b/sound/core/rawmidi.c
@@ -58,12 +58,6 @@ snd_rawmidi_t *snd_rawmidi_devices[SNDRV_CARDS * SNDRV_RAWMIDI_DEVICES];
static DECLARE_MUTEX(register_mutex);
-static inline void dec_mod_count(struct module *module)
-{
- if (module)
- __MOD_DEC_USE_COUNT(module);
-}
-
static inline unsigned short snd_rawmidi_file_flags(struct file *file)
{
switch (file->f_mode & (FMODE_READ | FMODE_WRITE)) {
@@ -345,7 +339,7 @@ int snd_rawmidi_kernel_open(int cardnum, int device, int subdevice,
snd_rawmidi_done_buffer(output);
kfree(output);
}
- dec_mod_count(rmidi->card->module);
+ module_put(rmidi->card->module);
up(&rmidi->open_mutex);
__error1:
#ifdef LINUX_2_2
@@ -504,7 +498,7 @@ int snd_rawmidi_kernel_release(snd_rawmidi_file_t * rfile)
rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT].substream_opened--;
}
up(&rmidi->open_mutex);
- dec_mod_count(rmidi->card->module);
+ module_put(rmidi->card->module);
#ifdef LINUX_2_2
MOD_DEC_USE_COUNT;
#endif
diff --git a/sound/core/seq/oss/seq_oss_synth.c b/sound/core/seq/oss/seq_oss_synth.c
index 9cc61a3cd426..837ef15abb69 100644
--- a/sound/core/seq/oss/seq_oss_synth.c
+++ b/sound/core/seq/oss/seq_oss_synth.c
@@ -83,12 +83,6 @@ static spinlock_t register_lock = SPIN_LOCK_UNLOCKED;
static seq_oss_synth_t *get_synthdev(seq_oss_devinfo_t *dp, int dev);
static void reset_channels(seq_oss_synthinfo_t *info);
-static inline void dec_mod_count(struct module *module)
-{
- if (module)
- __MOD_DEC_USE_COUNT(module);
-}
-
/*
* global initialization
*/
@@ -245,7 +239,7 @@ snd_seq_oss_synth_setup(seq_oss_devinfo_t *dp)
continue;
}
if (rec->oper.open(&info->arg, rec->private_data) < 0) {
- dec_mod_count(rec->oper.owner);
+ module_put(rec->oper.owner);
snd_use_lock_free(&rec->use_lock);
continue;
}
@@ -322,7 +316,7 @@ snd_seq_oss_synth_cleanup(seq_oss_devinfo_t *dp)
if (rec->opened) {
debug_printk(("synth %d closed\n", i));
rec->oper.close(&info->arg);
- dec_mod_count(rec->oper.owner);
+ module_put(rec->oper.owner);
rec->opened--;
}
snd_use_lock_free(&rec->use_lock);
diff --git a/sound/core/seq/seq_ports.c b/sound/core/seq/seq_ports.c
index 8f5d7ed2b4d8..14943f8fecb8 100644
--- a/sound/core/seq/seq_ports.c
+++ b/sound/core/seq/seq_ports.c
@@ -55,12 +55,6 @@ much elements are in array.
*/
-static inline void dec_mod_count(struct module *module)
-{
- if (module)
- __MOD_DEC_USE_COUNT(module);
-}
-
/* return pointer to port structure - port is locked if found */
client_port_t *snd_seq_port_use_ptr(client_t *client, int num)
{
@@ -413,7 +407,7 @@ static int subscribe_port(client_t *client, client_port_t *port, port_subs_info_
if (grp->open && (port->callback_all || grp->count == 1)) {
err = grp->open(port->private_data, info);
if (err < 0) {
- dec_mod_count(port->owner);
+ module_put(port->owner);
grp->count--;
}
}
@@ -438,7 +432,7 @@ static int unsubscribe_port(client_t *client, client_port_t *port,
if (send_ack && client->type == USER_CLIENT)
snd_seq_client_notify_subscription(port->addr.client, port->addr.port,
info, SNDRV_SEQ_EVENT_PORT_UNSUBSCRIBED);
- dec_mod_count(port->owner);
+ module_put(port->owner);
return err;
}
diff --git a/sound/core/seq/seq_virmidi.c b/sound/core/seq/seq_virmidi.c
index d4fcb6aa085c..0719b6ad0ee8 100644
--- a/sound/core/seq/seq_virmidi.c
+++ b/sound/core/seq/seq_virmidi.c
@@ -53,12 +53,6 @@ MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>");
MODULE_DESCRIPTION("Virtual Raw MIDI client on Sequencer");
MODULE_LICENSE("GPL");
-static inline void dec_mod_count(struct module *module)
-{
- if (module)
- __MOD_DEC_USE_COUNT(module);
-}
-
/*
* initialize an event record
*/
@@ -303,7 +297,7 @@ static int snd_virmidi_unsubscribe(void *private_data, snd_seq_port_subscribe_t
rdev = snd_magic_cast(snd_virmidi_dev_t, private_data, return -EINVAL);
rdev->flags &= ~SNDRV_VIRMIDI_SUBSCRIBE;
- dec_mod_count(rdev->card->module);
+ module_put(rdev->card->module);
return 0;
}
@@ -331,7 +325,7 @@ static int snd_virmidi_unuse(void *private_data, snd_seq_port_subscribe_t *info)
rdev = snd_magic_cast(snd_virmidi_dev_t, private_data, return -EINVAL);
rdev->flags &= ~SNDRV_VIRMIDI_USE;
- dec_mod_count(rdev->card->module);
+ module_put(rdev->card->module);
return 0;
}
diff --git a/sound/core/timer.c b/sound/core/timer.c
index e16dfdda8a95..1b571b00728d 100644
--- a/sound/core/timer.c
+++ b/sound/core/timer.c
@@ -80,12 +80,6 @@ static int snd_timer_dev_unregister(snd_device_t *device);
static void snd_timer_reschedule(snd_timer_t * timer, unsigned long ticks_left);
-static inline void dec_mod_count(struct module *module)
-{
- if (module)
- __MOD_DEC_USE_COUNT(module);
-}
-
/*
* create a timer instance with the given owner string.
* when timer is not NULL, increments the module counter
@@ -325,7 +319,7 @@ int snd_timer_close(snd_timer_instance_t * timeri)
kfree(timeri->owner);
kfree(timeri);
if (timer && timer->card)
- dec_mod_count(timer->card->module);
+ module_put(timer->card->module);
return 0;
}
diff --git a/sound/drivers/opl3/opl3_seq.c b/sound/drivers/opl3/opl3_seq.c
index 2651522d72e5..c622456c6136 100644
--- a/sound/drivers/opl3/opl3_seq.c
+++ b/sound/drivers/opl3/opl3_seq.c
@@ -35,12 +35,6 @@ int use_internal_drums = 0;
MODULE_PARM(use_internal_drums, "i");
MODULE_PARM_DESC(use_internal_drums, "Enable internal OPL2/3 drums.");
-static inline void dec_mod_count(struct module *module)
-{
- if (module)
- __MOD_DEC_USE_COUNT(module);
-}
-
int snd_opl3_synth_use_inc(opl3_t * opl3)
{
if (!try_inc_mod_count(opl3->card->module))
@@ -51,7 +45,7 @@ int snd_opl3_synth_use_inc(opl3_t * opl3)
void snd_opl3_synth_use_dec(opl3_t * opl3)
{
- dec_mod_count(opl3->card->module);
+ module_put(opl3->card->module);
}
int snd_opl3_synth_setup(opl3_t * opl3)
diff --git a/sound/isa/gus/gus_main.c b/sound/isa/gus/gus_main.c
index 04fa4a649ab6..a3473afd0118 100644
--- a/sound/isa/gus/gus_main.c
+++ b/sound/isa/gus/gus_main.c
@@ -39,12 +39,6 @@ MODULE_LICENSE("GPL");
static int snd_gus_init_dma_irq(snd_gus_card_t * gus, int latches);
-static inline void dec_mod_count(struct module *module)
-{
- if (module)
- __MOD_DEC_USE_COUNT(module);
-}
-
int snd_gus_use_inc(snd_gus_card_t * gus)
{
MOD_INC_USE_COUNT;
@@ -57,7 +51,7 @@ int snd_gus_use_inc(snd_gus_card_t * gus)
void snd_gus_use_dec(snd_gus_card_t * gus)
{
- dec_mod_count(gus->card->module);
+ module_put(gus->card->module);
MOD_DEC_USE_COUNT;
}
diff --git a/sound/isa/wavefront/wavefront_fx.c b/sound/isa/wavefront/wavefront_fx.c
index 75aaca8a9fb9..817b6d807a86 100644
--- a/sound/isa/wavefront/wavefront_fx.c
+++ b/sound/isa/wavefront/wavefront_fx.c
@@ -33,13 +33,6 @@
#define FX_MSB_TRANSFER 0x02 /* transfer after DSP MSB byte written */
#define FX_AUTO_INCR 0x04 /* auto-increment DSP address after transfer */
-static inline void
-dec_mod_count(struct module *module)
-{
- if (module)
- __MOD_DEC_USE_COUNT(module);
-}
-
static int
wavefront_fx_idle (snd_wavefront_t *dev)
@@ -164,7 +157,7 @@ int
snd_wavefront_fx_release (snd_hwdep_t *hw, struct file *file)
{
- dec_mod_count(hw->card->module);
+ module_put(hw->card->module);
MOD_DEC_USE_COUNT;
return 0;
}
diff --git a/sound/isa/wavefront/wavefront_synth.c b/sound/isa/wavefront/wavefront_synth.c
index 5f0058dc08ca..f3e26ef9473f 100644
--- a/sound/isa/wavefront/wavefront_synth.c
+++ b/sound/isa/wavefront/wavefront_synth.c
@@ -233,13 +233,6 @@ static wavefront_command wavefront_commands[] = {
{ 0x00 }
};
-static inline void
-dec_mod_count(struct module *module)
-{
- if (module)
- __MOD_DEC_USE_COUNT(module);
-}
-
static const char *
wavefront_errorstr (int errnum)
@@ -1623,7 +1616,7 @@ int
snd_wavefront_synth_release (snd_hwdep_t *hw, struct file *file)
{
- dec_mod_count(hw->card->module);
+ module_put(hw->card->module);
MOD_DEC_USE_COUNT;
return 0;
}
diff --git a/sound/oss/audio.c b/sound/oss/audio.c
index 74e3c282c14f..91101d990e49 100644
--- a/sound/oss/audio.c
+++ b/sound/oss/audio.c
@@ -88,19 +88,20 @@ int audio_open(int dev, struct file *file)
return -ENXIO;
driver = audio_devs[dev]->d;
- if (driver->owner)
- __MOD_INC_USE_COUNT(driver->owner);
+
+ if (!try_module_get(driver->owner))
+ return -ENODEV;
if ((ret = DMAbuf_open(dev, mode)) < 0)
goto error_1;
if ( (coprocessor = audio_devs[dev]->coproc) != NULL ) {
- if (coprocessor->owner)
- __MOD_INC_USE_COUNT(coprocessor->owner);
+ if (!try_module_get(coprocessor->owner))
+ goto error_2;
if ((ret = coprocessor->open(coprocessor->devc, COPR_PCM)) < 0) {
printk(KERN_WARNING "Sound: Can't access coprocessor device\n");
- goto error_2;
+ goto error_3;
}
}
@@ -119,14 +120,14 @@ int audio_open(int dev, struct file *file)
* Clean-up stack: this is what needs (un)doing if
* we can't open the audio device ...
*/
+ error_3:
+ module_put(coprocessor->owner);
+
error_2:
- if (coprocessor->owner)
- __MOD_DEC_USE_COUNT(coprocessor->owner);
DMAbuf_release(dev, mode);
error_1:
- if (driver->owner)
- __MOD_DEC_USE_COUNT(driver->owner);
+ module_put(driver->owner);
return ret;
}
@@ -200,14 +201,11 @@ void audio_release(int dev, struct file *file)
if ( (coprocessor = audio_devs[dev]->coproc) != NULL ) {
coprocessor->close(coprocessor->devc, COPR_PCM);
-
- if (coprocessor->owner)
- __MOD_DEC_USE_COUNT(coprocessor->owner);
+ module_put(coprocessor->owner);
}
DMAbuf_release(dev, mode);
- if (audio_devs[dev]->d->owner)
- __MOD_DEC_USE_COUNT (audio_devs[dev]->d->owner);
+ module_put(audio_devs[dev]->d->owner);
}
static void translate_bytes(const unsigned char *table, unsigned char *buff, int n)
diff --git a/sound/oss/midibuf.c b/sound/oss/midibuf.c
index 58b330ecad1f..30f8c7f67971 100644
--- a/sound/oss/midibuf.c
+++ b/sound/oss/midibuf.c
@@ -170,8 +170,7 @@ int MIDIbuf_open(int dev, struct file *file)
* Interrupts disabled. Be careful
*/
- if (midi_devs[dev]->owner)
- __MOD_INC_USE_COUNT (midi_devs[dev]->owner);
+ module_put(midi_devs[dev]->owner);
if ((err = midi_devs[dev]->open(dev, mode,
midi_input_intr, midi_output_intr)) < 0)
@@ -254,8 +253,7 @@ void MIDIbuf_release(int dev, struct file *file)
midi_in_buf[dev] = NULL;
midi_out_buf[dev] = NULL;
- if (midi_devs[dev]->owner)
- __MOD_DEC_USE_COUNT (midi_devs[dev]->owner);
+ module_put(midi_devs[dev]->owner);
}
int MIDIbuf_write(int dev, struct file *file, const char *buf, int count)
diff --git a/sound/oss/mpu401.c b/sound/oss/mpu401.c
index a8817a2d8d02..c8d9d59ef915 100644
--- a/sound/oss/mpu401.c
+++ b/sound/oss/mpu401.c
@@ -498,8 +498,10 @@ static int mpu401_open(int dev, int mode,
if ( (coprocessor = midi_devs[dev]->coproc) != NULL )
{
- if (coprocessor->owner)
- __MOD_INC_USE_COUNT(coprocessor->owner);
+ if (!try_module_get(coprocessor->owner)) {
+ mpu401_close(dev);
+ return err;
+ }
if ((err = coprocessor->open(coprocessor->devc, COPR_MIDI)) < 0)
{
@@ -537,9 +539,7 @@ static void mpu401_close(int dev)
coprocessor = midi_devs[dev]->coproc;
if (coprocessor) {
coprocessor->close(coprocessor->devc, COPR_MIDI);
-
- if (coprocessor->owner)
- __MOD_DEC_USE_COUNT(coprocessor->owner);
+ module_put(coprocessor->owner);
}
devc->opened = 0;
}
@@ -838,8 +838,8 @@ static int mpu_synth_open(int dev, int mode)
coprocessor = midi_devs[midi_dev]->coproc;
if (coprocessor) {
- if (coprocessor->owner)
- __MOD_INC_USE_COUNT(coprocessor->owner);
+ if (!try_module_get(coprocessor->owner))
+ return err;
if ((err = coprocessor->open(coprocessor->devc, COPR_MIDI)) < 0)
{
@@ -876,9 +876,7 @@ static void mpu_synth_close(int dev)
coprocessor = midi_devs[midi_dev]->coproc;
if (coprocessor) {
coprocessor->close(coprocessor->devc, COPR_MIDI);
-
- if (coprocessor->owner)
- __MOD_DEC_USE_COUNT(coprocessor->owner);
+ module_put(coprocessor->owner);
}
devc->opened = 0;
devc->mode = 0;
diff --git a/sound/oss/sequencer.c b/sound/oss/sequencer.c
index 860e21734e9e..8a2f0055f1ac 100644
--- a/sound/oss/sequencer.c
+++ b/sound/oss/sequencer.c
@@ -1041,8 +1041,8 @@ int sequencer_open(int dev, struct file *file)
if (synth_devs[i]==NULL)
continue;
- if (synth_devs[i]->owner)
- __MOD_INC_USE_COUNT (synth_devs[i]->owner);
+ if (!try_module_get(synth_devs[i]->owner))
+ continue;
if ((tmp = synth_devs[i]->open(i, mode)) < 0)
{
@@ -1072,8 +1072,8 @@ int sequencer_open(int dev, struct file *file)
for (i = 0; i < max_mididev; i++)
if (!midi_opened[i] && midi_devs[i])
{
- if (midi_devs[i]->owner)
- __MOD_INC_USE_COUNT (midi_devs[i]->owner);
+ if (!try_module_get(midi_devs[i]->owner))
+ continue;
if ((retval = midi_devs[i]->open(i, mode,
sequencer_midi_input, sequencer_midi_output)) >= 0)
@@ -1084,9 +1084,8 @@ int sequencer_open(int dev, struct file *file)
}
if (seq_mode == SEQ_2) {
- if (tmr->owner)
- __MOD_INC_USE_COUNT (tmr->owner);
- tmr->open(tmr_no, seq_mode);
+ if (try_module_get(tmr->owner))
+ tmr->open(tmr_no, seq_mode);
}
init_waitqueue_head(&seq_sleeper);
@@ -1169,8 +1168,7 @@ void sequencer_release(int dev, struct file *file)
{
synth_devs[i]->close(i);
- if (synth_devs[i]->owner)
- __MOD_DEC_USE_COUNT (synth_devs[i]->owner);
+ module_put(synth_devs[i]->owner);
if (synth_devs[i]->midi_dev)
midi_opened[synth_devs[i]->midi_dev] = 0;
@@ -1181,15 +1179,13 @@ void sequencer_release(int dev, struct file *file)
{
if (midi_opened[i]) {
midi_devs[i]->close(i);
- if (midi_devs[i]->owner)
- __MOD_DEC_USE_COUNT (midi_devs[i]->owner);
+ module_put(midi_devs[i]->owner);
}
}
if (seq_mode == SEQ_2) {
tmr->close(tmr_no);
- if (tmr->owner)
- __MOD_DEC_USE_COUNT (tmr->owner);
+ module_put(tmr->owner);
}
if (obsolete_api_used)
diff --git a/sound/oss/soundcard.c b/sound/oss/soundcard.c
index 4d29d0ec11a5..89988a1b3814 100644
--- a/sound/oss/soundcard.c
+++ b/sound/oss/soundcard.c
@@ -222,9 +222,9 @@ static int sound_open(struct inode *inode, struct file *file)
}
if (dev && (dev >= num_mixers || mixer_devs[dev] == NULL))
return -ENXIO;
-
- if (mixer_devs[dev]->owner)
- __MOD_INC_USE_COUNT (mixer_devs[dev]->owner);
+
+ if (!try_module_get(mixer_devs[dev]->owner))
+ return -ENXIO;
break;
case SND_DEV_SEQ:
@@ -261,9 +261,7 @@ static int sound_release(struct inode *inode, struct file *file)
DEB(printk("sound_release(dev=%d)\n", dev));
switch (dev & 0x0f) {
case SND_DEV_CTL:
- dev >>= 4;
- if (mixer_devs[dev]->owner)
- __MOD_DEC_USE_COUNT (mixer_devs[dev]->owner);
+ module_put(mixer_devs[dev >> 4]->owner);
break;
case SND_DEV_SEQ:
diff --git a/sound/synth/emux/emux_seq.c b/sound/synth/emux/emux_seq.c
index 3175511d87f9..0dd6ef8c376c 100644
--- a/sound/synth/emux/emux_seq.c
+++ b/sound/synth/emux/emux_seq.c
@@ -61,12 +61,6 @@ static snd_midi_op_t emux_ops = {
/*
*/
-static inline void dec_mod_count(struct module *module)
-{
- if (module)
- __MOD_DEC_USE_COUNT(module);
-}
-
/*
* Initialise the EMUX Synth by creating a client and registering
* a series of ports.
@@ -283,7 +277,7 @@ snd_emux_inc_count(snd_emux_t *emu)
if (!try_inc_mod_count(emu->ops.owner))
goto __error;
if (!try_inc_mod_count(emu->card->module)) {
- dec_mod_count(emu->ops.owner);
+ module_put(emu->ops.owner);
__error:
emu->used--;
return 0;
@@ -298,11 +292,11 @@ snd_emux_inc_count(snd_emux_t *emu)
void
snd_emux_dec_count(snd_emux_t *emu)
{
- dec_mod_count(emu->ops.owner);
+ module_put(emu->ops.owner);
emu->used--;
if (emu->used <= 0)
snd_emux_terminate_all(emu);
- dec_mod_count(emu->card->module);
+ module_put(emu->card->module);
}
diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c
index 59eec43ef995..bc1d7f7b18de 100644
--- a/sound/usb/usbaudio.c
+++ b/sound/usb/usbaudio.c
@@ -2323,7 +2323,7 @@ static int usb_audio_probe(struct usb_interface *intf,
void *chip;
chip = snd_usb_audio_probe(interface_to_usbdev(intf), intf, id);
if (chip) {
- dev_set_drvdata(&intf->dev, chip);
+ usb_set_intfdata(intf, chip);
return 0;
} else
return -EIO;
@@ -2332,7 +2332,7 @@ static int usb_audio_probe(struct usb_interface *intf,
static void usb_audio_disconnect(struct usb_interface *intf)
{
snd_usb_audio_disconnect(interface_to_usbdev(intf),
- dev_get_drvdata(&intf->dev));
+ usb_get_intfdata(intf));
}
#endif