Commit 2e41f91d9e90e34254746fefcb7bb678a3c9d541
Committed by
Ralf Baechle
1 parent
05cf20790b
Exists in
master
and in
7 other branches
MIPS: SMTC: Avoid queing multiple reschedule IPIs
Signed-off-by: Chris Dearman <chris@mips.com> Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Showing 2 changed files with 31 additions and 4 deletions Side-by-side Diff
arch/mips/include/asm/smtc_ipi.h
arch/mips/kernel/smtc.c
... | ... | @@ -75,7 +75,6 @@ |
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 | */ |
... | ... | @@ -388,6 +387,7 @@ |
388 | 387 | IPIQ[i].head = IPIQ[i].tail = NULL; |
389 | 388 | spin_lock_init(&IPIQ[i].lock); |
390 | 389 | IPIQ[i].depth = 0; |
390 | + IPIQ[i].resched_flag = 0; /* No reschedules queued initially */ | |
391 | 391 | } |
392 | 392 | |
393 | 393 | /* cpu_data index starts at zero */ |
394 | 394 | |
395 | 395 | |
... | ... | @@ -741,11 +741,24 @@ |
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 | |
752 | 765 | |
... | ... | @@ -784,11 +797,16 @@ |
784 | 797 | int mtflags; |
785 | 798 | unsigned long tcrestart; |
786 | 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 | 803 | if (cpu == smp_processor_id()) { |
789 | 804 | printk("Cannot Send IPI to self!\n"); |
790 | 805 | return; |
791 | 806 | } |
807 | + if (set_resched_flag && IPIQ[cpu].resched_flag != 0) | |
808 | + return; /* There is a reschedule queued already */ | |
809 | + | |
792 | 810 | /* Set up a descriptor, to be delivered either promptly or queued */ |
793 | 811 | pipi = smtc_ipi_dq(&freeIPIq); |
794 | 812 | if (pipi == NULL) { |
... | ... | @@ -801,6 +819,7 @@ |
801 | 819 | pipi->dest = cpu; |
802 | 820 | if (cpu_data[cpu].vpe_id != cpu_data[smp_processor_id()].vpe_id) { |
803 | 821 | /* If not on same VPE, enqueue and send cross-VPE interrupt */ |
822 | + IPIQ[cpu].resched_flag |= set_resched_flag; | |
804 | 823 | smtc_ipi_nq(&IPIQ[cpu], pipi); |
805 | 824 | LOCK_CORE_PRA(); |
806 | 825 | settc(cpu_data[cpu].tc_id); |
... | ... | @@ -847,6 +866,7 @@ |
847 | 866 | */ |
848 | 867 | write_tc_c0_tchalt(0); |
849 | 868 | UNLOCK_CORE_PRA(); |
869 | + IPIQ[cpu].resched_flag |= set_resched_flag; | |
850 | 870 | smtc_ipi_nq(&IPIQ[cpu], pipi); |
851 | 871 | } else { |
852 | 872 | postdirect: |
853 | 873 | |
854 | 874 | |
... | ... | @@ -996,12 +1016,15 @@ |
996 | 1016 | * already enabled. |
997 | 1017 | */ |
998 | 1018 | local_irq_save(flags); |
999 | - | |
1000 | 1019 | spin_lock(&q->lock); |
1001 | 1020 | pipi = __smtc_ipi_dq(q); |
1002 | 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 | 1026 | ipi_decode(pipi); |
1027 | + } | |
1005 | 1028 | /* |
1006 | 1029 | * The use of the __raw_local restore isn't |
1007 | 1030 | * as obviously necessary here as in smtc_ipi_replay(), |
... | ... | @@ -1082,6 +1105,9 @@ |
1082 | 1105 | * with interrupts off |
1083 | 1106 | */ |
1084 | 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 | 1111 | ipi_decode(pipi); |
1086 | 1112 | local_irq_restore(flags); |
1087 | 1113 | } |