Re: [PATCH v3 10/13] iommu/arm-smmu-v3: Add second level of context descriptor table
From: Jean-Philippe Brucker <hidden>
Date: 2019-12-18 16:10:35
Also in:
linux-acpi, linux-devicetree, linux-iommu, linux-pci
On Wed, Dec 18, 2019 at 10:59:36AM +0100, Auger Eric wrote:
quoted
struct arm_smmu_s1_cfg { - struct arm_smmu_cd_table table; + struct arm_smmu_cd_table *tables; + size_t num_tables; + __le64 *l1ptr;you may add a comment saying that l1ptr and l1ptr_dma are only set/used in non linear case and one comment saying that "tables" represent leaf tables.
I now have /* Leaf tables or linear table */ and /* First level tables, when two level are used */ but I'm not entirely convinced it adds value
quoted
+ dma_addr_t l1ptr_dma; struct arm_smmu_ctx_desc cd; u8 s1fmt; u8 s1cdmax;@@ -1521,9 +1538,53 @@ static void arm_smmu_free_cd_leaf_table(struct arm_smmu_device *smmu, { size_t size = num_entries * (CTXDESC_CD_DWORDS << 3); + if (!table->ptr) + return; dmam_free_coherent(smmu->dev, size, table->ptr, table->ptr_dma); } +static void arm_smmu_write_cd_l1_desc(__le64 *dst, + struct arm_smmu_cd_table *table) +{ + u64 val = (table->ptr_dma & CTXDESC_L1_DESC_L2PTR_MASK) | + CTXDESC_L1_DESC_VALID; + + WRITE_ONCE(*dst, cpu_to_le64(val)); +} + +static __le64 *arm_smmu_get_cd_ptr(struct arm_smmu_domain *smmu_domain, + u32 ssid) +{ + __le64 *l1ptr; + unsigned int idx; + struct arm_smmu_cd_table *table; + struct arm_smmu_device *smmu = smmu_domain->smmu; + struct arm_smmu_s1_cfg *cfg = &smmu_domain->s1_cfg; + + if (cfg->s1fmt == STRTAB_STE_0_S1FMT_LINEAR) { + table = &cfg->tables[0]; + idx = ssid; + } else {nit: you may avoid this extra indent by either returning above or go to a label.quoted
+ idx = ssid >> CTXDESC_SPLIT; + if (idx >= cfg->num_tables) + return NULL; + + table = &cfg->tables[idx]; + if (!table->ptr) { + if (arm_smmu_alloc_cd_leaf_table(smmu, table, + CTXDESC_L2_ENTRIES)) + return NULL; + + l1ptr = cfg->l1ptr + idx * CTXDESC_L1_DESC_DWORDS; + arm_smmu_write_cd_l1_desc(l1ptr, table); + /* An invalid L1CD can be cached */ + arm_smmu_sync_cd(smmu_domain, ssid, false); + } + idx = ssid & (CTXDESC_L2_ENTRIES - 1); + } + return table->ptr + idx * CTXDESC_CD_DWORDS;> +} + static u64 arm_smmu_cpu_tcr_to_cd(u64 tcr) { u64 val = 0;@@ -1556,8 +1617,10 @@ static int arm_smmu_write_ctx_desc(struct arm_smmu_domain *smmu_domain, u64 val; bool cd_live; struct arm_smmu_device *smmu = smmu_domain->smmu; - __le64 *cdptr = smmu_domain->s1_cfg.table.ptr + ssid * - CTXDESC_CD_DWORDS; + __le64 *cdptr = arm_smmu_get_cd_ptr(smmu_domain, ssid); + + if (!cdptr) + return -ENOMEM;-ENOMEM does not fit well with (idx >= cfg->num_tables) case Besides the idx is checked against the max table capacity only in non linear mode. Can't you check the ssid against cfg->s1cdmax earlier?
Ok, I'll move that check here Thanks, Jean _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel