genirq: Overhaul for 2.6.39
Subsystems (10)
cover genirq: Overhaul for 2.6.39
This is a major overhaul of the generic interrupt layer.
- Namespace cleanup
- Further encapsulation of the core state
- Spurious/Poll handling fixes
- Stop setaffinity blindly manipulating affinity mask
- Cleanups and enhancements all over the place
1) Namespace cleanup
I reworked the slightly confusing (sorry, my bad) namespace of the various accessor functions. They follow a simple scheme now:
irq_set/get_xxx(unsigned int irq, ...)
irq_data_set/get_xxx(struct irq_data *d, ...)
That's the first patch in the series and I'm going to apply it to a separate rc-4 based branch which everybody can pull in to do the changes now in his tree.
2) Encapsulation
After __do_IRQ() was finally gone (Thanks to all involved!) I wanted to restructure the core status handling and cleanup the IRQ_* flag space.
A quick grep over the tree made me really shudder, so I converted 13 archs which are known to follow core changes slow to the new irq_chip callback functions and cleaned up the irq_desc accessors while at it. That way I learned also a lot about arch requirements.
Then I looked at the remaining places which deal with irq_desc->status directly.
1) Special EOI handling in sparc64/mips/sh. Easy to replace.
2) Random abusers of chained_interrupt_handler. The worst offender is arch/powerpc/sysdev/fsl_msi.c, which implements a combo eoi/level flow handler instead of using the existing ones.
3) Random places which quirk around their chip oddities instead of looking for solutions which can be made generic. One of them is the requirement to mask irq chips before setting the trigger type. Why is nobody talking to me ?
4) Random leftovers from the __do_IRQ() semantics which are easy to cleanup.
5) Initializations with IRQ_DISABLED and random IRQ_ flags. IRQ_DISABLED is core internal state and already set by default. The settable flags have to use the provided modifier functions.
6) Weird flow handlers in m68knommu/arm/powerpc. All of them can be either replaced by existing handlers or can use an existing handler with minimal modifications. Patches are already out.
7) Totally broken debug code in gpiolib and a copy of the same in some arm Soc code. Patch is in this series to kill it. Also remove unused code in arm/mach-tegra which seems to be some relict from the android mess.
So there is no real requirement to expose the guts of the generic irq code to the world.
Even if all is cleaned up, I'm tired of:
- Having to chase the creative abusage all the time
- People not talking to me about their special requirements
- Spending another day to find out that someone had typoed desc->status |= IRQ_LEVEL; into desc->status = IRQ_LEVEL; in some weird arch code and then complaining about the core code playing silly buggers.
So I decided to encapsulate the state into the core and make it hard to access and offenders easy to find. For now I keep the existing and used IRQ_* status bits up to date, unless GENERIC_HARDIRQS_NO_COMPAT=y which can be selected by the architecture. Be aware that not setting that config adds extra overhead to the core code.
For all real requirements which I found, I provided solutions either in the core itself or information accessible via a state field in irq_data, which is handed to the irq_chip functions. So setting GENERIC_HARDIRQS_NO_COMPAT=y should be not a big deal on most architectures. There are some gpio and mfd drivers which need to be converted to threaded interrupts instead of having the old style racy and ugly disable_irq_nosync/schedule_work() implementation.
There are a few places which need some thought like the powerpc kexec shutdown, but even that stuff should be generic as it makes sense to cleanup irqs before booting into a new kernel. Nothing which can't be solved though.
Note that most accessors to irq_desc are going away sooner than later and long term I want to remove irq_desc from the public space completely.
One step to this is a generic show_interrupts() function, which replaces the 23 copies with random modifications and different bugs inside. Unless you switch over you will be reminded by a nice deprecated warning.
3) Spurious/Poll
This is a long neglected piece of code and got an overhaul so it's simpler and less broken than it used to be.
4) irq_setaffinity()
Does not longer blindly update the affinity mask before calling into the arch code. Also the chip functions can now return a return code, which tells the core that it modified the mask itself. That's useful when arch code restricts the mask further than the core code can do.
5) Cleanups and enhancements
Main cleanup happened in poll and the consolidation of the flow handlers which moved their duplicated code into handle_irq_event
irq_set_type() now checks chip.flags for a chip flag, which indicates that the chip needs to be masked before setting the trigger type. That avoids duplicated code and fiddling with internal core state.
If no major outcry comes I'm going to push this into tip/irq/core and next.
A preview is available at:
git://git.kernel.org/pub/scm/linux/kernel/git/tglx/linux-2.6-genirq.git irq/core
Thanks,
tglx
PATCH 1/75 genirq: Namespace cleanup
The irq namespace has become quite convoluted. My bad. Clean it up and deprecate the old functions. All new functions follow the scheme:
irq number based:
irq_set/get/xxx/_xxx(unsigned int irq, ...)
irq_data based:
irq_data_set/get/xxx/_xxx(struct irq_data *d, ....)
irq_desc based:
irq_desc_get_xxx(struct irq_desc *desc)
--- include/linux/irq.h | 72 +++++++++++++++++++++++++++++++++++++++++------- include/linux/irqdesc.h | 44 ++++++++++++++++++++++++++--- kernel/irq/chip.c | 28 +++++++++--------- 3 files changed, 116 insertions(+), 28 deletions(-)
include/linux/irq.h +62 -10
@@ -351,52 +351,104 @@ static inline void dynamic_irq_init(unsi }/* Set/get chip/data for an IRQ: */ -extern int set_irq_chip (unsigned int irq,struct irq_chip *chip); -extern int set_irq_data (unsigned int irq,void *data); -extern int set_irq_chip_data (unsigned int irq,void *data); -extern int set_irq_type (unsigned int irq,unsigned int type); -extern int set_irq_msi (unsigned int irq,struct msi_desc *entry); +extern int irq_set_chip (unsigned int irq,struct irq_chip *chip); +extern int irq_set_handler_data (unsigned int irq,void *data); +extern int irq_set_chip_data (unsigned int irq,void *data); +extern int irq_set_irq_type (unsigned int irq,unsigned int type); +extern int irq_set_msi_desc (unsigned int irq,struct msi_desc *entry);extern struct irq_data *irq_get_irq_data (unsigned int irq); -static inline struct irq_chip *get_irq_chip (unsigned int irq) +static inline int __deprecated set_irq_chip (unsigned int irq, +struct irq_chip *chip) +{ +return irq_set_chip (irq, chip); +} + +static inline int __deprecated set_irq_data (unsigned int irq,void *data) +{ +return irq_set_handler_data (irq, data); +} + +static inline int __deprecated set_irq_chip_data (unsigned int irq,void *data) +{ +return irq_set_chip_data (irq, data); +} + +static inline int __deprecated set_irq_type (unsigned int irq,unsigned int type) +{ +return irq_set_irq_type (irq, type); +} + +static inline int __deprecated set_irq_msi (unsigned int irq, +struct msi_desc *entry) +{ +return irq_set_msi_desc (irq, entry); +} + +static inline struct irq_chip *irq_get_chip (unsigned int irq) {struct irq_data *d =irq_get_irq_data (irq);return d ? d->chip :NULL ; } +static inline __deprecated struct irq_chip *get_irq_chip (unsigned int irq) +{ +return irq_get_chip (irq); +} +static inline struct irq_chip *irq_data_get_irq_chip (struct irq_data *d) {return d->chip; } -static inline void *get_irq_chip_data (unsigned int irq) +static inline void *irq_get_chip_data (unsigned int irq) {struct irq_data *d =irq_get_irq_data (irq);return d ? d->chip_data :NULL ; } +static inline __deprecated void *get_irq_chip_data (unsigned int irq) +{ +return irq_get_chip_data (irq); +} +static inline void *irq_data_get_irq_chip_data (struct irq_data *d) {return d->chip_data; } -static inline void *get_irq_data (unsigned int irq) +static inline void *irq_get_handler_data (unsigned int irq) {struct irq_data *d =irq_get_irq_data (irq);return d ? d->handler_data :NULL ; } -static inline void *irq_data_get_irq_data (struct irq_data *d) +static inline __deprecated void *get_irq_data (unsigned int irq) +{ +return irq_get_handler_data (irq); +} + +static inline void *irq_data_get_irq_handler_data (struct irq_data *d) {return d->handler_data; } -static inline struct msi_desc *get_irq_msi (unsigned int irq) +static inline __deprecated void *irq_data_get_irq_data (struct irq_data *d) +{ +return irq_data_get_irq_handler_data (d); +} + +static inline struct msi_desc *irq_get_msi_desc (unsigned int irq) {struct irq_data *d =irq_get_irq_data (irq);return d ? d->msi_desc :NULL ; } +static inline __deprecated struct msi_desc *get_irq_msi (unsigned int irq) +{ +return irq_get_msi_desc (irq); +} +static inline struct msi_desc *irq_data_get_msi (struct irq_data *d) {return d->msi_desc;
include/linux/irqdesc.h +40 -4
50 lines not on this page · raw message
kernel/irq/chip.c +14 -14
@@ -19,11 +19,11 @@#include "internals.h" /** -* set_irq_chip - set the irq chip for an irq +* irq_set_chip - set the irq chip for an irq * @irq: irq number * @chip: pointer to irq chip description structure */ -int set_irq_chip (unsigned int irq,struct irq_chip *chip) +int irq_set_chip (unsigned int irq,struct irq_chip *chip) {struct irq_desc *desc =irq_to_desc (irq);unsigned long flags;
@@ -43,14 +43,14 @@ int set_irq_chip(unsigned int irq, strucreturn 0 ; } -EXPORT_SYMBOL (set_irq_chip); +EXPORT_SYMBOL (irq_set_chip);/** -* set_irq_type - set the irq trigger type for an irq +* irq_set_type - set the irq trigger type for an irq * @irq: irq number * @type: IRQ_TYPE_{LEVEL,EDGE}_* value - see include/linux/irq.h */ -int set_irq_type (unsigned int irq,unsigned int type) +int irq_set_type (unsigned int irq,unsigned int type) {struct irq_desc *desc =irq_to_desc (irq);unsigned long flags;
@@ -70,16 +70,16 @@ int set_irq_type(unsigned int irq, unsigraw_spin_unlock_irqrestore (&desc->lock, flags);return ret; } -EXPORT_SYMBOL (set_irq_type); +EXPORT_SYMBOL (irq_set_type);/** -* set_irq_data - set irq type data for an irq +* irq_set_handler_data - set irq handler data for an irq * @irq: Interrupt number * @data: Pointer to interrupt specific data * * Set the hardware irq controller data for an irq */ -int set_irq_data (unsigned int irq,void *data) +int irq_set_handler_data (unsigned int irq,void *data) {struct irq_desc *desc =irq_to_desc (irq);unsigned long flags;
@@ -95,16 +95,16 @@ int set_irq_data(unsigned int irq, voidraw_spin_unlock_irqrestore (&desc->lock, flags);return 0 ; } -EXPORT_SYMBOL (set_irq_data); +EXPORT_SYMBOL (irq_set_handler_data);/** -* set_irq_msi - set MSI descriptor data for an irq +* irq_set_msi_desc - set MSI descriptor data for an irq * @irq: Interrupt number * @entry: Pointer to MSI descriptor data * * Set the MSI descriptor entry for an irq */ -int set_irq_msi (unsigned int irq,struct msi_desc *entry) +int irq_set_msi_desc (unsigned int irq,struct msi_desc *entry) {struct irq_desc *desc =irq_to_desc (irq);unsigned long flags;
@@ -124,13 +124,13 @@ int set_irq_msi(unsigned int irq, struct }/** -* set_irq_chip_data - set irq chip data for an irq +* irq_set_chip_data - set irq chip data for an irq * @irq: Interrupt number * @data: Pointer to chip specific data * * Set the hardware irq chip data for an irq */ -int set_irq_chip_data (unsigned int irq,void *data) +int irq_set_chip_data (unsigned int irq,void *data) {struct irq_desc *desc =irq_to_desc (irq);unsigned long flags;
@@ -152,7 +152,7 @@ int set_irq_chip_data(unsigned int irq,return 0 ; } -EXPORT_SYMBOL (set_irq_chip_data); +EXPORT_SYMBOL (irq_set_chip_data);struct irq_data *irq_get_irq_data (unsigned int irq) {
PATCH 2/75 genirq: Simplify affinity related code
In reply to Thomas GleixnerThere is lot of #ifdef CONFIG_GENERIC_PENDING_IRQ along with duplicated code in the irq core. Move the #ifdeffery into one place and cleanup the code so it's readable. No functional change.
--- kernel/irq/manage.c | 64 +++++++++++++++++++++++++++++++++------------------- 1 file changed, 41 insertions(+), 23 deletions(-)
kernel/irq/manage.c +41 -23
@@ -100,47 +100,70 @@ void irq_set_thread_affinity(struct irq_ } } +#ifdef CONFIG_GENERIC_PENDING_IRQ +static inline bool irq_can_move_pcntxt (struct irq_desc *desc) +{ +return desc->status &IRQ_MOVE_PCNTXT ; +} +static inline bool irq_move_pending (struct irq_desc *desc) +{ +return desc->status &IRQ_MOVE_PENDING ; +} +static inline void +irq_copy_pending (struct irq_desc *desc,const struct cpumask *mask) +{ +cpumask_copy (desc->pending_mask, mask); +} +static inline void +irq_get_pending (struct cpumask *mask,struct irq_desc *desc) +{ +cpumask_copy (mask, desc->pending_mask); +} +#else +static inline bool irq_can_move_pcntxt (struct irq_desc *desc) {return true; } +static inline bool irq_move_pending (struct irq_desc *desc) {return false; } +static inline void +irq_copy_pending (struct irq_desc *desc,const struct cpumask *mask) { } +static inline void +irq_get_pending (struct cpumask *mask,struct irq_desc *desc) { } +#endif +/** * irq_set_affinity - Set the irq affinity of a given irq * @irq: Interrupt to set affinity * @cpumask: cpumask * */ -int irq_set_affinity (unsigned int irq,const struct cpumask *cpumask) +int irq_set_affinity (unsigned int irq,const struct cpumask *mask) {struct irq_desc *desc =irq_to_desc (irq);struct irq_chip *chip = desc->irq_data.chip;unsigned long flags; +int ret =0 ;if (!chip->irq_set_affinity)return -EINVAL ;raw_spin_lock_irqsave (&desc->lock, flags); -#ifdef CONFIG_GENERIC_PENDING_IRQ -if (desc->status &IRQ_MOVE_PCNTXT ) { -if (!chip->irq_set_affinity (&desc->irq_data, cpumask, false)) { -cpumask_copy (desc->irq_data.affinity, cpumask); +if (irq_can_move_pcntxt (desc)) { + ret = chip->irq_set_affinity (&desc->irq_data, mask, false); +if (!ret) { +cpumask_copy (desc->irq_data.affinity, mask);irq_set_thread_affinity (desc); } - } -else { + }else { desc->status |=IRQ_MOVE_PENDING ; -cpumask_copy (desc->pending_mask, cpumask); +irq_copy_pending (desc, mask); } -#else -if (!chip->irq_set_affinity (&desc->irq_data, cpumask, false)) { -cpumask_copy (desc->irq_data.affinity, cpumask); -irq_set_thread_affinity (desc); - } -#endif +if (desc->affinity_notify) {kref_get (&desc->affinity_notify->kref);schedule_work (&desc->affinity_notify->work); } desc->status |=IRQ_AFFINITY_SET ;raw_spin_unlock_irqrestore (&desc->lock, flags); -return 0 ; +return ret; }int irq_set_affinity_hint (unsigned int irq,const struct cpumask *m)
@@ -167,18 +190,13 @@ static void irq_affinity_notify(struct wcpumask_var_t cpumask;unsigned long flags; -if (!desc) - goto out; - -if (!alloc_cpumask_var (&cpumask,GFP_KERNEL )) +if (!desc || !alloc_cpumask_var (&cpumask,GFP_KERNEL )) goto out;raw_spin_lock_irqsave (&desc->lock, flags); -#ifdef CONFIG_GENERIC_PENDING_IRQ -if (desc->status &IRQ_MOVE_PENDING ) -cpumask_copy (cpumask, desc->pending_mask); +if (irq_move_pending (desc)) +irq_get_pending (cpumask, desc);else -#endif cpumask_copy (cpumask, desc->irq_data.affinity);raw_spin_unlock_irqrestore (&desc->lock, flags);
PATCH 3/75 genirq: Rremove redundant check
In reply to Thomas GleixnerIRQ_NO_BALANCING is already checked in irq_can_set_affinity() above, no need to check it again.
--- kernel/irq/manage.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
kernel/irq/manage.c +2 -1
@@ -256,6 +256,7 @@ EXPORT_SYMBOL_GPL(irq_set_affinity_notif*/ static int setup_affinity (unsigned int irq,struct irq_desc *desc) { +/* Excludes PER_CPU and NO_BALANCE interrupts */ if (!irq_can_set_affinity (irq))return 0 ;
@@ -263,7 +264,7 @@ static int setup_affinity(unsigned int i* Preserve an userspace affinity setup, but make sure that * one of the targets is online. */ -if (desc->status & (IRQ_AFFINITY_SET |IRQ_NO_BALANCING )) { +if (desc->status & (IRQ_AFFINITY_SET )) {if (cpumask_any_and (desc->irq_data.affinity, cpu_online_mask) < nr_cpu_ids) goto set_affinity;
PATCH 4/75 genirq: Always apply cpu online mask
In reply to Thomas GleixnerIf the affinity had been set by the user, then a later request_irq() will honour that setting. But online cpus can have changed. So apply the online mask and for this case as well.
--- kernel/irq/manage.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-)
kernel/irq/manage.c +6 -6
@@ -256,6 +256,8 @@ EXPORT_SYMBOL_GPL(irq_set_affinity_notif*/ static int setup_affinity (unsigned int irq,struct irq_desc *desc) { +struct cpumask *set = irq_default_affinity; +/* Excludes PER_CPU and NO_BALANCE interrupts */ if (!irq_can_set_affinity (irq))return 0 ;
@@ -265,15 +267,13 @@ static int setup_affinity(unsigned int i* one of the targets is online. */ if (desc->status & (IRQ_AFFINITY_SET )) { -if (cpumask_any_and (desc->irq_data.affinity, cpu_online_mask) - < nr_cpu_ids) - goto set_affinity; +if (cpumask_intersects (desc->irq_data.affinity, + cpu_online_mask)) + set = desc->irq_data.affinity;else desc->status &= ~IRQ_AFFINITY_SET ; } - -cpumask_and (desc->irq_data.affinity, cpu_online_mask, irq_default_affinity); -set_affinity: +cpumask_and (desc->irq_data.affinity, cpu_online_mask, set); desc->irq_data.chip->irq_set_affinity (&desc->irq_data, desc->irq_data.affinity, false);return 0 ;
PATCH 5/75 genirq: Do not copy affinity before set
In reply to Thomas GleixnerWhile rumaging through arch code I found that there are a few workarounds which deal with the fact that the initial affinity setting from request_irq() copies the mask into irq_data->affinity before the chip code is called. In the normal path we unconditionally copy the mask when the chip code returns 0.
Copy after the code is called and add a return code IRQ_SET_MASK_OK_NOCOPY for the chip functions, which prevents the copy. That way we see the real mask when the chip function decided to truncate it further as some arches do. IRQ_SET_MASK_OK is 0, which is the current behaviour.
--- include/linux/irq.h | 11 +++++++++++ kernel/irq/manage.c | 49 ++++++++++++++++++++++++++++++++++++++----------- 2 files changed, 49 insertions(+), 11 deletions(-)
include/linux/irq.h +11 -0
@@ -85,6 +85,17 @@ typedef void (*irq_flow_handler_t)(unsig# define IRQ_NO_BALANCING_MASK IRQ_NO_BALANCING#endif +/* +* Return value for chip->irq_set_affinity() +* +* IRQ_SET_MASK_OK - OK, core updates irq_data.affinity +* IRQ_SET_MASK_NOCPY - OK, chip did update irq_data.affinity +*/ +enum { +IRQ_SET_MASK_OK =0 , +IRQ_SET_MASK_OK_NOCOPY , +}; +struct msi_desc ;/**
kernel/irq/manage.c +38 -11
122 lines not on this page · raw message
PATCH 6/75 genirq: Plug race in report_bad_irq()
In reply to Thomas GleixnerWe cannot walk the action chain unlocked. Even if IRQ_INPROGRESS is set an action can be removed and we follow a null pointer. It's safe to take the lock there, because the code which removes the action will call synchronize_irq() which waits unlocked for IRQ_INPROGRESS going away.
--- kernel/irq/spurious.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-)
kernel/irq/spurious.c +9 -3
@@ -139,15 +139,13 @@ static void poll_spurious_irqs(unsigned* * (The other 100-of-100,000 interrupts may have been a correctly * functioning device sharing an IRQ with the failing one) -* -* Called under desc->lock */ -static void __report_bad_irq (unsigned int irq,struct irq_desc *desc,irqreturn_t action_ret) {struct irqaction *action; +unsigned long flags;if (action_ret !=IRQ_HANDLED && action_ret !=IRQ_NONE ) { printk(KERN_ERR "irq event %d: bogus return value %x\n",
@@ -159,6 +157,13 @@ __report_bad_irq(unsigned int irq, strucdump_stack ();printk (KERN_ERR "handlers:\n" ); +/* +* We need to take desc->lock here. note_interrupt() is called +* w/o desc->lock held, but IRQ_PROGRESS set. We might race +* with something else removing an action. It's ok to take +* desc->lock here. See synchronize_irq(). +*/ +raw_spin_lock_irqsave (&desc->lock, flags); action = desc->action;while (action) {printk (KERN_ERR "[<%p>]" , action->handler);
@@ -167,6 +172,7 @@ __report_bad_irq(unsigned int irq, strucprintk ("\n" ); action = action->next; } +raw_spin_unlock_irqrestore (&desc->lock, flags); } static void
PATCH 7/75 genirq: Warn when handler enables interrupts
In reply to Thomas GleixnerWe run all handlers with interrupts disabled and expect them not to enable them. Warn when we catch one who does.
--- kernel/irq/handle.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
kernel/irq/handle.c +3 -1
@@ -68,6 +68,9 @@ irqreturn_t handle_IRQ_event(unsigned in ret = action->handler (irq, action->dev_id);trace_irq_handler_exit (irq, action, ret); +if (WARN_ON_ONCE (!irqs_disabled ())) +local_irq_disable (); +switch (ret) {case IRQ_WAKE_THREAD :/*
@@ -114,7 +117,6 @@ irqreturn_t handle_IRQ_event(unsigned inif (status &IRQF_SAMPLE_RANDOM )add_interrupt_randomness (irq); -local_irq_disable ();return retval; }
PATCH 8/75 genirq: Fixup poll handling
In reply to Thomas Gleixnertry_one_irq() contains redundant code and lots of useless checks for shared interrupts. Check for shared before setting IRQ_INPROGRESS and then call handle_IRQ_event() while pending. Shorter version with the same functionality.
--- kernel/irq/spurious.c | 50 +++++++++++++++++++------------------------------- 1 file changed, 19 insertions(+), 31 deletions(-)
kernel/irq/spurious.c +19 -31
@@ -42,48 +42,36 @@ static int try_one_irq(int irq, struct iraw_spin_unlock (&desc->lock);return ok; } -/* Honour the normal IRQ locking */ - desc->status |=IRQ_INPROGRESS ; - action = desc->action; -raw_spin_unlock (&desc->lock); - -while (action) { -/* Only shared IRQ handlers are safe to call */ -if (action->flags &IRQF_SHARED ) { -if (action->handler (irq, action->dev_id) == -IRQ_HANDLED ) - ok =1 ; - } - action = action->next; - } -local_irq_disable (); -/* Now clean up the flags */ -raw_spin_lock (&desc->lock); - action = desc->action; -/* -* While we were looking for a fixup someone queued a real -* IRQ clashing with our walk: +* All handlers must agree on IRQF_SHARED, so we test just the +* first. Check for action->next as well. */ -while ((desc->status &IRQ_PENDING ) && action) { -/* -* Perform real IRQ processing for the IRQ we deferred -*/ - work =1 ; + action = desc->action; +if (!action || !(action->flags &IRQF_SHARED ) || !action->next) + goto out; + +/* Honour the normal IRQ locking */ + desc->status |=IRQ_INPROGRESS ; +do { + work++; + desc->status &= ~IRQ_PENDING ;raw_spin_unlock (&desc->lock); -handle_IRQ_event (irq, action); +if (handle_IRQ_event (irq, action) !=IRQ_NONE ) + ok =1 ;raw_spin_lock (&desc->lock); - desc->status &= ~IRQ_PENDING ; - } + action = desc->action; + }while ((desc->status &IRQ_PENDING ) && action); + desc->status &= ~IRQ_INPROGRESS ;/* * If we did actual work for the real IRQ line we must let the * IRQ controller clean up too */ -if (work) +if (work >1 )irq_end (irq, desc); -raw_spin_unlock (&desc->lock); +out: +raw_spin_unlock (&desc->lock);return ok; }
PATCH 9/75 genirq: Do not poll disabled, percpu and timer interrupts
In reply to Thomas GleixnerThere is no point in polling disabled lines.
percpu does not make sense at all because we only poll on the cpu we're currently running on. Also polling per_cpu interrupts is racy as hell. The handler runs without locking so we might get a huge surprise.
If the timer interrupt needs polling, then we wont get there anyway.
--- kernel/irq/spurious.c | 40 ++++++++++++++++++++++++++-------------- 1 file changed, 26 insertions(+), 14 deletions(-)
kernel/irq/spurious.c +26 -14
@@ -25,30 +25,42 @@ static DEFINE_TIMER(poll_spurious_irq_ti/* * Recovery handler for misrouted interrupts. */ -static int try_one_irq (int irq,struct irq_desc *desc) +static int try_one_irq (int irq,struct irq_desc *desc,bool force) {struct irqaction *action;int ok =0 , work =0 ;raw_spin_lock (&desc->lock); + +/* PER_CPU and nested thread interrupts are never polled */ +if (desc->status & (IRQ_PER_CPU |IRQ_NESTED_THREAD )) + goto out; + +/* +* Do not poll disabled interrupts unless the spurious +* disabled poller asks explicitely. +*/ +if ((desc->status &IRQ_DISABLED ) && !force) + goto out; + +/* +* All handlers must agree on IRQF_SHARED, so we test just the +* first. Check for action->next as well. +*/ + action = desc->action; +if (!action || !(action->flags &IRQF_SHARED ) || + (action->flags & __IRQF_TIMER) || !action->next) + goto out; +/* Already running on another processor */ if (desc->status &IRQ_INPROGRESS ) {/* * Already running: If it is shared get the other * CPU to go looking for our mystery interrupt too */ -if (desc->action && (desc->action->flags &IRQF_SHARED )) - desc->status |=IRQ_PENDING ; -raw_spin_unlock (&desc->lock); -return ok; - } -/* -* All handlers must agree on IRQF_SHARED, so we test just the -* first. Check for action->next as well. -*/ - action = desc->action; -if (!action || !(action->flags &IRQF_SHARED ) || !action->next) + desc->status |=IRQ_PENDING ; goto out; + }/* Honour the normal IRQ locking */ desc->status |=IRQ_INPROGRESS ;
@@ -87,7 +99,7 @@ static int misrouted_irq(int irq)if (i == irq)/* Already tried */ continue ; -if (try_one_irq (i, desc)) +if (try_one_irq (i, desc, false)) ok =1 ; }/* So the caller can adjust the irq error counts */
@@ -112,7 +124,7 @@ static void poll_spurious_irqs(unsignedcontinue ;local_irq_disable (); -try_one_irq (i, desc); +try_one_irq (i, desc, true);local_irq_enable (); }
PATCH 10/75 genirq: spurious: Run only one poller at a time
In reply to Thomas GleixnerNo point in running concurrent pollers which confuse each other by setting PENDING.
--- kernel/irq/spurious.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-)
kernel/irq/spurious.c +15 -1
@@ -21,6 +21,8 @@ static int irqfixup __read_mostly;#define POLL_SPURIOUS_IRQ_INTERVAL (HZ/10)static void poll_spurious_irqs (unsigned long dummy); static DEFINE_TIMER(poll_spurious_irq_timer, poll_spurious_irqs, 0, 0); +static int irq_poll_cpu; +static atomic_t irq_poll_active;/* * Recovery handler for misrouted interrupts.
@@ -92,6 +94,11 @@ static int misrouted_irq(int irq)struct irq_desc *desc;int i, ok =0 ; +if (atomic_inc_return (&irq_poll_active) ==1 ) + goto out; + + irq_poll_cpu =smp_processor_id (); +for_each_irq_desc (i, desc) {if (!i)continue ;
@@ -102,6 +109,8 @@ static int misrouted_irq(int irq)if (try_one_irq (i, desc, false)) ok =1 ; } +out: +atomic_dec (&irq_poll_active);/* So the caller can adjust the irq error counts */ return ok; }
@@ -111,6 +120,10 @@ static void poll_spurious_irqs(unsignedstruct irq_desc *desc;int i; +if (atomic_inc_return (&irq_poll_active) !=1 ) + goto out; + irq_poll_cpu =smp_processor_id (); +for_each_irq_desc (i, desc) {unsigned int status;
@@ -127,7 +140,8 @@ static void poll_spurious_irqs(unsignedtry_one_irq (i, desc, true);local_irq_enable (); } - +out: +atomic_dec (&irq_poll_active);mod_timer (&poll_spurious_irq_timer, jiffies +POLL_SPURIOUS_IRQ_INTERVAL ); }
PATCH 11/75 genirq: Mark polled irqs and defer the real handler
In reply to Thomas GleixnerWith the chip.end() function gone we might run into a situation where a poll call runs and the real interrupt comes in, sees IRQ_INPROGRESS and disables the line. That might be a perfect working one, which will then be masked forever.
So mark them polled while the poll runs. When the real handler sees IRQ_INPROGRESS it checks the poll flag and waits for the polling to complete. Add the necessary amount of sanity checks to it to avoid deadlocks.
--- include/linux/irq.h | 1 kernel/irq/chip.c | 26 +++++++++++++++++++----- kernel/irq/internals.h | 11 ---------- kernel/irq/spurious.c | 51 +++++++++++++++++++++++++++++++++++++------------ 4 files changed, 61 insertions(+), 28 deletions(-)
include/linux/irq.h +1 -0
@@ -71,6 +71,7 @@ typedef void (*irq_flow_handler_t)(unsig#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_POLL_INPROGRESS 0x20000000/* IRQ poll is in progress */ #define IRQF_MODIFY_MASK \ (IRQ_TYPE_SENSE_MASK | IRQ_NOPROBE | IRQ_NOREQUEST | \
kernel/irq/chip.c +20 -6
@@ -446,6 +446,13 @@ out_unlock: }EXPORT_SYMBOL_GPL (handle_nested_irq); +static bool irq_check_poll (struct irq_desc *desc) +{ +if (!(desc->status &IRQ_POLL_INPROGRESS )) +return false; +return irq_wait_for_poll (desc); +} +/** * handle_simple_irq - Simple and software-decoded IRQs. * @irq: the interrupt number
@@ -467,7 +474,9 @@ handle_simple_irq(unsigned int irq, struraw_spin_lock (&desc->lock);if (unlikely (desc->status &IRQ_INPROGRESS )) - goto out_unlock; +if (!irq_check_poll (desc)) + goto out_unlock; + desc->status &= ~(IRQ_REPLAY |IRQ_WAITING );kstat_incr_irqs_this_cpu (irq, desc);
@@ -508,7 +517,9 @@ handle_level_irq(unsigned int irq, strucmask_ack_irq (desc);if (unlikely (desc->status &IRQ_INPROGRESS )) - goto out_unlock; +if (!irq_check_poll (desc)) + goto out_unlock; + desc->status &= ~(IRQ_REPLAY |IRQ_WAITING );kstat_incr_irqs_this_cpu (irq, desc);
@@ -556,7 +567,8 @@ handle_fasteoi_irq(unsigned int irq, strraw_spin_lock (&desc->lock);if (unlikely (desc->status &IRQ_INPROGRESS )) - goto out; +if (!irq_check_poll (desc)) + goto out; desc->status &= ~(IRQ_REPLAY |IRQ_WAITING );kstat_incr_irqs_this_cpu (irq, desc);
@@ -618,9 +630,11 @@ handle_edge_irq(unsigned int irq, struct*/ if (unlikely ((desc->status & (IRQ_INPROGRESS |IRQ_DISABLED )) || !desc->action)) { - desc->status |= (IRQ_PENDING |IRQ_MASKED ); -mask_ack_irq (desc); - goto out_unlock; +if (!irq_check_poll (desc)) { + desc->status |= (IRQ_PENDING |IRQ_MASKED ); +mask_ack_irq (desc); + goto out_unlock; + } }kstat_incr_irqs_this_cpu (irq, desc);
kernel/irq/internals.h +1 -10
@@ -22,6 +22,7 @@ extern void init_kstat_irqs(struct irq_d/* Resending of interrupts :*/ void check_irq_resend (struct irq_desc *desc,unsigned int irq); +bool irq_wait_for_poll (struct irq_desc *desc);#ifdef CONFIG_PROC_FS extern void register_irq_proc (unsigned int irq,struct irq_desc *desc);
@@ -41,16 +42,6 @@ extern int irq_select_affinity_usr(unsigextern void irq_set_thread_affinity (struct irq_desc *desc); -#ifndef CONFIG_GENERIC_HARDIRQS_NO_DEPRECATED -static inline void irq_end (unsigned int irq,struct irq_desc *desc) -{ -if (desc->irq_data.chip && desc->irq_data.chip->end) - desc->irq_data.chip->end (irq); -} -#else -static inline void irq_end (unsigned int irq,struct irq_desc *desc) { } -#endif -/* Inline functions for support of irq chips on slow busses */ static inline void chip_bus_lock (struct irq_desc *desc) {
kernel/irq/spurious.c +39 -12
81 lines not on this page · raw message
PATCH 12/75 genirq: Move irq thread flags to core
In reply to Thomas GleixnerSoleley used in core code.
--- include/linux/interrupt.h | 14 -------------- kernel/irq/internals.h | 14 ++++++++++++++ 2 files changed, 14 insertions(+), 14 deletions(-)
include/linux/interrupt.h +0 -14
@@ -74,20 +74,6 @@#define IRQF_TIMER (__IRQF_TIMER | IRQF_NO_SUSPEND)/* -* Bits used by threaded handlers: -* IRQTF_RUNTHREAD - signals that the interrupt handler thread should run -* IRQTF_DIED - handler thread died -* IRQTF_WARNED - warning "IRQ_WAKE_THREAD w/o thread_fn" has been printed -* IRQTF_AFFINITY - irq thread is requested to adjust affinity -*/ -enum { -IRQTF_RUNTHREAD , -IRQTF_DIED , -IRQTF_WARNED , -IRQTF_AFFINITY , -}; - -/* * These values can be returned by request_any_context_irq() and * describe the context the interrupt will be run in. *
kernel/irq/internals.h +14 -0
@@ -5,6 +5,20 @@extern int noirqdebug; +/* +* Bits used by threaded handlers: +* IRQTF_RUNTHREAD - signals that the interrupt handler thread should run +* IRQTF_DIED - handler thread died +* IRQTF_WARNED - warning "IRQ_WAKE_THREAD w/o thread_fn" has been printed +* IRQTF_AFFINITY - irq thread is requested to adjust affinity +*/ +enum { +IRQTF_RUNTHREAD , +IRQTF_DIED , +IRQTF_WARNED , +IRQTF_AFFINITY , +}; +#define irq_data_to_desc (data) container_of(data, struct irq_desc, irq_data)/* Set default functions for irq_chip structures: */
PATCH 13/75 genirq: Remove bogus conditional
In reply to Thomas GleixnerThe if (chip->irq_shutdown) check will always evaluate to true, as we fill in chip->irq_shutdown with default_shutdown in irq_chip_set_defaults() if the chip does not provide its own function.
LKML-Reference: <[email protected]>
--- kernel/irq/manage.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-)
kernel/irq/manage.c +1 -4
@@ -1058,10 +1058,7 @@ static struct irqaction *__free_irq(unsi/* If this was the last handler, shut down the IRQ line: */ if (!desc->action) { desc->status |=IRQ_DISABLED ; -if (desc->irq_data.chip->irq_shutdown) - desc->irq_data.chip->irq_shutdown (&desc->irq_data); -else - desc->irq_data.chip->irq_disable (&desc->irq_data); + desc->irq_data.chip->irq_shutdown (&desc->irq_data); }#ifdef CONFIG_SMP
PATCH 14/75 genirq: Consolidate startup/shutdown of interrupts
In reply to Thomas GleixnerAside of duplicated code some of the startup/shutdown sites do not handle the MASKED/DISABLED flags and the depth field at all. Move that to a helper function and take care of it there.
LKML-Reference: <[email protected]>
--- kernel/irq/autoprobe.c | 10 +++++----- kernel/irq/chip.c | 37 ++++++++++++++++++++----------------- kernel/irq/internals.h | 3 +++ kernel/irq/manage.c | 14 +++++--------- 4 files changed, 33 insertions(+), 31 deletions(-)
kernel/irq/autoprobe.c +5 -5
@@ -60,7 +60,7 @@ unsigned long probe_irq_on(void)if (desc->irq_data.chip->irq_set_type) desc->irq_data.chip->irq_set_type (&desc->irq_data,IRQ_TYPE_PROBE ); - desc->irq_data.chip->irq_startup (&desc->irq_data); +irq_startup (desc); }raw_spin_unlock_irq (&desc->lock); }
@@ -77,7 +77,7 @@ unsigned long probe_irq_on(void)raw_spin_lock_irq (&desc->lock);if (!desc->action && !(desc->status &IRQ_NOPROBE )) { desc->status |=IRQ_AUTODETECT |IRQ_WAITING ; -if (desc->irq_data.chip->irq_startup (&desc->irq_data)) +if (irq_startup (desc)) desc->status |=IRQ_PENDING ; }raw_spin_unlock_irq (&desc->lock);
@@ -99,7 +99,7 @@ unsigned long probe_irq_on(void)/* It triggered already - consider it spurious. */ if (!(status &IRQ_WAITING )) { desc->status = status & ~IRQ_AUTODETECT ; - desc->irq_data.chip->irq_shutdown (&desc->irq_data); +irq_shutdown (desc); }else if (i <32 ) mask |=1 << i;
@@ -138,7 +138,7 @@ unsigned int probe_irq_mask(unsigned lon mask |=1 << i; desc->status = status & ~IRQ_AUTODETECT ; - desc->irq_data.chip->irq_shutdown (&desc->irq_data); +irq_shutdown (desc); }raw_spin_unlock_irq (&desc->lock); }
@@ -182,7 +182,7 @@ int probe_irq_off(unsigned long val) nr_of_irqs++; } desc->status = status & ~IRQ_AUTODETECT ; - desc->irq_data.chip->irq_shutdown (&desc->irq_data); +irq_shutdown (desc); }raw_spin_unlock_irq (&desc->lock); }
kernel/irq/chip.c +20 -17
@@ -190,6 +190,25 @@ void set_irq_nested_thread(unsigned int }EXPORT_SYMBOL_GPL (set_irq_nested_thread); +int irq_startup (struct irq_desc *desc) +{ + desc->status &= ~(IRQ_MASKED |IRQ_DISABLED ); + desc->depth =0 ; + +if (desc->irq_data.chip->irq_startup) +return desc->irq_data.chip->irq_startup (&desc->irq_data); + + desc->irq_data.chip->irq_enable (&desc->irq_data); +return 0 ; +} + +void irq_shutdown (struct irq_desc *desc) +{ + desc->status |=IRQ_MASKED |IRQ_DISABLED ; + desc->depth =1 ; + desc->irq_data.chip->irq_shutdown (&desc->irq_data); +} +/* * default enable function */
@@ -209,17 +228,6 @@ static void default_disable(struct irq_d }/* -* default startup function -*/ -static unsigned int default_startup (struct irq_data *data) -{ -struct irq_desc *desc =irq_data_to_desc (data); - - desc->irq_data.chip->irq_enable (data); -return 0 ; -} - -/* * default shutdown function */ static void default_shutdown (struct irq_data *data)
@@ -227,7 +235,6 @@ static void default_shutdown(struct irq_struct irq_desc *desc =irq_data_to_desc (data); desc->irq_data.chip->irq_mask (&desc->irq_data); - desc->status |=IRQ_MASKED ; }#ifndef CONFIG_GENERIC_HARDIRQS_NO_DEPRECATED
@@ -335,8 +342,6 @@ void irq_chip_set_defaults(struct irq_ch chip->irq_enable = default_enable;if (!chip->irq_disable) chip->irq_disable = default_disable; -if (!chip->irq_startup) - chip->irq_startup = default_startup;/* * We use chip->irq_disable, when the user provided its own. When * we have default_disable set for chip->irq_disable, then we need
@@ -745,10 +750,8 @@ __set_irq_handler(unsigned int irq, irq_ desc->name = name;if (handle != handle_bad_irq && is_chained) { - desc->status &= ~IRQ_DISABLED ; desc->status |=IRQ_NOREQUEST |IRQ_NOPROBE ; - desc->depth =0 ; - desc->irq_data.chip->irq_startup (&desc->irq_data); +irq_startup (desc); }raw_spin_unlock_irqrestore (&desc->lock, flags);chip_bus_sync_unlock (desc);
kernel/irq/internals.h +3 -0
@@ -32,6 +32,9 @@ extern int __irq_set_trigger(struct irq_extern void __disable_irq (struct irq_desc *desc,unsigned int irq,bool susp);extern void __enable_irq (struct irq_desc *desc,unsigned int irq,bool resume); +extern int irq_startup (struct irq_desc *desc); +extern void irq_shutdown (struct irq_desc *desc); +extern void init_kstat_irqs (struct irq_desc *desc,int node,int nr);/* Resending of interrupts :*/
kernel/irq/manage.c +5 -9
@@ -912,11 +912,9 @@ __setup_irq(unsigned int irq, struct irqif (new->flags &IRQF_ONESHOT ) desc->status |=IRQ_ONESHOT ; -if (!(desc->status &IRQ_NOAUTOEN )) { - desc->depth =0 ; - desc->status &= ~IRQ_DISABLED ; - desc->irq_data.chip->irq_startup (&desc->irq_data); - }else +if (!(desc->status &IRQ_NOAUTOEN )) +irq_startup (desc); +else /* Undo nested disables: */ desc->depth =1 ;
@@ -1056,10 +1054,8 @@ static struct irqaction *__free_irq(unsi#endif /* If this was the last handler, shut down the IRQ line: */ -if (!desc->action) { - desc->status |=IRQ_DISABLED ; - desc->irq_data.chip->irq_shutdown (&desc->irq_data); - } +if (!desc->action) +irq_shutdown (desc);#ifdef CONFIG_SMP /* make sure affinity_hint is cleaned up */
PATCH 15/75 genirq: Consolidate disable/enable
In reply to Thomas GleixnerCreate irq_disable/enable and use them to keep the flags consistent.
--- kernel/irq/chip.c | 12 +++++++++++- kernel/irq/internals.h | 2 ++ kernel/irq/manage.c | 2 +- kernel/irq/resend.c | 10 +++++----- kernel/irq/spurious.c | 2 +- 5 files changed, 20 insertions(+), 8 deletions(-)
kernel/irq/chip.c +11 -1
@@ -198,7 +198,7 @@ int irq_startup(struct irq_desc *desc)if (desc->irq_data.chip->irq_startup)return desc->irq_data.chip->irq_startup (&desc->irq_data); - desc->irq_data.chip->irq_enable (&desc->irq_data); +irq_enable (desc);return 0 ; }
@@ -209,6 +209,16 @@ void irq_shutdown(struct irq_desc *desc) desc->irq_data.chip->irq_shutdown (&desc->irq_data); } +void irq_enable (struct irq_desc *desc) +{ + desc->irq_data.chip->irq_enable (&desc->irq_data); +} + +void irq_disable (struct irq_desc *desc) +{ + desc->irq_data.chip->irq_disable (&desc->irq_data); +} +/* * default enable function */
kernel/irq/internals.h +2 -0
@@ -34,6 +34,8 @@ extern void __enable_irq(struct irq_descextern int irq_startup (struct irq_desc *desc);extern void irq_shutdown (struct irq_desc *desc); +extern void irq_enable (struct irq_desc *desc); +extern void irq_disable (struct irq_desc *desc);extern void init_kstat_irqs (struct irq_desc *desc,int node,int nr);
kernel/irq/manage.c +1 -1
@@ -339,7 +339,7 @@ void __disable_irq(struct irq_desc *descif (!desc->depth++) { desc->status |=IRQ_DISABLED ; - desc->irq_data.chip->irq_disable (&desc->irq_data); +irq_disable (desc); } }
kernel/irq/resend.c +5 -5
@@ -55,20 +55,20 @@ static DECLARE_TASKLET(resend_tasklet, r*/ 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->irq_data.chip->irq_enable (&desc->irq_data); +irq_enable (desc);/* * We do not resend level type interrupts. Level type * interrupts are resent by hardware when they are still * active. */ -if ((status & (IRQ_LEVEL |IRQ_PENDING |IRQ_REPLAY )) ==IRQ_PENDING ) { - desc->status = (status & ~IRQ_PENDING ) |IRQ_REPLAY ; +if (desc->status &IRQ_LEVEL ) +return ; +if ((desc->status & (IRQ_PENDING |IRQ_REPLAY )) ==IRQ_PENDING ) { + desc->status = (desc->status & ~IRQ_PENDING ) |IRQ_REPLAY ;if (!desc->irq_data.chip->irq_retrigger || !desc->irq_data.chip->irq_retrigger (&desc->irq_data)) {
kernel/irq/spurious.c +1 -1
@@ -303,7 +303,7 @@ void note_interrupt(unsigned int irq, stprintk (KERN_EMERG "Disabling IRQ #%d\n" , irq); desc->status |=IRQ_DISABLED |IRQ_SPURIOUS_DISABLED ; desc->depth++; - desc->irq_data.chip->irq_disable (&desc->irq_data); +irq_disable (desc);mod_timer (&poll_spurious_irq_timer, jiffies +POLL_SPURIOUS_IRQ_INTERVAL );
PATCH 16/75 genirq: Remove default magic
In reply to Thomas GleixnerNow that everything uses the wrappers, we can remove the default functions. None of those functions is performance critical.
That makes the IRQ_MASKED flag tracking fully consistent.
--- kernel/irq/chip.c | 73 ++++++++++------------------------------------------ kernel/irq/manage.c | 4 +- 2 files changed, 17 insertions(+), 60 deletions(-)
kernel/irq/chip.c +15 -58
@@ -206,45 +206,29 @@ void irq_shutdown(struct irq_desc *desc) { desc->status |=IRQ_MASKED |IRQ_DISABLED ; desc->depth =1 ; - desc->irq_data.chip->irq_shutdown (&desc->irq_data); +if (desc->irq_data.chip->irq_shutdown) + desc->irq_data.chip->irq_shutdown (&desc->irq_data); +if (desc->irq_data.chip->irq_disable) + desc->irq_data.chip->irq_disable (&desc->irq_data); +else + desc->irq_data.chip->irq_mask (&desc->irq_data); }void irq_enable (struct irq_desc *desc) { - desc->irq_data.chip->irq_enable (&desc->irq_data); -} - -void irq_disable (struct irq_desc *desc) -{ - desc->irq_data.chip->irq_disable (&desc->irq_data); -} - -/* -* default enable function -*/ -static void default_enable (struct irq_data *data) -{ -struct irq_desc *desc =irq_data_to_desc (data); - - desc->irq_data.chip->irq_unmask (&desc->irq_data); +if (desc->irq_data.chip->irq_enable) + desc->irq_data.chip->irq_enable (&desc->irq_data); +else + desc->irq_data.chip->irq_unmask (&desc->irq_data); desc->status &= ~IRQ_MASKED ; } -/* -* default disable function -*/ -static void default_disable (struct irq_data *data) -{ -} - -/* -* default shutdown function -*/ -static void default_shutdown (struct irq_data *data) +void irq_disable (struct irq_desc *desc) { -struct irq_desc *desc =irq_data_to_desc (data); - - desc->irq_data.chip->irq_mask (&desc->irq_data); +if (desc->irq_data.chip->irq_disable) { + desc->irq_data.chip->irq_disable (&desc->irq_data); + desc->status |=IRQ_MASKED ; + } }#ifndef CONFIG_GENERIC_HARDIRQS_NO_DEPRECATED
@@ -332,10 +316,6 @@ static void compat_bus_sync_unlock(strucvoid irq_chip_set_defaults (struct irq_chip *chip) {#ifndef CONFIG_GENERIC_HARDIRQS_NO_DEPRECATED -/* -* Compat fixup functions need to be before we set the -* defaults for enable/disable/startup/shutdown -*/ if (chip->enable) chip->irq_enable = compat_irq_enable;if (chip->disable)
@@ -344,31 +324,8 @@ void irq_chip_set_defaults(struct irq_ch chip->irq_shutdown = compat_irq_shutdown;if (chip->startup) chip->irq_startup = compat_irq_startup; -#endif -/* -* The real defaults -*/ -if (!chip->irq_enable) - chip->irq_enable = default_enable; -if (!chip->irq_disable) - chip->irq_disable = default_disable; -/* -* We use chip->irq_disable, when the user provided its own. When -* we have default_disable set for chip->irq_disable, then we need -* to use default_shutdown, otherwise the irq line is not -* disabled on free_irq(): -*/ -if (!chip->irq_shutdown) - chip->irq_shutdown = chip->irq_disable != default_disable ? - chip->irq_disable : default_shutdown; - -#ifndef CONFIG_GENERIC_HARDIRQS_NO_DEPRECATED if (!chip->end) chip->end = dummy_irq_chip.end; - -/* -* Now fix up the remaining compat handlers -*/ if (chip->bus_lock) chip->irq_bus_lock = compat_bus_lock;if (chip->bus_sync_unlock)
kernel/irq/manage.c +2 -2
@@ -448,8 +448,8 @@ void enable_irq(unsigned int irq)if (!desc)return ; -if (WARN (!desc->irq_data.chip || !desc->irq_data.chip->irq_enable, -KERN_ERR "enable_irq before setup/request_irq: irq %u\n" , irq)) +if (WARN (!desc->irq_data.chip, +KERN_ERR "enable_irq before setup/request_irq: irq %u\n" , irq))return ;chip_bus_lock (desc);
PATCH 17/75 genirq: Consolidate IRQ_DISABLED
In reply to Thomas GleixnerHandle IRQ_DISABLED consistent.
--- kernel/irq/chip.c | 14 ++++++++++---- kernel/irq/manage.c | 9 +++------ kernel/irq/resend.c | 5 ----- kernel/irq/spurious.c | 2 +- 4 files changed, 14 insertions(+), 16 deletions(-)
kernel/irq/chip.c +10 -4
@@ -192,11 +192,14 @@ EXPORT_SYMBOL_GPL(set_irq_nested_thread)int irq_startup (struct irq_desc *desc) { - desc->status &= ~(IRQ_MASKED |IRQ_DISABLED ); + desc->status &= ~IRQ_DISABLED ; desc->depth =0 ; -if (desc->irq_data.chip->irq_startup) -return desc->irq_data.chip->irq_startup (&desc->irq_data); +if (desc->irq_data.chip->irq_startup) { +int ret = desc->irq_data.chip->irq_startup (&desc->irq_data); + desc->status &=IRQ_MASKED ; +return ret; + }irq_enable (desc);return 0 ;
@@ -204,7 +207,7 @@ int irq_startup(struct irq_desc *desc)void irq_shutdown (struct irq_desc *desc) { - desc->status |=IRQ_MASKED |IRQ_DISABLED ; + desc->status |=IRQ_DISABLED ; desc->depth =1 ;if (desc->irq_data.chip->irq_shutdown) desc->irq_data.chip->irq_shutdown (&desc->irq_data);
@@ -212,10 +215,12 @@ void irq_shutdown(struct irq_desc *desc) desc->irq_data.chip->irq_disable (&desc->irq_data); else desc->irq_data.chip->irq_mask(&desc->irq_data); + desc->status |=IRQ_MASKED ; }void irq_enable (struct irq_desc *desc) { + desc->status &= ~IRQ_DISABLED ;if (desc->irq_data.chip->irq_enable) desc->irq_data.chip->irq_enable (&desc->irq_data);else
@@ -225,6 +230,7 @@ void irq_enable(struct irq_desc *desc)void irq_disable (struct irq_desc *desc) { + desc->status |=IRQ_DISABLED ;if (desc->irq_data.chip->irq_disable) { desc->irq_data.chip->irq_disable (&desc->irq_data); desc->status |=IRQ_MASKED ;
kernel/irq/manage.c +3 -6
@@ -337,10 +337,8 @@ void __disable_irq(struct irq_desc *desc desc->status |=IRQ_SUSPENDED ; } -if (!desc->depth++) { - desc->status |=IRQ_DISABLED ; +if (!desc->depth++)irq_disable (desc); - } }/**
@@ -415,12 +413,11 @@ void __enable_irq(struct irq_desc *desc,WARN (1 ,KERN_WARNING "Unbalanced enable for IRQ %d\n" , irq);break ;case 1 : { -unsigned int status = desc->status & ~IRQ_DISABLED ; -if (desc->status &IRQ_SUSPENDED ) goto err_out;/* Prevent probing on this irq: */ - desc->status = status |IRQ_NOPROBE ; + desc->status |=IRQ_NOPROBE ; +irq_enable (desc);check_irq_resend (desc, irq);/* fall-through */ }
kernel/irq/resend.c +0 -5
@@ -56,11 +56,6 @@ static DECLARE_TASKLET(resend_tasklet, rvoid check_irq_resend (struct irq_desc *desc,unsigned int irq) {/* -* Make sure the interrupt is enabled, before resending it: -*/ -irq_enable (desc); - -/* * We do not resend level type interrupts. Level type * interrupts are resent by hardware when they are still * active.
kernel/irq/spurious.c +1 -1
@@ -301,7 +301,7 @@ void note_interrupt(unsigned int irq, st* Now kill the IRQ */ printk (KERN_EMERG "Disabling IRQ #%d\n" , irq); - desc->status |=IRQ_DISABLED |IRQ_SPURIOUS_DISABLED ; + desc->status |=IRQ_SPURIOUS_DISABLED ; desc->depth++;irq_disable (desc);
Re: [patch 17/75] genirq: Consolidate IRQ_DISABLED
Quoted 7 lines · Thomas Gleixner
Index:
linux-2.6-tip/kernel/irq/chip.c
===================================================================kernel/irq/chip.c +0
-0@@ -192,11 +192,14 @@ EXPORT_SYMBOL_GPL(set_irq_nested_thread)int irq_startup (struct irq_desc *desc)
kernel/irq/chip.c EXPORT_SYMBOL_GPL(set_irq_nested_thread) · line 200
Quoted 10 lines
kernel/irq/chip.c +4
-3{ - desc->status &= ~(IRQ_MASKED |IRQ_DISABLED ); + desc->status &= ~IRQ_DISABLED ; desc->depth =0 ; -if (desc->irq_data.chip->irq_startup) -return desc->irq_data.chip->irq_startup (&desc->irq_data); +if (desc->irq_data.chip->irq_startup) { +int ret = desc->irq_data.chip->irq_startup (&desc->irq_data); + desc->status &=IRQ_MASKED ;
Although it is fixed in patch 45 of this series, I guess it should rather be desc->status &= ~IRQ_MASKED here too.
Quoted 2 lines
kernel/irq/chip.c +2
-0+return ret; + }
Re: [patch 17/75] genirq: Consolidate IRQ_DISABLED
Quoted 13 lines · Lars-Peter Clausen
Quoted 12 lines · Thomas Gleixner
Index:
linux-2.6-tip/kernel/irq/chip.c
===================================================================kernel/irq/chip.c +1
-1@@ -192,11 +192,14 @@ EXPORT_SYMBOL_GPL(set_irq_nested_thread)int irq_startup (struct irq_desc *desc) { - desc->status &= ~(IRQ_MASKED |IRQ_DISABLED ); + desc->status &= ~IRQ_DISABLED ; desc->depth =0 ;
Quoted 8 lines
kernel/irq/chip.c EXPORT_SYMBOL_GPL(set_irq_nested_thread) · line 200
Quoted 5 lines
kernel/irq/chip.c +3
-2-if (desc->irq_data.chip->irq_startup) -return desc->irq_data.chip->irq_startup (&desc->irq_data); +if (desc->irq_data.chip->irq_startup) { +int ret = desc->irq_data.chip->irq_startup (&desc->irq_data); + desc->status &=IRQ_MASKED ;Although it is fixed in patch 45 of this series, I guess it should rather be
desc->status&= ~IRQ_MASKED here too.
Good catch. Will fix nevertheless.
Thanks,
tglx
PATCH 18/75 genirq: Do not fiddle with IRQ_MASKED in handle_edge_irq()
In reply to Thomas GleixnerIRQ_MASKED is set in mask_ack_irq() anyway. Remove it from handle_edge_irq() to allow simpler ab^HHreuse of that function.
LKML-Reference: <[email protected]>
--- kernel/irq/chip.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
kernel/irq/chip.c +1 -1
@@ -609,7 +609,7 @@ handle_edge_irq(unsigned int irq, structif (unlikely ((desc->status & (IRQ_INPROGRESS |IRQ_DISABLED )) || !desc->action)) {if (!irq_check_poll (desc)) { - desc->status |= (IRQ_PENDING |IRQ_MASKED ); + desc->status |=IRQ_PENDING ;mask_ack_irq (desc); goto out_unlock; }
PATCH 19/75 m68knommu: 5772: Replace private irq flow handler
In reply to Thomas GleixnerThat handler lacks the minimal checks for action being zero etc. Keep the weird flow - ack before handling - intact and call into handle_simple_irq which does the right thing.
LKML-Reference: <[email protected]>
--- arch/m68knommu/platform/5272/intc.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-)
arch/m68knommu/platform/5272/intc.c +2 -5
@@ -137,11 +137,8 @@ static int intc_irq_set_type(unsigned in*/ static void intc_external_irq (unsigned int irq,struct irq_desc *desc) { -kstat_incr_irqs_this_cpu (irq, desc); - desc->status |=IRQ_INPROGRESS ; - desc->chip->ack (irq); -handle_IRQ_event (irq, desc->action); - desc->status &= ~IRQ_INPROGRESS ; +get_irq_desc_chip (desc)->irq_ack (irq); +handle_simple_irq (irq, desc); }static struct irq_chip intc_irq_chip = {
PATCH 20/75 arm: Ns9xxx: Remove private irq flow handler
In reply to Thomas GleixnerAn embedded and charset-unspecified text was scrubbed...
Name: arm-ns9xxx-remove-private-irq-flow-handler.patch
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20110210/6d23cb43/attachment.ksh>
PATCH 21/75 genirq: Mark handle_IRQ_event deprecated
In reply to Thomas GleixnerWe really want to have special flow handlers in the core code so we can see the patterns.
--- include/linux/irq.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
include/linux/irq.h +3 -2
@@ -248,8 +248,9 @@ static inline void move_masked_irq(int iextern int no_irq_affinity; -/* Handle irq action chains: */ -extern irqreturn_t handle_IRQ_event (unsigned int irq,struct irqaction *action); +/* Handle irq action chains. Will go away */ +extern irqreturn_t __deprecated handle_IRQ_event (unsigned int irq, +struct irqaction *action);/* * Built-in IRQ handlers for various IRQ types,
PATCH 22/75 genirq: Implement handle_irq_event()
In reply to Thomas GleixnerCore code replacement for the ugly camel case. It contains all the code which is shared in all handlers.
clear status flags
set INPROGRESS flag
unlock
call action chain
note_interrupt
lock
clr INPROGRESS flag
--- kernel/irq/handle.c | 47 +++++++++++++++++++++++++++++++++++++++-------- kernel/irq/internals.h | 4 ++++ 2 files changed, 43 insertions(+), 8 deletions(-)
kernel/irq/handle.c +39 -8
@@ -51,14 +51,7 @@ static void warn_no_thread(unsigned int "but no thread function available.", irq, action->name); } -/** -* handle_IRQ_event - irq action chain handler -* @irq: the interrupt number -* @action: the interrupt action chain for this irq -* -* Handles the action chain of an irq event -*/ -irqreturn_t handle_IRQ_event (unsigned int irq,struct irqaction *action) +static irqreturn_t __handle_irq_event (unsigned int irq,struct irqaction *action) {irqreturn_t ret, retval =IRQ_NONE ;unsigned int status =0 ;
@@ -120,3 +113,41 @@ irqreturn_t handle_IRQ_event(unsigned inreturn retval; } + +irqreturn_t +handle_irq_event_percpu (struct irq_desc *desc,struct irqaction *action) +{ +irqreturn_t ret =__handle_irq_event (desc->irq_data.irq, action); + +if (!noirqdebug) +note_interrupt (desc->irq_data.irq, desc, ret); +return ret; +} + +irqreturn_t handle_irq_event (struct irq_desc *desc) +{ +struct irqaction *action = desc->action; +irqreturn_t ret; + + desc->status &= ~IRQ_PENDING ; + desc->status |=IRQ_INPROGRESS ; +raw_spin_unlock (&desc->lock); + + ret =handle_irq_event_percpu (desc, action); + +raw_spin_lock (&desc->lock); + desc->status &= ~IRQ_INPROGRESS ; +return ret; +} + +/** +* handle_IRQ_event - irq action chain handler +* @irq: the interrupt number +* @action: the interrupt action chain for this irq +* +* Handles the action chain of an irq event +*/ +irqreturn_t handle_IRQ_event (unsigned int irq,struct irqaction *action) +{ +return __handle_irq_event (irq, action); +}
kernel/irq/internals.h +4 -0
@@ -39,8 +39,12 @@ extern void irq_disable(struct irq_descextern void init_kstat_irqs (struct irq_desc *desc,int node,int nr); +irqreturn_t handle_irq_event_percpu (struct irq_desc *desc,struct irqaction *action); +irqreturn_t handle_irq_event (struct irq_desc *desc); +/* Resending of interrupts :*/ void check_irq_resend (struct irq_desc *desc,unsigned int irq); +bool irq_wait_for_poll (struct irq_desc *desc);#ifdef CONFIG_PROC_FS
PATCH 23/75 genirq: Use handle_irq_event() in handle_simple_irq()
In reply to Thomas Gleixner--- kernel/irq/chip.c | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-)
kernel/irq/chip.c +2 -13
@@ -446,9 +446,6 @@ static bool irq_check_poll(struct irq_devoid handle_simple_irq (unsigned int irq,struct irq_desc *desc) { -struct irqaction *action; -irqreturn_t action_ret; -raw_spin_lock (&desc->lock);if (unlikely (desc->status &IRQ_INPROGRESS ))
@@ -458,19 +455,11 @@ handle_simple_irq(unsigned int irq, stru desc->status &= ~(IRQ_REPLAY |IRQ_WAITING );kstat_incr_irqs_this_cpu (irq, desc); - action = desc->action; -if (unlikely (!action || (desc->status &IRQ_DISABLED ))) +if (unlikely (!desc->action || (desc->status &IRQ_DISABLED ))) goto out_unlock; - desc->status |=IRQ_INPROGRESS ; -raw_spin_unlock (&desc->lock); +handle_irq_event (desc); - action_ret =handle_IRQ_event (irq, action); -if (!noirqdebug) -note_interrupt (irq, desc, action_ret); - -raw_spin_lock (&desc->lock); - desc->status &= ~IRQ_INPROGRESS ; out_unlock:raw_spin_unlock (&desc->lock); }
PATCH 24/75 genirq: Use handle_irq_event() in handle_level_irq()
In reply to Thomas Gleixner--- kernel/irq/chip.c | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-)
kernel/irq/chip.c +2 -14
@@ -477,9 +477,6 @@ out_unlock:void handle_level_irq (unsigned int irq,struct irq_desc *desc) { -struct irqaction *action; -irqreturn_t action_ret; -raw_spin_lock (&desc->lock);mask_ack_irq (desc);
@@ -494,19 +491,10 @@ handle_level_irq(unsigned int irq, struc* If its disabled or no action available * keep it masked and get out of here */ - action = desc->action; -if (unlikely (!action || (desc->status &IRQ_DISABLED ))) +if (unlikely (!desc->action || (desc->status &IRQ_DISABLED ))) goto out_unlock; - desc->status |=IRQ_INPROGRESS ; -raw_spin_unlock (&desc->lock); - - action_ret =handle_IRQ_event (irq, action); -if (!noirqdebug) -note_interrupt (irq, desc, action_ret); - -raw_spin_lock (&desc->lock); - desc->status &= ~IRQ_INPROGRESS ; +handle_irq_event (desc);if (!(desc->status & (IRQ_DISABLED |IRQ_ONESHOT )))unmask_irq (desc);
PATCH 25/75 genirq: Use handle_irq_event() in handle_fasteoi_irq()
In reply to Thomas Gleixner--- kernel/irq/chip.c | 19 ++----------------- 1 file changed, 2 insertions(+), 17 deletions(-)
kernel/irq/chip.c +2 -17
@@ -516,9 +516,6 @@ EXPORT_SYMBOL_GPL(handle_level_irq);void handle_fasteoi_irq (unsigned int irq,struct irq_desc *desc) { -struct irqaction *action; -irqreturn_t action_ret; -raw_spin_lock (&desc->lock);if (unlikely (desc->status &IRQ_INPROGRESS ))
@@ -532,26 +529,14 @@ handle_fasteoi_irq(unsigned int irq, str* If its disabled or no action available * then mask it and get out of here: */ - action = desc->action; -if (unlikely (!action || (desc->status &IRQ_DISABLED ))) { +if (unlikely (!desc->action || (desc->status &IRQ_DISABLED ))) { desc->status |=IRQ_PENDING ;mask_irq (desc); goto out; } - - desc->status |=IRQ_INPROGRESS ; - desc->status &= ~IRQ_PENDING ; -raw_spin_unlock (&desc->lock); - - action_ret =handle_IRQ_event (irq, action); -if (!noirqdebug) -note_interrupt (irq, desc, action_ret); - -raw_spin_lock (&desc->lock); - desc->status &= ~IRQ_INPROGRESS ; +handle_irq_event (desc); out: desc->irq_data.chip->irq_eoi (&desc->irq_data); -raw_spin_unlock (&desc->lock); }
PATCH 26/75 genirq: Use handle_irq_event() in handle_edge_irq()
In reply to Thomas GleixnerIt's safe to drop the IRQ_INPROGRESS flag between action chain walks as we are protected by desc->lock.
--- kernel/irq/chip.c | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-)
kernel/irq/chip.c +2 -14
@@ -581,14 +581,8 @@ handle_edge_irq(unsigned int irq, struct/* Start handling the irq */ desc->irq_data.chip->irq_ack (&desc->irq_data); -/* Mark the IRQ currently in progress.*/ - desc->status |=IRQ_INPROGRESS ; - do { - struct irqaction *action = desc->action; - irqreturn_t action_ret; - - if (unlikely(!action)) { + if (unlikely(!desc->action)) { mask_irq(desc); goto out_unlock; }
@@ -604,16 +598,10 @@ handle_edge_irq(unsigned int irq, structunmask_irq (desc); } - desc->status &= ~IRQ_PENDING ; -raw_spin_unlock (&desc->lock); - action_ret =handle_IRQ_event (irq, action); -if (!noirqdebug) -note_interrupt (irq, desc, action_ret); -raw_spin_lock (&desc->lock); +handle_irq_event (desc); }while ((desc->status & (IRQ_PENDING |IRQ_DISABLED )) ==IRQ_PENDING ); - desc->status &= ~IRQ_INPROGRESS ; out_unlock:raw_spin_unlock (&desc->lock); }
PATCH 27/75 genirq: Use handle_perpcu_event() in handle_percpu_irq()
In reply to Thomas Gleixner--- kernel/irq/chip.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-)
kernel/irq/chip.c +6 -8
@@ -616,19 +616,17 @@ out_unlock:void handle_percpu_irq (unsigned int irq,struct irq_desc *desc) { -irqreturn_t action_ret; +struct irq_chip *chip =get_irq_desc_chip (desc);kstat_incr_irqs_this_cpu (irq, desc); -if (desc->irq_data.chip->irq_ack) - desc->irq_data.chip->irq_ack (&desc->irq_data); +if (chip->irq_ack) + chip->irq_ack (&desc->irq_data); - action_ret =handle_IRQ_event (irq, desc->action); -if (!noirqdebug) -note_interrupt (irq, desc, action_ret); +handle_irq_event_percpu (desc, desc->action); -if (desc->irq_data.chip->irq_eoi) - desc->irq_data.chip->irq_eoi (&desc->irq_data); +if (chip->irq_eoi) + chip->irq_eoi (&desc->irq_data); }void
PATCH 28/75 genirq: Use handle_irq_event() in the spurious poll code
In reply to Thomas Gleixner--- kernel/irq/spurious.c | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-)
kernel/irq/spurious.c +9 -12
@@ -56,13 +56,14 @@ bool irq_wait_for_poll(struct irq_desc *#endif } +/* * Recovery handler for misrouted interrupts. */ static int try_one_irq (int irq,struct irq_desc *desc,bool force) { +irqreturn_t ret =IRQ_NONE ;struct irqaction *action; -int ok =0 ;raw_spin_lock (&desc->lock);
@@ -96,21 +97,17 @@ static int try_one_irq(int irq, struct i goto out; } -/* Honour the normal IRQ locking and mark it poll in progress */ - desc->status |=IRQ_INPROGRESS |IRQ_POLL_INPROGRESS ; +/* Mark it poll in progress */ + desc->status |=IRQ_POLL_INPROGRESS ;do { - desc->status &= ~IRQ_PENDING ; -raw_spin_unlock (&desc->lock); -if (handle_IRQ_event (irq, action) !=IRQ_NONE ) - ok =1 ; -raw_spin_lock (&desc->lock); +if (handle_irq_event (desc) ==IRQ_HANDLED ) + ret =IRQ_HANDLED ; action = desc->action; - }while ((desc->status &IRQ_PENDING ) && action); - - desc->status &= ~(IRQ_INPROGRESS |IRQ_POLL_INPROGRESS ); + }while ((desc->status &IRQ_PENDING ) && action); + desc->status &= ~IRQ_POLL_INPROGRESS ; out:raw_spin_unlock (&desc->lock); -return ok; +return ret ==IRQ_HANDLED ; }static int misrouted_irq (int irq)
PATCH 29/75 genirq: Simplify handle_irq_event()
In reply to Thomas GleixnerNow that all core users are converted one layer can go.
--- kernel/irq/handle.c | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-)
kernel/irq/handle.c +5 -12
@@ -51,10 +51,11 @@ static void warn_no_thread(unsigned int "but no thread function available.", irq, action->name); } -static irqreturn_t __handle_irq_event (unsigned int irq,struct irqaction *action) +irqreturn_t +handle_irq_event_percpu (struct irq_desc *desc,struct irqaction *action) {irqreturn_t ret, retval =IRQ_NONE ; -unsigned int status =0 ; +unsigned int status =0 , irq = desc->irq_data.irq; do { trace_irq_handler_entry(irq, action);
@@ -111,17 +112,9 @@ static irqreturn_t __handle_irq_event(unif (status &IRQF_SAMPLE_RANDOM )add_interrupt_randomness (irq); -return retval; -} - -irqreturn_t -handle_irq_event_percpu (struct irq_desc *desc,struct irqaction *action) -{ -irqreturn_t ret =__handle_irq_event (desc->irq_data.irq, action); -if (!noirqdebug)note_interrupt (desc->irq_data.irq, desc, ret); -return ret; +return retval; }irqreturn_t handle_irq_event (struct irq_desc *desc)
@@ -149,5 +142,5 @@ irqreturn_t handle_irq_event(struct irq_*/ irqreturn_t handle_IRQ_event (unsigned int irq,struct irqaction *action) { -return __handle_irq_event (irq, action); +return handle_irq_event_percpu (irq_to_desc (irq), action); }
PATCH 30/75 genirq: Implement generic irq_show_interrupts()
In reply to Thomas GleixnerAll archs implement show_interrupts() in more or less the same way. That's tons of duplicated code with different bugs with no value. Implement a generic version and deprecate show_interrupts()
Unfortunately we need some ifdeffery for !GENERIC_HARDIRQ archs.
--- fs/proc/interrupts.c | 2 - include/linux/interrupt.h | 8 +++++ kernel/irq/Kconfig | 3 ++ kernel/irq/proc.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 80 insertions(+), 1 deletion(-)
fs/proc/interrupts.c +1 -1
@@ -30,7 +30,7 @@ static const struct seq_operations int_s .start = int_seq_start, .next = int_seq_next, .stop = int_seq_stop, - .show = show_interrupts + .show = proc_show_interrupts };static int interrupts_open (struct inode *inode,struct file *filp)
include/linux/interrupt.h +8 -0
@@ -662,7 +662,15 @@ static inline void init_irq_proc(void)#endif struct seq_file ; +#ifdef CONFIG_GENERIC_HARDIRQS +int __deprecated show_interrupts (struct seq_file *p,void *v); +int irq_show_interrupts (struct seq_file *p,void *v); +int arch_show_interrupts (struct seq_file *p,int prec); +# define proc_show_interrupts irq_show_interrupts +#else int show_interrupts (struct seq_file *p,void *v); +# define proc_show_interrupts show_interrupts +#endif extern int early_irq_init (void );extern int arch_probe_nr_irqs (void );
kernel/irq/Kconfig +3 -0
@@ -20,6 +20,9 @@ config HAVE_SPARSE_IRQ config GENERIC_IRQ_PROBE def_bool n +config GENERIC_IRQ_SHOW + def_bool n + config GENERIC_PENDING_IRQ def_bool n
kernel/irq/proc.c +68 -0
77 lines not on this page · raw message
PATCH 31/75 genirq: Fixup core code namespace fallout
In reply to Thomas Gleixner--- kernel/irq/chip.c | 6 +++--- kernel/irq/manage.c | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-)
kernel/irq/chip.c +3 -3
@@ -616,7 +616,7 @@ out_unlock:void handle_percpu_irq (unsigned int irq,struct irq_desc *desc) { -struct irq_chip *chip =get_irq_desc_chip (desc); +struct irq_chip *chip =irq_desc_get_chip (desc);kstat_incr_irqs_this_cpu (irq, desc);
@@ -683,7 +683,7 @@ void set_irq_chip_and_handler(unsigned int irq, struct irq_chip *chip, irq_flow_handler_t handle) { -set_irq_chip (irq, chip); +irq_set_chip (irq, chip);__set_irq_handler (irq, handle,0 ,NULL ); }
@@ -691,7 +691,7 @@ void set_irq_chip_and_handler_name(unsigned int irq, struct irq_chip *chip, irq_flow_handler_t handle, const char *name) { -set_irq_chip (irq, chip); +irq_set_chip (irq, chip);__set_irq_handler (irq, handle,0 , name); }
kernel/irq/manage.c +1 -1
@@ -260,7 +260,7 @@ EXPORT_SYMBOL_GPL(irq_set_affinity_notifstatic int setup_affinity (unsigned int irq,struct irq_desc *desc,struct cpumask *mask) { -struct irq_chip *chip =get_irq_desc_chip (desc); +struct irq_chip *chip =irq_desc_get_chip (desc);struct cpumask *set = irq_default_affinity;int ret;
PATCH 32/75 genirq: Add internal state field to irq_desc
In reply to Thomas GleixnerThat field will contain internal state information which is not going to be exposed to anything outside the core code - except via accessor functions. I'm tired of everyone fiddling in irq_desc.status.
core_internal_state__do_not_mess_with_it is clear enough, annoying to type and easy to grep for. Offenders will be tracked down and slapped with stinking trouts.
--- include/linux/irqdesc.h | 3 ++- kernel/irq/internals.h | 6 ++++++ 2 files changed, 8 insertions(+), 1 deletion(-)
include/linux/irqdesc.h +2 -1
@@ -19,6 +19,7 @@ struct timer_rand_state;* @handle_irq: highlevel irq-events handler [if NULL, __do_IRQ()] * @action: the irq action chain * @status: status information +* @core_internal_state__do_not_mess_with_it: core internal 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
@@ -63,7 +64,7 @@ struct irq_desc {irq_flow_handler_t handle_irq;struct irqaction *action;/* IRQ action list */ unsigned int status;/* IRQ status */ - +unsigned int core_internal_state__do_not_mess_with_it;unsigned int depth;/* nested irq disables */ unsigned int wake_depth;/* nested wake enables */ unsigned int irq_count;/* For detecting broken IRQs */
kernel/irq/internals.h +6 -0
@@ -1,8 +1,14 @@/* * IRQ subsystem internal functions and variables: +* +* Do not ever include this file from anything else than +* kernel/irq/. Do not even think about using any information outside +* of this file for your non core code. */ #include <linux/irqdesc.h> +#define istate core_internal_state__do_not_mess_with_it +extern int noirqdebug;/*
PATCH 33/75 gpio: Remove broken irq_desc hackery.
In reply to Thomas GleixnerNo code outside of core is supposed to fiddle with this. If there is something missing in core, then talk to me and we'll fix it. But fiddling in core guts just because it can be done is a nono. Using it unlocked and writing a comment about it is ....
--- drivers/gpio/gpiolib.c | 44 -------------------------------------------- 1 file changed, 44 deletions(-)
drivers/gpio/gpiolib.c +0 -44
@@ -1657,50 +1657,6 @@ static void gpiolib_dbg_show(struct seq_ ? (chip->get (chip, i) ?"hi" :"lo" ) : "? "); -if (!is_out) { -int irq =gpio_to_irq (gpio); -struct irq_desc *desc =irq_to_desc (irq); - -/* This races with request_irq(), set_irq_type(), -* and set_irq_wake() ... but those are "rare". -* -* More significantly, trigger type flags aren't -* currently maintained by genirq. -*/ -if (irq >=0 && desc->action) { -char *trigger; - -switch (desc->status &IRQ_TYPE_SENSE_MASK ) { -case IRQ_TYPE_NONE : - trigger ="(default)" ; -break ; -case IRQ_TYPE_EDGE_FALLING : - trigger ="edge-falling" ; -break ; -case IRQ_TYPE_EDGE_RISING : - trigger ="edge-rising" ; -break ; -case IRQ_TYPE_EDGE_BOTH : - trigger ="edge-both" ; -break ; -case IRQ_TYPE_LEVEL_HIGH : - trigger ="level-high" ; -break ; -case IRQ_TYPE_LEVEL_LOW : - trigger ="level-low" ; -break ; -default : - trigger ="?trigger?" ; -break ; - } - -seq_printf (s," irq-%d %s%s" , - irq, trigger, - (desc->status &IRQ_WAKEUP ) - ?" wakeup" :"" ); - } - } -seq_printf (s,"\n" ); } }
Re: [patch 33/75] gpio: Remove broken irq_desc hackery.
Quoted 4 lines · Thomas Gleixner
No code outside of core is supposed to fiddle with this. If there is something missing in core, then talk to me and we'll fix it. But fiddling in core guts just because it can be done is a nono. Using it unlocked and writing a comment about it is ....
I guess including <irq.h> should go then as well?
Regards,
Wolfram
Signature · 2 lines
Pengutronix e.K. | Wolfram Sang | Industrial Linux Solutions | http://www.pengutronix.de/ |
PATCH 34/75 arm: ep93xx: Kill another instance of broken irq_desc fiddling
In reply to Thomas Gleixner1. This is a copy of the borked code in gpiolib
2. If you need information about irq state which is not exposed, then talk to the maintainer of that code instead of adding totaly horrible open coded access.
--- arch/arm/mach-ep93xx/gpio.c | 38 -------------------------------------- 1 file changed, 38 deletions(-)
arch/arm/mach-ep93xx/gpio.c +0 -38
@@ -354,44 +354,6 @@ static void ep93xx_gpio_dbg_show(struct is_out ?"out" :"in " , (data_reg & (1 << i)) ? "hi" : "lo"); -if (!is_out) { -int irq =gpio_to_irq (gpio); -struct irq_desc *desc = irq_desc + irq; - -if (irq >=0 && desc->action) { -char *trigger; - -switch (desc->status &IRQ_TYPE_SENSE_MASK ) { -case IRQ_TYPE_NONE : - trigger ="(default)" ; -break ; -case IRQ_TYPE_EDGE_FALLING : - trigger ="edge-falling" ; -break ; -case IRQ_TYPE_EDGE_RISING : - trigger ="edge-rising" ; -break ; -case IRQ_TYPE_EDGE_BOTH : - trigger ="edge-both" ; -break ; -case IRQ_TYPE_LEVEL_HIGH : - trigger ="level-high" ; -break ; -case IRQ_TYPE_LEVEL_LOW : - trigger ="level-low" ; -break ; -default : - trigger ="?trigger?" ; -break ; - } - -seq_printf (s," irq-%d %s%s" , - irq, trigger, - (desc->status &IRQ_WAKEUP ) - ?" wakeup" :"" ); - } - } -seq_printf (s,"\n" ); } }
RE: [patch 34/75] arm: ep93xx: Kill another instance of broken irq_desc fiddling
Quoted 9 lines · Thomas Gleixner
1. This is a copy of the borked code in gpiolib
2. If you need information about irq state which is not exposed, then talk to the maintainer of that code instead of adding totaly horrible open coded access.Signed-off-by Thomas Gleixner <[email protected]>Cc Hartley Sweeten <[email protected]>Cc Russell King <[email protected]>
As stated, this was following what was provided in gpiolib.
The information was only provided by debugfs to help development. It's not necessarily needed.
Minor note below. But otherwise,
Quoted 41 lines
--- arch/arm/mach-ep93xx/gpio.c | 38 -------------------------------------- 1 file changed, 38 deletions(-)Index:
linux-2.6-tip/arch/arm/mach-ep93xx/gpio.c
===================================================================arch/arm/mach-ep93xx/gpio.c +0
-29@@ -354,44 +354,6 @@ static void ep93xx_gpio_dbg_show(struct is_out ?"out" :"in " , (data_reg & (1 << i)) ? "hi" : "lo"); -if (!is_out) { -int irq =gpio_to_irq (gpio); -struct irq_desc *desc = irq_desc + irq; - -if (irq >=0 && desc->action) { -char *trigger; - -switch (desc->status &IRQ_TYPE_SENSE_MASK ) { -case IRQ_TYPE_NONE : - trigger ="(default)" ; -break ; -case IRQ_TYPE_EDGE_FALLING : - trigger ="edge-falling" ; -break ; -case IRQ_TYPE_EDGE_RISING : - trigger ="edge-rising" ; -break ; -case IRQ_TYPE_EDGE_BOTH : - trigger ="edge-both" ; -break ; -case IRQ_TYPE_LEVEL_HIGH : - trigger ="level-high" ; -break ; -case IRQ_TYPE_LEVEL_LOW : - trigger ="level-low" ; -break ; -default : - trigger ="?trigger?" ; -break ;
arch/arm/mach-ep93xx/gpio.c static void ep93xx_gpio_dbg_show(struct · line 357
Quoted 10 lines
arch/arm/mach-ep93xx/gpio.c +0
-9- } - -seq_printf (s," irq-%d %s%s" , - irq, trigger, - (desc->status &IRQ_WAKEUP ) - ?" wakeup" :"" ); - } - } -seq_printf (s,"\n" );
This could just be merged into the previous seq_printf().
For that matter, the is_out variable could be removed and just code the test into the seq_printf().
Quoted 2 lines
arch/arm/mach-ep93xx/gpio.c +0
-0} }
Re: [patch 34/75] arm: ep93xx: Kill another instance of broken irq_desc fiddling
In reply to Thomas GleixnerQuoted 4 lines · Thomas Gleixner
1. This is a copy of the borked code in gpiolib
2. If you need information about irq state which is not exposed, then talk to the maintainer of that code instead of adding totaly horrible open coded access.
This code got added simply because it is sometimes helpful to be able to see how various gpio/irq pins are configured. I'm happy to drop the functionality (see below), but is there a better way to get this information? Is it already available somewhere else (proc, sys)?
Quoted 12 lines
Signed-off-by Thomas Gleixner <[email protected]>Cc Hartley Sweeten <[email protected]>Cc Russell King <[email protected]>--- arch/arm/mach-ep93xx/gpio.c | 38 -------------------------------------- 1 file changed, 38 deletions(-)Index:
linux-2.6-tip/arch/arm/mach-ep93xx/gpio.c
===================================================================
arch/arm/mach-ep93xx/gpio.c static void ep93xx_gpio_dbg_show(struct · line 361
Quoted 8 lines
arch/arm/mach-ep93xx/gpio.c +0
-5@@ -354,44 +354,6 @@ static void ep93xx_gpio_dbg_show(struct is_out ?"out" :"in " , (data_reg & (1 << i)) ? "hi" : "lo"); -if (!is_out) { -int irq =gpio_to_irq (gpio); -struct irq_desc *desc = irq_desc + irq; - -if (irq >=0 && desc->action) {
Would be nice to at least keep the fact that the gpio is configured as an interrupt. Something like:
if (!is_out) {
int irq;
irq = gpio_to_irq(gpio);
if (irq >= 0)
seq_printf(s, " (irq %d)", irq);
}I'm okay with this patch as-is though. We can add a corrected patch later if we decided that it is still useful to have this information.
~Ryan
Signature · 7 lines
Bluewater Systems Ltd - ARM Technology Solution Centre Ryan Mallon 5 Amuri Park, 404 Barbadoes St [email protected] PO Box 13 889, Christchurch 8013 http://www.bluewatersys.com New Zealand Phone: +64 3 3779127 Freecall: Australia 1800 148 751 Fax: +64 3 3779135 USA 1800 261 2934
Re: [patch 34/75] arm: ep93xx: Kill another instance of broken irq_desc fiddling
Quoted 10 lines · Ryan Mallon
Quoted 4 lines · Thomas Gleixner
1. This is a copy of the borked code in gpiolib
2. If you need information about irq state which is not exposed, then talk to the maintainer of that code instead of adding totaly horrible open coded access.This code got added simply because it is sometimes helpful to be able to see how various gpio/irq pins are configured. I'm happy to drop the functionality (see below), but is there a better way to get this information? Is it already available somewhere else (proc, sys)?
No, but we can add that if it's required in a sane form.
I don't have objections to expose debug informations in general, but I have objections that random code does this especially, when it's duplicated random code :)
Thanks,
tglx
Re: [patch 34/75] arm: ep93xx: Kill another instance of broken irq_desc fiddling
Quoted 11 lines · Thomas Gleixner
Quoted 9 lines · Ryan Mallon
Quoted 4 lines · Thomas Gleixner
1. This is a copy of the borked code in gpiolib
2. If you need information about irq state which is not exposed, then talk to the maintainer of that code instead of adding totaly horrible open coded access.This code got added simply because it is sometimes helpful to be able to see how various gpio/irq pins are configured. I'm happy to drop the functionality (see below), but is there a better way to get this information? Is it already available somewhere else (proc, sys)?
Quoted 6 lines
No, but we can add that if it's required in a sane form.
I don't have objections to expose debug informations in general, but I have objections that random code does this especially, when it's duplicated random code :)
Ok. Does it make sense to expose the interrupt configuration for all interrupts via proc, sys, debug, etc? Is this information useful to enough people to warrant it? I would rather have a global debug rather than individual platforms and drivers implementing it.
For the time being can we fix up the ep93xx gpio code with the amended patch below. It keeps the information that the pin is also configured as an interrupt and cleans the code up a bit.
---
arch/arm/mach-ep93xx/gpio.c +4 -42
@@ -347,52 +347,14 @@ static void ep93xx_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) gpio = ep93xx_chip->chip.base;for (i =0 ; i< chip->ngpio; i++, gpio++) {int is_out = data_dir_reg& (1 << i); +int irq =gpio_to_irq (gpio); -seq_printf (s," %s%d gpio-%-3d (%-12s) %s %s" , +seq_printf (s," %s%d gpio-%-3d (%-12s) %s %s %s\n" , chip->label, i, gpio,gpiochip_is_requested (chip, i) ? :"" , is_out ?"out" :"in " , - (data_reg& (1 << i)) ?"hi" :"lo" ); - -if (!is_out) { -int irq =gpio_to_irq (gpio); -struct irq_desc *desc = irq_desc + irq; - -if (irq>=0 && desc->action) { -char *trigger; - -switch (desc->status&IRQ_TYPE_SENSE_MASK ) { -case IRQ_TYPE_NONE : - trigger ="(default)" ; -break ; -case IRQ_TYPE_EDGE_FALLING : - trigger ="edge-falling" ; -break ; -case IRQ_TYPE_EDGE_RISING : - trigger ="edge-rising" ; -break ; -case IRQ_TYPE_EDGE_BOTH : - trigger ="edge-both" ; -break ; -case IRQ_TYPE_LEVEL_HIGH : - trigger ="level-high" ; -break ; -case IRQ_TYPE_LEVEL_LOW : - trigger ="level-low" ; -break ; -default : - trigger ="?trigger?" ; -break ; - } - -seq_printf (s," irq-%d %s%s" , - irq, trigger, - (desc->status&IRQ_WAKEUP ) - ?" wakeup" :"" ); - } - } - -seq_printf (s,"\n" ); + (data_reg& (1 << i)) ?"hi" :"lo" , + (!is_out&& irq>=0 ) ?"(interrupt)" :"" ); } }
PATCH 35/75 genirq: Protect tglx from tripping over his own feet
In reply to Thomas GleixnerThe irq_desc.status field will either go away or renamed to settings. Anyway we need to maintain compatibility to avoid breaking the world and some more. While moving bits into the core, I need to avoid that I use any of the still existing IRQ_ bits in the core code by typos. So that file will hold the inline wrappers and some nasty CPP tricks to break the build when typoed.
--- kernel/irq/internals.h | 2 ++ kernel/irq/irqdesc.c | 4 ++-- kernel/irq/settings.h | 7 +++++++ 3 files changed, 11 insertions(+), 2 deletions(-)
kernel/irq/internals.h +2 -0
@@ -7,6 +7,8 @@*/ #include <linux/irqdesc.h> +#include "settings.h" +#define istate core_internal_state__do_not_mess_with_itextern int noirqdebug;
kernel/irq/irqdesc.c +2 -2
@@ -79,7 +79,7 @@ static void desc_set_defaults(unsigned i desc->irq_data.chip_data =NULL ; desc->irq_data.handler_data =NULL ; desc->irq_data.msi_desc =NULL ; - desc->status =IRQ_DEFAULT_INIT_FLAGS ; + desc->status = _IRQ_DEFAULT_INIT_FLAGS; desc->handle_irq = handle_bad_irq; desc->depth =1 ; desc->irq_count =0 ;
@@ -229,7 +229,7 @@ int __init early_irq_init(void) struct irq_desc irq_desc[NR_IRQS] __cacheline_aligned_in_smp = { [0 ...NR_IRQS -1 ] = { - .status =IRQ_DEFAULT_INIT_FLAGS , + .status = _IRQ_DEFAULT_INIT_FLAGS, .handle_irq = handle_bad_irq, .depth =1 , .lock =__RAW_SPIN_LOCK_UNLOCKED (irq_desc->lock),
kernel/irq/settings.h new file +7 -0
@@ -0,0 +1,7 @@ +/* +* Internal header to deal with irq_desc->status which will be renamed +* to irq_desc->settings. +*/ +enum { + _IRQ_DEFAULT_INIT_FLAGS =IRQ_DEFAULT_INIT_FLAGS , +};
PATCH 36/75 genirq: Move IRQ_AUTODETECT to internal state
In reply to Thomas GleixnerNo users outside of core
--- include/linux/irq.h | 1 - kernel/irq/autoprobe.c | 29 ++++++++++++----------------- kernel/irq/internals.h | 15 +++++++++++++-- kernel/irq/manage.c | 3 ++- 4 files changed, 27 insertions(+), 21 deletions(-)
include/linux/irq.h +0 -1
@@ -54,7 +54,6 @@ typedef void (*irq_flow_handler_t)(unsig#define IRQ_DISABLED 0x00000200/* IRQ disabled - do not enter! */ #define IRQ_PENDING 0x00000400/* IRQ pending - replay on enable */ #define IRQ_REPLAY 0x00000800/* IRQ has been replayed but not acked yet */ -#define IRQ_AUTODETECT 0x00001000/* IRQ is being autodetected */ #define IRQ_WAITING 0x00002000/* IRQ not yet seen - for autodetection */ #define IRQ_LEVEL 0x00004000/* IRQ level triggered */ #define IRQ_MASKED 0x00008000/* IRQ masked - shouldn't be seen again */
kernel/irq/autoprobe.c +12 -17
@@ -32,7 +32,6 @@ unsigned long probe_irq_on(void) {struct irq_desc *desc;unsigned long mask =0 ; -unsigned int status;int i;/*
@@ -76,7 +75,8 @@ unsigned long probe_irq_on(void)for_each_irq_desc_reverse (i, desc) {raw_spin_lock_irq (&desc->lock);if (!desc->action && !(desc->status &IRQ_NOPROBE )) { - desc->status |=IRQ_AUTODETECT |IRQ_WAITING ; + desc->istate |=IRQS_AUTODETECT ; + desc->status |=IRQ_WAITING ;if (irq_startup (desc)) desc->status |=IRQ_PENDING ; }
@@ -93,12 +93,11 @@ unsigned long probe_irq_on(void)*/ for_each_irq_desc (i, desc) {raw_spin_lock_irq (&desc->lock); - status = desc->status; -if (status &IRQ_AUTODETECT ) { +if (desc->istate &IRQS_AUTODETECT ) {/* It triggered already - consider it spurious. */ -if (!(status &IRQ_WAITING )) { - desc->status = status & ~IRQ_AUTODETECT ; +if (!(desc->status &IRQ_WAITING )) { + desc->istate &= ~IRQS_AUTODETECT ;irq_shutdown (desc); }else if (i <32 )
@@ -125,19 +124,17 @@ EXPORT_SYMBOL(probe_irq_on);*/ unsigned int probe_irq_mask (unsigned long val) { -unsigned int status, mask =0 ; +unsigned int mask =0 ;struct irq_desc *desc;int i;for_each_irq_desc (i, desc) {raw_spin_lock_irq (&desc->lock); - status = desc->status; - -if (status &IRQ_AUTODETECT ) { -if (i <16 && !(status &IRQ_WAITING )) +if (desc->istate &IRQS_AUTODETECT ) { +if (i <16 && !(desc->status &IRQ_WAITING )) mask |=1 << i; - desc->status = status & ~IRQ_AUTODETECT ; + desc->istate &= ~IRQS_AUTODETECT ;irq_shutdown (desc); }raw_spin_unlock_irq (&desc->lock);
@@ -169,19 +166,17 @@ int probe_irq_off(unsigned long val) {int i, irq_found =0 , nr_of_irqs =0 ;struct irq_desc *desc; -unsigned int status;for_each_irq_desc (i, desc) {raw_spin_lock_irq (&desc->lock); - status = desc->status; -if (status &IRQ_AUTODETECT ) { -if (!(status &IRQ_WAITING )) { +if (desc->istate &IRQS_AUTODETECT ) { +if (!(desc->status &IRQ_WAITING )) {if (!nr_of_irqs) irq_found = i; nr_of_irqs++; } - desc->status = status & ~IRQ_AUTODETECT ; + desc->istate &= ~IRQS_AUTODETECT ;irq_shutdown (desc); }raw_spin_unlock_irq (&desc->lock);
kernel/irq/internals.h +13 -2
@@ -27,6 +27,15 @@ enum { IRQTF_AFFINITY, }; +/* +* Bit masks for desc->state +* +* IRQS_AUTODETECT - autodetection in progress +*/ +enum { +IRQS_AUTODETECT =0x00000001 , +}; +#define irq_data_to_desc (data) container_of(data, struct irq_desc, irq_data)/* Set default functions for irq_chip structures: */
@@ -93,6 +102,7 @@ static inline void chip_bus_sync_unlock(#include <linux/kallsyms.h> #define P (f) if (desc->status & f) printk("%14s set\n", #f) +#define PS (f) if (desc->istate & f) printk("%14s set\n", #f)static inline void print_irq_desc (unsigned int irq,struct irq_desc *desc) {
@@ -112,7 +122,6 @@ static inline void print_irq_desc(unsignP (IRQ_DISABLED );P (IRQ_PENDING );P (IRQ_REPLAY ); -P (IRQ_AUTODETECT );P (IRQ_WAITING );P (IRQ_LEVEL );P (IRQ_MASKED );
@@ -122,7 +131,9 @@ static inline void print_irq_desc(unsignP (IRQ_NOPROBE );P (IRQ_NOREQUEST );P (IRQ_NOAUTOEN ); + +PS (IRQS_AUTODETECT ); }#undef P - +#undef PS
kernel/irq/manage.c +2 -1
@@ -903,8 +903,9 @@ __setup_irq(unsigned int irq, struct irq desc->status |=IRQ_PER_CPU ;#endif - desc->status &= ~(IRQ_AUTODETECT |IRQ_WAITING |IRQ_ONESHOT | + desc->status &= ~(IRQ_WAITING |IRQ_ONESHOT |IRQ_INPROGRESS |IRQ_SPURIOUS_DISABLED ); + desc->istate &= ~IRQS_AUTODETECT ;if (new->flags &IRQF_ONESHOT ) desc->status |=IRQ_ONESHOT ;
PATCH 37/75 genirq: Move IRQ_SPURIOUS_DISABLED to core state
In reply to Thomas GleixnerNo users outside.
--- include/linux/irq.h | 1 - kernel/irq/internals.h | 3 +++ kernel/irq/manage.c | 9 ++++----- kernel/irq/spurious.c | 8 ++++---- 4 files changed, 11 insertions(+), 10 deletions(-)
include/linux/irq.h +0 -1
@@ -64,7 +64,6 @@ typedef void (*irq_flow_handler_t)(unsig#define IRQ_WAKEUP 0x00100000/* IRQ triggers system wakeup */ #define IRQ_MOVE_PENDING 0x00200000/* need to re-target IRQ destination */ #define IRQ_NO_BALANCING 0x00400000/* IRQ is excluded from balancing */ -#define IRQ_SPURIOUS_DISABLED 0x00800000/* IRQ was disabled by the spurious trap */ #define IRQ_MOVE_PCNTXT 0x01000000/* IRQ migration from process context */ #define IRQ_AFFINITY_SET 0x02000000/* IRQ affinity was set from userspace*/ #define IRQ_SUSPENDED 0x04000000/* IRQ has gone through suspend sequence */
kernel/irq/internals.h +3 -0
@@ -31,9 +31,12 @@ enum {* Bit masks for desc->state * * IRQS_AUTODETECT - autodetection in progress +* IRQS_SPURIOUS_DISABLED - was disabled due to spurious interrupt +* detection */ enum {IRQS_AUTODETECT =0x00000001 , +IRQS_SPURIOUS_DISABLED =0x00000002 , };#define irq_data_to_desc (data) container_of(data, struct irq_desc, irq_data)
kernel/irq/manage.c +4 -5
@@ -903,9 +903,8 @@ __setup_irq(unsigned int irq, struct irq desc->status |=IRQ_PER_CPU ;#endif - desc->status &= ~(IRQ_WAITING |IRQ_ONESHOT | -IRQ_INPROGRESS |IRQ_SPURIOUS_DISABLED ); - desc->istate &= ~IRQS_AUTODETECT ; + desc->status &= ~(IRQ_WAITING |IRQ_ONESHOT |IRQ_INPROGRESS ); + desc->istate &= ~(IRQS_AUTODETECT |IRQS_SPURIOUS_DISABLED );if (new->flags &IRQF_ONESHOT ) desc->status |=IRQ_ONESHOT ;
@@ -943,8 +942,8 @@ __setup_irq(unsigned int irq, struct irq* Check whether we disabled the irq via the spurious handler * before. Reenable it and give it another chance. */ -if (shared && (desc->status &IRQ_SPURIOUS_DISABLED )) { - desc->status &= ~IRQ_SPURIOUS_DISABLED ; +if (shared && (desc->istate &IRQS_SPURIOUS_DISABLED )) { + desc->istate &= ~IRQS_SPURIOUS_DISABLED ;__enable_irq (desc, irq, false); }
kernel/irq/spurious.c +4 -4
@@ -146,15 +146,15 @@ static void poll_spurious_irqs(unsigned irq_poll_cpu =smp_processor_id ();for_each_irq_desc (i, desc) { -unsigned int status; +unsigned int state;if (!i)continue ;/* Racy but it doesn't matter */ - status = desc->status; + state = desc->istate;barrier (); -if (!(status &IRQ_SPURIOUS_DISABLED )) +if (!(state &IRQS_SPURIOUS_DISABLED ))continue ;local_irq_disable ();
@@ -298,7 +298,7 @@ void note_interrupt(unsigned int irq, st* Now kill the IRQ */ printk (KERN_EMERG "Disabling IRQ #%d\n" , irq); - desc->status |=IRQ_SPURIOUS_DISABLED ; + desc->istate |=IRQS_SPURIOUS_DISABLED ; desc->depth++;irq_disable (desc);
PATCH 38/75 genirq: Move IRQ_NESTED_THREAD to core state
In reply to Thomas GleixnerNo users outside of core.
--- include/linux/irq.h | 1 - kernel/irq/chip.c | 10 +++++----- kernel/irq/internals.h | 3 +++ kernel/irq/manage.c | 4 ++-- kernel/irq/spurious.c | 2 +- 5 files changed, 11 insertions(+), 9 deletions(-)
include/linux/irq.h +0 -1
@@ -68,7 +68,6 @@ typedef void (*irq_flow_handler_t)(unsig#define IRQ_AFFINITY_SET 0x02000000/* IRQ affinity was set from userspace*/ #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_POLL_INPROGRESS 0x20000000/* IRQ poll is in progress */ #define IRQF_MODIFY_MASK \
kernel/irq/chip.c +5 -5
@@ -163,12 +163,12 @@ struct irq_data *irq_get_irq_data(unsignEXPORT_SYMBOL_GPL (irq_get_irq_data);/** -* set_irq_nested_thread - Set/Reset the IRQ_NESTED_THREAD flag of an irq +* set_irq_nested_thread - Set/Reset the IRQS_NESTED_THREAD flag of an irq * * @irq: Interrupt number -* @nest: 0 to clear / 1 to set the IRQ_NESTED_THREAD flag +* @nest: 0 to clear / 1 to set the IRQS_NESTED_THREAD flag * -* The IRQ_NESTED_THREAD flag indicates that on +* The IRQS_NESTED_THREAD flag indicates that on * request_threaded_irq() no separate interrupt thread should be * created for the irq as the handler are called nested in the * context of a demultiplexing interrupt handler thread.
@@ -183,9 +183,9 @@ void set_irq_nested_thread(unsigned intraw_spin_lock_irqsave (&desc->lock, flags);if (nest) - desc->status |=IRQ_NESTED_THREAD ; + desc->istate |=IRQS_NESTED_THREAD ;else - desc->status &= ~IRQ_NESTED_THREAD ; + desc->istate &= ~IRQS_NESTED_THREAD ;raw_spin_unlock_irqrestore (&desc->lock, flags); }EXPORT_SYMBOL_GPL (set_irq_nested_thread);
kernel/irq/internals.h +3 -0
@@ -33,10 +33,13 @@ enum {* IRQS_AUTODETECT - autodetection in progress * IRQS_SPURIOUS_DISABLED - was disabled due to spurious interrupt * detection +* IRQS_NESTED_THREAD - nested into another threaded handler +* no own irq thread. */ enum {IRQS_AUTODETECT =0x00000001 ,IRQS_SPURIOUS_DISABLED =0x00000002 , +IRQS_NESTED_THREAD =0x00000004 , };#define irq_data_to_desc (data) container_of(data, struct irq_desc, irq_data)
kernel/irq/manage.c +2 -2
@@ -812,7 +812,7 @@ __setup_irq(unsigned int irq, struct irq* Check whether the interrupt nests into another interrupt * thread. */ - nested = desc->status &IRQ_NESTED_THREAD ; + nested = desc->istate &IRQS_NESTED_THREAD ;if (nested) {if (!new->thread_fn)return -EINVAL ;
@@ -1276,7 +1276,7 @@ int request_any_context_irq(unsigned intif (!desc)return -EINVAL ; -if (desc->status &IRQ_NESTED_THREAD ) { +if (desc->istate &IRQS_NESTED_THREAD ) { ret =request_threaded_irq (irq,NULL , handler, flags, name, dev_id);return !ret ?IRQC_IS_NESTED : ret;
kernel/irq/spurious.c +1 -1
@@ -68,7 +68,7 @@ static int try_one_irq(int irq, struct iraw_spin_lock (&desc->lock);/* PER_CPU and nested thread interrupts are never polled */ -if (desc->status & (IRQ_PER_CPU |IRQ_NESTED_THREAD )) +if ((desc->status &IRQ_PER_CPU ) || (desc->istate &IRQS_NESTED_THREAD )) goto out;/*
PATCH 39/75 genirq: Move IRQ_POLL_INPROGRESS to core
In reply to Thomas GleixnerNo users outside of core.
--- include/linux/irq.h | 1 - kernel/irq/chip.c | 2 +- kernel/irq/internals.h | 2 ++ kernel/irq/spurious.c | 6 +++--- 4 files changed, 6 insertions(+), 5 deletions(-)
include/linux/irq.h +0 -1
@@ -68,7 +68,6 @@ typedef void (*irq_flow_handler_t)(unsig#define IRQ_AFFINITY_SET 0x02000000/* IRQ affinity was set from userspace*/ #define IRQ_SUSPENDED 0x04000000/* IRQ has gone through suspend sequence */ #define IRQ_ONESHOT 0x08000000/* IRQ is not unmasked after hardirq */ -#define IRQ_POLL_INPROGRESS 0x20000000/* IRQ poll is in progress */ #define IRQF_MODIFY_MASK \ (IRQ_TYPE_SENSE_MASK | IRQ_NOPROBE | IRQ_NOREQUEST | \
kernel/irq/chip.c +1 -1
@@ -426,7 +426,7 @@ EXPORT_SYMBOL_GPL(handle_nested_irq);static bool irq_check_poll (struct irq_desc *desc) { -if (!(desc->status &IRQ_POLL_INPROGRESS )) +if (!(desc->istate &IRQS_POLL_INPROGRESS ))return false;return irq_wait_for_poll (desc); }
kernel/irq/internals.h +2 -0
@@ -35,11 +35,13 @@ enum {* detection * IRQS_NESTED_THREAD - nested into another threaded handler * no own irq thread. +* IRQS_POLL_INPROGRESS - polling in progress */ enum {IRQS_AUTODETECT =0x00000001 ,IRQS_SPURIOUS_DISABLED =0x00000002 ,IRQS_NESTED_THREAD =0x00000004 , +IRQS_POLL_INPROGRESS =0x00000008 , };#define irq_data_to_desc (data) container_of(data, struct irq_desc, irq_data)
kernel/irq/spurious.c +3 -3
@@ -98,13 +98,13 @@ static int try_one_irq(int irq, struct i }/* Mark it poll in progress */ - desc->status |=IRQ_POLL_INPROGRESS ; + desc->istate |=IRQS_POLL_INPROGRESS ;do {if (handle_irq_event (desc) ==IRQ_HANDLED ) ret =IRQ_HANDLED ; action = desc->action; }while ((desc->status &IRQ_PENDING ) && action); - desc->status &= ~IRQ_POLL_INPROGRESS ; + desc->istate &= ~IRQS_POLL_INPROGRESS ; out:raw_spin_unlock (&desc->lock);return ret ==IRQ_HANDLED ;
@@ -259,7 +259,7 @@ try_misrouted_irq(unsigned int irq, struvoid note_interrupt (unsigned int irq,struct irq_desc *desc,irqreturn_t action_ret) { -if (desc->status &IRQ_POLL_INPROGRESS ) +if (desc->istate &IRQS_POLL_INPROGRESS )return ;if (unlikely (action_ret !=IRQ_HANDLED )) {
PATCH 40/75 genirq: Add IRQ_INPROGRESS to core
In reply to Thomas GleixnerWe need to maintain the flag for now in both fields status and istate. Add a CONFIG_GENERIC_HARDIRQS_NO_COMPAT switch to allow testing w/o the status one. Wrap the access to status IRQ_INPROGRESS in a inline which can be turned of with CONFIG_GENERIC_HARDIRQS_NO_COMPAT along with the define.
There is no reason that anything outside of core looks at this. That needs some modifications, but we'll get there.
--- include/linux/irq.h | 6 +++++- kernel/irq/Kconfig | 3 +++ kernel/irq/chip.c | 16 +++++++++------- kernel/irq/compat.h | 17 +++++++++++++++++ kernel/irq/handle.c | 6 ++++-- kernel/irq/internals.h | 5 ++++- kernel/irq/manage.c | 17 +++++++++-------- kernel/irq/settings.h | 3 +++ kernel/irq/spurious.c | 6 +++--- 9 files changed, 57 insertions(+), 22 deletions(-)
include/linux/irq.h +5 -1
@@ -50,7 +50,11 @@ typedef void (*irq_flow_handler_t)(unsig#define IRQ_TYPE_PROBE 0x00000010/* Probing in progress */ /* Internal flags */ -#define IRQ_INPROGRESS 0x00000100/* IRQ handler active - do not enter! */ + +#ifndef CONFIG_GENERIC_HARDIRQS_NO_COMPAT +#define IRQ_INPROGRESS 0x00000100/* DEPRECATED */ +#endif +#define IRQ_DISABLED 0x00000200/* IRQ disabled - do not enter! */ #define IRQ_PENDING 0x00000400/* IRQ pending - replay on enable */ #define IRQ_REPLAY 0x00000800/* IRQ has been replayed but not acked yet */
kernel/irq/Kconfig +3 -0
@@ -13,6 +13,9 @@ config GENERIC_HARDIRQS config GENERIC_HARDIRQS_NO_DEPRECATED def_bool n +config GENERIC_HARDIRQS_NO_COMPAT + def_bool n + # Options selectable by the architecture code config HAVE_SPARSE_IRQ def_bool n
kernel/irq/chip.c +9 -7
@@ -409,7 +409,8 @@ void handle_nested_irq(unsigned int irq)if (unlikely (!action || (desc->status &IRQ_DISABLED ))) goto out_unlock; - desc->status |=IRQ_INPROGRESS ; +irq_compat_set_progress (desc); + desc->istate |=IRQS_INPROGRESS ;raw_spin_unlock_irq (&desc->lock); action_ret = action->thread_fn (action->irq, action->dev_id);
@@ -417,7 +418,8 @@ void handle_nested_irq(unsigned int irq)note_interrupt (irq, desc, action_ret);raw_spin_lock_irq (&desc->lock); - desc->status &= ~IRQ_INPROGRESS ; + desc->istate &= ~IRQS_INPROGRESS ; +irq_compat_clr_progress (desc); out_unlock:raw_spin_unlock_irq (&desc->lock);
@@ -448,7 +450,7 @@ handle_simple_irq(unsigned int irq, stru {raw_spin_lock (&desc->lock); -if (unlikely (desc->status &IRQ_INPROGRESS )) +if (unlikely (desc->istate &IRQS_INPROGRESS ))if (!irq_check_poll (desc)) goto out_unlock;
@@ -480,7 +482,7 @@ handle_level_irq(unsigned int irq, strucraw_spin_lock (&desc->lock);mask_ack_irq (desc); -if (unlikely (desc->status &IRQ_INPROGRESS )) +if (unlikely (desc->istate &IRQS_INPROGRESS ))if (!irq_check_poll (desc)) goto out_unlock;
@@ -518,7 +520,7 @@ handle_fasteoi_irq(unsigned int irq, str {raw_spin_lock (&desc->lock); -if (unlikely (desc->status &IRQ_INPROGRESS )) +if (unlikely (desc->istate &IRQS_INPROGRESS ))if (!irq_check_poll (desc)) goto out;
@@ -568,8 +570,8 @@ handle_edge_irq(unsigned int irq, struct* we shouldn't process the IRQ. Mark it pending, handle * the necessary masking and go out */ -if (unlikely ((desc->status & (IRQ_INPROGRESS |IRQ_DISABLED )) || - !desc->action)) { +if (unlikely ((desc->istate & (IRQS_INPROGRESS ) || + (desc->status &IRQ_DISABLED ) || !desc->action))) {if (!irq_check_poll (desc)) { desc->status |=IRQ_PENDING ;mask_ack_irq (desc);
kernel/irq/compat.h new file +17 -0
@@ -0,0 +1,17 @@ +/* +* Compat layer for transition period +*/ +#ifndef CONFIG_GENERIC_HARDIRQS_NO_COMPAT +static inline void irq_compat_set_progress (struct irq_desc *desc) +{ + desc->status |=IRQ_INPROGRESS ; +} + +static inline void irq_compat_clr_progress (struct irq_desc *desc) +{ + desc->status &= ~IRQ_INPROGRESS ; +} +#else +static inline void irq_compat_set_progress (struct irq_desc *desc) { } +static inline void irq_compat_clr_progress (struct irq_desc *desc) { } +#endif
kernel/irq/handle.c +4 -2
@@ -123,13 +123,15 @@ irqreturn_t handle_irq_event(struct irq_irqreturn_t ret; desc->status &= ~IRQ_PENDING ; - desc->status |=IRQ_INPROGRESS ; +irq_compat_set_progress (desc); + desc->istate |=IRQS_INPROGRESS ;raw_spin_unlock (&desc->lock); ret =handle_irq_event_percpu (desc, action);raw_spin_lock (&desc->lock); - desc->status &= ~IRQ_INPROGRESS ; + desc->istate &= ~IRQS_INPROGRESS ; +irq_compat_clr_progress (desc);return ret; }
kernel/irq/internals.h +4 -1
@@ -7,6 +7,7 @@*/ #include <linux/irqdesc.h> +#include "compat.h" #include "settings.h" #define istate core_internal_state__do_not_mess_with_it
@@ -36,12 +37,14 @@ enum {* IRQS_NESTED_THREAD - nested into another threaded handler * no own irq thread. * IRQS_POLL_INPROGRESS - polling in progress +* IRQS_INPROGRESS - Interrupt in progress */ enum {IRQS_AUTODETECT =0x00000001 ,IRQS_SPURIOUS_DISABLED =0x00000002 ,IRQS_NESTED_THREAD =0x00000004 ,IRQS_POLL_INPROGRESS =0x00000008 , +IRQS_INPROGRESS =0x00000010 , };#define irq_data_to_desc (data) container_of(data, struct irq_desc, irq_data)
@@ -126,7 +129,6 @@ static inline void print_irq_desc(unsignprint_symbol ("%s\n" , (unsigned long )desc->action->handler); } -P (IRQ_INPROGRESS );P (IRQ_DISABLED );P (IRQ_PENDING );P (IRQ_REPLAY );
@@ -141,6 +143,7 @@ static inline void print_irq_desc(unsignP (IRQ_NOAUTOEN );PS (IRQS_AUTODETECT ); +PS (IRQS_INPROGRESS ); }#undef P
kernel/irq/manage.c +9 -8
@@ -30,7 +30,7 @@void synchronize_irq (unsigned int irq) {struct irq_desc *desc =irq_to_desc (irq); -unsigned int status; +unsigned int state;if (!desc)return ;
@@ -42,16 +42,16 @@ void synchronize_irq(unsigned int irq)* Wait until we're out of the critical section. This might * give the wrong answer due to the lack of memory barriers. */ -while (desc->status &IRQ_INPROGRESS ) +while (desc->istate &IRQS_INPROGRESS )cpu_relax ();/* Ok, that indicated we're done: double-check carefully. */ raw_spin_lock_irqsave (&desc->lock, flags); - status = desc->status; + state = desc->istate;raw_spin_unlock_irqrestore (&desc->lock, flags);/* Oops, that failed? */ - }while (status &IRQ_INPROGRESS ); + }while (state &IRQS_INPROGRESS );/* * We made sure that no hardirq handler is running. Now verify
@@ -643,9 +643,9 @@ again:* The thread is faster done than the hard interrupt handler * on the other CPU. If we unmask the irq line then the * interrupt can come in again and masks the line, leaves due -* to IRQ_INPROGRESS and the irq line is masked forever. +* to IRQS_INPROGRESS and the irq line is masked forever. */ -if (unlikely (desc->status &IRQ_INPROGRESS )) { +if (unlikely (desc->istate &IRQS_INPROGRESS )) {raw_spin_unlock_irq (&desc->lock);chip_bus_sync_unlock (desc);cpu_relax ();
@@ -903,8 +903,9 @@ __setup_irq(unsigned int irq, struct irq desc->status |=IRQ_PER_CPU ;#endif - desc->status &= ~(IRQ_WAITING |IRQ_ONESHOT |IRQ_INPROGRESS ); - desc->istate &= ~(IRQS_AUTODETECT |IRQS_SPURIOUS_DISABLED ); + desc->status &= ~(IRQ_WAITING |IRQ_ONESHOT ); + desc->istate &= ~(IRQS_AUTODETECT |IRQS_SPURIOUS_DISABLED | \ +IRQS_INPROGRESS );if (new->flags &IRQF_ONESHOT ) desc->status |=IRQ_ONESHOT ;
kernel/irq/settings.h +3 -0
@@ -5,3 +5,6 @@enum { _IRQ_DEFAULT_INIT_FLAGS =IRQ_DEFAULT_INIT_FLAGS , }; + +#undef IRQ_INPROGRESS +#define IRQ_INPROGRESS GOT_YOU_MORON
kernel/irq/spurious.c +3 -3
@@ -45,10 +45,10 @@ bool irq_wait_for_poll(struct irq_desc *#ifdef CONFIG_SMP do {raw_spin_unlock (&desc->lock); -while (desc->status &IRQ_INPROGRESS ) +while (desc->istate &IRQS_INPROGRESS )cpu_relax ();raw_spin_lock (&desc->lock); - }while (desc->status &IRQ_INPROGRESS ); + }while (desc->istate &IRQS_INPROGRESS );/* Might have been disabled in meantime */ return !(desc->status &IRQ_DISABLED ) && desc->action;#else
@@ -88,7 +88,7 @@ static int try_one_irq(int irq, struct i goto out;/* Already running on another processor */ -if (desc->status &IRQ_INPROGRESS ) { +if (desc->istate &IRQS_INPROGRESS ) {/* * Already running: If it is shared get the other * CPU to go looking for our mystery interrupt too
PATCH 41/75 genirq: Move IRQ_ONESHOT to core
In reply to Thomas GleixnerNo users outside of core.
--- include/linux/irq.h | 1 - kernel/irq/chip.c | 2 +- kernel/irq/internals.h | 2 ++ kernel/irq/manage.c | 8 ++++---- 4 files changed, 7 insertions(+), 6 deletions(-)
include/linux/irq.h +0 -1
@@ -71,7 +71,6 @@ typedef void (*irq_flow_handler_t)(unsig#define IRQ_MOVE_PCNTXT 0x01000000/* IRQ migration from process context */ #define IRQ_AFFINITY_SET 0x02000000/* IRQ affinity was set from userspace*/ #define IRQ_SUSPENDED 0x04000000/* IRQ has gone through suspend sequence */ -#define IRQ_ONESHOT 0x08000000/* IRQ is not unmasked after hardirq */ #define IRQF_MODIFY_MASK \ (IRQ_TYPE_SENSE_MASK | IRQ_NOPROBE | IRQ_NOREQUEST | \
kernel/irq/chip.c +1 -1
@@ -498,7 +498,7 @@ handle_level_irq(unsigned int irq, struchandle_irq_event (desc); -if (!(desc->status & (IRQ_DISABLED |IRQ_ONESHOT ))) +if (!(desc->status &IRQ_DISABLED ) && !(desc->istate &IRQS_ONESHOT ))unmask_irq (desc); out_unlock:raw_spin_unlock (&desc->lock);
kernel/irq/internals.h +2 -0
@@ -38,6 +38,7 @@ enum {* no own irq thread. * IRQS_POLL_INPROGRESS - polling in progress * IRQS_INPROGRESS - Interrupt in progress +* IRQS_ONESHOT - irq is not unmasked in primary handler */ enum {IRQS_AUTODETECT =0x00000001 ,
@@ -45,6 +46,7 @@ enum {IRQS_NESTED_THREAD =0x00000004 ,IRQS_POLL_INPROGRESS =0x00000008 ,IRQS_INPROGRESS =0x00000010 , + IRQS_ONESHOT = 0x00000020, };#define irq_data_to_desc (data) container_of(data, struct irq_desc, irq_data)
kernel/irq/manage.c +4 -4
@@ -703,7 +703,7 @@ static int irq_thread(void *data) };struct irqaction *action = data;struct irq_desc *desc =irq_to_desc (action->irq); -int wake, oneshot = desc->status &IRQ_ONESHOT ; +int wake, oneshot = desc->istate &IRQS_ONESHOT ;sched_setscheduler (current,SCHED_FIFO , ¶m); current->irqaction = action;
@@ -903,12 +903,12 @@ __setup_irq(unsigned int irq, struct irq desc->status |=IRQ_PER_CPU ;#endif - desc->status &= ~(IRQ_WAITING |IRQ_ONESHOT ); + desc->status &= ~IRQ_WAITING ; desc->istate &= ~(IRQS_AUTODETECT |IRQS_SPURIOUS_DISABLED | \ -IRQS_INPROGRESS ); +IRQS_INPROGRESS |IRQS_ONESHOT );if (new->flags &IRQF_ONESHOT ) - desc->status |=IRQ_ONESHOT ; + desc->istate |=IRQS_ONESHOT ;if (!(desc->status &IRQ_NOAUTOEN ))irq_startup (desc);
PATCH 42/75 genirq: Move IRQ_REPLAY and IRQ_WAITING to core
In reply to Thomas GleixnerNo users outside of core.
--- include/linux/irq.h | 9 +++++---- kernel/irq/autoprobe.c | 11 +++++------ kernel/irq/chip.c | 9 ++++----- kernel/irq/internals.h | 8 ++++++-- kernel/irq/manage.c | 4 ++-- kernel/irq/resend.c | 7 +++++-- kernel/irq/settings.h | 4 ++++ 7 files changed, 31 insertions(+), 21 deletions(-)
include/linux/irq.h +5 -4
@@ -53,12 +53,13 @@ typedef void (*irq_flow_handler_t)(unsig#ifndef CONFIG_GENERIC_HARDIRQS_NO_COMPAT #define IRQ_INPROGRESS 0x00000100/* DEPRECATED */ +#define IRQ_REPLAY 0x00000200/* DEPRECATED */ +#define IRQ_WAITING 0x00000400/* DEPRECATED */ #endif -#define IRQ_DISABLED 0x00000200/* IRQ disabled - do not enter! */ -#define IRQ_PENDING 0x00000400/* IRQ pending - replay on enable */ -#define IRQ_REPLAY 0x00000800/* IRQ has been replayed but not acked yet */ -#define IRQ_WAITING 0x00002000/* IRQ not yet seen - for autodetection */ +#define IRQ_DISABLED 0x00000800/* IRQ disabled - do not enter! */ +#define IRQ_PENDING 0x00001000/* IRQ pending - replay on enable */ +#define IRQ_LEVEL 0x00004000/* IRQ level triggered */ #define IRQ_MASKED 0x00008000/* IRQ masked - shouldn't be seen again */ #define IRQ_PER_CPU 0x00010000/* IRQ is per CPU */
kernel/irq/autoprobe.c +5 -6
@@ -17,7 +17,7 @@/* * Autodetection depends on the fact that any interrupt that * comes in on to an unassigned handler will get stuck with -* "IRQ_WAITING" cleared and the interrupt disabled. +* "IRQS_WAITING" cleared and the interrupt disabled. */ static DEFINE_MUTEX (probing_active);
@@ -75,8 +75,7 @@ unsigned long probe_irq_on(void)for_each_irq_desc_reverse (i, desc) {raw_spin_lock_irq (&desc->lock);if (!desc->action && !(desc->status &IRQ_NOPROBE )) { - desc->istate |=IRQS_AUTODETECT ; - desc->status |=IRQ_WAITING ; + desc->istate |=IRQS_AUTODETECT |IRQS_WAITING ;if (irq_startup (desc)) desc->status |=IRQ_PENDING ; }
@@ -96,7 +95,7 @@ unsigned long probe_irq_on(void)if (desc->istate &IRQS_AUTODETECT ) {/* It triggered already - consider it spurious. */ -if (!(desc->status &IRQ_WAITING )) { +if (!(desc->istate &IRQS_WAITING )) { desc->istate &= ~IRQS_AUTODETECT ;irq_shutdown (desc); }else
@@ -131,7 +130,7 @@ unsigned int probe_irq_mask(unsigned lonfor_each_irq_desc (i, desc) {raw_spin_lock_irq (&desc->lock);if (desc->istate &IRQS_AUTODETECT ) { -if (i <16 && !(desc->status &IRQ_WAITING )) +if (i <16 && !(desc->istate &IRQS_WAITING )) mask |=1 << i; desc->istate &= ~IRQS_AUTODETECT ;
@@ -171,7 +170,7 @@ int probe_irq_off(unsigned long val)raw_spin_lock_irq (&desc->lock);if (desc->istate &IRQS_AUTODETECT ) { -if (!(desc->status &IRQ_WAITING )) { +if (!(desc->istate &IRQS_WAITING )) {if (!nr_of_irqs) irq_found = i; nr_of_irqs++;
kernel/irq/chip.c +4 -5
@@ -454,7 +454,7 @@ handle_simple_irq(unsigned int irq, struif (!irq_check_poll (desc)) goto out_unlock; - desc->status &= ~(IRQ_REPLAY |IRQ_WAITING ); + desc->istate &= ~(IRQS_REPLAY |IRQS_WAITING );kstat_incr_irqs_this_cpu (irq, desc);if (unlikely (!desc->action || (desc->status &IRQ_DISABLED )))
@@ -486,7 +486,7 @@ handle_level_irq(unsigned int irq, strucif (!irq_check_poll (desc)) goto out_unlock; - desc->status &= ~(IRQ_REPLAY |IRQ_WAITING ); + desc->istate &= ~(IRQS_REPLAY |IRQS_WAITING );kstat_incr_irqs_this_cpu (irq, desc);/*
@@ -524,7 +524,7 @@ handle_fasteoi_irq(unsigned int irq, strif (!irq_check_poll (desc)) goto out; - desc->status &= ~(IRQ_REPLAY |IRQ_WAITING ); + desc->istate &= ~(IRQS_REPLAY |IRQS_WAITING );kstat_incr_irqs_this_cpu (irq, desc);/*
@@ -563,8 +563,7 @@ handle_edge_irq(unsigned int irq, struct {raw_spin_lock (&desc->lock); - desc->status &= ~(IRQ_REPLAY |IRQ_WAITING ); - + desc->istate &= ~(IRQS_REPLAY |IRQS_WAITING );/* * If we're currently running this IRQ, or its disabled, * we shouldn't process the IRQ. Mark it pending, handle
kernel/irq/internals.h +6 -2
@@ -39,6 +39,8 @@ enum {* IRQS_POLL_INPROGRESS - polling in progress * IRQS_INPROGRESS - Interrupt in progress * IRQS_ONESHOT - irq is not unmasked in primary handler +* IRQS_REPLAY - irq is replayed +* IRQS_WAITING - irq is waiting */ enum {IRQS_AUTODETECT =0x00000001 ,
@@ -47,6 +49,8 @@ enum {IRQS_POLL_INPROGRESS =0x00000008 ,IRQS_INPROGRESS =0x00000010 ,IRQS_ONESHOT =0x00000020 , +IRQS_REPLAY =0x00000040 , + IRQS_WAITING = 0x00000080, };#define irq_data_to_desc (data) container_of(data, struct irq_desc, irq_data)
@@ -133,8 +137,6 @@ static inline void print_irq_desc(unsignP (IRQ_DISABLED );P (IRQ_PENDING ); -P (IRQ_REPLAY ); -P (IRQ_WAITING );P (IRQ_LEVEL );P (IRQ_MASKED );#ifdef CONFIG_IRQ_PER_CPU
@@ -146,6 +148,8 @@ static inline void print_irq_desc(unsignPS (IRQS_AUTODETECT );PS (IRQS_INPROGRESS ); +PS (IRQS_REPLAY ); +PS (IRQS_WAITING ); }#undef P
kernel/irq/manage.c +2 -2
@@ -903,9 +903,9 @@ __setup_irq(unsigned int irq, struct irq desc->status |=IRQ_PER_CPU ;#endif - desc->status &= ~IRQ_WAITING ; desc->istate &= ~(IRQS_AUTODETECT |IRQS_SPURIOUS_DISABLED | \ -IRQS_INPROGRESS |IRQS_ONESHOT ); +IRQS_INPROGRESS |IRQS_ONESHOT | \ +IRQS_WAITING );if (new->flags &IRQF_ONESHOT ) desc->istate |=IRQS_ONESHOT ;
kernel/irq/resend.c +5 -2
@@ -62,8 +62,11 @@ void check_irq_resend(struct irq_desc *d*/ if (desc->status &IRQ_LEVEL )return ; -if ((desc->status & (IRQ_PENDING |IRQ_REPLAY )) ==IRQ_PENDING ) { - desc->status = (desc->status & ~IRQ_PENDING ) |IRQ_REPLAY ; +if (desc->istate &IRQS_REPLAY ) +return ; +if (desc->status &IRQ_PENDING ) { + desc->status &=IRQ_PENDING ; + desc->istate |=IRQS_REPLAY ;if (!desc->irq_data.chip->irq_retrigger || !desc->irq_data.chip->irq_retrigger (&desc->irq_data)) {
kernel/irq/settings.h +4 -0
@@ -8,3 +8,7 @@ enum {#undef IRQ_INPROGRESS#define IRQ_INPROGRESS GOT_YOU_MORON +#undef IRQ_REPLAY +#define IRQ_REPLAY GOT_YOU_MORON +#undef IRQ_WAITING +#define IRQ_WAITING GOT_YOU_MORON
PATCH 43/75 genirq: Move IRQ_DISABLED to core
In reply to Thomas GleixnerKeep status in sync until all abusers are fixed.
--- include/linux/irq.h | 4 ++-- kernel/irq/chip.c | 48 +++++++++++++++++++++++++++++++----------------- kernel/irq/compat.h | 12 ++++++++++++ kernel/irq/internals.h | 4 +++- kernel/irq/irqdesc.c | 2 ++ kernel/irq/manage.c | 4 ++-- kernel/irq/migration.c | 2 +- kernel/irq/settings.h | 2 ++ kernel/irq/spurious.c | 4 ++-- 9 files changed, 57 insertions(+), 25 deletions(-)
include/linux/irq.h +2 -2
@@ -55,9 +55,9 @@ typedef void (*irq_flow_handler_t)(unsig#define IRQ_INPROGRESS 0x00000100/* DEPRECATED */ #define IRQ_REPLAY 0x00000200/* DEPRECATED */ #define IRQ_WAITING 0x00000400/* DEPRECATED */ +#define IRQ_DISABLED 0x00000800/* DEPRECATED */ #endif -#define IRQ_DISABLED 0x00000800/* IRQ disabled - do not enter! */ #define IRQ_PENDING 0x00001000/* IRQ pending - replay on enable */ #define IRQ_LEVEL 0x00004000/* IRQ level triggered */
@@ -230,7 +230,7 @@ struct irq_chip {# define ARCH_IRQ_INIT_FLAGS 0#endif -#define IRQ_DEFAULT_INIT_FLAGS (IRQ_DISABLED | ARCH_IRQ_INIT_FLAGS) +#define IRQ_DEFAULT_INIT_FLAGS ARCH_IRQ_INIT_FLAGSstruct irqaction ;extern int setup_irq (unsigned int irq,struct irqaction *new);
kernel/irq/chip.c +31 -17
124 lines not on this page · raw message
kernel/irq/compat.h +12 -0
@@ -11,7 +11,19 @@ static inline void irq_compat_clr_progre { desc->status &= ~IRQ_INPROGRESS ; } +static inline void irq_compat_set_disabled (struct irq_desc *desc) +{ + desc->status |=IRQ_DISABLED ; +} + +static inline void irq_compat_clr_disabled (struct irq_desc *desc) +{ + desc->status &= ~IRQ_DISABLED ; +}#else static inline void irq_compat_set_progress (struct irq_desc *desc) { }static inline void irq_compat_clr_progress (struct irq_desc *desc) { } +static inline void irq_compat_set_disabled (struct irq_desc *desc) { } +static inline void irq_compat_clr_disabled (struct irq_desc *desc) { }#endif +
kernel/irq/internals.h +3 -1
@@ -41,6 +41,7 @@ enum {* IRQS_ONESHOT - irq is not unmasked in primary handler * IRQS_REPLAY - irq is replayed * IRQS_WAITING - irq is waiting +* IRQS_DISABLED - irq is disabled */ enum {IRQS_AUTODETECT =0x00000001 ,
@@ -51,6 +52,7 @@ enum {IRQS_ONESHOT =0x00000020 ,IRQS_REPLAY =0x00000040 ,IRQS_WAITING =0x00000080 , + IRQS_DISABLED = 0x00000100, };#define irq_data_to_desc (data) container_of(data, struct irq_desc, irq_data)
@@ -135,7 +137,6 @@ static inline void print_irq_desc(unsignprint_symbol ("%s\n" , (unsigned long )desc->action->handler); } -P (IRQ_DISABLED );P (IRQ_PENDING );P (IRQ_LEVEL );P (IRQ_MASKED );
@@ -150,6 +151,7 @@ static inline void print_irq_desc(unsignPS (IRQS_INPROGRESS );PS (IRQS_REPLAY );PS (IRQS_WAITING ); +PS (IRQS_DISABLED ); }#undef P
kernel/irq/irqdesc.c +2 -0
@@ -80,6 +80,7 @@ static void desc_set_defaults(unsigned i desc->irq_data.handler_data =NULL ; desc->irq_data.msi_desc =NULL ; desc->status = _IRQ_DEFAULT_INIT_FLAGS; + desc->istate =IRQS_DISABLED ; desc->handle_irq = handle_bad_irq; desc->depth =1 ; desc->irq_count =0 ;
@@ -230,6 +231,7 @@ int __init early_irq_init(void) struct irq_desc irq_desc[NR_IRQS] __cacheline_aligned_in_smp = { [0 ...NR_IRQS -1 ] = { .status = _IRQ_DEFAULT_INIT_FLAGS, + .istate =IRQS_DISABLED , .handle_irq = handle_bad_irq, .depth =1 , .lock =__RAW_SPIN_LOCK_UNLOCKED (irq_desc->lock),
kernel/irq/manage.c +2 -2
@@ -652,7 +652,7 @@ again: goto again; } -if (!(desc->status &IRQ_DISABLED ) && (desc->status &IRQ_MASKED )) { +if (!(desc->istate &IRQS_DISABLED ) && (desc->status &IRQ_MASKED )) { desc->status &= ~IRQ_MASKED ; desc->irq_data.chip->irq_unmask (&desc->irq_data); }
@@ -715,7 +715,7 @@ static int irq_thread(void *data)atomic_inc (&desc->threads_active);raw_spin_lock_irq (&desc->lock); -if (unlikely (desc->status &IRQ_DISABLED )) { +if (unlikely (desc->istate &IRQS_DISABLED )) {/* * CHECKME: We might need a dedicated * IRQ_THREAD_PENDING flag here, which
kernel/irq/migration.c +1 -1
@@ -61,7 +61,7 @@ void move_native_irq(int irq)if (likely (!(desc->status &IRQ_MOVE_PENDING )))return ; -if (unlikely (desc->status &IRQ_DISABLED )) +if (unlikely (desc->istate &IRQS_DISABLED ))return ;/*
kernel/irq/settings.h +2 -0
@@ -12,3 +12,5 @@ enum {#define IRQ_REPLAY GOT_YOU_MORON#undef IRQ_WAITING#define IRQ_WAITING GOT_YOU_MORON +#undef IRQ_DISABLED +#define IRQ_DISABLED GOT_YOU_MORON
kernel/irq/spurious.c +2 -2
@@ -50,7 +50,7 @@ bool irq_wait_for_poll(struct irq_desc * raw_spin_lock(&desc->lock); }while (desc->istate &IRQS_INPROGRESS );/* Might have been disabled in meantime */ -return !(desc->status &IRQ_DISABLED ) && desc->action; +return !(desc->istate &IRQS_DISABLED ) && desc->action;#else return false;#endif
@@ -75,7 +75,7 @@ static int try_one_irq(int irq, struct i* Do not poll disabled interrupts unless the spurious * disabled poller asks explicitely. */ -if ((desc->status &IRQ_DISABLED ) && !force) +if ((desc->istate &IRQS_DISABLED ) && !force) goto out;/*
PATCH 44/75 genirq: Move IRQ_PENDING flag to core
In reply to Thomas GleixnerKeep status in sync until all users are fixed.
--- include/linux/irq.h | 2 +- kernel/irq/autoprobe.c | 6 ++++-- kernel/irq/chip.c | 10 ++++++---- kernel/irq/compat.h | 12 +++++++++++- kernel/irq/handle.c | 3 ++- kernel/irq/internals.h | 4 +++- kernel/irq/manage.c | 5 +++-- kernel/irq/pm.c | 3 ++- kernel/irq/resend.c | 5 +++-- kernel/irq/settings.h | 2 ++ kernel/irq/spurious.c | 5 +++-- 11 files changed, 40 insertions(+), 17 deletions(-)
include/linux/irq.h +1 -1
@@ -56,9 +56,9 @@ typedef void (*irq_flow_handler_t)(unsig#define IRQ_REPLAY 0x00000200/* DEPRECATED */ #define IRQ_WAITING 0x00000400/* DEPRECATED */ #define IRQ_DISABLED 0x00000800/* DEPRECATED */ +#define IRQ_PENDING 0x00001000/* DEPRECATED */ #endif -#define IRQ_PENDING 0x00001000/* IRQ pending - replay on enable */ #define IRQ_LEVEL 0x00004000/* IRQ level triggered */ #define IRQ_MASKED 0x00008000/* IRQ masked - shouldn't be seen again */
kernel/irq/autoprobe.c +4 -2
@@ -76,8 +76,10 @@ unsigned long probe_irq_on(void)raw_spin_lock_irq (&desc->lock);if (!desc->action && !(desc->status &IRQ_NOPROBE )) { desc->istate |=IRQS_AUTODETECT |IRQS_WAITING ; -if (irq_startup (desc)) - desc->status |=IRQ_PENDING ; +if (irq_startup (desc)) { +irq_compat_set_pending (desc); + desc->istate |=IRQS_PENDING ; + } }raw_spin_unlock_irq (&desc->lock); }
kernel/irq/chip.c +6 -4
@@ -544,7 +544,8 @@ handle_fasteoi_irq(unsigned int irq, str* then mask it and get out of here: */ if (unlikely (!desc->action || (desc->istate &IRQS_DISABLED ))) { - desc->status |=IRQ_PENDING ; +irq_compat_set_pending (desc); + desc->istate |=IRQS_PENDING ;mask_irq (desc); goto out; }
@@ -584,7 +585,8 @@ handle_edge_irq(unsigned int irq, structif (unlikely ((desc->istate & (IRQS_DISABLED |IRQS_INPROGRESS ) || !desc->action))) {if (!irq_check_poll (desc)) { - desc->status |=IRQ_PENDING ; +irq_compat_set_pending (desc); + desc->istate |=IRQS_PENDING ;mask_ack_irq (desc); goto out_unlock; }
@@ -605,7 +607,7 @@ handle_edge_irq(unsigned int irq, struct* one, we could have masked the irq. * Renable it, if it was not disabled in meantime. */ -if (unlikely (desc->status &IRQ_PENDING )) { +if (unlikely (desc->istate &IRQS_PENDING )) {if (!(desc->istate &IRQS_DISABLED ) && (desc->status &IRQ_MASKED ))unmask_irq (desc);
@@ -613,7 +615,7 @@ handle_edge_irq(unsigned int irq, structhandle_irq_event (desc); - }while ((desc->status &IRQ_PENDING ) && + }while ((desc->istate &IRQS_PENDING ) && !(desc->istate &IRQS_DISABLED )); out_unlock:
kernel/irq/compat.h +11 -1
@@ -15,15 +15,25 @@ static inline void irq_compat_set_disabl { desc->status |=IRQ_DISABLED ; } -static inline void irq_compat_clr_disabled (struct irq_desc *desc) { desc->status &= ~IRQ_DISABLED ; } +static inline void irq_compat_set_pending (struct irq_desc *desc) +{ + desc->status |=IRQ_PENDING ; +} + +static inline void irq_compat_clr_pending (struct irq_desc *desc) +{ + desc->status &= ~IRQ_PENDING ; +}#else static inline void irq_compat_set_progress (struct irq_desc *desc) { }static inline void irq_compat_clr_progress (struct irq_desc *desc) { }static inline void irq_compat_set_disabled (struct irq_desc *desc) { }static inline void irq_compat_clr_disabled (struct irq_desc *desc) { } +static inline void irq_compat_set_pending (struct irq_desc *desc) { } +static inline void irq_compat_clr_pending (struct irq_desc *desc) { }#endif
kernel/irq/handle.c +2 -1
@@ -122,7 +122,8 @@ irqreturn_t handle_irq_event(struct irq_struct irqaction *action = desc->action;irqreturn_t ret; - desc->status &= ~IRQ_PENDING ; +irq_compat_clr_pending (desc); + desc->istate &= ~IRQS_PENDING ;irq_compat_set_progress (desc); desc->istate |=IRQS_INPROGRESS ;raw_spin_unlock (&desc->lock);
kernel/irq/internals.h +3 -1
@@ -42,6 +42,7 @@ enum {* IRQS_REPLAY - irq is replayed * IRQS_WAITING - irq is waiting * IRQS_DISABLED - irq is disabled +* IRQS_PENDING - irq is pending and replayed later */ enum {IRQS_AUTODETECT =0x00000001 ,
@@ -53,6 +54,7 @@ enum {IRQS_REPLAY =0x00000040 ,IRQS_WAITING =0x00000080 ,IRQS_DISABLED =0x00000100 , + IRQS_PENDING = 0x00000200, };#define irq_data_to_desc (data) container_of(data, struct irq_desc, irq_data)
@@ -137,7 +139,6 @@ static inline void print_irq_desc(unsignprint_symbol ("%s\n" , (unsigned long )desc->action->handler); } -P (IRQ_PENDING );P (IRQ_LEVEL );P (IRQ_MASKED );#ifdef CONFIG_IRQ_PER_CPU
@@ -152,6 +153,7 @@ static inline void print_irq_desc(unsignPS (IRQS_REPLAY );PS (IRQS_WAITING );PS (IRQS_DISABLED ); +PS (IRQS_PENDING ); }#undef P
kernel/irq/manage.c +3 -2
@@ -720,10 +720,11 @@ static int irq_thread(void *data)* CHECKME: We might need a dedicated * IRQ_THREAD_PENDING flag here, which * retriggers the thread in check_irq_resend() -* but AFAICT IRQ_PENDING should be fine as it +* but AFAICT IRQS_PENDING should be fine as it * retriggers the interrupt itself --- tglx */ - desc->status |=IRQ_PENDING ; +irq_compat_set_pending (desc); + desc->istate |=IRQS_PENDING ;raw_spin_unlock_irq (&desc->lock); }else {raw_spin_unlock_irq (&desc->lock);
kernel/irq/pm.c +2 -1
@@ -69,7 +69,8 @@ int check_wakeup_irqs(void)int irq;for_each_irq_desc (irq, desc) -if ((desc->status &IRQ_WAKEUP ) && (desc->status &IRQ_PENDING )) +if ((desc->status &IRQ_WAKEUP ) && + (desc->istate &IRQS_PENDING ))return -EBUSY ;return 0 ;
kernel/irq/resend.c +3 -2
@@ -64,8 +64,9 @@ void check_irq_resend(struct irq_desc *dreturn ;if (desc->istate &IRQS_REPLAY )return ; -if (desc->status &IRQ_PENDING ) { - desc->status &=IRQ_PENDING ; +if (desc->istate &IRQS_PENDING ) { +irq_compat_clr_pending (desc); + desc->istate &=IRQS_PENDING ; desc->istate |=IRQS_REPLAY ; if (!desc->irq_data.chip->irq_retrigger ||
kernel/irq/settings.h +2 -0
@@ -14,3 +14,5 @@ enum {#define IRQ_WAITING GOT_YOU_MORON#undef IRQ_DISABLED#define IRQ_DISABLED GOT_YOU_MORON +#undef IRQ_PENDING +#define IRQ_PENDING GOT_YOU_MORON
kernel/irq/spurious.c +3 -2
@@ -93,7 +93,8 @@ static int try_one_irq(int irq, struct i* Already running: If it is shared get the other * CPU to go looking for our mystery interrupt too */ - desc->status |=IRQ_PENDING ; +irq_compat_set_pending (desc); + desc->istate |=IRQS_PENDING ; goto out; }
@@ -103,7 +104,7 @@ static int try_one_irq(int irq, struct iif (handle_irq_event (desc) ==IRQ_HANDLED ) ret =IRQ_HANDLED ; action = desc->action; - }while ((desc->status &IRQ_PENDING ) && action); + }while ((desc->istate &IRQS_PENDING ) && action); desc->istate &= ~IRQS_POLL_INPROGRESS ; out:raw_spin_unlock (&desc->lock);
PATCH 45/75 genirq: Move IRQ_MASKED to core
In reply to Thomas GleixnerKeep status in sync until all users are fixed.
--- include/linux/irq.h | 2 +- kernel/irq/chip.c | 28 ++++++++++++++++++++-------- kernel/irq/compat.h | 11 +++++++++++ kernel/irq/internals.h | 4 +++- kernel/irq/manage.c | 5 +++-- kernel/irq/migration.c | 2 +- kernel/irq/settings.h | 2 ++ 7 files changed, 41 insertions(+), 13 deletions(-)
include/linux/irq.h +1 -1
@@ -57,11 +57,11 @@ typedef void (*irq_flow_handler_t)(unsig#define IRQ_WAITING 0x00000400/* DEPRECATED */ #define IRQ_DISABLED 0x00000800/* DEPRECATED */ #define IRQ_PENDING 0x00001000/* DEPRECATED */ +#define IRQ_MASKED 0x00002000/* DEPRECATED */ #endif #define IRQ_LEVEL 0x00004000/* IRQ level triggered */ -#define IRQ_MASKED 0x00008000/* IRQ masked - shouldn't be seen again */ #define IRQ_PER_CPU 0x00010000/* IRQ is per CPU */ #define IRQ_NOPROBE 0x00020000/* IRQ is not valid for probing */ #define IRQ_NOREQUEST 0x00040000/* IRQ cannot be requested */
kernel/irq/chip.c +20 -8
@@ -202,6 +202,18 @@ static void irq_state_set_disabled(strucirq_compat_set_disabled (desc); } +static void irq_state_clr_masked (struct irq_desc *desc) +{ + desc->istate &= ~IRQS_MASKED ; +irq_compat_clr_masked (desc); +} + +static void irq_state_set_masked (struct irq_desc *desc) +{ + desc->istate |=IRQS_MASKED ; +irq_compat_set_masked (desc); +} +int irq_startup (struct irq_desc *desc) {irq_state_clr_disabled (desc);
@@ -209,7 +221,7 @@ int irq_startup(struct irq_desc *desc)if (desc->irq_data.chip->irq_startup) {int ret = desc->irq_data.chip->irq_startup (&desc->irq_data); - desc->status &=IRQ_MASKED ; +irq_state_clr_masked (desc);return ret; }
@@ -227,7 +239,7 @@ void irq_shutdown(struct irq_desc *desc) desc->irq_data.chip->irq_disable (&desc->irq_data); else desc->irq_data.chip->irq_mask(&desc->irq_data); - desc->status |=IRQ_MASKED ; +irq_state_set_masked (desc); }void irq_enable (struct irq_desc *desc)
@@ -237,7 +249,7 @@ void irq_enable(struct irq_desc *desc) desc->irq_data.chip->irq_enable (&desc->irq_data); else desc->irq_data.chip->irq_unmask(&desc->irq_data); - desc->status &= ~IRQ_MASKED ; +irq_state_clr_masked (desc); }void irq_disable (struct irq_desc *desc)
@@ -245,8 +257,8 @@ void irq_disable(struct irq_desc *desc)irq_state_set_disabled (desc);if (desc->irq_data.chip->irq_disable) { desc->irq_data.chip->irq_disable (&desc->irq_data); - desc->status |=IRQ_MASKED ; } +irq_state_set_masked (desc); }#ifndef CONFIG_GENERIC_HARDIRQS_NO_DEPRECATED
@@ -378,14 +390,14 @@ static inline void mask_ack_irq(struct iif (desc->irq_data.chip->irq_ack) desc->irq_data.chip->irq_ack (&desc->irq_data); } - desc->status |=IRQ_MASKED ; +irq_state_set_masked (desc); }static inline void mask_irq (struct irq_desc *desc) {if (desc->irq_data.chip->irq_mask) { desc->irq_data.chip->irq_mask (&desc->irq_data); - desc->status |=IRQ_MASKED ; +irq_state_set_masked (desc); } }
@@ -393,7 +405,7 @@ static inline void unmask_irq(struct irq {if (desc->irq_data.chip->irq_unmask) { desc->irq_data.chip->irq_unmask (&desc->irq_data); - desc->status &= ~IRQ_MASKED ; +irq_state_clr_masked (desc); } }
@@ -609,7 +621,7 @@ handle_edge_irq(unsigned int irq, struct*/ if (unlikely (desc->istate &IRQS_PENDING )) {if (!(desc->istate &IRQS_DISABLED ) && - (desc->status &IRQ_MASKED )) + (desc->istate &IRQS_MASKED ))unmask_irq (desc); }
kernel/irq/compat.h +11 -0
@@ -28,6 +28,15 @@ static inline void irq_compat_clr_pendin { desc->status &= ~IRQ_PENDING ; } +static inline void irq_compat_set_masked (struct irq_desc *desc) +{ + desc->status |=IRQ_MASKED ; +} + +static inline void irq_compat_clr_masked (struct irq_desc *desc) +{ + desc->status &= ~IRQ_MASKED ; +}#else static inline void irq_compat_set_progress (struct irq_desc *desc) { }static inline void irq_compat_clr_progress (struct irq_desc *desc) { }
@@ -35,5 +44,7 @@ static inline void irq_compat_set_disablstatic inline void irq_compat_clr_disabled (struct irq_desc *desc) { }static inline void irq_compat_set_pending (struct irq_desc *desc) { }static inline void irq_compat_clr_pending (struct irq_desc *desc) { } +static inline void irq_compat_set_masked (struct irq_desc *desc) { } +static inline void irq_compat_clr_masked (struct irq_desc *desc) { }#endif
kernel/irq/internals.h +3 -1
@@ -43,6 +43,7 @@ enum {* IRQS_WAITING - irq is waiting * IRQS_DISABLED - irq is disabled * IRQS_PENDING - irq is pending and replayed later +* IRQS_MASKED - irq is masked */ enum {IRQS_AUTODETECT =0x00000001 ,
@@ -55,6 +56,7 @@ enum {IRQS_WAITING =0x00000080 ,IRQS_DISABLED =0x00000100 ,IRQS_PENDING =0x00000200 , + IRQS_MASKED = 0x00000400, };#define irq_data_to_desc (data) container_of(data, struct irq_desc, irq_data)
@@ -140,7 +142,6 @@ static inline void print_irq_desc(unsign }P (IRQ_LEVEL ); -P (IRQ_MASKED );#ifdef CONFIG_IRQ_PER_CPU P (IRQ_PER_CPU );#endif
@@ -154,6 +155,7 @@ static inline void print_irq_desc(unsignPS (IRQS_WAITING );PS (IRQS_DISABLED );PS (IRQS_PENDING ); +PS (IRQS_MASKED ); }#undef P
kernel/irq/manage.c +3 -2
@@ -652,8 +652,9 @@ again: goto again; } -if (!(desc->istate &IRQS_DISABLED ) && (desc->status &IRQ_MASKED )) { - desc->status &= ~IRQ_MASKED ; +if (!(desc->istate &IRQS_DISABLED ) && (desc->istate &IRQS_MASKED )) { +irq_compat_clr_masked (desc); + desc->istate &= ~IRQS_MASKED ; desc->irq_data.chip->irq_unmask (&desc->irq_data); }raw_spin_unlock_irq (&desc->lock);
kernel/irq/migration.c +1 -1
@@ -69,7 +69,7 @@ void move_native_irq(int irq)* threaded interrupt with ONESHOT set, we can end up with an * interrupt storm. */ - masked = desc->status &IRQ_MASKED ; + masked = desc->istate &IRQS_MASKED ;if (!masked) desc->irq_data.chip->irq_mask (&desc->irq_data);move_masked_irq (irq);
kernel/irq/settings.h +2 -0
@@ -16,3 +16,5 @@ enum {#define IRQ_DISABLED GOT_YOU_MORON#undef IRQ_PENDING#define IRQ_PENDING GOT_YOU_MORON +#undef IRQ_MASKED +#define IRQ_MASKED GOT_YOU_MORON
PATCH 46/75 genirq: Move IRQ_SUSPENDED to core
In reply to Thomas GleixnerNo users outside of core.
--- include/linux/irq.h | 2 -- kernel/irq/internals.h | 2 ++ kernel/irq/manage.c | 8 ++++---- kernel/irq/pm.c | 6 +++--- 4 files changed, 9 insertions(+), 9 deletions(-)
include/linux/irq.h +0 -2
@@ -60,7 +60,6 @@ typedef void (*irq_flow_handler_t)(unsig#define IRQ_MASKED 0x00002000/* DEPRECATED */ #endif -#define IRQ_LEVEL 0x00004000/* IRQ level triggered */ #define IRQ_PER_CPU 0x00010000/* IRQ is per CPU */ #define IRQ_NOPROBE 0x00020000/* IRQ is not valid for probing */
@@ -71,7 +70,6 @@ typedef void (*irq_flow_handler_t)(unsig#define IRQ_NO_BALANCING 0x00400000/* IRQ is excluded from balancing */ #define IRQ_MOVE_PCNTXT 0x01000000/* IRQ migration from process context */ #define IRQ_AFFINITY_SET 0x02000000/* IRQ affinity was set from userspace*/ -#define IRQ_SUSPENDED 0x04000000/* IRQ has gone through suspend sequence */ #define IRQF_MODIFY_MASK \ (IRQ_TYPE_SENSE_MASK | IRQ_NOPROBE | IRQ_NOREQUEST | \
kernel/irq/internals.h +2 -0
@@ -44,6 +44,7 @@ enum {* IRQS_DISABLED - irq is disabled * IRQS_PENDING - irq is pending and replayed later * IRQS_MASKED - irq is masked +* IRQS_SUSPENDED - irq is suspended */ enum {IRQS_AUTODETECT =0x00000001 ,
@@ -57,6 +58,7 @@ enum {IRQS_DISABLED =0x00000100 ,IRQS_PENDING =0x00000200 ,IRQS_MASKED =0x00000400 , + IRQS_SUSPENDED = 0x00000800, };#define irq_data_to_desc (data) container_of(data, struct irq_desc, irq_data)
kernel/irq/manage.c +4 -4
@@ -334,7 +334,7 @@ void __disable_irq(struct irq_desc *descif (suspend) {if (!desc->action || (desc->action->flags &IRQF_NO_SUSPEND ))return ; - desc->status |=IRQ_SUSPENDED ; + desc->istate |=IRQS_SUSPENDED ; }if (!desc->depth++)
@@ -396,7 +396,7 @@ EXPORT_SYMBOL(disable_irq);void __enable_irq (struct irq_desc *desc,unsigned int irq,bool resume) {if (resume) { -if (!(desc->status &IRQ_SUSPENDED )) { +if (!(desc->istate &IRQS_SUSPENDED )) {if (!desc->action)return ;if (!(desc->action->flags &IRQF_FORCE_RESUME ))
@@ -404,7 +404,7 @@ void __enable_irq(struct irq_desc *desc,/* Pretend that it got disabled ! */ desc->depth++; } - desc->status &= ~IRQ_SUSPENDED ; + desc->istate &= ~IRQS_SUSPENDED ; }switch (desc->depth) {
@@ -413,7 +413,7 @@ void __enable_irq(struct irq_desc *desc,WARN (1 ,KERN_WARNING "Unbalanced enable for IRQ %d\n" , irq);break ;case 1 : { -if (desc->status &IRQ_SUSPENDED ) +if (desc->istate &IRQS_SUSPENDED ) goto err_out;/* Prevent probing on this irq: */ desc->status |=IRQ_NOPROBE ;
kernel/irq/pm.c +3 -3
@@ -18,7 +18,7 @@* During system-wide suspend or hibernation device drivers need to be prevented * from receiving interrupts and this function is provided for this purpose. * It marks all interrupt lines in use, except for the timer ones, as disabled -* and sets the IRQ_SUSPENDED flag for each of them. +* and sets the IRQS_SUSPENDED flag for each of them. */ void suspend_device_irqs (void ) {
@@ -34,7 +34,7 @@ void suspend_device_irqs(void) }for_each_irq_desc (irq, desc) -if (desc->status &IRQ_SUSPENDED ) +if (desc->istate &IRQS_SUSPENDED )synchronize_irq (irq); }EXPORT_SYMBOL_GPL (suspend_device_irqs);
@@ -43,7 +43,7 @@ EXPORT_SYMBOL_GPL(suspend_device_irqs);* resume_device_irqs - enable interrupt lines disabled by suspend_device_irqs() * * Enable all interrupt lines previously disabled by suspend_device_irqs() that -* have the IRQ_SUSPENDED flag set. +* have the IRQS_SUSPENDED flag set. */ void resume_device_irqs (void ) {
PATCH 47/75 arm: tegra: Remove unused function which fiddles with irq_desc
In reply to Thomas GleixnerAn embedded and charset-unspecified text was scrubbed...
Name: arm-tegra.patch
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20110210/f5bcbf8a/attachment.ksh>
Re: [patch 47/75] arm: tegra: Remove unused function which fiddles with irq_desc
Quoted 146 lines · Thomas Gleixner
These functions are unused and in the way of cleanups in the core code. If you have special requirements vs. irqs and PM then please talk to me. Access to the generic core internals is going away.
Signed-off-by Thomas Gleixner <[email protected]>Cc Colin Cross <[email protected]>Cc linux-tegra at vger.kernel.orgCc linux-arm-kernel at lists.infradead.org---
?arch/arm/mach-tegra/gpio.c | ? 63 --------------------------------------------- ?arch/arm/mach-tegra/irq.c ?| ? 58 ----------------------------------------- ?2 files changed, 121 deletions(-)Index:
linux-2.6-tip/arch/arm/mach-tegra/gpio.c
===================================================================arch/arm/mach-tegra/gpio.c +0
-0@@ -253,69 +253,6 @@ static void tegra_gpio_irq_handler(unsig ?}?#ifdef
CONFIG_PMarch/arm/mach-tegra/gpio.c +0
-63-void tegra_gpio_resume (void ) -{ - ? ? ? unsigned long flags; - ? ? ? int b, p, i; - - ? ? ? local_irq_save(flags); - - ? ? ? for (b = 0; b < ARRAY_SIZE(tegra_gpio_banks); b++) { - ? ? ? ? ? ? ? struct tegra_gpio_bank *bank = &tegra_gpio_banks[b]; - - ? ? ? ? ? ? ? for (p = 0; p < ARRAY_SIZE(bank->oe); p++) { - ? ? ? ? ? ? ? ? ? ? ? unsigned int gpio = (b<<5) | (p<<3); - ? ? ? ? ? ? ? ? ? ? ? __raw_writel(bank->cnf[p], GPIO_CNF(gpio)); - ? ? ? ? ? ? ? ? ? ? ? __raw_writel(bank->out[p], GPIO_OUT(gpio)); - ? ? ? ? ? ? ? ? ? ? ? __raw_writel(bank->oe[p], GPIO_OE(gpio)); - ? ? ? ? ? ? ? ? ? ? ? __raw_writel(bank->int_lvl[p], GPIO_INT_LVL(gpio)); - ? ? ? ? ? ? ? ? ? ? ? __raw_writel(bank->int_enb[p], GPIO_INT_ENB(gpio)); - ? ? ? ? ? ? ? } - ? ? ? } - - ? ? ? local_irq_restore(flags); - - ? ? ? for (i = INT_GPIO_BASE; i < (INT_GPIO_BASE + TEGRA_NR_GPIOS); i++) { - ? ? ? ? ? ? ? struct irq_desc *desc = irq_to_desc(i); - ? ? ? ? ? ? ? if (!desc || (desc->status & IRQ_WAKEUP)) - ? ? ? ? ? ? ? ? ? ? ? continue; - ? ? ? ? ? ? ? enable_irq(i); - ? ? ? } -} - -void tegra_gpio_suspend (void ) -{ - ? ? ? unsigned long flags; - ? ? ? int b, p, i; - - ? ? ? for (i = INT_GPIO_BASE; i < (INT_GPIO_BASE + TEGRA_NR_GPIOS); i++) { - ? ? ? ? ? ? ? struct irq_desc *desc = irq_to_desc(i); - ? ? ? ? ? ? ? if (!desc) - ? ? ? ? ? ? ? ? ? ? ? continue; - ? ? ? ? ? ? ? if (desc->status & IRQ_WAKEUP) { - ? ? ? ? ? ? ? ? ? ? ? int gpio = i - INT_GPIO_BASE; - ? ? ? ? ? ? ? ? ? ? ? pr_debug("gpio %d.%d is wakeup\n", gpio/8, gpio&7); - ? ? ? ? ? ? ? ? ? ? ? continue; - ? ? ? ? ? ? ? } - ? ? ? ? ? ? ? disable_irq(i); - ? ? ? } - - ? ? ? local_irq_save(flags); - ? ? ? for (b = 0; b < ARRAY_SIZE(tegra_gpio_banks); b++) { - ? ? ? ? ? ? ? struct tegra_gpio_bank *bank = &tegra_gpio_banks[b]; - - ? ? ? ? ? ? ? for (p = 0; p < ARRAY_SIZE(bank->oe); p++) { - ? ? ? ? ? ? ? ? ? ? ? unsigned int gpio = (b<<5) | (p<<3); - ? ? ? ? ? ? ? ? ? ? ? bank->cnf[p] = __raw_readl(GPIO_CNF(gpio)); - ? ? ? ? ? ? ? ? ? ? ? bank->out[p] = __raw_readl(GPIO_OUT(gpio)); - ? ? ? ? ? ? ? ? ? ? ? bank->oe[p] = __raw_readl(GPIO_OE(gpio)); - ? ? ? ? ? ? ? ? ? ? ? bank->int_enb[p] = __raw_readl(GPIO_INT_ENB(gpio)); - ? ? ? ? ? ? ? ? ? ? ? bank->int_lvl[p] = __raw_readl(GPIO_INT_LVL(gpio)); - ? ? ? ? ? ? ? } - ? ? ? } - ? ? ? local_irq_restore(flags); -} -?static int
tegra_gpio_wake_enable(struct irq_data *d, unsigned int enable)?{
? ? ? ?structtegra_gpio_bank*bank =irq_data_get_irq_chip_data(d);
Index:linux-2.6-tip/arch/arm/mach-tegra/irq.c
===================================================================arch/arm/mach-tegra/irq.c +0
-48@@ -111,61 +111,3 @@ void __init tegra_init_irq(void) ? ? ? ? ? ? ? ?set_irq_flags(i, IRQF_VALID); ? ? ? ?} ?} - -#ifdef CONFIG_PM -static u32 cop_ier[PPI_NR ]; -static u32 cpu_ier[PPI_NR ]; -static u32 cpu_iep[PPI_NR ]; - -void tegra_irq_suspend (void ) -{ - ? ? ? unsigned long flags; - ? ? ? int i; - - ? ? ? for (i = INT_PRI_BASE; i < INT_GPIO_BASE; i++) { - ? ? ? ? ? ? ? struct irq_desc *desc = irq_to_desc(i); - ? ? ? ? ? ? ? if (!desc) - ? ? ? ? ? ? ? ? ? ? ? continue; - ? ? ? ? ? ? ? if (desc->status & IRQ_WAKEUP) { - ? ? ? ? ? ? ? ? ? ? ? pr_debug("irq %d is wakeup\n", i); - ? ? ? ? ? ? ? ? ? ? ? continue; - ? ? ? ? ? ? ? } - ? ? ? ? ? ? ? disable_irq(i); - ? ? ? } - - ? ? ? local_irq_save(flags); - ? ? ? for (i = 0; i < PPI_NR; i++) { - ? ? ? ? ? ? ? void __iomem *ictlr = ictlr_to_virt(i); - ? ? ? ? ? ? ? cpu_ier[i] = readl(ictlr + ICTLR_CPU_IER); - ? ? ? ? ? ? ? cpu_iep[i] = readl(ictlr + ICTLR_CPU_IEP_CLASS); - ? ? ? ? ? ? ? cop_ier[i] = readl(ictlr + ICTLR_COP_IER); - ? ? ? ? ? ? ? writel(~0, ictlr + ICTLR_COP_IER_CLR); - ? ? ? } - ? ? ? local_irq_restore(flags); -} - -void tegra_irq_resume (void ) -{ - ? ? ? unsigned long flags; - ? ? ? int i; - - ? ? ? local_irq_save(flags); - ? ? ? for (i = 0; i < PPI_NR; i++) { - ? ? ? ? ? ? ? void __iomem *ictlr = ictlr_to_virt(i); - ? ? ? ? ? ? ? writel(cpu_iep[i], ictlr + ICTLR_CPU_IEP_CLASS); - ? ? ? ? ? ? ? writel(~0ul, ictlr + ICTLR_CPU_IER_CLR); - ? ? ? ? ? ? ? writel(cpu_ier[i], ictlr + ICTLR_CPU_IER_SET); - ? ? ? ? ? ? ? writel(0, ictlr + ICTLR_COP_IEP_CLASS); - ? ? ? ? ? ? ? writel(~0ul, ictlr + ICTLR_COP_IER_CLR); - ? ? ? ? ? ? ? writel(cop_ier[i], ictlr + ICTLR_COP_IER_SET); - ? ? ? }
arch/arm/mach-tegra/irq.c void __init tegra_init_irq(void) · line 171
Quoted 10 lines
arch/arm/mach-tegra/irq.c +0
-10- ? ? ? local_irq_restore(flags); - - ? ? ? for (i = INT_PRI_BASE; i < INT_GPIO_BASE; i++) { - ? ? ? ? ? ? ? struct irq_desc *desc = irq_to_desc(i); - ? ? ? ? ? ? ? if (!desc || (desc->status & IRQ_WAKEUP)) - ? ? ? ? ? ? ? ? ? ? ? continue; - ? ? ? ? ? ? ? enable_irq(i); - ? ? ? } -} -#endif
These functions are clearly incorrectly accessing IRQ internals. I have replacements that have been posted for review that properly track the wakeup state using set_wake, but they are held up on some unrelated PM changes.
PATCH 48/75 genirq: Move IRQ_WAKEUP to core
In reply to Thomas GleixnerNo users outside of core.
--- include/linux/irq.h | 1 - kernel/irq/internals.h | 2 ++ kernel/irq/manage.c | 4 ++-- kernel/irq/pm.c | 2 +- kernel/irq/settings.h | 2 ++ 5 files changed, 7 insertions(+), 4 deletions(-)
include/linux/irq.h +0 -1
@@ -65,7 +65,6 @@ typedef void (*irq_flow_handler_t)(unsig#define IRQ_NOPROBE 0x00020000/* IRQ is not valid for probing */ #define IRQ_NOREQUEST 0x00040000/* IRQ cannot be requested */ #define IRQ_NOAUTOEN 0x00080000/* IRQ will not be enabled on request irq */ -#define IRQ_WAKEUP 0x00100000/* IRQ triggers system wakeup */ #define IRQ_MOVE_PENDING 0x00200000/* need to re-target IRQ destination */ #define IRQ_NO_BALANCING 0x00400000/* IRQ is excluded from balancing */ #define IRQ_MOVE_PCNTXT 0x01000000/* IRQ migration from process context */
kernel/irq/internals.h +2 -0
@@ -45,6 +45,7 @@ enum {* IRQS_PENDING - irq is pending and replayed later * IRQS_MASKED - irq is masked * IRQS_SUSPENDED - irq is suspended +* IRQS_WAKEUP - irq triggers system wakeup from suspend */ enum {IRQS_AUTODETECT =0x00000001 ,
@@ -59,6 +60,7 @@ enum {IRQS_PENDING =0x00000200 ,IRQS_MASKED =0x00000400 ,IRQS_SUSPENDED =0x00000800 , + IRQS_WAKEUP = 0x00001000, };#define irq_data_to_desc (data) container_of(data, struct irq_desc, irq_data)
kernel/irq/manage.c +2 -2
@@ -496,7 +496,7 @@ int set_irq_wake(unsigned int irq, unsigif (ret) desc->wake_depth =0 ;else - desc->status |=IRQ_WAKEUP ; + desc->istate |=IRQS_WAKEUP ; } }else {if (desc->wake_depth ==0 ) {
@@ -506,7 +506,7 @@ int set_irq_wake(unsigned int irq, unsigif (ret) desc->wake_depth =1 ;else - desc->status &= ~IRQ_WAKEUP ; + desc->istate &= ~IRQS_WAKEUP ; } }
kernel/irq/pm.c +1 -1
@@ -69,7 +69,7 @@ int check_wakeup_irqs(void)int irq;for_each_irq_desc (irq, desc) -if ((desc->status &IRQ_WAKEUP ) && +if ((desc->istate &IRQS_WAKEUP ) && (desc->istate &IRQS_PENDING ))return -EBUSY ;
kernel/irq/settings.h +2 -0
@@ -18,3 +18,5 @@ enum {#define IRQ_PENDING GOT_YOU_MORON#undef IRQ_MASKED#define IRQ_MASKED GOT_YOU_MORON +#undef IRQ_WAKEUP +#define IRQ_WAKEUP GOT_YOU_MORON
PATCH 49/75 genirq: Add state field to irq_data
In reply to Thomas GleixnerSome chip implementations need to access certain status flags. With sparse irqs that requires a lookup of the irq descriptor. Add a state field which contains such flags.
Name it in a way which will make coders happy to access it with the proper accessor functions. And it's easy to grep for.
--- include/linux/irq.h | 3 +++ include/linux/irqdesc.h | 1 + 2 files changed, 4 insertions(+)
include/linux/irq.h +3 -0
@@ -100,6 +100,8 @@ struct msi_desc;* struct irq_data - per irq and irq chip data passed down to chip functions * @irq: interrupt number * @node: node index useful for balancing +* @state_use_accessor: status information for irq chip functions. +* Use accessor functions to deal with it * @chip: low level interrupt hardware access * @handler_data: per-IRQ data for the irq_chip methods * @chip_data: platform-specific per-chip private data for the chip
@@ -114,6 +116,7 @@ struct msi_desc;struct irq_data {unsigned int irq;unsigned int node; +unsigned int state_use_accessors;struct irq_chip *chip;void *handler_data;void *chip_data;
include/linux/irqdesc.h +1 -0
@@ -48,6 +48,7 @@ struct irq_desc {struct {unsigned int irq;unsigned int node; +unsigned int pad_do_not_even_think_about_it;struct irq_chip *chip;void *handler_data;void *chip_data;
PATCH 50/75 genirq: Add IRQ_MOVE_PENDING to irq_data.state
In reply to Thomas Gleixnerchip implementations need to know about it. Keep status in sync until all users are fixed.
Accessor function: irqd_is_setaffinity_pending(irqdata)
Coders who access them directly will be tracked down and slapped with stinking trouts.
--- include/linux/irq.h | 20 ++++++++++++++++++-- kernel/irq/compat.h | 11 +++++++++++ kernel/irq/internals.h | 15 +++++++++++++++ kernel/irq/manage.c | 4 ++-- kernel/irq/migration.c | 6 +++--- kernel/irq/proc.c | 2 +- kernel/irq/settings.h | 2 ++ 7 files changed, 52 insertions(+), 8 deletions(-)
include/linux/irq.h +18 -2
@@ -58,14 +58,15 @@ typedef void (*irq_flow_handler_t)(unsig#define IRQ_DISABLED 0x00000800/* DEPRECATED */ #define IRQ_PENDING 0x00001000/* DEPRECATED */ #define IRQ_MASKED 0x00002000/* DEPRECATED */ +/* DEPRECATED use irq_setaffinity_pending() instead*/ +#define IRQ_MOVE_PENDING 0x00004000#endif -#define IRQ_LEVEL 0x00004000/* IRQ level triggered */ +#define IRQ_LEVEL 0x00008000/* IRQ level triggered */ #define IRQ_PER_CPU 0x00010000/* IRQ is per CPU */ #define IRQ_NOPROBE 0x00020000/* IRQ is not valid for probing */ #define IRQ_NOREQUEST 0x00040000/* IRQ cannot be requested */ #define IRQ_NOAUTOEN 0x00080000/* IRQ will not be enabled on request irq */ -#define IRQ_MOVE_PENDING 0x00200000/* need to re-target IRQ destination */ #define IRQ_NO_BALANCING 0x00400000/* IRQ is excluded from balancing */ #define IRQ_MOVE_PCNTXT 0x01000000/* IRQ migration from process context */ #define IRQ_AFFINITY_SET 0x02000000/* IRQ affinity was set from userspace*/
@@ -126,6 +127,21 @@ struct irq_data {#endif }; +/* +* Bit masks for irq_data.state +* +* IRQD_SETAFFINITY_PENDING - Affinity setting is pending +*/ +enum { +/* Bit 0 - 7 reserved for TYPE will use later */ +IRQD_SETAFFINITY_PENDING = (1 <<8 ), +}; + +static inline bool irqd_is_setaffinity_pending (struct irq_data *d) +{ +return d->state_use_accessors &IRQD_SETAFFINITY_PENDING ; +} +/** * struct irq_chip - hardware interrupt chip descriptor *
kernel/irq/compat.h +11 -0
@@ -37,6 +37,15 @@ static inline void irq_compat_clr_masked { desc->status &= ~IRQ_MASKED ; } +static inline void irq_compat_set_move_pending (struct irq_desc *desc) +{ + desc->status |=IRQ_MOVE_PENDING ; +} + +static inline void irq_compat_clr_move_pending (struct irq_desc *desc) +{ + desc->status &= ~IRQ_MOVE_PENDING ; +}#else static inline void irq_compat_set_progress (struct irq_desc *desc) { }static inline void irq_compat_clr_progress (struct irq_desc *desc) { }
@@ -46,5 +55,7 @@ static inline void irq_compat_set_pendinstatic inline void irq_compat_clr_pending (struct irq_desc *desc) { }static inline void irq_compat_set_masked (struct irq_desc *desc) { }static inline void irq_compat_clr_masked (struct irq_desc *desc) { } +static inline void irq_compat_set_move_pending (struct irq_desc *desc) { } +static inline void irq_compat_clr_move_pending (struct irq_desc *desc) { }#endif
kernel/irq/internals.h +15 -0
@@ -123,6 +123,21 @@ static inline void chip_bus_sync_unlock( }/* +* Manipulation functions for irq_data.state +*/ +static inline void irqd_set_move_pending (struct irq_data *d) +{ + d->state_use_accessors |=IRQD_SETAFFINITY_PENDING ; +irq_compat_set_move_pending (irq_data_to_desc (d)); +} + +static inline void irqd_clr_move_pending (struct irq_data *d) +{ + d->state_use_accessors &= ~IRQD_SETAFFINITY_PENDING ; +irq_compat_clr_move_pending (irq_data_to_desc (d)); +} + +/* * Debugging printout: */
kernel/irq/manage.c +2 -2
@@ -107,7 +107,7 @@ static inline bool irq_can_move_pcntxt(s }static inline bool irq_move_pending (struct irq_desc *desc) { -return desc->status &IRQ_MOVE_PENDING ; +return irqd_is_setaffinity_pending (&desc->irq_data); }static inline void irq_copy_pending (struct irq_desc *desc,const struct cpumask *mask)
@@ -156,7 +156,7 @@ int irq_set_affinity(unsigned int irq, c ret =0 ; } }else { - desc->status |=IRQ_MOVE_PENDING ; +irqd_set_move_pending (&desc->irq_data);irq_copy_pending (desc, mask); }
kernel/irq/migration.c +3 -3
@@ -9,7 +9,7 @@ void move_masked_irq(int irq)struct irq_desc *desc =irq_to_desc (irq);struct irq_chip *chip = desc->irq_data.chip; -if (likely (!(desc->status &IRQ_MOVE_PENDING ))) +if (likely (!irqd_is_setaffinity_pending (&desc->irq_data)))return ;/*
@@ -20,7 +20,7 @@ void move_masked_irq(int irq)return ; } - desc->status &= ~IRQ_MOVE_PENDING ; +irqd_clr_move_pending (&desc->irq_data);if (unlikely (cpumask_empty (desc->pending_mask)))return ;
@@ -58,7 +58,7 @@ void move_native_irq(int irq)struct irq_desc *desc =irq_to_desc (irq);bool masked; -if (likely (!(desc->status &IRQ_MOVE_PENDING ))) +if (likely (!irqd_is_setaffinity_pending (&desc->irq_data)))return ;if (unlikely (desc->istate &IRQS_DISABLED ))
kernel/irq/proc.c +1 -1
@@ -25,7 +25,7 @@ static int irq_affinity_proc_show(structconst struct cpumask *mask = desc->irq_data.affinity;#ifdef CONFIG_GENERIC_PENDING_IRQ -if (desc->status &IRQ_MOVE_PENDING ) +if (irqd_is_setaffinity_pending (&desc->irq_data)) mask = desc->pending_mask;#endif seq_cpumask (m, mask);
kernel/irq/settings.h +2 -0
@@ -20,3 +20,5 @@ enum {#define IRQ_MASKED GOT_YOU_MORON#undef IRQ_WAKEUP#define IRQ_WAKEUP GOT_YOU_MORON +#undef IRQ_MOVE_PENDING +#define IRQ_MOVE_PENDING GOT_YOU_MORON
PATCH 51/75 genirq: Remove CONFIG_IRQ_PER_CPU
In reply to Thomas GleixnerThe saving of this switch is minimal versus the ifdef mess it creates. Simple enable PER_CPU unconditionally and remove the config switch.
--- include/linux/irq.h | 5 ----- kernel/irq/Kconfig | 3 --- kernel/irq/internals.h | 2 -- kernel/irq/manage.c | 9 +++------ 4 files changed, 3 insertions(+), 16 deletions(-)
include/linux/irq.h +0 -5
@@ -76,13 +76,8 @@ typedef void (*irq_flow_handler_t)(unsig IRQ_NOAUTOEN | IRQ_MOVE_PCNTXT | IRQ_LEVEL | IRQ_NO_BALANCING | \ IRQ_PER_CPU) -#ifdef CONFIG_IRQ_PER_CPU # define CHECK_IRQ_PER_CPU (var) ((var) & IRQ_PER_CPU)# define IRQ_NO_BALANCING_MASK (IRQ_PER_CPU | IRQ_NO_BALANCING) -#else -# define CHECK_IRQ_PER_CPU (var) 0 -# define IRQ_NO_BALANCING_MASK IRQ_NO_BALANCING -#endif /* * Return value for chip->irq_set_affinity()
kernel/irq/Kconfig +0 -3
@@ -32,9 +32,6 @@ config GENERIC_PENDING_IRQ config AUTO_IRQ_AFFINITY def_bool n -config IRQ_PER_CPU - def_bool n - config HARDIRQS_SW_RESEND def_bool n
kernel/irq/internals.h +0 -2
@@ -161,9 +161,7 @@ static inline void print_irq_desc(unsign }P (IRQ_LEVEL ); -#ifdef CONFIG_IRQ_PER_CPU P (IRQ_PER_CPU ); -#endif P (IRQ_NOPROBE );P (IRQ_NOREQUEST );P (IRQ_NOAUTOEN );
kernel/irq/manage.c +3 -6
@@ -871,12 +871,10 @@ __setup_irq(unsigned int irq, struct irq goto mismatch; } -#if defined(CONFIG_IRQ_PER_CPU )/* All handlers must agree on per-cpuness */ if ((old->flags &IRQF_PERCPU ) != (new->flags &IRQF_PERCPU )) goto mismatch; -#endif /* add new interrupt at end of irq queue */ do {
@@ -900,15 +898,14 @@ __setup_irq(unsigned int irq, struct irq goto out_mask; }else compat_irq_chip_set_default_handler (desc); -#if defined(CONFIG_IRQ_PER_CPU ) -if (new->flags &IRQF_PERCPU ) - desc->status |=IRQ_PER_CPU ; -#endif desc->istate &= ~(IRQS_AUTODETECT |IRQS_SPURIOUS_DISABLED | \IRQS_INPROGRESS |IRQS_ONESHOT | \IRQS_WAITING ); +if (new->flags &IRQF_PERCPU ) + desc->status |=IRQ_PER_CPU ; +if (new->flags &IRQF_ONESHOT ) desc->istate |=IRQS_ONESHOT ;
PATCH 52/75 genirq: Make CHECK_IRQ_PER_CPU an inline and deprecate it
In reply to Thomas GleixnerIts' too ugly and needs to go. The only users are core code and parisc. Core code does not need it and parisc gets a new check once IRQ_PER_CPU is reflected in irq_data.state.
--- include/linux/irq.h | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
include/linux/irq.h +6 -2
@@ -76,8 +76,12 @@ typedef void (*irq_flow_handler_t)(unsig IRQ_NOAUTOEN | IRQ_MOVE_PCNTXT | IRQ_LEVEL | IRQ_NO_BALANCING | \ IRQ_PER_CPU) -# define CHECK_IRQ_PER_CPU (var) ((var) & IRQ_PER_CPU) -# define IRQ_NO_BALANCING_MASK (IRQ_PER_CPU | IRQ_NO_BALANCING) +#define IRQ_NO_BALANCING_MASK (IRQ_PER_CPU | IRQ_NO_BALANCING) + +static inline __deprecated bool CHECK_IRQ_PER_CPU (unsigned int status) +{ +return status &IRQ_PER_CPU ; +}/* * Return value for chip->irq_set_affinity()
PATCH 53/75 genirq: Remove CHECK_IRQ_PER_CPU from core code
In reply to Thomas Gleixner--- kernel/irq/manage.c | 4 ++-- kernel/irq/migration.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-)
kernel/irq/manage.c +2 -2
@@ -73,8 +73,8 @@ int irq_can_set_affinity(unsigned int ir {struct irq_desc *desc =irq_to_desc (irq); -if (CHECK_IRQ_PER_CPU (desc->status) || !desc->irq_data.chip || - !desc->irq_data.chip->irq_set_affinity) +if ((desc->status & (IRQ_PER_CPU |IRQ_NO_BALANCING )) || + !desc->irq_data.chip || !desc->irq_data.chip->irq_set_affinity)return 0 ;return 1 ;
kernel/irq/migration.c +1 -1
@@ -15,7 +15,7 @@ void move_masked_irq(int irq)/* * Paranoia: cpu-local interrupts shouldn't be calling in here anyway. */ -if (CHECK_IRQ_PER_CPU (desc->status)) { +if (desc->status & (IRQ_PER_CPU |IRQ_NO_BALANCING )) {WARN_ON (1 );return ; }
PATCH 54/75 genirq: Move debug code to separate header
In reply to Thomas GleixnerIt'll break when I'm going to undefine the constants.
--- kernel/irq/debug.h | 40 ++++++++++++++++++++++++++++++++++++++++ kernel/irq/internals.h | 48 ++++-------------------------------------------- 2 files changed, 44 insertions(+), 44 deletions(-)
kernel/irq/debug.h new file +40 -0
@@ -0,0 +1,40 @@ +/* +* Debugging printout: +*/ + +#include <linux/kallsyms.h> + +#define P (f) if (desc->status & f) printk("%14s set\n", #f) +#define PS (f) if (desc->istate & f) printk("%14s set\n", #f) + +static inline void print_irq_desc (unsigned int irq,struct irq_desc *desc) +{ +printk ("irq %d, desc: %p, depth: %d, count: %d, unhandled: %d\n" , + irq, desc, desc->depth, desc->irq_count, desc->irqs_unhandled); +printk ("->handle_irq(): %p, " , desc->handle_irq); +print_symbol ("%s\n" , (unsigned long )desc->handle_irq); +printk ("->irq_data.chip(): %p, " , desc->irq_data.chip); +print_symbol ("%s\n" , (unsigned long )desc->irq_data.chip); +printk ("->action(): %p\n" , desc->action); +if (desc->action) { +printk ("->action->handler(): %p, " , desc->action->handler); +print_symbol ("%s\n" , (unsigned long )desc->action->handler); + } + +P (IRQ_LEVEL ); +P (IRQ_PER_CPU ); +P (IRQ_NOPROBE ); +P (IRQ_NOREQUEST ); +P (IRQ_NOAUTOEN ); + +PS (IRQS_AUTODETECT ); +PS (IRQS_INPROGRESS ); +PS (IRQS_REPLAY ); +PS (IRQS_WAITING ); +PS (IRQS_DISABLED ); +PS (IRQS_PENDING ); +PS (IRQS_MASKED ); +} + +#undef P +#undef PS
kernel/irq/internals.h +4 -44
63 lines not on this page · raw message
PATCH 55/75 genirq: Mirror IRQ_PER_CPU and IRQ_NO_BALANCING in irq_data.state
In reply to Thomas GleixnerThat's the right data structure to look at for arch code.
Accessor functions are provided.
irqd_is_per_cpu(irqdata); irqd_can_balance(irqdata);
Coders who access them directly will be tracked down and slapped with stinking trouts.
--- include/linux/irq.h | 16 +++++++++++++++- kernel/irq/chip.c | 15 +++++++++------ kernel/irq/internals.h | 11 +++++++++++ kernel/irq/manage.c | 16 ++++++++++------ kernel/irq/migration.c | 2 +- kernel/irq/settings.h | 36 ++++++++++++++++++++++++++++++++++++ kernel/irq/spurious.c | 3 ++- 7 files changed, 84 insertions(+), 15 deletions(-)
include/linux/irq.h +15 -1
@@ -130,10 +130,14 @@ struct irq_data {* Bit masks for irq_data.state * * IRQD_SETAFFINITY_PENDING - Affinity setting is pending +* IRQD_NO_BALANCING - Balancing disabled for this IRQ +* IRQD_PER_CPU - Interrupt is per cpu */ enum {/* Bit 0 - 7 reserved for TYPE will use later */ -IRQD_SETAFFINITY_PENDING = (1 <<8 ), +IRQD_SETAFFINITY_PENDING = (1 <<8 ), +IRQD_NO_BALANCING = (1 <<10 ), +IRQD_PER_CPU = (1 <<11 ), };static inline bool irqd_is_setaffinity_pending (struct irq_data *d)
@@ -141,6 +145,16 @@ static inline bool irqd_is_setaffinity_preturn d->state_use_accessors &IRQD_SETAFFINITY_PENDING ; } +static inline bool irqd_is_per_cpu (struct irq_data *d) +{ +return d->state_use_accessors &IRQD_PER_CPU ; +} + +static inline bool irqd_can_balance (struct irq_data *d) +{ +return !(d->state_use_accessors & (IRQD_PER_CPU |IRQD_NO_BALANCING )); +} +/** * struct irq_chip - hardware interrupt chip descriptor *
kernel/irq/chip.c +9 -6
@@ -732,12 +732,15 @@ void irq_modify_status(unsigned int irq,if (!desc)return ; -/* Sanitize flags */ - set &=IRQF_MODIFY_MASK ; - clr &=IRQF_MODIFY_MASK ; -raw_spin_lock_irqsave (&desc->lock, flags); - desc->status &= ~clr; - desc->status |= set; + +irq_settings_clr_and_set (desc, clr, set); + +irqd_clear (&desc->irq_data,IRQD_NO_BALANCING |IRQD_PER_CPU ); +if (irq_settings_has_no_balance_set (desc)) +irqd_set (&desc->irq_data,IRQD_NO_BALANCING ); +if (irq_settings_is_per_cpu (desc)) +irqd_set (&desc->irq_data,IRQD_PER_CPU ); +raw_spin_unlock_irqrestore (&desc->lock, flags); }
kernel/irq/internals.h +11 -0
@@ -137,3 +137,14 @@ static inline void irqd_clr_move_pending d->state_use_accessors &= ~IRQD_SETAFFINITY_PENDING ;irq_compat_clr_move_pending (irq_data_to_desc (d)); } + +static inline void irqd_clear (struct irq_data *d,unsigned int mask) +{ + d->state_use_accessors &= ~mask; +} + +static inline void irqd_set (struct irq_data *d,unsigned int mask) +{ + d->state_use_accessors |= mask; +} +
kernel/irq/manage.c +10 -6
@@ -73,8 +73,8 @@ int irq_can_set_affinity(unsigned int ir {struct irq_desc *desc =irq_to_desc (irq); -if ((desc->status & (IRQ_PER_CPU |IRQ_NO_BALANCING )) || - !desc->irq_data.chip || !desc->irq_data.chip->irq_set_affinity) +if (!irqd_can_balance (&desc->irq_data) || !desc->irq_data.chip || + !desc->irq_data.chip->irq_set_affinity)return 0 ;return 1 ;
@@ -903,8 +903,10 @@ __setup_irq(unsigned int irq, struct irqIRQS_INPROGRESS |IRQS_ONESHOT | \ IRQS_WAITING); -if (new->flags &IRQF_PERCPU ) - desc->status |=IRQ_PER_CPU ; +if (new->flags &IRQF_PERCPU ) { +irqd_set (&desc->irq_data,IRQD_PER_CPU ); +irq_settings_set_per_cpu (desc); + }if (new->flags &IRQF_ONESHOT ) desc->istate |=IRQS_ONESHOT ;
@@ -916,8 +918,10 @@ __setup_irq(unsigned int irq, struct irq desc->depth =1 ;/* Exclude IRQ from balancing if requested */ -if (new->flags &IRQF_NOBALANCING ) - desc->status |=IRQ_NO_BALANCING ; +if (new->flags &IRQF_NOBALANCING ) { +irq_settings_set_no_balancing (desc); +irqd_set (&desc->irq_data,IRQD_NO_BALANCING ); + }/* Set default affinity mask once everything is setup */ setup_affinity (irq, desc, mask);
kernel/irq/migration.c +1 -1
@@ -15,7 +15,7 @@ void move_masked_irq(int irq)/* * Paranoia: cpu-local interrupts shouldn't be calling in here anyway. */ -if (desc->status & (IRQ_PER_CPU |IRQ_NO_BALANCING )) { +if (!irqd_can_balance (&desc->irq_data)) {WARN_ON (1 );return ; }
kernel/irq/settings.h +36 -0
@@ -4,6 +4,9 @@*/ enum { _IRQ_DEFAULT_INIT_FLAGS =IRQ_DEFAULT_INIT_FLAGS , + _IRQ_PER_CPU =IRQ_PER_CPU , + _IRQ_NO_BALANCING =IRQ_NO_BALANCING , + _IRQF_MODIFY_MASK =IRQF_MODIFY_MASK , };#undef IRQ_INPROGRESS
@@ -22,3 +25,36 @@ enum {#define IRQ_WAKEUP GOT_YOU_MORON#undef IRQ_MOVE_PENDING#define IRQ_MOVE_PENDING GOT_YOU_MORON +#undef IRQ_PER_CPU +#define IRQ_PER_CPU GOT_YOU_MORON +#undef IRQ_NO_BALANCING +#define IRQ_NO_BALANCING GOT_YOU_MORON +#undef IRQF_MODIFY_MASK +#define IRQF_MODIFY_MASK GOT_YOU_MORON + +static inline void +irq_settings_clr_and_set (struct irq_desc *desc,u32 clr,u32 set) +{ + desc->status &= ~(clr & _IRQF_MODIFY_MASK); + desc->status |= (set & _IRQF_MODIFY_MASK); +} + +static inline bool irq_settings_is_per_cpu (struct irq_desc *desc) +{ +return desc->status & _IRQ_PER_CPU; +} + +static inline void irq_settings_set_per_cpu (struct irq_desc *desc) +{ + desc->status |= _IRQ_PER_CPU; +} + +static inline void irq_settings_set_no_balancing (struct irq_desc *desc) +{ + desc->status |= _IRQ_NO_BALANCING; +} + +static inline bool irq_settings_has_no_balance_set (struct irq_desc *desc) +{ +return desc->status & _IRQ_NO_BALANCING; +}
kernel/irq/spurious.c +2 -1
@@ -68,7 +68,8 @@ static int try_one_irq(int irq, struct iraw_spin_lock (&desc->lock);/* PER_CPU and nested thread interrupts are never polled */ -if ((desc->status &IRQ_PER_CPU ) || (desc->istate &IRQS_NESTED_THREAD )) +if (irq_settings_is_per_cpu (desc) || + (desc->istate &IRQS_NESTED_THREAD )) goto out;/*
PATCH 56/75 genirq: Reuse existing can set affinty check
In reply to Thomas GleixnerAdd a !desc check while at it.
--- kernel/irq/manage.c | 4 ++-- kernel/irq/proc.c | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-)
kernel/irq/manage.c +2 -2
@@ -73,8 +73,8 @@ int irq_can_set_affinity(unsigned int ir {struct irq_desc *desc =irq_to_desc (irq); -if (!irqd_can_balance (&desc->irq_data) || !desc->irq_data.chip || - !desc->irq_data.chip->irq_set_affinity) +if (!desc || !irqd_can_balance (&desc->irq_data) || + !desc->irq_data.chip || !desc->irq_data.chip->irq_set_affinity)return 0 ;return 1 ;
kernel/irq/proc.c +1 -2
@@ -66,8 +66,7 @@ static ssize_t irq_affinity_proc_write(scpumask_var_t new_value;int err; -if (!irq_to_desc (irq)->irq_data.chip->irq_set_affinity || no_irq_affinity || -irq_balancing_disabled (irq)) +if (!irq_can_set_affinity (irq) || no_irq_affinity)return -EIO ;if (!alloc_cpumask_var (&new_value,GFP_KERNEL ))
PATCH 57/75 genirq: Move IRQ_AFFINITY_SET to core
In reply to Thomas GleixnerKeep status in sync until last abuser is gone.
--- include/linux/irq.h | 9 ++++++++- kernel/irq/compat.h | 11 +++++++++++ kernel/irq/internals.h | 4 ++++ kernel/irq/manage.c | 11 +++++++---- kernel/irq/settings.h | 2 ++ 5 files changed, 32 insertions(+), 5 deletions(-)
include/linux/irq.h +8 -1
@@ -60,6 +60,7 @@ typedef void (*irq_flow_handler_t)(unsig#define IRQ_MASKED 0x00002000/* DEPRECATED */ /* DEPRECATED use irq_setaffinity_pending() instead*/ #define IRQ_MOVE_PENDING 0x00004000 +#define IRQ_AFFINITY_SET 0x02000000/* DEPRECATED */ #endif #define IRQ_LEVEL 0x00008000/* IRQ level triggered */
@@ -69,7 +70,6 @@ typedef void (*irq_flow_handler_t)(unsig#define IRQ_NOAUTOEN 0x00080000/* IRQ will not be enabled on request irq */ #define IRQ_NO_BALANCING 0x00400000/* IRQ is excluded from balancing */ #define IRQ_MOVE_PCNTXT 0x01000000/* IRQ migration from process context */ -#define IRQ_AFFINITY_SET 0x02000000/* IRQ affinity was set from userspace*/ #define IRQF_MODIFY_MASK \ (IRQ_TYPE_SENSE_MASK | IRQ_NOPROBE | IRQ_NOREQUEST | \
@@ -132,12 +132,14 @@ struct irq_data {* IRQD_SETAFFINITY_PENDING - Affinity setting is pending * IRQD_NO_BALANCING - Balancing disabled for this IRQ * IRQD_PER_CPU - Interrupt is per cpu +* IRQD_AFFINITY_SET - Interrupt affinity was set */ enum {/* Bit 0 - 7 reserved for TYPE will use later */ IRQD_SETAFFINITY_PENDING = (1 <<8 ),IRQD_NO_BALANCING = (1 <<10 ),IRQD_PER_CPU = (1 <<11 ), +IRQD_AFFINITY_SET = (1 <<12 ), };static inline bool irqd_is_setaffinity_pending (struct irq_data *d)
@@ -155,6 +157,11 @@ static inline bool irqd_can_balance(strureturn !(d->state_use_accessors & (IRQD_PER_CPU |IRQD_NO_BALANCING )); } +static inline bool irqd_affinity_was_set (struct irq_data *d) +{ +return d->state_use_accessors &IRQD_AFFINITY_SET ; +} +/** * struct irq_chip - hardware interrupt chip descriptor *
kernel/irq/compat.h +11 -0
@@ -46,6 +46,15 @@ static inline void irq_compat_clr_move_p { desc->status &= ~IRQ_MOVE_PENDING ; } +static inline void irq_compat_set_affinity (struct irq_desc *desc) +{ + desc->status |=IRQ_AFFINITY_SET ; +} + +static inline void irq_compat_clr_affinity (struct irq_desc *desc) +{ + desc->status &= ~IRQ_AFFINITY_SET ; +}#else static inline void irq_compat_set_progress (struct irq_desc *desc) { }static inline void irq_compat_clr_progress (struct irq_desc *desc) { }
@@ -57,5 +66,7 @@ static inline void irq_compat_set_maskedstatic inline void irq_compat_clr_masked (struct irq_desc *desc) { }static inline void irq_compat_set_move_pending (struct irq_desc *desc) { }static inline void irq_compat_clr_move_pending (struct irq_desc *desc) { } +static inline void irq_compat_set_affinity (struct irq_desc *desc) { } +static inline void irq_compat_clr_affinity (struct irq_desc *desc) { }#endif
kernel/irq/internals.h +4 -0
@@ -148,3 +148,7 @@ static inline void irqd_set(struct irq_d d->state_use_accessors |= mask; } +static inline bool irqd_has_set (struct irq_data *d,unsigned int mask) +{ +return d->state_use_accessors & mask; +}
kernel/irq/manage.c +7 -4
@@ -164,7 +164,8 @@ int irq_set_affinity(unsigned int irq, ckref_get (&desc->affinity_notify->kref);schedule_work (&desc->affinity_notify->work); } - desc->status |=IRQ_AFFINITY_SET ; +irq_compat_set_affinity (desc); +irqd_set (&desc->irq_data,IRQD_AFFINITY_SET );raw_spin_unlock_irqrestore (&desc->lock, flags);return ret; }
@@ -272,12 +273,14 @@ setup_affinity(unsigned int irq, struct* Preserve an userspace affinity setup, but make sure that * one of the targets is online. */ -if (desc->status & (IRQ_AFFINITY_SET )) { +if (irqd_has_set (&desc->irq_data,IRQD_AFFINITY_SET )) {if (cpumask_intersects (desc->irq_data.affinity, cpu_online_mask)) set = desc->irq_data.affinity; -else - desc->status &= ~IRQ_AFFINITY_SET ; +else { +irq_compat_clr_affinity (desc); +irqd_clear (&desc->irq_data,IRQD_AFFINITY_SET ); + } }cpumask_and (mask, cpu_online_mask, set);
kernel/irq/settings.h +2 -0
@@ -29,6 +29,8 @@ enum {#define IRQ_PER_CPU GOT_YOU_MORON#undef IRQ_NO_BALANCING#define IRQ_NO_BALANCING GOT_YOU_MORON +#undef IRQ_AFFINITY_SET +#define IRQ_AFFINITY_SET GOT_YOU_MORON#undef IRQF_MODIFY_MASK#define IRQF_MODIFY_MASK GOT_YOU_MORON
PATCH 58/75 genirq: Mirror irq trigger type bits in irq_data.state
In reply to Thomas GleixnerThat's the data structure chip functions get provided. Also allow them to signal the core code that they updated the flags in irq_data.state by returning IRQ_SET_MASK_OK_NOCOPY. The default is unchanged.
The type bits should be accessed via:
val = irqd_get_trigger_type(irqdata);
andirqd_set_trigger_type(irqdata, val);
Coders who access them directly will be tracked down and slapped with stinking trouts.
---
--- include/linux/irq.h | 26 +++++++++++++++++++++++++- kernel/irq/chip.c | 5 ++++- kernel/irq/manage.c | 44 +++++++++++++++++++++++++++----------------- kernel/irq/resend.c | 2 +- kernel/irq/settings.h | 30 ++++++++++++++++++++++++++++++ 5 files changed, 87 insertions(+), 20 deletions(-)
include/linux/irq.h +25 -1
@@ -46,7 +46,9 @@ typedef void (*irq_flow_handler_t)(unsig#define IRQ_TYPE_EDGE_BOTH (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING)#define IRQ_TYPE_LEVEL_HIGH 0x00000004/* Level high type */ #define IRQ_TYPE_LEVEL_LOW 0x00000008/* Level low type */ +#define IRQ_TYPE_LEVEL_MASK (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH)#define IRQ_TYPE_SENSE_MASK 0x0000000f/* Mask of the above */ +#define IRQ_TYPE_PROBE 0x00000010/* Probing in progress */ /* Internal flags */
@@ -129,17 +131,20 @@ struct irq_data {/* * Bit masks for irq_data.state * +* IRQD_TRIGGER_MASK - Mask for the trigger type bits * IRQD_SETAFFINITY_PENDING - Affinity setting is pending * IRQD_NO_BALANCING - Balancing disabled for this IRQ * IRQD_PER_CPU - Interrupt is per cpu * IRQD_AFFINITY_SET - Interrupt affinity was set +* IRQD_LEVEL - Interrupt is level triggered */ enum { -/* Bit 0 - 7 reserved for TYPE will use later */ +IRQD_TRIGGER_MASK =0xf ,IRQD_SETAFFINITY_PENDING = (1 <<8 ),IRQD_NO_BALANCING = (1 <<10 ),IRQD_PER_CPU = (1 <<11 ),IRQD_AFFINITY_SET = (1 <<12 ), +IRQD_LEVEL = (1 <<13 ), };static inline bool irqd_is_setaffinity_pending (struct irq_data *d)
@@ -162,6 +167,25 @@ static inline bool irqd_affinity_was_setreturn d->state_use_accessors &IRQD_AFFINITY_SET ; } +static inline u32 irqd_get_trigger_type (struct irq_data *d) +{ +return d->state_use_accessors &IRQD_TRIGGER_MASK ; +} + +/* +* Must only be called inside irq_chip.irq_set_type() functions. +*/ +static inline void irqd_set_trigger_type (struct irq_data *d,u32 type) +{ + d->state_use_accessors &= ~IRQD_TRIGGER_MASK ; + d->state_use_accessors |= type &IRQD_TRIGGER_MASK ; +} + +static inline bool irqd_is_level_type (struct irq_data *d) +{ +return d->state_use_accessors &IRQD_LEVEL ; +} +/** * struct irq_chip - hardware interrupt chip descriptor *
kernel/irq/chip.c +4 -1
@@ -736,11 +736,14 @@ void irq_modify_status(unsigned int irq,irq_settings_clr_and_set (desc, clr, set); -irqd_clear (&desc->irq_data,IRQD_NO_BALANCING |IRQD_PER_CPU ); +irqd_clear (&desc->irq_data,IRQD_NO_BALANCING |IRQD_PER_CPU | +IRQD_TRIGGER_MASK |IRQD_LEVEL );if (irq_settings_has_no_balance_set (desc))irqd_set (&desc->irq_data,IRQD_NO_BALANCING );if (irq_settings_is_per_cpu (desc))irqd_set (&desc->irq_data,IRQD_PER_CPU ); +irqd_set (&desc->irq_data,irq_settings_get_trigger_mask (desc)); +raw_spin_unlock_irqrestore (&desc->lock, flags); }
kernel/irq/manage.c +27 -17
63 lines not on this page · raw message
kernel/irq/resend.c +1 -1
@@ -60,7 +60,7 @@ void check_irq_resend(struct irq_desc *d* interrupts are resent by hardware when they are still * active. */ -if (desc->status &IRQ_LEVEL ) +if (irq_settings_is_level (desc))return ;if (desc->istate &IRQS_REPLAY )return ;
kernel/irq/settings.h +30 -0
@@ -5,6 +5,7 @@enum { _IRQ_DEFAULT_INIT_FLAGS =IRQ_DEFAULT_INIT_FLAGS , _IRQ_PER_CPU =IRQ_PER_CPU , + _IRQ_LEVEL =IRQ_LEVEL , _IRQ_NO_BALANCING =IRQ_NO_BALANCING , _IRQF_MODIFY_MASK =IRQF_MODIFY_MASK , };
@@ -31,6 +32,8 @@ enum {#define IRQ_NO_BALANCING GOT_YOU_MORON#undef IRQ_AFFINITY_SET#define IRQ_AFFINITY_SET GOT_YOU_MORON +#undef IRQ_LEVEL +#define IRQ_LEVEL GOT_YOU_MORON#undef IRQF_MODIFY_MASK#define IRQF_MODIFY_MASK GOT_YOU_MORON
@@ -60,3 +63,30 @@ static inline bool irq_settings_has_no_b {return desc->status & _IRQ_NO_BALANCING; } + +static inline u32 irq_settings_get_trigger_mask (struct irq_desc *desc) +{ +return desc->status &IRQ_TYPE_SENSE_MASK ; +} + +static inline void +irq_settings_set_trigger_mask (struct irq_desc *desc,u32 mask) +{ + desc->status &= ~IRQ_TYPE_SENSE_MASK ; + desc->status |= mask &IRQ_TYPE_SENSE_MASK ; +} + +static inline bool irq_settings_is_level (struct irq_desc *desc) +{ +return desc->status & _IRQ_LEVEL; +} + +static inline void irq_settings_clr_level (struct irq_desc *desc) +{ + desc->status &= ~_IRQ_LEVEL; +} + +static inline void irq_settings_set_level (struct irq_desc *desc) +{ + desc->status |= _IRQ_LEVEL; +}
PATCH 59/75 genirq: Wrap the remaning IRQ_* flags
In reply to Thomas GleixnerUse wrappers to keep them away from the core code.
--- kernel/irq/autoprobe.c | 4 +-- kernel/irq/chip.c | 3 +- kernel/irq/manage.c | 10 ++++----- kernel/irq/settings.h | 50 +++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 59 insertions(+), 8 deletions(-)
kernel/irq/autoprobe.c +2 -2
@@ -45,7 +45,7 @@ unsigned long probe_irq_on(void)*/ for_each_irq_desc_reverse (i, desc) {raw_spin_lock_irq (&desc->lock); -if (!desc->action && !(desc->status &IRQ_NOPROBE )) { +if (!desc->action &&irq_settings_can_probe (desc)) {/* * An old-style architecture might still have * the handle_bad_irq handler there:
@@ -74,7 +74,7 @@ unsigned long probe_irq_on(void)*/ for_each_irq_desc_reverse (i, desc) {raw_spin_lock_irq (&desc->lock); -if (!desc->action && !(desc->status &IRQ_NOPROBE )) { +if (!desc->action &&irq_settings_can_probe (desc)) { desc->istate |=IRQS_AUTODETECT |IRQS_WAITING ;if (irq_startup (desc)) {irq_compat_set_pending (desc);
kernel/irq/chip.c +2 -1
@@ -700,7 +700,8 @@ __set_irq_handler(unsigned int irq, irq_ desc->name = name;if (handle != handle_bad_irq && is_chained) { - desc->status |=IRQ_NOREQUEST |IRQ_NOPROBE ; +irq_settings_set_noprobe (desc); +irq_settings_set_norequest (desc);irq_startup (desc); }raw_spin_unlock_irqrestore (&desc->lock, flags);
kernel/irq/manage.c +5 -5
@@ -103,7 +103,7 @@ void irq_set_thread_affinity(struct irq_#ifdef CONFIG_GENERIC_PENDING_IRQ static inline bool irq_can_move_pcntxt (struct irq_desc *desc) { -return desc->status &IRQ_MOVE_PCNTXT ; +return irq_settings_can_move_pcntxt (desc); }static inline bool irq_move_pending (struct irq_desc *desc) {
@@ -419,7 +419,7 @@ void __enable_irq(struct irq_desc *desc,if (desc->istate &IRQS_SUSPENDED ) goto err_out;/* Prevent probing on this irq: */ - desc->status |=IRQ_NOPROBE ; +irq_settings_set_noprobe (desc);irq_enable (desc);check_irq_resend (desc, irq);/* fall-through */
@@ -532,7 +532,7 @@ int can_request_irq(unsigned int irq, unif (!desc)return 0 ; -if (desc->status &IRQ_NOREQUEST ) +if (!irq_settings_can_request (desc))return 0 ;raw_spin_lock_irqsave (&desc->lock, flags);
@@ -923,7 +923,7 @@ __setup_irq(unsigned int irq, struct irqif (new->flags &IRQF_ONESHOT ) desc->istate |=IRQS_ONESHOT ; -if (!(desc->status &IRQ_NOAUTOEN )) +if (irq_settings_can_autoenable (desc))irq_startup (desc);else /* Undo nested disables: */
@@ -1218,7 +1218,7 @@ int request_threaded_irq(unsigned int irif (!desc)return -EINVAL ; -if (desc->status &IRQ_NOREQUEST ) +if (!irq_settings_can_request (desc))return -EINVAL ;if (!handler) {
kernel/irq/settings.h +50 -0
65 lines not on this page · raw message
PATCH 60/75 genirq: Force wrapped access to desc->status in core code
In reply to Thomas GleixnerForce the usage of wrappers by another nasty CPP substitution.
--- kernel/irq/handle.c | 6 +++--- kernel/irq/irqdesc.c | 4 ++-- kernel/irq/settings.h | 3 +++ 3 files changed, 8 insertions(+), 5 deletions(-)
kernel/irq/handle.c +3 -3
@@ -55,7 +55,7 @@ irqreturn_t handle_irq_event_percpu(struct irq_desc *desc, struct irqaction *action) { irqreturn_t ret, retval = IRQ_NONE; -unsigned int status =0 , irq = desc->irq_data.irq; +unsigned int random =0 , irq = desc->irq_data.irq; do { trace_irq_handler_entry(irq, action);
@@ -98,7 +98,7 @@ handle_irq_event_percpu(struct irq_desc/* Fall through to add to randomness */ case IRQ_HANDLED : - status |= action->flags; + random |= action->flags;break ;default :
@@ -109,7 +109,7 @@ handle_irq_event_percpu(struct irq_desc action = action->next; }while (action); -if (status &IRQF_SAMPLE_RANDOM ) +if (random &IRQF_SAMPLE_RANDOM )add_interrupt_randomness (irq);if (!noirqdebug)
kernel/irq/irqdesc.c +2 -2
@@ -79,7 +79,7 @@ static void desc_set_defaults(unsigned i desc->irq_data.chip_data =NULL ; desc->irq_data.handler_data =NULL ; desc->irq_data.msi_desc =NULL ; - desc->status = _IRQ_DEFAULT_INIT_FLAGS; +irq_settings_clr_and_set (desc, ~0 , _IRQ_DEFAULT_INIT_FLAGS); desc->istate =IRQS_DISABLED ; desc->handle_irq = handle_bad_irq; desc->depth =1 ;
@@ -230,7 +230,6 @@ int __init early_irq_init(void) struct irq_desc irq_desc[NR_IRQS] __cacheline_aligned_in_smp = { [0 ...NR_IRQS -1 ] = { - .status = _IRQ_DEFAULT_INIT_FLAGS, .istate =IRQS_DISABLED , .handle_irq = handle_bad_irq, .depth =1 ,
@@ -254,6 +253,7 @@ int __init early_irq_init(void) desc[i].irq_data.irq = i; desc[i].irq_data.chip = &no_irq_chip; desc[i].kstat_irqs = alloc_percpu(unsigned int); +irq_settings_clr_and_set (desc, ~0 , _IRQ_DEFAULT_INIT_FLAGS);alloc_masks (desc + i,GFP_KERNEL , node);desc_smp_init (desc + i, node);lockdep_set_class (&desc[i].lock, &irq_desc_lock_class);
kernel/irq/settings.h +3 -0
@@ -140,3 +140,6 @@ static inline bool irq_settings_can_auto {return !(desc->status & _IRQ_NOAUTOEN); } + +/* Nothing should touch desc->status from now on */ +#define status USE_THE_PROPER_WRAPPERS_YOU_MORON
PATCH 61/75 genirq: Cleanup irq.h
In reply to Thomas GleixnerPut the constants into an enum and document them.
--- include/linux/irq.h | 90 ++++++++++++++++++++++++++++++++------------------ kernel/irq/settings.h | 15 -------- 2 files changed, 59 insertions(+), 46 deletions(-)
include/linux/irq.h +59 -31
@@ -36,42 +36,70 @@ typedef void (*irq_flow_handler_t)(unsig/* * IRQ line status. * -* Bits 0-7 are reserved for the IRQF_* bits in linux/interrupt.h +* Bits 0-7 are the same as the IRQF_* bits in linux/interrupt.h +* +* IRQ_TYPE_NONE - default, unspecified type +* IRQ_TYPE_EDGE_RISING - rising edge triggered +* IRQ_TYPE_EDGE_FALLING - falling edge triggered +* IRQ_TYPE_EDGE_BOTH - rising and falling edge triggered +* IRQ_TYPE_LEVEL_HIGH - high level triggered +* IRQ_TYPE_LEVEL_LOW - low level triggered +* IRQ_TYPE_LEVEL_MASK - Mask to filter out the level bits +* IRQ_TYPE_SENSE_MASK - Mask for all the above bits +* IRQ_TYPE_PROBE - Special flag for probing in progress +* +* Bits which can be modified via irq_set/clear/modify_status_flags() +* IRQ_LEVEL - Interrupt is level type. Will be also +* updated in the code when the above trigger +* bits are modified via set_irq_type() +* IRQ_PER_CPU - Mark an interrupt PER_CPU. Will protect +* it from affinity setting +* IRQ_NOPROBE - Interrupt cannot be probed by autoprobing +* IRQ_NOREQUEST - Interrupt cannot be requested via +* request_irq() +* IRQ_NOAUTOEN - Interrupt is not automatically enabled in +* request/setup_irq() +* IRQ_NO_BALANCING - Interrupt cannot be balanced (affinity set) +* IRQ_MOVE_PCNTXT - Interrupt can be migrated from process context +* +* Deprecated bits. They are kept updated as long as +* CONFIG_GENERIC_HARDIRQS_NO_COMPAT is not set. Will go away soon. These bits +* are internal state of the core code and if you really need to acces +* them then talk to the genirq maintainer instead of hacking +* something weird. * -* IRQ types */ -#define IRQ_TYPE_NONE 0x00000000/* Default, unspecified type */ -#define IRQ_TYPE_EDGE_RISING 0x00000001/* Edge rising type */ -#define IRQ_TYPE_EDGE_FALLING 0x00000002/* Edge falling type */ -#define IRQ_TYPE_EDGE_BOTH (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING) -#define IRQ_TYPE_LEVEL_HIGH 0x00000004/* Level high type */ -#define IRQ_TYPE_LEVEL_LOW 0x00000008/* Level low type */ -#define IRQ_TYPE_LEVEL_MASK (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH) -#define IRQ_TYPE_SENSE_MASK 0x0000000f/* Mask of the above */ - -#define IRQ_TYPE_PROBE 0x00000010/* Probing in progress */ - -/* Internal flags */ +enum { +IRQ_TYPE_NONE =0x00000000 , +IRQ_TYPE_EDGE_RISING =0x00000001 , +IRQ_TYPE_EDGE_FALLING =0x00000002 , +IRQ_TYPE_EDGE_BOTH = (IRQ_TYPE_EDGE_FALLING |IRQ_TYPE_EDGE_RISING ), +IRQ_TYPE_LEVEL_HIGH =0x00000004 , +IRQ_TYPE_LEVEL_LOW =0x00000008 , +IRQ_TYPE_LEVEL_MASK = (IRQ_TYPE_LEVEL_LOW |IRQ_TYPE_LEVEL_HIGH ), +IRQ_TYPE_SENSE_MASK =0x0000000f , + +IRQ_TYPE_PROBE =0x00000010 , + +IRQ_LEVEL = (1 <<8 ), +IRQ_PER_CPU = (1 <<9 ), +IRQ_NOPROBE = (1 <<10 ), +IRQ_NOREQUEST = (1 <<11 ), +IRQ_NOAUTOEN = (1 <<12 ), +IRQ_NO_BALANCING = (1 <<13 ), +IRQ_MOVE_PCNTXT = (1 <<14 ),#ifndef CONFIG_GENERIC_HARDIRQS_NO_COMPAT -#define IRQ_INPROGRESS 0x00000100/* DEPRECATED */ -#define IRQ_REPLAY 0x00000200/* DEPRECATED */ -#define IRQ_WAITING 0x00000400/* DEPRECATED */ -#define IRQ_DISABLED 0x00000800/* DEPRECATED */ -#define IRQ_PENDING 0x00001000/* DEPRECATED */ -#define IRQ_MASKED 0x00002000/* DEPRECATED */ -/* DEPRECATED use irq_setaffinity_pending() instead*/ -#define IRQ_MOVE_PENDING 0x00004000 -#define IRQ_AFFINITY_SET 0x02000000/* DEPRECATED */ +IRQ_INPROGRESS = (1 <<24 ), +IRQ_REPLAY = (1 <<25 ), +IRQ_WAITING = (1 <<26 ), +IRQ_DISABLED = (1 <<27 ), +IRQ_PENDING = (1 <<28 ), +IRQ_MASKED = (1 <<29 ), +IRQ_MOVE_PENDING = (1 <<30 ), +IRQ_AFFINITY_SET = (1 <<31 ),#endif - -#define IRQ_LEVEL 0x00008000/* IRQ level triggered */ -#define IRQ_PER_CPU 0x00010000/* IRQ is per CPU */ -#define IRQ_NOPROBE 0x00020000/* IRQ is not valid for probing */ -#define IRQ_NOREQUEST 0x00040000/* IRQ cannot be requested */ -#define IRQ_NOAUTOEN 0x00080000/* IRQ will not be enabled on request irq */ -#define IRQ_NO_BALANCING 0x00400000/* IRQ is excluded from balancing */ -#define IRQ_MOVE_PCNTXT 0x01000000/* IRQ migration from process context */ +};#define IRQF_MODIFY_MASK \ (IRQ_TYPE_SENSE_MASK | IRQ_NOPROBE | IRQ_NOREQUEST | \
kernel/irq/settings.h +0 -15
@@ -14,35 +14,20 @@ enum { _IRQF_MODIFY_MASK = IRQF_MODIFY_MASK, }; -#undef IRQ_INPROGRESS#define IRQ_INPROGRESS GOT_YOU_MORON -#undef IRQ_REPLAY#define IRQ_REPLAY GOT_YOU_MORON -#undef IRQ_WAITING#define IRQ_WAITING GOT_YOU_MORON -#undef IRQ_DISABLED#define IRQ_DISABLED GOT_YOU_MORON -#undef IRQ_PENDING#define IRQ_PENDING GOT_YOU_MORON -#undef IRQ_MASKED#define IRQ_MASKED GOT_YOU_MORON -#undef IRQ_WAKEUP#define IRQ_WAKEUP GOT_YOU_MORON -#undef IRQ_MOVE_PENDING#define IRQ_MOVE_PENDING GOT_YOU_MORON -#undef IRQ_PER_CPU#define IRQ_PER_CPU GOT_YOU_MORON -#undef IRQ_NO_BALANCING#define IRQ_NO_BALANCING GOT_YOU_MORON -#undef IRQ_AFFINITY_SET#define IRQ_AFFINITY_SET GOT_YOU_MORON -#undef IRQ_LEVEL#define IRQ_LEVEL GOT_YOU_MORON -#undef IRQ_NOPROBE#define IRQ_NOPROBE GOT_YOU_MORON -#undef IRQ_NOREQUEST#define IRQ_NOREQUEST GOT_YOU_MORON -#undef IRQ_NOAUTOEN#define IRQ_NOATOEN GOT_YOU_MORON#undef IRQF_MODIFY_MASK#define IRQF_MODIFY_MASK GOT_YOU_MORON
PATCH 62/75 genirq: Add flags to irq_chip
In reply to Thomas GleixnerLooking through irq_chip implementations I noticed that some of them have special requirements, like setting the type masked and therefor fiddle in irq_desc->status. Add a flag field, so the core code can handle it.
--- include/linux/irq.h | 3 +++ 1 file changed, 3 insertions(+)
include/linux/irq.h +3 -0
@@ -250,6 +250,7 @@ static inline bool irqd_is_level_type(st* @irq_set_wake: enable/disable power-management wake-on of an IRQ * @irq_bus_lock: function to lock access to slow bus (i2c) chips * @irq_bus_sync_unlock:function to sync and unlock slow bus (i2c) chips +* @flags: chip specific flags * * @release: release function solely used by UML */
@@ -296,6 +297,8 @@ struct irq_chip {void (*irq_bus_lock)(struct irq_data *data);void (*irq_bus_sync_unlock)(struct irq_data *data); +unsigned long flags; +/* Currently used only by UML, might disappear one day.*/ #ifdef CONFIG_IRQ_RELEASE_METHOD void (*release)(unsigned int irq,void *dev_id);
PATCH 63/75 genirq: Add IRQCHIP_SET_TYPE_MASKED flag and IRQD_WAKE_SET
In reply to Thomas Gleixnerirq_chips, which require to mask the chip before changing the trigger type should set this flag. So the core takes care of it and the requirement for looking into desc->status in the chip goes away.
Add also a flag which reflects the WAKEUP state of the interrupt line, which is also required by some of those chips.
--- include/linux/irq.h | 9 +++++++++ kernel/irq/chip.c | 4 ++-- kernel/irq/internals.h | 2 ++ kernel/irq/manage.c | 14 ++++++++++++-- 4 files changed, 25 insertions(+), 4 deletions(-)
include/linux/irq.h +9 -0
@@ -305,6 +305,15 @@ struct irq_chip {#endif }; +/* +* irq_chip specific flags +* +* IRQCHIP_SET_TYPE_MASKED: Mask before calling chip.irq_set_type() +*/ +enum { +IRQCHIP_SET_TYPE_MASKED = (1 <<0 ), +}; +/* This include will go away once we isolated irq_desc usage to core code */ #include <linux/irqdesc.h>
kernel/irq/chip.c +2 -2
@@ -393,7 +393,7 @@ static inline void mask_ack_irq(struct iirq_state_set_masked (desc); } -static inline void mask_irq (struct irq_desc *desc) +void mask_irq (struct irq_desc *desc) {if (desc->irq_data.chip->irq_mask) { desc->irq_data.chip->irq_mask (&desc->irq_data);
@@ -401,7 +401,7 @@ static inline void mask_irq(struct irq_d } } -static inline void unmask_irq (struct irq_desc *desc) +void unmask_irq (struct irq_desc *desc) {if (desc->irq_data.chip->irq_unmask) { desc->irq_data.chip->irq_unmask (&desc->irq_data);
kernel/irq/internals.h +2 -0
@@ -81,6 +81,8 @@ extern int irq_startup(struct irq_desc *extern void irq_shutdown (struct irq_desc *desc);extern void irq_enable (struct irq_desc *desc);extern void irq_disable (struct irq_desc *desc); +extern void mask_irq (struct irq_desc *desc); +extern void unmask_irq (struct irq_desc *desc);extern void init_kstat_irqs (struct irq_desc *desc,int node,int nr);
kernel/irq/manage.c +12 -2
@@ -560,8 +560,8 @@ void compat_irq_chip_set_default_handlerint __irq_set_trigger (struct irq_desc *desc,unsigned int irq,unsigned long flags) { -int ret;struct irq_chip *chip = desc->irq_data.chip; +int ret, unmask =0 ;if (!chip || !chip->irq_set_type) {/*
@@ -574,6 +574,14 @@ int __irq_set_trigger(struct irq_desc *d } flags &=IRQ_TYPE_SENSE_MASK ; + +if (chip->flags &IRQCHIP_SET_TYPE_MASKED ) { +if (!(desc->istate &IRQS_MASKED )) +mask_irq (desc); +if (!(desc->istate &IRQS_DISABLED )) + unmask =1 ; + } +/* caller masked out all except trigger mode flags */ ret = chip->irq_set_type (&desc->irq_data, flags);
@@ -599,6 +607,8 @@ int __irq_set_trigger(struct irq_desc *dpr_err ("setting trigger mode %lu for irq %u failed (%pF)\n" , flags, irq, chip->irq_set_type); } +if (unmask) +unmask_irq (desc);return ret; }
@@ -675,7 +685,7 @@ again:#ifdef CONFIG_SMP /* -* Check whether we need to change the affinity of the interrupt thread. +* Check whether we need to chasnge the affinity of the interrupt thread. */ static void irq_thread_check_affinity (struct irq_desc *desc,struct irqaction *action)
Re: [patch 63/75] genirq: Add IRQCHIP_SET_TYPE_MASKED flag and IRQD_WAKE_SET
Quoted 2 lines · Thomas Gleixner
Add also a flag which reflects the WAKEUP state of the interrupt line, which is also required by some of those chips.
This part (the IRQD_WAKE_SET mentioned in the subject) appears to be missing from this patch?
Re: [patch 63/75] genirq: Add IRQCHIP_SET_TYPE_MASKED flag and IRQD_WAKE_SET
Quoted 6 lines · Rabin Vincent
Quoted 2 lines · Thomas Gleixner
Add also a flag which reflects the WAKEUP state of the interrupt line, which is also required by some of those chips.
This part (the
IRQD_WAKE_SETmentioned in the subject) appears to be missing from this patch?
Yep, intentionally. Subject line is crapped. Fixed locally already.
Thanks for pointing it out.
tglx
PATCH 64/75 genirq: Move wakeup state to irq_data
In reply to Thomas GleixnerSome irq_chips need to know the state of wakeup mode for setting the trigger type etc. Reflect it in irq_data state.
--- include/linux/irq.h | 8 ++++++++ kernel/irq/internals.h | 2 -- kernel/irq/manage.c | 4 ++-- kernel/irq/pm.c | 2 +- 4 files changed, 11 insertions(+), 5 deletions(-)
include/linux/irq.h +8 -0
@@ -165,6 +165,8 @@ struct irq_data {* IRQD_PER_CPU - Interrupt is per cpu * IRQD_AFFINITY_SET - Interrupt affinity was set * IRQD_LEVEL - Interrupt is level triggered +* IRQD_WAKEUP_STATE - Interrupt is configured for wakeup +* from suspend */ enum {IRQD_TRIGGER_MASK =0xf ,
@@ -173,6 +175,7 @@ enum {IRQD_PER_CPU = (1 <<11 ),IRQD_AFFINITY_SET = (1 <<12 ),IRQD_LEVEL = (1 <<13 ), + IRQD_WAKEUP_STATE = (1 << 14), };static inline bool irqd_is_setaffinity_pending (struct irq_data *d)
@@ -214,6 +217,11 @@ static inline bool irqd_is_level_type(streturn d->state_use_accessors &IRQD_LEVEL ; } +static inline bool irqd_is_wakeup_set (struct irq_data *d) +{ +return d->state_use_accessors &IRQD_WAKEUP_STATE ; +} +/** * struct irq_chip - hardware interrupt chip descriptor *
kernel/irq/internals.h +0 -2
@@ -42,7 +42,6 @@ enum {* IRQS_PENDING - irq is pending and replayed later * IRQS_MASKED - irq is masked * IRQS_SUSPENDED - irq is suspended -* IRQS_WAKEUP - irq triggers system wakeup from suspend */ enum {IRQS_AUTODETECT =0x00000001 ,
@@ -57,7 +56,6 @@ enum {IRQS_PENDING =0x00000200 ,IRQS_MASKED =0x00000400 , IRQS_SUSPENDED = 0x00000800, - IRQS_WAKEUP = 0x00001000, };#include "compat.h"
kernel/irq/manage.c +2 -2
@@ -499,7 +499,7 @@ int set_irq_wake(unsigned int irq, unsigif (ret) desc->wake_depth =0 ;else - desc->istate |=IRQS_WAKEUP ; +irqd_set (&desc->irq_data,IRQD_WAKEUP_STATE ); } }else {if (desc->wake_depth ==0 ) {
@@ -509,7 +509,7 @@ int set_irq_wake(unsigned int irq, unsigif (ret) desc->wake_depth =1 ;else - desc->istate &= ~IRQS_WAKEUP ; +irqd_clear (&desc->irq_data,IRQD_WAKEUP_STATE ); } }
kernel/irq/pm.c +1 -1
@@ -69,7 +69,7 @@ int check_wakeup_irqs(void)int irq;for_each_irq_desc (irq, desc) -if ((desc->istate &IRQS_WAKEUP ) && +if (irqd_is_wakeup_set (&desc->irq_data) && (desc->istate &IRQS_PENDING ))return -EBUSY ;
PATCH 65/75 genirq: Reflect IRQ_INPROGRESS/DISABLED in irq_data.state
In reply to Thomas GleixnerSome irq_chips check irq_desc->state for IRQ_DISABLED or IRQ_INPROGRESS in their irq_eoi() function. Reflect the state in irq_data.state so they can access it there.
Note, that this state is only valid in the irq_chip callbacks. Looking at the state in other context has no guarantee for correctness.
--- include/linux/irq.h | 16 ++++++++++++++++ kernel/irq/chip.c | 2 ++ kernel/irq/handle.c | 2 ++ 3 files changed, 20 insertions(+)
include/linux/irq.h +16 -0
@@ -167,6 +167,10 @@ struct irq_data {* IRQD_LEVEL - Interrupt is level triggered * IRQD_WAKEUP_STATE - Interrupt is configured for wakeup * from suspend +* IRDQ_DISABLED - Interrupt is disabled, only +* valid in irq_chip.functions +* IRDQ_INPROGRESS - Interrupt is in progress, only +* valid in irq_chip.functions */ enum {IRQD_TRIGGER_MASK =0xf ,
@@ -176,6 +180,8 @@ enum {IRQD_AFFINITY_SET = (1 <<12 ),IRQD_LEVEL = (1 <<13 ),IRQD_WAKEUP_STATE = (1 <<14 ), +IRQD_DISABLED = (1 <<15 ), + IRQD_INPROGRESS = (1 << 16), };static inline bool irqd_is_setaffinity_pending (struct irq_data *d)
@@ -222,6 +228,16 @@ static inline bool irqd_is_wakeup_set(streturn d->state_use_accessors &IRQD_WAKEUP_STATE ; } +static inline bool irqd_is_inprogres (struct irq_data *d) +{ +return d->state_use_accessors &IRQD_INPROGRESS ; +} + +static inline bool irqd_is_disabled (struct irq_data *d) +{ +return d->state_use_accessors &IRQD_DISABLED ; +} +/** * struct irq_chip - hardware interrupt chip descriptor *
kernel/irq/chip.c +2 -0
@@ -194,12 +194,14 @@ static void irq_state_clr_disabled(struc { desc->istate &= ~IRQS_DISABLED ;irq_compat_clr_disabled (desc); +irqd_clear (&desc->irq_data,IRQD_DISABLED ); }static void irq_state_set_disabled (struct irq_desc *desc) { desc->istate |=IRQS_DISABLED ;irq_compat_set_disabled (desc); +irqd_set (&desc->irq_data,IRQD_DISABLED ); }static void irq_state_clr_masked (struct irq_desc *desc)
kernel/irq/handle.c +2 -0
@@ -126,6 +126,7 @@ irqreturn_t handle_irq_event(struct irq_ desc->istate &= ~IRQS_PENDING ;irq_compat_set_progress (desc); desc->istate |=IRQS_INPROGRESS ; +irqd_set (&desc->irq_data,IRQD_INPROGRESS );raw_spin_unlock (&desc->lock); ret =handle_irq_event_percpu (desc, action);
@@ -133,6 +134,7 @@ irqreturn_t handle_irq_event(struct irq_raw_spin_lock (&desc->lock); desc->istate &= ~IRQS_INPROGRESS ;irq_compat_clr_progress (desc); +irqd_clear (&desc->irq_data,IRQD_INPROGRESS );return ret; }
PATCH 66/75 genirq: Reflect IRQ_MOVE_PCNTXT in irq_data state
In reply to Thomas GleixnerRequired by x86.
--- include/linux/irq.h | 8 ++++++++ kernel/irq/chip.c | 4 +++- 2 files changed, 11 insertions(+), 1 deletion(-)
include/linux/irq.h +8 -0
@@ -171,6 +171,8 @@ struct irq_data {* valid in irq_chip.functions * IRDQ_INPROGRESS - Interrupt is in progress, only * valid in irq_chip.functions +* IRDQ_MOVE_PCNTXT - Interrupt can be moved in process +* context */ enum {IRQD_TRIGGER_MASK =0xf ,
@@ -182,6 +184,7 @@ enum {IRQD_WAKEUP_STATE = (1 <<14 ),IRQD_DISABLED = (1 <<15 ),IRQD_INPROGRESS = (1 <<16 ), + IRQD_MOVE_PCNTXT = (1 << 17), };static inline bool irqd_is_setaffinity_pending (struct irq_data *d)
@@ -238,6 +241,11 @@ static inline bool irqd_is_disabled(strureturn d->state_use_accessors &IRQD_DISABLED ; } +static inline bool irqd_can_move_in_process_context (struct irq_data *d) +{ +return d->state_use_accessors &IRQD_MOVE_PCNTXT ; +} +/** * struct irq_chip - hardware interrupt chip descriptor *
kernel/irq/chip.c +3 -1
@@ -740,11 +740,13 @@ void irq_modify_status(unsigned int irq,irq_settings_clr_and_set (desc, clr, set);irqd_clear (&desc->irq_data,IRQD_NO_BALANCING |IRQD_PER_CPU | -IRQD_TRIGGER_MASK |IRQD_LEVEL ); +IRQD_TRIGGER_MASK |IRQD_LEVEL |IRQD_MOVE_PCNTXT );if (irq_settings_has_no_balance_set (desc))irqd_set (&desc->irq_data,IRQD_NO_BALANCING );if (irq_settings_is_per_cpu (desc))irqd_set (&desc->irq_data,IRQD_PER_CPU ); +if (irq_settings_can_move_pcntxt (desc)) +irqd_set (&desc->irq_data,IRQD_MOVE_PCNTXT );irqd_set (&desc->irq_data,irq_settings_get_trigger_mask (desc));
PATCH 67/75 genirq: Remove desc->status when GENERIC_HARDIRQS_NO_COMPAT=y
In reply to Thomas GleixnerIf everything uses the right accessors, then enabling GENERIC_HARDIRQS_NO_COMPAT should just work. If not it will tell you.
Don't be lazy and use the trick which I use in the core code!
git grep settings_use_proper_accessors
will unearth it in a split second. Offenders are tracked down and not slapped with stinking trouts. This time we use frozen shark for a better educational value.
--- include/linux/irqdesc.h | 6 ++++++ kernel/irq/internals.h | 4 ++++ kernel/irq/settings.h | 1 + 3 files changed, 11 insertions(+)
include/linux/irqdesc.h +6 -0
@@ -64,7 +64,11 @@ struct irq_desc {unsigned int __percpu *kstat_irqs;irq_flow_handler_t handle_irq;struct irqaction *action;/* IRQ action list */ +#ifdef CONFIG_GENERIC_HARDIRQS_NO_COMPAT +unsigned int settings_use_the_proper_accessors; +#else unsigned int status;/* IRQ status */ +#endif unsigned int core_internal_state__do_not_mess_with_it;unsigned int depth;/* nested irq disables */ unsigned int wake_depth;/* nested wake enables */
@@ -164,6 +168,7 @@ static inline int irq_has_action(unsignereturn desc->action !=NULL ; } +#ifndef CONFIG_GENERIC_HARDIRQS_NO_COMPAT static inline int irq_balancing_disabled (unsigned int irq) {struct irq_desc *desc;
@@ -171,6 +176,7 @@ static inline int irq_balancing_disabled desc =irq_to_desc (irq);return desc->status &IRQ_NO_BALANCING_MASK ; } +#endif /* caller has locked the irq_desc and both params are valid */ static inline void __set_irq_handler_unlocked(int irq,
kernel/irq/internals.h +4 -0
@@ -9,6 +9,10 @@#define istate core_internal_state__do_not_mess_with_it +#ifdef CONFIG_GENERIC_HARDIRQS_NO_COMPAT +# define status settings_use_the_proper_accessors +#endif +extern int noirqdebug;/*
kernel/irq/settings.h +1 -0
@@ -127,4 +127,5 @@ static inline bool irq_settings_can_auto }/* Nothing should touch desc->status from now on */ +#undef status#define status USE_THE_PROPER_WRAPPERS_YOU_MORON
PATCH 68/75 genirq: Add preflow handler support
In reply to Thomas Gleixnersparc64 needs to call a preflow handler on certain interrupts befor calling the action chain. Integrate it into handle_fasteoi_irq. Must be enabled via CONFIG_IRQ_FASTEOI_PREFLOW. No impact when disabled.
--- include/linux/irq.h | 3 ++- include/linux/irqdesc.h | 14 ++++++++++++++ kernel/irq/Kconfig | 3 +++ kernel/irq/chip.c | 11 +++++++++++ 4 files changed, 30 insertions(+), 1 deletion(-)
include/linux/irq.h +2 -1
@@ -29,9 +29,10 @@#include <asm/irq_regs.h> struct irq_desc ; +struct irq_data ;typedef void (*irq_flow_handler_t )(unsigned int irq,struct irq_desc *desc); - +typedef void (*irq_preflow_handler_t )(struct irq_data *data);/* * IRQ line status.
include/linux/irqdesc.h +14 -0
@@ -63,6 +63,9 @@ struct irq_desc {struct timer_rand_state *timer_rand_state;unsigned int __percpu *kstat_irqs;irq_flow_handler_t handle_irq; +#ifdef CONFIG_IRQ_PREFLOW_FASTEOI +irq_preflow_handler_t preflow_handler; +#endif struct irqaction *action;/* IRQ action list */ #ifdef CONFIG_GENERIC_HARDIRQS_NO_COMPAT unsigned int settings_use_the_proper_accessors;
@@ -187,6 +190,17 @@ static inline void __set_irq_handler_unl desc =irq_to_desc (irq); desc->handle_irq = handler; } + +#ifdef CONFIG_IRQ_PREFLOW_FASTEOI +static inline void +__irq_set_preflow_handler (unsigned int irq,irq_preflow_handler_t handler) +{ +struct irq_desc *desc; + + desc =irq_to_desc (irq); + desc->preflow_handler = handler; +} +#endif #endif #endif
kernel/irq/Kconfig +3 -0
@@ -35,6 +35,9 @@ config AUTO_IRQ_AFFINITY config HARDIRQS_SW_RESEND def_bool n +config IRQ_PREFLOW_FASTEOI + def_bool n + config SPARSE_IRQ bool "Support sparse irq numbering" depends on HAVE_SPARSE_IRQ
kernel/irq/chip.c +11 -0
@@ -531,6 +531,16 @@ out_unlock: }EXPORT_SYMBOL_GPL (handle_level_irq); +#ifdef CONFIG_IRQ_PREFLOW_FASTEOI +static inline void preflow_handler (struct irq_desc *desc) +{ +if (desc->preflow_handler) + desc->preflow_handler (&desc->irq_data); +} +#else +static inline void preflow_handler (struct irq_desc *desc) { } +#endif +/** * handle_fasteoi_irq - irq handler for transparent controllers * @irq: the interrupt number
@@ -563,6 +573,7 @@ handle_fasteoi_irq(unsigned int irq, strmask_irq (desc); goto out; } +preflow_handler (desc);handle_irq_event (desc); out: desc->irq_data.chip->irq_eoi (&desc->irq_data);
PATCH 69/75 genirq: Implement irq_data based move_*_irq() versions
In reply to Thomas GleixnerNo need to lookup the irq descriptor when calling from a chip callback function which has irq_data already handy.
--- include/linux/irq.h | 8 ++++++-- kernel/irq/migration.c | 28 +++++++++++++++++++--------- 2 files changed, 25 insertions(+), 11 deletions(-)
include/linux/irq.h +6 -2
@@ -372,11 +372,15 @@ extern void remove_irq(unsigned int irq,#ifdef CONFIG_GENERIC_HARDIRQS #if defined(CONFIG_SMP ) && defined(CONFIG_GENERIC_PENDING_IRQ ) -void move_native_irq (int irq); -void move_masked_irq (int irq); +void __deprecated move_native_irq (int irq); +void __deprecated move_masked_irq (int irq); +void irq_move_irq (struct irq_data *data); +void irq_move_masked_irq (struct irq_data *data);#else static inline void move_native_irq (int irq) { }static inline void move_masked_irq (int irq) { } +static inline void irq_move_irq (struct irq_data *data) { } +static inline void irq_move_masked_irq (struct irq_data *data) { }#endif extern int no_irq_affinity;
kernel/irq/migration.c +19 -9
@@ -4,10 +4,10 @@#include "internals.h" -void move_masked_irq (int irq) +void irq_move_masked_irq (struct irq_data *idata) { -struct irq_desc *desc =irq_to_desc (irq); -struct irq_chip *chip = desc->irq_data.chip; +struct irq_desc *desc =irq_data_to_desc (idata); +struct irq_chip *chip = idata->chip;if (likely (!irqd_is_setaffinity_pending (&desc->irq_data)))return ;
@@ -53,12 +53,17 @@ void move_masked_irq(int irq)cpumask_clear (desc->pending_mask); } -void move_native_irq (int irq) +void move_masked_irq (int irq) +{ +irq_move_masked_irq (irq_get_irq_data (irq)); +} + +void irq_move_irq (struct irq_data *idata) { -struct irq_desc *desc =irq_to_desc (irq); +struct irq_desc *desc =irq_data_to_desc (idata);bool masked; -if (likely (!irqd_is_setaffinity_pending (&desc->irq_data))) +if (likely (!irqd_is_setaffinity_pending (idata)))return ;if (unlikely (desc->istate &IRQS_DISABLED ))
@@ -71,8 +76,13 @@ void move_native_irq(int irq)*/ masked = desc->istate &IRQS_MASKED ;if (!masked) - desc->irq_data.chip->irq_mask (&desc->irq_data); -move_masked_irq (irq); + idata->chip->irq_mask (idata); +irq_move_masked_irq (idata);if (!masked) - desc->irq_data.chip->irq_unmask (&desc->irq_data); + idata->chip->irq_unmask (idata); +} + +void move_native_irq (int irq) +{ +irq_move_irq (irq_get_irq_data (irq)); }
PATCH 70/75 x86: Fixup deprecation warnings
In reply to Thomas GleixnerReplace the deprecated get/set_irq calls.
--- arch/x86/kernel/apic/io_apic.c | 36 ++++++++++++++++++------------------ arch/x86/kernel/hpet.c | 2 +- 2 files changed, 19 insertions(+), 19 deletions(-)
arch/x86/kernel/apic/io_apic.c +18 -18
@@ -181,7 +181,7 @@ int __init arch_early_irq_init(void)irq_reserve_irqs (0 , legacy_pic->nr_legacy_irqs);for (i =0 ; i < count; i++) { -set_irq_chip_data (i, &cfg[i]); +irq_set_chip_data (i, &cfg[i]);zalloc_cpumask_var_node (&cfg[i].domain,GFP_KERNEL , node);zalloc_cpumask_var_node (&cfg[i].old_domain,GFP_KERNEL , node);/*
@@ -200,7 +200,7 @@ int __init arch_early_irq_init(void)#ifdef CONFIG_SPARSE_IRQ static struct irq_cfg *irq_cfg (unsigned int irq) { -return get_irq_chip_data (irq); +return irq_get_chip_data (irq); }static struct irq_cfg *alloc_irq_cfg (unsigned int irq,int node)
@@ -256,14 +256,14 @@ static struct irq_cfg *alloc_irq_and_cfgif (res <0 ) {if (res != -EEXIST )return NULL ; - cfg =get_irq_chip_data (at); + cfg =irq_get_chip_data (at);if (cfg)return cfg; } cfg =alloc_irq_cfg (at, node);if (cfg) -set_irq_chip_data (at, cfg); +irq_set_chip_data (at, cfg);else irq_free_desc (at);return cfg;
@@ -1189,7 +1189,7 @@ void __setup_vector_irq(int cpu)raw_spin_lock (&vector_lock);/* Mark the inuse vectors */ for_each_active_irq (irq) { - cfg =get_irq_chip_data (irq); + cfg =irq_get_chip_data (irq);if (!cfg)continue ;/*
@@ -1257,7 +1257,7 @@ static void ioapic_register_intr(unsigneelse irq_clear_status_flags (irq,IRQ_LEVEL ); -if (irq_remapped (get_irq_chip_data (irq))) { +if (irq_remapped (irq_get_chip_data (irq))) {irq_set_status_flags (irq,IRQ_MOVE_PCNTXT );if (trigger) set_irq_chip_and_handler_name(irq, &ir_ioapic_chip,
@@ -1625,7 +1625,7 @@ __apicdebuginit(void) print_IO_APIC(voidfor_each_active_irq (irq) {struct irq_pin_list *entry; - cfg =get_irq_chip_data (irq); + cfg =irq_get_chip_data (irq);if (!cfg)continue ; entry = cfg->irq_2_pin;
@@ -2391,7 +2391,7 @@ static void irq_complete_move(struct irqvoid irq_force_complete_move (int irq) { -struct irq_cfg *cfg =get_irq_chip_data (irq); +struct irq_cfg *cfg =irq_get_chip_data (irq);if (!cfg)return ;
@@ -2614,7 +2614,7 @@ static inline void init_IO_APIC_traps(vo* 0x80, because int 0x80 is hm, kind of importantish. ;) */ for_each_active_irq (irq) { - cfg =get_irq_chip_data (irq); + cfg =irq_get_chip_data (irq);if (IO_APIC_IRQ (irq) && cfg && !cfg->vector) {/* * Hmm.. We don't have an entry for this,
@@ -2625,7 +2625,7 @@ static inline void init_IO_APIC_traps(vo legacy_pic->make_irq (irq); else /* Strange. Oh, well.. */ - set_irq_chip(irq, &no_irq_chip); + irq_set_chip(irq, &no_irq_chip); } } }
@@ -2749,7 +2749,7 @@ int timer_through_8259 __initdata;*/ static inline void __init check_timer (void ) { -struct irq_cfg *cfg =get_irq_chip_data (0 ); +struct irq_cfg *cfg =irq_get_chip_data (0 );int node =cpu_to_node (0 );int apic1, pin1, apic2, pin2;unsigned long flags;
@@ -3060,7 +3060,7 @@ unsigned int create_irq_nr(unsigned intraw_spin_unlock_irqrestore (&vector_lock, flags);if (ret) { -set_irq_chip_data (irq, cfg); +irq_set_chip_data (irq, cfg);irq_clear_status_flags (irq,IRQ_NOREQUEST ); }else {free_irq_at (irq, cfg);
@@ -3085,7 +3085,7 @@ int create_irq(void)void destroy_irq (unsigned int irq) { -struct irq_cfg *cfg =get_irq_chip_data (irq); +struct irq_cfg *cfg =irq_get_chip_data (irq);unsigned long flags;irq_set_status_flags (irq,IRQ_NOREQUEST |IRQ_NOPROBE );
@@ -3119,7 +3119,7 @@ static int msi_compose_msg(struct pci_de dest = apic->cpu_mask_to_apicid_and (cfg->domain, apic->target_cpus ()); -if (irq_remapped (get_irq_chip_data (irq))) { +if (irq_remapped (irq_get_chip_data (irq))) {struct irte irte;int ir_index;u16 sub_handle;
@@ -3298,10 +3298,10 @@ static int setup_msi_irq(struct pci_devif (ret <0 )return ret; -set_irq_msi (irq, msidesc); +irq_set_msi_desc (irq, msidesc);write_msi_msg (irq, &msg); -if (irq_remapped (get_irq_chip_data (irq))) { +if (irq_remapped (irq_get_chip_data (irq))) {irq_set_status_flags (irq,IRQ_MOVE_PCNTXT );set_irq_chip_and_handler_name (irq, &msi_ir_chip, handle_edge_irq,"edge" ); }else
@@ -3501,9 +3501,9 @@ int arch_setup_hpet_msi(unsigned int irqif (ret <0 )return ret; -hpet_msi_write (get_irq_data (irq), &msg); +hpet_msi_write (irq_get_handler_data (irq), &msg);irq_set_status_flags (irq,IRQ_MOVE_PCNTXT ); -if (irq_remapped (get_irq_chip_data (irq))) +if (irq_remapped (irq_get_chip_data (irq)))set_irq_chip_and_handler_name (irq, &ir_hpet_msi_type, handle_edge_irq,"edge" );else
arch/x86/kernel/hpet.c +1 -1
@@ -503,7 +503,7 @@ static int hpet_assign_irq(struct hpet_dif (!irq)return -EINVAL ; -set_irq_data (irq, dev); +irq_set_handler_data (irq, dev);if (hpet_setup_msi_irq (irq))return -EINVAL ;
PATCH 71/75 x86: ioapic: Use irq_data->state
In reply to Thomas GleixnerUse the state information in irq_data. That avoids a radix-tree lookup from apic_ack_level() and simplifies setup_ioapic_dest().
--- arch/x86/kernel/apic/io_apic.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-)
arch/x86/kernel/apic/io_apic.c +7 -8
@@ -2462,7 +2462,7 @@ static void ack_apic_level(struct irq_dairq_complete_move (cfg);#ifdef CONFIG_GENERIC_PENDING_IRQ /* If we are moving the irq we need to mask it */ -if (unlikely (irq_to_desc (irq)->status &IRQ_MOVE_PENDING )) { +if (unlikely (irqd_is_setaffinity_pending (data))) { do_unmask_irq =1 ;mask_ioapic (cfg); }
@@ -3868,8 +3868,8 @@ int acpi_get_override_irq(u32 gsi, int *void __init setup_ioapic_dest (void ) {int pin, ioapic, irq, irq_entry; -struct irq_desc *desc;const struct cpumask *mask; +struct irq_data *idata;if (skip_ioapic_setup ==1 )return ;
@@ -3884,21 +3884,20 @@ void __init setup_ioapic_dest(void)if ((ioapic >0 ) && (irq >16 ))continue ; - desc =irq_to_desc (irq); + idata =irq_get_irq_data (irq);/* * Honour affinities which have been set in early boot */ -if (desc->status & - (IRQ_NO_BALANCING |IRQ_AFFINITY_SET )) - mask = desc->irq_data.affinity; +if (!irqd_can_balance (idata) ||irqd_affinity_was_set (idata)) + mask = idata->affinity;else mask = apic->target_cpus ();if (intr_remapping_enabled) -ir_ioapic_set_affinity (&desc->irq_data, mask, false); +ir_ioapic_set_affinity (idata, mask, false);else -ioapic_set_affinity (&desc->irq_data, mask, false); +ioapic_set_affinity (idata, mask, false); } }
PATCH 72/75 x86: Use the proper accessors in fixup_irqs()
In reply to Thomas Gleixner--- arch/x86/kernel/irq.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
arch/x86/kernel/irq.c +4 -2
@@ -327,7 +327,8 @@ void fixup_irqs(void) affinity = cpu_all_mask; } -if (!(desc->status &IRQ_MOVE_PCNTXT ) && data->chip->irq_mask) +if (!irqd_can_move_in_process_context (data) && + data->chip->irq_mask) data->chip->irq_mask (data);if (data->chip->irq_set_affinity)
@@ -335,7 +336,8 @@ void fixup_irqs(void)else if (!(warned++)) set_affinity =0 ; -if (!(desc->status &IRQ_MOVE_PCNTXT ) && data->chip->irq_unmask) +if (!irqd_can_move_in_process_context (data) && + data->chip->irq_unmask) data->chip->irq_unmask (data);raw_spin_unlock (&desc->lock);
PATCH 73/75 x86: ioapic: Use new move_irq functions
In reply to Thomas GleixnerUse the functions which take irq_data. We already have a pointer to irq_data. That avoids a sparse irq lookup in move_*_irq.
--- arch/x86/kernel/apic/io_apic.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
arch/x86/kernel/apic/io_apic.c +2 -2
@@ -2405,7 +2405,7 @@ static inline void irq_complete_move(strstatic void ack_apic_edge (struct irq_data *data) {irq_complete_move (data->chip_data); -move_native_irq (data->irq); +irq_move_irq (data);ack_APIC_irq (); }
@@ -2551,7 +2551,7 @@ static void ack_apic_level(struct irq_da* and you can go talk to the chipset vendor about it. */ if (!io_apic_level_ack_pending (cfg)) -move_masked_irq (irq); +irq_move_masked_irq (data);unmask_ioapic (cfg); } }
PATCH 74/75 x86: Use generic show_interrupts
In reply to Thomas Gleixner--- arch/x86/Kconfig | 1 arch/x86/kernel/irq.c | 57 +------------------------------------------------- 2 files changed, 3 insertions(+), 55 deletions(-)
arch/x86/Kconfig +1 -0
@@ -66,6 +66,7 @@ config X86 select HAVE_SPARSE_IRQ select GENERIC_IRQ_PROBE select GENERIC_PENDING_IRQ if SMP + select GENERIC_IRQ_SHOW select USE_GENERIC_SMP_HELPERS if SMP config INSTRUCTION_DECODER
arch/x86/kernel/irq.c +2 -55
70 lines not on this page · raw message
PATCH 75/75 x86: Disable deprecated GENIRQ features
In reply to Thomas Gleixnerx86 builds and works without the deprecated stuff when XEN, and MFD are disabled. Once those are fixed, we can remove the conditionals.
--- arch/x86/Kconfig | 2 ++ 1 file changed, 2 insertions(+)
arch/x86/Kconfig +2 -0
@@ -67,6 +67,8 @@ config X86 select GENERIC_IRQ_PROBE select GENERIC_PENDING_IRQ if SMP select GENERIC_IRQ_SHOW + select GENERIC_HARDIRQS_NO_DEPRECATED if !XEN && !MFD + select GENERIC_HARDIRQS_NO_COMPAT if !XEN && !MFD select USE_GENERIC_SMP_HELPERS if SMP config INSTRUCTION_DECODER
Quoted 4 lines · Thomas Gleixner
A preview is available at:
git://git.kernel.org/pub/scm/linux/kernel/git/tglx/linux-2.6-genirq.gitirq/core
For things like this, please just always include a diffstat so that people can tell from the email whether they care or not.
Linus
Quoted 8 lines · Linus Torvalds
Quoted 4 lines · Thomas Gleixner
A preview is available at:
git://git.kernel.org/pub/scm/linux/kernel/git/tglx/linux-2.6-genirq.gitirq/coreFor things like this, please just always include a diffstat so that people can tell from the email whether they care or not.
Oops. Forgot.
arch/arm/mach-ep93xx/gpio.c | 38 --- arch/arm/mach-ns9xxx/irq.c | 58 ----- arch/arm/mach-tegra/gpio.c | 63 ------ arch/arm/mach-tegra/irq.c | 58 ----- arch/m68knommu/platform/5272/intc.c | 7 arch/x86/Kconfig | 3 arch/x86/kernel/apic/io_apic.c | 55 ++--- arch/x86/kernel/hpet.c | 2 arch/x86/kernel/irq.c | 63 ------ drivers/gpio/gpiolib.c | 44 ---- fs/proc/interrupts.c | 2 include/linux/interrupt.h | 22 -- include/linux/irq.h | 314 ++++++++++++++++++++++++++------ include/linux/irqdesc.h | 68 ++++++ kernel/irq/Kconfig | 10 - kernel/irq/autoprobe.c | 48 ++-- kernel/irq/chip.c | 353 +++++++++++++++++------------------- kernel/irq/compat.h | 72 +++++++ kernel/irq/debug.h | 40 ++++ kernel/irq/handle.c | 55 ++++- kernel/irq/internals.h | 136 +++++++++---- kernel/irq/irqdesc.c | 6 kernel/irq/manage.c | 303 ++++++++++++++++++------------ kernel/irq/migration.c | 38 ++- kernel/irq/pm.c | 9 kernel/irq/proc.c | 73 +++++++ kernel/irq/resend.c | 17 - kernel/irq/settings.h | 131 +++++++++++++ kernel/irq/spurious.c | 164 ++++++++++------ 29 files changed, 1353 insertions(+), 899 deletions(-)
Quoted 2 lines · Thomas Gleixner
29 files changed, 1353 insertions(+), 899 deletions(-)
So what is it that adds so many lines? Your description made me think "cleanups", not "50% more code"
(Yeah, yeah, I could look at the code, but I also want to point out that this really doesn't look like much of an improvement from a high-level standpoint)
Linus
Quoted 10 lines · Linus Torvalds
Quoted 2 lines · Thomas Gleixner
29 files changed, 1353 insertions(+), 899 deletions(-)So what is it that adds so many lines? Your description made me think "cleanups", not "50% more code"
(Yeah, yeah, I could look at the code, but I also want to point out that this really doesn't look like much of an improvement from a high-level standpoint)
Part of it is then namespace cleanup which makes the deprecated functions wrappers around the new ones. Easy to solve with a script.
More stuff will go way again when the wrappers which I added to prevent wreckage of arch/* fiddling with irq_desc are gone
The other things are simple inline functions which provide accessors to state which is intentionally named:
state_use_accessors,
For simple reasons:
1) while you type it it should click that you're doing something wrong
2) easy to grep for to find offenderrs. git grep status sucks
There are more wrappers in the core code kernel/irq solely to prevent using anything which got deprecated.
So yes, it's net more source lines, but not resulting in any binary bloat.
Thanks,
tglx
Quoted 3 lines · Thomas Gleixner
On Thu, 10 Feb 2011, Linus Torvalds wrote:
So yes, it's net more source lines, but not resulting in any binary bloat.
Just checked. When the compat layer goes away it will kill about 500 lines. So it's less code with better encapsulation.
Once all genirq archs convert to the generic irq_show_interrupts(), this will kill another 1000+ lines.
Thanks,
tglx
Quoted 10 lines · Thomas Gleixner
Quoted 3 lines · Thomas Gleixner
On Thu, 10 Feb 2011, Linus Torvalds wrote:
So yes, it's net more source lines, but not resulting in any binary bloat.Just checked. When the compat layer goes away it will kill about 500 lines. So it's less code with better encapsulation.
Once all genirq archs convert to the generic
irq_show_interrupts(), this will kill another 1000+ lines.
So while this is the first step:
Quoted 1 line
29 files changed, 1353 insertions(+), 899 deletions(-)
It turns into this end result (mockup):
Quoted 1 line
129 files changed, 1353 insertions(+), 2400 deletions(-)
Right? Or, more likely, considering all the surrounding code changes, something like:
Quoted 1 line
129 files changed, 4353 insertions(+), 5400 deletions(-)
Did I get the file count right - roughtly how many files are affected throughout all architectures? The changes are massively intrusive and widely spread out so we cannot do them in one go, right?
Thanks,
Ingo
Quoted 6 lines · Ingo Molnar
Quoted 1 line · Thomas Gleixner
129 files changed, 4353 insertions(+), 5400 deletions(-)Did I get the file count right - roughtly how many files are affected throughout all architectures? The changes are massively intrusive and widely spread out so we cannot do them in one go, right?
Alone the stuff which fiddles in irq_desc->status for whatever reasons is >100 files in arch/. And that has do be done manually case by case.
The namespace cleanup affects about 300 files in arch, but that can be done in one go right after -rc1 if I manage to get the regex straight :)
Thanks,
tglx
Quoted 10 lines · Thomas Gleixner
Quoted 6 lines · Ingo Molnar
Quoted 1 line · Thomas Gleixner
129 files changed, 4353 insertions(+), 5400 deletions(-)Did I get the file count right - roughtly how many files are affected throughout all architectures? The changes are massively intrusive and widely spread out so we cannot do them in one go, right?
Alone the stuff which fiddles in
irq_desc->statusfor whatever reasons is >100 files inarch/. And that has do be done manually case by case.
Some kind of arch TODO list wold be nice. Just to let the arch maintainers know what you expect from them (on top of the deprecated warnings).
Sam
Quoted 9 lines · Sam Ravnborg
Quoted 8 lines · Thomas Gleixner
Quoted 6 lines · Ingo Molnar
Quoted 1 line · Thomas Gleixner
129 files changed, 4353 insertions(+), 5400 deletions(-)Did I get the file count right - roughtly how many files are affected throughout all architectures? The changes are massively intrusive and widely spread out so we cannot do them in one go, right?
Quoted 5 lines
Quoted 2 lines
Alone the stuff which fiddles in
irq_desc->statusfor whatever reasons is >100 files inarch/. And that has do be done manually case by case.Some kind of arch TODO list wold be nice. Just to let the arch maintainers know what you expect from them (on top of the deprecated warnings).
One thing which can be done right now is to use the proper existing accessors irq_to_desc(), irq_set/clear_status_flags().
The remaining fixes depend on the yet to be merged queue. I will do the namespace cleanup with cocinelle after rc1 as this is purely mechanical. The other few things which will be left need manual attendance, I will post either patches or a TODO list.
Thanks,
tglx
Quoted 11 lines · Thomas Gleixner
This is a major overhaul of the generic interrupt layer.
- Namespace cleanup
- Further encapsulation of the core state
- Spurious/Poll handling fixes
- Stop setaffinity blindly manipulating affinity mask
- Cleanups and enhancements all over the place
Hi Thomas,
You seem to have overlooked a patch from me:
Update comments to match code change in 70aedd24
The comments for enable_irq() were updated correctly, but disable_irq_nosync() and disable_irq() were missed.
---
kernel/irq/manage.c | 7 5 + 2 - 0 !
1 file changed, 5 insertions(+), 2 deletions(-)
kernel/irq/manage.c +5 -2
@@ -353,7 +353,8 @@ void __disable_irq(struct irq_desc *desc* Unlike disable_irq(), this function does not ensure existing * instances of the IRQ handler have completed before returning. * -* This function may be called from IRQ context. +* This function may be called from IRQ context only when +* desc->chip->bus_lock and desc->chip->bus_sync_unlock are NULL ! */ void disable_irq_nosync (unsigned int irq) {
@@ -381,7 +382,9 @@ EXPORT_SYMBOL(disable_irq_nosync);* to complete before returning. If you use this function while * holding a resource the IRQ handler may need you will deadlock. * -* This function may be called - with care - from IRQ context. +* This function may be called - with care - from IRQ context only when +* desc->chip->bus_lock and desc->chip->bus_sync_unlock are NULL ! +* See synchronize_irq() comments for explanation of "with care". */ void disable_irq (unsigned int irq) {