Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 4 additions & 0 deletions drivers/gpu/drm/asahi/asahi_core.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
// SPDX-License-Identifier: GPL-2.0-only OR MIT
#![recursion_limit = "2048"]

Expand Down Expand Up @@ -137,6 +137,10 @@
default: 1,
description: "G15: answer firmware halts with the halt/resume handshake (0: fail-stop)",
},
g15_sleep_hold: u32 {
default: 1,
description: "G15 (T6031): keep the GFX domain on through system sleep (0: genpd may power it off under the firmware)",
},
g15_stream_gate: u32 {
default: 1,
description: "G15: admit only known CDM/VDM stream records (0: bring-up only)",
Expand Down
40 changes: 30 additions & 10 deletions drivers/gpu/drm/asahi/g15/boot.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
// SPDX-License-Identifier: GPL-2.0-only OR MIT

//! Admission and firmware start to READY.
Expand All @@ -6,7 +6,8 @@
//! `apple_pmp_t6030_board`, or the SoC's machine compatible), the PMP supplier on a SoC with
//! the PMP AGX vote (`apple_pmp_j514s_gpu_prepare`, may return EPROBE_DEFER), the GPU regions and
//! segments ([`super::adt`]: the ADT export, or the GPU device tree node), exact firmware TEXT
//! identity ([`super::identity`]), MMIO windows, runtime-PM hold of the GFX domain.
//! identity ([`super::identity`]), MMIO windows, runtime-PM hold of the GFX domain (on T6031
//! through system sleep too, the device being left out of it).
//!
//! Start: PMP AGX vote (`apple_pmp_j514s_gpu_get`) where the SoC takes one, hardware identity
//! and core masks (one word, or two above 32 core slots), `sgx_open`
Expand Down Expand Up @@ -46,7 +47,7 @@
use super::hw;
use super::initdata::{self, InitData};
use super::object::Objects;
use super::{identity, regs, uat, Config, Shared};
use super::{identity, params, regs, uat, Config, Shared};
use crate::driver::AsahiDrmDevice as AsahiDevice;
use crate::mmu;

Expand All @@ -59,7 +60,7 @@
fn asahi_g15_sha256(data: *const u8, len: usize, out: *mut u8);
fn asahi_g15_board() -> bool;
fn asahi_g15_machine(compatible: *const core::ffi::c_char) -> bool;
fn asahi_g15_hold_power(dev: *mut core::ffi::c_void);
fn asahi_g15_hold_power(dev: *mut core::ffi::c_void, sleep_hold: bool);
fn asahi_g15_release_power(dev: *mut core::ffi::c_void);
fn asahi_g15_module_try_get() -> bool;
fn asahi_g15_module_put();
Expand Down Expand Up @@ -105,10 +106,12 @@
unsafe { asahi_g15_machine(compatible.as_char_ptr()) }
}

/// Holds the GFX power domain for the retained session.
pub(crate) fn hold_power(dev: &device::Device) {
// SAFETY: `dev` is a valid device; runtime-PM accounting on it has no other requirement.
unsafe { asahi_g15_hold_power(dev.as_raw().cast()) };
/// Holds the GFX power domain for the retained session, and with `sleep_hold` through system
/// sleep too: the device is then left out of system sleep (`asahi_g15_hold_power()`).
pub(crate) fn hold_power(dev: &device::Device, sleep_hold: bool) {
// SAFETY: `dev` is a valid device; runtime-PM accounting and its syscore flag have no
// other requirement.
unsafe { asahi_g15_hold_power(dev.as_raw().cast(), sleep_hold) };
}

/// Gives the GFX power domain hold back after a start that touched nothing firmware-visible.
Expand Down Expand Up @@ -520,9 +523,26 @@
}
let board_images = initdata::prepare_board(dev, cfg, &adt)?;
let regs = regs::Regs::new(pdev)?;
// Keep the GFX domain powered for the whole (retained) session.
glue::hold_power(dev);
dev_info!(dev, "{} admitted, ASC={:#x}\n", cfg.name, regs.asc_control()?);
// Read before the hold: nothing after it may fail before `Gpu::new()` can give it back. The
// domain is on already, since the probe attached the device to it.
let asc = regs.asc_control()?;
// Keep the GFX domain powered for the whole (retained) session; on T6031, whose GPU that
// domain alone powers, through system sleep too, unless g15_sleep_hold=0.
let t6031 = cfg.platform == hw::Platform::DeviceTree;
let sleep_hold = t6031 && params::sleep_hold();
glue::hold_power(dev, sleep_hold);
dev_info!(dev, "{} admitted, ASC={:#x}\n", cfg.name, asc);
if sleep_hold {
dev_info!(
dev,
"G15: the GFX domain stays on through system sleep, as nothing starts the firmware again (g15_sleep_hold=0 lets genpd power it off)\n"
);
} else if t6031 {
dev_warn!(
dev,
"G15: g15_sleep_hold=0: system sleep may power the GFX domain off under the firmware, which nothing starts again\n"
);
}
Ok(Admitted { regs, adt, board_images })
}

Expand Down
17 changes: 15 additions & 2 deletions drivers/gpu/drm/asahi/g15/glue.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
void asahi_g15_sha256(const u8 *data, size_t len, u8 *out);
bool asahi_g15_board(void);
bool asahi_g15_machine(const char *compatible);
void asahi_g15_hold_power(struct device *dev);
void asahi_g15_hold_power(struct device *dev, bool sleep_hold);
void asahi_g15_release_power(struct device *dev);
bool asahi_g15_module_try_get(void);
void asahi_g15_module_put(void);
Expand Down Expand Up @@ -222,12 +222,24 @@ bool asahi_g15_machine(const char *compatible)
* Keep the GFX domain powered for the whole (retained) session, like the
* firmware session itself; released only by a start that failed before the
* firmware was touched (asahi_g15_release_power()).
*
* With @sleep_hold (T6031), through system sleep as well. In the noirq
* phase genpd counts the GPU, the only device in the domain, as suspended,
* whatever its runtime-PM state, and powers the domain off under the
* running firmware, which nothing starts again. genpd spares a device in
* the wakeup path only in a domain with GENPD_FLAG_ACTIVE_WAKEUP, which
* PMGR gives only to a domain it finds on when it probes it. As a syscore
* device the GPU is left out of system sleep instead: genpd never counts it
* as suspended, and the domain stays on, as dwc3-apple keeps its core's
* domain on and the ISP and the SEP those of their resident firmware.
* Nothing changes while the system is awake.
*/
void asahi_g15_hold_power(struct device *dev)
void asahi_g15_hold_power(struct device *dev, bool sleep_hold)
{
pm_runtime_get_noresume(dev);
pm_runtime_set_active(dev);
pm_runtime_enable(dev);
dev_pm_syscore_device(dev, sleep_hold);
}

/*
Expand All @@ -238,6 +250,7 @@ void asahi_g15_hold_power(struct device *dev)
*/
void asahi_g15_release_power(struct device *dev)
{
dev_pm_syscore_device(dev, false);
pm_runtime_put_noidle(dev);
pm_runtime_disable(dev);
pm_runtime_set_suspended(dev);
Expand Down
6 changes: 6 additions & 0 deletions drivers/gpu/drm/asahi/g15/params.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
// SPDX-License-Identifier: GPL-2.0-only OR MIT

//! Module parameters and the GET_PARAMS identity.
Expand Down Expand Up @@ -53,6 +53,12 @@
*module_parameters::g15_recovery.value() != 0
}

/// Whether the T6031 GFX domain is held through system sleep too, the device being left out of
/// it (else genpd may power the domain off under the firmware in the noirq phase).
pub(crate) fn sleep_hold() -> bool {
*module_parameters::g15_sleep_hold.value() != 0
}

/// Whether the CDM/VDM stream gates are on.
pub(crate) fn stream_gate() -> bool {
*module_parameters::g15_stream_gate.value() != 0
Expand Down
Loading