From: Alexandre Courbot <acourbot@nvidia.com>
To: "Alexandre Courbot" <acourbot@nvidia.com>,
"Yury Norov" <yury.norov@gmail.com>,
"Miguel Ojeda" <ojeda@kernel.org>,
"Boqun Feng" <boqun@kernel.org>, "Gary Guo" <gary@garyguo.net>,
"Björn Roy Baron" <bjorn3_gh@protonmail.com>,
"Benno Lossin" <lossin@kernel.org>,
"Andreas Hindborg" <a.hindborg@kernel.org>,
"Alice Ryhl" <aliceryhl@google.com>,
"Trevor Gross" <tmgross@umich.edu>,
"Danilo Krummrich" <dakr@kernel.org>,
"Daniel Almeida" <daniel.almeida@collabora.com>,
"Tamir Duberstein" <tamird@kernel.org>,
"Onur Özkan" <work@onurozkan.dev>,
"David Airlie" <airlied@gmail.com>,
"Simona Vetter" <simona@ffwll.ch>
Cc: John Hubbard <jhubbard@nvidia.com>,
Alistair Popple <apopple@nvidia.com>,
Timur Tabi <ttabi@nvidia.com>,
Eliot Courtney <ecourtney@nvidia.com>,
Zhi Wang <zhiw@nvidia.com>,
linux-kernel@vger.kernel.org, rust-for-linux@vger.kernel.org,
nova-gpu@lists.linux.dev, dri-devel@lists.freedesktop.org
Subject: [PATCH v2 2/2] gpu: nova-core: use kernel lossless integer conversion module
Date: Thu, 06 Aug 2026 16:35:54 +0900 [thread overview]
Message-ID: <20260806-as_casts-v2-2-cb76a4d3a6ef@nvidia.com> (raw)
In-Reply-To: <20260806-as_casts-v2-0-cb76a4d3a6ef@nvidia.com>
The `kernel` crate now features a copy of our lossless integer
conversion routines. Switch to the kernel version and remove our own.
Signed-off-by: Alexandre Courbot <acourbot@nvidia.com>
---
drivers/gpu/nova-core/falcon.rs | 12 +-
drivers/gpu/nova-core/falcon/fsp.rs | 4 +-
drivers/gpu/nova-core/fb.rs | 2 +-
drivers/gpu/nova-core/fb/hal/gb100.rs | 11 +-
drivers/gpu/nova-core/firmware.rs | 8 +-
drivers/gpu/nova-core/firmware/booter.rs | 10 +-
drivers/gpu/nova-core/firmware/fwsec.rs | 2 +-
drivers/gpu/nova-core/firmware/fwsec/bootloader.rs | 2 +-
drivers/gpu/nova-core/firmware/gsp.rs | 7 +-
drivers/gpu/nova-core/firmware/riscv.rs | 6 +-
drivers/gpu/nova-core/fsp.rs | 4 +-
drivers/gpu/nova-core/gsp.rs | 4 +-
drivers/gpu/nova-core/gsp/cmdq.rs | 24 +--
drivers/gpu/nova-core/gsp/fw.rs | 42 ++--
drivers/gpu/nova-core/gsp/sequencer.rs | 2 +-
drivers/gpu/nova-core/num.rs | 211 ---------------------
drivers/gpu/nova-core/vbios.rs | 2 +-
17 files changed, 73 insertions(+), 280 deletions(-)
diff --git a/drivers/gpu/nova-core/falcon.rs b/drivers/gpu/nova-core/falcon.rs
index 94c7696a6493..e352b300f763 100644
--- a/drivers/gpu/nova-core/falcon.rs
+++ b/drivers/gpu/nova-core/falcon.rs
@@ -23,6 +23,10 @@
},
Io,
},
+ num::casts::{
+ self,
+ FromSafeCast, //
+ },
prelude::*,
sync::aref::ARef,
time::Delta,
@@ -33,11 +37,7 @@
driver::Bar0,
falcon::hal::LoadMethod,
gpu::Chipset,
- num::{
- self,
- FromSafeCast, //
- },
- regs,
+ regs, //
};
pub(crate) mod fsp;
@@ -518,7 +518,7 @@ fn dma_wr(
target_mem: FalconMem,
load_offsets: FalconDmaLoadTarget,
) -> Result {
- const DMA_LEN: u32 = num::usize_into_u32::<{ MEM_BLOCK_ALIGNMENT }>();
+ const DMA_LEN: u32 = casts::usize_into_u32::<{ MEM_BLOCK_ALIGNMENT }>();
// For IMEM, we want to use the start offset as a virtual address tag for each page, since
// code addresses in the firmware (and the boot vector) are virtual.
diff --git a/drivers/gpu/nova-core/falcon/fsp.rs b/drivers/gpu/nova-core/falcon/fsp.rs
index 52cdb84ef0e8..00bfd56c52a5 100644
--- a/drivers/gpu/nova-core/falcon/fsp.rs
+++ b/drivers/gpu/nova-core/falcon/fsp.rs
@@ -16,6 +16,7 @@
},
Io, //
},
+ num::casts,
prelude::*,
time::Delta,
};
@@ -28,7 +29,6 @@
PFalcon2Base,
PFalconBase, //
},
- num,
regs, //
};
@@ -155,7 +155,7 @@ pub(crate) fn recv_msg(&mut self, bar: Bar0<'_>) -> Result<KVec<u8>> {
Delta::from_millis(10),
Delta::from_millis(FSP_MSG_TIMEOUT_MS),
)
- .map(num::u32_as_usize)?;
+ .map(casts::u32_as_usize)?;
let mut buffer = KVec::<u8>::new();
buffer.resize(msg_size, 0, GFP_KERNEL)?;
diff --git a/drivers/gpu/nova-core/fb.rs b/drivers/gpu/nova-core/fb.rs
index 725e428154cf..6301ea3ddfb0 100644
--- a/drivers/gpu/nova-core/fb.rs
+++ b/drivers/gpu/nova-core/fb.rs
@@ -10,6 +10,7 @@
dma::CoherentHandle,
fmt,
io::Io,
+ num::casts::FromSafeCast,
prelude::*,
ptr::{
Alignable,
@@ -23,7 +24,6 @@
firmware::gsp::GspFirmware,
gpu::Chipset,
gsp,
- num::FromSafeCast,
regs, //
};
diff --git a/drivers/gpu/nova-core/fb/hal/gb100.rs b/drivers/gpu/nova-core/fb/hal/gb100.rs
index 6e0eba101ca1..49b85968e919 100644
--- a/drivers/gpu/nova-core/fb/hal/gb100.rs
+++ b/drivers/gpu/nova-core/fb/hal/gb100.rs
@@ -11,7 +11,10 @@
},
Io, //
},
- num::Bounded,
+ num::{
+ casts,
+ Bounded, //
+ },
prelude::*,
ptr::{
const_align_up,
@@ -23,7 +26,6 @@
use crate::{
driver::Bar0,
fb::hal::FbHal,
- num::usize_into_u32,
regs, //
};
@@ -79,8 +81,9 @@ fn write_sysmem_flush_page_gb100(bar: Bar0<'_>, addr: Bounded<u64, 52>) {
}
pub(super) const fn pmu_reserved_size_gb100() -> u32 {
- usize_into_u32::<{ const_align_up(SZ_8M + SZ_16M + SZ_4K, Alignment::new::<SZ_128K>()).unwrap() }>(
- )
+ casts::usize_into_u32::<
+ { const_align_up(SZ_8M + SZ_16M + SZ_4K, Alignment::new::<SZ_128K>()).unwrap() },
+ >()
}
impl FbHal for Gb100 {
diff --git a/drivers/gpu/nova-core/firmware.rs b/drivers/gpu/nova-core/firmware.rs
index 1e89390209f5..454d08ad8542 100644
--- a/drivers/gpu/nova-core/firmware.rs
+++ b/drivers/gpu/nova-core/firmware.rs
@@ -10,6 +10,10 @@
use kernel::{
device,
firmware,
+ num::casts::{
+ FromSafeCast,
+ IntoSafeCast, //
+ },
prelude::*,
str::CString,
transmute::FromBytes, //
@@ -21,10 +25,6 @@
FalconFirmware, //
},
gpu,
- num::{
- FromSafeCast,
- IntoSafeCast, //
- },
};
pub(crate) mod booter;
diff --git a/drivers/gpu/nova-core/firmware/booter.rs b/drivers/gpu/nova-core/firmware/booter.rs
index d9313ac361af..46fec211a4c2 100644
--- a/drivers/gpu/nova-core/firmware/booter.rs
+++ b/drivers/gpu/nova-core/firmware/booter.rs
@@ -10,6 +10,10 @@
use kernel::{
device,
dma::Coherent,
+ num::casts::{
+ FromSafeCast,
+ IntoSafeCast, //
+ },
prelude::*,
transmute::FromBytes, //
};
@@ -31,11 +35,7 @@
Signed,
Unsigned, //
},
- gpu::Chipset,
- num::{
- FromSafeCast,
- IntoSafeCast, //
- },
+ gpu::Chipset, //
};
/// Local convenience function to return a copy of `S` by reinterpreting the bytes starting at
diff --git a/drivers/gpu/nova-core/firmware/fwsec.rs b/drivers/gpu/nova-core/firmware/fwsec.rs
index 199ae2adb664..fca127d96e55 100644
--- a/drivers/gpu/nova-core/firmware/fwsec.rs
+++ b/drivers/gpu/nova-core/firmware/fwsec.rs
@@ -19,6 +19,7 @@
self,
Device, //
},
+ num::casts::FromSafeCast,
prelude::*,
transmute::{
AsBytes,
@@ -43,7 +44,6 @@
Signed,
Unsigned, //
},
- num::FromSafeCast,
vbios::Vbios,
};
diff --git a/drivers/gpu/nova-core/firmware/fwsec/bootloader.rs b/drivers/gpu/nova-core/firmware/fwsec/bootloader.rs
index 039920dc340b..0fbc7971477b 100644
--- a/drivers/gpu/nova-core/firmware/fwsec/bootloader.rs
+++ b/drivers/gpu/nova-core/firmware/fwsec/bootloader.rs
@@ -17,6 +17,7 @@
register::WithBase, //
Io,
},
+ num::casts::FromSafeCast,
prelude::*,
ptr::{
Alignable,
@@ -51,7 +52,6 @@
FIRMWARE_VERSION, //
},
gpu::Chipset,
- num::FromSafeCast,
regs,
};
diff --git a/drivers/gpu/nova-core/firmware/gsp.rs b/drivers/gpu/nova-core/firmware/gsp.rs
index 99a302bae567..39f50c927b72 100644
--- a/drivers/gpu/nova-core/firmware/gsp.rs
+++ b/drivers/gpu/nova-core/firmware/gsp.rs
@@ -8,6 +8,10 @@
DataDirection,
DmaAddress, //
},
+ num::casts::{
+ arch::FromSafeCastArch,
+ FromSafeCast, //
+ },
prelude::*,
scatterlist::{
Owned,
@@ -25,7 +29,6 @@
Chipset, //
},
gsp::GSP_PAGE_SIZE,
- num::FromSafeCast,
};
/// GSP firmware with 3-level radix page tables for the GSP bootloader.
@@ -175,7 +178,7 @@ pub(crate) fn radix3_dma_handle(&self) -> DmaAddress {
fn map_into_lvl(sg_table: &SGTable<Owned<VVec<u8>>>, mut dst: VVec<u8>) -> Result<VVec<u8>> {
for sg_entry in sg_table.iter() {
// Number of pages we need to map.
- let num_pages = usize::from_safe_cast(sg_entry.dma_len()).div_ceil(GSP_PAGE_SIZE);
+ let num_pages = usize::from_safe_cast_arch(sg_entry.dma_len()).div_ceil(GSP_PAGE_SIZE);
for i in 0..num_pages {
let entry = sg_entry.dma_address()
diff --git a/drivers/gpu/nova-core/firmware/riscv.rs b/drivers/gpu/nova-core/firmware/riscv.rs
index 2afa7f36404e..43015ea5c831 100644
--- a/drivers/gpu/nova-core/firmware/riscv.rs
+++ b/drivers/gpu/nova-core/firmware/riscv.rs
@@ -7,14 +7,12 @@
device,
dma::Coherent,
firmware::Firmware,
+ num::casts::FromSafeCast,
prelude::*,
transmute::FromBytes, //
};
-use crate::{
- firmware::BinFirmware,
- num::FromSafeCast, //
-};
+use crate::firmware::BinFirmware;
/// Descriptor for microcode running on a RISC-V core.
#[repr(C)]
diff --git a/drivers/gpu/nova-core/fsp.rs b/drivers/gpu/nova-core/fsp.rs
index 8fc243c66e35..581ed301d37a 100644
--- a/drivers/gpu/nova-core/fsp.rs
+++ b/drivers/gpu/nova-core/fsp.rs
@@ -11,6 +11,7 @@
device,
dma::Coherent,
io::poll::read_poll_timeout,
+ num::casts,
prelude::*,
ptr::{
Alignable,
@@ -42,7 +43,6 @@
NvdmHeader,
NvdmType, //
},
- num,
regs, //
};
@@ -128,7 +128,7 @@ fn new<'a>(
};
let version = hal::fsp_hal(args.chipset).ok_or(ENOTSUPP)?.cot_version();
- let size = num::usize_into_u16::<{ core::mem::size_of::<NvdmPayloadCot>() }>();
+ let size = casts::usize_into_u16::<{ core::mem::size_of::<NvdmPayloadCot>() }>();
Ok(init!(Self {
mctp_header: MctpHeader::single_packet(),
diff --git a/drivers/gpu/nova-core/gsp.rs b/drivers/gpu/nova-core/gsp.rs
index 69175ca3315c..5fafd6716ba3 100644
--- a/drivers/gpu/nova-core/gsp.rs
+++ b/drivers/gpu/nova-core/gsp.rs
@@ -11,6 +11,7 @@
CoherentBox,
DmaAddress, //
},
+ num::casts,
pci,
prelude::*,
transmute::{
@@ -36,7 +37,6 @@
GspArgumentsPadded,
LibosMemoryRegionInitArgument, //
},
- num,
};
pub(crate) const GSP_PAGE_SHIFT: usize = 12;
@@ -61,7 +61,7 @@ impl<const NUM_PAGES: usize> PteArray<NUM_PAGES> {
// TODO: Replace with `IoView` projection once available.
fn entry(start: DmaAddress, index: usize) -> Result<u64> {
start
- .checked_add(num::usize_as_u64(index) << GSP_PAGE_SHIFT)
+ .checked_add(casts::usize_as_u64(index) << GSP_PAGE_SHIFT)
.ok_or(EOVERFLOW)
}
}
diff --git a/drivers/gpu/nova-core/gsp/cmdq.rs b/drivers/gpu/nova-core/gsp/cmdq.rs
index 070de0731e95..39326e3007bd 100644
--- a/drivers/gpu/nova-core/gsp/cmdq.rs
+++ b/drivers/gpu/nova-core/gsp/cmdq.rs
@@ -16,6 +16,7 @@
Io, //
},
new_mutex,
+ num::casts,
prelude::*,
ptr,
sync::{
@@ -26,7 +27,7 @@
transmute::{
AsBytes,
FromBytes, //
- },
+ }, //
};
use continuation::{
@@ -50,7 +51,6 @@
GSP_PAGE_SHIFT,
GSP_PAGE_SIZE, //
},
- num,
regs,
sbuffer::SBufferIter, //
};
@@ -154,7 +154,7 @@ fn read(
#[repr(C, align(0x1000))]
#[derive(Debug)]
struct MsgqData {
- data: [[u8; GSP_PAGE_SIZE]; num::u32_as_usize(MSGQ_NUM_PAGES)],
+ data: [[u8; GSP_PAGE_SIZE]; casts::u32_as_usize(MSGQ_NUM_PAGES)],
}
// Annoyingly we are forced to use a literal to specify the alignment of
@@ -229,8 +229,8 @@ unsafe impl FromBytes for GspMem {}
impl DmaGspMem {
/// Allocate a new instance and map it for `dev`.
fn new(dev: &device::Device<device::Bound>) -> Result<Self> {
- const MSGQ_SIZE: u32 = num::usize_into_u32::<{ size_of::<Msgq>() }>();
- const RX_HDR_OFF: u32 = num::usize_into_u32::<{ mem::offset_of!(Msgq, rx) }>();
+ const MSGQ_SIZE: u32 = casts::usize_into_u32::<{ size_of::<Msgq>() }>();
+ const RX_HDR_OFF: u32 = casts::usize_into_u32::<{ mem::offset_of!(Msgq, rx) }>();
let gsp_mem = Coherent::<GspMem>::zeroed(dev, GFP_KERNEL)?;
@@ -291,10 +291,10 @@ fn new(dev: &device::Device<device::Bound>) -> Result<Self> {
unsafe {
(
core::slice::from_raw_parts_mut(
- data.add(num::u32_as_usize(tx)),
- num::u32_as_usize(tail_end - tx),
+ data.add(casts::u32_as_usize(tx)),
+ casts::u32_as_usize(tail_end - tx),
),
- core::slice::from_raw_parts_mut(data, num::u32_as_usize(wrap_end)),
+ core::slice::from_raw_parts_mut(data, casts::u32_as_usize(wrap_end)),
)
}
}
@@ -309,7 +309,7 @@ fn driver_write_area_size(&self) -> usize {
// `cpu_write_ptr`. The minimum value case is where `rx == 0` and `tx == MSGQ_NUM_PAGES -
// 1`, which gives `0 + MSGQ_NUM_PAGES - (MSGQ_NUM_PAGES - 1) - 1 == 0`.
let slots = (rx + MSGQ_NUM_PAGES - tx - 1) % MSGQ_NUM_PAGES;
- num::u32_as_usize(slots) * GSP_PAGE_SIZE
+ casts::u32_as_usize(slots) * GSP_PAGE_SIZE
}
/// Returns the region of the GSP message queue that the driver is currently allowed to read
@@ -345,10 +345,10 @@ fn driver_write_area_size(&self) -> usize {
unsafe {
(
core::slice::from_raw_parts(
- data.add(num::u32_as_usize(rx)),
- num::u32_as_usize(tail_end - rx),
+ data.add(casts::u32_as_usize(rx)),
+ casts::u32_as_usize(tail_end - rx),
),
- core::slice::from_raw_parts(data, num::u32_as_usize(wrap_end)),
+ core::slice::from_raw_parts(data, casts::u32_as_usize(wrap_end)),
)
}
}
diff --git a/drivers/gpu/nova-core/gsp/fw.rs b/drivers/gpu/nova-core/gsp/fw.rs
index 4db0cfa4dc4d..ad659293aae1 100644
--- a/drivers/gpu/nova-core/gsp/fw.rs
+++ b/drivers/gpu/nova-core/gsp/fw.rs
@@ -11,6 +11,10 @@
use kernel::{
dma::Coherent,
+ num::casts::{
+ self,
+ FromSafeCast, //
+ },
prelude::*,
ptr::{
Alignable,
@@ -38,10 +42,6 @@
cmdq::Cmdq, //
GSP_PAGE_SIZE,
},
- num::{
- self,
- FromSafeCast, //
- },
};
// TODO: Replace with `IoView` projections once available.
@@ -99,7 +99,7 @@ pub(in crate::gsp) fn advance_cpu_write_ptr(qs: &Coherent<GspMem>, count: u32) {
/// Maximum size of a single GSP message queue element in bytes.
pub(crate) const GSP_MSG_QUEUE_ELEMENT_SIZE_MAX: usize =
- num::u32_as_usize(bindings::GSP_MSG_QUEUE_ELEMENT_SIZE_MAX);
+ casts::u32_as_usize(bindings::GSP_MSG_QUEUE_ELEMENT_SIZE_MAX);
/// Empty type to group methods related to heap parameters for running the GSP firmware.
enum GspFwHeapParams {}
@@ -152,19 +152,19 @@ pub(crate) struct LibosParams {
impl LibosParams {
/// Version 2 of the GSP LIBOS (Turing and GA100)
const LIBOS2: LibosParams = LibosParams {
- carveout_size: num::u32_as_u64(bindings::GSP_FW_HEAP_PARAM_OS_SIZE_LIBOS2),
- allowed_heap_size: num::u32_as_u64(bindings::GSP_FW_HEAP_SIZE_OVERRIDE_LIBOS2_MIN_MB)
+ carveout_size: casts::u32_as_u64(bindings::GSP_FW_HEAP_PARAM_OS_SIZE_LIBOS2),
+ allowed_heap_size: casts::u32_as_u64(bindings::GSP_FW_HEAP_SIZE_OVERRIDE_LIBOS2_MIN_MB)
* u64::SZ_1M
- ..num::u32_as_u64(bindings::GSP_FW_HEAP_SIZE_OVERRIDE_LIBOS2_MAX_MB) * u64::SZ_1M,
+ ..casts::u32_as_u64(bindings::GSP_FW_HEAP_SIZE_OVERRIDE_LIBOS2_MAX_MB) * u64::SZ_1M,
};
/// Version 3 of the GSP LIBOS (GA102+)
const LIBOS3: LibosParams = LibosParams {
- carveout_size: num::u32_as_u64(bindings::GSP_FW_HEAP_PARAM_OS_SIZE_LIBOS3_BAREMETAL),
- allowed_heap_size: num::u32_as_u64(
+ carveout_size: casts::u32_as_u64(bindings::GSP_FW_HEAP_PARAM_OS_SIZE_LIBOS3_BAREMETAL),
+ allowed_heap_size: casts::u32_as_u64(
bindings::GSP_FW_HEAP_SIZE_OVERRIDE_LIBOS3_BAREMETAL_MIN_MB,
) * u64::SZ_1M
- ..num::u32_as_u64(bindings::GSP_FW_HEAP_SIZE_OVERRIDE_LIBOS3_BAREMETAL_MAX_MB)
+ ..casts::u32_as_u64(bindings::GSP_FW_HEAP_SIZE_OVERRIDE_LIBOS3_BAREMETAL_MAX_MB)
* u64::SZ_1M,
};
@@ -678,11 +678,11 @@ fn id8(name: &str) -> u64 {
let init_inner = init!(bindings::LibosMemoryRegionInitArgument {
id8: id8(name),
pa: obj.dma_handle(),
- size: num::usize_as_u64(obj.size()),
- kind: num::u32_into_u8::<
+ size: casts::usize_as_u64(obj.size()),
+ kind: casts::u32_into_u8::<
{ bindings::LibosMemoryRegionKind_LIBOS_MEMORY_REGION_CONTIGUOUS },
>(),
- loc: num::u32_into_u8::<
+ loc: casts::u32_into_u8::<
{ bindings::LibosMemoryRegionLoc_LIBOS_MEMORY_REGION_LOC_SYSMEM },
>(),
..Zeroable::init_zeroed()
@@ -712,12 +712,12 @@ pub(crate) fn new(msgq_size: u32, rx_hdr_offset: u32, msg_count: u32) -> Self {
Self(bindings::msgqTxHeader {
version: 0,
size: msgq_size,
- msgSize: num::usize_into_u32::<GSP_PAGE_SIZE>(),
+ msgSize: casts::usize_into_u32::<GSP_PAGE_SIZE>(),
msgCount: msg_count,
writePtr: 0,
flags: 1,
rxHdrOff: rx_hdr_offset,
- entryOff: num::usize_into_u32::<GSP_PAGE_SIZE>(),
+ entryOff: casts::usize_into_u32::<GSP_PAGE_SIZE>(),
})
}
}
@@ -829,7 +829,7 @@ pub(crate) fn set_checksum(&mut self, checksum: u32) {
/// Returns the length of the message's payload.
pub(crate) fn payload_length(&self) -> usize {
// `rpc.length` includes the length of the RPC message header.
- num::u32_as_usize(self.inner.rpc.length)
+ casts::u32_as_usize(self.inner.rpc.length)
.saturating_sub(size_of::<bindings::rpc_message_header_v>())
}
@@ -927,9 +927,9 @@ impl MessageQueueInitArguments {
fn new(cmdq: &Cmdq) -> impl Init<Self> + '_ {
init!(MessageQueueInitArguments {
sharedMemPhysAddr: cmdq.dma_handle,
- pageTableEntryCount: num::usize_into_u32::<{ Cmdq::NUM_PTES }>(),
- cmdQueueOffset: num::usize_as_u64(Cmdq::CMDQ_OFFSET),
- statQueueOffset: num::usize_as_u64(Cmdq::STATQ_OFFSET),
+ pageTableEntryCount: casts::usize_into_u32::<{ Cmdq::NUM_PTES }>(),
+ cmdQueueOffset: casts::usize_as_u64(Cmdq::CMDQ_OFFSET),
+ statQueueOffset: casts::usize_as_u64(Cmdq::STATQ_OFFSET),
..Zeroable::init_zeroed()
})
}
@@ -950,7 +950,7 @@ fn new(target: GspDmaTarget, wpr_meta_addr: u64) -> impl Init<Self> {
#[allow(non_snake_case)]
let params = init!(Self {
target: target as u32,
- gspRmDescSize: num::usize_into_u32::<{ size_of::<GspFwWprMeta>() }>(),
+ gspRmDescSize: casts::usize_into_u32::<{ size_of::<GspFwWprMeta>() }>(),
gspRmDescOffset: wpr_meta_addr,
bIsGspRmBoot: 1,
wprCarveoutOffset: 0,
diff --git a/drivers/gpu/nova-core/gsp/sequencer.rs b/drivers/gpu/nova-core/gsp/sequencer.rs
index e0850d21adca..3944b396f67c 100644
--- a/drivers/gpu/nova-core/gsp/sequencer.rs
+++ b/drivers/gpu/nova-core/gsp/sequencer.rs
@@ -10,6 +10,7 @@
poll::read_poll_timeout,
Io, //
},
+ num::casts::FromSafeCast,
prelude::*,
time::{
delay::fsleep,
@@ -32,7 +33,6 @@
},
fw,
},
- num::FromSafeCast,
sbuffer::SBufferIter,
};
diff --git a/drivers/gpu/nova-core/num.rs b/drivers/gpu/nova-core/num.rs
index 6eb174d136ab..3921ef6f238e 100644
--- a/drivers/gpu/nova-core/num.rs
+++ b/drivers/gpu/nova-core/num.rs
@@ -5,217 +5,6 @@
//! This is essentially a staging module for code to mature until it can be moved to the `kernel`
//! crate.
-use kernel::{
- macros::paste,
- prelude::*, //
-};
-
-/// Implements safe `as` conversion functions from a given type into a series of target types.
-///
-/// These functions can be used in place of `as`, with the guarantee that they will be lossless.
-macro_rules! impl_safe_as {
- ($from:ty as { $($into:ty),* }) => {
- $(
- paste! {
- #[doc = ::core::concat!(
- "Losslessly converts a [`",
- ::core::stringify!($from),
- "`] into a [`",
- ::core::stringify!($into),
- "`].")]
- ///
- /// This conversion is allowed as it is always lossless. Prefer this over the `as`
- /// keyword to ensure no lossy casts are performed.
- ///
- /// This is for use from a `const` context. For non `const` use, prefer the
- /// [`FromSafeCast`] and [`IntoSafeCast`] traits.
- ///
- /// # Examples
- ///
- /// ```
- /// use crate::num;
- ///
- #[doc = ::core::concat!(
- "assert_eq!(num::",
- ::core::stringify!($from),
- "_as_",
- ::core::stringify!($into),
- "(1",
- ::core::stringify!($from),
- "), 1",
- ::core::stringify!($into),
- ");")]
- /// ```
- #[allow(unused)]
- #[inline(always)]
- pub(crate) const fn [<$from _as_ $into>](value: $from) -> $into {
- ::kernel::build_assert::static_assert!(size_of::<$into>() >= size_of::<$from>());
-
- value as $into
- }
- }
- )*
- };
-}
-
-impl_safe_as!(u8 as { u16, u32, u64, usize });
-impl_safe_as!(u16 as { u32, u64, usize });
-impl_safe_as!(u32 as { u64, usize } );
-// `u64` and `usize` have the same size on 64-bit platforms.
-#[cfg(CONFIG_64BIT)]
-impl_safe_as!(u64 as { usize } );
-
-// A `usize` fits into a `u64` on 32 and 64-bit platforms.
-#[cfg(any(CONFIG_32BIT, CONFIG_64BIT))]
-impl_safe_as!(usize as { u64 });
-
-// A `usize` fits into a `u32` on 32-bit platforms.
-#[cfg(CONFIG_32BIT)]
-impl_safe_as!(usize as { u32 });
-
-/// Extension trait providing guaranteed lossless cast to `Self` from `T`.
-///
-/// The standard library's `From` implementations do not cover conversions that are not portable or
-/// future-proof. For instance, even though it is safe today, `From<usize>` is not implemented for
-/// [`u64`] because of the possibility to support larger-than-64bit architectures in the future.
-///
-/// The workaround is to either deal with the error handling of [`TryFrom`] for an operation that
-/// technically cannot fail, or to use the `as` keyword, which can silently strip data if the
-/// destination type is smaller than the source.
-///
-/// Both options are hardly acceptable for the kernel. It is also a much more architecture
-/// dependent environment, supporting only 32 and 64 bit architectures, with some modules
-/// explicitly depending on a specific bus width that could greatly benefit from infallible
-/// conversion operations.
-///
-/// Thus this extension trait that provides, for the architecture the kernel is built for, safe
-/// conversion between types for which such cast is lossless.
-///
-/// In other words, this trait is implemented if, for the current build target and with `t: T`, the
-/// `t as Self` operation is completely lossless.
-///
-/// Prefer this over the `as` keyword to ensure no lossy casts are performed.
-///
-/// If you need to perform a conversion in `const` context, use [`u64_as_usize`], [`u32_as_usize`],
-/// [`usize_as_u64`], etc.
-///
-/// # Examples
-///
-/// ```
-/// use crate::num::FromSafeCast;
-///
-/// assert_eq!(usize::from_safe_cast(0xf00u32), 0xf00u32 as usize);
-/// ```
-pub(crate) trait FromSafeCast<T> {
- /// Create a `Self` from `value`. This operation is guaranteed to be lossless.
- fn from_safe_cast(value: T) -> Self;
-}
-
-impl FromSafeCast<usize> for u64 {
- fn from_safe_cast(value: usize) -> Self {
- usize_as_u64(value)
- }
-}
-
-#[cfg(CONFIG_32BIT)]
-impl FromSafeCast<usize> for u32 {
- fn from_safe_cast(value: usize) -> Self {
- usize_as_u32(value)
- }
-}
-
-impl FromSafeCast<u32> for usize {
- fn from_safe_cast(value: u32) -> Self {
- u32_as_usize(value)
- }
-}
-
-#[cfg(CONFIG_64BIT)]
-impl FromSafeCast<u64> for usize {
- fn from_safe_cast(value: u64) -> Self {
- u64_as_usize(value)
- }
-}
-
-/// Counterpart to the [`FromSafeCast`] trait, i.e. this trait is to [`FromSafeCast`] what [`Into`]
-/// is to [`From`].
-///
-/// See the documentation of [`FromSafeCast`] for the motivation.
-///
-/// # Examples
-///
-/// ```
-/// use crate::num::IntoSafeCast;
-///
-/// assert_eq!(0xf00u32.into_safe_cast(), 0xf00u32 as usize);
-/// ```
-pub(crate) trait IntoSafeCast<T> {
- /// Convert `self` into a `T`. This operation is guaranteed to be lossless.
- fn into_safe_cast(self) -> T;
-}
-
-/// Reverse operation for types implementing [`FromSafeCast`].
-impl<S, T> IntoSafeCast<T> for S
-where
- T: FromSafeCast<S>,
-{
- fn into_safe_cast(self) -> T {
- T::from_safe_cast(self)
- }
-}
-
-/// Implements lossless conversion of a constant from a larger type into a smaller one.
-macro_rules! impl_const_into {
- ($from:ty => { $($into:ty),* }) => {
- $(
- paste! {
- #[doc = ::core::concat!(
- "Performs a build-time safe conversion of a [`",
- ::core::stringify!($from),
- "`] constant value into a [`",
- ::core::stringify!($into),
- "`].")]
- ///
- /// This checks at compile-time that the conversion is lossless, and triggers a build
- /// error if it isn't.
- ///
- /// # Examples
- ///
- /// ```
- /// use crate::num;
- ///
- /// // Succeeds because the value of the source fits into the destination's type.
- #[doc = ::core::concat!(
- "assert_eq!(num::",
- ::core::stringify!($from),
- "_into_",
- ::core::stringify!($into),
- "::<1",
- ::core::stringify!($from),
- ">(), 1",
- ::core::stringify!($into),
- ");")]
- /// ```
- #[allow(unused)]
- pub(crate) const fn [<$from _into_ $into>]<const N: $from>() -> $into {
- // Make sure that the target type is smaller than the source one.
- static_assert!($from::BITS >= $into::BITS);
- // CAST: we statically enforced above that `$from` is larger than `$into`, so the
- // `as` conversion will be lossless.
- build_assert!(N >= $into::MIN as $from && N <= $into::MAX as $from);
-
- N as $into
- }
- }
- )*
- };
-}
-
-impl_const_into!(usize => { u8, u16, u32 });
-impl_const_into!(u64 => { u8, u16, u32 });
-impl_const_into!(u32 => { u8, u16 });
-impl_const_into!(u16 => { u8 });
-
/// Creates an enum type associated to a [`Bounded`](kernel::num::Bounded), with a [`From`]
/// conversion to the associated `Bounded` and either a [`TryFrom`] or `From` conversion from the
/// associated `Bounded`.
diff --git a/drivers/gpu/nova-core/vbios.rs b/drivers/gpu/nova-core/vbios.rs
index c6e6bfcd6a1f..e67a82fcc8c0 100644
--- a/drivers/gpu/nova-core/vbios.rs
+++ b/drivers/gpu/nova-core/vbios.rs
@@ -5,6 +5,7 @@
use kernel::{
device,
io::Io,
+ num::casts::FromSafeCast,
prelude::*,
ptr::{
Alignable,
@@ -26,7 +27,6 @@
FalconUCodeDescV2,
FalconUCodeDescV3, //
},
- num::FromSafeCast,
};
/// BIOS Image Type from PCI Data Structure code_type field.
--
2.55.0
next prev parent reply other threads:[~2026-08-06 7:36 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-06 7:35 [PATCH v2 0/2] rust: add functions and traits for lossless integer conversions Alexandre Courbot
2026-08-06 7:35 ` [PATCH v2 1/2] " Alexandre Courbot
2026-08-06 7:35 ` Alexandre Courbot [this message]
2026-08-06 21:10 ` [PATCH v2 0/2] " Danilo Krummrich
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260806-as_casts-v2-2-cb76a4d3a6ef@nvidia.com \
--to=acourbot@nvidia.com \
--cc=a.hindborg@kernel.org \
--cc=airlied@gmail.com \
--cc=aliceryhl@google.com \
--cc=apopple@nvidia.com \
--cc=bjorn3_gh@protonmail.com \
--cc=boqun@kernel.org \
--cc=dakr@kernel.org \
--cc=daniel.almeida@collabora.com \
--cc=dri-devel@lists.freedesktop.org \
--cc=ecourtney@nvidia.com \
--cc=gary@garyguo.net \
--cc=jhubbard@nvidia.com \
--cc=linux-kernel@vger.kernel.org \
--cc=lossin@kernel.org \
--cc=nova-gpu@lists.linux.dev \
--cc=ojeda@kernel.org \
--cc=rust-for-linux@vger.kernel.org \
--cc=simona@ffwll.ch \
--cc=tamird@kernel.org \
--cc=tmgross@umich.edu \
--cc=ttabi@nvidia.com \
--cc=work@onurozkan.dev \
--cc=yury.norov@gmail.com \
--cc=zhiw@nvidia.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.