diff options
| author | Jaidev Patwardhan <jaidev@mips.com> | 2009-07-10 05:06:00 -0400 |
|---|---|---|
| committer | Ralf Baechle <ralf@linux-mips.org> | 2009-11-02 06:00:06 -0500 |
| commit | 2e41f91d9e90e34254746fefcb7bb678a3c9d541 (patch) | |
| tree | 2e2484f0c4fb0b309d1c6fd289f2b2ab11b88c40 | |
| parent | 05cf20790b3b3ed81cb001e8f41e473247f28302 (diff) | |
MIPS: SMTC: Avoid queing multiple reschedule IPIs
Signed-off-by: Chris Dearman <chris@mips.com>
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
| -rw-r--r-- | arch/mips/include/asm/smtc_ipi.h | 1 | ||||
| -rw-r--r-- | arch/mips/kernel/smtc.c | 34 |
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 | ||
| 50 | static inline void smtc_ipi_nq(struct smtc_ipi_q *q, struct smtc_ipi *p) | 51 | static 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 | ||
| 76 | asiduse smtc_live_asid[MAX_SMTC_TLBS][MAX_SMTC_ASIDS]; | 76 | asiduse 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) | |||
| 741 | static void smtc_ipi_qdump(void) | 741 | static 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 { |
| 852 | postdirect: | 872 | postdirect: |
| @@ -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 | } |
