Skip to contentSkip to conversation

drm/tyr: GPU reset infrastructure

PATCH In review Onur Özkan 2 participants 7 messages Sep 12 – Nov 11

Subsystems (4)
lore
Share & tools
lore

Onur Özkan

author reviewer
#0 lore raw

v7 cover drm/tyr: GPU reset infrastructure

Add support for scheduling GPU resets on a dedicated workqueue. Track the reset state to avoid queueing another reset while one is already pending or in progress.

Use an SRCU based gate with mutex-protected reader admission to block hardware accesses while reset work runs and wait for current users before resetting.

Stop new reset requests during teardown and drain any queued or running reset work before releasing the device resources.

This is the initial reset infrastructure only. It is not wired to a reset source yet as those will follow in separate work.

Based on 'commit 53441a9cae3c ("drm/tyr: program CSF global interface")' from tyr-for-upstream with the following patch series on the ML:
- rust: add SRCU abstraction [1]
- rust: workqueue: add cancel_sync support [2]

TODOs:
- On reset failure, we don't do anything for now. We should unplug the GPU.
- In schedule(), similar to panthor_device_schedule_reset(), we should have a PM check but similar to the note above, we don't have the infrastructure for that yet.

Changes since v6:
- Acquire the hardware gate once per address-space operation and pass the guarded iomem reference to helpers to avoid deadlocks.
- Clone the gate Arc before acquiring a guard so mutating address-space helpers can retain their &mut self receivers as suggested by Daniel.
- Collect review and test tags.

---
Onur Özkan (3):
drm/tyr: clear stale IRQ state before soft reset drm/tyr: add GPU reset infrastructure drm/tyr: put iomem behind the hardware gate

 drivers/gpu/drm/tyr/driver.rs            |  65 ++++-----
 drivers/gpu/drm/tyr/fw.rs                |  16 +-
 drivers/gpu/drm/tyr/mmu.rs               |   9 +-
 drivers/gpu/drm/tyr/mmu/address_space.rs |  90 +++++++-----
 drivers/gpu/drm/tyr/reset.rs             | 242 +++++++++++++++++++++++++++++++
 drivers/gpu/drm/tyr/reset/hw_gate.rs     | 106 ++++++++++++++
 drivers/gpu/drm/tyr/tyr.rs               |   1 +
 7 files changed, 436 insertions(+), 93 deletions(-)

---
base-commit: 53441a9cae3c4be552fa8aefa6e61b0f1bceb8a5
change-id: 20260813-tyr-reset-impl-93e951f996b4
prerequisite-message-id: <[email protected]>
prerequisite-patch-id: 4275f7d6e3cf96d61221d47f2398ebfb896db0c7
prerequisite-patch-id: f5e24f7b3717f2ab0445b5395c7f12b554861d78
prerequisite-patch-id: 0bf6ae4abcef7090d0e48921d6ec627a59dc6a7a
prerequisite-patch-id: 8dc24064e858240a6bb5411a261a987a7eae3fad
prerequisite-patch-id: eefbd4a72ed6da0083e20811882738cc3b05604f
prerequisite-patch-id: 7502236d334b13c547a8b47f0be9bf7171b5ca6b
prerequisite-message-id: <[email protected]>
prerequisite-patch-id: 9e1efee190d212ba1b01cd0acb5a4357e0b4da42
prerequisite-patch-id: 26aba035f4d1e212fa6ea7078095febefff5c5ba
prerequisite-patch-id: ffa25d5aadec4c04589af2bdd59a9c022f0fc9b0
prerequisite-patch-id: c2e05a4ac9d665d331952b291a622df6be673e41
prerequisite-patch-id: c14a4bd8a68b045356d61f7fa94690bd037ad08b

author reviewer
#1 lore raw

PATCH v7 1/3 drm/tyr: clear stale IRQ state before soft reset

Previous reset may leave the reset completed IRQ set which can make the poll return too early.

Clear the IRQ first so the driver waits for the current reset to complete.

---
 drivers/gpu/drm/tyr/driver.rs | 3 +++
 1 file changed, 3 insertions(+)
drivers/gpu/drm/tyr/driver.rs +3 -0
index c5063b2be94d..90d6cd988cd2 100644
@@ -86,6 +86,9 @@ pub(crate) struct TyrDrmRegistrationData<'bound> {
 }
 
 fn issue_soft_reset(dev: &Device, iomem: &IoMem<'_>) -> Result {
+    // Clear any stale reset IRQ state before issuing a new soft reset.
+    iomem.write_reg(GPU_IRQ_CLEAR::zeroed().with_reset_completed(true));
+
     iomem.write_reg(GPU_COMMAND::reset(ResetMode::SoftReset));
 
     poll::read_poll_timeout(
Signature · 1 line
2.54.0
author reviewer
#2 lore raw

PATCH v7 2/3 drm/tyr: add GPU reset infrastructure

In reply to Onur Özkan

Add support for scheduling GPU resets on a dedicated workqueue. Track the reset state to avoid queueing another reset while one is already pending or in progress.

Use an SRCU based gate with mutex-protected reader admission to block hardware accesses while reset work runs and wait for current users before resetting.

Stop new reset requests during teardown and drain any queued or running reset work before releasing the device resources.

This is the initial reset infrastructure only. It is not wired to a reset source yet as those will follow in separate work.

---
 drivers/gpu/drm/tyr/driver.rs        |  41 ++----
 drivers/gpu/drm/tyr/reset.rs         | 249 +++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/tyr/reset/hw_gate.rs |  80 +++++++++++
 drivers/gpu/drm/tyr/tyr.rs           |   1 +
 4 files changed, 343 insertions(+), 28 deletions(-)
drivers/gpu/drm/tyr/driver.rs +13 -28
index 90d6cd988cd2..52b1f16fa405 100644
@@ -8,7 +8,6 @@
     device::{
         Bound,
         Core,
-        Device,
         DeviceContext, //
     },
     dma::{
@@ -17,13 +16,9 @@
     },
     drm,
     drm::ioctl,
-    io::{
-        poll,
-        Io, //
-    },
     new_mutex,
     of,
-    platform,
+    platform, //
     prelude::*,
     regulator,
     regulator::Regulator,
@@ -33,7 +28,6 @@
         Arc,
         Mutex, //
     },
-    time,
     types::ForLt, //
 };
 
@@ -41,10 +35,10 @@
     file::TyrDrmFileData,
     fw::Firmware,
     gem::BoData,
-    gpu,
     gpu::GpuInfo,
     mmu::Mmu,
-    regs::gpu_control::*, //
+    regs::gpu_control::*,
+    reset, //
 };
 
 pub(crate) type IoMem<'a> = kernel::io::mem::IoMem<'a, SZ_2M>;
@@ -67,6 +61,12 @@ pub(crate) struct TyrDrmRegistrationData<'bound> {
     /// Parent platform device.
     pub(crate) pdev: &'bound platform::Device<Bound>,
 
+    // `ResetHandle::drop()` drains queued/running works and this must happen
+    // before clocks/regulators are dropped. So keep this field before them to
+    // ensure the correct drop order.
+    #[pin]
+    pub(crate) reset: reset::ResetHandle<'bound>,
+
     /// Firmware sections.
     pub(crate) fw: Arc<Firmware<'bound>>,
 
@@ -85,23 +85,6 @@ pub(crate) struct TyrDrmRegistrationData<'bound> {
     pub(crate) gpu_info: GpuInfo,
 }
 
-fn issue_soft_reset(dev: &Device, iomem: &IoMem<'_>) -> Result {
-    // Clear any stale reset IRQ state before issuing a new soft reset.
-    iomem.write_reg(GPU_IRQ_CLEAR::zeroed().with_reset_completed(true));
-
-    iomem.write_reg(GPU_COMMAND::reset(ResetMode::SoftReset));
-
-    poll::read_poll_timeout(
-        || Ok(iomem.read(GPU_IRQ_RAWSTAT)),
-        |status| status.reset_completed(),
-        time::Delta::from_millis(1),
-        time::Delta::from_millis(100),
-    )
-    .inspect_err(|_| dev_err!(dev, "GPU reset failed."))?;
-
-    Ok(())
-}
-
 kernel::of_device_table!(
     OF_TABLE,
     MODULE_OF_TABLE,
@@ -136,8 +119,7 @@ fn probe<'bound>(
 
         let iomem = Arc::new(request.iomap_sized::<SZ_2M>()?, GFP_KERNEL)?;
 
-        issue_soft_reset(pdev.as_ref(), &iomem)?;
-        gpu::l2_power_on(pdev.as_ref(), &iomem)?;
+        reset::run_reset(pdev.as_ref(), &iomem)?;
 
         let gpu_info = GpuInfo::new(&iomem);
         gpu_info.log(pdev.as_ref());
@@ -167,6 +149,9 @@ fn probe<'bound>(
 
         let reg_data = try_pin_init!(TyrDrmRegistrationData {
                 pdev,
+                // SAFETY: `Registration` is stored in the platform driver data and
+                // not leaked, so `ResetHandle` is dropped before borrowed data expires.
+                reset <- unsafe { reset::ResetHandle::new(pdev, iomem.as_arc_borrow())? },
                 fw: firmware,
                 clks <- new_mutex!(Clocks {
                     core: core_clk,
drivers/gpu/drm/tyr/reset.rs new file +249 -0

249 lines not on this page · raw message

drivers/gpu/drm/tyr/reset/hw_gate.rs new file +80 -0

80 lines not on this page · raw message

drivers/gpu/drm/tyr/tyr.rs +1 -0
index 3f6fe5fbeb0f..63873628c843 100644
@@ -14,6 +14,7 @@
 mod gpu;
 mod mmu;
 mod regs;
+mod reset;
 mod slot;
 mod vm;
 mod wait;
Signature · 1 line
2.54.0
author reviewer
#3 lore raw

PATCH v7 3/3 drm/tyr: put iomem behind the hardware gate

In reply to Onur Özkan

Move iomem mapping into HwGate and pass Arc<HwGate> to components that access hardware. Callers obtain HwAccessGuard before accessing the iomem so the reset worker waits for ongoing accesses.

Acquire the gate once per address-space operation and pass the guarded iomem reference to its helpers. This prevents nested gate acquisition from deadlocking with reset and keeps each operation protected throughout. Clone the gate Arc before acquiring the guard so mutating helpers can retain their mutable self receivers.

---
 drivers/gpu/drm/tyr/driver.rs            | 35 ++++++-------
 drivers/gpu/drm/tyr/fw.rs                | 16 +++---
 drivers/gpu/drm/tyr/mmu.rs               |  9 ++--
 drivers/gpu/drm/tyr/mmu/address_space.rs | 90 ++++++++++++++++++--------------
 drivers/gpu/drm/tyr/reset.rs             | 33 +++++-------
 drivers/gpu/drm/tyr/reset/hw_gate.rs     | 44 ++++++++++++----
 6 files changed, 126 insertions(+), 101 deletions(-)
drivers/gpu/drm/tyr/driver.rs +16 -19
index 52b1f16fa405..c326192f8af2 100644
@@ -76,9 +76,6 @@ pub(crate) struct TyrDrmRegistrationData<'bound> {
     #[pin]
     regulators: Mutex<Regulators>,
 
-    /// GPU MMIO register mapping.
-    pub(crate) iomem: Arc<IoMem<'bound>>,
-
     /// Some information on the GPU.
     ///
     /// This is mainly queried by userspace, i.e.: Mesa.
@@ -117,12 +114,19 @@ fn probe<'bound>(
 
         let request = pdev.io_request_by_index(0).ok_or(ENODEV)?;
 
-        let iomem = Arc::new(request.iomap_sized::<SZ_2M>()?, GFP_KERNEL)?;
+        let hw = Arc::pin_init(
+            reset::HwGate::new(request.iomap_sized::<SZ_2M>()?),
+            GFP_KERNEL,
+        )?;
 
-        reset::run_reset(pdev.as_ref(), &iomem)?;
+        reset::run_reset(pdev.as_ref(), &hw)?;
 
-        let gpu_info = GpuInfo::new(&iomem);
-        gpu_info.log(pdev.as_ref());
+        let gpu_info = {
+            let hw_guard = hw.access();
+            let gpu_info = GpuInfo::new(hw_guard.iomem());
+            gpu_info.log(pdev.as_ref());
+            gpu_info
+        };
 
         let pa_bits = MMU_FEATURES::from_raw(gpu_info.mmu_features)
             .pa_bits()
@@ -134,24 +138,18 @@ fn probe<'bound>(
 
         let unreg_dev = drm::UnregisteredDevice::<TyrDrmDriver>::new(pdev, Ok(()))?;
 
-        let mmu = Mmu::new(iomem.as_arc_borrow(), &gpu_info)?;
+        let mmu = Mmu::new(hw.clone(), &gpu_info)?;
 
-        let firmware = Firmware::new(
-            pdev,
-            iomem.clone(),
-            &unreg_dev,
-            mmu.as_arc_borrow(),
-            &gpu_info,
-        )?;
+        let firmware = Firmware::new(pdev, hw.clone(), &unreg_dev, mmu.as_arc_borrow(), &gpu_info)?;
 
         firmware.boot()?;
         firmware.enable_global_interface(&gpu_info, &core_clk)?;
 
         let reg_data = try_pin_init!(TyrDrmRegistrationData {
                 pdev,
-                // SAFETY: `Registration` is stored in the platform driver data and
-                // not leaked, so `ResetHandle` is dropped before borrowed data expires.
-                reset <- unsafe { reset::ResetHandle::new(pdev, iomem.as_arc_borrow())? },
+                // SAFETY: `ResetHandle` is stored in registration data created with `new_with_lt`
+                // and is dropped before the borrowed device and MMIO references expire.
+                reset <- unsafe { reset::ResetHandle::new(pdev, hw.clone())? },
                 fw: firmware,
                 clks <- new_mutex!(Clocks {
                     core: core_clk,
@@ -162,7 +160,6 @@ fn probe<'bound>(
                     _mali: mali_regulator,
                     _sram: sram_regulator,
                 }),
-                iomem,
                 gpu_info,
         });
 
drivers/gpu/drm/tyr/fw.rs +9 -7
index 651bbe77f10b..e1522ab14e8d 100644
@@ -41,7 +41,6 @@
 
 use crate::{
     driver::{
-        IoMem,
         TyrDrmDevice, //
     },
     fw::{
@@ -65,6 +64,7 @@
         MCU_CONTROL,
         MCU_STATUS, //
     },
+    reset::HwGate,
     vm::Vm, //
 };
 
@@ -148,8 +148,8 @@ pub(crate) struct Firmware<'bound> {
     /// Platform device reference (needed to access the MCU JOB_IRQ registers).
     _pdev: ARef<platform::Device>,
 
-    /// Iomem need to access registers.
-    iomem: Arc<IoMem<'bound>>,
+    /// Shared gate that coordinates hardware access with GPU reset.
+    hw: Arc<HwGate<'bound>>,
 
     /// MCU VM.
     vm: Arc<Vm<'bound>>,
@@ -221,7 +221,7 @@ fn load(
     /// Load firmware and map sections into MCU VM.
     pub(crate) fn new(
         pdev: &'bound platform::Device<Bound>,
-        iomem: Arc<IoMem<'bound>>,
+        hw: Arc<HwGate<'bound>>,
         ddev: &TyrDrmDevice<Uninit>,
         mmu: ArcBorrow<'_, Mmu<'bound>>,
         gpu_info: &GpuInfo,
@@ -262,7 +262,7 @@ pub(crate) fn new(
         let firmware = Arc::pin_init(
             try_pin_init!(Firmware {
                 _pdev: pdev.into(),
-                iomem,
+                hw,
                 vm,
                 sections,
                 global_iface <- new_mutex!(GlobalInterface::new()?),
@@ -288,7 +288,8 @@ pub(crate) fn shared_section<'a>(&'a self) -> Result<&'a Section<'bound>> {
     }
 
     pub(crate) fn boot(&self) -> Result {
-        let io = &self.iomem;
+        let hw_guard = self.hw.access();
+        let io = hw_guard.iomem();
         io.write_reg(MCU_CONTROL::zeroed().with_req(McuControlMode::Auto));
 
         if let Err(e) = poll::read_poll_timeout(
@@ -307,8 +308,9 @@ pub(crate) fn boot(&self) -> Result {
     /// Enable the global interface.
     pub(crate) fn enable_global_interface(&self, gpu_info: &GpuInfo, core_clk: &Clk) -> Result {
         let shared_section = self.shared_section()?;
+        let hw_guard = self.hw.access();
         self.global_iface
             .lock()
-            .enable(&self.iomem, shared_section, gpu_info, core_clk)
+            .enable(hw_guard.iomem(), shared_section, gpu_info, core_clk)
     }
 }
drivers/gpu/drm/tyr/mmu.rs +3 -6
index cb5908c80e3d..8df6d2ef3c74 100644
@@ -26,7 +26,6 @@
 };
 
 use crate::{
-    driver::IoMem,
     gpu::GpuInfo,
     mmu::address_space::{
         AddressSpaceManager,
@@ -36,6 +35,7 @@
         gpu_control::AS_PRESENT,
         MAX_AS, //
     },
+    reset::HwGate,
     slot::SlotManager, //
 };
 
@@ -67,14 +67,11 @@ pub(crate) struct Mmu<'bound> {
 
 impl<'bound> Mmu<'bound> {
     /// Create an MMU component for this device.
-    pub(crate) fn new(
-        iomem: ArcBorrow<'_, IoMem<'bound>>,
-        gpu_info: &GpuInfo,
-    ) -> Result<Arc<Mmu<'bound>>> {
+    pub(crate) fn new(hw: Arc<HwGate<'bound>>, gpu_info: &GpuInfo) -> Result<Arc<Mmu<'bound>>> {
         let present = AS_PRESENT::from_raw(gpu_info.as_present).present().get();
         let slot_count = present.count_ones().try_into()?;
 
-        let as_manager = AddressSpaceManager::new(iomem, present)?;
+        let as_manager = AddressSpaceManager::new(hw, present)?;
         let mmu_init = try_pin_init!(Self{
             as_manager <- new_mutex!(SlotManager::new(as_manager, slot_count)?),
         });
drivers/gpu/drm/tyr/mmu/address_space.rs +50 -40

219 lines not on this page · raw message

drivers/gpu/drm/tyr/reset.rs +13 -20
index a41158c7ea21..1abcd25877d3 100644
@@ -21,7 +21,7 @@
 
 mod hw_gate;
 
-use hw_gate::HwGate;
+pub(crate) use hw_gate::HwGate;
 
 use kernel::{
     device::{
@@ -41,8 +41,7 @@
             Full,
             Release, //
         },
-        Arc,
-        ArcBorrow, //
+        Arc, //
     },
     time,
     workqueue::{
@@ -84,13 +83,10 @@ unsafe impl AtomicType for ResetState {
 struct Controller<'ctrl> {
     /// Parent platform device.
     pdev: &'ctrl platform::Device<Bound>,
-    /// Mapped register space needed for reset operations.
-    iomem: Arc<IoMem<'ctrl>>,
     /// State shared by reset schedulers and the worker.
     state: Atomic<ResetState>,
-    /// Drains reset-sensitive hardware accesses before a reset.
-    #[pin]
-    hw: HwGate,
+    /// Shared gate that coordinates hardware access with GPU reset.
+    hw: Arc<HwGate<'ctrl>>,
 }
 
 impl<'ctrl> ScopedWorkItem for Controller<'ctrl> {
@@ -103,13 +99,12 @@ impl<'ctrl> Controller<'ctrl> {
     /// Creates a reset controller.
     fn new(
         pdev: &'ctrl platform::Device<Bound>,
-        iomem: Arc<IoMem<'ctrl>>,
+        hw: Arc<HwGate<'ctrl>>,
     ) -> impl PinInit<Self, Error> {
         try_pin_init!(Self {
             pdev,
-            iomem,
             state: Atomic::new(ResetState::Idle),
-            hw <- HwGate::new(),
+            hw,
         })
     }
 
@@ -136,10 +131,7 @@ fn reset_work(&self) {
 
         dev_dbg!(self.pdev, "Starting GPU reset.\n");
 
-        // Wait for current hardware accesses to finish before resetting.
-        let reset_guard = self.hw.close();
-        let reset_result = run_reset(self.pdev.as_ref(), &self.iomem);
-        drop(reset_guard);
+        let reset_result = run_reset(self.pdev.as_ref(), &self.hw);
 
         if let Err(e) = reset_result {
             dev_err!(self.pdev, "GPU reset failed: {:?}\n", e);
@@ -175,12 +167,10 @@ impl<'reset> ResetHandle<'reset> {
     /// running [`Drop`], since it owns work that may borrow from `'reset`.
     pub(crate) unsafe fn new(
         pdev: &'reset platform::Device<Bound>,
-        iomem: ArcBorrow<'_, IoMem<'reset>>,
+        hw: Arc<HwGate<'reset>>,
     ) -> Result<impl PinInit<Self, Error>> {
-        let iomem = iomem.into();
-
         Ok(try_pin_init!(Self {
-            controller <- kernel::new_scoped_work!("tyr::reset", Controller::new(pdev, iomem)),
+            controller <- kernel::new_scoped_work!("tyr::reset", Controller::new(pdev, hw)),
             // SAFETY: The caller guarantees the handle is dropped.
             wq: unsafe { ScopedQueue::new(c"tyr-reset-wq")? },
         }))
@@ -242,7 +232,10 @@ fn issue_soft_reset(dev: &Device<Bound>, io: &IoMem<'_>) -> Result {
 ///   - Trigger a GPU soft reset.
 ///   - Wait for the reset-complete IRQ status.
 ///   - Power L2 back on.
-pub(super) fn run_reset(dev: &Device<Bound>, iomem: &IoMem<'_>) -> Result {
+pub(super) fn run_reset(dev: &Device<Bound>, hw: &HwGate<'_>) -> Result {
+    let hw_guard = hw.close();
+    let iomem = hw_guard.iomem();
+
     issue_soft_reset(dev, iomem)?;
     gpu::l2_power_on(dev, iomem)?;
     Ok(())
drivers/gpu/drm/tyr/reset/hw_gate.rs +35 -9

93 lines not on this page · raw message

Signature · 1 line
2.54.0
maintainer Reviewed-by on v7 3/3
#4 lore raw

Re: [PATCH v7 3/3] drm/tyr: put iomem behind the hardware gate

Quoted 8 lines · Onur Özkan

Move iomem mapping into HwGate and pass Arc<HwGate> to components that access hardware. Callers obtain HwAccessGuard before accessing the iomem so the reset worker waits for ongoing accesses.

Quoted 8 lines

Acquire the gate once per address-space operation and pass the guarded iomem reference to its helpers. This prevents nested gate acquisition from deadlocking with reset and keeps each operation protected throughout. Clone the gate Arc before acquiring the guard so mutating helpers can retain their mutable self receivers.

maintainer
#5 lore raw
In reply to Onur Özkan
Quoted 55 lines · Onur Özkan

Add support for scheduling GPU resets on a dedicated workqueue. Track the reset state to avoid queueing another reset while one is already pending or in progress.

Use an SRCU based gate with mutex-protected reader admission to block hardware accesses while reset work runs and wait for current users before resetting.

Stop new reset requests during teardown and drain any queued or running reset work before releasing the device resources.

This is the initial reset infrastructure only. It is not wired to a reset source yet as those will follow in separate work.

Based on 'commit 53441a9cae3c ("drm/tyr: program CSF global interface")' from tyr-for-upstream with the following patch series on the ML:
- rust: add SRCU abstraction [1]
- rust: workqueue: add cancel_sync support [2]

TODOs:
- On reset failure, we don't do anything for now. We should unplug the GPU.
- In schedule(), similar to panthor_device_schedule_reset(), we should have a PM check but similar to the note above, we don't have the infrastructure for that yet.

Changes since v6:
- Acquire the hardware gate once per address-space operation and pass the guarded iomem reference to helpers to avoid deadlocks.
- Clone the gate Arc before acquiring a guard so mutating address-space helpers can retain their &mut self receivers as suggested by Daniel.

---
Onur Özkan (3):
drm/tyr: clear stale IRQ state before soft reset drm/tyr: add GPU reset infrastructure drm/tyr: put iomem behind the hardware gate

drivers/gpu/drm/tyr/driver.rs            |  65 ++++-----
drivers/gpu/drm/tyr/fw.rs                |  16 +-
drivers/gpu/drm/tyr/mmu.rs               |   9 +-
drivers/gpu/drm/tyr/mmu/address_space.rs |  90 +++++++-----
drivers/gpu/drm/tyr/reset.rs             | 242 +++++++++++++++++++++++++++++++
drivers/gpu/drm/tyr/reset/hw_gate.rs     | 106 ++++++++++++++
drivers/gpu/drm/tyr/tyr.rs               |   1 +
7 files changed, 436 insertions(+), 93 deletions(-)
Quoted 19 lines

---
base-commit: 53441a9cae3c4be552fa8aefa6e61b0f1bceb8a5
change-id: 20260813-tyr-reset-impl-93e951f996b4
prerequisite-message-id: <[email protected]>
prerequisite-patch-id: 4275f7d6e3cf96d61221d47f2398ebfb896db0c7
prerequisite-patch-id: f5e24f7b3717f2ab0445b5395c7f12b554861d78
prerequisite-patch-id: 0bf6ae4abcef7090d0e48921d6ec627a59dc6a7a
prerequisite-patch-id: 8dc24064e858240a6bb5411a261a987a7eae3fad
prerequisite-patch-id: eefbd4a72ed6da0083e20811882738cc3b05604f
prerequisite-patch-id: 7502236d334b13c547a8b47f0be9bf7171b5ca6b
prerequisite-message-id: <[email protected]>
prerequisite-patch-id: 9e1efee190d212ba1b01cd0acb5a4357e0b4da42
prerequisite-patch-id: 26aba035f4d1e212fa6ea7078095febefff5c5ba
prerequisite-patch-id: ffa25d5aadec4c04589af2bdd59a9c022f0fc9b0
prerequisite-patch-id: c2e05a4ac9d665d331952b291a622df6be673e41
prerequisite-patch-id: c14a4bd8a68b045356d61f7fa94690bd037ad08b

Alice, if you are ok with this series, feel free to merge. At least from my side it looks ok.

— Daniel

author reviewer
#6 lore raw
Quoted 72 lines · On Wed, 23 Sep 2026 10:56:48 -0300 Daniel Almeida…
Quoted 72 lines · Onur Özkan

Add support for scheduling GPU resets on a dedicated workqueue. Track the reset state to avoid queueing another reset while one is already pending or in progress.

Use an SRCU based gate with mutex-protected reader admission to block hardware accesses while reset work runs and wait for current users before resetting.

Stop new reset requests during teardown and drain any queued or running reset work before releasing the device resources.

This is the initial reset infrastructure only. It is not wired to a reset source yet as those will follow in separate work.

Based on 'commit 53441a9cae3c ("drm/tyr: program CSF global interface")' from tyr-for-upstream with the following patch series on the ML:
- rust: add SRCU abstraction [1]
- rust: workqueue: add cancel_sync support [2]

TODOs:
- On reset failure, we don't do anything for now. We should unplug the GPU.
- In schedule(), similar to panthor_device_schedule_reset(), we should have a PM check but similar to the note above, we don't have the infrastructure for that yet.

Changes since v6:
- Acquire the hardware gate once per address-space operation and pass the guarded iomem reference to helpers to avoid deadlocks.
- Clone the gate Arc before acquiring a guard so mutating address-space helpers can retain their &mut self receivers as suggested by Daniel.

---
Onur Özkan (3):
drm/tyr: clear stale IRQ state before soft reset drm/tyr: add GPU reset infrastructure drm/tyr: put iomem behind the hardware gate

drivers/gpu/drm/tyr/driver.rs            |  65 ++++-----
drivers/gpu/drm/tyr/fw.rs                |  16 +-
drivers/gpu/drm/tyr/mmu.rs               |   9 +-
drivers/gpu/drm/tyr/mmu/address_space.rs |  90 +++++++-----
drivers/gpu/drm/tyr/reset.rs             | 242 +++++++++++++++++++++++++++++++
drivers/gpu/drm/tyr/reset/hw_gate.rs     | 106 ++++++++++++++
drivers/gpu/drm/tyr/tyr.rs               |   1 +
7 files changed, 436 insertions(+), 93 deletions(-)

---
base-commit: 53441a9cae3c4be552fa8aefa6e61b0f1bceb8a5
change-id: 20260813-tyr-reset-impl-93e951f996b4
prerequisite-message-id: <[email protected]>
prerequisite-patch-id: 4275f7d6e3cf96d61221d47f2398ebfb896db0c7
prerequisite-patch-id: f5e24f7b3717f2ab0445b5395c7f12b554861d78
prerequisite-patch-id: 0bf6ae4abcef7090d0e48921d6ec627a59dc6a7a
prerequisite-patch-id: 8dc24064e858240a6bb5411a261a987a7eae3fad
prerequisite-patch-id: eefbd4a72ed6da0083e20811882738cc3b05604f
prerequisite-patch-id: 7502236d334b13c547a8b47f0be9bf7171b5ca6b
prerequisite-message-id: <[email protected]>
prerequisite-patch-id: 9e1efee190d212ba1b01cd0acb5a4357e0b4da42
prerequisite-patch-id: 26aba035f4d1e212fa6ea7078095febefff5c5ba
prerequisite-patch-id: ffa25d5aadec4c04589af2bdd59a9c022f0fc9b0
prerequisite-patch-id: c2e05a4ac9d665d331952b291a622df6be673e41
prerequisite-patch-id: c14a4bd8a68b045356d61f7fa94690bd037ad08b

Quoted 8 lines
Quoted 2 lines

Alice, if you are ok with this series, feel free to merge. At least from my side it looks ok.

— Daniel

Any updates on this? I am preparing v2 of the GPU unplug series [1] which depends on this series. The reset patches need rebasing against current drm-rust-next.

Would you prefer me to send a rebased v8 and base unplug v2 on it or are you planning to pick up v7 and handle the rebase?

Thanks,
Onur

[1]: https://lore.kernel.org/all/[email protected]