[PATCH RFC v5 3/6] iommu/arm-smmu-v3: Delay stream allocation to inside the mutex

Nicolin Chen nicolinc at nvidia.com
Wed Oct 7 16:55:37 PDT 2026


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



More information about the linux-arm-kernel mailing list