Re: [PATCH v11 11/16] iommu/arm-smmu-v3: Add CMDQ_PROD_STOP_FLAG to gate CMDQ submissions
From: Pranjal Shrivastava
Date: Mon Oct 19 2026 - 04:08:05 EST
On Sat, Oct 17, 2026 at 11:16:45AM -0700, Nicolin Chen wrote:
> On Sat, Oct 17, 2026 at 02:49:12PM -0300, Jason Gunthorpe wrote:
> > On Tue, Oct 06, 2026 at 10:26:41AM -0700, Nicolin Chen wrote:
> > > > pci_dev_reset_iommu_prepare/done() pair (with slight refactoring) in EP's
> > > > suspend/resume?
> > >
> > > That sounds right to me, though a different API for suspend/resume
> > > will be required. And call them in pci_pm_runtime_suspend/resume()
> > > maybe.
> > >
> > > Jason, how do you think about this?
> >
> > Maybe lets just start by refusing power management when ATS is on? For
> > PCIe devices too?
> >
> > It isn't just ARM that has this issue, every iommu is busted if you
> > suspend the PCI device while an ATS domain is still active..
>
> So, should we put that refuse guard in pci_pm_runtime_suspend()?
>
> I am thinking about splitting the iommu and pci patches out of my
> smmmuv3_atc_timeout series. They could be get merged alone.
>
> Then, we add a new API for pci_pm_runtime_suspend/resume() with a
> new BLOCKED_SUSPEND reason in the list:
The guard doesn't sound too bad, but what if we refactor the reset APIs
instead and use them from the PCI core to disable ATS + flush the ATC
right before the EP suspends, as discussed earlier? That'd fix it for
every IOMMU without taking PM away from anyone.
FWIW, AFAICT VT-d and AMD-Vi already enable ATS for ATS-capable devices
attached to the default DMA domain, so a blanket refusal might end up
disabling RPM for some internal devices (e.g. dGPUs / NVMe) that rely on
it today.
On the PCI side, I could roughly:
- Base on Nicolin's split out iommu/pci patches (blocked reason list)
- Add a suspend flavour of pci_dev_reset_iommu_prepare/done() with a
BLOCKED_SUSPEND reason, i.e. RID/PASIDs parked on the blocking
domain, group->domain retained (so dma_map/unmap keep working),
ATS-capable devices only
- Call prepare() in pci_pm_runtime_suspend() after the driver's
callback but before D3, and done() in pci_pm_runtime_resume() after
D0 + pci_restore_state() but before the driver's callback. Same for
the system sleep (noirq) paths
- Keep the guard only as a fallback, i.e. -EBUSY the suspend if
prepare() fails
That flushes the ATC while the EP can still respond and stops any new
ATC_INVs to it. On the SMMU side, we'd then never see a suspended ATS
master with ATS still enabled, so a WARN_ON_ONCE() at suspend would do.
WDYT?
Thanks,
Praan