Skip to content

Commit adfec2e

Browse files
rmurphy-armwildea01
authored andcommitted
iommu/arm-smmu: Convert to iommu_fwspec
In the final step of preparation for full generic configuration support, swap our fixed-size master_cfg for the generic iommu_fwspec. For the legacy DT bindings, the driver simply gets to act as its own 'firmware'. Farewell, arbitrary MAX_MASTER_STREAMIDS! Signed-off-by: Robin Murphy <robin.murphy@arm.com> Signed-off-by: Will Deacon <will.deacon@arm.com>
1 parent 588888a commit adfec2e

File tree

1 file changed

+78
-62
lines changed

1 file changed

+78
-62
lines changed

drivers/iommu/arm-smmu.c

Lines changed: 78 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
#include <linux/of.h>
4343
#include <linux/of_address.h>
4444
#include <linux/of_device.h>
45+
#include <linux/of_iommu.h>
4546
#include <linux/pci.h>
4647
#include <linux/platform_device.h>
4748
#include <linux/slab.h>
@@ -51,9 +52,6 @@
5152

5253
#include "io-pgtable.h"
5354

54-
/* Maximum number of stream IDs assigned to a single device */
55-
#define MAX_MASTER_STREAMIDS 128
56-
5755
/* Maximum number of context banks per SMMU */
5856
#define ARM_SMMU_MAX_CBS 128
5957

@@ -321,13 +319,13 @@ struct arm_smmu_smr {
321319

322320
struct arm_smmu_master_cfg {
323321
struct arm_smmu_device *smmu;
324-
int num_streamids;
325-
u16 streamids[MAX_MASTER_STREAMIDS];
326-
s16 smendx[MAX_MASTER_STREAMIDS];
322+
s16 smendx[];
327323
};
328324
#define INVALID_SMENDX -1
329-
#define for_each_cfg_sme(cfg, i, idx) \
330-
for (i = 0; idx = cfg->smendx[i], i < cfg->num_streamids; ++i)
325+
#define __fwspec_cfg(fw) ((struct arm_smmu_master_cfg *)fw->iommu_priv)
326+
#define fwspec_smmu(fw) (__fwspec_cfg(fw)->smmu)
327+
#define for_each_cfg_sme(fw, i, idx) \
328+
for (i = 0; idx = __fwspec_cfg(fw)->smendx[i], i < fw->num_ids; ++i)
331329

332330
struct arm_smmu_device {
333331
struct device *dev;
@@ -480,14 +478,16 @@ static int __find_legacy_master_phandle(struct device *dev, void *data)
480478
}
481479

482480
static struct platform_driver arm_smmu_driver;
481+
static struct iommu_ops arm_smmu_ops;
483482

484-
static int arm_smmu_register_legacy_master(struct device *dev)
483+
static int arm_smmu_register_legacy_master(struct device *dev,
484+
struct arm_smmu_device **smmu)
485485
{
486-
struct arm_smmu_device *smmu;
487-
struct arm_smmu_master_cfg *cfg;
486+
struct device *smmu_dev;
488487
struct device_node *np;
489488
struct of_phandle_iterator it;
490489
void *data = &it;
490+
u32 *sids;
491491
__be32 pci_sid;
492492
int err;
493493

@@ -500,20 +500,13 @@ static int arm_smmu_register_legacy_master(struct device *dev)
500500
it.node = np;
501501
err = driver_for_each_device(&arm_smmu_driver.driver, NULL, &data,
502502
__find_legacy_master_phandle);
503+
smmu_dev = data;
503504
of_node_put(np);
504505
if (err == 0)
505506
return -ENODEV;
506507
if (err < 0)
507508
return err;
508509

509-
smmu = dev_get_drvdata(data);
510-
511-
if (it.cur_count > MAX_MASTER_STREAMIDS) {
512-
dev_err(smmu->dev,
513-
"reached maximum number (%d) of stream IDs for master device %s\n",
514-
MAX_MASTER_STREAMIDS, dev_name(dev));
515-
return -ENOSPC;
516-
}
517510
if (dev_is_pci(dev)) {
518511
/* "mmu-masters" assumes Stream ID == Requester ID */
519512
pci_for_each_dma_alias(to_pci_dev(dev), __arm_smmu_get_pci_sid,
@@ -522,17 +515,20 @@ static int arm_smmu_register_legacy_master(struct device *dev)
522515
it.cur_count = 1;
523516
}
524517

525-
cfg = kzalloc(sizeof(*cfg), GFP_KERNEL);
526-
if (!cfg)
527-
return -ENOMEM;
528-
529-
cfg->smmu = smmu;
530-
dev->archdata.iommu = cfg;
518+
err = iommu_fwspec_init(dev, &smmu_dev->of_node->fwnode,
519+
&arm_smmu_ops);
520+
if (err)
521+
return err;
531522

532-
while (it.cur_count--)
533-
cfg->streamids[cfg->num_streamids++] = be32_to_cpup(it.cur++);
523+
sids = kcalloc(it.cur_count, sizeof(*sids), GFP_KERNEL);
524+
if (!sids)
525+
return -ENOMEM;
534526

535-
return 0;
527+
*smmu = dev_get_drvdata(smmu_dev);
528+
of_phandle_iterator_args(&it, sids, it.cur_count);
529+
err = iommu_fwspec_add_ids(dev, sids, it.cur_count);
530+
kfree(sids);
531+
return err;
536532
}
537533

538534
static int __arm_smmu_alloc_bitmap(unsigned long *map, int start, int end)
@@ -1127,27 +1123,28 @@ static bool arm_smmu_free_sme(struct arm_smmu_device *smmu, int idx)
11271123

11281124
static int arm_smmu_master_alloc_smes(struct device *dev)
11291125
{
1130-
struct arm_smmu_master_cfg *cfg = dev->archdata.iommu;
1126+
struct iommu_fwspec *fwspec = dev->iommu_fwspec;
1127+
struct arm_smmu_master_cfg *cfg = fwspec->iommu_priv;
11311128
struct arm_smmu_device *smmu = cfg->smmu;
11321129
struct arm_smmu_smr *smrs = smmu->smrs;
11331130
struct iommu_group *group;
11341131
int i, idx, ret;
11351132

11361133
mutex_lock(&smmu->stream_map_mutex);
11371134
/* Figure out a viable stream map entry allocation */
1138-
for_each_cfg_sme(cfg, i, idx) {
1135+
for_each_cfg_sme(fwspec, i, idx) {
11391136
if (idx != INVALID_SMENDX) {
11401137
ret = -EEXIST;
11411138
goto out_err;
11421139
}
11431140

1144-
ret = arm_smmu_find_sme(smmu, cfg->streamids[i], 0);
1141+
ret = arm_smmu_find_sme(smmu, fwspec->ids[i], 0);
11451142
if (ret < 0)
11461143
goto out_err;
11471144

11481145
idx = ret;
11491146
if (smrs && smmu->s2crs[idx].count == 0) {
1150-
smrs[idx].id = cfg->streamids[i];
1147+
smrs[idx].id = fwspec->ids[i];
11511148
smrs[idx].mask = 0; /* We don't currently share SMRs */
11521149
smrs[idx].valid = true;
11531150
}
@@ -1165,7 +1162,7 @@ static int arm_smmu_master_alloc_smes(struct device *dev)
11651162
iommu_group_put(group);
11661163

11671164
/* It worked! Now, poke the actual hardware */
1168-
for_each_cfg_sme(cfg, i, idx) {
1165+
for_each_cfg_sme(fwspec, i, idx) {
11691166
arm_smmu_write_sme(smmu, idx);
11701167
smmu->s2crs[idx].group = group;
11711168
}
@@ -1182,13 +1179,14 @@ static int arm_smmu_master_alloc_smes(struct device *dev)
11821179
return ret;
11831180
}
11841181

1185-
static void arm_smmu_master_free_smes(struct arm_smmu_master_cfg *cfg)
1182+
static void arm_smmu_master_free_smes(struct iommu_fwspec *fwspec)
11861183
{
1187-
struct arm_smmu_device *smmu = cfg->smmu;
1184+
struct arm_smmu_device *smmu = fwspec_smmu(fwspec);
1185+
struct arm_smmu_master_cfg *cfg = fwspec->iommu_priv;
11881186
int i, idx;
11891187

11901188
mutex_lock(&smmu->stream_map_mutex);
1191-
for_each_cfg_sme(cfg, i, idx) {
1189+
for_each_cfg_sme(fwspec, i, idx) {
11921190
if (arm_smmu_free_sme(smmu, idx))
11931191
arm_smmu_write_sme(smmu, idx);
11941192
cfg->smendx[i] = INVALID_SMENDX;
@@ -1197,7 +1195,7 @@ static void arm_smmu_master_free_smes(struct arm_smmu_master_cfg *cfg)
11971195
}
11981196

11991197
static int arm_smmu_domain_add_master(struct arm_smmu_domain *smmu_domain,
1200-
struct arm_smmu_master_cfg *cfg)
1198+
struct iommu_fwspec *fwspec)
12011199
{
12021200
struct arm_smmu_device *smmu = smmu_domain->smmu;
12031201
struct arm_smmu_s2cr *s2cr = smmu->s2crs;
@@ -1214,7 +1212,7 @@ static int arm_smmu_domain_add_master(struct arm_smmu_domain *smmu_domain,
12141212
if (smmu_domain->domain.type == IOMMU_DOMAIN_DMA)
12151213
type = S2CR_TYPE_BYPASS;
12161214

1217-
for_each_cfg_sme(cfg, i, idx) {
1215+
for_each_cfg_sme(fwspec, i, idx) {
12181216
if (type == s2cr[idx].type && cbndx == s2cr[idx].cbndx)
12191217
continue;
12201218

@@ -1229,32 +1227,34 @@ static int arm_smmu_domain_add_master(struct arm_smmu_domain *smmu_domain,
12291227
static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
12301228
{
12311229
int ret;
1230+
struct iommu_fwspec *fwspec = dev->iommu_fwspec;
1231+
struct arm_smmu_device *smmu;
12321232
struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain);
1233-
struct arm_smmu_master_cfg *cfg = dev->archdata.iommu;
12341233

1235-
if (!cfg) {
1234+
if (!fwspec || fwspec->ops != &arm_smmu_ops) {
12361235
dev_err(dev, "cannot attach to SMMU, is it on the same bus?\n");
12371236
return -ENXIO;
12381237
}
12391238

1239+
smmu = fwspec_smmu(fwspec);
12401240
/* Ensure that the domain is finalised */
1241-
ret = arm_smmu_init_domain_context(domain, cfg->smmu);
1241+
ret = arm_smmu_init_domain_context(domain, smmu);
12421242
if (ret < 0)
12431243
return ret;
12441244

12451245
/*
12461246
* Sanity check the domain. We don't support domains across
12471247
* different SMMUs.
12481248
*/
1249-
if (smmu_domain->smmu != cfg->smmu) {
1249+
if (smmu_domain->smmu != smmu) {
12501250
dev_err(dev,
12511251
"cannot attach to SMMU %s whilst already attached to domain on SMMU %s\n",
1252-
dev_name(smmu_domain->smmu->dev), dev_name(cfg->smmu->dev));
1252+
dev_name(smmu_domain->smmu->dev), dev_name(smmu->dev));
12531253
return -EINVAL;
12541254
}
12551255

12561256
/* Looks ok, so add the device to the domain */
1257-
return arm_smmu_domain_add_master(smmu_domain, cfg);
1257+
return arm_smmu_domain_add_master(smmu_domain, fwspec);
12581258
}
12591259

12601260
static int arm_smmu_map(struct iommu_domain *domain, unsigned long iova,
@@ -1375,57 +1375,72 @@ static bool arm_smmu_capable(enum iommu_cap cap)
13751375

13761376
static int arm_smmu_add_device(struct device *dev)
13771377
{
1378+
struct arm_smmu_device *smmu;
13781379
struct arm_smmu_master_cfg *cfg;
1380+
struct iommu_fwspec *fwspec;
13791381
int i, ret;
13801382

1381-
ret = arm_smmu_register_legacy_master(dev);
1382-
cfg = dev->archdata.iommu;
1383+
ret = arm_smmu_register_legacy_master(dev, &smmu);
1384+
fwspec = dev->iommu_fwspec;
13831385
if (ret)
13841386
goto out_free;
13851387

13861388
ret = -EINVAL;
1387-
for (i = 0; i < cfg->num_streamids; i++) {
1388-
u16 sid = cfg->streamids[i];
1389+
for (i = 0; i < fwspec->num_ids; i++) {
1390+
u16 sid = fwspec->ids[i];
13891391

1390-
if (sid & ~cfg->smmu->streamid_mask) {
1392+
if (sid & ~smmu->streamid_mask) {
13911393
dev_err(dev, "stream ID 0x%x out of range for SMMU (0x%x)\n",
13921394
sid, cfg->smmu->streamid_mask);
13931395
goto out_free;
13941396
}
1395-
cfg->smendx[i] = INVALID_SMENDX;
13961397
}
13971398

1399+
ret = -ENOMEM;
1400+
cfg = kzalloc(offsetof(struct arm_smmu_master_cfg, smendx[i]),
1401+
GFP_KERNEL);
1402+
if (!cfg)
1403+
goto out_free;
1404+
1405+
cfg->smmu = smmu;
1406+
fwspec->iommu_priv = cfg;
1407+
while (i--)
1408+
cfg->smendx[i] = INVALID_SMENDX;
1409+
13981410
ret = arm_smmu_master_alloc_smes(dev);
1399-
if (!ret)
1400-
return ret;
1411+
if (ret)
1412+
goto out_free;
1413+
1414+
return 0;
14011415

14021416
out_free:
1403-
kfree(cfg);
1404-
dev->archdata.iommu = NULL;
1417+
if (fwspec)
1418+
kfree(fwspec->iommu_priv);
1419+
iommu_fwspec_free(dev);
14051420
return ret;
14061421
}
14071422

14081423
static void arm_smmu_remove_device(struct device *dev)
14091424
{
1410-
struct arm_smmu_master_cfg *cfg = dev->archdata.iommu;
1425+
struct iommu_fwspec *fwspec = dev->iommu_fwspec;
14111426

1412-
if (!cfg)
1427+
if (!fwspec || fwspec->ops != &arm_smmu_ops)
14131428
return;
14141429

1415-
arm_smmu_master_free_smes(cfg);
1430+
arm_smmu_master_free_smes(fwspec);
14161431
iommu_group_remove_device(dev);
1417-
kfree(cfg);
1418-
dev->archdata.iommu = NULL;
1432+
kfree(fwspec->iommu_priv);
1433+
iommu_fwspec_free(dev);
14191434
}
14201435

14211436
static struct iommu_group *arm_smmu_device_group(struct device *dev)
14221437
{
1423-
struct arm_smmu_master_cfg *cfg = dev->archdata.iommu;
1424-
struct arm_smmu_device *smmu = cfg->smmu;
1438+
struct iommu_fwspec *fwspec = dev->iommu_fwspec;
1439+
struct arm_smmu_device *smmu = fwspec_smmu(fwspec);
14251440
struct iommu_group *group = NULL;
14261441
int i, idx;
14271442

1428-
for_each_cfg_sme(cfg, i, idx) {
1443+
for_each_cfg_sme(fwspec, i, idx) {
14291444
if (group && smmu->s2crs[idx].group &&
14301445
group != smmu->s2crs[idx].group)
14311446
return ERR_PTR(-EINVAL);
@@ -1936,6 +1951,7 @@ static int arm_smmu_device_dt_probe(struct platform_device *pdev)
19361951
}
19371952
}
19381953

1954+
of_iommu_set_ops(dev->of_node, &arm_smmu_ops);
19391955
platform_set_drvdata(pdev, smmu);
19401956
arm_smmu_device_reset(smmu);
19411957
return 0;

0 commit comments

Comments
 (0)