diff options
Diffstat (limited to 'arch/mips')
-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 | } |