Skip to content

Commit bdf28b8

Browse files
committed
drm/asahi: mmu: Use abstractions, drop bindings import
Signed-off-by: Asahi Lina <[email protected]>
1 parent debd390 commit bdf28b8

1 file changed

Lines changed: 43 additions & 53 deletions

File tree

drivers/gpu/drm/asahi/mmu.rs

Lines changed: 43 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,15 @@ use core::fmt::Debug;
1414
use core::mem::size_of;
1515
use core::num::NonZeroUsize;
1616
use core::ops::Range;
17-
use core::ptr::NonNull;
1817
use core::sync::atomic::{fence, AtomicU32, AtomicU64, AtomicU8, Ordering};
1918
use core::time::Duration;
2019

2120
use kernel::{
2221
addr::PhysicalAddr,
23-
bindings, c_str, delay, device, drm,
22+
c_str, delay, device, drm,
2423
drm::{gem::BaseObject, gpuvm, mm},
25-
error::{to_result, Result},
24+
error::Result,
25+
io_mem::{self, Resource},
2626
prelude::*,
2727
static_lock_class,
2828
sync::{
@@ -86,7 +86,7 @@ pub(crate) const IOVA_USER_USABLE_RANGE: Range<u64> = IOVA_USER_BASE..IOVA_UNK_P
8686
/// A pre-allocated memory region for UAT management
8787
struct UatRegion {
8888
base: PhysicalAddr,
89-
map: NonNull<core::ffi::c_void>,
89+
map: io_mem::Mem,
9090
}
9191

9292
/// It's safe to share UAT region records across threads.
@@ -769,13 +769,13 @@ impl UatShared {
769769
/// Returns the handoff region area
770770
fn handoff(&self) -> &Handoff {
771771
// SAFETY: pointer is non-null per the type invariant
772-
unsafe { (self.handoff_rgn.map.as_ptr() as *mut Handoff).as_ref() }.unwrap()
772+
unsafe { (self.handoff_rgn.map.ptr() as *mut Handoff).as_ref() }.unwrap()
773773
}
774774

775775
/// Returns the TTBAT area
776776
fn ttbs(&self) -> &[SlotTTBS; UAT_NUM_CTX] {
777777
// SAFETY: pointer is non-null per the type invariant
778-
unsafe { (self.ttbs_rgn.map.as_ptr() as *mut [SlotTTBS; UAT_NUM_CTX]).as_ref() }.unwrap()
778+
unsafe { (self.ttbs_rgn.map.ptr() as *mut [SlotTTBS; UAT_NUM_CTX]).as_ref() }.unwrap()
779779
}
780780
}
781781

@@ -815,13 +815,6 @@ pub(crate) struct Uat {
815815
kernel_lower_vm: Vm,
816816
}
817817

818-
impl Drop for UatRegion {
819-
fn drop(&mut self) {
820-
// SAFETY: the pointer is valid by the type invariant
821-
unsafe { bindings::memunmap(self.map.as_ptr()) };
822-
}
823-
}
824-
825818
impl Handoff {
826819
/// Lock the handoff region from firmware access
827820
fn lock(&self) {
@@ -1309,33 +1302,24 @@ impl Drop for VmInner {
13091302
}
13101303

13111304
impl Uat {
1312-
fn get_region(dev: &device::Device, name: &CStr) -> Result<(PhysicalAddr, usize)> {
1313-
let mut res = core::mem::MaybeUninit::<bindings::resource>::uninit();
1314-
1315-
let res = unsafe {
1316-
let dev_node = dev.of_node().ok_or(EINVAL)?;
1317-
let node = dev_node.parse_phandle_by_name(
1318-
c_str!("memory-region"),
1319-
c_str!("memory-region-names"),
1320-
name,
1321-
);
1322-
if node.is_none() {
1323-
dev_err!(dev, "Missing {} region\n", name);
1324-
return Err(EINVAL);
1325-
}
1326-
let ret = bindings::of_address_to_resource(node.unwrap().as_raw(), 0, res.as_mut_ptr());
1305+
fn get_region(dev: &device::Device, name: &CStr) -> Result<Resource> {
1306+
let dev_node = dev.of_node().ok_or(EINVAL)?;
13271307

1328-
if ret < 0 {
1329-
dev_err!(dev, "Failed to get {} region\n", name);
1330-
to_result(ret)?
1331-
}
1332-
1333-
res.assume_init()
1308+
let node = dev_node.parse_phandle_by_name(
1309+
c_str!("memory-region"),
1310+
c_str!("memory-region-names"),
1311+
name,
1312+
);
1313+
let Some(node) = node else {
1314+
dev_err!(dev, "Missing {} region\n", name);
1315+
return Err(EINVAL);
13341316
};
1317+
let res = node.address_as_resource(0).map_err(|e| {
1318+
dev_err!(dev, "Failed to get {} region\n", name);
1319+
e
1320+
})?;
13351321

1336-
let rgn_size: usize = unsafe { bindings::resource_size(&res) } as usize;
1337-
1338-
Ok((res.start, rgn_size))
1322+
Ok(res)
13391323
}
13401324

13411325
/// Map a bootloader-preallocated memory region
@@ -1345,34 +1329,37 @@ impl Uat {
13451329
size: usize,
13461330
cached: bool,
13471331
) -> Result<UatRegion> {
1348-
let (start, rgn_size) = Self::get_region(dev, name)?;
1332+
let res = Self::get_region(dev, name)?;
1333+
let base = res.start();
1334+
let res_size = res.size().try_into()?;
13491335

1350-
if size > rgn_size {
1336+
if size > res_size {
13511337
dev_err!(
13521338
dev,
13531339
"Region {} is too small (expected {}, got {})\n",
13541340
name,
13551341
size,
1356-
rgn_size
1342+
res_size
13571343
);
13581344
return Err(ENOMEM);
13591345
}
13601346

13611347
let flags = if cached {
1362-
bindings::MEMREMAP_WB
1348+
io_mem::MemFlags::WB
13631349
} else {
1364-
bindings::MEMREMAP_WC
1350+
io_mem::MemFlags::WC
13651351
};
1366-
let map = unsafe { bindings::memremap(start, rgn_size, flags.into()) };
1367-
let map = NonNull::new(map);
13681352

1369-
match map {
1370-
None => {
1371-
dev_err!(dev, "Failed to remap {} region\n", name);
1372-
Err(ENOMEM)
1373-
}
1374-
Some(map) => Ok(UatRegion { base: start, map }),
1375-
}
1353+
// SAFETY: The safety of this operation hinges on the correctness of
1354+
// much of this file and also the `pgtable` module, so it is difficult
1355+
// to prove in a single safety comment. Such is life with raw GPU
1356+
// page table management...
1357+
let map = unsafe { io_mem::Mem::try_new(res, flags) }.map_err(|e| {
1358+
dev_err!(dev, "Failed to remap {} region\n", name);
1359+
e
1360+
})?;
1361+
1362+
Ok(UatRegion { base, map })
13761363
}
13771364

13781365
/// Returns a reference to the global kernel (upper half) `Vm`
@@ -1476,7 +1463,7 @@ impl Uat {
14761463
let handoff_rgn = Self::map_region(dev.as_ref(), c_str!("handoff"), HANDOFF_SIZE, true)?;
14771464
let ttbs_rgn = Self::map_region(dev.as_ref(), c_str!("ttbs"), SLOTS_SIZE, true)?;
14781465

1479-
let handoff = unsafe { &(handoff_rgn.map.as_ptr() as *mut Handoff).as_ref().unwrap() };
1466+
let handoff = unsafe { &(handoff_rgn.map.ptr() as *mut Handoff).as_ref().unwrap() };
14801467

14811468
dev_info!(dev.as_ref(), "MMU: Initializing kernel page table\n");
14821469

@@ -1510,7 +1497,10 @@ impl Uat {
15101497

15111498
let inner = Self::make_inner(dev)?;
15121499

1513-
let (ttb1, ttb1size) = Self::get_region(dev.as_ref(), c_str!("pagetables"))?;
1500+
let res = Self::get_region(dev.as_ref(), c_str!("pagetables"))?;
1501+
let ttb1 = res.start();
1502+
let ttb1size: usize = res.size().try_into()?;
1503+
15141504
if ttb1size < PAGETABLES_SIZE {
15151505
dev_err!(dev.as_ref(), "MMU: Pagetables region is too small\n");
15161506
return Err(ENOMEM);

0 commit comments

Comments
 (0)