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

Commit 86568dc4 authored by David Daney's avatar David Daney Committed by Ralf Baechle
Browse files

MIPS: Octeon: Do proper acknowledgment of CIU timer interrupts.



Signed-off-by: default avatarDavid Daney <ddaney@caviumnetworks.com>
To: linux-mips@linux-mips.org
To: netdev@vger.kernel.org
To: gregkh@suse.de
Patchwork: http://patchwork.linux-mips.org/patch/967/


Signed-off-by: default avatarRalf Baechle <ralf@linux-mips.org>
parent f8c26486
Loading
Loading
Loading
Loading
+63 −4
Original line number Diff line number Diff line
@@ -51,9 +51,6 @@ static void octeon_irq_core_eoi(unsigned int irq)
	 */
	if (desc->status & IRQ_DISABLED)
		return;

	/* There is a race here.  We should fix it.  */

	/*
	 * We don't need to disable IRQs to make these atomic since
	 * they are already disabled earlier in the low level
@@ -201,6 +198,29 @@ static void octeon_irq_ciu0_ack_v2(unsigned int irq)
	cvmx_write_csr(CVMX_CIU_INTX_EN0_W1C(index), mask);
}

/*
 * CIU timer type interrupts must be acknoleged by writing a '1' bit
 * to their sum0 bit.
 */
static void octeon_irq_ciu0_timer_ack(unsigned int irq)
{
	int index = cvmx_get_core_num() * 2;
	uint64_t mask = 1ull << (irq - OCTEON_IRQ_WORKQ0);
	cvmx_write_csr(CVMX_CIU_INTX_SUM0(index), mask);
}

static void octeon_irq_ciu0_timer_ack_v1(unsigned int irq)
{
	octeon_irq_ciu0_timer_ack(irq);
	octeon_irq_ciu0_ack(irq);
}

static void octeon_irq_ciu0_timer_ack_v2(unsigned int irq)
{
	octeon_irq_ciu0_timer_ack(irq);
	octeon_irq_ciu0_ack_v2(irq);
}

/*
 * Enable the irq on the current core for chips that have the EN*_W1{S,C}
 * registers.
@@ -304,6 +324,28 @@ static struct irq_chip octeon_irq_chip_ciu0 = {
#endif
};

static struct irq_chip octeon_irq_chip_ciu0_timer_v2 = {
	.name = "CIU0-T",
	.enable = octeon_irq_ciu0_enable_v2,
	.disable = octeon_irq_ciu0_disable_all_v2,
	.ack = octeon_irq_ciu0_timer_ack_v2,
	.eoi = octeon_irq_ciu0_eoi_v2,
#ifdef CONFIG_SMP
	.set_affinity = octeon_irq_ciu0_set_affinity_v2,
#endif
};

static struct irq_chip octeon_irq_chip_ciu0_timer = {
	.name = "CIU0-T",
	.enable = octeon_irq_ciu0_enable,
	.disable = octeon_irq_ciu0_disable,
	.ack = octeon_irq_ciu0_timer_ack_v1,
	.eoi = octeon_irq_ciu0_eoi,
#ifdef CONFIG_SMP
	.set_affinity = octeon_irq_ciu0_set_affinity,
#endif
};


static void octeon_irq_ciu1_ack(unsigned int irq)
{
@@ -587,6 +629,7 @@ void __init arch_init_irq(void)
{
	int irq;
	struct irq_chip *chip0;
	struct irq_chip *chip0_timer;
	struct irq_chip *chip1;

#ifdef CONFIG_SMP
@@ -602,9 +645,11 @@ void __init arch_init_irq(void)
	    OCTEON_IS_MODEL(OCTEON_CN56XX_PASS2_X) ||
	    OCTEON_IS_MODEL(OCTEON_CN52XX_PASS2_X)) {
		chip0 = &octeon_irq_chip_ciu0_v2;
		chip0_timer = &octeon_irq_chip_ciu0_timer_v2;
		chip1 = &octeon_irq_chip_ciu1_v2;
	} else {
		chip0 = &octeon_irq_chip_ciu0;
		chip0_timer = &octeon_irq_chip_ciu0_timer;
		chip1 = &octeon_irq_chip_ciu1;
	}

@@ -618,7 +663,21 @@ void __init arch_init_irq(void)

	/* 24 - 87 CIU_INT_SUM0 */
	for (irq = OCTEON_IRQ_WORKQ0; irq <= OCTEON_IRQ_BOOTDMA; irq++) {
		switch (irq) {
		case OCTEON_IRQ_GMX_DRP0:
		case OCTEON_IRQ_GMX_DRP1:
		case OCTEON_IRQ_IPD_DRP:
		case OCTEON_IRQ_KEY_ZERO:
		case OCTEON_IRQ_TIMER0:
		case OCTEON_IRQ_TIMER1:
		case OCTEON_IRQ_TIMER2:
		case OCTEON_IRQ_TIMER3:
			set_irq_chip_and_handler(irq, chip0_timer, handle_percpu_irq);
			break;
		default:
			set_irq_chip_and_handler(irq, chip0, handle_percpu_irq);
			break;
		}
	}

	/* 88 - 151 CIU_INT_SUM1 */