Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

rust: platform: add irq accessors

These accessors can be used to retrieve a irq::Registration and
irq::ThreadedRegistration from a platform device by
index or name. Alternatively, drivers can retrieve an IrqRequest from a
bound platform device for later use.

These accessors ensure that only valid IRQ lines can ever be registered.

Reviewed-by: Alice Ryhl <aliceryhl@google.com>
Tested-by: Joel Fernandes <joelagnelf@nvidia.com>
Tested-by: Dirk Behme <dirk.behme@de.bosch.com>
Signed-off-by: Daniel Almeida <daniel.almeida@collabora.com>
Link: https://lore.kernel.org/r/20250811-topics-tyr-request_irq2-v9-5-0485dcd9bcbf@collabora.com
[ Remove expect(dead_code) from IrqRequest::new(), re-format macros and
macro invocations to not exceed 100 characters line length. - Danilo ]
Signed-off-by: Danilo Krummrich <dakr@kernel.org>

authored by

Daniel Almeida and committed by
Danilo Krummrich
17e70f0c 135d4052

+176 -1
-1
rust/kernel/irq/request.rs
··· 111 111 /// # Safety 112 112 /// 113 113 /// - `irq` should be a valid IRQ number for `dev`. 114 - #[expect(dead_code)] 115 114 pub(crate) unsafe fn new(dev: &'a Device<Bound>, irq: u32) -> Self { 116 115 // INVARIANT: `irq` is a valid IRQ number for `dev`. 117 116 IrqRequest { dev, irq }
+176
rust/kernel/platform.rs
··· 10 10 driver, 11 11 error::{from_result, to_result, Result}, 12 12 io::{mem::IoRequest, Resource}, 13 + irq::{self, IrqRequest}, 13 14 of, 14 15 prelude::*, 15 16 types::Opaque, ··· 283 282 // lifetime of the `IoRequest`. 284 283 .map(|resource| unsafe { IoRequest::new(self.as_ref(), resource) }) 285 284 } 285 + } 286 + 287 + macro_rules! define_irq_accessor_by_index { 288 + ( 289 + $(#[$meta:meta])* $fn_name:ident, 290 + $request_fn:ident, 291 + $reg_type:ident, 292 + $handler_trait:ident 293 + ) => { 294 + $(#[$meta])* 295 + pub fn $fn_name<'a, T: irq::$handler_trait + 'static>( 296 + &'a self, 297 + flags: irq::Flags, 298 + index: u32, 299 + name: &'static CStr, 300 + handler: impl PinInit<T, Error> + 'a, 301 + ) -> Result<impl PinInit<irq::$reg_type<T>, Error> + 'a> { 302 + let request = self.$request_fn(index)?; 303 + 304 + Ok(irq::$reg_type::<T>::new( 305 + request, 306 + flags, 307 + name, 308 + handler, 309 + )) 310 + } 311 + }; 312 + } 313 + 314 + macro_rules! define_irq_accessor_by_name { 315 + ( 316 + $(#[$meta:meta])* $fn_name:ident, 317 + $request_fn:ident, 318 + $reg_type:ident, 319 + $handler_trait:ident 320 + ) => { 321 + $(#[$meta])* 322 + pub fn $fn_name<'a, T: irq::$handler_trait + 'static>( 323 + &'a self, 324 + flags: irq::Flags, 325 + irq_name: &CStr, 326 + name: &'static CStr, 327 + handler: impl PinInit<T, Error> + 'a, 328 + ) -> Result<impl PinInit<irq::$reg_type<T>, Error> + 'a> { 329 + let request = self.$request_fn(irq_name)?; 330 + 331 + Ok(irq::$reg_type::<T>::new( 332 + request, 333 + flags, 334 + name, 335 + handler, 336 + )) 337 + } 338 + }; 339 + } 340 + 341 + impl Device<Bound> { 342 + /// Returns an [`IrqRequest`] for the IRQ at the given index, if any. 343 + pub fn irq_by_index(&self, index: u32) -> Result<IrqRequest<'_>> { 344 + // SAFETY: `self.as_raw` returns a valid pointer to a `struct platform_device`. 345 + let irq = unsafe { bindings::platform_get_irq(self.as_raw(), index) }; 346 + 347 + if irq < 0 { 348 + return Err(Error::from_errno(irq)); 349 + } 350 + 351 + // SAFETY: `irq` is guaranteed to be a valid IRQ number for `&self`. 352 + Ok(unsafe { IrqRequest::new(self.as_ref(), irq as u32) }) 353 + } 354 + 355 + /// Returns an [`IrqRequest`] for the IRQ at the given index, but does not 356 + /// print an error if the IRQ cannot be obtained. 357 + pub fn optional_irq_by_index(&self, index: u32) -> Result<IrqRequest<'_>> { 358 + // SAFETY: `self.as_raw` returns a valid pointer to a `struct platform_device`. 359 + let irq = unsafe { bindings::platform_get_irq_optional(self.as_raw(), index) }; 360 + 361 + if irq < 0 { 362 + return Err(Error::from_errno(irq)); 363 + } 364 + 365 + // SAFETY: `irq` is guaranteed to be a valid IRQ number for `&self`. 366 + Ok(unsafe { IrqRequest::new(self.as_ref(), irq as u32) }) 367 + } 368 + 369 + /// Returns an [`IrqRequest`] for the IRQ with the given name, if any. 370 + pub fn irq_by_name(&self, name: &CStr) -> Result<IrqRequest<'_>> { 371 + // SAFETY: `self.as_raw` returns a valid pointer to a `struct platform_device`. 372 + let irq = unsafe { bindings::platform_get_irq_byname(self.as_raw(), name.as_char_ptr()) }; 373 + 374 + if irq < 0 { 375 + return Err(Error::from_errno(irq)); 376 + } 377 + 378 + // SAFETY: `irq` is guaranteed to be a valid IRQ number for `&self`. 379 + Ok(unsafe { IrqRequest::new(self.as_ref(), irq as u32) }) 380 + } 381 + 382 + /// Returns an [`IrqRequest`] for the IRQ with the given name, but does not 383 + /// print an error if the IRQ cannot be obtained. 384 + pub fn optional_irq_by_name(&self, name: &CStr) -> Result<IrqRequest<'_>> { 385 + // SAFETY: `self.as_raw` returns a valid pointer to a `struct platform_device`. 386 + let irq = unsafe { 387 + bindings::platform_get_irq_byname_optional(self.as_raw(), name.as_char_ptr()) 388 + }; 389 + 390 + if irq < 0 { 391 + return Err(Error::from_errno(irq)); 392 + } 393 + 394 + // SAFETY: `irq` is guaranteed to be a valid IRQ number for `&self`. 395 + Ok(unsafe { IrqRequest::new(self.as_ref(), irq as u32) }) 396 + } 397 + 398 + define_irq_accessor_by_index!( 399 + /// Returns a [`irq::Registration`] for the IRQ at the given index. 400 + request_irq_by_index, 401 + irq_by_index, 402 + Registration, 403 + Handler 404 + ); 405 + define_irq_accessor_by_name!( 406 + /// Returns a [`irq::Registration`] for the IRQ with the given name. 407 + request_irq_by_name, 408 + irq_by_name, 409 + Registration, 410 + Handler 411 + ); 412 + define_irq_accessor_by_index!( 413 + /// Does the same as [`Self::request_irq_by_index`], except that it does 414 + /// not print an error message if the IRQ cannot be obtained. 415 + request_optional_irq_by_index, 416 + optional_irq_by_index, 417 + Registration, 418 + Handler 419 + ); 420 + define_irq_accessor_by_name!( 421 + /// Does the same as [`Self::request_irq_by_name`], except that it does 422 + /// not print an error message if the IRQ cannot be obtained. 423 + request_optional_irq_by_name, 424 + optional_irq_by_name, 425 + Registration, 426 + Handler 427 + ); 428 + 429 + define_irq_accessor_by_index!( 430 + /// Returns a [`irq::ThreadedRegistration`] for the IRQ at the given index. 431 + request_threaded_irq_by_index, 432 + irq_by_index, 433 + ThreadedRegistration, 434 + ThreadedHandler 435 + ); 436 + define_irq_accessor_by_name!( 437 + /// Returns a [`irq::ThreadedRegistration`] for the IRQ with the given name. 438 + request_threaded_irq_by_name, 439 + irq_by_name, 440 + ThreadedRegistration, 441 + ThreadedHandler 442 + ); 443 + define_irq_accessor_by_index!( 444 + /// Does the same as [`Self::request_threaded_irq_by_index`], except 445 + /// that it does not print an error message if the IRQ cannot be 446 + /// obtained. 447 + request_optional_threaded_irq_by_index, 448 + optional_irq_by_index, 449 + ThreadedRegistration, 450 + ThreadedHandler 451 + ); 452 + define_irq_accessor_by_name!( 453 + /// Does the same as [`Self::request_threaded_irq_by_name`], except that 454 + /// it does not print an error message if the IRQ cannot be obtained. 455 + request_optional_threaded_irq_by_name, 456 + optional_irq_by_name, 457 + ThreadedRegistration, 458 + ThreadedHandler 459 + ); 286 460 } 287 461 288 462 // SAFETY: `Device` is a transparent wrapper of a type that doesn't depend on `Device`'s generic