MIPS: SMTC: Avoid queing multiple reschedule IPIs

Signed-off-by: Chris Dearman <chris@mips.com>
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
This commit is contained in:
Jaidev Patwardhan 2009-07-10 02:06:00 -07:00 committed by Ralf Baechle
parent 05cf20790b
commit 2e41f91d9e
2 changed files with 31 additions and 4 deletions

View File

@ -45,6 +45,7 @@ struct smtc_ipi_q {
spinlock_t lock;
struct smtc_ipi *tail;
int depth;
int resched_flag; /* reschedule already queued */
};
static inline void smtc_ipi_nq(struct smtc_ipi_q *q, struct smtc_ipi *p)

View File

@ -75,7 +75,6 @@ unsigned long irq_hwmask[NR_IRQS];
asiduse smtc_live_asid[MAX_SMTC_TLBS][MAX_SMTC_ASIDS];
/*
* Number of InterProcessor Interrupt (IPI) message buffers to allocate
*/
@ -388,6 +387,7 @@ void smtc_prepare_cpus(int cpus)
IPIQ[i].head = IPIQ[i].tail = NULL;
spin_lock_init(&IPIQ[i].lock);
IPIQ[i].depth = 0;
IPIQ[i].resched_flag = 0; /* No reschedules queued initially */
}
/* cpu_data index starts at zero */
@ -741,11 +741,24 @@ void smtc_forward_irq(unsigned int irq)
static void smtc_ipi_qdump(void)
{
int i;
struct smtc_ipi *temp;
for (i = 0; i < NR_CPUS ;i++) {
printk("IPIQ[%d]: head = 0x%x, tail = 0x%x, depth = %d\n",
pr_info("IPIQ[%d]: head = 0x%x, tail = 0x%x, depth = %d\n",
i, (unsigned)IPIQ[i].head, (unsigned)IPIQ[i].tail,
IPIQ[i].depth);
temp = IPIQ[i].head;
while (temp != IPIQ[i].tail) {
pr_debug("%d %d %d: ", temp->type, temp->dest,
(int)temp->arg);
#ifdef SMTC_IPI_DEBUG
pr_debug("%u %lu\n", temp->sender, temp->stamp);
#else
pr_debug("\n");
#endif
temp = temp->flink;
}
}
}
@ -784,11 +797,16 @@ void smtc_send_ipi(int cpu, int type, unsigned int action)
int mtflags;
unsigned long tcrestart;
extern void r4k_wait_irqoff(void), __pastwait(void);
int set_resched_flag = (type == LINUX_SMP_IPI &&
action == SMP_RESCHEDULE_YOURSELF);
if (cpu == smp_processor_id()) {
printk("Cannot Send IPI to self!\n");
return;
}
if (set_resched_flag && IPIQ[cpu].resched_flag != 0)
return; /* There is a reschedule queued already */
/* Set up a descriptor, to be delivered either promptly or queued */
pipi = smtc_ipi_dq(&freeIPIq);
if (pipi == NULL) {
@ -801,6 +819,7 @@ void smtc_send_ipi(int cpu, int type, unsigned int action)
pipi->dest = cpu;
if (cpu_data[cpu].vpe_id != cpu_data[smp_processor_id()].vpe_id) {
/* If not on same VPE, enqueue and send cross-VPE interrupt */
IPIQ[cpu].resched_flag |= set_resched_flag;
smtc_ipi_nq(&IPIQ[cpu], pipi);
LOCK_CORE_PRA();
settc(cpu_data[cpu].tc_id);
@ -847,6 +866,7 @@ void smtc_send_ipi(int cpu, int type, unsigned int action)
*/
write_tc_c0_tchalt(0);
UNLOCK_CORE_PRA();
IPIQ[cpu].resched_flag |= set_resched_flag;
smtc_ipi_nq(&IPIQ[cpu], pipi);
} else {
postdirect:
@ -996,12 +1016,15 @@ void deferred_smtc_ipi(void)
* already enabled.
*/
local_irq_save(flags);
spin_lock(&q->lock);
pipi = __smtc_ipi_dq(q);
spin_unlock(&q->lock);
if (pipi != NULL)
if (pipi != NULL) {
if (pipi->type == LINUX_SMP_IPI &&
(int)pipi->arg == SMP_RESCHEDULE_YOURSELF)
IPIQ[cpu].resched_flag = 0;
ipi_decode(pipi);
}
/*
* The use of the __raw_local restore isn't
* as obviously necessary here as in smtc_ipi_replay(),
@ -1082,6 +1105,9 @@ static irqreturn_t ipi_interrupt(int irq, void *dev_idm)
* with interrupts off
*/
local_irq_save(flags);
if (pipi->type == LINUX_SMP_IPI &&
(int)pipi->arg == SMP_RESCHEDULE_YOURSELF)
IPIQ[cpu].resched_flag = 0;
ipi_decode(pipi);
local_irq_restore(flags);
}