CVSROOT: /home/cvs
Module name: malta
Changes by: beth@ftp.linux-mips.org 05/09/02 18:02:54
Modified files:
linux/arch/mips/kernel: Tag: MaltaRef_2_6 kspd.c rtlx.c vpe.c
Log message:
* arch/mips/kernel/kspd.c: Stop KSPD from trying to read from the
syscall channel if we are stopping.
* arch/mips/kernel/rtlx.c: Fix bug where multiple process could
open /dev/rt? and sit on the wait queue for SP to set up the
shared structure.
* arch/mips/kernel/vpe.c: Fix loading of fully linked SP images.
__start symbol wasn't found so the TC's restart address was incorrect.
diff -urN malta/linux/arch/mips/kernel/kspd.c
malta/linux/arch/mips/kernel/kspd.c
--- malta/linux/arch/mips/kernel/Attic/kspd.c 2005/08/19 13:47:36
1.1.1000.4
+++ malta/linux/arch/mips/kernel/Attic/kspd.c 2005/09/02 17:02:54
1.1.1000.5
@@ -113,7 +113,6 @@
register long int _arg1 __asm__ ("$5") = arg1;
register long int _arg2 __asm__ ("$6") = arg2;
register long int _arg3 __asm__ ("$7") = arg3;
-// register long int eflag __asm__ ("$7") = 1;
mm_segment_t old_fs;
@@ -286,8 +285,10 @@
} else {
/* wait for some data, allow it to sleep */
rtlx_read_poll(RTLX_CHANNEL_SYSIO, 1);
-
- sp_work_handle_request();
+
+ /* Check we haven't been woken because we are stopping */
+ if (!sp_stopping)
+ sp_work_handle_request();
}
if (!sp_stopping)
diff -urN malta/linux/arch/mips/kernel/rtlx.c
malta/linux/arch/mips/kernel/rtlx.c
--- malta/linux/arch/mips/kernel/rtlx.c 2005/08/19 13:47:36 1.1.1000.5
+++ malta/linux/arch/mips/kernel/rtlx.c 2005/09/02 17:02:54 1.1.1000.6
@@ -52,6 +52,7 @@
static struct chan_waitqueues {
wait_queue_head_t rt_queue;
wait_queue_head_t lx_queue;
+ int in_open;
} channel_wqs[RTLX_CHANNELS];
static struct irqaction irq;
@@ -61,7 +62,6 @@
extern void *vpe_get_shared(int index);
static int rtlx_init(struct rtlx_info *rtlxi);
-DECLARE_MUTEX(wq_mutex);
static void rtlx_dispatch(struct pt_regs *regs)
{
@@ -111,7 +111,7 @@
static int rtlx_init(struct rtlx_info *rtlxi)
{
if (rtlxi->id != RTLX_ID) {
- printk(KERN_ERR "no valid RTLX id at 0x%p found 0x%x should be
0x%x\n",
+ printk(KERN_ERR "no valid RTLX id at 0x%p found 0x%lx should be
0x%x\n",
rtlxi, rtlxi->id, RTLX_ID);
return -ENOEXEC;
}
@@ -149,6 +149,18 @@
int ret;
struct rtlx_channel *chan;
volatile struct rtlx_info **p;
+
+ if (index >= RTLX_CHANNELS) {
+ printk(KERN_DEBUG "rtlx_open index out of range\n");
+ return -ENOSYS;
+ }
+
+ if (channel_wqs[index].in_open) {
+ printk(KERN_DEBUG "rtlx_open channel %d already opened\n",
index);
+ return -EBUSY;
+ }
+
+ channel_wqs[index].in_open++;
if (rtlx == NULL) {
if( (p = vpe_get_shared(RTLX_TARG_VPE)) == NULL) {
@@ -171,6 +183,7 @@
} else {
printk( KERN_DEBUG "No SP program loaded, and
device "
"opened with O_NONBLOCK\n");
+ channel_wqs[index].in_open = 0;
return -ENOSYS;
}
}
@@ -186,12 +199,7 @@
while (*p == NULL) {
schedule();
- /* reset task state to interruptable
otherwise
- we'll whizz round here like a very
fast loopy
- thing. schedule() appears to return
with state
- set to TASK_RUNNING.
-
- If the loaded SP program, for
whatever reason,
+ /* If the loaded SP program, for
whatever reason,
doesn't set up the shared structure
*p will never
become true. So whoever connected to
either /dev/rt?
or if it was kspd, will then take up
rather a lot of
@@ -209,6 +217,7 @@
else {
printk(" *vpe_get_shared is NULL. "
"Has an SP program been loaded?\n");
+ channel_wqs[index].in_open = 0;
return -ENOSYS;
}
}
@@ -216,20 +225,26 @@
if ((unsigned int)*p < KSEG0) {
printk(KERN_WARNING "vpe_get_shared returned an invalid
pointer "
"maybe an error code %d\n", (int)*p);
+ channel_wqs[index].in_open = 0;
return -ENOSYS;
}
- if ((ret = rtlx_init(*p)) < 0)
+ if ((ret = rtlx_init(*p)) < 0) {
+ channel_wqs[index].in_open = 0;
return ret;
+ }
}
-
+
chan = &rtlx->channel[index];
/* already open? */
- if (chan->lx_state == RTLX_STATE_OPENED)
+ if (chan->lx_state == RTLX_STATE_OPENED) {
+ channel_wqs[index].in_open = 0;
return -EBUSY;
+ }
chan->lx_state = RTLX_STATE_OPENED;
+ channel_wqs[index].in_open = 0;
return 0;
}
@@ -478,6 +493,7 @@
for (i = 0; i < RTLX_CHANNELS; i++) {
init_waitqueue_head(&channel_wqs[i].rt_queue);
init_waitqueue_head(&channel_wqs[i].lx_queue);
+ channel_wqs[i].in_open = 0;
}
/* set up notifiers */
diff -urN malta/linux/arch/mips/kernel/vpe.c malta/linux/arch/mips/kernel/vpe.c
--- malta/linux/arch/mips/kernel/vpe.c 2005/08/19 13:47:36 1.1.1000.4
+++ malta/linux/arch/mips/kernel/vpe.c 2005/09/02 17:02:54 1.1.1000.5
@@ -164,8 +164,10 @@
} vpecontrol;
static void release_progmem(void *ptr);
-static void dump_vpe(vpe_t * v);
extern void save_gp_address(unsigned int secbase, unsigned int rel);
+#ifdef VPE_DEBUG
+static void dump_vpe(vpe_t * v);
+#endif
/* get the vpe associated with this minor */
struct vpe *get_vpe(int minor)
@@ -741,9 +743,6 @@
/* disable MT (using dvpe) */
dvpe();
- /* Put MVPE's into 'configuration state' */
- write_c0_mvpcontrol(read_c0_mvpcontrol() | MVPCONTROL_VPC);
-
if (!list_empty(&v->tc)) {
if ((t = list_entry(v->tc.next, struct tc, tc)) == NULL) {
printk(KERN_WARNING "VPE: TC %d is already in use.\n",
@@ -756,6 +755,9 @@
return -ENOEXEC;
}
+ /* Put MVPE's into 'configuration state' */
+ write_c0_mvpcontrol(read_c0_mvpcontrol() | MVPCONTROL_VPC);
+
settc(t->index);
/* should check it is halted, and not activated */
@@ -773,10 +775,8 @@
/* Write the address we want it to start running from in the TCPC
register. */
write_tc_c0_tcrestart((unsigned long)v->__start);
-
write_tc_c0_tccontext((unsigned long)0);
-
/* mark the TC as activated, not interrupt exempt and not dynamically
allocatable */
val = read_tc_c0_tcstatus();
@@ -823,7 +823,7 @@
return 0;
}
-static unsigned long find_vpe_symbols(vpe_t * v, Elf_Shdr * sechdrs,
+static int find_vpe_symbols(vpe_t * v, Elf_Shdr * sechdrs,
unsigned int symindex, const char *strtab,
struct module *mod)
{
@@ -840,6 +840,9 @@
}
}
+ if ( (v->__start == 0) || (v->shared_ptr == NULL))
+ return -1;
+
return 0;
}
@@ -974,6 +977,19 @@
}
} else {
for (i = 0; i < hdr->e_shnum; i++) {
+
+ /* Internal symbols and strings. */
+ if (sechdrs[i].sh_type == SHT_SYMTAB) {
+ symindex = i;
+ strindex = sechdrs[i].sh_link;
+ strtab = (char *)hdr +
sechdrs[strindex].sh_offset;
+
+ /* mark the symtab's address for when we try to
find the
+ magic symbols */
+ sechdrs[i].sh_addr = (size_t) hdr +
sechdrs[i].sh_offset;
+ }
+
+ /* filter sections we dont want in the final image */
if (!(sechdrs[i].sh_flags & SHF_ALLOC) ||
(sechdrs[i].sh_type == SHT_MIPS_REGINFO)) {
printk( KERN_DEBUG " ignoring section, "
@@ -992,12 +1008,13 @@
return -ENOEXEC;
}
- printk(KERN_DEBUG " copying section sh_name %s, sh_addr
0x%x size 0x%x\n",
+ printk(KERN_DEBUG " copying section sh_name %s, sh_addr
0x%x "
+ "size 0x%x0 from x%p\n",
secstrings + sechdrs[i].sh_name,
sechdrs[i].sh_addr,
- sechdrs[i].sh_size);
+ sechdrs[i].sh_size, hdr + sechdrs[i].sh_offset);
if (sechdrs[i].sh_type != SHT_NOBITS)
- memcpy((void *)sechdrs[i].sh_addr, v->pbuffer +
sechdrs[i].sh_offset,
+ memcpy((void *)sechdrs[i].sh_addr, (char *)hdr
+ sechdrs[i].sh_offset,
sechdrs[i].sh_size);
else
memset((void *)sechdrs[i].sh_addr, 0,
sechdrs[i].sh_size);
@@ -1022,6 +1039,7 @@
return err;
}
+#ifdef VPE_DEBUG
static void dump_vpe(vpe_t * v)
{
struct tc *t;
@@ -1035,6 +1053,7 @@
dump_tc(t);
}
}
+#endif
static void cleanup_tc(struct tc *tc)
{
@@ -1129,6 +1148,8 @@
printk("VPE: open, getcwd returned %d\n", ret);
}
+ v->shared_ptr = NULL;
+ v->__start = 0;
return 0;
}
@@ -1157,14 +1178,6 @@
ret = -ENOEXEC;
}
- /* It's good to be able to run the SP and if it chokes have a look at
- the /dev/rt?. But if we reset the pointer to the shared struct we
- loose what has happened. So perhaps if garbage is sent to the vpe
- device, use it as a trigger for the reset. Hopefully a nice
- executable will be along shortly. */
- if (ret < 0)
- v->shared_ptr = NULL;
-
// cleanup any temp buffers
if (v->pbuffer)
vfree(v->pbuffer);
|