Skip to content

Commit 8bcfb1a

Browse files
committed
drm/asahi: Copy tyr's mmu/vm/range.rs
Signed-off-by: Janne Grunau <j@jannau.net>
1 parent 4655d12 commit 8bcfb1a

3 files changed

Lines changed: 132 additions & 0 deletions

File tree

drivers/gpu/drm/asahi/asahi.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ mod queue;
2727
mod regs;
2828
mod slotalloc;
2929
mod util;
30+
#[cfg(CONFIG_DRM_ASAHI_MAPLE_TREE)]
31+
mod vm;
3032
mod workqueue;
3133

3234
kernel::module_platform_driver! {

drivers/gpu/drm/asahi/vm/mod.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
// SPDX-License-Identifier: GPL-2.0-only OR MIT
2+
3+
//! Virtual address space management
4+
5+
mod range;

drivers/gpu/drm/asahi/vm/range.rs

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
// SPDX-License-Identifier: GPL-2.0 or MIT
2+
3+
// Copied from tyr's mmu/vm/range.rs
4+
5+
//! Range allocator.
6+
//!
7+
//! This module allows you to search for unused ranges to store GEM objects.
8+
9+
use kernel::alloc::Flags;
10+
use kernel::maple_tree::MapleTreeAlloc;
11+
use kernel::prelude::*;
12+
use kernel::sync::Arc;
13+
14+
use core::ops::Range;
15+
16+
/// The actual storage for the ranges.
17+
///
18+
/// All ranges must fit within the `range` field.
19+
///
20+
/// The implementation is different on 32-bit and 64-bit cpus. On 64-bit, the 64-bit addresses are
21+
/// stored directly in the maple tree, but on 32-bit, the maple tree stores the ranges translated
22+
/// in the range zero until `range.end-range.start`. This is done because the maple tree uses
23+
/// unsigned long as its address type, which is too small to store the 64-bit address directly on
24+
/// 32-bit machines.
25+
#[pin_data]
26+
struct RangeAllocInner {
27+
#[pin]
28+
maple: MapleTreeAlloc<()>,
29+
range: Range<u64>,
30+
}
31+
32+
/// This object allows you to allocate ranges on the inner maple tree.
33+
pub(crate) struct RangeAlloc {
34+
inner: Arc<RangeAllocInner>,
35+
}
36+
37+
/// Represents a live range in the maple tree.
38+
///
39+
/// The destructor removes the range from the maple tree, allowing others to allocate it in the
40+
/// future.
41+
pub(crate) struct LiveRange {
42+
inner: Arc<RangeAllocInner>,
43+
offset: u64,
44+
size: usize,
45+
}
46+
47+
impl RangeAlloc {
48+
pub(crate) fn new(start: u64, end: u64, gfp: Flags) -> Result<Self> {
49+
if end < start {
50+
return Err(EINVAL);
51+
}
52+
53+
let inner = Arc::pin_init(
54+
try_pin_init!(RangeAllocInner {
55+
maple <- MapleTreeAlloc::new(),
56+
range: start..end,
57+
}),
58+
gfp,
59+
)?;
60+
61+
Ok(RangeAlloc { inner })
62+
}
63+
64+
pub(crate) fn allocate(&self, size: usize, gfp: Flags) -> Result<LiveRange> {
65+
let maple_start = self.inner.range.start as usize;
66+
let maple_end = self.inner.range.end as usize;
67+
68+
let offset = self
69+
.inner
70+
.maple
71+
.alloc_range(size, (), maple_start..maple_end, gfp)?;
72+
73+
Ok(LiveRange {
74+
inner: self.inner.clone(),
75+
offset: offset as u64,
76+
size,
77+
})
78+
}
79+
80+
pub(crate) fn insert(&self, start: u64, end: u64, gfp: Flags) -> Result<LiveRange> {
81+
if end < start {
82+
return Err(EINVAL);
83+
}
84+
if start < self.inner.range.start {
85+
return Err(EINVAL);
86+
}
87+
if end > self.inner.range.end {
88+
return Err(EINVAL);
89+
}
90+
91+
self.inner
92+
.maple
93+
.insert_range(start as usize..end as usize, (), gfp)?;
94+
95+
Ok(LiveRange {
96+
inner: self.inner.clone(),
97+
offset: start,
98+
size: (end - start) as usize,
99+
})
100+
}
101+
}
102+
103+
impl LiveRange {
104+
pub(crate) fn size(&self) -> usize {
105+
self.size
106+
}
107+
108+
pub(crate) fn start(&self) -> u64 {
109+
self.offset
110+
}
111+
112+
pub(crate) fn end(&self) -> u64 {
113+
self.offset + self.size as u64
114+
}
115+
116+
pub(crate) fn range(&self) -> Range<u64> {
117+
self.start()..self.end()
118+
}
119+
}
120+
121+
impl Drop for LiveRange {
122+
fn drop(&mut self) {
123+
self.inner.maple.erase(self.offset as usize);
124+
}
125+
}

0 commit comments

Comments
 (0)