[PATCH v8 05/12] iommu/arm-smmu-v3: Cache and restore MSI config
Mostafa Saleh
smostafa at google.com
Mon Jun 15 10:04:02 PDT 2026
On Mon, Jun 01, 2026 at 09:59:02PM +0000, Pranjal Shrivastava wrote:
> The SMMU's MSI configuration registers (*_IRQ_CFGn) containing target
> address, data and memory attributes lose their state when the SMMU is
> powered down. We'll need to cache and restore their contents to ensure
> that MSIs work after the system resumes.
>
> To address this, cache the original `msi_msg` within the `msi_desc`
> when the configuration is first written by `arm_smmu_write_msi_msg`.
> This primarily includes the target address and data since the memory
> attributes are fixed.
>
> Introduce a new helper `arm_smmu_resume_msis` which will later be called
> during the driver's resume callback. The helper would retrieve the
> cached MSI message for each relevant interrupt (evtq, gerr, priq) via
> get_cached_msi_msg & re-config the registers via arm_smmu_write_msi_msg.
>
> Reviewed-by: Nicolin Chen <nicolinc at nvidia.com>
> Signed-off-by: Pranjal Shrivastava <praan at google.com>
Reviewed-by: Mostafa Saleh <smostafa at google.com>
Thanks,
Mostafa
> ---
> drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 37 +++++++++++++++++++++
> 1 file changed, 37 insertions(+)
>
> diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
> index 8682be5060ed..93cee32f6c99 100644
> --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
> +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
> @@ -4551,6 +4551,9 @@ static void arm_smmu_write_msi_msg(struct msi_desc *desc, struct msi_msg *msg)
> struct arm_smmu_device *smmu = dev_get_drvdata(dev);
> phys_addr_t *cfg = arm_smmu_msi_cfg[desc->msi_index];
>
> + /* Cache the msi_msg for resume */
> + desc->msg = *msg;
> +
> doorbell = (((u64)msg->address_hi) << 32) | msg->address_lo;
> doorbell &= MSI_CFG0_ADDR_MASK;
>
> @@ -4559,6 +4562,40 @@ static void arm_smmu_write_msi_msg(struct msi_desc *desc, struct msi_msg *msg)
> writel_relaxed(ARM_SMMU_MEMATTR_DEVICE_nGnRE, smmu->base + cfg[2]);
> }
>
> +static void arm_smmu_resume_msi(struct arm_smmu_device *smmu,
> + unsigned int irq, const char *name)
> +{
> + struct msi_desc *desc;
> + struct msi_msg msg;
> +
> + if (!irq)
> + return;
> +
> + desc = irq_get_msi_desc(irq);
> + if (!desc) {
> + dev_err(smmu->dev, "Failed to resume msi: %s", name);
> + return;
> + }
> +
> + get_cached_msi_msg(irq, &msg);
> + arm_smmu_write_msi_msg(desc, &msg);
> +}
> +
> +static void arm_smmu_resume_msis(struct arm_smmu_device *smmu)
> +{
> + if (!(smmu->features & ARM_SMMU_FEAT_MSI))
> + return;
> +
> + if (!dev_get_msi_domain(smmu->dev))
> + return;
> +
> + arm_smmu_resume_msi(smmu, smmu->gerr_irq, "gerror");
> + arm_smmu_resume_msi(smmu, smmu->evtq.q.irq, "evtq");
> +
> + if (smmu->features & ARM_SMMU_FEAT_PRI)
> + arm_smmu_resume_msi(smmu, smmu->priq.q.irq, "priq");
> +}
> +
> static void arm_smmu_setup_msis(struct arm_smmu_device *smmu)
> {
> int ret, nvec = ARM_SMMU_MAX_MSIS;
> --
> 2.54.0.1013.g208068f2d8-goog
>
>
More information about the linux-arm-kernel
mailing list