Re: [PATCH V1 3/3] iommu/arm-smmu-v3: Honor IORT Root Complex PASID descriptors

From: Jason Gunthorpe

Date: Thu Apr 23 2026 - 18:45:26 EST


On Fri, Apr 24, 2026 at 12:44:17AM +0530, Vidya Sagar wrote:
> The SMMUv3 driver currently calls pci_enable_pasid() for any PCI
> master that exposes a PASID capability, regardless of whether the
> upstream Root Complex actually supports PASID and regardless of the
> RC's declared Max PASID Width. With IORT spec E.c (RC node revision
> >= 4) firmware reports both, so we can do better:
>
> - If the IORT Root Complex node says PASID is not supported
> (Flags bit 0 == 0 at byte offset 36), enabling PASID on the
> endpoint is futile - the RC will not forward the PASID prefix to
> the SMMU - so skip pci_enable_pasid() silently.
>
> - If the IORT Root Complex node reports a Max PASID Width (bits[4:0]
> of PASID Capabilities at offset 33), clamp the endpoint's
> pci_max_pasids() result by 1 << width before computing the SMMU
> SSID width. This prevents master->ssid_bits from exceeding what
> the RC can actually carry.
>
> Both behaviours are gated on iort_pci_rc_pasid_max_width_known(), i.e.
> RC node revision >= 4, so platforms with older IORT firmware see no
> behavioural change and continue to enable PASID purely on the basis
> of the endpoint capability.
>
> Use the new IOMMU_FWSPEC_PCI_RC_PASID fwspec flag (set by IORT) for
> the support check, and call iort_pci_rc_pasid_max_width_for_dev() for
> the width clamp; both pieces are wired up in
> iort_iommu_configure_id() by the previous patch.
>
> Signed-off-by: Vidya Sagar <vidyas@xxxxxxxxxx>
> ---
> drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 26 ++++++++++++++++++---
> 1 file changed, 23 insertions(+), 3 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 e8d7dbe495f0..2b269307fd33 100644
> --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
> +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
> @@ -3071,16 +3071,28 @@ static void arm_smmu_enable_ats(struct arm_smmu_master *master)
>
> static int arm_smmu_enable_pasid(struct arm_smmu_master *master)
> {
> - int ret;
> - int features;
> - int num_pasids;
> + struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(master->dev);
> struct pci_dev *pdev;
> + int features, num_pasids, ret, rc_width;

Don't reformat the code like this.

Otherwise the series broadly makes sense to me

Jason