From: Deng-Cheng Zhu <dczhu@xxxxxxxx> Now CPS such as 1004K can run programs in APRP (APSP) model. For example, a 3 core 1004K CPU can run SMVP Linux on the first 2 cores and leave a VPE of the 3rd core to run RTOS or signal processing program. The kernel command line option "maxcpus=" needs to be appointed. Basically I think the way we are doing with rtlx/kspd/vpe_loader can be extended to other architectures, despite of the low-level register details. To handle the AP/RP communication interrupt, we hook our ISR into the ipi resched interrupt. Known issue: When we define CONFIG_MIPS_CMP to let 1004K run SMVP Linux and RP program, currently we can only load the RP program 1 time. Loading it multiple times won't affect the kernel, but only the 1st time works as expected. This is not a top priority issue I suppose, since normally we build RP programs to keep alive as kind of server programs -- They wait for requests in the CPU "wait" mode. Signed-off-by: Deng-Cheng Zhu <dczhu@xxxxxxxx> --- Changes: v2 - v1: o Rebase the patch to the latest kernel, and fix a bunch of warnings and errors reported by the current scripts/checkpatch.pl. However, there are still 2 warnings that I decide to leave alone for now: 1) externs should be avoided in .c files #261: FILE: arch/mips/kernel/rtlx.c:382: + extern struct plat_smp_ops cmp_smp_ops; Currently, in smp-ops.h, {up|cmp|vsmp}_smp_ops are not externed globally. Maybe we can do it in a separate patch. 2) Use of volatile is usually wrong: see Documentation/volatile-considered-harmful.txt #456: FILE: arch/mips/kernel/vpe.c:698: + volatile struct cpulaunch *launch = The volatile is really needed in here. The content pointed to by launch will be updated by YAMON. arch/mips/include/asm/rtlx.h | 5 +- arch/mips/kernel/kspd.c | 26 +++- arch/mips/kernel/rtlx.c | 158 ++++++++++++++++++++---- arch/mips/kernel/vpe.c | 253 +++++++++++++++++++++++++++++++++++---- arch/mips/mti-malta/malta-int.c | 16 ++- 5 files changed, 397 insertions(+), 61 deletions(-) diff --git a/arch/mips/include/asm/rtlx.h b/arch/mips/include/asm/rtlx.h index cf23a8c..478349e 100644 --- a/arch/mips/include/asm/rtlx.h +++ b/arch/mips/include/asm/rtlx.h @@ -28,7 +28,7 @@ extern ssize_t rtlx_write(int index, const void __user *buffer, size_t count); extern unsigned int rtlx_read_poll(int index, int can_sleep); extern unsigned int rtlx_write_poll(int index); -extern void (*aprp_dispatch)(void); +extern void (*aprp_hook)(void); enum rtlx_state { RTLX_STATE_UNUSED = 0, @@ -60,6 +60,9 @@ struct rtlx_channel { struct rtlx_info { unsigned long id; enum rtlx_state state; +#ifdef CONFIG_MIPS_CMP + int ap_int_pending; +#endif struct rtlx_channel channel[RTLX_CHANNELS]; }; diff --git a/arch/mips/kernel/kspd.c b/arch/mips/kernel/kspd.c index 84d0639..bb8d26d 100644 --- a/arch/mips/kernel/kspd.c +++ b/arch/mips/kernel/kspd.c @@ -31,6 +31,9 @@ #include <asm/rtlx.h> #include <asm/kspd.h> +#ifdef CONFIG_MIPS_CMP +static int cpu_idx; +#endif static struct workqueue_struct *workqueue; static struct work_struct work; @@ -208,6 +211,7 @@ void sp_work_handle_request(void) char *vcwd; int size; + int index; ret.retval = -1; @@ -230,11 +234,16 @@ void sp_work_handle_request(void) } } +#ifdef CONFIG_MIPS_CMP + index = cpu_idx; +#else + index = tclimit; +#endif /* Run the syscall at the privilege of the user who loaded the SP program */ - if (vpe_getuid(tclimit)) { - err = sp_setfsuidgid(vpe_getuid(tclimit), vpe_getgid(tclimit)); + if (vpe_getuid(index)) { + err = sp_setfsuidgid(vpe_getuid(index), vpe_getgid(index)); if (!err) pr_err("Change of creds failed\n"); } @@ -256,7 +265,7 @@ void sp_work_handle_request(void) case MTSP_SYSCALL_EXIT: list_for_each_entry(n, &kspd_notifylist, list) - n->kspd_sp_exit(tclimit); + n->kspd_sp_exit(index); sp_stopping = 1; printk(KERN_DEBUG "KSPD got exit syscall from SP exitcode %d\n", @@ -266,7 +275,7 @@ void sp_work_handle_request(void) case MTSP_SYSCALL_OPEN: generic.arg1 = translate_open_flags(generic.arg1); - vcwd = vpe_getcwd(tclimit); + vcwd = vpe_getcwd(index); /* change to cwd of the process that loaded the SP program */ old_fs = get_fs(); @@ -294,7 +303,7 @@ void sp_work_handle_request(void) break; } /* switch */ - if (vpe_getuid(tclimit)) { + if (vpe_getuid(index)) { err = sp_setfsuidgid(0, 0); if (!err) pr_err("restoring old creds failed\n"); @@ -399,13 +408,18 @@ void kspd_notify(struct kspd_notifications *notify) } static struct vpe_notifications notify; -static int kspd_module_init(void) +static int __init kspd_module_init(void) { INIT_LIST_HEAD(&kspd_notifylist); notify.start = startwork; notify.stop = stopwork; +#ifdef CONFIG_MIPS_CMP + cpu_idx = setup_max_cpus; + vpe_notify(cpu_idx, ¬ify); +#else vpe_notify(tclimit, ¬ify); +#endif return 0; } diff --git a/arch/mips/kernel/rtlx.c b/arch/mips/kernel/rtlx.c index 9522aa5..7c02f02 100644 --- a/arch/mips/kernel/rtlx.c +++ b/arch/mips/kernel/rtlx.c @@ -54,17 +54,38 @@ static struct chan_waitqueues { static struct vpe_notifications notify; static int sp_stopping; -static void (*save_aprp_dispatch)(void); +static void (*save_aprp_hook)(void); extern void *vpe_get_shared(int index); +#ifdef CONFIG_MIPS_CMP +static int cpu_idx; +static void rtlx_interrupt(void) +{ + int i; + struct rtlx_info *info; + struct rtlx_info **p = vpe_get_shared(cpu_idx); + + if (p == NULL || *p == NULL) + return; + + info = *p; + + if (info->ap_int_pending == 1 && smp_processor_id() == 0) { + for (i = 0; i < RTLX_CHANNELS; i++) { + wake_up(&channel_wqs[i].lx_queue); + wake_up(&channel_wqs[i].rt_queue); + } + info->ap_int_pending = 0; + } +} +#else static void rtlx_dispatch(void) { if (read_c0_cause() & read_c0_status() & C_SW0) do_IRQ(MIPS_CPU_IRQ_BASE + MIPS_CPU_RTLX_IRQ); } - /* Interrupt handler may be called before rtlx_init has otherwise had a chance to run. */ @@ -83,12 +104,13 @@ static irqreturn_t rtlx_interrupt(int irq, void *dev_id) local_irq_restore(flags); for (i = 0; i < RTLX_CHANNELS; i++) { - wake_up(&channel_wqs[i].lx_queue); - wake_up(&channel_wqs[i].rt_queue); + wake_up(&channel_wqs[i].lx_queue); + wake_up(&channel_wqs[i].rt_queue); } return IRQ_HANDLED; } +#endif static void __used dump_rtlx(void) { @@ -157,6 +179,7 @@ int rtlx_open(int index, int can_sleep) struct rtlx_channel *chan; enum rtlx_state state; int ret = 0; + int cpu_index; if (index >= RTLX_CHANNELS) { printk(KERN_DEBUG "rtlx_open index out of range\n"); @@ -170,19 +193,27 @@ int rtlx_open(int index, int can_sleep) goto out_fail; } +#ifdef CONFIG_MIPS_CMP + cpu_index = cpu_idx; +#else + cpu_index = tclimit; +#endif + if (rtlx == NULL) { - if( (p = vpe_get_shared(tclimit)) == NULL) { - if (can_sleep) { - __wait_event_interruptible(channel_wqs[index].lx_queue, - (p = vpe_get_shared(tclimit)), ret); - if (ret) + p = vpe_get_shared(cpu_index); + if (p == NULL) { + if (can_sleep) { + __wait_event_interruptible( + channel_wqs[index].lx_queue, + (p = vpe_get_shared(cpu_index)), ret); + if (ret) + goto out_fail; + } else { + printk(KERN_DEBUG + "No SP program loaded, and device opened with O_NONBLOCK\n"); + ret = -ENOSYS; goto out_fail; - } else { - printk(KERN_DEBUG "No SP program loaded, and device " - "opened with O_NONBLOCK\n"); - ret = -ENOSYS; - goto out_fail; - } + } } smp_rmb(); @@ -345,6 +376,14 @@ out: return count; } +#ifdef CONFIG_MIPS_CMP +static void _interrupt_sp(void) +{ + extern struct plat_smp_ops cmp_smp_ops; + + cmp_smp_ops.send_ipi_single(cpu_idx, SMP_RESCHEDULE_YOURSELF); +} +#else static void _interrupt_sp(void) { unsigned long flags; @@ -356,6 +395,7 @@ static void _interrupt_sp(void) evpe(EVPE_ENABLE); local_irq_restore(flags); } +#endif ssize_t rtlx_write(int index, const void __user *buffer, size_t count) { @@ -486,6 +526,75 @@ static const struct file_operations rtlx_fops = { .llseek = noop_llseek, }; +static char register_chrdev_failed[] __initdata = + KERN_ERR "rtlx_module_init: unable to register device\n"; + +#ifdef CONFIG_MIPS_CMP +static int __init rtlx_module_init(void) +{ + struct device *dev; + int i, err; + + if (!cpu_has_mipsmt) { + printk(KERN_WARNING + "VPE loader: not a MIPS MT capable processor\n"); + return -ENODEV; + } + + cpu_idx = setup_max_cpus; + + if (num_possible_cpus() - cpu_idx < 1) { + printk(KERN_WARNING + "No TCs reserved for AP/SP, not initializing RTLX.\n" + "Pass maxcpus=<n> argument as kernel argument\n"); + + return -ENODEV; + } + + major = register_chrdev(0, module_name, &rtlx_fops); + if (major < 0) { + printk(register_chrdev_failed); + return major; + } + + /* initialise the wait queues */ + for (i = 0; i < RTLX_CHANNELS; i++) { + 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), NULL, + "%s%d", module_name, i); + if (IS_ERR(dev)) { + err = PTR_ERR(dev); + goto out_chrdev; + } + } + + /* set up notifiers */ + notify.start = starting; + notify.stop = stopping; + vpe_notify(cpu_idx, ¬ify); + + if (cpu_has_vint) { + save_aprp_hook = aprp_hook; + aprp_hook = rtlx_interrupt; + } else { + pr_err("APRP RTLX init on non-vectored-interrupt processor\n"); + err = -ENODEV; + goto out_chrdev; + } + + return 0; + +out_chrdev: + for (i = 0; i < RTLX_CHANNELS; i++) + device_destroy(mt_class, MKDEV(major, i)); + + return err; +} +#else static struct irqaction rtlx_irq = { .handler = rtlx_interrupt, .name = "RTLX", @@ -493,23 +602,21 @@ static struct irqaction rtlx_irq = { static int rtlx_irq_num = MIPS_CPU_IRQ_BASE + MIPS_CPU_RTLX_IRQ; -static char register_chrdev_failed[] __initdata = - KERN_ERR "rtlx_module_init: unable to register device\n"; - static int __init rtlx_module_init(void) { struct device *dev; int i, err; if (!cpu_has_mipsmt) { - printk("VPE loader: not a MIPS MT capable processor\n"); + printk(KERN_WARNING + "VPE loader: not a MIPS MT capable processor\n"); return -ENODEV; } if (tclimit == 0) { - printk(KERN_WARNING "No TCs reserved for AP/SP, not " - "initializing RTLX.\nPass maxtcs=<n> argument as kernel " - "argument\n"); + printk(KERN_WARNING + "No TCs reserved for AP/SP, not initializing RTLX.\n" + "Pass maxtcs=<n> argument as kernel argument\n"); return -ENODEV; } @@ -546,8 +653,8 @@ static int __init rtlx_module_init(void) * gets set, a hw interrupt is signaled as well. Here we * are hooking it into platform specific dispatch. */ - save_aprp_dispatch = aprp_dispatch; - aprp_dispatch = rtlx_dispatch; + save_aprp_hook = aprp_hook; + aprp_hook = rtlx_dispatch; } else { pr_err("APRP RTLX init on non-vectored-interrupt processor\n"); err = -ENODEV; @@ -565,6 +672,7 @@ out_chrdev: return err; } +#endif static void __exit rtlx_module_exit(void) { @@ -574,7 +682,7 @@ static void __exit rtlx_module_exit(void) device_destroy(mt_class, MKDEV(major, i)); unregister_chrdev(major, module_name); - aprp_dispatch = save_aprp_dispatch; + aprp_hook = save_aprp_hook; } module_init(rtlx_module_init); diff --git a/arch/mips/kernel/vpe.c b/arch/mips/kernel/vpe.c index b1f69f2..1ac3fd4 100644 --- a/arch/mips/kernel/vpe.c +++ b/arch/mips/kernel/vpe.c @@ -51,6 +51,10 @@ #include <asm/processor.h> #include <asm/vpe.h> #include <asm/kspd.h> +#ifdef CONFIG_MIPS_CMP +#include <asm/amon.h> +#include <asm/mips-boards/launch.h> +#endif typedef void *vpe_handle; @@ -64,7 +68,11 @@ typedef void *vpe_handle; /* * The number of TCs and VPEs physically available on the core */ +#ifdef CONFIG_MIPS_CMP +static int cpu_idx; +#else static int hw_tcs, hw_vpes; +#endif static char module_name[] = "vpe"; static int major; static const int minor = 1; /* fixed for now */ @@ -176,7 +184,7 @@ static struct vpe *get_vpe(int minor) } /* get the vpe associated with this minor */ -static struct tc *get_tc(int index) +static __attribute__((__unused__)) struct tc *get_tc(int index) { struct tc *res, *t; @@ -681,6 +689,46 @@ static void dump_elfsymbols(Elf_Shdr * sechdrs, unsigned int symindex, } #endif +#ifdef CONFIG_MIPS_CMP +#ifdef CONFIG_MIPS_MALTA +/* Borrowed from amon_cpu_start() in arch/mips/mti-malta/malta-amon.c */ +static int vpe_run(struct vpe *v) +{ + struct vpe_notifications *n; + volatile struct cpulaunch *launch = + (struct cpulaunch *)CKSEG0ADDR(CPULAUNCH); + + if (!amon_cpu_avail(cpu_idx)) + return -1; + if (cpu_idx == smp_processor_id()) { + printk(KERN_WARNING "launch: I am cpu%d!\n", cpu_idx); + return -1; + } + launch += cpu_idx; + + printk(KERN_INFO "launch: starting cpu%d\n", cpu_idx); + + launch->pc = v->__start; + launch->gp = 0; + launch->sp = 0; + launch->a0 = 0; + + smp_wmb(); + launch->flags |= LAUNCH_FGO; + smp_wmb(); + + while ((launch->flags & LAUNCH_FGONE) == 0) + ; + smp_rmb(); + printk(KERN_INFO "launch: cpu%d gone!\n", cpu_idx); + + list_for_each_entry(n, &v->notify, list) + n->start(minor); + + return 0; +} +#endif +#else /* We are prepared so configure and start the VPE... */ static int vpe_run(struct vpe * v) { @@ -810,6 +858,7 @@ static int vpe_run(struct vpe * v) return 0; } +#endif /* CONFIG_MIPS_CMP */ static int find_vpe_symbols(struct vpe * v, Elf_Shdr * sechdrs, unsigned int symindex, const char *strtab, @@ -1008,6 +1057,7 @@ static int vpe_elfload(struct vpe * v) return 0; } +#ifndef CONFIG_MIPS_CMP static void cleanup_tc(struct tc *tc) { unsigned long flags; @@ -1039,6 +1089,7 @@ static void cleanup_tc(struct tc *tc) emt(mtflags); local_irq_restore(flags); } +#endif static int getcwd(char *buff, int size) { @@ -1061,7 +1112,13 @@ static int vpe_open(struct inode *inode, struct file *filp) enum vpe_state state; struct vpe_notifications *not; struct vpe *v; - int ret; + int ret, index; + +#ifdef CONFIG_MIPS_CMP + index = cpu_idx; +#else + index = tclimit; +#endif if (minor != iminor(inode)) { /* assume only 1 device at the moment. */ @@ -1070,7 +1127,8 @@ static int vpe_open(struct inode *inode, struct file *filp) return -ENODEV; } - if ((v = get_vpe(tclimit)) == NULL) { + v = get_vpe(index); + if (v == NULL) { pr_warning("VPE loader: unable to get vpe\n"); return -ENODEV; @@ -1081,11 +1139,13 @@ static int vpe_open(struct inode *inode, struct file *filp) printk(KERN_DEBUG "VPE loader: tc in use dumping regs\n"); list_for_each_entry(not, &v->notify, list) { - not->stop(tclimit); + not->stop(index); } release_progmem(v->load_addr); - cleanup_tc(get_tc(tclimit)); +#ifndef CONFIG_MIPS_CMP + cleanup_tc(get_tc(index)); +#endif } /* this of-course trashes what was there before... */ @@ -1126,7 +1186,11 @@ static int vpe_release(struct inode *inode, struct file *filp) Elf_Ehdr *hdr; int ret = 0; +#ifdef CONFIG_MIPS_CMP + v = get_vpe(cpu_idx); +#else v = get_vpe(tclimit); +#endif if (v == NULL) return -ENODEV; @@ -1166,7 +1230,11 @@ static ssize_t vpe_write(struct file *file, const char __user * buffer, if (iminor(file->f_path.dentry->d_inode) != minor) return -ENODEV; +#ifdef CONFIG_MIPS_CMP + v = get_vpe(cpu_idx); +#else v = get_vpe(tclimit); +#endif if (v == NULL) return -ENODEV; @@ -1192,6 +1260,7 @@ static const struct file_operations vpe_fops = { .llseek = noop_llseek, }; +#ifndef CONFIG_MIPS_CMP /* module wrapper entry points */ /* give me a vpe */ vpe_handle vpe_alloc(void) @@ -1279,6 +1348,7 @@ int vpe_free(vpe_handle vpe) } EXPORT_SYMBOL(vpe_free); +#endif /* CONFIG_MIPS_CMP */ void *vpe_get_shared(int index) { @@ -1341,8 +1411,59 @@ char *vpe_getcwd(int index) EXPORT_SYMBOL(vpe_getcwd); +#ifdef CONFIG_MIPS_CMP #ifdef CONFIG_MIPS_APSP_KSPD -static void kspd_sp_exit( int sp_id) +static void kspd_sp_exit(int sp_id) +{ + /* Do nothing to the SP core. */ +} +#endif + +static ssize_t store_kill(struct device *dev, struct device_attribute *attr, + const char *buf, size_t len) +{ + struct vpe *vpe = get_vpe(cpu_idx); + struct vpe_notifications *not; + + list_for_each_entry(not, &vpe->notify, list) { + not->stop(cpu_idx); + } + + release_progmem(vpe->load_addr); + vpe->state = VPE_STATE_UNUSED; + + return len; +} + +static ssize_t show_ntcs(struct device *cd, struct device_attribute *attr, + char *buf) +{ + struct vpe *vpe = get_vpe(cpu_idx); + + return sprintf(buf, "%d\n", vpe->ntcs); +} + +static ssize_t store_ntcs(struct device *dev, struct device_attribute *attr, + const char *buf, size_t len) +{ + struct vpe *vpe = get_vpe(cpu_idx); + unsigned long new; + int ret; + + ret = kstrtoul(buf, 0, &new); + if (ret < 0) + return ret; + + if (new != 1) + return -EINVAL; + + vpe->ntcs = new; + + return len; +} +#else +#ifdef CONFIG_MIPS_APSP_KSPD +static void kspd_sp_exit(int sp_id) { cleanup_tc(get_tc(sp_id)); } @@ -1379,22 +1500,20 @@ static ssize_t store_ntcs(struct device *dev, struct device_attribute *attr, { struct vpe *vpe = get_vpe(tclimit); unsigned long new; - char *endp; + int ret; - new = simple_strtoul(buf, &endp, 0); - if (endp == buf) - goto out_einval; + ret = kstrtoul(buf, 0, &new); + if (ret < 0) + return ret; if (new == 0 || new > (hw_tcs - tclimit)) - goto out_einval; + return -EINVAL; vpe->ntcs = new; return len; - -out_einval: - return -EINVAL; } +#endif /* CONFIG_MIPS_CMP */ static struct device_attribute vpe_class_attributes[] = { __ATTR(kill, S_IWUSR, NULL, store_kill), @@ -1416,6 +1535,90 @@ struct class vpe_class = { struct device vpe_device; +#ifdef CONFIG_MIPS_CMP +static int __init vpe_module_init(void) +{ + struct vpe *v = NULL; + struct tc *t; + int err; + + if (!cpu_has_mipsmt) { + printk(KERN_WARNING + "VPE loader: not a MIPS MT capable processor\n"); + return -ENODEV; + } + + cpu_idx = setup_max_cpus; + + if (num_possible_cpus() - cpu_idx < 1) { + printk(KERN_WARNING + "No VPEs reserved for AP/SP, not initialize VPE loader\n" + "Pass maxcpus=<n> argument as kernel argument\n"); + return -ENODEV; + } + + major = register_chrdev(0, module_name, &vpe_fops); + if (major < 0) { + printk(KERN_WARNING + "VPE loader: unable to register character device\n"); + return major; + } + + err = class_register(&vpe_class); + if (err) { + printk(KERN_ERR "vpe_class registration failed\n"); + goto out_chrdev; + } + + device_initialize(&vpe_device); + vpe_device.class = &vpe_class, + vpe_device.parent = NULL, + dev_set_name(&vpe_device, "vpe_sp"); + vpe_device.devt = MKDEV(major, minor); + err = device_add(&vpe_device); + if (err) { + printk(KERN_ERR "Adding vpe_device failed\n"); + goto out_class; + } + + t = alloc_tc(cpu_idx); + if (!t) { + printk(KERN_WARNING "VPE: unable to allocate TC\n"); + err = -ENOMEM; + goto out; + } + + /* VPE */ + v = alloc_vpe(cpu_idx); + if (v == NULL) { + printk(KERN_WARNING "VPE: unable to allocate VPE\n"); + kfree(t); + err = -ENOMEM; + goto out; + } + + v->ntcs = 1; + + /* add the tc to the list of this vpe's tc's. */ + list_add(&t->tc, &v->tc); + + /* TC */ + t->pvpe = v; /* set the parent vpe */ + +#ifdef CONFIG_MIPS_APSP_KSPD + kspd_events.kspd_sp_exit = kspd_sp_exit; +#endif + return 0; + +out_class: + class_unregister(&vpe_class); +out_chrdev: + unregister_chrdev(major, module_name); + +out: + return err; +} +#else static int __init vpe_module_init(void) { unsigned int mtflags, vpflags; @@ -1425,29 +1628,31 @@ static int __init vpe_module_init(void) int tc, err; if (!cpu_has_mipsmt) { - printk("VPE loader: not a MIPS MT capable processor\n"); + printk(KERN_WARNING + "VPE loader: not a MIPS MT capable processor\n"); return -ENODEV; } if (vpelimit == 0) { - printk(KERN_WARNING "No VPEs reserved for AP/SP, not " - "initializing VPE loader.\nPass maxvpes=<n> argument as " - "kernel argument\n"); + printk(KERN_WARNING + "No VPEs reserved for AP/SP, not initialize VPE loader\n" + "Pass maxvpes=<n> argument as kernel argument\n"); return -ENODEV; } if (tclimit == 0) { - printk(KERN_WARNING "No TCs reserved for AP/SP, not " - "initializing VPE loader.\nPass maxtcs=<n> argument as " - "kernel argument\n"); + printk(KERN_WARNING + "No TCs reserved for AP/SP, not initialize VPE loader\n" + "Pass maxtcs=<n> argument as kernel argument\n"); return -ENODEV; } major = register_chrdev(0, module_name, &vpe_fops); if (major < 0) { - printk("VPE loader: unable to register character device\n"); + printk(KERN_WARNING + "VPE loader: unable to register character device\n"); return major; } @@ -1505,7 +1710,8 @@ static int __init vpe_module_init(void) if (tc < hw_tcs) { settc(tc); - if ((v = alloc_vpe(tc)) == NULL) { + v = alloc_vpe(tc); + if (v == NULL) { printk(KERN_WARNING "VPE: unable to allocate VPE\n"); goto out_reenable; @@ -1598,6 +1804,7 @@ out_chrdev: out: return err; } +#endif /* CONFIG_MIPS_CMP */ static void __exit vpe_module_exit(void) { diff --git a/arch/mips/mti-malta/malta-int.c b/arch/mips/mti-malta/malta-int.c index 62d77df..1a15fd6 100644 --- a/arch/mips/mti-malta/malta-int.c +++ b/arch/mips/mti-malta/malta-int.c @@ -119,12 +119,12 @@ static inline int get_int(void) } #ifdef CONFIG_MIPS_VPE_APSP_API -static void null_aprp_dispatch(void) +static void null_aprp_hook(void) { } -void (*aprp_dispatch)(void); -EXPORT_SYMBOL(aprp_dispatch); +void (*aprp_hook)(void); +EXPORT_SYMBOL(aprp_hook); #endif static void malta_hw0_irqdispatch(void) @@ -139,13 +139,13 @@ static void malta_hw0_irqdispatch(void) do_IRQ(MALTA_INT_BASE + irq); -#ifdef CONFIG_MIPS_VPE_APSP_API +#if defined(CONFIG_MIPS_VPE_APSP_API) && !defined(CONFIG_MIPS_CMP) /* * When sw0 gets set, a spurious hw interrupt is signaled as well. * The sw0 will not be handled until the hw interrupt is cleared. * We use the hook to handle sw0 and the hw interrupt gets cleared. */ - aprp_dispatch(); + aprp_hook(); #endif } @@ -328,6 +328,10 @@ static void ipi_call_dispatch(void) static irqreturn_t ipi_resched_interrupt(int irq, void *dev_id) { +#if defined(CONFIG_MIPS_VPE_APSP_API) && defined(CONFIG_MIPS_CMP) + aprp_hook(); +#endif + scheduler_ipi(); return IRQ_HANDLED; @@ -640,7 +644,7 @@ void __init arch_init_irq(void) } #ifdef CONFIG_MIPS_VPE_APSP_API - aprp_dispatch = null_aprp_dispatch; + aprp_hook = null_aprp_hook; #endif } -- 1.7.1