diff options
Diffstat (limited to 'arch')
249 files changed, 6976 insertions, 4421 deletions
diff --git a/arch/alpha/kernel/osf_sys.c b/arch/alpha/kernel/osf_sys.c index 01fe990d3e5..7fb14f42a12 100644 --- a/arch/alpha/kernel/osf_sys.c +++ b/arch/alpha/kernel/osf_sys.c @@ -960,7 +960,7 @@ osf_utimes(char __user *filename, struct timeval32 __user *tvs) return -EFAULT; } - return do_utimes(filename, tvs ? ktvs : NULL); + return do_utimes(AT_FDCWD, filename, tvs ? ktvs : NULL); } #define MAX_SELECT_SECONDS \ diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S index aaa47400eb9..db3389d8e02 100644 --- a/arch/arm/boot/compressed/head.S +++ b/arch/arm/boot/compressed/head.S @@ -334,7 +334,7 @@ __setup_mmu: sub r3, r4, #16384 @ Page directory size mov r1, #0x12 orr r1, r1, #3 << 10 add r2, r3, #16384 -1: cmp r1, r8 @ if virt > start of RAM +1: cmp r1, r9 @ if virt > start of RAM orrhs r1, r1, #0x0c @ set cacheable, bufferable cmp r1, r10 @ if virt > end of RAM bichs r1, r1, #0x0c @ clear cacheable, bufferable diff --git a/arch/arm/configs/bast_defconfig b/arch/arm/configs/bast_defconfig index 6886001b536..4a8564f386a 100644 --- a/arch/arm/configs/bast_defconfig +++ b/arch/arm/configs/bast_defconfig @@ -14,8 +14,7 @@ CONFIG_GENERIC_IOMAP=y # Code maturity level options # CONFIG_EXPERIMENTAL=y -# CONFIG_CLEAN_COMPILE is not set -CONFIG_BROKEN=y +CONFIG_CLEAN_COMPILE=y CONFIG_BROKEN_ON_SMP=y # @@ -360,7 +359,6 @@ CONFIG_BLK_DEV_IDE_BAST=y # # IEEE 1394 (FireWire) support # -# CONFIG_IEEE1394 is not set # # I2O device support @@ -781,7 +779,6 @@ CONFIG_SYSFS=y # CONFIG_DEVFS_FS is not set # CONFIG_DEVPTS_FS_XATTR is not set # CONFIG_TMPFS is not set -# CONFIG_HUGETLBFS is not set # CONFIG_HUGETLB_PAGE is not set CONFIG_RAMFS=y diff --git a/arch/arm/configs/collie_defconfig b/arch/arm/configs/collie_defconfig index 15468a0cf70..c9aa878e610 100644 --- a/arch/arm/configs/collie_defconfig +++ b/arch/arm/configs/collie_defconfig @@ -13,8 +13,7 @@ CONFIG_GENERIC_CALIBRATE_DELAY=y # Code maturity level options # CONFIG_EXPERIMENTAL=y -# CONFIG_CLEAN_COMPILE is not set -CONFIG_BROKEN=y +CONFIG_CLEAN_COMPILE=y CONFIG_BROKEN_ON_SMP=y CONFIG_LOCK_KERNEL=y CONFIG_INIT_ENV_ARG_LIMIT=32 @@ -308,9 +307,7 @@ CONFIG_MTD_CFI_I2=y # CONFIG_MTD_ROM is not set # CONFIG_MTD_ABSENT is not set CONFIG_MTD_OBSOLETE_CHIPS=y -# CONFIG_MTD_AMDSTD is not set CONFIG_MTD_SHARP=y -# CONFIG_MTD_JEDEC is not set # # Mapping drivers for chip access @@ -396,7 +393,6 @@ CONFIG_ATA_OVER_ETH=m # # IEEE 1394 (FireWire) support # -# CONFIG_IEEE1394 is not set # # I2O device support @@ -741,7 +737,6 @@ CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" CONFIG_PROC_FS=y CONFIG_SYSFS=y CONFIG_TMPFS=y -# CONFIG_HUGETLBFS is not set # CONFIG_HUGETLB_PAGE is not set CONFIG_RAMFS=y # CONFIG_RELAYFS_FS is not set diff --git a/arch/arm/configs/ep80219_defconfig b/arch/arm/configs/ep80219_defconfig index fbe312e757c..3c73b707c2f 100644 --- a/arch/arm/configs/ep80219_defconfig +++ b/arch/arm/configs/ep80219_defconfig @@ -522,6 +522,7 @@ CONFIG_E100=y # CONFIG_DL2K is not set CONFIG_E1000=y CONFIG_E1000_NAPI=y +# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set # CONFIG_NS83820 is not set # CONFIG_HAMACHI is not set # CONFIG_YELLOWFIN is not set diff --git a/arch/arm/configs/iq31244_defconfig b/arch/arm/configs/iq31244_defconfig index c07628ceaf0..32467160a6d 100644 --- a/arch/arm/configs/iq31244_defconfig +++ b/arch/arm/configs/iq31244_defconfig @@ -493,6 +493,7 @@ CONFIG_NETDEVICES=y # CONFIG_DL2K is not set CONFIG_E1000=y CONFIG_E1000_NAPI=y +# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set # CONFIG_NS83820 is not set # CONFIG_HAMACHI is not set # CONFIG_YELLOWFIN is not set diff --git a/arch/arm/configs/iq80321_defconfig b/arch/arm/configs/iq80321_defconfig index 18fa1615fdf..b000da753c4 100644 --- a/arch/arm/configs/iq80321_defconfig +++ b/arch/arm/configs/iq80321_defconfig @@ -415,6 +415,7 @@ CONFIG_NETDEVICES=y # CONFIG_DL2K is not set CONFIG_E1000=y CONFIG_E1000_NAPI=y +# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set # CONFIG_NS83820 is not set # CONFIG_HAMACHI is not set # CONFIG_YELLOWFIN is not set diff --git a/arch/arm/configs/iq80331_defconfig b/arch/arm/configs/iq80331_defconfig index f50035de1ff..46c79e1efe0 100644 --- a/arch/arm/configs/iq80331_defconfig +++ b/arch/arm/configs/iq80331_defconfig @@ -496,6 +496,7 @@ CONFIG_NETDEVICES=y # CONFIG_DL2K is not set CONFIG_E1000=y CONFIG_E1000_NAPI=y +# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set # CONFIG_NS83820 is not set # CONFIG_HAMACHI is not set # CONFIG_YELLOWFIN is not set diff --git a/arch/arm/configs/iq80332_defconfig b/arch/arm/configs/iq80332_defconfig index 18b3f372ed6..11959b705d8 100644 --- a/arch/arm/configs/iq80332_defconfig +++ b/arch/arm/configs/iq80332_defconfig @@ -496,6 +496,7 @@ CONFIG_NETDEVICES=y # CONFIG_DL2K is not set CONFIG_E1000=y CONFIG_E1000_NAPI=y +# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set # CONFIG_NS83820 is not set # CONFIG_HAMACHI is not set # CONFIG_YELLOWFIN is not set diff --git a/arch/arm/configs/s3c2410_defconfig b/arch/arm/configs/s3c2410_defconfig index 33f31080a98..1964ccd8a71 100644 --- a/arch/arm/configs/s3c2410_defconfig +++ b/arch/arm/configs/s3c2410_defconfig @@ -13,8 +13,7 @@ CONFIG_GENERIC_CALIBRATE_DELAY=y # Code maturity level options # CONFIG_EXPERIMENTAL=y -# CONFIG_CLEAN_COMPILE is not set -CONFIG_BROKEN=y +CONFIG_CLEAN_COMPILE=y CONFIG_BROKEN_ON_SMP=y CONFIG_INIT_ENV_ARG_LIMIT=32 @@ -473,7 +472,6 @@ CONFIG_BLK_DEV_IDE_BAST=y # # IEEE 1394 (FireWire) support # -# CONFIG_IEEE1394 is not set # # I2O device support @@ -896,7 +894,6 @@ CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" CONFIG_PROC_FS=y CONFIG_SYSFS=y # CONFIG_TMPFS is not set -# CONFIG_HUGETLBFS is not set # CONFIG_HUGETLB_PAGE is not set CONFIG_RAMFS=y # CONFIG_RELAYFS_FS is not set diff --git a/arch/arm/kernel/calls.S b/arch/arm/kernel/calls.S index 75e6f9a9471..d058e7c1256 100644 --- a/arch/arm/kernel/calls.S +++ b/arch/arm/kernel/calls.S @@ -7,337 +7,334 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * - * This file is included twice in entry-common.S + * This file is included thrice in entry-common.S */ -#ifndef NR_syscalls -#define NR_syscalls 328 -#else - -100: -/* 0 */ .long sys_restart_syscall - .long sys_exit - .long sys_fork_wrapper - .long sys_read - .long sys_write -/* 5 */ .long sys_open - .long sys_close - .long sys_ni_syscall /* was sys_waitpid */ - .long sys_creat - .long sys_link -/* 10 */ .long sys_unlink - .long sys_execve_wrapper - .long sys_chdir - .long OBSOLETE(sys_time) /* used by libc4 */ - .long sys_mknod -/* 15 */ .long sys_chmod - .long sys_lchown16 - .long sys_ni_syscall /* was sys_break */ - .long sys_ni_syscall /* was sys_stat */ - .long sys_lseek -/* 20 */ .long sys_getpid - .long sys_mount - .long OBSOLETE(sys_oldumount) /* used by libc4 */ - .long sys_setuid16 - .long sys_getuid16 -/* 25 */ .long OBSOLETE(sys_stime) - .long sys_ptrace - .long OBSOLETE(sys_alarm) /* used by libc4 */ - .long sys_ni_syscall /* was sys_fstat */ - .long sys_pause -/* 30 */ .long OBSOLETE(sys_utime) /* used by libc4 */ - .long sys_ni_syscall /* was sys_stty */ - .long sys_ni_syscall /* was sys_getty */ - .long sys_access - .long sys_nice -/* 35 */ .long sys_ni_syscall /* was sys_ftime */ - .long sys_sync - .long sys_kill - .long sys_rename - .long sys_mkdir -/* 40 */ .long sys_rmdir - .long sys_dup - .long sys_pipe - .long sys_times - .long sys_ni_syscall /* was sys_prof */ -/* 45 */ .long sys_brk - .long sys_setgid16 - .long sys_getgid16 - .long sys_ni_syscall /* was sys_signal */ - .long sys_geteuid16 -/* 50 */ .long sys_getegid16 - .long sys_acct - .long sys_umount - .long sys_ni_syscall /* was sys_lock */ - .long sys_ioctl -/* 55 */ .long sys_fcntl - .long sys_ni_syscall /* was sys_mpx */ - .long sys_setpgid - .long sys_ni_syscall /* was sys_ulimit */ - .long sys_ni_syscall /* was sys_olduname */ -/* 60 */ .long sys_umask - .long sys_chroot - .long sys_ustat - .long sys_dup2 - .long sys_getppid -/* 65 */ .long sys_getpgrp - .long sys_setsid - .long sys_sigaction - .long sys_ni_syscall /* was sys_sgetmask */ - .long sys_ni_syscall /* was sys_ssetmask */ -/* 70 */ .long sys_setreuid16 - .long sys_setregid16 - .long sys_sigsuspend_wrapper - .long sys_sigpending - .long sys_sethostname -/* 75 */ .long sys_setrlimit - .long OBSOLETE(sys_old_getrlimit) /* used by libc4 */ - .long sys_getrusage - .long sys_gettimeofday - .long sys_settimeofday -/* 80 */ .long sys_getgroups16 - .long sys_setgroups16 - .long OBSOLETE(old_select) /* used by libc4 */ - .long sys_symlink - .long sys_ni_syscall /* was sys_lstat */ -/* 85 */ .long sys_readlink - .long sys_uselib - .long sys_swapon - .long sys_reboot - .long OBSOLETE(old_readdir) /* used by libc4 */ -/* 90 */ .long OBSOLETE(old_mmap) /* used by libc4 */ - .long sys_munmap - .long sys_truncate - .long sys_ftruncate - .long sys_fchmod -/* 95 */ .long sys_fchown16 - .long sys_getpriority - .long sys_setpriority - .long sys_ni_syscall /* was sys_profil */ - .long sys_statfs -/* 100 */ .long sys_fstatfs - .long sys_ni_syscall - .long OBSOLETE(sys_socketcall) - .long sys_syslog - .long sys_setitimer -/* 105 */ .long sys_getitimer - .long sys_newstat - .long sys_newlstat - .long sys_newfstat - .long sys_ni_syscall /* was sys_uname */ -/* 110 */ .long sys_ni_syscall /* was sys_iopl */ - .long sys_vhangup - .long sys_ni_syscall - .long OBSOLETE(sys_syscall) /* call a syscall */ - .long sys_wait4 -/* 115 */ .long sys_swapoff - .long sys_sysinfo - .long OBSOLETE(ABI(sys_ipc, sys_oabi_ipc)) - .long sys_fsync - .long sys_sigreturn_wrapper -/* 120 */ .long sys_clone_wrapper - .long sys_setdomainname - .long sys_newuname - .long sys_ni_syscall - .long sys_adjtimex -/* 125 */ .long sys_mprotect - .long sys_sigprocmask - .long sys_ni_syscall /* was sys_create_module */ - .long sys_init_module - .long sys_delete_module -/* 130 */ .long sys_ni_syscall /* was sys_get_kernel_syms */ - .long sys_quotactl - .long sys_getpgid - .long sys_fchdir - .long sys_bdflush -/* 135 */ .long sys_sysfs - .long sys_personality - .long sys_ni_syscall /* .long _sys_afs_syscall */ - .long sys_setfsuid16 - .long sys_setfsgid16 -/* 140 */ .long sys_llseek - .long sys_getdents - .long sys_select - .long sys_flock - .long sys_msync -/* 145 */ .long sys_readv - .long sys_writev - .long sys_getsid - .long sys_fdatasync - .long sys_sysctl -/* 150 */ .long sys_mlock - .long sys_munlock - .long sys_mlockall - .long sys_munlockall - .long sys_sched_setparam -/* 155 */ .long sys_sched_getparam - .long sys_sched_setscheduler - .long sys_sched_getscheduler - .long sys_sched_yield - .long sys_sched_get_priority_max -/* 160 */ .long sys_sched_get_priority_min - .long sys_sched_rr_get_interval - .long sys_nanosleep - .long sys_arm_mremap - .long sys_setresuid16 -/* 165 */ .long sys_getresuid16 - .long sys_ni_syscall - .long sys_ni_syscall /* was sys_query_module */ - .long sys_poll - .long sys_nfsservctl -/* 170 */ .long sys_setresgid16 - .long sys_getresgid16 - .long sys_prctl - .long sys_rt_sigreturn_wrapper - .long sys_rt_sigaction -/* 175 */ .long sys_rt_sigprocmask - .long sys_rt_sigpending - .long sys_rt_sigtimedwait - .long sys_rt_sigqueueinfo - .long sys_rt_sigsuspend_wrapper -/* 180 */ .long ABI(sys_pread64, sys_oabi_pread64) - .long ABI(sys_pwrite64, sys_oabi_pwrite64) - .long sys_chown16 - .long sys_getcwd - .long sys_capget -/* 185 */ .long sys_capset - .long sys_sigaltstack_wrapper - .long sys_sendfile - .long sys_ni_syscall - .long sys_ni_syscall -/* 190 */ .long sys_vfork_wrapper - .long sys_getrlimit - .long sys_mmap2 - .long ABI(sys_truncate64, sys_oabi_truncate64) - .long ABI(sys_ftruncate64, sys_oabi_ftruncate64) -/* 195 */ .long ABI(sys_stat64, sys_oabi_stat64) - .long ABI(sys_lstat64, sys_oabi_lstat64) - .long ABI(sys_fstat64, sys_oabi_fstat64) - .long sys_lchown - .long sys_getuid -/* 200 */ .long sys_getgid - .long sys_geteuid - .long sys_getegid - .long sys_setreuid - .long sys_setregid -/* 205 */ .long sys_getgroups - .long sys_setgroups - .long sys_fchown - .long sys_setresuid - .long sys_getresuid -/* 210 */ .long sys_setresgid - .long sys_getresgid - .long sys_chown - .long sys_setuid - .long sys_setgid -/* 215 */ .long sys_setfsuid - .long sys_setfsgid - .long sys_getdents64 - .long sys_pivot_root - .long sys_mincore -/* 220 */ .long sys_madvise - .long ABI(sys_fcntl64, sys_oabi_fcntl64) - .long sys_ni_syscall /* TUX */ - .long sys_ni_syscall - .long sys_gettid -/* 225 */ .long ABI(sys_readahead, sys_oabi_readahead) - .long sys_setxattr - .long sys_lsetxattr - .long sys_fsetxattr - .long sys_getxattr -/* 230 */ .long sys_lgetxattr - .long sys_fgetxattr - .long sys_listxattr - .long sys_llistxattr - .long sys_flistxattr -/* 235 */ .long sys_removexattr - .long sys_lremovexattr - .long sys_fremovexattr - .long sys_tkill - .long sys_sendfile64 -/* 240 */ .long sys_futex - .long sys_sched_setaffinity - .long sys_sched_getaffinity - .long sys_io_setup - .long sys_io_destroy -/* 245 */ .long sys_io_getevents - .long sys_io_submit - .long sys_io_cancel - .long sys_exit_group - .long sys_lookup_dcookie -/* 250 */ .long sys_epoll_create - .long ABI(sys_epoll_ctl, sys_oabi_epoll_ctl) - .long ABI(sys_epoll_wait, sys_oabi_epoll_wait) - .long sys_remap_file_pages - .long sys_ni_syscall /* sys_set_thread_area */ -/* 255 */ .long sys_ni_syscall /* sys_get_thread_area */ - .long sys_set_tid_address - .long sys_timer_create - .long sys_timer_settime - .long sys_timer_gettime -/* 260 */ .long sys_timer_getoverrun - .long sys_timer_delete - .long sys_clock_settime - .long sys_clock_gettime - .long sys_clock_getres -/* 265 */ .long sys_clock_nanosleep - .long sys_statfs64_wrapper - .long sys_fstatfs64_wrapper - .long sys_tgkill - .long sys_utimes -/* 270 */ .long sys_arm_fadvise64_64 - .long sys_pciconfig_iobase - .long sys_pciconfig_read - .long sys_pciconfig_write - .long sys_mq_open -/* 275 */ .long sys_mq_unlink - .long sys_mq_timedsend - .long sys_mq_timedreceive - .long sys_mq_notify - .long sys_mq_getsetattr -/* 280 */ .long sys_waitid - .long sys_socket - .long sys_bind - .long sys_connect - .long sys_listen -/* 285 */ .long sys_accept - .long sys_getsockname - .long sys_getpeername - .long sys_socketpair - .long sys_send -/* 290 */ .long sys_sendto - .long sys_recv - .long sys_recvfrom - .long sys_shutdown - .long sys_setsockopt -/* 295 */ .long sys_getsockopt - .long sys_sendmsg - .long sys_recvmsg - .long ABI(sys_semop, sys_oabi_semop) - .long sys_semget -/* 300 */ .long sys_semctl - .long sys_msgsnd - .long sys_msgrcv - .long sys_msgget - .long sys_msgctl -/* 305 */ .long sys_shmat - .long sys_shmdt - .long sys_shmget - .long sys_shmctl - .long sys_add_key -/* 310 */ .long sys_request_key - .long sys_keyctl - .long ABI(sys_semtimedop, sys_oabi_semtimedop) -/* vserver */ .long sys_ni_syscall - .long sys_ioprio_set -/* 315 */ .long sys_ioprio_get - .long sys_inotify_init - .long sys_inotify_add_watch - .long sys_inotify_rm_watch - .long sys_mbind -/* 320 */ .long sys_get_mempolicy - .long sys_set_mempolicy - - .rept NR_syscalls - (. - 100b) / 4 - .long sys_ni_syscall - .endr +/* 0 */ CALL(sys_restart_syscall) + CALL(sys_exit) + CALL(sys_fork_wrapper) + CALL(sys_read) + CALL(sys_write) +/* 5 */ CALL(sys_open) + CALL(sys_close) + CALL(sys_ni_syscall) /* was sys_waitpid */ + CALL(sys_creat) + CALL(sys_link) +/* 10 */ CALL(sys_unlink) + CALL(sys_execve_wrapper) + CALL(sys_chdir) + CALL(OBSOLETE(sys_time)) /* used by libc4 */ + CALL(sys_mknod) +/* 15 */ CALL(sys_chmod) + CALL(sys_lchown16) + CALL(sys_ni_syscall) /* was sys_break */ + CALL(sys_ni_syscall) /* was sys_stat */ + CALL(sys_lseek) +/* 20 */ CALL(sys_getpid) + CALL(sys_mount) + CALL(OBSOLETE(sys_oldumount)) /* used by libc4 */ + CALL(sys_setuid16) + CALL(sys_getuid16) +/* 25 */ CALL(OBSOLETE(sys_stime)) + CALL(sys_ptrace) + CALL(OBSOLETE(sys_alarm)) /* used by libc4 */ + CALL(sys_ni_syscall) /* was sys_fstat */ + CALL(sys_pause) +/* 30 */ CALL(OBSOLETE(sys_utime)) /* used by libc4 */ + CALL(sys_ni_syscall) /* was sys_stty */ + CALL(sys_ni_syscall) /* was sys_getty */ + CALL(sys_access) + CALL(sys_nice) +/* 35 */ CALL(sys_ni_syscall) /* was sys_ftime */ + CALL(sys_sync) + CALL(sys_kill) + CALL(sys_rename) + CALL(sys_mkdir) +/* 40 */ CALL(sys_rmdir) + CALL(sys_dup) + CALL(sys_pipe) + CALL(sys_times) + CALL(sys_ni_syscall) /* was sys_prof */ +/* 45 */ CALL(sys_brk) + CALL(sys_setgid16) + CALL(sys_getgid16) + CALL(sys_ni_syscall) /* was sys_signal */ + CALL(sys_geteuid16) +/* 50 */ CALL(sys_getegid16) + CALL(sys_acct) + CALL(sys_umount) + CALL(sys_ni_syscall) /* was sys_lock */ + CALL(sys_ioctl) +/* 55 */ CALL(sys_fcntl) + CALL(sys_ni_syscall) /* was sys_mpx */ + CALL(sys_setpgid) + CALL(sys_ni_syscall) /* was sys_ulimit */ + CALL(sys_ni_syscall) /* was sys_olduname */ +/* 60 */ CALL(sys_umask) + CALL(sys_chroot) + CALL(sys_ustat) + CALL(sys_dup2) + CALL(sys_getppid) +/* 65 */ CALL(sys_getpgrp) + CALL(sys_setsid) + CALL(sys_sigaction) + CALL(sys_ni_syscall) /* was sys_sgetmask */ + CALL(sys_ni_syscall) /* was sys_ssetmask */ +/* 70 */ CALL(sys_setreuid16) + CALL(sys_setregid16) + CALL(sys_sigsuspend_wrapper) + CALL(sys_sigpending) + CALL(sys_sethostname) +/* 75 */ CALL(sys_setrlimit) + CALL(OBSOLETE(sys_old_getrlimit)) /* used by libc4 */ + CALL(sys_getrusage) + CALL(sys_gettimeofday) + CALL(sys_settimeofday) +/* 80 */ CALL(sys_getgroups16) + CALL(sys_setgroups16) + CALL(OBSOLETE(old_select)) /* used by libc4 */ + CALL(sys_symlink) + CALL(sys_ni_syscall) /* was sys_lstat */ +/* 85 */ CALL(sys_readlink) + CALL(sys_uselib) + CALL(sys_swapon) + CALL(sys_reboot) + CALL(OBSOLETE(old_readdir)) /* used by libc4 */ +/* 90 */ CALL(OBSOLETE(old_mmap)) /* used by libc4 */ + CALL(sys_munmap) + CALL(sys_truncate) + CALL(sys_ftruncate) + CALL(sys_fchmod) +/* 95 */ CALL(sys_fchown16) + CALL(sys_getpriority) + CALL(sys_setpriority) + CALL(sys_ni_syscall) /* was sys_profil */ + CALL(sys_statfs) +/* 100 */ CALL(sys_fstatfs) + CALL(sys_ni_syscall) + CALL(OBSOLETE(sys_socketcall)) + CALL(sys_syslog) + CALL(sys_setitimer) +/* 105 */ CALL(sys_getitimer) + CALL(sys_newstat) + CALL(sys_newlstat) + CALL(sys_newfstat) + CALL(sys_ni_syscall) /* was sys_uname */ +/* 110 */ CALL(sys_ni_syscall) /* was sys_iopl */ + CALL(sys_vhangup) + CALL(sys_ni_syscall) + CALL(OBSOLETE(sys_syscall)) /* call a syscall */ + CALL(sys_wait4) +/* 115 */ CALL(sys_swapoff) + CALL(sys_sysinfo) + CALL(OBSOLETE(ABI(sys_ipc, sys_oabi_ipc))) + CALL(sys_fsync) + CALL(sys_sigreturn_wrapper) +/* 120 */ CALL(sys_clone_wrapper) + CALL(sys_setdomainname) + CALL(sys_newuname) + CALL(sys_ni_syscall) + CALL(sys_adjtimex) +/* 125 */ CALL(sys_mprotect) + CALL(sys_sigprocmask) + CALL(sys_ni_syscall) /* was sys_create_module */ + CALL(sys_init_module) + CALL(sys_delete_module) +/* 130 */ CALL(sys_ni_syscall) /* was sys_get_kernel_syms */ + CALL(sys_quotactl) + CALL(sys_getpgid) + CALL(sys_fchdir) + CALL(sys_bdflush) +/* 135 */ CALL(sys_sysfs) + CALL(sys_personality) + CALL(sys_ni_syscall) /* CALL(_sys_afs_syscall) */ + CALL(sys_setfsuid16) + CALL(sys_setfsgid16) +/* 140 */ CALL(sys_llseek) + CALL(sys_getdents) + CALL(sys_select) + CALL(sys_flock) + CALL(sys_msync) +/* 145 */ CALL(sys_readv) + CALL(sys_writev) + CALL(sys_getsid) + CALL(sys_fdatasync) + CALL(sys_sysctl) +/* 150 */ CALL(sys_mlock) + CALL(sys_munlock) + CALL(sys_mlockall) + CALL(sys_munlockall) + CALL(sys_sched_setparam) +/* 155 */ CALL(sys_sched_getparam) + CALL(sys_sched_setscheduler) + CALL(sys_sched_getscheduler) + CALL(sys_sched_yield) + CALL(sys_sched_get_priority_max) +/* 160 */ CALL(sys_sched_get_priority_min) + CALL(sys_sched_rr_get_interval) + CALL(sys_nanosleep) + CALL(sys_arm_mremap) + CALL(sys_setresuid16) +/* 165 */ CALL(sys_getresuid16) + CALL(sys_ni_syscall) + CALL(sys_ni_syscall) /* was sys_query_module */ + CALL(sys_poll) + CALL(sys_nfsservctl) +/* 170 */ CALL(sys_setresgid16) + CALL(sys_getresgid16) + CALL(sys_prctl) + CALL(sys_rt_sigreturn_wrapper) + CALL(sys_rt_sigaction) +/* 175 */ CALL(sys_rt_sigprocmask) + CALL(sys_rt_sigpending) + CALL(sys_rt_sigtimedwait) + CALL(sys_rt_sigqueueinfo) + CALL(sys_rt_sigsuspend_wrapper) +/* 180 */ CALL(ABI(sys_pread64, sys_oabi_pread64)) + CALL(ABI(sys_pwrite64, sys_oabi_pwrite64)) + CALL(sys_chown16) + CALL(sys_getcwd) + CALL(sys_capget) +/* 185 */ CALL(sys_capset) + CALL(sys_sigaltstack_wrapper) + CALL(sys_sendfile) + CALL(sys_ni_syscall) + CALL(sys_ni_syscall) +/* 190 */ CALL(sys_vfork_wrapper) + CALL(sys_getrlimit) + CALL(sys_mmap2) + CALL(ABI(sys_truncate64, sys_oabi_truncate64)) + CALL(ABI(sys_ftruncate64, sys_oabi_ftruncate64)) +/* 195 */ CALL(ABI(sys_stat64, sys_oabi_stat64)) + CALL(ABI(sys_lstat64, sys_oabi_lstat64)) + CALL(ABI(sys_fstat64, sys_oabi_fstat64)) + CALL(sys_lchown) + CALL(sys_getuid) +/* 200 */ CALL(sys_getgid) + CALL(sys_geteuid) + CALL(sys_getegid) + CALL(sys_setreuid) + CALL(sys_setregid) +/* 205 */ CALL(sys_getgroups) + CALL(sys_setgroups) + CALL(sys_fchown) + CALL(sys_setresuid) + CALL(sys_getresuid) +/* 210 */ CALL(sys_setresgid) + CALL(sys_getresgid) + CALL(sys_chown) + CALL(sys_setuid) + CALL(sys_setgid) +/* 215 */ CALL(sys_setfsuid) + CALL(sys_setfsgid) + CALL(sys_getdents64) + CALL(sys_pivot_root) + CALL(sys_mincore) +/* 220 */ CALL(sys_madvise) + CALL(ABI(sys_fcntl64, sys_oabi_fcntl64)) + CALL(sys_ni_syscall) /* TUX */ + CALL(sys_ni_syscall) + CALL(sys_gettid) +/* 225 */ CALL(ABI(sys_readahead, sys_oabi_readahead)) + CALL(sys_setxattr) + CALL(sys_lsetxattr) + CALL(sys_fsetxattr) + CALL(sys_getxattr) +/* 230 */ CALL(sys_lgetxattr) + CALL(sys_fgetxattr) + CALL(sys_listxattr) + CALL(sys_llistxattr) + CALL(sys_flistxattr) +/* 235 */ CALL(sys_removexattr) + CALL(sys_lremovexattr) + CALL(sys_fremovexattr) + CALL(sys_tkill) + CALL(sys_sendfile64) +/* 240 */ CALL(sys_futex) + CALL(sys_sched_setaffinity) + CALL(sys_sched_getaffinity) + CALL(sys_io_setup) + CALL(sys_io_destroy) +/* 245 */ CALL(sys_io_getevents) + CALL(sys_io_submit) + CALL(sys_io_cancel) + CALL(sys_exit_group) + CALL(sys_lookup_dcookie) +/* 250 */ CALL(sys_epoll_create) + CALL(ABI(sys_epoll_ctl, sys_oabi_epoll_ctl)) + CALL(ABI(sys_epoll_wait, sys_oabi_epoll_wait)) + CALL(sys_remap_file_pages) + CALL(sys_ni_syscall) /* sys_set_thread_area */ +/* 255 */ CALL(sys_ni_syscall) /* sys_get_thread_area */ + CALL(sys_set_tid_address) + CALL(sys_timer_create) + CALL(sys_timer_settime) + CALL(sys_timer_gettime) +/* 260 */ CALL(sys_timer_getoverrun) + CALL(sys_timer_delete) + CALL(sys_clock_settime) + CALL(sys_clock_gettime) + CALL(sys_clock_getres) +/* 265 */ CALL(sys_clock_nanosleep) + CALL(sys_statfs64_wrapper) + CALL(sys_fstatfs64_wrapper) + CALL(sys_tgkill) + CALL(sys_utimes) +/* 270 */ CALL(sys_arm_fadvise64_64) + CALL(sys_pciconfig_iobase) + CALL(sys_pciconfig_read) + CALL(sys_pciconfig_write) + CALL(sys_mq_open) +/* 275 */ CALL(sys_mq_unlink) + CALL(sys_mq_timedsend) + CALL(sys_mq_timedreceive) + CALL(sys_mq_notify) + CALL(sys_mq_getsetattr) +/* 280 */ CALL(sys_waitid) + CALL(sys_socket) + CALL(sys_bind) + CALL(sys_connect) + CALL(sys_listen) +/* 285 */ CALL(sys_accept) + CALL(sys_getsockname) + CALL(sys_getpeername) + CALL(sys_socketpair) + CALL(sys_send) +/* 290 */ CALL(sys_sendto) + CALL(sys_recv) + CALL(sys_recvfrom) + CALL(sys_shutdown) + CALL(sys_setsockopt) +/* 295 */ CALL(sys_getsockopt) + CALL(sys_sendmsg) + CALL(sys_recvmsg) + CALL(ABI(sys_semop, sys_oabi_semop)) + CALL(sys_semget) +/* 300 */ CALL(sys_semctl) + CALL(sys_msgsnd) + CALL(sys_msgrcv) + CALL(sys_msgget) + CALL(sys_msgctl) +/* 305 */ CALL(sys_shmat) + CALL(sys_shmdt) + CALL(sys_shmget) + CALL(sys_shmctl) + CALL(sys_add_key) +/* 310 */ CALL(sys_request_key) + CALL(sys_keyctl) + CALL(ABI(sys_semtimedop, sys_oabi_semtimedop)) +/* vserver */ CALL(sys_ni_syscall) + CALL(sys_ioprio_set) +/* 315 */ CALL(sys_ioprio_get) + CALL(sys_inotify_init) + CALL(sys_inotify_add_watch) + CALL(sys_inotify_rm_watch) + CALL(sys_mbind) +/* 320 */ CALL(sys_get_mempolicy) + CALL(sys_set_mempolicy) +#ifndef syscalls_counted +.equ syscalls_padding, ((NR_syscalls + 3) & ~3) - NR_syscalls +#define syscalls_counted #endif +.rept syscalls_padding + CALL(sys_ni_syscall) +.endr diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S index 874e6bb7940..d401d908c46 100644 --- a/arch/arm/kernel/entry-armv.S +++ b/arch/arm/kernel/entry-armv.S @@ -735,8 +735,11 @@ __kuser_cmpxchg: @ 0xffff0fc0 * The kernel itself must perform the operation. * A special ghost syscall is used for that (see traps.c). */ + stmfd sp!, {r7, lr} + mov r7, #0xff00 @ 0xfff0 into r7 for EABI + orr r7, r7, #0xf0 swi #0x9ffff0 - mov pc, lr + ldmfd sp!, {r7, pc} #elif __LINUX_ARM_ARCH__ < 6 diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S index 2b92ce85f97..dbcb11a31f7 100644 --- a/arch/arm/kernel/entry-common.S +++ b/arch/arm/kernel/entry-common.S @@ -87,7 +87,11 @@ ENTRY(ret_from_fork) b ret_slow_syscall + .equ NR_syscalls,0 +#define CALL(x) .equ NR_syscalls,NR_syscalls+1 #include "calls.S" +#undef CALL +#define CALL(x) .long x /*============================================================================= * SWI handler diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c index 765922bcf9e..a0cd0a90a10 100644 --- a/arch/arm/kernel/signal.c +++ b/arch/arm/kernel/signal.c @@ -30,15 +30,21 @@ #define SWI_SYS_RT_SIGRETURN (0xef000000|(__NR_rt_sigreturn)) /* + * With EABI, the syscall number has to be loaded into r7. + */ +#define MOV_R7_NR_SIGRETURN (0xe3a07000 | (__NR_sigreturn - __NR_SYSCALL_BASE)) +#define MOV_R7_NR_RT_SIGRETURN (0xe3a07000 | (__NR_rt_sigreturn - __NR_SYSCALL_BASE)) + +/* * For Thumb syscalls, we pass the syscall number via r7. We therefore * need two 16-bit instructions. */ #define SWI_THUMB_SIGRETURN (0xdf00 << 16 | 0x2700 | (__NR_sigreturn - __NR_SYSCALL_BASE)) #define SWI_THUMB_RT_SIGRETURN (0xdf00 << 16 | 0x2700 | (__NR_rt_sigreturn - __NR_SYSCALL_BASE)) -const unsigned long sigreturn_codes[4] = { - SWI_SYS_SIGRETURN, SWI_THUMB_SIGRETURN, - SWI_SYS_RT_SIGRETURN, SWI_THUMB_RT_SIGRETURN +const unsigned long sigreturn_codes[7] = { + MOV_R7_NR_SIGRETURN, SWI_SYS_SIGRETURN, SWI_THUMB_SIGRETURN, + MOV_R7_NR_RT_SIGRETURN, SWI_SYS_RT_SIGRETURN, SWI_THUMB_RT_SIGRETURN, }; static int do_signal(sigset_t *oldset, struct pt_regs * regs, int syscall); @@ -189,7 +195,7 @@ struct aux_sigframe { struct sigframe { struct sigcontext sc; unsigned long extramask[_NSIG_WORDS-1]; - unsigned long retcode; + unsigned long retcode[2]; struct aux_sigframe aux __attribute__((aligned(8))); }; @@ -198,7 +204,7 @@ struct rt_sigframe { void __user *puc; struct siginfo info; struct ucontext uc; - unsigned long retcode; + unsigned long retcode[2]; struct aux_sigframe aux __attribute__((aligned(8))); }; @@ -436,12 +442,13 @@ setup_return(struct pt_regs *regs, struct k_sigaction *ka, if (ka->sa.sa_flags & SA_RESTORER) { retcode = (unsigned long)ka->sa.sa_restorer; } else { - unsigned int idx = thumb; + unsigned int idx = thumb << 1; if (ka->sa.sa_flags & SA_SIGINFO) - idx += 2; + idx += 3; - if (__put_user(sigreturn_codes[idx], rc)) + if (__put_user(sigreturn_codes[idx], rc) || + __put_user(sigreturn_codes[idx+1], rc+1)) return 1; if (cpsr & MODE32_BIT) { @@ -456,7 +463,7 @@ setup_return(struct pt_regs *regs, struct k_sigaction *ka, * the return code written onto the stack. */ flush_icache_range((unsigned long)rc, - (unsigned long)(rc + 1)); + (unsigned long)(rc + 2)); retcode = ((unsigned long)rc) + thumb; } @@ -488,7 +495,7 @@ setup_frame(int usig, struct k_sigaction *ka, sigset_t *set, struct pt_regs *reg } if (err == 0) - err = setup_return(regs, ka, &frame->retcode, frame, usig); + err = setup_return(regs, ka, frame->retcode, frame, usig); return err; } @@ -522,7 +529,7 @@ setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info, err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); if (err == 0) - err = setup_return(regs, ka, &frame->retcode, frame, usig); + err = setup_return(regs, ka, frame->retcode, frame, usig); if (err == 0) { /* diff --git a/arch/arm/kernel/signal.h b/arch/arm/kernel/signal.h index 91d26faca62..9991049c522 100644 --- a/arch/arm/kernel/signal.h +++ b/arch/arm/kernel/signal.h @@ -9,4 +9,4 @@ */ #define KERN_SIGRETURN_CODE 0xffff0500 -extern const unsigned long sigreturn_codes[4]; +extern const unsigned long sigreturn_codes[7]; diff --git a/arch/arm/mach-integrator/integrator_cp.c b/arch/arm/mach-integrator/integrator_cp.c index 31820170f30..a0724f2b24c 100644 --- a/arch/arm/mach-integrator/integrator_cp.c +++ b/arch/arm/mach-integrator/integrator_cp.c @@ -469,7 +469,9 @@ static void cp_clcd_enable(struct clcd_fb *fb) if (fb->fb.var.bits_per_pixel <= 8) val = CM_CTRL_LCDMUXSEL_VGA_8421BPP; else if (fb->fb.var.bits_per_pixel <= 16) - val = CM_CTRL_LCDMUXSEL_VGA_16BPP; + val = CM_CTRL_LCDMUXSEL_VGA_16BPP + | CM_CTRL_LCDEN0 | CM_CTRL_LCDEN1 + | CM_CTRL_STATIC1 | CM_CTRL_STATIC2; else val = 0; /* no idea for this, don't trust the docs */ diff --git a/arch/arm/mach-ixp4xx/common.c b/arch/arm/mach-ixp4xx/common.c index 6b393691d0e..4bdc9d4526c 100644 --- a/arch/arm/mach-ixp4xx/common.c +++ b/arch/arm/mach-ixp4xx/common.c @@ -333,6 +333,7 @@ static struct platform_device *ixp46x_devices[] __initdata = { }; unsigned long ixp4xx_exp_bus_size; +EXPORT_SYMBOL(ixp4xx_exp_bus_size); void __init ixp4xx_sys_init(void) { @@ -352,7 +353,7 @@ void __init ixp4xx_sys_init(void) } } - printk("IXP4xx: Using %uMiB expansion bus window size\n", + printk("IXP4xx: Using %luMiB expansion bus window size\n", ixp4xx_exp_bus_size >> 20); } diff --git a/arch/arm/mach-omap1/clock.c b/arch/arm/mach-omap1/clock.c index 9d862f86bba..75110ba1042 100644 --- a/arch/arm/mach-omap1/clock.c +++ b/arch/arm/mach-omap1/clock.c @@ -50,10 +50,10 @@ static int omap1_clk_enable_dsp_domain(struct clk *clk) { int retval; - retval = omap1_clk_use(&api_ck.clk); + retval = omap1_clk_enable(&api_ck.clk); if (!retval) { - retval = omap1_clk_enable(clk); - omap1_clk_unuse(&api_ck.clk); + retval = omap1_clk_enable_generic(clk); + omap1_clk_disable(&api_ck.clk); } return retval; @@ -61,9 +61,9 @@ static int omap1_clk_enable_dsp_domain(struct clk *clk) static void omap1_clk_disable_dsp_domain(struct clk *clk) { - if (omap1_clk_use(&api_ck.clk) == 0) { - omap1_clk_disable(clk); - omap1_clk_unuse(&api_ck.clk); + if (omap1_clk_enable(&api_ck.clk) == 0) { + omap1_clk_disable_generic(clk); + omap1_clk_disable(&api_ck.clk); } } @@ -72,7 +72,7 @@ static int omap1_clk_enable_uart_functional(struct clk *clk) int ret; struct uart_clk *uclk; - ret = omap1_clk_enable(clk); + ret = omap1_clk_enable_generic(clk); if (ret == 0) { /* Set smart idle acknowledgement mode */ uclk = (struct uart_clk *)clk; @@ -91,7 +91,7 @@ static void omap1_clk_disable_uart_functional(struct clk *clk) uclk = (struct uart_clk *)clk; omap_writeb((omap_readb(uclk->sysc_addr) & ~0x18), uclk->sysc_addr); - omap1_clk_disable(clk); + omap1_clk_disable_generic(clk); } static void omap1_clk_allow_idle(struct clk *clk) @@ -230,9 +230,9 @@ static void omap1_ckctl_recalc_dsp_domain(struct clk * clk) * Note that DSP_CKCTL virt addr = phys addr, so * we must use __raw_readw() instead of omap_readw(). */ - omap1_clk_use(&api_ck.clk); + omap1_clk_enable(&api_ck.clk); dsor = 1 << (3 & (__raw_readw(DSP_CKCTL) >> clk->rate_offset)); - omap1_clk_unuse(&api_ck.clk); + omap1_clk_disable(&api_ck.clk); if (unlikely(clk->rate == clk->parent->rate / dsor)) return; /* No change, quick exit */ @@ -412,12 +412,12 @@ static void omap1_init_ext_clk(struct clk * clk) clk-> rate = 96000000 / dsor; } -static int omap1_clk_use(struct clk *clk) +static int omap1_clk_enable(struct clk *clk) { int ret = 0; if (clk->usecount++ == 0) { if (likely(clk->parent)) { - ret = omap1_clk_use(clk->parent); + ret = omap1_clk_enable(clk->parent); if (unlikely(ret != 0)) { clk->usecount--; @@ -432,7 +432,7 @@ static int omap1_clk_use(struct clk *clk) ret = clk->enable(clk); if (unlikely(ret != 0) && clk->parent) { - omap1_clk_unuse(clk->parent); + omap1_clk_disable(clk->parent); clk->usecount--; } } @@ -440,12 +440,12 @@ static int omap1_clk_use(struct clk *clk) return ret; } -static void omap1_clk_unuse(struct clk *clk) +static void omap1_clk_disable(struct clk *clk) { if (clk->usecount > 0 && !(--clk->usecount)) { clk->disable(clk); if (likely(clk->parent)) { - omap1_clk_unuse(clk->parent); + omap1_clk_disable(clk->parent); if (clk->flags & CLOCK_NO_IDLE_PARENT) if (!cpu_is_omap24xx()) omap1_clk_allow_idle(clk->parent); @@ -453,7 +453,7 @@ static void omap1_clk_unuse(struct clk *clk) } } -static int omap1_clk_enable(struct clk *clk) +static int omap1_clk_enable_generic(struct clk *clk) { __u16 regval16; __u32 regval32; @@ -492,7 +492,7 @@ static int omap1_clk_enable(struct clk *clk) return 0; } -static void omap1_clk_disable(struct clk *clk) +static void omap1_clk_disable_generic(struct clk *clk) { __u16 regval16; __u32 regval32; @@ -654,8 +654,8 @@ late_initcall(omap1_late_clk_reset); #endif static struct clk_functions omap1_clk_functions = { - .clk_use = omap1_clk_use, - .clk_unuse = omap1_clk_unuse, + .clk_enable = omap1_clk_enable, + .clk_disable = omap1_clk_disable, .clk_round_rate = omap1_clk_round_rate, .clk_set_rate = omap1_clk_set_rate, }; @@ -780,9 +780,9 @@ int __init omap1_clk_init(void) * Only enable those clocks we will need, let the drivers * enable other clocks as necessary */ - clk_use(&armper_ck.clk); - clk_use(&armxor_ck.clk); - clk_use(&armtim_ck.clk); /* This should be done by timer code */ + clk_enable(&armper_ck.clk); + clk_enable(&armxor_ck.clk); + clk_enable(&armtim_ck.clk); /* This should be done by timer code */ if (cpu_is_omap1510()) clk_enable(&arm_gpio_ck); diff --git a/arch/arm/mach-omap1/clock.h b/arch/arm/mach-omap1/clock.h index f3bdfb50e01..4f18d1b9444 100644 --- a/arch/arm/mach-omap1/clock.h +++ b/arch/arm/mach-omap1/clock.h @@ -13,8 +13,8 @@ #ifndef __ARCH_ARM_MACH_OMAP1_CLOCK_H #define __ARCH_ARM_MACH_OMAP1_CLOCK_H -static int omap1_clk_enable(struct clk * clk); -static void omap1_clk_disable(struct clk * clk); +static int omap1_clk_enable_generic(struct clk * clk); +static void omap1_clk_disable_generic(struct clk * clk); static void omap1_ckctl_recalc(struct clk * clk); static void omap1_watchdog_recalc(struct clk * clk); static void omap1_ckctl_recalc_dsp_domain(struct clk * clk); @@ -30,8 +30,8 @@ static long omap1_round_ext_clk_rate(struct clk * clk, unsigned long rate); static void omap1_init_ext_clk(struct clk * clk); static int omap1_select_table_rate(struct clk * clk, unsigned long rate); static long omap1_round_to_table_rate(struct clk * clk, unsigned long rate); -static int omap1_clk_use(struct clk *clk); -static void omap1_clk_unuse(struct clk *clk); +static int omap1_clk_enable(struct clk *clk); +static void omap1_clk_disable(struct clk *clk); struct mpu_rate { unsigned long rate; @@ -152,8 +152,8 @@ static struct clk ck_ref = { .rate = 12000000, .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | ALWAYS_ENABLED, - .enable = &omap1_clk_enable, - .disable = &omap1_clk_disable, + .enable = &omap1_clk_enable_generic, + .disable = &omap1_clk_disable_generic, }; static struct clk ck_dpll1 = { @@ -161,8 +161,8 @@ static struct clk ck_dpll1 = { .parent = &ck_ref, .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | RATE_PROPAGATES | ALWAYS_ENABLED, - .enable = &omap1_clk_enable, - .disable = &omap1_clk_disable, + .enable = &omap1_clk_enable_generic, + .disable = &omap1_clk_disable_generic, }; static struct arm_idlect1_clk ck_dpll1out = { @@ -173,8 +173,8 @@ static struct arm_idlect1_clk ck_dpll1out = { .enable_reg = (void __iomem *)ARM_IDLECT2, .enable_bit = EN_CKOUT_ARM, .recalc = &followparent_recalc, - .enable = &omap1_clk_enable, - .disable = &omap1_clk_disable, + .enable = &omap1_clk_enable_generic, + .disable = &omap1_clk_disable_generic, }, .idlect_shift = 12, }; @@ -186,8 +186,8 @@ static struct clk arm_ck = { RATE_CKCTL | RATE_PROPAGATES | ALWAYS_ENABLED, .rate_offset = CKCTL_ARMDIV_OFFSET, .recalc = &omap1_ckctl_recalc, - .enable = &omap1_clk_enable, - .disable = &omap1_clk_disable, + .enable = &omap1_clk_enable_generic, + .disable = &omap1_clk_disable_generic, }; static struct arm_idlect1_clk armper_ck = { @@ -200,8 +200,8 @@ static struct arm_idlect1_clk armper_ck = { .enable_bit = EN_PERCK, .rate_offset = CKCTL_PERDIV_OFFSET, .recalc = &omap1_ckctl_recalc, - .enable = &omap1_clk_enable, - .disable = &omap1_clk_disable, + .enable = &omap1_clk_enable_generic, + .disable = &omap1_clk_disable_generic, }, .idlect_shift = 2, }; @@ -213,8 +213,8 @@ static struct clk arm_gpio_ck = { .enable_reg = (void __iomem *)ARM_IDLECT2, .enable_bit = EN_GPIOCK, .recalc = &followparent_recalc, - .enable = &omap1_clk_enable, - .disable = &omap1_clk_disable, + .enable = &omap1_clk_enable_generic, + .disable = &omap1_clk_disable_generic, }; static struct arm_idlect1_clk armxor_ck = { @@ -226,8 +226,8 @@ static struct arm_idlect1_clk armxor_ck = { .enable_reg = (void __iomem *)ARM_IDLECT2, .enable_bit = EN_XORPCK, .recalc = &followparent_recalc, - .enable = &omap1_clk_enable, - .disable = &omap1_clk_disable, + .enable = &omap1_clk_enable_generic, + .disable = &omap1_clk_disable_generic, }, .idlect_shift = 1, }; @@ -241,8 +241,8 @@ static struct arm_idlect1_clk armtim_ck = { .enable_reg = (void __iomem *)ARM_IDLECT2, .enable_bit = EN_TIMCK, .recalc = &followparent_recalc, - .enable = &omap1_clk_enable, - .disable = &omap1_clk_disable, + .enable = &omap1_clk_enable_generic, + .disable = &omap1_clk_disable_generic, }, .idlect_shift = 9, }; @@ -256,8 +256,8 @@ static struct arm_idlect1_clk armwdt_ck = { .enable_reg = (void __iomem *)ARM_IDLECT2, .enable_bit = EN_WDTCK, .recalc = &omap1_watchdog_recalc, - .enable = &omap1_clk_enable, - .disable = &omap1_clk_disable, + .enable = &omap1_clk_enable_generic, + .disable = &omap1_clk_disable_generic, }, .idlect_shift = 0, }; @@ -272,8 +272,8 @@ static struct clk arminth_ck16xx = { * * 1510 version is in TC clocks. */ - .enable = &omap1_clk_enable, - .disable = &omap1_clk_disable, + .enable = &omap1_clk_enable_generic, + .disable = &omap1_clk_disable_generic, }; static struct clk dsp_ck = { @@ -285,8 +285,8 @@ static struct clk dsp_ck = { .enable_bit = EN_DSPCK, .rate_offset = CKCTL_DSPDIV_OFFSET, .recalc = &omap1_ckctl_recalc, - .enable = &omap1_clk_enable, - .disable = &omap1_clk_disable, + .enable = &omap1_clk_enable_generic, + .disable = &omap1_clk_disable_generic, }; static struct clk dspmmu_ck = { @@ -296,8 +296,8 @@ static struct clk dspmmu_ck = { RATE_CKCTL | ALWAYS_ENABLED, .rate_offset = CKCTL_DSPMMUDIV_OFFSET, .recalc = &omap1_ckctl_recalc, - .enable = &omap1_clk_enable, - .disable = &omap1_clk_disable, + .enable = &omap1_clk_enable_generic, + .disable = &omap1_clk_disable_generic, }; static struct clk dspper_ck = { @@ -349,8 +349,8 @@ static struct arm_idlect1_clk tc_ck = { CLOCK_IDLE_CONTROL, .rate_offset = CKCTL_TCDIV_OFFSET, .recalc = &omap1_ckctl_recalc, - .enable = &omap1_clk_enable, - .disable = &omap1_clk_disable, + .enable = &omap1_clk_enable_generic, + .disable = &omap1_clk_disable_generic, }, .idlect_shift = 6, }; @@ -364,8 +364,8 @@ static struct clk arminth_ck1510 = { * * 16xx version is in MPU clocks. */ - .enable = &omap1_clk_enable, - .disable = &omap1_clk_disable, + .enable = &omap1_clk_enable_generic, + .disable = &omap1_clk_disable_generic, }; static struct clk tipb_ck = { @@ -374,8 +374,8 @@ static struct clk tipb_ck = { .parent = &tc_ck.clk, .flags = CLOCK_IN_OMAP1510 | ALWAYS_ENABLED, .recalc = &followparent_recalc, - .enable = &omap1_clk_enable, - .disable = &omap1_clk_disable, + .enable = &omap1_clk_enable_generic, + .disable = &omap1_clk_disable_generic, }; static struct clk l3_ocpi_ck = { @@ -386,8 +386,8 @@ static struct clk l3_ocpi_ck = { .enable_reg = (void __iomem *)ARM_IDLECT3, .enable_bit = EN_OCPI_CK, .recalc = &followparent_recalc, - .enable = &omap1_clk_enable, - .disable = &omap1_clk_disable, + .enable = &omap1_clk_enable_generic, + .disable = &omap1_clk_disable_generic, }; static struct clk tc1_ck = { @@ -397,8 +397,8 @@ static struct clk tc1_ck = { .enable_reg = (void __iomem *)ARM_IDLECT3, .enable_bit = EN_TC1_CK, .recalc = &followparent_recalc, - .enable = &omap1_clk_enable, - .disable = &omap1_clk_disable, + .enable = &omap1_clk_enable_generic, + .disable = &omap1_clk_disable_generic, }; static struct clk tc2_ck = { @@ -408,8 +408,8 @@ static struct clk tc2_ck = { .enable_reg = (void __iomem *)ARM_IDLECT3, .enable_bit = EN_TC2_CK, .recalc = &followparent_recalc, - .enable = &omap1_clk_enable, - .disable = &omap1_clk_disable, + .enable = &omap1_clk_enable_generic, + .disable = &omap1_clk_disable_generic, }; static struct clk dma_ck = { @@ -419,8 +419,8 @@ static struct clk dma_ck = { .flags = CLOCK_IN_OMAP1510 | CLOCK_IN_OMAP16XX | ALWAYS_ENABLED, .recalc = &followparent_recalc, - .enable = &omap1_clk_enable, - .disable = &omap1_clk_disable, + .enable = &omap1_clk_enable_generic, + .disable = &omap1_clk_disable_generic, }; static struct clk dma_lcdfree_ck = { @@ -428,8 +428,8 @@ static struct clk dma_lcdfree_ck = { .parent = &tc_ck.clk, .flags = CLOCK_IN_OMAP16XX | ALWAYS_ENABLED, .recalc = &followparent_recalc, - .enable = &omap1_clk_enable, - .disable = &omap1_clk_disable, + .enable = &omap1_clk_enable_generic, + .disable = &omap1_clk_disable_generic, }; static struct arm_idlect1_clk api_ck = { @@ -441,8 +441,8 @@ static struct arm_idlect1_clk api_ck = { .enable_reg = (void __iomem *)ARM_IDLECT2, .enable_bit = EN_APICK, .recalc = &followparent_recalc, - .enable = &omap1_clk_enable, - .disable = &omap1_clk_disable, + .enable = &omap1_clk_enable_generic, + .disable = &omap1_clk_disable_generic, }, .idlect_shift = 8, }; @@ -455,8 +455,8 @@ static struct arm_idlect1_clk lb_ck = { .enable_reg = (void __iomem *)ARM_IDLECT2, .enable_bit = EN_LBCK, .recalc = &followparent_recalc, - .enable = &omap1_clk_enable, - .disable = &omap1_clk_disable, + .enable = &omap1_clk_enable_generic, + .disable = &omap1_clk_disable_generic, }, .idlect_shift = 4, }; @@ -466,8 +466,8 @@ static struct clk rhea1_ck = { .parent = &tc_ck.clk, .flags = CLOCK_IN_OMAP16XX | ALWAYS_ENABLED, .recalc = &followparent_recalc, - .enable = &omap1_clk_enable, - .disable = &omap1_clk_disable, + .enable = &omap1_clk_enable_generic, + .disable = &omap1_clk_disable_generic, }; static struct clk rhea2_ck = { @@ -475,8 +475,8 @@ static struct clk rhea2_ck = { .parent = &tc_ck.clk, .flags = CLOCK_IN_OMAP16XX | ALWAYS_ENABLED, .recalc = &followparent_recalc, - .enable = &omap1_clk_enable, - .disable = &omap1_clk_disable, + .enable = &omap1_clk_enable_generic, + .disable = &omap1_clk_disable_generic, }; static struct clk lcd_ck_16xx = { @@ -487,8 +487,8 @@ static struct clk lcd_ck_16xx = { .enable_bit = EN_LCDCK, .rate_offset = CKCTL_LCDDIV_OFFSET, .recalc = &omap1_ckctl_recalc, - .enable = &omap1_clk_enable, - .disable = &omap1_clk_disable, + .enable = &omap1_clk_enable_generic, + .disable = &omap1_clk_disable_generic, }; static struct arm_idlect1_clk lcd_ck_1510 = { @@ -501,8 +501,8 @@ static struct arm_idlect1_clk lcd_ck_1510 = { .enable_bit = EN_LCDCK, .rate_offset = CKCTL_LCDDIV_OFFSET, .recalc = &omap1_ckctl_recalc, - .enable = &omap1_clk_enable, - .disable = &omap1_clk_disable, + .enable = &omap1_clk_enable_generic, + .disable = &omap1_clk_disable_generic, }, .idlect_shift = 3, }; @@ -518,8 +518,8 @@ static struct clk uart1_1510 = { .enable_bit = 29, /* Chooses between 12MHz and 48MHz */ .set_rate = &omap1_set_uart_rate, .recalc = &omap1_uart_recalc, - .enable = &omap1_clk_enable, - .disable = &omap1_clk_disable, + .enable = &omap1_clk_enable_generic, + .disable = &omap1_clk_disable_generic, }; static struct uart_clk uart1_16xx = { @@ -550,8 +550,8 @@ static struct clk uart2_ck = { .enable_bit = 30, /* Chooses between 12MHz and 48MHz */ .set_rate = &omap1_set_uart_rate, .recalc = &omap1_uart_recalc, - .enable = &omap1_clk_enable, - .disable = &omap1_clk_disable, + .enable = &omap1_clk_enable_generic, + .disable = &omap1_clk_disable_generic, }; static struct clk uart3_1510 = { @@ -565,8 +565,8 @@ static struct clk uart3_1510 = { .enable_bit = 31, /* Chooses between 12MHz and 48MHz */ .set_rate = &omap1_set_uart_rate, .recalc = &omap1_uart_recalc, - .enable = &omap1_clk_enable, - .disable = &omap1_clk_disable, + .enable = &omap1_clk_enable_generic, + .disable = &omap1_clk_disable_generic, }; static struct uart_clk uart3_16xx = { @@ -593,8 +593,8 @@ static struct clk usb_clko = { /* 6 MHz output on W4_USB_CLKO */ RATE_FIXED | ENABLE_REG_32BIT, .enable_reg = (void __iomem *)ULPD_CLOCK_CTRL, .enable_bit = USB_MCLK_EN_BIT, - .enable = &omap1_clk_enable, - .disable = &omap1_clk_disable, + .enable = &omap1_clk_enable_generic, + .disable = &omap1_clk_disable_generic, }; static struct clk usb_hhc_ck1510 = { @@ -605,8 +605,8 @@ static struct clk usb_hhc_ck1510 = { RATE_FIXED | ENABLE_REG_32BIT, .enable_reg = (void __iomem *)MOD_CONF_CTRL_0, .enable_bit = USB_HOST_HHC_UHOST_EN, - .enable = &omap1_clk_enable, - .disable = &omap1_clk_disable, + .enable = &omap1_clk_enable_generic, + .disable = &omap1_clk_disable_generic, }; static struct clk usb_hhc_ck16xx = { @@ -618,8 +618,8 @@ static struct clk usb_hhc_ck16xx = { RATE_FIXED | ENABLE_REG_32BIT, .enable_reg = (void __iomem *)OTG_BASE + 0x08 /* OTG_SYSCON_2 */, .enable_bit = 8 /* UHOST_EN */, - .enable = &omap1_clk_enable, - .disable = &omap1_clk_disable, + .enable = &omap1_clk_enable_generic, + .disable = &omap1_clk_disable_generic, }; static struct clk usb_dc_ck = { @@ -629,8 +629,8 @@ static struct clk usb_dc_ck = { .flags = CLOCK_IN_OMAP16XX | RATE_FIXED, .enable_reg = (void __iomem *)SOFT_REQ_REG, .enable_bit = 4, - .enable = &omap1_clk_enable, - .disable = &omap1_clk_disable, + .enable = &omap1_clk_enable_generic, + .disable = &omap1_clk_disable_generic, }; static struct clk mclk_1510 = { @@ -638,8 +638,8 @@ static struct clk mclk_1510 = { /* Direct from ULPD, no parent. May be enabled by ext hardware. */ .rate = 12000000, .flags = CLOCK_IN_OMAP1510 | RATE_FIXED, - .enable = &omap1_clk_enable, - .disable = &omap1_clk_disable, + .enable = &omap1_clk_enable_generic, + .disable = &omap1_clk_disable_generic, }; static struct clk mclk_16xx = { @@ -651,8 +651,8 @@ static struct clk mclk_16xx = { .set_rate = &omap1_set_ext_clk_rate, .round_rate = &omap1_round_ext_clk_rate, .init = &omap1_init_ext_clk, - .enable = &omap1_clk_enable, - .disable = &omap1_clk_disable, + .enable = &omap1_clk_enable_generic, + .disable = &omap1_clk_disable_generic, }; static struct clk bclk_1510 = { @@ -660,8 +660,8 @@ static struct clk bclk_1510 = { /* Direct from ULPD, no parent. May be enabled by ext hardware. */ .rate = 12000000, .flags = CLOCK_IN_OMAP1510 | RATE_FIXED, - .enable = &omap1_clk_enable, - .disable = &omap1_clk_disable, + .enable = &omap1_clk_enable_generic, + .disable = &omap1_clk_disable_generic, }; static struct clk bclk_16xx = { @@ -673,8 +673,8 @@ static struct clk bclk_16xx = { .set_rate = &omap1_set_ext_clk_rate, .round_rate = &omap1_round_ext_clk_rate, .init = &omap1_init_ext_clk, - .enable = &omap1_clk_enable, - .disable = &omap1_clk_disable, + .enable = &omap1_clk_enable_generic, + .disable = &omap1_clk_disable_generic, }; static struct clk mmc1_ck = { @@ -686,8 +686,8 @@ static struct clk mmc1_ck = { RATE_FIXED | ENABLE_REG_32BIT | CLOCK_NO_IDLE_PARENT, .enable_reg = (void __iomem *)MOD_CONF_CTRL_0, .enable_bit = 23, - .enable = &omap1_clk_enable, - .disable = &omap1_clk_disable, + .enable = &omap1_clk_enable_generic, + .disable = &omap1_clk_disable_generic, }; static struct clk mmc2_ck = { @@ -699,8 +699,8 @@ static struct clk mmc2_ck = { RATE_FIXED | ENABLE_REG_32BIT | CLOCK_NO_IDLE_PARENT, .enable_reg = (void __iomem *)MOD_CONF_CTRL_0, .enable_bit = 20, - .enable = &omap1_clk_enable, - .disable = &omap1_clk_disable, + .enable = &omap1_clk_enable_generic, + .disable = &omap1_clk_disable_generic, }; static struct clk virtual_ck_mpu = { @@ -711,8 +711,8 @@ static struct clk virtual_ck_mpu = { .recalc = &followparent_recalc, .set_rate = &omap1_select_table_rate, .round_rate = &omap1_round_to_table_rate, - .enable = &omap1_clk_enable, - .disable = &omap1_clk_disable, + .enable = &omap1_clk_enable_generic, + .disable = &omap1_clk_disable_generic, }; static struct clk * onchip_clks[] = { diff --git a/arch/arm/mach-omap1/serial.c b/arch/arm/mach-omap1/serial.c index 7a68f098a02..e924e0c6a4c 100644 --- a/arch/arm/mach-omap1/serial.c +++ b/arch/arm/mach-omap1/serial.c @@ -146,7 +146,7 @@ void __init omap_serial_init(void) if (IS_ERR(uart1_ck)) printk("Could not get uart1_ck\n"); else { - clk_use(uart1_ck); + clk_enable(uart1_ck); if (cpu_is_omap1510()) clk_set_rate(uart1_ck, 12000000); } @@ -166,7 +166,7 @@ void __init omap_serial_init(void) if (IS_ERR(uart2_ck)) printk("Could not get uart2_ck\n"); else { - clk_use(uart2_ck); + clk_enable(uart2_ck); if (cpu_is_omap1510()) clk_set_rate(uart2_ck, 12000000); else @@ -188,7 +188,7 @@ void __init omap_serial_init(void) if (IS_ERR(uart3_ck)) printk("Could not get uart3_ck\n"); else { - clk_use(uart3_ck); + clk_enable(uart3_ck); if (cpu_is_omap1510()) clk_set_rate(uart3_ck, 12000000); } diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c index 5407b954915..180f675c906 100644 --- a/arch/arm/mach-omap2/clock.c +++ b/arch/arm/mach-omap2/clock.c @@ -111,7 +111,7 @@ static void omap2_clk_fixed_enable(struct clk *clk) /* Enables clock without considering parent dependencies or use count * REVISIT: Maybe change this to use clk->enable like on omap1? */ -static int omap2_clk_enable(struct clk * clk) +static int _omap2_clk_enable(struct clk * clk) { u32 regval32; @@ -150,7 +150,7 @@ static void omap2_clk_fixed_disable(struct clk *clk) } /* Disables clock without considering parent dependencies or use count */ -static void omap2_clk_disable(struct clk *clk) +static void _omap2_clk_disable(struct clk *clk) { u32 regval32; @@ -167,23 +167,23 @@ static void omap2_clk_disable(struct clk *clk) __raw_writel(regval32, clk->enable_reg); } -static int omap2_clk_use(struct clk *clk) +static int omap2_clk_enable(struct clk *clk) { int ret = 0; if (clk->usecount++ == 0) { if (likely((u32)clk->parent)) - ret = omap2_clk_use(clk->parent); + ret = omap2_clk_enable(clk->parent); if (unlikely(ret != 0)) { clk->usecount--; return ret; } - ret = omap2_clk_enable(clk); + ret = _omap2_clk_enable(clk); if (unlikely(ret != 0) && clk->parent) { - omap2_clk_unuse(clk->parent); + omap2_clk_disable(clk->parent); clk->usecount--; } } @@ -191,12 +191,12 @@ static int omap2_clk_use(struct clk *clk) return ret; } -static void omap2_clk_unuse(struct clk *clk) +static void omap2_clk_disable(struct clk *clk) { if (clk->usecount > 0 && !(--clk->usecount)) { - omap2_clk_disable(clk); + _omap2_clk_disable(clk); if (likely((u32)clk->parent)) - omap2_clk_unuse(clk->parent); + omap2_clk_disable(clk->parent); } } @@ -873,7 +873,7 @@ static int omap2_clk_set_parent(struct clk *clk, struct clk *new_parent) reg = (void __iomem *)src_sel; if (clk->usecount > 0) - omap2_clk_disable(clk); + _omap2_clk_disable(clk); /* Set new source value (previous dividers if any in effect) */ reg_val = __raw_readl(reg) & ~(field_mask << src_off); @@ -884,7 +884,7 @@ static int omap2_clk_set_parent(struct clk *clk, struct clk *new_parent) __raw_writel(0x1, (void __iomem *)&PRCM_CLKCFG_CTRL); if (clk->usecount > 0) - omap2_clk_enable(clk); + _omap2_clk_enable(clk); clk->parent = new_parent; @@ -999,8 +999,6 @@ static int omap2_select_table_rate(struct clk * clk, unsigned long rate) static struct clk_functions omap2_clk_functions = { .clk_enable = omap2_clk_enable, .clk_disable = omap2_clk_disable, - .clk_use = omap2_clk_use, - .clk_unuse = omap2_clk_unuse, .clk_round_rate = omap2_clk_round_rate, .clk_set_rate = omap2_clk_set_rate, .clk_set_parent = omap2_clk_set_parent, @@ -1045,7 +1043,7 @@ static void __init omap2_disable_unused_clocks(void) continue; printk(KERN_INFO "Disabling unused clock \"%s\"\n", ck->name); - omap2_clk_disable(ck); + _omap2_clk_disable(ck); } } late_initcall(omap2_disable_unused_clocks); @@ -1120,10 +1118,10 @@ int __init omap2_clk_init(void) * Only enable those clocks we will need, let the drivers * enable other clocks as necessary */ - clk_use(&sync_32k_ick); - clk_use(&omapctrl_ick); + clk_enable(&sync_32k_ick); + clk_enable(&omapctrl_ick); if (cpu_is_omap2430()) - clk_use(&sdrc_ick); + clk_enable(&sdrc_ick); return 0; } diff --git a/arch/arm/mach-omap2/clock.h b/arch/arm/mach-omap2/clock.h index 4aeab5591bd..6cab20b1d3c 100644 --- a/arch/arm/mach-omap2/clock.h +++ b/arch/arm/mach-omap2/clock.h @@ -24,7 +24,7 @@ static void omap2_propagate_rate(struct clk * clk); static void omap2_mpu_recalc(struct clk * clk); static int omap2_select_table_rate(struct clk * clk, unsigned long rate); static long omap2_round_to_table_rate(struct clk * clk, unsigned long rate); -static void omap2_clk_unuse(struct clk *clk); +static void omap2_clk_disable(struct clk *clk); static void omap2_sys_clk_recalc(struct clk * clk); static u32 omap2_clksel_to_divisor(u32 div_sel, u32 field_val); static u32 omap2_clksel_get_divisor(struct clk *clk); @@ -859,7 +859,7 @@ static struct clk core_l3_ck = { /* Used for ick and fck, interconnect */ static struct clk usb_l4_ick = { /* FS-USB interface clock */ .name = "usb_l4_ick", - .parent = &core_ck, + .parent = &core_l3_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | RATE_CKCTL | CM_CORE_SEL1 | DELAYED_APP | CONFIG_PARTICIPANT, @@ -1045,7 +1045,7 @@ static struct clk gpt1_ick = { .name = "gpt1_ick", .parent = &l4_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, - .enable_reg = (void __iomem *)&CM_ICLKEN_WKUP, /* Bit4 */ + .enable_reg = (void __iomem *)&CM_ICLKEN_WKUP, /* Bit0 */ .enable_bit = 0, .recalc = &omap2_followparent_recalc, }; @@ -1055,7 +1055,7 @@ static struct clk gpt1_fck = { .parent = &func_32k_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X | CM_WKUP_SEL1, - .enable_reg = (void __iomem *)&CM_FCLKEN_WKUP, + .enable_reg = (void __iomem *)&CM_FCLKEN_WKUP, /* Bit0 */ .enable_bit = 0, .src_offset = 0, .recalc = &omap2_followparent_recalc, @@ -1065,7 +1065,7 @@ static struct clk gpt2_ick = { .name = "gpt2_ick", .parent = &l4_ck, .flags = CLOCK_IN_OMAP242X | CLOCK_IN_OMAP243X, - .enable_reg = (void __iomem *)&CM_ICLKEN1_CORE, /* bit4 */ + .enable_reg = (void __iomem *)&CM_ICLKEN1_CORE, /* Bit4 */ .enable_bit = 0, .recalc = &omap2_followparent_recalc, }; @@ -1839,7 +1839,7 @@ static struct clk usb_fck = { static struct clk usbhs_ick = { .name = "usbhs_ick", - .parent = &l4_ck, + .parent = &core_l3_ck, .flags = CLOCK_IN_OMAP243X, .enable_reg = (void __iomem *)&CM_ICLKEN2_CORE, .enable_bit = 6, diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c index e1bd46a96e1..24dd374224a 100644 --- a/arch/arm/mach-omap2/serial.c +++ b/arch/arm/mach-omap2/serial.c @@ -119,14 +119,14 @@ void __init omap_serial_init() if (IS_ERR(uart1_ick)) printk("Could not get uart1_ick\n"); else { - clk_use(uart1_ick); + clk_enable(uart1_ick); } uart1_fck = clk_get(NULL, "uart1_fck"); if (IS_ERR(uart1_fck)) printk("Could not get uart1_fck\n"); else { - clk_use(uart1_fck); + clk_enable(uart1_fck); } break; case 1: @@ -134,14 +134,14 @@ void __init omap_serial_init() if (IS_ERR(uart2_ick)) printk("Could not get uart2_ick\n"); else { - clk_use(uart2_ick); + clk_enable(uart2_ick); } uart2_fck = clk_get(NULL, "uart2_fck"); if (IS_ERR(uart2_fck)) printk("Could not get uart2_fck\n"); else { - clk_use(uart2_fck); + clk_enable(uart2_fck); } break; case 2: @@ -149,14 +149,14 @@ void __init omap_serial_init() if (IS_ERR(uart3_ick)) printk("Could not get uart3_ick\n"); else { - clk_use(uart3_ick); + clk_enable(uart3_ick); } uart3_fck = clk_get(NULL, "uart3_fck"); if (IS_ERR(uart3_fck)) printk("Could not get uart3_fck\n"); else { - clk_use(uart3_fck); + clk_enable(uart3_fck); } break; } diff --git a/arch/arm/mach-omap2/timer-gp.c b/arch/arm/mach-omap2/timer-gp.c index 23d36b1c40f..1d2f5ac2f69 100644 --- a/arch/arm/mach-omap2/timer-gp.c +++ b/arch/arm/mach-omap2/timer-gp.c @@ -104,7 +104,7 @@ static void __init omap2_gp_timer_init(void) if (IS_ERR(sys_ck)) printk(KERN_ERR "Could not get sys_ck\n"); else { - clk_use(sys_ck); + clk_enable(sys_ck); tick_period = clk_get_rate(sys_ck) / 100; clk_put(sys_ck); } diff --git a/arch/arm/mach-s3c2410/cpu.h b/arch/arm/mach-s3c2410/cpu.h index 9cbe5eef492..fc1067783f6 100644 --- a/arch/arm/mach-s3c2410/cpu.h +++ b/arch/arm/mach-s3c2410/cpu.h @@ -17,11 +17,12 @@ * 14-Jan-2005 BJD Added s3c24xx_init_clocks() call * 10-Mar-2005 LCVR Changed S3C2410_{VA,SZ} to S3C24XX_{VA,SZ} & IODESC_ENT * 14-Mar-2005 BJD Updated for __iomem + * 15-Jan-2006 LCVR Updated S3C2410_PA_##x to new S3C24XX_PA_##x macro */ /* todo - fix when rmk changes iodescs to use `void __iomem *` */ -#define IODESC_ENT(x) { (unsigned long)S3C24XX_VA_##x, __phys_to_pfn(S3C2410_PA_##x), S3C24XX_SZ_##x, MT_DEVICE } +#define IODESC_ENT(x) { (unsigned long)S3C24XX_VA_##x, __phys_to_pfn(S3C24XX_PA_##x), S3C24XX_SZ_##x, MT_DEVICE } #ifndef MHZ #define MHZ (1000*1000) diff --git a/arch/arm/mach-s3c2410/devs.c b/arch/arm/mach-s3c2410/devs.c index f58406e6ef5..b8d994a24d1 100644 --- a/arch/arm/mach-s3c2410/devs.c +++ b/arch/arm/mach-s3c2410/devs.c @@ -10,6 +10,7 @@ * published by the Free Software Foundation. * * Modifications: + * 15-Jan-2006 LCVR Using S3C24XX_PA_##x macro for common S3C24XX devices * 10-Mar-2005 LCVR Changed S3C2410_{VA,SZ} to S3C24XX_{VA,SZ} * 10-Feb-2005 BJD Added camera from guillaume.gourat@nexvision.tv * 29-Aug-2004 BJD Added timers 0 through 3 @@ -46,8 +47,8 @@ struct platform_device *s3c24xx_uart_devs[3]; static struct resource s3c_usb_resource[] = { [0] = { - .start = S3C2410_PA_USBHOST, - .end = S3C2410_PA_USBHOST + S3C24XX_SZ_USBHOST - 1, + .start = S3C24XX_PA_USBHOST, + .end = S3C24XX_PA_USBHOST + S3C24XX_SZ_USBHOST - 1, .flags = IORESOURCE_MEM, }, [1] = { @@ -76,8 +77,8 @@ EXPORT_SYMBOL(s3c_device_usb); static struct resource s3c_lcd_resource[] = { [0] = { - .start = S3C2410_PA_LCD, - .end = S3C2410_PA_LCD + S3C24XX_SZ_LCD - 1, + .start = S3C24XX_PA_LCD, + .end = S3C24XX_PA_LCD + S3C24XX_SZ_LCD - 1, .flags = IORESOURCE_MEM, }, [1] = { @@ -139,8 +140,8 @@ EXPORT_SYMBOL(s3c_device_nand); static struct resource s3c_usbgadget_resource[] = { [0] = { - .start = S3C2410_PA_USBDEV, - .end = S3C2410_PA_USBDEV + S3C24XX_SZ_USBDEV - 1, + .start = S3C24XX_PA_USBDEV, + .end = S3C24XX_PA_USBDEV + S3C24XX_SZ_USBDEV - 1, .flags = IORESOURCE_MEM, }, [1] = { @@ -164,8 +165,8 @@ EXPORT_SYMBOL(s3c_device_usbgadget); static struct resource s3c_wdt_resource[] = { [0] = { - .start = S3C2410_PA_WATCHDOG, - .end = S3C2410_PA_WATCHDOG + S3C24XX_SZ_WATCHDOG - 1, + .start = S3C24XX_PA_WATCHDOG, + .end = S3C24XX_PA_WATCHDOG + S3C24XX_SZ_WATCHDOG - 1, .flags = IORESOURCE_MEM, }, [1] = { @@ -189,8 +190,8 @@ EXPORT_SYMBOL(s3c_device_wdt); static struct resource s3c_i2c_resource[] = { [0] = { - .start = S3C2410_PA_IIC, - .end = S3C2410_PA_IIC + S3C24XX_SZ_IIC - 1, + .start = S3C24XX_PA_IIC, + .end = S3C24XX_PA_IIC + S3C24XX_SZ_IIC - 1, .flags = IORESOURCE_MEM, }, [1] = { @@ -214,8 +215,8 @@ EXPORT_SYMBOL(s3c_device_i2c); static struct resource s3c_iis_resource[] = { [0] = { - .start = S3C2410_PA_IIS, - .end = S3C2410_PA_IIS + S3C24XX_SZ_IIS -1, + .start = S3C24XX_PA_IIS, + .end = S3C24XX_PA_IIS + S3C24XX_SZ_IIS -1, .flags = IORESOURCE_MEM, } }; @@ -239,8 +240,8 @@ EXPORT_SYMBOL(s3c_device_iis); static struct resource s3c_rtc_resource[] = { [0] = { - .start = S3C2410_PA_RTC, - .end = S3C2410_PA_RTC + 0xff, + .start = S3C24XX_PA_RTC, + .end = S3C24XX_PA_RTC + 0xff, .flags = IORESOURCE_MEM, }, [1] = { @@ -268,8 +269,8 @@ EXPORT_SYMBOL(s3c_device_rtc); static struct resource s3c_adc_resource[] = { [0] = { - .start = S3C2410_PA_ADC, - .end = S3C2410_PA_ADC + S3C24XX_SZ_ADC - 1, + .start = S3C24XX_PA_ADC, + .end = S3C24XX_PA_ADC + S3C24XX_SZ_ADC - 1, .flags = IORESOURCE_MEM, }, [1] = { @@ -316,8 +317,8 @@ EXPORT_SYMBOL(s3c_device_sdi); static struct resource s3c_spi0_resource[] = { [0] = { - .start = S3C2410_PA_SPI, - .end = S3C2410_PA_SPI + 0x1f, + .start = S3C24XX_PA_SPI, + .end = S3C24XX_PA_SPI + 0x1f, .flags = IORESOURCE_MEM, }, [1] = { @@ -341,8 +342,8 @@ EXPORT_SYMBOL(s3c_device_spi0); static struct resource s3c_spi1_resource[] = { [0] = { - .start = S3C2410_PA_SPI + 0x20, - .end = S3C2410_PA_SPI + 0x20 + 0x1f, + .start = S3C24XX_PA_SPI + 0x20, + .end = S3C24XX_PA_SPI + 0x20 + 0x1f, .flags = IORESOURCE_MEM, }, [1] = { @@ -366,8 +367,8 @@ EXPORT_SYMBOL(s3c_device_spi1); static struct resource s3c_timer0_resource[] = { [0] = { - .start = S3C2410_PA_TIMER + 0x0C, - .end = S3C2410_PA_TIMER + 0x0C + 0xB, + .start = S3C24XX_PA_TIMER + 0x0C, + .end = S3C24XX_PA_TIMER + 0x0C + 0xB, .flags = IORESOURCE_MEM, }, [1] = { @@ -391,8 +392,8 @@ EXPORT_SYMBOL(s3c_device_timer0); static struct resource s3c_timer1_resource[] = { [0] = { - .start = S3C2410_PA_TIMER + 0x18, - .end = S3C2410_PA_TIMER + 0x23, + .start = S3C24XX_PA_TIMER + 0x18, + .end = S3C24XX_PA_TIMER + 0x23, .flags = IORESOURCE_MEM, }, [1] = { @@ -416,8 +417,8 @@ EXPORT_SYMBOL(s3c_device_timer1); static struct resource s3c_timer2_resource[] = { [0] = { - .start = S3C2410_PA_TIMER + 0x24, - .end = S3C2410_PA_TIMER + 0x2F, + .start = S3C24XX_PA_TIMER + 0x24, + .end = S3C24XX_PA_TIMER + 0x2F, .flags = IORESOURCE_MEM, }, [1] = { @@ -441,8 +442,8 @@ EXPORT_SYMBOL(s3c_device_timer2); static struct resource s3c_timer3_resource[] = { [0] = { - .start = S3C2410_PA_TIMER + 0x30, - .end = S3C2410_PA_TIMER + 0x3B, + .start = S3C24XX_PA_TIMER + 0x30, + .end = S3C24XX_PA_TIMER + 0x3B, .flags = IORESOURCE_MEM, }, [1] = { diff --git a/arch/arm/mach-s3c2410/dma.c b/arch/arm/mach-s3c2410/dma.c index 65feaf20d23..4dbd8e758ea 100644 --- a/arch/arm/mach-s3c2410/dma.c +++ b/arch/arm/mach-s3c2410/dma.c @@ -1152,7 +1152,7 @@ static int __init s3c2410_init_dma(void) printk("S3C2410 DMA Driver, (c) 2003-2004 Simtec Electronics\n"); - dma_base = ioremap(S3C2410_PA_DMA, 0x200); + dma_base = ioremap(S3C24XX_PA_DMA, 0x200); if (dma_base == NULL) { printk(KERN_ERR "dma failed to remap register block\n"); return -ENOMEM; diff --git a/arch/arm/mach-s3c2410/sleep.S b/arch/arm/mach-s3c2410/sleep.S index 61768dac7fe..e9a055b779b 100644 --- a/arch/arm/mach-s3c2410/sleep.S +++ b/arch/arm/mach-s3c2410/sleep.S @@ -133,12 +133,12 @@ ENTRY(s3c2410_cpu_resume) @@ load UART to allow us to print the two characters for @@ resume debug - mov r2, #S3C2410_PA_UART & 0xff000000 - orr r2, r2, #S3C2410_PA_UART & 0xff000 + mov r2, #S3C24XX_PA_UART & 0xff000000 + orr r2, r2, #S3C24XX_PA_UART & 0xff000 #if 0 /* SMDK2440 LED set */ - mov r14, #S3C2410_PA_GPIO + mov r14, #S3C24XX_PA_GPIO ldr r12, [ r14, #0x54 ] bic r12, r12, #3<<4 orr r12, r12, #1<<7 diff --git a/arch/arm/mm/ioremap.c b/arch/arm/mm/ioremap.c index de3ce1eec2e..da9b3597411 100644 --- a/arch/arm/mm/ioremap.c +++ b/arch/arm/mm/ioremap.c @@ -142,7 +142,7 @@ __ioremap_pfn(unsigned long pfn, unsigned long offset, size_t size, return NULL; addr = (unsigned long)area->addr; if (remap_area_pages(addr, pfn, size, flags)) { - vfree(addr); + vfree((void *)addr); return NULL; } return (void __iomem *) (offset + (char *)addr); diff --git a/arch/arm/mm/mm-armv.c b/arch/arm/mm/mm-armv.c index d0245a31d4d..ef8d30a185a 100644 --- a/arch/arm/mm/mm-armv.c +++ b/arch/arm/mm/mm-armv.c @@ -343,6 +343,12 @@ static struct mem_types mem_types[] __initdata = { PMD_SECT_AP_WRITE | PMD_SECT_BUFFERABLE | PMD_SECT_TEX(1), .domain = DOMAIN_IO, + }, + [MT_NONSHARED_DEVICE] = { + .prot_l1 = PMD_TYPE_TABLE, + .prot_sect = PMD_TYPE_SECT | PMD_SECT_NONSHARED_DEV | + PMD_SECT_AP_WRITE, + .domain = DOMAIN_IO, } }; diff --git a/arch/arm/plat-omap/clock.c b/arch/arm/plat-omap/clock.c index 7ebc5a29db8..3c2bfc0efda 100644 --- a/arch/arm/plat-omap/clock.c +++ b/arch/arm/plat-omap/clock.c @@ -34,7 +34,7 @@ DEFINE_SPINLOCK(clockfw_lock); static struct clk_functions *arch_clock; /*------------------------------------------------------------------------- - * Standard clock functions defined in asm/hardware/clock.h + * Standard clock functions defined in include/linux/clk.h *-------------------------------------------------------------------------*/ struct clk * clk_get(struct device *dev, const char *id) @@ -60,12 +60,8 @@ int clk_enable(struct clk *clk) int ret = 0; spin_lock_irqsave(&clockfw_lock, flags); - if (clk->enable) - ret = clk->enable(clk); - else if (arch_clock->clk_enable) + if (arch_clock->clk_enable) ret = arch_clock->clk_enable(clk); - else - printk(KERN_ERR "Could not enable clock %s\n", clk->name); spin_unlock_irqrestore(&clockfw_lock, flags); return ret; @@ -77,41 +73,12 @@ void clk_disable(struct clk *clk) unsigned long flags; spin_lock_irqsave(&clockfw_lock, flags); - if (clk->disable) - clk->disable(clk); - else if (arch_clock->clk_disable) + if (arch_clock->clk_disable) arch_clock->clk_disable(clk); - else - printk(KERN_ERR "Could not disable clock %s\n", clk->name); spin_unlock_irqrestore(&clockfw_lock, flags); } EXPORT_SYMBOL(clk_disable); -int clk_use(struct clk *clk) -{ - unsigned long flags; - int ret = 0; - - spin_lock_irqsave(&clockfw_lock, flags); - if (arch_clock->clk_use) - ret = arch_clock->clk_use(clk); - spin_unlock_irqrestore(&clockfw_lock, flags); - - return ret; -} -EXPORT_SYMBOL(clk_use); - -void clk_unuse(struct clk *clk) -{ - unsigned long flags; - - spin_lock_irqsave(&clockfw_lock, flags); - if (arch_clock->clk_unuse) - arch_clock->clk_unuse(clk); - spin_unlock_irqrestore(&clockfw_lock, flags); -} -EXPORT_SYMBOL(clk_unuse); - int clk_get_usecount(struct clk *clk) { unsigned long flags; @@ -146,7 +113,7 @@ void clk_put(struct clk *clk) EXPORT_SYMBOL(clk_put); /*------------------------------------------------------------------------- - * Optional clock functions defined in asm/hardware/clock.h + * Optional clock functions defined in include/linux/clk.h *-------------------------------------------------------------------------*/ long clk_round_rate(struct clk *clk, unsigned long rate) diff --git a/arch/arm/plat-omap/gpio.c b/arch/arm/plat-omap/gpio.c index ca3681a824a..b4d5b9e4bfc 100644 --- a/arch/arm/plat-omap/gpio.c +++ b/arch/arm/plat-omap/gpio.c @@ -853,19 +853,19 @@ static int __init _omap_gpio_init(void) if (IS_ERR(gpio_ick)) printk("Could not get arm_gpio_ck\n"); else - clk_use(gpio_ick); + clk_enable(gpio_ick); } if (cpu_is_omap24xx()) { gpio_ick = clk_get(NULL, "gpios_ick"); if (IS_ERR(gpio_ick)) printk("Could not get gpios_ick\n"); else - clk_use(gpio_ick); + clk_enable(gpio_ick); gpio_fck = clk_get(NULL, "gpios_fck"); if (IS_ERR(gpio_ick)) printk("Could not get gpios_fck\n"); else - clk_use(gpio_fck); + clk_enable(gpio_fck); } #ifdef CONFIG_ARCH_OMAP15XX diff --git a/arch/arm/plat-omap/mcbsp.c b/arch/arm/plat-omap/mcbsp.c index be0e0f32a59..1cd2cace7e1 100644 --- a/arch/arm/plat-omap/mcbsp.c +++ b/arch/arm/plat-omap/mcbsp.c @@ -190,11 +190,11 @@ static int omap_mcbsp_check(unsigned int id) static void omap_mcbsp_dsp_request(void) { if (cpu_is_omap1510() || cpu_is_omap16xx()) { - clk_use(mcbsp_dsp_ck); - clk_use(mcbsp_api_ck); + clk_enable(mcbsp_dsp_ck); + clk_enable(mcbsp_api_ck); /* enable 12MHz clock to mcbsp 1 & 3 */ - clk_use(mcbsp_dspxor_ck); + clk_enable(mcbsp_dspxor_ck); /* * DSP external peripheral reset @@ -208,9 +208,9 @@ static void omap_mcbsp_dsp_request(void) static void omap_mcbsp_dsp_free(void) { if (cpu_is_omap1510() || cpu_is_omap16xx()) { - clk_unuse(mcbsp_dspxor_ck); - clk_unuse(mcbsp_dsp_ck); - clk_unuse(mcbsp_api_ck); + clk_disable(mcbsp_dspxor_ck); + clk_disable(mcbsp_dsp_ck); + clk_disable(mcbsp_api_ck); } } diff --git a/arch/arm/plat-omap/ocpi.c b/arch/arm/plat-omap/ocpi.c index e40fcc8b43d..5cc6775c789 100644 --- a/arch/arm/plat-omap/ocpi.c +++ b/arch/arm/plat-omap/ocpi.c @@ -88,7 +88,7 @@ static int __init omap_ocpi_init(void) if (IS_ERR(ocpi_ck)) return PTR_ERR(ocpi_ck); - clk_use(ocpi_ck); + clk_enable(ocpi_ck); ocpi_enable(); printk("OMAP OCPI interconnect driver loaded\n"); @@ -102,7 +102,7 @@ static void __exit omap_ocpi_exit(void) if (!cpu_is_omap16xx()) return; - clk_unuse(ocpi_ck); + clk_disable(ocpi_ck); clk_put(ocpi_ck); } diff --git a/arch/arm26/kernel/irq.c b/arch/arm26/kernel/irq.c index f3cc1036e5b..0934e6fba60 100644 --- a/arch/arm26/kernel/irq.c +++ b/arch/arm26/kernel/irq.c @@ -141,7 +141,7 @@ int show_interrupts(struct seq_file *p, void *v) if (i < NR_IRQS) { action = irq_desc[i].action; if (!action) - continue; + goto out; seq_printf(p, "%3d: %10u ", i, kstat_irqs(i)); seq_printf(p, " %s", action->name); for (action = action->next; action; action = action->next) { @@ -152,6 +152,7 @@ int show_interrupts(struct seq_file *p, void *v) show_fiq_list(p, v); seq_printf(p, "Err: %10lu\n", irq_err_count); } +out: return 0; } diff --git a/arch/arm26/kernel/ptrace.c b/arch/arm26/kernel/ptrace.c index 3c3371d4683..282e24d7932 100644 --- a/arch/arm26/kernel/ptrace.c +++ b/arch/arm26/kernel/ptrace.c @@ -527,7 +527,7 @@ static int ptrace_getfpregs(struct task_struct *tsk, void *ufp) static int ptrace_setfpregs(struct task_struct *tsk, void *ufp) { set_stopped_child_used_math(tsk); - return copy_from_user(&task_threas_info(tsk)->fpstate, ufp, + return copy_from_user(&task_thread_info(tsk)->fpstate, ufp, sizeof(struct user_fp)) ? -EFAULT : 0; } diff --git a/arch/frv/kernel/signal.c b/arch/frv/kernel/signal.c index 5b7146f54fd..679c1d5cc95 100644 --- a/arch/frv/kernel/signal.c +++ b/arch/frv/kernel/signal.c @@ -35,74 +35,22 @@ struct fdpic_func_descriptor { unsigned long GOT; }; -static int do_signal(sigset_t *oldset); - /* * Atomically swap in the new signal mask, and wait for a signal. */ asmlinkage int sys_sigsuspend(int history0, int history1, old_sigset_t mask) { - sigset_t saveset; - mask &= _BLOCKABLE; spin_lock_irq(¤t->sighand->siglock); - saveset = current->blocked; + current->saved_sigmask = current->blocked; siginitset(¤t->blocked, mask); recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); - __frame->gr8 = -EINTR; - while (1) { - current->state = TASK_INTERRUPTIBLE; - schedule(); - if (do_signal(&saveset)) - /* return the signal number as the return value of this function - * - this is an utterly evil hack. syscalls should not invoke do_signal() - * as entry.S sets regs->gr8 to the return value of the system call - * - we can't just use sigpending() as we'd have to discard SIG_IGN signals - * and call waitpid() if SIGCHLD needed discarding - * - this only works on the i386 because it passes arguments to the signal - * handler on the stack, and the return value in EAX is effectively - * discarded - */ - return __frame->gr8; - } -} - -asmlinkage int sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize) -{ - sigset_t saveset, newset; - - /* XXX: Don't preclude handling different sized sigset_t's. */ - if (sigsetsize != sizeof(sigset_t)) - return -EINVAL; - - if (copy_from_user(&newset, unewset, sizeof(newset))) - return -EFAULT; - sigdelsetmask(&newset, ~_BLOCKABLE); - - spin_lock_irq(¤t->sighand->siglock); - saveset = current->blocked; - current->blocked = newset; - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); - - __frame->gr8 = -EINTR; - while (1) { - current->state = TASK_INTERRUPTIBLE; - schedule(); - if (do_signal(&saveset)) - /* return the signal number as the return value of this function - * - this is an utterly evil hack. syscalls should not invoke do_signal() - * as entry.S sets regs->gr8 to the return value of the system call - * - we can't just use sigpending() as we'd have to discard SIG_IGN signals - * and call waitpid() if SIGCHLD needed discarding - * - this only works on the i386 because it passes arguments to the signal - * handler on the stack, and the return value in EAX is effectively - * discarded - */ - return __frame->gr8; - } + current->state = TASK_INTERRUPTIBLE; + schedule(); + set_thread_flag(TIF_RESTORE_SIGMASK); + return -ERESTARTNOHAND; } asmlinkage int sys_sigaction(int sig, @@ -372,11 +320,11 @@ static int setup_frame(int sig, struct k_sigaction *ka, sigset_t *set) frame->pretcode); #endif - return 1; + return 0; give_sigsegv: force_sig(SIGSEGV, current); - return 0; + return -EFAULT; } /* end setup_frame() */ @@ -471,11 +419,11 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, frame->pretcode); #endif - return 1; + return 0; give_sigsegv: force_sig(SIGSEGV, current); - return 0; + return -EFAULT; } /* end setup_rt_frame() */ @@ -516,7 +464,7 @@ static int handle_signal(unsigned long sig, siginfo_t *info, else ret = setup_frame(sig, ka, oldset); - if (ret) { + if (ret == 0) { spin_lock_irq(¤t->sighand->siglock); sigorsets(¤t->blocked, ¤t->blocked, &ka->sa.sa_mask); @@ -536,10 +484,11 @@ static int handle_signal(unsigned long sig, siginfo_t *info, * want to handle. Thus you cannot kill init even with a SIGKILL even by * mistake. */ -static int do_signal(sigset_t *oldset) +static void do_signal(void) { struct k_sigaction ka; siginfo_t info; + sigset_t *oldset; int signr; /* @@ -549,43 +498,62 @@ static int do_signal(sigset_t *oldset) * if so. */ if (!user_mode(__frame)) - return 1; + return; if (try_to_freeze()) goto no_signal; - if (!oldset) + if (test_thread_flag(TIF_RESTORE_SIGMASK)) + oldset = ¤t->saved_sigmask; + else oldset = ¤t->blocked; signr = get_signal_to_deliver(&info, &ka, __frame, NULL); - if (signr > 0) - return handle_signal(signr, &info, &ka, oldset); + if (signr > 0) { + if (handle_signal(signr, &info, &ka, oldset) == 0) { + /* a signal was successfully delivered; the saved + * sigmask will have been stored in the signal frame, + * and will be restored by sigreturn, so we can simply + * clear the TIF_RESTORE_SIGMASK flag */ + if (test_thread_flag(TIF_RESTORE_SIGMASK)) + clear_thread_flag(TIF_RESTORE_SIGMASK); + } + + return; + } no_signal: /* Did we come from a system call? */ if (__frame->syscallno >= 0) { /* Restart the system call - no handlers present */ - if (__frame->gr8 == -ERESTARTNOHAND || - __frame->gr8 == -ERESTARTSYS || - __frame->gr8 == -ERESTARTNOINTR) { + switch (__frame->gr8) { + case -ERESTARTNOHAND: + case -ERESTARTSYS: + case -ERESTARTNOINTR: __frame->gr8 = __frame->orig_gr8; __frame->pc -= 4; - } + break; - if (__frame->gr8 == -ERESTART_RESTARTBLOCK){ + case -ERESTART_RESTARTBLOCK: __frame->gr8 = __NR_restart_syscall; __frame->pc -= 4; + break; } } - return 0; + /* if there's no signal to deliver, we just put the saved sigmask + * back */ + if (test_thread_flag(TIF_RESTORE_SIGMASK)) { + clear_thread_flag(TIF_RESTORE_SIGMASK); + sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); + } } /* end do_signal() */ /*****************************************************************************/ /* * notification of userspace execution resumption - * - triggered by current->work.notify_resume + * - triggered by the TIF_WORK_MASK flags */ asmlinkage void do_notify_resume(__u32 thread_info_flags) { @@ -594,7 +562,7 @@ asmlinkage void do_notify_resume(__u32 thread_info_flags) clear_thread_flag(TIF_SINGLESTEP); /* deal with pending signal delivery */ - if (thread_info_flags & _TIF_SIGPENDING) - do_signal(NULL); + if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK)) + do_signal(); } /* end do_notify_resume() */ diff --git a/arch/i386/Makefile b/arch/i386/Makefile index bd2d53a9dd2..36bef6543ac 100644 --- a/arch/i386/Makefile +++ b/arch/i386/Makefile @@ -37,10 +37,7 @@ CFLAGS += $(call cc-option,-mpreferred-stack-boundary=2) # CPU-specific tuning. Anything which can be shared with UML should go here. include $(srctree)/arch/i386/Makefile.cpu -# -mregparm=3 works ok on gcc-3.0 and later -# -cflags-$(CONFIG_REGPARM) += $(shell if [ $(call cc-version) -ge 0300 ] ; then \ - echo "-mregparm=3"; fi ;) +cflags-$(CONFIG_REGPARM) += -mregparm=3 # Disable unit-at-a-time mode on pre-gcc-4.0 compilers, it makes gcc use # a lot more stack due to the lack of sharing of stacklots: diff --git a/arch/i386/defconfig b/arch/i386/defconfig index 6a431b92601..3cbe6e9cb9f 100644 --- a/arch/i386/defconfig +++ b/arch/i386/defconfig @@ -644,6 +644,8 @@ CONFIG_8139TOO_PIO=y # CONFIG_ACENIC is not set # CONFIG_DL2K is not set # CONFIG_E1000 is not set +# CONFIG_E1000_NAPI is not set +# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set # CONFIG_NS83820 is not set # CONFIG_HAMACHI is not set # CONFIG_YELLOWFIN is not set diff --git a/arch/i386/kernel/cpu/cpufreq/Kconfig b/arch/i386/kernel/cpu/cpufreq/Kconfig index 0f1eb507233..26892d2099b 100644 --- a/arch/i386/kernel/cpu/cpufreq/Kconfig +++ b/arch/i386/kernel/cpu/cpufreq/Kconfig @@ -96,6 +96,7 @@ config X86_POWERNOW_K8_ACPI config X86_GX_SUSPMOD tristate "Cyrix MediaGX/NatSemi Geode Suspend Modulation" + depends on PCI help This add the CPUFreq driver for NatSemi Geode processors which support suspend modulation. diff --git a/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c b/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c index 270f2188d68..cc73a7ae34b 100644 --- a/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c +++ b/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c @@ -52,6 +52,7 @@ enum { static int has_N44_O17_errata[NR_CPUS]; +static int has_N60_errata[NR_CPUS]; static unsigned int stock_freq; static struct cpufreq_driver p4clockmod_driver; static unsigned int cpufreq_p4_get(unsigned int cpu); @@ -226,6 +227,12 @@ static int cpufreq_p4_cpu_init(struct cpufreq_policy *policy) case 0x0f12: has_N44_O17_errata[policy->cpu] = 1; dprintk("has errata -- disabling low frequencies\n"); + break; + + case 0x0f29: + has_N60_errata[policy->cpu] = 1; + dprintk("has errata -- disabling frequencies lower than 2ghz\n"); + break; } /* get max frequency */ @@ -237,6 +244,8 @@ static int cpufreq_p4_cpu_init(struct cpufreq_policy *policy) for (i=1; (p4clockmod_table[i].frequency != CPUFREQ_TABLE_END); i++) { if ((i<2) && (has_N44_O17_errata[policy->cpu])) p4clockmod_table[i].frequency = CPUFREQ_ENTRY_INVALID; + else if (has_N60_errata[policy->cpu] && p4clockmod_table[i].frequency < 2000000) + p4clockmod_table[i].frequency = CPUFREQ_ENTRY_INVALID; else p4clockmod_table[i].frequency = (stock_freq * i)/8; } diff --git a/arch/i386/kernel/quirks.c b/arch/i386/kernel/quirks.c index aaf89cb2bc5..87ccdac8492 100644 --- a/arch/i386/kernel/quirks.c +++ b/arch/i386/kernel/quirks.c @@ -25,8 +25,7 @@ static void __devinit quirk_intel_irqbalance(struct pci_dev *dev) /* enable access to config space*/ pci_read_config_byte(dev, 0xf4, &config); - config |= 0x2; - pci_write_config_byte(dev, 0xf4, config); + pci_write_config_byte(dev, 0xf4, config|0x2); /* read xTPR register */ raw_pci_ops->read(0, 0, 0x40, 0x4c, 2, &word); @@ -42,9 +41,9 @@ static void __devinit quirk_intel_irqbalance(struct pci_dev *dev) #endif } - config &= ~0x2; - /* disable access to config space*/ - pci_write_config_byte(dev, 0xf4, config); + /* put back the original value for config space*/ + if (!(config & 0x2)) + pci_write_config_byte(dev, 0xf4, config); } DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7320_MCH, quirk_intel_irqbalance); DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7525_MCH, quirk_intel_irqbalance); diff --git a/arch/i386/kernel/signal.c b/arch/i386/kernel/signal.c index adcd069db91..963616d364e 100644 --- a/arch/i386/kernel/signal.c +++ b/arch/i386/kernel/signal.c @@ -37,51 +37,17 @@ asmlinkage int sys_sigsuspend(int history0, int history1, old_sigset_t mask) { - struct pt_regs * regs = (struct pt_regs *) &history0; - sigset_t saveset; - mask &= _BLOCKABLE; spin_lock_irq(¤t->sighand->siglock); - saveset = current->blocked; + current->saved_sigmask = current->blocked; siginitset(¤t->blocked, mask); recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); - regs->eax = -EINTR; - while (1) { - current->state = TASK_INTERRUPTIBLE; - schedule(); - if (do_signal(regs, &saveset)) - return -EINTR; - } -} - -asmlinkage int -sys_rt_sigsuspend(struct pt_regs regs) -{ - sigset_t saveset, newset; - - /* XXX: Don't preclude handling different sized sigset_t's. */ - if (regs.ecx != sizeof(sigset_t)) - return -EINVAL; - - if (copy_from_user(&newset, (sigset_t __user *)regs.ebx, sizeof(newset))) - return -EFAULT; - sigdelsetmask(&newset, ~_BLOCKABLE); - - spin_lock_irq(¤t->sighand->siglock); - saveset = current->blocked; - current->blocked = newset; - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); - - regs.eax = -EINTR; - while (1) { - current->state = TASK_INTERRUPTIBLE; - schedule(); - if (do_signal(®s, &saveset)) - return -EINTR; - } + current->state = TASK_INTERRUPTIBLE; + schedule(); + set_thread_flag(TIF_RESTORE_SIGMASK); + return -ERESTARTNOHAND; } asmlinkage int @@ -433,11 +399,11 @@ static int setup_frame(int sig, struct k_sigaction *ka, current->comm, current->pid, frame, regs->eip, frame->pretcode); #endif - return 1; + return 0; give_sigsegv: force_sigsegv(sig, current); - return 0; + return -EFAULT; } static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, @@ -527,11 +493,11 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, current->comm, current->pid, frame, regs->eip, frame->pretcode); #endif - return 1; + return 0; give_sigsegv: force_sigsegv(sig, current); - return 0; + return -EFAULT; } /* @@ -581,7 +547,7 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, else ret = setup_frame(sig, ka, oldset, regs); - if (ret) { + if (ret == 0) { spin_lock_irq(¤t->sighand->siglock); sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); if (!(ka->sa.sa_flags & SA_NODEFER)) @@ -598,11 +564,12 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, * want to handle. Thus you cannot kill init even with a SIGKILL even by * mistake. */ -int fastcall do_signal(struct pt_regs *regs, sigset_t *oldset) +static void fastcall do_signal(struct pt_regs *regs) { siginfo_t info; int signr; struct k_sigaction ka; + sigset_t *oldset; /* * We want the common case to go fast, which @@ -613,12 +580,14 @@ int fastcall do_signal(struct pt_regs *regs, sigset_t *oldset) * CS suffices. */ if (!user_mode(regs)) - return 1; + return; if (try_to_freeze()) goto no_signal; - if (!oldset) + if (test_thread_flag(TIF_RESTORE_SIGMASK)) + oldset = ¤t->saved_sigmask; + else oldset = ¤t->blocked; signr = get_signal_to_deliver(&info, &ka, regs, NULL); @@ -628,38 +597,55 @@ int fastcall do_signal(struct pt_regs *regs, sigset_t *oldset) * have been cleared if the watchpoint triggered * inside the kernel. */ - if (unlikely(current->thread.debugreg[7])) { + if (unlikely(current->thread.debugreg[7])) set_debugreg(current->thread.debugreg[7], 7); - } /* Whee! Actually deliver the signal. */ - return handle_signal(signr, &info, &ka, oldset, regs); + if (handle_signal(signr, &info, &ka, oldset, regs) == 0) { + /* a signal was successfully delivered; the saved + * sigmask will have been stored in the signal frame, + * and will be restored by sigreturn, so we can simply + * clear the TIF_RESTORE_SIGMASK flag */ + if (test_thread_flag(TIF_RESTORE_SIGMASK)) + clear_thread_flag(TIF_RESTORE_SIGMASK); + } + + return; } - no_signal: +no_signal: /* Did we come from a system call? */ if (regs->orig_eax >= 0) { /* Restart the system call - no handlers present */ - if (regs->eax == -ERESTARTNOHAND || - regs->eax == -ERESTARTSYS || - regs->eax == -ERESTARTNOINTR) { + switch (regs->eax) { + case -ERESTARTNOHAND: + case -ERESTARTSYS: + case -ERESTARTNOINTR: regs->eax = regs->orig_eax; regs->eip -= 2; - } - if (regs->eax == -ERESTART_RESTARTBLOCK){ + break; + + case -ERESTART_RESTARTBLOCK: regs->eax = __NR_restart_syscall; regs->eip -= 2; + break; } } - return 0; + + /* if there's no signal to deliver, we just put the saved sigmask + * back */ + if (test_thread_flag(TIF_RESTORE_SIGMASK)) { + clear_thread_flag(TIF_RESTORE_SIGMASK); + sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); + } } /* * notification of userspace execution resumption - * - triggered by current->work.notify_resume + * - triggered by the TIF_WORK_MASK flags */ __attribute__((regparm(3))) -void do_notify_resume(struct pt_regs *regs, sigset_t *oldset, +void do_notify_resume(struct pt_regs *regs, void *_unused, __u32 thread_info_flags) { /* Pending single-step? */ @@ -667,9 +653,10 @@ void do_notify_resume(struct pt_regs *regs, sigset_t *oldset, regs->eflags |= TF_MASK; clear_thread_flag(TIF_SINGLESTEP); } + /* deal with pending signal delivery */ - if (thread_info_flags & _TIF_SIGPENDING) - do_signal(regs,oldset); + if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK)) + do_signal(regs); clear_thread_flag(TIF_IRET); } diff --git a/arch/i386/kernel/syscall_table.S b/arch/i386/kernel/syscall_table.S index 6ff3e524322..1b665928336 100644 --- a/arch/i386/kernel/syscall_table.S +++ b/arch/i386/kernel/syscall_table.S @@ -294,3 +294,18 @@ ENTRY(sys_call_table) .long sys_inotify_add_watch .long sys_inotify_rm_watch .long sys_migrate_pages + .long sys_openat /* 295 */ + .long sys_mkdirat + .long sys_mknodat + .long sys_fchownat + .long sys_futimesat + .long sys_newfstatat /* 300 */ + .long sys_unlinkat + .long sys_renameat + .long sys_linkat + .long sys_symlinkat + .long sys_readlinkat /* 305 */ + .long sys_fchmodat + .long sys_faccessat + .long sys_pselect6 + .long sys_ppoll diff --git a/arch/i386/mm/init.c b/arch/i386/mm/init.c index 7df494b51a5..2700f01994b 100644 --- a/arch/i386/mm/init.c +++ b/arch/i386/mm/init.c @@ -268,7 +268,7 @@ static void __init permanent_kmaps_init(pgd_t *pgd_base) pkmap_page_table = pte; } -static void __devinit free_new_highpage(struct page *page) +static void __meminit free_new_highpage(struct page *page) { set_page_count(page, 1); __free_page(page); diff --git a/arch/ia64/configs/gensparse_defconfig b/arch/ia64/configs/gensparse_defconfig index 1d07d8072ec..991c07b57c2 100644 --- a/arch/ia64/configs/gensparse_defconfig +++ b/arch/ia64/configs/gensparse_defconfig @@ -557,6 +557,7 @@ CONFIG_E100=m # CONFIG_DL2K is not set CONFIG_E1000=y # CONFIG_E1000_NAPI is not set +# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set # CONFIG_NS83820 is not set # CONFIG_HAMACHI is not set # CONFIG_YELLOWFIN is not set diff --git a/arch/ia64/configs/tiger_defconfig b/arch/ia64/configs/tiger_defconfig index b1e8f09e9fd..6859119bc9d 100644 --- a/arch/ia64/configs/tiger_defconfig +++ b/arch/ia64/configs/tiger_defconfig @@ -565,6 +565,7 @@ CONFIG_E100=m # CONFIG_DL2K is not set CONFIG_E1000=y # CONFIG_E1000_NAPI is not set +# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set # CONFIG_NS83820 is not set # CONFIG_HAMACHI is not set # CONFIG_YELLOWFIN is not set diff --git a/arch/ia64/configs/zx1_defconfig b/arch/ia64/configs/zx1_defconfig index 0856ca67dd5..53899dc8eb5 100644 --- a/arch/ia64/configs/zx1_defconfig +++ b/arch/ia64/configs/zx1_defconfig @@ -548,6 +548,7 @@ CONFIG_E100=y # CONFIG_DL2K is not set CONFIG_E1000=y # CONFIG_E1000_NAPI is not set +# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set # CONFIG_NS83820 is not set # CONFIG_HAMACHI is not set # CONFIG_YELLOWFIN is not set diff --git a/arch/ia64/defconfig b/arch/ia64/defconfig index 275a26c6e5a..dcbc78a4cfa 100644 --- a/arch/ia64/defconfig +++ b/arch/ia64/defconfig @@ -565,6 +565,7 @@ CONFIG_E100=m # CONFIG_DL2K is not set CONFIG_E1000=y # CONFIG_E1000_NAPI is not set +# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set # CONFIG_NS83820 is not set # CONFIG_HAMACHI is not set # CONFIG_YELLOWFIN is not set diff --git a/arch/ia64/ia32/sys_ia32.c b/arch/ia64/ia32/sys_ia32.c index 3945d378bd7..70dba1f0e2e 100644 --- a/arch/ia64/ia32/sys_ia32.c +++ b/arch/ia64/ia32/sys_ia32.c @@ -52,9 +52,9 @@ #include <linux/compat.h> #include <linux/vfs.h> #include <linux/mman.h> +#include <linux/mutex.h> #include <asm/intrinsics.h> -#include <asm/semaphore.h> #include <asm/types.h> #include <asm/uaccess.h> #include <asm/unistd.h> @@ -86,7 +86,7 @@ * while doing so. */ /* XXX make per-mm: */ -static DECLARE_MUTEX(ia32_mmap_sem); +static DEFINE_MUTEX(ia32_mmap_mutex); asmlinkage long sys32_execve (char __user *name, compat_uptr_t __user *argv, compat_uptr_t __user *envp, @@ -895,11 +895,11 @@ ia32_do_mmap (struct file *file, unsigned long addr, unsigned long len, int prot prot = get_prot32(prot); #if PAGE_SHIFT > IA32_PAGE_SHIFT - down(&ia32_mmap_sem); + mutex_lock(&ia32_mmap_mutex); { addr = emulate_mmap(file, addr, len, prot, flags, offset); } - up(&ia32_mmap_sem); + mutex_unlock(&ia32_mmap_mutex); #else down_write(¤t->mm->mmap_sem); { @@ -1000,11 +1000,9 @@ sys32_munmap (unsigned int start, unsigned int len) if (start >= end) return 0; - down(&ia32_mmap_sem); - { - ret = sys_munmap(start, end - start); - } - up(&ia32_mmap_sem); + mutex_lock(&ia32_mmap_mutex); + ret = sys_munmap(start, end - start); + mutex_unlock(&ia32_mmap_mutex); #endif return ret; } @@ -1056,7 +1054,7 @@ sys32_mprotect (unsigned int start, unsigned int len, int prot) if (retval < 0) return retval; - down(&ia32_mmap_sem); + mutex_lock(&ia32_mmap_mutex); { if (offset_in_page(start)) { /* start address is 4KB aligned but not page aligned. */ @@ -1080,7 +1078,7 @@ sys32_mprotect (unsigned int start, unsigned int len, int prot) retval = sys_mprotect(start, end - start, prot); } out: - up(&ia32_mmap_sem); + mutex_unlock(&ia32_mmap_mutex); return retval; #endif } @@ -1124,11 +1122,9 @@ sys32_mremap (unsigned int addr, unsigned int old_len, unsigned int new_len, old_len = PAGE_ALIGN(old_end) - addr; new_len = PAGE_ALIGN(new_end) - addr; - down(&ia32_mmap_sem); - { - ret = sys_mremap(addr, old_len, new_len, flags, new_addr); - } - up(&ia32_mmap_sem); + mutex_lock(&ia32_mmap_mutex); + ret = sys_mremap(addr, old_len, new_len, flags, new_addr); + mutex_unlock(&ia32_mmap_mutex); if ((ret >= 0) && (old_len < new_len)) { /* mremap expanded successfully */ diff --git a/arch/ia64/kernel/mca_asm.S b/arch/ia64/kernel/mca_asm.S index 403a80a58c1..60a464bfd9e 100644 --- a/arch/ia64/kernel/mca_asm.S +++ b/arch/ia64/kernel/mca_asm.S @@ -512,7 +512,7 @@ ia64_state_save: st8 [temp1]=r12 // os_status, default is cold boot mov r6=IA64_MCA_SAME_CONTEXT ;; - st8 [temp1]=r6 // context, default is same context + st8 [temp2]=r6 // context, default is same context // Save the pt_regs data that is not in minstate. The previous code // left regs at sos. diff --git a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c index bd87cb6b7a8..9c5194b385d 100644 --- a/arch/ia64/kernel/perfmon.c +++ b/arch/ia64/kernel/perfmon.c @@ -40,6 +40,7 @@ #include <linux/bitops.h> #include <linux/capability.h> #include <linux/rcupdate.h> +#include <linux/completion.h> #include <asm/errno.h> #include <asm/intrinsics.h> @@ -286,7 +287,7 @@ typedef struct pfm_context { unsigned long ctx_ovfl_regs[4]; /* which registers overflowed (notification) */ - struct semaphore ctx_restart_sem; /* use for blocking notification mode */ + struct completion ctx_restart_done; /* use for blocking notification mode */ unsigned long ctx_used_pmds[4]; /* bitmask of PMD used */ unsigned long ctx_all_pmds[4]; /* bitmask of all accessible PMDs */ @@ -628,9 +629,11 @@ static int pfm_write_ibr_dbr(int mode, pfm_context_t *ctx, void *arg, int count, #include "perfmon_itanium.h" #include "perfmon_mckinley.h" +#include "perfmon_montecito.h" #include "perfmon_generic.h" static pmu_config_t *pmu_confs[]={ + &pmu_conf_mont, &pmu_conf_mck, &pmu_conf_ita, &pmu_conf_gen, /* must be last */ @@ -1989,7 +1992,7 @@ pfm_close(struct inode *inode, struct file *filp) /* * force task to wake up from MASKED state */ - up(&ctx->ctx_restart_sem); + complete(&ctx->ctx_restart_done); DPRINT(("waking up ctx_state=%d\n", state)); @@ -2704,7 +2707,7 @@ pfm_context_create(pfm_context_t *ctx, void *arg, int count, struct pt_regs *reg /* * init restart semaphore to locked */ - sema_init(&ctx->ctx_restart_sem, 0); + init_completion(&ctx->ctx_restart_done); /* * activation is used in SMP only @@ -3685,7 +3688,7 @@ pfm_restart(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs) */ if (CTX_OVFL_NOBLOCK(ctx) == 0 && state == PFM_CTX_MASKED) { DPRINT(("unblocking [%d] \n", task->pid)); - up(&ctx->ctx_restart_sem); + complete(&ctx->ctx_restart_done); } else { DPRINT(("[%d] armed exit trap\n", task->pid)); @@ -5087,7 +5090,7 @@ pfm_handle_work(void) * may go through without blocking on SMP systems * if restart has been received already by the time we call down() */ - ret = down_interruptible(&ctx->ctx_restart_sem); + ret = wait_for_completion_interruptible(&ctx->ctx_restart_done); DPRINT(("after block sleeping ret=%d\n", ret)); diff --git a/arch/ia64/kernel/perfmon_montecito.h b/arch/ia64/kernel/perfmon_montecito.h new file mode 100644 index 00000000000..cd06ac6a686 --- /dev/null +++ b/arch/ia64/kernel/perfmon_montecito.h @@ -0,0 +1,269 @@ +/* + * This file contains the Montecito PMU register description tables + * and pmc checker used by perfmon.c. + * + * Copyright (c) 2005-2006 Hewlett-Packard Development Company, L.P. + * Contributed by Stephane Eranian <eranian@hpl.hp.com> + */ +static int pfm_mont_pmc_check(struct task_struct *task, pfm_context_t *ctx, unsigned int cnum, unsigned long *val, struct pt_regs *regs); + +#define RDEP_MONT_ETB (RDEP(38)|RDEP(39)|RDEP(48)|RDEP(49)|RDEP(50)|RDEP(51)|RDEP(52)|RDEP(53)|RDEP(54)|\ + RDEP(55)|RDEP(56)|RDEP(57)|RDEP(58)|RDEP(59)|RDEP(60)|RDEP(61)|RDEP(62)|RDEP(63)) +#define RDEP_MONT_DEAR (RDEP(32)|RDEP(33)|RDEP(36)) +#define RDEP_MONT_IEAR (RDEP(34)|RDEP(35)) + +static pfm_reg_desc_t pfm_mont_pmc_desc[PMU_MAX_PMCS]={ +/* pmc0 */ { PFM_REG_CONTROL , 0, 0x0, -1, NULL, NULL, {0,0, 0, 0}, {0,0, 0, 0}}, +/* pmc1 */ { PFM_REG_CONTROL , 0, 0x0, -1, NULL, NULL, {0,0, 0, 0}, {0,0, 0, 0}}, +/* pmc2 */ { PFM_REG_CONTROL , 0, 0x0, -1, NULL, NULL, {0,0, 0, 0}, {0,0, 0, 0}}, +/* pmc3 */ { PFM_REG_CONTROL , 0, 0x0, -1, NULL, NULL, {0,0, 0, 0}, {0,0, 0, 0}}, +/* pmc4 */ { PFM_REG_COUNTING, 6, 0x2000000, 0x7c7fff7f, NULL, pfm_mont_pmc_check, {RDEP(4),0, 0, 0}, {0,0, 0, 0}}, +/* pmc5 */ { PFM_REG_COUNTING, 6, 0x2000000, 0x7c7fff7f, NULL, pfm_mont_pmc_check, {RDEP(5),0, 0, 0}, {0,0, 0, 0}}, +/* pmc6 */ { PFM_REG_COUNTING, 6, 0x2000000, 0x7c7fff7f, NULL, pfm_mont_pmc_check, {RDEP(6),0, 0, 0}, {0,0, 0, 0}}, +/* pmc7 */ { PFM_REG_COUNTING, 6, 0x2000000, 0x7c7fff7f, NULL, pfm_mont_pmc_check, {RDEP(7),0, 0, 0}, {0,0, 0, 0}}, +/* pmc8 */ { PFM_REG_COUNTING, 6, 0x2000000, 0x7c7fff7f, NULL, pfm_mont_pmc_check, {RDEP(8),0, 0, 0}, {0,0, 0, 0}}, +/* pmc9 */ { PFM_REG_COUNTING, 6, 0x2000000, 0x7c7fff7f, NULL, pfm_mont_pmc_check, {RDEP(9),0, 0, 0}, {0,0, 0, 0}}, +/* pmc10 */ { PFM_REG_COUNTING, 6, 0x2000000, 0x7c7fff7f, NULL, pfm_mont_pmc_check, {RDEP(10),0, 0, 0}, {0,0, 0, 0}}, +/* pmc11 */ { PFM_REG_COUNTING, 6, 0x2000000, 0x7c7fff7f, NULL, pfm_mont_pmc_check, {RDEP(11),0, 0, 0}, {0,0, 0, 0}}, +/* pmc12 */ { PFM_REG_COUNTING, 6, 0x2000000, 0x7c7fff7f, NULL, pfm_mont_pmc_check, {RDEP(12),0, 0, 0}, {0,0, 0, 0}}, +/* pmc13 */ { PFM_REG_COUNTING, 6, 0x2000000, 0x7c7fff7f, NULL, pfm_mont_pmc_check, {RDEP(13),0, 0, 0}, {0,0, 0, 0}}, +/* pmc14 */ { PFM_REG_COUNTING, 6, 0x2000000, 0x7c7fff7f, NULL, pfm_mont_pmc_check, {RDEP(14),0, 0, 0}, {0,0, 0, 0}}, +/* pmc15 */ { PFM_REG_COUNTING, 6, 0x2000000, 0x7c7fff7f, NULL, pfm_mont_pmc_check, {RDEP(15),0, 0, 0}, {0,0, 0, 0}}, +/* pmc16 */ { PFM_REG_NOTIMPL, }, +/* pmc17 */ { PFM_REG_NOTIMPL, }, +/* pmc18 */ { PFM_REG_NOTIMPL, }, +/* pmc19 */ { PFM_REG_NOTIMPL, }, +/* pmc20 */ { PFM_REG_NOTIMPL, }, +/* pmc21 */ { PFM_REG_NOTIMPL, }, +/* pmc22 */ { PFM_REG_NOTIMPL, }, +/* pmc23 */ { PFM_REG_NOTIMPL, }, +/* pmc24 */ { PFM_REG_NOTIMPL, }, +/* pmc25 */ { PFM_REG_NOTIMPL, }, +/* pmc26 */ { PFM_REG_NOTIMPL, }, +/* pmc27 */ { PFM_REG_NOTIMPL, }, +/* pmc28 */ { PFM_REG_NOTIMPL, }, +/* pmc29 */ { PFM_REG_NOTIMPL, }, +/* pmc30 */ { PFM_REG_NOTIMPL, }, +/* pmc31 */ { PFM_REG_NOTIMPL, }, +/* pmc32 */ { PFM_REG_CONFIG, 0, 0x30f01ffffffffff, 0x30f01ffffffffff, NULL, pfm_mont_pmc_check, {0,0, 0, 0}, {0,0, 0, 0}}, +/* pmc33 */ { PFM_REG_CONFIG, 0, 0x0, 0x1ffffffffff, NULL, pfm_mont_pmc_check, {0,0, 0, 0}, {0,0, 0, 0}}, +/* pmc34 */ { PFM_REG_CONFIG, 0, 0xf01ffffffffff, 0xf01ffffffffff, NULL, pfm_mont_pmc_check, {0,0, 0, 0}, {0,0, 0, 0}}, +/* pmc35 */ { PFM_REG_CONFIG, 0, 0x0, 0x1ffffffffff, NULL, pfm_mont_pmc_check, {0,0, 0, 0}, {0,0, 0, 0}}, +/* pmc36 */ { PFM_REG_CONFIG, 0, 0xfffffff0, 0xf, NULL, pfm_mont_pmc_check, {0,0, 0, 0}, {0,0, 0, 0}}, +/* pmc37 */ { PFM_REG_MONITOR, 4, 0x0, 0x3fff, NULL, pfm_mont_pmc_check, {RDEP_MONT_IEAR, 0, 0, 0}, {0, 0, 0, 0}}, +/* pmc38 */ { PFM_REG_CONFIG, 0, 0xdb6, 0x2492, NULL, pfm_mont_pmc_check, {0,0, 0, 0}, {0,0, 0, 0}}, +/* pmc39 */ { PFM_REG_MONITOR, 6, 0x0, 0xffcf, NULL, pfm_mont_pmc_check, {RDEP_MONT_ETB,0, 0, 0}, {0,0, 0, 0}}, +/* pmc40 */ { PFM_REG_MONITOR, 6, 0x2000000, 0xf01cf, NULL, pfm_mont_pmc_check, {RDEP_MONT_DEAR,0, 0, 0}, {0,0, 0, 0}}, +/* pmc41 */ { PFM_REG_CONFIG, 0, 0x00002078fefefefe, 0x1e00018181818, NULL, pfm_mont_pmc_check, {0,0, 0, 0}, {0,0, 0, 0}}, +/* pmc42 */ { PFM_REG_MONITOR, 6, 0x0, 0x7ff4f, NULL, pfm_mont_pmc_check, {RDEP_MONT_ETB,0, 0, 0}, {0,0, 0, 0}}, + { PFM_REG_END , 0, 0x0, -1, NULL, NULL, {0,}, {0,}}, /* end marker */ +}; + +static pfm_reg_desc_t pfm_mont_pmd_desc[PMU_MAX_PMDS]={ +/* pmd0 */ { PFM_REG_NOTIMPL, }, +/* pmd1 */ { PFM_REG_NOTIMPL, }, +/* pmd2 */ { PFM_REG_NOTIMPL, }, +/* pmd3 */ { PFM_REG_NOTIMPL, }, +/* pmd4 */ { PFM_REG_COUNTING, 0, 0x0, -1, NULL, NULL, {0,0, 0, 0}, {RDEP(4),0, 0, 0}}, +/* pmd5 */ { PFM_REG_COUNTING, 0, 0x0, -1, NULL, NULL, {0,0, 0, 0}, {RDEP(5),0, 0, 0}}, +/* pmd6 */ { PFM_REG_COUNTING, 0, 0x0, -1, NULL, NULL, {0,0, 0, 0}, {RDEP(6),0, 0, 0}}, +/* pmd7 */ { PFM_REG_COUNTING, 0, 0x0, -1, NULL, NULL, {0,0, 0, 0}, {RDEP(7),0, 0, 0}}, +/* pmd8 */ { PFM_REG_COUNTING, 0, 0x0, -1, NULL, NULL, {0,0, 0, 0}, {RDEP(8),0, 0, 0}}, +/* pmd9 */ { PFM_REG_COUNTING, 0, 0x0, -1, NULL, NULL, {0,0, 0, 0}, {RDEP(9),0, 0, 0}}, +/* pmd10 */ { PFM_REG_COUNTING, 0, 0x0, -1, NULL, NULL, {0,0, 0, 0}, {RDEP(10),0, 0, 0}}, +/* pmd11 */ { PFM_REG_COUNTING, 0, 0x0, -1, NULL, NULL, {0,0, 0, 0}, {RDEP(11),0, 0, 0}}, +/* pmd12 */ { PFM_REG_COUNTING, 0, 0x0, -1, NULL, NULL, {0,0, 0, 0}, {RDEP(12),0, 0, 0}}, +/* pmd13 */ { PFM_REG_COUNTING, 0, 0x0, -1, NULL, NULL, {0,0, 0, 0}, {RDEP(13),0, 0, 0}}, +/* pmd14 */ { PFM_REG_COUNTING, 0, 0x0, -1, NULL, NULL, {0,0, 0, 0}, {RDEP(14),0, 0, 0}}, +/* pmd15 */ { PFM_REG_COUNTING, 0, 0x0, -1, NULL, NULL, {0,0, 0, 0}, {RDEP(15),0, 0, 0}}, +/* pmd16 */ { PFM_REG_NOTIMPL, }, +/* pmd17 */ { PFM_REG_NOTIMPL, }, +/* pmd18 */ { PFM_REG_NOTIMPL, }, +/* pmd19 */ { PFM_REG_NOTIMPL, }, +/* pmd20 */ { PFM_REG_NOTIMPL, }, +/* pmd21 */ { PFM_REG_NOTIMPL, }, +/* pmd22 */ { PFM_REG_NOTIMPL, }, +/* pmd23 */ { PFM_REG_NOTIMPL, }, +/* pmd24 */ { PFM_REG_NOTIMPL, }, +/* pmd25 */ { PFM_REG_NOTIMPL, }, +/* pmd26 */ { PFM_REG_NOTIMPL, }, +/* pmd27 */ { PFM_REG_NOTIMPL, }, +/* pmd28 */ { PFM_REG_NOTIMPL, }, +/* pmd29 */ { PFM_REG_NOTIMPL, }, +/* pmd30 */ { PFM_REG_NOTIMPL, }, +/* pmd31 */ { PFM_REG_NOTIMPL, }, +/* pmd32 */ { PFM_REG_BUFFER, 0, 0x0, -1, NULL, NULL, {RDEP(33)|RDEP(36),0, 0, 0}, {RDEP(40),0, 0, 0}}, +/* pmd33 */ { PFM_REG_BUFFER, 0, 0x0, -1, NULL, NULL, {RDEP(32)|RDEP(36),0, 0, 0}, {RDEP(40),0, 0, 0}}, +/* pmd34 */ { PFM_REG_BUFFER, 0, 0x0, -1, NULL, NULL, {RDEP(35),0, 0, 0}, {RDEP(37),0, 0, 0}}, +/* pmd35 */ { PFM_REG_BUFFER, 0, 0x0, -1, NULL, NULL, {RDEP(34),0, 0, 0}, {RDEP(37),0, 0, 0}}, +/* pmd36 */ { PFM_REG_BUFFER, 0, 0x0, -1, NULL, NULL, {RDEP(32)|RDEP(33),0, 0, 0}, {RDEP(40),0, 0, 0}}, +/* pmd37 */ { PFM_REG_NOTIMPL, }, +/* pmd38 */ { PFM_REG_BUFFER, 0, 0x0, -1, NULL, NULL, {RDEP_MONT_ETB,0, 0, 0}, {RDEP(39),0, 0, 0}}, +/* pmd39 */ { PFM_REG_BUFFER, 0, 0x0, -1, NULL, NULL, {RDEP_MONT_ETB,0, 0, 0}, {RDEP(39),0, 0, 0}}, +/* pmd40 */ { PFM_REG_NOTIMPL, }, +/* pmd41 */ { PFM_REG_NOTIMPL, }, +/* pmd42 */ { PFM_REG_NOTIMPL, }, +/* pmd43 */ { PFM_REG_NOTIMPL, }, +/* pmd44 */ { PFM_REG_NOTIMPL, }, +/* pmd45 */ { PFM_REG_NOTIMPL, }, +/* pmd46 */ { PFM_REG_NOTIMPL, }, +/* pmd47 */ { PFM_REG_NOTIMPL, }, +/* pmd48 */ { PFM_REG_BUFFER, 0, 0x0, -1, NULL, NULL, {RDEP_MONT_ETB,0, 0, 0}, {RDEP(39),0, 0, 0}}, +/* pmd49 */ { PFM_REG_BUFFER, 0, 0x0, -1, NULL, NULL, {RDEP_MONT_ETB,0, 0, 0}, {RDEP(39),0, 0, 0}}, +/* pmd50 */ { PFM_REG_BUFFER, 0, 0x0, -1, NULL, NULL, {RDEP_MONT_ETB,0, 0, 0}, {RDEP(39),0, 0, 0}}, +/* pmd51 */ { PFM_REG_BUFFER, 0, 0x0, -1, NULL, NULL, {RDEP_MONT_ETB,0, 0, 0}, {RDEP(39),0, 0, 0}}, +/* pmd52 */ { PFM_REG_BUFFER, 0, 0x0, -1, NULL, NULL, {RDEP_MONT_ETB,0, 0, 0}, {RDEP(39),0, 0, 0}}, +/* pmd53 */ { PFM_REG_BUFFER, 0, 0x0, -1, NULL, NULL, {RDEP_MONT_ETB,0, 0, 0}, {RDEP(39),0, 0, 0}}, +/* pmd54 */ { PFM_REG_BUFFER, 0, 0x0, -1, NULL, NULL, {RDEP_MONT_ETB,0, 0, 0}, {RDEP(39),0, 0, 0}}, +/* pmd55 */ { PFM_REG_BUFFER, 0, 0x0, -1, NULL, NULL, {RDEP_MONT_ETB,0, 0, 0}, {RDEP(39),0, 0, 0}}, +/* pmd56 */ { PFM_REG_BUFFER, 0, 0x0, -1, NULL, NULL, {RDEP_MONT_ETB,0, 0, 0}, {RDEP(39),0, 0, 0}}, +/* pmd57 */ { PFM_REG_BUFFER, 0, 0x0, -1, NULL, NULL, {RDEP_MONT_ETB,0, 0, 0}, {RDEP(39),0, 0, 0}}, +/* pmd58 */ { PFM_REG_BUFFER, 0, 0x0, -1, NULL, NULL, {RDEP_MONT_ETB,0, 0, 0}, {RDEP(39),0, 0, 0}}, +/* pmd59 */ { PFM_REG_BUFFER, 0, 0x0, -1, NULL, NULL, {RDEP_MONT_ETB,0, 0, 0}, {RDEP(39),0, 0, 0}}, +/* pmd60 */ { PFM_REG_BUFFER, 0, 0x0, -1, NULL, NULL, {RDEP_MONT_ETB,0, 0, 0}, {RDEP(39),0, 0, 0}}, +/* pmd61 */ { PFM_REG_BUFFER, 0, 0x0, -1, NULL, NULL, {RDEP_MONT_ETB,0, 0, 0}, {RDEP(39),0, 0, 0}}, +/* pmd62 */ { PFM_REG_BUFFER, 0, 0x0, -1, NULL, NULL, {RDEP_MONT_ETB,0, 0, 0}, {RDEP(39),0, 0, 0}}, +/* pmd63 */ { PFM_REG_BUFFER, 0, 0x0, -1, NULL, NULL, {RDEP_MONT_ETB,0, 0, 0}, {RDEP(39),0, 0, 0}}, + { PFM_REG_END , 0, 0x0, -1, NULL, NULL, {0,}, {0,}}, /* end marker */ +}; + +/* + * PMC reserved fields must have their power-up values preserved + */ +static int +pfm_mont_reserved(unsigned int cnum, unsigned long *val, struct pt_regs *regs) +{ + unsigned long tmp1, tmp2, ival = *val; + + /* remove reserved areas from user value */ + tmp1 = ival & PMC_RSVD_MASK(cnum); + + /* get reserved fields values */ + tmp2 = PMC_DFL_VAL(cnum) & ~PMC_RSVD_MASK(cnum); + + *val = tmp1 | tmp2; + + DPRINT(("pmc[%d]=0x%lx, mask=0x%lx, reset=0x%lx, val=0x%lx\n", + cnum, ival, PMC_RSVD_MASK(cnum), PMC_DFL_VAL(cnum), *val)); + return 0; +} + +/* + * task can be NULL if the context is unloaded + */ +static int +pfm_mont_pmc_check(struct task_struct *task, pfm_context_t *ctx, unsigned int cnum, unsigned long *val, struct pt_regs *regs) +{ + int ret = 0; + unsigned long val32 = 0, val38 = 0, val41 = 0; + unsigned long tmpval; + int check_case1 = 0; + int is_loaded; + + /* first preserve the reserved fields */ + pfm_mont_reserved(cnum, val, regs); + + tmpval = *val; + + /* sanity check */ + if (ctx == NULL) return -EINVAL; + + is_loaded = ctx->ctx_state == PFM_CTX_LOADED || ctx->ctx_state == PFM_CTX_MASKED; + + /* + * we must clear the debug registers if pmc41 has a value which enable + * memory pipeline event constraints. In this case we need to clear the + * the debug registers if they have not yet been accessed. This is required + * to avoid picking stale state. + * PMC41 is "active" if: + * one of the pmc41.cfg_dtagXX field is different from 0x3 + * AND + * at the corresponding pmc41.en_dbrpXX is set. + * AND + * ctx_fl_using_dbreg == 0 (i.e., dbr not yet used) + */ + DPRINT(("cnum=%u val=0x%lx, using_dbreg=%d loaded=%d\n", cnum, tmpval, ctx->ctx_fl_using_dbreg, is_loaded)); + + if (cnum == 41 && is_loaded + && (tmpval & 0x1e00000000000) && (tmpval & 0x18181818UL) != 0x18181818UL && ctx->ctx_fl_using_dbreg == 0) { + + DPRINT(("pmc[%d]=0x%lx has active pmc41 settings, clearing dbr\n", cnum, tmpval)); + + /* don't mix debug with perfmon */ + if (task && (task->thread.flags & IA64_THREAD_DBG_VALID) != 0) return -EINVAL; + + /* + * a count of 0 will mark the debug registers if: + * AND + */ + ret = pfm_write_ibr_dbr(PFM_DATA_RR, ctx, NULL, 0, regs); + if (ret) return ret; + } + /* + * we must clear the (instruction) debug registers if: + * pmc38.ig_ibrpX is 0 (enabled) + * AND + * ctx_fl_using_dbreg == 0 (i.e., dbr not yet used) + */ + if (cnum == 38 && is_loaded && ((tmpval & 0x492UL) != 0x492UL) && ctx->ctx_fl_using_dbreg == 0) { + + DPRINT(("pmc38=0x%lx has active pmc38 settings, clearing ibr\n", tmpval)); + + /* don't mix debug with perfmon */ + if (task && (task->thread.flags & IA64_THREAD_DBG_VALID) != 0) return -EINVAL; + + /* + * a count of 0 will mark the debug registers as in use and also + * ensure that they are properly cleared. + */ + ret = pfm_write_ibr_dbr(PFM_CODE_RR, ctx, NULL, 0, regs); + if (ret) return ret; + + } + switch(cnum) { + case 32: val32 = *val; + val38 = ctx->ctx_pmcs[38]; + val41 = ctx->ctx_pmcs[41]; + check_case1 = 1; + break; + case 38: val38 = *val; + val32 = ctx->ctx_pmcs[32]; + val41 = ctx->ctx_pmcs[41]; + check_case1 = 1; + break; + case 41: val41 = *val; + val32 = ctx->ctx_pmcs[32]; + val38 = ctx->ctx_pmcs[38]; + check_case1 = 1; + break; + } + /* check illegal configuration which can produce inconsistencies in tagging + * i-side events in L1D and L2 caches + */ + if (check_case1) { + ret = (((val41 >> 45) & 0xf) == 0 && ((val32>>57) & 0x1) == 0) + && ((((val38>>1) & 0x3) == 0x2 || ((val38>>1) & 0x3) == 0) + || (((val38>>4) & 0x3) == 0x2 || ((val38>>4) & 0x3) == 0)); + if (ret) { + DPRINT(("invalid config pmc38=0x%lx pmc41=0x%lx pmc32=0x%lx\n", val38, val41, val32)); + return -EINVAL; + } + } + *val = tmpval; + return 0; +} + +/* + * impl_pmcs, impl_pmds are computed at runtime to minimize errors! + */ +static pmu_config_t pmu_conf_mont={ + .pmu_name = "Montecito", + .pmu_family = 0x20, + .flags = PFM_PMU_IRQ_RESEND, + .ovfl_val = (1UL << 47) - 1, + .pmd_desc = pfm_mont_pmd_desc, + .pmc_desc = pfm_mont_pmc_desc, + .num_ibrs = 8, + .num_dbrs = 8, + .use_rr_dbregs = 1 /* debug register are use for range retrictions */ +}; diff --git a/arch/ia64/kernel/unaligned.c b/arch/ia64/kernel/unaligned.c index 43b45b65ee5..f9e0ae936d1 100644 --- a/arch/ia64/kernel/unaligned.c +++ b/arch/ia64/kernel/unaligned.c @@ -1283,8 +1283,9 @@ within_logging_rate_limit (void) if (jiffies - last_time > 5*HZ) count = 0; - if (++count < 5) { + if (count < 5) { last_time = jiffies; + count++; return 1; } return 0; diff --git a/arch/ia64/kernel/uncached.c b/arch/ia64/kernel/uncached.c index b631cf86ed4..fcd2bad0286 100644 --- a/arch/ia64/kernel/uncached.c +++ b/arch/ia64/kernel/uncached.c @@ -210,6 +210,7 @@ uncached_build_memmap(unsigned long start, unsigned long end, void *arg) dprintk(KERN_ERR "uncached_build_memmap(%lx %lx)\n", start, end); + touch_softlockup_watchdog(); memset((char *)start, 0, length); node = paddr_to_nid(start - __IA64_UNCACHED_OFFSET); diff --git a/arch/ia64/mm/init.c b/arch/ia64/mm/init.c index e3215ba64ff..b38b6d213c1 100644 --- a/arch/ia64/mm/init.c +++ b/arch/ia64/mm/init.c @@ -635,3 +635,39 @@ mem_init (void) ia32_mem_init(); #endif } + +#ifdef CONFIG_MEMORY_HOTPLUG +void online_page(struct page *page) +{ + ClearPageReserved(page); + set_page_count(page, 1); + __free_page(page); + totalram_pages++; + num_physpages++; +} + +int add_memory(u64 start, u64 size) +{ + pg_data_t *pgdat; + struct zone *zone; + unsigned long start_pfn = start >> PAGE_SHIFT; + unsigned long nr_pages = size >> PAGE_SHIFT; + int ret; + + pgdat = NODE_DATA(0); + + zone = pgdat->node_zones + ZONE_NORMAL; + ret = __add_pages(zone, start_pfn, nr_pages); + + if (ret) + printk("%s: Problem encountered in __add_pages() as ret=%d\n", + __FUNCTION__, ret); + + return ret; +} + +int remove_memory(u64 start, u64 size) +{ + return -EINVAL; +} +#endif diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c index 30dbc98bf0b..d27ecdcb6fc 100644 --- a/arch/ia64/pci/pci.c +++ b/arch/ia64/pci/pci.c @@ -454,14 +454,13 @@ static int __devinit is_valid_resource(struct pci_dev *dev, int idx) return 0; } -static void __devinit pcibios_fixup_device_resources(struct pci_dev *dev) +static void __devinit +pcibios_fixup_resources(struct pci_dev *dev, int start, int limit) { struct pci_bus_region region; int i; - int limit = (dev->hdr_type == PCI_HEADER_TYPE_NORMAL) ? \ - PCI_BRIDGE_RESOURCES : PCI_NUM_RESOURCES; - for (i = 0; i < limit; i++) { + for (i = start; i < limit; i++) { if (!dev->resource[i].flags) continue; region.start = dev->resource[i].start; @@ -472,6 +471,16 @@ static void __devinit pcibios_fixup_device_resources(struct pci_dev *dev) } } +static void __devinit pcibios_fixup_device_resources(struct pci_dev *dev) +{ + pcibios_fixup_resources(dev, 0, PCI_BRIDGE_RESOURCES); +} + +static void __devinit pcibios_fixup_bridge_resources(struct pci_dev *dev) +{ + pcibios_fixup_resources(dev, PCI_BRIDGE_RESOURCES, PCI_NUM_RESOURCES); +} + /* * Called after each bus is probed, but before its children are examined. */ @@ -482,7 +491,7 @@ pcibios_fixup_bus (struct pci_bus *b) if (b->self) { pci_read_bridge_bases(b); - pcibios_fixup_device_resources(b->self); + pcibios_fixup_bridge_resources(b->self); } list_for_each_entry(dev, &b->devices, bus_list) pcibios_fixup_device_resources(dev); diff --git a/arch/ia64/sn/include/xtalk/hubdev.h b/arch/ia64/sn/include/xtalk/hubdev.h index 4d417c30120..8182583c762 100644 --- a/arch/ia64/sn/include/xtalk/hubdev.h +++ b/arch/ia64/sn/include/xtalk/hubdev.h @@ -40,8 +40,8 @@ struct sn_flush_device_common { unsigned long sfdl_force_int_addr; unsigned long sfdl_flush_value; volatile unsigned long *sfdl_flush_addr; - uint32_t sfdl_persistent_busnum; - uint32_t sfdl_persistent_segment; + u32 sfdl_persistent_busnum; + u32 sfdl_persistent_segment; struct pcibus_info *sfdl_pcibus_info; }; @@ -51,12 +51,21 @@ struct sn_flush_device_kernel { struct sn_flush_device_common *common; }; +/* 01/16/06 This struct is the old PROM/kernel struct and needs to be included + * for older official PROMs to function on the new kernel base. This struct + * will be removed when the next official PROM release occurs. */ + +struct sn_flush_device_war { + struct sn_flush_device_common common; + u32 filler; /* older PROMs expect the default size of a spinlock_t */ +}; + /* * **widget_p - Used as an array[wid_num][device] of sn_flush_device_kernel. */ struct sn_flush_nasid_entry { struct sn_flush_device_kernel **widget_p; // Used as an array of wid_num - uint64_t iio_itte[8]; + u64 iio_itte[8]; }; struct hubdev_info { @@ -70,8 +79,8 @@ struct hubdev_info { void *hdi_nodepda; void *hdi_node_vertex; - uint32_t max_segment_number; - uint32_t max_pcibus_number; + u32 max_segment_number; + u32 max_pcibus_number; }; extern void hubdev_init_node(nodepda_t *, cnodeid_t); diff --git a/arch/ia64/sn/include/xtalk/xbow.h b/arch/ia64/sn/include/xtalk/xbow.h index ec56b3432f1..90f37a4133d 100644 --- a/arch/ia64/sn/include/xtalk/xbow.h +++ b/arch/ia64/sn/include/xtalk/xbow.h @@ -3,7 +3,8 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 1992-1997,2000-2004 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (C) 1992-1997,2000-2006 Silicon Graphics, Inc. All Rights + * Reserved. */ #ifndef _ASM_IA64_SN_XTALK_XBOW_H #define _ASM_IA64_SN_XTALK_XBOW_H @@ -21,94 +22,94 @@ /* Register set for each xbow link */ typedef volatile struct xb_linkregs_s { -/* +/* * we access these through synergy unswizzled space, so the address * gets twiddled (i.e. references to 0x4 actually go to 0x0 and vv.) * That's why we put the register first and filler second. */ - uint32_t link_ibf; - uint32_t filler0; /* filler for proper alignment */ - uint32_t link_control; - uint32_t filler1; - uint32_t link_status; - uint32_t filler2; - uint32_t link_arb_upper; - uint32_t filler3; - uint32_t link_arb_lower; - uint32_t filler4; - uint32_t link_status_clr; - uint32_t filler5; - uint32_t link_reset; - uint32_t filler6; - uint32_t link_aux_status; - uint32_t filler7; + u32 link_ibf; + u32 filler0; /* filler for proper alignment */ + u32 link_control; + u32 filler1; + u32 link_status; + u32 filler2; + u32 link_arb_upper; + u32 filler3; + u32 link_arb_lower; + u32 filler4; + u32 link_status_clr; + u32 filler5; + u32 link_reset; + u32 filler6; + u32 link_aux_status; + u32 filler7; } xb_linkregs_t; typedef volatile struct xbow_s { - /* standard widget configuration 0x000000-0x000057 */ - struct widget_cfg xb_widget; /* 0x000000 */ - - /* helper fieldnames for accessing bridge widget */ - -#define xb_wid_id xb_widget.w_id -#define xb_wid_stat xb_widget.w_status -#define xb_wid_err_upper xb_widget.w_err_upper_addr -#define xb_wid_err_lower xb_widget.w_err_lower_addr -#define xb_wid_control xb_widget.w_control -#define xb_wid_req_timeout xb_widget.w_req_timeout -#define xb_wid_int_upper xb_widget.w_intdest_upper_addr -#define xb_wid_int_lower xb_widget.w_intdest_lower_addr -#define xb_wid_err_cmdword xb_widget.w_err_cmd_word -#define xb_wid_llp xb_widget.w_llp_cfg -#define xb_wid_stat_clr xb_widget.w_tflush - -/* + /* standard widget configuration 0x000000-0x000057 */ + struct widget_cfg xb_widget; /* 0x000000 */ + + /* helper fieldnames for accessing bridge widget */ + +#define xb_wid_id xb_widget.w_id +#define xb_wid_stat xb_widget.w_status +#define xb_wid_err_upper xb_widget.w_err_upper_addr +#define xb_wid_err_lower xb_widget.w_err_lower_addr +#define xb_wid_control xb_widget.w_control +#define xb_wid_req_timeout xb_widget.w_req_timeout +#define xb_wid_int_upper xb_widget.w_intdest_upper_addr +#define xb_wid_int_lower xb_widget.w_intdest_lower_addr +#define xb_wid_err_cmdword xb_widget.w_err_cmd_word +#define xb_wid_llp xb_widget.w_llp_cfg +#define xb_wid_stat_clr xb_widget.w_tflush + +/* * we access these through synergy unswizzled space, so the address * gets twiddled (i.e. references to 0x4 actually go to 0x0 and vv.) * That's why we put the register first and filler second. */ - /* xbow-specific widget configuration 0x000058-0x0000FF */ - uint32_t xb_wid_arb_reload; /* 0x00005C */ - uint32_t _pad_000058; - uint32_t xb_perf_ctr_a; /* 0x000064 */ - uint32_t _pad_000060; - uint32_t xb_perf_ctr_b; /* 0x00006c */ - uint32_t _pad_000068; - uint32_t xb_nic; /* 0x000074 */ - uint32_t _pad_000070; - - /* Xbridge only */ - uint32_t xb_w0_rst_fnc; /* 0x00007C */ - uint32_t _pad_000078; - uint32_t xb_l8_rst_fnc; /* 0x000084 */ - uint32_t _pad_000080; - uint32_t xb_l9_rst_fnc; /* 0x00008c */ - uint32_t _pad_000088; - uint32_t xb_la_rst_fnc; /* 0x000094 */ - uint32_t _pad_000090; - uint32_t xb_lb_rst_fnc; /* 0x00009c */ - uint32_t _pad_000098; - uint32_t xb_lc_rst_fnc; /* 0x0000a4 */ - uint32_t _pad_0000a0; - uint32_t xb_ld_rst_fnc; /* 0x0000ac */ - uint32_t _pad_0000a8; - uint32_t xb_le_rst_fnc; /* 0x0000b4 */ - uint32_t _pad_0000b0; - uint32_t xb_lf_rst_fnc; /* 0x0000bc */ - uint32_t _pad_0000b8; - uint32_t xb_lock; /* 0x0000c4 */ - uint32_t _pad_0000c0; - uint32_t xb_lock_clr; /* 0x0000cc */ - uint32_t _pad_0000c8; - /* end of Xbridge only */ - uint32_t _pad_0000d0[12]; - - /* Link Specific Registers, port 8..15 0x000100-0x000300 */ - xb_linkregs_t xb_link_raw[MAX_XBOW_PORTS]; -#define xb_link(p) xb_link_raw[(p) & (MAX_XBOW_PORTS - 1)] - + /* xbow-specific widget configuration 0x000058-0x0000FF */ + u32 xb_wid_arb_reload; /* 0x00005C */ + u32 _pad_000058; + u32 xb_perf_ctr_a; /* 0x000064 */ + u32 _pad_000060; + u32 xb_perf_ctr_b; /* 0x00006c */ + u32 _pad_000068; + u32 xb_nic; /* 0x000074 */ + u32 _pad_000070; + + /* Xbridge only */ + u32 xb_w0_rst_fnc; /* 0x00007C */ + u32 _pad_000078; + u32 xb_l8_rst_fnc; /* 0x000084 */ + u32 _pad_000080; + u32 xb_l9_rst_fnc; /* 0x00008c */ + u32 _pad_000088; + u32 xb_la_rst_fnc; /* 0x000094 */ + u32 _pad_000090; + u32 xb_lb_rst_fnc; /* 0x00009c */ + u32 _pad_000098; + u32 xb_lc_rst_fnc; /* 0x0000a4 */ + u32 _pad_0000a0; + u32 xb_ld_rst_fnc; /* 0x0000ac */ + u32 _pad_0000a8; + u32 xb_le_rst_fnc; /* 0x0000b4 */ + u32 _pad_0000b0; + u32 xb_lf_rst_fnc; /* 0x0000bc */ + u32 _pad_0000b8; + u32 xb_lock; /* 0x0000c4 */ + u32 _pad_0000c0; + u32 xb_lock_clr; /* 0x0000cc */ + u32 _pad_0000c8; + /* end of Xbridge only */ + u32 _pad_0000d0[12]; + + /* Link Specific Registers, port 8..15 0x000100-0x000300 */ + xb_linkregs_t xb_link_raw[MAX_XBOW_PORTS]; } xbow_t; +#define xb_link(p) xb_link_raw[(p) & (MAX_XBOW_PORTS - 1)] + #define XB_FLAGS_EXISTS 0x1 /* device exists */ #define XB_FLAGS_MASTER 0x2 #define XB_FLAGS_SLAVE 0x0 @@ -160,7 +161,7 @@ typedef volatile struct xbow_s { /* End of Xbridge only */ /* used only in ide, but defined here within the reserved portion */ -/* of the widget0 address space (before 0xf4) */ +/* of the widget0 address space (before 0xf4) */ #define XBOW_WID_UNDEF 0xe4 /* xbow link register set base, legal value for x is 0x8..0xf */ @@ -179,29 +180,37 @@ typedef volatile struct xbow_s { /* link_control(x) */ #define XB_CTRL_LINKALIVE_IE 0x80000000 /* link comes alive */ - /* reserved: 0x40000000 */ +/* reserved: 0x40000000 */ #define XB_CTRL_PERF_CTR_MODE_MSK 0x30000000 /* perf counter mode */ -#define XB_CTRL_IBUF_LEVEL_MSK 0x0e000000 /* input packet buffer level */ -#define XB_CTRL_8BIT_MODE 0x01000000 /* force link into 8 bit mode */ -#define XB_CTRL_BAD_LLP_PKT 0x00800000 /* force bad LLP packet */ -#define XB_CTRL_WIDGET_CR_MSK 0x007c0000 /* LLP widget credit mask */ -#define XB_CTRL_WIDGET_CR_SHFT 18 /* LLP widget credit shift */ -#define XB_CTRL_ILLEGAL_DST_IE 0x00020000 /* illegal destination */ -#define XB_CTRL_OALLOC_IBUF_IE 0x00010000 /* overallocated input buffer */ - /* reserved: 0x0000fe00 */ +#define XB_CTRL_IBUF_LEVEL_MSK 0x0e000000 /* input packet buffer + level */ +#define XB_CTRL_8BIT_MODE 0x01000000 /* force link into 8 + bit mode */ +#define XB_CTRL_BAD_LLP_PKT 0x00800000 /* force bad LLP + packet */ +#define XB_CTRL_WIDGET_CR_MSK 0x007c0000 /* LLP widget credit + mask */ +#define XB_CTRL_WIDGET_CR_SHFT 18 /* LLP widget credit + shift */ +#define XB_CTRL_ILLEGAL_DST_IE 0x00020000 /* illegal destination + */ +#define XB_CTRL_OALLOC_IBUF_IE 0x00010000 /* overallocated input + buffer */ +/* reserved: 0x0000fe00 */ #define XB_CTRL_BNDWDTH_ALLOC_IE 0x00000100 /* bandwidth alloc */ #define XB_CTRL_RCV_CNT_OFLOW_IE 0x00000080 /* rcv retry overflow */ #define XB_CTRL_XMT_CNT_OFLOW_IE 0x00000040 /* xmt retry overflow */ #define XB_CTRL_XMT_MAX_RTRY_IE 0x00000020 /* max transmit retry */ #define XB_CTRL_RCV_IE 0x00000010 /* receive */ #define XB_CTRL_XMT_RTRY_IE 0x00000008 /* transmit retry */ - /* reserved: 0x00000004 */ -#define XB_CTRL_MAXREQ_TOUT_IE 0x00000002 /* maximum request timeout */ +/* reserved: 0x00000004 */ +#define XB_CTRL_MAXREQ_TOUT_IE 0x00000002 /* maximum request + timeout */ #define XB_CTRL_SRC_TOUT_IE 0x00000001 /* source timeout */ /* link_status(x) */ #define XB_STAT_LINKALIVE XB_CTRL_LINKALIVE_IE - /* reserved: 0x7ff80000 */ +/* reserved: 0x7ff80000 */ #define XB_STAT_MULTI_ERR 0x00040000 /* multi error */ #define XB_STAT_ILLEGAL_DST_ERR XB_CTRL_ILLEGAL_DST_IE #define XB_STAT_OALLOC_IBUF_ERR XB_CTRL_OALLOC_IBUF_IE @@ -211,7 +220,7 @@ typedef volatile struct xbow_s { #define XB_STAT_XMT_MAX_RTRY_ERR XB_CTRL_XMT_MAX_RTRY_IE #define XB_STAT_RCV_ERR XB_CTRL_RCV_IE #define XB_STAT_XMT_RTRY_ERR XB_CTRL_XMT_RTRY_IE - /* reserved: 0x00000004 */ +/* reserved: 0x00000004 */ #define XB_STAT_MAXREQ_TOUT_ERR XB_CTRL_MAXREQ_TOUT_IE #define XB_STAT_SRC_TOUT_ERR XB_CTRL_SRC_TOUT_IE @@ -222,7 +231,7 @@ typedef volatile struct xbow_s { #define XB_AUX_LINKFAIL_RST_BAD 0x00000040 #define XB_AUX_STAT_PRESENT 0x00000020 #define XB_AUX_STAT_PORT_WIDTH 0x00000010 - /* reserved: 0x0000000f */ +/* reserved: 0x0000000f */ /* * link_arb_upper/link_arb_lower(x), (reg) should be the link_arb_upper @@ -238,7 +247,8 @@ typedef volatile struct xbow_s { /* XBOW_WID_STAT */ #define XB_WID_STAT_LINK_INTR_SHFT (24) #define XB_WID_STAT_LINK_INTR_MASK (0xFF << XB_WID_STAT_LINK_INTR_SHFT) -#define XB_WID_STAT_LINK_INTR(x) (0x1 << (((x)&7) + XB_WID_STAT_LINK_INTR_SHFT)) +#define XB_WID_STAT_LINK_INTR(x) \ + (0x1 << (((x)&7) + XB_WID_STAT_LINK_INTR_SHFT)) #define XB_WID_STAT_WIDGET0_INTR 0x00800000 #define XB_WID_STAT_SRCID_MASK 0x000003c0 /* Xbridge only */ #define XB_WID_STAT_REG_ACC_ERR 0x00000020 @@ -264,7 +274,7 @@ typedef volatile struct xbow_s { #define XXBOW_WIDGET_PART_NUM 0xd000 /* Xbridge */ #define XBOW_WIDGET_MFGR_NUM 0x0 #define XXBOW_WIDGET_MFGR_NUM 0x0 -#define PXBOW_WIDGET_PART_NUM 0xd100 /* PIC */ +#define PXBOW_WIDGET_PART_NUM 0xd100 /* PIC */ #define XBOW_REV_1_0 0x1 /* xbow rev 1.0 is "1" */ #define XBOW_REV_1_1 0x2 /* xbow rev 1.1 is "2" */ @@ -279,13 +289,13 @@ typedef volatile struct xbow_s { #define XBOW_WID_ARB_RELOAD_INT 0x3f /* GBR reload interval */ #define IS_XBRIDGE_XBOW(wid) \ - (XWIDGET_PART_NUM(wid) == XXBOW_WIDGET_PART_NUM && \ - XWIDGET_MFG_NUM(wid) == XXBOW_WIDGET_MFGR_NUM) + (XWIDGET_PART_NUM(wid) == XXBOW_WIDGET_PART_NUM && \ + XWIDGET_MFG_NUM(wid) == XXBOW_WIDGET_MFGR_NUM) #define IS_PIC_XBOW(wid) \ - (XWIDGET_PART_NUM(wid) == PXBOW_WIDGET_PART_NUM && \ - XWIDGET_MFG_NUM(wid) == XXBOW_WIDGET_MFGR_NUM) + (XWIDGET_PART_NUM(wid) == PXBOW_WIDGET_PART_NUM && \ + XWIDGET_MFG_NUM(wid) == XXBOW_WIDGET_MFGR_NUM) #define XBOW_WAR_ENABLED(pv, widid) ((1 << XWIDGET_REV_NUM(widid)) & pv) -#endif /* _ASM_IA64_SN_XTALK_XBOW_H */ +#endif /* _ASM_IA64_SN_XTALK_XBOW_H */ diff --git a/arch/ia64/sn/include/xtalk/xwidgetdev.h b/arch/ia64/sn/include/xtalk/xwidgetdev.h index c5f4bc5cc03..2800eda0fd6 100644 --- a/arch/ia64/sn/include/xtalk/xwidgetdev.h +++ b/arch/ia64/sn/include/xtalk/xwidgetdev.h @@ -25,28 +25,28 @@ /* widget configuration registers */ struct widget_cfg{ - uint32_t w_id; /* 0x04 */ - uint32_t w_pad_0; /* 0x00 */ - uint32_t w_status; /* 0x0c */ - uint32_t w_pad_1; /* 0x08 */ - uint32_t w_err_upper_addr; /* 0x14 */ - uint32_t w_pad_2; /* 0x10 */ - uint32_t w_err_lower_addr; /* 0x1c */ - uint32_t w_pad_3; /* 0x18 */ - uint32_t w_control; /* 0x24 */ - uint32_t w_pad_4; /* 0x20 */ - uint32_t w_req_timeout; /* 0x2c */ - uint32_t w_pad_5; /* 0x28 */ - uint32_t w_intdest_upper_addr; /* 0x34 */ - uint32_t w_pad_6; /* 0x30 */ - uint32_t w_intdest_lower_addr; /* 0x3c */ - uint32_t w_pad_7; /* 0x38 */ - uint32_t w_err_cmd_word; /* 0x44 */ - uint32_t w_pad_8; /* 0x40 */ - uint32_t w_llp_cfg; /* 0x4c */ - uint32_t w_pad_9; /* 0x48 */ - uint32_t w_tflush; /* 0x54 */ - uint32_t w_pad_10; /* 0x50 */ + u32 w_id; /* 0x04 */ + u32 w_pad_0; /* 0x00 */ + u32 w_status; /* 0x0c */ + u32 w_pad_1; /* 0x08 */ + u32 w_err_upper_addr; /* 0x14 */ + u32 w_pad_2; /* 0x10 */ + u32 w_err_lower_addr; /* 0x1c */ + u32 w_pad_3; /* 0x18 */ + u32 w_control; /* 0x24 */ + u32 w_pad_4; /* 0x20 */ + u32 w_req_timeout; /* 0x2c */ + u32 w_pad_5; /* 0x28 */ + u32 w_intdest_upper_addr; /* 0x34 */ + u32 w_pad_6; /* 0x30 */ + u32 w_intdest_lower_addr; /* 0x3c */ + u32 w_pad_7; /* 0x38 */ + u32 w_err_cmd_word; /* 0x44 */ + u32 w_pad_8; /* 0x40 */ + u32 w_llp_cfg; /* 0x4c */ + u32 w_pad_9; /* 0x48 */ + u32 w_tflush; /* 0x54 */ + u32 w_pad_10; /* 0x50 */ }; /* @@ -63,7 +63,7 @@ struct xwidget_info{ struct xwidget_hwid xwi_hwid; /* Widget Identification */ char xwi_masterxid; /* Hub's Widget Port Number */ void *xwi_hubinfo; /* Hub's provider private info */ - uint64_t *xwi_hub_provider; /* prom provider functions */ + u64 *xwi_hub_provider; /* prom provider functions */ void *xwi_vertex; }; diff --git a/arch/ia64/sn/kernel/io_init.c b/arch/ia64/sn/kernel/io_init.c index 258d9d7aff9..a4c78152b33 100644 --- a/arch/ia64/sn/kernel/io_init.c +++ b/arch/ia64/sn/kernel/io_init.c @@ -10,6 +10,7 @@ #include <linux/nodemask.h> #include <asm/sn/types.h> #include <asm/sn/addrs.h> +#include <asm/sn/sn_feature_sets.h> #include <asm/sn/geo.h> #include <asm/sn/io.h> #include <asm/sn/pcibr_provider.h> @@ -132,8 +133,8 @@ static inline u64 sal_get_pcibus_info(u64 segment, u64 busnum, u64 address) * Retrieve the pci device information given the bus and device|function number. */ static inline u64 -sal_get_pcidev_info(u64 segment, u64 bus_number, u64 devfn, u64 pci_dev, - u64 sn_irq_info) +sal_get_pcidev_info(u64 segment, u64 bus_number, u64 devfn, u64 pci_dev, + u64 sn_irq_info) { struct ia64_sal_retval ret_stuff; ret_stuff.status = 0; @@ -141,7 +142,7 @@ sal_get_pcidev_info(u64 segment, u64 bus_number, u64 devfn, u64 pci_dev, SAL_CALL_NOLOCK(ret_stuff, (u64) SN_SAL_IOIF_GET_PCIDEV_INFO, - (u64) segment, (u64) bus_number, (u64) devfn, + (u64) segment, (u64) bus_number, (u64) devfn, (u64) pci_dev, sn_irq_info, 0, 0); return ret_stuff.v0; @@ -165,8 +166,46 @@ sn_pcidev_info_get(struct pci_dev *dev) return NULL; } +/* Older PROM flush WAR + * + * 01/16/06 -- This war will be in place until a new official PROM is released. + * Additionally note that the struct sn_flush_device_war also has to be + * removed from arch/ia64/sn/include/xtalk/hubdev.h + */ +static u8 war_implemented = 0; + +static s64 sn_device_fixup_war(u64 nasid, u64 widget, int device, + struct sn_flush_device_common *common) +{ + struct sn_flush_device_war *war_list; + struct sn_flush_device_war *dev_entry; + struct ia64_sal_retval isrv = {0,0,0,0}; + + if (!war_implemented) { + printk(KERN_WARNING "PROM version < 4.50 -- implementing old " + "PROM flush WAR\n"); + war_implemented = 1; + } + + war_list = kzalloc(DEV_PER_WIDGET * sizeof(*war_list), GFP_KERNEL); + if (!war_list) + BUG(); + + SAL_CALL_NOLOCK(isrv, SN_SAL_IOIF_GET_WIDGET_DMAFLUSH_LIST, + nasid, widget, __pa(war_list), 0, 0, 0 ,0); + if (isrv.status) + panic("sn_device_fixup_war failed: %s\n", + ia64_sal_strerror(isrv.status)); + + dev_entry = war_list + device; + memcpy(common,dev_entry, sizeof(*common)); + kfree(war_list); + + return isrv.status; +} + /* - * sn_fixup_ionodes() - This routine initializes the HUB data strcuture for + * sn_fixup_ionodes() - This routine initializes the HUB data strcuture for * each node in the system. */ static void sn_fixup_ionodes(void) @@ -242,12 +281,21 @@ static void sn_fixup_ionodes(void) memset(dev_entry->common, 0x0, sizeof(struct sn_flush_device_common)); - status = sal_get_device_dmaflush_list(nasid, - widget, - device, + if (sn_prom_feature_available( + PRF_DEVICE_FLUSH_LIST)) + status = sal_get_device_dmaflush_list( + nasid, + widget, + device, (u64)(dev_entry->common)); - if (status) - BUG(); + else + status = sn_device_fixup_war(nasid, + widget, + device, + dev_entry->common); + if (status != SALRET_OK) + panic("SAL call failed: %s\n", + ia64_sal_strerror(status)); spin_lock_init(&dev_entry->sfdl_flush_lock); } @@ -268,7 +316,7 @@ static void sn_fixup_ionodes(void) */ static void sn_pci_window_fixup(struct pci_dev *dev, unsigned int count, - int64_t * pci_addrs) + s64 * pci_addrs) { struct pci_controller *controller = PCI_CONTROLLER(dev->bus); unsigned int i; @@ -328,7 +376,7 @@ void sn_pci_fixup_slot(struct pci_dev *dev) struct pci_bus *host_pci_bus; struct pci_dev *host_pci_dev; struct pcidev_info *pcidev_info; - int64_t pci_addrs[PCI_ROM_RESOURCE + 1]; + s64 pci_addrs[PCI_ROM_RESOURCE + 1]; struct sn_irq_info *sn_irq_info; unsigned long size; unsigned int bus_no, devfn; diff --git a/arch/ia64/sn/kernel/irq.c b/arch/ia64/sn/kernel/irq.c index 01d18b7b5bb..ec37084bdc1 100644 --- a/arch/ia64/sn/kernel/irq.c +++ b/arch/ia64/sn/kernel/irq.c @@ -28,7 +28,7 @@ extern int sn_ioif_inited; static struct list_head **sn_irq_lh; static spinlock_t sn_irq_info_lock = SPIN_LOCK_UNLOCKED; /* non-IRQ lock */ -static inline uint64_t sn_intr_alloc(nasid_t local_nasid, int local_widget, +static inline u64 sn_intr_alloc(nasid_t local_nasid, int local_widget, u64 sn_irq_info, int req_irq, nasid_t req_nasid, int req_slice) @@ -123,7 +123,7 @@ static void sn_set_affinity_irq(unsigned int irq, cpumask_t mask) list_for_each_entry_safe(sn_irq_info, sn_irq_info_safe, sn_irq_lh[irq], list) { - uint64_t bridge; + u64 bridge; int local_widget, status; nasid_t local_nasid; struct sn_irq_info *new_irq_info; @@ -134,7 +134,7 @@ static void sn_set_affinity_irq(unsigned int irq, cpumask_t mask) break; memcpy(new_irq_info, sn_irq_info, sizeof(struct sn_irq_info)); - bridge = (uint64_t) new_irq_info->irq_bridge; + bridge = (u64) new_irq_info->irq_bridge; if (!bridge) { kfree(new_irq_info); break; /* irq is not a device interrupt */ @@ -349,10 +349,10 @@ static void force_interrupt(int irq) */ static void sn_check_intr(int irq, struct sn_irq_info *sn_irq_info) { - uint64_t regval; + u64 regval; int irr_reg_num; int irr_bit; - uint64_t irr_reg; + u64 irr_reg; struct pcidev_info *pcidev_info; struct pcibus_info *pcibus_info; diff --git a/arch/ia64/sn/kernel/mca.c b/arch/ia64/sn/kernel/mca.c index 6546db6abdb..9ab684d1bb5 100644 --- a/arch/ia64/sn/kernel/mca.c +++ b/arch/ia64/sn/kernel/mca.c @@ -10,6 +10,7 @@ #include <linux/kernel.h> #include <linux/timer.h> #include <linux/vmalloc.h> +#include <linux/mutex.h> #include <asm/mca.h> #include <asm/sal.h> #include <asm/sn/sn_sal.h> @@ -27,7 +28,7 @@ void sn_init_cpei_timer(void); /* Printing oemdata from mca uses data that is not passed through SAL, it is * global. Only one user at a time. */ -static DECLARE_MUTEX(sn_oemdata_mutex); +static DEFINE_MUTEX(sn_oemdata_mutex); static u8 **sn_oemdata; static u64 *sn_oemdata_size, sn_oemdata_bufsize; @@ -89,7 +90,7 @@ static int sn_platform_plat_specific_err_print(const u8 * sect_header, u8 ** oemdata, u64 * oemdata_size) { - down(&sn_oemdata_mutex); + mutex_lock(&sn_oemdata_mutex); sn_oemdata = oemdata; sn_oemdata_size = oemdata_size; sn_oemdata_bufsize = 0; @@ -107,7 +108,7 @@ sn_platform_plat_specific_err_print(const u8 * sect_header, u8 ** oemdata, *sn_oemdata_size = 0; ia64_sn_plat_specific_err_print(print_hook, (char *)sect_header); } - up(&sn_oemdata_mutex); + mutex_unlock(&sn_oemdata_mutex); return 0; } diff --git a/arch/ia64/sn/kernel/tiocx.c b/arch/ia64/sn/kernel/tiocx.c index 6a7939b16a1..d263d3e8fbb 100644 --- a/arch/ia64/sn/kernel/tiocx.c +++ b/arch/ia64/sn/kernel/tiocx.c @@ -245,7 +245,7 @@ static int cx_device_reload(struct cx_dev *cx_dev) cx_dev->bt); } -static inline uint64_t tiocx_intr_alloc(nasid_t nasid, int widget, +static inline u64 tiocx_intr_alloc(nasid_t nasid, int widget, u64 sn_irq_info, int req_irq, nasid_t req_nasid, int req_slice) @@ -302,7 +302,7 @@ struct sn_irq_info *tiocx_irq_alloc(nasid_t nasid, int widget, int irq, void tiocx_irq_free(struct sn_irq_info *sn_irq_info) { - uint64_t bridge = (uint64_t) sn_irq_info->irq_bridge; + u64 bridge = (u64) sn_irq_info->irq_bridge; nasid_t nasid = NASID_GET(bridge); int widget; @@ -313,12 +313,12 @@ void tiocx_irq_free(struct sn_irq_info *sn_irq_info) } } -uint64_t tiocx_dma_addr(uint64_t addr) +u64 tiocx_dma_addr(u64 addr) { return PHYS_TO_TIODMA(addr); } -uint64_t tiocx_swin_base(int nasid) +u64 tiocx_swin_base(int nasid) { return TIO_SWIN_BASE(nasid, TIOCX_CORELET); } @@ -335,8 +335,8 @@ EXPORT_SYMBOL(tiocx_swin_base); static void tio_conveyor_set(nasid_t nasid, int enable_flag) { - uint64_t ice_frz; - uint64_t disable_cb = (1ull << 61); + u64 ice_frz; + u64 disable_cb = (1ull << 61); if (!(nasid & 1)) return; @@ -388,7 +388,7 @@ static int is_fpga_tio(int nasid, int *bt) static int bitstream_loaded(nasid_t nasid) { - uint64_t cx_credits; + u64 cx_credits; cx_credits = REMOTE_HUB_L(nasid, TIO_ICE_PMI_TX_DYN_CREDIT_STAT_CB3); cx_credits &= TIO_ICE_PMI_TX_DYN_CREDIT_STAT_CB3_CREDIT_CNT_MASK; @@ -404,14 +404,14 @@ static int tiocx_reload(struct cx_dev *cx_dev) nasid_t nasid = cx_dev->cx_id.nasid; if (bitstream_loaded(nasid)) { - uint64_t cx_id; + u64 cx_id; int rv; rv = ia64_sn_sysctl_tio_clock_reset(nasid); if (rv) { printk(KERN_ALERT "CX port JTAG reset failed.\n"); } else { - cx_id = *(volatile uint64_t *) + cx_id = *(volatile u64 *) (TIO_SWIN_BASE(nasid, TIOCX_CORELET) + WIDGET_ID); part_num = XWIDGET_PART_NUM(cx_id); diff --git a/arch/ia64/sn/kernel/xp_main.c b/arch/ia64/sn/kernel/xp_main.c index 3be52a34c80..b7ea46645e1 100644 --- a/arch/ia64/sn/kernel/xp_main.c +++ b/arch/ia64/sn/kernel/xp_main.c @@ -19,6 +19,7 @@ #include <linux/kernel.h> #include <linux/interrupt.h> #include <linux/module.h> +#include <linux/mutex.h> #include <asm/sn/intr.h> #include <asm/sn/sn_sal.h> #include <asm/sn/xp.h> @@ -136,13 +137,13 @@ xpc_connect(int ch_number, xpc_channel_func func, void *key, u16 payload_size, registration = &xpc_registrations[ch_number]; - if (down_interruptible(®istration->sema) != 0) { + if (mutex_lock_interruptible(®istration->mutex) != 0) { return xpcInterrupted; } /* if XPC_CHANNEL_REGISTERED(ch_number) */ if (registration->func != NULL) { - up(®istration->sema); + mutex_unlock(®istration->mutex); return xpcAlreadyRegistered; } @@ -154,7 +155,7 @@ xpc_connect(int ch_number, xpc_channel_func func, void *key, u16 payload_size, registration->key = key; registration->func = func; - up(®istration->sema); + mutex_unlock(®istration->mutex); xpc_interface.connect(ch_number); @@ -190,11 +191,11 @@ xpc_disconnect(int ch_number) * figured XPC's users will just turn around and call xpc_disconnect() * again anyways, so we might as well wait, if need be. */ - down(®istration->sema); + mutex_lock(®istration->mutex); /* if !XPC_CHANNEL_REGISTERED(ch_number) */ if (registration->func == NULL) { - up(®istration->sema); + mutex_unlock(®istration->mutex); return; } @@ -208,7 +209,7 @@ xpc_disconnect(int ch_number) xpc_interface.disconnect(ch_number); - up(®istration->sema); + mutex_unlock(®istration->mutex); return; } @@ -250,9 +251,9 @@ xp_init(void) xp_nofault_PIOR_target = SH1_IPI_ACCESS; } - /* initialize the connection registration semaphores */ + /* initialize the connection registration mutex */ for (ch_number = 0; ch_number < XPC_NCHANNELS; ch_number++) { - sema_init(&xpc_registrations[ch_number].sema, 1); /* mutex */ + mutex_init(&xpc_registrations[ch_number].mutex); } return 0; diff --git a/arch/ia64/sn/kernel/xpc_channel.c b/arch/ia64/sn/kernel/xpc_channel.c index 0c0a6890240..36e5437a0fb 100644 --- a/arch/ia64/sn/kernel/xpc_channel.c +++ b/arch/ia64/sn/kernel/xpc_channel.c @@ -22,6 +22,8 @@ #include <linux/cache.h> #include <linux/interrupt.h> #include <linux/slab.h> +#include <linux/mutex.h> +#include <linux/completion.h> #include <asm/sn/bte.h> #include <asm/sn/sn_sal.h> #include <asm/sn/xpc.h> @@ -56,8 +58,8 @@ xpc_initialize_channels(struct xpc_partition *part, partid_t partid) atomic_set(&ch->n_to_notify, 0); spin_lock_init(&ch->lock); - sema_init(&ch->msg_to_pull_sema, 1); /* mutex */ - sema_init(&ch->wdisconnect_sema, 0); /* event wait */ + mutex_init(&ch->msg_to_pull_mutex); + init_completion(&ch->wdisconnect_wait); atomic_set(&ch->n_on_msg_allocate_wq, 0); init_waitqueue_head(&ch->msg_allocate_wq); @@ -445,7 +447,7 @@ xpc_allocate_local_msgqueue(struct xpc_channel *ch) nbytes = nentries * ch->msg_size; ch->local_msgqueue = xpc_kmalloc_cacheline_aligned(nbytes, - (GFP_KERNEL | GFP_DMA), + GFP_KERNEL, &ch->local_msgqueue_base); if (ch->local_msgqueue == NULL) { continue; @@ -453,7 +455,7 @@ xpc_allocate_local_msgqueue(struct xpc_channel *ch) memset(ch->local_msgqueue, 0, nbytes); nbytes = nentries * sizeof(struct xpc_notify); - ch->notify_queue = kmalloc(nbytes, (GFP_KERNEL | GFP_DMA)); + ch->notify_queue = kmalloc(nbytes, GFP_KERNEL); if (ch->notify_queue == NULL) { kfree(ch->local_msgqueue_base); ch->local_msgqueue = NULL; @@ -500,7 +502,7 @@ xpc_allocate_remote_msgqueue(struct xpc_channel *ch) nbytes = nentries * ch->msg_size; ch->remote_msgqueue = xpc_kmalloc_cacheline_aligned(nbytes, - (GFP_KERNEL | GFP_DMA), + GFP_KERNEL, &ch->remote_msgqueue_base); if (ch->remote_msgqueue == NULL) { continue; @@ -534,7 +536,6 @@ static enum xpc_retval xpc_allocate_msgqueues(struct xpc_channel *ch) { unsigned long irq_flags; - int i; enum xpc_retval ret; @@ -552,11 +553,6 @@ xpc_allocate_msgqueues(struct xpc_channel *ch) return ret; } - for (i = 0; i < ch->local_nentries; i++) { - /* use a semaphore as an event wait queue */ - sema_init(&ch->notify_queue[i].sema, 0); - } - spin_lock_irqsave(&ch->lock, irq_flags); ch->flags |= XPC_C_SETUP; spin_unlock_irqrestore(&ch->lock, irq_flags); @@ -799,10 +795,8 @@ xpc_process_disconnect(struct xpc_channel *ch, unsigned long *irq_flags) } if (ch->flags & XPC_C_WDISCONNECT) { - spin_unlock_irqrestore(&ch->lock, *irq_flags); - up(&ch->wdisconnect_sema); - spin_lock_irqsave(&ch->lock, *irq_flags); - + /* we won't lose the CPU since we're holding ch->lock */ + complete(&ch->wdisconnect_wait); } else if (ch->delayed_IPI_flags) { if (part->act_state != XPC_P_DEACTIVATING) { /* time to take action on any delayed IPI flags */ @@ -1092,12 +1086,12 @@ xpc_connect_channel(struct xpc_channel *ch) struct xpc_registration *registration = &xpc_registrations[ch->number]; - if (down_trylock(®istration->sema) != 0) { + if (mutex_trylock(®istration->mutex) == 0) { return xpcRetry; } if (!XPC_CHANNEL_REGISTERED(ch->number)) { - up(®istration->sema); + mutex_unlock(®istration->mutex); return xpcUnregistered; } @@ -1108,7 +1102,7 @@ xpc_connect_channel(struct xpc_channel *ch) if (ch->flags & XPC_C_DISCONNECTING) { spin_unlock_irqrestore(&ch->lock, irq_flags); - up(®istration->sema); + mutex_unlock(®istration->mutex); return ch->reason; } @@ -1140,7 +1134,7 @@ xpc_connect_channel(struct xpc_channel *ch) * channel lock be locked and will unlock and relock * the channel lock as needed. */ - up(®istration->sema); + mutex_unlock(®istration->mutex); XPC_DISCONNECT_CHANNEL(ch, xpcUnequalMsgSizes, &irq_flags); spin_unlock_irqrestore(&ch->lock, irq_flags); @@ -1155,7 +1149,7 @@ xpc_connect_channel(struct xpc_channel *ch) atomic_inc(&xpc_partitions[ch->partid].nchannels_active); } - up(®istration->sema); + mutex_unlock(®istration->mutex); /* initiate the connection */ @@ -2089,7 +2083,7 @@ xpc_pull_remote_msg(struct xpc_channel *ch, s64 get) enum xpc_retval ret; - if (down_interruptible(&ch->msg_to_pull_sema) != 0) { + if (mutex_lock_interruptible(&ch->msg_to_pull_mutex) != 0) { /* we were interrupted by a signal */ return NULL; } @@ -2125,7 +2119,7 @@ xpc_pull_remote_msg(struct xpc_channel *ch, s64 get) XPC_DEACTIVATE_PARTITION(part, ret); - up(&ch->msg_to_pull_sema); + mutex_unlock(&ch->msg_to_pull_mutex); return NULL; } @@ -2134,7 +2128,7 @@ xpc_pull_remote_msg(struct xpc_channel *ch, s64 get) ch->next_msg_to_pull += nmsgs; } - up(&ch->msg_to_pull_sema); + mutex_unlock(&ch->msg_to_pull_mutex); /* return the message we were looking for */ msg_offset = (get % ch->remote_nentries) * ch->msg_size; diff --git a/arch/ia64/sn/kernel/xpc_main.c b/arch/ia64/sn/kernel/xpc_main.c index 8930586e0eb..c75f8aeefc2 100644 --- a/arch/ia64/sn/kernel/xpc_main.c +++ b/arch/ia64/sn/kernel/xpc_main.c @@ -55,6 +55,7 @@ #include <linux/slab.h> #include <linux/delay.h> #include <linux/reboot.h> +#include <linux/completion.h> #include <asm/sn/intr.h> #include <asm/sn/sn_sal.h> #include <asm/kdebug.h> @@ -177,10 +178,10 @@ static DECLARE_WAIT_QUEUE_HEAD(xpc_act_IRQ_wq); static unsigned long xpc_hb_check_timeout; /* notification that the xpc_hb_checker thread has exited */ -static DECLARE_MUTEX_LOCKED(xpc_hb_checker_exited); +static DECLARE_COMPLETION(xpc_hb_checker_exited); /* notification that the xpc_discovery thread has exited */ -static DECLARE_MUTEX_LOCKED(xpc_discovery_exited); +static DECLARE_COMPLETION(xpc_discovery_exited); static struct timer_list xpc_hb_timer; @@ -321,7 +322,7 @@ xpc_hb_checker(void *ignore) /* mark this thread as having exited */ - up(&xpc_hb_checker_exited); + complete(&xpc_hb_checker_exited); return 0; } @@ -341,7 +342,7 @@ xpc_initiate_discovery(void *ignore) dev_dbg(xpc_part, "discovery thread is exiting\n"); /* mark this thread as having exited */ - up(&xpc_discovery_exited); + complete(&xpc_discovery_exited); return 0; } @@ -893,7 +894,7 @@ xpc_disconnect_wait(int ch_number) continue; } - (void) down(&ch->wdisconnect_sema); + wait_for_completion(&ch->wdisconnect_wait); spin_lock_irqsave(&ch->lock, irq_flags); DBUG_ON(!(ch->flags & XPC_C_DISCONNECTED)); @@ -946,10 +947,10 @@ xpc_do_exit(enum xpc_retval reason) free_irq(SGI_XPC_ACTIVATE, NULL); /* wait for the discovery thread to exit */ - down(&xpc_discovery_exited); + wait_for_completion(&xpc_discovery_exited); /* wait for the heartbeat checker thread to exit */ - down(&xpc_hb_checker_exited); + wait_for_completion(&xpc_hb_checker_exited); /* sleep for a 1/3 of a second or so */ @@ -1367,7 +1368,7 @@ xpc_init(void) dev_err(xpc_part, "failed while forking discovery thread\n"); /* mark this new thread as a non-starter */ - up(&xpc_discovery_exited); + complete(&xpc_discovery_exited); xpc_do_exit(xpcUnloading); return -EBUSY; diff --git a/arch/ia64/sn/pci/pci_dma.c b/arch/ia64/sn/pci/pci_dma.c index 9bf9f23b9a1..5a36292388e 100644 --- a/arch/ia64/sn/pci/pci_dma.c +++ b/arch/ia64/sn/pci/pci_dma.c @@ -90,14 +90,14 @@ void *sn_dma_alloc_coherent(struct device *dev, size_t size, */ node = pcibus_to_node(pdev->bus); if (likely(node >=0)) { - struct page *p = alloc_pages_node(node, GFP_ATOMIC, get_order(size)); + struct page *p = alloc_pages_node(node, flags, get_order(size)); if (likely(p)) cpuaddr = page_address(p); else return NULL; } else - cpuaddr = (void *)__get_free_pages(GFP_ATOMIC, get_order(size)); + cpuaddr = (void *)__get_free_pages(flags, get_order(size)); if (unlikely(!cpuaddr)) return NULL; diff --git a/arch/ia64/sn/pci/pcibr/pcibr_ate.c b/arch/ia64/sn/pci/pcibr/pcibr_ate.c index d1647b863e6..aa3fa5152a3 100644 --- a/arch/ia64/sn/pci/pcibr/pcibr_ate.c +++ b/arch/ia64/sn/pci/pcibr/pcibr_ate.c @@ -18,10 +18,10 @@ int pcibr_invalidate_ate = 0; /* by default don't invalidate ATE on free */ * mark_ate: Mark the ate as either free or inuse. */ static void mark_ate(struct ate_resource *ate_resource, int start, int number, - uint64_t value) + u64 value) { - uint64_t *ate = ate_resource->ate; + u64 *ate = ate_resource->ate; int index; int length = 0; @@ -38,7 +38,7 @@ static int find_free_ate(struct ate_resource *ate_resource, int start, int count) { - uint64_t *ate = ate_resource->ate; + u64 *ate = ate_resource->ate; int index; int start_free; @@ -119,7 +119,7 @@ static inline int alloc_ate_resource(struct ate_resource *ate_resource, int pcibr_ate_alloc(struct pcibus_info *pcibus_info, int count) { int status = 0; - uint64_t flag; + u64 flag; flag = pcibr_lock(pcibus_info); status = alloc_ate_resource(&pcibus_info->pbi_int_ate_resource, count); @@ -139,7 +139,7 @@ int pcibr_ate_alloc(struct pcibus_info *pcibus_info, int count) * Setup an Address Translation Entry as specified. Use either the Bridge * internal maps or the external map RAM, as appropriate. */ -static inline uint64_t *pcibr_ate_addr(struct pcibus_info *pcibus_info, +static inline u64 *pcibr_ate_addr(struct pcibus_info *pcibus_info, int ate_index) { if (ate_index < pcibus_info->pbi_int_ate_size) { @@ -153,7 +153,7 @@ static inline uint64_t *pcibr_ate_addr(struct pcibus_info *pcibus_info, */ void inline ate_write(struct pcibus_info *pcibus_info, int ate_index, int count, - volatile uint64_t ate) + volatile u64 ate) { while (count-- > 0) { if (ate_index < pcibus_info->pbi_int_ate_size) { @@ -171,9 +171,9 @@ ate_write(struct pcibus_info *pcibus_info, int ate_index, int count, void pcibr_ate_free(struct pcibus_info *pcibus_info, int index) { - volatile uint64_t ate; + volatile u64 ate; int count; - uint64_t flags; + u64 flags; if (pcibr_invalidate_ate) { /* For debugging purposes, clear the valid bit in the ATE */ diff --git a/arch/ia64/sn/pci/pcibr/pcibr_dma.c b/arch/ia64/sn/pci/pcibr/pcibr_dma.c index e68332d9317..54ce5b7ceed 100644 --- a/arch/ia64/sn/pci/pcibr/pcibr_dma.c +++ b/arch/ia64/sn/pci/pcibr/pcibr_dma.c @@ -41,21 +41,21 @@ extern int sn_ioif_inited; static dma_addr_t pcibr_dmamap_ate32(struct pcidev_info *info, - uint64_t paddr, size_t req_size, uint64_t flags) + u64 paddr, size_t req_size, u64 flags) { struct pcidev_info *pcidev_info = info->pdi_host_pcidev_info; struct pcibus_info *pcibus_info = (struct pcibus_info *)pcidev_info-> pdi_pcibus_info; - uint8_t internal_device = (PCI_SLOT(pcidev_info->pdi_host_pcidev_info-> + u8 internal_device = (PCI_SLOT(pcidev_info->pdi_host_pcidev_info-> pdi_linux_pcidev->devfn)) - 1; int ate_count; int ate_index; - uint64_t ate_flags = flags | PCI32_ATE_V; - uint64_t ate; - uint64_t pci_addr; - uint64_t xio_addr; - uint64_t offset; + u64 ate_flags = flags | PCI32_ATE_V; + u64 ate; + u64 pci_addr; + u64 xio_addr; + u64 offset; /* PIC in PCI-X mode does not supports 32bit PageMap mode */ if (IS_PIC_SOFT(pcibus_info) && IS_PCIX(pcibus_info)) { @@ -109,12 +109,12 @@ pcibr_dmamap_ate32(struct pcidev_info *info, } static dma_addr_t -pcibr_dmatrans_direct64(struct pcidev_info * info, uint64_t paddr, - uint64_t dma_attributes) +pcibr_dmatrans_direct64(struct pcidev_info * info, u64 paddr, + u64 dma_attributes) { struct pcibus_info *pcibus_info = (struct pcibus_info *) ((info->pdi_host_pcidev_info)->pdi_pcibus_info); - uint64_t pci_addr; + u64 pci_addr; /* Translate to Crosstalk View of Physical Address */ pci_addr = (IS_PIC_SOFT(pcibus_info) ? PHYS_TO_DMA(paddr) : @@ -127,7 +127,7 @@ pcibr_dmatrans_direct64(struct pcidev_info * info, uint64_t paddr, /* Handle Bridge Chipset differences */ if (IS_PIC_SOFT(pcibus_info)) { pci_addr |= - ((uint64_t) pcibus_info-> + ((u64) pcibus_info-> pbi_hub_xid << PIC_PCI64_ATTR_TARG_SHFT); } else pci_addr |= TIOCP_PCI64_CMDTYPE_MEM; @@ -142,17 +142,17 @@ pcibr_dmatrans_direct64(struct pcidev_info * info, uint64_t paddr, static dma_addr_t pcibr_dmatrans_direct32(struct pcidev_info * info, - uint64_t paddr, size_t req_size, uint64_t flags) + u64 paddr, size_t req_size, u64 flags) { struct pcidev_info *pcidev_info = info->pdi_host_pcidev_info; struct pcibus_info *pcibus_info = (struct pcibus_info *)pcidev_info-> pdi_pcibus_info; - uint64_t xio_addr; + u64 xio_addr; - uint64_t xio_base; - uint64_t offset; - uint64_t endoff; + u64 xio_base; + u64 offset; + u64 endoff; if (IS_PCIX(pcibus_info)) { return 0; @@ -209,14 +209,14 @@ pcibr_dma_unmap(struct pci_dev *hwdev, dma_addr_t dma_handle, int direction) * unlike the PIC Device(x) Write Request Buffer Flush register. */ -void sn_dma_flush(uint64_t addr) +void sn_dma_flush(u64 addr) { nasid_t nasid; int is_tio; int wid_num; int i, j; - uint64_t flags; - uint64_t itte; + u64 flags; + u64 itte; struct hubdev_info *hubinfo; volatile struct sn_flush_device_kernel *p; volatile struct sn_flush_device_common *common; @@ -299,8 +299,8 @@ void sn_dma_flush(uint64_t addr) * If CE ever needs the sn_dma_flush mechanism, we will have * to account for that here and in tioce_bus_fixup(). */ - uint32_t tio_id = HUB_L(TIO_IOSPACE_ADDR(nasid, TIO_NODE_ID)); - uint32_t revnum = XWIDGET_PART_REV_NUM(tio_id); + u32 tio_id = HUB_L(TIO_IOSPACE_ADDR(nasid, TIO_NODE_ID)); + u32 revnum = XWIDGET_PART_REV_NUM(tio_id); /* TIOCP BRINGUP WAR (PV907516): Don't write buffer flush reg */ if ((1 << XWIDGET_PART_REV_NUM_REV(revnum)) & PV907516) { @@ -315,7 +315,7 @@ void sn_dma_flush(uint64_t addr) *common->sfdl_flush_addr = 0; /* force an interrupt. */ - *(volatile uint32_t *)(common->sfdl_force_int_addr) = 1; + *(volatile u32 *)(common->sfdl_force_int_addr) = 1; /* wait for the interrupt to come back. */ while (*(common->sfdl_flush_addr) != 0x10f) diff --git a/arch/ia64/sn/pci/pcibr/pcibr_provider.c b/arch/ia64/sn/pci/pcibr/pcibr_provider.c index e328e948175..2fac27049bf 100644 --- a/arch/ia64/sn/pci/pcibr/pcibr_provider.c +++ b/arch/ia64/sn/pci/pcibr/pcibr_provider.c @@ -23,14 +23,16 @@ int sal_pcibr_slot_enable(struct pcibus_info *soft, int device, void *resp) { struct ia64_sal_retval ret_stuff; - uint64_t busnum; + u64 busnum; + u64 segment; ret_stuff.status = 0; ret_stuff.v0 = 0; + segment = soft->pbi_buscommon.bs_persist_segment; busnum = soft->pbi_buscommon.bs_persist_busnum; - SAL_CALL_NOLOCK(ret_stuff, (u64) SN_SAL_IOIF_SLOT_ENABLE, (u64) busnum, - (u64) device, (u64) resp, 0, 0, 0, 0); + SAL_CALL_NOLOCK(ret_stuff, (u64) SN_SAL_IOIF_SLOT_ENABLE, segment, + busnum, (u64) device, (u64) resp, 0, 0, 0); return (int)ret_stuff.v0; } @@ -40,15 +42,17 @@ sal_pcibr_slot_disable(struct pcibus_info *soft, int device, int action, void *resp) { struct ia64_sal_retval ret_stuff; - uint64_t busnum; + u64 busnum; + u64 segment; ret_stuff.status = 0; ret_stuff.v0 = 0; + segment = soft->pbi_buscommon.bs_persist_segment; busnum = soft->pbi_buscommon.bs_persist_busnum; SAL_CALL_NOLOCK(ret_stuff, (u64) SN_SAL_IOIF_SLOT_DISABLE, - (u64) busnum, (u64) device, (u64) action, - (u64) resp, 0, 0, 0); + segment, busnum, (u64) device, (u64) action, + (u64) resp, 0, 0); return (int)ret_stuff.v0; } @@ -56,7 +60,7 @@ sal_pcibr_slot_disable(struct pcibus_info *soft, int device, int action, static int sal_pcibr_error_interrupt(struct pcibus_info *soft) { struct ia64_sal_retval ret_stuff; - uint64_t busnum; + u64 busnum; int segment; ret_stuff.status = 0; ret_stuff.v0 = 0; @@ -159,9 +163,9 @@ pcibr_bus_fixup(struct pcibus_bussoft *prom_bussoft, struct pci_controller *cont /* Setup the PMU ATE map */ soft->pbi_int_ate_resource.lowest_free_index = 0; soft->pbi_int_ate_resource.ate = - kmalloc(soft->pbi_int_ate_size * sizeof(uint64_t), GFP_KERNEL); + kmalloc(soft->pbi_int_ate_size * sizeof(u64), GFP_KERNEL); memset(soft->pbi_int_ate_resource.ate, 0, - (soft->pbi_int_ate_size * sizeof(uint64_t))); + (soft->pbi_int_ate_size * sizeof(u64))); if (prom_bussoft->bs_asic_type == PCIIO_ASIC_TYPE_TIOCP) { /* TIO PCI Bridge: find nearest node with CPUs */ @@ -203,7 +207,7 @@ void pcibr_target_interrupt(struct sn_irq_info *sn_irq_info) struct pcidev_info *pcidev_info; struct pcibus_info *pcibus_info; int bit = sn_irq_info->irq_int_bit; - uint64_t xtalk_addr = sn_irq_info->irq_xtalkaddr; + u64 xtalk_addr = sn_irq_info->irq_xtalkaddr; pcidev_info = (struct pcidev_info *)sn_irq_info->irq_pciioinfo; if (pcidev_info) { diff --git a/arch/ia64/sn/pci/pcibr/pcibr_reg.c b/arch/ia64/sn/pci/pcibr/pcibr_reg.c index 79fdb91d725..8b8bbd51d43 100644 --- a/arch/ia64/sn/pci/pcibr/pcibr_reg.c +++ b/arch/ia64/sn/pci/pcibr/pcibr_reg.c @@ -23,7 +23,7 @@ union br_ptr { /* * Control Register Access -- Read/Write 0000_0020 */ -void pcireg_control_bit_clr(struct pcibus_info *pcibus_info, uint64_t bits) +void pcireg_control_bit_clr(struct pcibus_info *pcibus_info, u64 bits) { union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base; @@ -43,7 +43,7 @@ void pcireg_control_bit_clr(struct pcibus_info *pcibus_info, uint64_t bits) } } -void pcireg_control_bit_set(struct pcibus_info *pcibus_info, uint64_t bits) +void pcireg_control_bit_set(struct pcibus_info *pcibus_info, u64 bits) { union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base; @@ -66,10 +66,10 @@ void pcireg_control_bit_set(struct pcibus_info *pcibus_info, uint64_t bits) /* * PCI/PCIX Target Flush Register Access -- Read Only 0000_0050 */ -uint64_t pcireg_tflush_get(struct pcibus_info *pcibus_info) +u64 pcireg_tflush_get(struct pcibus_info *pcibus_info) { union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base; - uint64_t ret = 0; + u64 ret = 0; if (pcibus_info) { switch (pcibus_info->pbi_bridge_type) { @@ -96,10 +96,10 @@ uint64_t pcireg_tflush_get(struct pcibus_info *pcibus_info) /* * Interrupt Status Register Access -- Read Only 0000_0100 */ -uint64_t pcireg_intr_status_get(struct pcibus_info * pcibus_info) +u64 pcireg_intr_status_get(struct pcibus_info * pcibus_info) { union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base; - uint64_t ret = 0; + u64 ret = 0; if (pcibus_info) { switch (pcibus_info->pbi_bridge_type) { @@ -121,7 +121,7 @@ uint64_t pcireg_intr_status_get(struct pcibus_info * pcibus_info) /* * Interrupt Enable Register Access -- Read/Write 0000_0108 */ -void pcireg_intr_enable_bit_clr(struct pcibus_info *pcibus_info, uint64_t bits) +void pcireg_intr_enable_bit_clr(struct pcibus_info *pcibus_info, u64 bits) { union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base; @@ -141,7 +141,7 @@ void pcireg_intr_enable_bit_clr(struct pcibus_info *pcibus_info, uint64_t bits) } } -void pcireg_intr_enable_bit_set(struct pcibus_info *pcibus_info, uint64_t bits) +void pcireg_intr_enable_bit_set(struct pcibus_info *pcibus_info, u64 bits) { union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base; @@ -165,7 +165,7 @@ void pcireg_intr_enable_bit_set(struct pcibus_info *pcibus_info, uint64_t bits) * Intr Host Address Register (int_addr) -- Read/Write 0000_0130 - 0000_0168 */ void pcireg_intr_addr_addr_set(struct pcibus_info *pcibus_info, int int_n, - uint64_t addr) + u64 addr) { union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base; @@ -217,10 +217,10 @@ void pcireg_force_intr_set(struct pcibus_info *pcibus_info, int int_n) /* * Device(x) Write Buffer Flush Reg Access -- Read Only 0000_0240 - 0000_0258 */ -uint64_t pcireg_wrb_flush_get(struct pcibus_info *pcibus_info, int device) +u64 pcireg_wrb_flush_get(struct pcibus_info *pcibus_info, int device) { union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base; - uint64_t ret = 0; + u64 ret = 0; if (pcibus_info) { switch (pcibus_info->pbi_bridge_type) { @@ -242,7 +242,7 @@ uint64_t pcireg_wrb_flush_get(struct pcibus_info *pcibus_info, int device) } void pcireg_int_ate_set(struct pcibus_info *pcibus_info, int ate_index, - uint64_t val) + u64 val) { union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base; @@ -262,10 +262,10 @@ void pcireg_int_ate_set(struct pcibus_info *pcibus_info, int ate_index, } } -uint64_t __iomem *pcireg_int_ate_addr(struct pcibus_info *pcibus_info, int ate_index) +u64 __iomem *pcireg_int_ate_addr(struct pcibus_info *pcibus_info, int ate_index) { union br_ptr __iomem *ptr = (union br_ptr __iomem *)pcibus_info->pbi_buscommon.bs_base; - uint64_t __iomem *ret = NULL; + u64 __iomem *ret = NULL; if (pcibus_info) { switch (pcibus_info->pbi_bridge_type) { diff --git a/arch/ia64/sn/pci/tioca_provider.c b/arch/ia64/sn/pci/tioca_provider.c index 27aa1842dac..7571a402552 100644 --- a/arch/ia64/sn/pci/tioca_provider.c +++ b/arch/ia64/sn/pci/tioca_provider.c @@ -16,7 +16,7 @@ #include <asm/sn/pcibus_provider_defs.h> #include <asm/sn/tioca_provider.h> -uint32_t tioca_gart_found; +u32 tioca_gart_found; EXPORT_SYMBOL(tioca_gart_found); /* used by agp-sgi */ LIST_HEAD(tioca_list); @@ -34,8 +34,8 @@ static int tioca_gart_init(struct tioca_kernel *); static int tioca_gart_init(struct tioca_kernel *tioca_kern) { - uint64_t ap_reg; - uint64_t offset; + u64 ap_reg; + u64 offset; struct page *tmp; struct tioca_common *tioca_common; struct tioca __iomem *ca_base; @@ -214,7 +214,7 @@ void tioca_fastwrite_enable(struct tioca_kernel *tioca_kern) { int cap_ptr; - uint32_t reg; + u32 reg; struct tioca __iomem *tioca_base; struct pci_dev *pdev; struct tioca_common *common; @@ -276,7 +276,7 @@ EXPORT_SYMBOL(tioca_fastwrite_enable); /* used by agp-sgi */ * We will always use 0x1 * 55:55 - Swap bytes Currently unused */ -static uint64_t +static u64 tioca_dma_d64(unsigned long paddr) { dma_addr_t bus_addr; @@ -318,15 +318,15 @@ tioca_dma_d64(unsigned long paddr) * and so a given CA can only directly target nodes in the range * xxx - xxx+255. */ -static uint64_t -tioca_dma_d48(struct pci_dev *pdev, uint64_t paddr) +static u64 +tioca_dma_d48(struct pci_dev *pdev, u64 paddr) { struct tioca_common *tioca_common; struct tioca __iomem *ca_base; - uint64_t ct_addr; + u64 ct_addr; dma_addr_t bus_addr; - uint32_t node_upper; - uint64_t agp_dma_extn; + u32 node_upper; + u64 agp_dma_extn; struct pcidev_info *pcidev_info = SN_PCIDEV_INFO(pdev); tioca_common = (struct tioca_common *)pcidev_info->pdi_pcibus_info; @@ -367,10 +367,10 @@ tioca_dma_d48(struct pci_dev *pdev, uint64_t paddr) * dma_addr_t is guarenteed to be contiguous in CA bus space. */ static dma_addr_t -tioca_dma_mapped(struct pci_dev *pdev, uint64_t paddr, size_t req_size) +tioca_dma_mapped(struct pci_dev *pdev, u64 paddr, size_t req_size) { int i, ps, ps_shift, entry, entries, mapsize, last_entry; - uint64_t xio_addr, end_xio_addr; + u64 xio_addr, end_xio_addr; struct tioca_common *tioca_common; struct tioca_kernel *tioca_kern; dma_addr_t bus_addr = 0; @@ -514,10 +514,10 @@ tioca_dma_unmap(struct pci_dev *pdev, dma_addr_t bus_addr, int dir) * The mapping mode used is based on the devices dma_mask. As a last resort * use the GART mapped mode. */ -static uint64_t -tioca_dma_map(struct pci_dev *pdev, uint64_t paddr, size_t byte_count) +static u64 +tioca_dma_map(struct pci_dev *pdev, u64 paddr, size_t byte_count) { - uint64_t mapaddr; + u64 mapaddr; /* * If card is 64 or 48 bit addresable, use a direct mapping. 32 @@ -554,8 +554,8 @@ tioca_error_intr_handler(int irq, void *arg, struct pt_regs *pt) { struct tioca_common *soft = arg; struct ia64_sal_retval ret_stuff; - uint64_t segment; - uint64_t busnum; + u64 segment; + u64 busnum; ret_stuff.status = 0; ret_stuff.v0 = 0; @@ -620,7 +620,7 @@ tioca_bus_fixup(struct pcibus_bussoft *prom_bussoft, struct pci_controller *cont INIT_LIST_HEAD(&tioca_kern->ca_dmamaps); tioca_kern->ca_closest_node = nasid_to_cnodeid(tioca_common->ca_closest_nasid); - tioca_common->ca_kernel_private = (uint64_t) tioca_kern; + tioca_common->ca_kernel_private = (u64) tioca_kern; bus = pci_find_bus(tioca_common->ca_common.bs_persist_segment, tioca_common->ca_common.bs_persist_busnum); diff --git a/arch/ia64/sn/pci/tioce_provider.c b/arch/ia64/sn/pci/tioce_provider.c index dda196c9e32..e52831ed93e 100644 --- a/arch/ia64/sn/pci/tioce_provider.c +++ b/arch/ia64/sn/pci/tioce_provider.c @@ -81,10 +81,10 @@ * 61 - 0 since this is not an MSI transaction * 60:54 - reserved, MBZ */ -static uint64_t +static u64 tioce_dma_d64(unsigned long ct_addr) { - uint64_t bus_addr; + u64 bus_addr; bus_addr = ct_addr | (1UL << 63); @@ -141,9 +141,9 @@ pcidev_to_tioce(struct pci_dev *pdev, struct tioce **base, * length, and if enough resources exist, fill in the ATE's and construct a * tioce_dmamap struct to track the mapping. */ -static uint64_t +static u64 tioce_alloc_map(struct tioce_kernel *ce_kern, int type, int port, - uint64_t ct_addr, int len) + u64 ct_addr, int len) { int i; int j; @@ -152,11 +152,11 @@ tioce_alloc_map(struct tioce_kernel *ce_kern, int type, int port, int entries; int nates; int pagesize; - uint64_t *ate_shadow; - uint64_t *ate_reg; - uint64_t addr; + u64 *ate_shadow; + u64 *ate_reg; + u64 addr; struct tioce *ce_mmr; - uint64_t bus_base; + u64 bus_base; struct tioce_dmamap *map; ce_mmr = (struct tioce *)ce_kern->ce_common->ce_pcibus.bs_base; @@ -224,7 +224,7 @@ tioce_alloc_map(struct tioce_kernel *ce_kern, int type, int port, addr = ct_addr; for (j = 0; j < nates; j++) { - uint64_t ate; + u64 ate; ate = ATE_MAKE(addr, pagesize); ate_shadow[i + j] = ate; @@ -252,15 +252,15 @@ tioce_alloc_map(struct tioce_kernel *ce_kern, int type, int port, * * Map @paddr into 32-bit bus space of the CE associated with @pcidev_info. */ -static uint64_t -tioce_dma_d32(struct pci_dev *pdev, uint64_t ct_addr) +static u64 +tioce_dma_d32(struct pci_dev *pdev, u64 ct_addr) { int dma_ok; int port; struct tioce *ce_mmr; struct tioce_kernel *ce_kern; - uint64_t ct_upper; - uint64_t ct_lower; + u64 ct_upper; + u64 ct_lower; dma_addr_t bus_addr; ct_upper = ct_addr & ~0x3fffffffUL; @@ -269,7 +269,7 @@ tioce_dma_d32(struct pci_dev *pdev, uint64_t ct_addr) pcidev_to_tioce(pdev, &ce_mmr, &ce_kern, &port); if (ce_kern->ce_port[port].dirmap_refcnt == 0) { - uint64_t tmp; + u64 tmp; ce_kern->ce_port[port].dirmap_shadow = ct_upper; writeq(ct_upper, &ce_mmr->ce_ure_dir_map[port]); @@ -295,10 +295,10 @@ tioce_dma_d32(struct pci_dev *pdev, uint64_t ct_addr) * Given a TIOCE bus address, set the appropriate bit to indicate barrier * attributes. */ -static uint64_t -tioce_dma_barrier(uint64_t bus_addr, int on) +static u64 +tioce_dma_barrier(u64 bus_addr, int on) { - uint64_t barrier_bit; + u64 barrier_bit; /* barrier not supported in M40/M40S mode */ if (TIOCE_M40_ADDR(bus_addr) || TIOCE_M40S_ADDR(bus_addr)) @@ -351,7 +351,7 @@ tioce_dma_unmap(struct pci_dev *pdev, dma_addr_t bus_addr, int dir) list_for_each_entry(map, &ce_kern->ce_dmamap_list, ce_dmamap_list) { - uint64_t last; + u64 last; last = map->pci_start + map->nbytes - 1; if (bus_addr >= map->pci_start && bus_addr <= last) @@ -385,17 +385,17 @@ tioce_dma_unmap(struct pci_dev *pdev, dma_addr_t bus_addr, int dir) * This is the main wrapper for mapping host physical pages to CE PCI space. * The mapping mode used is based on the device's dma_mask. */ -static uint64_t -tioce_do_dma_map(struct pci_dev *pdev, uint64_t paddr, size_t byte_count, +static u64 +tioce_do_dma_map(struct pci_dev *pdev, u64 paddr, size_t byte_count, int barrier) { unsigned long flags; - uint64_t ct_addr; - uint64_t mapaddr = 0; + u64 ct_addr; + u64 mapaddr = 0; struct tioce_kernel *ce_kern; struct tioce_dmamap *map; int port; - uint64_t dma_mask; + u64 dma_mask; dma_mask = (barrier) ? pdev->dev.coherent_dma_mask : pdev->dma_mask; @@ -425,7 +425,7 @@ tioce_do_dma_map(struct pci_dev *pdev, uint64_t paddr, size_t byte_count, * address bits than this device can support. */ list_for_each_entry(map, &ce_kern->ce_dmamap_list, ce_dmamap_list) { - uint64_t last; + u64 last; last = map->ct_start + map->nbytes - 1; if (ct_addr >= map->ct_start && @@ -501,8 +501,8 @@ dma_map_done: * Simply call tioce_do_dma_map() to create a map with the barrier bit clear * in the address. */ -static uint64_t -tioce_dma(struct pci_dev *pdev, uint64_t paddr, size_t byte_count) +static u64 +tioce_dma(struct pci_dev *pdev, u64 paddr, size_t byte_count) { return tioce_do_dma_map(pdev, paddr, byte_count, 0); } @@ -515,8 +515,8 @@ tioce_dma(struct pci_dev *pdev, uint64_t paddr, size_t byte_count) * * Simply call tioce_do_dma_map() to create a map with the barrier bit set * in the address. - */ static uint64_t -tioce_dma_consistent(struct pci_dev *pdev, uint64_t paddr, size_t byte_count) + */ static u64 +tioce_dma_consistent(struct pci_dev *pdev, u64 paddr, size_t byte_count) { return tioce_do_dma_map(pdev, paddr, byte_count, 1); } @@ -551,7 +551,7 @@ tioce_error_intr_handler(int irq, void *arg, struct pt_regs *pt) tioce_kern_init(struct tioce_common *tioce_common) { int i; - uint32_t tmp; + u32 tmp; struct tioce *tioce_mmr; struct tioce_kernel *tioce_kern; @@ -563,7 +563,7 @@ tioce_kern_init(struct tioce_common *tioce_common) tioce_kern->ce_common = tioce_common; spin_lock_init(&tioce_kern->ce_lock); INIT_LIST_HEAD(&tioce_kern->ce_dmamap_list); - tioce_common->ce_kernel_private = (uint64_t) tioce_kern; + tioce_common->ce_kernel_private = (u64) tioce_kern; /* * Determine the secondary bus number of the port2 logical PPB. @@ -575,7 +575,7 @@ tioce_kern_init(struct tioce_common *tioce_common) raw_pci_ops->read(tioce_common->ce_pcibus.bs_persist_segment, tioce_common->ce_pcibus.bs_persist_busnum, PCI_DEVFN(2, 0), PCI_SECONDARY_BUS, 1, &tmp); - tioce_kern->ce_port1_secondary = (uint8_t) tmp; + tioce_kern->ce_port1_secondary = (u8) tmp; /* * Set PMU pagesize to the largest size available, and zero out @@ -615,7 +615,7 @@ tioce_force_interrupt(struct sn_irq_info *sn_irq_info) struct pcidev_info *pcidev_info; struct tioce_common *ce_common; struct tioce *ce_mmr; - uint64_t force_int_val; + u64 force_int_val; if (!sn_irq_info->irq_bridge) return; @@ -687,7 +687,7 @@ tioce_target_interrupt(struct sn_irq_info *sn_irq_info) struct tioce_common *ce_common; struct tioce *ce_mmr; int bit; - uint64_t vector; + u64 vector; pcidev_info = (struct pcidev_info *)sn_irq_info->irq_pciioinfo; if (!pcidev_info) @@ -699,7 +699,7 @@ tioce_target_interrupt(struct sn_irq_info *sn_irq_info) bit = sn_irq_info->irq_int_bit; __sn_setq_relaxed(&ce_mmr->ce_adm_int_mask, (1UL << bit)); - vector = (uint64_t)sn_irq_info->irq_irq << INTR_VECTOR_SHFT; + vector = (u64)sn_irq_info->irq_irq << INTR_VECTOR_SHFT; vector |= sn_irq_info->irq_xtalkaddr; writeq(vector, &ce_mmr->ce_adm_int_dest[bit]); __sn_clrq_relaxed(&ce_mmr->ce_adm_int_mask, (1UL << bit)); diff --git a/arch/mips/kernel/reset.c b/arch/mips/kernel/reset.c index ae2ba67b7ef..5e37df3111a 100644 --- a/arch/mips/kernel/reset.c +++ b/arch/mips/kernel/reset.c @@ -12,6 +12,9 @@ #include <linux/reboot.h> #include <asm/reboot.h> +void (*pm_power_off)(void); +EXPORT_SYMBOL(pm_power_off); + /* * Urgs ... Too many MIPS machines to handle this in a generic way. * So handle all using function pointers to machine specific @@ -33,6 +36,9 @@ void machine_halt(void) void machine_power_off(void) { + if (pm_power_off) + pm_power_off(); + _machine_power_off(); } diff --git a/arch/parisc/configs/a500_defconfig b/arch/parisc/configs/a500_defconfig index 955ef5084f3..959ad3c4e37 100644 --- a/arch/parisc/configs/a500_defconfig +++ b/arch/parisc/configs/a500_defconfig @@ -602,6 +602,7 @@ CONFIG_ACENIC_OMIT_TIGON_I=y # CONFIG_DL2K is not set CONFIG_E1000=m CONFIG_E1000_NAPI=y +# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set # CONFIG_NS83820 is not set # CONFIG_HAMACHI is not set # CONFIG_YELLOWFIN is not set diff --git a/arch/parisc/configs/c3000_defconfig b/arch/parisc/configs/c3000_defconfig index 9d86b6b1ebd..0b1c8c1fa8a 100644 --- a/arch/parisc/configs/c3000_defconfig +++ b/arch/parisc/configs/c3000_defconfig @@ -626,6 +626,7 @@ CONFIG_ACENIC=m # CONFIG_DL2K is not set CONFIG_E1000=m # CONFIG_E1000_NAPI is not set +# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set # CONFIG_NS83820 is not set # CONFIG_HAMACHI is not set # CONFIG_YELLOWFIN is not set diff --git a/arch/powerpc/configs/cell_defconfig b/arch/powerpc/configs/cell_defconfig index b657f7e4476..063b84f2cbe 100644 --- a/arch/powerpc/configs/cell_defconfig +++ b/arch/powerpc/configs/cell_defconfig @@ -533,6 +533,7 @@ CONFIG_MII=y # CONFIG_DL2K is not set CONFIG_E1000=m # CONFIG_E1000_NAPI is not set +# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set # CONFIG_NS83820 is not set # CONFIG_HAMACHI is not set # CONFIG_YELLOWFIN is not set diff --git a/arch/powerpc/configs/g5_defconfig b/arch/powerpc/configs/g5_defconfig index 3c22ccb1851..d6fed3f5658 100644 --- a/arch/powerpc/configs/g5_defconfig +++ b/arch/powerpc/configs/g5_defconfig @@ -675,6 +675,7 @@ CONFIG_ACENIC_OMIT_TIGON_I=y # CONFIG_DL2K is not set CONFIG_E1000=y # CONFIG_E1000_NAPI is not set +# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set # CONFIG_NS83820 is not set # CONFIG_HAMACHI is not set # CONFIG_YELLOWFIN is not set diff --git a/arch/powerpc/configs/iseries_defconfig b/arch/powerpc/configs/iseries_defconfig index 751a622fb7a..c775027947f 100644 --- a/arch/powerpc/configs/iseries_defconfig +++ b/arch/powerpc/configs/iseries_defconfig @@ -567,6 +567,7 @@ CONFIG_ACENIC=m # CONFIG_DL2K is not set CONFIG_E1000=m # CONFIG_E1000_NAPI is not set +# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set # CONFIG_NS83820 is not set # CONFIG_HAMACHI is not set # CONFIG_YELLOWFIN is not set diff --git a/arch/powerpc/configs/maple_defconfig b/arch/powerpc/configs/maple_defconfig index 07b6d3d2336..68194c03f6d 100644 --- a/arch/powerpc/configs/maple_defconfig +++ b/arch/powerpc/configs/maple_defconfig @@ -454,6 +454,7 @@ CONFIG_AMD8111_ETH=y # CONFIG_DL2K is not set CONFIG_E1000=y # CONFIG_E1000_NAPI is not set +# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set # CONFIG_NS83820 is not set # CONFIG_HAMACHI is not set # CONFIG_YELLOWFIN is not set diff --git a/arch/powerpc/configs/ppc64_defconfig b/arch/powerpc/configs/ppc64_defconfig index 0b2b55a79c3..6f6c6bed1aa 100644 --- a/arch/powerpc/configs/ppc64_defconfig +++ b/arch/powerpc/configs/ppc64_defconfig @@ -724,6 +724,7 @@ CONFIG_ACENIC_OMIT_TIGON_I=y # CONFIG_DL2K is not set CONFIG_E1000=y # CONFIG_E1000_NAPI is not set +# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set # CONFIG_NS83820 is not set # CONFIG_HAMACHI is not set # CONFIG_YELLOWFIN is not set diff --git a/arch/powerpc/configs/pseries_defconfig b/arch/powerpc/configs/pseries_defconfig index a50ce0fa924..aa9893a1f6e 100644 --- a/arch/powerpc/configs/pseries_defconfig +++ b/arch/powerpc/configs/pseries_defconfig @@ -671,6 +671,7 @@ CONFIG_ACENIC_OMIT_TIGON_I=y # CONFIG_DL2K is not set CONFIG_E1000=y # CONFIG_E1000_NAPI is not set +# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set # CONFIG_NS83820 is not set # CONFIG_HAMACHI is not set # CONFIG_YELLOWFIN is not set diff --git a/arch/powerpc/kernel/entry_32.S b/arch/powerpc/kernel/entry_32.S index d8da2a35c0a..f20a67261ec 100644 --- a/arch/powerpc/kernel/entry_32.S +++ b/arch/powerpc/kernel/entry_32.S @@ -227,7 +227,7 @@ ret_from_syscall: MTMSRD(r10) lwz r9,TI_FLAGS(r12) li r8,-_LAST_ERRNO - andi. r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SIGPENDING|_TIF_NEED_RESCHED|_TIF_RESTOREALL) + andi. r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SIGPENDING|_TIF_NEED_RESCHED|_TIF_RESTOREALL|_TIF_RESTORE_SIGMASK) bne- syscall_exit_work cmplw 0,r3,r8 blt+ syscall_exit_cont @@ -357,7 +357,7 @@ save_user_nvgprs_cont: lwz r5,_MSR(r1) andi. r5,r5,MSR_PR beq ret_from_except - andi. r0,r9,_TIF_SIGPENDING + andi. r0,r9,_TIF_SIGPENDING|_TIF_RESTORE_SIGMASK beq ret_from_except b do_user_signal 8: @@ -683,7 +683,7 @@ user_exc_return: /* r10 contains MSR_KERNEL here */ /* Check current_thread_info()->flags */ rlwinm r9,r1,0,0,(31-THREAD_SHIFT) lwz r9,TI_FLAGS(r9) - andi. r0,r9,(_TIF_SIGPENDING|_TIF_NEED_RESCHED|_TIF_RESTOREALL) + andi. r0,r9,(_TIF_SIGPENDING|_TIF_NEED_RESCHED|_TIF_RESTOREALL|_TIF_RESTORE_SIGMASK) bne do_work restore_user: @@ -917,7 +917,7 @@ recheck: lwz r9,TI_FLAGS(r9) andi. r0,r9,_TIF_NEED_RESCHED bne- do_resched - andi. r0,r9,_TIF_SIGPENDING + andi. r0,r9,_TIF_SIGPENDING|_TIF_RESTORE_SIGMASK beq restore_user do_user_signal: /* r10 contains MSR_KERNEL here */ ori r10,r10,MSR_EE diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S index 54203631886..388f861b8ed 100644 --- a/arch/powerpc/kernel/entry_64.S +++ b/arch/powerpc/kernel/entry_64.S @@ -160,7 +160,7 @@ syscall_exit: mtmsrd r10,1 ld r9,TI_FLAGS(r12) li r11,-_LAST_ERRNO - andi. r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SINGLESTEP|_TIF_SIGPENDING|_TIF_NEED_RESCHED|_TIF_RESTOREALL|_TIF_SAVE_NVGPRS|_TIF_NOERROR) + andi. r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SINGLESTEP|_TIF_SIGPENDING|_TIF_NEED_RESCHED|_TIF_RESTOREALL|_TIF_SAVE_NVGPRS|_TIF_NOERROR|_TIF_RESTORE_SIGMASK) bne- syscall_exit_work cmpld r3,r11 ld r5,_CCR(r1) diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c index 177bba78fb0..3747ab0dac3 100644 --- a/arch/powerpc/kernel/signal_32.c +++ b/arch/powerpc/kernel/signal_32.c @@ -252,8 +252,7 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs); /* * Atomically swap in the new signal mask, and wait for a signal. */ -long sys_sigsuspend(old_sigset_t mask, int p2, int p3, int p4, int p6, int p7, - struct pt_regs *regs) +long sys_sigsuspend(old_sigset_t mask) { sigset_t saveset; @@ -264,55 +263,10 @@ long sys_sigsuspend(old_sigset_t mask, int p2, int p3, int p4, int p6, int p7, recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); - regs->result = -EINTR; - regs->gpr[3] = EINTR; - regs->ccr |= 0x10000000; - while (1) { - current->state = TASK_INTERRUPTIBLE; - schedule(); - if (do_signal(&saveset, regs)) { - set_thread_flag(TIF_RESTOREALL); - return 0; - } - } -} - -long sys_rt_sigsuspend( -#ifdef CONFIG_PPC64 - compat_sigset_t __user *unewset, -#else - sigset_t __user *unewset, -#endif - size_t sigsetsize, int p3, int p4, - int p6, int p7, struct pt_regs *regs) -{ - sigset_t saveset, newset; - - /* XXX: Don't preclude handling different sized sigset_t's. */ - if (sigsetsize != sizeof(sigset_t)) - return -EINVAL; - - if (get_sigset_t(&newset, unewset)) - return -EFAULT; - sigdelsetmask(&newset, ~_BLOCKABLE); - - spin_lock_irq(¤t->sighand->siglock); - saveset = current->blocked; - current->blocked = newset; - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); - - regs->result = -EINTR; - regs->gpr[3] = EINTR; - regs->ccr |= 0x10000000; - while (1) { - current->state = TASK_INTERRUPTIBLE; - schedule(); - if (do_signal(&saveset, regs)) { - set_thread_flag(TIF_RESTOREALL); - return 0; - } - } + current->state = TASK_INTERRUPTIBLE; + schedule(); + set_thread_flag(TIF_RESTORE_SIGMASK); + return -ERESTARTNOHAND; } #ifdef CONFIG_PPC32 @@ -1174,7 +1128,7 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs) { siginfo_t info; struct k_sigaction ka; - unsigned int frame, newsp; + unsigned int newsp; int signr, ret; #ifdef CONFIG_PPC32 @@ -1185,11 +1139,11 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs) } #endif - if (!oldset) + if (test_thread_flag(TIF_RESTORE_SIGMASK)) + oldset = ¤t->saved_sigmask; + else if (!oldset) oldset = ¤t->blocked; - newsp = frame = 0; - signr = get_signal_to_deliver(&info, &ka, regs, NULL); #ifdef CONFIG_PPC32 no_signal: @@ -1219,8 +1173,14 @@ no_signal: } } - if (signr == 0) + if (signr == 0) { + /* No signal to deliver -- put the saved sigmask back */ + if (test_thread_flag(TIF_RESTORE_SIGMASK)) { + clear_thread_flag(TIF_RESTORE_SIGMASK); + sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); + } return 0; /* no signals delivered */ + } if ((ka.sa.sa_flags & SA_ONSTACK) && current->sas_ss_size && !on_sig_stack(regs->gpr[1])) @@ -1253,6 +1213,10 @@ no_signal: sigaddset(¤t->blocked, signr); recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); + /* A signal was successfully delivered; the saved sigmask is in + its frame, and we can clear the TIF_RESTORE_SIGMASK flag */ + if (test_thread_flag(TIF_RESTORE_SIGMASK)) + clear_thread_flag(TIF_RESTORE_SIGMASK); } return ret; diff --git a/arch/powerpc/kernel/signal_64.c b/arch/powerpc/kernel/signal_64.c index 7b9d999e211..b3193116e68 100644 --- a/arch/powerpc/kernel/signal_64.c +++ b/arch/powerpc/kernel/signal_64.c @@ -67,42 +67,6 @@ struct rt_sigframe { char abigap[288]; } __attribute__ ((aligned (16))); - -/* - * Atomically swap in the new signal mask, and wait for a signal. - */ -long sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize, int p3, int p4, - int p6, int p7, struct pt_regs *regs) -{ - sigset_t saveset, newset; - - /* XXX: Don't preclude handling different sized sigset_t's. */ - if (sigsetsize != sizeof(sigset_t)) - return -EINVAL; - - if (copy_from_user(&newset, unewset, sizeof(newset))) - return -EFAULT; - sigdelsetmask(&newset, ~_BLOCKABLE); - - spin_lock_irq(¤t->sighand->siglock); - saveset = current->blocked; - current->blocked = newset; - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); - - regs->result = -EINTR; - regs->gpr[3] = EINTR; - regs->ccr |= 0x10000000; - while (1) { - current->state = TASK_INTERRUPTIBLE; - schedule(); - if (do_signal(&saveset, regs)) { - set_thread_flag(TIF_RESTOREALL); - return 0; - } - } -} - long sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, unsigned long r5, unsigned long r6, unsigned long r7, unsigned long r8, struct pt_regs *regs) @@ -556,11 +520,15 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs) if (test_thread_flag(TIF_32BIT)) return do_signal32(oldset, regs); - if (!oldset) + if (test_thread_flag(TIF_RESTORE_SIGMASK)) + oldset = ¤t->saved_sigmask; + else if (!oldset) oldset = ¤t->blocked; signr = get_signal_to_deliver(&info, &ka, regs, NULL); if (signr > 0) { + int ret; + /* Whee! Actually deliver the signal. */ if (TRAP(regs) == 0x0C00) syscall_restart(regs, &ka); @@ -573,7 +541,14 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs) if (current->thread.dabr) set_dabr(current->thread.dabr); - return handle_signal(signr, &ka, &info, oldset, regs); + ret = handle_signal(signr, &ka, &info, oldset, regs); + + /* If a signal was successfully delivered, the saved sigmask is in + its frame, and we can clear the TIF_RESTORE_SIGMASK flag */ + if (ret && test_thread_flag(TIF_RESTORE_SIGMASK)) + clear_thread_flag(TIF_RESTORE_SIGMASK); + + return ret; } if (TRAP(regs) == 0x0C00) { /* System Call! */ @@ -589,6 +564,11 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs) regs->result = 0; } } + /* No signal to deliver -- put the saved sigmask back */ + if (test_thread_flag(TIF_RESTORE_SIGMASK)) { + clear_thread_flag(TIF_RESTORE_SIGMASK); + sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); + } return 0; } diff --git a/arch/powerpc/kernel/systbl.S b/arch/powerpc/kernel/systbl.S index 68013179a50..007b15ee36d 100644 --- a/arch/powerpc/kernel/systbl.S +++ b/arch/powerpc/kernel/systbl.S @@ -321,3 +321,5 @@ SYSCALL(inotify_add_watch) SYSCALL(inotify_rm_watch) SYSCALL(spu_run) SYSCALL(spu_create) +COMPAT_SYS(pselect6) +COMPAT_SYS(ppoll) diff --git a/arch/powerpc/platforms/powermac/feature.c b/arch/powerpc/platforms/powermac/feature.c index 558dd069209..2296f3d46ca 100644 --- a/arch/powerpc/platforms/powermac/feature.c +++ b/arch/powerpc/platforms/powermac/feature.c @@ -910,16 +910,18 @@ core99_gmac_phy_reset(struct device_node *node, long param, long value) macio->type != macio_intrepid) return -ENODEV; + printk(KERN_DEBUG "Hard reset of PHY chip ...\n"); + LOCK(flags); MACIO_OUT8(KL_GPIO_ETH_PHY_RESET, KEYLARGO_GPIO_OUTPUT_ENABLE); (void)MACIO_IN8(KL_GPIO_ETH_PHY_RESET); UNLOCK(flags); - mdelay(10); + msleep(10); LOCK(flags); MACIO_OUT8(KL_GPIO_ETH_PHY_RESET, /*KEYLARGO_GPIO_OUTPUT_ENABLE | */ KEYLARGO_GPIO_OUTOUT_DATA); UNLOCK(flags); - mdelay(10); + msleep(10); return 0; } diff --git a/arch/ppc/configs/bamboo_defconfig b/arch/ppc/configs/bamboo_defconfig index 0ba4e70d50b..41fd3938fa5 100644 --- a/arch/ppc/configs/bamboo_defconfig +++ b/arch/ppc/configs/bamboo_defconfig @@ -499,6 +499,7 @@ CONFIG_NATSEMI=y # CONFIG_DL2K is not set CONFIG_E1000=y # CONFIG_E1000_NAPI is not set +# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set # CONFIG_NS83820 is not set # CONFIG_HAMACHI is not set # CONFIG_YELLOWFIN is not set diff --git a/arch/ppc/configs/katana_defconfig b/arch/ppc/configs/katana_defconfig index 0f3bb9af9c2..7311fe6b42d 100644 --- a/arch/ppc/configs/katana_defconfig +++ b/arch/ppc/configs/katana_defconfig @@ -488,6 +488,7 @@ CONFIG_E100=y # CONFIG_DL2K is not set CONFIG_E1000=y # CONFIG_E1000_NAPI is not set +# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set # CONFIG_NS83820 is not set # CONFIG_HAMACHI is not set # CONFIG_YELLOWFIN is not set diff --git a/arch/ppc/configs/mpc834x_sys_defconfig b/arch/ppc/configs/mpc834x_sys_defconfig index 673dc64ebcb..b96a6d6dad0 100644 --- a/arch/ppc/configs/mpc834x_sys_defconfig +++ b/arch/ppc/configs/mpc834x_sys_defconfig @@ -402,6 +402,7 @@ CONFIG_E100=y # CONFIG_DL2K is not set CONFIG_E1000=y # CONFIG_E1000_NAPI is not set +# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set # CONFIG_NS83820 is not set # CONFIG_HAMACHI is not set # CONFIG_YELLOWFIN is not set diff --git a/arch/ppc/configs/power3_defconfig b/arch/ppc/configs/power3_defconfig index 93da595a473..a1ef929bca5 100644 --- a/arch/ppc/configs/power3_defconfig +++ b/arch/ppc/configs/power3_defconfig @@ -442,6 +442,7 @@ CONFIG_E100=y # CONFIG_DL2K is not set CONFIG_E1000=y # CONFIG_E1000_NAPI is not set +# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set # CONFIG_NS83820 is not set # CONFIG_HAMACHI is not set # CONFIG_YELLOWFIN is not set diff --git a/arch/ppc/syslib/mv64x60.c b/arch/ppc/syslib/mv64x60.c index 94ea346b7b4..1f01b7e2376 100644 --- a/arch/ppc/syslib/mv64x60.c +++ b/arch/ppc/syslib/mv64x60.c @@ -313,7 +313,7 @@ static struct platform_device mpsc1_device = { }; #endif -#ifdef CONFIG_MV643XX_ETH +#if defined(CONFIG_MV643XX_ETH) || defined(CONFIG_MV643XX_ETH_MODULE) static struct resource mv64x60_eth_shared_resources[] = { [0] = { .name = "ethernet shared base", @@ -456,7 +456,7 @@ static struct platform_device *mv64x60_pd_devs[] __initdata = { &mpsc0_device, &mpsc1_device, #endif -#ifdef CONFIG_MV643XX_ETH +#if defined(CONFIG_MV643XX_ETH) || defined(CONFIG_MV643XX_ETH_MODULE) &mv64x60_eth_shared_device, #endif #ifdef CONFIG_MV643XX_ETH_0 diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig index 8cf6d437a63..01bc7d589af 100644 --- a/arch/sh/Kconfig +++ b/arch/sh/Kconfig @@ -33,9 +33,11 @@ config GENERIC_CALIBRATE_DELAY bool default y +config GENERIC_IOMAP + bool + config ARCH_MAY_HAVE_PC_FDC bool - default y source "init/Kconfig" @@ -53,24 +55,28 @@ config SH_SOLUTION_ENGINE config SH_7751_SOLUTION_ENGINE bool "SolutionEngine7751" + select CPU_SUBTYPE_SH7751 help Select 7751 SolutionEngine if configuring for a Hitachi SH7751 evaluation board. config SH_7300_SOLUTION_ENGINE bool "SolutionEngine7300" + select CPU_SUBTYPE_SH7300 help Select 7300 SolutionEngine if configuring for a Hitachi SH7300(SH-Mobile V) evaluation board. config SH_73180_SOLUTION_ENGINE bool "SolutionEngine73180" + select CPU_SUBTYPE_SH73180 help Select 73180 SolutionEngine if configuring for a Hitachi SH73180(SH-Mobile 3) evaluation board. config SH_7751_SYSTEMH bool "SystemH7751R" + select CPU_SUBTYPE_SH7751R help Select SystemH if you are configuring for a Renesas SystemH 7751R evaluation board. @@ -81,27 +87,13 @@ config SH_STB1_HARP config SH_STB1_OVERDRIVE bool "STB1_Overdrive" -config SH_HP620 - bool "HP620" +config SH_HP6XX + bool "HP6XX" help - Select HP620 if configuring for a HP jornada HP620. + Select HP6XX if configuring for a HP jornada HP6xx. More information (hardware only) at <http://www.hp.com/jornada/>. -config SH_HP680 - bool "HP680" - help - Select HP680 if configuring for a HP Jornada HP680. - More information (hardware only) at - <http://www.hp.com/jornada/products/680/>. - -config SH_HP690 - bool "HP690" - help - Select HP690 if configuring for a HP Jornada HP690. - More information (hardware only) - at <http://www.hp.com/jornada/products/680/>. - config SH_CQREEK bool "CqREEK" help @@ -123,11 +115,13 @@ config SH_EC3104 config SH_SATURN bool "Saturn" + select CPU_SUBTYPE_SH7604 help Select Saturn if configuring for a SEGA Saturn. config SH_DREAMCAST bool "Dreamcast" + select CPU_SUBTYPE_SH7091 help Select Dreamcast if configuring for a SEGA Dreamcast. More information at @@ -142,6 +136,7 @@ config SH_BIGSUR config SH_SH2000 bool "SH2000" + select CPU_SUBTYPE_SH7709 help SH-2000 is a single-board computer based around SH7709A chip intended for embedded applications. @@ -153,20 +148,22 @@ config SH_ADX bool "ADX" config SH_MPC1211 - bool "MPC1211" + bool "Interface MPC1211" + help + CTP/PCI-SH02 is a CPU module computer that is produced + by Interface Corporation. + More information at <http://www.interface.co.jp> config SH_SH03 - bool "SH03" + bool "Interface CTP/PCI-SH03" help - CTP/PCI-SH03 is a CPU module computer that produced + CTP/PCI-SH03 is a CPU module computer that is produced by Interface Corporation. - It is compact and excellent in durability. - It will play an active part in your factory or laboratory - as a FA computer. More information at <http://www.interface.co.jp> config SH_SECUREEDGE5410 bool "SecureEdge5410" + select CPU_SUBTYPE_SH7751R help Select SecureEdge5410 if configuring for a SnapGear SH board. This includes both the OEM SecureEdge products as well as the @@ -174,25 +171,49 @@ config SH_SECUREEDGE5410 config SH_HS7751RVOIP bool "HS7751RVOIP" + select CPU_SUBTYPE_SH7751R help Select HS7751RVOIP if configuring for a Renesas Technology Sales VoIP board. config SH_RTS7751R2D bool "RTS7751R2D" + select CPU_SUBTYPE_SH7751R help Select RTS7751R2D if configuring for a Renesas Technology Sales SH-Graphics board. +config SH_R7780RP + bool "R7780RP-1" + select CPU_SUBTYPE_SH7780 + help + Select R7780RP-1 if configuring for a Renesas Solutions + HIGHLANDER board. + config SH_EDOSK7705 bool "EDOSK7705" + select CPU_SUBTYPE_SH7705 config SH_SH4202_MICRODEV bool "SH4-202 MicroDev" + select CPU_SUBTYPE_SH4_202 help Select SH4-202 MicroDev if configuring for a SuperH MicroDev board with an SH4-202 CPU. +config SH_LANDISK + bool "LANDISK" + select CPU_SUBTYPE_SH7751R + help + I-O DATA DEVICE, INC. "LANDISK Series" support. + +config SH_TITAN + bool "TITAN" + select CPU_SUBTYPE_SH7751R + help + Select Titan if you are configuring for a Nimble Microsystems + NetEngine NP51R. + config SH_UNKNOWN bool "BareCPU" help @@ -207,168 +228,27 @@ config SH_UNKNOWN endchoice -choice - prompt "Processor family" - default CPU_SH4 - help - This option determines the CPU family to compile for. Supported - targets are SH-2, SH-3, and SH-4. These options are independent of - CPU functionality. As such, SH-DSP users will still want to select - their respective processor family in addition to the DSP support - option. - -config CPU_SH2 - bool "SH-2" - select SH_WRITETHROUGH - -config CPU_SH3 - bool "SH-3" - -config CPU_SH4 - bool "SH-4" - -endchoice - -choice - prompt "Processor subtype" - -config CPU_SUBTYPE_SH7604 - bool "SH7604" - depends on CPU_SH2 - help - Select SH7604 if you have SH7604 - -config CPU_SUBTYPE_SH7300 - bool "SH7300" - depends on CPU_SH3 - -config CPU_SUBTYPE_SH7705 - bool "SH7705" - depends on CPU_SH3 - -config CPU_SUBTYPE_SH7707 - bool "SH7707" - depends on CPU_SH3 - help - Select SH7707 if you have a 60 Mhz SH-3 HD6417707 CPU. - -config CPU_SUBTYPE_SH7708 - bool "SH7708" - depends on CPU_SH3 - help - Select SH7708 if you have a 60 Mhz SH-3 HD6417708S or - if you have a 100 Mhz SH-3 HD6417708R CPU. - -config CPU_SUBTYPE_SH7709 - bool "SH7709" - depends on CPU_SH3 - help - Select SH7709 if you have a 80 Mhz SH-3 HD6417709 CPU. - -config CPU_SUBTYPE_SH7750 - bool "SH7750" - depends on CPU_SH4 - help - Select SH7750 if you have a 200 Mhz SH-4 HD6417750 CPU. - -config CPU_SUBTYPE_SH7751 - bool "SH7751/SH7751R" - depends on CPU_SH4 - help - Select SH7751 if you have a 166 Mhz SH-4 HD6417751 CPU, - or if you have a HD6417751R CPU. - -config CPU_SUBTYPE_SH7760 - bool "SH7760" - depends on CPU_SH4 - -config CPU_SUBTYPE_SH73180 - bool "SH73180" - depends on CPU_SH4 - -config CPU_SUBTYPE_ST40STB1 - bool "ST40STB1 / ST40RA" - depends on CPU_SH4 - help - Select ST40STB1 if you have a ST40RA CPU. - This was previously called the ST40STB1, hence the option name. - -config CPU_SUBTYPE_ST40GX1 - bool "ST40GX1" - depends on CPU_SH4 - help - Select ST40GX1 if you have a ST40GX1 CPU. - -config CPU_SUBTYPE_SH4_202 - bool "SH4-202" - depends on CPU_SH4 - -endchoice - -config SH7705_CACHE_32KB - bool "Enable 32KB cache size for SH7705" - depends on CPU_SUBTYPE_SH7705 - default y - -config MMU - bool "Support for memory management hardware" - depends on !CPU_SH2 - default y - help - Early SH processors (such as the SH7604) lack an MMU. In order to - boot on these systems, this option must not be set. - - On other systems (such as the SH-3 and 4) where an MMU exists, - turning this off will boot the kernel on these machines with the - MMU implicitly switched off. - -choice - prompt "HugeTLB page size" - depends on HUGETLB_PAGE && CPU_SH4 && MMU - default HUGETLB_PAGE_SIZE_64K - -config HUGETLB_PAGE_SIZE_64K - bool "64K" - -config HUGETLB_PAGE_SIZE_1MB - bool "1MB" - -endchoice - -config CMDLINE_BOOL - bool "Default bootloader kernel arguments" - -config CMDLINE - string "Initial kernel command string" - depends on CMDLINE_BOOL - default "console=ttySC1,115200" +source "arch/sh/mm/Kconfig" -# Platform-specific memory start and size definitions config MEMORY_START - hex "Physical memory start address" if !MEMORY_SET || MEMORY_OVERRIDE - default "0x08000000" if !MEMORY_SET || MEMORY_OVERRIDE || !MEMORY_OVERRIDE && SH_ADX || SH_MPC1211 || SH_SH03 || SH_SECUREEDGE5410 || SH_SH4202_MICRODEV - default "0x0c000000" if !MEMORY_OVERRIDE && (SH_DREAMCAST || SH_HP600 || SH_BIGSUR || SH_SH2000 || SH_73180_SOLUTION_ENGINE || SH_7300_SOLUTION_ENGINE || SH_7751_SOLUTION_ENGINE || SH_SOLUTION_ENGINE || SH_HS7751RVOIP || SH_RTS7751R2D || SH_EDOSK7705) + hex "Physical memory start address" + default "0x08000000" ---help--- Computers built with Hitachi SuperH processors always map the ROM starting at address zero. But the processor does not specify the range that RAM takes. The physical memory (RAM) start address will be automatically - set to 08000000, unless you selected one of the following - processor types: SolutionEngine, Overdrive, HP620, HP680, HP690, - in which case the start address will be set to 0c000000. + set to 08000000. Other platforms, such as the Solution Engine + boards typically map RAM at 0C000000. - Tweak this only when porting to a new machine which is not already - known by the config system. Changing it from the known correct + Tweak this only when porting to a new machine which does not + already have a defconfig. Changing it from the known correct value on any of the known systems will only lead to disaster. config MEMORY_SIZE - hex "Physical memory size" if !MEMORY_SET || MEMORY_OVERRIDE - default "0x00400000" if !MEMORY_SET || MEMORY_OVERRIDE || !MEMORY_OVERRIDE && SH_ADX || !MEMORY_OVERRIDE && (SH_HP600 || SH_BIGSUR || SH_SH2000) - default "0x01000000" if !MEMORY_OVERRIDE && SH_DREAMCAST || SH_SECUREEDGE5410 || SH_EDOSK7705 - default "0x02000000" if !MEMORY_OVERRIDE && (SH_73180_SOLUTION_ENGINE || SH_SOLUTION_ENGINE) - default "0x04000000" if !MEMORY_OVERRIDE && (SH_7300_SOLUTION_ENGINE || SH_7751_SOLUTION_ENGINE || SH_HS7751RVOIP || SH_RTS7751R2D || SH_SH4202_MICRODEV) - default "0x08000000" if SH_MPC1211 || SH_SH03 + hex "Physical memory size" + default "0x00400000" help This sets the default memory size assumed by your SH kernel. It can be overridden as normal by the 'mem=' argument on the kernel command @@ -376,21 +256,6 @@ config MEMORY_SIZE as 0x00400000 which was the default value before this became configurable. -config MEMORY_SET - bool - depends on !MEMORY_OVERRIDE && (SH_MPC1211 || SH_SH03 || SH_ADX || SH_DREAMCAST || SH_HP600 || SH_BIGSUR || SH_SH2000 || SH_7751_SOLUTION_ENGINE || SH_SOLUTION_ENGINE || SH_SECUREEDGE5410 || SH_HS7751RVOIP || SH_RTS7751R2D || SH_SH4202_MICRODEV || SH_EDOSK7705) - default y - help - This is an option about which you will never be asked a question. - Therefore, I conclude that you do not exist - go away. - - There is a grue here. - -# If none of the above have set memory start/size, ask the user. -config MEMORY_OVERRIDE - bool "Override default load address and memory size" - -# XXX: break these out into the board-specific configs below config CF_ENABLER bool "Compact Flash Enabler support" depends on SH_ADX || SH_SOLUTION_ENGINE || SH_UNKNOWN || SH_CAT68701 || SH_SH03 @@ -434,10 +299,21 @@ config CF_BASE_ADDR default "0xb8000000" if CF_AREA6 default "0xb4000000" if CF_AREA5 +menu "Processor features" + +config CPU_LITTLE_ENDIAN + bool "Little Endian" + help + Some SuperH machines can be configured for either little or big + endian byte order. These modes require different kernels. Say Y if + your machine is little endian, N if it's a big endian machine. + # The SH7750 RTC module is disabled in the Dreamcast config SH_RTC bool - depends on !SH_DREAMCAST && !SH_SATURN && !SH_7300_SOLUTION_ENGINE && !SH_73180_SOLUTION_ENGINE + depends on !SH_DREAMCAST && !SH_SATURN && !SH_7300_SOLUTION_ENGINE && \ + !SH_73180_SOLUTION_ENGINE && !SH_LANDISK && \ + !SH_R7780RP default y help Selecting this option will allow the Linux kernel to emulate @@ -476,104 +352,131 @@ config SH_ADC If unsure, say N. -config SH_HP600 +config SH_STORE_QUEUES + bool "Support for Store Queues" + depends on CPU_SH4 + help + Selecting this option will enable an in-kernel API for manipulating + the store queues integrated in the SH-4 processors. + +config CPU_HAS_INTEVT bool - depends on SH_HP620 || SH_HP680 || SH_HP690 - default y -config CPU_SUBTYPE_ST40 - bool - depends on CPU_SUBTYPE_ST40STB1 || CPU_SUBTYPE_ST40GX1 - default y +config CPU_HAS_PINT_IRQ + bool -source "mm/Kconfig" +config CPU_HAS_INTC2_IRQ + bool -config ZERO_PAGE_OFFSET - hex "Zero page offset" - default "0x00001000" if !(SH_MPC1211 || SH_SH03) - default "0x00004000" if SH_MPC1211 || SH_SH03 +config CPU_HAS_SR_RB + bool "CPU has SR.RB" + depends on CPU_SH3 || CPU_SH4 + default y help - This sets the default offset of zero page. + This will enable the use of SR.RB register bank usage. Processors + that are lacking this bit must have another method in place for + accomplishing what is taken care of by the banked registers. -# XXX: needs to lose subtype for system type -config ST40_LMI_MEMORY - bool "Memory on LMI" - depends on CPU_SUBTYPE_ST40STB1 + See <file:Documentation/sh/register-banks.txt> for further + information on SR.RB and register banking in the kernel in general. -config MEMORY_START - hex - depends on CPU_SUBTYPE_ST40STB1 && ST40_LMI_MEMORY - default "0x08000000" +endmenu -config MEMORY_SIZE - hex - depends on CPU_SUBTYPE_ST40STB1 && ST40_LMI_MEMORY - default "0x00400000" +menu "Timer support" -config MEMORY_SET - bool - depends on CPU_SUBTYPE_ST40STB1 && ST40_LMI_MEMORY +config SH_TMU + bool "TMU timer support" default y - -config BOOT_LINK_OFFSET - hex "Link address offset for booting" - default "0x00800000" help - This option allows you to set the link address offset of the zImage. - This can be useful if you are on a board which has a small amount of - memory. + This enables the use of the TMU as the system timer. -config CPU_LITTLE_ENDIAN - bool "Little Endian" - help - Some SuperH machines can be configured for either little or big - endian byte order. These modes require different kernels. Say Y if - your machine is little endian, N if it's a big endian machine. +endmenu -config PREEMPT - bool "Preemptible Kernel (EXPERIMENTAL)" - depends on EXPERIMENTAL +source "arch/sh/boards/renesas/hs7751rvoip/Kconfig" -config UBC_WAKEUP - bool "Wakeup UBC on startup" +source "arch/sh/boards/renesas/rts7751r2d/Kconfig" + +config SH_PCLK_FREQ_BOOL + bool "Set default pclk frequency" + default y if !SH_RTC + default n + +config SH_PCLK_FREQ + int "Peripheral clock frequency (in Hz)" + depends on SH_PCLK_FREQ_BOOL + default "50000000" if CPU_SUBTYPE_SH7750 || CPU_SUBTYPE_SH7780 + default "60000000" if CPU_SUBTYPE_SH7751 + default "33333333" if CPU_SUBTYPE_SH7300 || CPU_SUBTYPE_SH7770 || CPU_SUBTYPE_SH7760 + default "27000000" if CPU_SUBTYPE_SH73180 + default "66000000" if CPU_SUBTYPE_SH4_202 help - Selecting this option will wakeup the User Break Controller (UBC) on - startup. Although the UBC is left in an awake state when the processor - comes up, some boot loaders misbehave by putting the UBC to sleep in a - power saving state, which causes issues with things like ptrace(). + This option is used to specify the peripheral clock frequency. + This is necessary for determining the reference clock value on + platforms lacking an RTC. - If unsure, say N. +menu "CPU Frequency scaling" + +source "drivers/cpufreq/Kconfig" -config SH_WRITETHROUGH - bool "Use write-through caching" - default y if CPU_SH2 +config SH_CPU_FREQ + tristate "SuperH CPU Frequency driver" + depends on CPU_FREQ + select CPU_FREQ_TABLE help - Selecting this option will configure the caches in write-through - mode, as opposed to the default write-back configuration. + This adds the cpufreq driver for SuperH. At present, only + the SH-4 is supported. - Since there's sill some aliasing issues on SH-4, this option will - unfortunately still require the majority of flushing functions to - be implemented to deal with aliasing. + For details, take a look at <file:Documentation/cpu-freq>. If unsure, say N. -config SH_OCRAM - bool "Operand Cache RAM (OCRAM) support" +endmenu + +source "arch/sh/drivers/dma/Kconfig" + +source "arch/sh/cchips/Kconfig" + +config HEARTBEAT + bool "Heartbeat LED" + depends on SH_MPC1211 || SH_SH03 || SH_CAT68701 || \ + SH_STB1_HARP || SH_STB1_OVERDRIVE || SH_BIGSUR || \ + SH_7751_SOLUTION_ENGINE || SH_7300_SOLUTION_ENGINE || \ + SH_73180_SOLUTION_ENGINE || SH_SOLUTION_ENGINE || \ + SH_RTS7751R2D || SH_SH4202_MICRODEV || SH_LANDISK help - Selecting this option will automatically tear down the number of - sets in the dcache by half, which in turn exposes a memory range. + Use the power-on LED on your machine as a load meter. The exact + behavior is platform-dependent, but normally the flash frequency is + a hyperbolic function of the 5-minute load average. - The addresses for the OC RAM base will vary according to the - processor version. Consult vendor documentation for specifics. +endmenu - If unsure, say N. +config ISA_DMA_API + bool + depends on MPC1211 + default y -config SH_STORE_QUEUES - bool "Support for Store Queues" - depends on CPU_SH4 +menu "Kernel features" + +config KEXEC + bool "kexec system call (EXPERIMENTAL)" + depends on EXPERIMENTAL help - Selecting this option will enable an in-kernel API for manipulating - the store queues integrated in the SH-4 processors. + kexec is a system call that implements the ability to shutdown your + current kernel, and to start another kernel. It is like a reboot + but it is indepedent of the system firmware. And like a reboot + you can start any kernel with it, not just Linux. + + The name comes from the similiarity to the exec system call. + + It is an ongoing process to be certain the hardware in a machine + is properly shutdown, so do not be surprised if this code does not + initially work for you. It may help to enable device hotplugging + support. As of this writing the exact hardware interface is + strongly in flux, so no good recommendation can be made. + +config PREEMPT + bool "Preemptible Kernel (EXPERIMENTAL)" + depends on EXPERIMENTAL config SMP bool "Symmetric multi-processing support" @@ -610,87 +513,58 @@ config NR_CPUS This is purely to save memory - each supported CPU adds approximately eight kilobytes to the kernel image. -config HS7751RVOIP_CODEC - bool "Support VoIP Codec section" - depends on SH_HS7751RVOIP - help - Selecting this option will support CODEC section. - -config RTS7751R2D_REV11 - bool "RTS7751R2D Rev. 1.1 board support" - depends on SH_RTS7751R2D - help - Selecting this option will support version rev. 1.1. - -config SH_PCLK_CALC - bool - default n if CPU_SUBTYPE_SH7300 || CPU_SUBTYPE_SH73180 +config CPU_HAS_SR_RB + bool "CPU has SR.RB" + depends on CPU_SH3 || CPU_SH4 default y help - This option will cause the PCLK value to be probed at run-time. It - will display a notification if the probed value has greater than a - 1% variance of the hardcoded CONFIG_SH_PCLK_FREQ. + This will enable the use of SR.RB register bank usage. Processors + that are lacking this bit must have another method in place for + accomplishing what is taken care of by the banked registers. -config SH_PCLK_FREQ - int "Peripheral clock frequency (in Hz)" - default "50000000" if CPU_SUBTYPE_SH7750 - default "60000000" if CPU_SUBTYPE_SH7751 - default "33333333" if CPU_SUBTYPE_SH7300 - default "27000000" if CPU_SUBTYPE_SH73180 - default "66000000" if CPU_SUBTYPE_SH4_202 - default "1193182" - help - This option is used to specify the peripheral clock frequency. This - option must be set for each processor in order for the kernel to - function reliably. If no sane default exists, we use a default from - the legacy i8254. Any discrepancies will be reported on boot time - with an auto-probed frequency which should be considered the proper - value for your hardware. + See <file:Documentation/sh/register-banks.txt> for further + information on SR.RB and register banking in the kernel in general. -menu "CPU Frequency scaling" +endmenu -source "drivers/cpufreq/Kconfig" +menu "Boot options" -config SH_CPU_FREQ - tristate "SuperH CPU Frequency driver" - depends on CPU_FREQ - select CPU_FREQ_TABLE +config ZERO_PAGE_OFFSET + hex "Zero page offset" + default "0x00004000" if SH_MPC1211 || SH_SH03 + default "0x00001000" help - This adds the cpufreq driver for SuperH. At present, only - the SH-4 is supported. - - For details, take a look at <file:Documentation/cpu-freq>. - - If unsure, say N. + This sets the default offset of zero page. -endmenu +config BOOT_LINK_OFFSET + hex "Link address offset for booting" + default "0x00800000" + help + This option allows you to set the link address offset of the zImage. + This can be useful if you are on a board which has a small amount of + memory. -source "arch/sh/drivers/dma/Kconfig" +config UBC_WAKEUP + bool "Wakeup UBC on startup" + help + Selecting this option will wakeup the User Break Controller (UBC) on + startup. Although the UBC is left in an awake state when the processor + comes up, some boot loaders misbehave by putting the UBC to sleep in a + power saving state, which causes issues with things like ptrace(). -source "arch/sh/cchips/Kconfig" + If unsure, say N. -config HEARTBEAT - bool "Heartbeat LED" - depends on SH_MPC1211 || SH_SH03 || SH_CAT68701 || SH_STB1_HARP || SH_STB1_OVERDRIVE || SH_BIGSUR || SH_7751_SOLUTION_ENGINE || SH_7300_SOLUTION_ENGINE || SH_73180_SOLUTION_ENGINE || SH_SOLUTION_ENGINE || SH_RTS7751R2D || SH_SH4202_MICRODEV - help - Use the power-on LED on your machine as a load meter. The exact - behavior is platform-dependent, but normally the flash frequency is - a hyperbolic function of the 5-minute load average. +config CMDLINE_BOOL + bool "Default bootloader kernel arguments" -config RTC_9701JE - tristate "EPSON RTC-9701JE support" - depends on SH_RTS7751R2D - help - Selecting this option will support EPSON RTC-9701JE. +config CMDLINE + string "Initial kernel command string" + depends on CMDLINE_BOOL + default "console=ttySC1,115200" endmenu -config ISA_DMA_API - bool - depends on MPC1211 - default y - -menu "Bus options (PCI, PCMCIA, EISA, MCA, ISA)" +menu "Bus options" # Even on SuperH devices which don't have an ISA bus, # this variable helps the PCMCIA modules handle @@ -701,7 +575,7 @@ menu "Bus options (PCI, PCMCIA, EISA, MCA, ISA)" # PCMCIA outright. -- PFM. config ISA bool - default y if PCMCIA || SMC91X + default y if PCMCIA 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 @@ -735,10 +609,9 @@ config MCA config SBUS bool -config MAPLE - tristate "Maple Bus support" - depends on SH_DREAMCAST - default y +config SUPERHYWAY + tristate "SuperHyway Bus support" + depends on CPU_SUBTYPE_SH4_202 source "arch/sh/drivers/pci/Kconfig" diff --git a/arch/sh/Kconfig.debug b/arch/sh/Kconfig.debug index 3fab181da36..8fb31ab2c02 100644 --- a/arch/sh/Kconfig.debug +++ b/arch/sh/Kconfig.debug @@ -17,7 +17,7 @@ config SH_STANDARD_BIOS config EARLY_SCIF_CONSOLE bool "Use early SCIF console" - depends on CPU_SH4 + depends on CPU_SH4 || CPU_SH2A && !SH_STANDARD_BIOS config EARLY_PRINTK bool "Early printk support" diff --git a/arch/sh/Makefile b/arch/sh/Makefile index 67192d6b00d..08c9515c480 100644 --- a/arch/sh/Makefile +++ b/arch/sh/Makefile @@ -17,10 +17,30 @@ cflags-y := -mb cflags-$(CONFIG_CPU_LITTLE_ENDIAN) := -ml +isa-y := any +isa-$(CONFIG_CPU_SH2) := sh2 +isa-$(CONFIG_CPU_SH3) := sh3 +isa-$(CONFIG_CPU_SH4) := sh4 +isa-$(CONFIG_CPU_SH4A) := sh4a +isa-$(CONFIG_CPU_SH2A) := sh2a + +isa-$(CONFIG_SH_DSP) := $(isa-y)-dsp + +ifndef CONFIG_MMU +isa-y := $(isa-y)-nommu +endif + +ifndef CONFIG_SH_FPU +isa-y := $(isa-y)-nofpu +endif + +cflags-y += $(call as-option,-Wa$(comma)-isa=$(isa-y),) + cflags-$(CONFIG_CPU_SH2) += -m2 cflags-$(CONFIG_CPU_SH3) += -m3 cflags-$(CONFIG_CPU_SH4) += -m4 \ $(call cc-option,-mno-implicit-fp,-m4-nofpu) +cflags-$(CONFIG_CPU_SH4A) += $(call cc-option,-m4a-nofpu,) cflags-$(CONFIG_SH_DSP) += -Wa,-dsp cflags-$(CONFIG_SH_KGDB) += -g @@ -67,9 +87,7 @@ machdir-$(CONFIG_SH_7300_SOLUTION_ENGINE) := se/7300 machdir-$(CONFIG_SH_73180_SOLUTION_ENGINE) := se/73180 machdir-$(CONFIG_SH_STB1_HARP) := harp machdir-$(CONFIG_SH_STB1_OVERDRIVE) := overdrive -machdir-$(CONFIG_SH_HP620) := hp6xx/hp620 -machdir-$(CONFIG_SH_HP680) := hp6xx/hp680 -machdir-$(CONFIG_SH_HP690) := hp6xx/hp690 +machdir-$(CONFIG_SH_HP6XX) := hp6xx machdir-$(CONFIG_SH_CQREEK) := cqreek machdir-$(CONFIG_SH_DMIDA) := dmida machdir-$(CONFIG_SH_EC3104) := ec3104 @@ -119,31 +137,39 @@ boot := arch/sh/boot CPPFLAGS_vmlinux.lds := -traditional +ifneq ($(KBUILD_SRC),) +incdir-prefix := $(srctree)/include/asm-sh/ +else +incdir-prefix := +endif + # Update machine arch and proc symlinks if something which affects # them changed. We use .arch and .mach to indicate when they were # updated last, otherwise make uses the target directory mtime. include/asm-sh/.cpu: $(wildcard include/config/cpu/*.h) include/config/MARKER @echo ' SYMLINK include/asm-sh/cpu -> include/asm-sh/$(cpuincdir-y)' -ifneq ($(KBUILD_SRC),) - $(Q)mkdir -p include/asm-sh - $(Q)ln -fsn $(srctree)/include/asm-sh/$(cpuincdir-y) include/asm-sh/cpu -else - $(Q)ln -fsn $(cpuincdir-y) include/asm-sh/cpu -endif + $(Q)if [ ! -d include/asm-sh ]; then mkdir -p include/asm-sh; fi + $(Q)ln -fsn $(incdir-prefix)$(cpuincdir-y) include/asm-sh/cpu @touch $@ +# Most boards have their own mach directories. For the ones that +# don't, just reference the parent directory so the semantics are +# kept roughly the same. + include/asm-sh/.mach: $(wildcard include/config/sh/*.h) include/config/MARKER - @echo ' SYMLINK include/asm-sh/mach -> include/asm-sh/$(incdir-y)' -ifneq ($(KBUILD_SRC),) - $(Q)mkdir -p include/asm-sh - $(Q)ln -fsn $(srctree)/include/asm-sh/$(incdir-y) include/asm-sh/mach -else - $(Q)ln -fsn $(incdir-y) include/asm-sh/mach -endif + @echo -n ' SYMLINK include/asm-sh/mach -> ' + $(Q)if [ ! -d include/asm-sh ]; then mkdir -p include/asm-sh; fi + $(Q)if [ -d $(incdir-prefix)$(incdir-y) ]; then \ + echo -e 'include/asm-sh/$(incdir-y)'; \ + ln -fsn $(incdir-prefix)$(incdir-y) \ + include/asm-sh/mach; \ + else \ + echo -e 'include/asm-sh'; \ + ln -fsn $(incdir-prefix) include/asm-sh/mach; \ + fi @touch $@ - archprepare: maketools include/asm-sh/.cpu include/asm-sh/.mach .PHONY: maketools FORCE diff --git a/arch/sh/boards/hp6xx/Makefile b/arch/sh/boards/hp6xx/Makefile new file mode 100644 index 00000000000..927fe0aa5df --- /dev/null +++ b/arch/sh/boards/hp6xx/Makefile @@ -0,0 +1,6 @@ +# +# Makefile for the HP6xx specific parts of the kernel +# + +obj-y := mach.o setup.o + diff --git a/arch/sh/boards/hp6xx/hp620/Makefile b/arch/sh/boards/hp6xx/hp620/Makefile deleted file mode 100644 index 20691dbce34..00000000000 --- a/arch/sh/boards/hp6xx/hp620/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -# -# Makefile for the HP620 specific parts of the kernel -# - -obj-y := mach.o setup.o - diff --git a/arch/sh/boards/hp6xx/hp620/mach.c b/arch/sh/boards/hp6xx/hp620/mach.c deleted file mode 100644 index 0392d82b4a7..00000000000 --- a/arch/sh/boards/hp6xx/hp620/mach.c +++ /dev/null @@ -1,52 +0,0 @@ -/* - * linux/arch/sh/boards/hp6xx/hp620/mach.c - * - * Copyright (C) 2000 Stuart Menefy (stuart.menefy@st.com) - * - * May be copied or modified under the terms of the GNU General Public - * License. See linux/COPYING for more information. - * - * Machine vector for the HP620 - */ - -#include <linux/init.h> - -#include <asm/machvec.h> -#include <asm/rtc.h> -#include <asm/machvec_init.h> - -#include <asm/io.h> -#include <asm/hd64461/hd64461.h> -#include <asm/irq.h> - -/* - * The Machine Vector - */ - -struct sh_machine_vector mv_hp620 __initmv = { - .mv_nr_irqs = HD64461_IRQBASE+HD64461_IRQ_NUM, - - .mv_inb = hd64461_inb, - .mv_inw = hd64461_inw, - .mv_inl = hd64461_inl, - .mv_outb = hd64461_outb, - .mv_outw = hd64461_outw, - .mv_outl = hd64461_outl, - - .mv_inb_p = hd64461_inb_p, - .mv_inw_p = hd64461_inw, - .mv_inl_p = hd64461_inl, - .mv_outb_p = hd64461_outb_p, - .mv_outw_p = hd64461_outw, - .mv_outl_p = hd64461_outl, - - .mv_insb = hd64461_insb, - .mv_insw = hd64461_insw, - .mv_insl = hd64461_insl, - .mv_outsb = hd64461_outsb, - .mv_outsw = hd64461_outsw, - .mv_outsl = hd64461_outsl, - - .mv_irq_demux = hd64461_irq_demux, -}; -ALIAS_MV(hp620) diff --git a/arch/sh/boards/hp6xx/hp620/setup.c b/arch/sh/boards/hp6xx/hp620/setup.c deleted file mode 100644 index 045fc5da727..00000000000 --- a/arch/sh/boards/hp6xx/hp620/setup.c +++ /dev/null @@ -1,45 +0,0 @@ -/* - * linux/arch/sh/boards/hp6xx/hp620/setup.c - * - * Copyright (C) 2002 Andriy Skulysh, 2005 Kristoffer Ericson - * - * May be copied or modified under the terms of the GNU General Public - * License. See Linux/COPYING for more information. - * - * Setup code for an HP620. - * Due to similiarity with hp680/hp690 same inits are done (for now) - */ - -#include <linux/config.h> -#include <linux/init.h> -#include <asm/hd64461/hd64461.h> -#include <asm/io.h> -#include <asm/hp6xx/hp6xx.h> -#include <asm/cpu/dac.h> - -const char *get_system_type(void) -{ - return "HP620"; -} - -int __init platform_setup(void) -{ - u16 v; - - v = inw(HD64461_STBCR); - v |= HD64461_STBCR_SURTST | HD64461_STBCR_SIRST | - HD64461_STBCR_STM1ST | HD64461_STBCR_STM0ST | - HD64461_STBCR_SAFEST | HD64461_STBCR_SPC0ST | - HD64461_STBCR_SMIAST | HD64461_STBCR_SAFECKE_OST | - HD64461_STBCR_SAFECKE_IST; - outw(v, HD64461_STBCR); - - v = inw(HD64461_GPADR); - v |= HD64461_GPADR_SPEAKER | HD64461_GPADR_PCMCIA0; - outw(v, HD64461_GPADR); - - sh_dac_disable(DAC_SPEAKER_VOLUME); - - return 0; -} - diff --git a/arch/sh/boards/hp6xx/hp680/Makefile b/arch/sh/boards/hp6xx/hp680/Makefile deleted file mode 100644 index 0beef11d9b1..00000000000 --- a/arch/sh/boards/hp6xx/hp680/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -# -# Makefile for the HP680 specific parts of the kernel -# - -obj-y := mach.o setup.o - diff --git a/arch/sh/boards/hp6xx/hp690/Makefile b/arch/sh/boards/hp6xx/hp690/Makefile deleted file mode 100644 index fbbe95e75f8..00000000000 --- a/arch/sh/boards/hp6xx/hp690/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -# -# Makefile for the HP690 specific parts of the kernel -# - -obj-y := mach.o - diff --git a/arch/sh/boards/hp6xx/hp690/mach.c b/arch/sh/boards/hp6xx/hp690/mach.c deleted file mode 100644 index 2a4c68783cd..00000000000 --- a/arch/sh/boards/hp6xx/hp690/mach.c +++ /dev/null @@ -1,48 +0,0 @@ -/* - * linux/arch/sh/boards/hp6xx/hp690/mach.c - * - * Copyright (C) 2000 Stuart Menefy (stuart.menefy@st.com) - * - * May be copied or modified under the terms of the GNU General Public - * License. See linux/COPYING for more information. - * - * Machine vector for the HP690 - */ - -#include <linux/init.h> - -#include <asm/machvec.h> -#include <asm/rtc.h> -#include <asm/machvec_init.h> - -#include <asm/io.h> -#include <asm/hd64461/hd64461.h> -#include <asm/irq.h> - -struct sh_machine_vector mv_hp690 __initmv = { - .mv_nr_irqs = HD64461_IRQBASE+HD64461_IRQ_NUM, - - .mv_inb = hd64461_inb, - .mv_inw = hd64461_inw, - .mv_inl = hd64461_inl, - .mv_outb = hd64461_outb, - .mv_outw = hd64461_outw, - .mv_outl = hd64461_outl, - - .mv_inb_p = hd64461_inb_p, - .mv_inw_p = hd64461_inw, - .mv_inl_p = hd64461_inl, - .mv_outb_p = hd64461_outb_p, - .mv_outw_p = hd64461_outw, - .mv_outl_p = hd64461_outl, - - .mv_insb = hd64461_insb, - .mv_insw = hd64461_insw, - .mv_insl = hd64461_insl, - .mv_outsb = hd64461_outsb, - .mv_outsw = hd64461_outsw, - .mv_outsl = hd64461_outsl, - - .mv_irq_demux = hd64461_irq_demux, -}; -ALIAS_MV(hp690) diff --git a/arch/sh/boards/hp6xx/hp680/mach.c b/arch/sh/boards/hp6xx/mach.c index d7348613604..08dbba910f7 100644 --- a/arch/sh/boards/hp6xx/hp680/mach.c +++ b/arch/sh/boards/hp6xx/mach.c @@ -1,5 +1,5 @@ /* - * linux/arch/sh/boards/hp6xx/hp680/mach.c + * linux/arch/sh/boards/hp6xx/mach.c * * Copyright (C) 2000 Stuart Menefy (stuart.menefy@st.com) * @@ -8,19 +8,12 @@ * * Machine vector for the HP680 */ - -#include <linux/init.h> - #include <asm/machvec.h> -#include <asm/rtc.h> -#include <asm/machvec_init.h> - +#include <asm/hd64461.h> #include <asm/io.h> -#include <asm/hd64461/hd64461.h> -#include <asm/hp6xx/io.h> #include <asm/irq.h> -struct sh_machine_vector mv_hp680 __initmv = { +struct sh_machine_vector mv_hp6xx __initmv = { .mv_nr_irqs = HD64461_IRQBASE + HD64461_IRQ_NUM, .mv_inb = hd64461_inb, @@ -50,4 +43,4 @@ struct sh_machine_vector mv_hp680 __initmv = { .mv_irq_demux = hd64461_irq_demux, }; -ALIAS_MV(hp680) +ALIAS_MV(hp6xx) diff --git a/arch/sh/boards/hp6xx/hp680/setup.c b/arch/sh/boards/hp6xx/setup.c index 4170190f264..6d94a8e2e67 100644 --- a/arch/sh/boards/hp6xx/hp680/setup.c +++ b/arch/sh/boards/hp6xx/setup.c @@ -11,18 +11,19 @@ #include <linux/config.h> #include <linux/init.h> -#include <asm/hd64461/hd64461.h> #include <asm/io.h> +#include <asm/hd64461.h> #include <asm/hp6xx/hp6xx.h> #include <asm/cpu/dac.h> const char *get_system_type(void) { - return "HP680"; + return "HP6xx"; } int __init platform_setup(void) { + u8 v8; u16 v; v = inw(HD64461_STBCR); v |= HD64461_STBCR_SURTST | HD64461_STBCR_SIRST | @@ -30,12 +31,25 @@ int __init platform_setup(void) HD64461_STBCR_SAFEST | HD64461_STBCR_SPC0ST | HD64461_STBCR_SMIAST | HD64461_STBCR_SAFECKE_OST | HD64461_STBCR_SAFECKE_IST; +#ifndef CONFIG_HD64461_ENABLER + v |= HD64461_STBCR_SPC1ST; +#endif outw(v, HD64461_STBCR); v = inw(HD64461_GPADR); v |= HD64461_GPADR_SPEAKER | HD64461_GPADR_PCMCIA0; outw(v, HD64461_GPADR); + outw(HD64461_PCCGCR_VCC0 | HD64461_PCCSCR_VCC1, HD64461_PCC0GCR); + +#ifndef CONFIG_HD64461_ENABLER + outw(HD64461_PCCGCR_VCC0 | HD64461_PCCSCR_VCC1, HD64461_PCC1GCR); +#endif + + sh_dac_output(0, DAC_SPEAKER_VOLUME); sh_dac_disable(DAC_SPEAKER_VOLUME); + v8 = ctrl_inb(DACR); + v8 &= ~DACR_DAE; + ctrl_outb(v8,DACR); return 0; } diff --git a/arch/sh/boards/overdrive/Makefile b/arch/sh/boards/overdrive/Makefile index 1762b59e927..245f03baf76 100644 --- a/arch/sh/boards/overdrive/Makefile +++ b/arch/sh/boards/overdrive/Makefile @@ -2,7 +2,7 @@ # Makefile for the STMicroelectronics Overdrive specific parts of the kernel # -obj-y := mach.o setup.o io.o irq.o led.o time.o +obj-y := mach.o setup.o io.o irq.o led.o obj-$(CONFIG_PCI) += fpga.o galileo.o pcidma.o diff --git a/arch/sh/boards/overdrive/setup.c b/arch/sh/boards/overdrive/setup.c index a36ce0284ed..94f6165d33b 100644 --- a/arch/sh/boards/overdrive/setup.c +++ b/arch/sh/boards/overdrive/setup.c @@ -17,8 +17,6 @@ #include <asm/overdrive/overdrive.h> #include <asm/overdrive/fpga.h> -extern void od_time_init(void); - const char *get_system_type(void) { return "SH7750 Overdrive"; @@ -31,11 +29,9 @@ int __init platform_setup(void) { #ifdef CONFIG_PCI init_overdrive_fpga(); - galileo_init(); + galileo_init(); #endif - board_time_init = od_time_init; - /* Enable RS232 receive buffers */ writel(0x1e, OVERDRIVE_CTRL); } diff --git a/arch/sh/boards/overdrive/time.c b/arch/sh/boards/overdrive/time.c deleted file mode 100644 index 68533690e09..00000000000 --- a/arch/sh/boards/overdrive/time.c +++ /dev/null @@ -1,119 +0,0 @@ -/* - * arch/sh/boards/overdrive/time.c - * - * Copyright (C) 2000 Stuart Menefy (stuart.menefy@st.com) - * Copyright (C) 2002 Paul Mundt (lethal@chaoticdreams.org) - * - * May be copied or modified under the terms of the GNU General Public - * License. See linux/COPYING for more information. - * - * STMicroelectronics Overdrive Support. - */ - -void od_time_init(void) -{ - struct frqcr_data { - unsigned short frqcr; - struct { - unsigned char multiplier; - unsigned char divisor; - } factor[3]; - }; - - static struct frqcr_data st40_frqcr_table[] = { - { 0x000, {{1,1}, {1,1}, {1,2}}}, - { 0x002, {{1,1}, {1,1}, {1,4}}}, - { 0x004, {{1,1}, {1,1}, {1,8}}}, - { 0x008, {{1,1}, {1,2}, {1,2}}}, - { 0x00A, {{1,1}, {1,2}, {1,4}}}, - { 0x00C, {{1,1}, {1,2}, {1,8}}}, - { 0x011, {{1,1}, {2,3}, {1,6}}}, - { 0x013, {{1,1}, {2,3}, {1,3}}}, - { 0x01A, {{1,1}, {1,2}, {1,4}}}, - { 0x01C, {{1,1}, {1,2}, {1,8}}}, - { 0x023, {{1,1}, {2,3}, {1,3}}}, - { 0x02C, {{1,1}, {1,2}, {1,8}}}, - { 0x048, {{1,2}, {1,2}, {1,4}}}, - { 0x04A, {{1,2}, {1,2}, {1,6}}}, - { 0x04C, {{1,2}, {1,2}, {1,8}}}, - { 0x05A, {{1,2}, {1,3}, {1,6}}}, - { 0x05C, {{1,2}, {1,3}, {1,6}}}, - { 0x063, {{1,2}, {1,4}, {1,4}}}, - { 0x06C, {{1,2}, {1,4}, {1,8}}}, - { 0x091, {{1,3}, {1,3}, {1,6}}}, - { 0x093, {{1,3}, {1,3}, {1,6}}}, - { 0x0A3, {{1,3}, {1,6}, {1,6}}}, - { 0x0DA, {{1,4}, {1,4}, {1,8}}}, - { 0x0DC, {{1,4}, {1,4}, {1,8}}}, - { 0x0EC, {{1,4}, {1,8}, {1,8}}}, - { 0x123, {{1,4}, {1,4}, {1,8}}}, - { 0x16C, {{1,4}, {1,8}, {1,8}}}, - }; - - struct memclk_data { - unsigned char multiplier; - unsigned char divisor; - }; - static struct memclk_data st40_memclk_table[8] = { - {1,1}, // 000 - {1,2}, // 001 - {1,3}, // 010 - {2,3}, // 011 - {1,4}, // 100 - {1,6}, // 101 - {1,8}, // 110 - {1,8} // 111 - }; - - unsigned long pvr; - - /* - * This should probably be moved into the SH3 probing code, and then - * use the processor structure to determine which CPU we are running - * on. - */ - pvr = ctrl_inl(CCN_PVR); - printk("PVR %08x\n", pvr); - - if (((pvr >> CCN_PVR_CHIP_SHIFT) & CCN_PVR_CHIP_MASK) == CCN_PVR_CHIP_ST40STB1) { - /* - * Unfortunatly the STB1 FRQCR values are different from the - * 7750 ones. - */ - struct frqcr_data *d; - int a; - unsigned long memclkcr; - struct memclk_data *e; - - for (a=0; a<ARRAY_SIZE(st40_frqcr_table); a++) { - d = &st40_frqcr_table[a]; - if (d->frqcr == (frqcr & 0x1ff)) - break; - } - if (a == ARRAY_SIZE(st40_frqcr_table)) { - d = st40_frqcr_table; - printk("ERROR: Unrecognised FRQCR value, using default multipliers\n"); - } - - memclkcr = ctrl_inl(CLOCKGEN_MEMCLKCR); - e = &st40_memclk_table[memclkcr & MEMCLKCR_RATIO_MASK]; - - printk("Clock multipliers: CPU: %d/%d Bus: %d/%d Mem: %d/%d Periph: %d/%d\n", - d->factor[0].multiplier, d->factor[0].divisor, - d->factor[1].multiplier, d->factor[1].divisor, - e->multiplier, e->divisor, - d->factor[2].multiplier, d->factor[2].divisor); - - current_cpu_data.master_clock = current_cpu_data.module_clock * - d->factor[2].divisor / - d->factor[2].multiplier; - current_cpu_data.bus_clock = current_cpu_data.master_clock * - d->factor[1].multiplier / - d->factor[1].divisor; - current_cpu_data.memory_clock = current_cpu_data.master_clock * - e->multiplier / e->divisor; - current_cpu_data.cpu_clock = current_cpu_data.master_clock * - d->factor[0].multiplier / - d->factor[0].divisor; -} - diff --git a/arch/sh/configs/hp680_defconfig b/arch/sh/configs/hp6xx_defconfig index c85d3655b53..b36f102cec8 100644 --- a/arch/sh/configs/hp680_defconfig +++ b/arch/sh/configs/hp6xx_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.11-sh -# Wed Mar 2 15:09:41 2005 +# Linux kernel version: 2.6.15-sh +# Wed Jan 4 15:32:56 2006 # CONFIG_SUPERH=y CONFIG_UID16=y @@ -17,31 +17,36 @@ CONFIG_EXPERIMENTAL=y # CONFIG_CLEAN_COMPILE is not set CONFIG_BROKEN=y CONFIG_BROKEN_ON_SMP=y +CONFIG_INIT_ENV_ARG_LIMIT=32 # # General setup # CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y CONFIG_SWAP=y # CONFIG_SYSVIPC is not set # CONFIG_BSD_PROCESS_ACCT is not set # CONFIG_SYSCTL is not set -# CONFIG_AUDIT is not set -CONFIG_LOG_BUF_SHIFT=14 -# CONFIG_HOTPLUG is not set +CONFIG_HOTPLUG=y # CONFIG_IKCONFIG is not set +CONFIG_INITRAMFS_SOURCE="" +CONFIG_CC_OPTIMIZE_FOR_SIZE=y # CONFIG_EMBEDDED is not set CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_BASE_FULL=y CONFIG_FUTEX=y CONFIG_EPOLL=y -# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set CONFIG_SHMEM=y CONFIG_CC_ALIGN_FUNCTIONS=0 CONFIG_CC_ALIGN_LABELS=0 CONFIG_CC_ALIGN_LOOPS=0 CONFIG_CC_ALIGN_JUMPS=0 # CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 # # Loadable module support @@ -49,6 +54,24 @@ CONFIG_CC_ALIGN_JUMPS=0 # CONFIG_MODULES is not set # +# Block layer +# +# CONFIG_LBD is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +CONFIG_DEFAULT_AS=y +# CONFIG_DEFAULT_DEADLINE is not set +# CONFIG_DEFAULT_CFQ is not set +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="anticipatory" + +# # System type # # CONFIG_SH_SOLUTION_ENGINE is not set @@ -58,9 +81,7 @@ CONFIG_CC_ALIGN_JUMPS=0 # CONFIG_SH_7751_SYSTEMH is not set # CONFIG_SH_STB1_HARP is not set # CONFIG_SH_STB1_OVERDRIVE is not set -# CONFIG_SH_HP620 is not set -CONFIG_SH_HP680=y -# CONFIG_SH_HP690 is not set +CONFIG_SH_HP6XX=y # CONFIG_SH_CQREEK is not set # CONFIG_SH_DMIDA is not set # CONFIG_SH_EC3104 is not set @@ -77,43 +98,90 @@ CONFIG_SH_HP680=y # CONFIG_SH_RTS7751R2D is not set # CONFIG_SH_EDOSK7705 is not set # CONFIG_SH_SH4202_MICRODEV is not set +# CONFIG_SH_LANDISK is not set +# CONFIG_SH_TITAN is not set # CONFIG_SH_UNKNOWN is not set -# CONFIG_CPU_SH2 is not set + +# +# Processor selection +# CONFIG_CPU_SH3=y -# CONFIG_CPU_SH4 is not set + +# +# SH-2 Processor Support +# # CONFIG_CPU_SUBTYPE_SH7604 is not set + +# +# SH-3 Processor Support +# # CONFIG_CPU_SUBTYPE_SH7300 is not set # CONFIG_CPU_SUBTYPE_SH7705 is not set # CONFIG_CPU_SUBTYPE_SH7707 is not set # CONFIG_CPU_SUBTYPE_SH7708 is not set CONFIG_CPU_SUBTYPE_SH7709=y + +# +# SH-4 Processor Support +# # CONFIG_CPU_SUBTYPE_SH7750 is not set +# CONFIG_CPU_SUBTYPE_SH7091 is not set +# CONFIG_CPU_SUBTYPE_SH7750R is not set +# CONFIG_CPU_SUBTYPE_SH7750S is not set # CONFIG_CPU_SUBTYPE_SH7751 is not set +# CONFIG_CPU_SUBTYPE_SH7751R is not set # CONFIG_CPU_SUBTYPE_SH7760 is not set -# CONFIG_CPU_SUBTYPE_SH73180 is not set +# CONFIG_CPU_SUBTYPE_SH4_202 is not set + +# +# ST40 Processor Support +# # CONFIG_CPU_SUBTYPE_ST40STB1 is not set # CONFIG_CPU_SUBTYPE_ST40GX1 is not set -# CONFIG_CPU_SUBTYPE_SH4_202 is not set + +# +# SH-4A Processor Support +# +# CONFIG_CPU_SUBTYPE_SH73180 is not set +# CONFIG_CPU_SUBTYPE_SH7770 is not set +# CONFIG_CPU_SUBTYPE_SH7780 is not set + +# +# Memory management options +# CONFIG_MMU=y -# CONFIG_CMDLINE_BOOL is not set +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +# CONFIG_SPARSEMEM_STATIC is not set +CONFIG_SPLIT_PTLOCK_CPUS=4 + +# +# Cache configuration +# +# CONFIG_SH_DIRECT_MAPPED is not set +# CONFIG_SH_WRITETHROUGH is not set +# CONFIG_SH_OCRAM is not set CONFIG_MEMORY_START=0x0c000000 CONFIG_MEMORY_SIZE=0x00400000 -CONFIG_MEMORY_SET=y -# CONFIG_MEMORY_OVERRIDE is not set + +# +# Processor features +# +CONFIG_CPU_LITTLE_ENDIAN=y CONFIG_SH_RTC=y # CONFIG_SH_DSP is not set CONFIG_SH_ADC=y -CONFIG_SH_HP600=y -CONFIG_ZERO_PAGE_OFFSET=0x00001000 -CONFIG_BOOT_LINK_OFFSET=0x00800000 -CONFIG_CPU_LITTLE_ENDIAN=y -# CONFIG_PREEMPT is not set -# CONFIG_UBC_WAKEUP is not set -# CONFIG_SH_WRITETHROUGH is not set -# CONFIG_SH_OCRAM is not set -# CONFIG_SMP is not set -CONFIG_SH_PCLK_CALC=y -CONFIG_SH_PCLK_FREQ=1193182 + +# +# Timer support +# +CONFIG_SH_TMU=y +CONFIG_SH_PCLK_FREQ_BOOL=y +CONFIG_SH_PCLK_FREQ=22110000 # # CPU Frequency scaling @@ -123,7 +191,10 @@ CONFIG_SH_PCLK_FREQ=1193182 # # DMA support # -# CONFIG_SH_DMA is not set +CONFIG_SH_DMA=y +CONFIG_NR_ONCHIP_DMA_CHANNELS=4 +# CONFIG_NR_DMA_CHANNELS_BOOL is not set +# CONFIG_DMA_PAGE_OPS is not set # # Companion Chips @@ -132,21 +203,47 @@ CONFIG_HD6446X_SERIES=y CONFIG_HD64461=y # CONFIG_HD64465 is not set CONFIG_HD64461_IRQ=36 -# CONFIG_HD64461_ENABLER is not set +CONFIG_HD64461_IOBASE=0xb0000000 +CONFIG_HD64461_ENABLER=y + +# +# Kernel features +# +# CONFIG_KEXEC is not set +# CONFIG_PREEMPT is not set +# CONFIG_SMP is not set # -# Bus options (PCI, PCMCIA, EISA, MCA, ISA) +# Boot options # +CONFIG_ZERO_PAGE_OFFSET=0x00001000 +CONFIG_BOOT_LINK_OFFSET=0x00800000 +# CONFIG_UBC_WAKEUP is not set +# CONFIG_CMDLINE_BOOL is not set + +# +# Bus options +# +CONFIG_ISA=y # CONFIG_PCI is not set # # PCCARD (PCMCIA/CardBus) support # -# CONFIG_PCCARD is not set +CONFIG_PCCARD=y +# CONFIG_PCMCIA_DEBUG is not set +CONFIG_PCMCIA=y +CONFIG_PCMCIA_LOAD_CIS=y +CONFIG_PCMCIA_IOCTL=y # # PC-card bridges # +# CONFIG_I82365 is not set +# CONFIG_TCIC is not set +CONFIG_HD64461_PCMCIA=y +CONFIG_HD64461_PCMCIA_SOCKETS=1 +CONFIG_PCMCIA_PROBE=y # # PCI Hotplug Support @@ -160,9 +257,9 @@ CONFIG_BINFMT_ELF=y # CONFIG_BINFMT_MISC is not set # -# SH initrd options +# Networking # -# CONFIG_EMBEDDED_RAMDISK is not set +# CONFIG_NET is not set # # Device Drivers @@ -173,7 +270,11 @@ CONFIG_BINFMT_ELF=y # # CONFIG_STANDALONE is not set CONFIG_PREVENT_FIRMWARE_BUILD=y -# CONFIG_FW_LOADER is not set +CONFIG_FW_LOADER=y + +# +# Connector - unified userspace <-> kernelspace linker +# # # Memory Technology Devices (MTD) @@ -188,30 +289,20 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y # # Plug and Play support # +# CONFIG_PNP is not set # # Block devices # -# CONFIG_BLK_DEV_FD is not set # CONFIG_BLK_DEV_COW_COMMON is not set # CONFIG_BLK_DEV_LOOP is not set CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_COUNT=16 CONFIG_BLK_DEV_RAM_SIZE=4096 CONFIG_BLK_DEV_INITRD=y -CONFIG_INITRAMFS_SOURCE="" -# CONFIG_LBD is not set # CONFIG_CDROM_PKTCDVD is not set # -# IO Schedulers -# -CONFIG_IOSCHED_NOOP=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y -CONFIG_IOSCHED_CFQ=y - -# # ATA/ATAPI/MFM/RLL support # CONFIG_IDE=y @@ -224,6 +315,7 @@ CONFIG_BLK_DEV_IDE=y # CONFIG_BLK_DEV_IDE_SATA is not set CONFIG_BLK_DEV_IDEDISK=y # CONFIG_IDEDISK_MULTI_MODE is not set +# CONFIG_BLK_DEV_IDECS is not set # CONFIG_BLK_DEV_IDECD is not set # CONFIG_BLK_DEV_IDETAPE is not set # CONFIG_BLK_DEV_IDEFLOPPY is not set @@ -235,6 +327,7 @@ CONFIG_BLK_DEV_IDEDISK=y CONFIG_IDE_GENERIC=y CONFIG_IDE_SH=y # CONFIG_IDE_ARM is not set +# CONFIG_IDE_CHIPSETS is not set # CONFIG_BLK_DEV_IDEDMA is not set # CONFIG_IDEDMA_AUTO is not set # CONFIG_BLK_DEV_HD is not set @@ -242,9 +335,15 @@ CONFIG_IDE_SH=y # # SCSI device support # +# CONFIG_RAID_ATTRS is not set # CONFIG_SCSI is not set # +# Old CD-ROM drivers (not SCSI, not IDE) +# +# CONFIG_CD_NO_IDESCSI is not set + +# # Multi-device support (RAID and LVM) # # CONFIG_MD is not set @@ -252,6 +351,7 @@ CONFIG_IDE_SH=y # # Fusion MPT device support # +# CONFIG_FUSION is not set # # IEEE 1394 (FireWire) support @@ -263,9 +363,8 @@ CONFIG_IDE_SH=y # # -# Networking support +# Network device support # -# CONFIG_NET is not set # CONFIG_NETPOLL is not set # CONFIG_NET_POLL_CONTROLLER is not set @@ -296,17 +395,6 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 # CONFIG_INPUT_EVBUG is not set # -# Input I/O drivers -# -# CONFIG_GAMEPORT is not set -CONFIG_SOUND_GAMEPORT=y -CONFIG_SERIO=y -# CONFIG_SERIO_I8042 is not set -# CONFIG_SERIO_SERPORT is not set -# CONFIG_SERIO_CT82C710 is not set -# CONFIG_SERIO_RAW is not set - -# # Input Device Drivers # # CONFIG_INPUT_KEYBOARD is not set @@ -316,6 +404,15 @@ CONFIG_SERIO=y # CONFIG_INPUT_MISC is not set # +# Hardware I/O ports +# +CONFIG_SERIO=y +# CONFIG_SERIO_I8042 is not set +# CONFIG_SERIO_SERPORT is not set +# CONFIG_SERIO_RAW is not set +# CONFIG_GAMEPORT is not set + +# # Character devices # CONFIG_VT=y @@ -353,10 +450,22 @@ CONFIG_LEGACY_PTY_COUNT=256 # # Ftape, the floppy tape device driver # -# CONFIG_DRM is not set + +# +# PCMCIA character devices +# +# CONFIG_SYNCLINK_CS is not set +# CONFIG_CARDMAN_4000 is not set +# CONFIG_CARDMAN_4040 is not set # CONFIG_RAW_DRIVER is not set # +# TPM devices +# +# CONFIG_TCG_TPM is not set +# CONFIG_TELCLOCK is not set + +# # I2C support # # CONFIG_I2C is not set @@ -367,10 +476,21 @@ CONFIG_LEGACY_PTY_COUNT=256 # CONFIG_W1 is not set # +# Hardware Monitoring support +# +CONFIG_HWMON=y +# CONFIG_HWMON_VID is not set +# CONFIG_HWMON_DEBUG_CHIP is not set + +# # Misc devices # # +# Multimedia Capabilities Port drivers +# + +# # Multimedia devices # # CONFIG_VIDEO_DEV is not set @@ -383,27 +503,35 @@ CONFIG_LEGACY_PTY_COUNT=256 # Graphics support # CONFIG_FB=y +CONFIG_FB_CFB_FILLRECT=y +CONFIG_FB_CFB_COPYAREA=y +CONFIG_FB_CFB_IMAGEBLIT=y +# CONFIG_FB_MACMODES is not set # CONFIG_FB_MODE_HELPERS is not set # CONFIG_FB_TILEBLITTING is not set # CONFIG_FB_EPSON1355 is not set +# CONFIG_FB_S1D13XXX is not set CONFIG_FB_HIT=y # CONFIG_FB_VIRTUAL is not set # # Console display driver support # -# CONFIG_VGA_CONSOLE is not set +# CONFIG_MDA_CONSOLE is not set CONFIG_DUMMY_CONSOLE=y CONFIG_FRAMEBUFFER_CONSOLE=y +# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set CONFIG_FONTS=y # CONFIG_FONT_8x8 is not set # CONFIG_FONT_8x16 is not set # CONFIG_FONT_6x11 is not set +# CONFIG_FONT_7x14 is not set CONFIG_FONT_PEARL_8x8=y # CONFIG_FONT_ACORN_8x8 is not set # CONFIG_FONT_MINI_4x6 is not set # CONFIG_FONT_SUN8x16 is not set # CONFIG_FONT_SUN12x22 is not set +# CONFIG_FONT_10x18 is not set # # Logo configuration @@ -414,7 +542,22 @@ CONFIG_FONT_PEARL_8x8=y # # Sound # -# CONFIG_SOUND is not set +CONFIG_SOUND=y + +# +# Advanced Linux Sound Architecture +# +# CONFIG_SND is not set + +# +# Open Sound System +# +CONFIG_SOUND_PRIME=y +# CONFIG_OBSOLETE_OSS_DRIVER is not set +# CONFIG_SOUND_MSNDCLAS is not set +# CONFIG_SOUND_MSNDPIN is not set +CONFIG_SOUND_SH_DAC_AUDIO=y +CONFIG_SOUND_SH_DAC_AUDIO_CHANNEL=1 # # USB support @@ -423,7 +566,7 @@ CONFIG_FONT_PEARL_8x8=y # CONFIG_USB_ARCH_HAS_OHCI is not set # -# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' # # @@ -442,25 +585,29 @@ CONFIG_FONT_PEARL_8x8=y # CONFIG_INFINIBAND is not set # +# SN Devices +# + +# # File systems # CONFIG_EXT2_FS=y # CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT2_FS_XIP is not set # CONFIG_EXT3_FS is not set # CONFIG_JBD is not set # CONFIG_REISERFS_FS is not set # CONFIG_JFS_FS is not set - -# -# XFS support -# +# CONFIG_FS_POSIX_ACL is not set # CONFIG_XFS_FS is not set # CONFIG_MINIX_FS is not set # CONFIG_ROMFS_FS is not set +CONFIG_INOTIFY=y # CONFIG_QUOTA is not set CONFIG_DNOTIFY=y # CONFIG_AUTOFS_FS is not set # CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set # # CD-ROM/DVD Filesystems @@ -471,8 +618,11 @@ CONFIG_DNOTIFY=y # # DOS/FAT/NT Filesystems # +CONFIG_FAT_FS=y # CONFIG_MSDOS_FS is not set -# CONFIG_VFAT_FS is not set +CONFIG_VFAT_FS=y +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" # CONFIG_NTFS_FS is not set # @@ -481,14 +631,11 @@ CONFIG_DNOTIFY=y CONFIG_PROC_FS=y CONFIG_PROC_KCORE=y CONFIG_SYSFS=y -CONFIG_DEVFS_FS=y -CONFIG_DEVFS_MOUNT=y -# CONFIG_DEVFS_DEBUG is not set -# CONFIG_DEVPTS_FS_XATTR is not set # CONFIG_TMPFS is not set # CONFIG_HUGETLBFS is not set # CONFIG_HUGETLB_PAGE is not set CONFIG_RAMFS=y +# CONFIG_RELAYFS_FS is not set # # Miscellaneous filesystems @@ -516,7 +663,46 @@ CONFIG_MSDOS_PARTITION=y # # Native Language Support # -# CONFIG_NLS is not set +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="iso8859-1" +# CONFIG_NLS_CODEPAGE_437 is not set +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +# CONFIG_NLS_ASCII is not set +# CONFIG_NLS_ISO8859_1 is not set +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +# CONFIG_NLS_UTF8 is not set # # Profiling support @@ -526,7 +712,9 @@ CONFIG_MSDOS_PARTITION=y # # Kernel hacking # +# CONFIG_PRINTK_TIME is not set # CONFIG_DEBUG_KERNEL is not set +CONFIG_LOG_BUF_SHIFT=14 # CONFIG_FRAME_POINTER is not set # CONFIG_SH_STANDARD_BIOS is not set # CONFIG_KGDB is not set @@ -550,5 +738,6 @@ CONFIG_MSDOS_PARTITION=y # Library routines # # CONFIG_CRC_CCITT is not set +# CONFIG_CRC16 is not set CONFIG_CRC32=y # CONFIG_LIBCRC32C is not set diff --git a/arch/sh/drivers/dma/dma-api.c b/arch/sh/drivers/dma/dma-api.c index 96e3036ec2b..47c3e837599 100644 --- a/arch/sh/drivers/dma/dma-api.c +++ b/arch/sh/drivers/dma/dma-api.c @@ -3,7 +3,7 @@ * * SuperH-specific DMA management API * - * Copyright (C) 2003, 2004 Paul Mundt + * Copyright (C) 2003, 2004, 2005 Paul Mundt * * 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 @@ -15,6 +15,7 @@ #include <linux/spinlock.h> #include <linux/proc_fs.h> #include <linux/list.h> +#include <linux/platform_device.h> #include <asm/dma.h> DEFINE_SPINLOCK(dma_spin_lock); @@ -55,16 +56,14 @@ static LIST_HEAD(registered_dmac_list); struct dma_info *get_dma_info(unsigned int chan) { - struct list_head *pos, *tmp; + struct dma_info *info; unsigned int total = 0; /* * Look for each DMAC's range to determine who the owner of * the channel is. */ - list_for_each_safe(pos, tmp, ®istered_dmac_list) { - struct dma_info *info = list_entry(pos, struct dma_info, list); - + list_for_each_entry(info, ®istered_dmac_list, list) { total += info->nr_channels; if (chan > total) continue; @@ -75,6 +74,20 @@ struct dma_info *get_dma_info(unsigned int chan) return NULL; } +static unsigned int get_nr_channels(void) +{ + struct dma_info *info; + unsigned int nr = 0; + + if (unlikely(list_empty(®istered_dmac_list))) + return nr; + + list_for_each_entry(info, ®istered_dmac_list, list) + nr += info->nr_channels; + + return nr; +} + struct dma_channel *get_dma_channel(unsigned int chan) { struct dma_info *info = get_dma_info(chan); @@ -173,7 +186,7 @@ int dma_xfer(unsigned int chan, unsigned long from, static int dma_read_proc(char *buf, char **start, off_t off, int len, int *eof, void *data) { - struct list_head *pos, *tmp; + struct dma_info *info; char *p = buf; if (list_empty(®istered_dmac_list)) @@ -182,8 +195,7 @@ static int dma_read_proc(char *buf, char **start, off_t off, /* * Iterate over each registered DMAC */ - list_for_each_safe(pos, tmp, ®istered_dmac_list) { - struct dma_info *info = list_entry(pos, struct dma_info, list); + list_for_each_entry(info, ®istered_dmac_list, list) { int i; /* @@ -205,9 +217,9 @@ static int dma_read_proc(char *buf, char **start, off_t off, #endif -int __init register_dmac(struct dma_info *info) +int register_dmac(struct dma_info *info) { - int i; + unsigned int total_channels, i; INIT_LIST_HEAD(&info->list); @@ -217,6 +229,11 @@ int __init register_dmac(struct dma_info *info) BUG_ON((info->flags & DMAC_CHANNELS_CONFIGURED) && !info->channels); + info->pdev = platform_device_register_simple((char *)info->name, -1, + NULL, 0); + if (IS_ERR(info->pdev)) + return PTR_ERR(info->pdev); + /* * Don't touch pre-configured channels */ @@ -232,10 +249,12 @@ int __init register_dmac(struct dma_info *info) memset(info->channels, 0, size); } + total_channels = get_nr_channels(); for (i = 0; i < info->nr_channels; i++) { struct dma_channel *chan = info->channels + i; chan->chan = i; + chan->vchan = i + total_channels; memcpy(chan->dev_id, "Unused", 7); @@ -245,9 +264,7 @@ int __init register_dmac(struct dma_info *info) init_MUTEX(&chan->sem); init_waitqueue_head(&chan->wait_queue); -#ifdef CONFIG_SYSFS - dma_create_sysfs_files(chan); -#endif + dma_create_sysfs_files(chan, info); } list_add(&info->list, ®istered_dmac_list); @@ -255,12 +272,18 @@ int __init register_dmac(struct dma_info *info) return 0; } -void __exit unregister_dmac(struct dma_info *info) +void unregister_dmac(struct dma_info *info) { + unsigned int i; + + for (i = 0; i < info->nr_channels; i++) + dma_remove_sysfs_files(info->channels + i, info); + if (!(info->flags & DMAC_CHANNELS_CONFIGURED)) kfree(info->channels); list_del(&info->list); + platform_device_unregister(info->pdev); } static int __init dma_api_init(void) diff --git a/arch/sh/drivers/dma/dma-g2.c b/arch/sh/drivers/dma/dma-g2.c index 231e3f6fb28..5afab6f56ec 100644 --- a/arch/sh/drivers/dma/dma-g2.c +++ b/arch/sh/drivers/dma/dma-g2.c @@ -140,7 +140,7 @@ static struct dma_ops g2_dma_ops = { }; static struct dma_info g2_dma_info = { - .name = "G2 DMA", + .name = "g2_dmac", .nr_channels = 4, .ops = &g2_dma_ops, .flags = DMAC_CHANNELS_TEI_CAPABLE, @@ -160,6 +160,7 @@ static int __init g2_dma_init(void) static void __exit g2_dma_exit(void) { free_irq(HW_EVENT_G2_DMA, 0); + unregister_dmac(&g2_dma_info); } subsys_initcall(g2_dma_init); diff --git a/arch/sh/drivers/dma/dma-isa.c b/arch/sh/drivers/dma/dma-isa.c index 1c9bc45b8bc..05a74ffdb68 100644 --- a/arch/sh/drivers/dma/dma-isa.c +++ b/arch/sh/drivers/dma/dma-isa.c @@ -25,14 +25,14 @@ * such, this code is meant for only the simplest of tasks (and shouldn't be * used in any new drivers at all). * - * It should also be noted that various functions here are labelled as - * being deprecated. This is due to the fact that the ops->xfer() method is - * the preferred way of doing things (as well as just grabbing the spinlock - * directly). As such, any users of this interface will be warned rather - * loudly. + * NOTE: ops->xfer() is the preferred way of doing things. However, there + * are some users of the ISA DMA API that exist in common code that we + * don't necessarily want to go out of our way to break, so we still + * allow for some compatability at that level. Any new code is strongly + * advised to run far away from the ISA DMA API and use the SH DMA API + * directly. */ - -unsigned long __deprecated claim_dma_lock(void) +unsigned long claim_dma_lock(void) { unsigned long flags; @@ -42,19 +42,19 @@ unsigned long __deprecated claim_dma_lock(void) } EXPORT_SYMBOL(claim_dma_lock); -void __deprecated release_dma_lock(unsigned long flags) +void release_dma_lock(unsigned long flags) { spin_unlock_irqrestore(&dma_spin_lock, flags); } EXPORT_SYMBOL(release_dma_lock); -void __deprecated disable_dma(unsigned int chan) +void disable_dma(unsigned int chan) { /* Nothing */ } EXPORT_SYMBOL(disable_dma); -void __deprecated enable_dma(unsigned int chan) +void enable_dma(unsigned int chan) { struct dma_info *info = get_dma_info(chan); struct dma_channel *channel = &info->channels[chan]; diff --git a/arch/sh/drivers/dma/dma-pvr2.c b/arch/sh/drivers/dma/dma-pvr2.c index 2e1d58f2d1b..df604975ccc 100644 --- a/arch/sh/drivers/dma/dma-pvr2.c +++ b/arch/sh/drivers/dma/dma-pvr2.c @@ -80,7 +80,7 @@ static struct dma_ops pvr2_dma_ops = { }; static struct dma_info pvr2_dma_info = { - .name = "PowerVR 2 DMA", + .name = "pvr2_dmac", .nr_channels = 1, .ops = &pvr2_dma_ops, .flags = DMAC_CHANNELS_TEI_CAPABLE, @@ -98,6 +98,7 @@ static void __exit pvr2_dma_exit(void) { free_dma(PVR2_CASCADE_CHAN); free_irq(HW_EVENT_PVR2_DMA, 0); + unregister_dmac(&pvr2_dma_info); } subsys_initcall(pvr2_dma_init); diff --git a/arch/sh/drivers/dma/dma-sh.c b/arch/sh/drivers/dma/dma-sh.c index 31dacd4444b..cca26c4c9d1 100644 --- a/arch/sh/drivers/dma/dma-sh.c +++ b/arch/sh/drivers/dma/dma-sh.c @@ -5,6 +5,7 @@ * * Copyright (C) 2000 Takashi YOSHII * Copyright (C) 2003, 2004 Paul Mundt + * Copyright (C) 2005 Andriy Skulysh * * 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 @@ -16,51 +17,28 @@ #include <linux/irq.h> #include <linux/interrupt.h> #include <linux/module.h> +#include <asm/dreamcast/dma.h> #include <asm/signal.h> #include <asm/irq.h> #include <asm/dma.h> #include <asm/io.h> #include "dma-sh.h" -/* - * The SuperH DMAC supports a number of transmit sizes, we list them here, - * with their respective values as they appear in the CHCR registers. - * - * Defaults to a 64-bit transfer size. - */ -enum { - XMIT_SZ_64BIT, - XMIT_SZ_8BIT, - XMIT_SZ_16BIT, - XMIT_SZ_32BIT, - XMIT_SZ_256BIT, -}; - -/* - * The DMA count is defined as the number of bytes to transfer. - */ -static unsigned int ts_shift[] = { - [XMIT_SZ_64BIT] = 3, - [XMIT_SZ_8BIT] = 0, - [XMIT_SZ_16BIT] = 1, - [XMIT_SZ_32BIT] = 2, - [XMIT_SZ_256BIT] = 5, -}; - static inline unsigned int get_dmte_irq(unsigned int chan) { - unsigned int irq; + unsigned int irq = 0; /* * Normally we could just do DMTE0_IRQ + chan outright, though in the * case of the 7751R, the DMTE IRQs for channels > 4 start right above * the SCIF */ - if (chan < 4) { irq = DMTE0_IRQ + chan; } else { +#ifdef DMTE4_IRQ irq = DMTE4_IRQ + chan - 4; +#endif } return irq; @@ -78,9 +56,7 @@ static inline unsigned int calc_xmit_shift(struct dma_channel *chan) { u32 chcr = ctrl_inl(CHCR[chan->chan]); - chcr >>= 4; - - return ts_shift[chcr & 0x0007]; + return ts_shift[(chcr & CHCR_TS_MASK)>>CHCR_TS_SHIFT]; } /* @@ -109,8 +85,13 @@ static irqreturn_t dma_tei(int irq, void *dev_id, struct pt_regs *regs) static int sh_dmac_request_dma(struct dma_channel *chan) { + char name[32]; + + snprintf(name, sizeof(name), "DMAC Transfer End (Channel %d)", + chan->chan); + return request_irq(get_dmte_irq(chan->chan), dma_tei, - SA_INTERRUPT, "DMAC Transfer End", chan); + SA_INTERRUPT, name, chan); } static void sh_dmac_free_dma(struct dma_channel *chan) @@ -118,10 +99,18 @@ static void sh_dmac_free_dma(struct dma_channel *chan) free_irq(get_dmte_irq(chan->chan), chan); } -static void sh_dmac_configure_channel(struct dma_channel *chan, unsigned long chcr) +static void +sh_dmac_configure_channel(struct dma_channel *chan, unsigned long chcr) { if (!chcr) - chcr = RS_DUAL; + chcr = RS_DUAL | CHCR_IE; + + if (chcr & CHCR_IE) { + chcr &= ~CHCR_IE; + chan->flags |= DMA_TEI_CAPABLE; + } else { + chan->flags &= ~DMA_TEI_CAPABLE; + } ctrl_outl(chcr, CHCR[chan->chan]); @@ -130,22 +119,32 @@ static void sh_dmac_configure_channel(struct dma_channel *chan, unsigned long ch static void sh_dmac_enable_dma(struct dma_channel *chan) { - int irq = get_dmte_irq(chan->chan); + int irq; u32 chcr; chcr = ctrl_inl(CHCR[chan->chan]); - chcr |= CHCR_DE | CHCR_IE; + chcr |= CHCR_DE; + + if (chan->flags & DMA_TEI_CAPABLE) + chcr |= CHCR_IE; + ctrl_outl(chcr, CHCR[chan->chan]); - enable_irq(irq); + if (chan->flags & DMA_TEI_CAPABLE) { + irq = get_dmte_irq(chan->chan); + enable_irq(irq); + } } static void sh_dmac_disable_dma(struct dma_channel *chan) { - int irq = get_dmte_irq(chan->chan); + int irq; u32 chcr; - disable_irq(irq); + if (chan->flags & DMA_TEI_CAPABLE) { + irq = get_dmte_irq(chan->chan); + disable_irq(irq); + } chcr = ctrl_inl(CHCR[chan->chan]); chcr &= ~(CHCR_DE | CHCR_TE | CHCR_IE); @@ -158,7 +157,7 @@ static int sh_dmac_xfer_dma(struct dma_channel *chan) * If we haven't pre-configured the channel with special flags, use * the defaults. */ - if (!(chan->flags & DMA_CONFIGURED)) + if (unlikely(!(chan->flags & DMA_CONFIGURED))) sh_dmac_configure_channel(chan, 0); sh_dmac_disable_dma(chan); @@ -178,9 +177,11 @@ static int sh_dmac_xfer_dma(struct dma_channel *chan) * cascading to the PVR2 DMAC. In this case, we still need to write * SAR and DAR, regardless of value, in order for cascading to work. */ - if (chan->sar || (mach_is_dreamcast() && chan->chan == 2)) + if (chan->sar || (mach_is_dreamcast() && + chan->chan == PVR2_CASCADE_CHAN)) ctrl_outl(chan->sar, SAR[chan->chan]); - if (chan->dar || (mach_is_dreamcast() && chan->chan == 2)) + if (chan->dar || (mach_is_dreamcast() && + chan->chan == PVR2_CASCADE_CHAN)) ctrl_outl(chan->dar, DAR[chan->chan]); ctrl_outl(chan->count >> calc_xmit_shift(chan), DMATCR[chan->chan]); @@ -198,17 +199,38 @@ static int sh_dmac_get_dma_residue(struct dma_channel *chan) return ctrl_inl(DMATCR[chan->chan]) << calc_xmit_shift(chan); } -#if defined(CONFIG_CPU_SH4) -static irqreturn_t dma_err(int irq, void *dev_id, struct pt_regs *regs) +#ifdef CONFIG_CPU_SUBTYPE_SH7780 +#define dmaor_read_reg() ctrl_inw(DMAOR) +#define dmaor_write_reg(data) ctrl_outw(data, DMAOR) +#else +#define dmaor_read_reg() ctrl_inl(DMAOR) +#define dmaor_write_reg(data) ctrl_outl(data, DMAOR) +#endif + +static inline int dmaor_reset(void) { - unsigned long dmaor = ctrl_inl(DMAOR); + unsigned long dmaor = dmaor_read_reg(); + + /* Try to clear the error flags first, incase they are set */ + dmaor &= ~(DMAOR_NMIF | DMAOR_AE); + dmaor_write_reg(dmaor); - printk("DMAE: DMAOR=%lx\n", dmaor); + dmaor |= DMAOR_INIT; + dmaor_write_reg(dmaor); - ctrl_outl(ctrl_inl(DMAOR)&~DMAOR_NMIF, DMAOR); - ctrl_outl(ctrl_inl(DMAOR)&~DMAOR_AE, DMAOR); - ctrl_outl(ctrl_inl(DMAOR)|DMAOR_DME, DMAOR); + /* See if we got an error again */ + if ((dmaor_read_reg() & (DMAOR_AE | DMAOR_NMIF))) { + printk(KERN_ERR "dma-sh: Can't initialize DMAOR.\n"); + return -EINVAL; + } + return 0; +} + +#if defined(CONFIG_CPU_SH4) +static irqreturn_t dma_err(int irq, void *dev_id, struct pt_regs *regs) +{ + dmaor_reset(); disable_irq(irq); return IRQ_HANDLED; @@ -224,8 +246,8 @@ static struct dma_ops sh_dmac_ops = { }; static struct dma_info sh_dmac_info = { - .name = "SuperH DMAC", - .nr_channels = 4, + .name = "sh_dmac", + .nr_channels = CONFIG_NR_ONCHIP_DMA_CHANNELS, .ops = &sh_dmac_ops, .flags = DMAC_CHANNELS_TEI_CAPABLE, }; @@ -248,7 +270,13 @@ static int __init sh_dmac_init(void) make_ipr_irq(irq, DMA_IPR_ADDR, DMA_IPR_POS, DMA_PRIORITY); } - ctrl_outl(0x8000 | DMAOR_DME, DMAOR); + /* + * Initialize DMAOR, and clean up any error flags that may have + * been set. + */ + i = dmaor_reset(); + if (i < 0) + return i; return register_dmac(info); } @@ -258,10 +286,12 @@ static void __exit sh_dmac_exit(void) #ifdef CONFIG_CPU_SH4 free_irq(DMAE_IRQ, 0); #endif + unregister_dmac(&sh_dmac_info); } subsys_initcall(sh_dmac_init); module_exit(sh_dmac_exit); +MODULE_AUTHOR("Takashi YOSHII, Paul Mundt, Andriy Skulysh"); +MODULE_DESCRIPTION("SuperH On-Chip DMAC Support"); MODULE_LICENSE("GPL"); - diff --git a/arch/sh/drivers/dma/dma-sh.h b/arch/sh/drivers/dma/dma-sh.h index dd9d547539a..0f591fbc922 100644 --- a/arch/sh/drivers/dma/dma-sh.h +++ b/arch/sh/drivers/dma/dma-sh.h @@ -11,6 +11,8 @@ #ifndef __DMA_SH_H #define __DMA_SH_H +#include <asm/cpu/dma.h> + /* Definitions for the SuperH DMAC */ #define REQ_L 0x00000000 #define REQ_E 0x00080000 @@ -26,27 +28,47 @@ #define SM_DEC 0x00002000 #define RS_IN 0x00000200 #define RS_OUT 0x00000300 -#define TM_BURST 0x0000080 -#define TS_8 0x00000010 -#define TS_16 0x00000020 -#define TS_32 0x00000030 -#define TS_64 0x00000000 #define TS_BLK 0x00000040 #define CHCR_DE 0x00000001 #define CHCR_TE 0x00000002 #define CHCR_IE 0x00000004 -/* Define the default configuration for dual address memory-memory transfer. - * The 0x400 value represents auto-request, external->external. - */ -#define RS_DUAL (DM_INC | SM_INC | 0x400 | TS_32) - -#define DMAOR_COD 0x00000008 +/* DMAOR definitions */ #define DMAOR_AE 0x00000004 #define DMAOR_NMIF 0x00000002 #define DMAOR_DME 0x00000001 +/* + * Define the default configuration for dual address memory-memory transfer. + * The 0x400 value represents auto-request, external->external. + */ +#define RS_DUAL (DM_INC | SM_INC | 0x400 | TS_32) + #define MAX_DMAC_CHANNELS (CONFIG_NR_ONCHIP_DMA_CHANNELS) +/* + * Subtypes that have fewer channels than this simply need to change + * CONFIG_NR_ONCHIP_DMA_CHANNELS. Likewise, subtypes with a larger number + * of channels should expand on this. + * + * For most subtypes we can easily figure these values out with some + * basic calculation, unfortunately on other subtypes these are more + * scattered, so we just leave it unrolled for simplicity. + */ +#define SAR ((unsigned long[]){SH_DMAC_BASE + 0x00, SH_DMAC_BASE + 0x10, \ + SH_DMAC_BASE + 0x20, SH_DMAC_BASE + 0x30, \ + SH_DMAC_BASE + 0x50, SH_DMAC_BASE + 0x60}) +#define DAR ((unsigned long[]){SH_DMAC_BASE + 0x04, SH_DMAC_BASE + 0x14, \ + SH_DMAC_BASE + 0x24, SH_DMAC_BASE + 0x34, \ + SH_DMAC_BASE + 0x54, SH_DMAC_BASE + 0x64}) +#define DMATCR ((unsigned long[]){SH_DMAC_BASE + 0x08, SH_DMAC_BASE + 0x18, \ + SH_DMAC_BASE + 0x28, SH_DMAC_BASE + 0x38, \ + SH_DMAC_BASE + 0x58, SH_DMAC_BASE + 0x68}) +#define CHCR ((unsigned long[]){SH_DMAC_BASE + 0x0c, SH_DMAC_BASE + 0x1c, \ + SH_DMAC_BASE + 0x2c, SH_DMAC_BASE + 0x3c, \ + SH_DMAC_BASE + 0x5c, SH_DMAC_BASE + 0x6c}) + +#define DMAOR (SH_DMAC_BASE + 0x40) + #endif /* __DMA_SH_H */ diff --git a/arch/sh/drivers/dma/dma-sysfs.c b/arch/sh/drivers/dma/dma-sysfs.c index 6e3b58bd879..70a5d82eb2f 100644 --- a/arch/sh/drivers/dma/dma-sysfs.c +++ b/arch/sh/drivers/dma/dma-sysfs.c @@ -3,7 +3,7 @@ * * sysfs interface for SH DMA API * - * Copyright (C) 2004 Paul Mundt + * Copyright (C) 2004, 2005 Paul Mundt * * 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 @@ -12,7 +12,9 @@ #include <linux/kernel.h> #include <linux/init.h> #include <linux/sysdev.h> +#include <linux/platform_device.h> #include <linux/module.h> +#include <linux/err.h> #include <linux/string.h> #include <asm/dma.h> @@ -77,7 +79,7 @@ static ssize_t dma_store_config(struct sys_device *dev, unsigned long config; config = simple_strtoul(buf, NULL, 0); - dma_configure_channel(channel->chan, config); + dma_configure_channel(channel->vchan, config); return count; } @@ -111,12 +113,13 @@ static SYSDEV_ATTR(field, S_IRUGO, dma_show_##field, NULL); dma_ro_attr(count, "0x%08x\n"); dma_ro_attr(flags, "0x%08lx\n"); -int __init dma_create_sysfs_files(struct dma_channel *chan) +int dma_create_sysfs_files(struct dma_channel *chan, struct dma_info *info) { struct sys_device *dev = &chan->dev; + char name[16]; int ret; - dev->id = chan->chan; + dev->id = chan->vchan; dev->cls = &dma_sysclass; ret = sysdev_register(dev); @@ -129,6 +132,24 @@ int __init dma_create_sysfs_files(struct dma_channel *chan) sysdev_create_file(dev, &attr_flags); sysdev_create_file(dev, &attr_config); - return 0; + snprintf(name, sizeof(name), "dma%d", chan->chan); + return sysfs_create_link(&info->pdev->dev.kobj, &dev->kobj, name); +} + +void dma_remove_sysfs_files(struct dma_channel *chan, struct dma_info *info) +{ + struct sys_device *dev = &chan->dev; + char name[16]; + + sysdev_remove_file(dev, &attr_dev_id); + sysdev_remove_file(dev, &attr_count); + sysdev_remove_file(dev, &attr_mode); + sysdev_remove_file(dev, &attr_flags); + sysdev_remove_file(dev, &attr_config); + + snprintf(name, sizeof(name), "dma%d", chan->chan); + sysfs_remove_link(&info->pdev->dev.kobj, name); + + sysdev_unregister(dev); } diff --git a/arch/sh/kernel/Makefile b/arch/sh/kernel/Makefile index 8b819698df1..7a86eeb2265 100644 --- a/arch/sh/kernel/Makefile +++ b/arch/sh/kernel/Makefile @@ -17,6 +17,4 @@ obj-$(CONFIG_SH_KGDB) += kgdb_stub.o kgdb_jmp.o obj-$(CONFIG_SH_CPU_FREQ) += cpufreq.o obj-$(CONFIG_MODULES) += module.o obj-$(CONFIG_EARLY_PRINTK) += early_printk.o - -USE_STANDARD_AS_RULE := true - +obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o diff --git a/arch/sh/kernel/cpu/Makefile b/arch/sh/kernel/cpu/Makefile index cd43714df61..5bfc33bec5d 100644 --- a/arch/sh/kernel/cpu/Makefile +++ b/arch/sh/kernel/cpu/Makefile @@ -2,15 +2,12 @@ # Makefile for the Linux/SuperH CPU-specifc backends. # -obj-y := irq_ipr.o irq_imask.o init.o bus.o +obj-y += irq/ init.o bus.o clock.o obj-$(CONFIG_CPU_SH2) += sh2/ obj-$(CONFIG_CPU_SH3) += sh3/ obj-$(CONFIG_CPU_SH4) += sh4/ -obj-$(CONFIG_SH_RTC) += rtc.o +obj-$(CONFIG_SH_RTC) += rtc.o obj-$(CONFIG_UBC_WAKEUP) += ubc.o -obj-$(CONFIG_SH_ADC) += adc.o - -USE_STANDARD_AS_RULE := true - +obj-$(CONFIG_SH_ADC) += adc.o diff --git a/arch/sh/kernel/cpu/bus.c b/arch/sh/kernel/cpu/bus.c index 3278d234bb1..fc6c4bd40c6 100644 --- a/arch/sh/kernel/cpu/bus.c +++ b/arch/sh/kernel/cpu/bus.c @@ -109,6 +109,8 @@ int sh_device_register(struct sh_dev *dev) /* This is needed for USB OHCI to work */ if (dev->dma_mask) dev->dev.dma_mask = dev->dma_mask; + if (dev->coherent_dma_mask) + dev->dev.coherent_dma_mask = dev->coherent_dma_mask; snprintf(dev->dev.bus_id, BUS_ID_SIZE, "%s%u", dev->name, dev->dev_id); diff --git a/arch/sh/kernel/cpu/clock.c b/arch/sh/kernel/cpu/clock.c new file mode 100644 index 00000000000..989e7fdd524 --- /dev/null +++ b/arch/sh/kernel/cpu/clock.c @@ -0,0 +1,287 @@ +/* + * arch/sh/kernel/cpu/clock.c - SuperH clock framework + * + * Copyright (C) 2005 Paul Mundt + * + * This clock framework is derived from the OMAP version by: + * + * Copyright (C) 2004 Nokia Corporation + * Written by Tuukka Tikkanen <tuukka.tikkanen@elektrobit.com> + * + * 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. + */ +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/module.h> +#include <linux/list.h> +#include <linux/kref.h> +#include <linux/seq_file.h> +#include <linux/err.h> +#include <asm/clock.h> +#include <asm/timer.h> + +static LIST_HEAD(clock_list); +static DEFINE_SPINLOCK(clock_lock); +static DECLARE_MUTEX(clock_list_sem); + +/* + * Each subtype is expected to define the init routines for these clocks, + * as each subtype (or processor family) will have these clocks at the + * very least. These are all provided through the CPG, which even some of + * the more quirky parts (such as ST40, SH4-202, etc.) still have. + * + * The processor-specific code is expected to register any additional + * clock sources that are of interest. + */ +static struct clk master_clk = { + .name = "master_clk", + .flags = CLK_ALWAYS_ENABLED | CLK_RATE_PROPAGATES, +#ifdef CONFIG_SH_PCLK_FREQ_BOOL + .rate = CONFIG_SH_PCLK_FREQ, +#endif +}; + +static struct clk module_clk = { + .name = "module_clk", + .parent = &master_clk, + .flags = CLK_ALWAYS_ENABLED | CLK_RATE_PROPAGATES, +}; + +static struct clk bus_clk = { + .name = "bus_clk", + .parent = &master_clk, + .flags = CLK_ALWAYS_ENABLED | CLK_RATE_PROPAGATES, +}; + +static struct clk cpu_clk = { + .name = "cpu_clk", + .parent = &master_clk, + .flags = CLK_ALWAYS_ENABLED, +}; + +/* + * The ordering of these clocks matters, do not change it. + */ +static struct clk *onchip_clocks[] = { + &master_clk, + &module_clk, + &bus_clk, + &cpu_clk, +}; + +static void propagate_rate(struct clk *clk) +{ + struct clk *clkp; + + list_for_each_entry(clkp, &clock_list, node) { + if (likely(clkp->parent != clk)) + continue; + if (likely(clkp->ops && clkp->ops->recalc)) + clkp->ops->recalc(clkp); + } +} + +int __clk_enable(struct clk *clk) +{ + /* + * See if this is the first time we're enabling the clock, some + * clocks that are always enabled still require "special" + * initialization. This is especially true if the clock mode + * changes and the clock needs to hunt for the proper set of + * divisors to use before it can effectively recalc. + */ + if (unlikely(atomic_read(&clk->kref.refcount) == 1)) + if (clk->ops && clk->ops->init) + clk->ops->init(clk); + + if (clk->flags & CLK_ALWAYS_ENABLED) + return 0; + + if (likely(clk->ops && clk->ops->enable)) + clk->ops->enable(clk); + + kref_get(&clk->kref); + return 0; +} + +int clk_enable(struct clk *clk) +{ + unsigned long flags; + int ret; + + spin_lock_irqsave(&clock_lock, flags); + ret = __clk_enable(clk); + spin_unlock_irqrestore(&clock_lock, flags); + + return ret; +} + +static void clk_kref_release(struct kref *kref) +{ + /* Nothing to do */ +} + +void __clk_disable(struct clk *clk) +{ + if (clk->flags & CLK_ALWAYS_ENABLED) + return; + + kref_put(&clk->kref, clk_kref_release); +} + +void clk_disable(struct clk *clk) +{ + unsigned long flags; + + spin_lock_irqsave(&clock_lock, flags); + __clk_disable(clk); + spin_unlock_irqrestore(&clock_lock, flags); +} + +int clk_register(struct clk *clk) +{ + down(&clock_list_sem); + + list_add(&clk->node, &clock_list); + kref_init(&clk->kref); + + up(&clock_list_sem); + + return 0; +} + +void clk_unregister(struct clk *clk) +{ + down(&clock_list_sem); + list_del(&clk->node); + up(&clock_list_sem); +} + +inline unsigned long clk_get_rate(struct clk *clk) +{ + return clk->rate; +} + +int clk_set_rate(struct clk *clk, unsigned long rate) +{ + int ret = -EOPNOTSUPP; + + if (likely(clk->ops && clk->ops->set_rate)) { + unsigned long flags; + + spin_lock_irqsave(&clock_lock, flags); + ret = clk->ops->set_rate(clk, rate); + spin_unlock_irqrestore(&clock_lock, flags); + } + + if (unlikely(clk->flags & CLK_RATE_PROPAGATES)) + propagate_rate(clk); + + return ret; +} + +void clk_recalc_rate(struct clk *clk) +{ + if (likely(clk->ops && clk->ops->recalc)) { + unsigned long flags; + + spin_lock_irqsave(&clock_lock, flags); + clk->ops->recalc(clk); + spin_unlock_irqrestore(&clock_lock, flags); + } + + if (unlikely(clk->flags & CLK_RATE_PROPAGATES)) + propagate_rate(clk); +} + +struct clk *clk_get(const char *id) +{ + struct clk *p, *clk = ERR_PTR(-ENOENT); + + down(&clock_list_sem); + list_for_each_entry(p, &clock_list, node) { + if (strcmp(id, p->name) == 0 && try_module_get(p->owner)) { + clk = p; + break; + } + } + up(&clock_list_sem); + + return clk; +} + +void clk_put(struct clk *clk) +{ + if (clk && !IS_ERR(clk)) + module_put(clk->owner); +} + +void __init __attribute__ ((weak)) +arch_init_clk_ops(struct clk_ops **ops, int type) +{ +} + +int __init clk_init(void) +{ + int i, ret = 0; + + if (unlikely(!master_clk.rate)) + /* + * NOTE: This will break if the default divisor has been + * changed. + * + * No one should be changing the default on us however, + * expect that a sane value for CONFIG_SH_PCLK_FREQ will + * be defined in the event of a different divisor. + */ + master_clk.rate = get_timer_frequency() * 4; + + for (i = 0; i < ARRAY_SIZE(onchip_clocks); i++) { + struct clk *clk = onchip_clocks[i]; + + arch_init_clk_ops(&clk->ops, i); + ret |= clk_register(clk); + clk_enable(clk); + } + + /* Kick the child clocks.. */ + propagate_rate(&master_clk); + propagate_rate(&bus_clk); + + return ret; +} + +int show_clocks(struct seq_file *m) +{ + struct clk *clk; + + list_for_each_entry_reverse(clk, &clock_list, node) { + unsigned long rate = clk_get_rate(clk); + + /* + * Don't bother listing dummy clocks with no ancestry + * that only support enable and disable ops. + */ + if (unlikely(!rate && !clk->parent)) + continue; + + seq_printf(m, "%-12s\t: %ld.%02ldMHz\n", clk->name, + rate / 1000000, (rate % 1000000) / 10000); + } + + return 0; +} + +EXPORT_SYMBOL_GPL(clk_register); +EXPORT_SYMBOL_GPL(clk_unregister); +EXPORT_SYMBOL_GPL(clk_get); +EXPORT_SYMBOL_GPL(clk_put); +EXPORT_SYMBOL_GPL(clk_enable); +EXPORT_SYMBOL_GPL(clk_disable); +EXPORT_SYMBOL_GPL(__clk_enable); +EXPORT_SYMBOL_GPL(__clk_disable); +EXPORT_SYMBOL_GPL(clk_get_rate); +EXPORT_SYMBOL_GPL(clk_set_rate); +EXPORT_SYMBOL_GPL(clk_recalc_rate); diff --git a/arch/sh/kernel/cpu/irq/Makefile b/arch/sh/kernel/cpu/irq/Makefile new file mode 100644 index 00000000000..e3cccea15e1 --- /dev/null +++ b/arch/sh/kernel/cpu/irq/Makefile @@ -0,0 +1,7 @@ +# +# Makefile for the Linux/SuperH CPU-specifc IRQ handlers. +# +obj-y += ipr.o imask.o + +obj-$(CONFIG_CPU_HAS_PINT_IRQ) += pint.o +obj-$(CONFIG_CPU_HAS_INTC2_IRQ) += intc2.o diff --git a/arch/sh/kernel/cpu/irq_imask.c b/arch/sh/kernel/cpu/irq/imask.c index a963d00a971..baed9a550d3 100644 --- a/arch/sh/kernel/cpu/irq_imask.c +++ b/arch/sh/kernel/cpu/irq/imask.c @@ -1,16 +1,12 @@ -/* $Id: irq_imask.c,v 1.1.2.1 2002/11/17 10:53:43 mrbrown Exp $ - * - * linux/arch/sh/kernel/irq_imask.c +/* + * arch/sh/kernel/cpu/irq/imask.c * * Copyright (C) 1999, 2000 Niibe Yutaka * * Simple interrupt handling using IMASK of SR register. * */ - /* NOTE: Will not work on level 15 */ - - #include <linux/ptrace.h> #include <linux/errno.h> #include <linux/kernel_stat.h> @@ -19,13 +15,11 @@ #include <linux/interrupt.h> #include <linux/init.h> #include <linux/bitops.h> - -#include <asm/system.h> -#include <asm/irq.h> - #include <linux/spinlock.h> #include <linux/cache.h> #include <linux/irq.h> +#include <asm/system.h> +#include <asm/irq.h> /* Bitmap of IRQ masked */ static unsigned long imask_mask = 0x7fff; @@ -40,7 +34,7 @@ static void end_imask_irq(unsigned int irq); #define IMASK_PRIORITY 15 static unsigned int startup_imask_irq(unsigned int irq) -{ +{ /* Nothing to do */ return 0; /* never anything pending */ } diff --git a/arch/sh/kernel/cpu/irq/intc2.c b/arch/sh/kernel/cpu/irq/intc2.c new file mode 100644 index 00000000000..06e8afab32e --- /dev/null +++ b/arch/sh/kernel/cpu/irq/intc2.c @@ -0,0 +1,284 @@ +/* + * Interrupt handling for INTC2-based IRQ. + * + * Copyright (C) 2001 David J. Mckay (david.mckay@st.com) + * Copyright (C) 2005, 2006 Paul Mundt (lethal@linux-sh.org) + * + * May be copied or modified under the terms of the GNU General Public + * License. See linux/COPYING for more information. + * + * These are the "new Hitachi style" interrupts, as present on the + * Hitachi 7751, the STM ST40 STB1, SH7760, and SH7780. + */ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/irq.h> +#include <asm/system.h> +#include <asm/io.h> +#include <asm/machvec.h> + +struct intc2_data { + unsigned char msk_offset; + unsigned char msk_shift; + + int (*clear_irq) (int); +}; + +static struct intc2_data intc2_data[NR_INTC2_IRQS]; + +static void enable_intc2_irq(unsigned int irq); +static void disable_intc2_irq(unsigned int irq); + +/* shutdown is same as "disable" */ +#define shutdown_intc2_irq disable_intc2_irq + +static void mask_and_ack_intc2(unsigned int); +static void end_intc2_irq(unsigned int irq); + +static unsigned int startup_intc2_irq(unsigned int irq) +{ + enable_intc2_irq(irq); + return 0; /* never anything pending */ +} + +static struct hw_interrupt_type intc2_irq_type = { + .typename = "INTC2-IRQ", + .startup = startup_intc2_irq, + .shutdown = shutdown_intc2_irq, + .enable = enable_intc2_irq, + .disable = disable_intc2_irq, + .ack = mask_and_ack_intc2, + .end = end_intc2_irq +}; + +static void disable_intc2_irq(unsigned int irq) +{ + int irq_offset = irq - INTC2_FIRST_IRQ; + int msk_shift, msk_offset; + + /* Sanity check */ + if (unlikely(irq_offset < 0 || irq_offset >= NR_INTC2_IRQS)) + return; + + msk_shift = intc2_data[irq_offset].msk_shift; + msk_offset = intc2_data[irq_offset].msk_offset; + + ctrl_outl(1 << msk_shift, + INTC2_BASE + INTC2_INTMSK_OFFSET + msk_offset); +} + +static void enable_intc2_irq(unsigned int irq) +{ + int irq_offset = irq - INTC2_FIRST_IRQ; + int msk_shift, msk_offset; + + /* Sanity check */ + if (unlikely(irq_offset < 0 || irq_offset >= NR_INTC2_IRQS)) + return; + + msk_shift = intc2_data[irq_offset].msk_shift; + msk_offset = intc2_data[irq_offset].msk_offset; + + ctrl_outl(1 << msk_shift, + INTC2_BASE + INTC2_INTMSKCLR_OFFSET + msk_offset); +} + +static void mask_and_ack_intc2(unsigned int irq) +{ + disable_intc2_irq(irq); +} + +static void end_intc2_irq(unsigned int irq) +{ + if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) + enable_intc2_irq(irq); + + if (unlikely(intc2_data[irq - INTC2_FIRST_IRQ].clear_irq)) + intc2_data[irq - INTC2_FIRST_IRQ].clear_irq(irq); +} + +/* + * Setup an INTC2 style interrupt. + * NOTE: Unlike IPR interrupts, parameters are not shifted by this code, + * allowing the use of the numbers straight out of the datasheet. + * For example: + * PIO1 which is INTPRI00[19,16] and INTMSK00[13] + * would be: ^ ^ ^ ^ + * | | | | + * make_intc2_irq(84, 0, 16, 0, 13); + */ +void make_intc2_irq(unsigned int irq, + unsigned int ipr_offset, unsigned int ipr_shift, + unsigned int msk_offset, unsigned int msk_shift, + unsigned int priority) +{ + int irq_offset = irq - INTC2_FIRST_IRQ; + unsigned int flags; + unsigned long ipr; + + if (unlikely(irq_offset < 0 || irq_offset >= NR_INTC2_IRQS)) + return; + + disable_irq_nosync(irq); + + /* Fill the data we need */ + intc2_data[irq_offset].msk_offset = msk_offset; + intc2_data[irq_offset].msk_shift = msk_shift; + intc2_data[irq_offset].clear_irq = NULL; + + /* Set the priority level */ + local_irq_save(flags); + + ipr = ctrl_inl(INTC2_BASE + INTC2_INTPRI_OFFSET + ipr_offset); + ipr &= ~(0xf << ipr_shift); + ipr |= priority << ipr_shift; + ctrl_outl(ipr, INTC2_BASE + INTC2_INTPRI_OFFSET + ipr_offset); + + local_irq_restore(flags); + + irq_desc[irq].handler = &intc2_irq_type; + + disable_intc2_irq(irq); +} + +static struct intc2_init { + unsigned short irq; + unsigned char ipr_offset, ipr_shift; + unsigned char msk_offset, msk_shift; + unsigned char priority; +} intc2_init_data[] __initdata = { +#if defined(CONFIG_CPU_SUBTYPE_ST40) + {64, 0, 0, 0, 0, 13}, /* PCI serr */ + {65, 0, 4, 0, 1, 13}, /* PCI err */ + {66, 0, 4, 0, 2, 13}, /* PCI ad */ + {67, 0, 4, 0, 3, 13}, /* PCI pwd down */ + {72, 0, 8, 0, 5, 13}, /* DMAC INT0 */ + {73, 0, 8, 0, 6, 13}, /* DMAC INT1 */ + {74, 0, 8, 0, 7, 13}, /* DMAC INT2 */ + {75, 0, 8, 0, 8, 13}, /* DMAC INT3 */ + {76, 0, 8, 0, 9, 13}, /* DMAC INT4 */ + {78, 0, 8, 0, 11, 13}, /* DMAC ERR */ + {80, 0, 12, 0, 12, 13}, /* PIO0 */ + {84, 0, 16, 0, 13, 13}, /* PIO1 */ + {88, 0, 20, 0, 14, 13}, /* PIO2 */ + {112, 4, 0, 4, 0, 13}, /* Mailbox */ + #ifdef CONFIG_CPU_SUBTYPE_ST40GX1 + {116, 4, 4, 4, 4, 13}, /* SSC0 */ + {120, 4, 8, 4, 8, 13}, /* IR Blaster */ + {124, 4, 12, 4, 12, 13}, /* USB host */ + {128, 4, 16, 4, 16, 13}, /* Video processor BLITTER */ + {132, 4, 20, 4, 20, 13}, /* UART0 */ + {134, 4, 20, 4, 22, 13}, /* UART2 */ + {136, 4, 24, 4, 24, 13}, /* IO_PIO0 */ + {140, 4, 28, 4, 28, 13}, /* EMPI */ + {144, 8, 0, 8, 0, 13}, /* MAFE */ + {148, 8, 4, 8, 4, 13}, /* PWM */ + {152, 8, 8, 8, 8, 13}, /* SSC1 */ + {156, 8, 12, 8, 12, 13}, /* IO_PIO1 */ + {160, 8, 16, 8, 16, 13}, /* USB target */ + {164, 8, 20, 8, 20, 13}, /* UART1 */ + {168, 8, 24, 8, 24, 13}, /* Teletext */ + {172, 8, 28, 8, 28, 13}, /* VideoSync VTG */ + {173, 8, 28, 8, 29, 13}, /* VideoSync DVP0 */ + {174, 8, 28, 8, 30, 13}, /* VideoSync DVP1 */ +#endif +#elif defined(CONFIG_CPU_SUBTYPE_SH7760) +/* + * SH7760 INTC2-Style interrupts, vectors IRQ48-111 INTEVT 0x800-0xFE0 + */ + /* INTPRIO0 | INTMSK0 */ + {48, 0, 28, 0, 31, 3}, /* IRQ 4 */ + {49, 0, 24, 0, 30, 3}, /* IRQ 3 */ + {50, 0, 20, 0, 29, 3}, /* IRQ 2 */ + {51, 0, 16, 0, 28, 3}, /* IRQ 1 */ + /* 52-55 (INTEVT 0x880-0x8E0) unused/reserved */ + /* INTPRIO4 | INTMSK0 */ + {56, 4, 28, 0, 25, 3}, /* HCAN2_CHAN0 */ + {57, 4, 24, 0, 24, 3}, /* HCAN2_CHAN1 */ + {58, 4, 20, 0, 23, 3}, /* I2S_CHAN0 */ + {59, 4, 16, 0, 22, 3}, /* I2S_CHAN1 */ + {60, 4, 12, 0, 21, 3}, /* AC97_CHAN0 */ + {61, 4, 8, 0, 20, 3}, /* AC97_CHAN1 */ + {62, 4, 4, 0, 19, 3}, /* I2C_CHAN0 */ + {63, 4, 0, 0, 18, 3}, /* I2C_CHAN1 */ + /* INTPRIO8 | INTMSK0 */ + {52, 8, 16, 0, 11, 3}, /* SCIF0_ERI_IRQ */ + {53, 8, 16, 0, 10, 3}, /* SCIF0_RXI_IRQ */ + {54, 8, 16, 0, 9, 3}, /* SCIF0_BRI_IRQ */ + {55, 8, 16, 0, 8, 3}, /* SCIF0_TXI_IRQ */ + {64, 8, 28, 0, 17, 3}, /* USBHI_IRQ */ + {65, 8, 24, 0, 16, 3}, /* LCDC */ + /* 66, 67 unused */ + {68, 8, 20, 0, 14, 13}, /* DMABRGI0_IRQ */ + {69, 8, 20, 0, 13, 13}, /* DMABRGI1_IRQ */ + {70, 8, 20, 0, 12, 13}, /* DMABRGI2_IRQ */ + /* 71 unused */ + {72, 8, 12, 0, 7, 3}, /* SCIF1_ERI_IRQ */ + {73, 8, 12, 0, 6, 3}, /* SCIF1_RXI_IRQ */ + {74, 8, 12, 0, 5, 3}, /* SCIF1_BRI_IRQ */ + {75, 8, 12, 0, 4, 3}, /* SCIF1_TXI_IRQ */ + {76, 8, 8, 0, 3, 3}, /* SCIF2_ERI_IRQ */ + {77, 8, 8, 0, 2, 3}, /* SCIF2_RXI_IRQ */ + {78, 8, 8, 0, 1, 3}, /* SCIF2_BRI_IRQ */ + {79, 8, 8, 0, 0, 3}, /* SCIF2_TXI_IRQ */ + /* | INTMSK4 */ + {80, 8, 4, 4, 23, 3}, /* SIM_ERI */ + {81, 8, 4, 4, 22, 3}, /* SIM_RXI */ + {82, 8, 4, 4, 21, 3}, /* SIM_TXI */ + {83, 8, 4, 4, 20, 3}, /* SIM_TEI */ + {84, 8, 0, 4, 19, 3}, /* HSPII */ + /* INTPRIOC | INTMSK4 */ + /* 85-87 unused/reserved */ + {88, 12, 20, 4, 18, 3}, /* MMCI0 */ + {89, 12, 20, 4, 17, 3}, /* MMCI1 */ + {90, 12, 20, 4, 16, 3}, /* MMCI2 */ + {91, 12, 20, 4, 15, 3}, /* MMCI3 */ + {92, 12, 12, 4, 6, 3}, /* MFI (unsure, bug? in my 7760 manual*/ + /* 93-107 reserved/undocumented */ + {108,12, 4, 4, 1, 3}, /* ADC */ + {109,12, 0, 4, 0, 3}, /* CMTI */ + /* 110-111 reserved/unused */ +#elif defined(CONFIG_CPU_SUBTYPE_SH7780) + { TIMER_IRQ, 0, 24, 0, INTC_TMU0_MSK, 2}, +#ifdef CONFIG_SH_RTC + { RTC_IRQ, 4, 0, 0, INTC_RTC_MSK, TIMER_PRIORITY }, +#endif + { SCIF0_ERI_IRQ, 8, 24, 0, INTC_SCIF0_MSK, SCIF0_PRIORITY }, + { SCIF0_RXI_IRQ, 8, 24, 0, INTC_SCIF0_MSK, SCIF0_PRIORITY }, + { SCIF0_BRI_IRQ, 8, 24, 0, INTC_SCIF0_MSK, SCIF0_PRIORITY }, + { SCIF0_TXI_IRQ, 8, 24, 0, INTC_SCIF0_MSK, SCIF0_PRIORITY }, + + { SCIF1_ERI_IRQ, 8, 16, 0, INTC_SCIF1_MSK, SCIF1_PRIORITY }, + { SCIF1_RXI_IRQ, 8, 16, 0, INTC_SCIF1_MSK, SCIF1_PRIORITY }, + { SCIF1_BRI_IRQ, 8, 16, 0, INTC_SCIF1_MSK, SCIF1_PRIORITY }, + { SCIF1_TXI_IRQ, 8, 16, 0, INTC_SCIF1_MSK, SCIF1_PRIORITY }, + + { PCIC0_IRQ, 0x10, 8, 0, INTC_PCIC0_MSK, PCIC0_PRIORITY }, + { PCIC1_IRQ, 0x10, 0, 0, INTC_PCIC1_MSK, PCIC1_PRIORITY }, + { PCIC2_IRQ, 0x14, 24, 0, INTC_PCIC2_MSK, PCIC2_PRIORITY }, + { PCIC3_IRQ, 0x14, 16, 0, INTC_PCIC3_MSK, PCIC3_PRIORITY }, + { PCIC4_IRQ, 0x14, 8, 0, INTC_PCIC4_MSK, PCIC4_PRIORITY }, +#endif +}; + +void __init init_IRQ_intc2(void) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(intc2_init_data); i++) { + struct intc2_init *p = intc2_init_data + i; + make_intc2_irq(p->irq, p->ipr_offset, p->ipr_shift, + p-> msk_offset, p->msk_shift, p->priority); + } +} + +/* Adds a termination callback to the interrupt */ +void intc2_add_clear_irq(int irq, int (*fn)(int)) +{ + if (unlikely(irq < INTC2_FIRST_IRQ)) + return; + + intc2_data[irq - INTC2_FIRST_IRQ].clear_irq = fn; +} + diff --git a/arch/sh/kernel/cpu/irq_ipr.c b/arch/sh/kernel/cpu/irq/ipr.c index 71f92096132..fdbd718ae5c 100644 --- a/arch/sh/kernel/cpu/irq_ipr.c +++ b/arch/sh/kernel/cpu/irq/ipr.c @@ -1,6 +1,5 @@ -/* $Id: irq_ipr.c,v 1.1.2.1 2002/11/17 10:53:43 mrbrown Exp $ - * - * linux/arch/sh/kernel/irq_ipr.c +/* + * arch/sh/kernel/cpu/irq/ipr.c * * Copyright (C) 1999 Niibe Yutaka & Takeshi Yaegashi * Copyright (C) 2000 Kazumoto Kojima @@ -109,7 +108,8 @@ static void end_ipr_irq(unsigned int irq) enable_ipr_irq(irq); } -void make_ipr_irq(unsigned int irq, unsigned int addr, int pos, int priority) +void make_ipr_irq(unsigned int irq, unsigned int addr, int pos, + int priority, int maskpos) { disable_irq_nosync(irq); ipr_data[irq].addr = addr; @@ -120,126 +120,47 @@ void make_ipr_irq(unsigned int irq, unsigned int addr, int pos, int priority) disable_ipr_irq(irq); } -#if defined(CONFIG_CPU_SUBTYPE_SH7705) || \ - defined(CONFIG_CPU_SUBTYPE_SH7707) || \ - defined(CONFIG_CPU_SUBTYPE_SH7709) -static unsigned char pint_map[256]; -static unsigned long portcr_mask = 0; - -static void enable_pint_irq(unsigned int irq); -static void disable_pint_irq(unsigned int irq); - -/* shutdown is same as "disable" */ -#define shutdown_pint_irq disable_pint_irq - -static void mask_and_ack_pint(unsigned int); -static void end_pint_irq(unsigned int irq); - -static unsigned int startup_pint_irq(unsigned int irq) -{ - enable_pint_irq(irq); - return 0; /* never anything pending */ -} - -static struct hw_interrupt_type pint_irq_type = { - .typename = "PINT-IRQ", - .startup = startup_pint_irq, - .shutdown = shutdown_pint_irq, - .enable = enable_pint_irq, - .disable = disable_pint_irq, - .ack = mask_and_ack_pint, - .end = end_pint_irq -}; - -static void disable_pint_irq(unsigned int irq) -{ - unsigned long val, flags; - - local_irq_save(flags); - val = ctrl_inw(INTC_INTER); - val &= ~(1 << (irq - PINT_IRQ_BASE)); - ctrl_outw(val, INTC_INTER); /* disable PINTn */ - portcr_mask &= ~(3 << (irq - PINT_IRQ_BASE)*2); - local_irq_restore(flags); -} - -static void enable_pint_irq(unsigned int irq) -{ - unsigned long val, flags; - - local_irq_save(flags); - val = ctrl_inw(INTC_INTER); - val |= 1 << (irq - PINT_IRQ_BASE); - ctrl_outw(val, INTC_INTER); /* enable PINTn */ - portcr_mask |= 3 << (irq - PINT_IRQ_BASE)*2; - local_irq_restore(flags); -} - -static void mask_and_ack_pint(unsigned int irq) -{ - disable_pint_irq(irq); -} - -static void end_pint_irq(unsigned int irq) -{ - if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) - enable_pint_irq(irq); -} - -void make_pint_irq(unsigned int irq) -{ - disable_irq_nosync(irq); - irq_desc[irq].handler = &pint_irq_type; - disable_pint_irq(irq); -} -#endif - void __init init_IRQ(void) { -#if defined(CONFIG_CPU_SUBTYPE_SH7705) || \ - defined(CONFIG_CPU_SUBTYPE_SH7707) || \ - defined(CONFIG_CPU_SUBTYPE_SH7709) - int i; -#endif - - make_ipr_irq(TIMER_IRQ, TIMER_IPR_ADDR, TIMER_IPR_POS, TIMER_PRIORITY); - make_ipr_irq(TIMER1_IRQ, TIMER1_IPR_ADDR, TIMER1_IPR_POS, TIMER1_PRIORITY); +#ifndef CONFIG_CPU_SUBTYPE_SH7780 + make_ipr_irq(TIMER_IRQ, TIMER_IPR_ADDR, TIMER_IPR_POS, TIMER_PRIORITY, 0); + make_ipr_irq(TIMER1_IRQ, TIMER1_IPR_ADDR, TIMER1_IPR_POS, TIMER1_PRIORITY, 0); #if defined(CONFIG_SH_RTC) - make_ipr_irq(RTC_IRQ, RTC_IPR_ADDR, RTC_IPR_POS, RTC_PRIORITY); + make_ipr_irq(RTC_IRQ, RTC_IPR_ADDR, RTC_IPR_POS, RTC_PRIORITY, 0); #endif #ifdef SCI_ERI_IRQ - make_ipr_irq(SCI_ERI_IRQ, SCI_IPR_ADDR, SCI_IPR_POS, SCI_PRIORITY); - make_ipr_irq(SCI_RXI_IRQ, SCI_IPR_ADDR, SCI_IPR_POS, SCI_PRIORITY); - make_ipr_irq(SCI_TXI_IRQ, SCI_IPR_ADDR, SCI_IPR_POS, SCI_PRIORITY); + make_ipr_irq(SCI_ERI_IRQ, SCI_IPR_ADDR, SCI_IPR_POS, SCI_PRIORITY, 0); + make_ipr_irq(SCI_RXI_IRQ, SCI_IPR_ADDR, SCI_IPR_POS, SCI_PRIORITY, 0); + make_ipr_irq(SCI_TXI_IRQ, SCI_IPR_ADDR, SCI_IPR_POS, SCI_PRIORITY, 0); #endif #ifdef SCIF1_ERI_IRQ - make_ipr_irq(SCIF1_ERI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY); - make_ipr_irq(SCIF1_RXI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY); - make_ipr_irq(SCIF1_BRI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY); - make_ipr_irq(SCIF1_TXI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY); + make_ipr_irq(SCIF1_ERI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY, 0); + make_ipr_irq(SCIF1_RXI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY, 0); + make_ipr_irq(SCIF1_BRI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY, 0); + make_ipr_irq(SCIF1_TXI_IRQ, SCIF1_IPR_ADDR, SCIF1_IPR_POS, SCIF1_PRIORITY, 0); #endif #if defined(CONFIG_CPU_SUBTYPE_SH7300) - make_ipr_irq(SCIF0_IRQ, SCIF0_IPR_ADDR, SCIF0_IPR_POS, SCIF0_PRIORITY); - make_ipr_irq(DMTE2_IRQ, DMA1_IPR_ADDR, DMA1_IPR_POS, DMA1_PRIORITY); - make_ipr_irq(DMTE3_IRQ, DMA1_IPR_ADDR, DMA1_IPR_POS, DMA1_PRIORITY); - make_ipr_irq(VIO_IRQ, VIO_IPR_ADDR, VIO_IPR_POS, VIO_PRIORITY); + make_ipr_irq(SCIF0_IRQ, SCIF0_IPR_ADDR, SCIF0_IPR_POS, SCIF0_PRIORITY, 0); + make_ipr_irq(DMTE2_IRQ, DMA1_IPR_ADDR, DMA1_IPR_POS, DMA1_PRIORITY, 0); + make_ipr_irq(DMTE3_IRQ, DMA1_IPR_ADDR, DMA1_IPR_POS, DMA1_PRIORITY, 0); + make_ipr_irq(VIO_IRQ, VIO_IPR_ADDR, VIO_IPR_POS, VIO_PRIORITY, 0); #endif #ifdef SCIF_ERI_IRQ - make_ipr_irq(SCIF_ERI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY); - make_ipr_irq(SCIF_RXI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY); - make_ipr_irq(SCIF_BRI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY); - make_ipr_irq(SCIF_TXI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY); + make_ipr_irq(SCIF_ERI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY, 0); + make_ipr_irq(SCIF_RXI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY, 0); + make_ipr_irq(SCIF_BRI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY, 0); + make_ipr_irq(SCIF_TXI_IRQ, SCIF_IPR_ADDR, SCIF_IPR_POS, SCIF_PRIORITY, 0); #endif #ifdef IRDA_ERI_IRQ - make_ipr_irq(IRDA_ERI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY); - make_ipr_irq(IRDA_RXI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY); - make_ipr_irq(IRDA_BRI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY); - make_ipr_irq(IRDA_TXI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY); + make_ipr_irq(IRDA_ERI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY, 0); + make_ipr_irq(IRDA_RXI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY, 0); + make_ipr_irq(IRDA_BRI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY, 0); + make_ipr_irq(IRDA_TXI_IRQ, IRDA_IPR_ADDR, IRDA_IPR_POS, IRDA_PRIORITY, 0); #endif #if defined(CONFIG_CPU_SUBTYPE_SH7707) || defined(CONFIG_CPU_SUBTYPE_SH7709) || \ @@ -254,86 +175,32 @@ void __init init_IRQ(void) * You should set corresponding bits of PFC to "00" * to enable these interrupts. */ - make_ipr_irq(IRQ0_IRQ, IRQ0_IPR_ADDR, IRQ0_IPR_POS, IRQ0_PRIORITY); - make_ipr_irq(IRQ1_IRQ, IRQ1_IPR_ADDR, IRQ1_IPR_POS, IRQ1_PRIORITY); - make_ipr_irq(IRQ2_IRQ, IRQ2_IPR_ADDR, IRQ2_IPR_POS, IRQ2_PRIORITY); - make_ipr_irq(IRQ3_IRQ, IRQ3_IPR_ADDR, IRQ3_IPR_POS, IRQ3_PRIORITY); - make_ipr_irq(IRQ4_IRQ, IRQ4_IPR_ADDR, IRQ4_IPR_POS, IRQ4_PRIORITY); - make_ipr_irq(IRQ5_IRQ, IRQ5_IPR_ADDR, IRQ5_IPR_POS, IRQ5_PRIORITY); -#if !defined(CONFIG_CPU_SUBTYPE_SH7300) - make_ipr_irq(PINT0_IRQ, PINT0_IPR_ADDR, PINT0_IPR_POS, PINT0_PRIORITY); - make_ipr_irq(PINT8_IRQ, PINT8_IPR_ADDR, PINT8_IPR_POS, PINT8_PRIORITY); - enable_ipr_irq(PINT0_IRQ); - enable_ipr_irq(PINT8_IRQ); + make_ipr_irq(IRQ0_IRQ, IRQ0_IPR_ADDR, IRQ0_IPR_POS, IRQ0_PRIORITY, 0); + make_ipr_irq(IRQ1_IRQ, IRQ1_IPR_ADDR, IRQ1_IPR_POS, IRQ1_PRIORITY, 0); + make_ipr_irq(IRQ2_IRQ, IRQ2_IPR_ADDR, IRQ2_IPR_POS, IRQ2_PRIORITY, 0); + make_ipr_irq(IRQ3_IRQ, IRQ3_IPR_ADDR, IRQ3_IPR_POS, IRQ3_PRIORITY, 0); + make_ipr_irq(IRQ4_IRQ, IRQ4_IPR_ADDR, IRQ4_IPR_POS, IRQ4_PRIORITY, 0); + make_ipr_irq(IRQ5_IRQ, IRQ5_IPR_ADDR, IRQ5_IPR_POS, IRQ5_PRIORITY, 0); +#endif +#endif - for(i = 0; i < 16; i++) - make_pint_irq(PINT_IRQ_BASE + i); - for(i = 0; i < 256; i++) - { - if(i & 1) pint_map[i] = 0; - else if(i & 2) pint_map[i] = 1; - else if(i & 4) pint_map[i] = 2; - else if(i & 8) pint_map[i] = 3; - else if(i & 0x10) pint_map[i] = 4; - else if(i & 0x20) pint_map[i] = 5; - else if(i & 0x40) pint_map[i] = 6; - else if(i & 0x80) pint_map[i] = 7; - } -#endif /* !CONFIG_CPU_SUBTYPE_SH7300 */ -#endif /* CONFIG_CPU_SUBTYPE_SH7707 || CONFIG_CPU_SUBTYPE_SH7709 || CONFIG_CPU_SUBTYPE_SH7300*/ +#ifdef CONFIG_CPU_HAS_PINT_IRQ + init_IRQ_pint(); +#endif -#ifdef CONFIG_CPU_SUBTYPE_ST40 +#ifdef CONFIG_CPU_HAS_INTC2_IRQ init_IRQ_intc2(); #endif - /* Perform the machine specific initialisation */ - if (sh_mv.mv_init_irq != NULL) { + if (sh_mv.mv_init_irq != NULL) sh_mv.mv_init_irq(); - } } -#if defined(CONFIG_CPU_SUBTYPE_SH7707) || defined(CONFIG_CPU_SUBTYPE_SH7709) || \ - defined(CONFIG_CPU_SUBTYPE_SH7300) || defined(CONFIG_CPU_SUBTYPE_SH7705) + +#if !defined(CONFIG_CPU_HAS_PINT_IRQ) int ipr_irq_demux(int irq) { -#if !defined(CONFIG_CPU_SUBTYPE_SH7300) - unsigned long creg, dreg, d, sav; - - if(irq == PINT0_IRQ) - { -#if defined(CONFIG_CPU_SUBTYPE_SH7707) - creg = PORT_PACR; - dreg = PORT_PADR; -#else - creg = PORT_PCCR; - dreg = PORT_PCDR; -#endif - sav = ctrl_inw(creg); - ctrl_outw(sav | portcr_mask, creg); - d = (~ctrl_inb(dreg) ^ ctrl_inw(INTC_ICR2)) & ctrl_inw(INTC_INTER) & 0xff; - ctrl_outw(sav, creg); - if(d == 0) return irq; - return PINT_IRQ_BASE + pint_map[d]; - } - else if(irq == PINT8_IRQ) - { -#if defined(CONFIG_CPU_SUBTYPE_SH7707) - creg = PORT_PBCR; - dreg = PORT_PBDR; -#else - creg = PORT_PFCR; - dreg = PORT_PFDR; -#endif - sav = ctrl_inw(creg); - ctrl_outw(sav | (portcr_mask >> 16), creg); - d = (~ctrl_inb(dreg) ^ (ctrl_inw(INTC_ICR2) >> 8)) & (ctrl_inw(INTC_INTER) >> 8) & 0xff; - ctrl_outw(sav, creg); - if(d == 0) return irq; - return PINT_IRQ_BASE + 8 + pint_map[d]; - } -#endif return irq; } #endif EXPORT_SYMBOL(make_ipr_irq); - diff --git a/arch/sh/kernel/cpu/irq/pint.c b/arch/sh/kernel/cpu/irq/pint.c new file mode 100644 index 00000000000..95d6024fe1a --- /dev/null +++ b/arch/sh/kernel/cpu/irq/pint.c @@ -0,0 +1,169 @@ +/* + * arch/sh/kernel/cpu/irq/pint.c - Interrupt handling for PINT-based IRQs. + * + * Copyright (C) 1999 Niibe Yutaka & Takeshi Yaegashi + * Copyright (C) 2000 Kazumoto Kojima + * Copyright (C) 2003 Takashi Kusuda <kusuda-takashi@hitachi-ul.co.jp> + * + * 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. + */ + +#include <linux/config.h> +#include <linux/init.h> +#include <linux/irq.h> +#include <linux/module.h> + +#include <asm/system.h> +#include <asm/io.h> +#include <asm/machvec.h> + +static unsigned char pint_map[256]; +static unsigned long portcr_mask; + +static void enable_pint_irq(unsigned int irq); +static void disable_pint_irq(unsigned int irq); + +/* shutdown is same as "disable" */ +#define shutdown_pint_irq disable_pint_irq + +static void mask_and_ack_pint(unsigned int); +static void end_pint_irq(unsigned int irq); + +static unsigned int startup_pint_irq(unsigned int irq) +{ + enable_pint_irq(irq); + return 0; /* never anything pending */ +} + +static struct hw_interrupt_type pint_irq_type = { + .typename = "PINT-IRQ", + .startup = startup_pint_irq, + .shutdown = shutdown_pint_irq, + .enable = enable_pint_irq, + .disable = disable_pint_irq, + .ack = mask_and_ack_pint, + .end = end_pint_irq +}; + +static void disable_pint_irq(unsigned int irq) +{ + unsigned long val, flags; + + local_irq_save(flags); + val = ctrl_inw(INTC_INTER); + val &= ~(1 << (irq - PINT_IRQ_BASE)); + ctrl_outw(val, INTC_INTER); /* disable PINTn */ + portcr_mask &= ~(3 << (irq - PINT_IRQ_BASE)*2); + local_irq_restore(flags); +} + +static void enable_pint_irq(unsigned int irq) +{ + unsigned long val, flags; + + local_irq_save(flags); + val = ctrl_inw(INTC_INTER); + val |= 1 << (irq - PINT_IRQ_BASE); + ctrl_outw(val, INTC_INTER); /* enable PINTn */ + portcr_mask |= 3 << (irq - PINT_IRQ_BASE)*2; + local_irq_restore(flags); +} + +static void mask_and_ack_pint(unsigned int irq) +{ + disable_pint_irq(irq); +} + +static void end_pint_irq(unsigned int irq) +{ + if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) + enable_pint_irq(irq); +} + +void make_pint_irq(unsigned int irq) +{ + disable_irq_nosync(irq); + irq_desc[irq].handler = &pint_irq_type; + disable_pint_irq(irq); +} + +void __init init_IRQ_pint(void) +{ + int i; + + make_ipr_irq(PINT0_IRQ, PINT0_IPR_ADDR, PINT0_IPR_POS, PINT0_PRIORITY); + make_ipr_irq(PINT8_IRQ, PINT8_IPR_ADDR, PINT8_IPR_POS, PINT8_PRIORITY); + + enable_irq(PINT0_IRQ); + enable_irq(PINT8_IRQ); + + for(i = 0; i < 16; i++) + make_pint_irq(PINT_IRQ_BASE + i); + + for(i = 0; i < 256; i++) { + if (i & 1) + pint_map[i] = 0; + else if (i & 2) + pint_map[i] = 1; + else if (i & 4) + pint_map[i] = 2; + else if (i & 8) + pint_map[i] = 3; + else if (i & 0x10) + pint_map[i] = 4; + else if (i & 0x20) + pint_map[i] = 5; + else if (i & 0x40) + pint_map[i] = 6; + else if (i & 0x80) + pint_map[i] = 7; + } +} + +int ipr_irq_demux(int irq) +{ + unsigned long creg, dreg, d, sav; + + if (irq == PINT0_IRQ) { +#if defined(CONFIG_CPU_SUBTYPE_SH7707) + creg = PORT_PACR; + dreg = PORT_PADR; +#else + creg = PORT_PCCR; + dreg = PORT_PCDR; +#endif + sav = ctrl_inw(creg); + ctrl_outw(sav | portcr_mask, creg); + d = (~ctrl_inb(dreg) ^ ctrl_inw(INTC_ICR2)) & + ctrl_inw(INTC_INTER) & 0xff; + ctrl_outw(sav, creg); + + if (d == 0) + return irq; + + return PINT_IRQ_BASE + pint_map[d]; + } else if (irq == PINT8_IRQ) { +#if defined(CONFIG_CPU_SUBTYPE_SH7707) + creg = PORT_PBCR; + dreg = PORT_PBDR; +#else + creg = PORT_PFCR; + dreg = PORT_PFDR; +#endif + sav = ctrl_inw(creg); + ctrl_outw(sav | (portcr_mask >> 16), creg); + d = (~ctrl_inb(dreg) ^ (ctrl_inw(INTC_ICR2) >> 8)) & + (ctrl_inw(INTC_INTER) >> 8) & 0xff; + ctrl_outw(sav, creg); + + if (d == 0) + return irq; + + return PINT_IRQ_BASE + 8 + pint_map[d]; + } + + return irq; +} + diff --git a/arch/sh/kernel/cpu/sh3/Makefile b/arch/sh/kernel/cpu/sh3/Makefile index a64532e4dc6..b54dbb9a0c8 100644 --- a/arch/sh/kernel/cpu/sh3/Makefile +++ b/arch/sh/kernel/cpu/sh3/Makefile @@ -4,3 +4,10 @@ obj-y := ex.o probe.o +clock-$(CONFIG_CPU_SH3) := clock-sh3.o +clock-$(CONFIG_CPU_SUBTYPE_SH7300) := clock-sh7300.o +clock-$(CONFIG_CPU_SUBTYPE_SH7705) := clock-sh7705.o +clock-$(CONFIG_CPU_SUBTYPE_SH7709) := clock-sh7709.o + +obj-y += $(clock-y) + diff --git a/arch/sh/kernel/cpu/sh3/clock-sh3.c b/arch/sh/kernel/cpu/sh3/clock-sh3.c new file mode 100644 index 00000000000..c3c945958ba --- /dev/null +++ b/arch/sh/kernel/cpu/sh3/clock-sh3.c @@ -0,0 +1,89 @@ +/* + * arch/sh/kernel/cpu/sh3/clock-sh3.c + * + * Generic SH-3 support for the clock framework + * + * Copyright (C) 2005 Paul Mundt + * + * FRQCR parsing hacked out of arch/sh/kernel/time.c + * + * Copyright (C) 1999 Tetsuya Okada & Niibe Yutaka + * Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org> + * Copyright (C) 2002, 2003, 2004 Paul Mundt + * Copyright (C) 2002 M. R. Brown <mrbrown@linux-sh.org> + * + * 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. + */ +#include <linux/init.h> +#include <linux/kernel.h> +#include <asm/clock.h> +#include <asm/freq.h> +#include <asm/io.h> + +static int stc_multipliers[] = { 1, 2, 3, 4, 6, 1, 1, 1 }; +static int ifc_divisors[] = { 1, 2, 3, 4, 1, 1, 1, 1 }; +static int pfc_divisors[] = { 1, 2, 3, 4, 6, 1, 1, 1 }; + +static void master_clk_init(struct clk *clk) +{ + int frqcr = ctrl_inw(FRQCR); + int idx = ((frqcr & 0x2000) >> 11) | (frqcr & 0x0003); + + clk->rate *= pfc_divisors[idx]; +} + +static struct clk_ops sh3_master_clk_ops = { + .init = master_clk_init, +}; + +static void module_clk_recalc(struct clk *clk) +{ + int frqcr = ctrl_inw(FRQCR); + int idx = ((frqcr & 0x2000) >> 11) | (frqcr & 0x0003); + + clk->rate = clk->parent->rate / pfc_divisors[idx]; +} + +static struct clk_ops sh3_module_clk_ops = { + .recalc = module_clk_recalc, +}; + +static void bus_clk_recalc(struct clk *clk) +{ + int frqcr = ctrl_inw(FRQCR); + int idx = ((frqcr & 0x8000) >> 13) | ((frqcr & 0x0030) >> 4); + + clk->rate = clk->parent->rate / stc_multipliers[idx]; +} + +static struct clk_ops sh3_bus_clk_ops = { + .recalc = bus_clk_recalc, +}; + +static void cpu_clk_recalc(struct clk *clk) +{ + int frqcr = ctrl_inw(FRQCR); + int idx = ((frqcr & 0x4000) >> 12) | ((frqcr & 0x000c) >> 2); + + clk->rate = clk->parent->rate / ifc_divisors[idx]; +} + +static struct clk_ops sh3_cpu_clk_ops = { + .recalc = cpu_clk_recalc, +}; + +static struct clk_ops *sh3_clk_ops[] = { + &sh3_master_clk_ops, + &sh3_module_clk_ops, + &sh3_bus_clk_ops, + &sh3_cpu_clk_ops, +}; + +void __init arch_init_clk_ops(struct clk_ops **ops, int idx) +{ + if (idx < ARRAY_SIZE(sh3_clk_ops)) + *ops = sh3_clk_ops[idx]; +} + diff --git a/arch/sh/kernel/cpu/sh3/clock-sh7300.c b/arch/sh/kernel/cpu/sh3/clock-sh7300.c new file mode 100644 index 00000000000..e804174b962 --- /dev/null +++ b/arch/sh/kernel/cpu/sh3/clock-sh7300.c @@ -0,0 +1,78 @@ +/* + * arch/sh/kernel/cpu/sh3/clock-sh7300.c + * + * SH7300 support for the clock framework + * + * Copyright (C) 2005 Paul Mundt + * + * FRQCR parsing hacked out of arch/sh/kernel/time.c + * + * Copyright (C) 1999 Tetsuya Okada & Niibe Yutaka + * Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org> + * Copyright (C) 2002, 2003, 2004 Paul Mundt + * Copyright (C) 2002 M. R. Brown <mrbrown@linux-sh.org> + * + * 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. + */ +#include <linux/init.h> +#include <linux/kernel.h> +#include <asm/clock.h> +#include <asm/freq.h> +#include <asm/io.h> + +static int md_table[] = { 1, 2, 3, 4, 6, 8, 12 }; + +static void master_clk_init(struct clk *clk) +{ + clk->rate *= md_table[ctrl_inw(FRQCR) & 0x0007]; +} + +static struct clk_ops sh7300_master_clk_ops = { + .init = master_clk_init, +}; + +static void module_clk_recalc(struct clk *clk) +{ + int idx = (ctrl_inw(FRQCR) & 0x0007); + clk->rate = clk->parent->rate / md_table[idx]; +} + +static struct clk_ops sh7300_module_clk_ops = { + .recalc = module_clk_recalc, +}; + +static void bus_clk_recalc(struct clk *clk) +{ + int idx = (ctrl_inw(FRQCR) & 0x0700) >> 8; + clk->rate = clk->parent->rate / md_table[idx]; +} + +static struct clk_ops sh7300_bus_clk_ops = { + .recalc = bus_clk_recalc, +}; + +static void cpu_clk_recalc(struct clk *clk) +{ + int idx = (ctrl_inw(FRQCR) & 0x0070) >> 4; + clk->rate = clk->parent->rate / md_table[idx]; +} + +static struct clk_ops sh7300_cpu_clk_ops = { + .recalc = cpu_clk_recalc, +}; + +static struct clk_ops *sh7300_clk_ops[] = { + &sh7300_master_clk_ops, + &sh7300_module_clk_ops, + &sh7300_bus_clk_ops, + &sh7300_cpu_clk_ops, +}; + +void __init arch_init_clk_ops(struct clk_ops **ops, int idx) +{ + if (idx < ARRAY_SIZE(sh7300_clk_ops)) + *ops = sh7300_clk_ops[idx]; +} + diff --git a/arch/sh/kernel/cpu/sh3/clock-sh7705.c b/arch/sh/kernel/cpu/sh3/clock-sh7705.c new file mode 100644 index 00000000000..dfdbf3277fd --- /dev/null +++ b/arch/sh/kernel/cpu/sh3/clock-sh7705.c @@ -0,0 +1,84 @@ +/* + * arch/sh/kernel/cpu/sh3/clock-sh7705.c + * + * SH7705 support for the clock framework + * + * Copyright (C) 2005 Paul Mundt + * + * FRQCR parsing hacked out of arch/sh/kernel/time.c + * + * Copyright (C) 1999 Tetsuya Okada & Niibe Yutaka + * Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org> + * Copyright (C) 2002, 2003, 2004 Paul Mundt + * Copyright (C) 2002 M. R. Brown <mrbrown@linux-sh.org> + * + * 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. + */ +#include <linux/init.h> +#include <linux/kernel.h> +#include <asm/clock.h> +#include <asm/freq.h> +#include <asm/io.h> + +/* + * SH7705 uses the same divisors as the generic SH-3 case, it's just the + * FRQCR layout that is a bit different.. + */ +static int stc_multipliers[] = { 1, 2, 3, 4, 6, 1, 1, 1 }; +static int ifc_divisors[] = { 1, 2, 3, 4, 1, 1, 1, 1 }; +static int pfc_divisors[] = { 1, 2, 3, 4, 6, 1, 1, 1 }; + +static void master_clk_init(struct clk *clk) +{ + clk->rate *= pfc_divisors[ctrl_inw(FRQCR) & 0x0003]; +} + +static struct clk_ops sh7705_master_clk_ops = { + .init = master_clk_init, +}; + +static void module_clk_recalc(struct clk *clk) +{ + int idx = ctrl_inw(FRQCR) & 0x0003; + clk->rate = clk->parent->rate / pfc_divisors[idx]; +} + +static struct clk_ops sh7705_module_clk_ops = { + .recalc = module_clk_recalc, +}; + +static void bus_clk_recalc(struct clk *clk) +{ + int idx = (ctrl_inw(FRQCR) & 0x0300) >> 8; + clk->rate = clk->parent->rate / stc_multipliers[idx]; +} + +static struct clk_ops sh7705_bus_clk_ops = { + .recalc = bus_clk_recalc, +}; + +static void cpu_clk_recalc(struct clk *clk) +{ + int idx = (ctrl_inw(FRQCR) & 0x0030) >> 4; + clk->rate = clk->parent->rate / ifc_divisors[idx]; +} + +static struct clk_ops sh7705_cpu_clk_ops = { + .recalc = cpu_clk_recalc, +}; + +static struct clk_ops *sh7705_clk_ops[] = { + &sh7705_master_clk_ops, + &sh7705_module_clk_ops, + &sh7705_bus_clk_ops, + &sh7705_cpu_clk_ops, +}; + +void __init arch_init_clk_ops(struct clk_ops **ops, int idx) +{ + if (idx < ARRAY_SIZE(sh7705_clk_ops)) + *ops = sh7705_clk_ops[idx]; +} + diff --git a/arch/sh/kernel/cpu/sh3/clock-sh7709.c b/arch/sh/kernel/cpu/sh3/clock-sh7709.c new file mode 100644 index 00000000000..10461a745e5 --- /dev/null +++ b/arch/sh/kernel/cpu/sh3/clock-sh7709.c @@ -0,0 +1,96 @@ +/* + * arch/sh/kernel/cpu/sh3/clock-sh7709.c + * + * SH7709 support for the clock framework + * + * Copyright (C) 2005 Andriy Skulysh + * + * Based on arch/sh/kernel/cpu/sh3/clock-sh7705.c + * Copyright (C) 2005 Paul Mundt + * + * 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. + */ +#include <linux/init.h> +#include <linux/kernel.h> +#include <asm/clock.h> +#include <asm/freq.h> +#include <asm/io.h> + +static int stc_multipliers[] = { 1, 2, 4, 8, 3, 6, 1, 1 }; +static int ifc_divisors[] = { 1, 2, 4, 1, 3, 1, 1, 1 }; +static int pfc_divisors[] = { 1, 2, 4, 1, 3, 6, 1, 1 }; + +static void set_bus_parent(struct clk *clk) +{ + struct clk *bus_clk = clk_get("bus_clk"); + clk->parent = bus_clk; + clk_put(bus_clk); +} + +static void master_clk_init(struct clk *clk) +{ + int frqcr = ctrl_inw(FRQCR); + int idx = ((frqcr & 0x2000) >> 11) | (frqcr & 0x0003); + + clk->rate *= pfc_divisors[idx]; +} + +static struct clk_ops sh7709_master_clk_ops = { + .init = master_clk_init, +}; + +static void module_clk_recalc(struct clk *clk) +{ + int frqcr = ctrl_inw(FRQCR); + int idx = ((frqcr & 0x2000) >> 11) | (frqcr & 0x0003); + + clk->rate = clk->parent->rate / pfc_divisors[idx]; +} + +static struct clk_ops sh7709_module_clk_ops = { +#ifdef CLOCK_MODE_0_1_2_7 + .init = set_bus_parent, +#endif + .recalc = module_clk_recalc, +}; + +static void bus_clk_recalc(struct clk *clk) +{ + int frqcr = ctrl_inw(FRQCR); + int idx = (frqcr & 0x0080) ? + ((frqcr & 0x8000) >> 13) | ((frqcr & 0x0030) >> 4) : 1; + + clk->rate = clk->parent->rate * stc_multipliers[idx]; +} + +static struct clk_ops sh7709_bus_clk_ops = { + .recalc = bus_clk_recalc, +}; + +static void cpu_clk_recalc(struct clk *clk) +{ + int frqcr = ctrl_inw(FRQCR); + int idx = ((frqcr & 0x4000) >> 12) | ((frqcr & 0x000c) >> 2); + + clk->rate = clk->parent->rate / ifc_divisors[idx]; +} + +static struct clk_ops sh7709_cpu_clk_ops = { + .init = set_bus_parent, + .recalc = cpu_clk_recalc, +}; + +static struct clk_ops *sh7709_clk_ops[] = { + &sh7709_master_clk_ops, + &sh7709_module_clk_ops, + &sh7709_bus_clk_ops, + &sh7709_cpu_clk_ops, +}; + +void __init arch_init_clk_ops(struct clk_ops **ops, int idx) +{ + if (idx < ARRAY_SIZE(sh7709_clk_ops)) + *ops = sh7709_clk_ops[idx]; +} diff --git a/arch/sh/kernel/cpu/sh4/Makefile b/arch/sh/kernel/cpu/sh4/Makefile index ead1071eac7..3d5cafc71ae 100644 --- a/arch/sh/kernel/cpu/sh4/Makefile +++ b/arch/sh/kernel/cpu/sh4/Makefile @@ -5,6 +5,15 @@ obj-y := ex.o probe.o obj-$(CONFIG_SH_FPU) += fpu.o -obj-$(CONFIG_CPU_SUBTYPE_ST40STB1) += irq_intc2.o obj-$(CONFIG_SH_STORE_QUEUES) += sq.o +# Primary on-chip clocks (common) +clock-$(CONFIG_CPU_SH4) := clock-sh4.o +clock-$(CONFIG_CPU_SUBTYPE_SH73180) := clock-sh73180.o +clock-$(CONFIG_CPU_SUBTYPE_SH7770) := clock-sh7770.o +clock-$(CONFIG_CPU_SUBTYPE_SH7780) := clock-sh7780.o + +# Additional clocks by subtype +clock-$(CONFIG_CPU_SUBTYPE_SH4_202) += clock-sh4-202.o + +obj-y += $(clock-y) diff --git a/arch/sh/kernel/cpu/sh4/clock-sh4-202.c b/arch/sh/kernel/cpu/sh4/clock-sh4-202.c new file mode 100644 index 00000000000..bfdf5fe8d94 --- /dev/null +++ b/arch/sh/kernel/cpu/sh4/clock-sh4-202.c @@ -0,0 +1,179 @@ +/* + * arch/sh/kernel/cpu/sh4/clock-sh4-202.c + * + * Additional SH4-202 support for the clock framework + * + * Copyright (C) 2005 Paul Mundt + * + * 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. + */ +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/err.h> +#include <asm/clock.h> +#include <asm/freq.h> +#include <asm/io.h> + +#define CPG2_FRQCR3 0xfe0a0018 + +static int frqcr3_divisors[] = { 1, 2, 3, 4, 6, 8, 16 }; +static int frqcr3_values[] = { 0, 1, 2, 3, 4, 5, 6 }; + +static void emi_clk_recalc(struct clk *clk) +{ + int idx = ctrl_inl(CPG2_FRQCR3) & 0x0007; + clk->rate = clk->parent->rate / frqcr3_divisors[idx]; +} + +static inline int frqcr3_lookup(struct clk *clk, unsigned long rate) +{ + int divisor = clk->parent->rate / rate; + int i; + + for (i = 0; i < ARRAY_SIZE(frqcr3_divisors); i++) + if (frqcr3_divisors[i] == divisor) + return frqcr3_values[i]; + + /* Safe fallback */ + return 5; +} + +static struct clk_ops sh4202_emi_clk_ops = { + .recalc = emi_clk_recalc, +}; + +static struct clk sh4202_emi_clk = { + .name = "emi_clk", + .flags = CLK_ALWAYS_ENABLED, + .ops = &sh4202_emi_clk_ops, +}; + +static void femi_clk_recalc(struct clk *clk) +{ + int idx = (ctrl_inl(CPG2_FRQCR3) >> 3) & 0x0007; + clk->rate = clk->parent->rate / frqcr3_divisors[idx]; +} + +static struct clk_ops sh4202_femi_clk_ops = { + .recalc = femi_clk_recalc, +}; + +static struct clk sh4202_femi_clk = { + .name = "femi_clk", + .flags = CLK_ALWAYS_ENABLED, + .ops = &sh4202_femi_clk_ops, +}; + +static void shoc_clk_init(struct clk *clk) +{ + int i; + + /* + * For some reason, the shoc_clk seems to be set to some really + * insane value at boot (values outside of the allowable frequency + * range for instance). We deal with this by scaling it back down + * to something sensible just in case. + * + * Start scaling from the high end down until we find something + * that passes rate verification.. + */ + for (i = 0; i < ARRAY_SIZE(frqcr3_divisors); i++) { + int divisor = frqcr3_divisors[i]; + + if (clk->ops->set_rate(clk, clk->parent->rate / divisor) == 0) + break; + } + + WARN_ON(i == ARRAY_SIZE(frqcr3_divisors)); /* Undefined clock */ +} + +static void shoc_clk_recalc(struct clk *clk) +{ + int idx = (ctrl_inl(CPG2_FRQCR3) >> 6) & 0x0007; + clk->rate = clk->parent->rate / frqcr3_divisors[idx]; +} + +static int shoc_clk_verify_rate(struct clk *clk, unsigned long rate) +{ + struct clk *bclk = clk_get("bus_clk"); + unsigned long bclk_rate = clk_get_rate(bclk); + + clk_put(bclk); + + if (rate > bclk_rate) + return 1; + if (rate > 66000000) + return 1; + + return 0; +} + +static int shoc_clk_set_rate(struct clk *clk, unsigned long rate) +{ + unsigned long frqcr3; + unsigned int tmp; + + /* Make sure we have something sensible to switch to */ + if (shoc_clk_verify_rate(clk, rate) != 0) + return -EINVAL; + + tmp = frqcr3_lookup(clk, rate); + + frqcr3 = ctrl_inl(CPG2_FRQCR3); + frqcr3 &= ~(0x0007 << 6); + frqcr3 |= tmp << 6; + ctrl_outl(frqcr3, CPG2_FRQCR3); + + clk->rate = clk->parent->rate / frqcr3_divisors[tmp]; + + return 0; +} + +static struct clk_ops sh4202_shoc_clk_ops = { + .init = shoc_clk_init, + .recalc = shoc_clk_recalc, + .set_rate = shoc_clk_set_rate, +}; + +static struct clk sh4202_shoc_clk = { + .name = "shoc_clk", + .flags = CLK_ALWAYS_ENABLED, + .ops = &sh4202_shoc_clk_ops, +}; + +static struct clk *sh4202_onchip_clocks[] = { + &sh4202_emi_clk, + &sh4202_femi_clk, + &sh4202_shoc_clk, +}; + +static int __init sh4202_clk_init(void) +{ + struct clk *clk = clk_get("master_clk"); + int i; + + for (i = 0; i < ARRAY_SIZE(sh4202_onchip_clocks); i++) { + struct clk *clkp = sh4202_onchip_clocks[i]; + + clkp->parent = clk; + clk_register(clkp); + clk_enable(clkp); + } + + /* + * Now that we have the rest of the clocks registered, we need to + * force the parent clock to propagate so that these clocks will + * automatically figure out their rate. We cheat by handing the + * parent clock its current rate and forcing child propagation. + */ + clk_set_rate(clk, clk_get_rate(clk)); + + clk_put(clk); + + return 0; +} + +arch_initcall(sh4202_clk_init); + diff --git a/arch/sh/kernel/cpu/sh4/clock-sh4.c b/arch/sh/kernel/cpu/sh4/clock-sh4.c new file mode 100644 index 00000000000..dca9f87a12d --- /dev/null +++ b/arch/sh/kernel/cpu/sh4/clock-sh4.c @@ -0,0 +1,80 @@ +/* + * arch/sh/kernel/cpu/sh4/clock-sh4.c + * + * Generic SH-4 support for the clock framework + * + * Copyright (C) 2005 Paul Mundt + * + * FRQCR parsing hacked out of arch/sh/kernel/time.c + * + * Copyright (C) 1999 Tetsuya Okada & Niibe Yutaka + * Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org> + * Copyright (C) 2002, 2003, 2004 Paul Mundt + * Copyright (C) 2002 M. R. Brown <mrbrown@linux-sh.org> + * + * 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. + */ +#include <linux/init.h> +#include <linux/kernel.h> +#include <asm/clock.h> +#include <asm/freq.h> +#include <asm/io.h> + +static int ifc_divisors[] = { 1, 2, 3, 4, 6, 8, 1, 1 }; +#define bfc_divisors ifc_divisors /* Same */ +static int pfc_divisors[] = { 2, 3, 4, 6, 8, 2, 2, 2 }; + +static void master_clk_init(struct clk *clk) +{ + clk->rate *= pfc_divisors[ctrl_inw(FRQCR) & 0x0007]; +} + +static struct clk_ops sh4_master_clk_ops = { + .init = master_clk_init, +}; + +static void module_clk_recalc(struct clk *clk) +{ + int idx = (ctrl_inw(FRQCR) & 0x0007); + clk->rate = clk->parent->rate / pfc_divisors[idx]; +} + +static struct clk_ops sh4_module_clk_ops = { + .recalc = module_clk_recalc, +}; + +static void bus_clk_recalc(struct clk *clk) +{ + int idx = (ctrl_inw(FRQCR) >> 3) & 0x0007; + clk->rate = clk->parent->rate / bfc_divisors[idx]; +} + +static struct clk_ops sh4_bus_clk_ops = { + .recalc = bus_clk_recalc, +}; + +static void cpu_clk_recalc(struct clk *clk) +{ + int idx = (ctrl_inw(FRQCR) >> 6) & 0x0007; + clk->rate = clk->parent->rate / ifc_divisors[idx]; +} + +static struct clk_ops sh4_cpu_clk_ops = { + .recalc = cpu_clk_recalc, +}; + +static struct clk_ops *sh4_clk_ops[] = { + &sh4_master_clk_ops, + &sh4_module_clk_ops, + &sh4_bus_clk_ops, + &sh4_cpu_clk_ops, +}; + +void __init arch_init_clk_ops(struct clk_ops **ops, int idx) +{ + if (idx < ARRAY_SIZE(sh4_clk_ops)) + *ops = sh4_clk_ops[idx]; +} + diff --git a/arch/sh/kernel/cpu/sh4/clock-sh73180.c b/arch/sh/kernel/cpu/sh4/clock-sh73180.c new file mode 100644 index 00000000000..2fa5cb2ae68 --- /dev/null +++ b/arch/sh/kernel/cpu/sh4/clock-sh73180.c @@ -0,0 +1,81 @@ +/* + * arch/sh/kernel/cpu/sh4/clock-sh73180.c + * + * SH73180 support for the clock framework + * + * Copyright (C) 2005 Paul Mundt + * + * FRQCR parsing hacked out of arch/sh/kernel/time.c + * + * Copyright (C) 1999 Tetsuya Okada & Niibe Yutaka + * Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org> + * Copyright (C) 2002, 2003, 2004 Paul Mundt + * Copyright (C) 2002 M. R. Brown <mrbrown@linux-sh.org> + * + * 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. + */ +#include <linux/init.h> +#include <linux/kernel.h> +#include <asm/clock.h> +#include <asm/freq.h> +#include <asm/io.h> + +/* + * SH73180 uses a common set of divisors, so this is quite simple.. + */ +static int divisors[] = { 1, 2, 3, 4, 6, 8, 12, 16 }; + +static void master_clk_init(struct clk *clk) +{ + clk->rate *= divisors[ctrl_inl(FRQCR) & 0x0007]; +} + +static struct clk_ops sh73180_master_clk_ops = { + .init = master_clk_init, +}; + +static void module_clk_recalc(struct clk *clk) +{ + int idx = (ctrl_inl(FRQCR) & 0x0007); + clk->rate = clk->parent->rate / divisors[idx]; +} + +static struct clk_ops sh73180_module_clk_ops = { + .recalc = module_clk_recalc, +}; + +static void bus_clk_recalc(struct clk *clk) +{ + int idx = (ctrl_inl(FRQCR) >> 12) & 0x0007; + clk->rate = clk->parent->rate / divisors[idx]; +} + +static struct clk_ops sh73180_bus_clk_ops = { + .recalc = bus_clk_recalc, +}; + +static void cpu_clk_recalc(struct clk *clk) +{ + int idx = (ctrl_inl(FRQCR) >> 20) & 0x0007; + clk->rate = clk->parent->rate / divisors[idx]; +} + +static struct clk_ops sh73180_cpu_clk_ops = { + .recalc = cpu_clk_recalc, +}; + +static struct clk_ops *sh73180_clk_ops[] = { + &sh73180_master_clk_ops, + &sh73180_module_clk_ops, + &sh73180_bus_clk_ops, + &sh73180_cpu_clk_ops, +}; + +void __init arch_init_clk_ops(struct clk_ops **ops, int idx) +{ + if (idx < ARRAY_SIZE(sh73180_clk_ops)) + *ops = sh73180_clk_ops[idx]; +} + diff --git a/arch/sh/kernel/cpu/sh4/clock-sh7770.c b/arch/sh/kernel/cpu/sh4/clock-sh7770.c new file mode 100644 index 00000000000..c8694bac647 --- /dev/null +++ b/arch/sh/kernel/cpu/sh4/clock-sh7770.c @@ -0,0 +1,73 @@ +/* + * arch/sh/kernel/cpu/sh4/clock-sh7770.c + * + * SH7770 support for the clock framework + * + * Copyright (C) 2005 Paul Mundt + * + * 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. + */ +#include <linux/init.h> +#include <linux/kernel.h> +#include <asm/clock.h> +#include <asm/freq.h> +#include <asm/io.h> + +static int ifc_divisors[] = { 1, 1, 1, 1, 1, 1, 1, 1 }; +static int bfc_divisors[] = { 1, 1, 1, 1, 1, 8,12, 1 }; +static int pfc_divisors[] = { 1, 8, 1,10,12,16, 1, 1 }; + +static void master_clk_init(struct clk *clk) +{ + clk->rate *= pfc_divisors[(ctrl_inl(FRQCR) >> 28) & 0x000f]; +} + +static struct clk_ops sh7770_master_clk_ops = { + .init = master_clk_init, +}; + +static void module_clk_recalc(struct clk *clk) +{ + int idx = ((ctrl_inl(FRQCR) >> 28) & 0x000f); + clk->rate = clk->parent->rate / pfc_divisors[idx]; +} + +static struct clk_ops sh7770_module_clk_ops = { + .recalc = module_clk_recalc, +}; + +static void bus_clk_recalc(struct clk *clk) +{ + int idx = (ctrl_inl(FRQCR) & 0x000f); + clk->rate = clk->parent->rate / bfc_divisors[idx]; +} + +static struct clk_ops sh7770_bus_clk_ops = { + .recalc = bus_clk_recalc, +}; + +static void cpu_clk_recalc(struct clk *clk) +{ + int idx = ((ctrl_inl(FRQCR) >> 24) & 0x000f); + clk->rate = clk->parent->rate / ifc_divisors[idx]; +} + +static struct clk_ops sh7770_cpu_clk_ops = { + .recalc = cpu_clk_recalc, +}; + +static struct clk_ops *sh7770_clk_ops[] = { + &sh7770_master_clk_ops, + &sh7770_module_clk_ops, + &sh7770_bus_clk_ops, + &sh7770_cpu_clk_ops, +}; + +void __init arch_init_clk_ops(struct clk_ops **ops, int idx) +{ + if (idx < ARRAY_SIZE(sh7770_clk_ops)) + *ops = sh7770_clk_ops[idx]; +} + diff --git a/arch/sh/kernel/cpu/sh4/clock-sh7780.c b/arch/sh/kernel/cpu/sh4/clock-sh7780.c new file mode 100644 index 00000000000..93ad367342c --- /dev/null +++ b/arch/sh/kernel/cpu/sh4/clock-sh7780.c @@ -0,0 +1,126 @@ +/* + * arch/sh/kernel/cpu/sh4/clock-sh7780.c + * + * SH7780 support for the clock framework + * + * Copyright (C) 2005 Paul Mundt + * + * 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. + */ +#include <linux/init.h> +#include <linux/kernel.h> +#include <asm/clock.h> +#include <asm/freq.h> +#include <asm/io.h> + +static int ifc_divisors[] = { 2, 4 }; +static int bfc_divisors[] = { 1, 1, 1, 8, 12, 16, 24, 1 }; +static int pfc_divisors[] = { 1, 24, 24, 1 }; +static int cfc_divisors[] = { 1, 1, 4, 1, 6, 1, 1, 1 }; + +static void master_clk_init(struct clk *clk) +{ + clk->rate *= pfc_divisors[ctrl_inl(FRQCR) & 0x0003]; +} + +static struct clk_ops sh7780_master_clk_ops = { + .init = master_clk_init, +}; + +static void module_clk_recalc(struct clk *clk) +{ + int idx = (ctrl_inl(FRQCR) & 0x0003); + clk->rate = clk->parent->rate / pfc_divisors[idx]; +} + +static struct clk_ops sh7780_module_clk_ops = { + .recalc = module_clk_recalc, +}; + +static void bus_clk_recalc(struct clk *clk) +{ + int idx = ((ctrl_inl(FRQCR) >> 16) & 0x0007); + clk->rate = clk->parent->rate / bfc_divisors[idx]; +} + +static struct clk_ops sh7780_bus_clk_ops = { + .recalc = bus_clk_recalc, +}; + +static void cpu_clk_recalc(struct clk *clk) +{ + int idx = ((ctrl_inl(FRQCR) >> 24) & 0x0001); + clk->rate = clk->parent->rate / ifc_divisors[idx]; +} + +static struct clk_ops sh7780_cpu_clk_ops = { + .recalc = cpu_clk_recalc, +}; + +static struct clk_ops *sh7780_clk_ops[] = { + &sh7780_master_clk_ops, + &sh7780_module_clk_ops, + &sh7780_bus_clk_ops, + &sh7780_cpu_clk_ops, +}; + +void __init arch_init_clk_ops(struct clk_ops **ops, int idx) +{ + if (idx < ARRAY_SIZE(sh7780_clk_ops)) + *ops = sh7780_clk_ops[idx]; +} + +static void shyway_clk_recalc(struct clk *clk) +{ + int idx = ((ctrl_inl(FRQCR) >> 20) & 0x0007); + clk->rate = clk->parent->rate / cfc_divisors[idx]; +} + +static struct clk_ops sh7780_shyway_clk_ops = { + .recalc = shyway_clk_recalc, +}; + +static struct clk sh7780_shyway_clk = { + .name = "shyway_clk", + .flags = CLK_ALWAYS_ENABLED, + .ops = &sh7780_shyway_clk_ops, +}; + +/* + * Additional SH7780-specific on-chip clocks that aren't already part of the + * clock framework + */ +static struct clk *sh7780_onchip_clocks[] = { + &sh7780_shyway_clk, +}; + +static int __init sh7780_clk_init(void) +{ + struct clk *clk = clk_get("master_clk"); + int i; + + for (i = 0; i < ARRAY_SIZE(sh7780_onchip_clocks); i++) { + struct clk *clkp = sh7780_onchip_clocks[i]; + + clkp->parent = clk; + clk_register(clkp); + clk_enable(clkp); + } + + /* + * Now that we have the rest of the clocks registered, we need to + * force the parent clock to propagate so that these clocks will + * automatically figure out their rate. We cheat by handing the + * parent clock its current rate and forcing child propagation. + */ + clk_set_rate(clk, clk_get_rate(clk)); + + clk_put(clk); + + return 0; +} + +arch_initcall(sh7780_clk_init); + diff --git a/arch/sh/kernel/cpu/sh4/irq_intc2.c b/arch/sh/kernel/cpu/sh4/irq_intc2.c deleted file mode 100644 index f6b16ba0193..00000000000 --- a/arch/sh/kernel/cpu/sh4/irq_intc2.c +++ /dev/null @@ -1,222 +0,0 @@ -/* - * linux/arch/sh/kernel/irq_intc2.c - * - * Copyright (C) 2001 David J. Mckay (david.mckay@st.com) - * - * May be copied or modified under the terms of the GNU General Public - * License. See linux/COPYING for more information. - * - * Interrupt handling for INTC2-based IRQ. - * - * These are the "new Hitachi style" interrupts, as present on the - * Hitachi 7751 and the STM ST40 STB1. - */ - -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/irq.h> - -#include <asm/system.h> -#include <asm/io.h> -#include <asm/machvec.h> - - -struct intc2_data { - unsigned char msk_offset; - unsigned char msk_shift; -#ifdef CONFIG_CPU_SUBTYPE_ST40 - int (*clear_irq) (int); -#endif -}; - - -static struct intc2_data intc2_data[NR_INTC2_IRQS]; - -static void enable_intc2_irq(unsigned int irq); -static void disable_intc2_irq(unsigned int irq); - -/* shutdown is same as "disable" */ -#define shutdown_intc2_irq disable_intc2_irq - -static void mask_and_ack_intc2(unsigned int); -static void end_intc2_irq(unsigned int irq); - -static unsigned int startup_intc2_irq(unsigned int irq) -{ - enable_intc2_irq(irq); - return 0; /* never anything pending */ -} - -static struct hw_interrupt_type intc2_irq_type = { - .typename = "INTC2-IRQ", - .startup = startup_intc2_irq, - .shutdown = shutdown_intc2_irq, - .enable = enable_intc2_irq, - .disable = disable_intc2_irq, - .ack = mask_and_ack_intc2, - .end = end_intc2_irq -}; - -static void disable_intc2_irq(unsigned int irq) -{ - int irq_offset = irq - INTC2_FIRST_IRQ; - int msk_shift, msk_offset; - - // Sanity check - if((irq_offset<0) || (irq_offset>=NR_INTC2_IRQS)) - return; - - msk_shift = intc2_data[irq_offset].msk_shift; - msk_offset = intc2_data[irq_offset].msk_offset; - - ctrl_outl(1<<msk_shift, - INTC2_BASE+INTC2_INTMSK_OFFSET+msk_offset); -} - -static void enable_intc2_irq(unsigned int irq) -{ - int irq_offset = irq - INTC2_FIRST_IRQ; - int msk_shift, msk_offset; - - /* Sanity check */ - if((irq_offset<0) || (irq_offset>=NR_INTC2_IRQS)) - return; - - msk_shift = intc2_data[irq_offset].msk_shift; - msk_offset = intc2_data[irq_offset].msk_offset; - - ctrl_outl(1<<msk_shift, - INTC2_BASE+INTC2_INTMSKCLR_OFFSET+msk_offset); -} - -static void mask_and_ack_intc2(unsigned int irq) -{ - disable_intc2_irq(irq); -} - -static void end_intc2_irq(unsigned int irq) -{ - if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) - enable_intc2_irq(irq); - -#ifdef CONFIG_CPU_SUBTYPE_ST40 - if (intc2_data[irq - INTC2_FIRST_IRQ].clear_irq) - intc2_data[irq - INTC2_FIRST_IRQ].clear_irq (irq); -#endif -} - -/* - * Setup an INTC2 style interrupt. - * NOTE: Unlike IPR interrupts, parameters are not shifted by this code, - * allowing the use of the numbers straight out of the datasheet. - * For example: - * PIO1 which is INTPRI00[19,16] and INTMSK00[13] - * would be: ^ ^ ^ ^ - * | | | | - * make_intc2_irq(84, 0, 16, 0, 13); - */ -void make_intc2_irq(unsigned int irq, - unsigned int ipr_offset, unsigned int ipr_shift, - unsigned int msk_offset, unsigned int msk_shift, - unsigned int priority) -{ - int irq_offset = irq - INTC2_FIRST_IRQ; - unsigned int flags; - unsigned long ipr; - - if((irq_offset<0) || (irq_offset>=NR_INTC2_IRQS)) - return; - - disable_irq_nosync(irq); - - /* Fill the data we need */ - intc2_data[irq_offset].msk_offset = msk_offset; - intc2_data[irq_offset].msk_shift = msk_shift; -#ifdef CONFIG_CPU_SUBTYPE_ST40 - intc2_data[irq_offset].clear_irq = NULL; -#endif - - /* Set the priority level */ - local_irq_save(flags); - - ipr=ctrl_inl(INTC2_BASE+INTC2_INTPRI_OFFSET+ipr_offset); - ipr&=~(0xf<<ipr_shift); - ipr|=(priority)<<ipr_shift; - ctrl_outl(ipr, INTC2_BASE+INTC2_INTPRI_OFFSET+ipr_offset); - - local_irq_restore(flags); - - irq_desc[irq].handler=&intc2_irq_type; - - disable_intc2_irq(irq); -} - -#ifdef CONFIG_CPU_SUBTYPE_ST40 - -struct intc2_init { - unsigned short irq; - unsigned char ipr_offset, ipr_shift; - unsigned char msk_offset, msk_shift; -}; - -static struct intc2_init intc2_init_data[] __initdata = { - {64, 0, 0, 0, 0}, /* PCI serr */ - {65, 0, 4, 0, 1}, /* PCI err */ - {66, 0, 4, 0, 2}, /* PCI ad */ - {67, 0, 4, 0, 3}, /* PCI pwd down */ - {72, 0, 8, 0, 5}, /* DMAC INT0 */ - {73, 0, 8, 0, 6}, /* DMAC INT1 */ - {74, 0, 8, 0, 7}, /* DMAC INT2 */ - {75, 0, 8, 0, 8}, /* DMAC INT3 */ - {76, 0, 8, 0, 9}, /* DMAC INT4 */ - {78, 0, 8, 0, 11}, /* DMAC ERR */ - {80, 0, 12, 0, 12}, /* PIO0 */ - {84, 0, 16, 0, 13}, /* PIO1 */ - {88, 0, 20, 0, 14}, /* PIO2 */ - {112, 4, 0, 4, 0}, /* Mailbox */ -#ifdef CONFIG_CPU_SUBTYPE_ST40GX1 - {116, 4, 4, 4, 4}, /* SSC0 */ - {120, 4, 8, 4, 8}, /* IR Blaster */ - {124, 4, 12, 4, 12}, /* USB host */ - {128, 4, 16, 4, 16}, /* Video processor BLITTER */ - {132, 4, 20, 4, 20}, /* UART0 */ - {134, 4, 20, 4, 22}, /* UART2 */ - {136, 4, 24, 4, 24}, /* IO_PIO0 */ - {140, 4, 28, 4, 28}, /* EMPI */ - {144, 8, 0, 8, 0}, /* MAFE */ - {148, 8, 4, 8, 4}, /* PWM */ - {152, 8, 8, 8, 8}, /* SSC1 */ - {156, 8, 12, 8, 12}, /* IO_PIO1 */ - {160, 8, 16, 8, 16}, /* USB target */ - {164, 8, 20, 8, 20}, /* UART1 */ - {168, 8, 24, 8, 24}, /* Teletext */ - {172, 8, 28, 8, 28}, /* VideoSync VTG */ - {173, 8, 28, 8, 29}, /* VideoSync DVP0 */ - {174, 8, 28, 8, 30}, /* VideoSync DVP1 */ -#endif -}; - -void __init init_IRQ_intc2(void) -{ - struct intc2_init *p; - - printk(KERN_ALERT "init_IRQ_intc2\n"); - - for (p = intc2_init_data; - p<intc2_init_data+ARRAY_SIZE(intc2_init_data); - p++) { - make_intc2_irq(p->irq, p->ipr_offset, p->ipr_shift, - p-> msk_offset, p->msk_shift, 13); - } -} - -/* Adds a termination callback to the interrupt */ -void intc2_add_clear_irq(int irq, int (*fn)(int)) -{ - if (irq < INTC2_FIRST_IRQ) - return; - - intc2_data[irq - INTC2_FIRST_IRQ].clear_irq = fn; -} - -#endif /* CONFIG_CPU_SUBTYPE_ST40 */ diff --git a/arch/sh/kernel/io.c b/arch/sh/kernel/io.c index d9932f25993..71c9fde2fd9 100644 --- a/arch/sh/kernel/io.c +++ b/arch/sh/kernel/io.c @@ -2,58 +2,73 @@ * linux/arch/sh/kernel/io.c * * Copyright (C) 2000 Stuart Menefy + * Copyright (C) 2005 Paul Mundt * * Provide real functions which expand to whatever the header file defined. * Also definitions of machine independent IO functions. + * + * 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. */ - -#include <asm/io.h> #include <linux/module.h> +#include <asm/machvec.h> +#include <asm/io.h> /* * Copy data from IO memory space to "real" memory space. * This needs to be optimized. */ -void memcpy_fromio(void * to, unsigned long from, unsigned long count) +void memcpy_fromio(void *to, volatile void __iomem *from, unsigned long count) { char *p = to; while (count) { count--; - *p = readb(from); + *p = readb((void __iomem *)from); p++; from++; } } - +EXPORT_SYMBOL(memcpy_fromio); + /* * Copy data from "real" memory space to IO memory space. * This needs to be optimized. */ -void memcpy_toio(unsigned long to, const void * from, unsigned long count) +void memcpy_toio(volatile void __iomem *to, const void *from, unsigned long count) { const char *p = from; while (count) { count--; - writeb(*p, to); + writeb(*p, (void __iomem *)to); p++; to++; } } - +EXPORT_SYMBOL(memcpy_toio); + /* * "memset" on IO memory space. * This needs to be optimized. */ -void memset_io(unsigned long dst, int c, unsigned long count) +void memset_io(volatile void __iomem *dst, int c, unsigned long count) { while (count) { count--; - writeb(c, dst); + writeb(c, (void __iomem *)dst); dst++; } } - -EXPORT_SYMBOL(memcpy_fromio); -EXPORT_SYMBOL(memcpy_toio); EXPORT_SYMBOL(memset_io); +void __iomem *ioport_map(unsigned long port, unsigned int nr) +{ + return sh_mv.mv_ioport_map(port, nr); +} +EXPORT_SYMBOL(ioport_map); + +void ioport_unmap(void __iomem *addr) +{ + sh_mv.mv_ioport_unmap(addr); +} +EXPORT_SYMBOL(ioport_unmap); diff --git a/arch/sh/kernel/io_generic.c b/arch/sh/kernel/io_generic.c index a911b0149d1..28ec7487de8 100644 --- a/arch/sh/kernel/io_generic.c +++ b/arch/sh/kernel/io_generic.c @@ -3,6 +3,7 @@ * linux/arch/sh/kernel/io_generic.c * * Copyright (C) 2000 Niibe Yutaka + * Copyright (C) 2005 Paul Mundt * * Generic I/O routine. These can be used where a machine specific version * is not required. @@ -10,21 +11,20 @@ * 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. - * */ - +#include <linux/module.h> #include <asm/io.h> #include <asm/machvec.h> -#include <linux/module.h> -#if defined(CONFIG_CPU_SH3) +#ifdef CONFIG_CPU_SH3 +/* SH3 has a PCMCIA bug that needs a dummy read from area 6 for a + * workaround. */ /* I'm not sure SH7709 has this kind of bug */ -#define SH3_PCMCIA_BUG_WORKAROUND 1 -#define DUMMY_READ_AREA6 0xba000000 +#define dummy_read() ctrl_inb(0xba000000) +#else +#define dummy_read() #endif -#define PORT2ADDR(x) (sh_mv.mv_isa_port2addr(x)) - unsigned long generic_io_base; static inline void delay(void) @@ -32,40 +32,40 @@ static inline void delay(void) ctrl_inw(0xa0000000); } -unsigned char generic_inb(unsigned long port) +u8 generic_inb(unsigned long port) { - return *(volatile unsigned char*)PORT2ADDR(port); + return ctrl_inb((unsigned long __force)ioport_map(port, 1)); } -unsigned short generic_inw(unsigned long port) +u16 generic_inw(unsigned long port) { - return *(volatile unsigned short*)PORT2ADDR(port); + return ctrl_inw((unsigned long __force)ioport_map(port, 2)); } -unsigned int generic_inl(unsigned long port) +u32 generic_inl(unsigned long port) { - return *(volatile unsigned long*)PORT2ADDR(port); + return ctrl_inl((unsigned long __force)ioport_map(port, 4)); } -unsigned char generic_inb_p(unsigned long port) +u8 generic_inb_p(unsigned long port) { - unsigned long v = *(volatile unsigned char*)PORT2ADDR(port); + unsigned long v = generic_inb(port); delay(); return v; } -unsigned short generic_inw_p(unsigned long port) +u16 generic_inw_p(unsigned long port) { - unsigned long v = *(volatile unsigned short*)PORT2ADDR(port); + unsigned long v = generic_inw(port); delay(); return v; } -unsigned int generic_inl_p(unsigned long port) +u32 generic_inl_p(unsigned long port) { - unsigned long v = *(volatile unsigned long*)PORT2ADDR(port); + unsigned long v = generic_inl(port); delay(); return v; @@ -77,75 +77,70 @@ unsigned int generic_inl_p(unsigned long port) * convert the port address to real address once. */ -void generic_insb(unsigned long port, void *buffer, unsigned long count) +void generic_insb(unsigned long port, void *dst, unsigned long count) { - volatile unsigned char *port_addr; - unsigned char *buf=buffer; - - port_addr = (volatile unsigned char *)PORT2ADDR(port); + volatile u8 *port_addr; + u8 *buf = dst; - while(count--) - *buf++ = *port_addr; + port_addr = (volatile u8 *)ioport_map(port, 1); + while (count--) + *buf++ = *port_addr; } -void generic_insw(unsigned long port, void *buffer, unsigned long count) +void generic_insw(unsigned long port, void *dst, unsigned long count) { - volatile unsigned short *port_addr; - unsigned short *buf=buffer; + volatile u16 *port_addr; + u16 *buf = dst; - port_addr = (volatile unsigned short *)PORT2ADDR(port); + port_addr = (volatile u16 *)ioport_map(port, 2); + while (count--) + *buf++ = *port_addr; - while(count--) - *buf++ = *port_addr; -#ifdef SH3_PCMCIA_BUG_WORKAROUND - ctrl_inb (DUMMY_READ_AREA6); -#endif + dummy_read(); } -void generic_insl(unsigned long port, void *buffer, unsigned long count) +void generic_insl(unsigned long port, void *dst, unsigned long count) { - volatile unsigned long *port_addr; - unsigned long *buf=buffer; + volatile u32 *port_addr; + u32 *buf = dst; - port_addr = (volatile unsigned long *)PORT2ADDR(port); + port_addr = (volatile u32 *)ioport_map(port, 4); + while (count--) + *buf++ = *port_addr; - while(count--) - *buf++ = *port_addr; -#ifdef SH3_PCMCIA_BUG_WORKAROUND - ctrl_inb (DUMMY_READ_AREA6); -#endif + dummy_read(); } -void generic_outb(unsigned char b, unsigned long port) +void generic_outb(u8 b, unsigned long port) { - *(volatile unsigned char*)PORT2ADDR(port) = b; + ctrl_outb(b, (unsigned long __force)ioport_map(port, 1)); } -void generic_outw(unsigned short b, unsigned long port) +void generic_outw(u16 b, unsigned long port) { - *(volatile unsigned short*)PORT2ADDR(port) = b; + ctrl_outw(b, (unsigned long __force)ioport_map(port, 2)); } -void generic_outl(unsigned int b, unsigned long port) +void generic_outl(u32 b, unsigned long port) { - *(volatile unsigned long*)PORT2ADDR(port) = b; + ctrl_outl(b, (unsigned long __force)ioport_map(port, 4)); } -void generic_outb_p(unsigned char b, unsigned long port) +void generic_outb_p(u8 b, unsigned long port) { - *(volatile unsigned char*)PORT2ADDR(port) = b; + generic_outb(b, port); delay(); } -void generic_outw_p(unsigned short b, unsigned long port) +void generic_outw_p(u16 b, unsigned long port) { - *(volatile unsigned short*)PORT2ADDR(port) = b; + generic_outw(b, port); delay(); } -void generic_outl_p(unsigned int b, unsigned long port) +void generic_outl_p(u32 b, unsigned long port) { - *(volatile unsigned long*)PORT2ADDR(port) = b; + generic_outl(b, port); delay(); } @@ -154,90 +149,77 @@ void generic_outl_p(unsigned int b, unsigned long port) * address. However as the port address doesn't change we only need to * convert the port address to real address once. */ - -void generic_outsb(unsigned long port, const void *buffer, unsigned long count) +void generic_outsb(unsigned long port, const void *src, unsigned long count) { - volatile unsigned char *port_addr; - const unsigned char *buf=buffer; + volatile u8 *port_addr; + const u8 *buf = src; - port_addr = (volatile unsigned char *)PORT2ADDR(port); + port_addr = (volatile u8 __force *)ioport_map(port, 1); - while(count--) - *port_addr = *buf++; + while (count--) + *port_addr = *buf++; } -void generic_outsw(unsigned long port, const void *buffer, unsigned long count) +void generic_outsw(unsigned long port, const void *src, unsigned long count) { - volatile unsigned short *port_addr; - const unsigned short *buf=buffer; + volatile u16 *port_addr; + const u16 *buf = src; - port_addr = (volatile unsigned short *)PORT2ADDR(port); + port_addr = (volatile u16 __force *)ioport_map(port, 2); - while(count--) - *port_addr = *buf++; + while (count--) + *port_addr = *buf++; -#ifdef SH3_PCMCIA_BUG_WORKAROUND - ctrl_inb (DUMMY_READ_AREA6); -#endif + dummy_read(); } -void generic_outsl(unsigned long port, const void *buffer, unsigned long count) +void generic_outsl(unsigned long port, const void *src, unsigned long count) { - volatile unsigned long *port_addr; - const unsigned long *buf=buffer; + volatile u32 *port_addr; + const u32 *buf = src; - port_addr = (volatile unsigned long *)PORT2ADDR(port); + port_addr = (volatile u32 __force *)ioport_map(port, 4); + while (count--) + *port_addr = *buf++; - while(count--) - *port_addr = *buf++; - -#ifdef SH3_PCMCIA_BUG_WORKAROUND - ctrl_inb (DUMMY_READ_AREA6); -#endif -} - -unsigned char generic_readb(unsigned long addr) -{ - return *(volatile unsigned char*)addr; + dummy_read(); } -unsigned short generic_readw(unsigned long addr) +u8 generic_readb(void __iomem *addr) { - return *(volatile unsigned short*)addr; + return ctrl_inb((unsigned long __force)addr); } -unsigned int generic_readl(unsigned long addr) +u16 generic_readw(void __iomem *addr) { - return *(volatile unsigned long*)addr; + return ctrl_inw((unsigned long __force)addr); } -void generic_writeb(unsigned char b, unsigned long addr) +u32 generic_readl(void __iomem *addr) { - *(volatile unsigned char*)addr = b; + return ctrl_inl((unsigned long __force)addr); } -void generic_writew(unsigned short b, unsigned long addr) +void generic_writeb(u8 b, void __iomem *addr) { - *(volatile unsigned short*)addr = b; + ctrl_outb(b, (unsigned long __force)addr); } -void generic_writel(unsigned int b, unsigned long addr) +void generic_writew(u16 b, void __iomem *addr) { - *(volatile unsigned long*)addr = b; + ctrl_outw(b, (unsigned long __force)addr); } -void * generic_ioremap(unsigned long offset, unsigned long size) +void generic_writel(u32 b, void __iomem *addr) { - return (void *) P2SEGADDR(offset); + ctrl_outl(b, (unsigned long __force)addr); } -EXPORT_SYMBOL(generic_ioremap); -void generic_iounmap(void *addr) +void __iomem *generic_ioport_map(unsigned long addr, unsigned int size) { + return (void __iomem *)(addr + generic_io_base); } -EXPORT_SYMBOL(generic_iounmap); -unsigned long generic_isa_port2addr(unsigned long offset) +void generic_ioport_unmap(void __iomem *addr) { - return offset + generic_io_base; } diff --git a/arch/sh/kernel/irq.c b/arch/sh/kernel/irq.c index 54c171225b7..6883c00728c 100644 --- a/arch/sh/kernel/irq.c +++ b/arch/sh/kernel/irq.c @@ -8,38 +8,13 @@ * SuperH version: Copyright (C) 1999 Niibe Yutaka */ -/* - * IRQs are in fact implemented a bit like signal handlers for the kernel. - * Naturally it's not a 1:1 relation, but there are similarities. - */ - -#include <linux/config.h> -#include <linux/module.h> -#include <linux/ptrace.h> -#include <linux/errno.h> -#include <linux/kernel_stat.h> -#include <linux/signal.h> -#include <linux/sched.h> -#include <linux/ioport.h> +#include <linux/irq.h> #include <linux/interrupt.h> -#include <linux/timex.h> -#include <linux/mm.h> -#include <linux/slab.h> -#include <linux/random.h> -#include <linux/smp.h> -#include <linux/smp_lock.h> -#include <linux/init.h> +#include <linux/kernel_stat.h> #include <linux/seq_file.h> -#include <linux/kallsyms.h> -#include <linux/bitops.h> - -#include <asm/system.h> -#include <asm/io.h> -#include <asm/pgalloc.h> -#include <asm/delay.h> #include <asm/irq.h> -#include <linux/irq.h> - +#include <asm/processor.h> +#include <asm/cpu/mmu_context.h> /* * 'what should we do if we get a hw irq event on an illegal vector'. @@ -66,7 +41,7 @@ int show_interrupts(struct seq_file *p, void *v) seq_putc(p, '\n'); } - if (i < ACTUAL_NR_IRQS) { + if (i < NR_IRQS) { spin_lock_irqsave(&irq_desc[i].lock, flags); action = irq_desc[i].action; if (!action) @@ -86,19 +61,32 @@ unlock: } #endif + asmlinkage int do_IRQ(unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7, struct pt_regs regs) -{ - int irq; +{ + int irq = r4; irq_enter(); - asm volatile("stc r2_bank, %0\n\t" - "shlr2 %0\n\t" - "shlr2 %0\n\t" - "shlr %0\n\t" - "add #-16, %0\n\t" - :"=z" (irq)); + +#ifdef CONFIG_CPU_HAS_INTEVT + __asm__ __volatile__ ( +#ifdef CONFIG_CPU_HAS_SR_RB + "stc r2_bank, %0\n\t" +#else + "mov.l @%1, %0\n\t" +#endif + "shlr2 %0\n\t" + "shlr2 %0\n\t" + "shlr %0\n\t" + "add #-16, %0\n\t" + : "=z" (irq), "=r" (r4) + : "1" (INTEVT) + : "memory" + ); +#endif + irq = irq_demux(irq); __do_IRQ(irq, ®s); irq_exit(); diff --git a/arch/sh/kernel/machine_kexec.c b/arch/sh/kernel/machine_kexec.c new file mode 100644 index 00000000000..43546525f28 --- /dev/null +++ b/arch/sh/kernel/machine_kexec.c @@ -0,0 +1,112 @@ +/* + * machine_kexec.c - handle transition of Linux booting another kernel + * Copyright (C) 2002-2003 Eric Biederman <ebiederm@xmission.com> + * + * GameCube/ppc32 port Copyright (C) 2004 Albert Herranz + * LANDISK/sh4 supported by kogiidena + * + * This source code is licensed under the GNU General Public License, + * Version 2. See the file COPYING for more details. + */ + +#include <linux/mm.h> +#include <linux/kexec.h> +#include <linux/delay.h> +#include <linux/reboot.h> +#include <asm/pgtable.h> +#include <asm/pgalloc.h> +#include <asm/mmu_context.h> +#include <asm/io.h> +#include <asm/cacheflush.h> + +typedef NORET_TYPE void (*relocate_new_kernel_t)( + unsigned long indirection_page, + unsigned long reboot_code_buffer, + unsigned long start_address, + unsigned long vbr_reg) ATTRIB_NORET; + +const extern unsigned char relocate_new_kernel[]; +const extern unsigned int relocate_new_kernel_size; +extern void *gdb_vbr_vector; + +/* + * Provide a dummy crash_notes definition while crash dump arrives to ppc. + * This prevents breakage of crash_notes attribute in kernel/ksysfs.c. + */ +void *crash_notes = NULL; + +void machine_shutdown(void) +{ +} + +void machine_crash_shutdown(struct pt_regs *regs) +{ +} + +/* + * Do what every setup is needed on image and the + * reboot code buffer to allow us to avoid allocations + * later. + */ +int machine_kexec_prepare(struct kimage *image) +{ + return 0; +} + +void machine_kexec_cleanup(struct kimage *image) +{ +} + +static void kexec_info(struct kimage *image) +{ + int i; + printk("kexec information\n"); + for (i = 0; i < image->nr_segments; i++) { + printk(" segment[%d]: 0x%08x - 0x%08x (0x%08x)\n", + i, + (unsigned int)image->segment[i].mem, + (unsigned int)image->segment[i].mem + image->segment[i].memsz, + (unsigned int)image->segment[i].memsz); + } + printk(" start : 0x%08x\n\n", (unsigned int)image->start); +} + + +/* + * Do not allocate memory (or fail in any way) in machine_kexec(). + * We are past the point of no return, committed to rebooting now. + */ +NORET_TYPE void machine_kexec(struct kimage *image) +{ + + unsigned long page_list; + unsigned long reboot_code_buffer; + unsigned long vbr_reg; + relocate_new_kernel_t rnk; + +#if defined(CONFIG_SH_STANDARD_BIOS) + vbr_reg = ((unsigned long )gdb_vbr_vector) - 0x100; +#else + vbr_reg = 0x80000000; // dummy +#endif + /* Interrupts aren't acceptable while we reboot */ + local_irq_disable(); + + page_list = image->head; + + /* we need both effective and real address here */ + reboot_code_buffer = + (unsigned long)page_address(image->control_code_page); + + /* copy our kernel relocation code to the control code page */ + memcpy((void *)reboot_code_buffer, relocate_new_kernel, + relocate_new_kernel_size); + + kexec_info(image); + flush_cache_all(); + + /* now call it */ + rnk = (relocate_new_kernel_t) reboot_code_buffer; + (*rnk)(page_list, reboot_code_buffer, image->start, vbr_reg); +} + diff --git a/arch/sh/kernel/process.c b/arch/sh/kernel/process.c index aac15e42d03..a4dc2b532e1 100644 --- a/arch/sh/kernel/process.c +++ b/arch/sh/kernel/process.c @@ -71,6 +71,16 @@ void cpu_idle(void) void machine_restart(char * __unused) { + +#ifdef CONFIG_KEXEC + struct kimage *image; + image = xchg(&kexec_image, 0); + if (image) { + machine_shutdown(); + machine_kexec(image); + } +#endif + /* SR.BL=1 and invoke address error to let CPU reset (manual reset) */ asm volatile("ldc %0, sr\n\t" "mov.l @%1, %0" : : "r" (0x10000000), "r" (0x80000001)); diff --git a/arch/sh/kernel/relocate_kernel.S b/arch/sh/kernel/relocate_kernel.S new file mode 100644 index 00000000000..b0695cffec6 --- /dev/null +++ b/arch/sh/kernel/relocate_kernel.S @@ -0,0 +1,102 @@ +/* + * relocate_kernel.S - put the kernel image in place to boot + * 2005.9.17 kogiidena@eggplant.ddo.jp + * + * LANDISK/sh4 is supported. Maybe, SH archtecture works well. + * + * This source code is licensed under the GNU General Public License, + * Version 2. See the file COPYING for more details. + */ + +#include <linux/config.h> +#include <linux/linkage.h> + +#define PAGE_SIZE 4096 /* must be same value as in <asm/page.h> */ + + + .globl relocate_new_kernel +relocate_new_kernel: + /* r4 = indirection_page */ + /* r5 = reboot_code_buffer */ + /* r6 = start_address */ + /* r7 = vbr_reg */ + + mov.l 10f,r8 /* 4096 */ + mov.l 11f,r9 /* 0xa0000000 */ + + /* stack setting */ + add r8,r5 + mov r5,r15 + + bra 1f + mov r4,r0 /* cmd = indirection_page */ +0: + mov.l @r4+,r0 /* cmd = *ind++ */ + +1: /* addr = (cmd | 0xa0000000) & 0xfffffff0 */ + mov r0,r2 + or r9,r2 + mov #-16,r1 + and r1,r2 + + /* if(cmd & IND_DESTINATION) dst = addr */ + tst #1,r0 + bt 2f + bra 0b + mov r2,r5 + +2: /* else if(cmd & IND_INDIRECTION) ind = addr */ + tst #2,r0 + bt 3f + bra 0b + mov r2,r4 + +3: /* else if(cmd & IND_DONE) goto 6 */ + tst #4,r0 + bt 4f + bra 6f + nop + +4: /* else if(cmd & IND_SOURCE) memcpy(dst,addr,PAGE_SIZE) */ + tst #8,r0 + bt 0b + + mov r8,r3 + shlr2 r3 + shlr2 r3 +5: + dt r3 + mov.l @r2+,r1 /* 16n+0 */ + mov.l r1,@r5 + add #4,r5 + mov.l @r2+,r1 /* 16n+4 */ + mov.l r1,@r5 + add #4,r5 + mov.l @r2+,r1 /* 16n+8 */ + mov.l r1,@r5 + add #4,r5 + mov.l @r2+,r1 /* 16n+12 */ + mov.l r1,@r5 + add #4,r5 + bf 5b + + bra 0b + nop +6: +#ifdef CONFIG_SH_STANDARD_BIOS + ldc r7, vbr +#endif + jmp @r6 + nop + + .align 2 +10: + .long PAGE_SIZE +11: + .long 0xa0000000 + +relocate_new_kernel_end: + + .globl relocate_new_kernel_size +relocate_new_kernel_size: + .long relocate_new_kernel_end - relocate_new_kernel diff --git a/arch/sh/kernel/time.c b/arch/sh/kernel/time.c index 671b876416b..314a275c04e 100644 --- a/arch/sh/kernel/time.c +++ b/arch/sh/kernel/time.c @@ -3,7 +3,7 @@ * * Copyright (C) 1999 Tetsuya Okada & Niibe Yutaka * Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org> - * Copyright (C) 2002, 2003, 2004 Paul Mundt + * Copyright (C) 2002, 2003, 2004, 2005 Paul Mundt * Copyright (C) 2002 M. R. Brown <mrbrown@linux-sh.org> * * Some code taken from i386 version. @@ -11,50 +11,21 @@ */ #include <linux/config.h> -#include <linux/errno.h> -#include <linux/module.h> -#include <linux/sched.h> #include <linux/kernel.h> -#include <linux/param.h> -#include <linux/string.h> -#include <linux/mm.h> -#include <linux/interrupt.h> -#include <linux/time.h> -#include <linux/delay.h> +#include <linux/module.h> #include <linux/init.h> -#include <linux/smp.h> #include <linux/profile.h> - -#include <asm/processor.h> -#include <asm/uaccess.h> -#include <asm/io.h> -#include <asm/irq.h> -#include <asm/delay.h> -#include <asm/machvec.h> +#include <asm/clock.h> #include <asm/rtc.h> -#include <asm/freq.h> -#include <asm/cpu/timer.h> -#ifdef CONFIG_SH_KGDB +#include <asm/timer.h> #include <asm/kgdb.h> -#endif - -#include <linux/timex.h> -#include <linux/irq.h> - -#define TMU_TOCR_INIT 0x00 -#define TMU0_TCR_INIT 0x0020 -#define TMU_TSTR_INIT 1 - -#define TMU0_TCR_CALIB 0x0000 - -#ifdef CONFIG_CPU_SUBTYPE_ST40STB1 -#define CLOCKGEN_MEMCLKCR 0xbb040038 -#define MEMCLKCR_RATIO_MASK 0x7 -#endif /* CONFIG_CPU_SUBTYPE_ST40STB1 */ extern unsigned long wall_jiffies; -#define TICK_SIZE (tick_nsec / 1000) -DEFINE_SPINLOCK(tmu0_lock); +struct sys_timer *sys_timer; + +/* Move this somewhere more sensible.. */ +DEFINE_SPINLOCK(rtc_lock); +EXPORT_SYMBOL(rtc_lock); /* XXX: Can we initialize this in a routine somewhere? Dreamcast doesn't want * these routines anywhere... */ @@ -66,98 +37,14 @@ void (*rtc_get_time)(struct timespec *); int (*rtc_set_time)(const time_t); #endif -#if defined(CONFIG_CPU_SUBTYPE_SH7300) -static int md_table[] = { 1, 2, 3, 4, 6, 8, 12 }; -#endif -#if defined(CONFIG_CPU_SH3) -static int stc_multipliers[] = { 1, 2, 3, 4, 6, 1, 1, 1 }; -static int stc_values[] = { 0, 1, 4, 2, 5, 0, 0, 0 }; -#define bfc_divisors stc_multipliers -#define bfc_values stc_values -static int ifc_divisors[] = { 1, 2, 3, 4, 1, 1, 1, 1 }; -static int ifc_values[] = { 0, 1, 4, 2, 0, 0, 0, 0 }; -static int pfc_divisors[] = { 1, 2, 3, 4, 6, 1, 1, 1 }; -static int pfc_values[] = { 0, 1, 4, 2, 5, 0, 0, 0 }; -#elif defined(CONFIG_CPU_SH4) -#if defined(CONFIG_CPU_SUBTYPE_SH73180) -static int ifc_divisors[] = { 1, 2, 3, 4, 6, 8, 12, 16 }; -static int ifc_values[] = { 0, 1, 2, 3, 4, 5, 6, 7 }; -#define bfc_divisors ifc_divisors /* Same */ -#define bfc_values ifc_values -#define pfc_divisors ifc_divisors /* Same */ -#define pfc_values ifc_values -#else -static int ifc_divisors[] = { 1, 2, 3, 4, 6, 8, 1, 1 }; -static int ifc_values[] = { 0, 1, 2, 3, 0, 4, 0, 5 }; -#define bfc_divisors ifc_divisors /* Same */ -#define bfc_values ifc_values -static int pfc_divisors[] = { 2, 3, 4, 6, 8, 2, 2, 2 }; -static int pfc_values[] = { 0, 0, 1, 2, 0, 3, 0, 4 }; -#endif -#else -#error "Unknown ifc/bfc/pfc/stc values for this processor" -#endif - /* * Scheduler clock - returns current time in nanosec units. */ -unsigned long long sched_clock(void) +unsigned long long __attribute__ ((weak)) sched_clock(void) { return (unsigned long long)jiffies * (1000000000 / HZ); } -static unsigned long do_gettimeoffset(void) -{ - int count; - unsigned long flags; - - static int count_p = 0x7fffffff; /* for the first call after boot */ - static unsigned long jiffies_p = 0; - - /* - * cache volatile jiffies temporarily; we have IRQs turned off. - */ - unsigned long jiffies_t; - - spin_lock_irqsave(&tmu0_lock, flags); - /* timer count may underflow right here */ - count = ctrl_inl(TMU0_TCNT); /* read the latched count */ - - jiffies_t = jiffies; - - /* - * avoiding timer inconsistencies (they are rare, but they happen)... - * there is one kind of problem that must be avoided here: - * 1. the timer counter underflows - */ - - if( jiffies_t == jiffies_p ) { - if( count > count_p ) { - /* the nutcase */ - - if(ctrl_inw(TMU0_TCR) & 0x100) { /* Check UNF bit */ - /* - * We cannot detect lost timer interrupts ... - * well, that's why we call them lost, don't we? :) - * [hmm, on the Pentium and Alpha we can ... sort of] - */ - count -= LATCH; - } else { - printk("do_slow_gettimeoffset(): hardware timer problem?\n"); - } - } - } else - jiffies_p = jiffies_t; - - count_p = count; - spin_unlock_irqrestore(&tmu0_lock, flags); - - count = ((LATCH-1) - count) * TICK_SIZE; - count = (count + LATCH/2) / LATCH; - - return count; -} - void do_gettimeofday(struct timeval *tv) { unsigned long seq; @@ -166,7 +53,7 @@ void do_gettimeofday(struct timeval *tv) do { seq = read_seqbegin(&xtime_lock); - usec = do_gettimeoffset(); + usec = get_timer_offset(); lost = jiffies - wall_jiffies; if (lost) @@ -202,7 +89,7 @@ int do_settimeofday(struct timespec *tv) * wall time. Discover what correction gettimeofday() would have * made, and then undo it! */ - nsec -= 1000 * (do_gettimeoffset() + + nsec -= 1000 * (get_timer_offset() + (jiffies - wall_jiffies) * (1000000 / HZ)); wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec); @@ -224,10 +111,10 @@ EXPORT_SYMBOL(do_settimeofday); static long last_rtc_update; /* - * timer_interrupt() needs to keep up the real-time clock, + * handle_timer_tick() needs to keep up the real-time clock, * as well as call the "do_timer()" routine every clocktick */ -static inline void do_timer_interrupt(int irq, struct pt_regs *regs) +void handle_timer_tick(struct pt_regs *regs) { do_timer(regs); #ifndef CONFIG_SMP @@ -252,337 +139,35 @@ static inline void do_timer_interrupt(int irq, struct pt_regs *regs) if (rtc_set_time(xtime.tv_sec) == 0) last_rtc_update = xtime.tv_sec; else - last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */ + /* do it again in 60s */ + last_rtc_update = xtime.tv_sec - 600; } } -/* - * This is the same as the above, except we _also_ save the current - * Time Stamp Counter value at the time of the timer interrupt, so that - * we later on can estimate the time of day more exactly. - */ -static irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) -{ - unsigned long timer_status; - - /* Clear UNF bit */ - timer_status = ctrl_inw(TMU0_TCR); - timer_status &= ~0x100; - ctrl_outw(timer_status, TMU0_TCR); - - /* - * Here we are in the timer irq handler. We just have irqs locally - * disabled but we don't know if the timer_bh is running on the other - * CPU. We need to avoid to SMP race with it. NOTE: we don' t need - * the irq version of write_lock because as just said we have irq - * locally disabled. -arca - */ - write_seqlock(&xtime_lock); - do_timer_interrupt(irq, regs); - write_sequnlock(&xtime_lock); - - return IRQ_HANDLED; -} - -/* - * Hah! We'll see if this works (switching from usecs to nsecs). - */ -static unsigned int __init get_timer_frequency(void) -{ - u32 freq; - struct timespec ts1, ts2; - unsigned long diff_nsec; - unsigned long factor; - - /* Setup the timer: We don't want to generate interrupts, just - * have it count down at its natural rate. - */ - ctrl_outb(0, TMU_TSTR); -#if !defined(CONFIG_CPU_SUBTYPE_SH7300) - ctrl_outb(TMU_TOCR_INIT, TMU_TOCR); -#endif - ctrl_outw(TMU0_TCR_CALIB, TMU0_TCR); - ctrl_outl(0xffffffff, TMU0_TCOR); - ctrl_outl(0xffffffff, TMU0_TCNT); - - rtc_get_time(&ts2); - - do { - rtc_get_time(&ts1); - } while (ts1.tv_nsec == ts2.tv_nsec && ts1.tv_sec == ts2.tv_sec); - - /* actually start the timer */ - ctrl_outb(TMU_TSTR_INIT, TMU_TSTR); - - do { - rtc_get_time(&ts2); - } while (ts1.tv_nsec == ts2.tv_nsec && ts1.tv_sec == ts2.tv_sec); - - freq = 0xffffffff - ctrl_inl(TMU0_TCNT); - if (ts2.tv_nsec < ts1.tv_nsec) { - ts2.tv_nsec += 1000000000; - ts2.tv_sec--; - } - - diff_nsec = (ts2.tv_sec - ts1.tv_sec) * 1000000000 + (ts2.tv_nsec - ts1.tv_nsec); - - /* this should work well if the RTC has a precision of n Hz, where - * n is an integer. I don't think we have to worry about the other - * cases. */ - factor = (1000000000 + diff_nsec/2) / diff_nsec; - - if (factor * diff_nsec > 1100000000 || - factor * diff_nsec < 900000000) - panic("weird RTC (diff_nsec %ld)", diff_nsec); - - return freq * factor; -} - -void (*board_time_init)(void); -void (*board_timer_setup)(struct irqaction *irq); - -static unsigned int sh_pclk_freq __initdata = CONFIG_SH_PCLK_FREQ; - -static int __init sh_pclk_setup(char *str) -{ - unsigned int freq; - - if (get_option(&str, &freq)) - sh_pclk_freq = freq; - - return 1; -} -__setup("sh_pclk=", sh_pclk_setup); - -static struct irqaction irq0 = { timer_interrupt, SA_INTERRUPT, CPU_MASK_NONE, "timer", NULL, NULL}; - -void get_current_frequency_divisors(unsigned int *ifc, unsigned int *bfc, unsigned int *pfc) -{ - unsigned int frqcr = ctrl_inw(FRQCR); - -#if defined(CONFIG_CPU_SH3) -#if defined(CONFIG_CPU_SUBTYPE_SH7300) - *ifc = md_table[((frqcr & 0x0070) >> 4)]; - *bfc = md_table[((frqcr & 0x0700) >> 8)]; - *pfc = md_table[frqcr & 0x0007]; -#elif defined(CONFIG_CPU_SUBTYPE_SH7705) - *bfc = stc_multipliers[(frqcr & 0x0300) >> 8]; - *ifc = ifc_divisors[(frqcr & 0x0030) >> 4]; - *pfc = pfc_divisors[frqcr & 0x0003]; -#else - unsigned int tmp; - - tmp = (frqcr & 0x8000) >> 13; - tmp |= (frqcr & 0x0030) >> 4; - *bfc = stc_multipliers[tmp]; - tmp = (frqcr & 0x4000) >> 12; - tmp |= (frqcr & 0x000c) >> 2; - *ifc = ifc_divisors[tmp]; - tmp = (frqcr & 0x2000) >> 11; - tmp |= frqcr & 0x0003; - *pfc = pfc_divisors[tmp]; -#endif -#elif defined(CONFIG_CPU_SH4) -#if defined(CONFIG_CPU_SUBTYPE_SH73180) - *ifc = ifc_divisors[(frqcr>> 20) & 0x0007]; - *bfc = bfc_divisors[(frqcr>> 12) & 0x0007]; - *pfc = pfc_divisors[frqcr & 0x0007]; -#else - *ifc = ifc_divisors[(frqcr >> 6) & 0x0007]; - *bfc = bfc_divisors[(frqcr >> 3) & 0x0007]; - *pfc = pfc_divisors[frqcr & 0x0007]; -#endif -#endif -} - -/* - * This bit of ugliness builds up accessor routines to get at both - * the divisors and the physical values. - */ -#define _FREQ_TABLE(x) \ - unsigned int get_##x##_divisor(unsigned int value) \ - { return x##_divisors[value]; } \ - \ - unsigned int get_##x##_value(unsigned int divisor) \ - { return x##_values[(divisor - 1)]; } - -_FREQ_TABLE(ifc); -_FREQ_TABLE(bfc); -_FREQ_TABLE(pfc); - -#ifdef CONFIG_CPU_SUBTYPE_ST40STB1 - -/* - * The ST40 divisors are totally different so we set the cpu data - * clocks using a different algorithm - * - * I've just plugged this from the 2.4 code - * - Alex Bennee <kernel-hacker@bennee.com> - */ -#define CCN_PVR_CHIP_SHIFT 24 -#define CCN_PVR_CHIP_MASK 0xff -#define CCN_PVR_CHIP_ST40STB1 0x4 - - -struct frqcr_data { - unsigned short frqcr; - - struct { - unsigned char multiplier; - unsigned char divisor; - } factor[3]; -}; - -static struct frqcr_data st40_frqcr_table[] = { - { 0x000, {{1,1}, {1,1}, {1,2}}}, - { 0x002, {{1,1}, {1,1}, {1,4}}}, - { 0x004, {{1,1}, {1,1}, {1,8}}}, - { 0x008, {{1,1}, {1,2}, {1,2}}}, - { 0x00A, {{1,1}, {1,2}, {1,4}}}, - { 0x00C, {{1,1}, {1,2}, {1,8}}}, - { 0x011, {{1,1}, {2,3}, {1,6}}}, - { 0x013, {{1,1}, {2,3}, {1,3}}}, - { 0x01A, {{1,1}, {1,2}, {1,4}}}, - { 0x01C, {{1,1}, {1,2}, {1,8}}}, - { 0x023, {{1,1}, {2,3}, {1,3}}}, - { 0x02C, {{1,1}, {1,2}, {1,8}}}, - { 0x048, {{1,2}, {1,2}, {1,4}}}, - { 0x04A, {{1,2}, {1,2}, {1,6}}}, - { 0x04C, {{1,2}, {1,2}, {1,8}}}, - { 0x05A, {{1,2}, {1,3}, {1,6}}}, - { 0x05C, {{1,2}, {1,3}, {1,6}}}, - { 0x063, {{1,2}, {1,4}, {1,4}}}, - { 0x06C, {{1,2}, {1,4}, {1,8}}}, - { 0x091, {{1,3}, {1,3}, {1,6}}}, - { 0x093, {{1,3}, {1,3}, {1,6}}}, - { 0x0A3, {{1,3}, {1,6}, {1,6}}}, - { 0x0DA, {{1,4}, {1,4}, {1,8}}}, - { 0x0DC, {{1,4}, {1,4}, {1,8}}}, - { 0x0EC, {{1,4}, {1,8}, {1,8}}}, - { 0x123, {{1,4}, {1,4}, {1,8}}}, - { 0x16C, {{1,4}, {1,8}, {1,8}}}, +static struct sysdev_class timer_sysclass = { + set_kset_name("timer"), }; -struct memclk_data { - unsigned char multiplier; - unsigned char divisor; -}; - -static struct memclk_data st40_memclk_table[8] = { - {1,1}, // 000 - {1,2}, // 001 - {1,3}, // 010 - {2,3}, // 011 - {1,4}, // 100 - {1,6}, // 101 - {1,8}, // 110 - {1,8} // 111 -}; - -static void st40_specific_time_init(unsigned int module_clock, unsigned short frqcr) +static int __init timer_init_sysfs(void) { - unsigned int cpu_clock, master_clock, bus_clock, memory_clock; - struct frqcr_data *d; - int a; - unsigned long memclkcr; - struct memclk_data *e; + int ret = sysdev_class_register(&timer_sysclass); + if (ret != 0) + return ret; - for (a = 0; a < ARRAY_SIZE(st40_frqcr_table); a++) { - d = &st40_frqcr_table[a]; - - if (d->frqcr == (frqcr & 0x1ff)) - break; - } + sys_timer->dev.cls = &timer_sysclass; + return sysdev_register(&sys_timer->dev); +} - if (a == ARRAY_SIZE(st40_frqcr_table)) { - d = st40_frqcr_table; +device_initcall(timer_init_sysfs); - printk("ERROR: Unrecognised FRQCR value (0x%x), " - "using default multipliers\n", frqcr); - } - - memclkcr = ctrl_inl(CLOCKGEN_MEMCLKCR); - e = &st40_memclk_table[memclkcr & MEMCLKCR_RATIO_MASK]; - - printk(KERN_INFO "Clock multipliers: CPU: %d/%d Bus: %d/%d " - "Mem: %d/%d Periph: %d/%d\n", - d->factor[0].multiplier, d->factor[0].divisor, - d->factor[1].multiplier, d->factor[1].divisor, - e->multiplier, e->divisor, - d->factor[2].multiplier, d->factor[2].divisor); - - master_clock = module_clock * d->factor[2].divisor - / d->factor[2].multiplier; - bus_clock = master_clock * d->factor[1].multiplier - / d->factor[1].divisor; - memory_clock = master_clock * e->multiplier - / e->divisor; - cpu_clock = master_clock * d->factor[0].multiplier - / d->factor[0].divisor; - - current_cpu_data.cpu_clock = cpu_clock; - current_cpu_data.master_clock = master_clock; - current_cpu_data.bus_clock = bus_clock; - current_cpu_data.memory_clock = memory_clock; - current_cpu_data.module_clock = module_clock; -} -#endif +void (*board_time_init)(void); void __init time_init(void) { - unsigned int timer_freq = 0; - unsigned int ifc, pfc, bfc; - unsigned long interval; -#ifdef CONFIG_CPU_SUBTYPE_ST40STB1 - unsigned long pvr; - unsigned short frqcr; -#endif - if (board_time_init) board_time_init(); - /* - * If we don't have an RTC (such as with the SH7300), don't attempt to - * probe the timer frequency. Rely on an either hardcoded peripheral - * clock value, or on the sh_pclk command line option. Note that we - * still need to have CONFIG_SH_PCLK_FREQ set in order for things like - * CLOCK_TICK_RATE to be sane. - */ - current_cpu_data.module_clock = sh_pclk_freq; - -#ifdef CONFIG_SH_PCLK_CALC - /* XXX: Switch this over to a more generic test. */ - { - unsigned int freq; - - /* - * If we've specified a peripheral clock frequency, and we have - * an RTC, compare it against the autodetected value. Complain - * if there's a mismatch. - */ - timer_freq = get_timer_frequency(); - freq = timer_freq * 4; - - if (sh_pclk_freq && (sh_pclk_freq/100*99 > freq || sh_pclk_freq/100*101 < freq)) { - printk(KERN_NOTICE "Calculated peripheral clock value " - "%d differs from sh_pclk value %d, fixing..\n", - freq, sh_pclk_freq); - current_cpu_data.module_clock = freq; - } - } -#endif - -#ifdef CONFIG_CPU_SUBTYPE_ST40STB1 - /* XXX: Update ST40 code to use board_time_init() */ - pvr = ctrl_inl(CCN_PVR); - frqcr = ctrl_inw(FRQCR); - printk("time.c ST40 Probe: PVR %08lx, FRQCR %04hx\n", pvr, frqcr); - - if (((pvr >> CCN_PVR_CHIP_SHIFT) & CCN_PVR_CHIP_MASK) == CCN_PVR_CHIP_ST40STB1) - st40_specific_time_init(current_cpu_data.module_clock, frqcr); - else -#endif - get_current_frequency_divisors(&ifc, &bfc, &pfc); + clk_init(); if (rtc_get_time) { rtc_get_time(&xtime); @@ -594,51 +179,12 @@ void __init time_init(void) set_normalized_timespec(&wall_to_monotonic, -xtime.tv_sec, -xtime.tv_nsec); - if (board_timer_setup) { - board_timer_setup(&irq0); - } else { - setup_irq(TIMER_IRQ, &irq0); - } - /* - * for ST40 chips the current_cpu_data should already be set - * so not having valid pfc/bfc/ifc shouldn't be a problem + * Find the timer to use as the system timer, it will be + * initialized for us. */ - if (!current_cpu_data.master_clock) - current_cpu_data.master_clock = current_cpu_data.module_clock * pfc; - if (!current_cpu_data.bus_clock) - current_cpu_data.bus_clock = current_cpu_data.master_clock / bfc; - if (!current_cpu_data.cpu_clock) - current_cpu_data.cpu_clock = current_cpu_data.master_clock / ifc; - - printk("CPU clock: %d.%02dMHz\n", - (current_cpu_data.cpu_clock / 1000000), - (current_cpu_data.cpu_clock % 1000000)/10000); - printk("Bus clock: %d.%02dMHz\n", - (current_cpu_data.bus_clock / 1000000), - (current_cpu_data.bus_clock % 1000000)/10000); -#ifdef CONFIG_CPU_SUBTYPE_ST40STB1 - printk("Memory clock: %d.%02dMHz\n", - (current_cpu_data.memory_clock / 1000000), - (current_cpu_data.memory_clock % 1000000)/10000); -#endif - printk("Module clock: %d.%02dMHz\n", - (current_cpu_data.module_clock / 1000000), - (current_cpu_data.module_clock % 1000000)/10000); - - interval = (current_cpu_data.module_clock/4 + HZ/2) / HZ; - - printk("Interval = %ld\n", interval); - - /* Start TMU0 */ - ctrl_outb(0, TMU_TSTR); -#if !defined(CONFIG_CPU_SUBTYPE_SH7300) - ctrl_outb(TMU_TOCR_INIT, TMU_TOCR); -#endif - ctrl_outw(TMU0_TCR_INIT, TMU0_TCR); - ctrl_outl(interval, TMU0_TCOR); - ctrl_outl(interval, TMU0_TCNT); - ctrl_outb(TMU_TSTR_INIT, TMU_TSTR); + sys_timer = get_sys_timer(); + printk(KERN_INFO "Using %s for system timer\n", sys_timer->name); #if defined(CONFIG_SH_KGDB) /* diff --git a/arch/sh/kernel/timers/Makefile b/arch/sh/kernel/timers/Makefile new file mode 100644 index 00000000000..151a6a304ce --- /dev/null +++ b/arch/sh/kernel/timers/Makefile @@ -0,0 +1,8 @@ +# +# Makefile for the various Linux/SuperH timers +# + +obj-y := timer.o + +obj-$(CONFIG_SH_TMU) += timer-tmu.o + diff --git a/arch/sh/kernel/timers/timer-tmu.c b/arch/sh/kernel/timers/timer-tmu.c new file mode 100644 index 00000000000..96a64cb1310 --- /dev/null +++ b/arch/sh/kernel/timers/timer-tmu.c @@ -0,0 +1,229 @@ +/* + * arch/sh/kernel/timers/timer-tmu.c - TMU Timer Support + * + * Copyright (C) 2005 Paul Mundt + * + * TMU handling code hacked out of arch/sh/kernel/time.c + * + * Copyright (C) 1999 Tetsuya Okada & Niibe Yutaka + * Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org> + * Copyright (C) 2002, 2003, 2004 Paul Mundt + * Copyright (C) 2002 M. R. Brown <mrbrown@linux-sh.org> + * + * 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. + */ +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/interrupt.h> +#include <linux/spinlock.h> +#include <linux/seqlock.h> +#include <asm/timer.h> +#include <asm/rtc.h> +#include <asm/io.h> +#include <asm/irq.h> +#include <asm/clock.h> + +#define TMU_TOCR_INIT 0x00 +#define TMU0_TCR_INIT 0x0020 +#define TMU_TSTR_INIT 1 + +#define TMU0_TCR_CALIB 0x0000 + +static DEFINE_SPINLOCK(tmu0_lock); + +static unsigned long tmu_timer_get_offset(void) +{ + int count; + unsigned long flags; + + static int count_p = 0x7fffffff; /* for the first call after boot */ + static unsigned long jiffies_p = 0; + + /* + * cache volatile jiffies temporarily; we have IRQs turned off. + */ + unsigned long jiffies_t; + + spin_lock_irqsave(&tmu0_lock, flags); + /* timer count may underflow right here */ + count = ctrl_inl(TMU0_TCNT); /* read the latched count */ + + jiffies_t = jiffies; + + /* + * avoiding timer inconsistencies (they are rare, but they happen)... + * there is one kind of problem that must be avoided here: + * 1. the timer counter underflows + */ + + if (jiffies_t == jiffies_p) { + if (count > count_p) { + /* the nutcase */ + if (ctrl_inw(TMU0_TCR) & 0x100) { /* Check UNF bit */ + count -= LATCH; + } else { + printk("%s (): hardware timer problem?\n", + __FUNCTION__); + } + } + } else + jiffies_p = jiffies_t; + + count_p = count; + spin_unlock_irqrestore(&tmu0_lock, flags); + + count = ((LATCH-1) - count) * TICK_SIZE; + count = (count + LATCH/2) / LATCH; + + return count; +} + +static irqreturn_t tmu_timer_interrupt(int irq, void *dev_id, + struct pt_regs *regs) +{ + unsigned long timer_status; + + /* Clear UNF bit */ + timer_status = ctrl_inw(TMU0_TCR); + timer_status &= ~0x100; + ctrl_outw(timer_status, TMU0_TCR); + + /* + * Here we are in the timer irq handler. We just have irqs locally + * disabled but we don't know if the timer_bh is running on the other + * CPU. We need to avoid to SMP race with it. NOTE: we don' t need + * the irq version of write_lock because as just said we have irq + * locally disabled. -arca + */ + write_seqlock(&xtime_lock); + handle_timer_tick(regs); + write_sequnlock(&xtime_lock); + + return IRQ_HANDLED; +} + +static struct irqaction tmu_irq = { + .name = "timer", + .handler = tmu_timer_interrupt, + .flags = SA_INTERRUPT, + .mask = CPU_MASK_NONE, +}; + +/* + * Hah! We'll see if this works (switching from usecs to nsecs). + */ +static unsigned long tmu_timer_get_frequency(void) +{ + u32 freq; + struct timespec ts1, ts2; + unsigned long diff_nsec; + unsigned long factor; + + /* Setup the timer: We don't want to generate interrupts, just + * have it count down at its natural rate. + */ + ctrl_outb(0, TMU_TSTR); +#if !defined(CONFIG_CPU_SUBTYPE_SH7300) && !defined(CONFIG_CPU_SUBTYPE_SH7760) + ctrl_outb(TMU_TOCR_INIT, TMU_TOCR); +#endif + ctrl_outw(TMU0_TCR_CALIB, TMU0_TCR); + ctrl_outl(0xffffffff, TMU0_TCOR); + ctrl_outl(0xffffffff, TMU0_TCNT); + + rtc_get_time(&ts2); + + do { + rtc_get_time(&ts1); + } while (ts1.tv_nsec == ts2.tv_nsec && ts1.tv_sec == ts2.tv_sec); + + /* actually start the timer */ + ctrl_outb(TMU_TSTR_INIT, TMU_TSTR); + + do { + rtc_get_time(&ts2); + } while (ts1.tv_nsec == ts2.tv_nsec && ts1.tv_sec == ts2.tv_sec); + + freq = 0xffffffff - ctrl_inl(TMU0_TCNT); + if (ts2.tv_nsec < ts1.tv_nsec) { + ts2.tv_nsec += 1000000000; + ts2.tv_sec--; + } + + diff_nsec = (ts2.tv_sec - ts1.tv_sec) * 1000000000 + (ts2.tv_nsec - ts1.tv_nsec); + + /* this should work well if the RTC has a precision of n Hz, where + * n is an integer. I don't think we have to worry about the other + * cases. */ + factor = (1000000000 + diff_nsec/2) / diff_nsec; + + if (factor * diff_nsec > 1100000000 || + factor * diff_nsec < 900000000) + panic("weird RTC (diff_nsec %ld)", diff_nsec); + + return freq * factor; +} + +static void tmu_clk_init(struct clk *clk) +{ + u8 divisor = TMU0_TCR_INIT & 0x7; + ctrl_outw(TMU0_TCR_INIT, TMU0_TCR); + clk->rate = clk->parent->rate / (4 << (divisor << 1)); +} + +static void tmu_clk_recalc(struct clk *clk) +{ + u8 divisor = ctrl_inw(TMU0_TCR) & 0x7; + clk->rate = clk->parent->rate / (4 << (divisor << 1)); +} + +static struct clk_ops tmu_clk_ops = { + .init = tmu_clk_init, + .recalc = tmu_clk_recalc, +}; + +static struct clk tmu0_clk = { + .name = "tmu0_clk", + .ops = &tmu_clk_ops, +}; + +static int tmu_timer_init(void) +{ + unsigned long interval; + + setup_irq(TIMER_IRQ, &tmu_irq); + + tmu0_clk.parent = clk_get("module_clk"); + + /* Start TMU0 */ + ctrl_outb(0, TMU_TSTR); +#if !defined(CONFIG_CPU_SUBTYPE_SH7300) && !defined(CONFIG_CPU_SUBTYPE_SH7760) + ctrl_outb(TMU_TOCR_INIT, TMU_TOCR); +#endif + + clk_register(&tmu0_clk); + clk_enable(&tmu0_clk); + + interval = (clk_get_rate(&tmu0_clk) + HZ / 2) / HZ; + printk(KERN_INFO "Interval = %ld\n", interval); + + ctrl_outl(interval, TMU0_TCOR); + ctrl_outl(interval, TMU0_TCNT); + + ctrl_outb(TMU_TSTR_INIT, TMU_TSTR); + + return 0; +} + +struct sys_timer_ops tmu_timer_ops = { + .init = tmu_timer_init, + .get_frequency = tmu_timer_get_frequency, + .get_offset = tmu_timer_get_offset, +}; + +struct sys_timer tmu_timer = { + .name = "tmu", + .ops = &tmu_timer_ops, +}; + diff --git a/arch/sh/kernel/timers/timer.c b/arch/sh/kernel/timers/timer.c new file mode 100644 index 00000000000..dc1f631053a --- /dev/null +++ b/arch/sh/kernel/timers/timer.c @@ -0,0 +1,50 @@ +/* + * arch/sh/kernel/timers/timer.c - Common timer code + * + * Copyright (C) 2005 Paul Mundt + * + * 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. + */ +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/timer.h> +#include <linux/string.h> +#include <asm/timer.h> + +static struct sys_timer *sys_timers[] __initdata = { +#ifdef CONFIG_SH_TMU + &tmu_timer, +#endif + NULL, +}; + +static char timer_override[10] __initdata; +static int __init timer_setup(char *str) +{ + if (str) + strlcpy(timer_override, str, sizeof(timer_override)); + return 1; +} +__setup("timer=", timer_setup); + +struct sys_timer *get_sys_timer(void) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(sys_timers); i++) { + struct sys_timer *t = sys_timers[i]; + + if (unlikely(!t)) + break; + if (unlikely(timer_override[0])) + if ((strcmp(timer_override, t->name) != 0)) + continue; + if (likely(t->ops->init() == 0)) + return t; + } + + return NULL; +} + diff --git a/arch/sh/mm/Kconfig b/arch/sh/mm/Kconfig new file mode 100644 index 00000000000..fb586b1cf8b --- /dev/null +++ b/arch/sh/mm/Kconfig @@ -0,0 +1,233 @@ +menu "Processor selection" + +# +# Processor families +# +config CPU_SH2 + bool + select SH_WRITETHROUGH + +config CPU_SH3 + bool + select CPU_HAS_INTEVT + select CPU_HAS_SR_RB + +config CPU_SH4 + bool + select CPU_HAS_INTEVT + select CPU_HAS_SR_RB + +config CPU_SH4A + bool + select CPU_SH4 + select CPU_HAS_INTC2_IRQ + +config CPU_SUBTYPE_ST40 + bool + select CPU_SH4 + select CPU_HAS_INTC2_IRQ + +# +# Processor subtypes +# + +comment "SH-2 Processor Support" + +config CPU_SUBTYPE_SH7604 + bool "Support SH7604 processor" + select CPU_SH2 + +comment "SH-3 Processor Support" + +config CPU_SUBTYPE_SH7300 + bool "Support SH7300 processor" + select CPU_SH3 + +config CPU_SUBTYPE_SH7705 + bool "Support SH7705 processor" + select CPU_SH3 + select CPU_HAS_PINT_IRQ + +config CPU_SUBTYPE_SH7707 + bool "Support SH7707 processor" + select CPU_SH3 + select CPU_HAS_PINT_IRQ + help + Select SH7707 if you have a 60 Mhz SH-3 HD6417707 CPU. + +config CPU_SUBTYPE_SH7708 + bool "Support SH7708 processor" + select CPU_SH3 + help + Select SH7708 if you have a 60 Mhz SH-3 HD6417708S or + if you have a 100 Mhz SH-3 HD6417708R CPU. + +config CPU_SUBTYPE_SH7709 + bool "Support SH7709 processor" + select CPU_SH3 + select CPU_HAS_PINT_IRQ + help + Select SH7709 if you have a 80 Mhz SH-3 HD6417709 CPU. + +comment "SH-4 Processor Support" + +config CPU_SUBTYPE_SH7750 + bool "Support SH7750 processor" + select CPU_SH4 + help + Select SH7750 if you have a 200 Mhz SH-4 HD6417750 CPU. + +config CPU_SUBTYPE_SH7091 + bool "Support SH7091 processor" + select CPU_SH4 + select CPU_SUBTYPE_SH7750 + help + Select SH7091 if you have an SH-4 based Sega device (such as + the Dreamcast, Naomi, and Naomi 2). + +config CPU_SUBTYPE_SH7750R + bool "Support SH7750R processor" + select CPU_SH4 + select CPU_SUBTYPE_SH7750 + +config CPU_SUBTYPE_SH7750S + bool "Support SH7750S processor" + select CPU_SH4 + select CPU_SUBTYPE_SH7750 + +config CPU_SUBTYPE_SH7751 + bool "Support SH7751 processor" + select CPU_SH4 + help + Select SH7751 if you have a 166 Mhz SH-4 HD6417751 CPU, + or if you have a HD6417751R CPU. + +config CPU_SUBTYPE_SH7751R + bool "Support SH7751R processor" + select CPU_SH4 + select CPU_SUBTYPE_SH7751 + +config CPU_SUBTYPE_SH7760 + bool "Support SH7760 processor" + select CPU_SH4 + select CPU_HAS_INTC2_IRQ + +config CPU_SUBTYPE_SH4_202 + bool "Support SH4-202 processor" + select CPU_SH4 + +comment "ST40 Processor Support" + +config CPU_SUBTYPE_ST40STB1 + bool "Support ST40STB1/ST40RA processors" + select CPU_SUBTYPE_ST40 + help + Select ST40STB1 if you have a ST40RA CPU. + This was previously called the ST40STB1, hence the option name. + +config CPU_SUBTYPE_ST40GX1 + bool "Support ST40GX1 processor" + select CPU_SUBTYPE_ST40 + help + Select ST40GX1 if you have a ST40GX1 CPU. + +comment "SH-4A Processor Support" + +config CPU_SUBTYPE_SH73180 + bool "Support SH73180 processor" + select CPU_SH4A + +config CPU_SUBTYPE_SH7770 + bool "Support SH7770 processor" + select CPU_SH4A + +config CPU_SUBTYPE_SH7780 + bool "Support SH7780 processor" + select CPU_SH4A + +endmenu + +menu "Memory management options" + +config MMU + bool "Support for memory management hardware" + depends on !CPU_SH2 + default y + help + Some SH processors (such as SH-2/SH-2A) lack an MMU. In order to + boot on these systems, this option must not be set. + + On other systems (such as the SH-3 and 4) where an MMU exists, + turning this off will boot the kernel on these machines with the + MMU implicitly switched off. + +config 32BIT + bool "Support 32-bit physical addressing through PMB" + depends on CPU_SH4A + default y + help + If you say Y here, physical addressing will be extended to + 32-bits through the SH-4A PMB. If this is not set, legacy + 29-bit physical addressing will be used. + +choice + prompt "HugeTLB page size" + depends on HUGETLB_PAGE && CPU_SH4 && MMU + default HUGETLB_PAGE_SIZE_64K + +config HUGETLB_PAGE_SIZE_64K + bool "64K" + +config HUGETLB_PAGE_SIZE_1MB + bool "1MB" + +endchoice + +source "mm/Kconfig" + +endmenu + +menu "Cache configuration" + +config SH7705_CACHE_32KB + bool "Enable 32KB cache size for SH7705" + depends on CPU_SUBTYPE_SH7705 + default y + +config SH_DIRECT_MAPPED + bool "Use direct-mapped caching" + default n + help + Selecting this option will configure the caches to be direct-mapped, + even if the cache supports a 2 or 4-way mode. This is useful primarily + for debugging on platforms with 2 and 4-way caches (SH7750R/SH7751R, + SH4-202, SH4-501, etc.) + + Turn this option off for platforms that do not have a direct-mapped + cache, and you have no need to run the caches in such a configuration. + +config SH_WRITETHROUGH + bool "Use write-through caching" + default y if CPU_SH2 + help + Selecting this option will configure the caches in write-through + mode, as opposed to the default write-back configuration. + + Since there's sill some aliasing issues on SH-4, this option will + unfortunately still require the majority of flushing functions to + be implemented to deal with aliasing. + + If unsure, say N. + +config SH_OCRAM + bool "Operand Cache RAM (OCRAM) support" + help + Selecting this option will automatically tear down the number of + sets in the dcache by half, which in turn exposes a memory range. + + The addresses for the OC RAM base will vary according to the + processor version. Consult vendor documentation for specifics. + + If unsure, say N. + +endmenu diff --git a/arch/sh/mm/ioremap.c b/arch/sh/mm/ioremap.c index e794e27a72f..96fa4a999e2 100644 --- a/arch/sh/mm/ioremap.c +++ b/arch/sh/mm/ioremap.c @@ -6,13 +6,19 @@ * 640k-1MB IO memory area on PC's * * (C) Copyright 1995 1996 Linus Torvalds + * (C) Copyright 2005, 2006 Paul Mundt + * + * 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. */ - #include <linux/vmalloc.h> +#include <linux/module.h> #include <linux/mm.h> #include <asm/io.h> #include <asm/page.h> #include <asm/pgalloc.h> +#include <asm/addrspace.h> #include <asm/cacheflush.h> #include <asm/tlbflush.h> @@ -80,9 +86,15 @@ int remap_area_pages(unsigned long address, unsigned long phys_addr, if (address >= end) BUG(); do { + pud_t *pud; pmd_t *pmd; - pmd = pmd_alloc(&init_mm, dir, address); + error = -ENOMEM; + + pud = pud_alloc(&init_mm, dir, address); + if (!pud) + break; + pmd = pmd_alloc(&init_mm, pud, address); if (!pmd) break; if (remap_area_pmd(pmd, address, end - address, @@ -97,10 +109,6 @@ int remap_area_pages(unsigned long address, unsigned long phys_addr, } /* - * Generic mapping function (not visible outside): - */ - -/* * Remap an arbitrary physical address space into the kernel virtual * address space. Needed when the kernel wants to access high addresses * directly. @@ -109,11 +117,11 @@ int remap_area_pages(unsigned long address, unsigned long phys_addr, * have to convert them into an offset in a page-aligned mapping, but the * caller shouldn't need to know that small detail. */ -void * p3_ioremap(unsigned long phys_addr, unsigned long size, unsigned long flags) +void __iomem *__ioremap(unsigned long phys_addr, unsigned long size, + unsigned long flags) { - void * addr; struct vm_struct * area; - unsigned long offset, last_addr; + unsigned long offset, last_addr, addr, orig_addr; /* Don't allow wraparound or zero size */ last_addr = phys_addr + size - 1; @@ -124,7 +132,7 @@ void * p3_ioremap(unsigned long phys_addr, unsigned long size, unsigned long fla * Don't remap the low PCI/ISA area, it's always mapped.. */ if (phys_addr >= 0xA0000 && last_addr < 0x100000) - return phys_to_virt(phys_addr); + return (void __iomem *)phys_to_virt(phys_addr); /* * Don't allow anybody to remap normal RAM that we're using.. @@ -146,16 +154,71 @@ void * p3_ioremap(unsigned long phys_addr, unsigned long size, unsigned long fla if (!area) return NULL; area->phys_addr = phys_addr; - addr = area->addr; - if (remap_area_pages((unsigned long) addr, phys_addr, size, flags)) { - vunmap(addr); - return NULL; + orig_addr = addr = (unsigned long)area->addr; + +#ifdef CONFIG_32BIT + /* + * First try to remap through the PMB once a valid VMA has been + * established. Smaller allocations (or the rest of the size + * remaining after a PMB mapping due to the size not being + * perfectly aligned on a PMB size boundary) are then mapped + * through the UTLB using conventional page tables. + * + * PMB entries are all pre-faulted. + */ + if (unlikely(size >= 0x1000000)) { + unsigned long mapped = pmb_remap(addr, phys_addr, size, flags); + + if (likely(mapped)) { + addr += mapped; + phys_addr += mapped; + size -= mapped; + } } - return (void *) (offset + (char *)addr); +#endif + + if (likely(size)) + if (remap_area_pages(addr, phys_addr, size, flags)) { + vunmap((void *)orig_addr); + return NULL; + } + + return (void __iomem *)(offset + (char *)orig_addr); } +EXPORT_SYMBOL(__ioremap); -void p3_iounmap(void *addr) +void __iounmap(void __iomem *addr) { - if (addr > high_memory) - vfree((void *)(PAGE_MASK & (unsigned long)addr)); + unsigned long vaddr = (unsigned long __force)addr; + struct vm_struct *p; + + if (PXSEG(vaddr) < P3SEG) + return; + +#ifdef CONFIG_32BIT + /* + * Purge any PMB entries that may have been established for this + * mapping, then proceed with conventional VMA teardown. + * + * XXX: Note that due to the way that remove_vm_area() does + * matching of the resultant VMA, we aren't able to fast-forward + * the address past the PMB space until the end of the VMA where + * the page tables reside. As such, unmap_vm_area() will be + * forced to linearly scan over the area until it finds the page + * tables where PTEs that need to be unmapped actually reside, + * which is far from optimal. Perhaps we need to use a separate + * VMA for the PMB mappings? + * -- PFM. + */ + pmb_unmap(vaddr); +#endif + + p = remove_vm_area((void *)(vaddr & PAGE_MASK)); + if (!p) { + printk(KERN_ERR "%s: bad address %p\n", __FUNCTION__, addr); + return; + } + + kfree(p); } +EXPORT_SYMBOL(__iounmap); diff --git a/arch/sh/tools/mach-types b/arch/sh/tools/mach-types index 0693fbd1f95..182fe909257 100644 --- a/arch/sh/tools/mach-types +++ b/arch/sh/tools/mach-types @@ -10,10 +10,7 @@ SE SH_SOLUTION_ENGINE 7300SE SH_7300_SOLUTION_ENGINE 73180SE SH_73180_SOLUTION_ENGINE 7751SYSTEMH SH_7751_SYSTEMH -HP600 SH_HP600 -HP620 SH_HP620 -HP680 SH_HP680 -HP690 SH_HP690 +HP6XX SH_HP6XX HD64461 HD64461 HD64465 HD64465 SH2000 SH_SH2000 diff --git a/arch/sparc/kernel/entry.S b/arch/sparc/kernel/entry.S index 03ecb4e4614..267ec8f6fb5 100644 --- a/arch/sparc/kernel/entry.S +++ b/arch/sparc/kernel/entry.S @@ -38,7 +38,7 @@ #define curptr g6 -#define NR_SYSCALLS 284 /* Each OS is different... */ +#define NR_SYSCALLS 299 /* Each OS is different... */ /* These are just handy. */ #define _SV save %sp, -STACKFRAME_SZ, %sp @@ -1277,62 +1277,6 @@ sys_sigstack: mov %l5, %o7 .align 4 - .globl sys_sigpause -sys_sigpause: - /* Note: %o0 already has correct value... */ - call do_sigpause - add %sp, STACKFRAME_SZ, %o1 - - ld [%curptr + TI_FLAGS], %l5 - andcc %l5, _TIF_SYSCALL_TRACE, %g0 - be 1f - nop - - call syscall_trace - nop - -1: - /* We are returning to a signal handler. */ - RESTORE_ALL - - .align 4 - .globl sys_sigsuspend -sys_sigsuspend: - call do_sigsuspend - add %sp, STACKFRAME_SZ, %o0 - - ld [%curptr + TI_FLAGS], %l5 - andcc %l5, _TIF_SYSCALL_TRACE, %g0 - be 1f - nop - - call syscall_trace - nop - -1: - /* We are returning to a signal handler. */ - RESTORE_ALL - - .align 4 - .globl sys_rt_sigsuspend -sys_rt_sigsuspend: - /* Note: %o0, %o1 already have correct value... */ - call do_rt_sigsuspend - add %sp, STACKFRAME_SZ, %o2 - - ld [%curptr + TI_FLAGS], %l5 - andcc %l5, _TIF_SYSCALL_TRACE, %g0 - be 1f - nop - - call syscall_trace - nop - -1: - /* We are returning to a signal handler. */ - RESTORE_ALL - - .align 4 .globl sys_sigreturn sys_sigreturn: call do_sigreturn diff --git a/arch/sparc/kernel/rtrap.S b/arch/sparc/kernel/rtrap.S index f7460d897e7..77ca6fd8125 100644 --- a/arch/sparc/kernel/rtrap.S +++ b/arch/sparc/kernel/rtrap.S @@ -68,15 +68,14 @@ ret_trap_lockless_ipi: ld [%curptr + TI_FLAGS], %g2 signal_p: - andcc %g2, (_TIF_NOTIFY_RESUME|_TIF_SIGPENDING), %g0 + andcc %g2, (_TIF_SIGPENDING|_TIF_RESTORE_SIGMASK), %g0 bz,a ret_trap_continue ld [%sp + STACKFRAME_SZ + PT_PSR], %t_psr - clr %o0 - mov %l5, %o2 - mov %l6, %o3 + mov %l5, %o1 + mov %l6, %o2 call do_signal - add %sp, STACKFRAME_SZ, %o1 ! pt_regs ptr + add %sp, STACKFRAME_SZ, %o0 ! pt_regs ptr /* Fall through. */ ld [%sp + STACKFRAME_SZ + PT_PSR], %t_psr diff --git a/arch/sparc/kernel/signal.c b/arch/sparc/kernel/signal.c index 5f34d7dc2b8..0748d8147bb 100644 --- a/arch/sparc/kernel/signal.c +++ b/arch/sparc/kernel/signal.c @@ -35,9 +35,6 @@ extern void fpsave(unsigned long *fpregs, unsigned long *fsr, void *fpqueue, unsigned long *fpqdepth); extern void fpload(unsigned long *fpregs, unsigned long *fsr); -asmlinkage int do_signal(sigset_t *oldset, struct pt_regs * regs, - unsigned long orig_o0, int restart_syscall); - /* Signal frames: the original one (compatible with SunOS): * * Set up a signal frame... Make the stack look the way SunOS @@ -95,98 +92,30 @@ struct rt_signal_frame { #define NF_ALIGNEDSZ (((sizeof(struct new_signal_frame) + 7) & (~7))) #define RT_ALIGNEDSZ (((sizeof(struct rt_signal_frame) + 7) & (~7))) -/* - * atomically swap in the new signal mask, and wait for a signal. - * This is really tricky on the Sparc, watch out... - */ -asmlinkage void _sigpause_common(old_sigset_t set, struct pt_regs *regs) +static int _sigpause_common(old_sigset_t set) { - sigset_t saveset; - set &= _BLOCKABLE; spin_lock_irq(¤t->sighand->siglock); - saveset = current->blocked; + current->saved_sigmask = current->blocked; siginitset(¤t->blocked, set); recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); - regs->pc = regs->npc; - regs->npc += 4; - - /* Condition codes and return value where set here for sigpause, - * and so got used by setup_frame, which again causes sigreturn() - * to return -EINTR. - */ - while (1) { - current->state = TASK_INTERRUPTIBLE; - schedule(); - /* - * Return -EINTR and set condition code here, - * so the interrupted system call actually returns - * these. - */ - regs->psr |= PSR_C; - regs->u_regs[UREG_I0] = EINTR; - if (do_signal(&saveset, regs, 0, 0)) - return; - } -} + current->state = TASK_INTERRUPTIBLE; + schedule(); + set_thread_flag(TIF_RESTORE_SIGMASK); -asmlinkage void do_sigpause(unsigned int set, struct pt_regs *regs) -{ - _sigpause_common(set, regs); + return -ERESTARTNOHAND; } -asmlinkage void do_sigsuspend (struct pt_regs *regs) +asmlinkage int sys_sigpause(unsigned int set) { - _sigpause_common(regs->u_regs[UREG_I0], regs); + return _sigpause_common(set); } -asmlinkage void do_rt_sigsuspend(sigset_t __user *uset, size_t sigsetsize, - struct pt_regs *regs) +asmlinkage int sys_sigsuspend(old_sigset_t set) { - sigset_t oldset, set; - - /* XXX: Don't preclude handling different sized sigset_t's. */ - if (sigsetsize != sizeof(sigset_t)) { - regs->psr |= PSR_C; - regs->u_regs[UREG_I0] = EINVAL; - return; - } - - if (copy_from_user(&set, uset, sizeof(set))) { - regs->psr |= PSR_C; - regs->u_regs[UREG_I0] = EFAULT; - return; - } - - sigdelsetmask(&set, ~_BLOCKABLE); - spin_lock_irq(¤t->sighand->siglock); - oldset = current->blocked; - current->blocked = set; - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); - - regs->pc = regs->npc; - regs->npc += 4; - - /* Condition codes and return value where set here for sigpause, - * and so got used by setup_frame, which again causes sigreturn() - * to return -EINTR. - */ - while (1) { - current->state = TASK_INTERRUPTIBLE; - schedule(); - /* - * Return -EINTR and set condition code here, - * so the interrupted system call actually returns - * these. - */ - regs->psr |= PSR_C; - regs->u_regs[UREG_I0] = EINTR; - if (do_signal(&oldset, regs, 0, 0)) - return; - } + return _sigpause_common(set); } static inline int @@ -1067,13 +996,13 @@ static inline void syscall_restart(unsigned long orig_i0, struct pt_regs *regs, * want to handle. Thus you cannot kill init even with a SIGKILL even by * mistake. */ -asmlinkage int do_signal(sigset_t *oldset, struct pt_regs * regs, - unsigned long orig_i0, int restart_syscall) +asmlinkage void do_signal(struct pt_regs * regs, unsigned long orig_i0, int restart_syscall) { siginfo_t info; struct sparc_deliver_cookie cookie; struct k_sigaction ka; int signr; + sigset_t *oldset; /* * XXX Disable svr4 signal handling until solaris emulation works. @@ -1089,7 +1018,9 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs * regs, cookie.restart_syscall = restart_syscall; cookie.orig_i0 = orig_i0; - if (!oldset) + if (test_thread_flag(TIF_RESTORE_SIGMASK)) + oldset = ¤t->saved_sigmask; + else oldset = ¤t->blocked; signr = get_signal_to_deliver(&info, &ka, regs, &cookie); @@ -1098,7 +1029,14 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs * regs, syscall_restart(cookie.orig_i0, regs, &ka.sa); handle_signal(signr, &ka, &info, oldset, regs, svr4_signal); - return 1; + /* a signal was successfully delivered; the saved + * sigmask will have been stored in the signal frame, + * and will be restored by sigreturn, so we can simply + * clear the TIF_RESTORE_SIGMASK flag. + */ + if (test_thread_flag(TIF_RESTORE_SIGMASK)) + clear_thread_flag(TIF_RESTORE_SIGMASK); + return; } if (cookie.restart_syscall && (regs->u_regs[UREG_I0] == ERESTARTNOHAND || @@ -1115,7 +1053,14 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs * regs, regs->pc -= 4; regs->npc -= 4; } - return 0; + + /* if there's no signal to deliver, we just put the saved sigmask + * back + */ + if (test_thread_flag(TIF_RESTORE_SIGMASK)) { + clear_thread_flag(TIF_RESTORE_SIGMASK); + sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); + } } asmlinkage int diff --git a/arch/sparc/kernel/sparc_ksyms.c b/arch/sparc/kernel/sparc_ksyms.c index 0b0d492c953..19b25399d7e 100644 --- a/arch/sparc/kernel/sparc_ksyms.c +++ b/arch/sparc/kernel/sparc_ksyms.c @@ -66,7 +66,6 @@ struct poll { extern int svr4_getcontext (svr4_ucontext_t *, struct pt_regs *); extern int svr4_setcontext (svr4_ucontext_t *, struct pt_regs *); -void _sigpause_common (unsigned int set, struct pt_regs *); extern void (*__copy_1page)(void *, const void *); extern void __memmove(void *, const void *, __kernel_size_t); extern void (*bzero_1page)(void *); @@ -227,7 +226,6 @@ EXPORT_SYMBOL(kunmap_atomic); /* Solaris/SunOS binary compatibility */ EXPORT_SYMBOL(svr4_setcontext); EXPORT_SYMBOL(svr4_getcontext); -EXPORT_SYMBOL(_sigpause_common); EXPORT_SYMBOL(dump_thread); diff --git a/arch/sparc/kernel/systbls.S b/arch/sparc/kernel/systbls.S index e457a40838f..6877ae4cd1d 100644 --- a/arch/sparc/kernel/systbls.S +++ b/arch/sparc/kernel/systbls.S @@ -75,7 +75,10 @@ sys_call_table: /*265*/ .long sys_timer_delete, sys_timer_create, sys_nis_syscall, sys_io_setup, sys_io_destroy /*270*/ .long sys_io_submit, sys_io_cancel, sys_io_getevents, sys_mq_open, sys_mq_unlink /*275*/ .long sys_mq_timedsend, sys_mq_timedreceive, sys_mq_notify, sys_mq_getsetattr, sys_waitid -/*280*/ .long sys_ni_syscall, sys_add_key, sys_request_key, sys_keyctl +/*280*/ .long sys_ni_syscall, sys_add_key, sys_request_key, sys_keyctl, sys_openat +/*285*/ .long sys_mkdirat, sys_mknodat, sys_fchownat, sys_futimesat, sys_newfstatat +/*290*/ .long sys_unlinkat, sys_renameat, sys_linkat, sys_symlinkat, sys_readlinkat +/*295*/ .long sys_fchmodat, sys_faccessat, sys_pselect6, sys_ppoll #ifdef CONFIG_SUNOS_EMUL /* Now the SunOS syscall table. */ @@ -181,6 +184,11 @@ sunos_sys_table: .long sunos_nosys, sunos_nosys, sunos_nosys .long sunos_nosys /*280*/ .long sunos_nosys, sunos_nosys, sunos_nosys + .long sunos_nosys, sunos_nosys, sunos_nosys + .long sunos_nosys, sunos_nosys, sunos_nosys .long sunos_nosys +/*290*/ .long sunos_nosys, sunos_nosys, sunos_nosys + .long sunos_nosys, sunos_nosys, sunos_nosys + .long sunos_nosys, sunos_nosys, sunos_nosys #endif diff --git a/arch/sparc/math-emu/math.c b/arch/sparc/math-emu/math.c index be2c80932e2..8613b3eb877 100644 --- a/arch/sparc/math-emu/math.c +++ b/arch/sparc/math-emu/math.c @@ -323,11 +323,6 @@ static int do_one_mathemu(u32 insn, unsigned long *pfsr, unsigned long *fregs) case FMOVS: case FABSS: case FNEGS: TYPE(2,1,0,1,0,0,0); break; - default: -#ifdef DEBUG_MATHEMU - printk("unknown FPop1: %03lx\n",(insn>>5)&0x1ff); -#endif - break; } } else if ((insn & 0xc1f80000) == 0x81a80000) /* FPOP2 */ { switch ((insn >> 5) & 0x1ff) { @@ -337,11 +332,6 @@ static int do_one_mathemu(u32 insn, unsigned long *pfsr, unsigned long *fregs) case FCMPED: TYPE(3,0,0,2,1,2,1); break; case FCMPQ: TYPE(3,0,0,3,1,3,1); break; case FCMPEQ: TYPE(3,0,0,3,1,3,1); break; - default: -#ifdef DEBUG_MATHEMU - printk("unknown FPop2: %03lx\n",(insn>>5)&0x1ff); -#endif - break; } } diff --git a/arch/sparc/mm/iommu.c b/arch/sparc/mm/iommu.c index 489bf68d5f0..77840c80478 100644 --- a/arch/sparc/mm/iommu.c +++ b/arch/sparc/mm/iommu.c @@ -295,8 +295,7 @@ static void iommu_release_one(u32 busa, int npages, struct sbus_bus *sbus) int ioptex; int i; - if (busa < iommu->start) - BUG(); + BUG_ON(busa < iommu->start); ioptex = (busa - iommu->start) >> PAGE_SHIFT; for (i = 0; i < npages; i++) { iopte_val(iommu->page_table[ioptex + i]) = 0; @@ -340,9 +339,9 @@ static int iommu_map_dma_area(dma_addr_t *pba, unsigned long va, iopte_t *first; int ioptex; - if ((va & ~PAGE_MASK) != 0) BUG(); - if ((addr & ~PAGE_MASK) != 0) BUG(); - if ((len & ~PAGE_MASK) != 0) BUG(); + BUG_ON((va & ~PAGE_MASK) != 0); + BUG_ON((addr & ~PAGE_MASK) != 0); + BUG_ON((len & ~PAGE_MASK) != 0); /* page color = physical address */ ioptex = bit_map_string_get(&iommu->usemap, len >> PAGE_SHIFT, @@ -405,8 +404,8 @@ static void iommu_unmap_dma_area(unsigned long busa, int len) unsigned long end; int ioptex = (busa - iommu->start) >> PAGE_SHIFT; - if ((busa & ~PAGE_MASK) != 0) BUG(); - if ((len & ~PAGE_MASK) != 0) BUG(); + BUG_ON((busa & ~PAGE_MASK) != 0); + BUG_ON((len & ~PAGE_MASK) != 0); iopte += ioptex; end = busa + len; diff --git a/arch/sparc64/defconfig b/arch/sparc64/defconfig index a3fb3376ffa..9ceddad0fb4 100644 --- a/arch/sparc64/defconfig +++ b/arch/sparc64/defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.15 -# Mon Jan 9 14:36:29 2006 +# Linux kernel version: 2.6.16-rc1 +# Wed Jan 18 13:41:02 2006 # CONFIG_SPARC=y CONFIG_SPARC64=y @@ -233,6 +233,11 @@ CONFIG_VLAN_8021Q=m # CONFIG_ATALK is not set # CONFIG_X25 is not set # CONFIG_LAPB is not set + +# +# TIPC Configuration (EXPERIMENTAL) +# +# CONFIG_TIPC is not set # CONFIG_NET_DIVERT is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set @@ -420,8 +425,7 @@ CONFIG_ISCSI_TCP=m # CONFIG_SCSI_QLOGIC_FC is not set # CONFIG_SCSI_QLOGIC_1280 is not set # CONFIG_SCSI_QLOGICPTI is not set -CONFIG_SCSI_QLA2XXX=y -# CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE is not set +# CONFIG_SCSI_QLA_FC is not set # CONFIG_SCSI_LPFC is not set # CONFIG_SCSI_DC395x is not set # CONFIG_SCSI_DC390T is not set @@ -529,6 +533,7 @@ CONFIG_NET_PCI=y # CONFIG_DL2K is not set CONFIG_E1000=m CONFIG_E1000_NAPI=y +# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set # CONFIG_MYRI_SBUS is not set # CONFIG_NS83820 is not set # CONFIG_HAMACHI is not set @@ -652,7 +657,6 @@ CONFIG_SERIAL_SUNSU_CONSOLE=y CONFIG_SERIAL_SUNSAB=m CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y -# CONFIG_SERIAL_JSM is not set CONFIG_UNIX98_PTYS=y # CONFIG_LEGACY_PTYS is not set @@ -738,6 +742,12 @@ CONFIG_I2C_ALGOBIT=y # CONFIG_I2C_DEBUG_CHIP is not set # +# SPI support +# +# CONFIG_SPI is not set +# CONFIG_SPI_MASTER is not set + +# # Dallas's 1-wire bus # # CONFIG_W1 is not set @@ -1014,6 +1024,7 @@ CONFIG_USB_UHCI_HCD=m # CONFIG_USB_HID=y CONFIG_USB_HIDINPUT=y +# CONFIG_USB_HIDINPUT_POWERBOOK is not set # CONFIG_HID_FF is not set CONFIG_USB_HIDDEV=y # CONFIG_USB_AIPTEK is not set @@ -1268,12 +1279,13 @@ CONFIG_KPROBES=y # Kernel hacking # CONFIG_PRINTK_TIME=y -CONFIG_DEBUG_KERNEL=y CONFIG_MAGIC_SYSRQ=y +CONFIG_DEBUG_KERNEL=y CONFIG_LOG_BUF_SHIFT=18 CONFIG_DETECT_SOFTLOCKUP=y CONFIG_SCHEDSTATS=y # CONFIG_DEBUG_SLAB is not set +# CONFIG_DEBUG_MUTEXES is not set # CONFIG_DEBUG_SPINLOCK is not set # CONFIG_DEBUG_SPINLOCK_SLEEP is not set # CONFIG_DEBUG_KOBJECT is not set @@ -1281,6 +1293,7 @@ CONFIG_DEBUG_BUGVERBOSE=y # CONFIG_DEBUG_INFO is not set CONFIG_DEBUG_FS=y # CONFIG_DEBUG_VM is not set +CONFIG_FORCED_INLINING=y # CONFIG_RCU_TORTURE_TEST is not set # CONFIG_DEBUG_STACK_USAGE is not set # CONFIG_DEBUG_DCFLUSH is not set diff --git a/arch/sparc64/kernel/entry.S b/arch/sparc64/kernel/entry.S index 71000299188..12911e7463f 100644 --- a/arch/sparc64/kernel/entry.S +++ b/arch/sparc64/kernel/entry.S @@ -25,7 +25,7 @@ #define curptr g6 -#define NR_SYSCALLS 284 /* Each OS is different... */ +#define NR_SYSCALLS 299 /* Each OS is different... */ .text .align 32 @@ -1416,7 +1416,6 @@ execve_merge: add %sp, PTREGS_OFF, %o0 .globl sys_pipe, sys_sigpause, sys_nis_syscall - .globl sys_sigsuspend, sys_rt_sigsuspend .globl sys_rt_sigreturn .globl sys_ptrace .globl sys_sigaltstack @@ -1440,28 +1439,6 @@ sys32_sigaltstack: mov %i6, %o2 #endif .align 32 -sys_sigsuspend: add %sp, PTREGS_OFF, %o0 - call do_sigsuspend - add %o7, 1f-.-4, %o7 - nop -sys_rt_sigsuspend: /* NOTE: %o0,%o1 have a correct value already */ - add %sp, PTREGS_OFF, %o2 - call do_rt_sigsuspend - add %o7, 1f-.-4, %o7 - nop -#ifdef CONFIG_COMPAT - .globl sys32_rt_sigsuspend -sys32_rt_sigsuspend: /* NOTE: %o0,%o1 have a correct value already */ - srl %o0, 0, %o0 - add %sp, PTREGS_OFF, %o2 - call do_rt_sigsuspend32 - add %o7, 1f-.-4, %o7 -#endif - /* NOTE: %o0 has a correct value already */ -sys_sigpause: add %sp, PTREGS_OFF, %o1 - call do_sigpause - add %o7, 1f-.-4, %o7 - nop #ifdef CONFIG_COMPAT .globl sys32_sigreturn sys32_sigreturn: diff --git a/arch/sparc64/kernel/process.c b/arch/sparc64/kernel/process.c index 1dc3650c5ca..059b0d02522 100644 --- a/arch/sparc64/kernel/process.c +++ b/arch/sparc64/kernel/process.c @@ -164,6 +164,7 @@ void machine_restart(char * cmd) panic("Reboot failed!"); } +#ifdef CONFIG_COMPAT static void show_regwindow32(struct pt_regs *regs) { struct reg_window32 __user *rw; @@ -189,6 +190,9 @@ static void show_regwindow32(struct pt_regs *regs) r_w.ins[0], r_w.ins[1], r_w.ins[2], r_w.ins[3], r_w.ins[4], r_w.ins[5], r_w.ins[6], r_w.ins[7]); } +#else +#define show_regwindow32(regs) do { } while (0) +#endif static void show_regwindow(struct pt_regs *regs) { diff --git a/arch/sparc64/kernel/rtrap.S b/arch/sparc64/kernel/rtrap.S index 090dcca00d2..b80eba0081c 100644 --- a/arch/sparc64/kernel/rtrap.S +++ b/arch/sparc64/kernel/rtrap.S @@ -53,14 +53,13 @@ __handle_user_windows: wrpr %g0, RTRAP_PSTATE_IRQOFF, %pstate ldx [%g6 + TI_FLAGS], %l0 -1: andcc %l0, (_TIF_NOTIFY_RESUME | _TIF_SIGPENDING), %g0 +1: andcc %l0, (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK), %g0 be,pt %xcc, __handle_user_windows_continue nop - clr %o0 - mov %l5, %o2 - mov %l6, %o3 - add %sp, PTREGS_OFF, %o1 - mov %l0, %o4 + mov %l5, %o1 + mov %l6, %o2 + add %sp, PTREGS_OFF, %o0 + mov %l0, %o3 call do_notify_resume wrpr %g0, RTRAP_PSTATE, %pstate @@ -96,15 +95,14 @@ __handle_perfctrs: wrpr %g0, RTRAP_PSTATE, %pstate wrpr %g0, RTRAP_PSTATE_IRQOFF, %pstate ldx [%g6 + TI_FLAGS], %l0 -1: andcc %l0, (_TIF_NOTIFY_RESUME | _TIF_SIGPENDING), %g0 +1: andcc %l0, (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK), %g0 be,pt %xcc, __handle_perfctrs_continue sethi %hi(TSTATE_PEF), %o0 - clr %o0 - mov %l5, %o2 - mov %l6, %o3 - add %sp, PTREGS_OFF, %o1 - mov %l0, %o4 + mov %l5, %o1 + mov %l6, %o2 + add %sp, PTREGS_OFF, %o0 + mov %l0, %o3 call do_notify_resume wrpr %g0, RTRAP_PSTATE, %pstate @@ -129,11 +127,10 @@ __handle_userfpu: ba,a,pt %xcc, __handle_userfpu_continue __handle_signal: - clr %o0 - mov %l5, %o2 - mov %l6, %o3 - add %sp, PTREGS_OFF, %o1 - mov %l0, %o4 + mov %l5, %o1 + mov %l6, %o2 + add %sp, PTREGS_OFF, %o0 + mov %l0, %o3 call do_notify_resume wrpr %g0, RTRAP_PSTATE, %pstate wrpr %g0, RTRAP_PSTATE_IRQOFF, %pstate @@ -200,7 +197,7 @@ __handle_preemption_continue: andcc %l1, %o0, %g0 andcc %l0, _TIF_NEED_RESCHED, %g0 bne,pn %xcc, __handle_preemption - andcc %l0, (_TIF_NOTIFY_RESUME | _TIF_SIGPENDING), %g0 + andcc %l0, (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK), %g0 bne,pn %xcc, __handle_signal __handle_signal_continue: ldub [%g6 + TI_WSAVED], %o2 diff --git a/arch/sparc64/kernel/setup.c b/arch/sparc64/kernel/setup.c index 250745896ae..054461e6946 100644 --- a/arch/sparc64/kernel/setup.c +++ b/arch/sparc64/kernel/setup.c @@ -561,6 +561,8 @@ static int __init set_preferred_console(void) serial_console = 1; } else if (idev == PROMDEV_ITTYB && odev == PROMDEV_OTTYB) { serial_console = 2; + } else if (idev == PROMDEV_IRSC && odev == PROMDEV_ORSC) { + serial_console = 3; } else { prom_printf("Inconsistent console: " "input %d, output %d\n", diff --git a/arch/sparc64/kernel/signal.c b/arch/sparc64/kernel/signal.c index 60f5dfabb1e..ca11a4c457d 100644 --- a/arch/sparc64/kernel/signal.c +++ b/arch/sparc64/kernel/signal.c @@ -36,9 +36,6 @@ #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) -static int do_signal(sigset_t *oldset, struct pt_regs * regs, - unsigned long orig_o0, int ret_from_syscall); - /* {set, get}context() needed for 64-bit SparcLinux userland. */ asmlinkage void sparc64_set_context(struct pt_regs *regs) { @@ -242,114 +239,29 @@ struct rt_signal_frame { /* Align macros */ #define RT_ALIGNEDSZ (((sizeof(struct rt_signal_frame) + 7) & (~7))) -/* - * atomically swap in the new signal mask, and wait for a signal. - * This is really tricky on the Sparc, watch out... - */ -asmlinkage void _sigpause_common(old_sigset_t set, struct pt_regs *regs) +static long _sigpause_common(old_sigset_t set) { - sigset_t saveset; - -#ifdef CONFIG_SPARC32_COMPAT - if (test_thread_flag(TIF_32BIT)) { - extern asmlinkage void _sigpause32_common(compat_old_sigset_t, - struct pt_regs *); - _sigpause32_common(set, regs); - return; - } -#endif set &= _BLOCKABLE; spin_lock_irq(¤t->sighand->siglock); - saveset = current->blocked; + current->saved_sigmask = current->blocked; siginitset(¤t->blocked, set); recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); - - if (test_thread_flag(TIF_32BIT)) { - regs->tpc = (regs->tnpc & 0xffffffff); - regs->tnpc = (regs->tnpc + 4) & 0xffffffff; - } else { - regs->tpc = regs->tnpc; - regs->tnpc += 4; - } - /* Condition codes and return value where set here for sigpause, - * and so got used by setup_frame, which again causes sigreturn() - * to return -EINTR. - */ - while (1) { - current->state = TASK_INTERRUPTIBLE; - schedule(); - /* - * Return -EINTR and set condition code here, - * so the interrupted system call actually returns - * these. - */ - regs->tstate |= (TSTATE_ICARRY|TSTATE_XCARRY); - regs->u_regs[UREG_I0] = EINTR; - if (do_signal(&saveset, regs, 0, 0)) - return; - } + current->state = TASK_INTERRUPTIBLE; + schedule(); + set_thread_flag(TIF_RESTORE_SIGMASK); + return -ERESTARTNOHAND; } -asmlinkage void do_sigpause(unsigned int set, struct pt_regs *regs) +asmlinkage long sys_sigpause(unsigned int set) { - _sigpause_common(set, regs); + return _sigpause_common(set); } -asmlinkage void do_sigsuspend(struct pt_regs *regs) +asmlinkage long sys_sigsuspend(old_sigset_t set) { - _sigpause_common(regs->u_regs[UREG_I0], regs); -} - -asmlinkage void do_rt_sigsuspend(sigset_t __user *uset, size_t sigsetsize, struct pt_regs *regs) -{ - sigset_t oldset, set; - - /* XXX: Don't preclude handling different sized sigset_t's. */ - if (sigsetsize != sizeof(sigset_t)) { - regs->tstate |= (TSTATE_ICARRY|TSTATE_XCARRY); - regs->u_regs[UREG_I0] = EINVAL; - return; - } - if (copy_from_user(&set, uset, sizeof(set))) { - regs->tstate |= (TSTATE_ICARRY|TSTATE_XCARRY); - regs->u_regs[UREG_I0] = EFAULT; - return; - } - - sigdelsetmask(&set, ~_BLOCKABLE); - spin_lock_irq(¤t->sighand->siglock); - oldset = current->blocked; - current->blocked = set; - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); - - if (test_thread_flag(TIF_32BIT)) { - regs->tpc = (regs->tnpc & 0xffffffff); - regs->tnpc = (regs->tnpc + 4) & 0xffffffff; - } else { - regs->tpc = regs->tnpc; - regs->tnpc += 4; - } - - /* Condition codes and return value where set here for sigpause, - * and so got used by setup_frame, which again causes sigreturn() - * to return -EINTR. - */ - while (1) { - current->state = TASK_INTERRUPTIBLE; - schedule(); - /* - * Return -EINTR and set condition code here, - * so the interrupted system call actually returns - * these. - */ - regs->tstate |= (TSTATE_ICARRY|TSTATE_XCARRY); - regs->u_regs[UREG_I0] = EINTR; - if (do_signal(&oldset, regs, 0, 0)) - return; - } + return _sigpause_common(set); } static inline int @@ -607,26 +519,29 @@ static inline void syscall_restart(unsigned long orig_i0, struct pt_regs *regs, * want to handle. Thus you cannot kill init even with a SIGKILL even by * mistake. */ -static int do_signal(sigset_t *oldset, struct pt_regs * regs, - unsigned long orig_i0, int restart_syscall) +static void do_signal(struct pt_regs *regs, unsigned long orig_i0, int restart_syscall) { siginfo_t info; struct signal_deliver_cookie cookie; struct k_sigaction ka; int signr; + sigset_t *oldset; cookie.restart_syscall = restart_syscall; cookie.orig_i0 = orig_i0; - if (!oldset) + if (test_thread_flag(TIF_RESTORE_SIGMASK)) + oldset = ¤t->saved_sigmask; + else oldset = ¤t->blocked; #ifdef CONFIG_SPARC32_COMPAT if (test_thread_flag(TIF_32BIT)) { - extern int do_signal32(sigset_t *, struct pt_regs *, - unsigned long, int); - return do_signal32(oldset, regs, orig_i0, - cookie.restart_syscall); + extern void do_signal32(sigset_t *, struct pt_regs *, + unsigned long, int); + do_signal32(oldset, regs, orig_i0, + cookie.restart_syscall); + return; } #endif @@ -635,7 +550,15 @@ static int do_signal(sigset_t *oldset, struct pt_regs * regs, if (cookie.restart_syscall) syscall_restart(orig_i0, regs, &ka.sa); handle_signal(signr, &ka, &info, oldset, regs); - return 1; + + /* a signal was successfully delivered; the saved + * sigmask will have been stored in the signal frame, + * and will be restored by sigreturn, so we can simply + * clear the TIF_RESTORE_SIGMASK flag. + */ + if (test_thread_flag(TIF_RESTORE_SIGMASK)) + clear_thread_flag(TIF_RESTORE_SIGMASK); + return; } if (cookie.restart_syscall && (regs->u_regs[UREG_I0] == ERESTARTNOHAND || @@ -652,15 +575,21 @@ static int do_signal(sigset_t *oldset, struct pt_regs * regs, regs->tpc -= 4; regs->tnpc -= 4; } - return 0; + + /* if there's no signal to deliver, we just put the saved sigmask + * back + */ + if (test_thread_flag(TIF_RESTORE_SIGMASK)) { + clear_thread_flag(TIF_RESTORE_SIGMASK); + sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); + } } -void do_notify_resume(sigset_t *oldset, struct pt_regs *regs, - unsigned long orig_i0, int restart_syscall, +void do_notify_resume(struct pt_regs *regs, unsigned long orig_i0, int restart_syscall, unsigned long thread_info_flags) { - if (thread_info_flags & _TIF_SIGPENDING) - do_signal(oldset, regs, orig_i0, restart_syscall); + if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK)) + do_signal(regs, orig_i0, restart_syscall); } void ptrace_signal_deliver(struct pt_regs *regs, void *cookie) diff --git a/arch/sparc64/kernel/signal32.c b/arch/sparc64/kernel/signal32.c index 009a86e5ded..708ba9b42cd 100644 --- a/arch/sparc64/kernel/signal32.c +++ b/arch/sparc64/kernel/signal32.c @@ -32,9 +32,6 @@ #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) -int do_signal32(sigset_t *oldset, struct pt_regs *regs, - unsigned long orig_o0, int ret_from_syscall); - /* Signal frames: the original one (compatible with SunOS): * * Set up a signal frame... Make the stack look the way SunOS @@ -226,102 +223,6 @@ int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from) return 0; } -/* - * atomically swap in the new signal mask, and wait for a signal. - * This is really tricky on the Sparc, watch out... - */ -asmlinkage void _sigpause32_common(compat_old_sigset_t set, struct pt_regs *regs) -{ - sigset_t saveset; - - set &= _BLOCKABLE; - spin_lock_irq(¤t->sighand->siglock); - saveset = current->blocked; - siginitset(¤t->blocked, set); - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); - - regs->tpc = regs->tnpc; - regs->tnpc += 4; - if (test_thread_flag(TIF_32BIT)) { - regs->tpc &= 0xffffffff; - regs->tnpc &= 0xffffffff; - } - - /* Condition codes and return value where set here for sigpause, - * and so got used by setup_frame, which again causes sigreturn() - * to return -EINTR. - */ - while (1) { - current->state = TASK_INTERRUPTIBLE; - schedule(); - /* - * Return -EINTR and set condition code here, - * so the interrupted system call actually returns - * these. - */ - regs->tstate |= TSTATE_ICARRY; - regs->u_regs[UREG_I0] = EINTR; - if (do_signal32(&saveset, regs, 0, 0)) - return; - } -} - -asmlinkage void do_rt_sigsuspend32(u32 uset, size_t sigsetsize, struct pt_regs *regs) -{ - sigset_t oldset, set; - compat_sigset_t set32; - - /* XXX: Don't preclude handling different sized sigset_t's. */ - if (((compat_size_t)sigsetsize) != sizeof(sigset_t)) { - regs->tstate |= TSTATE_ICARRY; - regs->u_regs[UREG_I0] = EINVAL; - return; - } - if (copy_from_user(&set32, compat_ptr(uset), sizeof(set32))) { - regs->tstate |= TSTATE_ICARRY; - regs->u_regs[UREG_I0] = EFAULT; - return; - } - switch (_NSIG_WORDS) { - case 4: set.sig[3] = set32.sig[6] + (((long)set32.sig[7]) << 32); - case 3: set.sig[2] = set32.sig[4] + (((long)set32.sig[5]) << 32); - case 2: set.sig[1] = set32.sig[2] + (((long)set32.sig[3]) << 32); - case 1: set.sig[0] = set32.sig[0] + (((long)set32.sig[1]) << 32); - } - sigdelsetmask(&set, ~_BLOCKABLE); - spin_lock_irq(¤t->sighand->siglock); - oldset = current->blocked; - current->blocked = set; - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); - - regs->tpc = regs->tnpc; - regs->tnpc += 4; - if (test_thread_flag(TIF_32BIT)) { - regs->tpc &= 0xffffffff; - regs->tnpc &= 0xffffffff; - } - - /* Condition codes and return value where set here for sigpause, - * and so got used by setup_frame, which again causes sigreturn() - * to return -EINTR. - */ - while (1) { - current->state = TASK_INTERRUPTIBLE; - schedule(); - /* - * Return -EINTR and set condition code here, - * so the interrupted system call actually returns - * these. - */ - regs->tstate |= TSTATE_ICARRY; - regs->u_regs[UREG_I0] = EINTR; - if (do_signal32(&oldset, regs, 0, 0)) - return; - } -} - static int restore_fpu_state32(struct pt_regs *regs, __siginfo_fpu_t __user *fpu) { unsigned long *fpregs = current_thread_info()->fpregs; @@ -1362,8 +1263,8 @@ static inline void syscall_restart32(unsigned long orig_i0, struct pt_regs *regs * want to handle. Thus you cannot kill init even with a SIGKILL even by * mistake. */ -int do_signal32(sigset_t *oldset, struct pt_regs * regs, - unsigned long orig_i0, int restart_syscall) +void do_signal32(sigset_t *oldset, struct pt_regs * regs, + unsigned long orig_i0, int restart_syscall) { siginfo_t info; struct signal_deliver_cookie cookie; @@ -1380,7 +1281,15 @@ int do_signal32(sigset_t *oldset, struct pt_regs * regs, syscall_restart32(orig_i0, regs, &ka.sa); handle_signal32(signr, &ka, &info, oldset, regs, svr4_signal); - return 1; + + /* a signal was successfully delivered; the saved + * sigmask will have been stored in the signal frame, + * and will be restored by sigreturn, so we can simply + * clear the TIF_RESTORE_SIGMASK flag. + */ + if (test_thread_flag(TIF_RESTORE_SIGMASK)) + clear_thread_flag(TIF_RESTORE_SIGMASK); + return; } if (cookie.restart_syscall && (regs->u_regs[UREG_I0] == ERESTARTNOHAND || @@ -1397,7 +1306,14 @@ int do_signal32(sigset_t *oldset, struct pt_regs * regs, regs->tpc -= 4; regs->tnpc -= 4; } - return 0; + + /* if there's no signal to deliver, we just put the saved sigmask + * back + */ + if (test_thread_flag(TIF_RESTORE_SIGMASK)) { + clear_thread_flag(TIF_RESTORE_SIGMASK); + sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); + } } struct sigstack32 { diff --git a/arch/sparc64/kernel/sparc64_ksyms.c b/arch/sparc64/kernel/sparc64_ksyms.c index d177d7e5c9d..3c06bfb92a8 100644 --- a/arch/sparc64/kernel/sparc64_ksyms.c +++ b/arch/sparc64/kernel/sparc64_ksyms.c @@ -69,7 +69,6 @@ struct poll { extern void die_if_kernel(char *str, struct pt_regs *regs); extern pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); -void _sigpause_common (unsigned int set, struct pt_regs *); extern void *__bzero(void *, size_t); extern void *__memscan_zero(void *, size_t); extern void *__memscan_generic(void *, int, size_t); @@ -236,9 +235,10 @@ EXPORT_SYMBOL(pci_dma_supported); /* I/O device mmaping on Sparc64. */ EXPORT_SYMBOL(io_remap_pfn_range); +#ifdef CONFIG_COMPAT /* Solaris/SunOS binary compatibility */ -EXPORT_SYMBOL(_sigpause_common); EXPORT_SYMBOL(verify_compat_iovec); +#endif EXPORT_SYMBOL(dump_fpu); EXPORT_SYMBOL(pte_alloc_one_kernel); diff --git a/arch/sparc64/kernel/sys32.S b/arch/sparc64/kernel/sys32.S index 9cd272ac3ac..60b59375aa7 100644 --- a/arch/sparc64/kernel/sys32.S +++ b/arch/sparc64/kernel/sys32.S @@ -84,7 +84,6 @@ SIGN2(sys32_fadvise64_64, compat_sys_fadvise64_64, %o0, %o5) SIGN2(sys32_bdflush, sys_bdflush, %o0, %o1) SIGN1(sys32_mlockall, sys_mlockall, %o0) SIGN1(sys32_nfsservctl, compat_sys_nfsservctl, %o0) -SIGN1(sys32_clock_settime, compat_sys_clock_settime, %o1) SIGN1(sys32_clock_nanosleep, compat_sys_clock_nanosleep, %o1) SIGN1(sys32_timer_settime, compat_sys_timer_settime, %o1) SIGN1(sys32_io_submit, compat_sys_io_submit, %o1) diff --git a/arch/sparc64/kernel/sys_sparc32.c b/arch/sparc64/kernel/sys_sparc32.c index d4b7a100cb8..9264ccbaaaf 100644 --- a/arch/sparc64/kernel/sys_sparc32.c +++ b/arch/sparc64/kernel/sys_sparc32.c @@ -821,7 +821,7 @@ asmlinkage long sys32_utimes(char __user *filename, return -EFAULT; } - return do_utimes(filename, (tvs ? &ktvs[0] : NULL)); + return do_utimes(AT_FDCWD, filename, (tvs ? &ktvs[0] : NULL)); } /* These are here just in case some old sparc32 binary calls it. */ @@ -1003,7 +1003,7 @@ asmlinkage long sys32_adjtimex(struct timex32 __user *utp) asmlinkage long sparc32_open(const char __user *filename, int flags, int mode) { - return do_sys_open(filename, flags, mode); + return do_sys_open(AT_FDCWD, filename, flags, mode); } extern unsigned long do_mremap(unsigned long addr, diff --git a/arch/sparc64/kernel/systbls.S b/arch/sparc64/kernel/systbls.S index 98d24bc0004..2881faf3663 100644 --- a/arch/sparc64/kernel/systbls.S +++ b/arch/sparc64/kernel/systbls.S @@ -41,7 +41,7 @@ sys_call_table32: /*90*/ .word sys_dup2, sys_setfsuid, compat_sys_fcntl, sys32_select, sys_setfsgid .word sys_fsync, sys32_setpriority, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall /*100*/ .word sys32_getpriority, sys32_rt_sigreturn, sys32_rt_sigaction, sys32_rt_sigprocmask, sys32_rt_sigpending - .word compat_sys_rt_sigtimedwait, sys32_rt_sigqueueinfo, sys32_rt_sigsuspend, sys_setresuid, sys_getresuid + .word compat_sys_rt_sigtimedwait, sys32_rt_sigqueueinfo, compat_sys_rt_sigsuspend, sys_setresuid, sys_getresuid /*110*/ .word sys_setresgid, sys_getresgid, sys_setregid, sys_nis_syscall, sys_nis_syscall .word sys32_getgroups, sys32_gettimeofday, sys32_getrusage, sys_nis_syscall, sys_getcwd /*120*/ .word compat_sys_readv, compat_sys_writev, sys32_settimeofday, sys32_fchown16, sys_fchmod @@ -71,12 +71,15 @@ sys_call_table32: /*240*/ .word sys_munlockall, sys32_sched_setparam, sys32_sched_getparam, sys32_sched_setscheduler, sys32_sched_getscheduler .word sys_sched_yield, sys32_sched_get_priority_max, sys32_sched_get_priority_min, sys32_sched_rr_get_interval, compat_sys_nanosleep /*250*/ .word sys32_mremap, sys32_sysctl, sys32_getsid, sys_fdatasync, sys32_nfsservctl - .word sys_ni_syscall, sys32_clock_settime, compat_sys_clock_gettime, compat_sys_clock_getres, sys32_clock_nanosleep + .word sys_ni_syscall, compat_sys_clock_settime, compat_sys_clock_gettime, compat_sys_clock_getres, sys32_clock_nanosleep /*260*/ .word compat_sys_sched_getaffinity, compat_sys_sched_setaffinity, sys32_timer_settime, compat_sys_timer_gettime, sys_timer_getoverrun .word sys_timer_delete, compat_sys_timer_create, sys_ni_syscall, compat_sys_io_setup, sys_io_destroy /*270*/ .word sys32_io_submit, sys_io_cancel, compat_sys_io_getevents, sys32_mq_open, sys_mq_unlink .word compat_sys_mq_timedsend, compat_sys_mq_timedreceive, compat_sys_mq_notify, compat_sys_mq_getsetattr, compat_sys_waitid -/*280*/ .word sys_ni_syscall, sys_add_key, sys_request_key, sys_keyctl +/*280*/ .word sys_ni_syscall, sys_add_key, sys_request_key, sys_keyctl, compat_sys_openat + .word sys_mkdirat, sys_mknodat, sys_fchownat, compat_sys_futimesat, compat_sys_newfstatat +/*285*/ .word sys_unlinkat, sys_renameat, sys_linkat, sys_symlinkat, sys_readlinkat + .word sys_fchmodat, sys_faccessat, compat_sys_pselect6, compat_sys_ppoll #endif /* CONFIG_COMPAT */ @@ -142,7 +145,10 @@ sys_call_table: .word sys_timer_delete, sys_timer_create, sys_ni_syscall, sys_io_setup, sys_io_destroy /*270*/ .word sys_io_submit, sys_io_cancel, sys_io_getevents, sys_mq_open, sys_mq_unlink .word sys_mq_timedsend, sys_mq_timedreceive, sys_mq_notify, sys_mq_getsetattr, sys_waitid -/*280*/ .word sys_nis_syscall, sys_add_key, sys_request_key, sys_keyctl +/*280*/ .word sys_nis_syscall, sys_add_key, sys_request_key, sys_keyctl, sys_openat + .word sys_mkdirat, sys_mknodat, sys_fchownat, sys_futimesat, compat_sys_newfstatat +/*285*/ .word sys_unlinkat, sys_renameat, sys_linkat, sys_symlinkat, sys_readlinkat + .word sys_fchmodat, sys_faccessat, sys_pselect6, sys_ppoll #if defined(CONFIG_SUNOS_EMUL) || defined(CONFIG_SOLARIS_EMUL) || \ defined(CONFIG_SOLARIS_EMUL_MODULE) @@ -239,13 +245,20 @@ sunos_sys_table: /*250*/ .word sunos_nosys, sunos_nosys, sunos_nosys .word sunos_nosys, sunos_nosys, sunos_nosys .word sunos_nosys, sunos_nosys, sunos_nosys + .word sunos_nosys +/*260*/ .word sunos_nosys, sunos_nosys, sunos_nosys .word sunos_nosys, sunos_nosys, sunos_nosys .word sunos_nosys, sunos_nosys, sunos_nosys + .word sunos_nosys +/*270*/ .word sunos_nosys, sunos_nosys, sunos_nosys .word sunos_nosys, sunos_nosys, sunos_nosys .word sunos_nosys, sunos_nosys, sunos_nosys + .word sunos_nosys +/*280*/ .word sunos_nosys, sunos_nosys, sunos_nosys .word sunos_nosys, sunos_nosys, sunos_nosys .word sunos_nosys, sunos_nosys, sunos_nosys + .word sunos_nosys +/*290*/ .word sunos_nosys, sunos_nosys, sunos_nosys .word sunos_nosys, sunos_nosys, sunos_nosys .word sunos_nosys, sunos_nosys, sunos_nosys - .word sunos_nosys #endif diff --git a/arch/sparc64/kernel/time.c b/arch/sparc64/kernel/time.c index 459c8fbe02b..a22930d62ad 100644 --- a/arch/sparc64/kernel/time.c +++ b/arch/sparc64/kernel/time.c @@ -280,9 +280,9 @@ static struct sparc64_tick_ops stick_operations __read_mostly = { * Since STICK is constantly updating, we have to access it carefully. * * The sequence we use to read is: - * 1) read low - * 2) read high - * 3) read low again, if it rolled over increment high by 1 + * 1) read high + * 2) read low + * 3) read high again, if it rolled re-read both low and high again. * * Writing STICK safely is also tricky: * 1) write low to zero @@ -295,18 +295,18 @@ static struct sparc64_tick_ops stick_operations __read_mostly = { static unsigned long __hbird_read_stick(void) { unsigned long ret, tmp1, tmp2, tmp3; - unsigned long addr = HBIRD_STICK_ADDR; + unsigned long addr = HBIRD_STICK_ADDR+8; - __asm__ __volatile__("ldxa [%1] %5, %2\n\t" - "add %1, 0x8, %1\n\t" - "ldxa [%1] %5, %3\n\t" + __asm__ __volatile__("ldxa [%1] %5, %2\n" + "1:\n\t" "sub %1, 0x8, %1\n\t" + "ldxa [%1] %5, %3\n\t" + "add %1, 0x8, %1\n\t" "ldxa [%1] %5, %4\n\t" "cmp %4, %2\n\t" - "blu,a,pn %%xcc, 1f\n\t" - " add %3, 1, %3\n" - "1:\n\t" - "sllx %3, 32, %3\n\t" + "bne,a,pn %%xcc, 1b\n\t" + " mov %4, %2\n\t" + "sllx %4, 32, %4\n\t" "or %3, %4, %0\n\t" : "=&r" (ret), "=&r" (addr), "=&r" (tmp1), "=&r" (tmp2), "=&r" (tmp3) diff --git a/arch/sparc64/prom/console.c b/arch/sparc64/prom/console.c index eae5db8dda5..ac6d035dd15 100644 --- a/arch/sparc64/prom/console.c +++ b/arch/sparc64/prom/console.c @@ -99,8 +99,12 @@ prom_query_input_device(void) if (!strncmp(propb, "keyboard", 8)) return PROMDEV_ITTYA; + if (!strncmp (propb, "rsc", 3)) + return PROMDEV_IRSC; + if (strncmp (propb, "tty", 3) || !propb[3]) return PROMDEV_I_UNK; + switch (propb[3]) { case 'a': return PROMDEV_ITTYA; case 'b': return PROMDEV_ITTYB; @@ -136,8 +140,12 @@ prom_query_output_device(void) if (!strncmp(propb, "screen", 6)) return PROMDEV_OTTYA; + if (!strncmp (propb, "rsc", 3)) + return PROMDEV_ORSC; + if (strncmp (propb, "tty", 3) || !propb[3]) return PROMDEV_O_UNK; + switch (propb[3]) { case 'a': return PROMDEV_OTTYA; case 'b': return PROMDEV_OTTYB; diff --git a/arch/sparc64/solaris/entry64.S b/arch/sparc64/solaris/entry64.S index 4b6ae583c0a..eb314ed23cd 100644 --- a/arch/sparc64/solaris/entry64.S +++ b/arch/sparc64/solaris/entry64.S @@ -180,6 +180,8 @@ solaris_sigsuspend: nop call sys_sigsuspend stx %o0, [%sp + PTREGS_OFF + PT_V9_I0] + b,pt %xcc, ret_from_solaris + nop .globl solaris_getpid solaris_getpid: diff --git a/arch/um/Kconfig b/arch/um/Kconfig index 8ff3bcbce5f..5982fe2753e 100644 --- a/arch/um/Kconfig +++ b/arch/um/Kconfig @@ -143,6 +143,7 @@ config HOSTFS config HPPFS tristate "HoneyPot ProcFS (EXPERIMENTAL)" + depends on EXPERIMENTAL help hppfs (HoneyPot ProcFS) is a filesystem which allows UML /proc entries to be overridden, removed, or fabricated from the host. @@ -155,10 +156,6 @@ config HPPFS You only need this if you are setting up a UML honeypot. Otherwise, it is safe to say 'N' here. - If you are actively using it, please report any problems, since it's - getting fixed. In this moment, it is experimental on 2.6 (it works on - 2.4). - config MCONSOLE bool "Management console" default y @@ -243,8 +240,16 @@ config NEST_LEVEL Only change this if you are running nested UMLs. config HIGHMEM - bool "Highmem support" - depends on !64BIT + bool "Highmem support (EXPERIMENTAL)" + depends on !64BIT && EXPERIMENTAL + default n + help + This was used to allow UML to run with big amounts of memory. + Currently it is unstable, so if unsure say N. + + To use big amounts of memory, it is recommended to disable TT mode (i.e. + CONFIG_MODE_TT) and enable static linking (i.e. CONFIG_STATIC_LINK) - + this should allow the guest to use up to 2.75G of memory. config KERNEL_STACK_ORDER int "Kernel stack size order" @@ -269,17 +274,13 @@ endmenu source "init/Kconfig" -source "net/Kconfig" - -source "drivers/base/Kconfig" +source "drivers/block/Kconfig" source "arch/um/Kconfig.char" -source "drivers/block/Kconfig" +source "drivers/base/Kconfig" -config NETDEVICES - bool - default NET +source "net/Kconfig" source "arch/um/Kconfig.net" diff --git a/arch/um/Kconfig.i386 b/arch/um/Kconfig.i386 index c71b39a677a..ef79ed25aec 100644 --- a/arch/um/Kconfig.i386 +++ b/arch/um/Kconfig.i386 @@ -22,13 +22,17 @@ config TOP_ADDR default 0x80000000 if HOST_2G_2G config 3_LEVEL_PGTABLES - bool "Three-level pagetables" + bool "Three-level pagetables (EXPERIMENTAL)" default n + depends on EXPERIMENTAL help Three-level pagetables will let UML have more than 4G of physical memory. All the memory that can't be mapped directly will be treated as high memory. + However, this it experimental on 32-bit architectures, so if unsure say + N (on x86-64 it's automatically enabled, instead, as it's safe there). + config STUB_CODE hex default 0xbfffe000 diff --git a/arch/um/Makefile b/arch/um/Makefile index 45435ff589c..6430a638385 100644 --- a/arch/um/Makefile +++ b/arch/um/Makefile @@ -32,7 +32,7 @@ um-modes-$(CONFIG_MODE_TT) += tt um-modes-$(CONFIG_MODE_SKAS) += skas MODE_INCLUDE += $(foreach mode,$(um-modes-y),\ - -I$(srctree)/$(ARCH_DIR)/kernel/$(mode)/include) + -I$(srctree)/$(ARCH_DIR)/include/$(mode)) MAKEFILES-INCL += $(foreach mode,$(um-modes-y),\ $(srctree)/$(ARCH_DIR)/Makefile-$(mode)) diff --git a/arch/um/drivers/daemon_kern.c b/arch/um/drivers/daemon_kern.c index 30d285b266a..507e3cbac9d 100644 --- a/arch/um/drivers/daemon_kern.c +++ b/arch/um/drivers/daemon_kern.c @@ -31,6 +31,10 @@ void daemon_init(struct net_device *dev, void *data) dpri->fd = -1; dpri->control = -1; dpri->dev = dev; + /* We will free this pointer. If it contains crap we're burned. */ + dpri->ctl_addr = NULL; + dpri->data_addr = NULL; + dpri->local_addr = NULL; printk("daemon backend (uml_switch version %d) - %s:%s", SWITCH_VERSION, dpri->sock_type, dpri->ctl_sock); diff --git a/arch/um/drivers/daemon_user.c b/arch/um/drivers/daemon_user.c index 1bb085b2824..c944265955e 100644 --- a/arch/um/drivers/daemon_user.c +++ b/arch/um/drivers/daemon_user.c @@ -158,10 +158,16 @@ static void daemon_remove(void *data) struct daemon_data *pri = data; os_close_file(pri->fd); + pri->fd = -1; os_close_file(pri->control); + pri->control = -1; + kfree(pri->data_addr); + pri->data_addr = NULL; kfree(pri->ctl_addr); + pri->ctl_addr = NULL; kfree(pri->local_addr); + pri->local_addr = NULL; } int daemon_user_write(int fd, void *buf, int len, struct daemon_data *pri) diff --git a/arch/um/drivers/fd.c b/arch/um/drivers/fd.c index 3296e86a03a..c41f75e4acb 100644 --- a/arch/um/drivers/fd.c +++ b/arch/um/drivers/fd.c @@ -11,6 +11,7 @@ #include "user.h" #include "user_util.h" #include "chan_user.h" +#include "os.h" struct fd_chan { int fd; diff --git a/arch/um/drivers/net_kern.c b/arch/um/drivers/net_kern.c index fb1f9fb9b87..8ebb2241ad4 100644 --- a/arch/um/drivers/net_kern.c +++ b/arch/um/drivers/net_kern.c @@ -68,6 +68,11 @@ static int uml_net_rx(struct net_device *dev) return pkt_len; } +static void uml_dev_close(void* dev) +{ + dev_close( (struct net_device *) dev); +} + irqreturn_t uml_net_interrupt(int irq, void *dev_id, struct pt_regs *regs) { struct net_device *dev = dev_id; @@ -80,15 +85,21 @@ irqreturn_t uml_net_interrupt(int irq, void *dev_id, struct pt_regs *regs) spin_lock(&lp->lock); while((err = uml_net_rx(dev)) > 0) ; if(err < 0) { + DECLARE_WORK(close_work, uml_dev_close, dev); printk(KERN_ERR "Device '%s' read returned %d, shutting it down\n", dev->name, err); - dev_close(dev); + /* dev_close can't be called in interrupt context, and takes + * again lp->lock. + * And dev_close() can be safely called multiple times on the + * same device, since it tests for (dev->flags & IFF_UP). So + * there's no harm in delaying the device shutdown. */ + schedule_work(&close_work); goto out; } reactivate_fd(lp->fd, UM_ETH_IRQ); - out: +out: spin_unlock(&lp->lock); return(IRQ_HANDLED); } @@ -317,6 +328,11 @@ static int eth_configure(int n, void *init, char *mac, return 1; } + lp = dev->priv; + /* This points to the transport private data. It's still clear, but we + * must memset it to 0 *now*. Let's help the drivers. */ + memset(lp, 0, size); + /* sysfs register */ if (!driver_registered) { platform_driver_register(¨_net_driver); @@ -358,7 +374,6 @@ static int eth_configure(int n, void *init, char *mac, free_netdev(dev); return 1; } - lp = dev->priv; /* lp.user is the first four bytes of the transport data, which * has already been initialized. This structure assignment will diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c index 7696f8d2d89..101efd26d46 100644 --- a/arch/um/drivers/ubd_kern.c +++ b/arch/um/drivers/ubd_kern.c @@ -1103,31 +1103,33 @@ static int ubd_ioctl(struct inode * inode, struct file * file, return(-EINVAL); } -static int same_backing_files(char *from_cmdline, char *from_cow, char *cow) +static int path_requires_switch(char *from_cmdline, char *from_cow, char *cow) { struct uml_stat buf1, buf2; int err; - if(from_cmdline == NULL) return(1); - if(!strcmp(from_cmdline, from_cow)) return(1); + if(from_cmdline == NULL) + return 0; + if(!strcmp(from_cmdline, from_cow)) + return 0; err = os_stat_file(from_cmdline, &buf1); if(err < 0){ printk("Couldn't stat '%s', err = %d\n", from_cmdline, -err); - return(1); + return 0; } err = os_stat_file(from_cow, &buf2); if(err < 0){ printk("Couldn't stat '%s', err = %d\n", from_cow, -err); - return(1); + return 1; } if((buf1.ust_dev == buf2.ust_dev) && (buf1.ust_ino == buf2.ust_ino)) - return(1); + return 0; printk("Backing file mismatch - \"%s\" requested,\n" "\"%s\" specified in COW header of \"%s\"\n", from_cmdline, from_cow, cow); - return(0); + return 1; } static int backing_file_mismatch(char *file, __u64 size, time_t mtime) @@ -1189,18 +1191,19 @@ int open_ubd_file(char *file, struct openflags *openflags, unsigned long long size; __u32 version, align; char *backing_file; - int fd, err, sectorsize, same, mode = 0644; + int fd, err, sectorsize, asked_switch, mode = 0644; fd = os_open_file(file, *openflags, mode); - if(fd < 0){ - if((fd == -ENOENT) && (create_cow_out != NULL)) + if (fd < 0) { + if ((fd == -ENOENT) && (create_cow_out != NULL)) *create_cow_out = 1; - if(!openflags->w || - ((fd != -EROFS) && (fd != -EACCES))) return(fd); + if (!openflags->w || + ((fd != -EROFS) && (fd != -EACCES))) + return fd; openflags->w = 0; fd = os_open_file(file, *openflags, mode); - if(fd < 0) - return(fd); + if (fd < 0) + return fd; } err = os_lock_file(fd, openflags->w); @@ -1209,7 +1212,9 @@ int open_ubd_file(char *file, struct openflags *openflags, goto out_close; } - if(backing_file_out == NULL) return(fd); + /* Succesful return case! */ + if(backing_file_out == NULL) + return(fd); err = read_cow_header(file_reader, &fd, &version, &backing_file, &mtime, &size, §orsize, &align, bitmap_offset_out); @@ -1218,34 +1223,34 @@ int open_ubd_file(char *file, struct openflags *openflags, "errno = %d\n", file, -err); goto out_close; } - if(err) return(fd); - - if(backing_file_out == NULL) return(fd); + if(err) + return(fd); - same = same_backing_files(*backing_file_out, backing_file, file); + asked_switch = path_requires_switch(*backing_file_out, backing_file, file); - if(!same && !backing_file_mismatch(*backing_file_out, size, mtime)){ + /* Allow switching only if no mismatch. */ + if (asked_switch && !backing_file_mismatch(*backing_file_out, size, mtime)) { printk("Switching backing file to '%s'\n", *backing_file_out); err = write_cow_header(file, fd, *backing_file_out, sectorsize, align, &size); - if(err){ + if (err) { printk("Switch failed, errno = %d\n", -err); - return(err); + goto out_close; } - } - else { + } else { *backing_file_out = backing_file; err = backing_file_mismatch(*backing_file_out, size, mtime); - if(err) goto out_close; + if (err) + goto out_close; } cow_sizes(version, size, sectorsize, align, *bitmap_offset_out, bitmap_len_out, data_offset_out); - return(fd); + return fd; out_close: os_close_file(fd); - return(err); + return err; } int create_cow_file(char *cow_file, char *backing_file, struct openflags flags, diff --git a/arch/um/include/kern_util.h b/arch/um/include/kern_util.h index 8f4e46d677a..c649108a9e9 100644 --- a/arch/um/include/kern_util.h +++ b/arch/um/include/kern_util.h @@ -120,8 +120,10 @@ extern void machine_halt(void); extern int is_syscall(unsigned long addr); extern void arch_switch(void); extern void free_irq(unsigned int, void *); -extern int um_in_interrupt(void); extern int cpu(void); + +/* Are we disallowed to sleep? Used to choose between GFP_KERNEL and GFP_ATOMIC. */ +extern int __cant_sleep(void); extern void segv_handler(int sig, union uml_pt_regs *regs); extern void sigio_handler(int sig, union uml_pt_regs *regs); diff --git a/arch/um/include/longjmp.h b/arch/um/include/longjmp.h new file mode 100644 index 00000000000..018b3819ab0 --- /dev/null +++ b/arch/um/include/longjmp.h @@ -0,0 +1,19 @@ +#ifndef __UML_LONGJMP_H +#define __UML_LONGJMP_H + +#include <setjmp.h> +#include "os.h" + +#define UML_SIGLONGJMP(buf, val) do { \ + longjmp(*buf, val); \ +} while(0) + +#define UML_SIGSETJMP(buf, enable) ({ \ + int n; \ + enable = get_signals(); \ + n = setjmp(*buf); \ + if(n != 0) \ + set_signals(enable); \ + n; }) + +#endif diff --git a/arch/um/include/mode_kern.h b/arch/um/include/mode_kern.h index 2d88afd0cf1..e7539a8451e 100644 --- a/arch/um/include/mode_kern.h +++ b/arch/um/include/mode_kern.h @@ -9,22 +9,11 @@ #include "linux/config.h" #ifdef CONFIG_MODE_TT -#include "mode_kern-tt.h" +#include "mode_kern_tt.h" #endif #ifdef CONFIG_MODE_SKAS -#include "mode_kern-skas.h" +#include "mode_kern_skas.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/os.h b/arch/um/include/os.h index dd72d66cf0e..eb1710b8125 100644 --- a/arch/um/include/os.h +++ b/arch/um/include/os.h @@ -11,6 +11,7 @@ #include "../os/include/file.h" #include "sysdep/ptrace.h" #include "kern_util.h" +#include "skas/mm_id.h" #define OS_TYPE_FILE 1 #define OS_TYPE_DIR 2 @@ -190,11 +191,12 @@ extern int os_protect_memory(void *addr, unsigned long len, int r, int w, int x); extern int os_unmap_memory(void *addr, int len); extern void os_flush_stdout(void); -extern unsigned long long os_usecs(void); /* tt.c * for tt mode only (will be deleted in future...) */ +extern void stop(void); +extern int wait_for_stop(int pid, int sig, int cont_type, void *relay); extern int protect_memory(unsigned long addr, unsigned long len, int r, int w, int x, int must_succeed); extern void forward_pending_sigio(int target); @@ -230,9 +232,63 @@ extern void block_signals(void); extern void unblock_signals(void); extern int get_signals(void); extern int set_signals(int enable); +extern void os_usr1_signal(int on); /* trap.c */ extern void os_fill_handlinfo(struct kern_handlers h); extern void do_longjmp(void *p, int val); +/* util.c */ +extern void stack_protections(unsigned long address); +extern void task_protections(unsigned long address); +extern int raw(int fd); +extern void setup_machinename(char *machine_out); +extern void setup_hostinfo(void); +extern int setjmp_wrapper(void (*proc)(void *, void *), ...); + +/* time.c */ +#define BILLION (1000 * 1000 * 1000) + +extern void switch_timers(int to_real); +extern void idle_sleep(int secs); +extern void enable_timer(void); +extern void disable_timer(void); +extern void user_time_init(void); +extern void uml_idle_timer(void); +extern unsigned long long os_nsecs(void); + +/* skas/mem.c */ +extern long run_syscall_stub(struct mm_id * mm_idp, + int syscall, unsigned long *args, long expected, + void **addr, int done); +extern long syscall_stub_data(struct mm_id * mm_idp, + unsigned long *data, int data_count, + void **addr, void **stub_addr); +extern int map(struct mm_id * mm_idp, unsigned long virt, + unsigned long len, int r, int w, int x, int phys_fd, + unsigned long long offset, int done, void **data); +extern int unmap(struct mm_id * mm_idp, void *addr, unsigned long len, + int done, void **data); +extern int protect(struct mm_id * mm_idp, unsigned long addr, + unsigned long len, int r, int w, int x, int done, + void **data); + +/* skas/process.c */ +extern int is_skas_winch(int pid, int fd, void *data); +extern int start_userspace(unsigned long stub_stack); +extern int copy_context_skas0(unsigned long stack, int pid); +extern void userspace(union uml_pt_regs *regs); +extern void map_stub_pages(int fd, unsigned long code, + unsigned long data, unsigned long stack); +extern void new_thread(void *stack, void **switch_buf_ptr, + void **fork_buf_ptr, void (*handler)(int)); +extern void thread_wait(void *sw, void *fb); +extern void switch_threads(void *me, void *next); +extern int start_idle_thread(void *stack, void *switch_buf_ptr, + void **fork_buf_ptr); +extern void initial_thread_cb_skas(void (*proc)(void *), + void *arg); +extern void halt_skas(void); +extern void reboot_skas(void); + #endif diff --git a/arch/um/kernel/skas/include/mm_id.h b/arch/um/include/skas/mm_id.h index 48dd0989dda..48dd0989dda 100644 --- a/arch/um/kernel/skas/include/mm_id.h +++ b/arch/um/include/skas/mm_id.h diff --git a/arch/um/include/skas/mmu-skas.h b/arch/um/include/skas/mmu-skas.h new file mode 100644 index 00000000000..d8869a6ef1b --- /dev/null +++ b/arch/um/include/skas/mmu-skas.h @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) + * Licensed under the GPL + */ + +#ifndef __SKAS_MMU_H +#define __SKAS_MMU_H + +#include "linux/config.h" +#include "mm_id.h" +#include "asm/ldt.h" + +struct mmu_context_skas { + struct mm_id id; + unsigned long last_page_table; +#ifdef CONFIG_3_LEVEL_PGTABLES + unsigned long last_pmd; +#endif + uml_ldt_t ldt; +}; + +extern void switch_mm_skas(struct mm_id * mm_idp); + +#endif diff --git a/arch/um/include/skas/mode-skas.h b/arch/um/include/skas/mode-skas.h new file mode 100644 index 00000000000..260065cfeef --- /dev/null +++ b/arch/um/include/skas/mode-skas.h @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) + * Licensed under the GPL + */ + +#ifndef __MODE_SKAS_H__ +#define __MODE_SKAS_H__ + +#include <sysdep/ptrace.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 sig_handler_common_skas(int sig, void *sc_ptr); +extern void kill_off_processes_skas(void); + +#endif diff --git a/arch/um/kernel/skas/include/mode_kern-skas.h b/arch/um/include/skas/mode_kern_skas.h index c97a80dfe37..63c58739bde 100644 --- a/arch/um/kernel/skas/include/mode_kern-skas.h +++ b/arch/um/include/skas/mode_kern_skas.h @@ -18,7 +18,6 @@ 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 initial_thread_cb_skas(void (*proc)(void *), void *arg); extern void init_idle_skas(void); extern void flush_tlb_kernel_range_skas(unsigned long start, unsigned long end); @@ -39,14 +38,3 @@ extern int thread_pid_skas(struct task_struct *task); #define kmem_end_skas (host_task_size - 1024 * 1024) #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/include/skas/proc_mm.h index cce61a67905..90280920960 100644 --- a/arch/um/kernel/skas/include/proc_mm.h +++ b/arch/um/include/skas/proc_mm.h @@ -1,4 +1,4 @@ -/* +/* * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) * Licensed under the GPL */ @@ -22,13 +22,13 @@ struct mm_mmap { struct mm_munmap { unsigned long addr; - unsigned long len; + unsigned long len; }; struct mm_mprotect { unsigned long addr; unsigned long len; - unsigned int prot; + unsigned int prot; }; struct proc_mm_op { @@ -42,14 +42,3 @@ struct proc_mm_op { }; #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/skas/skas.h b/arch/um/include/skas/skas.h new file mode 100644 index 00000000000..86357282d68 --- /dev/null +++ b/arch/um/include/skas/skas.h @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) + * Licensed under the GPL + */ + +#ifndef __SKAS_H +#define __SKAS_H + +#include "mm_id.h" +#include "sysdep/ptrace.h" + +extern int userspace_pid[]; +extern int proc_mm, ptrace_faultinfo, ptrace_ldt; +extern int skas_needs_stub; + +extern int user_thread(unsigned long stack, int flags); +extern void new_thread_proc(void *stack, void (*handler)(int sig)); +extern void new_thread_handler(int sig); +extern void handle_syscall(union uml_pt_regs *regs); +extern void user_signal(int sig, union uml_pt_regs *regs, int pid); +extern int new_mm(unsigned long stack); +extern void get_skas_faultinfo(int pid, struct faultinfo * fi); +extern long execute_syscall_skas(void *r); +extern unsigned long current_stub_stack(void); + +#endif diff --git a/arch/um/kernel/skas/include/stub-data.h b/arch/um/include/skas/stub-data.h index f6ed92c3727..f6ed92c3727 100644 --- a/arch/um/kernel/skas/include/stub-data.h +++ b/arch/um/include/skas/stub-data.h diff --git a/arch/um/kernel/skas/include/uaccess-skas.h b/arch/um/include/skas/uaccess-skas.h index 64516c556cd..224a75f4c02 100644 --- a/arch/um/kernel/skas/include/uaccess-skas.h +++ b/arch/um/include/skas/uaccess-skas.h @@ -19,14 +19,3 @@ extern int clear_user_skas(void __user *mem, int len); extern int strnlen_user_skas(const void __user *str, int 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/time_user.h b/arch/um/include/time_user.h deleted file mode 100644 index 17d7ef2141f..00000000000 --- a/arch/um/include/time_user.h +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) - * Licensed under the GPL - */ - -#ifndef __TIME_USER_H__ -#define __TIME_USER_H__ - -extern void timer(void); -extern void switch_timers(int to_real); -extern void idle_sleep(int secs); -extern void enable_timer(void); -extern void prepare_timer(void * ptr); -extern void disable_timer(void); -extern unsigned long time_lock(void); -extern void time_unlock(unsigned long); -extern void user_time_init(void); - -#endif diff --git a/arch/um/kernel/tt/include/debug.h b/arch/um/include/tt/debug.h index 738435461e1..9778fa83829 100644 --- a/arch/um/kernel/tt/include/debug.h +++ b/arch/um/include/tt/debug.h @@ -1,4 +1,4 @@ -/* +/* * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) and * Lars Brinkhoff. * Licensed under the GPL diff --git a/arch/um/include/tt/mmu-tt.h b/arch/um/include/tt/mmu-tt.h new file mode 100644 index 00000000000..572a78b2258 --- /dev/null +++ b/arch/um/include/tt/mmu-tt.h @@ -0,0 +1,12 @@ +/* + * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) + * Licensed under the GPL + */ + +#ifndef __TT_MMU_H +#define __TT_MMU_H + +struct mmu_context_tt { +}; + +#endif diff --git a/arch/um/include/tt/mode-tt.h b/arch/um/include/tt/mode-tt.h new file mode 100644 index 00000000000..2823cd56eea --- /dev/null +++ b/arch/um/include/tt/mode-tt.h @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) + * Licensed under the GPL + */ + +#ifndef __MODE_TT_H__ +#define __MODE_TT_H__ + +#include "sysdep/ptrace.h" + +enum { OP_NONE, OP_EXEC, OP_FORK, OP_TRACE_ON, OP_REBOOT, OP_HALT, OP_CB }; + +extern int tracing_pid; + +extern int tracer(int (*init_proc)(void *), void *sp); +extern void sig_handler_common_tt(int sig, void *sc); +extern void syscall_handler_tt(int sig, union 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 diff --git a/arch/um/include/tt/mode_kern_tt.h b/arch/um/include/tt/mode_kern_tt.h new file mode 100644 index 00000000000..efa0012550d --- /dev/null +++ b/arch/um/include/tt/mode_kern_tt.h @@ -0,0 +1,41 @@ +/* + * 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 initial_thread_cb_tt(void (*proc)(void *), void *arg); +extern void init_idle_tt(void); +extern void flush_tlb_kernel_range_tt(unsigned long start, unsigned long end); +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 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 diff --git a/arch/um/kernel/tt/include/tt.h b/arch/um/include/tt/tt.h index c667b67af40..80852198018 100644 --- a/arch/um/kernel/tt/include/tt.h +++ b/arch/um/include/tt/tt.h @@ -1,4 +1,4 @@ -/* +/* * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) * Licensed under the GPL */ @@ -34,13 +34,3 @@ extern long execute_syscall_tt(void *r); #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-tt.h b/arch/um/include/tt/uaccess-tt.h index b9bfe9c481c..b19645f32f2 100644 --- a/arch/um/kernel/tt/include/uaccess-tt.h +++ b/arch/um/include/tt/uaccess-tt.h @@ -46,14 +46,3 @@ extern int clear_user_tt(void __user *mem, int len); extern int strnlen_user_tt(const void __user *str, int 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.h b/arch/um/include/user.h index 0f865ef4691..91b0ac4ad88 100644 --- a/arch/um/include/user.h +++ b/arch/um/include/user.h @@ -18,6 +18,7 @@ extern int open_gdb_chan(void); extern unsigned long strlcpy(char *, const char *, unsigned long); extern unsigned long strlcat(char *, const char *, unsigned long); extern void *um_vmalloc(int size); +extern void *um_vmalloc_atomic(int size); extern void vfree(void *ptr); #endif diff --git a/arch/um/include/user_util.h b/arch/um/include/user_util.h index c1dbd77b073..a6f1f176cf8 100644 --- a/arch/um/include/user_util.h +++ b/arch/um/include/user_util.h @@ -44,10 +44,6 @@ extern unsigned long brk_start; extern int pty_output_sigio; 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 wait_for_stop(int pid, int sig, int cont_type, void *relay); extern void *add_signal_handler(int sig, void (*handler)(int)); extern int linux_main(int argc, char **argv); extern void set_cmdline(char *cmd); @@ -55,8 +51,6 @@ extern void input_cb(void (*proc)(void *), void *arg, int arg_len); extern int get_pty(void); extern void *um_kmalloc(int size); extern int 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 do_exec(int old_pid, int new_pid); extern void tracer_panic(char *msg, ...); extern int detach(int pid, int sig); @@ -70,18 +64,6 @@ extern int cpu_feature(char *what, char *buf, int len); extern int arch_handle_signal(int sig, union uml_pt_regs *regs); extern int arch_fixup(unsigned long address, void *sc_ptr); extern void arch_init_thread(void); -extern int setjmp_wrapper(void (*proc)(void *, void *), ...); extern int raw(int 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/Makefile b/arch/um/kernel/Makefile index 193cc2b7448..693018ba80f 100644 --- a/arch/um/kernel/Makefile +++ b/arch/um/kernel/Makefile @@ -9,9 +9,8 @@ clean-files := obj-y = config.o exec_kern.o exitcode.o \ init_task.o irq.o irq_user.o ksyms.o mem.o physmem.o \ process_kern.o ptrace.o reboot.o resource.o sigio_user.o sigio_kern.o \ - signal_kern.o smp.o syscall_kern.o sysrq.o time.o \ - time_kern.o tlb.o trap_kern.o uaccess.o um_arch.o umid.o \ - user_util.o + signal_kern.o smp.o syscall_kern.o sysrq.o \ + time_kern.o tlb.o trap_kern.o uaccess.o um_arch.o umid.o obj-$(CONFIG_BLK_DEV_INITRD) += initrd.o obj-$(CONFIG_GPROF) += gprof_syms.o @@ -24,7 +23,7 @@ obj-$(CONFIG_MODE_SKAS) += skas/ user-objs-$(CONFIG_TTY_LOG) += tty_log.o -USER_OBJS := $(user-objs-y) config.o time.o tty_log.o user_util.o +USER_OBJS := $(user-objs-y) config.o tty_log.o include arch/um/scripts/Makefile.rules diff --git a/arch/um/kernel/exec_kern.c b/arch/um/kernel/exec_kern.c index efd222ffe20..569fe8b9b05 100644 --- a/arch/um/kernel/exec_kern.c +++ b/arch/um/kernel/exec_kern.c @@ -17,7 +17,6 @@ #include "irq_user.h" #include "tlb.h" #include "os.h" -#include "time_user.h" #include "choose-mode.h" #include "mode_kern.h" diff --git a/arch/um/kernel/process_kern.c b/arch/um/kernel/process_kern.c index 7f13b85d265..3113cab8675 100644 --- a/arch/um/kernel/process_kern.c +++ b/arch/um/kernel/process_kern.c @@ -39,7 +39,6 @@ #include "init.h" #include "irq_user.h" #include "mem_user.h" -#include "time_user.h" #include "tlb.h" #include "frame_kern.h" #include "sigcontext.h" @@ -288,17 +287,27 @@ EXPORT_SYMBOL(disable_hlt); void *um_kmalloc(int size) { - return(kmalloc(size, GFP_KERNEL)); + return kmalloc(size, GFP_KERNEL); } void *um_kmalloc_atomic(int size) { - return(kmalloc(size, GFP_ATOMIC)); + return kmalloc(size, GFP_ATOMIC); } void *um_vmalloc(int size) { - return(vmalloc(size)); + return vmalloc(size); +} + +void *um_vmalloc_atomic(int size) +{ + return __vmalloc(size, GFP_ATOMIC | __GFP_HIGHMEM, PAGE_KERNEL); +} + +int __cant_sleep(void) { + return in_atomic() || irqs_disabled() || in_interrupt(); + /* Is in_interrupt() really needed? */ } unsigned long get_fault_addr(void) @@ -370,11 +379,6 @@ int smp_sigio_handler(void) return(0); } -int um_in_interrupt(void) -{ - return(in_interrupt()); -} - int cpu(void) { return(current_thread->cpu); diff --git a/arch/um/kernel/sigio_user.c b/arch/um/kernel/sigio_user.c index 62e5cfdf218..f7b18e157d3 100644 --- a/arch/um/kernel/sigio_user.c +++ b/arch/um/kernel/sigio_user.c @@ -337,70 +337,103 @@ int ignore_sigio_fd(int fd) return(err); } -static int setup_initial_poll(int fd) +static struct pollfd* setup_initial_poll(int fd) { struct pollfd *p; - p = um_kmalloc_atomic(sizeof(struct pollfd)); - if(p == NULL){ + p = um_kmalloc(sizeof(struct pollfd)); + if (p == NULL) { printk("setup_initial_poll : failed to allocate poll\n"); - return(-1); + return NULL; } *p = ((struct pollfd) { .fd = fd, .events = POLLIN, .revents = 0 }); - current_poll = ((struct pollfds) { .poll = p, - .used = 1, - .size = 1 }); - return(0); + return p; } void write_sigio_workaround(void) { unsigned long stack; + struct pollfd *p; int err; + int l_write_sigio_fds[2]; + int l_sigio_private[2]; + int l_write_sigio_pid; + /* We call this *tons* of times - and most ones we must just fail. */ sigio_lock(); - if(write_sigio_pid != -1) - goto out; + l_write_sigio_pid = write_sigio_pid; + sigio_unlock(); - err = os_pipe(write_sigio_fds, 1, 1); + if (l_write_sigio_pid != -1) + return; + + err = os_pipe(l_write_sigio_fds, 1, 1); if(err < 0){ printk("write_sigio_workaround - os_pipe 1 failed, " "err = %d\n", -err); - goto out; + return; } - err = os_pipe(sigio_private, 1, 1); + err = os_pipe(l_sigio_private, 1, 1); if(err < 0){ - printk("write_sigio_workaround - os_pipe 2 failed, " + printk("write_sigio_workaround - os_pipe 1 failed, " "err = %d\n", -err); goto out_close1; } - if(setup_initial_poll(sigio_private[1])) + + p = setup_initial_poll(l_sigio_private[1]); + if(!p) goto out_close2; - write_sigio_pid = run_helper_thread(write_sigio_thread, NULL, + sigio_lock(); + + /* Did we race? Don't try to optimize this, please, it's not so likely + * to happen, and no more than once at the boot. */ + if(write_sigio_pid != -1) + goto out_unlock; + + write_sigio_pid = run_helper_thread(write_sigio_thread, NULL, CLONE_FILES | CLONE_VM, &stack, 0); - if(write_sigio_pid < 0) goto out_close2; + if (write_sigio_pid < 0) + goto out_clear; - if(write_sigio_irq(write_sigio_fds[0])) + if (write_sigio_irq(l_write_sigio_fds[0])) goto out_kill; - out: + /* Success, finally. */ + memcpy(write_sigio_fds, l_write_sigio_fds, sizeof(l_write_sigio_fds)); + memcpy(sigio_private, l_sigio_private, sizeof(l_sigio_private)); + + current_poll = ((struct pollfds) { .poll = p, + .used = 1, + .size = 1 }); + sigio_unlock(); return; out_kill: - os_kill_process(write_sigio_pid, 1); + l_write_sigio_pid = write_sigio_pid; write_sigio_pid = -1; + sigio_unlock(); + /* Going to call waitpid, avoid holding the lock. */ + os_kill_process(l_write_sigio_pid, 1); + goto out_free; + + out_clear: + write_sigio_pid = -1; + out_unlock: + sigio_unlock(); + out_free: + kfree(p); out_close2: - os_close_file(sigio_private[0]); - os_close_file(sigio_private[1]); + os_close_file(l_sigio_private[0]); + os_close_file(l_sigio_private[1]); out_close1: - os_close_file(write_sigio_fds[0]); - os_close_file(write_sigio_fds[1]); - sigio_unlock(); + os_close_file(l_write_sigio_fds[0]); + os_close_file(l_write_sigio_fds[1]); + return; } int read_sigio_fd(int fd) diff --git a/arch/um/kernel/signal_kern.c b/arch/um/kernel/signal_kern.c index 7b0e0e81c16..da17b7541e0 100644 --- a/arch/um/kernel/signal_kern.c +++ b/arch/um/kernel/signal_kern.c @@ -99,31 +99,46 @@ static int handle_signal(struct pt_regs *regs, unsigned long signr, return err; } -static int kern_do_signal(struct pt_regs *regs, sigset_t *oldset) +static int kern_do_signal(struct pt_regs *regs) { struct k_sigaction ka_copy; siginfo_t info; + sigset_t *oldset; int sig, handled_sig = 0; + if (test_thread_flag(TIF_RESTORE_SIGMASK)) + oldset = ¤t->saved_sigmask; + else + oldset = ¤t->blocked; + while((sig = get_signal_to_deliver(&info, &ka_copy, regs, NULL)) > 0){ handled_sig = 1; /* Whee! Actually deliver the signal. */ - if(!handle_signal(regs, sig, &ka_copy, &info, oldset)) + if(!handle_signal(regs, sig, &ka_copy, &info, oldset)){ + /* a signal was successfully delivered; the saved + * sigmask will have been stored in the signal frame, + * and will be restored by sigreturn, so we can simply + * clear the TIF_RESTORE_SIGMASK flag */ + if (test_thread_flag(TIF_RESTORE_SIGMASK)) + clear_thread_flag(TIF_RESTORE_SIGMASK); break; + } } /* Did we come from a system call? */ if(!handled_sig && (PT_REGS_SYSCALL_NR(regs) >= 0)){ /* Restart the system call - no handlers present */ - if(PT_REGS_SYSCALL_RET(regs) == -ERESTARTNOHAND || - PT_REGS_SYSCALL_RET(regs) == -ERESTARTSYS || - PT_REGS_SYSCALL_RET(regs) == -ERESTARTNOINTR){ + switch(PT_REGS_SYSCALL_RET(regs)){ + case -ERESTARTNOHAND: + case -ERESTARTSYS: + case -ERESTARTNOINTR: PT_REGS_ORIG_SYSCALL(regs) = PT_REGS_SYSCALL_NR(regs); PT_REGS_RESTART_SYSCALL(regs); - } - else if(PT_REGS_SYSCALL_RET(regs) == -ERESTART_RESTARTBLOCK){ + break; + case -ERESTART_RESTARTBLOCK: PT_REGS_SYSCALL_RET(regs) = __NR_restart_syscall; PT_REGS_RESTART_SYSCALL(regs); + break; } } @@ -137,12 +152,19 @@ static int kern_do_signal(struct pt_regs *regs, sigset_t *oldset) if(current->ptrace & PT_DTRACE) current->thread.singlestep_syscall = is_syscall(PT_REGS_IP(¤t->thread.regs)); + + /* if there's no signal to deliver, we just put the saved sigmask + * back */ + if (!handled_sig && test_thread_flag(TIF_RESTORE_SIGMASK)) { + clear_thread_flag(TIF_RESTORE_SIGMASK); + sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); + } return(handled_sig); } int do_signal(void) { - return(kern_do_signal(¤t->thread.regs, ¤t->blocked)); + return(kern_do_signal(¤t->thread.regs)); } /* @@ -150,63 +172,20 @@ int do_signal(void) */ long sys_sigsuspend(int history0, int history1, old_sigset_t mask) { - sigset_t saveset; - mask &= _BLOCKABLE; spin_lock_irq(¤t->sighand->siglock); - saveset = current->blocked; + current->saved_sigmask = current->blocked; siginitset(¤t->blocked, mask); recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); - PT_REGS_SYSCALL_RET(¤t->thread.regs) = -EINTR; - while (1) { - current->state = TASK_INTERRUPTIBLE; - schedule(); - if(kern_do_signal(¤t->thread.regs, &saveset)) - return(-EINTR); - } -} - -long sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize) -{ - sigset_t saveset, newset; - - /* XXX: Don't preclude handling different sized sigset_t's. */ - if (sigsetsize != sizeof(sigset_t)) - return -EINVAL; - - if (copy_from_user(&newset, unewset, sizeof(newset))) - return -EFAULT; - sigdelsetmask(&newset, ~_BLOCKABLE); - - spin_lock_irq(¤t->sighand->siglock); - saveset = current->blocked; - current->blocked = newset; - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); - - PT_REGS_SYSCALL_RET(¤t->thread.regs) = -EINTR; - while (1) { - current->state = TASK_INTERRUPTIBLE; - schedule(); - if (kern_do_signal(¤t->thread.regs, &saveset)) - return(-EINTR); - } + current->state = TASK_INTERRUPTIBLE; + schedule(); + set_thread_flag(TIF_RESTORE_SIGMASK); + return -ERESTARTNOHAND; } long sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss) { return(do_sigaltstack(uss, uoss, PT_REGS_SP(¤t->thread.regs))); } - -/* - * 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/Makefile b/arch/um/kernel/skas/Makefile index 7a9fc16d71d..57181a920d4 100644 --- a/arch/um/kernel/skas/Makefile +++ b/arch/um/kernel/skas/Makefile @@ -1,12 +1,12 @@ -# +# # Copyright (C) 2002 - 2004 Jeff Dike (jdike@addtoit.com) # Licensed under the GPL # -obj-y := clone.o exec_kern.o mem.o mem_user.o mmu.o process.o process_kern.o \ +obj-y := clone.o exec_kern.o mem.o mmu.o process_kern.o \ syscall.o tlb.o uaccess.o -USER_OBJS := process.o clone.o +USER_OBJS := clone.o include arch/um/scripts/Makefile.rules diff --git a/arch/um/kernel/skas/include/mmu-skas.h b/arch/um/kernel/skas/include/mmu-skas.h deleted file mode 100644 index 44110c521e4..00000000000 --- a/arch/um/kernel/skas/include/mmu-skas.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) - * Licensed under the GPL - */ - -#ifndef __SKAS_MMU_H -#define __SKAS_MMU_H - -#include "linux/config.h" -#include "mm_id.h" -#include "asm/ldt.h" - -struct mmu_context_skas { - struct mm_id id; - unsigned long last_page_table; -#ifdef CONFIG_3_LEVEL_PGTABLES - unsigned long last_pmd; -#endif - uml_ldt_t ldt; -}; - -extern void switch_mm_skas(struct mm_id * mm_idp); - -#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-skas.h b/arch/um/kernel/skas/include/mode-skas.h deleted file mode 100644 index bcd26a6a388..00000000000 --- a/arch/um/kernel/skas/include/mode-skas.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) - * Licensed under the GPL - */ - -#ifndef __MODE_SKAS_H__ -#define __MODE_SKAS_H__ - -#include <sysdep/ptrace.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 sig_handler_common_skas(int sig, void *sc_ptr); -extern void halt_skas(void); -extern void reboot_skas(void); -extern void kill_off_processes_skas(void); -extern int is_skas_winch(int pid, int fd, void *data); - -#endif - -/* - * 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 deleted file mode 100644 index 01d489de398..00000000000 --- a/arch/um/kernel/skas/include/skas.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) - * Licensed under the GPL - */ - -#ifndef __SKAS_H -#define __SKAS_H - -#include "mm_id.h" -#include "sysdep/ptrace.h" - -extern int userspace_pid[]; -extern int proc_mm, ptrace_faultinfo, ptrace_ldt; -extern int skas_needs_stub; - -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(union uml_pt_regs *regs); -extern void new_thread_proc(void *stack, void (*handler)(int sig)); -extern void new_thread_handler(int sig); -extern void handle_syscall(union uml_pt_regs *regs); -extern int map(struct mm_id * mm_idp, unsigned long virt, - unsigned long len, int r, int w, int x, int phys_fd, - unsigned long long offset, int done, void **data); -extern int unmap(struct mm_id * mm_idp, void *addr, unsigned long len, - int done, void **data); -extern int protect(struct mm_id * mm_idp, unsigned long addr, - unsigned long len, int r, int w, int x, int done, - void **data); -extern void user_signal(int sig, union uml_pt_regs *regs, int pid); -extern int new_mm(int from, unsigned long stack); -extern int start_userspace(unsigned long stub_stack); -extern int copy_context_skas0(unsigned long stack, int pid); -extern void get_skas_faultinfo(int pid, struct faultinfo * fi); -extern long execute_syscall_skas(void *r); -extern unsigned long current_stub_stack(void); -extern long run_syscall_stub(struct mm_id * mm_idp, - int syscall, unsigned long *args, long expected, - void **addr, int done); -extern long syscall_stub_data(struct mm_id * mm_idp, - unsigned long *data, int data_count, - void **addr, void **stub_addr); - -#endif diff --git a/arch/um/kernel/skas/mmu.c b/arch/um/kernel/skas/mmu.c index 677871f1b37..c5c9885a829 100644 --- a/arch/um/kernel/skas/mmu.c +++ b/arch/um/kernel/skas/mmu.c @@ -78,7 +78,7 @@ int init_new_context_skas(struct task_struct *task, struct mm_struct *mm) struct mmu_context_skas *from_mm = NULL; struct mmu_context_skas *to_mm = &mm->context.skas; unsigned long stack = 0; - int from_fd, ret = -ENOMEM; + int ret = -ENOMEM; if(skas_needs_stub){ stack = get_zeroed_page(GFP_KERNEL); @@ -108,11 +108,7 @@ int init_new_context_skas(struct task_struct *task, struct mm_struct *mm) from_mm = ¤t->mm->context.skas; if(proc_mm){ - if(from_mm) - from_fd = from_mm->id.u.mm_fd; - else from_fd = -1; - - ret = new_mm(from_fd, stack); + ret = new_mm(stack); if(ret < 0){ printk("init_new_context_skas - new_mm failed, " "errno = %d\n", ret); diff --git a/arch/um/kernel/skas/process.c b/arch/um/kernel/skas/process.c index 3b3955d8440..eea1c9c4bb0 100644 --- a/arch/um/kernel/skas/process.c +++ b/arch/um/kernel/skas/process.c @@ -18,7 +18,6 @@ #include <asm/types.h> #include "user.h" #include "ptrace_user.h" -#include "time_user.h" #include "sysdep/ptrace.h" #include "user_util.h" #include "kern_util.h" diff --git a/arch/um/kernel/skas/process_kern.c b/arch/um/kernel/skas/process_kern.c index dc41c6dc2f3..3f70a2e12f0 100644 --- a/arch/um/kernel/skas/process_kern.c +++ b/arch/um/kernel/skas/process_kern.c @@ -1,4 +1,4 @@ -/* +/* * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) * Licensed under the GPL */ @@ -13,14 +13,12 @@ #include "asm/uaccess.h" #include "asm/atomic.h" #include "kern_util.h" -#include "time_user.h" #include "skas.h" #include "os.h" #include "user_util.h" #include "tlb.h" #include "kern.h" #include "mode.h" -#include "proc_mm.h" #include "registers.h" void switch_to_skas(void *prev, void *next) @@ -34,7 +32,7 @@ void switch_to_skas(void *prev, void *next) if(current->pid == 0) switch_timers(0); - switch_threads(&from->thread.mode.skas.switch_buf, + switch_threads(&from->thread.mode.skas.switch_buf, to->thread.mode.skas.switch_buf); if(current->pid == 0) @@ -50,8 +48,8 @@ void new_thread_handler(int sig) fn = current->thread.request.u.thread.proc; arg = current->thread.request.u.thread.arg; - change_sig(SIGUSR1, 1); - thread_wait(¤t->thread.mode.skas.switch_buf, + os_usr1_signal(1); + thread_wait(¤t->thread.mode.skas.switch_buf, current->thread.mode.skas.fork_buf); if(current->thread.prev_sched != NULL) @@ -82,8 +80,8 @@ void release_thread_skas(struct task_struct *task) void fork_handler(int sig) { - change_sig(SIGUSR1, 1); - thread_wait(¤t->thread.mode.skas.switch_buf, + os_usr1_signal(1); + thread_wait(¤t->thread.mode.skas.switch_buf, current->thread.mode.skas.fork_buf); force_flush_all(); @@ -93,13 +91,13 @@ void fork_handler(int sig) schedule_tail(current->thread.prev_sched); current->thread.prev_sched = NULL; - /* Handle any immediate reschedules or signals */ +/* Handle any immediate reschedules or signals */ interrupt_end(); userspace(¤t->thread.regs.regs); } int copy_thread_skas(int nr, unsigned long clone_flags, unsigned long sp, - unsigned long stack_top, struct task_struct * p, + unsigned long stack_top, struct task_struct * p, struct pt_regs *regs) { void (*handler)(int); @@ -123,27 +121,14 @@ int copy_thread_skas(int nr, unsigned long clone_flags, unsigned long sp, return(0); } -extern void map_stub_pages(int fd, unsigned long code, - unsigned long data, unsigned long stack); -int new_mm(int from, unsigned long stack) +int new_mm(unsigned long stack) { - struct proc_mm_op copy; - int n, fd; + int fd; fd = os_open_file("/proc/mm", of_cloexec(of_write(OPENFLAGS())), 0); if(fd < 0) return(fd); - if(from != -1){ - copy = ((struct proc_mm_op) { .op = MM_COPY_SEGMENTS, - .u = - { .copy_segments = from } } ); - n = os_write_file(fd, ©, sizeof(copy)); - if(n != sizeof(copy)) - printk("new_mm : /proc/mm copy_segments failed, " - "err = %d\n", -n); - } - if(skas_needs_stub) map_stub_pages(fd, CONFIG_STUB_CODE, CONFIG_STUB_DATA, stack); diff --git a/arch/um/kernel/skas/uaccess.c b/arch/um/kernel/skas/uaccess.c index a5a47528dec..5992c325716 100644 --- a/arch/um/kernel/skas/uaccess.c +++ b/arch/um/kernel/skas/uaccess.c @@ -13,7 +13,7 @@ #include "asm/pgtable.h" #include "asm/uaccess.h" #include "kern_util.h" -#include "user_util.h" +#include "os.h" extern void *um_virt_to_phys(struct task_struct *task, unsigned long addr, pte_t *pte_out); diff --git a/arch/um/kernel/syscall.c b/arch/um/kernel/syscall.c index 1429c131879..1731d90e685 100644 --- a/arch/um/kernel/syscall.c +++ b/arch/um/kernel/syscall.c @@ -25,12 +25,12 @@ int record_syscall_start(int syscall) syscall_record[index].syscall = syscall; syscall_record[index].pid = current_pid(); syscall_record[index].result = 0xdeadbeef; - syscall_record[index].start = os_usecs(); + syscall_record[index].start = os_nsecs(); return(index); } void record_syscall_end(int index, long result) { syscall_record[index].result = result; - syscall_record[index].end = os_usecs(); + syscall_record[index].end = os_nsecs(); } diff --git a/arch/um/kernel/time_kern.c b/arch/um/kernel/time_kern.c index 020ca79b8d3..3c7626cdba4 100644 --- a/arch/um/kernel/time_kern.c +++ b/arch/um/kernel/time_kern.c @@ -1,4 +1,4 @@ -/* +/* * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) * Licensed under the GPL */ @@ -13,12 +13,12 @@ #include "linux/interrupt.h" #include "linux/init.h" #include "linux/delay.h" +#include "linux/hrtimer.h" #include "asm/irq.h" #include "asm/param.h" #include "asm/current.h" #include "kern_util.h" #include "user_util.h" -#include "time_user.h" #include "mode.h" #include "os.h" @@ -39,7 +39,7 @@ unsigned long long sched_clock(void) int timer_irq_inited = 0; static int first_tick; -static unsigned long long prev_usecs; +static unsigned long long prev_nsecs; #ifdef CONFIG_UML_REAL_TIME_CLOCK static long long delta; /* Deviation per interval */ #endif @@ -58,23 +58,23 @@ void timer_irq(union uml_pt_regs *regs) if(first_tick){ #ifdef CONFIG_UML_REAL_TIME_CLOCK /* We've had 1 tick */ - unsigned long long usecs = os_usecs(); + unsigned long long nsecs = os_nsecs(); - delta += usecs - prev_usecs; - prev_usecs = usecs; + delta += nsecs - prev_nsecs; + prev_nsecs = nsecs; /* Protect against the host clock being set backwards */ if(delta < 0) delta = 0; - ticks += (delta * HZ) / MILLION; - delta -= (ticks * MILLION) / HZ; + ticks += (delta * HZ) / BILLION; + delta -= (ticks * BILLION) / HZ; #else ticks = 1; #endif } else { - prev_usecs = os_usecs(); + prev_nsecs = os_nsecs(); first_tick = 1; } @@ -84,49 +84,102 @@ void timer_irq(union uml_pt_regs *regs) } } -void boot_timer_handler(int sig) +void do_boot_timer_handler(struct sigcontext * sc) { struct pt_regs regs; - CHOOSE_MODE((void) - (UPT_SC(®s.regs) = (struct sigcontext *) (&sig + 1)), + CHOOSE_MODE((void) (UPT_SC(®s.regs) = sc), (void) (regs.regs.skas.is_user = 0)); do_timer(®s); } +static DEFINE_SPINLOCK(timer_spinlock); + +static unsigned long long local_offset = 0; + +static inline unsigned long long get_time(void) +{ + unsigned long long nsecs; + unsigned long flags; + + spin_lock_irqsave(&timer_spinlock, flags); + nsecs = os_nsecs(); + nsecs += local_offset; + spin_unlock_irqrestore(&timer_spinlock, flags); + + return nsecs; +} + irqreturn_t um_timer(int irq, void *dev, struct pt_regs *regs) { + unsigned long long nsecs; unsigned long flags; do_timer(regs); + write_seqlock_irqsave(&xtime_lock, flags); - timer(); + nsecs = get_time() + local_offset; + xtime.tv_sec = nsecs / NSEC_PER_SEC; + xtime.tv_nsec = nsecs - xtime.tv_sec * NSEC_PER_SEC; write_sequnlock_irqrestore(&xtime_lock, flags); + return(IRQ_HANDLED); } long um_time(int __user *tloc) { - struct timeval now; + long ret = get_time() / NSEC_PER_SEC; - do_gettimeofday(&now); - if (tloc) { - if (put_user(now.tv_sec, tloc)) - now.tv_sec = -EFAULT; - } - return now.tv_sec; + if((tloc != NULL) && put_user(ret, tloc)) + return -EFAULT; + + return ret; +} + +void do_gettimeofday(struct timeval *tv) +{ + unsigned long long nsecs = get_time(); + + tv->tv_sec = nsecs / NSEC_PER_SEC; + /* Careful about calculations here - this was originally done as + * (nsecs - tv->tv_sec * NSEC_PER_SEC) / NSEC_PER_USEC + * which gave bogus (> 1000000) values. Dunno why, suspect gcc + * (4.0.0) miscompiled it, or there's a subtle 64/32-bit conversion + * problem that I missed. + */ + nsecs -= tv->tv_sec * NSEC_PER_SEC; + tv->tv_usec = (unsigned long) nsecs / NSEC_PER_USEC; +} + +static inline void set_time(unsigned long long nsecs) +{ + unsigned long long now; + unsigned long flags; + + spin_lock_irqsave(&timer_spinlock, flags); + now = os_nsecs(); + local_offset = nsecs - now; + spin_unlock_irqrestore(&timer_spinlock, flags); + + clock_was_set(); } long um_stime(int __user *tptr) { int value; - struct timespec new; if (get_user(value, tptr)) return -EFAULT; - new.tv_sec = value; - new.tv_nsec = 0; - do_settimeofday(&new); + + set_time((unsigned long long) value * NSEC_PER_SEC); + + return 0; +} + +int do_settimeofday(struct timespec *tv) +{ + set_time((unsigned long long) tv->tv_sec * NSEC_PER_SEC + tv->tv_nsec); + return 0; } @@ -134,29 +187,15 @@ void timer_handler(int sig, union uml_pt_regs *regs) { local_irq_disable(); irq_enter(); - update_process_times(CHOOSE_MODE(user_context(UPT_SP(regs)), - (regs)->skas.is_user)); + update_process_times(CHOOSE_MODE( + (UPT_SC(regs) && user_context(UPT_SP(regs))), + (regs)->skas.is_user)); irq_exit(); local_irq_enable(); if(current_thread->cpu == 0) timer_irq(regs); } -static DEFINE_SPINLOCK(timer_spinlock); - -unsigned long time_lock(void) -{ - unsigned long flags; - - spin_lock_irqsave(&timer_spinlock, flags); - return(flags); -} - -void time_unlock(unsigned long flags) -{ - spin_unlock_irqrestore(&timer_spinlock, flags); -} - int __init timer_init(void) { int err; @@ -171,14 +210,3 @@ int __init timer_init(void) } __initcall(timer_init); - -/* - * 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/exec_kern.c b/arch/um/kernel/tt/exec_kern.c index 8f40e483873..5c1e4cc1c04 100644 --- a/arch/um/kernel/tt/exec_kern.c +++ b/arch/um/kernel/tt/exec_kern.c @@ -13,7 +13,6 @@ #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" diff --git a/arch/um/kernel/tt/gdb.c b/arch/um/kernel/tt/gdb.c index 37e22d71a0d..786e4edd86c 100644 --- a/arch/um/kernel/tt/gdb.c +++ b/arch/um/kernel/tt/gdb.c @@ -20,6 +20,7 @@ #include "user_util.h" #include "tt.h" #include "sysdep/thread.h" +#include "os.h" extern int debugger_pid; extern int debugger_fd; diff --git a/arch/um/kernel/tt/include/mmu-tt.h b/arch/um/kernel/tt/include/mmu-tt.h deleted file mode 100644 index 0440510ab3f..00000000000 --- a/arch/um/kernel/tt/include/mmu-tt.h +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) - * Licensed under the GPL - */ - -#ifndef __TT_MMU_H -#define __TT_MMU_H - -struct mmu_context_tt { -}; - -#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/process_kern.c b/arch/um/kernel/tt/process_kern.c index 62535303aa2..295c1ac817b 100644 --- a/arch/um/kernel/tt/process_kern.c +++ b/arch/um/kernel/tt/process_kern.c @@ -18,7 +18,6 @@ #include "os.h" #include "kern.h" #include "sigcontext.h" -#include "time_user.h" #include "mem_user.h" #include "tlb.h" #include "mode.h" diff --git a/arch/um/kernel/tt/ptproxy/ptrace.c b/arch/um/kernel/tt/ptproxy/ptrace.c index 528a5fc8d88..03774427d46 100644 --- a/arch/um/kernel/tt/ptproxy/ptrace.c +++ b/arch/um/kernel/tt/ptproxy/ptrace.c @@ -20,6 +20,7 @@ Jeff Dike (jdike@karaya.com) : Modified for integration into uml #include "kern_util.h" #include "ptrace_user.h" #include "tt.h" +#include "os.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/kernel/tt/ptproxy/sysdep.c b/arch/um/kernel/tt/ptproxy/sysdep.c index a5f0e01e214..99f178319d0 100644 --- a/arch/um/kernel/tt/ptproxy/sysdep.c +++ b/arch/um/kernel/tt/ptproxy/sysdep.c @@ -15,6 +15,7 @@ terms and conditions. #include "ptrace_user.h" #include "user_util.h" #include "user.h" +#include "os.h" int get_syscall(pid_t pid, long *arg1, long *arg2, long *arg3, long *arg4, long *arg5) diff --git a/arch/um/kernel/tt/trap_user.c b/arch/um/kernel/tt/trap_user.c index a414c529fbc..b5d9d64d91e 100644 --- a/arch/um/kernel/tt/trap_user.c +++ b/arch/um/kernel/tt/trap_user.c @@ -18,7 +18,7 @@ void sig_handler_common_tt(int sig, void *sc_ptr) { struct sigcontext *sc = sc_ptr; struct tt_regs save_regs, *r; - int save_errno = errno, is_user; + int save_errno = errno, is_user = 0; void (*handler)(int, union uml_pt_regs *); /* This is done because to allow SIGSEGV to be delivered inside a SEGV @@ -35,7 +35,8 @@ void sig_handler_common_tt(int sig, void *sc_ptr) GET_FAULTINFO_FROM_SC(r->faultinfo, sc); } save_regs = *r; - is_user = user_context(SC_SP(sc)); + if (sc) + is_user = user_context(SC_SP(sc)); r->sc = sc; if(sig != SIGUSR2) r->syscall = -1; diff --git a/arch/um/os-Linux/Makefile b/arch/um/os-Linux/Makefile index 40c7d6b1df6..08a4e628b24 100644 --- a/arch/um/os-Linux/Makefile +++ b/arch/um/os-Linux/Makefile @@ -5,12 +5,12 @@ obj-y = aio.o elf_aux.o file.o helper.o main.o mem.o process.o signal.o \ start_up.o time.o trap.o tt.o tty.o uaccess.o umid.o user_syms.o \ - drivers/ sys-$(SUBARCH)/ + util.o drivers/ sys-$(SUBARCH)/ obj-$(CONFIG_MODE_SKAS) += skas/ USER_OBJS := aio.o elf_aux.o file.o helper.o main.o mem.o process.o signal.o \ - start_up.o time.o trap.o tt.o tty.o uaccess.o umid.o + start_up.o time.o trap.o tt.o tty.o uaccess.o umid.o util.o elf_aux.o: $(ARCH_DIR)/kernel-offsets.h CFLAGS_elf_aux.o += -I$(objtree)/arch/um diff --git a/arch/um/os-Linux/helper.c b/arch/um/os-Linux/helper.c index 36cc8475bcd..6490a4ff40a 100644 --- a/arch/um/os-Linux/helper.c +++ b/arch/um/os-Linux/helper.c @@ -60,7 +60,7 @@ int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv, if((stack_out != NULL) && (*stack_out != 0)) stack = *stack_out; - else stack = alloc_stack(0, um_in_interrupt()); + else stack = alloc_stack(0, __cant_sleep()); if(stack == 0) return(-ENOMEM); @@ -124,7 +124,7 @@ int run_helper_thread(int (*proc)(void *), void *arg, unsigned int flags, unsigned long stack, sp; int pid, status, err; - stack = alloc_stack(stack_order, um_in_interrupt()); + stack = alloc_stack(stack_order, __cant_sleep()); if(stack == 0) return(-ENOMEM); sp = stack + (page_size() << stack_order) - sizeof(void *); diff --git a/arch/um/os-Linux/main.c b/arch/um/os-Linux/main.c index 172c8474453..2878e89a674 100644 --- a/arch/um/os-Linux/main.c +++ b/arch/um/os-Linux/main.c @@ -16,7 +16,6 @@ #include "user_util.h" #include "kern_util.h" #include "mem_user.h" -#include "time_user.h" #include "irq_user.h" #include "user.h" #include "init.h" @@ -82,20 +81,8 @@ extern void scan_elf_aux( char **envp); int main(int argc, char **argv, char **envp) { char **new_argv; - sigset_t mask; int ret, i, err; - /* Enable all signals except SIGIO - in some environments, we can - * enter with some signals blocked - */ - - sigemptyset(&mask); - sigaddset(&mask, SIGIO); - if(sigprocmask(SIG_SETMASK, &mask, NULL) < 0){ - perror("sigprocmask"); - exit(1); - } - #ifdef UML_CONFIG_CMDLINE_ON_HOST /* Allocate memory for thread command lines */ if(argc < 2 || strlen(argv[1]) < THREAD_NAME_LEN - 1){ diff --git a/arch/um/os-Linux/process.c b/arch/um/os-Linux/process.c index 39815c6b5e4..7f5e2dac2a3 100644 --- a/arch/um/os-Linux/process.c +++ b/arch/um/os-Linux/process.c @@ -18,6 +18,7 @@ #include "process.h" #include "irq_user.h" #include "kern_util.h" +#include "longjmp.h" #define ARBITRARY_ADDR -1 #define FAILURE_PID -1 @@ -205,24 +206,13 @@ void init_new_thread_signals(int altstack) int run_kernel_thread(int (*fn)(void *), void *arg, void **jmp_ptr) { - sigjmp_buf buf; - int n; - - *jmp_ptr = &buf; - n = sigsetjmp(buf, 1); - if(n != 0) - return(n); - (*fn)(arg); - return(0); + sigjmp_buf buf; + int n, enable; + + *jmp_ptr = &buf; + n = UML_SIGSETJMP(&buf, enable); + if(n != 0) + return(n); + (*fn)(arg); + 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/os-Linux/signal.c b/arch/um/os-Linux/signal.c index c1f46a0fef1..f11b3124a0c 100644 --- a/arch/um/os-Linux/signal.c +++ b/arch/um/os-Linux/signal.c @@ -12,32 +12,66 @@ #include <string.h> #include <sys/mman.h> #include "user_util.h" -#include "kern_util.h" #include "user.h" #include "signal_kern.h" #include "sysdep/sigcontext.h" #include "sysdep/signal.h" #include "sigcontext.h" -#include "time_user.h" #include "mode.h" +#include "os.h" + +/* These are the asynchronous signals. SIGVTALRM and SIGARLM are handled + * together under SIGVTALRM_BIT. SIGPROF is excluded because we want to + * be able to profile all of UML, not just the non-critical sections. If + * profiling is not thread-safe, then that is not my problem. We can disable + * profiling when SMP is enabled in that case. + */ +#define SIGIO_BIT 0 +#define SIGIO_MASK (1 << SIGIO_BIT) + +#define SIGVTALRM_BIT 1 +#define SIGVTALRM_MASK (1 << SIGVTALRM_BIT) + +#define SIGALRM_BIT 2 +#define SIGALRM_MASK (1 << SIGALRM_BIT) + +static int signals_enabled = 1; +static int pending = 0; void sig_handler(ARCH_SIGHDLR_PARAM) { struct sigcontext *sc; + int enabled; + + /* Must be the first thing that this handler does - x86_64 stores + * the sigcontext in %rdx, and we need to save it before it has a + * chance to get trashed. + */ ARCH_GET_SIGCONTEXT(sc, sig); + + enabled = signals_enabled; + if(!enabled && (sig == SIGIO)){ + pending |= SIGIO_MASK; + return; + } + + block_signals(); + CHOOSE_MODE_PROC(sig_handler_common_tt, sig_handler_common_skas, sig, sc); + + set_signals(enabled); } extern int timer_irq_inited; -void alarm_handler(ARCH_SIGHDLR_PARAM) +static void real_alarm_handler(int sig, struct sigcontext *sc) { - struct sigcontext *sc; - - ARCH_GET_SIGCONTEXT(sc, sig); - if(!timer_irq_inited) return; + if(!timer_irq_inited){ + signals_enabled = 1; + return; + } if(sig == SIGALRM) switch_timers(0); @@ -47,6 +81,52 @@ void alarm_handler(ARCH_SIGHDLR_PARAM) if(sig == SIGALRM) switch_timers(1); + +} + +void alarm_handler(ARCH_SIGHDLR_PARAM) +{ + struct sigcontext *sc; + int enabled; + + ARCH_GET_SIGCONTEXT(sc, sig); + + enabled = signals_enabled; + if(!signals_enabled){ + if(sig == SIGVTALRM) + pending |= SIGVTALRM_MASK; + else pending |= SIGALRM_MASK; + + return; + } + + block_signals(); + + real_alarm_handler(sig, sc); + set_signals(enabled); +} + +extern void do_boot_timer_handler(struct sigcontext * sc); + +void boot_timer_handler(ARCH_SIGHDLR_PARAM) +{ + struct sigcontext *sc; + int enabled; + + ARCH_GET_SIGCONTEXT(sc, sig); + + enabled = signals_enabled; + if(!enabled){ + if(sig == SIGVTALRM) + pending |= SIGVTALRM_MASK; + else pending |= SIGALRM_MASK; + return; + } + + block_signals(); + + do_boot_timer_handler(sc); + set_signals(enabled); } void set_sigstack(void *sig_stack, int size) @@ -73,6 +153,7 @@ void set_handler(int sig, void (*handler)(int), int flags, ...) { struct sigaction action; va_list ap; + sigset_t sig_mask; int mask; va_start(ap, flags); @@ -85,7 +166,12 @@ void set_handler(int sig, void (*handler)(int), int flags, ...) action.sa_flags = flags; action.sa_restorer = NULL; if(sigaction(sig, &action, NULL) < 0) - panic("sigaction failed"); + panic("sigaction failed - errno = %d\n", errno); + + sigemptyset(&sig_mask); + sigaddset(&sig_mask, sig); + if(sigprocmask(SIG_UNBLOCK, &sig_mask, NULL) < 0) + panic("sigprocmask failed - errno = %d\n", errno); } int change_sig(int signal, int on) @@ -98,89 +184,77 @@ int change_sig(int signal, int on) return(!sigismember(&old, signal)); } -/* Both here and in set/get_signal we don't touch SIGPROF, because we must not - * disable profiling; it's safe because the profiling code does not interact - * with the kernel code at all.*/ - -static void change_signals(int type) -{ - sigset_t mask; - - sigemptyset(&mask); - sigaddset(&mask, SIGVTALRM); - sigaddset(&mask, SIGALRM); - sigaddset(&mask, SIGIO); - if(sigprocmask(type, &mask, NULL) < 0) - panic("Failed to change signal mask - errno = %d", errno); -} - void block_signals(void) { - change_signals(SIG_BLOCK); + signals_enabled = 0; } void unblock_signals(void) { - change_signals(SIG_UNBLOCK); -} + int save_pending; -/* These are the asynchronous signals. SIGVTALRM and SIGARLM are handled - * together under SIGVTALRM_BIT. SIGPROF is excluded because we want to - * be able to profile all of UML, not just the non-critical sections. If - * profiling is not thread-safe, then that is not my problem. We can disable - * profiling when SMP is enabled in that case. - */ -#define SIGIO_BIT 0 -#define SIGVTALRM_BIT 1 + if(signals_enabled == 1) + return; -static int enable_mask(sigset_t *mask) -{ - int sigs; + /* We loop because the IRQ handler returns with interrupts off. So, + * interrupts may have arrived and we need to re-enable them and + * recheck pending. + */ + while(1){ + /* Save and reset save_pending after enabling signals. This + * way, pending won't be changed while we're reading it. + */ + signals_enabled = 1; + + save_pending = pending; + if(save_pending == 0) + return; + + pending = 0; + + /* We have pending interrupts, so disable signals, as the + * handlers expect them off when they are called. They will + * be enabled again above. + */ + + signals_enabled = 0; - sigs = sigismember(mask, SIGIO) ? 0 : 1 << SIGIO_BIT; - sigs |= sigismember(mask, SIGVTALRM) ? 0 : 1 << SIGVTALRM_BIT; - sigs |= sigismember(mask, SIGALRM) ? 0 : 1 << SIGVTALRM_BIT; - return(sigs); + /* Deal with SIGIO first because the alarm handler might + * schedule, leaving the pending SIGIO stranded until we come + * back here. + */ + if(save_pending & SIGIO_MASK) + CHOOSE_MODE_PROC(sig_handler_common_tt, + sig_handler_common_skas, SIGIO, NULL); + + if(save_pending & SIGALRM_MASK) + real_alarm_handler(SIGALRM, NULL); + + if(save_pending & SIGVTALRM_MASK) + real_alarm_handler(SIGVTALRM, NULL); + } } int get_signals(void) { - sigset_t mask; - - if(sigprocmask(SIG_SETMASK, NULL, &mask) < 0) - panic("Failed to get signal mask"); - return(enable_mask(&mask)); + return signals_enabled; } int set_signals(int enable) { - sigset_t mask; int ret; + if(signals_enabled == enable) + return enable; - sigemptyset(&mask); - if(enable & (1 << SIGIO_BIT)) - sigaddset(&mask, SIGIO); - if(enable & (1 << SIGVTALRM_BIT)){ - sigaddset(&mask, SIGVTALRM); - sigaddset(&mask, SIGALRM); - } + ret = signals_enabled; + if(enable) + unblock_signals(); + else block_signals(); - /* This is safe - sigprocmask is guaranteed to copy locally the - * value of new_set, do his work and then, at the end, write to - * old_set. - */ - if(sigprocmask(SIG_UNBLOCK, &mask, &mask) < 0) - panic("Failed to enable signals"); - ret = enable_mask(&mask); - sigemptyset(&mask); - if((enable & (1 << SIGIO_BIT)) == 0) - sigaddset(&mask, SIGIO); - if((enable & (1 << SIGVTALRM_BIT)) == 0){ - sigaddset(&mask, SIGVTALRM); - sigaddset(&mask, SIGALRM); - } - if(sigprocmask(SIG_BLOCK, &mask, NULL) < 0) - panic("Failed to block signals"); + return ret; +} - return(ret); +void os_usr1_signal(int on) +{ + change_sig(SIGUSR1, on); } diff --git a/arch/um/os-Linux/skas/Makefile b/arch/um/os-Linux/skas/Makefile index eab5386d60a..5fd8d4dad66 100644 --- a/arch/um/os-Linux/skas/Makefile +++ b/arch/um/os-Linux/skas/Makefile @@ -3,8 +3,8 @@ # Licensed under the GPL # -obj-y := trap.o +obj-y := mem.o process.o trap.o -USER_OBJS := trap.o +USER_OBJS := mem.o process.o trap.o include arch/um/scripts/Makefile.rules diff --git a/arch/um/kernel/skas/mem_user.c b/arch/um/os-Linux/skas/mem.c index 1d89640bd50..9890e9090f5 100644 --- a/arch/um/kernel/skas/mem_user.c +++ b/arch/um/os-Linux/skas/mem.c @@ -1,4 +1,4 @@ -/* +/* * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) * Licensed under the GPL */ @@ -32,7 +32,7 @@ extern void wait_stub_done(int pid, int sig, char * fname); static inline unsigned long *check_init_stack(struct mm_id * mm_idp, unsigned long *stack) { - if(stack == NULL){ + if(stack == NULL) { stack = (unsigned long *) mm_idp->stack + 2; *stack = 0; } @@ -45,13 +45,14 @@ int single_count = 0; int multi_count = 0; int multi_op_count = 0; -static long do_syscall_stub(struct mm_id *mm_idp, void **addr) +static inline long do_syscall_stub(struct mm_id * mm_idp, void **addr) { unsigned long regs[MAX_REG_NR]; - unsigned long *data; - unsigned long *syscall; + int n; long ret, offset; - int n, pid = mm_idp->u.pid; + unsigned long * data; + unsigned long * syscall; + int pid = mm_idp->u.pid; if(proc_mm) #warning Need to look up userspace_pid by cpu @@ -59,10 +60,11 @@ static long do_syscall_stub(struct mm_id *mm_idp, void **addr) multi_count++; - get_safe_registers(regs); - regs[REGS_IP_INDEX] = UML_CONFIG_STUB_CODE + + get_safe_registers(regs); + regs[REGS_IP_INDEX] = UML_CONFIG_STUB_CODE + ((unsigned long) &batch_syscall_stub - - (unsigned long) &__syscall_stub_start); + (unsigned long) &__syscall_stub_start); + n = ptrace_setregs(pid, regs); if(n < 0) panic("do_syscall_stub : PTRACE_SETREGS failed, errno = %d\n", @@ -80,6 +82,8 @@ static long do_syscall_stub(struct mm_id *mm_idp, void **addr) if (offset) { data = (unsigned long *)(mm_idp->stack + offset - UML_CONFIG_STUB_DATA); + printk("do_syscall_stub : ret = %d, offset = %d, " + "data = 0x%x\n", ret, offset, data); syscall = (unsigned long *)((unsigned long)data + data[0]); printk("do_syscall_stub: syscall %ld failed, return value = " "0x%lx, expected return value = 0x%lx\n", @@ -107,32 +111,32 @@ static long do_syscall_stub(struct mm_id *mm_idp, void **addr) long run_syscall_stub(struct mm_id * mm_idp, int syscall, unsigned long *args, long expected, void **addr, - int done) + int done) { - unsigned long *stack = check_init_stack(mm_idp, *addr); + unsigned long *stack = check_init_stack(mm_idp, *addr); if(done && *addr == NULL) single_count++; - *stack += sizeof(long); + *stack += sizeof(long); stack += *stack / sizeof(long); - *stack++ = syscall; - *stack++ = args[0]; - *stack++ = args[1]; - *stack++ = args[2]; - *stack++ = args[3]; - *stack++ = args[4]; - *stack++ = args[5]; + *stack++ = syscall; + *stack++ = args[0]; + *stack++ = args[1]; + *stack++ = args[2]; + *stack++ = args[3]; + *stack++ = args[4]; + *stack++ = args[5]; *stack++ = expected; - *stack = 0; - multi_op_count++; + *stack = 0; + multi_op_count++; - if(!done && ((((unsigned long) stack) & ~PAGE_MASK) < + if(!done && ((((unsigned long) stack) & ~PAGE_MASK) < PAGE_SIZE - 10 * sizeof(long))){ *addr = stack; - return 0; - } + return 0; + } return do_syscall_stub(mm_idp, addr); } @@ -150,7 +154,7 @@ long syscall_stub_data(struct mm_id * mm_idp, if((((unsigned long) *addr) & ~PAGE_MASK) >= PAGE_SIZE - (10 + data_count) * sizeof(long)) { ret = do_syscall_stub(mm_idp, addr); - /* in case of error, don't overwrite data on stack */ + /* in case of error, don't overwrite data on stack */ if(ret) return ret; } @@ -172,39 +176,39 @@ int map(struct mm_id * mm_idp, unsigned long virt, unsigned long len, int r, int w, int x, int phys_fd, unsigned long long offset, int done, void **data) { - int prot, ret; - - prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) | - (x ? PROT_EXEC : 0); - - if(proc_mm){ - struct proc_mm_op map; - int fd = mm_idp->u.mm_fd; - - map = ((struct proc_mm_op) { .op = MM_MMAP, - .u = - { .mmap = - { .addr = virt, - .len = len, - .prot = prot, - .flags = MAP_SHARED | - MAP_FIXED, - .fd = phys_fd, - .offset= offset - } } } ); + int prot, ret; + + prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) | + (x ? PROT_EXEC : 0); + + if(proc_mm){ + struct proc_mm_op map; + int fd = mm_idp->u.mm_fd; + + map = ((struct proc_mm_op) { .op = MM_MMAP, + .u = + { .mmap = + { .addr = virt, + .len = len, + .prot = prot, + .flags = MAP_SHARED | + MAP_FIXED, + .fd = phys_fd, + .offset= offset + } } } ); ret = os_write_file(fd, &map, sizeof(map)); if(ret != sizeof(map)) printk("map : /proc/mm map failed, err = %d\n", -ret); else ret = 0; - } - else { - unsigned long args[] = { virt, len, prot, - MAP_SHARED | MAP_FIXED, phys_fd, - MMAP_OFFSET(offset) }; + } + else { + unsigned long args[] = { virt, len, prot, + MAP_SHARED | MAP_FIXED, phys_fd, + MMAP_OFFSET(offset) }; ret = run_syscall_stub(mm_idp, STUB_MMAP_NR, args, virt, data, done); - } + } return ret; } @@ -212,68 +216,66 @@ int map(struct mm_id * mm_idp, unsigned long virt, unsigned long len, int unmap(struct mm_id * mm_idp, void *addr, unsigned long len, int done, void **data) { - int ret; - - if(proc_mm){ - struct proc_mm_op unmap; - int fd = mm_idp->u.mm_fd; - - unmap = ((struct proc_mm_op) { .op = MM_MUNMAP, - .u = - { .munmap = - { .addr = - (unsigned long) addr, - .len = len } } } ); + int ret; + + if(proc_mm){ + struct proc_mm_op unmap; + int fd = mm_idp->u.mm_fd; + + unmap = ((struct proc_mm_op) { .op = MM_MUNMAP, + .u = + { .munmap = + { .addr = + (unsigned long) addr, + .len = len } } } ); ret = os_write_file(fd, &unmap, sizeof(unmap)); if(ret != sizeof(unmap)) printk("unmap - proc_mm write returned %d\n", ret); else ret = 0; - } - else { - unsigned long args[] = { (unsigned long) addr, len, 0, 0, 0, - 0 }; + } + else { + unsigned long args[] = { (unsigned long) addr, len, 0, 0, 0, + 0 }; ret = run_syscall_stub(mm_idp, __NR_munmap, args, 0, data, done); - if(ret < 0) - printk("munmap stub failed, errno = %d\n", ret); - } + } - return ret; + return ret; } int protect(struct mm_id * mm_idp, unsigned long addr, unsigned long len, int r, int w, int x, int done, void **data) { - struct proc_mm_op protect; - int prot, ret; - - prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) | - (x ? PROT_EXEC : 0); - - if(proc_mm){ - int fd = mm_idp->u.mm_fd; - protect = ((struct proc_mm_op) { .op = MM_MPROTECT, - .u = - { .mprotect = - { .addr = - (unsigned long) addr, - .len = len, - .prot = prot } } } ); - - ret = os_write_file(fd, &protect, sizeof(protect)); - if(ret != sizeof(protect)) - printk("protect failed, err = %d", -ret); - else ret = 0; - } - else { - unsigned long args[] = { addr, len, prot, 0, 0, 0 }; - - ret = run_syscall_stub(mm_idp, __NR_mprotect, args, 0, - data, done); - } - - return ret; + struct proc_mm_op protect; + int prot, ret; + + prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) | + (x ? PROT_EXEC : 0); + if(proc_mm){ + int fd = mm_idp->u.mm_fd; + + protect = ((struct proc_mm_op) { .op = MM_MPROTECT, + .u = + { .mprotect = + { .addr = + (unsigned long) addr, + .len = len, + .prot = prot } } } ); + + ret = os_write_file(fd, &protect, sizeof(protect)); + if(ret != sizeof(protect)) + printk("protect failed, err = %d", -ret); + else ret = 0; + } + else { + unsigned long args[] = { addr, len, prot, 0, 0, 0 }; + + ret = run_syscall_stub(mm_idp, __NR_mprotect, args, 0, + data, done); + } + + return ret; } void before_mem_skas(unsigned long unused) diff --git a/arch/um/os-Linux/skas/process.c b/arch/um/os-Linux/skas/process.c new file mode 100644 index 00000000000..120a21c5883 --- /dev/null +++ b/arch/um/os-Linux/skas/process.c @@ -0,0 +1,566 @@ +/* + * Copyright (C) 2002- 2004 Jeff Dike (jdike@addtoit.com) + * Licensed under the GPL + */ + +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <errno.h> +#include <signal.h> +#include <setjmp.h> +#include <sched.h> +#include "ptrace_user.h" +#include <sys/wait.h> +#include <sys/mman.h> +#include <sys/user.h> +#include <sys/time.h> +#include <asm/unistd.h> +#include <asm/types.h> +#include "user.h" +#include "sysdep/ptrace.h" +#include "user_util.h" +#include "kern_util.h" +#include "skas.h" +#include "stub-data.h" +#include "mm_id.h" +#include "sysdep/sigcontext.h" +#include "sysdep/stub.h" +#include "os.h" +#include "proc_mm.h" +#include "skas_ptrace.h" +#include "chan_user.h" +#include "registers.h" +#include "mem.h" +#include "uml-config.h" +#include "process.h" +#include "longjmp.h" + +int is_skas_winch(int pid, int fd, void *data) +{ + if(pid != os_getpgrp()) + return(0); + + register_winch_irq(-1, fd, -1, data); + return(1); +} + +void wait_stub_done(int pid, int sig, char * fname) +{ + int n, status, err; + + do { + if ( sig != -1 ) { + err = ptrace(PTRACE_CONT, pid, 0, sig); + if(err) + panic("%s : continue failed, errno = %d\n", + fname, errno); + } + sig = 0; + + CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED)); + } while((n >= 0) && WIFSTOPPED(status) && + ((WSTOPSIG(status) == SIGVTALRM) || + /* running UML inside a detached screen can cause + * SIGWINCHes + */ + (WSTOPSIG(status) == SIGWINCH))); + + if((n < 0) || !WIFSTOPPED(status) || + (WSTOPSIG(status) != SIGUSR1 && WSTOPSIG(status) != SIGTRAP)){ + unsigned long regs[HOST_FRAME_SIZE]; + + if(ptrace(PTRACE_GETREGS, pid, 0, regs) < 0) + printk("Failed to get registers from stub, " + "errno = %d\n", errno); + else { + int i; + + printk("Stub registers -\n"); + for(i = 0; i < HOST_FRAME_SIZE; i++) + printk("\t%d - %lx\n", i, regs[i]); + } + panic("%s : failed to wait for SIGUSR1/SIGTRAP, " + "pid = %d, n = %d, errno = %d, status = 0x%x\n", + fname, pid, n, errno, status); + } +} + +extern unsigned long current_stub_stack(void); + +void get_skas_faultinfo(int pid, struct faultinfo * fi) +{ + int err; + + if(ptrace_faultinfo){ + err = ptrace(PTRACE_FAULTINFO, pid, 0, fi); + if(err) + panic("get_skas_faultinfo - PTRACE_FAULTINFO failed, " + "errno = %d\n", errno); + + /* Special handling for i386, which has different structs */ + if (sizeof(struct ptrace_faultinfo) < sizeof(struct faultinfo)) + memset((char *)fi + sizeof(struct ptrace_faultinfo), 0, + sizeof(struct faultinfo) - + sizeof(struct ptrace_faultinfo)); + } + else { + wait_stub_done(pid, SIGSEGV, "get_skas_faultinfo"); + + /* faultinfo is prepared by the stub-segv-handler at start of + * the stub stack page. We just have to copy it. + */ + memcpy(fi, (void *)current_stub_stack(), sizeof(*fi)); + } +} + +static void handle_segv(int pid, union uml_pt_regs * regs) +{ + get_skas_faultinfo(pid, ®s->skas.faultinfo); + segv(regs->skas.faultinfo, 0, 1, NULL); +} + +/*To use the same value of using_sysemu as the caller, ask it that value (in local_using_sysemu)*/ +static void handle_trap(int pid, union uml_pt_regs *regs, int local_using_sysemu) +{ + int err, status; + + /* Mark this as a syscall */ + UPT_SYSCALL_NR(regs) = PT_SYSCALL_NR(regs->skas.regs); + + if (!local_using_sysemu) + { + err = ptrace(PTRACE_POKEUSR, 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); + + CATCH_EINTR(err = waitpid(pid, &status, WUNTRACED)); + if((err < 0) || !WIFSTOPPED(status) || + (WSTOPSIG(status) != SIGTRAP + 0x80)) + panic("handle_trap - failed to wait at end of syscall, " + "errno = %d, status = %d\n", errno, status); + } + + handle_syscall(regs); +} + +extern int __syscall_stub_start; + +static int userspace_tramp(void *stack) +{ + void *addr; + + ptrace(PTRACE_TRACEME, 0, 0, 0); + + init_new_thread_signals(1); + enable_timer(); + + if(!proc_mm){ + /* This has a pte, but it can't be mapped in with the usual + * tlb_flush mechanism because this is part of that mechanism + */ + int fd; + __u64 offset; + fd = phys_mapping(to_phys(&__syscall_stub_start), &offset); + addr = mmap64((void *) UML_CONFIG_STUB_CODE, page_size(), + PROT_EXEC, MAP_FIXED | MAP_PRIVATE, fd, offset); + if(addr == MAP_FAILED){ + printk("mapping mmap stub failed, errno = %d\n", + errno); + exit(1); + } + + if(stack != NULL){ + fd = phys_mapping(to_phys(stack), &offset); + addr = mmap((void *) UML_CONFIG_STUB_DATA, page_size(), + PROT_READ | PROT_WRITE, + MAP_FIXED | MAP_SHARED, fd, offset); + if(addr == MAP_FAILED){ + printk("mapping segfault stack failed, " + "errno = %d\n", errno); + exit(1); + } + } + } + if(!ptrace_faultinfo && (stack != NULL)){ + unsigned long v = UML_CONFIG_STUB_CODE + + (unsigned long) stub_segv_handler - + (unsigned long) &__syscall_stub_start; + + set_sigstack((void *) UML_CONFIG_STUB_DATA, page_size()); + set_handler(SIGSEGV, (void *) v, SA_ONSTACK, + SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, + SIGUSR1, -1); + } + + os_stop_process(os_getpid()); + return(0); +} + +/* Each element set once, and only accessed by a single processor anyway */ +#undef NR_CPUS +#define NR_CPUS 1 +int userspace_pid[NR_CPUS]; + +int start_userspace(unsigned long stub_stack) +{ + void *stack; + unsigned long sp; + int pid, status, n, flags; + + 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 *); + + flags = CLONE_FILES | SIGCHLD; + if(proc_mm) flags |= CLONE_VM; + pid = clone(userspace_tramp, (void *) sp, flags, (void *) stub_stack); + if(pid < 0) + panic("start_userspace : clone failed, errno = %d", errno); + + do { + CATCH_EINTR(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 (ptrace(PTRACE_OLDSETOPTIONS, pid, NULL, (void *)PTRACE_O_TRACESYSGOOD) < 0) + panic("start_userspace : PTRACE_OLDSETOPTIONS failed, errno=%d\n", + errno); + + if(munmap(stack, PAGE_SIZE) < 0) + panic("start_userspace : munmap failed, errno = %d\n", errno); + + return(pid); +} + +void userspace(union uml_pt_regs *regs) +{ + int err, status, op, pid = userspace_pid[0]; + int local_using_sysemu; /*To prevent races if using_sysemu changes under us.*/ + + while(1){ + restore_registers(pid, regs); + + /* Now we set local_using_sysemu to be used for one loop */ + local_using_sysemu = get_using_sysemu(); + + op = SELECT_PTRACE_OPERATION(local_using_sysemu, singlestepping(NULL)); + + err = ptrace(op, pid, 0, 0); + if(err) + panic("userspace - could not resume userspace process, " + "pid=%d, ptrace operation = %d, errno = %d\n", + op, errno); + + CATCH_EINTR(err = waitpid(pid, &status, WUNTRACED)); + if(err < 0) + panic("userspace - waitpid failed, errno = %d\n", + errno); + + regs->skas.is_user = 1; + save_registers(pid, regs); + UPT_SYSCALL_NR(regs) = -1; /* Assume: It's not a syscall */ + + if(WIFSTOPPED(status)){ + switch(WSTOPSIG(status)){ + case SIGSEGV: + if(PTRACE_FULL_FAULTINFO || !ptrace_faultinfo) + user_signal(SIGSEGV, regs, pid); + else handle_segv(pid, regs); + break; + case SIGTRAP + 0x80: + handle_trap(pid, regs, local_using_sysemu); + break; + case SIGTRAP: + relay_signal(SIGTRAP, regs); + break; + case SIGIO: + case SIGVTALRM: + case SIGILL: + case SIGBUS: + case SIGFPE: + case SIGWINCH: + user_signal(WSTOPSIG(status), regs, pid); + break; + default: + printk("userspace - child stopped with signal " + "%d\n", WSTOPSIG(status)); + } + pid = userspace_pid[0]; + interrupt_end(); + + /* Avoid -ERESTARTSYS handling in host */ + if(PT_SYSCALL_NR_OFFSET != PT_SYSCALL_RET_OFFSET) + PT_SYSCALL_NR(regs->skas.regs) = -1; + } + } +} +#define INIT_JMP_NEW_THREAD 0 +#define INIT_JMP_REMOVE_SIGSTACK 1 +#define INIT_JMP_CALLBACK 2 +#define INIT_JMP_HALT 3 +#define INIT_JMP_REBOOT 4 + +int copy_context_skas0(unsigned long new_stack, int pid) +{ + int err; + unsigned long regs[MAX_REG_NR]; + unsigned long current_stack = current_stub_stack(); + struct stub_data *data = (struct stub_data *) current_stack; + struct stub_data *child_data = (struct stub_data *) new_stack; + __u64 new_offset; + int new_fd = phys_mapping(to_phys((void *)new_stack), &new_offset); + + /* prepare offset and fd of child's stack as argument for parent's + * and child's mmap2 calls + */ + *data = ((struct stub_data) { .offset = MMAP_OFFSET(new_offset), + .fd = new_fd, + .timer = ((struct itimerval) + { { 0, 1000000 / hz() }, + { 0, 1000000 / hz() }})}); + get_safe_registers(regs); + + /* Set parent's instruction pointer to start of clone-stub */ + regs[REGS_IP_INDEX] = UML_CONFIG_STUB_CODE + + (unsigned long) stub_clone_handler - + (unsigned long) &__syscall_stub_start; + regs[REGS_SP_INDEX] = UML_CONFIG_STUB_DATA + PAGE_SIZE - + sizeof(void *); +#ifdef __SIGNAL_FRAMESIZE + regs[REGS_SP_INDEX] -= __SIGNAL_FRAMESIZE; +#endif + err = ptrace_setregs(pid, regs); + if(err < 0) + panic("copy_context_skas0 : PTRACE_SETREGS failed, " + "pid = %d, errno = %d\n", pid, errno); + + /* set a well known return code for detection of child write failure */ + child_data->err = 12345678; + + /* Wait, until parent has finished its work: read child's pid from + * parent's stack, and check, if bad result. + */ + wait_stub_done(pid, 0, "copy_context_skas0"); + + pid = data->err; + if(pid < 0) + panic("copy_context_skas0 - stub-parent reports error %d\n", + pid); + + /* Wait, until child has finished too: read child's result from + * child's stack and check it. + */ + wait_stub_done(pid, -1, "copy_context_skas0"); + if (child_data->err != UML_CONFIG_STUB_DATA) + panic("copy_context_skas0 - stub-child reports error %d\n", + child_data->err); + + if (ptrace(PTRACE_OLDSETOPTIONS, pid, NULL, + (void *)PTRACE_O_TRACESYSGOOD) < 0) + panic("copy_context_skas0 : PTRACE_OLDSETOPTIONS failed, " + "errno = %d\n", errno); + + return pid; +} + +/* + * This is used only, if stub pages are needed, while proc_mm is + * availabl. Opening /proc/mm creates a new mm_context, which lacks + * the stub-pages. Thus, we map them using /proc/mm-fd + */ +void map_stub_pages(int fd, unsigned long code, + unsigned long data, unsigned long stack) +{ + struct proc_mm_op mmop; + int n; + __u64 code_offset; + int code_fd = phys_mapping(to_phys((void *) &__syscall_stub_start), + &code_offset); + + mmop = ((struct proc_mm_op) { .op = MM_MMAP, + .u = + { .mmap = + { .addr = code, + .len = PAGE_SIZE, + .prot = PROT_EXEC, + .flags = MAP_FIXED | MAP_PRIVATE, + .fd = code_fd, + .offset = code_offset + } } }); + n = os_write_file(fd, &mmop, sizeof(mmop)); + if(n != sizeof(mmop)) + panic("map_stub_pages : /proc/mm map for code failed, " + "err = %d\n", -n); + + if ( stack ) { + __u64 map_offset; + int map_fd = phys_mapping(to_phys((void *)stack), &map_offset); + mmop = ((struct proc_mm_op) + { .op = MM_MMAP, + .u = + { .mmap = + { .addr = data, + .len = PAGE_SIZE, + .prot = PROT_READ | PROT_WRITE, + .flags = MAP_FIXED | MAP_SHARED, + .fd = map_fd, + .offset = map_offset + } } }); + n = os_write_file(fd, &mmop, sizeof(mmop)); + if(n != sizeof(mmop)) + panic("map_stub_pages : /proc/mm map for data failed, " + "err = %d\n", -n); + } +} + +void new_thread(void *stack, void **switch_buf_ptr, void **fork_buf_ptr, + void (*handler)(int)) +{ + unsigned long flags; + sigjmp_buf switch_buf, fork_buf; + int enable; + + *switch_buf_ptr = &switch_buf; + *fork_buf_ptr = &fork_buf; + + /* Somewhat subtle - siglongjmp restores the signal mask before doing + * the longjmp. This means that when jumping from one stack to another + * when the target stack has interrupts enabled, an interrupt may occur + * on the source stack. This is bad when starting up a process because + * it's not supposed to get timer ticks until it has been scheduled. + * So, we disable interrupts around the sigsetjmp to ensure that + * they can't happen until we get back here where they are safe. + */ + flags = get_signals(); + block_signals(); + if(UML_SIGSETJMP(&fork_buf, enable) == 0) + new_thread_proc(stack, handler); + + remove_sigstack(); + + set_signals(flags); +} + +void thread_wait(void *sw, void *fb) +{ + sigjmp_buf buf, **switch_buf = sw, *fork_buf; + int enable; + + *switch_buf = &buf; + fork_buf = fb; + if(UML_SIGSETJMP(&buf, enable) == 0) + siglongjmp(*fork_buf, INIT_JMP_REMOVE_SIGSTACK); +} + +void switch_threads(void *me, void *next) +{ + sigjmp_buf my_buf, **me_ptr = me, *next_buf = next; + int enable; + + *me_ptr = &my_buf; + if(UML_SIGSETJMP(&my_buf, enable) == 0) + UML_SIGLONGJMP(next_buf, 1); +} + +static sigjmp_buf initial_jmpbuf; + +/* XXX Make these percpu */ +static void (*cb_proc)(void *arg); +static void *cb_arg; +static sigjmp_buf *cb_back; + +int start_idle_thread(void *stack, void *switch_buf_ptr, void **fork_buf_ptr) +{ + sigjmp_buf **switch_buf = switch_buf_ptr; + int n, enable; + + set_handler(SIGWINCH, (__sighandler_t) sig_handler, + SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGALRM, + SIGVTALRM, -1); + + *fork_buf_ptr = &initial_jmpbuf; + n = UML_SIGSETJMP(&initial_jmpbuf, enable); + switch(n){ + case INIT_JMP_NEW_THREAD: + new_thread_proc((void *) stack, new_thread_handler); + break; + case INIT_JMP_REMOVE_SIGSTACK: + remove_sigstack(); + break; + case INIT_JMP_CALLBACK: + (*cb_proc)(cb_arg); + UML_SIGLONGJMP(cb_back, 1); + break; + case INIT_JMP_HALT: + kmalloc_ok = 0; + return(0); + case INIT_JMP_REBOOT: + kmalloc_ok = 0; + return(1); + default: + panic("Bad sigsetjmp return in start_idle_thread - %d\n", n); + } + UML_SIGLONGJMP(*switch_buf, 1); +} + +void initial_thread_cb_skas(void (*proc)(void *), void *arg) +{ + sigjmp_buf here; + int enable; + + cb_proc = proc; + cb_arg = arg; + cb_back = &here; + + block_signals(); + if(UML_SIGSETJMP(&here, enable) == 0) + UML_SIGLONGJMP(&initial_jmpbuf, INIT_JMP_CALLBACK); + unblock_signals(); + + cb_proc = NULL; + cb_arg = NULL; + cb_back = NULL; +} + +void halt_skas(void) +{ + block_signals(); + UML_SIGLONGJMP(&initial_jmpbuf, INIT_JMP_HALT); +} + +void reboot_skas(void) +{ + block_signals(); + UML_SIGLONGJMP(&initial_jmpbuf, INIT_JMP_REBOOT); +} + +void switch_mm_skas(struct mm_id *mm_idp) +{ + int err; + +#warning need cpu pid in switch_mm_skas + if(proc_mm){ + err = ptrace(PTRACE_SWITCH_MM, userspace_pid[0], 0, + mm_idp->u.mm_fd); + if(err) + panic("switch_mm_skas - PTRACE_SWITCH_MM failed, " + "errno = %d\n", errno); + } + else userspace_pid[0] = mm_idp->u.pid; +} diff --git a/arch/um/os-Linux/start_up.c b/arch/um/os-Linux/start_up.c index b47e5e71d1a..6c5b17ed59e 100644 --- a/arch/um/os-Linux/start_up.c +++ b/arch/um/os-Linux/start_up.c @@ -29,7 +29,6 @@ #include "irq_user.h" #include "ptrace_user.h" #include "mem_user.h" -#include "time_user.h" #include "init.h" #include "os.h" #include "uml-config.h" diff --git a/arch/um/os-Linux/time.c b/arch/um/os-Linux/time.c index cf30a39bc48..6f7626775ac 100644 --- a/arch/um/os-Linux/time.c +++ b/arch/um/os-Linux/time.c @@ -1,21 +1,128 @@ +/* + * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) + * Licensed under the GPL + */ + +#include <stdio.h> #include <stdlib.h> +#include <unistd.h> +#include <time.h> #include <sys/time.h> +#include <signal.h> +#include <errno.h> +#include "user_util.h" +#include "kern_util.h" +#include "user.h" +#include "process.h" +#include "kern_constants.h" +#include "os.h" + +/* XXX This really needs to be declared and initialized in a kernel file since + * it's in <linux/time.h> + */ +extern struct timespec wall_to_monotonic; + +static void set_interval(int timer_type) +{ + int usec = 1000000/hz(); + struct itimerval interval = ((struct itimerval) { { 0, usec }, + { 0, usec } }); + + if(setitimer(timer_type, &interval, NULL) == -1) + panic("setitimer failed - errno = %d\n", errno); +} + +void enable_timer(void) +{ + set_interval(ITIMER_VIRTUAL); +} + +void disable_timer(void) +{ + struct itimerval disable = ((struct itimerval) { { 0, 0 }, { 0, 0 }}); + if((setitimer(ITIMER_VIRTUAL, &disable, NULL) < 0) || + (setitimer(ITIMER_REAL, &disable, NULL) < 0)) + printk("disnable_timer - setitimer failed, errno = %d\n", + errno); + /* If there are signals already queued, after unblocking ignore them */ + set_handler(SIGALRM, SIG_IGN, 0, -1); + set_handler(SIGVTALRM, SIG_IGN, 0, -1); +} + +void switch_timers(int to_real) +{ + struct itimerval disable = ((struct itimerval) { { 0, 0 }, { 0, 0 }}); + struct itimerval enable = ((struct itimerval) { { 0, 1000000/hz() }, + { 0, 1000000/hz() }}); + int old, new; + + if(to_real){ + old = ITIMER_VIRTUAL; + new = ITIMER_REAL; + } + else { + old = ITIMER_REAL; + new = ITIMER_VIRTUAL; + } + + if((setitimer(old, &disable, NULL) < 0) || + (setitimer(new, &enable, NULL))) + printk("switch_timers - setitimer failed, errno = %d\n", + errno); +} -unsigned long long os_usecs(void) +void uml_idle_timer(void) +{ + if(signal(SIGVTALRM, SIG_IGN) == SIG_ERR) + panic("Couldn't unset SIGVTALRM handler"); + + set_handler(SIGALRM, (__sighandler_t) alarm_handler, + SA_RESTART, SIGUSR1, SIGIO, SIGWINCH, SIGVTALRM, -1); + set_interval(ITIMER_REAL); +} + +extern void ktime_get_ts(struct timespec *ts); +#define do_posix_clock_monotonic_gettime(ts) ktime_get_ts(ts) + +void time_init(void) +{ + struct timespec now; + + if(signal(SIGVTALRM, boot_timer_handler) == SIG_ERR) + panic("Couldn't set SIGVTALRM handler"); + set_interval(ITIMER_VIRTUAL); + + do_posix_clock_monotonic_gettime(&now); + wall_to_monotonic.tv_sec = -now.tv_sec; + wall_to_monotonic.tv_nsec = -now.tv_nsec; +} + +unsigned long long os_nsecs(void) { struct timeval tv; gettimeofday(&tv, NULL); - return((unsigned long long) tv.tv_sec * 1000000 + tv.tv_usec); + return((unsigned long long) tv.tv_sec * BILLION + tv.tv_usec * 1000); } -/* - * 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: - */ +void idle_sleep(int secs) +{ + struct timespec ts; + + ts.tv_sec = secs; + ts.tv_nsec = 0; + nanosleep(&ts, NULL); +} + +/* XXX This partly duplicates init_irq_signals */ + +void user_time_init(void) +{ + set_handler(SIGVTALRM, (__sighandler_t) alarm_handler, + SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGWINCH, + SIGALRM, SIGUSR2, -1); + set_handler(SIGALRM, (__sighandler_t) alarm_handler, + SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGWINCH, + SIGVTALRM, SIGUSR2, -1); + set_interval(ITIMER_VIRTUAL); +} diff --git a/arch/um/os-Linux/trap.c b/arch/um/os-Linux/trap.c index 321e1c8e227..a9f6b26f982 100644 --- a/arch/um/os-Linux/trap.c +++ b/arch/um/os-Linux/trap.c @@ -10,6 +10,7 @@ #include "user_util.h" #include "os.h" #include "mode.h" +#include "longjmp.h" void usr2_handler(int sig, union uml_pt_regs *regs) { @@ -36,5 +37,5 @@ void do_longjmp(void *b, int val) { sigjmp_buf *buf = b; - siglongjmp(*buf, val); + UML_SIGLONGJMP(buf, val); } diff --git a/arch/um/os-Linux/tt.c b/arch/um/os-Linux/tt.c index cb2648b79d0..919d19f1153 100644 --- a/arch/um/os-Linux/tt.c +++ b/arch/um/os-Linux/tt.c @@ -27,7 +27,6 @@ #include "sysdep/sigcontext.h" #include "irq_user.h" #include "ptrace_user.h" -#include "time_user.h" #include "init.h" #include "os.h" #include "uml-config.h" @@ -63,6 +62,54 @@ void kill_child_dead(int pid) } while(1); } +void stop(void) +{ + while(1) sleep(1000000); +} + +int wait_for_stop(int pid, int sig, int cont_type, void *relay) +{ + sigset_t *relay_signals = relay; + int status, ret; + + while(1){ + CATCH_EINTR(ret = waitpid(pid, &status, WUNTRACED)); + if((ret < 0) || + !WIFSTOPPED(status) || (WSTOPSIG(status) != sig)){ + if(ret < 0){ + printk("wait failed, errno = %d\n", + errno); + } + else if(WIFEXITED(status)) + printk("process %d exited with status %d\n", + pid, WEXITSTATUS(status)); + else if(WIFSIGNALED(status)) + printk("process %d exited with signal %d\n", + pid, WTERMSIG(status)); + else if((WSTOPSIG(status) == SIGVTALRM) || + (WSTOPSIG(status) == SIGALRM) || + (WSTOPSIG(status) == SIGIO) || + (WSTOPSIG(status) == SIGPROF) || + (WSTOPSIG(status) == SIGCHLD) || + (WSTOPSIG(status) == SIGWINCH) || + (WSTOPSIG(status) == SIGINT)){ + ptrace(cont_type, pid, 0, WSTOPSIG(status)); + continue; + } + else if((relay_signals != NULL) && + sigismember(relay_signals, WSTOPSIG(status))){ + ptrace(cont_type, pid, 0, WSTOPSIG(status)); + continue; + } + else printk("process %d stopped with signal %d\n", + pid, WSTOPSIG(status)); + panic("wait_for_stop failed to wait for %d to stop " + "with %d\n", pid, sig); + } + return(status); + } +} + /* *------------------------- * only for tt mode (will be deleted in future...) diff --git a/arch/um/os-Linux/uaccess.c b/arch/um/os-Linux/uaccess.c index 38d710158c3..166fb66995d 100644 --- a/arch/um/os-Linux/uaccess.c +++ b/arch/um/os-Linux/uaccess.c @@ -6,6 +6,7 @@ #include <setjmp.h> #include <string.h> +#include "longjmp.h" unsigned long __do_user_copy(void *to, const void *from, int n, void **fault_addr, void **fault_catcher, @@ -13,10 +14,11 @@ unsigned long __do_user_copy(void *to, const void *from, int n, int n), int *faulted_out) { unsigned long *faddrp = (unsigned long *) fault_addr, ret; + int enable; sigjmp_buf jbuf; *fault_catcher = &jbuf; - if(sigsetjmp(jbuf, 1) == 0){ + if(UML_SIGSETJMP(&jbuf, enable) == 0){ (*op)(to, from, n); ret = 0; *faulted_out = 0; diff --git a/arch/um/kernel/user_util.c b/arch/um/os-Linux/util.c index 4c231161f25..e32065e2fdc 100644 --- a/arch/um/kernel/user_util.c +++ b/arch/um/os-Linux/util.c @@ -1,4 +1,4 @@ -/* +/* * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) * Licensed under the GPL */ @@ -29,17 +29,14 @@ #include "init.h" #include "ptrace_user.h" #include "uml-config.h" - -void stop(void) -{ - while(1) sleep(1000000); -} +#include "os.h" +#include "longjmp.h" void stack_protections(unsigned long address) { int prot = PROT_READ | PROT_WRITE | PROT_EXEC; - if(mprotect((void *) address, page_size(), prot) < 0) + if(mprotect((void *) address, page_size(), prot) < 0) panic("protecting stack failed, errno = %d", errno); } @@ -59,49 +56,6 @@ void task_protections(unsigned long address) panic("protecting stack failed, errno = %d", errno); } -int wait_for_stop(int pid, int sig, int cont_type, void *relay) -{ - sigset_t *relay_signals = relay; - int status, ret; - - while(1){ - CATCH_EINTR(ret = waitpid(pid, &status, WUNTRACED)); - if((ret < 0) || - !WIFSTOPPED(status) || (WSTOPSIG(status) != sig)){ - if(ret < 0){ - printk("wait failed, errno = %d\n", - errno); - } - else if(WIFEXITED(status)) - printk("process %d exited with status %d\n", - pid, WEXITSTATUS(status)); - else if(WIFSIGNALED(status)) - printk("process %d exited with signal %d\n", - pid, WTERMSIG(status)); - else if((WSTOPSIG(status) == SIGVTALRM) || - (WSTOPSIG(status) == SIGALRM) || - (WSTOPSIG(status) == SIGIO) || - (WSTOPSIG(status) == SIGPROF) || - (WSTOPSIG(status) == SIGCHLD) || - (WSTOPSIG(status) == SIGWINCH) || - (WSTOPSIG(status) == SIGINT)){ - ptrace(cont_type, pid, 0, WSTOPSIG(status)); - continue; - } - else if((relay_signals != NULL) && - sigismember(relay_signals, WSTOPSIG(status))){ - ptrace(cont_type, pid, 0, WSTOPSIG(status)); - continue; - } - else printk("process %d stopped with signal %d\n", - pid, WSTOPSIG(status)); - panic("wait_for_stop failed to wait for %d to stop " - "with %d\n", pid, sig); - } - return(status); - } -} - int raw(int fd) { struct termios tt; @@ -113,7 +67,7 @@ int raw(int fd) cfmakeraw(&tt); - CATCH_EINTR(err = tcsetattr(fd, TCSADRAIN, &tt)); + CATCH_EINTR(err = tcsetattr(fd, TCSADRAIN, &tt)); if(err < 0) return -errno; @@ -149,7 +103,7 @@ void setup_hostinfo(void) int setjmp_wrapper(void (*proc)(void *, void *), ...) { - va_list args; + va_list args; sigjmp_buf buf; int n; @@ -161,14 +115,3 @@ int setjmp_wrapper(void (*proc)(void *, void *), ...) va_end(args); return(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/sys-i386/ldt.c b/arch/um/sys-i386/ldt.c index 17746b4c08f..0cdfd4481d5 100644 --- a/arch/um/sys-i386/ldt.c +++ b/arch/um/sys-i386/ldt.c @@ -16,6 +16,8 @@ #include "choose-mode.h" #include "kern.h" #include "mode_kern.h" +#include "proc_mm.h" +#include "os.h" extern int modify_ldt(int func, void *ptr, unsigned long bytecount); @@ -456,13 +458,14 @@ long init_new_ldt(struct mmu_context_skas * new_mm, int i; long page, err=0; void *addr = NULL; + struct proc_mm_op copy; - memset(&desc, 0, sizeof(desc)); if(!ptrace_ldt) init_MUTEX(&new_mm->ldt.semaphore); if(!from_mm){ + memset(&desc, 0, sizeof(desc)); /* * We have to initialize a clean ldt. */ @@ -494,8 +497,26 @@ long init_new_ldt(struct mmu_context_skas * new_mm, } } new_mm->ldt.entry_count = 0; + + goto out; } - else if (!ptrace_ldt) { + + if(proc_mm){ + /* We have a valid from_mm, so we now have to copy the LDT of + * from_mm to new_mm, because using proc_mm an new mm with + * an empty/default LDT was created in new_mm() + */ + copy = ((struct proc_mm_op) { .op = MM_COPY_SEGMENTS, + .u = + { .copy_segments = + from_mm->id.u.mm_fd } } ); + i = os_write_file(new_mm->id.u.mm_fd, ©, sizeof(copy)); + if(i != sizeof(copy)) + printk("new_mm : /proc/mm copy_segments failed, " + "err = %d\n", -i); + } + + if(!ptrace_ldt) { /* Our local LDT is used to supply the data for * modify_ldt(READLDT), if PTRACE_LDT isn't available, * i.e., we have to use the stub for modify_ldt, which @@ -524,6 +545,7 @@ long init_new_ldt(struct mmu_context_skas * new_mm, up(&from_mm->ldt.semaphore); } + out: return err; } diff --git a/arch/x86_64/Kconfig b/arch/x86_64/Kconfig index 787feff0e8a..2f9deca31cc 100644 --- a/arch/x86_64/Kconfig +++ b/arch/x86_64/Kconfig @@ -305,7 +305,11 @@ config ARCH_DISCONTIGMEM_DEFAULT config ARCH_SPARSEMEM_ENABLE def_bool y - depends on NUMA + depends on (NUMA || EXPERIMENTAL) + +config ARCH_MEMORY_PROBE + def_bool y + depends on MEMORY_HOTPLUG config ARCH_FLATMEM_ENABLE def_bool y @@ -315,6 +319,7 @@ source "mm/Kconfig" config HAVE_ARCH_EARLY_PFN_TO_NID def_bool y + depends on NUMA config NR_CPUS int "Maximum number of CPUs (2-256)" diff --git a/arch/x86_64/defconfig b/arch/x86_64/defconfig index 054dcd8a5e9..09a3eb74331 100644 --- a/arch/x86_64/defconfig +++ b/arch/x86_64/defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.15-git7 -# Wed Jan 11 11:57:36 2006 +# Linux kernel version: 2.6.15-git12 +# Mon Jan 16 13:09:08 2006 # CONFIG_X86_64=y CONFIG_64BIT=y @@ -319,6 +319,11 @@ CONFIG_IPV6=y # CONFIG_ATALK is not set # CONFIG_X25 is not set # CONFIG_LAPB is not set + +# +# TIPC Configuration (EXPERIMENTAL) +# +# CONFIG_TIPC is not set # CONFIG_NET_DIVERT is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set @@ -537,8 +542,7 @@ CONFIG_SCSI_SATA_INTEL_COMBINED=y # CONFIG_SCSI_IPR is not set # CONFIG_SCSI_QLOGIC_FC is not set # CONFIG_SCSI_QLOGIC_1280 is not set -CONFIG_SCSI_QLA2XXX=y -# CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE is not set +# CONFIG_SCSI_QLA_FC is not set # CONFIG_SCSI_LPFC is not set # CONFIG_SCSI_DC395x is not set # CONFIG_SCSI_DC390T is not set @@ -642,6 +646,7 @@ CONFIG_8139TOO=y # CONFIG_DL2K is not set CONFIG_E1000=y # CONFIG_E1000_NAPI is not set +# CONFIG_E1000_DISABLE_PACKET_SPLIT is not set # CONFIG_NS83820 is not set # CONFIG_HAMACHI is not set # CONFIG_YELLOWFIN is not set @@ -805,6 +810,7 @@ CONFIG_SOFT_WATCHDOG=y # CONFIG_W83877F_WDT is not set # CONFIG_W83977F_WDT is not set # CONFIG_MACHZ_WDT is not set +# CONFIG_SBC_EPX_C3_WATCHDOG is not set # # PCI-based Watchdog Cards @@ -850,6 +856,12 @@ CONFIG_HPET_MMAP=y # CONFIG_I2C is not set # +# SPI support +# +# CONFIG_SPI is not set +# CONFIG_SPI_MASTER is not set + +# # Dallas's 1-wire bus # # CONFIG_W1 is not set @@ -992,6 +1004,7 @@ CONFIG_USB_STORAGE=y # CONFIG_USB_HID=y CONFIG_USB_HIDINPUT=y +# CONFIG_USB_HIDINPUT_POWERBOOK is not set # CONFIG_HID_FF is not set # CONFIG_USB_HIDDEV is not set # CONFIG_USB_AIPTEK is not set @@ -1276,6 +1289,7 @@ CONFIG_DETECT_SOFTLOCKUP=y CONFIG_DEBUG_FS=y # CONFIG_DEBUG_VM is not set # CONFIG_FRAME_POINTER is not set +# CONFIG_FORCED_INLINING is not set # CONFIG_RCU_TORTURE_TEST is not set CONFIG_INIT_DEBUG=y # CONFIG_DEBUG_RODATA is not set diff --git a/arch/x86_64/ia32/Makefile b/arch/x86_64/ia32/Makefile index 051608d5592..929e6b0771f 100644 --- a/arch/x86_64/ia32/Makefile +++ b/arch/x86_64/ia32/Makefile @@ -3,7 +3,8 @@ # obj-$(CONFIG_IA32_EMULATION) := ia32entry.o sys_ia32.o ia32_signal.o tls32.o \ - ia32_binfmt.o fpu32.o ptrace32.o syscall32.o syscall32_syscall.o + ia32_binfmt.o fpu32.o ptrace32.o syscall32.o syscall32_syscall.o \ + mmap32.o sysv-$(CONFIG_SYSVIPC) := ipc32.o obj-$(CONFIG_IA32_EMULATION) += $(sysv-y) diff --git a/arch/x86_64/ia32/ia32_binfmt.c b/arch/x86_64/ia32/ia32_binfmt.c index 029bddab045..572b3b28772 100644 --- a/arch/x86_64/ia32/ia32_binfmt.c +++ b/arch/x86_64/ia32/ia32_binfmt.c @@ -293,8 +293,6 @@ int ia32_setup_arg_pages(struct linux_binprm *bprm, unsigned long stack_top, int } while(0) -#define elf_map elf32_map - #include <linux/module.h> MODULE_DESCRIPTION("Binary format loader for compatibility with IA32 ELF binaries."); @@ -390,21 +388,6 @@ int ia32_setup_arg_pages(struct linux_binprm *bprm, unsigned long stack_top, } EXPORT_SYMBOL(ia32_setup_arg_pages); -static unsigned long -elf32_map (struct file *filep, unsigned long addr, struct elf_phdr *eppnt, int prot, int type) -{ - unsigned long map_addr; - struct task_struct *me = current; - - down_write(&me->mm->mmap_sem); - map_addr = do_mmap(filep, ELF_PAGESTART(addr), - eppnt->p_filesz + ELF_PAGEOFFSET(eppnt->p_vaddr), prot, - type, - eppnt->p_offset - ELF_PAGEOFFSET(eppnt->p_vaddr)); - up_write(&me->mm->mmap_sem); - return(map_addr); -} - #ifdef CONFIG_SYSCTL /* Register vsyscall32 into the ABI table */ #include <linux/sysctl.h> diff --git a/arch/x86_64/ia32/ia32entry.S b/arch/x86_64/ia32/ia32entry.S index 58f5bfb52c6..f05c2a80248 100644 --- a/arch/x86_64/ia32/ia32entry.S +++ b/arch/x86_64/ia32/ia32entry.S @@ -672,6 +672,19 @@ ia32_sys_call_table: .quad sys_inotify_add_watch .quad sys_inotify_rm_watch .quad sys_migrate_pages + .quad compat_sys_openat /* 295 */ + .quad sys_mkdirat + .quad sys_mknodat + .quad sys_fchownat + .quad sys_futimesat + .quad compat_sys_newfstatat /* 300 */ + .quad sys_unlinkat + .quad sys_renameat + .quad sys_linkat + .quad sys_symlinkat + .quad sys_readlinkat /* 305 */ + .quad sys_fchmodat + .quad sys_faccessat ia32_syscall_end: .rept IA32_NR_syscalls-(ia32_syscall_end-ia32_sys_call_table)/8 .quad ni_syscall diff --git a/arch/x86_64/ia32/mmap32.c b/arch/x86_64/ia32/mmap32.c new file mode 100644 index 00000000000..079f4132575 --- /dev/null +++ b/arch/x86_64/ia32/mmap32.c @@ -0,0 +1,78 @@ +/* + * linux/arch/x86_64/ia32/mm/mmap.c + * + * flexible mmap layout support + * + * Based on the i386 version which was + * + * Copyright 2003-2004 Red Hat Inc., Durham, North Carolina. + * All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * + * Started by Ingo Molnar <mingo@elte.hu> + */ + +#include <linux/personality.h> +#include <linux/mm.h> +#include <linux/random.h> + +/* + * Top of mmap area (just below the process stack). + * + * Leave an at least ~128 MB hole. + */ +#define MIN_GAP (128*1024*1024) +#define MAX_GAP (TASK_SIZE/6*5) + +static inline unsigned long mmap_base(struct mm_struct *mm) +{ + unsigned long gap = current->signal->rlim[RLIMIT_STACK].rlim_cur; + unsigned long random_factor = 0; + + if (current->flags & PF_RANDOMIZE) + random_factor = get_random_int() % (1024*1024); + + if (gap < MIN_GAP) + gap = MIN_GAP; + else if (gap > MAX_GAP) + gap = MAX_GAP; + + return PAGE_ALIGN(TASK_SIZE - gap - random_factor); +} + +/* + * This function, called very early during the creation of a new + * process VM image, sets up which VM layout function to use: + */ +void ia32_pick_mmap_layout(struct mm_struct *mm) +{ + /* + * Fall back to the standard layout if the personality + * bit is set, or if the expected stack growth is unlimited: + */ + if (sysctl_legacy_va_layout || + (current->personality & ADDR_COMPAT_LAYOUT) || + current->signal->rlim[RLIMIT_STACK].rlim_cur == RLIM_INFINITY) { + mm->mmap_base = TASK_UNMAPPED_BASE; + mm->get_unmapped_area = arch_get_unmapped_area; + mm->unmap_area = arch_unmap_area; + } else { + mm->mmap_base = mmap_base(mm); + mm->get_unmapped_area = arch_get_unmapped_area_topdown; + mm->unmap_area = arch_unmap_area_topdown; + } +} diff --git a/arch/x86_64/kernel/head.S b/arch/x86_64/kernel/head.S index 38fc3d5112e..692c737fedd 100644 --- a/arch/x86_64/kernel/head.S +++ b/arch/x86_64/kernel/head.S @@ -241,104 +241,70 @@ ljumpvector: ENTRY(stext) ENTRY(_stext) -.org 0x1000 -ENTRY(init_level4_pgt) + $page = 0 +#define NEXT_PAGE(name) \ + $page = $page + 1; \ + .org $page * 0x1000; \ + phys_/**/name = $page * 0x1000 + __PHYSICAL_START; \ +ENTRY(name) + +NEXT_PAGE(init_level4_pgt) /* This gets initialized in x86_64_start_kernel */ .fill 512,8,0 -.org 0x2000 -ENTRY(level3_ident_pgt) - .quad 0x0000000000004007 + __PHYSICAL_START +NEXT_PAGE(level3_ident_pgt) + .quad phys_level2_ident_pgt | 0x007 .fill 511,8,0 -.org 0x3000 -ENTRY(level3_kernel_pgt) +NEXT_PAGE(level3_kernel_pgt) .fill 510,8,0 /* (2^48-(2*1024*1024*1024)-((2^39)*511))/(2^30) = 510 */ - .quad 0x0000000000005007 + __PHYSICAL_START /* -> level2_kernel_pgt */ + .quad phys_level2_kernel_pgt | 0x007 .fill 1,8,0 -.org 0x4000 -ENTRY(level2_ident_pgt) +NEXT_PAGE(level2_ident_pgt) /* 40MB for bootup. */ - .quad 0x0000000000000083 - .quad 0x0000000000200083 - .quad 0x0000000000400083 - .quad 0x0000000000600083 - .quad 0x0000000000800083 - .quad 0x0000000000A00083 - .quad 0x0000000000C00083 - .quad 0x0000000000E00083 - .quad 0x0000000001000083 - .quad 0x0000000001200083 - .quad 0x0000000001400083 - .quad 0x0000000001600083 - .quad 0x0000000001800083 - .quad 0x0000000001A00083 - .quad 0x0000000001C00083 - .quad 0x0000000001E00083 - .quad 0x0000000002000083 - .quad 0x0000000002200083 - .quad 0x0000000002400083 - .quad 0x0000000002600083 + i = 0 + .rept 20 + .quad i << 21 | 0x083 + i = i + 1 + .endr /* Temporary mappings for the super early allocator in arch/x86_64/mm/init.c */ .globl temp_boot_pmds temp_boot_pmds: .fill 492,8,0 -.org 0x5000 -ENTRY(level2_kernel_pgt) +NEXT_PAGE(level2_kernel_pgt) /* 40MB kernel mapping. The kernel code cannot be bigger than that. When you change this change KERNEL_TEXT_SIZE in page.h too. */ /* (2^48-(2*1024*1024*1024)-((2^39)*511)-((2^30)*510)) = 0 */ - .quad 0x0000000000000183 - .quad 0x0000000000200183 - .quad 0x0000000000400183 - .quad 0x0000000000600183 - .quad 0x0000000000800183 - .quad 0x0000000000A00183 - .quad 0x0000000000C00183 - .quad 0x0000000000E00183 - .quad 0x0000000001000183 - .quad 0x0000000001200183 - .quad 0x0000000001400183 - .quad 0x0000000001600183 - .quad 0x0000000001800183 - .quad 0x0000000001A00183 - .quad 0x0000000001C00183 - .quad 0x0000000001E00183 - .quad 0x0000000002000183 - .quad 0x0000000002200183 - .quad 0x0000000002400183 - .quad 0x0000000002600183 + i = 0 + .rept 20 + .quad i << 21 | 0x183 + i = i + 1 + .endr /* Module mapping starts here */ .fill 492,8,0 -.org 0x6000 -ENTRY(empty_zero_page) - -.org 0x7000 -ENTRY(empty_bad_page) +NEXT_PAGE(empty_zero_page) -.org 0x8000 -ENTRY(empty_bad_pte_table) +NEXT_PAGE(level3_physmem_pgt) + .quad phys_level2_kernel_pgt | 0x007 /* so that __va works even before pagetable_init */ + .fill 511,8,0 -.org 0x9000 -ENTRY(empty_bad_pmd_table) +#undef NEXT_PAGE -.org 0xa000 -ENTRY(level3_physmem_pgt) - .quad 0x0000000000005007 + __PHYSICAL_START /* -> level2_kernel_pgt (so that __va works even before pagetable_init) */ + .data - .org 0xb000 #ifdef CONFIG_ACPI_SLEEP + .align PAGE_SIZE ENTRY(wakeup_level4_pgt) - .quad 0x0000000000002007 + __PHYSICAL_START /* -> level3_ident_pgt */ + .quad phys_level3_ident_pgt | 0x007 .fill 255,8,0 - .quad 0x000000000000a007 + __PHYSICAL_START + .quad phys_level3_physmem_pgt | 0x007 .fill 254,8,0 /* (2^48-(2*1024*1024*1024))/(2^39) = 511 */ - .quad 0x0000000000003007 + __PHYSICAL_START /* -> level3_kernel_pgt */ + .quad phys_level3_kernel_pgt | 0x007 #endif #ifndef CONFIG_HOTPLUG_CPU @@ -352,12 +318,12 @@ ENTRY(wakeup_level4_pgt) */ .align PAGE_SIZE ENTRY(boot_level4_pgt) - .quad 0x0000000000002007 + __PHYSICAL_START /* -> level3_ident_pgt */ + .quad phys_level3_ident_pgt | 0x007 .fill 255,8,0 - .quad 0x000000000000a007 + __PHYSICAL_START + .quad phys_level3_physmem_pgt | 0x007 .fill 254,8,0 /* (2^48-(2*1024*1024*1024))/(2^39) = 511 */ - .quad 0x0000000000003007 + __PHYSICAL_START /* -> level3_kernel_pgt */ + .quad phys_level3_kernel_pgt | 0x007 .data diff --git a/arch/x86_64/kernel/setup64.c b/arch/x86_64/kernel/setup64.c index 8ac4db09610..70f1bb808a2 100644 --- a/arch/x86_64/kernel/setup64.c +++ b/arch/x86_64/kernel/setup64.c @@ -146,7 +146,7 @@ void pda_init(int cpu) pda->irqstackptr += IRQSTACKSIZE-64; } -char boot_exception_stacks[(N_EXCEPTION_STACKS - 2) * EXCEPTION_STKSZ + DEBUG_STKSZ] +char boot_exception_stacks[(N_EXCEPTION_STACKS - 1) * EXCEPTION_STKSZ + DEBUG_STKSZ] __attribute__((section(".bss.page_aligned"))); /* May not be marked __init: used by software suspend */ diff --git a/arch/x86_64/mm/Makefile b/arch/x86_64/mm/Makefile index 1d232a87f11..d25ac86fe27 100644 --- a/arch/x86_64/mm/Makefile +++ b/arch/x86_64/mm/Makefile @@ -2,7 +2,7 @@ # Makefile for the linux x86_64-specific parts of the memory manager. # -obj-y := init.o fault.o ioremap.o extable.o pageattr.o +obj-y := init.o fault.o ioremap.o extable.o pageattr.o mmap.o obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o obj-$(CONFIG_NUMA) += numa.o obj-$(CONFIG_K8_NUMA) += k8topology.o diff --git a/arch/x86_64/mm/init.c b/arch/x86_64/mm/init.c index 307d1ac0ef3..7af1742aa95 100644 --- a/arch/x86_64/mm/init.c +++ b/arch/x86_64/mm/init.c @@ -24,6 +24,8 @@ #include <linux/proc_fs.h> #include <linux/pci.h> #include <linux/dma-mapping.h> +#include <linux/module.h> +#include <linux/memory_hotplug.h> #include <asm/processor.h> #include <asm/system.h> @@ -180,13 +182,19 @@ static struct temp_map { {} }; -static __init void *alloc_low_page(int *index, unsigned long *phys) +static __meminit void *alloc_low_page(int *index, unsigned long *phys) { struct temp_map *ti; int i; unsigned long pfn = table_end++, paddr; void *adr; + if (after_bootmem) { + adr = (void *)get_zeroed_page(GFP_ATOMIC); + *phys = __pa(adr); + return adr; + } + if (pfn >= end_pfn) panic("alloc_low_page: ran out of memory"); for (i = 0; temp_mappings[i].allocated; i++) { @@ -199,55 +207,86 @@ static __init void *alloc_low_page(int *index, unsigned long *phys) ti->allocated = 1; __flush_tlb(); adr = ti->address + ((pfn << PAGE_SHIFT) & ~PMD_MASK); + memset(adr, 0, PAGE_SIZE); *index = i; *phys = pfn * PAGE_SIZE; return adr; } -static __init void unmap_low_page(int i) +static __meminit void unmap_low_page(int i) { - struct temp_map *ti = &temp_mappings[i]; + struct temp_map *ti; + + if (after_bootmem) + return; + + ti = &temp_mappings[i]; set_pmd(ti->pmd, __pmd(0)); ti->allocated = 0; } -static void __init phys_pud_init(pud_t *pud, unsigned long address, unsigned long end) +static void __meminit +phys_pmd_init(pmd_t *pmd, unsigned long address, unsigned long end) +{ + int i; + + for (i = 0; i < PTRS_PER_PMD; pmd++, i++, address += PMD_SIZE) { + unsigned long entry; + + if (address > end) { + for (; i < PTRS_PER_PMD; i++, pmd++) + set_pmd(pmd, __pmd(0)); + break; + } + entry = _PAGE_NX|_PAGE_PSE|_KERNPG_TABLE|_PAGE_GLOBAL|address; + entry &= __supported_pte_mask; + set_pmd(pmd, __pmd(entry)); + } +} + +static void __meminit +phys_pmd_update(pud_t *pud, unsigned long address, unsigned long end) +{ + pmd_t *pmd = pmd_offset(pud, (unsigned long)__va(address)); + + if (pmd_none(*pmd)) { + spin_lock(&init_mm.page_table_lock); + phys_pmd_init(pmd, address, end); + spin_unlock(&init_mm.page_table_lock); + __flush_tlb_all(); + } +} + +static void __meminit phys_pud_init(pud_t *pud, unsigned long address, unsigned long end) { - long i, j; + long i = pud_index(address); - i = pud_index(address); pud = pud + i; + + if (after_bootmem && pud_val(*pud)) { + phys_pmd_update(pud, address, end); + return; + } + for (; i < PTRS_PER_PUD; pud++, i++) { int map; unsigned long paddr, pmd_phys; pmd_t *pmd; - paddr = address + i*PUD_SIZE; - if (paddr >= end) { - for (; i < PTRS_PER_PUD; i++, pud++) - set_pud(pud, __pud(0)); + paddr = (address & PGDIR_MASK) + i*PUD_SIZE; + if (paddr >= end) break; - } - if (!e820_mapped(paddr, paddr+PUD_SIZE, 0)) { + if (!after_bootmem && !e820_mapped(paddr, paddr+PUD_SIZE, 0)) { set_pud(pud, __pud(0)); continue; } pmd = alloc_low_page(&map, &pmd_phys); + spin_lock(&init_mm.page_table_lock); set_pud(pud, __pud(pmd_phys | _KERNPG_TABLE)); - for (j = 0; j < PTRS_PER_PMD; pmd++, j++, paddr += PMD_SIZE) { - unsigned long pe; - - if (paddr >= end) { - for (; j < PTRS_PER_PMD; j++, pmd++) - set_pmd(pmd, __pmd(0)); - break; - } - pe = _PAGE_NX|_PAGE_PSE | _KERNPG_TABLE | _PAGE_GLOBAL | paddr; - pe &= __supported_pte_mask; - set_pmd(pmd, __pmd(pe)); - } + phys_pmd_init(pmd, paddr, end); + spin_unlock(&init_mm.page_table_lock); unmap_low_page(map); } __flush_tlb(); @@ -272,12 +311,15 @@ static void __init find_early_table_space(unsigned long end) table_start >>= PAGE_SHIFT; table_end = table_start; + + early_printk("kernel direct mapping tables up to %lx @ %lx-%lx\n", + end, table_start << PAGE_SHIFT, table_end << PAGE_SHIFT); } /* Setup the direct mapping of the physical memory at PAGE_OFFSET. This runs before bootmem is initialized and gets pages directly from the physical memory. To access them they are temporarily mapped. */ -void __init init_memory_mapping(unsigned long start, unsigned long end) +void __meminit init_memory_mapping(unsigned long start, unsigned long end) { unsigned long next; @@ -289,7 +331,8 @@ void __init init_memory_mapping(unsigned long start, unsigned long end) * mapped. Unfortunately this is done currently before the nodes are * discovered. */ - find_early_table_space(end); + if (!after_bootmem) + find_early_table_space(end); start = (unsigned long)__va(start); end = (unsigned long)__va(end); @@ -297,20 +340,26 @@ void __init init_memory_mapping(unsigned long start, unsigned long end) for (; start < end; start = next) { int map; unsigned long pud_phys; - pud_t *pud = alloc_low_page(&map, &pud_phys); + pgd_t *pgd = pgd_offset_k(start); + pud_t *pud; + + if (after_bootmem) + pud = pud_offset_k(pgd, __PAGE_OFFSET); + else + pud = alloc_low_page(&map, &pud_phys); + next = start + PGDIR_SIZE; if (next > end) next = end; phys_pud_init(pud, __pa(start), __pa(next)); - set_pgd(pgd_offset_k(start), mk_kernel_pgd(pud_phys)); + if (!after_bootmem) + set_pgd(pgd_offset_k(start), mk_kernel_pgd(pud_phys)); unmap_low_page(map); } - asm volatile("movq %%cr4,%0" : "=r" (mmu_cr4_features)); + if (!after_bootmem) + asm volatile("movq %%cr4,%0" : "=r" (mmu_cr4_features)); __flush_tlb_all(); - early_printk("kernel direct mapping tables upto %lx @ %lx-%lx\n", end, - table_start<<PAGE_SHIFT, - table_end<<PAGE_SHIFT); } void __cpuinit zap_low_mappings(int cpu) @@ -385,6 +434,9 @@ size_zones(unsigned long *z, unsigned long *h, void __init paging_init(void) { unsigned long zones[MAX_NR_ZONES], holes[MAX_NR_ZONES]; + + memory_present(0, 0, end_pfn); + sparse_init(); size_zones(zones, holes, 0, end_pfn); free_area_init_node(0, NODE_DATA(0), zones, __pa(PAGE_OFFSET) >> PAGE_SHIFT, holes); @@ -425,6 +477,50 @@ void __init clear_kernel_mapping(unsigned long address, unsigned long size) __flush_tlb_all(); } +/* + * Memory hotplug specific functions + * These are only for non-NUMA machines right now. + */ +#ifdef CONFIG_MEMORY_HOTPLUG + +void online_page(struct page *page) +{ + ClearPageReserved(page); + set_page_count(page, 1); + __free_page(page); + totalram_pages++; + num_physpages++; +} + +int add_memory(u64 start, u64 size) +{ + struct pglist_data *pgdat = NODE_DATA(0); + struct zone *zone = pgdat->node_zones + MAX_NR_ZONES-2; + unsigned long start_pfn = start >> PAGE_SHIFT; + unsigned long nr_pages = size >> PAGE_SHIFT; + int ret; + + ret = __add_pages(zone, start_pfn, nr_pages); + if (ret) + goto error; + + init_memory_mapping(start, (start + size -1)); + + return ret; +error: + printk("%s: Problem encountered in __add_pages!\n", __func__); + return ret; +} +EXPORT_SYMBOL_GPL(add_memory); + +int remove_memory(u64 start, u64 size) +{ + return -EINVAL; +} +EXPORT_SYMBOL_GPL(remove_memory); + +#endif + static struct kcore_list kcore_mem, kcore_vmalloc, kcore_kernel, kcore_modules, kcore_vsyscall; diff --git a/arch/x86_64/mm/mmap.c b/arch/x86_64/mm/mmap.c new file mode 100644 index 00000000000..43e9b99bdf2 --- /dev/null +++ b/arch/x86_64/mm/mmap.c @@ -0,0 +1,30 @@ +/* Copyright 2005 Andi Kleen, SuSE Labs. + * Licensed under GPL, v.2 + */ +#include <linux/config.h> +#include <linux/mm.h> +#include <linux/sched.h> +#include <linux/random.h> +#include <asm/ia32.h> + +/* Notebook: move the mmap code from sys_x86_64.c over here. */ + +void arch_pick_mmap_layout(struct mm_struct *mm) +{ +#ifdef CONFIG_IA32_EMULATION + if (current_thread_info()->flags & _TIF_IA32) + return ia32_pick_mmap_layout(mm); +#endif + mm->mmap_base = TASK_UNMAPPED_BASE; + if (current->flags & PF_RANDOMIZE) { + /* Add 28bit randomness which is about 40bits of address space + because mmap base has to be page aligned. + or ~1/128 of the total user VM + (total user address space is 47bits) */ + unsigned rnd = get_random_int() & 0xfffffff; + mm->mmap_base += ((unsigned long)rnd) << PAGE_SHIFT; + } + mm->get_unmapped_area = arch_get_unmapped_area; + mm->unmap_area = arch_unmap_area; +} + |