xref: /linux/rust/kernel/irq/request.rs (revision 17e70f0c549f4a19da7d681d60b552901833f8f3)
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     pub(crate) unsafe fn new(dev: &'a Device<Bound>, irq: u32) -> Self {
115         // INVARIANT: `irq` is a valid IRQ number for `dev`.
116         IrqRequest { dev, irq }
117     }
118 
119     /// Returns the IRQ number of an [`IrqRequest`].
120     pub fn irq(&self) -> u32 {
121         self.irq
122     }
123 }
124 
125 /// A registration of an IRQ handler for a given IRQ line.
126 ///
127 /// # Examples
128 ///
129 /// The following is an example of using `Registration`. It uses a
130 /// [`Completion`] to coordinate between the IRQ
131 /// handler and process context. [`Completion`] uses interior mutability, so the
132 /// handler can signal with [`Completion::complete_all()`] and the process
133 /// context can wait with [`Completion::wait_for_completion()`] even though
134 /// there is no way to get a mutable reference to the any of the fields in
135 /// `Data`.
136 ///
137 /// [`Completion`]: kernel::sync::Completion
138 /// [`Completion::complete_all()`]: kernel::sync::Completion::complete_all
139 /// [`Completion::wait_for_completion()`]: kernel::sync::Completion::wait_for_completion
140 ///
141 /// ```
142 /// use kernel::c_str;
143 /// use kernel::device::Bound;
144 /// use kernel::irq::{self, Flags, IrqRequest, IrqReturn, Registration};
145 /// use kernel::prelude::*;
146 /// use kernel::sync::{Arc, Completion};
147 ///
148 /// // Data shared between process and IRQ context.
149 /// #[pin_data]
150 /// struct Data {
151 ///     #[pin]
152 ///     completion: Completion,
153 /// }
154 ///
155 /// impl irq::Handler for Data {
156 ///     // Executed in IRQ context.
157 ///     fn handle(&self) -> IrqReturn {
158 ///         self.completion.complete_all();
159 ///         IrqReturn::Handled
160 ///     }
161 /// }
162 ///
163 /// // Registers an IRQ handler for the given IrqRequest.
164 /// //
165 /// // This runs in process context and assumes `request` was previously acquired from a device.
166 /// fn register_irq(
167 ///     handler: impl PinInit<Data, Error>,
168 ///     request: IrqRequest<'_>,
169 /// ) -> Result<Arc<Registration<Data>>> {
170 ///     let registration = Registration::new(request, Flags::SHARED, c_str!("my_device"), handler);
171 ///
172 ///     let registration = Arc::pin_init(registration, GFP_KERNEL)?;
173 ///
174 ///     registration.handler().completion.wait_for_completion();
175 ///
176 ///     Ok(registration)
177 /// }
178 /// # Ok::<(), Error>(())
179 /// ```
180 ///
181 /// # Invariants
182 ///
183 /// * We own an irq handler using `&self.handler` as its private data.
184 #[pin_data]
185 pub struct Registration<T: Handler + 'static> {
186     #[pin]
187     inner: Devres<RegistrationInner>,
188 
189     #[pin]
190     handler: T,
191 
192     /// Pinned because we need address stability so that we can pass a pointer
193     /// to the callback.
194     #[pin]
195     _pin: PhantomPinned,
196 }
197 
198 impl<T: Handler + 'static> Registration<T> {
199     /// Registers the IRQ handler with the system for the given IRQ number.
200     pub fn new<'a>(
201         request: IrqRequest<'a>,
202         flags: Flags,
203         name: &'static CStr,
204         handler: impl PinInit<T, Error> + 'a,
205     ) -> impl PinInit<Self, Error> + 'a {
206         try_pin_init!(&this in Self {
207             handler <- handler,
208             inner <- Devres::new(
209                 request.dev,
210                 try_pin_init!(RegistrationInner {
211                     // SAFETY: `this` is a valid pointer to the `Registration` instance
212                     cookie: unsafe { &raw mut (*this.as_ptr()).handler }.cast(),
213                     irq: {
214                         // SAFETY:
215                         // - The callbacks are valid for use with request_irq.
216                         // - If this succeeds, the slot is guaranteed to be valid until the
217                         //   destructor of Self runs, which will deregister the callbacks
218                         //   before the memory location becomes invalid.
219                         to_result(unsafe {
220                             bindings::request_irq(
221                                 request.irq,
222                                 Some(handle_irq_callback::<T>),
223                                 flags.into_inner(),
224                                 name.as_char_ptr(),
225                                 (&raw mut (*this.as_ptr()).handler).cast(),
226                             )
227                         })?;
228                         request.irq
229                     }
230                 })
231             ),
232             _pin: PhantomPinned,
233         })
234     }
235 
236     /// Returns a reference to the handler that was registered with the system.
237     pub fn handler(&self) -> &T {
238         &self.handler
239     }
240 
241     /// Wait for pending IRQ handlers on other CPUs.
242     ///
243     /// This will attempt to access the inner [`Devres`] container.
244     pub fn try_synchronize(&self) -> Result {
245         let inner = self.inner.try_access().ok_or(ENODEV)?;
246         inner.synchronize();
247         Ok(())
248     }
249 
250     /// Wait for pending IRQ handlers on other CPUs.
251     pub fn synchronize(&self, dev: &Device<Bound>) -> Result {
252         let inner = self.inner.access(dev)?;
253         inner.synchronize();
254         Ok(())
255     }
256 }
257 
258 /// # Safety
259 ///
260 /// This function should be only used as the callback in `request_irq`.
261 unsafe extern "C" fn handle_irq_callback<T: Handler>(_irq: i32, ptr: *mut c_void) -> c_uint {
262     // SAFETY: `ptr` is a pointer to T set in `Registration::new`
263     let handler = unsafe { &*(ptr as *const T) };
264     T::handle(handler) as c_uint
265 }
266 
267 /// The value that can be returned from [`ThreadedHandler::handle`].
268 #[repr(u32)]
269 pub enum ThreadedIrqReturn {
270     /// The interrupt was not from this device or was not handled.
271     None = bindings::irqreturn_IRQ_NONE,
272 
273     /// The interrupt was handled by this device.
274     Handled = bindings::irqreturn_IRQ_HANDLED,
275 
276     /// The handler wants the handler thread to wake up.
277     WakeThread = bindings::irqreturn_IRQ_WAKE_THREAD,
278 }
279 
280 /// Callbacks for a threaded IRQ handler.
281 pub trait ThreadedHandler: Sync {
282     /// The hard IRQ handler.
283     ///
284     /// This is executed in interrupt context, hence all corresponding
285     /// limitations do apply. All work that does not necessarily need to be
286     /// executed from interrupt context, should be deferred to the threaded
287     /// handler, i.e. [`ThreadedHandler::handle_threaded`].
288     ///
289     /// The default implementation returns [`ThreadedIrqReturn::WakeThread`].
290     fn handle(&self) -> ThreadedIrqReturn {
291         ThreadedIrqReturn::WakeThread
292     }
293 
294     /// The threaded IRQ handler.
295     ///
296     /// This is executed in process context. The kernel creates a dedicated
297     /// `kthread` for this purpose.
298     fn handle_threaded(&self) -> IrqReturn;
299 }
300 
301 impl<T: ?Sized + ThreadedHandler + Send> ThreadedHandler for Arc<T> {
302     fn handle(&self) -> ThreadedIrqReturn {
303         T::handle(self)
304     }
305 
306     fn handle_threaded(&self) -> IrqReturn {
307         T::handle_threaded(self)
308     }
309 }
310 
311 impl<T: ?Sized + ThreadedHandler, A: Allocator> ThreadedHandler for Box<T, A> {
312     fn handle(&self) -> ThreadedIrqReturn {
313         T::handle(self)
314     }
315 
316     fn handle_threaded(&self) -> IrqReturn {
317         T::handle_threaded(self)
318     }
319 }
320 
321 /// A registration of a threaded IRQ handler for a given IRQ line.
322 ///
323 /// Two callbacks are required: one to handle the IRQ, and one to handle any
324 /// other work in a separate thread.
325 ///
326 /// The thread handler is only called if the IRQ handler returns
327 /// [`ThreadedIrqReturn::WakeThread`].
328 ///
329 /// # Examples
330 ///
331 /// The following is an example of using [`ThreadedRegistration`]. It uses a
332 /// [`Mutex`](kernel::sync::Mutex) to provide interior mutability.
333 ///
334 /// ```
335 /// use kernel::c_str;
336 /// use kernel::device::Bound;
337 /// use kernel::irq::{
338 ///   self, Flags, IrqRequest, IrqReturn, ThreadedHandler, ThreadedIrqReturn,
339 ///   ThreadedRegistration,
340 /// };
341 /// use kernel::prelude::*;
342 /// use kernel::sync::{Arc, Mutex};
343 ///
344 /// // Declare a struct that will be passed in when the interrupt fires. The u32
345 /// // merely serves as an example of some internal data.
346 /// //
347 /// // [`irq::ThreadedHandler::handle`] takes `&self`. This example
348 /// // illustrates how interior mutability can be used when sharing the data
349 /// // between process context and IRQ context.
350 /// #[pin_data]
351 /// struct Data {
352 ///     #[pin]
353 ///     value: Mutex<u32>,
354 /// }
355 ///
356 /// impl ThreadedHandler for Data {
357 ///     // This will run (in a separate kthread) if and only if
358 ///     // [`ThreadedHandler::handle`] returns [`WakeThread`], which it does by
359 ///     // default.
360 ///     fn handle_threaded(&self) -> IrqReturn {
361 ///         let mut data = self.value.lock();
362 ///         *data += 1;
363 ///         IrqReturn::Handled
364 ///     }
365 /// }
366 ///
367 /// // Registers a threaded IRQ handler for the given [`IrqRequest`].
368 /// //
369 /// // This is executing in process context and assumes that `request` was
370 /// // previously acquired from a device.
371 /// fn register_threaded_irq(
372 ///     handler: impl PinInit<Data, Error>,
373 ///     request: IrqRequest<'_>,
374 /// ) -> Result<Arc<ThreadedRegistration<Data>>> {
375 ///     let registration =
376 ///         ThreadedRegistration::new(request, Flags::SHARED, c_str!("my_device"), handler);
377 ///
378 ///     let registration = Arc::pin_init(registration, GFP_KERNEL)?;
379 ///
380 ///     {
381 ///         // The data can be accessed from process context too.
382 ///         let mut data = registration.handler().value.lock();
383 ///         *data += 1;
384 ///     }
385 ///
386 ///     Ok(registration)
387 /// }
388 /// # Ok::<(), Error>(())
389 /// ```
390 ///
391 /// # Invariants
392 ///
393 /// * We own an irq handler using `&T` as its private data.
394 #[pin_data]
395 pub struct ThreadedRegistration<T: ThreadedHandler + 'static> {
396     #[pin]
397     inner: Devres<RegistrationInner>,
398 
399     #[pin]
400     handler: T,
401 
402     /// Pinned because we need address stability so that we can pass a pointer
403     /// to the callback.
404     #[pin]
405     _pin: PhantomPinned,
406 }
407 
408 impl<T: ThreadedHandler + 'static> ThreadedRegistration<T> {
409     /// Registers the IRQ handler with the system for the given IRQ number.
410     pub fn new<'a>(
411         request: IrqRequest<'a>,
412         flags: Flags,
413         name: &'static CStr,
414         handler: impl PinInit<T, Error> + 'a,
415     ) -> impl PinInit<Self, Error> + 'a {
416         try_pin_init!(&this in Self {
417             handler <- handler,
418             inner <- Devres::new(
419                 request.dev,
420                 try_pin_init!(RegistrationInner {
421                     // SAFETY: `this` is a valid pointer to the `ThreadedRegistration` instance.
422                     cookie: unsafe { &raw mut (*this.as_ptr()).handler }.cast(),
423                     irq: {
424                         // SAFETY:
425                         // - The callbacks are valid for use with request_threaded_irq.
426                         // - If this succeeds, the slot is guaranteed to be valid until the
427                         // destructor of Self runs, which will deregister the callbacks
428                         // before the memory location becomes invalid.
429                         to_result(unsafe {
430                             bindings::request_threaded_irq(
431                                 request.irq,
432                                 Some(handle_threaded_irq_callback::<T>),
433                                 Some(thread_fn_callback::<T>),
434                                 flags.into_inner(),
435                                 name.as_char_ptr(),
436                                 (&raw mut (*this.as_ptr()).handler).cast(),
437                             )
438                         })?;
439                         request.irq
440                     }
441                 })
442             ),
443             _pin: PhantomPinned,
444         })
445     }
446 
447     /// Returns a reference to the handler that was registered with the system.
448     pub fn handler(&self) -> &T {
449         &self.handler
450     }
451 
452     /// Wait for pending IRQ handlers on other CPUs.
453     ///
454     /// This will attempt to access the inner [`Devres`] container.
455     pub fn try_synchronize(&self) -> Result {
456         let inner = self.inner.try_access().ok_or(ENODEV)?;
457         inner.synchronize();
458         Ok(())
459     }
460 
461     /// Wait for pending IRQ handlers on other CPUs.
462     pub fn synchronize(&self, dev: &Device<Bound>) -> Result {
463         let inner = self.inner.access(dev)?;
464         inner.synchronize();
465         Ok(())
466     }
467 }
468 
469 /// # Safety
470 ///
471 /// This function should be only used as the callback in `request_threaded_irq`.
472 unsafe extern "C" fn handle_threaded_irq_callback<T: ThreadedHandler>(
473     _irq: i32,
474     ptr: *mut c_void,
475 ) -> c_uint {
476     // SAFETY: `ptr` is a pointer to T set in `ThreadedRegistration::new`
477     let handler = unsafe { &*(ptr as *const T) };
478     T::handle(handler) as c_uint
479 }
480 
481 /// # Safety
482 ///
483 /// This function should be only used as the callback in `request_threaded_irq`.
484 unsafe extern "C" fn thread_fn_callback<T: ThreadedHandler>(_irq: i32, ptr: *mut c_void) -> c_uint {
485     // SAFETY: `ptr` is a pointer to T set in `ThreadedRegistration::new`
486     let handler = unsafe { &*(ptr as *const T) };
487     T::handle_threaded(handler) as c_uint
488 }
489