Skip to content

Commit d38b3c8

Browse files
committed
drm/asahi: gpu,hw: Fix array IOMappings
These arrays aren't consecutive, but rather are supposed to have a stride and possibly also span multiple dies. This doesn't affect T8xxx, but I have no idea how this ever worked for T60xx... Signed-off-by: Asahi Lina <lina@asahilina.net>
1 parent 9e179fa commit d38b3c8

8 files changed

Lines changed: 171 additions & 126 deletions

File tree

drivers/gpu/drm/asahi/fw/initdata.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -591,8 +591,8 @@ pub(crate) mod raw {
591591
pub(crate) struct IOMapping {
592592
pub(crate) phys_addr: U64,
593593
pub(crate) virt_addr: U64,
594-
pub(crate) size: u32,
595-
pub(crate) range_size: u32,
594+
pub(crate) total_size: u32,
595+
pub(crate) element_size: u32,
596596
pub(crate) readwrite: U64,
597597
}
598598

drivers/gpu/drm/asahi/gpu.rs

Lines changed: 62 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,10 @@ const IOVA_KERN_GPU_TOP: u64 = 0xffffffadffffffff;
9191
const IOVA_KERN_RTKIT_BASE: u64 = 0xffffffae00000000;
9292
/// GPU/FW shared structure VA range top.
9393
const IOVA_KERN_RTKIT_TOP: u64 = 0xffffffae0fffffff;
94+
/// FW MMIO VA range base.
95+
const IOVA_KERN_MMIO_BASE: u64 = 0xffffffaf00000000;
96+
/// FW MMIO VA range top.
97+
const IOVA_KERN_MMIO_TOP: u64 = 0xffffffafffffffff;
9498

9599
/// GPU/FW buffer manager control address (context 0 low)
96100
pub(crate) const IOVA_KERN_GPU_BUFMGR_LOW: u64 = 0x20_0000_0000;
@@ -202,6 +206,7 @@ pub(crate) struct GpuManager {
202206
#[pin]
203207
alloc: Mutex<KernelAllocators>,
204208
io_mappings: Vec<mmu::Mapping>,
209+
next_mmio_iova: u64,
205210
#[pin]
206211
rtkit: Mutex<Option<rtkit::RtKit<GpuManager::ver>>>,
207212
#[pin]
@@ -506,18 +511,19 @@ impl GpuManager::ver {
506511

507512
for (i, map) in cfg.io_mappings.iter().enumerate() {
508513
if let Some(map) = map.as_ref() {
509-
Self::iomap(&mut mgr, i, map)?;
514+
Self::iomap(&mut mgr, cfg, i, map)?;
510515
}
511516
}
512517

513518
#[ver(V >= V13_0B4)]
514519
if let Some(base) = cfg.sram_base {
515520
let size = cfg.sram_size.unwrap() as usize;
521+
let iova = mgr.as_mut().alloc_mmio_iova(size);
516522

517523
let mapping =
518524
mgr.uat
519525
.kernel_vm()
520-
.map_io(base as usize, size, mmu::PROT_FW_SHARED_RW)?;
526+
.map_io(iova, base as usize, size, mmu::PROT_FW_SHARED_RW)?;
521527

522528
mgr.as_mut()
523529
.initdata_mut()
@@ -558,6 +564,21 @@ impl GpuManager::ver {
558564
unsafe { &mut self.get_unchecked_mut().io_mappings }
559565
}
560566

567+
/// Allocate an MMIO iova range
568+
fn alloc_mmio_iova(self: Pin<&mut Self>, size: usize) -> u64 {
569+
// SAFETY: next_mmio_iova does not require structural pinning.
570+
let next_ref = unsafe { &mut self.get_unchecked_mut().next_mmio_iova };
571+
572+
let addr = *next_ref;
573+
let next = addr + (size + mmu::UAT_PGSZ) as u64;
574+
575+
assert!(next - 1 <= IOVA_KERN_MMIO_TOP);
576+
577+
*next_ref = next;
578+
579+
addr
580+
}
581+
561582
/// Build the entire GPU InitData structure tree and return it as a boxed GpuObject.
562583
fn make_initdata(
563584
dev: &AsahiDevice,
@@ -648,6 +669,7 @@ impl GpuManager::ver {
648669
initdata: *initdata,
649670
uat: *uat,
650671
io_mappings: Vec::new(),
672+
next_mmio_iova: IOVA_KERN_MMIO_BASE,
651673
rtkit <- Mutex::new_named(None, c_str!("rtkit")),
652674
crashed: AtomicBool::new(false),
653675
event_manager,
@@ -774,21 +796,47 @@ impl GpuManager::ver {
774796
/// index.
775797
fn iomap(
776798
this: &mut Pin<UniqueArc<GpuManager::ver>>,
799+
cfg: &'static hw::HwConfig,
777800
index: usize,
778801
map: &hw::IOMapping,
779802
) -> Result {
803+
let dies = if map.per_die {
804+
cfg.num_dies as usize
805+
} else {
806+
1
807+
};
808+
780809
let off = map.base & mmu::UAT_PGMSK;
781810
let base = map.base - off;
782811
let end = (map.base + map.size + mmu::UAT_PGMSK) & !mmu::UAT_PGMSK;
783-
let mapping = this.uat.kernel_vm().map_io(
784-
base,
785-
end - base,
786-
if map.writable {
787-
mmu::PROT_FW_MMIO_RW
788-
} else {
789-
mmu::PROT_FW_MMIO_RO
790-
},
791-
)?;
812+
let map_size = end - base;
813+
814+
// Array mappings must be aligned
815+
assert!((off == 0 && map_size == map.size) || (map.count == 1 && !map.per_die));
816+
assert!(map.count > 0);
817+
818+
let iova = this.as_mut().alloc_mmio_iova(map_size * map.count * dies);
819+
let mut cur_iova = iova;
820+
821+
for die in 0..dies {
822+
for i in 0..map.count {
823+
let phys_off = die * 0x20_0000_0000 + i * map.stride;
824+
825+
let mapping = this.uat.kernel_vm().map_io(
826+
cur_iova,
827+
base + phys_off,
828+
map_size,
829+
if map.writable {
830+
mmu::PROT_FW_MMIO_RW
831+
} else {
832+
mmu::PROT_FW_MMIO_RO
833+
},
834+
)?;
835+
836+
this.as_mut().io_mappings_mut().try_push(mapping)?;
837+
cur_iova += map_size as u64;
838+
}
839+
}
792840

793841
this.as_mut()
794842
.initdata_mut()
@@ -797,14 +845,13 @@ impl GpuManager::ver {
797845
.with_mut(|raw, _| {
798846
raw.io_mappings[index] = fw::initdata::raw::IOMapping {
799847
phys_addr: U64(map.base as u64),
800-
virt_addr: U64((mapping.iova() + off) as u64),
801-
size: map.size as u32,
802-
range_size: map.range_size as u32,
848+
virt_addr: U64(iova + off as u64),
849+
total_size: (map.size * map.count * dies) as u32,
850+
element_size: map.size as u32,
803851
readwrite: U64(map.writable as u64),
804852
};
805853
});
806854

807-
this.as_mut().io_mappings_mut().try_push(mapping)?;
808855
Ok(())
809856
}
810857

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

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -133,10 +133,14 @@ pub(crate) struct PowerZone {
133133
pub(crate) struct IOMapping {
134134
/// Base physical address of the mapping.
135135
pub(crate) base: usize,
136-
/// Size of the mapping.
136+
/// Whether this mapping should be replicated to all dies
137+
pub(crate) per_die: bool,
138+
/// Number of mappings.
139+
pub(crate) count: usize,
140+
/// Size of one mapping.
137141
pub(crate) size: usize,
138-
/// Range size of the mapping (for arrays?)
139-
pub(crate) range_size: usize,
142+
/// Stride between mappings.
143+
pub(crate) stride: usize,
140144
/// Whether the mapping should be writable.
141145
pub(crate) writable: bool,
142146
}
@@ -145,14 +149,18 @@ impl IOMapping {
145149
/// Convenience constructor for a new IOMapping.
146150
pub(crate) const fn new(
147151
base: usize,
152+
per_die: bool,
153+
count: usize,
148154
size: usize,
149-
range_size: usize,
155+
stride: usize,
150156
writable: bool,
151157
) -> IOMapping {
152158
IOMapping {
153159
base,
160+
per_die,
161+
count,
154162
size,
155-
range_size,
163+
stride,
156164
writable,
157165
}
158166
}

drivers/gpu/drm/asahi/hw/t600x.rs

Lines changed: 23 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -8,36 +8,38 @@ use super::*;
88

99
const fn iomaps(mcc_count: usize, has_die1: bool) -> [Option<IOMapping>; 20] {
1010
[
11-
Some(IOMapping::new(0x404d00000, 0x1c000, 0x1c000, true)), // Fender
12-
Some(IOMapping::new(0x20e100000, 0x4000, 0x4000, false)), // AICTimer
13-
Some(IOMapping::new(0x28e104000, 0x4000, 0x4000, true)), // AICSWInt
14-
Some(IOMapping::new(0x404000000, 0x20000, 0x20000, true)), // RGX
15-
None, // UVD
16-
None, // unused
17-
None, // DisplayUnderrunWA
18-
Some(IOMapping::new(0x28e494000, 0x8000, 0x4000, false)), // AnalogTempSensorControllerRegs
19-
None, // PMPDoorbell
20-
Some(IOMapping::new(0x404d80000, 0x8000, 0x8000, true)), // MetrologySensorRegs
21-
Some(IOMapping::new(0x204d61000, 0x1000, 0x1000, true)), // GMGIFAFRegs
11+
Some(IOMapping::new(0x404d00000, false, 1, 0x1c000, 0, true)), // Fender
12+
Some(IOMapping::new(0x20e100000, false, 1, 0x4000, 0, false)), // AICTimer
13+
Some(IOMapping::new(0x28e104000, false, 1, 0x4000, 0, true)), // AICSWInt
14+
Some(IOMapping::new(0x404000000, false, 1, 0x20000, 0, true)), // RGX
15+
None, // UVD
16+
None, // unused
17+
None, // DisplayUnderrunWA
18+
Some(IOMapping::new(0x28e494000, true, 1, 0x4000, 0, false)), // AnalogTempSensorControllerRegs
19+
None, // PMPDoorbell
20+
Some(IOMapping::new(0x404d80000, false, 1, 0x8000, 0, true)), // MetrologySensorRegs
21+
Some(IOMapping::new(0x204d61000, false, 1, 0x1000, 0, true)), // GMGIFAFRegs
2222
Some(IOMapping::new(
2323
0x200000000,
24-
mcc_count * 0xd8000,
24+
true,
25+
mcc_count,
2526
0xd8000,
27+
0x1000000,
2628
true,
2729
)), // MCache registers
28-
None, // AICBankedRegisters
29-
None, // PMGRScratch
30-
Some(IOMapping::new(0x2643c4000, 0x1000, 0x1000, true)), // NIA Special agent idle register die 0
30+
None, // AICBankedRegisters
31+
None, // PMGRScratch
32+
Some(IOMapping::new(0x2643c4000, false, 1, 0x1000, 0, true)), // NIA Special agent idle register die 0
3133
if has_die1 {
3234
// NIA Special agent idle register die 1
33-
Some(IOMapping::new(0x22643c4000, 0x1000, 0x1000, true))
35+
Some(IOMapping::new(0x22643c4000, false, 1, 0x1000, 0, true))
3436
} else {
3537
None
3638
},
37-
None, // CRE registers
38-
None, // Streaming codec registers
39-
Some(IOMapping::new(0x28e3d0000, 0x1000, 0x1000, true)), // ?
40-
Some(IOMapping::new(0x28e3c0000, 0x2000, 0x2000, false)), // ?
39+
None, // CRE registers
40+
None, // Streaming codec registers
41+
Some(IOMapping::new(0x28e3d0000, false, 1, 0x1000, 0, true)), // ?
42+
Some(IOMapping::new(0x28e3c0000, false, 1, 0x2000, 0, false)), // ?
4143
]
4244
}
4345

@@ -128,7 +130,7 @@ pub(crate) const HWCONFIG_T6002: super::HwConfig = HwConfig {
128130
fast_sensor_mask: [0x8080808080808080, 0],
129131
fast_sensor_mask_alt: [0x9090909090909090, 0],
130132
fast_die0_sensor_present: 0xff,
131-
io_mappings: &iomaps(16, true),
133+
io_mappings: &iomaps(8, true),
132134
sram_base: None,
133135
sram_size: None,
134136
};

drivers/gpu/drm/asahi/hw/t602x.rs

Lines changed: 22 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -8,41 +8,38 @@ use super::*;
88

99
const fn iomaps(chip_id: u32, mcc_count: usize) -> [Option<IOMapping>; 24] {
1010
[
11-
Some(IOMapping::new(0x404d00000, 0x144000, 0x144000, true)), // Fender
12-
Some(IOMapping::new(0x20e100000, 0x4000, 0x4000, false)), // AICTimer
13-
Some(IOMapping::new(0x28e106000, 0x4000, 0x4000, true)), // AICSWInt
14-
Some(IOMapping::new(0x404000000, 0x20000, 0x20000, true)), // RGX
15-
None, // UVD
16-
None, // unused
17-
None, // DisplayUnderrunWA
11+
Some(IOMapping::new(0x404d00000, false, 1, 0x144000, 0, true)), // Fender
12+
Some(IOMapping::new(0x20e100000, false, 1, 0x4000, 0, false)), // AICTimer
13+
Some(IOMapping::new(0x28e106000, false, 1, 0x4000, 0, true)), // AICSWInt
14+
Some(IOMapping::new(0x404000000, false, 1, 0x20000, 0, true)), // RGX
15+
None, // UVD
16+
None, // unused
17+
None, // DisplayUnderrunWA
1818
Some(match chip_id {
19-
0x6020 => IOMapping::new(0x28e460000, 0x4000, 0x4000, false),
20-
_ => IOMapping::new(0x28e478000, 0x8000, 0x4000, false),
19+
0x6020 => IOMapping::new(0x28e460000, true, 1, 0x4000, 0, false),
20+
_ => IOMapping::new(0x28e478000, true, 1, 0x4000, 0, false),
2121
}), // AnalogTempSensorControllerRegs
22-
None, // PMPDoorbell
23-
Some(IOMapping::new(0x404e08000, 0x8000, 0x8000, true)), // MetrologySensorRegs
24-
None, // GMGIFAFRegs
22+
None, // PMPDoorbell
23+
Some(IOMapping::new(0x404e08000, false, 1, 0x8000, 0, true)), // MetrologySensorRegs
24+
None, // GMGIFAFRegs
2525
Some(IOMapping::new(
2626
0x200000000,
27-
mcc_count * 0xd8000,
27+
true,
28+
mcc_count,
2829
0xd8000,
30+
0x1000000,
2931
true,
3032
)), // MCache registers
31-
Some(IOMapping::new(0x28e118000, 0x4000, 0x4000, false)), // AICBankedRegisters
32-
None, // PMGRScratch
33+
Some(IOMapping::new(0x28e118000, false, 1, 0x4000, 0, false)), // AICBankedRegisters
34+
None, // PMGRScratch
3335
None, // NIA Special agent idle register die 0
3436
None, // NIA Special agent idle register die 1
3537
None, // CRE registers
3638
None, // Streaming codec registers
37-
Some(IOMapping::new(0x28e3d0000, 0x4000, 0x4000, true)), // ?
38-
Some(IOMapping::new(0x28e3c0000, 0x4000, 0x4000, false)), // ?
39-
Some(IOMapping::new(0x28e3d8000, 0x4000, 0x4000, true)), // ?
40-
Some(IOMapping::new(
41-
0x404eac000,
42-
if mcc_count > 8 { 0x8000 } else { 0x4000 },
43-
0x4000,
44-
true,
45-
)), // ?
39+
Some(IOMapping::new(0x28e3d0000, false, 1, 0x4000, 0, true)), // ?
40+
Some(IOMapping::new(0x28e3c0000, false, 1, 0x4000, 0, false)), // ?
41+
Some(IOMapping::new(0x28e3d8000, false, 1, 0x4000, 0, true)), // ?
42+
Some(IOMapping::new(0x404eac000, true, 1, 0x4000, 0, true)), // ?
4643
None,
4744
None,
4845
]
@@ -146,7 +143,7 @@ pub(crate) const HWCONFIG_T6022: super::HwConfig = HwConfig {
146143
// Apple typo? Should probably be 0x140015001c001d00
147144
fast_sensor_mask_alt: [0x140015001d001d00, 0x1d001c0015001400],
148145
fast_die0_sensor_present: 0, // Unused
149-
io_mappings: &iomaps(0x6022, 16),
146+
io_mappings: &iomaps(0x6022, 8),
150147
sram_base: Some(0x404d60000),
151148
sram_size: Some(0x20000),
152149
};

drivers/gpu/drm/asahi/hw/t8103.rs

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -68,20 +68,20 @@ pub(crate) const HWCONFIG: super::HwConfig = HwConfig {
6868
fast_sensor_mask_alt: [0x12, 0],
6969
fast_die0_sensor_present: 0x01,
7070
io_mappings: &[
71-
Some(IOMapping::new(0x204d00000, 0x1c000, 0x1c000, true)), // Fender
72-
Some(IOMapping::new(0x20e100000, 0x4000, 0x4000, false)), // AICTimer
73-
Some(IOMapping::new(0x23b104000, 0x4000, 0x4000, true)), // AICSWInt
74-
Some(IOMapping::new(0x204000000, 0x20000, 0x20000, true)), // RGX
75-
None, // UVD
76-
None, // unused
77-
None, // DisplayUnderrunWA
78-
Some(IOMapping::new(0x23b2e8000, 0x1000, 0x1000, false)), // AnalogTempSensorControllerRegs
79-
Some(IOMapping::new(0x23bc00000, 0x1000, 0x1000, true)), // PMPDoorbell
80-
Some(IOMapping::new(0x204d80000, 0x5000, 0x5000, true)), // MetrologySensorRegs
81-
Some(IOMapping::new(0x204d61000, 0x1000, 0x1000, true)), // GMGIFAFRegs
82-
Some(IOMapping::new(0x200000000, 0xd6400, 0xd6400, true)), // MCache registers
83-
None, // AICBankedRegisters
84-
Some(IOMapping::new(0x23b738000, 0x1000, 0x1000, true)), // PMGRScratch
71+
Some(IOMapping::new(0x204d00000, false, 1, 0x1c000, 0, true)), // Fender
72+
Some(IOMapping::new(0x20e100000, false, 1, 0x4000, 0, false)), // AICTimer
73+
Some(IOMapping::new(0x23b104000, false, 1, 0x4000, 0, true)), // AICSWInt
74+
Some(IOMapping::new(0x204000000, false, 1, 0x20000, 0, true)), // RGX
75+
None, // UVD
76+
None, // unused
77+
None, // DisplayUnderrunWA
78+
Some(IOMapping::new(0x23b2e8000, false, 1, 0x1000, 0, false)), // AnalogTempSensorControllerRegs
79+
Some(IOMapping::new(0x23bc00000, false, 1, 0x1000, 0, true)), // PMPDoorbell
80+
Some(IOMapping::new(0x204d80000, false, 1, 0x5000, 0, true)), // MetrologySensorRegs
81+
Some(IOMapping::new(0x204d61000, false, 1, 0x1000, 0, true)), // GMGIFAFRegs
82+
Some(IOMapping::new(0x200000000, false, 1, 0xd6400, 0, true)), // MCache registers
83+
None, // AICBankedRegisters
84+
Some(IOMapping::new(0x23b738000, false, 1, 0x1000, 0, true)), // PMGRScratch
8585
None, // NIA Special agent idle register die 0
8686
None, // NIA Special agent idle register die 1
8787
None, // CRE registers

0 commit comments

Comments
 (0)