From: Robin Murphy <robin.murphy-5wv7dgnIgG8@public.gmane.org> To: will.deacon-5wv7dgnIgG8@public.gmane.org, joro-zLv9SwRftAIdnm+yROfE0A@public.gmane.org, iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA@public.gmane.org, linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org Cc: devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, punit.agrawal-5wv7dgnIgG8@public.gmane.org, thunder.leizhen-hv44wF8Li93QT0dZR+AlfA@public.gmane.org Subject: [PATCH v7 11/22] iommu/arm-smmu: Consolidate stream map entry state Date: Mon, 12 Sep 2016 17:13:49 +0100 [thread overview] Message-ID: <9c3bc893a478185c1002f5c290ff79f0caeeba57.1473695704.git.robin.murphy@arm.com> (raw) In-Reply-To: <cover.1473695704.git.robin.murphy-5wv7dgnIgG8@public.gmane.org> In order to consider SMR masking, we really want to be able to validate ID/mask pairs against existing SMR contents to prevent stream match conflicts, which at best would cause transactions to fault unexpectedly, and at worst lead to silent unpredictable behaviour. With our SMMU instance data holding only an allocator bitmap, and the SMR values themselves scattered across master configs hanging off devices which we may have no way of finding, there's essentially no way short of digging everything back out of the hardware. Similarly, the thought of power management ops to support suspend/resume faces the exact same problem. By massaging the software state into a closer shape to the underlying hardware, everything comes together quite nicely; the allocator and the high-level view of the data become a single centralised state which we can easily keep track of, and to which any updates can be validated in full before being synchronised to the hardware itself. Signed-off-by: Robin Murphy <robin.murphy-5wv7dgnIgG8@public.gmane.org> --- - Make INVALID_SMENDX checks explicit --- drivers/iommu/arm-smmu.c | 147 +++++++++++++++++++++++++++-------------------- 1 file changed, 86 insertions(+), 61 deletions(-) diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index f86d7887f69a..dfe13780ba54 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -28,6 +28,7 @@ #define pr_fmt(fmt) "arm-smmu: " fmt +#include <linux/atomic.h> #include <linux/delay.h> #include <linux/dma-iommu.h> #include <linux/dma-mapping.h> @@ -55,9 +56,6 @@ /* Maximum number of context banks per SMMU */ #define ARM_SMMU_MAX_CBS 128 -/* Maximum number of mapping groups per SMMU */ -#define ARM_SMMU_MAX_SMRS 128 - /* SMMU global address space */ #define ARM_SMMU_GR0(smmu) ((smmu)->base) #define ARM_SMMU_GR1(smmu) ((smmu)->base + (1 << (smmu)->pgshift)) @@ -295,16 +293,17 @@ enum arm_smmu_implementation { }; struct arm_smmu_smr { - u8 idx; u16 mask; u16 id; + bool valid; }; struct arm_smmu_master_cfg { int num_streamids; u16 streamids[MAX_MASTER_STREAMIDS]; - struct arm_smmu_smr *smrs; + s16 smendx[MAX_MASTER_STREAMIDS]; }; +#define INVALID_SMENDX -1 struct arm_smmu_master { struct device_node *of_node; @@ -346,7 +345,7 @@ struct arm_smmu_device { u32 num_mapping_groups; u16 streamid_mask; u16 smr_mask_mask; - DECLARE_BITMAP(smr_map, ARM_SMMU_MAX_SMRS); + struct arm_smmu_smr *smrs; unsigned long va_size; unsigned long ipa_size; @@ -550,6 +549,7 @@ static int register_smmu_master(struct arm_smmu_device *smmu, return -ERANGE; } master->cfg.streamids[i] = streamid; + master->cfg.smendx[i] = INVALID_SMENDX; } return insert_smmu_master(smmu, master); } @@ -1080,79 +1080,91 @@ static void arm_smmu_domain_free(struct iommu_domain *domain) kfree(smmu_domain); } -static int arm_smmu_master_configure_smrs(struct arm_smmu_device *smmu, - struct arm_smmu_master_cfg *cfg) +static int arm_smmu_alloc_smr(struct arm_smmu_device *smmu) { int i; - struct arm_smmu_smr *smrs; - void __iomem *gr0_base = ARM_SMMU_GR0(smmu); - if (!(smmu->features & ARM_SMMU_FEAT_STREAM_MATCH)) - return 0; + for (i = 0; i < smmu->num_mapping_groups; i++) + if (!cmpxchg(&smmu->smrs[i].valid, false, true)) + return i; - if (cfg->smrs) - return -EEXIST; + return INVALID_SMENDX; +} - smrs = kmalloc_array(cfg->num_streamids, sizeof(*smrs), GFP_KERNEL); - if (!smrs) { - dev_err(smmu->dev, "failed to allocate %d SMRs\n", - cfg->num_streamids); - return -ENOMEM; - } +static void arm_smmu_free_smr(struct arm_smmu_device *smmu, int idx) +{ + writel_relaxed(~SMR_VALID, ARM_SMMU_GR0(smmu) + ARM_SMMU_GR0_SMR(idx)); + WRITE_ONCE(smmu->smrs[idx].valid, false); +} + +static void arm_smmu_write_smr(struct arm_smmu_device *smmu, int idx) +{ + struct arm_smmu_smr *smr = smmu->smrs + idx; + u32 reg = (smr->id & smmu->streamid_mask) << SMR_ID_SHIFT | + (smr->mask & smmu->smr_mask_mask) << SMR_MASK_SHIFT; + + if (smr->valid) + reg |= SMR_VALID; + writel_relaxed(reg, ARM_SMMU_GR0(smmu) + ARM_SMMU_GR0_SMR(idx)); +} + +static int arm_smmu_master_alloc_smes(struct arm_smmu_device *smmu, + struct arm_smmu_master_cfg *cfg) +{ + struct arm_smmu_smr *smrs = smmu->smrs; + int i, idx; /* Allocate the SMRs on the SMMU */ for (i = 0; i < cfg->num_streamids; ++i) { - int idx = __arm_smmu_alloc_bitmap(smmu->smr_map, 0, - smmu->num_mapping_groups); + if (cfg->smendx[i] != INVALID_SMENDX) + return -EEXIST; + + /* ...except on stream indexing hardware, of course */ + if (!smrs) { + cfg->smendx[i] = cfg->streamids[i]; + continue; + } + + idx = arm_smmu_alloc_smr(smmu); if (idx < 0) { dev_err(smmu->dev, "failed to allocate free SMR\n"); goto err_free_smrs; } + cfg->smendx[i] = idx; - smrs[i] = (struct arm_smmu_smr) { - .idx = idx, - .mask = 0, /* We don't currently share SMRs */ - .id = cfg->streamids[i], - }; + smrs[idx].id = cfg->streamids[i]; + smrs[idx].mask = 0; /* We don't currently share SMRs */ } + if (!smrs) + return 0; + /* It worked! Now, poke the actual hardware */ - for (i = 0; i < cfg->num_streamids; ++i) { - u32 reg = SMR_VALID | smrs[i].id << SMR_ID_SHIFT | - smrs[i].mask << SMR_MASK_SHIFT; - writel_relaxed(reg, gr0_base + ARM_SMMU_GR0_SMR(smrs[i].idx)); - } + for (i = 0; i < cfg->num_streamids; ++i) + arm_smmu_write_smr(smmu, cfg->smendx[i]); - cfg->smrs = smrs; return 0; err_free_smrs: - while (--i >= 0) - __arm_smmu_free_bitmap(smmu->smr_map, smrs[i].idx); - kfree(smrs); + while (i--) { + arm_smmu_free_smr(smmu, cfg->smendx[i]); + cfg->smendx[i] = INVALID_SMENDX; + } return -ENOSPC; } -static void arm_smmu_master_free_smrs(struct arm_smmu_device *smmu, +static void arm_smmu_master_free_smes(struct arm_smmu_device *smmu, struct arm_smmu_master_cfg *cfg) { int i; - void __iomem *gr0_base = ARM_SMMU_GR0(smmu); - struct arm_smmu_smr *smrs = cfg->smrs; - - if (!smrs) - return; /* Invalidate the SMRs before freeing back to the allocator */ for (i = 0; i < cfg->num_streamids; ++i) { - u8 idx = smrs[i].idx; + if (smmu->smrs) + arm_smmu_free_smr(smmu, cfg->smendx[i]); - writel_relaxed(~SMR_VALID, gr0_base + ARM_SMMU_GR0_SMR(idx)); - __arm_smmu_free_bitmap(smmu->smr_map, idx); + cfg->smendx[i] = INVALID_SMENDX; } - - cfg->smrs = NULL; - kfree(smrs); } static int arm_smmu_domain_add_master(struct arm_smmu_domain *smmu_domain, @@ -1172,14 +1184,14 @@ static int arm_smmu_domain_add_master(struct arm_smmu_domain *smmu_domain, return 0; /* Devices in an IOMMU group may already be configured */ - ret = arm_smmu_master_configure_smrs(smmu, cfg); + ret = arm_smmu_master_alloc_smes(smmu, cfg); if (ret) return ret == -EEXIST ? 0 : ret; for (i = 0; i < cfg->num_streamids; ++i) { u32 idx, s2cr; - idx = cfg->smrs ? cfg->smrs[i].idx : cfg->streamids[i]; + idx = cfg->smendx[i]; s2cr = S2CR_TYPE_TRANS | S2CR_PRIVCFG_UNPRIV | (smmu_domain->cfg.cbndx << S2CR_CBNDX_SHIFT); writel_relaxed(s2cr, gr0_base + ARM_SMMU_GR0_S2CR(idx)); @@ -1195,22 +1207,22 @@ static void arm_smmu_domain_remove_master(struct arm_smmu_domain *smmu_domain, struct arm_smmu_device *smmu = smmu_domain->smmu; void __iomem *gr0_base = ARM_SMMU_GR0(smmu); - /* An IOMMU group is torn down by the first device to be removed */ - if ((smmu->features & ARM_SMMU_FEAT_STREAM_MATCH) && !cfg->smrs) - return; - /* * We *must* clear the S2CR first, because freeing the SMR means * that it can be re-allocated immediately. */ for (i = 0; i < cfg->num_streamids; ++i) { - u32 idx = cfg->smrs ? cfg->smrs[i].idx : cfg->streamids[i]; + int idx = cfg->smendx[i]; u32 reg = disable_bypass ? S2CR_TYPE_FAULT : S2CR_TYPE_BYPASS; + /* An IOMMU group is torn down by the first device to be removed */ + if (idx == INVALID_SMENDX) + return; + writel_relaxed(reg, gr0_base + ARM_SMMU_GR0_S2CR(idx)); } - arm_smmu_master_free_smrs(smmu, cfg); + arm_smmu_master_free_smes(smmu, cfg); } static void arm_smmu_detach_dev(struct device *dev, @@ -1424,8 +1436,11 @@ static int arm_smmu_init_pci_device(struct pci_dev *pdev, break; /* Avoid duplicate SIDs, as this can lead to SMR conflicts */ - if (i == cfg->num_streamids) - cfg->streamids[cfg->num_streamids++] = sid; + if (i == cfg->num_streamids) { + cfg->streamids[i] = sid; + cfg->smendx[i] = INVALID_SMENDX; + cfg->num_streamids++; + } return 0; } @@ -1556,17 +1571,21 @@ static void arm_smmu_device_reset(struct arm_smmu_device *smmu) { void __iomem *gr0_base = ARM_SMMU_GR0(smmu); void __iomem *cb_base; - int i = 0; + int i; u32 reg, major; /* clear global FSR */ reg = readl_relaxed(ARM_SMMU_GR0_NS(smmu) + ARM_SMMU_GR0_sGFSR); writel(reg, ARM_SMMU_GR0_NS(smmu) + ARM_SMMU_GR0_sGFSR); - /* Mark all SMRn as invalid and all S2CRn as bypass unless overridden */ + /* + * Reset stream mapping groups: Initial values mark all SMRn as + * invalid and all S2CRn as bypass unless overridden. + */ reg = disable_bypass ? S2CR_TYPE_FAULT : S2CR_TYPE_BYPASS; for (i = 0; i < smmu->num_mapping_groups; ++i) { - writel_relaxed(0, gr0_base + ARM_SMMU_GR0_SMR(i)); + if (smmu->smrs) + arm_smmu_write_smr(smmu, i); writel_relaxed(reg, gr0_base + ARM_SMMU_GR0_S2CR(i)); } @@ -1744,6 +1763,12 @@ static int arm_smmu_device_cfg_probe(struct arm_smmu_device *smmu) smr = readl_relaxed(gr0_base + ARM_SMMU_GR0_SMR(0)); smmu->smr_mask_mask = smr >> SMR_MASK_SHIFT; + /* Zero-initialised to mark as invalid */ + smmu->smrs = devm_kcalloc(smmu->dev, size, sizeof(*smmu->smrs), + GFP_KERNEL); + if (!smmu->smrs) + return -ENOMEM; + dev_notice(smmu->dev, "\tstream matching with %lu register groups, mask 0x%x", size, smmu->smr_mask_mask); -- 2.8.1.dirty
WARNING: multiple messages have this Message-ID (diff)
From: robin.murphy@arm.com (Robin Murphy) To: linux-arm-kernel@lists.infradead.org Subject: [PATCH v7 11/22] iommu/arm-smmu: Consolidate stream map entry state Date: Mon, 12 Sep 2016 17:13:49 +0100 [thread overview] Message-ID: <9c3bc893a478185c1002f5c290ff79f0caeeba57.1473695704.git.robin.murphy@arm.com> (raw) In-Reply-To: <cover.1473695704.git.robin.murphy@arm.com> In order to consider SMR masking, we really want to be able to validate ID/mask pairs against existing SMR contents to prevent stream match conflicts, which at best would cause transactions to fault unexpectedly, and at worst lead to silent unpredictable behaviour. With our SMMU instance data holding only an allocator bitmap, and the SMR values themselves scattered across master configs hanging off devices which we may have no way of finding, there's essentially no way short of digging everything back out of the hardware. Similarly, the thought of power management ops to support suspend/resume faces the exact same problem. By massaging the software state into a closer shape to the underlying hardware, everything comes together quite nicely; the allocator and the high-level view of the data become a single centralised state which we can easily keep track of, and to which any updates can be validated in full before being synchronised to the hardware itself. Signed-off-by: Robin Murphy <robin.murphy@arm.com> --- - Make INVALID_SMENDX checks explicit --- drivers/iommu/arm-smmu.c | 147 +++++++++++++++++++++++++++-------------------- 1 file changed, 86 insertions(+), 61 deletions(-) diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index f86d7887f69a..dfe13780ba54 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -28,6 +28,7 @@ #define pr_fmt(fmt) "arm-smmu: " fmt +#include <linux/atomic.h> #include <linux/delay.h> #include <linux/dma-iommu.h> #include <linux/dma-mapping.h> @@ -55,9 +56,6 @@ /* Maximum number of context banks per SMMU */ #define ARM_SMMU_MAX_CBS 128 -/* Maximum number of mapping groups per SMMU */ -#define ARM_SMMU_MAX_SMRS 128 - /* SMMU global address space */ #define ARM_SMMU_GR0(smmu) ((smmu)->base) #define ARM_SMMU_GR1(smmu) ((smmu)->base + (1 << (smmu)->pgshift)) @@ -295,16 +293,17 @@ enum arm_smmu_implementation { }; struct arm_smmu_smr { - u8 idx; u16 mask; u16 id; + bool valid; }; struct arm_smmu_master_cfg { int num_streamids; u16 streamids[MAX_MASTER_STREAMIDS]; - struct arm_smmu_smr *smrs; + s16 smendx[MAX_MASTER_STREAMIDS]; }; +#define INVALID_SMENDX -1 struct arm_smmu_master { struct device_node *of_node; @@ -346,7 +345,7 @@ struct arm_smmu_device { u32 num_mapping_groups; u16 streamid_mask; u16 smr_mask_mask; - DECLARE_BITMAP(smr_map, ARM_SMMU_MAX_SMRS); + struct arm_smmu_smr *smrs; unsigned long va_size; unsigned long ipa_size; @@ -550,6 +549,7 @@ static int register_smmu_master(struct arm_smmu_device *smmu, return -ERANGE; } master->cfg.streamids[i] = streamid; + master->cfg.smendx[i] = INVALID_SMENDX; } return insert_smmu_master(smmu, master); } @@ -1080,79 +1080,91 @@ static void arm_smmu_domain_free(struct iommu_domain *domain) kfree(smmu_domain); } -static int arm_smmu_master_configure_smrs(struct arm_smmu_device *smmu, - struct arm_smmu_master_cfg *cfg) +static int arm_smmu_alloc_smr(struct arm_smmu_device *smmu) { int i; - struct arm_smmu_smr *smrs; - void __iomem *gr0_base = ARM_SMMU_GR0(smmu); - if (!(smmu->features & ARM_SMMU_FEAT_STREAM_MATCH)) - return 0; + for (i = 0; i < smmu->num_mapping_groups; i++) + if (!cmpxchg(&smmu->smrs[i].valid, false, true)) + return i; - if (cfg->smrs) - return -EEXIST; + return INVALID_SMENDX; +} - smrs = kmalloc_array(cfg->num_streamids, sizeof(*smrs), GFP_KERNEL); - if (!smrs) { - dev_err(smmu->dev, "failed to allocate %d SMRs\n", - cfg->num_streamids); - return -ENOMEM; - } +static void arm_smmu_free_smr(struct arm_smmu_device *smmu, int idx) +{ + writel_relaxed(~SMR_VALID, ARM_SMMU_GR0(smmu) + ARM_SMMU_GR0_SMR(idx)); + WRITE_ONCE(smmu->smrs[idx].valid, false); +} + +static void arm_smmu_write_smr(struct arm_smmu_device *smmu, int idx) +{ + struct arm_smmu_smr *smr = smmu->smrs + idx; + u32 reg = (smr->id & smmu->streamid_mask) << SMR_ID_SHIFT | + (smr->mask & smmu->smr_mask_mask) << SMR_MASK_SHIFT; + + if (smr->valid) + reg |= SMR_VALID; + writel_relaxed(reg, ARM_SMMU_GR0(smmu) + ARM_SMMU_GR0_SMR(idx)); +} + +static int arm_smmu_master_alloc_smes(struct arm_smmu_device *smmu, + struct arm_smmu_master_cfg *cfg) +{ + struct arm_smmu_smr *smrs = smmu->smrs; + int i, idx; /* Allocate the SMRs on the SMMU */ for (i = 0; i < cfg->num_streamids; ++i) { - int idx = __arm_smmu_alloc_bitmap(smmu->smr_map, 0, - smmu->num_mapping_groups); + if (cfg->smendx[i] != INVALID_SMENDX) + return -EEXIST; + + /* ...except on stream indexing hardware, of course */ + if (!smrs) { + cfg->smendx[i] = cfg->streamids[i]; + continue; + } + + idx = arm_smmu_alloc_smr(smmu); if (idx < 0) { dev_err(smmu->dev, "failed to allocate free SMR\n"); goto err_free_smrs; } + cfg->smendx[i] = idx; - smrs[i] = (struct arm_smmu_smr) { - .idx = idx, - .mask = 0, /* We don't currently share SMRs */ - .id = cfg->streamids[i], - }; + smrs[idx].id = cfg->streamids[i]; + smrs[idx].mask = 0; /* We don't currently share SMRs */ } + if (!smrs) + return 0; + /* It worked! Now, poke the actual hardware */ - for (i = 0; i < cfg->num_streamids; ++i) { - u32 reg = SMR_VALID | smrs[i].id << SMR_ID_SHIFT | - smrs[i].mask << SMR_MASK_SHIFT; - writel_relaxed(reg, gr0_base + ARM_SMMU_GR0_SMR(smrs[i].idx)); - } + for (i = 0; i < cfg->num_streamids; ++i) + arm_smmu_write_smr(smmu, cfg->smendx[i]); - cfg->smrs = smrs; return 0; err_free_smrs: - while (--i >= 0) - __arm_smmu_free_bitmap(smmu->smr_map, smrs[i].idx); - kfree(smrs); + while (i--) { + arm_smmu_free_smr(smmu, cfg->smendx[i]); + cfg->smendx[i] = INVALID_SMENDX; + } return -ENOSPC; } -static void arm_smmu_master_free_smrs(struct arm_smmu_device *smmu, +static void arm_smmu_master_free_smes(struct arm_smmu_device *smmu, struct arm_smmu_master_cfg *cfg) { int i; - void __iomem *gr0_base = ARM_SMMU_GR0(smmu); - struct arm_smmu_smr *smrs = cfg->smrs; - - if (!smrs) - return; /* Invalidate the SMRs before freeing back to the allocator */ for (i = 0; i < cfg->num_streamids; ++i) { - u8 idx = smrs[i].idx; + if (smmu->smrs) + arm_smmu_free_smr(smmu, cfg->smendx[i]); - writel_relaxed(~SMR_VALID, gr0_base + ARM_SMMU_GR0_SMR(idx)); - __arm_smmu_free_bitmap(smmu->smr_map, idx); + cfg->smendx[i] = INVALID_SMENDX; } - - cfg->smrs = NULL; - kfree(smrs); } static int arm_smmu_domain_add_master(struct arm_smmu_domain *smmu_domain, @@ -1172,14 +1184,14 @@ static int arm_smmu_domain_add_master(struct arm_smmu_domain *smmu_domain, return 0; /* Devices in an IOMMU group may already be configured */ - ret = arm_smmu_master_configure_smrs(smmu, cfg); + ret = arm_smmu_master_alloc_smes(smmu, cfg); if (ret) return ret == -EEXIST ? 0 : ret; for (i = 0; i < cfg->num_streamids; ++i) { u32 idx, s2cr; - idx = cfg->smrs ? cfg->smrs[i].idx : cfg->streamids[i]; + idx = cfg->smendx[i]; s2cr = S2CR_TYPE_TRANS | S2CR_PRIVCFG_UNPRIV | (smmu_domain->cfg.cbndx << S2CR_CBNDX_SHIFT); writel_relaxed(s2cr, gr0_base + ARM_SMMU_GR0_S2CR(idx)); @@ -1195,22 +1207,22 @@ static void arm_smmu_domain_remove_master(struct arm_smmu_domain *smmu_domain, struct arm_smmu_device *smmu = smmu_domain->smmu; void __iomem *gr0_base = ARM_SMMU_GR0(smmu); - /* An IOMMU group is torn down by the first device to be removed */ - if ((smmu->features & ARM_SMMU_FEAT_STREAM_MATCH) && !cfg->smrs) - return; - /* * We *must* clear the S2CR first, because freeing the SMR means * that it can be re-allocated immediately. */ for (i = 0; i < cfg->num_streamids; ++i) { - u32 idx = cfg->smrs ? cfg->smrs[i].idx : cfg->streamids[i]; + int idx = cfg->smendx[i]; u32 reg = disable_bypass ? S2CR_TYPE_FAULT : S2CR_TYPE_BYPASS; + /* An IOMMU group is torn down by the first device to be removed */ + if (idx == INVALID_SMENDX) + return; + writel_relaxed(reg, gr0_base + ARM_SMMU_GR0_S2CR(idx)); } - arm_smmu_master_free_smrs(smmu, cfg); + arm_smmu_master_free_smes(smmu, cfg); } static void arm_smmu_detach_dev(struct device *dev, @@ -1424,8 +1436,11 @@ static int arm_smmu_init_pci_device(struct pci_dev *pdev, break; /* Avoid duplicate SIDs, as this can lead to SMR conflicts */ - if (i == cfg->num_streamids) - cfg->streamids[cfg->num_streamids++] = sid; + if (i == cfg->num_streamids) { + cfg->streamids[i] = sid; + cfg->smendx[i] = INVALID_SMENDX; + cfg->num_streamids++; + } return 0; } @@ -1556,17 +1571,21 @@ static void arm_smmu_device_reset(struct arm_smmu_device *smmu) { void __iomem *gr0_base = ARM_SMMU_GR0(smmu); void __iomem *cb_base; - int i = 0; + int i; u32 reg, major; /* clear global FSR */ reg = readl_relaxed(ARM_SMMU_GR0_NS(smmu) + ARM_SMMU_GR0_sGFSR); writel(reg, ARM_SMMU_GR0_NS(smmu) + ARM_SMMU_GR0_sGFSR); - /* Mark all SMRn as invalid and all S2CRn as bypass unless overridden */ + /* + * Reset stream mapping groups: Initial values mark all SMRn as + * invalid and all S2CRn as bypass unless overridden. + */ reg = disable_bypass ? S2CR_TYPE_FAULT : S2CR_TYPE_BYPASS; for (i = 0; i < smmu->num_mapping_groups; ++i) { - writel_relaxed(0, gr0_base + ARM_SMMU_GR0_SMR(i)); + if (smmu->smrs) + arm_smmu_write_smr(smmu, i); writel_relaxed(reg, gr0_base + ARM_SMMU_GR0_S2CR(i)); } @@ -1744,6 +1763,12 @@ static int arm_smmu_device_cfg_probe(struct arm_smmu_device *smmu) smr = readl_relaxed(gr0_base + ARM_SMMU_GR0_SMR(0)); smmu->smr_mask_mask = smr >> SMR_MASK_SHIFT; + /* Zero-initialised to mark as invalid */ + smmu->smrs = devm_kcalloc(smmu->dev, size, sizeof(*smmu->smrs), + GFP_KERNEL); + if (!smmu->smrs) + return -ENOMEM; + dev_notice(smmu->dev, "\tstream matching with %lu register groups, mask 0x%x", size, smmu->smr_mask_mask); -- 2.8.1.dirty
next prev parent reply other threads:[~2016-09-12 16:13 UTC|newest] Thread overview: 104+ messages / expand[flat|nested] mbox.gz Atom feed top 2016-09-12 16:13 [PATCH v7 00/22] Generic DT bindings for PCI IOMMUs and ARM SMMU Robin Murphy 2016-09-12 16:13 ` Robin Murphy [not found] ` <cover.1473695704.git.robin.murphy-5wv7dgnIgG8@public.gmane.org> 2016-09-12 16:13 ` [PATCH v7 01/22] Docs: dt: add PCI IOMMU map bindings Robin Murphy 2016-09-12 16:13 ` Robin Murphy 2016-09-12 16:13 ` [PATCH v7 02/22] of/irq: Break out msi-map lookup (again) Robin Murphy 2016-09-12 16:13 ` Robin Murphy 2016-09-12 16:13 ` [PATCH v7 03/22] iommu/of: Handle iommu-map property for PCI Robin Murphy 2016-09-12 16:13 ` Robin Murphy 2016-09-12 16:13 ` [PATCH v7 04/22] iommu: Introduce iommu_fwspec Robin Murphy 2016-09-12 16:13 ` Robin Murphy [not found] ` <742a71630de502ac5a7a8641c6ed368d8409324d.1473695704.git.robin.murphy-5wv7dgnIgG8@public.gmane.org> 2016-09-13 9:54 ` [PATCH v7.1 " Robin Murphy 2016-09-13 9:54 ` Robin Murphy 2016-09-12 16:13 ` [PATCH v7 05/22] Docs: dt: document ARM SMMUv3 generic binding usage Robin Murphy 2016-09-12 16:13 ` Robin Murphy [not found] ` <2273645f1fa5c76b6b98b5fd03804ab8b55a7691.1473695704.git.robin.murphy-5wv7dgnIgG8@public.gmane.org> 2016-09-20 14:46 ` Rob Herring 2016-09-20 14:46 ` Rob Herring 2016-09-12 16:13 ` [PATCH v7 06/22] iommu/arm-smmu: Fall back to global bypass Robin Murphy 2016-09-12 16:13 ` Robin Murphy 2016-09-12 16:13 ` [PATCH v7 07/22] iommu/arm-smmu: Implement of_xlate() for SMMUv3 Robin Murphy 2016-09-12 16:13 ` Robin Murphy 2016-09-12 16:13 ` [PATCH v7 08/22] iommu/arm-smmu: Support non-PCI devices with SMMUv3 Robin Murphy 2016-09-12 16:13 ` Robin Murphy 2016-09-12 16:13 ` [PATCH v7 09/22] iommu/arm-smmu: Set PRIVCFG in stage 1 STEs Robin Murphy 2016-09-12 16:13 ` Robin Murphy 2016-09-12 16:13 ` [PATCH v7 10/22] iommu/arm-smmu: Handle stream IDs more dynamically Robin Murphy 2016-09-12 16:13 ` Robin Murphy 2016-09-12 16:13 ` Robin Murphy [this message] 2016-09-12 16:13 ` [PATCH v7 11/22] iommu/arm-smmu: Consolidate stream map entry state Robin Murphy 2016-09-12 16:13 ` [PATCH v7 12/22] iommu/arm-smmu: Keep track of S2CR state Robin Murphy 2016-09-12 16:13 ` Robin Murphy 2016-09-12 16:13 ` [PATCH v7 13/22] iommu/arm-smmu: Refactor mmu-masters handling Robin Murphy 2016-09-12 16:13 ` Robin Murphy [not found] ` <046d2d21f988d6ece916fc45b0af0804a7f200f2.1473695704.git.robin.murphy-5wv7dgnIgG8@public.gmane.org> 2016-09-14 14:21 ` [PATCH v7.1 " Robin Murphy 2016-09-14 14:21 ` Robin Murphy 2016-09-12 16:13 ` [PATCH v7 14/22] iommu/arm-smmu: Streamline SMMU data lookups Robin Murphy 2016-09-12 16:13 ` Robin Murphy 2016-09-12 16:13 ` [PATCH v7 15/22] iommu/arm-smmu: Add a stream map entry iterator Robin Murphy 2016-09-12 16:13 ` Robin Murphy 2016-09-12 16:13 ` [PATCH v7 16/22] iommu/arm-smmu: Intelligent SMR allocation Robin Murphy 2016-09-12 16:13 ` Robin Murphy 2016-09-12 16:13 ` [PATCH v7 17/22] iommu/arm-smmu: Convert to iommu_fwspec Robin Murphy 2016-09-12 16:13 ` Robin Murphy 2016-09-12 16:13 ` [PATCH v7 18/22] Docs: dt: document ARM SMMU generic binding usage Robin Murphy 2016-09-12 16:13 ` Robin Murphy 2016-09-12 16:13 ` [PATCH v7 19/22] iommu/arm-smmu: Wire up generic configuration support Robin Murphy 2016-09-12 16:13 ` Robin Murphy [not found] ` <228dc6c675f10ae7481640d4ef2f4960c170621f.1473695704.git.robin.murphy-5wv7dgnIgG8@public.gmane.org> 2016-09-14 14:26 ` [PATCH v7.1 " Robin Murphy 2016-09-14 14:26 ` Robin Murphy 2016-09-12 16:13 ` [PATCH v7 20/22] iommu/arm-smmu: Set domain geometry Robin Murphy 2016-09-12 16:13 ` Robin Murphy 2016-09-12 16:13 ` [PATCH v7 21/22] iommu/dma: Add support for mapping MSIs Robin Murphy 2016-09-12 16:13 ` Robin Murphy [not found] ` <2273af20d844bd618c6a90b57e639700328ebf7f.1473695704.git.robin.murphy-5wv7dgnIgG8@public.gmane.org> 2016-10-05 7:00 ` Nipun Gupta 2016-10-05 7:00 ` Nipun Gupta [not found] ` <DB6PR0402MB2694B2E5AE266F138784D2C2E6C40-2mNvjAGDOPn2WJ5A9zev/o3W/0Ik+aLCnBOFsp37pqbUKgpGm//BTAC/G2K4zDHf@public.gmane.org> 2016-10-05 9:55 ` Robin Murphy 2016-10-05 9:55 ` Robin Murphy [not found] ` <6ec9519b-01df-3be8-2967-7556bd306909-5wv7dgnIgG8@public.gmane.org> 2016-10-05 11:31 ` Nipun Gupta 2016-10-05 11:31 ` Nipun Gupta 2016-09-12 16:14 ` [PATCH v7 22/22] iommu/dma: Avoid PCI host bridge windows Robin Murphy 2016-09-12 16:14 ` Robin Murphy [not found] ` <5f7bfee298f98d29a35933d3e0252d32b83d62b8.1473695704.git.robin.murphy-5wv7dgnIgG8@public.gmane.org> 2016-09-14 10:55 ` Marek Szyprowski 2016-09-14 10:55 ` Marek Szyprowski [not found] ` <ab8693f6-20d6-2a95-9f1f-0607e72bc012-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org> 2016-09-14 11:10 ` Robin Murphy 2016-09-14 11:10 ` Robin Murphy [not found] ` <49c51c4f-cb00-445d-b8f8-b632babf2b3e-5wv7dgnIgG8@public.gmane.org> 2016-09-14 12:35 ` Marek Szyprowski 2016-09-14 12:35 ` Marek Szyprowski [not found] ` <dc9f945f-2756-ab70-d061-9fdc7c5afdee-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org> 2016-09-14 13:25 ` Robin Murphy 2016-09-14 13:25 ` Robin Murphy [not found] ` <bbdc42fa-ea35-945f-3e2a-e0ab03fc997d-5wv7dgnIgG8@public.gmane.org> 2016-09-15 7:08 ` Marek Szyprowski 2016-09-15 7:08 ` Marek Szyprowski 2016-09-13 12:14 ` [PATCH v7 00/22] Generic DT bindings for PCI IOMMUs and ARM SMMU Auger Eric 2016-09-13 12:14 ` Auger Eric [not found] ` <92f27a6b-9752-516d-3924-c552fc6a5ace-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org> 2016-09-13 12:40 ` Robin Murphy 2016-09-13 12:40 ` Robin Murphy [not found] ` <e24821be-5cc4-52b3-f961-1eb32cf58293-5wv7dgnIgG8@public.gmane.org> 2016-09-13 12:57 ` Auger Eric 2016-09-13 12:57 ` Auger Eric 2016-09-14 8:41 ` Auger Eric 2016-09-14 8:41 ` Auger Eric [not found] ` <11ebd81e-2ea5-5ff3-35b3-be95f03e05bd-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org> 2016-09-14 9:20 ` Will Deacon 2016-09-14 9:20 ` Will Deacon [not found] ` <20160914092051.GB19622-5wv7dgnIgG8@public.gmane.org> 2016-09-14 9:35 ` Auger Eric 2016-09-14 9:35 ` Auger Eric 2016-09-14 10:35 ` Robin Murphy 2016-09-14 10:35 ` Robin Murphy [not found] ` <d03ea5e7-59f1-8b49-4ba2-d05fc2030ebc-5wv7dgnIgG8@public.gmane.org> 2016-09-14 12:32 ` Auger Eric 2016-09-14 12:32 ` Auger Eric [not found] ` <04a0a682-4fdc-8d62-57cd-efdf730582c6-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org> 2016-09-14 12:53 ` Robin Murphy 2016-09-14 12:53 ` Robin Murphy [not found] ` <c2645c5e-edd3-2b31-4311-0ca621a915e2-5wv7dgnIgG8@public.gmane.org> 2016-09-15 9:29 ` Auger Eric 2016-09-15 9:29 ` Auger Eric [not found] ` <4d87d5f2-0350-b5f8-ffc3-4e9377cf1f87-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org> 2016-09-15 10:15 ` Robin Murphy 2016-09-15 10:15 ` Robin Murphy [not found] ` <fc4ce398-4eeb-f2ca-b964-e9f466be79c4-5wv7dgnIgG8@public.gmane.org> 2016-09-15 16:46 ` Auger Eric 2016-09-15 16:46 ` Auger Eric [not found] ` <1838c65d-5944-8946-781c-b420bea1acab-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org> 2016-09-16 16:18 ` Robin Murphy 2016-09-16 16:18 ` Robin Murphy [not found] ` <f16db032-1905-9804-0607-fe007af72b0e-5wv7dgnIgG8@public.gmane.org> 2016-09-19 12:13 ` Auger Eric 2016-09-19 12:13 ` Auger Eric [not found] ` <48f3bc10-3966-7d50-d070-7ec7f0946c92-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org> 2016-09-19 12:24 ` Will Deacon 2016-09-19 12:24 ` Will Deacon [not found] ` <20160919122435.GD9005-5wv7dgnIgG8@public.gmane.org> 2016-09-19 12:41 ` Robin Murphy 2016-09-19 12:41 ` Robin Murphy [not found] ` <99ee0946-c7ff-e6e4-08c1-ff686ea1a8a5-5wv7dgnIgG8@public.gmane.org> 2016-09-19 14:17 ` Will Deacon 2016-09-19 14:17 ` Will Deacon
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=9c3bc893a478185c1002f5c290ff79f0caeeba57.1473695704.git.robin.murphy@arm.com \ --to=robin.murphy-5wv7dgnigg8@public.gmane.org \ --cc=devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \ --cc=iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA@public.gmane.org \ --cc=joro-zLv9SwRftAIdnm+yROfE0A@public.gmane.org \ --cc=linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org \ --cc=punit.agrawal-5wv7dgnIgG8@public.gmane.org \ --cc=thunder.leizhen-hv44wF8Li93QT0dZR+AlfA@public.gmane.org \ --cc=will.deacon-5wv7dgnIgG8@public.gmane.org \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.