xref: /linux/rust/kernel/irq/request.rs (revision 135d40523244dcad3c64eb2ce131cf018db5cff4)
1 // SPDX-License-Identifier: GPL-2.0
2 // SPDX-FileCopyrightText: Copyright 2025 Collabora ltd.
3 
4 //! This module provides types like [`Registration`] and
5 //! [`ThreadedRegistration`], which allow users to register handlers for a given
6 //! IRQ line.
7 
8 use core::marker::PhantomPinned;
9 
10 use crate::alloc::Allocator;
11 use crate::device::{Bound, Device};
12 use crate::devres::Devres;
13 use crate::error::to_result;
14 use crate::irq::flags::Flags;
15 use crate::prelude::*;
16 use crate::str::CStr;
17 use crate::sync::Arc;
18 
19 /// The value that can be returned from a [`Handler`] or a [`ThreadedHandler`].
20 #[repr(u32)]
21 pub enum IrqReturn {
22     /// The interrupt was not from this device or was not handled.
23     None = bindings::irqreturn_IRQ_NONE,
24 
25     /// The interrupt was handled by this device.
26     Handled = bindings::irqreturn_IRQ_HANDLED,
27 }
28 
29 /// Callbacks for an IRQ handler.
30 pub trait Handler: Sync {
31     /// The hard IRQ handler.
32     ///
33     /// This is executed in interrupt context, hence all corresponding
34     /// limitations do apply.
35     ///
36     /// All work that does not necessarily need to be executed from
37     /// interrupt context, should be deferred to a threaded handler.
38     /// See also [`ThreadedRegistration`].
39     fn handle(&self) -> IrqReturn;
40 }
41 
42 impl<T: ?Sized + Handler + Send> Handler for Arc<T> {
43     fn handle(&self) -> IrqReturn {
44         T::handle(self)
45     }
46 }
47 
48 impl<T: ?Sized + Handler, A: Allocator> Handler for Box<T, A> {
49     fn handle(&self) -> IrqReturn {
50         T::handle(self)
51     }
52 }
53 
54 /// # Invariants
55 ///
56 /// - `self.irq` is the same as the one passed to `request_{threaded}_irq`.
57 /// - `cookie` was passed to `request_{threaded}_irq` as the cookie. It is guaranteed to be unique
58 ///   by the type system, since each call to `new` will return a different instance of
59 ///   `Registration`.
60 #[pin_data(PinnedDrop)]
61 struct RegistrationInner {
62     irq: u32,
63     cookie: *mut c_void,
64 }
65 
66 impl RegistrationInner {
67     fn synchronize(&self) {
68         // SAFETY: safe as per the invariants of `RegistrationInner`
69         unsafe { bindings::synchronize_irq(self.irq) };
70     }
71 }
72 
73 #[pinned_drop]
74 impl PinnedDrop for RegistrationInner {
75     fn drop(self: Pin<&mut Self>) {
76         // SAFETY:
77         //
78         // Safe as per the invariants of `RegistrationInner` and:
79         //
80         // - The containing struct is `!Unpin` and was initialized using
81         // pin-init, so it occupied the same memory location for the entirety of
82         // its lifetime.
83         //
84         // Notice that this will block until all handlers finish executing,
85         // i.e.: at no point will &self be invalid while the handler is running.
86         unsafe { bindings::free_irq(self.irq, self.cookie) };
87     }
88 }
89 
90 // SAFETY: We only use `inner` on drop, which called at most once with no
91 // concurrent access.
92 unsafe impl Sync for RegistrationInner {}
93 
94 // SAFETY: It is safe to send `RegistrationInner` across threads.
95 unsafe impl Send for RegistrationInner {}
96 
97 /// A request for an IRQ line for a given device.
98 ///
99 /// # Invariants
100 ///
101 /// - `ìrq` is the number of an interrupt source of `dev`.
102 /// - `irq` has not been registered yet.
103 pub struct IrqRequest<'a> {
104     dev: &'a Device<Bound>,
105     irq: u32,
106 }
107 
108 impl<'a> IrqRequest<'a> {
109     /// Creates a new IRQ request for the given device and IRQ number.
110     ///
111     /// # Safety
112     ///
113     /// - `irq` should be a valid IRQ number for `dev`.
114     #[expect(dead_code)]
115     pub(crate) unsafe fn new(dev: &'a Device<Bound>, irq: u32) -> Self {
116         // INVARIANT: `irq` is a valid IRQ number for `dev`.
117         IrqRequest { dev, irq }
118     }
119 
120     /// Returns the IRQ number of an [`IrqRequest`].
121     pub fn irq(&self) -> u32 {
122         self.irq
123     }
124 }
125 
126 /// A registration of an IRQ handler for a given IRQ line.
127 ///
128 /// # Examples
129 ///
130 /// The following is an example of using `Registration`. It uses a
131 /// [`Completion`] to coordinate between the IRQ
132 /// handler and process context. [`Completion`] uses interior mutability, so the
133 /// handler can signal with [`Completion::complete_all()`] and the process
134 /// context can wait with [`Completion::wait_for_completion()`] even though
135 /// there is no way to get a mutable reference to the any of the fields in
136 /// `Data`.
137 ///
138 /// [`Completion`]: kernel::sync::Completion
139 /// [`Completion::complete_all()`]: kernel::sync::Completion::complete_all
140 /// [`Completion::wait_for_completion()`]: kernel::sync::Completion::wait_for_completion
141 ///
142 /// ```
143 /// use kernel::c_str;
144 /// use kernel::device::Bound;
145 /// use kernel::irq::{self, Flags, IrqRequest, IrqReturn, Registration};
146 /// use kernel::prelude::*;
147 /// use kernel::sync::{Arc, Completion};
148 ///
149 /// // Data shared between process and IRQ context.
150 /// #[pin_data]
151 /// struct Data {
152 ///     #[pin]
153 ///     completion: Completion,
154 /// }
155 ///
156 /// impl irq::Handler for Data {
157 ///     // Executed in IRQ context.
158 ///     fn handle(&self) -> IrqReturn {
159 ///         self.completion.complete_all();
160 ///         IrqReturn::Handled
161 ///     }
162 /// }
163 ///
164 /// // Registers an IRQ handler for the given IrqRequest.
165 /// //
166 /// // This runs in process context and assumes `request` was previously acquired from a device.
167 /// fn register_irq(
168 ///     handler: impl PinInit<Data, Error>,
169 ///     request: IrqRequest<'_>,
170 /// ) -> Result<Arc<Registration<Data>>> {
171 ///     let registration = Registration::new(request, Flags::SHARED, c_str!("my_device"), handler);
172 ///
173 ///     let registration = Arc::pin_init(registration, GFP_KERNEL)?;
174 ///
175 ///     registration.handler().completion.wait_for_completion();
176 ///
177 ///     Ok(registration)
178 /// }
179 /// # Ok::<(), Error>(())
180 /// ```
181 ///
182 /// # Invariants
183 ///
184 /// * We own an irq handler using `&self.handler` as its private data.
185 #[pin_data]
186 pub struct Registration<T: Handler + 'static> {
187     #[pin]
188     inner: Devres<RegistrationInner>,
189 
190     #[pin]
191     handler: T,
192 
193     /// Pinned because we need address stability so that we can pass a pointer
194     /// to the callback.
195     #[pin]
196     _pin: PhantomPinned,
197 }
198 
199 impl<T: Handler + 'static> Registration<T> {
200     /// Registers the IRQ handler with the system for the given IRQ number.
201     pub fn new<'a>(
202         request: IrqRequest<'a>,
203         flags: Flags,
204         name: &'static CStr,
205         handler: impl PinInit<T, Error> + 'a,
206     ) -> impl PinInit<Self, Error> + 'a {
207         try_pin_init!(&this in Self {
208             handler <- handler,
209             inner <- Devres::new(
210                 request.dev,
211                 try_pin_init!(RegistrationInner {
212                     // SAFETY: `this` is a valid pointer to the `Registration` instance
213                     cookie: unsafe { &raw mut (*this.as_ptr()).handler }.cast(),
214                     irq: {
215                         // SAFETY:
216                         // - The callbacks are valid for use with request_irq.
217                         // - If this succeeds, the slot is guaranteed to be valid until the
218                         //   destructor of Self runs, which will deregister the callbacks
219                         //   before the memory location becomes invalid.
220                         to_result(unsafe {
221                             bindings::request_irq(
222                                 request.irq,
223                                 Some(handle_irq_callback::<T>),
224                                 flags.into_inner(),
225                                 name.as_char_ptr(),
226                                 (&raw mut (*this.as_ptr()).handler).cast(),
227                             )
228                         })?;
229                         request.irq
230                     }
231                 })
232             ),
233             _pin: PhantomPinned,
234         })
235     }
236 
237     /// Returns a reference to the handler that was registered with the system.
238     pub fn handler(&self) -> &T {
239         &self.handler
240     }
241 
242     /// Wait for pending IRQ handlers on other CPUs.
243     ///
244     /// This will attempt to access the inner [`Devres`] container.
245     pub fn try_synchronize(&self) -> Result {
246         let inner = self.inner.try_access().ok_or(ENODEV)?;
247         inner.synchronize();
248         Ok(())
249     }
250 
251     /// Wait for pending IRQ handlers on other CPUs.
252     pub fn synchronize(&self, dev: &Device<Bound>) -> Result {
253         let inner = self.inner.access(dev)?;
254         inner.synchronize();
255         Ok(())
256     }
257 }
258 
259 /// # Safety
260 ///
261 /// This function should be only used as the callback in `request_irq`.
262 unsafe extern "C" fn handle_irq_callback<T: Handler>(_irq: i32, ptr: *mut c_void) -> c_uint {
263     // SAFETY: `ptr` is a pointer to T set in `Registration::new`
264     let handler = unsafe { &*(ptr as *const T) };
265     T::handle(handler) as c_uint
266 }
267 
268 /// The value that can be returned from [`ThreadedHandler::handle`].
269 #[repr(u32)]
270 pub enum ThreadedIrqReturn {
271     /// The interrupt was not from this device or was not handled.
272     None = bindings::irqreturn_IRQ_NONE,
273 
274     /// The interrupt was handled by this device.
275     Handled = bindings::irqreturn_IRQ_HANDLED,
276 
277     /// The handler wants the handler thread to wake up.
278     WakeThread = bindings::irqreturn_IRQ_WAKE_THREAD,
279 }
280 
281 /// Callbacks for a threaded IRQ handler.
282 pub trait ThreadedHandler: Sync {
283     /// The hard IRQ handler.
284     ///
285     /// This is executed in interrupt context, hence all corresponding
286     /// limitations do apply. All work that does not necessarily need to be
287     /// executed from interrupt context, should be deferred to the threaded
288     /// handler, i.e. [`ThreadedHandler::handle_threaded`].
289     ///
290     /// The default implementation returns [`ThreadedIrqReturn::WakeThread`].
291     fn handle(&self) -> ThreadedIrqReturn {
292         ThreadedIrqReturn::WakeThread
293     }
294 
295     /// The threaded IRQ handler.
296     ///
297     /// This is executed in process context. The kernel creates a dedicated
298     /// `kthread` for this purpose.
299     fn handle_threaded(&self) -> IrqReturn;
300 }
301 
302 impl<T: ?Sized + ThreadedHandler + Send> ThreadedHandler for Arc<T> {
303     fn handle(&self) -> ThreadedIrqReturn {
304         T::handle(self)
305     }
306 
307     fn handle_threaded(&self) -> IrqReturn {
308         T::handle_threaded(self)
309     }
310 }
311 
312 impl<T: ?Sized + ThreadedHandler, A: Allocator> ThreadedHandler for Box<T, A> {
313     fn handle(&self) -> ThreadedIrqReturn {
314         T::handle(self)
315     }
316 
317     fn handle_threaded(&self) -> IrqReturn {
318         T::handle_threaded(self)
319     }
320 }
321 
322 /// A registration of a threaded IRQ handler for a given IRQ line.
323 ///
324 /// Two callbacks are required: one to handle the IRQ, and one to handle any
325 /// other work in a separate thread.
326 ///
327 /// The thread handler is only called if the IRQ handler returns
328 /// [`ThreadedIrqReturn::WakeThread`].
329 ///
330 /// # Examples
331 ///
332 /// The following is an example of using [`ThreadedRegistration`]. It uses a
333 /// [`Mutex`](kernel::sync::Mutex) to provide interior mutability.
334 ///
335 /// ```
336 /// use kernel::c_str;
337 /// use kernel::device::Bound;
338 /// use kernel::irq::{
339 ///   self, Flags, IrqRequest, IrqReturn, ThreadedHandler, ThreadedIrqReturn,
340 ///   ThreadedRegistration,
341 /// };
342 /// use kernel::prelude::*;
343 /// use kernel::sync::{Arc, Mutex};
344 ///
345 /// // Declare a struct that will be passed in when the interrupt fires. The u32
346 /// // merely serves as an example of some internal data.
347 /// //
348 /// // [`irq::ThreadedHandler::handle`] takes `&self`. This example
349 /// // illustrates how interior mutability can be used when sharing the data
350 /// // between process context and IRQ context.
351 /// #[pin_data]
352 /// struct Data {
353 ///     #[pin]
354 ///     value: Mutex<u32>,
355 /// }
356 ///
357 /// impl ThreadedHandler for Data {
358 ///     // This will run (in a separate kthread) if and only if
359 ///     // [`ThreadedHandler::handle`] returns [`WakeThread`], which it does by
360 ///     // default.
361 ///     fn handle_threaded(&self) -> IrqReturn {
362 ///         let mut data = self.value.lock();
363 ///         *data += 1;
364 ///         IrqReturn::Handled
365 ///     }
366 /// }
367 ///
368 /// // Registers a threaded IRQ handler for the given [`IrqRequest`].
369 /// //
370 /// // This is executing in process context and assumes that `request` was
371 /// // previously acquired from a device.
372 /// fn register_threaded_irq(
373 ///     handler: impl PinInit<Data, Error>,
374 ///     request: IrqRequest<'_>,
375 /// ) -> Result<Arc<ThreadedRegistration<Data>>> {
376 ///     let registration =
377 ///         ThreadedRegistration::new(request, Flags::SHARED, c_str!("my_device"), handler);
378 ///
379 ///     let registration = Arc::pin_init(registration, GFP_KERNEL)?;
380 ///
381 ///     {
382 ///         // The data can be accessed from process context too.
383 ///         let mut data = registration.handler().value.lock();
384 ///         *data += 1;
385 ///     }
386 ///
387 ///     Ok(registration)
388 /// }
389 /// # Ok::<(), Error>(())
390 /// ```
391 ///
392 /// # Invariants
393 ///
394 /// * We own an irq handler using `&T` as its private data.
395 #[pin_data]
396 pub struct ThreadedRegistration<T: ThreadedHandler + 'static> {
397     #[pin]
398     inner: Devres<RegistrationInner>,
399 
400     #[pin]
401     handler: T,
402 
403     /// Pinned because we need address stability so that we can pass a pointer
404     /// to the callback.
405     #[pin]
406     _pin: PhantomPinned,
407 }
408 
409 impl<T: ThreadedHandler + 'static> ThreadedRegistration<T> {
410     /// Registers the IRQ handler with the system for the given IRQ number.
411     pub fn new<'a>(
412         request: IrqRequest<'a>,
413         flags: Flags,
414         name: &'static CStr,
415         handler: impl PinInit<T, Error> + 'a,
416     ) -> impl PinInit<Self, Error> + 'a {
417         try_pin_init!(&this in Self {
418             handler <- handler,
419             inner <- Devres::new(
420                 request.dev,
421                 try_pin_init!(RegistrationInner {
422                     // SAFETY: `this` is a valid pointer to the `ThreadedRegistration` instance.
423                     cookie: unsafe { &raw mut (*this.as_ptr()).handler }.cast(),
424                     irq: {
425                         // SAFETY:
426                         // - The callbacks are valid for use with request_threaded_irq.
427                         // - If this succeeds, the slot is guaranteed to be valid until the
428                         // destructor of Self runs, which will deregister the callbacks
429                         // before the memory location becomes invalid.
430                         to_result(unsafe {
431                             bindings::request_threaded_irq(
432                                 request.irq,
433                                 Some(handle_threaded_irq_callback::<T>),
434                                 Some(thread_fn_callback::<T>),
435                                 flags.into_inner(),
436                                 name.as_char_ptr(),
437                                 (&raw mut (*this.as_ptr()).handler).cast(),
438                             )
439                         })?;
440                         request.irq
441                     }
442                 })
443             ),
444             _pin: PhantomPinned,
445         })
446     }
447 
448     /// Returns a reference to the handler that was registered with the system.
449     pub fn handler(&self) -> &T {
450         &self.handler
451     }
452 
453     /// Wait for pending IRQ handlers on other CPUs.
454     ///
455     /// This will attempt to access the inner [`Devres`] container.
456     pub fn try_synchronize(&self) -> Result {
457         let inner = self.inner.try_access().ok_or(ENODEV)?;
458         inner.synchronize();
459         Ok(())
460     }
461 
462     /// Wait for pending IRQ handlers on other CPUs.
463     pub fn synchronize(&self, dev: &Device<Bound>) -> Result {
464         let inner = self.inner.access(dev)?;
465         inner.synchronize();
466         Ok(())
467     }
468 }
469 
470 /// # Safety
471 ///
472 /// This function should be only used as the callback in `request_threaded_irq`.
473 unsafe extern "C" fn handle_threaded_irq_callback<T: ThreadedHandler>(
474     _irq: i32,
475     ptr: *mut c_void,
476 ) -> c_uint {
477     // SAFETY: `ptr` is a pointer to T set in `ThreadedRegistration::new`
478     let handler = unsafe { &*(ptr as *const T) };
479     T::handle(handler) as c_uint
480 }
481 
482 /// # Safety
483 ///
484 /// This function should be only used as the callback in `request_threaded_irq`.
485 unsafe extern "C" fn thread_fn_callback<T: ThreadedHandler>(_irq: i32, ptr: *mut c_void) -> c_uint {
486     // SAFETY: `ptr` is a pointer to T set in `ThreadedRegistration::new`
487     let handler = unsafe { &*(ptr as *const T) };
488     T::handle_threaded(handler) as c_uint
489 }
490