Skip to content

Commit f7d2d89

Browse files
hoshinolinajannau
authored andcommitted
drm/asahi: mmu: Use abstractions, drop bindings import
Signed-off-by: Asahi Lina <lina@asahilina.net>
1 parent 128a6fc commit f7d2d89

1 file changed

Lines changed: 42 additions & 53 deletions

File tree

drivers/gpu/drm/asahi/mmu.rs

Lines changed: 42 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,16 @@ 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,
26+
io::resource::Resource,
2627
prelude::*,
2728
static_lock_class,
2829
sync::{
@@ -86,7 +87,7 @@ pub(crate) const IOVA_USER_USABLE_RANGE: Range<u64> = IOVA_USER_BASE..IOVA_UNK_P
8687
/// A pre-allocated memory region for UAT management
8788
struct UatRegion {
8889
base: PhysicalAddr,
89-
map: NonNull<core::ffi::c_void>,
90+
map: io::mem::Mem,
9091
}
9192

9293
/// It's safe to share UAT region records across threads.
@@ -769,13 +770,13 @@ impl UatShared {
769770
/// Returns the handoff region area
770771
fn handoff(&self) -> &Handoff {
771772
// SAFETY: pointer is non-null per the type invariant
772-
unsafe { (self.handoff_rgn.map.as_ptr() as *mut Handoff).as_ref() }.unwrap()
773+
unsafe { (self.handoff_rgn.map.ptr() as *mut Handoff).as_ref() }.unwrap()
773774
}
774775

775776
/// Returns the TTBAT area
776777
fn ttbs(&self) -> &[SlotTTBS; UAT_NUM_CTX] {
777778
// 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()
779+
unsafe { (self.ttbs_rgn.map.ptr() as *mut [SlotTTBS; UAT_NUM_CTX]).as_ref() }.unwrap()
779780
}
780781
}
781782

@@ -815,13 +816,6 @@ pub(crate) struct Uat {
815816
kernel_lower_vm: Vm,
816817
}
817818

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-
825819
impl Handoff {
826820
/// Lock the handoff region from firmware access
827821
fn lock(&self) {
@@ -1309,33 +1303,23 @@ impl Drop for VmInner {
13091303
}
13101304

13111305
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());
1306+
fn get_region(dev: &device::Device, name: &CStr) -> Result<Resource> {
1307+
let dev_node = dev.of_node().ok_or(EINVAL)?;
13271308

1328-
if ret < 0 {
1329-
dev_err!(dev, "Failed to get {} region\n", name);
1330-
to_result(ret)?
1331-
}
1332-
1333-
res.assume_init()
1309+
let node = dev_node.parse_phandle_by_name(
1310+
c_str!("memory-region"),
1311+
c_str!("memory-region-names"),
1312+
name,
1313+
);
1314+
let Some(node) = node else {
1315+
dev_err!(dev, "Missing {} region\n", name);
1316+
return Err(EINVAL);
13341317
};
1318+
let res = node.address_as_resource(0).inspect_err(|_| {
1319+
dev_err!(dev, "Failed to get {} region\n", name);
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,36 @@ 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) }.inspect_err(|_| {
1358+
dev_err!(dev, "Failed to remap {} mem resource\n", name);
1359+
})?;
1360+
1361+
Ok(UatRegion { base, map })
13761362
}
13771363

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

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

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

@@ -1510,7 +1496,10 @@ impl Uat {
15101496

15111497
let inner = Self::make_inner(dev)?;
15121498

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

0 commit comments

Comments
 (0)