Skip to content

Commit

Permalink
Merge branch 'upstream' of git://ftp.linux-mips.org/pub/scm/upstream-…
Browse files Browse the repository at this point in the history
…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.
  • Loading branch information
Linus Torvalds committed Mar 17, 2007
2 parents 5379058 + f510aa3 commit 4745591
Show file tree
Hide file tree
Showing 24 changed files with 338 additions and 226 deletions.
4 changes: 2 additions & 2 deletions arch/mips/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@ config LASAT
select R5000_CPU_SCACHE
select SYS_HAS_CPU_R5000
select SYS_SUPPORTS_32BIT_KERNEL
select SYS_SUPPORTS_64BIT_KERNEL if EXPERIMENTAL
select SYS_SUPPORTS_64BIT_KERNEL if BROKEN
select SYS_SUPPORTS_LITTLE_ENDIAN
select GENERIC_HARDIRQS_NO__DO_IRQ

Expand Down Expand Up @@ -1559,6 +1559,7 @@ config MIPS_MT_SMP
select CPU_MIPSR2_IRQ_VI
select CPU_MIPSR2_SRS
select MIPS_MT
select NR_CPUS_DEFAULT_2
select SMP
select SYS_SUPPORTS_SMP
help
Expand All @@ -1573,7 +1574,6 @@ config MIPS_MT_SMTC
select CPU_MIPSR2_IRQ_VI
select CPU_MIPSR2_SRS
select MIPS_MT
select NR_CPUS_DEFAULT_2
select NR_CPUS_DEFAULT_8
select SMP
select SYS_SUPPORTS_SMP
Expand Down
18 changes: 14 additions & 4 deletions arch/mips/kernel/kspd.c
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,8 @@ void sp_work_handle_request(void)
struct mtsp_syscall_generic generic;
struct mtsp_syscall_ret ret;
struct kspd_notifications *n;
unsigned long written;
mm_segment_t old_fs;
struct timeval tv;
struct timezone tz;
int cmd;
Expand All @@ -201,15 +203,20 @@ void sp_work_handle_request(void)

ret.retval = -1;

if (!rtlx_read(RTLX_CHANNEL_SYSIO, &sc, sizeof(struct mtsp_syscall), 0)) {
old_fs = get_fs();
set_fs(KERNEL_DS);

if (!rtlx_read(RTLX_CHANNEL_SYSIO, &sc, sizeof(struct mtsp_syscall))) {
set_fs(old_fs);
printk(KERN_ERR "Expected request but nothing to read\n");
return;
}

size = sc.size;

if (size) {
if (!rtlx_read(RTLX_CHANNEL_SYSIO, &generic, size, 0)) {
if (!rtlx_read(RTLX_CHANNEL_SYSIO, &generic, size)) {
set_fs(old_fs);
printk(KERN_ERR "Expected request but nothing to read\n");
return;
}
Expand Down Expand Up @@ -282,8 +289,11 @@ void sp_work_handle_request(void)
if (vpe_getuid(SP_VPE))
sp_setfsuidgid( 0, 0);

if ((rtlx_write(RTLX_CHANNEL_SYSIO, &ret, sizeof(struct mtsp_syscall_ret), 0))
< sizeof(struct mtsp_syscall_ret))
old_fs = get_fs();
set_fs(KERNEL_DS);
written = rtlx_write(RTLX_CHANNEL_SYSIO, &ret, sizeof(ret));
set_fs(old_fs);
if (written < sizeof(ret))
printk("KSPD: sp_work_handle_request failed to send to SP\n");
}

Expand Down
12 changes: 12 additions & 0 deletions arch/mips/kernel/linux32.c
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,8 @@ asmlinkage int sys32_sched_rr_get_interval(compat_pid_t pid,
return ret;
}

#ifdef CONFIG_SYSVIPC

asmlinkage long
sys32_ipc (u32 call, int first, int second, int third, u32 ptr, u32 fifth)
{
Expand Down Expand Up @@ -368,6 +370,16 @@ sys32_ipc (u32 call, int first, int second, int third, u32 ptr, u32 fifth)
return err;
}

#else

asmlinkage long
sys32_ipc (u32 call, int first, int second, int third, u32 ptr, u32 fifth)
{
return -ENOSYS;
}

#endif /* CONFIG_SYSVIPC */

#ifdef CONFIG_MIPS32_N32
asmlinkage long sysn32_semctl(int semid, int semnum, int cmd, u32 arg)
{
Expand Down
10 changes: 6 additions & 4 deletions arch/mips/kernel/r2300_switch.S
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,7 @@ LEAF(resume)
#ifndef CONFIG_CPU_HAS_LLSC
sw zero, ll_bit
#endif
mfc0 t1, CP0_STATUS
sw t1, THREAD_STATUS(a0)
mfc0 t2, CP0_STATUS
cpu_save_nonscratch a0
sw ra, THREAD_REG31(a0)

Expand All @@ -60,8 +59,8 @@ LEAF(resume)
lw t3, TASK_THREAD_INFO(a0)
lw t0, TI_FLAGS(t3)
li t1, _TIF_USEDFPU
and t2, t0, t1
beqz t2, 1f
and t1, t0
beqz t1, 1f
nor t1, zero, t1

and t0, t0, t1
Expand All @@ -74,10 +73,13 @@ LEAF(resume)
li t1, ~ST0_CU1
and t0, t0, t1
sw t0, ST_OFF(t3)
/* clear thread_struct CU1 bit */
and t2, t1

fpu_save_single a0, t0 # clobbers t0

1:
sw t2, THREAD_STATUS(a0)
/*
* The order of restoring the registers takes care of the race
* updating $28, $29 and kernelsp without disabling ints.
Expand Down
16 changes: 0 additions & 16 deletions arch/mips/kernel/r4k_fpu.S
Original file line number Diff line number Diff line change
Expand Up @@ -114,14 +114,6 @@ LEAF(_save_fp_context32)
*/
LEAF(_restore_fp_context)
EX lw t0, SC_FPC_CSR(a0)

/* Fail if the CSR has exceptions pending */
srl t1, t0, 5
and t1, t0
andi t1, 0x1f << 7
bnez t1, fault
nop

#ifdef CONFIG_64BIT
EX ldc1 $f1, SC_FPREGS+8(a0)
EX ldc1 $f3, SC_FPREGS+24(a0)
Expand Down Expand Up @@ -165,14 +157,6 @@ LEAF(_restore_fp_context)
LEAF(_restore_fp_context32)
/* Restore an o32 sigcontext. */
EX lw t0, SC32_FPC_CSR(a0)

/* Fail if the CSR has exceptions pending */
srl t1, t0, 5
and t1, t0
andi t1, 0x1f << 7
bnez t1, fault
nop

EX ldc1 $f0, SC32_FPREGS+0(a0)
EX ldc1 $f2, SC32_FPREGS+16(a0)
EX ldc1 $f4, SC32_FPREGS+32(a0)
Expand Down
10 changes: 6 additions & 4 deletions arch/mips/kernel/r4k_switch.S
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,7 @@
#ifndef CONFIG_CPU_HAS_LLSC
sw zero, ll_bit
#endif
mfc0 t1, CP0_STATUS
LONG_S t1, THREAD_STATUS(a0)
mfc0 t2, CP0_STATUS
cpu_save_nonscratch a0
LONG_S ra, THREAD_REG31(a0)

Expand All @@ -59,8 +58,8 @@
PTR_L t3, TASK_THREAD_INFO(a0)
LONG_L t0, TI_FLAGS(t3)
li t1, _TIF_USEDFPU
and t2, t0, t1
beqz t2, 1f
and t1, t0
beqz t1, 1f
nor t1, zero, t1

and t0, t0, t1
Expand All @@ -73,10 +72,13 @@
li t1, ~ST0_CU1
and t0, t0, t1
LONG_S t0, ST_OFF(t3)
/* clear thread_struct CU1 bit */
and t2, t1

fpu_save_double a0 t0 t1 # c0_status passed in t0
# clobbers t1
1:
LONG_S t2, THREAD_STATUS(a0)

/*
* The order of restoring the registers takes care of the race
Expand Down
104 changes: 62 additions & 42 deletions arch/mips/kernel/rtlx.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ static struct chan_waitqueues {
wait_queue_head_t rt_queue;
wait_queue_head_t lx_queue;
atomic_t in_open;
struct mutex mutex;
} channel_wqs[RTLX_CHANNELS];

static struct irqaction irq;
Expand Down Expand Up @@ -146,7 +147,7 @@ static void stopping(int vpe)

int rtlx_open(int index, int can_sleep)
{
volatile struct rtlx_info **p;
struct rtlx_info **p;
struct rtlx_channel *chan;
enum rtlx_state state;
int ret = 0;
Expand Down Expand Up @@ -179,13 +180,24 @@ int rtlx_open(int index, int can_sleep)
}
}

smp_rmb();
if (*p == NULL) {
if (can_sleep) {
__wait_event_interruptible(channel_wqs[index].lx_queue,
*p != NULL,
ret);
if (ret)
DEFINE_WAIT(wait);

for (;;) {
prepare_to_wait(&channel_wqs[index].lx_queue, &wait, TASK_INTERRUPTIBLE);
smp_rmb();
if (*p != NULL)
break;
if (!signal_pending(current)) {
schedule();
continue;
}
ret = -ERESTARTSYS;
goto out_fail;
}
finish_wait(&channel_wqs[index].lx_queue, &wait);
} else {
printk(" *vpe_get_shared is NULL. "
"Has an SP program been loaded?\n");
Expand Down Expand Up @@ -277,81 +289,88 @@ unsigned int rtlx_write_poll(int index)
return write_spacefree(chan->rt_read, chan->rt_write, chan->buffer_size);
}

static inline void copy_to(void *dst, void *src, size_t count, int user)
{
if (user)
copy_to_user(dst, src, count);
else
memcpy(dst, src, count);
}

static inline void copy_from(void *dst, void *src, size_t count, int user)
ssize_t rtlx_read(int index, void __user *buff, size_t count, int user)
{
if (user)
copy_from_user(dst, src, count);
else
memcpy(dst, src, count);
}

ssize_t rtlx_read(int index, void *buff, size_t count, int user)
{
size_t fl = 0L;
size_t lx_write, fl = 0L;
struct rtlx_channel *lx;
unsigned long failed;

if (rtlx == NULL)
return -ENOSYS;

lx = &rtlx->channel[index];

mutex_lock(&channel_wqs[index].mutex);
smp_rmb();
lx_write = lx->lx_write;

/* find out how much in total */
count = min(count,
(size_t)(lx->lx_write + lx->buffer_size - lx->lx_read)
(size_t)(lx_write + lx->buffer_size - lx->lx_read)
% lx->buffer_size);

/* then how much from the read pointer onwards */
fl = min( count, (size_t)lx->buffer_size - lx->lx_read);
fl = min(count, (size_t)lx->buffer_size - lx->lx_read);

copy_to(buff, &lx->lx_buffer[lx->lx_read], fl, user);
failed = copy_to_user(buff, lx->lx_buffer + lx->lx_read, fl);
if (failed)
goto out;

/* and if there is anything left at the beginning of the buffer */
if ( count - fl )
copy_to (buff + fl, lx->lx_buffer, count - fl, user);
if (count - fl)
failed = copy_to_user(buff + fl, lx->lx_buffer, count - fl);

/* update the index */
lx->lx_read += count;
lx->lx_read %= lx->buffer_size;
out:
count -= failed;

smp_wmb();
lx->lx_read = (lx->lx_read + count) % lx->buffer_size;
smp_wmb();
mutex_unlock(&channel_wqs[index].mutex);

return count;
}

ssize_t rtlx_write(int index, void *buffer, size_t count, int user)
ssize_t rtlx_write(int index, const void __user *buffer, size_t count, int user)
{
struct rtlx_channel *rt;
size_t rt_read;
size_t fl;

if (rtlx == NULL)
return(-ENOSYS);

rt = &rtlx->channel[index];

mutex_lock(&channel_wqs[index].mutex);
smp_rmb();
rt_read = rt->rt_read;

/* total number of bytes to copy */
count = min(count,
(size_t)write_spacefree(rt->rt_read, rt->rt_write,
rt->buffer_size));
(size_t)write_spacefree(rt_read, rt->rt_write, rt->buffer_size));

/* first bit from write pointer to the end of the buffer, or count */
fl = min(count, (size_t) rt->buffer_size - rt->rt_write);

copy_from (&rt->rt_buffer[rt->rt_write], buffer, fl, user);
failed = copy_from_user(rt->rt_buffer + rt->rt_write, buffer, fl);
if (failed)
goto out;

/* if there's any left copy to the beginning of the buffer */
if( count - fl )
copy_from (rt->rt_buffer, buffer + fl, count - fl, user);
if (count - fl) {
failed = copy_from_user(rt->rt_buffer, buffer + fl, count - fl);
}

out:
count -= cailed;

rt->rt_write += count;
rt->rt_write %= rt->buffer_size;
smp_wmb();
rt->rt_write = (rt->rt_write + count) % rt->buffer_size;
smp_wmb();
mutex_unlock(&channel_wqs[index].mutex);

return(count);
return count;
}


Expand Down Expand Up @@ -403,7 +422,7 @@ static ssize_t file_read(struct file *file, char __user * buffer, size_t count,
return 0; // -EAGAIN makes cat whinge
}

return rtlx_read(minor, buffer, count, 1);
return rtlx_read(minor, buffer, count);
}

static ssize_t file_write(struct file *file, const char __user * buffer,
Expand All @@ -429,7 +448,7 @@ static ssize_t file_write(struct file *file, const char __user * buffer,
return ret;
}

return rtlx_write(minor, (void *)buffer, count, 1);
return rtlx_write(minor, buffer, count);
}

static const struct file_operations rtlx_fops = {
Expand Down Expand Up @@ -468,6 +487,7 @@ static int rtlx_module_init(void)
init_waitqueue_head(&channel_wqs[i].rt_queue);
init_waitqueue_head(&channel_wqs[i].lx_queue);
atomic_set(&channel_wqs[i].in_open, 0);
mutex_init(&channel_wqs[i].mutex);

dev = device_create(mt_class, NULL, MKDEV(major, i),
"%s%d", module_name, i);
Expand Down
Loading

0 comments on commit 4745591

Please sign in to comment.