Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
127 commits
Select commit Hold shift + click to select a range
d3f6486
drm/apple: accept automatic PMGR activity in J613 coldplug
satchlj Oct 31, 2026
31a2f5d
test: vary unrelated bits in J613 PMGR state words
satchlj Oct 31, 2026
dfb9d8b
drm/asahi: describe the T8122 extended firmware profile and owned IO …
satchlj Oct 31, 2026
32ad468
drm/asahi: construct and publish extended T8122 initialization data
satchlj Oct 31, 2026
ee69dab
drm/asahi: prepare extended firmware queues and controller handoff
satchlj Oct 31, 2026
c5e1b35
drm/asahi: dispatch G15 compute through extended T8122 firmware
satchlj Oct 31, 2026
ec30b22
drm/asahi: enable J613 extended firmware render and retirement
satchlj Oct 31, 2026
efcd402
drm/asahi: admit authorized HIGH queues on Extended T8122
satchlj Nov 3, 2026
c1c0e23
drm/asahi: test the M3 host priority mapping alongside admission
satchlj Nov 3, 2026
ba872b9
ci: register the M3 queue priority admission tests
satchlj Nov 4, 2026
bd92c01
drm/asahi: back off interrupt-assisted M3 completion waits
satchlj Nov 3, 2026
9f3b310
drm/asahi: omit no-op M3 module pins without unload support
satchlj Nov 3, 2026
8f8374b
Merge branch 'satchlj/t8122-api-fixes-20261104' into satchlj/port-347…
satchlj Nov 5, 2026
40c0f57
selftests: asahi: match the 7.3 capability argument type
satchlj Nov 5, 2026
841394c
Merge branch 'satchlj/port-346-20261104' into satchlj/port-347-20261104
satchlj Nov 5, 2026
94d141f
Merge branch 'satchlj/t8122-api-fixes-20261104' into satchlj/port-303…
satchlj Nov 5, 2026
28caf6d
Merge branch 'satchlj/t8122-api-fixes-20261104' into satchlj/port-304…
satchlj Nov 5, 2026
2284c4e
Merge branch 'satchlj/t8122-api-fixes-20261104' into satchlj/port-305…
satchlj Nov 5, 2026
c3910f7
Merge branch 'satchlj/t8122-api-fixes-20261104' into satchlj/port-306…
satchlj Nov 5, 2026
a64da66
Merge branch 'satchlj/t8122-api-fixes-20261104' into satchlj/port-307…
satchlj Nov 5, 2026
3822ecc
Merge branch 'satchlj/t8122-api-fixes-20261104' into satchlj/port-346…
satchlj Nov 5, 2026
82aaf1b
Merge branch 'satchlj/t8122-api-fixes-20261104' into satchlj/port-347…
satchlj Nov 5, 2026
0a00e92
Merge branch 'satchlj/t8122-api-fixes-20261104' into satchlj/port-303…
satchlj Nov 5, 2026
c6ab2ef
Merge branch 'satchlj/t8122-api-fixes-20261104' into satchlj/port-304…
satchlj Nov 5, 2026
167dcfe
Merge branch 'satchlj/t8122-api-fixes-20261104' into satchlj/port-305…
satchlj Nov 5, 2026
4425ded
Merge branch 'satchlj/t8122-api-fixes-20261104' into satchlj/port-306…
satchlj Nov 5, 2026
8363fbb
Merge branch 'satchlj/t8122-api-fixes-20261104' into satchlj/port-307…
satchlj Nov 5, 2026
ae10e3b
Merge branch 'satchlj/t8122-api-fixes-20261104' into satchlj/port-346…
satchlj Nov 5, 2026
a3cf48e
Merge branch 'satchlj/t8122-api-fixes-20261104' into satchlj/port-347…
satchlj Nov 5, 2026
bdb27ea
Merge branch 'satchlj/t8122-api-fixes-20261104' into satchlj/port-303…
satchlj Nov 5, 2026
5f64a63
Merge branch 'satchlj/t8122-api-fixes-20261104' into satchlj/port-304…
satchlj Nov 5, 2026
9130710
Merge branch 'satchlj/t8122-api-fixes-20261104' into satchlj/port-305…
satchlj Nov 5, 2026
2cbb206
Merge branch 'satchlj/t8122-api-fixes-20261104' into satchlj/port-306…
satchlj Nov 5, 2026
7879118
Merge branch 'satchlj/t8122-api-fixes-20261104' into satchlj/port-307…
satchlj Nov 5, 2026
79d45bd
Merge branch 'satchlj/t8122-api-fixes-20261104' into satchlj/port-346…
satchlj Nov 5, 2026
d7be34e
Merge branch 'satchlj/t8122-api-fixes-20261104' into satchlj/port-347…
satchlj Nov 5, 2026
4b07a28
selftests: apple: accept the explicitly registered PMGR fixture
satchlj Nov 5, 2026
d92133b
Merge branch 'satchlj/port-301-20261104' into satchlj/port-303-20261104
satchlj Nov 5, 2026
471a4a4
Merge branch 'satchlj/port-302-20261104' into satchlj/port-303-20261104
satchlj Nov 5, 2026
cb3408f
Merge branch 'satchlj/port-303-20261104' into satchlj/port-304-20261104
satchlj Nov 5, 2026
d5fcae0
Merge branch 'satchlj/port-304-20261104' into satchlj/port-305-20261104
satchlj Nov 5, 2026
e71fbb0
Merge branch 'satchlj/port-305-20261104' into satchlj/port-306-20261104
satchlj Nov 5, 2026
72b6142
Merge branch 'satchlj/port-306-20261104' into satchlj/port-307-20261104
satchlj Nov 5, 2026
66eb34e
Merge branch 'satchlj/port-307-20261104' into satchlj/port-346-20261104
satchlj Nov 5, 2026
03692e5
Merge branch 'satchlj/port-346-20261104' into satchlj/port-347-20261104
satchlj Nov 5, 2026
a84b3dd
Merge branch 'satchlj/t8122-api-fixes-20261104' into satchlj/port-303…
satchlj Nov 5, 2026
f157192
Merge branch 'satchlj/t8122-api-fixes-20261104' into satchlj/port-304…
satchlj Nov 5, 2026
05524e2
Merge branch 'satchlj/t8122-api-fixes-20261104' into satchlj/port-305…
satchlj Nov 5, 2026
a0d0a49
Merge branch 'satchlj/t8122-api-fixes-20261104' into satchlj/port-306…
satchlj Nov 5, 2026
34de4e4
Merge branch 'satchlj/t8122-api-fixes-20261104' into satchlj/port-307…
satchlj Nov 5, 2026
119f1ea
Merge branch 'satchlj/t8122-api-fixes-20261104' into satchlj/port-346…
satchlj Nov 5, 2026
020e3f8
Merge branch 'satchlj/t8122-api-fixes-20261104' into satchlj/port-347…
satchlj Nov 5, 2026
1f39fce
Merge branch 'satchlj/t8122-api-fixes-20261104' into satchlj/port-303…
satchlj Nov 5, 2026
4583d2a
Merge branch 'satchlj/t8122-api-fixes-20261104' into satchlj/port-304…
satchlj Nov 5, 2026
44442b3
Merge branch 'satchlj/t8122-api-fixes-20261104' into satchlj/port-305…
satchlj Nov 5, 2026
032486e
Merge branch 'satchlj/t8122-api-fixes-20261104' into satchlj/port-306…
satchlj Nov 5, 2026
2436856
Merge branch 'satchlj/t8122-api-fixes-20261104' into satchlj/port-307…
satchlj Nov 5, 2026
49a678e
Merge branch 'satchlj/t8122-api-fixes-20261104' into satchlj/port-346…
satchlj Nov 5, 2026
523b9eb
Merge branch 'satchlj/t8122-api-fixes-20261104' into satchlj/port-347…
satchlj Nov 5, 2026
fc2cccf
Merge branch 'satchlj/port-302-20261104' into satchlj/port-303-20261104
satchlj Nov 5, 2026
f6c563e
Merge branch 'satchlj/port-303-20261104' into satchlj/port-304-20261104
satchlj Nov 5, 2026
610a513
Merge branch 'satchlj/port-304-20261104' into satchlj/port-305-20261104
satchlj Nov 5, 2026
ea7c050
Merge branch 'satchlj/port-305-20261104' into satchlj/port-306-20261104
satchlj Nov 5, 2026
ef875a1
Merge branch 'satchlj/port-306-20261104' into satchlj/port-307-20261104
satchlj Nov 5, 2026
44c5989
Merge branch 'satchlj/port-307-20261104' into satchlj/port-346-20261104
satchlj Nov 5, 2026
c89fd6e
Merge branch 'satchlj/port-346-20261104' into satchlj/port-347-20261104
satchlj Nov 5, 2026
1d28b76
Merge branch 'satchlj/t8122-api-fixes-20261104' into satchlj/port-303…
satchlj Nov 5, 2026
f7ac189
Merge branch 'satchlj/t8122-api-fixes-20261104' into satchlj/port-304…
satchlj Nov 5, 2026
fc87ce0
Merge branch 'satchlj/t8122-api-fixes-20261104' into satchlj/port-305…
satchlj Nov 5, 2026
f163501
Merge branch 'satchlj/t8122-api-fixes-20261104' into satchlj/port-306…
satchlj Nov 5, 2026
57d2141
Merge branch 'satchlj/t8122-api-fixes-20261104' into satchlj/port-307…
satchlj Nov 5, 2026
9a28266
Merge branch 'satchlj/t8122-api-fixes-20261104' into satchlj/port-346…
satchlj Nov 5, 2026
d798e55
Merge branch 'satchlj/t8122-api-fixes-20261104' into satchlj/port-347…
satchlj Nov 5, 2026
85dfdef
Merge branch 'satchlj/port-302-20261104' into satchlj/port-303-20261104
satchlj Nov 5, 2026
03c778b
Merge branch 'satchlj/port-303-20261104' into satchlj/port-304-20261104
satchlj Nov 5, 2026
07c5d35
Merge branch 'satchlj/port-304-20261104' into satchlj/port-305-20261104
satchlj Nov 5, 2026
b17b5ec
Merge branch 'satchlj/port-305-20261104' into satchlj/port-306-20261104
satchlj Nov 5, 2026
ea85d43
Merge branch 'satchlj/port-306-20261104' into satchlj/port-307-20261104
satchlj Nov 5, 2026
33dcc77
Merge branch 'satchlj/port-307-20261104' into satchlj/port-346-20261104
satchlj Nov 5, 2026
1ac0d6b
Merge branch 'satchlj/port-346-20261104' into satchlj/port-347-20261104
satchlj Nov 5, 2026
150703d
Merge commit '33313096c66f4afdff4ef7060d20fe9bedebc34c' into satchlj/…
satchlj Nov 5, 2026
46d759b
Merge commit '33313096c66f4afdff4ef7060d20fe9bedebc34c' into satchlj/…
satchlj Nov 5, 2026
a8afe80
Merge commit '33313096c66f4afdff4ef7060d20fe9bedebc34c' into satchlj/…
satchlj Nov 5, 2026
ae91e26
Merge commit '33313096c66f4afdff4ef7060d20fe9bedebc34c' into satchlj/…
satchlj Nov 5, 2026
368d1dc
Merge commit '33313096c66f4afdff4ef7060d20fe9bedebc34c' into satchlj/…
satchlj Nov 5, 2026
076b28b
Merge commit '33313096c66f4afdff4ef7060d20fe9bedebc34c' into satchlj/…
satchlj Nov 5, 2026
c34bce8
Merge commit '33313096c66f4afdff4ef7060d20fe9bedebc34c' into satchlj/…
satchlj Nov 5, 2026
bbf8435
Merge commit '33313096c66f4afdff4ef7060d20fe9bedebc34c' into satchlj/…
satchlj Nov 5, 2026
8994247
Merge branch 'satchlj/port-301-20261104' into satchlj/port-303-20261104
satchlj Nov 5, 2026
bc9af1f
Merge branch 'satchlj/port-302-20261104' into satchlj/port-303-20261104
satchlj Nov 5, 2026
379b08b
Merge branch 'satchlj/port-303-20261104' into satchlj/port-304-20261104
satchlj Nov 5, 2026
f13e806
Merge branch 'satchlj/port-304-20261104' into satchlj/port-305-20261104
satchlj Nov 5, 2026
0a7d334
Merge branch 'satchlj/port-305-20261104' into satchlj/port-306-20261104
satchlj Nov 5, 2026
0d31784
Merge branch 'satchlj/port-306-20261104' into satchlj/port-307-20261104
satchlj Nov 5, 2026
f1e8a99
Merge branch 'satchlj/port-307-20261104' into satchlj/port-346-20261104
satchlj Nov 5, 2026
b73d1f9
Merge branch 'satchlj/port-346-20261104' into satchlj/port-347-20261104
satchlj Nov 5, 2026
b932fc2
Merge commit 'b50066848322c6799c1433ee3a358aab2e9faabb' into satchlj/…
satchlj Nov 5, 2026
c816139
Merge commit 'b50066848322c6799c1433ee3a358aab2e9faabb' into satchlj/…
satchlj Nov 5, 2026
d655162
Merge commit 'b50066848322c6799c1433ee3a358aab2e9faabb' into satchlj/…
satchlj Nov 5, 2026
1d520b6
Merge commit 'b50066848322c6799c1433ee3a358aab2e9faabb' into satchlj/…
satchlj Nov 5, 2026
8d07b11
Merge commit 'b50066848322c6799c1433ee3a358aab2e9faabb' into satchlj/…
satchlj Nov 5, 2026
c81410e
Merge commit 'b50066848322c6799c1433ee3a358aab2e9faabb' into satchlj/…
satchlj Nov 5, 2026
cd9eac9
Merge commit 'b50066848322c6799c1433ee3a358aab2e9faabb' into satchlj/…
satchlj Nov 5, 2026
1f5c951
Merge commit 'b50066848322c6799c1433ee3a358aab2e9faabb' into satchlj/…
satchlj Nov 5, 2026
e957f8e
Merge branch 'satchlj/port-301-20261104' into satchlj/port-303-20261104
satchlj Nov 5, 2026
aa8d159
Merge branch 'satchlj/port-302-20261104' into satchlj/port-303-20261104
satchlj Nov 5, 2026
ac13353
Merge branch 'satchlj/port-303-20261104' into satchlj/port-304-20261104
satchlj Nov 5, 2026
b166d93
Merge branch 'satchlj/port-304-20261104' into satchlj/port-305-20261104
satchlj Nov 5, 2026
58c89f5
Merge branch 'satchlj/port-305-20261104' into satchlj/port-306-20261104
satchlj Nov 5, 2026
9b2e8cf
Merge branch 'satchlj/port-306-20261104' into satchlj/port-307-20261104
satchlj Nov 5, 2026
e7936d8
Merge branch 'satchlj/port-307-20261104' into satchlj/port-346-20261104
satchlj Nov 5, 2026
7b88ebb
Merge branch 'satchlj/port-346-20261104' into satchlj/port-347-20261104
satchlj Nov 5, 2026
dfff108
Merge satchlj/port-302-20261104 into satchlj/port-303-20261104
satchlj Nov 5, 2026
5941c36
Merge satchlj/port-303-20261104 into satchlj/port-304-20261104
satchlj Nov 5, 2026
a53a714
Merge satchlj/port-303-20261104 into satchlj/port-304-20261104
DjDeveloperr Nov 7, 2026
b8aec2f
Merge satchlj/port-302-20261104 into satchlj/port-303-20261104
DjDeveloperr Nov 7, 2026
25afe62
Merge satchlj/port-304-20261104 into satchlj/port-305-20261104
DjDeveloperr Nov 7, 2026
bb25219
Merge satchlj/port-305-20261104 into satchlj/port-306-20261104
DjDeveloperr Nov 7, 2026
cc7dc16
Merge satchlj/port-306-20261104 into satchlj/port-307-20261104
DjDeveloperr Nov 7, 2026
b3a9f65
Merge satchlj/port-307-20261104 into satchlj/port-346-20261104
DjDeveloperr Nov 7, 2026
25f9051
Merge satchlj/port-346-20261104 into satchlj/port-347-20261104
DjDeveloperr Nov 7, 2026
9840daa
Merge pull request #977 from aurora-silicon/satchlj/port-347-20261104
RyanTheTide Nov 10, 2026
27d860d
Merge pull request #976 from aurora-silicon/satchlj/port-346-20261104
RyanTheTide Nov 10, 2026
fe20293
Merge pull request #969 from aurora-silicon/satchlj/port-307-20261104
RyanTheTide Nov 10, 2026
f8002c6
Merge pull request #968 from aurora-silicon/satchlj/port-306-20261104
RyanTheTide Nov 10, 2026
e9fe095
Merge pull request #967 from aurora-silicon/satchlj/port-305-20261104
RyanTheTide Nov 10, 2026
dcab88c
Merge pull request #966 from aurora-silicon/satchlj/port-304-20261104
RyanTheTide Nov 10, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions MAINTAINERS
Original file line number Diff line number Diff line change
Expand Up @@ -2794,9 +2794,11 @@ F: tools/asahi/apple-pwm-pm-tests.py
F: drivers/reset/reset-apple-cio.c
F: drivers/rtc/rtc-macsmc.c
F: drivers/soc/apple/*
F: tools/asahi/m3-uapi-*
F: drivers/soc/apple/clpc.kunitconfig
F: tools/asahi/pmp-bootargs-tests.rs
F: drivers/spi/spi-apple-test.c
F: tools/asahi/test-m3-uapi.py
F: drivers/spi/spi-apple.c
F: drivers/spmi/spmi-apple-controller.c
F: drivers/thermal/apple-pmp*
Expand Down
9 changes: 8 additions & 1 deletion drivers/gpu/drm/apple/j613_dcp_activate.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,13 @@ bool apple_t8122_25g83_board(void)
return ok;
}

/* Match the PMGR provider: automatic domains can be clock-gated while active. */
static bool j613_power_state_active(u32 state)
{
return FIELD_GET(GENMASK(7, 4), state) == 15 ||
((state & BIT(28)) && FIELD_GET(GENMASK(3, 0), state) == 15);
}

/* These are DT domain nodes, carrying the PMGR offsets, not copied registers. */
static int j613_power_ready(void)
{
Expand Down Expand Up @@ -82,7 +89,7 @@ static int j613_power_ready(void)
return -ENOMEM;
state = readl(pmgr + offset);
iounmap(pmgr);
if (FIELD_GET(GENMASK(7, 4), state) != 15)
if (!j613_power_state_active(state))
return -EBUSY;
}
return 0;
Expand Down
10 changes: 8 additions & 2 deletions drivers/gpu/drm/asahi/file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::<crate::g17::Gpu>();
#[cfg(CONFIG_DRM_ASAHI_M3_T8122)]
let high_supported = high_supported || reg_data.gpu.as_any()
.downcast_ref::<crate::m3::m3_drm::Backend>()
.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::<crate::g17::Gpu>()
&& !high_supported
{
cls_pr_debug!(
Errors,
Expand Down
57 changes: 55 additions & 2 deletions drivers/gpu/drm/asahi/m3/m3_adt_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,14 @@ impl PstatePolicy {

/// The runtime backend's InitData contents: the generated object images and the
/// performance-state policy.
pub(crate) struct ExtendedInputs {
pub(crate) power: hw::PwrConfig,
pub(crate) sram_uv: KVec<u32>,
pub(crate) bases: super::m3_mmio_26::RegisterBases,
}

pub(crate) struct Contents {
pub(crate) extended: Option<ExtendedInputs>,
/// Generated images, per owner; None for owners that stay zero. Only the three image
/// owners' images are uploaded; the records' are checked.
images: KVec<Option<KVVec<u8>>>,
Expand Down Expand Up @@ -304,6 +311,10 @@ impl Contents {
experiment: Option<&Experiment>,
) -> Result<Self> {
let dev = pdev.as_ref();
if firmware.profile() == super::m3_profile::Profile::Extended {
if experiment.is_some() { return Err(EINVAL); }
return Self::extended(dev, soc);
}
let param = m3_params::initdata_param();
check_version(dev, firmware, experiment)?;
let iomaps = match experiment {
Expand Down Expand Up @@ -370,12 +381,54 @@ impl Contents {
);
let read_only_slots = experiment.map(|e| e.read_only_slots()).unwrap_or(0);
let hwdata_object = soc.hwdata_object;
Ok(Contents { images, pstates, iomaps, table, read_only_slots, hwdata_object })
Ok(Contents { extended: None, images, pstates, iomaps, table, read_only_slots, hwdata_object })
}

fn extended(dev: &device::Device, soc: &Soc) -> Result<Self> {
let cfg = soc.hwcfg.ok_or(ENODEV)?;
if soc.chip_id != 0x8122 || cfg.chip_id != 0x8122 { return Err(ENODEV); }
let power = hw::PwrConfig::load(dev, cfg)?;
let tables = initdata::PStateTables::new(&power, true, None, false)?;
if tables.len != 9 || tables.max != 8 || tables.max_frequency_khz(&power) != 1_338_000 {
return Err(EINVAL);
}
let node = dev.of_node().ok_or(ENODEV)?;
let opps = node.parse_phandle(c_str!("operating-points-v2"), 0).ok_or(EINVAL)?;
let mut sram_uv = KVec::new();
for opp in opps.children() {
let values: KVec<u32> = opp.get_property(c_str!("opp-microvolt-sram"))?;
if values.len() != 1 { return Err(EINVAL); }
sram_uv.push(values[0], GFP_KERNEL)?;
}
if sram_uv.len() != power.perf_states.len() { return Err(EINVAL); }
let block = |index: usize| -> Result<u64> {
Ok(cfg.io_mappings.get(index).and_then(|value| value.as_ref()).ok_or(EINVAL)?.base as u64)
};
let bases = super::m3_mmio_26::RegisterBases {
gpu: soc.windows.sgx, interrupt: block(2)?,
memory: block(11)?.checked_add(0x1c4000).ok_or(EOVERFLOW)?,
telemetry_write: block(18)?, telemetry_read: block(19)?,
neural: block(25)?, metrology: block(26)?,
};
let mut freqs = [0; 16];
for (index, value) in freqs.iter_mut().enumerate().take(tables.len) {
*value = tables.primary_state(&power, index).freq_hz / 1_000_000;
}
// This profile enables the native firmware's thermal/PID controllers.
// The legacy host-only thermal governor must not replace those inputs.
let pstates = PstatePolicy { table_max: 8, table_max_mhz: 1338,
max: 8, safe: 8, boot: 1, max_mhz: 1338, safe_mhz: 1338,
boot_mhz: freqs[1], freqs, thermal: ThermalMode::Off };
let mut images = KVec::new();
for _ in 0..super::m3_init_26::COUNT { images.push(None, GFP_KERNEL)?; }
Ok(Self { extended: Some(ExtendedInputs { power, sram_uv, bases }),
images, pstates, iomaps: &[], table: (8, 1338), read_only_slots: 0, hwdata_object: None })
}

/// Check the contents before they are uploaded.
pub(crate) fn check_for_upload(&self) -> Result {
if self.images.len() == storage::COUNT {
let count = if self.extended.is_some() { super::m3_init_26::COUNT } else { storage::COUNT };
if self.images.len() == count {
Ok(())
} else {
Err(EINVAL)
Expand Down
2 changes: 1 addition & 1 deletion drivers/gpu/drm/asahi/m3/m3_board.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use crate::m3::m3_resources::{
use crate::m3::m3_soc::Soc;

/// Whether the root node's compatible list contains `compatible`.
fn board_is(compatible: &[u8]) -> bool {
pub(crate) fn board_is(compatible: &[u8]) -> bool {
let Some(root) = kernel::of::root() else {
return false;
};
Expand Down
182 changes: 182 additions & 0 deletions drivers/gpu/drm/asahi/m3/m3_channel_format.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
// SPDX-License-Identifier: GPL-2.0-only OR MIT

//! Bounded firmware channel records. Publication and retirement belong to Config.

use super::m3_init_layout::Error;

pub(crate) const CONTROL_BYTES: usize = 64;
pub(crate) const RECEIVE_BYTES: usize = 72;
pub(crate) const SLOTS: u32 = 256;

#[derive(Clone, Copy, Debug)]
pub(crate) enum Action {
Initialize,
Register {
pipe: u32,
engine: u32,
},
Idle {
enabled: bool,
},
Release {
group: u8,
index: u8,
weight: u8,
address: u64,
},
}

impl Action {
/// The first two actions precede the first generation-bearing publication.
pub(crate) fn generation(self, published: u32, consumed: u32) -> Result<u32, Error> {
match self {
Self::Initialize | Self::Register { .. } => {
if published != 0 || consumed != 0 {
return Err(Error::Address);
}
Ok(0)
}
_ => published.max(consumed).checked_add(1).ok_or(Error::Address),
}
}

pub(crate) fn encode(self, output: &mut [u8]) -> Result<(), Error> {
let mut words = [0u32; 3];
let mut release = None;
match self {
Self::Initialize => words[0] = 0x16,
Self::Register { pipe, engine } => {
if pipe >= 3 || !(1..=2).contains(&engine) {
return Err(Error::Address);
}
words = [0x1b, pipe, engine];
}
Self::Idle { enabled } => words = [0x0a, enabled.into(), 0],
Self::Release {
group,
index,
weight,
address,
} => {
if index == 255
|| weight == 255
|| address < 0xffff_fc00_0000_0000
|| address & 7 != 0
{
return Err(Error::Address);
}
words[0] = 0x14;
words[2] = u32::from_le_bytes([group, index, weight, 4]);
release = Some(address);
}
}
let bytes = output.get_mut(..CONTROL_BYTES).ok_or(Error::Size)?;
bytes.fill(0);
for (index, word) in words.iter().enumerate() {
bytes[index * 4..index * 4 + 4].copy_from_slice(&word.to_le_bytes());
}
if let Some(address) = release {
bytes[12..20].copy_from_slice(&address.to_le_bytes());
}
Ok(())
}
}

/// An empty ring is required before publishing a synchronous control transaction.
/// Both consumers must retire it before the next control action may be published.
pub(crate) fn idle_cursor(cursors: [u32; 3]) -> Result<u32, Error> {
if cursors.iter().any(|value| *value >= SLOTS) {
return Err(Error::Bounds);
}
if cursors[0] != cursors[2] || cursors[1] != cursors[2] {
return Err(Error::Address);
}
Ok(cursors[2])
}

pub(crate) fn payload_offset(thread: usize, slot: u32) -> Result<usize, Error> {
if thread >= 9 {
return Err(Error::Bounds);
}
Ok((thread * 256 + (slot & 255) as usize) * 0xd8)
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn initialization_records_have_only_their_defined_words() {
for action in [Action::Initialize, Action::Register { pipe: 2, engine: 1 }] {
let mut output = [0xa5; CONTROL_BYTES + 8];
action.encode(&mut output).unwrap();
assert_eq!(&output[12..CONTROL_BYTES], &[0; CONTROL_BYTES - 12]);
assert_eq!(&output[CONTROL_BYTES..], &[0xa5; 8]);
assert_eq!(action.generation(0, 0), Ok(0));
assert!(action.generation(1, 0).is_err());
}
}

#[test]
fn invalid_actions_preserve_the_entire_output() {
for action in [
Action::Register { pipe: 3, engine: 1 },
Action::Register { pipe: 0, engine: 0 },
Action::Release {
group: 0,
index: 255,
weight: 1,
address: 0xffff_fc21_0000_0000,
},
Action::Release {
group: 0,
index: 0,
weight: 1,
address: 8,
},
] {
let mut output = [0xa5; CONTROL_BYTES];
assert!(action.encode(&mut output).is_err());
assert_eq!(output, [0xa5; CONTROL_BYTES]);
}
}

#[test]
fn generations_follow_consumption_and_never_wrap() {
let action = Action::Idle { enabled: true };
assert_eq!(action.generation(3, 5), Ok(6));
assert_eq!(action.generation(5, 3), Ok(6));
assert!(action.generation(u32::MAX, 0).is_err());
assert!(action.generation(0, u32::MAX).is_err());
let mut output = [0; CONTROL_BYTES];
action.encode(&mut output).unwrap();
assert_eq!(&output[..8], &[10, 0, 0, 0, 1, 0, 0, 0]);
}

#[test]
fn both_consumers_and_all_indices_are_checked() {
assert_eq!(idle_cursor([255, 255, 255]), Ok(255));
for cursors in [[0, 1, 1], [1, 0, 1], [256, 256, 256]] {
assert!(idle_cursor(cursors).is_err());
}
assert_eq!(payload_offset(8, 0x101), Ok((8 * 256 + 1) * 0xd8));
assert!(payload_offset(9, 0).is_err());
}

#[test]
fn release_uses_the_packed_owned_pointer() {
let action = Action::Release {
group: 1,
index: 2,
weight: 3,
address: 0xffff_fc21_0400_0000,
};
let mut output = [0; CONTROL_BYTES];
action.encode(&mut output).unwrap();
assert_eq!(&output[8..12], &[1, 2, 3, 4]);
assert_eq!(
u64::from_le_bytes(output[12..20].try_into().unwrap()),
0xffff_fc21_0400_0000
);
}
}
17 changes: 14 additions & 3 deletions drivers/gpu/drm/asahi/m3/m3_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ use crate::{
const AGX3_PARAMS_SIZE: u64 =
(core::mem::offset_of!(uapi::drm_asahi_params_global, gpu_hal_generation)
+ core::mem::size_of::<u32>()) as u64;
const _: () = assert!(AGX3_PARAMS_SIZE == 600);
const _: () = assert!(AGX3_PARAMS_SIZE == super::m3_profile::PARAMS_REQUIRED);

/// Refused clients that are logged per boot; later refusals only count.
const REFUSALS_LOGGED: u32 = 16;
Expand All @@ -45,10 +45,19 @@ static REFUSALS: AtomicU32 = AtomicU32::new(0);
/// [`AGX3_PARAMS_SIZE`] bytes (so it knows this GPU runs AGX3 command streams), and pass
/// VM_CREATE flags 0 (legacy HAL). `size` is the largest GET_PARAMS size the file asked for.
pub(crate) fn admit_vm(device: &kernel::device::Device, size: u64, flags: u32) -> Result {
admit_vm_for(device, super::m3_profile::Profile::Legacy, size, flags)
}

pub(crate) fn admit_vm_for(
device: &kernel::device::Device,
profile: super::m3_profile::Profile,
size: u64,
flags: u32,
) -> Result {
{
// The positive acknowledgement of the command ABI (7.1.12 `g16_profile::client_admitted`):
// GET_PARAMS coverage, and VM_CREATE flags 0 on the legacy-HAL M3 runtime.
if size >= AGX3_PARAMS_SIZE && flags == 0 {
if profile.vm_acknowledged(size, flags) {
return Ok(());
}
let refusals = REFUSALS.fetch_add(1, Ordering::Relaxed).saturating_add(1);
Expand All @@ -64,11 +73,13 @@ pub(crate) fn admit_vm(device: &kernel::device::Device, size: u64, flags: u32) -
};
dev_info!(
device,
"M3: refusing a VM for {}[{}]: it asked GET_PARAMS for {} of the {} parameter bytes, so it cannot know this GPU runs AGX3 command streams; M3-aware userspace is needed{}\n",
"M3: refusing a VM for {}[{}]: GET_PARAMS bytes={}/{} HAL={} flags={:#x}{}\n",
name,
task.group_leader().pid(),
size,
AGX3_PARAMS_SIZE,
profile.hal(),
flags,
last
);
}
Expand Down
Loading