diff options
author | Hyungwoo Yang <hyungwoo.yang@intel.com> | 2019-04-15 22:17:11 -0700 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2019-04-26 04:19:18 -0700 |
commit | f730c0c1ab2cadb820676ef09ebb57888d48cb96 (patch) | |
tree | 8953f42e6776f828c0f55cc2c01d44c087a43511 /core/minute-ia/interrupts.c | |
parent | 6549da39d519b4d07e8bca7bef0393549765412b (diff) | |
download | chrome-ec-f730c0c1ab2cadb820676ef09ebb57888d48cb96.tar.gz |
ish: fix s/w generated interrupt request
Current s/w generated IRQ uses LAPIC's ICR but it causes pending
interrupts for other IRQs in IOAPIC and leads LVT error with
illegal vector. So instead of using ICR, we use "int" instruction.
BRANCH=none
BUG=b:129937881,b:124128140
TEST=Tested on Arcada platform
Change-Id: I49c4120e7355f9a98d20d5ed259c4fdf6bad5196
Signed-off-by: Hyungwoo Yang <hyungwoo.yang@intel.com>
Signed-off-by: Jett Rink <jettrink@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/1568786
Commit-Ready: Jack Rosenthal <jrosenth@chromium.org>
Reviewed-by: Jack Rosenthal <jrosenth@chromium.org>
Diffstat (limited to 'core/minute-ia/interrupts.c')
-rw-r--r-- | core/minute-ia/interrupts.c | 35 |
1 files changed, 34 insertions, 1 deletions
diff --git a/core/minute-ia/interrupts.c b/core/minute-ia/interrupts.c index 87926a9736..a08e02de90 100644 --- a/core/minute-ia/interrupts.c +++ b/core/minute-ia/interrupts.c @@ -349,6 +349,11 @@ __asm__ ( "movl %esp, %eax\n" "movl $stack_end, %esp\n" "push %eax\n" +#ifdef CONFIG_TASK_PROFILING + "push $" STRINGIFY(CONFIG_IRQ_COUNT) "\n" + "call task_start_irq_handler\n" + "addl $0x04, %esp\n" +#endif "call handle_lapic_lvt_error\n" "pop %esp\n" "movl $0x00, (0xFEE000B0)\n" /* Set EOI for LAPIC */ @@ -369,6 +374,30 @@ void unhandled_vector(void) /* This needs to be moved to link_defs.h */ extern const struct irq_data __irq_data[], __irq_data_end[]; +/** + * Called from SOFTIRQ_VECTOR when software is trigger an IRQ manually + * + * If IRQ is out of range, then no routine should be called + */ +void call_irq_service_routine(uint32_t irq) +{ + const struct irq_data *p = __irq_data; + + /* If just rescheduling a task, we won't have a routine to call */ + if (irq >= CONFIG_IRQ_COUNT) + return; + + for (; p < __irq_data_end; p++) { + if (p->irq == irq) { + p->routine(); + break; + } + } + + if (p == __irq_data_end) + CPRINTS("IRQ %d routine not found!", irq); +} + void init_interrupts(void) { unsigned entry; @@ -378,7 +407,11 @@ void init_interrupts(void) /* Setup gates for IRQs declared by drivers using DECLARE_IRQ */ for (; p < __irq_data_end; p++) - set_interrupt_gate(IRQ_TO_VEC(p->irq), p->routine, IDT_DESC_FLAGS); + set_interrupt_gate(IRQ_TO_VEC(p->irq), p->ioapic_routine, + IDT_DESC_FLAGS); + + /* Software generated IRQ */ + set_interrupt_gate(SOFTIRQ_VECTOR, sw_irq_handler, IDT_DESC_FLAGS); /* Setup gate for LAPIC_LVT_ERROR vector; clear any remnant error. */ REG32(LAPIC_ESR_REG) = 0; |