Loading arch/mips/include/asm/smtc_ipi.h +1 −0 Original line number Original line Diff line number Diff line Loading @@ -45,6 +45,7 @@ struct smtc_ipi_q { spinlock_t lock; spinlock_t lock; struct smtc_ipi *tail; struct smtc_ipi *tail; int depth; int depth; int resched_flag; /* reschedule already queued */ }; }; static inline void smtc_ipi_nq(struct smtc_ipi_q *q, struct smtc_ipi *p) static inline void smtc_ipi_nq(struct smtc_ipi_q *q, struct smtc_ipi *p) Loading arch/mips/kernel/smtc.c +30 −4 Original line number Original line Diff line number Diff line Loading @@ -75,7 +75,6 @@ unsigned long irq_hwmask[NR_IRQS]; asiduse smtc_live_asid[MAX_SMTC_TLBS][MAX_SMTC_ASIDS]; asiduse smtc_live_asid[MAX_SMTC_TLBS][MAX_SMTC_ASIDS]; /* /* * Number of InterProcessor Interrupt (IPI) message buffers to allocate * Number of InterProcessor Interrupt (IPI) message buffers to allocate */ */ Loading Loading @@ -388,6 +387,7 @@ void smtc_prepare_cpus(int cpus) IPIQ[i].head = IPIQ[i].tail = NULL; IPIQ[i].head = IPIQ[i].tail = NULL; spin_lock_init(&IPIQ[i].lock); spin_lock_init(&IPIQ[i].lock); IPIQ[i].depth = 0; IPIQ[i].depth = 0; IPIQ[i].resched_flag = 0; /* No reschedules queued initially */ } } /* cpu_data index starts at zero */ /* cpu_data index starts at zero */ Loading Loading @@ -741,11 +741,24 @@ void smtc_forward_irq(unsigned int irq) static void smtc_ipi_qdump(void) static void smtc_ipi_qdump(void) { { int i; int i; struct smtc_ipi *temp; for (i = 0; i < NR_CPUS ;i++) { for (i = 0; i < NR_CPUS ;i++) { printk("IPIQ[%d]: head = 0x%x, tail = 0x%x, depth = %d\n", pr_info("IPIQ[%d]: head = 0x%x, tail = 0x%x, depth = %d\n", i, (unsigned)IPIQ[i].head, (unsigned)IPIQ[i].tail, i, (unsigned)IPIQ[i].head, (unsigned)IPIQ[i].tail, IPIQ[i].depth); IPIQ[i].depth); temp = IPIQ[i].head; while (temp != IPIQ[i].tail) { pr_debug("%d %d %d: ", temp->type, temp->dest, (int)temp->arg); #ifdef SMTC_IPI_DEBUG pr_debug("%u %lu\n", temp->sender, temp->stamp); #else pr_debug("\n"); #endif temp = temp->flink; } } } } } Loading Loading @@ -784,11 +797,16 @@ void smtc_send_ipi(int cpu, int type, unsigned int action) int mtflags; int mtflags; unsigned long tcrestart; unsigned long tcrestart; extern void r4k_wait_irqoff(void), __pastwait(void); extern void r4k_wait_irqoff(void), __pastwait(void); int set_resched_flag = (type == LINUX_SMP_IPI && action == SMP_RESCHEDULE_YOURSELF); if (cpu == smp_processor_id()) { if (cpu == smp_processor_id()) { printk("Cannot Send IPI to self!\n"); printk("Cannot Send IPI to self!\n"); return; return; } } if (set_resched_flag && IPIQ[cpu].resched_flag != 0) return; /* There is a reschedule queued already */ /* Set up a descriptor, to be delivered either promptly or queued */ /* Set up a descriptor, to be delivered either promptly or queued */ pipi = smtc_ipi_dq(&freeIPIq); pipi = smtc_ipi_dq(&freeIPIq); if (pipi == NULL) { if (pipi == NULL) { Loading @@ -801,6 +819,7 @@ void smtc_send_ipi(int cpu, int type, unsigned int action) pipi->dest = cpu; pipi->dest = cpu; if (cpu_data[cpu].vpe_id != cpu_data[smp_processor_id()].vpe_id) { if (cpu_data[cpu].vpe_id != cpu_data[smp_processor_id()].vpe_id) { /* If not on same VPE, enqueue and send cross-VPE interrupt */ /* If not on same VPE, enqueue and send cross-VPE interrupt */ IPIQ[cpu].resched_flag |= set_resched_flag; smtc_ipi_nq(&IPIQ[cpu], pipi); smtc_ipi_nq(&IPIQ[cpu], pipi); LOCK_CORE_PRA(); LOCK_CORE_PRA(); settc(cpu_data[cpu].tc_id); settc(cpu_data[cpu].tc_id); Loading Loading @@ -847,6 +866,7 @@ void smtc_send_ipi(int cpu, int type, unsigned int action) */ */ write_tc_c0_tchalt(0); write_tc_c0_tchalt(0); UNLOCK_CORE_PRA(); UNLOCK_CORE_PRA(); IPIQ[cpu].resched_flag |= set_resched_flag; smtc_ipi_nq(&IPIQ[cpu], pipi); smtc_ipi_nq(&IPIQ[cpu], pipi); } else { } else { postdirect: postdirect: Loading Loading @@ -996,12 +1016,15 @@ void deferred_smtc_ipi(void) * already enabled. * already enabled. */ */ local_irq_save(flags); local_irq_save(flags); spin_lock(&q->lock); spin_lock(&q->lock); pipi = __smtc_ipi_dq(q); pipi = __smtc_ipi_dq(q); spin_unlock(&q->lock); spin_unlock(&q->lock); if (pipi != NULL) if (pipi != NULL) { if (pipi->type == LINUX_SMP_IPI && (int)pipi->arg == SMP_RESCHEDULE_YOURSELF) IPIQ[cpu].resched_flag = 0; ipi_decode(pipi); ipi_decode(pipi); } /* /* * The use of the __raw_local restore isn't * The use of the __raw_local restore isn't * as obviously necessary here as in smtc_ipi_replay(), * as obviously necessary here as in smtc_ipi_replay(), Loading Loading @@ -1082,6 +1105,9 @@ static irqreturn_t ipi_interrupt(int irq, void *dev_idm) * with interrupts off * with interrupts off */ */ local_irq_save(flags); local_irq_save(flags); if (pipi->type == LINUX_SMP_IPI && (int)pipi->arg == SMP_RESCHEDULE_YOURSELF) IPIQ[cpu].resched_flag = 0; ipi_decode(pipi); ipi_decode(pipi); local_irq_restore(flags); local_irq_restore(flags); } } Loading Loading
arch/mips/include/asm/smtc_ipi.h +1 −0 Original line number Original line Diff line number Diff line Loading @@ -45,6 +45,7 @@ struct smtc_ipi_q { spinlock_t lock; spinlock_t lock; struct smtc_ipi *tail; struct smtc_ipi *tail; int depth; int depth; int resched_flag; /* reschedule already queued */ }; }; static inline void smtc_ipi_nq(struct smtc_ipi_q *q, struct smtc_ipi *p) static inline void smtc_ipi_nq(struct smtc_ipi_q *q, struct smtc_ipi *p) Loading
arch/mips/kernel/smtc.c +30 −4 Original line number Original line Diff line number Diff line Loading @@ -75,7 +75,6 @@ unsigned long irq_hwmask[NR_IRQS]; asiduse smtc_live_asid[MAX_SMTC_TLBS][MAX_SMTC_ASIDS]; asiduse smtc_live_asid[MAX_SMTC_TLBS][MAX_SMTC_ASIDS]; /* /* * Number of InterProcessor Interrupt (IPI) message buffers to allocate * Number of InterProcessor Interrupt (IPI) message buffers to allocate */ */ Loading Loading @@ -388,6 +387,7 @@ void smtc_prepare_cpus(int cpus) IPIQ[i].head = IPIQ[i].tail = NULL; IPIQ[i].head = IPIQ[i].tail = NULL; spin_lock_init(&IPIQ[i].lock); spin_lock_init(&IPIQ[i].lock); IPIQ[i].depth = 0; IPIQ[i].depth = 0; IPIQ[i].resched_flag = 0; /* No reschedules queued initially */ } } /* cpu_data index starts at zero */ /* cpu_data index starts at zero */ Loading Loading @@ -741,11 +741,24 @@ void smtc_forward_irq(unsigned int irq) static void smtc_ipi_qdump(void) static void smtc_ipi_qdump(void) { { int i; int i; struct smtc_ipi *temp; for (i = 0; i < NR_CPUS ;i++) { for (i = 0; i < NR_CPUS ;i++) { printk("IPIQ[%d]: head = 0x%x, tail = 0x%x, depth = %d\n", pr_info("IPIQ[%d]: head = 0x%x, tail = 0x%x, depth = %d\n", i, (unsigned)IPIQ[i].head, (unsigned)IPIQ[i].tail, i, (unsigned)IPIQ[i].head, (unsigned)IPIQ[i].tail, IPIQ[i].depth); IPIQ[i].depth); temp = IPIQ[i].head; while (temp != IPIQ[i].tail) { pr_debug("%d %d %d: ", temp->type, temp->dest, (int)temp->arg); #ifdef SMTC_IPI_DEBUG pr_debug("%u %lu\n", temp->sender, temp->stamp); #else pr_debug("\n"); #endif temp = temp->flink; } } } } } Loading Loading @@ -784,11 +797,16 @@ void smtc_send_ipi(int cpu, int type, unsigned int action) int mtflags; int mtflags; unsigned long tcrestart; unsigned long tcrestart; extern void r4k_wait_irqoff(void), __pastwait(void); extern void r4k_wait_irqoff(void), __pastwait(void); int set_resched_flag = (type == LINUX_SMP_IPI && action == SMP_RESCHEDULE_YOURSELF); if (cpu == smp_processor_id()) { if (cpu == smp_processor_id()) { printk("Cannot Send IPI to self!\n"); printk("Cannot Send IPI to self!\n"); return; return; } } if (set_resched_flag && IPIQ[cpu].resched_flag != 0) return; /* There is a reschedule queued already */ /* Set up a descriptor, to be delivered either promptly or queued */ /* Set up a descriptor, to be delivered either promptly or queued */ pipi = smtc_ipi_dq(&freeIPIq); pipi = smtc_ipi_dq(&freeIPIq); if (pipi == NULL) { if (pipi == NULL) { Loading @@ -801,6 +819,7 @@ void smtc_send_ipi(int cpu, int type, unsigned int action) pipi->dest = cpu; pipi->dest = cpu; if (cpu_data[cpu].vpe_id != cpu_data[smp_processor_id()].vpe_id) { if (cpu_data[cpu].vpe_id != cpu_data[smp_processor_id()].vpe_id) { /* If not on same VPE, enqueue and send cross-VPE interrupt */ /* If not on same VPE, enqueue and send cross-VPE interrupt */ IPIQ[cpu].resched_flag |= set_resched_flag; smtc_ipi_nq(&IPIQ[cpu], pipi); smtc_ipi_nq(&IPIQ[cpu], pipi); LOCK_CORE_PRA(); LOCK_CORE_PRA(); settc(cpu_data[cpu].tc_id); settc(cpu_data[cpu].tc_id); Loading Loading @@ -847,6 +866,7 @@ void smtc_send_ipi(int cpu, int type, unsigned int action) */ */ write_tc_c0_tchalt(0); write_tc_c0_tchalt(0); UNLOCK_CORE_PRA(); UNLOCK_CORE_PRA(); IPIQ[cpu].resched_flag |= set_resched_flag; smtc_ipi_nq(&IPIQ[cpu], pipi); smtc_ipi_nq(&IPIQ[cpu], pipi); } else { } else { postdirect: postdirect: Loading Loading @@ -996,12 +1016,15 @@ void deferred_smtc_ipi(void) * already enabled. * already enabled. */ */ local_irq_save(flags); local_irq_save(flags); spin_lock(&q->lock); spin_lock(&q->lock); pipi = __smtc_ipi_dq(q); pipi = __smtc_ipi_dq(q); spin_unlock(&q->lock); spin_unlock(&q->lock); if (pipi != NULL) if (pipi != NULL) { if (pipi->type == LINUX_SMP_IPI && (int)pipi->arg == SMP_RESCHEDULE_YOURSELF) IPIQ[cpu].resched_flag = 0; ipi_decode(pipi); ipi_decode(pipi); } /* /* * The use of the __raw_local restore isn't * The use of the __raw_local restore isn't * as obviously necessary here as in smtc_ipi_replay(), * as obviously necessary here as in smtc_ipi_replay(), Loading Loading @@ -1082,6 +1105,9 @@ static irqreturn_t ipi_interrupt(int irq, void *dev_idm) * with interrupts off * with interrupts off */ */ local_irq_save(flags); local_irq_save(flags); if (pipi->type == LINUX_SMP_IPI && (int)pipi->arg == SMP_RESCHEDULE_YOURSELF) IPIQ[cpu].resched_flag = 0; ipi_decode(pipi); ipi_decode(pipi); local_irq_restore(flags); local_irq_restore(flags); } } Loading