[PATCH v11 03/11] iommu/arm-smmu-v3: Swap EVTQ_MSI_INDEX and GERROR_MSI_INDEX

Jason Gunthorpe jgg at nvidia.com
Tue Oct 13 07:49:36 PDT 2026


> The nvec trick in arm_smmu_setup_msis() works well on PRIQ since its index
> is the last index in enum arm_smmu_msi_index, but it does not work well on
> the EVTQ as its index is 0.
> 
> A subsequent change will make EVTQ optional so it can be disabled in kdump
> mode. This can skip its MSI vector allocation.
> 
> The index is driver-internal to select arm_smmu_msi_cfg[] register set and
> the corresponding MSI slot. Nothing else.
> 
> Swap EVTQ_MSI_INDEX and GERROR_MSI_INDEX. Then, arm_smmu_setup_msis() will
> simply decrease nvec when EVTQ is disabled.
> 
> No functional change intended.
> 
> Signed-off-by: Nicolin Chen <nicolinc at nvidia.com>
> ---
>  drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 16 ++++++++--------
>  1 file changed, 8 insertions(+), 8 deletions(-)
>
> 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 aeace4335abfe9..6ff61565f75838 100644
> --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
> +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
> @@ -57,8 +57,8 @@ static struct iommu_dirty_ops arm_smmu_dirty_ops;
>  static DEFINE_STATIC_KEY_FALSE(arm_smmu_erratum_repeat_tlbi_cfgi_key);
>  
>  enum arm_smmu_msi_index {
> -	EVTQ_MSI_INDEX,
>  	GERROR_MSI_INDEX,
> +	EVTQ_MSI_INDEX,
>  	PRIQ_MSI_INDEX,
>  	ARM_SMMU_MAX_MSIS,
>  };

This is the only change that is really needed

> @@ -68,16 +68,16 @@ static_assert(sizeof(struct arm_smmu_ste) == NUM_ENTRY_QWORDS * sizeof(u64));
>  static_assert(sizeof(struct arm_smmu_cd) == NUM_ENTRY_QWORDS * sizeof(u64));
>  
>  static phys_addr_t arm_smmu_msi_cfg[ARM_SMMU_MAX_MSIS][3] = {
> -	[EVTQ_MSI_INDEX] = {
> -		ARM_SMMU_EVTQ_IRQ_CFG0,
> -		ARM_SMMU_EVTQ_IRQ_CFG1,
> -		ARM_SMMU_EVTQ_IRQ_CFG2,
> -	},
>  	[GERROR_MSI_INDEX] = {
>  		ARM_SMMU_GERROR_IRQ_CFG0,
>  		ARM_SMMU_GERROR_IRQ_CFG1,
>  		ARM_SMMU_GERROR_IRQ_CFG2,
>  	},
> +	[EVTQ_MSI_INDEX] = {
> +		ARM_SMMU_EVTQ_IRQ_CFG0,
> +		ARM_SMMU_EVTQ_IRQ_CFG1,
> +		ARM_SMMU_EVTQ_IRQ_CFG2,
> +	},

The arrays don't have to be in order

>  	[PRIQ_MSI_INDEX] = {
>  		ARM_SMMU_PRIQ_IRQ_CFG0,
>  		ARM_SMMU_PRIQ_IRQ_CFG1,
> @@ -4965,15 +4965,15 @@ static void arm_smmu_setup_msis(struct arm_smmu_device *smmu)
>  		return;
>  	}
>  
> -	/* Allocate MSIs for evtq, gerror and priq. Ignore cmdq */
> +	/* Allocate MSIs for gerror, evtq and priq. Ignore cmdq */
>  	ret = platform_device_msi_init_and_alloc_irqs(dev, nvec, arm_smmu_write_msi_msg);
>  	if (ret) {
>  		dev_warn(dev, "failed to allocate MSIs - falling back to wired irqs\n");
>  		return;
>  	}
>  
> -	smmu->evtq.q.irq = msi_get_virq(dev, EVTQ_MSI_INDEX);
>  	smmu->gerr_irq = msi_get_virq(dev, GERROR_MSI_INDEX);
> +	smmu->evtq.q.irq = msi_get_virq(dev, EVTQ_MSI_INDEX);
>  	smmu->priq.q.irq = msi_get_virq(dev, PRIQ_MSI_INDEX);

Nor do the assignments.

But I'm not really a fan of this design, it is very fragile.

I think if you want to compress the nvec's array it should be done
directly.

The smmu should have a small array
   u8 msi_map[]

Which holds the xx_MSI_INDEX value. Then arm_smmu_write_msi_msg()
would indirect to get the config:

	phys_addr_t *cfg = arm_smmu_msi_cfg[smmu->msi_map[desc->msi_index]];

And we just compress msi_map as we go through the normal flow

   index_msi[EVTQ_MSI_INDEX] = nvec;
   smmu->msi_map[nvec++] = EVTQ_MSI_INDEX

Then it isn't fragile at all.

-- 
Jason



More information about the linux-arm-kernel mailing list