Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

MIPS: SMTC: Avoid queing multiple reschedule IPIs

Signed-off-by: Chris Dearman <chris@mips.com>
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>

authored by

Jaidev Patwardhan and committed by
Ralf Baechle
2e41f91d 05cf2079

+31 -4
+1
arch/mips/include/asm/smtc_ipi.h
··· 45 45 spinlock_t lock; 46 46 struct smtc_ipi *tail; 47 47 int depth; 48 + int resched_flag; /* reschedule already queued */ 48 49 }; 49 50 50 51 static inline void smtc_ipi_nq(struct smtc_ipi_q *q, struct smtc_ipi *p)
+30 -4
arch/mips/kernel/smtc.c
··· 75 75 76 76 asiduse smtc_live_asid[MAX_SMTC_TLBS][MAX_SMTC_ASIDS]; 77 77 78 - 79 78 /* 80 79 * Number of InterProcessor Interrupt (IPI) message buffers to allocate 81 80 */ ··· 387 388 IPIQ[i].head = IPIQ[i].tail = NULL; 388 389 spin_lock_init(&IPIQ[i].lock); 389 390 IPIQ[i].depth = 0; 391 + IPIQ[i].resched_flag = 0; /* No reschedules queued initially */ 390 392 } 391 393 392 394 /* cpu_data index starts at zero */ ··· 741 741 static void smtc_ipi_qdump(void) 742 742 { 743 743 int i; 744 + struct smtc_ipi *temp; 744 745 745 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 748 i, (unsigned)IPIQ[i].head, (unsigned)IPIQ[i].tail, 748 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 ··· 797 784 int mtflags; 798 785 unsigned long tcrestart; 799 786 extern void r4k_wait_irqoff(void), __pastwait(void); 787 + int set_resched_flag = (type == LINUX_SMP_IPI && 788 + action == SMP_RESCHEDULE_YOURSELF); 800 789 801 790 if (cpu == smp_processor_id()) { 802 791 printk("Cannot Send IPI to self!\n"); 803 792 return; 804 793 } 794 + if (set_resched_flag && IPIQ[cpu].resched_flag != 0) 795 + return; /* There is a reschedule queued already */ 796 + 805 797 /* Set up a descriptor, to be delivered either promptly or queued */ 806 798 pipi = smtc_ipi_dq(&freeIPIq); 807 799 if (pipi == NULL) { ··· 819 801 pipi->dest = cpu; 820 802 if (cpu_data[cpu].vpe_id != cpu_data[smp_processor_id()].vpe_id) { 821 803 /* If not on same VPE, enqueue and send cross-VPE interrupt */ 804 + IPIQ[cpu].resched_flag |= set_resched_flag; 822 805 smtc_ipi_nq(&IPIQ[cpu], pipi); 823 806 LOCK_CORE_PRA(); 824 807 settc(cpu_data[cpu].tc_id); ··· 866 847 */ 867 848 write_tc_c0_tchalt(0); 868 849 UNLOCK_CORE_PRA(); 850 + IPIQ[cpu].resched_flag |= set_resched_flag; 869 851 smtc_ipi_nq(&IPIQ[cpu], pipi); 870 852 } else { 871 853 postdirect: ··· 1016 996 * already enabled. 1017 997 */ 1018 998 local_irq_save(flags); 1019 - 1020 999 spin_lock(&q->lock); 1021 1000 pipi = __smtc_ipi_dq(q); 1022 1001 spin_unlock(&q->lock); 1023 - if (pipi != NULL) 1002 + if (pipi != NULL) { 1003 + if (pipi->type == LINUX_SMP_IPI && 1004 + (int)pipi->arg == SMP_RESCHEDULE_YOURSELF) 1005 + IPIQ[cpu].resched_flag = 0; 1024 1006 ipi_decode(pipi); 1007 + } 1025 1008 /* 1026 1009 * The use of the __raw_local restore isn't 1027 1010 * as obviously necessary here as in smtc_ipi_replay(), ··· 1105 1082 * with interrupts off 1106 1083 */ 1107 1084 local_irq_save(flags); 1085 + if (pipi->type == LINUX_SMP_IPI && 1086 + (int)pipi->arg == SMP_RESCHEDULE_YOURSELF) 1087 + IPIQ[cpu].resched_flag = 0; 1108 1088 ipi_decode(pipi); 1109 1089 local_irq_restore(flags); 1110 1090 }