Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2e41f91d authored by Jaidev Patwardhan's avatar Jaidev Patwardhan Committed by Ralf Baechle
Browse files

MIPS: SMTC: Avoid queing multiple reschedule IPIs



Signed-off-by: default avatarChris Dearman <chris@mips.com>
Signed-off-by: default avatarRalf Baechle <ralf@linux-mips.org>
parent 05cf2079
Loading
Loading
Loading
Loading
+1 −0
Original line number Original line Diff line number Diff line
@@ -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)
+30 −4
Original line number Original line Diff line number Diff line
@@ -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);
			}
			}