[patch V2 26/45] genirq/chip: Rework irq_set_handler() variants

Thomas Gleixner posted 45 patches 7 months, 3 weeks ago
[patch V2 26/45] genirq/chip: Rework irq_set_handler() variants
Posted by Thomas Gleixner 7 months, 3 weeks ago
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);
Re: [patch V2 26/45] genirq/chip: Rework irq_set_handler() variants
Posted by Nathan Chancellor 7 months, 1 week ago
Hi Thomas,

On Tue, Apr 29, 2025 at 08:55:26AM +0200, Thomas Gleixner wrote:
> 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)

I am investigating some cases where

  WARN(!irqs_disabled(), "Interrupts were enabled early\n");

in start_kernel() in init/main.c is triggered in certain builds with
clang after patch 23 of this series (very bizarre since the conversion
seems to be correct) and I happened to notice that this conversion seems
to be incorrect? Should this be scoped_irqdesc_get_and_buslock() like
below?

> +		__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);
>  
> 
> 
>
Re: [patch V2 26/45] genirq/chip: Rework irq_set_handler() variants
Posted by Miguel Ojeda 7 months, 1 week ago
On Fri, 09 May 2025 14:22:11 +0100 Nathan Chancellor <nathan@kernel.org> wrote:
>
> I am investigating some cases where
>
> WARN(!irqs_disabled(), "Interrupts were enabled early\n");
>
> in start_kernel() in init/main.c is triggered in certain builds with
> clang after patch 23 of this series (very bizarre since the conversion
> seems to be correct) and I happened to notice that this conversion seems
> to be incorrect? Should this be scoped_irqdesc_get_and_buslock() like
> below?

Yeah, I am also seeing this in next-20250509 in a LLVM=1 arm64 defconfig + Rust
build under QEMU.

Cheers,
Miguel

[    0.007387] ------------[ cut here ]------------
[    0.007414] Interrupts were enabled early
[    0.007833] WARNING: CPU: 0 PID: 0 at init/main.c:1023 start_kernel+0x31c/0x394
[    0.008001] Modules linked in:
[    0.008340] CPU: 0 UID: 0 PID: 0 Comm: swapper/0 Not tainted 6.15.0-rc5-next-20250509 #1 PREEMPT
[    0.008458] Hardware name: linux,dummy-virt (DT)
[    0.008610] pstate: 60000005 (nZCv daif -PAN -UAO -TCO -DIT -SSBS BTYPE=--)
[    0.008641] pc : start_kernel+0x31c/0x394
[    0.008657] lr : start_kernel+0x31c/0x394
[    0.008670] sp : ffffdcd810333e80
[    0.008688] x29: ffffdcd810333e90 x28: 0000000000000000 x27: 0000000000000000
[    0.008748] x26: 0000000000000000 x25: 0000000000000000 x24: 0000000000000000
[    0.008762] x23: 0000000000000000 x22: 0000000000000000 x21: 0000000044200000
[    0.008775] x20: ffffdcd81033a000 x19: ffffdcd810345940 x18: 00000000000000b0
[    0.008789] x17: 0000000000000000 x16: 0000000000000008 x15: 0000000000000004
[    0.008802] x14: ffffdcd81036e830 x13: 0000000000000003 x12: 0000000000000003
[    0.008815] x11: 00000000ffffefff x10: 0000000000000000 x9 : 77ed5dd15956fc00
[    0.008849] x8 : 77ed5dd15956fc00 x7 : 2065726577207374 x6 : 7075727265746e49
[    0.008862] x5 : ffffdcd810886ef6 x4 : ffffdcd80fe025f2 x3 : 0000000000000000
[    0.008875] x2 : 0000000000000000 x1 : ffffdcd810333b80 x0 : 000000000000001d
[    0.008985] Call trace:
[    0.009142]  start_kernel+0x31c/0x394 (P)
[    0.009320]  __primary_switched+0x88/0x90
[    0.009501] ---[ end trace 0000000000000000 ]---

[    0.007587] ------------[ cut here ]------------
[    0.007623] Interrupts were enabled early
[    0.008277] WARNING: CPU: 0 PID: 0 at init/main.c:1023 start_kernel+0x31c/0x394
[    0.008526] Modules linked in:
[    0.009030] CPU: 0 UID: 0 PID: 0 Comm: swapper/0 Not tainted 6.15.0-rc5-next-20250509 #1 PREEMPT
[    0.009228] Hardware name: linux,dummy-virt (DT)
[    0.009459] pstate: 60000005 (nZCv daif -PAN -UAO -TCO -DIT -SSBS BTYPE=--)
[    0.009507] pc : start_kernel+0x31c/0x394
[    0.009531] lr : start_kernel+0x31c/0x394
[    0.009554] sp : ffffd5bfd7933e80
[    0.009585] x29: ffffd5bfd7933e90 x28: 0000000000000000 x27: 0000000000000000
[    0.009672] x26: 0000000000000000 x25: 0000000000000000 x24: 0000000000000000
[    0.009687] x23: 0000000000000000 x22: 0000000000000000 x21: 0000000044200000
[    0.009701] x20: ffffd5bfd793a000 x19: ffffd5bfd7945940 x18: 00000000000000b0
[    0.009715] x17: 0000000000000000 x16: 0000000000000008 x15: 0000000000000004
[    0.009729] x14: ffffd5bfd796e830 x13: 0000000000000003 x12: 0000000000000003
[    0.009743] x11: 00000000ffffefff x10: 0000000000000000 x9 : 2d9976f44ddcd000
[    0.009778] x8 : 2d9976f44ddcd000 x7 : 2065726577207374 x6 : 7075727265746e49
[    0.009792] x5 : ffffd5bfd7e86ef6 x4 : ffffd5bfd74025f2 x3 : 0000000000000000
[    0.009806] x2 : 0000000000000000 x1 : ffffd5bfd7933b80 x0 : 000000000000001d
[    0.009914] Call trace:
[    0.010060]  start_kernel+0x31c/0x394 (P)
[    0.010250]  __primary_switched+0x88/0x90
[    0.010458] ---[ end trace 0000000000000000 ]---
Re: [patch V2 26/45] genirq/chip: Rework irq_set_handler() variants
Posted by Nathan Chancellor 7 months, 1 week ago
On Sun, May 11, 2025 at 07:29:11PM +0200, Miguel Ojeda wrote:
> On Fri, 09 May 2025 14:22:11 +0100 Nathan Chancellor <nathan@kernel.org> wrote:
> >
> > I am investigating some cases where
> >
> > WARN(!irqs_disabled(), "Interrupts were enabled early\n");
> >
> > in start_kernel() in init/main.c is triggered in certain builds with
> > clang after patch 23 of this series (very bizarre since the conversion
> > seems to be correct) and I happened to notice that this conversion seems
> > to be incorrect? Should this be scoped_irqdesc_get_and_buslock() like
> > below?
> 
> Yeah, I am also seeing this in next-20250509 in a LLVM=1 arm64 defconfig + Rust
> build under QEMU.

I noticed that the warning was reproducible with just the first patch of
the series that adds the lock guards and patch 23 but also several other
individual patches within the series, as I could not just revert patch
23 on next-20250509 to fix it. I have no idea why yet because I have not
had the chance to actually sit down and dig into it but this diff fixes
every instance of the warning that I saw in my tests... :/ could be a
compiler bug or just some difference in behavior between compilers.

diff --git a/kernel/irq/internals.h b/kernel/irq/internals.h
index bd2db6ebb98e..94f463de8f26 100644
--- a/kernel/irq/internals.h
+++ b/kernel/irq/internals.h
@@ -176,10 +176,9 @@ __DEFINE_UNLOCK_GUARD(irqdesc_lock, struct irq_desc,
 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),
-	};
+	class_irqdesc_lock_t _t = {};
+	_t.bus	= bus;
+	_t.lock	= __irq_get_desc_lock(irq, &_t.flags, bus, check);
 	return _t;
 }
Re: [patch V2 26/45] genirq/chip: Rework irq_set_handler() variants
Posted by Jiri Slaby 7 months, 1 week ago
On 11. 05. 25, 19:49, Nathan Chancellor wrote:
> On Sun, May 11, 2025 at 07:29:11PM +0200, Miguel Ojeda wrote:
>> On Fri, 09 May 2025 14:22:11 +0100 Nathan Chancellor <nathan@kernel.org> wrote:
>>>
>>> I am investigating some cases where
>>>
>>> WARN(!irqs_disabled(), "Interrupts were enabled early\n");
>>>
>>> in start_kernel() in init/main.c is triggered in certain builds with
>>> clang after patch 23 of this series (very bizarre since the conversion
>>> seems to be correct) and I happened to notice that this conversion seems
>>> to be incorrect? Should this be scoped_irqdesc_get_and_buslock() like
>>> below?
>>
>> Yeah, I am also seeing this in next-20250509 in a LLVM=1 arm64 defconfig + Rust
>> build under QEMU.
> 
> I noticed that the warning was reproducible with just the first patch of
> the series that adds the lock guards and patch 23 but also several other
> individual patches within the series, as I could not just revert patch
> 23 on next-20250509 to fix it. I have no idea why yet because I have not
> had the chance to actually sit down and dig into it but this diff fixes
> every instance of the warning that I saw in my tests... :/ could be a
> compiler bug or just some difference in behavior between compilers.
> 
> diff --git a/kernel/irq/internals.h b/kernel/irq/internals.h
> index bd2db6ebb98e..94f463de8f26 100644
> --- a/kernel/irq/internals.h
> +++ b/kernel/irq/internals.h
> @@ -176,10 +176,9 @@ __DEFINE_UNLOCK_GUARD(irqdesc_lock, struct irq_desc,
>   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),

I assume the value stored by __irq_get_desc_lock() to &_t.flags is 
overwritten by 0 by the initializer. class_irqdesc_lock_t::flags is 
later than ::lock in the structure, so __irq_get_desc_lock() should be 
called, setting ::flags, then the initializer should set flags to 0.

> -	};
> +	class_irqdesc_lock_t _t = {};
> +	_t.bus	= bus;
> +	_t.lock	= __irq_get_desc_lock(irq, &_t.flags, bus, check);

That's why this works ^^.

>   	return _t;
>   }
>   


-- 
js
suse labs
Re: [patch V2 26/45] genirq/chip: Rework irq_set_handler() variants
Posted by Thomas Gleixner 7 months, 1 week ago
On Mon, May 12 2025 at 09:25, Jiri Slaby wrote:
> On 11. 05. 25, 19:49, Nathan Chancellor wrote:
>>   {
>> -	class_irqdesc_lock_t _t = {
>> -		.bus	= bus,
>> -		.lock	= __irq_get_desc_lock(irq, &_t.flags, bus, check),
>
> I assume the value stored by __irq_get_desc_lock() to &_t.flags is 
> overwritten by 0 by the initializer. class_irqdesc_lock_t::flags is 
> later than ::lock in the structure, so __irq_get_desc_lock() should be 
> called, setting ::flags, then the initializer should set flags to 0.

That's what you'd assume. But indeed the compiler might decide that
flags is uninitialized and then overwrite it after the initialized
fields :(

Nathan, can you please send a patch with a proper change log?

Thanks,

        tglx
Re: [patch V2 26/45] genirq/chip: Rework irq_set_handler() variants
Posted by Jiri Slaby 7 months, 1 week ago
On 12. 05. 25, 9:25, Jiri Slaby wrote:
> On 11. 05. 25, 19:49, Nathan Chancellor wrote:
>> On Sun, May 11, 2025 at 07:29:11PM +0200, Miguel Ojeda wrote:
>>> On Fri, 09 May 2025 14:22:11 +0100 Nathan Chancellor 
>>> <nathan@kernel.org> wrote:
>>>>
>>>> I am investigating some cases where
>>>>
>>>> WARN(!irqs_disabled(), "Interrupts were enabled early\n");
>>>>
>>>> in start_kernel() in init/main.c is triggered in certain builds with
>>>> clang after patch 23 of this series (very bizarre since the conversion
>>>> seems to be correct) and I happened to notice that this conversion 
>>>> seems
>>>> to be incorrect? Should this be scoped_irqdesc_get_and_buslock() like
>>>> below?
>>>
>>> Yeah, I am also seeing this in next-20250509 in a LLVM=1 arm64 
>>> defconfig + Rust
>>> build under QEMU.
>>
>> I noticed that the warning was reproducible with just the first patch of
>> the series that adds the lock guards and patch 23 but also several other
>> individual patches within the series, as I could not just revert patch
>> 23 on next-20250509 to fix it. I have no idea why yet because I have not
>> had the chance to actually sit down and dig into it but this diff fixes
>> every instance of the warning that I saw in my tests... :/ could be a
>> compiler bug or just some difference in behavior between compilers.
>>
>> diff --git a/kernel/irq/internals.h b/kernel/irq/internals.h
>> index bd2db6ebb98e..94f463de8f26 100644
>> --- a/kernel/irq/internals.h
>> +++ b/kernel/irq/internals.h
>> @@ -176,10 +176,9 @@ __DEFINE_UNLOCK_GUARD(irqdesc_lock, struct irq_desc,
>>   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),
> 
> I assume the value stored by __irq_get_desc_lock() to &_t.flags is 
> overwritten by 0 by the initializer. class_irqdesc_lock_t::flags is 
> later than ::lock in the structure, so __irq_get_desc_lock() should be 
> called, setting ::flags, then the initializer should set flags to 0.
> 
>> -    };
>> +    class_irqdesc_lock_t _t = {};
>> +    _t.bus    = bus;
>> +    _t.lock    = __irq_get_desc_lock(irq, &_t.flags, bus, check);
> 
> That's why this works ^^.

In fact, this should work around the issue too:
--- a/kernel/irq/internals.h
+++ b/kernel/irq/internals.h
@@ -178,6 +178,7 @@ static inline class_irqdesc_lock_t 
class_irqdesc_lock_constructor(unsigned int i
  {
         class_irqdesc_lock_t _t = {
                 .bus    = bus,
+               .flags  = 0,
                 .lock   = __irq_get_desc_lock(irq, &_t.flags, bus, check),
         };
         return _t;


-- 
js
suse labs

Re: [patch V2 26/45] genirq/chip: Rework irq_set_handler() variants
Posted by Jiri Slaby 7 months, 1 week ago
On 12. 05. 25, 9:32, Jiri Slaby wrote:
> On 12. 05. 25, 9:25, Jiri Slaby wrote:
>> On 11. 05. 25, 19:49, Nathan Chancellor wrote:
>>> On Sun, May 11, 2025 at 07:29:11PM +0200, Miguel Ojeda wrote:
>>>> On Fri, 09 May 2025 14:22:11 +0100 Nathan Chancellor 
>>>> <nathan@kernel.org> wrote:
>>>>>
>>>>> I am investigating some cases where
>>>>>
>>>>> WARN(!irqs_disabled(), "Interrupts were enabled early\n");
>>>>>
>>>>> in start_kernel() in init/main.c is triggered in certain builds with
>>>>> clang after patch 23 of this series (very bizarre since the conversion
>>>>> seems to be correct) and I happened to notice that this conversion 
>>>>> seems
>>>>> to be incorrect? Should this be scoped_irqdesc_get_and_buslock() like
>>>>> below?
>>>>
>>>> Yeah, I am also seeing this in next-20250509 in a LLVM=1 arm64 
>>>> defconfig + Rust
>>>> build under QEMU.
>>>
>>> I noticed that the warning was reproducible with just the first patch of
>>> the series that adds the lock guards and patch 23 but also several other
>>> individual patches within the series, as I could not just revert patch
>>> 23 on next-20250509 to fix it. I have no idea why yet because I have not
>>> had the chance to actually sit down and dig into it but this diff fixes
>>> every instance of the warning that I saw in my tests... :/ could be a
>>> compiler bug or just some difference in behavior between compilers.
>>>
>>> diff --git a/kernel/irq/internals.h b/kernel/irq/internals.h
>>> index bd2db6ebb98e..94f463de8f26 100644
>>> --- a/kernel/irq/internals.h
>>> +++ b/kernel/irq/internals.h
>>> @@ -176,10 +176,9 @@ __DEFINE_UNLOCK_GUARD(irqdesc_lock, struct 
>>> irq_desc,
>>>   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),
>>
>> I assume the value stored by __irq_get_desc_lock() to &_t.flags is 
>> overwritten by 0 by the initializer. class_irqdesc_lock_t::flags is 
>> later than ::lock in the structure, so __irq_get_desc_lock() should be 
>> called, setting ::flags, then the initializer should set flags to 0.
>>
>>> -    };
>>> +    class_irqdesc_lock_t _t = {};
>>> +    _t.bus    = bus;
>>> +    _t.lock    = __irq_get_desc_lock(irq, &_t.flags, bus, check);
>>
>> That's why this works ^^.
> 
> In fact, this should work around the issue too:

Or not. While the order of initializers is in order as specified, the 
order of side effects wrt to initialization is _unspecified_. So that 
&_t.flags setting can happen any time during initialization.

In sum, _t.flags has to be set out of the initialization for this to be 
working (as you suggested in the code above). Either before or after.

(Setting of .bus can remain in the initializer.)

> --- a/kernel/irq/internals.h
> +++ b/kernel/irq/internals.h
> @@ -178,6 +178,7 @@ static inline class_irqdesc_lock_t 
> class_irqdesc_lock_constructor(unsigned int i
>   {
>          class_irqdesc_lock_t _t = {
>                  .bus    = bus,
> +               .flags  = 0,
>                  .lock   = __irq_get_desc_lock(irq, &_t.flags, bus, check),
>          };
>          return _t;
> 
> 

-- 
js
suse labs

[tip: irq/core] genirq/chip: Rework irq_set_handler() variants
Posted by tip-bot2 for Thomas Gleixner 7 months, 2 weeks ago
The following commit has been merged into the irq/core branch of tip:

Commit-ID:     5cd05f3e23152b97e0be09938c78058395c3ee19
Gitweb:        https://git.kernel.org/tip/5cd05f3e23152b97e0be09938c78058395c3ee19
Author:        Thomas Gleixner <tglx@linutronix.de>
AuthorDate:    Tue, 29 Apr 2025 08:55:26 +02:00
Committer:     Thomas Gleixner <tglx@linutronix.de>
CommitterDate: Wed, 07 May 2025 09:08:14 +02:00

genirq/chip: Rework irq_set_handler() variants

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>
Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Link: https://lore.kernel.org/all/20250429065421.590753128@linutronix.de


---
 kernel/irq/chip.c | 34 +++++++++++-----------------------
 1 file changed, 11 insertions(+), 23 deletions(-)

diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c
index 2041225..7f1c640 100644
--- a/kernel/irq/chip.c
+++ b/kernel/irq/chip.c
@@ -941,35 +941,23 @@ __irq_do_set_handler(struct irq_desc *desc, irq_flow_handler_t handle,
 	}
 }
 
-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);
+	scoped_irqdesc_get_and_buslock(irq, 0) {
+		struct irq_desc *desc = scoped_irqdesc;
 
-	if (!desc)
-		return;
-
-	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);