diff options
| author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-03-16 22:28:15 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-03-16 22:28:15 -0400 |
| commit | 47455911674d65fba28d43f4135c28ee40c75bac (patch) | |
| tree | bb109710af11a8e499e971a230fff7316cc49095 | |
| parent | 5379058b718ac6354ba99cc74d10c28d632dc28a (diff) | |
| parent | f510aa3bdb095c5253f6bee9e0f5a3a9ac69ded4 (diff) | |
Merge branch 'upstream' of git://ftp.linux-mips.org/pub/scm/upstream-linus
* 'upstream' of git://ftp.linux-mips.org/pub/scm/upstream-linus:
[MIPS] Kconfig: Move missplaced NR_CPUS default from SMTC to VSMP.
[MIPS] Lockdep: Fix recursion bug.
[MIPS] RTLX: Handle copy_*_user return values.
[MIPS] RTLX: Protect rtlx_{read,write} with mutex.
[MIPS] RTLX: Harden against compiler reordering and optimization.
[MIPS] RTLX: Don't use volatile; it's fragile.
[MIPS] Lasat: Downgrade 64-bit kernel from experimental to broken.
[MIPS] Compat: Fix build if CONFIG_SYSVIPC is disabled.
[CHAR] lcd: Fix two warnings.
[MIPS] FPU ownership management & preemption fixes
[MIPS] Check FCSR for pending interrupts, alternative version
[MIPS] IP27, IP35: Fix warnings.
| -rw-r--r-- | arch/mips/Kconfig | 4 | ||||
| -rw-r--r-- | arch/mips/kernel/kspd.c | 18 | ||||
| -rw-r--r-- | arch/mips/kernel/linux32.c | 12 | ||||
| -rw-r--r-- | arch/mips/kernel/r2300_switch.S | 10 | ||||
| -rw-r--r-- | arch/mips/kernel/r4k_fpu.S | 16 | ||||
| -rw-r--r-- | arch/mips/kernel/r4k_switch.S | 10 | ||||
| -rw-r--r-- | arch/mips/kernel/rtlx.c | 104 | ||||
| -rw-r--r-- | arch/mips/kernel/signal-common.h | 3 | ||||
| -rw-r--r-- | arch/mips/kernel/signal.c | 75 | ||||
| -rw-r--r-- | arch/mips/kernel/signal32.c | 56 | ||||
| -rw-r--r-- | arch/mips/kernel/signal_n32.c | 6 | ||||
| -rw-r--r-- | arch/mips/kernel/traps.c | 84 | ||||
| -rw-r--r-- | arch/mips/math-emu/kernel_linkage.c | 8 | ||||
| -rw-r--r-- | drivers/char/lcd.c | 5 | ||||
| -rw-r--r-- | include/asm-mips/atomic.h | 40 | ||||
| -rw-r--r-- | include/asm-mips/bitops.h | 24 | ||||
| -rw-r--r-- | include/asm-mips/cpu-features.h | 3 | ||||
| -rw-r--r-- | include/asm-mips/cpu-info.h | 1 | ||||
| -rw-r--r-- | include/asm-mips/fpu.h | 54 | ||||
| -rw-r--r-- | include/asm-mips/mach-ip27/dma-coherence.h | 5 | ||||
| -rw-r--r-- | include/asm-mips/mach-ip32/dma-coherence.h | 5 | ||||
| -rw-r--r-- | include/asm-mips/rtlx.h | 4 | ||||
| -rw-r--r-- | include/asm-mips/system.h | 16 | ||||
| -rw-r--r-- | include/asm-mips/thread_info.h | 1 |
24 files changed, 338 insertions, 226 deletions
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 2b9c65c3b5d1..5f29018a6533 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig | |||
| @@ -250,7 +250,7 @@ config LASAT | |||
| 250 | select R5000_CPU_SCACHE | 250 | select R5000_CPU_SCACHE |
| 251 | select SYS_HAS_CPU_R5000 | 251 | select SYS_HAS_CPU_R5000 |
| 252 | select SYS_SUPPORTS_32BIT_KERNEL | 252 | select SYS_SUPPORTS_32BIT_KERNEL |
| 253 | select SYS_SUPPORTS_64BIT_KERNEL if EXPERIMENTAL | 253 | select SYS_SUPPORTS_64BIT_KERNEL if BROKEN |
| 254 | select SYS_SUPPORTS_LITTLE_ENDIAN | 254 | select SYS_SUPPORTS_LITTLE_ENDIAN |
| 255 | select GENERIC_HARDIRQS_NO__DO_IRQ | 255 | select GENERIC_HARDIRQS_NO__DO_IRQ |
| 256 | 256 | ||
| @@ -1559,6 +1559,7 @@ config MIPS_MT_SMP | |||
| 1559 | select CPU_MIPSR2_IRQ_VI | 1559 | select CPU_MIPSR2_IRQ_VI |
| 1560 | select CPU_MIPSR2_SRS | 1560 | select CPU_MIPSR2_SRS |
| 1561 | select MIPS_MT | 1561 | select MIPS_MT |
| 1562 | select NR_CPUS_DEFAULT_2 | ||
| 1562 | select SMP | 1563 | select SMP |
| 1563 | select SYS_SUPPORTS_SMP | 1564 | select SYS_SUPPORTS_SMP |
| 1564 | help | 1565 | help |
| @@ -1573,7 +1574,6 @@ config MIPS_MT_SMTC | |||
| 1573 | select CPU_MIPSR2_IRQ_VI | 1574 | select CPU_MIPSR2_IRQ_VI |
| 1574 | select CPU_MIPSR2_SRS | 1575 | select CPU_MIPSR2_SRS |
| 1575 | select MIPS_MT | 1576 | select MIPS_MT |
| 1576 | select NR_CPUS_DEFAULT_2 | ||
| 1577 | select NR_CPUS_DEFAULT_8 | 1577 | select NR_CPUS_DEFAULT_8 |
| 1578 | select SMP | 1578 | select SMP |
| 1579 | select SYS_SUPPORTS_SMP | 1579 | select SYS_SUPPORTS_SMP |
diff --git a/arch/mips/kernel/kspd.c b/arch/mips/kernel/kspd.c index 241ee7a2906e..29eadd404fa5 100644 --- a/arch/mips/kernel/kspd.c +++ b/arch/mips/kernel/kspd.c | |||
| @@ -191,6 +191,8 @@ void sp_work_handle_request(void) | |||
| 191 | struct mtsp_syscall_generic generic; | 191 | struct mtsp_syscall_generic generic; |
| 192 | struct mtsp_syscall_ret ret; | 192 | struct mtsp_syscall_ret ret; |
| 193 | struct kspd_notifications *n; | 193 | struct kspd_notifications *n; |
| 194 | unsigned long written; | ||
| 195 | mm_segment_t old_fs; | ||
| 194 | struct timeval tv; | 196 | struct timeval tv; |
| 195 | struct timezone tz; | 197 | struct timezone tz; |
| 196 | int cmd; | 198 | int cmd; |
| @@ -201,7 +203,11 @@ void sp_work_handle_request(void) | |||
| 201 | 203 | ||
| 202 | ret.retval = -1; | 204 | ret.retval = -1; |
| 203 | 205 | ||
| 204 | if (!rtlx_read(RTLX_CHANNEL_SYSIO, &sc, sizeof(struct mtsp_syscall), 0)) { | 206 | old_fs = get_fs(); |
| 207 | set_fs(KERNEL_DS); | ||
| 208 | |||
| 209 | if (!rtlx_read(RTLX_CHANNEL_SYSIO, &sc, sizeof(struct mtsp_syscall))) { | ||
| 210 | set_fs(old_fs); | ||
| 205 | printk(KERN_ERR "Expected request but nothing to read\n"); | 211 | printk(KERN_ERR "Expected request but nothing to read\n"); |
| 206 | return; | 212 | return; |
| 207 | } | 213 | } |
| @@ -209,7 +215,8 @@ void sp_work_handle_request(void) | |||
| 209 | size = sc.size; | 215 | size = sc.size; |
| 210 | 216 | ||
| 211 | if (size) { | 217 | if (size) { |
| 212 | if (!rtlx_read(RTLX_CHANNEL_SYSIO, &generic, size, 0)) { | 218 | if (!rtlx_read(RTLX_CHANNEL_SYSIO, &generic, size)) { |
| 219 | set_fs(old_fs); | ||
| 213 | printk(KERN_ERR "Expected request but nothing to read\n"); | 220 | printk(KERN_ERR "Expected request but nothing to read\n"); |
| 214 | return; | 221 | return; |
| 215 | } | 222 | } |
| @@ -282,8 +289,11 @@ void sp_work_handle_request(void) | |||
| 282 | if (vpe_getuid(SP_VPE)) | 289 | if (vpe_getuid(SP_VPE)) |
| 283 | sp_setfsuidgid( 0, 0); | 290 | sp_setfsuidgid( 0, 0); |
| 284 | 291 | ||
| 285 | if ((rtlx_write(RTLX_CHANNEL_SYSIO, &ret, sizeof(struct mtsp_syscall_ret), 0)) | 292 | old_fs = get_fs(); |
| 286 | < sizeof(struct mtsp_syscall_ret)) | 293 | set_fs(KERNEL_DS); |
| 294 | written = rtlx_write(RTLX_CHANNEL_SYSIO, &ret, sizeof(ret)); | ||
| 295 | set_fs(old_fs); | ||
| 296 | if (written < sizeof(ret)) | ||
| 287 | printk("KSPD: sp_work_handle_request failed to send to SP\n"); | 297 | printk("KSPD: sp_work_handle_request failed to send to SP\n"); |
| 288 | } | 298 | } |
| 289 | 299 | ||
diff --git a/arch/mips/kernel/linux32.c b/arch/mips/kernel/linux32.c index 1df544c1f966..37849edd0645 100644 --- a/arch/mips/kernel/linux32.c +++ b/arch/mips/kernel/linux32.c | |||
| @@ -311,6 +311,8 @@ asmlinkage int sys32_sched_rr_get_interval(compat_pid_t pid, | |||
| 311 | return ret; | 311 | return ret; |
| 312 | } | 312 | } |
| 313 | 313 | ||
| 314 | #ifdef CONFIG_SYSVIPC | ||
| 315 | |||
| 314 | asmlinkage long | 316 | asmlinkage long |
| 315 | sys32_ipc (u32 call, int first, int second, int third, u32 ptr, u32 fifth) | 317 | sys32_ipc (u32 call, int first, int second, int third, u32 ptr, u32 fifth) |
| 316 | { | 318 | { |
| @@ -368,6 +370,16 @@ sys32_ipc (u32 call, int first, int second, int third, u32 ptr, u32 fifth) | |||
| 368 | return err; | 370 | return err; |
| 369 | } | 371 | } |
| 370 | 372 | ||
| 373 | #else | ||
| 374 | |||
| 375 | asmlinkage long | ||
| 376 | sys32_ipc (u32 call, int first, int second, int third, u32 ptr, u32 fifth) | ||
| 377 | { | ||
| 378 | return -ENOSYS; | ||
| 379 | } | ||
| 380 | |||
| 381 | #endif /* CONFIG_SYSVIPC */ | ||
| 382 | |||
| 371 | #ifdef CONFIG_MIPS32_N32 | 383 | #ifdef CONFIG_MIPS32_N32 |
| 372 | asmlinkage long sysn32_semctl(int semid, int semnum, int cmd, u32 arg) | 384 | asmlinkage long sysn32_semctl(int semid, int semnum, int cmd, u32 arg) |
| 373 | { | 385 | { |
diff --git a/arch/mips/kernel/r2300_switch.S b/arch/mips/kernel/r2300_switch.S index 656bde2e11b1..28c2e2e6af73 100644 --- a/arch/mips/kernel/r2300_switch.S +++ b/arch/mips/kernel/r2300_switch.S | |||
| @@ -49,8 +49,7 @@ LEAF(resume) | |||
| 49 | #ifndef CONFIG_CPU_HAS_LLSC | 49 | #ifndef CONFIG_CPU_HAS_LLSC |
| 50 | sw zero, ll_bit | 50 | sw zero, ll_bit |
| 51 | #endif | 51 | #endif |
| 52 | mfc0 t1, CP0_STATUS | 52 | mfc0 t2, CP0_STATUS |
| 53 | sw t1, THREAD_STATUS(a0) | ||
| 54 | cpu_save_nonscratch a0 | 53 | cpu_save_nonscratch a0 |
| 55 | sw ra, THREAD_REG31(a0) | 54 | sw ra, THREAD_REG31(a0) |
| 56 | 55 | ||
| @@ -60,8 +59,8 @@ LEAF(resume) | |||
| 60 | lw t3, TASK_THREAD_INFO(a0) | 59 | lw t3, TASK_THREAD_INFO(a0) |
| 61 | lw t0, TI_FLAGS(t3) | 60 | lw t0, TI_FLAGS(t3) |
| 62 | li t1, _TIF_USEDFPU | 61 | li t1, _TIF_USEDFPU |
| 63 | and t2, t0, t1 | 62 | and t1, t0 |
| 64 | beqz t2, 1f | 63 | beqz t1, 1f |
| 65 | nor t1, zero, t1 | 64 | nor t1, zero, t1 |
| 66 | 65 | ||
| 67 | and t0, t0, t1 | 66 | and t0, t0, t1 |
| @@ -74,10 +73,13 @@ LEAF(resume) | |||
| 74 | li t1, ~ST0_CU1 | 73 | li t1, ~ST0_CU1 |
| 75 | and t0, t0, t1 | 74 | and t0, t0, t1 |
| 76 | sw t0, ST_OFF(t3) | 75 | sw t0, ST_OFF(t3) |
| 76 | /* clear thread_struct CU1 bit */ | ||
| 77 | and t2, t1 | ||
| 77 | 78 | ||
| 78 | fpu_save_single a0, t0 # clobbers t0 | 79 | fpu_save_single a0, t0 # clobbers t0 |
| 79 | 80 | ||
| 80 | 1: | 81 | 1: |
| 82 | sw t2, THREAD_STATUS(a0) | ||
| 81 | /* | 83 | /* |
| 82 | * The order of restoring the registers takes care of the race | 84 | * The order of restoring the registers takes care of the race |
| 83 | * updating $28, $29 and kernelsp without disabling ints. | 85 | * updating $28, $29 and kernelsp without disabling ints. |
diff --git a/arch/mips/kernel/r4k_fpu.S b/arch/mips/kernel/r4k_fpu.S index 59c1577ecbb3..dbd42adc52ed 100644 --- a/arch/mips/kernel/r4k_fpu.S +++ b/arch/mips/kernel/r4k_fpu.S | |||
| @@ -114,14 +114,6 @@ LEAF(_save_fp_context32) | |||
| 114 | */ | 114 | */ |
| 115 | LEAF(_restore_fp_context) | 115 | LEAF(_restore_fp_context) |
| 116 | EX lw t0, SC_FPC_CSR(a0) | 116 | EX lw t0, SC_FPC_CSR(a0) |
| 117 | |||
| 118 | /* Fail if the CSR has exceptions pending */ | ||
| 119 | srl t1, t0, 5 | ||
| 120 | and t1, t0 | ||
| 121 | andi t1, 0x1f << 7 | ||
| 122 | bnez t1, fault | ||
| 123 | nop | ||
| 124 | |||
| 125 | #ifdef CONFIG_64BIT | 117 | #ifdef CONFIG_64BIT |
| 126 | EX ldc1 $f1, SC_FPREGS+8(a0) | 118 | EX ldc1 $f1, SC_FPREGS+8(a0) |
| 127 | EX ldc1 $f3, SC_FPREGS+24(a0) | 119 | EX ldc1 $f3, SC_FPREGS+24(a0) |
| @@ -165,14 +157,6 @@ LEAF(_restore_fp_context) | |||
| 165 | LEAF(_restore_fp_context32) | 157 | LEAF(_restore_fp_context32) |
| 166 | /* Restore an o32 sigcontext. */ | 158 | /* Restore an o32 sigcontext. */ |
| 167 | EX lw t0, SC32_FPC_CSR(a0) | 159 | EX lw t0, SC32_FPC_CSR(a0) |
| 168 | |||
| 169 | /* Fail if the CSR has exceptions pending */ | ||
| 170 | srl t1, t0, 5 | ||
| 171 | and t1, t0 | ||
| 172 | andi t1, 0x1f << 7 | ||
| 173 | bnez t1, fault | ||
| 174 | nop | ||
| 175 | |||
| 176 | EX ldc1 $f0, SC32_FPREGS+0(a0) | 160 | EX ldc1 $f0, SC32_FPREGS+0(a0) |
| 177 | EX ldc1 $f2, SC32_FPREGS+16(a0) | 161 | EX ldc1 $f2, SC32_FPREGS+16(a0) |
| 178 | EX ldc1 $f4, SC32_FPREGS+32(a0) | 162 | EX ldc1 $f4, SC32_FPREGS+32(a0) |
diff --git a/arch/mips/kernel/r4k_switch.S b/arch/mips/kernel/r4k_switch.S index cc566cf12246..c7698fd9955c 100644 --- a/arch/mips/kernel/r4k_switch.S +++ b/arch/mips/kernel/r4k_switch.S | |||
| @@ -48,8 +48,7 @@ | |||
| 48 | #ifndef CONFIG_CPU_HAS_LLSC | 48 | #ifndef CONFIG_CPU_HAS_LLSC |
| 49 | sw zero, ll_bit | 49 | sw zero, ll_bit |
| 50 | #endif | 50 | #endif |
| 51 | mfc0 t1, CP0_STATUS | 51 | mfc0 t2, CP0_STATUS |
| 52 | LONG_S t1, THREAD_STATUS(a0) | ||
| 53 | cpu_save_nonscratch a0 | 52 | cpu_save_nonscratch a0 |
| 54 | LONG_S ra, THREAD_REG31(a0) | 53 | LONG_S ra, THREAD_REG31(a0) |
| 55 | 54 | ||
| @@ -59,8 +58,8 @@ | |||
| 59 | PTR_L t3, TASK_THREAD_INFO(a0) | 58 | PTR_L t3, TASK_THREAD_INFO(a0) |
| 60 | LONG_L t0, TI_FLAGS(t3) | 59 | LONG_L t0, TI_FLAGS(t3) |
| 61 | li t1, _TIF_USEDFPU | 60 | li t1, _TIF_USEDFPU |
| 62 | and t2, t0, t1 | 61 | and t1, t0 |
| 63 | beqz t2, 1f | 62 | beqz t1, 1f |
| 64 | nor t1, zero, t1 | 63 | nor t1, zero, t1 |
| 65 | 64 | ||
| 66 | and t0, t0, t1 | 65 | and t0, t0, t1 |
| @@ -73,10 +72,13 @@ | |||
| 73 | li t1, ~ST0_CU1 | 72 | li t1, ~ST0_CU1 |
| 74 | and t0, t0, t1 | 73 | and t0, t0, t1 |
| 75 | LONG_S t0, ST_OFF(t3) | 74 | LONG_S t0, ST_OFF(t3) |
| 75 | /* clear thread_struct CU1 bit */ | ||
| 76 | and t2, t1 | ||
| 76 | 77 | ||
| 77 | fpu_save_double a0 t0 t1 # c0_status passed in t0 | 78 | fpu_save_double a0 t0 t1 # c0_status passed in t0 |
| 78 | # clobbers t1 | 79 | # clobbers t1 |
| 79 | 1: | 80 | 1: |
| 81 | LONG_S t2, THREAD_STATUS(a0) | ||
| 80 | 82 | ||
| 81 | /* | 83 | /* |
| 82 | * The order of restoring the registers takes care of the race | 84 | * The order of restoring the registers takes care of the race |
diff --git a/arch/mips/kernel/rtlx.c b/arch/mips/kernel/rtlx.c index e14ae09eda2b..e6e3047151a6 100644 --- a/arch/mips/kernel/rtlx.c +++ b/arch/mips/kernel/rtlx.c | |||
| @@ -54,6 +54,7 @@ static struct chan_waitqueues { | |||
| 54 | wait_queue_head_t rt_queue; | 54 | wait_queue_head_t rt_queue; |
| 55 | wait_queue_head_t lx_queue; | 55 | wait_queue_head_t lx_queue; |
| 56 | atomic_t in_open; | 56 | atomic_t in_open; |
| 57 | struct mutex mutex; | ||
| 57 | } channel_wqs[RTLX_CHANNELS]; | 58 | } channel_wqs[RTLX_CHANNELS]; |
| 58 | 59 | ||
| 59 | static struct irqaction irq; | 60 | static struct irqaction irq; |
| @@ -146,7 +147,7 @@ static void stopping(int vpe) | |||
| 146 | 147 | ||
| 147 | int rtlx_open(int index, int can_sleep) | 148 | int rtlx_open(int index, int can_sleep) |
| 148 | { | 149 | { |
| 149 | volatile struct rtlx_info **p; | 150 | struct rtlx_info **p; |
| 150 | struct rtlx_channel *chan; | 151 | struct rtlx_channel *chan; |
| 151 | enum rtlx_state state; | 152 | enum rtlx_state state; |
| 152 | int ret = 0; | 153 | int ret = 0; |
| @@ -179,13 +180,24 @@ int rtlx_open(int index, int can_sleep) | |||
| 179 | } | 180 | } |
| 180 | } | 181 | } |
| 181 | 182 | ||
| 183 | smp_rmb(); | ||
| 182 | if (*p == NULL) { | 184 | if (*p == NULL) { |
| 183 | if (can_sleep) { | 185 | if (can_sleep) { |
| 184 | __wait_event_interruptible(channel_wqs[index].lx_queue, | 186 | DEFINE_WAIT(wait); |
| 185 | *p != NULL, | 187 | |
| 186 | ret); | 188 | for (;;) { |
| 187 | if (ret) | 189 | prepare_to_wait(&channel_wqs[index].lx_queue, &wait, TASK_INTERRUPTIBLE); |
| 190 | smp_rmb(); | ||
| 191 | if (*p != NULL) | ||
| 192 | break; | ||
| 193 | if (!signal_pending(current)) { | ||
| 194 | schedule(); | ||
| 195 | continue; | ||
| 196 | } | ||
| 197 | ret = -ERESTARTSYS; | ||
| 188 | goto out_fail; | 198 | goto out_fail; |
| 199 | } | ||
| 200 | finish_wait(&channel_wqs[index].lx_queue, &wait); | ||
| 189 | } else { | 201 | } else { |
| 190 | printk(" *vpe_get_shared is NULL. " | 202 | printk(" *vpe_get_shared is NULL. " |
| 191 | "Has an SP program been loaded?\n"); | 203 | "Has an SP program been loaded?\n"); |
| @@ -277,56 +289,52 @@ unsigned int rtlx_write_poll(int index) | |||
| 277 | return write_spacefree(chan->rt_read, chan->rt_write, chan->buffer_size); | 289 | return write_spacefree(chan->rt_read, chan->rt_write, chan->buffer_size); |
| 278 | } | 290 | } |
| 279 | 291 | ||
| 280 | static inline void copy_to(void *dst, void *src, size_t count, int user) | 292 | ssize_t rtlx_read(int index, void __user *buff, size_t count, int user) |
| 281 | { | ||
| 282 | if (user) | ||
| 283 | copy_to_user(dst, src, count); | ||
| 284 | else | ||
| 285 | memcpy(dst, src, count); | ||
| 286 | } | ||
| 287 | |||
| 288 | static inline void copy_from(void *dst, void *src, size_t count, int user) | ||
| 289 | { | 293 | { |
| 290 | if (user) | 294 | size_t lx_write, fl = 0L; |
| 291 | copy_from_user(dst, src, count); | ||
| 292 | else | ||
| 293 | memcpy(dst, src, count); | ||
| 294 | } | ||
| 295 | |||
| 296 | ssize_t rtlx_read(int index, void *buff, size_t count, int user) | ||
| 297 | { | ||
| 298 | size_t fl = 0L; | ||
| 299 | struct rtlx_channel *lx; | 295 | struct rtlx_channel *lx; |
| 296 | unsigned long failed; | ||
| 300 | 297 | ||
| 301 | if (rtlx == NULL) | 298 | if (rtlx == NULL) |
| 302 | return -ENOSYS; | 299 | return -ENOSYS; |
| 303 | 300 | ||
| 304 | lx = &rtlx->channel[index]; | 301 | lx = &rtlx->channel[index]; |
| 305 | 302 | ||
| 303 | mutex_lock(&channel_wqs[index].mutex); | ||
| 304 | smp_rmb(); | ||
| 305 | lx_write = lx->lx_write; | ||
| 306 | |||
| 306 | /* find out how much in total */ | 307 | /* find out how much in total */ |
| 307 | count = min(count, | 308 | count = min(count, |
| 308 | (size_t)(lx->lx_write + lx->buffer_size - lx->lx_read) | 309 | (size_t)(lx_write + lx->buffer_size - lx->lx_read) |
| 309 | % lx->buffer_size); | 310 | % lx->buffer_size); |
| 310 | 311 | ||
| 311 | /* then how much from the read pointer onwards */ | 312 | /* then how much from the read pointer onwards */ |
| 312 | fl = min( count, (size_t)lx->buffer_size - lx->lx_read); | 313 | fl = min(count, (size_t)lx->buffer_size - lx->lx_read); |
| 313 | 314 | ||
| 314 | copy_to(buff, &lx->lx_buffer[lx->lx_read], fl, user); | 315 | failed = copy_to_user(buff, lx->lx_buffer + lx->lx_read, fl); |
| 316 | if (failed) | ||
| 317 | goto out; | ||
| 315 | 318 | ||
| 316 | /* and if there is anything left at the beginning of the buffer */ | 319 | /* and if there is anything left at the beginning of the buffer */ |
| 317 | if ( count - fl ) | 320 | if (count - fl) |
| 318 | copy_to (buff + fl, lx->lx_buffer, count - fl, user); | 321 | failed = copy_to_user(buff + fl, lx->lx_buffer, count - fl); |
| 319 | 322 | ||
| 320 | /* update the index */ | 323 | out: |
| 321 | lx->lx_read += count; | 324 | count -= failed; |
| 322 | lx->lx_read %= lx->buffer_size; | 325 | |
| 326 | smp_wmb(); | ||
| 327 | lx->lx_read = (lx->lx_read + count) % lx->buffer_size; | ||
| 328 | smp_wmb(); | ||
| 329 | mutex_unlock(&channel_wqs[index].mutex); | ||
| 323 | 330 | ||
| 324 | return count; | 331 | return count; |
| 325 | } | 332 | } |
| 326 | 333 | ||
| 327 | ssize_t rtlx_write(int index, void *buffer, size_t count, int user) | 334 | ssize_t rtlx_write(int index, const void __user *buffer, size_t count, int user) |
| 328 | { | 335 | { |
| 329 | struct rtlx_channel *rt; | 336 | struct rtlx_channel *rt; |
| 337 | size_t rt_read; | ||
| 330 | size_t fl; | 338 | size_t fl; |
| 331 | 339 | ||
| 332 | if (rtlx == NULL) | 340 | if (rtlx == NULL) |
| @@ -334,24 +342,35 @@ ssize_t rtlx_write(int index, void *buffer, size_t count, int user) | |||
| 334 | 342 | ||
| 335 | rt = &rtlx->channel[index]; | 343 | rt = &rtlx->channel[index]; |
| 336 | 344 | ||
| 345 | mutex_lock(&channel_wqs[index].mutex); | ||
| 346 | smp_rmb(); | ||
| 347 | rt_read = rt->rt_read; | ||
| 348 | |||
| 337 | /* total number of bytes to copy */ | 349 | /* total number of bytes to copy */ |
| 338 | count = min(count, | 350 | count = min(count, |
| 339 | (size_t)write_spacefree(rt->rt_read, rt->rt_write, | 351 | (size_t)write_spacefree(rt_read, rt->rt_write, rt->buffer_size)); |
| 340 | rt->buffer_size)); | ||
| 341 | 352 | ||
| 342 | /* first bit from write pointer to the end of the buffer, or count */ | 353 | /* first bit from write pointer to the end of the buffer, or count */ |
| 343 | fl = min(count, (size_t) rt->buffer_size - rt->rt_write); | 354 | fl = min(count, (size_t) rt->buffer_size - rt->rt_write); |
| 344 | 355 | ||
| 345 | copy_from (&rt->rt_buffer[rt->rt_write], buffer, fl, user); | 356 | failed = copy_from_user(rt->rt_buffer + rt->rt_write, buffer, fl); |
| 357 | if (failed) | ||
| 358 | goto out; | ||
| 346 | 359 | ||
| 347 | /* if there's any left copy to the beginning of the buffer */ | 360 | /* if there's any left copy to the beginning of the buffer */ |
| 348 | if( count - fl ) | 361 | if (count - fl) { |
| 349 | copy_from (rt->rt_buffer, buffer + fl, count - fl, user); | 362 | failed = copy_from_user(rt->rt_buffer, buffer + fl, count - fl); |
| 363 | } | ||
| 364 | |||
| 365 | out: | ||
| 366 | count -= cailed; | ||
| 350 | 367 | ||
| 351 | rt->rt_write += count; | 368 | smp_wmb(); |
| 352 | rt->rt_write %= rt->buffer_size; | 369 | rt->rt_write = (rt->rt_write + count) % rt->buffer_size; |
| 370 | smp_wmb(); | ||
| 371 | mutex_unlock(&channel_wqs[index].mutex); | ||
| 353 | 372 | ||
| 354 | return(count); | 373 | return count; |
| 355 | } | 374 | } |
| 356 | 375 | ||
| 357 | 376 | ||
| @@ -403,7 +422,7 @@ static ssize_t file_read(struct file *file, char __user * buffer, size_t count, | |||
| 403 | return 0; // -EAGAIN makes cat whinge | 422 | return 0; // -EAGAIN makes cat whinge |
| 404 | } | 423 | } |
| 405 | 424 | ||
| 406 | return rtlx_read(minor, buffer, count, 1); | 425 | return rtlx_read(minor, buffer, count); |
| 407 | } | 426 | } |
| 408 | 427 | ||
| 409 | static ssize_t file_write(struct file *file, const char __user * buffer, | 428 | static ssize_t file_write(struct file *file, const char __user * buffer, |
| @@ -429,7 +448,7 @@ static ssize_t file_write(struct file *file, const char __user * buffer, | |||
| 429 | return ret; | 448 | return ret; |
| 430 | } | 449 | } |
| 431 | 450 | ||
| 432 | return rtlx_write(minor, (void *)buffer, count, 1); | 451 | return rtlx_write(minor, buffer, count); |
| 433 | } | 452 | } |
| 434 | 453 | ||
| 435 | static const struct file_operations rtlx_fops = { | 454 | static const struct file_operations rtlx_fops = { |
| @@ -468,6 +487,7 @@ static int rtlx_module_init(void) | |||
| 468 | init_waitqueue_head(&channel_wqs[i].rt_queue); | 487 | init_waitqueue_head(&channel_wqs[i].rt_queue); |
| 469 | init_waitqueue_head(&channel_wqs[i].lx_queue); | 488 | init_waitqueue_head(&channel_wqs[i].lx_queue); |
| 470 | atomic_set(&channel_wqs[i].in_open, 0); | 489 | atomic_set(&channel_wqs[i].in_open, 0); |
| 490 | mutex_init(&channel_wqs[i].mutex); | ||
| 471 | 491 | ||
| 472 | dev = device_create(mt_class, NULL, MKDEV(major, i), | 492 | dev = device_create(mt_class, NULL, MKDEV(major, i), |
| 473 | "%s%d", module_name, i); | 493 | "%s%d", module_name, i); |
diff --git a/arch/mips/kernel/signal-common.h b/arch/mips/kernel/signal-common.h index fdbdbdc65b54..297dfcb97524 100644 --- a/arch/mips/kernel/signal-common.h +++ b/arch/mips/kernel/signal-common.h | |||
| @@ -31,4 +31,7 @@ extern void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, | |||
| 31 | */ | 31 | */ |
| 32 | extern int install_sigtramp(unsigned int __user *tramp, unsigned int syscall); | 32 | extern int install_sigtramp(unsigned int __user *tramp, unsigned int syscall); |
| 33 | 33 | ||
| 34 | /* Check and clear pending FPU exceptions in saved CSR */ | ||
| 35 | extern int fpcsr_pending(unsigned int __user *fpcsr); | ||
| 36 | |||
| 34 | #endif /* __SIGNAL_COMMON_H */ | 37 | #endif /* __SIGNAL_COMMON_H */ |
diff --git a/arch/mips/kernel/signal.c b/arch/mips/kernel/signal.c index f091786187a6..8c3c5a5789b0 100644 --- a/arch/mips/kernel/signal.c +++ b/arch/mips/kernel/signal.c | |||
| @@ -82,6 +82,7 @@ int setup_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc) | |||
| 82 | { | 82 | { |
| 83 | int err = 0; | 83 | int err = 0; |
| 84 | int i; | 84 | int i; |
| 85 | unsigned int used_math; | ||
| 85 | 86 | ||
| 86 | err |= __put_user(regs->cp0_epc, &sc->sc_pc); | 87 | err |= __put_user(regs->cp0_epc, &sc->sc_pc); |
| 87 | 88 | ||
| @@ -104,26 +105,53 @@ int setup_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc) | |||
| 104 | err |= __put_user(rddsp(DSP_MASK), &sc->sc_dsp); | 105 | err |= __put_user(rddsp(DSP_MASK), &sc->sc_dsp); |
| 105 | } | 106 | } |
| 106 | 107 | ||
| 107 | err |= __put_user(!!used_math(), &sc->sc_used_math); | 108 | used_math = !!used_math(); |
| 109 | err |= __put_user(used_math, &sc->sc_used_math); | ||
| 108 | 110 | ||
| 109 | if (used_math()) { | 111 | if (used_math) { |
| 110 | /* | 112 | /* |
| 111 | * Save FPU state to signal context. Signal handler | 113 | * Save FPU state to signal context. Signal handler |
| 112 | * will "inherit" current FPU state. | 114 | * will "inherit" current FPU state. |
| 113 | */ | 115 | */ |
| 114 | preempt_disable(); | 116 | own_fpu(1); |
| 115 | 117 | enable_fp_in_kernel(); | |
| 116 | if (!is_fpu_owner()) { | ||
| 117 | own_fpu(); | ||
| 118 | restore_fp(current); | ||
| 119 | } | ||
| 120 | err |= save_fp_context(sc); | 118 | err |= save_fp_context(sc); |
| 121 | 119 | disable_fp_in_kernel(); | |
| 122 | preempt_enable(); | ||
| 123 | } | 120 | } |
| 124 | return err; | 121 | return err; |
| 125 | } | 122 | } |
| 126 | 123 | ||
| 124 | int fpcsr_pending(unsigned int __user *fpcsr) | ||
| 125 | { | ||
| 126 | int err, sig = 0; | ||
| 127 | unsigned int csr, enabled; | ||
| 128 | |||
| 129 | err = __get_user(csr, fpcsr); | ||
| 130 | enabled = FPU_CSR_UNI_X | ((csr & FPU_CSR_ALL_E) << 5); | ||
| 131 | /* | ||
| 132 | * If the signal handler set some FPU exceptions, clear it and | ||
| 133 | * send SIGFPE. | ||
| 134 | */ | ||
| 135 | if (csr & enabled) { | ||
| 136 | csr &= ~enabled; | ||
| 137 | err |= __put_user(csr, fpcsr); | ||
| 138 | sig = SIGFPE; | ||
| 139 | } | ||
| 140 | return err ?: sig; | ||
| 141 | } | ||
| 142 | |||
| 143 | static int | ||
| 144 | check_and_restore_fp_context(struct sigcontext __user *sc) | ||
| 145 | { | ||
| 146 | int err, sig; | ||
| 147 | |||
| 148 | err = sig = fpcsr_pending(&sc->sc_fpc_csr); | ||
| 149 | if (err > 0) | ||
| 150 | err = 0; | ||
| 151 | err |= restore_fp_context(sc); | ||
| 152 | return err ?: sig; | ||
| 153 | } | ||
| 154 | |||
| 127 | int restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc) | 155 | int restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc) |
| 128 | { | 156 | { |
| 129 | unsigned int used_math; | 157 | unsigned int used_math; |
| @@ -157,19 +185,18 @@ int restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc) | |||
| 157 | err |= __get_user(used_math, &sc->sc_used_math); | 185 | err |= __get_user(used_math, &sc->sc_used_math); |
| 158 | conditional_used_math(used_math); | 186 | conditional_used_math(used_math); |
| 159 | 187 | ||
| 160 | preempt_disable(); | 188 | if (used_math) { |
| 161 | |||
| 162 | if (used_math()) { | ||
| 163 | /* restore fpu context if we have used it before */ | 189 | /* restore fpu context if we have used it before */ |
| 164 | own_fpu(); | 190 | own_fpu(0); |
| 165 | err |= restore_fp_context(sc); | 191 | enable_fp_in_kernel(); |
| 192 | if (!err) | ||
| 193 | err = check_and_restore_fp_context(sc); | ||
| 194 | disable_fp_in_kernel(); | ||
| 166 | } else { | 195 | } else { |
| 167 | /* signal handler may have used FPU. Give it up. */ | 196 | /* signal handler may have used FPU. Give it up. */ |
| 168 | lose_fpu(); | 197 | lose_fpu(0); |
| 169 | } | 198 | } |
| 170 | 199 | ||
| 171 | preempt_enable(); | ||
| 172 | |||
| 173 | return err; | 200 | return err; |
| 174 | } | 201 | } |
| 175 | 202 | ||
| @@ -332,6 +359,7 @@ asmlinkage void sys_sigreturn(nabi_no_regargs struct pt_regs regs) | |||
| 332 | { | 359 | { |
| 333 | struct sigframe __user *frame; | 360 | struct sigframe __user *frame; |
| 334 | sigset_t blocked; | 361 | sigset_t blocked; |
| 362 | int sig; | ||
| 335 | 363 | ||
| 336 | frame = (struct sigframe __user *) regs.regs[29]; | 364 | frame = (struct sigframe __user *) regs.regs[29]; |
| 337 | if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) | 365 | if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) |
| @@ -345,8 +373,11 @@ asmlinkage void sys_sigreturn(nabi_no_regargs struct pt_regs regs) | |||
| 345 | recalc_sigpending(); | 373 | recalc_sigpending(); |
| 346 | spin_unlock_irq(¤t->sighand->siglock); | 374 | spin_unlock_irq(¤t->sighand->siglock); |
| 347 | 375 | ||
| 348 | if (restore_sigcontext(®s, &frame->sf_sc)) | 376 | sig = restore_sigcontext(®s, &frame->sf_sc); |
| 377 | if (sig < 0) | ||
| 349 | goto badframe; | 378 | goto badframe; |
| 379 | else if (sig) | ||
| 380 | force_sig(sig, current); | ||
| 350 | 381 | ||
| 351 | /* | 382 | /* |
| 352 | * Don't let your children do this ... | 383 | * Don't let your children do this ... |
| @@ -368,6 +399,7 @@ asmlinkage void sys_rt_sigreturn(nabi_no_regargs struct pt_regs regs) | |||
| 368 | struct rt_sigframe __user *frame; | 399 | struct rt_sigframe __user *frame; |
| 369 | sigset_t set; | 400 | sigset_t set; |
| 370 | stack_t st; | 401 | stack_t st; |
| 402 | int sig; | ||
| 371 | 403 | ||
| 372 | frame = (struct rt_sigframe __user *) regs.regs[29]; | 404 | frame = (struct rt_sigframe __user *) regs.regs[29]; |
| 373 | if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) | 405 | if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) |
| @@ -381,8 +413,11 @@ asmlinkage void sys_rt_sigreturn(nabi_no_regargs struct pt_regs regs) | |||
| 381 | recalc_sigpending(); | 413 | recalc_sigpending(); |
| 382 | spin_unlock_irq(¤t->sighand->siglock); | 414 | spin_unlock_irq(¤t->sighand->siglock); |
| 383 | 415 | ||
| 384 | if (restore_sigcontext(®s, &frame->rs_uc.uc_mcontext)) | 416 | sig = restore_sigcontext(®s, &frame->rs_uc.uc_mcontext); |
| 417 | if (sig < 0) | ||
| 385 | goto badframe; | 418 | goto badframe; |
| 419 | else if (sig) | ||
| 420 | force_sig(sig, current); | ||
| 386 | 421 | ||
| 387 | if (__copy_from_user(&st, &frame->rs_uc.uc_stack, sizeof(st))) | 422 | if (__copy_from_user(&st, &frame->rs_uc.uc_stack, sizeof(st))) |
| 388 | goto badframe; | 423 | goto badframe; |
diff --git a/arch/mips/kernel/signal32.c b/arch/mips/kernel/signal32.c index 19bbef001959..151fd2f0893a 100644 --- a/arch/mips/kernel/signal32.c +++ b/arch/mips/kernel/signal32.c | |||
| @@ -181,6 +181,7 @@ static int setup_sigcontext32(struct pt_regs *regs, | |||
| 181 | { | 181 | { |
| 182 | int err = 0; | 182 | int err = 0; |
| 183 | int i; | 183 | int i; |
| 184 | u32 used_math; | ||
| 184 | 185 | ||
| 185 | err |= __put_user(regs->cp0_epc, &sc->sc_pc); | 186 | err |= __put_user(regs->cp0_epc, &sc->sc_pc); |
| 186 | 187 | ||
| @@ -200,26 +201,34 @@ static int setup_sigcontext32(struct pt_regs *regs, | |||
| 200 | err |= __put_user(mflo3(), &sc->sc_lo3); | 201 | err |= __put_user(mflo3(), &sc->sc_lo3); |
| 201 | } | 202 | } |
| 202 | 203 | ||
| 203 | err |= __put_user(!!used_math(), &sc->sc_used_math); | 204 | used_math = !!used_math(); |
| 205 | err |= __put_user(used_math, &sc->sc_used_math); | ||
| 204 | 206 | ||
| 205 | if (used_math()) { | 207 | if (used_math) { |
| 206 | /* | 208 | /* |
| 207 | * Save FPU state to signal context. Signal handler | 209 | * Save FPU state to signal context. Signal handler |
| 208 | * will "inherit" current FPU state. | 210 | * will "inherit" current FPU state. |
| 209 | */ | 211 | */ |
| 210 | preempt_disable(); | 212 | own_fpu(1); |
| 211 | 213 | enable_fp_in_kernel(); | |
| 212 | if (!is_fpu_owner()) { | ||
| 213 | own_fpu(); | ||
| 214 | restore_fp(current); | ||
| 215 | } | ||
| 216 | err |= save_fp_context32(sc); | 214 | err |= save_fp_context32(sc); |
| 217 | 215 | disable_fp_in_kernel(); | |
| 218 | preempt_enable(); | ||
| 219 | } | 216 | } |
| 220 | return err; | 217 | return err; |
| 221 | } | 218 | } |
| 222 | 219 | ||
| 220 | static int | ||
| 221 | check_and_restore_fp_context32(struct sigcontext32 __user *sc) | ||
| 222 | { | ||
| 223 | int err, sig; | ||
| 224 | |||
| 225 | err = sig = fpcsr_pending(&sc->sc_fpc_csr); | ||
| 226 | if (err > 0) | ||
| 227 | err = 0; | ||
| 228 | err |= restore_fp_context32(sc); | ||
| 229 | return err ?: sig; | ||
| 230 | } | ||
| 231 | |||
| 223 | static int restore_sigcontext32(struct pt_regs *regs, | 232 | static int restore_sigcontext32(struct pt_regs *regs, |
| 224 | struct sigcontext32 __user *sc) | 233 | struct sigcontext32 __user *sc) |
| 225 | { | 234 | { |
| @@ -250,19 +259,18 @@ static int restore_sigcontext32(struct pt_regs *regs, | |||
| 250 | err |= __get_user(used_math, &sc->sc_used_math); | 259 | err |= __get_user(used_math, &sc->sc_used_math); |
| 251 | conditional_used_math(used_math); | 260 | conditional_used_math(used_math); |
| 252 | 261 | ||
| 253 | preempt_disable(); | 262 | if (used_math) { |
| 254 | |||
| 255 | if (used_math()) { | ||
| 256 | /* restore fpu context if we have used it before */ | 263 | /* restore fpu context if we have used it before */ |
| 257 | own_fpu(); | 264 | own_fpu(0); |
| 258 | err |= restore_fp_context32(sc); | 265 | enable_fp_in_kernel(); |
| 266 | if (!err) | ||
| 267 | err = check_and_restore_fp_context32(sc); | ||
| 268 | disable_fp_in_kernel(); | ||
| 259 | } else { | 269 | } else { |
| 260 | /* signal handler may have used FPU. Give it up. */ | 270 | /* signal handler may have used FPU. Give it up. */ |
| 261 | lose_fpu(); | 271 | lose_fpu(0); |
| 262 | } | 272 | } |
| 263 | 273 | ||
| 264 | preempt_enable(); | ||
| 265 | |||
| 266 | return err; | 274 | return err; |
| 267 | } | 275 | } |
| 268 | 276 | ||
| @@ -508,6 +516,7 @@ asmlinkage void sys32_sigreturn(nabi_no_regargs struct pt_regs regs) | |||
| 508 | { | 516 | { |
| 509 | struct sigframe32 __user *frame; | 517 | struct sigframe32 __user *frame; |
| 510 | sigset_t blocked; | 518 | sigset_t blocked; |
| 519 | int sig; | ||
| 511 | 520 | ||
| 512 | frame = (struct sigframe32 __user *) regs.regs[29]; | 521 | frame = (struct sigframe32 __user *) regs.regs[29]; |
| 513 | if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) | 522 | if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) |
| @@ -521,8 +530,11 @@ asmlinkage void sys32_sigreturn(nabi_no_regargs struct pt_regs regs) | |||
| 521 | recalc_sigpending(); | 530 | recalc_sigpending(); |
| 522 | spin_unlock_irq(¤t->sighand->siglock); | 531 | spin_unlock_irq(¤t->sighand->siglock); |
| 523 | 532 | ||
| 524 | if (restore_sigcontext32(®s, &frame->sf_sc)) | 533 | sig = restore_sigcontext32(®s, &frame->sf_sc); |
| 534 | if (sig < 0) | ||
| 525 | goto badframe; | 535 | goto badframe; |
| 536 | else if (sig) | ||
| 537 | force_sig(sig, current); | ||
| 526 | 538 | ||
| 527 | /* | 539 | /* |
| 528 | * Don't let your children do this ... | 540 | * Don't let your children do this ... |
| @@ -545,6 +557,7 @@ asmlinkage void sys32_rt_sigreturn(nabi_no_regargs struct pt_regs regs) | |||
| 545 | sigset_t set; | 557 | sigset_t set; |
| 546 | stack_t st; | 558 | stack_t st; |
| 547 | s32 sp; | 559 | s32 sp; |
| 560 | int sig; | ||
| 548 | 561 | ||
| 549 | frame = (struct rt_sigframe32 __user *) regs.regs[29]; | 562 | frame = (struct rt_sigframe32 __user *) regs.regs[29]; |
| 550 | if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) | 563 | if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) |
| @@ -558,8 +571,11 @@ asmlinkage void sys32_rt_sigreturn(nabi_no_regargs struct pt_regs regs) | |||
| 558 | recalc_sigpending(); | 571 | recalc_sigpending(); |
| 559 | spin_unlock_irq(¤t->sighand->siglock); | 572 | spin_unlock_irq(¤t->sighand->siglock); |
| 560 | 573 | ||
| 561 | if (restore_sigcontext32(®s, &frame->rs_uc.uc_mcontext)) | 574 | sig = restore_sigcontext32(®s, &frame->rs_uc.uc_mcontext); |
| 575 | if (sig < 0) | ||
| 562 | goto badframe; | 576 | goto badframe; |
| 577 | else if (sig) | ||
| 578 | force_sig(sig, current); | ||
| 563 | 579 | ||
| 564 | /* The ucontext contains a stack32_t, so we must convert! */ | 580 | /* The ucontext contains a stack32_t, so we must convert! */ |
| 565 | if (__get_user(sp, &frame->rs_uc.uc_stack.ss_sp)) | 581 | if (__get_user(sp, &frame->rs_uc.uc_stack.ss_sp)) |
diff --git a/arch/mips/kernel/signal_n32.c b/arch/mips/kernel/signal_n32.c index ecf1f7ecaad9..a9202fa95987 100644 --- a/arch/mips/kernel/signal_n32.c +++ b/arch/mips/kernel/signal_n32.c | |||
| @@ -127,6 +127,7 @@ asmlinkage void sysn32_rt_sigreturn(nabi_no_regargs struct pt_regs regs) | |||
| 127 | sigset_t set; | 127 | sigset_t set; |
| 128 | stack_t st; | 128 | stack_t st; |
| 129 | s32 sp; | 129 | s32 sp; |
| 130 | int sig; | ||
| 130 | 131 | ||
| 131 | frame = (struct rt_sigframe_n32 __user *) regs.regs[29]; | 132 | frame = (struct rt_sigframe_n32 __user *) regs.regs[29]; |
| 132 | if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) | 133 | if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) |
| @@ -140,8 +141,11 @@ asmlinkage void sysn32_rt_sigreturn(nabi_no_regargs struct pt_regs regs) | |||
| 140 | recalc_sigpending(); | 141 | recalc_sigpending(); |
| 141 | spin_unlock_irq(¤t->sighand->siglock); | 142 | spin_unlock_irq(¤t->sighand->siglock); |
| 142 | 143 | ||
| 143 | if (restore_sigcontext(®s, &frame->rs_uc.uc_mcontext)) | 144 | sig = restore_sigcontext(®s, &frame->rs_uc.uc_mcontext); |
| 145 | if (sig < 0) | ||
| 144 | goto badframe; | 146 | goto badframe; |
| 147 | else if (sig) | ||
| 148 | force_sig(sig, current); | ||
| 145 | 149 | ||
| 146 | /* The ucontext contains a stack32_t, so we must convert! */ | 150 | /* The ucontext contains a stack32_t, so we must convert! */ |
| 147 | if (__get_user(sp, &frame->rs_uc.uc_stack.ss_sp)) | 151 | if (__get_user(sp, &frame->rs_uc.uc_stack.ss_sp)) |
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index 18f56a9dbcfa..7d76a85422b2 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c | |||
| @@ -610,16 +610,6 @@ asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31) | |||
| 610 | if (fcr31 & FPU_CSR_UNI_X) { | 610 | if (fcr31 & FPU_CSR_UNI_X) { |
| 611 | int sig; | 611 | int sig; |
| 612 | 612 | ||
| 613 | preempt_disable(); | ||
| 614 | |||
| 615 | #ifdef CONFIG_PREEMPT | ||
| 616 | if (!is_fpu_owner()) { | ||
| 617 | /* We might lose fpu before disabling preempt... */ | ||
| 618 | own_fpu(); | ||
| 619 | BUG_ON(!used_math()); | ||
| 620 | restore_fp(current); | ||
| 621 | } | ||
| 622 | #endif | ||
| 623 | /* | 613 | /* |
| 624 | * Unimplemented operation exception. If we've got the full | 614 | * Unimplemented operation exception. If we've got the full |
| 625 | * software emulator on-board, let's use it... | 615 | * software emulator on-board, let's use it... |
| @@ -630,18 +620,12 @@ asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31) | |||
| 630 | * register operands before invoking the emulator, which seems | 620 | * register operands before invoking the emulator, which seems |
| 631 | * a bit extreme for what should be an infrequent event. | 621 | * a bit extreme for what should be an infrequent event. |
| 632 | */ | 622 | */ |
| 633 | save_fp(current); | ||
| 634 | /* Ensure 'resume' not overwrite saved fp context again. */ | 623 | /* Ensure 'resume' not overwrite saved fp context again. */ |
| 635 | lose_fpu(); | 624 | lose_fpu(1); |
| 636 | |||
| 637 | preempt_enable(); | ||
| 638 | 625 | ||
| 639 | /* Run the emulator */ | 626 | /* Run the emulator */ |
| 640 | sig = fpu_emulator_cop1Handler (regs, ¤t->thread.fpu, 1); | 627 | sig = fpu_emulator_cop1Handler (regs, ¤t->thread.fpu, 1); |
| 641 | 628 | ||
| 642 | preempt_disable(); | ||
| 643 | |||
| 644 | own_fpu(); /* Using the FPU again. */ | ||
| 645 | /* | 629 | /* |
| 646 | * We can't allow the emulated instruction to leave any of | 630 | * We can't allow the emulated instruction to leave any of |
| 647 | * the cause bit set in $fcr31. | 631 | * the cause bit set in $fcr31. |
| @@ -649,9 +633,7 @@ asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31) | |||
| 649 | current->thread.fpu.fcr31 &= ~FPU_CSR_ALL_X; | 633 | current->thread.fpu.fcr31 &= ~FPU_CSR_ALL_X; |
| 650 | 634 | ||
| 651 | /* Restore the hardware register state */ | 635 | /* Restore the hardware register state */ |
| 652 | restore_fp(current); | 636 | own_fpu(1); /* Using the FPU again. */ |
| 653 | |||
| 654 | preempt_enable(); | ||
| 655 | 637 | ||
| 656 | /* If something went wrong, signal */ | 638 | /* If something went wrong, signal */ |
| 657 | if (sig) | 639 | if (sig) |
| @@ -775,12 +757,11 @@ asmlinkage void do_cpu(struct pt_regs *regs) | |||
| 775 | { | 757 | { |
| 776 | unsigned int cpid; | 758 | unsigned int cpid; |
| 777 | 759 | ||
| 778 | die_if_kernel("do_cpu invoked from kernel context!", regs); | ||
| 779 | |||
| 780 | cpid = (regs->cp0_cause >> CAUSEB_CE) & 3; | 760 | cpid = (regs->cp0_cause >> CAUSEB_CE) & 3; |
| 781 | 761 | ||
| 782 | switch (cpid) { | 762 | switch (cpid) { |
| 783 | case 0: | 763 | case 0: |
| 764 | die_if_kernel("do_cpu invoked from kernel context!", regs); | ||
| 784 | if (!cpu_has_llsc) | 765 | if (!cpu_has_llsc) |
| 785 | if (!simulate_llsc(regs)) | 766 | if (!simulate_llsc(regs)) |
| 786 | return; | 767 | return; |
| @@ -791,21 +772,30 @@ asmlinkage void do_cpu(struct pt_regs *regs) | |||
| 791 | break; | 772 | break; |
| 792 | 773 | ||
| 793 | case 1: | 774 | case 1: |
| 794 | preempt_disable(); | 775 | if (!test_thread_flag(TIF_ALLOW_FP_IN_KERNEL)) |
| 795 | 776 | die_if_kernel("do_cpu invoked from kernel context!", | |
| 796 | own_fpu(); | 777 | regs); |
| 797 | if (used_math()) { /* Using the FPU again. */ | 778 | if (used_math()) /* Using the FPU again. */ |
| 798 | restore_fp(current); | 779 | own_fpu(1); |
| 799 | } else { /* First time FPU user. */ | 780 | else { /* First time FPU user. */ |
| 800 | init_fpu(); | 781 | init_fpu(); |
| 801 | set_used_math(); | 782 | set_used_math(); |
| 802 | } | 783 | } |
| 803 | 784 | ||
| 804 | if (cpu_has_fpu) { | 785 | if (raw_cpu_has_fpu) { |
| 805 | preempt_enable(); | 786 | if (test_thread_flag(TIF_ALLOW_FP_IN_KERNEL)) { |
| 787 | local_irq_disable(); | ||
| 788 | if (cpu_has_fpu) | ||
| 789 | regs->cp0_status |= ST0_CU1; | ||
| 790 | /* | ||
| 791 | * We must return without enabling | ||
| 792 | * interrupts to ensure keep FPU | ||
| 793 | * ownership until resume. | ||
| 794 | */ | ||
| 795 | return; | ||
| 796 | } | ||
| 806 | } else { | 797 | } else { |
| 807 | int sig; | 798 | int sig; |
| 808 | preempt_enable(); | ||
| 809 | sig = fpu_emulator_cop1Handler(regs, | 799 | sig = fpu_emulator_cop1Handler(regs, |
| 810 | ¤t->thread.fpu, 0); | 800 | ¤t->thread.fpu, 0); |
| 811 | if (sig) | 801 | if (sig) |
| @@ -1259,26 +1249,26 @@ static inline void mips_srs_init(void) | |||
| 1259 | /* | 1249 | /* |
| 1260 | * This is used by native signal handling | 1250 | * This is used by native signal handling |
| 1261 | */ | 1251 | */ |
| 1262 | asmlinkage int (*save_fp_context)(struct sigcontext *sc); | 1252 | asmlinkage int (*save_fp_context)(struct sigcontext __user *sc); |
| 1263 | asmlinkage int (*restore_fp_context)(struct sigcontext *sc); | 1253 | asmlinkage int (*restore_fp_context)(struct sigcontext __user *sc); |
| 1264 | 1254 | ||
| 1265 | extern asmlinkage int _save_fp_context(struct sigcontext *sc); | 1255 | extern asmlinkage int _save_fp_context(struct sigcontext __user *sc); |
| 1266 | extern asmlinkage int _restore_fp_context(struct sigcontext *sc); | 1256 | extern asmlinkage int _restore_fp_context(struct sigcontext __user *sc); |
| 1267 | 1257 | ||
| 1268 | extern asmlinkage int fpu_emulator_save_context(struct sigcontext *sc); | 1258 | extern asmlinkage int fpu_emulator_save_context(struct sigcontext __user *sc); |
| 1269 | extern asmlinkage int fpu_emulator_restore_context(struct sigcontext *sc); | 1259 | extern asmlinkage int fpu_emulator_restore_context(struct sigcontext __user *sc); |
| 1270 | 1260 | ||
| 1271 | #ifdef CONFIG_SMP | 1261 | #ifdef CONFIG_SMP |
| 1272 | static int smp_save_fp_context(struct sigcontext *sc) | 1262 | static int smp_save_fp_context(struct sigcontext __user *sc) |
| 1273 | { | 1263 | { |
| 1274 | return cpu_has_fpu | 1264 | return raw_cpu_has_fpu |
| 1275 | ? _save_fp_context(sc) | 1265 | ? _save_fp_context(sc) |
| 1276 | : fpu_emulator_save_context(sc); | 1266 | : fpu_emulator_save_context(sc); |
| 1277 | } | 1267 | } |
| 1278 | 1268 | ||
| 1279 | static int smp_restore_fp_context(struct sigcontext *sc) | 1269 | static int smp_restore_fp_context(struct sigcontext __user *sc) |
| 1280 | { | 1270 | { |
| 1281 | return cpu_has_fpu | 1271 | return raw_cpu_has_fpu |
| 1282 | ? _restore_fp_context(sc) | 1272 | ? _restore_fp_context(sc) |
| 1283 | : fpu_emulator_restore_context(sc); | 1273 | : fpu_emulator_restore_context(sc); |
| 1284 | } | 1274 | } |
| @@ -1306,14 +1296,14 @@ static inline void signal_init(void) | |||
| 1306 | /* | 1296 | /* |
| 1307 | * This is used by 32-bit signal stuff on the 64-bit kernel | 1297 | * This is used by 32-bit signal stuff on the 64-bit kernel |
| 1308 | */ | 1298 | */ |
| 1309 | asmlinkage int (*save_fp_context32)(struct sigcontext32 *sc); | 1299 | asmlinkage int (*save_fp_context32)(struct sigcontext32 __user *sc); |
| 1310 | asmlinkage int (*restore_fp_context32)(struct sigcontext32 *sc); | 1300 | asmlinkage int (*restore_fp_context32)(struct sigcontext32 __user *sc); |
| 1311 | 1301 | ||
| 1312 | extern asmlinkage int _save_fp_context32(struct sigcontext32 *sc); | 1302 | extern asmlinkage int _save_fp_context32(struct sigcontext32 __user *sc); |
| 1313 | extern asmlinkage int _restore_fp_context32(struct sigcontext32 *sc); | 1303 | extern asmlinkage int _restore_fp_context32(struct sigcontext32 __user *sc); |
| 1314 | 1304 | ||
| 1315 | extern asmlinkage int fpu_emulator_save_context32(struct sigcontext32 *sc); | 1305 | extern asmlinkage int fpu_emulator_save_context32(struct sigcontext32 __user *sc); |
| 1316 | extern asmlinkage int fpu_emulator_restore_context32(struct sigcontext32 *sc); | 1306 | extern asmlinkage int fpu_emulator_restore_context32(struct sigcontext32 __user *sc); |
| 1317 | 1307 | ||
| 1318 | static inline void signal32_init(void) | 1308 | static inline void signal32_init(void) |
| 1319 | { | 1309 | { |
diff --git a/arch/mips/math-emu/kernel_linkage.c b/arch/mips/math-emu/kernel_linkage.c index 5b3390f64917..ed49ef01ac53 100644 --- a/arch/mips/math-emu/kernel_linkage.c +++ b/arch/mips/math-emu/kernel_linkage.c | |||
| @@ -51,7 +51,7 @@ void fpu_emulator_init_fpu(void) | |||
| 51 | * with appropriate macros from uaccess.h | 51 | * with appropriate macros from uaccess.h |
| 52 | */ | 52 | */ |
| 53 | 53 | ||
| 54 | int fpu_emulator_save_context(struct sigcontext *sc) | 54 | int fpu_emulator_save_context(struct sigcontext __user *sc) |
| 55 | { | 55 | { |
| 56 | int i; | 56 | int i; |
| 57 | int err = 0; | 57 | int err = 0; |
| @@ -65,7 +65,7 @@ int fpu_emulator_save_context(struct sigcontext *sc) | |||
| 65 | return err; | 65 | return err; |
| 66 | } | 66 | } |
| 67 | 67 | ||
| 68 | int fpu_emulator_restore_context(struct sigcontext *sc) | 68 | int fpu_emulator_restore_context(struct sigcontext __user *sc) |
| 69 | { | 69 | { |
| 70 | int i; | 70 | int i; |
| 71 | int err = 0; | 71 | int err = 0; |
| @@ -84,7 +84,7 @@ int fpu_emulator_restore_context(struct sigcontext *sc) | |||
| 84 | * This is the o32 version | 84 | * This is the o32 version |
| 85 | */ | 85 | */ |
| 86 | 86 | ||
| 87 | int fpu_emulator_save_context32(struct sigcontext32 *sc) | 87 | int fpu_emulator_save_context32(struct sigcontext32 __user *sc) |
| 88 | { | 88 | { |
| 89 | int i; | 89 | int i; |
| 90 | int err = 0; | 90 | int err = 0; |
| @@ -98,7 +98,7 @@ int fpu_emulator_save_context32(struct sigcontext32 *sc) | |||
| 98 | return err; | 98 | return err; |
| 99 | } | 99 | } |
| 100 | 100 | ||
| 101 | int fpu_emulator_restore_context32(struct sigcontext32 *sc) | 101 | int fpu_emulator_restore_context32(struct sigcontext32 __user *sc) |
| 102 | { | 102 | { |
| 103 | int i; | 103 | int i; |
| 104 | int err = 0; | 104 | int err = 0; |
diff --git a/drivers/char/lcd.c b/drivers/char/lcd.c index 5f4fdcf7c96e..1f0962616ee5 100644 --- a/drivers/char/lcd.c +++ b/drivers/char/lcd.c | |||
| @@ -11,9 +11,6 @@ | |||
| 11 | * March 2001: Ported from 2.0.34 by Liam Davies | 11 | * March 2001: Ported from 2.0.34 by Liam Davies |
| 12 | * | 12 | * |
| 13 | */ | 13 | */ |
| 14 | |||
| 15 | #define RTC_IO_EXTENT 0x10 /*Only really two ports, but... */ | ||
| 16 | |||
| 17 | #include <linux/types.h> | 14 | #include <linux/types.h> |
| 18 | #include <linux/errno.h> | 15 | #include <linux/errno.h> |
| 19 | #include <linux/miscdevice.h> | 16 | #include <linux/miscdevice.h> |
| @@ -32,8 +29,6 @@ | |||
| 32 | 29 | ||
| 33 | #include "lcd.h" | 30 | #include "lcd.h" |
| 34 | 31 | ||
| 35 | static DEFINE_SPINLOCK(lcd_lock); | ||
| 36 | |||
| 37 | static int lcd_ioctl(struct inode *inode, struct file *file, | 32 | static int lcd_ioctl(struct inode *inode, struct file *file, |
| 38 | unsigned int cmd, unsigned long arg); | 33 | unsigned int cmd, unsigned long arg); |
| 39 | 34 | ||
diff --git a/include/asm-mips/atomic.h b/include/asm-mips/atomic.h index 8578869a8bcf..1ac50b6c47ad 100644 --- a/include/asm-mips/atomic.h +++ b/include/asm-mips/atomic.h | |||
| @@ -79,9 +79,9 @@ static __inline__ void atomic_add(int i, atomic_t * v) | |||
| 79 | } else { | 79 | } else { |
| 80 | unsigned long flags; | 80 | unsigned long flags; |
| 81 | 81 | ||
| 82 | local_irq_save(flags); | 82 | raw_local_irq_save(flags); |
| 83 | v->counter += i; | 83 | v->counter += i; |
| 84 | local_irq_restore(flags); | 84 | raw_local_irq_restore(flags); |
| 85 | } | 85 | } |
| 86 | } | 86 | } |
| 87 | 87 | ||
| @@ -124,9 +124,9 @@ static __inline__ void atomic_sub(int i, atomic_t * v) | |||
| 124 | } else { | 124 | } else { |
| 125 | unsigned long flags; | 125 | unsigned long flags; |
| 126 | 126 | ||
| 127 | local_irq_save(flags); | 127 | raw_local_irq_save(flags); |
| 128 | v->counter -= i; | 128 | v->counter -= i; |
| 129 | local_irq_restore(flags); | 129 | raw_local_irq_restore(flags); |
| 130 | } | 130 | } |
| 131 | } | 131 | } |
| 132 | 132 | ||
| @@ -173,11 +173,11 @@ static __inline__ int atomic_add_return(int i, atomic_t * v) | |||
| 173 | } else { | 173 | } else { |
| 174 | unsigned long flags; | 174 | unsigned long flags; |
| 175 | 175 | ||
| 176 | local_irq_save(flags); | 176 | raw_local_irq_save(flags); |
| 177 | result = v->counter; | 177 | result = v->counter; |
| 178 | result += i; | 178 | result += i; |
| 179 | v->counter = result; | 179 | v->counter = result; |
| 180 | local_irq_restore(flags); | 180 | raw_local_irq_restore(flags); |
| 181 | } | 181 | } |
| 182 | 182 | ||
| 183 | smp_mb(); | 183 | smp_mb(); |
| @@ -225,11 +225,11 @@ static __inline__ int atomic_sub_return(int i, atomic_t * v) | |||
| 225 | } else { | 225 | } else { |
| 226 | unsigned long flags; | 226 | unsigned long flags; |
| 227 | 227 | ||
| 228 | local_irq_save(flags); | 228 | raw_local_irq_save(flags); |
| 229 | result = v->counter; | 229 | result = v->counter; |
| 230 | result -= i; | 230 | result -= i; |
| 231 | v->counter = result; | 231 | v->counter = result; |
| 232 | local_irq_restore(flags); | 232 | raw_local_irq_restore(flags); |
| 233 | } | 233 | } |
| 234 | 234 | ||
| 235 | smp_mb(); | 235 | smp_mb(); |
| @@ -293,12 +293,12 @@ static __inline__ int atomic_sub_if_positive(int i, atomic_t * v) | |||
| 293 | } else { | 293 | } else { |
| 294 | unsigned long flags; | 294 | unsigned long flags; |
| 295 | 295 | ||
| 296 | local_irq_save(flags); | 296 | raw_local_irq_save(flags); |
| 297 | result = v->counter; | 297 | result = v->counter; |
| 298 | result -= i; | 298 | result -= i; |
| 299 | if (result >= 0) | 299 | if (result >= 0) |
| 300 | v->counter = result; | 300 | v->counter = result; |
| 301 | local_irq_restore(flags); | 301 | raw_local_irq_restore(flags); |
| 302 | } | 302 | } |
| 303 | 303 | ||
| 304 | smp_mb(); | 304 | smp_mb(); |
| @@ -454,9 +454,9 @@ static __inline__ void atomic64_add(long i, atomic64_t * v) | |||
| 454 | } else { | 454 | } else { |
| 455 | unsigned long flags; | 455 | unsigned long flags; |
| 456 | 456 | ||
| 457 | local_irq_save(flags); | 457 | raw_local_irq_save(flags); |
| 458 | v->counter += i; | 458 | v->counter += i; |
| 459 | local_irq_restore(flags); | 459 | raw_local_irq_restore(flags); |
| 460 | } | 460 | } |
| 461 | } | 461 | } |
| 462 | 462 | ||
| @@ -499,9 +499,9 @@ static __inline__ void atomic64_sub(long i, atomic64_t * v) | |||
| 499 | } else { | 499 | } else { |
| 500 | unsigned long flags; | 500 | unsigned long flags; |
| 501 | 501 | ||
| 502 | local_irq_save(flags); | 502 | raw_local_irq_save(flags); |
| 503 | v->counter -= i; | 503 | v->counter -= i; |
| 504 | local_irq_restore(flags); | 504 | raw_local_irq_restore(flags); |
| 505 | } | 505 | } |
| 506 | } | 506 | } |
| 507 | 507 | ||
| @@ -548,11 +548,11 @@ static __inline__ long atomic64_add_return(long i, atomic64_t * v) | |||
| 548 | } else { | 548 | } else { |
| 549 | unsigned long flags; | 549 | unsigned long flags; |
| 550 | 550 | ||
| 551 | local_irq_save(flags); | 551 | raw_local_irq_save(flags); |
| 552 | result = v->counter; | 552 | result = v->counter; |
| 553 | result += i; | 553 | result += i; |
| 554 | v->counter = result; | 554 | v->counter = result; |
| 555 | local_irq_restore(flags); | 555 | raw_local_irq_restore(flags); |
| 556 | } | 556 | } |
| 557 | 557 | ||
| 558 | smp_mb(); | 558 | smp_mb(); |
| @@ -600,11 +600,11 @@ static __inline__ long atomic64_sub_return(long i, atomic64_t * v) | |||
| 600 | } else { | 600 | } else { |
| 601 | unsigned long flags; | 601 | unsigned long flags; |
| 602 | 602 | ||
| 603 | local_irq_save(flags); | 603 | raw_local_irq_save(flags); |
| 604 | result = v->counter; | 604 | result = v->counter; |
| 605 | result -= i; | 605 | result -= i; |
| 606 | v->counter = result; | 606 | v->counter = result; |
| 607 | local_irq_restore(flags); | 607 | raw_local_irq_restore(flags); |
| 608 | } | 608 | } |
| 609 | 609 | ||
| 610 | smp_mb(); | 610 | smp_mb(); |
| @@ -668,12 +668,12 @@ static __inline__ long atomic64_sub_if_positive(long i, atomic64_t * v) | |||
| 668 | } else { | 668 | } else { |
| 669 | unsigned long flags; | 669 | unsigned long flags; |
| 670 | 670 | ||
| 671 | local_irq_save(flags); | 671 | raw_local_irq_save(flags); |
| 672 | result = v->counter; | 672 | result = v->counter; |
| 673 | result -= i; | 673 | result -= i; |
| 674 | if (result >= 0) | 674 | if (result >= 0) |
| 675 | v->counter = result; | 675 | v->counter = result; |
| 676 | local_irq_restore(flags); | 676 | raw_local_irq_restore(flags); |
| 677 | } | 677 | } |
| 678 | 678 | ||
| 679 | smp_mb(); | 679 | smp_mb(); |
diff --git a/include/asm-mips/bitops.h b/include/asm-mips/bitops.h index 8959da245cfb..d995413e11fd 100644 --- a/include/asm-mips/bitops.h +++ b/include/asm-mips/bitops.h | |||
| @@ -100,9 +100,9 @@ static inline void set_bit(unsigned long nr, volatile unsigned long *addr) | |||
| 100 | 100 | ||
| 101 | a += nr >> SZLONG_LOG; | 101 | a += nr >> SZLONG_LOG; |
| 102 | mask = 1UL << bit; | 102 | mask = 1UL << bit; |
| 103 | local_irq_save(flags); | 103 | raw_local_irq_save(flags); |
| 104 | *a |= mask; | 104 | *a |= mask; |
| 105 | local_irq_restore(flags); | 105 | raw_local_irq_restore(flags); |
| 106 | } | 106 | } |
| 107 | } | 107 | } |
| 108 | 108 | ||
| @@ -165,9 +165,9 @@ static inline void clear_bit(unsigned long nr, volatile unsigned long *addr) | |||
| 165 | 165 | ||
| 166 | a += nr >> SZLONG_LOG; | 166 | a += nr >> SZLONG_LOG; |
| 167 | mask = 1UL << bit; | 167 | mask = 1UL << bit; |
| 168 | local_irq_save(flags); | 168 | raw_local_irq_save(flags); |
| 169 | *a &= ~mask; | 169 | *a &= ~mask; |
| 170 | local_irq_restore(flags); | 170 | raw_local_irq_restore(flags); |
| 171 | } | 171 | } |
| 172 | } | 172 | } |
| 173 | 173 | ||
| @@ -220,9 +220,9 @@ static inline void change_bit(unsigned long nr, volatile unsigned long *addr) | |||
| 220 | 220 | ||
| 221 | a += nr >> SZLONG_LOG; | 221 | a += nr >> SZLONG_LOG; |
| 222 | mask = 1UL << bit; | 222 | mask = 1UL << bit; |
| 223 | local_irq_save(flags); | 223 | raw_local_irq_save(flags); |
| 224 | *a ^= mask; | 224 | *a ^= mask; |
| 225 | local_irq_restore(flags); | 225 | raw_local_irq_restore(flags); |
| 226 | } | 226 | } |
| 227 | } | 227 | } |
| 228 | 228 | ||
| @@ -287,10 +287,10 @@ static inline int test_and_set_bit(unsigned long nr, | |||
| 287 | 287 | ||
| 288 | a += nr >> SZLONG_LOG; | 288 | a += nr >> SZLONG_LOG; |
| 289 | mask = 1UL << bit; | 289 | mask = 1UL << bit; |
| 290 | local_irq_save(flags); | 290 | raw_local_irq_save(flags); |
| 291 | retval = (mask & *a) != 0; | 291 | retval = (mask & *a) != 0; |
| 292 | *a |= mask; | 292 | *a |= mask; |
| 293 | local_irq_restore(flags); | 293 | raw_local_irq_restore(flags); |
| 294 | 294 | ||
| 295 | return retval; | 295 | return retval; |
| 296 | } | 296 | } |
| @@ -381,10 +381,10 @@ static inline int test_and_clear_bit(unsigned long nr, | |||
| 381 | 381 | ||
| 382 | a += nr >> SZLONG_LOG; | 382 | a += nr >> SZLONG_LOG; |
| 383 | mask = 1UL << bit; | 383 | mask = 1UL << bit; |
| 384 | local_irq_save(flags); | 384 | raw_local_irq_save(flags); |
| 385 | retval = (mask & *a) != 0; | 385 | retval = (mask & *a) != 0; |
| 386 | *a &= ~mask; | 386 | *a &= ~mask; |
| 387 | local_irq_restore(flags); | 387 | raw_local_irq_restore(flags); |
| 388 | 388 | ||
| 389 | return retval; | 389 | return retval; |
| 390 | } | 390 | } |
| @@ -452,10 +452,10 @@ static inline int test_and_change_bit(unsigned long nr, | |||
| 452 | 452 | ||
| 453 | a += nr >> SZLONG_LOG; | 453 | a += nr >> SZLONG_LOG; |
| 454 | mask = 1UL << bit; | 454 | mask = 1UL << bit; |
| 455 | local_irq_save(flags); | 455 | raw_local_irq_save(flags); |
| 456 | retval = (mask & *a) != 0; | 456 | retval = (mask & *a) != 0; |
| 457 | *a ^= mask; | 457 | *a ^= mask; |
| 458 | local_irq_restore(flags); | 458 | raw_local_irq_restore(flags); |
| 459 | 459 | ||
| 460 | return retval; | 460 | return retval; |
| 461 | } | 461 | } |
diff --git a/include/asm-mips/cpu-features.h b/include/asm-mips/cpu-features.h index eadca266f159..5e4bed123b48 100644 --- a/include/asm-mips/cpu-features.h +++ b/include/asm-mips/cpu-features.h | |||
| @@ -40,6 +40,9 @@ | |||
| 40 | #endif | 40 | #endif |
| 41 | #ifndef cpu_has_fpu | 41 | #ifndef cpu_has_fpu |
| 42 | #define cpu_has_fpu (current_cpu_data.options & MIPS_CPU_FPU) | 42 | #define cpu_has_fpu (current_cpu_data.options & MIPS_CPU_FPU) |
| 43 | #define raw_cpu_has_fpu (raw_current_cpu_data.options & MIPS_CPU_FPU) | ||
| 44 | #else | ||
| 45 | #define raw_cpu_has_fpu cpu_has_fpu | ||
| 43 | #endif | 46 | #endif |
| 44 | #ifndef cpu_has_32fpr | 47 | #ifndef cpu_has_32fpr |
| 45 | #define cpu_has_32fpr (cpu_data[0].options & MIPS_CPU_32FPR) | 48 | #define cpu_has_32fpr (cpu_data[0].options & MIPS_CPU_32FPR) |
diff --git a/include/asm-mips/cpu-info.h b/include/asm-mips/cpu-info.h index 610d0cdeaa9e..22fe8453fcc7 100644 --- a/include/asm-mips/cpu-info.h +++ b/include/asm-mips/cpu-info.h | |||
| @@ -87,6 +87,7 @@ struct cpuinfo_mips { | |||
| 87 | 87 | ||
| 88 | extern struct cpuinfo_mips cpu_data[]; | 88 | extern struct cpuinfo_mips cpu_data[]; |
| 89 | #define current_cpu_data cpu_data[smp_processor_id()] | 89 | #define current_cpu_data cpu_data[smp_processor_id()] |
| 90 | #define raw_current_cpu_data cpu_data[raw_smp_processor_id()] | ||
| 90 | 91 | ||
| 91 | extern void cpu_probe(void); | 92 | extern void cpu_probe(void); |
| 92 | extern void cpu_report(void); | 93 | extern void cpu_report(void); |
diff --git a/include/asm-mips/fpu.h b/include/asm-mips/fpu.h index efef843b93f0..4e12d1f9534f 100644 --- a/include/asm-mips/fpu.h +++ b/include/asm-mips/fpu.h | |||
| @@ -27,11 +27,11 @@ | |||
| 27 | struct sigcontext; | 27 | struct sigcontext; |
| 28 | struct sigcontext32; | 28 | struct sigcontext32; |
| 29 | 29 | ||
| 30 | extern asmlinkage int (*save_fp_context)(struct sigcontext *sc); | 30 | extern asmlinkage int (*save_fp_context)(struct sigcontext __user *sc); |
| 31 | extern asmlinkage int (*restore_fp_context)(struct sigcontext *sc); | 31 | extern asmlinkage int (*restore_fp_context)(struct sigcontext __user *sc); |
| 32 | 32 | ||
| 33 | extern asmlinkage int (*save_fp_context32)(struct sigcontext32 *sc); | 33 | extern asmlinkage int (*save_fp_context32)(struct sigcontext32 __user *sc); |
| 34 | extern asmlinkage int (*restore_fp_context32)(struct sigcontext32 *sc); | 34 | extern asmlinkage int (*restore_fp_context32)(struct sigcontext32 __user *sc); |
| 35 | 35 | ||
| 36 | extern void fpu_emulator_init_fpu(void); | 36 | extern void fpu_emulator_init_fpu(void); |
| 37 | extern void _init_fpu(void); | 37 | extern void _init_fpu(void); |
| @@ -68,6 +68,8 @@ do { \ | |||
| 68 | /* We don't care about the c0 hazard here */ \ | 68 | /* We don't care about the c0 hazard here */ \ |
| 69 | } while (0) | 69 | } while (0) |
| 70 | 70 | ||
| 71 | #define __fpu_enabled() (read_c0_status() & ST0_CU1) | ||
| 72 | |||
| 71 | #define enable_fpu() \ | 73 | #define enable_fpu() \ |
| 72 | do { \ | 74 | do { \ |
| 73 | if (cpu_has_fpu) \ | 75 | if (cpu_has_fpu) \ |
| @@ -93,31 +95,47 @@ static inline int is_fpu_owner(void) | |||
| 93 | return cpu_has_fpu && __is_fpu_owner(); | 95 | return cpu_has_fpu && __is_fpu_owner(); |
| 94 | } | 96 | } |
| 95 | 97 | ||
| 96 | static inline void own_fpu(void) | 98 | static inline void __own_fpu(void) |
| 97 | { | 99 | { |
| 98 | if (cpu_has_fpu) { | 100 | __enable_fpu(); |
| 99 | __enable_fpu(); | 101 | KSTK_STATUS(current) |= ST0_CU1; |
| 100 | KSTK_STATUS(current) |= ST0_CU1; | 102 | set_thread_flag(TIF_USEDFPU); |
| 101 | set_thread_flag(TIF_USEDFPU); | 103 | } |
| 104 | |||
| 105 | static inline void own_fpu(int restore) | ||
| 106 | { | ||
| 107 | preempt_disable(); | ||
| 108 | if (cpu_has_fpu && !__is_fpu_owner()) { | ||
| 109 | __own_fpu(); | ||
| 110 | if (restore) | ||
| 111 | _restore_fp(current); | ||
| 102 | } | 112 | } |
| 113 | preempt_enable(); | ||
| 103 | } | 114 | } |
| 104 | 115 | ||
| 105 | static inline void lose_fpu(void) | 116 | static inline void lose_fpu(int save) |
| 106 | { | 117 | { |
| 107 | if (cpu_has_fpu) { | 118 | preempt_disable(); |
| 119 | if (is_fpu_owner()) { | ||
| 120 | if (save) | ||
| 121 | _save_fp(current); | ||
| 108 | KSTK_STATUS(current) &= ~ST0_CU1; | 122 | KSTK_STATUS(current) &= ~ST0_CU1; |
| 109 | clear_thread_flag(TIF_USEDFPU); | 123 | clear_thread_flag(TIF_USEDFPU); |
| 110 | __disable_fpu(); | 124 | __disable_fpu(); |
| 111 | } | 125 | } |
| 126 | preempt_enable(); | ||
| 112 | } | 127 | } |
| 113 | 128 | ||
| 114 | static inline void init_fpu(void) | 129 | static inline void init_fpu(void) |
| 115 | { | 130 | { |
| 131 | preempt_disable(); | ||
| 116 | if (cpu_has_fpu) { | 132 | if (cpu_has_fpu) { |
| 133 | __own_fpu(); | ||
| 117 | _init_fpu(); | 134 | _init_fpu(); |
| 118 | } else { | 135 | } else { |
| 119 | fpu_emulator_init_fpu(); | 136 | fpu_emulator_init_fpu(); |
| 120 | } | 137 | } |
| 138 | preempt_enable(); | ||
| 121 | } | 139 | } |
| 122 | 140 | ||
| 123 | static inline void save_fp(struct task_struct *tsk) | 141 | static inline void save_fp(struct task_struct *tsk) |
| @@ -144,4 +162,18 @@ static inline fpureg_t *get_fpu_regs(struct task_struct *tsk) | |||
| 144 | return tsk->thread.fpu.fpr; | 162 | return tsk->thread.fpu.fpr; |
| 145 | } | 163 | } |
| 146 | 164 | ||
| 165 | static inline void enable_fp_in_kernel(void) | ||
| 166 | { | ||
| 167 | set_thread_flag(TIF_ALLOW_FP_IN_KERNEL); | ||
| 168 | /* make sure CU1 and FPU ownership are consistent */ | ||
| 169 | if (!__is_fpu_owner() && __fpu_enabled()) | ||
| 170 | __disable_fpu(); | ||
| 171 | } | ||
| 172 | |||
| 173 | static inline void disable_fp_in_kernel(void) | ||
| 174 | { | ||
| 175 | BUG_ON(!__is_fpu_owner() && __fpu_enabled()); | ||
| 176 | clear_thread_flag(TIF_ALLOW_FP_IN_KERNEL); | ||
| 177 | } | ||
| 178 | |||
| 147 | #endif /* _ASM_FPU_H */ | 179 | #endif /* _ASM_FPU_H */ |
diff --git a/include/asm-mips/mach-ip27/dma-coherence.h b/include/asm-mips/mach-ip27/dma-coherence.h index 659816e200d4..3fdbbf68e952 100644 --- a/include/asm-mips/mach-ip27/dma-coherence.h +++ b/include/asm-mips/mach-ip27/dma-coherence.h | |||
| @@ -18,7 +18,8 @@ | |||
| 18 | 18 | ||
| 19 | struct device; | 19 | struct device; |
| 20 | 20 | ||
| 21 | static dma_addr_t plat_map_dma_mem(struct device *dev, void *addr, size_t size) | 21 | static inline dma_addr_t plat_map_dma_mem(struct device *dev, void *addr, |
| 22 | size_t size) | ||
| 22 | { | 23 | { |
| 23 | dma_addr_t pa = dev_to_baddr(dev, virt_to_phys(addr)); | 24 | dma_addr_t pa = dev_to_baddr(dev, virt_to_phys(addr)); |
| 24 | 25 | ||
| @@ -37,7 +38,7 @@ static unsigned long plat_dma_addr_to_phys(dma_addr_t dma_addr) | |||
| 37 | return dma_addr & (0xffUL << 56); | 38 | return dma_addr & (0xffUL << 56); |
| 38 | } | 39 | } |
| 39 | 40 | ||
| 40 | static void plat_unmap_dma_mem(dma_addr_t dma_addr) | 41 | static inline void plat_unmap_dma_mem(dma_addr_t dma_addr) |
| 41 | { | 42 | { |
| 42 | } | 43 | } |
| 43 | 44 | ||
diff --git a/include/asm-mips/mach-ip32/dma-coherence.h b/include/asm-mips/mach-ip32/dma-coherence.h index 950be17bbb86..c3f9a6a20eb0 100644 --- a/include/asm-mips/mach-ip32/dma-coherence.h +++ b/include/asm-mips/mach-ip32/dma-coherence.h | |||
| @@ -26,7 +26,8 @@ struct device; | |||
| 26 | 26 | ||
| 27 | #define RAM_OFFSET_MASK 0x3fffffffUL | 27 | #define RAM_OFFSET_MASK 0x3fffffffUL |
| 28 | 28 | ||
| 29 | static dma_addr_t plat_map_dma_mem(struct device *dev, void *addr, size_t size) | 29 | static inline dma_addr_t plat_map_dma_mem(struct device *dev, void *addr, |
| 30 | size_t size) | ||
| 30 | { | 31 | { |
| 31 | dma_addr_t pa = virt_to_phys(addr) & RAM_OFFSET_MASK; | 32 | dma_addr_t pa = virt_to_phys(addr) & RAM_OFFSET_MASK; |
| 32 | 33 | ||
| @@ -59,7 +60,7 @@ static unsigned long plat_dma_addr_to_phys(dma_addr_t dma_addr) | |||
| 59 | return addr; | 60 | return addr; |
| 60 | } | 61 | } |
| 61 | 62 | ||
| 62 | static void plat_unmap_dma_mem(dma_addr_t dma_addr) | 63 | static inline void plat_unmap_dma_mem(dma_addr_t dma_addr) |
| 63 | { | 64 | { |
| 64 | } | 65 | } |
| 65 | 66 | ||
diff --git a/include/asm-mips/rtlx.h b/include/asm-mips/rtlx.h index 59162f74a798..65778c890a62 100644 --- a/include/asm-mips/rtlx.h +++ b/include/asm-mips/rtlx.h | |||
| @@ -23,8 +23,8 @@ | |||
| 23 | 23 | ||
| 24 | extern int rtlx_open(int index, int can_sleep); | 24 | extern int rtlx_open(int index, int can_sleep); |
| 25 | extern int rtlx_release(int index); | 25 | extern int rtlx_release(int index); |
| 26 | extern ssize_t rtlx_read(int index, void *buff, size_t count, int user); | 26 | extern ssize_t rtlx_read(int index, void __user *buff, size_t count); |
| 27 | extern ssize_t rtlx_write(int index, void *buffer, size_t count, int user); | 27 | extern ssize_t rtlx_write(int index, const void __user *buffer, size_t count); |
| 28 | extern unsigned int rtlx_read_poll(int index, int can_sleep); | 28 | extern unsigned int rtlx_read_poll(int index, int can_sleep); |
| 29 | extern unsigned int rtlx_write_poll(int index); | 29 | extern unsigned int rtlx_write_poll(int index); |
| 30 | 30 | ||
diff --git a/include/asm-mips/system.h b/include/asm-mips/system.h index 597a3743f6a1..290887077e44 100644 --- a/include/asm-mips/system.h +++ b/include/asm-mips/system.h | |||
| @@ -121,10 +121,10 @@ static inline unsigned long __xchg_u32(volatile int * m, unsigned int val) | |||
| 121 | } else { | 121 | } else { |
| 122 | unsigned long flags; | 122 | unsigned long flags; |
| 123 | 123 | ||
| 124 | local_irq_save(flags); | 124 | raw_local_irq_save(flags); |
| 125 | retval = *m; | 125 | retval = *m; |
| 126 | *m = val; | 126 | *m = val; |
| 127 | local_irq_restore(flags); /* implies memory barrier */ | 127 | raw_local_irq_restore(flags); /* implies memory barrier */ |
| 128 | } | 128 | } |
| 129 | 129 | ||
| 130 | smp_mb(); | 130 | smp_mb(); |
| @@ -169,10 +169,10 @@ static inline __u64 __xchg_u64(volatile __u64 * m, __u64 val) | |||
| 169 | } else { | 169 | } else { |
| 170 | unsigned long flags; | 170 | unsigned long flags; |
| 171 | 171 | ||
| 172 | local_irq_save(flags); | 172 | raw_local_irq_save(flags); |
| 173 | retval = *m; | 173 | retval = *m; |
| 174 | *m = val; | 174 | *m = val; |
| 175 | local_irq_restore(flags); /* implies memory barrier */ | 175 | raw_local_irq_restore(flags); /* implies memory barrier */ |
| 176 | } | 176 | } |
| 177 | 177 | ||
| 178 | smp_mb(); | 178 | smp_mb(); |
| @@ -250,11 +250,11 @@ static inline unsigned long __cmpxchg_u32(volatile int * m, unsigned long old, | |||
| 250 | } else { | 250 | } else { |
| 251 | unsigned long flags; | 251 | unsigned long flags; |
| 252 | 252 | ||
| 253 | local_irq_save(flags); | 253 | raw_local_irq_save(flags); |
| 254 | retval = *m; | 254 | retval = *m; |
| 255 | if (retval == old) | 255 | if (retval == old) |
| 256 | *m = new; | 256 | *m = new; |
| 257 | local_irq_restore(flags); /* implies memory barrier */ | 257 | raw_local_irq_restore(flags); /* implies memory barrier */ |
| 258 | } | 258 | } |
| 259 | 259 | ||
| 260 | smp_mb(); | 260 | smp_mb(); |
| @@ -304,11 +304,11 @@ static inline unsigned long __cmpxchg_u64(volatile int * m, unsigned long old, | |||
| 304 | } else { | 304 | } else { |
| 305 | unsigned long flags; | 305 | unsigned long flags; |
| 306 | 306 | ||
| 307 | local_irq_save(flags); | 307 | raw_local_irq_save(flags); |
| 308 | retval = *m; | 308 | retval = *m; |
| 309 | if (retval == old) | 309 | if (retval == old) |
| 310 | *m = new; | 310 | *m = new; |
| 311 | local_irq_restore(flags); /* implies memory barrier */ | 311 | raw_local_irq_restore(flags); /* implies memory barrier */ |
| 312 | } | 312 | } |
| 313 | 313 | ||
| 314 | smp_mb(); | 314 | smp_mb(); |
diff --git a/include/asm-mips/thread_info.h b/include/asm-mips/thread_info.h index fbcda8204473..6cf05f4a4e7e 100644 --- a/include/asm-mips/thread_info.h +++ b/include/asm-mips/thread_info.h | |||
| @@ -119,6 +119,7 @@ register struct thread_info *__current_thread_info __asm__("$28"); | |||
| 119 | #define TIF_POLLING_NRFLAG 17 /* true if poll_idle() is polling TIF_NEED_RESCHED */ | 119 | #define TIF_POLLING_NRFLAG 17 /* true if poll_idle() is polling TIF_NEED_RESCHED */ |
| 120 | #define TIF_MEMDIE 18 | 120 | #define TIF_MEMDIE 18 |
| 121 | #define TIF_FREEZE 19 | 121 | #define TIF_FREEZE 19 |
| 122 | #define TIF_ALLOW_FP_IN_KERNEL 20 | ||
| 122 | #define TIF_SYSCALL_TRACE 31 /* syscall trace active */ | 123 | #define TIF_SYSCALL_TRACE 31 /* syscall trace active */ |
| 123 | 124 | ||
| 124 | #define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE) | 125 | #define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE) |
