From efcd402f4ccd5ecfb91745a944c328486af3745e Mon Sep 17 00:00:00 2001 From: Satya Benson Date: Tue, 3 Nov 2026 16:28:32 -0500 Subject: [PATCH 1/4] drm/asahi: admit authorized HIGH queues on Extended T8122 Signed-off-by: Satya Benson --- drivers/gpu/drm/asahi/file.rs | 10 ++++- drivers/gpu/drm/asahi/m3/m3_drm.rs | 5 +++ tools/asahi/queue-priority-tests.py | 69 +++++++++++++++++++++++++++++ 3 files changed, 82 insertions(+), 2 deletions(-) create mode 100644 tools/asahi/queue-priority-tests.py diff --git a/drivers/gpu/drm/asahi/file.rs b/drivers/gpu/drm/asahi/file.rs index 24e8db30e580..a09fa33ed02a 100644 --- a/drivers/gpu/drm/asahi/file.rs +++ b/drivers/gpu/drm/asahi/file.rs @@ -1350,9 +1350,15 @@ impl File { cls_pr_debug!(Errors, "queue_create: Invalid priority\n"); return Err(EINVAL); } - // HIGH has only been run on G17; G13 and G14 keep refusing it. + // Keep support tied to a backend and admitted profile. G13/G14 and + // unqualified M3 profiles retain their previous rejection. + let high_supported = reg_data.gpu.as_any().is::(); + #[cfg(CONFIG_DRM_ASAHI_M3_T8122)] + let high_supported = high_supported || reg_data.gpu.as_any() + .downcast_ref::() + .is_some_and(|gpu| gpu.supports_high_priority()); if data.priority == uapi::drm_asahi_priority_DRM_ASAHI_PRIORITY_HIGH - && !reg_data.gpu.as_any().is::() + && !high_supported { cls_pr_debug!( Errors, diff --git a/drivers/gpu/drm/asahi/m3/m3_drm.rs b/drivers/gpu/drm/asahi/m3/m3_drm.rs index 8aedd920f31d..555edf7074a6 100644 --- a/drivers/gpu/drm/asahi/m3/m3_drm.rs +++ b/drivers/gpu/drm/asahi/m3/m3_drm.rs @@ -96,6 +96,11 @@ pub(crate) struct Backend { } impl Backend { + /// HIGH promises host publication ordering, not firmware preemption. + pub(crate) fn supports_high_priority(&self) -> bool { + self.soc.chip_id == 0x8122 && self.profile == super::m3_profile::Profile::Extended + } + /// Admits and starts the M3 runtime on `soc` (the T8122), with the DRM device `drm` that the /// caller registers afterwards. pub(crate) fn start( diff --git a/tools/asahi/queue-priority-tests.py b/tools/asahi/queue-priority-tests.py new file mode 100644 index 000000000000..5ecce0620588 --- /dev/null +++ b/tools/asahi/queue-priority-tests.py @@ -0,0 +1,69 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: GPL-2.0-only OR MIT +"""Compile the production queue admission gate with controlled credentials/backends.""" +from pathlib import Path +import subprocess +import tempfile +root = Path(__file__).resolve().parents[2] +s = (root / 'drivers/gpu/drm/asahi/file.rs').read_text() +a = s.index(' if data.flags != 0', s.index('pub(crate) fn queue_create(')) +b = s.index(' let queues_xa', a) +gate = s[a:b] +predicate = (root / 'drivers/gpu/drm/asahi/m3/m3_drm.rs').read_text().split('pub(crate) fn supports_high_priority(&self) -> bool {', 1)[1].split('\n }', 1)[0] +unit = r''' +#![allow(dead_code, non_upper_case_globals)] +use std::any::Any; +const EINVAL:i32=22; const EACCES:i32=13; +macro_rules! cls_pr_debug { ($($arg:tt)*) => {} } +mod uapi { + pub const drm_asahi_priority_DRM_ASAHI_PRIORITY_REALTIME:u32=3; + pub const drm_asahi_priority_DRM_ASAHI_PRIORITY_HIGH:u32=2; +} +mod bindings { pub const CAP_SYS_NICE:u32=23; + pub unsafe fn capable(_:u32)->bool { CAP.with(|c|c.get()) } + thread_local! {pub static CAP:std::cell::Cell=const {std::cell::Cell::new(false)};} +} +mod g17 {pub struct Gpu;} +mod m3 {pub mod m3_drm { + #[derive(PartialEq)] pub enum Profile {Legacy, Extended} + pub struct Soc {pub chip_id:u32} + pub struct Backend {pub soc:Soc,pub profile:Profile} + impl Backend {pub fn supports_high_priority(&self)->bool { PREDICATE }} +}} +struct Gpu(Box); impl Gpu {fn as_any(&self)->&dyn Any {&*self.0}} +struct Reg {gpu:Gpu} +struct Data {flags:u32,priority:u32} +struct File(bool); impl File {fn is_current_master(&self)->bool {self.0}} +fn admit(reg_data:&Reg,data:&Data,file:&File)->Result<(),i32> { GATE Ok(()) } +fn main() { + use m3::m3_drm::*; + let mut n=0; + for backend in 0..5 { for cap in [false,true] { for master in [false,true] { + let gpu:Box=match backend { + 0=>Box::new(g17::Gpu), + 1=>Box::new(Backend{soc:Soc{chip_id:0x8122},profile:Profile::Extended}), + 2=>Box::new(Backend{soc:Soc{chip_id:0x8122},profile:Profile::Legacy}), + 3=>Box::new(Backend{soc:Soc{chip_id:0x6030},profile:Profile::Extended}), + _=>Box::new(())}; + let reg=Reg{gpu:Gpu(gpu)}; + bindings::CAP.with(|c|c.set(cap)); + for flags in [0,1,u32::MAX] { for priority in [0,1,2,3,4,u32::MAX] { + let expected=if flags!=0 || priority>=3 {Err(EINVAL)} + else if priority!=2 {Ok(())} + else if backend!=0 && !(backend==1 && cfg!(CONFIG_DRM_ASAHI_M3_T8122)) {Err(EINVAL)} + else if cap||master {Ok(())} else {Err(EACCES)}; + assert_eq!(admit(®,&Data{flags,priority},&File(master)),expected, + "backend={backend} cap={cap} master={master} flags={flags} priority={priority}"); n+=1; + }} + }}} + println!("{n} actual admission cases passed"); +} +'''.replace('PREDICATE', predicate.replace('super::m3_profile::Profile', 'Profile')).replace('GATE', gate) +with tempfile.TemporaryDirectory(prefix='queue-priority-') as d: + p = Path(d) / 'gate.rs' + p.write_text(unit) + for enabled in [False, True]: + subprocess.run(['rustc', '--edition=2021', *(['--cfg', 'CONFIG_DRM_ASAHI_M3_T8122'] if enabled else []), str(p), '-o', str(p.with_suffix(''))], check=True) + # Without M3 compiled only the G17 backend is admitted. + subprocess.run([str(p.with_suffix(''))], check=True) +print('M3 enabled/disabled gate compilation passed') From c1c0e23c6e4f50e03038a22a6cab7f8d72e39a54 Mon Sep 17 00:00:00 2001 From: Satya Benson Date: Tue, 3 Nov 2026 17:25:00 -0500 Subject: [PATCH 2/4] drm/asahi: test the M3 host priority mapping alongside admission Signed-off-by: Satya Benson --- tools/asahi/queue-priority-tests.py | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/tools/asahi/queue-priority-tests.py b/tools/asahi/queue-priority-tests.py index 5ecce0620588..cfbbe8f36d4e 100644 --- a/tools/asahi/queue-priority-tests.py +++ b/tools/asahi/queue-priority-tests.py @@ -10,6 +10,10 @@ b = s.index(' let queues_xa', a) gate = s[a:b] predicate = (root / 'drivers/gpu/drm/asahi/m3/m3_drm.rs').read_text().split('pub(crate) fn supports_high_priority(&self) -> bool {', 1)[1].split('\n }', 1)[0] +submit = (root / 'drivers/gpu/drm/asahi/m3/m3_submit.rs').read_text() +ordering = submit.split(' let urgency=', 1)[1].split(' Ok(Self', 1)[0] +ordering = 'let urgency=' + ordering +assert 'uapi::drm_asahi_priority_DRM_ASAHI_PRIORITY_REALTIME - data.priority' in s unit = r''' #![allow(dead_code, non_upper_case_globals)] use std::any::Any; @@ -35,6 +39,13 @@ struct Data {flags:u32,priority:u32} struct File(bool); impl File {fn is_current_master(&self)->bool {self.0}} fn admit(reg_data:&Reg,data:&Data,file:&File)->Result<(),i32> { GATE Ok(()) } +mod sched { + #[derive(Debug,PartialEq)] pub enum Priority {Low,Normal,High,Kernel} +} +fn ordering(priority:u32)->Result<(u8,sched::Priority),i32> { + ORDERING + Ok((urgency,priority)) +} fn main() { use m3::m3_drm::*; let mut n=0; @@ -56,9 +67,13 @@ "backend={backend} cap={cap} master={master} flags={flags} priority={priority}"); n+=1; }} }}} - println!("{n} actual admission cases passed"); + for (uapi,expected) in [(0,sched::Priority::Low),(1,sched::Priority::Normal),(2,sched::Priority::High)] { + assert_eq!(ordering(3-uapi),Ok((uapi as u8,expected))); + } + assert_eq!(ordering(4),Err(EINVAL)); + println!("{n} actual admission cases and LOW/MEDIUM/HIGH host mappings passed"); } -'''.replace('PREDICATE', predicate.replace('super::m3_profile::Profile', 'Profile')).replace('GATE', gate) +'''.replace('PREDICATE', predicate.replace('super::m3_profile::Profile', 'Profile')).replace('GATE', gate).replace('ORDERING', ordering) with tempfile.TemporaryDirectory(prefix='queue-priority-') as d: p = Path(d) / 'gate.rs' p.write_text(unit) From ba872b99a0039f15a82fa0f91ed7b8ab4e5905c1 Mon Sep 17 00:00:00 2001 From: Satya Benson Date: Tue, 3 Nov 2026 20:36:32 -0500 Subject: [PATCH 3/4] ci: register the M3 queue priority admission tests Signed-off-by: Satya Benson --- tools/asahi/run-host-tests.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/asahi/run-host-tests.py b/tools/asahi/run-host-tests.py index 5dfda83574ea..4ebce94ccb47 100755 --- a/tools/asahi/run-host-tests.py +++ b/tools/asahi/run-host-tests.py @@ -53,6 +53,7 @@ def mutations(flag, names, base, expect=KILL): # test file -> [(arguments, expectation)]. '{out}' is a fresh directory. ASAHI_TESTS = { + 'queue-priority-tests.py': [([], PASS)], 'test-m3-power.py': [([], PASS)], 'test-m3-uapi.py': [([], PASS)], 'test-m3-mailbox.py': [([], PASS)], From 40c0f578fa188d83dbe58f0cdd0780aff05696fa Mon Sep 17 00:00:00 2001 From: Satya Benson Date: Wed, 4 Nov 2026 21:13:17 -0500 Subject: [PATCH 4/4] selftests: asahi: match the 7.3 capability argument type Signed-off-by: Satya Benson --- tools/asahi/queue-priority-tests.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/asahi/queue-priority-tests.py b/tools/asahi/queue-priority-tests.py index cfbbe8f36d4e..1c5b4695c85f 100644 --- a/tools/asahi/queue-priority-tests.py +++ b/tools/asahi/queue-priority-tests.py @@ -24,7 +24,7 @@ pub const drm_asahi_priority_DRM_ASAHI_PRIORITY_HIGH:u32=2; } mod bindings { pub const CAP_SYS_NICE:u32=23; - pub unsafe fn capable(_:u32)->bool { CAP.with(|c|c.get()) } + pub unsafe fn capable(_:i32)->bool { CAP.with(|c|c.get()) } thread_local! {pub static CAP:std::cell::Cell=const {std::cell::Cell::new(false)};} } mod g17 {pub struct Gpu;}