Skip to content

Commit dc0eaa4

Browse files
Aleksey Makarovwildea01
authored andcommitted
iommu/arm-smmu: Support for Extended Stream ID (16 bit)
It is the time we have the real 16-bit Stream ID user, which is the ThunderX. Its IO topology uses 1:1 map for Requester ID to Stream ID translation for each root complex which allows to get full 16-bit Stream ID. Firmware assigns bus IDs that are greater than 128 (0x80) to some buses under PEM (external PCIe interface). Eventually SMMU drops devices on that buses because their Stream ID is out of range: pci 0006:90:00.0: stream ID 0x9000 out of range for SMMU (0x7fff) To fix above issue enable the Extended Stream ID optional feature when available. Reviewed-by: Tomasz Nowicki <[email protected]> Signed-off-by: Aleksey Makarov <[email protected]> Tested-by: Tomasz Nowicki <[email protected]> Signed-off-by: Will Deacon <[email protected]>
1 parent 65e251a commit dc0eaa4

File tree

1 file changed

+48
-21
lines changed

1 file changed

+48
-21
lines changed

drivers/iommu/arm-smmu.c

Lines changed: 48 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
* - v7/v8 long-descriptor format
2525
* - Non-secure access to the SMMU
2626
* - Context fault reporting
27+
* - Extended Stream ID (16 bit)
2728
*/
2829

2930
#define pr_fmt(fmt) "arm-smmu: " fmt
@@ -87,6 +88,7 @@
8788
#define sCR0_CLIENTPD (1 << 0)
8889
#define sCR0_GFRE (1 << 1)
8990
#define sCR0_GFIE (1 << 2)
91+
#define sCR0_EXIDENABLE (1 << 3)
9092
#define sCR0_GCFGFRE (1 << 4)
9193
#define sCR0_GCFGFIE (1 << 5)
9294
#define sCR0_USFCFG (1 << 10)
@@ -126,6 +128,7 @@
126128
#define ID0_NUMIRPT_MASK 0xff
127129
#define ID0_NUMSIDB_SHIFT 9
128130
#define ID0_NUMSIDB_MASK 0xf
131+
#define ID0_EXIDS (1 << 8)
129132
#define ID0_NUMSMRG_SHIFT 0
130133
#define ID0_NUMSMRG_MASK 0xff
131134

@@ -169,6 +172,7 @@
169172
#define ARM_SMMU_GR0_S2CR(n) (0xc00 + ((n) << 2))
170173
#define S2CR_CBNDX_SHIFT 0
171174
#define S2CR_CBNDX_MASK 0xff
175+
#define S2CR_EXIDVALID (1 << 10)
172176
#define S2CR_TYPE_SHIFT 16
173177
#define S2CR_TYPE_MASK 0x3
174178
enum arm_smmu_s2cr_type {
@@ -351,6 +355,7 @@ struct arm_smmu_device {
351355
#define ARM_SMMU_FEAT_FMT_AARCH64_64K (1 << 9)
352356
#define ARM_SMMU_FEAT_FMT_AARCH32_L (1 << 10)
353357
#define ARM_SMMU_FEAT_FMT_AARCH32_S (1 << 11)
358+
#define ARM_SMMU_FEAT_EXIDS (1 << 12)
354359
u32 features;
355360

356361
#define ARM_SMMU_OPT_SECURE_CFG_ACCESS (1 << 0)
@@ -1048,7 +1053,7 @@ static void arm_smmu_write_smr(struct arm_smmu_device *smmu, int idx)
10481053
struct arm_smmu_smr *smr = smmu->smrs + idx;
10491054
u32 reg = smr->id << SMR_ID_SHIFT | smr->mask << SMR_MASK_SHIFT;
10501055

1051-
if (smr->valid)
1056+
if (!(smmu->features & ARM_SMMU_FEAT_EXIDS) && smr->valid)
10521057
reg |= SMR_VALID;
10531058
writel_relaxed(reg, ARM_SMMU_GR0(smmu) + ARM_SMMU_GR0_SMR(idx));
10541059
}
@@ -1060,6 +1065,9 @@ static void arm_smmu_write_s2cr(struct arm_smmu_device *smmu, int idx)
10601065
(s2cr->cbndx & S2CR_CBNDX_MASK) << S2CR_CBNDX_SHIFT |
10611066
(s2cr->privcfg & S2CR_PRIVCFG_MASK) << S2CR_PRIVCFG_SHIFT;
10621067

1068+
if (smmu->features & ARM_SMMU_FEAT_EXIDS && smmu->smrs &&
1069+
smmu->smrs[idx].valid)
1070+
reg |= S2CR_EXIDVALID;
10631071
writel_relaxed(reg, ARM_SMMU_GR0(smmu) + ARM_SMMU_GR0_S2CR(idx));
10641072
}
10651073

@@ -1070,6 +1078,34 @@ static void arm_smmu_write_sme(struct arm_smmu_device *smmu, int idx)
10701078
arm_smmu_write_smr(smmu, idx);
10711079
}
10721080

1081+
/*
1082+
* The width of SMR's mask field depends on sCR0_EXIDENABLE, so this function
1083+
* should be called after sCR0 is written.
1084+
*/
1085+
static void arm_smmu_test_smr_masks(struct arm_smmu_device *smmu)
1086+
{
1087+
void __iomem *gr0_base = ARM_SMMU_GR0(smmu);
1088+
u32 smr;
1089+
1090+
if (!smmu->smrs)
1091+
return;
1092+
1093+
/*
1094+
* SMR.ID bits may not be preserved if the corresponding MASK
1095+
* bits are set, so check each one separately. We can reject
1096+
* masters later if they try to claim IDs outside these masks.
1097+
*/
1098+
smr = smmu->streamid_mask << SMR_ID_SHIFT;
1099+
writel_relaxed(smr, gr0_base + ARM_SMMU_GR0_SMR(0));
1100+
smr = readl_relaxed(gr0_base + ARM_SMMU_GR0_SMR(0));
1101+
smmu->streamid_mask = smr >> SMR_ID_SHIFT;
1102+
1103+
smr = smmu->streamid_mask << SMR_MASK_SHIFT;
1104+
writel_relaxed(smr, gr0_base + ARM_SMMU_GR0_SMR(0));
1105+
smr = readl_relaxed(gr0_base + ARM_SMMU_GR0_SMR(0));
1106+
smmu->smr_mask_mask = smr >> SMR_MASK_SHIFT;
1107+
}
1108+
10731109
static int arm_smmu_find_sme(struct arm_smmu_device *smmu, u16 id, u16 mask)
10741110
{
10751111
struct arm_smmu_smr *smrs = smmu->smrs;
@@ -1648,6 +1684,9 @@ static void arm_smmu_device_reset(struct arm_smmu_device *smmu)
16481684
if (smmu->features & ARM_SMMU_FEAT_VMID16)
16491685
reg |= sCR0_VMID16EN;
16501686

1687+
if (smmu->features & ARM_SMMU_FEAT_EXIDS)
1688+
reg |= sCR0_EXIDENABLE;
1689+
16511690
/* Push the button */
16521691
__arm_smmu_tlb_sync(smmu);
16531692
writel(reg, ARM_SMMU_GR0_NS(smmu) + ARM_SMMU_GR0_sCR0);
@@ -1735,11 +1774,14 @@ static int arm_smmu_device_cfg_probe(struct arm_smmu_device *smmu)
17351774
"\t(IDR0.CTTW overridden by FW configuration)\n");
17361775

17371776
/* Max. number of entries we have for stream matching/indexing */
1738-
size = 1 << ((id >> ID0_NUMSIDB_SHIFT) & ID0_NUMSIDB_MASK);
1777+
if (smmu->version == ARM_SMMU_V2 && id & ID0_EXIDS) {
1778+
smmu->features |= ARM_SMMU_FEAT_EXIDS;
1779+
size = 1 << 16;
1780+
} else {
1781+
size = 1 << ((id >> ID0_NUMSIDB_SHIFT) & ID0_NUMSIDB_MASK);
1782+
}
17391783
smmu->streamid_mask = size - 1;
17401784
if (id & ID0_SMS) {
1741-
u32 smr;
1742-
17431785
smmu->features |= ARM_SMMU_FEAT_STREAM_MATCH;
17441786
size = (id >> ID0_NUMSMRG_SHIFT) & ID0_NUMSMRG_MASK;
17451787
if (size == 0) {
@@ -1748,30 +1790,14 @@ static int arm_smmu_device_cfg_probe(struct arm_smmu_device *smmu)
17481790
return -ENODEV;
17491791
}
17501792

1751-
/*
1752-
* SMR.ID bits may not be preserved if the corresponding MASK
1753-
* bits are set, so check each one separately. We can reject
1754-
* masters later if they try to claim IDs outside these masks.
1755-
*/
1756-
smr = smmu->streamid_mask << SMR_ID_SHIFT;
1757-
writel_relaxed(smr, gr0_base + ARM_SMMU_GR0_SMR(0));
1758-
smr = readl_relaxed(gr0_base + ARM_SMMU_GR0_SMR(0));
1759-
smmu->streamid_mask = smr >> SMR_ID_SHIFT;
1760-
1761-
smr = smmu->streamid_mask << SMR_MASK_SHIFT;
1762-
writel_relaxed(smr, gr0_base + ARM_SMMU_GR0_SMR(0));
1763-
smr = readl_relaxed(gr0_base + ARM_SMMU_GR0_SMR(0));
1764-
smmu->smr_mask_mask = smr >> SMR_MASK_SHIFT;
1765-
17661793
/* Zero-initialised to mark as invalid */
17671794
smmu->smrs = devm_kcalloc(smmu->dev, size, sizeof(*smmu->smrs),
17681795
GFP_KERNEL);
17691796
if (!smmu->smrs)
17701797
return -ENOMEM;
17711798

17721799
dev_notice(smmu->dev,
1773-
"\tstream matching with %lu register groups, mask 0x%x",
1774-
size, smmu->smr_mask_mask);
1800+
"\tstream matching with %lu register groups", size);
17751801
}
17761802
/* s2cr->type == 0 means translation, so initialise explicitly */
17771803
smmu->s2crs = devm_kmalloc_array(smmu->dev, size, sizeof(*smmu->s2crs),
@@ -2094,6 +2120,7 @@ static int arm_smmu_device_probe(struct platform_device *pdev)
20942120
iommu_register_instance(dev->fwnode, &arm_smmu_ops);
20952121
platform_set_drvdata(pdev, smmu);
20962122
arm_smmu_device_reset(smmu);
2123+
arm_smmu_test_smr_masks(smmu);
20972124

20982125
/* Oh, for a proper bus abstraction */
20992126
if (!iommu_present(&platform_bus_type))

0 commit comments

Comments
 (0)