MIPS: Octeon: Do proper acknowledgment of CIU timer interrupts.
Signed-off-by: David 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: Ralf Baechle <ralf@linux-mips.org>
This commit is contained in:
parent
f8c2648666
commit
86568dc41e
1 changed files with 63 additions and 4 deletions
|
@ -51,9 +51,6 @@ static void octeon_irq_core_eoi(unsigned int irq)
|
||||||
*/
|
*/
|
||||||
if (desc->status & IRQ_DISABLED)
|
if (desc->status & IRQ_DISABLED)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* There is a race here. We should fix it. */
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We don't need to disable IRQs to make these atomic since
|
* We don't need to disable IRQs to make these atomic since
|
||||||
* they are already disabled earlier in the low level
|
* 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);
|
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}
|
* Enable the irq on the current core for chips that have the EN*_W1{S,C}
|
||||||
* registers.
|
* registers.
|
||||||
|
@ -304,6 +324,28 @@ static struct irq_chip octeon_irq_chip_ciu0 = {
|
||||||
#endif
|
#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)
|
static void octeon_irq_ciu1_ack(unsigned int irq)
|
||||||
{
|
{
|
||||||
|
@ -587,6 +629,7 @@ void __init arch_init_irq(void)
|
||||||
{
|
{
|
||||||
int irq;
|
int irq;
|
||||||
struct irq_chip *chip0;
|
struct irq_chip *chip0;
|
||||||
|
struct irq_chip *chip0_timer;
|
||||||
struct irq_chip *chip1;
|
struct irq_chip *chip1;
|
||||||
|
|
||||||
#ifdef CONFIG_SMP
|
#ifdef CONFIG_SMP
|
||||||
|
@ -602,9 +645,11 @@ void __init arch_init_irq(void)
|
||||||
OCTEON_IS_MODEL(OCTEON_CN56XX_PASS2_X) ||
|
OCTEON_IS_MODEL(OCTEON_CN56XX_PASS2_X) ||
|
||||||
OCTEON_IS_MODEL(OCTEON_CN52XX_PASS2_X)) {
|
OCTEON_IS_MODEL(OCTEON_CN52XX_PASS2_X)) {
|
||||||
chip0 = &octeon_irq_chip_ciu0_v2;
|
chip0 = &octeon_irq_chip_ciu0_v2;
|
||||||
|
chip0_timer = &octeon_irq_chip_ciu0_timer_v2;
|
||||||
chip1 = &octeon_irq_chip_ciu1_v2;
|
chip1 = &octeon_irq_chip_ciu1_v2;
|
||||||
} else {
|
} else {
|
||||||
chip0 = &octeon_irq_chip_ciu0;
|
chip0 = &octeon_irq_chip_ciu0;
|
||||||
|
chip0_timer = &octeon_irq_chip_ciu0_timer;
|
||||||
chip1 = &octeon_irq_chip_ciu1;
|
chip1 = &octeon_irq_chip_ciu1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -618,7 +663,21 @@ void __init arch_init_irq(void)
|
||||||
|
|
||||||
/* 24 - 87 CIU_INT_SUM0 */
|
/* 24 - 87 CIU_INT_SUM0 */
|
||||||
for (irq = OCTEON_IRQ_WORKQ0; irq <= OCTEON_IRQ_BOOTDMA; irq++) {
|
for (irq = OCTEON_IRQ_WORKQ0; irq <= OCTEON_IRQ_BOOTDMA; irq++) {
|
||||||
set_irq_chip_and_handler(irq, chip0, handle_percpu_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 */
|
/* 88 - 151 CIU_INT_SUM1 */
|
||||||
|
|
Reference in a new issue