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.

gpu: nova-core: introduce `bounded_enum` macro

Introduce a powered-up version of our ad-hoc `impl_from_enum_to_u8`
macro that allows the definition of an enum type associated to a
`Bounded` of a given width, and provides the `From` and `TryFrom`
implementations required to use that enum as a register field member.

This allows us to generate the required conversion implementations for
using the kernel register macro and skip some tedious boilerplate.

Acked-by: Danilo Krummrich <dakr@kernel.org>
Link: https://patch.msgid.link/20260325-b4-nova-register-v4-1-bdf172f0f6ca@nvidia.com
Signed-off-by: Alexandre Courbot <acourbot@nvidia.com>

+81
+1
drivers/gpu/nova-core/nova_core.rs
··· 21 21 mod gfw; 22 22 mod gpu; 23 23 mod gsp; 24 + #[macro_use] 24 25 mod num; 25 26 mod regs; 26 27 mod sbuffer;
+80
drivers/gpu/nova-core/num.rs
··· 215 215 impl_const_into!(u64 => { u8, u16, u32 }); 216 216 impl_const_into!(u32 => { u8, u16 }); 217 217 impl_const_into!(u16 => { u8 }); 218 + 219 + /// Creates an enum type associated to a [`Bounded`](kernel::num::Bounded), with a [`From`] 220 + /// conversion to the associated `Bounded` and either a [`TryFrom`] or `From` conversion from the 221 + /// associated `Bounded`. 222 + // TODO[FPRI]: This is a temporary solution to be replaced with the corresponding derive macros 223 + // once they land. 224 + #[macro_export] 225 + macro_rules! bounded_enum { 226 + ( 227 + $(#[$enum_meta:meta])* 228 + $vis:vis enum $enum_type:ident with $from_impl:ident<Bounded<$width:ty, $length:literal>> { 229 + $( $(#[doc = $variant_doc:expr])* $variant:ident = $value:expr),* $(,)* 230 + } 231 + ) => { 232 + $(#[$enum_meta])* 233 + $vis enum $enum_type { 234 + $( 235 + $(#[doc = $variant_doc])* 236 + $variant = $value 237 + ),* 238 + } 239 + 240 + impl core::convert::From<$enum_type> for kernel::num::Bounded<$width, $length> { 241 + fn from(value: $enum_type) -> Self { 242 + match value { 243 + $($enum_type::$variant => 244 + kernel::num::Bounded::<$width, _>::new::<{ $value }>()),* 245 + } 246 + } 247 + } 248 + 249 + bounded_enum!(@impl_from $enum_type with $from_impl<Bounded<$width, $length>> { 250 + $($variant = $value),* 251 + }); 252 + }; 253 + 254 + // `TryFrom` implementation from associated `Bounded` to enum type. 255 + (@impl_from $enum_type:ident with TryFrom<Bounded<$width:ty, $length:literal>> { 256 + $($variant:ident = $value:expr),* $(,)* 257 + }) => { 258 + impl core::convert::TryFrom<kernel::num::Bounded<$width, $length>> for $enum_type { 259 + type Error = kernel::error::Error; 260 + 261 + fn try_from( 262 + value: kernel::num::Bounded<$width, $length> 263 + ) -> kernel::error::Result<Self> { 264 + match value.get() { 265 + $( 266 + $value => Ok($enum_type::$variant), 267 + )* 268 + _ => Err(kernel::error::code::EINVAL), 269 + } 270 + } 271 + } 272 + }; 273 + 274 + // `From` implementation from associated `Bounded` to enum type. Triggers a build-time error if 275 + // all possible values of the `Bounded` are not covered by the enum type. 276 + (@impl_from $enum_type:ident with From<Bounded<$width:ty, $length:literal>> { 277 + $($variant:ident = $value:expr),* $(,)* 278 + }) => { 279 + impl core::convert::From<kernel::num::Bounded<$width, $length>> for $enum_type { 280 + fn from(value: kernel::num::Bounded<$width, $length>) -> Self { 281 + const MAX: $width = 1 << $length; 282 + 283 + // Makes the compiler optimizer aware of the possible range of values. 284 + let value = value.get() & ((1 << $length) - 1); 285 + match value { 286 + $( 287 + $value => $enum_type::$variant, 288 + )* 289 + // PANIC: we cannot reach this arm as all possible variants are handled by the 290 + // match arms above. It is here to make the compiler complain if `$enum_type` 291 + // does not cover all values of the `0..MAX` range. 292 + MAX.. => unreachable!(), 293 + } 294 + } 295 + } 296 + } 297 + }