aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/mips/include/asm/smtc_ipi.h1
-rw-r--r--arch/mips/kernel/smtc.c34
2 files changed, 31 insertions, 4 deletions
diff --git a/arch/mips/include/asm/smtc_ipi.h b/arch/mips/include/asm/smtc_ipi.h
index 8ce517574340..15278dbd7e79 100644
--- a/arch/mips/include/asm/smtc_ipi.h
+++ b/arch/mips/include/asm/smtc_ipi.h
@@ -45,6 +45,7 @@ struct smtc_ipi_q {
45 spinlock_t lock; 45 spinlock_t lock;
46 struct smtc_ipi *tail; 46 struct smtc_ipi *tail;
47 int depth; 47 int depth;
48 int resched_flag; /* reschedule already queued */
48}; 49};
49 50
50static inline void smtc_ipi_nq(struct smtc_ipi_q *q, struct smtc_ipi *p) 51static inline void smtc_ipi_nq(struct smtc_ipi_q *q, struct smtc_ipi *p)
diff --git a/arch/mips/kernel/smtc.c b/arch/mips/kernel/smtc.c
index 4d181df44a40..24630fd8ef60 100644
--- a/arch/mips/kernel/smtc.c
+++ b/arch/mips/kernel/smtc.c
@@ -75,7 +75,6 @@ unsigned long irq_hwmask[NR_IRQS];
75 75
76asiduse smtc_live_asid[MAX_SMTC_TLBS][MAX_SMTC_ASIDS]; 76asiduse smtc_live_asid[MAX_SMTC_TLBS][MAX_SMTC_ASIDS];
77 77
78
79/* 78/*
80 * Number of InterProcessor Interrupt (IPI) message buffers to allocate 79 * Number of InterProcessor Interrupt (IPI) message buffers to allocate
81 */ 80 */
@@ -388,6 +387,7 @@ void smtc_prepare_cpus(int cpus)
388 IPIQ[i].head = IPIQ[i].tail = NULL; 387 IPIQ[i].head = IPIQ[i].tail = NULL;
389 spin_lock_init(&IPIQ[i].lock); 388 spin_lock_init(&IPIQ[i].lock);
390 IPIQ[i].depth = 0; 389 IPIQ[i].depth = 0;
390 IPIQ[i].resched_flag = 0; /* No reschedules queued initially */
391 } 391 }
392 392
393 /* cpu_data index starts at zero */ 393 /* cpu_data index starts at zero */
@@ -741,11 +741,24 @@ void smtc_forward_irq(unsigned int irq)
741static void smtc_ipi_qdump(void) 741static void smtc_ipi_qdump(void)
742{ 742{
743 int i; 743 int i;
744 struct smtc_ipi *temp;
744 745
745 for (i = 0; i < NR_CPUS ;i++) { 746 for (i = 0; i < NR_CPUS ;i++) {
746 printk("IPIQ[%d]: head = 0x%x, tail = 0x%x, depth = %d\n", 747 pr_info("IPIQ[%d]: head = 0x%x, tail = 0x%x, depth = %d\n",
747 i, (unsigned)IPIQ[i].head, (unsigned)IPIQ[i].tail, 748 i, (unsigned)IPIQ[i].head, (unsigned)IPIQ[i].tail,
748 IPIQ[i].depth); 749 IPIQ[i].depth);
750 temp = IPIQ[i].head;
751
752 while (temp != IPIQ[i].tail) {
753 pr_debug("%d %d %d: ", temp->type, temp->dest,
754 (int)temp->arg);
755#ifdef SMTC_IPI_DEBUG
756 pr_debug("%u %lu\n", temp->sender, temp->stamp);
757#else
758 pr_debug("\n");
759#endif
760 temp = temp->flink;
761 }
749 } 762 }
750} 763}
751 764
@@ -784,11 +797,16 @@ void smtc_send_ipi(int cpu, int type, unsigned int action)
784 int mtflags; 797 int mtflags;
785 unsigned long tcrestart; 798 unsigned long tcrestart;
786 extern void r4k_wait_irqoff(void), __pastwait(void); 799 extern void r4k_wait_irqoff(void), __pastwait(void);
800 int set_resched_flag = (type == LINUX_SMP_IPI &&
801 action == SMP_RESCHEDULE_YOURSELF);
787 802
788 if (cpu == smp_processor_id()) { 803 if (cpu == smp_processor_id()) {
789 printk("Cannot Send IPI to self!\n"); 804 printk("Cannot Send IPI to self!\n");
790 return; 805 return;
791 } 806 }
807 if (set_resched_flag && IPIQ[cpu].resched_flag != 0)
808 return; /* There is a reschedule queued already */
809
792 /* Set up a descriptor, to be delivered either promptly or queued */ 810 /* Set up a descriptor, to be delivered either promptly or queued */
793 pipi = smtc_ipi_dq(&freeIPIq); 811 pipi = smtc_ipi_dq(&freeIPIq);
794 if (pipi == NULL) { 812 if (pipi == NULL) {
@@ -801,6 +819,7 @@ void smtc_send_ipi(int cpu, int type, unsigned int action)
801 pipi->dest = cpu; 819 pipi->dest = cpu;
802 if (cpu_data[cpu].vpe_id != cpu_data[smp_processor_id()].vpe_id) { 820 if (cpu_data[cpu].vpe_id != cpu_data[smp_processor_id()].vpe_id) {
803 /* If not on same VPE, enqueue and send cross-VPE interrupt */ 821 /* If not on same VPE, enqueue and send cross-VPE interrupt */
822 IPIQ[cpu].resched_flag |= set_resched_flag;
804 smtc_ipi_nq(&IPIQ[cpu], pipi); 823 smtc_ipi_nq(&IPIQ[cpu], pipi);
805 LOCK_CORE_PRA(); 824 LOCK_CORE_PRA();
806 settc(cpu_data[cpu].tc_id); 825 settc(cpu_data[cpu].tc_id);
@@ -847,6 +866,7 @@ void smtc_send_ipi(int cpu, int type, unsigned int action)
847 */ 866 */
848 write_tc_c0_tchalt(0); 867 write_tc_c0_tchalt(0);
849 UNLOCK_CORE_PRA(); 868 UNLOCK_CORE_PRA();
869 IPIQ[cpu].resched_flag |= set_resched_flag;
850 smtc_ipi_nq(&IPIQ[cpu], pipi); 870 smtc_ipi_nq(&IPIQ[cpu], pipi);
851 } else { 871 } else {
852postdirect: 872postdirect:
@@ -996,12 +1016,15 @@ void deferred_smtc_ipi(void)
996 * already enabled. 1016 * already enabled.
997 */ 1017 */
998 local_irq_save(flags); 1018 local_irq_save(flags);
999
1000 spin_lock(&q->lock); 1019 spin_lock(&q->lock);
1001 pipi = __smtc_ipi_dq(q); 1020 pipi = __smtc_ipi_dq(q);
1002 spin_unlock(&q->lock); 1021 spin_unlock(&q->lock);
1003 if (pipi != NULL) 1022 if (pipi != NULL) {
1023 if (pipi->type == LINUX_SMP_IPI &&
1024 (int)pipi->arg == SMP_RESCHEDULE_YOURSELF)
1025 IPIQ[cpu].resched_flag = 0;
1004 ipi_decode(pipi); 1026 ipi_decode(pipi);
1027 }
1005 /* 1028 /*
1006 * The use of the __raw_local restore isn't 1029 * The use of the __raw_local restore isn't
1007 * as obviously necessary here as in smtc_ipi_replay(), 1030 * as obviously necessary here as in smtc_ipi_replay(),
@@ -1082,6 +1105,9 @@ static irqreturn_t ipi_interrupt(int irq, void *dev_idm)
1082 * with interrupts off 1105 * with interrupts off
1083 */ 1106 */
1084 local_irq_save(flags); 1107 local_irq_save(flags);
1108 if (pipi->type == LINUX_SMP_IPI &&
1109 (int)pipi->arg == SMP_RESCHEDULE_YOURSELF)
1110 IPIQ[cpu].resched_flag = 0;
1085 ipi_decode(pipi); 1111 ipi_decode(pipi);
1086 local_irq_restore(flags); 1112 local_irq_restore(flags);
1087 } 1113 }