Re: [PATCH RFC v5 3/6] iommu/arm-smmu-v3: Delay stream allocation to inside the mutex
From: Nicolin Chen
Date: Wed Oct 07 2026 - 19:56:20 EST
On Tue, Oct 06, 2026 at 08:19:09PM +0800, Peng Fan (OSS) wrote:
> @@ -4110,52 +4110,29 @@ static int arm_smmu_insert_master(struct arm_smmu_device *smmu,
[...]
> - /* Insert into SID tree */
> - existing = rb_find_add(&new_stream->node, &smmu->streams,
> - arm_smmu_streams_cmp_node);
> + existing = rb_find(&sid, &smmu->streams,
> + arm_smmu_streams_cmp_key);
> if (existing) {
> struct arm_smmu_master *existing_master =
> rb_entry(existing, struct arm_smmu_stream, node)
> ->master;
>
> /* Bridged PCI devices may end up with duplicated IDs */
> - if (existing_master == master)
> + if (existing_master == master) {
> + master->streams[i] = rb_entry(existing,
> + struct arm_smmu_stream, node);
This can be cleaned a bit by moving the arm_smmu_find_stream()
from PATCH-4 to this patch.
> if (ret) {
> - for (i--; i >= 0; i--)
> - if (!RB_EMPTY_NODE(&master->streams[i]->node))
> - rb_erase(&master->streams[i]->node,
> - &smmu->streams);
> + for (i--; i >= 0; i--) {
> + int j;
> +
> + if (!master->streams[i])
> + continue;
> + /* Skip duplicated SID pointers already freed */
> + for (j = 0; j < i; j++)
> + if (master->streams[j] == master->streams[i])
> + break;
> + if (j < i)
> + continue;
> + rb_erase(&master->streams[i]->node, &smmu->streams);
> + kfree(master->streams[i]);
> + }
Add a helper to share with arm_smmu_remove_master():
static void arm_smmu_free_master_streams(struct arm_smmu_master *master)
{
struct arm_smmu_device *smmu = master->smmu;
int i;
lockdep_assert_held(&smmu->streams_mutex);
for (i = 0; i < master->num_streams; i++) {
int j;
if (!master->streams[i])
continue;
/* Skip duplicated SID pointers already freed */
for (j = 0; j < i; j++)
if (master->streams[j] == master->streams[i])
break;
if (j < i)
continue;
rb_erase(&master->streams[i]->node, &smmu->streams);
kfree(master->streams[i]);
}
}
Nicolin