Messages in this thread Patch in this message | | | From | Marc Zyngier <> | Subject | [PATCH v2 1/6] genirq: Add __irq_modify_status() helper to clear/set special flags | Date | Tue, 24 Nov 2020 14:14:44 +0000 |
| |
Some arch-specific flags need to be set/cleared, but not exposed to random device drivers. Introduce a new helper (__irq_modify_status()) that takes an arbitrary mask, and rewrite irq_modify_status() to use this new helper.
No functionnal change.
Signed-off-by: Marc Zyngier <maz@kernel.org> --- include/linux/irq.h | 3 +++ kernel/irq/chip.c | 12 ++++++++++-- kernel/irq/settings.h | 10 ++++++++-- 3 files changed, 21 insertions(+), 4 deletions(-)
diff --git a/include/linux/irq.h b/include/linux/irq.h index c54365309e97..c55f218d5b61 100644 --- a/include/linux/irq.h +++ b/include/linux/irq.h @@ -751,6 +751,9 @@ void irq_set_chained_handler_and_data(unsigned int irq, irq_flow_handler_t handle, void *data); +void __irq_modify_status(unsigned int irq, unsigned long clr, + unsigned long set, unsigned long mask); + void irq_modify_status(unsigned int irq, unsigned long clr, unsigned long set); static inline void irq_set_status_flags(unsigned int irq, unsigned long set) diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c index b9b9618e1aca..85176712a484 100644 --- a/kernel/irq/chip.c +++ b/kernel/irq/chip.c @@ -1107,7 +1107,8 @@ irq_set_chip_and_handler_name(unsigned int irq, struct irq_chip *chip, } EXPORT_SYMBOL_GPL(irq_set_chip_and_handler_name); -void irq_modify_status(unsigned int irq, unsigned long clr, unsigned long set) +void __irq_modify_status(unsigned int irq, unsigned long clr, + unsigned long set, unsigned long mask) { unsigned long flags, trigger, tmp; struct irq_desc *desc = irq_get_desc_lock(irq, &flags, 0); @@ -1121,7 +1122,9 @@ void irq_modify_status(unsigned int irq, unsigned long clr, unsigned long set) */ WARN_ON_ONCE(!desc->depth && (set & _IRQ_NOAUTOEN)); - irq_settings_clr_and_set(desc, clr, set); + /* Warn when trying to clear or set a bit disallowed by the mask */ + WARN_ON((clr | set) & ~mask); + __irq_settings_clr_and_set(desc, clr, set, mask); trigger = irqd_get_trigger_type(&desc->irq_data); @@ -1144,6 +1147,11 @@ void irq_modify_status(unsigned int irq, unsigned long clr, unsigned long set) irq_put_desc_unlock(desc, flags); } + +void irq_modify_status(unsigned int irq, unsigned long clr, unsigned long set) +{ + __irq_modify_status(irq, clr, set, _IRQF_MODIFY_MASK); +} EXPORT_SYMBOL_GPL(irq_modify_status); /** diff --git a/kernel/irq/settings.h b/kernel/irq/settings.h index 403378b9947b..51acdf43eadc 100644 --- a/kernel/irq/settings.h +++ b/kernel/irq/settings.h @@ -36,11 +36,17 @@ enum { #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, u32 mask) +{ + desc->status_use_accessors &= ~(clr & mask); + desc->status_use_accessors |= (set & mask); +} + static inline void irq_settings_clr_and_set(struct irq_desc *desc, u32 clr, u32 set) { - desc->status_use_accessors &= ~(clr & _IRQF_MODIFY_MASK); - desc->status_use_accessors |= (set & _IRQF_MODIFY_MASK); + __irq_settings_clr_and_set(desc, clr, set, _IRQF_MODIFY_MASK); } static inline bool irq_settings_is_per_cpu(struct irq_desc *desc) -- 2.28.0
| |