forked from PeterCxy/android_kernel_oneplus_sm8150
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[PATCH] genirq: add genirq sw IRQ-retrigger
Enable platforms that do not have a hardware-assisted hardirq-resend mechanism to resend them via a softirq-driven IRQ emulation mechanism. Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Ingo Molnar <mingo@elte.hu> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
- Loading branch information
Showing
4 changed files
with
83 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,5 @@ | ||
|
||
obj-y := handle.o manage.o spurious.o | ||
obj-y := handle.o manage.o spurious.o resend.o | ||
obj-$(CONFIG_GENERIC_IRQ_PROBE) += autoprobe.o | ||
obj-$(CONFIG_PROC_FS) += proc.o | ||
obj-$(CONFIG_GENERIC_PENDING_IRQ) += migration.o |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
/* | ||
* linux/kernel/irq/resend.c | ||
* | ||
* Copyright (C) 1992, 1998-2006 Linus Torvalds, Ingo Molnar | ||
* Copyright (C) 2005-2006, Thomas Gleixner | ||
* | ||
* This file contains the IRQ-resend code | ||
* | ||
* If the interrupt is waiting to be processed, we try to re-run it. | ||
* We can't directly run it from here since the caller might be in an | ||
* interrupt-protected region. Not all irq controller chips can | ||
* retrigger interrupts at the hardware level, so in those cases | ||
* we allow the resending of IRQs via a tasklet. | ||
*/ | ||
|
||
#include <linux/irq.h> | ||
#include <linux/module.h> | ||
#include <linux/random.h> | ||
#include <linux/interrupt.h> | ||
|
||
#include "internals.h" | ||
|
||
#ifdef CONFIG_HARDIRQS_SW_RESEND | ||
|
||
/* Bitmap to handle software resend of interrupts: */ | ||
static DECLARE_BITMAP(irqs_resend, NR_IRQS); | ||
|
||
/* | ||
* Run software resends of IRQ's | ||
*/ | ||
static void resend_irqs(unsigned long arg) | ||
{ | ||
struct irq_desc *desc; | ||
int irq; | ||
|
||
while (!bitmap_empty(irqs_resend, NR_IRQS)) { | ||
irq = find_first_bit(irqs_resend, NR_IRQS); | ||
clear_bit(irq, irqs_resend); | ||
desc = irq_desc + irq; | ||
spin_lock_irqsave(&desc->lock, flags); | ||
desc->handle_irq(irq, desc, NULL); | ||
spin_unlock_irqrestore(&desc->lock, flags); | ||
} | ||
} | ||
|
||
/* Tasklet to handle resend: */ | ||
static DECLARE_TASKLET(resend_tasklet, resend_irqs, 0); | ||
|
||
#endif | ||
|
||
/* | ||
* IRQ resend | ||
* | ||
* Is called with interrupts disabled and desc->lock held. | ||
*/ | ||
void check_irq_resend(struct irq_desc *desc, unsigned int irq) | ||
{ | ||
unsigned int status = desc->status; | ||
|
||
/* | ||
* Make sure the interrupt is enabled, before resending it: | ||
*/ | ||
desc->chip->enable(irq); | ||
|
||
if ((status & (IRQ_PENDING | IRQ_REPLAY)) == IRQ_PENDING) { | ||
desc->status &= ~IRQ_PENDING; | ||
desc->status = status | IRQ_REPLAY; | ||
|
||
if (!desc->chip || !desc->chip->retrigger || | ||
!desc->chip->retrigger(irq)) { | ||
#ifdef CONFIG_HARDIRQS_SW_RESEND | ||
/* Set it pending and activate the softirq: */ | ||
set_bit(irq, irqs_resend); | ||
tasklet_schedule(&resend_tasklet); | ||
#endif | ||
} | ||
} | ||
} |