--- zzzz-none-000/linux-3.10.107/arch/mips/kernel/smtc.c 2017-06-27 09:49:32.000000000 +0000 +++ vr9-7490-729/linux-3.10.107/arch/mips/kernel/smtc.c 2021-11-10 11:53:54.000000000 +0000 @@ -420,7 +420,7 @@ IPIQ[i].head = IPIQ[i].tail = NULL; spin_lock_init(&IPIQ[i].lock); IPIQ[i].depth = 0; - IPIQ[i].resched_flag = 0; /* No reschedules queued initially */ + atomic_set(&IPIQ[i].resched_flag, 0); /* No reschedules queued initially */ } /* cpu_data index starts at zero */ @@ -620,7 +620,7 @@ pipi = kmalloc(nipi *sizeof(struct smtc_ipi), GFP_KERNEL); if (pipi == NULL) - panic("kmalloc of IPI message buffers failed"); + panic("kmalloc of IPI message buffers failed\n"); else printk("IPI buffer pool of %d buffers\n", nipi); for (i = 0; i < nipi; i++) { @@ -647,7 +647,7 @@ */ void __cpuinit smtc_boot_secondary(int cpu, struct task_struct *idle) { - extern u32 kernelsp[NR_CPUS]; + extern unsigned long kernelsp[NR_CPUS]; unsigned long flags; int mtflags; @@ -660,6 +660,10 @@ /* pc */ write_tc_c0_tcrestart((unsigned long)&smp_bootstrap); +#ifdef CONFIG_AVM_ENHANCED + write_tc_c0_tcstatus(read_tc_c0_tcstatus() | TCSTATUS_TMX); /* allow DSP instructions */ +#endif + /* stack pointer */ kernelsp[cpu] = __KSTK_TOS(idle); write_tc_gpr_sp(__KSTK_TOS(idle)); @@ -810,7 +814,7 @@ pr_info("IPIQ[%d]: head = 0x%x, tail = 0x%x, depth = %d\n", i, (unsigned)IPIQ[i].head, (unsigned)IPIQ[i].tail, IPIQ[i].depth); - temp = IPIQ[i].head; + temp = (struct smtc_ipi *) IPIQ[i].head; while (temp != IPIQ[i].tail) { pr_debug("%d %d %d: ", temp->type, temp->dest, @@ -866,14 +870,14 @@ printk("Cannot Send IPI to self!\n"); return; } - if (set_resched_flag && IPIQ[cpu].resched_flag != 0) + if (set_resched_flag && atomic_read(&IPIQ[cpu].resched_flag) != 0) return; /* There is a reschedule queued already */ /* Set up a descriptor, to be delivered either promptly or queued */ pipi = smtc_ipi_dq(&freeIPIq); if (pipi == NULL) { bust_spinlocks(1); - mips_mt_regdump(dvpe()); + mips_mt_regdump(0); panic("IPI Msg. Buffers Depleted"); } pipi->type = type; @@ -881,7 +885,9 @@ pipi->dest = cpu; if (cpu_data[cpu].vpe_id != cpu_data[smp_processor_id()].vpe_id) { /* If not on same VPE, enqueue and send cross-VPE interrupt */ - IPIQ[cpu].resched_flag |= set_resched_flag; + if (set_resched_flag) + atomic_set(&IPIQ[cpu].resched_flag, set_resched_flag); + smp_mb(); smtc_ipi_nq(&IPIQ[cpu], pipi); LOCK_CORE_PRA(); settc(cpu_data[cpu].tc_id); @@ -927,7 +933,9 @@ */ write_tc_c0_tchalt(0); UNLOCK_CORE_PRA(); - IPIQ[cpu].resched_flag |= set_resched_flag; + if (set_resched_flag) + atomic_set(&IPIQ[cpu].resched_flag, set_resched_flag); + smp_mb(); smtc_ipi_nq(&IPIQ[cpu], pipi); } else { postdirect: @@ -946,7 +954,7 @@ struct pt_regs *kstack; unsigned long tcstatus; unsigned long tcrestart; - extern u32 kernelsp[NR_CPUS]; + extern unsigned long kernelsp[NR_CPUS]; extern void __smtc_ipi_vector(void); //printk("%s: on %d for %d\n", __func__, smp_processor_id(), cpu); @@ -1029,6 +1037,7 @@ switch ((int)arg_copy) { case SMP_RESCHEDULE_YOURSELF: ipi_resched_interrupt(); + atomic_set(&IPIQ[smp_processor_id()].resched_flag, 0); break; case SMP_CALL_FUNCTION: ipi_call_interrupt(); @@ -1088,7 +1097,7 @@ if (pipi != NULL) { if (pipi->type == LINUX_SMP_IPI && (int)pipi->arg == SMP_RESCHEDULE_YOURSELF) - IPIQ[cpu].resched_flag = 0; + atomic_set(&IPIQ[cpu].resched_flag, 0); ipi_decode(pipi); } /* @@ -1110,16 +1119,54 @@ static int cpu_ipi_irq = MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_IRQ; -static irqreturn_t ipi_interrupt(int irq, void *dev_idm) +static inline void ipi_interrupt_dequeue_and_handle(int cpu) { - int my_vpe = cpu_data[smp_processor_id()].vpe_id; - int my_tc = cpu_data[smp_processor_id()].tc_id; - int cpu; struct smtc_ipi *pipi; unsigned long tcstatus; - int sent; unsigned long flags; unsigned int mtflags; + int my_tc = cpu_data[smp_processor_id()].tc_id; + int sent; + + do { + pipi = smtc_ipi_dq(&IPIQ[cpu]); + if (!pipi) + break; + + if (cpu_data[cpu].tc_id != my_tc) { + sent = 0; + LOCK_CORE_PRA(); + settc(cpu_data[cpu].tc_id); + write_tc_c0_tchalt(TCHALT_H); + mips_ihb(); + tcstatus = read_tc_c0_tcstatus(); + if ((tcstatus & TCSTATUS_IXMT) == 0) { + post_direct_ipi(cpu, pipi); + sent = 1; + } + write_tc_c0_tchalt(0); + UNLOCK_CORE_PRA(); + if (!sent) { + smtc_ipi_req(&IPIQ[cpu], pipi); + } + } else { + /* + * ipi_decode() should be called + * with interrupts off + */ + if (pipi->type == LINUX_SMP_IPI && + (int)pipi->arg == SMP_RESCHEDULE_YOURSELF) + atomic_set(&IPIQ[cpu].resched_flag, 0); + ipi_decode(pipi); + } + } while (pipi); +} + +static irqreturn_t ipi_interrupt(int irq, void *dev_idm) +{ + int my_vpe = cpu_data[smp_processor_id()].vpe_id; + int cpu; + unsigned long flags; unsigned int vpflags; /* @@ -1130,56 +1177,33 @@ */ local_irq_save(flags); vpflags = dvpe(); - clear_c0_cause(0x100 << MIPS_CPU_IPI_IRQ); - set_c0_status(0x100 << MIPS_CPU_IPI_IRQ); - irq_enable_hazard(); - evpe(vpflags); - local_irq_restore(flags); - /* - * Cross-VPE Interrupt handler: Try to directly deliver IPIs - * queued for TCs on this VPE other than the current one. - * Return-from-interrupt should cause us to drain the queue - * for the current TC, so we ought not to have to do it explicitly here. - */ + while (read_c0_cause() & (0x100 << MIPS_CPU_IPI_IRQ)) { + clear_c0_cause(0x100 << MIPS_CPU_IPI_IRQ); + set_c0_status(0x100 << MIPS_CPU_IPI_IRQ); + irq_enable_hazard(); + evpe(vpflags); - for_each_online_cpu(cpu) { - if (cpu_data[cpu].vpe_id != my_vpe) - continue; + /* + * Cross-VPE Interrupt handler: Try to directly deliver IPIs + * queued for TCs on this VPE other than the current one. + * Return-from-interrupt should cause us to drain the queue + * for the current TC, so we ought not to have to do it explicitly here. + */ - pipi = smtc_ipi_dq(&IPIQ[cpu]); - if (pipi != NULL) { - if (cpu_data[cpu].tc_id != my_tc) { - sent = 0; - LOCK_MT_PRA(); - settc(cpu_data[cpu].tc_id); - write_tc_c0_tchalt(TCHALT_H); - mips_ihb(); - tcstatus = read_tc_c0_tcstatus(); - if ((tcstatus & TCSTATUS_IXMT) == 0) { - post_direct_ipi(cpu, pipi); - sent = 1; - } - write_tc_c0_tchalt(0); - UNLOCK_MT_PRA(); - if (!sent) { - smtc_ipi_req(&IPIQ[cpu], pipi); - } - } else { - /* - * ipi_decode() should be called - * with interrupts off - */ - local_irq_save(flags); - if (pipi->type == LINUX_SMP_IPI && - (int)pipi->arg == SMP_RESCHEDULE_YOURSELF) - IPIQ[cpu].resched_flag = 0; - ipi_decode(pipi); - local_irq_restore(flags); - } + for_each_online_cpu(cpu) { + if (cpu_data[cpu].vpe_id != my_vpe) + continue; + + ipi_interrupt_dequeue_and_handle(cpu); } + + vpflags = dvpe(); } + evpe(vpflags); + local_irq_restore(flags); + return IRQ_HANDLED; } @@ -1301,13 +1325,13 @@ } } + /* Prüfung vom 3.14.40 Kernel übernommen */ /* Have we stupidly left IXMT set somewhere? */ if (read_c0_tcstatus() & 0x400) { write_c0_tcstatus(read_c0_tcstatus() & ~0x400); ehb(); printk("Dangling IXMT in cpu_idle()\n"); } - /* Have we stupidly left an IM bit turned off? */ #define IM_LIMIT 2000 local_irq_save(flags); @@ -1349,16 +1373,16 @@ { int i; - printk("Counter Interrupts taken per CPU (TC)\n"); + printk(KERN_EMERG"Counter Interrupts taken per CPU (TC)\n"); for (i=0; i < NR_CPUS; i++) { printk("%d: %ld\n", i, smtc_cpu_stats[i].timerints); } - printk("Self-IPI invocations:\n"); + printk(KERN_EMERG"Self-IPI invocations:\n"); for (i=0; i < NR_CPUS; i++) { printk("%d: %ld\n", i, smtc_cpu_stats[i].selfipis); } smtc_ipi_qdump(); - printk("%d Recoveries of \"stolen\" FPU\n", + printk(KERN_EMERG"%d Recoveries of \"stolen\" FPU\n", atomic_read(&smtc_fpu_recoveries)); } @@ -1517,7 +1541,6 @@ * that all CACHE ops have played through. */ mips_ihb(); - for_each_online_cpu(cpu) { if (cpu != smp_processor_id()) { settc(cpu_data[cpu].tc_id);