* [patch 00/46] genirq: Cleanups and conversion to lock guards
@ 2025-03-13 15:59 Thomas Gleixner
2025-03-13 15:59 ` [patch 01/46] genirq: Provide conditional " Thomas Gleixner
` (46 more replies)
0 siblings, 47 replies; 50+ messages in thread
From: Thomas Gleixner @ 2025-03-13 15:59 UTC (permalink / raw)
To: LKML; +Cc: Peter Zijlstra, Jiri Slaby
The generic interrupt core code has accumulated quite some inconsistencies
over time and a common pattern in various API functions is:
unsigned long flags;
struct irq_desc *desc = irq_get_desc_[bus]lock(irq, &flags, mode);
if (!desc)
return -EINVAL;
....
irq_put_desc_[bus]unlock(desc, flags);
That's awkward and requires gotos in failure paths.
This series provides conditional lock guards and converts the core code
over to use those guards. Along with that it converts the other open coded
lock/unlock pairs and fixes up coding and kernel doc formatting. The
conversions were partially done with Coccinelle where possible.
The series applies on Linus tree and is also available from git:
git://git.kernel.org/pub/scm/linux/kernel/git/tglx/devel.git irq/core
Thanks,
tglx
---
include/linux/irq.h | 2
kernel/irq/autoprobe.c | 26 -
kernel/irq/chip.c | 640 ++++++++++----------------
kernel/irq/cpuhotplug.c | 10
kernel/irq/debugfs.c | 3
kernel/irq/internals.h | 47 -
kernel/irq/irqdesc.c | 136 +----
kernel/irq/manage.c | 1154 ++++++++++++++++++++----------------------------
kernel/irq/pm.c | 38 -
kernel/irq/proc.c | 65 --
kernel/irq/resend.c | 50 --
kernel/irq/spurious.c | 104 +---
12 files changed, 920 insertions(+), 1355 deletions(-)
^ permalink raw reply [flat|nested] 50+ messages in thread
* [patch 01/46] genirq: Provide conditional lock guards
2025-03-13 15:59 [patch 00/46] genirq: Cleanups and conversion to lock guards Thomas Gleixner
@ 2025-03-13 15:59 ` Thomas Gleixner
2025-03-13 15:59 ` [patch 02/46] genirq/irqdesc: Switch to " Thomas Gleixner
` (45 subsequent siblings)
46 siblings, 0 replies; 50+ messages in thread
From: Thomas Gleixner @ 2025-03-13 15:59 UTC (permalink / raw)
To: LKML; +Cc: Peter Zijlstra, Jiri Slaby
The interrupt core code has an ever repeating pattern:
unsigned long flags;
struct irq_desc *desc = irq_get_desc_[bus]lock(irq, &flags, mode);
if (!desc)
return -EINVAL;
....
irq_put_desc_[bus]unlock(desc, flags);
That requires gotos in failure paths and just creates visual clutter.
Provide lock guards, which allow to simplify the code.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Jiri Slaby <jirislaby@kernel.org>
---
kernel/irq/internals.h | 35 +++++++++++++++++++++++++++++------
1 file changed, 29 insertions(+), 6 deletions(-)
--- a/kernel/irq/internals.h
+++ b/kernel/irq/internals.h
@@ -150,6 +150,10 @@ extern int irq_setup_affinity(struct irq
static inline int irq_setup_affinity(struct irq_desc *desc) { return 0; }
#endif
+
+#define for_each_action_of_desc(desc, act) \
+ for (act = desc->action; act; act = act->next)
+
/* Inline functions for support of irq chips on slow busses */
static inline void chip_bus_lock(struct irq_desc *desc)
{
@@ -169,14 +173,33 @@ static inline void chip_bus_sync_unlock(
#define IRQ_GET_DESC_CHECK_GLOBAL (_IRQ_DESC_CHECK)
#define IRQ_GET_DESC_CHECK_PERCPU (_IRQ_DESC_CHECK | _IRQ_DESC_PERCPU)
-#define for_each_action_of_desc(desc, act) \
- for (act = desc->action; act; act = act->next)
-
-struct irq_desc *
-__irq_get_desc_lock(unsigned int irq, unsigned long *flags, bool bus,
- unsigned int check);
+struct irq_desc *__irq_get_desc_lock(unsigned int irq, unsigned long *flags, bool bus,
+ unsigned int check);
void __irq_put_desc_unlock(struct irq_desc *desc, unsigned long flags, bool bus);
+__DEFINE_CLASS_IS_CONDITIONAL(irqdesc_lock, true);
+__DEFINE_UNLOCK_GUARD(irqdesc_lock, struct irq_desc,
+ __irq_put_desc_unlock(_T->lock, _T->flags, _T->bus),
+ unsigned long flags; bool bus);
+
+static inline class_irqdesc_lock_t class_irqdesc_lock_constructor(unsigned int irq, bool bus,
+ unsigned int check)
+{
+ class_irqdesc_lock_t _t = {
+ .bus = bus,
+ .lock = __irq_get_desc_lock(irq, &_t.flags, bus, check),
+ };
+ return _t;
+}
+
+#define scoped_irqdesc_get_and_lock(_irq, _check) \
+ scoped_guard(irqdesc_lock, _irq, false, _check)
+
+#define scoped_irqdesc_get_and_buslock(_irq, _check) \
+ scoped_guard(irqdesc_lock, _irq, true, _check)
+
+#define scoped_irqdesc ((struct irq_desc *)(__guard_ptr(irqdesc_lock)(&scope)))
+
static inline struct irq_desc *
irq_get_desc_buslock(unsigned int irq, unsigned long *flags, unsigned int check)
{
^ permalink raw reply [flat|nested] 50+ messages in thread
* [patch 02/46] genirq/irqdesc: Switch to lock guards
2025-03-13 15:59 [patch 00/46] genirq: Cleanups and conversion to lock guards Thomas Gleixner
2025-03-13 15:59 ` [patch 01/46] genirq: Provide conditional " Thomas Gleixner
@ 2025-03-13 15:59 ` Thomas Gleixner
2025-03-14 10:57 ` Jiri Slaby
2025-03-13 15:59 ` [patch 03/46] genirq/autoprobe: " Thomas Gleixner
` (44 subsequent siblings)
46 siblings, 1 reply; 50+ messages in thread
From: Thomas Gleixner @ 2025-03-13 15:59 UTC (permalink / raw)
To: LKML; +Cc: Peter Zijlstra, Jiri Slaby
Replace all lock/unlock pairs with lock guards and simplify the code flow.
No functional change.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
kernel/irq/irqdesc.c | 136 +++++++++++++++------------------------------------
1 file changed, 42 insertions(+), 94 deletions(-)
--- a/kernel/irq/irqdesc.c
+++ b/kernel/irq/irqdesc.c
@@ -266,104 +266,68 @@ static ssize_t per_cpu_count_show(struct
}
IRQ_ATTR_RO(per_cpu_count);
-static ssize_t chip_name_show(struct kobject *kobj,
- struct kobj_attribute *attr, char *buf)
+static ssize_t chip_name_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
{
struct irq_desc *desc = container_of(kobj, struct irq_desc, kobj);
- ssize_t ret = 0;
-
- raw_spin_lock_irq(&desc->lock);
- if (desc->irq_data.chip && desc->irq_data.chip->name) {
- ret = scnprintf(buf, PAGE_SIZE, "%s\n",
- desc->irq_data.chip->name);
- }
- raw_spin_unlock_irq(&desc->lock);
- return ret;
+ guard(raw_spinlock_irq)(&desc->lock);
+ if (desc->irq_data.chip && desc->irq_data.chip->name)
+ return scnprintf(buf, PAGE_SIZE, "%s\n", desc->irq_data.chip->name);
+ return 0;
}
IRQ_ATTR_RO(chip_name);
-static ssize_t hwirq_show(struct kobject *kobj,
- struct kobj_attribute *attr, char *buf)
+static ssize_t hwirq_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
{
struct irq_desc *desc = container_of(kobj, struct irq_desc, kobj);
- ssize_t ret = 0;
-
- raw_spin_lock_irq(&desc->lock);
- if (desc->irq_data.domain)
- ret = sprintf(buf, "%lu\n", desc->irq_data.hwirq);
- raw_spin_unlock_irq(&desc->lock);
- return ret;
+ guard(raw_spinlock_irq)(&desc->lock);
+ return desc->irq_data.domain ? sprintf(buf, "%lu\n", desc->irq_data.hwirq) : 0;
}
IRQ_ATTR_RO(hwirq);
-static ssize_t type_show(struct kobject *kobj,
- struct kobj_attribute *attr, char *buf)
+static ssize_t type_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
{
struct irq_desc *desc = container_of(kobj, struct irq_desc, kobj);
- ssize_t ret = 0;
-
- raw_spin_lock_irq(&desc->lock);
- ret = sprintf(buf, "%s\n",
- irqd_is_level_type(&desc->irq_data) ? "level" : "edge");
- raw_spin_unlock_irq(&desc->lock);
-
- return ret;
+ guard(raw_spinlock_irq)(&desc->lock);
+ return sprintf(buf, "%s\n", irqd_is_level_type(&desc->irq_data) ? "level" : "edge");
}
IRQ_ATTR_RO(type);
-static ssize_t wakeup_show(struct kobject *kobj,
- struct kobj_attribute *attr, char *buf)
+static ssize_t wakeup_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
{
struct irq_desc *desc = container_of(kobj, struct irq_desc, kobj);
- ssize_t ret = 0;
-
- raw_spin_lock_irq(&desc->lock);
- ret = sprintf(buf, "%s\n", str_enabled_disabled(irqd_is_wakeup_set(&desc->irq_data)));
- raw_spin_unlock_irq(&desc->lock);
-
- return ret;
+ guard(raw_spinlock_irq)(&desc->lock);
+ return sprintf(buf, "%s\n", str_enabled_disabled(irqd_is_wakeup_set(&desc->irq_data)));
}
IRQ_ATTR_RO(wakeup);
-static ssize_t name_show(struct kobject *kobj,
- struct kobj_attribute *attr, char *buf)
+static ssize_t name_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
{
struct irq_desc *desc = container_of(kobj, struct irq_desc, kobj);
- ssize_t ret = 0;
- raw_spin_lock_irq(&desc->lock);
- if (desc->name)
- ret = scnprintf(buf, PAGE_SIZE, "%s\n", desc->name);
- raw_spin_unlock_irq(&desc->lock);
-
- return ret;
+ guard(raw_spinlock_irq)(&desc->lock);
+ return desc->name ? scnprintf(buf, PAGE_SIZE, "%s\n", desc->name) : 0;
}
IRQ_ATTR_RO(name);
-static ssize_t actions_show(struct kobject *kobj,
- struct kobj_attribute *attr, char *buf)
+static ssize_t actions_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
{
struct irq_desc *desc = container_of(kobj, struct irq_desc, kobj);
struct irqaction *action;
ssize_t ret = 0;
char *p = "";
- raw_spin_lock_irq(&desc->lock);
- for_each_action_of_desc(desc, action) {
- ret += scnprintf(buf + ret, PAGE_SIZE - ret, "%s%s",
- p, action->name);
- p = ",";
+ scoped_guard (raw_spinlock_irq, &desc->lock) {
+ for_each_action_of_desc(desc, action) {
+ ret += scnprintf(buf + ret, PAGE_SIZE - ret, "%s%s", p, action->name);
+ p = ",";
+ }
}
- raw_spin_unlock_irq(&desc->lock);
-
- if (ret)
- ret += scnprintf(buf + ret, PAGE_SIZE - ret, "\n");
- return ret;
+ return ret ? ret + scnprintf(buf + ret, PAGE_SIZE - ret, "\n") : 0;
}
IRQ_ATTR_RO(actions);
@@ -418,19 +382,14 @@ static int __init irq_sysfs_init(void)
int irq;
/* Prevent concurrent irq alloc/free */
- irq_lock_sparse();
-
+ guard(mutex)(&sparse_irq_lock);
irq_kobj_base = kobject_create_and_add("irq", kernel_kobj);
- if (!irq_kobj_base) {
- irq_unlock_sparse();
+ if (!irq_kobj_base)
return -ENOMEM;
- }
/* Add the already allocated interrupts */
for_each_irq_desc(irq, desc)
irq_sysfs_add(irq, desc);
- irq_unlock_sparse();
-
return 0;
}
postcore_initcall(irq_sysfs_init);
@@ -573,12 +532,12 @@ static int alloc_descs(unsigned int star
return -ENOMEM;
}
-static int irq_expand_nr_irqs(unsigned int nr)
+static bool irq_expand_nr_irqs(unsigned int nr)
{
if (nr > MAX_SPARSE_IRQS)
- return -ENOMEM;
+ return false;
nr_irqs = nr;
- return 0;
+ return true;
}
int __init early_irq_init(void)
@@ -656,11 +615,9 @@ EXPORT_SYMBOL(irq_to_desc);
static void free_desc(unsigned int irq)
{
struct irq_desc *desc = irq_to_desc(irq);
- unsigned long flags;
- raw_spin_lock_irqsave(&desc->lock, flags);
- desc_set_defaults(irq, desc, irq_desc_get_node(desc), NULL, NULL);
- raw_spin_unlock_irqrestore(&desc->lock, flags);
+ scoped_guard (raw_spinlock_irqsave, &desc->lock)
+ desc_set_defaults(irq, desc, irq_desc_get_node(desc), NULL, NULL);
delete_irq_desc(irq);
}
@@ -681,14 +638,13 @@ static inline int alloc_descs(unsigned i
static int irq_expand_nr_irqs(unsigned int nr)
{
- return -ENOMEM;
+ return false;
}
void irq_mark_irq(unsigned int irq)
{
- mutex_lock(&sparse_irq_lock);
+ guard(mutex)(&sparse_irq_lock);
irq_insert_desc(irq, irq_desc + irq);
- mutex_unlock(&sparse_irq_lock);
}
#ifdef CONFIG_GENERIC_IRQ_LEGACY
@@ -827,11 +783,9 @@ void irq_free_descs(unsigned int from, u
if (from >= nr_irqs || (from + cnt) > nr_irqs)
return;
- mutex_lock(&sparse_irq_lock);
+ guard(mutex)(&sparse_irq_lock);
for (i = 0; i < cnt; i++)
free_desc(from + i);
-
- mutex_unlock(&sparse_irq_lock);
}
EXPORT_SYMBOL_GPL(irq_free_descs);
@@ -848,11 +802,10 @@ EXPORT_SYMBOL_GPL(irq_free_descs);
*
* Returns the first irq number or error code
*/
-int __ref
-__irq_alloc_descs(int irq, unsigned int from, unsigned int cnt, int node,
- struct module *owner, const struct irq_affinity_desc *affinity)
+int __ref __irq_alloc_descs(int irq, unsigned int from, unsigned int cnt, int node,
+ struct module *owner, const struct irq_affinity_desc *affinity)
{
- int start, ret;
+ int start;
if (!cnt)
return -EINVAL;
@@ -870,22 +823,17 @@ int __ref
from = arch_dynirq_lower_bound(from);
}
- mutex_lock(&sparse_irq_lock);
+ guard(mutex)(&sparse_irq_lock);
start = irq_find_free_area(from, cnt);
- ret = -EEXIST;
if (irq >=0 && start != irq)
- goto unlock;
+ return -EEXIST;
if (start + cnt > nr_irqs) {
- ret = irq_expand_nr_irqs(start + cnt);
- if (ret)
- goto unlock;
+ if (!irq_expand_nr_irqs(start + cnt))
+ return -ENOMEM;
}
- ret = alloc_descs(start, cnt, node, affinity, owner);
-unlock:
- mutex_unlock(&sparse_irq_lock);
- return ret;
+ return alloc_descs(start, cnt, node, affinity, owner);
}
EXPORT_SYMBOL_GPL(__irq_alloc_descs);
^ permalink raw reply [flat|nested] 50+ messages in thread
* [patch 03/46] genirq/autoprobe: Switch to lock guards
2025-03-13 15:59 [patch 00/46] genirq: Cleanups and conversion to lock guards Thomas Gleixner
2025-03-13 15:59 ` [patch 01/46] genirq: Provide conditional " Thomas Gleixner
2025-03-13 15:59 ` [patch 02/46] genirq/irqdesc: Switch to " Thomas Gleixner
@ 2025-03-13 15:59 ` Thomas Gleixner
2025-03-13 15:59 ` [patch 04/46] genirq/pm: " Thomas Gleixner
` (43 subsequent siblings)
46 siblings, 0 replies; 50+ messages in thread
From: Thomas Gleixner @ 2025-03-13 15:59 UTC (permalink / raw)
To: LKML; +Cc: Peter Zijlstra, Jiri Slaby
Convert all lock/unlock pairs to guards.
No functional change.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
kernel/irq/autoprobe.c | 26 +++++++++-----------------
1 file changed, 9 insertions(+), 17 deletions(-)
--- a/kernel/irq/autoprobe.c
+++ b/kernel/irq/autoprobe.c
@@ -43,18 +43,16 @@ unsigned long probe_irq_on(void)
* flush such a longstanding irq before considering it as spurious.
*/
for_each_irq_desc_reverse(i, desc) {
- raw_spin_lock_irq(&desc->lock);
+ guard(raw_spinlock_irq)(&desc->lock);
if (!desc->action && irq_settings_can_probe(desc)) {
/*
* Some chips need to know about probing in
* progress:
*/
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_set_type(&desc->irq_data, IRQ_TYPE_PROBE);
irq_activate_and_startup(desc, IRQ_NORESEND);
}
- raw_spin_unlock_irq(&desc->lock);
}
/* Wait for longstanding interrupts to trigger. */
@@ -66,13 +64,12 @@ unsigned long probe_irq_on(void)
* happened in the previous stage, it may have masked itself)
*/
for_each_irq_desc_reverse(i, desc) {
- raw_spin_lock_irq(&desc->lock);
+ guard(raw_spinlock_irq)(&desc->lock);
if (!desc->action && irq_settings_can_probe(desc)) {
desc->istate |= IRQS_AUTODETECT | IRQS_WAITING;
if (irq_activate_and_startup(desc, IRQ_NORESEND))
desc->istate |= IRQS_PENDING;
}
- raw_spin_unlock_irq(&desc->lock);
}
/*
@@ -84,18 +81,16 @@ unsigned long probe_irq_on(void)
* Now filter out any obviously spurious interrupts
*/
for_each_irq_desc(i, desc) {
- raw_spin_lock_irq(&desc->lock);
-
+ guard(raw_spinlock_irq)(&desc->lock);
if (desc->istate & IRQS_AUTODETECT) {
/* It triggered already - consider it spurious. */
if (!(desc->istate & IRQS_WAITING)) {
desc->istate &= ~IRQS_AUTODETECT;
irq_shutdown_and_deactivate(desc);
- } else
- if (i < 32)
- mask |= 1 << i;
+ } else if (i < 32) {
+ mask |= 1 << i;
+ }
}
- raw_spin_unlock_irq(&desc->lock);
}
return mask;
@@ -121,7 +116,7 @@ unsigned int probe_irq_mask(unsigned lon
int i;
for_each_irq_desc(i, desc) {
- raw_spin_lock_irq(&desc->lock);
+ guard(raw_spinlock_irq)(&desc->lock);
if (desc->istate & IRQS_AUTODETECT) {
if (i < 16 && !(desc->istate & IRQS_WAITING))
mask |= 1 << i;
@@ -129,7 +124,6 @@ unsigned int probe_irq_mask(unsigned lon
desc->istate &= ~IRQS_AUTODETECT;
irq_shutdown_and_deactivate(desc);
}
- raw_spin_unlock_irq(&desc->lock);
}
mutex_unlock(&probing_active);
@@ -160,8 +154,7 @@ int probe_irq_off(unsigned long val)
struct irq_desc *desc;
for_each_irq_desc(i, desc) {
- raw_spin_lock_irq(&desc->lock);
-
+ guard(raw_spinlock_irq)(&desc->lock);
if (desc->istate & IRQS_AUTODETECT) {
if (!(desc->istate & IRQS_WAITING)) {
if (!nr_of_irqs)
@@ -171,7 +164,6 @@ int probe_irq_off(unsigned long val)
desc->istate &= ~IRQS_AUTODETECT;
irq_shutdown_and_deactivate(desc);
}
- raw_spin_unlock_irq(&desc->lock);
}
mutex_unlock(&probing_active);
^ permalink raw reply [flat|nested] 50+ messages in thread
* [patch 04/46] genirq/pm: Switch to lock guards
2025-03-13 15:59 [patch 00/46] genirq: Cleanups and conversion to lock guards Thomas Gleixner
` (2 preceding siblings ...)
2025-03-13 15:59 ` [patch 03/46] genirq/autoprobe: " Thomas Gleixner
@ 2025-03-13 15:59 ` Thomas Gleixner
2025-03-13 15:59 ` [patch 05/46] genirq/resend: " Thomas Gleixner
` (42 subsequent siblings)
46 siblings, 0 replies; 50+ messages in thread
From: Thomas Gleixner @ 2025-03-13 15:59 UTC (permalink / raw)
To: LKML; +Cc: Peter Zijlstra, Jiri Slaby
Convert all lock/unlock pairs to guards and tidy up the code.
No functional change.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
kernel/irq/pm.c | 38 +++++++++++++-------------------------
1 file changed, 13 insertions(+), 25 deletions(-)
--- a/kernel/irq/pm.c
+++ b/kernel/irq/pm.c
@@ -46,8 +46,7 @@ void irq_pm_install_action(struct irq_de
desc->cond_suspend_depth++;
WARN_ON_ONCE(desc->no_suspend_depth &&
- (desc->no_suspend_depth +
- desc->cond_suspend_depth) != desc->nr_actions);
+ (desc->no_suspend_depth + desc->cond_suspend_depth) != desc->nr_actions);
}
/*
@@ -134,14 +133,12 @@ void suspend_device_irqs(void)
int irq;
for_each_irq_desc(irq, desc) {
- unsigned long flags;
bool sync;
if (irq_settings_is_nested_thread(desc))
continue;
- raw_spin_lock_irqsave(&desc->lock, flags);
- sync = suspend_device_irq(desc);
- raw_spin_unlock_irqrestore(&desc->lock, flags);
+ scoped_guard (raw_spinlock_irqsave, &desc->lock)
+ sync = suspend_device_irq(desc);
if (sync)
synchronize_irq(irq);
@@ -186,18 +183,15 @@ static void resume_irqs(bool want_early)
int irq;
for_each_irq_desc(irq, desc) {
- unsigned long flags;
- bool is_early = desc->action &&
- desc->action->flags & IRQF_EARLY_RESUME;
+ bool is_early = desc->action && desc->action->flags & IRQF_EARLY_RESUME;
if (!is_early && want_early)
continue;
if (irq_settings_is_nested_thread(desc))
continue;
- raw_spin_lock_irqsave(&desc->lock, flags);
+ guard(raw_spinlock_irqsave)(&desc->lock);
resume_irq(desc);
- raw_spin_unlock_irqrestore(&desc->lock, flags);
}
}
@@ -207,22 +201,16 @@ static void resume_irqs(bool want_early)
*/
void rearm_wake_irq(unsigned int irq)
{
- unsigned long flags;
- struct irq_desc *desc = irq_get_desc_buslock(irq, &flags, IRQ_GET_DESC_CHECK_GLOBAL);
+ scoped_irqdesc_get_and_buslock(irq, IRQ_GET_DESC_CHECK_GLOBAL) {
+ struct irq_desc *desc = scoped_irqdesc;
- if (!desc)
- return;
-
- if (!(desc->istate & IRQS_SUSPENDED) ||
- !irqd_is_wakeup_set(&desc->irq_data))
- goto unlock;
-
- desc->istate &= ~IRQS_SUSPENDED;
- irqd_set(&desc->irq_data, IRQD_WAKEUP_ARMED);
- __enable_irq(desc);
+ if (!(desc->istate & IRQS_SUSPENDED) || !irqd_is_wakeup_set(&desc->irq_data))
+ return;
-unlock:
- irq_put_desc_busunlock(desc, flags);
+ desc->istate &= ~IRQS_SUSPENDED;
+ irqd_set(&desc->irq_data, IRQD_WAKEUP_ARMED);
+ __enable_irq(desc);
+ }
}
/**
^ permalink raw reply [flat|nested] 50+ messages in thread
* [patch 05/46] genirq/resend: Switch to lock guards
2025-03-13 15:59 [patch 00/46] genirq: Cleanups and conversion to lock guards Thomas Gleixner
` (3 preceding siblings ...)
2025-03-13 15:59 ` [patch 04/46] genirq/pm: " Thomas Gleixner
@ 2025-03-13 15:59 ` Thomas Gleixner
2025-03-17 8:22 ` Shrikanth Hegde
2025-03-13 15:59 ` [patch 06/46] genirq/proc: " Thomas Gleixner
` (41 subsequent siblings)
46 siblings, 1 reply; 50+ messages in thread
From: Thomas Gleixner @ 2025-03-13 15:59 UTC (permalink / raw)
To: LKML; +Cc: Peter Zijlstra, Jiri Slaby
Convert all lock/unlock pairs to guards and tidy up the code.
No functional change.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
kernel/irq/resend.c | 50 +++++++++++++++++++++-----------------------------
1 file changed, 21 insertions(+), 29 deletions(-)
--- a/kernel/irq/resend.c
+++ b/kernel/irq/resend.c
@@ -30,18 +30,17 @@ static DEFINE_RAW_SPINLOCK(irq_resend_lo
*/
static void resend_irqs(struct tasklet_struct *unused)
{
- struct irq_desc *desc;
-
- raw_spin_lock_irq(&irq_resend_lock);
+ guard(raw_spinlock_irq)(&irq_resend_lock);
while (!hlist_empty(&irq_resend_list)) {
- desc = hlist_entry(irq_resend_list.first, struct irq_desc,
- resend_node);
+ struct irq_desc *desc;
+
+ desc = hlist_entry(irq_resend_list.first, struct irq_desc, resend_node);
hlist_del_init(&desc->resend_node);
+
raw_spin_unlock(&irq_resend_lock);
desc->handle_irq(desc);
raw_spin_lock(&irq_resend_lock);
}
- raw_spin_unlock_irq(&irq_resend_lock);
}
/* Tasklet to handle resend: */
@@ -75,19 +74,18 @@ static int irq_sw_resend(struct irq_desc
}
/* Add to resend_list and activate the softirq: */
- raw_spin_lock(&irq_resend_lock);
- if (hlist_unhashed(&desc->resend_node))
- hlist_add_head(&desc->resend_node, &irq_resend_list);
- raw_spin_unlock(&irq_resend_lock);
+ scoped_guard (raw_spinlock, &irq_resend_lock) {
+ if (hlist_unhashed(&desc->resend_node))
+ hlist_add_head(&desc->resend_node, &irq_resend_list);
+ }
tasklet_schedule(&resend_tasklet);
return 0;
}
void clear_irq_resend(struct irq_desc *desc)
{
- raw_spin_lock(&irq_resend_lock);
+ guard(raw_spinlock)(&irq_resend_lock);
hlist_del_init(&desc->resend_node);
- raw_spin_unlock(&irq_resend_lock);
}
void irq_resend_init(struct irq_desc *desc)
@@ -172,30 +170,24 @@ int check_irq_resend(struct irq_desc *de
*/
int irq_inject_interrupt(unsigned int irq)
{
- struct irq_desc *desc;
- unsigned long flags;
- int err;
+ int err = -EINVAL;
/* Try the state injection hardware interface first */
if (!irq_set_irqchip_state(irq, IRQCHIP_STATE_PENDING, true))
return 0;
/* That failed, try via the resend mechanism */
- desc = irq_get_desc_buslock(irq, &flags, 0);
- if (!desc)
- return -EINVAL;
+ scoped_irqdesc_get_and_buslock(irq, 0) {
+ struct irq_desc *desc = scoped_irqdesc;
- /*
- * Only try to inject when the interrupt is:
- * - not NMI type
- * - activated
- */
- if (irq_is_nmi(desc) || !irqd_is_activated(&desc->irq_data))
- err = -EINVAL;
- else
- err = check_irq_resend(desc, true);
-
- irq_put_desc_busunlock(desc, flags);
+ /*
+ * Only try to inject when the interrupt is:
+ * - not NMI type
+ * - activated
+ */
+ if (!irq_is_nmi(desc) && irqd_is_activated(&desc->irq_data))
+ err = check_irq_resend(desc, true);
+ }
return err;
}
EXPORT_SYMBOL_GPL(irq_inject_interrupt);
^ permalink raw reply [flat|nested] 50+ messages in thread
* [patch 06/46] genirq/proc: Switch to lock guards
2025-03-13 15:59 [patch 00/46] genirq: Cleanups and conversion to lock guards Thomas Gleixner
` (4 preceding siblings ...)
2025-03-13 15:59 ` [patch 05/46] genirq/resend: " Thomas Gleixner
@ 2025-03-13 15:59 ` Thomas Gleixner
2025-03-13 15:59 ` [patch 07/46] genirq/spurious: Cleanup code Thomas Gleixner
` (40 subsequent siblings)
46 siblings, 0 replies; 50+ messages in thread
From: Thomas Gleixner @ 2025-03-13 15:59 UTC (permalink / raw)
To: LKML; +Cc: Peter Zijlstra, Jiri Slaby
Convert all lock/unlock pairs to guards and tidy up the code.
No functional change.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
kernel/irq/proc.c | 65 +++++++++++++++++++-----------------------------------
1 file changed, 24 insertions(+), 41 deletions(-)
--- a/kernel/irq/proc.c
+++ b/kernel/irq/proc.c
@@ -81,20 +81,18 @@ static int show_irq_affinity(int type, s
static int irq_affinity_hint_proc_show(struct seq_file *m, void *v)
{
struct irq_desc *desc = irq_to_desc((long)m->private);
- unsigned long flags;
cpumask_var_t mask;
if (!zalloc_cpumask_var(&mask, GFP_KERNEL))
return -ENOMEM;
- raw_spin_lock_irqsave(&desc->lock, flags);
- if (desc->affinity_hint)
- cpumask_copy(mask, desc->affinity_hint);
- raw_spin_unlock_irqrestore(&desc->lock, flags);
+ scoped_guard (raw_spinlock_irq, &desc->lock) {
+ if (desc->affinity_hint)
+ cpumask_copy(mask, desc->affinity_hint);
+ }
seq_printf(m, "%*pb\n", cpumask_pr_args(mask));
free_cpumask_var(mask);
-
return 0;
}
@@ -295,23 +293,18 @@ static int irq_spurious_proc_show(struct
#define MAX_NAMELEN 128
-static int name_unique(unsigned int irq, struct irqaction *new_action)
+static bool name_unique(unsigned int irq, struct irqaction *new_action)
{
struct irq_desc *desc = irq_to_desc(irq);
struct irqaction *action;
- unsigned long flags;
- int ret = 1;
- raw_spin_lock_irqsave(&desc->lock, flags);
+ guard(raw_spinlock_irq)(&desc->lock);
for_each_action_of_desc(desc, action) {
if ((action != new_action) && action->name &&
- !strcmp(new_action->name, action->name)) {
- ret = 0;
- break;
- }
+ !strcmp(new_action->name, action->name))
+ return false;
}
- raw_spin_unlock_irqrestore(&desc->lock, flags);
- return ret;
+ return true;
}
void register_handler_proc(unsigned int irq, struct irqaction *action)
@@ -319,8 +312,7 @@ void register_handler_proc(unsigned int
char name [MAX_NAMELEN];
struct irq_desc *desc = irq_to_desc(irq);
- if (!desc->dir || action->dir || !action->name ||
- !name_unique(irq, action))
+ if (!desc->dir || action->dir || !action->name || !name_unique(irq, action))
return;
snprintf(name, MAX_NAMELEN, "%s", action->name);
@@ -347,17 +339,16 @@ void register_irq_proc(unsigned int irq,
* added, not when the descriptor is created, so multiple
* tasks might try to register at the same time.
*/
- mutex_lock(®ister_lock);
+ guard(mutex)(®ister_lock);
if (desc->dir)
- goto out_unlock;
-
- sprintf(name, "%d", irq);
+ return;
/* create /proc/irq/1234 */
+ sprintf(name, "%d", irq);
desc->dir = proc_mkdir(name, root_irq_dir);
if (!desc->dir)
- goto out_unlock;
+ return;
#ifdef CONFIG_SMP
umode_t umode = S_IRUGO;
@@ -366,31 +357,27 @@ void register_irq_proc(unsigned int irq,
umode |= S_IWUSR;
/* create /proc/irq/<irq>/smp_affinity */
- proc_create_data("smp_affinity", umode, desc->dir,
- &irq_affinity_proc_ops, irqp);
+ proc_create_data("smp_affinity", umode, desc->dir, &irq_affinity_proc_ops, irqp);
/* create /proc/irq/<irq>/affinity_hint */
proc_create_single_data("affinity_hint", 0444, desc->dir,
- irq_affinity_hint_proc_show, irqp);
+ irq_affinity_hint_proc_show, irqp);
/* create /proc/irq/<irq>/smp_affinity_list */
proc_create_data("smp_affinity_list", umode, desc->dir,
&irq_affinity_list_proc_ops, irqp);
- proc_create_single_data("node", 0444, desc->dir, irq_node_proc_show,
- irqp);
+ proc_create_single_data("node", 0444, desc->dir, irq_node_proc_show, irqp);
# ifdef CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK
proc_create_single_data("effective_affinity", 0444, desc->dir,
- irq_effective_aff_proc_show, irqp);
+ irq_effective_aff_proc_show, irqp);
proc_create_single_data("effective_affinity_list", 0444, desc->dir,
- irq_effective_aff_list_proc_show, irqp);
+ irq_effective_aff_list_proc_show, irqp);
# endif
#endif
proc_create_single_data("spurious", 0444, desc->dir,
- irq_spurious_proc_show, (void *)(long)irq);
+ irq_spurious_proc_show, (void *)(long)irq);
-out_unlock:
- mutex_unlock(®ister_lock);
}
void unregister_irq_proc(unsigned int irq, struct irq_desc *desc)
@@ -468,7 +455,6 @@ int show_interrupts(struct seq_file *p,
int i = *(loff_t *) v, j;
struct irqaction *action;
struct irq_desc *desc;
- unsigned long flags;
if (i > ACTUAL_NR_IRQS)
return 0;
@@ -487,13 +473,13 @@ int show_interrupts(struct seq_file *p,
seq_putc(p, '\n');
}
- rcu_read_lock();
+ guard(rcu)();
desc = irq_to_desc(i);
if (!desc || irq_settings_is_hidden(desc))
- goto outsparse;
+ return 0;
if (!desc->action || irq_desc_is_chained(desc) || !desc->kstat_irqs)
- goto outsparse;
+ return 0;
seq_printf(p, "%*d:", prec, i);
for_each_online_cpu(j) {
@@ -503,7 +489,7 @@ int show_interrupts(struct seq_file *p,
}
seq_putc(p, ' ');
- raw_spin_lock_irqsave(&desc->lock, flags);
+ guard(raw_spinlock_irq)(&desc->lock);
if (desc->irq_data.chip) {
if (desc->irq_data.chip->irq_print_chip)
desc->irq_data.chip->irq_print_chip(&desc->irq_data, p);
@@ -532,9 +518,6 @@ int show_interrupts(struct seq_file *p,
}
seq_putc(p, '\n');
- raw_spin_unlock_irqrestore(&desc->lock, flags);
-outsparse:
- rcu_read_unlock();
return 0;
}
#endif
^ permalink raw reply [flat|nested] 50+ messages in thread
* [patch 07/46] genirq/spurious: Cleanup code
2025-03-13 15:59 [patch 00/46] genirq: Cleanups and conversion to lock guards Thomas Gleixner
` (5 preceding siblings ...)
2025-03-13 15:59 ` [patch 06/46] genirq/proc: " Thomas Gleixner
@ 2025-03-13 15:59 ` Thomas Gleixner
2025-03-13 15:59 ` [patch 08/46] genirq/spurious: Switch to lock guards Thomas Gleixner
` (39 subsequent siblings)
46 siblings, 0 replies; 50+ messages in thread
From: Thomas Gleixner @ 2025-03-13 15:59 UTC (permalink / raw)
To: LKML; +Cc: Peter Zijlstra, Jiri Slaby
Clean up the coding style
No functional change.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
kernel/irq/spurious.c | 74 ++++++++++++++++++--------------------------------
1 file changed, 28 insertions(+), 46 deletions(-)
--- a/kernel/irq/spurious.c
+++ b/kernel/irq/spurious.c
@@ -34,8 +34,9 @@ static atomic_t irq_poll_active;
* true and let the handler run.
*/
bool irq_wait_for_poll(struct irq_desc *desc)
- __must_hold(&desc->lock)
{
+ lockdep_assert_held(&desc->lock);
+
if (WARN_ONCE(irq_poll_cpu == smp_processor_id(),
"irq poll in progress on cpu %d for irq %d\n",
smp_processor_id(), desc->irq_data.irq))
@@ -157,8 +158,7 @@ static void poll_spurious_irqs(struct ti
continue;
/* Racy but it doesn't matter */
- state = desc->istate;
- barrier();
+ state = READ_ONCE(desc->istate);
if (!(state & IRQS_SPURIOUS_DISABLED))
continue;
@@ -168,8 +168,7 @@ static void poll_spurious_irqs(struct ti
}
out:
atomic_dec(&irq_poll_active);
- mod_timer(&poll_spurious_irq_timer,
- jiffies + POLL_SPURIOUS_IRQ_INTERVAL);
+ mod_timer(&poll_spurious_irq_timer, jiffies + POLL_SPURIOUS_IRQ_INTERVAL);
}
static inline int bad_action_ret(irqreturn_t action_ret)
@@ -195,15 +194,12 @@ static void __report_bad_irq(struct irq_
struct irqaction *action;
unsigned long flags;
- if (bad_action_ret(action_ret)) {
- printk(KERN_ERR "irq event %d: bogus return value %x\n",
- irq, action_ret);
- } else {
- printk(KERN_ERR "irq %d: nobody cared (try booting with "
- "the \"irqpoll\" option)\n", irq);
- }
+ if (bad_action_ret(action_ret))
+ pr_err("irq event %d: bogus return value %x\n", irq, action_ret);
+ else
+ pr_err("irq %d: nobody cared (try booting with the \"irqpoll\" option)\n", irq);
dump_stack();
- printk(KERN_ERR "handlers:\n");
+ pr_err("handlers:\n");
/*
* We need to take desc->lock here. note_interrupt() is called
@@ -213,11 +209,10 @@ static void __report_bad_irq(struct irq_
*/
raw_spin_lock_irqsave(&desc->lock, flags);
for_each_action_of_desc(desc, action) {
- printk(KERN_ERR "[<%p>] %ps", action->handler, action->handler);
+ pr_err("[<%p>] %ps", action->handler, action->handler);
if (action->thread_fn)
- printk(KERN_CONT " threaded [<%p>] %ps",
- action->thread_fn, action->thread_fn);
- printk(KERN_CONT "\n");
+ pr_cont(" threaded [<%p>] %ps", action->thread_fn, action->thread_fn);
+ pr_cont("\n");
}
raw_spin_unlock_irqrestore(&desc->lock, flags);
}
@@ -232,18 +227,17 @@ static void report_bad_irq(struct irq_de
}
}
-static inline int
-try_misrouted_irq(unsigned int irq, struct irq_desc *desc,
- irqreturn_t action_ret)
+static inline bool try_misrouted_irq(unsigned int irq, struct irq_desc *desc,
+ irqreturn_t action_ret)
{
struct irqaction *action;
if (!irqfixup)
- return 0;
+ return false;
/* We didn't actually handle the IRQ - see if it was misrouted? */
if (action_ret == IRQ_NONE)
- return 1;
+ return true;
/*
* But for 'irqfixup == 2' we also do it for handled interrupts if
@@ -251,19 +245,16 @@ try_misrouted_irq(unsigned int irq, stru
* traditional PC timer interrupt.. Legacy)
*/
if (irqfixup < 2)
- return 0;
+ return false;
if (!irq)
- return 1;
+ return true;
/*
* Since we don't get the descriptor lock, "action" can
- * change under us. We don't really care, but we don't
- * want to follow a NULL pointer. So tell the compiler to
- * just load it once by using a barrier.
+ * change under us.
*/
- action = desc->action;
- barrier();
+ action = READ_ONCE(desc->action);
return action && (action->flags & IRQF_IRQPOLL);
}
@@ -273,8 +264,7 @@ void note_interrupt(struct irq_desc *des
{
unsigned int irq;
- if (desc->istate & IRQS_POLL_INPROGRESS ||
- irq_settings_is_polled(desc))
+ if (desc->istate & IRQS_POLL_INPROGRESS || irq_settings_is_polled(desc))
return;
if (bad_action_ret(action_ret)) {
@@ -420,13 +410,12 @@ void note_interrupt(struct irq_desc *des
/*
* Now kill the IRQ
*/
- printk(KERN_EMERG "Disabling IRQ #%d\n", irq);
+ pr_emerg("Disabling IRQ #%d\n", irq);
desc->istate |= IRQS_SPURIOUS_DISABLED;
desc->depth++;
irq_disable(desc);
- mod_timer(&poll_spurious_irq_timer,
- jiffies + POLL_SPURIOUS_IRQ_INTERVAL);
+ mod_timer(&poll_spurious_irq_timer, jiffies + POLL_SPURIOUS_IRQ_INTERVAL);
}
desc->irqs_unhandled = 0;
}
@@ -436,11 +425,9 @@ bool noirqdebug __read_mostly;
int noirqdebug_setup(char *str)
{
noirqdebug = 1;
- printk(KERN_INFO "IRQ lockup detection disabled\n");
-
+ pr_info("IRQ lockup detection disabled\n");
return 1;
}
-
__setup("noirqdebug", noirqdebug_setup);
module_param(noirqdebug, bool, 0644);
MODULE_PARM_DESC(noirqdebug, "Disable irq lockup detection when true");
@@ -452,12 +439,10 @@ static int __init irqfixup_setup(char *s
return 1;
}
irqfixup = 1;
- printk(KERN_WARNING "Misrouted IRQ fixup support enabled.\n");
- printk(KERN_WARNING "This may impact system performance.\n");
-
+ pr_warn("Misrouted IRQ fixup support enabled.\n");
+ pr_warn("This may impact system performance.\n");
return 1;
}
-
__setup("irqfixup", irqfixup_setup);
module_param(irqfixup, int, 0644);
@@ -468,11 +453,8 @@ static int __init irqpoll_setup(char *st
return 1;
}
irqfixup = 2;
- printk(KERN_WARNING "Misrouted IRQ fixup and polling support "
- "enabled\n");
- printk(KERN_WARNING "This may significantly impact system "
- "performance\n");
+ pr_warn("Misrouted IRQ fixup and polling support enabled\n");
+ pr_warn("This may significantly impact system performance\n");
return 1;
}
-
__setup("irqpoll", irqpoll_setup);
^ permalink raw reply [flat|nested] 50+ messages in thread
* [patch 08/46] genirq/spurious: Switch to lock guards
2025-03-13 15:59 [patch 00/46] genirq: Cleanups and conversion to lock guards Thomas Gleixner
` (6 preceding siblings ...)
2025-03-13 15:59 ` [patch 07/46] genirq/spurious: Cleanup code Thomas Gleixner
@ 2025-03-13 15:59 ` Thomas Gleixner
2025-03-13 15:59 ` [patch 09/46] genirq/cpuhotplug: Convert " Thomas Gleixner
` (38 subsequent siblings)
46 siblings, 0 replies; 50+ messages in thread
From: Thomas Gleixner @ 2025-03-13 15:59 UTC (permalink / raw)
To: LKML; +Cc: Peter Zijlstra, Jiri Slaby
Convert all lock/unlock pairs to guards and tidy up the code.
No functional change.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
kernel/irq/spurious.c | 30 ++++++++++++------------------
1 file changed, 12 insertions(+), 18 deletions(-)
--- a/kernel/irq/spurious.c
+++ b/kernel/irq/spurious.c
@@ -60,37 +60,35 @@ bool irq_wait_for_poll(struct irq_desc *
/*
* Recovery handler for misrouted interrupts.
*/
-static int try_one_irq(struct irq_desc *desc, bool force)
+static bool try_one_irq(struct irq_desc *desc, bool force)
{
- irqreturn_t ret = IRQ_NONE;
struct irqaction *action;
+ bool ret = false;
- raw_spin_lock(&desc->lock);
+ guard(raw_spinlock)(&desc->lock);
/*
* PER_CPU, nested thread interrupts and interrupts explicitly
* marked polled are excluded from polling.
*/
- if (irq_settings_is_per_cpu(desc) ||
- irq_settings_is_nested_thread(desc) ||
+ if (irq_settings_is_per_cpu(desc) || irq_settings_is_nested_thread(desc) ||
irq_settings_is_polled(desc))
- goto out;
+ return false;
/*
* Do not poll disabled interrupts unless the spurious
* disabled poller asks explicitly.
*/
if (irqd_irq_disabled(&desc->irq_data) && !force)
- goto out;
+ return false;
/*
* All handlers must agree on IRQF_SHARED, so we test just the
* first.
*/
action = desc->action;
- if (!action || !(action->flags & IRQF_SHARED) ||
- (action->flags & __IRQF_TIMER))
- goto out;
+ if (!action || !(action->flags & IRQF_SHARED) || (action->flags & __IRQF_TIMER))
+ return false;
/* Already running on another processor */
if (irqd_irq_inprogress(&desc->irq_data)) {
@@ -99,21 +97,19 @@ static int try_one_irq(struct irq_desc *
* CPU to go looking for our mystery interrupt too
*/
desc->istate |= IRQS_PENDING;
- goto out;
+ return false;
}
/* Mark it poll in progress */
desc->istate |= IRQS_POLL_INPROGRESS;
do {
if (handle_irq_event(desc) == IRQ_HANDLED)
- ret = IRQ_HANDLED;
+ ret = true;
/* Make sure that there is still a valid action */
action = desc->action;
} while ((desc->istate & IRQS_PENDING) && action);
desc->istate &= ~IRQS_POLL_INPROGRESS;
-out:
- raw_spin_unlock(&desc->lock);
- return ret == IRQ_HANDLED;
+ return ret;
}
static int misrouted_irq(int irq)
@@ -192,7 +188,6 @@ static void __report_bad_irq(struct irq_
{
unsigned int irq = irq_desc_get_irq(desc);
struct irqaction *action;
- unsigned long flags;
if (bad_action_ret(action_ret))
pr_err("irq event %d: bogus return value %x\n", irq, action_ret);
@@ -207,14 +202,13 @@ static void __report_bad_irq(struct irq_
* with something else removing an action. It's ok to take
* desc->lock here. See synchronize_irq().
*/
- raw_spin_lock_irqsave(&desc->lock, flags);
+ guard(raw_spinlock_irqsave)(&desc->lock);
for_each_action_of_desc(desc, action) {
pr_err("[<%p>] %ps", action->handler, action->handler);
if (action->thread_fn)
pr_cont(" threaded [<%p>] %ps", action->thread_fn, action->thread_fn);
pr_cont("\n");
}
- raw_spin_unlock_irqrestore(&desc->lock, flags);
}
static void report_bad_irq(struct irq_desc *desc, irqreturn_t action_ret)
^ permalink raw reply [flat|nested] 50+ messages in thread
* [patch 09/46] genirq/cpuhotplug: Convert to lock guards
2025-03-13 15:59 [patch 00/46] genirq: Cleanups and conversion to lock guards Thomas Gleixner
` (7 preceding siblings ...)
2025-03-13 15:59 ` [patch 08/46] genirq/spurious: Switch to lock guards Thomas Gleixner
@ 2025-03-13 15:59 ` Thomas Gleixner
2025-03-13 15:59 ` [patch 10/46] genirq/debugfs: " Thomas Gleixner
` (37 subsequent siblings)
46 siblings, 0 replies; 50+ messages in thread
From: Thomas Gleixner @ 2025-03-13 15:59 UTC (permalink / raw)
To: LKML; +Cc: Peter Zijlstra, Jiri Slaby
Convert all lock/unlock pairs to guards and tidy up the code.
No functional change.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
kernel/irq/cpuhotplug.c | 10 ++++------
1 file changed, 4 insertions(+), 6 deletions(-)
--- a/kernel/irq/cpuhotplug.c
+++ b/kernel/irq/cpuhotplug.c
@@ -177,9 +177,8 @@ void irq_migrate_all_off_this_cpu(void)
bool affinity_broken;
desc = irq_to_desc(irq);
- raw_spin_lock(&desc->lock);
- affinity_broken = migrate_one_irq(desc);
- raw_spin_unlock(&desc->lock);
+ scoped_guard (raw_spinlock, &desc->lock)
+ affinity_broken = migrate_one_irq(desc);
if (affinity_broken) {
pr_debug_ratelimited("IRQ %u: no longer affine to CPU%u\n",
@@ -244,9 +243,8 @@ int irq_affinity_online_cpu(unsigned int
irq_lock_sparse();
for_each_active_irq(irq) {
desc = irq_to_desc(irq);
- raw_spin_lock_irq(&desc->lock);
- irq_restore_affinity_of_irq(desc, cpu);
- raw_spin_unlock_irq(&desc->lock);
+ scoped_guard (raw_spinlock, &desc->lock)
+ irq_restore_affinity_of_irq(desc, cpu);
}
irq_unlock_sparse();
^ permalink raw reply [flat|nested] 50+ messages in thread
* [patch 10/46] genirq/debugfs: Convert to lock guards
2025-03-13 15:59 [patch 00/46] genirq: Cleanups and conversion to lock guards Thomas Gleixner
` (8 preceding siblings ...)
2025-03-13 15:59 ` [patch 09/46] genirq/cpuhotplug: Convert " Thomas Gleixner
@ 2025-03-13 15:59 ` Thomas Gleixner
2025-03-13 16:00 ` [patch 11/46] genirq/chip: Prepare for code reduction Thomas Gleixner
` (36 subsequent siblings)
46 siblings, 0 replies; 50+ messages in thread
From: Thomas Gleixner @ 2025-03-13 15:59 UTC (permalink / raw)
To: LKML; +Cc: Peter Zijlstra, Jiri Slaby
Convert all lock/unlock pairs to guards and tidy up the code.
No functional change.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
kernel/irq/debugfs.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
--- a/kernel/irq/debugfs.c
+++ b/kernel/irq/debugfs.c
@@ -160,7 +160,7 @@ static int irq_debug_show(struct seq_fil
struct irq_desc *desc = m->private;
struct irq_data *data;
- raw_spin_lock_irq(&desc->lock);
+ guard(raw_spinlock_irq)(&desc->lock);
data = irq_desc_get_irq_data(desc);
seq_printf(m, "handler: %ps\n", desc->handle_irq);
seq_printf(m, "device: %s\n", desc->dev_name);
@@ -178,7 +178,6 @@ static int irq_debug_show(struct seq_fil
seq_printf(m, "node: %d\n", irq_data_get_node(data));
irq_debug_show_masks(m, desc);
irq_debug_show_data(m, data, 0);
- raw_spin_unlock_irq(&desc->lock);
return 0;
}
^ permalink raw reply [flat|nested] 50+ messages in thread
* [patch 11/46] genirq/chip: Prepare for code reduction
2025-03-13 15:59 [patch 00/46] genirq: Cleanups and conversion to lock guards Thomas Gleixner
` (9 preceding siblings ...)
2025-03-13 15:59 ` [patch 10/46] genirq/debugfs: " Thomas Gleixner
@ 2025-03-13 16:00 ` Thomas Gleixner
2025-03-13 16:00 ` [patch 12/46] genirq/chip: Rework handle_nested_irq() Thomas Gleixner
` (35 subsequent siblings)
46 siblings, 0 replies; 50+ messages in thread
From: Thomas Gleixner @ 2025-03-13 16:00 UTC (permalink / raw)
To: LKML; +Cc: Peter Zijlstra, Jiri Slaby
The interrupt flow handlers have similar patterns to decide whether to
handle an interrupt or not.
Provide common helper functions to allow removal of duplicated code.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
kernel/irq/chip.c | 37 ++++++++++++++++++++++++++++---------
1 file changed, 28 insertions(+), 9 deletions(-)
--- a/kernel/irq/chip.c
+++ b/kernel/irq/chip.c
@@ -499,7 +499,7 @@ static bool irq_check_poll(struct irq_de
return irq_wait_for_poll(desc);
}
-static bool irq_may_run(struct irq_desc *desc)
+static bool irq_can_handle_pm(struct irq_desc *desc)
{
unsigned int mask = IRQD_IRQ_INPROGRESS | IRQD_WAKEUP_ARMED;
@@ -524,6 +524,25 @@ static bool irq_may_run(struct irq_desc
return irq_check_poll(desc);
}
+static inline bool irq_can_handle_actions(struct irq_desc *desc)
+{
+ desc->istate &= ~(IRQS_REPLAY | IRQS_WAITING);
+
+ if (unlikely(!desc->action || irqd_irq_disabled(&desc->irq_data))) {
+ desc->istate |= IRQS_PENDING;
+ return false;
+ }
+ return true;
+}
+
+static inline bool irq_can_handle(struct irq_desc *desc)
+{
+ if (!irq_can_handle_pm(desc))
+ return false;
+
+ return irq_can_handle_actions(desc);
+}
+
/**
* handle_simple_irq - Simple and software-decoded IRQs.
* @desc: the interrupt description structure for this irq
@@ -539,7 +558,7 @@ void handle_simple_irq(struct irq_desc *
{
raw_spin_lock(&desc->lock);
- if (!irq_may_run(desc))
+ if (!irq_can_handle_pm(desc))
goto out_unlock;
desc->istate &= ~(IRQS_REPLAY | IRQS_WAITING);
@@ -574,7 +593,7 @@ void handle_untracked_irq(struct irq_des
{
raw_spin_lock(&desc->lock);
- if (!irq_may_run(desc))
+ if (!irq_can_handle_pm(desc))
goto out_unlock;
desc->istate &= ~(IRQS_REPLAY | IRQS_WAITING);
@@ -630,7 +649,7 @@ void handle_level_irq(struct irq_desc *d
raw_spin_lock(&desc->lock);
mask_ack_irq(desc);
- if (!irq_may_run(desc))
+ if (!irq_can_handle_pm(desc))
goto out_unlock;
desc->istate &= ~(IRQS_REPLAY | IRQS_WAITING);
@@ -695,7 +714,7 @@ void handle_fasteoi_irq(struct irq_desc
* can arrive on the new CPU before the original CPU has completed
* handling the previous one - it may need to be resent.
*/
- if (!irq_may_run(desc)) {
+ if (!irq_can_handle_pm(desc)) {
if (irqd_needs_resend_when_in_progress(&desc->irq_data))
desc->istate |= IRQS_PENDING;
goto out;
@@ -790,7 +809,7 @@ void handle_edge_irq(struct irq_desc *de
desc->istate &= ~(IRQS_REPLAY | IRQS_WAITING);
- if (!irq_may_run(desc)) {
+ if (!irq_can_handle_pm(desc)) {
desc->istate |= IRQS_PENDING;
mask_ack_irq(desc);
goto out_unlock;
@@ -854,7 +873,7 @@ void handle_edge_eoi_irq(struct irq_desc
desc->istate &= ~(IRQS_REPLAY | IRQS_WAITING);
- if (!irq_may_run(desc)) {
+ if (!irq_can_handle_pm(desc)) {
desc->istate |= IRQS_PENDING;
goto out_eoi;
}
@@ -1213,7 +1232,7 @@ void handle_fasteoi_ack_irq(struct irq_d
raw_spin_lock(&desc->lock);
- if (!irq_may_run(desc))
+ if (!irq_can_handle_pm(desc))
goto out;
desc->istate &= ~(IRQS_REPLAY | IRQS_WAITING);
@@ -1265,7 +1284,7 @@ void handle_fasteoi_mask_irq(struct irq_
raw_spin_lock(&desc->lock);
mask_ack_irq(desc);
- if (!irq_may_run(desc))
+ if (!irq_can_handle_pm(desc))
goto out;
desc->istate &= ~(IRQS_REPLAY | IRQS_WAITING);
^ permalink raw reply [flat|nested] 50+ messages in thread
* [patch 12/46] genirq/chip: Rework handle_nested_irq()
2025-03-13 15:59 [patch 00/46] genirq: Cleanups and conversion to lock guards Thomas Gleixner
` (10 preceding siblings ...)
2025-03-13 16:00 ` [patch 11/46] genirq/chip: Prepare for code reduction Thomas Gleixner
@ 2025-03-13 16:00 ` Thomas Gleixner
2025-03-13 16:00 ` [patch 13/46] genirq/chip: Rework handle_simple_irq() Thomas Gleixner
` (34 subsequent siblings)
46 siblings, 0 replies; 50+ messages in thread
From: Thomas Gleixner @ 2025-03-13 16:00 UTC (permalink / raw)
To: LKML; +Cc: Peter Zijlstra, Jiri Slaby
Use the new helpers to decide whether the interrupt should be handled and
switch the descriptor locking to guard().
Fixup the kernel doc comment while at it.
No functional change.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
kernel/irq/chip.c | 78 ++++++++++++++++++++++++------------------------------
1 file changed, 36 insertions(+), 42 deletions(-)
--- a/kernel/irq/chip.c
+++ b/kernel/irq/chip.c
@@ -450,48 +450,6 @@ void unmask_threaded_irq(struct irq_desc
unmask_irq(desc);
}
-/*
- * handle_nested_irq - Handle a nested irq from a irq thread
- * @irq: the interrupt number
- *
- * Handle interrupts which are nested into a threaded interrupt
- * handler. The handler function is called inside the calling
- * threads context.
- */
-void handle_nested_irq(unsigned int irq)
-{
- struct irq_desc *desc = irq_to_desc(irq);
- struct irqaction *action;
- irqreturn_t action_ret;
-
- might_sleep();
-
- raw_spin_lock_irq(&desc->lock);
-
- desc->istate &= ~(IRQS_REPLAY | IRQS_WAITING);
-
- action = desc->action;
- if (unlikely(!action || irqd_irq_disabled(&desc->irq_data))) {
- desc->istate |= IRQS_PENDING;
- raw_spin_unlock_irq(&desc->lock);
- return;
- }
-
- kstat_incr_irqs_this_cpu(desc);
- atomic_inc(&desc->threads_active);
- raw_spin_unlock_irq(&desc->lock);
-
- action_ret = IRQ_NONE;
- for_each_action_of_desc(desc, action)
- action_ret |= action->thread_fn(action->irq, action->dev_id);
-
- if (!irq_settings_no_debug(desc))
- note_interrupt(desc, action_ret);
-
- wake_threads_waitq(desc);
-}
-EXPORT_SYMBOL_GPL(handle_nested_irq);
-
static bool irq_check_poll(struct irq_desc *desc)
{
if (!(desc->istate & IRQS_POLL_INPROGRESS))
@@ -544,6 +502,42 @@ static inline bool irq_can_handle(struct
}
/**
+ * handle_nested_irq - Handle a nested irq from a irq thread
+ * @irq: the interrupt number
+ *
+ * Handle interrupts which are nested into a threaded interrupt
+ * handler. The handler function is called inside the calling threads
+ * context.
+ */
+void handle_nested_irq(unsigned int irq)
+{
+ struct irq_desc *desc = irq_to_desc(irq);
+ struct irqaction *action;
+ irqreturn_t action_ret;
+
+ might_sleep();
+
+ scoped_guard (raw_spinlock_irq, &desc->lock) {
+ if (irq_can_handle_actions(desc))
+ return;
+
+ action = desc->action;
+ kstat_incr_irqs_this_cpu(desc);
+ atomic_inc(&desc->threads_active);
+ }
+
+ action_ret = IRQ_NONE;
+ for_each_action_of_desc(desc, action)
+ action_ret |= action->thread_fn(action->irq, action->dev_id);
+
+ if (!irq_settings_no_debug(desc))
+ note_interrupt(desc, action_ret);
+
+ wake_threads_waitq(desc);
+}
+EXPORT_SYMBOL_GPL(handle_nested_irq);
+
+/**
* handle_simple_irq - Simple and software-decoded IRQs.
* @desc: the interrupt description structure for this irq
*
^ permalink raw reply [flat|nested] 50+ messages in thread
* [patch 13/46] genirq/chip: Rework handle_simple_irq()
2025-03-13 15:59 [patch 00/46] genirq: Cleanups and conversion to lock guards Thomas Gleixner
` (11 preceding siblings ...)
2025-03-13 16:00 ` [patch 12/46] genirq/chip: Rework handle_nested_irq() Thomas Gleixner
@ 2025-03-13 16:00 ` Thomas Gleixner
2025-03-13 16:00 ` [patch 14/46] genirq/chip: Rework handle_untracked_irq() Thomas Gleixner
` (33 subsequent siblings)
46 siblings, 0 replies; 50+ messages in thread
From: Thomas Gleixner @ 2025-03-13 16:00 UTC (permalink / raw)
To: LKML; +Cc: Peter Zijlstra, Jiri Slaby
Use the new helpers to decide whether the interrupt should be handled and
switch the descriptor locking to guard().
Fixup the kernel doc comment while at it.
No functional change.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
kernel/irq/chip.c | 30 ++++++++++--------------------
1 file changed, 10 insertions(+), 20 deletions(-)
--- a/kernel/irq/chip.c
+++ b/kernel/irq/chip.c
@@ -538,35 +538,25 @@ void handle_nested_irq(unsigned int irq)
EXPORT_SYMBOL_GPL(handle_nested_irq);
/**
- * handle_simple_irq - Simple and software-decoded IRQs.
- * @desc: the interrupt description structure for this irq
+ * handle_simple_irq - Simple and software-decoded IRQs.
+ * @desc: the interrupt description structure for this irq
*
- * Simple interrupts are either sent from a demultiplexing interrupt
- * handler or come from hardware, where no interrupt hardware control
- * is necessary.
+ * Simple interrupts are either sent from a demultiplexing interrupt
+ * handler or come from hardware, where no interrupt hardware control is
+ * necessary.
*
- * Note: The caller is expected to handle the ack, clear, mask and
- * unmask issues if necessary.
+ * Note: The caller is expected to handle the ack, clear, mask and unmask
+ * issues if necessary.
*/
void handle_simple_irq(struct irq_desc *desc)
{
- raw_spin_lock(&desc->lock);
+ guard(raw_spinlock)(&desc->lock);
- if (!irq_can_handle_pm(desc))
- goto out_unlock;
-
- desc->istate &= ~(IRQS_REPLAY | IRQS_WAITING);
-
- if (unlikely(!desc->action || irqd_irq_disabled(&desc->irq_data))) {
- desc->istate |= IRQS_PENDING;
- goto out_unlock;
- }
+ if (!irq_can_handle(desc))
+ return;
kstat_incr_irqs_this_cpu(desc);
handle_irq_event(desc);
-
-out_unlock:
- raw_spin_unlock(&desc->lock);
}
EXPORT_SYMBOL_GPL(handle_simple_irq);
^ permalink raw reply [flat|nested] 50+ messages in thread
* [patch 14/46] genirq/chip: Rework handle_untracked_irq()
2025-03-13 15:59 [patch 00/46] genirq: Cleanups and conversion to lock guards Thomas Gleixner
` (12 preceding siblings ...)
2025-03-13 16:00 ` [patch 13/46] genirq/chip: Rework handle_simple_irq() Thomas Gleixner
@ 2025-03-13 16:00 ` Thomas Gleixner
2025-03-13 16:00 ` [patch 15/46] genirq/chip: Rework handle_level_irq() Thomas Gleixner
` (32 subsequent siblings)
46 siblings, 0 replies; 50+ messages in thread
From: Thomas Gleixner @ 2025-03-13 16:00 UTC (permalink / raw)
To: LKML; +Cc: Peter Zijlstra, Jiri Slaby
Use the new helpers to decide whether the interrupt should be handled and
switch the descriptor locking to guard().
Fixup the kernel doc comment while at it.
No functional change.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
kernel/irq/chip.c | 43 ++++++++++++++++---------------------------
1 file changed, 16 insertions(+), 27 deletions(-)
--- a/kernel/irq/chip.c
+++ b/kernel/irq/chip.c
@@ -561,43 +561,32 @@ void handle_simple_irq(struct irq_desc *
EXPORT_SYMBOL_GPL(handle_simple_irq);
/**
- * handle_untracked_irq - Simple and software-decoded IRQs.
- * @desc: the interrupt description structure for this irq
+ * handle_untracked_irq - Simple and software-decoded IRQs.
+ * @desc: the interrupt description structure for this irq
*
- * Untracked interrupts are sent from a demultiplexing interrupt
- * handler when the demultiplexer does not know which device it its
- * multiplexed irq domain generated the interrupt. IRQ's handled
- * through here are not subjected to stats tracking, randomness, or
- * spurious interrupt detection.
+ * Untracked interrupts are sent from a demultiplexing interrupt handler
+ * when the demultiplexer does not know which device it its multiplexed irq
+ * domain generated the interrupt. IRQ's handled through here are not
+ * subjected to stats tracking, randomness, or spurious interrupt
+ * detection.
*
- * Note: Like handle_simple_irq, the caller is expected to handle
- * the ack, clear, mask and unmask issues if necessary.
+ * Note: Like handle_simple_irq, the caller is expected to handle the ack,
+ * clear, mask and unmask issues if necessary.
*/
void handle_untracked_irq(struct irq_desc *desc)
{
- raw_spin_lock(&desc->lock);
+ scoped_guard (raw_spinlock, &desc->lock) {
+ if (!irq_can_handle(desc))
+ return;
- if (!irq_can_handle_pm(desc))
- goto out_unlock;
-
- desc->istate &= ~(IRQS_REPLAY | IRQS_WAITING);
-
- if (unlikely(!desc->action || irqd_irq_disabled(&desc->irq_data))) {
- desc->istate |= IRQS_PENDING;
- goto out_unlock;
+ desc->istate &= ~IRQS_PENDING;
+ irqd_set(&desc->irq_data, IRQD_IRQ_INPROGRESS);
}
- desc->istate &= ~IRQS_PENDING;
- irqd_set(&desc->irq_data, IRQD_IRQ_INPROGRESS);
- raw_spin_unlock(&desc->lock);
-
__handle_irq_event_percpu(desc);
- raw_spin_lock(&desc->lock);
- irqd_clear(&desc->irq_data, IRQD_IRQ_INPROGRESS);
-
-out_unlock:
- raw_spin_unlock(&desc->lock);
+ scoped_guard (raw_spinlock, &desc->lock)
+ irqd_clear(&desc->irq_data, IRQD_IRQ_INPROGRESS);
}
EXPORT_SYMBOL_GPL(handle_untracked_irq);
^ permalink raw reply [flat|nested] 50+ messages in thread
* [patch 15/46] genirq/chip: Rework handle_level_irq()
2025-03-13 15:59 [patch 00/46] genirq: Cleanups and conversion to lock guards Thomas Gleixner
` (13 preceding siblings ...)
2025-03-13 16:00 ` [patch 14/46] genirq/chip: Rework handle_untracked_irq() Thomas Gleixner
@ 2025-03-13 16:00 ` Thomas Gleixner
2025-03-13 16:00 ` [patch 16/46] genirq/chip: Rework handle_eoi_irq() Thomas Gleixner
` (31 subsequent siblings)
46 siblings, 0 replies; 50+ messages in thread
From: Thomas Gleixner @ 2025-03-13 16:00 UTC (permalink / raw)
To: LKML; +Cc: Peter Zijlstra, Jiri Slaby
Use the new helpers to decide whether the interrupt should be handled and
switch the descriptor locking to guard().
Fixup the kernel doc comment while at it.
No functional change.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
kernel/irq/chip.c | 32 +++++++++-----------------------
1 file changed, 9 insertions(+), 23 deletions(-)
--- a/kernel/irq/chip.c
+++ b/kernel/irq/chip.c
@@ -609,40 +609,26 @@ static void cond_unmask_irq(struct irq_d
}
/**
- * handle_level_irq - Level type irq handler
- * @desc: the interrupt description structure for this irq
+ * handle_level_irq - Level type irq handler
+ * @desc: the interrupt description structure for this irq
*
- * Level type interrupts are active as long as the hardware line has
- * the active level. This may require to mask the interrupt and unmask
- * it after the associated handler has acknowledged the device, so the
- * interrupt line is back to inactive.
+ * Level type interrupts are active as long as the hardware line has the
+ * active level. This may require to mask the interrupt and unmask it after
+ * the associated handler has acknowledged the device, so the interrupt
+ * line is back to inactive.
*/
void handle_level_irq(struct irq_desc *desc)
{
- raw_spin_lock(&desc->lock);
+ guard(raw_spinlock)(&desc->lock);
mask_ack_irq(desc);
- if (!irq_can_handle_pm(desc))
- goto out_unlock;
-
- desc->istate &= ~(IRQS_REPLAY | IRQS_WAITING);
-
- /*
- * If its disabled or no action available
- * keep it masked and get out of here
- */
- if (unlikely(!desc->action || irqd_irq_disabled(&desc->irq_data))) {
- desc->istate |= IRQS_PENDING;
- goto out_unlock;
- }
+ if (!irq_can_handle(desc))
+ return;
kstat_incr_irqs_this_cpu(desc);
handle_irq_event(desc);
cond_unmask_irq(desc);
-
-out_unlock:
- raw_spin_unlock(&desc->lock);
}
EXPORT_SYMBOL_GPL(handle_level_irq);
^ permalink raw reply [flat|nested] 50+ messages in thread
* [patch 16/46] genirq/chip: Rework handle_eoi_irq()
2025-03-13 15:59 [patch 00/46] genirq: Cleanups and conversion to lock guards Thomas Gleixner
` (14 preceding siblings ...)
2025-03-13 16:00 ` [patch 15/46] genirq/chip: Rework handle_level_irq() Thomas Gleixner
@ 2025-03-13 16:00 ` Thomas Gleixner
2025-03-13 16:00 ` [patch 17/46] genirq/chip: Rework handle_edge_irq() Thomas Gleixner
` (30 subsequent siblings)
46 siblings, 0 replies; 50+ messages in thread
From: Thomas Gleixner @ 2025-03-13 16:00 UTC (permalink / raw)
To: LKML; +Cc: Peter Zijlstra, Jiri Slaby
Use the new helpers to decide whether the interrupt should be handled and
switch the descriptor locking to guard().
Fixup the kernel doc comment while at it.
No functional change.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
kernel/irq/chip.c | 42 ++++++++++++++++++------------------------
1 file changed, 18 insertions(+), 24 deletions(-)
--- a/kernel/irq/chip.c
+++ b/kernel/irq/chip.c
@@ -653,20 +653,26 @@ static void cond_unmask_eoi_irq(struct i
}
}
+static inline void cond_eoi_irq(struct irq_chip *chip, struct irq_data *data)
+{
+ if (!(chip->flags & IRQCHIP_EOI_IF_HANDLED))
+ chip->irq_eoi(data);
+}
+
/**
- * handle_fasteoi_irq - irq handler for transparent controllers
- * @desc: the interrupt description structure for this irq
+ * handle_fasteoi_irq - irq handler for transparent controllers
+ * @desc: the interrupt description structure for this irq
*
- * Only a single callback will be issued to the chip: an ->eoi()
- * call when the interrupt has been serviced. This enables support
- * for modern forms of interrupt handlers, which handle the flow
- * details in hardware, transparently.
+ * Only a single callback will be issued to the chip: an ->eoi() call when
+ * the interrupt has been serviced. This enables support for modern forms
+ * of interrupt handlers, which handle the flow details in hardware,
+ * transparently.
*/
void handle_fasteoi_irq(struct irq_desc *desc)
{
struct irq_chip *chip = desc->irq_data.chip;
- raw_spin_lock(&desc->lock);
+ guard(raw_spinlock)(&desc->lock);
/*
* When an affinity change races with IRQ handling, the next interrupt
@@ -676,19 +682,14 @@ void handle_fasteoi_irq(struct irq_desc
if (!irq_can_handle_pm(desc)) {
if (irqd_needs_resend_when_in_progress(&desc->irq_data))
desc->istate |= IRQS_PENDING;
- goto out;
+ cond_eoi_irq(chip, &desc->irq_data);
+ return;
}
- desc->istate &= ~(IRQS_REPLAY | IRQS_WAITING);
-
- /*
- * If its disabled or no action available
- * then mask it and get out of here:
- */
- if (unlikely(!desc->action || irqd_irq_disabled(&desc->irq_data))) {
- desc->istate |= IRQS_PENDING;
+ if (!irq_can_handle_actions(desc)) {
mask_irq(desc);
- goto out;
+ cond_eoi_irq(chip, &desc->irq_data);
+ return;
}
kstat_incr_irqs_this_cpu(desc);
@@ -704,13 +705,6 @@ void handle_fasteoi_irq(struct irq_desc
*/
if (unlikely(desc->istate & IRQS_PENDING))
check_irq_resend(desc, false);
-
- raw_spin_unlock(&desc->lock);
- return;
-out:
- if (!(chip->flags & IRQCHIP_EOI_IF_HANDLED))
- chip->irq_eoi(&desc->irq_data);
- raw_spin_unlock(&desc->lock);
}
EXPORT_SYMBOL_GPL(handle_fasteoi_irq);
^ permalink raw reply [flat|nested] 50+ messages in thread
* [patch 17/46] genirq/chip: Rework handle_edge_irq()
2025-03-13 15:59 [patch 00/46] genirq: Cleanups and conversion to lock guards Thomas Gleixner
` (15 preceding siblings ...)
2025-03-13 16:00 ` [patch 16/46] genirq/chip: Rework handle_eoi_irq() Thomas Gleixner
@ 2025-03-13 16:00 ` Thomas Gleixner
2025-03-13 16:00 ` [patch 18/46] genirq/chip: Rework handle_edge_eoi_irq() Thomas Gleixner
` (29 subsequent siblings)
46 siblings, 0 replies; 50+ messages in thread
From: Thomas Gleixner @ 2025-03-13 16:00 UTC (permalink / raw)
To: LKML; +Cc: Peter Zijlstra, Jiri Slaby
Use the new helpers to decide whether the interrupt should be handled and
switch the descriptor locking to guard().
Fixup the kernel doc comment while at it.
No functional change.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
kernel/irq/chip.c | 49 ++++++++++++++++---------------------------------
1 file changed, 16 insertions(+), 33 deletions(-)
--- a/kernel/irq/chip.c
+++ b/kernel/irq/chip.c
@@ -742,40 +742,27 @@ void handle_fasteoi_nmi(struct irq_desc
EXPORT_SYMBOL_GPL(handle_fasteoi_nmi);
/**
- * handle_edge_irq - edge type IRQ handler
- * @desc: the interrupt description structure for this irq
+ * handle_edge_irq - edge type IRQ handler
+ * @desc: the interrupt description structure for this irq
*
- * Interrupt occurs on the falling and/or rising edge of a hardware
- * signal. The occurrence is latched into the irq controller hardware
- * and must be acked in order to be reenabled. After the ack another
- * interrupt can happen on the same source even before the first one
- * is handled by the associated event handler. If this happens it
- * might be necessary to disable (mask) the interrupt depending on the
- * controller hardware. This requires to reenable the interrupt inside
- * of the loop which handles the interrupts which have arrived while
- * the handler was running. If all pending interrupts are handled, the
- * loop is left.
+ * Interrupt occurs on the falling and/or rising edge of a hardware
+ * signal. The occurrence is latched into the irq controller hardware and
+ * must be acked in order to be reenabled. After the ack another interrupt
+ * can happen on the same source even before the first one is handled by
+ * the associated event handler. If this happens it might be necessary to
+ * disable (mask) the interrupt depending on the controller hardware. This
+ * requires to reenable the interrupt inside of the loop which handles the
+ * interrupts which have arrived while the handler was running. If all
+ * pending interrupts are handled, the loop is left.
*/
void handle_edge_irq(struct irq_desc *desc)
{
- raw_spin_lock(&desc->lock);
+ guard(raw_spinlock)(&desc->lock);
- desc->istate &= ~(IRQS_REPLAY | IRQS_WAITING);
-
- if (!irq_can_handle_pm(desc)) {
- desc->istate |= IRQS_PENDING;
- mask_ack_irq(desc);
- goto out_unlock;
- }
-
- /*
- * If its disabled or no action available then mask it and get
- * out of here.
- */
- if (irqd_irq_disabled(&desc->irq_data) || !desc->action) {
+ if (!irq_can_handle(desc)) {
desc->istate |= IRQS_PENDING;
mask_ack_irq(desc);
- goto out_unlock;
+ return;
}
kstat_incr_irqs_this_cpu(desc);
@@ -786,7 +773,7 @@ void handle_edge_irq(struct irq_desc *de
do {
if (unlikely(!desc->action)) {
mask_irq(desc);
- goto out_unlock;
+ return;
}
/*
@@ -802,11 +789,7 @@ void handle_edge_irq(struct irq_desc *de
handle_irq_event(desc);
- } while ((desc->istate & IRQS_PENDING) &&
- !irqd_irq_disabled(&desc->irq_data));
-
-out_unlock:
- raw_spin_unlock(&desc->lock);
+ } while ((desc->istate & IRQS_PENDING) && !irqd_irq_disabled(&desc->irq_data));
}
EXPORT_SYMBOL(handle_edge_irq);
^ permalink raw reply [flat|nested] 50+ messages in thread
* [patch 18/46] genirq/chip: Rework handle_edge_eoi_irq()
2025-03-13 15:59 [patch 00/46] genirq: Cleanups and conversion to lock guards Thomas Gleixner
` (16 preceding siblings ...)
2025-03-13 16:00 ` [patch 17/46] genirq/chip: Rework handle_edge_irq() Thomas Gleixner
@ 2025-03-13 16:00 ` Thomas Gleixner
2025-03-13 16:00 ` [patch 19/46] genirq/chip: Rework handle_fasteoi_ack_irq() Thomas Gleixner
` (28 subsequent siblings)
46 siblings, 0 replies; 50+ messages in thread
From: Thomas Gleixner @ 2025-03-13 16:00 UTC (permalink / raw)
To: LKML; +Cc: Peter Zijlstra, Jiri Slaby
Use the new helpers to decide whether the interrupt should be handled and
switch the descriptor locking to guard().
Fixup the kernel doc comment while at it.
No functional change.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
kernel/irq/chip.c | 31 ++++++++-----------------------
1 file changed, 8 insertions(+), 23 deletions(-)
--- a/kernel/irq/chip.c
+++ b/kernel/irq/chip.c
@@ -795,8 +795,8 @@ EXPORT_SYMBOL(handle_edge_irq);
#ifdef CONFIG_IRQ_EDGE_EOI_HANDLER
/**
- * handle_edge_eoi_irq - edge eoi type IRQ handler
- * @desc: the interrupt description structure for this irq
+ * handle_edge_eoi_irq - edge eoi type IRQ handler
+ * @desc: the interrupt description structure for this irq
*
* Similar as the above handle_edge_irq, but using eoi and w/o the
* mask/unmask logic.
@@ -805,38 +805,23 @@ void handle_edge_eoi_irq(struct irq_desc
{
struct irq_chip *chip = irq_desc_get_chip(desc);
- raw_spin_lock(&desc->lock);
+ guard(raw_spinlock)(&desc->lock);
- desc->istate &= ~(IRQS_REPLAY | IRQS_WAITING);
-
- if (!irq_can_handle_pm(desc)) {
- desc->istate |= IRQS_PENDING;
- goto out_eoi;
- }
-
- /*
- * If its disabled or no action available then mask it and get
- * out of here.
- */
- if (irqd_irq_disabled(&desc->irq_data) || !desc->action) {
+ if (!irq_can_handle(desc)) {
desc->istate |= IRQS_PENDING;
- goto out_eoi;
+ chip->irq_eoi(&desc->irq_data);
+ return;
}
kstat_incr_irqs_this_cpu(desc);
do {
if (unlikely(!desc->action))
- goto out_eoi;
-
+ break;
handle_irq_event(desc);
+ } while ((desc->istate & IRQS_PENDING) && !irqd_irq_disabled(&desc->irq_data));
- } while ((desc->istate & IRQS_PENDING) &&
- !irqd_irq_disabled(&desc->irq_data));
-
-out_eoi:
chip->irq_eoi(&desc->irq_data);
- raw_spin_unlock(&desc->lock);
}
#endif
^ permalink raw reply [flat|nested] 50+ messages in thread
* [patch 19/46] genirq/chip: Rework handle_fasteoi_ack_irq()
2025-03-13 15:59 [patch 00/46] genirq: Cleanups and conversion to lock guards Thomas Gleixner
` (17 preceding siblings ...)
2025-03-13 16:00 ` [patch 18/46] genirq/chip: Rework handle_edge_eoi_irq() Thomas Gleixner
@ 2025-03-13 16:00 ` Thomas Gleixner
2025-03-13 16:00 ` [patch 20/46] genirq/chip: Rework handle_fasteoi_mask_irq() Thomas Gleixner
` (27 subsequent siblings)
46 siblings, 0 replies; 50+ messages in thread
From: Thomas Gleixner @ 2025-03-13 16:00 UTC (permalink / raw)
To: LKML; +Cc: Peter Zijlstra, Jiri Slaby
Use the new helpers to decide whether the interrupt should be handled and
switch the descriptor locking to guard().
Fixup the kernel doc comment while at it.
No functional change.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
kernel/irq/chip.c | 39 +++++++++++++--------------------------
1 file changed, 13 insertions(+), 26 deletions(-)
--- a/kernel/irq/chip.c
+++ b/kernel/irq/chip.c
@@ -1138,53 +1138,40 @@ void irq_cpu_offline(void)
#ifdef CONFIG_IRQ_FASTEOI_HIERARCHY_HANDLERS
/**
- * handle_fasteoi_ack_irq - irq handler for edge hierarchy
- * stacked on transparent controllers
+ * handle_fasteoi_ack_irq - irq handler for edge hierarchy stacked on
+ * transparent controllers
*
- * @desc: the interrupt description structure for this irq
+ * @desc: the interrupt description structure for this irq
*
- * Like handle_fasteoi_irq(), but for use with hierarchy where
- * the irq_chip also needs to have its ->irq_ack() function
- * called.
+ * Like handle_fasteoi_irq(), but for use with hierarchy where the irq_chip
+ * also needs to have its ->irq_ack() function called.
*/
void handle_fasteoi_ack_irq(struct irq_desc *desc)
{
struct irq_chip *chip = desc->irq_data.chip;
- raw_spin_lock(&desc->lock);
+ guard(raw_spinlock)(&desc->lock);
- if (!irq_can_handle_pm(desc))
- goto out;
-
- desc->istate &= ~(IRQS_REPLAY | IRQS_WAITING);
+ if (!irq_can_handle_pm(desc)) {
+ cond_eoi_irq(chip, &desc->irq_data);
+ return;
+ }
- /*
- * If its disabled or no action available
- * then mask it and get out of here:
- */
- if (unlikely(!desc->action || irqd_irq_disabled(&desc->irq_data))) {
- desc->istate |= IRQS_PENDING;
+ if (unlikely(!irq_can_handle_actions(desc))) {
mask_irq(desc);
- goto out;
+ cond_eoi_irq(chip, &desc->irq_data);
+ return;
}
kstat_incr_irqs_this_cpu(desc);
if (desc->istate & IRQS_ONESHOT)
mask_irq(desc);
- /* Start handling the irq */
desc->irq_data.chip->irq_ack(&desc->irq_data);
handle_irq_event(desc);
cond_unmask_eoi_irq(desc, chip);
-
- raw_spin_unlock(&desc->lock);
- return;
-out:
- if (!(chip->flags & IRQCHIP_EOI_IF_HANDLED))
- chip->irq_eoi(&desc->irq_data);
- raw_spin_unlock(&desc->lock);
}
EXPORT_SYMBOL_GPL(handle_fasteoi_ack_irq);
^ permalink raw reply [flat|nested] 50+ messages in thread
* [patch 20/46] genirq/chip: Rework handle_fasteoi_mask_irq()
2025-03-13 15:59 [patch 00/46] genirq: Cleanups and conversion to lock guards Thomas Gleixner
` (18 preceding siblings ...)
2025-03-13 16:00 ` [patch 19/46] genirq/chip: Rework handle_fasteoi_ack_irq() Thomas Gleixner
@ 2025-03-13 16:00 ` Thomas Gleixner
2025-03-13 16:00 ` [patch 21/46] genirq/chip: Use lock guards where applicable Thomas Gleixner
` (26 subsequent siblings)
46 siblings, 0 replies; 50+ messages in thread
From: Thomas Gleixner @ 2025-03-13 16:00 UTC (permalink / raw)
To: LKML; +Cc: Peter Zijlstra, Jiri Slaby
Use the new helpers to decide whether the interrupt should be handled and
switch the descriptor locking to guard().
Note: The mask_irq() operation in the second condition was redundant as the
interrupt is already masked right at the beginning of the function.
Fixup the kernel doc comment while at it.
No functional change.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
kernel/irq/chip.c | 38 +++++++++-----------------------------
1 file changed, 9 insertions(+), 29 deletions(-)
--- a/kernel/irq/chip.c
+++ b/kernel/irq/chip.c
@@ -1176,51 +1176,31 @@ void handle_fasteoi_ack_irq(struct irq_d
EXPORT_SYMBOL_GPL(handle_fasteoi_ack_irq);
/**
- * handle_fasteoi_mask_irq - irq handler for level hierarchy
- * stacked on transparent controllers
+ * handle_fasteoi_mask_irq - irq handler for level hierarchy stacked on
+ * transparent controllers
*
- * @desc: the interrupt description structure for this irq
+ * @desc: the interrupt description structure for this irq
*
- * Like handle_fasteoi_irq(), but for use with hierarchy where
- * the irq_chip also needs to have its ->irq_mask_ack() function
- * called.
+ * Like handle_fasteoi_irq(), but for use with hierarchy where the irq_chip
+ * also needs to have its ->irq_mask_ack() function called.
*/
void handle_fasteoi_mask_irq(struct irq_desc *desc)
{
struct irq_chip *chip = desc->irq_data.chip;
- raw_spin_lock(&desc->lock);
+ guard(raw_spinlock)(&desc->lock);
mask_ack_irq(desc);
- if (!irq_can_handle_pm(desc))
- goto out;
-
- desc->istate &= ~(IRQS_REPLAY | IRQS_WAITING);
-
- /*
- * If its disabled or no action available
- * then mask it and get out of here:
- */
- if (unlikely(!desc->action || irqd_irq_disabled(&desc->irq_data))) {
- desc->istate |= IRQS_PENDING;
- mask_irq(desc);
- goto out;
+ if (!irq_can_handle(desc)) {
+ cond_eoi_irq(chip, &desc->irq_data);
+ return;
}
kstat_incr_irqs_this_cpu(desc);
- if (desc->istate & IRQS_ONESHOT)
- mask_irq(desc);
handle_irq_event(desc);
cond_unmask_eoi_irq(desc, chip);
-
- raw_spin_unlock(&desc->lock);
- return;
-out:
- if (!(chip->flags & IRQCHIP_EOI_IF_HANDLED))
- chip->irq_eoi(&desc->irq_data);
- raw_spin_unlock(&desc->lock);
}
EXPORT_SYMBOL_GPL(handle_fasteoi_mask_irq);
^ permalink raw reply [flat|nested] 50+ messages in thread
* [patch 21/46] genirq/chip: Use lock guards where applicable
2025-03-13 15:59 [patch 00/46] genirq: Cleanups and conversion to lock guards Thomas Gleixner
` (19 preceding siblings ...)
2025-03-13 16:00 ` [patch 20/46] genirq/chip: Rework handle_fasteoi_mask_irq() Thomas Gleixner
@ 2025-03-13 16:00 ` Thomas Gleixner
2025-03-13 16:00 ` [patch 22/46] genirq/chip: Rework irq_set_chip() Thomas Gleixner
` (25 subsequent siblings)
46 siblings, 0 replies; 50+ messages in thread
From: Thomas Gleixner @ 2025-03-13 16:00 UTC (permalink / raw)
To: LKML; +Cc: Peter Zijlstra, Jiri Slaby
Convert all lock/unlock pairs to guards and tidy up the code.
No functional change.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
kernel/irq/chip.c | 24 ++++++++----------------
1 file changed, 8 insertions(+), 16 deletions(-)
--- a/kernel/irq/chip.c
+++ b/kernel/irq/chip.c
@@ -1081,25 +1081,21 @@ EXPORT_SYMBOL_GPL(irq_modify_status);
*/
void irq_cpu_online(void)
{
- struct irq_desc *desc;
- struct irq_chip *chip;
- unsigned long flags;
unsigned int irq;
for_each_active_irq(irq) {
- desc = irq_to_desc(irq);
+ struct irq_desc *desc = irq_to_desc(irq);
+ struct irq_chip *chip;
+
if (!desc)
continue;
- raw_spin_lock_irqsave(&desc->lock, flags);
-
+ guard(raw_spinlock_irqsave)(&desc->lock);
chip = irq_data_get_irq_chip(&desc->irq_data);
if (chip && chip->irq_cpu_online &&
(!(chip->flags & IRQCHIP_ONOFFLINE_ENABLED) ||
!irqd_irq_disabled(&desc->irq_data)))
chip->irq_cpu_online(&desc->irq_data);
-
- raw_spin_unlock_irqrestore(&desc->lock, flags);
}
}
@@ -1111,25 +1107,21 @@ void irq_cpu_online(void)
*/
void irq_cpu_offline(void)
{
- struct irq_desc *desc;
- struct irq_chip *chip;
- unsigned long flags;
unsigned int irq;
for_each_active_irq(irq) {
- desc = irq_to_desc(irq);
+ struct irq_desc *desc = irq_to_desc(irq);
+ struct irq_chip *chip;
+
if (!desc)
continue;
- raw_spin_lock_irqsave(&desc->lock, flags);
-
+ guard(raw_spinlock_irqsave)(&desc->lock);
chip = irq_data_get_irq_chip(&desc->irq_data);
if (chip && chip->irq_cpu_offline &&
(!(chip->flags & IRQCHIP_ONOFFLINE_ENABLED) ||
!irqd_irq_disabled(&desc->irq_data)))
chip->irq_cpu_offline(&desc->irq_data);
-
- raw_spin_unlock_irqrestore(&desc->lock, flags);
}
}
#endif
^ permalink raw reply [flat|nested] 50+ messages in thread
* [patch 22/46] genirq/chip: Rework irq_set_chip()
2025-03-13 15:59 [patch 00/46] genirq: Cleanups and conversion to lock guards Thomas Gleixner
` (20 preceding siblings ...)
2025-03-13 16:00 ` [patch 21/46] genirq/chip: Use lock guards where applicable Thomas Gleixner
@ 2025-03-13 16:00 ` Thomas Gleixner
2025-03-13 16:00 ` [patch 23/46] genirq/chip: Rework irq_set_irq_type() Thomas Gleixner
` (24 subsequent siblings)
46 siblings, 0 replies; 50+ messages in thread
From: Thomas Gleixner @ 2025-03-13 16:00 UTC (permalink / raw)
To: LKML; +Cc: Peter Zijlstra, Jiri Slaby
Use the new guards to get and lock the interrupt descriptor and tidy up the
code.
Fixup the kernel doc comment while at it.
No functional change.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
kernel/irq/chip.c | 28 ++++++++++++----------------
1 file changed, 12 insertions(+), 16 deletions(-)
--- a/kernel/irq/chip.c
+++ b/kernel/irq/chip.c
@@ -34,26 +34,22 @@ struct irqaction chained_action = {
};
/**
- * irq_set_chip - set the irq chip for an irq
- * @irq: irq number
- * @chip: pointer to irq chip description structure
+ * irq_set_chip - set the irq chip for an irq
+ * @irq: irq number
+ * @chip: pointer to irq chip description structure
*/
int irq_set_chip(unsigned int irq, const struct irq_chip *chip)
{
- unsigned long flags;
- struct irq_desc *desc = irq_get_desc_lock(irq, &flags, 0);
+ int ret = -EINVAL;
- if (!desc)
- return -EINVAL;
-
- desc->irq_data.chip = (struct irq_chip *)(chip ?: &no_irq_chip);
- irq_put_desc_unlock(desc, flags);
- /*
- * For !CONFIG_SPARSE_IRQ make the irq show up in
- * allocated_irqs.
- */
- irq_mark_irq(irq);
- return 0;
+ scoped_irqdesc_get_and_lock(irq, 0) {
+ scoped_irqdesc->irq_data.chip = (struct irq_chip *)(chip ?: &no_irq_chip);
+ ret = 0;
+ }
+ /* For !CONFIG_SPARSE_IRQ make the irq show up in allocated_irqs. */
+ if (!ret)
+ irq_mark_irq(irq);
+ return ret;
}
EXPORT_SYMBOL(irq_set_chip);
^ permalink raw reply [flat|nested] 50+ messages in thread
* [patch 23/46] genirq/chip: Rework irq_set_irq_type()
2025-03-13 15:59 [patch 00/46] genirq: Cleanups and conversion to lock guards Thomas Gleixner
` (21 preceding siblings ...)
2025-03-13 16:00 ` [patch 22/46] genirq/chip: Rework irq_set_chip() Thomas Gleixner
@ 2025-03-13 16:00 ` Thomas Gleixner
2025-03-13 16:00 ` [patch 24/46] genirq/chip: Rework irq_set_handler_data() Thomas Gleixner
` (23 subsequent siblings)
46 siblings, 0 replies; 50+ messages in thread
From: Thomas Gleixner @ 2025-03-13 16:00 UTC (permalink / raw)
To: LKML; +Cc: Peter Zijlstra, Jiri Slaby
Use the new guards to get and lock the interrupt descriptor and tidy up the
code.
Fixup the kernel doc comment while at it.
No functional change.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
kernel/irq/chip.c | 19 ++++++-------------
1 file changed, 6 insertions(+), 13 deletions(-)
--- a/kernel/irq/chip.c
+++ b/kernel/irq/chip.c
@@ -54,22 +54,15 @@ int irq_set_chip(unsigned int irq, const
EXPORT_SYMBOL(irq_set_chip);
/**
- * irq_set_irq_type - set the irq trigger type for an irq
- * @irq: irq number
- * @type: IRQ_TYPE_{LEVEL,EDGE}_* value - see include/linux/irq.h
+ * irq_set_irq_type - set the irq trigger type for an irq
+ * @irq: irq number
+ * @type: IRQ_TYPE_{LEVEL,EDGE}_* value - see include/linux/irq.h
*/
int irq_set_irq_type(unsigned int irq, unsigned int type)
{
- unsigned long flags;
- struct irq_desc *desc = irq_get_desc_buslock(irq, &flags, IRQ_GET_DESC_CHECK_GLOBAL);
- int ret = 0;
-
- if (!desc)
- return -EINVAL;
-
- ret = __irq_set_trigger(desc, type);
- irq_put_desc_busunlock(desc, flags);
- return ret;
+ scoped_irqdesc_get_and_buslock(irq, IRQ_GET_DESC_CHECK_GLOBAL)
+ return __irq_set_trigger(scoped_irqdesc, type);
+ return -EINVAL;
}
EXPORT_SYMBOL(irq_set_irq_type);
^ permalink raw reply [flat|nested] 50+ messages in thread
* [patch 24/46] genirq/chip: Rework irq_set_handler_data()
2025-03-13 15:59 [patch 00/46] genirq: Cleanups and conversion to lock guards Thomas Gleixner
` (22 preceding siblings ...)
2025-03-13 16:00 ` [patch 23/46] genirq/chip: Rework irq_set_irq_type() Thomas Gleixner
@ 2025-03-13 16:00 ` Thomas Gleixner
2025-03-13 16:00 ` [patch 25/46] genirq/chip: Rework irq_set_msi_desc_off() Thomas Gleixner
` (22 subsequent siblings)
46 siblings, 0 replies; 50+ messages in thread
From: Thomas Gleixner @ 2025-03-13 16:00 UTC (permalink / raw)
To: LKML; +Cc: Peter Zijlstra, Jiri Slaby
Use the new guards to get and lock the interrupt descriptor and tidy up the
code.
Fixup the kernel doc comment while at it.
No functional change.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
kernel/irq/chip.c | 21 +++++++++------------
1 file changed, 9 insertions(+), 12 deletions(-)
--- a/kernel/irq/chip.c
+++ b/kernel/irq/chip.c
@@ -67,22 +67,19 @@ int irq_set_irq_type(unsigned int irq, u
EXPORT_SYMBOL(irq_set_irq_type);
/**
- * irq_set_handler_data - set irq handler data for an irq
- * @irq: Interrupt number
- * @data: Pointer to interrupt specific data
+ * 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
+ * Set the hardware irq controller data for an irq
*/
int irq_set_handler_data(unsigned int irq, void *data)
{
- unsigned long flags;
- struct irq_desc *desc = irq_get_desc_lock(irq, &flags, 0);
-
- if (!desc)
- return -EINVAL;
- desc->irq_common_data.handler_data = data;
- irq_put_desc_unlock(desc, flags);
- return 0;
+ scoped_irqdesc_get_and_lock(irq, 0) {
+ scoped_irqdesc->irq_common_data.handler_data = data;
+ return 0;
+ }
+ return -EINVAL;
}
EXPORT_SYMBOL(irq_set_handler_data);
^ permalink raw reply [flat|nested] 50+ messages in thread
* [patch 25/46] genirq/chip: Rework irq_set_msi_desc_off()
2025-03-13 15:59 [patch 00/46] genirq: Cleanups and conversion to lock guards Thomas Gleixner
` (23 preceding siblings ...)
2025-03-13 16:00 ` [patch 24/46] genirq/chip: Rework irq_set_handler_data() Thomas Gleixner
@ 2025-03-13 16:00 ` Thomas Gleixner
2025-03-13 16:00 ` [patch 26/46] genirq/chip: Rework irq_set_chip_data() Thomas Gleixner
` (21 subsequent siblings)
46 siblings, 0 replies; 50+ messages in thread
From: Thomas Gleixner @ 2025-03-13 16:00 UTC (permalink / raw)
To: LKML; +Cc: Peter Zijlstra, Jiri Slaby
Use the new guards to get and lock the interrupt descriptor and tidy up the
code.
Fixup the kernel doc comment while at it.
No functional change.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
kernel/irq/chip.c | 38 +++++++++++++++++---------------------
1 file changed, 17 insertions(+), 21 deletions(-)
--- a/kernel/irq/chip.c
+++ b/kernel/irq/chip.c
@@ -84,34 +84,30 @@ int irq_set_handler_data(unsigned int ir
EXPORT_SYMBOL(irq_set_handler_data);
/**
- * irq_set_msi_desc_off - set MSI descriptor data for an irq at offset
- * @irq_base: Interrupt number base
- * @irq_offset: Interrupt number offset
- * @entry: Pointer to MSI descriptor data
+ * irq_set_msi_desc_off - set MSI descriptor data for an irq at offset
+ * @irq_base: Interrupt number base
+ * @irq_offset: Interrupt number offset
+ * @entry: Pointer to MSI descriptor data
*
- * Set the MSI descriptor entry for an irq at offset
+ * Set the MSI descriptor entry for an irq at offset
*/
-int irq_set_msi_desc_off(unsigned int irq_base, unsigned int irq_offset,
- struct msi_desc *entry)
+int irq_set_msi_desc_off(unsigned int irq_base, unsigned int irq_offset, struct msi_desc *entry)
{
- unsigned long flags;
- struct irq_desc *desc = irq_get_desc_lock(irq_base + irq_offset, &flags, IRQ_GET_DESC_CHECK_GLOBAL);
-
- if (!desc)
- return -EINVAL;
- desc->irq_common_data.msi_desc = entry;
- if (entry && !irq_offset)
- entry->irq = irq_base;
- irq_put_desc_unlock(desc, flags);
- return 0;
+ scoped_irqdesc_get_and_lock(irq_base + irq_offset, IRQ_GET_DESC_CHECK_GLOBAL) {
+ scoped_irqdesc->irq_common_data.msi_desc = entry;
+ if (entry && !irq_offset)
+ entry->irq = irq_base;
+ return 0;
+ }
+ return -EINVAL;
}
/**
- * irq_set_msi_desc - set MSI descriptor data for an irq
- * @irq: Interrupt number
- * @entry: Pointer to MSI descriptor data
+ * 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
+ * Set the MSI descriptor entry for an irq
*/
int irq_set_msi_desc(unsigned int irq, struct msi_desc *entry)
{
^ permalink raw reply [flat|nested] 50+ messages in thread
* [patch 26/46] genirq/chip: Rework irq_set_chip_data()
2025-03-13 15:59 [patch 00/46] genirq: Cleanups and conversion to lock guards Thomas Gleixner
` (24 preceding siblings ...)
2025-03-13 16:00 ` [patch 25/46] genirq/chip: Rework irq_set_msi_desc_off() Thomas Gleixner
@ 2025-03-13 16:00 ` Thomas Gleixner
2025-03-13 16:00 ` [patch 27/46] genirq/chip: Rework irq_set_handler() variants Thomas Gleixner
` (20 subsequent siblings)
46 siblings, 0 replies; 50+ messages in thread
From: Thomas Gleixner @ 2025-03-13 16:00 UTC (permalink / raw)
To: LKML; +Cc: Peter Zijlstra, Jiri Slaby
Use the new guards to get and lock the interrupt descriptor and tidy up the
code.
Fixup the kernel doc comment while at it.
No functional change.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
kernel/irq/chip.c | 21 +++++++++------------
1 file changed, 9 insertions(+), 12 deletions(-)
--- a/kernel/irq/chip.c
+++ b/kernel/irq/chip.c
@@ -115,22 +115,19 @@ int irq_set_msi_desc(unsigned int irq, s
}
/**
- * irq_set_chip_data - set irq chip data for an irq
- * @irq: Interrupt number
- * @data: Pointer to chip specific data
+ * 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
+ * Set the hardware irq chip data for an irq
*/
int irq_set_chip_data(unsigned int irq, void *data)
{
- unsigned long flags;
- struct irq_desc *desc = irq_get_desc_lock(irq, &flags, 0);
-
- if (!desc)
- return -EINVAL;
- desc->irq_data.chip_data = data;
- irq_put_desc_unlock(desc, flags);
- return 0;
+ scoped_irqdesc_get_and_lock(irq, 0) {
+ scoped_irqdesc->irq_data.chip_data = data;
+ return 0;
+ }
+ return -EINVAL;
}
EXPORT_SYMBOL(irq_set_chip_data);
^ permalink raw reply [flat|nested] 50+ messages in thread
* [patch 27/46] genirq/chip: Rework irq_set_handler() variants
2025-03-13 15:59 [patch 00/46] genirq: Cleanups and conversion to lock guards Thomas Gleixner
` (25 preceding siblings ...)
2025-03-13 16:00 ` [patch 26/46] genirq/chip: Rework irq_set_chip_data() Thomas Gleixner
@ 2025-03-13 16:00 ` Thomas Gleixner
2025-03-13 16:00 ` [patch 28/46] genirq/chip: Rework irq_modify_status() Thomas Gleixner
` (19 subsequent siblings)
46 siblings, 0 replies; 50+ messages in thread
From: Thomas Gleixner @ 2025-03-13 16:00 UTC (permalink / raw)
To: LKML; +Cc: Peter Zijlstra, Jiri Slaby
Use the new guards to get and lock the interrupt descriptor and tidy up the
code.
Fixup the kernel doc comment while at it.
No functional change.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
kernel/irq/chip.c | 34 +++++++++++-----------------------
1 file changed, 11 insertions(+), 23 deletions(-)
--- a/kernel/irq/chip.c
+++ b/kernel/irq/chip.c
@@ -973,35 +973,23 @@ static void
}
}
-void
-__irq_set_handler(unsigned int irq, irq_flow_handler_t handle, int is_chained,
- const char *name)
+void __irq_set_handler(unsigned int irq, irq_flow_handler_t handle, int is_chained,
+ const char *name)
{
- unsigned long flags;
- struct irq_desc *desc = irq_get_desc_buslock(irq, &flags, 0);
-
- if (!desc)
- return;
-
- __irq_do_set_handler(desc, handle, is_chained, name);
- irq_put_desc_busunlock(desc, flags);
+ scoped_irqdesc_get_and_lock(irq, 0)
+ __irq_do_set_handler(scoped_irqdesc, handle, is_chained, name);
}
EXPORT_SYMBOL_GPL(__irq_set_handler);
-void
-irq_set_chained_handler_and_data(unsigned int irq, irq_flow_handler_t handle,
- void *data)
+void irq_set_chained_handler_and_data(unsigned int irq, irq_flow_handler_t handle,
+ void *data)
{
- unsigned long flags;
- struct irq_desc *desc = irq_get_desc_buslock(irq, &flags, 0);
-
- if (!desc)
- return;
+ scoped_irqdesc_get_and_buslock(irq, 0) {
+ struct irq_desc *desc = scoped_irqdesc;
- desc->irq_common_data.handler_data = data;
- __irq_do_set_handler(desc, handle, 1, NULL);
-
- irq_put_desc_busunlock(desc, flags);
+ desc->irq_common_data.handler_data = data;
+ __irq_do_set_handler(desc, handle, 1, NULL);
+ }
}
EXPORT_SYMBOL_GPL(irq_set_chained_handler_and_data);
^ permalink raw reply [flat|nested] 50+ messages in thread
* [patch 28/46] genirq/chip: Rework irq_modify_status()
2025-03-13 15:59 [patch 00/46] genirq: Cleanups and conversion to lock guards Thomas Gleixner
` (26 preceding siblings ...)
2025-03-13 16:00 ` [patch 27/46] genirq/chip: Rework irq_set_handler() variants Thomas Gleixner
@ 2025-03-13 16:00 ` Thomas Gleixner
2025-03-13 16:00 ` [patch 29/46] genirq/manage: Cleanup kernel doc comments Thomas Gleixner
` (18 subsequent siblings)
46 siblings, 0 replies; 50+ messages in thread
From: Thomas Gleixner @ 2025-03-13 16:00 UTC (permalink / raw)
To: LKML; +Cc: Peter Zijlstra, Jiri Slaby
Use the new guards to get and lock the interrupt descriptor and tidy up the
code.
Fixup the kernel doc comment while at it.
No functional change.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
kernel/irq/chip.c | 58 +++++++++++++++++++++++++-----------------------------
1 file changed, 27 insertions(+), 31 deletions(-)
--- a/kernel/irq/chip.c
+++ b/kernel/irq/chip.c
@@ -1004,38 +1004,34 @@ EXPORT_SYMBOL_GPL(irq_set_chip_and_handl
void irq_modify_status(unsigned int irq, unsigned long clr, unsigned long set)
{
- unsigned long flags, trigger, tmp;
- struct irq_desc *desc = irq_get_desc_lock(irq, &flags, 0);
+ scoped_irqdesc_get_and_lock(irq, 0) {
+ struct irq_desc *desc = scoped_irqdesc;
+ unsigned long trigger, tmp;
+ /*
+ * Warn when a driver sets the no autoenable flag on an already
+ * active interrupt.
+ */
+ WARN_ON_ONCE(!desc->depth && (set & _IRQ_NOAUTOEN));
+
+ irq_settings_clr_and_set(desc, clr, set);
+
+ trigger = irqd_get_trigger_type(&desc->irq_data);
+
+ 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);
+ if (irq_settings_is_level(desc))
+ irqd_set(&desc->irq_data, IRQD_LEVEL);
+
+ tmp = irq_settings_get_trigger_mask(desc);
+ if (tmp != IRQ_TYPE_NONE)
+ trigger = tmp;
- if (!desc)
- return;
-
- /*
- * Warn when a driver sets the no autoenable flag on an already
- * active interrupt.
- */
- WARN_ON_ONCE(!desc->depth && (set & _IRQ_NOAUTOEN));
-
- irq_settings_clr_and_set(desc, clr, set);
-
- trigger = irqd_get_trigger_type(&desc->irq_data);
-
- 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);
- if (irq_settings_is_level(desc))
- irqd_set(&desc->irq_data, IRQD_LEVEL);
-
- tmp = irq_settings_get_trigger_mask(desc);
- if (tmp != IRQ_TYPE_NONE)
- trigger = tmp;
-
- irqd_set(&desc->irq_data, trigger);
-
- irq_put_desc_unlock(desc, flags);
+ irqd_set(&desc->irq_data, trigger);
+ }
}
EXPORT_SYMBOL_GPL(irq_modify_status);
^ permalink raw reply [flat|nested] 50+ messages in thread
* [patch 29/46] genirq/manage: Cleanup kernel doc comments
2025-03-13 15:59 [patch 00/46] genirq: Cleanups and conversion to lock guards Thomas Gleixner
` (27 preceding siblings ...)
2025-03-13 16:00 ` [patch 28/46] genirq/chip: Rework irq_modify_status() Thomas Gleixner
@ 2025-03-13 16:00 ` Thomas Gleixner
2025-03-13 16:00 ` [patch 30/46] genirq/manage: Convert to lock guards Thomas Gleixner
` (17 subsequent siblings)
46 siblings, 0 replies; 50+ messages in thread
From: Thomas Gleixner @ 2025-03-13 16:00 UTC (permalink / raw)
To: LKML; +Cc: Peter Zijlstra, Jiri Slaby
Get rid of the extra tab to make it consistent.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
kernel/irq/manage.c | 570 +++++++++++++++++++++++++---------------------------
1 file changed, 276 insertions(+), 294 deletions(-)
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -74,26 +74,25 @@ static void __synchronize_hardirq(struct
}
/**
- * synchronize_hardirq - wait for pending hard IRQ handlers (on other CPUs)
- * @irq: interrupt number to wait for
+ * synchronize_hardirq - wait for pending hard IRQ handlers (on other CPUs)
+ * @irq: interrupt number to wait for
*
- * This function waits for any pending hard IRQ handlers for this
- * interrupt to complete before returning. If you use this
- * function while holding a resource the IRQ handler may need you
- * will deadlock. It does not take associated threaded handlers
- * into account.
- *
- * Do not use this for shutdown scenarios where you must be sure
- * that all parts (hardirq and threaded handler) have completed.
- *
- * Returns: false if a threaded handler is active.
- *
- * This function may be called - with care - from IRQ context.
- *
- * It does not check whether there is an interrupt in flight at the
- * hardware level, but not serviced yet, as this might deadlock when
- * called with interrupts disabled and the target CPU of the interrupt
- * is the current CPU.
+ * This function waits for any pending hard IRQ handlers for this interrupt
+ * to complete before returning. If you use this function while holding a
+ * resource the IRQ handler may need you will deadlock. It does not take
+ * associated threaded handlers into account.
+ *
+ * Do not use this for shutdown scenarios where you must be sure that all
+ * parts (hardirq and threaded handler) have completed.
+ *
+ * Returns: false if a threaded handler is active.
+ *
+ * This function may be called - with care - from IRQ context.
+ *
+ * It does not check whether there is an interrupt in flight at the
+ * hardware level, but not serviced yet, as this might deadlock when called
+ * with interrupts disabled and the target CPU of the interrupt is the
+ * current CPU.
*/
bool synchronize_hardirq(unsigned int irq)
{
@@ -119,19 +118,19 @@ static void __synchronize_irq(struct irq
}
/**
- * synchronize_irq - wait for pending IRQ handlers (on other CPUs)
- * @irq: interrupt number to wait for
+ * synchronize_irq - wait for pending IRQ handlers (on other CPUs)
+ * @irq: interrupt number to wait for
*
- * This function waits for any pending IRQ handlers for this interrupt
- * to complete before returning. If you use this function while
- * holding a resource the IRQ handler may need you will deadlock.
- *
- * Can only be called from preemptible code as it might sleep when
- * an interrupt thread is associated to @irq.
- *
- * It optionally makes sure (when the irq chip supports that method)
- * that the interrupt is not pending in any CPU and waiting for
- * service.
+ * This function waits for any pending IRQ handlers for this interrupt to
+ * complete before returning. If you use this function while holding a
+ * resource the IRQ handler may need you will deadlock.
+ *
+ * Can only be called from preemptible code as it might sleep when
+ * an interrupt thread is associated to @irq.
+ *
+ * It optionally makes sure (when the irq chip supports that method)
+ * that the interrupt is not pending in any CPU and waiting for
+ * service.
*/
void synchronize_irq(unsigned int irq)
{
@@ -154,8 +153,8 @@ static bool __irq_can_set_affinity(struc
}
/**
- * irq_can_set_affinity - Check if the affinity of a given irq can be set
- * @irq: Interrupt to check
+ * irq_can_set_affinity - Check if the affinity of a given irq can be set
+ * @irq: Interrupt to check
*
*/
int irq_can_set_affinity(unsigned int irq)
@@ -179,13 +178,13 @@ bool irq_can_set_affinity_usr(unsigned i
}
/**
- * irq_set_thread_affinity - Notify irq threads to adjust affinity
- * @desc: irq descriptor which has affinity changed
+ * irq_set_thread_affinity - Notify irq threads to adjust affinity
+ * @desc: irq descriptor which has affinity changed
*
- * We just set IRQTF_AFFINITY and delegate the affinity setting
- * to the interrupt thread itself. We can not call
- * set_cpus_allowed_ptr() here as we hold desc->lock and this
- * code can be called from hard interrupt context.
+ * Just set IRQTF_AFFINITY and delegate the affinity setting to the
+ * interrupt thread itself. We can not call set_cpus_allowed_ptr() here as
+ * we hold desc->lock and this code can be called from hard interrupt
+ * context.
*/
void irq_set_thread_affinity(struct irq_desc *desc)
{
@@ -541,18 +540,17 @@ static void irq_affinity_notify(struct w
}
/**
- * irq_set_affinity_notifier - control notification of IRQ affinity changes
- * @irq: Interrupt for which to enable/disable notification
- * @notify: Context for notification, or %NULL to disable
- * notification. Function pointers must be initialised;
- * the other fields will be initialised by this function.
- *
- * Must be called in process context. Notification may only be enabled
- * after the IRQ is allocated and must be disabled before the IRQ is
- * freed using free_irq().
+ * irq_set_affinity_notifier - control notification of IRQ affinity changes
+ * @irq: Interrupt for which to enable/disable notification
+ * @notify: Context for notification, or %NULL to disable
+ * notification. Function pointers must be initialised;
+ * the other fields will be initialised by this function.
+ *
+ * Must be called in process context. Notification may only be enabled
+ * after the IRQ is allocated and must be disabled before the IRQ is freed
+ * using free_irq().
*/
-int
-irq_set_affinity_notifier(unsigned int irq, struct irq_affinity_notify *notify)
+int irq_set_affinity_notifier(unsigned int irq, struct irq_affinity_notify *notify)
{
struct irq_desc *desc = irq_to_desc(irq);
struct irq_affinity_notify *old_notify;
@@ -643,15 +641,14 @@ int irq_setup_affinity(struct irq_desc *
/**
- * irq_set_vcpu_affinity - Set vcpu affinity for the interrupt
- * @irq: interrupt number to set affinity
- * @vcpu_info: vCPU specific data or pointer to a percpu array of vCPU
- * specific data for percpu_devid interrupts
- *
- * This function uses the vCPU specific data to set the vCPU
- * affinity for an irq. The vCPU specific data is passed from
- * outside, such as KVM. One example code path is as below:
- * KVM -> IOMMU -> irq_set_vcpu_affinity().
+ * irq_set_vcpu_affinity - Set vcpu affinity for the interrupt
+ * @irq: interrupt number to set affinity
+ * @vcpu_info: vCPU specific data or pointer to a percpu array of vCPU
+ * specific data for percpu_devid interrupts
+ *
+ * This function uses the vCPU specific data to set the vCPU affinity for
+ * an irq. The vCPU specific data is passed from outside, such as KVM. One
+ * example code path is as below: KVM -> IOMMU -> irq_set_vcpu_affinity().
*/
int irq_set_vcpu_affinity(unsigned int irq, void *vcpu_info)
{
@@ -703,15 +700,15 @@ static int __disable_irq_nosync(unsigned
}
/**
- * disable_irq_nosync - disable an irq without waiting
- * @irq: Interrupt to disable
+ * disable_irq_nosync - disable an irq without waiting
+ * @irq: Interrupt to disable
*
- * Disable the selected interrupt line. Disables and Enables are
- * nested.
- * Unlike disable_irq(), this function does not ensure existing
- * instances of the IRQ handler have completed before returning.
+ * Disable the selected interrupt line. Disables and Enables are
+ * nested.
+ * 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.
*/
void disable_irq_nosync(unsigned int irq)
{
@@ -720,17 +717,17 @@ void disable_irq_nosync(unsigned int irq
EXPORT_SYMBOL(disable_irq_nosync);
/**
- * disable_irq - disable an irq and wait for completion
- * @irq: Interrupt to disable
+ * disable_irq - disable an irq and wait for completion
+ * @irq: Interrupt to disable
+ *
+ * Disable the selected interrupt line. Enables and Disables are nested.
*
- * Disable the selected interrupt line. Enables and Disables are
- * nested.
- * This function waits for any pending IRQ handlers for this interrupt
- * to complete before returning. If you use this function while
- * holding a resource the IRQ handler may need you will deadlock.
+ * This function waits for any pending IRQ handlers for this interrupt to
+ * complete before returning. If you use this function while holding a
+ * resource the IRQ handler may need you will deadlock.
*
- * Can only be called from preemptible code as it might sleep when
- * an interrupt thread is associated to @irq.
+ * Can only be called from preemptible code as it might sleep when an
+ * interrupt thread is associated to @irq.
*
*/
void disable_irq(unsigned int irq)
@@ -742,40 +739,39 @@ void disable_irq(unsigned int irq)
EXPORT_SYMBOL(disable_irq);
/**
- * disable_hardirq - disables an irq and waits for hardirq completion
- * @irq: Interrupt to disable
+ * disable_hardirq - disables an irq and waits for hardirq completion
+ * @irq: Interrupt to disable
*
- * Disable the selected interrupt line. Enables and Disables are
- * nested.
- * This function waits for any pending hard IRQ handlers for this
- * interrupt to complete before returning. If you use this function while
- * holding a resource the hard IRQ handler may need you will deadlock.
+ * Disable the selected interrupt line. Enables and Disables are nested.
*
- * When used to optimistically disable an interrupt from atomic context
- * the return value must be checked.
+ * This function waits for any pending hard IRQ handlers for this interrupt
+ * to complete before returning. If you use this function while holding a
+ * resource the hard IRQ handler may need you will deadlock.
*
- * Returns: false if a threaded handler is active.
+ * When used to optimistically disable an interrupt from atomic context the
+ * return value must be checked.
*
- * This function may be called - with care - from IRQ context.
+ * Returns: false if a threaded handler is active.
+ *
+ * This function may be called - with care - from IRQ context.
*/
bool disable_hardirq(unsigned int irq)
{
if (!__disable_irq_nosync(irq))
return synchronize_hardirq(irq);
-
return false;
}
EXPORT_SYMBOL_GPL(disable_hardirq);
/**
- * disable_nmi_nosync - disable an nmi without waiting
- * @irq: Interrupt to disable
+ * disable_nmi_nosync - disable an nmi without waiting
+ * @irq: Interrupt to disable
+ *
+ * Disable the selected interrupt line. Disables and enables are nested.
*
- * Disable the selected interrupt line. Disables and enables are
- * nested.
- * The interrupt to disable must have been requested through request_nmi.
- * Unlike disable_nmi(), this function does not ensure existing
- * instances of the IRQ handler have completed before returning.
+ * The interrupt to disable must have been requested through request_nmi.
+ * Unlike disable_nmi(), this function does not ensure existing
+ * instances of the IRQ handler have completed before returning.
*/
void disable_nmi_nosync(unsigned int irq)
{
@@ -815,15 +811,14 @@ void __enable_irq(struct irq_desc *desc)
}
/**
- * enable_irq - enable handling of an irq
- * @irq: Interrupt to enable
+ * enable_irq - enable handling of an irq
+ * @irq: Interrupt to enable
*
- * Undoes the effect of one call to disable_irq(). If this
- * matches the last disable, processing of interrupts on this
- * IRQ line is re-enabled.
+ * Undoes the effect of one call to disable_irq(). If this matches the
+ * last disable, processing of interrupts on this IRQ line is re-enabled.
*
- * This function may be called from IRQ context only when
- * desc->irq_data.chip->bus_lock and desc->chip->bus_sync_unlock are NULL !
+ * This function may be called from IRQ context only when
+ * desc->irq_data.chip->bus_lock and desc->chip->bus_sync_unlock are NULL !
*/
void enable_irq(unsigned int irq)
{
@@ -843,13 +838,12 @@ void enable_irq(unsigned int irq)
EXPORT_SYMBOL(enable_irq);
/**
- * enable_nmi - enable handling of an nmi
- * @irq: Interrupt to enable
+ * enable_nmi - enable handling of an nmi
+ * @irq: Interrupt to enable
*
- * The interrupt to enable must have been requested through request_nmi.
- * Undoes the effect of one call to disable_nmi(). If this
- * matches the last disable, processing of interrupts on this
- * IRQ line is re-enabled.
+ * The interrupt to enable must have been requested through request_nmi.
+ * Undoes the effect of one call to disable_nmi(). If this matches the last
+ * disable, processing of interrupts on this IRQ line is re-enabled.
*/
void enable_nmi(unsigned int irq)
{
@@ -871,23 +865,22 @@ static int set_irq_wake_real(unsigned in
}
/**
- * irq_set_irq_wake - control irq power management wakeup
- * @irq: interrupt to control
- * @on: enable/disable power management wakeup
- *
- * Enable/disable power management wakeup mode, which is
- * disabled by default. Enables and disables must match,
- * just as they match for non-wakeup mode support.
- *
- * Wakeup mode lets this IRQ wake the system from sleep
- * states like "suspend to RAM".
- *
- * Note: irq enable/disable state is completely orthogonal
- * to the enable/disable state of irq wake. An irq can be
- * disabled with disable_irq() and still wake the system as
- * long as the irq has wake enabled. If this does not hold,
- * then the underlying irq chip and the related driver need
- * to be investigated.
+ * irq_set_irq_wake - control irq power management wakeup
+ * @irq: interrupt to control
+ * @on: enable/disable power management wakeup
+ *
+ * Enable/disable power management wakeup mode, which is disabled by
+ * default. Enables and disables must match, just as they match for
+ * non-wakeup mode support.
+ *
+ * Wakeup mode lets this IRQ wake the system from sleep states like
+ * "suspend to RAM".
+ *
+ * Note: irq enable/disable state is completely orthogonal to the
+ * enable/disable state of irq wake. An irq can be disabled with
+ * disable_irq() and still wake the system as long as the irq has wake
+ * enabled. If this does not hold, then the underlying irq chip and the
+ * related driver need to be investigated.
*/
int irq_set_irq_wake(unsigned int irq, unsigned int on)
{
@@ -1332,10 +1325,9 @@ static int irq_thread(void *data)
}
/**
- * irq_wake_thread - wake the irq thread for the action identified by dev_id
- * @irq: Interrupt line
- * @dev_id: Device identity for which the thread should be woken
- *
+ * irq_wake_thread - wake the irq thread for the action identified by dev_id
+ * @irq: Interrupt line
+ * @dev_id: Device identity for which the thread should be woken
*/
void irq_wake_thread(unsigned int irq, void *dev_id)
{
@@ -2003,20 +1995,19 @@ static struct irqaction *__free_irq(stru
}
/**
- * free_irq - free an interrupt allocated with request_irq
- * @irq: Interrupt line to free
- * @dev_id: Device identity to free
- *
- * Remove an interrupt handler. The handler is removed and if the
- * interrupt line is no longer in use by any driver it is disabled.
- * On a shared IRQ the caller must ensure the interrupt is disabled
- * on the card it drives before calling this function. The function
- * does not return until any executing interrupts for this IRQ
- * have completed.
+ * free_irq - free an interrupt allocated with request_irq
+ * @irq: Interrupt line to free
+ * @dev_id: Device identity to free
+ *
+ * Remove an interrupt handler. The handler is removed and if the interrupt
+ * line is no longer in use by any driver it is disabled. On a shared IRQ
+ * the caller must ensure the interrupt is disabled on the card it drives
+ * before calling this function. The function does not return until any
+ * executing interrupts for this IRQ have completed.
*
- * This function must not be called from interrupt context.
+ * This function must not be called from interrupt context.
*
- * Returns the devname argument passed to request_irq.
+ * Returns the devname argument passed to request_irq.
*/
const void *free_irq(unsigned int irq, void *dev_id)
{
@@ -2097,42 +2088,40 @@ const void *free_nmi(unsigned int irq, v
}
/**
- * request_threaded_irq - allocate an interrupt line
- * @irq: Interrupt line to allocate
- * @handler: Function to be called when the IRQ occurs.
- * Primary handler for threaded interrupts.
- * If handler is NULL and thread_fn != NULL
- * the default primary handler is installed.
- * @thread_fn: Function called from the irq handler thread
- * If NULL, no irq thread is created
- * @irqflags: Interrupt type flags
- * @devname: An ascii name for the claiming device
- * @dev_id: A cookie passed back to the handler function
- *
- * This call allocates interrupt resources and enables the
- * interrupt line and IRQ handling. From the point this
- * call is made your handler function may be invoked. Since
- * your handler function must clear any interrupt the board
- * raises, you must take care both to initialise your hardware
- * and to set up the interrupt handler in the right order.
- *
- * If you want to set up a threaded irq handler for your device
- * then you need to supply @handler and @thread_fn. @handler is
- * still called in hard interrupt context and has to check
- * whether the interrupt originates from the device. If yes it
- * needs to disable the interrupt on the device and return
- * IRQ_WAKE_THREAD which will wake up the handler thread and run
- * @thread_fn. This split handler design is necessary to support
- * shared interrupts.
- *
- * Dev_id must be globally unique. Normally the address of the
- * device data structure is used as the cookie. Since the handler
- * receives this value it makes sense to use it.
+ * request_threaded_irq - allocate an interrupt line
+ * @irq: Interrupt line to allocate
+ * @handler: Function to be called when the IRQ occurs.
+ * Primary handler for threaded interrupts.
+ * If handler is NULL and thread_fn != NULL
+ * the default primary handler is installed.
+ * @thread_fn: Function called from the irq handler thread
+ * If NULL, no irq thread is created
+ * @irqflags: Interrupt type flags
+ * @devname: An ascii name for the claiming device
+ * @dev_id: A cookie passed back to the handler function
+ *
+ * This call allocates interrupt resources and enables the interrupt line
+ * and IRQ handling. From the point this call is made your handler function
+ * may be invoked. Since your handler function must clear any interrupt the
+ * board raises, you must take care both to initialise your hardware and to
+ * set up the interrupt handler in the right order.
+ *
+ * If you want to set up a threaded irq handler for your device then you
+ * need to supply @handler and @thread_fn. @handler is still called in hard
+ * interrupt context and has to check whether the interrupt originates from
+ * the device. If yes it needs to disable the interrupt on the device and
+ * return IRQ_WAKE_THREAD which will wake up the handler thread and run
+ * @thread_fn. This split handler design is necessary to support shared
+ * interrupts.
+ *
+ * @dev_id must be globally unique. Normally the address of the device data
+ * structure is used as the cookie. Since the handler receives this value
+ * it makes sense to use it.
*
- * If your interrupt is shared you must pass a non NULL dev_id
- * as this is required when freeing the interrupt.
+ * If your interrupt is shared you must pass a non NULL dev_id as this is
+ * required when freeing the interrupt.
*
- * Flags:
+ * Flags:
*
* IRQF_SHARED Interrupt is shared
* IRQF_TRIGGER_* Specify active edge(s) or level
@@ -2230,21 +2219,20 @@ int request_threaded_irq(unsigned int ir
EXPORT_SYMBOL(request_threaded_irq);
/**
- * request_any_context_irq - allocate an interrupt line
- * @irq: Interrupt line to allocate
- * @handler: Function to be called when the IRQ occurs.
- * Threaded handler for threaded interrupts.
- * @flags: Interrupt type flags
- * @name: An ascii name for the claiming device
- * @dev_id: A cookie passed back to the handler function
- *
- * This call allocates interrupt resources and enables the
- * interrupt line and IRQ handling. It selects either a
- * hardirq or threaded handling method depending on the
- * context.
+ * request_any_context_irq - allocate an interrupt line
+ * @irq: Interrupt line to allocate
+ * @handler: Function to be called when the IRQ occurs.
+ * Threaded handler for threaded interrupts.
+ * @flags: Interrupt type flags
+ * @name: An ascii name for the claiming device
+ * @dev_id: A cookie passed back to the handler function
+ *
+ * This call allocates interrupt resources and enables the interrupt line
+ * and IRQ handling. It selects either a hardirq or threaded handling
+ * method depending on the context.
*
- * On failure, it returns a negative value. On success,
- * it returns either IRQC_IS_HARDIRQ or IRQC_IS_NESTED.
+ * Returns: On failure, it returns a negative value. On success, it returns either
+ * IRQC_IS_HARDIRQ or IRQC_IS_NESTED.
*/
int request_any_context_irq(unsigned int irq, irq_handler_t handler,
unsigned long flags, const char *name, void *dev_id)
@@ -2271,30 +2259,29 @@ int request_any_context_irq(unsigned int
EXPORT_SYMBOL_GPL(request_any_context_irq);
/**
- * request_nmi - allocate an interrupt line for NMI delivery
- * @irq: Interrupt line to allocate
- * @handler: Function to be called when the IRQ occurs.
- * Threaded handler for threaded interrupts.
- * @irqflags: Interrupt type flags
- * @name: An ascii name for the claiming device
- * @dev_id: A cookie passed back to the handler function
- *
- * This call allocates interrupt resources and enables the
- * interrupt line and IRQ handling. It sets up the IRQ line
- * to be handled as an NMI.
- *
- * An interrupt line delivering NMIs cannot be shared and IRQ handling
- * cannot be threaded.
- *
- * Interrupt lines requested for NMI delivering must produce per cpu
- * interrupts and have auto enabling setting disabled.
- *
- * Dev_id must be globally unique. Normally the address of the
- * device data structure is used as the cookie. Since the handler
- * receives this value it makes sense to use it.
+ * request_nmi - allocate an interrupt line for NMI delivery
+ * @irq: Interrupt line to allocate
+ * @handler: Function to be called when the IRQ occurs.
+ * Threaded handler for threaded interrupts.
+ * @irqflags: Interrupt type flags
+ * @name: An ascii name for the claiming device
+ * @dev_id: A cookie passed back to the handler function
+ *
+ * This call allocates interrupt resources and enables the interrupt line
+ * and IRQ handling. It sets up the IRQ line to be handled as an NMI.
+ *
+ * An interrupt line delivering NMIs cannot be shared and IRQ handling
+ * cannot be threaded.
+ *
+ * Interrupt lines requested for NMI delivering must produce per cpu
+ * interrupts and have auto enabling setting disabled.
+ *
+ * @dev_id must be globally unique. Normally the address of the device data
+ * structure is used as the cookie. Since the handler receives this value
+ * it makes sense to use it.
*
- * If the interrupt line cannot be used to deliver NMIs, function
- * will fail and return a negative value.
+ * If the interrupt line cannot be used to deliver NMIs, function will fail
+ * and return a negative value.
*/
int request_nmi(unsigned int irq, irq_handler_t handler,
unsigned long irqflags, const char *name, void *dev_id)
@@ -2496,9 +2483,9 @@ static struct irqaction *__free_percpu_i
}
/**
- * remove_percpu_irq - free a per-cpu interrupt
- * @irq: Interrupt line to free
- * @act: irqaction for the interrupt
+ * remove_percpu_irq - free a per-cpu interrupt
+ * @irq: Interrupt line to free
+ * @act: irqaction for the interrupt
*
* Used to remove interrupts statically setup by the early boot process.
*/
@@ -2507,20 +2494,20 @@ void remove_percpu_irq(unsigned int irq,
struct irq_desc *desc = irq_to_desc(irq);
if (desc && irq_settings_is_per_cpu_devid(desc))
- __free_percpu_irq(irq, act->percpu_dev_id);
+ __free_percpu_irq(irq, act->percpu_dev_id);
}
/**
- * free_percpu_irq - free an interrupt allocated with request_percpu_irq
- * @irq: Interrupt line to free
- * @dev_id: Device identity to free
+ * free_percpu_irq - free an interrupt allocated with request_percpu_irq
+ * @irq: Interrupt line to free
+ * @dev_id: Device identity to free
*
- * Remove a percpu interrupt handler. The handler is removed, but
- * the interrupt line is not disabled. This must be done on each
- * CPU before calling this function. The function does not return
- * until any executing interrupts for this IRQ have completed.
+ * Remove a percpu interrupt handler. The handler is removed, but the
+ * interrupt line is not disabled. This must be done on each CPU before
+ * calling this function. The function does not return until any executing
+ * interrupts for this IRQ have completed.
*
- * This function must not be called from interrupt context.
+ * This function must not be called from interrupt context.
*/
void free_percpu_irq(unsigned int irq, void __percpu *dev_id)
{
@@ -2549,9 +2536,9 @@ void free_percpu_nmi(unsigned int irq, v
}
/**
- * setup_percpu_irq - setup a per-cpu interrupt
- * @irq: Interrupt line to setup
- * @act: irqaction for the interrupt
+ * setup_percpu_irq - setup a per-cpu interrupt
+ * @irq: Interrupt line to setup
+ * @act: irqaction for the interrupt
*
* Used to statically setup per-cpu interrupts in the early boot process.
*/
@@ -2576,21 +2563,20 @@ int setup_percpu_irq(unsigned int irq, s
}
/**
- * __request_percpu_irq - allocate a percpu interrupt line
- * @irq: Interrupt line to allocate
- * @handler: Function to be called when the IRQ occurs.
- * @flags: Interrupt type flags (IRQF_TIMER only)
- * @devname: An ascii name for the claiming device
- * @dev_id: A percpu cookie passed back to the handler function
- *
- * This call allocates interrupt resources and enables the
- * interrupt on the local CPU. If the interrupt is supposed to be
- * enabled on other CPUs, it has to be done on each CPU using
- * enable_percpu_irq().
- *
- * Dev_id must be globally unique. It is a per-cpu variable, and
- * the handler gets called with the interrupted CPU's instance of
- * that variable.
+ * __request_percpu_irq - allocate a percpu interrupt line
+ * @irq: Interrupt line to allocate
+ * @handler: Function to be called when the IRQ occurs.
+ * @flags: Interrupt type flags (IRQF_TIMER only)
+ * @devname: An ascii name for the claiming device
+ * @dev_id: A percpu cookie passed back to the handler function
+ *
+ * This call allocates interrupt resources and enables the interrupt on the
+ * local CPU. If the interrupt is supposed to be enabled on other CPUs, it
+ * has to be done on each CPU using enable_percpu_irq().
+ *
+ * @dev_id must be globally unique. It is a per-cpu variable, and
+ * the handler gets called with the interrupted CPU's instance of
+ * that variable.
*/
int __request_percpu_irq(unsigned int irq, irq_handler_t handler,
unsigned long flags, const char *devname,
@@ -2638,25 +2624,25 @@ int __request_percpu_irq(unsigned int ir
EXPORT_SYMBOL_GPL(__request_percpu_irq);
/**
- * request_percpu_nmi - allocate a percpu interrupt line for NMI delivery
- * @irq: Interrupt line to allocate
- * @handler: Function to be called when the IRQ occurs.
- * @name: An ascii name for the claiming device
- * @dev_id: A percpu cookie passed back to the handler function
- *
- * This call allocates interrupt resources for a per CPU NMI. Per CPU NMIs
- * have to be setup on each CPU by calling prepare_percpu_nmi() before
- * being enabled on the same CPU by using enable_percpu_nmi().
- *
- * Dev_id must be globally unique. It is a per-cpu variable, and
- * the handler gets called with the interrupted CPU's instance of
- * that variable.
+ * request_percpu_nmi - allocate a percpu interrupt line for NMI delivery
+ * @irq: Interrupt line to allocate
+ * @handler: Function to be called when the IRQ occurs.
+ * @name: An ascii name for the claiming device
+ * @dev_id: A percpu cookie passed back to the handler function
+ *
+ * This call allocates interrupt resources for a per CPU NMI. Per CPU NMIs
+ * have to be setup on each CPU by calling prepare_percpu_nmi() before
+ * being enabled on the same CPU by using enable_percpu_nmi().
+ *
+ * @dev_id must be globally unique. It is a per-cpu variable, and the
+ * handler gets called with the interrupted CPU's instance of that
+ * variable.
*
- * Interrupt lines requested for NMI delivering should have auto enabling
- * setting disabled.
+ * Interrupt lines requested for NMI delivering should have auto enabling
+ * setting disabled.
*
- * If the interrupt line cannot be used to deliver NMIs, function
- * will fail returning a negative value.
+ * If the interrupt line cannot be used to deliver NMIs, function
+ * will fail returning a negative value.
*/
int request_percpu_nmi(unsigned int irq, irq_handler_t handler,
const char *name, void __percpu *dev_id)
@@ -2714,17 +2700,17 @@ int request_percpu_nmi(unsigned int irq,
}
/**
- * prepare_percpu_nmi - performs CPU local setup for NMI delivery
- * @irq: Interrupt line to prepare for NMI delivery
+ * prepare_percpu_nmi - performs CPU local setup for NMI delivery
+ * @irq: Interrupt line to prepare for NMI delivery
*
- * This call prepares an interrupt line to deliver NMI on the current CPU,
- * before that interrupt line gets enabled with enable_percpu_nmi().
+ * This call prepares an interrupt line to deliver NMI on the current CPU,
+ * before that interrupt line gets enabled with enable_percpu_nmi().
*
- * As a CPU local operation, this should be called from non-preemptible
- * context.
+ * As a CPU local operation, this should be called from non-preemptible
+ * context.
*
- * If the interrupt line cannot be used to deliver NMIs, function
- * will fail returning a negative value.
+ * If the interrupt line cannot be used to deliver NMIs, function will fail
+ * returning a negative value.
*/
int prepare_percpu_nmi(unsigned int irq)
{
@@ -2758,16 +2744,14 @@ int prepare_percpu_nmi(unsigned int irq)
}
/**
- * teardown_percpu_nmi - undoes NMI setup of IRQ line
- * @irq: Interrupt line from which CPU local NMI configuration should be
- * removed
- *
- * This call undoes the setup done by prepare_percpu_nmi().
+ * teardown_percpu_nmi - undoes NMI setup of IRQ line
+ * @irq: Interrupt line from which CPU local NMI configuration should be removed
*
- * IRQ line should not be enabled for the current CPU.
+ * This call undoes the setup done by prepare_percpu_nmi().
*
- * As a CPU local operation, this should be called from non-preemptible
- * context.
+ * IRQ line should not be enabled for the current CPU.
+ * As a CPU local operation, this should be called from non-preemptible
+ * context.
*/
void teardown_percpu_nmi(unsigned int irq)
{
@@ -2814,17 +2798,16 @@ int __irq_get_irqchip_state(struct irq_d
}
/**
- * irq_get_irqchip_state - returns the irqchip state of a interrupt.
- * @irq: Interrupt line that is forwarded to a VM
- * @which: One of IRQCHIP_STATE_* the caller wants to know about
- * @state: a pointer to a boolean where the state is to be stored
- *
- * This call snapshots the internal irqchip state of an
- * interrupt, returning into @state the bit corresponding to
- * stage @which
+ * irq_get_irqchip_state - returns the irqchip state of a interrupt.
+ * @irq: Interrupt line that is forwarded to a VM
+ * @which: One of IRQCHIP_STATE_* the caller wants to know about
+ * @state: a pointer to a boolean where the state is to be stored
+ *
+ * This call snapshots the internal irqchip state of an interrupt,
+ * returning into @state the bit corresponding to stage @which
*
- * This function should be called with preemption disabled if the
- * interrupt controller has per-cpu registers.
+ * This function should be called with preemption disabled if the interrupt
+ * controller has per-cpu registers.
*/
int irq_get_irqchip_state(unsigned int irq, enum irqchip_irq_state which,
bool *state)
@@ -2848,19 +2831,18 @@ int irq_get_irqchip_state(unsigned int i
EXPORT_SYMBOL_GPL(irq_get_irqchip_state);
/**
- * irq_set_irqchip_state - set the state of a forwarded interrupt.
- * @irq: Interrupt line that is forwarded to a VM
- * @which: State to be restored (one of IRQCHIP_STATE_*)
- * @val: Value corresponding to @which
+ * irq_set_irqchip_state - set the state of a forwarded interrupt.
+ * @irq: Interrupt line that is forwarded to a VM
+ * @which: State to be restored (one of IRQCHIP_STATE_*)
+ * @val: Value corresponding to @which
*
- * This call sets the internal irqchip state of an interrupt,
- * depending on the value of @which.
+ * This call sets the internal irqchip state of an interrupt, depending on
+ * the value of @which.
*
- * This function should be called with migration disabled if the
- * interrupt controller has per-cpu registers.
+ * This function should be called with migration disabled if the interrupt
+ * controller has per-cpu registers.
*/
-int irq_set_irqchip_state(unsigned int irq, enum irqchip_irq_state which,
- bool val)
+int irq_set_irqchip_state(unsigned int irq, enum irqchip_irq_state which, bool val)
{
struct irq_desc *desc;
struct irq_data *data;
^ permalink raw reply [flat|nested] 50+ messages in thread
* [patch 30/46] genirq/manage: Convert to lock guards
2025-03-13 15:59 [patch 00/46] genirq: Cleanups and conversion to lock guards Thomas Gleixner
` (28 preceding siblings ...)
2025-03-13 16:00 ` [patch 29/46] genirq/manage: Cleanup kernel doc comments Thomas Gleixner
@ 2025-03-13 16:00 ` Thomas Gleixner
2025-03-13 16:00 ` [patch 31/46] genirq/manage: Rework irq_update_affinity_desc() Thomas Gleixner
` (16 subsequent siblings)
46 siblings, 0 replies; 50+ messages in thread
From: Thomas Gleixner @ 2025-03-13 16:00 UTC (permalink / raw)
To: LKML; +Cc: Peter Zijlstra, Jiri Slaby
Convert lock/unlock pairs to guards.
No functional change.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
kernel/irq/manage.c | 155 +++++++++++++++++++---------------------------------
1 file changed, 58 insertions(+), 97 deletions(-)
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -41,8 +41,6 @@ static void __synchronize_hardirq(struct
bool inprogress;
do {
- unsigned long flags;
-
/*
* Wait until we're out of the critical section. This might
* give the wrong answer due to the lack of memory barriers.
@@ -51,7 +49,7 @@ static void __synchronize_hardirq(struct
cpu_relax();
/* Ok, that indicated we're done: double-check carefully. */
- raw_spin_lock_irqsave(&desc->lock, flags);
+ guard(raw_spinlock_irqsave)(&desc->lock);
inprogress = irqd_irq_inprogress(&desc->irq_data);
/*
@@ -67,8 +65,6 @@ static void __synchronize_hardirq(struct
__irq_get_irqchip_state(irqd, IRQCHIP_STATE_ACTIVE,
&inprogress);
}
- raw_spin_unlock_irqrestore(&desc->lock, flags);
-
/* Oops, that failed? */
} while (inprogress);
}
@@ -456,16 +452,12 @@ static int __irq_set_affinity(unsigned i
bool force)
{
struct irq_desc *desc = irq_to_desc(irq);
- unsigned long flags;
- int ret;
if (!desc)
return -EINVAL;
- raw_spin_lock_irqsave(&desc->lock, flags);
- ret = irq_set_affinity_locked(irq_desc_get_irq_data(desc), mask, force);
- raw_spin_unlock_irqrestore(&desc->lock, flags);
- return ret;
+ guard(raw_spinlock_irqsave)(&desc->lock);
+ return irq_set_affinity_locked(irq_desc_get_irq_data(desc), mask, force);
}
/**
@@ -520,17 +512,16 @@ static void irq_affinity_notify(struct w
container_of(work, struct irq_affinity_notify, work);
struct irq_desc *desc = irq_to_desc(notify->irq);
cpumask_var_t cpumask;
- unsigned long flags;
if (!desc || !alloc_cpumask_var(&cpumask, GFP_KERNEL))
goto out;
- raw_spin_lock_irqsave(&desc->lock, flags);
- if (irq_move_pending(&desc->irq_data))
- irq_get_pending(cpumask, desc);
- else
- cpumask_copy(cpumask, desc->irq_common_data.affinity);
- raw_spin_unlock_irqrestore(&desc->lock, flags);
+ scoped_guard (raw_spinlock_irqsave, &desc->lock) {
+ if (irq_move_pending(&desc->irq_data))
+ irq_get_pending(cpumask, desc);
+ else
+ cpumask_copy(cpumask, desc->irq_common_data.affinity);
+ }
notify->notify(notify, cpumask);
@@ -554,7 +545,6 @@ int irq_set_affinity_notifier(unsigned i
{
struct irq_desc *desc = irq_to_desc(irq);
struct irq_affinity_notify *old_notify;
- unsigned long flags;
/* The release function is promised process context */
might_sleep();
@@ -569,10 +559,10 @@ int irq_set_affinity_notifier(unsigned i
INIT_WORK(¬ify->work, irq_affinity_notify);
}
- raw_spin_lock_irqsave(&desc->lock, flags);
- old_notify = desc->affinity_notify;
- desc->affinity_notify = notify;
- raw_spin_unlock_irqrestore(&desc->lock, flags);
+ scoped_guard (raw_spinlock_irqsave, &desc->lock) {
+ old_notify = desc->affinity_notify;
+ desc->affinity_notify = notify;
+ }
if (old_notify) {
if (cancel_work_sync(&old_notify->work)) {
@@ -593,7 +583,8 @@ EXPORT_SYMBOL_GPL(irq_set_affinity_notif
int irq_setup_affinity(struct irq_desc *desc)
{
struct cpumask *set = irq_default_affinity;
- int ret, node = irq_desc_get_node(desc);
+ int node = irq_desc_get_node(desc);
+
static DEFINE_RAW_SPINLOCK(mask_lock);
static struct cpumask mask;
@@ -601,7 +592,7 @@ int irq_setup_affinity(struct irq_desc *
if (!__irq_can_set_affinity(desc))
return 0;
- raw_spin_lock(&mask_lock);
+ guard(raw_spinlock)(&mask_lock);
/*
* Preserve the managed affinity setting and a userspace affinity
* setup, but make sure that one of the targets is online.
@@ -626,9 +617,7 @@ int irq_setup_affinity(struct irq_desc *
if (cpumask_intersects(&mask, nodemask))
cpumask_and(&mask, &mask, nodemask);
}
- ret = irq_do_set_affinity(&desc->irq_data, &mask, false);
- raw_spin_unlock(&mask_lock);
- return ret;
+ return irq_do_set_affinity(&desc->irq_data, &mask, false);
}
#else
/* Wrapper for ALPHA specific affinity selector magic */
@@ -1070,19 +1059,19 @@ static void irq_thread_check_affinity(st
return;
}
- raw_spin_lock_irq(&desc->lock);
- /*
- * This code is triggered unconditionally. Check the affinity
- * mask pointer. For CPU_MASK_OFFSTACK=n this is optimized out.
- */
- if (cpumask_available(desc->irq_common_data.affinity)) {
- const struct cpumask *m;
+ scoped_guard (raw_spinlock_irq, &desc->lock) {
+ /*
+ * This code is triggered unconditionally. Check the affinity
+ * mask pointer. For CPU_MASK_OFFSTACK=n this is optimized out.
+ */
+ if (cpumask_available(desc->irq_common_data.affinity)) {
+ const struct cpumask *m;
- m = irq_data_get_effective_affinity_mask(&desc->irq_data);
- cpumask_copy(mask, m);
- valid = true;
+ m = irq_data_get_effective_affinity_mask(&desc->irq_data);
+ cpumask_copy(mask, m);
+ valid = true;
+ }
}
- raw_spin_unlock_irq(&desc->lock);
if (valid)
set_cpus_allowed_ptr(current, mask);
@@ -1250,9 +1239,8 @@ static void irq_wake_secondary(struct ir
if (WARN_ON_ONCE(!secondary))
return;
- raw_spin_lock_irq(&desc->lock);
+ guard(raw_spinlock_irq)(&desc->lock);
__irq_wake_thread(desc, secondary);
- raw_spin_unlock_irq(&desc->lock);
}
/*
@@ -1333,12 +1321,11 @@ void irq_wake_thread(unsigned int irq, v
{
struct irq_desc *desc = irq_to_desc(irq);
struct irqaction *action;
- unsigned long flags;
if (!desc || WARN_ON(irq_settings_is_per_cpu_devid(desc)))
return;
- raw_spin_lock_irqsave(&desc->lock, flags);
+ guard(raw_spinlock_irqsave)(&desc->lock);
for_each_action_of_desc(desc, action) {
if (action->dev_id == dev_id) {
if (action->thread)
@@ -1346,7 +1333,6 @@ void irq_wake_thread(unsigned int irq, v
break;
}
}
- raw_spin_unlock_irqrestore(&desc->lock, flags);
}
EXPORT_SYMBOL_GPL(irq_wake_thread);
@@ -1977,9 +1963,8 @@ static struct irqaction *__free_irq(stru
* There is no interrupt on the fly anymore. Deactivate it
* completely.
*/
- raw_spin_lock_irqsave(&desc->lock, flags);
- irq_domain_deactivate_irq(&desc->irq_data);
- raw_spin_unlock_irqrestore(&desc->lock, flags);
+ scoped_guard (raw_spinlock_irqsave, &desc->lock)
+ irq_domain_deactivate_irq(&desc->irq_data);
irq_release_resources(desc);
chip_bus_sync_unlock(desc);
@@ -2064,8 +2049,6 @@ static const void *__cleanup_nmi(unsigne
const void *free_nmi(unsigned int irq, void *dev_id)
{
struct irq_desc *desc = irq_to_desc(irq);
- unsigned long flags;
- const void *devname;
if (!desc || WARN_ON(!irq_is_nmi(desc)))
return NULL;
@@ -2077,14 +2060,9 @@ const void *free_nmi(unsigned int irq, v
if (WARN_ON(desc->depth == 0))
disable_nmi_nosync(irq);
- raw_spin_lock_irqsave(&desc->lock, flags);
-
+ guard(raw_spinlock_irqsave)(&desc->lock);
irq_nmi_teardown(desc);
- devname = __cleanup_nmi(irq, desc);
-
- raw_spin_unlock_irqrestore(&desc->lock, flags);
-
- return devname;
+ return __cleanup_nmi(irq, desc);
}
/**
@@ -2288,7 +2266,6 @@ int request_nmi(unsigned int irq, irq_ha
{
struct irqaction *action;
struct irq_desc *desc;
- unsigned long flags;
int retval;
if (irq == IRQ_NOTCONNECTED)
@@ -2330,21 +2307,17 @@ int request_nmi(unsigned int irq, irq_ha
if (retval)
goto err_irq_setup;
- raw_spin_lock_irqsave(&desc->lock, flags);
-
- /* Setup NMI state */
- desc->istate |= IRQS_NMI;
- retval = irq_nmi_setup(desc);
- if (retval) {
- __cleanup_nmi(irq, desc);
- raw_spin_unlock_irqrestore(&desc->lock, flags);
- return -EINVAL;
+ scoped_guard (raw_spinlock_irqsave, &desc->lock) {
+ /* Setup NMI state */
+ desc->istate |= IRQS_NMI;
+ retval = irq_nmi_setup(desc);
+ if (retval) {
+ __cleanup_nmi(irq, desc);
+ return -EINVAL;
+ }
+ return 0;
}
- raw_spin_unlock_irqrestore(&desc->lock, flags);
-
- return 0;
-
err_irq_setup:
irq_chip_pm_put(&desc->irq_data);
err_out:
@@ -2443,43 +2416,34 @@ static struct irqaction *__free_percpu_i
{
struct irq_desc *desc = irq_to_desc(irq);
struct irqaction *action;
- unsigned long flags;
WARN(in_interrupt(), "Trying to free IRQ %d from IRQ context!\n", irq);
if (!desc)
return NULL;
- raw_spin_lock_irqsave(&desc->lock, flags);
+ scoped_guard (raw_spinlock_irqsave, &desc->lock) {
+ action = desc->action;
+ if (!action || action->percpu_dev_id != dev_id) {
+ WARN(1, "Trying to free already-free IRQ %d\n", irq);
+ return NULL;
+ }
- action = desc->action;
- if (!action || action->percpu_dev_id != dev_id) {
- WARN(1, "Trying to free already-free IRQ %d\n", irq);
- goto bad;
- }
+ if (!cpumask_empty(desc->percpu_enabled)) {
+ WARN(1, "percpu IRQ %d still enabled on CPU%d!\n",
+ irq, cpumask_first(desc->percpu_enabled));
+ return NULL;
+ }
- if (!cpumask_empty(desc->percpu_enabled)) {
- WARN(1, "percpu IRQ %d still enabled on CPU%d!\n",
- irq, cpumask_first(desc->percpu_enabled));
- goto bad;
+ /* Found it - now remove it from the list of entries: */
+ desc->action = NULL;
+ desc->istate &= ~IRQS_NMI;
}
- /* Found it - now remove it from the list of entries: */
- desc->action = NULL;
-
- desc->istate &= ~IRQS_NMI;
-
- raw_spin_unlock_irqrestore(&desc->lock, flags);
-
unregister_handler_proc(irq, action);
-
irq_chip_pm_put(&desc->irq_data);
module_put(desc->owner);
return action;
-
-bad:
- raw_spin_unlock_irqrestore(&desc->lock, flags);
- return NULL;
}
/**
@@ -2649,7 +2613,6 @@ int request_percpu_nmi(unsigned int irq,
{
struct irqaction *action;
struct irq_desc *desc;
- unsigned long flags;
int retval;
if (!handler)
@@ -2685,10 +2648,8 @@ int request_percpu_nmi(unsigned int irq,
if (retval)
goto err_irq_setup;
- raw_spin_lock_irqsave(&desc->lock, flags);
+ guard(raw_spinlock_irqsave)(&desc->lock);
desc->istate |= IRQS_NMI;
- raw_spin_unlock_irqrestore(&desc->lock, flags);
-
return 0;
err_irq_setup:
^ permalink raw reply [flat|nested] 50+ messages in thread
* [patch 31/46] genirq/manage: Rework irq_update_affinity_desc()
2025-03-13 15:59 [patch 00/46] genirq: Cleanups and conversion to lock guards Thomas Gleixner
` (29 preceding siblings ...)
2025-03-13 16:00 ` [patch 30/46] genirq/manage: Convert to lock guards Thomas Gleixner
@ 2025-03-13 16:00 ` Thomas Gleixner
2025-03-13 16:00 ` [patch 32/46] genirq/manage: Rework __irq_apply_affinity_hint() Thomas Gleixner
` (15 subsequent siblings)
46 siblings, 0 replies; 50+ messages in thread
From: Thomas Gleixner @ 2025-03-13 16:00 UTC (permalink / raw)
To: LKML; +Cc: Peter Zijlstra, Jiri Slaby
Use the new guards to get and lock the interrupt descriptor and tidy up the
code.
No functional change.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
kernel/irq/manage.c | 76 +++++++++++++++++++++-------------------------------
1 file changed, 32 insertions(+), 44 deletions(-)
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -393,14 +393,8 @@ int irq_set_affinity_locked(struct irq_d
* an interrupt which is already started or which has already been configured
* as managed will also fail, as these mean invalid init state or double init.
*/
-int irq_update_affinity_desc(unsigned int irq,
- struct irq_affinity_desc *affinity)
+int irq_update_affinity_desc(unsigned int irq, struct irq_affinity_desc *affinity)
{
- struct irq_desc *desc;
- unsigned long flags;
- bool activated;
- int ret = 0;
-
/*
* Supporting this with the reservation scheme used by x86 needs
* some more thought. Fail it for now.
@@ -408,44 +402,38 @@ int irq_update_affinity_desc(unsigned in
if (IS_ENABLED(CONFIG_GENERIC_IRQ_RESERVATION_MODE))
return -EOPNOTSUPP;
- desc = irq_get_desc_buslock(irq, &flags, 0);
- if (!desc)
- return -EINVAL;
-
- /* Requires the interrupt to be shut down */
- if (irqd_is_started(&desc->irq_data)) {
- ret = -EBUSY;
- goto out_unlock;
- }
-
- /* Interrupts which are already managed cannot be modified */
- if (irqd_affinity_is_managed(&desc->irq_data)) {
- ret = -EBUSY;
- goto out_unlock;
+ scoped_irqdesc_get_and_buslock(irq, 0) {
+ struct irq_desc *desc = scoped_irqdesc;
+ bool activated;
+
+ /* Requires the interrupt to be shut down */
+ if (irqd_is_started(&desc->irq_data))
+ return -EBUSY;
+
+ /* Interrupts which are already managed cannot be modified */
+ if (irqd_affinity_is_managed(&desc->irq_data))
+ return -EBUSY;
+ /*
+ * Deactivate the interrupt. That's required to undo
+ * anything an earlier activation has established.
+ */
+ activated = irqd_is_activated(&desc->irq_data);
+ if (activated)
+ irq_domain_deactivate_irq(&desc->irq_data);
+
+ if (affinity->is_managed) {
+ irqd_set(&desc->irq_data, IRQD_AFFINITY_MANAGED);
+ irqd_set(&desc->irq_data, IRQD_MANAGED_SHUTDOWN);
+ }
+
+ cpumask_copy(desc->irq_common_data.affinity, &affinity->mask);
+
+ /* Restore the activation state */
+ if (activated)
+ irq_domain_activate_irq(&desc->irq_data, false);
+ return 0;
}
-
- /*
- * Deactivate the interrupt. That's required to undo
- * anything an earlier activation has established.
- */
- activated = irqd_is_activated(&desc->irq_data);
- if (activated)
- irq_domain_deactivate_irq(&desc->irq_data);
-
- if (affinity->is_managed) {
- irqd_set(&desc->irq_data, IRQD_AFFINITY_MANAGED);
- irqd_set(&desc->irq_data, IRQD_MANAGED_SHUTDOWN);
- }
-
- cpumask_copy(desc->irq_common_data.affinity, &affinity->mask);
-
- /* Restore the activation state */
- if (activated)
- irq_domain_activate_irq(&desc->irq_data, false);
-
-out_unlock:
- irq_put_desc_busunlock(desc, flags);
- return ret;
+ return -EINVAL;
}
static int __irq_set_affinity(unsigned int irq, const struct cpumask *mask,
^ permalink raw reply [flat|nested] 50+ messages in thread
* [patch 32/46] genirq/manage: Rework __irq_apply_affinity_hint()
2025-03-13 15:59 [patch 00/46] genirq: Cleanups and conversion to lock guards Thomas Gleixner
` (30 preceding siblings ...)
2025-03-13 16:00 ` [patch 31/46] genirq/manage: Rework irq_update_affinity_desc() Thomas Gleixner
@ 2025-03-13 16:00 ` Thomas Gleixner
2025-03-13 16:00 ` [patch 33/46] genirq/manage: Rework irq_set_vcpu_affinity() Thomas Gleixner
` (14 subsequent siblings)
46 siblings, 0 replies; 50+ messages in thread
From: Thomas Gleixner @ 2025-03-13 16:00 UTC (permalink / raw)
To: LKML; +Cc: Peter Zijlstra, Jiri Slaby
Use the new guards to get and lock the interrupt descriptor and tidy up the
code.
No functional change.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
kernel/irq/manage.c | 22 ++++++++++------------
1 file changed, 10 insertions(+), 12 deletions(-)
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -478,26 +478,24 @@ int irq_force_affinity(unsigned int irq,
}
EXPORT_SYMBOL_GPL(irq_force_affinity);
-int __irq_apply_affinity_hint(unsigned int irq, const struct cpumask *m,
- bool setaffinity)
+int __irq_apply_affinity_hint(unsigned int irq, const struct cpumask *m, bool setaffinity)
{
- unsigned long flags;
- struct irq_desc *desc = irq_get_desc_lock(irq, &flags, IRQ_GET_DESC_CHECK_GLOBAL);
+ int ret = -EINVAL;
- if (!desc)
- return -EINVAL;
- desc->affinity_hint = m;
- irq_put_desc_unlock(desc, flags);
- if (m && setaffinity)
+ scoped_irqdesc_get_and_lock(irq, IRQ_GET_DESC_CHECK_GLOBAL) {
+ scoped_irqdesc->affinity_hint = m;
+ ret = 0;
+ }
+
+ if (!ret && m && setaffinity)
__irq_set_affinity(irq, m, false);
- return 0;
+ return ret;
}
EXPORT_SYMBOL_GPL(__irq_apply_affinity_hint);
static void irq_affinity_notify(struct work_struct *work)
{
- struct irq_affinity_notify *notify =
- container_of(work, struct irq_affinity_notify, work);
+ struct irq_affinity_notify *notify = container_of(work, struct irq_affinity_notify, work);
struct irq_desc *desc = irq_to_desc(notify->irq);
cpumask_var_t cpumask;
^ permalink raw reply [flat|nested] 50+ messages in thread
* [patch 33/46] genirq/manage: Rework irq_set_vcpu_affinity()
2025-03-13 15:59 [patch 00/46] genirq: Cleanups and conversion to lock guards Thomas Gleixner
` (31 preceding siblings ...)
2025-03-13 16:00 ` [patch 32/46] genirq/manage: Rework __irq_apply_affinity_hint() Thomas Gleixner
@ 2025-03-13 16:00 ` Thomas Gleixner
2025-03-13 16:00 ` [patch 34/46] genirq/manage: Rework __disable_irq_nosync() Thomas Gleixner
` (13 subsequent siblings)
46 siblings, 0 replies; 50+ messages in thread
From: Thomas Gleixner @ 2025-03-13 16:00 UTC (permalink / raw)
To: LKML; +Cc: Peter Zijlstra, Jiri Slaby
Use the new guards to get and lock the interrupt descriptor and tidy up the
code.
No functional change.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
kernel/irq/manage.c | 40 +++++++++++++++++-----------------------
1 file changed, 17 insertions(+), 23 deletions(-)
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -627,32 +627,26 @@ int irq_setup_affinity(struct irq_desc *
*/
int irq_set_vcpu_affinity(unsigned int irq, void *vcpu_info)
{
- unsigned long flags;
- struct irq_desc *desc = irq_get_desc_lock(irq, &flags, 0);
- struct irq_data *data;
- struct irq_chip *chip;
- int ret = -ENOSYS;
+ scoped_irqdesc_get_and_lock(irq, 0) {
+ struct irq_desc *desc = scoped_irqdesc;
+ struct irq_data *data;
+ struct irq_chip *chip;
+ int ret = -ENOSYS;
- if (!desc)
- return -EINVAL;
+ data = irq_desc_get_irq_data(desc);
+ do {
+ chip = irq_data_get_irq_chip(data);
+ if (chip && chip->irq_set_vcpu_affinity)
+ break;
- data = irq_desc_get_irq_data(desc);
- do {
- chip = irq_data_get_irq_chip(data);
- if (chip && chip->irq_set_vcpu_affinity)
- break;
-#ifdef CONFIG_IRQ_DOMAIN_HIERARCHY
- data = data->parent_data;
-#else
- data = NULL;
-#endif
- } while (data);
+ data = irqd_get_parent_data(data);
+ } while (data);
- if (data)
- ret = chip->irq_set_vcpu_affinity(data, vcpu_info);
- irq_put_desc_unlock(desc, flags);
-
- return ret;
+ if (data)
+ ret = chip->irq_set_vcpu_affinity(data, vcpu_info);
+ return ret;
+ }
+ return -EINVAL;
}
EXPORT_SYMBOL_GPL(irq_set_vcpu_affinity);
^ permalink raw reply [flat|nested] 50+ messages in thread
* [patch 34/46] genirq/manage: Rework __disable_irq_nosync()
2025-03-13 15:59 [patch 00/46] genirq: Cleanups and conversion to lock guards Thomas Gleixner
` (32 preceding siblings ...)
2025-03-13 16:00 ` [patch 33/46] genirq/manage: Rework irq_set_vcpu_affinity() Thomas Gleixner
@ 2025-03-13 16:00 ` Thomas Gleixner
2025-03-13 16:00 ` [patch 35/46] genirq/manage: Rework enable_irq() Thomas Gleixner
` (12 subsequent siblings)
46 siblings, 0 replies; 50+ messages in thread
From: Thomas Gleixner @ 2025-03-13 16:00 UTC (permalink / raw)
To: LKML; +Cc: Peter Zijlstra, Jiri Slaby
Use the new guards to get and lock the interrupt descriptor and tidy up the
code.
No functional change.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
kernel/irq/manage.c | 13 +++++--------
1 file changed, 5 insertions(+), 8 deletions(-)
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -658,14 +658,11 @@ void __disable_irq(struct irq_desc *desc
static int __disable_irq_nosync(unsigned int irq)
{
- unsigned long flags;
- struct irq_desc *desc = irq_get_desc_buslock(irq, &flags, IRQ_GET_DESC_CHECK_GLOBAL);
-
- if (!desc)
- return -EINVAL;
- __disable_irq(desc);
- irq_put_desc_busunlock(desc, flags);
- return 0;
+ scoped_irqdesc_get_and_lock(irq, IRQ_GET_DESC_CHECK_GLOBAL) {
+ __disable_irq(scoped_irqdesc);
+ return 0;
+ }
+ return -EINVAL;
}
/**
^ permalink raw reply [flat|nested] 50+ messages in thread
* [patch 35/46] genirq/manage: Rework enable_irq()
2025-03-13 15:59 [patch 00/46] genirq: Cleanups and conversion to lock guards Thomas Gleixner
` (33 preceding siblings ...)
2025-03-13 16:00 ` [patch 34/46] genirq/manage: Rework __disable_irq_nosync() Thomas Gleixner
@ 2025-03-13 16:00 ` Thomas Gleixner
2025-03-13 16:00 ` [patch 36/46] genirq/manage: Rework irq_set_irq_wake() Thomas Gleixner
` (11 subsequent siblings)
46 siblings, 0 replies; 50+ messages in thread
From: Thomas Gleixner @ 2025-03-13 16:00 UTC (permalink / raw)
To: LKML; +Cc: Peter Zijlstra, Jiri Slaby
Use the new guards to get and lock the interrupt descriptor and tidy up the
code.
No functional change.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
kernel/irq/manage.c | 17 ++++++-----------
1 file changed, 6 insertions(+), 11 deletions(-)
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -788,18 +788,13 @@ void __enable_irq(struct irq_desc *desc)
*/
void enable_irq(unsigned int irq)
{
- unsigned long flags;
- struct irq_desc *desc = irq_get_desc_buslock(irq, &flags, IRQ_GET_DESC_CHECK_GLOBAL);
+ scoped_irqdesc_get_and_lock(irq, IRQ_GET_DESC_CHECK_GLOBAL) {
+ struct irq_desc *desc = scoped_irqdesc;
- if (!desc)
- return;
- if (WARN(!desc->irq_data.chip,
- KERN_ERR "enable_irq before setup/request_irq: irq %u\n", irq))
- goto out;
-
- __enable_irq(desc);
-out:
- irq_put_desc_busunlock(desc, flags);
+ if (WARN(!desc->irq_data.chip, "enable_irq before setup/request_irq: irq %u\n", irq))
+ return;
+ __enable_irq(desc);
+ }
}
EXPORT_SYMBOL(enable_irq);
^ permalink raw reply [flat|nested] 50+ messages in thread
* [patch 36/46] genirq/manage: Rework irq_set_irq_wake()
2025-03-13 15:59 [patch 00/46] genirq: Cleanups and conversion to lock guards Thomas Gleixner
` (34 preceding siblings ...)
2025-03-13 16:00 ` [patch 35/46] genirq/manage: Rework enable_irq() Thomas Gleixner
@ 2025-03-13 16:00 ` Thomas Gleixner
2025-03-13 16:00 ` [patch 37/46] genirq/manage: Rework can_request_irq() Thomas Gleixner
` (10 subsequent siblings)
46 siblings, 0 replies; 50+ messages in thread
From: Thomas Gleixner @ 2025-03-13 16:00 UTC (permalink / raw)
To: LKML; +Cc: Peter Zijlstra, Jiri Slaby
Use the new guards to get and lock the interrupt descriptor and tidy up the
code.
No functional change.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
kernel/irq/manage.c | 61 +++++++++++++++++++++++-----------------------------
1 file changed, 28 insertions(+), 33 deletions(-)
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -845,44 +845,39 @@ static int set_irq_wake_real(unsigned in
*/
int irq_set_irq_wake(unsigned int irq, unsigned int on)
{
- unsigned long flags;
- struct irq_desc *desc = irq_get_desc_buslock(irq, &flags, IRQ_GET_DESC_CHECK_GLOBAL);
- int ret = 0;
+ int ret = -EINVAL;
- if (!desc)
- return -EINVAL;
+ scoped_irqdesc_get_and_lock(irq, IRQ_GET_DESC_CHECK_GLOBAL) {
+ struct irq_desc *desc = scoped_irqdesc;
- /* Don't use NMIs as wake up interrupts please */
- if (irq_is_nmi(desc)) {
- ret = -EINVAL;
- goto out_unlock;
- }
+ /* Don't use NMIs as wake up interrupts please */
+ if (irq_is_nmi(desc))
+ return -EINVAL;
- /* wakeup-capable irqs can be shared between drivers that
- * don't need to have the same sleep mode behaviors.
- */
- if (on) {
- if (desc->wake_depth++ == 0) {
- ret = set_irq_wake_real(irq, on);
- if (ret)
- desc->wake_depth = 0;
- else
- irqd_set(&desc->irq_data, IRQD_WAKEUP_STATE);
- }
- } else {
- if (desc->wake_depth == 0) {
- WARN(1, "Unbalanced IRQ %d wake disable\n", irq);
- } else if (--desc->wake_depth == 0) {
- ret = set_irq_wake_real(irq, on);
- if (ret)
- desc->wake_depth = 1;
- else
- irqd_clear(&desc->irq_data, IRQD_WAKEUP_STATE);
+ /*
+ * wakeup-capable irqs can be shared between drivers that
+ * don't need to have the same sleep mode behaviors.
+ */
+ if (on) {
+ if (desc->wake_depth++ == 0) {
+ ret = set_irq_wake_real(irq, on);
+ if (ret)
+ desc->wake_depth = 0;
+ else
+ irqd_set(&desc->irq_data, IRQD_WAKEUP_STATE);
+ }
+ } else {
+ if (desc->wake_depth == 0) {
+ WARN(1, "Unbalanced IRQ %d wake disable\n", irq);
+ } else if (--desc->wake_depth == 0) {
+ ret = set_irq_wake_real(irq, on);
+ if (ret)
+ desc->wake_depth = 1;
+ else
+ irqd_clear(&desc->irq_data, IRQD_WAKEUP_STATE);
+ }
}
}
-
-out_unlock:
- irq_put_desc_busunlock(desc, flags);
return ret;
}
EXPORT_SYMBOL(irq_set_irq_wake);
^ permalink raw reply [flat|nested] 50+ messages in thread
* [patch 37/46] genirq/manage: Rework can_request_irq()
2025-03-13 15:59 [patch 00/46] genirq: Cleanups and conversion to lock guards Thomas Gleixner
` (35 preceding siblings ...)
2025-03-13 16:00 ` [patch 36/46] genirq/manage: Rework irq_set_irq_wake() Thomas Gleixner
@ 2025-03-13 16:00 ` Thomas Gleixner
2025-03-13 16:00 ` [patch 38/46] genirq/manage: Rework irq_set_parent() Thomas Gleixner
` (9 subsequent siblings)
46 siblings, 0 replies; 50+ messages in thread
From: Thomas Gleixner @ 2025-03-13 16:00 UTC (permalink / raw)
To: LKML; +Cc: Peter Zijlstra, Jiri Slaby
Use the new guards to get and lock the interrupt descriptor and tidy up the
code.
Make the return value boolean to reflect it's meaning.
No functional change.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
include/linux/irq.h | 2 +-
kernel/irq/manage.c | 21 ++++++++-------------
2 files changed, 9 insertions(+), 14 deletions(-)
--- a/include/linux/irq.h
+++ b/include/linux/irq.h
@@ -700,7 +700,7 @@ extern void note_interrupt(struct irq_de
extern int noirqdebug_setup(char *str);
/* Checks whether the interrupt can be requested by request_irq(): */
-extern int can_request_irq(unsigned int irq, unsigned long irqflags);
+extern bool can_request_irq(unsigned int irq, unsigned long irqflags);
/* Dummy irq-chip implementations: */
extern struct irq_chip no_irq_chip;
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -887,22 +887,17 @@ EXPORT_SYMBOL(irq_set_irq_wake);
* particular irq has been exclusively allocated or is available
* for driver use.
*/
-int can_request_irq(unsigned int irq, unsigned long irqflags)
+bool can_request_irq(unsigned int irq, unsigned long irqflags)
{
- unsigned long flags;
- struct irq_desc *desc = irq_get_desc_lock(irq, &flags, 0);
- int canrequest = 0;
+ scoped_irqdesc_get_and_lock(irq, IRQ_GET_DESC_CHECK_GLOBAL) {
+ struct irq_desc *desc = scoped_irqdesc;
- if (!desc)
- return 0;
-
- if (irq_settings_can_request(desc)) {
- if (!desc->action ||
- irqflags & desc->action->flags & IRQF_SHARED)
- canrequest = 1;
+ if (irq_settings_can_request(desc)) {
+ if (!desc->action || irqflags & desc->action->flags & IRQF_SHARED)
+ return true;
+ }
}
- irq_put_desc_unlock(desc, flags);
- return canrequest;
+ return false;
}
int __irq_set_trigger(struct irq_desc *desc, unsigned long flags)
^ permalink raw reply [flat|nested] 50+ messages in thread
* [patch 38/46] genirq/manage: Rework irq_set_parent()
2025-03-13 15:59 [patch 00/46] genirq: Cleanups and conversion to lock guards Thomas Gleixner
` (36 preceding siblings ...)
2025-03-13 16:00 ` [patch 37/46] genirq/manage: Rework can_request_irq() Thomas Gleixner
@ 2025-03-13 16:00 ` Thomas Gleixner
2025-03-13 16:00 ` [patch 39/46] genirq/manage: Rework enable_percpu_irq() Thomas Gleixner
` (8 subsequent siblings)
46 siblings, 0 replies; 50+ messages in thread
From: Thomas Gleixner @ 2025-03-13 16:00 UTC (permalink / raw)
To: LKML; +Cc: Peter Zijlstra, Jiri Slaby
Use the new guards to get and lock the interrupt descriptor and tidy up the
code.
No functional change.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
kernel/irq/manage.c | 15 +++++----------
1 file changed, 5 insertions(+), 10 deletions(-)
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -958,16 +958,11 @@ int __irq_set_trigger(struct irq_desc *d
#ifdef CONFIG_HARDIRQS_SW_RESEND
int irq_set_parent(int irq, int parent_irq)
{
- unsigned long flags;
- struct irq_desc *desc = irq_get_desc_lock(irq, &flags, 0);
-
- if (!desc)
- return -EINVAL;
-
- desc->parent_irq = parent_irq;
-
- irq_put_desc_unlock(desc, flags);
- return 0;
+ scoped_irqdesc_get_and_lock(irq, 0) {
+ scoped_irqdesc->parent_irq = parent_irq;
+ return 0;
+ }
+ return -EINVAL;
}
EXPORT_SYMBOL_GPL(irq_set_parent);
#endif
^ permalink raw reply [flat|nested] 50+ messages in thread
* [patch 39/46] genirq/manage: Rework enable_percpu_irq()
2025-03-13 15:59 [patch 00/46] genirq: Cleanups and conversion to lock guards Thomas Gleixner
` (37 preceding siblings ...)
2025-03-13 16:00 ` [patch 38/46] genirq/manage: Rework irq_set_parent() Thomas Gleixner
@ 2025-03-13 16:00 ` Thomas Gleixner
2025-03-13 16:00 ` [patch 40/46] genirq/manage: Rework irq_percpu_is_enabled() Thomas Gleixner
` (7 subsequent siblings)
46 siblings, 0 replies; 50+ messages in thread
From: Thomas Gleixner @ 2025-03-13 16:00 UTC (permalink / raw)
To: LKML; +Cc: Peter Zijlstra, Jiri Slaby
Use the new guards to get and lock the interrupt descriptor and tidy up the
code.
No functional change.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
kernel/irq/manage.c | 42 ++++++++++++++++--------------------------
1 file changed, 16 insertions(+), 26 deletions(-)
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -2285,35 +2285,25 @@ int request_nmi(unsigned int irq, irq_ha
void enable_percpu_irq(unsigned int irq, unsigned int type)
{
- unsigned int cpu = smp_processor_id();
- unsigned long flags;
- struct irq_desc *desc = irq_get_desc_lock(irq, &flags, IRQ_GET_DESC_CHECK_PERCPU);
+ scoped_irqdesc_get_and_lock(irq, IRQ_GET_DESC_CHECK_PERCPU) {
+ struct irq_desc *desc = scoped_irqdesc;
- if (!desc)
- return;
-
- /*
- * If the trigger type is not specified by the caller, then
- * use the default for this interrupt.
- */
- type &= IRQ_TYPE_SENSE_MASK;
- if (type == IRQ_TYPE_NONE)
- type = irqd_get_trigger_type(&desc->irq_data);
-
- if (type != IRQ_TYPE_NONE) {
- int ret;
-
- ret = __irq_set_trigger(desc, type);
-
- if (ret) {
- WARN(1, "failed to set type for IRQ%d\n", irq);
- goto out;
+ /*
+ * If the trigger type is not specified by the caller, then
+ * use the default for this interrupt.
+ */
+ type &= IRQ_TYPE_SENSE_MASK;
+ if (type == IRQ_TYPE_NONE)
+ type = irqd_get_trigger_type(&desc->irq_data);
+
+ if (type != IRQ_TYPE_NONE) {
+ if (__irq_set_trigger(desc, type)) {
+ WARN(1, "failed to set type for IRQ%d\n", irq);
+ return;
+ }
}
+ irq_percpu_enable(desc, smp_processor_id());
}
-
- irq_percpu_enable(desc, cpu);
-out:
- irq_put_desc_unlock(desc, flags);
}
EXPORT_SYMBOL_GPL(enable_percpu_irq);
^ permalink raw reply [flat|nested] 50+ messages in thread
* [patch 40/46] genirq/manage: Rework irq_percpu_is_enabled()
2025-03-13 15:59 [patch 00/46] genirq: Cleanups and conversion to lock guards Thomas Gleixner
` (38 preceding siblings ...)
2025-03-13 16:00 ` [patch 39/46] genirq/manage: Rework enable_percpu_irq() Thomas Gleixner
@ 2025-03-13 16:00 ` Thomas Gleixner
2025-03-13 16:00 ` [patch 41/46] genirq/manage: Rework disable_percpu_irq() Thomas Gleixner
` (6 subsequent siblings)
46 siblings, 0 replies; 50+ messages in thread
From: Thomas Gleixner @ 2025-03-13 16:00 UTC (permalink / raw)
To: LKML; +Cc: Peter Zijlstra, Jiri Slaby
Use the new guards to get and lock the interrupt descriptor and tidy up the
code.
No functional change.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
kernel/irq/manage.c | 16 +++-------------
1 file changed, 3 insertions(+), 13 deletions(-)
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -2321,19 +2321,9 @@ void enable_percpu_nmi(unsigned int irq,
*/
bool irq_percpu_is_enabled(unsigned int irq)
{
- unsigned int cpu = smp_processor_id();
- struct irq_desc *desc;
- unsigned long flags;
- bool is_enabled;
-
- desc = irq_get_desc_lock(irq, &flags, IRQ_GET_DESC_CHECK_PERCPU);
- if (!desc)
- return false;
-
- is_enabled = cpumask_test_cpu(cpu, desc->percpu_enabled);
- irq_put_desc_unlock(desc, flags);
-
- return is_enabled;
+ scoped_irqdesc_get_and_lock(irq, IRQ_GET_DESC_CHECK_PERCPU)
+ return cpumask_test_cpu(smp_processor_id(), scoped_irqdesc->percpu_enabled);
+ return false;
}
EXPORT_SYMBOL_GPL(irq_percpu_is_enabled);
^ permalink raw reply [flat|nested] 50+ messages in thread
* [patch 41/46] genirq/manage: Rework disable_percpu_irq()
2025-03-13 15:59 [patch 00/46] genirq: Cleanups and conversion to lock guards Thomas Gleixner
` (39 preceding siblings ...)
2025-03-13 16:00 ` [patch 40/46] genirq/manage: Rework irq_percpu_is_enabled() Thomas Gleixner
@ 2025-03-13 16:00 ` Thomas Gleixner
2025-03-13 16:00 ` [patch 42/46] genirq/manage: Rework prepare_percpu_nmi() Thomas Gleixner
` (5 subsequent siblings)
46 siblings, 0 replies; 50+ messages in thread
From: Thomas Gleixner @ 2025-03-13 16:00 UTC (permalink / raw)
To: LKML; +Cc: Peter Zijlstra, Jiri Slaby
Use the new guards to get and lock the interrupt descriptor and tidy up the
code.
No functional change.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
kernel/irq/manage.c | 11 ++---------
1 file changed, 2 insertions(+), 9 deletions(-)
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -2329,15 +2329,8 @@ EXPORT_SYMBOL_GPL(irq_percpu_is_enabled)
void disable_percpu_irq(unsigned int irq)
{
- unsigned int cpu = smp_processor_id();
- unsigned long flags;
- struct irq_desc *desc = irq_get_desc_lock(irq, &flags, IRQ_GET_DESC_CHECK_PERCPU);
-
- if (!desc)
- return;
-
- irq_percpu_disable(desc, cpu);
- irq_put_desc_unlock(desc, flags);
+ scoped_irqdesc_get_and_lock(irq, IRQ_GET_DESC_CHECK_PERCPU)
+ irq_percpu_disable(scoped_irqdesc, smp_processor_id());
}
EXPORT_SYMBOL_GPL(disable_percpu_irq);
^ permalink raw reply [flat|nested] 50+ messages in thread
* [patch 42/46] genirq/manage: Rework prepare_percpu_nmi()
2025-03-13 15:59 [patch 00/46] genirq: Cleanups and conversion to lock guards Thomas Gleixner
` (40 preceding siblings ...)
2025-03-13 16:00 ` [patch 41/46] genirq/manage: Rework disable_percpu_irq() Thomas Gleixner
@ 2025-03-13 16:00 ` Thomas Gleixner
2025-03-13 16:00 ` [patch 43/46] genirq/manage: Rework teardown_percpu_nmi() Thomas Gleixner
` (4 subsequent siblings)
46 siblings, 0 replies; 50+ messages in thread
From: Thomas Gleixner @ 2025-03-13 16:00 UTC (permalink / raw)
To: LKML; +Cc: Peter Zijlstra, Jiri Slaby
Use the new guards to get and lock the interrupt descriptor and tidy up the
code.
No functional change.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
kernel/irq/manage.c | 31 +++++++++----------------------
1 file changed, 9 insertions(+), 22 deletions(-)
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -2605,32 +2605,19 @@ int request_percpu_nmi(unsigned int irq,
*/
int prepare_percpu_nmi(unsigned int irq)
{
- unsigned long flags;
- struct irq_desc *desc;
- int ret = 0;
+ int ret = -EINVAL;
WARN_ON(preemptible());
- desc = irq_get_desc_lock(irq, &flags,
- IRQ_GET_DESC_CHECK_PERCPU);
- if (!desc)
- return -EINVAL;
-
- if (WARN(!irq_is_nmi(desc),
- KERN_ERR "prepare_percpu_nmi called for a non-NMI interrupt: irq %u\n",
- irq)) {
- ret = -EINVAL;
- goto out;
- }
-
- ret = irq_nmi_setup(desc);
- if (ret) {
- pr_err("Failed to setup NMI delivery: irq %u\n", irq);
- goto out;
+ scoped_irqdesc_get_and_lock(irq, IRQ_GET_DESC_CHECK_PERCPU) {
+ if (WARN(!irq_is_nmi(scoped_irqdesc),
+ "prepare_percpu_nmi called for a non-NMI interrupt: irq %u\n", irq))
+ return -EINVAL;
+
+ ret = irq_nmi_setup(scoped_irqdesc);
+ if (ret)
+ pr_err("Failed to setup NMI delivery: irq %u\n", irq);
}
-
-out:
- irq_put_desc_unlock(desc, flags);
return ret;
}
^ permalink raw reply [flat|nested] 50+ messages in thread
* [patch 43/46] genirq/manage: Rework teardown_percpu_nmi()
2025-03-13 15:59 [patch 00/46] genirq: Cleanups and conversion to lock guards Thomas Gleixner
` (41 preceding siblings ...)
2025-03-13 16:00 ` [patch 42/46] genirq/manage: Rework prepare_percpu_nmi() Thomas Gleixner
@ 2025-03-13 16:00 ` Thomas Gleixner
2025-03-13 16:00 ` [patch 44/46] genirq/manage: Rework irq_get_irqchip_state() Thomas Gleixner
` (3 subsequent siblings)
46 siblings, 0 replies; 50+ messages in thread
From: Thomas Gleixner @ 2025-03-13 16:00 UTC (permalink / raw)
To: LKML; +Cc: Peter Zijlstra, Jiri Slaby
Use the new guards to get and lock the interrupt descriptor and tidy up the
code.
No functional change.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
kernel/irq/manage.c | 19 +++++--------------
1 file changed, 5 insertions(+), 14 deletions(-)
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -2633,22 +2633,13 @@ int prepare_percpu_nmi(unsigned int irq)
*/
void teardown_percpu_nmi(unsigned int irq)
{
- unsigned long flags;
- struct irq_desc *desc;
-
WARN_ON(preemptible());
- desc = irq_get_desc_lock(irq, &flags,
- IRQ_GET_DESC_CHECK_PERCPU);
- if (!desc)
- return;
-
- if (WARN_ON(!irq_is_nmi(desc)))
- goto out;
-
- irq_nmi_teardown(desc);
-out:
- irq_put_desc_unlock(desc, flags);
+ scoped_irqdesc_get_and_lock(irq, IRQ_GET_DESC_CHECK_PERCPU) {
+ if (WARN_ON(!irq_is_nmi(scoped_irqdesc)))
+ return;
+ irq_nmi_teardown(scoped_irqdesc);
+ }
}
int __irq_get_irqchip_state(struct irq_data *data, enum irqchip_irq_state which,
^ permalink raw reply [flat|nested] 50+ messages in thread
* [patch 44/46] genirq/manage: Rework irq_get_irqchip_state()
2025-03-13 15:59 [patch 00/46] genirq: Cleanups and conversion to lock guards Thomas Gleixner
` (42 preceding siblings ...)
2025-03-13 16:00 ` [patch 43/46] genirq/manage: Rework teardown_percpu_nmi() Thomas Gleixner
@ 2025-03-13 16:00 ` Thomas Gleixner
2025-03-13 16:01 ` [patch 45/46] genirq/manage: Rework irq_set_irqchip_state() Thomas Gleixner
` (2 subsequent siblings)
46 siblings, 0 replies; 50+ messages in thread
From: Thomas Gleixner @ 2025-03-13 16:00 UTC (permalink / raw)
To: LKML; +Cc: Peter Zijlstra, Jiri Slaby
Use the new guards to get and lock the interrupt descriptor and tidy up the
code.
No functional change.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
kernel/irq/manage.c | 22 ++++++----------------
1 file changed, 6 insertions(+), 16 deletions(-)
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -2678,24 +2678,14 @@ int __irq_get_irqchip_state(struct irq_d
* This function should be called with preemption disabled if the interrupt
* controller has per-cpu registers.
*/
-int irq_get_irqchip_state(unsigned int irq, enum irqchip_irq_state which,
- bool *state)
+int irq_get_irqchip_state(unsigned int irq, enum irqchip_irq_state which, bool *state)
{
- struct irq_desc *desc;
- struct irq_data *data;
- unsigned long flags;
- int err = -EINVAL;
+ scoped_irqdesc_get_and_buslock(irq, 0) {
+ struct irq_data *data = irq_desc_get_irq_data(scoped_irqdesc);
- desc = irq_get_desc_buslock(irq, &flags, 0);
- if (!desc)
- return err;
-
- data = irq_desc_get_irq_data(desc);
-
- err = __irq_get_irqchip_state(data, which, state);
-
- irq_put_desc_busunlock(desc, flags);
- return err;
+ return __irq_get_irqchip_state(data, which, state);
+ }
+ return -EINVAL;
}
EXPORT_SYMBOL_GPL(irq_get_irqchip_state);
^ permalink raw reply [flat|nested] 50+ messages in thread
* [patch 45/46] genirq/manage: Rework irq_set_irqchip_state()
2025-03-13 15:59 [patch 00/46] genirq: Cleanups and conversion to lock guards Thomas Gleixner
` (43 preceding siblings ...)
2025-03-13 16:00 ` [patch 44/46] genirq/manage: Rework irq_get_irqchip_state() Thomas Gleixner
@ 2025-03-13 16:01 ` Thomas Gleixner
2025-03-13 16:01 ` [patch 46/46] genirq: Remove irq_[get|put]_desc*() Thomas Gleixner
2025-03-14 9:04 ` [patch 00/46] genirq: Cleanups and conversion to lock guards Peter Zijlstra
46 siblings, 0 replies; 50+ messages in thread
From: Thomas Gleixner @ 2025-03-13 16:01 UTC (permalink / raw)
To: LKML; +Cc: Peter Zijlstra, Jiri Slaby
Use the new guards to get and lock the interrupt descriptor and tidy up the
code.
No functional change.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
kernel/irq/manage.c | 53 +++++++++++++++++++---------------------------------
1 file changed, 20 insertions(+), 33 deletions(-)
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -2703,39 +2703,26 @@ EXPORT_SYMBOL_GPL(irq_get_irqchip_state)
*/
int irq_set_irqchip_state(unsigned int irq, enum irqchip_irq_state which, bool val)
{
- struct irq_desc *desc;
- struct irq_data *data;
- struct irq_chip *chip;
- unsigned long flags;
- int err = -EINVAL;
-
- desc = irq_get_desc_buslock(irq, &flags, 0);
- if (!desc)
- return err;
-
- data = irq_desc_get_irq_data(desc);
-
- do {
- chip = irq_data_get_irq_chip(data);
- if (WARN_ON_ONCE(!chip)) {
- err = -ENODEV;
- goto out_unlock;
- }
- if (chip->irq_set_irqchip_state)
- break;
-#ifdef CONFIG_IRQ_DOMAIN_HIERARCHY
- data = data->parent_data;
-#else
- data = NULL;
-#endif
- } while (data);
-
- if (data)
- err = chip->irq_set_irqchip_state(data, which, val);
-
-out_unlock:
- irq_put_desc_busunlock(desc, flags);
- return err;
+ scoped_irqdesc_get_and_buslock(irq, 0) {
+ struct irq_data *data = irq_desc_get_irq_data(scoped_irqdesc);
+ struct irq_chip *chip;
+
+ do {
+ chip = irq_data_get_irq_chip(data);
+
+ if (WARN_ON_ONCE(!chip))
+ return -ENODEV;
+
+ if (chip->irq_set_irqchip_state)
+ break;
+
+ data = irqd_get_parent_data(data);
+ } while (data);
+
+ if (data)
+ return chip->irq_set_irqchip_state(data, which, val);
+ }
+ return -EINVAL;
}
EXPORT_SYMBOL_GPL(irq_set_irqchip_state);
^ permalink raw reply [flat|nested] 50+ messages in thread
* [patch 46/46] genirq: Remove irq_[get|put]_desc*()
2025-03-13 15:59 [patch 00/46] genirq: Cleanups and conversion to lock guards Thomas Gleixner
` (44 preceding siblings ...)
2025-03-13 16:01 ` [patch 45/46] genirq/manage: Rework irq_set_irqchip_state() Thomas Gleixner
@ 2025-03-13 16:01 ` Thomas Gleixner
2025-03-14 9:04 ` [patch 00/46] genirq: Cleanups and conversion to lock guards Peter Zijlstra
46 siblings, 0 replies; 50+ messages in thread
From: Thomas Gleixner @ 2025-03-13 16:01 UTC (permalink / raw)
To: LKML; +Cc: Peter Zijlstra, Jiri Slaby
All users are converted to the guards. Remove the helpers.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
kernel/irq/internals.h | 24 ------------------------
1 file changed, 24 deletions(-)
--- a/kernel/irq/internals.h
+++ b/kernel/irq/internals.h
@@ -200,30 +200,6 @@ static inline class_irqdesc_lock_t class
#define scoped_irqdesc ((struct irq_desc *)(__guard_ptr(irqdesc_lock)(&scope)))
-static inline struct irq_desc *
-irq_get_desc_buslock(unsigned int irq, unsigned long *flags, unsigned int check)
-{
- return __irq_get_desc_lock(irq, flags, true, check);
-}
-
-static inline void
-irq_put_desc_busunlock(struct irq_desc *desc, unsigned long flags)
-{
- __irq_put_desc_unlock(desc, flags, true);
-}
-
-static inline struct irq_desc *
-irq_get_desc_lock(unsigned int irq, unsigned long *flags, unsigned int check)
-{
- return __irq_get_desc_lock(irq, flags, false, check);
-}
-
-static inline void
-irq_put_desc_unlock(struct irq_desc *desc, unsigned long flags)
-{
- __irq_put_desc_unlock(desc, flags, false);
-}
-
#define __irqd_to_state(d) ACCESS_PRIVATE((d)->common, state_use_accessors)
static inline unsigned int irqd_get(struct irq_data *d)
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [patch 00/46] genirq: Cleanups and conversion to lock guards
2025-03-13 15:59 [patch 00/46] genirq: Cleanups and conversion to lock guards Thomas Gleixner
` (45 preceding siblings ...)
2025-03-13 16:01 ` [patch 46/46] genirq: Remove irq_[get|put]_desc*() Thomas Gleixner
@ 2025-03-14 9:04 ` Peter Zijlstra
46 siblings, 0 replies; 50+ messages in thread
From: Peter Zijlstra @ 2025-03-14 9:04 UTC (permalink / raw)
To: Thomas Gleixner; +Cc: LKML, Jiri Slaby
On Thu, Mar 13, 2025 at 04:59:41PM +0100, Thomas Gleixner wrote:
> The generic interrupt core code has accumulated quite some inconsistencies
> over time and a common pattern in various API functions is:
>
> unsigned long flags;
> struct irq_desc *desc = irq_get_desc_[bus]lock(irq, &flags, mode);
>
> if (!desc)
> return -EINVAL;
> ....
> irq_put_desc_[bus]unlock(desc, flags);
>
> That's awkward and requires gotos in failure paths.
>
> This series provides conditional lock guards and converts the core code
> over to use those guards. Along with that it converts the other open coded
> lock/unlock pairs and fixes up coding and kernel doc formatting. The
> conversions were partially done with Coccinelle where possible.
I see you've chosen for the scoped_guard() variant here, as opposed to
the scoped_cond_guard() one :-)
Anyway, cursory reading of the patches show no obvious weirdness.
> include/linux/irq.h | 2
> kernel/irq/autoprobe.c | 26 -
> kernel/irq/chip.c | 640 ++++++++++----------------
> kernel/irq/cpuhotplug.c | 10
> kernel/irq/debugfs.c | 3
> kernel/irq/internals.h | 47 -
> kernel/irq/irqdesc.c | 136 +----
> kernel/irq/manage.c | 1154 ++++++++++++++++++++----------------------------
> kernel/irq/pm.c | 38 -
> kernel/irq/proc.c | 65 --
> kernel/irq/resend.c | 50 --
> kernel/irq/spurious.c | 104 +---
> 12 files changed, 920 insertions(+), 1355 deletions(-)
Nice!
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [patch 02/46] genirq/irqdesc: Switch to lock guards
2025-03-13 15:59 ` [patch 02/46] genirq/irqdesc: Switch to " Thomas Gleixner
@ 2025-03-14 10:57 ` Jiri Slaby
0 siblings, 0 replies; 50+ messages in thread
From: Jiri Slaby @ 2025-03-14 10:57 UTC (permalink / raw)
To: Thomas Gleixner, LKML; +Cc: Peter Zijlstra
On 13. 03. 25, 16:59, Thomas Gleixner wrote:
> Replace all lock/unlock pairs with lock guards and simplify the code flow.
>
> No functional change.
>
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
> ---
> kernel/irq/irqdesc.c | 136 +++++++++++++++------------------------------------
> 1 file changed, 42 insertions(+), 94 deletions(-)
>
> --- a/kernel/irq/irqdesc.c
> +++ b/kernel/irq/irqdesc.c
> @@ -266,104 +266,68 @@ static ssize_t per_cpu_count_show(struct
> }
> IRQ_ATTR_RO(per_cpu_count);
>
> -static ssize_t chip_name_show(struct kobject *kobj,
> - struct kobj_attribute *attr, char *buf)
> +static ssize_t chip_name_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
> {
> struct irq_desc *desc = container_of(kobj, struct irq_desc, kobj);
> - ssize_t ret = 0;
> -
> - raw_spin_lock_irq(&desc->lock);
> - if (desc->irq_data.chip && desc->irq_data.chip->name) {
> - ret = scnprintf(buf, PAGE_SIZE, "%s\n",
> - desc->irq_data.chip->name);
> - }
> - raw_spin_unlock_irq(&desc->lock);
>
> - return ret;
> + guard(raw_spinlock_irq)(&desc->lock);
> + if (desc->irq_data.chip && desc->irq_data.chip->name)
> + return scnprintf(buf, PAGE_SIZE, "%s\n", desc->irq_data.chip->name);
> + return 0;
FWIW I consider this ^^^ ...
> }
> IRQ_ATTR_RO(chip_name);
>
> -static ssize_t hwirq_show(struct kobject *kobj,
> - struct kobj_attribute *attr, char *buf)
> +static ssize_t hwirq_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
> {
> struct irq_desc *desc = container_of(kobj, struct irq_desc, kobj);
> - ssize_t ret = 0;
> -
> - raw_spin_lock_irq(&desc->lock);
> - if (desc->irq_data.domain)
> - ret = sprintf(buf, "%lu\n", desc->irq_data.hwirq);
> - raw_spin_unlock_irq(&desc->lock);
>
> - return ret;
> + guard(raw_spinlock_irq)(&desc->lock);
> + return desc->irq_data.domain ? sprintf(buf, "%lu\n", desc->irq_data.hwirq) : 0;
... more readable than this ^^^. (Ie. I would preserve the 'if'. Even
though here is only a simple condition.)
> }
> IRQ_ATTR_RO(hwirq);
> -static ssize_t name_show(struct kobject *kobj,
> - struct kobj_attribute *attr, char *buf)
> +static ssize_t name_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
> {
> struct irq_desc *desc = container_of(kobj, struct irq_desc, kobj);
> - ssize_t ret = 0;
>
> - raw_spin_lock_irq(&desc->lock);
> - if (desc->name)
> - ret = scnprintf(buf, PAGE_SIZE, "%s\n", desc->name);
> - raw_spin_unlock_irq(&desc->lock);
> -
> - return ret;
> + guard(raw_spinlock_irq)(&desc->lock);
You do guard() ...
> + return desc->name ? scnprintf(buf, PAGE_SIZE, "%s\n", desc->name) : 0;
> }
> IRQ_ATTR_RO(name);
>
> -static ssize_t actions_show(struct kobject *kobj,
> - struct kobj_attribute *attr, char *buf)
> +static ssize_t actions_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
> {
> struct irq_desc *desc = container_of(kobj, struct irq_desc, kobj);
> struct irqaction *action;
> ssize_t ret = 0;
> char *p = "";
>
> - raw_spin_lock_irq(&desc->lock);
> - for_each_action_of_desc(desc, action) {
> - ret += scnprintf(buf + ret, PAGE_SIZE - ret, "%s%s",
> - p, action->name);
> - p = ",";
> + scoped_guard (raw_spinlock_irq, &desc->lock) {
... but scoped_guard<space>(). Unlike in internals.h where you do
scoped_guard(). Any reason for that?
> + for_each_action_of_desc(desc, action) {
> + ret += scnprintf(buf + ret, PAGE_SIZE - ret, "%s%s", p, action->name);
> + p = ",";
> + }
> }
> - raw_spin_unlock_irq(&desc->lock);
> -
> - if (ret)
> - ret += scnprintf(buf + ret, PAGE_SIZE - ret, "\n");
>
> - return ret;
> + return ret ? ret + scnprintf(buf + ret, PAGE_SIZE - ret, "\n") : 0;
> }
> IRQ_ATTR_RO(actions);
...
> @@ -573,12 +532,12 @@ static int alloc_descs(unsigned int star
> return -ENOMEM;
> }
>
> -static int irq_expand_nr_irqs(unsigned int nr)
> +static bool irq_expand_nr_irqs(unsigned int nr)
> {
> if (nr > MAX_SPARSE_IRQS)
> - return -ENOMEM;
> + return false;
> nr_irqs = nr;
> - return 0;
> + return true;
This is sort of unrelated to $SUBJ ^^^. In any case:
> @@ -681,14 +638,13 @@ static inline int alloc_descs(unsigned i
>
> static int irq_expand_nr_irqs(unsigned int nr)
s/int/bool/ here too.
> {
> - return -ENOMEM;
> + return false;
> }
thanks,
--
js
suse labs
^ permalink raw reply [flat|nested] 50+ messages in thread
* Re: [patch 05/46] genirq/resend: Switch to lock guards
2025-03-13 15:59 ` [patch 05/46] genirq/resend: " Thomas Gleixner
@ 2025-03-17 8:22 ` Shrikanth Hegde
0 siblings, 0 replies; 50+ messages in thread
From: Shrikanth Hegde @ 2025-03-17 8:22 UTC (permalink / raw)
To: Thomas Gleixner, Peter Zijlstra; +Cc: Jiri Slaby, LKML
Hi Thomas.
On 3/13/25 21:29, Thomas Gleixner wrote:
> Convert all lock/unlock pairs to guards and tidy up the code.
>
> No functional change.
>
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
> ---
> kernel/irq/resend.c | 50 +++++++++++++++++++++-----------------------------
> 1 file changed, 21 insertions(+), 29 deletions(-)
>
> --- a/kernel/irq/resend.c
> +++ b/kernel/irq/resend.c
> @@ -30,18 +30,17 @@ static DEFINE_RAW_SPINLOCK(irq_resend_lo
> */
> static void resend_irqs(struct tasklet_struct *unused)
> {
> - struct irq_desc *desc;
> -
> - raw_spin_lock_irq(&irq_resend_lock);
> + guard(raw_spinlock_irq)(&irq_resend_lock);
> while (!hlist_empty(&irq_resend_list)) {
> - desc = hlist_entry(irq_resend_list.first, struct irq_desc,
> - resend_node);
> + struct irq_desc *desc;
> +
> + desc = hlist_entry(irq_resend_list.first, struct irq_desc, resend_node);
> hlist_del_init(&desc->resend_node);
> +
> raw_spin_unlock(&irq_resend_lock);
> desc->handle_irq(desc);
> raw_spin_lock(&irq_resend_lock);
> }
> - raw_spin_unlock_irq(&irq_resend_lock);
> }
>
> /* Tasklet to handle resend: */
> @@ -75,19 +74,18 @@ static int irq_sw_resend(struct irq_desc
> }
>
> /* Add to resend_list and activate the softirq: */
> - raw_spin_lock(&irq_resend_lock);
> - if (hlist_unhashed(&desc->resend_node))
> - hlist_add_head(&desc->resend_node, &irq_resend_list);
> - raw_spin_unlock(&irq_resend_lock);
> + scoped_guard (raw_spinlock, &irq_resend_lock) {
Nit: Any reason why it is "scoped_guard ()" instead of "scoped_guard()".
Is there a difference between the two?
I have seen in the current code base both are present, i would be nice
to have one of it no? or guideline on which one to use when?
> + if (hlist_unhashed(&desc->resend_node))
> + hlist_add_head(&desc->resend_node, &irq_resend_list);
> + }
> tasklet_schedule(&resend_tasklet);
> return 0;
> }
>
> void clear_irq_resend(struct irq_desc *desc)
> {
> - raw_spin_lock(&irq_resend_lock);
> + guard(raw_spinlock)(&irq_resend_lock);
> hlist_del_init(&desc->resend_node);
> - raw_spin_unlock(&irq_resend_lock);
> }
>
> void irq_resend_init(struct irq_desc *desc)
> @@ -172,30 +170,24 @@ int check_irq_resend(struct irq_desc *de
> */
> int irq_inject_interrupt(unsigned int irq)
> {
> - struct irq_desc *desc;
> - unsigned long flags;
> - int err;
> + int err = -EINVAL;
>
> /* Try the state injection hardware interface first */
> if (!irq_set_irqchip_state(irq, IRQCHIP_STATE_PENDING, true))
> return 0;
>
> /* That failed, try via the resend mechanism */
> - desc = irq_get_desc_buslock(irq, &flags, 0);
> - if (!desc)
> - return -EINVAL;
> + scoped_irqdesc_get_and_buslock(irq, 0) {
> + struct irq_desc *desc = scoped_irqdesc;
>
> - /*
> - * Only try to inject when the interrupt is:
> - * - not NMI type
> - * - activated
> - */
> - if (irq_is_nmi(desc) || !irqd_is_activated(&desc->irq_data))
> - err = -EINVAL;
> - else
> - err = check_irq_resend(desc, true);
> -
> - irq_put_desc_busunlock(desc, flags);
> + /*
> + * Only try to inject when the interrupt is:
> + * - not NMI type
> + * - activated
> + */
> + if (!irq_is_nmi(desc) && irqd_is_activated(&desc->irq_data))
> + err = check_irq_resend(desc, true);
> + }
> return err;
> }
> EXPORT_SYMBOL_GPL(irq_inject_interrupt);
>
>
^ permalink raw reply [flat|nested] 50+ messages in thread
end of thread, other threads:[~2025-03-17 8:23 UTC | newest]
Thread overview: 50+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-03-13 15:59 [patch 00/46] genirq: Cleanups and conversion to lock guards Thomas Gleixner
2025-03-13 15:59 ` [patch 01/46] genirq: Provide conditional " Thomas Gleixner
2025-03-13 15:59 ` [patch 02/46] genirq/irqdesc: Switch to " Thomas Gleixner
2025-03-14 10:57 ` Jiri Slaby
2025-03-13 15:59 ` [patch 03/46] genirq/autoprobe: " Thomas Gleixner
2025-03-13 15:59 ` [patch 04/46] genirq/pm: " Thomas Gleixner
2025-03-13 15:59 ` [patch 05/46] genirq/resend: " Thomas Gleixner
2025-03-17 8:22 ` Shrikanth Hegde
2025-03-13 15:59 ` [patch 06/46] genirq/proc: " Thomas Gleixner
2025-03-13 15:59 ` [patch 07/46] genirq/spurious: Cleanup code Thomas Gleixner
2025-03-13 15:59 ` [patch 08/46] genirq/spurious: Switch to lock guards Thomas Gleixner
2025-03-13 15:59 ` [patch 09/46] genirq/cpuhotplug: Convert " Thomas Gleixner
2025-03-13 15:59 ` [patch 10/46] genirq/debugfs: " Thomas Gleixner
2025-03-13 16:00 ` [patch 11/46] genirq/chip: Prepare for code reduction Thomas Gleixner
2025-03-13 16:00 ` [patch 12/46] genirq/chip: Rework handle_nested_irq() Thomas Gleixner
2025-03-13 16:00 ` [patch 13/46] genirq/chip: Rework handle_simple_irq() Thomas Gleixner
2025-03-13 16:00 ` [patch 14/46] genirq/chip: Rework handle_untracked_irq() Thomas Gleixner
2025-03-13 16:00 ` [patch 15/46] genirq/chip: Rework handle_level_irq() Thomas Gleixner
2025-03-13 16:00 ` [patch 16/46] genirq/chip: Rework handle_eoi_irq() Thomas Gleixner
2025-03-13 16:00 ` [patch 17/46] genirq/chip: Rework handle_edge_irq() Thomas Gleixner
2025-03-13 16:00 ` [patch 18/46] genirq/chip: Rework handle_edge_eoi_irq() Thomas Gleixner
2025-03-13 16:00 ` [patch 19/46] genirq/chip: Rework handle_fasteoi_ack_irq() Thomas Gleixner
2025-03-13 16:00 ` [patch 20/46] genirq/chip: Rework handle_fasteoi_mask_irq() Thomas Gleixner
2025-03-13 16:00 ` [patch 21/46] genirq/chip: Use lock guards where applicable Thomas Gleixner
2025-03-13 16:00 ` [patch 22/46] genirq/chip: Rework irq_set_chip() Thomas Gleixner
2025-03-13 16:00 ` [patch 23/46] genirq/chip: Rework irq_set_irq_type() Thomas Gleixner
2025-03-13 16:00 ` [patch 24/46] genirq/chip: Rework irq_set_handler_data() Thomas Gleixner
2025-03-13 16:00 ` [patch 25/46] genirq/chip: Rework irq_set_msi_desc_off() Thomas Gleixner
2025-03-13 16:00 ` [patch 26/46] genirq/chip: Rework irq_set_chip_data() Thomas Gleixner
2025-03-13 16:00 ` [patch 27/46] genirq/chip: Rework irq_set_handler() variants Thomas Gleixner
2025-03-13 16:00 ` [patch 28/46] genirq/chip: Rework irq_modify_status() Thomas Gleixner
2025-03-13 16:00 ` [patch 29/46] genirq/manage: Cleanup kernel doc comments Thomas Gleixner
2025-03-13 16:00 ` [patch 30/46] genirq/manage: Convert to lock guards Thomas Gleixner
2025-03-13 16:00 ` [patch 31/46] genirq/manage: Rework irq_update_affinity_desc() Thomas Gleixner
2025-03-13 16:00 ` [patch 32/46] genirq/manage: Rework __irq_apply_affinity_hint() Thomas Gleixner
2025-03-13 16:00 ` [patch 33/46] genirq/manage: Rework irq_set_vcpu_affinity() Thomas Gleixner
2025-03-13 16:00 ` [patch 34/46] genirq/manage: Rework __disable_irq_nosync() Thomas Gleixner
2025-03-13 16:00 ` [patch 35/46] genirq/manage: Rework enable_irq() Thomas Gleixner
2025-03-13 16:00 ` [patch 36/46] genirq/manage: Rework irq_set_irq_wake() Thomas Gleixner
2025-03-13 16:00 ` [patch 37/46] genirq/manage: Rework can_request_irq() Thomas Gleixner
2025-03-13 16:00 ` [patch 38/46] genirq/manage: Rework irq_set_parent() Thomas Gleixner
2025-03-13 16:00 ` [patch 39/46] genirq/manage: Rework enable_percpu_irq() Thomas Gleixner
2025-03-13 16:00 ` [patch 40/46] genirq/manage: Rework irq_percpu_is_enabled() Thomas Gleixner
2025-03-13 16:00 ` [patch 41/46] genirq/manage: Rework disable_percpu_irq() Thomas Gleixner
2025-03-13 16:00 ` [patch 42/46] genirq/manage: Rework prepare_percpu_nmi() Thomas Gleixner
2025-03-13 16:00 ` [patch 43/46] genirq/manage: Rework teardown_percpu_nmi() Thomas Gleixner
2025-03-13 16:00 ` [patch 44/46] genirq/manage: Rework irq_get_irqchip_state() Thomas Gleixner
2025-03-13 16:01 ` [patch 45/46] genirq/manage: Rework irq_set_irqchip_state() Thomas Gleixner
2025-03-13 16:01 ` [patch 46/46] genirq: Remove irq_[get|put]_desc*() Thomas Gleixner
2025-03-14 9:04 ` [patch 00/46] genirq: Cleanups and conversion to lock guards Peter Zijlstra
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox