Skip to content

Commit cdf315f

Browse files
jpbruckerjoergroedel
authored andcommitted
iommu/arm-smmu-v3: Maintain a SID->device structure
When handling faults from the event or PRI queue, we need to find the struct device associated with a SID. Add a rb_tree to keep track of SIDs. Acked-by: Jonathan Cameron <[email protected]> Reviewed-by: Eric Auger <[email protected]> Reviewed-by: Keqian Zhu <[email protected]> Signed-off-by: Jean-Philippe Brucker <[email protected]> Acked-by: Will Deacon <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Joerg Roedel <[email protected]>
1 parent fc36479 commit cdf315f

File tree

2 files changed

+141
-30
lines changed

2 files changed

+141
-30
lines changed

drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c

Lines changed: 130 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -909,8 +909,8 @@ static void arm_smmu_sync_cd(struct arm_smmu_domain *smmu_domain,
909909

910910
spin_lock_irqsave(&smmu_domain->devices_lock, flags);
911911
list_for_each_entry(master, &smmu_domain->devices, domain_head) {
912-
for (i = 0; i < master->num_sids; i++) {
913-
cmd.cfgi.sid = master->sids[i];
912+
for (i = 0; i < master->num_streams; i++) {
913+
cmd.cfgi.sid = master->streams[i].id;
914914
arm_smmu_cmdq_batch_add(smmu, &cmds, &cmd);
915915
}
916916
}
@@ -1355,6 +1355,29 @@ static int arm_smmu_init_l2_strtab(struct arm_smmu_device *smmu, u32 sid)
13551355
return 0;
13561356
}
13571357

1358+
__maybe_unused
1359+
static struct arm_smmu_master *
1360+
arm_smmu_find_master(struct arm_smmu_device *smmu, u32 sid)
1361+
{
1362+
struct rb_node *node;
1363+
struct arm_smmu_stream *stream;
1364+
1365+
lockdep_assert_held(&smmu->streams_mutex);
1366+
1367+
node = smmu->streams.rb_node;
1368+
while (node) {
1369+
stream = rb_entry(node, struct arm_smmu_stream, node);
1370+
if (stream->id < sid)
1371+
node = node->rb_right;
1372+
else if (stream->id > sid)
1373+
node = node->rb_left;
1374+
else
1375+
return stream->master;
1376+
}
1377+
1378+
return NULL;
1379+
}
1380+
13581381
/* IRQ and event handlers */
13591382
static irqreturn_t arm_smmu_evtq_thread(int irq, void *dev)
13601383
{
@@ -1588,8 +1611,8 @@ static int arm_smmu_atc_inv_master(struct arm_smmu_master *master)
15881611

15891612
arm_smmu_atc_inv_to_cmd(0, 0, 0, &cmd);
15901613

1591-
for (i = 0; i < master->num_sids; i++) {
1592-
cmd.atc.sid = master->sids[i];
1614+
for (i = 0; i < master->num_streams; i++) {
1615+
cmd.atc.sid = master->streams[i].id;
15931616
arm_smmu_cmdq_issue_cmd(master->smmu, &cmd);
15941617
}
15951618

@@ -1632,8 +1655,8 @@ int arm_smmu_atc_inv_domain(struct arm_smmu_domain *smmu_domain, int ssid,
16321655
if (!master->ats_enabled)
16331656
continue;
16341657

1635-
for (i = 0; i < master->num_sids; i++) {
1636-
cmd.atc.sid = master->sids[i];
1658+
for (i = 0; i < master->num_streams; i++) {
1659+
cmd.atc.sid = master->streams[i].id;
16371660
arm_smmu_cmdq_batch_add(smmu_domain->smmu, &cmds, &cmd);
16381661
}
16391662
}
@@ -2065,13 +2088,13 @@ static void arm_smmu_install_ste_for_dev(struct arm_smmu_master *master)
20652088
int i, j;
20662089
struct arm_smmu_device *smmu = master->smmu;
20672090

2068-
for (i = 0; i < master->num_sids; ++i) {
2069-
u32 sid = master->sids[i];
2091+
for (i = 0; i < master->num_streams; ++i) {
2092+
u32 sid = master->streams[i].id;
20702093
__le64 *step = arm_smmu_get_step_for_sid(smmu, sid);
20712094

20722095
/* Bridged PCI devices may end up with duplicated IDs */
20732096
for (j = 0; j < i; j++)
2074-
if (master->sids[j] == sid)
2097+
if (master->streams[j].id == sid)
20752098
break;
20762099
if (j < i)
20772100
continue;
@@ -2345,11 +2368,101 @@ static bool arm_smmu_sid_in_range(struct arm_smmu_device *smmu, u32 sid)
23452368
return sid < limit;
23462369
}
23472370

2371+
static int arm_smmu_insert_master(struct arm_smmu_device *smmu,
2372+
struct arm_smmu_master *master)
2373+
{
2374+
int i;
2375+
int ret = 0;
2376+
struct arm_smmu_stream *new_stream, *cur_stream;
2377+
struct rb_node **new_node, *parent_node = NULL;
2378+
struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(master->dev);
2379+
2380+
master->streams = kcalloc(fwspec->num_ids, sizeof(*master->streams),
2381+
GFP_KERNEL);
2382+
if (!master->streams)
2383+
return -ENOMEM;
2384+
master->num_streams = fwspec->num_ids;
2385+
2386+
mutex_lock(&smmu->streams_mutex);
2387+
for (i = 0; i < fwspec->num_ids; i++) {
2388+
u32 sid = fwspec->ids[i];
2389+
2390+
new_stream = &master->streams[i];
2391+
new_stream->id = sid;
2392+
new_stream->master = master;
2393+
2394+
/*
2395+
* Check the SIDs are in range of the SMMU and our stream table
2396+
*/
2397+
if (!arm_smmu_sid_in_range(smmu, sid)) {
2398+
ret = -ERANGE;
2399+
break;
2400+
}
2401+
2402+
/* Ensure l2 strtab is initialised */
2403+
if (smmu->features & ARM_SMMU_FEAT_2_LVL_STRTAB) {
2404+
ret = arm_smmu_init_l2_strtab(smmu, sid);
2405+
if (ret)
2406+
break;
2407+
}
2408+
2409+
/* Insert into SID tree */
2410+
new_node = &(smmu->streams.rb_node);
2411+
while (*new_node) {
2412+
cur_stream = rb_entry(*new_node, struct arm_smmu_stream,
2413+
node);
2414+
parent_node = *new_node;
2415+
if (cur_stream->id > new_stream->id) {
2416+
new_node = &((*new_node)->rb_left);
2417+
} else if (cur_stream->id < new_stream->id) {
2418+
new_node = &((*new_node)->rb_right);
2419+
} else {
2420+
dev_warn(master->dev,
2421+
"stream %u already in tree\n",
2422+
cur_stream->id);
2423+
ret = -EINVAL;
2424+
break;
2425+
}
2426+
}
2427+
if (ret)
2428+
break;
2429+
2430+
rb_link_node(&new_stream->node, parent_node, new_node);
2431+
rb_insert_color(&new_stream->node, &smmu->streams);
2432+
}
2433+
2434+
if (ret) {
2435+
for (i--; i >= 0; i--)
2436+
rb_erase(&master->streams[i].node, &smmu->streams);
2437+
kfree(master->streams);
2438+
}
2439+
mutex_unlock(&smmu->streams_mutex);
2440+
2441+
return ret;
2442+
}
2443+
2444+
static void arm_smmu_remove_master(struct arm_smmu_master *master)
2445+
{
2446+
int i;
2447+
struct arm_smmu_device *smmu = master->smmu;
2448+
struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(master->dev);
2449+
2450+
if (!smmu || !master->streams)
2451+
return;
2452+
2453+
mutex_lock(&smmu->streams_mutex);
2454+
for (i = 0; i < fwspec->num_ids; i++)
2455+
rb_erase(&master->streams[i].node, &smmu->streams);
2456+
mutex_unlock(&smmu->streams_mutex);
2457+
2458+
kfree(master->streams);
2459+
}
2460+
23482461
static struct iommu_ops arm_smmu_ops;
23492462

23502463
static struct iommu_device *arm_smmu_probe_device(struct device *dev)
23512464
{
2352-
int i, ret;
2465+
int ret;
23532466
struct arm_smmu_device *smmu;
23542467
struct arm_smmu_master *master;
23552468
struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
@@ -2370,27 +2483,12 @@ static struct iommu_device *arm_smmu_probe_device(struct device *dev)
23702483

23712484
master->dev = dev;
23722485
master->smmu = smmu;
2373-
master->sids = fwspec->ids;
2374-
master->num_sids = fwspec->num_ids;
23752486
INIT_LIST_HEAD(&master->bonds);
23762487
dev_iommu_priv_set(dev, master);
23772488

2378-
/* Check the SIDs are in range of the SMMU and our stream table */
2379-
for (i = 0; i < master->num_sids; i++) {
2380-
u32 sid = master->sids[i];
2381-
2382-
if (!arm_smmu_sid_in_range(smmu, sid)) {
2383-
ret = -ERANGE;
2384-
goto err_free_master;
2385-
}
2386-
2387-
/* Ensure l2 strtab is initialised */
2388-
if (smmu->features & ARM_SMMU_FEAT_2_LVL_STRTAB) {
2389-
ret = arm_smmu_init_l2_strtab(smmu, sid);
2390-
if (ret)
2391-
goto err_free_master;
2392-
}
2393-
}
2489+
ret = arm_smmu_insert_master(smmu, master);
2490+
if (ret)
2491+
goto err_free_master;
23942492

23952493
device_property_read_u32(dev, "pasid-num-bits", &master->ssid_bits);
23962494
master->ssid_bits = min(smmu->ssid_bits, master->ssid_bits);
@@ -2429,6 +2527,7 @@ static void arm_smmu_release_device(struct device *dev)
24292527
WARN_ON(arm_smmu_master_sva_enabled(master));
24302528
arm_smmu_detach_dev(master);
24312529
arm_smmu_disable_pasid(master);
2530+
arm_smmu_remove_master(master);
24322531
kfree(master);
24332532
iommu_fwspec_free(dev);
24342533
}
@@ -2852,6 +2951,9 @@ static int arm_smmu_init_structures(struct arm_smmu_device *smmu)
28522951
{
28532952
int ret;
28542953

2954+
mutex_init(&smmu->streams_mutex);
2955+
smmu->streams = RB_ROOT;
2956+
28552957
ret = arm_smmu_init_queues(smmu);
28562958
if (ret)
28572959
return ret;

drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -639,6 +639,15 @@ struct arm_smmu_device {
639639

640640
/* IOMMU core code handle */
641641
struct iommu_device iommu;
642+
643+
struct rb_root streams;
644+
struct mutex streams_mutex;
645+
};
646+
647+
struct arm_smmu_stream {
648+
u32 id;
649+
struct arm_smmu_master *master;
650+
struct rb_node node;
642651
};
643652

644653
/* SMMU private data for each master */
@@ -647,8 +656,8 @@ struct arm_smmu_master {
647656
struct device *dev;
648657
struct arm_smmu_domain *domain;
649658
struct list_head domain_head;
650-
u32 *sids;
651-
unsigned int num_sids;
659+
struct arm_smmu_stream *streams;
660+
unsigned int num_streams;
652661
bool ats_enabled;
653662
bool sva_enabled;
654663
struct list_head bonds;

0 commit comments

Comments
 (0)