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:
committed by
Ralf Baechle
parent
05cf20790b
commit
2e41f91d9e
@@ -45,6 +45,7 @@ struct smtc_ipi_q {
|
|||||||
spinlock_t lock;
|
spinlock_t lock;
|
||||||
struct smtc_ipi *tail;
|
struct smtc_ipi *tail;
|
||||||
int depth;
|
int depth;
|
||||||
|
int resched_flag; /* reschedule already queued */
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline void smtc_ipi_nq(struct smtc_ipi_q *q, struct smtc_ipi *p)
|
static inline void smtc_ipi_nq(struct smtc_ipi_q *q, struct smtc_ipi *p)
|
||||||
|
@@ -75,7 +75,6 @@ unsigned long irq_hwmask[NR_IRQS];
|
|||||||
|
|
||||||
asiduse smtc_live_asid[MAX_SMTC_TLBS][MAX_SMTC_ASIDS];
|
asiduse smtc_live_asid[MAX_SMTC_TLBS][MAX_SMTC_ASIDS];
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Number of InterProcessor Interrupt (IPI) message buffers to allocate
|
* 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;
|
IPIQ[i].head = IPIQ[i].tail = NULL;
|
||||||
spin_lock_init(&IPIQ[i].lock);
|
spin_lock_init(&IPIQ[i].lock);
|
||||||
IPIQ[i].depth = 0;
|
IPIQ[i].depth = 0;
|
||||||
|
IPIQ[i].resched_flag = 0; /* No reschedules queued initially */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* cpu_data index starts at zero */
|
/* cpu_data index starts at zero */
|
||||||
@@ -741,11 +741,24 @@ void smtc_forward_irq(unsigned int irq)
|
|||||||
static void smtc_ipi_qdump(void)
|
static void smtc_ipi_qdump(void)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
struct smtc_ipi *temp;
|
||||||
|
|
||||||
for (i = 0; i < NR_CPUS ;i++) {
|
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,
|
i, (unsigned)IPIQ[i].head, (unsigned)IPIQ[i].tail,
|
||||||
IPIQ[i].depth);
|
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;
|
int mtflags;
|
||||||
unsigned long tcrestart;
|
unsigned long tcrestart;
|
||||||
extern void r4k_wait_irqoff(void), __pastwait(void);
|
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()) {
|
if (cpu == smp_processor_id()) {
|
||||||
printk("Cannot Send IPI to self!\n");
|
printk("Cannot Send IPI to self!\n");
|
||||||
return;
|
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 */
|
/* Set up a descriptor, to be delivered either promptly or queued */
|
||||||
pipi = smtc_ipi_dq(&freeIPIq);
|
pipi = smtc_ipi_dq(&freeIPIq);
|
||||||
if (pipi == NULL) {
|
if (pipi == NULL) {
|
||||||
@@ -801,6 +819,7 @@ void smtc_send_ipi(int cpu, int type, unsigned int action)
|
|||||||
pipi->dest = cpu;
|
pipi->dest = cpu;
|
||||||
if (cpu_data[cpu].vpe_id != cpu_data[smp_processor_id()].vpe_id) {
|
if (cpu_data[cpu].vpe_id != cpu_data[smp_processor_id()].vpe_id) {
|
||||||
/* If not on same VPE, enqueue and send cross-VPE interrupt */
|
/* If not on same VPE, enqueue and send cross-VPE interrupt */
|
||||||
|
IPIQ[cpu].resched_flag |= set_resched_flag;
|
||||||
smtc_ipi_nq(&IPIQ[cpu], pipi);
|
smtc_ipi_nq(&IPIQ[cpu], pipi);
|
||||||
LOCK_CORE_PRA();
|
LOCK_CORE_PRA();
|
||||||
settc(cpu_data[cpu].tc_id);
|
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);
|
write_tc_c0_tchalt(0);
|
||||||
UNLOCK_CORE_PRA();
|
UNLOCK_CORE_PRA();
|
||||||
|
IPIQ[cpu].resched_flag |= set_resched_flag;
|
||||||
smtc_ipi_nq(&IPIQ[cpu], pipi);
|
smtc_ipi_nq(&IPIQ[cpu], pipi);
|
||||||
} else {
|
} else {
|
||||||
postdirect:
|
postdirect:
|
||||||
@@ -996,12 +1016,15 @@ void deferred_smtc_ipi(void)
|
|||||||
* already enabled.
|
* already enabled.
|
||||||
*/
|
*/
|
||||||
local_irq_save(flags);
|
local_irq_save(flags);
|
||||||
|
|
||||||
spin_lock(&q->lock);
|
spin_lock(&q->lock);
|
||||||
pipi = __smtc_ipi_dq(q);
|
pipi = __smtc_ipi_dq(q);
|
||||||
spin_unlock(&q->lock);
|
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);
|
ipi_decode(pipi);
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
* The use of the __raw_local restore isn't
|
* The use of the __raw_local restore isn't
|
||||||
* as obviously necessary here as in smtc_ipi_replay(),
|
* 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
|
* with interrupts off
|
||||||
*/
|
*/
|
||||||
local_irq_save(flags);
|
local_irq_save(flags);
|
||||||
|
if (pipi->type == LINUX_SMP_IPI &&
|
||||||
|
(int)pipi->arg == SMP_RESCHEDULE_YOURSELF)
|
||||||
|
IPIQ[cpu].resched_flag = 0;
|
||||||
ipi_decode(pipi);
|
ipi_decode(pipi);
|
||||||
local_irq_restore(flags);
|
local_irq_restore(flags);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user