Skip to content

Commit

Permalink
drm/asahi: gpu,hw: Fix array IOMappings
Browse files Browse the repository at this point in the history
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 <[email protected]>
  • Loading branch information
asahilina committed Aug 9, 2023
1 parent 9e179fa commit d38b3c8
Show file tree
Hide file tree
Showing 8 changed files with 171 additions and 126 deletions.
4 changes: 2 additions & 2 deletions drivers/gpu/drm/asahi/fw/initdata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -591,8 +591,8 @@ pub(crate) mod raw {
pub(crate) struct IOMapping {
pub(crate) phys_addr: U64,
pub(crate) virt_addr: U64,
pub(crate) size: u32,
pub(crate) range_size: u32,
pub(crate) total_size: u32,
pub(crate) element_size: u32,
pub(crate) readwrite: U64,
}

Expand Down
77 changes: 62 additions & 15 deletions drivers/gpu/drm/asahi/gpu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,10 @@ const IOVA_KERN_GPU_TOP: u64 = 0xffffffadffffffff;
const IOVA_KERN_RTKIT_BASE: u64 = 0xffffffae00000000;
/// GPU/FW shared structure VA range top.
const IOVA_KERN_RTKIT_TOP: u64 = 0xffffffae0fffffff;
/// FW MMIO VA range base.
const IOVA_KERN_MMIO_BASE: u64 = 0xffffffaf00000000;
/// FW MMIO VA range top.
const IOVA_KERN_MMIO_TOP: u64 = 0xffffffafffffffff;

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

for (i, map) in cfg.io_mappings.iter().enumerate() {
if let Some(map) = map.as_ref() {
Self::iomap(&mut mgr, i, map)?;
Self::iomap(&mut mgr, cfg, i, map)?;
}
}

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

let mapping =
mgr.uat
.kernel_vm()
.map_io(base as usize, size, mmu::PROT_FW_SHARED_RW)?;
.map_io(iova, base as usize, size, mmu::PROT_FW_SHARED_RW)?;

mgr.as_mut()
.initdata_mut()
Expand Down Expand Up @@ -558,6 +564,21 @@ impl GpuManager::ver {
unsafe { &mut self.get_unchecked_mut().io_mappings }
}

/// Allocate an MMIO iova range
fn alloc_mmio_iova(self: Pin<&mut Self>, size: usize) -> u64 {
// SAFETY: next_mmio_iova does not require structural pinning.
let next_ref = unsafe { &mut self.get_unchecked_mut().next_mmio_iova };

let addr = *next_ref;
let next = addr + (size + mmu::UAT_PGSZ) as u64;

assert!(next - 1 <= IOVA_KERN_MMIO_TOP);

*next_ref = next;

addr
}

/// Build the entire GPU InitData structure tree and return it as a boxed GpuObject.
fn make_initdata(
dev: &AsahiDevice,
Expand Down Expand Up @@ -648,6 +669,7 @@ impl GpuManager::ver {
initdata: *initdata,
uat: *uat,
io_mappings: Vec::new(),
next_mmio_iova: IOVA_KERN_MMIO_BASE,
rtkit <- Mutex::new_named(None, c_str!("rtkit")),
crashed: AtomicBool::new(false),
event_manager,
Expand Down Expand Up @@ -774,21 +796,47 @@ impl GpuManager::ver {
/// index.
fn iomap(
this: &mut Pin<UniqueArc<GpuManager::ver>>,
cfg: &'static hw::HwConfig,
index: usize,
map: &hw::IOMapping,
) -> Result {
let dies = if map.per_die {
cfg.num_dies as usize
} else {
1
};

let off = map.base & mmu::UAT_PGMSK;
let base = map.base - off;
let end = (map.base + map.size + mmu::UAT_PGMSK) & !mmu::UAT_PGMSK;
let mapping = this.uat.kernel_vm().map_io(
base,
end - base,
if map.writable {
mmu::PROT_FW_MMIO_RW
} else {
mmu::PROT_FW_MMIO_RO
},
)?;
let map_size = end - base;

// Array mappings must be aligned
assert!((off == 0 && map_size == map.size) || (map.count == 1 && !map.per_die));
assert!(map.count > 0);

let iova = this.as_mut().alloc_mmio_iova(map_size * map.count * dies);
let mut cur_iova = iova;

for die in 0..dies {
for i in 0..map.count {
let phys_off = die * 0x20_0000_0000 + i * map.stride;

let mapping = this.uat.kernel_vm().map_io(
cur_iova,
base + phys_off,
map_size,
if map.writable {
mmu::PROT_FW_MMIO_RW
} else {
mmu::PROT_FW_MMIO_RO
},
)?;

this.as_mut().io_mappings_mut().try_push(mapping)?;
cur_iova += map_size as u64;
}
}

this.as_mut()
.initdata_mut()
Expand All @@ -797,14 +845,13 @@ impl GpuManager::ver {
.with_mut(|raw, _| {
raw.io_mappings[index] = fw::initdata::raw::IOMapping {
phys_addr: U64(map.base as u64),
virt_addr: U64((mapping.iova() + off) as u64),
size: map.size as u32,
range_size: map.range_size as u32,
virt_addr: U64(iova + off as u64),
total_size: (map.size * map.count * dies) as u32,
element_size: map.size as u32,
readwrite: U64(map.writable as u64),
};
});

this.as_mut().io_mappings_mut().try_push(mapping)?;
Ok(())
}

Expand Down
18 changes: 13 additions & 5 deletions drivers/gpu/drm/asahi/hw/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,10 +133,14 @@ pub(crate) struct PowerZone {
pub(crate) struct IOMapping {
/// Base physical address of the mapping.
pub(crate) base: usize,
/// Size of the mapping.
/// Whether this mapping should be replicated to all dies
pub(crate) per_die: bool,
/// Number of mappings.
pub(crate) count: usize,
/// Size of one mapping.
pub(crate) size: usize,
/// Range size of the mapping (for arrays?)
pub(crate) range_size: usize,
/// Stride between mappings.
pub(crate) stride: usize,
/// Whether the mapping should be writable.
pub(crate) writable: bool,
}
Expand All @@ -145,14 +149,18 @@ impl IOMapping {
/// Convenience constructor for a new IOMapping.
pub(crate) const fn new(
base: usize,
per_die: bool,
count: usize,
size: usize,
range_size: usize,
stride: usize,
writable: bool,
) -> IOMapping {
IOMapping {
base,
per_die,
count,
size,
range_size,
stride,
writable,
}
}
Expand Down
44 changes: 23 additions & 21 deletions drivers/gpu/drm/asahi/hw/t600x.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,36 +8,38 @@ use super::*;

const fn iomaps(mcc_count: usize, has_die1: bool) -> [Option<IOMapping>; 20] {
[
Some(IOMapping::new(0x404d00000, 0x1c000, 0x1c000, true)), // Fender
Some(IOMapping::new(0x20e100000, 0x4000, 0x4000, false)), // AICTimer
Some(IOMapping::new(0x28e104000, 0x4000, 0x4000, true)), // AICSWInt
Some(IOMapping::new(0x404000000, 0x20000, 0x20000, true)), // RGX
None, // UVD
None, // unused
None, // DisplayUnderrunWA
Some(IOMapping::new(0x28e494000, 0x8000, 0x4000, false)), // AnalogTempSensorControllerRegs
None, // PMPDoorbell
Some(IOMapping::new(0x404d80000, 0x8000, 0x8000, true)), // MetrologySensorRegs
Some(IOMapping::new(0x204d61000, 0x1000, 0x1000, true)), // GMGIFAFRegs
Some(IOMapping::new(0x404d00000, false, 1, 0x1c000, 0, true)), // Fender
Some(IOMapping::new(0x20e100000, false, 1, 0x4000, 0, false)), // AICTimer
Some(IOMapping::new(0x28e104000, false, 1, 0x4000, 0, true)), // AICSWInt
Some(IOMapping::new(0x404000000, false, 1, 0x20000, 0, true)), // RGX
None, // UVD
None, // unused
None, // DisplayUnderrunWA
Some(IOMapping::new(0x28e494000, true, 1, 0x4000, 0, false)), // AnalogTempSensorControllerRegs
None, // PMPDoorbell
Some(IOMapping::new(0x404d80000, false, 1, 0x8000, 0, true)), // MetrologySensorRegs
Some(IOMapping::new(0x204d61000, false, 1, 0x1000, 0, true)), // GMGIFAFRegs
Some(IOMapping::new(
0x200000000,
mcc_count * 0xd8000,
true,
mcc_count,
0xd8000,
0x1000000,
true,
)), // MCache registers
None, // AICBankedRegisters
None, // PMGRScratch
Some(IOMapping::new(0x2643c4000, 0x1000, 0x1000, true)), // NIA Special agent idle register die 0
None, // AICBankedRegisters
None, // PMGRScratch
Some(IOMapping::new(0x2643c4000, false, 1, 0x1000, 0, true)), // NIA Special agent idle register die 0
if has_die1 {
// NIA Special agent idle register die 1
Some(IOMapping::new(0x22643c4000, 0x1000, 0x1000, true))
Some(IOMapping::new(0x22643c4000, false, 1, 0x1000, 0, true))
} else {
None
},
None, // CRE registers
None, // Streaming codec registers
Some(IOMapping::new(0x28e3d0000, 0x1000, 0x1000, true)), // ?
Some(IOMapping::new(0x28e3c0000, 0x2000, 0x2000, false)), // ?
None, // CRE registers
None, // Streaming codec registers
Some(IOMapping::new(0x28e3d0000, false, 1, 0x1000, 0, true)), // ?
Some(IOMapping::new(0x28e3c0000, false, 1, 0x2000, 0, false)), // ?
]
}

Expand Down Expand Up @@ -128,7 +130,7 @@ pub(crate) const HWCONFIG_T6002: super::HwConfig = HwConfig {
fast_sensor_mask: [0x8080808080808080, 0],
fast_sensor_mask_alt: [0x9090909090909090, 0],
fast_die0_sensor_present: 0xff,
io_mappings: &iomaps(16, true),
io_mappings: &iomaps(8, true),
sram_base: None,
sram_size: None,
};
Expand Down
47 changes: 22 additions & 25 deletions drivers/gpu/drm/asahi/hw/t602x.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,41 +8,38 @@ use super::*;

const fn iomaps(chip_id: u32, mcc_count: usize) -> [Option<IOMapping>; 24] {
[
Some(IOMapping::new(0x404d00000, 0x144000, 0x144000, true)), // Fender
Some(IOMapping::new(0x20e100000, 0x4000, 0x4000, false)), // AICTimer
Some(IOMapping::new(0x28e106000, 0x4000, 0x4000, true)), // AICSWInt
Some(IOMapping::new(0x404000000, 0x20000, 0x20000, true)), // RGX
None, // UVD
None, // unused
None, // DisplayUnderrunWA
Some(IOMapping::new(0x404d00000, false, 1, 0x144000, 0, true)), // Fender
Some(IOMapping::new(0x20e100000, false, 1, 0x4000, 0, false)), // AICTimer
Some(IOMapping::new(0x28e106000, false, 1, 0x4000, 0, true)), // AICSWInt
Some(IOMapping::new(0x404000000, false, 1, 0x20000, 0, true)), // RGX
None, // UVD
None, // unused
None, // DisplayUnderrunWA
Some(match chip_id {
0x6020 => IOMapping::new(0x28e460000, 0x4000, 0x4000, false),
_ => IOMapping::new(0x28e478000, 0x8000, 0x4000, false),
0x6020 => IOMapping::new(0x28e460000, true, 1, 0x4000, 0, false),
_ => IOMapping::new(0x28e478000, true, 1, 0x4000, 0, false),
}), // AnalogTempSensorControllerRegs
None, // PMPDoorbell
Some(IOMapping::new(0x404e08000, 0x8000, 0x8000, true)), // MetrologySensorRegs
None, // GMGIFAFRegs
None, // PMPDoorbell
Some(IOMapping::new(0x404e08000, false, 1, 0x8000, 0, true)), // MetrologySensorRegs
None, // GMGIFAFRegs
Some(IOMapping::new(
0x200000000,
mcc_count * 0xd8000,
true,
mcc_count,
0xd8000,
0x1000000,
true,
)), // MCache registers
Some(IOMapping::new(0x28e118000, 0x4000, 0x4000, false)), // AICBankedRegisters
None, // PMGRScratch
Some(IOMapping::new(0x28e118000, false, 1, 0x4000, 0, false)), // AICBankedRegisters
None, // PMGRScratch
None, // NIA Special agent idle register die 0
None, // NIA Special agent idle register die 1
None, // CRE registers
None, // Streaming codec registers
Some(IOMapping::new(0x28e3d0000, 0x4000, 0x4000, true)), // ?
Some(IOMapping::new(0x28e3c0000, 0x4000, 0x4000, false)), // ?
Some(IOMapping::new(0x28e3d8000, 0x4000, 0x4000, true)), // ?
Some(IOMapping::new(
0x404eac000,
if mcc_count > 8 { 0x8000 } else { 0x4000 },
0x4000,
true,
)), // ?
Some(IOMapping::new(0x28e3d0000, false, 1, 0x4000, 0, true)), // ?
Some(IOMapping::new(0x28e3c0000, false, 1, 0x4000, 0, false)), // ?
Some(IOMapping::new(0x28e3d8000, false, 1, 0x4000, 0, true)), // ?
Some(IOMapping::new(0x404eac000, true, 1, 0x4000, 0, true)), // ?
None,
None,
]
Expand Down Expand Up @@ -146,7 +143,7 @@ pub(crate) const HWCONFIG_T6022: super::HwConfig = HwConfig {
// Apple typo? Should probably be 0x140015001c001d00
fast_sensor_mask_alt: [0x140015001d001d00, 0x1d001c0015001400],
fast_die0_sensor_present: 0, // Unused
io_mappings: &iomaps(0x6022, 16),
io_mappings: &iomaps(0x6022, 8),
sram_base: Some(0x404d60000),
sram_size: Some(0x20000),
};
Expand Down
28 changes: 14 additions & 14 deletions drivers/gpu/drm/asahi/hw/t8103.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,20 +68,20 @@ pub(crate) const HWCONFIG: super::HwConfig = HwConfig {
fast_sensor_mask_alt: [0x12, 0],
fast_die0_sensor_present: 0x01,
io_mappings: &[
Some(IOMapping::new(0x204d00000, 0x1c000, 0x1c000, true)), // Fender
Some(IOMapping::new(0x20e100000, 0x4000, 0x4000, false)), // AICTimer
Some(IOMapping::new(0x23b104000, 0x4000, 0x4000, true)), // AICSWInt
Some(IOMapping::new(0x204000000, 0x20000, 0x20000, true)), // RGX
None, // UVD
None, // unused
None, // DisplayUnderrunWA
Some(IOMapping::new(0x23b2e8000, 0x1000, 0x1000, false)), // AnalogTempSensorControllerRegs
Some(IOMapping::new(0x23bc00000, 0x1000, 0x1000, true)), // PMPDoorbell
Some(IOMapping::new(0x204d80000, 0x5000, 0x5000, true)), // MetrologySensorRegs
Some(IOMapping::new(0x204d61000, 0x1000, 0x1000, true)), // GMGIFAFRegs
Some(IOMapping::new(0x200000000, 0xd6400, 0xd6400, true)), // MCache registers
None, // AICBankedRegisters
Some(IOMapping::new(0x23b738000, 0x1000, 0x1000, true)), // PMGRScratch
Some(IOMapping::new(0x204d00000, false, 1, 0x1c000, 0, true)), // Fender
Some(IOMapping::new(0x20e100000, false, 1, 0x4000, 0, false)), // AICTimer
Some(IOMapping::new(0x23b104000, false, 1, 0x4000, 0, true)), // AICSWInt
Some(IOMapping::new(0x204000000, false, 1, 0x20000, 0, true)), // RGX
None, // UVD
None, // unused
None, // DisplayUnderrunWA
Some(IOMapping::new(0x23b2e8000, false, 1, 0x1000, 0, false)), // AnalogTempSensorControllerRegs
Some(IOMapping::new(0x23bc00000, false, 1, 0x1000, 0, true)), // PMPDoorbell
Some(IOMapping::new(0x204d80000, false, 1, 0x5000, 0, true)), // MetrologySensorRegs
Some(IOMapping::new(0x204d61000, false, 1, 0x1000, 0, true)), // GMGIFAFRegs
Some(IOMapping::new(0x200000000, false, 1, 0xd6400, 0, true)), // MCache registers
None, // AICBankedRegisters
Some(IOMapping::new(0x23b738000, false, 1, 0x1000, 0, true)), // PMGRScratch
None, // NIA Special agent idle register die 0
None, // NIA Special agent idle register die 1
None, // CRE registers
Expand Down
Loading

0 comments on commit d38b3c8

Please sign in to comment.