Manipulating IRQ flags (i.e.: IRQF_*) will soon be necessary, specially to
register IRQ handlers through bindings::request_irq().
Add a kernel::irq::Flags for that purpose.
Signed-off-by: Daniel Almeida <daniel.almeida@collabora.com>
---
rust/kernel/irq.rs | 3 ++
rust/kernel/irq/flags.rs | 102 +++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 105 insertions(+)
diff --git a/rust/kernel/irq.rs b/rust/kernel/irq.rs
index fae7b15effc80c936d6bffbd5b4150000d6c2898..9abd9a6dc36f3e3ecc1f92ad7b0040176b56a079 100644
--- a/rust/kernel/irq.rs
+++ b/rust/kernel/irq.rs
@@ -9,3 +9,6 @@
//! drivers to register a handler for a given IRQ line.
//!
//! C header: [`include/linux/device.h`](srctree/include/linux/interrupt.h)
+
+/// Flags to be used when registering IRQ handlers.
+pub mod flags;
diff --git a/rust/kernel/irq/flags.rs b/rust/kernel/irq/flags.rs
new file mode 100644
index 0000000000000000000000000000000000000000..3cfaef65ae14f6c02f55ebcf4d52450c0052df30
--- /dev/null
+++ b/rust/kernel/irq/flags.rs
@@ -0,0 +1,102 @@
+// SPDX-License-Identifier: GPL-2.0
+// SPDX-FileCopyrightText: Copyright 2025 Collabora ltd.
+
+use crate::bindings;
+
+/// Flags to be used when registering IRQ handlers.
+///
+/// They can be combined with the operators `|`, `&`, and `!`.
+#[derive(Clone, Copy, PartialEq, Eq)]
+pub struct Flags(u64);
+
+impl Flags {
+ pub(crate) fn into_inner(self) -> u64 {
+ self.0
+ }
+}
+
+impl core::ops::BitOr for Flags {
+ type Output = Self;
+ fn bitor(self, rhs: Self) -> Self::Output {
+ Self(self.0 | rhs.0)
+ }
+}
+
+impl core::ops::BitAnd for Flags {
+ type Output = Self;
+ fn bitand(self, rhs: Self) -> Self::Output {
+ Self(self.0 & rhs.0)
+ }
+}
+
+impl core::ops::Not for Flags {
+ type Output = Self;
+ fn not(self) -> Self::Output {
+ Self(!self.0)
+ }
+}
+
+/// Use the interrupt line as already configured.
+pub const TRIGGER_NONE: Flags = Flags(bindings::IRQF_TRIGGER_NONE as u64);
+
+/// The interrupt is triggered when the signal goes from low to high.
+pub const TRIGGER_RISING: Flags = Flags(bindings::IRQF_TRIGGER_RISING as u64);
+
+/// The interrupt is triggered when the signal goes from high to low.
+pub const TRIGGER_FALLING: Flags = Flags(bindings::IRQF_TRIGGER_FALLING as u64);
+
+/// The interrupt is triggered while the signal is held high.
+pub const TRIGGER_HIGH: Flags = Flags(bindings::IRQF_TRIGGER_HIGH as u64);
+
+/// The interrupt is triggered while the signal is held low.
+pub const TRIGGER_LOW: Flags = Flags(bindings::IRQF_TRIGGER_LOW as u64);
+
+/// Allow sharing the irq among several devices.
+pub const SHARED: Flags = Flags(bindings::IRQF_SHARED as u64);
+
+/// Set by callers when they expect sharing mismatches to occur.
+pub const PROBE_SHARED: Flags = Flags(bindings::IRQF_PROBE_SHARED as u64);
+
+/// Flag to mark this interrupt as timer interrupt.
+pub const TIMER: Flags = Flags(bindings::IRQF_TIMER as u64);
+
+/// Interrupt is per cpu.
+pub const PERCPU: Flags = Flags(bindings::IRQF_PERCPU as u64);
+
+/// Flag to exclude this interrupt from irq balancing.
+pub const NOBALANCING: Flags = Flags(bindings::IRQF_NOBALANCING as u64);
+
+/// Interrupt is used for polling (only the interrupt that is registered
+/// first in a shared interrupt is considered for performance reasons).
+pub const IRQPOLL: Flags = Flags(bindings::IRQF_IRQPOLL as u64);
+
+/// Interrupt is not reenabled after the hardirq handler finished. Used by
+/// threaded interrupts which need to keep the irq line disabled until the
+/// threaded handler has been run.
+pub const ONESHOT: Flags = Flags(bindings::IRQF_ONESHOT as u64);
+
+/// Do not disable this IRQ during suspend. Does not guarantee that this
+/// interrupt will wake the system from a suspended state.
+pub const NO_SUSPEND: Flags = Flags(bindings::IRQF_NO_SUSPEND as u64);
+
+/// Force enable it on resume even if [`NO_SUSPEND`] is set.
+pub const FORCE_RESUME: Flags = Flags(bindings::IRQF_FORCE_RESUME as u64);
+
+/// Interrupt cannot be threaded.
+pub const NO_THREAD: Flags = Flags(bindings::IRQF_NO_THREAD as u64);
+
+/// Resume IRQ early during syscore instead of at device resume time.
+pub const EARLY_RESUME: Flags = Flags(bindings::IRQF_EARLY_RESUME as u64);
+
+/// If the IRQ is shared with a [`NO_SUSPEND`] user, execute this interrupt
+/// handler after suspending interrupts. For system wakeup devices users
+/// need to implement wakeup detection in their interrupt handlers.
+pub const COND_SUSPEND: Flags = Flags(bindings::IRQF_COND_SUSPEND as u64);
+
+/// Don't enable IRQ or NMI automatically when users request it. Users will
+/// enable it explicitly by `enable_irq` or `enable_nmi` later.
+pub const NO_AUTOEN: Flags = Flags(bindings::IRQF_NO_AUTOEN as u64);
+
+/// Exclude from runnaway detection for IPI and similar handlers, depends on
+/// `PERCPU`.
+pub const NO_DEBUG: Flags = Flags(bindings::IRQF_NO_DEBUG as u64);
--
2.50.0
Hi Daniel, On 7/3/25 9:30 PM, Daniel Almeida wrote: > +/// Flags to be used when registering IRQ handlers. > +/// > +/// They can be combined with the operators `|`, `&`, and `!`. > +#[derive(Clone, Copy, PartialEq, Eq)] > +pub struct Flags(u64); Why not Flags(u32)? You may get rid of all unnecessary casts later, plus save some extra bytes. > +/// Use the interrupt line as already configured. > +pub const TRIGGER_NONE: Flags = Flags(bindings::IRQF_TRIGGER_NONE as u64); > + > +/// The interrupt is triggered when the signal goes from low to high. > +pub const TRIGGER_RISING: Flags = Flags(bindings::IRQF_TRIGGER_RISING as u64); > + > +/// The interrupt is triggered when the signal goes from high to low. > +pub const TRIGGER_FALLING: Flags = Flags(bindings::IRQF_TRIGGER_FALLING as u64); > + > +/// The interrupt is triggered while the signal is held high. > +pub const TRIGGER_HIGH: Flags = Flags(bindings::IRQF_TRIGGER_HIGH as u64); > + > +/// The interrupt is triggered while the signal is held low. > +pub const TRIGGER_LOW: Flags = Flags(bindings::IRQF_TRIGGER_LOW as u64); > + > +/// Allow sharing the irq among several devices. nit: irq -> IRQ? > +pub const SHARED: Flags = Flags(bindings::IRQF_SHARED as u64); > + > +/// Set by callers when they expect sharing mismatches to occur. > +pub const PROBE_SHARED: Flags = Flags(bindings::IRQF_PROBE_SHARED as u64); > + > +/// Flag to mark this interrupt as timer interrupt. > +pub const TIMER: Flags = Flags(bindings::IRQF_TIMER as u64); > + > +/// Interrupt is per cpu. nit: cpu -> CPU? > +pub const PERCPU: Flags = Flags(bindings::IRQF_PERCPU as u64); Thanks! Daniel
On Fri, Jul 4, 2025 at 8:14 AM Daniel Sedlak <daniel@sedlak.dev> wrote: > > Why not Flags(u32)? You may get rid of all unnecessary casts later, plus > save some extra bytes. Yeah, avoiding the casts would be nice -- however it is done. On the patch: it wouldn't hurt to add an example for each of the operators too. Even better if it is a common use case of each (say, for `|`, a common combination of these flags). (By the way, the use of the `into_inner()` name here is another one we will want to discuss for the new naming guidelines table.) Thanks! Cheers, Miguel
On Fri, Jul 04, 2025 at 08:14:11AM +0200, Daniel Sedlak wrote:
> Hi Daniel,
>
> On 7/3/25 9:30 PM, Daniel Almeida wrote:
> > +/// Flags to be used when registering IRQ handlers.
> > +///
> > +/// They can be combined with the operators `|`, `&`, and `!`.
> > +#[derive(Clone, Copy, PartialEq, Eq)]
> > +pub struct Flags(u64);
>
> Why not Flags(u32)? You may get rid of all unnecessary casts later, plus
> save some extra bytes.
It looks like the C methods take an `unsigned long`. In that case, I'd
probably write the code to match that.
pub struct Flags(c_ulong);
and git rid of the cast when calling bindings::request_irq.
As for all the constants in this file, maybe it would be nice with a
private constructor that uses the same type as bindings to avoid the
casts?
impl Flags {
const fn new(value: u32) -> Flags {
...
}
}
/// Use the interrupt line as already configured.
pub const TRIGGER_NONE: Flags = Flags::new(bindings::IRQF_TRIGGER_NONE);
Not a big deal, but avoiding the cast when calling bindings::request_irq
is a good idea I think.
With that:
Reviewed-by: Alice Ryhl <aliceryhl@google.com>
Alice
Hi Alice,
> On 4 Jul 2025, at 04:42, Alice Ryhl <aliceryhl@google.com> wrote:
>
> On Fri, Jul 04, 2025 at 08:14:11AM +0200, Daniel Sedlak wrote:
>> Hi Daniel,
>>
>> On 7/3/25 9:30 PM, Daniel Almeida wrote:
>>> +/// Flags to be used when registering IRQ handlers.
>>> +///
>>> +/// They can be combined with the operators `|`, `&`, and `!`.
>>> +#[derive(Clone, Copy, PartialEq, Eq)]
>>> +pub struct Flags(u64);
>>
>> Why not Flags(u32)? You may get rid of all unnecessary casts later, plus
>> save some extra bytes.
>
> It looks like the C methods take an `unsigned long`. In that case, I'd
> probably write the code to match that.
>
> pub struct Flags(c_ulong);
>
> and git rid of the cast when calling bindings::request_irq.
>
> As for all the constants in this file, maybe it would be nice with a
> private constructor that uses the same type as bindings to avoid the
> casts?
>
> impl Flags {
> const fn new(value: u32) -> Flags {
> ...
> }
> }
Sure, but what goes here? This has to be "value as c_ulong” anyways so it
doesn’t really reduce the number of casts.
We should probably switch to Flags(u32) as Daniel Sedlak suggested. Then
it’s a matter of casting once for bindings::request_irq().
— Daniel
On Sat, Jul 12, 2025 at 6:27 PM Daniel Almeida
<daniel.almeida@collabora.com> wrote:
>
> Hi Alice,
>
> > On 4 Jul 2025, at 04:42, Alice Ryhl <aliceryhl@google.com> wrote:
> >
> > On Fri, Jul 04, 2025 at 08:14:11AM +0200, Daniel Sedlak wrote:
> >> Hi Daniel,
> >>
> >> On 7/3/25 9:30 PM, Daniel Almeida wrote:
> >>> +/// Flags to be used when registering IRQ handlers.
> >>> +///
> >>> +/// They can be combined with the operators `|`, `&`, and `!`.
> >>> +#[derive(Clone, Copy, PartialEq, Eq)]
> >>> +pub struct Flags(u64);
> >>
> >> Why not Flags(u32)? You may get rid of all unnecessary casts later, plus
> >> save some extra bytes.
> >
> > It looks like the C methods take an `unsigned long`. In that case, I'd
> > probably write the code to match that.
> >
> > pub struct Flags(c_ulong);
> >
> > and git rid of the cast when calling bindings::request_irq.
> >
> > As for all the constants in this file, maybe it would be nice with a
> > private constructor that uses the same type as bindings to avoid the
> > casts?
> >
> > impl Flags {
> > const fn new(value: u32) -> Flags {
> > ...
> > }
> > }
>
>
> Sure, but what goes here? This has to be "value as c_ulong” anyways so it
> doesn’t really reduce the number of casts.
>
> We should probably switch to Flags(u32) as Daniel Sedlak suggested. Then
> it’s a matter of casting once for bindings::request_irq().
IMO the advantage of doing it here is that we can fail compilation if
the cast is out of bounds, whereas the other cast is at runtime so we
can't do that.
Alice
> On 12 Jul 2025, at 17:03, Alice Ryhl <aliceryhl@google.com> wrote:
>
> On Sat, Jul 12, 2025 at 6:27 PM Daniel Almeida
> <daniel.almeida@collabora.com> wrote:
>>
>> Hi Alice,
>>
>>> On 4 Jul 2025, at 04:42, Alice Ryhl <aliceryhl@google.com> wrote:
>>>
>>> On Fri, Jul 04, 2025 at 08:14:11AM +0200, Daniel Sedlak wrote:
>>>> Hi Daniel,
>>>>
>>>> On 7/3/25 9:30 PM, Daniel Almeida wrote:
>>>>> +/// Flags to be used when registering IRQ handlers.
>>>>> +///
>>>>> +/// They can be combined with the operators `|`, `&`, and `!`.
>>>>> +#[derive(Clone, Copy, PartialEq, Eq)]
>>>>> +pub struct Flags(u64);
>>>>
>>>> Why not Flags(u32)? You may get rid of all unnecessary casts later, plus
>>>> save some extra bytes.
>>>
>>> It looks like the C methods take an `unsigned long`. In that case, I'd
>>> probably write the code to match that.
>>>
>>> pub struct Flags(c_ulong);
>>>
>>> and git rid of the cast when calling bindings::request_irq.
>>>
>>> As for all the constants in this file, maybe it would be nice with a
>>> private constructor that uses the same type as bindings to avoid the
>>> casts?
>>>
>>> impl Flags {
>>> const fn new(value: u32) -> Flags {
>>> ...
>>> }
>>> }
>>
>>
>> Sure, but what goes here? This has to be "value as c_ulong” anyways so it
>> doesn’t really reduce the number of casts.
>>
>> We should probably switch to Flags(u32) as Daniel Sedlak suggested. Then
>> it’s a matter of casting once for bindings::request_irq().
>
> IMO the advantage of doing it here is that we can fail compilation if
> the cast is out of bounds, whereas the other cast is at runtime so we
> can't do that.
>
> Alice
I’m not sure I am following. How is this compile-time checked?
>>> impl Flags {
>>> const fn new(value: u32) -> Flags {
>>> Self(value as c_ulong)
>>> }
Or perhaps I misunderstood you?
— Daniel
On Sat, Jul 12, 2025 at 10:49 PM Daniel Almeida
<daniel.almeida@collabora.com> wrote:
>
>
>
> > On 12 Jul 2025, at 17:03, Alice Ryhl <aliceryhl@google.com> wrote:
> >
> > On Sat, Jul 12, 2025 at 6:27 PM Daniel Almeida
> > <daniel.almeida@collabora.com> wrote:
> >>
> >> Hi Alice,
> >>
> >>> On 4 Jul 2025, at 04:42, Alice Ryhl <aliceryhl@google.com> wrote:
> >>>
> >>> On Fri, Jul 04, 2025 at 08:14:11AM +0200, Daniel Sedlak wrote:
> >>>> Hi Daniel,
> >>>>
> >>>> On 7/3/25 9:30 PM, Daniel Almeida wrote:
> >>>>> +/// Flags to be used when registering IRQ handlers.
> >>>>> +///
> >>>>> +/// They can be combined with the operators `|`, `&`, and `!`.
> >>>>> +#[derive(Clone, Copy, PartialEq, Eq)]
> >>>>> +pub struct Flags(u64);
> >>>>
> >>>> Why not Flags(u32)? You may get rid of all unnecessary casts later, plus
> >>>> save some extra bytes.
> >>>
> >>> It looks like the C methods take an `unsigned long`. In that case, I'd
> >>> probably write the code to match that.
> >>>
> >>> pub struct Flags(c_ulong);
> >>>
> >>> and git rid of the cast when calling bindings::request_irq.
> >>>
> >>> As for all the constants in this file, maybe it would be nice with a
> >>> private constructor that uses the same type as bindings to avoid the
> >>> casts?
> >>>
> >>> impl Flags {
> >>> const fn new(value: u32) -> Flags {
> >>> ...
> >>> }
> >>> }
> >>
> >>
> >> Sure, but what goes here? This has to be "value as c_ulong” anyways so it
> >> doesn’t really reduce the number of casts.
> >>
> >> We should probably switch to Flags(u32) as Daniel Sedlak suggested. Then
> >> it’s a matter of casting once for bindings::request_irq().
> >
> > IMO the advantage of doing it here is that we can fail compilation if
> > the cast is out of bounds, whereas the other cast is at runtime so we
> > can't do that.
> >
> > Alice
>
> I’m not sure I am following. How is this compile-time checked?
>
> >>> impl Flags {
> >>> const fn new(value: u32) -> Flags {
> >>> Self(value as c_ulong)
> >>> }
>
> Or perhaps I misunderstood you?
Well, that particular implementation would not be. But you could
implement it to compile-time check.
Alice
© 2016 - 2025 Red Hat, Inc.