diff options
Diffstat (limited to 'include/linux/irq.h')
-rw-r--r-- | include/linux/irq.h | 40 |
1 files changed, 32 insertions, 8 deletions
diff --git a/include/linux/irq.h b/include/linux/irq.h index fff1d77c3753..4cb22259edd9 100644 --- a/include/linux/irq.h +++ b/include/linux/irq.h @@ -21,6 +21,7 @@ #include <linux/irqreturn.h> #include <linux/irqnr.h> #include <linux/errno.h> +#include <linux/timer.h> #include <linux/topology.h> #include <linux/wait.h> @@ -71,6 +72,8 @@ typedef void (*irq_flow_handler_t)(unsigned int irq, #define IRQ_SUSPENDED 0x04000000 /* IRQ has gone through suspend sequence */ #define IRQ_ONESHOT 0x08000000 /* IRQ is not unmasked after hardirq */ #define IRQ_NESTED_THREAD 0x10000000 /* IRQ is nested into another, no own handler thread */ +#define IRQ_IN_POLLING 0x20000000 /* IRQ polling in progress */ +#define IRQ_CHECK_WATCHES 0x40000000 /* IRQ watch enabled */ #ifdef CONFIG_IRQ_PER_CPU # define CHECK_IRQ_PER_CPU(var) ((var) & IRQ_PER_CPU) @@ -144,6 +147,17 @@ struct irq_chip { struct timer_rand_state; struct irq_2_iommu; + +/* spurious IRQ tracking and handling */ +struct irq_spr { + unsigned long last_bad; /* when was the last bad? */ + unsigned long period_start; /* period start jiffies */ + unsigned int nr_samples; /* nr of irqs in this period */ + unsigned int nr_bad; /* nr of bad deliveries */ + unsigned int poll_cnt; /* nr to poll once activated */ + unsigned int poll_rem; /* how many polls are left? */ +}; + /** * struct irq_desc - interrupt descriptor * @irq: interrupt number for this descriptor @@ -160,15 +174,14 @@ struct irq_2_iommu; * @status: status information * @depth: disable-depth, for nested irq_disable() calls * @wake_depth: enable depth, for multiple set_irq_wake() callers - * @irq_count: stats field to detect stalled irqs - * @last_unhandled: aging timer for unhandled count - * @irqs_unhandled: stats field for spurious unhandled interrupts * @lock: locking for SMP * @affinity: IRQ affinity on SMP * @node: node index useful for balancing * @pending_mask: pending rebalanced interrupts * @threads_active: number of irqaction threads currently running * @wait_for_threads: wait queue for sync_irq to wait for threaded handlers + * @spr: data for spurious IRQ handling + * @poll_timer: timer for IRQ polling * @dir: /proc/irq/ procfs entry * @name: flow handler name for /proc/interrupts output */ @@ -189,9 +202,6 @@ struct irq_desc { unsigned int depth; /* nested irq disables */ unsigned int wake_depth; /* nested wake enables */ - unsigned int irq_count; /* For detecting broken IRQs */ - unsigned long last_unhandled; /* Aging timer for unhandled count */ - unsigned int irqs_unhandled; raw_spinlock_t lock; #ifdef CONFIG_SMP cpumask_var_t affinity; @@ -203,6 +213,11 @@ struct irq_desc { #endif atomic_t threads_active; wait_queue_head_t wait_for_threads; + + struct irq_spr spr; + struct timer_list poll_timer; + bool poll_warned; + #ifdef CONFIG_PROC_FS struct proc_dir_entry *dir; #endif @@ -324,8 +339,17 @@ static inline void generic_handle_irq(unsigned int irq) } /* Handling of unhandled and spurious interrupts: */ -extern void note_interrupt(unsigned int irq, struct irq_desc *desc, - irqreturn_t action_ret); +extern void __note_interrupt(unsigned int irq, struct irq_desc *desc, + irqreturn_t action_ret); + +static inline void note_interrupt(unsigned int irq, struct irq_desc *desc, + irqreturn_t action_ret) +{ + extern int noirqdebug; + + if (!noirqdebug) + __note_interrupt(irq, desc, action_ret); +} /* Resending of interrupts :*/ void check_irq_resend(struct irq_desc *desc, unsigned int irq); |