iommu/arm-smmu: Updates for 4.4
Subsystems (4)
cover iommu/arm-smmu: Updates for 4.4
Hi all,
Here are the ARM SMMU updates I have queued for 4.4. I'm away next week, so I'll send a corresponding pull request shortly.
Will
--->8
Fabio Estevam (1):
iommu/arm-smmu: Remove unneeded '0x' annotation
Marc Zyngier (1):
iommu/arm-smmu: Add support for MSI on SMMUv3
Tirumalesh Chalamarla (1):
iommu/arm-smmu: ThunderX mis-extends 64bit registers
Will Deacon (3):
iommu/arm-smmu: Use drvdata instead of maintaining smmu_devices list iommu/arm-smmu: fix error checking for ASID and VMID allocation iommu/arm-smmu: remove redundant calculation of gr0 base address
.../devicetree/bindings/iommu/arm,smmu-v3.txt | 19 +++ drivers/iommu/Kconfig | 1 + drivers/iommu/arm-smmu-v3.c | 154 +++++++++++++++------ drivers/iommu/arm-smmu.c | 55 ++++---- 4 files changed, 159 insertions(+), 70 deletions(-)
Signature · 1 line
2.1.4
PATCH 1/6 iommu/arm-smmu: Use drvdata instead of maintaining smmu_devices list
Rather than keep a private list of struct arm_smmu_device and searching this whenever we need to look up the correct SMMU instance, instead use the drvdata field in the struct device to take care of the mapping for us.
--- drivers/iommu/arm-smmu-v3.c | 42 +++++++++--------------------------------- 1 file changed, 9 insertions(+), 33 deletions(-)
drivers/iommu/arm-smmu-v3.c +9 -33
@@ -28,6 +28,7 @@#include <linux/module.h> #include <linux/of.h> #include <linux/of_address.h> +#include <linux/of_platform.h> #include <linux/pci.h> #include <linux/platform_device.h>
@@ -568,7 +569,6 @@ struct arm_smmu_device {unsigned int sid_bits;struct arm_smmu_strtab_cfg strtab_cfg; -struct list_head list; };/* SMMU private data for an IOMMU group */
@@ -603,10 +603,6 @@ struct arm_smmu_domain {struct iommu_domain domain; }; -/* Our list of SMMU instances */ -static DEFINE_SPINLOCK (arm_smmu_devices_lock); -static LIST_HEAD (arm_smmu_devices); -struct arm_smmu_option_prop {u32 opt;const char *prop;
@@ -1722,7 +1718,8 @@ static void __arm_smmu_release_pci_iommudata(void *data)static struct arm_smmu_device *arm_smmu_get_for_pci_dev (struct pci_dev *pdev) {struct device_node *of_node; -struct arm_smmu_device *curr, *smmu =NULL ; +struct platform_device *smmu_pdev; +struct arm_smmu_device *smmu =NULL ;struct pci_bus *bus = pdev->bus;/* Walk up to the root bus */
@@ -1735,14 +1732,10 @@ static struct arm_smmu_device *arm_smmu_get_for_pci_dev(struct pci_dev *pdev)return NULL ;/* See if we can find an SMMU corresponding to the phandle */ -spin_lock (&arm_smmu_devices_lock); -list_for_each_entry (curr, &arm_smmu_devices, list) { -if (curr->dev->of_node == of_node) { - smmu = curr; -break ; - } - } -spin_unlock (&arm_smmu_devices_lock); + smmu_pdev =of_find_device_by_node (of_node); +if (smmu_pdev) + smmu =platform_get_drvdata (smmu_pdev); +of_node_put (of_node);return smmu; }
@@ -2609,10 +2602,7 @@ static int arm_smmu_device_dt_probe(struct platform_device *pdev) goto out_free_structures;/* Record our private device structure */ -INIT_LIST_HEAD (&smmu->list); -spin_lock (&arm_smmu_devices_lock); -list_add (&smmu->list, &arm_smmu_devices); -spin_unlock (&arm_smmu_devices_lock); +platform_set_drvdata (pdev, smmu);return 0 ; out_free_structures:
@@ -2622,21 +2612,7 @@ out_free_structures:static int arm_smmu_device_remove (struct platform_device *pdev) { -struct arm_smmu_device *curr, *smmu =NULL ; -struct device *dev = &pdev->dev; - -spin_lock (&arm_smmu_devices_lock); -list_for_each_entry (curr, &arm_smmu_devices, list) { -if (curr->dev == dev) { - smmu = curr; -list_del (&smmu->list); -break ; - } - } -spin_unlock (&arm_smmu_devices_lock); - -if (!smmu) -return -ENODEV ; +struct arm_smmu_device *smmu =platform_get_drvdata (pdev);arm_smmu_device_disable (smmu);arm_smmu_free_structures (smmu);
Signature · 1 line
2.1.4
PATCH 2/6 iommu/arm-smmu: Remove unneeded '0x' annotation
In reply to Will DeaconFrom: Fabio Estevam <[email protected]>
'%pad' automatically prints with '0x', so remove the explicit '0x' annotation.
--- drivers/iommu/arm-smmu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/iommu/arm-smmu.c +1 -1
@@ -1222,7 +1222,7 @@ static phys_addr_t arm_smmu_iova_to_phys_hard(struct iommu_domain *domain,if (readl_poll_timeout_atomic (cb_base +ARM_SMMU_CB_ATSR , tmp, !(tmp &ATSR_ACTIVE ),5 ,50 )) {dev_err (dev, -"iova to phys timed out on 0x%pad. Falling back to software table walk.\n" , +"iova to phys timed out on %pad. Falling back to software table walk.\n" , &iova);return ops->iova_to_phys (ops, iova); }
Signature · 1 line
2.1.4
PATCH 3/6 iommu/arm-smmu: ThunderX mis-extends 64bit registers
In reply to Will DeaconFrom: Tirumalesh Chalamarla <[email protected]>
The SMMU architecture defines two different behaviors when 64-bit registers are written with 32-bit writes. The first behavior causes zero extension into the upper 32-bits. The second behavior splits a 64-bit register into "normal" 32-bit register pairs.
On some buggy implementations, registers incorrectly zero extended when they should instead behave as normal 32-bit register pairs.
--- drivers/iommu/arm-smmu.c | 50 ++++++++++++++++++++++++++---------------------- 1 file changed, 27 insertions(+), 23 deletions(-)
drivers/iommu/arm-smmu.c +27 -23
@@ -70,6 +70,18 @@ ((smmu->options & ARM_SMMU_OPT_SECURE_CFG_ACCESS) \ ? 0x400 : 0)) +#ifdef CONFIG_64BIT +#define smmu_writeq writeq_relaxed +#else +#define smmu_writeq (reg64, addr) \ + do { \ + u64 __val = (reg64); \ + void __iomem *__addr = (addr); \ + writel_relaxed(__val >> 32, __addr + 4); \ + writel_relaxed(__val, __addr); \ + } while (0) +#endif +/* Configuration registers */ #define ARM_SMMU_GR0_sCR0 0x0#define sCR0_CLIENTPD (1 << 0)
@@ -185,10 +197,8 @@#define ARM_SMMU_CB_SCTLR 0x0#define ARM_SMMU_CB_RESUME 0x8#define ARM_SMMU_CB_TTBCR2 0x10 -#define ARM_SMMU_CB_TTBR0_LO 0x20 -#define ARM_SMMU_CB_TTBR0_HI 0x24 -#define ARM_SMMU_CB_TTBR1_LO 0x28 -#define ARM_SMMU_CB_TTBR1_HI 0x2c +#define ARM_SMMU_CB_TTBR0 0x20 +#define ARM_SMMU_CB_TTBR1 0x28#define ARM_SMMU_CB_TTBCR 0x30#define ARM_SMMU_CB_S1_MAIR0 0x38#define ARM_SMMU_CB_S1_MAIR1 0x3c
@@ -226,7 +236,7 @@#define TTBCR2_SEP_SHIFT 15#define TTBCR2_SEP_UPSTREAM (0x7 << TTBCR2_SEP_SHIFT) -#define TTBRn_HI_ASID_SHIFT 16 +#define TTBRn_ASID_SHIFT 48#define FSR_MULTI (1 << 31)#define FSR_SS (1 << 30)
@@ -695,6 +705,7 @@ static void arm_smmu_init_context_bank(struct arm_smmu_domain *smmu_domain, struct io_pgtable_cfg *pgtbl_cfg) {u32 reg; +u64 reg64;bool stage1;struct arm_smmu_cfg *cfg = &smmu_domain->cfg;struct arm_smmu_device *smmu = smmu_domain->smmu;
@@ -738,22 +749,17 @@ static void arm_smmu_init_context_bank(struct arm_smmu_domain *smmu_domain,/* TTBRs */ if (stage1) { - reg = pgtbl_cfg->arm_lpae_s1_cfg.ttbr[0 ]; -writel_relaxed (reg, cb_base +ARM_SMMU_CB_TTBR0_LO ); - reg = pgtbl_cfg->arm_lpae_s1_cfg.ttbr[0 ] >>32 ; - reg |=ARM_SMMU_CB_ASID (cfg) << TTBRn_HI_ASID_SHIFT; -writel_relaxed (reg, cb_base +ARM_SMMU_CB_TTBR0_HI ); - - reg = pgtbl_cfg->arm_lpae_s1_cfg.ttbr[1 ]; -writel_relaxed (reg, cb_base +ARM_SMMU_CB_TTBR1_LO ); - reg = pgtbl_cfg->arm_lpae_s1_cfg.ttbr[1 ] >>32 ; - reg |=ARM_SMMU_CB_ASID (cfg) << TTBRn_HI_ASID_SHIFT; -writel_relaxed (reg, cb_base +ARM_SMMU_CB_TTBR1_HI ); + reg64 = pgtbl_cfg->arm_lpae_s1_cfg.ttbr[0 ]; + + reg64 |= ((u64 )ARM_SMMU_CB_ASID (cfg)) << TTBRn_ASID_SHIFT; +smmu_writeq (reg64, cb_base +ARM_SMMU_CB_TTBR0 ); + + reg64 = pgtbl_cfg->arm_lpae_s1_cfg.ttbr[1 ]; + reg64 |= ((u64 )ARM_SMMU_CB_ASID (cfg)) << TTBRn_ASID_SHIFT; +smmu_writeq (reg64, cb_base +ARM_SMMU_CB_TTBR1 ); }else { - reg = pgtbl_cfg->arm_lpae_s2_cfg.vttbr; -writel_relaxed (reg, cb_base +ARM_SMMU_CB_TTBR0_LO ); - reg = pgtbl_cfg->arm_lpae_s2_cfg.vttbr >>32 ; -writel_relaxed (reg, cb_base +ARM_SMMU_CB_TTBR0_HI ); + reg64 = pgtbl_cfg->arm_lpae_s2_cfg.vttbr; +smmu_writeq (reg64, cb_base +ARM_SMMU_CB_TTBR0 ); }/* TTBCR */
@@ -1212,11 +1218,9 @@ static phys_addr_t arm_smmu_iova_to_phys_hard(struct iommu_domain *domain,/* ATS1 registers can only be written atomically */ va = iova & ~0xfffUL ; -#ifdef CONFIG_64BIT if (smmu->version ==ARM_SMMU_V2 ) -writeq_relaxed (va, cb_base +ARM_SMMU_CB_ATS1PR ); +smmu_writeq (va, cb_base +ARM_SMMU_CB_ATS1PR );else -#endif writel_relaxed (va, cb_base +ARM_SMMU_CB_ATS1PR ); if (readl_poll_timeout_atomic(cb_base + ARM_SMMU_CB_ATSR, tmp,
Signature · 1 line
2.1.4
PATCH 4/6 iommu/arm-smmu: fix error checking for ASID and VMID allocation
In reply to Will DeaconThe bitmap allocator returns an int, which is one of the standard negative values on failure. Rather than assigning this straight to a u16 (like we do for the ASID and VMID callers), which means that we won't detect failure correctly, use an int for the purposes of error checking.
--- drivers/iommu/arm-smmu-v3.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-)
drivers/iommu/arm-smmu-v3.c +5 -4
@@ -1419,7 +1419,7 @@ static int arm_smmu_domain_finalise_s1(struct arm_smmu_domain *smmu_domain, struct io_pgtable_cfg *pgtbl_cfg) {int ret; -u16 asid; +int asid;struct arm_smmu_device *smmu = smmu_domain->smmu;struct arm_smmu_s1_cfg *cfg = &smmu_domain->s1_cfg;
@@ -1431,10 +1431,11 @@ static int arm_smmu_domain_finalise_s1(struct arm_smmu_domain *smmu_domain, &cfg->cdptr_dma, GFP_KERNEL);if (!cfg->cdptr) {dev_warn (smmu->dev,"failed to allocate context descriptor\n" ); + ret = -ENOMEM ; goto out_free_asid; } - cfg->cd.asid = asid; + cfg->cd.asid = (u16 )asid; cfg->cd.ttbr = pgtbl_cfg->arm_lpae_s1_cfg.ttbr[0 ]; cfg->cd.tcr = pgtbl_cfg->arm_lpae_s1_cfg.tcr; cfg->cd.mair = pgtbl_cfg->arm_lpae_s1_cfg.mair[0 ];
@@ -1448,7 +1449,7 @@ out_free_asid:static int arm_smmu_domain_finalise_s2 (struct arm_smmu_domain *smmu_domain,struct io_pgtable_cfg *pgtbl_cfg) { -u16 vmid; +int vmid;struct arm_smmu_device *smmu = smmu_domain->smmu;struct arm_smmu_s2_cfg *cfg = &smmu_domain->s2_cfg;
@@ -1456,7 +1457,7 @@ static int arm_smmu_domain_finalise_s2(struct arm_smmu_domain *smmu_domain,if (IS_ERR_VALUE (vmid))return vmid; - cfg->vmid = vmid; + cfg->vmid = (u16 )vmid; cfg->vttbr = pgtbl_cfg->arm_lpae_s2_cfg.vttbr; cfg->vtcr = pgtbl_cfg->arm_lpae_s2_cfg.vtcr;return 0 ;
Signature · 1 line
2.1.4
PATCH 5/6 iommu/arm-smmu: remove redundant calculation of gr0 base address
In reply to Will DeaconSince commit 1463fe44fd0f ("iommu/arm-smmu: Don't use VMIDs for stage-1 translations"), we don't need the GR0 base address when initialising a context bank, so remove the useless local variable and its init code.
--- drivers/iommu/arm-smmu.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
drivers/iommu/arm-smmu.c +1 -2
@@ -709,9 +709,8 @@ static void arm_smmu_init_context_bank(struct arm_smmu_domain *smmu_domain,bool stage1;struct arm_smmu_cfg *cfg = &smmu_domain->cfg;struct arm_smmu_device *smmu = smmu_domain->smmu; -void __iomem *cb_base, *gr0_base, *gr1_base; +void __iomem *cb_base, *gr1_base; - gr0_base =ARM_SMMU_GR0 (smmu); gr1_base =ARM_SMMU_GR1 (smmu); stage1 = cfg->cbar !=CBAR_TYPE_S2_TRANS ; cb_base =ARM_SMMU_CB_BASE (smmu) +ARM_SMMU_CB (smmu, cfg->cbndx);
Signature · 1 line
2.1.4
PATCH 6/6 iommu/arm-smmu: Add support for MSI on SMMUv3
In reply to Will DeaconFrom: Marc Zyngier <[email protected]>
Despite being a platform device, the SMMUv3 is capable of signaling interrupts using MSIs. Hook it into the platform MSI framework and enjoy faults being reported in a new and exciting way.
--- .../devicetree/bindings/iommu/arm,smmu-v3.txt | 19 ++++ drivers/iommu/Kconfig | 1 + drivers/iommu/arm-smmu-v3.c | 105 +++++++++++++++++++-- 3 files changed, 117 insertions(+), 8 deletions(-)
Documentation/devicetree/bindings/iommu/arm,smmu-v3.txt +19 -0
@@ -36,5 +36,24 @@ the PCIe specification. NOTE: this only applies to the SMMU itself, not masters connected upstream of the SMMU. +- msi-parent : See the generic MSI binding described in + devicetree/bindings/interrupt-controller/msi.txt + for a description of the msi-parent property. + - hisilicon,broken-prefetch-cmd : Avoid sending CMD_PREFETCH_* commands to the SMMU. + +** Example + + smmu at 2b400000 { + compatible = "arm,smmu-v3"; + reg = <0x0 0x2b400000 0x0 0x20000>; + interrupts = <GIC_SPI 74 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 75 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 77 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 79 IRQ_TYPE_EDGE_RISING>; + interrupt-names = "eventq", "priq", "cmdq-sync", "gerror"; + dma-coherent; + #iommu-cells = <0>; + msi-parent = <&its 0xff0000>; + };
drivers/iommu/Kconfig +1 -0
@@ -362,6 +362,7 @@ config ARM_SMMU_V3 depends on ARM64 && PCI select IOMMU_API select IOMMU_IO_PGTABLE_LPAE + select GENERIC_MSI_IRQ_DOMAIN help Support for implementations of the ARM System MMU architecture version 3 providing translation support to a PCIe root complex.
drivers/iommu/arm-smmu-v3.c +97 -8
147 lines not on this page · raw message
Signature · 1 line
2.1.4
cover iommu/arm-smmu: Updates for 4.4
In reply to Will DeaconHi Will,
Quoted 2 lines · Will Deacon
Here are the ARM SMMU updates I have queued for 4.4. I'm away next week, so I'll send a corresponding pull request shortly.
When you do, please make sure that all patch subjects start with a capital letter after the colon.
Thanks,
Joerg